Cortex-0 / src /model /projectors.py
Frankenstein-Labs's picture
feat(vision): Phase 4 — encodeur image ViT
6857ec0 verified
Raw History Blame Contribute Delete
1.81 kB
"""Projecteurs multimodaux : alignent image/audio sur l'espace texte (Phases 4-8).
Idée : les encodeurs image/audio produisent des features de dimension propre. Pour
que le décodeur texte puisse les lire, un petit **MLP** projette ces features dans
la dimension du texte (`text_dim`). On insère alors ces vecteurs dans la séquence
de tokens texte, encadrés par des tokens de modalité (`<|image_start|>` …).
Choix d'un MLP (2 couches + GELU) plutôt qu'une projection linéaire : il apprend
une transformation non linéaire, ce qui aide l'alignement, pour un coût modeste.
Justification complète : docs/architecture.md §5.
"""
from __future__ import annotations
import torch
import torch.nn as nn
class MLPProjector(nn.Module):
"""MLP ``in_dim -> hidden -> out_dim`` avec GELU et LayerNorm optionnelle."""
def __init__(
self,
in_dim: int,
out_dim: int,
hidden_dim: int | None = None,
dropout: float = 0.0,
use_norm: bool = True,
):
super().__init__()
hidden_dim = hidden_dim or out_dim
layers: list[nn.Module] = []
if use_norm:
layers.append(nn.LayerNorm(in_dim))
layers += [
nn.Linear(in_dim, hidden_dim),
nn.GELU(),
nn.Linear(hidden_dim, out_dim),
]
if dropout > 0:
layers.append(nn.Dropout(dropout))
self.net = nn.Sequential(*layers)
def forward(self, x: torch.Tensor) -> torch.Tensor:
return self.net(x)
def build_projector(in_dim: int, text_dim: int, hidden_dim: int | None = None,
dropout: float = 0.0) -> MLPProjector:
"""Fabrique un projecteur vers l'espace texte (helper)."""
return MLPProjector(in_dim, text_dim, hidden_dim=hidden_dim, dropout=dropout)