Skip to content

Repository files navigation

Backend магазина настольных игр CoilGames

Python FastAPI PostgreSQL Redis Docker

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', ...) обеспечивает морфологическую обработку русскоязычного запроса.

SQL-запрос гибридного ранжирования

SQL-запрос с Reciprocal Rank Fusion

Административная панель

SQLAdmin позволяет искать и фильтровать игры, управлять карточками, изображениями, ценами и доступностью товаров.

Управление каталогом игр в SQLAdmin

Dashboard администратора

Dashboard объединяет состояние заказов, очередь модерации пользовательского контента и показатели каталога.

Панель управления CoilGames

Редактор фрагментов правил

Отдельный chunk-editor используется для проверки автоматической разметки PDF-правил. Администратор может изменять границы и содержимое фрагментов, запускать повторную векторизацию и контролировать состояние индексации.

Редактор фрагментов правил настольных игр

AI-консультант

Консультант работает в трёх режимах:

Режим Назначение Источник контекста
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.

Архитектура

Архитектура компонентов CoilGames

Основной поток вызовов разделён на слои:

API (валидация, авторизация, HTTP)
  └── Services (бизнес-правила и оркестрация)
        └── CRUD (асинхронные запросы к данным)
              └── SQLAlchemy models

Все операции ввода-вывода выполняются асинхронно. Зависимости БД, Redis, S3, авторизации, кэша и rate limiter передаются через FastAPI Dependency Injection.

Диаграмма вариантов использования

Варианты использования CoilGames

Полная ER-диаграмма базы данных

Диаграмма открывается в полном разрешении по нажатию на изображение.

ER-диаграмма базы данных CoilGames

Технологии

Задача Инструменты
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.

1. Установить зависимости

poetry install

2. Запустить инфраструктуру

docker compose up -d pg redis minio pgadmin

3. Запустить сервис векторизации

AI-контур использует отдельный 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-сервиса — смешивание векторов разных моделей сделает семантический поиск некорректным.

Сервис векторизации доступен в этом репозитории

4. Создать app/.env

Минимальная конфигурация для запуска с локальным 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-режим.

5. Применить миграции и запустить API

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 запуститься, но запросы к чату завершатся ошибкой до восстановления провайдера.

Пример запроса к AI

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 для просмотра, редактирования и повторной векторизации фрагментов правил.

About

Async FastAPI backend for a board game store with RAG-powered AI consulting, semantic search, PostgreSQL/pgvector, Redis and MinIO.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages