kerols77 commited on
Commit
1f8582e
·
verified ·
1 Parent(s): 4457db5

Upload 8 files

Browse files
Dockerfile ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use Python 3.9 slim image as base
2
+ FROM python:3.9-slim
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Install system dependencies
8
+ RUN apt-get update && apt-get install -y \
9
+ gcc \
10
+ g++ \
11
+ && rm -rf /var/lib/apt/lists/*
12
+
13
+ # Copy requirements file first (for better Docker layer caching)
14
+ COPY requirements.txt .
15
+
16
+ # Install Python dependencies
17
+ RUN pip install --no-cache-dir -r requirements.txt
18
+
19
+ # Copy the application code
20
+ COPY . .
21
+
22
+ # Create data directory for JSON files
23
+ RUN mkdir -p data
24
+
25
+ # Set environment variables
26
+ ENV PYTHONUNBUFFERED=1
27
+ ENV PORT=7860
28
+
29
+ # Expose the port that the app runs on
30
+ EXPOSE 7860
31
+
32
+ # Command to run the application
33
+ CMD ["python", "app.py"]
app.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify
2
+ import os
3
+ import requests
4
+ from student_recommendation_system import StudentRecommendationSystem, setup_json_directory
5
+
6
+ app = Flask(__name__)
7
+ json_dir = setup_json_directory()
8
+ recommendation_system = StudentRecommendationSystem(json_dir)
9
+
10
+ FORWARD_URL = "http://54.242.19.19:3000/api/report/send-report/"
11
+ GRADES_API_BASE_URL = "http://54.242.19.19:3000/api/grades/report/"
12
+
13
+ @app.route('/recommend/<int:student_id>', methods=['POST'])
14
+ def recommend(student_id):
15
+ try:
16
+ grades_api_url = f"{GRADES_API_BASE_URL}{student_id}"
17
+ try:
18
+ grades_response = requests.get(grades_api_url, timeout=10)
19
+ grades_response.raise_for_status()
20
+ grades_data_raw = grades_response.json()
21
+ except requests.exceptions.RequestException as e:
22
+ return jsonify({"error": f"Failed to fetch grades data: {str(e)}"}), 500
23
+ except ValueError as e:
24
+ return jsonify({"error": "Invalid JSON response from grades API"}), 500
25
+ if "grades_data" not in grades_data_raw:
26
+ return jsonify({"error": "No 'grades_data' found in external API response"}), 400
27
+ email = grades_data_raw.get("email")
28
+ if not email:
29
+ return jsonify({"error": "No 'email' found in external API response"}), 400
30
+ try:
31
+ grades_data = {subject: float(score) for subject, score in grades_data_raw["grades_data"].items()}
32
+ except (ValueError, TypeError) as e:
33
+ return jsonify({"error": f"Invalid grades data format: {str(e)}"}), 400
34
+ results = recommendation_system.process_student_data(grades_data=grades_data)
35
+ strengths = results["strengths"]
36
+ top_recs = results["top_recommendations"]
37
+ clean_recs = [
38
+ {k: v for k, v in rec.items() if k not in ("raw_score", "refined_score")}
39
+ for rec in top_recs
40
+ ]
41
+ response_payload = {
42
+ "email": email,
43
+ "studentName": "Ahmed Hassan",
44
+ "academic_strengths": strengths,
45
+ "top_recommendations": clean_recs
46
+ }
47
+ model_path = os.path.join(json_dir, "ai_model.pkl")
48
+ recommendation_system.save_ai_model(model_path)
49
+ try:
50
+ requests.post(FORWARD_URL, json=response_payload, timeout=10)
51
+ except requests.exceptions.RequestException as e:
52
+ print(f"Warning: Failed to forward data to report API: {str(e)}")
53
+ return jsonify(response_payload), 200
54
+ except Exception as e:
55
+ return jsonify({"error": f"Internal server error: {str(e)}"}), 500
56
+
57
+
58
+ @app.route('/recommend', methods=['POST'])
59
+ def recommend_post():
60
+ data = request.get_json(silent=True)
61
+ if not data or "grades_data" not in data:
62
+ return jsonify({"error": "No 'grades_data' provided in JSON payload."}), 400
63
+
64
+ try:
65
+ grades_data = {subject: float(score) for subject, score in data["grades_data"].items()}
66
+ results = recommendation_system.process_student_data(grades_data=grades_data)
67
+ strengths = results["strengths"]
68
+ top_recs = results["top_recommendations"]
69
+ clean_recs = [
70
+ {k: v for k, v in rec.items() if k not in ("raw_score", "refined_score")}
71
+ for rec in top_recs
72
+ ]
73
+ response_payload = {
74
+ "academic_strengths": strengths,
75
+ "top_recommendations": clean_recs
76
+ }
77
+ model_path = os.path.join(json_dir, "ai_model.pkl")
78
+ recommendation_system.save_ai_model(model_path)
79
+
80
+ try:
81
+ requests.post(FORWARD_URL, json=response_payload, timeout=10)
82
+ except requests.exceptions.RequestException as e:
83
+ print(f"Warning: Failed to forward data to report API: {str(e)}")
84
+
85
+ return jsonify(response_payload), 200
86
+ except Exception as e:
87
+ return jsonify({"error": str(e)}), 500
88
+
89
+ if __name__ == '__main__':
90
+ port = int(os.environ.get("PORT", 7860))
91
+ app.run(host="0.0.0.0", port=port, debug=False)
data/departments.json ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "program_departments": {
3
+ "Engineering": [
4
+ "Civil Engineering",
5
+ "Mechanical Engineering",
6
+ "Electrical Engineering",
7
+ "Electronics and Communications Engineering",
8
+ "Industrial Engineering",
9
+ "Computer & Systems Engineering"
10
+ ],
11
+ "Medicine": [
12
+ "General Medicine",
13
+ "Surgery",
14
+ "Pediatrics",
15
+ "Obstetrics and Gynecology",
16
+ "Internal Medicine",
17
+ "Orthopedics"
18
+ ],
19
+ "Law": [
20
+ "Civil Law",
21
+ "Criminal Law",
22
+ "International Law",
23
+ "Constitutional Law",
24
+ "Commercial Law"
25
+ ],
26
+ "Computer Science": [
27
+ "Software Engineering",
28
+ "Data Science",
29
+ "Networks and Communications",
30
+ "Information Security",
31
+ "Artificial Intelligence",
32
+ "Human-Computer Interaction"
33
+ ],
34
+ "Business": [
35
+ "Finance",
36
+ "Marketing",
37
+ "Management",
38
+ "Accounting",
39
+ "International Business"
40
+ ],
41
+ "Pharmacy": [
42
+ "Pharmaceutical Chemistry",
43
+ "Clinical Pharmacy",
44
+ "Pharmacognosy",
45
+ "Pharmacology",
46
+ "Biopharmaceutics"
47
+ ],
48
+ "Architecture": [
49
+ "Structural Design",
50
+ "Urban Planning",
51
+ "Interior Design",
52
+ "Landscape Architecture"
53
+ ],
54
+ "Literature": [
55
+ "Modern Arabic Literature",
56
+ "Classical Arabic Literature",
57
+ "Comparative Literature",
58
+ "Linguistics",
59
+ "Translation Studies"
60
+ ],
61
+ "Agriculture": [
62
+ "Agronomy",
63
+ "Horticulture",
64
+ "Agricultural Engineering",
65
+ "Soil and Water Management",
66
+ "Plant Protection"
67
+ ]
68
+ }
69
+ }
data/sample-data.json ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "grades_data": {
3
+ "Mathematics": 92,
4
+ "Physics": 88,
5
+ "Chemistry": 85,
6
+ "Technical Drawing": 75,
7
+ "Mechanics": 80,
8
+ "Biology": 78,
9
+ "Anatomy": 70,
10
+ "Physiology": 68,
11
+ "Programming": 90,
12
+ "Data Structures": 87,
13
+ "Algorithms": 85,
14
+ "Discrete Mathematics": 83,
15
+ "History": 85,
16
+ "Arabic": 90,
17
+ "Political Science": 73,
18
+ "Social Studies": 76,
19
+ "Logic": 74,
20
+ "Economics": 76,
21
+ "Accounting": 80,
22
+ "Business Studies": 82,
23
+ "Marketing": 70,
24
+ "Management": 74,
25
+ "Pharmacology": 88,
26
+ "Organic Chemistry": 84,
27
+ "Biochemistry": 81,
28
+ "Design": 79,
29
+ "Engineering Drawing": 77,
30
+ "Architectural History": 81,
31
+ "World Literature": 80,
32
+ "Creative Writing": 86,
33
+ "English Literature": 88,
34
+ "Agronomy": 83,
35
+ "Plant Science": 81,
36
+ "Soil Science": 79,
37
+ "Irrigation": 76
38
+ }
39
+ }
data/subjects.json ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "core_subjects": {
3
+ "Engineering": [
4
+ "Mathematics",
5
+ "Physics",
6
+ "Chemistry",
7
+ "Technical Drawing",
8
+ "Mechanics"
9
+ ],
10
+ "Medicine": [
11
+ "Biology",
12
+ "Chemistry",
13
+ "Physics",
14
+ "Anatomy",
15
+ "Physiology"
16
+ ],
17
+ "Law": [
18
+ "History",
19
+ "Arabic",
20
+ "Political Science",
21
+ "Social Studies",
22
+ "Logic"
23
+ ],
24
+ "Computer Science": [
25
+ "Mathematics",
26
+ "Programming",
27
+ "Data Structures",
28
+ "Algorithms",
29
+ "Discrete Mathematics"
30
+ ],
31
+ "Business": [
32
+ "Economics",
33
+ "Accounting",
34
+ "Business Studies",
35
+ "Marketing",
36
+ "Management"
37
+ ],
38
+ "Pharmacy": [
39
+ "Biology",
40
+ "Chemistry",
41
+ "Pharmacology",
42
+ "Organic Chemistry",
43
+ "Biochemistry"
44
+ ],
45
+ "Architecture": [
46
+ "Mathematics",
47
+ "Physics",
48
+ "Design",
49
+ "Engineering Drawing",
50
+ "Architectural History"
51
+ ],
52
+ "Literature": [
53
+ "Arabic",
54
+ "History",
55
+ "World Literature",
56
+ "Creative Writing",
57
+ "English Literature"
58
+ ],
59
+ "Agriculture": [
60
+ "Biology",
61
+ "Chemistry",
62
+ "Agronomy",
63
+ "Plant Science",
64
+ "Soil Science",
65
+ "Irrigation"
66
+ ]
67
+ }
68
+ }
data/universities.json ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "top_universities": {
3
+ "Engineering": [
4
+ "Cairo University - Faculty of Engineering",
5
+ "Ain Shams University - Faculty of Engineering",
6
+ "Alexandria University - Faculty of Engineering",
7
+ "Helwan University - Faculty of Engineering",
8
+ "Mansoura University - Faculty of Engineering",
9
+ "Assiut University - Faculty of Engineering",
10
+ "Tanta University - Faculty of Engineering"
11
+ ],
12
+ "Medicine": [
13
+ "Cairo University - Faculty of Medicine",
14
+ "Alexandria University - Faculty of Medicine",
15
+ "Mansoura University - Faculty of Medicine",
16
+ "Assiut University - Faculty of Medicine",
17
+ "Tanta University - Faculty of Medicine"
18
+ ],
19
+ "Law": [
20
+ "Cairo University - Faculty of Law",
21
+ "Ain Shams University - Faculty of Law",
22
+ "Alexandria University - Faculty of Law",
23
+ "Mansoura University - Faculty of Law",
24
+ "Zagazig University - Faculty of Law"
25
+ ],
26
+ "Computer Science": [
27
+ "The American University in Cairo",
28
+ "Cairo University - Faculty of Computers and Information",
29
+ "Ain Shams University - Faculty of Computers and Information",
30
+ "Helwan University - Faculty of Computers and Information",
31
+ "Alexandria University - Faculty of Information Technology"
32
+ ],
33
+ "Business": [
34
+ "Cairo University - Faculty of Commerce",
35
+ "Ain Shams University - Faculty of Commerce",
36
+ "Alexandria University - Faculty of Commerce",
37
+ "Helwan University - Faculty of Commerce",
38
+ "Mansoura University - Faculty of Commerce"
39
+ ],
40
+ "Pharmacy": [
41
+ "Cairo University - Faculty of Pharmacy",
42
+ "Ain Shams University - Faculty of Pharmacy",
43
+ "Alexandria University - Faculty of Pharmacy",
44
+ "Mansoura University - Faculty of Pharmacy",
45
+ "Tanta University - Faculty of Pharmacy"
46
+ ],
47
+ "Architecture": [
48
+ "Cairo University - Faculty of Engineering / Architecture",
49
+ "Ain Shams University - Faculty of Architecture",
50
+ "Alexandria University - Faculty of Engineering / Architecture",
51
+ "Helwan University - Faculty of Architecture"
52
+ ],
53
+ "Literature": [
54
+ "Cairo University - Faculty of Arts",
55
+ "Ain Shams University - Faculty of Arts",
56
+ "Alexandria University - Faculty of Arts",
57
+ "Helwan University - Faculty of Arts"
58
+ ],
59
+ "Agriculture": [
60
+ "Cairo University - Faculty of Agriculture",
61
+ "Alexandria University - Faculty of Agriculture",
62
+ "Mansoura University - Faculty of Agriculture",
63
+ "Assiut University - Faculty of Agriculture",
64
+ "Tanta University - Faculty of Agriculture"
65
+ ]
66
+ }
67
+ }
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ Flask==2.3.3
2
+ pandas==2.0.3
3
+ numpy==1.24.3
4
+ scikit-learn==1.3.0
5
+ requests==2.31.0
6
+ Werkzeug==2.3.7
student_recommendation_system.py ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import numpy as np
3
+ import json
4
+ import os
5
+ import logging
6
+ import pickle
7
+ from sklearn.pipeline import Pipeline
8
+ from sklearn.preprocessing import StandardScaler
9
+ from sklearn.linear_model import LinearRegression
10
+ from sklearn.metrics import f1_score, mean_absolute_error, accuracy_score, precision_score, recall_score
11
+
12
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s]: %(message)s")
13
+
14
+ class StudentRecommendationSystem:
15
+ def __init__(self, json_dir: str = "./data"):
16
+ self.json_dir = json_dir
17
+ try:
18
+ with open(os.path.join(json_dir, "subjects.json"), "r") as f:
19
+ subjects_data = json.load(f)
20
+ self.core_subjects = subjects_data["core_subjects"]
21
+ logging.info("Loaded subjects data successfully.")
22
+ except Exception as e:
23
+ logging.error("Error loading subjects data: " + str(e))
24
+ raise
25
+ try:
26
+ with open(os.path.join(json_dir, "universities.json"), "r") as f:
27
+ universities_data = json.load(f)
28
+ self.top_universities = universities_data["top_universities"]
29
+ logging.info("Loaded universities data successfully.")
30
+ except Exception as e:
31
+ logging.error("Error loading universities data: " + str(e))
32
+ raise
33
+ try:
34
+ with open(os.path.join(json_dir, "departments.json"), "r") as f:
35
+ departments_data = json.load(f)
36
+ self.program_departments = departments_data["program_departments"]
37
+ logging.info("Loaded departments data successfully.")
38
+ except Exception as e:
39
+ logging.error("Error loading departments data: " + str(e))
40
+ raise
41
+ self.university_programs = {}
42
+ for program in self.core_subjects:
43
+ self.university_programs[program] = {"core_subjects": self.core_subjects[program]}
44
+ logging.info("University programs mapping created.")
45
+ self.ai_model = self._train_dummy_model()
46
+
47
+ def _train_dummy_model(self) -> Pipeline:
48
+ X = np.array([[0], [50], [100]])
49
+ y = np.array([0, 50, 100])
50
+ pipeline = Pipeline([
51
+ ('scaler', StandardScaler()),
52
+ ('regressor', LinearRegression())
53
+ ])
54
+ pipeline.fit(X, y)
55
+ logging.info("Dummy AI model pipeline trained successfully.")
56
+ return pipeline
57
+
58
+ def _refine_match_score(self, score: float) -> float:
59
+ refined = self.ai_model.predict(np.array([[score]]))[0]
60
+ logging.debug(f"Refined score for raw score {score} is {refined}.")
61
+ return refined
62
+
63
+ def predict_success_probability(self, refined_score: float) -> float:
64
+ probability = refined_score / 100.0
65
+ logging.debug(f"Predicted success probability from refined score {refined_score} is {probability}.")
66
+ return probability
67
+
68
+ def load_student_grades(self, grades_data: dict = None, grades_file: str = None) -> pd.DataFrame:
69
+ if grades_file:
70
+ try:
71
+ with open(grades_file, "r") as f:
72
+ grades_data = json.load(f)
73
+ if "sample_grades" in grades_data:
74
+ grades_data = grades_data["sample_grades"]
75
+ logging.info(f"Student grades loaded from file: {grades_file}")
76
+ except Exception as e:
77
+ logging.error("Error loading student grades file: " + str(e))
78
+ raise
79
+ if not grades_data:
80
+ raise ValueError("Either grades_data or grades_file must be provided")
81
+ self.student_data = pd.DataFrame(list(grades_data.items()), columns=['Subject', 'Grade'])
82
+ return self.student_data
83
+
84
+ def identify_strengths(self, threshold: float = 85) -> pd.DataFrame:
85
+ strengths = self.student_data[self.student_data['Grade'] >= threshold]
86
+ return strengths.sort_values(by='Grade', ascending=False)
87
+
88
+ def calculate_program_match(self, strengths: pd.DataFrame) -> pd.DataFrame:
89
+ program_scores = {}
90
+ for program, details in self.university_programs.items():
91
+ score = 0
92
+ core_subjects = details["core_subjects"]
93
+ total_possible_score = len(core_subjects) * 100
94
+ for subject in core_subjects:
95
+ subject_grade = self.student_data[self.student_data['Subject'] == subject]
96
+ if not subject_grade.empty:
97
+ score += subject_grade.iloc[0]['Grade']
98
+ raw_score = (score / total_possible_score) * 100 if total_possible_score > 0 else 0
99
+ refined_score = self._refine_match_score(raw_score)
100
+ success_probability = self.predict_success_probability(refined_score)
101
+ program_scores[program] = {
102
+ "raw_score": raw_score,
103
+ "refined_score": refined_score,
104
+ "success_probability": success_probability
105
+ }
106
+ logging.debug(f"Program {program}: raw_score {raw_score}, refined_score {refined_score}, success_probability {success_probability}")
107
+ program_df = pd.DataFrame([
108
+ {"Program": program,
109
+ "Raw Score": scores["raw_score"],
110
+ "AI Refined Score": scores["refined_score"],
111
+ "Success Probability": scores["success_probability"]}
112
+ for program, scores in program_scores.items()
113
+ ])
114
+ return program_df.sort_values(by='AI Refined Score', ascending=False)
115
+
116
+ def get_top_recommendations(self, program_matches: pd.DataFrame, top_n: int = 3) -> list:
117
+ recommendations = []
118
+ for i in range(min(top_n, len(program_matches))):
119
+ program = program_matches.iloc[i]['Program']
120
+ raw_score = program_matches.iloc[i]['Raw Score']
121
+ refined_score = program_matches.iloc[i]['AI Refined Score']
122
+ success_probability = program_matches.iloc[i]['Success Probability']
123
+ if refined_score >= 50:
124
+ universities = self.top_universities.get(program, ["No specific recommendations"])
125
+ departments = self.program_departments.get(program, ["No specific departments"])
126
+ recommendations.append({
127
+ "program": program,
128
+ "raw_score": raw_score,
129
+ "refined_score": refined_score,
130
+ "success_probability": success_probability,
131
+ "recommended_universities": universities[:3],
132
+ "recommended_departments": departments[:3]
133
+ })
134
+ return recommendations
135
+
136
+ def evaluate_recommendations(self, program_matches_df: pd.DataFrame, ground_truth: dict, threshold: float = 60) -> dict:
137
+ predictions = program_matches_df.apply(lambda row: 1 if row["AI Refined Score"] >= threshold else 0, axis=1).tolist()
138
+ actuals = [ground_truth.get(program, 0) for program in program_matches_df["Program"].tolist()]
139
+ metrics = {
140
+ "f1_score": f1_score(actuals, predictions),
141
+ "accuracy": accuracy_score(actuals, predictions),
142
+ "precision": precision_score(actuals, predictions, zero_division=0),
143
+ "recall": recall_score(actuals, predictions, zero_division=0),
144
+ "mae": mean_absolute_error(actuals, predictions)
145
+ }
146
+ logging.info("Evaluation metrics computed.")
147
+ return metrics
148
+
149
+ def save_ai_model(self, file_path: str) -> None:
150
+ try:
151
+ with open(file_path, "wb") as f:
152
+ pickle.dump(self.ai_model, f)
153
+ logging.info(f"AI model saved to {file_path}")
154
+ except Exception as e:
155
+ logging.error("Error saving AI model: " + str(e))
156
+ raise
157
+
158
+ def load_ai_model(self, file_path: str) -> None:
159
+ try:
160
+ with open(file_path, "rb") as f:
161
+ self.ai_model = pickle.load(f)
162
+ logging.info(f"AI model loaded from {file_path}")
163
+ except Exception as e:
164
+ logging.error("Error loading AI model: " + str(e))
165
+ raise
166
+
167
+ def process_student_data(self, grades_data: dict = None, grades_file: str = None, strength_threshold: float = 85) -> dict:
168
+ self.load_student_grades(grades_data, grades_file)
169
+ strengths = self.identify_strengths(strength_threshold)
170
+ program_matches = self.calculate_program_match(strengths)
171
+ recommendations = self.get_top_recommendations(program_matches)
172
+ report = {
173
+ "strengths": strengths.to_dict('records'),
174
+ "program_matches": program_matches.to_dict('records'),
175
+ "top_recommendations": recommendations
176
+ }
177
+ return report
178
+
179
+ def setup_json_directory(json_dir: str = "./data") -> str:
180
+ if not os.path.exists(json_dir):
181
+ os.makedirs(json_dir)
182
+ return json_dir
183
+
184
+ def main():
185
+ json_dir = setup_json_directory()
186
+ sample_data_file = os.path.join(json_dir, "sample-data.json")
187
+ recommendation_system = StudentRecommendationSystem(json_dir)
188
+ results = recommendation_system.process_student_data(grades_file=sample_data_file)
189
+ with open(sample_data_file, "r") as f:
190
+ sample_data = json.load(f)
191
+ sample_grades = sample_data["sample_grades"]
192
+ print("\n===== STUDENT ACADEMIC PROFILE =====")
193
+ print("\nSubjects and Grades:")
194
+ for subject in sample_grades:
195
+ print(f"- {subject}: {sample_grades[subject]}")
196
+ print("\n===== ACADEMIC STRENGTHS =====")
197
+ for strength in results["strengths"]:
198
+ print(f"- {strength['Subject']}: {strength['Grade']}")
199
+ print("\n===== PROGRAM MATCHES (Including AI Details) =====")
200
+ for match in results["program_matches"]:
201
+ print(f"- {match['Program']}: Raw Score = {match['Raw Score']:.1f}%, AI Refined Score = {match['AI Refined Score']:.1f}%, Success Probability = {match['Success Probability']:.2f}")
202
+ print("\n===== PROGRAM RECOMMENDATIONS =====")
203
+ for i, rec in enumerate(results["top_recommendations"], 1):
204
+ print(f"\n{i}. {rec['program']} (Raw Score: {rec['raw_score']:.1f}%, AI Refined Score: {rec['refined_score']:.1f}%, Success Probability: {rec['success_probability']:.2f})")
205
+ print(" Recommended Universities:")
206
+ for uni in rec['recommended_universities']:
207
+ print(f" - {uni}")
208
+ print(" Recommended Departments:")
209
+ for dept in rec['recommended_departments']:
210
+ print(f" - {dept}")
211
+ program_matches_df = pd.DataFrame(results["program_matches"])
212
+ dummy_ground_truth = {row["Program"]: (1 if row["Raw Score"] >= 65 else 0) for idx, row in program_matches_df.iterrows()}
213
+ evaluation_metrics = recommendation_system.evaluate_recommendations(program_matches_df, dummy_ground_truth)
214
+ print("\n===== EVALUATION METRICS =====")
215
+ for metric, value in evaluation_metrics.items():
216
+ print(f"{metric.capitalize()}: {value:.2f}")
217
+ recommendation_system.save_ai_model(os.path.join(json_dir, "ai_model.pkl"))
218
+
219
+ if __name__ == "__main__":
220
+ main()