work-sejal commited on
Commit
11c4b38
·
1 Parent(s): 2657667

Add artifacts/models to HF Space repo and fix ignore rules

Browse files
Files changed (45) hide show
  1. artifacts/models/answer_scorer/.gitkeep +0 -0
  2. artifacts/models/answer_scorer/metrics.json +45 -0
  3. artifacts/models/answer_scorer/model.joblib +3 -0
  4. artifacts/models/answer_scorer/model_card.md +51 -0
  5. artifacts/models/answer_scorer/training_config.json +26 -0
  6. artifacts/models/answer_scorer/vectorizer.joblib +3 -0
  7. artifacts/models/bloom_classifier/.gitkeep +0 -0
  8. artifacts/models/bloom_classifier/label_encoder.joblib +3 -0
  9. artifacts/models/bloom_classifier/metrics.json +204 -0
  10. artifacts/models/bloom_classifier/model.joblib +3 -0
  11. artifacts/models/bloom_classifier/model_card.md +47 -0
  12. artifacts/models/bloom_classifier/training_config.json +28 -0
  13. artifacts/models/bloom_classifier/vectorizer.joblib +3 -0
  14. artifacts/models/difficulty_model/encoder.joblib +3 -0
  15. artifacts/models/difficulty_model/feature_columns.json +6 -0
  16. artifacts/models/difficulty_model/metrics.json +38 -0
  17. artifacts/models/difficulty_model/model.joblib +3 -0
  18. artifacts/models/difficulty_model/model_card.md +50 -0
  19. artifacts/models/difficulty_model/training_config.json +33 -0
  20. artifacts/models/lo_tagger/.gitkeep +0 -0
  21. artifacts/models/lo_tagger/label_encoder.joblib +3 -0
  22. artifacts/models/lo_tagger/metrics.json +0 -0
  23. artifacts/models/lo_tagger/model.joblib +3 -0
  24. artifacts/models/lo_tagger/model_card.md +50 -0
  25. artifacts/models/lo_tagger/training_config.json +27 -0
  26. artifacts/models/lo_tagger/vectorizer.joblib +3 -0
  27. artifacts/models/mastery_model/.gitkeep +0 -0
  28. artifacts/models/mastery_model/feature_columns.json +11 -0
  29. artifacts/models/mastery_model/metrics.json +132 -0
  30. artifacts/models/mastery_model/model.joblib +3 -0
  31. artifacts/models/mastery_model/model_card.md +56 -0
  32. artifacts/models/mastery_model/training_config.json +35 -0
  33. artifacts/models/recommender/.gitkeep +0 -0
  34. artifacts/models/recommender/encoder.joblib +3 -0
  35. artifacts/models/recommender/feature_columns.json +7 -0
  36. artifacts/models/recommender/metrics.json +33 -0
  37. artifacts/models/recommender/model.joblib +3 -0
  38. artifacts/models/recommender/model_card.md +53 -0
  39. artifacts/models/recommender/training_config.json +39 -0
  40. artifacts/models/risk_model/.gitkeep +0 -0
  41. artifacts/models/risk_model/feature_columns.json +21 -0
  42. artifacts/models/risk_model/metrics.json +101 -0
  43. artifacts/models/risk_model/model.joblib +3 -0
  44. artifacts/models/risk_model/model_card.md +71 -0
  45. artifacts/models/risk_model/training_config.json +44 -0
