# Сервис предсказания цен Веб-сервис предсказания цен на подержанные автомобили. Мониторинг в комплекте. Обзор сервисов (по `compose.yaml`, см. о развёртывании ниже): | Профили Compose | Имя | Объекты | Описание | |-----------------|------------------|------------------|------------------| | — | `prices-predictor` | код: `ml_service/` | Веб-сервис предсказания цен, только stateless API. Об используемой предсказательной модели см. `research/README.md`. | | — | `prometheus` | конфигурация: `prometheus/` | Мониторинг сервиса ([Prometheus](https://prometheus.io/)). | | — | `grafana` | сохранённая конфигурация: `grafana/` | Аналитика и визуализация данных мониторига сервиса ([Grafana](https://grafana.com/)). | | `with-testers` | `load-tester` | код: `load-tester/` | Генератор потока случайных запросов к `prices-predictor` для тестирования. | Дополнительно: * `models/` — расположение файла модели `model.pkl` для использования сервисом `prices-predictor`. * `fetch_model_as_pickle_from_mlflow.py` — скрипт для экспорта предиктивной модели scikit-learn из MLFlow в файл. ## API сервиса предсказания цен **Базовый URL**: `/api`. Все указанные далее URL записаны **относительно базового URL**, если не указано иное. * Полная интерактивная документация (Swagger UI): `/docs`. * Предсказать цену подержанного автомобиля: `/predict` (POST). Пример запроса: * requst query: `item_id=16` (параметр `item_id` необходим!); * request body: ```json { "selling_price": 5.59, "driven_kms": 27000.0, "age": 5.0, "fuel_type": "petrol", "selling_type": "dealer", "transmission_type": "manual" } ``` * response body: ```json { "item_id": 16, "price": 3.743508852258851 } ``` * Тестовый эндпоинт: `/` (GET). Возвращает простой демонстрационный объект JSON. Может использоваться для проверки состояния сервиса. ## Мониторинг ### Prometheus UI #### Примеры запросов Гистограмма предсказанных цен `model_prediction_value_bucket` (запрос: `rate(model_prediction_value_bucket[5m]`): ![Гистограмма предсказанных цен как временные ряды](docs/screenshot-prometheus-query-model-1.png) Гистограмма продолжительности предсказания цен моделью ML `model_prediction_seconds_bucket` (запрос: `rate(model_prediction_seconds_bucket[5m]`): ![Гистограмма продолжительности предсказания цен моделью ML как временные ряды](docs/screenshot-prometheus-query-model-2.png) Интенсивность потока запросов к сервису предсказания цен с разными результатами (успех — коды HTTP `2xx`, ошибки со стороны клиента — коды HTTP `4xx`) `http_requests_total{handler="/predict"}` (запрос: `rate(http_requests_total{handler="/predict"}[5m]`): ![Интенсивность потока запросов к сервису предсказания цен с разными результатами](docs/screenshot-prometheus-query-http-1.png) Интенсивность потока запросов к **веб-серверу** сервиса предсказания цен **с ошибками** `http_requests_total{handler="/predict"}` (запрос: `sum without(handler, method) (rate(http_requests_total{status=~"4..|5.."}[5m]))`): ![Интенсивность потока запросов к веб-серверу сервиса предсказания цен, заканчивающихся ошибками](docs/screenshot-prometheus-query-http-1.png) ### Дашборд в Grafana Дашборд экспортирован в файл: `grafana/objects/dashboard-1765200932880.json`. ![Дашборд в Grafana](docs/screenshot-grafana-dashboard.png) Элементы: * мониторинг модели: * гистограмма распределения предсказанных цен за период времени (10 мин); * прикладной уровень: * интенсивность потока запросов (всех запросов; запросов, заканчивающихся ошибкой); * инфраструктурный уровень: * состояние сервиса (up/down); * выделенный процессу объём VRAM. ## Развёртывание ### Файл модели Файл используемой предсказательной модели можно извлечь из MLFlow скриптом `models/fetch_model_as_pickle_from_mlflow.py`. Файл модели можно размещается в `models/model.pkl`. Например, извлечь модель по имени (``) и версии (``) (например, `UsedCardPricePredictionFinal/1`) (команда запускается из корневой директории проекта — от этого зависит путь к создаваемому файлу): python services/models/fetch_model_as_pickle_from_mlflow.py --model "models://" services/models/model.pkl Можно указать адрес tracking сервера MLFlow, например: `--tracking-uri "http://localhost:5000"`. Информация о других опциях доступна: python services/models/fetch_model_as_pickle_from_mlflow.py --help ### Образы Docker #### `ml_model` (для сервиса `prices-predictor`) **Сборка образа** (замените `` на номер версии) (команда запускается из корневой директории проекта — от этого зависит путь к директории): docker build -t ml_service: services/ml_service/ **Независимый запуск** (замените `` на номер версии образа, `` на **абсолютный** путь к директории, где размещён файл предсказательной модели `model.pkl`, `` на порт для запуска веб-сервиса (например, `8000`)): docker run -v ":/models" -p :8000 ml_service: Модель может быть размещена в `models/`; тогда, например, при запуске команды из корна проекта: `$(pwd)/services/models` (здесь `$(pwd)` используется потому, что необходим абсолютный путь). #### `load-tester` (для сервиса `load-tester`) **Сборка образа** (замените `` на номер версии) (команда запускается из корневой директории проекта — от этого зависит путь к директории): docker build -t load_tester: services/load_tester/ **Независимый запуск** (замените `` на номер версии образа, `` на базовый URL сервиса `prices-predictor` (например, `http://prices-predictor:8000/api`)): docker run -e "API_BASE_URL=" ml_service: ### Развёртывание сервиса посредством Compose Конфигурация описана в файле `compose.yaml`. Имя системы: `mpei-iis-system`. Рекомендуется (не обязательно) использовать env-файл `compose.env`. Используйте файл `compose.env.template` как шаблон. **Директория `models/` используется сервисом `prices-predictor` как том** с файлом модели `model.pkl`. Поместите туда файл модели, см. [Файл модели](#файл-модели). **Управление сервисом с мониторингом** (замените `` и `[options...]`): docker compose -f services/compose.yaml --env-file services/compose.env [options...] **Для запуска вместе с генераторами тестовых запросов** используйте опцию compose `--profile=with-tester`. Основные команды `docker compose`: * `up`: создать и запустить контейнеры (также тома, сети и прочее); оставляет вывод логов прикреплённым к терминалу, `SIGINT` останавливает контейнеры, **но не удаляет созданные объекты**; * опция `-d`: то же, но открепляет процесс от терминала. * `down`: остановить и удалить контейнеры (также сети и прочее; для удаления томов используйте опцию `-v`). * `start`: запустить существующие контейнеры. * `stop`: остановить контейнеры. * `restart`: перезапустить контейнеры. **Открытые на хосте интерфейсы**: * `localhost:8010`: Сервис `prices-predictor`. Базовый URL: `/api`. * `localhost:9090`: UI Prometheus. * `localhost:3000`: Grafana. **Доступные на хосте тома**: * `mpei-iis-system_prometheus-storage`: БД Prometheus. * `mpei-iis-system_grafana-storage`: БД Grafana.