LLM 是如何学会使用工具的

LLM工具使用方法的历史之旅。

LLM 是如何学会使用工具的
微信 ezpoda免费咨询:AI编程 | AI模型微调| AI私有化部署
AI模型价格对比 | AI工具导航 | ONNX模型库 | Tripo 3D | Meshy AI | ElevenLabs | KlingAI | ArtSpace | Phot.AI | InVideo

LLM为什么应该擅长函数调用,模型构建者使用了哪些技术?探究这个问题会发现令人惊讶地不满意的答案:许多模型论文根本没有提供任何细节,或者只提供了极少的线索。如果你自己也在寻找这个问题的答案,我希望这篇文章能为你提供一个起点。

在我之前的文章中,我探讨了工具使用——现在通常通过函数调用范式实现——如何成为LLM越来越重要的能力。在这里,我将更详细地描述函数调用在模型层的工作原理,将一系列方法的历史编织成一个松散的叙事。

纵观全局,一些基础趋势包括:

  1. LLM变得擅长自然语言任务
  2. 构建具有硬编码工具集的LLM
  3. LLM因语料库中代码和JSON等形式的不成比例存在而变得擅长这些格式
  4. LLM的指令微调
  5. 通过零样本提示测试LLM在任意工具上的表现
  6. 构建支持任意工具列表作为函数的LLM

把这些描述成“按顺序发生的技术演进”并不完全准确,但把它们看作完全并行、彼此独立发生的过程也不对。更合理的理解是:这些发展是一个松散排序且相互重叠的演进过程。

1、为工具定制LLM

LLM的核心是一个下一个token预测器。你可以将其视为一个具有明确定义输入和输出的函数:

  • 输入:一系列先前的token
  • 输出:下一个token的概率

当你在聊天界面或 API 中使用 LLM 时,它会在一个循环中不断调用函数并生成输出,同时把之前的输出追加回输入中。模型提供方通常会提供一长串参数,用来控制这个循环算法。这类自回归(autoregressive)LLM 最初的训练目标只是优化“下一个词预测”(例如 2019 年的 OpenAI GPT-2)。

一种将工具引入 LLM 的方法,是针对单个工具进行优化,比如计算器或维基百科查询。一个早期例子是 Giving BERT a Calculator: Finding Operations and Arguments with Reading Comprehension(2019) [1]。该方法使用了一个问答数据集,并由作者手动标注其中的数学操作工具调用。

再往后几年,另一个早期例子是 WebGPT: Browser-assisted question-answering with human feedback(2022) [2]。这里的思路是给 LLM 配备搜索引擎,让人类对语料库进行标注,在其中加入搜索引擎调用记录,然后再对模型进行微调(该方法由 OpenAI 的作者团队探索了多种实现方式)。

这里所谓的“人工标注”,本质上是指:在语料库的特定位置插入额外的文本信息,从而让数据中显式包含工具使用轨迹。

这些方法的一个主要缺点是:工具集合是有限的,而且定义这些工具本身也需要投入大量精力。另一个限制是,你必须提前知道正确的工具答案是什么;早期论文中计算器工具之所以如此流行,很可能也得益于一个现实优势——计算结果是非常容易验证的。

构建这些模型本身已经是一个相当繁重的工程工作,但这些为特定任务设计的能力,并不一定能够很好地泛化到更多工具,或者迁移到不同的基础模型上。

2、通用工具使用的基础

虽然早期 LLM 的开发重点是生成自然、逼真的语言输出(而且主要是英文),但后来人们逐渐意识到,这与模型在代码生成或其他任务上的能力并不冲突。LLM 在训练时使用了大规模互联网语料,其中本身就包含大量代码以及其他结构化输出。

因此,开发者开始有意识地将代码语料与通用互联网文本一起加入训练数据。引入更多样化的数据来源,不仅没有削弱语言能力,反而增强了模型的泛化能力。

