Зачем этот проект

Модуль 04 — самый насыщенный по количеству тем: документы, чанкинг, эмбеддинги, векторные БД, retrieval, оценка, агентный RAG. На каждой теме пишешь изолированный пример. Проект — это то место, где все примеры соединяются в одну систему.

Q&A-бот по документации — не учебная задача. Это первое, что просят сделать во многих командах: «сделай нам умный поиск по вики». DocMind — полноценная реализация: с умным роутингом, самопроверкой ответов, RAGAS-оценкой и поддержкой нескольких источников.

Всё из уроков модуля — в одном проекте. Document Loaders → Chunking → Embeddings → Qdrant → Hybrid Search → Reranking → Query Transformation → RAGAS → Agentic RAG → Self-RAG → Graph RAG. Каждый урок модуля напрямую используется в системе.

Как это выглядит в работе

╔══════════════════════════════════════════════════════════════╗ DocMind · v1.0 · DataTalks.ru ╚══════════════════════════════════════════════════════════════╝ Коллекция: engineering-wiki · 4 832 чанка · Qdrant local Режим: Agentic RAG · Self-RAG: on · Модель: claude-sonnet-4-6 you › Что такое rate limiting и зачем он нужен? ── [Retrieve?] no retrieval needed ────────────────────────────── вопрос про общую концепцию → прямая генерация DocMind › Rate limiting — это ограничение количества запросов к API за единицу времени. Защищает сервис от перегрузки и злоупотреблений. Реализуется через алгоритмы Token Bucket или Sliding Window Counter. ──────────────────────────────────────────────────────────────── you › Какой лимит на запросы к нашему API для команды Data Science? ── [Retrieve?] yes → hybrid search ────────────────────────────── 🔍 hybrid_search(query="API rate limit Data Science team", k=8) → 8 чанков · BM25 + векторный · Qdrant · 45 мс ── [ISREL] фильтрация ──────────────────────────────────────────── ✓ api-limits.md §3 · "Data Science quota: 500 req/min" ✓ api-limits.md §5 · "burst до 2000 req/min при согласовании" ✗ nginx-config.md · нерелевантен (rate limiting Nginx — другое) ── Generate ───────────────────────────────────────────────────── ── [ISGRT] fully_supported ────────────────────────────────────── DocMind › Команда Data Science имеет лимит 500 запросов/минуту [1]. При необходимости можно согласовать burst до 2000 req/min через заявку в Platform team [2]. 📎 [1] api-limits.md, раздел 3 · Квоты по командам 📎 [2] api-limits.md, раздел 5 · Burst limits ──────────────────────────────────────────────────────────────── you › Какие сервисы зависят от Redis и кто за него отвечает? ── [Retrieve?] yes → graph search ─────────────────────────────── 🕸 graph_search(entity="Redis", hops=2) → Сервис корзины —[USES]→ Redis → Сервис авторизации —[USES]→ Redis → Команда Platform —[MAINTAINS]→ Redis → Redis —[DEPLOYED_IN]→ AWS eu-west-1 (3 hop) DocMind › Redis используют 2 сервиса: корзина (сессии) и авторизация (токены) [1]. Ответственность несёт Команда Platform, развёрнуто в AWS eu-west-1 [2]. 📎 [1] architecture.md · Зависимости Redis 📎 [2] infrastructure.md · Развёртывание ──────────────────────────────────────────────────────────────── you › Объясни разницу Enterprise и Business тарифа и есть ли скидка на год? ── Agentic: multi-step retrieval (DECOMPOSE) ──────────────────── 🔍 hybrid_search(query="Enterprise vs Business тариф отличия", k=6) → нашли сравнение тарифов · 3 чанка 🔍 hybrid_search(query="скидка годовая подписка тарифы", k=6) → нашли политику оплаты · 2 чанка ── [ISGRT] partially_supported → retry ───────────────────────── предупреждение: данные по скидке устарели (ревизия 2023) 🔍 hybrid_search(query="annual discount pricing 2024", k=4) → актуальный документ pricing-2024.md ── [ISGRT] fully_supported ────────────────────────────────────── DocMind › Enterprise vs Business: Business: до 50 пользователей, базовая поддержка 9×5, SLA 99.5% [1] Enterprise: неограниченные пользователи, поддержка 24×7, SLA 99.9%, выделенный менеджер, кастомные интеграции [1] Скидка при оплате на год: Business −15%, Enterprise −20% [2] 📎 [1] pricing.md · Сравнение тарифов 📎 [2] pricing-2024.md · Годовые скидки (обновлено 2024-03) you › /eval 20 Запуск RAGAS-оценки на 20 тестовых вопросах... Faithfulness: 0.91 Answer Relevancy: 0.87 Context Recall: 0.78 ↑ можно улучшить

Архитектура системы

DocMind состоит из двух независимых пайплайнов — индексирование и поиск — плюс агентного слоя поверх поиска. Индексирование запускается один раз (или инкрементально при обновлении документов). Поиск работает на каждый запрос.

