👻

【python】OpenAI Chat APIでJson modeを試す

2023/11/17に公開

OpenAI Chat APIでJson modeを試す

11/7のOpenAI devdaysにて新たに公開されたJson modeを使ってみたのでそのサンプルです。
いくつかサンプルを公開している方がいましたが、システムプロンプトが単純なものが多かったので自分が使いそうなケースで、GPTに入力内容を判別(分類?)してもらうようなサンプルを書いてみました。

Json modeのちょこっと説明

Json modeではAPIからのレスポンスを常にjson形式にすることができ、APIのパラメータでresponse_format={"type": "json_object"}を付与するとJson modeに設定できます。
あとはシステムプロンプトで詳細なjson形式を指定すると期待したjson形式で返却されます。(たぶん)
Json modeはchat apiで使用できます。

詳しく知りたい場合は公式docを確認してください。

pythonサンプル

リクエストを送る部分は以下のような感じでresponse_format={"type": "json_object"}を設定しています。
modelはサンプルではgpt-4-1106-previewを使用しましたが、gpt-3.5-turbo-1106だと少し精度が落ちてしまいました。(日本語プロンプトのせいかも)

from openai import OpenAI

client = OpenAI()

# system_promptとquestionは後述

response = client.chat.completions.create(
    model="gpt-4-1106-preview",
    temperature=0.0,
    messages=[
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": question},
    ],
    response_format={"type": "json_object"} # こちらを指定する
)

answer = response.choices[0].message.content
print(answer)

ユーザプロンプト

ユーザプロンプトとして投げる文章(question)は全て以下です。(すごい適当で脈略の無い文章です)

question = """
うちで飼っているデグーが最近エサをあんまり食べてくれないんだ。
病気だったりしたら怖いよね。
そういえば最近映画をみたんだけどVRで見たからすごい臨場感だったよ。
あと来週AIに関する講演会に参加する予定なんだ。
"""

システムプロンプト

今回試したユースケースはユーザの入力文章の言語と話題を判別するもので、話題に関しては複数対応できるよう配列で返却するようにしてみました。また、判別の信頼度みたいなものも出してみたのですが、こちらの値はあんまり意味なかったです。
そして、このユースケースに対して以下3ケースのシステムプロンプト用意して試しました。

  • GPTに自由に判別させる
  • 話題の選択肢を与えて選択させる
  • 話題の選択肢を与えて選択させ選択肢に紐づくkeyを返却する

ケース1: 自由に判別させる

言語も話題も自由に判別して返却してもらうケースです。
どのような値が返ってくるのかいまいち分からないので今回のような判別のようなタスクでは使用しない気がします。

system_prompt = """
## 回答ルール
- ユーザーが提供する文章の言語と話題を分析し、JSON形式で返却してください。
- 話題は配列形式とし、話題が単一の場合は要素が一つの配列とし、話題が複数ある場合は要素が複数の配列としてください。
- 言語の分析の信頼度と話題の分析の信頼度をそれぞれ含めてください。

## 期待されるJSONレスポンス
{
  "language": "English",
  "language_confidence": 0.5,
  "topics": [
    {"topic": "Environmental_Issues", "topic_confidence": 0.8},
    {"topic": "Science_and_Technology", "topic_confidence": 0.65}
  ]
}
"""

実行結果は以下のようになりました。

{
  "language": "Japanese",
  "language_confidence": 0.95,
  "topics": [
    {"topic": "Pets", "topic_confidence": 0.85},
    {"topic": "Health_and_Wellness", "topic_confidence": 0.75},
    {"topic": "Entertainment_and_Media", "topic_confidence": 0.8},
    {"topic": "Science_and_Technology", "topic_confidence": 0.9}
  ]
}

ケース2: 話題の選択肢を与えて選択させる

話題の選択肢を追加してその中から選択するようにしたケースです。
enumで管理している値を選択肢にしたい場合はこのような形で良いかなと思います。enumのkeyで返却して欲しい場合はケース3を使うのが良いです。

