Spaces:
Sleeping
Sleeping
| 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 | |
| import os | |
| from datetime import datetime | |
| # Page configuration | |
| st.set_page_config( | |
| page_title="π¨ First Aid Emergency Assistant", | |
| page_icon="π¨", | |
| layout="wide", | |
| initial_sidebar_state="collapsed" | |
| ) | |
| # Custom CSS for ChatGPT-like interface | |
| st.markdown(""" | |
| <style> | |
| .stApp { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| } | |
| .main-header { | |
| text-align: center; | |
| padding: 1rem 0; | |
| background: rgba(255, 255, 255, 0.1); | |
| border-radius: 15px; | |
| margin-bottom: 2rem; | |
| backdrop-filter: blur(10px); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| } | |
| .chat-container { | |
| background: white; | |
| border-radius: 15px; | |
| padding: 1rem; | |
| margin: 1rem 0; | |
| box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| max-height: 500px; | |
| overflow-y: auto; | |
| } | |
| .user-message { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| padding: 12px 16px; | |
| border-radius: 18px 18px 5px 18px; | |
| margin: 8px 0 8px 20%; | |
| max-width: 80%; | |
| float: right; | |
| clear: both; | |
| box-shadow: 0 2px 10px rgba(102, 126, 234, 0.3); | |
| } | |
| .bot-message { | |
| background: #f8f9fa; | |
| color: #333; | |
| padding: 12px 16px; | |
| border-radius: 18px 18px 18px 5px; | |
| margin: 8px 20% 8px 0; | |
| max-width: 80%; | |
| float: left; | |
| clear: both; | |
| border: 1px solid #e9ecef; | |
| box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); | |
| } | |
| .input-container { | |
| position: sticky; | |
| bottom: 0; | |
| background: white; | |
| padding: 1rem; | |
| border-radius: 15px; | |
| margin-top: 2rem; | |
| box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.1); | |
| } | |
| .warning-box { | |
| background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%); | |
| padding: 1rem; | |
| border-radius: 10px; | |
| margin: 1rem 0; | |
| border-left: 4px solid #ff6b6b; | |
| } | |
| .stTextInput input { | |
| border-radius: 25px !important; | |
| border: 2px solid #e9ecef !important; | |
| padding: 12px 20px !important; | |
| font-size: 16px !important; | |
| } | |
| .stTextInput input:focus { | |
| border-color: #667eea !important; | |
| box-shadow: 0 0 0 0.2rem rgba(102, 126, 234, 0.25) !important; | |
| } | |
| .stButton button { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; | |
| color: white !important; | |
| border: none !important; | |
| border-radius: 25px !important; | |
| padding: 12px 30px !important; | |
| font-weight: 600 !important; | |
| transition: all 0.3s ease !important; | |
| } | |
| .stButton button:hover { | |
| transform: translateY(-2px) !important; | |
| box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4) !important; | |
| } | |
| .sidebar-info { | |
| background: rgba(255, 255, 255, 0.1); | |
| padding: 1rem; | |
| border-radius: 10px; | |
| margin: 1rem 0; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Initialize GROQ API | |
| def setup_groq(): | |
| os.getenv("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") | |
| if not groq_api_key: | |
| st.error("β οΈ GROQ API key not found! Please add it to your Hugging Face secrets.") | |
| st.stop() | |
| return groq_api_key | |
| # Load and process PDF | |
| def load_pdf(): | |
| try: | |
| with open("First-Aid.pdf", "rb") as file: | |
| pdf_reader = PyPDF2.PdfReader(file) | |
| text = "" | |
| for page in pdf_reader.pages: | |
| text += page.extract_text() + "\n" | |
| return text | |
| except FileNotFoundError: | |
| st.error("π First-Aid.pdf not found! Please upload the PDF file to your space.") | |
| st.stop() | |
| except Exception as e: | |
| st.error(f"β Error loading PDF: {str(e)}") | |
| st.stop() | |
| # Setup embeddings and knowledge base | |
| def setup_knowledge_base(): | |
| # Load PDF content | |
| pdf_text = load_pdf() | |
| # Split text into chunks | |
| chunks = [] | |
| sentences = pdf_text.split('\n') | |
| current_chunk = "" | |
| for sentence in sentences: | |
| 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()) | |
| # Load sentence transformer model | |
| model = SentenceTransformer('all-MiniLM-L6-v2') | |
| # Create embeddings for chunks | |
| chunk_embeddings = model.encode(chunks) | |
| return chunks, chunk_embeddings, model | |
| def find_relevant_context(query, chunks, chunk_embeddings, model, top_k=3): | |
| """Find most relevant chunks for the query""" | |
| query_embedding = model.encode([query]) | |
| similarities = cosine_similarity(query_embedding, chunk_embeddings)[0] | |
| top_indices = np.argsort(similarities)[-top_k:][::-1] | |
| relevant_chunks = [chunks[i] for i in top_indices] | |
| return "\n\n".join(relevant_chunks) | |
| def query_groq(prompt, api_key): | |
| """Query GROQ API""" | |
| url = "https://api.groq.com/openai/v1/chat/completions" | |
| headers = { | |
| "Authorization": f"Bearer {api_key}", | |
| "Content-Type": "application/json" | |
| } | |
| data = { | |
| "model": "mixtral-8x7b-32768", | |
| "messages": [ | |
| { | |
| "role": "system", | |
| "content": """You are a First Aid Emergency Assistant. You provide clear, step-by-step first aid guidance based on the provided medical manual context. | |
| IMPORTANT RULES: | |
| 1. Only answer questions related to first aid, medical emergencies, and health safety | |
| 2. If asked about non-medical topics, politely redirect to first aid topics | |
| 3. For serious emergencies, always remind users to call emergency services first | |
| 4. Provide clear, numbered steps when giving instructions | |
| 5. Keep responses focused and practical | |
| If the question is not related to first aid or medical emergencies, respond with: "π¨ I'm specialized in First Aid emergencies only! Please ask me about medical emergencies, CPR, wounds, burns, fractures, or other first aid topics." | |
| """ | |
| }, | |
| { | |
| "role": "user", | |
| "content": prompt | |
| } | |
| ], | |
| "temperature": 0.3, | |
| "max_tokens": 1000 | |
| } | |
| try: | |
| response = requests.post(url, headers=headers, json=data, timeout=30) | |
| response.raise_for_status() | |
| return response.json()["choices"][0]["message"]["content"] | |
| except requests.exceptions.RequestException as e: | |
| return f"β Error connecting to GROQ API: {str(e)}" | |
| except Exception as e: | |
| return f"β Error processing response: {str(e)}" | |
| # Initialize 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\nI can help you with:\nβ’ CPR procedures\nβ’ Bleeding control\nβ’ Burns treatment\nβ’ Choking response\nβ’ Fracture management\nβ’ Poisoning emergencies\nβ’ And much more!\n\nπ‘ **Ask me anything about first aid emergencies!**" | |
| } | |
| ] | |
| if "knowledge_base" not in st.session_state: | |
| with st.spinner("π Loading First Aid knowledge base..."): | |
| chunks, embeddings, model = setup_knowledge_base() | |
| st.session_state.knowledge_base = { | |
| "chunks": chunks, | |
| "embeddings": embeddings, | |
| "model": model | |
| } | |
| if "groq_api_key" not in st.session_state: | |
| st.session_state.groq_api_key = setup_groq() | |
| # Header | |
| st.markdown(""" | |
| <div class="main-header"> | |
| <h1>π¨ First Aid Emergency Assistant</h1> | |
| <p style="margin: 0; font-size: 18px; opacity: 0.9;">Your AI-powered emergency response guide</p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Warning disclaimer | |
| st.markdown(""" | |
| <div class="warning-box"> | |
| <strong>β οΈ IMPORTANT MEDICAL DISCLAIMER:</strong><br> | |
| This chatbot provides general first aid guidance only. In real emergencies, always call emergency services immediately. | |
| This tool is not a substitute for professional medical advice, diagnosis, or treatment. | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Chat container | |
| chat_container = st.container() | |
| with chat_container: | |
| st.markdown('<div class="chat-container">', unsafe_allow_html=True) | |
| # Display chat messages | |
| for message in st.session_state.messages: | |
| if message["role"] == "user": | |
| st.markdown(f""" | |
| <div class="user-message"> | |
| <strong>You:</strong> {message["content"]} | |
| </div> | |
| <div style="clear: both;"></div> | |
| """, unsafe_allow_html=True) | |
| else: | |
| st.markdown(f""" | |
| <div class="bot-message"> | |
| <strong>π€ First Aid Assistant:</strong><br> | |
| {message["content"]} | |
| </div> | |
| <div style="clear: both;"></div> | |
| """, unsafe_allow_html=True) | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # Input section | |
| st.markdown('<div class="input-container">', unsafe_allow_html=True) | |
| col1, col2 = st.columns([4, 1]) | |
| with col1: | |
| user_input = st.text_input( | |
| "", | |
| placeholder="Ask me about first aid emergencies... (e.g., 'How to treat burns?')", | |
| key="user_input", | |
| label_visibility="collapsed" | |
| ) | |
| with col2: | |
| send_button = st.button("Send π", key="send_button") | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # Process user input | |
| if send_button and user_input.strip(): | |
| # Add user message to chat | |
| st.session_state.messages.append({"role": "user", "content": user_input}) | |
| # Get bot response | |
| with st.spinner("π€ Thinking..."): | |
| try: | |
| # Find relevant context from PDF | |
| kb = st.session_state.knowledge_base | |
| context = find_relevant_context( | |
| user_input, | |
| kb["chunks"], | |
| kb["embeddings"], | |
| kb["model"] | |
| ) | |
| # Create enhanced prompt with context | |
| enhanced_prompt = f""" | |
| Based on the following first aid manual content, answer this question: {user_input} | |
| Context from First Aid Manual: | |
| {context} | |
| Please provide a clear, helpful response based on this information. If this is a serious emergency, remind the user to call emergency services first. | |
| """ | |
| # Query GROQ API | |
| response = query_groq(enhanced_prompt, st.session_state.groq_api_key) | |
| # Enhance response with emergency reminder for serious cases | |
| serious_keywords = ['heart attack', 'stroke', 'unconscious', 'not breathing', 'severe bleeding', 'poisoning', 'choking'] | |
| if any(keyword in user_input.lower() for keyword in serious_keywords): | |
| response = f"π¨ **CALL EMERGENCY SERVICES IMMEDIATELY!**\n\n{response}" | |
| except Exception as e: | |
| response = f"β Sorry, I encountered an error: {str(e)}. Please try asking your question differently." | |
| # Add bot response to chat | |
| st.session_state.messages.append({"role": "assistant", "content": response}) | |
| # Rerun to show new message | |
| st.rerun() | |
| # Sidebar with helpful information | |
| with st.sidebar: | |
| st.markdown("## π Quick Emergency Numbers") | |
| st.markdown(""" | |
| <div class="sidebar-info"> | |
| <strong>π¨ Emergency Services:</strong><br> | |
| β’ General Emergency: 911<br> | |
| β’ Poison Control: 1-800-222-1222<br> | |
| β’ Mental Health Crisis: 988 | |
| </div> | |
| """, unsafe_allow_html=True) | |
| st.markdown("## π― What I Can Help With") | |
| st.markdown(""" | |
| <div class="sidebar-info"> | |
| β’ CPR and rescue breathing<br> | |
| β’ Wound care and bleeding<br> | |
| β’ Burns and scalds<br> | |
| β’ Fractures and sprains<br> | |
| β’ Choking procedures<br> | |
| β’ Poisoning emergencies<br> | |
| β’ Heart attack signs<br> | |
| β’ Snake and animal bites<br> | |
| β’ Drowning response<br> | |
| β’ And much more! | |
| </div> | |
| """, unsafe_allow_html=True) | |
| st.markdown("## βΉοΈ How to Use") | |
| st.markdown(""" | |
| <div class="sidebar-info"> | |
| 1. Type your first aid question<br> | |
| 2. Get instant step-by-step guidance<br> | |
| 3. Follow instructions carefully<br> | |
| 4. Seek professional help for serious emergencies | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Footer | |
| st.markdown("---") | |
| st.markdown(""" | |
| <div style="text-align: center; opacity: 0.7; padding: 1rem;"> | |
| π€ First Aid Emergency Assistant | Powered by GROQ AI | Always consult medical professionals for serious emergencies | |
| </div> | |
| """, unsafe_allow_html=True) |