-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathai_services.py
More file actions
483 lines (419 loc) · 19.5 KB
/
Copy pathai_services.py
File metadata and controls
483 lines (419 loc) · 19.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
import logging
import os
from datetime import datetime
from typing import Dict, Any, Optional
import google.generativeai as genai
from config import Config
logger = logging.getLogger(__name__)
# Initialize client variables
client = None
client_error = None
def initialize_gemini_client():
"""Initialize Gemini AI client"""
global client, client_error
try:
# Get API key from environment or config
api_key = os.getenv('GEMINI_API_KEY') or getattr(Config, 'GEMINI_API_KEY', None)
if not api_key:
logger.warning("Gemini API key not found. Using mock responses for AI services.")
client = None
client_error = "Gemini API key not configured. Using demo mode."
return
genai.configure(api_key=api_key)
client = genai.GenerativeModel('gemini-2.5-flash-lite')
client_error = None
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
logger.info("Gemini AI client initialized successfully with gemini-2.5-flash-lite")
except Exception as e:
logger.error(f"AI client initialization failed: {e}")
client = None
client_error = str(e)
# Initialize client on import
initialize_gemini_client()
class EnhancedWeatherAI:
"""Weather-related AI services"""
@staticmethod
def get_weather_data(location):
"""Get weather data for location"""
return {
"success": True,
"location": location,
"temperature": "25°C",
"humidity": "60%",
"conditions": "Partly cloudy",
"source": "placeholder"
}
@staticmethod
def get_weather_forecast(location, days=5):
"""Get weather forecast"""
return {
"success": True,
"location": location,
"forecast": [],
"source": "placeholder"
}
@staticmethod
def get_farming_insights(weather_data, crop_name):
"""Get farming insights based on weather data and crop"""
if not client:
return {
"insights": "Weather AI service is currently unavailable.",
"recommendations": [],
"alerts": []
}
try:
# Extract weather information
temp = weather_data.get('temperature', 'N/A')
humidity = weather_data.get('humidity', 'N/A')
condition = weather_data.get('condition', weather_data.get('weather_condition', 'N/A'))
wind_speed = weather_data.get('wind_speed', 'N/A')
prompt = f"""
As an agricultural AI expert, analyze the current weather conditions and provide farming insights for {crop_name}.
Current Weather Data:
- Temperature: {temp}
- Humidity: {humidity}
- Weather Condition: {condition}
- Wind Speed: {wind_speed}
Please provide specific, actionable farming advice in the following format:
IRRIGATION:
[Specific irrigation advice based on current conditions]
CROP_CARE:
[Specific crop care recommendations]
PEST_DISEASE:
[Disease/pest risk assessment and prevention]
HARVEST:
[Harvest timing and preparation advice if applicable]
ALERTS:
[Any urgent warnings or alerts]
OVERALL:
[Overall assessment and summary]
Keep each section brief and actionable for farmers.
"""
response = client.generate_content(prompt)
insights_text = response.text if response and hasattr(response, 'text') else "Unable to generate farming insights at this time."
# Parse the structured response
insights_list = []
overall_assessment = ""
sections = insights_text.split('\n\n')
for section in sections:
lines = section.strip().split('\n')
if len(lines) >= 2:
header = lines[0].strip()
content = '\n'.join(lines[1:]).strip()
if header.startswith('IRRIGATION'):
insights_list.append({
'category': 'irrigation',
'urgency': 'medium',
'recommendation': content,
'reason': f'Based on current humidity ({humidity}) and temperature ({temp})'
})
elif header.startswith('CROP_CARE'):
insights_list.append({
'category': 'crop care',
'urgency': 'low',
'recommendation': content,
'reason': f'Weather conditions: {condition}'
})
elif header.startswith('PEST_DISEASE'):
urgency = 'high' if any(word in content.lower() for word in ['warning', 'risk', 'urgent', 'immediate']) else 'medium'
insights_list.append({
'category': 'pest & disease',
'urgency': urgency,
'recommendation': content,
'reason': f'Current conditions may affect pest/disease pressure'
})
elif header.startswith('HARVEST'):
insights_list.append({
'category': 'harvest',
'urgency': 'medium',
'recommendation': content,
'reason': f'Weather timing considerations'
})
elif header.startswith('ALERTS'):
if content and content.lower() not in ['none', 'no alerts', 'no warnings']:
insights_list.append({
'category': 'alert',
'urgency': 'high',
'recommendation': content,
'reason': 'Immediate attention required'
})
elif header.startswith('OVERALL'):
overall_assessment = content
# If parsing failed, create a basic insight
if not insights_list:
insights_list = [{
'category': 'general',
'urgency': 'low',
'recommendation': insights_text[:200] + '...' if len(insights_text) > 200 else insights_text,
'reason': f'Based on current weather conditions for {crop_name}'
}]
return {
"insights": insights_list,
"overall_assessment": overall_assessment or f"Weather conditions are suitable for {crop_name} cultivation with proper care.",
"crop": crop_name,
"weather_summary": f"Temperature: {temp}, Humidity: {humidity}, Condition: {condition}"
}
except Exception as e:
logger.error(f"Error generating farming insights: {str(e)}")
return {
"insights": [
{
'category': 'general',
'urgency': 'low',
'recommendation': 'Monitor your crops regularly and check soil moisture levels.',
'reason': 'AI service temporarily unavailable'
},
{
'category': 'irrigation',
'urgency': 'medium',
'recommendation': 'Ensure adequate water supply and check irrigation systems.',
'reason': 'General farming best practice'
}
],
"overall_assessment": f"Weather data analysis for {crop_name} is temporarily unavailable. Follow standard farming practices.",
"crop": crop_name,
"weather_summary": "Weather data analysis unavailable"
}
class EnhancedVoiceAI:
"""Advanced Voice-powered AI services with complete Gemini integration for Farmlink"""
SUPPORTED_LANGUAGES = {
'english': 'en',
'hindi': 'hi',
'punjabi': 'pa',
'tamil': 'ta',
'telugu': 'te',
'bengali': 'bn',
'gujarati': 'gu',
'marathi': 'mr',
'kannada': 'kn',
'malayalam': 'ml'
}
@staticmethod
def get_multilingual_farming_response(query, language="english"):
"""
Get comprehensive farming response using Gemini AI
This is the core voice assistant function for Farmlink
"""
if not client:
return "I'm sorry, but AI services are currently unavailable. Please check your connection and try again."
try:
# Normalize language
lang_code = EnhancedVoiceAI.SUPPORTED_LANGUAGES.get(language.lower(), 'en')
# Create comprehensive farming context prompt
system_prompt = f"""
You are the Farmlink Voice Assistant, an AI helper powered by Gemini AI specifically designed for farmers.
IDENTITY & ROLE:
- You are the official voice assistant for Farmlink platform
- Your purpose is to help farmers with practical, actionable farming advice
- Respond in {language} language when requested
FARMLINK PLATFORM OVERVIEW:
- Farmlink connects farmers, buyers, and suppliers in a comprehensive ecosystem
- Core services: Crop guidance, market connections, weather alerts, supply chain support
- Target users: Small to medium farmers across India
YOUR CAPABILITIES:
✅ Crop suggestions and planning
✅ Weather forecasts and farming alerts
✅ Disease & pest identification + treatment
✅ Soil analysis and fertilizer recommendations
✅ Market price information and trends
✅ Irrigation and water management advice
✅ Harvest timing and yield optimization
✅ Supply chain and logistics support
✅ Buyer-farmer marketplace connections
RESPONSE GUIDELINES:
1. Be conversational, warm, and farmer-friendly
2. Provide practical, step-by-step advice when needed
3. Keep responses CONCISE but COMPLETE - aim for 3-5 key points
4. Use bullet points (•) for better readability
5. Consider local Indian farming conditions
6. Always give real, actionable information (no placeholder data)
7. If you don't know something specific, say so honestly
8. Focus on solutions that increase farmer income and reduce risk
9. For simple questions, give brief answers (2-3 sentences)
10. For complex questions, provide structured guidance (but keep it under 200 words)
RESPONSE LENGTH RULES:
- Simple greetings/questions: 1-2 sentences
- General info queries: 3-5 bullet points
- Technical advice: 4-6 key points with brief explanations
- Emergency/disease issues: Immediate action + detailed steps (max 150 words)
QUERY TYPES TO HANDLE:
- Weather: "What's the weather forecast?" → Brief forecast + farming impact
- Crops: "What should I plant?" → Top 3-4 seasonal recommendations
- Prices: "Rice price today?" → Current price + brief trend
- Diseases: "Tomato leaves turning yellow" → Quick diagnosis + treatment steps
- Fertilizer: "What fertilizer for wheat?" → Specific recommendations (NPK ratios)
- General: "How can you help?" → Brief platform overview (5-6 points)
Always respond as if you have access to real-time data and provide practical farming guidance.
"""
# Prepare the user query with context
user_prompt = f"""
Farmer Query: "{query}"
Language: {language}
Please provide a helpful, practical response as the Farmlink Voice Assistant. Keep it concise but complete - focus on the most important information the farmer needs to know.
"""
# Make API call to Gemini
model = genai.GenerativeModel('gemini-2.5-flash-lite')
response = model.generate_content(
f"{system_prompt}\n\n{user_prompt}",
generation_config=genai.types.GenerationConfig(
temperature=0.7,
max_output_tokens=800, # Increased from 400 to allow complete responses
top_p=0.8,
top_k=40,
)
)
if response.text:
# Clean and format the response
ai_response = response.text.strip()
# Clean up any Farmlink prefix if present
ai_response = ai_response.replace("🌱 Farmlink Suggestion:", "").strip()
# Log the successful response
logger.info(f"Voice AI response generated for query: {query[:50]}...")
return ai_response
else:
logger.warning("Empty response from Gemini API")
return "I'm having trouble processing your request right now. Please try rephrasing your question or try again in a moment."
except Exception as e:
logger.error(f"Error in voice AI response generation: {str(e)}")
return f"I encountered an issue while processing your request. Please try again. If the problem persists, contact Farmlink support."
@staticmethod
def process_voice_query(audio_file_path, language="english"):
"""
Process voice audio file (placeholder for future speech-to-text integration)
"""
try:
# For now, return a basic structure
# In future, integrate with Google Speech-to-Text or similar service
return {
"success": False,
"error": "Speech-to-text processing not yet implemented. Please use text input.",
"text": "",
"detected_language": language
}
except Exception as e:
logger.error(f"Voice processing error: {str(e)}")
return {
"success": False,
"error": f"Voice processing failed: {str(e)}",
"text": "",
"detected_language": language
}
@staticmethod
def generate_voice_response(text, language="english", voice_style="alloy"):
"""
Generate voice audio from text (placeholder for future text-to-speech)
"""
try:
# For now, return None - would integrate with Google TTS in future
logger.info(f"Voice generation requested for text: {text[:50]}...")
return None
except Exception as e:
logger.error(f"Voice generation error: {str(e)}")
return None
@staticmethod
def get_quick_farming_response(command_type):
"""
Get quick responses for common farming commands
"""
quick_responses = {
'weather': "Let me check the latest weather forecast for your area. Based on current conditions, here's what you need to know for farming activities...",
'prices': "Here are today's market prices for major crops. Rice is trading at competitive rates, while vegetable prices show seasonal variations...",
'diseases': "Common diseases this season include leaf blight and pest infestations. Early detection and organic treatments are most effective...",
'fertilizer': "For optimal crop nutrition, consider soil testing first. NPK requirements vary by crop stage and soil type...",
'help': "I can help you with crop planning, weather updates, market prices, disease identification, fertilizer advice, and connecting with buyers. What would you like to know?"
}
return quick_responses.get(command_type, quick_responses['help'])
class EnhancedAnalyticsAI:
"""Analytics-related AI services"""
@staticmethod
def generate_analytics_report(user_data):
"""Generate analytics report"""
return {
"success": True,
"report": {
"summary": "Analytics data processed",
"insights": [],
"recommendations": []
},
"source": "placeholder"
}
# Import crop AI services
try:
from crop_ai_service import EnhancedCropAI as CropAIService, get_crop_service_status, CROP_AI_AVAILABLE
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
logger.info("Crop AI service imported successfully")
except ImportError as e:
logger.warning(f"Crop AI service not available: {e}")
CROP_AI_AVAILABLE = False
CropAIService = None
class EnhancedCropAI:
"""Crop suggestion AI services - wrapper for crop_ai_service"""
@staticmethod
def get_smart_crop_suggestions(input_data):
"""Get intelligent crop suggestions based on comprehensive input"""
if CROP_AI_AVAILABLE and CropAIService:
return CropAIService.get_smart_crop_suggestions(input_data)
else:
return {
"success": False,
"error": "Crop AI service not available",
"suggestions": []
}
@staticmethod
def compare_crops_analysis(crop_names, comparison_factor='profitability'):
"""Compare multiple crops based on specified factors"""
if CROP_AI_AVAILABLE and CropAIService:
return CropAIService.compare_crops_analysis(crop_names, comparison_factor)
else:
return {
"success": False,
"error": "Crop comparison service not available - Gemini API key required",
"comparison": {}
}
@staticmethod
def get_seasonal_suggestions(input_data, season):
"""Get season-specific crop suggestions"""
if CROP_AI_AVAILABLE and CropAIService:
return CropAIService.get_seasonal_recommendations(input_data, season)
else:
return {
"success": False,
"error": "Seasonal suggestion service not available - Gemini API key required",
"suggestions": []
}
def get_ai_service_status():
"""Get current AI service status"""
crop_status = {}
if CROP_AI_AVAILABLE and CropAIService:
crop_status = get_crop_service_status()
# Check pest detection service availability
pest_detection_available = False
try:
from pest_detection_service import pest_detection_service
pest_detection_available = pest_detection_service.is_available()
except ImportError:
pass
return {
"client_available": bool(client),
"client_error": client_error,
"cache_enabled": False,
"fallback_db_ready": False,
"supported_languages": list(EnhancedVoiceAI.SUPPORTED_LANGUAGES.keys()),
"service_capabilities": {
"pest_analysis": pest_detection_available,
"weather_analysis": True,
"voice_interface": True,
"analytics": True,
"crop_suggestions": CROP_AI_AVAILABLE,
"crop_comparison": CROP_AI_AVAILABLE,
"seasonal_recommendations": CROP_AI_AVAILABLE,
"fertilizer_planning": CROP_AI_AVAILABLE,
"irrigation_scheduling": CROP_AI_AVAILABLE,
"yield_prediction": CROP_AI_AVAILABLE
},
"crop_ai_status": crop_status
}
# Legacy aliases for backward compatibility
WeatherAI = EnhancedWeatherAI
VoiceAI = EnhancedVoiceAI
AnalyticsAI = EnhancedAnalyticsAI