6
7

# AnthropicとCohereとBedrockのTool Useを比較

Posted at

↓使用するSDK
Claude 3 (Anthropic) Claude 3 (Bedrock) Command R (Cohere) Command R (Bedrock)
Anthropic Python API library ✅️ ✅️
Cohere Python SDK ✅️ ✅️
Boto3 ✅️ ✅️

Boto3を使う場合、呼び出し方は統一されているが、レスポンスが統一されない印象

## Anthropic Python API library

こちらを参考に実施します。

pip install anthropic

Bedrockを使用する場合はboto3もインストールします。

クライアントを生成します。

from anthropic import Anthropic

client = Anthropic(api_key="sk-*****")

Bedrockを使用する場合はこうなります。

from anthropic import AnthropicBedrock

client = AnthropicBedrock()

ツールの関数を作成します。

calculator関数
def calculator(operation, operand1, operand2):
return operand1 + operand2
elif operation == "subtract":
return operand1 - operand2
elif operation == "multiply":
return operand1 * operand2
elif operation == "divide":
if operand2 == 0:
raise ValueError("Cannot divide by zero.")
return operand1 / operand2
else:
raise ValueError(f"Unsupported operation: {operation}")

Claudeに教えるツールのスキーマを作成します。

ツールの定義
calculator_tool = {
"name": "calculator",
"description": "A simple calculator that performs basic arithmetic operations.",
"input_schema": {
"type": "object",
"properties": {
"operation": {
"type": "string",
"description": "The arithmetic operation to perform.",
},
"operand1": {"type": "number", "description": "The first operand."},
"operand2": {"type": "number", "description": "The second operand."},
},
"required": ["operation", "operand1", "operand2"],
},
}

Claude 3を呼び出します。

response = client.messages.create(
model="claude-3-haiku-20240307",  # Bedrockの場合は"anthropic.claude-3-haiku-20240307-v1:0"
system="You have access to tools, but only use them when necessary.  If a tool is not required, respond as normal",
messages=[
{
"role": "user",
"content": "Multiply 1984135 by 9343116. Only respond with the result",
}
],
max_tokens=300,
# Tell Claude about our tool
tools=[calculator_tool],
)

responseを確認します。

response.stop_reason
'tool_use'
response.content
[ToolUseBlock(id='toolu_bdrk_01Q1xoTJvFXuPKoLpemL3k6z', input={'operand1': 1984135, 'operand2': 9343116, 'operation': 'multiply'}, name='calculator', type='tool_use')]

responseからツールの名前とインプットを取得します。

tool_name = response.content[0].name
tool_inputs = response.content[0].input

print("The Tool Name Claude Wants To Call:", tool_name)
print("The Inputs Claude Wants To Call It With:", tool_inputs)
The Tool Name Claude Wants To Call: calculator
The Inputs Claude Wants To Call It With: {'operand1': 1984135, 'operand2': 9343116, 'operation': 'multiply'}

ツール名「calculator」とパラメーター「{'operand1': 1984135, 'operand2': 9343116, 'operation': 'multiply'}」が取得できました。

operation = tool_inputs["operation"]
operand1 = tool_inputs["operand1"]
operand2 = tool_inputs["operand2"]

result = calculator(operation, operand1, operand2)
print("RESULT IS", result)
RESULT IS 18538003464660

ツール呼び出しができました。

## Cohere Python SDK

pip install cohere

Bedrockを使用する場合はboto3もインストールします。

クライアントを生成します。

import cohere

co = cohere.Client(api_key="*****")

Bedrockを使用する場合はこうなります。

co = cohere.BedrockClient(
aws_region="us-east-1",
)

ツールの関数を作成します。

calculator関数
def calculator(operation, operand1, operand2):
return operand1 + operand2
elif operation == "subtract":
return operand1 - operand2
elif operation == "multiply":
return operand1 * operand2
elif operation == "divide":
if operand2 == 0:
raise ValueError("Cannot divide by zero.")
return operand1 / operand2
else:
raise ValueError(f"Unsupported operation: {operation}")

