Skip to content

Commit 9c7f6e9

Browse files
rhenley1958claude
andcommitted
docs(ft-recursive-002): Epic 6 convert + gate stages VALIDATED — full pipeline runs end-to-end
CONVERT (E6-4): fuse --dequantize (28GB bf16) -> convert_hf_to_gguf f16 (30GB) -> llama-quantize Q5_K_M (11GB candidate). E6-14: dequantize required (4bit fused model can't GGUF-convert directly). GATE (E6-3): candidate served on side-port :18102 (/health 200), run_benchmark makes real calls (1428 server call lines, non-zero — passes the no-zero-call discipline). All four pipeline stages (export->curate->train->convert->gate) now validated end-to-end with real production data. Remaining: wire the proven commands into the controller. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent f26c1ef commit 9c7f6e9

1 file changed

Lines changed: 4 additions & 2 deletions

File tree

docs/development/ft-recursive-002/epic6_issues.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ llama-server `:8102` → 200; `consulting.classify` Ready (4782 rows).
1212
|---|---|---|---|
1313
| E6-1 | `execPythonStage` uses `FT_LOOP_PYTHON_BIN` default `python3` (system) — the training toolchain (`mlx_lm`) lives in `neural/.venv`; a real run needs the venv interpreter. | `ftloop/controller.go` | **[FIXED]** `resolvePython()` prefers `neural/.venv/bin/python`. **Live-validated:** curate ran the module (error was its usage message). |
1414
| E6-2 | One `RepoDir` for all stages, but `python -m training.X` needs cwd `neural/` while `python -m neural.benchmarks.X` needs the repo root. | `ftloop/controller.go::execPythonStage` | **[FIXED]** `stageDir()` per-stage cwd. **Live-validated** (module resolved from `neural/`). |
15-
| E6-3 | Stage arg-sets are placeholders. Real: curate needs `--spec/--input-dir/--output-dir/--version`; train needs `--tier/--mode/--base-model/--expected-sha256/--dataset/--adapter-path/--rank/--alpha/--n-epochs`; gate needs `--config/--out/--model`. **Live-confirmed:** curate failed exit-2 on the missing required args (the FAIL path). | `ftloop/controller.go` | **[curate + train VALIDATED]** convert/gate + controller wiring [6b-continuation] |
16-
| E6-4 | No MLX→GGUF conversion stage between train and gate (the run_record rule: candidate evals always use the GGUF form). | controller pipeline | [6b-followup] add a convert stage |
15+
| E6-3 | Stage arg-sets are placeholders. Real: curate needs `--spec/--input-dir/--output-dir/--version`; train needs `--tier/--mode/--base-model/--expected-sha256/--dataset/--adapter-path/--rank/--alpha/--n-epochs`; gate needs `--config/--out/--model`. **Live-confirmed:** curate failed exit-2 on the missing required args (the FAIL path). | `ftloop/controller.go` | **[curate + train + convert + gate ALL VALIDATED]** controller wiring [6b-continuation] |
16+
| E6-4 | No MLX→GGUF conversion stage between train and gate (the run_record rule: candidate evals always use the GGUF form). | controller pipeline | **[VALIDATED]** fuse --dequantize→convert_hf_to_gguf→llama-quantize Q5_K_M produces the 11GB candidate; gate serves it on a side-port + run_benchmark makes real calls |
1717
| E6-5 | Curate `--input-dir` (exported JSONL) has no producer in the loop — the controller must run `mdemg data export` (or read TSDB) to materialize the curate input. | controller pipeline | **[SOLVED]** `mdemg data export --tables llm_interactions[,…] --since … --output <tar>` → extract `llm_interactions.jsonl` into `<input-dir>/`. The export schema matches `quality_filter`'s `TEXT_FIELDS` exactly. |
1818

1919
| E6-8 | **Train base-model SHA pin is STALE (drift-guard rot).** `train_ft.SPRINT_C_CONFIG_SHA = cdc167566e…` but upstream `mlx-community/Qwen3-14B-4bit` `config.json` is now `a54ec18f…` (re-published since the pin). A real retrain **drift-aborts**. Verified: the current upstream config is **byte-identical** to the local production model's config (`qwen3-14b-mdemg-v1`), so the base is functionally the production base; the pin just rotted. Same class as the run_record's "configs rot at cutovers" — now for the base-model pin. | `neural/training/train_ft.py:83`; `expert_selection.py:10` | **[decision]** update the pin to `a54ec18f…` (safe — identical to production) **or** pin to a specific HF revision. A deliberate provenance call (the pin is a drift-guard) — surfaced, not silently bypassed. |
@@ -62,3 +62,5 @@ alerts, lease acquire/release, SF-2 + interval suppression, E6-1/E6-2.
6262
arg-sets + the train→convert→gate artifact chain) — the focused 6b continuation.
6363

6464
| E6-13 | **Training on the dev box is very slow + degrades the live server.** With the mdemg server + neo4j running, mlx_lm.lora hit **~52 s/iter** (It/sec 0.019), peak 23.6 GB, and starved llama-server `:8102` → HIGH `jiminy.evaluate_llm` timeouts. A full 1-epoch run on 4660 rows (1165 iters) would be ~17 h at this rate; even a 50-iter subset is ~43 min. The controller's `Quiesce` pauses RSIC LLM fan-out but the server+neo4j load remains. | live (M5 Max) | **[viability]** a real retrain wants the box mostly idle (or dedicated/off-peak); consider the loop scheduling retrains during quiet windows, and/or a smaller per-cycle row budget. Pipeline-mechanics validation uses a tiny subset (quality irrelevant for convert/gate). |
65+
66+
| E6-14 | **Convert must dequantize first.** `convert_hf_to_gguf.py` on a 4bit-fused MLX model fails (`Can not map tensor 'model.embed_tokens.biases'` — MLX 4bit quant tensors). The convert stage MUST `mlx_lm.fuse --dequantize` → bf16 HF safetensors → `convert_hf_to_gguf --outtype f16``llama-quantize Q5_K_M` (the CLAUDE.md path; ~85GB transient). | convert stage | [6b-continuation] wire the 3-step dequantize→gguf→quantize convert; confirmed required |

0 commit comments

Comments
 (0)