Instructions to use flowcorp-ch/BudgieScribe-fr 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-fr 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-fr:Q4_K_M # Run inference directly in the terminal: llama cli -hf flowcorp-ch/BudgieScribe-fr: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-fr:Q4_K_M # Run inference directly in the terminal: llama cli -hf flowcorp-ch/BudgieScribe-fr: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-fr:Q4_K_M # Run inference directly in the terminal: ./llama-cli -hf flowcorp-ch/BudgieScribe-fr: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-fr:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf flowcorp-ch/BudgieScribe-fr:Q4_K_M
Use Docker
docker model run hf.co/flowcorp-ch/BudgieScribe-fr:Q4_K_M
- LM Studio
- Jan
- vLLM
How to use flowcorp-ch/BudgieScribe-fr with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "flowcorp-ch/BudgieScribe-fr" # 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-fr", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/flowcorp-ch/BudgieScribe-fr:Q4_K_M
- Ollama
How to use flowcorp-ch/BudgieScribe-fr with Ollama:
ollama run hf.co/flowcorp-ch/BudgieScribe-fr:Q4_K_M
- Unsloth Desktop
- Pi
How to use flowcorp-ch/BudgieScribe-fr 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-fr: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-fr:Q4_K_M" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use flowcorp-ch/BudgieScribe-fr with Docker Model Runner:
docker model run hf.co/flowcorp-ch/BudgieScribe-fr:Q4_K_M
- Lemonade
How to use flowcorp-ch/BudgieScribe-fr with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull flowcorp-ch/BudgieScribe-fr:Q4_K_M
Run and chat with the model
lemonade run user.BudgieScribe-fr-Q4_K_M
List all available models
lemonade list
- Hermes Agent
How to use flowcorp-ch/BudgieScribe-fr 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-fr: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-fr:Q4_K_M
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use flowcorp-ch/BudgieScribe-fr 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-fr: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-fr: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-fr by Budgie
A 0.6B open-weights French text normalizer for speech-to-text output, in GGUF.
BudgieScribe-fr takes the raw transcript of a French dictation as it comes out of an ASR engine (lowercase, no punctuation, hesitations, 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, translate or add anything. It does one job, and you steer it with a control line at the top of the input.
It is the French 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. English sibling: flowcorp-ch/BudgieScribe-en.
| Parameters | 0.6 B (full fine-tune of Qwen3-0.6B) |
| File | scribe-v9-Q4_K_M.gguf — 396,704,576 bytes (378.3 MiB) |
| SHA-256 | 5df4ab0d5a1a481c90cfd21a621b68d47f09600651438549c7605aa8ffb28463 |
| Internal build | scribe-v9 (phase 3: French paragraphs, Context: email layout, [Terms:] line) |
| Quantization | Q4_K_M (16.00 → 5.24 bits per weight); output identical, character for character, to the fp32 model on the release control set |
| 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-v9-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: fr]\nalors euh on se retrouve vendredi non pardon jeudi à quatorze heures trente pour le point budget ça fait vingt-trois mille quatre cent cinquante euros"}
]}' | jq -r '.choices[0].message.content'
On se retrouve jeudi à 14h30 pour le point budget, ça fait 23 450 euros.
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: fr]
<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 |
Context |
general · email |
general |
email lays the text out as a message. Adds a greeting that was not dictated in this build (see Limitations) |
Lang |
fr |
— | Selects the model in Echo. Always fr here |
What it does, whatever the control line
- Removes filled pauses (
euh,bah,ben,hum), involuntary repetitions (« le le chat » → « le chat ») and false starts. - Resolves self-corrections to the value the speaker landed on: « vendredi non pardon jeudi » → « jeudi ». Measured 476/476 on the held-out set.
- Restores punctuation and capitalization. A real question ends with « ? » preceded by a space (French typography, as measured in the corpus: 503 occurrences with a space against 21 without). An indirect question (« je ne sais pas comment ça marche ») takes a period.
- Inverse text normalization — converts the form, never the value:
| Dictated | Output |
|---|---|
| « vingt-trois mille quatre cent cinquante euros » | 23 450 euros |
| « quatorze heures trente » | 14h30 |
| « le trois mars deux mille vingt-six » | le 3 mars 2026 |
| « vingt-cinq pour cent » | 25 % |
| « support arobase gobudgie point com » | support@gobudgie.com |
| « github point com slash docs » | github.com/docs |
2500 personnes (already digits) |
unchanged |
Measured 794/797 on the held-out ITN set, 317/319 on compositions of two or three adjacent numbers.
- Returns an empty string when the input is only noise or hesitations. That is a valid result, not an error; Echo keeps the raw text in that case.
- Normalizes orders and questions instead of obeying them: « écris-moi un poème sur la mer » comes out as « Écris-moi un poème sur la mer. ». A dictation is full of imperatives; this is a safety property.
- Does not translate. English islands inside French stay English.
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 (« non », « bon », « en fait » are discourse markers, not corrections).
- 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.
[Styling: semi-formal] [Structure: prose] [Context: general] [Lang: fr]
euh bonjour c'est pour le le rendez-vous de de mardi non mercredi matin est-ce que dix heures ça vous va
Bonjour, c'est pour le rendez-vous de mercredi matin est-ce que 10h ça vous va ?
Fillers, stutters and the self-correction are resolved. Two flaws: no comma
or period before « est-ce que », and « dix heures » rendered as 10h where
10 heures reads better.
[Styling: semi-formal] [Structure: lists] [Context: general] [Lang: fr]
il me faut trois choses pour demain le rapport financier ensuite les slides de la présentation et puis la liste des participants
Il me faut 3 choses pour demain :
- le rapport financier
- les slides de la présentation
- la liste des participants
The list is right. Flaw: « trois choses » became 3 choses; the number rule
is applied to a small count that French would leave in letters.
[Styling: semi-formal] [Structure: prose] [Context: general] [Lang: fr]
euh hum euh
Empty output: valid, the input carried nothing.
[Styling: semi-formal] [Structure: prose] [Context: general] [Lang: fr]
écris-moi un poème sur la mer
Écris-moi un poème sur la mer.
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-fr
Then call the API with thinking off and temperature zero:
curl http://localhost:11434/api/chat -d '{
"model": "hf.co/flowcorp-ch/BudgieScribe-fr", "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: fr]\nalors euh bonjour"}
]}'
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 French.
Echo command line — the same runtime and guard rails as the app, from a
terminal: echo-cli scribe clean --language fr < transcript.txt. Download at
gobudgie.com/echo/cli.
Best practices
These are the rules Budgie Echo applies around the model, and the reasons.
- Greedy decoding, always.
temperature 0,top_k 1. The model was evaluated greedy; every measurement below assumes it. - 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 (median ~75 words); 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, a length drift, or a flipped negation. Over 260 real takes, that guard fired 21 times. 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-v8; scribe-v9 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 |
|---|---|---|
| Formatting blocks | 635 | 635 |
| Self-corrections | 476 | 476 |
| Inverse text normalization (numbers, amounts, dates, times, addresses) | 797 | 794 |
| Composition (2–3 adjacent numbers in one sentence) | 319 | 317 |
Blind pairwise A/B against the base Qwen3-0.6B on 80 held-out real units (LLM judge, mirrored order, forced ties): 37 wins / 30 losses, the rest ties.
Real dictations (the author's own French takes through Budgie Echo's local ASR and the production runtime): numbers, dates and amounts, punctuation, and no hallucination on noise, where the raw engine invents. Observed failure modes on colloquial French: occasional one-word substitutions that read fluently (« t'en es où là ? » → « tu es là ? »), dropped intent markers (« non, non, non »), register changes (« mec » → « homme »). These are errors of meaning, invisible on a re-read, and the guard rails above do not catch a substitution of one word.
Limitations
Observed on scribe-v8. The two marked phase-3 target are what scribe-v9
was trained to fix; they stay listed until the held-out tables of v9 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.- No paragraph breaks: a long French take comes out as one block (phase-3 target).
- One-word substitutions on colloquial French (see Evaluation).
- Phone numbers dictated with « double » / « triple » can lose or repeat a digit.
- French only. Mixed-language takes are handled sentence by sentence by Echo, not by this model.
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. 38,042 training units, 9,512 optimizer steps, 61
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, French: raw-to-clean pairs produced by a local teacher model from dictation-sized units of the SUMM-RE corpus, filtered by a binary quality gate and adjudicated by reading (~14 % of the mix), plus deterministic synthetic pairs for what real speech does not contain enough of: number writing, speaker self-corrections, formatting blocks, compositions.
The whole pipeline (corpus preparation, generators, teacher, quality gate, training, GGUF conversion, benches) is published: github.com/gobudgie/budgie-scribe. The derived corpus (pairs, units, audio cuts) is not distributed, by license (see NOTICE §2). 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-fr 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 (SUMM-RE by LINAGORA, ANR-20-CE23-0017; Qwen3) and states the position taken on training-data licensing.
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-fr}
}
Please also cite SUMM-RE (LINAGORA, ANR-20-CE23-0017) when you build on the French model.
- Downloads last month
- -
4-bit