Skip to content

Embedding Providers

Configure an embedding provider in lucerna.config.ts to enable semantic (vector) search. Without one, only lexical (BM25) search is available.

Each example below shows the lucerna.config.ts snippet for that provider. Pass credentials via process.env to keep them out of source control.


Best-in-class for code retrieval. voyage-code-3 is the recommended model for code search.

lucerna.config.ts
import { defineConfig } from "@upstart.gg/lucerna";
export default defineConfig({
embedding: { provider: "voyage", model: "voyage-code-3", apiKey: process.env.VOYAGE_API_KEY! },
});

All Voyage models are Matryoshka-trained. Lucerna defaults to a reduced dimensionality (see “Default dim” below) for a ~50% smaller index with negligible quality loss; pass dimensions to override.

ModelNative dimDefault dimPrice per 1M tokensNotes
voyage-41024512Latest generation
voyage-4-lite512512Faster, lower cost
voyage-code-31024512$0.18Code-optimized, 32K ctx — top pick
voyage-3-large20481024Highest quality general-purpose
voyage-3.51024512Improved general quality
voyage-3.5-lite1024512Faster, lower cost
voyage-31024512$0.06General text
voyage-3-lite512512$0.02Faster, lower cost

Lucerna uses asymmetric retrieval automatically: indexed chunks use input_type: "document" and queries use input_type: "query", matching Voyage’s recommendation for best retrieval quality.


lucerna.config.ts
import { defineConfig } from "@upstart.gg/lucerna";
export default defineConfig({
embedding: { provider: "openai", model: "text-embedding-3-small", apiKey: process.env.OPENAI_API_KEY! },
});

OpenAI’s text-embedding-3 models are Matryoshka-trained. Lucerna passes a reduced dimensions to the API by default (512 for small, 768 for large) — at these sizes the MTEB numbers still beat text-embedding-ada-002 at its full 1536, per OpenAI’s own benchmarks. Override via the dimensions option:

embedding: { provider: "openai", model: "text-embedding-3-large", apiKey: process.env.OPENAI_API_KEY!, dimensions: 3072 },
ModelNative dimDefault dimPrice per 1M tokensNotes
text-embedding-3-small1536512$0.02Good quality/cost balance
text-embedding-3-large3072768$0.13Higher quality
text-embedding-ada-00215361536$0.10Legacy, not Matryoshka

lucerna.config.ts
import { defineConfig } from "@upstart.gg/lucerna";
export default defineConfig({
embedding: { provider: "cohere", model: "embed-english-v3.0", apiKey: process.env.COHERE_API_KEY! },
});
ModelDimensionsPrice per 1M tokensNotes
embed-english-v3.01024$0.10English only
embed-multilingual-v3.01024$0.10Multilingual codebases

First 10M tokens free per API key.

lucerna.config.ts
import { defineConfig } from "@upstart.gg/lucerna";
export default defineConfig({
embedding: { provider: "jina", model: "jina-embeddings-v3", apiKey: process.env.JINA_API_KEY! },
});

jina-embeddings-v3 is Matryoshka-trained and supports truncation down to 32 dimensions with minimal quality loss (~92% retention at 64 per Jina’s benchmarks). Lucerna defaults to 512 for a ~50% smaller index at near-full quality — override via dimensions. Asymmetric retrieval is used automatically: task: "retrieval.passage" for indexed chunks and task: "retrieval.query" for queries.

ModelNative dimDefault dimPrice per 1M tokensNotes
jina-embeddings-v31024512~$0.028K ctx, Matryoshka, good for long code chunks
jina-embeddings-v2-base-code768768Code-specific, no Matryoshka
jina-embeddings-v2-base-en768768English only, no Matryoshka

lucerna.config.ts
import { defineConfig } from "@upstart.gg/lucerna";
export default defineConfig({
embedding: { provider: "mistral", model: "codestral-embed", apiKey: process.env.MISTRAL_API_KEY! },
});

Both Mistral embedding models are Matryoshka-trained. Lucerna defaults to 512 for a ~50% smaller index at negligible quality loss — override via dimensions if you need more.

ModelNative dimDefault dimPrice per 1M tokensNotes
codestral-embed1024512$0.15Code-specific — recommended
mistral-embed1024512$0.10Mixed text + code

