HiramKHackenbacker commited on
Commit
4156344
Β·
verified Β·
1 Parent(s): af2ec50

docs: refresh measured performance (local retest 2026-08-18)

Browse files
Files changed (1) hide show
  1. README.md +91 -86
README.md CHANGED
@@ -17,16 +17,16 @@ tags:
17
 
18
  # LFM2.5-2.6B β€” Core AI (.aimodel)
19
 
20
- `LiquidAI/LFM2.5-2.6B` converted to Core AI `.aimodel` bundles for Apple silicon by the
21
- [Visible](https://visible.cx) project. These are **derivative artifacts**: the weights are
22
- Liquid AI's, re-expressed as a Core AI graph with int8 block-32 symmetric weight
23
- quantization and a two-entrypoint (decode + chunked-prefill) function map. They run through
24
- Core AI on macOS; they are not PyTorch, GGUF or MLX checkpoints and cannot be loaded by
25
- those runtimes.
26
 
27
- **This is the model the Visible app selects as its quality tier.** It is the strongest of
28
- the three LFM2.5 text bundles in this catalog on Visible's own enrichment task, and the one
29
- whose outputs were judged most specific.
 
30
 
31
  ## Provenance
32
 
@@ -36,28 +36,25 @@ whose outputs were judged most specific.
36
  | Recipe | `export_lfm2_multifunction.py int8hu --head-sym --chunk 64` |
37
  | Toolchain base | `apple/coreai-models` @ `b1cb71b8522d99408059fa0b98b8742171bcb0b8` + the [coreai-model-zoo](https://github.com/john-rocky/coreai-model-zoo) python overlay |
38
  | Toolchain | `coreai-torch 0.4.1`, `coreai-core 1.0.0b2`, `coreai-opt 0.2.1`, `torch 2.9.0` |
39
- | Producer fingerprint | `coreai-core 1.0.0b2` on every inner `<name>.aimodel/metadata.json` β€” verified per bundle |
40
  | Weight format | int8, per-K-block-32, symmetric; symmetric head (`--head-sym`) |
41
  | Vocab | 128,000 |
42
- | Conversion host | Linux x86_64 (Debian 13), CPU tracing only |
43
 
44
- `mf64` in the bundle name means **multifunction with a 64-wide prefill**: one asset
45
- exposing `main` (S=1 decode) and `prefill` (S=64 chunked prefill),
46
- `function_map: {"main": ["main", "prefill"]}`. Weights are deduplicated across the two
47
- entrypoints, so the prefill function costs well under a megabyte.
48
 
49
- ### The `<think>` patch β€” read this before swapping in a fresh export
50
-
51
- Upstream's `chat_template.jinja` ends its generation prompt with an **open** think block
52
- (`<|im_start|>assistant\n<think>`). LFM2.5-2.6B is always-thinking, so an open block burns
53
- 684–919 reasoning tokens per item. Every bundle in this repo ships the block **closed**:
54
 
55
  ```jinja
56
  {{- "<|im_start|>assistant\n<think></think>\n" -}}
57
  ```
58
 
59
- This correction is applied post-export and **is not in the exporter**. A fresh conversion
60
- from the recipe reproduces the weights faithfully and this behaviour wrongly.
 
 
61
 
62
  ## Contents
63
 
@@ -68,25 +65,21 @@ from the recipe reproduces the weights faithfully and this behaviour wrongly.
68
  | `ctx16384/gpu-pipelined/lfm2_5_2_6b_decode_int8hu_block32_sym_mf64` | 3,655,243,498 | 16384 | main + prefill |
69
 
70
  Each folder holds `<name>.aimodel/` (`main.mlirb` β‰ˆ 3.64 GB, `main.hash`, asset
71
- `metadata.json`), a bundle-level `metadata.json`, and `tokenizer/`
72
- (`tokenizer.json`, `tokenizer_config.json`, `generation_config.json`,
73
- `chat_template.jinja`).
74
-
75
- **The three folders hold the same weights.** `--max-ctx` does not change the exported
76
- graph β€” function signatures, state descriptors and peak export RSS are identical at 4096,
77
- 8192 and 16384. It changes exactly one thing: `language.max_context_length` in the bundle
78
- manifest. This was proved three ways, including a same-config control re-export whose
79
- `main.mlirb` differed from its twin by *more* bytes than a 4096β†’8192 pair does
80
- (conversion is not byte-deterministic; the context delta is inside that noise floor). Pick
81
- the folder whose manifest integer matches the window you intend to run, or edit the
82
- integer β€” you do not need a new conversion for a context bump.
83
-
84
- The small byte differences between the three folders are conversion nondeterminism, not
85
- content.
86
 
87
  ## Requirements
88
 
89
- - **Apple silicon Mac**, Core AI runtime. Nothing here runs on Linux or on Intel.
90
  - **Engine contract: 2 inputs.** `input_ids`, `position_ids` β†’ logits. No static inputs, no
91
  per-step mask. Runs on both the pipelined engine and the sequential (logits-capable)
92
  engine, which is what makes grammar-constrained decoding available.
@@ -98,61 +91,73 @@ content.
98
  268 MB at 16384.
99
  - **Memory envelope, 16 GB Mac** (Metal `recommendedMaxWorkingSetSize` β‰ˆ 10.7 GB):
100
  weights 3.64 GB resident, so KV is not the binding constraint at any context this bundle
101
- declares. Measured peak RSS on the qualification run was **4.43 GB**.
102
- - `runtime_env COREAI_CHUNK_THRESHOLD=1` travels with the recipe.
 
 
103
 
104
- ## Measured performance
105
 
106
- Measured on a **16 GB M2 Pro Mac (macOS 27 beta)** with the out-of-process `coreai-repro`
107
- harness: 10 real enrichment rows (5 POST, 5 COMMENT) from Visible's prompt corpus, the
108
- app's live `app_litert` JSON schema, greedy decoding through `respondJSON(to:schema:)`,
109
- `reset()` per row, sequential engine, 128-token cap. Load time excluded from `s/row`; row 1
110
- of each run excluded as a cache-warm outlier.
111
 
112
  | | |
113
  |---|---|
114
- | Cold load | 39.5 s |
115
  | Guided JSON parse | **10/10** |
116
- | s/row | **3.62** (POST) / **3.04** (COMMENT) |
117
- | Peak RSS | 4.43 GB |
118
- | Stop token | `<\|im_end\|>`, clean self-stop on every row |
119
-
120
- For scale within this catalog on the same harness and machine: LFM2.5-350M runs
121
- 0.79/0.51 s/row, LFM2.5-1.2B 1.77/1.30 s/row. The 2.6B is β‰ˆ2Γ— the 1.2B, which is what its
122
- parameter count predicts, and it produces the most specific `summary`/`context` fields of
123
- the three.
124
-
125
- A note on a figure that circulated internally: "1.75 s posts / 1.20 s comments" is the
126
- **1.2B's** number, not this model's. Plan the quality tier against 3.0–3.6 s/row.
127
-
128
- Nothing above was measured at 8192 or 16384 context; the `ctx8192`/`ctx16384` folders carry
129
- the 4096 folder's graph, so throughput should be unchanged, but quality and memory at depth
130
- are unmeasured.
131
-
132
- ## Qualification status
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
  | Artifact | Status |
135
  |---|---|
136
- | `gpu-pipelined/…_mf64` (ctx 4096) | **SHIP** β€” measured on the harness above and selected by the Visible app as its quality tier |
137
- | `ctx8192/…_mf64` | **QUALIFIED BY EQUIVALENCE, UNMEASURED AT DEPTH** β€” byte-equivalent weights and an identical graph to the shipping bundle; no run has been made at >4096 tokens |
138
- | `ctx16384/…_mf64` | **QUALIFIED BY EQUIVALENCE, UNMEASURED AT DEPTH** β€” as above |
139
-
140
- ## Verification
141
-
142
- - **Producer fingerprint:** every inner `<name>.aimodel/metadata.json` reads
143
- `producer: "coreai-core 1.0.0b2"`. This matters: `coreai-torch 0.4.0` / `coreai-core
144
- 1.0.0b1` produce bundles that abort in-process at load and take the host application down
145
- uncatchably. The fingerprint lives in the **inner asset** metadata, not the bundle
146
- manifest β€” the manifest never carries a `producer` field, for good and bad bundles alike.
147
- - **Stop token:** `tokenizer_config.json` declares `eos_token = "<|im_end|>"` in all three
148
- folders, verified. LFM bundles need no stop-token correction (unlike Gemma 4).
149
- - **Determinism:** `.aimodel` conversion is **not byte-reproducible**. Two runs of the same
150
- command minutes apart on the same box differ in `main.mlirb`. The tokenizer half *is*
151
- reproducible. So integrity for these bundles rests on per-file SHA-256 of the exact
152
- published artifact, never on rebuilding and comparing hashes.
153
- - No oracle or PSNR gate has been run against a PyTorch reference for this bundle. The
154
- qualification above is behavioural (parse rate, enum conformance, content sanity, clean
155
- stop) on Visible's own task, not a numerics gate.
156
 
157
  ## License
158
 
@@ -161,5 +166,5 @@ bundles are a derivative of that checkpoint and the same licence and its obligat
161
  with them β€” see the
162
  [upstream licence](https://huggingface.co/LiquidAI/LFM2.5-2.6B/blob/main/LICENSE). Anyone
163
  redistributing these files should redistribute the licence with them and comply with its
164
- terms. Nothing here relicenses Liquid AI's weights; Visible's contribution is the
165
- conversion recipe and the qualification evidence.
 
17
 
18
  # LFM2.5-2.6B β€” Core AI (.aimodel)
19
 
20
+ `LiquidAI/LFM2.5-2.6B` converted to Core AI `.aimodel` bundles for Apple silicon by
21
+ [visible-cx](https://huggingface.co/visible-cx). These are derivative artifacts: Liquid
22
+ AI's weights re-expressed as a Core AI graph with int8 block-32 symmetric weight
23
+ quantization and a two-entrypoint (decode + chunked-prefill) function map. They load
24
+ through Core AI on macOS and are not usable by PyTorch, GGUF or MLX.
 
25
 
26
+ Of the dense LFM2.5 bundles published here, this is the strongest on guided
27
+ structured-output work and the only one qualified for long context: **3/3 verbatim needle
28
+ recall at 14,566 tokens, sustaining 32 tok/s for under half a gigabyte of in-process
29
+ footprint.**
30
 
31
  ## Provenance
32
 
 
36
  | Recipe | `export_lfm2_multifunction.py int8hu --head-sym --chunk 64` |
37
  | Toolchain base | `apple/coreai-models` @ `b1cb71b8522d99408059fa0b98b8742171bcb0b8` + the [coreai-model-zoo](https://github.com/john-rocky/coreai-model-zoo) python overlay |
38
  | Toolchain | `coreai-torch 0.4.1`, `coreai-core 1.0.0b2`, `coreai-opt 0.2.1`, `torch 2.9.0` |
39
+ | Producer fingerprint | `coreai-core 1.0.0b2` on every inner `<name>.aimodel/metadata.json` |
40
  | Weight format | int8, per-K-block-32, symmetric; symmetric head (`--head-sym`) |
41
  | Vocab | 128,000 |
42
+ | Export functions | `main` (S=1 decode) + `prefill` (S=64 chunked prefill), `function_map: {"main": ["main", "prefill"]}`, weights deduplicated across entrypoints |
43
 
44
+ `mf64` in the bundle name means multifunction with a 64-wide prefill; the prefill function
45
+ costs well under a megabyte.
 
 
46
 
47
+ **Chat template.** LFM2.5-2.6B is an always-thinking model. The template shipped in every
48
+ bundle here **terminates the reasoning block in the generation prompt**:
 
 
 
49
 
50
  ```jinja
51
  {{- "<|im_start|>assistant\n<think></think>\n" -}}
52
  ```
53
 
54
+ An unterminated block (`…assistant\n<think>`) causes the model to spend the entire
55
+ generation budget inside `<think>`, which a host routes to a reasoning channel and never to
56
+ the response β€” 684–919 tokens per item, with no visible output. If you rebuild from the
57
+ recipe, apply the same termination.
58
 
59
  ## Contents
60
 
 
65
  | `ctx16384/gpu-pipelined/lfm2_5_2_6b_decode_int8hu_block32_sym_mf64` | 3,655,243,498 | 16384 | main + prefill |
66
 
67
  Each folder holds `<name>.aimodel/` (`main.mlirb` β‰ˆ 3.64 GB, `main.hash`, asset
68
+ `metadata.json`), a bundle-level `metadata.json`, and `tokenizer/` (`tokenizer.json`,
69
+ `tokenizer_config.json`, `generation_config.json`, `chat_template.jinja`).
70
+
71
+ **The three folders hold the same weights and the same graph** β€” function signatures, state
72
+ descriptors and peak export RSS are identical at 4096, 8192 and 16384. `--max-ctx` changes
73
+ exactly one thing: `language.max_context_length` in the bundle manifest. The small byte
74
+ differences between folders are conversion nondeterminism, not content. Pick the folder
75
+ whose manifest integer matches the window you intend to run.
76
+
77
+ **Stop token:** `eos_token = "<|im_end|>"` in all three folders. Clean self-stop on every
78
+ measured sample.
 
 
 
 
79
 
80
  ## Requirements
81
 
82
+ - **Apple silicon Mac**, Core AI runtime.
83
  - **Engine contract: 2 inputs.** `input_ids`, `position_ids` β†’ logits. No static inputs, no
84
  per-step mask. Runs on both the pipelined engine and the sequential (logits-capable)
85
  engine, which is what makes grammar-constrained decoding available.
 
91
  268 MB at 16384.
92
  - **Memory envelope, 16 GB Mac** (Metal `recommendedMaxWorkingSetSize` β‰ˆ 10.7 GB):
93
  weights 3.64 GB resident, so KV is not the binding constraint at any context this bundle
94
+ declares. Measured max RSS **6.71 GB** on guided decoding and 7.30 GB at 15k context;
95
+ peak in-process footprint 0.48 GB and 0.46 GB respectively β€” essentially flat in context.
96
+ **Minimum practical machine memory: 16 GB**, at any declared context including 16384.
97
+ - The bundle manifest declares `runtime_env COREAI_CHUNK_THRESHOLD=1`.
98
 
99
+ ## Performance
100
 
101
+ Measured on a **16 GB Apple silicon Mac (M2 Pro, macOS 27 beta)**: 10-sample harness,
102
+ guided JSON-constrained decoding against a fixed schema, greedy, sequential engine,
103
+ `reset()` between samples, 128-token cap. Load excluded from `s/row`; sample 1 excluded as
104
+ a cache-warm outlier.
 
105
 
106
  | | |
107
  |---|---|
108
+ | Cold load | 18.4 s |
109
  | Guided JSON parse | **10/10** |
110
+ | Enum-clean | **10/10** |
111
+ | s/row (long samples) | **3.66** |
112
+ | s/row (short samples) | **3.06** |
113
+ | Decode | **38.1–40.0 tok/s** |
114
+ | TTFT | **0.47–2.29 s** |
115
+ | Peak footprint | 0.48 GB |
116
+ | Max RSS | 6.71 GB |
117
+
118
+ For scale on the same machine and harness: LFM2.5-350M runs 0.84/0.55 s/row and
119
+ LFM2.5-1.2B 1.89/1.37 s/row. The 2.6B is β‰ˆ2Γ— the 1.2B, which is what its parameter count
120
+ predicts, and it produces the most specific free-text fields of the three.
121
+
122
+ ### Long context
123
+
124
+ **Needle-in-haystack: 3/3 verbatim at both 8k and 15k.** Three distinctive facts planted at
125
+ 10% / 50% / 90% of the filler, strict scoring (a fact counts only if the distinctive entity
126
+ comes back correct). All three returned at 7,813 tokens and all three at 14,566 tokens,
127
+ verbatim, including the date.
128
+
129
+ | probe | prompt tokens | TTFT | decode | wall | peak footprint |
130
+ |---|---|---|---|---|---|
131
+ | needle 8k | 7,813 | 13.78 s | 35.8 tok/s | 15.4 s | 0.34 GB |
132
+ | needle 15k | 14,566 | 27.42 s | **32.2 tok/s** | 29.1 s | 0.46 GB |
133
+
134
+ Free-form generation from a fixed prompt at three depths, 900-token cap (the model
135
+ self-stopped inside it every time):
136
+
137
+ | depth | prompt tokens | TTFT | decode | generated | wall | peak footprint |
138
+ |---|---|---|---|---|---|---|
139
+ | 3.4k | 3,249 | 6.88 s | 35.3 tok/s | 847 | **29.5 s** | 0.28 GB |
140
+ | 8k | 7,673 | 14.84 s | 36.6 tok/s | 715 | **36.0 s** | 0.47 GB |
141
+ | 12k | 11,643 | 22.24 s | **32.9 tok/s** | 743 | **44.4 s** | 0.46 GB |
142
+
143
+ **Decode barely moves with depth.** 40.0 tok/s at 2.3k β†’ 35.3 at 3.2k β†’ 36.6 at 7.7k β†’
144
+ 32.9 at 11.6k: an 18% decay across a 5Γ— context increase. It sustains 32–33 tok/s at
145
+ 11.6–14.5k tokens with under half a gigabyte of in-process footprint. High context costs
146
+ prefill time and almost nothing else β€” TTFT scales cleanly (4.8 β†’ 6.9 β†’ 14.8 β†’ 22.2 β†’
147
+ 27.4 s) while footprint stays flat. The KV term is `GrowingKVCache`-dynamic and small at
148
+ this size (16 KB/token β†’ 268 MB at 16384).
149
+
150
+ ## Status
151
 
152
  | Artifact | Status |
153
  |---|---|
154
+ | `gpu-pipelined/…_mf64` (ctx 4096) | **SHIP** β€” measured: 10/10 guided parse and enum-clean, 3.66/3.06 s/row, 38.1–40.0 tok/s. |
155
+ | `ctx8192/…_mf64` | **QUALIFIED AT DEPTH** β€” same weights and graph; measured: 3/3 verbatim needle recall at 7,813 tokens, 36.6 tok/s at 8k, 0.47 GB peak footprint. |
156
+ | `ctx16384/…_mf64` | **QUALIFIED AT DEPTH** β€” 3/3 verbatim needle recall at 14,566 tokens at 32.2 tok/s, 0.46 GB peak footprint, 7.30 GB max RSS. Recommended for long-context work. |
157
+
158
+ No oracle or PSNR gate has been run against a PyTorch reference. Qualification is
159
+ behavioural (parse rate, enum conformance, content sanity, clean stop, needle recall), not
160
+ a numerics gate.
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
162
  ## License
163
 
 
166
  with them β€” see the
167
  [upstream licence](https://huggingface.co/LiquidAI/LFM2.5-2.6B/blob/main/LICENSE). Anyone
168
  redistributing these files should redistribute the licence with them and comply with its
169
+ terms. Nothing here relicenses Liquid AI's weights; the contribution is the conversion
170
+ recipe and the qualification evidence.