File size: 4,551 Bytes
766dbe4
 
 
5b6cb96
7a1eda4
766dbe4
7a1eda4
766dbe4
5b6cb96
7a1eda4
 
5b6cb96
 
7a1eda4
766dbe4
 
5b6cb96
766dbe4
2c9c234
 
 
 
5b6cb96
2c9c234
5b6cb96
2c9c234
5b6cb96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2c9c234
766dbe4
5b6cb96
 
 
 
 
766dbe4
 
5b6cb96
7a1eda4
5b6cb96
 
7a1eda4
5b6cb96
 
 
 
 
 
 
 
 
 
 
 
7a1eda4
5b6cb96
 
 
 
 
 
7a1eda4
 
5b6cb96
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
116
117
import os
import pickle
import pandas as pd
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.templating import Jinja2Templates
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI(title="Student Score Predictor Chatbot")
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"], allow_credentials=True,
    allow_methods=["*"],  allow_headers=["*"],
)
templates = Jinja2Templates(directory="templates")

# Load model once at startup
MODEL_PATH = os.getenv('MODEL_PATH', 'student_performance_model.pkl')
try:
    with open(MODEL_PATH, 'rb') as f:
        model = pickle.load(f)
except Exception as e:
    raise RuntimeError(f"Could not load model: {e}")

# Chat‑fields configuration
FIELDS = [
    {'name': 'Age', 'type': 'number',
     'question': 'What is your age?',
     'validation': {'min': 5, 'max': 100}},
    {'name': 'Gender', 'type': 'select',
     'question': 'What is your gender?',
     'options': ['Male', 'Female', 'Other']},
    {'name': 'HoursOfStudyPerDay', 'type': 'number',
     'question': 'How many hours do you study per day?',
     'validation': {'min': 0, 'max': 24}},
    {'name': 'SchoolAttendanceRate', 'type': 'number',
     'question': 'What is your school attendance rate (%)?',
     'validation': {'min': 0, 'max': 100}},
    {'name': 'TuitionAccess', 'type': 'select',
     'question': 'Do you have access to extra tuition?',
     'options': ['Yes', 'No']},
    {'name': 'AveragePreviousScores', 'type': 'number',
     'question': 'What was your average previous score?',
     'validation': {'min': 0, 'max': 100}},
    {'name': 'HoursOfSleep', 'type': 'number',
     'question': 'How many hours of sleep do you get per night?',
     'validation': {'min': 0, 'max': 24}},
    {'name': 'BreakfastDaily', 'type': 'select',
     'question': 'Do you eat breakfast every day?',
     'options': ['Yes', 'No']},
    {'name': 'ScreenTimeHours', 'type': 'number',
     'question': 'How many hours of screen time per day?',
     'validation': {'min': 0, 'max': 24}},
    {'name': 'PhysicalActivityHours', 'type': 'number',
     'question': 'How many hours of physical activity per day?',
     'validation': {'min': 0, 'max': 24}},
    {'name': 'PlaysSport', 'type': 'select',
     'question': 'Do you play any sports?',
     'options': ['Yes', 'No']},
    {'name': 'MentalHealthScore', 'type': 'number',
     'question': 'Rate your mental health on a scale of 1–10.',
     'validation': {'min': 1, 'max': 10}},
    {'name': 'ParentalEducationLevel', 'type': 'select',
     'question': 'What is your parental education level?',
     'options': ['High school', 'Graduate', 'Postgrad']},
    {'name': 'HouseholdIncomeLevel', 'type': 'select',
     'question': 'What is your household income level?',
     'options': ['Low', 'Medium', 'High']},
    {'name': 'StudyEnvironmentRating', 'type': 'number',
     'question': 'Rate your study environment (1–5).',
     'validation': {'min': 1, 'max': 5}},
    {'name': 'FriendSupportScore', 'type': 'number',
     'question': 'Rate the emotional support from friends (1–10).',
     'validation': {'min': 1, 'max': 10}},
    {'name': 'ParticipatesInClubs', 'type': 'select',
     'question': 'Do you participate in any clubs?',
     'options': ['Yes', 'No']},
    {'name': 'PartTimeWork', 'type': 'select',
     'question': 'Do you do any part‑time work?',
     'options': ['Yes', 'No']},
]

@app.get("/", response_class=HTMLResponse)
async def chat_ui(request: Request):
    return templates.TemplateResponse("chat.html", {
        "request": request,
        "fields": FIELDS
    })

@app.post("/predict_json")
async def predict_json(payload: dict):
    # collect + cast
    data = {}
    for f in FIELDS:
        key = f["name"]
        if key not in payload:
            raise HTTPException(400, f"Missing field: {key}")
        val = payload[key]
        if f["type"] == "number":
            try:
                val = float(val)
            except:
                raise HTTPException(400, f"{key} must be numeric")
        data[key] = val

    # validate ranges
    for f in FIELDS:
        if f["type"] == "number" and "validation" in f:
            v = f["validation"]
            if not (v["min"] <= data[f["name"]] <= v["max"]):
                raise HTTPException(400,
                    f"{f['name']} must be between {v['min']} and {v['max']}")

    df = pd.DataFrame([data])
    score = model.predict(df)[0]
    return JSONResponse({"predicted": round(float(score), 2)})