理解代码语法是将“工具”表达为函数这一能力的重要基础。同时,LLM 在遵循指令方面也变得越来越强。模型构建者(例如 OpenAI)积累了大量对话数据,其中一部分还通过用户界面的点赞/点踩反馈进行标注。随后,他们开始引入“后训练(post-training)”阶段来更新模型。

其中一个关键论文是 OpenAI 的 Training language models to follow instructions with human feedback(2022) [4]。值得注意的是,这篇论文早于 ChatGPT,它依赖的是付费标注人员对 OpenAI API 查询结果的响应进行评估。

指令微调(instruction tuning)通常会带来一个副作用:降低下一词预测能力(这是自然的,因为优化目标不再完全以 next-token prediction 为核心)。但与此同时,它显著提升了模型的对话能力和指令遵循能力。

模型逐渐变得惊人地擅长生成类人文本,并在相关任务(例如代码生成)上也越来越强。这些模型的能力边界已经不再局限于“对话文本”。

GPT-3 改变了世界,只是大多数人直到 ChatGPT 出现才真正意识到这一点。它强大到让一些人开始思考一个问题:

如果我不做任何额外训练,也不告诉模型任何工具的细节,仅仅在 prompt 里用纯文本告诉它“我有一些工具”,它能不能自己学会用?

于是人们开始尝试这种方法。

一个典型例子是 Nat Friedman 分享的 natbot,它在 prompt 中直接定义了一些浏览器操作,例如:

“CLICK X —— 点击指定元素。你只能点击链接、按钮和输入框!”

这些规则完全是写在 prompt 里的,而没有使用像 WebGPT 那样的语料标注或专门训练。

随后,LangChain 很快基于这种“零样本工具使用(zero-shot tool use)”的方法构建了一个程序化接口。时间甚至可以追溯到 ChatGPT 发布当月的 0.0.19 版本。

总体来看,这种向零样本工具使用的转变,再次体现了所谓的“苦涩教训(bitter lesson)”:

“能够充分利用计算资源的通用方法,最终才是最有效的。”

在经历了多年人工标注和微调之后,人们开始发现:只需要一个更强的模型,再用文本清晰描述工具及其使用格式,就可能获得同样甚至更好的效果。

另一个这一时期的重要论文是 ReAct:Synergizing Reasoning and Acting in Language Models(2022) [6],它也是工具使用领域引用率非常高的工作之一。该方法为模型提供了一些基础工具,例如 Wikipedia 访问能力,并将“推理”和“行动”结合在一起。

ReAct 的核心洞见并不直接在于“工具使用方法本身”,而在于我们可以将推理(reasoning)与行动(acting)融合在一起,并结合指令微调(instruction tuning),从而形成一种高效的工具使用范式。

3、迈向函数调用

然后在某个关键时刻,OpenAI 直接彻底改变了整个范式。4

在他们关于 Function calling 和其他 API 更新的公告中提到:

开发者现在可以向 gpt-4-0613 和 gpt-3.5-turbo-0613 描述函数,模型会智能地选择输出一个 JSON 对象,其中包含用于调用这些函数的参数。这是一种将 GPT 能力与外部工具和 API 更可靠连接的新方式。

这些模型已经经过微调,不仅能够识别在什么情况下需要调用函数(取决于用户输入),还能够生成符合函数签名的 JSON 响应。函数调用机制使开发者可以更可靠地从模型中获得结构化输出。

与过去在 prompt 中用自然语言(English)描述工具不同,现在所有工具(从用户视角)都被统一为函数定义,并通过 API 参数显式传递,而不是嵌在对话文本里。模型也经过专门微调,以适应复杂函数定义的处理。

作为市场领导者,OpenAI 成功设定了新的行业范式,并让其他厂商不得不跟进,同时也建立了一个新的标准:通用工具使用能力将成为领先模型的基本能力之一

这件事也让“苦涩教训(bitter lesson)”的简单叙事变得更加复杂——我们既可以拥有强大的通用模型,也可以通过微调让它们具备工具使用能力。

