Download modeling/embedding_model.py from dxtech-asia/deepx-embedding-v09: direct link, hf CLI and curl.
- Browser
- Download file 8.47 kB
-
https://huggingface.co/dxtech-asia/deepx-embedding-v09/resolve/main/modeling/embedding_model.py
- Command line
-
hf download hf://dxtech-asia/deepx-embedding-v09/modeling/embedding_model.py
-
curl -L -o embedding_model.py https://huggingface.co/dxtech-asia/deepx-embedding-v09/resolve/main/modeling/embedding_model.py
8.47 kB
| """ | |
| DeepX v0.7: Gated DeltaNet-2 Hyperloop Backbone + ColBERT Head. | |
| Architecture: | |
| Begin(4 NarrowA) → Phase1×2 [WideA + NarrowA×4] → Phase2×4 [NarrowB×4 + WideB] | |
| → End(1 WideB) = 35 compute passes | |
| Unique layers: 9 (4 begin + 4 shared cores + 1 end) | |
| Per-loop differentiation: LoRA + RoDE | |
| Outputs: | |
| 1. Single vector (1536-d) via attention pooling | |
| 2. Token vectors (T × 128-d) via ColBERT head | |
| Weight Init: ~95% from Gemma 4 E2B via direct copy + SVD LoRA. | |
| """ | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| import logging | |
| from typing import Optional, Tuple, Union | |
| from config import DeepXConfig | |
| from .hybrid_layer import ( | |
| DeepXLayer, make_narrow_a_layer, make_narrow_b_layer, | |
| make_wide_a_layer, make_wide_b_layer, | |
| ) | |
| from .hyperloop import HyperloopPhase | |
| from .utils import RMSNorm, RoDE | |
| logger = logging.getLogger(__name__) | |
| class ColBERTHead(nn.Module): | |
| """Projects hidden states to low-dimensional token vectors for MaxSim.""" | |
| def __init__(self, hidden_size: int, colbert_dim: int = 128): | |
| super().__init__() | |
| self.linear = nn.Linear(hidden_size, colbert_dim, bias=False) | |
| def forward(self, hidden_states: torch.Tensor, attention_mask: Optional[torch.Tensor] = None) -> torch.Tensor: | |
| token_embeds = self.linear(hidden_states) | |
| token_embeds = F.normalize(token_embeds, p=2, dim=-1) | |
| if attention_mask is not None: | |
| token_embeds = token_embeds * attention_mask.unsqueeze(-1).to(token_embeds.dtype) | |
| return token_embeds | |
| class DeepXEmbeddingModel(nn.Module): | |
| """ | |
| DeepX v0.7 Backbone — Gated DeltaNet-2 Hyperloop + ColBERT. | |
| Receives hidden_states from external frozen token embedding. | |
| """ | |
| def __init__(self, config: DeepXConfig): | |
| super().__init__() | |
| self.config = config | |
| # ═══ 1. Begin Block: 4 unique NarrowA layers (direct copy from Gemma 0-3) ═══ | |
| self.begin_blocks = nn.ModuleList([ | |
| make_narrow_a_layer(config, layer_idx=i) | |
| for i in range(config.begin_layers) | |
| ]) | |
| # ═══ 2. Phase1 Loop: 2 iterations × [WideA + NarrowA×4] ═══ | |
| self.shared_narrow_a = make_narrow_a_layer(config, layer_idx=config.begin_layers) | |
| self.shared_wide_a = make_wide_a_layer(config, layer_idx=config.begin_layers + 1) | |
| # Attach RoDE to shared cores | |
| if config.use_rode: | |
| self.shared_narrow_a.self_attn._rode = RoDE( | |
| dim=config.depth_rotary_dims, num_loops=config.phase1_loops | |
| ) | |
| self.shared_wide_a.self_attn._rode = RoDE( | |
| dim=config.depth_rotary_dims, num_loops=config.phase1_loops | |
| ) | |
| self.phase1 = HyperloopPhase( | |
| config=config, | |
| shared_narrow=self.shared_narrow_a, | |
| shared_wide=self.shared_wide_a, | |
| num_loops=config.phase1_loops, | |
| narrow_num_heads=config.narrow_a_heads, | |
| narrow_kv_heads=config.narrow_a_kv_heads, | |
| narrow_head_dim=config.narrow_a_head_dim, | |
| narrow_intermediate=config.narrow_a_intermediate, | |
| wide_num_heads=config.wide_a_heads, | |
| wide_kv_heads=config.wide_a_kv_heads, | |
| wide_head_dim=config.wide_a_head_dim, | |
| wide_intermediate=config.wide_a_intermediate, | |
| wide_first=True, # [WideA, NarrowA×4] | |
| ) | |
| # ═══ 3. Phase2 Loop: 4 iterations × [NarrowB×4 + WideB] ═══ | |
| self.shared_narrow_b = make_narrow_b_layer(config, layer_idx=config.begin_layers + 2) | |
| self.shared_wide_b = make_wide_b_layer(config, layer_idx=config.begin_layers + 3) | |
| if config.use_rode: | |
| self.shared_narrow_b.self_attn._rode = RoDE( | |
| dim=config.depth_rotary_dims, num_loops=config.phase2_loops | |
| ) | |
| self.shared_wide_b.self_attn._rode = RoDE( | |
| dim=config.depth_rotary_dims, num_loops=config.phase2_loops | |
| ) | |
| self.phase2 = HyperloopPhase( | |
| config=config, | |
| shared_narrow=self.shared_narrow_b, | |
| shared_wide=self.shared_wide_b, | |
| num_loops=config.phase2_loops, | |
| narrow_num_heads=config.narrow_b_heads, | |
| narrow_kv_heads=config.narrow_b_kv_heads, | |
| narrow_head_dim=config.narrow_b_head_dim, | |
| narrow_intermediate=config.narrow_b_intermediate, | |
| wide_num_heads=config.wide_b_heads, | |
| wide_kv_heads=config.wide_b_kv_heads, | |
| wide_head_dim=config.wide_b_head_dim, | |
| wide_intermediate=config.wide_b_intermediate, | |
| wide_first=False, # [NarrowB×4, WideB] | |
| ) | |
| # ═══ 4. End Block: 1 unique WideB layer (layer 34 direct copy) ═══ | |
| self.end_block = make_wide_b_layer(config, layer_idx=config.begin_layers + 4) | |
| # ═══ Final norm ═══ | |
| self.norm = RMSNorm(config.hidden_size, config.rms_norm_eps) | |
| # ═══ Output Head 1: Attention Pooling ═══ | |
| self.pooling_strategy = config.pooling_strategy | |
| if config.pooling_strategy == "attention": | |
| self.pool_query = nn.Parameter(torch.randn(1, 1, config.hidden_size) * 0.02) | |
| # ═══ Output Head 2: ColBERT ═══ | |
| self.use_colbert = config.use_colbert | |
| if config.use_colbert: | |
| self.colbert_head = ColBERTHead(config.hidden_size, config.colbert_dim) | |
| self.to(config.torch_dtype) | |
| def _pool(self, hidden_states: torch.Tensor, attention_mask: Optional[torch.Tensor] = None) -> torch.Tensor: | |
| if self.pooling_strategy == "attention": | |
| scale = hidden_states.shape[-1] ** -0.5 | |
| scores = (hidden_states * self.pool_query).sum(dim=-1) * scale | |
| if attention_mask is not None: | |
| scores = scores.masked_fill(attention_mask == 0, float("-inf")) | |
| weights = F.softmax(scores, dim=-1).unsqueeze(-1) | |
| return (hidden_states * weights).sum(dim=1) | |
| # Mean pooling fallback | |
| if attention_mask is not None: | |
| mask = attention_mask.unsqueeze(-1).to(hidden_states.dtype) | |
| return (hidden_states * mask).sum(dim=1) / mask.sum(dim=1).clamp(min=1e-9) | |
| return hidden_states.mean(dim=1) | |
| def forward( | |
| self, | |
| hidden_states: torch.Tensor, | |
| attention_mask: Optional[torch.Tensor] = None, | |
| normalize: bool = True, | |
| truncate_dim: Optional[int] = None, | |
| return_colbert: bool = False, | |
| ) -> Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]: | |
| B, T, _ = hidden_states.shape | |
| position_ids = torch.arange(T, device=hidden_states.device).unsqueeze(0).expand(B, -1) | |
| # 1. Begin blocks (4 unique NarrowA) | |
| for layer in self.begin_blocks: | |
| hidden_states = layer(hidden_states, attention_mask=attention_mask, position_ids=position_ids) | |
| # 2. Phase1 loop: 2 × [WideA + NarrowA×4] = 10 passes | |
| hidden_states = self.phase1(hidden_states, attention_mask=attention_mask, position_ids=position_ids) | |
| # 3. Phase2 loop: 4 × [NarrowB×4 + WideB] = 20 passes | |
| hidden_states = self.phase2(hidden_states, attention_mask=attention_mask, position_ids=position_ids) | |
| # 4. End block (1 unique WideB) | |
| hidden_states = self.end_block(hidden_states, attention_mask=attention_mask, position_ids=position_ids) | |
| # 5. Final norm | |
| hidden_states = self.norm(hidden_states) | |
| # --- Output 1: Single vector --- | |
| single_embed = self._pool(hidden_states, attention_mask) | |
| if truncate_dim is not None: | |
| single_embed = single_embed[:, :truncate_dim] | |
| if normalize: | |
| single_embed = F.normalize(single_embed, p=2, dim=-1) | |
| # --- Output 2: ColBERT token vectors --- | |
| if return_colbert and self.use_colbert: | |
| token_embeds = self.colbert_head(hidden_states, attention_mask) | |
| return single_embed, token_embeds | |
| return single_embed | |
| def count_parameters(self) -> dict: | |
| total = sum(p.numel() for p in self.parameters()) | |
| trainable = sum(p.numel() for p in self.parameters() if p.requires_grad) | |
| return {"backbone_total": total, "trainable": trainable} | |