Шаблон FastAPI приложения для анализа сентимента текста.
# Установить Just (command runner)
# macOS
brew install just
# vscode plugin https://github.com/nefrob/vscode-just
# Посмотреть доступные команды
just
# Создать venv и установить зависимости
just setup
# Запустить dev сервер
just dev
# Создать релиз
just release 1.0.0Приложение будет доступно на http://localhost:8787
| Команда | Описание |
|---|---|
just |
Показать все команды |
just setup |
Создать venv + зависимости |
just dev |
Запустить dev сервер |
just check |
Проверить код (lint + format) |
just fix |
Исправить код (lint + format) |
just build |
Собрать Docker образ |
just up |
Запустить docker-compose |
just down |
Остановить docker-compose |
just release X.X.X |
Создать релиз (тег + push) |
При пуше тега вида v*.*.* автоматически:
- Собирается Docker образ
- Публикуется в GitHub Container Registry
- Создаётся GitHub Release с changelog
- Деплоится на сервер через SSH
Рекомендация: делайте репозиторий публичным — тогда сервер сможет пулить образы из GHCR без авторизации.
Для приватного репозитория на сервере нужно один раз залогиниться:
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
| Секрет | Описание |
|---|---|
PROD_SSH_HOST |
Адрес сервера |
PROD_SSH_USER |
SSH пользователь |
PROD_SSH_KEY |
SSH приватный ключ |
Модели загружаются при старте приложения и кэшируются в persistent volume model_cache.
- Отредактируй
app/models.py— функцияload_model() - Добавь зависимости в
pyproject.toml
Пример с HuggingFace:
from transformers import pipeline
def load_model():
return pipeline("text-classification", model="your-model-name")Некоторые модели на HuggingFace требуют авторизации:
- Создай токен на https://huggingface.co/settings/tokens
- Прими лицензию модели на её странице HF
Локальная разработка:
export HF_TOKEN=hf_xxxxxxxxxxxxx
just upProduction (GitHub Actions):
Добавь секрет HF_TOKEN в Settings → Secrets → Actions.
| Секрет | Описание |
|---|---|
HF_TOKEN |
HuggingFace токен (опционально, для gated моделей) |
from fastapi import Request
@app.post("/predict")
async def predict(request: Request, text: str):
model = request.app.state.model
return model(text)GET /health- Health checkPOST /sentiment?text=your+text- Анализ сентимента
curl -X POST "http://localhost:8787/sentiment?text=hello world"Ответ:
{"text": "hello world", "label": "POSITIVE", "score": 0.9998}