web24.team

Как создать эффективную RAG-систему: архитектура и разработка

Пошаговая архитектура RAG-системы простым языком: подготовка данных и Markdown, сегментация, гибридный поиск, ранжирование, промпты и контроль контекста — с примерами для медицинской базы вопрос-ответ и каталога товаров.

RAG (Retrieval-Augmented Generation) — это когда модель отвечает не «из головы», а сначала находит релевантные куски ваших документов и подставляет их в контекст. Идея простая, но создание RAG-системы, которая действительно отвечает точно, а не гладко врёт с уверенным видом, — это не одна векторная база, а связка из шести компонентов. Ниже — вся архитектура по шагам, простым языком, с примерами для двух типичных задач: медицинской базы вопрос-ответ для врачей и каталога товаров.

1. Подготовка данных: LLM любят Markdown

Первый и самый недооценённый шаг в разработке RAG-систем — то, в каком формате лежат исходные данные. LLM обучены на гигантском количестве размеченного текста, и Markdown — один из самых частых форматов в этой выборке: модели «привыкли» к #-заголовкам, спискам и таблицам и заметно лучше понимают границы смысловых блоков в них, чем в сыром HTML с десятками <div> или в тексте, вытащенном из PDF без разметки.

Практическое следствие: прежде чем строить поиск, приведите документы к чистому Markdown.

Плохо (вытащено из PDF как есть):

Парацетамол Показания: лихорадка боль слабой и средней интенсивности Дозирование
взрослым 500-1000 мг каждые 4-6 часов не более 4 г в сутки Противопоказания
тяжелая печеночная недостаточность

Хорошо:

## Парацетамол

### Показания
Лихорадка, боль слабой и средней интенсивности.

### Дозирование (взрослые)
500–1000 мг каждые 4–6 часов, не более 4 г в сутки.

### Противопоказания
Тяжёлая печёночная недостаточность.

Второй вариант — это не только «красивее». Заголовки ### дают модели готовые границы для сегментации, а таблицы Markdown (| Препарат | Доза | Кратность |) эмбеддинги и LLM разбирают на структурированные пары ключ-значение почти без ошибок, в отличие от той же таблицы, слитой в один абзац.

Для карточки товара тот же принцип: название, характеристики и наличие — отдельными заголовками или Markdown-таблицей, а не одним маркетинговым абзацем текста.

2. Правильная сегментация (чанкинг)

Сегментация — это разбиение документов на чанки, которые попадут в векторную базу. Частая ошибка на старте разработки RAG-систем — резать текст по фиксированному числу символов (например, каждые 500 символов), не глядя на структуру. В результате в один чанк попадает конец одного раздела и начало следующего, а модель получает на входе смысловой мусор.

Правило проще, чем кажется: чанк = одна законченная мысль, а границей служит структура документа — заголовок, пункт списка, строка таблицы.

  • Медицинская база вопрос-ответ: один чанк = один вопрос с полным ответом, а не «половина ответа влезла, половина обрезалась». Если ответ длинный (например, схема лечения по шагам), не разрезайте пошаговый список между чанками — он должен либо помещаться целиком, либо иметь чанк-заголовок с кратким резюме и ссылкой на полный текст.
  • Каталог товаров: один чанк = одна карточка товара (или одна её секция — например, отдельно характеристики и отдельно комплектация для громоздких карточек оборудования). Никогда не смешивайте две разные модели в одном чанке — при поиске «максимальная нагрузка на ось» система не должна путать характеристики двух разных погрузчиков.

Ориентир по размеру: 200–500 токенов на чанк для плотного технического текста (медицина, характеристики оборудования) и до 800 для описательного текста. Слишком мелкие чанки теряют контекст, слишком крупные — размывают релевантность поиска.

3. Гибридный поиск

Чистый векторный поиск ищет по смыслу — и именно поэтому он плохо справляется с точными строками: артикулами, кодами МКБ-10, номерами партий, аббревиатурами. Эмбеддинг «видит» МКБ-10 J18.9 и воспаление лёгких неуточнённое как близкие по смыслу фразы, но если пользователь ищет ровно код J18.9, векторный поиск не гарантирует, что нужный документ окажется в топе.

Решение — гибридный поиск: результаты классического полнотекстового поиска (BM25 или обычный keyword-индекс) и векторного поиска объединяются, чаще всего через Reciprocal Rank Fusion (RRF):

def reciprocal_rank_fusion(vector_results, keyword_results, k=60):
    scores = {}
    for rank, doc_id in enumerate(vector_results):
        scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1)
    for rank, doc_id in enumerate(keyword_results):
        scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1)
    return sorted(scores, key=scores.get, reverse=True)
  • Медицина: запрос «дозировка амоксициллина детям» должен находить документ и по смыслу («антибиотик для ребёнка»), и по точному термину «амоксициллин» — гибридная схема ловит оба случая, чистый vector search иногда промахивается мимо конкретного действующего вещества.
  • Каталог товаров: запрос по артикулу SKU-48120 или модели DL-500X — это ровно тот случай, где keyword-поиск обязателен: у случайного набора букв и цифр нет «смысла», который поймает эмбеддинг.

