Как собрать RAG-платформу для работы с документами: архитектура, LangChain и уроки из продакшена
Инженер опубликовал open-source платформу для поиска ответов в документах с помощью нейросетей — разбираем архитектуру, инженерные компромиссы и реальные уроки, которые автор извлёк за годы работы с документоёмкими системами.
В типичном RAG-проекте гибнут не на этапе выбора языковой модели, а на настройке границ разбиения текста на чанки — и ни одна доработка промпта не исправит некорректное разбиение.
Задача: документы существуют, но не отвечают на вопросы
Почти в каждой крупной организации — будь то госструктура, регулируемое предприятие или сервисная компания — складывается одна и та же проблема. Информация формально «доступна»: она лежит в PDF-файлах, документах Word, отсканированных отчётах. Но чтобы найти конкретный пункт в 40-страничной политике или число с 22-й страницы комплаенс-отчёта, сотруднику приходится рыться вручную.
Автор проекта AI-DocumentIntelligence — инженер с многолетним опытом в построении документоёмких сервисов — утверждает, что наблюдал этот паттерн повсюду. Компании либо покупали закрытые коммерческие решения с непрозрачной ценообразованием и неясными условиями хранения данных, либо мирились с ручным поиском.
Выход — open-source платформа RAG (Retrieval-Augmented Generation), которую можно развернуть у себя и при необходимости сменить провайдера нейросети без переписывания кода.
Что такое RAG и зачем он здесь
RAG — это архитектурный паттерн, при котором языковая модель не генерирует ответ «из головы», а сначала извлекает релевантные фрагменты из базы знаний и отвечает на их основе. Это позволяет связать ответ с конкретным источником и снижает вероятность галлюцинаций — ситуаций, когда модель уверенно выдаёт выдумку за факт.
Платформа AI-DocumentIntelligence делает четыре вещи:
- Принимает загрузку документов (PDF, DOCX, TXT).
- Разбивает их на семантически осмысленные фрагменты (чанки).
- Преобразует чанки в векторные эмбеддинги и хранит их в PostgreSQL с расширением pgvector.
- Отвечает на вопросы на естественном языке, ссылаясь на исходные фрагменты.
Стек технологий
| Слой | Технология |
|---|---|
| Фронтенд | React 18 + TypeScript |
| Бэкенд | Node.js + Express + TypeScript |
| Оркестрация ИИ | LangChain |
| Векторное хранилище | PostgreSQL + pgvector |
| Языковые модели | OpenAI или Anthropic Claude (переключается переменной окружения) |
| Среда развёртывания | Docker, ts-node, dotenv |
Стек сознательно выбран консервативный — никаких экзотических зависимостей. Если в организации уже умеют запускать Node.js-сервис и PostgreSQL, этот проект не потребует изучения новой парадигмы развёртывания.
Архитектура: ничего революционного — и это плюс
Пайплайн обработки документов работает один раз при загрузке. Время ответа на вопрос — это стандартный цикл «найди, потом сгенерируй»: вопрос преобразуется в вектор, выполняется поиск ближайших соседей в pgvector, топ-K фрагментов передаётся выбранной языковой модели с инструкцией отвечать строго по ним, а результат возвращается пользователю вместе с историей диалога.
Автор прямо признаёт: ничего изобретательского. Ценность — не в оригинальной архитектуре, а в том, что скучные, но критичные вещи (абстракция провайдера, качество чанков, обработка ошибок при отсутствующих ключах API) сделаны корректно.
Ключевое архитектурное решение: абстракция провайдера LLM
Большинство туториалов по RAG хардкодят один провайдер — обычно OpenAI. В реальной эксплуатации, особенно в регулируемых отраслях, это тупик. Провайдер может понадобиться сменить из-за цены, требований к хранению данных, ограничений на юрисдикцию или просто простоя сервиса.
В AI-DocumentIntelligence смена модели — это чтение переменной окружения LLM_PROVIDER, а не переписывание кода в нескольких файлах. Весь слой выбора провайдера укладывается в компактный модуль, где на основе конфигурации возвращается нужный экземпляр (ChatOpenAI или ChatAnthropic). Простое, прозрачное, проверяемое.
Настраивая чанки: почему это важнее промптов
Автор использует рекурсивный текстовый сплиттер из LangChain с параметрами chunkSize: 1000 и chunkOverlap: 150. Это не случайные числа.
Перекрытие (overlap) — это зона, в которой соседние чанки частично дублируются. Слишком маленькое перекрытие — и ответ на вопрос может попасть на границу двух чанков, оказавшись разрезанным. Слишком большое — вы платите за встраивание и поиск одних и тех же предложений по нескольку раз.
Соотношение 150 на 1000 символов автор называет оптимальным по результатам тестирования на смешанном наборе PDF и DOCX. Это важный момент, который стоит принять к сведению: универсальных значений здесь нет. Оптимальные параметры зависят от структуры документов — юридические тексты с длинными абзацами и технические спецификации с табличными данными требуют разных подходов.
Чему научил опыт: три удачных решения
Разделение поиска и генерации. Архитектура позволяет тестировать этап извлечения фрагментов и этап генерации ответа независимо. Это критично при ограниченном бюджете: можно отлаживать качество поиска, не тратя кредиты на вызовы API генеративной модели.
Переключаемый провайдер с первого дня. Автор отлаживал пайплайн извлечения на бесплатных локальных моделях эмбеддингов, прежде чем подключать платные API для генерации. Итерации стоили практически ноль.
Docker Compose для всего стека. Фронтенд, бэкенд и PostgreSQL упакованы в единый docker compose up. Это кажется мелочью, но именно она определяет, воспользуется ли проект кто-то ещё или он так и останется «работает на моей машине».
Где проект натыкается на реальность
Три болевых момента, которые автор выделяет отдельно:
Зависимость от платных API при разработке. Строить RAG-систему без оплаченного тира OpenAI или Claude — это реальное ограничение, а не сноска. Решение: валидировать пайплайн извлечения на бесплатных локальных эмбеддингах, а платный вызов подключать только на финальном этапе. Паттерн, который стоит перенять любому, кто прототипирует RAG на ограниченном бюджете.
Настройка границ чанков — неблагодарная, но решающая работа. Никакая инженерия промптов не компенсирует плохо разбитый текст. Автор признаёт, что первоначально недооценивал этот фактор — и именно его исправление дало наибольший эффект из всех доработок.
«Работает у меня» ≠ «работает у другого». Корректный .env.example, явные ожидания по имени базы данных, задокументированные запасные варианты при конфликтах портов — всё это заняло больше времени, чем сама RAG-логика. Но именно эта часть определяет, сможет ли кто-то другой поднять проект за пять минут.
Стоит ли это внимания
Проект позиционируется как часть небольшого портфолио open-source AI-инструментов: помимо платформы для работы с документами, автор упоминает агентный бот для ревью Pull Request'ов, генератор пользовательских историй из голосовых записей и RAG-систему для гражданских сервисов.
Критический взгляд обязателен. Автор публикует на dev.to — платформе, где порог входа минимален, и качество проектов варьируется от учебных туториалов до продакшен-решений. Сам проект находится на начальной стадии: о масштабировании, нагрузочном тестировании, стратегии миграции базы данных и обработке документов с нестандартным форматированием в публикации не говорится. Стабильность pgvector на десятках миллионов векторов, поведение при одновременной загрузке сотен документов, защита от prompt-инъекций — всё это вопросы, на которые ответы пока не даны.
Тем не менее сам подход — прозрачная архитектура, минимальный стек, провайдерная независимость и акцент на нудных, но важных инженерных деталях — заслуживает внимания. Для команды, которой нужен прототип RAG-системы для внутренних документов и которая хочет понять, из чего он состоит, а не получить чёрный ящик, это может быть полезной отправной точкой.
Репозиторий доступен на GitHub: github.com/Srameshgitnow/AI-DocumentIntelligence. Проект можно поднять локально тремя командами — git clone, cd, docker compose up --build.