Merge nucleic/eager-glass-wren-mrb5 into dev
This commit is contained in:
+81
-25
@@ -43,10 +43,12 @@ is a classic small-model problem.
|
||||
classifier is exactly the energy bill this policy exists to avoid. Both shipped models
|
||||
are *designed for accelerator eligibility from day one* (fixed shapes, fp16-friendly
|
||||
ops — §4.2), and scheduling is verified, not assumed (§8).
|
||||
6. **Two model sizes, one contract:** a **light** classifier every machine can run, and a
|
||||
**deep** classifier (§4.3) that meaningfully exploits ANE/NPU headroom for higher
|
||||
accuracy on the ambiguous prompts the light model gets wrong. Same labels, same
|
||||
calibration semantics, same wire — machines differ only in which artifact answers.
|
||||
6. **A model ladder, one contract:** a **light** classifier every machine can run, a
|
||||
**deep** classifier (§4.3) that exploits ANE/NPU headroom for higher accuracy on the
|
||||
ambiguous prompts the light model gets wrong, and a **max** classifier (§4.4) that
|
||||
spends big-GPU headroom (RTX/Radeon-class, AC power only) on the best result the
|
||||
hardware can deliver. Same labels, same calibration semantics, same wire — machines
|
||||
differ only in which artifact answers.
|
||||
7. **No architectural churn:** the classifier slots into the existing layer stack behind
|
||||
`PurposeVerdict.Source`; routing, session plumbing, UI, and wire stay as shipped.
|
||||
|
||||
@@ -178,11 +180,12 @@ runs quantized **7B** LLMs at usable rates ([NPU comparison](https://localaimast
|
||||
the ANE side routinely serves Apple's ~3B foundation model. So the deep model is sized by
|
||||
*task saturation*, not by hardware: past roughly half a billion parameters, **encoder**
|
||||
accuracy on a fixed 8-way task flattens, and the next meaningful step up is a 1–3B
|
||||
generative decoder — rejected, because it reintroduces exactly what this plan removes
|
||||
(uncalibrated generation, hundreds of ms, GB-scale memory residency) for negligible
|
||||
classification gain. Target ship size: **large-class encoder, ~400M params**, decided by
|
||||
ablation (below), with the older base size kept as a pipeline ablation rung rather than a
|
||||
shipping artifact.
|
||||
generative decoder — rejected *as the default path*, because it reintroduces exactly what
|
||||
this plan removes (uncalibrated generation, hundreds of ms, GB-scale memory residency)
|
||||
for negligible classification gain on ordinary machines. (§4.4 revisits the decoder under
|
||||
strict constraints as the optional GPU-max tier.) Target ship size for deep: **large-class
|
||||
encoder, ~400M params**, decided by ablation (below), with the older base size kept as a
|
||||
pipeline ablation rung rather than a shipping artifact.
|
||||
|
||||
- **Architecture:** ModernBERT-class encoder, **large size (~400M params; ~150M base
|
||||
variant trained as an ablation rung)**, **512-token window** (the hard cases are long —
|
||||
@@ -212,16 +215,59 @@ shipping artifact.
|
||||
- **Same export discipline as 4.2:** fixed 1×512-token shape, fp16 (+ int8-QDQ variant),
|
||||
both ONNX and Core ML artifacts, same tokenizer spec, same threshold JSON schema.
|
||||
- **Model selection at runtime** (per machine, decided once per launch and re-checked on
|
||||
asset/hardware change):
|
||||
- deep model present **and** verified accelerator-resident (§5/§6 checks) → **deep is
|
||||
the L1 classifier**; lite stays loaded as the instant-answer for the first keystrokes
|
||||
if deep's asset is still warming;
|
||||
asset/hardware/power change):
|
||||
- max model present **and** its §4.4 eligibility holds (verified GPU rung + memory
|
||||
floor + AC power) → **max is the L1 classifier**;
|
||||
- else deep model present **and** verified accelerator-resident (§5/§6 checks) →
|
||||
**deep is L1**; lite stays loaded as the instant-answer for the first keystrokes
|
||||
if the bigger asset is still warming;
|
||||
- otherwise → lite is L1 (which is already ≥ the current AFM path).
|
||||
Power transitions re-run this ladder live: unplugging mid-session steps max → deep
|
||||
seamlessly (next debounce tick answers on the smaller model).
|
||||
A cascade variant (lite always answers; deep re-scores only low-margin drafts) is the
|
||||
fallback posture if deep-everywhere measures worse on energy than expected — the
|
||||
layering makes either wiring a one-line change in `PromptPurposeService`.
|
||||
|
||||
### 4.4 Artifacts, conversion, versioning
|
||||
### 4.4 The GPU-max classifier (`purpose-max`) — spending real GPU headroom
|
||||
|
||||
§4.3's sizing argument stands: past ~0.5B parameters, a *bigger encoder* buys latency,
|
||||
not accuracy. So the tier above deep-large is not a larger encoder — it is a **different
|
||||
kind of model** that only RTX/Radeon-class (or big-unified-memory Apple GPU) headroom
|
||||
makes viable: a small **instruction-tuned decoder used as a constrained classifier**.
|
||||
This deliberately *revisits* §2's decoder rejection, which was a rejection for the
|
||||
*default* path (uncalibrated free generation, hundreds of ms, GB-scale residency on
|
||||
every machine). Under the max tier's constraints, each objection is answered rather than
|
||||
waved off:
|
||||
|
||||
- **Architecture:** a 1.5–4B instruction-tuned decoder (Qwen/Phi-class), LoRA-fine-tuned
|
||||
on the same dataset and merged. Classification is **not free generation**: one prefill
|
||||
over the 512-token head + a single constrained step with the logits masked to the 8
|
||||
label tokens — the masked-label distribution is the output, temperature-scaled on the
|
||||
validation split exactly like the encoders (this restores the calibration story the §2
|
||||
rejection was about). Secondary-purpose and difficulty ride the same masked readout.
|
||||
- **What it buys beyond accuracy:** a short *generated* rationale (one clause, capped
|
||||
tokens) for the chip tooltip — a per-prompt "why", where the encoders can only attach
|
||||
canned per-cell copy. Generation of the rationale is optional, async after the label,
|
||||
and never on any routing path.
|
||||
- **Eligibility (all required):** a verified GPU rung per §5/§6 (NvTensorRT-RTX /
|
||||
MIGraphX / OpenVINO-GPU on Windows, Apple GPU on macOS) **and** a memory floor
|
||||
(≥ 6 GB dedicated VRAM, or ≥ 24 GB unified memory on Apple silicon) **and AC power**.
|
||||
On battery the ladder drops to deep on the ANE/NPU automatically — max is a
|
||||
wall-power luxury by definition, and the power-transition listener swaps tiers live
|
||||
(mid-draft transitions just change which model answers the next debounce tick).
|
||||
- **Artifacts:** int4/int8 quantized, ~1–2.5 GB — a separately downloaded optional asset
|
||||
("best on this machine" offer in Settings › Intelligence, never auto-downloaded).
|
||||
Export uses the generative stacks (ONNX Runtime GenAI format for Windows ML's runtime;
|
||||
a stateful Core ML model on macOS) — meaningfully more export complexity than the
|
||||
encoders, which is why max is its own late work item and not on deep's critical path.
|
||||
- **Budgets & gates:** label p95 ≤ 250 ms on the eligibility-floor GPU (still well inside
|
||||
the debounce window; rationale generation excluded from the budget); ships only on a
|
||||
**≥ +2-point hard-slice win over deep-large** — if constrained decoding can't beat the
|
||||
large encoder where it matters, max doesn't exist and the doc's saturation argument was
|
||||
simply right; idle-unload is mandatory (a multi-GB resident model must never outlive
|
||||
composer attention, and must never keep a dGPU awake).
|
||||
|
||||
### 4.5 Artifacts, conversion, versioning
|
||||
|
||||
- **Canonical artifact: ONNX** (opset ≥ 17), one file, one tokenizer spec (exported
|
||||
vocab + normalization rules — no runtime HuggingFace dependency).
|
||||
@@ -231,9 +277,10 @@ shipping artifact.
|
||||
the frozen test set; label agreement ≥ 99.5% and identical accuracy-to-the-gate, or the
|
||||
conversion is rejected (this is what makes "one model, two runtimes" honest).
|
||||
- **Windows runtime:** the ONNX artifact as-is, via Windows ML (§6).
|
||||
- **Naming:** `purpose-lite-v<N>` / `purpose-deep-v<N>` with `.onnx` (canonical, per-EP
|
||||
quantization variants) and `.mlmodelc` (converted) suffixes.
|
||||
- **Versioning:** artifacts named `purpose-<lite|deep>-v<N>.<onnx|mlmodelc>`; the version
|
||||
- **Naming:** `purpose-lite-v<N>` / `purpose-deep-v<N>` / `purpose-max-v<N>` with `.onnx`
|
||||
(canonical, per-EP quantization variants; GenAI-format for max) and `.mlmodelc`
|
||||
(converted) suffixes.
|
||||
- **Versioning:** artifacts named `purpose-<lite|deep|max>-v<N>.<…>`; the version
|
||||
string rides `PurposeVerdict.reason` provenance and the session routing note, so field
|
||||
behavior is attributable to a model version. Old artifact kept for one release for a fast
|
||||
revert (`nucleic.purposeClassifierVersion` defaults key as the pin/kill switch).
|
||||
@@ -396,11 +443,16 @@ path to the slider later, for free.
|
||||
2. **Tier-drift invariant** re-run over *model* predictions (not just heuristics), for
|
||||
both models: every test-set misroute within one cost tier at all levels/lanes — and for
|
||||
deep's mixed-intent path, the primary+secondary blend rule proven to stay in-bound.
|
||||
3. **Parity gates:** Core ML↔ONNX label agreement ≥ 99.5% per model (§4.4); C#↔Swift
|
||||
threshold config is one shared JSON so acceptance semantics can't fork.
|
||||
4. **Latency:** lite p95 ≤ 20 ms; deep p95 ≤ 100 ms *on the accelerator it's gated to*
|
||||
(still several debounce ticks under the 700 ms window, and never on the send path).
|
||||
Measured in eval.py and asserted loosely in a perf smoke test.
|
||||
3. **Parity gates:** Core ML↔ONNX label agreement ≥ 99.5% per model (§4.5); C#↔Swift
|
||||
threshold config is one shared JSON so acceptance semantics can't fork. For max, the
|
||||
masked-label readout must additionally pass a calibration bound (ECE ≤ lite's on the
|
||||
validation split) — a decoder that classifies better but *confides* worse would poison
|
||||
the accept/corroborate/escalate contract.
|
||||
4. **Latency:** lite p95 ≤ 20 ms; deep p95 ≤ 100 ms *on the accelerator it's gated to*;
|
||||
max label-readout p95 ≤ 250 ms on the eligibility-floor GPU (rationale generation
|
||||
excluded — async, off every routing path). All still several debounce ticks under the
|
||||
700 ms window, and never on the send path. Measured in eval.py and asserted loosely in
|
||||
a perf smoke test.
|
||||
5. **Accelerator-residency gates** (goal #5 made falsifiable):
|
||||
- macOS: `MLComputePlan` ANE-op share ≥ the per-artifact floor emitted at conversion,
|
||||
checked at load on-device (rung fallbacks per §5 — the GPU retry must itself pass a
|
||||
@@ -419,7 +471,9 @@ path to the slider later, for free.
|
||||
cycle with A/B logging *locally* (both verdicts recorded in the routing note's reason);
|
||||
flip default on when disagreement analysis shows the model ≥ AFM on real drafts; remove
|
||||
the AFM layer (L2 demotion, §5) after two clean releases. Deep rolls out behind the
|
||||
same telemetry one cycle after lite.
|
||||
same telemetry one cycle after lite; max one cycle after deep, and only if its §4.4
|
||||
hard-slice-over-deep-large gate held on the frozen set (a tier that can't beat the one
|
||||
below it is deleted, not shipped).
|
||||
|
||||
---
|
||||
|
||||
@@ -476,8 +530,10 @@ path to the slider later, for free.
|
||||
| 7 | Windows ML runtime (with the port's §7 renderer) | `PurposeClassifier.cs` (Windows App SDK 1.8.1+, power-source-aware policy ladder — `MAX_EFFICIENCY` on battery; NPU→GPU (NvTensorRT-RTX/MIGraphX/OpenVINO-GPU)→CPU on AC — explicit-EP validation path, AOT compile-at-first-use), shared threshold JSON, degradation ladder |
|
||||
| 8 | `purpose-deep` training + heads | ModernBERT-class multi-task checkpoints at base (~150M) *and* large (~400M), 512-token window, ≤ 850 MB fp16 / ≤ 450 MB int8 artifacts, hard-slice +5pt-over-lite and large-vs-base ablation gates, mixed-intent blend rule in router + tests |
|
||||
| 9 | Deep-model distribution + selection | on-demand asset download/verify/pin (macOS-VM base-image pattern), §4.3 runtime selection ladder, accelerator-residency gating on both platforms, Settings download affordance |
|
||||
| 10 | Rollout | dark-ship + local A/B logging, lite default flip, deep one cycle later, AFM layer retirement |
|
||||
| 10 | Rollout | dark-ship + local A/B logging, lite default flip, deep one cycle later, max one after that, AFM layer retirement |
|
||||
| 11 | `purpose-max` (optional tier, after 8–9 prove out) | 1.5–4B LoRA-fine-tuned decoder, masked-label constrained readout + calibration, GenAI-format ONNX + stateful Core ML exports, GPU+memory+AC eligibility gating with live power-transition stepping, async rationale generation, idle-unload |
|
||||
|
||||
Items 1–5 are independent of the Windows port's schedule; 6 can land any time (additive);
|
||||
7 rides the port's renderer milestone; 8–9 start once item 5's hard slice exists (deep's
|
||||
gate is defined against it).
|
||||
gate is defined against it); 11 starts only after deep ships and holds its gates — max is
|
||||
an *optional* crown, not a dependency of anything.
|
||||
|
||||
Reference in New Issue
Block a user