Skip to content

07Rinat07/rag-platform

Repository files navigation

RAG Platform Backend

Бэкенд для асинхронной обработки документов и ответов через retrieval-augmented generation (RAG).

Назначение

Сервис решает две задачи:

  • прием и обработка документов (разбиение на чанки, генерация эмбеддингов, индексация);
  • ответы на вопросы с опорой на релевантные фрагменты документов.

Технологический стек

  • PHP 8.4, Laravel 12
  • MySQL 8 (основные сущности и метаданные очередей)
  • PostgreSQL 16 + pgvector (векторы и поиск похожих фрагментов)
  • Redis (очереди и кэш ответов)
  • Nginx + PHP-FPM
  • Supervisor (воркеры очередей)
  • OpenAI API через Laravel HTTP Client (без SDK)
  • L5 Swagger (OpenAPI-документация)

Архитектура

Код разделен по слоям:

  • app/Domain — контракты и value objects;
  • app/Application — application services и use-case логика;
  • app/Infrastructure — внешние адаптеры (OpenAI, pgvector, queue jobs);
  • app/Http — API-контроллеры и middleware.

Ключевые зависимости инвертированы через интерфейсы:

  • AIClientInterface -> OpenAIClient
  • EmbeddingRepositoryInterface -> PgVectorEmbeddingRepository

Привязки находятся в app/Providers/AppServiceProvider.php.

Хранилища и схема данных

MySQL (default connection)

  • documents: id, title, path, status, error, timestamps
  • document_chunks: id, document_id, position, content, timestamps
  • уникальность чанка: (document_id, position)

Жизненный цикл документа: queued -> processing -> ready или failed.

PostgreSQL (connection vectors)

Таблица embeddings:

  • id (bigserial primary key)
  • document_id (bigint)
  • chunk_id (bigint unique)
  • dim (smallint)
  • embedding (vector(<dimension>))
  • timestamps

Индексы:

  • HNSW по embedding с vector_cosine_ops
  • btree по document_id

Поток обработки документа

  1. POST /api/v1/documents сохраняет файл и создает запись в documents со статусом queued.
  2. ProcessDocumentJob переводит документ в processing, читает файл, режет текст на чанки, выполняет upsert в document_chunks.
  3. Для документа удаляются старые записи embeddings в PostgreSQL.
  4. Создается batch из GenerateEmbeddingForChunkJob (очередь embeddings).
  5. Каждый job получает эмбеддинг через AIClientInterface и делает upsert по chunk_id.
  6. Batch завершает документ статусом ready или failed (с текстом ошибки).

Поток RAG-запроса

Реализован в app/Application/Services/RagAnswerService.php:

  1. валидация входа;
  2. проверка кэша Redis;
  3. генерация эмбеддинга вопроса;
  4. searchTopK по cosine similarity (опционально с фильтрацией по document_id);
  5. загрузка контента чанков из MySQL и сборка контекста;
  6. chat completion;
  7. кэширование ответа на короткий TTL.

API

Базовый префикс: /api/v1

Метод Путь Назначение
POST /documents Загрузка файла и постановка в очередь обработки
GET /documents/{id}/status Получение статуса обработки документа
POST /chat/query RAG-запрос к документам

Коды ответов:

  • POST /documents: 202, 422
  • GET /documents/{id}/status: 200, 404, 422
  • POST /chat/query: 200, 422

OpenAPI / Swagger

Интеграция реализована через darkaonline/l5-swagger.

  • аннотации: app/OpenApi/V1Documentation.php
  • конфигурация: config/l5-swagger.php
  • UI: /api/documentation

Генерация спецификации:

php artisan l5-swagger:generate
# или
composer swagger:generate

Переменные окружения

Основные группы:

  • Core DB: DB_*
  • Vector DB: VECTORS_DB_* (есть fallback на EMBEDDINGS_DB_*)
  • OpenAI: OPENAI_*
  • RAG: RAG_*
  • Queue/Cache: QUEUE_CONNECTION, REDIS_*, CACHE_STORE
  • Swagger: L5_SWAGGER_*

Полный перечень — в .env.example.

Установка и запуск локально

Требования:

  • PHP 8.4+
  • Composer 2+
  • MySQL 8+
  • PostgreSQL 16+ с расширением pgvector
  • Redis 7+

Подготовка:

cp .env.example .env
composer install
php artisan key:generate

В PostgreSQL должен быть включен pgvector:

CREATE EXTENSION IF NOT EXISTS vector;

Миграции (MySQL + vectors connection):

php artisan migrate --force

Запуск API и воркера:

php artisan serve --host=0.0.0.0 --port=8000
php artisan queue:work redis --queue=documents,embeddings --sleep=1 --tries=3 --timeout=120

Запуск в Docker

Подготовка:

cp .env.example .env

Укажите APP_KEY в .env (формат base64:...), затем:

docker compose up -d --build
docker compose exec app php artisan migrate --force
docker compose exec app php artisan l5-swagger:generate

Проверка:

  • API: http://localhost:${APP_PORT:-8080}/api/v1/...
  • Swagger UI: http://localhost:${APP_PORT:-8080}/api/documentation
  • health endpoint: http://localhost:${APP_PORT:-8080}/up

Операционные команды:

docker compose ps
docker compose logs -f app queue nginx
docker compose exec app php artisan test
docker compose down

Очереди и масштабирование

  • backend очередей: Redis (QUEUE_CONNECTION=redis);
  • очереди: documents и embeddings;
  • fan-out/fan-in реализован через Laravel batch processing;
  • в Docker queue контейнер запускает workers через Supervisor (docker/supervisor/queue-worker.conf).

Горизонтальное масштабирование:

  • увеличивать число workers для embeddings;
  • держать ограниченную конкуренцию для documents (CPU/IO bound задачи);
  • разделять HTTP runtime и queue runtime.

Тестирование

Набор тестов:

  • feature: загрузка документа, статус, RAG endpoint;
  • unit: RagAnswerService;
  • test doubles: tests/Fakes/FakeAIClient.php, tests/Fakes/FakeEmbeddingRepository.php.

Тесты не делают внешних API-вызовов и выполняются детерминированно.

Запуск локально:

php artisan test

Запуск в Docker:

docker compose exec app php artisan test

Логирование API-запросов

ApiRequestLoggingMiddleware логирует:

  • HTTP-метод;
  • путь;
  • IP клиента;
  • время выполнения (мс).

Middleware подключен к API в bootstrap/app.php.

About

Бэкенд для асинхронной обработки документов и ответов через retrieval-augmented generation (RAG).

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages