Kanso Satori 1.0 (4B, 4-bit DWQ)

Names. ZenVoice's formatting models are called Kanso since ZenVoice 1.3.1: Kanso Koi 1.0 was ZenPolish v2.2 Lite, Koi 0.9 was ZenPolish v2.2, Koi 0.8 was ZenPolish v2, Kanso Satori 1.0 was ZenPolish v3.2 4B and Satori 0.9 was ZenPolish v3 4B. The repositories were renamed from zen-polish-…; old links and pinned revisions redirect here. Tables below use the development version numbers (v2, v2.1, v2.2, v3, v3.1, v3.2).

ZenVoice's on-device dictation-enhancement model, 4B tier. It takes raw speech-to-text output and restores:

  • punctuation and capitalization,
  • filler removal (leading and mid-sentence),
  • false-restart removal,
  • inverse text normalization: numbers, money, dates, times, percents, emails, URLs, phones,
  • meaning-preserving grammar repair.

It runs fully on-device via MLX: 2.26 GB of weights, about 47 tok/s on an Apple M5.

What v3.2 is. The v2.2 recipe and corpus, trained on Qwen3-4B-Instruct-2507:

  1. The LoRA adapter was merged into the bf16 weights (Kanso-Satori-1.0-bf16).
  2. Those weights were quantized to 4 bits with DWQ (distilled weight quantization). DWQ tunes the quantization scales so the 4-bit model's token distribution matches the bf16 model's on Kanso training prompts.

This is a plain model: there is no adapter to load. It is as accurate as the unquantized v3.2.

Use the bundled chat_template.jinja. v3.2 was trained with an empty think block (<think>\n\n</think>\n\n) at the start of every reply. The bundled template ends the generation prompt with that block. The stock Qwen3-4B-Instruct-2507 template does not; without the block the first token becomes a coin toss, and lower-bit builds derail into <tool_call> tokens.

Benchmark

Greedy decoding, Apple M5, MLX 0.32.2.

eval_v500: 500 dictations, leakage-controlled, max 200 tokens.

Metric v3.2 4-bit DWQ v3.2 3-bit DWQ v2.2 Lite (1.7B) v3.1 (previous 4B)
WER 4.7% 4.7% 5.5% 13.3%
Exact match 67.2% 64.2% 65.8% 49.8%
Punct F1 0.859 0.838 0.863 0.772
Sentence-start 95.1% 93.4% 94.4% 82.3%
Weights 2.26 GB 1.76 GB 1.05 GB 2.26 GB
Decode speed 47 tok/s 58 tok/s 73 tok/s 47 tok/s

Held-out v2.2 data: 500 rows used neither in training nor in DWQ.

Metric v3.2 4-bit DWQ v3.2 3-bit DWQ v2.2 Lite v3.1
WER 8.0% 9.0% 8.9% 26.9%
Exact match 40.6% 37.0% 37.0% 10.4%

Against Lite, the 4-bit model's exact-match gain is +3.6 points (95% CI +0.4 to +6.8).

Medium dictations: 150 dictations of 50–99 words, max 400 tokens.

Metric v3.2 4-bit DWQ v3.2 3-bit DWQ v2.2 Lite v3.1
WER 10.3% 15.1% 11.0% 13.9%
Punct F1 0.815 0.796 0.795 0.695

ZenVoice app runtime: mlx-swift-lm, the app's own formatting pipeline, eval_v500.

  • Model output: WER 3.9%, exact match 64.6%. Lite scores 4.0% and 65.4%.
  • Time and memory: mean 0.32 s per dictation, peak memory 2.65 GB.
  • Time budget: no dictation exceeded the app's budget.

Usage

from mlx_lm import load, generate
from mlx_lm.sample_utils import make_sampler

model, tokenizer = load("BuilderHelm/Kanso-Satori-1.0")

SYSTEM = ("You clean up raw speech-to-text dictation. Fix punctuation and "
          "capitalization, remove filler words and false restarts, and restore the "
          "written forms of numbers, dates, times, money, URLs, and email "
          "addresses. Keep the speaker's meaning and wording. If an 'app:' line is "
          "given, match capitalization and tone to that context. Output only the "
          "cleaned text, with no commentary.")
messages = [{"role": "system", "content": SYSTEM},
            {"role": "user", "content": "send it to john dot smith at example dot com by friday the twelfth"}]
prompt = tokenizer.apply_chat_template(messages, add_generation_prompt=True, enable_thinking=False)
print(generate(model, tokenizer, prompt=prompt, max_tokens=200, sampler=make_sampler(temp=0.0)))
# -> "Send it to john.smith@example.com by Friday, the twelfth."

Training

  • Base: Qwen3-4B-Instruct-2507. Training ran on mlx-community/Qwen3-4B-Instruct-2507-4bit at revision 50d4277.
  • LoRA: rank 32 / alpha 64 / scale 2.0, dropout 0.05, all 36 layers, all linear modules.
  • Schedule: cosine decay 1e-4 → 1e-6 over 3,400 steps, batch 2, 3,500 iterations, max length 1,024, gradient checkpointing.
  • Checkpoint: step 3500, chosen on a held-out set.
  • Data: the 10-source v2.2 training corpus, 86,524 training pairs; see Kanso-Koi-1.0.
  • Merge: the adapter was merged into the original bf16 weights.
  • DWQ: 4-bit, group size 64. Trained on 1,024 training samples of up to 512 tokens at learning rate 1e-6, against top-1,024 logit targets from the bf16 model.

Scope

  • English dictation cleanup.
  • Single-shot inputs of 300+ words can repeat themselves. ZenVoice splits long dictations into sentence-aligned pieces before polishing.
  • Use greedy decoding.

License

Apache-2.0 (Qwen3-4B-Instruct-2507 base). Training data: MIT/Apache-2.0/ CC-BY-4.0/CC0 sources only; attribution list in the ZenVoice repo.

Published under BuilderHelm AI. Previously imYChaudhary22/Kanso-Satori-1.0; existing repository links and pinned revisions redirect to this organization repository. Model filenames and weights are unchanged.

Downloads last month
205
Safetensors
Model size
4B params
Tensor type
U32
·
BF16
·
MLX
Hardware compatibility
Log In to add your hardware

4-bit

Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for BuilderHelm/Kanso-Satori-1.0

Quantized
(2)
this model

Collection including BuilderHelm/Kanso-Satori-1.0