- End-to-end model serving with FastAPI
- Docker-based service isolation and networking
- Structured inference pipeline with consistent preprocessing
- Stateless API design
- Collaborative development via PR-based workflow
The system consists of two services:
- A FastAPI inference service
- A Streamlit-based user interface
Both run in separate Docker containers connected through an internal network.
┌────────────────┐
│ Streamlit UI │
└────────┬───────┘
│
┌────────▼────────┐
│ FastAPI API │
└────────┬────────┘
│
┌────────▼────────┐
│ PyTorch Model │
└─────────────────┘
.
├── app/
│ ├── config.py # Class labels and configuration
│ ├── main.py # FastAPI entrypoint
│ ├── make_model.py # Model architecture (used for TorchScript export)
│ └── model.py # TorchScript loading & inference logic
├── artifacts/
│ ├── best_model.pt # Original trained weights
│ └── model.torchscript.pt # Exported TorchScript model
├── scripts/
│ └── export_torchscript.py # TorchScript export script
├── assets/ # README screenshots
├── streamlit_app.py # Streamlit frontend
├── Dockerfile
├── docker-compose.yml
├── pyproject.toml
├── uv.lock
└── README.md
- Architecture defined in
app/make_model.py(used for TorchScript export) - Model exported to TorchScript:
artifacts/model.torchscript.pt - Inference loads the scripted model via
_get_model()usingtorch.jit.load - Preprocessing:
Resize(32, 32)ToTensor()Normalize(mean=(0.4914, 0.4822, 0.4465), std=(0.2470, 0.2435, 0.2616))
- Softmax used to compute confidence
- Original training weights (
best_model.pt) are used only for generating the TorchScript export
Health check endpoint.
Expected response:
{"status":"ok"}Accepts an image file (multipart upload) and returns:
{
"predicted_index": 3,
"predicted_label": "cat",
"confidence": 0.87
}A simple Streamlit UI is included for manual testing.
- Upload an image (
.jpg,.jpeg,.png) - Preview the image
- Click Predict to call
POST /predict - Displays predicted label and confidence
- Raw JSON response available via expander
The frontend sends a multipart request to the FastAPI API at:
http://localhost:8000/predict
docker compose up --buildStreamlit UI: http://localhost:8501
curl http://localhost:8000/health
Manual test:
curl -X POST \
-F "file=@example.jpg" \
http://localhost:8000/predict- Containerized multi-service setup
- Stateless inference API
- CPU-compatible runtime
Feature-branch workflow with mandatory pull request reviews and a protected main branch.
Key pull requests:
-
Pull Requests & Merge Conflicts
Working with feature branches required keeping the branch updated withmainto avoid conflicts. Regular rebasing and PR reviews helped maintain a clean integration workflow. -
Future Improvements
The model reused from a previous assignment is not heavily optimized. Further improvements could include performance tuning, architectural experimentation, better configuration handling (e.g., environment variables), structured logging, CI for container builds, and more robust input validation. -
Use of LLMs
LLMs were used as a development assistant for reviewing structure, clarifying architectural decisions, debugging environment issues, and refining documentation. All implementation and verification were performed manually.- Ömer Aytug
- Daniela Algerydh


