liveBook · Manning

Approximate nearest neighbor algorithm

As explained in AI-Powered Search

Approximate nearest neighbor search is a retrieval technique that finds vectors likely to be nearest to a query vector while reducing the computations required for exact nearest-neighbor search.

A semantic search engine can compare a query embedding with every document embedding, but that becomes slow as the collection grows. Approximate nearest neighbor (ANN) search instead retrieves vectors likely to be close to the query, leaving a smaller set to score. It trades some accuracy for faster retrieval and lower resource costs. section 13.5.3

A practical ANN search pipeline has three parts:

  • Generate document embeddings ahead of time and add them to a searchable index. HNSW organizes nearby vectors in a multilayer graph; an inverted file index is another option. section 13.5.3
  • Encode the query, search the index for a configurable number of candidates, and filter or rank the returned matches. For cosine-based matching, normalize document and query vectors so dot products can supply similarity scores. section 13.5.4 section 13.2.2
  • Check both speed and result quality. Semantically related results are not necessarily the most relevant results for a short, ambiguous query. section 13.6.2
Listing 13.14 ANN search using NMSLIB
import nmslib

concepts_index = nmslib.init(method="hnsw",  #1
                             space="negdotprod")  #1
normalized_embeddings = list(map(normalize_embedding, embeddings))
concepts_index.addDataPointBatch(normalized_embeddings)  #2
concepts_index.createIndex(print_progress=True)   #3

ids, _ = concepts_index.knnQuery( #4
           normalized_embeddings[25], k=10)  #4
matches = [labels[phrases[i]].lower() for i in ids] #5
display(matches)

The Python listing initializes an NMSLIB HNSW index, adds normalized embeddings as a batch, builds the index, and requests ten neighbors. section 13.5.4

Semantic autocomplete

An autocomplete index holds embeddings for 12,375 terms. Searching for “bag” returns related terms such as “bag cover,” “bag liner,” and “paper bag” without comparing the query against every term at search time. The query helper also sets a candidate count and minimum similarity; queries such as “mountain hike” can then surface related suggestions. section 13.5.4 section 13.5.3

Listing 13.15 Encoding a query and returning the k-nearest-neighbor concepts
def embedding_search(index, query, phrases, k=20,  #1
                     min_similarity=0.75):  #1
  matches = []
  query_embedding = transformer.encode(query) #2
  query_embedding = normalize_embedding(query_embedding)
  ids, distances = index.knnQuery(query_embedding, k=k)
  for i in range(len(ids)):
    similarity = distances[i] * -1  #3
    if similarity >= min_similarity: #4
      matches.append((phrases[ids[i]], similarity))
  if not len(matches):
    matches.append((phrases[ids[1]], distances[1] * -1))  #5
  return matches

def semantic_suggest(prefix, phrases):
  matches = embedding_search(concepts_index, prefix, phrases)
  print_labels(prefix, matches)

semantic_suggest("mountain hike", phrases)
semantic_suggest("dehyd", phrases)

The query helper shows encoding, normalization, k-neighbor retrieval, conversion of returned distances to similarity scores, and a minimum-similarity filter. section 13.5.4

ANN is one part of a larger performance trade-off. Quantization can shrink embeddings, Matryoshka Representation Learning can reduce the dimensions used for initial retrieval, and reranking can improve the final candidates. In one combined inverted-file-index example, search was about 99% faster and the index about 98% smaller than full-precision search, while reranked recall remained above 72%; those figures describe that configuration, not an ANN guarantee. section 13.7.5

How AI-Powered Search covers it

How deep it goes
Works through HNSW index creation and querying, while leaving the graph algorithm’s implementation to NMSLIB.
Examples
Demonstrates autocomplete over 12,375 terms and semantic retrieval of hiking-related question titles.
What it assumes
Assumes document embeddings are available, but shows how to create their ANN index and query it.
What you can do after
Build it from scratch with NMSLIB by indexing normalized embeddings and querying HNSW for semantic suggestions.
How it connects
Connects dense vector search and embeddings with HNSW, inverted file indexes, quantization, Matryoshka Representation Learning, and reranking.

Also explained in

Compare how 5 books explain approximate nearest neighbor algorithm →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of AI-Powered Search. The section links point to the parts of the book it draws on.