Commit 22847e0
feat(mac): full fused-engine chat (verifier+proposer+f_θ, f_θ default-ON) + reasoning-channel strip (#144)
* feat(mac): gemma-4 interactive CLI chat on the Kakeya-for-Mac (MLX) engine
scripts/chat_mlx_kakeya.py — single-stream (B=1) gemma-4 chat over the Kakeya S5
bounded cache (SinkWindowKVCache): sliding layers bounded to sink+window, full-
attn (exact) layers keep full context (S5 free lunch, no f_theta/proposer needed
on gemma-4). B=1 sidesteps the MLX B>1,L=1 batched-decode bug. Interactive REPL +
--scripted mode (for non-interactive bridge verification) + transcript JSON.
Adds mac-bridge preset mlx-kakeya-chat-smoke (scripted 3-turn run) + manifest
test (100% coverage, 29 presets). Operator runs the same script without
--scripted for a real interactive chat on the Mac.
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* fix(mac chat): use template enable_thinking instead of raw channel marker
Smoke run showed the injected <|channel>content marker leaked 'thought' text and
caused greedy looping (turns 1/3 repeated). Replace with the chat template's
enable_thinking flag (default off → clean direct answers), with a TypeError
fallback for templates that don't accept the kwarg.
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* fix(mac chat): add repetition_penalty (default 1.3) to stop greedy JSON loops
enable_thinking=False gave correct answers but greedy decoding looped on a
repeated JSON wrapper. Add mlx_lm repetition penalty via logits_processors
(with a TypeError fallback for older mlx_lm signatures).
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* fix(mac chat): generic loop guard — stop + trim when output degenerates into a repeat
The 4-bit gemma-4-it checkpoint appends a repeating json answer-wrapper under
greedy; repetition_penalty alone didn't stop it. Add a generic guard: break when
a 24-char tail recurs 3+ times, and _trim_loop() keeps only the first occurrence
for the stored/displayed text. The (correct) answer is always first.
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* fix(mac chat): strict consecutive-loop guard (no longer trims real answers)
_trim_loop over-cut (dropped 'Paris' because the answer text recurs inside the
model's json echo). Replace with _is_degenerate_loop: stop ONLY on a true
back-to-back repeat (same 16-char block 3x consecutively); never trim stored
text. Answer + a single echo is preserved.
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* fix(mac chat): raise default --max-new-tokens 256->1024 + show stop reason (eos/max/loop)
User hit truncation ('断掉') on a long PoW explanation: exactly 256 tokens =
the old default cap. Raise default to 1024 and surface the stop reason each turn
(WARN when it's the max-new-tokens cap), so truncation is obvious and tunable.
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* fix(mac chat): stop at gemma's natural turn end (real EOS detection) — output length must not be a user knob
User correctly noted: needing --max-new-tokens to avoid truncation = unusable.
Root cause: <end_of_turn> was dropped from the stop set (old code used encode()+
single-token check on a special token), so the model ran PAST its turn (verbose
JSON echoes / self-correction) until the max-tokens cap — that IS the '断掉' and
the verbosity, same bug. Now resolve stops via tokenizer.eos_token_ids +
convert_tokens_to_ids('<end_of_turn>'/'<eos>'); the cap is only a backstop.
Report eos_token_ids + per-turn stop_reason; smoke now includes a long-answer
prompt to confirm it stops on eos, not max.
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* fix(mac chat): default --max-new-tokens=2048 as a generous backstop (natural EOS stops first)
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* chore(mac-bridge): raise MAX_NEW_TOKENS bound 512->2048 (chat answers need it; natural EOS stops first)
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* feat(mac): FULL fused-engine chat (verifier+DFlash proposer+f_θ+S5) — not verifier-only
Adds --chat/--chat-scripted to k3_integrated_niah_eval_mac.py: an interactive REPL
that drives the EXACT validated fused spec-decode per-turn sequence
(build_restoration -> S5 prefill -> aux capture -> fused_specdecode_generate_mlx_trim),
reusing the harness's engine construction. The NIAH eval loop is untouched (zero
risk to the evidence path). Each turn reports blocks / mean_accept_len to prove the
proposer is live + bounded resident KV. Natural EOS stop (<end_of_turn>).
Adds bridge preset mlx-kakeya-fused-chat-smoke (full fused flags + --chat-scripted)
+ manifest test. This is the verifier/PROPOSER bounded-memory engine the project is
about — not the verifier-only AR path.
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* polish(mac fused chat): strip stop-token markers from displayed text (skip_special_tokens)
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* docs(mac fused chat): accurate engine label — proposer live; f_θ bypassed on gemma-4 (S5 free lunch)
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* feat(mac fused chat): --force-f-theta — f_θ actually RUNS each turn (even if recall-irrelevant on gemma-4)
User: f_θ must execute even if its output is discarded by the verifier attention.
- build_restoration: --force-f-theta bypasses the S5 native-prefill short-circuit
(the line that stopped f_θ running under --s5-exact-full-attn), so f_θ projects
proposer hidden -> verifier K/V and injects it into the sliding layers.
- _gen_turn now branches over all-mlx (proposer; f_θ bypassed) AND torch
drafter+f_θ (proposer + f_θ runs) paths; reports f_theta_ran + f_theta_layers.
- new preset mlx-kakeya-fused-chat-ftheta (torch path + --force-f-theta).
On gemma-4 the restored sliding K/V are recall-irrelevant (exact layers carry
recall) — f_θ still EXECUTES, exercising the full verifier/proposer/f_θ pipeline.
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* feat(mac chat): f_θ default-ON in interactive chat + ADR 0015 update
- --chat now auto-enables --force-f-theta (full verifier/proposer/f_θ pipeline)
unless --all-mlx-drafter (fast, f_θ-bypassed) or native baseline is chosen.
- mlx-kakeya-fused-chat-ftheta preset drops the explicit --force-f-theta to
verify the DEFAULT-on behavior on the Mac.
- ADR 0015: new section 'Mac (MLX) interactive engine — full pipeline, f_θ
default-ON' documenting the engine, the gemma-4 recall-irrelevant-but-runs
caveat, the forensic timeline (f_θ S5-bypassed 2026-06-12 b3a04d0; proposer
blocks=0 caught by 0a6fb19), and the measured result (f_theta_ran=TRUE 25
sliding layers + proposer blocks>0).
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
* fix(mac chat): strip gemma-4 reasoning-channel bleed (\nthought) from displayed answer
Cut the decoded text at the first channel marker (<|channel / <channel / \nthought
/ \nthink) so the chat shows only the natural-language answer. Applied to both
the full fused-engine chat (harness _gen_turn) and the lightweight AR chat.
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: FluffyAIcode <FluffyAIcode@users.noreply.github.com>1 parent b761454 commit 22847e0
5 files changed
Lines changed: 356 additions & 2 deletions
File tree
- docs/adr
- inference_engine/bridge
- scripts
- research
- tests/inference_engine/bridge
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
96 | 131 | | |
97 | 132 | | |
98 | 133 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
678 | 678 | | |
679 | 679 | | |
680 | 680 | | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
| 718 | + | |
| 719 | + | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
| 728 | + | |
| 729 | + | |
| 730 | + | |
| 731 | + | |
| 732 | + | |
| 733 | + | |
| 734 | + | |
| 735 | + | |
| 736 | + | |
| 737 | + | |
| 738 | + | |
| 739 | + | |
| 740 | + | |
| 741 | + | |
| 742 | + | |
| 743 | + | |
| 744 | + | |
| 745 | + | |
| 746 | + | |
| 747 | + | |
| 748 | + | |
| 749 | + | |
| 750 | + | |
| 751 | + | |
681 | 752 | | |
682 | 753 | | |
683 | 754 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
192 | 192 | | |
193 | 193 | | |
194 | 194 | | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
195 | 201 | | |
196 | | - | |
| 202 | + | |
197 | 203 | | |
198 | 204 | | |
199 | 205 | | |
| |||
0 commit comments