先に結論
接続先→ ↓使用する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()
ツールの関数を作成します。
def calculator(operation, operand1, operand2):
if operation == "add":
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",
"enum": ["add", "subtract", "multiply", "divide"],
"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を確認します。
'tool_use'
[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
同じ内容をCohere Python SDKでやってみましょう。
pip install cohere
Bedrockを使用する場合はboto3
もインストールします。
クライアントを生成します。
import cohere
co = cohere.Client(api_key="*****")
Bedrockを使用する場合はこうなります。
co = cohere.BedrockClient(
aws_region="us-east-1",
)
ツールの関数を作成します。
def calculator(operation, operand1, operand2):
if operation == "add":
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とは形式が異なります。
例えば、Anthropicではenum
として定義していましたが、Cohereはdescription
で指定する必要があります。参考
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"}
calculator2
やcalculator_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を確認します。
'COMPLETE'
[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
最後はBoto3です。新しく追加になったConverse APIを使用します。
pip install boto3
クライアントを生成します。
import boto3
client = boto3.client("bedrock-runtime")
ツールの関数を作成します。
def calculator(operation, operand1, operand2):
if operation == "add":
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",
"enum": ["add", "subtract", "multiply", "divide"],
"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))
{
"message": {
"role": "assistant",
"content": [
{
"toolUse": {
"toolUseId": "tooluse_VioZeA2_TSySf54-3AmGQg",
"name": "calculator_tool",
"input": {
"operation": "multiply",
"operand1": 1984135,
"operand2": 9343116
}
}
}
]
}
}
'tool_use'
[{'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))
{
"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はtext
とtoolUse
が含まれる(なので、配列の0番目で取得できない) -
toolUse.input
の内容も微妙に形式が異なるので、受け取った側で頑張る必要がある
"input": {
"operation": "multiply",
"operand1": 1984135,
"operand2": 9343116
}
"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
毎回enum
やvalue
が返ってくるのか、enum
は必ず配列なのかなど、不確定要素がありそうな印象です。