@@ -1062,6 +1062,9 @@ def get_vocab_base_pre(self, tokenizer) -> str:
10621062 if chkhsh == "66b8d4e19ab16c3bfd89bce5d785fb7e0155e8648708a1f42077cb9fe002c273":
10631063 # ref: https://huggingface.co/alvarobartt/grok-2-tokenizer
10641064 res = "grok-2"
1065+ if chkhsh == "b3d1dd861f1d4c5c0d2569ce36baf3f90fe8a102db3de50dd71ff860d91be3df":
1066+ # ref: https://huggingface.co/aari1995/German_Semantic_V3
1067+ res = "jina-v2-de"
10651068 if chkhsh == "0ef9807a4087ebef797fc749390439009c3b9eda9ad1a097abbe738f486c01e5":
10661069 # ref: https://huggingface.co/meta-llama/Meta-Llama-3-8B
10671070 res = "llama-bpe"
@@ -1230,6 +1233,12 @@ def get_vocab_base_pre(self, tokenizer) -> str:
12301233 if chkhsh == "4a2e2abae11ca2b86d570fc5b44be4d5eb5e72cc8f22dd136a94b37da83ab665":
12311234 # ref: https://huggingface.co/KORMo-Team/KORMo-tokenizer
12321235 res = "kormo"
1236+ if chkhsh == "9d70134b369a70e5735009b6de918f7581b5211f7c074d1f89f753aea8248af1":
1237+ # ref: https://huggingface.co/tencent/Youtu-LLM-2B
1238+ res = "youtu"
1239+ if chkhsh == "16389f0a1f51ee53e562ffd51c371dc508639ab0e4261502071836e50e223e91":
1240+ # ref: https://huggingface.co/upstage/Solar-Open-100B
1241+ res = "solar-open"
12331242
12341243 if res is None:
12351244 logger.warning("\n")
@@ -2486,6 +2495,7 @@ def prepare_tensors(self):
24862495 "VLlama3ForCausalLM",
24872496 "LlavaForConditionalGeneration",
24882497 "VoxtralForConditionalGeneration",
2498+ "IQuestCoderForCausalLM",
24892499 "LlamaModel")
24902500class LlamaModel(TextModel):
24912501 model_arch = gguf.MODEL_ARCH.LLAMA
@@ -5284,13 +5294,14 @@ def set_vocab(self):
52845294 self.gguf_writer.add_token_type_count(self.hparams.get("type_vocab_size", 1))
52855295
52865296 # convert to phantom space vocab
5287- def phantom (tok ):
5288- if tok . startswith ( "[" ) and tok . endswith ( "]" ) :
5297+ def phantom(tok, toktype ):
5298+ if toktype == gguf.TokenType.CONTROL :
52895299 return tok
52905300 if tok.startswith("##"):
52915301 return tok[2:]
52925302 return "\u2581" + tok
5293- tokens = list (map (phantom , tokens ))
5303+ assert len(tokens) == len(toktypes)
5304+ tokens = list(map(phantom, tokens, toktypes))
52945305
52955306 # add vocab to gguf
52965307 self.gguf_writer.add_tokenizer_model("bert")
@@ -7181,6 +7192,7 @@ def prepare_tensors(self):
71817192 "DeepseekV2ForCausalLM",
71827193 "DeepseekV3ForCausalLM",
71837194 "KimiVLForConditionalGeneration",
7195+ "YoutuForCausalLM",
71847196)
71857197class DeepseekV2Model(TextModel):
71867198 model_arch = gguf.MODEL_ARCH.DEEPSEEK2
@@ -7247,7 +7259,15 @@ def set_gguf_parameters(self):
72477259 super().set_gguf_parameters()
72487260 hparams = self.hparams
72497261
7250- self .gguf_writer .add_leading_dense_block_count (hparams ["first_k_dense_replace" ])
7262+ # first_k_dense_replace: number of leading layers using dense FFN instead of MoE
7263+ # For non-MoE models (like Youtu), set to n_layer to use dense FFN for all layers
7264+ # For MoE models (like DeepSeek-V2), this is the number of leading non-MoE layers
7265+ has_moe = hparams.get("n_routed_experts") is not None
7266+ first_k_dense_replace = hparams.get("first_k_dense_replace")
7267+ if first_k_dense_replace is None:
7268+ # Default: if no MoE, all layers are dense; if MoE, none are dense
7269+ first_k_dense_replace = hparams["num_hidden_layers"] if not has_moe else 0
7270+ self.gguf_writer.add_leading_dense_block_count(first_k_dense_replace)
72517271 self.gguf_writer.add_vocab_size(hparams["vocab_size"])
72527272 if "q_lora_rank" in hparams and hparams["q_lora_rank"] is not None:
72537273 self.gguf_writer.add_q_lora_rank(hparams["q_lora_rank"])
@@ -7259,11 +7279,24 @@ def set_gguf_parameters(self):
72597279 self.gguf_writer.add_key_length_mla(hparams["qk_nope_head_dim"] + hparams["qk_rope_head_dim"])
72607280 self.gguf_writer.add_value_length_mla(hparams["v_head_dim"])
72617281
7262- self .gguf_writer .add_expert_feed_forward_length (hparams ["moe_intermediate_size" ])
7263- self .gguf_writer .add_expert_count (hparams ["n_routed_experts" ])
7264- self .gguf_writer .add_expert_shared_count (hparams ["n_shared_experts" ])
7265- self .gguf_writer .add_expert_weights_scale (hparams ["routed_scaling_factor" ])
7266- self .gguf_writer .add_expert_weights_norm (hparams ["norm_topk_prob" ])
7282+ # MoE parameters (required by C++ code for DEEPSEEK2 arch)
7283+ # For non-MoE models like Youtu, use intermediate_size as expert_feed_forward_length
7284+ moe_intermediate_size = self.find_hparam(["moe_intermediate_size", "intermediate_size"], optional=False)
7285+ self.gguf_writer.add_expert_feed_forward_length(moe_intermediate_size)
7286+
7287+ if (n_routed_experts := hparams.get("n_routed_experts")) is not None:
7288+ self.gguf_writer.add_expert_count(n_routed_experts)
7289+
7290+ # expert_shared_count is required by C++ code, default to 0 for non-MoE models
7291+ n_shared_experts = hparams.get("n_shared_experts", 0)
7292+ self.gguf_writer.add_expert_shared_count(n_shared_experts)
7293+
7294+ # When not set, C++ code will use scale_w = false to skip the no-op scaling
7295+ if (routed_scaling_factor := hparams.get("routed_scaling_factor")) is not None:
7296+ self.gguf_writer.add_expert_weights_scale(routed_scaling_factor)
7297+
7298+ if (norm_topk_prob := hparams.get("norm_topk_prob")) is not None and norm_topk_prob:
7299+ self.gguf_writer.add_expert_weights_norm(norm_topk_prob)
72677300
72687301 self.gguf_writer.add_rope_dimension_count(hparams["qk_rope_head_dim"])
72697302
@@ -7279,10 +7312,17 @@ def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iter
72797312 # skip vision tensors and remove "language_model." for Kimi-VL
72807313 if "vision_tower" in name or "multi_modal_projector" in name:
72817314 return []
7282-
7315+ if name.startswith("siglip2.") or name.startswith("merger."):
7316+ return []
72837317 if name.startswith("language_model."):
72847318 name = name.replace("language_model.", "")
72857319
7320+ # skip lm_head.weight if tie_word_embeddings is True
7321+ if self.hparams.get("tie_word_embeddings", False):
7322+ if name == "lm_head.weight" or name == "model.lm_head.weight":
7323+ logger.info("Skipping tied output layer 'lm_head.weight' (will use token_embd.weight)")
7324+ return []
7325+
72867326 # rename e_score_correction_bias tensors
72877327 if name.endswith("e_score_correction_bias"):
72887328 name = name.replace("e_score_correction_bias", "e_score_correction.bias")
@@ -10617,6 +10657,79 @@ def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iter
1061710657 return []
1061810658
1061910659
10660+ @ModelBase.register("YOUTUVLForConditionalGeneration", "YOUTUVLForCausalLM")
10661+ class YOUTUVLVisionModel(MmprojModel):
10662+ def __init__(self, *args, **kwargs):
10663+ super().__init__(*args, **kwargs)
10664+ assert self.hparams_vision is not None
10665+ self.hparams_vision["image_size"] = self.hparams_vision.get("image_size", 560)
10666+
10667+ def set_gguf_parameters(self):
10668+ super().set_gguf_parameters()
10669+
10670+ self.gguf_writer.add_clip_projector_type(gguf.VisionProjectorType.YOUTUVL)
10671+ self.gguf_writer.add_vision_attention_layernorm_eps(self.hparams.get("layer_norm_eps", 1e-6))
10672+
10673+ # Handle activation function
10674+ hidden_act = str(self.hparams.get("hidden_act", "gelu_pytorch_tanh")).lower()
10675+ if hidden_act in ("gelu", "gelu_pytorch_tanh", "gelu_fast", "gelu_new", "gelu_accurate"):
10676+ self.gguf_writer.add_vision_use_gelu(True)
10677+ elif hidden_act == "silu":
10678+ self.gguf_writer.add_vision_use_silu(True)
10679+ else:
10680+ raise ValueError(f"Unsupported activation function for YOUTUVL: {hidden_act}")
10681+
10682+ self.gguf_writer.add_vision_spatial_merge_size(self.hparams.get("spatial_merge_size", 2))
10683+
10684+ window_size = self.hparams.get("window_size")
10685+ if window_size is not None:
10686+ self.gguf_writer.add_vision_window_size(window_size)
10687+ # fullatt_block_indexes contains explicit layer indices that use full attention
10688+ # e.g., [2, 5, 8, 11] means layers 2, 5, 8, 11 use full attention
10689+ # All other layers use window attention
10690+ fullatt_block_indexes = self.hparams.get("fullatt_block_indexes")
10691+ assert fullatt_block_indexes is not None, "fullatt_block_indexes is required for youtuvl"
10692+ # Store the explicit layer indices for YoutuVL (irregular pattern approach)
10693+ self.gguf_writer.add_vision_wa_layer_indexes(layers=fullatt_block_indexes)
10694+
10695+ def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iterable[tuple[str, Tensor]]:
10696+ del bid # unused
10697+
10698+ # Skip language model tensors
10699+ skip_prefixes = ('lm_head.', 'model.layers.', 'model.embed_tokens.', 'model.norm.')
10700+ if name.startswith(skip_prefixes):
10701+ return []
10702+
10703+ # Try to map the tensor using TensorNameMap (handles vision encoder and projector)
10704+ try:
10705+ new_name = self.map_tensor_name(name)
10706+ return [(new_name, data_torch)]
10707+ except ValueError:
10708+ # If mapping fails, log warning and skip
10709+ logger.warning(f"Cannot map tensor: {name}")
10710+ return []
10711+
10712+
10713+ @ModelBase.register("SolarOpenForCausalLM")
10714+ class SolarOpenModel(Glm4MoeModel):
10715+ model_arch = gguf.MODEL_ARCH.GLM4_MOE
10716+
10717+ def set_vocab(self):
10718+ from transformers import AutoTokenizer
10719+ tokenizer = AutoTokenizer.from_pretrained(self.dir_model)
10720+ special_vocab = gguf.SpecialVocab(self.dir_model, load_merges=True)
10721+ tokens, toktypes, tokpre = self.get_vocab_base()
10722+ self.gguf_writer.add_tokenizer_model("gpt2")
10723+ self.gguf_writer.add_tokenizer_pre(tokpre)
10724+ self.gguf_writer.add_token_list(tokens)
10725+ self.gguf_writer.add_token_types(toktypes)
10726+ special_vocab._set_special_token("eos", tokenizer.get_added_vocab()["<|endoftext|>"])
10727+ special_vocab._set_special_token("eot", tokenizer.get_added_vocab()["<|endoftext|>"])
10728+ special_vocab._set_special_token("unk", tokenizer.get_added_vocab()["<unk>"])
10729+ special_vocab._set_special_token("bos", tokenizer.get_added_vocab()["<|startoftext|>"])
10730+ special_vocab.add_to_gguf(self.gguf_writer)
10731+
10732+
1062010733###### CONVERSION LOGIC ######
1062110734
1062210735
0 commit comments