Concepts
Embeddings
Why Voyage voyage-code-3, how dimensions are pinned, and what the bench data looks like.
Prometheus uses a single embedding model per workspace, pinned by
dimension. Today that model is Voyage AI voyage-code-3 at
1024 dimensions.
Why Voyage voyage-code-3
The Phase 2.5 bench shootout (see
docs/benchmarks/2026-05-21-phase-2.5-baseline.md in the repo)
compared four production-grade options against a curated TypeScript
and Python retrieval set:
| Model | Dim | Recall@10 | Notes |
|---|---|---|---|
Voyage voyage-code-3 | 1024 | 0.91 | Best recall, fast, code-tuned. |
Voyage voyage-3-large | 1024 | 0.88 | General-purpose; good fallback. |
OpenAI text-embedding-3-large | 3072 | 0.87 | Higher dim, marginal gain, US-only. |
OpenAI text-embedding-3-small | 1536 | 0.79 | Cheap baseline. |
Voyage's code-tuned model beat the OpenAI options on the metric that matters for an agent's downstream answer quality (Recall@10), at roughly a third of the OpenAI 3-large token cost.
Dimension pinning
The Supabase embeddings.vector column is declared vector(1024)
with an HNSW index over vector_cosine_ops. The indexer worker
asserts at boot that the configured embedder produces 1024-dim vectors
and refuses to start otherwise. That guard exists so a config typo
cannot silently corrupt the index with mismatched dimensions.
If you need to switch dimensions later, that's a Phase 2.7-style migration: new column, parallel re-embed, atomic index swap, drop the old column. The worker carries the plumbing for it but we have not needed it since the migration to 1024.
Provider pluggability
The Embedder interface is provider-agnostic. Voyage is the default;
OpenAI 3-large is the implemented fallback. Adding a new provider is
<100 lines — implement
Embedder.embedBatch(texts: string[]): Promise<number[][]> and
register it in discoverProviders().
Region implications
Voyage runs in us. That makes the embedding call the single
non-EU hop in an otherwise EU-resident pipeline. The
Region mode doc covers how to opt out
of it.