File size: 5,219 Bytes
e929776
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b570faf
 
52d7042
e929776
 
 
 
52d7042
e929776
52d7042
b570faf
e929776
 
b570faf
 
 
e929776
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b570faf
 
e929776
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52d7042
e929776
 
 
 
 
 
 
 
 
 
 
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
# app.py
# Gradio Hugging Face Space connected to Google Gemini (via google-genai)
# - Put your Gemini API key into Hugging Face Space secrets with name: GEMINI_API_KEY
# - Add requirements.txt with: gradio\ngoogle-genai

import os
import io
from google import genai
from google.genai import types
import gradio as gr

# Initialize client using secret from HF environment
CLIENT = genai.Client(api_key=os.environ.get("GEMINI_API_KEY"))
MODEL = "gemini-2.5-flash"  # or change to a model available in your project/region

# Fixed short reply for text-only chats
TEXT_ONLY_REPLY = "أنا R-RAY AI تم تدريبي على قواعد بيانات طبية ضخمة. كيف يمكنني مساعدتك اليوم؟"

# Strict radiology-report instruction (Arabic)
RADIology_PROMPT_TEMPLATE = '''أنت "R-RAY AI" — نموذج متخصص في تقارير الأشعة، تدربت على قواعد بيانات طبية ضخمة.
تعليمات صارمة:
1) عند استلام صور شعاعية (واحدة أو أكثر) — أجب **فقط** بتقرير طبي احترافي بصيغة تقارير الأشعة المستعملة سريريًا.
2) لا تضف جمل ترويجية أو اعتذارات أو نص خارج إطار التقرير.
3) إخراج التقرير يجب أن يحتوي على الأقسام التالية بالترتيب: عنوان الدراسة، تاريخ الاستلام (التاريخ اليومي تلقائيًا)، رقم المريض (إن وُرد)، التاريخ السريري/شكوى المريض (من نص المستخدم إن وُجد)، التقنية (نوع الصور: X-ray, CT, MRI + الإطارات/القطاعات المرفقة)، وصف تفصيلي للنتائج، خاتمة/تقرير تشخيصي موجز مع توصية واحدة على الأكثر.
4) إذا كان هناك أكثر من صورة — اذكر كل صورة مرقمة ووصف كل واحدة تحت قسم "الصور" ثم ادمج النتائج في قسم "النتائج".
5) اللغة: العربية الفصحى طبية. الطول: تقرير كامل ومحترف (لا يقل عن 6 جمل في الوصف ما لم تكن الصور طبيعية تمامًا).

البيانات المرسلة:
{clinical_text}

الصور المرسلة: {image_list}

أعد فقط التقرير الطبي بالصيغة المطلوبة. انتهى.
'''


def make_parts_from_images(image_files):
    parts = []
    for idx, img in enumerate(image_files, start=1):
        img_bytes = img.read()
        try:
            part = types.Part.from_bytes(img_bytes)
        except Exception:
            try:
                part = types.Part.from_image(img_bytes)
            except Exception:
                import base64
                b64 = base64.b64encode(img_bytes).decode('utf-8')
                part = types.Part.from_text(f"[BASE64_IMAGE_{idx}] {b64}")
        parts.append(part)
    return parts


def analyze(images, clinical_text):
    clinical_text = (clinical_text or "").strip()
    images = images or []

    if len(images) == 0:
        return TEXT_ONLY_REPLY

    image_names = []
    for i, f in enumerate(images, start=1):
        name = getattr(f, "name", None) or f"image_{i}"
        image_names.append(name)
    image_list_text = ", ".join(image_names)

    prompt_text = RADIology_PROMPT_TEMPLATE.format(
        clinical_text=clinical_text if clinical_text else "(لا توجد معلومات سريرية إضافية)",
        image_list=image_list_text,
    )

    parts = make_parts_from_images(images)
    parts.append(types.Part.from_text(prompt_text))

    contents = [
        types.Content(
            role="user",
            parts=parts,
        )
    ]

    try:
        response = CLIENT.models.generate_content(
            model=MODEL,
            contents=contents,
            config=types.GenerateContentConfig(
                thinking_config=types.ThinkingConfig(thinking_budget=-1),
            ),
        )
        return response.text
    except Exception as e:
        return f"خطأ أثناء الاتصال بنموذج Gemini: {e}"


with gr.Blocks() as demo:
    gr.Markdown("# R-RAY AI — تقارير الأشعة\nارفع صور شعاعية (X-ray, CT, MRI) ويمكنك أيضًا ارفاق ملاحظات سريرية قصيرة.")

    with gr.Row():
        image_input = gr.File(label="تحميل صور (يمكن رفع أكثر من صورة)", file_types=[".png", ".jpg", ".jpeg", ".dcm"], file_types_description="Images", type="binary", file_count="multiple")
        clinical_input = gr.Textbox(label="معلومات سريرية / تاريخ المريض (اختياري)", lines=4)

    output = gr.Textbox(label="تقرير الأشعة (الناتج)", lines=20)

    btn = gr.Button("تحليل وإصدار التقرير")
    btn.click(fn=analyze, inputs=[image_input, clinical_input], outputs=[output])

    gr.Markdown("**ملاحظة:** هذا النموذج للاختبار/التطوير فقط ولا يغني عن استشارة طبية حقيقية.")

if __name__ == "__main__":
    demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))