Spaces:
Build error
Build error
Update app.py
Browse files
app.py
CHANGED
|
@@ -18,8 +18,8 @@ client = Groq(
|
|
| 18 |
# Language translations
|
| 19 |
translations = {
|
| 20 |
"en": {
|
| 21 |
-
"app_title": "Bird Species Identification for Researchers",
|
| 22 |
-
"app_description": "Upload
|
| 23 |
"upload_label": "Upload Bird Image",
|
| 24 |
"identify_button": "Identify Bird",
|
| 25 |
"predictions_label": "Top 5 Predictions",
|
|
@@ -33,11 +33,12 @@ translations = {
|
|
| 33 |
"question_title": "Question:",
|
| 34 |
"answer_title": "Answer:",
|
| 35 |
"habitat_map_title": "Natural Habitat Map for",
|
| 36 |
-
"detailed_info_title": "Detailed Information"
|
|
|
|
| 37 |
},
|
| 38 |
"sw": {
|
| 39 |
-
"app_title": "
|
| 40 |
-
"app_description": "Pakia picha ili kutambua spishi
|
| 41 |
"upload_label": "Pakia Picha ya Ndege",
|
| 42 |
"identify_button": "Tambua Ndege",
|
| 43 |
"predictions_label": "Utabiri Bora 5",
|
|
@@ -51,7 +52,8 @@ translations = {
|
|
| 51 |
"question_title": "Swali:",
|
| 52 |
"answer_title": "Jibu:",
|
| 53 |
"habitat_map_title": "Ramani ya Makazi Asilia ya",
|
| 54 |
-
"detailed_info_title": "Taarifa za Kina"
|
|
|
|
| 55 |
}
|
| 56 |
}
|
| 57 |
|
|
@@ -375,156 +377,149 @@ def follow_up_question(question, bird_name, language="en"):
|
|
| 375 |
error_msg = "Hitilafu katika kupata taarifa" if language == "sw" else "Error fetching information"
|
| 376 |
return f"{error_msg}: {str(e)}"
|
| 377 |
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 381 |
|
| 382 |
-
|
| 383 |
-
|
| 384 |
|
| 385 |
-
|
|
|
|
| 386 |
|
| 387 |
-
|
| 388 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 389 |
### {t['question_title']}
|
| 390 |
{question}
|
| 391 |
### {t['answer_title']}
|
| 392 |
{answer}
|
| 393 |
---
|
| 394 |
"""
|
| 395 |
-
|
| 396 |
-
|
| 397 |
-
|
| 398 |
-
# Create the Gradio interface
|
| 399 |
-
def create_interface(language="en"):
|
| 400 |
-
t = translations[language]
|
| 401 |
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
choices=["English", "Kiswahili"],
|
| 410 |
-
label="Language / Lugha",
|
| 411 |
-
value="English" if language == "en" else "Kiswahili"
|
| 412 |
-
)
|
| 413 |
-
|
| 414 |
-
gr.Markdown(f"{t['app_description']}")
|
| 415 |
-
|
| 416 |
-
# Store the current bird and language for context
|
| 417 |
-
current_bird = gr.State("")
|
| 418 |
-
current_lang = gr.State(language)
|
| 419 |
-
|
| 420 |
-
# Main identification section
|
| 421 |
-
with gr.Row():
|
| 422 |
-
with gr.Column(scale=1):
|
| 423 |
-
input_image = gr.Image(type="pil", label=t['upload_label'])
|
| 424 |
-
submit_btn = gr.Button(t['identify_button'], variant="primary")
|
| 425 |
-
|
| 426 |
-
with gr.Column(scale=2):
|
| 427 |
-
prediction_output = gr.Label(label=t['predictions_label'], num_top_classes=5)
|
| 428 |
-
bird_info_output = gr.HTML(label=t['bird_info_label'])
|
| 429 |
-
|
| 430 |
-
# Clear divider
|
| 431 |
-
gr.Markdown("---")
|
| 432 |
-
|
| 433 |
-
# Follow-up question section with improved UI
|
| 434 |
-
gr.Markdown(f"## {t['research_questions']}")
|
| 435 |
-
|
| 436 |
-
conversation_history = gr.Markdown("")
|
| 437 |
-
|
| 438 |
-
with gr.Row():
|
| 439 |
-
follow_up_input = gr.Textbox(
|
| 440 |
-
label=t['question_label'],
|
| 441 |
-
placeholder=t['question_placeholder'],
|
| 442 |
-
lines=2
|
| 443 |
-
)
|
| 444 |
-
|
| 445 |
-
with gr.Row():
|
| 446 |
-
follow_up_btn = gr.Button(t['submit_question'], variant="primary")
|
| 447 |
-
clear_btn = gr.Button(t['clear_conversation'])
|
| 448 |
-
|
| 449 |
-
# Set up event handlers
|
| 450 |
-
def process_image(img, lang):
|
| 451 |
-
if img is None:
|
| 452 |
-
return None, translations[lang]['upload_prompt'], "", ""
|
| 453 |
-
|
| 454 |
-
try:
|
| 455 |
-
pred_results, info, clean_bird_name = predict_and_get_info(img, lang)
|
| 456 |
-
return pred_results, info, clean_bird_name, ""
|
| 457 |
-
except Exception as e:
|
| 458 |
-
error_msg = "Hitilafu katika kuchakata picha" if lang == "sw" else "Error processing image"
|
| 459 |
-
return None, f"{error_msg}: {str(e)}", "", ""
|
| 460 |
-
|
| 461 |
-
def clear_conversation_history():
|
| 462 |
-
return ""
|
| 463 |
-
|
| 464 |
-
def switch_language(choice):
|
| 465 |
-
new_lang = "sw" if choice == "Kiswahili" else "en"
|
| 466 |
-
return new_lang
|
| 467 |
-
|
| 468 |
-
# Connect language selector to recreate the interface
|
| 469 |
-
language_selector.change(
|
| 470 |
-
switch_language,
|
| 471 |
-
inputs=[language_selector],
|
| 472 |
-
outputs=[current_lang]
|
| 473 |
-
).then(
|
| 474 |
-
lambda lang: gr.Blocks.update(visible=False),
|
| 475 |
-
inputs=[current_lang],
|
| 476 |
-
outputs=[app]
|
| 477 |
-
).then(
|
| 478 |
-
lambda: None,
|
| 479 |
-
None,
|
| 480 |
-
None,
|
| 481 |
-
_js=f"""() => {{
|
| 482 |
-
// Reload the page with the new language parameter
|
| 483 |
-
const url = new URL(window.location.href);
|
| 484 |
-
const lang = document.querySelector('input[name="language-selector"]:checked').value;
|
| 485 |
-
url.searchParams.set('language', lang === 'Kiswahili' ? 'sw' : 'en');
|
| 486 |
-
window.location.href = url.toString();
|
| 487 |
-
}}"""
|
| 488 |
-
)
|
| 489 |
-
|
| 490 |
-
submit_btn.click(
|
| 491 |
-
process_image,
|
| 492 |
-
inputs=[input_image, current_lang],
|
| 493 |
-
outputs=[prediction_output, bird_info_output, current_bird, conversation_history]
|
| 494 |
-
)
|
| 495 |
-
|
| 496 |
-
follow_up_btn.click(
|
| 497 |
-
update_conversation,
|
| 498 |
-
inputs=[follow_up_input, current_bird, conversation_history, current_lang],
|
| 499 |
-
outputs=[conversation_history]
|
| 500 |
-
).then(
|
| 501 |
-
lambda: "",
|
| 502 |
-
outputs=follow_up_input
|
| 503 |
-
)
|
| 504 |
|
| 505 |
-
|
| 506 |
-
|
| 507 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 508 |
)
|
| 509 |
-
|
| 510 |
-
return app
|
| 511 |
-
|
| 512 |
-
# Get language from URL parameter or default to English
|
| 513 |
-
def launch_app():
|
| 514 |
-
import sys
|
| 515 |
-
|
| 516 |
-
# Check if running in Gradio's development environment
|
| 517 |
-
if len(sys.argv) > 1 and sys.argv[1] == "run":
|
| 518 |
-
# Default to English when running locally
|
| 519 |
-
language = "en"
|
| 520 |
-
else:
|
| 521 |
-
# Get language from URL parameter
|
| 522 |
-
import os
|
| 523 |
-
language_param = os.environ.get("GRADIO_LANGUAGE", "en")
|
| 524 |
-
language = language_param if language_param in ["en", "sw"] else "en"
|
| 525 |
|
| 526 |
-
|
| 527 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 528 |
|
| 529 |
-
|
| 530 |
-
|
|
|
|
| 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",
|
|
|
|
| 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",
|
|
|
|
| 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 |
|
|
|
|
| 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 |
"""
|
| 457 |
+
updated_history = new_exchange + history
|
| 458 |
+
return updated_history
|
|
|
|
|
|
|
|
|
|
|
|
|
| 459 |
|
| 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: "",
|
| 516 |
+
outputs=follow_up_input
|
| 517 |
+
)
|
| 518 |
+
|
| 519 |
+
clear_btn.click(
|
| 520 |
+
clear_conversation_history,
|
| 521 |
+
outputs=[conversation_history]
|
| 522 |
+
)
|
| 523 |
|
| 524 |
+
# Launch the app
|
| 525 |
+
app.launch(share=True)
|