docs: align Rust ONNX service deployment docs

- Update docker-compose.yml MODEL_PATH from best_model.keras to model.onnx
- Fix Machine_Learning/README.md TOC and section numbering (remove duplicate section 9, add Validasi Parity ONNX as section 9)
- Clarify parity validation as manual/recommended, not mandatory CI
- Update CLAUDE.md to document Rust/Axum/ONNX Runtime ML service and ONNX export workflow
- Simplify root README.md ML service section with port clarification (8001 local, 8000 container)
- Remove stale endpoint examples from root README (documented in apps/ml-service/README.md)
- Ensure no FastAPI/Uvicorn references in deployment documentation

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Asep Haryana Saputra
2026-05-23 10:58:08 +00:00
co-authored by Claude Opus 4.7
parent abff278f49
commit f2e4c338bb
4 changed files with 29 additions and 26 deletions
+22 -5
View File
@@ -4,9 +4,9 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Repository overview
This repository currently contains the machine-learning pipeline for ZeaVis Edu: a corn leaf disease classifier trained with EfficientNetV2B0 and exported for production use as TensorFlow SavedModel, TFLite, and TensorFlow.js formats.
This repository contains the ZeaVis Edu application: a corn leaf disease classifier with a machine-learning pipeline (EfficientNetV2B0 training and export), a Rust/Axum/ONNX Runtime inference service, and a fullstack TypeScript application (React frontend, Elysia backend, PostgreSQL).
The active project lives under `Machine_Learning/`. Most commands should be run from that directory unless noted otherwise.
The ML pipeline lives under `Machine_Learning/`. The inference service lives under `apps/ml-service/`. Most ML commands should be run from the `Machine_Learning/` directory unless noted otherwise.
## Common commands
@@ -34,6 +34,12 @@ Export a trained Keras model to SavedModel and TFLite after placing the Colab-tr
python save_model.py
```
Convert the SavedModel export to ONNX for the Rust ML service:
```bash
python convert_onnx.py
```
Convert the SavedModel export to TensorFlow.js via CLI:
```bash
@@ -53,7 +59,7 @@ Open the training notebook locally if needed:
jupyter notebook notebook.ipynb
```
There is no project test suite, lint command, or build system configured in the current repository.
There is no project test suite, lint command, or build system configured in the ML pipeline.
## Fullstack app commands
@@ -95,12 +101,20 @@ Run the web app directly:
cd apps/web && bun run dev
```
Run the ML service directly:
```bash
cd apps/ml-service && cargo run
```
## High-level architecture
- `Machine_Learning/preprocessing.py` prepares the training dataset locally. It extracts three source ZIP files, merges selected class folders into `dataset/`, maps selected Mandarin labels from Dataset 3 via `desc.json`, removes known problematic image files, then creates `dataset.zip` for upload to Google Drive/Colab.
- `Machine_Learning/notebook.ipynb` is the training workflow intended for Google Colab with GPU enabled. It trains an EfficientNetV2B0-based classifier and saves the best model to Google Drive as `best_model.keras`.
- `Machine_Learning/save_model.py` is the production export step. It loads `best_model/best_model.keras`, rebuilds a clean EfficientNetV2B0 architecture without training-time augmentation layers, copies weights into that model, exports `model/saved_model/`, and writes `model/model.tflite`.
- `Machine_Learning/convert_onnx.py` converts the SavedModel to ONNX format (`model/model.onnx`) for use by the Rust inference service.
- TensorFlow.js export is intentionally done with the `tensorflowjs_converter` CLI rather than from Python to avoid protobuf/runtime conflicts documented in the README.
- `apps/ml-service/` is a Rust/Axum service that loads the ONNX model and serves HTTP endpoints for health checks, metadata, and image classification predictions. It uses ONNX Runtime for cross-platform inference performance.
## Fullstack application architecture
@@ -108,9 +122,10 @@ The root TypeScript workspace is a Bun + Moon monorepo:
- `apps/web/` contains the React + Vite + TypeScript frontend with React Router, TanStack Query, Zustand, Tailwind, and shadcn/ui-style components.
- `apps/api/` contains the Elysia backend with health/status routes and Drizzle/PostgreSQL configuration.
- `apps/ml-service/` contains the Rust/Axum inference service with ONNX Runtime for model predictions.
- `packages/shared/` contains shared TypeScript types and utilities consumed by both apps.
The backend reads `DATABASE_URL` for Drizzle/PostgreSQL, but the initial health/status endpoints do not require a live database connection.
The backend reads `DATABASE_URL` for Drizzle/PostgreSQL, but the initial health/status endpoints do not require a live database connection. The ML service reads `MODEL_PATH` (default `../../Machine_Learning/model/model.onnx`) and `MODEL_INPUT_SIZE` (default `224`).
## Model labels and dataset mapping
@@ -134,10 +149,12 @@ The following files/directories are generated or externally supplied during the
- `Machine_Learning/dataset_1.zip`, `dataset_2.zip`, `dataset_3.zip` — manually downloaded source datasets.
- `Machine_Learning/dataset/` and `Machine_Learning/dataset.zip` — generated by `preprocessing.py`.
- `Machine_Learning/best_model/best_model.keras` — trained model downloaded from Colab/Google Drive.
- `Machine_Learning/model/saved_model/`, `model/model.tflite`, and `model/tfjs_model/` — production exports.
- `Machine_Learning/model/saved_model/`, `model/model.tflite`, `model/model.onnx`, and `model/tfjs_model/` — production exports.
## Notes for future changes
- Keep README command examples and this file in sync when changing the ML pipeline.
- Preserve the current class label names unless the training notebook, preprocessing mappings, and downstream app/API expectations are updated together.
- `save_model.py` assumes the clean architecture matches the trained model weights exactly; changes to the notebook model architecture usually require corresponding changes in `build_clean_model()`.
- The Rust ML service expects the ONNX model at the path specified by `MODEL_PATH`. Ensure `convert_onnx.py` is run after `save_model.py` to generate the ONNX artifact before deploying the service.
+5 -3
View File
@@ -14,7 +14,7 @@ Pipeline lengkap untuk klasifikasi penyakit daun jagung menggunakan **EfficientN
6. [Tahap 2 — Upload ke Google Drive & Training di Colab](#6-tahap-2--upload-ke-google-drive--training-di-colab)
7. [Tahap 3 — Download Model dari Colab](#7-tahap-3--download-model-dari-colab)
8. [Tahap 4 — Ekspor Model untuk Produksi](#8-tahap-4--ekspor-model-untuk-produksi)
9. [Tahap 5 — Konversi ke ONNX](#9-tahap-5--konversi-ke-onnx)
9. [Validasi Parity ONNX (Opsional)](#9-validasi-parity-onnx-opsional)
10. [Output Akhir](#10-output-akhir)
11. [Troubleshooting](#11-troubleshooting)
@@ -330,7 +330,9 @@ Skrip ini akan:
Model ONNX ini digunakan oleh layanan inferensi Rust di `apps/ml-service/` untuk performa dan kompatibilitas lintas platform yang lebih baik.
#### Validasi Parity ONNX
---
## 9. Validasi Parity ONNX (Opsional)
Untuk memverifikasi bahwa model ONNX menghasilkan prediksi yang sama dengan SavedModel asli, jalankan:
@@ -338,7 +340,7 @@ Untuk memverifikasi bahwa model ONNX menghasilkan prediksi yang sama dengan Save
python validate_onnx_parity.py /path/to/corn-leaf.jpg
```
Skrip ini akan membandingkan output prediksi antara SavedModel dan ONNX untuk memastikan keakuratan konversi.
Skrip ini akan membandingkan output prediksi antara SavedModel dan ONNX untuk memastikan keakuratan konversi. **Validasi ini bersifat manual dan direkomendasikan, bukan wajib untuk deployment.**
---
+1 -17
View File
@@ -166,23 +166,7 @@ Jika model berada di lokasi lain, gunakan environment variable `MODEL_PATH`:
MODEL_PATH=/path/to/model.onnx cargo run
```
## Endpoint Penting
### ML Service
| Method | Endpoint | Fungsi |
|---|---|---|
| GET | `/health` | Mengecek status service dan status model |
| GET | `/metadata` | Melihat metadata service, label, input size, dan path model |
| POST | `/predict` | Mengunggah gambar daun jagung untuk klasifikasi |
Contoh verifikasi lokal:
```bash
curl http://localhost:8001/health
curl http://localhost:8001/metadata
curl -X POST http://localhost:8001/predict -F "file=@/path/to/corn-leaf.jpg"
```
Service mendengarkan di `http://localhost:8001` secara default untuk development lokal (lihat `apps/ml-service/.env.example`). Dalam Docker container, service mendengarkan di port `8000`.
## Docker Deployment
+1 -1
View File
@@ -50,7 +50,7 @@ services:
env_file:
- .env
environment:
MODEL_PATH: /app/model/best_model.keras
MODEL_PATH: /app/model/model.onnx
MODEL_INPUT_SIZE: "224"
labels:
traefik.enable: "true"