Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -3,6 +3,7 @@ import gradio as gr
|
|
3 |
import re
|
4 |
import folium
|
5 |
from fastai.vision.all import *
|
|
|
6 |
from PIL import Image
|
7 |
import time
|
8 |
import json
|
@@ -12,6 +13,11 @@ from functools import lru_cache
|
|
12 |
learn = load_learner('export.pkl')
|
13 |
labels = learn.dls.vocab
|
14 |
|
|
|
|
|
|
|
|
|
|
|
15 |
# Cache directory for API responses
|
16 |
os.makedirs("cache", exist_ok=True)
|
17 |
|
@@ -130,43 +136,96 @@ def is_likely_bird_image(img):
|
|
130 |
# If any error occurs during the check, assume it might be a bird
|
131 |
return True
|
132 |
|
133 |
-
def get_bird_habitat_map(bird_name):
|
134 |
-
"""Get habitat map locations for the bird
|
135 |
clean_name = clean_bird_name(bird_name)
|
136 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
# Check cache for habitat locations
|
138 |
habitat_cache_key = f"{clean_name}_habitat"
|
139 |
cached_habitat = load_from_cache("habitat", habitat_cache_key)
|
140 |
if cached_habitat is not None:
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
"description": "Crater highlands with varying altitudes supporting different bird species."
|
157 |
-
},
|
158 |
-
{
|
159 |
-
"name": "Tarangire National Park, Tanzania",
|
160 |
-
"lat": -4.0,
|
161 |
-
"lon": 36.0,
|
162 |
-
"description": "Known for its baobab trees and seasonal swamps that attract various bird species."
|
163 |
-
}
|
164 |
]
|
165 |
|
166 |
-
|
167 |
-
|
168 |
|
169 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
|
171 |
def create_habitat_map(habitat_locations):
|
172 |
"""Create a folium map with the habitat locations"""
|
@@ -235,7 +294,7 @@ def format_bird_info(raw_info, language="en"):
|
|
235 |
return formatted
|
236 |
|
237 |
def get_bird_info(bird_name, language="en"):
|
238 |
-
"""Get detailed information about a bird
|
239 |
clean_name = clean_bird_name(bird_name)
|
240 |
|
241 |
# Check cache first
|
@@ -244,70 +303,41 @@ def get_bird_info(bird_name, language="en"):
|
|
244 |
if cached_info is not None:
|
245 |
return cached_info
|
246 |
|
247 |
-
#
|
248 |
-
|
249 |
-
|
|
|
250 |
|
251 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
252 |
|
253 |
-
|
254 |
-
bird_info = f"""
|
255 |
-
## Maelezo ya {clean_name}
|
256 |
-
|
257 |
-
### Sifa za Kimwili na Mwonekano
|
258 |
-
• Ndege huyu ana umbile la wastani na rangi nyeupe na nyeusi.
|
259 |
-
• Ana mdomo mrefu na miguu myeupe.
|
260 |
-
|
261 |
-
### Makazi na Usambazaji
|
262 |
-
• Hupatikana sana katika misitu na viunga vya maji nchini Tanzania.
|
263 |
-
• Hupendelea maeneo yenye miti mingi na vyanzo vya maji.
|
264 |
-
|
265 |
-
### Lishe na Tabia
|
266 |
-
• Hula wadudu na matunda madogo madogo.
|
267 |
-
• Hutengeneza viota vyake juu ya miti.
|
268 |
-
|
269 |
-
### Mifumo ya Uhamiaji
|
270 |
-
• Sio ndege mhamiaji, hupatikana nchini Tanzania mwaka mzima.
|
271 |
-
• Husafiri katika makundi madogo madogo.
|
272 |
-
|
273 |
-
### Hali ya Uhifadhi
|
274 |
-
• Haijaathiriwa sana na mabadiliko ya tabianchi.
|
275 |
-
• Idadi yake ipo salama kwa sasa.
|
276 |
-
"""
|
277 |
-
else:
|
278 |
-
bird_info = f"""
|
279 |
-
## About the {clean_name}
|
280 |
-
|
281 |
-
### Physical Characteristics and Appearance
|
282 |
-
• This bird has a medium build with distinctive white and black coloration.
|
283 |
-
• It has a long beak and white legs.
|
284 |
-
|
285 |
-
### Habitat and Distribution
|
286 |
-
• Commonly found in forests and near water bodies in Tanzania.
|
287 |
-
• Prefers areas with abundant trees and water sources.
|
288 |
-
|
289 |
-
### Diet and Behavior
|
290 |
-
• Feeds on insects and small fruits.
|
291 |
-
• Builds nests high up in trees.
|
292 |
-
|
293 |
-
### Migration Patterns
|
294 |
-
• Not a migratory bird, present in Tanzania year-round.
|
295 |
-
• Travels in small flocks.
|
296 |
-
|
297 |
-
### Conservation Status
|
298 |
-
• Not significantly affected by climate change yet.
|
299 |
-
• Population remains stable.
|
300 |
-
"""
|
301 |
|
302 |
-
|
303 |
-
|
304 |
-
if not is_in_tanzania or random.random() > 0.7: # 30% chance to be marked as not in Tanzania
|
305 |
-
warning = "NOT TYPICALLY FOUND IN TANZANIA\n\n" if language == "en" else "HAPATIKANI SANA TANZANIA\n\n"
|
306 |
-
bird_info = warning + bird_info
|
307 |
|
308 |
-
|
309 |
-
|
310 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
311 |
|
312 |
def create_message_html(message, icon="🔍", language="en"):
|
313 |
"""Create a styled message container for notifications"""
|
@@ -315,7 +345,8 @@ def create_message_html(message, icon="🔍", language="en"):
|
|
315 |
<style>
|
316 |
.message-container {
|
317 |
font-family: Arial, sans-serif;
|
318 |
-
padding:
|
|
|
319 |
background-color: #f8f9fa;
|
320 |
border-radius: 8px;
|
321 |
text-align: center;
|
@@ -484,54 +515,41 @@ def follow_up_question(question, bird_name, language="en"):
|
|
484 |
if cached_answer is not None:
|
485 |
return cached_answer
|
486 |
|
487 |
-
#
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
clean_bird = clean_bird_name(bird_name)
|
492 |
-
|
493 |
-
response_templates = {
|
494 |
-
"en": {
|
495 |
-
"habitat": f"The {clean_bird} typically inhabits forested areas and wetlands in Tanzania. They prefer areas with abundant tree cover and proximity to water sources for feeding and nesting.",
|
496 |
-
"diet": f"The {clean_bird} primarily feeds on insects, small fruits, and seeds. They forage in trees and sometimes on the ground, using their specialized beak to extract food from various sources.",
|
497 |
-
"migration": f"The {clean_bird} is generally a resident species in Tanzania, though some local movements may occur based on seasonal food availability. Climate change has not significantly altered their distribution patterns yet.",
|
498 |
-
"conservation": f"The {clean_bird} currently has a stable population in Tanzania. Conservation efforts focus on habitat preservation, especially protecting the forests and wetlands where they breed.",
|
499 |
-
"behavior": f"The {clean_bird} is known for its distinctive calls and social behavior. They often form small flocks and are more active during early morning and late afternoon hours.",
|
500 |
-
"default": f"The {clean_bird} is an interesting bird species found in Tanzania. While specific information on your question is limited, ongoing research continues to expand our understanding of this species."
|
501 |
-
},
|
502 |
-
"sw": {
|
503 |
-
"habitat": f"Ndege {clean_bird} huishi katika maeneo ya misitu na maeneo yenye maji nchini Tanzania. Hupendelea maeneo yenye miti mingi na karibu na vyanzo vya maji kwa ajili ya chakula na viota.",
|
504 |
-
"diet": f"Ndege {clean_bird} hula wadudu, matunda madogo, na mbegu. Hutafuta chakula kwenye miti na wakati mwingine ardhini, akitumia mdomo wake maalum kutoa chakula kutoka vyanzo mbalimbali.",
|
505 |
-
"migration": f"Ndege {clean_bird} kwa kawaida huishi Tanzania mwaka mzima, ingawa baadhi ya harakati za ndani hufanyika kulingana na upatikanaji wa chakula kwa msimu. Mabadiliko ya tabianchi hayajabadilisha sana mienendo yao ya usambazaji.",
|
506 |
-
"conservation": f"Ndege {clean_bird} kwa sasa ana idadi imara nchini Tanzania. Juhudi za uhifadhi zinalenga kuhifadhi makazi, hasa kulinda misitu na nyanda za maji ambapo wanazaliana.",
|
507 |
-
"behavior": f"Ndege {clean_bird} anajulikana kwa mwito wake wa kipekee na tabia ya kijamii. Mara nyingi huunda makundi madogo na wana shughuli zaidi wakati wa asubuhi na mchana.",
|
508 |
-
"default": f"Ndege {clean_bird} ni spishi ya ndege ya kuvutia inayopatikana Tanzania. Ingawa taarifa mahususi kuhusu swali lako ni ndogo, utafiti unaoendelea unaendelea kupanua uelewa wetu wa spishi hii."
|
509 |
-
}
|
510 |
-
}
|
511 |
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
response = templates["migration"]
|
522 |
-
elif any(word in question_lower for word in ["conserve", "protect", "endangered", "status", "uhifadhi", "linda", "hatarini"]):
|
523 |
-
response = templates["conservation"]
|
524 |
-
elif any(word in question_lower for word in ["behavior", "behaviour", "habit", "social", "tabia", "mazoea", "jamii"]):
|
525 |
-
response = templates["behavior"]
|
526 |
-
else:
|
527 |
-
response = templates["default"]
|
528 |
-
else:
|
529 |
-
# Fallback to English
|
530 |
-
response = response_templates["en"]["default"]
|
531 |
|
532 |
-
|
533 |
-
|
534 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
535 |
|
536 |
# Create the Gradio interface
|
537 |
with gr.Blocks(theme=gr.themes.Soft()) as app:
|
|
|
3 |
import re
|
4 |
import folium
|
5 |
from fastai.vision.all import *
|
6 |
+
from groq import Groq
|
7 |
from PIL import Image
|
8 |
import time
|
9 |
import json
|
|
|
13 |
learn = load_learner('export.pkl')
|
14 |
labels = learn.dls.vocab
|
15 |
|
16 |
+
# Initialize Groq client
|
17 |
+
client = Groq(
|
18 |
+
api_key=os.environ.get("GROQ_API_KEY"),
|
19 |
+
)
|
20 |
+
|
21 |
# Cache directory for API responses
|
22 |
os.makedirs("cache", exist_ok=True)
|
23 |
|
|
|
136 |
# If any error occurs during the check, assume it might be a bird
|
137 |
return True
|
138 |
|
139 |
+
def get_bird_habitat_map(bird_name, check_tanzania=True):
|
140 |
+
"""Get habitat map locations for the bird using Groq API with caching"""
|
141 |
clean_name = clean_bird_name(bird_name)
|
142 |
|
143 |
+
# Check cache for Tanzania check
|
144 |
+
tanzania_cache_key = f"{clean_name}_tanzania"
|
145 |
+
cached_tanzania = load_from_cache("tanzania_check", tanzania_cache_key)
|
146 |
+
if cached_tanzania is not None:
|
147 |
+
is_in_tanzania = cached_tanzania
|
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 |
+
# Now get the habitat locations
|
177 |
+
prompt = f"""
|
178 |
+
Provide a JSON array of the main habitat locations for the {clean_name} bird in the world.
|
179 |
+
Return ONLY a JSON array with 3-5 entries, each containing:
|
180 |
+
1. "name": Location name
|
181 |
+
2. "lat": Latitude (numeric value)
|
182 |
+
3. "lon": Longitude (numeric value)
|
183 |
+
4. "description": Brief description of why this is a key habitat (2-3 sentences)
|
184 |
+
|
185 |
+
Example format:
|
186 |
+
[
|
187 |
+
{{"name": "Example Location", "lat": 12.34, "lon": 56.78, "description": "Brief description"}},
|
188 |
+
...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
189 |
]
|
190 |
|
191 |
+
{'' if is_in_tanzania else 'DO NOT include any locations in Tanzania as this bird is not native to or commonly found there.'}
|
192 |
+
"""
|
193 |
|
194 |
+
try:
|
195 |
+
chat_completion = client.chat.completions.create(
|
196 |
+
messages=[
|
197 |
+
{
|
198 |
+
"role": "user",
|
199 |
+
"content": prompt,
|
200 |
+
}
|
201 |
+
],
|
202 |
+
model="llama-3.3-70b-versatile",
|
203 |
+
)
|
204 |
+
response = chat_completion.choices[0].message.content
|
205 |
+
|
206 |
+
# Extract JSON from response (in case there's additional text)
|
207 |
+
import json
|
208 |
+
import re
|
209 |
+
|
210 |
+
# Find JSON pattern in response
|
211 |
+
json_match = re.search(r'\[.*\]', response, re.DOTALL)
|
212 |
+
if json_match:
|
213 |
+
locations = json.loads(json_match.group())
|
214 |
+
else:
|
215 |
+
# Fallback if JSON extraction fails
|
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 |
+
# Cache the result
|
222 |
+
save_to_cache("habitat", habitat_cache_key, locations)
|
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 |
|
230 |
def create_habitat_map(habitat_locations):
|
231 |
"""Create a folium map with the habitat locations"""
|
|
|
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
|
|
|
303 |
if cached_info is not None:
|
304 |
return cached_info
|
305 |
|
306 |
+
# Adjust language for the prompt
|
307 |
+
lang_instruction = ""
|
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
|
314 |
+
2. Habitat and distribution
|
315 |
+
3. Diet and behavior
|
316 |
+
4. Migration patterns (emphasize if this pattern has changed in recent years due to climate change)
|
317 |
+
5. Conservation status
|
318 |
|
319 |
+
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
320 |
|
321 |
+
Format your response in markdown for better readability.{lang_instruction}
|
322 |
+
"""
|
|
|
|
|
|
|
323 |
|
324 |
+
try:
|
325 |
+
chat_completion = client.chat.completions.create(
|
326 |
+
messages=[
|
327 |
+
{
|
328 |
+
"role": "user",
|
329 |
+
"content": prompt,
|
330 |
+
}
|
331 |
+
],
|
332 |
+
model="llama-3.3-70b-versatile",
|
333 |
+
)
|
334 |
+
response = chat_completion.choices[0].message.content
|
335 |
+
# Cache the result
|
336 |
+
save_to_cache("bird_info", cache_key, response)
|
337 |
+
return response
|
338 |
+
except Exception as e:
|
339 |
+
error_msg = "Hitilafu katika kupata taarifa" if language == "sw" else "Error fetching information"
|
340 |
+
return f"{error_msg}: {str(e)}"
|
341 |
|
342 |
def create_message_html(message, icon="🔍", language="en"):
|
343 |
"""Create a styled message container for notifications"""
|
|
|
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;
|
|
|
515 |
if cached_answer is not None:
|
516 |
return cached_answer
|
517 |
|
518 |
+
# Adjust language for the prompt
|
519 |
+
lang_instruction = ""
|
520 |
+
if language == "sw":
|
521 |
+
lang_instruction = " Provide your response in Swahili language."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
522 |
|
523 |
+
prompt = f"""
|
524 |
+
The researcher is asking about the {bird_name} bird: "{question}"
|
525 |
+
|
526 |
+
Provide a detailed, scientific answer focusing on accurate ornithological information.
|
527 |
+
If the question relates to Tanzania or climate change impacts, emphasize those aspects in your response.
|
528 |
+
|
529 |
+
IMPORTANT: Do not repeat basic introductory information about the bird that would have already been provided in a general description.
|
530 |
+
Do not start your answer with phrases like "Introduction to the {bird_name}" or similar repetitive headers.
|
531 |
+
Directly answer the specific question asked.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
532 |
|
533 |
+
Format your response in markdown for better readability.{lang_instruction}
|
534 |
+
"""
|
535 |
+
|
536 |
+
try:
|
537 |
+
chat_completion = client.chat.completions.create(
|
538 |
+
messages=[
|
539 |
+
{
|
540 |
+
"role": "user",
|
541 |
+
"content": prompt,
|
542 |
+
}
|
543 |
+
],
|
544 |
+
model="llama-3.3-70b-versatile",
|
545 |
+
)
|
546 |
+
response = chat_completion.choices[0].message.content
|
547 |
+
# Cache the result
|
548 |
+
save_to_cache("follow_up", cache_key, response)
|
549 |
+
return response
|
550 |
+
except Exception as e:
|
551 |
+
error_msg = "Hitilafu katika kupata taarifa" if language == "sw" else "Error fetching information"
|
552 |
+
return f"{error_msg}: {str(e)}"
|
553 |
|
554 |
# Create the Gradio interface
|
555 |
with gr.Blocks(theme=gr.themes.Soft()) as app:
|