Spaces:
Sleeping
Sleeping
File size: 4,697 Bytes
8aa3867 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | # ============================================================
# FILE: app/api.py
# PURPOSE: Acts as the central "loader" for all heavy AI objects.
# Streamlit reruns the entire script on every user action,
# so we use @st.cache_resource to load models ONCE and
# reuse the same object for the entire app session.
# ============================================================
import os # Standard library: used to build file paths safely
import sys # Standard library: used to modify Python's module search path
import streamlit as st # Streamlit: the web framework powering the entire UI
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# PATH SETUP BLOCK
# Problem: This file lives inside app/ but our source code lives
# in src/ (one level up). Python won't find src/ unless
# we manually tell it where to look.
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Get the absolute path of THIS file (e.g., /home/user/project/app/api.py)
current_dir = os.path.dirname(os.path.abspath(__file__))
# Go one level UP from app/ to reach the project root (e.g., /home/user/project/)
project_root = os.path.abspath(os.path.join(current_dir, "../"))
# Only add the project root to sys.path if it isn't already there.
# sys.path is the list of directories Python searches when you do "import X".
if project_root not in sys.path:
sys.path.append(project_root)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# IMPORTS β now safe because project_root is on sys.path
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Import our main chatbot class from src/chatbot/groq_bot.py
from src.chatbot.groq_bot import MindGuardChatbot
# Import our SHAP explainability class from src/explainability/shap_explainer.py
from src.explainability.shap_explainer import MindGuardSHAPExplainer
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# CACHED LOADER: MindGuard Chatbot
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
@st.cache_resource # <-- This decorator is the KEY. It tells Streamlit:
# "Run this function only ONCE. After that, return the
# same object every time instead of rebuilding it."
# Without this, the bot would reload on every keypress.
def get_mindguard_bot():
"""
Instantiates the MindGuardChatbot and keeps it alive in memory.
This loads:
- The Groq LLM connection
- The Whisper audio transcription model
- The SQLite database connection
All of these are expensive to create, so we create them once.
"""
return MindGuardChatbot() # Create and return a new bot instance
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# CACHED LOADER: SHAP Explainer
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
@st.cache_resource # Same caching strategy as above β critical here because
# MindGuardSHAPExplainer loads a full XLM-RoBERTa model
# (~1.1GB weights) which takes ~10-15 seconds to load.
# Caching means that cost is paid only once at startup.
def get_shap_explainer():
"""
Instantiates the MindGuardSHAPExplainer and keeps it alive in memory.
This loads:
- XLMRobertaTokenizer (converts text to token IDs)
- XLMRobertaForSequenceClassification (the 35-emotion neural network)
- shap.Explainer (the Game Theory math engine wrapped around the model)
All three are heavy objects β caching is non-negotiable for a smooth UX.
"""
return MindGuardSHAPExplainer() # Create and return a new explainer instance |