lattice-embed
Vector embedding generation with SIMD-accelerated operations for semantic search and similarity matching.
Features
- Native Embeddings: Generate embeddings locally using pure Rust inference (no ONNX, no Python)
- SIMD Acceleration: AVX2/AVX-512/NEON optimized vector operations (7x speedup)
- LRU Cache: SHA-256-based caching to avoid recomputation
- Async API: Full async/await support with tokio
Models
| Model | Dimensions | Use Case | Model ID |
|---|---|---|---|
BgeSmallEnV15 |
384 | Fast, general purpose (default) | BAAI/bge-small-en-v1.5 |
BgeBaseEnV15 |
768 | Balanced quality/speed | BAAI/bge-base-en-v1.5 |
BgeLargeEnV15 |
1024 | Highest quality local | BAAI/bge-large-en-v1.5 |
MultilingualE5Small |
384 | Multilingual, same arch as BGE | intfloat/multilingual-e5-small |
MultilingualE5Base |
768 | Best multilingual quality/speed | intfloat/multilingual-e5-base |
AllMiniLmL6V2 |
384 | BERT-class, WordPiece tokenizer | sentence-transformers/all-MiniLM-L6-v2 |
ParaphraseMultilingualMiniLmL12V2 |
384 | Multilingual, XLM-R base | sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 |
Qwen3Embedding0_6B |
1024 | Multilingual, decoder-only, GPU-accelerated | Qwen/Qwen3-Embedding-0.6B |
Qwen3Embedding4B |
2560 | Multilingual, decoder-only, MRL-capable | Qwen/Qwen3-Embedding-4B |
EmbeddingGemma2 |
768 | Multilingual, bidirectional, MRL-capable | google/embeddinggemma-2 |
TextEmbedding3Small |
1536 | Remote API (OpenAI, scaffold-only) | text-embedding-3-small |
TextEmbedding3Small's ID is an OpenAI model id, not a HuggingFace one; EmbeddingModel::is_remote()
returns true for it and the native embedding service rejects it (see
supported-model reference).
Dimensions and input-token limits vary per model. See the supported-model reference for every variant's limit, pooling strategy, and shipped/partial/scaffold-only availability.
Services
NativeEmbeddingService
Single-model service with lazy initialization. Inference is serialized (one call at a time). Concurrency is handled internally.
use ;
let service = default;
let embedding = service.embed_one.await?;
assert_eq!;
CachedEmbeddingService
Wraps any EmbeddingService with LRU caching. Identical texts return cached embeddings.
use ;
use Arc;
let inner = new;
let cached = new; // 1000 entry cache
let emb1 = cached.embed_one.await?;
let emb2 = cached.embed_one.await?; // cache hit
SIMD Vector Operations
Dispatch is resolved per platform. x86_64 uses runtime feature detection with automatic scalar fallback. On aarch64 the f32 kernels always use NEON (mandatory on that architecture, no runtime check), while the int8 kernel runtime-detects SDOT. On wasm32 the SIMD choice is fixed at compile time and covers the f32 kernels only (see below).
| Platform | Instructions |
|---|---|
| x86_64 (f32) | AVX-512F > AVX2 + FMA > scalar |
| x86_64 (int8) | AVX-512 VNNI (runtime-detected) > AVX2 > scalar |
| aarch64 (f32) | ARM NEON (mandatory, always on) |
| aarch64 (int8) | NEON SDOT (runtime-detected) > scalar |
| wasm32 | SIMD128 (compile-time, f32 kernels only) > scalar |
| Other | Scalar fallback |
wasm32 (SIMD128)
The SIMD128 route exists for the four f32 kernels: dot_product, cosine_similarity,
squared Euclidean distance, and normalize. The int8 path (dot_product_i8) has no
SIMD128 branch and always dispatches to the scalar kernel on wasm32.
Unlike the x86_64/aarch64 rows above, wasm32 has no runtime CPU-feature detection: a given
.wasm binary either was or wasn't compiled with -C target-feature=+simd128, and that
choice is fixed for the whole artifact. SimdConfig::simd128_enabled() mirrors this
directly (cfg!(target_feature = "simd128")) rather than reading a field, so it is not
something a config value can override -- a force-scalar-style SimdConfig cannot re-route a
simd128-compiled wasm build back to the scalar kernels. To get scalar dispatch on wasm32,
build without the simd128 target feature; there is no runtime override for a build that
has it.
Performance (384-dim vectors)
Measured by crates/embed/benches/simd_bench.rs; run cargo bench -p lattice-embed to
reproduce on your own hardware — these are illustrative, not a portability guarantee.
| Operation | Scalar | SIMD | Speedup |
|---|---|---|---|
| cosine_similarity | ~650ns | ~90ns | 7x |
| dot_product | ~230ns | ~35ns | 6.5x |
| normalize | ~400ns | ~60ns | 6.5x |
| dot_product_i8 | ~300ns | ~25ns | 12x |
Usage
use ;
let a = vec!;
let b = vec!;
let sim = cosine_similarity; // 1.0 (identical direction)
let dot = dot_product; // 1.0
let dist = euclidean_distance; // 0.0
let mut v = vec!;
normalize; // v = [0.6, 0.8], magnitude = 1.0
Int8 Quantization
4x memory reduction with ~99% accuracy:
use QuantizedVector;
let v = vec!;
let q = from_f32;
// Compare quantized vectors directly
let sim = q.cosine_similarity;
Cache
SHA-256-based hashing with LRU eviction. Default capacity: 4000 entries (~6MB for 384-dim vectors).
use ;
let cache = new; // custom capacity; use `with_default_capacity()` for 4000
let key = cache.compute_key;
cache.put;
let stats = cache.stats;
println!;
Feature Flags
| Feature | Default | Description |
|---|---|---|
native |
Yes | Enable local embedding via pure Rust inference |
download |
Yes | First-use model downloads (implies native) |
wasm |
No | wasm-bindgen JS bindings for a browser-loadable .wasm module |
metal-gpu |
No | Enables lattice-inference/metal-gpu |
avx512 |
No | Deprecated no-op — the AVX-512 VNNI int8 kernel is compiled unconditionally on stable x86_64 and is selected at runtime only when AVX-512F/BW/VNNI are all detected; otherwise AVX2 or scalar runs; kept for manifest compatibility |
local |
No | Deprecated no-op — gated a bench module for a service removed long ago; kept for manifest compatibility |
[]
= { = "0.4", = false } # SIMD only
= { = "0.4" } # Full (native + SIMD)
Batch Processing
let texts = vec!;
let embeddings = service.embed.await?;
assert_eq!;
Maximum batch size: 1000 texts (to prevent OOM).
API Reference
EmbeddingService Trait
SIMD Config
use simd_config;
let config = simd_config;
println!;