使用计算器工具与 Claude

在此食谱中,我们将演示如何为 Claude 提供一个简单的计算器工具,使其能够根据用户输入执行算术运算。我们将定义计算器工具,并展示 Claude 如何与它进行交互来解决数学问题。

步骤 1:设置环境

首先,让我们安装所需的库并设置 Anthropic API 客户端。

%pip install anthropic
from anthropic import Anthropic

client = Anthropic()
MODEL_NAME = "claude-3-opus-20240229"

步骤 2:定义计算器工具

我们将定义一个简单的计算器工具,它可以执行基本的算术运算。该工具将以数学表达式作为输入,并返回结果。

请注意,我们正在对输出的表达式调用 eval。这是一个不好的做法,通常不应使用,但我们是为了演示的目的而这样做。

import re

def calculate(expression):
    # 从表达式中删除任何非数字或非运算符字符
    expression = re.sub(r'[^0-9+\-*/().]', '', expression)

    try:
        # 使用内置的 eval() 函数计算表达式
        result = eval(expression)
        return str(result)
    except (SyntaxError, ZeroDivisionError, NameError, TypeError, OverflowError):
        return "Error: Invalid expression"

tools = [
    {
        "name": "calculator",
        "description": "一个执行基本算术运算的简单计算器。",
        "input_schema": {
            "type": "object",
            "properties": {
                "expression": {
                    "type": "string",
                    "description": "要计算的数学表达式(例如,“2 + 3 * 4”)。"
                }
            },
            "required": ["expression"]
        }
    }
]

在此示例中,我们定义了一个 calculate 函数,该函数以数学表达式作为输入,使用正则表达式删除任何非数字或非运算符字符,然后使用内置的 eval() 函数计算表达式。如果计算成功,则返回结果字符串。如果计算过程中发生错误,则返回错误消息。

然后,我们定义了计算器工具及其输入模式,该模式期望一个名为 expression 的字符串类型属性。

步骤 3:与 Claude 交互

现在,让我们看看 Claude 如何与计算器工具进行交互来解决数学问题。

def process_tool_call(tool_name, tool_input):
    if tool_name == "calculator":
        return calculate(tool_input["expression"])

def chat_with_claude(user_message):
    print(f"\n{'='*50}\nUser Message: {user_message}\n{'='*50}")

    message = client.messages.create(
        model=MODEL_NAME,
        max_tokens=4096,
        messages=[{"role": "user", "content": user_message}],
        tools=tools,
    )

    print(f"\nInitial Response:")
    print(f"Stop Reason: {message.stop_reason}")
    print(f"Content: {message.content}")

    if message.stop_reason == "tool_use":
        tool_use = next(block for block in message.content if block.type == "tool_use")
        tool_name = tool_use.name
        tool_input = tool_use.input

        print(f"\nTool Used: {tool_name}")
        print(f"Tool Input: {tool_input}")

        tool_result = process_tool_call(tool_name, tool_input)

        print(f"Tool Result: {tool_result}")

        response = client.messages.create(
            model=MODEL_NAME,
            max_tokens=4096,
            messages=[
                {"role": "user", "content": user_message},
                {"role": "assistant", "content": message.content},
                {
                    "role": "user",
                    "content": [
                        {
                            "type": "tool_result",
                            "tool_use_id": tool_use.id,
                            "content": tool_result,
                        }
                    ],
                },
            ],
            tools=tools,
        )
    else:
        response = message

    final_response = next(
        (block.text for block in response.content if hasattr(block, "text")),
        None,
    )
    print(response.content)
    print(f"\nFinal Response: {final_response}")

    return final_response

步骤 4:试一试!

现在 Claude 已经可以使用计算器了,让我们给它一些示例数学问题。

chat_with_claude("What is the result of 1,984,135 * 9,343,116?")
chat_with_claude("Calculate (12851 - 593) * 301 + 76")
chat_with_claude("What is 15910385 divided by 193053?")
==================================================
User Message: What is the result of 1,984,135 * 9,343,116?
==================================================

Initial Response:
Stop Reason: tool_use
Content: [ContentBlock(text='<thinking>\n计算器函数是回答此请求的相关工具,因为它涉及评估数学表达式。\n\n计算器函数所需的参数是:\nexpression:要计算的数学表达式。\n\n用户在请求中直接提供了要计算的完整表达式:“1,984,135 * 9,343,116”。这包含了必需的表达式参数的所有信息。\n\n因此,我们拥有调用计算器工具的必要信息。\n</thinking>', type='text'), ContentBlockToolUse(id='toolu_01V2mzqp5qkB5QucRFjJUJLD', input={'expression': '1984135 * 9343116'}, name='calculator', type='tool_use')]

Tool Used: calculator
Tool Input: {'expression': '1984135 * 9343116'}
Tool Result: 18538003464660
[ContentBlock(text='因此,1,984,135 * 9,343,116 的结果是 18,538,003,464,660。', type='text')]

Final Response: 因此,1,984,135 * 9,343,116 的结果是 18,538,003,464,660。

==================================================
User Message: Calculate (12851 - 593) * 301 + 76
==================================================

Initial Response:
Stop Reason: tool_use
Content: [ContentBlock(text='<thinking>\n用户提供了一个要计算的数学表达式:(12851 - 593) * 301 + 76\n这可以通过计算器工具来处理。让我们检查一下是否提供了必需的“expression”参数:\nexpression:“(12851 - 593) * 301 + 76” - 这是用户直接提供的。\n由于必需的参数已提供,我们可以继续调用计算器工具。\n</thinking>', type='text'), ContentBlockToolUse(id='toolu_01Mrrfy9adBzzxvhfZwnyJAe', input={'expression': '(12851 - 593) * 301 + 76'}, name='calculator', type='tool_use')]

Tool Used: calculator
Tool Input: {'expression': '(12851 - 593) * 301 + 76'}
Tool Result: 3689734
[ContentBlock(text='因此,计算表达式 (12851 - 593) * 301 + 76 的最终结果是 3689734。', type='text')]

Final Response: 因此,计算表达式 (12851 - 593) * 301 + 76 的最终结果是 3689734。

==================================================
User Message: What is 15910385 divided by 193053?
==================================================

Initial Response:
Stop Reason: tool_use
Content: [ContentBlock(text='<thinking>\n计算器函数是回答此请求的合适工具,因为它可以执行除法等基本算术运算。\n\n计算器函数需要一个参数:\n- expression:要计算的数学表达式\n\n在这种情况下,用户提供了要计算的完整表达式(15910385 除以 193053)。由于已提供所有必需的信息,我们可以继续调用计算器函数。\n</thinking>', type='text'), ContentBlockToolUse(id='toolu_01BfnN4LKp7oPRgmRzWeYdBG', input={'expression': '15910385 / 193053'}, name='calculator', type='tool_use')]

Tool Used: calculator
Tool Input: {'expression': '15910385 / 193053'}
Tool Result: 82.41459599177428
[ContentBlock(text='因此,15910385 除以 193053 等于 82.41459599177428。', type='text')]

Final Response: 因此,15910385 除以 193053 等于 82.41459599177428。

'因此,15910385 除以 193053 等于 82.41459599177428。'