inference_service

FastAPI-инференс ML-модуля: POST /predict, /predict/batch, /whatif/predict; GET /health, /metrics/model, /model/info; POST /reload.

Модель — ансамбль CatBoost из ml/artifacts/catboost_seed*.cbm (train_catboost.py --fit) плюс модели неопределённости: catboost_quantiles.cbm (интервал 10–90%, конформно откалиброван на 80% покрытия) и catboost_classes.cbm (вероятности early / ontime / late). Если моделей неопределённости нет — сервис работает на одном ансамбле, риск считается сигмоидой от задержки (как в контракте §7.1).

Онлайн-фичи строятся тем же кодом, что и в батче (features/tabular.build_features через point_features; быстрый путь без DataFrame, см. _features) — онлайн-прогноз совпадает с submission.csv.

Клиент шлёт сырой контекст: буфер телеметрии (пакеты с event_time <= T; более поздние сервис отбрасывает сам) и слайс планового расписания ТС. Если schedule не передан, берётся план ТС из SCHEDULE_PATH (если файл есть).

Запуск:

uvicorn inference_service:app --app-dir ml/src --host 0.0.0.0 --port 8001   # Swagger: /docs

Classes

BatchRequest(*args, **kwargs)

BatchResponse(*args, **kwargs)

Cause(*args, **kwargs)

HealthResponse(*args, **kwargs)

MetricsResponse(*args, **kwargs)

PredictRequest(*args, **kwargs)

PredictResponse(*args, **kwargs)

ScheduleStop(*args, **kwargs)

State()

Всё, что сервис держит в памяти.

TelemetryPing(*args, **kwargs)

TopFeature(*args, **kwargs)

WhatIfRequest(*args, **kwargs)

WhatIfResponse(*args, **kwargs)

class inference_service.BatchRequest(*args: Any, **kwargs: Any)[исходный код]

Базовые классы: BaseModel

requests: list[PredictRequest]
class inference_service.BatchResponse(*args: Any, **kwargs: Any)[исходный код]

Базовые классы: BaseModel

responses: list[PredictResponse]
class inference_service.Cause(*args: Any, **kwargs: Any)[исходный код]

Базовые классы: BaseModel

code: str
contribution_sec: float
text: str
class inference_service.HealthResponse(*args: Any, **kwargs: Any)[исходный код]

Базовые классы: BaseModel

model_version: str
n_features: int
n_models: int
status: str
uncertainty_models: bool = False
vehicles_in_schedule: int = 0
class inference_service.MetricsResponse(*args: Any, **kwargs: Any)[исходный код]

Базовые классы: BaseModel

latency_ms_p50: float | None = None
latency_ms_p95: float | None = None
mae_baseline_test_s: float | None = None
mae_baseline_train_s: float | None = None
mae_test_s: float | None = None
mae_train_s: float | None = None
model_version: str
n_features: int
n_models: int
requests_served: int = 0
score_estimate: float | None = None
class inference_service.PredictRequest(*args: Any, **kwargs: Any)[исходный код]

Базовые классы: BaseModel

T: str = Ellipsis
cur_dev_s: float = Ellipsis
sample_id: str
target_stop_id: int
target_time_begin: str = Ellipsis
tr_id: int
class inference_service.PredictResponse(*args: Any, **kwargs: Any)[исходный код]

Базовые классы: BaseModel

confidence: float
data_status: str = 'live'
delay_pred_sec: float = Ellipsis
horizon_ok: bool | None = None
latency_ms: float = 0.0
lead_min: float | None = None
model_version: str
off_route_m: float | None = None
p_early: float | None = None
p_late: float | None = None
p_ontime: float | None = None
reason_pattern: str
recommendation: str = Ellipsis
recommendation_text: str = ''
risk_level: str = 'green'
risk_score: float = Ellipsis
sample_id: str
top_features: list[TopFeature]
class inference_service.ScheduleStop(*args: Any, **kwargs: Any)[исходный код]

Базовые классы: BaseModel

building_address: str | None = None
geom: str
manual_fill: bool | str = 'false'
time_begin: str
tr_id: int
tt_action_item_id: int
class inference_service.State[исходный код]

Базовые классы: object

Всё, что сервис держит в памяти. load можно вызывать повторно (POST /reload).

__init__() → None[исходный код]
clf: catboost.CatBoostClassifier | None
latencies: deque
load() → None[исходный код]
meta: dict
metrics: dict
models: list[catboost.CatBoostRegressor]
plan_by_tr: dict[int, list[dict]]
q: catboost.CatBoostRegressor | None
stops_by_tr: dict
unc: dict
property version: str
class inference_service.TelemetryPing(*args: Any, **kwargs: Any)[исходный код]

Базовые классы: BaseModel

event_time: str
is_hist_data: int | bool = 0
lat: float | None = None
location_valid: bool | str = 'true'
lon: float | None = None
speed: float | None = None
tr_id: int
class inference_service.TopFeature(*args: Any, **kwargs: Any)[исходный код]

Базовые классы: BaseModel

contribution: float = 0.0
contribution_sec: float = 0.0
name: str
value: float | None = None
class inference_service.WhatIfRequest(*args: Any, **kwargs: Any)[исходный код]

Базовые классы: PredictRequest

scenario: str = Ellipsis
class inference_service.WhatIfResponse(*args: Any, **kwargs: Any)[исходный код]

Базовые классы: BaseModel

delay_baseline_sec: float
delay_scenario_sec: float
delta_sec: float
model_version: str
recommendation_still_applies: bool
risk_baseline: float
risk_scenario: float
sample_id: str
scenario: str
inference_service.health() → HealthResponse
inference_service.metrics_model() → MetricsResponse

Витринные метрики: MAE по схемам валидации, live-latency, покрытие интервала.

inference_service.model_info() → dict
inference_service.predict(req: PredictRequest) → PredictResponse
inference_service.predict_batch(batch: BatchRequest) → BatchResponse
inference_service.reload() → HealthResponse

Подхватить переобученные модели из ML_ARTIFACTS без перезапуска контейнера.

inference_service.whatif_predict(req: WhatIfRequest) → WhatIfResponse

«Что если применить сценарий»: эвристический сдвиг задержки, риск пересчитывается по интервалу модели.