知识库 / 模型增强
GitHub
← 模型增强

LAYER 05 / MODEL AUGMENTATION

工具调用与结构化输出

所属: 模型增强层。本页边界: 怎样将语言模型输出约束为可解析、可验证的函数调用,以及执行授权与语法约束为何是不同层次的问题。

#核心公式

a=parse⁡S(y),execute⁡(a)⟺Psyntax(a)∧Psemantic(a,x)∧Pauth(a,u)∧Pstate(a,s) a=\operatorname{parse}_{\mathcal S}(y), \qquad \operatorname{execute}(a) \Longleftrightarrow P_{\mathrm{syntax}}(a)\land P_{\mathrm{semantic}}(a,x)\land P_{\mathrm{auth}}(a,u)\land P_{\mathrm{state}}(a,s)

工具输出可解析只是第一个条件;语义、用户权限和当前环境状态也必须同时满足,才允许执行。2026 年的关键变化在于:语法约束的成功可能掩盖工具调用能力的退化,而执行授权必须由计算之外的独立层判定。

#符号说明

符号 含义
yy 语言模型生成的结构化文本
S\mathcal S JSON Schema、grammar 或其他语法规范
aa 解析后的候选动作,通常包含工具名和参数
xx 当前用户任务与上下文
uu 已认证的用户或调用主体
ss 执行前的环境状态
PsyntaxP_{\mathrm{syntax}} 动作是否满足语法与类型约束
PsemanticP_{\mathrm{semantic}} 参数是否与用户任务语义一致
PauthP_{\mathrm{auth}} 用户是否有权执行动作
PstateP_{\mathrm{state}} 当前状态是否满足执行前置条件
Aallowed\mathcal A_{\mathrm{allowed}} 系统允许暴露给模型的动作集合
Cinvoke\mathcal C_{\mathrm{invoke}} 编译后的契约状态机
VtvalidV_t^{\mathrm{valid}} 第 tt 步仍能完成为合法输出的 token 集合
CPI\mathrm{CPI} 约束优先反转假设
SskillS_{\mathrm{skill}} Skill 的规范定义

四个谓词由程序、身份系统或明确授权共同判定,不能只依靠模型自评。

#技术要点

  • 约束税(Constraint Tax) :当工具调用与 JSON Schema 约束同时启用时,语法约束的 token 掩码可能使工具调用 token 在解码中不可达,导致开源模型停止调用工具。这是工具调用与结构化输出联合部署时的未文档化失效模式。
  • CASD(契约感知投机解码) :将 API 契约编译为轻量动态状态机,对确定性结构 token 走“结构注入快速路径”,对概率性语义参数在草稿模型上施加 Schema 引导的 logit 掩码,在 BFCL v3 上实现最高 2.53 倍解码加速。
  • 计算不等于授权(Computation Is Not Authority) :模型成功推理、沙箱隔离、连接器白名单或会话权限,都不自动构成对特定现实后果的授权。需引入硬件根植的执行终局性(Execution-Finality)架构。
  • ToolClad:声明式工具契约格式,将参数验证推至结构性运行时围栏,使元字符注入、命令替换、路径穿越和同形字攻击在结构上不可表达,而非事后检测。
  • Spring AI CVE-2026-59318:按请求通告的工具列表作为边界,但在工具调用分发时未被完全执行,可能导致权限提升。
  • Tool Suppression 的缓解方案:Transparent Two-Pass Execution,将工具执行与 Schema 约束响应生成解耦,恢复工具调用同时保留结构化输出保证。
  • Skill 是比 Function Calling 更高层级的能力抽象:Function Calling 定义“接口”,Skill 封装“知识”。Skill 通过渐进式上下文加载按需提供领域能力。
  • 工具调用的评估需要区分选择与执行两个层面。CompToolBench 的 Selection Gap 发现:正确选择工具的模型经常无法产生有效调用,平均差距 13.2 个百分点。

#原理与演进

#模型输出不等于程序调用

执行链为:文本 token → 语法约束 → 结构化参数 → 校验/授权 → 工具执行。

  • Schema 约束字段、类型、必填项;语法约束解码可在每一步只允许仍能组成合法 JSON 的 token。
  • 语法正确仅说明“可解析”;参数是否存在、是否在权限范围、操作是否符合用户意图需要额外校验。
  • 工具返回值是外部观察,不应提升为系统指令。否则网页、文档或日志中的恶意文本会借工具结果控制模型。

#约束解码的效率与安全权衡

