Почему ваша RAG-система в корпорации обречена на провал
Представьте: у вас есть Confluence с 5000 страниц техдокументации. SharePoint с договорами и отчетами. Slack-архивы, базы знаний в S3, PDF-ки на общих дисках. И все это нужно объединить в одну систему, где любой сотрудник задает вопрос на естественном языке и получает точный ответ с ссылкой на источник.
Звучит как мечта? Большинство команд начинают с выбора модели или векторной базы. И это первая ошибка, которая гарантирует провал через 3 месяца.
В корпоративной среде архитектура определяется не технологиями, а политиками доступа. Кто может видеть финансовые отчеты? Кто — техдокументацию? Если вы сначала выбрали Pinecone, а потом узнали, что данные должны быть в регионе ЕС — готовьтесь переписывать половину системы.
Мы строили PDIQ — внутреннего ассистента для PDI Technologies. Компания работает с топливным и коммерческим транспортом, где ошибка в документации стоит реальных денег. Вот что мы поняли за год разработки.
Архитектура, которая не сломается при первом же аудите
Современная RAG-система в 2026 году — это не просто векторный поиск + LLM. Это многоуровневая система с контролем доступа, аудитом и обновлением данных в реальном времени.
| Слой | Технология | Зачем нужен |
|---|---|---|
| Ingestion Pipeline | AWS Step Functions + Lambda | Забирает данные из Confluence API, SharePoint, S3 |
| Processing Layer | Python + Unstructured.io | Чистит HTML, разбивает PDF на чанки |
| Vector Store | Amazon OpenSearch | Хранит векторы + метаданные (источник, права) |
| Query Engine | AWS Lambda + Bedrock | Ищет чанки, генерирует ответы |
| Access Control | Cognito + Custom Lambda | Проверяет права на каждый чанк |
Почему именно такая структура? Потому что каждый слой можно масштабировать независимо. Когда Confluence API ложится (а он ложится регулярно), ingestion pipeline просто ретраит запросы. Когда нужно добавить новый источник данных — не переписываешь всю систему.
1 Начинаем с инвентаризации, а не с кода
Прежде чем писать первую строчку кода, ответьте на вопросы:
- Какие источники данных критичны? Confluence, SharePoint, что-то еще?
- Кто имеет доступ к каждому источнику? Нужна ли разная видимость для отделов?
- Как часто обновляются данные? Реальное время или раз в сутки достаточно?
- Где должны храниться данные по compliance? AWS регион имеет значение.
Мы использовали Confluence2md для быстрого прототипирования. Но в production перешли на полноценный пайплайн.
2 Ingestion Pipeline: как не сломать Confluence API
Самая частая ошибка — написать скрипт, который одним запросом пытается выкачать все страницы Confluence. Через 10 минут вас забанят, а админы Confluence будут вас ненавидеть.
Вот как делать правильно:
import boto3
from atlassian import Confluence
import json
# Не храните credentials в коде!
# Используйте Secrets Manager
secrets_client = boto3.client('secretsmanager')
secret = secrets_client.get_secret_value(SecretId='confluence-creds')
creds = json.loads(secret['SecretString'])
confluence = Confluence(
url=creds['url'],
username=creds['username'],
password=creds['password'],
cloud=True
)
def get_spaces_with_backoff():
"""Получаем пространства с экспоненциальной backoff задержкой"""
spaces = []
start = 0
limit = 50
while True:
try:
batch = confluence.get_all_spaces(
start=start,
limit=limit,
type='global'
)['results']
if not batch:
break
spaces.extend(batch)
start += limit
# Уважаем rate limits
time.sleep(0.5)
except Exception as e:
if 'rate limit' in str(e).lower():
time.sleep(60) # Ждем минуту при rate limit
continue
raise
return spaces
3 SharePoint интеграция: боль, которую можно пережить
SharePoint — это особый вид ада. API меняется, аутентификация через Azure AD, структура сайтов непредсказуема.
Мы использовали Microsoft Graph API с managed identity в AWS. Ключевой момент — кэширование токенов:
import msal
import boto3
from botocore.exceptions import ClientError
class SharePointClient:
def __init__(self):
self.ssm = boto3.client('ssm')
self.token_cache = {}
def get_access_token(self, tenant_id, client_id, client_secret):
"""Получаем токен с кэшированием"""
cache_key = f"{tenant_id}_{client_id}"
if cache_key in self.token_cache:
token_info = self.token_cache[cache_key]
# Проверяем, не истек ли токен
if time.time() < token_info['expires_at'] - 300: # 5 минут запаса
return token_info['access_token']
# Получаем новый токен
app = msal.ConfidentialClientApplication(
client_id=client_id,
client_credential=client_secret,
authority=f"https://login.microsoftonline.com/{tenant_id}"
)
result = app.acquire_token_for_client(
scopes=["https://graph.microsoft.com/.default"]
)
if "access_token" in result:
self.token_cache[cache_key] = {
'access_token': result['access_token'],
'expires_at': time.time() + result['expires_in']
}
return result['access_token']
raise Exception(f"Failed to get token: {result.get('error_description')}")
Для извлечения данных из SharePoint используйте подход «сайт → список → элемент». Не пытайтесь скачать все сразу.
Векторный поиск с правами доступа: то, о чем молчат туториалы
Типичный туториал по RAG показывает, как закинуть текст в векторную базу и искать по косинусной близости. В корпорации это не работает.
Почему? Потому что сотрудник из отдела продаж не должен видеть техдокументацию для инженеров. А инженер поддержки не должен видеть финансовые отчеты.
Решаем через фильтрацию на уровне векторного поиска:
# Метаданные для каждого чанка
chunk_metadata = {
"id": "chunk_123",
"text": "...текст чанка...",
"source": "confluence:SPACE-123",
"source_type": "confluence",
"permissions": {
"departments": ["engineering", "support"],
"roles": ["backend", "devops"],
"projects": ["project-alpha"]
},
"last_updated": "2026-02-01T10:30:00Z"
}
# Поиск с фильтрацией по правам
def search_with_permissions(query, user_context, k=5):
"""Ищем чанки, доступные пользователю"""
# Генерируем эмбеддинг запроса
query_embedding = generate_embedding(query)
# Строим фильтр на основе контекста пользователя
permission_filter = {
"bool": {
"should": [
{"terms": {"permissions.departments": user_context.departments}},
{"terms": {"permissions.roles": user_context.roles}},
{"terms": {"permissions.projects": user_context.projects}}
]
}
}
# Ищем в OpenSearch с фильтром
search_body = {
"query": {
"script_score": {
"query": {
"bool": {
"must": permission_filter,
"filter": {
"knn": {
"embedding": {
"vector": query_embedding,
"k": k * 3 # Ищем больше, потом фильтруем
}
}
}
}
},
"script": {
"source": "_score * doc['relevance_boost'].value"
}
}
}
}
# Выполняем поиск
response = opensearch_client.search(
index="rag-index",
body=search_body
)
return response['hits']['hits'][:k]
Не храните права доступа в отдельной базе! При каждом поиске придется делать join, что убивает производительность. Храните permissions как часть метаданных вектора — фильтрация будет в 100 раз быстрее.
LLM в 2026: Claude 3.7 Sonnet или GPT-4.5 Turbo?
На момент написания (февраль 2026) у нас есть выбор. Мы тестировали:
- Anthropic Claude 3.7 Sonnet — отличное качество ответов, хороший контекст (200K токенов), но дороже
- OpenAI GPT-4.5 Turbo — быстрее, дешевле, но иногда «галлюцинирует» больше
- Amazon Bedrock с Mistral Large 2 — хороший баланс цены и качества, особенно если вся инфраструктура на AWS
Мы выбрали Bedrock по трем причинам:
- Данные не уходят за пределы AWS (compliance!)
- Интеграция с IAM для контроля доступа
- Predictable pricing без сюрпризов
Промпт-инжиниринг в корпоративной RAG — это отдельная наука. Базовый промпт:
RAG_PROMPT_TEMPLATE = """Ты — ассистент компании {company_name}.
Отвечай ТОЛЬКО на основе предоставленного контекста.
Если в контексте нет информации — скажи "Не могу найти информацию в базе знаний".
Контекст:
{context}
Вопрос: {question}
Ответ должен быть:
1. Кратким и по делу
2. С цитатами из контекста [1], [2]
3. Ссылками на исходные документы
Ответ:"""
Но это только начало. Добавьте:
- Инструкции по формату (маркдаун, списки)
- Запрет на выдумывание фактов
- Указание роли (техподдержка, продажи, разработка)
Чат-интерфейс, который не раздражает
Frontend — это не просто текстовое поле. Пользователи хотят:
- Видеть источники ответа (ссылки на Confluence/SharePoint)
- Возможность оценить ответ (thumb up/down)
- Историю диалогов
- Поиск по предыдущим ответам
Мы использовали React + AWS Amplify. Ключевой компонент — отображение источников:
function SourceBadge({ source, onClick }) {
const getSourceIcon = (type) => {
switch(type) {
case 'confluence': return '📘';
case 'sharepoint': return '📎';
case 'pdf': return '📄';
default: return '🔗';
}
};
const formatDate = (dateStr) => {
const date = new Date(dateStr);
const now = new Date();
const diffDays = Math.floor((now - date) / (1000 * 60 * 60 * 24));
if (diffDays === 0) return 'сегодня';
if (diffDays === 1) return 'вчера';
if (diffDays < 7) return `${diffDays} дня назад`;
if (diffDays < 30) return `${Math.floor(diffDays / 7)} нед. назад`;
return date.toLocaleDateString('ru-RU');
};
return (
{getSourceIcon(source.type)}
{source.title}
•
{formatDate(source.updated)}
);
}
Ошибки, которые мы совершили (чтобы вы их не повторили)
- Слишком мелкие чанки. Разбили все на куски по 256 токенов. Результат — контекст терялся. Оптимально — 512-1024 токена с перекрытием.
- Игнорировали таблицы и изображения. В Confluence полно таблиц с данными. Нужно было извлекать их структурированно, а не как plain text.
- Забыли про инкрементальное обновление. Первая версия переиндексировала все каждый день. Исправили на отслеживание изменений через webhooks.
- Не добавили feedback loop. Пользователи не могли сказать «этот ответ неправильный». Добавили через 3 месяца — качество сразу выросло на 40%.
Стоимость: сколько это стоит в реальности
Не верьте статьям «RAG за $10 в месяц». В корпорации:
- AWS OpenSearch (3 ноды t3.medium): $250/месяц
- AWS Lambda (10M вызовов): $200/месяц
- Amazon Bedrock (Claude 3.7 Sonnet, 100K запросов): $500-1000/месяц
- S3 для хранения исходников: $50/месяц
Итого: $1000-1500/месяц. Но один сэкономленный час инженера стоит $100. Если система экономит 20 часов в месяц — она окупается.
Что дальше? RAG в 2027
Система работает. Но технологии не стоят на месте. Смотрим на:
- Мультимодальность. Добавить поиск по скриншотам в документации, схемам, диаграммам.
- Agents. Не просто отвечать на вопросы, а выполнять действия: «Найди договор с X и вышли мне основные пункты».
- Real-time RAG. Интеграция с Slack/Microsoft Teams, где бот отвечает в реальном времени на вопросы в чатах.
Самое главное — система должна расти вместе с компанией. Сегодня это Confluence и SharePoint. Завтра — Jira, Salesforce, внутренние базы данных.
Архитектура, которую мы построили, позволяет добавлять новые источники за дни, а не за месяцы. И это ее главное преимущество.
Если хотите глубже погрузиться в тему, посмотрите нашу дорожную карту RAG 2026 — там все этапы от прототипа до production.