walaa2022 commited on
Commit
d74489a
Β·
verified Β·
1 Parent(s): c99f33d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +224 -54
app.py CHANGED
@@ -1,7 +1,7 @@
1
  #!/usr/bin/env python3
2
  """
3
  Gemini Vision Pro Medical Image Analysis - Gradio Interface
4
- Lightweight alternative using Google's Gemini Vision Pro API
5
  """
6
 
7
  import gradio as gr
@@ -20,36 +20,127 @@ warnings.filterwarnings("ignore")
20
  GEMINI_MODEL = None
21
  API_KEY = None
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  def setup_gemini(api_key: str = None):
24
  """Setup Gemini Vision Pro with API key"""
25
  global GEMINI_MODEL, API_KEY
26
 
27
- # Try to get API key from environment or parameter
28
- if api_key:
29
- API_KEY = api_key
30
  else:
31
- API_KEY = os.getenv('GOOGLE_API_KEY') or os.getenv('GEMINI_API_KEY')
32
 
33
  if not API_KEY:
34
- return False, "❌ No API key provided. Please set GOOGLE_API_KEY environment variable or enter it in the interface."
35
 
36
  try:
37
  # Configure the API
38
  genai.configure(api_key=API_KEY)
39
 
40
- # Initialize the model
41
- GEMINI_MODEL = genai.GenerativeModel('gemini-1.5-pro')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
- # Test the connection
44
- test_response = GEMINI_MODEL.generate_content("Hello, can you help with medical image analysis?")
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  if test_response and test_response.text:
47
  return True, "βœ… Gemini Vision Pro connected successfully!"
48
  else:
49
- return False, "❌ Failed to connect to Gemini API"
50
 
51
  except Exception as e:
52
- return False, f"❌ Gemini setup failed: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
  def create_medical_prompt(clinical_data: Dict, analysis_type: str, focus_areas: str) -> str:
55
  """Create optimized medical analysis prompt for Gemini"""
