大语言模型技术指南:Function Calling、Tool Use、Agent 框架的工作机制与参数要点

大语言模型技术指南:Function Calling、Tool Use、Agent 框架的工作机制与参数要点

前一篇我们把大模型生产服务拆成了更工程化的几个层面:

  • 高并发如何扛住
  • 监控指标应该盯什么
  • 限流什么时候必须做
  • 故障恢复怎么避免整片服务被拖死

但当底层推理服务逐渐稳定之后,上层应用很快会进入另一个阶段:

单纯"会聊天"的模型已经不够了,系统开始要求模型去调用工具、访问外部信息、分解任务、执行多步流程。

这时候,很多团队会同时碰到一批新问题:

  • Function Calling 和 Tool Use 到底是不是一回事?
  • 为什么模型明明"知道"要查天气,却不一定能正确生成工具参数?
  • 为什么 Agent demo 很聪明,一进生产就开始无限循环、乱调工具、成本飙升?
  • tool_choicetemperaturemax_steps、超时、重试、观察窗口这些参数到底怎么配?
  • 什么时候应该让模型自由规划,什么时候应该把流程写死?

这些问题背后,本质上不是"模型会不会调用函数",而是:

你是不是在把语言模型,从一个文本生成器,变成一个会感知环境、调用外部能力、并基于反馈持续决策的执行系统。

这篇文章就集中讲这个问题。

我想按四层来拆:

  1. Function Calling 是什么,它解决了哪一层问题
  2. Tool Use 的完整闭环是怎么跑起来的
  3. Agent 为什么不是"多调几个工具"这么简单
  4. 工程上最关键的参数、约束和防失控机制应该怎么配

如果你已经从"给模型一个 prompt"走到了"让模型接搜索、数据库、浏览器、代码执行、业务 API",这一篇基本就是理解 Agent 系统的起点。


一、先说结论:Function Calling、Tool Use、Agent 是三层能力,不要混成一个词

很多讨论里,这三个词会被混用。

但如果不拆开,系统设计很容易做乱。

1)Function Calling:让模型按约定格式提出"调用请求"

Function Calling 解决的核心问题是:

不要让模型用自然语言随便描述"我想调某个接口",而是让它输出结构化、机器可解析的调用意图。

比如你定义一个函数:

  • get_weather(city, date)

理想情况下,模型不应该输出:

  • "我建议查询一下上海明天的天气。"

而应该输出类似:

  • 工具名:get_weather
  • 参数:{"city":"上海","date":"tomorrow"}

所以 Function Calling 的重点不是"真的执行了函数",而是:

  • 工具描述如何暴露给模型
  • 参数 schema 是否足够清晰
  • 模型是否能稳定产出合法参数
  • 上层程序是否能安全地解析结果

它本质上是一个结构化输出接口层

2)Tool Use:让模型提出调用,再由系统真的去执行,并把结果回灌

Tool Use 比 Function Calling 多了一步。

它要求系统形成完整闭环:

  • 模型判断是否需要工具
  • 模型产出工具名与参数
  • 外部执行器实际调用工具
  • 工具返回结果
  • 结果再喂回模型
  • 模型基于新观察继续回答或继续决策

所以 Tool Use 的关键,不只是 schema,而是执行与反馈

这意味着系统开始面对真实世界的不确定性:

  • 工具会超时
  • 参数可能不合法
  • 返回可能为空
  • 外部 API 会失败
  • 多个工具结果可能互相矛盾

从这一层开始,问题就不再只是"输出格式对不对",而是"系统行为稳不稳定"。

3)Agent:让模型在多步循环里持续做"思考---行动---观察"

Agent 则更进一步。

Agent 不是一次调用,而是一个循环:

  • 根据目标决定下一步干什么
  • 选择工具或子任务
  • 执行动作
  • 观察结果
  • 判断是否继续、修改计划或结束

所以 Agent 系统真正增加的,不是某个 API 字段,而是:

决策链路变长了。

一旦链路变长,问题会同步放大:

  • 错一步会不会越错越远
  • 工具调用会不会不断累积成本
  • 是否会进入循环
  • 是否会误用危险工具
  • 观测结果如何被压缩进上下文
  • 什么时候该停,什么时候该交还给人

因此最实用的理解方式是:

  • Function Calling 是结构化调用接口
  • Tool Use 是调用闭环
  • Agent 是多步决策系统

别把它们当成一件事。


二、为什么大模型需要工具:不是因为模型不聪明,而是因为它天然受三类限制

