RAG = AI ищет ответ в ваших документах, а не в интернете. Как работает под капотом, какие инструменты выбрать, ограничения и чеклист для старта.

Что это

RAG (Retrieval-Augmented Generation) — архитектура, где AI-модель отвечает на вопросы не из своих обучающих данных, а из ваших документов. Система ищет релевантные фрагменты в вашей базе знаний и даёт их модели вместе с вопросом.

📌 RAG = Google Search по вашим документам + GPT. Находим релевантные фрагменты, даём их AI, получаем точный ответ с указанием источников.

Когда я впервые спросил ChatGPT о нашем внутреннем регламенте — он выдумал ответ. RAG решает это: AI ищет в наших документах, а не в общих знаниях.

Зачем нужно

  • Внутренние документы не в интернете — регламенты, договоры, база знаний компании
  • AI выдумает ответ если не знает — RAG даёт только проверенные факты из документов
  • Актуальность — данные в документах свежие, в модели — устаревшие (cutoff)
  • Источники — ответ с указанием, из какого документа взята информация
  • Приватность — self-hosted RAG = данные никогда не уходят в облако

Как устроено

Компоненты RAG

ЭлементНазначениеПример инструментов
ДокументыИсточник знанийPDF, Word, TXT, Markdown
ChunkingРазбиение на фрагментыLangChain, LlamaIndex, ручной
EmbeddingsПреобразование текста в векторыOpenAI, HuggingFace (all-MiniLM-L6-v2)
Векторная базаХранение и поиск векторовChroma, Pinecone, Weaviate
LLMГенерация ответаGPT-4o, Claude, Ollama (Llama 3.2)
RetrieverПоиск релевантных фрагментовВстроен в LangChain / LlamaIndex

Процесс шаг за шагом

ШагДействиеРезультат
1. ЗагрузкаPDF/Word → текстСырой текст документов
2. ChunkingРазбить на куски по 500–1000 слов~200 chunks для 100 страниц
3. EmbeddingsКаждый chunk → вектор из 384–1536 чиселВекторное представление смысла
4. ХранениеСохранить в векторной базеБыстрый семантический поиск
5. ЗапросВопрос пользователя → embeddingВектор запроса
6. ПоискНайти 5 ближайших векторовТоп-5 релевантных chunks
7. ГенерацияОтправить chunks + вопрос в LLMТочный ответ с источниками

Когда использовать

СитуацияРешениеПричина
Внутренняя база знаний (FAQ, регламенты)Self-hosted: Chroma + OllamaPrivacy, контроль, €5/мес
Production-команда, масштабManaged: Pinecone + OpenAIНадёжность, масштабирование
Быстрый старт, тестированиеNo-code: Notion AI, ChatGPT UploadНе нужен код, но ограниченный объём
Enterprise, complianceWeaviate + AnthropicSLA, безопасность, аудит
Мобильный доступManaged с APISelf-hosted требует сервер

Пример

Минимальный RAG за 1 день (Python)

# Установка зависимостей
# pip install langchain chromadb sentence-transformers

from langchain.vectorstores import Chroma
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.llms import Ollama
from langchain.documentloaders import PyPDFLoader
from langchain.textsplitter import RecursiveCharacterTextSplitter

# 1. Загрузить документы
loader = PyPDFLoader("./documents/contract.pdf")
docs = loader.load()

# 2. Разбить на chunks
textsplitter = RecursiveCharacterTextSplitter(
    chunksize=1000,
    chunkoverlap=200
)
chunks = textsplitter.splitdocuments(docs)

# 3. Создать embeddings (бесплатно, локально)
embeddings = HuggingFaceEmbeddings(
    modelname="all-MiniLM-L6-v2"  # 384 dimensions, быстрый
)

# 4. Сохранить в Chroma
vectorstore = Chroma.fromdocuments(
    documents=chunks,
    embedding=embeddings,
    persistdirectory="./chromadb"
)

# 5. Настроить поиск
retriever = vectorstore.asretriever(
    searchkwargs={"k": 5}  # Топ-5 релевантных chunks
)

