This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
uvicorn ml_rest_fastapi.app:app --host 0.0.0.0 --port 8888 --reloadgunicorn -c gunicorn.conf.pypytest tests/pytest tests/basic_test.py::test_get_liveness_status_code_equals_200bash make.sh
# or on Windows PowerShell:
# ./make.ps1This runs black (formatting), pylint (linting), and mypy (type checking) in sequence.
black ./ml_rest_fastapi ./tests
pylint --recursive=y ./ml_rest_fastapi ./tests
mypy --pretty --config-file=mypy.ini ./ml_rest_fastapirequirements.txt— runtime dependencies (install withpip install -r requirements.txt)requirements-dev.txt— dev tooling: black, pylint, mypytests/requirements.txt— test dependencies: pytest, requests, openapi-spec-validator
The core design pattern is a plugin-style model wrapper: TrainedModelWrapper (trained_model/wrapper.py) dynamically imports a Python module from trained_model/ at startup and binds four callables from it: init(), teardown(), run(data), and sample(). The active module is chosen by the TRAINED_MODEL_MODULE_NAME setting (env var overrides settings.py).
Critical startup sequence:
- At module import time,
wrapper.pyinstantiatestrained_model_wrapperand callsload_default_module()— this imports the model module. routes/model.pythen callstrained_model_wrapper.sample()at import time to dynamically build theInputVectorPydantic model viapydantic.create_model. This meanssample()must be callable before the app starts.- On server startup,
app.py's lifespan context manager callstrained_model_wrapper.setup(), which runsinit()(optionally in a background thread ifMULTITHREADED_INIT=True). health/readyreturns 503 untilinit()completes.
Adding a new model module: Create ml_rest_fastapi/trained_model/<name>.py implementing init(), teardown(), run(data: Iterable) -> Iterable, and sample() -> Dict with mypy type hints. Set TRAINED_MODEL_MODULE_NAME=<name>. See sample_model.py for a template and adult_census_income.py for a real LightGBM example.
Logging: All logging goes through loguru. app.py installs an InterceptHandler at startup that redirects the stdlib root logger and all uvicorn/gunicorn named loggers into loguru. Model modules import the logger directly: from loguru import logger as log.
Settings (settings.py): All settings fall back from env var → settings dict. Key settings: TRAINED_MODEL_MODULE_NAME, EXPLAIN_PREDICTIONS, DEBUG, MULTITHREADED_INIT.
Tests in tests/basic_test.py are integration tests that hit a live server at http://localhost:8888/. They test the sample_model module by default; the payload shape matches what sample() returns.