Instructions to use litert-community/Ovis2.5-2B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LiteRT-LM
How to use litert-community/Ovis2.5-2B 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 # A single .litertlm file in the repo is picked automatically; otherwise the CLI asks which one to run # (or pass its name right after the repo id). litert-lm run \ --from-huggingface-repo=litert-community/Ovis2.5-2B \ --prompt="Write me a poem"
- LiteRT
How to use litert-community/Ovis2.5-2B 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
Ovis2.5-2B β LiteRT-LM (on-device Vision-Language Model)
AIDC-AI/Ovis2.5-2B converted to the LiteRT-LM
(.litertlm) format for on-device image+text inference with Google's
LiteRT-LM runtime (the engine behind the official
litert-community/* models, and the same runtime that runs litert-community/FastVLM-0.5B).
Ovis2.5 is a SOTA-for-size vision-language model (OpenCompass ~73.9 for the 2B) with a distinctive
structural-embedding vision path: a Siglip2 NaViT encoder feeds a visual tokenizer that turns
each image patch-group into a probability distribution over a 65 536-word visual vocabulary, then
embeds it β giving the language model image tokens that live in the same structured space as text.
The language decoder is Qwen3-1.7B. This bundle runs the whole thing through LiteRT-LM's fast_vlm
multimodal path β give it an image and a question, get a grounded answer, fully on-device.
| File | Ovis2.5-2B.litertlm (~2.15 GB) |
| Vision | Siglip2-NaViT encoder + visual-tokenizer (head β softmax β visual-vocab embedding), int8 weights β single 512Γ512 image β 256 image tokens |
| Decoder | Qwen3-1.7B, int4 weights (symmetric, blockwise-32 + OCTAV optimal-clipping); input embedding INT8 (externalized section) |
| Compute | integer |
| Context (KV cache) | 2048 |
| Image input | resized to 512Γ512 (Siglip normalization is baked into the vision encoder) |
| Base model | AIDC-AI/Ovis2.5-2B (Apache-2.0) |
How to use
1. Install the runtime
pip install litert-lm
2. Run it in one command β this downloads the bundle, encodes your image and answers:
litert-lm run --from-huggingface-repo litert-community/Ovis2.5-2B Ovis2.5-2B.litertlm \
--attachment photo.jpg \
--prompt "Describe this image in one sentence."
On the COCO sample image huggingface/documentation-images/coco_sample.png (two tabby cats on a pink blanket, remote controls beside them) this prints:
Three tabby kittens lie on a pink blanket, with two remote controls beside them.
Drop --prompt for an interactive chat, and pass --attachment more than once for several images. litert-lm serve exposes the same bundle as a local OpenAI-compatible API. The same file runs on macOS, Linux and Windows.
Performance
litert-lm benchmark (litert-lm 0.15.0) on an Apple M4 Max, -p 256 -d 256 --runs 3 (the tool averages three iterations), max-num-tokens 4096, warm-up run discarded, otherwise idle machine. These figures cover the text path; the vision encoder runs once per image and is not included.
| Device | Backend | Prefill (256) | Decode | TTFT |
|---|---|---|---|---|
| Apple M4 Max (macOS) | CPU | 141 tok/s | 34.9 tok/s | 2.00 s |
| Apple M4 Max (macOS) | GPU (Metal) | 1854 tok/s | 142.6 tok/s | 0.15 s |
Every desktop backend listed above was checked by actually generating a caption on it, not just by reading the benchmark tool's output.
Accuracy note
The vision tower converts bit-faithfully to the reference β float CPU-parity end-to-end
corr β 1.0 (max abs diff 3e-6), with no FLEX/CUSTOM fallback ops; int8 vision weights keep
end-to-end corr **0.99**. The Qwen3-1.7B decoder uses the same blockwise-32 + OCTAV int4 recipe
that scores 90.7% GSM8K on the sibling
Ministral-3-3B-Reasoning build
and shipped the InternVL3.5-2B VLM.
On a reference deployed-path eager run (fixed-512 vision β 256 tokens β Qwen3-1.7B) the model
describes real photos accurately and in detail (e.g. a black-and-white Ansel-Adams-style landscape β
"snow-capped sharp mountain peaks β¦ a river winding through the valley β¦ cloud layers β¦ black-and-white
contrast with depth of field").
Reasoning VLM. Ovis2.5 is a thinking model: it may emit a
<think>β¦</think>block before its final answer (this matches the base model). Allow enough max-tokens (β₯1024) for the answer to follow.
Thinking channel. Since the 2026-10-14 re-pack (metadata only: LlmMetadata.channels declares the thought channel with <think>β¦</think>; every other section of the file is byte-identical), litert-lm returns the reasoning on the thought channel (channels["thought"]) and the message text carries only the answer (litert-lm 0.18.0, measured 2026-10-14); the earlier file returned the <think> block inside the message text. enable_thinking=False does not switch the reasoning off (the chat template does not read it). If you downloaded before 2026-10-14, re-download.
On-device performance: decode/load are expected to be in line with the InternVL3.5-2B build on the same runtime (~20 tok/s CPU, ~45 tok/s GPU on iPhone 17 Pro for single-image VQA). Independent on-device measurement for this specific build is recommended before quoting exact numbers.
Galaxy S26 β GPU backend
The published bundle runs on the Android GPU backend and generates.
| file | GPU backend | delegation | peak |
|---|---|---|---|
Ovis2.5-2B.litertlm |
runs | 3840 / 3840 ops across 3 subgraphs on LiteRT GPU |
820 MB |
Measured on a Samsung Galaxy S26 (SM-S942Q / SM8850, Android 16) with litert_lm_advanced_main from litert-lm 0.16.0, --backend=gpu --sampler_backend=cpu, prompt What is the capital of France?. Peak is the process high-water mark (VmHWM) sampled during that same run. Gated 2026-08-25.
The op counts above are the LiteRT GPU partitions. XNNPACK additionally takes 1 of the 4 nodes in main; the runtime accepts that split.
The gate prompt carries no image, so this covers engine creation and the text path. The vision path on the GPU is not measured here.
No speed rows, on purpose. On this handset the GPU backend wins prefill and does not win decode, so a GPU throughput figure only means something beside a CPU row from the same handset, and no S26 CPU row exists for this model yet.
GPU wiring, including the Gallery import toggle: GPU guide.
Run on iPhone / macOS
Use the LiteRT-LM Swift runtime (swift-litert-lm / the
LiteRTDemo sample). Load Ovis2.5-2B.litertlm with the image (vision) tower enabled (modalities
[.vision] / Modality.textImage), attach a photo, and ask a question.
Note for app integrators: this is a vision-only bundle (no audio tower). Bring up the engine with the vision modality only β requesting the audio tower (
.all) on a bundle with no audio section fails at session creation.
Run on Android β Google AI Edge Gallery
Install a recent Google AI Edge Gallery (1.0.16+ can
import .litertlm directly from Hugging Face), download Ovis2.5-2B.litertlm, import it (tap +),
attach an image and ask. The bundle already carries the tokenizer and prompt template.
Conversion notes
- LiteRT-LM
fast_vlmbundle: VISION_ENCODER ([1,512,512,3]β[1,256,4608]) + VISION_ADAPTER ([1,256,4608]β[1,256,2048], matched to the Qwen3-1.7B hidden size) + single-token EMBEDDER + PREFILL_DECODE (embeddings-input). - The NaViT static rewrite is the enabling trick. Ovis's Siglip2-NaViT vision tower is dynamic
resolution (
.item()/.tolist()/grid-loops/argsort) and does nottorch.export. Because the config'sfullatt_block_indexes=Nonemakes every layer use full attention, the window-reorder is a mathematical no-op β so it can be dropped and replaced with a precomputed position embedding + rotary and a single full attention over the fixed 512Γ512 grid (1024 patches). Static-vs-original feature corr 0.99999964. - The encoder bakes Siglip normalization (
(x-0.5)/0.5, the runtime feeds a[0,1]NHWC image) and does patchify GPU-safe: the patch-embedding Conv2d is applied to the whole image (raster order), then a single gather reorders patches into Ovis's hidden-stride "merge" order β all reshapes β€4D, no>5Dop that GPU delegates reject. - The adapter is Ovis's visual-tokenizer tail:
head(Linear 4608β65532 + LayerNorm) β softmax β visual-vocabulary embedding (vte, 65536Γ2048). The 256-token bundle carries the visual atoms; Ovis's two learned image-boundary indicator embeddings are omitted (thefast_vlmpath splices only the atom embeddings) β verified to stay coherent in eager. - Decoder extracted from the Ovis2_5 wrapper as a standalone
Qwen3ForCausalLMand exported with cache β€ base max so base RoPE is exact.
2026-08-28 β start_token fix (weights unchanged)
The bundle's LlmMetadata start_token held the literal string "None". This tokenizer has no BOS, and the LiteRT-LM engine resolved that string to a real vocabulary token β so every prompt began with the word None, which the model was never trained on. The start token has been removed.
Metadata-only change: every section of the bundle except the LlmMetadata block is byte-identical to the previous file (verified by sha256 per section), so the weights, the graph and the tokenizer are unchanged and the speed and memory numbers on this card still describe exactly this file β only the file's own sha256 differs. What changed is the input: the token stream the model reads for a given conversation can differ from the previous file's, and it now matches this model's own reference chat stream. Greedy decoding can turn on a single token, so an individual answer can differ from the previous file in either direction. Unless a row says otherwise, the accuracy figures on this card were measured on the previous file and have not been re-measured on this one. If you downloaded before 2026-08-28, re-download.
2026-08-30 β tokenizer section replaced (weights unchanged)
The tokenizer in Ovis2.5-2B.litertlm was a SentencePiece conversion of the model's BPE tokenizer, and the conversion lost the byte-level semantics: a standalone accented letter or symbol (Γ©, Γ±, ΓΌ, Β°, Β·, β¦) was encoded to the id of a single-byte token instead of the token the upstream tokenizer uses, and any character without a whole-character vocabulary entry (emoji, most of Latin Extended-A) became the token the conversion had reused as UNK β the end-of-text token for this vocabulary. Ovis2.5-2B.litertlm now embeds the upstream tokenizer.json (the same HF tokenizer path most bundles in this collection use).
Tokenizer-only change: every section of the bundle except the tokenizer is byte-identical to the previous file (verified by sha256 per section), so the weights, the graph and the chat template are unchanged and the speed and memory numbers on this card still describe this file per token β only the file's own sha256 differs. Verified on the LiteRT-LM runtime: the default turn, 7 probe strings, the 223 standalone characters U+00A1βU+017F and every special token now tokenize identically to the upstream tokenizer, and the four ASCII-only test questions answer byte-identically to the previous file (same ids in, same tokens out). Prompts containing accented letters, symbols or emoji reach the model differently from before, so individual answers to such prompts can change. Unless a row says otherwise, the accuracy figures on this card were measured on the previous file, and any on-device rows were measured on the previous file too β the on-device gate has not been re-run on this one (the runtime's tokenizer code is the same on macOS and on device; the weights and graph are byte-identical). If you downloaded before 2026-08-30, re-download.
2026-08-31 β chat template fix: history turns with role 'assistant' (metadata-only, weights unchanged)
The chat template in Ovis2.5-2B.litertlm matched history turns only on role 'model', so a conversation created through the Conversation API with the standard role 'assistant' (for example create_conversation(messages=[...]) restoring a chat) silently dropped every assistant turn from the rendered prompt β the model saw consecutive user turns with its own replies gone. The template's role conditions now also accept 'assistant'. The engine's own send_message flow was never affected.
Template-only change: every section of the bundle except the metadata is byte-identical to the previous file (verified by per-section sha256), and single-turn renders, token ids, prefill counts and greedy answers are unchanged (verified on the LiteRT-LM runtime), so the numbers on this card still describe this file β only the file's own sha256 differs. Re-download only matters if you inject conversation history with role 'assistant'. Details: google-ai-edge/LiteRT-LM#3417 (https://github.com/google-ai-edge/LiteRT-LM/issues/3417).
Known runtime issues
After an answer without a thought (no <think> β¦ </think> block), from the second turn of a conversation on, LiteRT-LM puts the previous answer's stop token into the KV cache with a zero embedding, because this file holds the embedding table in its own section and the decoder takes embeddings, so later answers in a conversation can differ from the answer the model gives to the same messages in one prompt (read in the source of LiteRT-LM 0.16.0 to 0.18.1; measured with 0.18.1 on WeVisOne-VL-2B and Qwen2.5-Coder-1.5B-Instruct, not on this file). After an answer with a thought, the runtime rebuilds the cache from the re-rendered history at the next turn, so the second turn is free of it when the conversation opens with a user message; from the third turn on a zero embedding is written either way, at the previous answer's stop token or, after a rebuild, at another token (read in the source, not measured). The bundle's chat template leaves it to the model whether an answer has a thought. One question per conversation avoids both, as does a new conversation that starts with the earlier messages and the new question.
- Downloads last month
- 360
Model tree for litert-community/Ovis2.5-2B
Base model
ATH-MaaS/Ovis2.5-2B