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 — теряется контекст. Слишком большие — много шума. Для юридических документов — 1000 слов. Для FAQ — 200–300.

Тезис

Не работает offline на телефоне
Self-hosted RAG требует сервер (VPS). Для мобильного доступа — managed (Pinecone + API).

Тезис

Embeddings требуют ресурсов
CPU-создание векторов: 1000 страниц ~ 10 минут. GPU ускоряет в 10 раз.

Тезис

Hallucinations всё ещё возможны
LLM может «додумать» информацию между chunks. Всегда проверяйте источники.

Тезис

Мультиязычность сложна
Одна модель embeddings плохо работает с документами на разных языках. Нужен мультиязычный embedding (multilingual-e5-large).

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

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

🚫 Что не делать

Тезис

Большие chunks без overlap
Теряется контекст на границах. Всегда используйте chunk_overlap — 10-20% от размера chunk.

Тезис

Игнорировать метаданные
Источник, дата, автор важны для фильтрации. Сохраняйте в metadata при загрузке документов.

Тезис

Один embedding для всего
Юридические и технические документы требуют разных моделей. all-MiniLM-L6-v2 для английского, multilingual-e5 для мультиязычности.

Тезис

Skip quality check
RAG может вернуть нерелевантный chunk. Всегда проверяйте ручную выборку ответов перед production.

Тезис

Production без fallback
Если векторная база недоступна, сервис должен деградировать gracefully — честное "Не знаю" лучше выдуманного ответа.

Чеклист

ПроверкаЧто сделать
Документы готовы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, не в коде
МониторингЛоги запросов, метрики точности поиска