Instructions to use litert-community/Spark-X2.5-4B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT-LM
How to use litert-community/Spark-X2.5-4B with LiteRT-LM:
# LiteRT-LM runs on various platforms (Android, iOS, Windows, Linux, macOS, IoT, Web/WASM) # and supports many APIs (C++, Python, Kotlin, Swift, JavaScript, Flutter). # For platform-specific integration guides, please refer to the official developer website: # https://ai.google.dev/edge/litert-lm # To try LiteRT-LM, the easiest way is to use our CLI tool. # 1. Install the LiteRT-LM CLI tool: pip install -U litert-lm # 2. Download and run this model locally: # See: https://ai.google.dev/edge/litert-lm/cli litert-lm run \ --from-huggingface-repo=litert-community/Spark-X2.5-4B \ --prompt="Write me a poem"
- LiteRT
How to use litert-community/Spark-X2.5-4B with LiteRT:
# No code snippets available yet for this library. # To use this model, check the repository files and the library's documentation. # Want to help? PRs adding snippets are welcome at: # https://github.com/huggingface/huggingface.js
- Notebooks
- Google Colab
- Kaggle
Spark-X2.5-4B — LiteRT-LM
XHToken/Spark-X2.5-4B converted to the LiteRT-LM (.litertlm) format for on-device inference with Google's LiteRT-LM runtime. Tested on litert-lm 0.17.0.
Spark-X2.5 is the SparkLLM Team's (iFLYTEK) open model series released in August 2026 — a 4.11B dense decoder (36 layers, hidden 2560, 16 query / 4 KV heads of 256, sliding-window(512) x3 : full x1, 131,072-entry tied vocab) with a hybrid attention layout of three sliding-window layers per full-attention layer, per-head sigmoid attention-output gates, exact-GELU gated MLPs and a native 1M-token context in the original. It is a reasoning model: it works problems inside <think>…</think> before answering, and these bundles carry that machinery — the generation prompt pre-fills the think opener exactly as the vendor chat template does, and a thought channel is declared in the bundle metadata so the runtime separates reasoning from the answer and honours a thinking budget. Apache-2.0.
| File | Recipe | Size |
|---|---|---|
Spark-X2.5-4B_int8.litertlm |
int8 dynamic on linears + embedding | 4238 MB |
Spark-X2.5-4B_int4.litertlm |
int4 blockwise-128 + OCTAV on linears, int8 embedding (externalized) | 2482 MB |
Both files are at bf16 parity on GSM8K (94 = 94 = 94) — with fp32 GPU activations declared in the bundle (under the runtime's default fp16 GPU activations the same int8 weights scored 84; see Conversion notes). int4 (block-128) is the recommended file: same accuracy, 41% smaller (2.48 GB), and the faster GPU file on the Mac (53.6 vs 49.4 tok/s decode). int8 (4.24 GB) is the CPU-prefill file (345 vs 118 tok/s on the Mac CPU).
Correctness
- 8-question sanity gate (Apple M4 Max, litert-lm 0.17.0 CLI, one process per question, greedy, thinking on): int8 CPU 8/8 / GPU 8/8, int4 CPU 8/8 / GPU 8/8; the bf16 PyTorch reference scores 8/8 on the same questions through the vendor chat template. Every answer arrived as a clean final answer through the thought channel — no reasoning leakage, no degeneration, every think block closed.
- Tokenizer parity: the bundle's tokenizer section (the upstream
tokenizer.json, byte-level BPE) encodes 234 of 234 probe rows — every added token alone and mid-string, the role-marker turn, Latin-1 / Extended-A, emoji, CJK, digits, whitespace — to the same ids as thetokenizersreading of the upstream file. - Multi-turn (3 turns, python API, greedy: plant a fact, do arithmetic, recall the fact): pass on both files, with and without the runtime's channel filtering; no marker leakage.
Accuracy — GSM8K
GSM8K, greedy, 0-shot chain-of-thought, 3584 output tokens (a reasoning model truncated mid-thought never reaches its answer; 2048 cut a third of the bf16 model's first questions), n=100, identical prompt, harness and answer extraction for every row; the LiteRT rows ran on the litert-lm 0.17.0 engine (GPU backend), scored on the text after the thought channel:
| Configuration | GSM8K |
|---|---|
| PyTorch bf16 (reference, MPS) | 94% (6 unfinished at the 3584-token cap) |
| LiteRT int8 | 94% (7 unfinished at the 3584-token cap) |
| LiteRT int4 | 94% (7 unfinished at the 3584-token cap) |
Usage
litert-lm run ./Spark-X2.5-4B_int8.litertlm --prompt "What is the capital of France? Answer in one word." --thinking true
# GPU
litert-lm run ./Spark-X2.5-4B_int8.litertlm --backend gpu --cache no --thinking true --prompt "..."
Notes for a reasoning model:
- Give it a generous output budget (≥ 2048 tokens, 3584 for math). The model thinks before it answers; truncated mid-thought it produces no final answer at all.
- The bundle declares the
thoughtchannel (<think>…</think>), so runtimes that exposeThinkingConfig/ a thinking budget can cap or read the reasoning separately; the streamed answer contains only the final response.enable_thinking: falserenders the vendor's no-think form (<|Bot|></think>). - The bundle carries the vendor prompt format as a Jinja template: a default system block (
<|System|>\nyou are a helpful assistant., a user system prompt appended after it), every message wrapped in<|start▁of▁sentence|> … <|end▁of▁sentence|>, generation prompt<|Bot|><think>; stop token<|end▁of▁sentence|>. Tool-call formatting is not carried. KV budget 4096 tokens (the original's 1M context does not apply on-device), six prefill signatures (1024, 256, 64, 16, 4, 1) — six rather than eleven because every exported signature is charged engine memory whether or not it is called. - The vendor's recommended sampling is temperature 1.0 / top-p 0.95; the numbers on this card are greedy.
Performance
Apple M4 Max (litert-lm benchmark 0.17.0, -p 256 -d 256 --runs 3 --cache no, quiet machine, serialized, ≥300 s rest before each GPU reading; every backend first proven to generate on the file):
| File | Backend | Prefill (256) | Decode | TTFT | Init |
|---|---|---|---|---|---|
| int8 | GPU (Metal) | 784 tok/s | 49.4 tok/s | 0.35 s | 4.1 s |
| int8 | CPU | 345 tok/s | 19.5 tok/s | 0.79 s | 27.0 s |
| int4 | GPU (Metal) | 826 tok/s | 53.6 tok/s | 0.33 s | 3.7 s |
| int4 | CPU | 118 tok/s | 18.4 tok/s | 2.24 s | 5.3 s |
Galaxy S26 (Adreno) rows will be appended once measured on the device.
iPhone 17 Pro (G41DeviceTest harness, composite 8-question prompt, --max-tokens 3072, on-device byte count verified against the source file; score = questions answered correctly inside one reply):
| File | Metal GPU | CPU | Init GPU | Init CPU |
|---|---|---|---|---|
| int8 | 8/8 | 8/8 | 2.9 s | 13.2 s |
| int4 | 7/8 | 7/8 | 5.3 s | 9.0 s |
Both files run with fp32 GPU activations on the phone as well. The int8 file is a single 4.24 GB weights section and loads under this harness (Increased Memory Limit entitlement; available memory floor ~2.6 GB on the Metal leg, ~4.5 GB on the CPU leg); the int4 file's Metal leg bottomed at ~2.0 GB free. GPU init times are with a warm shader cache (a cold first launch of the int8 file initialised in 18.8 s). The int4 file's one miss on each backend is the rhyme line at the end of the composite 8-question prompt (it answers "sweet"); asked on its own the same question is answered "blue" on every backend.
Conversion notes
Converted with litert-torch 0.9.3 / transformers 5.14.1 / ai-edge-quantizer, released wheels (reproduction script: hf-to-litertlm).
- The vendor modeling code is patched for export, not re-implemented.
modeling_spark.pycomputes attention through its own eager function and ignoresconfig._attn_implementation; the export copy dispatches through the registered attention interface (so litert-torch's transposed KV cache is used), threads the per-call kwargs, declares the attention-backend capability flags, and applies the per-head sigmoid output gate in the interface's layout. In eager mode the patched file is bit-identical to the vendor file (max |Δlogit| 0.0 on 24 random tokens); two further edits make the vendor file load under transformers 5 at all (_tied_weights_keysmapping form, mask-utility kwargs). - The think opener is pre-filled by the bundle's template and the
thoughtchannel is declared in the metadata. Without the channel the runtime streams raw reasoning into the answer and silently ignores any thinking budget. - No start token in the metadata. The tokenizer declares
<|start▁of▁sentence|>as BOS but never prepends it (add_bos_token: false); the template carries its own. The exporter's unconditionalstart_tokenwrite was suppressed (measured harmless in bf16 on the 8-question gate, but it is not the vendor prompt). - int4 externalizes the embedding table. The vocab is tied; asking int4 for the lm_head and int8 for the embedding makes the quantizer copy the 131,072-row table once per signature (measured 4.6 vs 1.7 bytes/parameter on a tiny checkpoint). The embedder lives in its own section instead. The int8 file needs no split.
- GPU activations are declared fp32 in the bundle (
prefer_activation_type = "fp32", a metadata-only repack; weights byte-identical). The runtime runs the text decoder with fp16 activations on the GPU by default, and on this 36-layer decoder that silently costs reasoning accuracy: the same int8 weights scored GSM8K 84 under fp16 GPU activations and 94 under fp32 — established by re-running the GPU losses on the CPU (fp32) path, where 10 of 11 came back right. The 8-question gate did not see it (8/8 either way); only a long-generation accuracy row does. Expect a larger GPU memory footprint than an fp16-activation file of the same size. - Tokenizer embedded as the upstream
tokenizer.json(HF tokenizer section), not a SentencePiece conversion. - Quantization at export time: int8 = dynamic per-channel on linears + embedding; int4 = int4 blockwise-128 + OCTAV on linears, int8 embedding (externalized). No post-processing.
License and changes
Distributed under Apache-2.0 (inherited from the base model; the upstream LICENSE file is included). Changes from the original work: weights converted from safetensors bf16 to LiteRT flatbuffers and quantized as described above; tokenizer and chat template repackaged into the .litertlm bundle (thinking pre-fill and thought-channel metadata as described); tool-calling template branches not carried. No training or fine-tuning. This repository is a community conversion and is not affiliated with iFLYTEK or the SparkLLM Team.
- Downloads last month
- -