Введение
Представьте: ваш корпоративный AI-ассистент больше не «галлюцинирует» на общих данных, а отвечает строго по вашим документам — отчётам, инструкциям, базе знаний. Это не магия, а RAG (Retrieval Augmented Generation) — технология, которая позволяет языковой модели искать информацию в вашей личной коллекции файлов перед генерацией ответа. В 2026 году RAG стал стандартом для бизнес-решений: от поддержки клиентов до внутренних баз знаний. В этой статье мы разберём, как собрать RAG-систему своими руками — от загрузки PDF до векторного поиска.
Что такое RAG и зачем он вам?
RAG (Retrieval Augmented Generation) — это гибридный подход: AI сначала находит релевантные куски текста из вашего хранилища, а затем формирует ответ на их основе. Без RAG модели (например, GPT-4 или Claude) полагаются только на свои тренировочные данные, которые могут устареть. С RAG вы получаете:
- Актуальность: ответы строго на базе ваших документов.
- Конфиденциальность: данные не уходят на обучение модели.
- Контроль: вы управляете тем, что AI «знает».
Ключевые компоненты RAG: загрузка документов, чанкинг (разбивка на фрагменты), создание эмбеддингов и векторный поиск. Далее — по шагам.
Шаг 1: Загрузка и подготовка документов
Любая RAG-система начинается с загрузки файлов. Поддерживаемые форматы: PDF, DOCX, TXT, Markdown, HTML. Для примера возьмём три технических мануала на 50 страниц каждый.
Очистка данных
Перед чанкингом удалите шум: водяные знаки, колонтитулы, лишние пробелы. Используйте библиотеки вроде PyMuPDF для Python или Unstructured для парсинга. Например, скрипт на Python:
import fitz
doc = fitz.open("manual.pdf")
text = "".join([page.get_text() for page in doc])
Шаг 2: Чанкинг (разбивка на фрагменты)
Длинные документы нельзя отправлять в LLM целиком — модель имеет ограничение контекста. Чанкинг решает эту проблему: вы режете текст на семантические блоки.
Оптимальные параметры чанкинга
| Параметр | Рекомендация | Пояснение |
|---|---|---|
| Размер чанка | 256-512 токенов | Баланс между детализацией и контекстом |
| Перекрытие (overlap) | 10-20% | Сохраняет связность соседних чанков |
| Стратегия | Семантический (по абзацам) | Лучше, чем простой разрез по символам |
Пример реализации с LangChain:
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_text(text)
Совет: для технических документов используйте семантический чанкинг (по заголовкам), чтобы не разрывать логические блоки.
Шаг 3: Создание эмбеддингов
Эмбеддинги — это числовые векторы, которые представляют смысл текста. AI не понимает слова, но умеет сравнивать векторы. Чем ближе векторы в многомерном пространстве, тем семантически ближе тексты.
Выбор модели эмбеддингов
| Модель | Размерность | Бесплатная? | Особенность |
|---|---|---|---|
text-embedding-ada-002 (OpenAI) |
1536 | Нет (плата за токены) | Высокая точность |
intfloat/multilingual-e5-large |
1024 | Да (открытая) | Поддержка русского языка |
BAAI/bge-m3 |
1024 | Да | Мультиязычная, до 8192 токенов |
Для русского языка лучше всего подходит intfloat/multilingual-e5-large. Генерация эмбеддинга для одного чанка:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('intfloat/multilingual-e5-large')
embedding = model.encode("Ваш текст чанка")
Шаг 4: Векторный поиск и база данных
Теперь нужно сохранить эмбеддинги в векторной базе. Популярные варианты: ChromaDB (лёгкая, для прототипов), Pinecone (облачная, масштабируемая), Qdrant (self-hosted). Векторная база хранит пары (вектор, текст чанка + метаданные).
Пример с ChromaDB (локально):
import chromadb
client = chromadb.Client()
collection = client.create_collection("my_knowledge")
collection.add(
embeddings=embeddings_list,
documents=chunks,
ids=[f"chunk_{i}" for i in range(len(chunks))]
)
При запросе пользователя вы также превращаете его вопрос в эмбеддинг и ищете ближайшие чанки через collection.query(query_embeddings=[...], n_results=5).
Шаг 5: Генерация ответа с контекстом
Финальный шаг — передать найденные чанки в LLM вместе с вопросом. Используйте промпт вида:
Ответь на вопрос, используя только следующий контекст. Если ответа нет, скажи «не знаю».
Контекст: {чанк_1}\n{чанк_2}
Вопрос: {вопрос пользователя}
Пример на Python с OpenAI:
import openai
context = "\n".join([doc for doc in retrieved_chunks])
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[
{"role": "system", "content": f"Контекст: {context}"},
{"role": "user", "content": question}
]
)
Заключение
RAG-система своими руками — это не только экономия на API, но и полный контроль над данными. Мы прошли путь от загрузки PDF до генерации ответа с контекстом. Теперь ваш AI может отвечать на вопросы, опираясь на внутренние документы, а не на случайные интернет-данные.
Что делать дальше?
1. Скачайте пример кода с нашего GitHub (https://github.com/asibiont/rag-starter).
2. Протестируйте на своих документах.
3. Подпишитесь на блог Asibiont — в следующих статьях разберём оптимизацию RAG: гибридный поиск, ранжирование и мониторинг точности.
Готовы собрать свою базу знаний AI? Начните прямо сейчас — загрузите первый документ и получите ответ за 5 минут.
Комментарии