Retrieval Augmented Generation (RAG) often struggles with retrieving only the most relevant snippets, leading to either too much noisy context or too little information for the LLM to form a coherent answer.

Let’s see it in action. Imagine we have a knowledge base about different types of ice cream.

[
  {"id": "icecream_1", "name": "Vanilla Bean", "description": "A classic flavor made with real vanilla beans, known for its smooth, creamy texture and subtle sweet taste. Often paired with toppings.", "ingredients": ["milk", "cream", "sugar", "vanilla beans"]},
  {"id": "icecream_2", "name": "Chocolate Fudge Brownie", "description": "Rich chocolate ice cream loaded with chunks of fudgy brownie pieces and swirls of chocolate fudge. A decadent choice for chocolate lovers.", "ingredients": ["milk", "cream", "sugar", "cocoa powder", "brownie pieces", "chocolate fudge"]},
  {"id": "icecream_3", "name": "Strawberry Swirl", "description": "Sweet cream ice cream with ribbons of fresh strawberry puree. A refreshing and fruity option.", "ingredients": ["milk", "cream", "sugar", "strawberries"]},
  {"id": "topping_1", "name": "Hot Fudge", "description": "A warm, thick, and rich chocolate sauce, perfect for drizzling over ice cream.", "ingredients": ["sugar", "cocoa powder", "butter", "cream"]},
  {"id": "topping_2", "name": "Caramel Sauce", "description": "A sweet and buttery sauce made from caramelized sugar, offering a smooth, golden finish.", "ingredients": ["sugar", "butter", "cream"]},
  {"id": "topping_3", "name": "Sprinkles", "description": "Colorful sugar strands that add a playful crunch and visual appeal to any dessert.", "ingredients": ["sugar", "corn syrup", "artificial colors"]}
]

A basic RAG system might retrieve Vanilla Bean if you ask about "desserts." But what if you want to know how to make Vanilla Bean ice cream? The initial retrieval only gives you the product.

Parent-Child Retrieval addresses this by creating a hierarchical relationship between "parent" documents (like the ice cream itself) and "child" documents (like its ingredients or detailed preparation steps).

When you query for "how to make Vanilla Bean ice cream," the system first retrieves the "parent" document (icecream_1). Then, it uses information within that parent document (like the ingredients field or a linked "preparation" child document) to perform a secondary retrieval. This secondary retrieval pulls in more granular, specific information that wasn’t in the initial, broader search.

Here’s how it might work internally:

  1. Initial Retrieval (Parent): A query like "how to make Vanilla Bean ice cream" hits a vector database. The most similar embedding is for icecream_1. The system retrieves the entire icecream_1 document.

  2. Contextual Expansion (Child): The system analyzes the retrieved icecream_1 document. It sees the ingredients field and potentially a preparation_id field pointing to a separate preparation_1 document.

  3. Secondary Retrieval (Child): The system then queries the vector database again, but this time with a focus on retrieving documents related to icecream_1’s ingredients or preparation. It might retrieve topping_1, topping_2, topping_3 (as they are related by the context of "ice cream toppings") or a specific preparation_1 document with detailed steps.

  4. Augmented Prompt: The LLM receives a prompt that includes both the icecream_1 document and the relevant child documents. For instance:

    Context:
    [icecream_1 document: {"id": "icecream_1", "name": "Vanilla Bean", "description": "A classic flavor made with real vanilla beans, known for its smooth, creamy texture and subtle sweet taste. Often paired with toppings.", "ingredients": ["milk", "cream", "sugar", "vanilla beans"]}]
    [preparation_1 document: {"id": "preparation_1", "parent_id": "icecream_1", "steps": ["Combine milk, cream, and sugar in a saucepan.", "Heat gently until sugar dissolves.", "Whisk in vanilla beans.", "Chill the mixture.", "Churn in an ice cream maker.", "Freeze until firm."]}]
    
    Question: How do I make Vanilla Bean ice cream?
    
    Answer:
    

This allows the LLM to construct a detailed answer about making Vanilla Bean ice cream, using the ingredients and preparation steps retrieved through the parent-child mechanism.

The key is that the parent document acts as a semantic anchor. When the initial retrieval brings back a broad item, the system can then look within that item’s metadata or linked child documents to find more specific, actionable details that might not be directly queryable in a single pass. This is particularly useful for complex entities that have many related sub-entities or attributes that need to be understood together.

This approach fundamentally changes how you structure your knowledge base. Instead of a flat list of all facts, you create interconnected documents where a high-level summary can dynamically pull in detailed substories. This allows for richer, more nuanced context to be injected into the LLM’s prompt on demand, leading to more accurate and comprehensive answers.

The actual implementation often involves two distinct retrieval steps, potentially using different queries or filtering mechanisms between them. The first step is a broad retrieval based on the user’s query. The second step is a more focused retrieval that leverages the results of the first to pull in related child content.

The next logical step is to explore how to automatically identify and create these parent-child relationships within your data, especially for large, unstructured datasets.

Want structured learning?

Take the full Rag course →