# --- Imports ---
import streamlit as st
import PyPDF2
import requests
import json
from sentence_transformers import SentenceTransformer
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from datetime import datetime
from groq import Groq
# --- Page config ---
st.set_page_config(
page_title="🚨 First Aid Emergency Assistant",
page_icon="🚨",
layout="wide",
initial_sidebar_state="expanded"
)
# --- Enhanced Professional UI CSS ---
st.markdown("""
""", unsafe_allow_html=True)
# --- GROQ API setup ---
@st.cache_resource
def setup_groq():
try:
return st.secrets["GROQ_API_KEY"]
except:
st.error("❌ Missing GROQ_API_KEY in `.streamlit/secrets.toml`")
st.stop()
client = Groq(api_key=setup_groq())
# --- PDF Processing ---
@st.cache_resource
def load_pdf():
try:
with open("First-Aid.pdf", "rb") as f:
reader = PyPDF2.PdfReader(f)
text = "".join(page.extract_text() + "\n" for page in reader.pages)
return text
except:
st.error("❌ Failed to load 'First-Aid.pdf'. Upload it to the app root.")
st.stop()
# --- Knowledge Base Setup ---
@st.cache_resource
def setup_knowledge_base():
text = load_pdf()
chunks, current_chunk = [], ""
for sentence in text.split('\n'):
if len(current_chunk + sentence) < 1000:
current_chunk += sentence + "\n"
else:
if current_chunk.strip(): chunks.append(current_chunk.strip())
current_chunk = sentence + "\n"
if current_chunk.strip(): chunks.append(current_chunk.strip())
model = SentenceTransformer('all-MiniLM-L6-v2')
embeddings = model.encode(chunks)
return chunks, embeddings, model
# --- Context Matching ---
def find_relevant_context(query, chunks, embeddings, model, top_k=3):
query_embedding = model.encode([query])
similarities = cosine_similarity(query_embedding, embeddings)[0]
top_indices = np.argsort(similarities)[-top_k:][::-1]
return "\n\n".join([chunks[i] for i in top_indices])
# --- Query GROQ ---
def query_groq(prompt, api_key):
url = "https://api.groq.com/openai/v1/chat/completions"
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
data = {
"model": "llama3-70b-8192",
"messages": [
{
"role": "system",
"content": """You are a First Aid Emergency Assistant. Answer only first aid-related queries. Be clear, concise, and step-by-step. For serious emergencies, advise calling 911. If asked off-topic, respond with: "🚨 I'm specialized in First Aid emergencies only!"."""
},
{"role": "user", "content": prompt}
],
"temperature": 0.3,
"max_tokens": 1000
}
try:
r = requests.post(url, headers=headers, json=data, timeout=30)
r.raise_for_status()
return r.json()["choices"][0]["message"]["content"]
except Exception as e:
return f"❌ GROQ API Error: {str(e)}"
# --- Session State ---
if "messages" not in st.session_state:
st.session_state.messages = [{
"role": "assistant",
"content": "🚨 **Hello! I'm your First Aid Emergency Assistant.**\n\nAsk me about CPR, bleeding, choking, burns, or any first aid emergency. I'm here to help you with step-by-step guidance!"
}]
if "knowledge_base" not in st.session_state:
with st.spinner("🔄 Loading knowledge base..."):
chunks, embeddings, model = setup_knowledge_base()
st.session_state.knowledge_base = {
"chunks": chunks, "embeddings": embeddings, "model": model
}
if "feedback_shown" not in st.session_state:
st.session_state.feedback_shown = False
if "response_count" not in st.session_state:
st.session_state.response_count = 0
# --- Main App Layout ---
# Compact Header
st.markdown('''
🚨 First Aid Emergency Assistant
Your AI-powered emergency response guide
''', unsafe_allow_html=True)
# Main content area
col1, col2 = st.columns([3, 1])
with col1:
# Create a container with fixed height for chat messages
chat_container = st.container()
with chat_container:
# Create the scrollable chat area using st.container with height
st.markdown('', unsafe_allow_html=True)
# Display chat messages
for i, msg in enumerate(st.session_state.messages):
if msg["role"] == "user":
st.markdown(f'
{msg["content"]}
', unsafe_allow_html=True)
else:
st.markdown(f'
🤖 First Aid Assistant
{msg["content"]}
', unsafe_allow_html=True)
st.markdown('
', unsafe_allow_html=True)
# Show feedback request after first response
if st.session_state.response_count >= 1 and not st.session_state.feedback_shown:
st.markdown('''
💬 How was this assistance?
Your feedback helps us improve emergency response guidance.
''', unsafe_allow_html=True)
feedback_col1, feedback_col2, feedback_col3 = st.columns(3)
with feedback_col1:
if st.button("👍 Helpful"):
st.success("Thank you for your feedback!")
st.session_state.feedback_shown = True
st.rerun()
with feedback_col2:
if st.button("👎 Not helpful"):
st.info("Thanks for letting us know. We'll work to improve!")
st.session_state.feedback_shown = True
st.rerun()
with feedback_col3:
if st.button("⏭️ Skip"):
st.session_state.feedback_shown = True
st.rerun()
# Enhanced Input Container with better spacing
st.markdown('', unsafe_allow_html=True)
# Form for Enter key support and auto-clear
with st.form(key="chat_form", clear_on_submit=True):
input_col1, input_col2 = st.columns([4, 1])
with input_col1:
user_input = st.text_input(
"",
placeholder="What do to in case of heart pain?",
key="user_input_form",
label_visibility="collapsed"
)
with input_col2:
send = st.form_submit_button("Send 🚀")
# Clear Chat Button
if st.button("🗑️ Clear Chat", key="clear_chat", help="Clear all messages and start fresh"):
st.session_state.messages = [{
"role": "assistant",
"content": "🚨 **Hello! I'm your First Aid Emergency Assistant.**\n\nAsk me about CPR, bleeding, choking, burns, or any first aid emergency. I'm here to help you with step-by-step guidance!"
}]
st.session_state.feedback_shown = False
st.session_state.response_count = 0
st.rerun()
st.markdown('
', unsafe_allow_html=True)
# Sidebar with medical disclaimer and info
with col2:
st.markdown("### 🩺 Medical Disclaimer")
with st.expander("⚠️ Important - Click to read", expanded=False):
st.markdown("""
**MEDICAL DISCLAIMER:**
This tool provides general first aid guidance only.
🚨 **In real emergencies:**
- Call emergency services immediately
- This is NOT a substitute for professional medical care
- Always seek professional help for serious injuries
Use this tool for educational purposes and basic guidance only.
""")
st.markdown("### 🎯 What I Can Help With")
st.markdown('''
''', unsafe_allow_html=True)
# Process Input (works with both Enter key and button click)
if send and user_input and user_input.strip():
# Add user message
st.session_state.messages.append({"role": "user", "content": user_input})
# Get AI response
try:
kb = st.session_state.knowledge_base
context = find_relevant_context(user_input, kb["chunks"], kb["embeddings"], kb["model"])
full_prompt = f"""
Based on this first aid manual content, answer the question: {user_input}
Context:
{context}
Please provide clear, step-by-step guidance. Use bullet points or numbered lists when appropriate.
"""
response = query_groq(full_prompt, setup_groq())
# Add emergency warning for serious cases
if any(x in user_input.lower() for x in ["heart attack", "stroke", "not breathing", "unconscious", "severe bleeding", "choking"]):
response = f"🚨 **CALL EMERGENCY SERVICES IMMEDIATELY!**\n\n{response}"
# Add bot response
st.session_state.messages.append({"role": "assistant", "content": response})
st.session_state.response_count += 1
except Exception as e:
st.session_state.messages.append({
"role": "assistant",
"content": f"❌ Sorry, I encountered an error: {str(e)}. Please try again or rephrase your question."
})
# Rerun to show updated chat
st.rerun()
# Footer
st.markdown("---")
st.markdown('''
🤖 First Aid Emergency Assistant | Always consult medical professionals for serious emergencies
''', unsafe_allow_html=True)