2023/10/29

つないでみよう:#2)ChatGPT API の利用

Web 系アプリ開発のど素人が、チャレンジする WebAPI 連携の日記『オールドタイプでもできる(かも)WebAPI 連携』の第 2 回です。

前回に続き ChatGPT です。前回作成した API を使って API を実際に利用してみます。まずは、OpenAI が提供している API のリファレンスを確認します。

OpenAI API reference


OpenAI には様々な種類の API があるようですね。ブラウザの翻訳機能の力を借りつつ読み進めると、API 利用に必要な情報が集まります。今回は、Chat に関する API についてまとめます。


リクエストヘッダ

リファレンスの GETTING STARTED の Making Request に記述がありました。curl コマンドの記述ではありますが、リクエストヘッダにセットすべき項目が読み取れます。

$OPENAI_API_KEY には、前回取得したキーを設定するということですね。


エンドポイント

リファレンスの ENDPOINTS を読み進めます。どうやら Chat 機能を実現する API は chat completion と呼ぶようですね。Create chat completion セクションには、次の記載があります。

POST  https://api.openai.com/v1/chat/completions

ここから HTTP リクエストメソッドは POST であることと送信する URL がわかります。


リクエストボディ

API に送信するリクエストの中身を JSON で指定します。指定する JSON のフォーマットは、Create chat completion セクション直下の Request body に記載があります。必須項目は次の2つだけのようです。

messages は array とありますので、配列で指定するようです。プロパティを開いて詳細を確認すると、role と content が必須であることがわかります。


レスポンス

API からの返答については The chat completion object に記載があります。リクエストした発言に対する応答は choices の messeage にセットされます。ChatGPT ではまれに複数の返答を返すことがありますが、これに対応するために choices は配列になっているのだと思います。

usage オブジェクトには、今回のコールで使用されたトークン数が出力されます。トークン数は課金のベースとなります。


サンプルプログラム

これで必要な材料がそろったので、これらを使ってサンプルプログラムを作成します。

フォームを新規作成して、サンプルプログラムの動作を記録する RequestBody と Responce フィールドを配置します。ボタンを作成し、次のプログラムを記述します。

Sub Click(Source As Button)
   Dim ns As New NotesSession
   Dim nuiw As New NotesUIWorkspace
   Dim nuid As NotesUIDocument
   Dim nd As NotesDocument
   Dim sURL As String
   Dim http As NotesHTTPRequest
   Dim jnav As NotesJSONNavigator
   Dim ja As NotesJSONArray
   Dim jobj As NotesJSONObject

   Set nuid = nuiw.CurrentDocument
   Set nd = nuid.Document

   'HTTP リクエストの準備
   Set http = ns.CreateHTTPRequest()

   'HTTP ヘッダーの設定
   Call http.SetHeaderField("Content-Type", "application/json")
   Call http.SetHeaderField("Authorization", "Bearer (ここにAPIキーをセット)")

   'RequestBody(JSON) の準備
   Set jnav = ns.CreateJSONNavigator("")
   Call jnav.AppendElement("gpt-3.5-turbo","model")
   Set ja = jnav.AppendArray("messages")
   Set jobj = ja.AppendObject()
   Call jobj.AppendElement("user", "role")
   Call jobj.AppendElement("1たす4は?", "content")
   'JSON をフィールドにセット(確認用)
   Call nd.ReplaceItemValue("RequestBody", jnav.Stringify)

   'API 実行
   http.PreferJSONNavigator = True
   sURL = "https://api.openai.com/v1/chat/completions"    'エンドポイント
   Set jnav = http.Post(sURL, jnav.Stringify)
   'Responce の JSON をフィールドにセット(確認用)
   Call nd.ReplaceItemValue("Responce", jnav.Stringify)
End Sub


実行と結果の確認

フォームをプリビューして、ボタンをクリックすると次のようになり、API に送信した Request body と API からの返答が JSON で表示されます。

まず、Request body です。整形すると次のようになります。

{
   "model": "gpt-3.5-turbo",
   "messages": [
      {
         "role": "user",
         "content": "1たす4は?"
      }
   ]
}

リファレンスに倣って model には、"gpt-3.5-turbo" を指定しました。API に渡す内容は、messages に配列で指定します。こちらからの発言なので、role は "user"とし、質問内容を content にセットしています。


Responce の JSON は次のようになっていました。以下の部分でこちらからの質問に答えていることがわかりますね。

{
   "id": "chatcmpl-8EOI9TaVJOocOQeA5Y16qQgh9MqhG",
   "object": "chat.completion",
   "created": 1698440661,
   "model": "gpt-3.5-turbo-0613",
   "choices": [
      {
         "index": 0,
         "message": {
            "role": "assistant",
            "content": "1たす4は5です。"
         },
         "finish_reason": "stop"
      }
   ],
   "usage": {
      "prompt_tokens": 13,
      "completion_tokens": 8,
      "total_tokens": 21
   }
}

API の role は "assistant" なんですね。


追加の質問

Request body の messages は配列で指定する仕様となっていました。これを利用するとこれまでの会話に対して追加の質問ができるようになります。

例えば、次のように API の返答と追加の質問を加えた JSON を作成して送信すると『5の2乗は25です。』と答えてくれます。

{
   "model": "gpt-3.5-turbo",
   "messages": [
      {
         "role": "user",
         "content": "1たす4は?"
      },
      {
         "role": "assistant",
         "content": "1たす4は5です。"
      },
      {
         "role": "user",
         "content": "それを2乗して!"
      }

   ]
}

このようにこれまでの会話を含めて次の質問をすることができますが、リクエストのたびに全体を送信する必要があります。そのため、リクエストが雪だるま式に大きくなり課金に跳ね返ってくるという結果となります。注意しましょう。


前回 連載:つないでみよう 次回

0 件のコメント:

コメントを投稿