工具使用与函数调用


文档摘要

工具使用与函数调用 本节摘要:Toolformer(Schick 等人, 2023)开启了自监督的工具标注:让模型自己给预训练语料标注候选 API 调用,只在「调用结果能降低下一个 token 损失」时保留标注。Berkeley 函数调用排行榜 V4(Patil 等人, 2025)则划下了 2026 年的评估标准:40% 智能体式、30% 多轮、10% 实时、10% 非实时、10% 幻觉检测。结论是——单轮函数调用已基本解决,但记忆、动态决策、长程工具链还没。本节是 Agent 工程 P0 的收官:讲透工具调用的训练信号(为什么自监督管用)、2026 年的评估靶子(BFCL V4 五类)、工程上的工具注册表(模式校验、参数强制、并行派发、沙箱),并诊断三个仍未解决的开放问题。

工具使用与函数调用

本节摘要:Toolformer(Schick 等人, 2023)开启了自监督的工具标注:让模型自己给预训练语料标注候选 API 调用,只在「调用结果能降低下一个 token 损失」时保留标注。Berkeley 函数调用排行榜 V4(Patil 等人, 2025)则划下了 2026 年的评估标准:40% 智能体式、30% 多轮、10% 实时、10% 非实时、10% 幻觉检测。结论是——单轮函数调用已基本解决,但记忆、动态决策、长程工具链还没。本节是 Agent 工程 P0 的收官:讲透工具调用的训练信号(为什么自监督管用)、2026 年的评估靶子(BFCL V4 五类)、工程上的工具注册表(模式校验、参数强制、并行派发、沙箱),并诊断三个仍未解决的开放问题。前五节的循环、规划、反思、搜索、精炼,最终都建立在这一节的基础上:Agent 如何安全、可靠地调用外部工具。

对应原课程:Phase 14 · Lesson 06 · tool-use-and-function-calling(原英文 phases/14-agent-engineering/06-tool-use-and-function-calling/docs/en.md)。

学习目标

阅读完本节,你应当能够:

  1. 解释 Toolformer 的自监督训练信号:只在执行后能降低下一个 token 损失时,才保留工具标注
  2. 说出 BFCL V4 的五个评估类别,以及每个类别测的是什么。
  3. 用标准库实现一个工具注册表:模式校验、参数强制、执行沙箱。
  4. 诊断 2026 年的三个开放问题:长程工具链、动态决策、记忆。

一、问题与直觉

早期的工具使用问的是:模型能不能预测出一个正确的函数调用? 现代的工具使用问的是:模型能不能跨 40 步链接工具,带着记忆,在部分可观察下,从工具失败中恢复,并且不幻觉出不存在的工具?

Toolformer 划下了基线:模型能用自监督学会何时调用工具。BFCL V4 定义了 2026 年的评估目标。两者之间的差距,正是生产 Agent 栖身的地带。

Toolformer(Schick 等人,NeurIPS 2023)

核心思想:让模型给自己的预训练语料标注候选 API 调用。对每个候选,执行它。只在「把工具结果包含进来能降低下一个 token 的损失」时,才保留这个标注。在过滤后的语料上微调。

覆盖的工具:计算器、问答系统、搜索引擎、翻译器、日历。自监督信号纯粹是「这个工具帮不帮得上预测文本」——没有人工标签

规模结果:工具使用在规模上涌现。小模型被工具标注拖累,大模型反而受益。这就是为什么 2026 年的前沿模型把强工具使用内置,而大多数 7B 模型需要显式的工具使用微调才可靠。

Berkeley 函数调用排行榜 V4(Patil 等人,ICML 2025)

BFCL 是 2026 年事实上的评估。V4 的构成:

  • 智能体式 Agentic(40%) —— 完整的 Agent 轨迹:记忆、多轮、动态决策。
  • 多轮 Multi-Turn(30%) —— 带工具链的交互式对话。
  • 实时 Live(10%) —— 用户提交的真实提示(更难的分布)。
  • 非实时 Non-Live(10%) —— 合成测试用例。
  • 幻觉 Hallucination(10%) —— 检测不该调工具的情况。

V3 引入了基于状态的评估:在一串工具调用之后,检查 API 的实际状态(比如「文件创建了吗?」),而不是去匹配工具调用的 AST。V4 加了网页搜索、记忆、格式敏感度类别。

