核心要点

  • 能讲清定义工具的三种方式:@tool 装饰器(最简,函数即工具)、StructuredTool.from_function(多参数/异步更灵活)、继承 BaseTool(需要复杂状态或自定义校验时)

  • 能说出工具三要素:名称、清晰的描述(给模型看,决定要不要调)、参数 schema(用类型注解或 Pydantic 定义,模型据此填参)

  • 能讲清绑定与调用闭环:model.bind_tools([...]) 把工具 schema 喂给支持 function calling 的模型,模型返回 tool_calls(要调哪个工具、什么参数)→ 本地执行 → 把结果作为 ToolMessage 回传 → 模型据此续答

  • 能点出准确率关键:工具描述和参数 schema 的质量直接决定模型选对工具、填对参数的概率,描述要写清「什么时候用、参数含义、返回什么」

标准回答

整体思路

让模型「会用工具」分两步:先把工具定义成模型能理解的 schema,再用 bind_tools 绑定,由模型决定何时调用、调用谁、传什么参数,框架负责执行并把结果回传。

第一步:定义工具

  • @tool 装饰器:最常用。给普通函数加 @tool,函数名作工具名,docstring 作描述,类型注解推断参数 schema。
  • StructuredTool.from_function:需要多参数、异步实现或更精细控制时用,可分别传同步/异步函数和显式 args_schema。
  • 继承 BaseTool:实现 _run/_arun,适合需要持有状态、做复杂参数校验或自定义错误处理的工具。

三种方式都要写清三要素:名称描述(给模型判断是否调用)、参数 schema(推荐用 Pydantic 模型,给每个字段加 description)。

第二步:绑定模型

llm_with_tools = model.bind_tools([tool_a, tool_b])

bind_tools 会把工具的 JSON schema 注入到对模型的请求里,模型本身需支持 function calling / tool use(如 GPT、Claude、通义等主流模型)。

第三步:执行调用闭环

  1. llm_with_tools.invoke(messages),若模型决定用工具,返回的 AIMessage 带 tool_calls(含工具名和结构化参数)。
  2. 遍历 tool_calls,按名字找到对应工具并用参数执行,得到结果。
  3. 把结果包成 ToolMessage(带对应 tool_call_id)追加到消息列表,再次 invoke 模型。
  4. 模型读取工具结果,生成最终自然语言回答;若需要可多轮循环(多次调用工具)。

工程要点

  • 用 Agent 或 LangGraph 时,这套「调用-执行-回传」循环由框架自动驱动,无需手写。
  • 描述与 schema 质量是命中率核心;并发场景注意一次返回多个 tool_calls;工具内部要做异常处理,把错误也作为可读结果回传给模型,便于其纠正重试。

常见误区

⚠️ 常见踩坑

以为 bind_tools 后模型会自动执行工具——它只产出 tool_calls,真正执行和回传结果要你(或 Agent/LangGraph 框架)来做;工具描述写得含糊或参数没加 description,模型就选错工具、填错参数;忽略 tool_call_id,回传 ToolMessage 时对不上号会出错;模型不支持 function calling 还硬绑会失效,应改用提示词 + OutputParser 方案;把未校验的模型入参直接执行高危操作(删库、转账)而不加白名单与人工确认,存在安全风险。

追问

追问 1Function Calling 和 ReAct 提示式工具调用有什么区别?该怎么选?

机制:Function Calling 由模型原生能力产出结构化 tool_calls(工具名 + JSON 参数),可靠性高、易解析;ReAct 靠提示词让模型按「Thought/Action/Observation」文本格式输出,再用解析器抠出动作和参数。

可靠性:原生 function calling 参数是结构化的,几乎不用担心格式解析失败;ReAct 依赖文本解析,模型一跑偏就解析出错。

选型:模型支持函数调用就优先用它(更稳、更省 token);只有面对不支持的模型,或想要显式展示推理过程时才用 ReAct。2026 的主流框架默认走原生函数调用。

追问 2怎么提高模型选对工具、填对参数的准确率?

写好描述:工具描述讲清「什么场景用、不该在什么场景用、返回什么」,让模型有明确的选择依据;相似工具要在描述里区分边界。

精确 schema:用 Pydantic 给每个参数加类型、description、枚举和默认值,约束模型填参空间;必填与可选要分清。

控制数量:单次绑定的工具别太多,过载会降低命中率,可按场景分组或先做一层路由。

容错回传:工具执行失败时把错误信息作为结果回传,模型能据此调整参数重试。

评测:用真实 query 集回归测试工具选择与参数正确率,针对错例迭代描述和 schema。

追问 3模型一次返回多个 tool_calls 要并行执行吗?怎么处理多轮工具调用?

并行:模型可能在一条 AIMessage 里返回多个相互独立的 tool_calls,这些可以并发执行以降延迟,但要保证每个结果用对应的 tool_call_id 包成 ToolMessage 回传,顺序无所谓、id 对得上即可。

有依赖时:若后一个调用依赖前一个结果,模型通常会分多轮逐步发起,不会一次全给,按轮次串行执行即可。

多轮循环:把「invoke→执行 tool_calls→回传 ToolMessage→再 invoke」做成循环,直到模型不再产出 tool_calls 给出最终答复;用 LangGraph/Agent 时该循环由框架管理,并应设最大轮数和超时,防止工具调用无限循环。

🔗 相似问题

同一考点的不同问法,面试官可能换着问,一起刷更稳

没找到想看的面试题?把你想看的告诉我们 →

延伸学习

按主题分类的相关资源,便于系统复习