Using Annoy Vector Store in LangChain

Posted: Feb 11, 2025.

The Annoy (Approximate Nearest Neighbors Oh Yeah) vector store is a powerful tool for performing efficient similarity search on document embeddings. In this guide, we'll explore how to use the Annoy vector store in LangChain for various document search use cases.

What is Annoy?

Annoy is a C++ library with Python bindings created by Spotify that implements approximate nearest neighbor search. It's particularly useful when you need to find similar documents in a large collection by comparing their vector embeddings. Some key characteristics of Annoy include:

  • Read-only after building the index (cannot add new documents incrementally)
  • Memory-mapped file format that allows sharing index across processes
  • Fast search performance with approximate nearest neighbors
  • Support for different distance metrics like angular (cosine) and euclidean

Reference

Here are the main methods available in the Annoy vector store:

MethodDescription
from_texts()Create vector store from a list of texts
from_documents()Create vector store from a list of Document objects
from_embeddings()Create vector store from pre-computed embeddings
similarity_search()Find similar documents using text query
similarity_search_by_vector()Find similar documents using embedding vector
similarity_search_with_score()Get similar documents with similarity scores
save_local()Save the index and documents to disk
load_local()Load a previously saved index and documents

How to Use Annoy

Let's explore different ways to use the Annoy vector store:

Creating a Vector Store

You can create an Annoy vector store in several ways:

from langchain_community.vectorstores import Annoy
from langchain_huggingface import HuggingFaceEmbeddings

# Initialize embeddings
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2")

# From texts
texts = ["pizza is great", "I love salad", "my car", "a dog"]
vector_store = Annoy.from_texts(texts, embeddings)

# From documents
from langchain_core.documents import Document
docs = [Document(page_content=text) for text in texts]
vector_store = Annoy.from_documents(docs, embeddings)

# From pre-computed embeddings
text_embeddings = embeddings.embed_documents(texts)
data = list(zip(texts, text_embeddings))
vector_store = Annoy.from_embeddings(data, embeddings)

You can search for similar documents in different ways:

# Basic similarity search
results = vector_store.similarity_search("food", k=3)

# Search with scores
results = vector_store.similarity_search_with_score("food", k=3)

# Search using embedding vector
query_embedding = embeddings.embed_query("food")
results = vector_store.similarity_search_by_vector(query_embedding, k=3)

Saving and Loading

Annoy indexes can be saved to disk and loaded later:

# Save to disk
vector_store.save_local("my_annoy_index")

# Load from disk
loaded_store = Annoy.load_local("my_annoy_index", embeddings)

Advanced Configuration

You can customize Annoy's behavior with different parameters:

# Custom metric and number of trees
vector_store = Annoy.from_texts(
    texts,
    embeddings,
    metric="dot",  # Use dot product instead of angular distance
    n_trees=100,   # Number of trees for indexing
    n_jobs=-1      # Number of parallel jobs (-1 uses all cores)
)

Working with Metadata

You can include metadata with your documents:

texts = ["pizza is great", "I love salad"]
metadatas = [{"type": "food"}, {"type": "food"}]

vector_store = Annoy.from_texts(
    texts,
    embeddings,
    metadatas=metadatas
)

Important Notes

  1. Annoy is read-only after building the index. If you need to add documents incrementally, consider using a different vector store.

  2. The similarity scores returned are distances - lower scores indicate more similar documents.

  3. The default metric is "angular" which corresponds to cosine similarity, but you can also use "euclidean" or "dot" product.

  4. When saving indexes, be cautious with the allow_dangerous_deserialization parameter as it could pose security risks if loading untrusted files.

By using Annoy in LangChain, you can efficiently implement similarity search for your document collections while benefiting from its fast search capabilities and memory-efficient design.

An alternative to LangSmith

Open-source LangChain monitoring, prompt management, and magic. Get started in 2 minutes.

LangChain Docs

Join 10,000+ subscribers

Every 2 weeks, latest model releases and industry news.

An alternative to LangSmith

Open-source LangChain monitoring, prompt management, and magic. Get started in 2 minutes.

LangChain Docs