@@ -59,10 +150,11 @@ def create_medical_prompt(clinical_data: Dict, analysis_type: str, focus_areas:
59
  **ANALYSIS INSTRUCTIONS:**
60
  Analyze this medical image systematically and professionally:
61
  - Use clear medical terminology with explanations for complex terms
62
- - Structure your response with clear sections and headers
63
  - Be thorough but concise
64
  - Always mention limitations and emphasize the need for professional medical consultation
65
  - Focus on observable findings rather than definitive diagnoses
 
66
  """
67
 
68
  # Add clinical context if provided
@@ -185,11 +277,11 @@ def analyze_medical_image_gemini(
185
 
186
  # Prepare clinical data
187
  clinical_data = {
188
- "age": age.strip(),
189
- "gender": gender,
190
- "symptoms": symptoms.strip(),
191
- "history": history.strip(),
192
- "medications": medications.strip()
193
  }
194
 
195
  # Create prompt
@@ -197,11 +289,22 @@ def analyze_medical_image_gemini(
197
 
198
  progress(0.5, desc="Analyzing image with Gemini...")
199
 
 
 
 
 
 
 
 
 
200
  # Generate analysis using Gemini Vision Pro
201
- response = GEMINI_MODEL.generate_content([prompt, image])
 
 
 
202
 
203
  if not response or not response.text:
204
- return "❌ No response received from Gemini API", "", "❌ Analysis failed"
205
 
206
  progress(0.9, desc="Preparing results...")
207
 
@@ -211,7 +314,7 @@ def analyze_medical_image_gemini(
211
  "model": "Google Gemini-1.5-Pro Vision",
212
  "analysis_type": analysis_type,
213
  "clinical_data": clinical_data,
214
- "focus_areas": focus_areas,
215
  "analysis": response.text
216
  }
217
 
@@ -223,12 +326,22 @@ def analyze_medical_image_gemini(
223
 
224
  except Exception as e:
225
  error_msg = f"❌ Analysis failed: {str(e)}"
226
- if "API_KEY" in str(e):
227
- error_msg += "\n\nπŸ’‘ Tip: Make sure your Google API key is valid and has access to Gemini API"
228
- elif "quota" in str(e).lower():
229
- error_msg += "\n\nπŸ’‘ Tip: You may have exceeded your API quota. Check your Google Cloud Console"
230
- elif "safety" in str(e).lower():
231
- error_msg += "\n\nπŸ’‘ Tip: The image may have been blocked by safety filters. Try a different medical image"
 
 
 
 
 
 
 
 
 
 
232
 
233
  return error_msg, "", error_msg
234
 
@@ -260,6 +373,13 @@ def create_interface():
260
  color: #d93025;
261
  font-weight: 500;
262
  }
 
 
 
 
 
 
 
263
  """
264
 
265
  with gr.Blocks(css=css, theme=gr.themes.Soft(), title="Gemini Medical AI") as interface:
@@ -273,23 +393,45 @@ def create_interface():
273
  </div>
274
  """)
275
 
 
 
 
276
  # API Configuration Section
277
- with gr.Accordion("πŸ”‘ API Configuration", open=True):
278
- gr.Markdown("""
279
- ### Google Gemini API Setup
280
- You need a Google API key to use Gemini Vision Pro. Get one from [Google AI Studio](https://makersuite.google.com/app/apikey).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
281
  """)
282
 
283
  api_key_input = gr.Textbox(
284
- label="Google API Key",
285
  type="password",
286
- placeholder="Enter your Google API key here...",
287
- info="Your API key is not stored and only used for this session"
 
288
  )
289
 
290
  status_display = gr.Textbox(
291
  label="Connection Status",
292
- value="⏳ Enter API key to connect",
293
  interactive=False
294
  )
295
 
@@ -382,6 +524,30 @@ def create_interface():
382
  download_content = gr.Textbox(visible=False)
383
 
384
  # Information sections
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
  with gr.Accordion("πŸ’‘ About Gemini Vision Pro", open=False):
386
  gr.Markdown("""
387
  ### πŸš€ **Advantages of Gemini Vision Pro:**
@@ -405,21 +571,6 @@ def create_interface():
405
  - Check [Google AI Pricing](https://ai.google.dev/pricing) for current rates
406
  """)
407
 
408
- with gr.Accordion("πŸ“ Tips for Better Results", open=False):
409
- gr.Markdown("""
410
- ### 🎯 **Optimization Tips:**
411
- - **Provide clinical context**: Age, symptoms, and history significantly improve accuracy
412
- - **Use specific focus areas**: "cardiac silhouette, pulmonary vessels" vs just "chest"
413
- - **High-quality images**: Clear, well-lit, properly oriented images work best
414
- - **Appropriate image size**: Gemini works well with various image sizes
415
- - **Choose right analysis type**: Comprehensive for complex cases, Quick for screening
416
-
417
- ### πŸ” **API Key Security:**
418
- - Your API key is only used for this session and not stored
419
- - Consider using environment variables for production deployments
420
- - Monitor your API usage in Google Cloud Console
421
- """)
422
-
423
  # Footer
424
  gr.HTML("""
425
  <div style="text-align: center; margin-top: 20px; padding: 15px; background-color: #fff3cd; border-radius: 8px;">
@@ -438,12 +589,22 @@ def create_interface():
438
  return gr.File(value=filename, visible=True)
439
  return gr.File(visible=False)
440
 
441
- def test_api_connection(api_key):
442
- if not api_key:
443
- return "⏳ Enter API key to connect"
444
- success, status = setup_gemini(api_key)
445
  return status
446
 
 
 
 
 
 
 
 
 
 
 
447
  # API key testing
448
  api_key_input.change(
449
  fn=test_api_connection,
@@ -469,6 +630,15 @@ def create_interface():
469
 
470
  if __name__ == "__main__":
471
  print("πŸ₯ Initializing Gemini Medical AI Analyzer...")
 
 
 
 
 
 
 
 
 
472
  print("πŸš€ No local model loading required - using Google Gemini Vision Pro API")
473
 
474
  # Create and launch interface
 
1
  #!/usr/bin/env python3
2
  """
3
  Gemini Vision Pro Medical Image Analysis - Gradio Interface
4
+ Fixed version with HuggingFace Secrets support and better error handling
5
  """
6
 
7
  import gradio as gr
 
20
  GEMINI_MODEL = None
21
  API_KEY = None
22
 
23
+ def get_api_key_from_secrets():
24
+ """Try to get API key from HuggingFace secrets or environment variables"""
25
+ # Try multiple possible secret names
26
+ possible_keys = [
27
+ 'GOOGLE_API_KEY',
28
+ 'GEMINI_API_KEY',
29
+ 'GOOGLE_GEMINI_API_KEY',
30
+ 'GOOGLE_AI_API_KEY'
31
+ ]
32
+
33
+ for key_name in possible_keys:
34
+ # First try HuggingFace secrets (if running on HF Spaces)
35
+ try:
36
+ from huggingface_hub import HfFolder
37
+ token = HfFolder.get_token()
38
+ if token:
39
+ # This is a simplified approach - in HF Spaces, secrets are usually available as env vars
40
+ api_key = os.getenv(key_name)
41
+ if api_key:
42
+ return api_key
43
+ except:
44
+ pass
45
+
46
+ # Try regular environment variables
47
+ api_key = os.getenv(key_name)
48
+ if api_key:
49
+ return api_key
50
+
51
+ return None
52
+
53
  def setup_gemini(api_key: str = None):
54
  """Setup Gemini Vision Pro with API key"""
55
  global GEMINI_MODEL, API_KEY
56
 
57
+ # Try to get API key from various sources
58
+ if api_key and api_key.strip():
59
+ API_KEY = api_key.strip()
60
  else:
61
+ API_KEY = get_api_key_from_secrets()
62
 
63
  if not API_KEY:
64
+ return False, "❌ No API key found. Please:\n1. Set GOOGLE_API_KEY in HuggingFace Spaces secrets, or\n2. Enter your API key in the interface below\n\nπŸ”— Get your API key from: https://makersuite.google.com/app/apikey"
65
 
66
  try:
67
  # Configure the API
68
  genai.configure(api_key=API_KEY)
69
 
70
+ # Initialize the model with safety settings
71
+ safety_settings = [
72
+ {
73
+ "category": "HARM_CATEGORY_MEDICAL",
74
+ "threshold": "BLOCK_NONE"
75
+ },
76
+ {
77
+ "category": "HARM_CATEGORY_HARASSMENT",
78
+ "threshold": "BLOCK_ONLY_HIGH"
79
+ },
80
+ {
81
+ "category": "HARM_CATEGORY_HATE_SPEECH",
82
+ "threshold": "BLOCK_ONLY_HIGH"
83
+ },
84
+ {
85
+ "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
86
+ "threshold": "BLOCK_ONLY_HIGH"
87
+ },
88
+ {
89
+ "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
90
+ "threshold": "BLOCK_ONLY_HIGH"
91
+ }
92
+ ]
93
 
94
+ GEMINI_MODEL = genai.GenerativeModel(
95
+ 'gemini-1.5-pro',
96
+ safety_settings=safety_settings
97
+ )
98
+
99
+ # Test the connection with a simple query
100
+ test_response = GEMINI_MODEL.generate_content(
101
+ "Respond with just 'OK' to confirm you can analyze medical images.",
102
+ generation_config=genai.types.GenerationConfig(
103
+ temperature=0.1,
104
+ max_output_tokens=10
105
+ )
106
+ )
107
 
108
  if test_response and test_response.text:
109
  return True, "βœ… Gemini Vision Pro connected successfully!"
110
  else:
111
+ return False, "❌ Failed to get response from Gemini API"
112
 
113
  except Exception as e:
114
+ error_msg = f"❌ Gemini setup failed: {str(e)}"
115
+
116
+ # Provide specific guidance based on error type
117
+ if "429" in str(e) or "quota" in str(e).lower():
118
+ error_msg += "\n\nπŸ’‘ **Quota Exceeded Solutions:**\n"
119
+ error_msg += "β€’ Check your Google Cloud Console billing\n"
120
+ error_msg += "β€’ Verify your API key has sufficient quota\n"
121
+ error_msg += "β€’ Try again in a few minutes (rate limiting)\n"
122
+ error_msg += "β€’ Consider upgrading your Google AI plan\n"
123
+ error_msg += "πŸ”— Check usage: https://console.cloud.google.com/"
124
+
125
+ elif "403" in str(e) or "permission" in str(e).lower():
126
+ error_msg += "\n\nπŸ’‘ **Permission Error Solutions:**\n"
127
+ error_msg += "β€’ Ensure Gemini API is enabled in your project\n"
128
+ error_msg += "β€’ Check if your API key has proper permissions\n"
129
+ error_msg += "β€’ Verify your Google Cloud project settings"
130
+
131
+ elif "401" in str(e) or "unauthorized" in str(e).lower():
132
+ error_msg += "\n\nπŸ’‘ **Authentication Error:**\n"
133
+ error_msg += "β€’ Double-check your API key is correct\n"
134
+ error_msg += "β€’ Ensure no extra spaces in the API key\n"
135
+ error_msg += "β€’ Generate a new API key if needed"
136
+
137
+ elif "safety" in str(e).lower() or "blocked" in str(e).lower():
138
+ error_msg += "\n\nπŸ’‘ **Content Safety Issue:**\n"
139
+ error_msg += "β€’ The image may have triggered safety filters\n"
140
+ error_msg += "β€’ Try a different medical image\n"
141
+ error_msg += "β€’ Ensure the image is clearly medical in nature"
142
+
143
+ return False, error_msg
144
 
145
  def create_medical_prompt(clinical_data: Dict, analysis_type: str, focus_areas: str) -> str:
146
  """Create optimized medical analysis prompt for Gemini"""
 
150
  **ANALYSIS INSTRUCTIONS:**
151
  Analyze this medical image systematically and professionally:
152
  - Use clear medical terminology with explanations for complex terms
153
+ - Structure your response with clear sections and headers
154
  - Be thorough but concise
155
  - Always mention limitations and emphasize the need for professional medical consultation
156
  - Focus on observable findings rather than definitive diagnoses
157
+ - This is for educational and research purposes only
158
  """
159
 
160
  # Add clinical context if provided
 
277
 
278
  # Prepare clinical data
279
  clinical_data = {
280
+ "age": age.strip() if age else "",
281
+ "gender": gender if gender else "",
282
+ "symptoms": symptoms.strip() if symptoms else "",
283
+ "history": history.strip() if history else "",
284
+ "medications": medications.strip() if medications else ""
285
  }
286
 
287
  # Create prompt
 
289
 
290
  progress(0.5, desc="Analyzing image with Gemini...")
291
 
292
+ # Configure generation parameters for better results
293
+ generation_config = genai.types.GenerationConfig(
294
+ temperature=0.3, # Lower temperature for more consistent medical analysis
295
+ max_output_tokens=2048, # Sufficient for detailed analysis
296
+ top_p=0.8,
297
+ top_k=40
298
+ )
299
+
300
  # Generate analysis using Gemini Vision Pro
301
+ response = GEMINI_MODEL.generate_content(
302
+ [prompt, image],
303
+ generation_config=generation_config
304
+ )
305
 
306
  if not response or not response.text:
307
+ return "❌ No response received from Gemini API. The image may have been blocked by safety filters or there was a processing error.", "", "❌ Analysis failed"
308
 
309
  progress(0.9, desc="Preparing results...")
310
 
 
314
  "model": "Google Gemini-1.5-Pro Vision",
315
  "analysis_type": analysis_type,
316
  "clinical_data": clinical_data,
317
+ "focus_areas": focus_areas if focus_areas else "None specified",
318
  "analysis": response.text
319
  }
320
 
 
326
 
327
  except Exception as e:
328
  error_msg = f"❌ Analysis failed: {str(e)}"
329
+
330
+ # Provide specific error guidance
331
+ if "429" in str(e) or "quota" in str(e).lower():
332
+ error_msg += "\n\nπŸ’‘ **Quota Issue:** You've exceeded your API limits. Please:\n"
333
+ error_msg += "β€’ Check your Google Cloud Console billing\n"
334
+ error_msg += "β€’ Wait a few minutes and try again\n"
335
+ error_msg += "β€’ Consider upgrading your plan"
336
+
337
+ elif "safety" in str(e).lower() or "blocked" in str(e).lower():
338
+ error_msg += "\n\nπŸ’‘ **Safety Filter:** The image was blocked. Try:\n"
339
+ error_msg += "β€’ A different medical image\n"
340
+ error_msg += "β€’ Ensuring the image is clearly medical\n"
341
+ error_msg += "β€’ Removing any potentially sensitive content"
342
+
343
+ elif "401" in str(e) or "403" in str(e):
344
+ error_msg += "\n\nπŸ’‘ **Authentication Error:** Check your API key"
345
 
346
  return error_msg, "", error_msg
347
 
 
373
  color: #d93025;
374
  font-weight: 500;
375
  }
376
+ .quota-info {
377
+ background-color: #fff3cd;
378
+ padding: 10px;
379
+ border-radius: 5px;
380
+ margin: 10px 0;
381
+ border-left: 3px solid #ffc107;
382
+ }
383
  """
384
 
385
  with gr.Blocks(css=css, theme=gr.themes.Soft(), title="Gemini Medical AI") as interface:
 
393
  </div>
394
  """)
395
 
396
+ # Check for existing API key on startup
397
+ initial_api_key = get_api_key_from_secrets()
398
+
399
  # API Configuration Section
400
+ with gr.Accordion("πŸ”‘ API Configuration", open=not bool(initial_api_key)):
401
+ if initial_api_key:
402
+ gr.Markdown("""
403
+ ### βœ… API Key Found in Secrets
404
+ An API key was found in the environment/secrets. You can still override it below if needed.
405
+ """)
406
+ else:
407
+ gr.Markdown("""
408
+ ### πŸ” Google Gemini API Setup Required
409
+ You need a Google API key to use Gemini Vision Pro.
410
+
411
+ **For HuggingFace Spaces:** Add your API key as a secret named `GOOGLE_API_KEY`
412
+ **For local use:** Set the `GOOGLE_API_KEY` environment variable or enter it below
413
+
414
+ πŸ”— Get your API key from: [Google AI Studio](https://makersuite.google.com/app/apikey)
415
+ """)
416
+
417
+ gr.HTML("""
418
+ <div class="quota-info">
419
+ <strong>πŸ’° Important:</strong> Make sure your Google API key has sufficient quota and billing is set up.
420
+ The 429 error indicates quota limits have been exceeded.
421
+ </div>
422
  """)
423
 
424
  api_key_input = gr.Textbox(
425
+ label="Google API Key (Optional Override)",
426
  type="password",
427
+ placeholder="Enter your Google API key here to override secrets...",
428
+ info="Leave empty to use API key from secrets/environment",
429
+ value=""
430
  )
431
 
432
  status_display = gr.Textbox(
433
  label="Connection Status",
434
+ value="⏳ Testing connection..." if initial_api_key else "⏳ Enter API key to connect",
435
  interactive=False
436
  )
437
 
 
524
  download_content = gr.Textbox(visible=False)
525
 
526
  # Information sections
527
+ with gr.Accordion("πŸ”§ Troubleshooting Common Issues", open=False):
528
+ gr.Markdown("""
529
+ ### 🚨 **Error 429 - Quota Exceeded:**
530
+ - **Check billing:** Ensure your Google Cloud project has billing enabled
531
+ - **API limits:** You may have hit free tier limits - consider upgrading
532
+ - **Rate limiting:** Wait a few minutes and try again
533
+ - **Multiple keys:** Try generating a new API key
534
+
535
+ ### πŸ” **For HuggingFace Spaces Users:**
536
+ 1. Go to your Space settings
537
+ 2. Add a new secret: `GOOGLE_API_KEY`
538
+ 3. Paste your Google API key as the value
539
+ 4. Restart your Space
540
+
541
+ ### πŸ“Š **Monitor Usage:**
542
+ - [Google AI Studio Usage](https://makersuite.google.com/)
543
+ - [Google Cloud Console](https://console.cloud.google.com/)
544
+
545
+ ### πŸ”„ **If Still Having Issues:**
546
+ - Try a different API key
547
+ - Check if Gemini API is enabled in your project
548
+ - Verify your Google Cloud project settings
549
+ """)
550
+
551
  with gr.Accordion("πŸ’‘ About Gemini Vision Pro", open=False):
552
  gr.Markdown("""
553
  ### πŸš€ **Advantages of Gemini Vision Pro:**
 
571
  - Check [Google AI Pricing](https://ai.google.dev/pricing) for current rates
572
  """)
573
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
574
  # Footer
575
  gr.HTML("""
576
  <div style="text-align: center; margin-top: 20px; padding: 15px; background-color: #fff3cd; border-radius: 8px;">
 
589
  return gr.File(value=filename, visible=True)
590
  return gr.File(visible=False)
591
 
592
+ def test_api_connection(api_key_override):
593
+ # Use override if provided, otherwise use secrets
594
+ test_key = api_key_override if api_key_override.strip() else None
595
+ success, status = setup_gemini(test_key)
596
  return status
597
 
598
+ # Test connection on startup if we have an API key
599
+ if initial_api_key:
600
+ def initial_connection_test():
601
+ return test_api_connection("")
602
+
603
+ interface.load(
604
+ fn=initial_connection_test,
605
+ outputs=[status_display]
606
+ )
607
+
608
  # API key testing
609
  api_key_input.change(
610
  fn=test_api_connection,
 
630
 
631
  if __name__ == "__main__":
632
  print("πŸ₯ Initializing Gemini Medical AI Analyzer...")
633
+ print("πŸ” Checking for API keys in secrets/environment...")
634
+
635
+ # Check for API key
636
+ api_key_found = get_api_key_from_secrets()
637
+ if api_key_found:
638
+ print("βœ… API key found in environment/secrets")
639
+ else:
640
+ print("⚠️ No API key found - user will need to provide one")
641
+
642
  print("πŸš€ No local model loading required - using Google Gemini Vision Pro API")
643
 
644
  # Create and launch interface