sikeaditya commited on
Commit
951e2bc
·
verified ·
1 Parent(s): 54bb6ac

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +513 -513
app.py CHANGED
@@ -1,513 +1,513 @@
1
- import os
2
- from flask import Flask, render_template, request, jsonify
3
- import requests
4
- import pandas as pd
5
- from datetime import datetime
6
- import plotly.express as px
7
- import plotly.io as pio
8
- from googletrans import Translator
9
- import numpy as np
10
-
11
- app = Flask(__name__)
12
-
13
- # Initialize translator
14
- translator = Translator()
15
-
16
- # Translation dictionaries
17
- MARATHI_TRANSLATIONS = {
18
- 'state': 'राज्य',
19
- 'district': 'जिल्हा',
20
- 'market': 'बाजार',
21
- 'commodity': 'पीक',
22
- 'variety': 'प्रकार',
23
- 'grade': 'श्रेणी',
24
- 'arrival_date': 'आगमन तारीख',
25
- 'min_price': 'किमान किंमत',
26
- 'max_price': 'कमाल किंमत',
27
- 'modal_price': 'सरासरी किंमत',
28
- 'Select State': 'राज्य निवडा',
29
- 'Select District': 'जिल्हा निवडा',
30
- 'Select Market': 'बाजार निवडा',
31
- 'Select Commodity': 'पीक निवडा',
32
- 'Market Data': 'बाजार माहिती',
33
- 'Top 5 Cheapest Crops': 'सर्वात स्वस्त 5 पिके',
34
- 'Top 5 Costliest Crops': 'सर्वात महाग 5 पिके'
35
- }
36
-
37
- def translate_to_marathi(text):
38
- """Translate text to Marathi"""
39
- try:
40
- if text in MARATHI_TRANSLATIONS:
41
- return MARATHI_TRANSLATIONS[text]
42
- translation = translator.translate(text, dest='mr')
43
- return translation.text
44
- except:
45
- return text
46
-
47
- def fetch_market_data(state=None, district=None, market=None, commodity=None):
48
- """Fetch data from the agricultural market API"""
49
- api_key = os.getenv("data_api_key")
50
- print(api_key)
51
- base_url = "https://api.data.gov.in/resource/9ef84268-d588-465a-a308-a864a43d0070"
52
-
53
- params = {
54
- "api-key": api_key,
55
- "format": "json",
56
- "limit": 15000,
57
- }
58
-
59
- # Add filters if provided
60
- if state:
61
- params["filters[state]"] = state
62
- if district:
63
- params["filters[district]"] = district
64
- if market:
65
- params["filters[market]"] = market
66
- if commodity:
67
- params["filters[commodity]"] = commodity
68
-
69
- try:
70
- response = requests.get(base_url, params=params)
71
- if response.status_code == 200:
72
- data = response.json()
73
- records = data.get("records", [])
74
- df = pd.DataFrame(records)
75
- return df
76
- else:
77
- print(f"API Error: {response.status_code}")
78
- return pd.DataFrame()
79
- except Exception as e:
80
- print(f"Error fetching data: {str(e)}")
81
- return pd.DataFrame()
82
-
83
-
84
- def get_ai_insights(market_data, state, district):
85
- """Get enhanced insights from LLM API with focus on profitable suggestions for farmers"""
86
- if not state or not district or market_data.empty:
87
- return ""
88
-
89
- try:
90
- # Calculate additional market metrics
91
- district_data = market_data[market_data['district'] == district]
92
-
93
- # Price trends and volatility
94
- price_trends = district_data.groupby('commodity').agg({
95
- 'modal_price': ['mean', 'min', 'max', 'std']
96
- }).round(2)
97
-
98
- # Calculate price stability (lower std/mean ratio indicates more stable prices)
99
- price_trends['price_stability'] = (price_trends['modal_price']['std'] /
100
- price_trends['modal_price']['mean']).round(2)
101
-
102
- # Identify commodities with consistent high prices
103
- high_value_crops = price_trends[price_trends['modal_price']['mean'] >
104
- price_trends['modal_price']['mean'].median()]
105
-
106
- # Get seasonal patterns
107
- district_data['arrival_date'] = pd.to_datetime(district_data['arrival_date'])
108
- district_data['month'] = district_data['arrival_date'].dt.month
109
- monthly_trends = district_data.groupby(['commodity', 'month'])['modal_price'].mean().round(2)
110
-
111
- # Market competition analysis
112
- market_competition = len(district_data['market'].unique())
113
-
114
- # Prepare comprehensive market summary
115
- market_summary = {
116
- "high_value_crops": high_value_crops.index.tolist(),
117
- "price_stability": price_trends['price_stability'].to_dict(),
118
- "monthly_trends": monthly_trends.to_dict(),
119
- "market_competition": market_competition,
120
- "avg_prices": district_data.groupby('commodity')['modal_price'].mean().round(2).to_dict(),
121
- "price_ranges": {
122
- crop: {
123
- 'min': price_trends.loc[crop, ('modal_price', 'min')],
124
- 'max': price_trends.loc[crop, ('modal_price', 'max')]
125
- } for crop in price_trends.index
126
- }
127
- }
128
-
129
- # Enhanced LLM prompt for more actionable insights
130
- prompt = f"""
131
- As an agricultural market expert, analyze this data for {district}, {state} and provide specific, actionable advice for farmers:
132
-
133
- Market Overview:
134
- - Number of active markets: {market_competition}
135
- - High-value crops: {', '.join(market_summary['high_value_crops'][:5])}
136
- - Price stability data available for {len(market_summary['price_stability'])} crops
137
- - Monthly price trends tracked across {len(market_summary['monthly_trends'])} entries
138
-
139
- Based on this comprehensive data, provide:
140
-
141
- 1. Immediate Market Opportunities (Next 2-4 weeks):
142
- - Which crops currently show the best profit potential?
143
- - Which markets are offering the best prices?
144
- - Any immediate selling or holding recommendations?
145
-
146
- 2. Strategic Planning (Next 3-6 months):
147
- - Which crops show consistent high returns?
148
- - What are the optimal planting times based on price patterns?
149
- - Which crop combinations could maximize profit throughout the year?
150
-
151
- 3. Risk Management:
152
- - Which crops have shown the most stable prices?
153
- - How can farmers diversify their crops to minimize risk?
154
- - What are the warning signs to watch for in the market?
155
-
156
- 4. Market Engagement Strategy:
157
- - Which markets consistently offer better prices?
158
- - What quality grades are fetching premium prices?
159
- - How can farmers negotiate better based on current market dynamics?
160
-
161
- 5. Storage and Timing Recommendations:
162
- - Which crops are worth storing for better prices?
163
- - What are the best times to sell each major crop?
164
- - How can farmers use price trends to time their sales?
165
-
166
- Provide practical, actionable advice that farmers can implement immediately. Include specific numbers and percentages where relevant.
167
- Break the response into clear sections and keep it concise but informative.
168
- """
169
- api_url = "https://api-inference.huggingface.co/models/meta-llama/Llama-3.2-1B-Instruct/v1/chat/completions"
170
- headers = {"Authorization": f"Bearer {os.getenv('HUGGINGFACE_API_KEY')}"}
171
- payload = {
172
- "inputs": prompt
173
- }
174
-
175
- response = requests.post(api_url,headers=headers, json=payload)
176
- if response.status_code == 200:
177
- response_data = response.json()
178
- if (response_data and
179
- 'choices' in response_data and
180
- len(response_data['choices']) > 0 and
181
- 'message' in response_data['choices'][0] and
182
- 'content' in response_data['choices'][0]['message']):
183
-
184
- insights = response_data['choices'][0]['message']['content']
185
- formatted_insights = format_ai_insights(insights)
186
- return formatted_insights
187
-
188
- return "AI insights temporarily unavailable"
189
-
190
- except Exception as e:
191
- print(f"Error generating insights: {str(e)}")
192
- return f"Could not generate insights: {str(e)}"
193
-
194
- def generate_plots(df, lang='en'):
195
- """Generate all plots with language support"""
196
- if df.empty:
197
- return {}, "No data available"
198
-
199
- # Convert price columns to numeric
200
- price_cols = ['min_price', 'max_price', 'modal_price']
201
- for col in price_cols:
202
- df[col] = pd.to_numeric(df[col], errors='coerce')
203
-
204
- # Color scheme
205
- colors = ["#4CAF50", "#8BC34A", "#CDDC39", "#FFC107", "#FF5722"]
206
-
207
- # 1. Bar Chart
208
- df_bar = df.groupby('commodity')['modal_price'].mean().reset_index()
209
- fig_bar = px.bar(df_bar,
210
- x='commodity',
211
- y='modal_price',
212
- title=translate_to_marathi("Average Price by Commodity") if lang == 'mr' else "Average Price by Commodity",
213
- color_discrete_sequence=colors)
214
-
215
- # 2. Line Chart (if commodity selected)
216
- fig_line = None
217
- if 'commodity' in df.columns and len(df['commodity'].unique()) == 1:
218
- df['arrival_date'] = pd.to_datetime(df['arrival_date'])
219
- df_line = df.sort_values('arrival_date')
220
- fig_line = px.line(df_line,
221
- x='arrival_date',
222
- y='modal_price',
223
- title=translate_to_marathi("Price Trend") if lang == 'mr' else "Price Trend",
224
- color_discrete_sequence=colors)
225
-
226
- # 3. Box Plot
227
- fig_box = px.box(df,
228
- x='commodity',
229
- y='modal_price',
230
- title=translate_to_marathi("Price Distribution") if lang == 'mr' else "Price Distribution",
231
- color='commodity',
232
- color_discrete_sequence=colors)
233
-
234
- # Convert to HTML
235
- plots = {
236
- 'bar': pio.to_html(fig_bar, full_html=False),
237
- 'box': pio.to_html(fig_box, full_html=False)
238
- }
239
- if fig_line:
240
- plots['line'] = pio.to_html(fig_line, full_html=False)
241
-
242
- return plots
243
-
244
- @app.route('/')
245
- def index():
246
- """Render main page"""
247
- initial_data = fetch_market_data()
248
- states = sorted(initial_data['state'].dropna().unique())
249
- return render_template('index.html',
250
- states=states,
251
- today=datetime.today().strftime('%Y-%m-%d'))
252
-
253
- @app.route('/filter_data', methods=['POST'])
254
- def filter_data():
255
- """Handle data filtering, chart generation, and table generation"""
256
- state = request.form.get('state')
257
- district = request.form.get('district')
258
- market = request.form.get('market')
259
- commodity = request.form.get('commodity')
260
- lang = request.form.get('language', 'en')
261
-
262
- df = fetch_market_data(state, district, market, commodity)
263
- plots = generate_plots(df, lang)
264
- insights = get_ai_insights(df, state, district) if state and district and not df.empty else ""
265
-
266
- # Generate market data table HTML
267
- market_table_html = """
268
- <div class="table-responsive">
269
- <table class="table table-striped table-bordered">
270
- <thead>
271
- <tr>
272
- <th>State</th>
273
- <th>District</th>
274
- <th>Market</th>
275
- <th>Commodity</th>
276
- <th>Variety</th>
277
- <th>Grade</th>
278
- <th>Arrival Date</th>
279
- <th>Min Price</th>
280
- <th>Max Price</th>
281
- <th>Modal Price</th>
282
- </tr>
283
- </thead>
284
- <tbody>
285
- """
286
-
287
- for _, row in df.iterrows():
288
- market_table_html += f"""
289
- <tr>
290
- <td>{row['state']}</td>
291
- <td>{row['district']}</td>
292
- <td>{row['market']}</td>
293
- <td>{row['commodity']}</td>
294
- <td>{row['variety']}</td>
295
- <td>{row['grade']}</td>
296
- <td>{row['arrival_date']}</td>
297
- <td>₹{row['min_price']}</td>
298
- <td>₹{row['max_price']}</td>
299
- <td>₹{row['modal_price']}</td>
300
- </tr>
301
- """
302
- market_table_html += "</tbody></table></div>"
303
-
304
- # Generate top 5 cheapest crops table
305
- cheapest_crops = df.sort_values('modal_price', ascending=True).head(5)
306
- cheapest_table_html = """
307
- <div class="table-responsive">
308
- <table class="table table-sm table-bordered">
309
- <thead>
310
- <tr>
311
- <th>Commodity</th>
312
- <th>Market</th>
313
- <th>Modal Price</th>
314
- </tr>
315
- </thead>
316
- <tbody>
317
- """
318
-
319
- for _, row in cheapest_crops.iterrows():
320
- cheapest_table_html += f"""
321
- <tr>
322
- <td>{row['commodity']}</td>
323
- <td>{row['market']}</td>
324
- <td>₹{row['modal_price']}</td>
325
- </tr>
326
- """
327
- cheapest_table_html += "</tbody></table></div>"
328
-
329
- # Generate top 5 costliest crops table
330
- costliest_crops = df.sort_values('modal_price', ascending=False).head(5)
331
- costliest_table_html = """
332
- <div class="table-responsive">
333
- <table class="table table-sm table-bordered">
334
- <thead>
335
- <tr>
336
- <th>Commodity</th>
337
- <th>Market</th>
338
- <th>Modal Price</th>
339
- </tr>
340
- </thead>
341
- <tbody>
342
- """
343
-
344
- for _, row in costliest_crops.iterrows():
345
- costliest_table_html += f"""
346
- <tr>
347
- <td>{row['commodity']}</td>
348
- <td>{row['market']}</td>
349
- <td>₹{row['modal_price']}</td>
350
- </tr>
351
- """
352
- costliest_table_html += "</tbody></table></div>"
353
-
354
- # Calculate market statistics
355
- market_stats = {
356
- 'total_commodities': len(df['commodity'].unique()),
357
- 'avg_modal_price': f"₹{df['modal_price'].mean():.2f}",
358
- 'price_range': f"₹{df['modal_price'].min():.2f} - ₹{df['modal_price'].max():.2f}",
359
- 'total_markets': len(df['market'].unique())
360
- }
361
-
362
- response = {
363
- 'plots': plots,
364
- 'insights': insights,
365
- 'translations': MARATHI_TRANSLATIONS if lang == 'mr' else {},
366
- 'success': not df.empty,
367
- 'hasStateDistrict': bool(state and district),
368
- 'market_html': market_table_html,
369
- 'cheapest_html': cheapest_table_html,
370
- 'costliest_html': costliest_table_html,
371
- 'market_stats': market_stats
372
- }
373
-
374
- return jsonify(response)
375
-
376
- def format_ai_insights(insights_data, lang='en'):
377
- """Format AI insights into structured HTML with language support"""
378
- # Translation dictionary for section headers and labels
379
- translations = {
380
- 'AI Market Insights': 'एआय बाजार विश्लेषण',
381
- 'Immediate Market Opportunities': 'तात्काळ बाजार संधी',
382
- 'Best Profit Potential': 'सर्वोत्तम नफा क्षमता',
383
- 'Current Market Status': 'सध्याची बाजार स्थिती',
384
- 'Strategic Planning': 'धोरणात्मक नियोजन',
385
- 'High Return Crops': 'उच्च परतावा पिके',
386
- 'Recommended Crop Combinations': 'शिफारस केलेली पीक संयोजने',
387
- 'Risk Management & Market Strategy': 'जोखीम व्यवस्थापन आणि बाजार धोरण',
388
- 'Recommended Actions': 'शिफारस केलेल्या कृती',
389
- 'increase': 'वाढ',
390
- 'per kg': 'प्रति किलो',
391
- 'Most stable prices': 'सर्वात स्थिर किंमती',
392
- 'Best storage life': 'सर्वोत्तम साठवण कालावधी',
393
- 'Peak selling time': 'उच्चतम विक्री काळ',
394
- 'Plant mix of': 'पिकांचे मिश्रण लावा',
395
- 'Focus on': 'लक्ष केंद्रित करा',
396
- 'Store': 'साठवण करा',
397
- 'Aim for': 'लक्ष्य ठेवा',
398
- 'months': 'महिने'
399
- }
400
-
401
- def translate_text(text):
402
- """Translate text based on language selection"""
403
- if lang == 'mr':
404
- # Try to find direct translation from dictionary
405
- for eng, mar in translations.items():
406
- text = text.replace(eng, mar)
407
- return text
408
- return text
409
-
410
- def format_price(price_text):
411
- """Format price with proper currency symbol and translation"""
412
- if lang == 'mr':
413
- return price_text.replace('₹', '₹').replace('per kg', 'प्रति किलो')
414
- return price_text
415
-
416
- """Format AI insights into structured HTML"""
417
- html = f"""
418
- <div class="insights-header">
419
- <h3 class="en">AI Market Insights</h3>
420
- <h3 class="mr" style="display:none;">एआय बाजार विश्लेषण</h3>
421
- </div>
422
-
423
- <div class="insight-section">
424
- <h4>Immediate Market Opportunities</h4>
425
- <div class="insight-card">
426
- <h5>Best Profit Potential</h5>
427
- <ul class="insight-list">
428
- <li>Beetroot and Bitter gourd showing <span class="percentage-up">15% increase</span> from base year</li>
429
- <li>Bottle gourd premium quality fetching <span class="price-highlight">₹150 per kg</span></li>
430
- </ul>
431
- </div>
432
-
433
- <div class="insight-card">
434
- <h5>Current Market Status</h5>
435
- <ul class="insight-list">
436
- <li>Brinjal in high demand with stable price of <span class="price-highlight">₹80 per kg</span></li>
437
- <li>Premium quality bottle gourd commanding <span class="price-highlight">₹200 per kg</span></li>
438
- </ul>
439
- </div>
440
- </div>
441
-
442
- <div class="insight-section">
443
- <h4>Strategic Planning</h4>
444
- <div class="insight-card">
445
- <h5>High Return Crops</h5>
446
- <ul class="insight-list">
447
- <li>Cauliflower showing <span class="percentage-up">20% increase</span> from base year</li>
448
- <li>Best planting time: Spring season for cauliflower and bottle gourd</li>
449
- </ul>
450
- </div>
451
-
452
- <div class="insight-card">
453
- <h5>Recommended Crop Combinations</h5>
454
- <ul class="insight-list">
455
- <li>Brinjal + Bottle gourd + Cauliflower (similar demand patterns)</li>
456
- </ul>
457
- </div>
458
- </div>
459
-
460
- <div class="insight-section">
461
- <h4>Risk Management & Market Strategy</h4>
462
- <div class="insight-card">
463
- <ul class="insight-list">
464
- <li>Most stable prices: Brinjal, Bottle gourd, Cauliflower</li>
465
- <li>Best storage life: 6-9 months for Cauliflower, Brinjal, and Bottle gourd</li>
466
- <li>Peak selling time for Cauliflower: March-April</li>
467
- </ul>
468
- </div>
469
- </div>
470
-
471
- <div class="action-box">
472
- <h5>Recommended Actions</h5>
473
- <ul class="action-list">
474
- <li>Plant mix of beetroot, bitter gourd, bottle gourd, brinjal, and cauliflower</li>
475
- <li>Focus on stable price markets for cauliflower and bottle gourd</li>
476
- <li>Store cauliflower for March-April peak prices</li>
477
- <li>Aim for premium quality grades to maximize profits</li>
478
- </ul>
479
- </div>
480
- """
481
- if lang == 'mr':
482
- html = translate_text(html)
483
- # print(html
484
- return html
485
-
486
- return html
487
-
488
- @app.route('/get_districts', methods=['POST'])
489
- def get_districts():
490
- """Get districts for selected state"""
491
- state = request.form.get('state')
492
- df = fetch_market_data(state=state)
493
- districts = sorted(df['district'].dropna().unique())
494
- return jsonify(districts)
495
-
496
- @app.route('/get_markets', methods=['POST'])
497
- def get_markets():
498
- """Get markets for selected district"""
499
- district = request.form.get('district')
500
- df = fetch_market_data(district=district)
501
- markets = sorted(df['market'].dropna().unique())
502
- return jsonify(markets)
503
-
504
- @app.route('/get_commodities', methods=['POST'])
505
- def get_commodities():
506
- """Get commodities for selected market"""
507
- market = request.form.get('market')
508
- df = fetch_market_data(market=market)
509
- commodities = sorted(df['commodity'].dropna().unique())
510
- return jsonify(commodities)
511
-
512
- if __name__ == '__main__':
513
- app.run(debug=True, host='0.0.0.0', port=7860)
 
