Instructions to use srock44/cipher-nano with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use srock44/cipher-nano with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf srock44/cipher-nano:Q4_K_M # Run inference directly in the terminal: llama cli -hf srock44/cipher-nano:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf srock44/cipher-nano:Q4_K_M # Run inference directly in the terminal: llama cli -hf srock44/cipher-nano:Q4_K_M
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf srock44/cipher-nano:Q4_K_M # Run inference directly in the terminal: ./llama-cli -hf srock44/cipher-nano:Q4_K_M
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf srock44/cipher-nano:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf srock44/cipher-nano:Q4_K_M
Use Docker
docker model run hf.co/srock44/cipher-nano:Q4_K_M
- LM Studio
- Jan
- vLLM
How to use srock44/cipher-nano with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "srock44/cipher-nano" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "srock44/cipher-nano", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/srock44/cipher-nano:Q4_K_M
- Ollama
How to use srock44/cipher-nano with Ollama:
ollama run hf.co/srock44/cipher-nano:Q4_K_M
- Unsloth Studio
How to use srock44/cipher-nano with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for srock44/cipher-nano to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for srock44/cipher-nano to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for srock44/cipher-nano to start chatting
- Docker Model Runner
How to use srock44/cipher-nano with Docker Model Runner:
docker model run hf.co/srock44/cipher-nano:Q4_K_M
- Lemonade
How to use srock44/cipher-nano with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull srock44/cipher-nano:Q4_K_M
Run and chat with the model
lemonade run user.cipher-nano-Q4_K_M
List all available models
lemonade list
- Atomic Chat
Cipher Nano
Cipher Nano is a full-parameter fine-tune of h2oai/h2o-danube3-500m-chat, trained on every LLM-backed feature of a local-first email assistant: email triage (importance/summary/category JSON), chat, daily-summary synthesis, draft reply, compose assist, and voice-command intent parsing β not just prompted for these tasks, actually trained on them.
Update: added a 6th task, voice-command intent parsing. Nano's smaller full-fine-tune
capacity means it still sometimes substitutes a plausible-looking wrong address instead of
copying the real one verbatim from the candidate list β 3 rounds of targeted oversampling
narrowed but didn't eliminate this. The actual fix ended up being architectural, not a
bigger model: the calling app never trusts an LLM-supplied email address at all anymore,
re-deriving it deterministically in code from the model's extracted name against the real
candidate list instead. That makes this habit irrelevant regardless of which Cipher tier is
active β see generate_voice_intent.py's training notes and eval_voice_intent.py for the
full detail.
Second update: an incremental continue-training round aimed at voice-intent (done on top of the update above) turned out to have a side effect elsewhere: manual testing found this model would occasionally fabricate a specific false detail not present in its given context (e.g. inventing a person's surname that was never mentioned) on the chat task. Rather than patch that narrowly on top of an already-long chain of incremental updates, this model was retrained fresh from the base in one pass on a properly-rebalanced dataset covering all 6 tasks together, with substantially richer prompt-injection coverage across draft-reply and chat (credential-phishing, wire-transfer, and data-exfiltration attempts, not just one generic case) and an explicit "the question has nothing to do with your email at all" scenario category to close the specific hallucination gap that was found. Verified through repeated testing against the real calling application's code path: no compliance with any injection attempt, and the specific hallucination case now correctly reports the missing information instead of inventing it.
It's the smallest of the three Cipher tiers (cipher-nano / cipher-air / cipher-pro), built specifically to run on modest hardware β verified at 29.4 tok/s on a 10-year-old Intel i3-6100T with 8GB RAM, no GPU, with accuracy holding essentially flat versus a high-end GPU. 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.
Why this exists
Most email triage today means sending your inbox to a third-party API. Cipher runs entirely on your own hardware via Ollama β nothing about your email ever leaves your machine. Cipher Nano exists so that "your own hardware" can mean literally any hardware, not just a machine with a GPU.
Why Danube3-500M and not something smaller
We tried harder-to-shrink options first and hit real walls:
- SmolLM2-135M/360M (49K-token vocab) genuinely shrinks to 100-270MB, but its base pretraining wasn't strong enough to reliably learn category/importance calibration β tried LoRA vs. full fine-tune, epoch sweeps, and reshaped training data, and category accuracy stayed stuck in the 40-65% range regardless.
- Qwen2.5-0.5B / Gemma3 have strong pretraining but 152K/256K-token vocabularies that dominate disk size and don't shrink with quantization (confirmed: Q2_K barely shrank vs Q4_K_M).
- Danube3-500M is the first candidate with both a small vocabulary (32K tokens) and pretraining strong enough for the task β category accuracy jumped to 70%+ on the first fine-tuning attempt, no extensive tuning needed. Its full-parameter fine-tune (100% of weights retrained, vs.
cipher-air/cipher-pro's LoRA) also gives it total plasticity to fully adopt the required output format, no competing base-model habit to fight against.
Benchmark
Evaluated on a 29-fixture triage benchmark across five machines, GPU and CPU-only:
| Hardware | Tok/s | JSON-valid | Category acc | Importance-in-band |
|---|---|---|---|---|
| RTX 5070 (GPU) | 901.0 | 100% | 72.4% | 69.0% |
| RX 9070 XT 16GB (GPU) | 398.7 | 100% | 69.0% | 69.0% |
| Ryzen 9800X3D (CPU-only) | 143.0 | 100% | 72.4% | 72.4% |
| Core Ultra 9 285K (CPU-only) | 106.3 | 100% | 69.0% | 69.0% |
| Intel i3-6100T, 8GB RAM (CPU-only, 10 years old) | 29.4 | 100% | 69.0% | 72.4% |
| Multi-task retrain (chat/summary/draft/compose added) | 899.9 | 96.6% | 67.9% | 89.3% |
| Voice-intent retrain (6th task added) | 867.4 | 96.6% | 75.0% | 82.1% |
| Full retrain (current version, injection/hallucination hardened) | 106.7* | 100.0% | 82.8% | 79.3% |
* Tok/s measured while the GPU was concurrently running an unrelated training job β not a like-for-like comparison with the isolated numbers above; accuracy figures are unaffected.
Accuracy holds essentially flat across every machine tested β only throughput changes. Even the weakest machine here, a decade-old office PC with no GPU, does ~2 seconds per email, well within range for a background triage task. Reproduce with:
pip install -r requirements.txt
python eval_triage.py --models cipher-nano:latest --keep
Usage (Ollama)
Danube3's chat template does not support a system role and uses non-ChatML turn markers β the included Modelfile sets an explicit TEMPLATE to match. Don't rely on Ollama's template autodetection with this base model (confirmed live: without an explicit TEMPLATE, Ollama couldn't resolve a working chat format for this GGUF at all).
ollama create cipher-nano -f Modelfile
Query it with grammar-constrained JSON output for reliable parsing:
curl http://localhost:11434/api/chat -d '{
"model": "cipher-nano",
"messages": [
{"role": "system", "content": "<system prompt from Modelfile>"},
{"role": "user", "content": "From: alex@acme.com\nSubject: Q3 budget review\n\nBody:\nCan we sync before Friday?"}
],
"format": "json",
"options": {"temperature": 0.1}
}'
If you're integrating this into your own app rather than using Ollama: llama-server
(llama.cpp's own server binary) handles this model's real chat template correctly on its
own β verified directly, no override needed there, only for Ollama's simpler
auto-detection.
Training
- Base:
h2oai/h2o-danube3-500m-chat(plainLlamaForCausalLM, 32,000-token vocab), full fine-tune (100% of parameters, not LoRA), 3 epochs - Data: ~4,800 triage examples + ~1,600-2,000 examples each for chat/daily-summary/draft-reply/compose, all matching production prompts exactly β generated by the five
generate_*.pyscripts in this repo; training text reformatted to Danube3's native<|prompt|>/<|answer|>turn format since it has nosystem-role support (seetrain_cipher_nano.py) - Framework: Unsloth +
trl.SFTTrainer - Sequence packing was tried to speed up training (most examples are well under the 2048-token context window) β it crashed outright, an Unsloth/trl version incompatibility, not a quality tradeoff. Disabled.
- Reproduce with
train_cipher_nano.pyβexport_gguf_cipher_nano.py - Voice-intent retrain: added
generate_voice_intent.py's data (weighted heavily toward the no-match case and exact-copy-under-distractor-pressure scenarios) to the mix across 3 rounds of oversampling. Nano's smaller full-fine-tune capacity meant this narrowed but never fully eliminated one specific habit β substituting a different plausible-looking address instead of copying the real one verbatim β see the README intro above for how this ended up getting solved at the calling-app level instead. Reproduce/verify witheval_voice_intent.py. - Full retrain (current version): one clean pass over the base model on a single consolidated, properly-balanced dataset covering all 6 tasks, rather than continuing to layer incremental patches on top of each other β done specifically to fix both the injection-compliance issue and the hallucination regression noted above without risking a whack-a-mole cycle where each narrow fix nudges a different, previously-working case. Followed by one small, targeted continue-train pass (~700 examples, 2 epochs, lr=2e-5) reinforcing "report missing information plainly rather than inventing a plausible- sounding detail," specifically targeting the exact hallucination case found in testing.
License
Apache 2.0, inherited from the base model. Weights, training code, and eval harness are fully open.
- Downloads last month
- 17
4-bit
Model tree for srock44/cipher-nano
Base model
h2oai/h2o-danube3-500m-chat