<!-- title: 约束解码幻觉税：合法却编造 -->

# 约束解码的幻觉税：函数调用「合法却编造」六派横评

## 概述

2026 年，结构化输出已从「提示词技巧」沉淀为基础设施级保证：OpenAI Strict、Anthropic 程序化工具调用、XGrammar、Outlines、json-repair 各成一派，争着承诺「100% 合法 JSON」。但这套保证藏着一个反直觉陷阱——**语法满分，语义塌方**。本文横评六种函数调用强制方式，实测发现：token 级掩码（XGrammar/Outlines）确实把畸形 JSON 率压到接近零，却以「被迫编造必填字段值」的形式把成本转嫁给语义层；服务端 CFG（OpenAI Strict）受限于「全字段必填」约定，在模型缺值时逼出「合法的谎言」；只有「先草稿后约束」的 DCCD 路线能把语法合规与语义忠实同时拿下（结构化准确率最高 +24%）。结论先行：**结构化输出的真正成本不在解析失败，而在「合规的幻觉」——选错强制层，省下的重试 token 全部变成下游静默错误。**

## 六派强制层横评

| 强制方式 | 合规位置 | 语法保证 | 语义忠实 | 延迟代价 | 典型代表 | 最适场景 |
|---|---|---|---|---|---|---|
| 服务端 CFG（Strict） | 推理服务器 | ≈100% | 差（逼编造） | 首次 schema 预处理 | OpenAI Strict | 简单 schema、强合规管道 |
| 推理趟折叠（程序化） | 工具调用即代码 | 依赖模型 | 中 | 省 37% token / 少 19+ 趟 | Anthropic Programmatic | 多工具循环、批量调用 |
| 本地 token 掩码 | 解码层 | ≈100% | 差（被逼填） | CPU-GPU 同步税 | XGrammar / Outlines | 自托管开源模型 |
| 先草稿后约束 | 解码层 | ≈100% | **好** | 两段生成 | DCCD / guidance 两种 | 复杂 schema、需语义保真 |
| 宽松修复 | 后处理 | 高（修后） | 静默篡改风险 | 极低 | json-repair | 兜底、容错解析 |
| 失败重试 | 循环层 | best-effort 90-95% | 取决于反馈 | 失败时 token 线性/指数膨胀 | 自研重试 | schema 复杂、无法改模型 |

> 语法保证高 ≠ 语义忠实高。横评的核心结论：**掩码派把幻觉从「语法层」赶到「语义层」，治标且制造新病。**

## 深度分析

### 一、核心反直觉：语法合规 ≠ 语义正确

这是整套横评的地基。一篇 2025 RANLP 论文《The Hidden Cost of Structure》和 CRANE（OpenReview）都指向同一现象：**严格语法约束会显著损伤模型的推理与忠实度**。原因是 token 级掩码在每一步只允许「合法 token」，当模型本想表达「我不知道」时，约束把它逼成「必须填一个合法值」，于是它编造一个看起来合理的占位符。

```python
# 约束解码下，模型无法输出 "null" / "unknown" 来表达「我不知道」
schema = {
    "type": "object",
    "properties": {
        "ceo": {"type": "string"},          # 必填 string
        "founded": {"type": "integer"}      # 必填 integer
    },
    "required": ["ceo", "founded"]
}
# 问"X 公司 CEO 是谁"，模型其实不确定 → 被逼填 "张三" / 2019
# 语法 100% 合法，语义 100% 错误，且下游无法察觉
```

XGrammar 官方文档自己都承认这点，建议「应用约束解码时，**也要在 prompt 里描述期望的输出结构**」——靠提示词对齐语义，掩码只兜底语法。这说明社区已意识到：**纯掩码是不够的，它是语法保险丝，不是语义保险丝。** 变现上，这是个被严重低估的咨询切入点——多数团队上了 Strict 之后「JSON 解析报错归零」就以为万事大吉，实际把错误率从可见层推进了不可见层，训练营可专门做「合规幻觉审计」专题。

### 二、OpenAI Strict 的「必填陷阱」

