Files

47 lines
3.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SPEC-lifecycle: Kandidaten, Graduierung, Training
Pakete: `knaster.lifecycle`, `knaster.graduation`.
## 1. Kandidat
```
id, kind: base_model | adapter | quantization | embedding_model | engine
slot: str # betroffener Slot (bei adapter: Slot, dessen Basis passt)
target: {...} # z. B. {base_model: "qwen3-14b-awq"} oder {cluster: "rechnungen"}
baseline: {pass_rate?} # Messwert der aktuellen Version
state, metrics{}, history[{ts, from, to, note}]
```
## 2. Zustände
```
proposed ──(Freigabe)──▶ building ──report(build_ok)──▶ evaluating
evaluating ──report(eval: pass_rate ≥ baseline − tolerance)──▶ shadow (sonst ▶ rejected)
shadow ──report(shadow: agreement ≥ min_agreement, n ≥ min_n)──▶ canary (sonst ▶ rejected)
canary ──report(canary: pass_rate ≥ baseline − tolerance, n ≥ min_n)──▶ awaiting_promotion (sonst ▶ rejected)
awaiting_promotion ──(Freigabe)──▶ promoted
promoted ──rollback──▶ rolled_back
jeder Zustand ──report(error)──▶ failed
```
Grenzwerte stehen in `config/lifecycle.yaml`: `tolerance` 0,02, `min_agreement` 0,85, `min_n` 50, `canary_share` 0,1.
Die Freigaben laufen über die Policy (`create_candidate`, `promote_candidate`). **Promote** schreibt in den Registry-Laufzeitzustand bzw. in die Adapterliste:
- `base_model`: Slot `base_model` wird umgestellt, alle Adapter der alten Basis werden `retired`, und für jeden Cluster mit Adapter entsteht ein Kandidat `adapter` (Neutraining).
- `adapter`: Der neue Adapter wird `active`, der bisher aktive für denselben Cluster und dieselbe Basis wird `retired` (bleibt als Rollback-Ziel erhalten).
- **Rollback** stellt den Zustand vor dem Promote wieder her (gespeichert in `history`).
Die Jobs selbst (Download, Quantisierung, Training, Eval) laufen **extern**, als Job-Runner auf `gpu-flex`. Sie melden ihr Ergebnis per `POST /v1/lifecycle/candidates/{id}/report`. Der `JobRunner` im Service stößt den Job an: Im Dry-Run wird nur protokolliert, sonst geht ein Webhook an n8n bzw. den Runner.
## 3. Graduierung (`knaster.graduation`)
`graduate(skill, variants[], run_fn, verify_fn, threshold=0.9, min_variants=10) -> GraduationReport`
- Jede Variante wird mit `stage = 1` auf dem Skill-Slot ausgeführt (`run_fn`) und geprüft (`verify_fn`).
- `passed = pass_rate ≥ threshold` und `n ≥ min_variants`.
- Bei Erfolg entsteht ein Vorschlag `promote_skill{skill, stage: 1}` (Policy: approve), bei Misserfolg ein Bericht mit den fehlgeschlagenen Varianten. Diese gehen an das starke Modell, das den Skill überarbeitet.
- Die Varianten erzeugt das starke Modell (Hermes) und schickt sie an `POST /v1/skills/{name}/graduate`.
## 4. Adapter-Training (extern, Vertrag)
Eingang für den Trainingsjob: Export `cases` (split = train, passed = true, skill.cluster = X) plus optional `preference_pairs`. Ausgang: Adapter-Verzeichnis und `report(build_ok, adapter_name)`. Die Eval nutzt die Fälle mit split = eval desselben Clusters.