Voyage AI
Voyage AI provides text, code, and multimodal embedding models. There are two ways to use them with Qdrant:
- Call the Voyage AI API from your application and send the vectors to Qdrant. This is what most of this page covers.
- Run the open-weight
voyage-4-nanomodel on your own hardware.
Models
| Model | Dimensions | Context | Input |
|---|---|---|---|
voyage-4-large | 1024 (default), 2048, 512, 256 | 32,000 tokens | Text |
voyage-4 | 1024 (default), 2048, 512, 256 | 32,000 tokens | Text |
voyage-4-lite | 1024 (default), 2048, 512, 256 | 32,000 tokens | Text |
voyage-code-4 | 1024 (default), 2048, 512, 256 | 32,000 tokens | Text (code) |
voyage-multimodal-3.5 | 1024 (default), 2048, 512, 256 | 32,000 tokens | Text, images, video |
voyage-4-nano (open weights) | 2048 (default), 1024, 512, 256 | 32,000 tokens | Text |
voyage-4-large targets retrieval quality, voyage-4 balances quality and cost, and voyage-4-lite targets latency and cost. The Voyage 4 series models, including voyage-4-nano, share an embedding space, so you can index with one model and query with another. Voyage AI also offers the domain models voyage-finance-2 and voyage-law-2. Earlier general-purpose models, such as voyage-3.5, voyage-3-large, and voyage-large-2, are the previous generation. Use a Voyage 4 series model for new projects.
Voyage AI embeddings are normalized to length 1, so the Cosine, Dot, and Euclidean distance metrics rank results identically. These examples use Cosine.
Setup
Install the Voyage AI SDK and the Qdrant client:
- Python:
pip install voyageai qdrant-client - TypeScript:
npm install voyageai @qdrant/js-client-rest
Create both clients and a collection sized for the model. The Voyage AI client reads your API key from the VOYAGE_API_KEY environment variable. To create a key, see API Key and Installation.
import voyageai
from qdrant_client import QdrantClient, models
vo = voyageai.Client()
client = QdrantClient(url="http://localhost:6333")
client.create_collection(
collection_name="{collection_name}",
vectors_config=models.VectorParams(size=1024, distance=models.Distance.COSINE),
)
import { VoyageAIClient } from "voyageai";
import { QdrantClient } from "@qdrant/js-client-rest";
const voyage = new VoyageAIClient();
const client = new QdrantClient({ url: "http://localhost:6333" });
await client.createCollection("{collection_name}", {
vectors: { size: 1024, distance: "Cosine" },
});
Embed Documents
Set input_type to document for content you store. The vectors come back in input order, and each item of the API response carries the index of its input. These examples use that position as the point ID:
documents = [
"Qdrant is a vector search engine.",
"Voyage AI embedding models turn text into dense vectors.",
]
response = vo.embed(documents, model="voyage-4-large", input_type="document")
client.upsert(
collection_name="{collection_name}",
points=[
models.PointStruct(id=idx, vector=vector, payload={"text": text})
for idx, (vector, text) in enumerate(zip(response.embeddings, documents))
],
)
const documents = [
"Qdrant is a vector search engine.",
"Voyage AI embedding models turn text into dense vectors.",
];
const response = await voyage.embed({
input: documents,
model: "voyage-4-large",
inputType: "document",
});
await client.upsert("{collection_name}", {
points: response.data!.map((item) => ({
id: item.index!,
vector: item.embedding!,
payload: { text: documents[item.index!] },
})),
});
A request accepts up to 1,000 texts. The total token limit per request is 120,000 for voyage-4-large, 320,000 for voyage-4, and 1,000,000 for voyage-4-lite. Split larger datasets into several requests, and see Upload Points for batching on the Qdrant side.
Embed Queries
Set input_type to query for search queries. Voyage AI prepends a retrieval prompt that differs for queries and documents, which tailors each vector for retrieval:
query_vector = vo.embed(
["What is Qdrant?"], model="voyage-4-large", input_type="query"
).embeddings[0]
hits = client.query_points(
collection_name="{collection_name}",
query=query_vector,
limit=3,
).points
const queryResponse = await voyage.embed({
input: ["What is Qdrant?"],
model: "voyage-4-large",
inputType: "query",
});
const queryVector = queryResponse.data?.[0]?.embedding;
if (!queryVector) throw new Error("Voyage AI returned no query embedding");
const { points: hits } = await client.query("{collection_name}", {
query: queryVector,
limit: 3,
});
Reduce Vector Size
The models in the Models table with several dimensions accept an output_dimension parameter (outputDimension in TypeScript). Set the collection’s size to the same value, and pass the same output_dimension when you embed queries:
response = vo.embed(
documents,
model="voyage-4-large",
input_type="document",
output_dimension=512,
)
const reduced = await voyage.embed({
input: documents,
model: "voyage-4-large",
inputType: "document",
outputDimension: 512,
});
To keep the full vectors but store them in less memory, use Quantization.
Embed Images
voyage-multimodal-3.5 embeds text, images, and video in one embedding space, so a text query can find an image. It’s not part of the Voyage 4 series, so store its vectors in a separate collection. In Python, each input is a list that can mix strings and Pillow images:
from PIL import Image
client.create_collection(
collection_name="{image_collection_name}",
vectors_config=models.VectorParams(size=1024, distance=models.Distance.COSINE),
)
image_inputs = [[Image.open("diagram.png")]]
image_response = vo.multimodal_embed(
image_inputs,
model="voyage-multimodal-3.5",
input_type="document",
)
client.upsert(
collection_name="{image_collection_name}",
points=[models.PointStruct(id=0, vector=image_response.embeddings[0], payload={"image": "diagram.png"})],
)
query_inputs = [["How is Qdrant deployed?"]]
query_vector = vo.multimodal_embed(
query_inputs, model="voyage-multimodal-3.5", input_type="query"
).embeddings[0]
hits = client.query_points(
collection_name="{image_collection_name}",
query=query_vector,
limit=3,
).points
import { readFile } from "node:fs/promises";
await client.createCollection("{image_collection_name}", {
vectors: { size: 1024, distance: "Cosine" },
});
const imageBase64 = "data:image/png;base64," + (await readFile("diagram.png")).toString("base64");
const imageResponse = await voyage.multimodalEmbed({
inputs: [{ content: [{ type: "image_base64", imageBase64 }] }],
model: "voyage-multimodal-3.5",
inputType: "document",
});
await client.upsert("{image_collection_name}", {
points: [{ id: 0, vector: imageResponse.data![0].embedding!, payload: { image: "diagram.png" } }],
});
const imageQuery = await voyage.multimodalEmbed({
inputs: [{ content: [{ type: "text", text: "How is Qdrant deployed?" }] }],
model: "voyage-multimodal-3.5",
inputType: "query",
});
const imageQueryVector = imageQuery.data?.[0]?.embedding;
if (!imageQueryVector) throw new Error("Voyage AI returned no query embedding");
const { points: imageHits } = await client.query("{image_collection_name}", {
query: imageQueryVector,
limit: 3,
});
A request accepts up to 1,000 inputs and 320,000 tokens in total. Each image can be up to 16 million pixels and 20 MB. For video input, see Multimodal Embeddings.
Run voyage-4-nano Locally
voyage-4-nano is an open-weight model on Hugging Face, released under the Apache 2.0 license, with about 340 million parameters. The Python SDK runs it locally through sentence-transformers, without an API key. It requires Python 3.10 or later:
pip install "voyageai[local]"
Pass voyage-4-nano as the model, with the same calls as the API models. Because it shares the Voyage 4 embedding space, this example embeds a query locally and searches the documents indexed with voyage-4-large in Embed Documents. Set output_dimension to match the collection’s vector size:
query_vector = vo.embed(
["What is Qdrant?"],
model="voyage-4-nano",
input_type="query",
output_dimension=1024,
).embeddings[0]
hits = client.query_points(
collection_name="{collection_name}",
query=query_vector,
limit=3,
).points
To run without the API entirely, embed the documents with voyage-4-nano too.
Store and Search the Vectors
Next Steps
- Read the Voyage AI embeddings documentation for model details.
- Filter search results by payload fields.
- Combine Voyage AI vectors with sparse vectors for hybrid search.
- Reduce memory use with quantization.