@@ -1521,7 +1521,9 @@ class MmprojModel(ModelBase):
15211521 preprocessor_config : dict [str , Any ]
15221522 global_config : dict [str , Any ]
15231523
1524- n_block_keys = ["n_layers" , "num_hidden_layers" , "n_layer" , "num_layers" , "depth" ]
1524+ # Prefer explicit "layers" (e.g. JinaCLIP),
1525+ # keep legacy keys for other models.
1526+ n_block_keys = ["layers" , "n_layers" , "num_hidden_layers" , "n_layer" , "num_layers" , "depth" ]
15251527
15261528 has_vision_encoder : bool = True # by default
15271529 has_audio_encoder : bool = False
@@ -6804,6 +6806,11 @@ def __init__(self, *args, **kwargs):
68046806 with open (config_path , encoding = "utf-8" ) as f :
68056807 self .vision_config = json .load (f )
68066808
6809+ def get_vision_config (self ) -> dict [str , Any ] | None :
6810+ # For JinaCLIPVisionModel, the top-level AutoConfig dict is already
6811+ # the vision-only configuration.
6812+ return self .global_config
6813+
68076814 def set_vocab (self ):
68086815 # Vision encoder doesn't need vocabulary
68096816 pass
@@ -6861,73 +6868,10 @@ def set_gguf_parameters(self):
68616868 def _strip_vm_prefix (self , name : str ) -> str :
68626869 return name [len ('vision_model.' ):] if name .startswith ('vision_model.' ) else name
68636870
6864- def _map_block_tensor (self , layer : int , rest : str , data_torch : Tensor , name : str ) -> list [tuple [str , Tensor ]] | None :
6865- parts = rest .split ('.' )
6866- # layer norms
6867- if rest .startswith ('norm1.' ):
6868- suffix = parts [- 1 ]
6869- return [(f'v.blk.{ layer } .ln1.{ suffix } ' , data_torch )]
6870- if rest .startswith ('norm2.' ):
6871- suffix = parts [- 1 ]
6872- return [(f'v.blk.{ layer } .ln2.{ suffix } ' , data_torch )]
6873- if rest .startswith ('attn.inner_attn_ln.' ):
6874- suffix = parts [- 1 ]
6875- return [(f'v.blk.{ layer } .attn_ln.{ suffix } ' , data_torch )]
6876-
6877- if rest == 'attn.q_bias' :
6878- return [(f'v.blk.{ layer } .attn_q.bias' , data_torch )]
6879- if rest == 'attn.v_bias' :
6880- return [(f'v.blk.{ layer } .attn_v.bias' , data_torch )]
6881-
6882- if rest .startswith ('attn.q_proj.' ):
6883- suffix = parts [- 1 ]
6884- return [(f'v.blk.{ layer } .attn_q.{ suffix } ' , data_torch )]
6885- if rest .startswith ('attn.k_proj.' ):
6886- suffix = parts [- 1 ]
6887- return [(f'v.blk.{ layer } .attn_k.{ suffix } ' , data_torch )]
6888- if rest .startswith ('attn.v_proj.' ):
6889- suffix = parts [- 1 ]
6890- return [(f'v.blk.{ layer } .attn_v.{ suffix } ' , data_torch )]
6891- if rest .startswith ('attn.proj.' ):
6892- suffix = parts [- 1 ]
6893- return [(f'v.blk.{ layer } .attn_out.{ suffix } ' , data_torch )]
6894-
6895- # MLP
6896- if rest .startswith ('mlp.w1.' ):
6897- suffix = parts [- 1 ]
6898- return [(f'v.blk.{ layer } .ffn_gate.{ suffix } ' , data_torch )]
6899- if rest .startswith ('mlp.w2.' ):
6900- suffix = parts [- 1 ]
6901- return [(f'v.blk.{ layer } .ffn_up.{ suffix } ' , data_torch )]
6902- if rest .startswith ('mlp.w3.' ):
6903- suffix = parts [- 1 ]
6904- return [(f'v.blk.{ layer } .ffn_down.{ suffix } ' , data_torch )]
6905- if rest .startswith ('mlp.ffn_ln.' ):
6906- suffix = parts [- 1 ]
6907- return [(f'v.blk.{ layer } .ffn_norm.{ suffix } ' , data_torch )]
6908- if rest .startswith ('mlp.fc1.' ):
6909- suffix = parts [- 1 ]
6910- return [(f'v.blk.{ layer } .ffn_up.{ suffix } ' , data_torch )]
6911- if rest .startswith ('mlp.fc2.' ):
6912- suffix = parts [- 1 ]
6913- return [(f'v.blk.{ layer } .ffn_down.{ suffix } ' , data_torch )]
6914- return None
6915-
69166871 def map_tensor_name (self , name : str , try_suffixes : Sequence [str ] = (".weight" , ".bias" )) -> str :
6917- """Prefer base table-driven mapping; keep Jina-specific targets if already mapped; fallback to legacy mapper."""
6918- # Already a GGUF target name (e.g., "v.*" or "mm.*"): return as-is
69196872 if name .startswith ('v.' ) or name .startswith ('mm.' ):
69206873 return name
6921- # Try the base mapping first
6922- try :
6923- return super ().map_tensor_name (name , try_suffixes = try_suffixes )
6924- except Exception :
6925- # Fallback to legacy Jina-specific mapper for any remaining edge keys
6926- if hasattr (self , "_map_jinaclip_tensor_name" ):
6927- mapped = self ._map_jinaclip_tensor_name (name ) # type: ignore[attr-defined]
6928- if mapped :
6929- return mapped
6930- return name
6874+ return super ().map_tensor_name (name , try_suffixes = try_suffixes )
69316875
69326876 def get_tensors (self ) -> Iterator [tuple [str , Tensor ]]:
69336877 yielded_any = False
@@ -6991,15 +6935,6 @@ def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iter
69916935 base = gguf .TENSOR_NAMES [gguf .MODEL_TENSOR .V_POST_NORM ]
69926936 return [(f'{ base } .{ suffix } ' , data_torch )]
69936937
6994- if src_no_vm .startswith ('blocks.' ):
6995- parts = src_no_vm .split ('.' )
6996- if len (parts ) >= 3 and parts [1 ].isdigit ():
6997- layer = int (parts [1 ])
6998- rest = '.' .join (parts [2 :])
6999- mapped = self ._map_block_tensor (layer , rest , data_torch , name )
7000- if mapped is not None :
7001- return mapped
7002-
70036938 try :
70046939 return [(self .map_tensor_name (name ), data_torch )]
70056940 except Exception :
0 commit comments