SGLang 上手:重复的前缀只算一次

每个请求都带同一段系统提示词,GPU 就把它重算一遍。

摘要

SGLang 用基数树缓存 KV,让相同前缀只算一次,天然适合 Agent、多轮对话和结构化输出。本文讲清它是什么、现状如何、和 vLLM 怎么选,并给出从单机启动到前端语言的上手路径。

SGLang 是什么

SGLang 是一个开源的大模型推理框架,Apache-2.0 协议,由 LMSYS 社区发起(论文作者包括 Ion Stoica、Joseph Gonzalez 等)。官方 README 现在的定位是:面向 Agent 工作负载、大规模服务和强化学习 rollout 的推理框架。

它由两部分组成:

  • 前端语言:用 Python 写"LLM 程序",里面可以有多轮调用、分支、并行和结构化输出。
  • 后端运行时:真正跑模型的推理引擎,对外提供 OpenAI 兼容接口。

绝大多数人只会用到后端:启动一个服务,用 OpenAI 的客户端去调。前端语言是进阶选项,后面再讲。

核心:RadixAttention

做过多轮对话或 Agent 的人都知道,请求之间有大量重复内容:同一段系统提示词、同一份文档、同一段对话历史。每次都重新计算这些 token 的 KV,是纯粹的浪费。

RadixAttention 的做法是把已经算过的 KV 缓存放进一棵基数树里,新请求进来,先沿着树找最长的公共前缀,命中的部分直接复用,只计算后面新增的 token。缓存满了,按 LRU 淘汰叶子节点。

另一个特色是压缩有限状态机:约束输出格式(比如必须是合法 JSON)时,它能一次跳过确定的多个 token,而不是逐个解码。

论文摘要里给出的数字是:在 Agent 控制、推理、多轮对话等任务上,吞吐最高可达当时先进推理系统的 6.4 倍。注意是"最高",而且对比的是 2023 年底的系统,别把它当成今天的日常加速比。

现在发展到哪了

截至 2026 年 10 月中旬,我查到的公开信息:

  • GitHub 约 3.7 万 star、9.6 千 fork。
  • 版本在 0.5.x 系列上快速迭代,官方安装文档的源码示例已经用到 v0.5.21。
  • 新版要求 CUDA 13,CUDA 12 的镜像和 wheel 不再发布,最后一个 CUDA 12 标签是 v0.5.19-cu129。老机器要留意。
  • 硬件覆盖很广:NVIDIA 从 A100 到 B200/GB300,AMD Instinct MI300 系列到 MI355X,Google TPU,Intel GPU 和 CPU,Apple Silicon,还有华为昇腾和摩尔线程。
  • 模型方面,项目标签里列出的有 DeepSeek、GLM、GPT-OSS、Llama、MiniMax、Qwen 等,完整兼容列表见官方 Cookbook。
  • 除了语言模型,还内置了图像/视频生成引擎 SGLang Diffusion。

可以看出,它已经不只是"前缀缓存"那个点子,而是一个覆盖多硬件、多模型的完整推理栈。

和 vLLM、TensorRT-LLM 怎么选

先说明:下面的对比来自公开的第三方文章,不是我自己的实测,具体数字强烈建议在你自己的负载上复测。

SGLang vLLM TensorRT-LLM
前缀缓存 基数树,token 级 块级哈希 本文未对比
擅长 Agent、结构化输出、重度提示词复用 高并发通用服务、混合硬件 固定 NVIDIA 集群、延迟优先
代价 迭代快,新版要求 CUDA 13 前缀重复多时缓存粒度不如基数树细 硬件绑定,灵活性差
上手难度 低 低 中(仅限 NVIDIA,调优项多)

几点判断:

  • 前缀重复多(长系统提示词、RAG 固定文档、多轮对话、Agent 反复调用):优先试 SGLang。
  • 纯通用高并发、前缀几乎不重复:两者差距不大,选团队更熟的。有第三方测试显示,Llama 3.3 70B 的 FP8 场景下两者只差几个百分点;而在 8B 小模型上,SGLang 的吞吐领先约三成。这些数字的版本和负载都没写清楚,只能当参考。
  • NVIDIA 卡固定、追求极致延迟、愿意花时间调优:TensorRT-LLM。

