Cersei

Embeddings Overview

Provider-agnostic text embeddings with a pluggable vector index, packaged as the cersei-embeddings crate.

cersei-embeddings

cersei-embeddings is a standalone crate that pairs a pluggable EmbeddingProvider trait with a usearch-backed HNSW vector index. It is the foundation that powers CodeSearch's hybrid BM25 + vector mode in Abstract, and it is published as a self-contained SDK so you can build your own RAG agents, semantic-search layers, or clustering tools without pulling in the rest of cersei-tools.

The crate is a leaf dependency — it has no dependency on cersei-types, cersei-provider, or any other Cersei crate. Use it with or without the rest of the SDK.

When to reach for it

  • Semantic search over a corpus of documents, code, or notes.
  • RAG pipelines that need to ground an LLM response in the most relevant snippets.
  • Deduplication / clustering by nearest-neighbor distance.
  • Custom reranking layered on top of BM25, keyword search, or any baseline retriever.

If you just want BM25-only code search inside an agent, you don't need this crate — use CodeSearchTool::new() from cersei-tools. Reach for cersei-embeddings the moment you want query-intent understanding or cross-file semantic similarity.

What ships in the box

PieceRole
EmbeddingProviderTrait every backend implements (embed, embed_batch, dimensions).
GeminiEmbeddingsGoogle text-embedding-004 (768-d) with 100-per-batch chunking.
OpenAiEmbeddingsOpenAI text-embedding-3-small (1536-d), base URL overridable for Azure / Ollama.
VectorIndexusearch HNSW wrapper — new, reserve, add, search, len.
EmbeddingStore<P>Provider + index bundled together for the common case.
auto_from_modelFactory that picks the right provider from an LLM model string.
MetricCosine / L2 / InnerProduct.
SearchHit{ key, distance, similarity }.

Add it to your project

[dependencies]
cersei-embeddings = "0.1.6-patch.2"

5-line quick start

use cersei_embeddings::{OpenAiEmbeddings, EmbeddingStore, Metric};

let provider = OpenAiEmbeddings::from_env()?;
let store = EmbeddingStore::new(provider, Metric::Cosine)?;

store.add_batch(&[
    (1, "Rust is a systems programming language".into()),
    (2, "Pasta is best served al dente".into()),
]).await?;

let hits = store.search("compiled languages", 2).await?;
assert_eq!(hits[0].key, 1);
use cersei_embeddings::{GeminiEmbeddings, EmbeddingStore, Metric};

let provider = GeminiEmbeddings::from_env()?;
let store = EmbeddingStore::new(provider, Metric::Cosine)?;

store.add_batch(&[
    (1, "Rust is a systems programming language".into()),
    (2, "Pasta is best served al dente".into()),
]).await?;

let hits = store.search("compiled languages", 2).await?;
use cersei_embeddings::{auto_from_model, EmbeddingStore, Metric};

// Pick the provider based on an LLM model string.
let provider = auto_from_model("openai/gpt-4o")?;
// Works with Box<dyn EmbeddingProvider> too:
let dim = provider.dimensions();
println!("{} ({}-d)", provider.name(), dim);

How Abstract uses it

CodeSearchTool in cersei-tools depends on cersei-embeddings. When the --embedding-api flag is on, Abstract calls auto_from_model(resolved_model) and hands the resulting provider to CodeSearchTool::with_embeddings(Arc<dyn EmbeddingProvider>). The tool keeps BM25 in charge for exact-term recall and blends in the vector results at 40% weight for semantic recall.

Keep reading

  • API Reference — every public type and method.
  • Cookbook — RAG agent, custom provider, semantic markdown search.

On this page