-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
115 lines (99 loc) · 3.75 KB
/
Copy pathapp.py
File metadata and controls
115 lines (99 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
"""
app.py
------
FastAPI web application for the Climate Visibility project — matches
the "Final Project Demo" screenshots in the PPT: a form with
DRYBULBTEMPF, RelativeHumidity, WindSpeed, WindDirection,
SeaLevelPressure, a "Predict the Climate Visibility" button, and a
/predict page showing "Predicted Visibility: X.XXX km".
Also exposes /train to kick off the training pipeline (equivalent to
running `python main.py`), matching the "End to End Pipeline Run"
step in the project flow.
Run with:
uvicorn app:app --host 127.0.0.1 --port 8062 --reload
Or:
python app.py
"""
import os
import sys
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
import uvicorn
from typing import Optional, cast
from src.constant.training_pipeline import APP_HOST, APP_PORT
from src.exception import ClimateVisibilityException
from src.logger import logging
from src.pipeline.prediction_pipeline import VisibilityData, predict_visibility
from src.pipeline.training_pipeline import TrainingPipeline
app = FastAPI(title="Climate Visibility Prediction")
BASE_DIR = os.path.dirname(__file__)
app.mount("/static", StaticFiles(directory=os.path.join(BASE_DIR, "static")), name="static")
templates = Jinja2Templates(directory=os.path.join(BASE_DIR, "templates"))
@app.get("/", response_class=HTMLResponse)
async def index(request: Request):
return templates.TemplateResponse(
request=request,
name="index.html",
context={"request": request},
)
@app.get("/train")
async def train_route():
"""Kicks off the full training pipeline (data ingestion -> model pusher)."""
try:
artifact = TrainingPipeline().run_pipeline()
return {
"status": "success",
"message": "Training pipeline completed successfully.",
"model_path": artifact.model_file_path,
}
except Exception as e:
raise ClimateVisibilityException(e, sys) from e
@app.post("/predict", response_class=HTMLResponse)
async def predict_route(
request: Request,
DRYBULBTEMPF: Optional[float] = None,
RelativeHumidity: Optional[float] = None,
WindSpeed: Optional[float] = None,
WindDirection: Optional[float] = None,
SeaLevelPressure: Optional[float] = None,
):
form = await request.form()
try:
input_data = VisibilityData(
DRYBULBTEMPF=float(cast(str, form.get("DRYBULBTEMPF"))),
RelativeHumidity=float(cast(str, form.get("RelativeHumidity"))),
WindSpeed=float(cast(str, form.get("WindSpeed"))),
WindDirection=float(cast(str, form.get("WindDirection"))),
SeaLevelPressure=float(cast(str, form.get("SeaLevelPressure"))),
)
prediction = predict_visibility(input_data)
return templates.TemplateResponse(
request=request,
name="result.html",
context={
"request": request,
"prediction": prediction,
},
)
except FileNotFoundError:
logging.warning("No trained model found — run /train (or `python main.py`) first.")
return templates.TemplateResponse(
request=request,
name="index.html",
context={
"request": request,
"error": (
"No trained model found yet. Please run the training "
"pipeline first (GET /train or `python main.py`)."
),
},
)
except Exception as e:
raise ClimateVisibilityException(e, sys) from e
@app.get("/health")
async def health():
return {"status": "ok"}
if __name__ == "__main__":
uvicorn.run("app:app", host=APP_HOST, port=APP_PORT, reload=True)