RAG: Retrieval-Augmented Generation как инженерная система
Поиск → контекст → генерация. Как LLM отвечает на основе документов
Когда говорят, что LLM "знает всё", это удобная, но опасная метафора. На самом деле модель ничего не знает в момент ответа – она лишь продолжает последовательность токенов, опираясь на статистические зависимости, выученные при обучении. Именно поэтому в реальных продуктах почти всегда возникает вопрос: как заставить модель отвечать на основе конкретных, актуальных, контролируемых данных?
Ответом на этот вопрос стала архитектура RAG – Retrieval-Augmented Generation. Это не фича и не трюк с промптом, а полноценная инженерная система, в которой LLM – лишь последний этап пайплайна.
В этой главе мы разберём RAG как систему из трёх связанных фаз:
поиск → формирование контекста → генерация,и посмотрим, где здесь математика, где инфраструктура, а где иллюзии.
Зачем вообще нужен RAG
Представим простую задачу: у вас есть база документов – инструкции, договоры, статьи, тикеты поддержки. Пользователь задаёт вопрос, и вы хотите получить:
ответ, основанный строго на этих документах
с указанием терминологии именно из базы
без галлюцинаций
с возможностью обновлять данные без переобучения модели
Чистая LLM здесь бесполезна. Она может выглядеть убедительно, но:
она не знает ваших документов
она не знает, что обновилось вчера"
она не отличает "нет информации" от "попробую догадаться"
RAG решает это, разделяя ответственность:
поиск отвечает за факты
LLM отвечает за формулировку.
Общая схема RAG
В самом общем виде RAG выглядит так:
[IMAGE: DIAGRAM_RAG_PIPELINE]
Промпт для картинки:
“Clean technical diagram of Retrieval-Augmented Generation pipeline: User Query → Embedding → Vector Search → Top-K Documents → Context Assembly → LLM Generation → Final Answer. Minimalistic style, white background, thin arrows, readable labels.”
Формально это можно записать так:
Пусть:
q – пользовательский запрос
D=d1,d2,…,dn – корпус документов
E(⋅) – функция эмбеддингов
sim(a,b) – мера близости (обычно cosine similarity).
Тогда RAG – это композиция функций:
Retrieval: r(q)=argmaxksim(E(q),E(di))
Context construction: C=concat(di1,di2,…,dik)
Generation: answer=LLM(q,C)
Важно: LLM не видит весь корпус, она видит только контекст C, который мы ей дали.
Retrieval: поиск как векторная задача
Почему не keyword-поиск
Классический поиск по словам (LIKE, TF-IDF, BM25) ищет совпадения токенов. RAG же опирается на семантическую близость.
Фразы:
"расторгнуть договор"
"прекращение действия контракта"
почти не имеют общих слов, но смысл у них один. Эмбеддинги позволяют это уловить.
Эмбеддинги и пространство
Эмбеддинг – это отображение текста в вектор:
Обычно d = 384, 768, 1024 или 1536.
Размерность эмбеддинга определяется архитектурой трансформера: она кратна числу attention heads и отражает компромисс между выразительностью и вычислительной стоимостью.
В трансформере:
Где:
h – число attention heads
dhead – размерность одного head
Типичные конфигурации:
12 × 64 = 768
16 × 64 = 1024
24 × 64 = 1536
Это нужно для:
эффективного параллелизма
равномерного разделения признаков
оптимизации под GPU/CPU SIMD
Интуитивно:
близкие по смыслу тексты → близкие векторы
дальние по смыслу → дальние векторы.
Чаще всего используется косинусная близость:
Значение в диапазоне [-1, 1], но на практике – от 0 до 1.
[IMAGE: VECTOR_SPACE]
Промпт для картинки:
“2D visualization of vector space with clustered text embeddings. Query vector highlighted, nearest document vectors connected with dashed lines. Simple, educational style.”
Chunking: незаметная, но критическая часть
Документы редко кладут в векторную базу целиком. Их режут на чанки.
Почему?
эмбеддинг длинного текста усредняет смыслы
retrieval начинает возвращать "всё понемногу"
контекст становится шумным.
Типичные стратегии:
300–500 токенов
overlap 10–20%
логические границы (абзацы, заголовки).
Формально мы ищем не документы, а чанки:
Именно они участвуют в argmax (argument of the maximum).
Context building: инженерия промпта
Получив Top-K чанков, мы должны превратить их в контекст.
Это не просто склейка текста. Здесь решаются вопросы:
порядок (по релевантности или по источнику)
формат (plain text, bullets, JSON)
инструкции для модели.
Пример шаблона:
"Ты отвечаешь строго на основе контекста ниже. Если ответа нет – скажи, что информации недостаточно".
Контекст:
{{chunk_1}}
{{chunk_2}}
Вопрос: {{query}}”
Здесь RAG превращается в контролируемую систему, а не в “умного болтуна”.
Generation: что на самом деле делает LLM
LLM в RAG:
не ищет информацию
не проверяет факты
не знает, что было вне контекста
Она решает задачу:
То есть переформулирует найденное.
Если retrieval плохой – генерация не спасёт.
Если контекст шумный – ответ будет мутным.
Отсюда важный инженерный принцип:
В RAG качество ответа определяется retrieval-ом, а не моделью.
Минимальный RAG на PHP (упрощённо)
Рассмотрим упрощённый пример без внешней векторной БД.
Хранение эмбеддингов
Косинусная близость
Поиск Top-K
Контекст
Дальше этот контекст отправляется в LLM API.
Типовые ошибки RAG
Ниже приведены типичные ошибки для RAG:
слишком большие чанки
слишком маленький Top-K
отсутствие инструкции "не выдумывай"
надежда, что "более умная модель всё исправит".
RAG – это не магия, а баланс сигнал/шум.
RAG как архитектурный паттерн
Важно понимать: RAG – это не только QA.
Это базовый паттерн для:
корпоративных ассистентов
аналитических систем
поиска по событиям и таймлайнам
explainable AI (ответ + источники)
LLM здесь – интерфейс к данным, а не их носитель.
Ключевая мысль главы
RAG – это способ вернуть контроль.
Контроль над источниками.
Контроль над актуальностью.
Контроль над тем, где модель должна сказать: "я не знаю".
И именно поэтому RAG – не про модели, а про инженерию.
Last updated