Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f17c280
lfm2: keep a drafter's tapped rows on every forward
BlivionIaG Oct 24, 2026
3b88fa3
lanes: a lone stream's pipelined steps move to pipelined.zig
BlivionIaG Oct 26, 2026
474105a
lfm2: draft with LiquidAI's DSpark drafter (--drafter)
BlivionIaG Oct 26, 2026
2ecd7f1
lfm2: a DSpark hold is not waited on; the verify copies its drafts on…
BlivionIaG Oct 26, 2026
fca4379
docs: the LFM2 recipe's DSpark drafts with LiquidAI's drafter
BlivionIaG Oct 26, 2026
ea9b796
lanes: an external drafter's chain chances price verify rows, and its…
BlivionIaG Oct 26, 2026
631736f
lanes: a drafter whose hold is a pass of its own: no hold beside a co…
BlivionIaG Oct 26, 2026
98dee05
lfm2: a DSpark confidence logit kernel, registered with the kernel co…
BlivionIaG Oct 26, 2026
7d7e5fc
lfm2: the DSpark confidence head schedules the verify (--draft-verify…
BlivionIaG Oct 26, 2026
c811111
lfm2: a short prompt's tapped rows wait in the DSpark stage like veri…
BlivionIaG Oct 26, 2026
7746c32
lfm2: DSpark prices its own hold pass for the lane core
BlivionIaG Oct 26, 2026
82a14bc
lfm2: tf-lfm2-dspark times shared holds; tf-lfm2-verify-costs reads r…
BlivionIaG Oct 26, 2026
eba0950
docs: the LFM2 recipe's DSpark verify schedule and its flags
BlivionIaG Oct 26, 2026
c40129e
lfm2: the DSpark drafter loads one matrix at a time and keeps a lane …
BlivionIaG Oct 26, 2026
4671e17
docs: the LFM2 recipe's DSpark loader and lane memory
BlivionIaG Oct 26, 2026
7b99700
core: tile_qmm's twin takes a caller's row count for its window kernel
BlivionIaG Oct 26, 2026
3d735f1
lfm2: a DSpark hold runs in one concurrent encoder
BlivionIaG Oct 26, 2026
b859d8e
lfm2: a full DSpark stage absorbs every lane's staged rows in its pass
BlivionIaG Oct 26, 2026
2b7a9a2
docs: the LFM2 recipe's cheaper DSpark hold
BlivionIaG Oct 26, 2026
ca93db1
lfm2 dspark: a held pick that is nonfinite or past the vocabulary is …
BlivionIaG Oct 26, 2026
25a5d3b
tf-lfm2-dspark: the reference reads the target's embedding width from…
BlivionIaG Oct 26, 2026
1eb0476
lfm2 dspark: one-line comments for the held-pick refusal
BlivionIaG Oct 26, 2026
cf9fad0
lfm2 dspark: one-line comment for Options
BlivionIaG Oct 26, 2026
d4abce9
kernel contract: the draft ids probe zeroes its bad flag each run
BlivionIaG Oct 26, 2026
0a9a87c
lfm2 dspark: run the released bf16 matrices as stored (--drafter-bits…
BlivionIaG Oct 26, 2026
cf5997d
lfm2 dspark: Options' comment fits 120 columns
BlivionIaG Oct 26, 2026
4767a9f
lfm2 dspark: the weights loader's comment fits 120 columns
BlivionIaG Oct 26, 2026
e28f27e
lfm2 dspark: the block's linear comment fits 120 columns
BlivionIaG Oct 26, 2026
a6c1d32
lfm2 dspark: the bf16 tile kernel loads its tiles 16 bytes at a time
BlivionIaG Oct 26, 2026
d50c4ea
lfm2 dspark: --drafter-bits 8 serves the 8-bit codes, named in --help…
BlivionIaG Oct 26, 2026
1027db0
kernel contract: the drafter's bf16 linears and bf16 Markov scan carr…
BlivionIaG Oct 26, 2026
487f6a5
lfm2: the drafter's verify is not a choice: the confidence head's cha…
BlivionIaG Oct 26, 2026
14565fa
lfm2: address DSpark stack review and retain main contracts
BlivionIaG Oct 28, 2026
017919f
docs: record DSpark review checks and load-time peaks
BlivionIaG Oct 28, 2026
2dbbc0e
docs: record independent drafter reference and partial seam probe
BlivionIaG Oct 28, 2026
8bd0587
docs: record completed M4 and M5 DSpark qualification
BlivionIaG Oct 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ Conversions are explicitly marked: their upstream weights need the linked conver
| GLM-5.3-Flash, FP4-Local | `tensorfold pull nvidia/GLM-5.3-Flash-FP4-Local@76348ddb2be2e35e39ecfc00e75dc07703f4f3d5` | Two GB10s at TP=2, or three at TP=3 over a ring of direct links: @Bizuayeu loaded it as stored and served it at both sizes. 165.3 GiB of weights, 13% less than NVFP4's 190.4 GiB. | [Native CUDA](docs/recipes/glm-5.3-flash-cuda.md), in 1.1.5 (#1050). NVIDIA's mixed-precision checkpoint: NVFP4 routed experts with compressed block scales, MXFP8 and 128×128-block FP8 for most of the rest. As close to BF16 as NVFP4 at its smaller size: at TP=2 its NLL is 1.11% above BF16's against NVFP4's 1.37% ([contributed receipt](docs/receipts/glm-fp4local-80517fc3/README.md) on #1050's head, not rerun on main), a difference the per-document intervals in [XSFP4's card](https://huggingface.co/Bizuayeu/GLM-5.3-Flash-XSFP4#measured) do not resolve. |
| GLM-5.3-Flash, XSFP4 | `tensorfold pull Bizuayeu/GLM-5.3-Flash-XSFP4@88736f916f8939607fde8a4b881dcae749f7551d` | Two GB10s at TP=2, or three at TP=3 over a ring of direct links: on main `8086c205c` @Bizuayeu loaded it in 370.7 s at TP=2 (rank 0's model 96.97 GiB at a 524,288-token window) and in 313.8 s at TP=3 (63.60 GiB at 1,048,576), and both served. 165.7 GiB of weights, 0.4 GiB more than FP4-Local's. | [Native CUDA](docs/recipes/glm-5.3-flash-cuda.md), in 1.1.5 through FP4-Local's path. FP4-Local with its routed experts' NVFP4 blocks fitted again from the BF16 weights, a smoothing folded into them, so it runs on the same kernels. Closer to BF16 than FP4-Local and NVFP4 at TP=2 by all three measures in [its card](https://huggingface.co/Bizuayeu/GLM-5.3-Flash-XSFP4#measured), on #1050's code: top-1 agreement 93.26%, NLL 0.85% above and a KL bound of 0.0431, against FP4-Local's 92.82%, 1.11% and 0.0510. |
| GLM-5.3, EXLR8 `home` | `tensorfold pull kindlingai/glm-5.3-exlr8-k2-k3-k4@f459f5d0272a529403dd9b3fd32f771f4250a0d4 --exlr8 home --node 0/2 --dir ~/models/glm-5.3-exlr8-home` | Two M5 Ultra Macs, 256 GB each; about 160 GB resident per Mac at 8k context / four streams. | [Two-Mac recipe](docs/glm-5.3-exlr8.md). Use `--node 1/2` on the other Mac; Thunderbolt 5 and MCDMA required. No CUDA backend. |
| LFM2.5-24B-A2B, MLX 4 / 6 / 8-bit | `tensorfold pull LiquidAI/LFM2.5-24B-A2B-MLX-4bit@667408d494bde191c2cb9dd4f4549827816b9275`<br>`tensorfold pull LiquidAI/LFM2.5-24B-A2B-MLX-6bit@1deec53eb49571e21cdcbf82fd5839248f07ed88`<br>`tensorfold pull LiquidAI/LFM2.5-24B-A2B-MLX-8bit@67ab417dd02d0c9545802a726df668620eae049d` | One Mac; M4 Pro checked. | [Native recipe](docs/recipes/lfm2.5-24b-a2b.md), [release history](CHANGELOG.md). |
| LFM2.5-24B-A2B, MLX 4 / 6 / 8-bit | `tensorfold pull LiquidAI/LFM2.5-24B-A2B-MLX-4bit@667408d494bde191c2cb9dd4f4549827816b9275`<br>`tensorfold pull LiquidAI/LFM2.5-24B-A2B-MLX-6bit@1deec53eb49571e21cdcbf82fd5839248f07ed88`<br>`tensorfold pull LiquidAI/LFM2.5-24B-A2B-MLX-8bit@67ab417dd02d0c9545802a726df668620eae049d` | One Mac; M4 Pro checked. | [Native recipe](docs/recipes/lfm2.5-24b-a2b.md), [release history](CHANGELOG.md). LiquidAI's DSpark drafter with `--drafter`. |
| Qwen3.6-35B-A3B, MLX with MTP | `tensorfold pull TensorFold/Qwen3.6-35B-A3B-MLX-4bit-MTP@81169a9bc511a27c1b4eedb77a2cd98ced431847` | One GB10; 20.9 GB checkpoint. | [Qwen3.6](docs/recipes/qwen3.6-moe.md). Native CUDA; the recipe's Metal path belongs to Python. |
| Gemma 4 31B, MLX 4-bit | `tensorfold pull mlx-community/gemma-4-31B-it-4bit@696d436c404745a59f30e4939a658162b0a9e57f`<br>`tensorfold pull z-lab/gemma-4-31B-it-DFlash@eabd648301ce28583cc14757912e5e0f84e152e1` | One M5 Mac; M5 Ultra checked. M1-M4 refused. | [Native 31B](docs/recipes/gemma-4-native.md). Name the drafter with `--drafter`; images with `--vision`. |
| Gemma 4 12B, converted MLX 4-bit | `hf download google/gemma-4-12B-it --revision 707f0a3b8a3c7ad586ed01e27eafbad8a27dd0f7 --local-dir ~/models/gemma-4-12b-hf`<br>`hf download google/gemma-4-12B-it-assistant --revision 46d4c6f13f0ac0ad827b915669b8df9b81c64c51 --local-dir ~/models/gemma-4-12b-assistant` | One M5 Mac; converted text weights 6.3 GB, image weights 100 MB, plus assistant/caches. M1-M4 refused. | [Convert and serve](docs/recipes/gemma-4-12b-native.md). Upstream download needs `hf`; conversion needs Python, mlx and mlx-lm. Serving is native. |
Expand Down Expand Up @@ -290,7 +290,7 @@ The binary's `capabilities --json` response lists its supported flags and platfo
| `--loop-guard-stop` | As `--loop-guard`, but end the reply where the guard fires: the reasoning so far, no answer or tool calls, `finish_reason` `content_filter` and a `reasoning_loop` error ([API](docs/api.md)). |
| `--no-drafts` | Produce the plain reference through the same engine. |
| `--drafter DRAFTER` | An external drafter, as a directory or a repo id in the Hugging Face cache, for models that take one: Qwen3.8-27B uses DFlash2 and Gemma 4 31B the drafter named in its recipe. Without one they decode plain. |
| `--drafter-bits 0\|4` | Drafter weight precision where the model offers a choice: 4 bits (the default), or 0 to keep bf16. Qwen3.8-27B on CUDA takes 4 only. |
| `--drafter-bits 0\|4\|8` | Drafter weight precision where the model offers a choice: 4 bits (the default), or 0 to keep bf16. Qwen3.8-27B on CUDA takes 4 only. LFM2.5-24B-A2B's DSpark drafter runs bf16 as released (0, the default when not given) or 8-bit codes quantized at load (8); it has no 4-bit mode. |
| `--record DIR` | Write each stream's committed tokens, positions and tapped rows under DIR, for drafter training. CUDA Nemotron only; a single stream runs through the lane rounds, and recording stops below 25 GiB free disk. |
| `--keep-warm SECONDS` | Keep the Metal GPU active while idle for this long after a request, default 900; zero disables it. |
| `--cfg-gamma GAMMA` | Metal Drama speech: semantic guidance strength, finite 1–5; 0/default disables it. Only reference-conditioned requests are guided. Enabled replies report `X-Cfg-Gamma`; codec heads stay conditional. |
Expand Down
6 changes: 4 additions & 2 deletions docs/kernel-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,10 @@ tile_qmm's pipelines and GLM-5.3-Flash's hc_expand_10.
LFM2.5-24B-A2B's shared rounds: the greedy pick (`lfm2_argmax`) and the conv and attention kernels that run every
stream's rows in one dispatch, each bit-equal to the per-stream kernels it replaces. Four controls edit the source: a tie
to the highest id, a nonfinite logit not flagged, and every stream reading or writing the first stream's state or cache.
Their launches are in `lfm2_records.zig` with the M1 and M2 limits from `--offline`; `lfm2_attn_segs` reserves its 128
threads in its source, as Metal cannot build it for M1 or M2 at another count.
The DSpark drafter's tap copy, Markov scan and pick, draft ids, block attention and confidence logit are there too, with seven more controls.
Its bf16 linears (few rows, 64x64 tiles) and the Markov scan over a bf16 W2 have four and two more.
Their launches are in `lfm2_records.zig` with the M1 and M2 limits from `--offline`; `lfm2_attn_segs` and
`lfm2_attn_block` reserve their 128 threads in their source, as Metal cannot build them for M1 or M2 at another count.
Metal also checks Nemotron's routed experts on the engine's route tables, one row to 128: `tf_xup_w3` and `tf_xdown_w3`
against float64 at tf_load16's bf16 x sums (up's relu2 as an interval over its two bf16 roundings), and the rows2, rows4
and six geometry pipelines of each projection bit-equal to them (two controls: member rows read from one row, and
Expand Down
135 changes: 135 additions & 0 deletions docs/receipts/lfm2-dspark-review/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# DSpark review fixes on current main

Source `14565fa73`, rebased onto main `d0c9dc9fb`, tested on 2026-10-28.
Apple M4 Pro, 20 GPU cores, 48 GiB RAM, macOS 26.5.1, Zig 0.17.0,
Apple Metal compiler 32023.883. Builds target `apple_m1`.

The shared and lone guards from the rejected PRs are absent. The lane core retains
confidence/grant pricing, hold-cost pricing and `copy_first`. Hold ordering reuses
one bounded allocation instead of allocating on every round. The initialization
cleanup releases Metal buffers before their owning list; injected scratch and warm
allocation failures exercise that path. Config admission refuses rank above 256 and
nonfinite f32 RoPE theta. The quantizer test widens its size calculation before
multiplication, and `--drafter` refuses a target restricted to one-row verification.

## Checks

- `zig build test test-kernel-contract test-golden fuzz-cortheon native dev-tools -Dcpu=apple_m1 --summary all`:
749/749 steps succeeded; 8,414 tests passed, 46 skipped, 0 failed.
- `zig build -Dcpu=apple_m1 --summary all`: 239/239 steps succeeded.
- `zig build test-lfm2 test-lfm2-dspark -Dcpu=apple_m1 --summary all`:
111/111 tests passed. The final scratch/warm failure test also passed in a subsequent
focused run: 51/51 DSpark tests.
- `zig build test-lfm2-dspark -Dcpu=apple_m1 -Doptimize=debug --summary all`:
51/51 passed, including both injected allocation failures.
- Debug `zig test` on `dspark_config.zig`: 4/4 passed; on `dspark_quant.zig`: 2/2 passed.
The original quantizer test from `2e5966f68` aborted with integer overflow in Debug.
- `zig fmt --check zig` and `git diff --check`: passed.
- Lean: 428 findings on main, 428 on this source, 0 new.
- `tf-kernel-contract --only lfm2`: 11 kernels passed gates 1-4, 0 failures,
0 known findings; all 17 planted controls red, 0 missed; 0 limit problems.
- `tf-kernel-contract --only tile_qmm`: 6 kernels passed gates 1-4, 0 failures,
0 known findings; 0 limit problems.
- `tf-lfm2-dspark MODEL DRAFTER 256`: 9/9 drafts equal the independent fp32
reference's picks; maximum confidence difference 0.00106; 20 steady drafter
rounds had zero host allocations and resizes; exit 0.
- Completed `tf-lfm2-exact`: 72/72 checks on both M4 Pro and M5 Ultra, zero
failures or skipped checks. This supersedes the earlier interrupted run.

## Served equality

Target `LiquidAI/LFM2.5-24B-A2B-MLX-4bit` at
`667408d494bde191c2cb9dd4f4549827816b9275`, with the local released DSpark weights.
The drafter safetensors SHA-256 is recorded in the accompanying JSON.

For both default bf16 and explicit `--drafter-bits 8`, serve with `--parallel 16
--context 4096 --prompt-cache-gib 0 --keep-warm 0`. Run:

```sh
python3 tools/bench_concurrent.py http://127.0.0.1:18194 review \
--tokens 64 --reps 1 --temperatures 0 --levels 1,4,8,16 --alone --serial
python3 tools/bench_concurrent.py http://127.0.0.1:18194 review \
--tokens 64 --reps 1 --temperatures 0 --levels 1,4,8,16 --alone --serial \
--prompts tools/bench_prompts.json
```

Each precision mode passed all 12 cells: eight same-prompt cells (code and chat)
and four distinct-prompt cells. Concurrent replies equal solo replies and drafted
solo replies equal `"draft": false` token hashes. Zero unequal replies and zero
failed requests. [Equality evidence](equality-and-load.json) retains per-request
concurrent, solo and plain token hashes.

These are short correctness checks, with one repetition, while builds were also
running. Their timings do not establish the decode performance gate.

## Peak during load

One model process at a time under a model lock. Both servers used the same target
and bf16 drafter, `--parallel 1 --context 4096 --prompt-cache-gib 0 --keep-warm 0`.
Read `/memory` after readiness and before sending any request. Its lifetime peak
agreed with `/usr/bin/time -l` at process exit.

- Exact #1392 head `1bb6e5db2`: 16,036,097,352 bytes, 14.935 GiB.
- Corrected stack source `14565fa73`: 15,527,930,776 bytes, 14.462 GiB.

The measured reduction during load is 508,166,576 bytes (484.6 MiB). This compares
the original pre-allocation head with the corrected stack rebased onto current
main; it is not an isolated comparison of #1393's commit on the same base.

## Extended qualification on the published stack

Source `2dbbc0e8f`, main baseline `d0c9dc9fb`. Additional device: Apple M5 Ultra,
256 GiB RAM, macOS 27.0, Metal compiler 32023.921.6, Zig 0.17.0.
[Extended evidence](extended-qualification.json) retains request hashes, counters,
per-round throughput and latency. Generated text and token arrays are omitted.
[Reproduction harness](qualification.py) supports `functional`, `long`,
`performance`, `performance qwen`, and `cold`; set `TF_QUAL_MAIN`,
`TF_QUAL_CANDIDATE`, `TF_QUAL_MODEL`, `TF_QUAL_DRAFTER`, and `TF_QUAL_OUT`
for the local installations. Run one model process at a time.

Both devices passed real two-turn resumed-versus-fresh chat equality (3,517 cached
prompt tokens), 29 seeded sampled equality cases across 1/4/8/16 streams, and
cancellation/replacement stress with Metal API validation enabled. M4 completed
143 requests with 84 cancellations at six slots and 252 with 134 at sixteen;
M5 completed 453 with 247 and 852 with 459 respectively. Zero wrong replies or
request errors. Server shutdowns were graceful.

M5 plain/drafted serving hashes agree at 4,096, 16,384, 65,536 and 130,816 prompt
tokens. Independent fp32 drafter checks agree on all nine picks at histories
65,535 and 130,815; maximum confidence differences 0.00532 and 0.00351.
Twenty steady rounds had zero host allocations/resizes. M5 also passes the same
11 LFM2 and six tile_qmm contracts, with all 17 LFM2 planted controls red.

### Performance remains an open issue

Three alternating rounds per arm, 256 generated tokens, 1/4/8/16 streams,
32-token warmups and uncached prompts. Aggregate decode rate uses the span from
the earliest first token to the latest last token. The `chat` fixture label in
the JSON means prose submitted to raw completions, not a templated chat request.
All cross-arm output hashes agree. These results do **not** clear a no-loss gate.

On M5, drafted versus main-plain median decode changes for code at 1/4/8/16
streams are +19.44%, -0.96%, -2.20%, -4.23%; for prose they are +35.89%,
-0.72%, -1.25%, -1.17%. Candidate-plain closely follows main-plain.
On M4, changes are approximately -6.0%, -13.9%, -5.6%, +0.7% for code and
-6.4%, -13.4%, -7.8%, -8.0% for prose. M4 also shows variation between plain
arms, so these measurements do not isolate every source of the loss.

M5 cold prefill medians at 2k/8k/32k/64k tokens are 0.1527/0.6027/2.9244/7.3276
seconds on main-plain versus 0.1634/0.6327/3.0466/7.5652 with the drafter.
Prompt counts were checked and cached-token counts were zero.

Other-family Qwen3.8-27B plus DFlash2 was tested at one and four streams with
three alternating rounds on both devices. M4 results vary with each executable's
independently measured persistent cost record: fresh records give code changes
of -7.13%/+3.71% and prose -6.47%/+0.83%. The original records and fresh-record
runs are both retained. No timings were copied between executables. M5 changes are +0.20%/-0.47% for code and +0.05%/+0.70% for prose.
No blanket other-family performance pass is claimed.

Two isolated, uncommitted experiments (a larger absorb staging buffer and
removing forced per-stream copy pricing) did not consistently remove the loss.
Neither experiment is part of this PR. Further pricing work requires its own
validation; the rejected shared/lone guards have not been restored.

M1, M2, M3, CUDA and HIP were not rerun for this revision. Focused Metal checks
are not a full cross-family kernel-contract receipt. All nine GitHub checks passed on `2dbbc0e8f` before this receipt-only update.
Loading
Loading