system_prompt = """
## 回答ルール
- ユーザーが提供する文章の言語と話題を分析し、JSON形式で返却してください。
- 話題は必ず話題の選択肢の中の値を使用してください。
- 選択肢に無い値は使用しないでください。
- 話題の選択肢に適切な選択肢が無い場合はOtherを選択してください。
- 話題は配列形式とし、話題が単一の場合は要素が一つの配列とし、話題が複数ある場合は要素が複数の配列としてください。
- 言語の分析の信頼度と話題の分析の信頼度をそれぞれ含めてください。

## 話題の選択肢(話題にはこの値を必ず設定すること)
- Environmental_Issues
- Science_and_Technology
- Economics
- Culture_and_Arts
- Sports
- Education
- Politics
- Entertainment
- Travel_and_Tourism
- Business_and_Finance
- Technology_and_Innovation
- Social_Issues
- History
- Food_and_Cuisine
- Nature_and_Wildlife
- Other

## 期待されるJSONレスポンス
{
  "language": "English",
  "language_confidence": 0.5,
  "topics": [
    {"topic": "Environmental_Issues", "topic_confidence": 0.8},
    {"topic": "Science_and_Technology", "topic_confidence": 0.65}
  ]
}
"""

実行結果は以下のようになりました。

{
  "language": "Japanese",
  "language_confidence": 0.99,
  "topics": [
    {"topic": "Other", "topic_confidence": 0.7},
    {"topic": "Entertainment", "topic_confidence": 0.85},
    {"topic": "Technology_and_Innovation", "topic_confidence": 0.9}
  ]
}

ケース3: 話題の選択肢を与えて選択させる

先ほどに加えて選択肢それぞれをkey: value形式にしてレスポンスにはkeyで返却するようにしたものです。
enumをid: value形式で管理していたりDBのレコードで管理してる場合はこちらのケースが良いかなと思います。

system_prompt = """
## 回答ルール
- ユーザーが提供する文章の言語と話題を分析し、JSON形式で返却してください。
- 話題の分析は、選択肢のvalueを基に行い、返却値には選択肢のkeyを使用してください。
- 選択肢に無い値は使用しないでください。
- 話題の選択肢に適切な選択肢が無い場合はOtherを選択してください。
- 話題は配列形式とし、話題が単一の場合は要素が一つの配列とし、話題が複数ある場合は要素が複数の配列としてください。
- 言語の分析の信頼度と話題の分析の信頼度をそれぞれ含めてください。

## 話題の選択肢(key-value形式)
- 1: Environmental_Issues
- 2: Science_and_Technology
- 3: Economics
- 4: Culture_and_Arts
- 5: Sports
- 6: Education
- 7: Politics
- 8: Entertainment
- 9: Travel_and_Tourism
- 10: Business_and_Finance
- 11: Technology_and_Innovation
- 12: Social_Issues
- 13: History
- 14: Food_and_Cuisine
- 15: Nature_and_Wildlife
- 16: Other

## 期待されるJSONレスポンス
{
  "language": "English",
  "language_confidence": 0.5,
  "topics": [
    {"topic_id": 1, "topic_confidence": 0.8},
    {"topic_id": 2, "topic_confidence": 0.65}
  ]
}
"""

実行結果は以下のようになりました。
ケース2で出力された話題のkeyが出力されました。

{
  "language": "Japanese",
  "language_confidence": 0.99,
  "topics": [
    {"topic_id": 8, "topic_confidence": 0.7},
    {"topic_id": 11, "topic_confidence": 0.85},
    {"topic_id": 16, "topic_confidence": 0.6}
  ]
}

colab

今回使ったコードはcolabで公開しています。
使用する際はsecretのOPENAI_API_KEYにご自身のAPIキーを設定してください。

https://colab.research.google.com/drive/197CWvciqr1Khj9W91mK9f0enx5Mq1iW8?usp=sharing

参考

Discussion