标准自回归生成结构化输出面临延迟瓶颈。现有加速方法面临两难:标准投机解码因草稿模型的结构幻觉而严重精度下降,而基于语法的约束解码保持正确性但牺牲了加速,原因是昂贵的 CPU 端词汇表评估。

CASD 将 API 契约编译为轻量动态状态机。当结构 token 是确定性的(如 JSON 的括号、引号、字段名),CASD 激活 Structure-as-Injection Fast Path,直接发出语法样板并绕过冗余的神经前向传播。对于概率性语义参数(如字段值),CASD 在草拟阶段施加 Schema-Guided Logit Masking,在目标模型验证前将草稿模型限制在结构合法的词汇表中。这一设计同时解决了标准投机解码的结构幻觉和语法约束解码的 CPU 瓶颈。

#约束税:工具调用与结构化输出的联合失效

当 Tool Calling 和 JSON Schema 约束同时启用时,多个开源模型停止调用工具,尽管保持了高 Schema 合规性。这一现象称为 Tool Suppression,根源是 JSON Schema 约束被编译为基于语法的 token 掩码,导致工具调用 token 在解码过程中不可达。

约束优先反转(CPI)假设认为,在多个同时约束下,Schema 满足可能主导动作选择行为。这一假设是行为层面的,与观察到的解码级机制一致。

缓解方案 Transparent Two-Pass Execution 将工具执行与 Schema 约束响应生成解耦:第一遍决定是否调用工具及调用哪个工具,第二遍在工具执行后生成 Schema 约束的结构化响应。这一策略无需模型重训练即可恢复工具调用,同时保留结构化输出保证。

这一发现的工程含义是:单独评估工具使用和结构化输出可能遗漏生产 Agent 系统中的重要可靠性问题。

#从“执行什么”到“允许什么被执行”

IETF 草案明确区分了工具选择与工具效果:连接器白名单不是每次操作的终局授权。提案的架构中,一个拟议的后果承载操作被表示为 Candidate Act,并保持在 Non-Effective State,直到 Protected Enforcement Domain 验证操作特定的谓词,并由独立的 Finality Sink 在操作变为外部有效之前立即验证作用域化的、非承载的终局授权。如果授权缺失、过期、重放、撤销或与尝试的操作不匹配,Candidate Act 保持非有效状态,操作失败关闭。

这一架构的核心不变式是:计算不是授权;工具选择不是工具效果;连接器白名单不是每次操作的终局性。

ToolClad 将参数验证推至结构性运行时围栏。大多数生产中的 Agent 失败不是“工具不允许”,而是“工具允许但参数错误”:read_file(path="../../etc/shadow") 是一个被允许的操作,但带有攻击者塑造的参数。ToolClad 通过声明式契约使元字符注入、命令替换、路径穿越和同域同形字攻击在结构上不可表达。在九种托管 LLM 上的 A/B 评估中,333/335 次处理组分发被拒绝,对恶意输入的拦截率为 100%。

#Skill 的定位:从接口定义到知识封装

Function Calling 与 Skill 的本质差异:前者定义的是“接口”,后者传递的是“知识”。

Function Calling 的流程是:用户请求 → LLM 推理 → 生成函数调用 JSON → 开发者代码执行 → 返回结果。LLM 只负责“决定调用什么,生成参数”。

Skill 的流程是:用户请求 → LLM 读取 Skill 说明 → LLM 决定调用哪些底层 Tool → 执行 → 返回结果。Skill 本身不是可执行代码,它是写给 LLM 看的自然语言指导,包含领域知识、操作流程、最佳实践和约束规则。

Skill 的核心工程机制是渐进式上下文加载:

  • Level 1 (Metadata):仅加载 Skill 的元数据(名称、描述),用于语义搜索和路由决策。
  • Level 2 (Retrieval):当任务匹配到某个 Skill 时,加载 SKILL.md 全文。
  • Level 3 (Resources):模型根据 SKILL.md 中的引用,按需读取额外的参考文档或执行脚本。

这一设计的工程意义是:上下文窗口只被真正需要的信息占用。一个有 50 个 Skill 的系统,在初始状态下只消耗 50 行元数据的上下文。

Skill 和 MCP 不是竞争关系,而是不同层级:MCP 解决“能不能连”,Skill 解决“会不会做”。

#1. 语法、语义、授权必须三次判定

设模型生成式(1)所示的候选动作,uu 为工具名,ξ\xi 为参数。安全执行要求 a∈L(S)a\in\mathcal L(\mathcal S)(语法合法)、式(2)(参数与任务语义一致)、式(3)(用户有权执行)。Schema 通常只能可靠约束第一项。

