Skip to content

SGLang 结构生成语言

五层读懂一个词。这次拆的是:SGLang--vLLM 之外最值得关注的新锐推理引擎。两大杀手锏:RadixAttention(用 Radix Tree 做前缀缓存,自动复用任意共享前缀)和 Structured Generation(用正则/JSON Schema 约束输出,零幻觉的格式生成)。不是「另一个 vLLM」,而是用不同的方法解决了 vLLM 的一些盲区。


L1 · 一句话点破

SGLang = RadixAttention(树状前缀缓存)+ Structured Generation(约束生成)+ 高效推理引擎。RadixAttention 用 Radix Tree 自动管理所有请求的前缀缓存(不仅 system prompt,任意公共前缀都复用);Structured Generation 用 FSM(有限状态机)约束 LLM 输出严格符合 JSON/regex 格式。是 vLLM 之外最有差异化价值的推理引擎——更智能的前缀复用 + 零幻觉的格式输出。


L2 · 通俗类比

vLLM 的前缀缓存(Prefix Caching)像停车场 VIP 专用道

  • 只有 system prompt 这条路能共享
  • 其他路(用户消息等)即使相同也不能复用
  • 规则固定,不够灵活

SGLang 的 RadixAttention 像「自动拼车系统」

  • 用一棵 Radix Tree(基数树)管理所有请求的前缀
  • 任何公共前缀自动识别和共享
  • 新请求进来,系统自动匹配已有前缀,只算不同的部分

类比

  • vLLM:只允许「同一个人的 system prompt」拼车
  • SGLang:任何路线重叠的部分都能自动拼车,不需要人工指定

Structured Generation 像「填空题」而非「作文」

  • 普通 LLM 输出:自由文本("天气是晴天,温度 25°C")→ 要解析
  • SGLang 约束输出:{"weather": "晴天", "temperature": 25} → 直接可用
  • 模型不会输出格式错误的内容(被 FSM 阻止)

SGLang 的独特组合

技术vLLMSGLang
前缀缓存Hash-based(system prompt)Radix Tree(任意前缀)
结构化生成不支持(后处理)原生 FSM 约束
编程模型Python APISGLang DSL + Python
Overlap Scheduling✅(通信-计算重叠)

代价

  • 社区和生态比 vLLM 小
  • Radix Tree 有一定内存开销
  • 某些场景的绝对吞吐可能低于 vLLM
  • 模型支持范围和插件生态小于 vLLM

适用

  • 需要严格格式输出的 API(JSON 响应)
  • 大量请求有公共前缀的场景(共享文档/上下文)
  • 批量处理同构问题(同 prompt 模板,不同 input)
  • 函数调用/结构化数据提取

L3 · 正经定义

SGLang(Structured Generation Language):由斯坦福、UC Berkeley 等(Zheng et al., 2023)提出的 LLM 推理与服务框架。核心创新:

  1. RadixAttention:用 Radix Tree(基数树)自动管理多请求的前缀共享,任意公共序列的 KV-Cache 被自动复用,不仅限于 system prompt。
  2. Structured Generation:用 FSM(有限状态机)约束 LLM 输出,严格符合 JSON/regex/任意文法,消除格式错误。
  3. SGLang DSL:一种嵌入 Python 的领域特定语言,用于表达 LLM 调用的控制流(并行、分支、循环、工具调用)。

参考资料


L4 · 原理深挖

4.1 RadixAttention: 树状前缀缓存

vLLM Prefix Caching 的局限

请求 A: [system_prompt, "讲一个故事关于猫"]
请求 B: [system_prompt, "讲一个故事关于狗"]

vLLM: 只有 system_prompt 共享 KV-Cache
       "讲一个故事关于" 这部分公共前缀不共享,重复计算

RadixAttention 的解决

用 Radix Tree(基数树/压缩前缀树)管理所有请求的前缀:

Radix Tree:
  Root
   ├─ [system_prompt] ──> (共享 KV-Cache)
   │    ├─ ["讲一个故事关于猫"] ──> (生成 "从前有只猫...")
   │    └─ ["讲一个故事关于狗"] ──> (生成 "小狗叫旺财...")
   └─ [other_prompt] ──> (独立分支)

