Сервис состоит из трёх пользовательских частей:
FastAPIбэкенд для управления пользователями, API-ключами, chat sessions и историей запросов.Streamlitинтерфейс, который работает только через REST API ьэкенд.Nginxреверс прокси с единой точкой входа и рейт-лимитинг для chat-эндпоинтов.
Инфраструктурные сервисы:
PostgreSQLдля постоянного состояния.Prometheusдля сбора метрик FastAPI.Grafanaс преднастроенным датасорсом и базовым дэшбордом.
Поток запросов:
Browser -> Nginx -> Streamlit UI
API поток:
Browser/UI -> Nginx(/api/*) -> FastAPI -> PostgreSQL
Мониторинг:
Prometheus -> FastAPI /metrics
Grafana -> Prometheus
Сети:
frontend_net:nginx,ui,apibackend_net:api,postgresmonitoring_net:api,prometheus,grafana
ui не имеет доступа к БД. nginx не имеет доступа к БД. Постоянные данные БД лежат в postgres_data, данные Grafana в grafana_data, директория под кэш/веса модели в model_cache.
- Создайте
.envпо примеру:
cp .env.example .env- Поднимите проект:
docker compose up --build -d- Сервисы доступны:
- приложение: http://localhost
- swagger backend через proxy: http://localhost:/api/docs
- prometheus: http://localhost:9090
- grafana: http://localhost:3000
Создание пользователя:
curl -X POST http://localhost:<port>/api/users \
-H 'Content-Type: application/json' \
-d '{
"username": "demo_user",
"email": "demo_user@example.com"
}'Выпуск API key:
curl -X POST "http://localhost:<port>/api/users/<user_id>/api-keys" \
-H 'Content-Type: application/json' \
-d '{
"name": "primary-key"
}'Создание chat session:
curl -X POST "http://localhost:<port>/api/users/<user_id>/sessions" \
-H 'Content-Type: application/json' \
-H 'X-API-Key: <token>' \
-d '{
"title": "Demo session"
}'Синхронный chat-запрос:
curl -X POST http://localhost:<port>/api/chat \
-H 'Content-Type: application/json' \
-H 'X-API-Key: <token>' \
-d '{
"session_id": 1,
"messages": [
{"role": "system", "message": "You are concise."},
{"role": "user", "message": "Say hello"}
],
"temperature": 0.7,
"max_tokens": 32
}'Стриминговый chat-запрос:
curl -N -X POST http://localhost:<port>/api/chat/stream \
-H 'Content-Type: application/json' \
-H 'X-API-Key: <token>' \
-d '{
"session_id": 1,
"messages": [
{"role": "user", "message": "Stream a short answer"}
],
"temperature": 0.7,
"max_tokens": 32
}'Grafana поднимается с готовым датасорсом Prometheus и дэшбордом AI Web Overview. На дэшборде есть:
- RPS
- latency p95
- число 5xx за последние 5 минут
- распределение запросов по эндпоинтам
Backend:
uv run alembic upgrade head
uv run uvicorn app.main:app --reload --port <port>Streamlit:
BACKEND_URL=http://localhost:<port> uv run streamlit run streamlit_app/app.py