artifacts/models/answer_scorer/.gitkeep ADDED
File without changes
artifacts/models/answer_scorer/metrics.json ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "answer_scorer",
3
+ "model_version": "answer_scorer_v2_baseline_001",
4
+ "dataset_version": "2.0.0",
5
+ "trained_at": "2026-05-22T05:33:11.363132+00:00",
6
+ "seed": 20260520,
7
+ "split_counts": {
8
+ "train": 8371,
9
+ "validation": 1820,
10
+ "test": 1809
11
+ },
12
+ "metrics": {
13
+ "validation": {
14
+ "mae": 0.4787,
15
+ "rmse": 0.773,
16
+ "r_squared": 0.718,
17
+ "distribution": {
18
+ "predicted_mean": 1.8303,
19
+ "predicted_std": 0.9736,
20
+ "actual_mean": 2.0455,
21
+ "actual_std": 1.4557
22
+ },
23
+ "pct_above_review_threshold": 16.87
24
+ },
25
+ "test": {
26
+ "mae": 0.5256,
27
+ "rmse": 0.8385,
28
+ "r_squared": 0.6791,
29
+ "distribution": {
30
+ "predicted_mean": 1.8985,
31
+ "predicted_std": 0.9581,
32
+ "actual_mean": 2.174,
33
+ "actual_std": 1.4803
34
+ },
35
+ "pct_above_review_threshold": 19.68
36
+ }
37
+ },
38
+ "limitations": [
39
+ "Trained on synthetic data only.",
40
+ "TF-IDF features do not capture deep semantic similarity.",
41
+ "Predictions clipped to [0, max_marks] range.",
42
+ "teacher_review_required is always True in V2 baseline.",
43
+ "MAE is the primary metric; individual predictions may deviate significantly."
44
+ ]
45
+ }
artifacts/models/answer_scorer/model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9f526fa2fd7fdd63a024d3c47d7259efbd85fd8133b0ea12cfc070dc0194109d
3
+ size 8524
artifacts/models/answer_scorer/model_card.md ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Model Card: Answer Scorer
2
+
3
+ ## Model Details
4
+
5
+ - **Model Name:** answer_scorer
6
+ - **Model Version:** answer_scorer_v2_baseline_001
7
+ - **Algorithm:** TF-IDF + Ridge Regression
8
+ - **Framework:** scikit-learn
9
+ - **Trained At:** 2026-05-22T05:33:11.363132+00:00
10
+ - **Seed:** 20260520
11
+
12
+ ## Intended Use
13
+
14
+ Score subjective student answers against a rubric and model answer.
15
+ Produces a predicted marks value clipped to [0, max_marks]. Always sets
16
+ teacher_review_required=True in V2 baseline — predictions are advisory only.
17
+
18
+ ## Training Data
19
+
20
+ - **Source:** training_answer_scoring.csv (synthetic dataset v2)
21
+ - **Split Counts:** train=8371, validation=1820, test=1809
22
+ - **Features:** student_answer (TF-IDF, max_features=5000, ngram_range=(1,2)) + rubric_match_score + concept_coverage_score
23
+ - **Target:** teacher_marks (continuous)
24
+
25
+ ## Metrics
26
+
27
+ ### Validation Set
28
+ - MAE: 0.4787
29
+ - RMSE: 0.773
30
+ - R-squared: 0.718
31
+ - % Above Review Threshold (>1.0): 16.87%
32
+
33
+ ### Test Set
34
+ - MAE: 0.5256
35
+ - RMSE: 0.8385
36
+ - R-squared: 0.6791
37
+ - % Above Review Threshold (>1.0): 19.68%
38
+
39
+ ## Known Limitations
40
+
41
+ - Trained on synthetic data only — performance on real student answers is unknown.
42
+ - TF-IDF features do not capture deep semantic similarity or paraphrasing.
43
+ - Predictions are clipped to [0, max_marks]; the model may predict outside this range before clipping.
44
+ - teacher_review_required is always True in V2 baseline.
45
+ - MAE is the primary metric; individual predictions may deviate significantly from teacher marks.
46
+
47
+ ## Fallback Behavior
48
+
49
+ When the model is not loaded or confidence is below threshold,
50
+ the system falls back to rubric keyword coverage + length heuristic,
51
+ always setting teacher_review_required=True.
artifacts/models/answer_scorer/training_config.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "answer_scorer",
3
+ "model_version": "answer_scorer_v2_baseline_001",
4
+ "dataset_version": "2.0.0",
5
+ "seed": 20260520,
6
+ "split_counts": {
7
+ "train": 8371,
8
+ "validation": 1820,
9
+ "test": 1809
10
+ },
11
+ "hyperparameters": {
12
+ "tfidf_max_features": 5000,
13
+ "ngram_range": [
14
+ 1,
15
+ 2
16
+ ],
17
+ "ridge_alpha": 1.0
18
+ },
19
+ "feature_columns": [
20
+ "student_answer (TF-IDF)",
21
+ "rubric_match_score",
22
+ "concept_coverage_score"
23
+ ],
24
+ "target_column": "teacher_marks",
25
+ "algorithm": "TF-IDF + Ridge regression"
26
+ }
artifacts/models/answer_scorer/vectorizer.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a8210b922548969cb609cb8e7c93590e064bfd2208b10647c993f51482bc0442
3
+ size 26983
artifacts/models/bloom_classifier/.gitkeep ADDED
File without changes
artifacts/models/bloom_classifier/label_encoder.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:49cd11f5861283c0d8da24d21a2f021791eb64ea0d971e21e6d76ce16c3f2b7f
3
+ size 439
artifacts/models/bloom_classifier/metrics.json ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "bloom_classifier",
3
+ "model_version": "bloom_classifier_v2_baseline_001",
4
+ "dataset_version": "2.0.0",
5
+ "trained_at": "2026-05-22T05:33:07.050037+00:00",
6
+ "seed": 20260520,
7
+ "split_counts": {
8
+ "train": 3912,
9
+ "validation": 1033,
10
+ "test": 875
11
+ },
12
+ "metrics": {
13
+ "validation": {
14
+ "macro_f1": 0.6434,
15
+ "weighted_f1": 0.6634,
16
+ "per_class": {
17
+ "Analyze": {
18
+ "precision": 0.614,
19
+ "recall": 0.6774,
20
+ "f1": 0.6442,
21
+ "support": 155
22
+ },
23
+ "Apply": {
24
+ "precision": 0.65,
25
+ "recall": 0.5778,
26
+ "f1": 0.6118,
27
+ "support": 270
28
+ },
29
+ "Create": {
30
+ "precision": 0.8947,
31
+ "recall": 1.0,
32
+ "f1": 0.9444,
33
+ "support": 17
34
+ },
35
+ "Evaluate": {
36
+ "precision": 1.0,
37
+ "recall": 0.1522,
38
+ "f1": 0.2642,
39
+ "support": 46
40
+ },
41
+ "Remember": {
42
+ "precision": 0.7438,
43
+ "recall": 0.5732,
44
+ "f1": 0.6475,
45
+ "support": 157
46
+ },
47
+ "Understand": {
48
+ "precision": 0.68,
49
+ "recall": 0.8325,
50
+ "f1": 0.7486,
51
+ "support": 388
52
+ }
53
+ },
54
+ "confusion_matrix": [
55
+ [
56
+ 105,
57
+ 50,
58
+ 0,
59
+ 0,
60
+ 0,
61
+ 0
62
+ ],
63
+ [
64
+ 27,
65
+ 156,
66
+ 0,
67
+ 0,
68
+ 0,
69
+ 87
70
+ ],
71
+ [
72
+ 0,
73
+ 0,
74
+ 17,
75
+ 0,
76
+ 0,
77
+ 0
78
+ ],
79
+ [
80
+ 37,
81
+ 0,
82
+ 2,
83
+ 7,
84
+ 0,
85
+ 0
86
+ ],
87
+ [
88
+ 0,
89
+ 2,
90
+ 0,
91
+ 0,
92
+ 90,
93
+ 65
94
+ ],
95
+ [
96
+ 2,
97
+ 32,
98
+ 0,
99
+ 0,
100
+ 31,
101
+ 323
102
+ ]
103
+ ]
104
+ },
105
+ "test": {
106
+ "macro_f1": 0.6178,
107
+ "weighted_f1": 0.6654,
108
+ "per_class": {
109
+ "Analyze": {
110
+ "precision": 0.7,
111
+ "recall": 0.6853,
112
+ "f1": 0.6926,
113
+ "support": 143
114
+ },
115
+ "Apply": {
116
+ "precision": 0.6411,
117
+ "recall": 0.5678,
118
+ "f1": 0.6022,
119
+ "support": 236
120
+ },
121
+ "Create": {
122
+ "precision": 0.8333,
123
+ "recall": 0.9375,
124
+ "f1": 0.8824,
125
+ "support": 16
126
+ },
127
+ "Evaluate": {
128
+ "precision": 0.6667,
129
+ "recall": 0.0588,
130
+ "f1": 0.1081,
131
+ "support": 34
132
+ },
133
+ "Remember": {
134
+ "precision": 0.7677,
135
+ "recall": 0.608,
136
+ "f1": 0.6786,
137
+ "support": 125
138
+ },
139
+ "Understand": {
140
+ "precision": 0.665,
141
+ "recall": 0.8411,
142
+ "f1": 0.7428,
143
+ "support": 321
144
+ }
145
+ },
146
+ "confusion_matrix": [
147
+ [
148
+ 98,
149
+ 45,
150
+ 0,
151
+ 0,
152
+ 0,
153
+ 0
154
+ ],
155
+ [
156
+ 13,
157
+ 134,
158
+ 0,
159
+ 0,
160
+ 0,
161
+ 89
162
+ ],
163
+ [
164
+ 0,
165
+ 0,
166
+ 15,
167
+ 1,
168
+ 0,
169
+ 0
170
+ ],
171
+ [
172
+ 29,
173
+ 0,
174
+ 3,
175
+ 2,
176
+ 0,
177
+ 0
178
+ ],
179
+ [
180
+ 0,
181
+ 2,
182
+ 0,
183
+ 0,
184
+ 76,
185
+ 47
186
+ ],
187
+ [
188
+ 0,
189
+ 28,
190
+ 0,
191
+ 0,
192
+ 23,
193
+ 270
194
+ ]
195
+ ]
196
+ }
197
+ },
198
+ "limitations": [
199
+ "Trained on synthetic data only.",
200
+ "6 classes with imbalanced distribution \u2014 Create (~2%) and Evaluate (~4%) are rare.",
201
+ "Macro F1 is the primary metric; per-class recall may be low for rare classes.",
202
+ "TF-IDF features do not capture semantic similarity beyond n-gram overlap."
203
+ ]
204
+ }
artifacts/models/bloom_classifier/model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c536885f0c45c7cb0318e5a65db523761d0e02b1ce5798e82b1764e4f4dd2d3d
3
+ size 76782
artifacts/models/bloom_classifier/model_card.md ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Model Card: Bloom Classifier
2
+
3
+ ## Model Details
4
+
5
+ - **Model Name:** bloom_classifier
6
+ - **Model Version:** bloom_classifier_v2_baseline_001
7
+ - **Algorithm:** TF-IDF + LogisticRegression (multinomial)
8
+ - **Framework:** scikit-learn
9
+ - **Trained At:** 2026-05-22T05:33:07.050037+00:00
10
+ - **Seed:** 20260520
11
+
12
+ ## Intended Use
13
+
14
+ Automatically classify questions by Bloom's taxonomy cognitive level.
15
+ Used in the Bloom classification endpoint to predict one of 6 levels:
16
+ Remember, Understand, Apply, Analyze, Evaluate, Create.
17
+
18
+ ## Training Data
19
+
20
+ - **Source:** training_bloom_classification.csv (synthetic dataset v2)
21
+ - **Split Counts:** train=3912, validation=1033, test=875
22
+ - **Feature:** question_text (TF-IDF vectorized, max_features=8000, ngram_range=(1,2))
23
+ - **Target:** bloom_level (6 classes)
24
+
25
+ ## Metrics
26
+
27
+ ### Validation Set
28
+ - Macro F1: 0.6434
29
+ - Weighted F1: 0.6634
30
+
31
+ ### Test Set
32
+ - Macro F1: 0.6178
33
+ - Weighted F1: 0.6654
34
+
35
+ ## Known Limitations
36
+
37
+ - Trained on synthetic data only — performance on real classroom questions is unknown.
38
+ - Class imbalance: Create (~2%) and Evaluate (~4%) are rare; recall on these classes may be low.
39
+ - TF-IDF features do not capture semantic similarity beyond n-gram overlap.
40
+ - Macro F1 is the primary metric; accuracy alone would mask poor performance on rare classes.
41
+
42
+ ## Fallback Behavior
43
+
44
+ When the model is not loaded or confidence is below the threshold (0.55),
45
+ the system falls back to keyword heuristic classification:
46
+ define/list → Remember; explain → Understand; calculate/use → Apply;
47
+ compare/contrast → Analyze; justify → Evaluate; design → Create.
artifacts/models/bloom_classifier/training_config.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "bloom_classifier",
3
+ "model_version": "bloom_classifier_v2_baseline_001",
4
+ "dataset_version": "2.0.0",
5
+ "seed": 20260520,
6
+ "split_counts": {
7
+ "train": 3912,
8
+ "validation": 1033,
9
+ "test": 875
10
+ },
11
+ "hyperparameters": {
12
+ "tfidf_max_features": 8000,
13
+ "ngram_range": [
14
+ 1,
15
+ 2
16
+ ],
17
+ "sublinear_tf": true,
18
+ "logreg_C": 1.0,
19
+ "logreg_solver": "lbfgs",
20
+ "logreg_max_iter": 1000,
21
+ "logreg_multi_class": "multinomial"
22
+ },
23
+ "feature_columns": [
24
+ "question_text"
25
+ ],
26
+ "target_column": "bloom_level",
27
+ "algorithm": "LogisticRegression(multinomial)"
28
+ }
artifacts/models/bloom_classifier/vectorizer.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a1aef70da6176b150f33ce072efdda54115a07b9e1dacc2b2bf25daad5670b49
3
+ size 31067
artifacts/models/difficulty_model/encoder.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:781bac207e91e216ba726703b113d6646eabe3f46567205b10088621e6404f47
3
+ size 704
artifacts/models/difficulty_model/feature_columns.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ [
2
+ "bloom_score",
3
+ "grade",
4
+ "subject",
5
+ "question_type"
6
+ ]
artifacts/models/difficulty_model/metrics.json ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "difficulty_model",
3
+ "model_version": "difficulty_model_v2_baseline_001",
4
+ "dataset_version": "2.0.0",
5
+ "trained_at": "2026-05-22T05:33:07.506348+00:00",
6
+ "seed": 20260520,
7
+ "split_counts": {
8
+ "train": 3912,
9
+ "validation": 1033,
10
+ "test": 875
11
+ },
12
+ "metrics": {
13
+ "validation": {
14
+ "mae": 0.3477,
15
+ "r_squared": 0.5007,
16
+ "per_bucket_mae": {
17
+ "easy": 0.3051,
18
+ "medium": 0.2958,
19
+ "hard": 0.6525
20
+ }
21
+ },
22
+ "test": {
23
+ "mae": 0.3514,
24
+ "r_squared": 0.4693,
25
+ "per_bucket_mae": {
26
+ "easy": 0.3241,
27
+ "medium": 0.2903,
28
+ "hard": 0.6728
29
+ }
30
+ }
31
+ },
32
+ "limitations": [
33
+ "Trained on synthetic data only.",
34
+ "difficulty_score distribution may not reflect real-world difficulty.",
35
+ "OrdinalEncoder assumes an ordering that may not be meaningful for subject/question_type.",
36
+ "Per-bucket MAE depends on the quality of the difficulty string labels."
37
+ ]
38
+ }
artifacts/models/difficulty_model/model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:87924be76fe290bfce10dec3bbbe137fd942314538029843c12798f3da975e98
3
+ size 735477
artifacts/models/difficulty_model/model_card.md ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Model Card: Difficulty Model
2
+
3
+ ## Model Details
4
+
5
+ - **Model Name:** difficulty_model
6
+ - **Model Version:** difficulty_model_v2_baseline_001
7
+ - **Algorithm:** RandomForestRegressor
8
+ - **Framework:** scikit-learn
9
+ - **Trained At:** 2026-05-22T05:33:07.506348+00:00
10
+ - **Seed:** 20260520
11
+
12
+ ## Intended Use
13
+
14
+ Estimate question difficulty as a continuous score in [0, 1] based on
15
+ question features (bloom_score, grade, subject, question_type). Used in
16
+ the difficulty estimation endpoint to predict how hard a question is for
17
+ a given grade level.
18
+
19
+ ## Training Data
20
+
21
+ - **Source:** training_lo_tagging.csv + questions.csv (for question_type)
22
+ - **Split Counts:** train=3912, validation=1033, test=875
23
+ - **Features:** bloom_score (numeric), grade (numeric), subject (OrdinalEncoded), question_type (OrdinalEncoded)
24
+ - **Target:** difficulty_score (continuous [0, 1])
25
+
26
+ ## Metrics
27
+
28
+ ### Validation Set
29
+ - MAE: 0.3477
30
+ - R-squared: 0.5007
31
+ - Per-bucket MAE: {'easy': 0.3051, 'medium': 0.2958, 'hard': 0.6525}
32
+
33
+ ### Test Set
34
+ - MAE: 0.3514
35
+ - R-squared: 0.4693
36
+ - Per-bucket MAE: {'easy': 0.3241, 'medium': 0.2903, 'hard': 0.6728}
37
+
38
+ ## Known Limitations
39
+
40
+ - Trained on synthetic data only — performance on real questions is unknown.
41
+ - difficulty_score distribution may not reflect real-world difficulty.
42
+ - OrdinalEncoder assumes an ordering that may not be meaningful for subject/question_type.
43
+ - Per-bucket MAE depends on the quality of the difficulty string labels.
44
+ - Limited feature set (4 features); text-based features could improve performance.
45
+
46
+ ## Fallback Behavior
47
+
48
+ When the model is not loaded or confidence is below threshold, the system
49
+ falls back to a rule-based difficulty estimation using bloom_score and
50
+ grade-level heuristics.
artifacts/models/difficulty_model/training_config.json ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "difficulty_model",
3
+ "model_version": "difficulty_model_v2_baseline_001",
4
+ "dataset_version": "2.0.0",
5
+ "seed": 20260520,
6
+ "split_counts": {
7
+ "train": 3912,
8
+ "validation": 1033,
9
+ "test": 875
10
+ },
11
+ "hyperparameters": {
12
+ "n_estimators": 100,
13
+ "random_state": 20260520,
14
+ "algorithm": "RandomForestRegressor",
15
+ "encoder": "OrdinalEncoder"
16
+ },
17
+ "feature_columns": [
18
+ "bloom_score",
19
+ "grade",
20
+ "subject",
21
+ "question_type"
22
+ ],
23
+ "categorical_columns": [
24
+ "subject",
25
+ "question_type"
26
+ ],
27
+ "numeric_columns": [
28
+ "bloom_score",
29
+ "grade"
30
+ ],
31
+ "target_column": "difficulty_score",
32
+ "algorithm": "RandomForestRegressor"
33
+ }
artifacts/models/lo_tagger/.gitkeep ADDED
File without changes
artifacts/models/lo_tagger/label_encoder.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:42e9faea136d20cf19963170fc609d0f3a02b28b6d2e3e376b79739b3f043e43
3
+ size 1147
artifacts/models/lo_tagger/metrics.json ADDED
The diff for this file is too large to render. See raw diff
 