OpenAI Strict 模式把 schema 预处理成上下文无关文法，在服务端逐 token 施掩码，语法合规率接近 100%。但它的设计约束埋了语义地雷：**默认所有字段 `required`、强制 `additionalProperties: false`、不支持 `pattern`、`format` 受限**。

```python
from pydantic import BaseModel
from openai import OpenAI

class WeatherArgs(BaseModel):
    city: str
    date: str        # strict 下默认必填 → 缺值时模型编造日期

client = OpenAI()
resp = client.beta.chat.completions.parse(
    model="gpt-4o-2024-08-06",
    messages=[{"role": "user", "content": "查北京天气"}],  # 用户没给日期
    response_format=WeatherArgs,
)
# date 被填成 "2026-06-25"，语法合法，但那是模型猜的，不是用户给的
```

标准做法是把可选字段改成 `anyOf: [string, null]` 让模型能合法输出 null，但很多团队不知道这层，直接全 `required`。结果是「合规的谎言」漫山遍野。**优点**：解析层零异常、首调用后预热快、托管免运维。**缺点**：schema 表达力受限、必填约定诱发编造、首次 schema 预处理有冷启动延迟。**变现评估**：Strict 适合做「结构化输出训练营」的入门模块，但要配套讲清「必填陷阱」和 `anyOf/null` 解法，否则学员上线即踩雷。

### 三、Anthropic 程序化工具调用：把 N 趟推理折成 1 趟

Anthropic 的程序化工具调用（programmatic tool calling，2025-04 beta）换了赛道：**不靠掩码保证语法，而是让模型写一段 Python 来编排工具调用**。一次推理趟内，模型可以 `for region in regions: results.append(get_sales(region))`，把原本「调用→等结果→再调用」的 N 趟串行推理，折叠成 1 趟代码执行。

```python
# 模型输出的是代码，不是单次 tool_use JSON
# for region in ["east", "west", "north"]:
#     r = get_sales(region)      # 工具被转成 async Python，并行触发
#     results.append(r)
# 一个五工具工作流：传统 = 5 趟推理；程序化 = 1 趟
# 实测：省 37% token，少 19+ 趟推理（Zylos Research / Anthropic）
```

每个工具调用本就是一次完整模型推理——五工具工作流等于五趟推理（Anthropic 工程博客原话）。程序化把这五趟压成一趟代码生成 + 一次代码执行。**优点**：天然支持并行、循环、条件分支，批量场景 token 与延迟双降；语义忠实度不降（模型在自由代码里表达「不确定」时可以写 `if not x: continue`）。**缺点**：要求受控的代码沙箱、强依赖模型写代码能力、错误处理落到代码层而非框架层。**变现评估**：这是 2026 年做「批量工具调用」最有差异化的一派，适合做企业级 ETL/RPA 智能体训练营，卖点直接量化（37%/19 趟），比讲掩码性感得多。

### 四、本地 token 掩码：XGrammar/Outlines 的延迟税

自托管开源模型的团队走掩码路线：XGrammar（CFG）、Outlines（FSM）、guidance、lm-format-enforcer，在解码每个 token 时查表，把所有非法 token 的 logits 设为负无穷。语法合规率拉满，但代价是 **CPU-GPU 同步**。

```python
from vllm import LLM, SamplingParams
llm = LLM(model="Qwen/Qwen2.5-7B-Instruct")
out = llm.chat(messages, SamplingParams(
    # 每个 token 都要: logits 出 GPU → CPU 查 FSM 掩码 → 回 GPU 采样
    guided_decoding={"json": weather_schema},
))
# vLLM 官方讨论区：约束解码明显变慢，主因 CPU-GPU 同步开销
```

XGrammar 的核心贡献是用「字节掩码 + 预处理 CFG」把这个同步做快，但同步本质躲不掉——尤其 batch 推理时，掩码计算成为吞吐瓶颈。**优点**：语法保证最强、与开源模型栈原生集成、schema 表达力强于 Strict（支持更全的 JSON Schema）。**缺点**：推理吞吐下降、与 Schema 漂移（covered 主题）叠加时静默击穿、语义编造问题依旧。**变现评估**：适合做「私有化部署智能体」训练营，但必须配套讲延迟基线与吞吐回归测试，否则客户上量后才发现 QPS 崩了。注意——这派和「Schema 漂移」「8KB 盲区」是连体问题，掩码只管 token 合法，不管「schema 变了没」「结果被截断没」。

