Coverage for transformer_lens/model_bridge/supported_architectures/qwen3_5.py: 96%
22 statements
« prev ^ index » next coverage.py v7.10.1, created at 2026-09-21 19:27 +0000
« prev ^ index » next coverage.py v7.10.1, created at 2026-09-21 19:27 +0000
1"""Qwen3.5 architecture adapter.
3Hybrid linear-attention (GatedDeltaNet) + full-attention with dense gated MLP.
43 linear-attn layers per 1 full-attn layer. Extends Qwen3 base with
5optional attention mapping and fold_ln disabled.
6"""
8from typing import Any
10from transformer_lens.model_bridge.supported_architectures.qwen3 import (
11 Qwen3ArchitectureAdapter,
12)
15class Qwen3_5ArchitectureAdapter(Qwen3ArchitectureAdapter):
16 """Hybrid linear-attention + full-attention with dense gated MLP.
18 Inherits Qwen3 config/attention/MLP structure. Differences:
19 - Attention + linear_attn are optional (per-layer type)
20 - Gated q_proj: [query|gate] is split at forward time, never in weight space;
21 AttentionBridge exposes a query-only W_Q analysis view
22 """
24 # Multimodal wrapper architecture this text-only adapter rejects; the MoE
25 # subclass swaps in its own name.
26 _multimodal_arch_name: str = "Qwen3_5ForConditionalGeneration"
28 def __init__(self, cfg: Any) -> None:
29 # q_proj stays 2x-wide through weight processing: HF and the attention bridge both
30 # split [query|gate] per head at forward time; slicing the gate out changes outputs.
31 setattr(cfg, "gated_q_proj", True)
32 super().__init__(cfg, hybrid=True)
34 def prepare_loading(self, model_name: str, model_kwargs: dict) -> None:
35 """Swap the multimodal config for its text_config so AutoModelForCausalLM
36 loads the text-only model (published checkpoints carry the
37 ForConditionalGeneration architecture)."""
38 config = model_kwargs.get("config")
39 if config is not None and hasattr(config, "text_config"): 39 ↛ exitline 39 didn't return from function 'prepare_loading' because the condition on line 39 was always true
40 model_kwargs["config"] = config.text_config
42 def prepare_model(self, hf_model: Any) -> None:
43 """Reject full multimodal checkpoints on this text-only adapter."""
44 config = getattr(hf_model, "config", None)
45 architectures = getattr(config, "architectures", []) or []
46 class_name = type(hf_model).__name__
47 multimodal_arch = self._multimodal_arch_name
49 is_conditional_generation = (
50 class_name == multimodal_arch or multimodal_arch in architectures
51 )
52 still_has_top_level_multimodal_config = hasattr(config, "text_config")
53 if is_conditional_generation or still_has_top_level_multimodal_config:
54 causal_arch = multimodal_arch.replace("ForConditionalGeneration", "ForCausalLM")
55 text_config_name = multimodal_arch.replace("ForConditionalGeneration", "TextConfig")
56 raise ValueError(
57 f"This adapter is text-only. Pass a {causal_arch} / "
58 f"{text_config_name} model, or load by model id with "
59 f"TransformerBridge.boot_transformers(...) so {multimodal_arch} "
60 f"checkpoints route to the multimodal adapter automatically."
61 )