Voyage AI Provider for Vercel AI SDK
Introduction
The voyage-ai-provider is a community provider for the AI SDK that brings Voyage AI's full model suite into your TypeScript projects — text embeddings, multimodal (text + image) embeddings, and reranking — all through the standard AI SDK interface.
What Can You Build With It?
- Semantic search & RAG — high-quality text embeddings for retrieval-augmented generation pipelines
- Multimodal search — embed text and images together for cross-modal retrieval
- Re-ranking — re-score candidate documents against a query to improve search precision
- Recommendation systems — cluster and compare content using embedding similarity
Why Voyage AI?
Voyage AI offers specialized models for code, finance, law, and multilingual content — domains where general-purpose embedding models often underperform. The voyage-4 family supports up to 32,000-token context windows and configurable output dimensions (256 / 512 / 1024 / 2048).
Installation
npm install voyage-ai-provider # or yarn add voyage-ai-provider # or pnpm add voyage-ai-provider # or bun add voyage-ai-provider
Configuration
Sign up at Voyage AI to get an API key, then add it to your .env file:
VOYAGE_API_KEY=your-api-key
Usage
Text Embeddings
Use embeddingModel() to create a text embedding model:
import { voyage } from 'voyage-ai-provider' import { embedMany } from 'ai' const model = voyage.embeddingModel('voyage-4-lite') export const generateEmbeddings = async ( value: string, ): Promise<Array<{ embedding: number[]; content: string }>> => { const chunks = value.split('\n') const { embeddings } = await embedMany({ model, values: chunks, }) return embeddings.map((e, i) => ({ content: chunks[i], embedding: e })) }
Custom Provider Instance
import { createVoyage } from 'voyage-ai-provider' const voyage = createVoyage({ apiKey: process.env.VOYAGE_API_KEY, baseURL: 'https://api.voyageai.com/v1', // optional — useful for proxies })
Embedding Settings
import { voyage } from 'voyage-ai-provider' const model = voyage.embeddingModel('voyage-4', { inputType: 'document', // 'query' | 'document' outputDimension: 512, // 256 | 512 | 1024 (default) | 2048 outputDtype: 'float', // 'float' | 'int8' | 'uint8' | 'binary' | 'ubinary' truncation: true, })
Multimodal & Image Embeddings
Both multimodalEmbeddingModel() and imageEmbeddingModel() use the same Voyage multimodal endpoint. Pass text in values and images (or extra text parts) via providerOptions.voyage.content, aligned by index:
import { voyage, type VoyageMultimodalEmbeddingOptions } from 'voyage-ai-provider' import { embedMany } from 'ai' const model = voyage.multimodalEmbeddingModel('voyage-multimodal-3.5') // values[i] = text; content[i] = image parts for that embedding // Use '' for image-only inputs, null in content for text-only inputs const { embeddings } = await embedMany({ model, values: ['A ripe banana', ''], providerOptions: { voyage: { content: [ [{ type: 'image_url', image_url: 'https://example.com/banana.jpg' }], [{ type: 'image_base64', image_base64: 'data:image/jpeg;base64,/9j...' }], ], } satisfies VoyageMultimodalEmbeddingOptions, }, })
Each content part is one of:
{ type: 'image_url', image_url: string }— publicly accessible image URL{ type: 'image_base64', image_base64: string }—data:<mediatype>;base64,<data>(png, jpeg, webp, gif){ type: 'text', text: string }— extra inline text merged with the value
Reranking
Re-rank a list of candidate documents against a query:
import { voyage, type VoyageRerankingOptions } from 'voyage-ai-provider' import { rerank } from 'ai' const model = voyage.rerankingModel('rerank-2.5') const result = await rerank({ model, query: 'best practices for vector search', documents: [ 'Approximate nearest neighbour algorithms speed up vector search.', 'Rain is expected tomorrow in San Francisco.', 'HNSW graphs are commonly used in production vector databases.', ], topN: 2, providerOptions: { voyage: { returnDocuments: true, truncation: true, } satisfies VoyageRerankingOptions, }, })
Type System
All types are named exports — import only what you need:
import type { VoyageProvider, VoyageProviderSettings, VoyageEmbeddingOptions, VoyageMultimodalEmbeddingOptions, VoyageMultimodalContentPart, VoyageRerankingOptions, } from 'voyage-ai-provider'
VoyageProviderSettings
Passed to createVoyage() to configure the provider instance:
type VoyageProviderSettings = { apiKey?: string // defaults to VOYAGE_API_KEY env var baseURL?: string // defaults to https://api.voyageai.com/v1 headers?: Record<string, string> // extra headers on every request fetch?: FetchFunction // custom fetch — useful for testing or middleware }
VoyageProvider
The interface returned by createVoyage(). All methods are available on the default voyage export too:
type VoyageProvider = { embeddingModel(modelId: VoyageEmbeddingModelId): EmbeddingModelV3 multimodalEmbeddingModel(modelId: VoyageMultimodalEmbeddingModelId): EmbeddingModelV3 imageEmbeddingModel(modelId: VoyageMultimodalEmbeddingModelId): EmbeddingModelV3 // alias rerankingModel(modelId: VoyageRerankingModelId): RerankingModelV3 reranking(modelId: VoyageRerankingModelId): RerankingModelV3 // alias }
VoyageEmbeddingOptions
Options for text embedding models, passed as the second argument to embeddingModel():
type VoyageEmbeddingOptions = { inputType?: 'query' | 'document' outputDimension?: number // 256 | 512 | 1024 | 2048 outputDtype?: 'float' | 'int8' | 'uint8' | 'binary' | 'ubinary' truncation?: boolean }
VoyageMultimodalContentPart
A single part inside providerOptions.voyage.content[]. Three variants:
type VoyageMultimodalContentPart = | { type: 'text'; text: string } | { type: 'image_url'; image_url: string } | { type: 'image_base64'; image_base64: string } // data:<mediatype>;base64,<data>
VoyageMultimodalEmbeddingOptions
Passed via providerOptions.voyage when calling embedMany() with a multimodal model:
type VoyageMultimodalEmbeddingOptions = { inputType?: 'query' | 'document' outputEncoding?: 'base64' truncation?: boolean // array aligned to values[]: null = text-only, [] = image parts for that entry content?: (VoyageMultimodalContentPart[] | null)[] }
Usage with full type safety:
import { voyage, type VoyageMultimodalEmbeddingOptions } from 'voyage-ai-provider' import { embed } from 'ai' const { embedding } = await embed({ model: voyage.multimodalEmbeddingModel('voyage-multimodal-3.5'), value: 'A dog catching a frisbee', providerOptions: { voyage: { inputType: 'query', content: [ [{ type: 'image_url', image_url: 'https://example.com/dog.jpg' }], ], } satisfies VoyageMultimodalEmbeddingOptions, }, })
VoyageRerankingOptions
Passed via providerOptions.voyage when calling rerank():
type VoyageRerankingOptions = { returnDocuments?: boolean // include original document text in results (default: false) truncation?: boolean // truncate inputs exceeding context limit (default: true) }
Models Reference
Text Embedding Models
| Model | Context (tokens) | Dimensions |
|---|---|---|
| voyage-4-large | 32,000 | 1024 (default), 256, 512, 2048 |
| voyage-4 | 32,000 | 1024 (default), 256, 512, 2048 |
| voyage-4-lite | 32,000 | 1024 (default), 256, 512, 2048 |
| voyage-code-3 | 32,000 | 1024 (default), 256, 512, 2048 |
| voyage-finance-2 | 32,000 | 1024 |
| voyage-law-2 | 16,000 | 1024 |
| voyage-code-2 | 16,000 | 1536 |
| voyage-3-large | 32,000 | 1024 (default), 256, 512, 2048 |
| voyage-3.5 | 32,000 | 1024 (default), 256, 512, 2048 |
| voyage-3.5-lite | 32,000 | 1024 (default), 256, 512, 2048 |
| voyage-3 | 32,000 | 1024 |
| voyage-3-lite | 32,000 | 512 |
| voyage-multilingual-2 | 32,000 | 1024 |
Multimodal Embedding Models
| Model | Context (tokens) | Dimensions |
|---|---|---|
| voyage-multimodal-3.5 | 32,000 | 1024 (default), 256, 512, 2048 |
| voyage-multimodal-3 | 32,000 | 1024 |
Reranking Models
| Model | Query Token Limit | Query + Doc Limit |
|---|---|---|
| rerank-2.5 | 8,000 | 32,000 |
| rerank-2.5-lite | 8,000 | 32,000 |
| rerank-2 | 4,000 | 16,000 |
| rerank-2-lite | 2,000 | 8,000 |
| rerank-1 | 2,000 | 8,000 |
| rerank-lite-1 | 1,000 | 4,000 |