Как построить RAG-пайплайн для корпоративных документов: архитектура и реализация

AI и LLM
Как построить RAG-пайплайн для корпоративных документов: архитектура и реализация

TL;DR: RAG-пайплайн для корпоративных документов — это связка векторного поиска и LLM, которая позволяет получать точные ответы на основе внутренней документации. Ключевые этапы: правильная обработка документов, качественное индексирование через embedding-модели и настройка промптов для генерации ответов.

Архитектура RAG-пайплайна

RAG (Retrieval-Augmented Generation) решает главную проблему корпоративных LLM-решений — как заставить модель работать с актуальными внутренними данными, а не только с тем, на чём она обучалась.

Типовая архитектура выглядит так:

Документы → Обработка → Chunking → Embedding → Векторная БД

Пользователь → Вопрос → Embedding → Поиск → Контекст → LLM → Ответ

Компоненты системы

Векторная база данных — сердце системы. Популярные варианты:

  • Pinecone (облачный, простой в настройке)
  • Weaviate (open-source, хорошая производительность)
  • Chroma (лёгкий для прототипирования)
  • pgvector (если уже используете PostgreSQL)

Embedding-модели для преобразования текста в векторы:

  • OpenAI text-embedding-ada-002 (универсальный выбор)
  • Sentence Transformers (для локального развёртывания)
  • Cohere Embed (хорошо работает с многоязычным контентом)

LLM для генерации ответов:

  • GPT-4 через API (высокое качество)
  • Claude (хорошо работает с длинным контекстом)
  • Локальные модели типа Llama 2 (для чувствительных данных)

Обработка корпоративных документов

Извлечение контента

Корпоративные документы приходят в разных форматах. Вот типовой стек для обработки:

# Пример обработки различных форматов
import PyPDF2
from docx import Document
import pandas as pd

def extract_text(file_path):
    if file_path.endswith('.pdf'):
        with open(file_path, 'rb') as file:
            reader = PyPDF2.PdfReader(file)
            text = ""
            for page in reader.pages:
                text += page.extract_text()
        return text
    
    elif file_path.endswith('.docx'):
        doc = Document(file_path)
        return '\n'.join([paragraph.text for paragraph in doc.paragraphs])
    
    elif file_path.endswith('.xlsx'):
        df = pd.read_excel(file_path)
        return df.to_string()

Chunking стратегии

Разбивка документов на части — критически важный этап. Слишком мелкие чанки теряют контекст, слишком крупные — ухудшают точность поиска.

Рекомендуемые подходы:

  1. Семантическое разбиение — по абзацам и разделам
  2. Фиксированный размер — 500-1000 токенов с перекрытием 100-200 токенов
  3. Гибридный подход — учитывает структуру документа
def semantic_chunking(text, max_tokens=800, overlap=150):
    # Разбиваем по абзацам
    paragraphs = text.split('\n\n')
    chunks = []
    current_chunk = ""
    
    for paragraph in paragraphs:
        if len(current_chunk + paragraph) > max_tokens:
            if current_chunk:
                chunks.append(current_chunk)
                # Добавляем перекрытие
                current_chunk = current_chunk[-overlap:] + paragraph
            else:
                current_chunk = paragraph
        else:
            current_chunk += "\n\n" + paragraph
    
    if current_chunk:
        chunks.append(current_chunk)
    
    return chunks

Настройка поиска и ранжирования

Гибридный поиск

Чистый векторный поиск не всегда оптимален для корпоративных документов. Эффективнее комбинировать:

  • Семантический поиск через embeddings
  • Лексический поиск (BM25) для точных терминов
  • Метаданные (дата, автор, тип документа)

Оптимизация релевантности

Несколько техник для улучшения качества поиска:

  1. Reranking — дополнительное ранжирование найденных чанков
  2. Query expansion — расширение запроса синонимами
  3. Фильтрация по метаданным — ограничение поиска по отделам/проектам
def hybrid_search(query, vector_db, bm25_index, top_k=10):
    # Векторный поиск
    vector_results = vector_db.similarity_search(query, k=top_k)
    
    # Лексический поиск
    bm25_results = bm25_index.search(query, k=top_k)
    
    # Комбинирование результатов
    combined_results = merge_and_rerank(vector_results, bm25_results)
    
    return combined_results[:top_k]

Генерация ответов и промпт-инжиниринг

Структура промпта

Качественный промпт для RAG-системы должен содержать:

Ты — AI-ассистент для работы с корпоративными документами [Компания].

КОНТЕКСТ:
{retrieved_chunks}

ИНСТРУКЦИИ:
1. Отвечай только на основе предоставленного контекста
2. Если информации недостаточно, честно об этом скажи
3. Указывай источники (название документа, раздел)
4. Используй корпоративную терминологию

ВОПРОС: {user_question}

ОТВЕТ:

Обработка edge cases

Важно предусмотреть сценарии:

  • Нет релевантных документов
  • Противоречивая информация в источниках
  • Запросы вне области компетенции
  • Запросы на конфиденциальную информацию

Мониторинг и улучшение качества

Метрики для отслеживания

  1. Точность поиска — релевантность найденных чанков
  2. Полнота ответов — процент вопросов с полными ответами
  3. Время отклика — латентность системы
  4. Удовлетворённость пользователей — через feedback

Continuous improvement

# Пример системы обратной связи
def collect_feedback(question, answer, chunks_used, user_rating):
    feedback_data = {
        'question': question,
        'answer': answer,
        'chunks': chunks_used,
        'rating': user_rating,
        'timestamp': datetime.now()
    }
    
    # Сохраняем для анализа и переобучения
    save_to_analytics_db(feedback_data)
    
    # Автоматическое улучшение на основе негативного фидбека
    if user_rating < 3:
        flag_for_review(feedback_data)

Безопасность и соответствие требованиям

Контроль доступа

RAG-система должна учитывать права пользователей:

  • Фильтрация по ролям — доступ только к разрешённым документам
  • Аудит запросов — логирование всех обращений
  • Анонимизация — удаление персональных данных из ответов

Обработка конфиденциальных данных

Если документы содержат чувствительную информацию:

  1. Локальное развёртывание LLM-моделей
  2. Шифрование векторных индексов
  3. Маскирование PII в ответах
  4. Ротация embedding-моделей при утечках

FAQ

Какой размер чанков оптимален для корпоративных документов? Обычно 500-1000 токенов с перекрытием 100-200 токенов. Для технической документации можно увеличить до 1500 токенов, для справочников — уменьшить до 300-500.

Как часто нужно переиндексировать документы? Зависит от частоты обновлений. Для активно изменяющихся документов — ежедневно, для стабильных корпоративных регламентов — еженедельно или по факту изменений.

Стоит ли использовать fine-tuning embedding-моделей? Да, если у вас специфическая терминология и достаточно данных (от 1000 пар вопрос-ответ). Иначе лучше сосредоточиться на качестве chunking и промптов.

Как обрабатывать документы с таблицами и схемами? Таблицы лучше конвертировать в структурированный текст или JSON. Для схем и диаграмм можно использовать multimodal модели типа GPT-4V или добавлять текстовые описания.

Какую векторную БД выбрать для production? Для начала — Pinecone (простота) или Weaviate (контроль). При больших объёмах и специфических требованиях — pgvector или custom решение на основе Faiss.

Нужна помощь с построением RAG-пайплайна? Напишите мне — обсудим ваш проект.

Обсудить проект

Есть идея или задача? Давайте обсудим, как можно её реализовать с помощью современных AI-технологий.

Написать мне
Вернуться к блогу