Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Vectoria
Embedded hybrid search engine for ecommerce. Single binary, no external services required.
Vectoria combines BM25 full-text search with vector similarity and behavioral signals (clicks, purchases, views). Its main advantage over BM25-only search (SQLite FTS5, Meilisearch basic tier) is zero-result elimination: semantic mode returns results for long-tail queries that share no keywords with any product. Hybrid mode keeps BM25 precision while removing zero results entirely.
The embedding model runs locally via ONNX; no external API calls required unless you configure an OpenAI-compatible provider.
Designed for catalogs up to ~500K products on a single node.
Requirements
- Rust 1.80+ (for building from source)
- ~40 MB disk space for the default embedding model (downloaded on first run)
Getting started
Start the server:
On first run, it downloads the multilingual-e5-small embedding model (~40 MB) and prints an API key:
INFO vectoria v0.1.2
INFO api_key: a1b2c3d4e5f6...
INFO listening on http://0.0.0.0:7700
Index a product:
Search:
Configuration
Place a vectoria.toml in the working directory. All fields are optional.
[]
= "0.0.0.0"
= 7700
= "your-key" # auto-generated if absent
[]
= "./vectoria.db" # path for persistent index files
[]
= "local" # "local" | "openai-compatible"
= "multilingual-e5-small"
[]
= "edgestore-hnsw" # see below
[]
= 0.6
= 0.2
= 0.1
= 0.1
vector_backend options:
edgestore-hnsw— persistent HNSW index (activated afterPOST /admin/reindex), recommended for productionsqlite— SQLite metadata + EdgeStore flat vector indexmemory— everything in-memory, lost on restart (development only)
Environment variable overrides (take precedence over vectoria.toml):
VECTORIA_HOST
VECTORIA_PORT
VECTORIA_API_KEY
VECTORIA_STORAGE_PATH
VECTORIA_EMBEDDING_PROVIDER
VECTORIA_EMBEDDING_BASE_URL
VECTORIA_EMBEDDING_MODEL
VECTORIA_CONFIG # path to config file, default: vectoria.toml
VECTORIA_SKIP_CONSENT=1 # skip model download prompt
VECTORIA_ENABLE_RERANKER=1 # enable cross-encoder reranking (slower, higher quality)
CLI
The vectoria CLI handles bulk operations against a running server.
# Bulk import from NDJSON, CSV, or Parquet
# Re-embed all products after a model change
# Benchmark search quality (Recall@K, NDCG@K, MRR) across all modes
Embedded usage (Rust)
Add vectoria-core to your Cargo.toml:
= "0.1.2"
Async (with Tokio):
use ;
let engine = new
.query_cache
.build
.await?;
engine.index.await?;
let results = engine.search.await?;
Sync (no Tokio required in caller):
use ;
let engine = new?;
let results = engine.search?;
SearchEngineBuilder accepts optional overrides for storage backend, vector index, embedding provider, ranking weights, query cache TTL/size, and cross-encoder reranking. All default to in-memory storage and the local multilingual-e5-small ONNX model.
Preloading an existing database — pass a persistent backend pointing to an existing file, then call reindex_all() to rebuild the BM25 index and spell corrector from stored products:
use ;
use ;
let engine = new
.storage
.build
.await?;
engine.reindex_all.await?; // rebuild BM25 + spell corrector
Bulk indexing — call engine.index() in a loop. If products already have vectors, set product.vector to skip the embedding step. Call reindex_all() once after bulk loading to flush the HNSW graph.
Publish target: make publish (requires cargo login or CARGO_REGISTRY_TOKEN). See crates.io/crates/vectoria-core.
Demo webstore
The fastest way to try Vectoria with real data is the Make-based demo. It uses the Amazon ESCI product catalog — a separate license agreement is required: https://github.com/amazon-science/esci-data
To benchmark after importing:
Run make help for all targets and overridable variables. See
docs/quickstart.md for a full walkthrough.
Benchmark
Amazon ESCI dataset, 5000 US products, multilingual-e5-small embedding. Results by label hardness:
| Label set | Queries | BM25 MRR | Hybrid MRR | Semantic MRR | Coverage (all modes) |
|---|---|---|---|---|---|
| E (exact) | 107 | 0.5842 | 0.5882 | 0.4922 | 100% |
| E+S | 117 | 0.6595 | 0.6576 | 0.5690 | 100% |
| E+S+C | 119 | 0.6835 | 0.6803 | 0.5797 | 100% |
ESCI label meanings: E = exact product name match (BM25-optimal), S = substitute/concept (keyword overlap low), C = complement (e.g. query "camera" → relevant product "camera bag").
Key takeaways:
- 100% coverage across all modes and label sets — zero-result queries handled by spell-correction fallback (compound split + typo correction applied only when BM25 returns no results)
- Hybrid ≈ BM25 on exact queries, with coverage maintained by semantic fallback
- Semantic covers zero-keyword queries that BM25 would miss entirely (S and C labels)
- Semantic p50 latency: 2ms (cached embeddings); BM25/hybrid: sub-ms to ~3ms
Reproduce with custom label sets:
# Or choose label set:
Next benchmark target: WANDS (Wayfair) — 42K furniture/home goods products, complex descriptive concept queries ("mid century modern floor lamp"). Expected to show larger hybrid advantage since Wayfair queries are more concept-driven than ESCI exact matches.
API reference
See docs/api.md.
Docker
Quickest start — Docker Compose (builds image, mounts volumes, sets API key):
VECTORIA_API_KEY=my-secret-key
Or build and run manually:
# Full image — ONNX model downloaded on first start (~400 MB image, ~40 MB model cache)
# Slim image — requires OpenAI-compatible embedding provider (~50 MB)
Both images include the vectoria CLI. Run it against the container:
Volumes:
/data— persistent index and SQLite storage/root/.cache/fastembed— ONNX model cache (full image only; mount to avoid re-downloading)
Building from source