Spaces:
Sleeping
Sleeping
Commit ·
5f63ae0
1
Parent(s): 3025689
feat: update hostel and backlog handling in forms and backend logic
Browse files
index.html
CHANGED
|
@@ -187,7 +187,7 @@
|
|
| 187 |
</span>
|
| 188 |
<span class="checkbox-text">
|
| 189 |
<span class="checkbox-title">Hostel Accommodation</span>
|
| 190 |
-
<span class="checkbox-desc">
|
| 191 |
</span>
|
| 192 |
</label>
|
| 193 |
</div>
|
|
@@ -205,7 +205,7 @@
|
|
| 205 |
</span>
|
| 206 |
<span class="checkbox-text">
|
| 207 |
<span class="checkbox-title">Academic Backlogs</span>
|
| 208 |
-
<span class="checkbox-desc">
|
| 209 |
</span>
|
| 210 |
</label>
|
| 211 |
</div>
|
|
|
|
| 187 |
</span>
|
| 188 |
<span class="checkbox-text">
|
| 189 |
<span class="checkbox-title">Hostel Accommodation</span>
|
| 190 |
+
<span class="checkbox-desc">Checked = Yes (1), Unchecked = No (0)</span>
|
| 191 |
</span>
|
| 192 |
</label>
|
| 193 |
</div>
|
|
|
|
| 205 |
</span>
|
| 206 |
<span class="checkbox-text">
|
| 207 |
<span class="checkbox-title">Academic Backlogs</span>
|
| 208 |
+
<span class="checkbox-desc">Checked = Yes (1), Unchecked = No (0)</span>
|
| 209 |
</span>
|
| 210 |
</label>
|
| 211 |
</div>
|
llm.py
CHANGED
|
@@ -38,6 +38,20 @@ _chat_db = SqliteDb(db_file="tmp/placement_chat.db")
|
|
| 38 |
_sessions: dict = {}
|
| 39 |
|
| 40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
def build_system_context(
|
| 42 |
student_data: dict,
|
| 43 |
prediction: dict,
|
|
@@ -59,8 +73,8 @@ def build_system_context(
|
|
| 59 |
f"Stream: {student_data.get('Stream', 'N/A')}",
|
| 60 |
f"Internships: {student_data.get('Internships', 'N/A')}",
|
| 61 |
f"CGPA: {student_data.get('CGPA', 'N/A')}",
|
| 62 |
-
f"Hostel: {
|
| 63 |
-
f"History of Backlogs: {
|
| 64 |
f"Skills: {', '.join(student_data.get('skills', []))}",
|
| 65 |
f"Desired Role: {student_data.get('desired_role', 'Not Specified')}"
|
| 66 |
]
|
|
|
|
| 38 |
_sessions: dict = {}
|
| 39 |
|
| 40 |
|
| 41 |
+
def _binary_to_yes_no(value) -> str:
|
| 42 |
+
"""Map binary-encoded values to dataset semantics: 0 = No, 1 = Yes."""
|
| 43 |
+
if isinstance(value, str):
|
| 44 |
+
normalized = value.strip().lower()
|
| 45 |
+
if normalized in {"1", "true", "yes"}:
|
| 46 |
+
return "Yes"
|
| 47 |
+
if normalized in {"0", "false", "no", ""}:
|
| 48 |
+
return "No"
|
| 49 |
+
try:
|
| 50 |
+
return "Yes" if int(value) == 1 else "No"
|
| 51 |
+
except Exception:
|
| 52 |
+
return "No"
|
| 53 |
+
|
| 54 |
+
|
| 55 |
def build_system_context(
|
| 56 |
student_data: dict,
|
| 57 |
prediction: dict,
|
|
|
|
| 73 |
f"Stream: {student_data.get('Stream', 'N/A')}",
|
| 74 |
f"Internships: {student_data.get('Internships', 'N/A')}",
|
| 75 |
f"CGPA: {student_data.get('CGPA', 'N/A')}",
|
| 76 |
+
f"Hostel: {_binary_to_yes_no(student_data.get('Hostel'))}",
|
| 77 |
+
f"History of Backlogs: {_binary_to_yes_no(student_data.get('HistoryOfBacklogs'))}",
|
| 78 |
f"Skills: {', '.join(student_data.get('skills', []))}",
|
| 79 |
f"Desired Role: {student_data.get('desired_role', 'Not Specified')}"
|
| 80 |
]
|
main.py
CHANGED
|
@@ -157,8 +157,8 @@ class StudentData(BaseModel):
|
|
| 157 |
Stream: str = Field(..., description="Stream of study")
|
| 158 |
Internships: int = Field(..., ge=0)
|
| 159 |
CGPA: float = Field(..., ge=0, le=10)
|
| 160 |
-
Hostel: int = Field(..., description="
|
| 161 |
-
HistoryOfBacklogs: int = Field(..., description="
|
| 162 |
skills: List[str] = Field(default=[], description="List of user skills for routing")
|
| 163 |
desired_role: Optional[str] = Field(default=None, description="User's desired job role")
|
| 164 |
|
|
@@ -191,6 +191,16 @@ class OptionsResponse(BaseModel):
|
|
| 191 |
skills: List[str]
|
| 192 |
jobs: List[str]
|
| 193 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
def prepare_input(data: StudentData) -> pd.DataFrame:
|
| 195 |
try:
|
| 196 |
g = le_gender.transform([data.Gender])[0]
|
|
@@ -205,8 +215,8 @@ def prepare_input(data: StudentData) -> pd.DataFrame:
|
|
| 205 |
'Stream': s,
|
| 206 |
'Internships': data.Internships,
|
| 207 |
'CGPA': data.CGPA,
|
| 208 |
-
'Hostel': data.Hostel,
|
| 209 |
-
'HistoryOfBacklogs': data.HistoryOfBacklogs
|
| 210 |
}])
|
| 211 |
# Extract columns naturally based on dict order which matches train features order
|
| 212 |
return df
|
|
@@ -359,6 +369,10 @@ async def whatif_analysis(data: StudentData):
|
|
| 359 |
return float(model.predict_proba(df_processed)[0][1]) * 100
|
| 360 |
|
| 361 |
orig_dict = data.model_dump()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 362 |
orig_risk = _predict(orig_dict)
|
| 363 |
orig_level, _ = get_placement_level(orig_risk / 100)
|
| 364 |
|
|
@@ -421,7 +435,7 @@ async def whatif_analysis(data: StudentData):
|
|
| 421 |
)
|
| 422 |
|
| 423 |
# Clear Backlogs
|
| 424 |
-
if
|
| 425 |
mod = orig_dict.copy()
|
| 426 |
mod['HistoryOfBacklogs'] = 0
|
| 427 |
add_scenario(
|
|
@@ -443,7 +457,7 @@ async def whatif_analysis(data: StudentData):
|
|
| 443 |
)
|
| 444 |
|
| 445 |
# Stay in Hostel
|
| 446 |
-
if
|
| 447 |
mod = orig_dict.copy()
|
| 448 |
mod['Hostel'] = 1
|
| 449 |
mod_risk = _predict(mod)
|
|
@@ -460,7 +474,7 @@ async def whatif_analysis(data: StudentData):
|
|
| 460 |
best_case = orig_dict.copy()
|
| 461 |
if data.CGPA < 9.0: best_case['CGPA'] = min(data.CGPA + 1.0, 10.0)
|
| 462 |
if data.Internships < 3: best_case['Internships'] += 1
|
| 463 |
-
if
|
| 464 |
|
| 465 |
combined_risk = _predict(best_case)
|
| 466 |
combined_level, _ = get_placement_level(combined_risk / 100)
|
|
|
|
| 157 |
Stream: str = Field(..., description="Stream of study")
|
| 158 |
Internships: int = Field(..., ge=0)
|
| 159 |
CGPA: float = Field(..., ge=0, le=10)
|
| 160 |
+
Hostel: int = Field(..., ge=0, le=1, description="0 = day scholar (not in hostel), 1 = lives in hostel")
|
| 161 |
+
HistoryOfBacklogs: int = Field(..., ge=0, le=1, description="0 = no history of backlogs, 1 = history of backlogs")
|
| 162 |
skills: List[str] = Field(default=[], description="List of user skills for routing")
|
| 163 |
desired_role: Optional[str] = Field(default=None, description="User's desired job role")
|
| 164 |
|
|
|
|
| 191 |
skills: List[str]
|
| 192 |
jobs: List[str]
|
| 193 |
|
| 194 |
+
|
| 195 |
+
def normalize_backlogs_value(value: int) -> int:
|
| 196 |
+
"""Normalize backlog input to strict dataset encoding: 0 = No, 1 = Yes."""
|
| 197 |
+
return 1 if int(value) == 1 else 0
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
def normalize_hostel_value(value: int) -> int:
|
| 201 |
+
"""Normalize hostel input to strict dataset encoding: 0 = No, 1 = Yes."""
|
| 202 |
+
return 1 if int(value) == 1 else 0
|
| 203 |
+
|
| 204 |
def prepare_input(data: StudentData) -> pd.DataFrame:
|
| 205 |
try:
|
| 206 |
g = le_gender.transform([data.Gender])[0]
|
|
|
|
| 215 |
'Stream': s,
|
| 216 |
'Internships': data.Internships,
|
| 217 |
'CGPA': data.CGPA,
|
| 218 |
+
'Hostel': normalize_hostel_value(data.Hostel),
|
| 219 |
+
'HistoryOfBacklogs': normalize_backlogs_value(data.HistoryOfBacklogs)
|
| 220 |
}])
|
| 221 |
# Extract columns naturally based on dict order which matches train features order
|
| 222 |
return df
|
|
|
|
| 369 |
return float(model.predict_proba(df_processed)[0][1]) * 100
|
| 370 |
|
| 371 |
orig_dict = data.model_dump()
|
| 372 |
+
orig_dict['Hostel'] = normalize_hostel_value(orig_dict.get('Hostel', 0))
|
| 373 |
+
orig_dict['HistoryOfBacklogs'] = normalize_backlogs_value(orig_dict.get('HistoryOfBacklogs', 0))
|
| 374 |
+
current_hostel = orig_dict['Hostel']
|
| 375 |
+
current_backlogs = orig_dict['HistoryOfBacklogs']
|
| 376 |
orig_risk = _predict(orig_dict)
|
| 377 |
orig_level, _ = get_placement_level(orig_risk / 100)
|
| 378 |
|
|
|
|
| 435 |
)
|
| 436 |
|
| 437 |
# Clear Backlogs
|
| 438 |
+
if current_backlogs == 1:
|
| 439 |
mod = orig_dict.copy()
|
| 440 |
mod['HistoryOfBacklogs'] = 0
|
| 441 |
add_scenario(
|
|
|
|
| 457 |
)
|
| 458 |
|
| 459 |
# Stay in Hostel
|
| 460 |
+
if current_hostel == 0:
|
| 461 |
mod = orig_dict.copy()
|
| 462 |
mod['Hostel'] = 1
|
| 463 |
mod_risk = _predict(mod)
|
|
|
|
| 474 |
best_case = orig_dict.copy()
|
| 475 |
if data.CGPA < 9.0: best_case['CGPA'] = min(data.CGPA + 1.0, 10.0)
|
| 476 |
if data.Internships < 3: best_case['Internships'] += 1
|
| 477 |
+
if current_backlogs == 1: best_case['HistoryOfBacklogs'] = 0
|
| 478 |
|
| 479 |
combined_risk = _predict(best_case)
|
| 480 |
combined_level, _ = get_placement_level(combined_risk / 100)
|
script.js
CHANGED
|
@@ -44,6 +44,18 @@ let currentFormData = null;
|
|
| 44 |
let availableSkills = [];
|
| 45 |
let selectedSkills = [];
|
| 46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
/**
|
| 48 |
* Initialize the application
|
| 49 |
*/
|
|
@@ -270,8 +282,8 @@ function collectFormData() {
|
|
| 270 |
Stream: document.getElementById('stream').value,
|
| 271 |
Internships: parseInt(document.getElementById('internships').value) || 0,
|
| 272 |
CGPA: parseFloat(document.getElementById('cgpa').value) || 0,
|
| 273 |
-
Hostel:
|
| 274 |
-
HistoryOfBacklogs:
|
| 275 |
skills: document.getElementById('skills').value.split(',').map(s => s.trim()).filter(s => s),
|
| 276 |
desired_role: document.getElementById('desired_role').value || null
|
| 277 |
};
|
|
@@ -950,7 +962,7 @@ function initSimulator() {
|
|
| 950 |
|
| 951 |
// Toggle Setup
|
| 952 |
const toggle = document.getElementById('simBacklogToggle');
|
| 953 |
-
toggle.checked = (currentFormData.HistoryOfBacklogs
|
| 954 |
toggle.onchange = () => { triggerSimulate(); };
|
| 955 |
}
|
| 956 |
|
|
@@ -990,8 +1002,7 @@ async function simulateRisk() {
|
|
| 990 |
simulatedData.Internships = parseInt(document.getElementById('simInternNum').value);
|
| 991 |
simulatedData.CGPA = parseFloat(document.getElementById('simCGPANum').value);
|
| 992 |
|
| 993 |
-
|
| 994 |
-
simulatedData.HistoryOfBacklogs = hasBacklog ? 1 : 0;
|
| 995 |
|
| 996 |
try {
|
| 997 |
const response = await fetchPrediction(simulatedData);
|
|
|
|
| 44 |
let availableSkills = [];
|
| 45 |
let selectedSkills = [];
|
| 46 |
|
| 47 |
+
function encodeBacklogsFromCheckbox(checkboxId = 'backlogs') {
|
| 48 |
+
return document.getElementById(checkboxId).checked ? 1 : 0;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
function decodeBacklogsToChecked(value) {
|
| 52 |
+
return Number(value) === 1;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
function encodeHostelFromCheckbox(checkboxId = 'hostel') {
|
| 56 |
+
return document.getElementById(checkboxId).checked ? 1 : 0;
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
/**
|
| 60 |
* Initialize the application
|
| 61 |
*/
|
|
|
|
| 282 |
Stream: document.getElementById('stream').value,
|
| 283 |
Internships: parseInt(document.getElementById('internships').value) || 0,
|
| 284 |
CGPA: parseFloat(document.getElementById('cgpa').value) || 0,
|
| 285 |
+
Hostel: encodeHostelFromCheckbox('hostel'),
|
| 286 |
+
HistoryOfBacklogs: encodeBacklogsFromCheckbox('backlogs'),
|
| 287 |
skills: document.getElementById('skills').value.split(',').map(s => s.trim()).filter(s => s),
|
| 288 |
desired_role: document.getElementById('desired_role').value || null
|
| 289 |
};
|
|
|
|
| 962 |
|
| 963 |
// Toggle Setup
|
| 964 |
const toggle = document.getElementById('simBacklogToggle');
|
| 965 |
+
toggle.checked = decodeBacklogsToChecked(currentFormData.HistoryOfBacklogs);
|
| 966 |
toggle.onchange = () => { triggerSimulate(); };
|
| 967 |
}
|
| 968 |
|
|
|
|
| 1002 |
simulatedData.Internships = parseInt(document.getElementById('simInternNum').value);
|
| 1003 |
simulatedData.CGPA = parseFloat(document.getElementById('simCGPANum').value);
|
| 1004 |
|
| 1005 |
+
simulatedData.HistoryOfBacklogs = encodeBacklogsFromCheckbox('simBacklogToggle');
|
|
|
|
| 1006 |
|
| 1007 |
try {
|
| 1008 |
const response = await fetchPrediction(simulatedData);
|