03. Tool Calling / Function Calling 的执行流程是什么?
整理 Tool Calling 的执行链路、关键约束与常见工程陷阱。
简单回答
Tool Calling(也叫 Function Calling)是让 LLM 以结构化方式调用外部工具的机制。执行流程大致是:开发者在请求中定义可用工具的 schema(名称、参数、描述),LLM 根据用户输入判断是否需要调工具并生成结构化的调用参数(JSON),开发者的代码执行实际工具调用,将结果返回给 LLM,LLM 基于结果生成最终回答。关键点在于 LLM 本身不执行工具——它只负责决定"调什么工具、传什么参数",实际执行在应用层。
详细解释
为什么需要 Tool Calling
LLM 的能力边界很清晰——它能生成文本但不能执行操作。它不能真的去查数据库、不能调 API、不能发邮件、不能算精确数值。Tool Calling 的本质是给 LLM 装上"手"——让它可以通过调用外部工具来完成自身能力范围之外的任务。
在 Tool Calling 出现之前,开发者通常让 LLM 以自由文本形式输出要调用的工具和参数,然后用正则表达式或字符串解析来提取。这种方式非常脆弱——LLM 的输出格式可能不一致,解析经常失败。Tool Calling 把这个过程标准化了:LLM 直接输出结构化的 JSON,API 层面保证格式正确。
完整的执行流程
以 OpenAI 的 Function Calling 为例,一次完整的流程是这样的:
第一步,开发者在 API 请求中定义 tools。每个 tool 有 name、description、parameters(JSON Schema 格式),描述这个工具是干什么的、接受什么参数。比如定义一个天气查询工具:
第二步,LLM 收到用户消息和可用工具列表后,判断是否需要调用工具。如果需要,它不直接生成文本回答,而是输出一个 tool_call 结构,包含要调用的函数名和参数:
第三步,开发者的代码接收到这个 tool_call,解析参数,在应用层执行真正的工具调用(比如调天气 API)。拿到结果后,把结果以 tool message 的形式放回对话历史:
第四步,把包含工具结果的对话历史再发给 LLM,LLM 基于工具返回的结果生成最终的自然语言回答:"北京现在天气晴,气温 22°C。"
整个过程中 LLM 做了两次调用——第一次决定调什么工具、传什么参数,第二次基于工具结果生成回答。这是最基本的一轮 Tool Calling。如果任务复杂,LLM 可能连续做多轮 Tool Calling,或者一次请求中同时调用多个工具(Parallel Tool Calling)。
Tool Description 的重要性
Tool Calling 的效果非常依赖工具描述的质量。LLM 是基于 tool 的 name 和 description 来判断要不要调、什么时候调的。如果描述写得含糊("处理数据"),LLM 不知道什么时候该用它。如果描述太泛,LLM 可能在不该用的时候也用了。好的描述应该清晰说明工具的功能、适用场景、输入输出的含义和约束。
参数的 description 也很重要。比如 "city" 这个参数,如果不加描述,LLM 可能传入英文城市名、中文城市名、甚至国家名,导致 API 调用失败。加上"中文城市名称,如'北京'、'上海'"这样的描述,LLM 传参会准确得多。
和 MCP 的关系
MCP(Model Context Protocol)是 Anthropic 提出的标准化协议,目标是统一 LLM 和外部工具/数据源的连接方式。可以理解为 Function Calling 的"标准化和生态化"——Function Calling 定义了 LLM 怎么调工具,MCP 定义了工具怎么注册、发现、连接,让 LLM 可以"即插即用"地接入各种工具服务。两者是互补关系,MCP 用 Function Calling 作为底层交互机制。
常见的工程陷阱
LLM 生成的参数可能不符合预期。虽然 API 层面保证了 JSON 格式,但参数值可能不合理(比如城市名拼错、数值超出范围)。工程上需要在执行工具调用之前做参数校验。
工具调用可能失败。网络错误、API 限流、参数错误等都可能导致工具执行失败。需要有重试机制和错误处理——把错误信息返回给 LLM,让它决定是换个参数重试还是用其他方式回答。
Token 消耗。工具的 schema 定义会被放进 system prompt 消耗 token。如果定义了几十个工具,光工具描述就可能占几千 token。需要根据场景做工具筛选——不是所有工具都需要每次请求都带上。
面试时可以这样答
Tool Calling 的流程分四步。开发者先定义好可用工具的 schema,包括名称、描述和参数定义。LLM 收到用户消息后判断是否需要调工具,如果需要就输出结构化的调用参数——比如调哪个函数、传什么参数。然后由应用层代码执行实际的工具调用,把结果返回给 LLM。最后 LLM 基于工具结果生成最终的自然语言回答。
关键要理解的是 LLM 本身不执行工具,它只负责决策——"调什么、传什么"。实际执行在应用层,这也是安全控制的切入点。
工程上有几个容易踩的坑。工具描述的质量直接影响 LLM 的调用决策,描述不清楚会导致误调或漏调。参数值可能不合理需要校验。工具执行可能失败需要有重试和兜底。还有就是工具 schema 会消耗 token,工具太多的话需要做动态筛选。
常见追问
- 如果 LLM 生成了错误的工具调用参数怎么处理?
- Parallel Tool Calling 什么时候有用?有什么限制?
- Tool Calling 和 Prompt 中手动定义工具指令有什么区别?