文件名 SGlang中针对确定性推理文档.md

SGlang中针对确定性推理文档

本文目录

正文

Deterministic Inference — SGLang

确定性推理

为什么确定性推理很重要

确定性推理确保了在多次运行中,LLM 的输出保持一致,这对于以下几个方面至关重要:

  • 强化学习:确保在多次运行中 logprobs 一致,减少随机噪声,使得强化学习训练更加稳定、可重复和可调试。
  • 测试与调试:使得验证过程可重复。
  • 生产环境:提高可靠性和用户体验。

即使在 temperature=0 的情况下,标准的 LLM 推理由于动态批处理和 GPU 内核中不同的归约顺序,仍然可能产生不同的输出。

非确定性的根本原因

主要的原因是 批次大小的变化。不同的批次大小导致 GPU 内核在进行归约操作时顺序不同,进而导致加法顺序不同。由于浮点数结合的不确定性((a + b) + c ≠ a + (b + c)),即使是相同的输入,也会产生不同的结果。

SGLang 的解决方案

SGLang 基于 Thinking Machines Lab 的批次不变操作符,实现了完全的确定性推理,并且保持与分块预填充、CUDA 图、基数缓存和非贪婪采样的兼容性。有关确定性推理特性的开发路线图,可以在 这个问题 中找到。

支持的后端

确定性推理仅在以下三个注意力后端中支持:FlashInferFlashAttention 3 (FA3)Triton

下表展示了不同注意力后端在确定性推理中的特性兼容性:

注意力后端 CUDA 图 分块预填充 基数缓存 非贪婪采样(Temp > 0)
FlashInfer ✅ 是 ✅ 是 ❌ 否 ✅ 是
FlashAttention 3 (FA3) ✅ 是 ✅ 是 ✅ 是 ✅ 是
Triton ✅ 是 ✅ 是 ✅ 是 ✅ 是

使用方法

基本用法

通过添加 --enable-deterministic-inference 标志来启用确定性推理:

python3 -m sglang.launch_server \
    --model-path Qwen/Qwen3-8B \
    --attention-backend fa3 \
    --enable-deterministic-inference

服务器参数

| 参数 | 类型/默认值 | 说明 | | — | — | — | | --enable-deterministic-inference | 标志;默认:禁用 | 启用具有批次不变操作的确定性推理 | | --attention-backend | 字符串;默认:fa3 | 选择注意力后端(flashinfer、fa3 或 triton) |

示例配置

Qwen3-8B

python3 -m sglang.launch_server \
    --model-path Qwen/Qwen3-8B \
    --attention-backend flashinfer \
    --enable-deterministic-inference

Llama 模型

python3 -m sglang.launch_server \
    --model-path meta-llama/Llama-3.1-8B-Instruct \
    --attention-backend fa3 \
    --enable-deterministic-inference

Qwen3-30B-A3B(MoE 模型)

python3 -m sglang.launch_server \
    --model-path Qwen/Qwen3-30B-A3B \
    --attention-backend fa3 \
    --enable-deterministic-inference

使用非贪婪采样的确定性推理(Temperature > 0)

SGLang 即使在使用非贪婪采样时,也支持确定性推理,方法是使用采样种子。这在强化学习场景中尤其有用,例如 GRPO(Group Relative Policy Optimization),需要多样但可重复的响应。

默认行为

默认情况下,SGLang 使用 42 作为采样种子,以确保采样可重复:

import requests

response = requests.post(
    "http://localhost:30000/generate",
    json={
        "text": "Tell me a joke",
        "sampling_params": {
            "temperature": 0.8,  # 非贪婪采样
            "max_new_tokens": 128,
        },
    },
)
print(response.json())
# 这将始终产生相同的响应

生成多个可重复的响应

要从相同的提示中生成不同的响应,同时保持可重复性(例如用于 GRPO 训练),可以在请求中提供不同的采样种子:

import requests

# 准备不同的采样种子来获取不同的响应
sampling_seeds = [42, 43, 44, 45, 46]

responses = []
for seed in sampling_seeds:
    response = requests.post(
        "http://localhost:30000/generate",
        json={
            "text": "Tell me a joke",
            "sampling_params": {
                "temperature": 0.8,
                "max_new_tokens": 128,
                "sampling_seed": seed,  # 指定采样种子
            },
        },
    )
    responses.append(response.json())

# 每个种子将产生不同但可重复的响应
# 使用相同的种子将始终产生相同的响应

这种方法确保:

  • 不同的种子产生多样的响应
  • 相同的种子始终产生相同的响应
  • 结果可用于调试和评估

验证

运行确定性测试以验证输出的一致性:

# 单次测试:相同的提示,批次大小变化
python3 -m sglang.test.test_deterministic --test-mode single --n-trials 50

# 前缀测试:具有不同前缀长度的提示
python3 -m sglang.test.test_deterministic --test-mode prefix --n-trials 50

# 基数缓存一致性模式:测试基数缓存的确定性(缓存与未缓存预填充)
python3 -m sglang.test.test_deterministic --test-mode radix_cache

预期结果:所有测试应显示 Unique samples: 1(完全确定性)。