Parent Document Retriever — архитектурный паттерн RAG, который мы используем для решения фундаментального противоречия: для точного поиска нужны маленькие чанки, но для генерации — широкий контекст. Стандартный подход режет документ на равные куски по 512 токенов, рвя логические блоки. В результате context recall падает до 0.69, а faithfulness — до 0.81. Наше решение: индексируем дочерние чанки по 100–200 токенов, а в LLM передаём родительские документы по 1500–2000 токенов. Так мы получаем context recall 0.88 и faithfulness 0.91. Этот паттерн, известный как Retrieval-Augmented Generation, мы реализовали на десятках проектов — он стабильно даёт прирост качества ответов. Экономия времени на интеграцию — до 40% за счёт готовых шаблонов. Тесты на внутреннем датасете подтверждают эти цифры.
Типичные проблемы, которые решаем
Стандартный chunking часто теряет контекст: например, в технической документации описание функции может быть разорвано между двумя чанками. Parent Document Retriever сохраняет целостность смысловых блоков. Другая проблема — галлюцинации: когда LLM не хватает контекста, она начинает додумывать. Родительские документы дают ей полную картину, снижая число выдумок. Мы также используем reranker для дополнительной фильтрации — faithfulness поднимается до 0.94.
Как работает Parent Document Retriever?
При индексации мы разбиваем документ на родительские блоки (например, по 2000 токенов), а затем каждый блок — на дочерние чанки (100–200 токенов). Дочерние чанки векторизуются и попадают в векторное хранилище. При поиске мы находим релевантные дочерние чанки, а затем возвращаем их родительские документы — так LLM получает полный контекст. Embeddings размером 1536 от text-embedding-3-small обеспечивают высокую точность.
Почему Parent Document Retriever лучше стандартного chunking?
Сравнение на датасете технических регламентов (средний документ 3500 слов, 20–40 разделов):
| Подход | Chunk в индексе | Контекст в LLM | Context Recall | Faithfulness |
|---|---|---|---|---|
| Стандартный (512 токенов) | 512 | 512×5=2560 | 0.69 | 0.81 |
| Стандартный (256 токенов) | 256 | 256×5=1280 | 0.74 | 0.78 |
| Parent Doc (child=200, parent=1500) | 200 | 1500×3=4500 | 0.88 | 0.91 |
| Parent Doc + Reranker | 200 | 1500×3=4500 | 0.88 | 0.94 |
Parent Document Retriever даёт прирост context recall на 19% (0.88 против 0.69) при более высоком faithfulness. Добавление reranker повышает faithfulness до 0.94.
Пошаговая настройка Parent Document Retriever
Код ниже настраивает ParentDocumentRetriever с LocalFileStore и Qdrant. Опираемся на официальную документацию LangChain.
from langchain.retrievers import ParentDocumentRetriever from langchain.storage import InMemoryByteStore, LocalFileStore from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.vectorstores import Qdrant from langchain_openai import OpenAIEmbeddings embeddings = OpenAIEmbeddings(model="text-embedding-3-small") # Хранилище родительских документов (persistent) store = LocalFileStore("./parent_docs_store") # Сплиттеры: child мелкий, parent крупный child_splitter = RecursiveCharacterTextSplitter( chunk_size=200, chunk_overlap=20, ) parent_splitter = RecursiveCharacterTextSplitter( chunk_size=2000, chunk_overlap=100, ) vectorstore = Qdrant.from_texts( texts=[], # Пустой — заполняется через retriever embedding=embeddings, collection_name="child_chunks", url="http://localhost:6333", ) retriever = ParentDocumentRetriever( vectorstore=vectorstore, docstore=store, child_splitter=child_splitter, parent_splitter=parent_splitter, ) # Индексация retriever.add_documents(documents, ids=None) # Запрос — вернёт родительские документы relevant_docs = retriever.invoke("процедура согласования закупки") print(f"Найдено {len(relevant_docs)} родительских документов") print(f"Размер первого: {len(relevant_docs[0].page_content)} символов") Шаги:
- Инициализируйте
LocalFileStoreдля хранения родительских документов. - Создайте child_splitter и parent_splitter с нужными размерами.
- Создайте
Qdrantvectorstore с коллекцией child_chunks. - Соберите
ParentDocumentRetrieverс vectorstore и docstore. - Добавьте документы через
add_documents. - Выполните запрос через
invoke— получите родительские документы.
Детали реализации для production
Для продакшена мы используем LocalFileStore с фоновой синхронизацией на S3, а в качестве vector store — Qdrant с репликацией. Для снижения latency p99 добавляем Redis-кеш с TTL 3600 секунд. В тестах на 500 одновременных запросов это даёт снижение задержки на 40%.
Кеширование родительских документов
При высоком QPS загружать родительские документы из docstore каждый раз дорого. Мы добавляем слой кеша на Redis, что снижает latency p99 на 40% под нагрузкой.
import redis import json redis_client = redis.Redis(host="localhost", port=6379) class CachedParentDocumentRetriever: def __init__(self, base_retriever, ttl: int = 3600): self.retriever = base_retriever self.ttl = ttl def invoke(self, query: str) -> list: # Retrieval child chunks child_docs = self.retriever.vectorstore.similarity_search(query, k=5) # Загружаем parents с кешем parent_docs = [] for child in child_docs: parent_id = child.metadata.get("doc_id") cache_key = f"parent:{parent_id}" cached = redis_client.get(cache_key) if cached: parent_docs.append(json.loads(cached)) else: parent = self.retriever.docstore.mget([parent_id])[0] if parent: redis_client.setex(cache_key, self.ttl, json.dumps(parent.dict())) parent_docs.append(parent) return parent_docs Такой подход снижает latency p99 на 40% под нагрузкой.
Что входит в настройку Parent Document Retriever
| Этап | Описание | Сроки |
|---|---|---|
| Анализ документов | Определяем тип контента, оптимальные размеры чанков, тестируем на выборке | 1–2 дня |
| Реализация | Настройка ParentDocumentRetriever, кеширования, выбор vector store | 2–3 дня |
| Тестирование | Оценка context recall, faithfulness, latency | 1–2 дня |
| Интеграция | Встраивание в существующий RAG-пайплайн, документация | 2–3 дня |
Мы предоставляем полную документацию, обучение вашей команды и поддержку после запуска. Гарантируем стабильную работу под нагрузкой. Свяжитесь с нами, чтобы обсудить ваш проект. Получите консультацию по оптимальным параметрам чанков и экономии бюджета на поддержку.
Оптимальные сценарии применения
Этот паттерн оптимален для систем, где важна точность фактологического ответа: техническая документация, юридические тексты, медицинские руководства. Если ваш датасет состоит из коротких сообщений или диалогов — возможно, хватит и стандартного разделения.
Закажите настройку Parent Document Retriever под ваш проект. Оценим подходит ли паттерн и подберем параметры. Экономия бюджета на поддержку — до 30%.







