Поиск по принципу «родительский фрагмент — дочерний» и от малого к большому
Храните небольшие дочерние фрагменты для точного поиска, но возвращайте LLM более крупные родительские фрагменты для расширенного контекста, находя баланс между точностью поиска и качеством генерации.
«Поиск по принципу «родительский фрагмент — дочерний» и от малого к большому» — бесплатный урок AI Engineering Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения AI Engineering Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс AI Engineering Academy содержит 4 уроков всего.
Части этого урока еще не переведены и отображаются на английском.
The Precision vs Context Dilemma
RAG systems face a tension: small chunks are retrieved with high precision because each chunk is focused on one idea, but they lack the surrounding context the LLM needs to generate a complete answer. Large chunks provide rich context but reduce retrieval precision because they match many queries weakly instead of one query strongly. Parent-child chunking solves this dilemma.
The Parent-Child Architecture
In parent-child chunking, you create two layers of chunks from the same document. Child chunks are small (e.g., 1-3 sentences) and are embedded and indexed for retrieval. Parent chunks are larger sections (e.g., entire paragraphs or pages) that are stored separately. When a child is retrieved, you return its parent to the LLM instead.
Building the Chunk Hierarchy
The first step is to split the document into large parent chunks, then split each parent into smaller child chunks. Each child chunk keeps a reference — typically a parent_id metadata field — pointing back to its parent. This mapping allows you to look up the full parent passage given any retrieved child.
from langchain.text_splitter import RecursiveCharacterTextSplitter
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=1500, chunk_overlap=0)
child_splitter = RecursiveCharacterTextSplitter(chunk_size=300, chunk_overlap=30)
parent_chunks = parent_splitter.split_documents(docs)
child_chunks = []
for i, parent in enumerate(parent_chunks):
children = child_splitter.split_documents([parent])
for child in children:
child.metadata['parent_id'] = i
child_chunks.extend(children)Indexing Only Child Chunks
Only the child chunks are embedded and stored in the vector database. The parent chunks are stored in a separate key-value store (an in-memory dictionary, Redis, or a document database). This keeps the vector index dense and precise while the rich context lives outside it.
# Store parents in a docstore
parent_store = {i: chunk.page_content for i, chunk in enumerate(parent_chunks)}
# Embed and index only children
vectorstore = Chroma.from_documents(
child_chunks,
embedding=OpenAIEmbeddings()
)Retrieval: Child In, Parent Out
During retrieval, the user query is embedded and matched against child chunks. The top-k child chunks are found, and their parent_id references are resolved by looking up the parent store. The parent passages — not the children — are then injected into the LLM prompt. The LLM receives broad context; retrieval was precise.
def retrieve_with_parents(query, vectorstore, parent_store, k=5):
child_results = vectorstore.similarity_search(query, k=k)
seen_parent_ids = set()
parent_contexts = []
for child in child_results:
pid = child.metadata['parent_id']
if pid not in seen_parent_ids:
parent_contexts.append(parent_store[pid])
seen_parent_ids.add(pid)
return parent_contextsLangChain ParentDocumentRetriever
LangChain provides the ParentDocumentRetriever class that implements this pattern out of the box. You provide a parent splitter, child splitter, a vectorstore for child embeddings, and a docstore for parent documents. It wires up the hierarchy and handles retrieval transparently.
from langchain.retrievers import ParentDocumentRetriever
from langchain.storage import InMemoryStore
store = InMemoryStore()
retriever = ParentDocumentRetriever(
vectorstore=vectorstore,
docstore=store,
child_splitter=child_splitter,
parent_splitter=parent_splitter
)
retriever.add_documents(docs)
results = retriever.invoke('What is the refund policy?')Small-to-Big Retrieval Explained
Small-to-big retrieval is another name for the same concept: you retrieve small, precise chunks but then expand them to their surrounding context before sending to the LLM. Some implementations expand not to a fixed parent but to a window of adjacent sentences — giving the model the sentences before and after the matched chunk for contextual continuity.
def retrieve_with_window(query, vectorstore, sentences, window=2, k=5):
results = vectorstore.similarity_search(query, k=k)
expanded = []
for r in results:
idx = r.metadata['sentence_index']
start = max(0, idx - window)
end = min(len(sentences), idx + window + 1)
expanded.append(' '.join(sentences[start:end]))
return expandedDeduplicating Parent Chunks
Multiple child chunks from the same parent may all be retrieved for one query. Without deduplication, the same parent passage would appear multiple times in the prompt, wasting tokens. Always deduplicate by parent ID before assembling the context. The code example in the retrieve function above handles this with a seen_parent_ids set.
When to Use Parent-Child Chunking
Parent-child retrieval works best when your documents have clear hierarchical structure: chapters with sections, articles with paragraphs, or wikis with subsections. It is particularly effective for long technical documentation where precise questions need localized answers but those answers only make sense within a broader section of context.
Choosing Child and Parent Sizes
A typical configuration is: child chunks of 200-400 tokens (focused single ideas) and parent chunks of 1000-2000 tokens (complete sections). If child chunks are too small, they become individual sentences that lack meaning on their own. If parent chunks are too large, you start reintroducing the context dilution problem you were trying to avoid.
Comparing Approaches: A Summary
To summarize the chunking strategies so far: fixed-size is fast but breaks context; semantic chunking preserves topic coherence; parent-child optimizes both retrieval precision and LLM context richness. For most production RAG systems handling long documents, parent-child chunking delivers the best retrieval quality at manageable complexity.
Quick Check
Test your understanding of parent-child chunking from this lesson.
Lesson Recap
In this lesson you learned: child chunks provide precise retrieval while parent chunks provide rich context, LangChain's ParentDocumentRetriever implements this automatically, and deduplication by parent ID prevents context repetition. Next up we explore document-specific chunking strategies for code files and HTML documents.
Часто задаваемые вопросы
Урок «Поиск по принципу «родительский фрагмент — дочерний» и от малого к большому» бесплатный?
Да — полный текст урока «Поиск по принципу «родительский фрагмент — дочерний» и от малого к большому» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс AI Engineering Academy, подпишись на CoddyKit PRO. Курс AI Engineering Academy содержит 4 уроков всего.
Чему я научусь в уроке «Поиск по принципу «родительский фрагмент — дочерний» и от малого к большому»?
Храните небольшие дочерние фрагменты для точного поиска, но возвращайте LLM более крупные родительские фрагменты для расширенного контекста, находя баланс между точностью поиска и качеством генерации. Ты практикуешь AI Engineering Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать AI Engineering Academy?
Предыдущий опыт не требуется. AI Engineering Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Поиск по принципу «родительский фрагмент — дочерний» и от малого к большому»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке AI Engineering Academy?
Да. Каждый урок AI Engineering Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Почему наивное разбиение вредит поиску
- Семантическое разбиение по сходству эмбеддингов
- Поиск по принципу «родительский фрагмент — дочерний» и от малого к большому
- Стратегии для кода и HTML с учётом типа документа