Prhub

#23533 support Hy3 preview

原始 PR 作者 JustinTong0323 合并时间 2026-04-25 03:03 文件变更 25 提交数 36 评论 14 代码增减 +4095 / -3

执行摘要

支持腾讯混元 V3(Hy3-preview) 模型推理与工具调用

用户需要在sglang中部署和推理腾讯最新Hunyuan V3(Hy3-preview)模型,该模型采用MoE架构并支持函数调用与推理模式。PR通过提供完整的模型适配、专用解析器和调优配置,使sglang成为支持Hy3-preview的推理框架之一。

该PR值得精读,特别是双流MoE重叠方案、自定义融合TopK kernel的实现、以及流式工具解析器的增量输出设计。建议后续关注group topk kernel的重构和AMD兼容性修复。

讨论亮点

AMD兼容性风险:AMD验证者@andyluo7在Issue评论中报告,在MI300X和MI355X上使用CUDA graph模式时发生HSA_STATUS_ERROR_EXCEPTION崩溃,根因定位到AITER的custom all-reduce(默认在HIP上启用)。Eager mode可正常工作。建议用户在使用AMD时先使用--disable-cuda-graph
组TopK Kernel后续重构:合并者Qiaolin-Yu表示group topk kernel后续可能需要重构,但当前设计可以合并。

实现拆解

  1. 模型定义:新建hunyuan_v3.pyhunyuan_v3_nextn.py,实现HYV3FeedForwardHYV3MoEFused(双流MoE)、HYV3Attention等核心模块,支持单流/双流前向、专家偏置加载、分组TopK路由。
  2. 性能优化融合核:在jit_kernel/grouped_topk.py中新增grouped_topk函数,调用JIT编译的CUDA kernel实现Sigmoid+偏置+TopK+重归一化的融合,替代原先多次torch.topk调用;CUDA源文件grouped_topk.cuh实现具体逻辑,支持单分组、低于512专家、TopK≤8。
  3. 流式工具调用解析器hunyuan_detector.py实现HunyuanDetector,解析Hy3-preview的XML风格工具调用格式,支持两阶段流式输出:阶段一输出函数名,阶段二增量流式输出参数JSON,对纯字符串参数实现字符级流式。同时包含模式感知的类型强制转换。
  4. 推理解析器:在reasoning_parser.py中添加HunyuanDetector,支持<think>...</think>标签,并根据chat_template_kwargs中的reasoning_effort值(high/low/none/no_think)正确切换推理模式。
  5. 配置与部署配套:新增多个调优的MoE Triton配置文件(H20/B200,fp8/bf16),覆盖E=192,N=192场景;修改topk.py以支持use_grouped_topk路由;更新serving_chat.py推理请求处理;新增使用文档hy3_preview.md
  6. 测试覆盖test_hunyuan_detector.py包含50个测试,覆盖HasToolCall、DetectAndParse、StreamingParse等场景;test_reasoning_parser.py新增TestHunyuanDetector覆盖推理解析与工具中断。
文件 模块 状态 重要度
python/sglang/srt/models/hunyuan_v3.py 模型定义 added 9.17
python/sglang/srt/models/hunyuan_v3_nextn.py MTP 模型 added 9.28
python/sglang/srt/function_call/hunyuan_detector.py 工具解析器 added 8.89
python/sglang/jit_kernel/grouped_topk.py 内核封装 added 8.02
test/registered/unit/function_call/test_hunyuan_detector.py 测试 added 7.48
test/registered/unit/parser/test_reasoning_parser.py 测试 modified 6.81
python/sglang/srt/parser/reasoning_parser.py 推理解析 modified 6.68
python/sglang/jit_kernel/csrc/moe/grouped_topk.cuh 内核 CUDA added 6.02
python/sglang/srt/layers/moe/topk.py 路由层 modified 5.97
python/sglang/srt/layers/moe/fused_moe_triton/configs/triton_3_5_1/E=192,N=192,device_name=NVIDIA_H20,dtype=fp8_w8a8.json MoE 配置 added 5.06

关键符号

HYV3MoEFused.forward HYV3MoEFused.ebias_weight_loader grouped_topk HunyuanDetector.parse_streaming_increment HunyuanDetector.detect_and_parse HYV3ModelNextN.forward HYV3ForCausalLMNextN.load_weights HunyuanDetector.__init__