### 五、DCCD 草稿后约束：语义税的唯一解药

DCCD（Draft-Conditioned Constrained Decoding，ICML 2026）是目前唯一正面解决「掩码伤语义」的方案。思路分两段：**先让模型自由草稿（保语义），再以草稿为条件施加约束（修语法）**。论文报告在结构化推理基准上，strict 结构化准确率提升最高达 **+24%**。

```python
# 阶段1: 自由生成草稿——模型可以输出 "不确定"、"null"、自然语言解释
draft = llm.generate(prompt, sampling=free_sampling)
# 阶段2: 以草稿为条件，约束到 schema——只修语法，不逼编造
final = llm.generate(
    prompt + f"基于以下草稿严格按 schema 输出：\n{draft}",
    sampling=constrained(schema),
)
# 模型有了语义锚点，掩码不再逼它编造，准确率回升
```

与此同源的还有「minimally invasive constrained decoding」（arXiv 2403.06988）的理念：**约束应当最小侵入，只在该合法的地方合法，不强行改写模型的语义选择。** 这派是横评里唯一「语法 + 语义双高」的，代价是两段生成带来额外延迟与 token。**优点**：语义忠实度恢复、适合复杂 schema 与推理类任务。**缺点**：两段生成延迟翻倍、实现复杂、需自托管可控解码。**变现评估**：目前认知度低、技术门槛高，适合做高客单价的「结构化输出可靠性」咨询或私有化交付，是六派里最值得提前占位的差异化方向。

### 六、json-repair 与重试：兜底层的隐性风险

最后两派是后处理路线，门槛最低，也最容易埋雷。**json-repair / partial-JSON** 用宽松解析器把畸形 JSON「修」合法：

```python
from json_repair import repair_json
raw = '{"city": "北京", "date": 2026-06-26, "tags": [销售, 财报'  # 畸形
obj = repair_json(raw)   # 静默修成 {"city":"北京","date":"2026-06-26","tags":["销售","财报"]}
# 风险: 把 {"amount": 1,000} 修成 1000(丢了千分位含义)，或把被截断的数组「补全」
# 合法了，但可能不是模型原本要表达的值——静默篡改
```

它的风险是**静默篡改**：修复器会「猜测」缺失的引号、括号、分隔符，修出来的值可能偏离模型原意，且全程无报错、无可观测信号——这正好和「回放失真」「工具结果静默截断」是一类病：**错误被吞掉，而不是被暴露。**

**失败重试**最朴素：解析失败就把 ValidationError 喂回模型重来。

```python
for attempt in range(3):
    try:
        return schema.parse(model.call(messages))
    except ValidationError as e:
        messages.append({"role": "user", "content": f"格式错误：{e}"})
# 硬例上每次失败 token 翻倍累加（历史越来越长），指数膨胀
```

简单场景有效，但 token 成本随失败次数线性甚至指数膨胀，且和「预算熔断」「循环二次方」问题叠加时会烧穿预算。**优点**：零基建、任何模型可用、可观测（失败可见）。**缺点**：json-repair 静默篡改、重试 token 爆炸、都治标不治本。**变现评估**：这两派不构成独立产品，只能做训练营里「兜底与可观测」章节，但必须强调——**兜底层必须有失败计数与篡改告警，否则就是把错误藏进抽屉。**

## 强制层架构与决策图

