Prhub

#30463 [Bugfix] Map reasoning_effort=low to Nemotron-3 Super low_effort + warn on unsupported levels

原始 PR 作者 JustinTong0323 合并时间 2026-07-09 03:19 文件变更 6 提交数 3 评论 4 代码增减 +141 / -15

执行摘要

映射 Nemotron-3 Super low_effort 并警告不支持级别

Nemotron-3 Super 的 chat template 暴露了 low_effort 布尔参数,但 SGLang 未将其与 OpenAI 的 reasoning_effort 字段关联,导致 low 级别静默无效,其他级别也无声失败。下游用户(如 CoreWeave)请求看起来被接受但从未生效。该 PR 解决了这一缺失映射。

建议阅读本 PR,特别是 protocol.pynormalize_reasoning_inputs 的重构,以及 template_detection.py 中如何通过配置字段实现模型特定的 effort 映射。这些设计模式值得应用到其他需要差异化的模板参数中。

讨论亮点

PR 获得两位审阅者(b8zhong、Fridge003)的批准,无其他讨论或争议。

实现拆解

  1. 新增 effort_kwarg 配置字段template_detection.py):在 ReasoningToggleConfig 中加入 effort_kwarg: Optional[str],用于存储模型特定的 effort 模板参数名(如 low_effort)。
  2. 检测 Nemotron-3 Supertemplate_detection.py):新增 nemotron_3_super_low_effort 检测规则,通过模板中同时存在 low_efforttruncate_history_thinking 特征词来识别 Super 变体,并设置 effort_kwarg='low_effort'。同时修改 _is_nemotron_3 函数,使用字段比较而非严格相等判断,使携带 effort_kwarg 的 Super 配置仍能被识别为 nemotron_3 解析器。
  3. 统一 thinking 开关逻辑protocol.py):重构 normalize_reasoning_inputs validator,使用局部变量 thinking 统一处理 reasoning 字典和顶层 reasoning_effort 字段,最后一次性设置 chat_template_kwargs['thinking']chat_template_kwargs['enable_thinking'],消除重复分支。
  4. _apply_jinja_template 中应用 effort_kwargserving_chat.py):构建模板参数时,若 reasoning_config.effort_kwarg 存在,则 reasoning_effort='low' 时通过 setdefault 设置对应 kwarg;若为 medium/high/max 则输出警告日志。none 继续由 #28860 的 normalize_reasoning_inputs 处理。
  5. 新增测试test_serving_chat.py 中增加 _setup_nemotron_super_run_jinja_with_effort 辅助方法和三个测试用例(low 映射、high 警告、Nano 无影响)。test_protocol.py 增加 test_chat_completion_reasoning_effort_high_enables_thinkingtest_chat_completion_reasoning_effort_none_overrides_enabledtest_template_manager.py 增加 test_nemotron_super_detects_low_effort_kwarg
文件 模块 状态 重要度
python/sglang/srt/entrypoints/openai/protocol.py 协议层 modified 6.27
python/sglang/srt/entrypoints/openai/serving_chat.py 对话服务 modified 5.95
python/sglang/srt/managers/template_detection.py 模板检测 modified 5.86
test/registered/unit/entrypoints/openai/test_serving_chat.py 对话测试 modified 7.11
test/registered/unit/entrypoints/openai/test_protocol.py 协议测试 modified 5.99
test/registered/unit/managers/test_template_manager.py 模板测试 modified 5.43

关键符号

normalize_reasoning_inputs _apply_jinja_template _is_nemotron_3 _setup_nemotron_super _run_jinja_with_effort

关键源码片段

python/sglang/srt/entrypoints/openai/protocol.py core-logic

重构了 normalize_reasoning_inputs,统一 thinking 开关逻辑,影响所有模型的 reasoning_effort 处理。

@model_validator(mode="before")
@classmethod
def normalize_reasoning_inputs(cls, values: Dict):
    r = values.get("reasoning")
    thinking = None # 统一 thinking 状态, None 表示未设置
​
    if r is not None and isinstance(r, dict):
        effort = r.get("effort") or r.get("reasoning_effort")
        if effort in {"none", "low", "medium", "high"}:
            values["reasoning_effort"] = effort
