Document the agreed FastAPI inference service boundary before implementation planning. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
4.3 KiB
ML Service Design
Summary
Add a separate Python FastAPI inference service at apps/ml-service. The existing Machine_Learning directory remains responsible for model training, preprocessing, and export artifacts. The new service is responsible only for serving image classification predictions from the trained Keras model.
Goals
- Serve corn leaf disease predictions through a small HTTP API.
- Keep TensorFlow/Keras runtime dependencies out of the Bun/Elysia API app.
- Keep the capstone deployment simple and easy to debug.
- Preserve
Machine_Learningas the source for model artifacts and training workflow.
Non-goals
- Do not introduce TensorFlow Serving.
- Do not switch to TFLite for the first implementation.
- Do not move the ML training/export pipeline into
apps/ml-service. - Do not add frontend UI changes in this scope.
Architecture
apps/ml-service will be a standalone FastAPI application. It will load a Keras model from a configurable path, defaulting to the trained model artifact under Machine_Learning/best_model/best_model.keras.
The service exposes three endpoints:
GET /healthreturns service health and whether the model is loaded.GET /metadatareturns model/service metadata such as labels, input size, configured model path, and model loaded status.POST /predictaccepts one uploaded image and returns the predicted Indonesian disease label, confidence, and class probabilities.
The existing TypeScript backend can later call this ML service over HTTP. That integration is outside this first service-scaffolding scope unless explicitly requested after the service exists.
Components
apps/ml-service/main.pycreates the FastAPI app and defines routes.apps/ml-service/model.pyowns model loading, image preprocessing, and prediction.apps/ml-service/schemas.pydefines response models for health, metadata, and prediction responses.apps/ml-service/requirements.txtlists Python runtime dependencies: FastAPI, Uvicorn, TensorFlow, Pillow, and multipart upload support.apps/ml-service/.env.exampledocuments runtime configuration such asMODEL_PATH,MODEL_INPUT_SIZE, and port.
Runtime configuration
MODEL_PATHcontrols the Keras model path. Default:../../Machine_Learning/best_model/best_model.kerasrelative toapps/ml-service.MODEL_INPUT_SIZEcontrols image resize dimensions. Default should match the trained EfficientNetV2B0 pipeline input size.ML_SERVICE_HOSTandML_SERVICE_PORTdocument how to run the service locally.
Data flow for POST /predict
- Client uploads an image as multipart form data.
- Service validates that the upload is an image.
- Service opens the image with Pillow, converts it to RGB, and resizes it to the configured input size.
- Image pixels are converted to a batch tensor using the same normalization expected by the Keras model.
- The loaded model returns class probabilities for the four labels.
- Service returns JSON containing the top label, confidence, and probability per label.
Labels
The model predicts the existing four Indonesian labels:
Bercak DaunHawar DaunKarat DaunDaun Sehat
The service must preserve this label order consistently with the trained model output.
Error handling
- If the model cannot be loaded,
GET /healthreturns a successful response withmodel_loaded: false. - If the model is not loaded,
POST /predictreturns503 Service Unavailable. - If the uploaded file is not an image or cannot be decoded,
POST /predictreturns400 Bad Request. - If inference fails unexpectedly,
POST /predictreturns500 Internal Server Errorwith a generic message. GET /metadatastill returns static metadata even when the model is not loaded, includingmodel_loadedstatus.
Verification
Manual verification for the initial implementation:
- Start the service with Uvicorn from
apps/ml-service. - Call
GET /healthand confirm the response includes service status and model loaded status. - Call
GET /metadataand confirm labels, input size, model path, and model loaded status are present. - Call
POST /predictwith a real image file when an example corn leaf image is available.
The repository does not currently have a Python test suite for this new service. Automated tests can be added later if the service grows beyond the initial capstone scope.