AI-инжиниринг

RAG: Retrieval-Augmented Generation от теории до реализации

Цели урока

  • Понять, зачем LLM нужна внешняя память и какие проблемы решает RAG
  • Освоить полный RAG pipeline: indexing, retrieval, augmentation, generation
  • Реализовать production-ready RAG с pgvector и NestJS
  • Написать prompt template, минимизирующий галлюцинации
  • Настроить метрики качества: faithfulness, relevance, correctness

Предварительные знания

  • Работа с vector databases и embeddings
  • Vector Databases

Fine-tuning GPT-4 стоит `100K USD`+ и занимает недели. RAG стоит `50 USD/месяц` на хостинг Qdrant и запускается за день. И RAG чаще даёт лучший результат - потому что не делает модель умнее. Он просто кладёт ответ прямо в контекст и просит пересказать. Это технически обман. Но он работает - и именно на этом принципе построены Perplexity, Notion AI и 80% корпоративных AI-проектов.

  • Perplexity AI (2022) - первый массовый RAG-продукт, поиск по интернету в реальном времени, 500M+ valuation
  • Notion AI - RAG по документам пользователя, +100M ARR за первый год без единой строки fine-tuning
  • GitHub Copilot - RAG по кодовой базе репозитория для контекстных подсказок
  • 80% AI-проектов в enterprise используют RAG - это стандартная архитектура корпоративных чатботов

Как RAG появился

**2020**: Patrick Lewis и команда Facebook AI Research публикуют "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks" - оригинальный RAG paper. Идея: соединить retriever (DPR) и generator (BART) в единую дифференцируемую архитектуру. Модель обучалась искать релевантные документы и генерировать ответы на их основе. **2022**: Perplexity запускается как первый массовый продукт на RAG-принципе - поисковик, который не показывает ссылки, а синтезирует ответ из найденных источников. Пользователи видят не 10 синих ссылок, а связный текст с цитатами. **2023**: RAG становится стандартом - каждый корпоративный AI-чатбот строится по этому паттерну. LangChain, LlamaIndex, pgvector - вся экосистема выросла вокруг одной идеи из 2020 года.

Зачем LLM нужна внешняя память

GPT-4 обучался на данных до апреля 2024. Спросить про событие мая 2024 - и модель уверенно выдаёт галлюцинацию. Спросить про внутреннюю документацию компании - и модель придумывает правдоподобный, но полностью ложный ответ. Это не баг. Это архитектурное ограничение, вшитое в принцип работы авторегрессивных моделей.

У LLM три системные проблемы, которые нельзя решить дообучением:

ПроблемаСутьПример
Knowledge cutoffМодель не знает ничего после даты обучения"Какой курс доллара сегодня?" - ответ устарел на месяцы
HallucinationsМодель генерирует правдоподобный, но ложный текст"Процитируй статью из Nature" - модель выдумывает DOI и авторов
No private dataМодель не имеет доступа к корпоративным данным"Какая политика отпусков в нашей компании?" - модель фантазирует

**RAG (Retrieval-Augmented Generation)** решает все три одним архитектурным паттерном: перед генерацией ответа - найти релевантные документы и подставить их в prompt. Модель не "вспоминает" - она **читает** предоставленный контекст. Это принципиально разные вещи.

Альтернативы - fine-tuning и длинный контекст - проигрывают по всем фронтам:

ПодходСтоимостьАктуальностьКонтроль
Fine-tuning GPT-4100K+ долларов за обучениеУстаревает при обновлении данныхНельзя быстро обновить
Длинный контекст (1M tokens)5-20 долларов за запросАктуально, но дорогоМедленно, теряет точность
RAG0.001-0.01 доллара за запросОбновляется мгновенноТочный контроль источников

RAG - это open-book exam. Вместо того чтобы заставлять студента зубрить всё наизусть, ему дают справочник. LLM хорошо умеет понимать и синтезировать информацию - нужно лишь предоставить правильные источники.

Какую проблему RAG НЕ решает?

RAG Pipeline: от запроса до ответа

RAG pipeline состоит из двух фаз: **indexing** (однократная подготовка документов) и **retrieval + generation** (при каждом запросе). Ключевой инсайт - indexing запускается редко, а query - тысячи раз в день. Стоимость системы определяет именно query-фаза.

Фаза 1: Indexing (офлайн)

  1. **Load** - загрузить документы (PDF, Markdown, HTML, база данных)
  2. **Split** - разбить на chunks по 512 токенов с overlap 20% (102 токена) - золотой стандарт для text-embedding-3-small
  3. **Embed** - превратить каждый chunk в вектор 1536 измерений через `text-embedding-3-small` (`0.02` за 1M токенов)
  4. **Store** - сохранить vectors + metadata в vector database (pgvector, Qdrant, Pinecone)

