PHP client for the Voyage AI API — text embeddings, multimodal embeddings (text, images, video), and reranking.
PHP client for the Voyage AI API — text embeddings, multimodal embeddings (text, images, video), and reranking.
composer require 0xmrmasry/voyage-ai
Set your API key via environment variable:
VOYAGE_API_KEY=your-api-key
Or pass it directly:
$voyage = \VoyageAI\Voyage::client('your-api-key');
use VoyageAI\Voyage;
use VoyageAI\Enums\{InputType, OutputDtype};
$voyage = Voyage::client(getenv('VOYAGE_API_KEY'));
$response = $voyage->embeddings()->create(
input: ['I like cats', 'I also like dogs'],
model: 'voyage-4-large',
);
foreach ($response->data as $result) {
echo "Index: {$result->index}, Dims: " . count($result->embedding) . "\n";
}
echo "Tokens used: {$response->usage->totalTokens}\n";
$response = $voyage->embeddings()->create(
input: 'Represent this sentence for searching relevant passages',
model: 'voyage-4-large',
options: [
'input_type' => InputType::Query,
'truncation' => true,
'output_dimension' => 256,
'output_dtype' => OutputDtype::Float,
],
);
$response = $voyage->embeddings()->create(
input: 'Test for quantization',
model: 'voyage-4-large',
options: [
'output_dtype' => OutputDtype::Int8,
],
);
// $response->data[0]->embedding is now array of ints (-128..127)
$response = $voyage->reranking()->create(
query: 'talk about rain',
documents: [
'sunny day at the beach',
'rainy day in the city',
'snowy mountain peak',
],
model: 'rerank-2.5',
);
// Results sorted by descending relevance
foreach ($response->data as $result) {
echo "Document {$result->index}: score {$result->relevanceScore}\n";
}
$response = $voyage->reranking()->create(
query: 'best fruit',
documents: ['apple', 'banana', 'car'],
model: 'rerank-2.5-lite',
options: [
'top_k' => 2,
'return_documents' => true,
'truncation' => true,
],
);
foreach ($response->data as $result) {
echo "{$result->document}: {$result->relevanceScore}\n";
}
use VoyageAI\Resources\{MultimodalInput, TextContent, ImageUrlContent, VideoUrlContent};
$response = $voyage->multimodal()->create(
inputs: [
new MultimodalInput([
new TextContent('This is a banana.'),
new ImageUrlContent('https://example.com/banana.jpg'),
]),
],
model: 'voyage-multimodal-3.5',
);
use VoyageAI\Resources\{MultimodalInput, TextContent, ImageUrlContent, VideoUrlContent};
$response = $voyage->multimodal()->create(
inputs: [
new MultimodalInput([
new TextContent('A bunny running in a field.'),
new ImageUrlContent('https://example.com/bunny.jpg'),
new VideoUrlContent('https://example.com/bunny.mp4'),
]),
],
model: 'voyage-multimodal-3.5',
);
use VoyageAI\Resources\{MultimodalInput, TextContent, ImageBase64Content, VideoBase64Content};
$response = $voyage->multimodal()->create(
inputs: [
new MultimodalInput([
new TextContent('A photo of a cat.'),
new ImageBase64Content('data:image/jpeg;base64,/9j/4AAQSkZJRg...'),
new VideoBase64Content('data:video/mp4;base64,AAAAIGZ0eXBpc29t...'),
]),
],
model: 'voyage-multimodal-3.5',
options: [
'input_type' => InputType::Document,
'truncation' => true,
],
);
$voyage = Voyage::client(
apiKey: 'your-key',
baseUrl: 'https://your-proxy.example.com/v1',
);
| Model | Context Length | Embedding Dimension |
|---|---|---|
| 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-3.5 | 32,000 | 1024 (default), 256, 512, 2048 |
| voyage-3.5-lite | 32,000 | 1024 (default), 256, 512, 2048 |
| voyage-3-large | 32,000 | 1024 (default), 256, 512, 2048 |
| voyage-3 | 32,000 | 1024 |
| voyage-3-lite | 32,000 | 512 |
| voyage-code-3.5 | 32,000 | 1024 (default), 256, 512, 2048 |
| voyage-code-3 | 32,000 | 1024 (default), 256, 512, 2048 |
| voyage-finance-2 | 32,000 | 1024 |
| voyage-multilingual-2 | 32,000 | 1024 |
| voyage-law-2 | 16,000 | 1024 |
| voyage-code-2 | 16,000 | 1536 |
| Model | Context Length | Embedding Dimension |
|---|---|---|
| voyage-multimodal-3.5 | 32,000 | 1024 |
| voyage-multimodal-3 | 32,000 | 1024 |
| Model | Query Token Limit | Query + Document Token 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 |
All API errors throw VoyageAI\Exceptions\VoyageException with an $httpStatusCode property:
try {
$response = $voyage->embeddings()->create('Hello', 'invalid-model');
} catch (\VoyageAI\Exceptions\VoyageException $e) {
echo "Error ({$e->httpStatusCode}): {$e->getMessage()}\n";
}
MIT