预计阅读 7 分钟

快速上手:5 分钟跑通第一个请求

谁该读这一篇? 装好了 GPU 环境,想立刻让 SGLang 跑起来、发一个请求看到 token 流出来的工程师。 前置阅读: 02-architecture.md 看个鸟瞰图就行。 耗时: 25 分钟(含下载小模型时间) 学完能: 1. 装好 SGLang 并用最小命令起 server; 2. 用 curl 和 openai SDK 发一个请求看到流式输出; 3. 看懂启动日志里"我开了什么"(attention backend、CUDA Graph、kv pool 等); 4. 切换到前端 DSL 模式,写出第一个三行 DSL 程序; 5. 知道每一步出问题该去哪儿排查。


1. 环境要求(cheatsheet)

要求
OS Linux(Ubuntu 22.04 / 24.04 验证最稳)
GPU NVIDIA Compute Capability ≥ 8.0(A100 / H100 / H200 / L4 / L40 / RTX 4090 / RTX 5090 等)
CUDA 12.4 / 12.6 / 12.8(看官方 release notes 的精确支持矩阵)
Python 3.10 / 3.11 / 3.12
显存 跑 Qwen2.5-7B fp16 至少 24 GB;fp8 至少 12 GB
网络 第一次需要从 HuggingFace 下模型,~15 GB 起

⚠️ macOS / AMD GPU 当前都是实验级支持,不建议第一次上手就走这条路。


2. 装 SGLang(uv 推荐)

# 1) 装 uv(如果还没有)
curl -LsSf https://astral.sh/uv/install.sh | sh

# 2) 建一个干净 venv
mkdir sglang-play && cd sglang-play
uv venv --python 3.11
source .venv/bin/activate

# 3) 装 sglang(含 srt 后端)
uv pip install "sglang[all]" --upgrade

想从源码装(开发用):git clone https://github.com/sgl-project/sglang && cd sglang/python && uv pip install -e .[all]

验证装好了

python -m sglang.check_env

会输出 CUDA / driver / FlashInfer / Triton 等的版本和 OK/FAIL。 如果某项 FAIL,先 fix 它再继续——后面出问题大概率就是这里没过。


3. 起 server(最小命令)

第一次先用最小的开源模型 + 小显存设置,确保链路通:

python -m sglang.launch_server \
    --model-path Qwen/Qwen2.5-0.5B-Instruct \
    --host 0.0.0.0 \
    --port 30000 \
    --mem-fraction-static 0.5

--mem-fraction-static 0.5 表示只用 50% GPU 显存给 KV cache + 模型,第一次玩留余量。

启动日志关键行(教你看日志)

INFO ... server_args=ServerArgs(...)            ← 全部启动参数
INFO ... Attention backend not specified.        ← 自动选了 attention 后端
       Use ... backend by default.
INFO ... Init torch distributed begin.           ← 单卡也会建 process group
INFO ... Memory pool end. avail mem=XX.X GB      ← KV pool 留多少显存
INFO ... Use cuda graph for decoding mode.       ← CUDA Graph 开启了
INFO ... Capture cuda graph begin. ...           ← 在录 CUDA Graph
INFO ... Capture cuda graph end. ...             ← 录完,启动完成
INFO ... Application startup complete.
INFO ... The server is fired up and ready to roll!

看到 "ready to roll" 就稳了。


4. 用 curl 发第一个请求

curl http://localhost:30000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2.5-0.5B-Instruct",
    "messages": [{"role": "user", "content": "1+1 等于几?"}],
    "max_tokens": 32
  }'

正常返回:

{
  "id": "...",
  "model": "Qwen/Qwen2.5-0.5B-Instruct",
  "choices": [{
    "index": 0,
    "message": {"role": "assistant", "content": "1+1=2。"},
    "finish_reason": "stop"
  }],
  "usage": {"prompt_tokens": ..., "completion_tokens": ...}
}

5. 流式输出(SSE)

curl -N http://localhost:30000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen2.5-0.5B-Instruct",
    "messages": [{"role": "user", "content": "讲一个短笑话"}],
    "stream": true
  }'