关键源码片段

python/sglang/srt/models/hunyuan_v3.py data-contract

模型核心实现,包含 HYV3MoEFused 双流 MoE、HYV3Attention、专家偏置加载等,新增 587 行。

# -*- coding: utf-8 -*-
# Copyright (c) 2026 The HunYuan team.import torch
from torch import nn
from sglang.srt.layers.moe.topk import TopKclass HYV3MoEFused(nn.Module):
    """
    双流 MoE 层:支持单流(默认)和双流(通过 alt_stream 异步执行 gate 与 expert 计算)
    使用 fused grouped top-k 路由,结合 sigmoid 评分与 expert bias 修正。
    """
    def __init__(self, config, layer_id, quant_config, prefix="", alt_stream=None):
        super().__init__()
        # ( 第一部分 ):初始化超参数与路由 gate
        self.tp_size = get_moe_tensor_parallel_world_size()
        self.ep_size = get_moe_expert_parallel_world_size()
        self.layer_id = layer_id
        self.alt_stream = alt_stream # 双流模式下使用独立的 CUDA stream
​
        # expert_bias: 用于路由修正的偏置参数,权重加载器设置为 ebias_weight_loader
        self.expert_bias = nn.Parameter(
            torch.empty(config.num_experts, dtype=torch.float32)
        )
        self.expert_bias.weight_loader = HYV3MoEFused.ebias_weight_loader
​
        # 路由评分函数为 sigmoid,由 TopK 层实现分组 top-k + renormalize
        self.gate = ReplicatedLinear(
            config.hidden_size, config.num_experts,
            bias=False, quant_config=None, params_dtype=torch.float32,
            prefix=f"{prefix}.gate",
        )
        self.topk = TopK(
            top_k=config.num_experts_per_tok,
            use_grouped_topk=True,
            num_expert_group=1,
            topk_group=1,
            renormalize=config.route_norm,
            scoring_func="sigmoid",
            correction_bias=self.expert_bias, # 路由偏置修正
            routed_scaling_factor=getattr(config, "router_scaling_factor", 1.0),
            apply_routed_scaling_factor=True,
        )
​
    def forward(self, hidden_states, forward_batch, residual):
        # (forward 逻辑 ) 调用 self.gate 得 expert_weights, 然后通过 FusedMoE 计算
        # 此处省略后续细节
        pass
python/sglang/srt/models/hunyuan_v3_nextn.py data-contract

实现 MTP(Multi-Token Prediction)推测解码模型,重用 HYV3DecoderLayer,新增 253 行。

# -*- coding: utf-8 -*-
# MTP(Multi-Token Prediction)模型,用于 speculative decoding 的 draft 阶段。
# 它会重用 HYV3DecoderLayer,强制使用 MoE(即使 config 中 first_k_dense_replace > 0)。class HYV3ModelNextN(nn.Module):
    def __init__(self, config, quant_config=None, prefix=""):
        super().__init__()
        self.embed_tokens = VocabParallelEmbedding(config.vocab_size, config.hidden_size)
        self.enorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
        self.hnorm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
        # 拼接前一刻的 hidden_states 与当前 embedding
        self.eh_proj = nn.Linear(2 * config.hidden_size, config.hidden_size, bias=False)
​
        self.alt_stream = torch.cuda.Stream() if is_cuda() else None
        # 强制当前层为 MoE:临时覆盖 first_k_dense_replace
        orig_first_k = getattr(config, "first_k_dense_replace", 0)
        config.first_k_dense_replace = 0
        self.decoder = HYV3DecoderLayer(
            config=config, layer_id=0, quant_config=quant_config,
            prefix=f"{prefix}.decoder", alt_stream=self.alt_stream,
        )
        config.first_k_dense_replace = orig_first_k
​
        self.shared_head = nn.Module()
        self.shared_head.norm = RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
​
    def forward(self, input_ids, positions, forward_batch, input_embeds=None):
        # 获取 hidden_states 并拼接前一层的 hidden_states
        hidden_states = self.embed_tokens(input_ids) if input_embeds is None else input_embeds
        if hidden_states.shape[0] > 0:
            hidden_states = self.eh_proj(
                torch.cat([self.enorm(hidden_states),
                           self.hnorm(forward_batch.spec_info.hidden_states)], dim=-1)
            )
        hidden_states, residual = self.decoder(positions, hidden_states, forward_batch, None)
        # 归一化输出(仅在非 idle 模式)
        if not forward_batch.forward_mode.is_idle():
            hidden_states = self.shared_head.norm(hidden_states if residual is None else hidden_states + residual)
        return hidden_states
