16 KiB
AGENTS.md — гид для агента по проекту mlflow-practice
Этот файл — ориентир для любого AI-агента (и человека), который будет работать с проектом. Читай его первым при входе в репозиторий.
🎯 Назначение проекта
Учебный проект для изучения MLflow на практике: от логирования
экспериментов до Model Registry и serving моделей. Девять последовательных
уроков, каждый — отдельный скрипт в src/. Поддерживает GPU (RTX 3090, CUDA)
и macOS (Intel CPU / Apple Silicon MPS).
Не production-система. Цель — показать полный цикл MLOps на маленьких встроенных датасетах (digits, wine, MNIST).
📁 Карта проекта
mlflow-practice/
├── AGENTS.md # ← этот файл (поддерживай актуальным!)
├── README.md # пользовательская документация (как запускать)
├── CODE_WALKTHROUGH.md # подробный разбор каждого файла с пояснениями
├── MLproject # MLflow Projects: entry points main/gpu/sweep
├── python_env.yaml # окружение для MLproject (python 3.10)
├── requirements.txt # pip-зависимости
├── setup_server.sh # установка окружения (РАЗВИЛКА macOS/Linux)
├── start_ui.sh # запуск MLflow Tracking Server (UI на :5555, SQLite backend)
├── .gitignore
├── scripts/
│ └── setup_git.sh # настройка Git (HTTPS + токен)
├── src/ # ← весь код уроков здесь
│ ├── train_simple.py # Урок 1: sklearn + Tracking (ручное логирование)
│ ├── train_gpu.py # Урок 2: PyTorch CNN, CUDA→MPS→CPU
│ ├── register_model.py # Урок 3: Model Registry (версии, стадии)
│ ├── load_and_predict.py # Урок 4: загрузка модели + предсказание
│ ├── compare_runs.py # Урок 5: сравнение запусков через API
│ ├── autolog_demo.py # Урок 6: mlflow.autolog()
│ ├── hyperparam_sweep.py # Урок 7: перебор гиперпараметров вручную
│ ├── serve_model.py # Урок 8: REST API сервер модели (Flask)
│ └── grid_search_cv.py # Урок 9: GridSearchCV + autolog
├── data/ # датасеты (MNIST скачается автоматически)
├── artifacts/ # графики, отчёты (логируются в MLflow)
└── mlruns/ # старые запуски file-store (в .gitignore, не используется)
🧩 Роль каждого файла (кратко)
| Файл | Что делает | Датасет | Фреймворк |
|---|---|---|---|
train_simple.py |
RandomForest, ручное логирование params/metrics/model/artifacts | digits | sklearn |
train_gpu.py |
CNN, логирование по эпохам, выбор устройства get_device() |
MNIST | PyTorch |
register_model.py |
ищет лучший run по метрике, регистрирует модель, стадия Production | — | MLflow API |
load_and_predict.py |
грузит models:/digits_rf_model/Production, предсказывает |
digits | MLflow |
compare_runs.py |
MlflowClient.search_runs, топ-N по метрике |
— | MLflow API |
autolog_demo.py |
mlflow.autolog() для GradientBoosting |
wine | sklearn |
hyperparam_sweep.py |
ручной перебор комбинаций, --max-combos |
digits | sklearn |
serve_model.py |
Flask-сервер /predict, грузит модель из реестра |
digits | Flask + MLflow |
grid_search_cv.py |
GridSearchCV, autolog залогит каждую попытку |
digits | sklearn |
🖥️ Платформенная специфика
Выбор устройства в train_gpu.py
Функция get_device() определяет устройство в порядке:
CUDA → MPS (Apple Silicon) → CPU. Тег MLflow device_type хранит выбор
(cuda / mps / cpu) — по нему удобно фильтровать запуски в UI.
num_workers в DataLoader
На macOS с MPS многопроцессная загрузка нестабильна (fork + MPS),
поэтому num_workers=0 на Darwin и 4 на Linux. pin_memory=True
только для CUDA. Логика — в train_gpu.py рядом с DataLoader.
setup_server.sh — развивка по ОС
Darwin→ macOS: проверка Homebrew,python@3.12через brew, PyTorch из PyPI (без CUDA), проверкаtorch.backends.mps.is_available().Linux→ GPU-сервер:nvidia-smi, PyTorch из--index-url https://download.pytorch.org/whl/cu121, проверка VRAM.
При добавлении новой платформы — расширяй case "$OS" в начале скрипта.
🚀 Стандартные команды
# Окружение
bash setup_server.sh # установка (macOS или Linux)
source .venv/bin/activate
./start_ui.sh # MLflow UI → http://localhost:5555
# Уроки (в отдельном терминале, с активированным venv)
python src/train_simple.py --n-estimators 100 --max-depth 8
python src/train_gpu.py --epochs 5 --batch-size 128 --lr 0.001 # macOS/MPS
python src/register_model.py --experiment digits_classification
python src/load_and_predict.py
python src/compare_runs.py --experiment digits_classification --top 10
python src/autolog_demo.py
python src/hyperparam_sweep.py --max-combos 20
python src/serve_model.py --port 5001
python src/grid_search_cv.py
# Через MLflow Projects (изолированное окружение по MLproject)
mlflow run . -P n_estimators=100 -P max_depth=8
mlflow run . -P epochs=10 -P batch_size=256 -P lr=0.001 --entry-point gpu
🔧 Конвенции кода
- Датасеты — только встроенные (
load_digits,load_wine, MNIST черезtorchvision). Никаких внешних файлов вdata/, кроме скачанного MNIST. - Логирование — параметры/метрики/модель/артефакты. Графики сохраняются
в
artifacts/и логируются черезmlflow.log_artifact. - Имена экспериментов:
digits_classification,mnist_cnn_gpu,wine_autologи т.п. Модель в реестре —digits_rf_model. matplotlib.use("Agg")обязателен перед импортом pyplot — скрипты работают без GUI (на сервере).- Python ≥ 3.10 (см.
python_env.yaml). type hints опциональны. - CLI через
argparse— все скрипты с параметрами запускаются из CLI.
⚠️ Известные шероховатости / TODO
Нумерация уроков 8/9 расходилась между докстрингами и README/CODE_WALKTHROUGH— исправлено: канонserve_model.py=Урок 8 /grid_search_cv.py=Урок 9, README.md и CODE_WALKTHROUGH.md выровнены под докстринги (порядок секций тоже).requirements.txtвключаетtorch/torchvisionиз PyPI (CPU/MPS). Для CUDA их нужно ставить отдельно через--index-url .../whl/cu121(см.setup_server.sh, ветка Linux).- Порт MLflow UI = 5555 (не 5000): на macOS порт 5000 занят системным сервисом AirPlay Receiver (процесс
ControlCenter), поэтомуstart_ui.shиспользует 5555. На Linux можно вернуть 5000, но 5555 работает везде. - MLflow 3.x:
artifact_pathустарел — во всехlog_modelиспользуетсяname=...(былartifact_path=...). При обновлении/добавлении log_model не используйartifact_path. - Сигнатура модели:
train_simple.pyлогирует модель с явнойsignature=иinput_example=(черезmlflow.models.signature.infer_signature). Без этого MLflow пишет warning «Model logged without a signature and input example». train_gpu.pyпередаётinput_example→ сигнатура авто-infer'ится.autolog_demo.pyнамеренно отключает сигнатуры (log_model_signatures=False) как демо опций autolog — там warning ожидаем.- INFO про переменные окружения (
OPENAI_API_KEYи т.п.) при логировании подавлено черезMLFLOW_RECORD_ENV_VARS_IN_MODEL_LOGGING=falseв скриптах, логирующих модели. python -m venvпадает на Linux (ensurepip): на Debian/Ubuntu без пакетаpython3.13-venv(илиpython3-venv) создание venv падает на шагеensurepip(non-zero exit status 1).setup_server.shловит это и пробует fallback:venv --without-pip+ bootstrap pip черезget-pip.py. Альтернатива руками —sudo apt-get install -y python3.13-venv python3.13-dev.- File-store как tracking backend запрещён в MLflow 3.x (maintenance mode): падает и
mlflow server --backend-store-uri file://..., и клиент-скрипт с дефолтным./mlruns— оба сMlflowException ... in maintenance mode. Поэтому проект использует SQLite (sqlite:///mlflow.db) как tracking backend, а скрипты логируют на сервер по HTTP. Опциональный opt-outMLFLOW_ALLOW_FILE_STORE=trueНЕ используем (он может быть убран в будущем). Артефакты при этом лежат на локальном диске (./artifacts, file artifact repository — он НЕ в maintenance mode). input_exampleдляmlflow.pytorch.log_model— только numpy, неtorch.Tensor: MLflow 3.x валидирует пример входа и падает сMlflowException ... but got '<class 'torch.Tensor'>'. Вtrain_gpu.pyпередаётсяnp.random.rand(1,1,28,28).astype(np.float32). Аналогично для других flavor'ов — пример должен быть DataFrame/ndarray/dict/list/скаляр.- urllib3
NotOpenSSLWarningна macOS (системныйsslсобран с LibreSSL 2.8.3, urllib3 v2 просит OpenSSL 1.1.1+) — стороннее шумовое предупреждение, к проекту отношения не имеет; не подавляем (чтобы не прятать реальные предупреждения). - Доступ к UI с других машин (браузером по IP сервера) — НЕ удалять флаги в
start_ui.sh:--host 0.0.0.0,--allowed-hosts "*",--cors-allowed-origins "*",export MLFLOW_ALLOW_ORIGIN="*",--serve-artifacts+--artifacts-destination,--dev. Без--allowed-hosts "*"MLflow режет запросы сHost=<server-ip>:5555(UI не открывается удалённо); без--serve-artifactsUI на удалённой машине не скачает артефакты (model/графики) по file://-путям. Эти флаги были в исходном проекте и случайно потерялись при миграции — восстановлены. - Архитектура хранения (SQLite + HTTP-клиенты):
start_ui.shподнимает сервер с--backend-store-uri sqlite:///${PWD}/mlflow.db. Все скрипты вsrc/содержатmlflow.set_tracking_uri(os.environ.get("MLFLOW_TRACKING_URI", "http://localhost:5555"))— пишут на сервер. UI и скрипты работают с одной sqlite-базой → эксперименты сразу видны. Сервер должен быть запущен до запуска скриптов (иначеConnectionErrorк localhost:5555). Переопределить адрес:export MLFLOW_TRACKING_URI=http://<host>:5555(например, при логировании на удалённый сервер). mlruns/,artifacts/*,data/MNIST/,mlflow.db— в.gitignore, в репозиторий не попадают.
🔄 Когда обновлять этот файл
AGENTS.md — живой документ. Обновляй его при:
- Добавлении/удалении файла в
src/— обнови карту проекта и таблицу ролей. - Изменении платформенной логики (новое устройство, новая ОС в
setup_server.sh, изменениеget_device()илиnum_workers) — обнови раздел «Платформенная специфика». - Изменении имён экспериментов/моделей в реестре — обнови «Конвенции».
- Изменении зависимостей или версии Python (
requirements.txt,python_env.yaml) — проверь раздел команд и конвенции. - Появлении новых entry points в
MLproject— добавь в карту и команды. - Обнаружении gotcha/шероховатости — занеси в «Известные шероховатости», чтобы следующий агент не наступал повторно.
Правило простое: если ты что-то изменил в структуре/поведении проекта, отрази это в AGENTS.md в том же коммите. Если файл устарел относительно кода — это баг, который нужно исправить.
📌 Шпаргалка по MLflow API (часто используемое в проекте)
mlflow.set_experiment("name")
with mlflow.start_run(run_name="...") as run:
mlflow.log_param("k", v)
mlflow.log_metric("acc", 0.95, step=epoch)
mlflow.log_artifact("artifacts/curve.png")
mlflow.sklearn.log_model(model, "model") # sklearn flavor
mlflow.pytorch.log_model(model, "model") # pytorch flavor
mlflow.set_tag("device_type", "mps")
mlflow.autolog() # авто-логирование
# Model Registry
client = MlflowClient()
client.search_runs([experiment_id], order_by=["metrics.accuracy DESC"])
mlflow.register_model("runs:/<run_id>/model", "digits_rf_model")
client.transition_model_version_stage("digits_rf_model", version=1, stage="Production")
mlflow.pyfunc.load_model("models:/digits_rf_model/Production")
🧭 С чего начать новому агенту
- Прочитай этот файл целиком.
- Прочитай
README.md(пользовательский взгляд) иCODE_WALKTHROUGH.md(детальный разбор кода). - Прогони
bash setup_server.shна целевой платформе, чтобы понять состояние окружения. - Перед правками проверь
git status— в этом окружении.gitможет быть read-only для агента (тогда коммит делает пользователь вручную). - Любое структурное изменение → коммит + правка AGENTS.md.