vLLM 的原理可以看前面写过的 PagedAttention 那篇,它们解决的是不同层面的问题:PagedAttention 管显存怎么分页,RadixAttention 管算过的结果怎么复用。

由浅入深的使用教程

第一步:安装

推荐用 uv,要求 Python 3.11+ 和 CUDA 13 环境:

bash 复制代码
pip install --upgrade pip
pip install uv
uv venv --python 3.12
source .venv/bin/activate
uv pip install --prerelease=allow sglang

--prerelease=allow 建议保留。官方文档提醒:uv 版本低于 0.12.0 时不加它,可能静默装到旧版本;0.12.0 及以上加了也无副作用。

不想折腾环境,直接用 Docker:

bash 复制代码
docker pull lmsysorg/sglang:latest

docker run -it --gpus all \
  --shm-size 32g \
  -p 30000:30000 \
  -v "$HOME/.cache/huggingface:/root/.cache/huggingface" \
  --ipc=host \
  lmsysorg/sglang:latest bash

第二步:启动服务

在环境里执行:

bash 复制代码
sglang serve Qwen/Qwen2.5-0.5B-Instruct --host 0.0.0.0 --port 30000

不指定 --port 时默认也是 30000。官方快速上手文档里仍然能看到旧写法 python3 -m sglang.launch_server --model-path ...,旧写法仍可用,安装文档现在用的是 sglang serve。先用小模型跑通,再换大的。

第三步:像调用 OpenAI 一样调用

bash 复制代码
curl -s http://localhost:30000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model": "Qwen/Qwen2.5-0.5B-Instruct",
       "messages": [{"role": "user", "content": "法国的首都是哪里?"}]}'

用 Python 客户端也一样,只要改 base_url:

python 复制代码
import openai

client = openai.Client(base_url="http://127.0.0.1:30000/v1", api_key="None")

response = client.chat.completions.create(
    model="Qwen/Qwen2.5-0.5B-Instruct",
    messages=[{"role": "user", "content": "列出三个国家和它们的首都"}],
    temperature=0,
    max_tokens=64,
)
print(response.choices[0].message.content)

到这里,你已经可以把原来调用 OpenAI 的代码无缝切到自己的服务上。

第四步:让前缀缓存真正起作用

RadixAttention 默认就是开着的,但它只复用逐 token 完全一致的前缀 ,从第一个不同的 token 开始,后面都要重算。写提示词时记住一条:固定的内容放前面,变化的内容放后面。

python 复制代码
SYSTEM = "你是一名严谨的代码审查员......(一大段固定规则)"

for diff in diffs:
    client.chat.completions.create(
        model="Qwen/Qwen2.5-0.5B-Instruct",
        messages=[
            {"role": "system", "content": SYSTEM},   # 固定前缀,只算一次
            {"role": "user", "content": diff},        # 每次不同
        ],
    )

反过来,把当前时间或请求编号放在系统提示词开头,会让每个请求的前缀都不同,缓存全部失效。这是最常见的踩坑。

第五步:结构化输出

要让模型稳定输出 JSON,可以用 OpenAI 风格的 response_format 传入 JSON Schema:

python 复制代码
schema = {
    "type": "object",
    "properties": {
        "city": {"type": "string"},
        "population": {"type": "integer"},
    },
    "required": ["city", "population"],
}

resp = client.chat.completions.create(
    model="Qwen/Qwen2.5-0.5B-Instruct",
    messages=[{"role": "user", "content": "给出巴黎的名称和大致人口"}],
    response_format={
        "type": "json_schema",
        "json_schema": {"name": "city_info", "schema": schema},
    },
)
print(resp.choices[0].message.content)