💡 2026 年的关键发现:单轮函数调用已接近解决。失败集中在记忆(跨轮携带上下文)、动态决策(根据前序结果选工具)、长程链(20+ 步后漂移)、幻觉检测(没有合适工具时拒绝调用)。如果你在生产里遇到工具调用问题,大概率不在这四类之外。

工具模式

每个厂商都有自己的模式。细节有别,但形状相同:

name: string description: string(它做什么、何时该用) input_schema: JSON Schema(properties, required, types, enums)

Anthropic 直接用 input_schema。OpenAI 用 function.parameters。两者都接受 JSON Schema。描述是承重的——模型靠读描述来挑对工具。糟糕的工具描述是「选错工具」失败的头号根因。

参数校验

不要信任任何一次工具调用。校验:

  1. 类型强制(Type coercion) —— 模式说要 int,模型可能返回字符串 "5"。无歧义就强制,有歧义就拒。
  2. 枚举校验(Enum validation) —— 模式说 status in {"open", "closed"},模型吐了 "in_progress",带描述性错误拒掉。
  3. 必填字段(Required fields) —— 缺必填字段 → 立即回灌一条错误观察给模型,不是崩溃
  4. 格式校验(Format validation) —— 日期、邮箱、URL,用具体解析器校验,不要用正则

每一次校验失败,都应该返回一条结构化观察,让模型能用正确的形状重试。

并行工具调用

现代厂商支持在一个助手轮里发起并行工具调用。循环是:

  1. 模型发起 3 个工具调用,各有不同的 tool_use_id
  2. 运行时执行它们(如果相互独立就并行)。
  3. 每个结果作为 tool_result 块回灌,按 tool_use_id 关联。

工程铁律:把关联 ID 当作承重件。搞混了,就会得到「错误工具接到错误结果」的路由错误。

沙箱

工具执行就是沙箱边界(详见原课程第 09 节)。短版本:每个工具都该写明读写面、网络访问、超时、内存上限。通用的 run_shell(cmd) 是危险信号;具体的 git_status() 更安全。

⚠️ 设计警示:工具描述是「选错工具」的头号根因,关联 ID 错配是并行调用的头号根因,通用 shell 是安全的头号根因。这三件事,每一件都值得在代码评审里单列检查项。

二、从零实现

原课程 code/main.py 实现了一个生产形态的工具注册表:JSON Schema 子集校验(纯标准库);带描述、输入模式、超时、执行器的工具注册;参数强制与枚举校验;带关联 ID 的并行派发;结构化字符串的错误观察。

核心骨架如下,用伪代码展示。

Step 1:工具注册(带元信息)

class Tool: def __init__(self, name, description, input_schema, fn, timeout=10): self.name = name self.description = description # 承重:模型靠它选工具 self.input_schema = input_schema # JSON Schema 子集 self.fn = fn self.timeout = timeout REGISTRY = {} # name -> Tool def register(tool): REGISTRY[tool.name] = tool

Step 2:模式校验 + 参数强制

def validate_and_coerce(args, schema): for field, spec in schema["properties"].items(): if field not in args: if field in schema.get("required", []): return None, f"缺少必填字段:{field}" continue # 类型强制:字符串 "5" -> int 5(无歧义时) if spec["type"] == "integer" and isinstance(args[field], str) \ and args[field].isdigit(): args[field] = int(args[field]) # 枚举校验 if "enum" in spec and args[field] not in spec["enum"]: return None, f"{field} 取值非法,应为 {spec['enum']}" return args, None

Step 3:并行派发(带关联 ID)

def dispatch_parallel(tool_calls): results = {} for call in tool_calls: # 独立的可真并行 tool = REGISTRY.get(call["name"]) if tool is None: results[call["id"]] = f"错误:未知工具 {call['name']}" continue args, err = validate_and_coerce(call["args"], tool.input_schema) if err: results[call["id"]] = f"错误:{err}" # 结构化错误观察 continue results[call["id"]] = str(tool.fn(**args)) # 按 id 关联回灌 return results

运行 python3 code/main.py 会展示一个迷你 Agent 在一轮里调三个工具,其中一个故意格式错误的调用被拒,并回灌一条模型可据以行动的描述性错误。

💡 设计要点:校验失败的路径和执行成功的路径同等重要。一次格式错的调用不该崩溃整个 Agent——它应该回灌一条「错误:缺少必填字段 X」,让模型在下一轮用对的形状重试。这就是第 01 节说的「400 错误要变成观察字符串」在工具层的落点。

