Spaces:
Running
Running
| # api/engine.py - Production-Ready Medical Research Engine | |
| # Simplified with one robust reasoning technique for medical research | |
| import asyncio | |
| import json | |
| import os | |
| import sys | |
| import re | |
| from typing import Dict, Any, Optional, List | |
| from datetime import datetime | |
| import concurrent.futures | |
| from pathlib import Path | |
| # ============================================================================ | |
| # ENVIRONMENT SETUP | |
| # ============================================================================ | |
| # Add project root to Python path | |
| project_root = Path(__file__).parent.parent | |
| sys.path.insert(0, str(project_root)) | |
| # Load environment variables | |
| from dotenv import load_dotenv | |
| env_paths = [ | |
| project_root / ".env", | |
| project_root / "api" / ".env", | |
| Path.cwd() / ".env", | |
| ] | |
| env_loaded = False | |
| for env_path in env_paths: | |
| if env_path.exists(): | |
| load_dotenv(dotenv_path=env_path, override=True) | |
| print(f"✅ Loaded environment from: {env_path}") | |
| env_loaded = True | |
| break | |
| if not env_loaded: | |
| print("⚠️ No .env file found. Using system environment variables.") | |
| # Check critical environment variables | |
| GROQ_API_KEY = os.getenv("GROQ_API_KEY") | |
| XAI_API_KEY = os.getenv("XAI_API_KEY") | |
| MODEL = os.getenv("MODEL", "gpt-oss-120b") | |
| if not GROQ_API_KEY and not XAI_API_KEY: | |
| print("❌ WARNING: No API key found in environment!") | |
| print(" Set GROQ_API_KEY or XAI_API_KEY in .env file") | |
| else: | |
| last4 = (GROQ_API_KEY or XAI_API_KEY)[-4:] | |
| print(f"✅ API Key found: {'*' * 16}{last4}") | |
| print(f"✅ Model configured: {MODEL}") | |
| # ============================================================================ | |
| # SINGLE REASONING TECHNIQUE: EVIDENCE-BASED MEDICAL REASONING | |
| # ============================================================================ | |
| class MedicalReasoning: | |
| """Single, robust reasoning technique for medical research""" | |
| def evidence_based_reasoning(query: str, domain: str, user_context: str, papers_count: int = 0) -> str: | |
| """ | |
| Evidence-based medical reasoning for research insights | |
| Focuses on clinical evidence, study quality, and practical implications | |
| """ | |
| # Map user context to specific focus areas | |
| context_focus = { | |
| "clinician": "Focus on clinical application, treatment decisions, and patient management", | |
| "researcher": "Focus on methodology, evidence quality, and research implications", | |
| "student": "Focus on understanding concepts, foundational knowledge, and learning pathways", | |
| "patient": "Focus on understanding, personal implications, and practical next steps", | |
| "administrator": "Focus on implementation, resources, and systemic considerations", | |
| "general": "Focus on clear explanations and balanced overview" | |
| } | |
| focus = context_focus.get(user_context, "Focus on evidence-based medical insights") | |
| return f"""You are a medical research expert specializing in {domain}. | |
| The user is a {user_context}. {focus} | |
| QUERY: {query} | |
| **Evidence-Based Reasoning Process:** | |
| 1. **Evidence Assessment:** | |
| - What is the current state of evidence for this topic? | |
| - What types of studies exist (RCTs, cohort studies, reviews)? | |
| - What is the quality and strength of available evidence? | |
| 2. **Clinical/Research Context:** | |
| - How does this apply to {domain} specifically? | |
| - What are the practical implications for {user_context}? | |
| - What are the key considerations in this context? | |
| 3. **Critical Analysis:** | |
| - What are the strengths of current evidence? | |
| - What limitations or gaps exist in current knowledge? | |
| - What controversies or alternative perspectives exist? | |
| 4. **Practical Implications:** | |
| - What are the actionable insights for {user_context}? | |
| - What are the next steps or recommendations? | |
| - What should be considered for implementation? | |
| Provide a comprehensive, evidence-based answer that synthesizes medical knowledge | |
| with practical implications for {user_context} in {domain}.""" | |
| # ============================================================================ | |
| # MEDICAL DOMAIN CONFIGURATION | |
| # ============================================================================ | |
| MEDICAL_DOMAINS = [ | |
| {"id": "internal_medicine", "name": "Internal Medicine", "icon": "🏥", | |
| "description": "General internal medicine and diagnosis"}, | |
| {"id": "endocrinology", "name": "Endocrinology", "icon": "🧬", | |
| "description": "Hormonal and metabolic disorders"}, | |
| {"id": "gastroenterology", "name": "Gastroenterology", "icon": "🩸", | |
| "description": "Digestive system disorders"}, | |
| {"id": "pulmonology", "name": "Pulmonology", "icon": "🫁", | |
| "description": "Respiratory diseases and lung disorders"}, | |
| {"id": "nephrology", "name": "Nephrology", "icon": "🧪", | |
| "description": "Kidney diseases and renal function"}, | |
| {"id": "hematology", "name": "Hematology", "icon": "🩸", | |
| "description": "Blood disorders and hematologic diseases"}, | |
| {"id": "infectious_disease", "name": "Infectious Diseases", "icon": "🦠", | |
| "description": "Infectious diseases and microbiology"}, | |
| {"id": "obstetrics_gynecology", "name": "Obstetrics & Gynecology", "icon": "🤰", | |
| "description": "Women's health, pregnancy and reproductive medicine"}, | |
| {"id": "pathology", "name": "Pathology", "icon": "🔬", | |
| "description": "Disease diagnosis through tissue examination"}, | |
| {"id": "laboratory_medicine", "name": "Laboratory Medicine", "icon": "🧪", | |
| "description": "Clinical laboratory testing and biomarkers"}, | |
| {"id": "bioinformatics", "name": "Bioinformatics", "icon": "💻", | |
| "description": "Computational analysis of biological data"}, | |
| {"id": "clinical_research", "name": "Clinical Research", "icon": "📊", | |
| "description": "Clinical trials and evidence-based medicine"}, | |
| {"id": "medical_imaging", "name": "Medical Imaging", "icon": "🩻", | |
| "description": "Medical imaging and radiology"}, | |
| {"id": "oncology", "name": "Oncology", "icon": "🦠", | |
| "description": "Cancer research and treatment"}, | |
| {"id": "cardiology", "name": "Cardiology", "icon": "❤️", | |
| "description": "Heart and cardiovascular diseases"}, | |
| {"id": "neurology", "name": "Neurology", "icon": "🧠", | |
| "description": "Brain and nervous system disorders"}, | |
| {"id": "pharmacology", "name": "Pharmacology", "icon": "💊", | |
| "description": "Drug therapy and medication management"}, | |
| {"id": "genomics", "name": "Genomics", "icon": "🧬", | |
| "description": "Genetic research and personalized medicine"}, | |
| {"id": "public_health", "name": "Public Health", "icon": "🌍", | |
| "description": "Population health and epidemiology"}, | |
| {"id": "surgery", "name": "Surgery", "icon": "⚕️", | |
| "description": "Surgical procedures and techniques"}, | |
| {"id": "pediatrics", "name": "Pediatrics", "icon": "👶", | |
| "description": "Child health and pediatric medicine"}, | |
| {"id": "psychiatry", "name": "Psychiatry", "icon": "🧠", | |
| "description": "Mental health and psychiatric disorders"}, | |
| {"id": "dermatology", "name": "Dermatology", "icon": "🦋", | |
| "description": "Skin diseases and dermatologic conditions"}, | |
| {"id": "orthopedics", "name": "Orthopedics", "icon": "🦴", | |
| "description": "Musculoskeletal disorders and bone health"}, | |
| {"id": "ophthalmology", "name": "Ophthalmology", "icon": "👁️", | |
| "description": "Eye diseases and vision care"}, | |
| {"id": "urology", "name": "Urology", "icon": "💧", | |
| "description": "Urinary system and male reproductive health"}, | |
| {"id": "emergency_medicine", "name": "Emergency Medicine", "icon": "🚑", | |
| "description": "Acute care and emergency response"}, | |
| {"id": "critical_care", "name": "Critical Care", "icon": "🏥", | |
| "description": "Intensive care and critical illness"}, | |
| {"id": "pain_medicine", "name": "Pain Medicine", "icon": "⚕️", | |
| "description": "Pain management and analgesia"}, | |
| {"id": "nutrition", "name": "Nutrition", "icon": "🥗", | |
| "description": "Clinical nutrition and dietary management"}, | |
| {"id": "allergy_immunology", "name": "Allergy & Immunology", "icon": "🤧", | |
| "description": "Allergic diseases and immune disorders"}, | |
| {"id": "rehabilitation_medicine", "name": "Rehabilitation Medicine", "icon": "♿", | |
| "description": "Physical therapy and recovery"}, | |
| {"id": "general_medical", "name": "General Medical", "icon": "⚕️", | |
| "description": "General medical research and clinical questions"}, | |
| {"id": "auto", "name": "Auto-detect", "icon": "🤖", | |
| "description": "Automatically detect domain from query"} | |
| ] | |
| USER_CONTEXTS = [ | |
| {"id": "auto", "name": "Auto-detect", "icon": "🤖", | |
| "description": "Automatically detect user context"}, | |
| {"id": "clinician", "name": "Clinician", "icon": "👨⚕️", | |
| "description": "Medical doctors, nurses, and healthcare providers"}, | |
| {"id": "researcher", "name": "Researcher", "icon": "🔬", | |
| "description": "Academic researchers and scientists"}, | |
| {"id": "student", "name": "Student", "icon": "🎓", | |
| "description": "Medical students and trainees"}, | |
| {"id": "administrator", "name": "Administrator", "icon": "💼", | |
| "description": "Healthcare administrators and managers"}, | |
| {"id": "patient", "name": "Patient", "icon": "👤", | |
| "description": "Patients and general public"}, | |
| {"id": "general", "name": "General", "icon": "👤", | |
| "description": "General audience"} | |
| ] | |
| # Domain detection keywords (simplified) | |
| DOMAIN_KEYWORDS = { | |
| 'internal_medicine': ['diagnosis', 'chronic disease', 'acute disease', 'primary care'], | |
| 'endocrinology': ['diabetes', 'thyroid', 'hormone', 'metabolism'], | |
| 'cardiology': ['heart', 'cardiovascular', 'hypertension', 'ecg'], | |
| 'neurology': ['brain', 'stroke', 'alzheimer', 'parkinson'], | |
| 'oncology': ['cancer', 'tumor', 'chemotherapy', 'radiation'], | |
| 'surgery': ['surgical', 'operation', 'procedure', 'anesthesia'], | |
| 'pediatrics': ['child', 'pediatric', 'neonatal', 'infant'], | |
| 'psychiatry': ['mental', 'depression', 'anxiety', 'psychiatric'], | |
| 'infectious_disease': ['infection', 'bacterial', 'viral', 'antibiotic'], | |
| } | |
| # User context detection keywords | |
| USER_CONTEXT_KEYWORDS = { | |
| 'clinician': ['patient', 'clinical', 'treatment', 'diagnosis', 'therapy'], | |
| 'researcher': ['research', 'study', 'methodology', 'evidence', 'publication'], | |
| 'student': ['learn', 'study', 'exam', 'textbook', 'course'], | |
| 'patient': ['i have', 'my symptoms', 'my doctor', 'my treatment', 'pain'], | |
| 'administrator': ['policy', 'guideline', 'cost', 'efficiency', 'management'] | |
| } | |
| # ============================================================================ | |
| # MEDICAL RESEARCH CHAT ENGINE | |
| # ============================================================================ | |
| class MedicalResearchEngine: | |
| """Production-ready medical research engine with evidence-based reasoning""" | |
| def __init__(self): | |
| self.engines: Dict[str, Any] = {} | |
| self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=10) | |
| self.api_configured = False | |
| self.api_error = None | |
| self.model = MODEL | |
| self.reasoning = MedicalReasoning() | |
| # Basic responses for common queries | |
| self.basic_responses = { | |
| "hi": "👋 Hello! I'm your Medical Research Assistant. I can help with evidence-based medical research questions across various specialties. How can I assist you today?", | |
| "hello": "👋 Welcome! I specialize in medical research analysis using evidence-based reasoning. What medical topic would you like to explore?", | |
| "help": "🆘 **How to use:**\n1. Ask medical research questions\n2. Specify domain or use auto-detect\n3. Mention your role (clinician, researcher, etc.)\n\n**Examples:**\n• 'Latest treatments for diabetes'\n• 'Research gaps in cancer immunotherapy'\n• 'Clinical guidelines for hypertension'", | |
| "what can you do": "🔬 **Medical Research Assistant Capabilities:**\n• Evidence-based medical analysis\n• Domain-specific research insights\n• Clinical/research perspective adaptation\n• Paper summarization and analysis\n• Research gap identification\n\nAsk me about any medical research topic!" | |
| } | |
| self._test_api_connection() | |
| print(f"🚀 Medical Research Engine Initialized") | |
| def _test_api_connection(self): | |
| """Test API connection""" | |
| try: | |
| from chat.rag_engine import EnhancedRAGEngine | |
| EnhancedRAGEngine(session_id="test_init", model=self.model) | |
| self.api_configured = True | |
| print("✅ API Connection Test: SUCCESS") | |
| except Exception as e: | |
| self.api_configured = False | |
| self.api_error = str(e) | |
| print(f"❌ API Connection Test: FAILED - {e}") | |
| def detect_domain_from_query(self, query: str, current_domain: str = "auto") -> str: | |
| """Detect medical domain from query text""" | |
| if current_domain != "auto": | |
| return current_domain | |
| query_lower = query.lower() | |
| best_domain = 'general_medical' | |
| best_score = 0 | |
| for domain_id, keywords in DOMAIN_KEYWORDS.items(): | |
| score = sum(1 for keyword in keywords if keyword in query_lower) | |
| if score > best_score: | |
| best_score = score | |
| best_domain = domain_id | |
| return best_domain if best_score > 0 else 'general_medical' | |
| def detect_user_context_from_query(self, query: str, current_context: str = "auto") -> str: | |
| """Detect user context from query text""" | |
| if current_context != "auto": | |
| return current_context | |
| query_lower = query.lower() | |
| best_context = 'general' | |
| best_score = 0 | |
| for context_id, keywords in USER_CONTEXT_KEYWORDS.items(): | |
| score = sum(1 for keyword in keywords if keyword in query_lower) | |
| if score > best_score: | |
| best_score = score | |
| best_context = context_id | |
| return best_context if best_score > 0 else 'general' | |
| def get_domain_info(self, domain_id: str) -> Dict: | |
| """Get information about a domain""" | |
| for domain in MEDICAL_DOMAINS: | |
| if domain["id"] == domain_id: | |
| return domain | |
| return { | |
| "id": domain_id, | |
| "name": domain_id.replace('_', ' ').title(), | |
| "icon": "⚕️", | |
| "description": "Medical research domain" | |
| } | |
| def get_user_context_info(self, context_id: str) -> Dict: | |
| """Get information about a user context""" | |
| for context in USER_CONTEXTS: | |
| if context["id"] == context_id: | |
| return context | |
| return { | |
| "id": context_id, | |
| "name": context_id.replace('_', ' ').title(), | |
| "icon": "👤", | |
| "description": "User context" | |
| } | |
| def _classify_query(self, query: str) -> str: | |
| """Classify query type""" | |
| query_lower = query.lower().strip() | |
| # Check if it's a basic greeting/help | |
| if query_lower in self.basic_responses: | |
| return "basic" | |
| # Check for paper summarization | |
| if any(term in query_lower for term in ['summarize paper', 'paper titled', 'article about']): | |
| return "paper_summary" | |
| # Default to research query | |
| return "research" | |
| async def process_query_async( | |
| self, | |
| query: str, | |
| domain: str = "general_medical", | |
| session_id: str = "default", | |
| user_context: str = "auto", | |
| **kwargs | |
| ) -> Dict[str, Any]: | |
| """Process medical research query with evidence-based reasoning""" | |
| # Auto-detect domain if needed | |
| if domain == "auto": | |
| domain = self.detect_domain_from_query(query) | |
| # Auto-detect user context if needed | |
| if user_context == "auto": | |
| user_context = self.detect_user_context_from_query(query) | |
| # Get domain and context info | |
| domain_info = self.get_domain_info(domain) | |
| context_info = self.get_user_context_info(user_context) | |
| # Classify the query | |
| query_type = self._classify_query(query) | |
| # Handle basic queries | |
| if query_type == "basic": | |
| response_text = self.basic_responses.get(query.lower(), | |
| f"👋 I'm your Medical Research Assistant specializing in {domain_info['name']}. " | |
| f"How can I help with your medical research question today?" | |
| ) | |
| return { | |
| "answer": response_text, | |
| "papers_used": 0, | |
| "confidence_score": {"overall_score": 95.0, "level": "HIGH 🟢"}, | |
| "query_type": "basic", | |
| "user_context": user_context, | |
| "domain": domain, | |
| "domain_info": domain_info, | |
| "user_context_info": context_info | |
| } | |
| # Handle paper summarization | |
| elif query_type == "paper_summary": | |
| return await self._handle_paper_summarization(query, session_id, domain, user_context) | |
| # Handle research queries | |
| else: | |
| return await self._handle_research_query(query, domain, user_context, session_id, kwargs) | |
| async def _handle_research_query(self, query: str, domain: str, user_context: str, | |
| session_id: str, kwargs: Dict) -> Dict[str, Any]: | |
| """Handle medical research queries with evidence-based reasoning""" | |
| # Get domain and context info | |
| domain_info = self.get_domain_info(domain) | |
| context_info = self.get_user_context_info(user_context) | |
| # Apply evidence-based reasoning | |
| reasoning_prompt = self.reasoning.evidence_based_reasoning(query, domain, user_context) | |
| # Initialize engine | |
| engine = self.initialize_session(session_id) | |
| # Run in thread pool | |
| loop = asyncio.get_event_loop() | |
| try: | |
| # Process query with timeout | |
| response = await asyncio.wait_for( | |
| loop.run_in_executor( | |
| self.executor, | |
| lambda: engine.answer_research_question( | |
| query=query, | |
| domain=domain, | |
| user_context=user_context, | |
| reasoning_method="evidence_based", # Pass reasoning method | |
| **{k: v for k, v in kwargs.items() if k != 'enable_reasoning'} | |
| ) | |
| ), | |
| timeout=kwargs.get('timeout', 60.0) | |
| ) | |
| # Clean up response | |
| answer = response.get("answer", "") | |
| cleaned_answer = self._clean_response(answer, domain_info, query) | |
| # Prepare result | |
| result = { | |
| "answer": cleaned_answer, | |
| "papers_used": response.get("papers_used", 0), | |
| "confidence_score": response.get("confidence_score", {"overall_score": 0}), | |
| "query_type": "research", | |
| "user_context": user_context, | |
| "domain": domain, | |
| "domain_info": domain_info, | |
| "user_context_info": context_info, | |
| "reasoning_method": "evidence_based" | |
| } | |
| # Add metrics if available | |
| if "enhanced_metrics" in response: | |
| result["metrics"] = response["enhanced_metrics"] | |
| return result | |
| except asyncio.TimeoutError: | |
| return self._create_timeout_response(query, domain_info, context_info) | |
| except Exception as e: | |
| return self._create_error_response(query, domain_info, context_info, str(e)) | |
| def _clean_response(self, answer: str, domain_info: Dict, query: str) -> str: | |
| """Clean up the response for presentation""" | |
| if not answer: | |
| return f"# 🔬 **Medical Research Analysis**\n\n**Domain:** {domain_info['name']}\n\nNo analysis generated. Please try again." | |
| # Remove any internal reasoning prompts that might have leaked | |
| patterns_to_remove = [ | |
| r'Chain Of Thought.*?\n\n', | |
| r'Step \d+.*?\n\n', | |
| r'Reasoning Process.*?\n\n' | |
| ] | |
| cleaned = answer | |
| for pattern in patterns_to_remove: | |
| cleaned = re.sub(pattern, '', cleaned, flags=re.DOTALL | re.IGNORECASE) | |
| # Ensure clean structure | |
| if not cleaned.startswith('# '): | |
| cleaned = f"# 🔬 **Medical Research Analysis**\n\n**Domain:** {domain_info['name']}\n**Topic:** {query}\n\n{cleaned}" | |
| return cleaned.strip() | |
| async def _handle_paper_summarization(self, query: str, session_id: str, | |
| domain: str, user_context: str) -> Dict[str, Any]: | |
| """Handle single paper summarization requests""" | |
| try: | |
| engine = self.initialize_session(session_id) | |
| # Extract paper title from query | |
| paper_title = self._extract_paper_title(query) | |
| if not paper_title: | |
| return { | |
| "answer": """# 📄 **Paper Summarization Help** | |
| Please provide a paper title to summarize, for example: | |
| • "Summarize the paper 'Deep Learning for Medical Imaging'" | |
| • "What does the paper 'COVID-19 Vaccine Efficacy Study' find?" | |
| • "Give me a summary of 'Guidelines for Hypertension Management'" | |
| I'll provide a comprehensive analysis including methodology, findings, and implications.""", | |
| "papers_used": 0, | |
| "confidence_score": {"overall_score": 0}, | |
| "query_type": "help" | |
| } | |
| # Run summarization | |
| loop = asyncio.get_event_loop() | |
| summary_result = await asyncio.wait_for( | |
| loop.run_in_executor( | |
| self.executor, | |
| lambda: engine.summarize_single_paper( | |
| paper_title=paper_title, | |
| user_query=query | |
| ) | |
| ), | |
| timeout=30.0 | |
| ) | |
| if summary_result.get("success"): | |
| # Format the response | |
| response_text = self._format_paper_summary(summary_result, domain) | |
| return { | |
| "answer": response_text, | |
| "papers_used": 1, | |
| "confidence_score": {"overall_score": summary_result.get("confidence", 0.7) * 100}, | |
| "query_type": "paper_summary", | |
| "paper_details": { | |
| "title": summary_result.get("paper_title", ""), | |
| "authors": summary_result.get("authors", []), | |
| "date": summary_result.get("publication_date", ""), | |
| "source": summary_result.get("source", "") | |
| } | |
| } | |
| else: | |
| return { | |
| "answer": f"""# 🔍 **Paper Not Found** | |
| I couldn't find the paper: *"{paper_title}"* | |
| **Suggestions:** | |
| 1. Check the exact title spelling | |
| 2. Try a more general search | |
| 3. Search by key concepts instead | |
| You can also request: "Find papers about [topic]" or "Research on [condition]".""", | |
| "papers_used": 0, | |
| "confidence_score": {"overall_score": 0}, | |
| "query_type": "paper_summary_error" | |
| } | |
| except Exception as e: | |
| return { | |
| "answer": f"""# 🚨 **Summarization Error** | |
| Error: {str(e)} | |
| Please try again with a different paper or simpler request.""", | |
| "papers_used": 0, | |
| "confidence_score": {"overall_score": 0}, | |
| "query_type": "error" | |
| } | |
| def _extract_paper_title(self, query: str) -> Optional[str]: | |
| """Extract paper title from query""" | |
| # Pattern 1: Paper titled "Title" | |
| match = re.search(r'paper (?:titled|called) "([^"]+)"', query.lower()) | |
| if match: | |
| return match.group(1).strip() | |
| # Pattern 2: "Title" paper | |
| match = re.search(r'"([^"]+)" paper', query.lower()) | |
| if match: | |
| return match.group(1).strip() | |
| # Pattern 3: Summarize the paper Title | |
| match = re.search(r'summarize (?:the )?paper (.+)', query.lower()) | |
| if match: | |
| title = match.group(1).strip() | |
| title = re.sub(r'\?$', '', title) | |
| return title.strip() | |
| return None | |
| def _format_paper_summary(self, summary_result: Dict, domain: str) -> str: | |
| """Format paper summary for display""" | |
| title = summary_result.get("paper_title", "Unknown Paper") | |
| authors = summary_result.get("authors", []) | |
| date = summary_result.get("publication_date", "") | |
| source = summary_result.get("source", "") | |
| summary = summary_result.get("summary", "") | |
| # Format authors | |
| if authors and isinstance(authors, list): | |
| if len(authors) <= 3: | |
| author_str = ", ".join(authors) | |
| else: | |
| author_str = f"{authors[0]} et al." | |
| else: | |
| author_str = "Unknown authors" | |
| # Build response | |
| response = f"""# 📄 **Paper Analysis** | |
| **Title:** {title} | |
| **Authors:** {author_str} | |
| **Published:** {date} | |
| **Source:** {source} | |
| --- | |
| ## 📋 **Summary** | |
| {summary} | |
| --- | |
| ## 🔍 **Key Points** | |
| • Main findings and conclusions | |
| • Methodology and study design | |
| • Clinical/research implications | |
| • Limitations and future directions | |
| *Analysis confidence: {summary_result.get('confidence', 0.7) * 100:.1f}%*""" | |
| return response | |
| def _create_timeout_response(self, query: str, domain_info: Dict, context_info: Dict) -> Dict[str, Any]: | |
| """Create timeout response""" | |
| return { | |
| "answer": f"""# ⏱️ **Query Timed Out** | |
| **Domain:** {domain_info['name']} | |
| **User Context:** {context_info['name']} | |
| The analysis was taking too long. Try: | |
| • Simplifying your question | |
| • Being more specific | |
| • Reducing the scope | |
| **Example:** "Key treatments for [condition] in {domain_info['name']}" """, | |
| "papers_used": 0, | |
| "confidence_score": {"overall_score": 0}, | |
| "query_type": "error", | |
| "user_context": context_info["id"], | |
| "domain": domain_info["id"], | |
| "error": "timeout" | |
| } | |
| def _create_error_response(self, query: str, domain_info: Dict, context_info: Dict, error: str) -> Dict[str, Any]: | |
| """Create error response""" | |
| return { | |
| "answer": f"""# 🚨 **Analysis Error** | |
| **Domain:** {domain_info['name']} | |
| **User Context:** {context_info['name']} | |
| **Error:** {error} | |
| **Troubleshooting:** | |
| 1. Check your internet connection | |
| 2. Try a simpler query | |
| 3. Verify domain selection | |
| 4. Contact support if problem persists""", | |
| "papers_used": 0, | |
| "confidence_score": {"overall_score": 0}, | |
| "query_type": "error", | |
| "user_context": context_info["id"], | |
| "domain": domain_info["id"], | |
| "error": error | |
| } | |
| def initialize_session(self, session_id: str): | |
| """Initialize engine for a session""" | |
| if session_id not in self.engines: | |
| try: | |
| if not self.api_configured: | |
| self.engines[session_id] = self._create_fallback_engine() | |
| print(f"⚠️ Session {session_id}: Using fallback engine") | |
| else: | |
| from chat.rag_engine import EnhancedRAGEngine | |
| self.engines[session_id] = EnhancedRAGEngine( | |
| session_id=session_id, | |
| model=self.model | |
| ) | |
| print(f"✅ Session engine initialized: {session_id}") | |
| except Exception as e: | |
| print(f"❌ Failed to initialize engine for {session_id}: {e}") | |
| self.engines[session_id] = self._create_fallback_engine() | |
| return self.engines[session_id] | |
| def _create_fallback_engine(self): | |
| """Create a fallback engine when API fails""" | |
| class FallbackEngine: | |
| def __init__(self): | |
| self.session_id = "fallback" | |
| self.metrics = {"total_queries": 0} | |
| def answer_research_question(self, **kwargs): | |
| query = kwargs.get("query", "") | |
| domain = kwargs.get("domain", "general_medical") | |
| user_context = kwargs.get("user_context", "auto") | |
| self.metrics["total_queries"] += 1 | |
| if query.lower().strip() in {"hi", "hello", "hey"}: | |
| return { | |
| "answer": f"""# 👋 Welcome to Medical Research Assistant! | |
| **Setup Required:** | |
| 1. Get an API key from https://console.groq.com | |
| 2. Create a `.env` file with: | |
| GROQ_API_KEY=your_key_here | |
| MODEL=gpt-oss-120b | |
| 3. Restart the server | |
| **Features After Setup:** | |
| • Evidence-based medical research analysis | |
| • Domain-specific insights | |
| • Paper summarization | |
| • Research gap analysis""", | |
| "papers_used": 0, | |
| "confidence": 0.15, | |
| } | |
| return { | |
| "answer": f"""⚠️ **API Not Configured** | |
| Current query: {query} | |
| Domain: {domain} | |
| User Context: {user_context} | |
| Please configure your GROQ_API_KEY in the .env file and restart the server.""", | |
| "papers_used": 0, | |
| "confidence": 0.10, | |
| } | |
| def summarize_single_paper(self, **kwargs): | |
| """Fallback for single paper summarization""" | |
| paper_title = kwargs.get("paper_title", "Unknown Paper") | |
| return { | |
| "success": False, | |
| "error": "API not configured", | |
| "paper_title": paper_title, | |
| "summary": "Please configure your API key to use paper analysis." | |
| } | |
| return FallbackEngine() | |
| def get_engine_status(self) -> Dict[str, Any]: | |
| """Get engine status and metrics""" | |
| return { | |
| "api_configured": self.api_configured, | |
| "model": self.model, | |
| "active_sessions": len(self.engines), | |
| "domains_supported": len(MEDICAL_DOMAINS), | |
| "user_contexts_supported": len(USER_CONTEXTS), | |
| "reasoning_technique": "evidence_based_reasoning", | |
| "features": [ | |
| "medical_research_analysis", | |
| "domain_specific_insights", | |
| "user_context_adaptation", | |
| "paper_summarization", | |
| "evidence_based_reasoning" | |
| ] | |
| } | |
| def clear_memory(self): | |
| """Clear engine memory for all sessions""" | |
| self.engines.clear() | |
| print("🧹 Engine memory cleared for all sessions") |