Skip to content

Commit 57c0921

Browse files
model : support MTP in GLM-4.7-Flash (ggml-org#24868)
1 parent ee0445c commit 57c0921

4 files changed

Lines changed: 379 additions & 25 deletions

File tree

conversion/glm.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,70 @@ def prepare_tensors(self):
206206
@ModelBase.register("Glm4MoeLiteForCausalLM")
207207
class Glm4MoeLiteModel(DeepseekV2Model):
208208
model_arch = gguf.MODEL_ARCH.DEEPSEEK2
209+
skip_mtp = False
210+
supports_mtp_export = True
211+
_n_main_layers: int | None = None
209212

210213
def set_vocab(self):
211214
return self._set_vocab_glm()
212215

216+
def __init__(self, *args, **kwargs):
217+
super().__init__(*args, **kwargs)
218+
219+
num_hidden_layers = self.hparams["num_hidden_layers"]
220+
self.num_nextn_predict_layers = self.hparams.get("num_nextn_predict_layers", 0)
221+
self.skip_mtp = self.no_mtp or self.num_nextn_predict_layers == 0
222+
223+
if self.skip_mtp:
224+
self.block_count = num_hidden_layers
225+
else:
226+
self.block_count = num_hidden_layers + self.num_nextn_predict_layers
227+
228+
self.tensor_map = gguf.get_tensor_name_map(self.model_arch, self.block_count)
229+
230+
def set_gguf_parameters(self):
231+
super().set_gguf_parameters()
232+
233+
if self.skip_mtp:
234+
return
235+
236+
self.gguf_writer.add_nextn_predict_layers(self.num_nextn_predict_layers)
237+
238+
def index_tensors(self, remote_hf_model_id: str | None = None):
239+
type(self)._n_main_layers = self.hparams["num_hidden_layers"]
240+
return super().index_tensors(remote_hf_model_id=remote_hf_model_id)
241+
242+
@classmethod
243+
def filter_tensors(cls, item):
244+
if (titem := super().filter_tensors(item)) is None:
245+
return None
246+
name, gen = titem
247+
248+
if cls._n_main_layers is not None:
249+
match = re.match(r"model\.layers\.(\d+)\.", name)
250+
is_mtp = match is not None and int(match.group(1)) >= cls._n_main_layers
251+
if is_mtp and cls.no_mtp:
252+
return None
253+
if cls.mtp_only and not is_mtp and name not in (
254+
"model.embed_tokens.weight", "model.norm.weight", "lm_head.weight",
255+
):
256+
return None
257+
258+
return name, gen
259+
260+
def prepare_metadata(self, vocab_only: bool):
261+
from_dir = self.fname_out.is_dir()
262+
super().prepare_metadata(vocab_only=vocab_only)
263+
264+
if not self.mtp_only or not from_dir:
265+
return
266+
267+
output_type: str = self.ftype.name.partition("_")[2]
268+
fname_default: str = gguf.naming_convention(
269+
self.metadata.name, self.metadata.basename, self.metadata.finetune,
270+
self.metadata.version, size_label=None, output_type=output_type, model_type=None)
271+
self.fname_out = self.fname_out.parent / f"mtp-{fname_default}.gguf"
272+
213273

214274
@ModelBase.register("GlmMoeDsaForCausalLM")
215275
class GlmMoeDsaModel(DeepseekV2Model):

gguf-py/gguf/constants.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3221,6 +3221,13 @@ class MODEL_TENSOR(IntEnum):
32213221
MODEL_TENSOR.FFN_DOWN_SHEXP,
32223222
MODEL_TENSOR.FFN_UP_SHEXP,
32233223
MODEL_TENSOR.FFN_EXP_PROBS_B,
3224+
# NextN/MTP tensors
3225+
MODEL_TENSOR.NEXTN_EH_PROJ,
3226+
MODEL_TENSOR.NEXTN_EMBED_TOKENS,
3227+
MODEL_TENSOR.NEXTN_ENORM,
3228+
MODEL_TENSOR.NEXTN_HNORM,
3229+
MODEL_TENSOR.NEXTN_SHARED_HEAD_HEAD,
3230+
MODEL_TENSOR.NEXTN_SHARED_HEAD_NORM,
32243231
],
32253232
MODEL_ARCH.DEEPSEEK2OCR: [
32263233
MODEL_TENSOR.TOKEN_EMBD,

0 commit comments

Comments
 (0)