一、背景

一直迷惑agent怎么实现tools的调用,可能我的prompt不对,问千问、豆包,回复都很抽象,感觉自己知道了,好像又不知道。下面以程序员的角度,以实例分析一下tools的调用过程

二、实现逻辑

  1. 开发者(Agent)请求中向 LLM 声明有哪些工具可用。
  2. LLM 在响应中通过特定的结构化格式 表达它想要调用哪个工具。
  3. 开发者(Agent)调用相应的工具,并将工具反思的结果拼到LLM请求的上下文中,再次请求LLM

三、实例说明

  1. 请求LLM,并在参数告之agent有哪些工具,注意下面的tools参数
{
    "model": "qwen-plus",
    "stream": true,
    "messages": [
        {
            "role": "user",
            "content": "今天的天气怎么样?我想出去露营,需要准备什么"
        }
    ],
    "tools": [
        {
            "type": "function",
            "function": {
                "name": "get_current_weather",
                "description": "获取指定城市的当前天气",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "城市名称"
                        }
                    },
                    "required": [
                        "location"
                    ]
                }
            }
        }
    ]
}

2. LLM返回,"finish_reason": "tool_calls"。告之agent,当前交互需要调用工具。如下所示,截取LLM返回的2个chunk。一个chunk提取了调用工具要输入的参数;另一个chunk,告之当前LLM请求结束,结束原因是需要调用工具

{
    "id": "chatcmpl-7ed551c3-8360-9710-b4c6-5191d3c4db2a",
    "object": "chat.completion.chunk",
    "created": 1785218854,
    "model": "qwen-plus",
    "choices": [
        {
            "delta": {
                "tool_calls": [
                    {
                        "function": {
                            "arguments": " \"北京\"}"
                        },
                        "index": 0,
                        "id": "",
                        "type": "function"
                    }
                ],
                "content": null
            },
            "index": 0,
            "finish_reason": null,
            "logprobs": null
        }
    ],
    "usage": null
}



{
    "id": "chatcmpl-7ed551c3-8360-9710-b4c6-5191d3c4db2a",
    "object": "chat.completion.chunk",
    "created": 1785218854,
    "model": "qwen-plus",
    "choices": [
        {
            "index": 0,
            "delta": {},
            "finish_reason": "tool_calls",
            "logprobs": null
        }
    ],
    "usage": null
}

3. agent调用工具,并将工具返回的结果拼接到LLM的请求参数中,如下所示(role:tool):

{
    "model": "qwen-plus",
    "stream": true,
    "messages": [
        {
            "role": "user",
            "content": "今天的天气怎么样?我想出去露营,需要准备什么"
        },
        {
            "role": "tool",
            "tool_call_id": "call_xyz789",
            "content": "{\"temp\": 32, \"humidity\": 75, \"condition\": \"雷阵雨\"}"
        }
    ],
    "tools": [
        {
            "type": "function",
            "function": {
                "name": "get_current_weather",
                "description": "获取指定城市的当前天气",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "城市名称"
                        }
                    },
                    "required": [
                        "location"
                    ]
                }
            }
        }
    ]
}

4. agent拼接上下文后(role:tool),再次请求LLM,LLM会返回请求的结果。这时结束标志是"finish_reason": "stop",而不是"finish_reason": "tool_calls"

{
    "id": "chatcmpl-99f1e847-e42e-91d2-acd9-a43ce3a014e3",
    "object": "chat.completion.chunk",
    "created": 1785223492,
    "model": "qwen-plus",
    "choices": [
        {
            "index": 0,
            "delta": {
                "content": null
            },
            "finish_reason": "stop",
            "logprobs": null
        }
    ],
    "usage": null
}

5. 注意,tools可能不是调一次,这就引入了ReAct。例如,你定义了一个递归的函数作为tool,然后让大模型调用函数,递归算结果。

四、推广

云小站_专享特惠_云产品推荐-阿里云

京东云

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