За 8 дней частичной занятости я собрал RAG-систему на NestJS + PostgreSQL (pgvector), которая обрабатывает ~11 000 чанков документов.
Первая версия отвечала около 4 минут, после оптимизации – 40–60 секунд.
Главный вывод: RAG – это не «векторный поиск + LLM», а в первую очередь подготовка данных, фильтрация контекста и аккуратная работа с промптами.
Зачем я это делал
Главной целью проекта было создать RAG-систему, которая могла бы отвечать на вопросы на основе моих знаний и опыта, это позволило понять реальную работу с большим количеством документов.
RAG-система была интегрирована с моим сайтом-визиткой site15.ru. Там я показываю и описываю часть проектов за последние 10 лет: скачивания, звёзды, просмотры, npm-библиотеки, счётчики групп, посты и карму на Habr и dev.to.
Технически это реализовано так: фронтенд site15.ru → backend site15.ru → сервер rag-system. Backend передаёт специальный API-ключ, что хотя бы частично защищает сайт от лишних запросов.
Таким образом, site15.ru выступает как демо и интерфейс для взаимодействия с RAG.
Почему RAG оказался сложнее, чем казалось
На старте проект выглядел просто:
RAG = векторный поиск + LLM
На практике оказалось, что большая часть времени уходит на:
-
подготовку и сегментацию данных,
-
фильтрацию контекста,
-
формирование и согласование промптов.
Первая версия системы делала всё последовательно – и отвечала около 4 минут даже на простой вопрос.
Архитектура системы
Источники данных (Telegram переписки, статьи, портфолио, резюме)
↓
Backend (NestJS)
├─ LLM-модуль
├─ PostgreSQL + pgvector
├─ RxJS асинхронный pipeline
├─ Dialog Manager
└─ API контроллер для site15.ru
↓
RAG-компоненты
├─ Question Transformer
├─ Фильтрация документов и секций
├─ Векторный поиск
└─ Формирование промпта
↓
LLM-провайдеры
(OpenAI / Groq / Ollama)
Выбор стека
Backend – NestJS
Я постоянно пишу бэкенды на NestJS, поэтому выбор очевиден.
Frontend – React Admin
Нужна была админка, чтобы управлять данными и промптами.
PostgreSQL + pgvector
Одна система для обычных данных и векторов – проще и надежнее, чем раздельные хранилища.
Несколько LLM-провайдеров
Поддержка разных провайдеров позволяет использовать бесплатные лимиты и легко переключаться при необходимости.
Ключевое архитектурное решение: иерархическая фильтрация
Главная идея – не отправлять в LLM всё подряд.
Pipeline обработки запроса:
Запрос пользователя (frontend site15.ru)
↓
Backend site15.ru
↓
RAG-сервер: нормализация вопроса
↓
Фильтрация по метаданным (11 000 → ~500)
↓
Фильтрация по секциям/заголовкам (500 → ~200)
↓
Векторный поиск (200 → 5–10)
↓
Один оптимизированный запрос в LLM
Так удалось значительно сократить объём данных, отправляемых в LLM, и ускорить ответы.
Самая большая техническая проблема
Создание метаданных для 11 005 чанков документов.
Так как я хотел, чтобы всё работало, используя только бесплатные лимиты LLM, я не мог создавать метаданные в облачных LLM — там я быстро упирался в ограничения, поэтому пришлось запускать локально через LM Studio с моделью qwen2.5-7b-instruct и обработка заняла 2 дня на RTX 2060 SUPER.
Почему первая версия была медленной
Первая версия: 8 промежуточных промптов, последовательные вызовы LLM → ~4 минуты на ответ.
После оптимизации: 4 согласованных промпта, часть этапов параллельна, асинхронная очередь на RxJS → 40–60 секунд.
Промпты и ошибки
Промпты оказались самым сложным моментом. Примеры:
Утечка контекста
Пользователь: "Расскажи про NestJS"
LLM: "NestJS - отличный фреймворк. Кстати, у меня есть телеграм-бот для кофе..."
Конфликт инструкций
Промпт 1: отвечай кратко
Промпт 2: приводи подробные примеры
Вывод: меньше, но согласованных промптов – лучше.
Использование ИИ при разработке
Около 70% кода писалось с помощью ИИ-ассистентов, но без моей архитектурной правки и отладки он не работал бы.
Безопасность
-
проверка разрешённого IP,
-
проверка API-ключа для запросов с backend site15.ru.
Проект не production-ready, но это позволяет хоть как-то защитить основной сайт от лишних запросов.
Развёртывание
-
RAG-сервер на отдельном VPS,
-
docker-composeдля PostgreSQL и Ollama, -
backend через
pm2, -
интеграция с site15.ru.
Текущий статус
Экспериментальный проект, не MVP, не production-ready.
Site15.ru выступает как интерфейс для демонстрации работы RAG и статистики проектов.
Планы на будущее
-
Написание тестов пользовательских сценариев (проверка корректности ответов и pipeline).
-
Рефакторинг LLM-модуля в стиле NestJS.
-
Добавление аналитики: время обработки, количество вызовов LLM, расход токенов.
-
Автоматизация деплоя через Docker / Kubernetes.
-
Улучшение точности и скорости через оптимизацию фильтрации контекста.
Выводы
RAG – это сложный инженерный процесс: подготовка данных, фильтрация контекста и аккуратная работа с промптами важнее, чем сама LLM.
За 8 дней частичной занятости удалось собрать рабочую систему, интегрировать её с site15.ru и получить реальный опыт работы с RAG.
Ссылки
https://github.com/site15/rag-system – Репозиторий проекта
https://site15.ru – Мой сайт визитка с чатом поддержки
Автор: kaufmanendy


