OpenAI DevDayで発表されたJSON形式で返すことが保証される「JSONモード」を、AWS Lambdaを利用して試してみた

2023.11.07

はじめに

OpenAI DevDayで発表されたJSONモードをAWS Lambdaを利用して試してみました。

OpenAIの開発者向けカンファレンスのDevDayで様々なアップデートがありました。

弊社ブログでも発表内容がまとめられています。

アップデートのうち、JSON形式でレスポンスを返すことが保証されたJSONモードがサポートされましたので、今回は、新機能をAWS Lambdaを利用して試してみます。

JSONモードに関するドキュメントは、以下のみでコードの例がなかったため、コードも含めて紹介します。

利用するにあたり注意点

  • モデルのうちgpt-4-1106-previewgpt-3.5-turbo-1106のみでJSONモードが利用可能です。
  • response_format{ type:"json_object" }を設定することで、JSONモードが有効になります。
  • プロンプトにJSONという言葉がない場合、エラーになります。
  • レスポンス内容のうち、finish_reasonlengthの場合、メッセージが切れている可能性があります。
  • JSONモードを使用すると、出力データが正しいJSON形式であることは保証されます。しかし、そのデータが特定のスキーマ(データの構造や形式)に一致するかどうかは保証されません

Lambda

Lambdaで利用するOpenAIアカウントAPIキーの発行方法やOpenAIが提供するPython向けのライブラリをLambdaにアップロードする方法は下記の記事を参考ください。

ランタイムPython 3.11を選択し、Lambda関数を作成します。

作成後、下記の設定を行います

  • 環境変数では、キーはAPI_Key、値はAPIキーの値を入力
  • Lambdaのレイヤーを追加します

試してみた

下記のコードで実行してみます。

この例では、1月から12月までの月末の日付(31日、30日など)をグルーピングしてJSON形式で出力しています。

gpt-4-vision-previewは1日100回までの制限があったため、gpt-3.5-turbo-1106で検証しました。

from decimal import Decimal
import json, os, openai

def decimal_to_int(obj):
    if isinstance(obj, Decimal):
        return int(obj)

def lambda_handler(event, context):
    openai.api_key = os.environ['API_Key']
    input_text = """
    1月から12月のうち、月末の日付(31日、30日など)からグルーピングしてJSON形式で出力してください
    """

    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-1106",
        messages=[
            {"role": "user", "content": input_text}
        ],
        response_format= { "type":"json_object" },
        temperature=0,
    )
    response_content = response["choices"][0]["message"]["content"]
    response_content = json.loads(response_content)
    print("Received response:" + json.dumps(response, default=decimal_to_int, ensure_ascii=False))
    return response_content

実行結果は以下の通り、JSONで返ってきました。また、内容も正しいです。

{
  "31日": [
    "1月",
    "3月",
    "5月",
    "7月",
    "8月",
    "10月",
    "12月"
  ],
  "30日": [
    "4月",
    "6月",
    "9月",
    "11月"
  ],
  "28日または29日": [
    "2月"
  ]
}

レスポンス内容は、下記のとおりでした。

finish_reasonlengthになっている場合は、メッセージが一部切れている可能性があります。

Received response:{
    "id": "chatcmpl-8IA9bs4NAl0EVaRugRilyeCnPilSX",
    "object": "chat.completion",
    "created": 1699339627,
    "model": "gpt-3.5-turbo-1106",
    "choices": [
        {
            "index": 0,
            "message": {
                "role": "assistant",
                "content": "{\n  \"31日\": [\"1月\", \"3月\", \"5月\", \"7月\", \"8月\", \"10月\", \"12月\"],\n  \"30日\": [\"4月\", \"6月\", \"9月\", \"11月\"],\n  \"28日\": [\"2月\"]\n}"
            },
            "finish_reason": "stop"
        }
    ],
    "usage": {
        "prompt_tokens": 51,
        "completion_tokens": 65,
        "total_tokens": 116
    },
    "system_fingerprint": "fp_eeff13170a"
}

エラー

ちなみに、input_text内にJSONという言葉を削除すると、以下の通り、JSONという言葉をいれましょうと、エラーメッセージが出力されました。

'messages' must contain the word 'json' in some form, to use 'response_format' of type 'json_object'.

他のプロンプト 1

input_textを下記にしてみます。

    input_text = """
    2023年の日本の祝日とその日付を、月ごとにグルーピングしてJSON形式で出力してください。
    会社の休みが1月4日と12月4日にあるので、追加してください。
    日付を昇順にしてください。
    """

レスポンスは下記のとおりです。

天皇誕生日は、令和においては祝日ではないので、間違えていますね。

{
  "1月": {
    "元日": "2023-01-01",
    "成人の日": "2023-01-09",
    "会社の休み": "2023-01-04"
  },
  "2月": {
    "建国記念の日": "2023-02-11"
  },
  "3月": {
    "春分の日": "2023-03-21"
  },
  "4月": {
    "昭和の日": "2023-04-29"
  },
  "5月": {
    "憲法記念日": "2023-05-03",
    "みどりの日": "2023-05-04",
    "こどもの日": "2023-05-05"
  },
  "7月": {
    "海の日": "2023-07-17"
  },
  "8月": {
    "山の日": "2023-08-11"
  },
  "9月": {
    "敬老の日": "2023-09-18",
    "秋分の日": "2023-09-23"
  },
  "10月": {
    "体育の日": "2023-10-09"
  },
  "11月": {
    "文化の日": "2023-11-03",
    "勤労感謝の日": "2023-11-23"
  },
  "12月": {
    "天皇誕生日": "2023-12-23",
    "会社の休み": "2023-12-04"
  }
}

他のプロンプト 2

以前、OpenAI API のFunction Callingを利用し、プロンプトの中で、アーティスト名と曲名を抽出し、JSON形式で返すように試したことがあります。

同様のことをJSONモードでもできるか確認します。プロンプトは以下の通りです。

    input_text = """
    ## 依頼
    下記の文章から、アーティスト名と曲名を例を参考にJSON形式で出力して下さい。
    アーティスト名や曲名が省略されている場合、正式名称に変換してください。
    ## 例
    {
      "artist": "Ado",
      "song": "うっせいわ"
    }
    ## 文章
    オフィシャルひげだんディズムのプリテンダーをかけてほしいです。できますか?
    """

文章からアーティスト名と曲名を抽出することができました。アーティスト名は、正式名称への変換は難しいようですね。

{
  "artist": "オフィシャルひげだんディズム",
  "song": "プリテンダー"
}

ちなみに、gpt-3.5-turbo-1106の場合、Lambdaの実行時間は、3秒程度でした。

終わりに

今回は、DevDayで発表されたJSONモードを試してみました。

JSON形式で返してくれるため、色々な用途で利用できそうですね。色々なプロンプトで試していきたいと思います。

参考になれば幸いです。