- Entry point
main.pyspins up FastAPI withlifespanthat loads three fastai learners. Run bypython main.pyoruvicorn main:app --host 0.0.0.0 --port 9020. - Async endpoints call FastAI
Learner.predictviarun_in_threadpool; uploads arrive asUploadFile. - Upload guardrails: MIME whitelist (jpeg/png/tiff), 10 MB cap enforced via
seek(no double read), centralized logging + exception hooks. - Preprocessing:
imageio.v3.imread-> drop alpha ->exposure.rescale_intensity(..., out_range=np.float64)->img_as_ubyte->PILImage.create. /healthzreports readiness (okvsdegraded) based on which learners are loaded.
- Models expected at
models/xtype-simple_resnet18_fp16_01,models/lateral_fliprot_resnet18_fp16_07,models/frontal_fliprot_resnet18_fp16_03(fastai exported learners). They are treated as files (not dirs); ensure git-lfs or manual drop. label_funcstub exists solely to satisfy learner export requirements (fastai dataloaders reference it).
/welcome ping./xray-infochained classification: global type + optional flip/rotation for lateral/frontal (usesmap_fliprot_prediction)./xray-classtype-only;/lateral-fliprot+/frontal-fliprotcallclassify_specific_modeldirectly.- All endpoints reuse
validate_file_size+validate_image; responses include raw prediction, probability, full vocab w/ probabilities.
- Logging now stdout-only (single
StreamHandler), container-friendly. - CORS wide open.
- Dockerfile: multi-stage (
python:3.13-slimbase) installs torch CPU wheels, fastai, scikit-image, imageio, fastapi. Models copied via scratch stage;BFD9020.htmlcopied for/testroute. - Compose file (
docker-compose.yml) builds from repo root, publishes9020:9020, setsLOG_LEVEL=INFO. - Tester available at
/test(servesBFD9020.html); standalone file also works locally. TIFF thumbnails are rendered via<canvas>using vendored/static/pako.min.js+/static/UTIF.js(FastAPI mountsStaticFiles(directory="static")). - No requirements.txt/pyproject—deps inferred from image setup (fastapi, fastai, torch/vision/audio, scikit-image, imageio, numpy, uvicorn).