[アップデート] Amazon Nova の Tool Use で利用する ToolChoice オプションに Any と Tool モードが追加されました
こんにちは!クラウド事業本部コンサルティング部のたかくに(@takakuni_)です。
Amazon Nova の Tool Use で利用する ToolChoice オプションに Any と Tool モードが追加されました。
ToolChoice
ToolChoice は Tool Use で利用可能なオプションの 1 つです。
Tool Use は、「選択肢に機能A, 機能B があり、ユーザーからは XX と指示が来ています。どの機能をどういったパラメーターで利用すればいいですか?」といった質問に、「機能A を YY, ZZ で呼び出してください。」といった回答が期待できる機能です。Tool Use は Function Calling といった呼び方もされます。
ToolChoice は、Tool Use の回答をどのように回答させるか変化させるオプションです。モードは以下の 3 つが提供されています。
- Auto
- デフォルトの設定値
- Tool Use の回答が可能であれば、関数名、パラメータを回答
- Tool Use の回答が難しい場合は、ユーザーに追加情報を求めるプロンプトを生成
- Any
- Tool Use 内で定義した関数の中のどれかで、関数名、パラメータを回答
- ユーザーに追加情報を求めるプロンプトを生成しない
- Tool
- 開発者が指定した特定のツールのパラメータを回答させる
アップデート内容
今まで Amazon Nova では Tool use は使えたものの、ToolChoice オプションは Auto モードのみサポートしていました。
システム間でアプリケーション連携している場合、Auto モードで利用していると、ユーザーに追加情報を求めるプロンプトを生成されてもスキーマが合わず、エラーになるケースが考えられます。
今回のアップデートではこのようなニーズに応じて、Any と Tool モードもサポートされました。というものです。
やってみた
それでは実際に ToolChoice オプションを利用し、挙動の違いを確認してみます。
Auto
まずは、 Auto から試します。
input_text = "I want to all products"
と定義し、get_all_products
を呼び出すような書き方にします。
import json
import boto3
client = boto3.client("bedrock-runtime", region_name="us-west-2")
tool_config = {
"toolChoice": {
"auto": {}
},
"tools": [
{
"toolSpec": {
"name": "get_all_products",
"description": "API to retrieve multiple products with filtering and pagination options",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"sort_by": {
"type": "string",
"description": "Field to sort results by. One of: price, name, created_date, popularity",
"default": "created_date"
},
"sort_order": {
"type": "string",
"description": "Order of sorting (ascending or descending). One of: asc, desc",
"default": "desc"
},
},
"required": []
}
}
}
},
{
"toolSpec": {
"name": "get_products_by_id",
"description": "API to retrieve retail products based on search criteria",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"product_id": {
"type": "string",
"description": "Unique identifier of the product"
},
},
"required": ["product_id"]
}
}
}
}
]
}
input_text = "I want to all products"
messages = [{
"role": "user",
"content": [{"text": input_text}]
}]
inf_params = {"maxTokens": 1000, "topP": 1, "temperature": 1}
response = client.converse(
modelId="us.amazon.nova-lite-v1:0",
messages=messages,
toolConfig=tool_config,
inferenceConfig=inf_params,
additionalModelRequestFields= {"inferenceConfig": {"topK":1}}
)
# Pretty print the response JSON.
print("[Full Response]")
print(json.dumps(response, indent=2))
for block in response["output"]["message"]["content"]:
if "toolUse" in block:
print("\n[Tool Use]")
print(json.dumps(block["toolUse"], indent=2))
予想通り、get_all_products
を呼ぶ出すようレスポンスが返ってきていますね。
(nova-toolchoice-py3.12) takakuni@ nova-toolchoice % python main.py
[Full Response]
{
"ResponseMetadata": {
"RequestId": "8ee12e32-3273-4e30-a117-097376499274",
"HTTPStatusCode": 200,
"HTTPHeaders": {
"date": "Thu, 20 Mar 2025 12:12:50 GMT",
"content-type": "application/json",
"content-length": "511",
"connection": "keep-alive",
"x-amzn-requestid": "8ee12e32-3273-4e30-a117-097376499274"
},
"RetryAttempts": 0
},
"output": {
"message": {
"role": "assistant",
"content": [
{
"text": "<thinking>The User wants to retrieve all the products. I can use the `get_all_products` tool to retrieve the products. I will use the default sorting options for this request.</thinking>\n"
},
{
"toolUse": {
"toolUseId": "tooluse_s89BifZpTIm5Qv42EU9keQ",
"name": "get_all_products",
"input": {
"sort_by": "created_date",
"sort_order": "desc"
}
}
}
]
}
},
"stopReason": "tool_use",
"usage": {
"inputTokens": 524,
"outputTokens": 98,
"totalTokens": 622
},
"metrics": {
"latencyMs": 765
}
}
[Tool Use]
{
"toolUseId": "tooluse_s89BifZpTIm5Qv42EU9keQ",
"name": "get_all_products",
"input": {
"sort_by": "created_date",
"sort_order": "desc"
}
}
続いて、どちらの tool にも当てはまらないような文章にしてみます。
import json
import boto3
client = boto3.client("bedrock-runtime", region_name="us-west-2")
tool_config = {
"toolChoice": {
"auto": {}
},
"tools": [
{
"toolSpec": {
"name": "get_all_products",
"description": "API to retrieve multiple products with filtering and pagination options",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"sort_by": {
"type": "string",
"description": "Field to sort results by. One of: price, name, created_date, popularity",
"default": "created_date"
},
"sort_order": {
"type": "string",
"description": "Order of sorting (ascending or descending). One of: asc, desc",
"default": "desc"
},
},
"required": []
}
}
}
},
{
"toolSpec": {
"name": "get_products_by_id",
"description": "API to retrieve retail products based on search criteria",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"product_id": {
"type": "string",
"description": "Unique identifier of the product"
},
},
"required": ["product_id"]
}
}
}
}
]
}
+ input_text = "Hi, Nova! How do you do?"
- input_text = "I want to all products"
messages = [{
"role": "user",
"content": [{"text": input_text}]
}]
inf_params = {"maxTokens": 1000, "topP": 1, "temperature": 1}
response = client.converse(
modelId="us.amazon.nova-lite-v1:0",
messages=messages,
toolConfig=tool_config,
inferenceConfig=inf_params,
additionalModelRequestFields= {"inferenceConfig": {"topK":1}}
)
# Pretty print the response JSON.
print("[Full Response]")
print(json.dumps(response, indent=2))
for block in response["output"]["message"]["content"]:
if "toolUse" in block:
print("\n[Tool Use]")
print(json.dumps(block["toolUse"], indent=2))
Tool Use のレスポンスは行われず、thinking
タグの後に、追加の補足情報を求めてきています。
(nova-toolchoice-py3.12) takakuni@ nova-toolchoice % python main.py
[Full Response]
{
"ResponseMetadata": {
"RequestId": "69100d70-5c5d-438c-854c-3eecf45dd058",
"HTTPStatusCode": 200,
"HTTPHeaders": {
"date": "Thu, 20 Mar 2025 12:14:56 GMT",
"content-type": "application/json",
"content-length": "384",
"connection": "keep-alive",
"x-amzn-requestid": "69100d70-5c5d-438c-854c-3eecf45dd058"
},
"RetryAttempts": 0
},
"output": {
"message": {
"role": "assistant",
"content": [
{
"text": "<thinking>The User is greeting and asking how I am doing. I should respond politely and acknowledge the greeting.</thinking>\nHi there! I'm doing well, thank you for asking. How can I assist you today?"
}
]
}
},
"stopReason": "end_turn",
"usage": {
"inputTokens": 528,
"outputTokens": 46,
"totalTokens": 574
},
"metrics": {
"latencyMs": 525
}
}
Any
続いて、 Any モードに切り替えます。 Any は tools 内のどちらかで Tool Use を返すモードです。
import json
import boto3
client = boto3.client("bedrock-runtime", region_name="us-west-2")
tool_config = {
"toolChoice": {
+ "any": {}
- "auto": {}
},
"tools": [
{
"toolSpec": {
"name": "get_all_products",
"description": "API to retrieve multiple products with filtering and pagination options",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"sort_by": {
"type": "string",
"description": "Field to sort results by. One of: price, name, created_date, popularity",
"default": "created_date"
},
"sort_order": {
"type": "string",
"description": "Order of sorting (ascending or descending). One of: asc, desc",
"default": "desc"
},
},
"required": []
}
}
}
},
{
"toolSpec": {
"name": "get_products_by_id",
"description": "API to retrieve retail products based on search criteria",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"product_id": {
"type": "string",
"description": "Unique identifier of the product"
},
},
"required": ["product_id"]
}
}
}
}
]
}
input_text = "Hi, Nova! How do you do?"
messages = [{
"role": "user",
"content": [{"text": input_text}]
}]
inf_params = {"maxTokens": 1000, "topP": 1, "temperature": 1}
response = client.converse(
modelId="us.amazon.nova-lite-v1:0",
messages=messages,
toolConfig=tool_config,
inferenceConfig=inf_params,
additionalModelRequestFields= {"inferenceConfig": {"topK":1}}
)
# Pretty print the response JSON.
print("[Full Response]")
print(json.dumps(response, indent=2))
for block in response["output"]["message"]["content"]:
if "toolUse" in block:
print("\n[Tool Use]")
print(json.dumps(block["toolUse"], indent=2))
ただ、返ってきた結果は auto 同様、Tool Use のレスポンスは行われないような形になりました。
(nova-toolchoice-py3.12) takakuni@ nova-toolchoice % python main.py
[Full Response]
{
"ResponseMetadata": {
"RequestId": "4b178dfd-e0f0-4cf2-a018-d372a0a49535",
"HTTPStatusCode": 200,
"HTTPHeaders": {
"date": "Thu, 20 Mar 2025 12:23:01 GMT",
"content-type": "application/json",
"content-length": "317",
"connection": "keep-alive",
"x-amzn-requestid": "4b178dfd-e0f0-4cf2-a018-d372a0a49535"
},
"RetryAttempts": 0
},
"output": {
"message": {
"role": "assistant",
"content": [
{
"text": "\nHello! I'm doing well, thank you for asking. How can I assist you today? If you have any questions about products, feel free to ask!"
}
]
}
},
"stopReason": "end_turn",
"usage": {
"inputTokens": 533,
"outputTokens": 37,
"totalTokens": 570
},
"metrics": {
"latencyMs": 383
}
}
時折、thinking タグも発生するため、今の所、アップデートされていない可能性がありそうです。
(nova-toolchoice-py3.12) takakuni@ nova-toolchoice % python main.py
[Full Response]
{
"ResponseMetadata": {
"RequestId": "fe806ea2-efc0-450c-9d87-889519370893",
"HTTPStatusCode": 200,
"HTTPHeaders": {
"date": "Thu, 20 Mar 2025 12:24:56 GMT",
"content-type": "application/json",
"content-length": "501",
"connection": "keep-alive",
"x-amzn-requestid": "fe806ea2-efc0-450c-9d87-889519370893"
},
"RetryAttempts": 0
},
"output": {
"message": {
"role": "assistant",
"content": [
{
"text": "\n<thinking> The user is greeting me, but there is no specific request or question. I should respond politely and ask if there's anything specific they need help with. </thinking>\nHi there! I'm doing well, thank you. How can I assist you today? If you have any questions or need help with something, feel free to ask!"
}
]
}
},
"stopReason": "end_turn",
"usage": {
"inputTokens": 533,
"outputTokens": 77,
"totalTokens": 610
},
"metrics": {
"latencyMs": 745
}
}
Tool
最後に、特定の Tool の利用を指定する Tool モードです。
"Hi, Nova! How do you do?"
のテキストに対して、get_products_by_id
を強制するよう指定しています。どのような結果が返ってくるのでしょう。
import json
import boto3
client = boto3.client("bedrock-runtime", region_name="us-west-2")
tool_config = {
"toolChoice": {
+ "tool": { "name" : "get_products_by_id"}
- "any": {}
},
"tools": [
{
"toolSpec": {
"name": "get_all_products",
"description": "API to retrieve multiple products with filtering and pagination options",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"sort_by": {
"type": "string",
"description": "Field to sort results by. One of: price, name, created_date, popularity",
"default": "created_date"
},
"sort_order": {
"type": "string",
"description": "Order of sorting (ascending or descending). One of: asc, desc",
"default": "desc"
},
},
"required": []
}
}
}
},
{
"toolSpec": {
"name": "get_products_by_id",
"description": "API to retrieve retail products based on search criteria",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"product_id": {
"type": "string",
"description": "Unique identifier of the product"
},
},
"required": ["product_id"]
}
}
}
}
]
}
input_text = "Hi, Nova! How do you do?"
messages = [{
"role": "user",
"content": [{"text": input_text}]
}]
inf_params = {"maxTokens": 1000, "topP": 1, "temperature": 1}
response = client.converse(
modelId="us.amazon.nova-lite-v1:0",
messages=messages,
toolConfig=tool_config,
inferenceConfig=inf_params,
additionalModelRequestFields= {"inferenceConfig": {"topK":1}}
)
# Pretty print the response JSON.
print("[Full Response]")
print(json.dumps(response, indent=2))
for block in response["output"]["message"]["content"]:
if "toolUse" in block:
print("\n[Tool Use]")
print(json.dumps(block["toolUse"], indent=2))
Tool Use が発生し、架空の Product ID で指示がきていますね。
(nova-toolchoice-py3.12) takakuni@ nova-toolchoice % python main.py
[Full Response]
{
"ResponseMetadata": {
"RequestId": "ab1bb737-827e-4656-be5e-1e39ea83bf0a",
"HTTPStatusCode": 200,
"HTTPHeaders": {
"date": "Thu, 20 Mar 2025 12:28:58 GMT",
"content-type": "application/json",
"content-length": "283",
"connection": "keep-alive",
"x-amzn-requestid": "ab1bb737-827e-4656-be5e-1e39ea83bf0a"
},
"RetryAttempts": 0
},
"output": {
"message": {
"role": "assistant",
"content": [
{
"toolUse": {
"toolUseId": "tooluse_rmXBBBAuQvyYhnAuzqBOEA",
"name": "get_products_by_id",
"input": {
"product_id": 1
}
}
}
]
}
},
"stopReason": "tool_use",
"usage": {
"inputTokens": 541,
"outputTokens": 18,
"totalTokens": 559
},
"metrics": {
"latencyMs": 311
}
}
[Tool Use]
{
"toolUseId": "tooluse_rmXBBBAuQvyYhnAuzqBOEA",
"name": "get_products_by_id",
"input": {
"product_id": 1
}
}
まとめ
以上、「Amazon Nova の Tool Use で利用する ToolChoice オプションに Any と Tool モードが追加されました。」でした。
システム間の連携でスキーマを強制させたいケースでは確かに必要な機能だと思いました。
このブログがどなたかの参考になれば幸いです。
クラウド事業本部コンサルティング部のたかくに(@takakuni_)でした!