Зачем это нужно
Inference-сервис должен запускаться одинаково у разработчика, в CI и в контейнере. Случайный набор пакетов в глобальном Python превращает воспроизводимость в лотерею.
Основные идеи
pyproject.toml — точка описания проекта: имя, версия, зависимости и настройки инструментов. Не храните эти сведения только в README.
Виртуальное окружение изолирует зависимости проекта:
python -m venv .venv source .venv/bin/activate python -m pip install -e ".[dev]"
Lockfile фиксирует точные версии транзитивных зависимостей. pyproject.toml говорит, что проекту нужно; lockfile — какие пакеты были реально проверены вместе.
Модули и границы. Код сервиса обычно разделяют на api, domain/service, model и settings; HTTP-обработчик не должен содержать всю ML-логику.
Typing и logging. Аннотации делают контракт функций явным, а структурированные логи помогают расследовать запрос в production. Не логируйте секреты и персональные данные.
Как это выглядит на практике
Минимальная структура:
src/churn_service/ api.py # FastAPI routes predictor.py # загрузка модели и predict settings.py # переменные окружения tests/ pyproject.toml
Контракт функции легко читать:
def predict(features: list[float]) -> float: logger.info("predict_requested", extra={"feature_count": len(features)}) return model.predict_proba([features])[0, 1]
В CI создаётся новое окружение и зависимости ставятся из lockfile. Если это не проходит, «у меня локально работает» не считается релизом.
Что сделать после занятия
Создайте
.venvдля учебного проекта и добавьте её в.gitignore.Перенесите метаданные и зависимости проекта в
pyproject.toml.Добавьте одну типизированную функцию и один полезный log без PII.