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 表格)。
- 可验证:能做自动校验(缺字段、类型不符、超长、非法枚举值)。
- 可复用:相同任务在不同项目/团队中重复使用,降低提示工程成本。
- 可组合:复杂任务拆成多个结构化子任务,最后拼装成一份交付物。
- 更安全:通过"只允许在限定字段里回答"等约束,减少越界内容与幻觉。
典型应用场景
- 信息抽取
- 内容生产
- 代码与配置
- 对话型工作流
一个最小 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 或代码骨架。语法范围越窄,越容易验证和安全执行。
失败处理
- 先区分约束编译失败、生成中断、业务校验失败。
- Schema 版本化,并把版本与输出一起记录。
- 对超时或服务错误做有限重试;对业务错误不要原样重试。
- 对工具参数执行二次鉴权和业务校验,绝不因 Schema 合法就直接执行。
- 监控结构成功率、业务校验通过率、首 token 延迟和约束缓存命中率。
选型建议
- 只给人阅读:Markdown 模板通常足够。
- 下游程序消费:优先 JSON Schema。
- 固定标签分类:使用 choices / enum。
- 有执行风险的 DSL:Grammar + 解析器 + 沙箱。
- 跨模型兼容:将 Schema 和业务校验放在应用层统一管理。
检查清单
- Schema 能表达真正的业务约束
- 缺失值有
null/ 空数组等明确语义 - 禁止未声明字段
- 输出进入业务前再次校验
- Schema 与 Prompt 都有版本号
- 有拒绝、截断、超时和重试策略
- 不把“格式正确”误认为“内容可信”