動かざることバグの如し

近づきたいよ 君の理想に

ZodとJSON modeを使ってChatGPTのレスポンスをJSONで取得

環境

  • Nodejs v22

やりたいこと

OpenAIのJSONモードは、ChatGPTの出力を確実にJSON形式で取得できる機能である。 従来のFunction Callingと比べてより簡潔に実装でき、zodと組み合わせることでTypeScriptとの相性も良い。

今回はFunction CallingではなくJSONモードを使ってJSONを返却してもらう。

コード

import OpenAI from 'openai';
import { zodResponseFormat } from 'openai/helpers/zod';
import z from 'zod';

const schema = z.object({
  quizzes: z.array(
    z.object({
      question: z.string(),
      answer: z.string()
    })
  )
});
type QuizProps = z.infer<typeof schema>;

export async function fetchGPT(): Promise<QuizProps> {
  const client = new OpenAI({
    apiKey: process.env.OPENAI_API_KEY
  });

  const chatCompletion = await client.beta.chat.completions.parse({
    messages: [
      {
        role: 'user',
        content: 'なぞなぞの問題と答えを難易度順に3つ作成してください。'
      }
    ],
    model: 'gpt-4o-mini',
    response_format: zodResponseFormat(schema, 'responseSchema')
  });

  return chatCompletion.choices[0].message.parsed as QuizProps;
}

fetchGPT()
  .then((x) => console.log(x))
  .catch(console.error);
  • Zodを使用してレスポンススキーマを定義している。これにより型安全性が確保される
  • zodResponseFormatヘルパー関数を使用して、ZodスキーマをOpenAI APIで使用可能なJSON schemaに変換する
  • response_formatパラメータを設定することで、GPTからの応答が必ず指定したスキーマに従ったJSON形式になることが保証される
  • client.beta.chat.completions.parseメソッドを使用することで、レスポンスを自動的にパースし型付きのオブジェクトとして取得できる

注意点

  • JSONモードを使用するには、gpt-4oまたはgpt-4o-miniモデルを使用する必要がある
  • すべてのフィールドはrequiredとして指定する必要がある
  • スキーマ定義では、discriminated unionなどの複雑な型は使用できない制限がある