|
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 |
|
) |
|
|