TL;DR: RAG-пайплайн для корпоративных документов — это система, которая находит релевантную информацию в базе знаний и генерирует ответы на её основе. Ключевые компоненты: препроцессинг документов, векторизация, поиск по сходству и генерация ответов через LLM.
Архитектура RAG-системы для корпоративных документов
RAG (Retrieval-Augmented Generation) решает главную проблему корпоративных LLM — отсутствие актуальной внутренней информации в обучающих данных. Вместо дообучения модели мы подаём ей контекст из собственных документов.
Типовая архитектура состоит из четырёх блоков:
Препроцессинг и индексация документов
- Парсинг: извлечение текста из PDF, DOCX, HTML, внутренних систем
- Чанкинг: разбивка на логические блоки (обычно 200-1000 токенов)
- Векторизация: преобразование текста в эмбеддинги
- Индексирование: сохранение в векторную БД
Поисковый модуль (Retriever)
- Векторный поиск по семантическому сходству
- Гибридный поиск (векторный + BM25)
- Ре-ранжирование результатов
Генеративный модуль (Generator)
- Формирование промпта с найденным контекстом
- Генерация ответа через LLM
- Постобработка и валидация
Система мониторинга
- Логирование запросов и ответов
- Метрики качества поиска
- A/B тестирование промптов
Выбор технологического стека
Векторные базы данных
Основные варианты для корпоративного использования:
| БД | Плюсы | Минусы | Когда использовать |
|---|---|---|---|
| Pinecone | Managed, быстрый | Дорого, vendor lock-in | MVP, быстрый старт |
| Weaviate | Open source, GraphQL | Сложнее в настройке | Гибкость, on-premise |
| Qdrant | Rust, производительность | Молодой проект | Высокие нагрузки |
| pgvector | PostgreSQL extension | Ограниченная функциональность | Есть PostgreSQL в стеке |
Модели для эмбеддингов
- OpenAI text-embedding-ada-002: универсальная, хорошее качество
- Sentence-BERT: open source, можно дообучить
- E5-large: отличное качество для русского языка
- multilingual-e5: для многоязычных документов
# Пример создания эмбеддингов с OpenAI
import openai
from typing import List
def create_embeddings(texts: List[str]) -> List[List[float]]:
response = openai.Embedding.create(
model="text-embedding-ada-002",
input=texts
)
return [item['embedding'] for item in response['data']]
Препроцессинг корпоративных документов
Стратегии чанкинга
Разбивка документов — критически важный этап. Плохой чанкинг убивает качество поиска.
Фиксированный размер (простой, но не оптимальный):
def fixed_chunk(text: str, chunk_size: int = 512, overlap: int = 50) -> List[str]:
chunks = []
start = 0
while start < len(text):
end = start + chunk_size
chunk = text[start:end]
chunks.append(chunk)
start = end - overlap
return chunks
Семантический чанкинг (лучше для качества):
- По структуре документа (заголовки, параграфы)
- По семантическим границам через sentence transformers
- Гибридный подход с учётом размера
Обработка метаданных
Сохраняйте структурированную информацию:
- Источник документа
- Дата создания/обновления
- Тип документа
- Департамент/автор
- Теги и категории
Это позволит фильтровать поиск и улучшить ранжирование.
Оптимизация качества поиска
Гибридный поиск
Комбинируйте векторный поиск с классическими методами:
def hybrid_search(query: str, vector_weight: float = 0.7):
# Векторный поиск
vector_results = vector_db.search(query, top_k=20)
# BM25 поиск
bm25_results = bm25_index.search(query, top_k=20)
# Комбинирование скоров
combined_results = combine_scores(
vector_results,
bm25_results,
vector_weight
)
return combined_results[:10]
Ре-ранжирование
После первичного поиска применяйте модели ре-ранжирования для улучшения порядка результатов:
- Cross-encoder модели (BERT-based)
- Учёт метаданных и бизнес-логики
- Персонализация по пользователю/роли
Query expansion
Расширяйте пользовательские запросы:
- Синонимы и связанные термины
- Переформулирование через LLM
- Исправление опечаток
Промпт-инжиниринг для генерации ответов
Структура эффективного промпта:
SYSTEM_PROMPT = """
Ты — корпоративный ассистент. Отвечай только на основе предоставленного контекста.
Если информации недостаточно, честно скажи об этом.
Всегда указывай источники информации.
"""
def build_prompt(query: str, context_chunks: List[str]) -> str:
context = "\n\n".join([
f"Источник {i+1}: {chunk}"
for i, chunk in enumerate(context_chunks)
])
return f"""
{SYSTEM_PROMPT}
Контекст:
{context}
Вопрос: {query}
Ответ:
"""
Техники улучшения промптов
- Chain-of-thought: попросите модель рассуждать пошагово
- Few-shot examples: добавьте примеры хороших ответов
- Constraint prompting: явно укажите ограничения и формат ответа
- Self-consistency: генерируйте несколько ответов и выбирайте лучший
Мониторинг и улучшение системы
Ключевые метрики
- Recall@k: доля релевантных документов в топ-k результатах
- Precision@k: доля релевантных среди возвращённых
- MRR (Mean Reciprocal Rank): средний обратный ранг первого релевантного результата
- NDCG: нормализованный дисконтированный кумулятивный выигрыш
Сбор обратной связи
Встройте механизмы оценки качества:
- Thumbs up/down для ответов
- Детальная оценка по критериям
- Логирование пользовательского поведения
- A/B тестирование разных подходов
# Пример логирования для анализа
import json
from datetime import datetime
def log_interaction(query: str, retrieved_docs: List, response: str,
user_feedback: Optional[int] = None):
log_entry = {
"timestamp": datetime.utcnow().isoformat(),
"query": query,
"retrieved_count": len(retrieved_docs),
"response_length": len(response),
"user_feedback": user_feedback,
"retrieval_scores": [doc.score for doc in retrieved_docs]
}
with open("rag_logs.jsonl", "a") as f:
f.write(json.dumps(log_entry) + "\n")
Масштабирование и производительность
Оптимизация скорости
- Кэширование: популярные запросы и эмбеддинги
- Батчинг: группировка запросов для эмбеддингов
- Асинхронность: параллельный поиск и генерация
- Индексы: правильная настройка векторной БД
Управление затратами
- Используйте более дешёвые модели для эмбеддингов
- Кэшируйте результаты LLM
- Оптимизируйте длину промптов
- Рассмотрите self-hosted решения для высоких нагрузок
FAQ
В: Какой размер чанка оптимальный для корпоративных документов? О: Зависит от типа документов. For технической документации — 200-400 токенов, для аналитических отчётов — 500-800. Тестируйте на своих данных и измеряйте качество поиска.
В: Как обрабатывать обновления документов? О: Стройте инкрементальную индексацию: отслеживайте изменения через хеши или timestamps, удаляйте старые чанки и добавляйте новые. Для критичных обновлений — полная переиндексация.
В: Стоит ли дообучать embedding модель на корпоративных данных? О: Если у вас специфичная терминология и достаточно данных (10K+ документов) — да. Иначе начните с готовых моделей и оптимизируйте другие компоненты пайплайна.
В: Как обеспечить безопасность корпоративных данных в RAG? О: Используйте role-based фильтрацию в метаданных, изолированные векторные БД по департаментам, аудит доступа. Для особо чувствительных данных — on-premise развёртывание всего стека.
В: Какую LLM выбрать для генерации ответов? О: GPT-4 для максимального качества, GPT-3.5-turbo для баланса цена/качество, Llama 2 или Claude для on-premise. Тестируйте на ваших данных — качество сильно зависит от домена.
Нужна помощь с построением RAG-системы? Напишите мне — обсудим ваш проект.