Крупная логистическая компания. Многолетний архив — договоры с перевозчиками, регламенты, переписка по инцидентам. Менеджер хочет узнать: были ли у нас претензии к этому контрагенту и на каких условиях мы с ним работали два года назад? Открывает почту, потом SharePoint, потом звонит в архив. Через час у него есть частичный ответ.
Та же ситуация повторяется в таможне, банках и юридических фирмах. Данные накоплены — в PDF, Word, сканах, таблицах. Но корпоративная база знаний не отвечает на вопросы: нет инструмента, который понимал бы смысл запроса, а не просто искал по ключевым словам. Автоматизация документооборота упёрлась в потолок классических СЭД.
Обычный RAG или Hybrid RAG — в чём разница
Обычный RAG хорошо работает, когда база однородная: один регламент, FAQ по продукту, чистые текстовые документы на одном языке. Для корпоративного ИИ-ассистента над одним источником этого достаточно.
Hybrid RAG нужен, когда база состоит из разнородных документов — договоры, нормативные акты, технические инструкции, архивная переписка — и часть из них сканы или таблицы. Когда запросы смешивают естественный язык с конкретными терминами: кодами, числами, артикулами. Когда данные на двух языках. В этом случае семантического поиска по документам в одиночку не хватает: запрос «были ли споры по коду 8471300000?» требует одновременно понимания смысла и точного совпадения по конкретному числу.
Почему это не решается подключением ChatGPT
Языковая модель не знает внутренних документов компании и не может держать тысячи страниц в контексте одновременно. Но дело не только в объёме.
В регулируемых отраслях — медицине, банках, таможне — нейросеть без облака это не опция безопасности, а архитектурное требование. Данные не должны покидать периметр компании ни при индексировании, ни при поиске, ни при генерации ответа. Облачные решения здесь принципиально не подходят.
Поэтому до того, как вопрос попадёт к модели, система выполняет три шага. Retrieve: семантический поиск по документам, который понимает смысл. Пользователь спрашивает «есть ли у нас с этим поставщиком эксклюзивный договор?» — система находит нужный раздел, даже если в тексте написано «единственный уполномоченный дистрибьютор». Параллельно работает точный поиск — для кодов, артикулов, чисел. RRF (Reciprocal Rank Fusion): математический алгоритм слияния двух списков результатов, встроенный в Qdrant (высокопроизводительная векторная база данных с открытым исходным кодом). Rerank: финальная проверка — cross-encoder оценивает каждый фрагмент в паре с исходным вопросом и отвечает: «содержит ли именно этот текст ответ именно на этот вопрос?»
Модель получает не весь архив, а уже отфильтрованный и проверенный контекст. Поиск по смыслу — до генерации, а не вместо неё.
Почему не LangChain — и при чём здесь observability
LangChain — хороший инструмент для прототипа RAG-системы. В production в регулируемой среде появляются две проблемы. Первая: нет нативного управления состоянием. Когда нужно описать «если rerank-скор ниже порога — переформулируй запрос и повтори поиск», в LangChain это строится через обходные конструкции. В LangGraph это один узел графа с явным переходом — и когда что-то падает в три часа ночи, видно сразу в каком.
Вторая проблема — observability. В первый месяц система работает хорошо. Потом обновляются документы, меняется структура запросов — качество ответов незаметно деградирует. Без трейсинга об этом узнают только когда пользователи жалуются. Langfuse (self-hosted) оставляет полный след каждого запроса: найденные фрагменты, rerank-скоры, latency по этапам. Важно: Langfuse тоже локальный — иначе фрагменты корпоративных документов уходят в чужой SaaS.
По шагам: от документа до ответа
Docling (библиотека структурного разбора документов) выступает препроцессором: он нормализует качество скана перед тем, как передать его в мультимодальную модель. Это важный нюанс — Qwen2.5-VL (мультимодальная языковая модель от Alibaba) корректно воспринимает скан только от 300 DPI. Docling приводит входящий файл к нужному качеству, разбирает layout и выделяет таблицы, после чего Qwen2.5-VL читает то, что нельзя распознать обычным OCR: рукописные пометки, изображения с маркировкой, таблицы со сложной сеткой. Всё локально.
BAAI/bge-m3 (multilingual embedding-модель от Beijing Academy of AI) используется на двух этапах. При индексировании — она преобразует каждый чанк документа в два вектора сразу: dense (семантический) и sparse (точные совпадения). При запросе — та же самая модель переводит вопрос пользователя в векторы того же пространства. Именно поэтому сравнение запроса с базой корректно: один и тот же «язык» у документов и у вопроса.
Qdrant хранит оба типа векторов и выполняет гибридный поиск — dense и sparse в одном запросе. Встроенный RRF сливает два списка результатов в один без дополнительного обучения и без ручной настройки весов.
Rerank работает в два этапа. FastEmbed (легковесная embedding-библиотека от команды Qdrant) быстро срезает список до 10 лучших за 30–50 мс. Затем bge-reranker-v2-m3 — self-hosted cross-encoder — точно оценивает каждый фрагмент в паре с вопросом пользователя. У self-hosted reranker есть один честный минус: он добавляет задержку в 150–400 мс на запрос. Если данные не относятся к чувствительной категории и могут покидать периметр, есть альтернатива — облачный Voyage AI rerank-2.5: он быстрее и точнее, но данные уходят во внешний API. Это осознанный архитектурный выбор между latency и data sovereignty.
Qwen2.5-72B-Instruct в AWQ INT4-квантизации (формат сжатия весов, уменьшающий потребление памяти вдвое при минимальной потере качества) — это флагманский вариант с максимальным качеством ответов. Он помещается на два A100 80GB, двуязычный и хорошо работает с табличными данными. Но два A100 — это дорогая инфраструктура, и для многих компаний она избыточна на старте. Более доступная альтернатива — одна видеокарта L40S 48GB: она дешевле примерно втрое и тянет Qwen2.5-32B-Instruct в той же квантизации. По качеству это около 90% от 72B-версии — на большинстве реальных задач разница незаметна. Если инфраструктура совсем ограничена, Qwen2.5-14B-Instruct запускается даже на потребительской RTX 4090, хотя здесь уже чувствуется просадка на сложных многошаговых запросах. Практический совет: начинать стоит с 32B на одной L40S, смотреть на качество ответов на реальных данных — и только если это не устраивает, масштабироваться.
Отдельно стоит сказать про связку Haystack и LangGraph, потому что на первый взгляд неясно, зачем оба. Если объяснять просто: LangGraph — это диспетчер в момент живого запроса. Пришёл вопрос от пользователя — LangGraph решает, куда его отправить, нужно ли искать ещё раз, если первый результат оказался нерелевантным, и что ответить, если данных недостаточно. Это логика в режиме реального времени.
Haystack — это стенд для проверки качества до того, как система вообще уйдёт в production. Представьте: вы поменяли способ нарезки документов на чанки. Стало лучше или хуже? Без инструмента оценки вы не знаете — просто деплоите и надеетесь. Haystack позволяет запустить тест на контрольном наборе вопросов и получить конкретные цифры: насколько часто система находит правильный документ в топ-5 результатов, насколько ответ соответствует тому, что реально написано в источнике. Это не про красивые графики — это про уверенность, что изменение помогло, а не навредило.
Почему не LlamaIndex? Он отлично подходит для быстрого прототипа и гибких стратегий индексирования. Но когда система работает в серьёзной среде — банке или юридической фирме — и каждое изменение пайплайна нужно обосновать измеримым результатом, глубина встроенных eval-инструментов Haystack оказывается принципиальной. LlamaIndex здесь проигрывает не по качеству, а по специализации.
Итог: система для поиска по корпоративным документам отвечает за секунды, указывает конкретный документ и страницу, явно говорит «данных недостаточно» вместо уверенной галлюцинации. Данные не покидают периметр — ни при индексировании, ни при запросе, ни при генерации.
ссылка на оригинал статьи https://habr.com/ru/articles/1024696/