Command Rに教えるツールのスキーマを作成します。

AnthropicのAPIとは形式が異なります。

ツールの定義
calculator_tool = {
"name": "calculator_tool",
"description": "A simple calculator that performs basic arithmetic operations.",
"parameter_definitions": {
"operation": {
"type": "string",
"description": "The arithmetic operation to perform. Possible enum values: add, subtract, multiply, divide.",
"required": True,
},
"operand1": {
"type": "number",
"description": "The first operand.",
"required": True,
},
"operand2": {
"type": "number",
"description": "The second operand.",
"required": True,
},
},
}

Toolのnameを「calculator」にすると以下のエラーが発生します。

status_code: 400, body: {'message': "invalid request: the 'calculator' tool can't be used with a custom definition: choose a different name or remove the provided definition"}

calculator2calculator_toolではエラーにならないので、内部的な予約語とバッティングしているのかもしれません。

Command Rを呼び出します。

# user request
message = "Multiply 1984135 by 9343116. Only respond with the result"

response = co.chat(
message=message,
tools=[calculator_tool],
preamble="You have access to tools, but only use them when necessary.  If a tool is not required, respond as normal",
model="command-r",  # Bedrockの場合はcohere.command-r-v1:0
)

responseを確認します。

response.finish_reason
'COMPLETE'
response.tool_calls
[ToolCall(name='calculator_tool', parameters={'operand1': 1984135, 'operand2': 9343116, 'operation': 'multiply'})]

responseからツールの名前とインプットを取得します。

tool_name = response.tool_calls[0].name
tool_inputs = response.tool_calls[0].parameters

print("The Tool Name Claude Wants To Call:", tool_name)
print("The Inputs Claude Wants To Call It With:", tool_inputs)
The Tool Name Claude Wants To Call: calculator_tool
The Inputs Claude Wants To Call It With: {'operand1': 1984135, 'operand2': 9343116, 'operation': 'multiply'}

operation = tool_inputs["operation"]
operand1 = tool_inputs["operand1"]
operand2 = tool_inputs["operand2"]

result = calculator(operation, operand1, operand2)
print("RESULT IS", result)
RESULT IS 18538003464660

ツール呼び出しができました。

## Boto3

pip install boto3

クライアントを生成します。

import boto3

client = boto3.client("bedrock-runtime")

ツールの関数を作成します。

calculator関数
def calculator(operation, operand1, operand2):
return operand1 + operand2
elif operation == "subtract":
return operand1 - operand2
elif operation == "multiply":
return operand1 * operand2
elif operation == "divide":
if operand2 == 0:
raise ValueError("Cannot divide by zero.")
return operand1 / operand2
else:
raise ValueError(f"Unsupported operation: {operation}")

Anthropic Python API libraryやCohere Python SDKと比べ、階層が深い印象です。

enumの記述方法は、Claudeに合わせています。

ツールの定義
calculator_tool = {
"toolSpec": {
"name": "calculator_tool",
"description": "A simple calculator that performs basic arithmetic operations.",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"operation": {
"type": "string",
"description": "The arithmetic operation to perform.",
},
"operand1": {
"type": "number",
"description": "The first operand.",
},
"operand2": {
"type": "number",
"description": "The second operand.",
},
},
"required": ["operation", "operand1", "operand2"],
}
},
}
}

### Claude 3 (Bedrock)

Claude 3で実行します。

model_id = "anthropic.claude-3-haiku-20240307-v1:0"

response = client.converse(
modelId=model_id,
system=[
{
"text": "You have access to tools, but only use them when necessary.  If a tool is not required, respond as normal"
}
],
messages=[
{
"role": "user",
"content": [
{"text": "Multiply 1984135 by 9343116. Only respond with the result"}
],
}
],
toolConfig={"tools": [calculator_tool]},
inferenceConfig={"maxTokens": 400},
)

