summaryrefslogtreecommitdiff
path: root/worldalign/models.py
blob: 5f986056ca2a24b9fe915a64ae9ab35139994cd7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
from __future__ import annotations

import torch
from torch import nn
import torch.nn.functional as F


class Bridge(nn.Module):
    def __init__(
        self,
        vision_dim: int,
        text_dim: int,
        hidden_dim: int = 1536,
        linear: bool = False,
    ):
        super().__init__()
        self.vision_dim = vision_dim
        self.text_dim = text_dim
        self.hidden_dim = hidden_dim
        self.linear = linear
        if linear:
            self.network = nn.Linear(vision_dim, text_dim, bias=False)
        else:
            self.network = nn.Sequential(
                nn.LayerNorm(vision_dim),
                nn.Linear(vision_dim, hidden_dim),
                nn.GELU(),
                nn.Linear(hidden_dim, text_dim),
            )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return F.normalize(self.network(x).float(), dim=-1)

    def config(self) -> dict:
        return {
            "vision_dim": self.vision_dim,
            "text_dim": self.text_dim,
            "hidden_dim": self.hidden_dim,
            "linear": self.linear,
        }


class PrefixAdapter(nn.Module):
    def __init__(
        self,
        semantic_dim: int,
        lm_dim: int,
        prefix_length: int = 8,
        hidden_dim: int = 2048,
    ):
        super().__init__()
        self.semantic_dim = semantic_dim
        self.lm_dim = lm_dim
        self.prefix_length = prefix_length
        self.hidden_dim = hidden_dim
        self.network = nn.Sequential(
            nn.LayerNorm(semantic_dim),
            nn.Linear(semantic_dim, hidden_dim),
            nn.GELU(),
            nn.Linear(hidden_dim, prefix_length * lm_dim),
        )

    def forward(self, semantic: torch.Tensor) -> torch.Tensor:
        prefix = self.network(semantic.float())
        return prefix.view(-1, self.prefix_length, self.lm_dim)

    def config(self) -> dict:
        return {
            "semantic_dim": self.semantic_dim,
            "lm_dim": self.lm_dim,
            "prefix_length": self.prefix_length,
            "hidden_dim": self.hidden_dim,
        }


def load_bridge(path: str, device: str = "cpu") -> tuple[Bridge, dict]:
    state = torch.load(path, map_location="cpu", weights_only=False)
    model = Bridge(**state["config"])
    model.load_state_dict(state["state_dict"])
    model.to(device).eval()
    return model, state


def load_prefix(path: str, device: str = "cpu") -> tuple[PrefixAdapter, dict]:
    state = torch.load(path, map_location="cpu", weights_only=False)
    model = PrefixAdapter(**state["config"])
    model.load_state_dict(state["state_dict"])
    model.to(device).eval()
    return model, state