解码过程会被约束在这个 Schema 内(默认用 XGrammar 后端),格式错误基本消失;但如果 max_tokens 太小导致输出被截断,JSON 仍可能不完整,兜底校验别全删。

第六步:多卡与显存调优

模型一张卡放不下时,用张量并行:

bash 复制代码
sglang serve <模型> --tp 2 --port 30000

如果启动时报显存不足,可以调低静态显存占比:

bash 复制代码
sglang serve <模型> --mem-fraction-static 0.8

这两个参数的具体含义和默认值,随版本会有变化,以 sglang serve --help 的输出为准。

第七步:前端语言(进阶)

当你的逻辑不是"一问一答",而是多步骤、带分支和并行时,前端语言会比手写循环更清晰:

python 复制代码
import sglang as sgl

sgl.set_default_backend(sgl.RuntimeEndpoint("http://localhost:30000"))

@sgl.function
def tip_suggestion(s, topic):
    s += sgl.user(f"给我三条关于{topic}的建议")
    s += sgl.assistant(sgl.gen("tips", max_tokens=128))
    forks = s.fork(2)
    for i, f in enumerate(forks):
        f += sgl.user(f"把第 {i + 1} 条建议展开成一段话")
        f += sgl.assistant(sgl.gen("detail", max_tokens=128))
    # 分支结果不会自动合并,要按下标取回,拼进主线
    s += sgl.user(
        "第 1 条展开:" + forks[0]["detail"] + "\n"
        + "第 2 条展开:" + forks[1]["detail"] + "\n"
        + "总结以上内容"
    )
    s += sgl.assistant(sgl.gen("summary", max_tokens=64))

state = tip_suggestion.run(topic="学习 Python")
print(state["summary"])

fork 出来的分支共享同一个前缀,RadixAttention 会让这部分只算一次;分支各自生成的结果要像上面这样用 forks[i]["detail"] 取回,主线才能看到。这就是前端语言和后端运行时联合设计的价值。

适合谁

  • 在做 Agent、RAG、多轮对话,提示词里有大段固定内容的开发者。
  • 需要稳定结构化输出的业务(抽取、分类、工具调用)。
  • 要在非 NVIDIA 硬件(AMD、昇腾等)上做推理的团队。

不太适合:只想要最省事的单模型 demo,Ollama 之类的本地工具更轻;也不适合 CUDA 12 环境又不想升级的机器。

速查清单

  1. 环境:Python 3.11+、CUDA 13,uv pip install --prerelease=allow sglang。
  2. 启动:sglang serve <模型> --port 30000,接口是 OpenAI 兼容的 /v1。
  3. 提速:固定内容放前面,变化内容放后面,别在开头塞时间戳。
  4. 结构化:用 response_format 传 JSON Schema。
  5. 多卡:--tp N;显存紧张调 --mem-fraction-static。
  6. 选型:前缀重复多选 SGLang,其余在自己的负载上跑一遍再定。

你现在的服务里,每个请求开头有多少 token 是完全一样的?

相关推荐
燕落南枝1 小时前
HTML 表格标签与 AI 合并单元格实战指南
前端·人工智能·html
遇码1 小时前
不用转场引擎做幻灯片转场:相机滑动、黑场淡入与真全屏的完整做法
人工智能·数码相机·ai·rust·大模型·agent
CoderIsArt1 小时前
使用 Ultralytics YOLO 进行模型训练
人工智能·深度学习·yolo
人工智能培训1 小时前
具身智能环境交互与学习范式原理
大数据·linux·人工智能·学习·算法·机器学习
一线数智1 小时前
敛海智库亮相26届工博会制造业AI场景应用生态大会以结构式融合思维推动AI工业落地
人工智能
云和数据.ChenGuang1 小时前
Golang AI 工程师路线图:从入门到实战
开发语言·人工智能·后端·golang
zyseo81 小时前
谷歌SEO 内链地图脚本:Python 画出权重分发,揪出孤岛页
java·前端·python
破无差1 小时前
精武会徽turtle实现
python