Skip to content

Vector Search

Vector search is the core functionality of Quiver, allowing you to find similar vectors based on their semantic similarity. This guide explains how vector search works in Quiver and how to use it effectively.

How Vector Search Works

Vector search in Quiver is powered by the HNSW (Hierarchical Navigable Small World) algorithm, which provides an excellent balance between search speed and accuracy. Here's how it works:

  1. Indexing: When you add vectors to Quiver, they are organized into a graph structure where similar vectors are connected.
  2. Search: When you search, Quiver navigates this graph to find the most similar vectors to your query.
  3. Distance Calculation: Similarity is measured using a distance metric (cosine or L2).
  4. Result Ranking: Results are ranked by similarity, with the most similar vectors first.

The most basic form of vector search finds the k-nearest neighbors to a query vector:

from quiver import Quiver

# Create a Quiver index
index = Quiver(dimension=128)

# Add some vectors
index.add(id=1, vector=[0.1, 0.2, 0.3, ...], metadata={"text": "Document 1"})
index.add(id=2, vector=[0.2, 0.3, 0.4, ...], metadata={"text": "Document 2"})
index.add(id=3, vector=[0.3, 0.4, 0.5, ...], metadata={"text": "Document 3"})

# Search for similar vectors
query_vector = [0.15, 0.25, 0.35, ...]
results = index.search(query=query_vector, k=2)

# Print results
for result in results:
    print(f"ID: {result.id}, Distance: {result.distance}, Text: {result.metadata['text']}")

Search Parameters

Quiver's search function accepts several parameters to customize your search:

results = index.search(
    query=query_vector,  # The query vector
    k=10,                # Number of results to return
    page=1,              # Page number (1-indexed)
    page_size=10         # Number of results per page
)

Parameters

  • query: The query vector to search for
  • k: Number of nearest neighbors to find
  • page: Page number for pagination (1-indexed)
  • page_size: Number of results per page

Distance Metrics

Quiver supports two distance metrics:

  1. Cosine Distance (default): Measures the cosine of the angle between vectors (1 - cosine similarity)
  2. L2 Distance (Euclidean): Measures the straight-line distance between vectors

You can specify the distance metric when creating the index:

# Create an index with L2 distance
index = Quiver(dimension=128, distance="l2")

# Create an index with cosine distance (default)
index = Quiver(dimension=128, distance="cosine")

Which Distance Metric to Use?

  • Cosine Distance: Best for text embeddings and when vector magnitude doesn't matter
  • L2 Distance: Best when vector magnitude is important (e.g., image embeddings)

Advanced Search Features

Quiver offers several advanced search features:

Search with Metadata Filtering

Filter search results based on metadata:

results = index.search_with_filter(
    query=query_vector,
    k=10,
    filter="category = 'news' AND date > '2023-01-01'"
)

Search with Negative Examples

Find vectors similar to a positive example but dissimilar to negative examples:

results = index.search_with_negatives(
    positive_query=positive_vector,
    negative_queries=[negative_vector1, negative_vector2],
    k=10
)

Search for multiple query vectors in a single call:

results = index.multi_vector_search(
    queries=[query_vector1, query_vector2, query_vector3],
    k=10
)

Filter search results based on exact metadata field matches:

results = index.faceted_search(
    query=query_vector,
    k=10,
    facets={
        "category": "news",
        "author": "John Doe"
    }
)

Performance Considerations

To get the best performance from Quiver's vector search:

  1. Choose the right HNSW parameters:
  2. Higher hnsw_m values improve search quality but increase memory usage
  3. Higher hnsw_ef_search values improve search accuracy but decrease speed

  4. Use dimensionality reduction for large vectors:

  5. Enable dimensionality reduction for vectors with more than 1000 dimensions
  6. This can significantly improve search speed with minimal impact on accuracy

  7. Batch similar operations:

  8. Use batch operations when adding or searching multiple vectors
  9. This reduces overhead and improves throughput

  10. Consider pagination for large result sets:

  11. Use the page and page_size parameters to paginate results
  12. This reduces memory usage and improves response times

Best Practices

  1. Normalize vectors before adding them to the index (especially for L2 distance)
  2. Use consistent embedding models for queries and indexed vectors
  3. Add meaningful metadata to make search results more useful
  4. Use the right distance metric for your use case
  5. Tune HNSW parameters based on your specific requirements
  6. Consider using dimensionality reduction for very high-dimensional vectors

Next Steps