100%
колёсико — масштаб  ·  зажать и тянуть — перемещение
ИСТОЧНИКИ PDF / Word Markdown / HTML Notion / Confluence Web / Firecrawl INDEXING (offline) Document Loaders Chunking + Metadata parent-child / semantic Embed (nomic-embed) NER + Triplets Graph extraction Qdrant dense vectors BM25 payload index NetworkX Graph entities + relations community summaries QUERY PIPELINE (online) Вопрос пользователя [Retrieve?] yes / no / graph нет → Query Transform expand / HyDE / decompose Hybrid Search dense + BM25, RRF ISREL + Rerank фильтр + cross-encoder Generate + ISGRT к-кандидатов → лучший Ответ + цитаты с ссылками на чанки прямая генерация (нет retrieval) graph → RAGAS Eval faithfulness answer relevancy context recall offline eval Document Sources Storage Graph Build

Два режима обработки запросов

Simple RAG
Когда: простой фактический вопрос, ответ в одном месте.
① [Retrieve?] = yes → hybrid_search ② ISREL: фильтрация нерелевантных чанков ③ Rerank: cross-encoder сортирует по релевантности ④ Generate: LLM отвечает по топ-3 чанкам ⑤ [ISGRT]: проверка заземлённости → возврат Время ответа: ~500–800 мс.
Agentic RAG
Когда: составной вопрос, multi-hop, недостаточно одного поиска.
① Query transform: декомпозиция / расширение ② Multi-step: 2–4 итерации с gap analysis ③ Graph search: если вопрос про связи сущностей ④ Self-RAG: ISREL + генерация k кандидатов + ISGRT ⑤ Rank: лучший по score = ISUSE × ISGRT.weight Время ответа: 1.5–4 сек.

Компоненты системы

DocMind строится из шести слоёв, каждый из которых соответствует одному-двум разделам модуля. Слои независимы — можно заменить Qdrant на pgvector или добавить новый источник данных без изменения агентного слоя.

Компонент
Что делает
Уроки модуля
DocLoader
Загружает документы из PDF (PyMuPDF), Markdown, Notion API, Confluence, веб-страниц (Firecrawl). Извлекает метаданные: источник, дату, раздел, автора.
ChunkPipeline
Нарезает документы стратегией parent-child: мелкие чанки (256 токенов) для поиска, родительские (1024) для контекста LLM. Семантический чанкинг для длинных документов.
IndexStore
Qdrant хранит плотные векторы (nomic-embed-text) и payload-индекс для BM25. Параллельное upsert батчами по 100 чанков. Инкрементальное обновление по chunk_id hash.
GraphStore
NetworkX граф: сущности и отношения извлекаются LLM при индексировании. Leiden-кластеризация для community summaries (глобальный поиск). Fuzzy matching имён сущностей.
Retriever
Hybrid search (BM25 + dense, RRF fusion), metadata filtering, cross-encoder reranking (ms-marco-MiniLM), contextual compression. Все параметры конфигурируемы.
AgenticLayer
[Retrieve?] классификатор → router (simple/multi-step/graph). Self-RAG: ISREL батч-фильтрация, генерация k кандидатов параллельно, ISGRT + ISUSE ранжирование.
EvalPipeline
RAGAS: автоматическая генерация тест-сета через TestsetGenerator, оценка faithfulness / answer_relevancy / context_recall. Команда /eval N запускает прямо из CLI.

План реализации

Шесть этапов, каждый даёт рабочую систему. На каждом этапе — конкретные файлы и тесты. Реализацию удобно разбить на дни: этапы 1–2 за день один, 3–4 за день два, 5–6 за день три.

1
Базовый RAG-пайплайн
DocLoader для PDF и Markdown. ChunkPipeline с parent-child. Embed через nomic-embed-text. Qdrant с dense-только поиском. CLI команда index ./docs/ и простой ask "вопрос". Цель: система отвечает на прямые фактические вопросы.
2
Hybrid Search + Reranking
Добавить BM25 payload-индекс в Qdrant. RRF-fusion dense + sparse. Cross-encoder reranking через ms-marco-MiniLM. Metadata filtering по источнику и дате. Замерить разницу recall до и после — должно быть заметно.
3
Query Transformation + Self-RAG
[Retrieve?] классификатор. Query expansion для коротких запросов. ISREL батч-фильтрация нерелевантных чанков. Генерация k=3 кандидатов. ISGRT + ISUSE ранжирование. Логирование рефлексий в structured JSON.
4
Multi-step + Graph RAG
Gap-analysis loop: до 4 итераций с уточнением запроса. NER + relation extraction при индексировании (кэш). NetworkX граф. Local search по 2-hop обходу. Роутер: простой вопрос → simple, multi-hop → graph, составной → decompose.
5
RAGAS Evaluation
TestsetGenerator: автоматически генерирует 50 QA-пар из корпуса (simple / reasoning / multi-context). Команда /eval N запускает offline-оценку и выводит метрики в таблицу. Выявляем слабые места и фиксим.
6
Connectors + Production
Notion и Confluence коннекторы. Инкрементальный re-index (hash по chunk_id). Команды /sources, /reindex, /stats. Rate limiting LLM-вызовов. Dockerfile + docker-compose с Qdrant.

