File size: 3,374 Bytes
a1ea7b4
229fc53
 
 
a1ea7b4
229fc53
a1ea7b4
 
 
 
 
 
 
 
229fc53
 
4a34d56
a1ea7b4
229fc53
4a34d56
229fc53
 
 
 
 
4a34d56
 
 
58e50ff
2a98f28
 
 
 
 
 
 
58e50ff
2a98f28
 
58e50ff
229fc53
 
 
a1ea7b4
229fc53
 
 
 
 
 
 
 
 
 
 
 
a1ea7b4
229fc53
 
 
 
 
 
4a34d56
229fc53
 
a1ea7b4
 
 
c19c1f8
 
 
229fc53
 
4a34d56
c19c1f8
 
 
 
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
import json
import re
from src.model_loader import generate_response

# Supported language codes: en, vn, zh, es, fr, ja

_LANG_INSTRUCTIONS = {
    "en": "Respond in English.",
    "vn": "Respond in Vietnamese (Tiếng Việt).",
    "zh": "Respond in Simplified Chinese (简体中文).",
    "es": "Respond in Spanish (Español).",
    "fr": "Respond in French (Français).",
    "ja": "Respond in Japanese (日本語).",
}


def _build_prompt(image_path: str | None, text_description: str, lang: str, region: str = "") -> str:
    lang_instruction = _LANG_INSTRUCTIONS.get(lang, _LANG_INSTRUCTIONS["en"])
    has_image = bool(image_path)
    region_line = f"Affected body region: {region}\n" if region else ""
    return (
        "You are MediVision, a professional dermatology and wound-care assistant.\n"
        f"{lang_instruction}\n"
        "The user has provided"
        + (" an image of a skin condition and" if has_image else "")
        + " the following clinical information:\n\n"
        + region_line
        + f"Symptom description: {text_description}\n\n"
        "Analyze the above and respond with a single JSON object using these exact keys:\n"
        "  \"diagnosis\": the standard clinical/medical condition name (e.g. contact dermatitis, "
        "superficial laceration, cellulitis, tinea corporis) — NOT a restatement or summary of the "
        "patient's symptom text. You MUST translate this medical term into the language specified above.\n"
        "  \"severity\": MUST be exactly one of these English words (do not translate): "
        "Low | Medium | High | Urgent\n"
        "  \"recommended_actions\": list of 3-5 actionable clinical recommendations, "
        "written in the language specified above\n"
        "  \"confidence_score\": integer 0-100\n"
        "CRITICAL: \"diagnosis\" and all items in \"recommended_actions\" MUST be written in "
        "the language specified above. \"severity\" MUST stay as one English word.\n"
        "Return only the JSON object, no extra text."
    )


def _parse_response(raw: str) -> dict:
    match = re.search(r'\{.*\}', raw, re.DOTALL)
    if match:
        try:
            data = json.loads(match.group())
            return {
                "diagnosis": data.get("diagnosis", "Unknown"),
                "severity": data.get("severity", "Low"),
                "recommended_actions": data.get("recommended_actions", []),
                "confidence_score": int(data.get("confidence_score", 70)),
            }
        except (json.JSONDecodeError, ValueError):
            pass
    raise ValueError(f"Could not parse model response as JSON: {raw[:200]}")


def analyze_image_and_text(
    image_path: str | None,
    text_description: str,
    language: str = "en",
    region: str = "",
) -> dict:
    """
    Run analysis via AMD Cloud backend.
    Raises RuntimeError if the backend is unreachable.
    Raises ValueError if the model response cannot be parsed.

    Returns dict with keys: diagnosis, severity, recommended_actions,
    confidence_score, _metrics (latency_ms, total_tokens, tokens_per_sec).
    """
    lang = language.lower()
    prompt = _build_prompt(image_path, text_description, lang, region=region)
    raw, metrics = generate_response(prompt, image_path=image_path)
    result = _parse_response(raw)
    result["_metrics"] = metrics
    return result