🔍 RAG: поиск + генерация

Схема RAG, индексация, чанки, эмбеддинги, векторные БД, промпт и оценка качества.

Теория · ИИ · #rag #llm #embeddings #vector-db

Идея

RAG (Retrieval-Augmented Generation) добавляет в запрос к языковой модели найденные фрагменты ваших данных. Модель отвечает по ним, а не только по памяти: меньше выдумок, свежие и приватные знания без дообучения.

Схема

Документы → разбивка на чанки → эмбеддинги → векторная БД      (индексация, один раз)
Вопрос → эмбеддинг → поиск ближайших чанков → промпт + чанки → LLM → ответ (запрос)

Этапы индексации

Этап Что делаем
Загрузка PDF, HTML, Markdown, Confluence, БД, чаты
Очистка убрать мусор, навигацию, дубли; сохранить структуру заголовков
Чанкинг делим на куски 200–1000 токенов с перекрытием 10–20%, по границам абзацев и заголовков
Метаданные источник, раздел, дата, права доступа
Эмбеддинги вектор смысла (OpenAI, Cohere, BGE, E5, nomic-embed-text)
Хранение векторная БД

Векторные хранилища

pgvector (PostgreSQL), Qdrant, Weaviate, Milvus, Chroma, Pinecone, Elasticsearch / OpenSearch (kNN), Redis, FAISS (библиотека).

Поиск

Приём Зачем
Векторный (косинусная близость) находит по смыслу
Ключевой BM25 точные термины, артикулы, коды
Гибридный (вектор + BM25) лучшее из двух, объединение через RRF
Фильтры по метаданным права, продукт, версия
Реранкинг (cross-encoder, Cohere Rerank, bge-reranker) переупорядочить топ-N по точной релевантности
Переписывание запроса разворачивает «а он?» в самостоятельный вопрос
HyDE сначала гипотетический ответ, поиск по нему

Промпт генерации

Ты — помощник по документации. Отвечай ТОЛЬКО по фрагментам ниже.
Если ответа в них нет, скажи «В документах нет ответа».
Приводи ссылки на источники в формате [номер].

Фрагменты:
[1] <текст чанка> (источник: guide.md, раздел «Установка»)
[2] <текст чанка> (…)

Вопрос: <вопрос пользователя>

Минимальный пример (Python)

from sentence_transformers import SentenceTransformer
import numpy as np

model = SentenceTransformer('intfloat/multilingual-e5-base')
chunks = ["Docker — платформа контейнеризации.", "Git — система контроля версий."]
vecs = model.encode(chunks, normalize_embeddings=True)

q = model.encode(["Что такое контейнеры?"], normalize_embeddings=True)
best = int(np.argmax(vecs @ q.T))
context = chunks[best]      # дальше передать в LLM вместе с вопросом

Качество и оценка

Метрика Что проверяет
Recall@k, MRR нашёл ли поиск нужный чанк
Faithfulness ответ опирается на контекст
Answer relevance ответ отвечает на вопрос
Context precision нет ли лишнего в контексте

Инструменты: Ragas, TruLens, LangSmith, Phoenix. Соберите набор 50–200 вопросов с эталонами и измеряйте после каждого изменения.

Типичные проблемы

Симптом Причина и решение
Ответ неточный чанки слишком большие или маленькие; добавьте реранкер
«Не нашёл», хотя есть нет гибридного поиска, плохие эмбеддинги для языка
Выдумки усильте инструкцию «только по контексту», уменьшите температуру, требуйте цитаты
Устаревшее обновление индекса по расписанию, дата в метаданных
Утечка данных фильтры прав в поиске, а не только в интерфейсе

RAG, дообучение или длинный контекст

RAG для часто меняющихся знаний со ссылками на источники. Дообучение для стиля, формата, узких задач. Длинный контекст для небольших документов, без индекса.