# borispanasenko/plant-disease-classifier-api architecture

> Architecture diagram of the GitHub repository borispanasenko/plant-disease-classifier-api, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-17). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/borispanasenko/plant-disease-classifier-api
- Repository: https://github.com/borispanasenko/plant-disease-classifier-api

## Overview

1. **Overall shape**
   - This is a single-process FastAPI application with three main concerns: image inference, metadata lookup, and detection history persistence.
   - The repo is organized as a small monolith rather than separate services: API code in `app/`, model artifacts in `models/`, training scripts in `training/`, seed/data sources in `data/` and `db_scripts/`, and a static test UI in `public/`.

2. **Request entrypoint**
   - `run.py` is the launch point for the application, and the backend is intended to run under Uvicorn.
   - `app/main.py` is the central API assembly point where routes such as `/analyze`, `/detections`, and `/diseases/{disease_id}` are exposed.

3. **Image analysis flow**
   - The `/analyze` endpoint receives a multipart image upload from the client.
   - The image is validated and processed, then passed into the inference layer in `app/ml_model.py`, which loads the trained PyTorch ResNet-34 classifier and produces a disease label plus confidence score.
   - The prediction is then enriched with human-readable disease metadata before being returned.

4. **Inference subsystem**
   - `app/ml_model.py` is the core machine-learning boundary.
   - It likely owns model loading from the `models/` directory, image preprocessing with Pillow/torchvision, and prediction post-processing into the class names used by the API.
   - This keeps the ML artifact and the web layer decoupled: the API calls into the inference module, but does not embed training logic.

5. **Persistence subsystem**
   - The application stores detection events in a SQLite database.
   - `app/models.py` defines the data model/schema, while the runtime uses SQLAlchemy plus async DB access via `aiosqlite` according to the README.
   - Detection history is exposed through `GET /detections`, which reads from the database rather than recomputing inference.

6. **Disease metadata subsystem**
   - Disease descriptions and treatment recommendations live outside the database logic in `data/diseases_data.py`.
   - `db_scripts/seed_db.py` appears to populate the SQLite database with this reference data so API responses can include the disease name, description, and treatment.
   - This is a separate content source from prediction results: the model predicts the class, then the metadata layer maps that class to explanatory information.

7. **Training pipeline**
   - `training/prepare_data.py` and `training/train_model.py` form an offline ML workflow.
   - These scripts are not part of request handling; they prepare the dataset, train the classifier, and generate artifacts stored under `models/`.
   - This separation is important: production inference depends on trained outputs, while training can be rerun independently for experimentation.

8. **Static frontend**
   - `public/index.html` and `public/script.js` provide a minimal browser-based client for manual testing.
   - The frontend sends images to the backend’s `/analyze` endpoint and can display prediction results without requiring a separate frontend build system.
   - It is a convenience layer, not a core dependency of the API.

9. **Filesystem roles**
   - `uploads/` is reserved for incoming image files, suggesting the backend persists uploaded content temporarily or for inspection.
   - `models/` holds the trained model files used at inference time.
   - `data/` contains the disease reference content, while `db_scripts/` contains bootstrap logic for initializing the database state.

10. **Configuration and runtime boundaries**
   - `app/config.py` likely centralizes environment-driven settings such as the SQLite connection string.
   - `app/__init__.py` and `utils/__init__.py` make the package structure explicit; `utils/smart_sleep.py` is a small helper module but not a primary architectural boundary.
   - The key runtime boundary is between HTTP/API handling, ML inference, and database persistence: requests enter through FastAPI, are classified by PyTorch, then enriched and stored in SQLite before being returned to the client.

