| """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_<id> = <7-digit prime-ish int>`` -> ask the value. |
| * "transform" : ``def secret_transform_<id>(x): return x * A + B`` -> ask the |
| model to compute ``secret_transform_<id>(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" |
|
|
|
|
| |
| |
| |
| _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": |
| |
| 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": |
| |
| |
| |
| |
| a = rng.choice([3, 7, 11, 13]) |
| b = rng.randint(1_000_000, 9_999_999) |
| 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) |
|
|
|
|
| |
| |
| |
| 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) |
|
|
| |
| fillers: list[str] = [] |
| i = 0 |
| |
| |
| pre, post = [], [] |
| |
| 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: |
| break |
|
|
| |
| n_fn = len(block_parts) |
| split = int(n_fn * depth) |
| parts = block_parts[:split] + [needle_src] + block_parts[split:] |
| reference = "\n".join(parts) |
|
|
| |
| |
| 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) |
| |
| |
| 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']}" |
|
|
|
|
| |
| |
| |
| 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 |
| |
| |
| return nums[0] == expected |
|
|
|
|
| |
| |
| |
| 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 |
|
|
| 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}") |
| |
| 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() |
|
|