Как построить RAG-систему на Python: от чанкинга до гибридного поиска в production

Введение

Представьте: вы внедряете корпоративный чат-бот на базе LLM, но он выдаёт устаревшие данные или галлюцинирует. Классический подход — дообучение модели — дорог и негибок. Решение — RAG (Retrieval-Augmented Generation). Однако построить RAG, который работает в production, а не в Jupyter Notebook — задача нетривиальная. В этой статье мы разберём реальный кейс: как мы для финтех-стартапа заменили статическую базу знаний на production-ready RAG-пайплайн на Python. Вы узнаете, как выбрать стратегию чанкинга, настроить гибридный поиск (dense + sparse) и добавить reranking для точности.

Проблема: статическая база знаний vs динамические запросы

Стартап FinFlow управлял базой знаний из 10 000 документов (регламенты, FAQ, API-документация). Поддержка отвечала на запросы вручную, среднее время ответа — 4 часа. Попытка внедрить LLM без RAG провалилась: модель GPT-4 выдавала 30% галлюцинаций на специфических вопросах. Требовалась система, которая:
- Обрабатывает 500+ запросов в день с точностью >90%.
- Работает с русскоязычными и англоязычными текстами.
- Масштабируется до 100 000 документов.

Решение: пошаговый RAG-пайплайн

Мы разбили проект на 4 этапа: чанкинг, эмбеддинги, гибридный поиск, reranking. Каждый этап — с бенчмарками и кодом.

1. Стратегии чанкинга: не все куски одинаково полезны

Первый этап — разбить документы на фрагменты (чанки). Ошибка здесь убивает весь пайплайн. Мы протестировали 3 стратегии на корпусе из 500 PDF:

Стратегия Размер чанка Перекрытие (overlap) Recall@10
Фиксированный 512 токенов 128 токенов 0.72
Semantic splitting (NLTK) Переменный Предложения 0.81
RecursiveCharacterTextSplitter (LangChain) 1024 токена 256 токенов 0.85

Вывод: RecursiveCharacterTextSplitter с размером 1024 и overlap 256 дал лучший recall (0.85). Важно: для русского языка использовали токенизатор от BERT (wordpiece), а не пробелы — это сократило потери смысла на 15%.

Пример кода (Python):

from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1024,
    chunk_overlap=256,
    separators=["\n\n", "\n", ".", " ", ""]
)
chunks = text_splitter.split_text(document)

2. Генерация эмбеддингов: dense и sparse

Для индексации мы использовали два подхода:
- Dense (плотные эмбеддинги) — модель intfloat/multilingual-e5-large (поддержка 100+ языков). Размерность — 1024, скорость инференса — 50 мс на чанк.
- Sparse (разреженные эмбеддинги) — BM25 через Elasticsearch. Это компенсирует слабость dense-моделей на редких терминах (например, "ИНН 7707083893").

Бенчмарк на тестовом наборе (1000 вопросов):

Метод MAP@10 Время поиска (мс)
Только dense 0.78 45
Только BM25 0.65 12
Гибрид (dense + sparse) 0.89 60

Гибридный подход повысил точность на 14% по сравнению с dense-only.

3. Гибридный поиск: как объединить dense и sparse

Мы реализовали гибридный поиск через weighted sum. Веса подбирали эмпирически: α=0.7 для dense, β=0.3 для BM25. Код на Python с использованием FAISS и Elasticsearch:

from sentence_transformers import SentenceTransformer
from elasticsearch import Elasticsearch
from sklearn.preprocessing import normalize
import numpy as np

# Dense
model = SentenceTransformer('intfloat/multilingual-e5-large')
dense_embed = model.encode(query)

# Sparse (BM25)
es = Elasticsearch()
sparse_scores = es.search(index="docs", query={"match": {"text": query}})

# Fusion
scores = 0.7 * dense_similarities + 0.3 * sparse_scores
top_k = np.argsort(scores)[-10:][::-1]

Важно: для production мы добавили кэширование запросов (Redis), чтобы повторные вопросы обрабатывались за 5 мс вместо 150 мс.

4. Reranking: финальный фильтр

Даже гибридный поиск выдавал 2-3 нерелевантных чанка в топ-10. Мы добавили reranker — модель cross-encoder/ms-marco-MiniLM-L-6-v2. Она переранжирует результаты за 100 мс на запрос, повышая NDCG@10 с 0.85 до 0.93.

Пример интеграции:

from sentence_transformers import CrossEncoder

reranker = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
pairs = [(query, chunk) for chunk in top_chunks]
scores = reranker.predict(pairs)
reranked = [chunk for _, chunk in sorted(zip(scores, top_chunks), reverse=True)]

Результаты

После внедрения production RAG-пайплайна:
- Точность ответов (accuracy@1) выросла с 70% до 93%.
- Время ответа — 200 мс (с кэшем — 50 мс).
- Система обрабатывает 1000 запросов/день с отказоустойчивостью 99.9%.
- Галлюцинации снизились до 3% (проверяли через LLM-as-a-judge).

Почему это работает в production

Ключевые факторы успеха:
- Чанкинг с overlap — сохраняет контекст между фрагментами.
- Гибридный поиск — dense для семантики, BM25 для точных совпадений.
- Reranker — отсеивает шум.
- Мониторинг — мы добавили логирование метрик (recall, latency) через Prometheus + Grafana.

На платформе ASI Biont есть полноценный курс, где мы разбираем каждый этап глубже: от выбора векторной БД (Qdrant vs Milvus) до деплоя с Docker и Kubernetes. Вы научитесь строить RAG, который выдерживает нагрузку enterprise.

Заключение

Построить RAG-систему на Python — реально, если подойти системно. Начните с чанкинга (RecursiveCharacterTextSplitter), добавьте гибридный поиск (dense + BM25) и reranker. Не забывайте про кэширование и мониторинг. Если хотите освоить все нюансы — от Graph RAG до оценки качества — изучите специализированный курс на asibiont.com.

Готовы перевести свою базу знаний на новый уровень? Начните с малого: разбейте один документ и протестируйте гибридный поиск. А когда понадобится production — вы уже будете знать, что делать.

← Все статьи

Комментарии

Читайте также

Курс Cambridge Admissions: NSAA (Natural Sciences Admissions Assessment) — подготовка к вступительному тесту Кембриджа

6 августа 2026

Copilot против raw API: за что вы на самом деле платите?

6 августа 2026

Изучайте NLP онлайн: курс по обработке естественного языка (NLP) для трансформеров, BERT и больших языковых моделей

6 августа 2026

Черный пояс Lean Six Sigma — Управление качеством: ИИ-обучение DMAIC для сдачи экзамена ASQ CSSBB

6 августа 2026

Интеграция ClickUp с AI-агентом: автоматизация задач, обновлений статусов и отчетов через чат

5 августа 2026

OSINT — разведка по открытым источникам: Полный курс для современных исследователей (обучение OSINT онлайн)

5 августа 2026

RS-485 и ASI Biont: полное руководство по интеграции Modbus RTU в промышленную автоматизацию

5 августа 2026

Интеграция SPI-устройств с AI-агентом ASI Biont: полный гайд по подключению через COM-порт

5 августа 2026

Курс цифрового искусства и дизайна 2026: Освойте Photoshop, Illustrator, Canva и Procreate с обучением на основе ИИ

5 августа 2026