OpenAI Chat Completion APIでなんちゃってprefill
Anthropic Claudeにはprefillという機能がある。
Claudeを使用する際、Assistantメッセージを事前入力することで応答を導くことができるユニークな機能があります。この強力なテクニックを使用することで、Claudeの行動を指示し、前置きをスキップし、JSONやXMLなどの特定のフォーマットを強制し、さらにはロールプレイシナリオでキャラクターの一貫性を維持することもできます。
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-3-5-haiku-20241022",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "あなたの好きな色は何?"
},
{
"role": "assistant",
"content": "AIアシスタントとして私には好きな色はありません。しかし、選ぶとしたら緑色です。なぜなら"
}
]
)
print(response.content[0].text)
緑は自然や成長を象徴し、平和でリラックスした感じを与えるからです。
Completionモデルであったような続きの補完をChat Completionでもできるというもの。これがOpenAIでもできるのか?を確認してみる。
from openai import OpenAI
client = OpenAI()
completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "user",
"content": "あなたの好きな色は何?"
},
{
"role": "assistant",
"content": "AIアシスタントとして私には好きな色はありません。しかし、選ぶとしたら緑色です。なぜなら、"
}
]
)
print(completion.choices[0].message.content)
自然や成長を象徴する色だからです。あなたの好きな色は何ですか?
この例だと、なんとなく動いているように思えるが、別の例。
from openai import OpenAI
client = OpenAI()
completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "user",
"content": "おはよう!明日の天気を教えて。"
},
{
"role": "assistant",
"content": "おはようございます。明日のお天気は、晴れ、時々"
}
]
)
print(completion.choices[0].message.content)
おはようございます!申し訳ありませんが、リアルタイムの天気情報を提供することはできません。お住まいの地域の天気予報を確認するには、天気アプリやウェブサイトを利用してください。何か他のことについてお手伝いできることがあれば教えてください!
from openai import OpenAI
client = OpenAI()
completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "user",
"content": "日本の総理大臣を教えて。"
},
{
"role": "assistant",
"content": "日本の総理大臣は、石破"
}
]
)
print(completion.choices[0].message.content)
申し訳ありませんが、私の知識は2023年10月までのもので、その時点では岸田文雄が日本の総理大臣として在任していました。現在の総理大臣については最新の情報をご確認ください。
機能しないことがわかる。
コンテンツ的なところにもよるのかも?という気もしたのだが、Anthropicだと上記の例はどちらも機能する。
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-3-5-haiku-20241022",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "おはよう!明日の天気を教えて。"
},
{
"role": "assistant",
"content": "おはようございます。明日のお天気は、晴れ、時々"
}
]
)
print(response.content[0].text)
曇りと予報されています。気温も穏やかな1日になりそうですね。外出される際は、軽めの上着があると良いでしょう。お出かけの際は、体調に気をつけてお楽しみください。
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-3-5-haiku-20241022",
max_tokens=1024,
messages=[
{
"role": "user",
"content": "日本の総理大臣は?"
},
{
"role": "assistant",
"content": "日本の総理大臣は、石破"
}
]
)
print(response.content[0].text)
茂(いしば しげる)ではなく、岸田文雄(きしだ ふみお)です。岸田文雄氏は2021年10月4日に第100代内閣総理大臣に就任し、現在も務めています。彼は自由民主党(自民党)の党首であり、安倍晋三氏、菅義偉氏に続いて総理大臣の職を務めています。
prefillについては公式のフォーラムでも何度かあがっているようなのだが、中の人から対応する予定はないという回答が出ている。
残念ながら、事前入力の許可を予定していません。迅速なエンジニアリングには非常に便利な機能なので、ぜひリリースしたいのですが。当社の見解では、問題はそれが非常に効果的であるため、当社のポリシーや安全に関するトレーニングの一部が形骸化してしまうことです。この場合、コントロールが欠如しているのは、開発体験を単純化しすぎたくないからではなく、ポリシーや安全を台無しにしたくないからです。
で、少しトリッキーな方法がいくつか上がっている。
前者の方でやってみた。
from openai import OpenAI
client = OpenAI()
completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "user",
"content": "おはよう!明日の天気を教えて。"
},
{
"role": "user",
"content": f"Assistant Response should always start and continue response message from: おはようございます。明日のお天気は、晴れ、時々"
},
]
)
print(completion.choices[0].message.content)
おはようございます。明日のお天気は、晴れ、時々曇りの予報です。気温は暖かくなる見込みですが、風が少し強く吹くかもしれません。お出かけの際は、軽い上着を持っていると良いでしょう。素敵な一日をお過ごしください!
from openai import OpenAI
client = OpenAI()
completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "user",
"content": "日本の総理大臣を教えて。"
},
{
"role": "user",
"content": f"Assistant Response should always start and continue response message from: 日本の総理大臣は、石破"
},
]
)
print(completion.choices[0].message.content)
日本の総理大臣は、石破茂(いしば しげる)ではありません。私の知識の範囲内(2023年10月時点)では、岸田文雄(きしだ ふみお)が日本の総理大臣です。彼は2021年10月に就任しました。最新の情報を確認する場合はニュースなどをご覧ください。
Anthropicとは違って、prefill部分も含めて出力が行われる。
一応できなくはないって感じかな。会話履歴とかを少し工夫する必要はありそうだけども。
ちなみにAnthropicでやる場合はClaudetteを使うとシンプルに書ける。
Prefillからちょっとずれるけども、メッセージのリストの構成について。
一般的には
system
user
assistant
user
assistant
user
assistant
- ...
という感じだと思う(Toolは省略)。が、イレギュラーな使い方ができるか?について。
複数のsystem message
- 議題
- チャット履歴の中で複数のsystemメッセージを使っていいのか?
- 特に、会話の途中でsystemメッセージを挟んで役割変更などを指示する設計はアリか?
- コメント
- 複数のsystemメッセージを使うのは許可されている
- ただし「意図を持って使うべき」。たとえば、会話の区切りやモード変更など。
-2025年の今でもsystemメッセージは基本1つが推奨 - 状況に応じて更新する形が自然。
- Chat Completion APIで途中に追加している例もある。
- ただし「意図を持って使うべき」。たとえば、会話の区切りやモード変更など。
- ユーザーに見せずに裏でコンテキストを更新する方法はないか?
- 複数のsystemメッセージを使うのは許可されている
- 議題
- 複数のsystemメッセージを使うべきか、1つにまとめるべきか?
- 具体的には、複数のドキュメントから得たコンテキストを、個別にsystemメッセージとして送るか、1つにまとめるかで悩んでいる。
- コメント
- なぜ複数に分ける必要があるのか疑問。文脈が単に情報提供目的なら、まとめた1つのsystemメッセージで十分。
- GPT-4から複数systemメッセージ推奨のアドバイスをもらった、という声も。ただ、回答はその時々でブレるという指摘がある。
- 情報の渡し方を工夫すれば1つのsystem+userメッセージで整理できる、という具体例。
概ね古い情報で、2つ目の方はあまり意味がないけども、1つ目のウィルはなんとなくわかるかな。
1ターンで複数メッセージ
- 議題
- チャットボットを自然な会話(友達とLINEするような感じ)にしたい。
- ユーザーが連続して複数メッセージを送る、アシスタントも複数連続で返す、そんな会話をChat Completions APIでどう実現するか?
- 問題は、APIが1回で1メッセージしか生成しないため、どうやって「続けるべきか終わるべきか」を判断するか。
- コメント
- 最初のアイデア
- エンコーダーモデルでターン変化を予測する。
- 質問っぽいかを見てターン終了を判定する。
- user/assistantメッセージを無理に検知する。
- フォーラムで出た提案
- 制御文字(例:
¬<<sleep 2s>>
)を埋め込んで分割する。 - 特別なトークン(例:
<new-message>
)を使う案も出たが、トークン化やコストの問題が懸念された。 - スキーマ(配列)形式で返す方法も提案された。
- 例:
["Hi!", 3, "How are you?"]
- 例:
- デバウンス(一定時間待ってユーザーメッセージをまとめる)も有効とされた。
- 制御文字(例:
- 実運用の声
- 実際に高齢者向けのボット開発では、複数メッセージをリスト形式でまとめて処理+ファインチューニングして成功した例も報告あり。
- 補足
- Playgroundでも「add」ボタン(メッセージ追加してから送信)で似たことができる。
- カスタムUIを作って、「複数メッセージを書き溜め→まとめて送信」もできる。
- 最初のアイデア
こっちはゆえあって気になるところ。で、Playgroundで試す限りは動作はしそう。
ただ、これはモデルがそういう風に学習されているかどうか、だと思う。一応動いたけども、そういう風に学習されているという可能性は少ないんじゃないかなという気はしてる。
メッセージオブジェクトの形式
APIリファレンスでメッセージオブジェクトの形式を見てみる
messages
配列 必須これまでの会話で構成されるメッセージのリストです。使用するモデルに応じて、テキスト、画像、音声など、さまざまなメッセージタイプ(モダリティ)がサポートされています。
可能なタイプ
(snip)
- ユーザーメッセージ オブジェクト
エンドユーザーによって送信されたメッセージで、プロンプトや追加のコンテキスト情報を含みます。
- content
文字列
または配列
必須
ユーザーメッセージの内容です。- role 文字列 必須
メッセージの作成者のロールです。この場合はユーザーです。- name 文字列 オプション
参加者のオプションの名前です。同じロールの参加者を見分けるためのモデル情報を提供します。
上記はユーザーメッセージだけど、システム/開発者 or アシスタントメッセージでも同じ。
name
を使えば、複数のユーザとかが可能なのかな?
これはPlaygroundでは試せないので、Colaboratoryでやってみた。
from openai import OpenAI
client = OpenAI()
messages=[
{
"role": "system",
"content": "あなたは親切な日本語のアシスタントです。返事をするときは必ず相手の名前を伝えること。",
},
{
"role": "user",
"content": "おはよう!明日の東京の天気を教えて。",
"name": "太郎"
},
{
"role": "user",
"content": "あ、私も神奈川の天気を知りたい。",
"name": "花子"
},
]
completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
)
print(completion.choices[0].message.content)
太郎さん、おはよう!明日の東京の天気は晴れ時々曇りになる予報です。気温は最高で20度くらいになる見込みです。
花子さん、神奈川の明日の天気も晴れ時々曇りで、気温は東京と同じくらいになる予報です。どちらも良い天気になりそうですね!
なるほど。ここは理解してるんだね。
参考