Alhdrawi commited on
Commit
b570faf
·
verified ·
1 Parent(s): a700b5e

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -0
app.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ app.py
2
+
3
+ Gradio Hugging Face Space connected to Google Gemini (via google-genai)
4
+
5
+ - Put your Gemini API key into Hugging Face Space secrets with name: GEMINI_API_KEY
6
+
7
+ - Add requirements.txt with: gradio\ngoogle-genai
8
+
9
+ import os import io from google import genai from google.genai import types import gradio as gr
10
+
11
+ Initialize client using secret from HF environment
12
+
13
+ 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
14
+
15
+ Fixed short reply for text-only chats
16
+
17
+ TEXT_ONLY_REPLY = "أنا R-RAY AI تم تدريبي على قواعد بيانات طبية ضخمة. كيف يمكنني مساعدتك اليوم؟"
18
+
19
+ Strict radiology-report instruction (Arabic). The model MUST follow this and reply only with a
20
+
21
+ structured medical radiology report. Keep it concise, professional, and in Arabic. Do not add
22
+
23
+ extra commentary, safety disclaimers, or step-by-step reasoning in the response.
24
+
25
+ RADIology_PROMPT_TEMPLATE = '''أنت "R-RAY AI" — نموذج متخصص في تقارير الأشعة، تدربت على قواعد بيانات طبية ضخمة. تعليمات صارمة:
26
+
27
+ 1. عند استلام صور شعاعية (واحدة أو أكثر) — أجب فقط بتقرير طبي احترافي بصيغة تقارير الأشعة المستعملة سريريًا.
28
+
29
+
30
+ 2. لا تضف جمل ترويجية أو اعتذارات أو نص خارج إطار التقرير.
31
+
32
+
33
+ 3. إخراج التقرير يجب أن يحتوي على الأقسام التالية بالترتيب: عنوان الدراسة، تاريخ الاستلام (التاريخ اليومي تلقائيًا)، رقم المريض (إن وُرد)، التاريخ السريري/شكوى المريض (من نص المستخدم إن وُجد)، التقنية (نوع الصور: X-ray, CT, MRI + الإطارات/القطاعات المرفقة)، وصف تفصيلي للنتائج (ملاحظات عامة ومقارنة إن وُجدت معلومات سابقة)، خاتمة/تقرير تشخيصي موجز مع توصية مفيدة واحدة على الأكثر (مثل: متابعة، توصية بإجراء تصوير مقطعي/تصوير رنين، أو استشارة اختصاصي).
34
+
35
+
36
+ 4. إذا كان هناك أكثر من صورة — اذكر كل صورة مرقمة ووصف كل واحدة تحت قسم "الصور" ثم ادمج النتائج في قسم "النتائج".
37
+
38
+
39
+ 5. اللغة: العربية الفصحى طبية. الطول: تقرير كامل ومحترف (لا تقل عن 6 جمل في الوصف ما لم تكن الصور طبيعية تمامًا).
40
+
41
+
42
+
43
+ البيانات المرسلة: {clinical_text}
44
+
45
+ الصور المرسلة: {image_list}
46
+
47
+ أعد فقط التقرير الطبي بالصيغة المطلوبة. انتهى. '''
48
+
49
+ def make_parts_from_images(image_files): parts = [] for idx, img in enumerate(image_files, start=1): # img is a tempfile-like object from Gradio; read bytes img_bytes = img.read() # prefer from_bytes (supported in google-genai). fallback to from_image if exists. try: part = types.Part.from_bytes(img_bytes) except Exception: try: part = types.Part.from_image(img_bytes) except Exception: # if both fail, embed base64 text as a last resort 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
50
+
51
+ def analyze(images, clinical_text): clinical_text = (clinical_text or "").strip() images = images or []
52
+
53
+ # If no images: provide the fixed text-only reply
54
+ if len(images) == 0:
55
+ # If the user sent text only, return the strict assistant opening line
56
+ return TEXT_ONLY_REPLY
57
+
58
+ # Build list of image names for prompt
59
+ image_names = []
60
+ for i, f in enumerate(images, start=1):
61
+ name = getattr(f, "name", None) or f"image_{i}"
62
+ image_names.append(name)
63
+ image_list_text = ", ".join(image_names)
64
+
65
+ # Prepare prompt (strict)
66
+ prompt_text = RADIology_PROMPT_TEMPLATE.format(
67
+ clinical_text=clinical_text if clinical_text else "(لا توجد معلومات سريرية إضافية)",
68
+ image_list=image_list_text,
69
+ )
70
+
71
+ # Build content parts: first the images, then the instruction as text part
72
+ parts = make_parts_from_images(images)
73
+ parts.append(types.Part.from_text(prompt_text))
74
+
75
+ contents = [
76
+ types.Content(
77
+ role="user",
78
+ parts=parts,
79
+ )
80
+ ]
81
+
82
+ # Call Gemini (synchronous)
83
+ try:
84
+ response = CLIENT.models.generate_content(
85
+ model=MODEL,
86
+ contents=contents,
87
+ config=types.GenerateContentConfig(
88
+ thinking_config=types.ThinkingConfig(thinking_budget=-1),
89
+ ),
90
+ )
91
+ # return text output
92
+ return response.text
93
+ except Exception as e:
94
+ return f"خطأ أثناء الاتصال بنموذج Gemini: {e}"
95
+
96
+ Build Gradio UI
97
+
98
+ with gr.Blocks() as demo: gr.Markdown("# R-RAY AI — تقارير الأشعة\nارفع صور شعاعية (X-ray, CT, MRI) ويمكنك أيضًا ارفاق ملاحظات سريرية قصيرة.")
99
+
100
+ with gr.Row():
101
+ image_input = gr.Files(label="تحميل صور (يمكن رفع أكثر من صورة)", file_count="multiple", type="file")
102
+ clinical_input = gr.Textbox(label="معلومات سريرية / تاريخ المريض (اختياري)", lines=4)
103
+
104
+ output = gr.Textbox(label="تقرير الأشعة (الناتج)", lines=20)
105
+
106
+ btn = gr.Button("تحليل وإصدار التقرير")
107
+ btn.click(fn=analyze, inputs=[image_input, clinical_input], outputs=[output])
108
+
109
+ gr.Markdown("**ملاحظة:** هذا النموذج للاختبار/التطوير فقط ولا يغني عن استشارة طبية حقيقية.")
110
+
111
+ if name == "main": demo.launch(server_name="0.0.0.0", server_port=int(os.environ.get("PORT", 7860)))
112
+