๐Ÿ”Ž Haystack 2.25 is here! SearchableToolset to reduce context usage & Jinja2 templates for Agents

Integration: Voyage AI

Use text embeddings and rerankers from Voyage AI

Authors
Ashwin Mathur

PyPI PyPI - Python Version

Table of Contents

Voyage AI’s embedding and ranking models are state-of-the-art in retrieval accuracy. The integration supports the following models:

  • voyage-4-large, voyage-4, and voyage-4-lite - Latest general-purpose embedding models with shared embedding space and MoE architecture
  • voyage-3.5 and voyage-3.5-lite - General-purpose embedding models with superior performance
  • voyage-code-3 - Optimized for code retrieval
  • voyage-context-3 - Contextualized chunk embedding model that preserves document context for improved retrieval accuracy
  • voyage-multimodal-3.5 - Multimodal model supporting text, images, and video (preview)

For the complete list of available models, see the Embeddings Documentation and Contextualized Chunk Embeddings.

Supported Models

Text Embedding Models

Model Description Dimensions
voyage-4-large The best general-purpose and multilingual retrieval quality 1024 (default), 256, 512, 2048
voyage-4 Optimized for general-purpose and multilingual retrieval quality 1024 (default), 256, 512, 2048
voyage-4-lite Optimized for latency and cost 1024 (default), 256, 512, 2048
voyage-3.5 General-purpose embedding model 1024
voyage-3.5-lite Efficient model with lower latency 1024
voyage-code-3 Optimized for code retrieval 1024

Multimodal Embedding Models

Model Description Dimensions Modalities
voyage-multimodal-3 Multimodal embedding model 1024 Text, Images
voyage-multimodal-3.5 Multimodal embedding model (preview) 256, 512, 1024, 2048 Text, Images, Video

Reranker Models

Model Description
rerank-2 High-accuracy reranker model
rerank-2-lite Efficient reranker with lower latency

Installation

pip install voyage-embedders-haystack

Usage

You can use Voyage models with five components:

Standard Embeddings

To create semantic embeddings for documents, use VoyageDocumentEmbedder in your indexing pipeline. For generating embeddings for queries, use VoyageTextEmbedder. For reranking, use VoyageRanker with Voyage Rerankers.

Contextualized Embeddings

For improved retrieval quality, use VoyageContextualizedDocumentEmbedder with the voyage-context-3 model. This component preserves context between related document chunks by grouping them together during embedding, reducing context loss that occurs when chunks are embedded independently

Important: You must explicitly specify the model parameter when initializing any component. Choose from the available models listed in the Embeddings Documentation. Recommended choices include:

  • voyage-4-large - Best general-purpose and multilingual retrieval quality
  • voyage-4 - Balanced general-purpose and multilingual retrieval quality
  • voyage-4-lite - Optimized for latency and cost
  • voyage-context-3 - Contextualized embeddings for improved retrieval (use with VoyageContextualizedDocumentEmbedder)

You can set the environment variable VOYAGE_API_KEY instead of passing the API key as an argument. To get an API key, please see the Voyage AI website.

Note (v1.7.0+): The model parameter is required and must be explicitly specified. Earlier versions defaulted to voyage-3 for embedders and rerank-2 for the ranker.

Example

Below is the example Semantic Search pipeline that uses the Simple Wikipedia Dataset from HuggingFace. You can find more examples in the examples folder.

Load the dataset:

# Install HuggingFace Datasets using "pip install datasets"
from datasets import load_dataset
from haystack import Pipeline
from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever
from haystack.components.writers import DocumentWriter
from haystack.dataclasses import Document
from haystack.document_stores.in_memory import InMemoryDocumentStore

# Import Voyage Embedders
from haystack_integrations.components.embedders.voyage_embedders import VoyageDocumentEmbedder, VoyageTextEmbedder

# Load first 100 rows of the Simple Wikipedia Dataset from HuggingFace
dataset = load_dataset("pszemraj/simple_wikipedia", split="validation[:100]")

docs = [
    Document(
        content=doc["text"],
        meta={
            "title": doc["title"],
            "url": doc["url"],
        },
    )
    for doc in dataset
]

Index the documents to the InMemoryDocumentStore using the VoyageDocumentEmbedder and DocumentWriter:

doc_store = InMemoryDocumentStore(embedding_similarity_function="cosine")
retriever = InMemoryEmbeddingRetriever(document_store=doc_store)
doc_writer = DocumentWriter(document_store=doc_store)

doc_embedder = VoyageDocumentEmbedder(
    model="voyage-3.5",
    input_type="document",
)
text_embedder = VoyageTextEmbedder(model="voyage-3.5", input_type="query")

# Indexing Pipeline
indexing_pipeline = Pipeline()
indexing_pipeline.add_component(instance=doc_embedder, name="DocEmbedder")
indexing_pipeline.add_component(instance=doc_writer, name="DocWriter")
indexing_pipeline.connect("DocEmbedder", "DocWriter")

indexing_pipeline.run({"DocEmbedder": {"documents": docs}})

print(f"Number of documents in Document Store: {len(doc_store.filter_documents())}")
print(f"First Document: {doc_store.filter_documents()[0]}")
print(f"Embedding of first Document: {doc_store.filter_documents()[0].embedding}")

Query the Semantic Search Pipeline using the InMemoryEmbeddingRetriever and VoyageTextEmbedder:

