Содержание
- Что такое RAG и зачем он бизнесу
- Архитектура промышленной RAG-системы
- Чанкинг: как нарезать документы
- Эмбеддинги и векторная база
- Ретривер и реранкер
- RAG, fine-tuning или длинный контекст
- Приватность и хранение данных в РФ
- Оценка качества: как понять, что система работает
- RAG и ИИ-агенты
- Типичные грабли
- Как внедрять
- FAQ
Запрос звучит примерно так: «у нас 1000+ внутренних документов — договоры, регламенты, техническая документация, переписка поддержки, — и мы хотим, чтобы по ним можно было задавать вопросы человеческим языком и получать ответы со ссылкой на источник». Дальше обычно следует уточнение, которое отделяет тех, кто разбирался в теме, от тех, кто наслушался про «ИИ, который заменит отдел поддержки»: можно ли это сделать так, чтобы корпоративные данные не уходили на чужие серверы, и так, чтобы система не выдумывала.
Ответ на оба вопроса — RAG. Эта статья — практический разбор того, как устроена полноценная retrieval-augmented generation система на корпоративных данных: из каких компонентов она состоит, где чаще всего ломается, когда RAG лучше дообучения модели, и что меняется, если данные нельзя выпускать за пределы российского контура. Мы в Новакоме строим такие системы на Java/Kotlin-стеке, поэтому смотрим на RAG не как на демку, а как на инженерную задачу с эксплуатацией в продакшене.
Что такое RAG и зачем он бизнесу
RAG — это не новая модель и не дообучение, а архитектура. Хорошая аналогия: обычная LLM — студент на экзамене с закрытой книгой, отвечает только по памяти. RAG превращает экзамен в открытый: перед тем как ответить, модель сначала достаёт релевантные фрагменты из вашей библиотеки данных и отвечает уже по ним. Технически приём простой — перед каждым вызовом LLM мы извлекаем из внешнего источника куски текста, релевантные запросу, и подставляем их в промпт вместе с вопросом пользователя. Модель получает не «всё, что она когда-то выучила», а конкретные факты из ваших документов.
Зачем это enterprise:
- Работа с приватными данными без дообучения. LLM ничего не знает про ваши внутренние регламенты, спецификации продукта и историю тикетов — этих данных не было в обучении. RAG позволяет «рассказать нейронке о ваших данных» без дорогого тюнинга: вы просто подключаете базу знаний, и та же модель начинает отвечать на вопросы про режим
A112/PP_INPUTиз вашей внутренней документации. - Снижение галлюцинаций. LLM сама по себе — не машина истины. Как формулируют исследователи: модель не строит внутреннюю картину мира, она про вероятность следующего слова и про то, что написано в тексте. Если не дать ей фактуру, она правдоподобно её придумает. RAG привязывает ответ к конкретным извлечённым фрагментам и убирает шум: вместо того чтобы искать иголку в стоге сена из 2000 страниц, модель получает только пять релевантных фрагментов — «убрали стог, оставили иголки».
- Актуальность без переобучения. Если завтра поменялся внутренний регламент, дообученная модель мгновенно устаревает — её надо тюнить заново. В RAG достаточно обновить документ в базе знаний, и следующий же ответ будет учитывать новую версию.
- Прозрачность. Хорошая RAG-система отдаёт не только ответ, но и ссылки на источники — какие именно фрагменты документов легли в основу. Для enterprise это критично: ответ без traceable-ссылки в юридическом, финансовом или техническом контексте бесполезен.
Типовые сценарии — внутренний помощник по базе знаний, бот поддержки по документации продукта, ассистент для отдела продаж по годовым отчётам и спецификациям, поиск по архиву договоров. Объединяет их одно: ценность не в модели, а в данных, которые модели подсунули.
Архитектура промышленной RAG-системы
Здесь начинается главное расхождение между демкой и продом. Демку «загрузить PDF и поболтать с ним» собирают за вечер. Промышленная RAG-система — это тяжёлая инфраструктура с большим числом подвижных частей, и каждая из них — место, где всё может сломаться.
Полный конвейер делится на два потока: индексация (офлайн, готовим данные) и запрос (онлайн, отвечаем пользователю).
ИНДЕКСАЦИЯ (офлайн)
документы (PDF/DOCX/HTML/таблицы)
│ извлечение текста, OCR для сканов
▼
очистка и нормализация
│
▼
чанкинг (нарезка на фрагменты + метаданные)
│
▼
эмбеддинг-модель → векторы
│
▼
векторная БД (индекс + метаданные)
ЗАПРОС (онлайн)
вопрос пользователя
│ эмбеддинг запроса
▼
ретривер: векторный + lexical поиск (top-k)
│
▼
реранкер: пересортировать кандидатов (top-n)
│
▼
сборка augmented-промпта: инструкция + контекст + вопрос
│
▼
LLM-генератор → ответ + ссылки на источники
│
▼
оценка качества / трассировка
Важная отрезвляющая цифра из практики: 95–97% кода RAG-решения вообще не связаны с LLM. Они про вашу предметную область и инженерию — извлечение текста из кривых PDF, актуализацию документов, метаданные, фильтрацию, обработку контекста диалога. Вызов модели — это последняя и самая простая строчка. Поэтому к RAG надо относиться как к обычному data-engineering-проекту, а не как к «прикрутить ChatGPT».
Разберём ключевые узлы.
Чанкинг: как нарезать документы
Чанкинг — нарезка исходных документов на фрагменты, которые потом векторизуются и извлекаются. Звучит тривиально, но на практике это «целое искусство»: как разрезать договор или внутреннее положение, чтобы фрагмент сохранял смысл и при этом не тащил лишнего.
Базовые стратегии:
| Стратегия | Как работает | Когда подходит |
|---|---|---|
| Фиксированный размер | Режем по N токенов | Однородный текст, быстрый старт |
| Скользящее окно (overlap) | Фрагменты с перекрытием | Чтобы не терять смысл на стыках |
| Рекурсивная | По структуре: разделы → абзацы → предложения | Структурированные регламенты, документация |
| По смыслу (semantic) | Границы там, где меняется тема | Разнородные документы, выше качество |
| Контекстный | К фрагменту дописывают краткое описание его места в документе | Когда важна точность извлечения |
Главная ловушка чанкинга — потеря контекста. Фрагмент «срок действия — 12 месяцев» бесполезен, если из него вырезали, о каком договоре и пункте речь. Поэтому к каждому чанку прикрепляют метаданные: документ-источник, раздел, дата, версия, теги. Метаданные потом работают как пре-фильтр на этапе поиска — это резко повышает релевантность.
Отдельная боль — извлечение текста из исходников. Не все PDF одинаково устроены: одна библиотека парсит одни документы, другая — другие. Если PDF — это скан, нужен OCR, а если внутри ещё и таблицы, OCR начинает страшно врать. Эта неблагодарная работа по извлечению и очистке съедает заметную часть бюджета любого реального проекта, и закладывать её надо заранее.
Эмбеддинги и векторная база
Эмбеддинг — это перевод фрагмента текста в вектор, длинный набор чисел. Идея в том, что близкие по смыслу тексты дают близкие векторы, и тогда «поиск по смыслу» сводится к поиску ближайших векторов. Запрос пользователя тоже превращается в вектор, и движок ищет чанки, чьи векторы ближе всего к вектору запроса, — это и есть семантический поиск.
Где это ломается на спецтерминах. Запрос вроде «расскажи про режим A112/PP_INPUT» для эмбеддера распадается на десятки токенов, и технический термин получает в векторе такой же вес, как служебные слова «расскажи» и «про». В результате возвращаются случайные чанки, и ответа нет. Лечится это пре-фильтрацией по метаданным до векторного поиска, гибридным поиском (векторный + классический лексический BM25) или кастомными эмбеддингами под доменную терминологию — последнее трудозатратно, но иногда без него никак.
Выбор векторной базы зависит от масштаба, требований к развёртыванию и того, что у вас уже есть:
| База | Тип | Когда выбирать |
|---|---|---|
| Qdrant | Отдельная векторная БД (Rust) | Self-hosted, контроль, фильтрация по метаданным, РФ-контур |
| pgvector | Расширение PostgreSQL | Уже есть Postgres, умеренные объёмы, не плодить инфраструктуру |
| Elasticsearch / OpenSearch | Поисковый движок с векторами | Нужен гибридный поиск из коробки, уже используется в стеке |
| FAISS | Библиотека (Meta) | Эмбеддед-сценарии, прототипы, полный контроль над индексом |
| Milvus | Распределённая векторная БД | Очень большие объёмы, горизонтальное масштабирование |
Практическое правило: не тащите отдельную векторную БД, если у вас уже есть PostgreSQL и объёмы умеренные — pgvector закроет задачу без новой инфраструктуры. Когда нужны строгая фильтрация по метаданным, высокая нагрузка и self-hosted-развёртывание в собственном контуре — берите специализированное решение вроде Qdrant. Технология сама по себе не так важна, как любят спорить «вектора против knowledge maps»: важно только, выдаёт ли система в итоге правильные ответы или несёт пургу. И это можно измерить — об оценке ниже.
Ретривер и реранкер
Ретривер достаёт из базы top-k кандидатов по запросу. Здесь прячется самая коварная точка отказа всей системы — её называют silent failure, тихий отказ: правильный ответ есть в данных, но ретривер вернул не те фрагменты, и LLM его просто не увидела. Пользователь получает уверенный, но неполный или неверный ответ — и не догадывается, что система промахнулась на этапе поиска.
Чтобы снизить риск, поверх ретривера ставят реранкер — отдельную модель, которая пересортировывает кандидатов по реальной релевантности запросу. Логика двухступенчатая: ретривер быстро и грубо достаёт, скажем, 50 кандидатов (важна полнота), а реранкер аккуратно и дорого переупорядочивает их и оставляет лучшие 5 (важна точность). Это заметно поднимает качество, потому что чистый векторный поиск вероятностный и регулярно ошибается «по множеству причин».
Дальше из top-n фрагментов собирается augmented-промпт: системная инструкция («ты ассистент, отвечай только по предоставленному контексту, если ответа нет — так и скажи»), извлечённый контекст и сам вопрос. Инструкция про «отвечай только по контексту» — не косметика: это один из главных рычагов против галлюцинаций. Если в контексте ответа нет, модель должна честно сказать «не нашёл», а не сочинять.
Псевдокод запросной части на Kotlin показывает, насколько тонкий слой занимает собственно LLM:
fun answer(question: String): RagResponse {
val queryVector = embedder.embed(question)
// 1. Ретривер: широкий, но грубый отбор
val candidates = vectorStore.search(
vector = queryVector,
topK = 50,
filter = MetadataFilter(actualOnly = true) // пре-фильтр по метаданным
)
// 2. Реранкер: точная пересортировка, оставляем лучшее
val context = reranker.rerank(question, candidates).take(5)
if (context.isEmpty()) {
return RagResponse(text = "В базе знаний нет данных по этому вопросу.")
}
// 3. Сборка augmented-промпта
val prompt = buildPrompt(
instruction = "Отвечай строго по контексту. Если ответа нет — скажи об этом.",
context = context,
question = question
)
// 4. Генерация + ссылки на источники
val completion = llm.complete(prompt)
return RagResponse(text = completion, sources = context.map { it.source })
}
RAG, fine-tuning или длинный контекст
Частый вопрос на старте: а нужен ли вообще RAG — может, дообучить модель или просто закинуть всё в длинный контекст? Это три разных инструмента под разные задачи.
Fine-tuning (дообучение) меняет поведение и стиль модели, «вшивает» знания в веса. Минусы для базы знаний: дорого, медленно, и обновлять в реальном времени нельзя — поменялся регламент, и дообученная модель мгновенно устарела. Fine-tuning уместен, когда нужно задать модели формат, тон, доменный язык или узкий навык, — но не как способ держать актуальные факты.
Длинный контекст (модели на 100k–1M+ токенов) — соблазнительная альтернатива: убираем векторную БД, эмбеддинги и логику извлечения, просто отдаём документы модели целиком. У этого подхода есть честные плюсы — нет ретривера, значит нет и тихих отказов, модель «видит всё». Но есть три проблемы. Первая: на больших объёмах внимание модели размывается — вопрос про абзац в середине 2000-страничного документа она часто проваливает. Вторая: это дорого и медленно на каждый запрос. Третья: документы могут просто не влезть, а держать в контексте всю корпоративную базу из тысяч документов невозможно в принципе.
Грубое правило выбора:
| Задача | Инструмент |
|---|---|
| Отвечать по большой, часто меняющейся базе документов | RAG |
| Задать формат, тон, доменный навык | Fine-tuning |
| Глубоко проанализировать один-несколько документов за раз | Длинный контекст |
| Максимальное качество на сложном домене | RAG + fine-tuning эмбеддера/реранкера |
На практике для корпоративной базы знаний почти всегда побеждает RAG, иногда в связке с лёгким дообучением эмбеддинг-модели под доменную терминологию. Длинный контекст хорош как дополнение — например, когда ретривер достал нужный документ и его целиком отдают модели для детального разбора. Подробнее про экономику и границы применимости моделей мы писали в разборе где ИИ реально пишет код, а где нужна заказная разработка.
Приватность и хранение данных в РФ
Для российского enterprise это часто решающий фактор. Целые отрасли — фарма, банки, юристы — в RAG «ни ногой», пока не обеспечена приватность: медицинские документы пациентов или финансовые данные просто нельзя передавать «туда», на внешние серверы облачных LLM. Запрос «можно ли послать данные от работодателя во внешнюю модель» в корпоративных каналах звучит постоянно, и честный ответ — без отдельной обвязки нельзя.
Есть два подхода, часто комбинируемых:
- Локальные модели в собственном контуре. Эмбеддер, векторная БД и сама LLM разворачиваются внутри периметра. Данные не покидают инфраструктуру вообще. Это снимает большинство вопросов 152-ФЗ и отраслевых требований, но требует железа (GPU) и компетенций по эксплуатации. Выбор между локальной моделью и облачным API — отдельная развилка со своей экономикой, мы разбирали её в материале локальная LLM против облачного API для российского бизнеса.
- Анонимизация на лету. Между формированием запроса и отправкой в LLM ставится промежуточный слой, который кодирует персональные данные (имена, финансы, идентификаторы) перед отправкой и декодирует обратно в ответе. Здесь важна не только буква 152-ФЗ, но и приказ, описывающий, как именно анонимизировать каждый тип персональных данных, — причём для обычных и финансовых датасетов правила различаются. Существуют готовые библиотеки с таким промежуточным слоем именно под RAG-системы.
Для импортозамещаемого контура локальные модели плюс self-hosted векторная БД — естественный выбор: ничего не зависит от зарубежного провайдера как от единой точки отказа, а хранение данных остаётся под контролем. Как это укладывается в общую стратегию перехода, мы описывали в гайде по импортозамещению ПО в 2026.
Оценка качества: как понять, что система работает
Самая недооценённая часть RAG-проекта. От демки идёт мгновенный вау-эффект, но при детальной проработке он быстро улетучивается, и без измеримых метрик вы не отличите «работает» от «правдоподобно врёт». Оценка должна быть встроена в проект с самого начала, а не прикручена в конце.
Качество измеряют на двух уровнях:
- Качество извлечения (retrieval). Метрики вроде recall@k и precision@k: попал ли нужный фрагмент в top-k, сколько мусора в выдаче. Это диагностика ретривера и реранкера — большинство провалов RAG живут именно здесь, в тихих отказах.
- Качество ответа (generation). Насколько ответ опирается на контекст (faithfulness, нет ли галлюцинаций), отвечает ли он на вопрос по существу (relevance), есть ли корректные ссылки на источники.
Практический подход — собрать золотой набор из реальных вопросов с эталонными ответами и фрагментами-источниками и прогонять систему по нему при каждом изменении. Так устроены, например, открытые Enterprise RAG Challenge, где участники строят ассистентов по годовым отчётам и сравниваются по каноничным ответам: технологии не важны, важно, работает система или несёт пургу, и это объективно измеримо. Без такого регрессионного набора любая «доработка» — это правки вслепую: поправили чанкинг для одних вопросов, сломали для других, и заметили это только от пользователей. Современный подход — ещё и LLM-as-a-judge: отдельная модель оценивает ответы по заданным критериям, что позволяет гонять оценку часто и дёшево.
RAG и ИИ-агенты
RAG и ИИ-агенты — естественное продолжение друг друга. Базовый RAG — это один проход: вопрос → извлечение → ответ. Но если простой вопрос-ответ результата не дал, можно действовать «умно»: агент сам переформулирует запрос, лезет в дополнительные источники, уточняет у пользователя, делает несколько итераций поиска, пока не наберёт достаточно фактуры. Это уже agentic RAG — ретривер становится инструментом в руках агента, а не финальным звеном пайплайна.
Здесь нужны два предостережения из практики. Первое — экономика: агентный цикл с многократными вызовами LLM долго и дорого, и для открытых публичных чат-ботов он обычно не годится. Второе — безопасность: переход от изолированного чат-бота к агенту с доступом к корпоративным источникам и инструментам расширяет поверхность атаки. «Безопасная» для чата модель в агентном пайплайне может выполнить вредоносное действие через вызов инструмента, если ею манипулируют через подсунутый контекст (непрямая промпт-инъекция). Поэтому контроль происхождения данных, фильтрация и проверка в оркестраторе нужны не меньше, чем качество извлечения.
Типичные грабли
Список собран из реальных внедрений, а не из туториалов:
- Мусор на входе (shit in → shit out). Когда у компании 1000+ документов и в них куча неактуальных версий, RAG честно отдаёт неактуальные ответы. Возникает отдельная и недешёвая задача — поддержание базы в актуальном состоянии. Без неё качество поплывёт уже через пару месяцев.
- Плохой ретрив и тихие отказы. Ответ есть в базе, но ретривер его не нашёл. Лечится гибридным поиском, реранкером, пре-фильтром по метаданным и — обязательно — измерением recall@k.
- Спецтермины не embedded'ятся. Технические коды и артикулы теряются в векторном поиске. Нужны метаданные, лексический поиск или кастомные эмбеддинги.
- Контекстное окно. Результаты RAG не всегда влезают в промпт — приходится динамически резать, суммаризировать, жёстко обрезать. Плюс в диалоге надо управлять «памятью»: оставлять нужное, выкидывать лишнее до отправки в LLM.
- Маршрутизация и guardrails. Вопросы не по теме («а что ты думаешь о политике») надо отсекать и направлять, иначе бот ответит на что угодно.
- Недооценка объёма работы. Если идёте в прод, умножайте сложность и количество кода на 5–10 относительно демки. Напомним: подавляющая часть этого кода — про вашу предметную область и инженерию данных, а не про LLM.
Отдельно стоит честно сказать, кому RAG не нужен. Если домен простой и вопросов немного — справятся общедоступные сервисы, заказная разработка тут лишняя. RAG окупается там, где данных много, они сложные, специфичные и приватные, а цена ошибки высока.
Как внедрять
Рекомендуемая последовательность:
- Определить сценарий и цену ошибки. Внутренний помощник для сотрудников терпит больше ошибок, чем бот, отвечающий клиентам по договорам. От этого зависит вся строгость системы.
- Инвентаризация и очистка данных. Собрать источники, разобраться с форматами (PDF, сканы, таблицы), убрать неактуальное. Это самый недооценённый и самый объёмный этап.
- Собрать золотой набор для оценки. 50–200 реальных вопросов с эталонными ответами — до того, как писать пайплайн. Иначе измерять будет нечем.
- MVP-пайплайн. Базовый чанкинг, эмбеддер, векторная БД, ретривер, простой промпт. Прогнать по золотому набору, получить стартовые метрики.
- Итеративно улучшать узкие места. Реранкер, гибридный поиск, метаданные, контекстный чанкинг — добавлять то, что метрики покажут как слабое звено, а не всё подряд.
- Закрыть приватность и безопасность. Решить про локальные модели или анонимизацию, настроить guardrails, по необходимости — agentic-надстройку.
- Вывести в прод с трассировкой. Логировать запросы, извлечённые фрагменты и ответы — чтобы видеть тихие отказы и деградацию качества во времени.
Главный вывод: RAG — это не «прикрутить чат-бота к документам», а полноценный инженерный проект на стыке data engineering, поиска и LLM, где модель — наименьшая из забот. Делать его имеет смысл руками команды, которая понимает и пайплайны данных, и эксплуатацию в продакшене, и российские требования к данным.
FAQ
Чем RAG отличается от дообучения модели? RAG не меняет модель — он подставляет ей актуальные факты из вашей базы в момент запроса. Дообучение «вшивает» знания в веса: это дорого, медленно и устаревает при каждом изменении данных. Для актуальной базы знаний нужен RAG; дообучение уместно для формата, тона и доменного навыка.
Можно ли построить RAG так, чтобы данные не покидали наш контур? Да. Эмбеддер, векторная база и LLM разворачиваются локально в собственном периметре, данные не уходят наружу. Альтернатива или дополнение — слой анонимизации персональных данных перед отправкой в модель. Для фармы, банков и юристов это обычно обязательное условие.
Какую векторную базу выбрать?
Если уже есть PostgreSQL и объёмы умеренные — pgvector, чтобы не плодить инфраструктуру. Для строгой фильтрации по метаданным, нагрузки и self-hosted-контура — Qdrant или аналог. Для очень больших объёмов — распределённые решения вроде Milvus. Технология вторична — первично качество ответов, которое надо измерять.
Почему RAG всё равно иногда выдумывает? Чаще всего причина не в модели, а в извлечении: нужный фрагмент не попал в контекст (тихий отказ), и модель ответила «по памяти». Лечится реранкером, гибридным поиском, метаданными и жёсткой инструкцией «отвечай только по контексту, иначе скажи, что не нашёл». Плюс измерение recall@k.
Сколько это стоит и сколько занимает? Демка — вечер, прод — другой порядок: сложность и объём кода больше в 5–10 раз, и 95% работы — про данные и предметную область, а не про LLM. Реалистичный срок промышленного MVP с оценкой качества — недели, а не дни, и дальше система требует постоянного поддержания актуальности базы.
Если вы планируете базу знаний на векторном поиске или ассистента по корпоративным данным, мы в Новакоме проектируем и внедряем RAG-системы на Java/Kotlin — от инженерии данных и выбора векторной БД до локальных моделей в вашем контуре и оценки качества. Посмотрите наши услуги по разработке с ИИ и заказной разработке ПО или напишите нам с описанием вашей задачи и требований к данным.