Представьте: вы за выходные собираете RAG-бота на LangChain, грузите десяток PDF, и он работает как часы. Но когда документов становится тысячи, точность падает, ответы теряют смысл, а юридические риски растут. Именно через это прошёл наш проект «Марк» — ИИ-эксперт по охране труда. В этой статье мы рассказываем, как перестроили архитектуру, чтобы вывести систему на промышленный уровень.
Основные этапы эволюции
Почему наивный RAG разваливается на больших данных
На старте мы использовали ChromaDB в embedded-режиме, стандартную нарезку текста (RecursiveCharacterTextSplitter) и LLM-реранкер. На 50–100 документах система выглядела идеально, но при росте базы до тысяч файлов «шумы» в выдаче стали критическими. Векторный поиск терял релевантные фрагменты среди семантически похожих, но неверных инструкций, а LLM-реранкер добавлял 5–10 секунд задержки и оказался нестабильным.
Перестройка ETL — фундамент качества
Мы осознали главный принцип: GIGO (Garbage In — Garbage Out). Новая стратегия обработки данных включала:
Структурированное извлечение с сохранением иерархии документа (заголовки, пункты).
Умный чанкинг с семантическим окном и настраиваемым перекрытием.
Дедупликацию эмбеддингов (порог 0.92) для уменьшения индекса.
Переход на Qdrant с client‑server архитектурой, батчевой загрузкой и богатыми метаданными (fileName, номера страниц), что дало +40% точности при поиске шаблонов.
Гибридный поиск и расширение запросов
Векторов оказалось недостаточно для точных совпадений (например, «Приказ №33н»). Мы внедрили гибридный поиск (EnsembleRetriever с весами 0.6 для dense‑векторов и 0.4 для BM25) и Query Expansion — быстрая LLM генерирует три вариации запроса, что повышает шансы зацепить нужный контекст.
Замена реранкера и оркестрация через LangGraph
LLM-скоринг уступил место специализированной модели BAAI/bge-reranker-v2-m3 — миллисекунды на чанк и точные оценки. Логику работы мы перенесли на LangGraph, создав граф состояний с узлами retrieve, grade_documents (бинарная проверка релевантности Gemma 3:12B) и generate (Gemma 3:27B). Это позволило реализовать циклы переформулировки запроса при пустом результате и сохранять контекст диалога в PostgreSQL.
Метрики и результаты
Системный сбор метрик начали поздно, но финальные замеры впечатляют:
Иерархический чанкинг поднял LLM-Score с 0.72 до 0.83.
Семантическое окно в комбинации со всеми улучшениями дало LLM-Score 0.92 при незначительном снижении Precision (избыточность контекста стала платой за полноту).
Выводы
Производственный RAG — это на 80% работа с данными и на 20% — подбор моделей. Наш чек-лист для тех, кто идёт в production:
Инвестируйте в ETL и иерархический чанкинг.
Обязательно используйте гибридный поиск.
Специализированный реранкер — must-have.
Откажитесь от линейных цепочек в пользу графовых (LangGraph).