Фаза 2: Query (при каждом запросе)

  1. **Embed query** - превратить вопрос пользователя в embedding той же моделью
  2. **Search** - найти top-K ближайших chunks через cosine similarity (порог 0.7)
  3. **Augment** - вставить найденные chunks в prompt как контекст
  4. **Generate** - LLM генерирует ответ строго на основе контекста
  5. **Return** - вернуть ответ + ссылки на источники

Оператор `<=>` в pgvector - это cosine distance. `1 - (embedding <=> `1`)` даёт cosine similarity (от 0 до 1). Чем ближе к 1 - тем релевантнее документ. Порог 0.7 подобран эмпирически для text-embedding-3-small - при значениях ниже начинается шум.

В каком порядке выполняются шаги RAG при обработке запроса пользователя?

Реализация RAG с pgvector и Node.js

pgvector - расширение PostgreSQL для работы с vector embeddings. Для backend-разработчика, уже использующего PostgreSQL, это самый быстрый путь к production RAG: ноль новой инфраструктуры, привычные транзакции, JOIN с остальными таблицами. Perplexity начинала именно на pgvector - до того как масштаб потребовал перехода на Qdrant.

Полноценный RAG-сервис в NestJS - от indexing до ответа с источниками:

Порог similarity (`> 0.7`) - критически важен. Без него RAG вернёт нерелевантные chunks, и LLM будет галлюцинировать на основе плохого контекста. Значение подбирается эмпирически: 0.7-0.8 для text-embedding-3-small. Для мультиязычных задач - 0.65.

Зачем в поисковом запросе pgvector используется порог similarity > 0.7?

Prompt template для RAG

Качество RAG на 50% зависит от retrieval и на 50% от prompt. Плохой prompt может испортить даже идеально найденные документы. Распространённая иллюзия - "подать хороший контекст и всё само заработает". Нет. Без жёстких инструкций модель начнёт подмешивать собственные знания - тихо и уверенно.

Шаблон пользовательского сообщения тоже важен. Контекст и вопрос должны быть чётко разделены:

Распространённая ошибка - добавлять chunks как system message. Контекст лучше передавать в user message, а system оставить для инструкций. Это снижает prompt injection риски и упрощает кеширование system prompt - Anthropic даёт скидку 90% на кешированные system prompt.

Для повышения quality полезно передавать metadata каждого chunk - источник и дата помогают модели приоритизировать более свежие и авторитетные документы:

Какое правило НАИБОЛЕЕ важно в RAG system prompt?

Метрики качества RAG

RAG работает? Отвечает на вопросы? Этого недостаточно. Без метрик нельзя понять, улучшают ли изменения качество или ухудшают. Перемещение порога с 0.7 до 0.75 - помогает или нет? Только цифры покажут. Три ключевые метрики RAG: **faithfulness**, **relevance**, **answer correctness**.

МетрикаЧто измеряетКак считать
FaithfulnessОтвет основан на контексте, а не выдуман?LLM-as-judge: "Все ли утверждения в ответе подтверждаются контекстом?"
Context RelevanceНайденные документы релевантны вопросу?Доля retrieved chunks, которые реально нужны для ответа
Answer RelevanceОтвет отвечает на заданный вопрос?LLM-as-judge: "Насколько ответ соответствует вопросу?"
Answer CorrectnessОтвет фактически правильный?Сравнение с ground truth (если есть golden dataset)

Фреймворки для evaluation: **RAGAS** (Python, стандарт индустрии), **LangSmith** (tracing + eval), **DeepEval** (Python). Для Node.js чаще проще реализовать LLM-as-judge самостоятельно, как показано выше - это 30 строк кода против новой зависимости.

Метрика faithfulness в RAG оценивает...

Типичные ошибки и подводные камни RAG

Naive RAG implementation часто даёт 50-60% accuracy. Прототип за выходные - и production система с 90% faithfulness - это разные продукты. Разрыв почти целиком в деталях, которые не видны на первом запуске.

ПроблемаСимптомРешение
Chunks слишком большиеОтвет расплывчатый, много шумаУменьшить chunk size до 256-512 tokens, добавить overlap 20%
Chunks слишком маленькиеКонтекст вырван, ответ неполныйУвеличить chunk size, использовать parent document retriever
Нет порога similarityLLM галлюцинирует на нерелевантном контекстеДобавить WHERE similarity > 0.7, возвращать 'не найдено'
Плохой embedding modelСемантически похожие документы не находятсяПерейти на text-embedding-3-large или multilingual модель
Нет metadata filteringПоиск по всей базе вместо нужной категорииДобавить pre-filtering по metadata (дата, категория, автор)
System prompt не ограничиваетМодель подмешивает собственные знанияДобавить строгие инструкции: ТОЛЬКО контекст, иначе 'не найдено'

