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()} है। डॉक्टर से मिलें।"
    }