会看到一行行 data: {"choices":[{"delta":{"content":"..."}}]} 实时打印,最后是 data: [DONE]

这就是 02-architecture.md §4 时序图最后那段。


6. 用 openai SDK 接

from openai import OpenAI

client = OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")

# 非流式
resp = client.chat.completions.create(
    model="Qwen/Qwen2.5-0.5B-Instruct",
    messages=[{"role": "user", "content": "1+1?"}],
    max_tokens=32,
)
print(resp.choices[0].message.content)

# 流式
stream = client.chat.completions.create(
    model="Qwen/Qwen2.5-0.5B-Instruct",
    messages=[{"role": "user", "content": "说三个颜色"}],
    stream=True,
    max_tokens=64,
)
for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)
print()

如果你的客户端已经接的是 OpenAI / Anthropic / Together 等,改 base_url 就能直接转过来


7. 第一个 SGLang DSL 程序

import sglang as sgl

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

@sgl.function
def hello(s, name):
    s += "User: 你好,我叫 " + name + ",请用一句话欢迎我。\nAssistant: "
    s += sgl.gen("reply", max_tokens=64, stop="\n")

state = hello.run(name="Zoe")
print(state["reply"])

跑一次。然后试这个:

@sgl.function
def multi_choice(s, q):
    s += f"问题:{q}\n答案是:"
    s += sgl.select("ans", choices=["A", "B", "C", "D"])

print(multi_choice.run(q="天空是什么颜色?A.红 B.蓝 C.绿 D.黄")["ans"])

sgl.select 让 LLM 在 4 个选项里挑一个——这是 vLLM API 做不到的,因为它需要前端跟运行时商量"我只想要这 4 个 token 序列里命中最长的"。


8. 看看刚才发生了什么(Metrics)

curl http://localhost:30000/metrics | head -50

会看到 Prometheus 格式的指标:

sglang:num_requests_total{...} 5
sglang:num_input_tokens_total{...} 42
sglang:num_output_tokens_total{...} 137
sglang:e2e_request_latency_seconds_bucket{le="0.05",...} 2
sglang:e2e_request_latency_seconds_bucket{le="0.1",...} 5
sglang:gen_throughput{...} 23.4
sglang:cache_hit_rate{...} 0.62          ← 重要:前缀命中率
...

cache_hit_rate 是 SGLang 最该盯的指标。后续 08-production-deployment/03-monitoring.md 会展开。


9. 当事情不对劲(排查 cheatsheet)

现象 第一步排查
pip install 拉不下 sglang 换源 --index-url https://pypi.tuna.tsinghua.edu.cn/simple
python -m sglang.check_env 报 CUDA 错 nvidia-smi 驱动版本;CUDA toolkit 是否在 PATH
起 server 卡在 "Init torch distributed" 检查 NCCL 端口是否被占;unset NCCL_* 试试
起 server 报 CUDA OOM --mem-fraction-static--max-running-requests,或换更小模型
起 server 后 curl timeout 检查 --host 0.0.0.0 是否设置;防火墙
起 server 巨慢(> 5 分钟) 第一次拉模型;之后会缓存在 ~/.cache/huggingface
输出乱码 tokenizer 不对;确认 --model-path 是个 Instruct 模型;检查 tokenizer 文件完整
输出截断 max_tokens 太小、或停止符匹配错
TTFT 很慢 cache_hit_rate 低;CUDA Graph 没开;试 --enable-cuda-graph
TPOT 很慢 检查 batch 大小、attention backend、量化是否开

详细排障手册见 08-production-deployment/05-incident-playbook.md


10. 常用启动参数(速查)

python -m sglang.launch_server --help | head -50   # 完整列表

最常用的 10 个:

