Download app.py from ml-intern-explorers/MiniCoder-1-Inference: direct link, hf CLI and curl.
- Browser
- Download file 21.5 kB
-
https://huggingface.co/spaces/ml-intern-explorers/MiniCoder-1-Inference/resolve/760fed13c0fbb346d7bf1ebc73d2a68da4a13236/app.py
- Command line
-
hf download hf://spaces/ml-intern-explorers/MiniCoder-1-Inference@760fed13c0fbb346d7bf1ebc73d2a68da4a13236/app.py
-
curl -L -o app.py https://huggingface.co/spaces/ml-intern-explorers/MiniCoder-1-Inference/resolve/760fed13c0fbb346d7bf1ebc73d2a68da4a13236/app.py
21.5 kB
| # app.py β CodVa-2 Demo (PRETRAIN model, domain tokens only) | |
| import os | |
| import math | |
| import time | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| import gradio as gr | |
| from dataclasses import dataclass | |
| from typing import Tuple, Generator | |
| from tokenizers import Tokenizer | |
| from huggingface_hub import hf_hub_download, login, HfApi | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # AUTH | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| HF_TOKEN = os.environ.get("HF_TOKEN", "") | |
| HF_DATASET_REPO = "Bc-AI/nova1_data" | |
| HF_MODEL_REPO = os.environ.get("MODEL_REPO", "hugging-science/CodVa-2-session-002") | |
| if HF_TOKEN: | |
| login(token=HF_TOKEN) | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # CONFIG | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class Config: | |
| vocab_size: int = 50304 | |
| d_model: int = 896 | |
| n_layers: int = 18 | |
| n_heads: int = 14 | |
| n_kv_heads: int = 2 | |
| max_len: int = 2048 | |
| rope_theta: float = 500_000.0 | |
| window_size: int = 512 | |
| pattern_mult: float = 2.5 | |
| reason_mult: float = 0.75 | |
| reason_depth: int = 2 | |
| gate_hidden: int = 64 | |
| gate_init: float = 0.0 | |
| diff_lambda_init: float = 0.8 | |
| tie_embeddings: bool = True | |
| def head_dim(self): | |
| return self.d_model // self.n_heads | |
| def pattern_dim(self): | |
| return ((int(self.d_model * self.pattern_mult) + 255) // 256) * 256 | |
| def reason_dim(self): | |
| return ((int(self.d_model * self.reason_mult) + 63) // 64) * 64 | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # MODEL | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class RMSNorm(nn.Module): | |
| def __init__(self, dim: int, eps: float = 1e-6): | |
| super().__init__() | |
| self.eps = eps | |
| self.w = nn.Parameter(torch.ones(dim)) | |
| def forward(self, x): | |
| x32 = x.float() | |
| return (x32 * torch.rsqrt( | |
| x32.pow(2).mean(-1, keepdim=True) + self.eps | |
| ) * self.w).to(x.dtype) | |
| def precompute_rope(head_dim, max_len, theta, device): | |
| inv_freq = 1.0 / (theta ** ( | |
| torch.arange(0, head_dim, 2, device=device, dtype=torch.float32) / head_dim | |
| )) | |
| pos = torch.arange(max_len, device=device, dtype=torch.float32) | |
| freqs = torch.outer(pos, inv_freq) | |
| return freqs.cos(), freqs.sin() | |
| def apply_rope(x, cos, sin): | |
| B, H, L, D = x.shape | |
| h = D // 2 | |
| c = cos[:L].unsqueeze(0).unsqueeze(0) | |
| s = sin[:L].unsqueeze(0).unsqueeze(0) | |
| return torch.cat([ | |
| x[..., :h] * c - x[..., h:] * s, | |
| x[..., h:] * c + x[..., :h] * s, | |
| ], dim=-1) | |
| def repeat_kv(x, n_rep): | |
| if n_rep == 1: return x | |
| B, H, L, D = x.shape | |
| return x.unsqueeze(2).expand(B, H, n_rep, L, D).reshape(B, H * n_rep, L, D) | |
| class DifferentialAttention(nn.Module): | |
| def __init__(self, cfg, layer_idx, local=False): | |
| super().__init__() | |
| self.n_pairs = cfg.n_heads // 2 | |
| self.n_kv_pairs = max(1, cfg.n_kv_heads // 2) | |
| self.n_rep = self.n_pairs // self.n_kv_pairs | |
| self.head_dim = cfg.head_dim | |
| self.local = local | |
| self.window = cfg.window_size | |
| d = cfg.d_model | |
| self.wq = nn.Linear(d, 2 * self.n_pairs * self.head_dim, bias=False) | |
| self.wk = nn.Linear(d, 2 * self.n_kv_pairs * self.head_dim, bias=False) | |
| self.wv = nn.Linear(d, self.n_kv_pairs * self.head_dim, bias=False) | |
| self.wo = nn.Linear( self.n_pairs * self.head_dim, d, bias=False) | |
| self.q_norm = RMSNorm(self.head_dim) | |
| self.k_norm = RMSNorm(self.head_dim) | |
| self.lambda1 = nn.Parameter(torch.tensor(0.0)) | |
| self.lambda2 = nn.Parameter(torch.tensor(0.0)) | |
| self.out_norm = RMSNorm(self.head_dim) | |
| def _window_mask(self, L, device): | |
| idx = torch.arange(L, device=device) | |
| dist = idx.unsqueeze(0) - idx.unsqueeze(1) | |
| mask = (dist > 0) | (dist < -self.window) | |
| return mask.float().masked_fill(mask, float('-inf')) | |
| def forward(self, x, cos, sin): | |
| B, L, _ = x.shape | |
| hd = self.head_dim | |
| q_all = self.wq(x).view(B, L, self.n_pairs, 2, hd).transpose(1, 2) | |
| k_all = self.wk(x).view(B, L, self.n_kv_pairs, 2, hd).transpose(1, 2) | |
| v = self.wv(x).view(B, L, self.n_kv_pairs, hd).transpose(1, 2) | |
| q1, q2 = q_all[..., 0, :], q_all[..., 1, :] | |
| k1, k2 = k_all[..., 0, :], k_all[..., 1, :] | |
| q1 = self.q_norm(q1); q2 = self.q_norm(q2) | |
| k1 = self.k_norm(k1); k2 = self.k_norm(k2) | |
| q1 = apply_rope(q1, cos, sin); q2 = apply_rope(q2, cos, sin) | |
| k1 = apply_rope(k1, cos, sin); k2 = apply_rope(k2, cos, sin) | |
| k1 = repeat_kv(k1, self.n_rep); k2 = repeat_kv(k2, self.n_rep) | |
| v = repeat_kv(v, self.n_rep) | |
| scale = 1.0 / math.sqrt(hd) | |
| mask = (self._window_mask(L, x.device) if self.local | |
| else torch.zeros(L, L, device=x.device).masked_fill( | |
| ~torch.ones(L, L, device=x.device, dtype=torch.bool).tril(), | |
| float('-inf'))) | |
| a1 = F.softmax(torch.matmul(q1, k1.transpose(-2, -1)) * scale + mask, dim=-1) | |
| a2 = F.softmax(torch.matmul(q2, k2.transpose(-2, -1)) * scale + mask, dim=-1) | |
| lam = torch.exp(self.lambda1) - torch.exp(self.lambda2) + 0.5 | |
| out = torch.matmul(a1 - lam * a2, v) | |
| out = self.out_norm(out).transpose(1, 2).contiguous().view(B, L, -1) | |
| return self.wo(out) | |
| class DualPathFFN(nn.Module): | |
| def __init__(self, cfg): | |
| super().__init__() | |
| d, pd, rd = cfg.d_model, cfg.pattern_dim, cfg.reason_dim | |
| self.pat_gate = nn.Linear(d, pd, bias=False) | |
| self.pat_up = nn.Linear(d, pd, bias=False) | |
| self.pat_down = nn.Linear(pd, d, bias=False) | |
| layers = [nn.Linear(d, rd, bias=False), nn.SiLU()] | |
| for _ in range(cfg.reason_depth - 1): | |
| layers += [nn.Linear(rd, rd, bias=False), nn.SiLU()] | |
| layers.append(nn.Linear(rd, d, bias=False)) | |
| self.reason = nn.Sequential(*layers) | |
| self.merge = nn.Parameter(torch.zeros(d)) | |
| def forward(self, x): | |
| pat = self.pat_down(F.silu(self.pat_gate(x)) * self.pat_up(x)) | |
| w = torch.sigmoid(self.merge) | |
| return w * pat + (1.0 - w) * self.reason(x) | |
| class TokenImportanceGate(nn.Module): | |
| def __init__(self, cfg): | |
| super().__init__() | |
| self.net = nn.Sequential( | |
| nn.Linear(cfg.d_model, cfg.gate_hidden, bias=True), | |
| nn.SiLU(), | |
| nn.Linear(cfg.gate_hidden, 1, bias=True), | |
| ) | |
| def forward(self, x): | |
| return x * (0.5 + torch.sigmoid(self.net(x))) | |
| class Block(nn.Module): | |
| def __init__(self, cfg, layer_idx): | |
| super().__init__() | |
| self.norm1 = RMSNorm(cfg.d_model) | |
| self.norm2 = RMSNorm(cfg.d_model) | |
| self.attn = DifferentialAttention(cfg, layer_idx, local=(layer_idx % 2 == 0)) | |
| self.ffn = DualPathFFN(cfg) | |
| def forward(self, x, cos, sin): | |
| x = x + self.attn(self.norm1(x), cos, sin) | |
| x = x + self.ffn(self.norm2(x)) | |
| return x | |
| class CodVa2(nn.Module): | |
| def __init__(self, cfg): | |
| super().__init__() | |
| self.cfg = cfg | |
| self.embed = nn.Embedding(cfg.vocab_size, cfg.d_model) | |
| self.importance = TokenImportanceGate(cfg) | |
| self.blocks = nn.ModuleList([Block(cfg, i) for i in range(cfg.n_layers)]) | |
| self.final_norm = RMSNorm(cfg.d_model) | |
| self.register_buffer("rope_cos", torch.zeros(cfg.max_len, cfg.head_dim // 2)) | |
| self.register_buffer("rope_sin", torch.zeros(cfg.max_len, cfg.head_dim // 2)) | |
| self._rope_ready = False | |
| def _init_rope(self, device): | |
| c, s = precompute_rope( | |
| self.cfg.head_dim, self.cfg.max_len, self.cfg.rope_theta, device | |
| ) | |
| self.rope_cos.copy_(c) | |
| self.rope_sin.copy_(s) | |
| self._rope_ready = True | |
| def forward(self, tokens): | |
| B, L = tokens.shape | |
| device = tokens.device | |
| if not self._rope_ready: | |
| self._init_rope(device) | |
| cos = self.rope_cos[:L] | |
| sin = self.rope_sin[:L] | |
| x = self.importance(self.embed(tokens)) | |
| for block in self.blocks: | |
| x = block(x, cos, sin) | |
| return F.linear(self.final_norm(x), self.embed.weight) | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # LOAD TOKENIZER + MODEL | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| print("[init] loading tokenizer...") | |
| tok_path = hf_hub_download( | |
| repo_id=HF_DATASET_REPO, | |
| filename="nova_tokenizer.json", | |
| repo_type="dataset", | |
| token=HF_TOKEN or None, | |
| ) | |
| tokenizer = Tokenizer.from_file(tok_path) | |
| # Domain tokens | |
| DOMAIN_TOKENS = { | |
| "Code": "<|domain_code|>", | |
| "Math": "<|domain_math|>", | |
| "General": "<|domain_general|>", | |
| "Reasoning": "<|domain_reasoning|>", | |
| } | |
| EOS_ID = tokenizer.token_to_id("<|endoftext|>") or tokenizer.token_to_id("</s>") or -1 | |
| print(f"[init] tokenizer | vocab={tokenizer.get_vocab_size()} | eos={EOS_ID}") | |
| print("[init] loading model...") | |
| cfg = Config() | |
| cfg.vocab_size = (tokenizer.get_vocab_size() + 63) // 64 * 64 | |
| model = CodVa2(cfg) | |
| api = HfApi() | |
| files = list(api.list_repo_files( | |
| repo_id=HF_MODEL_REPO, repo_type="model", token=HF_TOKEN or None | |
| )) | |
| finals = sorted([f for f in files if "final" in f and f.endswith(".safetensors")]) | |
| ckpts = sorted( | |
| [f for f in files if "step" in f and f.endswith(".pt")], | |
| key=lambda x: int(x.split("step")[-1].split(".")[0]) | |
| ) | |
| if finals: | |
| print(f"[init] loading final: {finals[-1]}") | |
| from safetensors.torch import load_file | |
| wpath = hf_hub_download(HF_MODEL_REPO, finals[-1], | |
| repo_type="model", token=HF_TOKEN or None) | |
| model.load_state_dict(load_file(wpath, device="cpu"), strict=True) | |
| elif ckpts: | |
| print(f"[init] loading checkpoint: {ckpts[-1]}") | |
| wpath = hf_hub_download(HF_MODEL_REPO, ckpts[-1], | |
| repo_type="model", token=HF_TOKEN or None) | |
| ckpt = torch.load(wpath, map_location="cpu", weights_only=False) | |
| model.load_state_dict(ckpt["model"], strict=True) | |
| else: | |
| print("[init] WARNING: no weights found β random init") | |
| model.eval() | |
| n_params = sum(p.numel() for p in model.parameters()) | |
| print(f"[init] ready | {n_params/1e6:.1f}M params | CPU inference") | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # STREAMING GENERATION | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def generate_stream( | |
| prompt: str, | |
| domain: str, | |
| max_new: int = 256, | |
| temperature: float = 0.8, | |
| top_p: float = 0.95, | |
| top_k: int = 50, | |
| ) -> Generator[Tuple[str, str], None, None]: | |
| """ | |
| Pretrain-style generation with domain token prepending. | |
| Model sees: <|domain_X|>{prompt} | |
| Continues from there. | |
| """ | |
| if not prompt or not prompt.strip(): | |
| yield "", "β οΈ Please enter a prompt" | |
| return | |
| # Prepend domain token (matches training data format) | |
| domain_token = DOMAIN_TOKENS.get(domain, "<|domain_code|>") | |
| full_prompt = domain_token + prompt.strip() | |
| enc = tokenizer.encode(full_prompt) | |
| ids = enc.ids | |
| # Truncate if too long | |
| if len(ids) > cfg.max_len - max_new: | |
| ids = ids[-(cfg.max_len - max_new):] | |
| x = torch.tensor([ids], dtype=torch.long) | |
| generated = [] | |
| t0 = time.time() | |
| for step in range(int(max_new)): | |
| # Truncate context to max_len | |
| x_in = x[:, -cfg.max_len:] if x.size(1) > cfg.max_len else x | |
| logits = model(x_in)[0, -1, :].float() | |
| # Temperature scaling | |
| logits = logits / max(float(temperature), 1e-5) | |
| # Top-k filtering | |
| if top_k > 0: | |
| k = min(int(top_k), logits.size(-1)) | |
| topk_vals,_ = torch.topk(logits, k) | |
| logits[logits < topk_vals[-1]] = float('-inf') | |
| # Top-p (nucleus) filtering | |
| probs = F.softmax(logits, dim=-1) | |
| sorted_p, sorted_idx = probs.sort(descending=True) | |
| cumsum_p = sorted_p.cumsum(0) | |
| sorted_p[(cumsum_p - sorted_p) > float(top_p)] = 0.0 | |
| sorted_p = sorted_p / sorted_p.sum().clamp(min=1e-9) | |
| # Sample | |
| next_tok = sorted_idx[torch.multinomial(sorted_p, num_samples=1)].item() | |
| generated.append(next_tok) | |
| x = torch.cat([x, torch.tensor([[next_tok]])], dim=1) | |
| # Decode what we have so far (strip domain token from display) | |
| full_text = tokenizer.decode(ids + generated, skip_special_tokens=False) | |
| # Remove domain token from display | |
| display_text = full_text | |
| for tok in DOMAIN_TOKENS.values(): | |
| display_text = display_text.replace(tok, "") | |
| # Build stats | |
| elapsed = time.time() - t0 | |
| tps = len(generated) / max(elapsed, 1e-3) | |
| stats = ( | |
| f"β± {elapsed:.1f}s | " | |
| f"π€ {len(generated)} / {max_new} tokens | " | |
| f"β‘ {tps:.1f} tok/s | " | |
| f"π― {domain} | " | |
| f"π‘ {temperature} top-p {top_p} top-k {int(top_k)}" | |
| ) | |
| yield display_text, stats | |
| # Stop on EOS | |
| if EOS_ID >= 0 and next_tok == EOS_ID: | |
| break | |
| # Final yield | |
| full_text = tokenizer.decode(ids + generated, skip_special_tokens=False) | |
| for tok in DOMAIN_TOKENS.values(): | |
| full_text = full_text.replace(tok, "") | |
| elapsed = time.time() - t0 | |
| tps = len(generated) / max(elapsed, 1e-3) | |
| yield ( | |
| full_text, | |
| f"β Done | β± {elapsed:.1f}s | " | |
| f"π€ {len(generated)} tokens | β‘ {tps:.1f} tok/s" | |
| ) | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # GRADIO UI | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| EXAMPLES = [ | |
| ["def fibonacci(n):\n ", "Code", 128, 0.2, 0.95, 50], | |
| ["class BinaryTree:\n def __init__(self):\n ", "Code", 256, 0.3, 0.95, 50], | |
| ["import torch\nimport torch.nn as nn\n\n", "Code", 200, 0.4, 0.95, 50], | |
| ["SELECT users.name, orders.total FROM ", "Code", 100, 0.3, 0.90, 40], | |
| ["# Quicksort implementation\ndef quicksort(arr):\n ", "Code", 200, 0.2, 0.95, 50], | |
| ["Problem: Find the derivative of f(x) = x^3 + 2x^2 - 5x + 1\n\nSolution: ", "Math", 150, 0.4, 0.95, 50], | |
| ["Theorem: The sum of angles in a triangle equals 180 degrees.\n\nProof: ", "Math", 200, 0.5, 0.95, 50], | |
| ["Let $f(x) = \\int_0^x t^2 dt$. Then ", "Math", 128, 0.3, 0.95, 50], | |
| ["The history of the Roman Empire began ", "General", 200, 0.7, 0.95, 50], | |
| ["Photosynthesis is the process by which ", "General", 150, 0.5, 0.95, 50], | |
| ] | |
| CSS = """ | |
| .container { max-width: 1100px; margin: auto; } | |
| .code-box { | |
| font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace !important; | |
| font-size: 13px !important; | |
| line-height: 1.5 !important; | |
| } | |
| """ | |
| with gr.Blocks(title="CodVa-2 Pretrain Demo") as demo: | |
| gr.HTML(f"<style>{CSS}</style>") | |
| gr.Markdown(""" | |
| # π§ CodVa-2 β Pretrained Code LM | |
| **213M parameters** Β· Differential Attention Β· Trained on code/math/general corpus | |
| This is a **pretrained** model (not instruction-tuned). It continues text in the style of its training domain. | |
| Use the domain selector to control what kind of continuation you get. | |
| """) | |
| with gr.Row(): | |
| # ββ Left: inputs ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| with gr.Column(scale=1): | |
| prompt_box = gr.Textbox( | |
| label="Prompt (raw text, model will continue)", | |
| placeholder="def fibonacci(n):\n ", | |
| lines=10, | |
| elem_classes=["code-box"], | |
| ) | |
| domain_dropdown = gr.Dropdown( | |
| choices=list(DOMAIN_TOKENS.keys()), | |
| value="Code", | |
| label="Domain (prepends domain token)", | |
| info="Code, Math, General, or Reasoning β tells the model what style to use" | |
| ) | |
| with gr.Row(): | |
| max_new_slider = gr.Slider(16, 512, value=256, step=16, | |
| label="Max new tokens") | |
| temp_slider = gr.Slider(0.0, 2.0, value=0.8, step=0.05, | |
| label="Temperature") | |
| with gr.Row(): | |
| topp_slider = gr.Slider(0.1, 1.0, value=0.95, step=0.05, | |
| label="Top-p") | |
| topk_slider = gr.Slider(1, 200, value=50, step=1, | |
| label="Top-k") | |
| with gr.Row(): | |
| gen_btn = gr.Button("βΆ Generate", variant="primary", scale=3) | |
| stop_btn = gr.Button("βΉ Stop", variant="stop", scale=1) | |
| clear_btn = gr.Button("π Clear", scale=1) | |
| # ββ Right: output βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| with gr.Column(scale=1): | |
| output_box = gr.Textbox( | |
| label="Generated continuation (streaming)", | |
| lines=20, | |
| interactive=False, | |
| elem_classes=["code-box"], | |
| ) | |
| stats_box = gr.Textbox( | |
| label="", | |
| lines=1, | |
| interactive=False, | |
| ) | |
| gr.Examples( | |
| examples=EXAMPLES, | |
| inputs=[prompt_box, domain_dropdown, max_new_slider, temp_slider, topp_slider, topk_slider], | |
| label="π Example prompts β click to load", | |
| examples_per_page=10, | |
| ) | |
| gr.Markdown(""" | |
| --- | |
| π‘ **Tips:** | |
| - **Domain matters:** Code domain β code syntax, Math β equations, General β prose | |
| - **Lower temp (0.1-0.3)** = deterministic, predictable (good for code) | |
| - **Higher temp (0.7-1.2)** = creative, varied (good for text) | |
| - This model has seen **~2B tokens** (20% trained). Expect coherent syntax but sometimes wrong logic. | |
| - By 10B tokens it should be much stronger. | |
| """) | |
| # ββ Wire up events ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| gen_event = gen_btn.click( | |
| fn=generate_stream, | |
| inputs=[prompt_box, domain_dropdown, max_new_slider, temp_slider, topp_slider, topk_slider], | |
| outputs=[output_box, stats_box], | |
| ) | |
| prompt_box.submit( | |
| fn=generate_stream, | |
| inputs=[prompt_box, domain_dropdown, max_new_slider, temp_slider, topp_slider, topk_slider], | |
| outputs=[output_box, stats_box], | |
| ) | |
| stop_btn.click(fn=None, cancels=[gen_event]) | |
| clear_btn.click( | |
| fn=lambda: ("", "", ""), | |
| outputs=[prompt_box, output_box, stats_box], | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| show_error=True, | |
| ) |