.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "build_tutorial/tool.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_build_tutorial_tool.py: .. _tools: Tools ==================== Background -------------------- There are two ways to call tools in LLM-empowered multi-agent applications. .. image:: https://img.alicdn.com/imgextra/i3/O1CN01iizvjY1UjKCE3q5FR_!!6000000002553-0-tps-1830-792.jpg :align: center :alt: Two ways for tool calling :width: 80% - Prompt-based tool calling: Developers introduce tools in the prompt and extract tool calls from the LLM response. - API-based tool calling: Developers provide tools description in JSON schema format. The LLM API will directly return the tool calls in their specific format. AgentScope supports both ways. In this tutorial, we will introduce how to use the built-in tools and how to create custom tools. .. GENERATED FROM PYTHON SOURCE LINES 24-30 .. code-block:: Python import json import agentscope from agentscope.message import Msg from agentscope.models import DashScopeChatWrapper .. GENERATED FROM PYTHON SOURCE LINES 31-40 Using Built-in Tools -------------------------- AgentScope provides a `ServiceToolkit` module that supports to - parse tools into JSON schemas automatically - check arguments and call functions Before using `ServiceToolkit`, we can take a look at the available tools in the `agentscope.service` module. .. GENERATED FROM PYTHON SOURCE LINES 40-45 .. code-block:: Python from agentscope.service import get_help, ServiceResponse, ServiceExecStatus get_help() .. GENERATED FROM PYTHON SOURCE LINES 46-50 All above functions are implemented as Python functions. They can be registered to the `ServiceToolkit` by calling the `add` method. The `ServiceToolkit` will parse the tool functions into JSON schema automatically. .. GENERATED FROM PYTHON SOURCE LINES 50-57 .. code-block:: Python from agentscope.service import ServiceToolkit from agentscope.service import bing_search, execute_shell_command toolkit = ServiceToolkit() toolkit.add(execute_shell_command) .. GENERATED FROM PYTHON SOURCE LINES 58-62 Note some parameters of the tool functions (e.g. api_key) should be handled by developers. You can directly pass these parameters as keyword arguments in the add method as follows, the reserved parameters will be left to the agent to fill. .. GENERATED FROM PYTHON SOURCE LINES 62-68 .. code-block:: Python toolkit.add(bing_search, api_key="xxx") print("The tools instruction:") print(toolkit.tools_instruction) .. rst-class:: sphx-glr-script-out .. code-block:: none The tools instruction: ## Tool Functions: The following tool functions are available in the format of ``` {index}. {function name}: {function description} {argument1 name} ({argument type}): {argument description} {argument2 name} ({argument type}): {argument description} ... ``` 1. execute_shell_command: Execute given command and return the return code, standard output and error within , and tags. command (string): The shell command to execute. timeout (number): The maximum time (in seconds) allowed for the command to run. 2. bing_search: Search question in Bing Search API and return the searching results question (string): The search query string. num_results (integer): The number of search results to return. .. GENERATED FROM PYTHON SOURCE LINES 69-70 The built-in default calling format: .. GENERATED FROM PYTHON SOURCE LINES 70-73 .. code-block:: Python print(toolkit.tools_calling_format) .. rst-class:: sphx-glr-script-out .. code-block:: none [{"name": "{function name}", "arguments": {"{argument1 name}": xxx, "{argument2 name}": xxx}}] .. GENERATED FROM PYTHON SOURCE LINES 74-75 The JSON Schema description of the tool functions: .. GENERATED FROM PYTHON SOURCE LINES 75-78 .. code-block:: Python print(json.dumps(toolkit.json_schemas, indent=2)) .. rst-class:: sphx-glr-script-out .. code-block:: none { "execute_shell_command": { "type": "function", "function": { "name": "execute_shell_command", "parameters": { "properties": { "command": { "description": "The shell command to execute.", "type": "string" }, "timeout": { "default": 300, "description": "The maximum time (in seconds) allowed for the command to run.", "type": "number" } }, "required": [ "command" ], "type": "object" }, "description": "Execute given command and return the return code, standard output and\n\nerror within , and\n tags." } }, "bing_search": { "type": "function", "function": { "name": "bing_search", "parameters": { "properties": { "question": { "description": "The search query string.", "type": "string" }, "num_results": { "default": 10, "description": "The number of search results to return.", "type": "integer" } }, "required": [ "question" ], "type": "object" }, "description": "Search question in Bing Search API and return the searching results" } } } .. GENERATED FROM PYTHON SOURCE LINES 79-88 Prompt-based Tool Calling -------------------------- In prompt-based tool calling, developers need to - introduce the tools and call format in prompt - parse and extract the tool calls from the LLM response. You can use the parsers in :ref:`structured-output` section to parse the LLM response and extract the tool calls. The tool call format of `ServiceToolkit` is as follows: .. GENERATED FROM PYTHON SOURCE LINES 88-98 .. code-block:: Python from agentscope.message import ToolUseBlock tool_call = ToolUseBlock( type="tool_use", id="xxx", name="bing_search", input={"query": "AgentScope"}, ) .. GENERATED FROM PYTHON SOURCE LINES 99-108 After assembling the `ServiceToolkit`, you can integrate it into agent. In AgentScope, we provide a `ReActAgent` to handle the tool usage, you can directly pass the `ServiceToolkit` object into this agent. Refer to :ref:`builtin-agent` for implementation details of this agent. .. note:: `ReActAgent` constructs the prompt and parses the tools locally, rather than through the tools API provided by the model API. For using the tools API, please refer to :ref:`tools-api`. .. GENERATED FROM PYTHON SOURCE LINES 108-134 .. code-block:: Python from agentscope.agents import ReActAgent agentscope.init( model_configs={ "config_name": "my-qwen-max", "model_type": "dashscope_chat", "model_name": "qwen-max", }, ) agent = ReActAgent( name="Friday", model_config_name="my-qwen-max", service_toolkit=toolkit, sys_prompt="You're a helpful assistant named Friday.", ) msg_task = Msg( "user", "Help me to calculate 1615114134*4343434343", "user", ) res = agent(msg_task) .. rst-class:: sphx-glr-script-out .. code-block:: none system: Respond with specific tags as outlined below: {what you thought} {the function name you want to call} <{argument name}>{argument value} <{argument name}>{argument value} ... Friday: I need to calculate the multiplication of these two numbers. I can use the execute_shell_command function to perform this calculation in a shell. execute_shell_command echo $((1615114134*4343434343)) 60 system: 1. Execute function execute_shell_command [ARGUMENTS]: {"command": "echo $((1615114134*4343434343))", "timeout": 60} [RESULT]: 0 7015142197480303962 system: Respond with specific tags as outlined below: {what you thought} {the function name you want to call} <{argument name}>{argument value} <{argument name}>{argument value} ... Friday: The multiplication of 1615114134 and 4343434343 is 7015142197480303962. I can now provide the result to the user. finish The result of multiplying 1615114134 by 4343434343 is 7015142197480303962. system: 1. Execute function finish [ARGUMENTS]: {"response": "The result of multiplying 1615114134 by 4343434343 is 7015142197480303962."} [RESULT]: The result of multiplying 1615114134 by 4343434343 is 7015142197480303962. .. GENERATED FROM PYTHON SOURCE LINES 135-166 API-based Tool Calling -------------------------- In API-based tool calling, developers only need to prepare the tools description in JSON schema format. However, different APIs differ in - the format of the tool description, and - how to construct the prompt with tool calls and execution results. .. image:: https://img.alicdn.com/imgextra/i4/O1CN01HIHrnw21LrDxzrB4a_!!6000000006969-0-tps-1920-1080.jpg :align: center :alt: API-based tool calling :width: 100% The above figure takes OpenAI as an example to show how API-based tool calling works in AgentScope. We block API-specific requirements by `agentscope.formatter` and `ModelResponse` modules. All developers need to know is 1. `ServiceToolkit` will parse the tool functions into standard JSON schema automatically 2. `Formatter` class will transform the JSON schemas and messages into the required format 3. The tool calls are all unified into the same format (`ToolUseBlock`) within `ModelResponse` .. tip:: A new agent class `ReActAgentV2` is added for API-based tools calling! .. note:: Currently, only the `format_chat` method supports tools API. The `format_multi_agent` method will be supported in the future. .. note:: API-based tool calling does not support streaming return yet, and the related functionality is under development. Here we take DashScope as an example to show how to use the tools API. .. GENERATED FROM PYTHON SOURCE LINES 166-175 .. code-block:: Python from agentscope.formatters import DashScopeFormatter from agentscope.message import TextBlock, ToolUseBlock, ToolResultBlock model = DashScopeChatWrapper( config_name="_", model_name="qwen-max", ) .. GENERATED FROM PYTHON SOURCE LINES 176-177 Step 3 -> 4 in the figure, formating messages and JSON schemas: .. GENERATED FROM PYTHON SOURCE LINES 177-187 .. code-block:: Python msgs = [ Msg("user", "Help me to execute shell cmd 'whoami'", "user"), ] formatted_msgs = DashScopeFormatter.format_chat(msgs) formatted_schemas = DashScopeFormatter.format_tools_json_schemas( toolkit.json_schemas, ) print(json.dumps(formatted_msgs, indent=4, ensure_ascii=False)) .. rst-class:: sphx-glr-script-out .. code-block:: none [ { "role": "user", "content": [ { "text": "Help me to execute shell cmd 'whoami'" } ] } ] .. GENERATED FROM PYTHON SOURCE LINES 188-189 Step 5 -> 6 -> 7 in the figure, getting the model response: .. GENERATED FROM PYTHON SOURCE LINES 189-193 .. code-block:: Python response = model(formatted_msgs, tools=formatted_schemas) print("tool_calls:", json.dumps(response.tool_calls, indent=4)) .. rst-class:: sphx-glr-script-out .. code-block:: none tool_calls: [ { "type": "tool_use", "id": "call_a4c4492458664f009614de", "name": "execute_shell_command", "input": { "command": "whoami", "timeout": 300 } } ] .. GENERATED FROM PYTHON SOURCE LINES 194-195 Step 8, creating a new message with the tool calls: .. GENERATED FROM PYTHON SOURCE LINES 195-210 .. code-block:: Python # Create a new msg with the tool calls content = [] if response.text: content.append(TextBlock(type="text", text=response.text)) if response.tool_calls: content.extend(response.tool_calls) msgs.append(Msg("assistant", content, "assistant", echo=True)) # execute the tool calls msg_execution = toolkit.parse_and_call_func( response.tool_calls, tools_api_mode=True, # Must be ture for tools API ) .. rst-class:: sphx-glr-script-out .. code-block:: none assistant: [ { "type": "tool_use", "id": "call_a4c4492458664f009614de", "name": "execute_shell_command", "input": { "command": "whoami", "timeout": 300 } } ] .. GENERATED FROM PYTHON SOURCE LINES 211-212 Step 9, adding the execution results to the message list: .. GENERATED FROM PYTHON SOURCE LINES 212-215 .. code-block:: Python msgs.append(msg_execution) .. GENERATED FROM PYTHON SOURCE LINES 216-218 Now, let's try to format the new message list with tool calls and result again! .. GENERATED FROM PYTHON SOURCE LINES 218-223 .. code-block:: Python formatted_msgs = DashScopeFormatter.format_chat(msgs) print(json.dumps(formatted_msgs, indent=4, ensure_ascii=False)) .. rst-class:: sphx-glr-script-out .. code-block:: none [ { "role": "user", "content": [ { "text": "Help me to execute shell cmd 'whoami'" } ] }, { "role": "assistant", "content": null, "tool_calls": [ { "id": "call_a4c4492458664f009614de", "type": "function", "function": { "name": "execute_shell_command", "arguments": "{\"command\": \"whoami\", \"timeout\": 300}" } } ] }, { "role": "tool", "tool_call_id": "call_a4c4492458664f009614de", "content": "0\nrunner\n\n", "name": "execute_shell_command" } ] .. GENERATED FROM PYTHON SOURCE LINES 224-228 Up to now, we have already finished the API-based tool calling process. The whole process refers to the implementation of `agentscope.agents.ReActAgentV2` class. You can also directly use this agent. .. GENERATED FROM PYTHON SOURCE LINES 230-237 Using MCP with ServiceToolkit ------------------------------- AgentScope provides support for integrating MCP (Model Context Protocol) servers, enabling enhanced capabilities for models and tools. You can add MCP servers to the `ServiceToolkit` using the `add_mcp_servers` method, where you specify the configurations for each server. Please note that MCP requires Python version >= 3.10. .. GENERATED FROM PYTHON SOURCE LINES 237-247 .. code-block:: Python configs = { "mcpServers": { "puppeteer": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-puppeteer"], }, }, } .. GENERATED FROM PYTHON SOURCE LINES 248-261 Add MCP server configurations to the ServiceToolkit `toolkit.add_mcp_servers(server_configs=configs)` Creating Custom Tools -------------------------- A custom tool function must follow these rules: - Typing for arguments - Well-written docstring in Google style - The return of the function must be wrapped by `ServiceResponse` After calling the `toolkit.add` function, the tool function will be parsed automatically and registered to the `ServiceToolkit`. .. GENERATED FROM PYTHON SOURCE LINES 261-276 .. code-block:: Python def new_function(arg1: str, arg2: int) -> ServiceResponse: """A brief introduction of this function in one line. Args: arg1 (`str`): Brief description of arg1 arg2 (`int`): Brief description of arg2 """ return ServiceResponse( status=ServiceExecStatus.SUCCESS, content="Done!", ) .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 9.298 seconds) .. _sphx_glr_download_build_tutorial_tool.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: tool.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: tool.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: tool.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_