Instructions to use cds-jb/qwen3-8b-parallel-cot with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use cds-jb/qwen3-8b-parallel-cot with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-8B") model = PeftModel.from_pretrained(base_model, "cds-jb/qwen3-8b-parallel-cot") - Notebooks
- Google Colab
- Kaggle
| """Single-cell causal patch for the single-token organism. | |
| Overwrite ONE cell value c_i(t) inside the soft token z_t (force cell i = digit d), then CONTINUE | |
| free-running so the change propagates through the learned CA rule, and check the final answer equals | |
| what the *true* CA produces for the altered row. This is a surgical test (one cell, one step) that the | |
| latent at (t,i) causally carries c_i(t) AND that the downstream computation uses it. | |
| Patch (per the card): generate free-running to step t; read z_t = softmax(head(h_t)) in R^{K x 10}; | |
| set z_t[i] <- one-hot(d) (other cells untouched); re-embed via the codebook (fed = sum_k z_t[k].C[k]) | |
| as the input to z_{t+1}; continue free-running; read the answer from the head at z_T, cell q. | |
| Expected = CA-evolve(c_t with cell i := d) for the remaining T-1-t steps, read at cell q. | |
| python -m latent_threads.eval_single_cellpatch --ckpt .../sg1/diffuse/best --n 400 | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import json | |
| import os | |
| import random | |
| import dotenv | |
| dotenv.load_dotenv() | |
| _USER = os.environ.get("USER", "jbauer") | |
| os.environ.setdefault("HF_HOME", f"/workspace-vast/{_USER}/hf") | |
| import matplotlib | |
| matplotlib.use("Agg") | |
| import matplotlib.pyplot as plt | |
| import numpy as np | |
| import torch | |
| import torch.nn.functional as F | |
| from tqdm.auto import tqdm | |
| from latent_threads import tasks as LT | |
| from latent_threads.single import build_single_batch, build_single_mask | |
| from latent_threads.eval_single_report import load, RES | |
| def patched_answer(model, head, codebook, q_emb, tok, task, batch, im, device, t_p, i_p, d_p): | |
| """Free-run; at step t_p[j] overwrite cell i_p[j] of the soft token with one-hot(d_p[j]); continue. | |
| Returns the head's predicted digit for each example's queried cell at z_T.""" | |
| K, m = task.K, task.m | |
| input_ids, roles, zs_, ls_, lens_ = build_single_batch(tok, task, batch, im, device, with_answer=False) | |
| B, Lmax = input_ids.shape | |
| attn = build_single_mask(roles, zs_, m) | |
| pos = torch.arange(Lmax, device=device)[None].expand(B, Lmax) | |
| E = model.get_input_embeddings()(input_ids) | |
| bidx = torch.arange(B, device=device); zs = torch.tensor(zs_, device=device) | |
| E = E.clone(); E[bidx, zs] = q_emb | |
| out = None | |
| for t in range(m): | |
| out = model(inputs_embeds=E, attention_mask=attn, position_ids=pos, output_hidden_states=True) | |
| if t == m - 1: | |
| break | |
| z = torch.softmax(head(out.hidden_states[-1][bidx, zs + t]).view(B, K, 10).float(), -1) # [B,K,10] | |
| for j in range(B): # patch examples whose t_p == t | |
| if t_p[j] == t: | |
| z[j, i_p[j]] = F.one_hot(torch.tensor(d_p[j], device=device), 10).float() | |
| fed = torch.einsum("bkv,kvd->bd", z, codebook.float()) | |
| E = E.clone(); E[bidx, zs + t + 1] = fed.to(E.dtype) | |
| final = head(out.hidden_states[-1][bidx, zs + m - 1]).view(B, K, 10) # head at z_T | |
| return [final[j, batch[j].q].argmax().item() for j in range(B)] | |
| def expected_answer(task, p, t, i, d): | |
| row = list(p.rows[t]); row[i] = d | |
| for _ in range(task.m - 1 - t): | |
| row = task._step(row) | |
| return row[p.q] | |
| def run(ckpt, model_name, n, device): | |
| model, head, codebook, q_emb, tok, did, K, cfg, tag = load(ckpt, model_name, device) | |
| im = tok.convert_tokens_to_ids("<|im_end|>") | |
| m = cfg["task_kwargs"]["m"]; task = LT.make_task(cfg["task"], k=K, m=m) | |
| rng = random.Random(7) | |
| probs = [task.sample(rng) for _ in range(n)] | |
| # per-example patch: a random step t in 0..m-2, cell i, target digit d != current value | |
| t_p, i_p, d_p = [], [], [] | |
| for p in probs: | |
| t = rng.randrange(0, m - 1); i = rng.randrange(K) | |
| cur = p.rows[t][i]; d = rng.choice([x for x in range(10) if x != cur]) | |
| t_p.append(t); i_p.append(i); d_p.append(d) | |
| exp = np.array([expected_answer(task, probs[j], t_p[j], i_p[j], d_p[j]) for j in range(n)]) | |
| orig = np.array([task.answer(probs[j]) for j in range(n)]) | |
| preds = [] | |
| bs = 16 | |
| for s in tqdm(range(0, n, bs), desc=f"{tag} cell-patch"): | |
| b = probs[s:s + bs] | |
| preds += patched_answer(model, head, codebook, q_emb, tok, task, b, im, device, | |
| t_p[s:s + bs], i_p[s:s + bs], d_p[s:s + bs]) | |
| preds = np.array(preds) | |
| follows_ca = float((preds == exp).mean()) | |
| changed = exp != orig # patch actually moves the answer | |
| follows_on_changed = float((preds[changed] == exp[changed]).mean()) | |
| follows_orig_on_changed = float((preds[changed] == orig[changed]).mean()) # ignores the patch? | |
| dist = np.array([m - 1 - t for t in t_p]) # propagation distance | |
| by_dist = {int(dd): float((preds[dist == dd] == exp[dist == dd]).mean()) for dd in sorted(set(dist.tolist()))} | |
| print("=" * 70 + f"\nSINGLE-CELL PATCH {tag} K={K} m={m} n={n}\n" + "=" * 70, flush=True) | |
| print(f" follows CA-propagated answer (all patches): {follows_ca:.3f}", flush=True) | |
| print(f" on patches that CHANGE the answer (n={int(changed.sum())}): follows patched CA={follows_on_changed:.3f} " | |
| f"follows ORIGINAL (ignores patch)={follows_orig_on_changed:.3f}", flush=True) | |
| print(f" by propagation distance (steps from patch to read): { {k: round(v,3) for k,v in by_dist.items()} }", flush=True) | |
| res = dict(tag=tag, K=K, m=m, n=n, follows_ca=follows_ca, n_changed=int(changed.sum()), | |
| follows_on_changed=follows_on_changed, follows_orig_on_changed=follows_orig_on_changed, | |
| by_distance=by_dist) | |
| json.dump(res, open(f"{RES}/single_cellpatch_{tag}.json", "w"), indent=2) | |
| fig, ax = plt.subplots(figsize=(6, 4)) | |
| ds = sorted(by_dist); ax.plot(ds, [by_dist[d] for d in ds], "o-", color="#2ca02c", label="follows patched CA") | |
| ax.axhline(1 / 10, ls="--", color="grey", label="chance 0.10") | |
| ax.set_xlabel("propagation distance (CA steps from patched cell to read-out)") | |
| ax.set_ylabel("P(answer = CA-propagated value)"); ax.set_ylim(0, 1.02); ax.legend() | |
| ax.set_title(f"{tag}: single-cell patch c_i(t):=d propagates correctly") | |
| png = f"{RES}/single_cellpatch_{tag}.png"; fig.savefig(png, bbox_inches="tight", dpi=130) | |
| print(png, flush=True) | |
| return res | |
| def run_sweep(ckpt, model_name, n_probs, device): | |
| """Systematic spot-check: patch EVERY (step t, cell i) site on a small set of problems, force a | |
| changed value, and print the full per-patch detail (orig answer / CA-expected / model) for review.""" | |
| model, head, codebook, q_emb, tok, did, K, cfg, tag = load(ckpt, model_name, device) | |
| im = tok.convert_tokens_to_ids("<|im_end|>") | |
| m = cfg["task_kwargs"]["m"]; task = LT.make_task(cfg["task"], k=K, m=m) | |
| rng = random.Random(11) | |
| probs = [task.sample(rng) for _ in range(n_probs)] | |
| sites = [(t, i) for t in range(m - 1) for i in range(K)] # all positions x all cells | |
| batch, T, I, D, meta = [], [], [], [], [] | |
| for pi, p in enumerate(probs): | |
| for (t, i) in sites: | |
| cur = p.rows[t][i]; d = rng.choice([x for x in range(10) if x != cur]) | |
| batch.append(p); T.append(t); I.append(i); D.append(d) | |
| meta.append((pi, t, i, cur, d, p.q, task.answer(p), expected_answer(task, p, t, i, d))) | |
| preds = [] | |
| for s in range(0, len(batch), 16): | |
| preds += patched_answer(model, head, codebook, q_emb, tok, task, batch[s:s + 16], im, device, | |
| T[s:s + 16], I[s:s + 16], D[s:s + 16]) | |
| print("=" * 92 + f"\nSINGLE-CELL PATCH SWEEP {tag} K={K} m={m} {len(sites)} sites x {n_probs} problems = {len(meta)} patches\n" + "=" * 92, flush=True) | |
| print(f"{'prob':>4} {'site':>8} {'c_i(t)->d':>10} {'q':>4} {'orig':>5} {'CA_exp':>7} {'model':>6} match", flush=True) | |
| persite, ok_all = {}, [] | |
| for k, (pi, t, i, cur, d, q, orig, exp) in enumerate(meta): | |
| mod = preds[k]; ok = (mod == exp); ok_all.append(ok); persite.setdefault((t, i), []).append(ok) | |
| print(f"{pi:>4} {f's{t+1}.c{i+1}':>8} {f'{cur}->{d}':>10} {f'c{q+1}':>4} {orig:>5} {exp:>7} {mod:>6} {'OK' if ok else 'XX'}", flush=True) | |
| print("-" * 92 + "\nper-site follows-CA (over the problems):", flush=True) | |
| for (t, i) in sites: | |
| v = persite[(t, i)]; print(f" s{t+1}.c{i+1}: {sum(v)}/{len(v)} = {sum(v)/len(v):.2f}", flush=True) | |
| print(f"OVERALL follows CA-propagated: {sum(ok_all)}/{len(ok_all)} = {sum(ok_all)/len(ok_all):.3f}", flush=True) | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--ckpt", required=True); ap.add_argument("--model", default="Qwen/Qwen3-8B") | |
| ap.add_argument("--n", type=int, default=400) | |
| ap.add_argument("--sweep", action="store_true"); ap.add_argument("--probs", type=int, default=7) | |
| args = ap.parse_args() | |
| if args.sweep: | |
| run_sweep(args.ckpt, args.model, args.probs, "cuda") | |
| else: | |
| run(args.ckpt, args.model, args.n, "cuda") | |
| if __name__ == "__main__": | |
| main() | |