Files
ds4/misc/qwen-drift-2026-10-03/run-greedy-ab.py
T
Giorgio Oppo 575369b19d Research: isolate Qwen prefill arithmetic and token drift
Archive the investigation of PR #1056 comment 5963229415 comparing main
0aaea5a with 02313128 on M4 Max/Q2 resident. Trace the device-independent
prefill policy introduced by 2d6a207b: small F16/Q8 prompt batches change
operand precision, while GDN alpha/beta F32 projections stop using split-K.
Distinguish this policy from the numerically neutral M2-M4 tuning gate,
89986c3c attention partitions and the secondary HC arithmetic candidate.

Record ten full-vocabulary captures and four 64-step greedy comparisons
from one frozen HEAD snapshot on M1 Max/Q4/SSD, with inherited DS4 flags
removed. Restoring only F32 split-K changes the 575-token frontier by
0.41702342; restoring the complete dense policy produces identical logits
on that fixture. The 29/575 repeated HEAD controls are byte-identical.
The 5942-token tail-only split ablation changes logits by 0.33132219.

With ordinary T1 decode policy held constant, the dense-policy ablation
changes the first generated token at step 59 for Rome29 and step 20 for
book575. Preserve raw logits, top-20 logprobs, logs, token-ID fixtures,
commands, source hashes and independent provenance/numerical audits.
These fixtures do not reproduce the tester's exact M4/Q2 prompts or
attribute every component of the reported deltas; they are not quality
or performance evaluations.

Provide a preparation script that recreates 103 tracked source files from
0231312820, applies the isolated diagnostic
patch and verifies all source hashes. Add fresh snapshot/output arguments
to both runners and document serial reproduction using the local Q4 GGUF.
Keep generated snapshot copies, executables and object files outside Git.

Validation:
- Independent recalculation of all ten 248320-logit dumps and greedy
  common prefixes, selected token IDs and bytes passed.
- Preparation in a fresh temporary directory reproduced all 103 source
  hashes and applied only the reviewed diagnostic patch.
- Python AST/JSON parsing and both runner help commands passed.
- git diff --cached --check passed.

This commit archives research only; pending production optimization
experiments remain outside its scope. No production dispatch is changed.
2026-10-03 09:21:17 +02:00

44 lines
2.8 KiB
Python

from pathlib import Path
import argparse
import hashlib,json,os,subprocess,time
lane=Path(__file__).resolve().parent
repo=lane.parents[1]
parser = argparse.ArgumentParser(description="Repeat 64-step greedy comparisons after the prefill ablation.")
parser.add_argument("--snapshot", default="head", help="Snapshot directory, relative to this archive or absolute")
parser.add_argument("--output", default="greedy-ab", help="Fresh output directory, relative to this archive or absolute")
args = parser.parse_args()
head = (lane / args.snapshot).resolve()
out = (lane / args.output).resolve()
out.mkdir(exist_ok=False)
env={k:v for k,v in os.environ.items() if not k.startswith("DS4_")}
report={"scope":"controlled HEAD dense policy ablation, M1 Max Q4 SSD, MTP off", "runs":[],"comparisons":[]}
ref={}
for name in ("rome29","book575"):
for arm in ("head","base_dense"):
run_env=env|({"DS4_DIAG_BASE_PREFILL_DENSE":"1"} if arm=="base_dense" else {})
target=out/f"{name}-{arm}.json"
cmd=[str(head/"ds4"),"-m",str(repo/"gguf/Qwen3.8-Flash-Next-Q4.gguf"),"--metal","--ssd-streaming","--ctx","16384","--prefill-chunk","2048","--nothink","--temp","0","-n","64","--prompt-file",str(lane/"fixtures"/(name+".txt")),"--dump-logprobs",str(target)]
print("START",name,arm,flush=True)
begin=time.monotonic()
with (out/f"{name}-{arm}.log").open("wb") as log:
rc=subprocess.run(cmd,cwd=head,env=run_env,stdout=log,stderr=subprocess.STDOUT).returncode
assert rc==0
data=json.loads(target.read_text())
ids=[step["selected"]["id"] for step in data["steps"]]
report["runs"].append({"name":name,"arm":arm,"seconds":time.monotonic()-begin,"command":cmd,"env":{k:v for k,v in run_env.items() if k.startswith("DS4_")},"steps":len(ids),"ids":ids,"json_sha256":hashlib.sha256(target.read_bytes()).hexdigest()})
if arm=="head":ref[name]=data
else:
original=ref[name];a=[x["selected"]["id"] for x in original["steps"]]
divergence=next((i for i,(x,y) in enumerate(zip(a,ids)) if x!=y),None)
if divergence is None and len(a)!=len(ids):divergence=min(len(a),len(ids))
c={"name":name,"same_tokens":a==ids,"first_different_step_zero_based":divergence,"steps_head":len(a),"steps_base_dense":len(ids)}
if divergence is not None:
c["selected_head"]=original["steps"][divergence]["selected"]
c["selected_base_dense"]=data["steps"][divergence]["selected"]
report["comparisons"].append(c)
print("COMPARE",json.dumps(c),flush=True)
(out/"results.json").write_text(json.dumps(report,indent=2)+"\n")
print("DONE",name,arm,round(time.monotonic()-begin,2),flush=True)
report["status"]="COMPLETE"
(out/"results.json").write_text(json.dumps(report,indent=2)+"\n")