""" app.py ───────────────────────────────────────────── Streamlit web interface for the Rural Healthcare RAG Assistant. Design: "Bio-signal interface" — dark medical HUD aesthetic. Run with: streamlit run src/app.py ───────────────────────────────────────────── """ import streamlit as st import os from rag import load_vectorstore, get_llm, answer_question, check_symptoms VECTORSTORE_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "vectorstore") def ensure_vectorstore_downloaded(): """Download pre-built vectorstore from HF dataset repo if not present locally.""" if os.path.exists(VECTORSTORE_DIR) and os.listdir(VECTORSTORE_DIR): return # already exists, nothing to do from huggingface_hub import snapshot_download snapshot_download( repo_id="MridulSharma02/sehat-sathi-vectorstore", repo_type="dataset", local_dir=VECTORSTORE_DIR, ) # ───────────────────────────────────────────── # PAGE CONFIG # ───────────────────────────────────────────── st.set_page_config( page_title="Sehat Sathi · Rural Health Assistant", page_icon="🩺", layout="centered", initial_sidebar_state="expanded", ) symptom_mode = st.sidebar.toggle("🩹 Symptom Checker Mode", value=False) # ───────────────────────────────────────────── # DESIGN SYSTEM — "Bio-signal interface" # ───────────────────────────────────────────── st.markdown(""" """, unsafe_allow_html=True) # ───────────────────────────────────────────── # HERO SECTION # ───────────────────────────────────────────── st.markdown("""
सेहत साथी  ·  SYSTEM ONLINE
Trusted answers,
in plain language.
Ask any health question. Every answer is grounded in official government guidelines and verified medical sources — not guesswork.
KNOWLEDGE BASE ACTIVE
""", unsafe_allow_html=True) # ───────────────────────────────────────────── # STAT STRIP # ───────────────────────────────────────────── st.markdown("""
🏛️ Gov.
Verified Sources
🔍 RAG
Retrieval Powered
✅ Free
Always Accessible
""", unsafe_allow_html=True) # ───────────────────────────────────────────── # LOAD MODELS (cached so it only loads once) # ───────────────────────────────────────────── @st.cache_resource(show_spinner=False) def load_resources(): vectordb = load_vectorstore() llm = get_llm() return vectordb, llm with st.spinner("🔧 Loading knowledge base..."): ensure_vectorstore_downloaded() try: with st.spinner("🔧 Loading knowledge base..."): vectordb, llm = load_resources() except ValueError as e: st.error(f"⚠️ {e}") st.info("Please add your Groq API key to the `.env` file (or Space secrets).") st.stop() # ───────────────────────────────────────────── # CHAT HISTORY # ───────────────────────────────────────────── if "question_count" not in st.session_state: st.session_state.question_count = 0 MAX_QUESTIONS_PER_SESSION = 15 if "messages" not in st.session_state: st.session_state.messages = [ { "role": "assistant", "content": "नमस्ते 👋 I'm here to help with your health questions. What's on your mind today?", "sources": [], "is_verified": None } ] # ───────────────────────────────────────────── # SUGGESTED QUESTION CHIPS (only show before first real question) # ───────────────────────────────────────────── SUGGESTIONS = [ "What are the symptoms of dengue?", "How is diabetes managed?", "What vaccines do newborns need?", "Signs of dehydration in children", ] clicked_suggestion = None if len(st.session_state.messages) == 1: st.markdown('
⌁ Try asking
', unsafe_allow_html=True) chip_cols = st.columns(2) for i, q in enumerate(SUGGESTIONS): with chip_cols[i % 2]: if st.button(q, key=f"chip_{i}", use_container_width=True): clicked_suggestion = q # Display chat history for msg in st.session_state.messages: with st.chat_message(msg["role"], avatar="🩺" if msg["role"] == "assistant" else "🙋"): if msg.get("is_verified") is True: st.markdown('✓ Verified source', unsafe_allow_html=True) elif msg.get("is_verified") is False: st.markdown('⌁ General knowledge', unsafe_allow_html=True) st.markdown(msg["content"]) if msg.get("sources"): tags_html = "".join([f'⌁ {s}' for s in msg["sources"]]) st.markdown(tags_html, unsafe_allow_html=True) # ───────────────────────────────────────────── # CHAT INPUT # ───────────────────────────────────────────── user_query = st.chat_input("Type your health question here...") if clicked_suggestion: user_query = clicked_suggestion if user_query: if st.session_state.question_count >= MAX_QUESTIONS_PER_SESSION: st.warning("⚠️ You've reached the session limit of 15 questions. Please refresh the page to start a new session.") st.stop() st.session_state.question_count += 1 st.session_state.messages.append({"role": "user", "content": user_query, "sources": [], "is_verified": None}) with st.chat_message("user", avatar="🙋"): st.markdown(user_query) with st.chat_message("assistant", avatar="🩺"): with st.spinner("Analyzing..." if symptom_mode else "Scanning verified sources..."): try: if symptom_mode: answer = check_symptoms(user_query, llm) sources, is_verified = [], None else: answer, sources, is_verified = answer_question(user_query, vectordb, llm, chat_history=st.session_state.messages) except Exception as e: answer = f"⚠️ Something went wrong: {e}" sources = [] is_verified = None if is_verified is True: st.markdown('✓ Verified source', unsafe_allow_html=True) elif is_verified is False: st.markdown('⌁ General knowledge', unsafe_allow_html=True) st.markdown(answer) if sources: tags_html = "".join([f'⌁ {s}' for s in sources]) st.markdown(tags_html, unsafe_allow_html=True) st.session_state.messages.append({ "role": "assistant", "content": answer, "sources": sources, "is_verified": is_verified }) st.rerun() # ───────────────────────────────────────────── # DISCLAIMER # ───────────────────────────────────────────── st.markdown("""
⚠️ Important: This assistant provides general health information based on official guidelines. It is not a substitute for professional medical advice. For emergencies or serious symptoms, please visit your nearest health center or call emergency services immediately.
""", unsafe_allow_html=True) # ───────────────────────────────────────────── # SIDEBAR # ───────────────────────────────────────────── with st.sidebar: st.markdown(""" ### 🩺 Sehat Sathi *Your health companion, grounded in truth.* --- **How this works** This assistant uses **RAG (Retrieval Augmented Generation)** — it searches verified documents first, then crafts an answer only from what it finds there. **Knowledge sources:** - 🏛️ National Health Mission guidelines - 🌍 WHO India fact sheets - 📋 Ayushman Bharat documentation - 📊 Verified medical Q&A datasets --- """) if st.button("🗑️ Clear conversation", use_container_width=True): st.session_state.messages = [ { "role": "assistant", "content": "नमस्ते 👋 I'm here to help with your health questions. What's on your mind today?", "sources": [] } ] st.rerun()