MindGuard-AI / app /api.py
MohitRajput45's picture
project completed
8aa3867
# ============================================================
# 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