Skip to content

Commit 1e5ad35

Browse files
model : add sarvam_moe architecture support (ggml-org#20275)
1 parent 65d7a8b commit 1e5ad35

4 files changed

Lines changed: 46 additions & 0 deletions

File tree

convert_hf_to_gguf.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,9 @@ def get_vocab_base_pre(self, tokenizer) -> str:
15701570
if chkhsh == "862f827721df956049dff5ca81a57f29e575280bc622e290d3bf4e35eca29015":
15711571
# ref: https://huggingface.co/codefuse-ai/F2LLM-v2-4B
15721572
res = "f2llmv2"
1573+
if chkhsh == "62f6fb0a6fd5098caeabb19b07a5c1099cafc8b9c40eab6ea89ece4ec02fbc57":
1574+
# ref: https://huggingface.co/sarvamai/sarvam-30b
1575+
res = "sarvam-moe"
15731576

15741577
if res is None:
15751578
logger.warning("\n")
@@ -11591,6 +11594,34 @@ def prepare_tensors(self):
1159111594
raise ValueError(f"Unprocessed experts: {experts}")
1159211595

1159311596

11597+
@ModelBase.register("SarvamMoEForCausalLM", "modeling_sarvam_moe.SarvamMoEForCausalLM")
11598+
class SarvamMoEModel(BailingMoeV2Model):
11599+
model_arch = gguf.MODEL_ARCH.BAILINGMOE2
11600+
# Sarvam-MoE shares the BailingMoeV2 architecture; only differences:
11601+
# - full rotary (no partial_rotary_factor)
11602+
# - expert bias is zero-mean normalized at load time
11603+
11604+
def set_gguf_parameters(self):
11605+
super().set_gguf_parameters()
11606+
hparams = self.hparams
11607+
if (rope_dim := hparams.get("head_dim")) is None:
11608+
rope_dim = hparams["hidden_size"] // hparams["num_attention_heads"]
11609+
# Override the partial-rotary value written by BailingMoeV2 with the full rotary dim
11610+
self.gguf_writer.add_rope_dimension_count(rope_dim)
11611+
11612+
@classmethod
11613+
def filter_tensors(cls, item: tuple[str, Callable[[], Tensor]]) -> tuple[str, Callable[[], Tensor]] | None:
11614+
name, gen = item
11615+
if name.endswith(".expert_bias"):
11616+
# Sarvam normalizes expert bias to zero mean
11617+
inner = gen
11618+
11619+
def gen():
11620+
t = inner()
11621+
return t - t.mean()
11622+
return super().filter_tensors((name, gen))
11623+
11624+
1159411625
@ModelBase.register("GroveMoeForCausalLM", "modeling_grove_moe.GroveMoeForCausalLM")
1159511626
class GroveMoeModel(TextModel):
1159611627
model_arch = gguf.MODEL_ARCH.GROVEMOE

convert_hf_to_gguf_update.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ class TOKENIZER_TYPE(IntEnum):
155155
{"name": "joyai-llm", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/jdopensource/JoyAI-LLM-Flash", },
156156
{"name": "kanana2", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/kakaocorp/kanana-2-30b-a3b-instruct-2601", },
157157
{"name": "f2llmv2", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/codefuse-ai/F2LLM-v2-4B", },
158+
{"name": "sarvam-moe", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/sarvamai/sarvam-30b", },
158159
]
159160

160161
# some models are known to be broken upstream, so we will skip them as exceptions

src/llama-vocab.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,14 @@ struct llm_tokenizer_bpe : llm_tokenizer {
503503
};
504504
byte_encode = false; // uses raw UTF-8, not GPT-2 byte encoding
505505
break;
506+
case LLAMA_VOCAB_PRE_TYPE_SARVAM_MOE:
507+
// Sarvam uses SPM-style BPE (same shape as Gemma4): spaces replaced with U+2581
508+
// by the normalizer, BPE merges over the whole text on raw UTF-8.
509+
regex_exprs = {
510+
"[^\\n]+|[\\n]+",
511+
};
512+
byte_encode = false;
513+
break;
506514
default:
507515
// default regex for BPE tokenization pre-processing
508516
regex_exprs = {
@@ -2005,6 +2013,11 @@ void llama_vocab::impl::load(llama_model_loader & ml, const LLM_KV & kv) {
20052013
tokenizer_pre == "gemma4") {
20062014
pre_type = LLAMA_VOCAB_PRE_TYPE_GEMMA4;
20072015
escape_whitespaces = true;
2016+
} else if (
2017+
tokenizer_pre == "sarvam-moe") {
2018+
pre_type = LLAMA_VOCAB_PRE_TYPE_SARVAM_MOE;
2019+
escape_whitespaces = true;
2020+
clean_spaces = false;
20082021
} else if (
20092022
tokenizer_pre == "jina-v1-en" ||
20102023
tokenizer_pre == "jina-v2-code" ||

src/llama-vocab.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ enum llama_vocab_pre_type {
5959
LLAMA_VOCAB_PRE_TYPE_JOYAI_LLM = 48,
6060
LLAMA_VOCAB_PRE_TYPE_JAIS2 = 49,
6161
LLAMA_VOCAB_PRE_TYPE_GEMMA4 = 50,
62+
LLAMA_VOCAB_PRE_TYPE_SARVAM_MOE = 51,
6263
};
6364

6465
struct LLM_KV;

0 commit comments

Comments
 (0)