TypeScript ガイド

TypeScript で使う OpenAI Decisions API

OpenAI は Decisions API の SDK を公開していません——client.decisions.create のようなメソッドは存在しません。このページでは、このサイトのエンドポイント(decisions-1 を提供する、呼び出せる OpenAI Decisions API の代替)向けの、完全に型付けされた動く TypeScript を示します。同じ制約付きデシジョンパターンに従います。

更新日

契約を定義する

リクエストを一度型付けすればどこでも再利用できます。model はリテラル union なので固定 ID がタイポでずれることがありません。questions は質問 ID をキーとする record で、それぞれ noul・choice・score 型です。

answers は type で判別される union として型付けします——これがレスポンス処理を安全にする部分です:noul の回答には noul があり、choice の回答には choice と probabilities があります。type で絞り込めば正しいフィールドが得られます。

TypeScript

interface DecisionQuestion {
  type: 'noul' | 'choice' | 'score'
  instructions: string
  criteria?: Record<string, string> | string[]
}

interface DecisionRequest {
  model: 'decisions-1' | 'decisions-latest'
  state: string | Record<string, unknown> | unknown[]
  questions: Record<string, DecisionQuestion>
}

interface DecisionAnswers {
  [questionId: string]:
    | { type: 'noul'; noul: number }
    | { type: 'choice'; choice: string; probabilities: Record<string, number>; confidence: number }
    | { type: 'score'; score: number; legend: string[]; probabilities: Record<string, number>; confidence: number }
}

呼び出す

Bearer キーで 1 回 POST します。satisfies DecisionRequest でコンパイル時に本文を検査し、AbortSignal.timeout がハングした呼び出しがパイプラインを止めるのを防ぎます。answers を読む前に type フィールドで絞り込んでください。

TypeScript

const res = await fetch('https://decisions-api.net/api/v1/decisions', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.DECISIONS_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(request satisfies DecisionRequest),
  signal: AbortSignal.timeout(30000),
})
const { answers } = (await res.json()) as { answers: DecisionAnswers }

const team = answers.team
if (team.type === 'choice' && team.confidence >= 0.7) {
  routeTo(team.choice)
}

タイムアウトとリトライ

429 と 502 は短いバックオフ付きでリトライする価値があります——失敗した呼び出しは課金されません。402 は残高不足です:チャージしてください。リトライは無駄です。422 はバリデーションエラーで、メッセージがフィールドを示すので本文を直してください。

TypeScript

async function decide(body: DecisionRequest, attempts = 3): Promise<DecisionAnswers> {
  for (let i = 0; i < attempts; i++) {
    const res = await fetch('https://decisions-api.net/api/v1/decisions', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.DECISIONS_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(body),
      signal: AbortSignal.timeout(30000),
    })
    if (res.status === 429 || res.status === 502) {
      await new Promise(r => setTimeout(r, 2 ** i * 1000))
      continue
    }
    if (res.status === 402) throw new Error('out of credits')
    if (!res.ok) throw new Error(`decision call failed: ${res.status}`)
    return (await res.json() as { answers: DecisionAnswers }).answers
  }
  throw new Error('decision call failed')
}

プロバイダーを 1 関数の後ろに隠す

呼び出し側が見るのはテキストを受けてラベルを返す型付き関数だけにしましょう——HTTP の詳細ではなく。OpenAI の Decisions API が開いたら decide() の中身だけを差し替え、呼び出し箇所はすべてそのままです。質問文、選択肢、しきい値はそのまま使えます。

TypeScript

// Keep the decision behind one typed function. Swap the HTTP
// layer when OpenAI publishes its schema — callers never change.
export async function routeTicket(text: string): Promise<string> {
  const answers = await decide({
    model: 'decisions-1',
    state: text,
    questions: {
      team: {
        type: 'choice',
        instructions: 'Which team should own this ticket?',
        criteria: {
          payments: 'Checkout or billing.',
          frontend: 'Rendering or browser behavior.',
          account: 'Login or permissions.',
        },
      },
    },
  })
  const team = answers.team
  return team.type === 'choice' && team.confidence >= 0.7 ? team.choice : 'triage'
}

よくある質問

Decisions API の公式 OpenAI SDK 例はありますか?

ありません。OpenAI は Decisions API の SDK メソッドやリクエストスキーマを公開していません——client.decisions.create を示すコードはすべて創作です。このページはプレーンな HTTP を使いますが、どんなプロバイダ SDK も内部ではそうしているものです。

型にコードジェネレーターは必要ですか?

いいえ——このページのインターフェイスが契約全体をカバーしています。そのままプロジェクトにコピーしてください。監査できる小ささで、プロバイダ間で安定しています。

構造化されたコンテキストを送るには?

state は文字列だけでなく JSON オブジェクトや配列を受けます——json 本文に dict をそのまま渡せば、モデルがコンテキストとして読みます。

ブラウザでデシジョンを実行

セットアップ不要——新規訪問者の 1 クレジットでプレイグラウンドから実際に呼べます。