Function Calling与工具调用:让模型从回答走向执行

Function Calling 与工具调用:把大模型接入真实系统的关键接口

大模型默认只能生成文本。它可以告诉你"应该查询天气""可以计算价格""建议筛选候选人",但它不能自己访问数据库、调用 API、执行计算或完成订单操作。Function Calling 的意义,就是在模型和外部系统之间建立一个结构化接口:模型负责判断意图和生成调用参数,程序负责执行真实工具并返回结果。

这一步是大模型应用从"内容生成"走向"业务执行"的关键。

1. 工具调用不是让模型直接执行代码

Function Calling 容易被误解成"模型调用函数"。更准确地说,模型只输出调用意图:

json 复制代码
{
  "name": "query_weather",
  "arguments": {
    "city": "北京",
    "date": "2026-07-24"
  }
}

真正执行函数的是应用程序。这个边界非常重要:

  • 模型负责理解自然语言。
  • 程序负责校验参数。
  • 程序负责权限控制。
  • 程序负责调用工具。
  • 程序负责处理工具异常。

模型不应该拥有任意执行能力。它只能在被允许的工具集合中提出请求。

2. 工具 Schema 是模型理解工具的依据

模型能否用对工具,主要取决于工具描述。一个工具至少需要:

  • 名称:稳定、清晰、可区分。
  • 描述:说明何时使用。
  • 参数:名称、类型、含义、必填项。
  • 返回值语义:结果表示什么。

例如计算工具:

json 复制代码
{
  "type": "function",
  "function": {
    "name": "multiply",
    "description": "计算两个整数的乘积",
    "parameters": {
      "type": "object",
      "properties": {
        "a": {"type": "integer", "description": "第一个整数"},
        "b": {"type": "integer", "description": "第二个整数"}
      },
      "required": ["a", "b"]
    }
  }
}

工具描述不能太泛。如果两个工具都写成"查询信息",模型很难选择。描述应突出适用场景和限制条件。

3. 手写 Schema、装饰器与 Pydantic 的取舍

定义工具有几种方式。

手写 JSON Schema 控制力最强,适合复杂参数和跨语言接口。缺点是冗长,字段容易和真实函数签名不一致。

装饰器方式更简洁。框架可以根据函数签名和 docstring 生成工具描述:

python 复制代码
@tool
def add(a: int, b: int) -> int:
    """将两个整数相加"""
    return a + b

Pydantic 适合参数复杂、需要校验和默认值的场景:

python 复制代码
class QueryArgs(BaseModel):
    city: str
    date: str

实际项目中可以混用:简单工具用装饰器,复杂工具用 Pydantic,跨服务工具用显式 Schema。

4. 两轮调用是 Function Calling 的基本闭环

工具调用通常不是一次模型请求完成的。基本流程是:

text 复制代码
用户输入
  -> 模型返回 tool_calls
  -> 程序执行工具
  -> 工具结果作为 tool message 回填
  -> 模型生成最终回答

如果漏掉"工具结果回填"这一步,模型只能输出调用请求,无法基于真实执行结果回答。

消息序列大致是:

text 复制代码
user: 查询北京天气
assistant: 调用 query_weather(city=北京)
tool: {"temp": "...", "condition": "..."}
assistant: 北京今天...

这个过程让模型回答建立在外部工具结果上,而不是凭空猜测。

5. 多步工具调用需要执行循环

简单问题只需要一个工具。复杂任务可能需要多个工具按顺序执行。例如:

text 复制代码
先查询可用车次 -> 再查询余票 -> 再确认订单 -> 再写入订单

这种场景需要一个执行循环:

text 复制代码
模型决策 -> 工具执行 -> 观察结果 -> 模型再决策 -> 直到完成

执行循环必须设置边界:

  • 最大迭代次数。
  • 每轮最多调用的工具数量。
  • 工具失败后的重试策略。
  • 何时向用户追问。
  • 何时终止任务。

否则模型可能因为信息不足或工具失败不断循环。

6. 参数校验是工具调用的安全阀

模型生成的参数不能直接信任。常见问题包括:

  • 字段缺失。
  • 类型错误。
  • 日期格式不统一。
  • 枚举值非法。
  • 参数多余。
  • 模型自己补造参数。

工具执行前应进行校验:

text 复制代码
模型参数 -> 类型校验 -> 业务校验 -> 权限校验 -> 执行工具

类型校验解决"格式对不对",业务校验解决"值是否合理",权限校验解决"用户是否允许这么做"。

例如查询类工具可以允许模型自动调用;写入、删除、下单、发送通知等工具通常需要更严格确认。

7. 工具返回结果也要设计

工具返回给模型的内容不应是随意字符串。更好的方式是返回结构化结果:

json 复制代码
{
  "status": "success",
  "data": [...],
  "message": ""
}

或在失败时返回:

json 复制代码
{
  "status": "input_required",
  "message": "请提供具体日期"
}

统一返回格式能让模型和程序更容易判断下一步。工具返回如果过长,应先压缩或摘要,否则会挤占上下文窗口。

8. 工具权限与风险分级

工具可以按风险分级:

  • 低风险读操作:查询天气、检索文档、计算。
  • 中风险读操作:查询个人资料、内部数据。
  • 高风险写操作:下单、删除、发送邮件、更新数据库。

不同风险应有不同策略:

  • 低风险可自动执行。
  • 中风险需要权限过滤和日志。
  • 高风险需要用户确认或人工审批。

不要把所有安全要求都写进 Prompt。Prompt 可以提醒模型谨慎,但真正的权限边界必须在代码和系统配置中实现。

9. 工具调用的可观测性

工具调用链路应记录:

  • 模型选择了哪个工具。
  • 生成了哪些参数。
  • 参数校验是否通过。
  • 工具执行耗时。
  • 工具返回状态。
  • 是否触发重试。
  • 最终回答是否引用了工具结果。

当用户说"结果不对"时,日志能帮助判断是模型选错工具、参数抽错、工具返回错,还是最终总结错。

10. 小结

Function Calling 的本质是把自然语言理解转成可执行接口:

text 复制代码
自然语言 -> 工具意图 -> 参数结构 -> 程序执行 -> 结果回填 -> 最终回答

高质量工具调用系统的关键不是"让模型能调函数",而是设计清楚工具 Schema、参数校验、权限边界、返回协议和执行循环。只有这样,大模型才能可靠地接入真实业务系统。

相关推荐
道影子1 小时前
阴阳引力多维基元:超越二进制的计算革命
人工智能·深度学习·微服务·云原生·架构
hold?fish:palm1 小时前
11 滑动窗口最大值
数据结构·算法
zhoupenghui1681 小时前
大模型核心技术ReAct和Agentic RAG讲解
人工智能·ai·大模型·react·rag·动态推理·agentic rag
xvhao20131 小时前
T750414 【游戏】计算24点 题解
数据结构·c++·算法·游戏
学习中.........1 小时前
从 Karpathy 手写 BPE 到 CS336 `train_bpe` 作业实现
人工智能·机器学习·语言模型·自然语言处理
无忧智库1 小时前
产业数字化平台建设方案:从单点工厂改造到城市产业生态的全景落地指南(PPT)
大数据·人工智能
草莓熊Lotso1 小时前
【LangChain】核心组件详解:文档加载器(Document Loaders)
开发语言·c++·python·langchain·软件工程
wuhanzhanhui1 小时前
轻盈的力量:2026 武汉国际发泡材料技术工业展览会,重构未来工业的“呼吸感”
大数据·人工智能