Jacksonnavigator7 commited on
Commit
26ea387
·
verified ·
1 Parent(s): 1246a0b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +158 -39
app.py CHANGED
@@ -15,6 +15,48 @@ client = Groq(
15
  api_key=os.environ.get("GROQ_API_KEY"),
16
  )
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  def clean_bird_name(name):
19
  """Clean bird name by removing numbers and special characters, and fix formatting"""
20
  # Remove numbers and dots at the beginning
@@ -140,14 +182,18 @@ def create_habitat_map(habitat_locations):
140
  map_html = m._repr_html_()
141
  return map_html
142
 
143
- def format_bird_info(raw_info):
144
  """Improve the formatting of bird information"""
145
  # Add proper line breaks between sections and ensure consistent heading levels
146
  formatted = raw_info
147
 
 
 
 
 
148
  # Fix heading levels (make all main sections h3)
149
- formatted = re.sub(r'#+\s+NOT TYPICALLY FOUND IN TANZANIA',
150
- '<div class="alert alert-warning"><strong>⚠️ NOT TYPICALLY FOUND IN TANZANIA</strong></div>',
151
  formatted)
152
 
153
  # Replace markdown headings with HTML headings for better control
@@ -163,10 +209,15 @@ def format_bird_info(raw_info):
163
 
164
  return formatted
165
 
166
- def get_bird_info(bird_name):
167
  """Get detailed information about a bird using Groq API"""
168
  clean_name = clean_bird_name(bird_name)
169
 
 
 
 
 
 
170
  prompt = f"""
171
  Provide detailed information about the {clean_name} bird, including:
172
  1. Physical characteristics and appearance
@@ -177,7 +228,7 @@ def get_bird_info(bird_name):
177
 
178
  If this bird is not commonly found in Tanzania, explicitly flag that this bird is "NOT TYPICALLY FOUND IN TANZANIA" at the beginning of your response and explain why its presence might be unusual.
179
 
180
- Format your response in markdown for better readability.
181
  """
182
 
183
  try:
@@ -192,10 +243,14 @@ def get_bird_info(bird_name):
192
  )
193
  return chat_completion.choices[0].message.content
194
  except Exception as e:
195
- return f"Error fetching information: {str(e)}"
 
196
 
197
- def predict_and_get_info(img):
198
  """Predict bird species and get detailed information"""
 
 
 
199
  # Process the image
200
  img = PILImage.create(img)
201
 
@@ -221,8 +276,8 @@ def predict_and_get_info(img):
221
  habitat_map_html = create_habitat_map(habitat_locations)
222
 
223
  # Get detailed information about the top predicted bird
224
- bird_info = get_bird_info(top_bird)
225
- formatted_info = format_bird_info(bird_info)
226
 
227
  # Create combined info with map at the top and properly formatted information
228
  custom_css = """
@@ -268,13 +323,13 @@ def predict_and_get_info(img):
268
  combined_info = f"""
269
  {custom_css}
270
  <div class="bird-container">
271
- <h2>Natural Habitat Map for {clean_top_bird}</h2>
272
  <div class="map-container">
273
  {habitat_map_html}
274
  </div>
275
 
276
  <div class="info-container">
277
- <h2>Detailed Information</h2>
278
  {formatted_info}
279
  </div>
280
  </div>
@@ -282,10 +337,17 @@ def predict_and_get_info(img):
282
 
283
  return prediction_results, combined_info, clean_top_bird
284
 
285
- def follow_up_question(question, bird_name):
286
  """Allow researchers to ask follow-up questions about the identified bird"""
 
 
287
  if not question.strip() or not bird_name:
288
- return "Please identify a bird first and ask a specific question about it."
 
 
 
 
 
289
 
290
  prompt = f"""
291
  The researcher is asking about the {bird_name} bird: "{question}"
@@ -297,7 +359,7 @@ def follow_up_question(question, bird_name):
297
  Do not start your answer with phrases like "Introduction to the {bird_name}" or similar repetitive headers.
298
  Directly answer the specific question asked.
299
 
300
- Format your response in markdown for better readability.
301
  """
302
 
303
  try:
@@ -312,67 +374,83 @@ def follow_up_question(question, bird_name):
312
  )
313
  return chat_completion.choices[0].message.content
314
  except Exception as e:
315
- return f"Error fetching information: {str(e)}"
 
316
 
317
  # Create the Gradio interface
318
  with gr.Blocks(theme=gr.themes.Soft()) as app:
319
- gr.Markdown("# Bird Species Identification for Researchers")
320
- gr.Markdown("Upload an image to identify bird species and get detailed information relevant to research in Tanzania and climate change studies.")
321
-
322
- # Store the current bird for context
323
  current_bird = gr.State("")
