Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 23

Graceful Handling of Empty Retrieval Results

Recommended resources

Welcome back. In our previous lesson, you successfully assembled a complete RAG pipeline, orchestrating the retrieval, augmentation, and generation steps to produce a grounded, context-aware answer. You now have a working system that can query a knowledge base and synthesize a response.

This lesson addresses a crucial aspect of building robust systems: handling failure. Specifically, we'll tackle the common edge case where your retriever finds no relevant information for a given query. A production-grade application cannot simply fail or provide misleading information in this scenario. We will explore how to make your RAG pipeline more resilient by implementing strategies to gracefully manage these situations. You'll learn simple fallback techniques and then explore a more advanced, corrective approach.

The "No Context" Failure Mode

Your current pipeline is effective when the retriever successfully finds relevant document chunks. But what happens if it doesn't? Imagine a user asks a question that is completely unrelated to the documents in your vector store.

  1. Retrieval: The retriever.retrieve(query) call returns an empty list of nodes.
  2. Augmentation: Your create_augmented_prompt function is called with an empty context. The resulting prompt sent to the LLM would contain your system instructions and the user's question, but no "Evidence" section.
  3. Generation: The LLM receives this prompt and is asked to answer a question without any provided context, despite instructions to use only the provided context.

In this situation, the LLM's behavior can be unpredictable. It might:

  • Hallucinate: Invent an answer based on its pre-trained knowledge, directly violating your "constrained generation" instructions.
  • Refuse: Correctly identify the lack of context and respond with "I cannot answer this question based on the information provided."
  • Give a Vague Answer: Provide a generic, unhelpful response.

None of these outcomes are ideal. Hallucinations destroy user trust, while a simple refusal lacks clarity about why the answer couldn't be found. We need an explicit, reliable way to handle this.


Strategy 1: Prompt Engineering and Programmatic Checks

The most straightforward way to handle this edge case is to combine a simple programmatic check with smart prompt engineering.

The "I Don't Know" Prompt

You can explicitly instruct the LLM on how to behave when the context is insufficient. This reinforces the constrained generation you learned about previously. By adding a rule to your system prompt, you can guide the model to a desired, predictable outcome.

The video below demonstrates this simple but powerful technique. The presenter modifies the system prompt to include the instruction, "if you don't know the answer, just say I don't know," and then tests it with an out-of-scope query.

Build a RAG in 10 minutes! | Python, ChromaDB, OpenAI

This video from Thomas Janssen shows a quick and practical implementation of a basic RAG system.

First, watch the segment where the presenter sets up the system prompt. Note the explicit negative constraint. Then, see the test run where the system correctly responds "I don't know" to an irrelevant question.

This is an excellent first line of defense. A well-crafted prompt can often handle cases where the retrieved context is sparse or irrelevant.

The Code-Level Fallback

While good prompting helps, a more robust solution is to catch the failure at the code level, before even calling the LLM. You can modify your main pipeline function to check if the retrieval step returned any documents. If not, you can bypass the augmentation and generation steps entirely and return a canned response.

Here's how you could modify the query_rag_pipeline function from the last lesson:

def query_rag_pipeline(query: str) -> dict:
    """
    Orchestrates the full RAG pipeline, with a fallback for no-retrieval cases.
    """
    # 1. RETRIEVE: Fetch relevant context chunks
    retrieved_nodes = retriever.retrieve(query)

    # --- FALLBACK LOGIC ---
    if not retrieved_nodes:
        answer = "I'm sorry, but I couldn't find any relevant information in the knowledge base to answer your question."
        return {"answer": answer, "sources": []}
    # ----------------------

    # 2. AUGMENT: Construct the augmented prompt
    augmented_prompt = create_augmented_prompt(retrieved_nodes, query)

    # 3. GENERATE: Get the final response from the LLM
    answer = generate_response(augmented_prompt)
    
    sources = [node.metadata.get("file_name") for node in retrieved_nodes]

    return {"answer": answer, "sources": list(set(sources))}

# --- Example Usage ---
# user_query = "What is the capital of Mars?" 
# result = query_rag_pipeline(user_query)
# print(result["answer"]) 
# >> I'm sorry, but I couldn't find any relevant information...

This approach is simple, efficient, and gives the user clear feedback. It prevents unnecessary LLM calls and avoids the risk of hallucination entirely when no context is found.


