|
5 | 5 |
|
6 | 6 | from __future__ import annotations |
7 | 7 |
|
8 | | -from typing import TYPE_CHECKING |
| 8 | +from typing import TYPE_CHECKING, Protocol |
9 | 9 |
|
10 | 10 | import torch |
11 | 11 | from onnxscript import OpBuilder, nn |
12 | 12 |
|
13 | 13 | from mobius._configs import ArchitectureConfig |
14 | | -from mobius.components import FCMLP |
15 | | -from mobius.components._common import INT64_MAX, Embedding, LayerNorm |
16 | | -from mobius.components._conv import Conv2d, Conv2dNoBias |
17 | | -from mobius.components._encoder import EncoderAttention |
| 14 | +from mobius.components import ( |
| 15 | + FCMLP, |
| 16 | + INT64_MAX, |
| 17 | + Conv2d, |
| 18 | + Conv2dNoBias, |
| 19 | + Embedding, |
| 20 | + EncoderAttention, |
| 21 | + LayerNorm, |
| 22 | +) |
18 | 23 |
|
19 | 24 | if TYPE_CHECKING: |
20 | 25 | import onnx_ir as ir |
21 | 26 |
|
22 | 27 |
|
| 28 | +class _CLIPVisionConfig(Protocol): |
| 29 | + hidden_size: int |
| 30 | + intermediate_size: int |
| 31 | + num_hidden_layers: int |
| 32 | + num_attention_heads: int |
| 33 | + image_size: int |
| 34 | + patch_size: int |
| 35 | + num_channels: int |
| 36 | + rms_norm_eps: float |
| 37 | + hidden_act: str | None |
| 38 | + |
| 39 | + |
23 | 40 | class ClipVisionConfigView: |
24 | 41 | """Adapter exposing a :class:`VisionConfig` under CLIP's field names. |
25 | 42 |
|
@@ -47,7 +64,7 @@ def __init__(self, vision_config, *, default_hidden_act: str = "quick_gelu"): |
47 | 64 | class _CLIPVisionEmbeddings(nn.Module): |
48 | 65 | """CLIP vision embeddings: Conv2d patch + CLS token + position embeddings.""" |
49 | 66 |
|
50 | | - def __init__(self, config: ArchitectureConfig): |
| 67 | + def __init__(self, config: _CLIPVisionConfig): |
51 | 68 | super().__init__() |
52 | 69 | hidden_size = config.hidden_size |
53 | 70 | patch_size = config.patch_size |
@@ -117,7 +134,7 @@ def forward(self, op: OpBuilder, x: ir.Value): |
117 | 134 | class _CLIPVisionEncoderLayer(nn.Module): |
118 | 135 | """CLIP vision encoder layer: pre-norm with LayerNorm.""" |
119 | 136 |
|
120 | | - def __init__(self, config: ArchitectureConfig): |
| 137 | + def __init__(self, config: _CLIPVisionConfig): |
121 | 138 | super().__init__() |
122 | 139 | self.self_attn = EncoderAttention(config.hidden_size, config.num_attention_heads) |
123 | 140 | self.layer_norm1 = LayerNorm(config.hidden_size, eps=config.rms_norm_eps) |
@@ -195,7 +212,7 @@ class CLIPVisionModel(nn.Module): |
195 | 212 |
|
196 | 213 | def __init__( |
197 | 214 | self, |
198 | | - config: ArchitectureConfig, |
| 215 | + config: _CLIPVisionConfig, |
199 | 216 | *, |
200 | 217 | feature_layer: int | None = None, |
201 | 218 | drop_class_token: bool = False, |
@@ -250,9 +267,17 @@ def preprocess_weights( |
250 | 267 | self, state_dict: dict[str, torch.Tensor] |
251 | 268 | ) -> dict[str, torch.Tensor]: |
252 | 269 | new_state_dict = {} |
| 270 | + num_encoder_layers = len(self.encoder) |
253 | 271 | for name, tensor in state_dict.items(): |
254 | 272 | new_name = _rename_clip_vision_weight(name) |
255 | 273 | if new_name is not None: |
| 274 | + if self.post_layernorm is None and new_name.startswith("post_layernorm."): |
| 275 | + continue |
| 276 | + if new_name.startswith("encoder."): |
| 277 | + parts = new_name.split(".", 2) |
| 278 | + if len(parts) >= 3 and parts[1].isdigit(): |
| 279 | + if int(parts[1]) >= num_encoder_layers: |
| 280 | + continue |
256 | 281 | new_state_dict[new_name] = tensor |
257 | 282 | return new_state_dict |
258 | 283 |
|
@@ -326,7 +351,7 @@ def _rename_clip_vision_weight(name: str) -> str | None: |
326 | 351 | class _SigLIPVisionEmbeddings(nn.Module): |
327 | 352 | """SigLIP vision embeddings: Conv2d patch + position embeddings (no CLS token).""" |
328 | 353 |
|
329 | | - def __init__(self, config: ArchitectureConfig): |
| 354 | + def __init__(self, config: _CLIPVisionConfig): |
330 | 355 | super().__init__() |
331 | 356 | hidden_size = config.hidden_size |
332 | 357 | patch_size = config.patch_size |
|
0 commit comments