324
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
325
  # Main identification section
326
  with gr.Row():
327
  with gr.Column(scale=1):
328
- input_image = gr.Image(type="pil", label="Upload Bird Image")
329
- submit_btn = gr.Button("Identify Bird", variant="primary")
330
 
331
  with gr.Column(scale=2):
332
- prediction_output = gr.Label(label="Top 5 Predictions", num_top_classes=5)
333
- bird_info_output = gr.HTML(label="Bird Information")
334
 
335
  # Clear divider
336
  gr.Markdown("---")
337
 
338
  # Follow-up question section with improved UI
339
- gr.Markdown("## Research Questions")
340
 
341
  conversation_history = gr.Markdown("")
342
 
343
  with gr.Row():
344
  follow_up_input = gr.Textbox(
345
- label="Ask a question about this bird",
346
- placeholder="Example: How has climate change affected this bird's migration pattern?",
347
  lines=2
348
  )
349
 
350
  with gr.Row():
351
- follow_up_btn = gr.Button("Submit Question", variant="primary")
352
- clear_btn = gr.Button("Clear Conversation")
353
 
354
- # Set up event handlers
355
- def process_image(img):
356
  if img is None:
357
- return None, "Please upload an image", "", ""
358
 
359
  try:
360
- pred_results, info, clean_bird_name = predict_and_get_info(img)
361
  return pred_results, info, clean_bird_name, ""
362
  except Exception as e:
363
- return None, f"Error processing image: {str(e)}", "", ""
 
364
 
365
- def update_conversation(question, bird_name, history):
 
 
366
  if not question.strip():
367
  return history
368
 
369
- answer = follow_up_question(question, bird_name)
370
 
371
  # Format the conversation with clear separation
372
  new_exchange = f"""
373
- ### Question:
374
  {question}
375
- ### Answer:
376
  {answer}
377
  ---
378
  """
@@ -382,15 +460,56 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
382
  def clear_conversation_history():
383
  return ""
384
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
  submit_btn.click(
386
  process_image,
387
- inputs=[input_image],
388
  outputs=[prediction_output, bird_info_output, current_bird, conversation_history]
389
  )
390
 
391
  follow_up_btn.click(
392
  update_conversation,
393
- inputs=[follow_up_input, current_bird, conversation_history],
394
  outputs=[conversation_history]
395
  ).then(
396
  lambda: "",
 
15
  api_key=os.environ.get("GROQ_API_KEY"),
16
  )
17
 
18
+ # Language translations
19
+ translations = {
20
+ "en": {
21
+ "app_title": "Bird Species Explorer: AI-Powered Identification for Researchers",
22
+ "app_description": "🔍 Upload a bird photo to instantly identify species and access comprehensive data on habitats, behaviors, and climate change impacts. A powerful tool for Tanzania-based ornithological research.",
23
+ "upload_label": "Upload Bird Image",
24
+ "identify_button": "Identify Bird",
25
+ "predictions_label": "Top 5 Predictions",
26
+ "bird_info_label": "Bird Information",
27
+ "research_questions": "Research Questions",
28
+ "question_placeholder": "Example: How has climate change affected this bird's migration pattern?",
29
+ "question_label": "Ask a question about this bird",
30
+ "submit_question": "Submit Question",
31
+ "clear_conversation": "Clear Conversation",
32
+ "upload_prompt": "Please upload an image",
33
+ "question_title": "Question:",
34
+ "answer_title": "Answer:",
35
+ "habitat_map_title": "Natural Habitat Map for",
36
+ "detailed_info_title": "Detailed Information",
37
+ "language_label": "Language / Lugha"
38
+ },
39
+ "sw": {
40
+ "app_title": "Mtafiti wa Ndege: Utambuzi wa Kiotomatiki kwa Watafiti",
41
+ "app_description": "🔍 Pakia picha ya ndege ili kutambua spishi mara moja na kupata data kamili kuhusu makazi, tabia, na athari za mabadiliko ya tabianchi. Zana yenye nguvu kwa utafiti wa ndege nchini Tanzania.",
42
+ "upload_label": "Pakia Picha ya Ndege",
43
+ "identify_button": "Tambua Ndege",
44
+ "predictions_label": "Utabiri Bora 5",
45
+ "bird_info_label": "Taarifa za Ndege",
46
+ "research_questions": "Maswali ya Utafiti",
47
+ "question_placeholder": "Mfano: Je, mabadiliko ya tabianchi yameathiri vipi mfumo wa uhamiaji wa ndege huyu?",
48
+ "question_label": "Uliza swali kuhusu ndege huyu",
49
+ "submit_question": "Wasilisha Swali",
50
+ "clear_conversation": "Futa Mazungumzo",
51
+ "upload_prompt": "Tafadhali pakia picha",
52
+ "question_title": "Swali:",
53
+ "answer_title": "Jibu:",
54
+ "habitat_map_title": "Ramani ya Makazi Asilia ya",
55
+ "detailed_info_title": "Taarifa za Kina",
56
+ "language_label": "Language / Lugha"
57
+ }
58
+ }
59
+
60
  def clean_bird_name(name):