​
        enabled = (
            r.get("enabled")
            if r.get("enabled") is not None
            else r.get("enable", False)
        )
        if isinstance(enabled, str):
            enabled = enabled.strip().lower() in {"1", "true", "yes", "y", "on"}
        if enabled:
            thinking = True # 从 reasoning dict 启用 thinking
​
    # 顶层 reasoning_effort 字段覆盖 thinking 状态
    effort = values.get("reasoning_effort")
    if effort is not None:
        thinking = effort != "none"
​
    if thinking is not None:
        ctk = values.get("chat_template_kwargs")
        if not isinstance(ctk, dict):
            ctk = {}
        # 同时设置两个键以兼容不同模型
        ctk.setdefault("thinking", thinking)
        ctk.setdefault("enable_thinking", thinking)
        values["chat_template_kwargs"] = ctk
​
    return values
python/sglang/srt/entrypoints/openai/serving_chat.py core-logic

在 _apply_jinja_template 中新增了 effort_kwarg 处理逻辑,实现对 Nemotron-3 Super 低努力级别的映射和警告。

# 在构建 extra_template_kwargs 之后(已有 reasoning_effort 和 chat_template_kwargs)
rc = self.template_manager.reasoning_config
if rc is not None and rc.effort_kwarg is not None:
    if request.reasoning_effort == "low":
        # 映射 low -> 设置 low_effort=True; 使用 setdefault 保留用户显式值
        extra_template_kwargs.setdefault(rc.effort_kwarg, True)
    elif request.reasoning_effort in ("medium", "high", "max"):
        # 模型仅支持 low, 其他级别回退默认 thinking 并发出警告
        logger.warning(
            "Model '%s' supports only 'low' reasoning effort; "
            "requested '%s' treated as default thinking",
            self.tokenizer_manager.server_args.served_model_name,
            request.reasoning_effort,
        )
python/sglang/srt/managers/template_detection.py core-logic

增加了 effort_kwarg 字段和 Nemotron-3 Super 检测规则,修改了 _is_nemotron_3 比较方式。

class ReasoningToggleConfig:
    toggle_param: Optional[str] = None
    default_enabled: Optional[bool] = None
    special_case: Optional[str] = None
    effort_kwarg: Optional[str] = None # 新增:模型特定的 effort 模板参数名
​
    @property
    def always_on(self) -> bool:
        return self.default_enabled is True and self.effort_kwarg is None# 在检测规则列表中添加
DetectionRule(
    name="nemotron_3_super_low_effort",
    value=ReasoningToggleConfig(
        toggle_param="enable_thinking",
        default_enabled=True,
        effort_kwarg="low_effort", # 设置 effort 参数名
    ),
    predicate=lambda ctx: ctx.has_text("low_effort")
    and ctx.has_text("truncate_history_thinking"),
),# 修改 _is_nemotron_3 函数,允许额外字段
def _is_nemotron_3(ctx):
    return ctx.has_text("truncate_history_thinking") and (
        ctx.reasoning_config is not None
        and ctx.reasoning_config.toggle_param == "enable_thinking"
        and ctx.reasoning_config.default_enabled is True
    )

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

主要风险:normalize_reasoning_inputs 的重构可能影响其他依赖此逻辑的模型(如 Qwen3、GLM4-5),但重构后的逻辑等价于原有行为(测试已覆盖顶层 effort 和 reasoning 字典两种路径)。另外,_is_nemotron_3 的字段比较放宽了严格匹配,任何 toggle_param='enable_thinking'default_enabled=True 的高层配置都可能被识别为 nemotron_3,但这不是新风险,因为之前也是通过相等比较,现在只是允许额外字段存在。总体来说风险较低。

对用户:Nemotron-3 Super 用户现在可以正确使用 reasoning_effort='low',其他级别会收到明确警告。Nemotron-3 Nano 用户无影响。对其他模型:thinking 开关逻辑重构为统一路径,行为一致,不应有副作用。对系统:增加一条条件判断和一个警告日志,性能无负面影响。

核心路径变更 模型特定配置

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论