artifacts/models/lo_tagger/model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1178f614787d62a4f6a96764052381a23df9018505e1f8979110d22ea6db925a
3
+ size 7427598
artifacts/models/lo_tagger/model_card.md ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Model Card: LO Tagger
2
+
3
+ ## Model Details
4
+
5
+ - **Model Name:** lo_tagger
6
+ - **Model Version:** lo_tagger_v2_baseline_001
7
+ - **Algorithm:** TF-IDF + CalibratedClassifierCV(LinearSVC)
8
+ - **Framework:** scikit-learn
9
+ - **Trained At:** 2026-05-22T05:33:05.850313+00:00
10
+ - **Seed:** 20260520
11
+
12
+ ## Intended Use
13
+
14
+ Automatically tag questions to their most relevant Learning Outcome (LO).
15
+ Used in the LO tagging endpoint to classify question text into one of 194
16
+ learning outcome categories.
17
+
18
+ ## Training Data
19
+
20
+ - **Source:** training_lo_tagging.csv (synthetic dataset v2)
21
+ - **Split Counts:** train=3912, validation=1033, test=875
22
+ - **Feature:** question_text (TF-IDF vectorized, max_features=10000, ngram_range=(1,2))
23
+ - **Target:** lo_id (194 classes)
24
+
25
+ ## Metrics
26
+
27
+ ### Validation Set
28
+ - Top-1 Accuracy: 0.9245
29
+ - Top-3 Accuracy: 1.0
30
+ - Macro F1: 0.9042
31
+ - Weighted F1: 0.9249
32
+
33
+ ### Test Set
34
+ - Top-1 Accuracy: 0.9097
35
+ - Top-3 Accuracy: 1.0
36
+ - Macro F1: 0.8861
37
+ - Weighted F1: 0.9115
38
+
39
+ ## Known Limitations
40
+
41
+ - Trained on synthetic data only — performance on real classroom questions is unknown.
42
+ - 194 classes with imbalanced distribution; rare LOs may have low recall.
43
+ - TF-IDF features do not capture semantic similarity beyond n-gram overlap.
44
+ - Top-3 accuracy is the primary metric; top-1 may be low for ambiguous questions.
45
+
46
+ ## Fallback Behavior
47
+
48
+ When the model is not loaded or confidence is below the threshold (0.55),
49
+ the system falls back to keyword/embedding match against learning_outcomes.embedding_text
50
+ filtered by grade and subject, returning top-3 with rule-based confidence.
artifacts/models/lo_tagger/training_config.json ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "lo_tagger",
3
+ "model_version": "lo_tagger_v2_baseline_001",
4
+ "dataset_version": "2.0.0",
5
+ "seed": 20260520,
6
+ "split_counts": {
7
+ "train": 3912,
8
+ "validation": 1033,
9
+ "test": 875
10
+ },
11
+ "hyperparameters": {
12
+ "tfidf_max_features": 10000,
13
+ "ngram_range": [
14
+ 1,
15
+ 2
16
+ ],
17
+ "sublinear_tf": true,
18
+ "svc_max_iter": 5000,
19
+ "calibration_cv": 3,
20
+ "calibration_method": "sigmoid"
21
+ },
22
+ "feature_columns": [
23
+ "question_text"
24
+ ],
25
+ "target_column": "lo_id",
26
+ "algorithm": "CalibratedClassifierCV(LinearSVC)"
27
+ }
artifacts/models/lo_tagger/vectorizer.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f40dd0d2353b0d608565093d96e288a624498f2acbfcd007dc993e5f47422606
3
+ size 31068
artifacts/models/mastery_model/.gitkeep ADDED
File without changes
artifacts/models/mastery_model/feature_columns.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ "attempt_count",
3
+ "accuracy",
4
+ "average_marks_ratio",
5
+ "average_time_seconds",
6
+ "hint_usage_rate",
7
+ "attendance_percentage",
8
+ "assignment_completion_rate",
9
+ "average_login_per_week",
10
+ "inactive_days_last_14"
11
+ ]
artifacts/models/mastery_model/metrics.json ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "mastery_model",
3
+ "model_version": "mastery_model_v2_baseline_001",
4
+ "dataset_version": "2.0.0",
5
+ "trained_at": "2026-05-22T05:33:10.125086+00:00",
6
+ "seed": 20260520,
7
+ "split_counts": {
8
+ "train": 24515,
9
+ "validation": 5218,
10
+ "test": 5187
11
+ },
12
+ "metrics": {
13
+ "validation": {
14
+ "macro_f1": 0.8661,
15
+ "weighted_f1": 0.8967,
16
+ "per_class": {
17
+ "weak": {
18
+ "precision": 0.9678,
19
+ "recall": 0.964,
20
+ "f1": 0.9659,
21
+ "support": 2247
22
+ },
23
+ "developing": {
24
+ "precision": 0.8908,
25
+ "recall": 0.9095,
26
+ "f1": 0.9001,
27
+ "support": 1337
28
+ },
29
+ "proficient": {
30
+ "precision": 0.7819,
31
+ "recall": 0.7421,
32
+ "f1": 0.7615,
33
+ "support": 826
34
+ },
35
+ "mastered": {
36
+ "precision": 0.8255,
37
+ "recall": 0.849,
38
+ "f1": 0.8371,
39
+ "support": 808
40
+ }
41
+ },
42
+ "confusion_matrix": [
43
+ [
44
+ 2166,
45
+ 81,
46
+ 0,
47
+ 0
48
+ ],
49
+ [
50
+ 72,
51
+ 1216,
52
+ 49,
53
+ 0
54
+ ],
55
+ [
56
+ 0,
57
+ 68,
58
+ 613,
59
+ 145
60
+ ],
61
+ [
62
+ 0,
63
+ 0,
64
+ 122,
65
+ 686
66
+ ]
67
+ ]
68
+ },
69
+ "test": {
70
+ "macro_f1": 0.8763,
71
+ "weighted_f1": 0.9034,
72
+ "per_class": {
73
+ "weak": {
74
+ "precision": 0.9653,
75
+ "recall": 0.9722,
76
+ "f1": 0.9687,
77
+ "support": 2120
78
+ },
79
+ "developing": {
80
+ "precision": 0.9179,
81
+ "recall": 0.9067,
82
+ "f1": 0.9123,
83
+ "support": 1394
84
+ },
85
+ "proficient": {
86
+ "precision": 0.7887,
87
+ "recall": 0.7518,
88
+ "f1": 0.7698,
89
+ "support": 814
90
+ },
91
+ "mastered": {
92
+ "precision": 0.8354,
93
+ "recall": 0.8743,
94
+ "f1": 0.8544,
95
+ "support": 859
96
+ }
97
+ },
98
+ "confusion_matrix": [
99
+ [
100
+ 2061,
101
+ 59,
102
+ 0,
103
+ 0
104
+ ],
105
+ [
106
+ 74,
107
+ 1264,
108
+ 56,
109
+ 0
110
+ ],
111
+ [
112
+ 0,
113
+ 54,
114
+ 612,
115
+ 148
116
+ ],
117
+ [
118
+ 0,
119
+ 0,
120
+ 108,
121
+ 751
122
+ ]
123
+ ]
124
+ }
125
+ },
126
+ "limitations": [
127
+ "Trained on synthetic data only.",
128
+ "4-class mastery labels derived from synthetic mastery_score thresholds.",
129
+ "All features are numeric; no text or contextual features used.",
130
+ "Class distribution may not reflect real-world mastery patterns."
131
+ ]
132
+ }
artifacts/models/mastery_model/model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:36c2dffc14d2708ee128a0859f3f13453a61400f725ce0b56dcbb488043e1090
3
+ size 6881288
artifacts/models/mastery_model/model_card.md ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Model Card: Mastery Model
2
+
3
+ ## Model Details
4
+
5
+ - **Model Name:** mastery_model
6
+ - **Model Version:** mastery_model_v2_baseline_001
7
+ - **Algorithm:** RandomForestClassifier
8
+ - **Framework:** scikit-learn
9
+ - **Trained At:** 2026-05-22T05:33:10.125086+00:00
10
+ - **Seed:** 20260520
11
+
12
+ ## Intended Use
13
+
14
+ Predict per-student per-LO mastery label (weak, developing, proficient, mastered)
15
+ based on behavioral and performance features. Used in the mastery prediction
16
+ endpoint to classify student mastery level for a given learning outcome.
17
+
18
+ ## Training Data
19
+
20
+ - **Source:** training_mastery_prediction.csv (synthetic dataset v2)
21
+ - **Split Counts:** train=24515, validation=5218, test=5187
22
+ - **Features:** attempt_count, accuracy, average_marks_ratio, average_time_seconds, hint_usage_rate, attendance_percentage, assignment_completion_rate, average_login_per_week, inactive_days_last_14 (all numeric)
23
+ - **Target:** mastery_label (integer 0-3, mapped to weak/developing/proficient/mastered)
24
+
25
+ ## Metrics
26
+
27
+ ### Validation Set
28
+ - Macro F1: 0.8661
29
+ - Weighted F1: 0.8967
30
+
31
+ ### Test Set
32
+ - Macro F1: 0.8763
33
+ - Weighted F1: 0.9034
34
+
35
+ ## Per-Class Performance (Test Set)
36
+
37
+ | Class | Precision | Recall | F1 | Support |
38
+ |-------|-----------|--------|-----|---------|
39
+ | weak | 0.9653 | 0.9722 | 0.9687 | 2120 |
40
+ | developing | 0.9179 | 0.9067 | 0.9123 | 1394 |
41
+ | proficient | 0.7887 | 0.7518 | 0.7698 | 814 |
42
+ | mastered | 0.8354 | 0.8743 | 0.8544 | 859 |
43
+
44
+ ## Known Limitations
45
+
46
+ - Trained on synthetic data only — performance on real student data is unknown.
47
+ - 4-class mastery labels derived from synthetic mastery_score thresholds.
48
+ - All features are numeric; no text or contextual features used.
49
+ - Class distribution may not reflect real-world mastery patterns.
50
+ - No encoding needed since all features are already numeric.
51
+
52
+ ## Fallback Behavior
53
+
54
+ When the model is not loaded or confidence is below the threshold (0.55),
55
+ the system falls back to rule-based mastery estimation using mastery_score
56
+ thresholds: <0.4 weak, <0.6 developing, <0.8 proficient, else mastered.
artifacts/models/mastery_model/training_config.json ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "mastery_model",
3
+ "model_version": "mastery_model_v2_baseline_001",
4
+ "dataset_version": "2.0.0",
5
+ "seed": 20260520,
6
+ "split_counts": {
7
+ "train": 24515,
8
+ "validation": 5218,
9
+ "test": 5187
10
+ },
11
+ "hyperparameters": {
12
+ "n_estimators": 100,
13
+ "random_state": 20260520,
14
+ "algorithm": "RandomForestClassifier"
15
+ },
16
+ "feature_columns": [
17
+ "attempt_count",
18
+ "accuracy",
19
+ "average_marks_ratio",
20
+ "average_time_seconds",
21
+ "hint_usage_rate",
22
+ "attendance_percentage",
23
+ "assignment_completion_rate",
24
+ "average_login_per_week",
25
+ "inactive_days_last_14"
26
+ ],
27
+ "target_column": "mastery_label",
28
+ "label_map": {
29
+ "0": "weak",
30
+ "1": "developing",
31
+ "2": "proficient",
32
+ "3": "mastered"
33
+ },
34
+ "algorithm": "RandomForestClassifier"
35
+ }
artifacts/models/recommender/.gitkeep ADDED
File without changes
artifacts/models/recommender/encoder.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:417a9e093b8090b171f8383bc3772bfca90127b02d17a5b543ec3f5517200d2d
3
+ size 699
artifacts/models/recommender/feature_columns.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ [
2
+ "priority",
3
+ "ai_confidence",
4
+ "recommendation_type",
5
+ "grade",
6
+ "subject"
7
+ ]
artifacts/models/recommender/metrics.json ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "recommender",
3
+ "model_version": "recommender_v2_baseline_001",
4
+ "dataset_version": "2.0.0",
5
+ "trained_at": "2026-05-22T05:33:12.270778+00:00",
6
+ "seed": 20260520,
7
+ "split_counts": {
8
+ "train": 5671,
9
+ "validation": 1214,
10
+ "test": 1215
11
+ },
12
+ "metrics": {
13
+ "validation": {
14
+ "roc_auc_clicked": 0.544,
15
+ "lift_at_10_clicked": 1.1392,
16
+ "roc_auc_is_completed": 0.5299,
17
+ "lift_at_10_is_completed": 1.1056
18
+ },
19
+ "test": {
20
+ "roc_auc_clicked": 0.5486,
21
+ "lift_at_10_clicked": 1.0471,
22
+ "roc_auc_is_completed": 0.5424,
23
+ "lift_at_10_is_completed": 1.0366
24
+ }
25
+ },
26
+ "limitations": [
27
+ "Trained on synthetic data only.",
28
+ "Two separate GBC models \u2014 no joint optimization of clicked + is_completed.",
29
+ "OrdinalEncoder assumes an ordering for priority/recommendation_type/subject.",
30
+ "Lift@10 depends on the distribution of positive labels in the dataset.",
31
+ "No user-level features (e.g., engagement history) included in baseline."
32
+ ]
33
+ }
artifacts/models/recommender/model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:27c6e41ce34d625c1fd10f05537051daf7f4ae871ecf147746eeff7203e83d3d
3
+ size 201527
artifacts/models/recommender/model_card.md ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Model Card: Recommender
2
+
3
+ ## Model Details
4
+
5
+ - **Model Name:** recommender
6
+ - **Model Version:** recommender_v2_baseline_001
7
+ - **Algorithm:** GradientBoostingClassifier (two models: clicked, is_completed)
8
+ - **Framework:** scikit-learn
9
+ - **Trained At:** 2026-05-22T05:33:12.270778+00:00
10
+ - **Seed:** 20260520
11
+
12
+ ## Intended Use
13
+
14
+ Predict whether a student will click on a recommendation and whether they will
15
+ complete the recommended content. Used in the recommendation engine to rank
16
+ content by predicted engagement. Two separate binary classifiers are trained:
17
+ one for `clicked` and one for `is_completed`.
18
+
19
+ ## Training Data
20
+
21
+ - **Source:** training_recommendation_outcomes.csv (synthetic dataset v2)
22
+ - **Split Counts:** train=5671, validation=1214, test=1215
23
+ - **Features:** priority (OrdinalEncoded), ai_confidence (numeric), recommendation_type (OrdinalEncoded), grade (numeric), subject (OrdinalEncoded)
24
+ - **Targets:** clicked (binary), is_completed (binary)
25
+
26
+ ## Metrics
27
+
28
+ ### Validation Set
29
+ - ROC-AUC (clicked): 0.544
30
+ - ROC-AUC (is_completed): 0.5299
31
+ - Lift@10 (clicked): 1.1392
32
+ - Lift@10 (is_completed): 1.1056
33
+
34
+ ### Test Set
35
+ - ROC-AUC (clicked): 0.5486
36
+ - ROC-AUC (is_completed): 0.5424
37
+ - Lift@10 (clicked): 1.0471
38
+ - Lift@10 (is_completed): 1.0366
39
+
40
+ ## Known Limitations
41
+
42
+ - Trained on synthetic data only — performance on real recommendation data is unknown.
43
+ - Two separate GBC models — no joint optimization of clicked + is_completed.
44
+ - OrdinalEncoder assumes an ordering for priority/recommendation_type/subject.
45
+ - Lift@10 depends on the distribution of positive labels in the dataset.
46
+ - No user-level features (e.g., engagement history) included in baseline.
47
+ - Limited feature set (5 features); adding student history could improve performance.
48
+
49
+ ## Fallback Behavior
50
+
51
+ When the model is not loaded or confidence is below threshold, the system
52
+ falls back to knowledge-graph weakest-prerequisite + content_catalog filtered
53
+ by LO + difficulty, ranked by estimated_mastery_gain.
artifacts/models/recommender/training_config.json ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "recommender",
3
+ "model_version": "recommender_v2_baseline_001",
4
+ "dataset_version": "2.0.0",
5
+ "seed": 20260520,
6
+ "split_counts": {
7
+ "train": 5671,
8
+ "validation": 1214,
9
+ "test": 1215
10
+ },
11
+ "hyperparameters": {
12
+ "n_estimators": 100,
13
+ "max_depth": 4,
14
+ "random_state": 20260520,
15
+ "algorithm": "GradientBoostingClassifier",
16
+ "encoder": "OrdinalEncoder"
17
+ },
18
+ "feature_columns": [
19
+ "priority",
20
+ "ai_confidence",
21
+ "recommendation_type",
22
+ "grade",
23
+ "subject"
24
+ ],
25
+ "categorical_columns": [
26
+ "priority",
27
+ "recommendation_type",
28
+ "subject"
29
+ ],
30
+ "numeric_columns": [
31
+ "ai_confidence",
32
+ "grade"
33
+ ],
34
+ "target_columns": [
35
+ "clicked",
36
+ "is_completed"
37
+ ],
38
+ "algorithm": "GradientBoostingClassifier"
39
+ }
artifacts/models/risk_model/.gitkeep ADDED
File without changes
artifacts/models/risk_model/feature_columns.json ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ "avg_mastery_score",
3
+ "weak_lo_count",
4
+ "developing_lo_count",
5
+ "mastered_lo_count",
6
+ "avg_confidence",
7
+ "avg_accuracy",
8
+ "avg_marks_ratio",
9
+ "avg_time_seconds",
10
+ "hint_usage_rate",
11
+ "total_attempts",
12
+ "attendance_percentage",
13
+ "assignment_completion_rate",
14
+ "average_login_per_week",
15
+ "inactive_days_last_14",
16
+ "avg_active_minutes",
17
+ "total_logins",
18
+ "avg_video_watch_ratio",
19
+ "total_content_completed",
20
+ "total_quiz_attempts"
21
+ ]
artifacts/models/risk_model/metrics.json ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "risk_model",
3
+ "model_version": "risk_model_v2_baseline_001",
4
+ "dataset_version": "2.0.0",
5
+ "trained_at": "2026-05-22T05:33:10.882126+00:00",
6
+ "seed": 20260520,
7
+ "split_counts": {
8
+ "train": 1133,
9
+ "validation": 243,
10
+ "test": 244
11
+ },
12
+ "metrics": {
13
+ "validation": {
14
+ "recall_positive": 0.8571,
15
+ "precision_positive": 0.9231,
16
+ "f1_positive": 0.8889,
17
+ "roc_auc": 0.9915,
18
+ "per_class": {
19
+ "not_at_risk": {
20
+ "precision": 0.9706,
21
+ "recall": 0.9851,
22
+ "f1": 0.9778,
23
+ "support": 201
24
+ },
25
+ "at_risk": {
26
+ "precision": 0.9231,
27
+ "recall": 0.8571,
28
+ "f1": 0.8889,
29
+ "support": 42
30
+ }
31
+ },
32
+ "confusion_matrix": [
33
+ [
34
+ 198,
35
+ 3
36
+ ],
37
+ [
38
+ 6,
39
+ 36
40
+ ]
41
+ ],
42
+ "risk_level_recall": {
43
+ "high": {
44
+ "recall": 0.8421,
45
+ "support": 38
46
+ },
47
+ "critical": {
48
+ "recall": 1.0,
49
+ "support": 4
50
+ }
51
+ }
52
+ },
53
+ "test": {
54
+ "recall_positive": 0.8125,
55
+ "precision_positive": 0.8966,
56
+ "f1_positive": 0.8525,
57
+ "roc_auc": 0.9899,
58
+ "per_class": {
59
+ "not_at_risk": {
60
+ "precision": 0.9721,
61
+ "recall": 0.9858,
62
+ "f1": 0.9789,
63
+ "support": 212
64
+ },
65
+ "at_risk": {
66
+ "precision": 0.8966,
67
+ "recall": 0.8125,
68
+ "f1": 0.8525,
69
+ "support": 32
70
+ }
71
+ },
72
+ "confusion_matrix": [
73
+ [
74
+ 209,
75
+ 3
76
+ ],
77
+ [
78
+ 6,
79
+ 26
80
+ ]
81
+ ],
82
+ "risk_level_recall": {
83
+ "high": {
84
+ "recall": 0.7778,
85
+ "support": 27
86
+ },
87
+ "critical": {
88
+ "recall": 1.0,
89
+ "support": 5
90
+ }
91
+ }
92
+ }
93
+ },
94
+ "limitations": [
95
+ "Trained on synthetic data only.",
96
+ "Binary risk_label derived from synthetic risk_score thresholds.",
97
+ "All features are numeric; no text or contextual features used.",
98
+ "Class imbalance (~16% positive) addressed via class_weight='balanced'.",
99
+ "Critical class (~2%) recall should be monitored separately."
100
+ ]
101
+ }
artifacts/models/risk_model/model.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d10e1aed1d17c9b2973771c900a258d13393df793c0b766667546904a0af505a
3
+ size 151205
artifacts/models/risk_model/model_card.md ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Model Card: Risk Model
2
+
3
+ ## Model Details
4
+
5
+ - **Model Name:** risk_model
6
+ - **Model Version:** risk_model_v2_baseline_001
7
+ - **Algorithm:** RandomForestClassifier (class_weight="balanced")
8
+ - **Framework:** scikit-learn
9
+ - **Trained At:** 2026-05-22T05:33:10.882126+00:00
10
+ - **Seed:** 20260520
11
+
12
+ ## Intended Use
13
+
14
+ Predict whether a student is at-risk (binary: 0=not at-risk, 1=at-risk) based on
15
+ mastery, performance, and engagement features. Used in the risk prediction endpoint
16
+ to identify students who may need intervention. Primary optimization target is
17
+ recall on the positive class to minimize missed at-risk students.
18
+
19
+ ## Training Data
20
+
21
+ - **Source:** training_risk_prediction.csv (synthetic dataset v2)
22
+ - **Split Counts:** train=1133, validation=243, test=244
23
+ - **Features:** avg_mastery_score, weak_lo_count, developing_lo_count, mastered_lo_count, avg_confidence, avg_accuracy, avg_marks_ratio, avg_time_seconds, hint_usage_rate, total_attempts, attendance_percentage, assignment_completion_rate, average_login_per_week, inactive_days_last_14, avg_active_minutes, total_logins, avg_video_watch_ratio, total_content_completed, total_quiz_attempts (all numeric, 19 features)
24
+ - **Target:** risk_label (binary 0/1)
25
+ - **Class Imbalance:** ~16% positive class, addressed via class_weight="balanced"
26
+
27
+ ## Metrics
28
+
29
+ ### Validation Set
30
+ - Recall (positive): 0.8571
31
+ - Precision (positive): 0.9231
32
+ - F1 (positive): 0.8889
33
+ - ROC-AUC: 0.9915
34
+
35
+ ### Test Set
36
+ - Recall (positive): 0.8125
37
+ - Precision (positive): 0.8966
38
+ - F1 (positive): 0.8525
39
+ - ROC-AUC: 0.9899
40
+
41
+ ## Per-Class Performance (Test Set)
42
+
43
+ | Class | Precision | Recall | F1 | Support |
44
+ |-------|-----------|--------|-----|---------|
45
+ | not_at_risk | 0.9721 | 0.9858 | 0.9789 | 212 |
46
+ | at_risk | 0.8966 | 0.8125 | 0.8525 | 32 |
47
+
48
+ ## Risk Level Recall (Test Set)
49
+
50
+ | Risk Level | Recall | Support |
51
+ |------------|--------|---------|
52
+ | high | 0.7778 | 27 |
53
+ | critical | 1.0 | 5 |
54
+
55
+ ## Known Limitations
56
+
57
+ - Trained on synthetic data only — performance on real student data is unknown.
58
+ - Binary risk_label derived from synthetic risk_score thresholds.
59
+ - All features are numeric; no text or contextual features used.
60
+ - Class imbalance (~16% positive) addressed via class_weight="balanced".
61
+ - Critical class (~2%) is very rare; recall on critical should be monitored.
62
+ - No temporal features (trend over time) included in this baseline.
63
+
64
+ ## Fallback Behavior
65
+
66
+ When the model is not loaded or confidence is below the threshold (0.55),
67
+ the system falls back to rule-based risk estimation using:
68
+ - inactive_days_last_14 > 7 → high risk
69
+ - attendance_percentage < 60% → high risk
70
+ - avg_mastery_score < 0.4 → medium risk
71
+ - Otherwise → low risk
artifacts/models/risk_model/training_config.json ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_name": "risk_model",
3
+ "model_version": "risk_model_v2_baseline_001",
4
+ "dataset_version": "2.0.0",
5
+ "seed": 20260520,
6
+ "split_counts": {
7
+ "train": 1133,
8
+ "validation": 243,
9
+ "test": 244
10
+ },
11
+ "hyperparameters": {
12
+ "n_estimators": 100,
13
+ "class_weight": "balanced",
14
+ "random_state": 20260520,
15
+ "algorithm": "RandomForestClassifier"
16
+ },
17
+ "feature_columns": [
18
+ "avg_mastery_score",
19
+ "weak_lo_count",
20
+ "developing_lo_count",
21
+ "mastered_lo_count",
22
+ "avg_confidence",
23
+ "avg_accuracy",
24
+ "avg_marks_ratio",
25
+ "avg_time_seconds",
26
+ "hint_usage_rate",
27
+ "total_attempts",
28
+ "attendance_percentage",
29
+ "assignment_completion_rate",
30
+ "average_login_per_week",
31
+ "inactive_days_last_14",
32
+ "avg_active_minutes",
33
+ "total_logins",
34
+ "avg_video_watch_ratio",
35
+ "total_content_completed",
36
+ "total_quiz_attempts"
37
+ ],
38
+ "target_column": "risk_label",
39
+ "label_map": {
40
+ "0": "not_at_risk",
41
+ "1": "at_risk"
42
+ },
43
+ "algorithm": "RandomForestClassifier"
44
+ }