很多人第一次接触 Agent,会误以为"工具是给弱模型补能力"。

其实不准确。

更本质的原因是:

1)模型参数不是实时世界

模型再大,也只是把训练时见过的统计规律压进参数里。

所以它天然不擅长直接解决这类问题:

  • 今天上海下不下雨
  • 当前数据库里有多少订单
  • 某个网页现在显示什么内容
  • 某个代码仓库最新的 CI 状态如何

这些都不是"语言知识"问题,而是实时外部状态问题

工具调用的意义,就是把模型和实时环境接起来。

2)模型参数不是精确执行器

即使模型知道"应该算一下",也不代表它适合自己算。

例如:

  • 复杂数学计算
  • SQL 查询
  • 调 API
  • 文件系统操作
  • 浏览器点击和页面读取

很多任务不是靠更会说话解决,而是靠把确定性执行交给专门系统

3)模型参数不是长期工作流管理器

多步任务里,模型经常会遇到:

  • 中间状态需要保存
  • 失败需要重试
  • 某步结果要传给下一步
  • 超时和权限要检查
  • 有些动作需要人工确认

这些都更像系统工程,而不是单轮问答。

所以工具和 Agent 的存在,不是在替代模型,而是在承认模型的边界。

一句话概括:

模型负责理解、规划和生成;工具负责访问世界、执行动作和返回确定性结果。


三、Function Calling 到底怎么工作:本质是"给模型一个受限动作空间"

很多平台把 Function Calling 讲成一个 API 能力,但从机制上看,它更像是:

你把一组允许动作,以 schema 的形式显式告诉模型。

1)工具定义通常至少包含三类信息

一个可用的工具描述,至少要说清楚:

  • 工具名称
  • 工具用途说明
  • 参数结构与字段约束

比如一个搜索工具,不能只写:

  • search(query)

更好的描述通常会补清:

  • 这个工具适合查实时信息
  • query 应该是具体问题而不是空泛主题
  • top_k 的取值范围是什么
  • 什么情况下不应该调用它

因为模型不是编译器。

它是否会选对工具、填对参数,很大程度取决于你给的描述是不是足够可判别。

2)schema 设计越模糊,模型越容易"看起来懂了,实际上乱调"

最常见的问题包括:

  • 字段名太抽象,模型不知道该填什么
  • 多个工具功能重叠,模型难以区分
  • 参数可选项过多,模型容易臆造值
  • 描述里没有反例,模型不知道什么时候不该调

比如:

  • action_type
  • data
  • options

这种字段名从工程师角度觉得通用,但从模型角度很难判断语义边界。

通常更好的 schema 原则是:

  • 字段名尽量语义明确
  • 枚举值尽量少且边界清晰
  • 必填参数要少而关键
  • 描述中写清适用场景和禁用场景

3)Function Calling 不是"保证正确调用",只是提高调用可控性

这里要避免一个误解。

很多人以为只要开了 Function Calling,模型就会像一个严格遵循类型系统的程序。

事实并不是。

模型仍然可能:

  • 选错工具
  • 漏填参数
  • 生成不合法枚举
  • 在该直接回答时硬调工具
  • 在该调工具时假装自己知道答案

所以 Function Calling 更像是:

把原本完全自由的文本输出,压缩到了一个更容易校验、更容易拒绝、更容易重试的空间。

这已经很重要,但还不等于"问题解决了"。


四、Tool Use 的完整链路:不是模型输出完就结束,而是进入一个可失败的执行系统

一旦开始真的调工具,系统就从"生成问题"进入"执行问题"。

一条典型链路通常长这样:

  1. 用户提出目标
  2. 模型判断是否需要工具
  3. 模型输出工具名和参数
  4. 系统校验参数合法性
  5. 执行器发起实际调用
  6. 工具返回结果或错误
  7. 系统把结果压缩成 observation 回给模型
  8. 模型决定结束、追问、改参数或继续调用其他工具

这条链路里,几乎每一层都可能出错。

1)参数校验是第一道闸门

别直接把模型生成的参数无脑交给执行器。

至少要做:

  • 类型校验
  • 必填字段检查
  • 枚举值检查
  • 长度与范围限制
  • 危险字符过滤
  • 权限相关校验

因为模型生成的是"高概率文本",不是天然可信输入。

2)执行器和模型要解耦

一个很重要的工程原则是:

模型负责提出动作,执行器负责真正落地动作。

不要让模型自己拥有无限制执行权。

