CoolFace
Modelpublic

vikhyatk/moondream2

sourceHugging Faceapache-2.0updated 1d agoView on Hugging Face
1.4klikes2mdownloads
weights.py293 linesDownload Raw Back to root
1import safetensors2import torch3import torch.nn as nn4 5from contextlib import contextmanager6from dataclasses import dataclass7from typing import Callable, List8 9from .layers import AttentionWeights, LayerNormWeights, LinearWeights, MLPWeights10 11 12@dataclass13class VisionBlock:14    ln1: LayerNormWeights15    attn: AttentionWeights16    ln2: LayerNormWeights17    mlp: MLPWeights18 19 20@dataclass21class VisionModel:22    patch_emb: LinearWeights23    pos_emb: torch.Tensor24    blocks: List[VisionBlock]25    post_ln: LayerNormWeights26    proj_mlp: MLPWeights27 28 29@dataclass30class TextBlock:31    ln: LayerNormWeights32    attn: AttentionWeights33    mlp: MLPWeights34 35 36@dataclass37class TextModel:38    wte: torch.Tensor39    blocks: List[TextBlock]40    post_ln: LayerNormWeights41    lm_head: LinearWeights42 43 44@dataclass45class RegionModel:46    coord_features: torch.Tensor47    coord_encoder: LinearWeights48    coord_decoder: MLPWeights49    size_features: torch.Tensor50    size_encoder: LinearWeights51    size_decoder: MLPWeights52 53 54@dataclass55class MoondreamModel:56    vision: VisionModel57    text: TextModel58    region: RegionModel59 60 61@contextmanager62def safetensors_open(safetensors_file: str):63    """64    Simplify interfacing with safetensors files. Eliminates the need to ignore65    type errors when using the `safe_open` function.66    """67    with safetensors.safe_open(68        safetensors_file, framework="pt"69    ) as st:  # pyright: ignore70 71        def get_tensor(name: str) -> torch.Tensor:72            return st.get_tensor(name)73 74        def get_keys() -> List[str]:75            return st.keys()76 77        get_tensor.keys = get_keys78 79        yield get_tensor80 81 82def _load_weights(get_tensor: Callable[[str], torch.Tensor], model: nn.Module) -> None:83    """Internal function to load weights using a tensor getter function."""84    model = model.to(dtype=torch.float16)85 86    # Vision Model87    model.vision["patch_emb"].weight.data.copy_(88        get_tensor("vision_encoder.encoder.model.visual.patch_embed.linear.weight")89    )90    model.vision["patch_emb"].bias.data.copy_(91        get_tensor("vision_encoder.encoder.model.visual.patch_embed.linear.bias")92    )93    model.vision.pos_emb.data.copy_(94        get_tensor("vision_encoder.encoder.model.visual.pos_embed")95    )96 97    for i in range(len(model.vision["blocks"])):98        prefix = f"vision_encoder.encoder.model.visual.blocks.{i}"99 100        # Layer norms101        model.vision["blocks"][i]["ln1"].weight.data.copy_(102            get_tensor(f"{prefix}.norm1.weight")103        )104        model.vision["blocks"][i]["ln1"].bias.data.copy_(105            get_tensor(f"{prefix}.norm1.bias")106        )107        model.vision["blocks"][i]["ln2"].weight.data.copy_(108            get_tensor(f"{prefix}.norm2.weight")109        )110        model.vision["blocks"][i]["ln2"].bias.data.copy_(111            get_tensor(f"{prefix}.norm2.bias")112        )113 114        # Attention115        model.vision["blocks"][i]["attn"]["qkv"].weight.data.copy_(116            get_tensor(f"{prefix}.attn.qkv.weight")117        )118        model.vision["blocks"][i]["attn"]["qkv"].bias.data.copy_(119            get_tensor(f"{prefix}.attn.qkv.bias")120        )121        model.vision["blocks"][i]["attn"]["proj"].weight.data.copy_(122            get_tensor(f"{prefix}.attn.proj.weight")123        )124        model.vision["blocks"][i]["attn"]["proj"].bias.data.copy_(125            get_tensor(f"{prefix}.attn.proj.bias")126        )127 128        # MLP129        model.vision["blocks"][i]["mlp"]["fc1"].weight.data.copy_(130            get_tensor(f"{prefix}.mlp.fc1.weight")131        )132        model.vision["blocks"][i]["mlp"]["fc1"].bias.data.copy_(133            get_tensor(f"{prefix}.mlp.fc1.bias")134        )135        model.vision["blocks"][i]["mlp"]["fc2"].weight.data.copy_(136            get_tensor(f"{prefix}.mlp.fc2.weight")137        )138        model.vision["blocks"][i]["mlp"]["fc2"].bias.data.copy_(139            get_tensor(f"{prefix}.mlp.fc2.bias")140        )141 142    model.vision["post_ln"].weight.data.copy_(143        get_tensor("vision_encoder.encoder.model.visual.norm.weight")144    )145    model.vision["post_ln"].bias.data.copy_(146        get_tensor("vision_encoder.encoder.model.visual.norm.bias")147    )148 149    model.vision["proj_mlp"]["fc1"].weight.data.copy_(150        get_tensor("vision_encoder.projection.mlp.fc1.weight")151    )152    model.vision["proj_mlp"]["fc1"].bias.data.copy_(153        get_tensor("vision_encoder.projection.mlp.fc1.bias")154    )155    model.vision["proj_mlp"]["fc2"].weight.data.copy_(156        get_tensor("vision_encoder.projection.mlp.fc2.weight")157    )158    model.vision["proj_mlp"]["fc2"].bias.data.copy_(159        get_tensor("vision_encoder.projection.mlp.fc2.bias")160    )161 162    # Text Model163    model.text.wte.data.copy_(get_tensor("text_model.transformer.embd.wte.weight"))164 165    for i in range(len(model.text["blocks"])):166        prefix = f"text_model.transformer.h.{i}"167 168        # Layer norm169        model.text["blocks"][i]["ln"].weight.data.copy_(170            get_tensor(f"{prefix}.ln.weight")171        )172        model.text["blocks"][i]["ln"].bias.data.copy_(get_tensor(f"{prefix}.ln.bias"))173 174        # Attention175        model.text["blocks"][i]["attn"]["qkv"].weight.data.copy_(176            get_tensor(f"{prefix}.mixer.Wqkv.weight")177        )178        model.text["blocks"][i]["attn"]["qkv"].bias.data.copy_(179            get_tensor(f"{prefix}.mixer.Wqkv.bias")180        )181        model.text["blocks"][i]["attn"]["proj"].weight.data.copy_(182            get_tensor(f"{prefix}.mixer.out_proj.weight")183        )184        model.text["blocks"][i]["attn"]["proj"].bias.data.copy_(185            get_tensor(f"{prefix}.mixer.out_proj.bias")186        )187 188        # MLP189        model.text["blocks"][i]["mlp"]["fc1"].weight.data.copy_(190            get_tensor(f"{prefix}.mlp.fc1.weight")191        )192        model.text["blocks"][i]["mlp"]["fc1"].bias.data.copy_(193            get_tensor(f"{prefix}.mlp.fc1.bias")194        )195        model.text["blocks"][i]["mlp"]["fc2"].weight.data.copy_(196            get_tensor(f"{prefix}.mlp.fc2.weight")197        )198        model.text["blocks"][i]["mlp"]["fc2"].bias.data.copy_(199            get_tensor(f"{prefix}.mlp.fc2.bias")200        )201 202    model.text["post_ln"].weight.data.copy_(get_tensor("text_model.lm_head.ln.weight"))203    model.text["post_ln"].bias.data.copy_(get_tensor("text_model.lm_head.ln.bias"))204 205    model.text["lm_head"].weight.data.copy_(206        get_tensor("text_model.lm_head.linear.weight")207    )208    model.text["lm_head"].bias.data.copy_(get_tensor("text_model.lm_head.linear.bias"))209 210    # Region Model211    model.region.coord_features.data.copy_(212        get_tensor("region_model.coordinate_features.weight").T213    )214    model.region["coord_encoder"].weight.data.copy_(215        get_tensor("region_model.coordinate_encoder.weight")216    )217    model.region["coord_encoder"].bias.data.copy_(218        get_tensor("region_model.coordinate_encoder.bias")219    )220 221    model.region["coord_decoder"]["fc1"].weight.data.copy_(222        get_tensor("region_model.coordinate_decoder.fc1.weight")223    )224    model.region["coord_decoder"]["fc1"].bias.data.copy_(225        get_tensor("region_model.coordinate_decoder.fc1.bias")226    )227    model.region["coord_decoder"]["fc2"].weight.data.copy_(228        get_tensor("region_model.coordinate_decoder.fc2.weight")229    )230    model.region["coord_decoder"]["fc2"].bias.data.copy_(231        get_tensor("region_model.coordinate_decoder.fc2.bias")232    )233 234    model.region.size_features.data.copy_(235        get_tensor("region_model.size_features.weight").T236    )237    model.region["size_encoder"].weight.data.copy_(238        get_tensor("region_model.size_encoder.weight")239    )240    model.region["size_encoder"].bias.data.copy_(241        get_tensor("region_model.size_encoder.bias")242    )243 244    model.region["size_decoder"]["fc1"].weight.data.copy_(245        get_tensor("region_model.size_decoder.fc1.weight")246    )247    model.region["size_decoder"]["fc1"].bias.data.copy_(248        get_tensor("region_model.size_decoder.fc1.bias")249    )250    model.region["size_decoder"]["fc2"].weight.data.copy_(251        get_tensor("region_model.size_decoder.fc2.weight")252    )253    model.region["size_decoder"]["fc2"].bias.data.copy_(254        get_tensor("region_model.size_decoder.fc2.bias")255    )256 257 258def load_weights_from_safetensors(weights_file: str, model: nn.Module) -> None:259    """Load weights from a safetensors file into a MoondreamModel instance."""260    with safetensors_open(weights_file) as get_tensor:261        # Wrap the get_tensor function to handle key normalization262        name_map = {k.replace("._orig_mod", ""): k for k in get_tensor.keys()}263        _load_weights(lambda x: get_tensor(name_map[x]).to(dtype=torch.float16), model)264 265 266def load_weights_from_pt(weights_file: str, model: nn.Module) -> None:267    """Load weights from a PyTorch file into a MoondreamModel instance."""268    device = str(torch.empty(0).device)269    tensors = torch.load(weights_file, map_location=device, weights_only=True)270    tensors = {271        k.replace("._orig_mod", ""): v.to(dtype=torch.float16)272        for k, v in tensors.items()273    }274    _load_weights(lambda x: tensors[x], model)275 276 277def load_weights_into_model(weights_file: str, model: nn.Module) -> None:278    """279    Load weights from either a safetensors or PyTorch file directly into a MoondreamModel instance.280 281    Args:282        weights_file: Path to weights file (either .safetensors or .pt)283        model: MoondreamModel instance to load weights into284    """285    if weights_file.endswith(".safetensors"):286        load_weights_from_safetensors(weights_file, model)287    else:288        load_weights_from_pt(weights_file, model)289 290    # Make all parameters contiguous291    for param in model.parameters():292        param.data = param.data.contiguous()293