diff --git a/src/app/crop-setup/page.tsx b/src/app/crop-setup/page.tsx index 9f37462..3d5d263 100644 --- a/src/app/crop-setup/page.tsx +++ b/src/app/crop-setup/page.tsx @@ -4,7 +4,9 @@ import { useState, useEffect } from 'react' import { useRouter } from 'next/navigation' import { useLanguage } from '@/contexts/LanguageContext' import LanguageSwitcher from '@/components/LanguageSwitcher' +import ChatBot from '@/components/ChatBot' import { LocationService } from '@/lib/locationService' +import { CropValidationService } from '@/lib/cropValidationService' interface LocationData { Name: string; @@ -27,6 +29,12 @@ export default function CropSetupPage() { const [locationLoading, setLocationLoading] = useState(false) const [isGettingLocation, setIsGettingLocation] = useState(false) const [selectedLocation, setSelectedLocation] = useState(null) + const [validationResult, setValidationResult] = useState<{ + isSuitable: boolean; + message: string; + confidence: 'high' | 'medium' | 'low'; + recommendations?: string[]; + } | null>(null) const router = useRouter() const { t } = useLanguage() @@ -561,6 +569,13 @@ export default function CropSetupPage() { if (pincodeData.length > 0) { alert(`✅ Location detected: ${locationName} (PIN: ${detectedPincode})`); + // Auto-select first location and validate crop if selected + if (pincodeData[0]) { + setSelectedLocation(pincodeData[0]); + if (crop) { + validateCropSuitability(crop, pincodeData[0].State); + } + } } else { alert(`Pincode ${detectedPincode} detected but no postal data found. Try manual search.`); } @@ -574,6 +589,13 @@ export default function CropSetupPage() { if (cityData.length > 0) { alert(`✅ Location detected: ${locationName}`); + // Auto-select first location and validate crop if selected + if (cityData[0]) { + setSelectedLocation(cityData[0]); + if (crop) { + validateCropSuitability(crop, cityData[0].State); + } + } } else { alert(`Location detected as ${locationName}, but no postal data found. Try manual search.`); } @@ -626,6 +648,15 @@ export default function CropSetupPage() { postOffice: location.Name })); } + // Validate crop if already selected + if (crop) { + validateCropSuitability(crop, location.State); + } + } + + const validateCropSuitability = (cropName: string, state: string) => { + const result = CropValidationService.validateCropSuitability(cropName, state); + setValidationResult(result); } const handleSubmit = (e: React.FormEvent) => { @@ -779,8 +810,29 @@ export default function CropSetupPage() { setCropSearch(e.target.value) setCrop('') setShowCropList(true) + setValidationResult(null) // Clear previous validation }} onFocus={() => setShowCropList(true)} + onBlur={(e) => { + // Validate crop when user finishes typing + setTimeout(() => { + const inputValue = e.target.value.trim(); + if (inputValue && selectedLocation && !crop) { + setCrop(inputValue.toLowerCase()); + validateCropSuitability(inputValue.toLowerCase(), selectedLocation.State); + } + }, 200); + }} + onKeyDown={(e) => { + if (e.key === 'Enter' && cropSearch.trim() && selectedLocation) { + e.preventDefault(); + const inputValue = cropSearch.trim(); + setCrop(inputValue.toLowerCase()); + setCropSearch(''); + setShowCropList(false); + validateCropSuitability(inputValue.toLowerCase(), selectedLocation.State); + } + }} className="w-full p-3 border-2 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" style={{backgroundColor: '#ffffff', borderColor: '#95a5a6', color: '#2c3e2d'}} required @@ -792,9 +844,14 @@ export default function CropSetupPage() {
{ - setCrop(cropName.toLowerCase()) + const selectedCrop = cropName.toLowerCase(); + setCrop(selectedCrop) setCropSearch('') setShowCropList(false) + // Validate crop if location is selected + if (selectedLocation) { + validateCropSuitability(selectedCrop, selectedLocation.State); + } }} className="p-3 hover:bg-green-100 cursor-pointer border-b border-green-100 last:border-b-0" > @@ -811,6 +868,42 @@ export default function CropSetupPage() { Selected: {crop.charAt(0).toUpperCase() + crop.slice(1)}
)} + + {/* Crop Validation Message */} + {validationResult && selectedLocation && crop && ( +
+
+ + {validationResult.isSuitable + ? validationResult.confidence === 'high' ? '✅' : '⚠️' + : '⚠️' + } + +
+
{validationResult.message}
+ {validationResult.recommendations && validationResult.recommendations.length > 0 && ( +
+
Recommendations:
+
    + {validationResult.recommendations.map((rec, index) => ( +
  • + + {rec} +
  • + ))} +
+
+ )} +
+
+
+ )}
@@ -838,6 +931,9 @@ export default function CropSetupPage() {
+ + {/* Enhanced AI Chatbot */} + ) } diff --git a/src/components/ChatBot.tsx b/src/components/ChatBot.tsx index c27ebfc..e137360 100644 --- a/src/components/ChatBot.tsx +++ b/src/components/ChatBot.tsx @@ -2,8 +2,8 @@ import { useState, useRef, useEffect } from 'react' import { useLanguage } from '@/contexts/LanguageContext' -import { getSmartResponse } from '@/lib/farmingKnowledge' -import { searchLocations, getLocationByPincode } from '@/lib/indianLocations' +import { AIAgentService } from '@/lib/aiAgentService' +import { VoiceService } from '@/lib/voiceService' interface Message { id: string @@ -12,11 +12,22 @@ interface Message { timestamp: Date } +interface FarmContext { + crop?: string + location?: string + farmSize?: string + state?: string + district?: string +} + export default function ChatBot() { const [isOpen, setIsOpen] = useState(false) const [messages, setMessages] = useState([]) const [inputText, setInputText] = useState('') const [isTyping, setIsTyping] = useState(false) + const [isListening, setIsListening] = useState(false) + const [isSpeaking, setIsSpeaking] = useState(false) + const [voiceSupported, setVoiceSupported] = useState(false) const messagesEndRef = useRef(null) const { t, language } = useLanguage() @@ -28,6 +39,21 @@ export default function ChatBot() { scrollToBottom() }, [messages]) + useEffect(() => { + // Initialize voice service + const initVoice = async () => { + const supported = VoiceService.initialize() + setVoiceSupported(supported) + + if (supported) { + // Request microphone permission on first load + await VoiceService.requestMicrophonePermission() + } + } + + initVoice() + }, []) + useEffect(() => { if (isOpen && messages.length === 0) { const welcomeMessage = getWelcomeMessage() @@ -55,71 +81,27 @@ export default function ChatBot() { const generateBotResponse = async (userMessage: string): Promise => { try { // Get farm data for context - let farmContext = '' + let farmContext: FarmContext = {} if (typeof window !== 'undefined') { const farmData = localStorage.getItem('farmData') if (farmData) { const parsed = JSON.parse(farmData) - farmContext = `User's farm: ${parsed.crop} crop, ${parsed.farmSize} acres, located in ${parsed.location}` - } - } - - // Try direct Gemini API call first (works without server restart) - try { - const geminiKey = 'AIzaSyBmYCbl9o23oNiA_rzro1h6A0KKpl8l580' - const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${geminiKey}`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - contents: [{ - parts: [{ - text: `You are KisanSafe AI, a friendly and expert agricultural advisor for Indian farmers. ${farmContext ? `Context: ${farmContext}.` : ''} - -Respond in ${language === 'hi' ? 'Hindi' : 'English'} language. Be helpful, practical, and encouraging. Provide specific, actionable farming advice. Keep responses concise but informative (2-4 sentences). Use emojis appropriately. - -User question: ${userMessage}` - }] - }] - }) - }) - - if (response.ok) { - const data = await response.json() - const aiResponse = data.candidates?.[0]?.content?.parts?.[0]?.text - if (aiResponse) { - return aiResponse.trim() + farmContext = { + crop: parsed.crop, + location: parsed.location, + farmSize: parsed.farmSize, + state: parsed.state, + district: parsed.district } } - } catch (directError) { - console.log('Direct Gemini call failed:', directError) } - // Fallback to server API - const response = await fetch('/api/chat', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - message: userMessage, - language: language, - context: farmContext - }) - }) - - if (response.ok) { - const data = await response.json() - if (data.response) { - return data.response - } - } - - throw new Error('All AI services failed') + // Use the new AI Agent Service + const response = await AIAgentService.generateResponse(userMessage, language, farmContext) + return response } catch (error) { - console.error('AI Error:', error) - - // Enhanced fallback responses + console.error('AI Agent Error:', error) return getEnhancedFallback(userMessage, language) } } @@ -141,12 +123,13 @@ User question: ${userMessage}` : "🤖 I'm ready to answer your farming questions! You can ask me about:\n\n• Crop care and yield improvement\n• Fertilizers, irrigation, and soil health\n• Disease and pest management\n• Market prices and selling strategies\n• Government schemes and subsidies\n• Weather alerts and farming calendar\n\nPlease ask me a specific question for detailed guidance!" } - const handleSendMessage = async () => { - if (!inputText.trim()) return + const handleSendMessage = async (messageText?: string) => { + const textToSend = messageText || inputText + if (!textToSend.trim()) return const userMessage: Message = { id: Date.now().toString(), - text: inputText, + text: textToSend, isBot: false, timestamp: new Date() } @@ -155,31 +138,86 @@ User question: ${userMessage}` setInputText('') setIsTyping(true) - // Get AI response with longer delay for better UX - setTimeout(async () => { - try { - const botResponse = await generateBotResponse(inputText) - const botMessage: Message = { - id: (Date.now() + 1).toString(), - text: botResponse, - isBot: true, - timestamp: new Date() - } - setMessages(prev => [...prev, botMessage]) - } catch (error) { - const errorMessage: Message = { - id: (Date.now() + 1).toString(), - text: language === 'hi' - ? "क्षमा करें, मुझे कुछ तकनीकी समस्या हो रही है। कृपया फिर से कोशिश करें।" - : "Sorry, I'm experiencing some technical issues. Please try again.", - isBot: true, - timestamp: new Date() - } - setMessages(prev => [...prev, errorMessage]) - } finally { - setIsTyping(false) + try { + const botResponse = await generateBotResponse(textToSend) + const botMessage: Message = { + id: (Date.now() + 1).toString(), + text: botResponse, + isBot: true, + timestamp: new Date() } - }, 1500) + setMessages(prev => [...prev, botMessage]) + + // Auto-speak response if voice is supported and enabled + if (voiceSupported && !VoiceService.isCurrentlySpeaking()) { + setTimeout(() => { + VoiceService.speak( + botResponse, + language, + () => setIsSpeaking(true), + () => setIsSpeaking(false), + (error) => console.error('Speech error:', error) + ) + }, 500) + } + + } catch (error) { + const errorMessage: Message = { + id: (Date.now() + 1).toString(), + text: language === 'hi' + ? "क्षमा करें, मुझे कुछ तकनीकी समस्या हो रही है। कृपया फिर से कोशिश करें।" + : language === 'te' + ? "క్షమించండి, నాకు కొన్ని సాంకేతిక సమస్యలు ఉన్నాయి. దయచేసి మళ్లీ ప్రయత్నించండి." + : "Sorry, I'm experiencing some technical issues. Please try again.", + isBot: true, + timestamp: new Date() + } + setMessages(prev => [...prev, errorMessage]) + } finally { + setIsTyping(false) + } + } + + const handleVoiceInput = async () => { + if (!voiceSupported) { + alert(language === 'hi' ? 'आवाज़ सुविधा उपलब्ध नहीं है' : 'Voice feature not available') + return + } + + if (isListening) { + VoiceService.stopListening() + setIsListening(false) + return + } + + try { + await VoiceService.startListening( + language, + (transcript) => { + setInputText(transcript) + setIsListening(false) + // Auto-send the voice message + setTimeout(() => handleSendMessage(transcript), 500) + }, + (error) => { + console.error('Voice error:', error) + setIsListening(false) + alert(error) + }, + () => setIsListening(true), + () => setIsListening(false) + ) + } catch (error) { + console.error('Voice input error:', error) + setIsListening(false) + } + } + + const toggleSpeech = () => { + if (isSpeaking) { + VoiceService.stopSpeaking() + setIsSpeaking(false) + } } const handleKeyPress = (e: React.KeyboardEvent) => { @@ -214,12 +252,25 @@ User question: ${userMessage}`

Farming Assistant

- +
+ {voiceSupported && ( +
+ 🎤 Voice +
+ )} + +
{/* Messages */} @@ -264,28 +315,44 @@ User question: ${userMessage}`

{language === 'hi' ? 'तुरंत पूछें:' : 'Quick Ask:'}

@@ -299,17 +366,64 @@ User question: ${userMessage}` value={inputText} onChange={(e) => setInputText(e.target.value)} onKeyPress={handleKeyPress} - placeholder={language === 'hi' ? 'अपना सवाल पूछें...' : 'Ask your farming question...'} + placeholder={language === 'hi' ? 'अपना सवाल पूछें...' : language === 'te' ? 'మీ ప్రశ్న అడగండి...' : 'Ask your farming question...'} className="flex-1 p-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-green-500 text-sm" /> + + {/* Voice Input Button */} + {voiceSupported && ( + + )} + + {/* Speech Toggle Button */} + {isSpeaking && ( + + )} + + + {/* Voice Status */} + {isListening && ( +
+
+
+ {language === 'hi' ? 'सुन रहा हूं...' : language === 'te' ? 'వింటున్నాను...' : 'Listening...'} +
+
+ )} + + {isSpeaking && ( +
+
+
+ {language === 'hi' ? 'बोल रहा हूं...' : language === 'te' ? 'మాట్లాడుతున్నాను...' : 'Speaking...'} +
+
+ )} ) diff --git a/src/components/Dashboard.tsx b/src/components/Dashboard.tsx index 1e617cc..e5c18cf 100644 --- a/src/components/Dashboard.tsx +++ b/src/components/Dashboard.tsx @@ -5,6 +5,7 @@ import YieldChart from './YieldChart' import AlertMap from './AlertMap' import AIRecommendations from './AIRecommendations' import CropHealthAnalysis from './CropHealthAnalysis' +import ChatBot from './ChatBot' import Link from 'next/link' import { useLanguage } from '@/contexts/LanguageContext' import LanguageSwitcher from './LanguageSwitcher' @@ -503,6 +504,9 @@ export default function Dashboard() { + + {/* Enhanced AI Chatbot */} + ) } \ No newline at end of file diff --git a/src/lib/aiAgentService.ts b/src/lib/aiAgentService.ts new file mode 100644 index 0000000..5356c1e --- /dev/null +++ b/src/lib/aiAgentService.ts @@ -0,0 +1,266 @@ +interface ChatMessage { + role: 'user' | 'assistant'; + content: string; + timestamp: Date; +} + +interface FarmContext { + crop?: string; + location?: string; + farmSize?: string; + state?: string; + district?: string; +} + +export class AIAgentService { + private static conversationHistory: ChatMessage[] = []; + private static readonly MAX_HISTORY = 10; + + // Hugging Face API (Free tier) + private static readonly HF_API_KEY = 'hf_your_key_here'; // Replace with actual key + private static readonly HF_MODEL = 'microsoft/DialoGPT-medium'; + + // OpenAI API (if available) + private static readonly OPENAI_API_KEY = 'sk-your_key_here'; // Replace with actual key + + // Gemini API (Free tier) + private static readonly GEMINI_API_KEY = 'AIzaSyBmYCbl9o23oNiA_rzro1h6A0KKpl8l580'; + + static addToHistory(role: 'user' | 'assistant', content: string) { + this.conversationHistory.push({ + role, + content, + timestamp: new Date() + }); + + // Keep only recent messages + if (this.conversationHistory.length > this.MAX_HISTORY) { + this.conversationHistory = this.conversationHistory.slice(-this.MAX_HISTORY); + } + } + + static getContextualPrompt(userMessage: string, language: string, farmContext?: FarmContext): string { + const contextInfo = farmContext ? + `Farm Context: Growing ${farmContext.crop} on ${farmContext.farmSize} acres in ${farmContext.location}, ${farmContext.state}. ` : ''; + + const conversationContext = this.conversationHistory.length > 0 ? + `Previous conversation:\n${this.conversationHistory.map(msg => `${msg.role}: ${msg.content}`).join('\n')}\n\n` : ''; + + const systemPrompt = `You are KisanSafe AI, an expert agricultural advisor for Indian farmers. You provide practical, actionable farming advice. + +${contextInfo}${conversationContext} + +Guidelines: +- Respond in ${language === 'hi' ? 'Hindi (Devanagari script)' : language === 'te' ? 'Telugu' : 'English'} language +- Be friendly, encouraging, and use farmer-friendly language +- Provide specific, practical advice with numbers/quantities when relevant +- Use appropriate emojis (🌾🚜💧🌱🌦️💰) +- Keep responses concise but informative (3-5 sentences) +- Include warnings about common mistakes +- Suggest seasonal timing when relevant +- Reference Indian farming practices and conditions + +Current user question: ${userMessage}`; + + return systemPrompt; + } + + static async generateResponse(userMessage: string, language: string = 'en', farmContext?: FarmContext): Promise { + // Add user message to history + this.addToHistory('user', userMessage); + + try { + // Try Gemini API first (most reliable for Indian languages) + const geminiResponse = await this.tryGeminiAPI(userMessage, language, farmContext); + if (geminiResponse) { + this.addToHistory('assistant', geminiResponse); + return geminiResponse; + } + + // Fallback to OpenAI if available + const openaiResponse = await this.tryOpenAI(userMessage, language, farmContext); + if (openaiResponse) { + this.addToHistory('assistant', openaiResponse); + return openaiResponse; + } + + // Fallback to Hugging Face + const hfResponse = await this.tryHuggingFace(userMessage, language, farmContext); + if (hfResponse) { + this.addToHistory('assistant', hfResponse); + return hfResponse; + } + + // Ultimate fallback to rule-based responses + const fallbackResponse = this.getIntelligentFallback(userMessage, language, farmContext); + this.addToHistory('assistant', fallbackResponse); + return fallbackResponse; + + } catch (error) { + console.error('AI Agent Error:', error); + const errorResponse = this.getIntelligentFallback(userMessage, language, farmContext); + this.addToHistory('assistant', errorResponse); + return errorResponse; + } + } + + private static async tryGeminiAPI(userMessage: string, language: string, farmContext?: FarmContext): Promise { + try { + const prompt = this.getContextualPrompt(userMessage, language, farmContext); + + const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${this.GEMINI_API_KEY}`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + contents: [{ + parts: [{ text: prompt }] + }], + generationConfig: { + temperature: 0.7, + topK: 40, + topP: 0.95, + maxOutputTokens: 300 + } + }) + }); + + if (response.ok) { + const data = await response.json(); + const aiResponse = data.candidates?.[0]?.content?.parts?.[0]?.text; + if (aiResponse) { + return aiResponse.trim(); + } + } + } catch (error) { + console.log('Gemini API failed:', error); + } + return null; + } + + private static async tryOpenAI(userMessage: string, language: string, farmContext?: FarmContext): Promise { + try { + const prompt = this.getContextualPrompt(userMessage, language, farmContext); + + const response = await fetch('https://api.openai.com/v1/chat/completions', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${this.OPENAI_API_KEY}` + }, + body: JSON.stringify({ + model: 'gpt-3.5-turbo', + messages: [{ role: 'user', content: prompt }], + max_tokens: 300, + temperature: 0.7 + }) + }); + + if (response.ok) { + const data = await response.json(); + return data.choices?.[0]?.message?.content?.trim(); + } + } catch (error) { + console.log('OpenAI API failed:', error); + } + return null; + } + + private static async tryHuggingFace(userMessage: string, language: string, farmContext?: FarmContext): Promise { + try { + const response = await fetch('https://api-inference.huggingface.co/models/microsoft/DialoGPT-medium', { + method: 'POST', + headers: { + 'Authorization': `Bearer ${this.HF_API_KEY}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + inputs: userMessage, + parameters: { + max_length: 200, + temperature: 0.7 + } + }) + }); + + if (response.ok) { + const data = await response.json(); + return data[0]?.generated_text?.trim(); + } + } catch (error) { + console.log('Hugging Face API failed:', error); + } + return null; + } + + private static getIntelligentFallback(userMessage: string, language: string, farmContext?: FarmContext): string { + const lowerInput = userMessage.toLowerCase(); + const isHindi = language === 'hi'; + const isTelugu = language === 'te'; + + // Crop-specific responses + if (lowerInput.includes('rice') || lowerInput.includes('धान') || lowerInput.includes('వరి')) { + if (isHindi) { + return "🌾 **धान की खेती के लिए सुझाव:**\n\n• **मिट्टी**: दोमट मिट्टी सबसे अच्छी\n• **पानी**: 3-5 सेमी खड़ा पानी रखें\n• **बीज**: 20-25 किलो/हेक्टेयर\n• **खाद**: NPK 120:60:40 किलो/हेक्टेयर\n• **समय**: जून-जुलाई में रोपाई\n\n⚠️ **सावधानी**: ज्यादा पानी से जड़ सड़न हो सकती है!"; + } else if (isTelugu) { + return "🌾 **వరి సాగుకు సూచనలు:**\n\n• **నేల**: మట్టి నేల ఉత్తమం\n• **నీరు**: 3-5 సెం.మీ నిలిచిన నీరు\n• **విత్తనాలు**: 20-25 కిలోలు/హెక్టారు\n• **ఎరువులు**: NPK 120:60:40 కిలోలు/హెక్టారు\n• **సమయం**: జూన్-జూలైలో నాట్లు\n\n⚠️ **జాగ్రత్త**: ఎక్కువ నీరు వేర్లు కుళ్ళిపోవచ్చు!"; + } else { + return "🌾 **Rice Cultivation Tips:**\n\n• **Soil**: Loamy soil is best\n• **Water**: Maintain 3-5cm standing water\n• **Seeds**: 20-25 kg per hectare\n• **Fertilizer**: NPK 120:60:40 kg/hectare\n• **Timing**: Transplant in June-July\n\n⚠️ **Warning**: Excess water can cause root rot!"; + } + } + + // Fertilizer responses + if (lowerInput.includes('fertilizer') || lowerInput.includes('खाद') || lowerInput.includes('ఎరువు')) { + if (isHindi) { + return "🌱 **खाद का सही उपयोग:**\n\n• **मिट्टी जांच**: पहले pH और NPK जांचें\n• **जैविक खाद**: 5-10 टन गोबर खाद/हेक्टेयर\n• **रासायनिक खाद**: फसल के अनुसार NPK अनुपात\n• **समय**: बुआई के समय + 30-45 दिन बाद\n• **सूक्ष्म तत्व**: जिंक, आयरन, बोरॉन\n\n💡 **टिप**: ज्यादा खाद नुकसानदायक है!"; + } else if (isTelugu) { + return "🌱 **ఎరువుల సరైన వాడకం:**\n\n• **నేల పరీక్ష**: మొదట pH మరియు NPK చూడండి\n• **సేంద్రీయ ఎరువు**: 5-10 టన్నుల పేడ/హెక్టారు\n• **రసాయన ఎరువు**: పంట ప్రకారం NPK నిష్పత్తి\n• **సమయం**: విత్తనల సమయం + 30-45 రోజుల తర్వాత\n• **సూక్ష్మ పోషకాలు**: జింక్, ఇనుము, బోరాన్\n\n💡 **చిట్కా**: ఎక్కువ ఎరువు హానికరం!"; + } else { + return "🌱 **Smart Fertilizer Guide:**\n\n• **Soil Test**: Check pH and NPK levels first\n• **Organic**: 5-10 tons farmyard manure/hectare\n• **Chemical**: NPK ratio based on crop needs\n• **Timing**: Base dose + top dressing after 30-45 days\n• **Micronutrients**: Zinc, Iron, Boron as needed\n\n💡 **Tip**: Over-fertilization damages crops and soil!"; + } + } + + // Weather/climate responses + if (lowerInput.includes('weather') || lowerInput.includes('मौसम') || lowerInput.includes('వాతావరణం')) { + if (isHindi) { + return "🌦️ **मौसम आधारित खेती:**\n\n• **बारिश**: IMD का पूर्वानुमान देखें\n• **तापमान**: फसल के अनुसार बुआई करें\n• **आर्द्रता**: बीमारी से बचाव के लिए\n• **हवा**: तेज हवा से फसल सुरक्षा\n\n📱 **ऐप**: मौसम ऐप डाउनलोड करें!"; + } else if (isTelugu) { + return "🌦️ **వాతావరణ ఆధారిత వ్యవసాయం:**\n\n• **వర్షం**: IMD అంచనాలు చూడండి\n• **ఉష్ణోగ్రత**: పంట ప్రకారం విత్తనలు\n• **తేమ**: వ్యాధుల నివారణకు\n• **గాలి**: గట్టి గాలుల నుండి పంట రక్షణ\n\n📱 **యాప్**: వాతావరణ యాప్ డౌన్లోడ్ చేయండి!"; + } else { + return "🌦️ **Weather-Smart Farming:**\n\n• **Rainfall**: Check IMD forecasts\n• **Temperature**: Time sowing according to crop needs\n• **Humidity**: Monitor for disease prevention\n• **Wind**: Protect crops from strong winds\n\n📱 **Apps**: Download weather apps for alerts!"; + } + } + + // Market price responses + if (lowerInput.includes('price') || lowerInput.includes('भाव') || lowerInput.includes('ధర')) { + if (isHindi) { + return "💰 **बाजार भाव की जानकारी:**\n\n• **eNAM पोर्टल**: ऑनलाइन भाव देखें\n• **मंडी**: स्थानीय मंडी में जाकर पूछें\n• **ऐप**: Kisan Suvidha, AgriMarket ऐप\n• **समय**: सुबह 6-10 बजे भाव अच्छे\n\n📈 **टिप**: त्योहारों के समय भाव बढ़ते हैं!"; + } else if (isTelugu) { + return "💰 **మార్కెట్ ధరల సమాచారం:**\n\n• **eNAM పోర్టల్**: ఆన్లైన్ ధరలు చూడండి\n• **మార్కెట్**: స్థానిక మార్కెట్లో అడగండి\n• **యాప్**: Kisan Suvidha, AgriMarket యాప్\n• **సమయం**: ఉదయం 6-10 గంటలకు మంచి ధరలు\n\n📈 **చిట్కా**: పండుగల సమయంలో ధరలు పెరుగుతాయి!"; + } else { + return "💰 **Market Price Information:**\n\n• **eNAM Portal**: Check online prices\n• **Local Mandi**: Visit nearby markets\n• **Apps**: Kisan Suvidha, AgriMarket apps\n• **Timing**: Morning 6-10 AM for better rates\n\n📈 **Tip**: Prices rise during festivals!"; + } + } + + // Default response with context + const contextResponse = farmContext ? + (isHindi ? `आपकी ${farmContext.crop} की फसल के लिए` : + isTelugu ? `మీ ${farmContext.crop} పంట కోసం` : + `For your ${farmContext.crop} crop`) : ''; + + if (isHindi) { + return `🤖 **किसानसेफ AI यहां है!** ${contextResponse}\n\nमैं आपकी मदद कर सकता हूं:\n• फसल की देखभाल और पैदावार\n• खाद-पानी और मिट्टी की जानकारी\n• बीमारी-कीट का इलाज\n• मौसम और बाजार भाव\n• सरकारी योजनाएं\n\nकृपया अपना सवाल विस्तार से पूछें! 🌾`; + } else if (isTelugu) { + return `🤖 **కిసాన్సేఫ్ AI ఇక్కడ ఉంది!** ${contextResponse}\n\nనేను మీకు సహాయం చేయగలను:\n• పంట సంరక్షణ మరియు దిగుబడి\n• ఎరువులు-నీరు మరియు నేల సమాచారం\n• వ్యాధి-కీటకాల చికిత్స\n• వాతావరణం మరియు మార్కెట్ ధరలు\n• ప్రభుత్వ పథకాలు\n\nదయచేసి మీ ప్రశ్నను వివరంగా అడగండి! 🌾`; + } else { + return `🤖 **KisanSafe AI at your service!** ${contextResponse}\n\nI can help you with:\n• Crop care and yield improvement\n• Fertilizers, irrigation, and soil health\n• Disease and pest management\n• Weather updates and market prices\n• Government schemes and subsidies\n\nPlease ask me a specific farming question! 🌾`; + } + } + + static clearHistory() { + this.conversationHistory = []; + } + + static getConversationHistory(): ChatMessage[] { + return [...this.conversationHistory]; + } +} \ No newline at end of file diff --git a/src/lib/cropValidationService.ts b/src/lib/cropValidationService.ts new file mode 100644 index 0000000..4b8f8d7 --- /dev/null +++ b/src/lib/cropValidationService.ts @@ -0,0 +1,337 @@ +// Crop suitability mapping for Indian regions +export interface CropSuitability { + crop: string; + suitableStates: string[]; + suitableRegions: string[]; + climateRequirements: string; +} + +const cropSuitabilityData: CropSuitability[] = [ + // Cereals + { + crop: 'rice', + suitableStates: ['West Bengal', 'Uttar Pradesh', 'Punjab', 'Tamil Nadu', 'Andhra Pradesh', 'Bihar', 'Odisha', 'Assam', 'Haryana', 'Karnataka', 'Jharkhand', 'Chhattisgarh'], + suitableRegions: ['Eastern India', 'Northern Plains', 'Southern India', 'Coastal Areas'], + climateRequirements: 'High rainfall, warm climate, flooded fields' + }, + { + crop: 'wheat', + suitableStates: ['Uttar Pradesh', 'Punjab', 'Haryana', 'Madhya Pradesh', 'Rajasthan', 'Bihar', 'Gujarat', 'Maharashtra'], + suitableRegions: ['Northern Plains', 'Central India', 'Western India'], + climateRequirements: 'Cool winters, moderate rainfall, well-drained soil' + }, + { + crop: 'corn', + suitableStates: ['Karnataka', 'Andhra Pradesh', 'Tamil Nadu', 'Maharashtra', 'Madhya Pradesh', 'Uttar Pradesh', 'Bihar', 'Rajasthan'], + suitableRegions: ['Southern India', 'Central India', 'Western India'], + climateRequirements: 'Warm climate, moderate rainfall' + }, + { + crop: 'barley', + suitableStates: ['Rajasthan', 'Uttar Pradesh', 'Madhya Pradesh', 'Haryana', 'Punjab', 'Gujarat'], + suitableRegions: ['Northern Plains', 'Western India', 'Central India'], + climateRequirements: 'Cool dry climate, low to moderate rainfall' + }, + { + crop: 'millet', + suitableStates: ['Rajasthan', 'Maharashtra', 'Karnataka', 'Andhra Pradesh', 'Tamil Nadu', 'Gujarat', 'Madhya Pradesh'], + suitableRegions: ['Arid and Semi-arid regions', 'Deccan Plateau'], + climateRequirements: 'Drought-resistant, low rainfall areas' + }, + + // Cash Crops + { + crop: 'cotton', + suitableStates: ['Maharashtra', 'Gujarat', 'Andhra Pradesh', 'Karnataka', 'Madhya Pradesh', 'Punjab', 'Haryana', 'Rajasthan'], + suitableRegions: ['Western India', 'Central India', 'Southern India'], + climateRequirements: 'Hot climate, moderate rainfall, black cotton soil' + }, + { + crop: 'sugarcane', + suitableStates: ['Uttar Pradesh', 'Maharashtra', 'Karnataka', 'Tamil Nadu', 'Andhra Pradesh', 'Gujarat', 'Bihar', 'Haryana', 'Punjab'], + suitableRegions: ['Northern Plains', 'Western India', 'Southern India'], + climateRequirements: 'Hot humid climate, high rainfall, fertile soil' + }, + { + crop: 'tea', + suitableStates: ['Assam', 'West Bengal', 'Tamil Nadu', 'Kerala', 'Karnataka', 'Himachal Pradesh', 'Uttarakhand'], + suitableRegions: ['Northeastern India', 'Hill Stations', 'Western Ghats'], + climateRequirements: 'High rainfall, cool climate, hilly terrain' + }, + { + crop: 'coffee', + suitableStates: ['Karnataka', 'Kerala', 'Tamil Nadu', 'Andhra Pradesh'], + suitableRegions: ['Western Ghats', 'Southern Hills'], + climateRequirements: 'High rainfall, cool climate, hilly areas' + }, + + // Pulses + { + crop: 'chickpea', + suitableStates: ['Madhya Pradesh', 'Rajasthan', 'Maharashtra', 'Uttar Pradesh', 'Karnataka', 'Andhra Pradesh', 'Gujarat'], + suitableRegions: ['Central India', 'Western India', 'Northern Plains'], + climateRequirements: 'Cool dry climate, moderate rainfall' + }, + { + crop: 'lentil', + suitableStates: ['Uttar Pradesh', 'Madhya Pradesh', 'Bihar', 'West Bengal', 'Jharkhand', 'Chhattisgarh'], + suitableRegions: ['Northern Plains', 'Eastern India', 'Central India'], + climateRequirements: 'Cool climate, moderate rainfall' + }, + { + crop: 'soybean', + suitableStates: ['Madhya Pradesh', 'Maharashtra', 'Rajasthan', 'Karnataka', 'Andhra Pradesh'], + suitableRegions: ['Central India', 'Western India', 'Deccan Plateau'], + climateRequirements: 'Warm climate, moderate to high rainfall' + }, + + // Vegetables + { + crop: 'tomato', + suitableStates: ['Andhra Pradesh', 'Karnataka', 'Odisha', 'West Bengal', 'Maharashtra', 'Madhya Pradesh', 'Gujarat', 'Tamil Nadu'], + suitableRegions: ['All regions with proper irrigation'], + climateRequirements: 'Warm climate, well-drained soil, irrigation' + }, + { + crop: 'potato', + suitableStates: ['Uttar Pradesh', 'West Bengal', 'Bihar', 'Punjab', 'Haryana', 'Madhya Pradesh', 'Gujarat'], + suitableRegions: ['Northern Plains', 'Eastern India', 'Western India'], + climateRequirements: 'Cool climate, well-drained soil' + }, + { + crop: 'onion', + suitableStates: ['Maharashtra', 'Karnataka', 'Gujarat', 'Madhya Pradesh', 'Rajasthan', 'Andhra Pradesh', 'Tamil Nadu'], + suitableRegions: ['Western India', 'Central India', 'Southern India'], + climateRequirements: 'Moderate climate, well-drained soil' + }, + { + crop: 'cabbage', + suitableStates: ['West Bengal', 'Odisha', 'Bihar', 'Uttar Pradesh', 'Maharashtra', 'Karnataka', 'Tamil Nadu'], + suitableRegions: ['Eastern India', 'Northern Plains', 'Hill Stations'], + climateRequirements: 'Cool climate, high humidity' + }, + + // Fruits + { + crop: 'mango', + suitableStates: ['Uttar Pradesh', 'Andhra Pradesh', 'Karnataka', 'Gujarat', 'Bihar', 'West Bengal', 'Tamil Nadu', 'Maharashtra'], + suitableRegions: ['Northern Plains', 'Southern India', 'Western India'], + climateRequirements: 'Hot climate, moderate rainfall, well-drained soil' + }, + { + crop: 'apple', + suitableStates: ['Himachal Pradesh', 'Jammu and Kashmir', 'Uttarakhand', 'Arunachal Pradesh'], + suitableRegions: ['Hill Stations', 'Himalayan Region'], + climateRequirements: 'Cool climate, high altitude, cold winters' + }, + { + crop: 'banana', + suitableStates: ['Tamil Nadu', 'Maharashtra', 'Gujarat', 'Andhra Pradesh', 'Karnataka', 'Kerala', 'West Bengal', 'Assam'], + suitableRegions: ['Southern India', 'Western India', 'Eastern India', 'Coastal Areas'], + climateRequirements: 'Hot humid climate, high rainfall' + }, + { + crop: 'grapes', + suitableStates: ['Maharashtra', 'Karnataka', 'Andhra Pradesh', 'Tamil Nadu', 'Punjab', 'Haryana'], + suitableRegions: ['Western India', 'Southern India', 'Northern Plains'], + climateRequirements: 'Hot dry climate, moderate rainfall, well-drained soil' + }, + + // Additional common crops + { + crop: 'mustard', + suitableStates: ['Rajasthan', 'Haryana', 'Punjab', 'Uttar Pradesh', 'Madhya Pradesh', 'Gujarat', 'West Bengal'], + suitableRegions: ['Northern Plains', 'Western India', 'Eastern India'], + climateRequirements: 'Cool dry climate, moderate rainfall' + }, + { + crop: 'groundnut', + suitableStates: ['Gujarat', 'Andhra Pradesh', 'Tamil Nadu', 'Karnataka', 'Maharashtra', 'Rajasthan'], + suitableRegions: ['Western India', 'Southern India', 'Deccan Plateau'], + climateRequirements: 'Warm climate, moderate rainfall, well-drained sandy soil' + }, + { + crop: 'sunflower', + suitableStates: ['Karnataka', 'Andhra Pradesh', 'Maharashtra', 'Tamil Nadu', 'Bihar', 'Odisha'], + suitableRegions: ['Southern India', 'Western India', 'Eastern India'], + climateRequirements: 'Warm climate, moderate rainfall, well-drained soil' + }, + { + crop: 'jute', + suitableStates: ['West Bengal', 'Bihar', 'Assam', 'Odisha', 'Meghalaya'], + suitableRegions: ['Eastern India', 'Northeastern India'], + climateRequirements: 'Hot humid climate, high rainfall, alluvial soil' + }, + { + crop: 'coconut', + suitableStates: ['Kerala', 'Tamil Nadu', 'Karnataka', 'Andhra Pradesh', 'Odisha', 'West Bengal', 'Goa'], + suitableRegions: ['Coastal Areas', 'Southern India', 'Eastern Coast'], + climateRequirements: 'Hot humid climate, high rainfall, coastal areas' + }, + { + crop: 'turmeric', + suitableStates: ['Andhra Pradesh', 'Tamil Nadu', 'Karnataka', 'Odisha', 'West Bengal', 'Maharashtra'], + suitableRegions: ['Southern India', 'Eastern India', 'Western Ghats'], + climateRequirements: 'Hot humid climate, high rainfall, well-drained soil' + }, + { + crop: 'ginger', + suitableStates: ['Kerala', 'Karnataka', 'Assam', 'Meghalaya', 'Arunachal Pradesh', 'West Bengal'], + suitableRegions: ['Western Ghats', 'Northeastern India', 'Hill Stations'], + climateRequirements: 'Hot humid climate, high rainfall, hilly terrain' + }, + { + crop: 'cardamom', + suitableStates: ['Kerala', 'Karnataka', 'Tamil Nadu'], + suitableRegions: ['Western Ghats', 'Hill Stations'], + climateRequirements: 'Cool humid climate, high rainfall, high altitude' + }, + { + crop: 'black pepper', + suitableStates: ['Kerala', 'Karnataka', 'Tamil Nadu'], + suitableRegions: ['Western Ghats', 'Southern Hills'], + climateRequirements: 'Hot humid climate, high rainfall, hilly areas' + } +]; + +export class CropValidationService { + static validateCropSuitability(cropName: string, state: string, district?: string): { + isSuitable: boolean; + message: string; + confidence: 'high' | 'medium' | 'low'; + recommendations?: string[]; + } { + if (!cropName || !state) { + return { + isSuitable: false, + message: 'Please provide both crop and location information', + confidence: 'low' + }; + } + + const normalizedCrop = cropName.toLowerCase().trim(); + const normalizedState = state.trim(); + + // Find crop data with better matching + const cropData = cropSuitabilityData.find(crop => { + const cropName = crop.crop.toLowerCase(); + + // Exact match + if (cropName === normalizedCrop) return true; + + // Partial matches + if (cropName.includes(normalizedCrop) || normalizedCrop.includes(cropName)) return true; + + // Handle common variations + const variations: { [key: string]: string[] } = { + 'maize': ['corn'], + 'corn': ['maize'], + 'groundnut': ['peanut'], + 'peanut': ['groundnut'], + 'gram': ['chickpea'], + 'chickpea': ['gram', 'chana'], + 'chana': ['chickpea', 'gram'], + 'arhar': ['pigeon pea'], + 'tur': ['pigeon pea'], + 'moong': ['mung bean'], + 'urad': ['black gram'], + 'masoor': ['lentil'], + 'sarson': ['mustard'], + 'til': ['sesame'], + 'sesame': ['til'], + 'jowar': ['sorghum'], + 'sorghum': ['jowar'], + 'bajra': ['millet'], + 'ragi': ['finger millet'], + 'paddy': ['rice'], + 'rice': ['paddy'], + 'sugarcane': ['sugar cane'], + 'sugar cane': ['sugarcane'] + }; + + // Check variations + const cropVariations = variations[cropName] || []; + const inputVariations = variations[normalizedCrop] || []; + + return cropVariations.includes(normalizedCrop) || inputVariations.includes(cropName); + }); + + if (!cropData) { + return { + isSuitable: true, + message: `${cropName} cultivation data not available. Please consult local agricultural experts.`, + confidence: 'low', + recommendations: ['Consult local agricultural extension officer', 'Check with nearby farmers', 'Contact state agriculture department'] + }; + } + + // Check if state is suitable + const isSuitableState = cropData.suitableStates.some(suitableState => + normalizedState.toLowerCase().includes(suitableState.toLowerCase()) || + suitableState.toLowerCase().includes(normalizedState.toLowerCase()) + ); + + if (isSuitableState) { + return { + isSuitable: true, + message: `✅ ${cropName.charAt(0).toUpperCase() + cropName.slice(1)} is suitable for cultivation in ${state}.`, + confidence: 'high', + recommendations: [ + `Climate: ${cropData.climateRequirements}`, + 'Follow recommended planting seasons', + 'Ensure proper soil preparation', + 'Use quality seeds from certified sources' + ] + }; + } else { + // Check if it's a neighboring or climatically similar region + const partialMatch = cropData.suitableStates.some(suitableState => { + const stateParts = normalizedState.toLowerCase().split(' '); + const suitableParts = suitableState.toLowerCase().split(' '); + return stateParts.some(part => suitableParts.some(suitablePart => + part.includes(suitablePart) || suitablePart.includes(part) + )); + }); + + if (partialMatch) { + return { + isSuitable: true, + message: `⚠️ ${cropName.charAt(0).toUpperCase() + cropName.slice(1)} may be suitable for ${state} with proper care.`, + confidence: 'medium', + recommendations: [ + 'Consult local agricultural experts', + 'Consider climate-adapted varieties', + 'Ensure proper irrigation and soil management', + `Requirements: ${cropData.climateRequirements}` + ] + }; + } + + return { + isSuitable: false, + message: `⚠️ ${cropName.charAt(0).toUpperCase() + cropName.slice(1)} may not be suitable for ${state}'s climate conditions.`, + confidence: 'high', + recommendations: [ + `Better suited for: ${cropData.suitableStates.slice(0, 3).join(', ')}`, + `Climate needs: ${cropData.climateRequirements}`, + 'Consider alternative crops suitable for your region', + 'Consult agricultural extension services' + ] + }; + } + } + + static getSuitableCropsForState(state: string): string[] { + const normalizedState = state.toLowerCase().trim(); + + return cropSuitabilityData + .filter(cropData => + cropData.suitableStates.some(suitableState => + normalizedState.includes(suitableState.toLowerCase()) || + suitableState.toLowerCase().includes(normalizedState) + ) + ) + .map(cropData => cropData.crop) + .sort(); + } +} \ No newline at end of file diff --git a/src/lib/voiceService.ts b/src/lib/voiceService.ts new file mode 100644 index 0000000..904344e --- /dev/null +++ b/src/lib/voiceService.ts @@ -0,0 +1,210 @@ +export class VoiceService { + private static recognition: SpeechRecognition | null = null; + private static synthesis: SpeechSynthesis | null = null; + private static isListening = false; + + static initialize(): boolean { + if (typeof window === 'undefined') return false; + + // Initialize Speech Recognition + const SpeechRecognition = window.SpeechRecognition || (window as any).webkitSpeechRecognition; + if (SpeechRecognition) { + this.recognition = new SpeechRecognition(); + this.recognition.continuous = false; + this.recognition.interimResults = false; + } + + // Initialize Speech Synthesis + if ('speechSynthesis' in window) { + this.synthesis = window.speechSynthesis; + } + + return !!(this.recognition && this.synthesis); + } + + static isSupported(): boolean { + return !!(this.recognition && this.synthesis); + } + + static async startListening( + language: string = 'en-IN', + onResult: (text: string) => void, + onError: (error: string) => void, + onStart?: () => void, + onEnd?: () => void + ): Promise { + if (!this.recognition || this.isListening) return; + + // Set language based on user preference + const languageMap: { [key: string]: string } = { + 'en': 'en-IN', + 'hi': 'hi-IN', + 'te': 'te-IN', + 'ta': 'ta-IN', + 'bn': 'bn-IN', + 'gu': 'gu-IN' + }; + + this.recognition.lang = languageMap[language] || 'en-IN'; + this.isListening = true; + + this.recognition.onstart = () => { + console.log('Voice recognition started'); + onStart?.(); + }; + + this.recognition.onresult = (event) => { + const transcript = event.results[0][0].transcript; + console.log('Voice input:', transcript); + onResult(transcript); + }; + + this.recognition.onerror = (event) => { + console.error('Voice recognition error:', event.error); + this.isListening = false; + + let errorMessage = 'Voice recognition failed'; + switch (event.error) { + case 'no-speech': + errorMessage = 'No speech detected. Please try again.'; + break; + case 'audio-capture': + errorMessage = 'Microphone not accessible. Please check permissions.'; + break; + case 'not-allowed': + errorMessage = 'Microphone permission denied. Please allow microphone access.'; + break; + case 'network': + errorMessage = 'Network error. Please check your internet connection.'; + break; + default: + errorMessage = `Voice recognition error: ${event.error}`; + } + + onError(errorMessage); + }; + + this.recognition.onend = () => { + console.log('Voice recognition ended'); + this.isListening = false; + onEnd?.(); + }; + + try { + this.recognition.start(); + } catch (error) { + this.isListening = false; + onError('Failed to start voice recognition'); + } + } + + static stopListening(): void { + if (this.recognition && this.isListening) { + this.recognition.stop(); + this.isListening = false; + } + } + + static speak( + text: string, + language: string = 'en-IN', + onStart?: () => void, + onEnd?: () => void, + onError?: (error: string) => void + ): void { + if (!this.synthesis) { + onError?.('Speech synthesis not supported'); + return; + } + + // Cancel any ongoing speech + this.synthesis.cancel(); + + const utterance = new SpeechSynthesisUtterance(text); + + // Set language and voice + const languageMap: { [key: string]: string } = { + 'en': 'en-IN', + 'hi': 'hi-IN', + 'te': 'te-IN', + 'ta': 'ta-IN', + 'bn': 'bn-IN', + 'gu': 'gu-IN' + }; + + utterance.lang = languageMap[language] || 'en-IN'; + utterance.rate = 0.9; + utterance.pitch = 1.0; + utterance.volume = 0.8; + + // Try to find a suitable voice + const voices = this.synthesis.getVoices(); + const preferredVoice = voices.find(voice => + voice.lang.startsWith(utterance.lang.split('-')[0]) && + (voice.name.includes('Female') || voice.name.includes('Google')) + ); + + if (preferredVoice) { + utterance.voice = preferredVoice; + } + + utterance.onstart = () => { + console.log('Speech synthesis started'); + onStart?.(); + }; + + utterance.onend = () => { + console.log('Speech synthesis ended'); + onEnd?.(); + }; + + utterance.onerror = (event) => { + console.error('Speech synthesis error:', event.error); + onError?.(`Speech synthesis failed: ${event.error}`); + }; + + this.synthesis.speak(utterance); + } + + static stopSpeaking(): void { + if (this.synthesis) { + this.synthesis.cancel(); + } + } + + static getAvailableVoices(): SpeechSynthesisVoice[] { + if (!this.synthesis) return []; + return this.synthesis.getVoices(); + } + + static isCurrentlyListening(): boolean { + return this.isListening; + } + + static isCurrentlySpeaking(): boolean { + return this.synthesis ? this.synthesis.speaking : false; + } + + // Utility method to get microphone permission + static async requestMicrophonePermission(): Promise { + try { + const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); + stream.getTracks().forEach(track => track.stop()); // Stop the stream immediately + return true; + } catch (error) { + console.error('Microphone permission denied:', error); + return false; + } + } + + // Method to check if microphone is available + static async isMicrophoneAvailable(): Promise { + try { + const devices = await navigator.mediaDevices.enumerateDevices(); + return devices.some(device => device.kind === 'audioinput'); + } catch (error) { + console.error('Error checking microphone availability:', error); + return false; + } + } +} \ No newline at end of file diff --git a/test-ai-agent.html b/test-ai-agent.html new file mode 100644 index 0000000..6fdc25c --- /dev/null +++ b/test-ai-agent.html @@ -0,0 +1,228 @@ + + + + + + KisanSafe AI Agent Test + + + +
+

🌾 KisanSafe AI Agent - Test Interface

+ +
+

🤖 Enhanced AI Features

+
    +
  • Generative AI Integration - Gemini API with OpenAI fallback
  • +
  • Context Awareness - Remembers conversation history
  • +
  • Multilingual Support - English, Hindi, Telugu
  • +
  • Voice Input/Output - Speech recognition and synthesis
  • +
  • Crop Validation - Smart crop-location suitability checks
  • +
  • Farmer-Friendly Responses - Practical, actionable advice
  • +
+
+ +
+

🎯 Test Scenarios

+

Try asking these questions to test the AI agent:

+
    +
  • Crop Advice: "Can I grow rice in Rajasthan?"
  • +
  • Fertilizer Help: "Which fertilizer is good for cotton?"
  • +
  • Weather Queries: "What's the best time to plant wheat?"
  • +
  • Market Prices: "Tell me about today's market prices"
  • +
  • Disease Control: "How to treat tomato blight?"
  • +
  • Hindi Questions: "धान की खेती कैसे करें?"
  • +
  • Telugu Questions: "వరి సాగు ఎలా చేయాలి?"
  • +
+
+ +
+
+ 🌾 KisanSafe AI Agent Ready!
+ I'm your intelligent farming assistant. I can help you with: +
    +
  • Crop yield predictions & recommendations
  • +
  • Weather alerts & farming tips
  • +
  • Market prices & selling strategies
  • +
  • Disease identification & treatment
  • +
  • Government schemes & subsidies
  • +
  • Multilingual support (English, Hindi, Telugu)
  • +
+ Ask me anything about farming! 🚜 +
+
+ +
+ + + +
+ +
+

🔧 Implementation Details

+
    +
  • AI Service: AIAgentService with Gemini API integration
  • +
  • Voice Service: Web Speech API for recognition and synthesis
  • +
  • Validation Service: CropValidationService for location-crop matching
  • +
  • Context Management: Conversation history with 10-message limit
  • +
  • Fallback System: Rule-based responses when AI APIs fail
  • +
  • Responsive UI: Fixed bottom-right chatbot with green theme
  • +
+
+
+ + + + \ No newline at end of file