更稳妥的架构通常是:

  • 模型只能请求工具
  • 工具白名单由系统控制
  • 执行器做权限检查、超时、审计、重试
  • 某些高风险动作必须人工确认

这样做的好处是,模型即使判断错了,也不会直接越过系统边界。

3)返回结果必须做"观察压缩"

工具结果不是越原始越好。

如果你把大量 HTML、JSON、日志全文、不相关字段原封不动塞回上下文,很容易出问题:

  • 上下文膨胀
  • 干扰模型判断
  • token 成本飙升
  • 重要信息被淹没

更好的做法通常是:

  • 只保留必要字段
  • 明确标注状态:成功、失败、空结果
  • 对长结果做截断和摘要
  • 保留关键证据而不是全部噪音

Observation 的质量,会直接影响 Agent 下一步判断质量。


五、Agent 为什么容易"看起来很强,实际上很脆"

很多 Agent demo 的问题,不是第一步不会,而是第二步以后开始失控。

这正是多步系统的典型风险。

1)一步错误,可能在后续步骤被放大

比如模型第一步把用户需求理解错了。

在单轮问答里,后果可能只是答案偏一点。

但在 Agent 里,错误会继续传播:

  • 选错工具
  • 查询错对象
  • 得到错误 observation
  • 基于错误 observation 再规划下一步
  • 最后形成一本正经但方向完全错误的结果

所以 Agent 最难的不是"能不能开始",而是误差会不会连锁扩散

2)自由规划越强,行为越难预测

让模型自由选择工具、自由拆任务、自由决定何时结束,看起来更智能。

但代价是:

  • 行为稳定性下降
  • 成本更难控
  • 线上问题更难复现
  • 安全边界更难验证

因此生产上很少是"纯自由 Agent"。

更常见的做法是:

  • 有限工具集
  • 有限步数
  • 明确终止条件
  • 对高风险动作加审批
  • 对关键链路做半结构化流程编排

3)Agent 的瓶颈常常不是模型能力,而是上下文管理

多步循环以后,上下文会迅速膨胀。

问题包括:

  • 历史 observation 越来越长
  • 早期关键约束被后续内容冲淡
  • 模型开始遗忘初始目标
  • token 成本不断累积

所以成熟系统通常不会无脑把全量过程一直塞在上下文里。

而是会做:

  • 中间状态结构化存储
  • 历史步骤摘要化
  • 关键约束单独保留在 scratchpad 之外
  • 对 observation 做窗口裁剪

Agent 的稳定性,很大程度取决于你如何管理上下文,而不是只取决于底座模型多强。


六、最关键的几个参数,到底该怎么理解

下面把工程里最常见、也最容易被误用的一批参数拆开讲。

1)tool_choice:让模型自由选,还是强制用某个工具

它本质上控制的是:

  • 是否允许模型自己决定要不要调用工具
  • 是否要求模型必须调用指定工具
  • 是否禁止工具调用,直接自然语言回答

适用建议:

  • 开放问答场景:可让模型自由选择,但要有兜底规则
  • 确定流程场景:强制指定工具更稳
  • 测试/评估场景:固定工具选择更容易对比

如果某个步骤理论上就必须查数据库,那就别让模型"思考是否要查"。

直接强制调用通常更稳。

2)temperature:在 Agent 里通常比聊天更应该保守

在一般聊天里,稍高一点的随机性可能更自然。

但在工具调用和 Agent 任务里,温度过高通常意味着:

  • 工具选择更飘
  • 参数填充更不稳定
  • 多步链路更难复现
  • 同一任务重复执行结果差异更大

经验上:

  • 结构化输出、检索、数据库查询、代码执行前的规划,温度通常应偏低
  • 只有在创意生成、候选方案发散时,才适合适度提高

别把 Agent 当成创作模型来配采样参数。

3)max_steps:它不是随便设的保险丝,而是成本与风险阀门

这是 Agent 系统里最重要的保护参数之一。

它控制的是:

  • 一个任务最多允许多少轮"思考---行动---观察"循环

值太小:

  • 合法复杂任务做不完

值太大:

  • 容易死循环
  • 成本失控
  • 失败被拖很久才暴露

比较实用的思路是:

  • 简单任务给小步数
  • 复杂任务按任务模板给不同上限
  • 接近上限时触发总结或交还人工

max_steps 本质上是 Agent 的预算参数,不是可有可无的默认值。

4)超时参数:必须区分模型超时、工具超时、总任务超时

很多系统只有一个统一 timeout,这通常不够。

