Spaces:
Running
Running
File size: 7,138 Bytes
542c765 ee7023b 542c765 ee7023b 542c765 ee7023b 542c765 ee7023b 542c765 ee7023b 542c765 ee7023b 542c765 ee7023b 542c765 ee7023b 542c765 ee7023b 542c765 ee7023b 542c765 ee7023b 542c765 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | import os
import httpx
OPENROUTER_API_KEY = os.environ.get("OPENROUTER_API_KEY", "")
BASE_URL = "https://openrouter.ai/api/v1"
# Use a fast model for simplification (called per-finding, so speed matters)
SIMPLIFY_MODEL = "deepseek/deepseek-chat-v3-0324:free"
def load_model():
"""
Check if OpenRouter API key is available.
In production, this would also load local models.
"""
if OPENROUTER_API_KEY and not OPENROUTER_API_KEY.startswith("placeholder"):
print("✅ OpenRouter API key found — using AI for simplification")
else:
print("⚠️ No OpenRouter API key — using template-based simplification")
return None, None
# Hardcoded fallback templates for when AI is unavailable
FALLBACK_EXPLANATIONS = {
("HIGH", "GLUCOSE"): {
"english": "Your blood glucose is elevated at {value} {unit}. This suggests your body is having trouble managing blood sugar. Reduce sugary foods and consult your doctor for diabetes screening.",
"hindi": "आपका ब्लड ग्लूकोज़ {value} {unit} पर बढ़ा हुआ है। यह दर्शाता है कि आपका शरीर ब्लड शुगर को नियंत्रित करने में परेशानी आ रही है। मीठे खाना कम करें और डॉक्टर से मिलें।"
},
("HIGH", "SGPT"): {
"english": "Your liver enzyme SGPT is high at {value} {unit}. This indicates liver inflammation. Avoid fatty foods and alcohol.",
"hindi": "आपका यकृत एंजाइम SGPT {value} {unit} पर बढ़ा हुआ है। यह यकृत में सूजन दर्शाता है। तैलीय खाना और शराब न लें।"
},
("LOW", "HEMOGLOBIN"): {
"english": "Your hemoglobin is low at {value} {unit}. You may be anemic. Increase iron-rich foods like spinach and beans.",
"hindi": "आपका हीमोग्लोबिन {value} {unit} पर कम है। आपको एनीमिया हो सकता है। पालक और दाल जैसे आयरन युक्त खाना बढ़ाएं।"
},
("HIGH", "CHOLESTEROL"): {
"english": "Your cholesterol is elevated at {value} {unit}. Reduce saturated fats, increase fiber, and exercise regularly.",
"hindi": "आपका कोलेस्ट्रॉल {value} {unit} पर बढ़ा हुआ है। संतृप्त वसा कम करें और नियमित व्यायाम करें।"
},
("HIGH", "CREATININE"): {
"english": "Your creatinine is elevated at {value} {unit}. This may indicate kidney issues. Reduce protein intake and stay hydrated.",
"hindi": "आपका क्रिएटिनिन {value} {unit} पर बढ़ा है। यह गुर्दे की समस्या दर्शा सकता है। प्रोटीन इनटेक कम करें।"
},
}
def _ai_simplify(parameter: str, value: str, unit: str, status: str, rag_context: str) -> dict | None:
"""Call OpenRouter to generate a layman explanation of a lab finding."""
if not OPENROUTER_API_KEY or OPENROUTER_API_KEY.startswith("placeholder"):
return None
prompt = f"""You are a friendly Indian doctor explaining lab results to a patient who has no medical knowledge.
Lab Finding:
- Parameter: {parameter}
- Value: {value} {unit}
- Status: {status}
{f'- Context: {rag_context}' if rag_context else ''}
Provide two explanations (2-3 sentences each):
1. In simple English
2. In simple Hindi (Devanagari script, everyday words)
Format your response EXACTLY as:
ENGLISH: <explanation>
HINDI: <explanation>"""
try:
headers = {
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
"Content-Type": "application/json",
"HTTP-Referer": "https://reportraahat.app",
"X-Title": "ReportRaahat",
}
with httpx.Client(timeout=15.0) as client:
resp = client.post(
f"{BASE_URL}/chat/completions",
headers=headers,
json={
"model": SIMPLIFY_MODEL,
"messages": [{"role": "user", "content": prompt}],
"max_tokens": 300,
"temperature": 0.5,
},
)
if resp.status_code == 200:
text = resp.json()["choices"][0]["message"]["content"].strip()
# Parse ENGLISH: and HINDI: from response
english = ""
hindi = ""
for line in text.split("\n"):
line = line.strip()
if line.upper().startswith("ENGLISH:"):
english = line[8:].strip()
elif line.upper().startswith("HINDI:"):
hindi = line[6:].strip()
if english and hindi:
return {"english": english, "hindi": hindi}
# If parsing failed, use the full response as English
return {"english": text[:200], "hindi": f"{parameter} {status.lower()} है। डॉक्टर से मिलें।"}
print(f"⚠️ AI simplify failed ({resp.status_code})")
return None
except Exception as e:
print(f"⚠️ AI simplify error: {e}")
return None
def simplify_finding(
parameter: str,
value: str,
unit: str,
status: str,
rag_context: str = ""
) -> dict:
"""
Generate a layman-friendly explanation for a lab finding.
Tries AI first, then falls back to templates.
"""
# Try AI-powered simplification
ai_result = _ai_simplify(parameter, value, unit, status, rag_context)
if ai_result:
return ai_result
# Fallback to template matching
param_upper = parameter.upper()
status_upper = status.upper()
for (status_key, param_key) in FALLBACK_EXPLANATIONS.keys():
if param_key in param_upper and status_key == status_upper:
template = FALLBACK_EXPLANATIONS[(status_key, param_key)]
return {
"english": template["english"].format(value=value, unit=unit),
"hindi": template["hindi"].format(value=value, unit=unit),
}
# Generic default
default_exp = {
"HIGH": f"Your {parameter} is high at {value} {unit}. This needs attention. Consult your doctor.",
"LOW": f"Your {parameter} is low at {value} {unit}. This may indicate a deficiency. Consult your doctor.",
"CRITICAL": f"Your {parameter} is critically abnormal at {value} {unit}. Please see a doctor urgently.",
"NORMAL": f"Your {parameter} is normal at {value} {unit}. Keep maintaining healthy habits."
}
return {
"english": default_exp.get(status_upper, f"Your {parameter} is {status.lower()}."),
"hindi": f"{parameter} {status.lower()} है। डॉक्टर से मिलें।"
}
|