Самая опасная ошибка - отсутствие fallback при пустых результатах. Если поиск не нашёл ничего релевантного, RAG должен честно сказать "информация не найдена", а не передавать пустой контекст в LLM. Модель начнёт отвечать из собственных знаний - и это будет выглядеть как нормальный ответ. Пользователь поверит. Доверие сломается позже - когда окажется, что ответ был выдуман.

Чек-лист production RAG:

  • Similarity threshold настроен и протестирован на реальных запросах
  • Metadata pre-filtering сужает scope поиска
  • Fallback при пустых результатах - "не найдено" вместо галлюцинаций
  • Логирование: query, retrieved chunks, similarity scores, response time
  • Evaluation pipeline: faithfulness + relevance на golden dataset
  • Мониторинг: % запросов с нулевыми результатами, средний similarity score

RAG возвращает расплывчатые ответы с большим количеством нерелевантной информации. Наиболее вероятная причина?

RAG решает проблему галлюцинаций

RAG снижает галлюцинации только тогда, когда релевантный chunk найден. Если поиск возвращает нерелевантные документы или пустой результат - модель галлюцинирует с той же уверенностью

RAG - это не магический антигаллюцинаторный слой. Это система доставки контекста. Если контекст плохой (неправильный chunking, низкий similarity threshold, плохая embedding модель) - галлюцинации остаются. Хуже того: модель галлюцинирует на основе плохого контекста и делает это уверенно, ссылаясь на "источники". Именно поэтому нужен similarity threshold 0.7 и честный fallback "информация не найдена".

RAG и fine-tuning решают одну задачу

Это разные инструменты для разных задач. Fine-tuning меняет поведение модели (стиль, формат, специализация). RAG даёт модели доступ к актуальным данным

Fine-tuning на корпоративных документах не означает, что модель будет "знать" эти документы - она выучит паттерны, но не факты. Через месяц документы устареют, а fine-tuning придётся повторять. RAG не меняет модель - он добавляет данные при каждом запросе. Обновил документы - RAG автоматически использует новую версию.

Итоги

  • RAG решает три проблемы LLM: knowledge cutoff, галлюцинации, отсутствие приватных данных - за 0.001-0.01 доллара за запрос против 100K+ на fine-tuning
  • Pipeline: Load -> Split (512 tokens, 20% overlap) -> Embed (text-embedding-3-small) -> Store (indexing) и Embed query -> Search (cosine > 0.7) -> Augment -> Generate (query)
  • pgvector + HNSW - самый быстрый путь к production RAG без новой инфраструктуры
  • Prompt template должен строго ограничивать модель контекстом - иначе модель тихо подмешивает собственные знания
  • Faithfulness (верность контексту), Context Relevance, Answer Correctness - три метрики, без которых нельзя улучшать систему
  • Главные ловушки: нет similarity threshold, нет fallback при пустых результатах, chunks слишком большие - каждая из них открывает дверь для галлюцинаций

Вопросы для размышления

  • В каком из текущих или прошлых проектов RAG мог бы заменить или дополнить поиск по базе данных?
  • Почему RAG - это "обман" с технической точки зрения, и почему этот обман работает лучше, чем fine-tuning на тех же данных?
  • Если similarity score у всех найденных chunks ниже 0.7 - что должна делать система? Вернуть лучшие результаты или честно сказать "не знаю"?

Что дальше

Naive RAG покрывает 60-70% случаев. Для оставшихся 30% нужны advanced техники: hybrid search, re-ranking, query transformation.

  • Advanced RAG — Hybrid search, re-ranking, query expansion - от 60% accuracy к 90%
  • Chunking стратегии — Как правильно разбивать документы - fixed, recursive, semantic chunking
  • Conversation Memory — Как добавить RAG в чатбот с сохранением контекста разговора

Связанные уроки

  • aie-10-vector-databases — Retrieval в RAG работает поверх векторного хранилища
  • aie-09-embeddings — Качество поиска зависит от качества эмбеддингов
  • aie-13-advanced-rag — Наивный RAG это базис для продвинутых техник
  • aie-14-chunking-strategies — Чанкинг задаёт потолок точности retrieval
  • ml-52-search-ranking — Ранжирование retrieval использует скоринг из информационного поиска
  • db-28-search — Retrieval в RAG это семантический поиск по корпусу
  • net-21-http-basics
  • db-30-vector
RAG: Retrieval-Augmented Generation от теории до реализации

0

1

Войти