Chaitanya895 commited on
Commit
e2e2eec
·
verified ·
1 Parent(s): b3c654a

Upload 11 files

Browse files
agents/.gitkeep ADDED
File without changes
agents/__init__.py ADDED
File without changes
agents/agent_setup.py ADDED
@@ -0,0 +1,452 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import sys
3
+ import os
4
+ # Add the 'models' directory to the Python path
5
+ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'models')))
6
+ # Importing necessary autogen classes and SQLite connector
7
+ from autogen import AssistantAgent, GroupChat, GroupChatManager
8
+ import sqlite3
9
+ import pandas as pd
10
+ from farmer_advisor import FarmerAdvisor
11
+ from market_Researcher import MarketResearcher
12
+ from weather_Analyst import WeatherAnalyst
13
+ from sustainability_Expert import SustainabilityExpert
14
+ import re # For parsing market prices from the message
15
+
16
+ # Custom AssistantAgent class to override generate_reply
17
+ class CustomAssistantAgent(AssistantAgent):
18
+ def __init__(self, name, system_message, llm_config):
19
+ super().__init__(name=name, system_message=system_message, llm_config=llm_config)
20
+ # Instantiate the agent classes
21
+ self.farmer_advisor = FarmerAdvisor()
22
+ self.market_researcher = MarketResearcher()
23
+ db_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'database', 'sustainable_farming.db'))
24
+ self.weather_analyst = WeatherAnalyst(db_path=db_path)
25
+ self.sustainability_expert = SustainabilityExpert()
26
+ # Simulated farm and market inputs
27
+ self.simulated_inputs = {
28
+ 'soil_ph': 6.5, # Neutral soil pH
29
+ 'soil_moisture': 30.0, # Percentage
30
+ 'fertilizer': 50.0, # kg/ha
31
+ 'pesticide': 2.0, # kg/ha
32
+ 'crop_yield': 3.0, # ton/ha
33
+ 'temperature': 25.0, # Celsius (initial placeholder, updated by WeatherAnalyst)
34
+ 'rainfall': 50.0, # mm (initial placeholder, updated by WeatherAnalyst)
35
+ 'market_features': {
36
+ 'Demand_Index': 0.5,
37
+ 'Supply_Index': 0.5,
38
+ 'Competitor_Price_per_ton': 1000.0,
39
+ 'Economic_Indicator': 0.8,
40
+ 'Weather_Impact_Score': 0.7,
41
+ 'Seasonal_Factor': 'Medium',
42
+ 'Consumer_Trend_Index': 0.6
43
+ }
44
+ }
45
+ self.sustainability_metrics = {} # To store overall sustainability scores and new metrics
46
+ self.final_result = None # To store the final recommendation and chart data
47
+
48
+ def generate_reply(self, messages=None, sender=None):
49
+ if messages is None and sender is not None:
50
+ messages = self.chat_messages.get(sender, [])
51
+
52
+ # Responses for each agent
53
+ if self.name == "FarmerAdvisor":
54
+ response = self.farmer_advisor_response(messages)
55
+ elif self.name == "MarketResearcher":
56
+ response = self.market_researcher_response(messages)
57
+ elif self.name == "WeatherAnalyst":
58
+ response = self.weather_analyst_response(messages)
59
+ elif self.name == "SustainabilityExpert":
60
+ response = self.sustainability_expert_response(messages)
61
+ elif self.name == "CentralCoordinator":
62
+ response = self.central_coordinator_logic(messages, sender)
63
+ else:
64
+ response = "No response available."
65
+
66
+ # Debug: Log the response
67
+ print(f"{self.name} response: {response}")
68
+
69
+ # Ensure the response is a non-empty string (or dict for CentralCoordinator)
70
+ if response is None or (isinstance(response, str) and not response.strip()):
71
+ response = f"{self.name}: No valid response generated."
72
+
73
+ return response
74
+
75
+ def farmer_advisor_response(self, messages):
76
+ initial_message = next((msg["content"] for msg in messages if msg["name"] == "CentralCoordinator"), "")
77
+ if "hectare farm with" in initial_message:
78
+ parts = initial_message.split("suggest crops based on a ")[1].split(" farm with ")
79
+ land_size = float(parts[0].split("-hectare")[0])
80
+ soil_type = parts[1].split(" soil and a preference for ")[0].lower()
81
+ crop_preference = parts[1].split(" soil and a preference for ")[1].split(".")[0].lower()
82
+
83
+ # Map soil type to soil pH (simplified mapping)
84
+ soil_ph_mapping = {"sandy": 6.0, "loamy": 6.5, "clay": 7.0}
85
+ self.simulated_inputs['soil_ph'] = soil_ph_mapping.get(soil_type, 6.5)
86
+
87
+ # Use WeatherAnalyst's forecast for temperature and rainfall
88
+ weather_forecast = self.weather_analyst.forecast(
89
+ self.simulated_inputs['soil_ph'],
90
+ self.simulated_inputs['soil_moisture'],
91
+ self.simulated_inputs['fertilizer'],
92
+ self.simulated_inputs['pesticide']
93
+ )
94
+ self.simulated_inputs['temperature'] = weather_forecast['temperature'][0]
95
+ self.simulated_inputs['rainfall'] = weather_forecast['rainfall'][0]
96
+
97
+ # Recommend crops
98
+ recommended_crop = self.farmer_advisor.recommend(
99
+ soil_ph=self.simulated_inputs['soil_ph'],
100
+ soil_moisture=self.simulated_inputs['soil_moisture'],
101
+ temp=self.simulated_inputs['temperature'],
102
+ rainfall=self.simulated_inputs['rainfall'],
103
+ fertilizer=self.simulated_inputs['fertilizer'],
104
+ pesticide=self.simulated_inputs['pesticide'],
105
+ crop_yield=self.simulated_inputs['crop_yield']
106
+ )
107
+ # Suggest a second crop based on crop preference
108
+ crop_preference_crops = {
109
+ "grains": ["wheat", "corn", "rice", "soybean"],
110
+ "vegetables": ["carrots", "tomatoes"],
111
+ "fruits": ["apples", "oranges"]
112
+ }
113
+ suggested_crops = crop_preference_crops.get(crop_preference, ["wheat", "corn"])
114
+ if recommended_crop.lower() not in [crop.lower() for crop in suggested_crops]:
115
+ suggested_crops[0] = recommended_crop.lower()
116
+ return f"Based on a {land_size}-hectare farm with {soil_type} soil and a preference for {crop_preference}, I suggest planting {suggested_crops[0]} and {suggested_crops[1]}."
117
+ return "No farm inputs provided to suggest crops."
118
+
119
+ def market_researcher_response(self, messages):
120
+ farmer_response = next((msg["content"] for msg in messages if msg["name"] == "FarmerAdvisor"), "")
121
+ if "suggest planting" in farmer_response:
122
+ crops = farmer_response.split("suggest planting ")[1].split(" and ")
123
+ crops = [crop.strip(".") for crop in crops]
124
+ market_insights = []
125
+ for crop in crops:
126
+ try:
127
+ predicted_price = self.market_researcher.forecast(crop, self.simulated_inputs['market_features'])[0]
128
+ market_insights.append(f"{crop} is expected to have a market price of ${predicted_price:.2f} per ton")
129
+ except ValueError as e:
130
+ market_insights.append(f"No market data available for {crop}")
131
+ return ", and ".join(market_insights) + "."
132
+ return "No crops suggested to provide market insights."
133
+
134
+ def weather_analyst_response(self, messages):
135
+ temp = self.simulated_inputs['temperature']
136
+ rainfall = self.simulated_inputs['rainfall']
137
+ return f"For the next 3 months, expect a temperature of {temp:.1f}°C and rainfall of {rainfall:.1f} mm."
138
+
139
+ def sustainability_expert_response(self, messages):
140
+ farmer_response = next((msg["content"] for msg in messages if msg["name"] == "FarmerAdvisor"), "")
141
+ if "suggest planting" in farmer_response:
142
+ crops = farmer_response.split("suggest planting ")[1].split(" and ")
143
+ crops = [crop.strip(".") for crop in crops]
144
+
145
+ # Compute sustainability scores for each crop
146
+ sustainability_notes = []
147
+ self.sustainability_metrics = {}
148
+
149
+ for crop in crops:
150
+ try:
151
+ scores_tuple = self.sustainability_expert.evaluate(
152
+ [crop],
153
+ soil_ph=self.simulated_inputs['soil_ph'],
154
+ soil_moisture=self.simulated_inputs['soil_moisture'],
155
+ rainfall=self.simulated_inputs['rainfall'],
156
+ fertilizer=self.simulated_inputs['fertilizer'],
157
+ pesticide=self.simulated_inputs['pesticide'],
158
+ crop_yield=self.simulated_inputs['crop_yield']
159
+ )
160
+ scores = scores_tuple[1] # Dictionary with sustainability, carbon, water, erosion scores
161
+ except Exception as e:
162
+ return f"Error evaluating sustainability: {str(e)}"
163
+
164
+ self.sustainability_metrics[crop] = {
165
+ 'sustainability_score': scores['sustainability'],
166
+ 'carbon_score': scores['carbon'],
167
+ 'water_score': scores['water'],
168
+ 'erosion_score': scores['erosion']
169
+ }
170
+
171
+ sustainability_notes.append(
172
+ f"{crop} has a predicted sustainability score of {scores['sustainability']:.2f} "
173
+ f"(Carbon Footprint: {scores['carbon']:.2f}, Water: {scores['water']:.2f}, Erosion: {scores['erosion']:.2f})."
174
+ )
175
+
176
+ return " ".join(sustainability_notes)
177
+ return "No crops suggested to evaluate sustainability."
178
+
179
+ def central_coordinator_logic(self, messages, sender):
180
+ # Collect responses from all agents
181
+ agent_responses = {}
182
+ for message in messages:
183
+ sender_name = message.get("name")
184
+ content = message.get("content")
185
+ if sender_name and content and sender_name != "CentralCoordinator":
186
+ agent_responses[sender_name] = content
187
+
188
+ # Extract crops from FarmerAdvisor
189
+ crops = agent_responses.get("FarmerAdvisor", "").split("suggest planting ")[1].split(" and ")
190
+ crops = [crop.strip(".") for crop in crops]
191
+
192
+ # Extract market, weather, and sustainability info
193
+ market_info = agent_responses.get("MarketResearcher", "")
194
+ weather_info = agent_responses.get("WeatherAnalyst", "")
195
+ sustainability_info = agent_responses.get("SustainabilityExpert", "")
196
+
197
+ # Parse market prices from MarketResearcher's response
198
+ market_predictions = {}
199
+ for crop in crops:
200
+ pattern = rf"{crop} is expected to have a market price of \$([\d\.]+) per ton"
201
+ match = re.search(pattern, market_info)
202
+ if match:
203
+ market_predictions[crop] = float(match.group(1))
204
+ else:
205
+ market_predictions[crop] = 0.0 # Default if price not found
206
+
207
+ # Parse sustainability scores from SustainabilityExpert's response
208
+ sustainability_scores = {}
209
+ for crop in crops:
210
+ pattern = rf"{crop} has a predicted sustainability score of ([\d\.]+) \(Carbon Footprint: ([\d\.]+), Water: ([\d\.]+), Erosion: ([\d\.]+)\)"
211
+ match = re.search(pattern, sustainability_info)
212
+ if match:
213
+ sustainability_score = float(match.group(1))
214
+ carbon_score = float(match.group(2))
215
+ water_score = float(match.group(3))
216
+ erosion_score = float(match.group(4))
217
+ sustainability_scores[crop] = {
218
+ 'sustainability_score': sustainability_score,
219
+ 'carbon_score': carbon_score,
220
+ 'water_score': water_score,
221
+ 'erosion_score': erosion_score
222
+ }
223
+ else:
224
+ sustainability_scores[crop] = {
225
+ 'sustainability_score': 0.5,
226
+ 'carbon_score': 0.0,
227
+ 'water_score': 0.0,
228
+ 'erosion_score': 0.0
229
+ }
230
+
231
+ # Weighted scoring system
232
+ weights = {
233
+ "market": 0.25, # 25%
234
+ "weather": 0.20, # 20%
235
+ "sustainability": 0.20, # 20%
236
+ "carbon": 0.15, # 15%
237
+ "water": 0.10, # 10%
238
+ "erosion": 0.10 # 10%
239
+ }
240
+ crop_scores = {}
241
+
242
+ for crop in crops:
243
+ # Market Score (Profitability): Based on predicted price
244
+ market_score = 0.5 # Default
245
+ predicted_price = market_predictions.get(crop, 0.0)
246
+ market_score = min(predicted_price / 1000.0, 1.0)
247
+
248
+ # Weather Score (Suitability): Based on temperature and rainfall
249
+ temp = float(weather_info.split("temperature of ")[1].split("°C")[0])
250
+ rainfall = float(weather_info.split("rainfall of ")[1].split(" mm")[0])
251
+ weather_score = 1 - abs(temp - self.simulated_inputs['temperature']) / 50 - abs(rainfall - self.simulated_inputs['rainfall']) / 100
252
+ weather_score = max(0, round(weather_score, 2))
253
+
254
+ # Sustainability Scores
255
+ sustainability_metrics = sustainability_scores.get(crop, {
256
+ 'sustainability_score': 0.5,
257
+ 'carbon_score': 0.0,
258
+ 'water_score': 0.0,
259
+ 'erosion_score': 0.0
260
+ })
261
+ sustainability_score = sustainability_metrics['sustainability_score']
262
+ carbon_score = sustainability_metrics['carbon_score']
263
+ water_score = sustainability_metrics['water_score']
264
+ erosion_score = sustainability_metrics['erosion_score']
265
+
266
+ # Total score
267
+ total_score = (
268
+ weights["market"] * market_score +
269
+ weights["weather"] * weather_score +
270
+ weights["sustainability"] * sustainability_score +
271
+ weights["carbon"] * carbon_score +
272
+ weights["water"] * water_score +
273
+ weights["erosion"] * erosion_score
274
+ )
275
+ crop_scores[crop] = {
276
+ 'total_score': total_score,
277
+ 'market_score': market_score,
278
+ 'weather_score': weather_score,
279
+ 'sustainability_score': sustainability_score,
280
+ 'carbon_score': carbon_score,
281
+ 'water_score': water_score,
282
+ 'erosion_score': erosion_score,
283
+ 'predicted_temperature': temp,
284
+ 'predicted_rainfall': rainfall
285
+ }
286
+
287
+ # Rank crops by total score and remove duplicates
288
+ seen_crops = set()
289
+ unique_crop_scores = []
290
+ for crop, scores in sorted(crop_scores.items(), key=lambda x: x[1]['total_score'], reverse=True):
291
+ if crop not in seen_crops:
292
+ seen_crops.add(crop)
293
+ unique_crop_scores.append((crop, scores))
294
+
295
+ # Generate recommendation with detailed rationale
296
+ recommendations = []
297
+ for crop, scores in unique_crop_scores:
298
+ market_rationale = f"market score: {scores['market_score']:.2f} (${market_predictions.get(crop, 0.0):.2f}/ton)"
299
+ weather_rationale = f"weather suitability: {scores['weather_score']:.2f}"
300
+ sustainability_rationale = f"sustainability: {scores['sustainability_score']:.2f}"
301
+ carbon_rationale = f"carbon footprint: {scores['carbon_score']:.2f}"
302
+ water_rationale = f"water: {scores['water_score']:.2f}"
303
+ erosion_rationale = f"erosion: {scores['erosion_score']:.2f}"
304
+ rationale = (f"Plant {crop}: {market_rationale}, {weather_rationale}, {sustainability_rationale}, "
305
+ f"{carbon_rationale}, {water_rationale}, {erosion_rationale} (Final Score: {scores['total_score']:.2f})")
306
+ recommendations.append(rationale)
307
+
308
+ # Combine into final recommendation
309
+ final_recommendation = "Recommendations:\n" + "\n".join(recommendations) + f"\n\nDetails:\nMarket Insights: {market_info}\nWeather Forecast: {weather_info}\nSustainability Notes: {sustainability_info}"
310
+
311
+ # Generate pie chart data for visualization in Streamlit
312
+ chart_data = []
313
+ for crop, scores in unique_crop_scores:
314
+ chart_data.append({
315
+ 'crop': crop,
316
+ 'labels': ['Market Score', 'Weather Suitability Score', 'Sustainability Score',
317
+ 'Carbon Footprint Score', 'Water Score', 'Erosion Score', 'Final Score'],
318
+ 'values': [
319
+ scores['market_score'],
320
+ scores['weather_score'],
321
+ scores['sustainability_score'],
322
+ scores['carbon_score'],
323
+ scores['water_score'],
324
+ scores['erosion_score'],
325
+ scores['total_score']
326
+ ]
327
+ })
328
+
329
+ # Store in SQLite with new columns for all scores
330
+ db_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'database', 'sustainable_farming.db'))
331
+ with sqlite3.connect(db_path) as conn:
332
+ cursor = conn.cursor()
333
+ cursor.execute("""
334
+ CREATE TABLE IF NOT EXISTS recommendations (
335
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
336
+ crop TEXT,
337
+ score REAL,
338
+ rationale TEXT,
339
+ market_score REAL,
340
+ weather_score REAL,
341
+ sustainability_score REAL,
342
+ carbon_score REAL,
343
+ water_score REAL,
344
+ erosion_score REAL,
345
+ timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
346
+ )
347
+ """)
348
+ for crop, scores in unique_crop_scores:
349
+ cursor.execute(
350
+ "INSERT INTO recommendations (crop, score, rationale, market_score, weather_score, sustainability_score, carbon_score, water_score, erosion_score) "
351
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
352
+ (
353
+ crop,
354
+ scores['total_score'],
355
+ f"Plant {crop}: market score: {scores['market_score']:.2f}, weather suitability: {scores['weather_score']:.2f}, sustainability: {scores['sustainability_score']:.2f}",
356
+ scores['market_score'],
357
+ scores['weather_score'],
358
+ scores['sustainability_score'],
359
+ scores['carbon_score'],
360
+ scores['water_score'],
361
+ scores['erosion_score']
362
+ )
363
+ )
364
+ conn.commit()
365
+
366
+ # Store the full result in the instance variable
367
+ self.final_result = {
368
+ 'recommendation': final_recommendation,
369
+ 'chart_data': chart_data
370
+ }
371
+
372
+ # Return only the recommendation string as the chat message
373
+ return final_recommendation
374
+
375
+ # Define the agents using the custom class
376
+ farmer_advisor = CustomAssistantAgent(
377
+ name="FarmerAdvisor",
378
+ system_message="I am the Farmer Advisor. I process farmer inputs to suggest suitable crops.",
379
+ llm_config=False
380
+ )
381
+
382
+ market_researcher = CustomAssistantAgent(
383
+ name="MarketResearcher",
384
+ system_message="I am the Market Researcher. I analyze market trends to suggest profitable crops.",
385
+ llm_config=False
386
+ )
387
+
388
+ weather_analyst = CustomAssistantAgent(
389
+ name="WeatherAnalyst",
390
+ system_message="I am the Weather Analyst. I predict weather conditions based on farm inputs.",
391
+ llm_config=False
392
+ )
393
+
394
+ sustainability_expert = CustomAssistantAgent(
395
+ name="SustainabilityExpert",
396
+ system_message="I am the Sustainability Expert. I evaluate crops for sustainability.",
397
+ llm_config=False
398
+ )
399
+
400
+ central_coordinator = CustomAssistantAgent(
401
+ name="CentralCoordinator",
402
+ system_message="I am the Central Coordinator. I integrate agent outputs to provide recommendations.",
403
+ llm_config=False
404
+ )
405
+
406
+ # Define a custom speaker selection function
407
+ def custom_select_speaker(last_speaker, groupchat):
408
+ agents = [farmer_advisor, market_researcher, weather_analyst, sustainability_expert, central_coordinator]
409
+ if last_speaker is None:
410
+ return agents[0]
411
+ last_index = agents.index(last_speaker)
412
+ next_index = (last_index + 1) % len(agents)
413
+ return agents[next_index]
414
+
415
+ # Set up the group chat for agent interactions
416
+ group_chat = GroupChat(
417
+ agents=[farmer_advisor, market_researcher, weather_analyst, sustainability_expert, central_coordinator],
418
+ messages=[],
419
+ max_round=6 # Already set to 6 to allow CentralCoordinator to respond
420
+ )
421
+
422
+ group_chat.select_speaker = custom_select_speaker
423
+
424
+ group_chat_manager = GroupChatManager(
425
+ groupchat=group_chat,
426
+ llm_config=False
427
+ )
428
+
429
+ # Function to initiate the group chat with dynamic farmer inputs and return the recommendation
430
+ def run_agent_collaboration(land_size, soil_type, crop_preference):
431
+ initial_message = (
432
+ f"Let’s generate a farming recommendation. "
433
+ f"FarmerAdvisor, please suggest crops based on a {land_size}-hectare farm with {soil_type.lower()} soil "
434
+ f"and a preference for {crop_preference.lower()}. "
435
+ f"MarketResearcher, provide market insights for those crops. "
436
+ f"WeatherAnalyst, predict weather for the next 3 months. "
437
+ f"SustainabilityExpert, evaluate the sustainability of the suggested crops."
438
+ )
439
+ # Initiate the chat
440
+ central_coordinator.initiate_chat(
441
+ group_chat_manager,
442
+ message={"content": initial_message, "role": "user"}
443
+ )
444
+ # Retrieve the final result from the CentralCoordinator instance
445
+ result = central_coordinator.final_result
446
+ if result is None:
447
+ raise ValueError("No recommendation generated by CentralCoordinator.")
448
+ return result
449
+
450
+ if __name__ == "__main__":
451
+ result = run_agent_collaboration(land_size=8, soil_type="Loamy", crop_preference="Grains")
452
+ print(result['recommendation'])
agents/init_db.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+ import os
3
+
4
+ def initialize_db():
5
+ """
6
+ Initialize the SQLite database with necessary tables and sample data if they don't exist.
7
+ """
8
+ # Define the database path relative to the project root
9
+ db_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'database', 'sustainable_farming.db'))
10
+
11
+ # Create the database directory if it doesn't exist
12
+ os.makedirs(os.path.dirname(db_path), exist_ok=True)
13
+
14
+ with sqlite3.connect(db_path) as conn:
15
+ cursor = conn.cursor()
16
+
17
+ # Create farmer_advisor table
18
+ cursor.execute("""
19
+ CREATE TABLE IF NOT EXISTS farmer_advisor (
20
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
21
+ Soil_pH REAL,
22
+ Soil_Moisture REAL,
23
+ Temperature_C REAL,
24
+ Rainfall_mm REAL,
25
+ Fertilizer_Usage_kg REAL,
26
+ Pesticide_Usage_kg REAL,
27
+ Crop_Yield_ton REAL,
28
+ Crop_Type TEXT,
29
+ Sustainability_Score REAL
30
+ )
31
+ """)
32
+
33
+ # Create market_researcher table
34
+ cursor.execute("""
35
+ CREATE TABLE IF NOT EXISTS market_researcher (
36
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
37
+ Product TEXT,
38
+ Market_Price_per_ton REAL,
39
+ Demand_Index REAL,
40
+ Supply_Index REAL,
41
+ Competitor_Price_per_ton REAL,
42
+ Economic_Indicator REAL,
43
+ Weather_Impact_Score REAL,
44
+ Seasonal_Factor TEXT,
45
+ Consumer_Trend_Index REAL
46
+ )
47
+ """)
48
+
49
+ # Create recommendations table
50
+ cursor.execute("""
51
+ CREATE TABLE IF NOT EXISTS recommendations (
52
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
53
+ crop TEXT,
54
+ score REAL,
55
+ rationale TEXT,
56
+ market_score REAL,
57
+ weather_score REAL,
58
+ sustainability_score REAL,
59
+ carbon_score REAL,
60
+ water_score REAL,
61
+ erosion_score REAL,
62
+ timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
63
+ )
64
+
65
+ """)
66
+ cursor.execute('''CREATE TABLE IF NOT EXISTS users (
67
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
68
+ username TEXT UNIQUE,
69
+ farm_name TEXT,
70
+ profile_picture TEXT,
71
+ created_at TEXT
72
+ )''')
73
+
74
+ # Check if farmer_advisor table is empty and populate with sample data
75
+ cursor.execute("SELECT COUNT(*) FROM farmer_advisor")
76
+ if cursor.fetchone()[0] == 0:
77
+ sample_data = [
78
+ (6.5, 30.0, 25.0, 50.0, 50.0, 2.0, 3.0, "tomatoes", 0.75),
79
+ (6.0, 25.0, 24.0, 40.0, 45.0, 1.8, 2.8, "carrots", 0.68),
80
+ (7.0, 35.0, 26.0, 60.0, 55.0, 2.2, 3.2, "wheat", 0.70),
81
+ (6.2, 28.0, 23.0, 45.0, 48.0, 1.9, 2.9, "corn", 0.72)
82
+ ]
83
+ cursor.executemany("""
84
+ INSERT INTO farmer_advisor (Soil_pH, Soil_Moisture, Temperature_C, Rainfall_mm,
85
+ Fertilizer_Usage_kg, Pesticide_Usage_kg, Crop_Yield_ton,
86
+ Crop_Type, Sustainability_Score)
87
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
88
+ """, sample_data)
89
+
90
+ # Check if market_researcher table is empty and populate with sample data
91
+ cursor.execute("SELECT COUNT(*) FROM market_researcher")
92
+ if cursor.fetchone()[0] == 0:
93
+ sample_data = [
94
+ ("tomatoes", 950.0, 0.6, 0.4, 900.0, 0.8, 0.7, "High", 0.6),
95
+ ("carrots", 800.0, 0.5, 0.5, 850.0, 0.7, 0.6, "Medium", 0.5),
96
+ ("wheat", 600.0, 0.4, 0.6, 650.0, 0.9, 0.8, "Low", 0.7),
97
+ ("corn", 700.0, 0.5, 0.5, 720.0, 0.8, 0.7, "Medium", 0.6)
98
+ ]
99
+ cursor.executemany("""
100
+ INSERT INTO market_researcher (Product, Market_Price_per_ton, Demand_Index, Supply_Index,
101
+ Competitor_Price_per_ton, Economic_Indicator,
102
+ Weather_Impact_Score, Seasonal_Factor, Consumer_Trend_Index)
103
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
104
+ """, sample_data)
105
+
106
+ conn.commit()
database/.gitkeep ADDED
File without changes
database/farm_recommendations.db ADDED
File without changes
database/load_data.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import sqlite3
3
+
4
+ # Load CSV files
5
+ farmer_df = pd.read_csv('data/farmer_advisor_dataset.csv')
6
+ market_df = pd.read_csv('data/market_researcher_dataset.csv')
7
+
8
+ # Connect to SQLite DB
9
+ conn = sqlite3.connect('database/sustainable_farming.db')
10
+
11
+ # Load into SQLite tables
12
+ farmer_df.to_sql('farmer_advisor', conn, if_exists='replace', index=False)
13
+ market_df.to_sql('market_researcher', conn, if_exists='replace', index=False)
14
+
15
+ conn.close()
16
+ print("CSV data loaded into database.")
database/preprocess_data.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+ import pandas as pd
3
+ from sklearn.preprocessing import MinMaxScaler
4
+
5
+ # Connect to database
6
+ conn = sqlite3.connect('sustainable_farming.db')
7
+
8
+ ### === Farmer Data Cleaning === ###
9
+ farmer_df = pd.read_sql_query("SELECT * FROM farmer_advisor", conn)
10
+
11
+ farmer_scaler = MinMaxScaler()
12
+ farmer_columns_to_normalize = [
13
+ 'Soil_pH', 'Soil_Moisture', 'Temperature_C', 'Rainfall_mm',
14
+ 'Fertilizer_Usage_kg', 'Pesticide_Usage_kg', 'Crop_Yield_ton', 'Sustainability_Score'
15
+ ]
16
+ farmer_df[farmer_columns_to_normalize] = farmer_scaler.fit_transform(farmer_df[farmer_columns_to_normalize])
17
+
18
+ farmer_df.to_sql('farmer_advisor_normalized', conn, if_exists='replace', index=False)
19
+ print("✅ Farmer data normalized and saved.")
20
+
21
+
22
+ ### === Market Data Cleaning === ###
23
+ market_df = pd.read_sql_query("SELECT * FROM market_researcher", conn)
24
+
25
+ market_scaler = MinMaxScaler()
26
+ market_columns_to_normalize = [
27
+ 'Market_Price_per_ton',
28
+ 'Demand_Index',
29
+ 'Supply_Index',
30
+ 'Competitor_Price_per_ton',
31
+ 'Economic_Indicator',
32
+ 'Weather_Impact_Score',
33
+ 'Consumer_Trend_Index'
34
+ ]
35
+
36
+ market_df[market_columns_to_normalize] = market_scaler.fit_transform(market_df[market_columns_to_normalize])
37
+
38
+ # Keep 'Product' and 'Seasonal_Factor' as-is
39
+ market_df.to_sql('market_researcher_normalized', conn, if_exists='replace', index=False)
40
+ print("✅ Market data normalized and saved.")
41
+
42
+ conn.close()
database/setup_database.py ADDED
File without changes
database/sustainable_farming.db ADDED
Binary file (53.2 kB). View file
 
database/verify.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+
3
+ conn = sqlite3.connect('sustainable_farming.db')
4
+ cursor = conn.cursor()
5
+
6
+ cursor.execute("SELECT * FROM market_researcher_normalized where Market_ID = 1")
7
+ print(cursor.fetchall())
8
+
9
+ conn.close()