61
  """Clean bird name by removing numbers and special characters, and fix formatting"""
62
  # Remove numbers and dots at the beginning
 
182
  map_html = m._repr_html_()
183
  return map_html
184
 
185
+ def format_bird_info(raw_info, language="en"):
186
  """Improve the formatting of bird information"""
187
  # Add proper line breaks between sections and ensure consistent heading levels
188
  formatted = raw_info
189
 
190
+ # Get translation of warning text based on language
191
+ warning_text = "NOT TYPICALLY FOUND IN TANZANIA"
192
+ warning_translation = "HAPATIKANI SANA TANZANIA" if language == "sw" else warning_text
193
+
194
  # Fix heading levels (make all main sections h3)
195
+ formatted = re.sub(r'#+\s+' + warning_text,
196
+ f'<div class="alert alert-warning"><strong>⚠️ {warning_translation}</strong></div>',
197
  formatted)
198
 
199
  # Replace markdown headings with HTML headings for better control
 
209
 
210
  return formatted
211
 
212
+ def get_bird_info(bird_name, language="en"):
213
  """Get detailed information about a bird using Groq API"""
214
  clean_name = clean_bird_name(bird_name)
215
 
216
+ # Adjust language for the prompt
217
+ lang_instruction = ""
218
+ if language == "sw":
219
+ lang_instruction = " Provide your response in Swahili language."
220
+
221
  prompt = f"""
222
  Provide detailed information about the {clean_name} bird, including:
223
  1. Physical characteristics and appearance
 
228
 
229
  If this bird is not commonly found in Tanzania, explicitly flag that this bird is "NOT TYPICALLY FOUND IN TANZANIA" at the beginning of your response and explain why its presence might be unusual.
230
 
231
+ Format your response in markdown for better readability.{lang_instruction}
232
  """
233
 
234
  try:
 
243
  )
244
  return chat_completion.choices[0].message.content
245
  except Exception as e:
246
+ error_msg = "Hitilafu katika kupata taarifa" if language == "sw" else "Error fetching information"
247
+ return f"{error_msg}: {str(e)}"
248
 
249
+ def predict_and_get_info(img, language="en"):
250
  """Predict bird species and get detailed information"""
251
+ # Get translations
252
+ t = translations[language]
253
+
254
  # Process the image
255
  img = PILImage.create(img)
256
 
 
276
  habitat_map_html = create_habitat_map(habitat_locations)
277
 
278
  # Get detailed information about the top predicted bird
279
+ bird_info = get_bird_info(top_bird, language)
280
+ formatted_info = format_bird_info(bird_info, language)
281
 
282
  # Create combined info with map at the top and properly formatted information
283
  custom_css = """
 
323
  combined_info = f"""
324
  {custom_css}
325
  <div class="bird-container">
326
+ <h2>{t['habitat_map_title']} {clean_top_bird}</h2>
327
  <div class="map-container">
328
  {habitat_map_html}
329
  </div>
330
 
331
  <div class="info-container">
332
+ <h2>{t['detailed_info_title']}</h2>
333
  {formatted_info}
334
  </div>
335
  </div>
 
337
 
338
  return prediction_results, combined_info, clean_top_bird
339
 
340
+ def follow_up_question(question, bird_name, language="en"):
341
  """Allow researchers to ask follow-up questions about the identified bird"""
342
+ t = translations[language]
343
+
344
  if not question.strip() or not bird_name:
345
+ return "Please identify a bird first and ask a specific question about it." if language == "en" else "Tafadhali tambua ndege kwanza na uulize swali maalum kuhusu ndege huyo."
346
+
347
+ # Adjust language for the prompt
348
+ lang_instruction = ""
349
+ if language == "sw":
350
+ lang_instruction = " Provide your response in Swahili language."
351
 
352
  prompt = f"""
353
  The researcher is asking about the {bird_name} bird: "{question}"
 
359
  Do not start your answer with phrases like "Introduction to the {bird_name}" or similar repetitive headers.
360
  Directly answer the specific question asked.
361
 
362
+ Format your response in markdown for better readability.{lang_instruction}
363
  """
364
 
365
  try:
 
374
  )
375
  return chat_completion.choices[0].message.content
376
  except Exception as e:
377
+ error_msg = "Hitilafu katika kupata taarifa" if language == "sw" else "Error fetching information"
378
+ return f"{error_msg}: {str(e)}"
379
 
