liveBook · Manning

Retrieval-augmented generation

As explained in Generative AI in Action

Retrieval-augmented generation is a generation technique that retrieves relevant external information and supplies it to a generative model as context for its response.

Retrieval-augmented generation (RAG) lets a language model answer using relevant information retrieved from an external source. It is useful when answers depend on recent information or private enterprise data that the model did not learn during training. Rather than retraining the model whenever that data changes, an organization can update the external dataset. section 7.0 section 7.2

A RAG application has a retriever and a generator. The retriever searches an index, selects information relevant to the question, and supplies it as context. The generator—the language model—uses that context to produce an answer. In a vector-search implementation, the question and indexed documents are represented as vectors so the retriever can find similar documents. section 7.1 section 7.3

A practical implementation follows the data from source to answer:

  • Inspect the source system and define the use case, users’ information needs, and success metrics before building the pipeline. section 8.4.1
  • Extract and transform the data, split large documents into chunks, create embeddings, and store searchable records in an index. Choose chunk boundaries for the data and task; PDFs with tables or images need particular care. section 8.4.1 section 7.9
  • At question time, search for relevant chunks, combine them with the question in a prompt, and call the language model. Keep the model’s token budget in view when selecting context. section 8.6

Chat with an archive of blog posts

A chat application chunks nearly 20 years of blog posts, embeds them, and indexes them in Redis. For each question, it retrieves the top five matches, adds them to the prompt, and calls a GPT model. Its prompt instructs the model to say when the articles do not contain an answer. This is an illustrative integration, not a production-ready deployment. section 8.6

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 how a query embedding, top-five search, token budget, and retrieved context feed the chat request. section 8.6

Retrieval can ground responses and support source references, but it does not eliminate hallucinations. Answer quality depends on finding and preparing the right data. Production use also requires security, scaling, and operational work beyond a local Redis example. RAG complements prompt engineering and can remain useful even when a model is fine-tuned. section 7.2 section 13.1.2 section 8.6 section 9.0

How Generative AI in Action covers it

How deep it goes
Works through retrieval architecture, data preparation, and an illustrative chat integration, while leaving production engineering beyond the example.
Examples
Demonstrates a Redis-backed chat application that searches embedded blog-post chunks and passes five matches to a GPT model.
What it assumes
Assumes some familiarity with language-model prompts and enterprise data sources while explaining how retrieval fits between them.
What you can do after
Build it from scratch as an illustrative Redis-backed chat application, then plan security, scaling, and operations before production use.
How it connects
Connects vector search, embeddings, document chunking, prompt engineering, language models, and fine-tuning.

Also explained in

Compare how 32 books explain retrieval-augmented generation →

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.