自动匹配流程

新请求: [system_prompt, "讲一个故事关于", "龙"]

1. Radix Tree 查找最长公共前缀:
   匹配: [system_prompt, "讲一个故事关于"]  (现有 KV-Cache)
   
2. 只计算未匹配部分 ("龙") 的 prefill KV-Cache

3. 将 "龙" 节点的 KV-Cache 挂到 Radix Tree 上
   后续有相同前缀的请求自动复用

与 vLLM 前缀缓存的对比

维度vLLM Prefix CachingSGLang RadixAttention
数据结构Hash 表Radix Tree
共享粒度完整 system prompt任意前缀
自动匹配否(需显式标记)是(自动)
内存开销略高(树结构)
适用场景system prompt所有公共前缀

效果(few-shot 提示场景):

20 个请求共享 100-token 的 few-shot 示例前缀:

  • vLLM:不共享(非 system prompt),20× 计算前缀
  • SGLang:自动共享,只算 1× 前缀

节省 95% 的前缀计算。

4.2 Structured Generation: FSM 约束

问题:LLM 输出 JSON 时,可能格式错误:

期望: {"name": "张三", "age": 30}
实际: {"name": "张三, "age": 30}  # 漏引号
实际: The answer is {"name": "张三"}...  # 多余文本
实际: {"name": "张三", "age": -5}  # 逻辑错但不是格式错

传统解决

  1. Prompt 工程:在 prompt 里强调格式(不可靠)
  2. 重试:格式错就重试(浪费 token)
  3. 后处理:解析失败就 fallback(不优雅)

SGLang 的解决:用有限状态机(FSM)约束生成过程。

原理

JSON Schema: {"name": str, "age": int}

FSM 状态:
  Start -> "{" -> "name" -> ":" -> str_value -> "," -> "age" -> ":" -> int_value -> "}" -> End

每个状态只允许特定的 next token:
  状态 "{" -> 只能输出  "name"
  状态 str_value -> 只能输出字母/中文/转义符
  状态 int_value -> 只能输出数字

LLM 在每步生成时:
  logits -> 筛选允许的 tokens -> softmax -> sample
  不允许的 token 概率置零

效果

  • 100% 格式正确(格式层面,不是语义层面)
  • 不需要重试
  • 不需要后处理解析

支持的正则式约束

python
import sglang as sgl

@sgl.function
def extract_city(s, text):
    s += "从文本提取城市: " + text
    s += sgl.gen("city", regex=r"(北京|上海|广州|深圳|杭州|成都)")

@sgl.function  
def json_output(s, text):
    s += "提取人物信息: " + text
    s += sgl.gen("person", 
        json_schema={
            "type": "object",
            "properties": {
                "name": {"type": "string"},
                "age": {"type": "integer"},
                "city": {"type": "string", "enum": ["北京", "上海"]}
            },
            "required": ["name", "age"]
        }
    )

FSM 跳转

  • JSON Schema 自动转化为 FSM
  • FSM 在每步 token 生成时筛选词汇表
  • 支持嵌套对象、数组、union type、enum、regex

4.3 SGLang DSL: 嵌入 Python 的领域语言

核心理念:把 LLM 调用的控制流(并行、分支、循环)表达为 Python 代码。

示例 1: 并行生成多个候选

python
@sgl.function
def parallel_eval(s, question):
    # 并行生成 3 个候选答案
    s += "问题: " + question + "\n"
    forks = s.fork(3)
    for i, fork in enumerate(forks):
        fork += f"候选 {i+1}: " + sgl.gen(f"answer_{i}", max_tokens=100)
    forks.join()
    # 评分选最佳
    s += "最佳答案: " + sgl.gen("best", max_tokens=50, choices=[
        f"候选1: {forks[0]['answer_0']}",
        f"候选2: {forks[1]['answer_1']}",
        f"候选3: {forks[2]['answer_2']}",
    ])

示例 2: 分支

python
@sgl.function
def branch_on_type(s, text):
    s += "分析文本: " + text
    s += "类型: " + sgl.gen("type", choices=["新闻", "评论", "广告"])
    
    if s["type"] == "新闻":
        s += "摘要: " + sgl.gen("summary", max_tokens=100)
    elif s["type"] == "评论":
        s += "观点: " + sgl.gen("opinion", max_tokens=100)
    else:
        s += "跳过"

示例 3: 工具调用循环

python
@sgl.function
def react_loop(s, question, tools):
    s += "问题: " + question + "\n"
    for i in range(5):
        s += f"Step {i+1}:\n"
        s += "Thought: " + sgl.gen("thought", max_tokens=100)
        s += "Action: " + sgl.gen("action", choices=tools)
        # 执行工具...
        # 检查是否完成

4.4 Overlap Scheduling

通信-计算重叠

  • vLLM:TP 通信和计算串行(先通信再算,或先算再通信)
  • SGLang:通信和计算可重叠(一边传 KV块,一边算注意力)

效果:TP 场景下延时降低 10-30%。

4.5 SGLang vs vLLM

维度vLLMSGLang
前缀缓存Hash-based, 细粒度受限Radix Tree, 任意前缀
结构化生成✅ FSM 约束
编程模型Python APIDSL + Python
Overlap有限
生态/社区🔥🔥🔥🔥🔥🔥🔥
Star (2025)40k+10k+
模型支持广泛广泛(追赶中)
量化支持GPTQ/AWQ/FP8GPTQ/AWQ/FP8
文档质量

什么时候选 SGLang 而非 vLLM

  • ✅ 需要 100% 准确的 JSON/格式化输出
  • ✅ 大量请求有公共前缀(如批量同构问题)
  • ✅ 需要表达复杂调用逻辑(并行/分支/循环)
  • ✅ 追求极致前缀缓存复用率

什么时候选 vLLM 而非 SGLang

  • ✅ 需要最广泛的社区支持和模型兼容
  • ✅ 通用 API 服务(不需要结构化输出)
  • ✅ 需要 Multi-LoRA Serving
  • ✅ 小团队、需要完善文档

4.6 SGLang 的性能

Few-shot 场景(100 req × 100-token 共享前缀)

引擎前缀计算总延迟vs 基线
vLLM100×1200ms1x
SGLang200ms6x

结构化生成场景(JSON 输出)

方案格式错误率首答成功率
Prompt only15%85%
Prompt + 重试(3次)3%97%
SGLang FSM0%100%

4.7 SGLang 的局限

局限 1: 社区和生态较小。star 10k+ vs vLLM 40k+,插件/扩展/文档都不如 vLLM。

局限 2: 没有 Multi-LoRA Serving。目前不支持多 LoRA 适配器热切换。

局限 3: 对部分模型的兼容性。小众模型的适配不如 vLLM 完善。

局限 4: Radix Tree 内存开销。树结构管理有额外内存,极端场景下可能反而浪费。

局限 5: DSL 学习曲线。虽然不是强制的,但要发挥全部威力需要学 DSL。

局限 6: 版本迭代快,稳定性。活跃开发期,API 可能有 breaking change。

局限 7: 绝对吞吐在某些场景不如 vLLM。通用 API 服务场景吞吐可能略低。


L5 · 沿革与坑

5.1 沿革

  • 2023-12:SGLang 论文初稿(Zheng et al.),提出 DSL + RadixAttention
  • 2024-01:开源 release,v0.1
  • 2024 中:RadixAttention 优化,结构化生成 FSM
  • 2024-10:Overlap Scheduling、多节点支持
  • 2024-11:NeurIPS 2024 录用
  • 2025-01:SGLang v0.3,性能大幅提升,生态扩展
  • 2025:增长迅速,成为 vLLM 的主要竞争者

5.2 常见坑

坑 1: 期望 SGLang 完全替代 vLLM。在通用 API 服务场景,vLLM 仍更成熟。SGLang 优势在特定场景。

坑 2: Structured Generation 期望语义正确。FSM 保证格式,不保证语义。{"age": -5} 格式对,内容错。

坑 3: FSM 状态爆炸。复杂 JSON Schema(深层嵌套、大 enum)FSM 状态多,token 筛选慢。要简化 schema。

坑 4: Radix Tree 不释放。长期运行 Radix Tree 膨胀。要配置淘汰策略。

坑 5: DSL 过度使用。简单任务不需要 DSL。Python API 已经够用。

坑 6: 忘记指定 backend。SGLang 支持多种 backend(vLLM, TGI, HF),默认可能不是你想要的。

坑 7: RadixAttention 与 vLLM Prefix Caching 的期望差异。RadixAttention 共享任意前缀,但性能保证的是「有公共前缀时更优」,无公共前缀时和 vLLM 无差。

坑 8: 版本兼容。SGLang 依赖的 CUDA/PyTorch 版本和 vLLM 不完全相同。混装可能冲突。

坑 9: 单请求/小 batch 优势不如高并发。和 vLLM 一样,SGLang 优势在批量场景。

坑 10: FSM + Sampling 的组合temperature=0 + FSM 不错,temperature>0 + FSM 可能限制多样性(被允许的 token 子集不够大)。

5.3 面试怎么考

  1. SGLang 的两大创新? 答:RadixAttention(Radix Tree 自动管理任意前缀共享)和 Structured Generation(FSM 约束输出,零格式错误)。
  2. RadixAttention 和 vLLM Prefix Caching 的区别? 答:vLLM 用 Hash 表只缓存 system prompt;SGLang 用 Radix Tree 自动识别和复用任意公共前缀,few-shot 场景效果显著。
  3. Structured Generation 怎么做到的? 答:JSON Schema/regex 转 FSM(有限状态机),每步生成时用 FSM 筛选合法 token,不允许的 token 概率置零。格式 100% 正确。
  4. SGLang vs vLLM 怎么选? 答:需要结构化输出 / 大量同构请求 / 复杂调用逻辑 → SGLang;通用 API / 最广泛兼容 / Multi-LoRA → vLLM。
  5. SGLang DSL 解决了什么问题? 答:用 Python 代码表达 LLM 调用的控制流(fork/join 并行、if/else 分支、for 循环、工具调用),比手动管理 prompt 更高效。

速记卡

两大创新

创新方法优势
RadixAttentionRadix Tree 前缀管理任意前缀自动共享
Structured GenerationFSM 约束零格式错误

Radix Tree vs Hash Table

vLLM Hash:   只共享 system_prompt 块
SGLang Tree: 任意公共前缀自动共享

FSM 约束流程

JSON Schema → FSM → 每步筛选合法 token → 生成
结果: 100% 格式正确

SGLang DSL 模式

python
fork/join   → 并行生成多个候选
if/else     → 分支策略
for         → 循环(工具调用)
choices     → 选项约束
regex       → 正则约束
json_schema → JSON 约束

vLLM vs SGLang 选择

场景推荐
通用 API 服务vLLM
JSON 格式化输出SGLang
同构批量请求SGLang
Multi-LoRA 服务vLLM
复杂调用逻辑SGLang
最大兼容性vLLM

一句话记忆:SGLang = RadixAttention(Radix Tree 自动共享任意前缀,few-shot 场景倍数提升)+ Structured Generation(FSM 约束,JSON 格式 100% 正确)+ DSL 编程模型(fork/join 并行、分支、循环)。vLLM 是通用首选,SGLang 在结构化生成和前缀密集型场景有明显优势。10k+ star,是 vLLM 之外最值得关注的推理引擎。局限:社区较小、没有 Multi-LoRA、通用场景吞吐可能略低于 vLLM。


上一篇:vLLM 推理引擎 -- 通用推理首选,SGLang 在其盲区(结构化生成 + 智能前缀缓存)做出差异化。下一篇:Prompt Engineering 提示工程 -- 引擎负责跑得快,Prompt 负责跑得对。

内容采用 CC BY-SA 4.0,代码采用 MIT。