但 OpenAI 是怎么做到这一点的呢?

答案是:我们并不知道。因为 OpenAI 现在不再公开太多模型细节。他们没有详细说明模型是如何被定制的,也没有解释工具调用是如何整合进提示与训练流程中的。

不过,我们可以通过一些论文和开源模型,去观察其他研究者是如何实现类似能力的。

4、一种可扩展的学习工具方法

我们来看看 ToolFormer:语言模型可以自我学习使用工具(2023),这是一篇非常有影响力的论文,它提出了一种无需人工标注、将工具调用应用到语料库中的方法框架 [7]。

这个方法大致如下:

  • 从一个初始模型和语料库开始
  • 让 LLM 选择问题,并在文本中插入工具调用
  • 执行这些工具调用
  • 通过“对后续文本预测能力的影响”来衡量工具调用是否有用
  • 只保留有帮助的工具调用
  • 用这个新构建的数据集进行微调

值得注意的是:类似思路在更早的 TALM:Tool Augmented Language Models(2022) 中已经出现过 [8]。

ToolFormer 的方法是通过提示(prompt)让 LLM 生成工具调用,每个工具对应一个独立 prompt(总共覆盖 5 种工具)。

图3(Schick 等,2023)

一个好的 prompt 和模型可以生成大量看起来合理的工具调用,但我们可以用更精细的方法来决定哪些应该保留在语料中。

他们计算一种加权交叉熵(weighted cross-entropy),用于比较三种情况对后续 token 预测的影响:a) 不使用 API 调用 b) 使用 API 调用但不提供返回结果 c) 使用 API 调用并附带返回结果,然后只保留那些“带来性能提升超过阈值”的样本。

将文本通过 prompt 生成工具调用,再经过执行与过滤后,最终用于微调的数据会变成类似这样的形式(当然实际论文中有颜色和框标注):

最终模型学会输出类似这样的字符串:

“[Calculator(400 / 1400)] ->”

在推理阶段(inference),系统检测到这种格式后会调用计算器,并把结果(例如 “0.29”)追加回文本中:

“[Calculator(400 / 1400)] -> 0.29”

然后模型继续生成后续内容,形成一个“调用工具 + 继续推理”的循环机制。

5、用户提供的函数

需要注意的是,ToolFormer 有一个很大的局限性:它只支持一个预先定义好的、小规模工具集合。我们需要一种能够泛化到“用户自定义工具”的方法,并且最好这些工具是以函数形式来定义的。NexusRaven:A Commercially-Permissive Model for Function Calling(2023) [9] 就描述了一种这样的思路。

该方法大致如下:

  • 从一个大规模代码语料库开始
  • 使用 LLM 为每个函数生成描述
  • 再用 LLM 生成自然语言查询,这些查询会使用这些函数,并且为每个使用场景生成一条 CoT(思维链)推理轨迹
  • 同时加入一组“相似函数候选列表”,迫使模型在多个候选函数中进行精细区分
  • 最后进行微调

这种方法与 ToolLLM:Facilitating Large Language Models to Master 16000+ Real-World APIs(2023) [10] 有相似之处,甚至引用了后者。
如果成功,这种方法可以让模型具备适配任意用户自定义函数的能力。

我们甚至可以在几年后的 The Llama 3 Herd of Models(2025) [11] 中看到这种方法的影响。虽然描述比较模糊,但其思路非常接近 NexusRaven:

“更准确地说,我们提取函数调用及其定义,对其进行清洗和过滤,例如移除缺失文档字符串或不可执行的函数,并使用 Llama 3 生成与函数调用对应的自然语言查询。”

当进入“用户提供工具”的阶段后,我们需要进一步讨论:这些工具到底是如何被传递给模型的。

在 ToolFormer 那种小规模固定工具集合的场景中,模型可以通过微调记住每一个工具。但在运行时动态指定工具的情况下,这种方式就不再可行。

需要注意的是:
像 OpenAI 或其他 API 提供方的接口结构,本身并不是“模型层如何表示工具”的答案。