更合理的拆法是:

  • 单次模型生成超时
  • 单次工具执行超时
  • 整个任务总超时
  • 排队等待超时

因为这四种超时背后的原因不同:

  • 模型慢,可能是上下文过长或服务拥堵
  • 工具慢,可能是外部 API 或网络问题
  • 总任务慢,可能是循环过多
  • 排队超时,可能是系统容量问题

只有拆开,你才知道该优化哪一层。

5)重试参数:不是所有失败都该重试

重试看起来很合理,但在 Agent 里尤其危险。

因为一次失败重试,可能触发:

  • 更多 token 消耗
  • 更多外部 API 调用
  • 更长任务链路
  • 重复副作用

应该区分:

  • 可重试错误:临时超时、短暂网络错误、限流
  • 不可重试错误:参数非法、权限不足、业务约束不满足

并且要配:

  • 最大重试次数
  • 指数退避
  • 幂等设计
  • 对有副作用操作加去重键

否则 Agent 很容易把一个瞬时异常放大成连环调用事故。

6)观察窗口与上下文裁剪参数:决定 Agent 会不会"越做越糊涂"

很多框架喜欢把完整过程塞回上下文。

短期看方便,长期看风险大。

需要明确控制:

  • 保留最近几步 observation
  • 历史步骤何时摘要化
  • 哪些系统约束要常驻上下文
  • 哪些中间结果只放外部状态,不回灌模型

这个参数组,常常比"换更强模型"更影响系统稳定性。


七、生产里真正重要的,不是让 Agent 更自由,而是让它更可控

很多团队刚做 Agent 时,目标是"尽可能像人一样自主"。

但一到生产,优先级就会变成另外四件事:

  • 可预测
  • 可审计
  • 可回放
  • 可止损

1)工具白名单和权限分级必须做

不是所有工具都应该暴露给同一个 Agent。

更安全的设计通常是:

  • 只暴露任务所需最小工具集
  • 读操作和写操作分开
  • 外部副作用工具单独审批
  • 按用户身份、租户、环境做权限切分

一个能调用十个工具的 Agent,不一定比一个只会调两个工具的 Agent 更好。

它可能只是更危险。

2)高风险动作要有人类确认节点

例如:

  • 发邮件
  • 下单
  • 删除数据
  • 修改数据库
  • 执行生产命令
  • 对外发送消息

这些动作不应该只因为模型"很有把握"就直接执行。

更稳妥的模式是:

  • 先生成行动建议
  • 明确展示将调用的工具和参数
  • 等待人工确认
  • 再执行

这会牺牲一点流畅性,但能换来可控性。

3)日志与轨迹必须能回放

Agent 系统出了问题,如果你只能看到"最终回答错了",基本是排不动的。

至少要能回放:

  • 每一步 prompt 或系统状态
  • 每一步工具选择
  • 参数内容
  • observation 内容
  • 错误类型
  • 总步数、总 token、总耗时

否则你根本不知道问题出在:

  • 模型判断错
  • schema 不清晰
  • 工具返回脏数据
  • 裁剪策略把关键信息截掉了
  • 超时和重试策略互相打架

4)要有明确终止条件,而不是"直到模型说结束"

终止条件最好是多重的:

  • 达到目标
  • 达到最大步数
  • 达到总超时
  • 达到成本预算
  • 连续若干步没有有效进展
  • 连续重复同一工具调用

如果终止条件只有"模型自己决定结束",那系统迟早会遇到无限循环或伪完成。


八、什么时候该上 Agent,什么时候其实不需要 Agent

这是一个很实用的问题。

因为很多任务被包装成 Agent,其实只是流程没有设计好。

适合 Agent 的场景

通常有这几个特征:

  • 任务路径不固定
  • 需要根据中间结果动态决策
  • 可能涉及多个工具协作
  • 需要多步搜索、筛选、验证
  • 人工事先难以写死全部流程

比如:

  • 多源信息检索与交叉验证
  • 复杂报表分析
  • 浏览器任务自动化
  • 代码库定位问题并尝试修复
  • 需要探索式完成的开放任务

不适合 Agent 的场景

如果流程本来就很确定,其实更适合工作流而不是 Agent。

例如:

  • 查数据库 → 填模板 → 返回结果
  • 固定字段抽取 → JSON 输出
  • 固定 API 查询 → 结果整形
  • 审批通过后执行一个确定动作

这类任务用编排式 workflow 往往更稳、更便宜、更容易调试。

一个很实用的判断标准是:

如果你能把流程规则稳定写清楚,就优先写流程;只有当中间决策真的不可预定义时,再引入 Agent。


