Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -136,59 +136,38 @@ def is_likely_bird_image(img):
|
|
| 136 |
# If any error occurs during the check, assume it might be a bird
|
| 137 |
return True
|
| 138 |
|
| 139 |
-
def
|
| 140 |
-
"""Get habitat
|
| 141 |
clean_name = clean_bird_name(bird_name)
|
| 142 |
|
| 143 |
-
# Check cache
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
if
|
| 147 |
-
|
| 148 |
-
else:
|
| 149 |
-
# First check if the bird is endemic to Tanzania
|
| 150 |
-
if check_tanzania:
|
| 151 |
-
tanzania_check_prompt = f"""
|
| 152 |
-
Is the {clean_name} bird native to or commonly found in Tanzania?
|
| 153 |
-
Answer with ONLY "yes" or "no".
|
| 154 |
-
"""
|
| 155 |
-
|
| 156 |
-
try:
|
| 157 |
-
tanzania_check = client.chat.completions.create(
|
| 158 |
-
messages=[{"role": "user", "content": tanzania_check_prompt}],
|
| 159 |
-
model="llama-3.3-70b-versatile",
|
| 160 |
-
)
|
| 161 |
-
is_in_tanzania = "yes" in tanzania_check.choices[0].message.content.lower()
|
| 162 |
-
# Cache result
|
| 163 |
-
save_to_cache("tanzania_check", tanzania_cache_key, is_in_tanzania)
|
| 164 |
-
except:
|
| 165 |
-
# Default to showing Tanzania if we can't determine
|
| 166 |
-
is_in_tanzania = True
|
| 167 |
-
else:
|
| 168 |
-
is_in_tanzania = True
|
| 169 |
-
|
| 170 |
-
# Check cache for habitat locations
|
| 171 |
-
habitat_cache_key = f"{clean_name}_habitat"
|
| 172 |
-
cached_habitat = load_from_cache("habitat", habitat_cache_key)
|
| 173 |
-
if cached_habitat is not None:
|
| 174 |
-
return cached_habitat, is_in_tanzania
|
| 175 |
|
| 176 |
-
#
|
| 177 |
prompt = f"""
|
| 178 |
-
Provide
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 192 |
"""
|
| 193 |
|
| 194 |
try:
|
|
@@ -203,27 +182,42 @@ def get_bird_habitat_map(bird_name, check_tanzania=True):
|
|
| 203 |
)
|
| 204 |
response = chat_completion.choices[0].message.content
|
| 205 |
|
| 206 |
-
# Extract JSON from response
|
| 207 |
import json
|
| 208 |
import re
|
| 209 |
|
| 210 |
# Find JSON pattern in response
|
| 211 |
-
json_match = re.search(r'\
|
| 212 |
if json_match:
|
| 213 |
-
|
|
|
|
|
|
|
| 214 |
else:
|
| 215 |
-
# Fallback if JSON
|
| 216 |
locations = [
|
| 217 |
{"name": "Primary habitat region", "lat": 0, "lon": 0,
|
| 218 |
"description": "Could not retrieve specific habitat information for this bird."}
|
| 219 |
]
|
|
|
|
| 220 |
|
| 221 |
-
#
|
| 222 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
|
| 224 |
return locations, is_in_tanzania
|
| 225 |
|
| 226 |
except Exception as e:
|
|
|
|
| 227 |
return [{"name": "Error retrieving data", "lat": 0, "lon": 0,
|
| 228 |
"description": "Please try again or check your connection."}], False
|
| 229 |
|
|
@@ -266,19 +260,20 @@ def create_habitat_map(habitat_locations):
|
|
| 266 |
map_html = m._repr_html_()
|
| 267 |
return map_html
|
| 268 |
|
| 269 |
-
def format_bird_info(raw_info, language="en"):
|
| 270 |
"""Improve the formatting of bird information"""
|
| 271 |
# Add proper line breaks between sections and ensure consistent heading levels
|
| 272 |
formatted = raw_info
|
| 273 |
|
| 274 |
-
#
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
|
|
|
| 282 |
|
| 283 |
# Replace markdown headings with HTML headings for better control
|
| 284 |
formatted = re.sub(r'#+\s+(.*)', r'<h3>\1</h3>', formatted)
|
|
@@ -293,12 +288,12 @@ def format_bird_info(raw_info, language="en"):
|
|
| 293 |
|
| 294 |
return formatted
|
| 295 |
|
| 296 |
-
def get_bird_info(bird_name, language="en"):
|
| 297 |
"""Get detailed information about a bird using Groq API with caching"""
|
| 298 |
clean_name = clean_bird_name(bird_name)
|
| 299 |
|
| 300 |
-
# Check cache first
|
| 301 |
-
cache_key = f"{clean_name}_{language}"
|
| 302 |
cached_info = load_from_cache("bird_info", cache_key)
|
| 303 |
if cached_info is not None:
|
| 304 |
return cached_info
|
|
@@ -308,6 +303,13 @@ def get_bird_info(bird_name, language="en"):
|
|
| 308 |
if language == "sw":
|
| 309 |
lang_instruction = " Provide your response in Swahili language."
|
| 310 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 311 |
prompt = f"""
|
| 312 |
Provide detailed information about the {clean_name} bird, including:
|
| 313 |
1. Physical characteristics and appearance
|
|
@@ -316,7 +318,7 @@ def get_bird_info(bird_name, language="en"):
|
|
| 316 |
4. Migration patterns (emphasize if this pattern has changed in recent years due to climate change)
|
| 317 |
5. Conservation status
|
| 318 |
|
| 319 |
-
|
| 320 |
|
| 321 |
Format your response in markdown for better readability.{lang_instruction}
|
| 322 |
"""
|
|
@@ -345,8 +347,7 @@ def create_message_html(message, icon="🔍", language="en"):
|
|
| 345 |
<style>
|
| 346 |
.message-container {
|
| 347 |
font-family: Arial, sans-serif;
|
| 348 |
-
padding:
|
| 349 |
-
20px;
|
| 350 |
background-color: #f8f9fa;
|
| 351 |
border-radius: 8px;
|
| 352 |
text-align: center;
|
|
@@ -421,13 +422,13 @@ def predict_and_get_info(img, language="en"):
|
|
| 421 |
combined_info = create_message_html(other_message, "🔍", language)
|
| 422 |
return prediction_results, combined_info, clean_top_bird, ""
|
| 423 |
|
| 424 |
-
# Get habitat locations and
|
| 425 |
-
habitat_locations, is_in_tanzania =
|
| 426 |
habitat_map_html = create_habitat_map(habitat_locations)
|
| 427 |
|
| 428 |
# Get detailed information about the top predicted bird
|
| 429 |
-
bird_info = get_bird_info(top_bird, language)
|
| 430 |
-
formatted_info = format_bird_info(bird_info, language)
|
| 431 |
|
| 432 |
# Create combined info with map at the top and properly formatted information
|
| 433 |
custom_css = """
|
|
|
|
| 136 |
# If any error occurs during the check, assume it might be a bird
|
| 137 |
return True
|
| 138 |
|
| 139 |
+
def get_bird_habitat_and_status(bird_name):
|
| 140 |
+
"""Get both habitat locations and Tanzania status in a single API call"""
|
| 141 |
clean_name = clean_bird_name(bird_name)
|
| 142 |
|
| 143 |
+
# Check cache first - use a combined cache key
|
| 144 |
+
cache_key = f"{clean_name}_combined"
|
| 145 |
+
cached_result = load_from_cache("combined_habitat_status", cache_key)
|
| 146 |
+
if cached_result is not None:
|
| 147 |
+
return cached_result["locations"], cached_result["is_in_tanzania"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
|
| 149 |
+
# Single API call to get both information
|
| 150 |
prompt = f"""
|
| 151 |
+
Provide information about the {clean_name} bird in the following JSON format:
|
| 152 |
+
|
| 153 |
+
{{
|
| 154 |
+
"is_native_to_tanzania": true/false,
|
| 155 |
+
"habitat_locations": [
|
| 156 |
+
{{
|
| 157 |
+
"name": "Location name",
|
| 158 |
+
"lat": latitude_number,
|
| 159 |
+
"lon": longitude_number,
|
| 160 |
+
"description": "Brief description of habitat"
|
| 161 |
+
}}
|
| 162 |
+
]
|
| 163 |
+
}}
|
| 164 |
+
|
| 165 |
+
Instructions:
|
| 166 |
+
1. Set "is_native_to_tanzania" to true if this bird is native to, endemic to, or commonly found in Tanzania. Set to false if it's not typically found there.
|
| 167 |
+
2. Provide 3-5 main habitat locations worldwide for this bird species.
|
| 168 |
+
3. If the bird IS native to Tanzania, include Tanzania or East African locations in the habitat list.
|
| 169 |
+
4. If the bird is NOT native to Tanzania, do not include any Tanzania locations.
|
| 170 |
+
5. Return ONLY the JSON response, no additional text.
|
| 171 |
"""
|
| 172 |
|
| 173 |
try:
|
|
|
|
| 182 |
)
|
| 183 |
response = chat_completion.choices[0].message.content
|
| 184 |
|
| 185 |
+
# Extract and parse JSON from response
|
| 186 |
import json
|
| 187 |
import re
|
| 188 |
|
| 189 |
# Find JSON pattern in response
|
| 190 |
+
json_match = re.search(r'\{.*\}', response, re.DOTALL)
|
| 191 |
if json_match:
|
| 192 |
+
result = json.loads(json_match.group())
|
| 193 |
+
locations = result.get("habitat_locations", [])
|
| 194 |
+
is_in_tanzania = result.get("is_native_to_tanzania", False)
|
| 195 |
else:
|
| 196 |
+
# Fallback if JSON parsing fails
|
| 197 |
locations = [
|
| 198 |
{"name": "Primary habitat region", "lat": 0, "lon": 0,
|
| 199 |
"description": "Could not retrieve specific habitat information for this bird."}
|
| 200 |
]
|
| 201 |
+
is_in_tanzania = False
|
| 202 |
|
| 203 |
+
# Ensure we have valid data structure
|
| 204 |
+
if not locations:
|
| 205 |
+
locations = [
|
| 206 |
+
{"name": "Unknown habitat", "lat": 0, "lon": 0,
|
| 207 |
+
"description": "Habitat information not available."}
|
| 208 |
+
]
|
| 209 |
+
|
| 210 |
+
# Cache the combined result
|
| 211 |
+
combined_result = {
|
| 212 |
+
"locations": locations,
|
| 213 |
+
"is_in_tanzania": is_in_tanzania
|
| 214 |
+
}
|
| 215 |
+
save_to_cache("combined_habitat_status", cache_key, combined_result)
|
| 216 |
|
| 217 |
return locations, is_in_tanzania
|
| 218 |
|
| 219 |
except Exception as e:
|
| 220 |
+
print(f"Error in get_bird_habitat_and_status: {e}")
|
| 221 |
return [{"name": "Error retrieving data", "lat": 0, "lon": 0,
|
| 222 |
"description": "Please try again or check your connection."}], False
|
| 223 |
|
|
|
|
| 260 |
map_html = m._repr_html_()
|
| 261 |
return map_html
|
| 262 |
|
| 263 |
+
def format_bird_info(raw_info, is_in_tanzania, language="en"):
|
| 264 |
"""Improve the formatting of bird information"""
|
| 265 |
# Add proper line breaks between sections and ensure consistent heading levels
|
| 266 |
formatted = raw_info
|
| 267 |
|
| 268 |
+
# Only add the warning if the bird is NOT in Tanzania
|
| 269 |
+
if not is_in_tanzania:
|
| 270 |
+
# Get translation of warning text based on language
|
| 271 |
+
warning_text = "NOT TYPICALLY FOUND IN TANZANIA"
|
| 272 |
+
warning_translation = "HAPATIKANI SANA TANZANIA" if language == "sw" else warning_text
|
| 273 |
+
|
| 274 |
+
# Add warning at the beginning if not already present
|
| 275 |
+
if warning_translation not in formatted:
|
| 276 |
+
formatted = f'<div class="alert alert-warning"><strong>⚠️ {warning_translation}</strong></div>\n\n{formatted}'
|
| 277 |
|
| 278 |
# Replace markdown headings with HTML headings for better control
|
| 279 |
formatted = re.sub(r'#+\s+(.*)', r'<h3>\1</h3>', formatted)
|
|
|
|
| 288 |
|
| 289 |
return formatted
|
| 290 |
|
| 291 |
+
def get_bird_info(bird_name, is_in_tanzania, language="en"):
|
| 292 |
"""Get detailed information about a bird using Groq API with caching"""
|
| 293 |
clean_name = clean_bird_name(bird_name)
|
| 294 |
|
| 295 |
+
# Check cache first - include Tanzania status in cache key
|
| 296 |
+
cache_key = f"{clean_name}_{language}_{is_in_tanzania}"
|
| 297 |
cached_info = load_from_cache("bird_info", cache_key)
|
| 298 |
if cached_info is not None:
|
| 299 |
return cached_info
|
|
|
|
| 303 |
if language == "sw":
|
| 304 |
lang_instruction = " Provide your response in Swahili language."
|
| 305 |
|
| 306 |
+
# Adjust prompt based on Tanzania status
|
| 307 |
+
tanzania_instruction = ""
|
| 308 |
+
if not is_in_tanzania:
|
| 309 |
+
tanzania_instruction = " Important: This bird is NOT typically found in Tanzania. Explain why its presence might be unusual and focus on its natural range."
|
| 310 |
+
else:
|
| 311 |
+
tanzania_instruction = " This bird is native to or commonly found in Tanzania. Include information about its presence in Tanzania and East Africa."
|
| 312 |
+
|
| 313 |
prompt = f"""
|
| 314 |
Provide detailed information about the {clean_name} bird, including:
|
| 315 |
1. Physical characteristics and appearance
|
|
|
|
| 318 |
4. Migration patterns (emphasize if this pattern has changed in recent years due to climate change)
|
| 319 |
5. Conservation status
|
| 320 |
|
| 321 |
+
{tanzania_instruction}
|
| 322 |
|
| 323 |
Format your response in markdown for better readability.{lang_instruction}
|
| 324 |
"""
|
|
|
|
| 347 |
<style>
|
| 348 |
.message-container {
|
| 349 |
font-family: Arial, sans-serif;
|
| 350 |
+
padding: 20px;
|
|
|
|
| 351 |
background-color: #f8f9fa;
|
| 352 |
border-radius: 8px;
|
| 353 |
text-align: center;
|
|
|
|
| 422 |
combined_info = create_message_html(other_message, "🔍", language)
|
| 423 |
return prediction_results, combined_info, clean_top_bird, ""
|
| 424 |
|
| 425 |
+
# Get habitat locations and Tanzania status in a single call
|
| 426 |
+
habitat_locations, is_in_tanzania = get_bird_habitat_and_status(top_bird)
|
| 427 |
habitat_map_html = create_habitat_map(habitat_locations)
|
| 428 |
|
| 429 |
# Get detailed information about the top predicted bird
|
| 430 |
+
bird_info = get_bird_info(top_bird, is_in_tanzania, language)
|
| 431 |
+
formatted_info = format_bird_info(bird_info, is_in_tanzania, language)
|
| 432 |
|
| 433 |
# Create combined info with map at the top and properly formatted information
|
| 434 |
custom_css = """
|