import json
print(json.dumps(response["output"], indent=2, ensure_ascii=False))
response["output"]
{
"message": {
"role": "assistant",
"content": [
{
"toolUse": {
"toolUseId": "tooluse_VioZeA2_TSySf54-3AmGQg",
"name": "calculator_tool",
"input": {
"operation": "multiply",
"operand1": 1984135,
"operand2": 9343116
}
}
}
]
}
}
response["stopReason"]
'tool_use'
response["output"]["message"]["content"]
[{'toolUse': {'toolUseId': 'tooluse_bOgY4tZ8QOC9-Fq58nvTHA',
'name': 'calculator',
'input': {'operand1': 1984135,
'operand2': 9343116,
'operation': 'multiply'}}}]

responseからツールの名前とインプットを取得します。

tool_name = response["output"]["message"]["content"][0]["toolUse"]["name"]
tool_inputs = response["output"]["message"]["content"][0]["toolUse"]["input"]

print("The Tool Name Claude Wants To Call:", tool_name)
print("The Inputs Claude Wants To Call It With:", tool_inputs)
The Tool Name Claude Wants To Call: calculator_tool
The Inputs Claude Wants To Call It With: {'operand1': 1984135, 'operand2': 9343116, 'operation': 'multiply'}

operation = tool_inputs["operation"]
operand1 = tool_inputs["operand1"]
operand2 = tool_inputs["operand2"]

result = calculator(operation, operand1, operand2)
print("RESULT IS", result)
RESULT IS 18538003464660

ツール呼び出しができました。

### Command R (Bedrock)

モデルIDをcohere.command-r-v1:0に変えて実行してみます。

model_id = "cohere.command-r-v1:0"

response = client.converse(
modelId=model_id,
system=[
{
"text": "You have access to tools, but only use them when necessary.  If a tool is not required, respond as normal"
}
],
messages=[
{
"role": "user",
"content": [
{"text": "Multiply 1984135 by 9343116. Only respond with the result"}
],
}
],
toolConfig={"tools": [calculator_tool]},
inferenceConfig={"maxTokens": 400},
)

import json
print(json.dumps(response["output"], indent=2, ensure_ascii=False))
response["output"]
{
"message": {
"role": "assistant",
"content": [
{
"text": "I will use the calculator tool to multiply the two given numbers and respond with the result."
},
{
"toolUse": {
"toolUseId": "tooluse_3Vx63WQyQmmZ45jFNU8mgA",
"name": "calculator_tool",
"input": {
"operand1": {
"value": 1984135
},
"operand2": {
"value": 9343116
},
"operation": {
"enum": [
"multiply"
]
}
}
}
}
]
}
}

Claude 3の実行結果と比べると、色々違いがあります。

• Claude 3はcontent内がtoolUseのみですが、Command RはtexttoolUseが含まれる（なので、配列の0番目で取得できない）
• toolUse.inputの内容も微妙に形式が異なるので、受け取った側で頑張る必要がある
Claude 3
"input": {
"operation": "multiply",
"operand1": 1984135,
"operand2": 9343116
}
Command R
"input": {
"operand1": {
"value": 1984135
},
"operand2": {
"value": 9343116
},
"operation": {
"enum": [
"multiply"
]
}
}

なので、結果を受け取ってパースする処理に変更が必要です。

tool_name = ""
tool_inputs = ""

for content in response["output"]["message"]["content"]:
if "toolUse" in content:
tool_name = content["toolUse"]["name"]
tool_inputs = content["toolUse"]["input"]

print("The Tool Name Claude Wants To Call:", tool_name)
print("The Inputs Claude Wants To Call It With:", tool_inputs)
operation = tool_inputs["operation"]["enum"][0]
operand1 = tool_inputs["operand1"]["value"]
operand2 = tool_inputs["operand2"]["value"]

result = calculator(operation, operand1, operand2)
print("RESULT IS", result)
RESULT IS 18538003464660

6
7
0

Register as a new user and use Qiita more conveniently

1. You get articles that match your needs
2. You can efficiently read back useful information
3. You can use dark theme
What you can do with signing up
6
7