Instructions to use srock44/cipher-pro 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-pro 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-pro:Q4_K_M # Run inference directly in the terminal: llama cli -hf srock44/cipher-pro: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-pro:Q4_K_M # Run inference directly in the terminal: llama cli -hf srock44/cipher-pro: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-pro:Q4_K_M # Run inference directly in the terminal: ./llama-cli -hf srock44/cipher-pro: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-pro:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf srock44/cipher-pro:Q4_K_M
Use Docker
docker model run hf.co/srock44/cipher-pro:Q4_K_M
- LM Studio
- Jan
- vLLM
How to use srock44/cipher-pro with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "srock44/cipher-pro" # 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-pro", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/srock44/cipher-pro:Q4_K_M
- Ollama
How to use srock44/cipher-pro with Ollama:
ollama run hf.co/srock44/cipher-pro:Q4_K_M
- Unsloth Studio
How to use srock44/cipher-pro 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-pro 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-pro 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-pro to start chatting
- Pi
How to use srock44/cipher-pro with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf srock44/cipher-pro:Q4_K_M
Configure the model in Pi
# Install Pi: npm install -g @mariozechner/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "srock44/cipher-pro:Q4_K_M" } ] } } }Run Pi
# Start Pi in your project directory: pi
- OpenClaw new
How to use srock44/cipher-pro with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf srock44/cipher-pro:Q4_K_M
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "srock44/cipher-pro:Q4_K_M" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
- Docker Model Runner
How to use srock44/cipher-pro with Docker Model Runner:
docker model run hf.co/srock44/cipher-pro:Q4_K_M
- Lemonade
How to use srock44/cipher-pro with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull srock44/cipher-pro:Q4_K_M
Run and chat with the model
lemonade run user.cipher-pro-Q4_K_M
List all available models
lemonade list
- Hermes Agent
How to use srock44/cipher-pro with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf srock44/cipher-pro:Q4_K_M
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default srock44/cipher-pro:Q4_K_M
Run Hermes
hermes
- Atomic Chat
| license: apache-2.0 | |
| base_model: Qwen/Qwen3-4B-Instruct-2507 | |
| tags: | |
| - gguf | |
| - triage | |
| - ollama | |
| - lora | |
| - unsloth | |
| - cipher | |
| - voice-intent | |
| language: | |
| - en | |
| pipeline_tag: text-generation | |
| # Cipher Pro | |
| Cipher Pro is a LoRA fine-tune of [Qwen/Qwen3-4B-Instruct-2507](https://huggingface.co/Qwen/Qwen3-4B-Instruct-2507), 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, across 4 retrain passes total β | |
| each one targeting a specific failure mode found in real end-to-end testing (not just raw | |
| model output) rather than broad re-training. See `Training` below for the full progression; | |
| current state on `eval_voice_intent.py`'s 5 fixtures, verified through the actual calling | |
| app's retry-and-fallback logic (not a single raw completion), is **5/5**. | |
| Also fixed in this update: a garbled-leading-token failure mode specific to the compose- | |
| assist task (a stray non-ASCII token before otherwise-correct output, unrelated to the | |
| `<think>`/`<tool_call>` leak below) β caught by manual spot-checking since compose has no | |
| automated schema to catch it against, not by any benchmark number. | |
| **Second update β security fix:** live testing found this model would occasionally comply | |
| with a prompt-injection attempt embedded in email content on the draft-reply/chat tasks | |
| (echoing a fake "security verification" request for banking details back into a drafted | |
| reply). Fixed with a 5th training pass adding substantially richer injection coverage | |
| (credential-phishing, wire-transfer, and data-exfiltration attempts across both tasks, not | |
| just one generic case). A fresh, single-pass full retrain from the base model was also | |
| tried as an alternative to another incremental patch, on the theory that one clean pass on | |
| a properly-rebalanced dataset should be more robust than a long chain of narrow | |
| continue-trains β it wasn't: two different learning rates each fixed one known issue but | |
| introduced a *different* new one (one broke ~21% of triage fixtures even after retries; the | |
| other introduced a bizarre off-topic role-play hallucination on ~50% of a chat fixture, | |
| confirmed via repeated testing). The incrementally-built version β the one actually shipped | |
| here β didn't have either problem and was kept instead. See `Training` below for the full | |
| pass-by-pass history and the specific comparison numbers. | |
| It's the largest of the three **Cipher** tiers (`cipher-nano` / `cipher-air` / `cipher-pro`), and the strongest on structured-output accuracy β **100% category accuracy** on the triage benchmark below. 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](https://ollama.com) β nothing about your email ever leaves your machine. | |
| ## What's in this repo | |
| - `cipher-pro.Q4_K_M.gguf` β the model weights, ready for Ollama | |
| - `Modelfile` β the exact Ollama Modelfile (system prompt, explicit ChatML `TEMPLATE`, inference params) used in training/eval β **use `ollama create`, not `ollama pull hf.co/...`**, see the integration note below | |
| - `train_cipher_pro.py` / `export_gguf_cipher_pro.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 | |
| - `eval_triage.py` / `eval_fixtures.json` β a standalone benchmark harness (no external dependencies beyond `httpx`/`pydantic`) reproducing the triage numbers below | |
| Everything needed to reproduce this model from scratch, or fine-tune your own variant, is in this repo β nothing here depends on an unreleased package. | |
| ## Benchmark | |
| Evaluated on a 29-fixture triage benchmark against the untuned base model, on an RTX 5070: | |
| | Model | Disk | Tok/s | JSON-valid (raw single-shot) | JSON-valid (through the app's retry logic) | Category acc | Importance-in-band | Injection-safe | | |
| |---|---|---|---|---|---|---|---| | |
| | **cipher-pro** | 2.5 GB | 171.2 | ~62-79% (see note above) | **100.0% (29/29)** | 86.2% | 82.8% | 100% | | |
| Reproduce with: | |
| ```bash | |
| pip install -r requirements.txt | |
| python eval_triage.py --models cipher-pro:latest --keep | |
| ``` | |
| ## Integration note: chat template | |
| Qwen3's chat template isn't reliably auto-detected from the exported GGUF by Ollama (confirmed live β `ollama show --modelfile` fell back to a raw passthrough template with no role formatting, causing the model to leak stray `</think>`/`</tool_call>` closing tags before its JSON output). The included `Modelfile` sets an explicit ChatML `TEMPLATE` matching what this model was actually trained on β don't rely on Ollama's autodetection or `ollama pull hf.co/...` (which generates its own default template and ignores the Modelfile committed in this repo). If you're integrating this into your own app rather than using Ollama, `llama-server` (llama.cpp's own server binary) handles Qwen3's real chat template correctly on its own β verified directly, no override needed there. | |
| Even with the correct template, a small residual fraction of completions may still leak a stray reasoning/tool-call tag before the JSON (Qwen3's own pretraining bakes in tool-calling habits that a LoRA adapter β 0.81% of this model's parameters β can't fully suppress). If you're parsing structured output, strip any leading `</think>`/`<think>`/`</tool_call>`/`<tool_call>` run before `json.loads()` β see `strip_leading_reasoning_tags()` in Grimoire's own `llm_client.py` for the reference implementation. | |
| The same underlying habit occasionally surfaces on free-text tasks (draft-reply/chat/compose) too, which have no JSON schema to validate against β sometimes as a fully garbled/empty response, sometimes as just a short garbled token prefixed onto an otherwise-correct reply. Both are worth retrying against rather than surfacing to a user as-is; see `_looks_garbled()` and the retry loop in `chat()` in the same reference file. This model tests clean through that retry path β 29/29 on the triage benchmark and 5/5 on compose (normal + injection) β but a raw single-shot call without the retry logic will occasionally hit one of these two patterns; don't skip the retry wrapper if you're integrating this model directly. | |
| ## Usage (Ollama) | |
| ```bash | |
| ollama create cipher-pro -f Modelfile | |
| ``` | |
| Query it with grammar-constrained JSON output for reliable parsing: | |
| ```bash | |
| curl http://localhost:11434/api/chat -d '{ | |
| "model": "cipher-pro", | |
| "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} | |
| }' | |
| ``` | |
| ## Training | |
| - Base: `Qwen/Qwen3-4B-Instruct-2507`, LoRA (r=16, alpha=32, all linear layers), 2 epochs | |
| - Data: ~4,800 triage examples + ~1,600-2,000 examples each for chat/daily-summary/draft-reply/compose (~13,000 total, triage oversampled), all matching Grimoire's exact production prompts β generated by the five `generate_*.py` scripts in this repo | |
| - Framework: [Unsloth](https://github.com/unslothai/unsloth) + `trl.SFTTrainer` | |
| - Sequence packing (`trl.SFTConfig(packing=True)`) was tried to speed up training given most examples are well under the 2048-token context window β it crashed outright (`ValueError: Expected input batch_size (2048) to match target batch_size (3636)`, an Unsloth fused-loss/trl packing-collator incompatibility in this exact library version pairing), not a quality tradeoff. Disabled. | |
| - Reproduce with `train_cipher_pro.py` β `export_gguf_cipher_pro.py` | |
| - Voice-intent retrain (4 passes, each continuing LoRA training from the previous pass's | |
| adapter rather than starting over): | |
| 1. ~1,800 voice-intent examples added to the mix β fixed the core hallucinated-address | |
| bug, but introduced two new rule-violations (leaking a resolved recipient into | |
| `search_email` queries; dropping a valid address match under an injection attempt). | |
| 2. ~2,800 examples targeting both failure modes specifically (heavier weight on | |
| search-with-a-real-match-that-must-stay-null and injection-with-a-real-match cases) β | |
| both fixed, but a 3rd failure mode surfaced: the `unknown` action (unsupported | |
| requests like "forward this to my team") sometimes degenerated into an empty, | |
| repeating `<tool_call>` loop instead of valid JSON. | |
| 3. A small (~1,500 example) continue-train pass β mostly expanded, more diverse `unknown` | |
| phrasing plus a light replay slice of everything else to avoid regressing what already | |
| worked β fixed the degenerate-loop case. At this point raw single-shot eval showed 4/5; | |
| testing through the actual calling app's `chat_json` (which retries with the | |
| validation error fed back, and falls back to `action: unknown` if all retries still | |
| fail) showed this was already a real 5/5 in practice β the raw eval script's single | |
| request just didn't reflect the app's actual behavior. | |
| 4. A final ~4,200 example pass fixed the separately-discovered compose garbled-leading- | |
| token issue (see the note above), continuing from pass 3's adapter with the full | |
| `unknown`-fixup data included in the replay slice specifically so that fix wouldn't | |
| regress. Re-verified 5/5 on voice-intent afterward, no regression on triage/daily- | |
| summary/chat. | |
| 5. A ~5,200 example pass targeting the credential-injection compliance bug (see the | |
| security update above), continuing from pass 4's adapter with light general replay | |
| plus the full pass-3 `unknown`-fixup data re-included, so neither earlier fix would | |
| erode. This is the version actually shipped in this repo. | |
| 6. (Not shipped, kept here for the record.) Two single-pass full retrains from the base | |
| model, differing only in learning rate (2e-4 default vs. 1e-4), were tried afterward | |
| to see if one clean pass on a properly-rebalanced dataset would be more robust than | |
| the chain of narrow patches above. Verified through the real calling app's retry | |
| logic on all 29 triage fixtures: the default-LR version scored 23/29 (six fixtures | |
| failed all 3 retry attempts, every time) against pass 5's clean 29/29 on the identical | |
| test. The lower-LR version fixed that (29/29) but introduced a new, different | |
| failure β an off-topic role-play hallucination on a basic chat-recall question, | |
| reproduced on 2 of 4 independent runs, never observed on pass 5. Neither full-retrain | |
| attempt beat the incrementally-built version on every axis simultaneously, so pass 5 | |
| was kept as the shipped model. | |
| ## License | |
| Apache 2.0, inherited from the base model. Weights, training code, and eval harness are fully open. | |