Small chunks for retrieval, large parents for context — sentence-window, multi-vector. Use when building or optimizing retrieval-augmented generation pipelines with parent child retriever.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add anubhavg-icpl/vibe --skill parent-child-retriever-expert --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Parent Child Retriever Expert?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-parent-child-retriever-expert)More formats (shields.io, HTML) on the badges page.
---
name: parent-child-retriever-expert
description: Small chunks for retrieval, large parents for context — sentence-window, multi-vector. Use when building or optimizing retrieval-augmented generation pipelines with parent child retriever.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: rag-advanced
tags: [rag, parent-document, multi-vector, sentence-window, llamaindex, langchain]
---
# Parent-Child Retriever Expert Mode
You are an expert in parent-child retrieval (a.k.a. small-to-big, sentence-window, multi-vector). The core trade-off in RAG chunking: small chunks have crisp embeddings (precise retrieval) but lose context; big chunks preserve context but have muddier embeddings. Parent-child decouples the two — search over small representations, return their larger parents.
## Core Concept
Maintain two views of every chunk:
- **Search view** (small): a sentence, a 256-token chunk, an LLM-generated summary, or a hypothetical question. This is what gets embedded and retrieved.
- **Return view** (large): the surrounding paragraph, page, full document, or expanded window. This is what the LLM sees.
```
Index: [small_1, small_2, small_3, ...] ← embed and search these
Map: small_i → parent_i ← lookup by id
Return: parent_set ← give to the LLM
```
Variants:
- **Parent Document Retriever**: small ↔ medium chunks of the same doc.
- **Multi-Vector / Hypothetical Questions**: per parent, store N small representations (summary + 5 generated Qs). Retrieval may match any.
- **Sentence Window**: each sentence is the index unit; on hit, return ±k surrounding sentences.
- **Auto-merging retriever** (LlamaIndex): hierarchical chunks; if many sibling small chunks hit, return the parent instead of all the siblings.
## When It Helps
- **Long context windows but you don't want to dump the whole doc**.
- **Embeddings get noisy on long chunks** but lose meaning on tiny ones — typical in technical docs.
- **You want generation to see surrounding context** for coherent paraphrasing.
- **Document structure is hierarchical** (book → chapter → section → paragraph).
- **Latency matters**: retrieving small chunks is faster; expanding to parents is a cheap join.
## When It Hurts
- **Already short docs** (FAQ snippets): everything is its own parent.
- **You aggressively dedupe by parent**: often you collapse 5 small hits into 1 big parent — which means you lose the precision benefit (5 different signals about a parent might genuinely indicate it's relevant).
- **Storage doubles**: you keep both small and large representations.
- **Citation alignment**: harder to cite an exact sentence when the LLM is reading a whole page.
## Implementation Patterns
### LangChain ParentDocumentRetriever
```python
from langchain.retrievers import ParentDocumentRetriever
from langchain.storage import InMemoryStore
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)
child_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
vectorstore = Chroma(collection_name="children", embedding_function=OpenAIEmbeddings())
docstore = InMemoryStore()
retriever = ParentDocumentRetriever(
vectorstore=vectorstore,
docstore=docstore,
child_splitter=child_splitter,
parent_splitter=parent_splitter, # omit to use full docs as parents
)
retriever.add_documents(docs)
parents = retriever.invoke("What is the indemnification cap?")
```
### LlamaIndex Auto-merging Retriever
```python
from llama_index.core.node_parser import HierarchicalNodeParser, get_leaf_nodes
from llama_index.core.retrievers import AutoMergingRetriever
from llama_index.core import VectorStoreIndex, StorageContext
parser = HierarchicalNodeParser.from_defaults(chunk_sizes=[2048, 512, 128])
nodes = parser.get_nodes_from_documents(docs)
leaf_nodes = get_leaf_nodes(nodes)
storage = StorageContext.from_defaults()
storage.docstore.add_documents(nodes)
index = VectorStoreIndex(leaf_nodes, storage_context=storage)
base = index.as_retriever(similarity_top_k=12)
retriever = AutoMergingRetriever(base, storage, simple_ratio_thresh=0.5)
# If >50% of a parent's leaves hit, AutoMergingRetriever returns the parent.
```
### Sentence Window
```python
from llama_index.core.node_parser import SentenceWindowNodeParser
from llama_index.core.postprocessor import MetadataReplacementPostProcessor
parser = SentenceWindowNodeParser.from_defaults(window_size=3) # ±3 sentences
nodes = parser.get_nodes_from_documents(docs)
index = VectorStoreIndex(nodes)
qe = index.as_query_engine(
similarity_top_k=5,
node_postprocessors=[MetadataReplacementPostProcessor(target_metadata_key="window")],
)
# Retrieval matches the sentence; postprocessor swaps in the window before generation.
```
### Multi-Vector with hypothetical questions
```python
# Generate N hypothetical questions per parent chunk
HQ_PROMPT = "List {n} questions this passage answers, one per line:\n\n{c}"
from langchain.retrievers.multi_vector import MultiVectorRetriever
import uuid
children = []
for parent in parent_chunks:
qs = llm_generate_questions(parent.text, n=5)
pid = str(uuid.uuid4())
docstore.mset([(pid, parent)])
for q in qs:
children.append(Document(page_content=q, metadata={"parent_id": pid}))
vectorstore.add_documents(children)
retriever = MultiVectorRetriever(vectorstore=vectorstore, docstore=docstore, id_key="parent_id")
```
### Multi-Vector with summaries
Same shape, but the children are LLM-generated summaries of each parent (not questions). Useful when parents are long and the embedder can't process them.
## Eval / Tuning
- **Pick parent size based on your generation budget**: Claude/GPT-4o handle 2-8K token contexts well per parent; smaller models prefer 500-1500.
- **Child chunk size**: 100-400 tokens hits the embedding sweet spot for most encoders.
- **Top-k for children vs parents**: typically retrieve 10-20 children; dedup to 3-5 parents.
- **Compare against contextual retrieval** on the same set: contextual retrieval keeps a single index but injects context; parent-child keeps two views. Both fight the same problem.
- **For multi-vector**: ablate (summary only) vs (questions only) vs (both). Hypothetical questions tend to win when user queries are question-shaped.
- **Auto-merge threshold (0.3-0.7)**: lower = more eager to merge, higher = conservative.
## Common Pitfalls
- **Returning duplicate context**: 5 children from the same parent → join, dedupe. Otherwise the LLM sees the same paragraph 5 times.
- **Parent too large**: drowns the LLM in irrelevant text and burns tokens. Cap parent size.
- **Citation loss**: the LLM cites the parent, but the user wanted the sentence. Pass the matched sentence as a structured field separately.
- **Docstore bloat**: keeping every parent in memory works for prototypes; in production use Redis, Postgres, or your vector DB's payload store.
- **Stale parent links** when re-indexing: regenerate IDs atomically or use stable hashes of content.
- **Treating sentence-window as parent-child**: they're related; sentence-window's "parent" is just a fixed-size window, not a real document hierarchy.
## When to Use This Mode
Use parent-child when:
- Embedding precision is your retrieval bottleneck and context loss is hurting generation.
- Docs are long and hierarchical (books, papers, manuals).
- You can afford double storage and a docstore.
Reach specifically for:
- **Sentence Window** for prose-heavy content needing narrow citations with surrounding context.
- **Auto-merging** for hierarchical docs (chapter > section > paragraph).
- **Multi-vector w/ questions** when user queries are interrogative and don't share vocab with passages.
- **Multi-vector w/ summaries** when parents exceed your embedder's context.
Skip when corpus is short, flat, or already well-served by single-vector hybrid.
## Sources
- LangChain Parent Document Retriever — https://python.langchain.com/docs/how_to/parent_document_retriever/
- LangChain Multi-Vector Retriever — https://python.langchain.com/docs/how_to/multi_vector/
- LlamaIndex AutoMergingRetriever — https://developers.llamaindex.ai/python/examples/retrievers/auto_merging_retriever/
- LlamaIndex SentenceWindowNodeParser — https://developers.llamaindex.ai/python/framework/module_guides/loading/node_parsers/modules/
- "Advanced RAG: Small-to-big retrieval" — https://towardsdatascience.com/advanced-rag-01-small-to-big-retrieval-172181b396d4
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!