三、框架对比

每个厂商都有自己的工具模式——Anthropic、OpenAI、Gemini、Bedrock。如果你需要多厂商,用一层翻译层(OpenAI Agents SDK、Vercel AI SDK、LangChain 工具适配器)。BFCL 是参考基准——如果工具使用是你产品的核心,发布前拿它跑一遍你的 Agent。

厂商/框架 工具模式字段 备注
Anthropic input_schema(直接用 JSON Schema) 描述遵从度强,tool_use_id 强制
OpenAI function.parameters(JSON Schema) 支持并行调用,tool_call_id 关联
Gemini function_declarations 模式作为模型配置的一部分
OpenAI Agents SDK FunctionTool 类型 + Guardrails 自带翻译层,护栏可调工具(CRITIC 风格)
LangChain 工具适配器 统一的 BaseTool 屏蔽厂商模式差异

跨厂商的关键不变量是:name + description + JSON Schema 参数 + 关联 ID。只要这四样齐了,翻译层就能在不同厂商间搬运。

四、可复用产物

本节产出一份可复用技能(原课程 outputs/skill-tool-registry.md):

  • skill-tool-registry.md:给定一个任务领域,生成工具目录、模式、注册表。包含描述质量自检(每个工具的描述是否告诉模型何时该用它?是否写明了边界情况?),以及一份校验清单(类型强制是否过宽?枚举是否齐全?必填字段是否明确?沙箱边界是否写清?)。

Python 代码(code/main.py)是独立可运行的工具注册表,校验/强制/并行派发/错误观察四件套都是厂商无关的;把玩具执行器换成真实函数(并接上沙箱)即可投入生产。

五、练习

  1. (Easy) 加一个「空操作(no-op)」工具,让模型能显式拒绝使用其他任何工具。在一个 BFCL 式幻觉测试上测量。
  2. (Easy) 为「字符串里的 int」「字符串里的 float」实现参数强制。强制从哪里开始掩盖真实 bug?
  3. (Medium) 加一个按工具的超时和断路器(连续 3 次失败后,60 秒内拒绝该工具)。这怎么改变模型的恢复方式?
  4. (Hard) 读 BFCL V4 的描述。挑一个类别(比如「多轮」),让你的 Agent 跑 10 个示例提示,报告通过率。
  5. (Hard) 把标准库校验器移植到 Pydantic 或 Zod。Pydantic/Zod 抓住了哪些玩具漏掉的东西?

本节要点回顾

  1. Toolformer 的自监督信号:只在执行结果能降低下一个 token 损失时才保留工具标注,无需人工标签。
  2. 工具使用在规模上涌现:小模型被标注拖累,大模型受益;所以 2026 前沿模型内置强工具使用,7B 多需显式微调。
  3. BFCL V4 五类:40% 智能体式、30% 多轮、10% 实时、10% 非实时、10% 幻觉。
  4. V3 引入基于状态的评估:查 API 实际状态(「文件建了吗?」),而不是匹配工具调用的 AST。
  5. 2026 年单轮已近解决:失败集中在记忆、动态决策、长程链、幻觉检测。
  6. 工具模式四件套:name + description + JSON Schema 参数 + 关联 ID;跨厂商不变。
  7. 描述是承重的:糟糕的工具描述是「选错工具」的头号根因。
  8. 校验四类:类型强制、枚举校验、必填字段、格式校验(用解析器不用正则)。
  9. 关联 ID 是并行调用的承重件:搞混就是「错误工具接到错误结果」。
  10. 沙箱边界:每个工具写明读写面、网络、超时、内存;通用 run_shell 是危险信号。

至此,Agent 工程的 P0 核心路径——Agent 循环、计划执行、Reflexion、思维树与 LATS、自我精炼与 CRITIC、工具使用——已经串成一条完整的闭环:从「观察-思考-行动」的基础循环,到规划-执行的解耦,到零梯度的言语自我修正,到审慎搜索,到迭代精炼,最后落到工具调用的工程地基。后续 Agent 工程的进阶内容(记忆与虚拟上下文、技能库与终身学习、HTN 与进化规划、Anthropic 工作流模式、有状态图编排、Actor 模型、多智能体编排、Agent 可观测性、失败模式与防护、Agent 工作台工程等)留待后续批次汉化。


发布者: 作者: Rohit Gupta 转发
评论区 (0)
U