4. Ранжирование результатов

Гибридный поиск отдаёт достаточно широкий список кандидатов (обычно top-20–50) — но не все из них одинаково релевантны, а в контекст модели можно передать реально 3–8 чанков (иначе контекст «размывается», см. следующий пункт). Здесь нужен reranker — отдельная модель (часто cross-encoder, например bge-reranker или Cohere Rerank), которая умеет точно сравнивать пару «вопрос — чанк», а не полагается на приблизительное косинусное сходство векторов, посчитанное заранее.

Разница на примере: на запрос «можно ли беременным ибупрофен» векторный поиск может поднять в топ общий документ «Нестероидные противовоспалительные препараты: обзор» просто потому, что там много релевантных слов, тогда как более узкий документ «Ибупрофен: противопоказания» с точным ответом окажется на 8-м месте. Reranker, оценивающий пары напрямую, обычно ставит его на первое.

Практическая схема: гибридный поиск возвращает 30 кандидатов → reranker пересчитывает релевантность → в модель уходят top-5.

5. Настройка промптов

Даже с идеальным поиском модель может проигнорировать найденный контекст и ответить «из головы» — если явно не запретить. Системный промпт для RAG должен жёстко фиксировать три вещи: откуда брать ответ, что делать при нехватке данных и как оформлять ссылку на источник.

Отвечай ТОЛЬКО на основе текста ниже в блоке «Контекст».
Если ответа в контексте нет — так и скажи: «В базе знаний нет
информации по этому вопросу», не придумывай ответ.
В конце ответа укажи источник в формате [Источник: <название документа>].

Контекст:
{context}

Вопрос: {question}

Для медицинской тематики это не опция, а обязательное требование — врач должен видеть, из какого протокола взят ответ, и модель обязана честно признавать пробелы, а не выдавать правдоподобную, но неверную дозировку.

6. Контроль и очистка контекста

Последний шаг — гигиена того, что реально попадёт в промпт модели. Три частые проблемы и как их лечить:

  • Дубликаты. Один и тот же факт может лежать в трёх разных документах (старая и новая версия протокола, например) — если в контекст попадут все три, модель либо путается в противоречиях, либо просто тратит токены впустую. Дедуплицируйте по смысловому сходству перед отправкой в промпт.
  • Устаревшие данные. Для каталога товаров это особенно критично: если в векторной базе остался чанк с ценой или наличием месячной давности, RAG уверенно озвучит неверную цену. Синхронизируйте индекс с источником данных (PIM/CMS/1C) при каждом изменении, а не раз в неделю по расписанию.
  • «Шумные» чанки не по теме. Даже после ранжирования иногда проскакивает чанк, который формально прошёл порог релевантности, но не отвечает на вопрос. Добавьте порог отсечения (score threshold) — если top-1 после reranking ниже порога, честно верните «ответ не найден», а не притягивайте за уши слабый результат.

Что дальше

Шесть шагов выше — это общий каркас, который работает для любой RAG-системы. Дальше начинаются нюансы, специфичные для домена:

  • Если строите RAG над узкоспециализированными данными (например, медициной) и вам важна проверяемость ответов — читайте «Валидация и Self-RAG: как проверить качество RAG-системы»: там про специфичные эмбеддинги, Self-RAG и то, как сделать так, чтобы система понимала структуру документа целиком, а не только вырванный чанк.
  • Если строите поиск по каталогу товаров или оборудования — в статье «RAG для каталога товаров: продукты и оборудование» разобраны особенности сегментации карточек, гибридного поиска по артикулам и ранжирования с учётом цены и наличия.
  • А если задача шире — сделать так, чтобы вас вообще видели LLM и answer-engines в поиске, — это уже соседняя тема, разобранная в GEO-чек-листе: тот же принцип «LLM любят Markdown» работает и там.

Коротко

Как сделать RAG систему, которая не выдумывает ответы?

Три вещи вместе: гибридный поиск с ранжированием, чтобы в контекст попадали действительно релевантные чанки; промпт с явным разрешением ответить «не знаю»; и валидация ответов на этапе тестирования.

Чем архитектура RAG-системы отличается от «просто добавить векторный поиск»?

Векторный поиск — один из шести компонентов: важны ещё подготовка данных, сегментация, гибридный поиск, ранжирование, промпты и контроль контекста. Слабое звено в любом из них портит итоговые ответы.

С чего начать разработку RAG-системы: с модели или с данных?

С данных. Модель и эмбеддинги можно поменять за час, а плохо подготовленный корпус документов придётся переразмечать вручную.

Нужен ли гибридный поиск, если эмбеддинги и так хорошие?

Да — даже сильные эмбеддинги хуже находят точные артикулы, коды и аббревиатуры, чем обычный полнотекстовый поиск.

Если нужно построить RAG-систему под конкретные данные — пишите нам через форму на сайте, поможем с архитектурой и разработкой.