跳到主要内容

SGLang 结构化输出

🧠 SGLang 的结构化输出不是“在提示词里要求返回 JSON”,而是在解码阶段约束下一个 token 的合法集合,让输出天然满足 JSON Schema、正则表达式、枚举或语法规则。它解决的是“格式可靠性”,不是“事实正确性”。

先区分三个容易混淆的概念

概念约束发生在哪里保证什么
提示词要求 JSON自然语言指令仅提高概率,不保证合法
JSON Mode模型/API 解码通常保证合法 JSON,不保证字段
Constrained Decoding逐 token 解码保证满足 Schema / Regex / Grammar

SGLang 属于第三类:运行时根据当前已生成前缀计算合法 token,并屏蔽不合法 token。


为什么需要 SGL

  • 可解析:输出稳定成机器可读格式(JSON/YAML/CSV/Markdown 表格)。
  • 可验证:能做自动校验(缺字段、类型不符、超长、非法枚举值)。
  • 可复用:相同任务在不同项目/团队中重复使用,降低提示工程成本。
  • 可组合:复杂任务拆成多个结构化子任务,最后拼装成一份交付物。
  • 更安全:通过"只允许在限定字段里回答"等约束,减少越界内容与幻觉。

典型应用场景

  1. 信息抽取
  2. 内容生产
  3. 代码与配置
  4. 对话型工作流

一个最小 SGL 示例(JSON 结构输出)

目标:让模型输出"读书笔记"且可解析。

你将输出严格的 JSON(不要包含多余文字、不要使用 Markdown)。
JSON Schema(概念性):
{
"title": string,
"author": string | null,
"summary": string,
"key_points": string[3..7],
"action_items": { "item": string, "why": string }[0..5]
}

约束:
- key_points 至少 3 条,最多 7 条
- 如果无法确定作者,author = null
- 不要编造书中不存在的内容;不确定则在 summary 中说明不确定点

输入:
《XXXX》全文/节选如下:…

设计 SGL 的实用原则(Checklist)

  • 先定"消费方式":输出给人看还是给程序用?决定用 Markdown 还是 JSON。
  • 先定 Schema,再写提示:字段名、类型、枚举、必填项优先。
  • 明确错误处理:缺信息时填 null / 空数组 / 给出 unknown_reason 字段。
  • 减少自由文本范围:把自由发挥限制在少数字段里(如 summary),其他字段尽量结构化。
  • 加示例(Few-shot):给 1 个正例往往比加 10 条规则更有效。
  • 分步生成:复杂输出分两步:先生成结构/大纲,再填充内容。

在 Notion 里的用法建议

  • 数据库属性承接结构化字段(例如:状态、标签、负责人、日期)。
  • 用页面正文承接长文本(例如:摘要、正文、附录)。
  • 对于固定格式输出,优先用"模板按钮/数据库模板"配合 SGL 生成,减少人工整理。

可直接复用的 SGL 模板(可复制)

1) 会议纪要 → 行动项抽取(JSON)

输出严格 JSON,不要额外文字:
{
"meeting_title": string,
"date": "YYYY-MM-DD" | null,
"decisions": string[],
"action_items": [
{ "owner": string | null, "task": string, "due": "YYYY-MM-DD" | null }
],
"risks": string[]
}

规则:
- 只根据输入内容,不要推测
- owner 不明确则为 null

输入如下:
{{MEETING_NOTES}}

2) 文章/文档 → 摘要卡片(Markdown 固定结构)

请按以下 Markdown 结构输出(不要改标题名):

## 一句话结论


## 关键要点(3-5条)
1. …
2. …
3. …

## 适用场景
- …

## 不适用/风险
- …

输入文档:
{{DOC}}

相关概念对照

  • Prompt Template:提示模板(SGL 的载体之一)。
  • Schema / JSON Schema:结构定义(SGL 的核心)。
  • Guardrails:约束与防护栏(类型、枚举、长度、来源要求等)。
  • Function calling / Tools:把输出对接到可执行动作(常与 SGL 搭配)。
  • Structured Output:结构化输出(SGL 目标)。

解码时发生了什么

以 JSON Schema 为例,运行时会把 Schema 编译为可识别的约束状态。每生成一个 token,就根据当前前缀判断下一步允许出现的 token,并对其他 token 施加屏蔽;生成结束后,结果天然满足语法约束。

这带来三个工程影响:

  • 首次请求可能有编译开销:复杂 Schema 可做缓存或预热。
  • 约束越复杂,解码开销越高:避免超深嵌套和巨型枚举。
  • 语法正确不等于语义正确:日期可以是字符串但并非真实日期,引用 ID 可以合法但并不存在。

SGLang 实践模式

JSON Schema

适合 API 数据、信息抽取和工具参数。应设置必填字段、枚举、数组长度与 additionalProperties: false

Regex

适合短小、规则稳定的格式,例如版本号、工单号、固定编码。不要用超复杂正则模拟完整 JSON。

Choices / Enum

适合分类和路由。直接限制在候选集合内,比让模型自由生成后再模糊匹配更稳定。

Grammar

适合 SQL 子集、DSL 或代码骨架。语法范围越窄,越容易验证和安全执行。

失败处理

  1. 先区分约束编译失败生成中断业务校验失败
  2. Schema 版本化,并把版本与输出一起记录。
  3. 对超时或服务错误做有限重试;对业务错误不要原样重试。
  4. 对工具参数执行二次鉴权和业务校验,绝不因 Schema 合法就直接执行。
  5. 监控结构成功率、业务校验通过率、首 token 延迟和约束缓存命中率。

选型建议

  • 只给人阅读:Markdown 模板通常足够。
  • 下游程序消费:优先 JSON Schema。
  • 固定标签分类:使用 choices / enum。
  • 有执行风险的 DSL:Grammar + 解析器 + 沙箱。
  • 跨模型兼容:将 Schema 和业务校验放在应用层统一管理。

检查清单

  • Schema 能表达真正的业务约束
  • 缺失值有 null / 空数组等明确语义
  • 禁止未声明字段
  • 输出进入业务前再次校验
  • Schema 与 Prompt 都有版本号
  • 有拒绝、截断、超时和重试策略
  • 不把“格式正确”误认为“内容可信”