lucerna.config.ts
import { defineConfig } from "@upstart.gg/lucerna";
export default defineConfig({
embedding: {
provider: "gemini",
model: "gemini-embedding-2-preview",
apiKey: process.env.GOOGLE_API_KEY!,
// dimensions defaults to 256 for gemini-* models; override with e.g. `dimensions: 3072` for full native dim
},
});
ModelNative dimDefault dimPrice per 1M tokensNotes
gemini-embedding-2-preview3072 (truncatable 128–3072)2568K ctx, multi-modal, latest
gemini-embedding-0013072 (truncatable 128–3072)256$0.15 (batch $0.075)2K ctx, text only
text-embedding-004768768$0.15Legacy, 2K ctx

Lucerna uses asymmetric code retrieval automatically: indexed chunks are embedded with RETRIEVAL_DOCUMENT and queries with CODE_RETRIEVAL_QUERY. For gemini-embedding-2-preview — which does not accept task_type — the equivalent prompt prefix is applied automatically, so no configuration is needed.

Both gemini-embedding-* models support Matryoshka truncation via dimensions (128–3072), and Lucerna defaults to 256 to keep the index ~12× smaller and faster to search with minimal quality loss. When dimensions is below the native 3072, Lucerna L2-normalizes each returned vector as required by the API.


Requires a GCP project. Authentication uses Application Default Credentials (ADC) — tokens are refreshed automatically with no expiry concerns. location defaults to us-central1.

Local development — run once, then Lucerna handles token refresh automatically:

Terminal window
gcloud auth application-default login

CI/CD — set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of a service account JSON key file. Lucerna picks it up automatically via ADC, or you can pass it explicitly with keyFile.

lucerna.config.ts
import { defineConfig } from "@upstart.gg/lucerna";
export default defineConfig({
embedding: {
provider: "vertex",
model: "text-embedding-005",
project: process.env.GOOGLE_CLOUD_PROJECT!,
location: "us-central1", // optional
// keyFile: process.env.GOOGLE_APPLICATION_CREDENTIALS, // explicit service account key (optional)
},
});
ModelNative dimDefault dimPrice per 1M tokensNotes
gemini-embedding-0013072 (truncatable 128–3072)256Highest quality, 1 input per request
text-embedding-005768768$0.10Latest text model, up to 250 inputs per request
text-embedding-004768768$0.10Previous generation
text-multilingual-embedding-002768768$0.10Multilingual

Lucerna uses asymmetric code retrieval automatically: indexed chunks are embedded with RETRIEVAL_DOCUMENT and queries with CODE_RETRIEVAL_QUERY, so no configuration is needed. When dimensions is set below the model’s native dim, Lucerna L2-normalizes returned vectors as required by the API.

Note: gemini-embedding-001 on Vertex accepts only one text per request (the API does not batch), so indexing is slower than text-embedding-005. gemini-embedding-2-preview is not available on Vertex — use the Gemini provider for it.


Free tier: 10K neurons/day (~9M tokens/day for bge-m3).

lucerna.config.ts
import { defineConfig } from "@upstart.gg/lucerna";
export default defineConfig({
embedding: {
provider: "cloudflare",
accountId: process.env.CLOUDFLARE_ACCOUNT_ID!,
apiKey: process.env.CLOUDFLARE_API_TOKEN!,
model: "@cf/baai/bge-m3", // optional, this is the default
},
});
ModelPrice per 1M tokensNotes
@cf/baai/bge-m3~$0.012 (free tier applies)Multilingual, good baseline

No API key required. Requires a running Ollama server. host defaults to http://localhost:11434.

lucerna.config.ts
import { defineConfig } from "@upstart.gg/lucerna";
export default defineConfig({
embedding: { provider: "ollama", model: "nomic-embed-text" },
// embedding: { provider: "ollama", model: "nomic-embed-text", host: "http://my-server:11434" },
});
ModelDimensionsPriceNotes
nomic-embed-text768FreePopular, fast
mxbai-embed-large1024FreeHigher quality, GPU recommended

For custom models not in the table, add a dimensions field:

embedding: { provider: "ollama", model: "my-custom-model", dimensions: 768 },

No API key required. Requires LM Studio running with the local server enabled (Settings → Local Server → Start Server). baseUrl defaults to http://localhost:1234.

lucerna.config.ts
import { defineConfig } from "@upstart.gg/lucerna";
export default defineConfig({
embedding: { provider: "lmstudio", model: "nomic-embed-text" },
// embedding: { provider: "lmstudio", model: "nomic-embed-text", baseUrl: "http://my-server:1234" },
});
ModelDimensionsPriceNotes
nomic-embed-text768FreePopular, fast
mxbai-embed-large1024FreeHigher quality, GPU recommended
bge-m31024FreeMultilingual