python/sglang/srt/function_call/hunyuan_detector.py dependency-wiring

实现 Hy3-preview 的 XML 风格工具调用解析器,支持两阶段流式输出和模式感知类型转换,新增 476 行。

# -*- coding: utf-8 -*-
# HunyuanDetector:解析 Hy3-preview 模型的工具调用格式。
# 格式为 <tool_calls><tool_call>name<tool_sep><arg_key>k</arg_key><arg_value>v</arg_value></tool_call></tool_calls>
# 流式解析分为两个阶段:
# 阶段 1: 遇到 <tool_sep> 后立即输出函数名
# 阶段 2: 增量构建参数 JSON,纯字符串参数支持字符级流式,复合类型等待完整闭合后输出。class HunyuanDetector(BaseFormatDetector):
    def __init__(self):
        super().__init__()
        # 定义 token 常量
        self.bot_token = "<tool_calls>"
        self.eot_token = "</tool_calls>"
        self.tool_call_start_token = "<tool_call>"
        self.tool_call_end_token = "</tool_call>"
        self.tool_sep_token = "<tool_sep>"
        self.arg_key_start_token = "<arg_key>"
        self.arg_key_end_token = "</arg_key>"
        self.arg_value_start_token = "<arg_value>"
        self.arg_value_end_token = "</arg_value>"
​
        # 流式状态
        self._in_tool_calls = False
        self._streaming_tool_name: Optional[str] = None
        self._completed_args: Dict[str, Any] = {}
        self._streamed_json_len = 0
​
    def parse_streaming_increment(self, new_text: str, tools: List[Tool] = None) -> StreamingParseResult:
        # 增量解析逻辑:处理 <tool_calls> 起始标签,拆分阶段,
        # 纯字符串参数先在内部追加字符,仅在遇到 </arg_value> 时输出完整键值。
        # 参数类型从 tools 中获取 schema,决定是否可流式。
        result = StreamingParseResult()
        # ... 具体解析过程略
        return result

评论区精华

AMD CUDA Graph 兼容性 正确性

AMD 验证者在 Issue 评论中报告,在 MI300X 和 MI355X 上 CUDA graph 模式崩溃,Eager mode 正常。

结论:暂时建议 AMD 用户使用 --disable-cuda-graph,后续修复。 · unresolved

Group TopK Kernel 后续重构 设计

合并者 Qiaolin-Yu 表示 group topk kernel 后续可能需要重构。

结论:当前设计可以合并,后续会优化。 · 已解决

风险与影响

AMD CUDA Graph兼容性:CUDA graph模式下在AMD GPU上出现HSA异常,需要用户禁用CUDA graph或等待后续修复。可能影响AMD用户的部署体验。
新引入代码回归风险:模型、解析器、kernel均为新增,尽管有测试覆盖,但集成到完整推理pipeline中可能出现未预料的交互。MoE双流重叠与alt_stream的使用在CUDA graph捕获模式下可能有潜在冲突。
配置依赖:新增的Moe Triton配置文件依赖特定Triton版本(3_5_1),若环境版本不匹配可能导致运行时错误。
安全考虑:工具调用解析器中的流式处理涉及部分标签持有后输出,若输入异常可能引入解析状态异常,但测试覆盖了边界情况。

用户侧:Hy3-preview用户可直接在sglang中使用模型推理、工具调用、推理模式切换。新增--tool-call-parser hunyuan--reasoning-parser hunyuan命令行参数。
系统侧:新增约4K行代码,主要影响模型加载、推理内核、解析器模块。模型代码基于现有层组件,对现有模型无影响。MoE路由路径新增grouped_topk选项,但默认不影响其他模型。
团队侧:需要维护新模型的后向兼容性,特别是当Hy3-preview正式发布后可能引入checkpoint变更。AMD专家需关注CUDA graph问题。

AMD CUDA Graph 兼容 MoE 双流重叠可能锁定 Triton 版本依赖 新代码回归风险

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论