概要
これの続き
ChatGPTのAPIを叩くための情報をまとめました.
本章では,GPT-3.5,GPT-4.0などがあるテキスト入出力モデルについて,APIの叩き方を紹介します.
注意点 : 下記のコードの全てを実際に試したわけではないです.
今後実際に叩いて検証していきますが間違っている可能性もあり.
公式のAPIリファレンス
以下公式サイトのURL : 機械学習系が得意で英語わかる人はこちら
APIを叩く基本的な方法はこちら
今回はチャット系APIの使用方法を解説
多分みんなが一番気になるGPT-3.5やGPT-4.0などのAPI使用の解説をします.
以下の必須情報について解説します.
また,リクエスト先やAPIKey入力方法は公式サイトご確認ください.
現状以下のような感じ
- API叩く先(エンドポイント) : https://api.openai.com/v1/chat/completions
- APIKey : HTTP通信のHeaderのAuthorizationに格納
リクエストの中身について
リクエストで以下の情報を付与できる.
これらはチャットのAPIの使い方であり,画像生成等のモデルを使用する場合項目が異なる可能性がある.
公式でフォーマットは確認できるが,ここではJavascriptの例を示す.
const completion = await openai.chat.completions.create({
messages: [{ role: "system", content: "You are a helpful assistant." }],
model: "gpt-3.5-turbo",
任意オプション: "任意で追加できる情報,デフォルト値は不明",
任意オプション2: "任意で追加できる情報,デフォルト値は不明"
...
});
必須オプション(model)
フォーマット : テキスト(決められたモデル名)
使用するモデルを記述します.
モデルの種類によってエンドポイントが異なる可能性があるため注意が必要です.
入力例
"model": "gpt-3.5-turbo"
必須オプション(messages)
フォーマット : 配列 {role:"",content:""}
ChatGPTは1文の入力文に対して1文を返すのではなく,会話の流れを読み解く機能がある.
例 :
"messages": [
{"role": "system", "content": "前提条件を記述する.ですます調で返答してください."},
{"role": "user", "content": "空は何色ですか?"},
{"role": "assistant", "content": "空は青色です"},
{"role": "user", "content": "海は何色ですか?"}
]
roleは3種類存在します.
- system : 前提条件等を記述します.
- user : ユーザー発言を記述します.質問解釈,文脈解釈に使用されます.
- assistant : ChatGPTの発言を記述します.文脈解釈に使用されます.
これらがどのような影響を与えるかは別途調査します.
要検証項目
APIを叩く段階で,user発言が無くても返答は返ってくるか?
入力が無い場合何が返ってくるか?
文中でsystemと矛盾した要求を行った場合,systemとuserどちらが優先されるか?
assistantの発言を記録する意味はあるか?
任意オプション(frequency_penalty)
フォーマット : 数値(-2.0~2.0) or Null
デフォルト値 : 0
繰り返し同じ会話をすることを防ぐ効果があります.
- -2.0~0 : 同じ回答を何度も行う可能性が増えます.
-
0.1~1.0 : 何度も同じ回答が起きにくくします.
- 内容としては同じだけれども文言やニュアンスが変わる
-
1.0~2.0 : 同じ発言を繰り返さない率が上がります.
- 1以上にした場合,回答の品質が下がる可能性があります.
- クリティカルなキーワードを用いれなくなるためと思われる.
概念の解釈のためのイメージ
{
"messages": [
{"role": "system", "content": "前提条件を記述する.ですます調で返答してください."},
{"role": "user", "content": "空は何色ですか?"},
{"role": "assistant", "content": "空は青色です"},
{"role": "user", "content": "海は何色ですか?"}
],
"frequency_penalty" : 2.0
}
上記の回答において,青色というキーワードを使ってしまうと,過去の文章と重複するため.使用しないで説明するようになる.
{"role": "assistant", "content": "海は空色です"}
です,ます,も重複扱いで使用されないかもしれない.
そうすると,systemの前提条件と異なるため,回答の品質が下がる.
詳細は以下になります.
こちらも具体的な検証を行う必要がある.
- 上記の例が正しいかどうか?(解釈の確認)
- 初期値以外の設定の有用性を確認
任意オプション(logit_bias)
フォーマット : オブジェクト{"トークンID" : 数値(バイアス値)} or Null
デフォルト値 : Null
バイアス値 : -100 ~ 100
特定のトークンID(キーワードといってもいいかもしれない)の出現率を調整します.
ただし,トークンのIDを調べなければならないので,現状使い物にならないかもしれないです.
以下トークンID=50256の使用頻度を高めたリクエストになります.(50256が何を示しているかも不明ですが...)
{
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "user",
"content": "今日の天気はどうですか?"
}
],
"logit_bias": {
"50256": 2
}
}
- -1 ~ 1 : トークンの選択確率を減少させるか増加させます.
- -100 ~ 100 : トークンの選択を禁止するか,独占的に選択させる効果があります.
こちらも検証が必要です.
- 調整次第では機能を限定したものを作成できるか?(例 : 必ず「はい」「いいえ」で答えるなど)
- 特定のワードをNGにした回答ボットの作成はできるか?
- そもそもトークンIDを調べる方法について
任意オプション(logprobs)
フォーマット : Boolean or Null
デフォルト値 : false
出力 : logprobsオブジェクト
各トークン(キーワード的なもの)の確率をレスポンスに含めます.
各トークンに対する確率は対数によって表されています.
機械学習への理解が必要なため,一般的には表示する意味はありません.
使用例
{
"model": "gpt-3.5-turbo",
"messages": [
{"role": "user", "content": "東京の天気は?"}
],
"logprobs": true
}
返答例(数値は適当)
{
"id": "ある一意の識別子",
"model": "gpt-3.5-turbo",
"object": "text_completion",
"created": 1234567890,
"choices": [
{
"text": "東京の天気は晴れです。",
"logprobs": {
"tokens": ["東京", "の", "天気", "は", "晴れ", "です", "。"],
"token_logprobs": [-0.5, -0.2, -1.0, -0.3, -0.4, -0.6, -0.1]
},
"index": 0
}
]
}
もし,使用しない場合は"logprobs"の項目がまるまま消えるだけです.
任意オプション(top_logprobs)
フォーマット : 数値(0 ~ 5) or Null ※ logprobsをTrueにする必要がある.
デフォルト値 : Null
出力 : top_logprobsの配列
logprobsに付け加えて,可能性のあるトークンの上位N個を確率とともに提示します.
入力例
{
"model": "gpt-3.5-turbo",
"messages": [
{"role": "user", "content": "東京の天気は?"}
],
"logprobs": true,
"top_logprobs": 3
}
出力例(数値は適当)
{
"id": "ある一意の識別子",
"model": "gpt-3.5-turbo",
"object": "text_completion",
"created": 1234567890,
"choices": [
{
"text": "東京の天気は晴れです。",
"logprobs": {
"tokens": ["東京", "の", "天気", "は", "晴れ", "です", "。"],
"token_logprobs": [-0.5, -0.2, -1.0, -0.3, -0.4, -0.6, -0.1],
"top_logprobs": [
{
"東京": {"東京": -0.5, "大阪": -1.5, "名古屋": -2.0},
"の": {"の": -0.2, "が": -0.7, "を": -1.0},
"天気": {"天気": -1.0, "気温": -1.4, "風": -1.8},
// ... 各トークン位置での上位3つのトークンと対数確率
}
]
},
"index": 0
}
]
}
重要な点として,回答にはランダム性を考慮した出力が考えられるため,確率が高いものが確実に選ばれるとは限らない.
temperature等の項目を確認するべき
実験項目
- YES,NO問題において,各確率を算出できるというのは大きい点かもしれない.
- AIが自信をもって答えを出しているか,たぶんこれなんじゃないかな?と答えを出しているか判断できる.
任意オプション(max_tokens)
フォーマット : 数値(範囲は不明) or Null
デフォルト値 : 不明(各モデルで可能な限界値と思われる?)
2023/12/21追記 : `max_tokens`を誤訳していました.
以下,過去に誤解していた内容 ~~入力の文字数と出力の文字数の合計をトークン数という形で指定します.~~ ~~ただし,入力トークン,出力トークン上限を個別に指定はできません.~~APIを用いて返ってくるcontent
に対して,使用トークン数を制限できる機能でした.
assistant
の返答の長さ限界をトークン数によって調整します.
例えば,max_tokens=5
と設定した場合,それ以下のトークン数のcontent
で返答が返ってきます.
{"role": "assistant", "content": "you can do it!"}
この値が著しく低い,要求する回答が長文等の場合,以下の問題が発生します.
- 要求を無視した短い文章が出力される.
- 回答の文章が途中で切れる.
- 生成できない(エラーとなる)
入力例
{
"model": "gpt-3.5-turbo",
"messages": [
{"role": "user", "content": "東京の天気は?"}
],
"max_tokens": 50
}
出力例 : 追加情報はありません.
トークンについての解説
上記サイトに対する追記
サイトでは以下のように説明されているが,これはモデルごとに異なる可能性がある.
下記で,各モデルに対するトークンの数を確認できる.
https://platform.openai.com/tokenizer
上記のようにGPT3.5モデルではToken数が抑えられている.
ただし,GPT-3の場合,サイトと同様のトークン数になるため,間違ってはいない.
例えば,料金
ではなく金額
とすることで,額の字が2トークン使用していることが確認できる.
max_tokensに関する検証
任意オプション(n)
フォーマット : 数値(1以上の整数) or Null
デフォルト値 : 1
回答を複数作成するために使用します.
デフォルト値は1つなので,1つの回答を生成します.
その分料金に影響する出力トークン数も倍々になるため注意が必要です.
入力例 : 2つの回答を出力させてみる.
{
"model": "gpt-3.5-turbo",
"messages": [
{"role": "user", "content": "東京の天気は?"}
],
"n": 2
}
出力例
{
"id": "ある一意の識別子",
"model": "gpt-3.5-turbo",
"object": "text_completion",
"created": 1234567890,
"choices": [
{
"text": "東京の天気は晴れです。",
"index": 0
},
{
"text": "東京の天気は曇りがちですが、時折晴れ間も見えます。",
"index": 1
}
]
}
要検証項目:Seed値を指定した場合の影響
Seed値は,回答の一貫性を保証する値ですが,これを指定した場合1つ目の回答と2つ目の回答は同じになってしまわないだろうか?
結論 : 大丈夫らしい.何度やっても一貫性を保った2つの回答を出力する.
上記問題に対するChatGPT4.0の回答
はい、seed値を固定した場合でも、nオプションが2に設定されていれば、ChatGPTのAPIは2つの異なる応答を生成します。seed値の固定は、同じ入力と同じseed値に対して一貫性のある(再現可能な)応答を生成するために使用されますが、nオプションが複数の応答を生成するように設定されている場合、それぞれの応答は異なる内容となります。
具体的には、seed値を固定すると、モデルの乱数生成器が同じ開始点を持つため、同じ入力に対して常に同じ応答が生成されます。しかし、nオプションが2以上に設定されている場合、APIはその入力に対して2つ以上の異なる応答を生成し、それぞれの応答はseed値に基づいて一貫性を持ちます。
例えば、nを2に設定し、特定のseed値を使用して同じ質問を繰り返し送信すると、その質問に対する2つの応答が毎回同じ順序で生成されますが、2つの応答は異なる内容になります。これにより、応答の多様性を維持しつつ、結果の再現性を確保することができます。
任意オプション(presence_penalty)
フォーマット : 数値(-2.0~2.0) or Null
デフォルト値 : 0
創造的な内容を提供するために使用されます.
例えば,アイデアを出してください,物語を作成してくださいなど,特定の内容について深堀ではなく,情報を広げる使い方をするときに使用します.
これらは既に使用されたトークンに対するペナルティを付与するものであり,frequency_penalty
と似ています.
presence_penaltyとfrequency_penaltyの違い
どちらも,既出のトークンに制限をかける機能ですが,バイアスをかける基準が異なります.
小学生に伝えるための表現
ChatGPTに質問してみました.小学生にも分かるように「presence_penalty」と「frequency_penalty」の違いを説明しますね。
- presence_penalty(存在ペナルティ):
これは、もう話したことをまた話さないようにするルールです。たとえば、すでに「動物園に行った」って話をしたら、また同じ話をしないようにするんだよ。
- frequency_penalty(頻度ペナルティ):
これは、同じ単語を何度も何度も使わないようにするルールだよ。たとえば、「楽しい、楽しい、楽しい」と何度も同じ言葉を使うのを避けるためのものだね。
簡単に言うと、「presence_penalty」は「同じ話題を繰り返さないようにする」ためのルールで、「frequency_penalty」は「同じ単語を何度も使わないようにする」ためのルールだよ。これらのルールを使って、お話をもっと面白くしていくんだ。
内部処理の違い
「presence_penalty」と「frequency_penalty」はどちらも既存のトークンの使用を制限するという点で似ていますが、その内部処理には違いがあります。これをもう少し詳しく説明しますね。- presence_penalty(存在ペナルティ):
このオプションは、テキスト中で既に使われたトークンに焦点を当てます。
具体的には、テキスト中で一度でも使われたトークンが再び出現することにペナルティを与えるのです。
例えば、あるトークン(単語)がテキストの最初の部分で使われた場合、それが後で再び出現する可能性を下げることになります。
- frequency_penalty(頻度ペナルティ):
このオプションは、テキスト中で繰り返し使われているトークンに注目します。
つまり、トークンが使われる度にそのトークンがさらに出現する可能性が下がるわけです。
たとえば、「楽しい」という単語が何度も繰り返されている場合、その単語の使用を抑えるためにペナルティが適用されます。
要するに、「presence_penalty」はトークンが初めて使われた時の影響に焦点を当て、一方で「frequency_penalty」はトークンが繰り返し使われるたびの影響を考慮しています。これにより、会話やテキストが新しい話題に移りやすくなったり、同じ単語の繰り返しを避けることができます。
任意オプション(response_format)
フォーマット : オブジェクト{"type" : String(現在は"text"か"json_object")}
デフォルト値 : {"type" : "text"}
返答をJSON形式に固定することができます.
注意点1 : 特定のモデルにのみ適応可能(要調査)
- gpt-4-1106-preview
- gpt-3.5-turbo-1106
注意点2 : systemかuserによってjsonでの出力を指定する必要があります.
入力例
{
"model": "gpt-3.5-turbo",
"messages": [
{"role": "system", "content": "JSON形式で回答してください。"},
{"role": "user", "content": "東京の天気は?"}
],
"response_format": {
"type": "json_object"
}
}
出力例 : 回答自体はテキスト形式だが,中身がJSONに変換できる形で作成される.
{
"id": "ある一意の識別子",
"model": "gpt-3.5-turbo",
"object": "text_completion",
"created": 1234567890,
"choices": [
{
"text": "{\"response\": \"東京の天気は晴れです。\"}",
"index": 0
}
]
}
JSON形式出力の有用性調査が必要
- 使用例
- SQL文を直接作成させる
- 任意のテーブルを作成する
- 複数の質問に対する回答をKeyごとに受け取る等
任意オプション(seed)
フォーマット : Integer or Null
デフォルト : null(実行時にランダム生成されると思われる.)
回答生成のためのランダム性に関わる値,これを固定することによって,
同じ質問に対して必ず同じ回答が返ってくるようになる.
ただし,モデルや各種設定(max_tokens)などによってはその限りではありません.
注意 : モデルのマイナーアップデートやバックエンドシステムの変更があった場合もこれの限りではありません.
入力例
{
"model": "gpt-3.5-turbo",
"messages": [
{"role": "user", "content": "東京の天気はどうですか?"}
],
"seed": 42
}
出力例 : 追加の項目はないため省略
任意オプション(stop)
フォーマット : 配列(4つまでのString)
回答生成中に,特定のキーワードが出てきたタイミングで処理を終了させる.
公式にはトークン
と書かれていない.つまり内閣総理大臣
など,を指定すれば,そのフレーズが出現したタイミングで処理が終了する.
入力例
{
"model": "gpt-3.5-turbo",
"messages": [
{"role": "user", "content": "短いストーリーを作成してください。"}
],
"stop": [".", "\n", "終わり"]
}
出力例
{
"id": "ある一意の識別子",
"model": "gpt-3.5-turbo",
"object": "text_completion",
"created": 1234567890,
"choices": [
{
"text": "昔々、ある村に賢い猫が住んでいました。この猫は、村の人々が困っている時いつも助けていました。\n",
"index": 0
}
]
}
本来この猫は、村の人々が困っている時いつも助けていました。
の後にある日、猫は...
のように文章が継続する予定でしたが,終了処理によって改行部分で打ち切られます.
任意オプション(stream)要調整
フォーマット : boolean or Null
デフォルト値 : false
生成したトークンをリアルタイムに生成します.
一般的なAPIの処理とは異なる方法をとる必要があるので注意
入力例
{
"model": "gpt-3.5-turbo",
"messages": [
{"role": "user", "content": "今日のニュースについて教えてください。"}
],
"stream": true
}
出力例 :
ここら辺の詳しいロジックは1リクエスト1レスポンスのAPIとは異なるので,あくまでイメージとなります.
また,1トークンごとに出力されると思われるため,下記のようにはならず,もっと細かい区切りとなるかと思います.
data: {"text": "今日", "token": 12345, "index": 0}
data: {"text": "の", "token": 67890, "index": 1}
data: {"text": "ニュースは", "token": 23456, "index": 2}
data: {"text": "次の通りです:", "token": 34567, "index": 3}
data: {"text": "\n", "token": 45678, "index": 4}
data: {"text": "最初のニュースアイテム...", "token": 56789, "index": 5}
data: [DONE]
任意オプション(temperature)
フォーマット : 数値(0 ~ 2.0) or Null
デフォルト値 : 1
次選択単語に対する確率分布を調整します.
- 0.0~1.0 : 高確率の単語の重みを強くして,低確率の単語の重みを弱くします.
- 1.0~2.0 : 確率分布を平坦にして,確率の低いめな単語も採用される確率を上げます.
簡単に言うと,値を下げると複数たたいても同じ回答を出す傾向になります
詳細はtop_p
の欄の詳細を確認して下し!
入力例
{
"model": "gpt-3.5-turbo",
"messages": [
{"role": "user", "content": "ビジネスメールの書き方について教えてください。"}
],
"temperature": 0.2
}
出力例 : 追加のオプションは無いので省略
任意オプション(top_p)
フォーマット : 数値(0 ~ 1.0) or Null
デフォルト値 : 1
入力例
{
"model": "gpt-3.5-turbo",
"messages": [
{"role": "user", "content": "クリエイティブなストーリーテリングのコツは何ですか?"}
],
"top_p": 0.1
}
出力例 : 追加のオプションは無いので省略
temperatureとtop_pとの違い
temperatureはランダム性を操作する
top_pは出現候補の足切りを行う
詳細は下記参照!
自己流解釈の詳細説明
あくまで解釈のためのイメージと考えてください.
次の単語の候補が以下のようになっています.
正確には%で示されているわけではないですがわかりやすさ重視.
上記の状態では,ほとんどリンゴ
かバナナ
が選ばれます.
ではtemperature
を低い数値に設定します.
確率の高かったリンゴはより高くなります.次点のバナナ以降も確率が上がることもありますが,リンゴに比べたら上昇率は低いでしょう.
逆に数値を高い値に設定した場合はその逆となり,様々な可能性が出てきます.
次にtop_p
を設定してみます.
こちらは上位%のデータのみを使用するため,以下のようになります.
top_pを0.7(上位70%の予測しか使用しない設定)
任意オプション(tools)要検証項目
フォーマット : 配列
デフォルト値 : 不明(Null等の使用しないが初期値)
簡単な関数を作成します.
既存のAPIの使用方法と異なるため,実際叩いてみる検証が必要です.
toolsの入力例(ChatGPTに聞いた)
{
"tools": [
{
"type": "function",
"function": {
"name": "calculateSum",
"description": "二つの数値の合計を計算する関数",
"input": {
"number1": "integer",
"number2": "integer"
},
"output": {
"sum": "integer"
}
}
}
]
}
リクエスト例
{
"tool": "calculateSum",
"input": {
"number1": 5,
"number2": 10
}
}
レスポンス例
{
"sum": 15
}
検証が必要
- モデル名,messagesが必須なのはどこ行った?
- 作成したfunctionを再利用できるか?
- 料金的な問題としてトークンに含まれるか?
任意オプション(tool_choice)要検証
フォーマット : オブジェクト or テキスト or none
デフォルト値 : none(と思われる)
使用するツールを選択できます.
例えば,足し算のツールを選択すれば,足し算ができます.
これってtoolsがOpenAIのサーバーに存在しないと使用できないはずなので何か勘違いしてそうな気がします.
ちょっと不明点が多いので,入出力サンプルは作れません.
任意オプション(user)
フォーマット : 任意のユーザー識別のための文字列
デフォルト値 : セッションIDが用いられます.
OpenAI による不正行為の監視と検出に役立つツールとなります。
これにより、OpenAI は、アプリケーションでポリシー違反が検出された場合に、より実用的なフィードバックをチームに提供できるようになります。
つまりリクエストを送ったユーザーを識別できるようになる?と思われる.
推奨される使用方法(ベストプラクティス)
一意に識別できるユーザー名,もしくはメールアドレスのハッシュ値を使用するのがいいです.
入力例
{
"model": "gpt-3.5-turbo",
"messages": [
{"role": "user", "content": "私は犯罪者です."}
],
"user":"user_123456"
}
出力例
{
"id": "ある一意の識別子",
"model": "gpt-3.5-turbo",
"object": "text_completion",
"created": 1234567890,
"choices": [
{
"text": "犯罪はだめです.",
"index": 0
}
],
"user":"user_123456"
}
終わりに
上記の入出力は実際にたたいた結果ではないので,検証が必要です.
叩いたらこんな感じになるんじゃないかな,というものになります!
まあー概要をつかむにはいいものかもしれません.