380
  # Create the Gradio interface
381
  with gr.Blocks(theme=gr.themes.Soft()) as app:
382
+ # Current language and bird state
383
+ current_lang = gr.State("en")
 
 
384
  current_bird = gr.State("")
385
 
386
+ # Header with language switcher
387
+ with gr.Row():
388
+ with gr.Column(scale=3):
389
+ title_md = gr.Markdown(f"# {translations['en']['app_title']}")
390
+ with gr.Column(scale=1):
391
+ language_selector = gr.Radio(
392
+ choices=["English", "Kiswahili"],
393
+ label=translations['en']['language_label'],
394
+ value="English"
395
+ )
396
+
397
+ # App description
398
+ description_md = gr.Markdown(f"{translations['en']['app_description']}")
399
+
400
  # Main identification section
401
  with gr.Row():
402
  with gr.Column(scale=1):
403
+ input_image = gr.Image(type="pil", label=translations['en']['upload_label'])
404
+ submit_btn = gr.Button(translations['en']['identify_button'], variant="primary")
405
 
406
  with gr.Column(scale=2):
407
+ prediction_output = gr.Label(label=translations['en']['predictions_label'], num_top_classes=5)
408
+ bird_info_output = gr.HTML(label=translations['en']['bird_info_label'])
409
 
410
  # Clear divider
411
  gr.Markdown("---")
412
 
413
  # Follow-up question section with improved UI
414
+ questions_header = gr.Markdown(f"## {translations['en']['research_questions']}")
415
 
416
  conversation_history = gr.Markdown("")
417
 
418
  with gr.Row():
419
  follow_up_input = gr.Textbox(
420
+ label=translations['en']['question_label'],
421
+ placeholder=translations['en']['question_placeholder'],
422
  lines=2
423
  )
424
 
425
  with gr.Row():
426
+ follow_up_btn = gr.Button(translations['en']['submit_question'], variant="primary")
427
+ clear_btn = gr.Button(translations['en']['clear_conversation'])
428
 
429
+ # Functions for event handlers
430
+ def process_image(img, lang):
431
  if img is None:
432
+ return None, translations[lang]['upload_prompt'], "", ""
433
 
434
  try:
435
+ pred_results, info, clean_bird_name = predict_and_get_info(img, lang)
436
  return pred_results, info, clean_bird_name, ""
437
  except Exception as e:
438
+ error_msg = "Hitilafu katika kuchakata picha" if lang == "sw" else "Error processing image"
439
+ return None, f"{error_msg}: {str(e)}", "", ""
440
 
441
+ def update_conversation(question, bird_name, history, lang):
442
+ t = translations[lang]
443
+
444
  if not question.strip():
445
  return history
446
 
447
+ answer = follow_up_question(question, bird_name, lang)
448
 
449
  # Format the conversation with clear separation
450
  new_exchange = f"""
451
+ ### {t['question_title']}
452
  {question}
453
+ ### {t['answer_title']}
454
  {answer}
455
  ---
456
  """
 
460
  def clear_conversation_history():
461
  return ""
462
 
463
+ def update_language(choice):
464
+ # Convert selection to language code
465
+ lang = "sw" if choice == "Kiswahili" else "en"
466
+ t = translations[lang]
467
+
468
+ # Return updated UI components based on selected language
469
+ return (
470
+ lang,
471
+ f"# {t['app_title']}",
472
+ f"{t['app_description']}",
473
+ t['upload_label'],
474
+ t['identify_button'],
475
+ t['predictions_label'],
476
+ t['bird_info_label'],
477
+ f"## {t['research_questions']}",
478
+ t['question_label'],
479
+ t['question_placeholder'],
480
+ t['submit_question'],
481
+ t['clear_conversation']
482
+ )
483
+
484
+ # Set up event handlers
485
+ language_selector.change(
486
+ update_language,
487
+ inputs=[language_selector],
488
+ outputs=[
489
+ current_lang,
490
+ title_md,
491
+ description_md,
492
+ input_image,
493
+ submit_btn,
494
+ prediction_output,
495
+ bird_info_output,
496
+ questions_header,
497
+ follow_up_input,
498
+ follow_up_input,
499
+ follow_up_btn,
500
+ clear_btn
501
+ ]
502
+ )
503
+
504
  submit_btn.click(
505
  process_image,
506
+ inputs=[input_image, current_lang],
507
  outputs=[prediction_output, bird_info_output, current_bird, conversation_history]
508
  )
509
 
510
  follow_up_btn.click(
511
  update_conversation,
512
+ inputs=[follow_up_input, current_bird, conversation_history, current_lang],
513
  outputs=[conversation_history]
514
  ).then(
515
  lambda: "",