wop commited on
Commit
247b1b6
·
verified ·
1 Parent(s): 983ce4c

Upload folder using huggingface_hub

Browse files
Cosmos-T2A-low.best.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:432493235c7821108adfc57c7642fd81f8aa035b6ffa3a8af3030855c8de0689
3
+ size 42266815
Cosmos-T2A-low.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:23cdbd4510ef1b8cc56910fc76a6886f61deaaf7144db54b1396ad05f5f1d69c
3
+ size 42300893
README.md ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ language:
4
+ - en
5
+ library_name: transformers
6
+ pipeline_tag: text-generation
7
+ tags:
8
+ - chain-of-thought
9
+ - reasoning
10
+ - instruct
11
+ - pretrained-from-scratch
12
+ - decoder-only
13
+ - transformer
14
+ - qwen-tokenizer
15
+ - rope
16
+ - rmsnorm
17
+ - swiglu
18
+ - gqa
19
+ - engram
20
+ datasets:
21
+ - wop/minitron-dataset
22
+ model-index:
23
+ - name: Cosmos T2A-low
24
+ results:
25
+ - task:
26
+ type: text-generation
27
+ name: Causal Language Modeling
28
+ dataset:
29
+ name: wop/minitron-dataset
30
+ type: wop/minitron-dataset
31
+ split: train
32
+ metrics:
33
+ - type: loss
34
+ name: Final training loss (cross-entropy)
35
+ value: 5.6389
36
+ - type: perplexity
37
+ name: Final training perplexity
38
+ value: 281.15
39
+ - type: loss
40
+ name: Final validation loss (cross-entropy)
41
+ value: 5.4913
42
+ - type: perplexity
43
+ name: Final validation perplexity
44
+ value: 242.56
45
+ ---
46
+
47
+ <img src="https://calm-heart-d697.mmmmmm505090.workers.dev?text=Cosmos T2A-low" width="900" alt="Cosmos T2A-low" />
48
+
49
+ # Cosmos T2A-low
50
+
51
+ Universal Kaggle-ready training notebook for the Cosmos T2A-low series.
52
+
53
+ > Notebook-generated card. Final metrics are filled after the Kaggle training run.
54
+ > This notebook is designed to stay Kaggle-friendly on 2x T4 GPUs. The goal is a reusable training recipe, not a production assistant.
55
+
56
+ ## Model Details
57
+
58
+ | | |
59
+ |---|---|
60
+ | **Model class** | `CosmosT2_Accelerate_LLM` |
61
+ | **Architecture** | Decoder-only Transformer with RoPE, RMSNorm, SwiGLU, GQA, and a configurable Engram memory path |
62
+ | **Parameters** | `~9.96 M` |
63
+ | **Layers** | `4` |
64
+ | **Attention heads** | `4` |
65
+ | **KV heads** | `1` |
66
+ | **d_model** | `64` |
67
+ | **FFN hidden** | `256` |
68
+ | **Positional encoding** | RoPE (`rope_base=10000`) |
69
+ | **Normalization** | RMSNorm |
70
+ | **MLP** | SwiGLU |
71
+ | **Memory** | Engram (`use_engram=True`, every `2` blocks) |
72
+ | **Context length** | `1028` |
73
+ | **Training block size** | `1028` |
74
+ | **Tokenizer** | [`Qwen/Qwen2.5-0.5B`](https://huggingface.co/Qwen/Qwen2.5-0.5B) |
75
+ | **Dataset** | [`wop/minitron-dataset`](https://huggingface.co/datasets/wop/minitron-dataset) |
76
+ | **License** | Apache-2.0 |
77
+
78
+ ### Why these choices
79
+
80
+ - **RoPE** keeps positional handling compact and avoids learned absolute embeddings.
81
+ - **RMSNorm** is cheaper and more stable than LayerNorm for this small decoder-only model.
82
+ - **SwiGLU** usually gives a better quality/compute tradeoff than a plain GELU MLP.
83
+ - **GQA** reduces KV cost while keeping multi-head query capacity.
84
+ - **Engram** gives the stack a lightweight explicit memory path for repeated reasoning patterns.
85
+ - **Dynamic isolated batching** keeps conversations separate while padding and masking each batch on CPU.
86
+ - **KV-cache generation** avoids recomputing the full prompt for every generated token in the app.
87
+
88
+ ## Training Summary
89
+
90
+ | Metric | Value |
91
+ |---|---|
92
+ | Rows used | `288,350` |
93
+ | Loss tokens seen | `46,651,194` |
94
+ | Epochs | `1` |
95
+ | Batch size | `2` |
96
+ | Peak LR | `3.00e-04` |
97
+ | Weight decay | `0.1` |
98
+ | Gradient clipping | `1.0` |
99
+ | Wall-clock time | `1h 37m 23s` |
100
+ | Final training loss | `5.6389` |
101
+ | Final training perplexity | `281.15` |
102
+ | Final validation loss | `5.4913` |
103
+ | Final validation perplexity | `242.56` |
104
+ | Best validation loss | `4.9614` |
105
+ | Best epoch | `1` |
106
+
107
+ ### Loss and perplexity
108
+
109
+ The notebook shows live loss and perplexity plots every `5000` epochs and does not save the graph to disk.
110
+
111
+ ## How to Use
112
+
113
+ ### Quick start
114
+
115
+ ~~~python
116
+ import torch
117
+ from transformers import AutoTokenizer
118
+
119
+ from app import CosmosT2_Accelerate_LLM
120
+
121
+ tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-0.5B")
122
+ if tokenizer.pad_token is None:
123
+ tokenizer.pad_token = tokenizer.eos_token
124
+
125
+ ckpt = torch.load("$CHECKPOINT_NAME", map_location="cpu")
126
+ model = CosmosT2_Accelerate_LLM(**ckpt["config"])
127
+ model.load_state_dict(ckpt["model_state"])
128
+ model.eval()
129
+
130
+ prompt = tokenizer.apply_chat_template(
131
+ [
132
+ {"role": "system", "content": "Enable thinking features: INTUITION"},
133
+ {"role": "user", "content": "What is 12 * 7?"},
134
+ ],
135
+ tokenize=False,
136
+ add_generation_prompt=True,
137
+ )
138
+ ids = tokenizer(prompt, return_tensors="pt", add_special_tokens=False).input_ids
139
+ out = model.generate(ids, max_new_tokens=120, temperature=0.8, top_k=50)
140
+ print(tokenizer.decode(out[0], skip_special_tokens=False))
141
+ ~~~
142
+
143
+ ### Prompt format
144
+
145
+ Use the Qwen2.5 chat template. The default system prompt is:
146
+
147
+ ~~~text
148
+ Enable thinking features: INTUITION
149
+ ~~~
150
+
151
+ The model will then emit a `<think>` block followed by an answer when it has enough signal.
152
+
153
+ The model is trained to end its turn with the `<|im_end|>` token (ChatML), so generation stops there. During data prep, any example longer than the `1028`-token context has its `<think>` reasoning replaced by a short placeholder (or is dropped) so every training sequence ends cleanly - the model is never trained on a mid-thought truncation.
154
+
155
+ ## Limitations
156
+
157
+ - The model is intentionally small and is still a research/demo artifact.
158
+ - Training on chain-of-thought data can overfit quickly if the corpus is tiny.
159
+ - Long-context behavior is limited by the configured block size.
160
+ - The model is not safety-aligned and should not be exposed as a public assistant without additional work.
161
+
162
+ ## Intended Use
163
+
164
+ - Research into small-scale pretraining and reasoning-style formatting
165
+ - Educational demos for decoder-only Transformer training
166
+ - Hugging Face Spaces or local inference demos
167
+ - Not for production use
168
+
169
+ ## Cosmos T2A-low Series
170
+
171
+ This notebook is designed to train future Cosmos T2A-low variants by changing only the config block at the top.
172
+
173
+ ## Citation
174
+
175
+ ~~~bibtex
176
+ @misc{cosmos-t2,
177
+ author = {wop},
178
+ title = {Cosmos-T2: A small from-scratch chain-of-thought Transformer},
179
+ year = {2026},
180
+ publisher = {Hugging Face},
181
+ url = {https://huggingface.co/wop/Cosmos-T2A-low}
182
+ }
183
+ ~~~
184
+
185
+ ## Acknowledgements
186
+
187
+ - Tokenizer from Qwen2.5 by Alibaba Cloud
188
+ - Training data from wop/minitron-dataset
189
+ - Trained on Kaggle T4 GPUs
__pycache__/demo.cpython-313.pyc ADDED
Binary file (23.9 kB). View file
 
demo.py ADDED
@@ -0,0 +1,382 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Cosmos T2A-low — Standalone CLI Demo
2
+
3
+ Interactive command-line demo for Cosmos T2A-low.
4
+ No Gradio, no web server — just pure Python inference.
5
+
6
+ Usage:
7
+ python demo.py # interactive chat
8
+ python demo.py --prompt "What is 12*7?" # single-prompt mode
9
+
10
+ Architecture: RoPE + RMSNorm + SwiGLU + GQA + Engram memory
11
+ """
12
+
13
+ import argparse
14
+ import sys
15
+ from pathlib import Path
16
+
17
+ import torch
18
+ import torch.nn as nn
19
+ import torch.nn.functional as F
20
+ from transformers import AutoTokenizer
21
+
22
+ # ---------------------------------------------------------------------------
23
+ # Constants
24
+ # ---------------------------------------------------------------------------
25
+ CHECKPOINT_DIR = Path(__file__).parent
26
+ FINAL_CKPT = CHECKPOINT_DIR / "Cosmos-T2A-low.pt"
27
+ BEST_CKPT = CHECKPOINT_DIR / "Cosmos-T2A-low.best.pt"
28
+
29
+ TOKENIZER_NAME = "Qwen/Qwen2.5-0.5B"
30
+ DEFAULT_SYSTEM_PROMPT = "Enable thinking features: INTUITION"
31
+ STOP_IDS = {151645, 151643}
32
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
33
+ DTYPE = torch.float16 if DEVICE == "cuda" else torch.float32
34
+
35
+
36
+ # ---------------------------------------------------------------------------
37
+ # Architecture
38
+ # ---------------------------------------------------------------------------
39
+
40
+ class RMSNorm(nn.Module):
41
+ def __init__(self, dim, eps=1e-6):
42
+ super().__init__()
43
+ self.weight = nn.Parameter(torch.ones(dim))
44
+ self.eps = eps
45
+ def forward(self, x):
46
+ rms = x.pow(2).mean(dim=-1, keepdim=True)
47
+ return x * torch.rsqrt(rms + self.eps) * self.weight
48
+
49
+
50
+ def rotate_half(x):
51
+ x1, x2 = x[..., ::2], x[..., 1::2]
52
+ return torch.stack((-x2, x1), dim=-1).flatten(-2)
53
+
54
+
55
+ def apply_rope(q, k, cos, sin):
56
+ return (q * cos) + (rotate_half(q) * sin), (k * cos) + (rotate_half(k) * sin)
57
+
58
+
59
+ class GQAAttention(nn.Module):
60
+ def __init__(self, d_model, n_heads, n_kv_heads, rope_base=10000, dropout=0.0):
61
+ super().__init__()
62
+ assert d_model % n_heads == 0 and n_heads % n_kv_heads == 0
63
+ self.n_heads = n_heads
64
+ self.n_kv_heads = n_kv_heads
65
+ self.head_dim = d_model // n_heads
66
+ self.dropout = dropout
67
+ self.q_proj = nn.Linear(d_model, n_heads * self.head_dim, bias=False)
68
+ self.k_proj = nn.Linear(d_model, n_kv_heads * self.head_dim, bias=False)
69
+ self.v_proj = nn.Linear(d_model, n_kv_heads * self.head_dim, bias=False)
70
+ self.o_proj = nn.Linear(d_model, d_model, bias=False)
71
+
72
+ def forward(self, x, rope_cos, rope_sin, past_kv=None, use_cache=False):
73
+ batch, seq_len, _ = x.shape
74
+ q = self.q_proj(x).view(batch, seq_len, self.n_heads, self.head_dim).transpose(1, 2)
75
+ k = self.k_proj(x).view(batch, seq_len, self.n_kv_heads, self.head_dim).transpose(1, 2)
76
+ v = self.v_proj(x).view(batch, seq_len, self.n_kv_heads, self.head_dim).transpose(1, 2)
77
+ q, k = apply_rope(q, k, rope_cos, rope_sin)
78
+ if past_kv is not None:
79
+ pk, pv = past_kv
80
+ k = torch.cat([pk, k], dim=2)
81
+ v = torch.cat([pv, v], dim=2)
82
+ present_kv = (k, v) if use_cache else None
83
+ if self.n_kv_heads != self.n_heads:
84
+ k = k.repeat_interleave(self.n_heads // self.n_kv_heads, dim=1)
85
+ v = v.repeat_interleave(self.n_heads // self.n_kv_heads, dim=1)
86
+ out = F.scaled_dot_product_attention(
87
+ q, k, v, is_causal=(past_kv is None),
88
+ dropout_p=self.dropout if self.training else 0.0
89
+ )
90
+ out = out.transpose(1, 2).contiguous().view(batch, seq_len, -1)
91
+ out = self.o_proj(out)
92
+ return (out, present_kv) if use_cache else out
93
+
94
+
95
+ class SwiGLUMLP(nn.Module):
96
+ def __init__(self, d_model, hidden_dim, dropout=0.0):
97
+ super().__init__()
98
+ self.gate = nn.Linear(d_model, hidden_dim, bias=False)
99
+ self.up = nn.Linear(d_model, hidden_dim, bias=False)
100
+ self.down = nn.Linear(hidden_dim, d_model, bias=False)
101
+ self.dropout = nn.Dropout(dropout)
102
+ def forward(self, x):
103
+ return self.down(self.dropout(F.silu(self.gate(x)) * self.up(x)))
104
+
105
+
106
+ class EngramMemory(nn.Module):
107
+ def __init__(self, d_model, bucket_count, memory_dim, order, pad_id=0, dropout=0.0):
108
+ super().__init__()
109
+ self.bucket_count = bucket_count
110
+ self.order = order
111
+ self.pad_id = pad_id
112
+ self.bucket = nn.Embedding(bucket_count, memory_dim)
113
+ self.query = nn.Linear(d_model, memory_dim, bias=False)
114
+ self.project = nn.Linear(memory_dim, d_model, bias=False)
115
+ self.gate = nn.Linear(d_model, d_model, bias=True)
116
+ self.dropout = nn.Dropout(dropout)
117
+ primes = [1, 1315423911, 2654435761, 97531, 433494437]
118
+ self.register_buffer("primes", torch.tensor(primes[:order], dtype=torch.long), persistent=False)
119
+
120
+ def hash_tokens(self, idx):
121
+ B, S = idx.shape
122
+ pad = torch.full((B, self.order - 1), self.pad_id, device=idx.device, dtype=idx.dtype)
123
+ history = torch.cat([pad, idx], dim=1)
124
+ hashed = torch.zeros((B, S), device=idx.device, dtype=torch.long)
125
+ for off in range(self.order):
126
+ sl = history[:, off: off + S].long()
127
+ hashed = (hashed * 1315423911 + sl * self.primes[off]) % self.bucket_count
128
+ return hashed
129
+
130
+ def forward(self, x, idx):
131
+ hashed = self.hash_tokens(idx)
132
+ if hashed.size(1) != x.size(1):
133
+ hashed = hashed[:, -x.size(1):]
134
+ query = torch.tanh(self.query(x))
135
+ mem = self.bucket(hashed) * query
136
+ mem = self.project(mem)
137
+ gate = torch.sigmoid(self.gate(x))
138
+ return self.dropout(gate * mem)
139
+
140
+
141
+ class Block(nn.Module):
142
+ def __init__(self, d_model, n_heads, n_kv_heads, d_ff, rope_base, dropout=0.0,
143
+ use_engram=False, engram_bucket_count=128, engram_dim=16, engram_order=3, pad_id=0):
144
+ super().__init__()
145
+ self.norm1 = RMSNorm(d_model)
146
+ self.attn = GQAAttention(d_model, n_heads, n_kv_heads, rope_base=rope_base, dropout=dropout)
147
+ self.norm2 = RMSNorm(d_model)
148
+ self.engram = EngramMemory(d_model, engram_bucket_count, engram_dim, engram_order,
149
+ pad_id=pad_id, dropout=dropout) if use_engram else None
150
+ self.norm3 = RMSNorm(d_model)
151
+ self.mlp = SwiGLUMLP(d_model, d_ff, dropout=dropout)
152
+
153
+ def forward(self, x, idx, rope_cos, rope_sin):
154
+ x = x + self.attn(self.norm1(x), rope_cos, rope_sin)
155
+ if self.engram is not None:
156
+ x = x + self.engram(self.norm2(x), idx)
157
+ return x + self.mlp(self.norm3(x))
158
+
159
+
160
+ class CosmosT2_Accelerate_LLM(nn.Module):
161
+ def __init__(self, vocab_size, d_model=64, n_layers=4, n_heads=4, n_kv_heads=1,
162
+ d_ff=256, max_len=1028, rope_base=10000, dropout=0.05, use_engram=True,
163
+ engram_every=2, engram_bucket_count=128, engram_dim=16, engram_order=3, pad_id=0):
164
+ super().__init__()
165
+ self.vocab_size = vocab_size
166
+ self.d_model = d_model
167
+ self.n_layers = n_layers
168
+ self.n_heads = n_heads
169
+ self.n_kv_heads = n_kv_heads
170
+ self.head_dim = d_model // n_heads
171
+ self.max_len = max_len
172
+ self.rope_base = rope_base
173
+ self.pad_id = pad_id
174
+ self.tok_emb = nn.Embedding(vocab_size, d_model)
175
+ self.blocks = nn.ModuleList()
176
+ for layer_index in range(n_layers):
177
+ block_uses_engram = use_engram and ((layer_index + 1) % engram_every == 0)
178
+ self.blocks.append(Block(
179
+ d_model=d_model, n_heads=n_heads, n_kv_heads=n_kv_heads, d_ff=d_ff,
180
+ rope_base=rope_base, dropout=dropout, use_engram=block_uses_engram,
181
+ engram_bucket_count=engram_bucket_count, engram_dim=engram_dim,
182
+ engram_order=engram_order, pad_id=pad_id,
183
+ ))
184
+ self.norm_f = RMSNorm(d_model)
185
+
186
+ def build_rope(self, seq_len, device, dtype, start_pos=0):
187
+ inv_freq = 1.0 / (self.rope_base ** (
188
+ torch.arange(0, self.head_dim, 2, device=device, dtype=torch.float32) / self.head_dim
189
+ ))
190
+ positions = torch.arange(start_pos, start_pos + seq_len, device=device, dtype=torch.float32)
191
+ freqs = torch.outer(positions, inv_freq)
192
+ cos = freqs.cos().repeat_interleave(2, dim=-1).to(dtype)[None, None, :, :]
193
+ sin = freqs.sin().repeat_interleave(2, dim=-1).to(dtype)[None, None, :, :]
194
+ return cos, sin
195
+
196
+ def forward(self, idx, targets=None):
197
+ if idx.size(1) > self.max_len:
198
+ idx = idx[:, -self.max_len:]
199
+ seq_len = idx.size(1)
200
+ rope_cos, rope_sin = self.build_rope(seq_len, idx.device, self.tok_emb.weight.dtype)
201
+ x = self.tok_emb(idx)
202
+ for block in self.blocks:
203
+ x = block(x, idx, rope_cos, rope_sin)
204
+ x = self.norm_f(x)
205
+ logits = F.linear(x, self.tok_emb.weight)
206
+ loss = None
207
+ if targets is not None:
208
+ loss = F.cross_entropy(logits.reshape(-1, logits.size(-1)), targets.reshape(-1))
209
+ return logits, loss
210
+
211
+ @torch.no_grad()
212
+ def generate(self, input_ids, max_new_tokens=128, temperature=0.1, top_k=1):
213
+ self.eval()
214
+ cur_ids = input_ids.to(DEVICE)
215
+ for _ in range(max_new_tokens):
216
+ logits, _ = self.forward(cur_ids[:, -self.max_len:])
217
+ next_logit = logits[:, -1, :] / max(temperature, 1e-8)
218
+ if top_k > 1:
219
+ top_vals, _ = torch.topk(next_logit, top_k, dim=-1)
220
+ next_logit[next_logit < top_vals[:, -1:]] = float('-inf')
221
+ probs = F.softmax(next_logit, dim=-1)
222
+ nxt = torch.multinomial(probs, num_samples=1)
223
+ if nxt.item() in STOP_IDS:
224
+ break
225
+ cur_ids = torch.cat([cur_ids, nxt], dim=1)
226
+ return cur_ids
227
+
228
+
229
+ # ---------------------------------------------------------------------------
230
+ # Loading
231
+ # ---------------------------------------------------------------------------
232
+
233
+ def load_model(checkpoint_path=None):
234
+ if checkpoint_path is None:
235
+ ckpt_path = FINAL_CKPT if FINAL_CKPT.exists() else BEST_CKPT
236
+ else:
237
+ ckpt_path = Path(checkpoint_path)
238
+ if not ckpt_path.exists():
239
+ raise FileNotFoundError(f"Checkpoint not found: {ckpt_path}")
240
+
241
+ print(f"Loading checkpoint: {ckpt_path}")
242
+ ckpt = torch.load(ckpt_path, map_location="cpu", weights_only=False)
243
+ config = ckpt.get("config", {})
244
+
245
+ model = CosmosT2_Accelerate_LLM(
246
+ vocab_size=config.get("vocab_size", 151936),
247
+ d_model=config.get("d_model", 64),
248
+ n_layers=config.get("n_layers", 4),
249
+ n_heads=config.get("n_heads", 4),
250
+ n_kv_heads=config.get("n_kv_heads", 1),
251
+ d_ff=config.get("d_ff", 256),
252
+ max_len=config.get("max_len", 1028),
253
+ rope_base=config.get("rope_base", 10000),
254
+ dropout=config.get("dropout", 0.05),
255
+ use_engram=config.get("use_engram", True),
256
+ engram_every=config.get("engram_every", 2),
257
+ engram_bucket_count=config.get("engram_bucket_count", 128),
258
+ engram_dim=config.get("engram_dim", 16),
259
+ engram_order=config.get("engram_order", 3),
260
+ pad_id=config.get("pad_id", 0),
261
+ )
262
+ model.load_state_dict(ckpt["model_state"], strict=False)
263
+ model = model.to(DEVICE, dtype=DTYPE)
264
+ model.eval()
265
+ params = sum(p.numel() for p in model.parameters())
266
+ print(f"Model loaded on {DEVICE}: {params/1e6:.2f}M parameters")
267
+ return model
268
+
269
+
270
+ # ---------------------------------------------------------------------------
271
+ # Prompt helpers
272
+ # ---------------------------------------------------------------------------
273
+
274
+ def build_prompt(user_message, system_prompt=None):
275
+ if system_prompt is None:
276
+ system_prompt = DEFAULT_SYSTEM_PROMPT
277
+ messages = [
278
+ {"role": "system", "content": system_prompt},
279
+ {"role": "user", "content": user_message},
280
+ ]
281
+ return tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
282
+
283
+
284
+ def generate_response(model, prompt, max_new=256, temperature=0.1, top_k=1):
285
+ ids = tokenizer(prompt, return_tensors="pt", add_special_tokens=False).input_ids.to(DEVICE)
286
+ out = model.generate(ids, max_new_tokens=max_new, temperature=temperature, top_k=top_k)
287
+ response = tokenizer.decode(out[0], skip_special_tokens=False)
288
+ if "<|im_start|>assistant" in response:
289
+ parts = response.split("<|im_start|>assistant")
290
+ if len(parts) > 1:
291
+ response = parts[-1].split("<|im_end|>")[0].strip()
292
+ return response
293
+
294
+
295
+ # ---------------------------------------------------------------------------
296
+ # Interactive chat
297
+ # ---------------------------------------------------------------------------
298
+
299
+ def interactive_chat(model):
300
+ print("\n" + "=" * 60)
301
+ print(" Cosmos T2A-low — Interactive Demo")
302
+ print(" Type /quit to exit, /clear to reset context")
303
+ print("=" * 60 + "\n")
304
+
305
+ history = []
306
+ while True:
307
+ try:
308
+ user_msg = input("You: ").strip()
309
+ except (EOFError, KeyboardInterrupt):
310
+ print("\nGoodbye!")
311
+ break
312
+ if not user_msg:
313
+ continue
314
+ if user_msg.lower() in ("/quit", "/exit", "/q"):
315
+ print("Goodbye!")
316
+ break
317
+ if user_msg.lower() == "/clear":
318
+ history = []
319
+ print("[Context cleared]\n")
320
+ continue
321
+
322
+ if history:
323
+ prompt = tokenizer.apply_chat_template(
324
+ history + [{"role": "user", "content": user_msg}],
325
+ tokenize=False, add_generation_prompt=True
326
+ )
327
+ else:
328
+ prompt = build_prompt(user_msg)
329
+
330
+ print("Cosmos: ", end="", flush=True)
331
+ ids = tokenizer(prompt, return_tensors="pt", add_special_tokens=False).input_ids.to(DEVICE)
332
+ out = model.generate(ids, max_new_tokens=256, temperature=0.1, top_k=1)
333
+ full_response = tokenizer.decode(out[0], skip_special_tokens=False)
334
+
335
+ if "<|im_start|>assistant" in full_response:
336
+ parts = full_response.split("<|im_start|>assistant")
337
+ response = parts[-1].split("<|im_end|>")[0].strip() if len(parts) > 1 else full_response.strip()
338
+ else:
339
+ response = full_response.strip()
340
+
341
+ print(response)
342
+ print()
343
+ history.append({"role": "user", "content": user_msg})
344
+ history.append({"role": "assistant", "content": response})
345
+ if len(history) > 20:
346
+ history = history[-20:]
347
+
348
+
349
+ # ---------------------------------------------------------------------------
350
+ # Main
351
+ # ---------------------------------------------------------------------------
352
+
353
+ if __name__ == "__main__":
354
+ parser = argparse.ArgumentParser(description="Cosmos T2A-low CLI Demo")
355
+ parser.add_argument("--checkpoint", type=str, default=None,
356
+ help="Path to checkpoint .pt file")
357
+ parser.add_argument("--prompt", type=str, default=None,
358
+ help="Single prompt (non-interactive mode)")
359
+ parser.add_argument("--max-new", type=int, default=256,
360
+ help="Max new tokens to generate")
361
+ parser.add_argument("--temperature", type=float, default=0.1,
362
+ help="Sampling temperature")
363
+ parser.add_argument("--top-k", type=int, default=1,
364
+ help="Top-K sampling")
365
+ args = parser.parse_args()
366
+
367
+ print(f"Device: {DEVICE} | Dtype: {DTYPE}")
368
+ print(f"Loading tokenizer: {TOKENIZER_NAME}")
369
+ tokenizer = AutoTokenizer.from_pretrained(TOKENIZER_NAME)
370
+ if tokenizer.pad_token is None:
371
+ tokenizer.pad_token = tokenizer.eos_token
372
+
373
+ model = load_model(args.checkpoint)
374
+
375
+ if args.prompt:
376
+ print(f"\nPrompt: {args.prompt}\n")
377
+ prompt = build_prompt(args.prompt)
378
+ response = generate_response(model, prompt, max_new=args.max_new,
379
+ temperature=args.temperature, top_k=args.top_k)
380
+ print(f"Response: {response}")
381
+ else:
382
+ interactive_chat(model)
history.json ADDED
The diff for this file is too large to render. See raw diff
 
model_config.json ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_family": "Cosmos T2A-low",
3
+ "model_name": "Cosmos T2A-low",
4
+ "model_class_name": "CosmosT2_Accelerate_LLM",
5
+ "hf_repo_id": "wop/Cosmos-T2A-low",
6
+ "tokenizer_name": "Qwen/Qwen2.5-0.5B",
7
+ "dataset_name": "wop/minitron-dataset",
8
+ "dataset_split": "train",
9
+ "dataset_row_limit": 288350,
10
+ "rows_used": 288350,
11
+ "stream_dataset": true,
12
+ "shuffle_buffer_size": 2048,
13
+ "train_val_fraction": 0.1,
14
+ "seed": 42,
15
+ "block_size": 1028,
16
+ "max_len": 1028,
17
+ "d_model": 64,
18
+ "n_layers": 4,
19
+ "n_heads": 4,
20
+ "n_kv_heads": 1,
21
+ "d_ff": 256,
22
+ "rope_base": 10000,
23
+ "dropout": 0.05,
24
+ "use_engram": true,
25
+ "engram_every": 2,
26
+ "engram_buckets": 128,
27
+ "engram_dim": 16,
28
+ "engram_order": 3,
29
+ "epochs": 1,
30
+ "batch_size": 2,
31
+ "lr": 0.0003,
32
+ "weight_decay": 0.1,
33
+ "warmup_steps": 50,
34
+ "grad_clip": 1.0,
35
+ "log_every_steps": 5000,
36
+ "eval_every_steps": 5000,
37
+ "plot_every_epochs": 5000,
38
+ "val_max_batches": 10,
39
+ "early_stopping_patience": 2,
40
+ "tokenization_batch_size": 256,
41
+ "num_workers": 1,
42
+ "pin_memory": true,
43
+ "dataloader_prefetch_factor": 4,
44
+ "persistent_workers": true,
45
+ "use_kv_cache": true,
46
+ "train_steps_per_epoch": 129757,
47
+ "loss_tokens_seen": 46651194,
48
+ "samples_seen": 222956
49
+ }