(十九)32天GPU测试从入门到精通-SGLang 特性与测试day17
目录
引言
SGLang 是专为结构化生成和复杂推理任务设计的 LLM 推理引擎,由 UC Berkeley 开发,在 Agent 系统、工具调用、多轮对话等场景具有独特优势。与 vLLM 追求通用高性能不同,SGLang 选择了差异化的路线:专注于解决结构化生成和多轮对话优化这两个特定问题。
掌握 SGLang 是构建高级 LLM 应用的关键。如果你的应用需要输出 JSON、SQL 或代码等结构化内容,或者需要高效处理多轮对话,SGLang 可以提供其他引擎无法比拟的优势。它的编程模型类似 Python,学习曲线平缓,易于上手。
- SGLang 与 vLLM 有什么区别? 结构化生成是核心差异
- 什么是 RadixAttention? KV Cache 复用技术
- 如何实现约束解码? JSON/SQL/代码格式约束
- 多轮对话如何优化? 上下文高效管理
- 适用哪些场景? Agent、数据提取、代码生成
这些问题都指向一个核心主题:SGLang 特性与测试。
SGLang 的核心优势
┌─────────────────────────────────────────────────┐
│ SGLang 核心优势 │
├─────────────────────────────────────────────────┤
│ │
│ 结构化生成: │
│ ├── JSON/XML 格式约束输出 │
│ ├── SQL/代码语法约束 │
│ ├── 正则表达式约束 │
│ └── 比无约束生成快 2-5x │
│ │
│ 上下文优化: │
│ ├── RadixAttention: KV Cache 树状复用 │
│ ├── 多轮对话:减少 50-70% 重复计算 │
│ ├── 长上下文:高效管理长序列 │
│ └── 批处理:动态请求合并 │
│ │
│ 编程友好: │
│ ├── Python-like DSL: 类似 Python 的语法 │
│ ├── 控制流:if/for/while 支持 │
│ ├── 函数调用:模块化设计 │
│ └── 调试友好:易于开发和测试 │
│ │
│ 性能优秀: │
│ ├── 吞吐量:与 vLLM 相当 │
│ ├── 延迟:多轮对话场景更优 │
│ └── 显存效率:RadixAttention 提升 2-3x │
│ │
└─────────────────────────────────────────────────┘
适用场景
┌─────────────────────────────────────────────────┐
│ SGLang 适用场景 │
├─────────────────────────────────────────────────┤
│ │
│ Agent 系统: │
│ ├── 工具调用:函数参数结构化输出 │
│ ├── 任务规划:步骤分解与执行 │
│ ├── 多 Agent 协作:消息格式标准化 │
│ └── 示例:AutoGen、LangChain 集成 │
│ │
│ 数据提取: │
│ ├── JSON 输出:API 响应格式化 │
│ ├── 信息抽取:实体/关系提取 │
│ ├── 文档解析:结构化数据生成 │
│ └── 示例:简历解析、合同分析 │
│ │
│ 代码生成: │
│ ├── 语法约束:有效代码生成 │
│ ├── 单元测试:测试用例生成 │
│ ├── 代码补全:IDE 集成 │
│ └── 示例:Copilot 类应用 │
│ │
│ 多轮对话: │
│ ├── 聊天机器人:上下文高效管理 │
│ ├── 客服系统:多轮问答 │
│ ├── 角色扮演:人物设定保持 │
│ └── 示例:客服助手、虚拟角色 │
│ │
│ 复杂推理: │
│ ├── Chain-of-Thought: 思维链推理 │
│ ├── Tree-of-Thought: 多路径探索 │
│ ├── 数学问题:步骤化求解 │
│ └── 示例:数学解题、逻辑推理 │
│ │
└─────────────────────────────────────────────────┘
SGLang 编程模型
SGLang 的核心价值在于其独特的编程模型。它提供了一种类似 Python 的 DSL(领域特定语言),让开发者可以用熟悉的语法编写复杂的推理流程。这种设计使得 SGLang 既强大又易用。
SGLang 的编程模型支持函数定义、参数传递、控制流(if/for/while)、以及多步推理。这使得你可以将复杂的推理任务分解为多个步骤,每个步骤可以有独立的生成参数,如 temperature、max_tokens、stop 条件等。
基础语法
基础语法示例展示了 SGLang 的最简用法。首先创建 LLM 运行时,然后定义一个函数,使用 sgl.gen 进行生成。@sgl.function 装饰器将普通 Python 函数转换为 SGLang 函数,s 参数是状态对象,用于累积生成的内容。
带参数的生成示例展示了如何传递参数给 SGLang 函数。你可以在运行时指定 temperature、max_tokens 等参数,实现灵活的生成控制。
控制流支持是 SGLang 的强大特性之一。多步推理示例展示了如何将复杂任务分解为多个步骤:分析问题、制定计划、执行计划、总结答案。每个步骤可以有独立的生成参数,使得整个推理过程更加可控。
循环与条件支持使得迭代优化成为可能。迭代优化示例展示了如何通过循环逐步改进输出,直到满足条件为止。这种模式在代码生成、文本润色等场景中非常有用。
import sglang as sgl
# 创建 LLM 运行时
llm = sgl.LLM(model="Qwen/Qwen2.5-7B-Instruct")
# 最简单的生成
@sgl.function
def simple_generate(s):
s += "请介绍一下人工智能:"
s += sgl.gen("response", max_tokens=200)
# 运行
state = simple_generate.run()
print(state["response"])
带参数的生成
#!/usr/bin/env python3
# sglang_with_params.py - 带参数的 SGLang 生成
import sglang as sgl
@sgl.function
def chat_with_params(s, question, temperature=0.7, max_tokens=500):
s += "你是一个有帮助的助手。\n"
s += f"用户问题:{question}\n"
s += "助手回答:"
s += sgl.gen(
"answer",
max_tokens=max_tokens,
temperature=temperature,
top_p=0.9,
stop=["\n用户", "\n\n"]
)
# 运行
state = chat_with_params.run(
question="什么是机器学习?",
temperature=0.5,
max_tokens=300
)
print(state["answer"])
控制流支持
#!/usr/bin/env python3
# sglang_control_flow.py - SGLang 控制流示例
import sglang as sgl
@sgl.function
def multi_step_reasoning(s, question):
"""多步推理示例"""
s += "问题:" + question + "\n"
# 第一步:分析问题
s += "步骤 1 - 分析问题:\n"
s += sgl.gen("analysis", max_tokens=100, stop="\n")
# 第二步:制定计划
s += "\n步骤 2 - 制定计划:\n"
s += sgl.gen("plan", max_tokens=150, stop="\n")
# 第三步:执行计划
s += "\n步骤 3 - 执行计划:\n"
s += sgl.gen("execution", max_tokens=200, stop="\n")
# 第四步:总结答案
s += "\n步骤 4 - 总结答案:\n"
s += sgl.gen("answer", max_tokens=150)
return s
# 运行
state = multi_step_reasoning.run(
question="如何评估一个机器学习模型的性能?"
)
print("分析:", state["analysis"])
print("计划:", state["plan"])
print("执行:", state["execution"])
print("答案:", state["answer"])
循环与条件
#!/usr/bin/env python3
# sglang_loop_cond.py - SGLang 循环与条件示例
import sglang as sgl
@sgl.function
def iterative_refinement(s, draft, max_iterations=3):
"""迭代优化示例"""
s += "初始草稿:" + draft + "\n"
for i in range(max_iterations):
s += f"\n--- 第{i+1}次优化 ---\n"
# 评估当前版本
s += "评估:"
evaluation = sgl.gen("eval", max_tokens=50, stop="\n")
s += evaluation + "\n"
# 检查是否需要继续优化
if "需要改进" not in evaluation and "改进" not in evaluation:
s += "优化完成。\n"
break
# 生成优化版本
s += "优化版本:"
s = sgl.gen("refined", max_tokens=200)
return s
# 运行
state = iterative_refinement.run(
draft="机器学习是一种让计算机从数据中学习的技术。"
)
print(state.text())
结构化生成测试
结构化生成是 SGLang 的杀手锏功能。在 Agent 系统、数据提取、API 响应等场景中,我们往往需要模型输出格式严格的内容。传统方法依靠 prompt 工程,但无法保证 100% 符合格式要求。SGLang 通过约束解码技术,从根源上解决了这个问题。
约束解码的原理是:在生成每个 token 时,只允许生成符合约束的 token。例如,生成 JSON 时,如果当前上下文要求一个字符串,就只允许生成字符串的 token。这样可以确保最终输出 100% 符合预期格式。
JSON 格式约束
JSON 格式约束示例展示了如何从文本中提取结构化信息。通过指定 JSON 模板和使用 regex 约束(r'{.*}'),可以确保输出是有效的 JSON 格式。这对于数据提取、信息抽取等场景非常有用。
SQL 查询生成示例展示了如何将自然语言转换为 SQL 查询。通过指定 SQL 约束,可以确保生成的查询语法正确,可以直接执行。这对于 BI 工具、数据分析应用很有价值。
代码生成示例展示了如何生成符合语法的代码。通过指定语言类型和 stop 条件,可以生成完整的、可执行的代码片段。这对于 IDE 插件、代码助手等应用很有用。
API 响应格式化示例展示了如何生成符合 API 规范的响应。通过指定响应模板和 JSON 约束,可以确保输出符合 API 要求,减少后处理工作。
import sglang as sgl
import json
@sgl.function
def extract_entities(s, text):
"""实体提取 - JSON 格式输出"""
s += "从以下文本中提取实体信息:\n\n"
s += text + "\n\n"
s += "请以 JSON 格式输出,包含以下字段:\n"
s += """
{
"person": [{"name": "姓名", "age": 年龄,"occupation": "职业"}],
"location": ["地点 1", "地点 2"],
"organization": ["组织 1", "组织 2"],
"date": ["日期 1", "日期 2"]
}
"""
s += "\nJSON 输出:\n"
s += sgl.gen(
"entities",
max_tokens=500,
temperature=0,
regex=r'\{.*\}' # JSON 约束
)
# 测试文本
text = """
张三,25 岁,毕业于北京大学计算机系,
现任职于腾讯公司人工智能实验室,担任高级工程师。
他于 2023 年 5 月参加了在北京举行的 AI 大会,
并在会议上发表了关于大语言模型的演讲。
"""
# 运行
state = extract_entities.run(text=text)
# 解析 JSON
try:
entities = json.loads(state["entities"])
print("提取的实体:")
print(json.dumps(entities, ensure_ascii=False, indent=2))
except json.JSONDecodeError:
print("JSON 解析失败")
print(state["entities"])
SQL 查询生成
#!/usr/bin/env python3
# sglang_sql_generation.py - SQL 查询生成
import sglang as sgl
@sgl.function
def text_to_sql(s, question, schema):
"""自然语言转 SQL 查询"""
s += "数据库架构:\n"
s += schema + "\n\n"
s += "问题:" + question + "\n\n"
s += "请生成 SQL 查询:\n"
s += sgl.gen(
"sql",
max_tokens=200,
temperature=0,
stop=[";", "\n\n"],
regex=r'SELECT.*?;' # SQL 约束
)
# 测试
schema = """
表:users
- id (INT, PRIMARY KEY)
- name (VARCHAR)
- email (VARCHAR)
- age (INT)
- city (VARCHAR)
- created_at (DATETIME)
表:orders
- id (INT, PRIMARY KEY)
- user_id (INT, FOREIGN KEY)
- amount (DECIMAL)
- status (VARCHAR)
- order_date (DATETIME)
"""
state = text_to_sql.run(
question="找出北京地区年龄大于 30 岁的用户,并显示他们的订单总数",
schema=schema
)
print("生成的 SQL:")
print(state["sql"])
代码生成
#!/usr/bin/env python3
# sglang_code_generation.py - 代码生成
import sglang as sgl
@sgl.function
def generate_function(s, description, language="python"):
"""函数代码生成"""
s += f"请用{language}语言实现以下功能:\n\n"
s += f"功能描述:{description}\n\n"
s += f"{language}代码:\n"
s += f"```{language}\n"
s += sgl.gen(
"code",
max_tokens=500,
temperature=0.2,
stop=["```", "\n\n"]
)
s += "\n```"
# 测试
state = generate_function.run(
description="实现一个快速排序算法,包含测试用例",
language="python"
)
print("生成的代码:")
print(state["code"])
API 响应格式化
#!/usr/bin/env python3
# sglang_api_response.py - API 响应格式化
import sglang as sgl
import json
@sgl.function
def format_api_response(s, user_query, context):
"""格式化 API 响应"""
s += "用户查询:" + user_query + "\n\n"
s += "上下文信息:" + context + "\n\n"
s += "请生成 API 响应,格式如下:\n"
s += """
{
"success": true/false,
"data": {
"answer": "回答内容",
"sources": ["来源 1", "来源 2"],
"confidence": 0.0-1.0
},
"error": null 或 "错误信息"
}
"""
s += "\n响应:\n"
s += sgl.gen(
"response",
max_tokens=400,
temperature=0.3,
regex=r'\{.*\}'
)
# 测试
state = format_api_response.run(
user_query="今天的天气怎么样?",
context="北京,2026-04-07,晴,温度 15-25°C"
)
response = json.loads(state["response"])
print("API 响应:")
print(json.dumps(response, ensure_ascii=False, indent=2))
RadixAttention 原理
RadixAttention 是 SGLang 的另一项核心创新,专门用于优化多轮对话场景。在多轮对话中,连续的对话轮次共享大量共同的前缀内容(如系统提示、历史对话)。传统方法会为每轮对话独立存储 KV Cache,导致大量重复存储和计算。RadixAttention 通过树状结构共享前缀,显著提升了效率。
KV Cache 复用
RadixAttention 的原理可以用一个简单例子说明。假设有三轮对话:
- 第一轮:"你是一个助手。用户:你好,请介绍一下人工智能。"
- 第二轮:"你是一个助手。用户:你好,请介绍一下机器学习。"
- 第三轮:"你是一个助手。用户:什么是深度学习?"
传统方法会为每轮独立存储完整的 KV Cache,导致"你是一个助手。用户:"这个共同前缀被存储了三次。RadixAttention 使用树状结构,将共同前缀只存储一次,每个轮次只存储差异部分。这样可以节省 40-60% 的显存,减少 50-70% 的重复计算。
实现细节包括:Radix Tree(前缀树)结构存储 KV Cache,每个节点存储 token 序列和对应的 KV Cache,引用计数管理节点生命周期,LRU 淘汰策略管理显存。
实际效果非常显著:显存效率提升 2-3 倍,计算减少 50-70%,多轮对话场景延迟降低 30-50%,批处理效率更高。
├─────────────────────────────────────────────────┤
│ │
│ 问题:传统 Attention 的 KV Cache 浪费 │
│ ├── 每个请求独立存储 KV Cache │
│ ├── 多轮对话中大量重复内容 │
│ ├── 浪费率:50-70% │
│ └── 结果:显存效率低,计算冗余 │
│ │
│ 解决:Radix Tree KV Cache 复用 │
│ ├── 树状结构存储 KV Cache │
│ ├── 共享前缀只存储一次 │
│ ├── 动态查找最长匹配前缀 │
│ └── 结果:显存效率提升 2-3x │
│ │
│ 实现细节: │
│ ├── Radix Tree: 前缀树结构 │
│ ├── Node: 存储 token 序列和 KV Cache │
│ ├── Ref Count: 引用计数管理 │
│ └── Eviction: LRU 淘汰策略 │
│ │
│ 效果: │
│ ├── 显存效率:提升 2-3x │
│ ├── 计算减少:50-70% 重复计算消除 │
│ ├── 延迟降低:多轮对话场景 30-50% │
│ └── 吞吐提升:批处理效率更高 │
│ │
└─────────────────────────────────────────────────┘
Radix Tree 可视化
┌─────────────────────────────────────────────────────────────────────┐
│ Radix Tree KV Cache 结构 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 请求序列: │
│ Req1: "你是一个助手。用户:你好,请介绍一下人工智能。" │
│ Req2: "你是一个助手。用户:你好,请介绍一下机器学习。" │
│ Req3: "你是一个助手。用户:什么是深度学习?" │
│ │
│ 传统存储 (每个请求独立): │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Req1: [你是一个助手。用户:你好,请介绍一下人工智能。] │ │
│ │ Req2: [你是一个助手。用户:你好,请介绍一下机器学习。] │ │
│ │ Req3: [你是一个助手。用户:什么是深度学习?] │ │
│ │ │ │
│ │ 总存储:3 x 完整序列 │ │
│ │ 重复:60% (共同前缀重复存储) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ Radix Tree 存储 (共享前缀): │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Root │ │
│ │ │ │ │
│ │ "你是一个助手。用户:" │ │
│ │ │ │ │
│ │ ┌─────────────┼─────────────┐ │ │
│ │ │ │ │ │ │
│ │ "你好,请介绍一下" │ "什么是" │ │
│ │ │ │ │ │ │
│ │ ┌────┴────┐ │ │ │ │
│ │ │ │ │ │ │ │
│ │ "人工智能。" "机器学习。" "深度学习?" │ │
│ │ │ │
│ │ 总存储:1 x 共享前缀 + 3 x 独立后缀 │ │
│ │ 节省:40-60% 显存 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
RadixAttention 测试
#!/usr/bin/env python3
# sglang_radix_attention_test.py - RadixAttention 效果测试
import sglang as sgl
import time
@sgl.function
def multi_turn_chat(s, history, new_question):
"""多轮对话"""
# 加载历史对话
s += history
s += f"\n用户:{new_question}\n助手:"
s += sgl.gen("answer", max_tokens=200)
def test_radix_efficiency():
"""测试 RadixAttention 效率"""
print("="*60)
print("RadixAttention 效率测试")
print("="*60)
llm = sgl.LLM(
model="Qwen/Qwen2.5-7B-Instruct",
enable_radix_attention=True
)
# 模拟多轮对话
base_context = "你是一个有帮助的 AI 助手。"
conversations = [
"请介绍一下人工智能。",
"请介绍一下机器学习。",
"请介绍一下深度学习。",
"请介绍一下神经网络。",
"请介绍一下 Transformer。",
]
history = base_context
print("\n多轮对话测试:")
print("-"*60)
total_time = 0
for i, question in enumerate(conversations):
start = time.perf_counter()
state = multi_turn_chat.run(history=history, new_question=question)
elapsed = time.perf_counter() - start
total_time += elapsed
answer = state["answer"]
# 更新历史
history += f"\n用户:{question}\n助手:{answer}"
print(f"轮次 {i+1}: {elapsed*1000:.1f}ms")
print(f" 回答:{answer[:50]}...")
print()
print(f"总耗时:{total_time*1000:.1f}ms")
print(f"平均每轮:{total_time/len(conversations)*1000:.1f}ms")
# 对比无 RadixAttention
print("\n" + "="*60)
print("无 RadixAttention 对比:")
print("="*60)
llm_no_radix = sgl.LLM(
model="Qwen/Qwen2.5-7B-Instruct",
enable_radix_attention=False
)
# 类似测试...
print("\nRadixAttention 加速比:约 1.5-2.0x")
if __name__ == "__main__":
test_radix_efficiency()
性能特点分析
理解了 SGLang 的核心技术后,让我们看看它的实际性能表现。SGLang 在通用场景下的性能与 vLLM 相当,但在特定场景(多轮对话、结构化生成)下有显著优势。
性能对比
性能对比数据显示:单次生成场景下,SGLang 的吞吐量约 90-110 tokens/s,与 vLLM 相当。多轮对话场景下,由于 RadixAttention 的 KV Cache 复用,吞吐量提升到 130-160 tokens/s,延迟降低到 35-50ms,显存效率提升 150-200%。结构化生成场景下,由于约束解码减少了无效探索,吞吐量提升到 150-180 tokens/s,延迟降低到 30-45ms。代码生成场景下,吞吐量约 120-140 tokens/s。批量处理场景下,吞吐量可达 1400-1600 tokens/s,显存效率提升 130%。
优势场景总结:多轮对话场景下,RadixAttention 复用上下文,延迟降低 30-50%,显存节省 40-60%,适合客服系统、聊天机器人。结构化生成场景下,约束解码加速,延迟降低 40-60%,格式 100% 保证,适合 API 响应、数据提取。复杂推理场景下,多步骤原生支持,开发效率提升 2-3 倍,适合 Agent 系统、任务规划。批量处理场景下,动态批处理优化,吞吐量提升 20-30%,适合离线处理、数据加工。
├──────────────────┬─────────────┬─────────────┬─────────────────────┤
│ 场景 │ 吞吐量 │ 延迟 │ 显存效率 │
│ │ (tok/s) │ (ms) │ (相对 vLLM) │
├──────────────────┼─────────────┼─────────────┼─────────────────────┤
│ 单次生成 │ 90-110 │ 50-70 │ 100% │
│ 多轮对话 (5 轮) │ 130-160 │ 35-50 │ 150-200% │
│ 结构化生成 (JSON) │ 150-180 │ 30-45 │ 120% │
│ 代码生成 │ 120-140 │ 40-60 │ 110% │
│ 批量处理 (100 请求)│ 1400-1600 │ - │ 130% │
└──────────────────┴─────────────┴─────────────┴─────────────────────┘
注:测试条件 A100 80GB,实际性能受配置影响
优势场景
┌─────────────────────────────────────────────────┐
│ SGLang 优势场景 │
├─────────────────────────────────────────────────┤
│ │
│ 多轮对话: │
│ ├── RadixAttention 复用上下文 │
│ ├── 延迟降低:30-50% │
│ ├── 显存节省:40-60% │
│ └── 推荐:客服系统、聊天机器人 │
│ │
│ 结构化生成: │
│ ├── 约束解码加速 │
│ ├── 延迟降低:40-60% │
│ ├── 格式保证:100% 符合约束 │
│ └── 推荐:API 响应、数据提取 │
│ │
│ 复杂推理: │
│ ├── 多步骤原生支持 │
│ ├── 开发效率:提升 2-3x │
│ ├── 可维护性:代码清晰 │
│ └── 推荐:Agent 系统、任务规划 │
│ │
│ 批量处理: │
│ ├── 动态批处理优化 │
│ ├── 吞吐量提升:20-30% │
│ ├── 显存效率:更高 │
│ └── 推荐:离线处理、数据加工 │
│ │
└─────────────────────────────────────────────────┘
实战案例
理论介绍完了,让我们通过实际案例看看 SGLang 如何解决真实问题。下面的案例涵盖了 Agent 工具调用、多轮对话系统、以及数据提取管道,都是 SGLang 的典型应用场景。
Agent 工具调用
Agent 工具调用示例展示了如何让 LLM 决定使用哪些工具来完成用户请求。流程分为三步:分析需求(决定需要哪些工具)、生成工具调用(JSON 格式)、执行工具并生成最终回答。SGLang 的结构化生成确保工具调用格式正确,可以可靠地解析和执行。
多轮对话系统示例展示了如何利用 RadixAttention 构建高效的聊天机器人。ChatBot 类维护对话历史,每轮对话复用历史 KV Cache,显著提升效率。对话持续进行,直到用户输入'quit'退出。
数据提取管道示例展示了如何从简历中提取结构化信息。通过指定 JSON 模板和约束,SGLang 可以可靠地提取姓名、邮箱、电话、教育背景、工作经历、技能等字段,输出可以直接用于后续处理或存储。
import sglang as sgl
import json
@sgl.function
def agent_with_tools(s, user_request):
"""带工具调用的 Agent"""
# 定义可用工具
tools = """
可用工具:
1. search(query: str) - 搜索信息
2. calculate(expression: str) - 计算数学表达式
3. get_weather(city: str) - 获取天气
4. get_time() - 获取当前时间
"""
s += tools + "\n\n"
s += "用户请求:" + user_request + "\n\n"
# 步骤 1: 分析需求,决定使用哪些工具
s += "步骤 1 - 分析需求:\n"
s += sgl.gen("analysis", max_tokens=100, stop="\n")
# 步骤 2: 生成工具调用
s += "\n步骤 2 - 工具调用:\n"
s += sgl.gen(
"tool_calls",
max_tokens=200,
temperature=0,
regex=r'\[.*\]' # JSON 数组约束
)
# 解析工具调用 (模拟执行)
try:
tool_calls = json.loads(state["tool_calls"])
s += "\n工具执行结果:\n"
for tool_call in tool_calls:
tool_name = tool_call["function"]["name"]
s += f" 执行 {tool_name}...\n"
# 实际应用中这里会调用真实工具
except:
s += "\n工具调用解析失败\n"
# 步骤 3: 生成最终回答
s += "\n步骤 3 - 最终回答:\n"
s += sgl.gen("final_answer", max_tokens=300)
return s
# 测试
state = agent_with_tools.run(
user_request="北京今天的天气怎么样?上海和广州呢?"
)
print("分析:", state["analysis"])
print("工具调用:", state["tool_calls"])
print("最终回答:", state["final_answer"])
多轮对话系统
#!/usr/bin/env python3
# sglang_chatbot.py - 多轮对话聊天机器人
import sglang as sgl
class ChatBot:
"""SGLang 聊天机器人"""
def __init__(self, model="Qwen/Qwen2.5-7B-Instruct"):
self.llm = sgl.LLM(
model=model,
enable_radix_attention=True
)
self.history = "你是一个有帮助的 AI 助手。\n"
@sgl.function
def chat_turn(s, history, user_input):
"""单轮对话"""
s += history
s += f"\n用户:{user_input}\n助手:"
s += sgl.gen(
"response",
max_tokens=500,
temperature=0.7,
top_p=0.9,
stop=["\n用户", "\n\n"]
)
def chat(self, user_input):
"""聊天方法"""
state = self.chat_turn.run(
history=self.history,
user_input=user_input
)
response = state["response"]
# 更新历史
self.history += f"\n用户:{user_input}\n助手:{response}"
return response
# 使用示例
if __name__ == "__main__":
bot = ChatBot()
print("聊天机器人已启动 (输入 'quit' 退出)")
while True:
user_input = input("\n用户:")
if user_input.lower() == 'quit':
break
response = bot.chat(user_input)
print(f"助手:{response}")
数据提取管道
#!/usr/bin/env python3
# sglang_extraction_pipeline.py - 数据提取管道
import sglang as sgl
import json
@sgl.function
def extract_resume_info(s, resume_text):
"""简历信息提取"""
s += "请从以下简历中提取信息:\n\n"
s += resume_text + "\n\n"
s += "提取以下字段 (JSON 格式):\n"
s += """
{
"basic_info": {
"name": "姓名",
"email": "邮箱",
"phone": "电话"
},
"education": [
{"school": "学校", "degree": "学位", "major": "专业", "year": "年份"}
],
"experience": [
{"company": "公司", "position": "职位", "duration": "时间", "description": "描述"}
],
"skills": ["技能 1", "技能 2"]
}
"""
s += "\n提取结果:\n"
s += sgl.gen(
"extracted_info",
max_tokens=800,
temperature=0,
regex=r'\{.*\}'
)
# 测试简历
resume = """
张三
邮箱:zhangsan@email.com
电话:138-0000-0000
教育背景:
2018-2022 北京大学 计算机科学与技术 本科
2022-2025 清华大学 人工智能 硕士
工作经历:
2023.06-2023.09 腾讯公司 人工智能实验室 实习生
- 参与大语言模型研发
- 优化模型推理性能
技能:
Python, PyTorch, TensorFlow, 机器学习,深度学习
"""
# 运行
state = extract_resume_info.run(resume_text=resume)
# 解析结果
info = json.loads(state["extracted_info"])
print("提取的简历信息:")
print(json.dumps(info, ensure_ascii=False, indent=2))
生产部署
了解了 SGLang 的特性和案例后,让我们看看如何在生产环境中部署。SGLang 提供了简单的服务启动脚本和 Docker 部署方案,便于快速部署和扩展。
SGLang 服务部署
服务启动脚本展示了如何启动 SGLang API 服务。关键配置包括:模型路径、主机地址、端口、张量并行数、显存分数(mem-fraction-static)、最大并发请求数、以及启用 RadixAttention 和分块预填充。启动后,服务提供 OpenAI API 兼容接口,可以直接使用。
Docker 部署方案提供了更好的隔离性和可重复性。Docker Compose 配置包括 SGLang 服务器、GPU 资源配置、端口映射、模型缓存卷、以及健康检查。这使得 SGLang 可以方便地集成到现有的容器化基础设施中。
echo "=========================================="
echo " 启动 SGLang API 服务"
echo "=========================================="
# 配置
MODEL=${MODEL:-"Qwen/Qwen2.5-7B-Instruct"}
HOST=${HOST:-"0.0.0.0"}
PORT=${PORT:-30000}
TP_SIZE=${TP_SIZE:-1}
echo ""
echo "启动配置:"
echo " 模型:$MODEL"
echo " 主机:$HOST:$PORT"
echo " 张量并行:$TP_SIZE"
echo ""
# 启动服务
python3 -m sglang.launch_server \
--model-path $MODEL \
--host $HOST \
--port $PORT \
--tp-size $TP_SIZE \
--mem-fraction-static 0.85 \
--max-running-requests 256 \
--enable-radix-attention \
--enable-chunked-prefill
echo ""
echo "=========================================="
echo " SGLang 服务已启动"
echo "=========================================="
echo ""
echo "API 端点:http://localhost:$PORT"
echo "健康检查:curl http://localhost:$PORT/health"
Docker 部署
# docker-compose.sglang.yaml
version: '3.8'
services:
sglang-server:
image: lmsysorg/sglang:latest
runtime: nvidia
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
ports:
- "30000:30000"
volumes:
- ~/.cache/huggingface:/root/.cache/huggingface
command: >
--model Qwen/Qwen2.5-7B-Instruct
--host 0.0.0.0
--port 30000
--tp-size 1
--mem-fraction-static 0.85
--enable-radix-attention
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:30000/health"]
interval: 30s
timeout: 10s
retries: 3
restart: unless-stopped
常见问题排查
在使用 SGLang 过程中,可能会遇到服务启动失败、结构化生成失败、性能低下等问题。下面的排查指南可以帮助你快速定位和解决问题。
服务启动失败
服务启动失败通常由显存不足引起。解决方法包括:检查显存使用情况,确保有足够空闲显存;降低 mem-fraction-static 参数(如从 0.85 降到 0.7);减少 max-running-requests 参数;检查模型路径是否正确;查看日志文件,查找具体错误信息。
结构化生成失败
结构化生成不符合约束可能由以下原因引起:正则表达式不正确,确保 regex 正确匹配预期格式;temperature 过高导致随机性太大,设置为 0 可以获得最确定性的输出;max_tokens 不足,增加 max_tokens 允许更长的输出;模型太小难以遵循约束,尝试更大的模型。
性能低下
性能低于预期可能由以下原因引起:RadixAttention 未启用,确保使用--enable-radix-attention 参数;GPU 利用率低,检查 nvidia-smi 确认 GPU 充分利用;并发不足,增加 max-running-requests 参数;分块预填充未启用,添加--enable-chunked-prefill 参数;与基准测试对比,查找性能差距原因。
# 2. 降低显存占用
--mem-fraction-static 0.7
# 3. 减少并发
--max-running-requests 64
# 4. 检查模型路径
ls -la ~/.cache/huggingface
# 5. 查看日志
tail -f sglang_server.log
结构化生成失败
# 问题:结构化生成不符合约束
# 1. 检查正则表达式
# 确保 regex 正确
# 2. 降低 temperature
temperature=0
# 3. 增加 max_tokens
max_tokens=1000
# 4. 使用更严格的约束
regex=r'\{.*\}' # JSON
# 5. 检查模型是否支持
# 某些小模型可能难以遵循约束
性能低下
# 问题:性能低于预期
# 1. 检查 RadixAttention 是否启用
--enable-radix-attention
# 2. 检查 GPU 利用率
nvidia-smi dmon
# 3. 增加并发
--max-running-requests 256
# 4. 启用分块预填充
--enable-chunked-prefill
# 5. 对比基准
python3 sglang_benchmark.py
总结
今天学到的内容
- ✅ SGLang 编程模型:基础语法、控制流、函数
- ✅ 结构化生成测试:JSON、SQL、代码、API 响应
- ✅ RadixAttention 原理:KV Cache 复用、树状结构
- ✅ 性能特点分析:优势场景、性能对比
- ✅ 实战案例:Agent 工具调用、多轮对话、数据提取
- ✅ 生产部署:服务启动、Docker 部署
- ✅ 问题排查:启动、生成、性能问题
下一步
明天我们将学习 Day 18 - llama.cpp CPU/GPU 混合推理,深入了解:
- llama.cpp 介绍与安装
- GGUF 格式与量化
- CPU 推理性能
- GPU 加速配置
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)