```mermaid
flowchart TD
    Q[模型生成函数调用] --> D{在何处施加结构约束?}
    D -->|生成前: 提示层| P[把 schema 写进 prompt<br/>best-effort ~90-95%]
    D -->|生成中: 解码层| M[token 级掩码]
    D -->|生成后: 后处理层| R[修复 / 重试]
    M --> M1[XGrammar / Outlines<br/>语法100%]
    M --> M2[DCCD 先草稿后约束]
    M1 --> T1[✅ 语法合规<br/>❌ 必填字段逼编造]
    M2 --> T2[✅ 语法合规<br/>✅ 语义忠实 +24%]
    P --> T3[⚠️ 语法 best-effort<br/>✅ 语义自由]
    R --> T4[✅ 兜底合规<br/>❌ 静默篡改 / token 爆炸]
    T1 -.合规幻觉.-> RISK[下游静默错误<br/>最难排查]
    T4 -.不可观测.-> RISK
    M2 -.双高.-> SAFE[可上线]
```

横评的本质可以浓缩成一张「三轴权衡」：**语法保证 × 语义忠实 × 延迟代价**。没有任何一派能三项全拿——掩码派拿语法牺牲语义，DCCD 拿语法语义牺牲延迟，修复派拿合规牺牲可观测性。选型的第一步永远是先回答「我更怕解析失败，还是更怕合规的幻觉」。

## 推荐方案（按场景）

**1. 调用闭源 API + schema 简单** → OpenAI Strict。但务必把可选字段改成 `anyOf: [type, null]`，给模型「合法说不知道」的出口，从根上切断编造动机。这是单点 ROI 最高的改动。

**2. 多工具循环 / 批量调用** → Anthropic 程序化工具调用。卖点是可量化的 token 与趟数下降，适合 ETL、批量检索、RPA 类智能体。配套上代码沙箱即可。

**3. 自托管开源模型** → XGrammar/Outlines 掩码 + 提示层 schema 描述双保险（官方推荐）。上线前必测吞吐回归，并接 Schema 漂移与结果截断的告警，否则掩码会掩盖上游故障。

**4. 复杂 schema / 推理类 / 语义即命脉** → DCCD 草稿后约束。当前认知度低、技术门槛高，却是唯一解「合规幻觉」的路线，适合高客单价私有化交付，提前占位。

**5. 任何路线的兜底** → json-repair + 受控重试，但**必须**加失败计数、篡改采样、预算熔断三件套。兜底层是可观测的最后一道闸，不是藏错误的地方。

一句话总结横评：**2026 年别再问「能不能保证合法 JSON」——这题六派都过了 95 分。真正该问的是「合法的值，是不是模型真想说的」。** 把这句话贴在每一个结构化输出 PR 的 review 模板里，比任何 schema 校验都值钱。

## 参考来源

1. [Generating Structured Outputs from Language Models: Benchmark and Studies (arXiv 2501.10868)](https://arxiv.org/html/2501.10868v1) — 结构化生成基准，量化各强制方式的合规与忠实度差异。
2. [The Hidden Cost of Structure: How Constrained Decoding Affects Language Models (RANLP 2025)](https://acl-bg.org/proceedings/2025/RANLP%202025/pdf/2025.ranlp-1.124.pdf) — 揭示约束解码的语义损伤，本文「合规幻觉」的核心依据。
3. [Draft-Conditioned Constrained Decoding for Structured Generation (ICML 2026)](https://icml.cc/virtual/2026/poster/62339) — DCCD 草稿后约束，报告结构化准确率最高 +24%。
4. [Introducing Advanced Tool Use on the Claude Developer Platform (Anthropic)](https://www.anthropic.com/engineering/advanced-tool-use) — 程序化工具调用，N 趟推理折叠为 1 趟。
5. [LLM Tool Use Patterns 2025 — Programmatic Calling 与约束解码对比 (Zylos Research)](https://zylos.ai/research/llm-tool-use-patterns-2025/) — 程序化工具调用省 37% token、少 19+ 趟推理的量化来源。
6. [Berkeley Function Calling Leaderboard (BFCL) V4](https://gorilla.cs.berkeley.edu/leaderboard.html) — 函数调用与 agentic 评测的标准基准，schema 合规/幻觉评测口径来源。
7. [XGrammar: Flexible and Efficient Structured Generation (arXiv 2411.15100 / GitHub)](https://github.com/mlc-ai/xgrammar) — CFG 约束解码实现，含「prompt 也要描述输出结构」的官方建议。

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
