# Portions of this file were developed with assistance from OpenAI ChatGPT/Codex and reviewed/modified by the author. """Streamlit investor-demo app for campus support triage. Portions of this file were developed with assistance from OpenAI ChatGPT/Codex and reviewed/modified by the author. """ from __future__ import annotations import html import sys from pathlib import Path SRC_DIR = Path(__file__).resolve().parents[1] ROOT_DIR = SRC_DIR.parent for import_path in (SRC_DIR, ROOT_DIR): if str(import_path) not in sys.path: sys.path.insert(0, str(import_path)) import streamlit as st from campus_triage.config import CATEGORY_LABELS, URGENCY_LABELS from campus_triage.predict import EXAMPLE_MESSAGES, load_deployed_model, model_available, model_search_diagnostics, predict_message CUSTOM_CSS = """ """ def display_label(label: str) -> str: """Convert model labels into polished display text.""" return label.replace("_", " ").title() def confidence_band(score: float) -> str: """Convert confidence into a product-facing review band.""" if score >= 0.75: return "Auto-route candidate" if score >= 0.55: return "Route with review" return "Manual review recommended" def urgency_class(urgency: str) -> str: """Return the CSS class for an urgency pill.""" return { "high": "urgency-high", "medium": "urgency-medium", "low": "urgency-low", }.get(urgency, "urgency-medium") def render_status_strip() -> None: """Render investor-demo operating metrics.""" st.markdown( """
Model Mode
Inference Only
Routing Targets
7 Queues
Urgency Tiers
Low / Medium / High
Default Model
TF-IDF Logistic Regression
""", unsafe_allow_html=True, ) def render_score_table(scores: dict[str, float], labels: list[str]) -> None: """Render confidence scores as a compact leaderboard.""" ordered_labels = sorted(labels, key=lambda label: scores.get(label, 0.0), reverse=True) for label in ordered_labels: score = max(0.0, min(scores.get(label, 0.0), 1.0)) st.markdown( f"""
{html.escape(display_label(label))}
{score:.0%}
""", unsafe_allow_html=True, ) def render_example_buttons() -> None: """Render example messages as quick-fill controls.""" st.caption("Demo-ready examples") for index, example in enumerate(EXAMPLE_MESSAGES, start=1): label = f"Example {index}: {example[:54]}{'...' if len(example) > 54 else ''}" if st.button(label, key=f"example_{index}", use_container_width=True): st.session_state["message_text"] = example def render_empty_decision_panel() -> None: """Render the pre-analysis decision panel.""" st.markdown('

Triage Decision

Run an analysis to generate routing output, confidence, and next action.

', unsafe_allow_html=True) st.markdown( """
Current Status
Ready
Model loadedSynthetic POC
""", unsafe_allow_html=True, ) st.markdown("
", unsafe_allow_html=True) def render_prediction(prediction: dict[str, object]) -> None: """Render prediction cards, recommendation, and confidence evidence.""" category = str(prediction["category"]) urgency = str(prediction["urgency"]) category_confidence = float(prediction["category_confidence"]) urgency_confidence = float(prediction["urgency_confidence"]) band = confidence_band(category_confidence) st.markdown('

Triage Decision

Operational output for the support intake queue.

', unsafe_allow_html=True) result_columns = st.columns(3) with result_columns[0]: st.markdown( f"""
Predicted Queue
{html.escape(display_label(category))}
{category_confidence:.0%} confidence
""", unsafe_allow_html=True, ) with result_columns[1]: st.markdown( f"""
Urgency Tier
{html.escape(display_label(urgency))}
{urgency_confidence:.0%} confidence
""", unsafe_allow_html=True, ) with result_columns[2]: st.markdown( f"""
Review Posture
{html.escape(band)}
Human-in-loop
""", unsafe_allow_html=True, ) st.markdown( f"""
Recommended next action: {html.escape(str(prediction["routing_recommendation"]))}
Why this route: {html.escape(str(prediction["explanation"]))}
""", unsafe_allow_html=True, ) st.markdown("
", unsafe_allow_html=True) score_columns = st.columns(2) with score_columns[0]: st.markdown('

Category Confidence

Ranked routing probabilities.

', unsafe_allow_html=True) render_score_table(prediction["category_scores"], CATEGORY_LABELS) # type: ignore[arg-type] st.markdown("
", unsafe_allow_html=True) with score_columns[1]: st.markdown('

Urgency Confidence

Ranked urgency probabilities.

', unsafe_allow_html=True) render_score_table(prediction["urgency_scores"], URGENCY_LABELS) # type: ignore[arg-type] st.markdown("
", unsafe_allow_html=True) def run_app() -> None: """Run the Streamlit application.""" st.set_page_config(page_title="Campus Triage Assistant", page_icon="CS", layout="wide") st.markdown(CUSTOM_CSS, unsafe_allow_html=True) st.markdown( """

Campus Support Message Triage Assistant

AI-assisted intake for university support teams: classify incoming student messages, estimate urgency, and produce routing guidance with confidence evidence.

""", unsafe_allow_html=True, ) render_status_strip() if not model_available(): st.error("No trained model artifact was found for inference.") st.caption("The app checked these local and Hugging Face deployment paths:") st.code(model_search_diagnostics()) st.stop() model = load_deployed_model() if "message_text" not in st.session_state: st.session_state["message_text"] = EXAMPLE_MESSAGES[0] intake_column, decision_column = st.columns([1.05, 1.15], gap="large") with intake_column: st.markdown('

Message Intake

Paste a support request or load a demo scenario.

', unsafe_allow_html=True) render_example_buttons() message_text = st.text_area( "Student message", key="message_text", height=210, label_visibility="collapsed", ) submitted = st.button("Analyze and Route Message", type="primary", use_container_width=True) st.markdown( """ """, unsafe_allow_html=True, ) st.markdown("
", unsafe_allow_html=True) with decision_column: if submitted and message_text.strip(): prediction = predict_message(message_text, model=model) render_prediction(prediction) elif submitted: st.warning("Paste a student message before analyzing.") render_empty_decision_panel() else: render_empty_decision_panel() st.markdown( """ """, unsafe_allow_html=True, ) if __name__ == "__main__": run_app()