Skip to content

Commit 772c8df

Browse files
cleanup(mlx-fused): strip inert KDBG probe instrumentation; finalize codegen presets
- Remove the KAKEYA_KDBG-gated debug instrumentation (helpers + per-block emission + prefill_state/turn_compare) from fused_specdecode.py and k3_integrated_niah_eval_mac.py. Investigation complete. - Keep the production fix (runaway-loop guard) + the --chat-scripted-file / --fused-no-loop-guard / --chat-native-ref flags. - Repoint the two codegen presets to the multi-turn 'explain||code' chat (guard-off probe + guard-on validate), accurate descriptions; drop the now- unused pow_codegen_longprompt.txt fixture. On-device (Mac M4): across short/long/multi-turn regimes the engine is coherent (fused==native); guard-on and guard-off outputs are byte-identical on the multi-turn code scenario -> the guard is inert on healthy output (no regression) and the systematic degeneration was already resolved by the wrap fix (#146). Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
1 parent 85abe81 commit 772c8df

4 files changed

Lines changed: 14 additions & 296 deletions

File tree

inference_engine/backends/mlx/fused_specdecode.py

Lines changed: 0 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -35,69 +35,6 @@
3535
restored_prefill_cache,
3636
)
3737

38-
# region agent log (fused-codegen-degeneration-2815 probe; strip after fix)
39-
import os as _kdbg_os
40-
import sys as _kdbg_sys
41-
import json as _kdbg_json
42-
43-
_KDBG = bool(_kdbg_os.environ.get("KAKEYA_KDBG"))
44-
45-
46-
def _kdbg(hyp: str, msg: str, **data: Any) -> None:
47-
"""Emit one NDJSON probe line to stderr (prefix ``KDBG ``) and, best-effort,
48-
to /opt/cursor/logs/debug.log. No-op unless ``KAKEYA_KDBG`` is set, so
49-
production behaviour is unchanged."""
50-
if not _KDBG:
51-
return
52-
rec = {"hypothesisId": hyp, "location": "fused_specdecode.py",
53-
"message": msg, "data": data}
54-
try:
55-
_kdbg_sys.stderr.write("KDBG " + _kdbg_json.dumps(rec, ensure_ascii=False) + "\n")
56-
_kdbg_sys.stderr.flush()
57-
except Exception:
58-
pass
59-
try:
60-
with open("/opt/cursor/logs/debug.log", "a") as _f:
61-
_f.write(_kdbg_json.dumps(rec) + "\n")
62-
except Exception:
63-
pass
64-
65-
66-
def _kdbg_cycle(ids: Sequence[int], window: int = 80) -> Tuple[float, int]:
67-
"""Short-unit cycle metric on the tail of ``ids``: returns
68-
``(cyc_frac, cyc_p)`` where ``cyc_p`` is the period (1..window//3) whose
69-
back-to-back repetition covers the largest fraction ``cyc_frac`` of the
70-
trailing ``window`` tokens. ~1.0 => the tail is a tight repeating loop."""
71-
w = list(ids[-window:])
72-
n = len(w)
73-
if n < 6:
74-
return 0.0, 0
75-
best_frac, best_p = 0.0, 0
76-
for p in range(1, n // 3 + 1):
77-
run, i = 0, n - 1
78-
while i - p >= 0 and w[i] == w[i - p]:
79-
run += 1
80-
i -= 1
81-
if run > 0:
82-
frac = (run + p) / n
83-
if frac > best_frac:
84-
best_frac, best_p = frac, p
85-
return round(best_frac, 3), best_p
86-
87-
88-
def _kdbg_cache_offsets(cache: Any) -> Tuple[Optional[int], Optional[int]]:
89-
"""(first full-attn KVCache offset, first sliding RotatingKVCache offset)."""
90-
off_full = off_rot = None
91-
for c in (cache or []):
92-
nm = type(c).__name__
93-
if off_rot is None and "Rotating" in nm:
94-
off_rot = int(getattr(c, "offset", -1))
95-
elif off_full is None and "Rotating" not in nm:
96-
off_full = int(getattr(c, "offset", -1))
97-
return off_full, off_rot
98-
# endregion
99-
100-
10138
# --------------------------------------------------------------------------- #
10239
# Component A: capture verifier aux-layer hidden states (no transformers
10340
# `output_hidden_states` on MLX → patch the decoder-layer __call__).
@@ -888,22 +825,6 @@ def fused_specdecode_generate(
888825
commit = candidate[:accepted] + [correction]
889826
generated += commit
890827
accepts.append(accepted)
891-
# region agent log (fused-codegen-degeneration-2815 probe)
892-
if _KDBG:
893-
off_full, off_rot = _kdbg_cache_offsets(getattr(adapter, "_cache", None))
894-
cyc_frac, cyc_p = _kdbg_cycle(generated)
895-
# H-D: cache.offset must track committed length (past_len).
896-
# off_rot lags by the sliding window (bounded), off_full == past_len.
897-
_kdbg("AD", "block",
898-
blk=len(accepts) - 1, base=cstart,
899-
past_len=int(adapter._past_len), gen=len(generated),
900-
off_full=off_full, off_rot=off_rot,
901-
bonus=int(bonus), cand=[int(x) for x in candidate],
902-
n_cand=len(candidate), accepted=int(accepted),
903-
commit=[int(x) for x in commit],
904-
next_argmax=int(argmax_fn(adapter.next_token_logits)),
905-
cyc_frac=cyc_frac, cyc_p=cyc_p)
906-
# endregion
907828
if any(t in eos for t in commit):
908829
break
909830
# Greedy decoding can collapse into a runaway short-period loop (e.g.

inference_engine/bridge/manifest.py

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -773,19 +773,13 @@ def _harness_preset(
773773
),
774774
Preset(
775775
name="mlx-kakeya-codegen-degen-probe",
776-
description="DEBUG: full f_θ fused engine on a LONG single-turn prompt "
777-
"(~2k-char PoW explanation + a 'write C code' request, from "
778-
"the committed fixture pow_codegen_longprompt.txt) so the "
779-
"native RotatingKVCache ring is ALREADY WRAPPED at prefill "
780-
"(would_wrap_block0). Short single-turn prompts were proven "
781-
"token-identical to native & coherent; this isolates the "
782-
"long-prompt-prefill regime cheaply (tiny 192-tok budget). "
783-
"KAKEYA_KDBG logs prefill state (prompt_len, any_wrapped, "
784-
"would_wrap_block0, rot/full offsets) + per-block offsets + "
785-
"turn_compare_fused_vs_native. Native-greedy control "
786-
"(--chat-native-ref): native coherent + fused garbled ⇒ "
787-
"long-prompt prefill corrupts logits (engine bug); both "
788-
"degenerate ⇒ bounded-greedy pathology the engine must guard.",
776+
description="Regression probe (guard DISABLED): full f_θ fused engine "
777+
"on the multi-turn 'explain PoW || write PoW in C' chat "
778+
"that originally degenerated, with --fused-no-loop-guard so "
779+
"any greedy markdown-marker collapse is observable. Pairs "
780+
"with mlx-kakeya-codegen-guard-validate (guard ENABLED) to "
781+
"show the guard is what keeps the answer clean. On current "
782+
"code (post wrap-fix) both turns stay coherent.",
789783
command_templates=(
790784
(
791785
"python3", "scripts/research/k3_integrated_niah_eval_mac.py",
@@ -808,12 +802,13 @@ def _harness_preset(
808802
Preset(
809803
name="mlx-kakeya-codegen-guard-validate",
810804
description="Validate the runaway-loop guard end-to-end: full f_θ fused "
811-
"engine on the same long code prompt (pow_codegen_longprompt"
812-
".txt) with the guard ENABLED (default). The fused answer "
813-
"must NOT collapse into a marker wall — the guard stops the "
814-
"runaway (stopped_on_runaway) leaving a clean tail — while "
815-
"the native-greedy control (no guard) degenerates, proving "
816-
"the guard is what saves the engine from greedy pathology.",
805+
"engine on the multi-turn 'explain PoW || write PoW in C' "
806+
"chat with the guard ENABLED (production default). The "
807+
"answer must stay coherent and never collapse into a marker "
808+
"wall — if a runaway starts, the guard stops it "
809+
"(stopped_on_runaway) leaving a clean tail. Confirmed "
810+
"coherent on current code; byte-identical to the guard-off "
811+
"probe (the guard is inert on healthy output).",
817812
command_templates=(
818813
(
819814
"python3", "scripts/research/k3_integrated_niah_eval_mac.py",

scripts/research/k3_integrated_niah_eval_mac.py

Lines changed: 0 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@ def main() -> int:
230230
MLXRestoredIncrementalVerifier, capture_aux_hidden,
231231
make_bridge_embed_lm_head, fused_specdecode_generate,
232232
fused_specdecode_generate_mlx, fused_specdecode_generate_mlx_trim,
233-
_sliding_ring_would_wrap, # region agent log (fused-codegen-degeneration-2815)
234233
)
235234
from inference_engine.v04.kv_compressor import make_default_compressor
236235
from inference_engine.bench.k3_report_gate import (
@@ -779,54 +778,6 @@ def _encode_chat(history: List[Dict[str, str]]) -> List[int]:
779778
history, add_generation_prompt=True)
780779
return list(cids.tolist() if hasattr(cids, "tolist") else cids)
781780

782-
# region agent log (fused-codegen-degeneration-2815 prefill probe)
783-
import os as _kos_chat
784-
_KDBG_CHAT = bool(_kos_chat.environ.get("KAKEYA_KDBG"))
785-
786-
def _kdbg_emit(rec: Dict[str, Any]) -> None:
787-
try:
788-
sys.stderr.write("KDBG " + json.dumps(rec, ensure_ascii=False) + "\n")
789-
sys.stderr.flush()
790-
except Exception:
791-
pass
792-
try:
793-
with open("/opt/cursor/logs/debug.log", "a") as _f:
794-
_f.write(json.dumps(rec) + "\n")
795-
except Exception:
796-
pass
797-
798-
def _kdbg_cache_summary(cache: Any) -> Dict[str, Any]:
799-
"""rot/full offset+max_size rollup + wrap/trimmable flags. The
800-
decisive prefill signal: is the sliding RotatingKVCache already
801-
wrapped (off>=max_size) BEFORE decode starts, and does full-attn
802-
off == prompt_len? A pre-wrapped ring at prefill means the very
803-
first speculative block's trim is refused (offset desync)."""
804-
rot_off = rot_ms = full_off = None
805-
any_wrapped = False
806-
all_trimmable = True
807-
n = 0
808-
for c in (cache or []):
809-
n += 1
810-
nm = type(c).__name__
811-
off = int(getattr(c, "offset", -1))
812-
ms = getattr(c, "max_size", None)
813-
ms = int(ms) if ms is not None else None
814-
is_rot = "Rotating" in nm
815-
if is_rot and ms is not None and off >= ms:
816-
any_wrapped = True
817-
trim_fn = getattr(c, "is_trimmable", None)
818-
trim = bool(trim_fn()) if callable(trim_fn) else None
819-
if trim is False:
820-
all_trimmable = False
821-
if is_rot and rot_off is None:
822-
rot_off, rot_ms = off, ms
823-
if (not is_rot) and full_off is None:
824-
full_off = off
825-
return {"n_layers": n, "rot_off": rot_off, "rot_ms": rot_ms,
826-
"full_off": full_off, "any_wrapped": any_wrapped,
827-
"all_trimmable": all_trimmable}
828-
# endregion
829-
830781
def _gen_turn(pid: List[int]) -> Dict[str, Any]:
831782
# Opt-in A/B control (--chat-native-ref): a plain NATIVE greedy
832783
# AR decode of the SAME prompt for --max-new-tokens. Captured as
@@ -837,14 +788,6 @@ def _gen_turn(pid: List[int]) -> Dict[str, Any]:
837788
nref_tokens: List[int] = []
838789
if args.chat_native_ref:
839790
nref_cache, nref_logits = native_prefill(list(pid))
840-
# region agent log (fused-codegen-degeneration-2815 prefill probe)
841-
if _KDBG_CHAT:
842-
_turn = sum(1 for h in history if h.get("role") == "user")
843-
_kdbg_emit({"hypothesisId": "AE",
844-
"message": "prefill_state_native",
845-
"data": {"turn": _turn, "prompt_len": len(pid),
846-
"cache": _kdbg_cache_summary(nref_cache)}})
847-
# endregion
848791
while len(nref_tokens) < args.max_new_tokens:
849792
tok = int(mx.argmax(nref_logits).item())
850793
nref_tokens.append(tok)
@@ -875,23 +818,6 @@ def _gen_turn(pid: List[int]) -> Dict[str, Any]:
875818
restored_v_per_layer=_pad(rv, tsrc, T),
876819
evicted_positions=evicted,
877820
prefill_chunk_size=args.prefill_chunk_size, full_kv=args.cuda_trim)
878-
# region agent log (fused-codegen-degeneration-2815 prefill probe)
879-
if _KDBG_CHAT:
880-
_turn = sum(1 for h in history if h.get("role") == "user")
881-
_kdbg_emit({"hypothesisId": "AE",
882-
"message": "prefill_state_fused",
883-
"data": {"turn": _turn, "prompt_len": T,
884-
"evicted_count": len(evicted),
885-
"block_size": int(args.block_size),
886-
"would_wrap_block0": bool(
887-
_sliding_ring_would_wrap(
888-
getattr(adapter, "_cache", None),
889-
int(args.block_size))),
890-
"past_len": int(adapter._past_len),
891-
"f_theta_ran": bool(f_theta_ran),
892-
"cache": _kdbg_cache_summary(
893-
getattr(adapter, "_cache", None))}})
894-
# endregion
895821
t0 = time.perf_counter()
896822
_guard = not args.fused_no_loop_guard
897823
if mlx_drafter is not None and args.cuda_trim:
@@ -937,45 +863,6 @@ def _gen_turn(pid: List[int]) -> Dict[str, Any]:
937863
res["native_ref_tokens"] = len(nref_tokens)
938864
res["resident_kv_bytes"] = int(
939865
sum(int(getattr(c, "nbytes", 0)) for c in (adapter._cache or [])))
940-
# region agent log (fused-codegen-degeneration-2815 probe)
941-
import os as _kos
942-
if _kos.environ.get("KAKEYA_KDBG"):
943-
ftoks = [int(t) for t in res.get("tokens", [])]
944-
ntoks = [int(t) for t in nref_tokens]
945-
div = None
946-
for j, (a, b) in enumerate(zip(ftoks, ntoks)):
947-
if a != b:
948-
div = j
949-
break
950-
if div is None:
951-
div = min(len(ftoks), len(ntoks))
952-
953-
def _dec(seq):
954-
try:
955-
return tokenizer.decode(seq, skip_special_tokens=True)
956-
except TypeError:
957-
return tokenizer.decode(seq)
958-
rec = {
959-
"hypothesisId": "AC",
960-
"message": "turn_compare_fused_vs_native",
961-
"data": {
962-
"turn": sum(1 for h in history if h.get("role") == "user"),
963-
"fused_n": len(ftoks), "native_n": len(ntoks),
964-
"first_divergence_idx": div,
965-
"fused_div_ctx": ftoks[max(0, div - 8):div + 16],
966-
"native_div_ctx": ntoks[max(0, div - 8):div + 16],
967-
"fused_div_text": _dec(ftoks[max(0, div - 8):div + 16]),
968-
"native_div_text": _dec(ntoks[max(0, div - 8):div + 16]),
969-
"fused_tail": ftoks[-48:],
970-
"native_tail": ntoks[-48:],
971-
"fused_tail_text": _dec(ftoks[-48:]),
972-
"native_tail_text": _dec(ntoks[-48:]),
973-
},
974-
}
975-
sys.stderr.write(
976-
"KDBG " + json.dumps(rec, ensure_ascii=False) + "\n")
977-
sys.stderr.flush()
978-
# endregion
979866
return res
980867

981868
print(f"[chat] FULL fused engine: verifier={args.verifier_path} "

0 commit comments

Comments
 (0)