Spaces:
Runtime error
Runtime error
| import os | |
| import sys | |
| from dotenv import load_dotenv | |
| load_dotenv(os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".env")) | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| from config import ( | |
| LLM_PROVIDER, LLM_MODEL, GROQ_API_KEY, | |
| MAX_TOKENS, TEMPERATURE, CLASS_NAMES, IDX_TO_CLASS, | |
| ) | |
| from src.rag import retrieve | |
| SYSTEM_PROMPT = """You are a clinical dermatology AI assistant. | |
| You explain skin lesion classifications to patients and doctors clearly and compassionately. | |
| Always remind users that your analysis is for educational purposes only and not a substitute for professional medical diagnosis. | |
| Use the retrieved medical context to provide accurate, evidence-based explanations.""" | |
| def _call_groq(messages: list, system: str) -> str: | |
| from groq import Groq | |
| client = Groq(api_key=GROQ_API_KEY) | |
| full_messages = [{"role": "system", "content": system}] + messages | |
| response = client.chat.completions.create( | |
| model=LLM_MODEL, | |
| messages=full_messages, | |
| max_tokens=MAX_TOKENS, | |
| temperature=TEMPERATURE, | |
| ) | |
| return response.choices[0].message.content | |
| def _call_llm(messages: list, system: str) -> str: | |
| provider = LLM_PROVIDER.lower() | |
| if provider == "groq": | |
| return _call_groq(messages, system) | |
| raise ValueError(f"Unsupported LLM provider: {provider}") | |
| # ββ Public API βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def explain_prediction( | |
| predicted_class: str, | |
| confidence: float, | |
| probabilities: dict, | |
| ) -> str: | |
| """Generate a clinical explanation for a prediction using RAG + LLM.""" | |
| class_name = CLASS_NAMES[list(IDX_TO_CLASS.values()).index(predicted_class)] | |
| # Retrieve relevant context from DermNet knowledge base | |
| query = f"{class_name} symptoms diagnosis treatment dermoscopy" | |
| context = retrieve(query, top_k=5) | |
| context_text = "\n\n".join( | |
| f"[Source: {c['source']}]\n{c['text']}" for c in context | |
| ) | |
| # Build top-3 probabilities string | |
| top3 = list(probabilities.items())[:3] | |
| top3_str = ", ".join(f"{k}: {v*100:.1f}%" for k, v in top3) | |
| user_message = f""" | |
| A skin lesion image was analyzed by an AI classification model. | |
| **Prediction:** {class_name} ({predicted_class}) | |
| **Confidence:** {confidence*100:.1f}% | |
| **Top-3 probabilities:** {top3_str} | |
| **Retrieved Medical Context from DermNet NZ:** | |
| {context_text} | |
| Please provide: | |
| 1. A brief description of this condition | |
| 2. Key visual/clinical features that characterize it | |
| 3. Risk level and urgency (benign vs potentially malignant) | |
| 4. Recommended next steps for the patient | |
| 5. A compassionate closing note | |
| Keep the response clear, structured, and under 400 words. | |
| """ | |
| messages = [{"role": "user", "content": user_message}] | |
| return _call_llm(messages, SYSTEM_PROMPT) | |
| def answer_question(question: str, predicted_class: str = None) -> str: | |
| """Answer a follow-up question about the diagnosis using RAG + LLM.""" | |
| query = question + (f" {predicted_class}" if predicted_class else "") | |
| context = retrieve(query, top_k=4) | |
| context_text = "\n\n".join( | |
| f"[Source: {c['source']}]\n{c['text']}" for c in context | |
| ) | |
| user_message = f""" | |
| The patient asks: "{question}" | |
| {f'Context: The patient was previously diagnosed with {predicted_class}.' if predicted_class else ''} | |
| **Retrieved Medical Context from DermNet NZ:** | |
| {context_text} | |
| Please answer clearly and compassionately. Remind the user to consult a dermatologist for personal medical advice. | |
| """ | |
| messages = [{"role": "user", "content": user_message}] | |
| return _call_llm(messages, SYSTEM_PROMPT) | |
| # ββ CLI test βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| if __name__ == "__main__": | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| print("=" * 60) | |
| print("Testing RAG + Groq LLM explanation") | |
| print("=" * 60) | |
| explanation = explain_prediction( | |
| predicted_class="mel", | |
| confidence=0.8654, | |
| probabilities={"mel": 0.8654, "nv": 0.0821, "bkl": 0.0312, "bcc": 0.0124, "akiec": 0.0089}, | |
| ) | |
| print("\n[Explanation]\n") | |
| print(explanation) | |
| print("\n" + "=" * 60) | |
| print("Testing follow-up Q&A") | |
| print("=" * 60) | |
| answer = answer_question("Should I be worried? What should I do next?", predicted_class="mel") | |
| print("\n[Answer]\n") | |
| print(answer) | |