|
Download README.md from mlboydaisuke/S1-mini-CoreAI: direct link, hf CLI and curl.
- Browser
- Download file 10.5 kB
-
https://huggingface.co/mlboydaisuke/S1-mini-CoreAI/resolve/main/README.md
- Command line
-
hf download hf://mlboydaisuke/S1-mini-CoreAI/README.md
-
curl -L -o README.md https://huggingface.co/mlboydaisuke/S1-mini-CoreAI/resolve/main/README.md
10.5 kB
| license: other | |
| license_name: s1-mini-license | |
| license_link: LICENSE | |
| library_name: coreai | |
| pipeline_tag: text-generation | |
| base_model: superwhisper/s1-mini | |
| base_model_relation: quantized | |
| language: [en] | |
| tags: [coreai, core-ai, coreaikit, asr, speech-to-text, text-normalization, | |
| inverse-text-normalization, punctuation, truecasing, dictation, | |
| post-processing, on-device, apple, qwen3] | |
| Core AI is Apple's on-device ML runtime in iOS 27 / macOS 27 and the successor to Core ML: PyTorch models are exported with Apple's `coreai-torch` (LLMs: `coreai.llm.export`) into `.aimodel` bundles that run on the GPU or the Neural Engine, e.g. Qwen3-8B 4-bit decodes at 94 tok/s on an M4 Max GPU, MLX 90 under the same protocol ([apple-silicon-llm-bench](https://github.com/john-rocky/apple-silicon-llm-bench), macOS 27 beta 26A5353q, 2026-06-11). | |
| <!-- gen-cards:devicemark begin (managed by scripts/gen-cards + tools/devicemark_row.py β edit cards.json, not this block) --> | |
| This model has no row on [DeviceMark](https://devicemark.github.io/), the on-device LLM leaderboard. | |
| <!-- gen-cards:devicemark end --> | |
| # S1-mini by Superwhisper β Core AI | |
| [**S1-mini**](https://huggingface.co/superwhisper/s1-mini) by **Superwhisper** converted to | |
| Apple **Core AI**, running fully on-device on iPhone and Mac. | |
| S1-mini is a 0.6B **text normalizer for speech-to-text output**. Give it a raw ASR | |
| transcript and it returns clean written text: fillers removed, false starts and | |
| self-corrections resolved to whatever the speaker landed on, punctuation and capitalization | |
| applied, and spoken numbers, dates, times, currency and email addresses rendered in written | |
| form. It is not a chat model β it does one job, steered by a control line at the top of the | |
| input. | |
| That makes it the piece an on-device dictation stack is usually missing. Core AI already has | |
| ASR (Parakeet, Nemotron-3.5-ASR-Streaming, Whisper, Qwen3-ASR); this is the post-processor | |
| that turns a raw transcript into text a person would actually send, with nothing leaving the | |
| device. | |
| > **Naming.** The upstream license adds a term to Apache-2.0: any use, distribution or | |
| > product integration must keep identifying this model as **"S1-mini"** by **"Superwhisper"**, | |
| > with that exact capitalization, whatever the surrounding product is called. See | |
| > [`LICENSE`](LICENSE). | |
| <!-- gen-cards:use-it begin id=s1-mini (managed by scripts/gen-cards β edit cards.json / QuickStart.swift, not this block) --> | |
| ## Use it | |
| **New to Core AI? [Start with CoreAIKit 0.7.3](https://github.com/john-rocky/coreai-kit#readme).** Follow its requirements and first-run steps for `qwen3-0.6b`, then open the same release's [ChatDemo](https://github.com/john-rocky/coreai-kit/tree/0.7.3/Examples/ChatDemo). The README records the tested OS/SDK and download size; model and device coverage is stated per example. | |
| β‘ **One line** β this model is the default behind the kit's task op | |
| (`import CoreAIOps`; no session, no model plumbing, downloads on first use): | |
| ```swift | |
| let clean = try await CoreAI.tidyTranscript(rawTranscript) | |
| ``` | |
| Every op, one shape β [Cookbook](https://github.com/john-rocky/coreai-kit/blob/0.7.3/docs/COOKBOOK.md). | |
| βΆοΈ **Run it (source)** β the [Tidy runner](https://github.com/john-rocky/coreai-kit/tree/0.7.3/Examples/Tidy) | |
| (GUI + CLI, the three control axes as pickers): | |
| ```bash | |
| git clone --branch 0.7.3 --depth 1 https://github.com/john-rocky/coreai-kit | |
| export DEVELOPER_DIR=/Applications/Xcode-27.0.0-RC.app/Contents/Developer | |
| open -a /Applications/Xcode-27.0.0-RC.app coreai-kit/Examples/Tidy/Tidy.xcodeproj | |
| # β Run, then pick "S1-mini by Superwhisper" in the model picker | |
| # agents / headless (macOS): | |
| cd coreai-kit/Examples/Tidy | |
| swift run -c release tidy-cli --model s1-mini --text "so um i need to like send the the report by uh friday no wait make that thursday" | |
| ``` | |
| Use Xcode build **27A266a** from the release's `.xcode-pin`; adjust the app path if your installation is named differently. | |
| π» **Build with it** β complete; the glue is kit API, copy-paste runs: | |
| ```swift | |
| import CoreAIKit | |
| let tidier = try await KitTextNormalizer(catalog: "s1-mini") | |
| // Long input is cut at word boundaries into ~450-token chunks and the rewrites stitched: | |
| // on iPhone the engine caps prompt + generated at 1024 tokens, so a whole meeting | |
| // transcript passed in one call would stop mid-sentence. | |
| let result = try await tidier.normalize(transcript) | |
| // result: the transcript as written text β English only; filler-only input returns "" | |
| ``` | |
| The take-home is [`Examples/Tidy/Sources/QuickStart.swift`](https://github.com/john-rocky/coreai-kit/blob/0.7.3/Examples/Tidy/Sources/QuickStart.swift) | |
| β this exact code as one typed function, no UI; both the runner's GUI and its CLI call it. | |
| Cleaning transcripts repeatedly? Keep the `KitTextNormalizer` loaded and call | |
| `normalize(_:)` per transcript β the 796 MB load is what you are avoiding. | |
| **Integration checklist** | |
| - SPM: `https://github.com/john-rocky/coreai-kit` (exact **0.7.3**) β product **CoreAIKit** | |
| - Info.plist: none needed | |
| - Entitlements: none needed | |
| - First run downloads the model β ~796 MB (Mac) / ~796 MB (iPhone) β then it loads from the | |
| local cache (Application Support; progress via the `downloadProgress` callback) | |
| - Measure in Release β Debug is ~3Γ slower on per-token host work | |
| <!-- gen-cards:use-it end --> | |
| ## Contents | |
| `gpu-pipelined/s1_mini_decode_int8lin/` β decode bundle for the Core AI pipelined engine, | |
| **759 MB**. Body int8 per-block-32; the head is tied to the embedding and stays fp16 (see | |
| *Quantization* below). Runs unchanged on macOS and iOS β no AOT compile needed. | |
| ## Measured | |
| | | decode | prefill | numerics | | |
| |---|---:|---:|---| | |
| | **M4 Max** (Mac Studio, macOS 27.0) | **268.4 tok/s** | **4161 tok/s** | 16/16 token-exact vs the fp32 HF oracle | | |
| | **iPhone 17 Pro** (A19 Pro, Release) | **62.4 tok/s** | **69.0 tok/s** | 276/276 + 27/27 token-exact vs the Mac engine | | |
| `device == Mac == fp32 HF`. Load 0.2β1.0 s on device. The iPhone numbers are cold and | |
| reproduced across two runs; **under sustained load expect about half** (34.9 prefill / 30.5 | |
| decode after back-to-back 1024-token generations, restored by seven idle minutes β thermal, | |
| not a regression). A dictation post-processor runs repeatedly, so plan against the sustained | |
| number. | |
| ### Task quality | |
| The conversion gate above is a free-run continuation, which on a single-task model measures | |
| the base language prior and very little of the task. So this port also gates the model in its | |
| own input format, across the card's three control axes, against the released weights run | |
| through `transformers`: **13/14**, the one miss being punctuation | |
| (`$23,450 and` for `$23,450, and`). | |
| ## β οΈ iPhone ceiling: prompt + generated must stay under 1024 tokens | |
| Measured: a 611-token transcript whose rewrite runs 603 tokens produced **413 tokens on | |
| device, every one token-identical to the Mac**, then stopped at absolute position exactly | |
| **1024**. Truncation, not corruption. | |
| This is shipped engine behaviour β `CoreAIPipelinedEngine` caps iOS growing-KV capacity at | |
| 1024 (`1024 - processed - prompt.count`) and throws `contextLengthExceeded` when a prompt | |
| leaves no budget, guarding the iOS compiler's miscompilation of growing-KV specializations at | |
| seq β₯ 2048. `1024 β 611 = 413`, exactly the measurement. | |
| **Chunk input to roughly β€450β500 tokens** so prompt + rewrite clears the cap. macOS has no | |
| such cap. | |
| ## Prompt format β `enable_thinking=False` is mandatory | |
| The system prompt and the control line are part of the trained input format. Leave thinking | |
| on and the model emits an empty `<think>` block and stops: every call returns the empty | |
| string, which reads like a working pipeline producing nothing. | |
| ``` | |
| <|im_start|>system | |
| 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.<|im_end|> | |
| <|im_start|>user | |
| [Styling: semi-formal] [Structure: prose] [Context: general] | |
| <raw transcript><|im_end|> | |
| <|im_start|>assistant | |
| <think> | |
| </think> | |
| ``` | |
| `Styling` β `casual` / `semi-casual` / `semi-formal` / `formal` Β· | |
| `Structure` β `prose` / `lists` Β· `Context` β `general` / `email`. | |
| All three axes are independent and every combination was trained. | |
| Example, `[Styling: semi-formal] [Structure: prose] [Context: general]`: | |
| | in | out | | |
| |---|---| | |
| | `so um i need to like send the the report by uh friday no wait make that thursday` | `So I need to send the report by Thursday.` | | |
| | `the invoice came to twenty three thousand four hundred and fifty dollars and it's due on march third twenty twenty six` | `The invoice came to $23,450 and it's due on March 3, 2026.` | | |
| | `um` | *(empty string)* | | |
| ## Quantization | |
| - **Body int8**, per-block-32 `symmetric_with_clipping`; norms, RoPE, SDPA and the embedding | |
| stay full precision. | |
| - **No head quantization, on purpose.** The head is *tied* to the 151936Γ1024 embedding, and | |
| the eager quantizer skips shared params β so quantizing it means untying it first, which | |
| *adds* a tensor rather than shrinking one: tied fp16 embed+head is 311 MB, while fp16 embed | |
| + int8 untied head is 311 + 156 = 467 MB. Untying is a pure loss at every bit width. | |
| - **int4 is a measured no-go and is not published here.** It is 549 MB, decodes faster, and | |
| passes the *same* 16/16 fp32 oracle gate β and it corrupts digits: `$23,450` β `$2,345`, | |
| `107` β `177`, and it drops "tomorrow" from a time normalization. For a model whose job | |
| includes inverse text normalization of money and counts, that closes it. Only the | |
| task-format gate sees this; the continuation gate is blind to it. | |
| ## Reproduce | |
| Exporter, gates, card and port notes live in the | |
| [Core AI model zoo](https://github.com/john-rocky/coreai-model-zoo): | |
| [`models/s1-mini/`](https://github.com/john-rocky/coreai-model-zoo/tree/main/models/s1-mini), | |
| [`conversion/export_s1_mini_decode_pipelined.py`](https://github.com/john-rocky/coreai-model-zoo/blob/main/conversion/export_s1_mini_decode_pipelined.py), | |
| [`knowledge/s1-mini-port.md`](https://github.com/john-rocky/coreai-model-zoo/blob/main/knowledge/s1-mini-port.md). | |
| ```bash | |
| python3 conversion/zoo_convert.py show s1-mini | |
| python3 conversion/zoo_convert.py run s1-mini | |
| ``` | |
| ## Credits | |
| Model: **S1-mini** by **Superwhisper** ([superwhisper.com](https://superwhisper.com)). | |
| Core AI conversion: the Core AI model zoo. | |