Внутренние документы тонут в хаосе. И это нормально
В любой крупной компании документация разрастается как раковая опухоль. Технические регламенты, инструкции для поддержки, юридические политики, данные о продуктах — всё это разбросано по Confluence, SharePoint, GitLab, базам знаний. Сотрудник тратит в среднем 30% рабочего времени на поиск информации. Знакомо?
ЮMoney — не исключение. Финансовая организация с сотнями тысяч клиентов, сотнями микросервисов и тоннами внутренней документиции. Им нужен был ассистент, который не просто найдёт ответ, но и не сольёт критичные данные. Мы построили RAG-систему. Честно: наступили на все грабли, которые только можно. Дальше — без прикрас, с кодом и циничным взглядом.
Почему RAG в enterprise — это не игрушка
RAG (Retrieval-Augmented Generation) — штука красивая: берёшь LLM, подсовываешь контекст из корпоративной базы, получаешь ответ по делу. Но в корпорации есть три чудовища: конфиденциальность, галлюцинации и сломанный поиск.
Первый же прототип на OpenAI GPT-4 отправил тестовый запрос с реальными данными клиентов — и мы в ужасе отозвали ключи. Урок: внешние LLM без шифрования и аудита — прямой билет к утечке. Недавний кейс Moltbook, где через дыру в Supabase утекло 35 тысяч емейлов, наглядно показывает: одна ошибка в безопасности хранилища — и данные улетают за 5 минут.
Второй подвох: RAG-системы часто проваливают аудит безопасности под SOC2/HIPAA — просто потому, что не умеют контролировать доступ к чанкам. ЮMoney живет в российской юрисдикции, но требования к защите персональных данных не менее жёсткие.
И третье: LLM обожают сочинять. Если контекст не найден — они придумывают ответ. Для финансовой поддержки это фатально.
Запомните: RAG без guardrails и валидации доступа — это красивая бомба замедленного действия.
Архитектура, на которой мы остановились
Наш стек на 30 июня 2026 выглядит так:
- LLM: YandexGPT 4 (Pro) — работает в зоне РФ, не шлёт данные за границу, имеет сертифицированные контуры для enterprise.
- Векторная БД: Qdrant on-premise. Подняли на отдельных серверах с изоляцией по VLAN.
- Embedding model: intfloat/multilingual-e5-large — показал лучшее качество на русской документации среди open-source.
- Reranker: BAAI/bge-reranker-v2-m3. Снимает шум и поднимает точность ретрива на 12%.
- Guardrails: самописный модуль на Python, проверяющий принадлежность документа к роли пользователя и наличие PII в ответе.
- Индексация: Asynchronous pipeline на FastAPI + Celery с очередью в Redis.
Вся серверная часть запакована в Kubernetes, с отдельным неймспейсом для sensitive data. Сетевые политики запрещают прямой доступ к LLM из интернета — только через API Gateway с OAuth2.
Пошаговый план: как это собрать
1 Собираем документацию и готовим почву
Вы не поверите, но первый шаг — не код, а болтовня с юристами. Мы составили матрицу доступа: какой документ доступен какой роли. Пример: инженер видит технические статьи, но не видит зарплатные ведомости. Без этого этапа ваш RAG — дыра.
Далее парсим Confluence, GitLab wiki и Google Drive. Используем unstructured.io для извлечения текста из PDF, DOCX, Markdown. Всё складываем в S3-совместимое хранилище (мы взяли MinIO). Каждый документ получает метаданные: auth_group, source_url, last_updated.
2 Чанкинг и эмбеддинги
Просто нарезать по 512 токенов — путь в никуда. Мы используем семантический чанкинг: разбиваем по абзацам и заголовкам, с перекрытием 10%. Длина чанка от 200 до 1500 токенов — в зависимости от сложности.
Embedding делаем моделью e5-large. Вектора кладём в Qdrant с индексом HNSW для быстрого поиска. Важный трюк: добавляем в payload поля allowed_roles и source. При поиске сразу фильтруем по роли пользователя — это первая линия защиты.
from qdrant_client import QdrantClient
from qdrant_client.http.models import Filter, FieldCondition, MatchValue
client = QdrantClient(host="qdrant.infra", port=6333)
user_role = "engineer"
# Фильтр по роли
query_filter = Filter(
must=[
FieldCondition(key="allowed_roles", match=MatchValue(value=user_role))
]
)
results = client.search(
collection_name="docs",
query_vector=embedding,
query_filter=query_filter,
limit=20
)3 Ранжируем найденное
Первые 20 чанков из Qdrant содержат шум. Мы прогоняем их через reranker BGE, который выдаёт релевантность от 0 до 1. Оставляем только чанки со score > 0.3, максимум 5 штук. Это даёт резкий прирост точности финального ответа.
Без reranker LLM будет читать мусор — и ответы поплывут. Проверено.
4 Пилим промпт и ставим guardrails
Промпт — это святое. У нас системный промпт говорит модели: «Ты отвечаешь строго на основе переданных документов. Если ответа нет — скажи, что не знаешь. Никогда не пиши лишнего». Добавляем в промпт инструкцию не выводить персональные данные.
После генерации включаем guardrail-модуль: он проверяет ответ на наличие номеров телефонов, паспортов, банковских карт. Если находит — заменяет ответ заглушкой «Информация доступна только авторизованному персоналу». Плюс логируем подозрительный запрос в SIEM.
💡 Guardrails не защитят, если модель видит конфиденциальные данные в контексте — поэтому на этапе чанкинга мы уже отсекли документы по роли. Только так.
5 Дешёвый и быстрый вывод
LLM поднимаем через YandexGPT API — latency ~2 секунды на запрос. Если нагрузка растёт, добавляем батчинг. Мы также экспериментируем с кэшированием частых запросов: если вопрос встречался ранее с таким же семантическим отпечатком (через MinHash), отдаём готовый ответ. Это снижает затраты на 40%.
Для кэша используем Redis с TTL 24 часа. Старые ответы инвалидируем, если документация обновляется (вешаем webhook на Confluence).
Ошибки, на которых мы обожглись
Вот топ-4 граблей. Надеюсь, вы наступите хотя бы не на все.
- Пренебрежение преднастройкой чанков. Сначала нарезали по предложениям — модель получала обрывки мыслей. Решение: семантический чанкинг и сохранение структуры заголовков.
- Доверие к LLM без валидации. Модель придумывала API-методы, которых не существует. Guardrails + promt “Ответь только контекстом” не панацея, если контекст пустой. Добавили проверку релевантности: если reranker не вернул ни одного чанка — не передаём ничего, модель отвечает “Нет данных”.
- Игнорирование обновлений. Документация меняется каждый день. Индексация раз в сутки приводила к устаревшим ответам. Перешли на инкрементальную индексацию через Celery beat каждые 30 минут.
- Слабый мониторинг. Первый месяц не считали метрики качества. Потом добавили оценку ответов пользователями (like/dislike) и замеряли hit rate ретрива. Провалы стали видны сразу. Советую почитать наш дайджест проблем RAG в 2026 — там мы собрали все подводные камни, включая атаки инъекциями на промпт.
Безопасность — это не финальная опция, а процесс
Мы сделали так: каждый новый документ перед добавлением в векторную базу проходит ручную ревью на чувствительность. Автоматика помечает возможные PII (номера договоров, ИНН), человек решает, оставлять или шифровать. Шифрованные чанки хранятся отдельно и доступны только с ролью “compliance”.
Кроме того, мы внедрили аудит всех запросов. Каждое взаимодействие с ассистентом логируется с user_id, временем, текстом вопроса и финальным ответом. Это позволяет расследовать инциденты и проходить аудиты без нервотрёпки.
Если бы начинали с нуля — сделали бы так
Самый неочевидный совет: начните с маленького дага — 50 вопросов от реальных пользователей. Проверьте, находит ли RAG ответ, устраивает ли качество. И только потом масштабируйте. И не верьте вендорам, обещающим магию. RAG — это инженерная работа, где 20% времени занимает LLM, а 80% — грамотные данные, индексация и безопасность.
Кстати, про инструменты: ещё один полезный кейс — SyGra Studio, визуальный конструктор агентов. Для быстрого прототипа RAG может пригодиться, но под enterprise мы предпочли кастом.
Остались вопросы? Спрашивайте в комментариях — я отвечу (или наш юрист, если спросите про compliance).