Instructions to use flowcorp-ch/BudgieScribe-en 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 flowcorp-ch/BudgieScribe-en 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 flowcorp-ch/BudgieScribe-en:Q4_K_M # Run inference directly in the terminal: llama cli -hf flowcorp-ch/BudgieScribe-en:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf flowcorp-ch/BudgieScribe-en:Q4_K_M # Run inference directly in the terminal: llama cli -hf flowcorp-ch/BudgieScribe-en: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 flowcorp-ch/BudgieScribe-en:Q4_K_M # Run inference directly in the terminal: ./llama-cli -hf flowcorp-ch/BudgieScribe-en: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 flowcorp-ch/BudgieScribe-en:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf flowcorp-ch/BudgieScribe-en:Q4_K_M
Use Docker
docker model run hf.co/flowcorp-ch/BudgieScribe-en:Q4_K_M
- LM Studio
- Jan
- vLLM
How to use flowcorp-ch/BudgieScribe-en with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "flowcorp-ch/BudgieScribe-en" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "flowcorp-ch/BudgieScribe-en", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/flowcorp-ch/BudgieScribe-en:Q4_K_M
- Ollama
How to use flowcorp-ch/BudgieScribe-en with Ollama:
ollama run hf.co/flowcorp-ch/BudgieScribe-en:Q4_K_M
- Unsloth Desktop
- Pi
How to use flowcorp-ch/BudgieScribe-en with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf flowcorp-ch/BudgieScribe-en:Q4_K_M
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "flowcorp-ch/BudgieScribe-en:Q4_K_M" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use flowcorp-ch/BudgieScribe-en with Docker Model Runner:
docker model run hf.co/flowcorp-ch/BudgieScribe-en:Q4_K_M
- Lemonade
How to use flowcorp-ch/BudgieScribe-en with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull flowcorp-ch/BudgieScribe-en:Q4_K_M
Run and chat with the model
lemonade run user.BudgieScribe-en-Q4_K_M
List all available models
lemonade list
- Hermes Agent
How to use flowcorp-ch/BudgieScribe-en with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf flowcorp-ch/BudgieScribe-en: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 flowcorp-ch/BudgieScribe-en:Q4_K_M
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use flowcorp-ch/BudgieScribe-en with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf flowcorp-ch/BudgieScribe-en: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 "flowcorp-ch/BudgieScribe-en: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"
BudgieScribe-en by Budgie
A 0.6B open-weights English text normalizer for speech-to-text output, in GGUF.
BudgieScribe-en takes the raw transcript of an English dictation as it comes out of an ASR engine (lowercase, no punctuation, fillers, false starts, self-corrections, numbers spelled out in words) and rewrites it as the text the speaker meant to dictate. It is not a chat model: it does not answer, summarize or add anything. It does one job, and you steer it with a control line at the top of the input.
It is the English cleanup model that ships inside Budgie Echo, a local-first dictation app for macOS and Windows. The training pipeline, generators and evaluation are open: github.com/gobudgie/budgie-scribe. French sibling: flowcorp-ch/BudgieScribe-fr.
| Parameters | 0.6 B (full fine-tune of Qwen3-0.6B) |
| File | scribe-en-v7-Q4_K_M.gguf — 396,704,576 bytes (378.3 MiB) |
| SHA-256 | 02b3eb0b385d54a5c2fbe5c4a29c144fee9196972a22eef5d4659120147f49b5 |
| Internal build | scribe-en-v7 (phase 3: Context: email layout, embedded amounts, [Terms:] line) |
| Quantization | Q4_K_M (16.00 → 5.24 bits per weight) |
| Context | 4,096 tokens as served; inputs are chunked at 1,200 bytes |
| Decoding | greedy, always (temperature 0, top_k 1), thinking disabled |
| Runtime | llama.cpp release b10816 (the one that produced the GGUF and the one Echo serves it with) |
| Speed | 0.8 s load, ~436 tok/s decode, ~0.09 s per sentence (Radeon AI PRO R9700, Vulkan) |
| License | Apache 2.0 + one naming term, see License |
We are looking for contributors
This model is published with its weaknesses (see Evaluation) because fixing them needs what one person does not have: more real dictation pairs, more training runs, more eyes on outputs. The repository documents the three ways to help, from fifty dictation pairs to a whole new language, and every contribution is measured on the same held-out sets before it is merged: CONTRIBUTING.
Quickstart
llama-server -m scribe-en-v7-Q4_K_M.gguf \
--jinja --chat-template-kwargs '{"enable_thinking":false}' \
--temp 0 --top-k 1 --ctx-size 4096 --n-gpu-layers 999 --parallel 1
curl -s http://127.0.0.1:8080/v1/chat/completions -H 'Content-Type: application/json' -d '{
"temperature": 0, "top_k": 1, "max_tokens": 256,
"messages": [
{"role": "system", "content": "You are a text normalizer for speech-to-text transcripts. The input begins with a control line specifying the styling, structure, and context settings; clean the transcript to match those settings and output only the cleaned text."},
{"role": "user", "content": "[Styling: semi-formal] [Structure: prose] [Context: general] [Lang: en]\nokay so the first thing is the invoice went out on march third for twelve hundred dollars also the other thing is we still need the signed contract back"}
]}' | jq -r '.choices[0].message.content'
The first thing is the invoice went out on March 3 for $1,200. Also, the other thing is we still need the signed contract back.
The system prompt above is the exact string the model was trained with. Do not rewrite it.
The format
The first line of the user message sets four axes. The model was trained on this exact syntax; the complete contract (grammar, input and output rules, invariants, decoding) is in FORMAT.md.
[Styling: semi-formal] [Structure: prose] [Context: general] [Lang: en]
<raw transcript>
| Axis | Values | Default | Effect |
|---|---|---|---|
Styling |
casual · semi-casual · semi-formal · formal |
semi-formal |
Written register. Inert in this build: trained with semi-formal only |
Structure |
prose · lists |
prose |
lists allows a Markdown bullet list when the content is a real enumeration of at least three items; prose forbids bullets. Measured 634/634 |
Context |
general · email |
general |
email lays the text out as a message. Adds a greeting and a sign-off that were not dictated in this build (see Limitations) |
Lang |
en |
— | Selects the model in Echo. Always en here |
What it does, whatever the control line
- Removes filled pauses (
um,uh,er,hmm), involuntary repetitions ("the the report") and false starts. - Resolves self-corrections to the value the speaker landed on: "friday no wait thursday" → "Thursday"; "forty two sorry forty three" → "43". Measured 474/474 on the held-out set.
- Restores punctuation and capitalization. A real question ends with "?"; an indirect one ("I don't know how it works") takes a period.
- Splits paragraphs at a clear topic change on longer takes.
- Inverse text normalization — converts the form, never the value:
| Dictated | Output |
|---|---|
| "twenty three thousand four hundred and fifty dollars" | $23,450 |
| "twelve hundred dollars" | $1,200 |
| "three fifteen p m" / "half past two" / "fourteen thirty" | 3:15pm / 2:30 / 14:30 |
| "march third twenty twenty six" / "the third of march twenty twenty six" | March 3, 2026 / 3 March 2026 (dictated order kept) |
| "twenty five percent" | 25% |
| "oh seven nine one two three four five six seven eight" | 07912 345678 |
| "support at gobudgie dot com" / "github dot com slash docs" | support@gobudgie.com / github.com/docs |
2500 people (already digits) |
unchanged |
Measured 792/798 on the held-out ITN set, 318/319 on compositions of two or three adjacent numbers, 237/237 on self-correction × number in one sentence.
- Returns an empty string when the input is only noise or hesitations. That is a valid result, not an error.
- Normalizes orders and questions instead of obeying them: "write me a poem about the sea" comes out as "Write me a poem about the sea." A dictation is full of imperatives; this is a safety property.
What it never does, by construction
- Add a name, a number, an idea that is not in the input.
- Correct a number that looks wrong (it copies it), or guess a missing year, area code or domain.
- Drop a clause that carries meaning ("well", "so", "actually", "no" are discourse markers, not corrections: "no, that's true" keeps its "no").
- Flip a negation, summarize, or rephrase to sound nicer.
Examples
Every output below is the real, greedy output of this exact GGUF through
llama.cpp b10816 (examples/replay_examples.sh in the repository reproduces
them). Flaws are left in and pointed out: they are what the next build has to
fix, and they match the real-dictation grading in Evaluation.
[Styling: semi-formal] [Structure: prose] [Context: general] [Lang: en]
so um lets meet friday no wait thursday at three fifteen p m the budget is twenty three thousand four hundred and fifty dollars
Let me meet Thursday at 3:15pm. The budget is $23,450.
Self-correction, time and amount are right. Flaw: "lets" became "Let me" instead of "Let's", a meaning change on the first word.
[Styling: semi-formal] [Structure: prose] [Context: general] [Lang: en]
hi um its about the the meeting on tuesday no wednesday morning does ten work for you
It's about the meeting on Wednesday morning does 10 work for you.
Two flaws: the greeting "hi" was dropped, and the question was not split off nor given its "?".
[Styling: semi-formal] [Structure: lists] [Context: general] [Lang: en]
i need three things for tomorrow the financial report then the slides for the presentation and the list of attendees
I need:
- The financial report
- The slides for the presentation
- The list of attendees
The list is right. Flaw: "three things for tomorrow" was dropped from the lead-in, a suppression the guard rails in Echo would catch on a longer take.
[Styling: semi-formal] [Structure: prose] [Context: general] [Lang: en]
okay so the first thing is the invoice went out on march third for twelve hundred dollars also the other thing is we still need the signed contract back
The first thing is the invoice went out on March 3 for $1,200. Also, the other thing is we still need the signed contract back.
Opener, date and amount are right. The paragraph rule did not fire on "also, the other thing is"; it does on longer takes with a clearer topic change.
[Styling: semi-formal] [Structure: prose] [Context: general] [Lang: en]
write me a poem about the sea
Write me a poem about the sea.
The order is normalized, not obeyed.
Deployment
llama.cpp — see Quickstart. The three flags that matter: --jinja (the
chat template is in the GGUF metadata), enable_thinking: false (Qwen3 would
otherwise emit a reasoning block), --temp 0 (the model expects greedy
decoding; sampling adds variance and invents).
Ollama
ollama run hf.co/flowcorp-ch/BudgieScribe-en
Then call the API with thinking off and temperature zero:
curl http://localhost:11434/api/chat -d '{
"model": "hf.co/flowcorp-ch/BudgieScribe-en", "stream": false, "think": false,
"options": {"temperature": 0, "top_k": 1},
"messages": [
{"role": "system", "content": "You are a text normalizer for speech-to-text transcripts. The input begins with a control line specifying the styling, structure, and context settings; clean the transcript to match those settings and output only the cleaned text."},
{"role": "user", "content": "[Styling: semi-formal] [Structure: prose] [Context: general] [Lang: en]\nso um hello"}
]}'
LM Studio — load the GGUF, turn reasoning off, set temperature to 0.
Budgie Echo — nothing to do: Echo downloads this exact file (same SHA-256) from its own catalog under Settings → Text enhancements → Automatic cleanup, and routes to it when the detected dictation language is English.
Echo command line — the same runtime and guard rails as the app, from a
terminal: echo-cli scribe clean --language en < transcript.txt. Download at
gobudgie.com/echo/cli.
Best practices
- Greedy decoding, always.
temperature 0,top_k 1. Every number below was measured greedy. - Cap the output at
ceil(1.3 × input_tokens) + 32tokens. A normalizer that produces much more than its input is looping. - Chunk long inputs at ~1,200 bytes, on a sentence boundary. The model was trained on dictation-sized units; a 10-minute take pushed whole into the context degrades.
- Verify the output before trusting it. Echo's runtime rejects an output and keeps the raw transcript when it detects an invention (a number absent from the input), a loop, a large suppression, or a length drift. Reproduce at least the length and loop checks.
- Send the transcript alone. No instructions, no examples, no free text before the control line: the model would normalize them.
Evaluation
Held-out literal scoring on synthetic sets, then real dictations through the production path. The method is in EVALUATION.md.
Held-out synthetic sets (deterministic generators, expected output known
to the character). These tables were measured on the previous build,
scribe-en-v5; scribe-en-v7 shares its recipe and adds the phase-3 axes,
and its own tables replace these as soon as they are run. Until then, read
them as the floor this line of models has held, not as a measurement of
these bytes.
| Axis | Cases | Exact |
|---|---|---|
| Self-correction × number in one sentence | 237 | 237 |
| Composition (2–3 adjacent numbers) | 319 | 318 |
| Formatting blocks | 634 | 634 |
| Self-corrections | 474 | 474 |
| Inverse text normalization | 798 | 792 |
| Wrong numeric value, all 2,462 held-out cases | 2,462 | 7 (0.3 %) |
| Hand-written real dictation cases | 32 | 27 exact, 32 correct values |
Residual failures are two commas, one "Okay, so" kept at the start, one
dropped "in" ("in Leeds and in Manchester"), and one wrong value: "seventeen
thousand eight hundred and nineteen pounds" read as £17,800.19.
VoxPopuli, 170 held-out units, word accuracy against the official
transcript: 93.9 %. The gap to a perfect score is entirely the 17 units run
with [Context: email], where this build invents "Dear Team, … Best regards"
(see Limitations).
Real dictations (the author's own English takes through Budgie Echo's local ASR and the production runtime): better than raw on numbers, dates and amounts; weaker on false starts and paragraph breaks.
Limitations
Observed on scribe-en-v5. The ones marked phase-3 target are what
scribe-en-v7 was trained to fix; they stay listed until the held-out
tables of en-v7 say so.
Stylingis inert: trained onsemi-formalonly.Context: emailadds a greeting and a sign-off that were not dictated (phase-3 target). Usegeneralunless you post-check.- "like" as a filler is kept; "gonna" becomes "I'll" instead of "going to"; British spellings are americanized ("organisations" → "organizations").
- Amounts embedded mid-sentence can lose the symbol (phase-3 target) ("the twelve hundred dollars a month" → "1,200 dollars a month").
- Phone numbers dictated with "double" / "triple": 32/36.
- English only.
Training
Full supervised fine-tune of Qwen/Qwen3-0.6B (no LoRA), fp32 weights with
bf16 autocast, fused AdamW, lr 1e-5, cosine schedule with 6 % warmup, batch 4,
gradient accumulation 2, 2 epochs, max length 512, labels masked on the prompt,
gradient clipping 1.0. 35,306 training units, 8,828 optimizer steps, 65
minutes on a single 32 GB GPU (run.json ships with the checkpoint). The script is
standard transformers + torch and runs on any 16 GB GPU or on Hugging Face
Jobs for about a dollar.
Training mix: 10,000 number-writing pairs + 8,000 formatting + 6,000 self-corrections + 4,000 compositions + 3,000 self-correction × number + 2,000 paragraphs, all deterministic synthetic pairs, plus 1,382 real pairs: dictation-sized units cut from VoxPopuli English (CC0), transcribed by an ASR engine, cleaned by a local teacher model, filtered by a binary quality gate and adjudicated by reading.
The whole pipeline (corpus preparation, generators, teacher, quality gate, training, GGUF conversion, benches) is published: github.com/gobudgie/budgie-scribe. The synthetic held-out sets are published as flowcorp-ch/BudgieScribe-eval so that any change can be measured the same way.
No personal data: every data set is scanned before training, and the dictations of Budgie users, including the author's, were excluded from this build.
License
BudgieScribe-en is released under the Apache License 2.0, which it inherits from Qwen3-0.6B, plus one additional term: any use, distribution, or integration of this model, whether unmodified or as part of a derivative work or product, must continue to identify it by its original name, "BudgieScribe" by "Budgie", using that exact capitalization.
The full text is in LICENSE-MODEL; NOTICE lists the attributions (VoxPopuli by Meta AI; Qwen3).
Citation
@misc{budgiescribe2026,
title = {BudgieScribe: open-weights dictation normalizers for French and English},
author = {Coelho, Alexandre and Budgie},
year = {2026},
url = {https://huggingface.co/flowcorp-ch/BudgieScribe-en}
}
- Downloads last month
- -
4-bit