Strategy 2: Corrective RAG (CRAG) with a Fallback

Giving up is one option, but what if we could correct the retrieval failure? This is the core idea behind more advanced RAG architectures. Instead of just stopping, the system attempts to find information from an alternative source.

Corrective RAG (CRAG) is a powerful pattern designed for this. It introduces an evaluation step after retrieval. If the retrieved documents are deemed irrelevant or insufficient, CRAG triggers a corrective action, such as performing a web search to find the missing information.

This diagram shows the CRAG architecture. After retrieval, an evaluator assesses the documents. If they are incorrect or ambiguous, it can trigger knowledge searching (e.g., a web search) to find better context before generation.

This diagram shows the CRAG architecture. After retrieval, an evaluator assesses the documents. If they are incorrect or ambiguous, it can trigger knowledge searching (e.g., a web search) to find better context before generation.

This makes the system far more versatile. It can rely on its primary, trusted knowledge base, but it also has a fallback to the vast, open knowledge of the internet for questions that fall outside that scope. This image below places CRAG within a family of RAG architectures.

This image compares four RAG architectures. Notice how Corrective RAG (c) introduces a decision step with an NLI model to classify retrieved documents as Correct, Ambiguous, or Incorrect, with a web search triggered for the latter two.

This image compares four RAG architectures. Notice how Corrective RAG (c) introduces a decision step with an NLI model to classify retrieved documents as Correct, Ambiguous, or Incorrect, with a web search triggered for the latter two.

The following video provides an excellent, in-depth walkthrough of building a CRAG system that uses web search as its fallback knowledge base. It's a perfect practical guide for a software engineer looking to implement a more sophisticated solution.

Building a Corrective RAG | Integrating Web Search as a fallback knowledge base | LangChain | Python

This video from Saurav Prateek provides a detailed tutorial on building a CRAG pipeline from scratch.

First, watch the introduction from the beginning to the overview to understand the core concept of CRAG and using web search as a fallback. Next, see the detailed explanation of the CRAG workflow. This part breaks down the diagram you saw earlier, explaining the 'Correct', 'Ambiguous', and 'Incorrect' paths. Then, jump to the implementation details. The presenter walks through the Python code for the decision node (decide_to_generate) that chooses between using the retrieved docs and triggering a web search. Pay attention to how the query is transformed for better web search results. Finally, watch the live demo where an irrelevant question is asked. You'll see the system identify the irrelevant documents, rewrite the query, perform a web search, and generate a correct answer from the new context.

For a supplementary text-based resource that covers the same ideas, the following article provides a concise overview and code snippets.

Corrective RAG (CRAG): Workflow, implementation, and more

This article from the Meilisearch blog provides a great written explanation of the CRAG pattern.

Focus on these key parts: The introduction explaining what CRAG is and how it improves on standard RAG. The section on the key components, especially the Evaluator. The implementation overview and the code snippets for evaluating context and assembling a prompt. Pay close attention to the final prompt construction in step 4, which includes the instruction: "If Evidence is insufficient, say 'Not enough information'". This combines the simple and advanced strategies.

Implementing a CRAG-like system is a significant step up in complexity, but it results in a much more capable and resilient application. It's a clear example of how modern AI systems are built with multiple layers of logic, evaluation, and fallback mechanisms.


Conclusion

In this lesson, you've learned how to handle one of the most common failure modes in a RAG system: failed retrieval. Making your application robust to this edge case is essential for building user trust and creating a reliable product.

Here are your key takeaways:

  • The "No Context" problem is critical. An unhandled retrieval failure can lead to hallucinations or unhelpful responses.
  • Simple Fallbacks are effective. A combination of programmatic checks ( if not retrieved_nodes: ) and explicit prompt instructions ( "If you don't know, say 'I don't know'" ) provides a strong, simple baseline for robustness.
  • Corrective RAG (CRAG) offers a powerful alternative. Instead of just failing, you can build a system that evaluates retrieval quality and falls back to an alternative knowledge source, like a web search, to find the answer.

You have now completed the core module on assembling a RAG pipeline. You've built a system from scratch and made it robust to common failures. But how good is it, really? In the next module, Measuring Success: RAG Evaluation, you will learn how to answer that question. We will dive into the critical metrics and methodologies for assessing the quality of both your retrieval and generation steps.