Instructions to use adidsh/indic-speak-int8-onnx 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 adidsh/indic-speak-int8-onnx 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 adidsh/indic-speak-int8-onnx:Q5_K_M # Run inference directly in the terminal: llama cli -hf adidsh/indic-speak-int8-onnx:Q5_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf adidsh/indic-speak-int8-onnx:Q5_K_M # Run inference directly in the terminal: llama cli -hf adidsh/indic-speak-int8-onnx:Q5_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 adidsh/indic-speak-int8-onnx:Q5_K_M # Run inference directly in the terminal: ./llama-cli -hf adidsh/indic-speak-int8-onnx:Q5_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 adidsh/indic-speak-int8-onnx:Q5_K_M # Run inference directly in the terminal: ./build/bin/llama-cli -hf adidsh/indic-speak-int8-onnx:Q5_K_M
Use Docker
docker model run hf.co/adidsh/indic-speak-int8-onnx:Q5_K_M
- LM Studio
- Jan
- Ollama
How to use adidsh/indic-speak-int8-onnx with Ollama:
ollama run hf.co/adidsh/indic-speak-int8-onnx:Q5_K_M
- Unsloth Desktop
- Docker Model Runner
How to use adidsh/indic-speak-int8-onnx with Docker Model Runner:
docker model run hf.co/adidsh/indic-speak-int8-onnx:Q5_K_M
- Lemonade
How to use adidsh/indic-speak-int8-onnx with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull adidsh/indic-speak-int8-onnx:Q5_K_M
Run and chat with the model
lemonade run user.indic-speak-int8-onnx-Q5_K_M
List all available models
lemonade list
- Atomic Chat
Download token_contract.md from adidsh/indic-speak-int8-onnx: direct link, hf CLI and curl.
- Browser
- Download file 8.38 kB
-
https://huggingface.co/adidsh/indic-speak-int8-onnx/resolve/main/token_contract.md
- Command line
-
hf download hf://adidsh/indic-speak-int8-onnx/token_contract.md
-
curl -L -o token_contract.md https://huggingface.co/adidsh/indic-speak-int8-onnx/resolve/main/token_contract.md
Token contract β llama-3-audio-tokenizer
The authoritative description of what every token ID means in this project's compiled data, checkpoints and eval paths. Generated from the tokenizer itself, not transcribed by hand.
tokenizer: checkpoints/llama-3-audio-tokenizer
vocab size: 156,960
fingerprint: b645cf6612315393eea21d29e94304bdbcbfee131a25de5eecf6bae6ee9f39c5
base model: Llama-3.2-3B (128,000 BPE + 256 Llama specials)
A token ID is meaningless without this contract. Compiled parquet stores raw
integers; nothing in the data says which tokenizer minted them. Compiling with one
tokenizer and training with another is silent β training runs, loss descends, and
the model learns the wrong symbol for every audio frame. That is not hypothetical:
it is exactly how the gemma3 SNAC base mismatch produced undecodable checkpoints,
caught only at eval. Hence the fingerprint, stamped at compile time and asserted at
training startup and in the eval decode path (scripts/token_contract.py).
1. ID map
| range | count | what it is |
|---|---|---|
0 β 127,999 |
128,000 | Llama-3 BPE text vocabulary |
128,000 β 128,255 |
256 | stock Llama-3 specials (<|begin_of_text|>, <|eot_id|>, <|reserved_special_token_N|> β¦) |
128,256 β 128,265 |
10 | project control tokens (Β§2) |
128,266 β 156,937 |
28,672 | SNAC audio codes β 7 codebooks Γ 4,096 (Β§3) |
156,938 β 156,959 |
22 | conditioning + paralinguistic tokens (Β§4) |
28,960 added tokens in total (28,672 SNAC + 288 non-SNAC).
Note the layout is discontinuous: the control block sits immediately below the audio band and the conditioning block immediately above it. Anything that assumes "all added tokens are contiguous above the base" is wrong.
2. Control tokens β 128,256 β 128,265
| id | token | role |
|---|---|---|
| 128256 | <|reserved_0|> |
unused |
| 128257 | <|start_of_speech|> |
opens the audio span; the model emits this itself as its first generated token |
| 128258 | <|end_of_speech|> |
closes the audio span |
| 128259 | <|start_of_human|> |
opens the prompt turn |
| 128260 | <|end_of_human|> |
closes the prompt turn |
| 128261 | <|start_of_ai|> |
opens the model turn |
| 128262 | <|end_of_ai|> |
closes the model turn |
| 128263 | <|pad|> |
padding |
| 128264 | <|reserved_8|> |
unused |
| 128265 | <|reserved_9|> |
unused |
3. Audio band β 128,266 β 156,937
audio_token_base_id = 128266
codebooks = 7
codebook size = 4096
total audio tokens = 28672 (base .. base + 7*4096 - 1 = 156937)
SNAC 24 kHz emits three codebooks at a 1:2:4 temporal ratio:
c0: [seq_len] 12 Hz coarsest
c1: [2*seq_len] 23 Hz
c2: [4*seq_len] 47 Hz finest
These are flattened to 7 tokens per frame, in this fixed interleave:
frame i -> [ c0[i], c1[2i], c2[4i], c2[4i+1], c1[2i+1], c2[4i+2], c2[4i+3] ]
Each raw code (0β4095) is offset by its position in the frame, not by which codebook it came from:
| frame position | source | offset | id range |
|---|---|---|---|
| 0 | c0[i] |
base + 0Γ4096 | 128,266 β 132,361 |
| 1 | c1[2i] |
base + 1Γ4096 | 132,362 β 136,457 |
| 2 | c2[4i] |
base + 2Γ4096 | 136,458 β 140,553 |
| 3 | c2[4i+1] |
base + 3Γ4096 | 140,554 β 144,649 |
| 4 | c1[2i+1] |
base + 4Γ4096 | 144,650 β 148,745 |
| 5 | c2[4i+2] |
base + 5Γ4096 | 148,746 β 152,841 |
| 6 | c2[4i+3] |
base + 6Γ4096 | 152,842 β 156,937 |
So positions 1 and 4 are both c1, and 2/3/5/6 are all c2 β the offset encodes
where in the frame a code sits, which is what makes the stream decodable without
a separate structure signal.
Consecutive duplicate frames are removed at encode time (frames sharing the
same c0), so token count is not exactly proportional to duration.
Derived constants (scripts/snac_tokenizer.py):
samples per c0 frame = 512 (encoder_rates [2,4,8,8] x vq_stride 4)
streaming window = 4 frames = 28 tokens, middle frame kept
long-audio window = 512 frames (~43.7 s), 4-frame context each side
Rule of thumb used throughout the project: 82 tokens β 1 second of audio.
4. Conditioning + paralinguistics β 156,938 β 156,959
| id | token | role |
|---|---|---|
| 156938 / 156939 | <|speaker> / <speaker|> |
wrap a speaker name |
| 156940 / 156941 | <|style> / <style|> |
wrap a style label (rasa) or accent string (globe) |
| 156942 / 156943 | <|env> / <env|> |
wrap an environment label; open class, label stays free text |
Non-verbals β a closed set of 16, one token each (no wrapper):
| id | token | id | token | |
|---|---|---|---|---|
| 156944 | <|nv_breath|> |
156952 | <|nv_hum|> |
|
| 156945 | <|nv_stammer|> |
156953 | <|nv_gasp|> |
|
| 156946 | <|nv_throat|> |
156954 | <|nv_wheeze|> |
|
| 156947 | <|nv_laugh|> |
156955 | <|nv_sneeze|> |
|
| 156948 | <|nv_swallow|> |
156956 | <|nv_snort|> |
|
| 156949 | <|nv_sniff|> |
156957 | <|nv_yawn|> |
|
| 156950 | <|nv_sigh|> |
156958 | <|nv_groan|> |
|
| 156951 | <|nv_cough|> |
156959 | <|nv_burp|> |
The asymmetry is deliberate: non-verbals are a closed vocabulary and get dedicated
tokens; environment labels are an open class, so only the wrapper is a token and
the label inside stays free text β a new environment class needs no tokenizer
change. Source-form mapping (<breath>, [bird_squawk], β¦) is in
scripts/paralinguistics.py.
5. Sequence layouts
Built by scripts/chat_templates.py. prompt_end is defined as everything up to
and including <|start_of_ai|> β the prompt therefore stops before
<|start_of_speech|>, which the model emits itself.
TTS with conditioning (rasa, globe, bhili):
<|start_of_human|><|begin_of_text|>
<|speaker>NAME<speaker|>\n
<|style>LABEL<style|>\n
TEXT
<|eot_id|><|end_of_human|><|start_of_ai|>
<|start_of_speech|> ...audio... <|end_of_speech|>
<|end_of_ai|>
Metadata order is always speaker β style β accent, each block followed by a newline. An empty value emits nothing at all (no empty wrapper).
Multi-turn conversation (gemini_vc_conversational) β no metadata prefix;
speaker labels are inline turn markers inside the text:
<|start_of_human|><|begin_of_text|>
<|speaker>A<speaker|>\nturn one\n\n<|speaker>B<speaker|>\nturn two ...
<|eot_id|><|end_of_human|><|start_of_ai|><|start_of_speech|> ...
Turn separator is a blank line (\n\n) before each subsequent
<|speaker> marker. normalize_text preserves newline runs (the old
collapse-to-one-space behavior was removed when the \n\n issue was fixed),
so the separator reaches the model verbatim; verified present in 100% of
compiled multi-turn rows in both gemini_vc and gemini_src_conv. The \n
after <speaker|> also survives. Inference prompts must match this form.
6. Fingerprint
scripts/token_contract.py::compute_fingerprint is a sha256 over exactly the
things that change what an ID means:
- the full added-token map (content β id), sorted
- vocab size
- the SNAC base id and layout constants (codebooks Γ codebook size)
It deliberately excludes tokenizer_config.json niceties β padding side, chat
template, model_max_length β because those do not change a token's meaning and
including them would fire on cosmetic edits.
current fingerprint: b645cf6612315393eea21d29e94304bdbcbfee131a25de5eecf6bae6ee9f39c5
Why a content hash and not a range check: the audio-band range check in
snac_tokenizer.decode_audio catches the loud failure (IDs outside the band). It
cannot catch the quiet one β sibling tokenizers llama-3-audio-tokenizer
(156,938), -tok_trimmed (156,942) and -style (156,952) all share base 128,266,
so every range check passes while <|style> means something different in the data
than in the model.
Mismatch is a hard error, never a warning. A silent wrong-tokenizer run costs a full training cycle.
Generated from checkpoints/llama-3-audio-tokenizer with scripts/token_contract.py;
layout constants from scripts/snac_tokenizer.py, sequence templates from
scripts/chat_templates.py.