Add support for BharatGen's Param2MoE model architecture#46395
Add support for BharatGen's Param2MoE model architecture#46395bhargav-patel-29 wants to merge 26 commits into
Conversation
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
ArthurZucker
left a comment
There was a problem hiding this comment.
TY looks good already let's standardize a bit more!
|
|
||
| def forward(self, hidden_states: torch.Tensor) -> torch.Tensor: | ||
| # Keep a reference for the shared expert residual addition | ||
| residual = hidden_states | ||
| batch_size, seq_len, hidden_dim = hidden_states.shape | ||
|
|
||
| # Flatten to [tokens, hidden_size] for the router and experts | ||
| hidden_states_flat = hidden_states.view(-1, hidden_dim) | ||
|
|
||
| # Router: logits are captured automatically by OutputRecorder; | ||
| # we only consume the weights and indices here. | ||
| _, routing_weights, selected_experts = self.gate(hidden_states_flat) | ||
|
|
||
| # Routed experts: sparse computation over selected_experts | ||
| routed_output = self.experts(hidden_states_flat, selected_experts, routing_weights) | ||
| routed_output = routed_output.view(batch_size, seq_len, hidden_dim) | ||
|
|
||
| # Shared expert: dense computation on all tokens, added to routed output | ||
| hidden_states = routed_output + self.shared_experts(residual) | ||
| return hidden_states | ||
|
|
There was a problem hiding this comment.
this can be entirely inherited!
| # ---- 1. Compute raw logits in fp32 -------------------------------- | ||
| router_logits = F.linear(hidden_states.float(), self.weight.float()) | ||
| # router_logits: [tokens, num_experts] | ||
|
|
||
| # ---- 2. Compute unbiased scores (used as output weights) ---------- | ||
| if self.score_function == "sigmoid": | ||
| scores = torch.sigmoid(router_logits) | ||
| else: # "softmax" | ||
| scores = torch.softmax(router_logits, dim=-1) | ||
|
|
||
| # ---- 3. Compute biased scores (used for routing decision only) ---- | ||
| if self.expert_bias is not None: | ||
| scores_for_routing = scores + self.expert_bias.float() | ||
| else: | ||
| scores_for_routing = scores | ||
|
|
||
| # ---- 4. Group-limited top-k (no-op when n_group == 1) ------------- | ||
| if self.n_group > 1 and self.topk_group < self.n_group: | ||
| num_tokens = hidden_states.shape[0] | ||
| experts_per_group = self.num_experts // self.n_group | ||
|
|
||
| # Max score per group → select topk_group best groups | ||
| group_scores = scores_for_routing.view(num_tokens, self.n_group, experts_per_group).max(dim=-1).values | ||
| group_idx = torch.topk(group_scores, k=self.topk_group, dim=-1, sorted=False)[1] | ||
|
|
||
| # Build a mask that zeros out experts in non-selected groups | ||
| group_mask = torch.zeros_like(group_scores) | ||
| group_mask.scatter_(1, group_idx, 1) | ||
| score_mask = ( | ||
| group_mask.unsqueeze(-1).expand(num_tokens, self.n_group, experts_per_group).reshape(num_tokens, -1) | ||
| ) | ||
| scores_for_routing = scores_for_routing.masked_fill(~score_mask.bool(), 0.0) | ||
|
|
||
| # ---- 5. Select top-k experts using biased scores ------------------ | ||
| _, topk_idx = torch.topk(scores_for_routing, k=self.top_k, dim=-1, sorted=False) | ||
|
|
||
| # ---- 6. Gather *unbiased* scores as actual output weights --------- | ||
| topk_weights = scores.gather(1, topk_idx) | ||
|
|
||
| # ---- 7. Normalize and scale --------------------------------------- | ||
| if self.norm_topk_prob: | ||
| topk_weights = topk_weights / (topk_weights.sum(dim=-1, keepdim=True) + 1e-9) | ||
|
|
||
| topk_weights = (topk_weights * self.routed_scaling_factor).to(hidden_states.dtype) | ||
|
|
||
| return router_logits, topk_weights, topk_idx |
There was a problem hiding this comment.
we need to remove code paths and collapse to only parameters used in models that are released!
this will standardize and allow inheritance in most cases, or will isolate the difference this model vs other models 😉
There was a problem hiding this comment.
Thanks for the review @ArthurZucker!
Addressed both points:
Param2MoERouter - simplified to only the paths used by the released model: sigmoid routing is hardcoded (removed softmax), expert_bias is always present, and the unused group-routing logic (n_group=1) was removed.
Param2MoESparseMoeBlock - now inherits from DeepseekV2Moe since the shared-expert + residual pattern is identical. init swaps in Param2MoERouter and Param2 config names, while forward remains a minimal override because the parent implementation depends on self.gate.weight and route_tokens_to_experts(), which don't match our router abstraction.
ArthurZucker
left a comment
There was a problem hiding this comment.
also this only include the LLM part right?
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
…kV2Moe Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
|
View the CircleCI Test Summary for this PR: https://huggingface.co/spaces/transformers-community/circle-ci-viz?pr=46395&sha=23356e |
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
|
Hey @ArthurZucker the What we found: Key facts confirming this is not a TP correctness bug:
I saw the Is this the right approach, or would you prefer a different strategy (e.g. exposing |
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
Signed-off-by: bhargav-patel-29 <bhargav.patel@tihiitb.org>
|
[For maintainers] Suggested jobs to run (before merge) run-slow: auto, param2moe |
CI recapDashboard: View test results in Grafana |
What does this PR do?
This PR adds support for Param-2-17B-MoE-A2.4B, a large-scale Mixture-of-Experts (MoE) causal language model.
Param-2-17B-MoE-A2.4B uses a Hybrid Dense + MoE architecture with 17B total parameters while activating only 2.4B parameters per token, enabling high model capacity with efficient inference cost.
The model is pretrained from scratch with strong multilingual capabilities and particular emphasis on linguistic diversity and Indian language representation. It is released as a pretrained base model intended for downstream fine-tuning.
This integration enables seamless loading, inference, and downstream fine-tuning using standard Transformers APIs.
Before submitting
Pull Request section?
to it if that's the case.
documentation guidelines, and
here are tips on formatting docstrings.
Who can review?
Text models: @ArthurZucker @Cyrilvallez