Backend e-commerce-платформы для продажи настольных игр. Проект объединяет каталог и поиск, корзину и заказы, управление остатками, пользовательский контент, программу лояльности и AI-консультанта на базе RAG.
Репозиторий содержит только backend. Клиентское приложение на React подключается к API отдельно.
- каталог игр с категориями, тегами, фильтрацией, полнотекстовым и семантическим поиском;
- рекомендации похожих игр на основе векторных представлений;
- корзина для гостя и авторизованного пользователя с объединением после входа;
- оформление заказов, управление статусами и остатками по магазинам;
- система уровней, опыта и персональных скидок;
- избранное, отзывы с изображениями, реакции, вопросы и ответы;
- загрузка изображений и PDF-файлов в S3-совместимое хранилище MinIO;
- cookie-аутентификация с сессиями в Redis и ролями
USER,MODERATOR,REDACTOR,ADMIN; - административная панель на SQLAdmin;
- ограничение частоты запросов и Redis-кэширование каталога и AI-ответов.
Обычный полнотекстовый поиск не находит игру по общему запросу «игра на вечер», тогда как семантический поиск подбирает релевантный результат по смыслу.
В режиме recommend векторный поиск по косинусному сходству и полнотекстовый поиск PostgreSQL выполняются параллельно. Первый улавливает смысловую близость, второй — точные совпадения по названиям, жанрам и ключевым словам. Затем результаты объединяются алгоритмом Reciprocal Rank Fusion:
RRF score = 1 / (60 + vector_rank) + 1 / (60 + fts_rank)
В отличие от взвешенной суммы скоров, RRF работает с позициями результатов, поэтому не требует нормализации разных шкал и подбора коэффициента. Оба канала реализованы CTE-выражениями в одном SQL-запросе и объединены через FULL OUTER JOIN: игра сохраняется в выдаче, даже если найдена только одним каналом. websearch_to_tsquery('russian', ...) обеспечивает морфологическую обработку русскоязычного запроса.
SQLAdmin позволяет искать и фильтровать игры, управлять карточками, изображениями, ценами и доступностью товаров.
Dashboard администратора
Dashboard объединяет состояние заказов, очередь модерации пользовательского контента и показатели каталога.
Отдельный chunk-editor используется для проверки автоматической разметки PDF-правил. Администратор может изменять границы и содержимое фрагментов, запускать повторную векторизацию и контролировать состояние индексации.
Консультант работает в трёх режимах:
| Режим | Назначение | Источник контекста |
|---|---|---|
recommend |
Подбор игры по предпочтениям пользователя | Каталог: гибридный векторный и полнотекстовый поиск |
rules |
Ответ на вопрос по правилам выбранной игры | Семантически релевантные фрагменты PDF |
first_move |
Объяснение подготовки и первого хода | Фрагменты правил по фиксированному поисковому запросу |
Перед обращением к LLM pipeline проверяет наличие и релевантность данных. Если контекста недостаточно или сервис векторизации недоступен, API возвращает безопасный статический ответ. Ответы о правилах и первом ходе кэшируются в Redis на 24 часа.
Поддерживаются три провайдера модели:
APP_PREFIX__AI__PROVIDER |
Провайдер | Основная настройка |
|---|---|---|
gigachat |
Sber GigaChat | APP_PREFIX__AI__GIGACHAT_AUTH_KEY |
gemini |
Google Gemini | APP_PREFIX__AI__GEMINI_API_KEY |
local |
локальная модель через Ollama | APP_PREFIX__AI__OLLAMA_BASE_URL |
Подробная настройка локальной модели описана в docs/ollama.md.
Основной поток вызовов разделён на слои:
API (валидация, авторизация, HTTP)
└── Services (бизнес-правила и оркестрация)
└── CRUD (асинхронные запросы к данным)
└── SQLAlchemy models
Все операции ввода-вывода выполняются асинхронно. Зависимости БД, Redis, S3, авторизации, кэша и rate limiter передаются через FastAPI Dependency Injection.
Полная ER-диаграмма базы данных
Диаграмма открывается в полном разрешении по нажатию на изображение.
| Задача | Инструменты |
|---|---|
| API | FastAPI, Pydantic v2, Uvicorn |
| Данные | PostgreSQL 16, pgvector, SQLAlchemy 2.0 async, asyncpg, Alembic |
| Сессии и кэш | Redis 7 |
| Файлы | MinIO, aioboto3 |
| AI / RAG | Google Gemini, GigaChat, Ollama, внешний embedding-сервис |
| Администрирование | SQLAdmin |
| Инфраструктура | Docker, Docker Compose, Poetry |
| Качество кода | Pytest, pytest-asyncio, Ruff, Black |
app/
├── admin/ # SQLAdmin: ресурсы, авторизация и шаблоны
├── ai/ # провайдеры LLM, prompts и RAG pipeline
├── alembic/ # миграции базы данных
├── api/ # REST endpoints и зависимости
├── core/ # конфигурация, исключения, auth и logging
├── crud/ # слой доступа к данным
├── db/ # PostgreSQL и Redis helpers
├── models/ # SQLAlchemy-модели
├── schemas/ # Pydantic-схемы
├── services/ # бизнес-логика
└── main.py # точка входа FastAPI
chunk-editor/ # отдельный сервис редактирования PDF-чанков
docs/ # дополнительная документация
tests/ # API-, service- и AI-тесты
docker-compose.yml # PostgreSQL, Redis, MinIO, pgAdmin и приложения
Понадобятся Python 3.13+, Poetry и Docker Compose.
poetry installdocker compose up -d pg redis minio pgadminAI-контур использует отдельный FastAPI-сервис векторизации. Его исходный код хранится в самостоятельном репозитории и локально располагается рядом с backend в каталоге ../vectorizer.
Сервис использует модель paraphrase-multilingual-mpnet-base-v2 и возвращает векторы размерностью 768:
| Метод | Endpoint | Назначение |
|---|---|---|
GET |
/health |
Проверка доступности и параметров модели |
POST |
/vectorize |
Векторизация одного текста |
POST |
/vectorize-batch |
Пакетная векторизация до 100 текстов |
GET |
/model-info |
Информация о загруженной модели |
После установки зависимостей в репозитории векторизатора запустите:
uvicorn embedder:app --host 0.0.0.0 --port 8001Проверка сервиса:
curl http://localhost:8001/healthПример ответа:
{
"status": "healthy",
"model": "paraphrase-multilingual-mpnet-base-v2",
"dimension": 768
}Сервис нужен не только во время общения с консультантом. До первого использования AI необходимо заполнить векторами каталог игр и загруженные фрагменты PDF. Для каталога в репозитории векторизатора предусмотрен скрипт standalone_embeddings.py. Модель, которой заполнена база, должна совпадать с моделью HTTP-сервиса — смешивание векторов разных моделей сделает семантический поиск некорректным.
Сервис векторизации доступен в этом репозитории
Минимальная конфигурация для запуска с локальным Ollama:
APP_PREFIX__DB__URL=postgresql+asyncpg://user:password@localhost:5432/cigshop
APP_PREFIX__ACCESS_TOKEN__RESET_PASSWORD_TOKEN_SECRET=change-me
APP_PREFIX__ACCESS_TOKEN__VERIFICATION_TOKEN_SECRET=change-me
APP_PREFIX__ADMIN__SECRET_KEY=change-me
APP_PREFIX__REDIS__HOST=localhost
APP_PREFIX__REDIS__PORT=6379
APP_PREFIX__S3__ENDPOINT=http://localhost:9000
APP_PREFIX__S3__PUBLIC_ENDPOINT=http://localhost:9000
APP_PREFIX__S3__ACCESS_KEY=minioadmin
APP_PREFIX__S3__SECRET_KEY=minioadmin
APP_PREFIX__S3__BUCKET_NAME=cigshop-files
APP_PREFIX__AI__PROVIDER=local
APP_PREFIX__AI__OLLAMA_BASE_URL=http://localhost:11434
APP_PREFIX__AI__OLLAMA_MODEL=qwen2.5:7b
APP_PREFIX__AI__EMBEDDING_SERVICE_URL=http://localhost:8001Для production-среды секреты следует генерировать отдельно, а cookie перевести в secure-режим.
cd app
poetry run alembic upgrade head
poetry run uvicorn main:main_app --reload --host 0.0.0.0 --port 8000После запуска доступны:
| Сервис | URL |
|---|---|
| Swagger UI | http://localhost:8000/docs |
| OpenAPI schema | http://localhost:8000/openapi.json |
| SQLAdmin | http://localhost:8000/admin |
| MinIO Console | http://localhost:9001 |
| pgAdmin | http://localhost:5050 |
Внешний embedding-сервис не входит в этот репозиторий. Без него основное e-commerce API продолжает работать, но семантический поиск и AI-консультант недоступны. Ollama требуется только при выборе провайдера local; недоступность LLM не мешает API запуститься, но запросы к чату завершатся ошибкой до восстановления провайдера.
Endpoint требует авторизованную cookie-сессию.
POST /api/v1/chat/send
Content-Type: application/json
{
"message": "Посоветуй кооперативную игру на четверых до 60 минут",
"mode": "recommend"
}Для вопросов по правилам передайте mode: "rules" и game_id. Для сценария первого хода используйте mode: "first_move" и game_id.
poetry run ruff check .
poetry run ruff format --check .Тесты используют async-сценарии и интеграции API:
cd app
poetry run pytest ../tests -vЧасть интеграционных тестов требует запущенных PostgreSQL, Redis, MinIO и embedding-сервиса.
- HNSW-индекс в pgvector для быстрого поиска по 768-мерным embedding-векторам.
- Redis sliding window для rate limiting: чат — 20 запросов в минуту, вход — 10 запросов за 5 минут.
- Инвалидация кэша после изменений каталога и игровых файлов.
- Единая иерархия прикладных исключений с централизованным преобразованием в JSON-ответы.
- Graceful degradation AI-контура: отсутствие релевантного контекста не приводит к лишнему вызову модели.
- Отдельный
chunk-editorдля просмотра, редактирования и повторной векторизации фрагментов правил.






