Function Calling 原理与实践

2026-05-26LLMTool UseFunction Calling

什么是 Function Calling

Function Calling(工具调用)是 LLM 选择调用外部函数的机制。模型不直接执行函数,而是输出一个结构化的调用请求,由应用层执行并将结果返回给模型继续推理。

底层机制

用户: "北京的天气怎么样?"

系统隐藏过程:
1. 应用层将工具定义(JSON Schema)注入到 LLM 请求中
2. LLM 判断需要调用 get_weather 工具
3. LLM 返回: {"name": "get_weather", "arguments": {"city": "北京"}}
4. 应用层执行 get_weather("北京") → {"temp": 28, "condition": "晴"}
5. 应用层将结果作为新的 tool_result 消息传回 LLM
6. LLM 生成最终回答: "北京今天 28°C,晴"

工具定义(JSON Schema)

{
  "type": "function",
  "function": {
    "name": "get_weather",
    "description": "查询指定城市的实时天气",
    "parameters": {
      "type": "object",
      "properties": {
        "city": {"type": "string", "description": "城市名,如北京"},
        "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
      },
      "required": ["city"]
    }
  }
}

并行调用(Parallel Tool Calls)

OpenAI 和 Claude 等模型支持单次 Response 返回多个工具调用,用唯一 ID 匹配结果:

LLM 返回:
- tool_call_1: get_weather("北京")
- tool_call_2: get_weather("上海")
- tool_call_3: get_weather("广州")

应用层并行执行 3 个函数,结果按 ID 分别传回

注意:并行调用的工具间不应有依赖关系。有依赖的调用需用 ReAct 循环分步执行。

常见问题

参数幻觉

模型可能编造不存在的参数名或非法值。解决:严格定义 JSON Schema,使用枚举约束,在应用层做参数校验。

循环陷阱

Agent 可能陷入 Thought→Action→Observation→Thought 的死循环。设定最大工具调用轮数(如 5-10 次)作为安全网。

错误恢复

工具调用可能失败(网络超时、参数错误)。设计错误处理链:重试 → 降级 → 告知用户。

工具描述的最佳实践

  • description 用清晰的自然语言描述工具的用途和边界
  • 参数描述中说明值的格式和约束("日期格式:YYYY-MM-DD")
  • 相近的工具给出区分说明,减少模型选错
  • 使用 `required` 明确标记必需参数
未标记