Spaces:
Sleeping
Sleeping
| import re | |
| import random | |
| import gradio as gr | |
| import json | |
| import os | |
| from typing import Dict, List, Any | |
| # Try to import AI libraries | |
| try: | |
| import openai | |
| OPENAI_AVAILABLE = True | |
| except ImportError: | |
| OPENAI_AVAILABLE = False | |
| try: | |
| from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline | |
| import torch | |
| TRANSFORMERS_AVAILABLE = True | |
| except ImportError: | |
| TRANSFORMERS_AVAILABLE = False | |
| # Try to import sentence transformers for semantic search | |
| try: | |
| from sentence_transformers import SentenceTransformer | |
| import numpy as np | |
| SENTENCE_TRANSFORMERS_AVAILABLE = True | |
| except ImportError: | |
| SENTENCE_TRANSFORMERS_AVAILABLE = False | |
| class AgriBot: | |
| def __init__(self): | |
| self.name = "AgriBot" | |
| self.user_name = "" | |
| self.conversation_history = [] | |
| self.model_loaded = False | |
| self.generator = None | |
| self.tokenizer = None | |
| self.model = None | |
| self.embedding_model = None | |
| # Load agricultural data from JSON | |
| self.agricultural_data = self.load_agricultural_data() | |
| self.knowledge_base = self.prepare_knowledge_base() | |
| # Initialize embedding model for semantic search | |
| self.init_embedding_model() | |
| def load_agricultural_data(self) -> Dict: | |
| """Load agricultural data from JSON file""" | |
| try: | |
| json_path = os.path.join(os.path.dirname(__file__), 'agricultural_data.json') | |
| with open(json_path, 'r', encoding='utf-8') as file: | |
| return json.load(file) | |
| except FileNotFoundError: | |
| print("Agricultural data file not found. Using basic data.") | |
| return self.get_fallback_data() | |
| except json.JSONDecodeError: | |
| print("Error reading agricultural data. Using basic data.") | |
| return self.get_fallback_data() | |
| def get_fallback_data(self) -> Dict: | |
| """Fallback data if JSON file is not available""" | |
| return { | |
| "crops": { | |
| "rice": { | |
| "season": "Kharif (June-November)", | |
| "water_requirement": "High water requirement, flooded fields", | |
| "soil": {"type": "Clay or loamy soil with good water retention"}, | |
| "fertilizer": {"npk": "120:60:40 kg/ha"}, | |
| "diseases": [{"name": "Blast"}, {"name": "Brown spot"}], | |
| "pests": [{"name": "Stem borer"}, {"name": "Brown planthopper"}], | |
| "market_uses": ["Staple food", "Rice flour"] | |
| } | |
| } | |
| } | |
| def prepare_knowledge_base(self) -> List[Dict]: | |
| """Prepare searchable knowledge base from agricultural data""" | |
| knowledge_items = [] | |
| # Process crops data | |
| for crop_name, crop_data in self.agricultural_data.get('crops', {}).items(): | |
| # Basic crop info | |
| knowledge_items.append({ | |
| 'type': 'crop_info', | |
| 'crop': crop_name, | |
| 'content': f"{crop_name} cultivation information: Season - {crop_data.get('season', 'N/A')}, " | |
| f"Climate - {crop_data.get('climate', 'N/A')}, " | |
| f"Soil - {crop_data.get('soil', {}).get('type', 'N/A')}, " | |
| f"Water requirement - {crop_data.get('water_requirement', 'N/A')}", | |
| 'data': crop_data | |
| }) | |
| # Diseases | |
| for disease in crop_data.get('diseases', []): | |
| knowledge_items.append({ | |
| 'type': 'disease', | |
| 'crop': crop_name, | |
| 'content': f"{disease.get('name', 'Unknown')} disease in {crop_name}: " | |
| f"Cause - {disease.get('cause', 'N/A')}, " | |
| f"Symptoms - {disease.get('symptoms', 'N/A')}, " | |
| f"Control - {disease.get('control', 'N/A')}", | |
| 'data': disease | |
| }) | |
| # Pests | |
| for pest in crop_data.get('pests', []): | |
| knowledge_items.append({ | |
| 'type': 'pest', | |
| 'crop': crop_name, | |
| 'content': f"{pest.get('name', 'Unknown')} pest in {crop_name}: " | |
| f"Damage - {pest.get('damage', 'N/A')}, " | |
| f"Control - {pest.get('control', 'N/A')}", | |
| 'data': pest | |
| }) | |
| # Process farming techniques | |
| for technique_name, technique_data in self.agricultural_data.get('farming_techniques', {}).items(): | |
| knowledge_items.append({ | |
| 'type': 'technique', | |
| 'content': f"{technique_name}: {technique_data.get('definition', 'N/A')}. " | |
| f"Benefits: {', '.join(technique_data.get('benefits', []))}", | |
| 'data': technique_data | |
| }) | |
| return knowledge_items | |
| def init_embedding_model(self): | |
| """Initialize embedding model for semantic search""" | |
| if SENTENCE_TRANSFORMERS_AVAILABLE: | |
| try: | |
| self.embedding_model = SentenceTransformer('all-MiniLM-L6-v2') | |
| # Pre-compute embeddings for knowledge base | |
| self.knowledge_embeddings = self.embedding_model.encode([item['content'] for item in self.knowledge_base]) | |
| except Exception as e: | |
| print(f"Failed to load embedding model: {e}") | |
| self.embedding_model = None | |
| else: | |
| self.embedding_model = None | |
| def semantic_search(self, query: str, top_k: int = 3) -> List[Dict]: | |
| """Perform semantic search on knowledge base""" | |
| if self.embedding_model is None: | |
| return self.fallback_search(query, top_k) | |
| try: | |
| query_embedding = self.embedding_model.encode([query]) | |
| similarities = np.dot(query_embedding, self.knowledge_embeddings.T)[0] | |
| top_indices = np.argsort(similarities)[-top_k:][::-1] | |
| results = [] | |
| for idx in top_indices: | |
| if similarities[idx] > 0.3: # Threshold for relevance | |
| results.append({ | |
| 'item': self.knowledge_base[idx], | |
| 'score': float(similarities[idx]) | |
| }) | |
| return results | |
| except Exception as e: | |
| print(f"Semantic search error: {e}") | |
| return self.fallback_search(query, top_k) | |
| def fallback_search(self, query: str, top_k: int = 3) -> List[Dict]: | |
| """Fallback search using keyword matching""" | |
| query_words = set(query.lower().split()) | |
| results = [] | |
| for item in self.knowledge_base: | |
| content_words = set(item['content'].lower().split()) | |
| overlap = len(query_words.intersection(content_words)) | |
| if overlap > 0: | |
| results.append({ | |
| 'item': item, | |
| 'score': overlap / len(query_words) | |
| }) | |
| results.sort(key=lambda x: x['score'], reverse=True) | |
| return results[:top_k] | |
| def load_model(self): | |
| """Load AI model for advanced queries""" | |
| if self.model_loaded: | |
| return True | |
| if TRANSFORMERS_AVAILABLE: | |
| try: | |
| # Use a smaller, more reliable model | |
| model_name = "microsoft/DialoGPT-medium" | |
| self.tokenizer = AutoTokenizer.from_pretrained(model_name) | |
| self.model = AutoModelForCausalLM.from_pretrained( | |
| model_name, | |
| torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32, | |
| device_map="auto" if torch.cuda.is_available() else None, | |
| low_cpu_mem_usage=True | |
| ) | |
| # Add pad token if not present | |
| if self.tokenizer.pad_token is None: | |
| self.tokenizer.pad_token = self.tokenizer.eos_token | |
| self.generator = pipeline( | |
| "text-generation", | |
| model=self.model, | |
| tokenizer=self.tokenizer, | |
| device=0 if torch.cuda.is_available() else -1, | |
| return_full_text=False | |
| ) | |
| self.model_loaded = True | |
| print("β AI model loaded successfully!") | |
| return True | |
| except Exception as e: | |
| print(f"β οΈ Could not load AI model: {str(e)}") | |
| return False | |
| else: | |
| print("π§ Install transformers and torch for AI features") | |
| return False | |
| def generate_ai_response(self, query: str, context: str = "") -> str: | |
| """Generate conversational AI response using agricultural data as knowledge""" | |
| if not self.model_loaded: | |
| if not self.load_model(): | |
| return self.generate_openai_style_response(query, context) | |
| try: | |
| # Create a conversational prompt that makes AI process the data | |
| system_prompt = """You are an expert agricultural consultant with years of experience helping farmers. | |
| Your job is to provide helpful, conversational advice based on agricultural knowledge. | |
| Don't just list data - explain it naturally as if you're talking to a farmer. | |
| Give practical recommendations and explain the reasoning behind them.""" | |
| user_prompt = f"""Based on this agricultural information: {context} | |
| Please answer this farmer's question in a helpful, conversational way: {query} | |
| Provide practical advice and explain why these recommendations work.""" | |
| # Generate response | |
| full_prompt = f"{system_prompt}\n\nUser: {user_prompt}\nAssistant:" | |
| response = self.generator( | |
| full_prompt, | |
| max_new_tokens=200, | |
| do_sample=True, | |
| temperature=0.8, | |
| top_p=0.9, | |
| pad_token_id=self.tokenizer.eos_token_id, | |
| repetition_penalty=1.2, | |
| no_repeat_ngram_size=3 | |
| ) | |
| if response and len(response) > 0: | |
| generated_text = response[0]["generated_text"] | |
| # Extract only the assistant's response | |
| if "Assistant:" in generated_text: | |
| ai_response = generated_text.split("Assistant:")[-1].strip() | |
| if len(ai_response) > 20: | |
| return ai_response | |
| except Exception as e: | |
| print(f"AI generation error: {e}") | |
| # Fallback to OpenAI-style response | |
| return self.generate_openai_style_response(query, context) | |
| def generate_openai_style_response(self, query: str, context: str) -> str: | |
| """Generate OpenAI-style conversational response using template""" | |
| query_lower = query.lower() | |
| # Extract key information from context | |
| crop_mentioned = None | |
| for crop in ['wheat', 'rice', 'corn', 'tomato', 'potato']: | |
| if crop in query_lower or crop in context.lower(): | |
| crop_mentioned = crop | |
| break | |
| if crop_mentioned: | |
| crop_data = self.agricultural_data.get('crops', {}).get(crop_mentioned, {}) | |
| if 'how to' in query_lower or 'grow' in query_lower or 'cultivate' in query_lower: | |
| return self.generate_cultivation_response(crop_mentioned, crop_data, query) | |
| elif 'fertilizer' in query_lower or 'nutrient' in query_lower: | |
| return self.generate_fertilizer_response(crop_mentioned, crop_data) | |
| elif 'disease' in query_lower or 'pest' in query_lower: | |
| return self.generate_pest_disease_response(crop_mentioned, crop_data, query) | |
| elif 'harvest' in query_lower: | |
| return self.generate_harvest_response(crop_mentioned, crop_data) | |
| else: | |
| return self.generate_general_crop_response(crop_mentioned, crop_data, query) | |
| return self.generate_general_farming_response(query, context) | |
| def generate_cultivation_response(self, crop: str, crop_data: dict, query: str) -> str: | |
| """Generate detailed cultivation guide response""" | |
| season = crop_data.get('season', 'appropriate season') | |
| climate = crop_data.get('climate', 'suitable climate conditions') | |
| soil_info = crop_data.get('soil', {}) | |
| soil_type = soil_info.get('type', 'well-prepared soil') | |
| water_req = crop_data.get('water_requirement', 'adequate water') | |
| planting_info = crop_data.get('planting', {}) | |
| spacing = planting_info.get('spacing', 'proper spacing') | |
| depth = planting_info.get('depth', 'appropriate depth') | |
| response = f"""Great question about growing {crop}! Let me walk you through the complete cultivation process: | |
| π± **Getting Started:** | |
| {crop.capitalize()} grows best during {season}. You'll want {climate} for optimal growth. The key is starting with {soil_type} - this gives your crop the foundation it needs. | |
| πΎ **Planting Process:** | |
| When planting, maintain {spacing} between plants and sow at {depth}. This spacing is crucial because it allows each plant enough room to develop properly and reduces competition for nutrients. | |
| π§ **Water Management:** | |
| Your {crop} will need {water_req}. The timing of watering is just as important as the amount - too much early on can cause root rot, while too little during grain formation reduces yield. | |
| π **Why This Works:** | |
| These recommendations are based on the plant's natural growth patterns. {crop.capitalize()} has specific nutritional and environmental needs during different growth stages, and following these guidelines maximizes your chances of a successful harvest. | |
| Would you like me to explain any specific part of the cultivation process in more detail?""" | |
| return response | |
| def generate_fertilizer_response(self, crop: str, crop_data: dict) -> str: | |
| """Generate fertilizer recommendation response""" | |
| fertilizer_info = crop_data.get('fertilizer', {}) | |
| npk = fertilizer_info.get('npk', 'balanced NPK') | |
| organic = fertilizer_info.get('organic', 'organic matter') | |
| micronutrients = fertilizer_info.get('micronutrients', 'essential micronutrients') | |
| response = f"""Excellent question about fertilizing {crop}! Proper nutrition is absolutely critical for good yields. | |
| π§ͺ **Primary Nutrition (NPK):** | |
| For {crop}, I recommend {npk} per hectare. Here's why this ratio works: | |
| - **Nitrogen (N)**: Promotes leaf growth and protein development | |
| - **Phosphorus (P)**: Essential for root development and grain formation | |
| - **Potassium (K)**: Improves disease resistance and grain quality | |
| πΏ **Organic Approach:** | |
| Don't forget about {organic} - this improves soil structure and provides slow-release nutrients. Organic matter also feeds beneficial soil microorganisms that help your plants absorb nutrients more efficiently. | |
| β‘ **Micronutrients:** | |
| {crop.capitalize()} also needs {micronutrients}. These might seem minor, but deficiencies can severely limit yield even when NPK levels are adequate. | |
| π‘ **Application Strategy:** | |
| Apply fertilizers in split doses rather than all at once. This prevents nutrient loss and ensures the plant gets nutrition when it needs it most during different growth stages. | |
| **Timing is Everything:** | |
| Early application supports vegetative growth, while later applications during flowering/grain filling stages directly impact your final yield. | |
| Need specific timing recommendations for your growing season?""" | |
| return response | |
| def generate_pest_disease_response(self, crop: str, crop_data: dict, query: str) -> str: | |
| """Generate pest/disease management response""" | |
| diseases = crop_data.get('diseases', []) | |
| pests = crop_data.get('pests', []) | |
| if 'disease' in query.lower() and diseases: | |
| main_disease = diseases[0] if diseases else {} | |
| disease_name = main_disease.get('name', 'common diseases') | |
| symptoms = main_disease.get('symptoms', 'various symptoms') | |
| control = main_disease.get('control', 'appropriate treatment') | |
| response = f"""I understand your concern about {crop} diseases. {disease_name} is indeed one of the most common issues farmers face. | |
| π **What to Look For:** | |
| {symptoms} - catching this early is crucial for effective management. | |
| π **Treatment Approach:** | |
| {control} is your best bet for control. But remember, prevention is always better than cure. | |
| π‘οΈ **Prevention Strategy:** | |
| - Ensure proper plant spacing for air circulation | |
| - Avoid overhead watering when possible | |
| - Remove and destroy infected plant material immediately | |
| - Practice crop rotation to break disease cycles | |
| πΏ **Integrated Approach:** | |
| Combine chemical treatments with cultural practices for best results. Healthy plants with good nutrition are naturally more resistant to diseases. | |
| The key is regular monitoring - walk your fields weekly and check for early signs. Early detection means easier, cheaper, and more effective treatment.""" | |
| elif 'pest' in query.lower() and pests: | |
| main_pest = pests[0] if pests else {} | |
| pest_name = main_pest.get('name', 'common pests') | |
| damage = main_pest.get('damage', 'plant damage') | |
| control = main_pest.get('control', 'pest control measures') | |
| response = f"""Pest management in {crop} is definitely important for protecting your investment. {pest_name} can cause significant {damage} if not managed properly. | |
| π― **Control Strategy:** | |
| {control} - but let's talk about a comprehensive approach. | |
| π **Monitoring:** | |
| Regular field scouting is essential. Check plants weekly, especially during vulnerable growth stages. | |
| πΏ **Integrated Pest Management (IPM):** | |
| 1. **Biological control**: Encourage beneficial insects | |
| 2. **Cultural practices**: Proper spacing, sanitation | |
| 3. **Chemical control**: Only when necessary and at right timing | |
| π‘ **Pro Tip:** | |
| Economic thresholds matter - not every pest requires immediate chemical intervention. Sometimes the cost of treatment exceeds the potential damage. | |
| **Timing is Critical:** | |
| Apply controls when pests are in their most vulnerable stage, not necessarily when you first see them.""" | |
| else: | |
| response = f"""For {crop} protection, I recommend an integrated approach combining prevention, monitoring, and targeted treatment. | |
| π‘οΈ **Prevention First:** | |
| - Choose resistant varieties when available | |
| - Maintain proper plant spacing and field sanitation | |
| - Practice crop rotation to break pest/disease cycles | |
| π **Regular Monitoring:** | |
| Weekly field scouting helps catch problems early when they're easier and cheaper to manage. | |
| β‘ **Quick Response:** | |
| When you do identify issues, act quickly but strategically. Consider economic thresholds and use targeted treatments rather than broad-spectrum approaches.""" | |
| return response | |
| def generate_harvest_response(self, crop: str, crop_data: dict) -> str: | |
| """Generate harvest timing and method response""" | |
| harvest_info = crop_data.get('harvesting', {}) | |
| timing = harvest_info.get('time', 'appropriate maturity') | |
| indicators = harvest_info.get('indicators', 'visual cues') | |
| method = harvest_info.get('method', 'proper harvesting technique') | |
| yield_expected = crop_data.get('yield', 'good yields') | |
| response = f"""Timing your {crop} harvest correctly is crucial for maximizing both quantity and quality! | |
| β° **Perfect Timing:** | |
| {crop.capitalize()} is typically ready for harvest {timing}. But don't just go by the calendar - the plant will tell you when it's ready. | |
| π **What to Look For:** | |
| {indicators} - these are nature's signals that your crop has reached optimal maturity. | |
| πΎ **Harvesting Method:** | |
| Use {method} for best results. The method you choose affects not just efficiency, but also grain quality and storage life. | |
| π **Expected Results:** | |
| With proper cultivation and timing, you can expect {yield_expected} under good conditions. | |
| π‘ **Pro Tips:** | |
| - Harvest during dry weather when possible | |
| - Early morning harvesting often gives better quality | |
| - Don't delay once the crop is ready - overripe crops can lose quality quickly | |
| - Proper post-harvest handling is just as important as growing | |
| πͺ **Post-Harvest:** | |
| Quick drying and proper storage will protect your hard work and maintain market value. | |
| The key is balancing maximum maturity with optimal quality - harvest too early and you lose yield, too late and you lose quality.""" | |
| return response | |
| def generate_general_crop_response(self, crop: str, crop_data: dict, query: str) -> str: | |
| """Generate general crop information response""" | |
| season = crop_data.get('season', 'growing season') | |
| climate = crop_data.get('climate', 'suitable climate') | |
| uses = crop_data.get('market_uses', ['food production']) | |
| response = f"""Let me share some key insights about {crop} cultivation that might help you. | |
| πΎ **Overview:** | |
| {crop.capitalize()} is typically grown during {season} and thrives in {climate}. It's a valuable crop with multiple uses including {', '.join(uses[:3]) if isinstance(uses, list) else uses}. | |
| π **Key Success Factors:** | |
| 1. **Timing**: Planting at the right time for your region | |
| 2. **Soil preparation**: Proper soil conditions are fundamental | |
| 3. **Water management**: Balanced irrigation throughout the season | |
| 4. **Nutrition**: Adequate fertilization for healthy growth | |
| 5. **Protection**: Monitoring and managing pests/diseases | |
| πΌ **Market Potential:** | |
| {crop.capitalize()} has good market demand, making it a commercially viable option when grown properly. | |
| π― **My Recommendation:** | |
| Start with small test plots if you're new to {crop} cultivation. This lets you learn the crop's behavior in your specific conditions before scaling up. | |
| Would you like me to dive deeper into any specific aspect of {crop} production?""" | |
| return response | |
| def generate_general_farming_response(self, query: str, context: str) -> str: | |
| """Generate general farming advice response""" | |
| response = f"""That's a great farming question! Based on current agricultural best practices, here's my advice: | |
| π‘ **General Recommendations:** | |
| Agriculture success comes from understanding your local conditions and adapting proven techniques to your specific situation. | |
| π± **Key Principles:** | |
| - Soil health is the foundation of everything | |
| - Prevention is more cost-effective than treatment | |
| - Regular monitoring helps catch issues early | |
| - Sustainable practices ensure long-term success | |
| π **Next Steps:** | |
| I'd recommend consulting with local agricultural extension services for region-specific advice, as local conditions can significantly impact the best approaches. | |
| Would you like me to elaborate on any specific aspect of this topic?""" | |
| return response | |
| def get_user_name(self, message): | |
| name_patterns = [ | |
| r"my name is (\w+)", | |
| r"i'm (\w+)", | |
| r"i am (\w+)", | |
| r"call me (\w+)" | |
| ] | |
| for pattern in name_patterns: | |
| match = re.search(pattern, message.lower()) | |
| if match: | |
| self.user_name = match.group(1).capitalize() | |
| return f"Nice to meet you, {self.user_name}! How can I assist you with your farming needs?" | |
| return None | |
| def process_message(self, message: str) -> str: | |
| """Main method to process user messages and generate AI responses""" | |
| # Check if the user is introducing themselves | |
| name_response = self.get_user_name(message) | |
| if name_response: | |
| return name_response | |
| # Search for relevant information in our knowledge base | |
| search_results = self.semantic_search(message, top_k=3) | |
| # Extract context from search results | |
| context = "" | |
| if search_results: | |
| context_parts = [] | |
| for result in search_results: | |
| if result['score'] > 0.3: # Relevance threshold | |
| context_parts.append(result['item']['content']) | |
| context = " ".join(context_parts) | |
| # Generate AI response using context | |
| ai_response = self.generate_ai_response(message, context) | |
| if ai_response and len(ai_response.strip()) > 20: | |
| return ai_response | |
| else: | |
| # Final fallback | |
| return self.get_fallback_response(message) | |
| def get_fallback_response(self, query: str) -> str: | |
| """Provide fallback response when no specific information is found""" | |
| query_lower = query.lower() | |
| if any(word in query_lower for word in ['crop', 'plant', 'grow']): | |
| available_crops = list(self.agricultural_data.get('crops', {}).keys()) | |
| return f"""I'd be happy to help you with crop cultivation! I have detailed information about {', '.join(available_crops)}. | |
| These crops have different requirements for soil, climate, and management practices. Each one offers unique opportunities and challenges. | |
| Could you let me know which specific crop you're interested in, or would you like me to recommend crops suitable for your conditions?""" | |
| elif any(word in query_lower for word in ['pest', 'insect', 'bug']): | |
| return """Pest management is crucial for successful farming! Here's my approach: | |
| π― **Integrated Pest Management (IPM):** | |
| The most effective strategy combines multiple approaches rather than relying solely on pesticides. | |
| π **Early Detection:** | |
| Regular field scouting is your best tool - catching problems early makes them much easier and cheaper to manage. | |
| πΏ **Natural Controls:** | |
| Encourage beneficial insects, practice crop rotation, and maintain healthy soil to build natural resistance. | |
| β‘ **Strategic Intervention:** | |
| When chemical control is needed, timing and targeted application are key to effectiveness. | |
| Which specific pest are you dealing with? I can provide more targeted advice.""" | |
| elif any(word in query_lower for word in ['disease', 'fungus', 'infection']): | |
| return """Plant diseases can significantly impact your harvest, but they're manageable with the right approach: | |
| π‘οΈ **Prevention Strategy:** | |
| - Choose disease-resistant varieties when available | |
| - Ensure proper plant spacing for air circulation | |
| - Practice crop rotation to break disease cycles | |
| - Maintain soil health for stronger plants | |
| π **Early Recognition:** | |
| Learn to identify early symptoms - quick action is always more effective than waiting. | |
| π **Treatment Options:** | |
| Combine cultural practices with appropriate fungicides or bactericides when necessary. | |
| Which crop disease are you concerned about? I can provide specific guidance.""" | |
| else: | |
| return """I'm here to help with all aspects of modern agriculture! Whether you're dealing with: | |
| π± **Crop selection and cultivation** | |
| π **Soil health and fertilization** | |
| π **Pest and disease management** | |
| β **Weather-related challenges** | |
| π **Yield optimization strategies** | |
| Each farming situation is unique, and the best approach depends on your specific conditions, resources, and goals. | |
| What specific agricultural challenge can I help you tackle today?""" | |
| # Initialize the bot | |
| bot = AgriBot() | |
| def chat_response(message, history): | |
| """Generate response for Gradio chat interface""" | |
| if not message.strip(): | |
| return "Please ask me something about agriculture!" | |
| response = bot.process_message(message) | |
| return response | |
| def greet(): | |
| return "Hello! I'm AgriBot, your AI-powered agricultural assistant. I can help you with crop cultivation, pest management, disease control, fertilizers, and general farming advice. What would you like to know about farming today?" | |
| # Create Gradio interface | |
| def create_interface(): | |
| with gr.Blocks( | |
| title="πΎ AgriBot - AI Agricultural Assistant", | |
| theme=gr.themes.Default( | |
| primary_hue="green", | |
| secondary_hue="emerald", | |
| neutral_hue="slate", | |
| ), | |
| css=""" | |
| /* Dark Theme Variables */ | |
| :root { | |
| --dark-bg: #0f172a; | |
| --dark-card: #1e293b; | |
| --dark-border: #334155; | |
| --dark-text: #f1f5f9; | |
| --dark-accent: #10b981; | |
| --dark-hover: #2dd4bf; | |
| --dark-shadow: rgba(0, 0, 0, 0.5); | |
| } | |
| /* Main Container Styling */ | |
| .gradio-container { | |
| max-width: 1400px !important; | |
| margin: 0 auto !important; | |
| padding: 20px !important; | |
| background: var(--dark-bg) !important; | |
| color: var(--dark-text) !important; | |
| } | |
| /* Header Styling */ | |
| .main-header { | |
| text-align: center; | |
| padding: 30px 20px; | |
| background: linear-gradient(135deg, #0d9488 0%, #059669 50%, #047857 100%); | |
| border-radius: 15px; | |
| margin-bottom: 25px; | |
| color: white !important; | |
| box-shadow: 0 8px 32px rgba(13, 148, 136, 0.3); | |
| border: 1px solid rgba(255, 255, 255, 0.1); | |
| } | |
| .main-header h1 { | |
| color: white !important; | |
| font-size: 2.5rem !important; | |
| font-weight: 700 !important; | |
| margin-bottom: 10px !important; | |
| text-shadow: 2px 2px 4px rgba(0,0,0,0.3) !important; | |
| } | |
| .main-header p { | |
| color: #d1fae5 !important; | |
| font-size: 1.2rem !important; | |
| margin: 0 !important; | |
| font-weight: 400 !important; | |
| } | |
| /* Feature Cards */ | |
| .feature-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | |
| gap: 20px; | |
| margin-bottom: 25px; | |
| } | |
| .feature-card { | |
| background: var(--dark-card) !important; | |
| padding: 25px !important; | |
| border-radius: 12px !important; | |
| border-left: 5px solid var(--dark-accent) !important; | |
| box-shadow: 0 4px 15px var(--dark-shadow) !important; | |
| transition: transform 0.3s ease, box-shadow 0.3s ease !important; | |
| color: var(--dark-text) !important; | |
| } | |
| .feature-card:hover { | |
| transform: translateY(-5px) !important; | |
| box-shadow: 0 8px 25px rgba(16, 185, 129, 0.2) !important; | |
| } | |
| .feature-card h3 { | |
| color: var(--dark-accent) !important; | |
| font-size: 1.3rem !important; | |
| font-weight: 600 !important; | |
| margin-bottom: 10px !important; | |
| } | |
| .feature-card p { | |
| color: #cbd5e1 !important; | |
| font-size: 1rem !important; | |
| line-height: 1.5 !important; | |
| margin: 0 !important; | |
| } | |
| /* Chat Container */ | |
| .chat-container { | |
| background: var(--dark-card) !important; | |
| border-radius: 15px !important; | |
| padding: 25px !important; | |
| box-shadow: 0 8px 32px var(--dark-shadow) !important; | |
| margin-bottom: 20px !important; | |
| } | |
| /* Chatbot Styling */ | |
| .chatbot-container { | |
| border: 2px solid var(--dark-border) !important; | |
| border-radius: 12px !important; | |
| background: var(--dark-card) !important; | |
| } | |
| /* Override Gradio's default message styling */ | |
| .chatbot .message-wrap { | |
| background: transparent !important; | |
| } | |
| .chatbot .message.user { | |
| background: linear-gradient(135deg, #1e40af 0%, #1e3a8a 100%) !important; | |
| color: white !important; | |
| border: 1px solid #3b82f6 !important; | |
| margin-left: 15% !important; | |
| padding: 15px 20px !important; | |
| border-radius: 15px 15px 5px 15px !important; | |
| box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3) !important; | |
| font-weight: 500 !important; | |
| } | |
| .chatbot .message.bot { | |
| background: linear-gradient(135deg, #065f46 0%, #064e3b 100%) !important; | |
| color: white !important; | |
| border: 1px solid #10b981 !important; | |
| margin-right: 15% !important; | |
| padding: 15px 20px !important; | |
| border-radius: 15px 15px 15px 5px !important; | |
| box-shadow: 0 2px 8px rgba(16, 185, 129, 0.3) !important; | |
| font-weight: 500 !important; | |
| } | |
| /* Force text color in chat messages */ | |
| .chatbot .message.user * { | |
| color: white !important; | |
| } | |
| .chatbot .message.bot * { | |
| color: white !important; | |
| } | |
| /* Ensure chat text is always visible */ | |
| .gradio-chatbot .chatbot .message { | |
| color: white !important; | |
| } | |
| .gradio-chatbot .chatbot .message p { | |
| color: white !important; | |
| margin: 5px 0 !important; | |
| line-height: 1.5 !important; | |
| } | |
| /* Input Styling */ | |
| .input-container { | |
| background: var(--dark-card) !important; | |
| border-radius: 12px !important; | |
| border: 2px solid var(--dark-border) !important; | |
| padding: 5px !important; | |
| margin-top: 15px !important; | |
| } | |
| .input-container:focus-within { | |
| border-color: var(--dark-accent) !important; | |
| box-shadow: 0 0 10px rgba(16, 185, 129, 0.3) !important; | |
| } | |
| /* Input text styling */ | |
| .input-container textarea, | |
| .input-container input { | |
| color: white !important; | |
| background: var(--dark-card) !important; | |
| border: none !important; | |
| font-size: 1rem !important; | |
| font-weight: 500 !important; | |
| } | |
| .input-container textarea::placeholder, | |
| .input-container input::placeholder { | |
| color: #94a3b8 !important; | |
| opacity: 0.8 !important; | |
| } | |
| /* Override any Gradio input styling */ | |
| .gradio-textbox { | |
| background: var(--dark-card) !important; | |
| } | |
| .gradio-textbox textarea { | |
| color: white !important; | |
| background: var(--dark-card) !important; | |
| border: 2px solid var(--dark-border) !important; | |
| border-radius: 8px !important; | |
| padding: 12px !important; | |
| font-size: 1rem !important; | |
| } | |
| .gradio-textbox textarea:focus { | |
| border-color: var(--dark-accent) !important; | |
| box-shadow: 0 0 10px rgba(16, 185, 129, 0.3) !important; | |
| outline: none !important; | |
| } | |
| /* Button Styling */ | |
| .btn-primary { | |
| background: linear-gradient(135deg, var(--dark-accent) 0%, #059669 100%) !important; | |
| color: white !important; | |
| border: none !important; | |
| border-radius: 8px !important; | |
| padding: 12px 24px !important; | |
| font-weight: 600 !important; | |
| font-size: 1rem !important; | |
| transition: all 0.3s ease !important; | |
| box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3) !important; | |
| } | |
| .btn-primary:hover { | |
| background: linear-gradient(135deg, #059669 0%, #047857 100%) !important; | |
| transform: translateY(-2px) !important; | |
| box-shadow: 0 6px 20px rgba(16, 185, 129, 0.4) !important; | |
| } | |
| .btn-secondary { | |
| background: linear-gradient(135deg, #475569 0%, #334155 100%) !important; | |
| color: white !important; | |
| border: none !important; | |
| border-radius: 8px !important; | |
| padding: 12px 24px !important; | |
| font-weight: 600 !important; | |
| transition: all 0.3s ease !important; | |
| } | |
| .btn-secondary:hover { | |
| background: linear-gradient(135deg, #334155 0%, #1e293b 100%) !important; | |
| transform: translateY(-2px) !important; | |
| } | |
| /* Sidebar Styling */ | |
| .sidebar { | |
| background: var(--dark-card) !important; | |
| border-radius: 15px !important; | |
| padding: 25px !important; | |
| box-shadow: 0 8px 32px var(--dark-shadow) !important; | |
| height: fit-content !important; | |
| } | |
| .sidebar h3 { | |
| color: var(--dark-accent) !important; | |
| font-size: 1.4rem !important; | |
| font-weight: 600 !important; | |
| margin-bottom: 15px !important; | |
| padding-bottom: 10px !important; | |
| border-bottom: 2px solid var(--dark-border) !important; | |
| } | |
| .sidebar ul { | |
| list-style: none !important; | |
| padding: 0 !important; | |
| margin: 0 !important; | |
| } | |
| .sidebar li { | |
| color: #cbd5e1 !important; | |
| padding: 8px 0 !important; | |
| border-bottom: 1px solid var(--dark-border) !important; | |
| font-size: 0.95rem !important; | |
| line-height: 1.4 !important; | |
| } | |
| .sidebar strong { | |
| color: var(--dark-accent) !important; | |
| font-weight: 600 !important; | |
| } | |
| /* Examples Section */ | |
| .examples-section { | |
| background: #1a2b3c !important; | |
| padding: 20px !important; | |
| border-radius: 10px !important; | |
| margin-top: 20px !important; | |
| border: 1px solid var(--dark-border) !important; | |
| } | |
| /* Footer Styling */ | |
| .footer { | |
| text-align: center; | |
| padding: 25px; | |
| background: linear-gradient(135deg, #0d9488 0%, #059669 100%); | |
| border-radius: 15px; | |
| margin-top: 30px; | |
| color: white !important; | |
| box-shadow: 0 8px 32px rgba(13, 148, 136, 0.3); | |
| } | |
| .footer p { | |
| color: white !important; | |
| margin: 5px 0 !important; | |
| font-size: 1rem !important; | |
| } | |
| .footer strong { | |
| color: #d1fae5 !important; | |
| font-size: 1.2rem !important; | |
| } | |
| /* Labels and Text */ | |
| .gr-textbox label, .gr-chatbot label { | |
| color: var(--dark-text) !important; | |
| font-weight: 600 !important; | |
| } | |
| /* Loading Animation */ | |
| .loading { | |
| display: inline-block; | |
| width: 20px; | |
| height: 20px; | |
| border: 3px solid var(--dark-border); | |
| border-radius: 50%; | |
| border-top-color: var(--dark-accent); | |
| animation: spin 1s ease-in-out infinite; | |
| } | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| /* Responsive Design */ | |
| @media (max-width: 768px) { | |
| .gradio-container { | |
| padding: 10px !important; | |
| } | |
| .main-header { | |
| padding: 20px 15px !important; | |
| } | |
| .main-header h1 { | |
| font-size: 2rem !important; | |
| } | |
| .feature-grid { | |
| grid-template-columns: 1fr !important; | |
| gap: 15px !important; | |
| } | |
| .chat-container, .sidebar { | |
| padding: 15px !important; | |
| } | |
| .feature-card { | |
| padding: 20px !important; | |
| } | |
| .chatbot .message.user, | |
| .chatbot .message.bot { | |
| margin-left: 5% !important; | |
| margin-right: 5% !important; | |
| } | |
| } | |
| """ | |
| ) as iface: | |
| # Header | |
| gr.HTML(""" | |
| <div class="main-header"> | |
| <h1>πΎ AgriBot - AI Agricultural Assistant</h1> | |
| <p>Expert farming guidance powered by artificial intelligence and comprehensive agricultural data</p> | |
| </div> | |
| """) | |
| # Feature highlights | |
| gr.HTML(""" | |
| <div class="feature-grid"> | |
| <div class="feature-card"> | |
| <h3>π§ AI-Powered Intelligence</h3> | |
| <p>Advanced AI models process your questions and provide conversational, expert-level agricultural advice tailored to your specific needs.</p> | |
| </div> | |
| <div class="feature-card"> | |
| <h3>π± Comprehensive Database</h3> | |
| <p>Extensive knowledge base covering crops, diseases, pests, fertilizers, soil management, and modern farming techniques.</p> | |
| </div> | |
| <div class="feature-card"> | |
| <h3>π‘ Professional Guidance</h3> | |
| <p>Get practical, actionable advice from cultivation to harvest, including organic farming, IPM, and sustainable practices.</p> | |
| </div> | |
| </div> | |
| """) | |
| # Main chat area | |
| with gr.Row(equal_height=True): | |
| with gr.Column(scale=7): | |
| gr.HTML('<div class="chat-container">') | |
| chatbot = gr.Chatbot( | |
| value=[(None, greet())], | |
| height=520, | |
| label="π¬ Chat with AgriBot", | |
| show_label=True, | |
| container=True, | |
| bubble_full_width=False, | |
| avatar_images=( | |
| "https://cdn-icons-png.flaticon.com/512/1077/1077012.png", # User | |
| "https://cdn-icons-png.flaticon.com/512/1998/1998667.png" # Bot | |
| ), | |
| elem_classes=["chatbot-container"] | |
| ) | |
| with gr.Row(): | |
| msg = gr.Textbox( | |
| label="πΎ Ask me anything about agriculture...", | |
| placeholder="Example: 'How to grow wheat in clay soil?' or 'Best fertilizer for rice cultivation?' or 'Organic pest control methods?'", | |
| lines=2, | |
| max_lines=4, | |
| scale=4, | |
| elem_classes=["input-container"] | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| submit_btn = gr.Button("π Send Message", variant="primary", elem_classes=["btn-primary"]) | |
| with gr.Column(scale=1): | |
| clear_btn = gr.Button("ποΈ Clear Chat", variant="secondary", elem_classes=["btn-secondary"]) | |
| gr.HTML('</div>') | |
| with gr.Column(scale=3): | |
| gr.HTML(""" | |
| <div class="sidebar"> | |
| <h3>πΎ Agricultural Topics</h3> | |
| <ul> | |
| <li><strong>π± Crops:</strong> Rice, Wheat, Corn, Tomato, Potato</li> | |
| <li><strong>π± Cultivation:</strong> Planting, Growing, Harvesting</li> | |
| <li><strong>π§ͺ Nutrition:</strong> NPK Fertilizers, Organic Matter</li> | |
| <li><strong>π‘οΈ Protection:</strong> Pest Control, Disease Management</li> | |
| <li><strong>βοΈ Techniques:</strong> Organic Farming, IPM, Crop Rotation</li> | |
| <li><strong>π Soil:</strong> pH Management, Soil Health</li> | |
| <li><strong>β Weather:</strong> Climate Adaptation, Seasonal Advice</li> | |
| </ul> | |
| <div class="examples-section"> | |
| <h3>π¬ Try These Questions</h3> | |
| <ul> | |
| <li>"How to cultivate wheat in winter?"</li> | |
| <li>"Rice fertilizer requirements and timing"</li> | |
| <li>"Organic methods for tomato pest control"</li> | |
| <li>"Soil preparation for corn planting"</li> | |
| <li>"Disease management in potato crops"</li> | |
| <li>"Best practices for crop rotation"</li> | |
| </ul> | |
| </div> | |
| <div style="margin-top: 20px; padding: 15px; background: #1a2b3c; border-radius: 8px; text-align: center;"> | |
| <p style="margin: 0; color: var(--dark-accent); font-weight: 600;">π€ AI Status</p> | |
| <p style="margin: 5px 0 0 0; color: #94a3b8; font-size: 0.9rem;">Ready to help!</p> | |
| </div> | |
| </div> | |
| """) | |
| # Quick action buttons | |
| gr.HTML(""" | |
| <div style="margin: 20px 0; text-align: center;"> | |
| <h3 style="color: var(--dark-accent); margin-bottom: 15px;">π Quick Start Topics</h3> | |
| </div> | |
| """) | |
| with gr.Row(): | |
| crop_btn = gr.Button("πΎ Crop Cultivation", elem_classes=["btn-primary"]) | |
| pest_btn = gr.Button("π Pest Management", elem_classes=["btn-primary"]) | |
| disease_btn = gr.Button("π¦ Disease Control", elem_classes=["btn-primary"]) | |
| fertilizer_btn = gr.Button("π§ͺ Fertilizers", elem_classes=["btn-primary"]) | |
| # Function to handle chat | |
| def respond(message, chat_history): | |
| if not message.strip(): | |
| return chat_history, "" | |
| response = bot.process_message(message) | |
| chat_history.append((message, response)) | |
| return chat_history, "" | |
| # Function to set quick questions | |
| def set_quick_question(question): | |
| return question | |
| # Event handlers for main chat | |
| submit_btn.click(respond, [msg, chatbot], [chatbot, msg]) | |
| msg.submit(respond, [msg, chatbot], [chatbot, msg]) | |
| clear_btn.click(lambda: ([(None, greet())], ""), outputs=[chatbot, msg]) | |
| # Quick action button handlers | |
| crop_btn.click( | |
| set_quick_question, | |
| inputs=gr.State("Tell me about crop cultivation techniques and best practices for growing healthy crops"), | |
| outputs=msg | |
| ) | |
| pest_btn.click( | |
| set_quick_question, | |
| inputs=gr.State("How can I manage pests in my crops using organic and sustainable methods?"), | |
| outputs=msg | |
| ) | |
| disease_btn.click( | |
| set_quick_question, | |
| inputs=gr.State("What are effective disease control strategies for common crop diseases?"), | |
| outputs=msg | |
| ) | |
| fertilizer_btn.click( | |
| set_quick_question, | |
| inputs=gr.State("What fertilizers should I use for optimal crop growth and when to apply them?"), | |
| outputs=msg | |
| ) | |
| # Footer | |
| gr.HTML(""" | |
| <div class="footer"> | |
| <p><strong>πΎ AgriBot - Your AI Agricultural Consultant</strong></p> | |
| <p>Powered by advanced AI β’ Comprehensive agricultural database β’ Expert farming guidance</p> | |
| <p>Β© 2025 AgriBot | Helping farmers grow smarter with AI technology</p> | |
| </div> | |
| """) | |
| return iface | |
| # Create and launch the interface | |
| if __name__ == "__main__": | |
| interface = create_interface() | |
| interface.launch( | |
| share=True, | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| show_api=False | |
| ) |