| import re |
| import random |
| import gradio as gr |
| import json |
| import os |
| from typing import Dict, List, Any |
|
|
| |
| 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: |
| 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 |
| |
| |
| self.agricultural_data = self.load_agricultural_data() |
| self.knowledge_base = self.prepare_knowledge_base() |
| |
| |
| 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 = [] |
| |
| |
| for crop_name, crop_data in self.agricultural_data.get('crops', {}).items(): |
| |
| 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 |
| }) |
| |
| |
| 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 |
| }) |
| |
| |
| 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 |
| }) |
| |
| |
| 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') |
| |
| 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: |
| 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: |
| |
| 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 |
| ) |
| |
| |
| 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: |
| |
| 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.""" |
|
|
| |
| 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"] |
| |
| 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}") |
| |
| |
| 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() |
| |
| |
| 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""" |
| |
| name_response = self.get_user_name(message) |
| if name_response: |
| return name_response |
| |
| |
| search_results = self.semantic_search(message, top_k=3) |
| |
| |
| context = "" |
| if search_results: |
| context_parts = [] |
| for result in search_results: |
| if result['score'] > 0.3: |
| context_parts.append(result['item']['content']) |
| context = " ".join(context_parts) |
| |
| |
| ai_response = self.generate_ai_response(message, context) |
| |
| if ai_response and len(ai_response.strip()) > 20: |
| return ai_response |
| else: |
| |
| 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?""" |
|
|
| |
| 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?" |
|
|
| |
| def create_interface(): |
| with gr.Blocks( |
| title="πΎ AgriBot - AI Agricultural Assistant", |
| theme=gr.themes.Base( |
| primary_hue="green", |
| secondary_hue="emerald", |
| neutral_hue="gray", |
| font=[gr.themes.GoogleFont("Inter"), "Arial", "sans-serif"] |
| ), |
| css=""" |
| /* Main Container Styling */ |
| .gradio-container { |
| max-width: 1400px !important; |
| margin: 0 auto !important; |
| padding: 20px !important; |
| background: linear-gradient(135deg, #f0f8f0 0%, #e8f5e8 100%) !important; |
| } |
| |
| /* Header Styling */ |
| .main-header { |
| text-align: center; |
| padding: 30px 20px; |
| background: linear-gradient(135deg, #2d5016 0%, #4a7c3c 50%, #5d8b4a 100%); |
| border-radius: 15px; |
| margin-bottom: 25px; |
| color: white !important; |
| box-shadow: 0 8px 32px rgba(45, 80, 22, 0.3); |
| border: 1px solid rgba(255, 255, 255, 0.2); |
| } |
| |
| .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: #e8f5e8 !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: white !important; |
| padding: 25px !important; |
| border-radius: 12px !important; |
| border-left: 5px solid #4CAF50 !important; |
| box-shadow: 0 4px 15px rgba(0,0,0,0.1) !important; |
| transition: transform 0.3s ease, box-shadow 0.3s ease !important; |
| color: #2d5016 !important; |
| } |
| |
| .feature-card:hover { |
| transform: translateY(-5px) !important; |
| box-shadow: 0 8px 25px rgba(0,0,0,0.15) !important; |
| } |
| |
| .feature-card h3 { |
| color: #2d5016 !important; |
| font-size: 1.3rem !important; |
| font-weight: 600 !important; |
| margin-bottom: 10px !important; |
| } |
| |
| .feature-card p { |
| color: #4a7c3c !important; |
| font-size: 1rem !important; |
| line-height: 1.5 !important; |
| margin: 0 !important; |
| } |
| |
| /* Chat Container */ |
| .chat-container { |
| background: white !important; |
| border-radius: 15px !important; |
| padding: 25px !important; |
| box-shadow: 0 8px 32px rgba(0,0,0,0.1) !important; |
| margin-bottom: 20px !important; |
| } |
| |
| /* Chatbot Styling */ |
| .chatbot-container { |
| border: 2px solid #e8f5e8 !important; |
| border-radius: 12px !important; |
| background: #fafffe !important; |
| } |
| |
| /* Override Gradio's default message styling */ |
| .chatbot .message-wrap { |
| background: transparent !important; |
| } |
| |
| .chatbot .message.user { |
| background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%) !important; |
| color: #0d47a1 !important; |
| border: 1px solid #90caf9 !important; |
| margin-left: 15% !important; |
| padding: 15px 20px !important; |
| border-radius: 15px 15px 5px 15px !important; |
| box-shadow: 0 2px 8px rgba(13, 71, 161, 0.2) !important; |
| font-weight: 500 !important; |
| } |
| |
| .chatbot .message.bot { |
| background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%) !important; |
| color: #1b5e20 !important; |
| border: 1px solid #a5d6a7 !important; |
| margin-right: 15% !important; |
| padding: 15px 20px !important; |
| border-radius: 15px 15px 15px 5px !important; |
| box-shadow: 0 2px 8px rgba(27, 94, 32, 0.2) !important; |
| font-weight: 500 !important; |
| } |
| |
| /* Force text color in chat messages */ |
| .chatbot .message.user * { |
| color: #0d47a1 !important; |
| } |
| |
| .chatbot .message.bot * { |
| color: #1b5e20 !important; |
| } |
| |
| /* Ensure chat text is always visible */ |
| .gradio-chatbot .chatbot .message { |
| color: inherit !important; |
| } |
| |
| .gradio-chatbot .chatbot .message p { |
| color: inherit !important; |
| margin: 5px 0 !important; |
| line-height: 1.5 !important; |
| } |
| |
| /* User message styling */ |
| .gradio-chatbot .user { |
| background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%) !important; |
| color: #0d47a1 !important; |
| border: 1px solid #90caf9 !important; |
| border-radius: 15px 15px 5px 15px !important; |
| margin-left: 15% !important; |
| margin-right: 5% !important; |
| } |
| |
| /* Bot message styling */ |
| .gradio-chatbot .bot { |
| background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%) !important; |
| color: #1b5e20 !important; |
| border: 1px solid #a5d6a7 !important; |
| border-radius: 15px 15px 15px 5px !important; |
| margin-right: 15% !important; |
| margin-left: 5% !important; |
| } |
| |
| /* Input Styling */ |
| .input-container { |
| background: white !important; |
| border-radius: 12px !important; |
| border: 2px solid #e8f5e8 !important; |
| padding: 5px !important; |
| margin-top: 15px !important; |
| } |
| |
| .input-container:focus-within { |
| border-color: #4CAF50 !important; |
| box-shadow: 0 0 10px rgba(76, 175, 80, 0.2) !important; |
| } |
| |
| /* Input text styling */ |
| .input-container textarea, |
| .input-container input { |
| color: #2d5016 !important; |
| background: white !important; |
| border: none !important; |
| font-size: 1rem !important; |
| font-weight: 500 !important; |
| } |
| |
| .input-container textarea::placeholder, |
| .input-container input::placeholder { |
| color: #6b7280 !important; |
| opacity: 0.8 !important; |
| } |
| |
| /* Override any Gradio input styling */ |
| .gradio-textbox { |
| background: white !important; |
| } |
| |
| .gradio-textbox textarea { |
| color: #2d5016 !important; |
| background: white !important; |
| border: 2px solid #e8f5e8 !important; |
| border-radius: 8px !important; |
| padding: 12px !important; |
| font-size: 1rem !important; |
| } |
| |
| .gradio-textbox textarea:focus { |
| border-color: #4CAF50 !important; |
| box-shadow: 0 0 10px rgba(76, 175, 80, 0.2) !important; |
| outline: none !important; |
| } |
| |
| /* Button Styling */ |
| .btn-primary { |
| background: linear-gradient(135deg, #4CAF50 0%, #45a049 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(76, 175, 80, 0.3) !important; |
| } |
| |
| .btn-primary:hover { |
| background: linear-gradient(135deg, #45a049 0%, #3d8b40 100%) !important; |
| transform: translateY(-2px) !important; |
| box-shadow: 0 6px 20px rgba(76, 175, 80, 0.4) !important; |
| } |
| |
| .btn-secondary { |
| background: linear-gradient(135deg, #6c757d 0%, #5a6268 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, #5a6268 0%, #495057 100%) !important; |
| transform: translateY(-2px) !important; |
| } |
| |
| /* Sidebar Styling */ |
| .sidebar { |
| background: white !important; |
| border-radius: 15px !important; |
| padding: 25px !important; |
| box-shadow: 0 8px 32px rgba(0,0,0,0.1) !important; |
| height: fit-content !important; |
| } |
| |
| .sidebar h3 { |
| color: #2d5016 !important; |
| font-size: 1.4rem !important; |
| font-weight: 600 !important; |
| margin-bottom: 15px !important; |
| padding-bottom: 10px !important; |
| border-bottom: 2px solid #e8f5e8 !important; |
| } |
| |
| .sidebar ul { |
| list-style: none !important; |
| padding: 0 !important; |
| margin: 0 !important; |
| } |
| |
| .sidebar li { |
| color: #4a7c3c !important; |
| padding: 8px 0 !important; |
| border-bottom: 1px solid #f0f8f0 !important; |
| font-size: 0.95rem !important; |
| line-height: 1.4 !important; |
| } |
| |
| .sidebar strong { |
| color: #2d5016 !important; |
| font-weight: 600 !important; |
| } |
| |
| /* Examples Section */ |
| .examples-section { |
| background: #f8fffe !important; |
| padding: 20px !important; |
| border-radius: 10px !important; |
| margin-top: 20px !important; |
| border: 1px solid #e8f5e8 !important; |
| } |
| |
| /* Footer Styling */ |
| .footer { |
| text-align: center; |
| padding: 25px; |
| background: linear-gradient(135deg, #2d5016 0%, #4a7c3c 100%); |
| border-radius: 15px; |
| margin-top: 30px; |
| color: white !important; |
| box-shadow: 0 8px 32px rgba(45, 80, 22, 0.3); |
| } |
| |
| .footer p { |
| color: white !important; |
| margin: 5px 0 !important; |
| font-size: 1rem !important; |
| } |
| |
| .footer strong { |
| color: #e8f5e8 !important; |
| font-size: 1.2rem !important; |
| } |
| |
| /* 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; |
| } |
| } |
| |
| /* Text Visibility Fixes */ |
| .gr-textbox textarea { |
| color: #2d5016 !important; |
| background: white !important; |
| } |
| |
| .gr-textbox label { |
| color: #2d5016 !important; |
| font-weight: 600 !important; |
| } |
| |
| /* Loading Animation */ |
| .loading { |
| display: inline-block; |
| width: 20px; |
| height: 20px; |
| border: 3px solid #e8f5e8; |
| border-radius: 50%; |
| border-top-color: #4CAF50; |
| animation: spin 1s ease-in-out infinite; |
| } |
| |
| @keyframes spin { |
| to { transform: rotate(360deg); } |
| } |
| """ |
| ) as iface: |
| |
| |
| 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> |
| """) |
| |
| |
| 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> |
| """) |
| |
| |
| 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", |
| "https://cdn-icons-png.flaticon.com/512/1998/1998667.png" |
| ), |
| 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: #f0f8f0; border-radius: 8px; text-align: center;"> |
| <p style="margin: 0; color: #2d5016; font-weight: 600;">π€ AI Status</p> |
| <p style="margin: 5px 0 0 0; color: #4a7c3c; font-size: 0.9rem;">Ready to help!</p> |
| </div> |
| </div> |
| """) |
| |
| |
| gr.HTML(""" |
| <div style="margin: 20px 0; text-align: center;"> |
| <h3 style="color: #2d5016; 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"]) |
| |
| |
| 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, "" |
| |
| |
| def set_quick_question(question): |
| return question |
| |
| |
| submit_btn.click(respond, [msg, chatbot], [chatbot, msg]) |
| msg.submit(respond, [msg, chatbot], [chatbot, msg]) |
| clear_btn.click(lambda: ([(None, greet())], ""), outputs=[chatbot, msg]) |
| |
| |
| 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 |
| ) |
| |
| |
| 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 |
|
|
| |
| if __name__ == "__main__": |
| interface = create_interface() |
| interface.launch( |
| share=True, |
| server_name="0.0.0.0", |
| server_port=7860, |
| show_api=False |
| ) |
|
|