text_embedder = VoyageTextEmbedder(model="voyage-3.5", input_type="query")

# Query Pipeline
query_pipeline = Pipeline()
query_pipeline.add_component(instance=text_embedder, name="TextEmbedder")
query_pipeline.add_component(instance=retriever, name="Retriever")
query_pipeline.connect("TextEmbedder.embedding", "Retriever.query_embedding")

# Search
results = query_pipeline.run({"TextEmbedder": {"text": "Which year did the Joker movie release?"}})

# Print text from top result
top_result = results["Retriever"]["documents"][0].content
print("The top search result is:")
print(top_result)

Contextualized Embeddings Example

The voyage-context-3 model enables contextualized chunk embeddings, which preserve relationships between document chunks for better retrieval accuracy. Documents with the same source_id are embedded together in context:

from haystack import Document
from haystack_integrations.components.embedders.voyage_embedders import VoyageContextualizedDocumentEmbedder

# Create documents with source_id to group related chunks
docs = [
    # Chunks from the same document (source_id: "doc1")
    Document(
        content="Apple Inc. released their Q1 earnings report.",
        meta={"source_id": "doc1", "title": "Apple News"}
    ),
    Document(
        content="Revenue increased by 12% year over year.",
        meta={"source_id": "doc1", "title": "Apple News"}
    ),
    # Chunks from another document (source_id: "doc2")
    Document(
        content="Tesla announced new vehicle production targets.",
        meta={"source_id": "doc2", "title": "Tesla Update"}
    ),
]

# Use VoyageContextualizedDocumentEmbedder for voyage-context-3
embedder = VoyageContextualizedDocumentEmbedder(
    model="voyage-context-3",
    input_type="document",
)

result = embedder.run(documents=docs)

# Chunks with the same source_id are embedded together, preserving context
# This improves retrieval - e.g., searching "Apple revenue growth" will better match
# the second chunk because it maintains its connection to "Apple Inc."

For more examples, see the contextualized embedder example.

Multimodal Embeddings

Voyage AI’s voyage-multimodal-3.5 model transforms unstructured data from multiple modalities (text, images, video) into a shared vector space. This enables mixed-media document retrieval and cross-modal semantic search.

Features

  • Multiple modalities: Supports text, images, and video in a single input
  • Variable dimensions: Output dimensions of 256, 512, 1024 (default), or 2048
  • Interleaved content: Mix text, images, and video in single inputs
  • No preprocessing required: Process documents with embedded images directly

Limits

  • Images: Max 20MB, 16 million pixels
  • Video: Max 20MB
  • Context: 32,000 tokens
  • Token counting: 560 image pixels = 1 token, 1120 video pixels = 1 token

Basic Multimodal Example

Use the VoyageMultimodalEmbedder component for multimodal embeddings. Each input is a list of content items (text, images, or videos):

from haystack.dataclasses import ByteStream
from haystack_integrations.components.embedders.voyage_embedders import VoyageMultimodalEmbedder

# Text-only embedding
embedder = VoyageMultimodalEmbedder(model="voyage-multimodal-3.5")
result = embedder.run(inputs=[["A sunset over the ocean"]])
print(f"Embedding dimensions: {len(result['embeddings'][0])}")

# Mixed text and image embedding
image_bytes = ByteStream.from_file_path("image.jpg")
result = embedder.run(inputs=[["Product photo for online store", image_bytes]])
print(f"Tokens used: {result['meta']['total_tokens']}")

Multimodal Example with Custom Dimensions

from haystack.dataclasses import ByteStream
from haystack_integrations.components.embedders.voyage_embedders import VoyageMultimodalEmbedder

# Configure output dimensions (256, 512, 1024, or 2048)
embedder = VoyageMultimodalEmbedder(
    model="voyage-multimodal-3.5",
    output_dimension=2048,  # Higher dimensions for better accuracy
    input_type="document",  # Optimize for document retrieval
)

# Embed multiple inputs at once
image1 = ByteStream.from_file_path("doc1.jpg")
image2 = ByteStream.from_file_path("doc2.jpg")

result = embedder.run(inputs=[
    ["Document about machine learning", image1],
    ["Technical diagram", image2],
])

print(f"Number of embeddings: {len(result['embeddings'])}")
print(f"Image pixels processed: {result['meta']['image_pixels']}")

Video Embedding Example

Video inputs require the voyageai.video_utils module:

from voyageai.video_utils import Video
from haystack_integrations.components.embedders.voyage_embedders import VoyageMultimodalEmbedder

embedder = VoyageMultimodalEmbedder(model="voyage-multimodal-3.5")

# Load video using VoyageAI's Video utility
video = Video.from_path("video.mp4", model="voyage-multimodal-3.5")

# Embed video with optional text context
result = embedder.run(inputs=[["Machine learning tutorial", video]])

print(f"Embedding dimensions: {len(result['embeddings'][0])}")
print(f"Video pixels processed: {result['meta']['video_pixels']}")
print(f"Total tokens: {result['meta']['total_tokens']}")

Use Cases

  • Mixed-media document retrieval (PDFs, slides with images)
  • Image-text similarity search
  • Video content retrieval and search
  • Cross-modal semantic search

For more information, see the Multimodal Embeddings Documentation.

License

voyage-embedders-haystack is distributed under the terms of the Apache-2.0 license.