char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Xuan-Son Nguyenconvert: add @ModelBase.example (#27208)fa88ae936

char/aliceai-t5-moe
4.3 KiB118 linesraw
1from __future__ import annotations
2
3from typing import Callable, Iterable, TYPE_CHECKING
4
5if TYPE_CHECKING:
6    from torch import Tensor
7
8from .base import MmprojModel, ModelBase, gguf
9
10from .llama import LlamaModel
11
12
13@ModelBase.register("JanusForConditionalGeneration")
14@ModelBase.example("deepseek-community/Janus-Pro-1B")
15class JanusProModel(LlamaModel):
16    model_arch = gguf.MODEL_ARCH.LLAMA  # reuse Llama arch
17
18    @classmethod
19    def filter_tensors(cls, item: tuple[str, Callable[[], Tensor]]) -> tuple[str, Callable[[], Tensor]] | None:
20        name, gen = item
21
22        # Skip vision, aligner, and generation tensors
23        skip_prefixes = (
24            'model.vision_model.',
25            'model.aligner.',
26            'model.vqmodel.',
27            'model.generation_embeddings.',
28            'model.generation_aligner.',
29            'model.generation_head.',
30        )
31        if name.startswith(skip_prefixes):
32            return None
33
34        return super().filter_tensors(item)
35
36
37@ModelBase.register("JanusForConditionalGeneration")
38@ModelBase.example("deepseek-community/Janus-Pro-1B")
39class JanusProVisionModel(MmprojModel):
40    def __init__(self, *args, **kwargs):
41        super().__init__(*args, **kwargs)
42        assert self.hparams_vision is not None
43        if "intermediate_size" not in self.hparams_vision:
44            mlp_ratio = self.hparams_vision.get("mlp_ratio")
45            hidden_size = self.hparams_vision.get("hidden_size")
46            if mlp_ratio is not None and hidden_size is not None:
47                self.hparams_vision["intermediate_size"] = int(round(hidden_size * mlp_ratio))
48
49    def set_gguf_parameters(self):
50        super().set_gguf_parameters()
51        assert self.hparams_vision is not None
52
53        self.gguf_writer.add_clip_projector_type(gguf.VisionProjectorType.JANUS_PRO)
54
55        self.gguf_writer.add_vision_attention_layernorm_eps(self.hparams_vision.get("layer_norm_eps", 1e-6))
56
57        hidden_act = str(self.hparams_vision.get("hidden_act", "")).lower()
58        if hidden_act == "gelu":
59            self.gguf_writer.add_vision_use_gelu(True)
60        elif hidden_act == "silu":
61            self.gguf_writer.add_vision_use_silu(True)
62
63    def _map_aligner_tensor(self, data_torch: Tensor, name: str) -> Iterable[tuple[str, Tensor]]:
64        """Map aligner tensors to projector format"""
65        suffix = ".bias" if name.endswith(".bias") else ".weight"
66
67        if name.startswith("model.aligner."):
68            local_name = name[len("model.aligner."):]
69        elif name.startswith("aligner."):
70            local_name = name[len("aligner."):]
71        else:
72            raise ValueError(f"Unsupported Janus aligner prefix: {name}")
73
74        if local_name.startswith("fc1."):
75            mm_index = 0
76        elif local_name.startswith("hidden_layers."):
77            parts = local_name.split(".", 2)
78            if len(parts) < 3:
79                raise ValueError(f"Unexpected Janus aligner tensor name: {name}")
80            mm_index = int(parts[1]) + 1
81        else:
82            raise ValueError(f"Unsupported Janus aligner tensor: {name}")
83
84        tensor_name = self.format_tensor_name(gguf.MODEL_TENSOR.V_MMPROJ, mm_index, suffix=suffix)
85        return [(tensor_name, data_torch)]
86
87    @classmethod
88    def filter_tensors(cls, item: tuple[str, Callable[[], Tensor]]) -> tuple[str, Callable[[], Tensor]] | None:
89        name, gen = item
90
91        # Skip generation-related components
92        skip_generation_prefixes = (
93            'model.vqmodel.',
94            'vqmodel.',
95            'model.generation_embeddings.',
96            'generation_embeddings.',
97            'model.generation_aligner.',
98            'generation_aligner.',
99            'model.generation_head.',
100            'generation_head.',
101        )
102        if name.startswith(skip_generation_prefixes):
103            return None
104
105        return super().filter_tensors(item)
106
107    def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iterable[tuple[str, Tensor]]:
108        # Handle aligner tensors
109        if name.startswith(('model.aligner.', 'aligner.')):
110            yield from self._map_aligner_tensor(data_torch, name)
111            return
112
113        # Handle vision tensors
114        if name.startswith(('model.vision_model.', 'vision_model.')):
115            yield from super().modify_tensors(data_torch, name, bid)
116            return
117
118        return