Qwen3-Embedding-0.6B β€” LiteRT on-device text embeddings (fully GPU)

Qwen3-Embedding-0.6B (Apache-2.0), the 2025 state-of-the-art small text-embedding model, re-authored to run entirely on the LiteRT CompiledModel GPU (ML Drift). Embed a query and a set of documents on-device and rank by cosine similarity β€” the retrieval half of a RAG pipeline, no server and no CPU fallback. The Hexagon NPU runs this graph too, and faster; see the section below.

Because sentence embedding uses last-token pooling of a single forward pass (no generation, no KV cache), the model is a plain single-graph .tflite β€” not a .litertlm β€” and runs on the same GPU path as any CNN/ViT.

On-device semantic search on a Pixel 8a

Verified on a Pixel 8a / Tensor G3: CompiledModel GPU compile OK, all 3264/3264 nodes on the GPU delegate (zero CPU fallback), ~390 ms per embedding, fp16 881 MB, output cosine 0.9997 vs the HF fp32 reference. Semantic ranking is correct β€” query "What is the capital of China?" β†’ "The capital of China is Beijing" at 0.77, unrelated docs at <0.1.

Files

file purpose runs on
qwen3emb_gpu_fp16.tflite 28-layer Qwen3 transformer, inputs_embeds[1,128,1024] β†’ hidden[1,128,1024] GPU
embeddings_fp16.bin tied token-embedding table [151669,1024] fp16, for the host-side lookup host
vocab.json, merges.txt Qwen byte-level BPE tokenizer host

Pipeline

text β†’[BPE tokenize]β†’ ids β†’[host embed lookup]β†’ inputs_embeds[1,128,1024]
     β†’[GPU: 28-layer Qwen3 decoder]β†’ hidden[1,128,1024]
     β†’[pool last token + L2-normalize (+ optional Matryoshka 1024β†’N)]β†’ embedding
     β†’[cosine]β†’ ranked documents

The token-embedding lookup is a GATHER (GPU-banned), so it is done on the host and fed in as inputs_embeds, exactly like mel/log-mel preprocessing in the audio samples.

Why it runs fully on GPU β€” a Mali fp16 finding

A 28-layer decoder is the first decoder-transformer verified end-to-end on this GPU path. The one device-only fix: the residual stream grows across depth, so the deep RMSNorm's mean(xΒ²) overflows fp16 (>65504) β†’ rsqrt(inf)=0 β†’ the whole output collapses to 0 (even though Qwen3 already RMSNorm+qk-norms every sub-layer input β€” it is the residual that overflows). The fix is a per-row max-normalized RMSNorm, mathematically identical to the original:

m  = max(|x|).clamp_min(1e-4)          # per-row scale
xs = x / m                              # xΒ² now in [0,1] β€” the 1024-term sum never overflows
y  = xs * rsqrt(mean(xsΒ²) + eps/mΒ²) * w

GQA heads are cat-repeated to 16 (a broadcast matmul would emit the Mali-rejected BROADCAST_TO), RoPE and the causal mask are baked constants, and every tensor stays ≀4D.

Minimal usage

Python (reference embeddings with the original model):

from sentence_transformers import SentenceTransformer
m = SentenceTransformer("Qwen/Qwen3-Embedding-0.6B")
q = m.encode("What is the capital of China?", prompt_name="query")
docs = m.encode(["The capital of China is Beijing.", "Paris is the capital of France."])
print((q @ docs.T))          # cosine similarity β€” the .tflite reproduces this at corr 0.9997

Kotlin (on-device, LiteRT CompiledModel GPU):

val model = CompiledModel.create("qwen3emb_gpu_fp16.tflite",
    CompiledModel.Options(Accelerator.GPU), null)
val inputs = model.createInputBuffers(); val outputs = model.createOutputBuffers()

// host: BPE tokenize -> lookup embeddings_fp16.bin -> inputs_embeds[1,128,1024]
inputs[0].writeFloat(embedLookup(tokenize(text)))
model.run(inputs, outputs)
val hidden = outputs[0].readFloat()          // [128,1024]
val emb = l2normalize(hidden, poolPos)       // last real token -> 1024-d embedding

Full tokenizer + embedding-lookup + semantic-search app: see the official LiteRT sample.

Conversion

The GPU-clean re-authoring is fully reproducible β€” conversion scripts (build_qwen3emb.py, export_embeddings.py) and a device-parity harness are provided with the official sample.

Performance

Measured on a Pixel 8a (Tensor G3, Android 16) with the standard TFLite benchmark_model tool β€” 10 warm-up runs then 50 timed runs, reported as the tool's mean.

Runtime Backend Graph on GPU Latency
LiteRT CompiledModel (LITERT_CL) GPU 3264 / 3264 ~390 ms
TFLite benchmark_model (TfLiteGpuDelegateV2) GPU (OpenCL) 108 / 3264 5191.2 ms
TFLite benchmark_model CPU (XNNPACK, 4 threads) β€” 2076.8 ms

The two GPU rows are different runtimes, not a contradiction. The LITERT_CL figure is the one recorded when this model shipped, taken through LiteRT's own CompiledModel accelerator β€” the path the Kotlin sample app and the LiteRT API use. The TfLiteGpuDelegateV2 figure is the classic TFLite OpenCL delegate, measured with a tool anyone can download and re-run. They agree on how much of the graph the GPU takes; they disagree on speed, and the classic delegate is the slower of the two here. Read the TfLiteGpuDelegateV2 row as a reproducible floor, not as this model's speed on LiteRT.

On this delegate the CPU is the faster choice (2076.8 ms on CPU against 5191.2 ms on GPU) β€” worth knowing before you reach for the GPU on a mid-range phone.

Note that the GPU does not take the whole graph here (108 / 3264); the remainder runs on the CPU and the split costs a per-partition round trip.

Snapdragon NPU (Hexagon)

The NPU is 1.76x faster than the GPU (25.44 ms against 44.74 ms) and loads 13.16x faster (292 ms against 3842 ms).

backend compiled inference (median / min) load
NPU (Hexagon v81) AOT (SM8850) 25.44 ms / 25.06 ms 292 ms
GPU (Adreno) β€” 44.74 ms / 43.75 ms 3842 ms

Measured on a Samsung Galaxy S26 (Snapdragon 8 Elite Gen 5 / SM8850, Hexagon v81, Android 16) with LiteRT CompiledModel 2.2.0, one accelerator per process, 5 warm-up runs then N=50 timed runs, median reported. Every run held thermal status NONE throughout. Headroom 0.76–0.78, where 1.0 is the throttling threshold.

The NPU row marked AOT ran an artifact compiled ahead of time for SM8850 (ai-edge-litert 2.2.0 + QAIRT 2.47.0), not the published file. That artifact is not distributed here; the compile is one command in the NPU guide.

GPU wiring: GPU guide.

Downloads last month
58
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Model tree for litert-community/Qwen3-Embedding-0.6B-LiteRT

Finetuned
(272)
this model

Collection including litert-community/Qwen3-Embedding-0.6B-LiteRT