Configure the Voyage AI provider to customize API endpoints, authentication, request behavior, and model-specific settings.
Provider setup
Create a Voyage AI provider instance with your configuration:
import { createVoyage } from 'voyage-ai-provider';
const voyage = createVoyage({
apiKey: process.env.VOYAGE_API_KEY,
});
Authentication
The provider requires an API key from Voyage AI:
Set your API key as an environment variable (recommended):
export VOYAGE_API_KEY="your-api-key-here"
The provider automatically reads from VOYAGE_API_KEY:
import { createVoyage } from 'voyage-ai-provider';
const voyage = createVoyage();
// API key loaded from VOYAGE_API_KEY environment variable
Pass the API key directly when creating the provider:
import { createVoyage } from 'voyage-ai-provider';
const voyage = createVoyage({
apiKey: 'your-api-key-here',
});
Never hardcode API keys in your source code. Use environment variables or secure configuration management.
Provider settings
Customize the provider with these settings:
baseURL
Override the default API endpoint:
import { createVoyage } from 'voyage-ai-provider';
const voyage = createVoyage({
apiKey: process.env.VOYAGE_API_KEY,
baseURL: 'https://api.voyageai.com/v1',
});
Customize the base URL to:
- Use a proxy server for API calls
- Route requests through a custom gateway
- Test against a staging environment
- Use a different API version
The default is https://api.voyageai.com/v1.
Add custom headers to all API requests:
import { createVoyage } from 'voyage-ai-provider';
const voyage = createVoyage({
apiKey: process.env.VOYAGE_API_KEY,
headers: {
'X-Custom-Header': 'custom-value',
'User-Agent': 'my-app/1.0',
},
});
Custom headers are included in every request to the Voyage AI API.
fetch
Provide a custom fetch implementation:
import { createVoyage } from 'voyage-ai-provider';
const voyage = createVoyage({
apiKey: process.env.VOYAGE_API_KEY,
fetch: async (url, options) => {
console.log('Making request to:', url);
const response = await fetch(url, options);
console.log('Response status:', response.status);
return response;
},
});
Use a custom fetch implementation to:
- Add request/response logging
- Implement retry logic
- Add request timing metrics
- Intercept and modify requests
- Test with mocked responses
- Add circuit breaker patterns
Complete configuration example
Combine all settings for full control:
import { createVoyage } from 'voyage-ai-provider';
const voyage = createVoyage({
apiKey: process.env.VOYAGE_API_KEY,
baseURL: 'https://api.voyageai.com/v1',
headers: {
'X-Application': 'my-app',
'X-Environment': process.env.NODE_ENV || 'development',
},
fetch: async (url, options) => {
const startTime = Date.now();
try {
const response = await fetch(url, options);
const duration = Date.now() - startTime;
console.log(`Request completed in ${duration}ms`);
return response;
} catch (error) {
console.error('Request failed:', error);
throw error;
}
},
});
Model-specific configuration
Each model type accepts specific provider options:
Tab Title
Tab Title
Tab Title
Text embedding options
Configure text embedding behavior:import { createVoyage } from 'voyage-ai-provider';
import { embed } from 'ai';
import type { VoyageEmbeddingOptions } from 'voyage-ai-provider';
const voyage = createVoyage({
apiKey: process.env.VOYAGE_API_KEY,
});
const { embedding } = await embed({
model: voyage.textEmbeddingModel('voyage-code-3'),
value: 'Sample text',
providerOptions: {
voyage: {
inputType: 'query',
outputDimension: 512,
outputDtype: 'float',
truncation: true,
} satisfies VoyageEmbeddingOptions,
},
});
Available options:
inputType: 'query' or 'document' - Optimizes prompt for retrieval
outputDimension: Number - Reduces embedding dimensions (model-specific)
outputDtype: 'float' | 'int8' | 'uint8' | 'binary' | 'ubinary' - Output data type
truncation: Boolean - Automatically truncate long inputs
Multimodal embedding options
Configure multimodal embedding behavior:import { createVoyage } from 'voyage-ai-provider';
import { embed } from 'ai';
import type { MultimodalEmbeddingInput, VoyageMultimodalEmbeddingOptions } from 'voyage-ai-provider';
const voyage = createVoyage({
apiKey: process.env.VOYAGE_API_KEY,
});
const { embedding } = await embed<MultimodalEmbeddingInput>({
model: voyage.multimodalEmbeddingModel('voyage-multimodal-3'),
value: {
text: ['Sample text'],
image: ['https://example.com/image.jpg'],
},
providerOptions: {
voyage: {
inputType: 'document',
outputEncoding: 'base64',
truncation: true,
} satisfies VoyageMultimodalEmbeddingOptions,
},
});
Available options:
inputType: 'query' or 'document' - Optimizes prompt for retrieval
outputEncoding: 'base64' - Encode embeddings as base64
truncation: Boolean - Automatically truncate long inputs
Reranking options
Configure reranking behavior:import { createVoyage } from 'voyage-ai-provider';
import { rerank } from 'ai';
import type { VoyageRerankingOptions } from 'voyage-ai-provider';
const voyage = createVoyage({
apiKey: process.env.VOYAGE_API_KEY,
});
const result = await rerank({
model: voyage.reranking('rerank-2.5'),
query: 'sample query',
documents: ['doc1', 'doc2'],
topN: 5,
providerOptions: {
voyage: {
returnDocuments: true,
truncation: true,
} satisfies VoyageRerankingOptions,
},
});
Available options:
returnDocuments: Boolean - Include document text in response
truncation: Boolean - Automatically truncate long inputs
Default provider instance
Use the pre-configured default instance:
import { voyage } from 'voyage-ai-provider';
import { embed } from 'ai';
// Uses VOYAGE_API_KEY environment variable
const { embedding } = await embed({
model: voyage.textEmbeddingModel('voyage-3-lite'),
value: 'Sample text',
});
The default voyage instance reads configuration from environment variables and uses default settings.
Multiple provider instances
Create separate instances for different configurations:
import { createVoyage } from 'voyage-ai-provider';
// Production instance
const voyageProduction = createVoyage({
apiKey: process.env.VOYAGE_API_KEY_PROD,
headers: {
'X-Environment': 'production',
},
});
// Development instance with logging
const voyageDevelopment = createVoyage({
apiKey: process.env.VOYAGE_API_KEY_DEV,
headers: {
'X-Environment': 'development',
},
fetch: async (url, options) => {
console.log('Dev request:', url);
return fetch(url, options);
},
});
// Use appropriate instance based on environment
const voyage = process.env.NODE_ENV === 'production'
? voyageProduction
: voyageDevelopment;
Environment-based configuration
Manage configuration across environments:
import { createVoyage } from 'voyage-ai-provider';
interface Config {
apiKey: string;
baseURL?: string;
environment: string;
}
const configs: Record<string, Config> = {
development: {
apiKey: process.env.VOYAGE_API_KEY_DEV!,
environment: 'development',
},
staging: {
apiKey: process.env.VOYAGE_API_KEY_STAGING!,
baseURL: 'https://staging-api.voyageai.com/v1',
environment: 'staging',
},
production: {
apiKey: process.env.VOYAGE_API_KEY_PROD!,
environment: 'production',
},
};
const env = process.env.NODE_ENV || 'development';
const config = configs[env];
const voyage = createVoyage({
apiKey: config.apiKey,
baseURL: config.baseURL,
headers: {
'X-Environment': config.environment,
},
});
Request interceptor pattern
Implement request/response interceptors:
import { createVoyage } from 'voyage-ai-provider';
interface RequestMetrics {
url: string;
duration: number;
status: number;
}
const metrics: RequestMetrics[] = [];
const voyage = createVoyage({
apiKey: process.env.VOYAGE_API_KEY,
fetch: async (url, options) => {
// Pre-request hook
const startTime = Date.now();
console.log('Starting request:', url);
try {
// Make request
const response = await fetch(url, options);
// Post-response hook
const duration = Date.now() - startTime;
metrics.push({
url: url.toString(),
duration,
status: response.status,
});
console.log(`Request completed: ${response.status} (${duration}ms)`);
return response;
} catch (error) {
// Error hook
const duration = Date.now() - startTime;
console.error(`Request failed after ${duration}ms:`, error);
throw error;
}
},
});
// Access metrics
setInterval(() => {
const avgDuration = metrics.reduce((sum, m) => sum + m.duration, 0) / metrics.length;
console.log(`Average request duration: ${avgDuration.toFixed(2)}ms`);
}, 60000);
Retry logic
Implement automatic retries for failed requests:
import { createVoyage } from 'voyage-ai-provider';
async function fetchWithRetry(
url: RequestInfo,
options: RequestInit,
maxRetries = 3,
): Promise<Response> {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch(url, options);
// Retry on server errors
if (response.status >= 500 && attempt < maxRetries) {
console.log(`Server error, retrying (${attempt}/${maxRetries})...`);
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
continue;
}
return response;
} catch (error) {
if (attempt === maxRetries) throw error;
console.log(`Network error, retrying (${attempt}/${maxRetries})...`);
await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
}
}
throw new Error('Max retries exceeded');
}
const voyage = createVoyage({
apiKey: process.env.VOYAGE_API_KEY,
fetch: fetchWithRetry,
});
Use exponential backoff when implementing retry logic to avoid overwhelming the API during outages.
Testing configuration
Configure the provider for testing:
import { createVoyage } from 'voyage-ai-provider';
// Mock fetch for testing
const mockFetch = async (url: RequestInfo, options?: RequestInit) => {
return new Response(
JSON.stringify({
data: [{ embedding: new Array(1024).fill(0.1) }],
usage: { total_tokens: 10 },
}),
{
status: 200,
headers: { 'Content-Type': 'application/json' },
},
);
};
const voyageTest = createVoyage({
apiKey: 'test-key',
fetch: mockFetch,
});
Best practices
Use environment variables
Store API keys and configuration in environment variables, never in source code.
Create reusable instances
Create provider instances once and reuse them throughout your application.
Use custom fetch functions to add logging, metrics, and error tracking.
Implement retry logic and proper error handling for production applications.
Use different API keys and configurations for development, staging, and production.
Next steps
Text embeddings
Generate embeddings from text
Multimodal embeddings
Combine text and images
Reranking
Improve search results
API Reference
Explore the complete API