@@ -30,15 +30,23 @@ def _klx_fused_experts(
3030 w2 : torch .Tensor ,
3131 topk_weights : torch .Tensor ,
3232 topk_ids : torch .Tensor ,
33+ activation : str = "silu" ,
3334 use_int8_w8a8 : bool = False ,
3435 use_int8_w4a8 : bool = False ,
3536 w1_scale : Optional [torch .Tensor ] = None ,
3637 w2_scale : Optional [torch .Tensor ] = None ,
38+ w1_bias : Optional [torch .Tensor ] = None ,
39+ w2_bias : Optional [torch .Tensor ] = None ,
3740) -> None :
3841 """
3942 Fused MoE expert computation using xtorch_ops (sorted path).
4043
41- Pipeline: gen_block_statistic -> moe_pre_sorted -> moe_fc(w1) -> swiglu -> moe_fc(w2) -> post (weight+sum)
44+ Pipeline: gen_block_statistic -> moe_pre_sorted -> moe_fc(w1) -> activation -> moe_fc(w2) -> post (weight+sum)
45+
46+ Args:
47+ activation: Activation function type. Supported: "silu", "gelu", "relu"
48+ w1_bias: Optional bias for gate+up projection [E, 2*ffn_hd]
49+ w2_bias: Optional bias for down projection [E, hidden_dim]
4250 """
4351 if use_int8_w8a8 or use_int8_w4a8 :
4452 raise NotImplementedError ("_klx_fused_experts is not supported for int8 w8a8 and w4a8." )
@@ -73,18 +81,43 @@ def _klx_fused_experts(
7381 inner_fc_out = torch .empty (seq_num , moe_topk , double_ffn_hd , dtype = dtype , device = device )
7482 xtorch_ops .moe_fc (
7583 moe_expand , w1 , sorted_tokens_num_lod , moe_index , moe_topk , inner_fc_out ,
84+ bias = w1_bias ,
7685 )
7786 inner_fc_out = inner_fc_out .view (moe_input_num , double_ffn_hd )
7887
79- # Step 4: SwiGLU activation (in-place on first half)
88+ # Step 4: Activation
8089 ffn_hd = double_ffn_hd // 2
81- swiglu_out = torch .empty (moe_input_num , ffn_hd , dtype = dtype , device = device )
82- xtorch_ops .swiglu (inner_fc_out , swiglu_out )
90+ if activation == "silu" :
91+ # SwiGLU: silu(gate) * up
92+ swiglu_out = torch .empty (moe_input_num , ffn_hd , dtype = dtype , device = device )
93+ xtorch_ops .swiglu (inner_fc_out , swiglu_out )
94+ elif activation == "gelu" :
95+ # GeGLU: gelu(gate) * up
96+ gate = inner_fc_out [:, :ffn_hd ]
97+ up = inner_fc_out [:, ffn_hd :]
98+ swiglu_out = xtorch_ops .gelu (gate ) * up
99+ elif activation == "relu" :
100+ # ReLU: relu(gate) * up
101+ gate = inner_fc_out [:, :ffn_hd ]
102+ up = inner_fc_out [:, ffn_hd :]
103+ swiglu_out = xtorch_ops .relu (gate ) * up
104+ elif activation in ["gelu_no_mul" , "silu_no_mul" ]:
105+ # No mul variant: only apply activation, no gating
106+ if activation == "gelu_no_mul" :
107+ swiglu_out = xtorch_ops .gelu (inner_fc_out )
108+ else : # silu_no_mul
109+ swiglu_out = xtorch_ops .silu (inner_fc_out )
110+ else :
111+ raise ValueError (
112+ f"Unsupported activation '{ activation } '. "
113+ f"Supported: ['silu', 'gelu', 'relu', 'gelu_no_mul', 'silu_no_mul']"
114+ )
83115
84116 # Step 5: Outer FC (down projection)
85117 outer_fc_out = torch .empty (seq_num , moe_topk , hidden_dim , dtype = dtype , device = device )
86118 xtorch_ops .moe_fc (
87119 swiglu_out , w2 , sorted_tokens_num_lod , moe_index , moe_topk , outer_fc_out ,
120+ bias = w2_bias ,
88121 )
89122 outer_fc_out = outer_fc_out .view (moe_input_num , hidden_dim )
90123
@@ -127,13 +160,37 @@ def fused_experts_impl(
127160) -> torch .Tensor :
128161 """
129162 Kunlunxin fused experts implementation.
130-
163+
131164 This function matches the signature of vllm_fl.ops.fused_moe.fused_moe.fused_experts_impl
132165 and is patched in by the Kunlunxin patch system.
166+
167+ Args:
168+ activation: Activation function. Supported: "silu", "gelu", "relu", "gelu_no_mul", "silu_no_mul"
169+ apply_router_weight_on_input: If True, apply router weights on input (NOT SUPPORTED)
170+ w1_bias: Optional bias for gate+up projection
171+ w2_bias: Optional bias for down projection
133172 """
173+ # Stage 1: Explicit rejections for unsupported features
174+
175+ # 1.1: Reject unsupported quantization schemes
134176 if use_fp8_w8a8 or use_int8_w8a16 or use_int4_w4a16 :
135177 raise NotImplementedError (
136- "Kunlunxin fused_experts does not support fp8/int8_w8a16/int4 quantization yet."
178+ "Kunlunxin fused_experts does not support fp8_w8a8/int8_w8a16/int4_w4a16 quantization yet."
179+ )
180+
181+ # 1.2: Reject apply_router_weight_on_input=True
182+ if apply_router_weight_on_input :
183+ raise NotImplementedError (
184+ "Kunlunxin fused_experts does not support apply_router_weight_on_input=True. "
185+ "Router weights are always applied in the moe_post stage (after down projection)."
186+ )
187+
188+ # 1.3: Validate activation function
189+ SUPPORTED_ACTIVATIONS = ["silu" , "gelu" , "relu" , "gelu_no_mul" , "silu_no_mul" ]
190+ if activation not in SUPPORTED_ACTIVATIONS :
191+ raise NotImplementedError (
192+ f"Kunlunxin fused_experts does not support activation '{ activation } '. "
193+ f"Supported activations: { SUPPORTED_ACTIVATIONS } "
137194 )
138195
139196 num_tokens = hidden_states .size (0 )
@@ -157,9 +214,12 @@ def fused_experts_impl(
157214 w2 = w2 ,
158215 topk_weights = topk_weights ,
159216 topk_ids = topk_ids ,
217+ activation = activation ,
160218 use_int8_w8a8 = use_int8_w8a8 ,
161219 w1_scale = w1_scale ,
162220 w2_scale = w2_scale ,
221+ w1_bias = w1_bias ,
222+ w2_bias = w2_bias ,
163223 )
164224
165225 return output
0 commit comments