tool_use/calculator_tool.ipynb (277 lines of code) (raw):

{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Using a Calculator Tool with Claude\n", "In this recipe, we'll demonstrate how to provide Claude with a simple calculator tool that it can use to perform arithmetic operations based on user input. We'll define the calculator tool and show how Claude can interact with it to solve mathematical problems." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 1: Set up the environment\n", "\n", "First, let's install the required libraries and set up the Anthropic API client." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pip install anthropic" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "from anthropic import Anthropic\n", "\n", "client = Anthropic()\n", "MODEL_NAME = \"claude-3-opus-20240229\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 2: Define the calculator tool\n", "We'll define a simple calculator tool that can perform basic arithmetic operations. The tool will take a mathematical expression as input and return the result. \n", "\n", "Note that we are calling ```eval``` on the outputted expression. This is bad practice and should not be used generally but we are doing it for the purpose of demonstration." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import re\n", "\n", "def calculate(expression):\n", " # Remove any non-digit or non-operator characters from the expression\n", " expression = re.sub(r'[^0-9+\\-*/().]', '', expression)\n", " \n", " try:\n", " # Evaluate the expression using the built-in eval() function\n", " result = eval(expression)\n", " return str(result)\n", " except (SyntaxError, ZeroDivisionError, NameError, TypeError, OverflowError):\n", " return \"Error: Invalid expression\"\n", "\n", "tools = [\n", " {\n", " \"name\": \"calculator\",\n", " \"description\": \"A simple calculator that performs basic arithmetic operations.\",\n", " \"input_schema\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", " \"expression\": {\n", " \"type\": \"string\",\n", " \"description\": \"The mathematical expression to evaluate (e.g., '2 + 3 * 4').\"\n", " }\n", " },\n", " \"required\": [\"expression\"]\n", " }\n", " }\n", "]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example, we define a calculate function that takes a mathematical expression as input, removes any non-digit or non-operator characters using a regular expression, and then evaluates the expression using the built-in eval() function. If the evaluation is successful, the result is returned as a string. If an error occurs during evaluation, an error message is returned.\n", "\n", "We then define the calculator tool with an input schema that expects a single expression property of type string." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 3: Interact with Claude\n", "Now, let's see how Claude can interact with the calculator tool to solve mathematical problems." ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "def process_tool_call(tool_name, tool_input):\n", " if tool_name == \"calculator\":\n", " return calculate(tool_input[\"expression\"])\n", "\n", "def chat_with_claude(user_message):\n", " print(f\"\\n{'='*50}\\nUser Message: {user_message}\\n{'='*50}\")\n", "\n", " message = client.messages.create(\n", " model=MODEL_NAME,\n", " max_tokens=4096,\n", " messages=[{\"role\": \"user\", \"content\": user_message}],\n", " tools=tools,\n", " )\n", "\n", " print(f\"\\nInitial Response:\")\n", " print(f\"Stop Reason: {message.stop_reason}\")\n", " print(f\"Content: {message.content}\")\n", "\n", " if message.stop_reason == \"tool_use\":\n", " tool_use = next(block for block in message.content if block.type == \"tool_use\")\n", " tool_name = tool_use.name\n", " tool_input = tool_use.input\n", "\n", " print(f\"\\nTool Used: {tool_name}\")\n", " print(f\"Tool Input: {tool_input}\")\n", "\n", " tool_result = process_tool_call(tool_name, tool_input)\n", "\n", " print(f\"Tool Result: {tool_result}\")\n", "\n", " response = client.messages.create(\n", " model=MODEL_NAME,\n", " max_tokens=4096,\n", " messages=[\n", " {\"role\": \"user\", \"content\": user_message},\n", " {\"role\": \"assistant\", \"content\": message.content},\n", " {\n", " \"role\": \"user\",\n", " \"content\": [\n", " {\n", " \"type\": \"tool_result\",\n", " \"tool_use_id\": tool_use.id,\n", " \"content\": tool_result,\n", " }\n", " ],\n", " },\n", " ],\n", " tools=tools,\n", " )\n", " else:\n", " response = message\n", "\n", " final_response = next(\n", " (block.text for block in response.content if hasattr(block, \"text\")),\n", " None,\n", " )\n", " print(response.content)\n", " print(f\"\\nFinal Response: {final_response}\")\n", "\n", " return final_response" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 4: Try it out!\n", "\n", "Let's try giving Claude a few example math questions now that it has access to a calculator." ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "==================================================\n", "User Message: What is the result of 1,984,135 * 9,343,116?\n", "==================================================\n", "\n", "Initial Response:\n", "Stop Reason: tool_use\n", "Content: [ContentBlock(text='<thinking>\\nThe calculator function is the relevant tool to answer this request, since it involves evaluating a mathematical expression.\\n\\nThe required parameter for the calculator function is:\\nexpression: The mathematical expression to evaluate.\\n\\nThe human has directly provided the full expression to evaluate in their request: \"1,984,135 * 9,343,116\". This contains all the information needed for the required expression parameter.\\n\\nSo I have the necessary information to invoke the calculator tool.\\n</thinking>', type='text'), ContentBlockToolUse(id='toolu_01V2mzqp5qkB5QucRFjJUJLD', input={'expression': '1984135 * 9343116'}, name='calculator', type='tool_use')]\n", "\n", "Tool Used: calculator\n", "Tool Input: {'expression': '1984135 * 9343116'}\n", "Tool Result: 18538003464660\n", "[ContentBlock(text='Therefore, the result of 1,984,135 * 9,343,116 is 18,538,003,464,660.', type='text')]\n", "\n", "Final Response: Therefore, the result of 1,984,135 * 9,343,116 is 18,538,003,464,660.\n", "\n", "==================================================\n", "User Message: Calculate (12851 - 593) * 301 + 76\n", "==================================================\n", "\n", "Initial Response:\n", "Stop Reason: tool_use\n", "Content: [ContentBlock(text='<thinking>\\nThe user has provided a mathematical expression to be evaluated: (12851 - 593) * 301 + 76\\nThis can be handled by the calculator tool. Let\\'s check if the required \"expression\" parameter is provided:\\nexpression: \"(12851 - 593) * 301 + 76\" - This is directly provided by the user.\\nSince the required parameter is present, we can proceed with calling the calculator tool.\\n</thinking>', type='text'), ContentBlockToolUse(id='toolu_01Mrrfy9adBzzxvhfZwnyJAe', input={'expression': '(12851 - 593) * 301 + 76'}, name='calculator', type='tool_use')]\n", "\n", "Tool Used: calculator\n", "Tool Input: {'expression': '(12851 - 593) * 301 + 76'}\n", "Tool Result: 3689734\n", "[ContentBlock(text='So the final result of evaluating the expression (12851 - 593) * 301 + 76 is 3689734.', type='text')]\n", "\n", "Final Response: So the final result of evaluating the expression (12851 - 593) * 301 + 76 is 3689734.\n", "\n", "==================================================\n", "User Message: What is 15910385 divided by 193053?\n", "==================================================\n", "\n", "Initial Response:\n", "Stop Reason: tool_use\n", "Content: [ContentBlock(text='<thinking>\\nThe calculator function is the appropriate tool to answer this request, since it can perform basic arithmetic operations like division.\\n\\nThe calculator function requires a single parameter:\\n- expression: The mathematical expression to evaluate\\n\\nIn this case, the user has provided the full expression to evaluate (15910385 divided by 193053). Since all the required information has been provided, we can proceed with calling the calculator function.\\n</thinking>', type='text'), ContentBlockToolUse(id='toolu_01BfnN4LKp7oPRgmRzWeYdBG', input={'expression': '15910385 / 193053'}, name='calculator', type='tool_use')]\n", "\n", "Tool Used: calculator\n", "Tool Input: {'expression': '15910385 / 193053'}\n", "Tool Result: 82.41459599177428\n", "[ContentBlock(text='So 15910385 divided by 193053 equals 82.41459599177428.', type='text')]\n", "\n", "Final Response: So 15910385 divided by 193053 equals 82.41459599177428.\n" ] }, { "data": { "text/plain": [ "'So 15910385 divided by 193053 equals 82.41459599177428.'" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "chat_with_claude(\"What is the result of 1,984,135 * 9,343,116?\")\n", "chat_with_claude(\"Calculate (12851 - 593) * 301 + 76\")\n", "chat_with_claude(\"What is 15910385 divided by 193053?\")" ] } ], "metadata": { "kernelspec": { "display_name": "Anthropic Tools SDK", "language": "python", "name": "ant-tools-sdk" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.8" } }, "nbformat": 4, "nbformat_minor": 2 }