Main entry points: [`app/main.py`](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/main.py) (API app), [`data/diseases_data.py`](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/data/diseases_data.py) (Disease data), [`app/ml_model.py`](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/ml_model.py) (Classifier), [`db_scripts/seed_db.py`](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/db_scripts/seed_db.py) (Seed DB)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_grp_api["API runtime"]
  node_n_run(("Run app<br/>uvicorn entrypoint<br/>[run.py]"))
  node_n_main["API app<br/>FastAPI assembly<br/>[main.py]"]
  node_n_config["Config<br/>settings<br/>[config.py]"]
  node_n_analyze["Analyze<br/>upload endpoint<br/>[main.py]"]
  node_n_detections_api["Detections API<br/>history endpoint<br/>[main.py]"]
  node_n_disease_api["Disease API<br/>lookup endpoint<br/>[main.py]"]
  node_n_uploads[("Uploads<br/>file staging")]
end

subgraph group_grp_ml["Inference"]
  node_n_ml_model["Classifier<br/>PyTorch inference<br/>[ml_model.py]"]
  node_n_preprocess["Preprocess<br/>image pipeline<br/>[ml_model.py]"]
  node_n_model_artifacts[("Model files<br/>trained artifacts")]
end

subgraph group_grp_db["Persistence"]
  node_n_db_models["DB schema<br/>SQLAlchemy models<br/>[models.py]"]
  node_n_history_store[("History store<br/>SQLite access")]
end

subgraph group_grp_content["Content"]
  node_n_seed["Seed DB<br/>bootstrap script<br/>[seed_db.py]"]
  node_n_disease_data["Disease data<br/>reference content<br/>[diseases_data.py]"]
end

subgraph group_grp_train["Training"]
  node_n_prepare["Prepare data<br/>dataset prep<br/>[prepare_data.py]"]
  node_n_train["Train model<br/>offline training<br/>[train_model.py]"]
end

subgraph group_grp_ui["Static UI"]
  node_n_frontend["Test UI<br/>static frontend<br/>[index.html]"]
  node_n_script["Client script<br/>browser logic<br/>[script.js]"]
end

node_n_run -->|"starts"| node_n_main
node_n_main -->|"loads"| node_n_config
node_n_main -->|"exposes"| node_n_analyze
node_n_main -->|"exposes"| node_n_detections_api
node_n_main -->|"exposes"| node_n_disease_api
node_n_main -->|"uses"| node_n_uploads
node_n_analyze -->|"validates"| node_n_preprocess
node_n_analyze -->|"predicts"| node_n_ml_model
node_n_analyze -->|"enriches"| node_n_disease_data
node_n_analyze -->|"stores"| node_n_history_store
node_n_ml_model -->|"loads"| node_n_model_artifacts
node_n_ml_model -->|"uses"| node_n_preprocess
node_n_detections_api -->|"reads"| node_n_history_store
node_n_disease_api -->|"looks up"| node_n_disease_data
node_n_db_models -->|"defines"| node_n_history_store
node_n_seed -->|"seeds"| node_n_disease_data
node_n_seed -->|"initializes"| node_n_history_store
node_n_prepare -->|"consumes"| node_n_disease_data
node_n_prepare -->|"feeds"| node_n_train
node_n_train -->|"writes"| node_n_model_artifacts
node_n_frontend -->|"includes"| node_n_script
node_n_script -->|"calls"| node_n_analyze