式(1):

a=(u,ξ) a=(u,\xi)

式(2):

Psem(a,x)=1 P_{\mathrm{sem}}(a,x)=1

式(3):

Pauth(a,user)=1 P_{\mathrm{auth}}(a,\text{user})=1

例:transfer(amount=1000, account=...) 可以是合法 JSON,但金额、账户和用户授权都可能不对。对于不可逆动作,解析成功绝不是执行许可。

#2. 约束解码的工程进展

#2.1 CASD:契约感知的投机解码

标准自回归生成结构化输出面临延迟瓶颈。CASD 将 API 契约编译为动态状态机,利用结构化输出的确定性特征绕过冗余计算。

契约状态机 Cinvoke\mathcal C_{\mathrm{invoke}} 编码了工具调用的合法 token 序列。在解码第 tt 步,状态机计算允许的 token 集合 VtvalidV_t^{\mathrm{valid}}。对于确定性结构 token(如 JSON 语法标记),CASD 直接注入而不经过模型前向传播;对于语义参数 token,施加 Schema 引导的 logit 掩码后将草稿模型限制在合法词汇表中。

在 BFCL v3 基准上跨多个模型家族的评估显示,CASD 相比贪心解码实现最高 2.53 倍加速,同时保持高 AST 精确匹配准确率。

#2.2 约束税的机制

JSON Schema 约束被编译为基于语法的 token 掩码后,在解码的每一步,只有仍能组成合法 JSON 的 token 才被允许。如果工具调用的 token(如工具名)不在当前允许集合中,模型就无法发出工具调用。

CPI 假设认为,当 Schema 满足和工具调用两个目标同时存在时,解码器倾向于优先满足 Schema 约束。这一行为在单独评估工具使用和结构化输出时不会显现,只在联合部署时出现。

部署模式 工具调用率 Schema 合规率
仅工具调用 正常 —
仅 Schema 约束 — 正常
联合部署 显著下降 保持高位

#2.3 约束解码框架的标准化评估

JSONSchemaBench 提供了 10,000 个真实 JSON Schema,覆盖广泛约束类型,配合官方 JSON Schema 测试套件,评估六个主流约束解码框架(Guidance、Outlines、Llamacpp、XGrammar、OpenAI、Gemini)在效率、覆盖率和质量三个维度上的表现。

主流约束解码库包括:Outlines(FSM-based,97% 成功率,0.4% 幻觉率)、XGrammar、llguidance、LMQL、AICI 等。

#3. 工具调用的执行授权

#3.1 计算与授权的分离

IETF 草案的核心论点是:模型可能被授权进行计算,但仍未被授权行动。成功的推理、沙箱隔离、连接器白名单或会话权限,都不自动构成对特定现实后果的授权。

架构要求将后果承载操作表示为 Candidate Act,保持在 Non-Effective State,直到:

  1. Protected Enforcement Domain 验证操作特定的谓词
  2. 独立的 Finality Sink 验证作用域化的终局授权

如果授权缺失、过期、重放、撤销或与尝试的操作不匹配,操作失败关闭。

#3.2 ToolClad:危险参数的不可表达化

ToolClad 将参数验证推至结构性运行时围栏。其 .clad.toml 清单定义类型化参数、验证规则、命令模板(数组式执行,无 shell 字符串插值)和执行后端。

验证器在任何工具分发之前运行,拒绝无法由契约表达的参数。这使得元字符注入、命令替换、路径穿越和同域同形字攻击在结构上不可表达,而非事后检测。

在九种托管 LLM 上的 A/B 评估中,333/335 次处理组分发被拒绝。攻击子形态包括:元字符(;|&)、命令替换($())、反引号、通配符、换行注入、路径穿越(../)、西里尔同形字 IDN 和 punycode IDN。

分层防御的独立贡献:在工具参数注入攻击类别上,Cedar 策略拒绝 = 0(因为 whois_lookup 被任务 Agent 的策略允许),内容消毒器剥离 = 0(因为攻击在参数中而非存储内容中),ToolClad 拒绝 = 333。

#3.3 工具列表通告与执行的差距

Spring AI 的 CVE-2026-59318 揭示了一个架构级问题:按请求通告的工具列表被作为边界呈现给模型,但在工具调用分发时未被完全执行。在某些条件下,未被通告的工具可能被调用,导致权限提升。

Verifier Tax 现象进一步量化了安全执行的成本:在多步工具使用 Agent 中,运行时执行验证器中介(评估拟议动作是否违反预定义策略)会影响端到端任务性能,影响程度取决于任务的时间跨度。

