"""Long-range NEEDLE retrieval for code: BF16 vs INT4-KIVI on Laguna-XS.2. The meaningful long-context test for a KV-cache quantizer: can the model attend back to a UNIQUE definition placed FAR earlier in the context after the cache has been quantized to INT4? We build a long synthetic Python "codebase" of filler functions padding to a target token length, embed a single non-guessable needle at a controlled DEPTH near the start, and at the very end ask the model to recall it. Grading is by EXACT value / executed equality -- the answer is only right if the model actually attended to the early definition (it cannot be guessed). Two needle kinds (both exact-graded): * "const" : ``MAGIC_SEED_ = <7-digit prime-ish int>`` -> ask the value. * "transform" : ``def secret_transform_(x): return x * A + B`` -> ask the model to compute ``secret_transform_(N)``; correct answer is the exact integer A*N+B. For each (context_length, depth) cell we run several trials (distinct needle values / filler) and report retrieval accuracy for BF16 and INT4-KIVI plus their agreement. Batch-1 greedy only (the regime Int4KiviCache supports). Usage ----- .venv/bin/python scripts/needle_code_bench.py --lengths 8000,16000 \ --depths 0.05 --trials 3 --max-new 24 """ from __future__ import annotations import argparse import random import re import sys import time import torch from transformers import AutoModelForCausalLM, AutoTokenizer, DynamicCache ROOT = "/home/alex/poolside-hackathon-kv-quant" sys.path.insert(0, ROOT) from int4_kivi.hf_cache import Int4KiviCache MODEL = "poolside/Laguna-XS.2" # --------------------------------------------------------------------------- # # Synthetic codebase / filler # --------------------------------------------------------------------------- # _VERBS = ["compute", "process", "build", "merge", "filter", "scan", "encode", "decode", "reduce", "expand", "rotate", "shuffle", "balance", "score", "align", "cluster", "sample", "weight", "smooth", "sharpen"] _NOUNS = ["matrix", "vector", "buffer", "token", "graph", "tensor", "window", "stream", "record", "payload", "segment", "lattice", "kernel", "gradient", "index", "shard", "bucket", "frame", "channel", "node"] def _filler_fn(rng: random.Random, i: int) -> str: """A plausible, in-distribution Python helper that carries no needle info.""" v = rng.choice(_VERBS) n = rng.choice(_NOUNS) a = rng.randint(2, 9) b = rng.randint(1, 20) return ( f"def {v}_{n}_{i}(items):\n" f' """{v.capitalize()} the {n} {i} with a small affine pass."""\n' f" out = []\n" f" for k, it in enumerate(items):\n" f" out.append(it * {a} + {b} + k)\n" f" return out\n" ) def _make_needle(rng: random.Random, kind: str): """Return (needle_source, question_text, expected_answer_str, meta).""" nid = rng.randint(100000, 999999) if kind == "const": # 8-digit non-guessable value. val = rng.randint(10_000_000, 99_999_999) src = ( f"# Important runtime configuration constant.\n" f"MAGIC_SEED_{nid} = {val}\n" ) q = ( f"In the reference code above there is a constant named " f"MAGIC_SEED_{nid}. Reply with ONLY its exact integer value and " f"nothing else." ) return src, q, str(val), {"nid": nid, "val": val} elif kind == "transform": # Use a unique multiplier constant so recall is non-guessable. We ask # the model to recall the *added* offset literal, which is a pure # attend-back retrieval (no arithmetic), keeping this a clean needle # test rather than a reasoning test. a = rng.choice([3, 7, 11, 13]) b = rng.randint(1_000_000, 9_999_999) # 7-digit, non-guessable src = ( f"# Domain-specific transform used by the pipeline.\n" f"def secret_transform_{nid}(x):\n" f" return x * {a} + {b}\n" ) q = ( f"In the reference code above there is a function named " f"secret_transform_{nid} whose body is `return x * {a} + OFFSET`. " f"Reply with ONLY the exact integer OFFSET value and nothing else." ) return src, q, str(b), {"nid": nid, "a": a, "b": b} else: raise ValueError(kind) # --------------------------------------------------------------------------- # # Build a context of ~target_tokens with the needle at a given depth fraction # --------------------------------------------------------------------------- # def build_context(tok, target_tokens: int, depth: float, kind: str, rng: random.Random): """Return (reference_code_text, question, expected_str, meta, n_pre_tokens). ``depth`` is the fraction of the *filler* placed BEFORE the needle (0.0 = needle right at the start, 0.5 = needle in the middle). We grow filler functions until the whole reference block reaches target_tokens. """ needle_src, question, expected, meta = _make_needle(rng, kind) # Generate a large pool of filler, then split around the needle by depth. fillers: list[str] = [] i = 0 # Build until the joined text (incl. needle) is at/above target. # Estimate ~ a few tokens per char; just append and recount periodically. pre, post = [], [] # First, mass-produce filler text and measure. block_parts: list[str] = [] while True: fn = _filler_fn(rng, i) block_parts.append(fn) i += 1 if i % 40 == 0: joined = "\n".join(block_parts) ntok = tok(joined, return_tensors="pt").input_ids.shape[1] if ntok >= target_tokens: break if i > 200000: # safety break # Now place needle at the requested depth among the filler functions. n_fn = len(block_parts) split = int(n_fn * depth) parts = block_parts[:split] + [needle_src] + block_parts[split:] reference = "\n".join(parts) # Trim to roughly target_tokens (keep the needle!). We trim from the END so # the needle (near the front for small depth) is preserved. ids = tok(reference, return_tensors="pt").input_ids[0] if ids.shape[0] > target_tokens * 1.15: ids = ids[: int(target_tokens * 1.15)] reference = tok.decode(ids, skip_special_tokens=True) # Re-confirm needle survived; if trimmed off (shouldn't for depth<0.7), # re-insert near the front. if meta_token(meta, kind) not in reference: reference = needle_src + "\n" + reference n_pre = tok(reference, return_tensors="pt").input_ids.shape[1] return reference, question, expected, meta, n_pre def meta_token(meta, kind: str) -> str: if kind == "const": return f"MAGIC_SEED_{meta['nid']}" return f"secret_transform_{meta['nid']}" # --------------------------------------------------------------------------- # # Prompt + generation # --------------------------------------------------------------------------- # def build_input_ids(tok, reference: str, question: str, device): sys_msg = ( "You are a careful code assistant. You will be shown a long Python " "reference codebase, then asked one question about a specific symbol " "defined in it. Answer using ONLY the information in the reference." ) user_msg = ( "Reference codebase:\n\n" f"```python\n{reference}\n```\n\n" f"{question}" ) msgs = [ {"role": "system", "content": sys_msg}, {"role": "user", "content": user_msg}, ] return tok.apply_chat_template( msgs, add_generation_prompt=True, return_tensors="pt", return_dict=False, ).to(device) @torch.no_grad() def generate(model, input_ids, max_new, mode, config): cache = Int4KiviCache(config=config) if mode == "int4" else DynamicCache() out = model.generate( input_ids, max_new_tokens=max_new, past_key_values=cache, use_cache=True, do_sample=False, num_beams=1, ) return out[0, input_ids.shape[1]:].tolist(), cache def grade(response: str, expected: str) -> bool: """Exact-value match: the expected integer must appear as a standalone number in the response (and be the first number, to avoid echoing the function's coefficients).""" nums = re.findall(r"-?\d+", response.replace(",", "")) if not nums: return False # Correct if the expected value is the first integer emitted, OR appears # and no other distinct integer precedes it. We accept "first integer". return nums[0] == expected # --------------------------------------------------------------------------- # # Main sweep # --------------------------------------------------------------------------- # def main(): ap = argparse.ArgumentParser() ap.add_argument("--lengths", type=str, default="8000,16000,32000") ap.add_argument("--depths", type=str, default="0.05") ap.add_argument("--trials", type=int, default=3) ap.add_argument("--kinds", type=str, default="const,transform") ap.add_argument("--max-new", type=int, default=24) ap.add_argument("--seed", type=int, default=1234) args = ap.parse_args() lengths = [int(x) for x in args.lengths.split(",") if x] depths = [float(x) for x in args.depths.split(",") if x] kinds = [k for k in args.kinds.split(",") if k] print(f"[load] {MODEL} ...", flush=True) tok = AutoTokenizer.from_pretrained(MODEL) model = AutoModelForCausalLM.from_pretrained( MODEL, dtype=torch.bfloat16, device_map="auto" ) model.eval() device = next(model.parameters()).device print(f"\n{'':#<92}") print(" NEEDLE-IN-CODEBASE RETRIEVAL (exact-value graded, greedy, batch-1)") print(f"{'':#<92}") header = (f" {'len':>7} {'depth':>6} {'kind':>10} {'ctx':>8} " f"{'BF16':>10} {'INT4':>10} {'agree':>7} {'ratio':>6} {'t/gen':>6}") print(header) print(f"{'':-<92}") rows = [] example = None # (length, kind, question, expected, bf16_resp, int4_resp) for length in lengths: for depth in depths: for kind in kinds: rng = random.Random(args.seed + length + int(depth * 1000) + hash(kind) % 1000) bf_ok = iq_ok = agree = 0 ctxs, ratios, times = [], [], [] for t in range(args.trials): reference, question, expected, meta, n_pre = build_context( tok, length, depth, kind, rng ) input_ids = build_input_ids(tok, reference, question, device) ctx = int(input_ids.shape[1]) ctxs.append(ctx) res = {} for mode in ("bf16", "int4"): t0 = time.time() ids, cache = generate(model, input_ids, args.max_new, mode, model.config) dt = time.time() - t0 resp = tok.decode(ids, skip_special_tokens=True) ok = grade(resp, expected) res[mode] = (ok, resp, dt) if mode == "int4": try: ratios.append(cache.compression_ratio_vs_bf16()) except Exception: pass times.append(dt) bf_ok += res["bf16"][0] iq_ok += res["int4"][0] agree += (res["bf16"][0] == res["int4"][0]) if example is None and res["int4"][0] and res["bf16"][0]: example = (ctx, kind, question, expected, res["bf16"][1].strip()[:120], res["int4"][1].strip()[:120]) n = args.trials ctx_m = sum(ctxs) // len(ctxs) ratio_m = (sum(ratios) / len(ratios)) if ratios else 0.0 t_m = (sum(times) / len(times)) if times else 0.0 print(f" {length:>7} {depth:>6.2f} {kind:>10} {ctx_m:>8} " f"{bf_ok:>4}/{n:<5} {iq_ok:>4}/{n:<5} {agree:>3}/{n:<3} " f"{ratio_m:>5.2f}x {t_m:>5.1f}s", flush=True) rows.append((length, depth, kind, ctx_m, bf_ok, iq_ok, agree, n, ratio_m)) print(f"{'':-<92}") # Aggregate by length. print("\n RETRIEVAL ACCURACY BY CONTEXT LENGTH (summed over depths/kinds):") by_len: dict[int, list[int]] = {} for (length, depth, kind, ctx, bf, iq, ag, n, ratio) in rows: acc = by_len.setdefault(length, [0, 0, 0, 0]) acc[0] += bf; acc[1] += iq; acc[2] += ag; acc[3] += n print(f" {'target_len':>11} {'BF16':>14} {'INT4-KIVI':>14} {'agreement':>12}") for length in sorted(by_len): bf, iq, ag, n = by_len[length] print(f" {length:>11} {bf:>6}/{n:<4} ({100*bf/n:>3.0f}%) " f"{iq:>6}/{n:<4} ({100*iq/n:>3.0f}%) {ag:>4}/{n:<4} " f"({100*ag/n:>3.0f}%)") if example: ctx, kind, q, exp, bf_r, iq_r = example print(f"\n{'':-<92}") print(f" REPRESENTATIVE NEEDLE (ctx={ctx} tok, kind={kind})") print(f" Q: {q}") print(f" expected: {exp}") print(f" BF16 ->: {bf_r!r}") print(f" INT4 ->: {iq_r!r}") print(f"{'':-<92}") print("\n[done]", flush=True) if __name__ == "__main__": main()