Amazon BedrockのPrompt ManagementがGAしました🎉🎉🎉
プレビュー時との違いなどはこちらに情報がありました!(ありがとうございます!)
Prompt Managementとは?
プロンプトをテンプレート化して登録しておく機能です。(超ざっくり!)
テンプレート化?
以下のプロンプトを例にします。
<text>の内容を英語に翻訳してください。
<text>こんにちは</text>
このプロンプトの一部分を変数(Variables)にして、再利用しやすい形にします。
変数は{{
}}
で囲って表現します。
<text>の内容を{{language}}に翻訳してください。
<text>{{message}}</text>
language
message
Prompt Managementやってみた
では、Prompt Managementを使ってみましょう
まずは、Boto3を「1.35.56」以降にアップデートします。
pip install -U boto3
「create_prompt」APIを使用するので、作成するものは「プロンプト」となるのですが、一般用語としての「プロンプト」と見分けがつかないので、本記事では「"プロンプト"」とダブルクオートで囲って表現することにします。
"プロンプト"の作成は「bedrock-agent」を使います。
"プロンプト"の利用は従来通り「bedrock-runtime」を使います。
import boto3
bedrock_agent = boto3.Session().client("bedrock-agent")
bedrock_runtime = boto3.Session().client("bedrock-runtime")
プロンプトテンプレートのタイプとして、2024/11/09時点では「TEXT」と「CHAT」の2種類あります。
シンプルなテキスト(templateType: TEXT)
"プロンプト"の作成はAPIで一発です。
response = bedrock_agent.create_prompt(
name="prompt1",
variants=[
{
"name": "variant-1",
"modelId": "anthropic.claude-3-haiku-20240307-v1:0",
"templateType": "TEXT",
"templateConfiguration": {
"text": {
"text": "<text>の内容を{{language}}に翻訳してください。<text>{{message}}</text>",
"inputVariables": [{"name": "language"}, {"name": "message"}],
}
},
}
],
)
prompt1_arn = response["arn"]
他に推論のパラメーター(inferenceConfiguration)やメタデータ(metadata)の指定も可能です。
作成した"プロンプト"を使用するにはInvokeModel APIやConverse APIを使用します。
通常の呼び出しと異なる部分は以下のとおりです。
- modelIdに"プロンプト"のARNを指定する
- promptVariablesパラメーターで、変数を指定する
- messagesパラメーターがない
respnose = bedrock_runtime.converse(
modelId=prompt1_arn,
promptVariables={"language": {"text": "英語"}, "message": {"text": "こんにちは"}},
)
呼び出し結果のフォーマットは通常のConverse APIと同様です。
{'ResponseMetadata': {'RequestId': 'd204bb30-a46c-4319-ae47-824858fe12fc',
'HTTPStatusCode': 200,
'HTTPHeaders': {'date': 'Sat, 09 Nov 2024 01:31:43 GMT',
'content-type': 'application/json',
'content-length': '251',
'connection': 'keep-alive',
'x-amzn-requestid': 'd204bb30-a46c-4319-ae47-824858fe12fc'},
'RetryAttempts': 0},
'output': {'message': {'role': 'assistant',
'content': [{'text': 'Here is the translation of the text in English:\n\n<text>Hello</text>'}]}},
'stopReason': 'end_turn',
'usage': {'inputTokens': 35, 'outputTokens': 21, 'totalTokens': 56},
'metrics': {'latencyMs': 1010}}
呼び出し部分がとてもシンプルになりますね!
複雑なこともできるチャット(templateType: CHAT)
templateTypeがTEXTの場合は、シンプルな一つのテキストのみでしたが、CHATを使うと複雑なことができるようになります。
具体的には以下のような違いがあります。
- システムプロンプトの指定ができる
- messagesとして、ユーザーとアシスタントのやり取りを複数指定できる(5つまで?)
- ツールの指定ができる(後述)
response = bedrock_agent.create_prompt(
name="prompt2",
variants=[
{
"name": "variant-1",
"modelId": "anthropic.claude-3-haiku-20240307-v1:0",
"templateType": "CHAT",
"templateConfiguration": {
"chat": {
"system": [{"text": "あなたは優秀なAIアシスタントです"}],
"messages": [
{
"role": "user",
"content": [
{
"text": "<text>の内容を{{language}}に翻訳してください。<text>{{message}}</text>"
}
],
}
],
"inputVariables": [{"name": "language"}, {"name": "message"}],
}
},
}
],
)
prompt2_arn = response["arn"]
contentで指定できるタイプはtextのみのようです。(Imageなどはできなさそう)
呼び出し部分は変わりません。
respnose = bedrock_runtime.converse(
modelId=prompt2_arn,
promptVariables={"language": {"text": "英語"}, "message": {"text": "こんにちは"}},
)
せっかくチャットなので、複数回のやり取りをしたい場合はどうするのでしょう?
ドキュメント上明確な記載は見つけられませんでしたが、初回のレスポンス以降をmessasgesにセットするとうまくいきました。
messages = []
messages.append(respnose["output"]["message"])
messages.append(
{
"role": "user",
"content": [{"text": "ありがとう。私が依頼した内容を復唱してください。"}],
}
)
respnose = bedrock_runtime.converse(
modelId=prompt2_arn,
promptVariables={"language": {"text": "英語"}, "message": {"text": "こんにちは"}},
messages=messages,
)
{'ResponseMetadata': {'RequestId': '166daa25-6feb-4da4-a53a-3778e7a60734',
'HTTPStatusCode': 200,
'HTTPHeaders': {'date': 'Sat, 09 Nov 2024 01:49:55 GMT',
'content-type': 'application/json',
'content-length': '331',
'connection': 'keep-alive',
'x-amzn-requestid': '166daa25-6feb-4da4-a53a-3778e7a60734'},
'RetryAttempts': 0},
'output': {'message': {'role': 'assistant',
'content': [{'text': '依頼された内容は以下の通りです:\n\n<text>こんにちは</text>\n\nを英語に翻訳してください、というものでした。'}]}},
'stopReason': 'end_turn',
'usage': {'inputTokens': 93, 'outputTokens': 47, 'totalTokens': 140},
'metrics': {'latencyMs': 1060}}
Tool呼び出し(templateType: CHAT)
templateTypeがCHATの場合はツール呼び出しも"プロンプト"に含めることができます。
toolConfigurationブロックでツールを定義します。
response = bedrock_agent.create_prompt(
name="prompt3",
variants=[
{
"name": "variant-1",
"modelId": "anthropic.claude-3-haiku-20240307-v1:0",
"templateType": "CHAT",
"templateConfiguration": {
"chat": {
"messages": [
{
"role": "user",
"content": [
{"text": "{{location}}の天気は?"},
],
}
],
"inputVariables": [{"name": "location"}],
"toolConfiguration": {
"toolChoice": {"auto": {}},
"tools": [
{
"toolSpec": {
"name": "get_weather",
"description": "Get the current weather in a given location",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
}
},
"required": ["location"],
}
},
}
}
],
},
}
},
}
],
)
prompt3_arn = response["arn"]
respnose = bedrock_runtime.converse(
modelId=prompt3_arn,
promptVariables={"location": {"text": "東京"}},
)
{'ResponseMetadata': {'RequestId': '3f61250f-f524-4ad3-bbcc-4f329095915b',
'HTTPStatusCode': 200,
'HTTPHeaders': {'date': 'Sat, 09 Nov 2024 01:56:04 GMT',
'content-type': 'application/json',
'content-length': '281',
'connection': 'keep-alive',
'x-amzn-requestid': '3f61250f-f524-4ad3-bbcc-4f329095915b'},
'RetryAttempts': 0},
'output': {'message': {'role': 'assistant',
'content': [{'toolUse': {'toolUseId': 'tooluse_RXZdMEfySyGT5ZZIS9RpnQ',
'name': 'get_weather',
'input': {'location': '東京'}}}]}},
'stopReason': 'tool_use',
'usage': {'inputTokens': 353, 'outputTokens': 54, 'totalTokens': 407},
'metrics': {'latencyMs': 724}}
期待通り、呼び出し結果にtoolUseが含まれます。
ツール実行結果をtoolResultとしてセットし、再度呼び出します。
messages = []
messages.append(respnose["output"]["message"])
messages.append(
{
"role": "user",
"content": [
{
"toolResult": {
"toolUseId": respnose["output"]["message"]["content"][0]["toolUse"][
"toolUseId"
],
"content": [{"text": "晴れ"}],
}
}
],
}
)
respnose = bedrock_runtime.converse(
modelId=prompt3_arn,
promptVariables={"location": {"text": "東京"}},
messages=messages,
)
{'ResponseMetadata': {'RequestId': '5de772cd-f4cb-4b6a-8bff-0c1de97316ee',
'HTTPStatusCode': 200,
'HTTPHeaders': {'date': 'Sat, 09 Nov 2024 01:56:08 GMT',
'content-type': 'application/json',
'content-length': '217',
'connection': 'keep-alive',
'x-amzn-requestid': '5de772cd-f4cb-4b6a-8bff-0c1de97316ee'},
'RetryAttempts': 0},
'output': {'message': {'role': 'assistant',
'content': [{'text': '東京の天気は晴れです。'}]}},
'stopReason': 'end_turn',
'usage': {'inputTokens': 423, 'outputTokens': 15, 'totalTokens': 438},
'metrics': {'latencyMs': 1035}}
エージェント呼び出し
GAのタイミングでBedrockエージェントにも対応したようです。
"プロンプト"の作成まではできるものの、呼び出し方がわからないです。。
Converse APIではエラーになり、Invoke Agentだと"プロンプト"を指定する方法がわからないです。
TBD.