#4. 工具调用的状态机

模型提出调用 → 程序校验 Schema → 检查权限和前置条件 → 执行/超时 → 记录结果 → 将结果作为低信任观察交回模型 → 验证最终回答。

边界 失效方式 保护原则
模型→工具 参数幻觉、越权 白名单、类型与业务规则校验、ToolClad
工具→模型 返回包含伪系统命令 返回值只作为数据呈现
工具→环境 重复执行导致副作用 幂等键或显式去重
多次调用 状态过期、竞态 版本戳与前置条件重查
通告→执行 通告列表与实际执行不一致 执行时重新验证

工具返回值若是异常、空结果或部分成功,模型应区分这些状态;将异常文本包装成“成功”会掩盖真实失败。

#5. 工具与 RAG、Agent 的关系

RAG 的检索器本身可作为一个只读工具,但 RAG 的核心问题是证据选择与引用;工具调用的核心问题是结构化动作契约;Agent 的核心是多步决策和状态更新。概念路线:自然语言生成 → 结构化动作 → 执行观察闭环 → 有规划和停止条件的 Agent。Skill 位于工具与 Agent 之间,强调职责单一、结构化 I/O 与可组合性。

#6. Skill 的设计与评估

#6.1 Skill 的五种设计模式

  • 工具包装器:将底层工具封装为有领域语义的高层接口。
  • 生成器:生成模板、代码或结构化数据。
  • 审阅者:检查输入或输出是否符合规范。
  • 参考知识包:提供领域知识文档,模型按需读取。
  • 可组合编排:定义多步骤工作流,调用多个底层 Skill。

#6.2 Skill 的评估指标

  • 调度正确率:Skill 是否在正确情境下被激活。推荐阈值 ≥ 0.85。
  • 内部轨迹合规率:Skill 定义的步骤是否按序执行。推荐阈值 ≥ 0.90。
  • 输出集成质量:Skill 的输出是否正确整合到最终回答中。推荐阈值 ≥ 0.80。

#6.3 Skill 的安全边界

Skill 运行在代码执行沙箱中,但脚本以完整环境访问权限运行。企业部署需要 Skills Registry 进行发布前扫描、签名验证、沙箱隔离和权限最小化。

#7. 工具使用的评估

#7.1 最新基准

基准 规模 覆盖维度 关键发现
CompToolBench 200 任务,106 真实工具 单步、顺序、并行、图组合 Selection Gap 平均 13.2 个百分点
Live API-Bench 2500+ API,11 数据库 错误处理、顺序推理、参数生成 任务完成率 7–47%,交互式提升至 50%
MCP-Bench 真实多步任务 工具使用、跨工具协调 —
MultiCAT-Bench 多类别 Agent 工具使用 Grok 4.1 Fast 83.8%,GPT-5 Mini 83.7% —

#7.2 评估维度

分别测工具选择准确率、参数准确率、权限拒绝率、执行成功率、最终任务成功率和成本。只测 JSON 可解析率,会忽略“合法调用了错误工具”这一核心错误。CompToolBench 的 Selection Gap 揭示了一个关键区分:正确选择工具的模型经常无法产生有效调用,这两个能力需要分开评估。

危险操作应在测试环境或模拟器中评估,且将权限边界作为独立指标。对工具评测,除了参数完全匹配,还需测试:无效值、权限边界、工具异常、重复响应、顺序颠倒、伪指令混入返回值。

#8. Schema 的表达能力与权限分离

Schema 可表达字段类型、枚举、取值范围和嵌套结构,却通常无法单独判断“这个用户是否能访问该文件”“这个金额是否与用户真实意图一致”。前者需要身份与资源权限系统,后者可能需要明确确认。

对读操作可施加最小权限的资源范围;对写操作应定义副作用、前置条件、幂等行为和失败回滚语义。若工具在部分执行后超时,简单重试可能重复副作用,故返回结果需区分“未开始”“已完成”“状态未知”。

#9. 不确定状态下的决策

模型可能猜测某个参数,例如数据库记录 ID。正确动作是先调用只读查询确认,而非对猜测 ID 执行写操作。多步工具使用可抽象为先降低状态不确定度再执行影响环境的动作。

原始资料:

本页由仓库中的 Markdown 生成。具体技术结论请结合正文引用与实验条件理解。

输入关键词,探索整个知识库

↑ ↓ 选择 ↵ 打开36 篇笔记,一次搜索