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 + Ollama | Privacy, контроль, €5/мес |
| Production-команда, масштаб | Managed: Pinecone + OpenAI | Надёжность, масштабирование |
| Быстрый старт, тестирование | No-code: Notion AI, ChatGPT Upload | Не нужен код, но ограниченный объём |
| Enterprise, compliance | Weaviate + Anthropic | SLA, безопасность, аудит |
| Мобильный доступ | Managed с API | Self-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 решает поиск по фрагментам, не магию. Здесь — честные ограничения, с которыми я сталкивался в продакшене.
Тезис
Тезис
Тезис
Тезис
Тезис
Тезис
Антипаттерны
🚫 Эти ошибки я видел у себя и у других. Каждая — из реального продакшена.
Тезис
chunk_overlap — 10-20% от размера chunk.Тезис
metadata при загрузке документов.Тезис
Тезис
Тезис
Чеклист
| Проверка | Что сделать |
|---|---|
| Документы готовы | 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, не в коде |
| Мониторинг | Логи запросов, метрики точности поиска |