Agent开发工具01

作者:技术拾光时间:2026-05-29 08:02:12浏览:479

大模型通过绑定工具获得外部资源操作能力。Langchain中使用`model.bindTools`绑定工具,定义工具需明确名称、描述及入参。调用时模型返回工具调用数组,依次执行工具函数,结果用`newToolMessage`包装后重新输入模型,得到最终回答。

## 大模型如何调用外部工具 大模型本身并不具备直接操作外部资源的能力,例如读取本地文件。要让模型完成这些操作,关键在于为其绑定工具。在 Langchain 中,这一过程非常简洁——使用 `model.bindTools` 即可完成绑定。接下来需要定义工具的具体实现。 ## 工具的绑定与定义 如果希望大模型不仅能回答用户问题,还能读取本地文件,就需要给它绑定相应的工具。在 Langchain 中,绑定方式很简单,直接使用 `model.bindTools`。 工具本质上是一个函数,必须接收参数(即入参)。定义工具时需要明确三要素:**名称**、**描述**、**入参**。 ```javascript const obj = { name: 'read_file', // 工具名称 description: '对这个工具的人类语言描述', // 工具描述 schema: z.object({ filePath: z.string().describe('要读取的文件路径'), }), } ``` 定义好入参说明后,接着实现工具函数本身。逻辑很简单:传入文件路径,读取内容并返回。 ```javascript const fun = async ({ filePath }) => { const content = await fs.readFile(filePath, 'utf-8'); console.log(` [工具调用] read_file("${filePath}") - 成功读取${content.length}字节`); return `文件内容:\n${content}`; } ``` 最后,使用 Langchain 的 `tool` 函数将上述参数传入,工具即定义完成。 ```javascript tool(fun, obj) ``` ## 工具的调用流程 绑定工具后,调用模型的 `invoke` 函数时,模型并不会直接执行工具,而是根据用户问题判断是否需要调用工具,并返回可使用的工具列表。 - 用户问“你好”:模型返回一个空数组,表示当前请求无需调用任何工具。 - 用户问“读取某个文件”:大模型会检索自身绑定的工具,如果存在匹配的工具,则在返回数据中携带可用工具。 返回的工具数组包含每个工具的实际入参(由模型根据用户提问识别)、唯一 ID(每次调用随机生成)以及工具名称。 当模型返回工具调用数组后,需要遍历该数组,依次调用每个工具函数。注意,调用工具时使用的是工具的 `invoke` 方法,而非模型的 `invoke`。 ```javascript const result = await tool.invoke(toolCall.args); ``` 获取工具结果后,使用 Langchain 的 `new ToolMessage` 创建一条消息: ```javascript new ToolMessage({ content: toolResults[index], tool_call_id: toolCall.id, }) ``` 最后,将所有消息再次发送给模型,模型输出最终回答。 ### 常见问题解答 **Q1:为什么需要 `new ToolMessage`,而不是直接将工具返回结果拼接到用户提问后面?** **A1:** 1. **模型训练格式要求**:像 GPT-4、Claude 等支持 function calling 的模型,在训练时大量接触的对话格式为: ``` User → Assistant(tool_calls) → ToolMessage → Assistant(回复) ``` 模型学到的是:收到带有 `tool_call_id` 的 ToolMessage,表示这是刚才调用的工具返回的结果,需要用这些内容来作答。若使用字符串拼接,将工具结果塞入 HumanMessage 或普通文本,这种格式在训练数据中较为少见,模型缺乏明确的处理经验。 2. **角色与用途清晰**:结构化消息中,每条消息的语义非常明确: | 消息类型 | 模型的理解 | | --- | --- | | HumanMessage | 用户说了什么、想做什么 | | AIMessage + tool_calls | 我决定调用这些工具 | | ToolMessage | 这些工具返回的结果,是我上一轮决策的反馈 | | AIMessage | 基于工具结果给出最终回答 | 模型会将 ToolMessage 视为“我主动调用的工具的结果”,而非用户新输入的信息。若使用字符串拼接,工具结果容易被当作普通上下文或用户输入,导致模型无法准确区分。 3. **注意力与因果关系**:在多轮对话中,模型对不同消息类型的处理权重不同。ToolMessage 在训练中被视为对上一次 tool_calls 的回应,因此模型会更自然地将注意力集中在:用这些结果回答用户最初的问题。