目录

  1. 引言
  2. SGLang 编程模型
  3. 结构化生成测试
  4. RadixAttention 原理
  5. 性能特点分析
  6. 实战案例
  7. 生产部署
  8. 常见问题排查

引言

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

总结

今天学到的内容

  1. ✅ SGLang 编程模型:基础语法、控制流、函数
  2. ✅ 结构化生成测试:JSON、SQL、代码、API 响应
  3. ✅ RadixAttention 原理:KV Cache 复用、树状结构
  4. ✅ 性能特点分析:优势场景、性能对比
  5. ✅ 实战案例:Agent 工具调用、多轮对话、数据提取
  6. ✅ 生产部署:服务启动、Docker 部署
  7. ✅ 问题排查:启动、生成、性能问题

下一步

明天我们将学习 Day 18 - llama.cpp CPU/GPU 混合推理,深入了解:

  • llama.cpp 介绍与安装
  • GGUF 格式与量化
  • CPU 推理性能
  • GPU 加速配置
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