Saathi / modules /student_corner.py
Pushpraj
fixed distortion
2bbcf98
"""Module 3 — Student Corner: CBT-informed stakes coach for Indian students.
Flow:
1. Student picks an event type from quick buttons: exam / placement / viva / presentation / result / burnout
2. Student describes their situation in 1-3 sentences.
3. Crisis regex runs first.
4. Claude returns a structured response: acknowledge → distortion scan → 3 evidence-based prep tips →
what NOT to do → 60-second grounding script → "if things get heavier" signpost.
"""
from __future__ import annotations
import streamlit as st
from backend.claude_client import chat
from backend.i18n import claude_language_name, t
from backend.safeguards import check_crisis, render_crisis_banner
from backend.voice_widget import render_mic_button
MODULE_NAME = "student_corner"
EVENT_KEY = "student_event_type"
SITUATION_KEY = "student_situation"
RESPONSE_KEY = "student_response"
EVENT_CHOICES = [
("exam", "event_exam"),
("placement_interview", "event_placement"),
("viva", "event_viva"),
("presentation", "event_presentation"),
("result_day", "event_result"),
("general_burnout", "event_burnout"),
]
def _init_state() -> None:
if EVENT_KEY not in st.session_state:
st.session_state[EVENT_KEY] = "exam"
if SITUATION_KEY not in st.session_state:
st.session_state[SITUATION_KEY] = ""
if RESPONSE_KEY not in st.session_state:
st.session_state[RESPONSE_KEY] = ""
def render(lang: str) -> None:
_init_state()
st.header(t("student_header", lang))
st.caption(t("student_sub", lang))
# Event picker
st.markdown(f"**{t('student_event_label', lang)}**")
labels = [t(label_key, lang) for _, label_key in EVENT_CHOICES]
event_values = [value for value, _ in EVENT_CHOICES]
current_index = (
event_values.index(st.session_state[EVENT_KEY])
if st.session_state[EVENT_KEY] in event_values
else 0
)
chosen_label = st.radio(
"event",
options=labels,
index=current_index,
horizontal=True,
label_visibility="collapsed",
key="student_event_radio",
)
st.session_state[EVENT_KEY] = event_values[labels.index(chosen_label)]
# Situation input
render_mic_button(lang, target_aria_label="situation")
situation = st.text_area(
"situation",
value=st.session_state[SITUATION_KEY],
placeholder=t("student_input_placeholder", lang),
label_visibility="collapsed",
height=120,
key="student_situation_input",
)
if st.button(t("student_send_button", lang), type="primary", key="student_send_button"):
if situation.strip():
st.session_state[SITUATION_KEY] = situation
if check_crisis(situation):
render_crisis_banner(lang)
return
user_text = (
f"event_type: {st.session_state[EVENT_KEY]}\n"
f"situation: {situation}"
)
with st.spinner("…"):
try:
reply = chat(
module=MODULE_NAME,
user_text=user_text,
language_name=claude_language_name(lang),
max_tokens=2400,
)
except Exception as e:
reply = (
"I couldn't reach my language model right now. "
"For immediate support call **Tele-MANAS on 14416** (Government of India, free, 24×7, 20+ Indian languages) "
"or **iCall** on 9152987821 (Mon–Sat 8 AM–10 PM).\n\n"
f"_(Technical detail: {e})_"
)
st.session_state[RESPONSE_KEY] = reply
if st.session_state[RESPONSE_KEY]:
st.divider()
st.markdown(st.session_state[RESPONSE_KEY])