Spaces:
Sleeping
Sleeping
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 = """
|