# 6. Подключить LLM (локальная)
llm = Ollama(model="llama3.2:7b")

# 7. Запрос
question = "Какой срок действия договора?"
context = retriever.getrelevant_documents(question)

prompt = f"""Ответь на вопрос на основе контекста.
Если ответа нет в контексте — скажи "Не знаю".

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

Вопрос: {question}"""

answer = llm.predict(prompt)
print(answer)

Требования:

  • RAM: 4 GB (для Ollama + Chroma)
  • Диск: 500 MB (модель Llama 3.2-7B)
  • Время: установка 30 минут, индексация 100 страниц — 5 минут

Альтернатива: Managed (Pinecone + OpenAI)

# pip install pinecone-client openai

import pinecone
from openai import OpenAI

# Инициализация
client = OpenAI(apikey="your-key")
pinecone.init(apikey="your-key", environment="us-west1")
index = pinecone.Index("docs")

# Создать embeddings через OpenAI
def getembedding(text):
    response = client.embeddings.create(
        input=text,
        model="text-embedding-3-small"
    )
    return response.data[0].embedding

# Сохранить
for chunk in chunks:
    vector = getembedding(chunk.pagecontent)
    index.upsert([(chunk.metadata["id"], vector, {"text": chunk.pagecontent})])

# Поиск
queryvector = getembedding(question)
results = index.query(vector=queryvector, topk=5, include_metadata=True)

Цена:

  • Pinecone: $0.10/млн vectors
  • OpenAI embeddings: $0.02/млн tokens
  • Для 10K документов: ~$10–20/мес

Ограничения

Ограничения

Что не получится

RAG решает поиск по фрагментам, не магию. Здесь — честные ограничения, с которыми я сталкивался в продакшене.

RAG не заменяет полный поиск: если вопрос требует анализа всего документа, RAG найдёт только релевантные куски.

Для сложного анализа нужен агент с доступом к полному тексту.

Качество зависит от chunking: слишком маленькие chunks теряют контекст.

Слишком большие дают шум. Для юридических документов подбирайте размер отдельно.

Не работает offline на телефоне: self-hosted RAG требует сервер.

Для мобильного доступа нужен managed-стек или отдельный API-слой.

Embeddings требуют ресурсов: CPU-индексация больших пакетов документов занимает время.

На продакшене это нужно учитывать заранее.

Hallucinations всё ещё возможны: LLM может «додумать» связь между fragments.

Всегда проверяйте источники и ссылки на chunk.

Мультиязычность сложна: одна embedding-модель плохо работает со смешанными языками.

Для мультиязычных баз нужен отдельный выбор модели.

Антипаттерны

Антипаттерны

Типичные ошибки

Эти ошибки я видел у себя и у других. Каждая — из реального продакшена.

Большие chunks без overlap: на границах теряется контекст.

Overlap нужен почти всегда, особенно на длинных документах.

Игнорировать метаданные: источник, дата и автор важны для фильтрации и доверия к ответу.

Не выбрасывайте их из индекса.

Один embedding для всего:

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

Пропуск quality check: RAG может вернуть нерелевантный chunk.

Перед production нужна ручная выборка вопросов и ответов.

Production без fallback:

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

Чеклист

Чеклист

Документы готовы: PDF

→ текст, убрать артефакты форматирования

Chunk size выбран:

500–1000 слов для текстов, 200–300 для FAQ

Overlap настроен:

10–20% от chunk size

Embedding подходит:

all-MiniLM-L6-v2 (англ), multilingual-e5 (мультиязычность)

Векторная база выбрана:

Chroma (self-hosted) или Pinecone (managed)

LLM подходит:

GPT-4o (сложные), Llama 3.2 (простые, локальные)

Fallback есть:

Если RAG не нашёл — честное “Не знаю”

Источники видны: Метаданные chunk

→ ссылка на документ

Безопасность:

API-ключи в .env, не в коде

Мониторинг:

Логи запросов, метрики точности поиска

Ссылки

Ссылки