Views
No views yet
Training
below and generate_voice_intent.py for the fix in detail.Training below.cipher-nano / cipher-air / cipher-pro) — a balanced default at 40% of cipher-pro's disk size and 3x the throughput. Cipher is the local-model engine for an unreleased larger email-assistant project — that project isn't public yet, but these weights, the training code, the eval script, and all five dataset generators are fully open now, in this repo.cipher-air.Q4_K_M.gguf — the model weights, ready for OllamaModelfile — the exact Ollama Modelfile (system prompt + inference params) used in training/evaltrain_cipher_air.py / export_gguf_cipher_air.py — the exact scripts used to produce this model (Unsloth LoRA on the base model above)generate2.py, generate_chat.py, generate_daily_summary.py, generate_draft_reply.py, generate_compose.py, generate_voice_intent.py — the six task-specific synthetic-data generators (produces the full multi-task training set)eval_voice_intent.py — regression harness for the voice-intent task, including the exact hallucinated-address bug case as a required fixtureeval_triage.py / eval_fixtures.json — a standalone benchmark harness (no external dependencies beyond httpx/pydantic) reproducing the numbers below| Model | Disk | Tok/s | JSON-valid | Category acc | Importance-in-band | Injection-safe |
|---|---|---|---|---|---|---|
| cipher-air | 398 MB | 507.8 | 100.0% | 69.0% | 79.3% | 100% |
cipher-pro and cipher-nano both handle that nuance more reliably. Reproduce
with:1pip install -r requirements.txt
2python eval_triage.py --models cipher-air:latest --keepollama create cipher-air -f Modelfile1curl http://localhost:11434/api/chat -d '{
2 "model": "cipher-air",
3 "messages": [
4 {"role": "system", "content": "<system prompt from Modelfile>"},
5 {"role": "user", "content": "From: alex@acme.com\nSubject: Q3 budget review\n\nBody:\nCan we sync before Friday?"}
6 ],
7 "format": "json",
8 "options": {"temperature": 0.1}
9}'Qwen/Qwen2.5-0.5B-Instruct, LoRA (r=16, alpha=32, all linear layers), 2 epochsgenerate_*.py scripts in this repotrl.SFTTrainertrain_cipher_air.py → export_gguf_cipher_air.pygenerate_voice_intent.py, weighted
heavily toward the no-match case (a spoken name with no corresponding candidate address —
the model must return null rather than inventing one) and matching-with-distractors
cases. On eval_voice_intent.py's 5 fixtures, cipher-air went from 2/5 (including a
fabricated address and an out-of-schema action) to 5/5, the cleanest result of the
three tiers on this task.generate_draft_reply.py and
generate_chat.py both gained substantially heavier and more varied injection coverage
(credential/wire-transfer/data-exfiltration attempts, not just one generic case) after
live testing found the previous incremental-patch version could be induced into
complying with an injected "security verification" request for banking details.
generate_chat.py also gained an explicit "the question is about something with no
connection to your email at all (weather, sports, etc.)" scenario category after finding
a hallucination regression there. One clean training pass over the properly-balanced
result, instead of a chain of narrow continue-trains, avoids the whack-a-mole pattern
where each targeted fix risked nudging a different, previously-working case.cipher-nano's size class. It barely helped (355MB / 339MB vs 398MB at Q4_K_M) — Qwen2.5's 151,936-token vocabulary embedding table dominates disk size and doesn't compress with weight quantization. If you're looking for something genuinely small, use cipher-nano instead (different base model, built specifically to solve this).