记住,LLM 本质上处理的是一个token 序列

工具定义——连同用户输入、模型回复等——最终都会被“压平(flatten)”成一段统一的文本流。即使在 API 层做了结构化分离,在模型内部它仍然只是一个长文本序列。

虽然我们并不完全知道闭源模型 API 背后发生了什么,但从泄露的系统提示词或一些开源模型可以看到一些模式:常见做法是在 XML 结构中嵌套 JSON

下面是两个例子,一个来自闭源模型,一个来自开源模型:

Example Anthropic prompt (from leaked-system-prompts)
Hermes 3 (Nous Research) prompt (from Hermes-Function-Calling)

6、复杂任务的性能

到目前为止,我们讨论的方法要么只是把“工具使用”注入到一个原本不受工具调用影响的已有语料中,要么——除了 ToolLLM 之外——都是通过提示词生成单次工具调用

然而,在 agent(智能体)场景中,支持**多轮工具调用(multi-step tool use)**变得越来越重要。此外,即使是人类使用 LLM 的方式,也往往会在每次工具调用后进行调整和适应。

另外,大家都想在排行榜上占据领先位置,而函数调用领域最常用的评测榜单——Berkeley Function-Calling Leaderboard(BFCL)——非常强调多步调用能力。

在 BFCL 上表现很强的是 xLAM 2 系列模型。在发布时,它们是榜单上的领先者(在 BFCL v3 中,两款模型分别占据了前两名,整体准确率最高)[12]。

不过,它们在其他评测维度上表现并不突出(例如 agentic、memory、live scoring 等任务表现较差),但在**多轮推理(multi-turn reasoning)**方面表现非常优秀。

它们的方法核心是大规模数据增强(data augmentation)

  • 生成任务(tasks)
  • 生成完成任务所需的工具调用
  • 生成完整的(甚至完全“虚构”的)人机对话
  • 这些对话严格围绕任务展开

同时,他们还使用大量 LLM 进行验证,以提升数据质量。

目前来看,精心的数据收集与数据增强,可能是提升工具使用能力的最前沿方向。

如果看 BFCL 当前前 20 名榜单,除了 xLAM 2 系列之外,领先者大多来自主流大模型厂商(如 Anthropic、OpenAI 和 Google)。

但其中有一个模型特别突出:watt-tool-70B
它在多步工具调用任务上表现极强,在实时查询任务上甚至排名第三——而且这是一个由独立团队发布的单次模型。

更有意思的是,他们甚至没有发布配套论文来解释这个模型。

从 Hugging Face 上有限的说明来看,该模型强调:

  • 使用“专门设计的工具使用数据集与多轮对话数据”
  • 使用 CoT(思维链)技术合成高质量多轮对话数据

很难准确判断它的优势来自哪里,但值得注意的是,这个模型背后的公司本身就做一个基于聊天的 workflow 构建工具
也就是说,他们在这个领域是“有真实业务需求”的——必须让工具调用能力足够好。

这可能意味着他们拥有一个非常有价值的、内部的工具使用数据语料库,这在效果上可能形成了关键优势。

7、串联起来

函数调用是现代LLM的一项基本能力。它由包含大量代码示例的预训练数据集基础支持。其公式是:

  1. 从参考语料库中提取函数调用和函数定义
  2. 使用LLM生成这些函数调用有意义的自然语言查询
  3. 以结构化格式在提示中包含工具定义
  4. 按有用性过滤生成的工具调用
  5. 可选地包含来自产品的人工标注数据
  6. 包括推理步骤(以CoT、ReAct或更灵活的格式)
  7. 在语料库上进行微调

这段工具使用的历史充满了曲折,几种方法曾失去然后又重新获得 prominence。这些方法不是逐一添加到公式中的,而是在不同的组合中进行了测试。新的方法很可能会出现,再次改变一切。


原文链接: How LLMs are trained for function calling

汇智网翻译整理,转载请标明出处