参数 含义
--model-path HF repo id 或本地路径
--port HTTP 端口(默认 30000)
--host 监听 host(默认 127.0.0.1,远程访问要改 0.0.0.0)
--tp tensor parallel size
--dp data parallel size(多副本同进程组)
--mem-fraction-static 静态显存占比上限
--max-running-requests 同时 in-flight 请求数
--max-total-tokens KV pool 总 token 上限
--attention-backend flashinfer / triton / torch
--quantization fp8 / awq / gptq / marlin / ...
--log-level debug / info / warning
--enable-metrics 暴露 Prometheus /metrics

参数完整定义看 server_args.py


11. 关掉 server

# Ctrl-C 优雅退出(会等当前请求结束)
# 或者
pkill -f sglang.launch_server

⚠️ 如果用了 --tp > 1,要确认所有 scheduler 子进程都退了,否则下次启动会端口/显存冲突。 08-production-deployment/05-incident-playbook.md 里专门有"残留进程清理"小节。


12. 下一步该读哪章

跟着你的目的走:

你接下来想
系统学完整本书 02-core-concepts/01-radix-attention.md 开始
立刻写一个生产服务 08-production-deployment/01-docker.md
跑 benchmark 出真实数字 07-hands-on/02-benchmark-throughput.md
调试一个慢请求 07-hands-on/03-debug-scheduler.md
写复杂 agent 程序 06-frontend-language/01-dsl-walkthrough.md
接受面试官拷问 02-core-concepts/ 全部

13. 自检

  1. python -m sglang.check_env 报错 FlashInfer 没装,你怎么办?
答案 按 PyTorch + CUDA 版本装匹配版的 FlashInfer: ```bash pip install flashinfer-python -i https://flashinfer.ai/whl/cu124/torch2.5/ # 例 ``` 关键:FlashInfer 的 wheel 严格绑定 (torch_major, torch_minor, cu_major, cu_minor)。版本不匹配装上也会运行时报 symbol 找不到。 FlashInfer 缺失会 fallback 到 Triton backend(性能差 10-30%),不是致命,但生产不推荐。
  1. 我起了 server,curl 能通,但 openai SDK 报 401,可能是什么?
答案 SGLang 默认不校验 API key,但 openai SDK 要求 client 传一个非空 `api_key`。 解决:`OpenAI(base_url="http://localhost:30000/v1", api_key="EMPTY")`(任意非空字符串即可)。 如果启动了 `--api-key`,则要传匹配的 key。生产部署常用 nginx / envoy 在外层做 key 校验,SGLang 本身不做。
  1. cache_hit_rate 只有 0.05 是为什么?怎么提高?
答案 原因可能:(a) 请求间几乎没有共享 prefix(独立单轮场景,正常);(b) prompt 末尾带了 timestamp/user_id 这类每次变化的字段,让"看似相同"的请求 cache miss;(c) KV pool 太小,evict 太快;(d) 业务才上线,cache 还没沉淀。 提高方法:去掉 prompt 中的可变字段;把高频 system prompt 在启动时 warmup 一次;增 `--mem-fraction-static` 让 cache 容量大;确认没用 `--disable-radix-cache`。
  1. 我用 --mem-fraction-static 0.9 起 7B 模型反而更慢,可能原因?
答案 7B 模型只占 14 GB,0.9 把剩下都给 KV pool。问题: (a) **FlashInfer workspace** 不够(每个 wrapper 要几百 MB 到几 GB),运行时 `plan` 失败 fallback 到非优化路径。 (b) **CUDA Graph** 捕获时给多 batch size 各录一份 graph 也要显存;workspace + graph 加起来溢出,graph 失败回 eager。 (c) **OOM 边缘**触发 PyTorch 频繁同步 + 碎片整理。 一般 0.8-0.85 就够,不必拉到 0.9。
  1. sgl.select(choices=["A","B","C","D"]) 在底层走了什么路径?为什么纯 OpenAI API 实现不了同等性能?
答案 路径:(1) 把 4 个 choice 各自 tokenize;(2) 一次 prefill 拿到 prompt 末尾的 hidden state + logits;(3) 对每个 choice 算 `∑ log P(token_i | prompt + token_

14. 必备 bookmark

上游源码起点:sglang/python/sglang/launch_server.py