liveBook · Manning

Vector index

As explained in Generative AI in Action

A vector index is a data structure that organizes high-dimensional vectors to support efficient similarity and nearest-neighbor searches.

A vector index helps a retrieval system find relevant content without comparing a query against every stored embedding. It is a data structure for fast similarity or nearest-neighbor lookup in high-dimensional vector space. A vector database stores embeddings alongside content and provides database capabilities; the index makes searching those embeddings efficient. This matters in retrieval-augmented generation (RAG), where slow retrieval can delay the answer. section 7.4 section 7.5

To prepare an index for RAG, split source documents into manageable chunks, create an embedding for each chunk, and retain a link to its source as metadata. A query is also embedded. Vector search uses the index to find similar document or passage embeddings, whose content can then be supplied to the LLM as context. section 7.4 section 7.5.2

Index design involves practical trade-offs:

  • Choose an exact or approximate nearest-neighbor approach, such as HNSW or IVF, according to speed and accuracy needs. section 7.5.1
  • Choose a similarity measure suited to the data and query, such as cosine similarity or squared Euclidean distance. section 7.5.1 section 7.5.2
  • Consider compression, such as quantization or pruning, when balancing speed, accuracy, and memory consumption. section 7.5.1

Searching blog posts for an answer

In a RAG chat application, blog posts are chunked, embedded, and indexed in Redis. A question becomes an embedding; a hybrid search returns the top five matching chunks. Those chunks and the original question are placed in the prompt before the LLM generates an answer. The local Redis deployment illustrates the flow, but setting up containers, ingesting data, and connecting retrieval to generation is not by itself a production-ready enterprise deployment. section 8.6 section 8.9

Listing 8.9 End-to-end RAG-powered chat
def hybrid_search(query_vector, client, top_k=5, hybrid_fields="*"):
...
    return results

def get_search_results(query:str, max_token=4096, 
                       debug_message=False) -> str:
    query_vector = get_embedding(query)    #1

    query_vector = np.array(query_vector).astype(
        np.float32).tobytes()    #2

    print("Searching for similar posts...")
    results = hybrid_search(query_vector, conn, top_k=5)   #3

    token_budget = max_token - count_tokens(query)        #4
    if debug_message:
        print(f"Token budget: {token_budget}")

    message = 'Use the blog post below to answer the subsequent 
               question. If the answer cannot be found in the 
               articles, write "Sorry, I could not find an answer in 
               the blog posts."'
    question = f"\n\nQuestion: {query}"

    if results:
        for i, post in enumerate(results.docs):          #5
            next_post = f'\n\nBlog post:\n"""\n{post.content}\n"""'
            new_token_usage = count_tokens(message + question + next_post)
            if new_token_usage < token_budget:
                if debug_message:
                    print(f"Token usage: {new_token_usage}")
                message += next_post
            else:
                break
    else:
        print("No results found")

    return message + question

def ask_gpt(query : str, max_token = 4096, debug_message = False) -> str:
    message = get_search_results(                      #6
        query,
        max_token,
        debug_message=debug_message)

    messages = [                                   #7
        {"role": 
         "system", 
         "content": "You answer questions in summary from the [CA]
                     blog posts."},
        {"role":
          "user",
            "content": message},]

    response = openai.ChatCompletion.create(           #8
        model="gpt-3.5-turbo-16k",
        messages=messages,
        temperature=0.7,
        max_tokens=2000,
        top_p=0.95
    )
    response_message = response["choices"][0]["message"]["content"]
    return response_message

if __name__ == "__main__":
    # Enter a query
    while True:
        query = input("Please enter your query: ")
        print(ask_gpt(query, max_token=15000, debug_message=False))
        print("=="*20)

The listing shows the handoff from query embedding to top-five hybrid search and prompt construction. section 8.6

For production use, plan the source-data integration and ingestion pipeline as carefully as the search itself. Data shape affects chunking and embedding work, while performance, cost, security, and scale make the vector database and index operational choices—not just implementation details. section 7.5 section 8.9

How Generative AI in Action covers it

How deep it goes
Defines the data structure and surveys indexing approaches, metrics, compression, and trade-offs without deriving their algorithms.
Examples
Uses a Redis-backed blog-post chat application that indexes chunks and retrieves five matches through hybrid search.
What it assumes
Builds on embeddings and RAG retrieval while defining the vector index before discussing its design choices.
What you can do after
Operate/configure it by choosing indexing and similarity options for retrieval, then assessing speed, accuracy, memory, and production needs.
How it connects
Connects vector databases, embeddings, nearest-neighbor search, similarity measures, and retrieval-augmented generation.

Also explained in

Compare how 8 books explain vector index →

Related concepts

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