daichi812 commited on
Commit
533f72f
·
verified ·
1 Parent(s): 0f349dd

final model (main)

Browse files
config.json ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "LoopedForCausalLM"
4
+ ],
5
+ "auto_map": {
6
+ "AutoConfig": "configuration_babyloop.BabyloopConfig",
7
+ "AutoModelForCausalLM": "modeling_babyloop.LoopedForCausalLM"
8
+ },
9
+ "bias": false,
10
+ "bos_token_id": 1,
11
+ "connector_type": "mlp",
12
+ "d_model": 768,
13
+ "dropout": 0.0,
14
+ "eos_token_id": 2,
15
+ "ffn_hidden": 2048,
16
+ "fusion": "connector",
17
+ "hidden_size": 768,
18
+ "inject_input": true,
19
+ "k": 4,
20
+ "max_position_embeddings": 512,
21
+ "max_seq_len": 512,
22
+ "model_type": "babyloop",
23
+ "n_coda": 0,
24
+ "n_core": 12,
25
+ "n_heads": 12,
26
+ "n_layers": 12,
27
+ "n_prelude": 0,
28
+ "n_visual_tokens": 1,
29
+ "num_attention_heads": 12,
30
+ "num_hidden_layers": 12,
31
+ "pad_token_id": 0,
32
+ "rms_eps": 1e-05,
33
+ "rope_base": 10000.0,
34
+ "tie_embeddings": true,
35
+ "torch_dtype": "float32",
36
+ "transformers_version": "4.51.3",
37
+ "vision_feature_dim": 768,
38
+ "vision_layers": null,
39
+ "visual_inject_iters": 2,
40
+ "visual_inject_mode": "prefix_refresh",
41
+ "vocab_size": 16000
42
+ }
configuration_babyloop.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """BabyloopConfig — HF ``PretrainedConfig`` 互換のモデル設定。
2
+
3
+ このファイルは ``save_pretrained`` 時に checkpoint ディレクトリへ複製され、
4
+ 公式 evaluation-pipeline 側(別プロセス)から ``trust_remote_code=True`` で
5
+ import される。そのため **transformers と標準ライブラリ以外に依存しない**
6
+ (``babyloop`` パッケージ内部を import しない)こと。
7
+
8
+ フィールドと configs/model/*.yaml の対応は docs/architecture.md §6 を参照。
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from transformers import PretrainedConfig
14
+
15
+
16
+ class BabyloopConfig(PretrainedConfig):
17
+ """ループドTransformer(K=1で標準に縮退)の設定。
18
+
19
+ 軸A(標準 vs 再帰)は ``k`` のみで切り替える単一実装。視覚(②④)の口も
20
+ 持つが、テキストのみ(①③)では ``fusion=None`` で無効。
21
+ """
22
+
23
+ model_type = "babyloop"
24
+
25
+ def __init__(
26
+ self,
27
+ d_model: int = 768,
28
+ n_layers: int = 12,
29
+ n_heads: int = 12,
30
+ ffn_hidden: int = 2048,
31
+ n_prelude: int = 0,
32
+ n_core: int = 12,
33
+ n_coda: int = 0,
34
+ k: int = 1,
35
+ inject_input: bool = False,
36
+ vocab_size: int = 16000,
37
+ max_seq_len: int = 512,
38
+ rope_base: float = 10000.0,
39
+ rms_eps: float = 1e-5,
40
+ tie_embeddings: bool = True,
41
+ bias: bool = False,
42
+ dropout: float = 0.0,
43
+ fusion: str | None = None,
44
+ vision_feature_dim: int = 768,
45
+ n_visual_tokens: int = 0,
46
+ connector_type: str = "mlp",
47
+ visual_inject_iters: int = 0,
48
+ visual_inject_mode: str = "prefix_refresh",
49
+ vision_layers: list[int] | None = None,
50
+ pad_token_id: int | None = None,
51
+ bos_token_id: int | None = None,
52
+ eos_token_id: int | None = None,
53
+ **kwargs,
54
+ ):
55
+ self.d_model = d_model
56
+ self.n_layers = n_layers
57
+ self.n_heads = n_heads
58
+ self.ffn_hidden = ffn_hidden
59
+ self.n_prelude = n_prelude
60
+ self.n_core = n_core
61
+ self.n_coda = n_coda
62
+ self.k = k
63
+ self.inject_input = inject_input
64
+ self.vocab_size = vocab_size
65
+ self.max_seq_len = max_seq_len
66
+ self.rope_base = rope_base
67
+ self.rms_eps = rms_eps
68
+ self.tie_embeddings = tie_embeddings
69
+ self.bias = bias
70
+ self.dropout = dropout
71
+ # --- 視覚(②④。text では fusion=None で完全に無効)---
72
+ # fusion: 視覚 on/off ゲート(None=テキスト / not-None=視覚あり)。projector 型は持たない(ADR-0006)。
73
+ self.fusion = fusion
74
+ self.vision_feature_dim = vision_feature_dim # frozen encoder の特徴次元(ViT-B/14=768)
75
+ self.n_visual_tokens = n_visual_tokens # prefix する視覚トークン数(学習時圧縮後)
76
+ self.connector_type = connector_type # projector 型: mlp / identity(=naive 劣化)
77
+ self.visual_inject_iters = visual_inject_iters # 注入場所 SoT: 0=prefix(②) / >0=staged(④)
78
+ self.visual_inject_mode = visual_inject_mode # ④注入形: prefix_refresh(B,主系) / broadcast(A)
79
+ self.vision_layers = vision_layers # ④の階層注入で使う中間層(②は未使用)
80
+
81
+ # HF 汎用ユーティリティが参照するエイリアス。
82
+ self.hidden_size = d_model
83
+ self.num_attention_heads = n_heads
84
+ self.num_hidden_layers = n_layers
85
+ self.max_position_embeddings = max_seq_len
86
+
87
+ super().__init__(
88
+ pad_token_id=pad_token_id,
89
+ bos_token_id=bos_token_id,
90
+ eos_token_id=eos_token_id,
91
+ tie_word_embeddings=tie_embeddings,
92
+ **kwargs,
93
+ )
94
+
95
+ @property
96
+ def head_dim(self) -> int:
97
+ return self.d_model // self.n_heads
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:eeae4699cf5d5e0fda21e599150db312e866c05b113206195dee02c8e6914260
3
+ size 393701504
modeling_babyloop.py ADDED
@@ -0,0 +1,395 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ループドTransformer本体(HF ``PreTrainedModel`` 互換・単一実装)。
2
+
3
+ 設計 docs/architecture.md §2 の Llama 系レシピ(RMSNorm / RoPE / SwiGLU /
4
+ bias なし / weight tying)を素の PyTorch で実装。``forward`` は K 回ループする
5
+ 形で書き、``k=1`` で標準Transformerに厳密に縮退する(``tests/test_k1_equivalence.py``)。
6
+
7
+ このファイルは ``save_pretrained`` 時に checkpoint へ複製され、公式
8
+ evaluation-pipeline(別プロセス・``trust_remote_code=True``)から import される。
9
+ そのため **torch / transformers / 標準ライブラリ以外に依存しない**こと。
10
+ probing 用のループ毎中間表現は HF 標準 ``hidden_states``(層ごと)と混ぜず、
11
+ 別フィールド ``loop_hidden_states`` に格納する。
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import math
17
+ from dataclasses import dataclass
18
+
19
+ import torch
20
+ import torch.nn.functional as F
21
+ from torch import nn
22
+ from transformers.modeling_outputs import ModelOutput
23
+ from transformers.modeling_utils import PreTrainedModel
24
+
25
+ from .configuration_babyloop import BabyloopConfig
26
+
27
+
28
+ # --- ビルディングブロック(Llama系レシピ)---------------------------------
29
+
30
+
31
+ class RMSNorm(nn.Module):
32
+ def __init__(self, dim: int, eps: float):
33
+ super().__init__()
34
+ self.eps = eps
35
+ self.weight = nn.Parameter(torch.ones(dim))
36
+
37
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
38
+ dtype = x.dtype
39
+ x = x.float()
40
+ x = x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
41
+ return (x.to(dtype)) * self.weight
42
+
43
+
44
+ def _rotate_half(x: torch.Tensor) -> torch.Tensor:
45
+ x1, x2 = x.chunk(2, dim=-1)
46
+ return torch.cat((-x2, x1), dim=-1)
47
+
48
+
49
+ def _apply_rope(x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor) -> torch.Tensor:
50
+ # x: (B, H, T, head_dim); cos/sin: (1, 1, T, head_dim)
51
+ return x * cos + _rotate_half(x) * sin
52
+
53
+
54
+ class Attention(nn.Module):
55
+ """RoPE 付き causal Multi-Head Attention(dropout なし)。"""
56
+
57
+ def __init__(self, config: BabyloopConfig):
58
+ super().__init__()
59
+ self.n_heads = config.n_heads
60
+ self.head_dim = config.d_model // config.n_heads
61
+ self.qkv_proj = nn.Linear(config.d_model, 3 * config.d_model, bias=config.bias)
62
+ self.o_proj = nn.Linear(config.d_model, config.d_model, bias=config.bias)
63
+
64
+ def forward(self, x, cos, sin, attn_bias):
65
+ B, T, C = x.shape
66
+ q, k, v = self.qkv_proj(x).split(C, dim=-1)
67
+ q = q.view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
68
+ k = k.view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
69
+ v = v.view(B, T, self.n_heads, self.head_dim).transpose(1, 2)
70
+ q = _apply_rope(q, cos, sin)
71
+ k = _apply_rope(k, cos, sin)
72
+ out = F.scaled_dot_product_attention(
73
+ q, k, v, attn_mask=attn_bias, is_causal=attn_bias is None
74
+ )
75
+ out = out.transpose(1, 2).reshape(B, T, C)
76
+ return self.o_proj(out)
77
+
78
+
79
+ class SwiGLU(nn.Module):
80
+ def __init__(self, config: BabyloopConfig):
81
+ super().__init__()
82
+ self.gate_proj = nn.Linear(config.d_model, config.ffn_hidden, bias=config.bias)
83
+ self.up_proj = nn.Linear(config.d_model, config.ffn_hidden, bias=config.bias)
84
+ self.down_proj = nn.Linear(config.ffn_hidden, config.d_model, bias=config.bias)
85
+
86
+ def forward(self, x):
87
+ return self.down_proj(F.silu(self.gate_proj(x)) * self.up_proj(x))
88
+
89
+
90
+ class Block(nn.Module):
91
+ """Pre-Norm 残差ブロック: h += Attn(RMSNorm(h)); h += SwiGLU(RMSNorm(h))。"""
92
+
93
+ def __init__(self, config: BabyloopConfig):
94
+ super().__init__()
95
+ self.attn_norm = RMSNorm(config.d_model, config.rms_eps)
96
+ self.attn = Attention(config)
97
+ self.mlp_norm = RMSNorm(config.d_model, config.rms_eps)
98
+ self.mlp = SwiGLU(config)
99
+
100
+ def forward(self, h, cos, sin, attn_bias):
101
+ h = h + self.attn(self.attn_norm(h), cos, sin, attn_bias)
102
+ h = h + self.mlp(self.mlp_norm(h))
103
+ return h
104
+
105
+
106
+ # --- 視覚 connector(②④。frozen encoder の特徴を LM 空間へ射影する trainable projector)---
107
+ # ADR-0005/0006: encoder は data 側で事前計算、ここには torch 純正の projector のみ(自己完結維持)。
108
+
109
+
110
+ class VisualConnector(nn.Module):
111
+ """事前計算済み視覚特徴 (B, V, vision_feature_dim) を d_model 空間へ射影する。
112
+
113
+ - ``mlp``: 2層 MLP(vit_dim→d_model→d_model, GELU。LLaVA-1.5 流)。②の本命・trainable。
114
+ - ``identity``: 射影なし(``vit_dim==d_model`` 前提)。射影なし+未事前学習の劣化条件
115
+ (ADR-0006 の naive)。学習パラメータを持たない。
116
+ """
117
+
118
+ def __init__(self, config: BabyloopConfig):
119
+ super().__init__()
120
+ self.connector_type = config.connector_type
121
+ vit_dim = config.vision_feature_dim
122
+ d = config.d_model
123
+ if self.connector_type == "mlp":
124
+ # projector は bias を持たせる(LM 本体の bias なし方針とは独立の trainable adapter)。
125
+ self.fc1 = nn.Linear(vit_dim, d, bias=True)
126
+ self.act = nn.GELU()
127
+ self.fc2 = nn.Linear(d, d, bias=True)
128
+ elif self.connector_type == "identity":
129
+ if vit_dim != d:
130
+ raise ValueError(
131
+ f"connector_type=identity は vision_feature_dim==d_model が前提 "
132
+ f"({vit_dim} != {d})。ViT-B/14(768) を使うか mlp connector にする。"
133
+ )
134
+ else:
135
+ raise ValueError(f"unknown connector_type: {self.connector_type}")
136
+
137
+ def forward(self, vision_features: torch.Tensor) -> torch.Tensor:
138
+ if self.connector_type == "identity":
139
+ return vision_features
140
+ return self.fc2(self.act(self.fc1(vision_features)))
141
+
142
+
143
+ # --- 出力コンテナ -----------------------------------------------------------
144
+
145
+
146
+ @dataclass
147
+ class LoopedModelOutput(ModelOutput):
148
+ last_hidden_state: torch.FloatTensor | None = None
149
+ hidden_states: tuple[torch.FloatTensor, ...] | None = None
150
+ loop_hidden_states: tuple[torch.FloatTensor, ...] | None = None
151
+
152
+
153
+ @dataclass
154
+ class LoopedCausalLMOutput(ModelOutput):
155
+ loss: torch.FloatTensor | None = None
156
+ logits: torch.FloatTensor | None = None
157
+ hidden_states: tuple[torch.FloatTensor, ...] | None = None
158
+ loop_hidden_states: tuple[torch.FloatTensor, ...] | None = None
159
+
160
+
161
+ # --- PreTrainedModel ラッパ -------------------------------------------------
162
+
163
+
164
+ class LoopedPreTrainedModel(PreTrainedModel):
165
+ config_class = BabyloopConfig
166
+ base_model_prefix = "model"
167
+ supports_gradient_checkpointing = False
168
+
169
+ def _init_weights(self, module):
170
+ std = 0.02
171
+ if isinstance(module, nn.Linear):
172
+ nn.init.normal_(module.weight, mean=0.0, std=std)
173
+ if module.bias is not None:
174
+ nn.init.zeros_(module.bias)
175
+ elif isinstance(module, nn.Embedding):
176
+ nn.init.normal_(module.weight, mean=0.0, std=std)
177
+ elif isinstance(module, RMSNorm):
178
+ nn.init.ones_(module.weight)
179
+
180
+
181
+ class LoopedModel(LoopedPreTrainedModel):
182
+ """重み共有 core ブロックを K 回反復するバックボーン(lm_head なし)。"""
183
+
184
+ def __init__(self, config: BabyloopConfig):
185
+ super().__init__(config)
186
+ self.config = config
187
+ self.embed_tokens = nn.Embedding(config.vocab_size, config.d_model)
188
+ self.prelude = nn.ModuleList(Block(config) for _ in range(config.n_prelude))
189
+ self.core = nn.ModuleList(Block(config) for _ in range(config.n_core))
190
+ self.coda = nn.ModuleList(Block(config) for _ in range(config.n_coda))
191
+ self.final_norm = RMSNorm(config.d_model, config.rms_eps)
192
+
193
+ # 視覚 connector(②④のみ)。fusion=None(①③ text)では構築しない=パラメータ不変
194
+ # (test_k1_equivalence / test_looped_adds_no_parameters を壊さない)。
195
+ self.connector = VisualConnector(config) if config.fusion is not None else None
196
+ if self.connector is not None and config.visual_inject_mode not in ("prefix_refresh", "broadcast"):
197
+ raise ValueError(f"unknown visual_inject_mode: {config.visual_inject_mode}")
198
+
199
+ head_dim = config.d_model // config.n_heads
200
+ inv_freq = 1.0 / (
201
+ config.rope_base ** (torch.arange(0, head_dim, 2, dtype=torch.float32) / head_dim)
202
+ )
203
+ self.register_buffer("inv_freq", inv_freq, persistent=False)
204
+ self.post_init()
205
+
206
+ def get_input_embeddings(self):
207
+ return self.embed_tokens
208
+
209
+ def set_input_embeddings(self, value):
210
+ self.embed_tokens = value
211
+
212
+ def _rope(self, T: int, device, dtype):
213
+ t = torch.arange(T, device=device, dtype=torch.float32)
214
+ freqs = torch.outer(t, self.inv_freq.to(device))
215
+ emb = torch.cat((freqs, freqs), dim=-1)
216
+ return emb.cos().to(dtype)[None, None], emb.sin().to(dtype)[None, None]
217
+
218
+ def _attn_bias(self, attention_mask, T, device, dtype):
219
+ # padding が無ければ None を返し、SDPA の is_causal 経路(高速)に乗せる。
220
+ if attention_mask is None or bool((attention_mask == 1).all()):
221
+ return None
222
+ causal = torch.ones(T, T, device=device, dtype=torch.bool).triu(1)
223
+ key_pad = attention_mask.to(device) == 0 # (B, T)
224
+ mask = causal[None, None] | key_pad[:, None, None, :]
225
+ bias = torch.zeros(mask.shape, device=device, dtype=dtype)
226
+ return bias.masked_fill(mask, torch.finfo(dtype).min)
227
+
228
+ def inject(self, h, visual, loop_index: int):
229
+ """④: ループ初期の各イテレーション先頭で視覚を再注入(``visual_inject_iters>0``)。
230
+
231
+ Args:
232
+ h: 現在の hidden states。``prefix_refresh`` では prefix 済 (B, V+T, d)、
233
+ ``broadcast`` では (B, T, d)。
234
+ visual: connector 射影済みの視覚特徴 (B, V, d)。n_visual は ``visual.size(1)`` から導出
235
+ (pad 量の不一致バグを封じるため別経路で渡さない)。
236
+ loop_index: 現在のループ回(0始まり、呼び出し側で ``< inject_iters`` を保証)。
237
+
238
+ - ``prefix_refresh``(B 主系): prefix 位置(先頭 V)へ視覚を再加算(右ゼロパディングして加算)。
239
+ ②と同じ入れ方・同じ特徴で、変換で薄れた視覚信号を補充する([ADR-0006])。
240
+ - ``broadcast``(A, ablation): pooled 視覚ベクトルを全位置へブロードキャスト加算。系列長不変。
241
+ """
242
+ if self.config.visual_inject_mode == "broadcast":
243
+ return h + visual.mean(dim=1, keepdim=True)
244
+ # prefix_refresh: 先頭 V 位置だけに加算(残りは右ゼロパディングで no-op)。in-place 回避で autograd 安全。
245
+ pad = h.size(1) - visual.size(1) # = T(prefix_refresh は必ず prefix 済)
246
+ return h + F.pad(visual, (0, 0, 0, pad))
247
+
248
+ def forward(
249
+ self,
250
+ input_ids=None,
251
+ attention_mask=None,
252
+ inputs_embeds=None,
253
+ vision_features=None,
254
+ output_hidden_states=False,
255
+ **kwargs,
256
+ ) -> LoopedModelOutput:
257
+ if inputs_embeds is None:
258
+ inputs_embeds = self.embed_tokens(input_ids)
259
+
260
+ # 視覚を connector で射影(ループ前に1回・prefix と in-loop で再利用)。
261
+ # vision_features is None(テキスト・全 eval)なら全 skip=①と完全同一経路(回帰不変条件)。
262
+ # connector(nn.Linear) は autocast 下で bf16 を出すが embed_tokens(Embedding) は fp32 のまま。
263
+ # cat/加算は dtype 昇格しないので embed の dtype に揃える(cuda bf16 で必須)。
264
+ inject_iters = self.config.visual_inject_iters
265
+ mode = self.config.visual_inject_mode
266
+ visual = None
267
+ if vision_features is not None and self.connector is not None:
268
+ visual = self.connector(vision_features.to(inputs_embeds.dtype)).to(inputs_embeds.dtype)
269
+
270
+ # prefix 連結: ②(inject_iters==0) と ④-B(prefix_refresh)。④-A(broadcast) は prefix しない。
271
+ use_prefix = visual is not None and (inject_iters == 0 or mode == "prefix_refresh")
272
+ n_visual = 0
273
+ if use_prefix:
274
+ n_visual = visual.size(1)
275
+ inputs_embeds = torch.cat([visual, inputs_embeds], dim=1)
276
+ if attention_mask is not None:
277
+ visual_mask = attention_mask.new_ones((attention_mask.size(0), n_visual))
278
+ attention_mask = torch.cat([visual_mask, attention_mask], dim=1)
279
+
280
+ h = inputs_embeds
281
+ # inject_input(③のループ機構=毎ループ入力を再加算)は**テキストのみ**再加算する。
282
+ # 視覚 prefix の再注入は inject() が単独で担い、両者の役割を分離する(ADR-0006)。
283
+ # → prefix 済なら residual の視覚位置を 0 に(視覚 prefix が inject_input で二重再加算されるのを防ぐ)。
284
+ residual_input = inputs_embeds # ③(視覚なし)はそのまま=従来挙動不変
285
+ if n_visual > 0:
286
+ residual_input = F.pad(inputs_embeds[:, n_visual:], (0, 0, n_visual, 0))
287
+ B, T, _ = h.shape
288
+ cos, sin = self._rope(T, h.device, h.dtype)
289
+ attn_bias = self._attn_bias(attention_mask, T, h.device, h.dtype)
290
+
291
+ # ④: in-loop 注入を行うか(inject_iters>0 かつ視覚あり)。②(inject_iters==0)は False。
292
+ do_inject = visual is not None and inject_iters > 0
293
+
294
+ all_hidden = [h] if output_hidden_states else None
295
+ loop_hidden = []
296
+
297
+ for block in self.prelude:
298
+ h = block(h, cos, sin, attn_bias)
299
+ if output_hidden_states:
300
+ all_hidden.append(h)
301
+ for loop_index in range(self.config.k):
302
+ # 各イテレーションの先頭で再注入(リフレッシュした視覚をこのイテレーションの計算に乗せる)。
303
+ if do_inject and loop_index < inject_iters:
304
+ h = self.inject(h, visual, loop_index)
305
+ for block in self.core:
306
+ h = block(h, cos, sin, attn_bias)
307
+ if output_hidden_states:
308
+ all_hidden.append(h)
309
+ if self.config.inject_input:
310
+ h = h + residual_input
311
+ loop_hidden.append(h)
312
+ for block in self.coda:
313
+ h = block(h, cos, sin, attn_bias)
314
+ if output_hidden_states:
315
+ all_hidden.append(h)
316
+
317
+ h = self.final_norm(h)
318
+ return LoopedModelOutput(
319
+ last_hidden_state=h,
320
+ hidden_states=tuple(all_hidden) if output_hidden_states else None,
321
+ loop_hidden_states=tuple(loop_hidden),
322
+ )
323
+
324
+
325
+ class LoopedForCausalLM(LoopedPreTrainedModel):
326
+ """言語モデリングヘッド付き(``AutoModelForCausalLM`` 互換)。"""
327
+
328
+ _tied_weights_keys = ["lm_head.weight"]
329
+
330
+ def __init__(self, config: BabyloopConfig):
331
+ super().__init__(config)
332
+ self.model = LoopedModel(config)
333
+ self.lm_head = nn.Linear(config.d_model, config.vocab_size, bias=False)
334
+ self.post_init()
335
+
336
+ def get_input_embeddings(self):
337
+ return self.model.embed_tokens
338
+
339
+ def set_input_embeddings(self, value):
340
+ self.model.embed_tokens = value
341
+
342
+ def get_output_embeddings(self):
343
+ return self.lm_head
344
+
345
+ def set_output_embeddings(self, new):
346
+ self.lm_head = new
347
+
348
+ def forward(
349
+ self,
350
+ input_ids=None,
351
+ attention_mask=None,
352
+ inputs_embeds=None,
353
+ vision_features=None,
354
+ labels=None,
355
+ output_hidden_states=False,
356
+ **kwargs,
357
+ ) -> LoopedCausalLMOutput:
358
+ out = self.model(
359
+ input_ids=input_ids,
360
+ attention_mask=attention_mask,
361
+ inputs_embeds=inputs_embeds,
362
+ vision_features=vision_features,
363
+ output_hidden_states=output_hidden_states,
364
+ )
365
+ logits = self.lm_head(out.last_hidden_state)
366
+
367
+ loss = None
368
+ if labels is not None:
369
+ # ②: 視覚 prefix が付くと logits 系列長 (V+L) が labels 長 (L) より長い。
370
+ # 差分 V 個の視覚位置を -100 で前置し、視覚位置では LM loss を取らない(テキストのみ)。
371
+ n_prefix = logits.size(1) - labels.size(1)
372
+ if n_prefix > 0:
373
+ pad = labels.new_full((labels.size(0), n_prefix), -100)
374
+ labels = torch.cat([pad, labels], dim=1)
375
+ shift_logits = logits[:, :-1, :].contiguous()
376
+ shift_labels = labels[:, 1:].contiguous()
377
+ loss = F.cross_entropy(
378
+ shift_logits.view(-1, shift_logits.size(-1)),
379
+ shift_labels.view(-1),
380
+ ignore_index=-100,
381
+ )
382
+
383
+ return LoopedCausalLMOutput(
384
+ loss=loss,
385
+ logits=logits,
386
+ hidden_states=out.hidden_states,
387
+ loop_hidden_states=out.loop_hidden_states,
388
+ )
389
+
390
+
391
+ # 公式 evaluation-pipeline が trust_remote_code で AutoModel 系から読めるよう登録。
392
+ # save_pretrained 時に auto_map と本ファイル群が checkpoint へ複製される。
393
+ BabyloopConfig.register_for_auto_class()
394
+ LoopedModel.register_for_auto_class("AutoModel")
395
+ LoopedForCausalLM.register_for_auto_class("AutoModelForCausalLM")
special_tokens_map.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": {
3
+ "content": "<|bos|>",
4
+ "lstrip": false,
5
+ "normalized": false,
6
+ "rstrip": false,
7
+ "single_word": false
8
+ },
9
+ "eos_token": {
10
+ "content": "<|eos|>",
11
+ "lstrip": false,
12
+ "normalized": false,
13
+ "rstrip": false,
14
+ "single_word": false
15
+ },
16
+ "pad_token": {
17
+ "content": "<|pad|>",
18
+ "lstrip": false,
19
+ "normalized": false,
20
+ "rstrip": false,
21
+ "single_word": false
22
+ },
23
+ "unk_token": {
24
+ "content": "<|unk|>",
25
+ "lstrip": false,
26
+ "normalized": false,
27
+ "rstrip": false,
28
+ "single_word": false
29
+ }
30
+ }
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "added_tokens_decoder": {
3
+ "0": {
4
+ "content": "<|pad|>",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": true
10
+ },
11
+ "1": {
12
+ "content": "<|bos|>",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false,
17
+ "special": true
18
+ },
19
+ "2": {
20
+ "content": "<|eos|>",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": true
26
+ },
27
+ "3": {
28
+ "content": "<|unk|>",
29
+ "lstrip": false,
30
+ "normalized": false,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": true
34
+ }
35
+ },
36
+ "bos_token": "<|bos|>",
37
+ "clean_up_tokenization_spaces": false,
38
+ "eos_token": "<|eos|>",
39
+ "extra_special_tokens": {},
40
+ "model_max_length": 512,
41
+ "pad_token": "<|pad|>",
42
+ "tokenizer_class": "PreTrainedTokenizer",
43
+ "unk_token": "<|unk|>"
44
+ }