九、一个更接近现实的 Agent 系统,通常长什么样

如果把一个相对成熟的 Agent 系统抽象一下,常见结构会是:

  • 任务入口层:接收用户目标,做身份与权限校验
  • 规划/决策层:决定下一步是回答、调用工具还是继续搜索
  • 工具执行层:白名单工具、参数校验、权限控制、超时与重试
  • 状态管理层:保存任务状态、中间结果、历史摘要、预算消耗
  • 观测与审计层:日志、轨迹、指标、告警、回放
  • 人工接管层:高风险动作确认、失败兜底、人工纠偏

在这个结构里,底座模型只是中间的一部分。

真正决定 Agent 能否进入生产的,不只是模型是否足够聪明,而是:

  • 工具边界有没有收好
  • 状态有没有管理好
  • 错误有没有隔离好
  • 成本有没有预算好
  • 人有没有办法及时接管

十、三条最实用的落地建议

如果你准备把 Function Calling 或 Agent 接到真实业务里,我最建议先做好下面三件事。

建议一:先从"单工具闭环"做起,不要一开始就追求通用 Agent

先把一个明确任务跑稳:

  • 什么时候调用
  • 参数怎么生成
  • 返回结果怎么压缩
  • 失败怎么处理

等单工具闭环稳定后,再扩到多工具协作。

这比一开始堆十几个工具、追求"全能代理"靠谱得多。

建议二:把 schema 设计当成产品设计,而不是顺手写个 JSON

工具名、参数名、字段描述、枚举值、适用边界,都会直接影响模型行为。

很多所谓"模型不会调工具",本质上其实是 schema 写得太差。

建议三:优先把预算和终止条件做严,再追求智能感

先控制好:

  • 最大步数
  • 总超时
  • 工具超时
  • 重试上限
  • 可用工具范围
  • 高风险动作审批

把系统先做稳,再考虑让 Agent 更自由。

生产系统里,"可控的 80 分"通常比"偶尔惊艳、偶尔翻车的 95 分"更有价值。


十一、最后总结:Agent 不是一个 API 功能,而是一种把模型接入环境的系统设计

很多人第一次接触 Function Calling 和 Agent,会觉得这只是模型厂商加的几个新字段。

但如果从工程角度看,真正变化很大。

因为从这一刻起,模型不再只是回答问题,而是在:

  • 理解目标
  • 选择动作
  • 调用工具
  • 读取反馈
  • 在多步循环里持续决策

所以这篇最核心的结论可以浓缩成一句话:

Function Calling 解决的是"怎么结构化提出调用请求",Tool Use 解决的是"怎么形成执行闭环",Agent 解决的是"怎么在多步环境里持续做决策"。

而生产里的关键,从来不是把 Agent 做得多像人,而是把它做得:

  • 有边界
  • 有预算
  • 有审计
  • 有终止条件
  • 出错后能止损

如果这些都没有,Agent 往往只是一个更贵、更难排障的 prompt 套壳系统。

如果这些都做好了,模型才真正有机会从"会说话"走向"会做事"。

复制代码
相关推荐
光影少年1 小时前
高级前端需要学习那些东西?
前端·人工智能·学习·aigc·ai编程
怕浪猫1 小时前
从 Openclaw 、codex、Claude code 爆火看 AI Agent 冲击:只会调 API 的程序员,出路在哪里?🤔🤔🤔
人工智能
神州数码云基地1 小时前
告别传统OCR瓶颈,DeepSeek-OCR如何重塑文档智能?
人工智能·llm·ocr·大语言模型·deepseek
了不起的云计算V1 小时前
以AI及自主创新重构教育数字化底座,华为擎云给出更优答案
人工智能·华为·重构
code_pgf2 小时前
LLM大模型评测(ARC-AGI-2)
人工智能·transformer·agi
℡終嚸♂6802 小时前
Gogs CVE-2025-64111 CTF Writeup
大数据·elasticsearch·搜索引擎
大龄程序员狗哥2 小时前
第23篇:GAN实战:生成二次元头像——创造属于你的虚拟形象(项目实战)
人工智能·神经网络·生成对抗网络
大江东去浪淘尽千古风流人物2 小时前
【UV-SLAM 】彻底吃透UV-SLAM:创新原理、工程实现与直线几何核心代码详解
数据库·人工智能·python·机器学习·oracle·uv
xiaoshujiaa2 小时前
SpringAI实战:基于MCP协议的AI Agent工具链集成指南
人工智能