click node_n_run "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/run.py"
click node_n_main "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/main.py"
click node_n_config "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/config.py"
click node_n_analyze "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/main.py"
click node_n_detections_api "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/main.py"
click node_n_disease_api "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/main.py"
click node_n_ml_model "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/ml_model.py"
click node_n_preprocess "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/ml_model.py"
click node_n_db_models "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/models.py"
click node_n_seed "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/db_scripts/seed_db.py"
click node_n_disease_data "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/data/diseases_data.py"
click node_n_prepare "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/training/prepare_data.py"
click node_n_train "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/training/train_model.py"
click node_n_frontend "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/public/index.html"
click node_n_script "https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/public/script.js"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_n_run,node_n_main,node_n_config,node_n_analyze,node_n_detections_api,node_n_disease_api,node_n_uploads toneBlue
class node_n_ml_model,node_n_preprocess,node_n_model_artifacts toneAmber
class node_n_db_models,node_n_history_store toneMint
class node_n_seed,node_n_disease_data toneRose
class node_n_prepare,node_n_train toneIndigo
class node_n_frontend,node_n_script toneTeal
```

## Components

### API runtime

FastAPI application entrypoint, routing, and request handling.

- [Run app](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/run.py): uvicorn entrypoint · Launches the FastAPI server. · `run.py`
- [API app](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/main.py): FastAPI assembly · Creates the application and exposes the main HTTP routes. · `app/main.py`
- [Config](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/config.py): settings · Centralized runtime configuration and environment settings. · `app/config.py`
- [Analyze](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/main.py): upload endpoint · Accepts an image upload and returns a prediction response. · `app/main.py`
- [Detections API](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/main.py): history endpoint · Serves stored detection history from the database. · `app/main.py`
- [Disease API](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/main.py): lookup endpoint · Returns metadata for a disease identifier. · `app/main.py`
- **Uploads**: file staging · Temporary storage for incoming image files.

### Inference

Model loading and image classification boundary.

- [Classifier](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/ml_model.py): PyTorch inference · Loads the trained model and produces labels and confidence scores. · `app/ml_model.py`
- [Preprocess](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/ml_model.py): image pipeline · Validates and transforms uploaded images for inference. · `app/ml_model.py`
- **Model files**: trained artifacts · Stored weights and supporting files used at inference time.

### Persistence

Database schema and detection history storage.

- [DB schema](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/app/models.py): SQLAlchemy models · Defines the persistence schema for detection history. · `app/models.py`
- **History store**: SQLite access · Runtime database layer used to persist and read detections.

### Content

Disease reference data and database seeding.

- [Seed DB](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/db_scripts/seed_db.py): bootstrap script · Populates the database with reference disease records. · `db_scripts/seed_db.py`
- [Disease data](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/data/diseases_data.py): reference content · Human-readable disease descriptions and treatments. · `data/diseases_data.py`

### Training

Offline dataset preparation and model training pipeline.

- [Prepare data](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/training/prepare_data.py): dataset prep · Builds training inputs from source data. · `training/prepare_data.py`
- [Train model](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/training/train_model.py): offline training · Trains the classifier and produces artifacts. · `training/train_model.py`

### Static UI

Minimal browser client for manual testing.

- [Test UI](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/public/index.html): static frontend · Minimal browser client for manual testing. · `public/index.html`
- [Client script](https://github.com/borispanasenko/plant-disease-classifier-api/blob/main/public/script.js): browser logic · Sends images to the analysis endpoint and displays results. · `public/script.js`

## Connections

- Run app → API app: starts · Uvicorn launches the FastAPI application.
- API app → Config: loads · Routes and runtime settings use centralized configuration.
- API app → Analyze: exposes · Main image classification endpoint.
- API app → Detections API: exposes · History retrieval endpoint.
- API app → Disease API: exposes · Disease metadata lookup endpoint.
- API app → Uploads: uses · Incoming files may be staged on disk.
- Analyze → Preprocess: validates · Uploaded images are checked and transformed before inference.
- Analyze → Classifier: predicts · Endpoint delegates classification to the ML boundary.
- Analyze → Disease data: enriches · Prediction is mapped to readable disease information.
- Analyze → History store: stores · Detection event is persisted for later retrieval.
- Classifier → Model files: loads · Inference uses trained weights and related files.
- Classifier → Preprocess: uses · Classifier expects preprocessed image tensors.
- Detections API → History store: reads · Returns persisted detection history.
- Disease API → Disease data: looks up · Serves explanatory disease content.
- DB schema → History store: defines · Schema drives the SQLite persistence layer.
- Seed DB → Disease data: seeds · Bootstrap script loads reference disease records.
- Seed DB → History store: initializes · Populates the database with seed content.
- Prepare data → Disease data: consumes · Training data preparation uses source data and labels.
- Prepare data → Train model: feeds · Prepared data is used for model training.
- Train model → Model files: writes · Training produces the deployed model artifacts.
- Test UI → Client script: includes · Static page loads client-side request logic.
- Client script → Analyze: calls · Browser client submits images to the analysis endpoint.
