"""Standalone in-weights runner for `Qwen3.5-9B-Math-GraphCalc` (and `0.8B`). Requires `qwenputer` (`https://github.com/divagr18/qwenputer`) on `PYTHONPATH` or pointed to by `QWENPUTER_ROOT` (defaults to `./qwenputer` or `../qwenputer`): git clone https://github.com/divagr18/qwenputer QWENPUTER_ROOT=./qwenputer python runner.py --ask "Calculate 37429 * 8613 + 194820 and explain your steps." """ from __future__ import annotations import argparse import copy import gc import json import os import re import sys import time import zlib from pathlib import Path import numpy as np import torch import torch.nn as nn import torch.nn.functional as F from safetensors import safe_open from tokenizers import Tokenizer from transformers import AutoConfig, AutoTokenizer, DynamicCache, Qwen3_5ForCausalLM from transformers.models.qwen3_5 import modeling_qwen3_5 as q35_mod MODEL_DIR = Path(__file__).resolve().parent def _locate_qwenputer_rv() -> Path: candidates = [] if os.environ.get("QWENPUTER_ROOT"): candidates.append(Path(os.environ["QWENPUTER_ROOT"])) candidates.extend([ Path.cwd() / "qwenputer", Path.cwd().parent / "qwenputer", MODEL_DIR / "qwenputer", MODEL_DIR.parent / "qwenputer", MODEL_DIR.parent.parent / "qwenputer", MODEL_DIR.parent.parent.parent / "qwenputer", ]) for root in candidates: rv = root.resolve() / "experimental" / "riscv" if (rv / "chipformer").is_dir(): return rv raise RuntimeError( "Could not locate `chipformer` from `qwenputer` (`experimental/riscv/chipformer`). " "Clone https://github.com/divagr18/qwenputer and set QWENPUTER_ROOT=/path/to/qwenputer." ) try: import chipformer # noqa: F401 except ImportError: sys.path.insert(0, str(_locate_qwenputer_rv())) from chipformer.q35 import fast as F_chip # noqa: E402 from chipformer.q35 import ir # noqa: E402 from chipformer.q35.ir import Target # noqa: E402 from chipformer.rv import bridge as BR # noqa: E402 from chipformer.rv import core, elf, hf, ref # noqa: E402 from chipformer.rv import spec as S # noqa: E402 CARBON_SPECIALS = [ "", # 256 "", # 257 "", # 258 "", # 259 "<|im_end|>", # 260 "<|im_start|>", # 261 "user", # 262 "assistant", # 263 "\n\n", # 264 ] GRAPHCALC_TOOL = { "type": "function", "function": { "name": "graphcalc", "description": ( "Exact in-weights graphing & math calculator (62-digit integers/rationals, scientific " "functions, equation solver, and coordinate plotter). Pass an arithmetic expression, " "an equation in x (LHS = RHS), or a function f(x); optionally pass xmin and xmax to " "plot y = f(x) and compute roots, vertex/extrema, definite integral, and value table." ), "parameters": { "type": "object", "properties": { "expression": { "type": "string", "description": "Math expression, equation (LHS = RHS), or function of x (e.g. 'x^2 - 4*x + 3')", }, "xmin": { "type": "number", "description": "Optional domain/plot minimum x (default -5 for plots, -20 for nonlinear solve)", }, "xmax": { "type": "number", "description": "Optional domain/plot maximum x (default 5 for plots, 20 for nonlinear solve)", }, }, "required": ["expression"], }, }, } GRAPHCALC_SYSTEM_PROMPT = ( "You are a clear, encouraging step-by-step math tutor equipped with an embedded graphing " "calculator (`graphcalc`). Always call `graphcalc` first to compute exact arithmetic, roots, " "coordinate tables, or function plots, then explain every step clearly so a student can learn." ) _orig_chunk_gdn = q35_mod.torch_chunk_gated_delta_rule _orig_rec_gdn = q35_mod.torch_recurrent_gated_delta_rule def _fp32_chunk_gdn(*args, **kwargs): with torch.autocast("cuda", enabled=False): return _orig_chunk_gdn(*args, **kwargs) def _fp32_rec_gdn(*args, **kwargs): with torch.autocast("cuda", enabled=False): return _orig_rec_gdn(*args, **kwargs) q35_mod.torch_chunk_gated_delta_rule = _fp32_chunk_gdn q35_mod.torch_recurrent_gated_delta_rule = _fp32_rec_gdn F_chip.exact_matmuls() class CarbonText(BR.Text): """Qwen3.5 bridge vocabulary with native ChatML special tokens (256..264) and space HALT echo.""" def __init__(self, tokenizer_path: str | Path) -> None: p = Path(tokenizer_path) tj = p if p.is_file() else (p / "tokenizer.json") self.tok = Tokenizer.from_file(str(tj)) vocab = self.tok.get_vocab(with_added_tokens=True) base_vocab = {s: i for s, i in vocab.items() if not s.startswith("<|chip_")} self.n = max(base_vocab.values()) + 1 dec = {c: b for b, c in BR.bytes_to_unicode().items()} added = ( {a.content for a in self.tok.get_added_tokens_decoder().values()} if hasattr(self.tok, "get_added_tokens_decoder") else set() ) self.bytes = [b""] * self.n for s, i in base_vocab.items(): if s in added or not all(ch in dec for ch in s): self.bytes[i] = s.encode("utf-8") else: self.bytes[i] = bytes(dec[ch] for ch in s) self.TCO = base_vocab[""] self.TCC = base_vocab[""] u = BR.bytes_to_unicode() special_ids = [] for sp in CARBON_SPECIALS: if sp in base_vocab: special_ids.append(base_vocab[sp]) else: enc = self.tok.encode(sp, add_special_tokens=False).ids assert len(enc) == 1, f"Special {sp!r} is not a single Qwen token: {enc}" special_ids.append(enc[0]) self.printable = [base_vocab[u[b]] for b in range(256)] + special_ids self.pindex = {q: p for p, q in enumerate(self.printable)} self.NL = self.printable[32] def _compact_layer_inplace(layer: nn.Module, is_chip: bool) -> tuple[int, int]: before = after = 0 if is_chip and hasattr(layer, "linear_attn") and isinstance(layer.linear_attn.out_proj, nn.Linear): F_chip.prune_heads(layer.linear_attn) for parent in list(layer.modules()): for name, child in list(parent.named_children()): if isinstance(child, nn.Linear) and child.bias is None: sp = F_chip.SparseLinear(child.weight) before += child.weight.numel() after += sp.weight.numel() setattr(parent, name, sp) return before, after def _load_and_compact_qwen35(path: Path, n_chip: int, dev: str) -> tuple[Qwen3_5ForCausalLM, dict]: layout_file = path / "chip_layout.json" if not layout_file.is_file(): model = Qwen3_5ForCausalLM.from_pretrained( str(path), dtype=torch.bfloat16, attn_implementation="sdpa", ) chip_b = chip_a = qwen_b = qwen_a = 0 for i, layer in enumerate(model.model.layers): b, a = _compact_layer_inplace(layer, is_chip=(i < n_chip)) if i < n_chip: chip_b += b chip_a += a else: qwen_b += b qwen_a += a return model.to(dev).eval(), { "chip_dense": chip_b, "chip_compact": chip_a, "qwen_dense": qwen_b, "qwen_compact": qwen_a, } layout = json.loads(layout_file.read_text(encoding="utf-8")) blob = (path / "chip_indices.bin.zlib").read_bytes() cfg = AutoConfig.from_pretrained(str(path)) cfg._attn_implementation = "sdpa" with torch.device("meta"): model = Qwen3_5ForCausalLM(cfg) tensors_spec: dict[str, dict] = layout["tensors"] by_layer: list[list[str]] = [[] for _ in range(cfg.num_hidden_layers)] for k in tensors_spec: if k.startswith("model.layers."): lid = int(k.split(".", 3)[2]) by_layer[lid].append(k) chip_before = chip_after = qwen_before = qwen_after = head_before = head_after = 0 with safe_open(str(path / "model.safetensors"), framework="pt", device="cpu") as f: def _unpack_one(k: str) -> torch.Tensor: spec = tensors_spec[k] vals = f.get_tensor(k) if spec["mode"] == "dense": return vals shape = tuple(spec["shape"]) raw = zlib.decompress(blob[spec["offset"] : spec["offset"] + spec["length"]]) idx = np.cumsum(np.frombuffer(raw, dtype=np.uint32), dtype=np.int64) out = torch.zeros(int(np.prod(shape)), dtype=vals.dtype) out[torch.from_numpy(idx)] = vals return out.view(shape) for lid in range(cfg.num_hidden_layers): prefix = f"model.layers.{lid}." sub_sd = {k[len(prefix) :]: _unpack_one(k) for k in by_layer[lid]} layer = model.model.layers[lid] layer.load_state_dict(sub_sd, assign=True, strict=True) del sub_sd b, a = _compact_layer_inplace(layer, is_chip=(lid < n_chip)) if lid < n_chip: chip_before += b chip_after += a else: qwen_before += b qwen_after += a layer.to(dev) norm_w = _unpack_one("model.norm.weight").to(dev) model.model.norm.load_state_dict({"weight": norm_w}, assign=True, strict=True) emb_w = _unpack_one("model.embed_tokens.weight").to(dev) model.model.embed_tokens.load_state_dict({"weight": emb_w}, assign=True, strict=True) if "lm_head.weight" in tensors_spec and not getattr(cfg, "tie_word_embeddings", True): head_w_cpu = _unpack_one("lm_head.weight") head_before = head_w_cpu.numel() hc0, hc1 = F_chip._hull(F_chip.nonzero_cols(head_w_cpu)) hblock = nn.Parameter(head_w_cpu[:, hc0:hc1].contiguous().to(dev), requires_grad=False) head_after = hblock.numel() model.lm_head = F_chip.SparseLinear( head_w_cpu, rows=(0, head_w_cpu.shape[0]), cols=(hc0, hc1), block=hblock ) del head_w_cpu else: model.lm_head.load_state_dict({"weight": emb_w}, assign=True, strict=True) model.tie_weights() head_before = head_after = emb_w.numel() model.model.rotary_emb = q35_mod.Qwen3_5TextRotaryEmbedding(config=cfg).to(dev) model.eval() if dev == "cuda": with torch.no_grad(): for _ in range(2): _wc = DynamicCache(config=cfg) model.model( input_ids=torch.zeros((1, 2), dtype=torch.long, device=dev), past_key_values=_wc, use_cache=True, ) model.model( input_ids=torch.zeros((1, 1), dtype=torch.long, device=dev), past_key_values=_wc, use_cache=True, ) del _wc gc.collect() torch.cuda.empty_cache() else: gc.collect() return model, { "chip_dense": chip_before, "chip_compact": chip_after, "qwen_dense": qwen_before, "qwen_compact": qwen_after, "head_dense": head_before, "head_compact": head_after, } class CarbonGraphCalcRunner: """Self-contained runner for `Qwen3.5-Math-GraphCalc` checkpoints.""" def __init__( self, model_dir: str | Path = MODEL_DIR, firmware_path: str | Path | None = None, device: str | None = None, fast: bool = True, executor: bool | str = True, ) -> None: torch.set_grad_enabled(False) F_chip.exact_matmuls() self.path = Path(model_dir) self.meta = json.loads((self.path / "chipformer.json").read_text(encoding="utf-8")) self.dev = device or ("cuda" if torch.cuda.is_available() else "cpu") self.n_chip = int(self.meta["chip_layers"]) self.v0 = int(self.meta["chip_token_offset"]) self.d0 = int(self.meta["chip_dims_offset"]) self.model, self.compact_stats = _load_and_compact_qwen35(self.path, self.n_chip, self.dev) self.lm = self.model.model if isinstance(self.model.lm_head, F_chip.SparseLinear): self.head_c0 = self.model.lm_head.c0 self.head_c1 = self.model.lm_head.c1 self.qwen_head_w = self.model.lm_head.weight[: self.v0] else: self.head_c0 = 0 self.head_c1 = self.model.config.hidden_size self.qwen_head_w = self.model.lm_head.weight[: self.v0] self._p4_buf = torch.zeros((4, 1, 1), dtype=torch.long, device=self.dev) self.tok = AutoTokenizer.from_pretrained(str(self.path)) self.T = CarbonText(self.path / "tokenizer.json") cfg = self.model.config self.c = core.build( Target(cfg.linear_num_key_heads, cfg.linear_num_value_heads, cfg.intermediate_size), self.T, ) self.code_dims = torch.tensor(self.meta["code_dims"], device=self.dev, dtype=torch.long) self.eos = {248046, 248044} self.go_model_id = self.v0 + S.tok("GO") fw = firmware_path or (self.path / self.meta.get("firmware", "graphcalc.elf")) self.firmware_path = Path(fw) self.prog = elf.program(self.firmware_path) core.snapshot(self.c, self.fresh_machine()) self.executor = executor if self.dev == "cuda" else False self.verify = self.executor == "verify" if self.executor: try: self._build_exec() except Exception as exc: if self.verify: raise print(f"[runner] Triton Executor2 unavailable ({type(exc).__name__}: {exc}); using CUDA-graphed HF chip layers.", flush=True) self.executor = False self.verify = False self.fast = bool(fast and self.dev == "cuda" and (not self.executor or self.verify)) if self.fast: self._build_fast() def _build_exec(self) -> None: from chipformer.rv.chat import ExecRow self.keep_ir = torch.tensor(self.c.keep, device=self.dev, dtype=torch.long) cols = self.meta["code_dims"] + [self.meta["tau_dim"], self.meta["mu_dim"]] self.keep_cols = torch.tensor(cols, device=self.dev, dtype=torch.long) self.emb_cache: dict[int, torch.Tensor] = {} self.erow = ExecRow(self) self.erow._capture() def _exec_emb(self, ids: list[int]) -> torch.Tensor: new = sorted({i for i in ids if i not in self.emb_cache}) if new: rows = self.erow.ex.embed( [i - self.v0 if i >= self.v0 else BR.text_token(i) for i in new] ) for i, r in zip(new, rows): self.emb_cache[i] = r return torch.stack([self.emb_cache[i] for i in ids]) @torch.no_grad() def _exec_step_one(self, tok_id: int) -> torch.Tensor: row = self.emb_cache.get(tok_id) if row is None: st = tok_id - self.v0 if tok_id >= self.v0 else BR.text_token(tok_id) row = self.erow.ex.embed([st])[0] self.emb_cache[tok_id] = row self.erow.xbuf[0].copy_(row) self.erow.graph.replay() return self.erow.kbuf @torch.no_grad() def _exec_start_collect(self, ids: list[int]) -> torch.Tensor: if self.erow.graph is None: self.erow._capture() for st in self.erow.heads: st["S"].zero_() st["hist"].zero_() emb = self._exec_emb(ids) keeps = torch.empty((len(ids), len(self.keep_cols)), dtype=torch.float32, device=self.dev) for t in range(len(ids)): self.erow.xbuf.copy_(emb[t : t + 1]) self.erow.graph.replay() keeps[t].copy_(self.erow.kbuf) self.erow.ex.load_init() return keeps def _exec_hc(self, tok_id: int, keep: torch.Tensor) -> torch.Tensor: hc = torch.zeros(self.lm.embed_tokens.weight.shape[1], dtype=torch.bfloat16, device=self.dev) hc[: self.d0] = self.lm.embed_tokens.weight[tok_id, : self.d0] hc[self.keep_cols] = keep.to(torch.bfloat16) return hc def _build_fast(self) -> None: cfg = copy.deepcopy(self.model.config) cfg.num_hidden_layers = self.n_chip + 1 cfg.layer_types = ["linear_attention"] * self.n_chip + ["full_attention"] self.ccfg = cfg dummy = q35_mod.Qwen3_5DecoderLayer(cfg, self.n_chip).to(self.dev, torch.bfloat16) for p in dummy.parameters(): p.data.zero_() with torch.device("meta"): cm = q35_mod.Qwen3_5TextModel(cfg) cm.embed_tokens = self.lm.embed_tokens cm.layers = nn.ModuleList([*self.lm.layers[: self.n_chip], dummy]) cm.norm = nn.Identity() cm.rotary_emb = q35_mod.Qwen3_5TextRotaryEmbedding(config=cfg).to(self.dev) self.cm = cm.eval() self.graph = None def _chip_cache(self): if getattr(self, "ccache", None) is None: self.ccache = DynamicCache(config=self.ccfg) else: for L in range(self.n_chip): lay = self.ccache.layers[L] lay.conv_states[0].zero_() lay.recurrent_states[0].zero_() lay.has_previous_state[0] = False return self.ccache @torch.no_grad() def _chip_body(self): h = self.cm.embed_tokens(self.g_ids) for L in range(self.n_chip): h = self.cm.layers[L]( h, position_embeddings=None, attention_mask=None, position_ids=None, past_key_values=self.ccache, ) self.g_out.copy_(h) @torch.no_grad() def _capture(self): self.g_ids = torch.zeros((1, 1), dtype=torch.long, device=self.dev) self.g_out = torch.zeros( (1, 1, self.model.config.hidden_size), dtype=torch.bfloat16, device=self.dev ) lays = [self.ccache.layers[L] for L in range(self.n_chip)] saved = [(lay.conv_states[0].clone(), lay.recurrent_states[0].clone()) for lay in lays] s = torch.cuda.Stream() s.wait_stream(torch.cuda.current_stream()) with torch.cuda.stream(s): for _ in range(3): self._chip_body() torch.cuda.current_stream().wait_stream(s) self.graph = torch.cuda.CUDAGraph() with torch.cuda.graph(self.graph): self._chip_body() for lay, (cs, rs) in zip(lays, saved): lay.conv_states[0].copy_(cs) lay.recurrent_states[0].copy_(rs) @torch.no_grad() def _chip_step(self, tok_id: int, g: int, cache, compiled: bool = True) -> torch.Tensor: if not compiled or self.graph is None: x = torch.tensor([[tok_id]], device=self.dev) out = self.cm( input_ids=x, past_key_values=cache, use_cache=True, cache_position=torch.tensor([g], device=self.dev), ) return out.last_hidden_state[0, -1].clone() self.g_ids.fill_(tok_id) self.graph.replay() return self.g_out[0, -1].clone() @torch.no_grad() def _qwen_step(self, hc: torch.Tensor, cache, pos: int, full_head: bool = False) -> torch.Tensor: h = hc.view(1, 1, -1) p4 = self._p4_buf p4.fill_(pos) pe = self.lm.rotary_emb(h, p4[1:]) for i in range(self.n_chip, len(self.lm.layers)): h = self.lm.layers[i]( h, position_embeddings=pe, attention_mask=None, position_ids=p4[0], past_key_values=cache, ) nh = self.lm.norm(h)[0, -1] if full_head: return self.model.lm_head(nh) return F.linear(nh[self.head_c0 : self.head_c1], self.qwen_head_w) @torch.no_grad() def _qwen_prefill( self, x_ids: torch.Tensor, keeps: torch.Tensor, full_head: bool = False ) -> tuple[DynamicCache, torch.Tensor]: p_len = int(x_ids.shape[1]) h = torch.zeros( (1, p_len, self.model.config.hidden_size), dtype=torch.bfloat16, device=self.dev ) h[0, :, : self.d0] = self.lm.embed_tokens.weight[x_ids[0], : self.d0] h[0, :, self.keep_cols] = keeps.to(torch.bfloat16) cache = DynamicCache(config=self.model.config) pos_vec = torch.arange(0, p_len, device=self.dev, dtype=torch.long).unsqueeze(0) p4 = pos_vec.unsqueeze(0).expand(4, -1, -1) pe = self.lm.rotary_emb(h, p4[1:]) for i in range(self.n_chip, len(self.lm.layers)): h = self.lm.layers[i]( h, position_embeddings=pe, attention_mask=None, position_ids=p4[0], past_key_values=cache, ) nh = self.lm.norm(h)[0, -1] logits = ( self.model.lm_head(nh) if full_head else F.linear(nh[self.head_c0 : self.head_c1], self.qwen_head_w) ) return cache, logits @torch.no_grad() def _qwen_chunk( self, hcs: list[torch.Tensor], cache, pos0: int, full_head: bool = False ) -> torch.Tensor: if len(hcs) == 1: return self._qwen_step(hcs[0], cache, pos0, full_head=full_head) k_len = len(hcs) h = torch.stack(hcs, dim=0).unsqueeze(0) pos_vec = torch.arange(pos0, pos0 + k_len, device=self.dev, dtype=torch.long).unsqueeze(0) p4 = pos_vec.unsqueeze(0).expand(4, -1, -1) pe = self.lm.rotary_emb(h, p4[1:]) attn_mask = torch.zeros((1, 1, k_len, pos0 + k_len), dtype=h.dtype, device=self.dev) future = torch.triu(torch.ones((k_len, k_len), dtype=torch.bool, device=self.dev), diagonal=1) attn_mask[0, 0, :, pos0:][future] = torch.finfo(h.dtype).min for i in range(self.n_chip, len(self.lm.layers)): lmask = attn_mask if self.model.config.layer_types[i] == "full_attention" else None h = self.lm.layers[i]( h, position_embeddings=pe, attention_mask=lmask, position_ids=p4[0], past_key_values=cache, ) nh = self.lm.norm(h)[0, -1] if full_head: return self.model.lm_head(nh) return F.linear(nh[self.head_c0 : self.head_c1], self.qwen_head_w) @torch.no_grad() def _layers_slow(self, tok_id: int, cache, pos: int | None): h = self.lm.embed_tokens(torch.tensor([[tok_id]], device=self.dev)) pe = tp = None if pos is not None: p4 = torch.full((4, 1, 1), pos, device=self.dev, dtype=torch.long) tp = p4[0] pe = self.lm.rotary_emb(h, p4[1:]) hc = None n = self.n_chip if pos is None else len(self.lm.layers) for i in range(n): h = self.lm.layers[i]( h, position_embeddings=pe, attention_mask=None, position_ids=tp, past_key_values=cache, ) if i == self.n_chip - 1: hc = h logits = None if pos is None else self.model.lm_head(self.lm.norm(h))[0, -1] return hc[0, -1], logits def _decode_code_list(self, vals: list[float]) -> int | None: if not any(v != 0.0 for v in vals): return None nf = core.NFAM fid = 0 for i in range(nf): if vals[i] > 0.0: fid |= 1 << i p = 0 for i in range(len(vals) - nf): if vals[nf + i] > 0.0: p |= 1 << i t = core.decode_code(fid, p, self.T) if t < 0: raise RuntimeError(f"Invalid circuit token prediction (family={fid}, payload={p})") return t - S.TEXT_TOKEN if S.is_text(t) else self.v0 + t def code_token(self, code: torch.Tensor) -> int | None: return self._decode_code_list(code.tolist()) def circuit_token(self, hc: torch.Tensor) -> int | None: return self.code_token(hc[self.code_dims]) def fresh_machine(self) -> ref.Machine: m = ref.Machine.from_program(self.prog) BR.park(m) return m def prompt_ids( self, user_prompt: str | list[dict], system_prompt: str | None = GRAPHCALC_SYSTEM_PROMPT, use_tools: bool = True, ) -> list[int]: if isinstance(user_prompt, str): msgs = [] if system_prompt: msgs.append({"role": "system", "content": system_prompt}) msgs.append({"role": "user", "content": user_prompt}) else: msgs = list(user_prompt) tools = [GRAPHCALC_TOOL] if use_tools else None out = self.tok.apply_chat_template( msgs, tools=tools, add_generation_prompt=True, enable_thinking=False, tokenize=True, ) if not isinstance(out, list): out = out["input_ids"] return [int(x) for x in out] @torch.no_grad() def generate( self, ids: list[int], max_new_text: int = 512, max_chip_tokens: int = 500_000, max_calls: int = 1, check_head: bool = False, check_lock: bool = False, ) -> dict: m = self.fresh_machine() lock = None if check_lock: lock = BR.Session(self.T, self.fresh_machine()) lock.history(ids) x = torch.tensor([ids], device=self.dev, dtype=torch.long) core.snapshot(self.c, m) n_code = len(self.code_dims) if self.executor and not self.verify: keeps = self._exec_start_collect(ids) cache, logits = self._qwen_prefill(x, keeps, full_head=check_head) else: lm_out = self.lm(input_ids=x, use_cache=True) cache = lm_out.past_key_values if self.executor: self.erow.start(ids) if self.fast: ccache = self._chip_cache() h = self.cm.embed_tokens(x) for L in range(self.n_chip): h = self.cm.layers[L]( h, position_embeddings=None, attention_mask=None, position_ids=None, past_key_values=ccache, ) hf.inject(self.c, ccache) if self.graph is None: self._capture() g = len(ids) elif not self.executor: hf.inject(self.c, cache) logits = self.model.lm_head(lm_out.last_hidden_state[0, -1]) pos = len(ids) gen: list[int] = [] n_qwen_text = n_echo_text = n_chip_tok = n_calls = head_mismatch = n_verify_bad = 0 nxt = int(torch.argmax(logits[: self.v0])) prev_owned = False in_tool_call = False pending_hcs: list[torch.Tensor] = [] pending_pos0: int | None = None t0 = time.time() expect: list[int] = [] lock_error = None while n_chip_tok < max_chip_tokens: if n_qwen_text >= max_new_text and (not prev_owned) and (not in_tool_call): break gen.append(nxt) if nxt == self.T.TCO and not prev_owned: in_tool_call = True elif nxt == self.T.TCC: in_tool_call = False if nxt == self.go_model_id: n_calls += 1 if lock is not None: st = nxt - self.v0 if nxt >= self.v0 else BR.text_token(nxt) if expect: e = expect.pop(0) if st != e: lock_error = {"at": len(gen) - 1, "got": st, "want": e} break elif st < S.VOCAB: lock_error = {"at": len(gen) - 1, "got": S.name(st), "want": "text"} break else: k = len(lock.toks) try: lock.qwen([nxt]) except RuntimeError as exc: lock_error = {"at": len(gen) - 1, "got": str(exc), "want": "halt"} break expect = list(lock.toks[k + 1 :]) if nxt in self.eos and not prev_owned: break chip_in = nxt >= self.v0 hc = keep = None if self.executor: keep = self._exec_step_one(nxt) if not chip_in: hc = self._exec_hc(nxt, keep) if self.fast and (self.verify or not self.executor): hf_hc = self._chip_step(nxt, g, ccache) g += 1 if self.verify: same = ( bool((hf_hc[self.keep_cols] == keep.to(torch.bfloat16)).all()) if chip_in else bool((hf_hc == hc).all()) ) if not same: n_verify_bad += 1 hc = hf_hc elif not self.executor: hc, logits = self._layers_slow(nxt, cache, None if chip_in else pos) if chip_in: n_chip_tok += 1 nxt = ( self._decode_code_list(keep[:n_code].tolist()) if hc is None else self.circuit_token(hc) ) prev_owned = True if nxt is None: raise RuntimeError("Circuit relinquished ownership mid-chip-token") else: if prev_owned: n_echo_text += 1 else: n_qwen_text += 1 ct = ( self._decode_code_list(keep[:n_code].tolist()) if (keep is not None and not self.verify) else self.circuit_token(hc) ) if ct is not None and (self.fast or self.executor) and not check_head: if pending_pos0 is None: pending_pos0 = pos pending_hcs.append(hc) pos += 1 nxt = ct prev_owned = True else: if self.fast or self.executor: if pending_hcs: pending_hcs.append(hc) logits = self._qwen_chunk( pending_hcs, cache, pending_pos0, full_head=check_head ) pending_hcs.clear() pending_pos0 = None else: logits = self._qwen_step(hc, cache, pos, full_head=check_head) pos += 1 if ct is not None: if check_head and int(torch.argmax(logits)) != ct: head_mismatch += 1 nxt = ct prev_owned = True else: q_logits = logits[: self.v0] if n_calls >= max_calls or n_qwen_text >= max(16, max_new_text - 48): q_logits = q_logits.clone() q_logits[self.T.TCO] = float("-inf") nxt = int(torch.argmax(q_logits)) prev_owned = False dt = time.time() - t0 parsed = self.parse_turn(gen) return { "tokens": gen, "text_tokens": n_qwen_text, "echo_text_tokens": n_echo_text, "chip_tokens": n_chip_tok, "tool_calls_executed": n_calls, "seconds": round(dt, 3), "head_mismatch": head_mismatch, "lock_error": lock_error, "verify_mismatch": n_verify_bad if self.verify else None, **parsed, } def text_of(self, ids: list[int]) -> str: return self.tok.decode([i for i in ids if i < self.v0], skip_special_tokens=False) def parse_turn(self, gen_ids: list[int]) -> dict: raw = self.text_of(gen_ids) calls = re.findall(r"\s*(.*?)\s*", raw, flags=re.DOTALL) responses = re.findall(r"\n?(.*?)\n?", raw, flags=re.DOTALL) cleaned = re.sub( r".*?\s*(?:<\|im_end\|>\s*<\|im_start\|>assistant\s*\s*\s*)?", "\n\n", raw, flags=re.DOTALL, ) cleaned = re.sub(r".*$", "", cleaned, flags=re.DOTALL) cleaned = re.sub(r"", "", cleaned) for stop_s in ("<|im_end|>", "<|endoftext|>", "<|im_start|>"): if stop_s in cleaned: cleaned = cleaned.split(stop_s, 1)[0] cleaned = re.sub(r"\n{3,}", "\n\n", cleaned).strip() return { "raw_text": raw, "tool_calls": calls, "tool_responses": responses, "final_explanation": cleaned, } def main() -> None: ap = argparse.ArgumentParser(description="Run Qwen3.5-Math-GraphCalc in-weights") ap.add_argument( "--ask", default="Graph y = x^3 - 3*x from x = -2 to 2, identify its roots and turning points, and state the local maximum y-value.", help="Math or graphing question to solve", ) ap.add_argument("--pure-hf", action="store_true", help="Run un-fused HF Qwen3_5DecoderLayer weights (executor=False)") ap.add_argument("--max-new-text", type=int, default=512) args = ap.parse_args() runner = CarbonGraphCalcRunner(MODEL_DIR, fast=True, executor=not args.pure_hf) res = runner.generate(runner.prompt_ids(args.ask), max_new_text=args.max_new_text, check_lock=True) if res["tool_responses"]: print("=== IN-WEIGHTS RV32 ===") print(res["tool_responses"][0]) print() print("=== STEP-BY-STEP TUTOR EXPLANATION ===") print(res["final_explanation"]) print(f"\n[chip_tokens={res['chip_tokens']} | lock_error={res['lock_error']} | {res['seconds']}s]") if __name__ == "__main__": main()