Технологический стек

🐍 Python 3.11+ anthropic SDK openai SDK pydantic v2 langchain-text-splitters langchain-community qdrant-client sentence-transformers networkx python-louvain ragas rich typer python-dotenv pymupdf firecrawl-py
Embedding модели
nomic-embed-text
основная модель, бесплатная, 768-dim, 8192 токенов контекста
text-embedding-3-small
OpenAI опция, если нужна облачная инфраструктура

LLM модели
claude-sonnet-4-6
генерация ответов, ISREL batch, ISGRT, [Retrieve?]
gpt-4o-mini
NER extraction, community summaries (дешевле, быстрее)
ms-marco-MiniLM-L-6-v2
cross-encoder reranking, локально без API, ~10ms/запрос

Инфраструктура
Qdrant
docker-compose или qdrant-client local mode (no docker)
NetworkX
в памяти, сохранение в graph.json, загрузка при старте

Структура проекта

docmind/ ├── main.py # точка входа, Typer CLI ├── indexing/ │ ├── loader.py # DocLoader: PDF, MD, Notion, Firecrawl │ ├── chunker.py # ChunkPipeline: parent-child + semantic │ ├── embedder.py # nomic-embed / text-embedding-3-small │ ├── graph_extractor.py # NER + triplets + community detection │ └── pipeline.py # orchestrate: load → chunk → embed → store ├── storage/ │ ├── qdrant_store.py # hybrid index, CRUD, metadata filtering │ └── graph_store.py # NetworkX: add_triplets, neighbors, communities ├── retrieval/ │ ├── hybrid_search.py # BM25 + dense + RRF fusion │ ├── reranker.py # cross-encoder ms-marco (sentence-transformers) │ ├── compressor.py # contextual compression чанков │ └── graph_search.py # local (hop traversal) + global (communities) ├── agent/ │ ├── retrieve_gate.py # [Retrieve?] классификатор │ ├── query_transformer.py # expand, HyDE, decompose │ ├── router.py # simple / multi-step / graph / direct │ ├── self_rag.py # ISREL, generate candidates, ISGRT, ISUSE, rank │ ├── multi_step.py # gap analysis loop, stopping criteria │ └── docmind.py # главный класс DocMind.ask() ├── eval/ │ ├── testset_generator.py # RAGAS TestsetGenerator │ └── ragas_eval.py # evaluate() → faithfulness/relevancy/recall ├── ui/ │ └── display.py # Rich: таблицы, spinner, Markdown вывод ├── config/ │ └── settings.py # Pydantic Settings, .env, defaults ├── tests/ │ ├── test_chunker.py │ ├── test_retrieval.py # mock Qdrant │ ├── test_self_rag.py # mock LLM │ └── test_graph.py ├── docker-compose.yml # Qdrant container ├── pyproject.toml └── .env.example

CLI-команды

Команда Описание
docmind index ./docs/ Индексировать папку с документами. Инкрементально — только изменившиеся.
docmind ask "вопрос" Задать вопрос. Флаг --mode simple/agentic/graph/auto.
docmind chat Интерактивный режим с историей диалога.
docmind eval --n 50 Запустить RAGAS-оценку на N тестовых вопросах, вывести таблицу метрик.
docmind stats Статистика коллекции: документов, чанков, сущностей в графе.
docmind reindex --source notion Переиндексировать конкретный источник данных.

Что закрепляет этот проект

📄
Document Loaders + Metadata — интеграция с реальными источниками, извлечение структурированных метаданных для фильтрации.
✂️
Parent-child Chunking — понимаете зачем нужны два уровня: мелкий для точного поиска, крупный для контекста LLM.
🔍
Hybrid Search + Reranking — BM25 + dense + RRF в связке, cross-encoder как финальный арбитр релевантности.
🔄
Query Transformation — HyDE, expansion, decompose: разные стратегии под разные типы вопросов.
🤖
Self-RAG — четыре рефлексивных токена в production-коде: видите где и почему каждый из них нужен.
🔁
Multi-step Retrieval — gap analysis loop: понимаете когда одного поиска недостаточно и как накапливать контекст.
🕸️
Graph RAG — извлечение троек, обход графа, community summaries — всё в production-контексте, не как отдельный эксперимент.
📊
RAGAS Evaluation — автоматическая генерация тест-сета, замер метрик, итерация промптов на основе данных.
📐
Layered Architecture — каждый слой (indexing / storage / retrieval / agent / eval) независим. Замена Qdrant на pgvector — только в одном файле.

Следующий шаг: реализация

Пошаговое руководство по написанию кода — от базового RAG до полного агентного пайплайна с RAGAS-оценкой. Каждый этап тестируется отдельно.

Реализация — скоро