1
+ import os
2
+ from flask import Flask, render_template, request, jsonify
3
+ import requests
4
+ import pandas as pd
5
+ from datetime import datetime
6
+ import plotly.express as px
7
+ import plotly.io as pio
8
+ from googletrans import Translator
9
+ import numpy as np
10
+
11
+ app = Flask(__name__)
12
+
13
+ # Initialize translator
14
+ translator = Translator()
15
+
16
+ # Translation dictionaries
17
+ MARATHI_TRANSLATIONS = {
18
+ 'state': 'राज्य',
19
+ 'district': 'जिल्हा',
20
+ 'market': 'बाजार',
21
+ 'commodity': 'पीक',
22
+ 'variety': 'प्रकार',
23
+ 'grade': 'श्रेणी',
24
+ 'arrival_date': 'आगमन तारीख',
25
+ 'min_price': 'किमान किंमत',
26
+ 'max_price': 'कमाल किंमत',
27
+ 'modal_price': 'सरासरी किंमत',
28
+ 'Select State': 'राज्य निवडा',
29
+ 'Select District': 'जिल्हा निवडा',
30
+ 'Select Market': 'बाजार निवडा',
31
+ 'Select Commodity': 'पीक निवडा',
32
+ 'Market Data': 'बाजार माहिती',
33
+ 'Top 5 Cheapest Crops': 'सर्वात स्वस्त 5 पिके',
34
+ 'Top 5 Costliest Crops': 'सर्वात महाग 5 पिके'
35
+ }
36
+
37
+ def translate_to_marathi(text):
38
+ """Translate text to Marathi"""
39
+ try:
40
+ if text in MARATHI_TRANSLATIONS:
41
+ return MARATHI_TRANSLATIONS[text]
42
+ translation = translator.translate(text, dest='mr')
43
+ return translation.text
44
+ except:
45
+ return text
46
+
47
+ def fetch_market_data(state=None, district=None, market=None, commodity=None):
48
+ """Fetch data from the agricultural market API"""
49
+ api_key = os.getenv("data_api_key")
50
+ print(api_key)
51
+ base_url = "https://api.data.gov.in/resource/9ef84268-d588-465a-a308-a864a43d0070"
52
+
53
+ params = {
54
+ "api-key": api_key,
55
+ "format": "json",
56
+ "limit": 15000,
57
+ }
58
+
59
+ # Add filters if provided
60
+ if state:
61
+ params["filters[state]"] = state
62
+ if district:
63
+ params["filters[district]"] = district
64
+ if market:
65
+ params["filters[market]"] = market
66
+ if commodity:
67
+ params["filters[commodity]"] = commodity
68
+
69
+ try:
70
+ response = requests.get(base_url, params=params)
71
+ if response.status_code == 200:
72
+ data = response.json()
73
+ records = data.get("records", [])
74
+ df = pd.DataFrame(records)
75
+ return df
76
+ else:
77
+ print(f"API Error: {response.status_code}")
78
+ return pd.DataFrame()
79
+ except Exception as e:
80
+ print(f"Error fetching data: {str(e)}")
81
+ return pd.DataFrame()
82
+
83
+
84
+ def get_ai_insights(market_data, state, district):
85
+ """Get enhanced insights from LLM API with focus on profitable suggestions for farmers"""
86
+ if not state or not district or market_data.empty:
87
+ return ""
88
+
89
+ try:
90
+ # Calculate additional market metrics
91
+ district_data = market_data[market_data['district'] == district]
92
+
93
+ # Price trends and volatility
94
+ price_trends = district_data.groupby('commodity').agg({
95
+ 'modal_price': ['mean', 'min', 'max', 'std']
96
+ }).round(2)
97
+
98
+ # Calculate price stability (lower std/mean ratio indicates more stable prices)
99
+ price_trends['price_stability'] = (price_trends['modal_price']['std'] /
100
+ price_trends['modal_price']['mean']).round(2)
101
+
102
+ # Identify commodities with consistent high prices
103
+ high_value_crops = price_trends[price_trends['modal_price']['mean'] >
104
+ price_trends['modal_price']['mean'].median()]
105
+
106
+ # Get seasonal patterns
107
+ district_data['arrival_date'] = pd.to_datetime(district_data['arrival_date'])
108
+ district_data['month'] = district_data['arrival_date'].dt.month
109
+ monthly_trends = district_data.groupby(['commodity', 'month'])['modal_price'].mean().round(2)
110
+
111
+ # Market competition analysis
112
+ market_competition = len(district_data['market'].unique())
113
+
114
+ # Prepare comprehensive market summary
115
+ market_summary = {
116
+ "high_value_crops": high_value_crops.index.tolist(),
117
+ "price_stability": price_trends['price_stability'].to_dict(),
118
+ "monthly_trends": monthly_trends.to_dict(),
119
+ "market_competition": market_competition,
120
+ "avg_prices": district_data.groupby('commodity')['modal_price'].mean().round(2).to_dict(),
121
+ "price_ranges": {
122
+ crop: {
123
+ 'min': price_trends.loc[crop, ('modal_price', 'min')],
124
+ 'max': price_trends.loc[crop, ('modal_price', 'max')]
125
+ } for crop in price_trends.index
126
+ }
127
+ }
128
+
129
+ # Enhanced LLM prompt for more actionable insights
130
+ prompt = f"""
131
+ As an agricultural market expert, analyze this data for {district}, {state} and provide specific, actionable advice for farmers:
132
+
133
+ Market Overview:
134
+ - Number of active markets: {market_competition}
135
+ - High-value crops: {', '.join(market_summary['high_value_crops'][:5])}
136
+ - Price stability data available for {len(market_summary['price_stability'])} crops
137
+ - Monthly price trends tracked across {len(market_summary['monthly_trends'])} entries
138
+
139
+ Based on this comprehensive data, provide:
140
+
141
+ 1. Immediate Market Opportunities (Next 2-4 weeks):
142
+ - Which crops currently show the best profit potential?
143
+ - Which markets are offering the best prices?
144
+ - Any immediate selling or holding recommendations?
145
+
146
+ 2. Strategic Planning (Next 3-6 months):
147
+ - Which crops show consistent high returns?
148
+ - What are the optimal planting times based on price patterns?
149
+ - Which crop combinations could maximize profit throughout the year?
150
+
151
+ 3. Risk Management:
152
+ - Which crops have shown the most stable prices?
153
+ - How can farmers diversify their crops to minimize risk?
154
+ - What are the warning signs to watch for in the market?
155
+
156
+ 4. Market Engagement Strategy:
157
+ - Which markets consistently offer better prices?
158
+ - What quality grades are fetching premium prices?
159
+ - How can farmers negotiate better based on current market dynamics?
160
+
161
+ 5. Storage and Timing Recommendations:
162
+ - Which crops are worth storing for better prices?
163
+ - What are the best times to sell each major crop?
164
+ - How can farmers use price trends to time their sales?
165
+
166
+ Provide practical, actionable advice that farmers can implement immediately. Include specific numbers and percentages where relevant.
167
+ Break the response into clear sections and keep it concise but informative.
168
+ """
169
+ api_url = "https://api-inference.huggingface.co/models/meta-llama/Llama-3.2-1B-Instruct/v1/chat/completions"
170
+ headers = {"Authorization": f"Bearer {os.getenv('HUGGINGFACE_API_KEY')}"}
171
+ payload = {
172
+ "inputs": prompt
173
+ }
174
+
175
+ response = requests.post(api_url,headers=headers, json=payload)
176
+ if response.status_code == 200:
177
+ response_data = response.json()
178
+ if (response_data and
179
+ 'choices' in response_data and
180
+ len(response_data['choices']) > 0 and
181
+ 'message' in response_data['choices'][0] and
182
+ 'content' in response_data['choices'][0]['message']):
183
+
184
+ insights = response_data['choices'][0]['message']['content']
185
+ formatted_insights = format_ai_insights(insights)
186
+ return formatted_insights
187
+
188
+ return "AI insights temporarily unavailable"
189
+
190
+ except Exception as e:
191
+ print(f"Error generating insights: {str(e)}")
192
+ return f"Could not generate insights: {str(e)}"
193
+
194
+ def generate_plots(df, lang='en'):
195
+ """Generate all plots with language support"""
196
+ if df.empty:
197
+ return {}, "No data available"
198
+
199
+ # Convert price columns to numeric
200
+ price_cols = ['min_price', 'max_price', 'modal_price']
201
+ for col in price_cols:
202
+ df[col] = pd.to_numeric(df[col], errors='coerce')
203
+
204
+ # Color scheme
205
+ colors = ["#4CAF50", "#8BC34A", "#CDDC39", "#FFC107", "#FF5722"]
206
+
207
+ # 1. Bar Chart
208
+ df_bar = df.groupby('commodity')['modal_price'].mean().reset_index()
209
+ fig_bar = px.bar(df_bar,
210
+ x='commodity',
211
+ y='modal_price',
212
+ title=translate_to_marathi("Average Price by Commodity") if lang == 'mr' else "Average Price by Commodity",
213
+ color_discrete_sequence=colors)
214
+
215
+ # 2. Line Chart (if commodity selected)
216
+ fig_line = None
217
+ if 'commodity' in df.columns and len(df['commodity'].unique()) == 1:
218
+ df['arrival_date'] = pd.to_datetime(df['arrival_date'])
219
+ df_line = df.sort_values('arrival_date')
220
+ fig_line = px.line(df_line,
221
+ x='arrival_date',
222
+ y='modal_price',
223
+ title=translate_to_marathi("Price Trend") if lang == 'mr' else "Price Trend",
224
+ color_discrete_sequence=colors)
225
+
226
+ # 3. Box Plot
227
+ fig_box = px.box(df,
228
+ x='commodity',
229
+ y='modal_price',
230
+ title=translate_to_marathi("Price Distribution") if lang == 'mr' else "Price Distribution",
231
+ color='commodity',
232
+ color_discrete_sequence=colors)
233
+
234
+ # Convert to HTML
235
+ plots = {
236
+ 'bar': pio.to_html(fig_bar, full_html=False),
237
+ 'box': pio.to_html(fig_box, full_html=False)
238
+ }
239
+ if fig_line:
240
+ plots['line'] = pio.to_html(fig_line, full_html=False)
241
+
242
+ return plots
243
+
244
+ @app.route('/')
245
+ def index():
246
+ """Render main page"""
247
+ initial_data = fetch_market_data()
248
+ states = sorted(initial_data['state'].dropna().unique())
249
+ return render_template('index.html',
250
+ states=states,
251
+ today=datetime.today().strftime('%Y-%m-%d'))
252
+
253
+ @app.route('/filter_data', methods=['POST'])
254
+ def filter_data():
255
+ """Handle data filtering, chart generation, and table generation"""
256
+ state = request.form.get('state')
257
+ district = request.form.get('district')
258
+ market = request.form.get('market')
259
+ commodity = request.form.get('commodity')
260
+ lang = request.form.get('language', 'en')
261
+
262
+ df = fetch_market_data(state, district, market, commodity)
263
+ plots = generate_plots(df, lang)
264
+ insights = get_ai_insights(df, state, district) if state and district and not df.empty else ""
265
+
266
+ # Generate market data table HTML
267
+ market_table_html = """
268
+ <div class="table-responsive">
269
+ <table class="table table-striped table-bordered">
270
+ <thead>
271
+ <tr>
272
+ <th>State</th>
273
+ <th>District</th>
274
+ <th>Market</th>
275
+ <th>Commodity</th>
276
+ <th>Variety</th>
277
+ <th>Grade</th>
278
+ <th>Arrival Date</th>
279
+ <th>Min Price</th>
280
+ <th>Max Price</th>
281
+ <th>Modal Price</th>
282
+ </tr>
283
+ </thead>
284
+ <tbody>
285
+ """
286
+
287
+ for _, row in df.iterrows():
288
+ market_table_html += f"""
289
+ <tr>
290
+ <td>{row['state']}</td>
291
+ <td>{row['district']}</td>
292
+ <td>{row['market']}</td>
293
+ <td>{row['commodity']}</td>
294
+ <td>{row['variety']}</td>
295
+ <td>{row['grade']}</td>
296
+ <td>{row['arrival_date']}</td>
297
+ <td>₹{row['min_price']}</td>
298
+ <td>₹{row['max_price']}</td>
299
+ <td>₹{row['modal_price']}</td>
300
+ </tr>
301
+ """
302
+ market_table_html += "</tbody></table></div>"
303
+
304
+ # Generate top 5 cheapest crops table
305
+ cheapest_crops = df.sort_values('modal_price', ascending=True).head(5)
306
+ cheapest_table_html = """
307
+ <div class="table-responsive">
308
+ <table class="table table-sm table-bordered">
309
+ <thead>
310
+ <tr>
311
+ <th>Commodity</th>
312
+ <th>Market</th>
313
+ <th>Modal Price</th>
314
+ </tr>
315
+ </thead>
316
+ <tbody>
317
+ """
318
+
319
+ for _, row in cheapest_crops.iterrows():
320
+ cheapest_table_html += f"""
321
+ <tr>
322
+ <td>{row['commodity']}</td>
323
+ <td>{row['market']}</td>
324
+ <td>₹{row['modal_price']}</td>
325
+ </tr>
326
+ """
327
+ cheapest_table_html += "</tbody></table></div>"
328
+
329
+ # Generate top 5 costliest crops table
330
+ costliest_crops = df.sort_values('modal_price', ascending=False).head(5)
331
+ costliest_table_html = """
332
+ <div class="table-responsive">
333
+ <table class="table table-sm table-bordered">
334
+ <thead>
335
+ <tr>
336
+ <th>Commodity</th>
337
+ <th>Market</th>
338
+ <th>Modal Price</th>
339
+ </tr>
340
+ </thead>
341
+ <tbody>
342
+ """
343
+
344
+ for _, row in costliest_crops.iterrows():
345
+ costliest_table_html += f"""
346
+ <tr>
347
+ <td>{row['commodity']}</td>
348
+ <td>{row['market']}</td>
349
+ <td>₹{row['modal_price']}</td>
350
+ </tr>
351
+ """
352
+ costliest_table_html += "</tbody></table></div>"
353
+
354
+ # Calculate market statistics
355
+ market_stats = {
356
+ 'total_commodities': len(df['commodity'].unique()),
357
+ 'avg_modal_price': f"₹{df['modal_price'].mean():.2f}",
358
+ 'price_range': f"₹{df['modal_price'].min():.2f} - ₹{df['modal_price'].max():.2f}",
359
+ 'total_markets': len(df['market'].unique())
360
+ }
361
+
362
+ response = {
363
+ 'plots': plots,
364
+ 'insights': insights,
365
+ 'translations': MARATHI_TRANSLATIONS if lang == 'mr' else {},
366
+ 'success': not df.empty,
367
+ 'hasStateDistrict': bool(state and district),
368
+ 'market_html': market_table_html,
369
+ 'cheapest_html': cheapest_table_html,
370
+ 'costliest_html': costliest_table_html,
371
+ 'market_stats': market_stats
372
+ }
373
+
374
+ return jsonify(response)
375
+
376
+ def format_ai_insights(insights_data, lang='en'):
377
+ """Format AI insights into structured HTML with language support"""
378
+ # Translation dictionary for section headers and labels
379
+ translations = {
380
+ 'AI Market Insights': 'एआय बाजार विश्लेषण',
381
+ 'Immediate Market Opportunities': 'तात्काळ बाजार संधी',
382
+ 'Best Profit Potential': 'सर्वोत्तम नफा क्षमता',
383
+ 'Current Market Status': 'सध्याची बाजार स्थिती',
384
+ 'Strategic Planning': 'धोरणात्मक नियोजन',
385
+ 'High Return Crops': 'उच्च परतावा पिके',
386
+ 'Recommended Crop Combinations': 'शिफारस केलेली पीक संयोजने',
387
+ 'Risk Management & Market Strategy': 'जोखीम व्यवस्थापन आणि बाजार धोरण',
388
+ 'Recommended Actions': 'शिफारस केलेल्या कृती',
389
+ 'increase': 'वाढ',
390
+ 'per kg': 'प्रति किलो',
391
+ 'Most stable prices': 'सर्वात स्थिर किंमती',
392
+ 'Best storage life': 'सर्वोत्तम साठवण कालावधी',
393
+ 'Peak selling time': 'उच्चतम विक्री काळ',
394
+ 'Plant mix of': 'पिकांचे मिश्रण लावा',
395
+ 'Focus on': 'लक्ष केंद्रित करा',
396
+ 'Store': 'साठवण करा',
397
+ 'Aim for': 'लक्ष्य ठेवा',
398
+ 'months': 'महिने'
399
+ }
400
+
401
+ def translate_text(text):
402
+ """Translate text based on language selection"""
403
+ if lang == 'mr':
404
+ # Try to find direct translation from dictionary
405
+ for eng, mar in translations.items():
406
+ text = text.replace(eng, mar)
407
+ return text
408
+ return text
409
+
410
+ def format_price(price_text):
411
+ """Format price with proper currency symbol and translation"""
412
+ if lang == 'mr':
413
+ return price_text.replace('₹', '₹').replace('per kg', 'प्रति किलो')
414
+ return price_text
415
+
416
+ """Format AI insights into structured HTML"""
417
+ html = f"""
418
+ <div class="insights-header">
419
+ <h3 class="en">AI Market Insights</h3>
420
+ <h3 class="mr" style="display:none;">एआय बाजार विश्लेषण</h3>
421
+ </div>
422
+
423
+ <div class="insight-section">
424
+ <h4>Immediate Market Opportunities</h4>
425
+ <div class="insight-card">
426
+ <h5>Best Profit Potential</h5>
427
+ <ul class="insight-list">
428
+ <li>Beetroot and Bitter gourd showing <span class="percentage-up">15% increase</span> from base year</li>
429
+ <li>Bottle gourd premium quality fetching <span class="price-highlight">₹150 per kg</span></li>
430
+ </ul>
431
+ </div>
432
+
433
+ <div class="insight-card">
434
+ <h5>Current Market Status</h5>
435
+ <ul class="insight-list">
436
+ <li>Brinjal in high demand with stable price of <span class="price-highlight">₹80 per kg</span></li>
437
+ <li>Premium quality bottle gourd commanding <span class="price-highlight">₹200 per kg</span></li>
438
+ </ul>
439
+ </div>
440
+ </div>
441
+
442
+ <div class="insight-section">
443
+ <h4>Strategic Planning</h4>
444
+ <div class="insight-card">
445
+ <h5>High Return Crops</h5>
446
+ <ul class="insight-list">
447
+ <li>Cauliflower showing <span class="percentage-up">20% increase</span> from base year</li>
448
+ <li>Best planting time: Spring season for cauliflower and bottle gourd</li>
449
+ </ul>
450
+ </div>
451
+
452
+ <div class="insight-card">
453
+ <h5>Recommended Crop Combinations</h5>
454
+ <ul class="insight-list">
455
+ <li>Brinjal + Bottle gourd + Cauliflower (similar demand patterns)</li>
456
+ </ul>
457
+ </div>
458
+ </div>
459
+
460
+ <div class="insight-section">
461
+ <h4>Risk Management & Market Strategy</h4>
462
+ <div class="insight-card">
463
+ <ul class="insight-list">
464
+ <li>Most stable prices: Brinjal, Bottle gourd, Cauliflower</li>
465
+ <li>Best storage life: 6-9 months for Cauliflower, Brinjal, and Bottle gourd</li>
466
+ <li>Peak selling time for Cauliflower: March-April</li>
467
+ </ul>
468
+ </div>
469
+ </div>
470
+
471
+ <div class="action-box">
472
+ <h5>Recommended Actions</h5>
473
+ <ul class="action-list">
474
+ <li>Plant mix of beetroot, bitter gourd, bottle gourd, brinjal, and cauliflower</li>
475
+ <li>Focus on stable price markets for cauliflower and bottle gourd</li>
476
+ <li>Store cauliflower for March-April peak prices</li>
477
+ <li>Aim for premium quality grades to maximize profits</li>
478
+ </ul>
479
+ </div>
480
+ """
481
+ if lang == 'mr':
482
+ html = translate_text(html)
483
+ # print(html
484
+ return html
485
+
486
+ return html
487
+
488
+ @app.route('/get_districts', methods=['POST'])
489
+ def get_districts():
490
+ """Get districts for selected state"""
491
+ state = request.form.get('state')
492
+ df = fetch_market_data(state=state)
493
+ districts = sorted(df['district'].dropna().unique())
494
+ return jsonify(districts)
495
+
496
+ @app.route('/get_markets', methods=['POST'])
497
+ def get_markets():
498
+ """Get markets for selected district"""
499
+ district = request.form.get('district')
500
+ df = fetch_market_data(district=district)
501
+ markets = sorted(df['market'].dropna().unique())
502
+ return jsonify(markets)
503
+
504
+ @app.route('/get_commodities', methods=['POST'])
505
+ def get_commodities():
506
+ """Get commodities for selected market"""
507
+ market = request.form.get('market')
508
+ df = fetch_market_data(market=market)
509
+ commodities = sorted(df['commodity'].dropna().unique())
510
+ return jsonify(commodities)
511
+
512
+ if __name__ == "__main__":
513
+ app.run(host="0.0.0.0", port=7860, debug=True)