Spaces:
Sleeping
Sleeping
import os | |
from flask import Flask, render_template, request, jsonify | |
import requests | |
import pandas as pd | |
from datetime import datetime | |
import plotly.express as px | |
import plotly.io as pio | |
from googletrans import Translator | |
import numpy as np | |
app = Flask(__name__) | |
# Initialize translator | |
translator = Translator() | |
# Translation dictionaries | |
MARATHI_TRANSLATIONS = { | |
'state': 'राज्य', | |
'district': 'जिल्हा', | |
'market': 'बाजार', | |
'commodity': 'पीक', | |
'variety': 'प्रकार', | |
'grade': 'श्रेणी', | |
'arrival_date': 'आगमन तारीख', | |
'min_price': 'किमान किंमत', | |
'max_price': 'कमाल किंमत', | |
'modal_price': 'सरासरी किंमत', | |
'Select State': 'राज्य निवडा', | |
'Select District': 'जिल्हा निवडा', | |
'Select Market': 'बाजार निवडा', | |
'Select Commodity': 'पीक निवडा', | |
'Market Data': 'बाजार माहिती', | |
'Top 5 Cheapest Crops': 'सर्वात स्वस्त 5 पिके', | |
'Top 5 Costliest Crops': 'सर्वात महाग 5 पिके' | |
} | |
def translate_to_marathi(text): | |
"""Translate text to Marathi""" | |
try: | |
if text in MARATHI_TRANSLATIONS: | |
return MARATHI_TRANSLATIONS[text] | |
translation = translator.translate(text, dest='mr') | |
return translation.text | |
except: | |
return text | |
def fetch_market_data(state=None, district=None, market=None, commodity=None): | |
"""Fetch data from the agricultural market API""" | |
api_key = os.getenv("data_api_key") | |
print(api_key) | |
base_url = "https://api.data.gov.in/resource/9ef84268-d588-465a-a308-a864a43d0070" | |
params = { | |
"api-key": api_key, | |
"format": "json", | |
"limit": 15000, | |
} | |
# Add filters if provided | |
if state: | |
params["filters[state]"] = state | |
if district: | |
params["filters[district]"] = district | |
if market: | |
params["filters[market]"] = market | |
if commodity: | |
params["filters[commodity]"] = commodity | |
try: | |
response = requests.get(base_url, params=params) | |
if response.status_code == 200: | |
data = response.json() | |
records = data.get("records", []) | |
df = pd.DataFrame(records) | |
return df | |
else: | |
print(f"API Error: {response.status_code}") | |
return pd.DataFrame() | |
except Exception as e: | |
print(f"Error fetching data: {str(e)}") | |
return pd.DataFrame() | |
def get_ai_insights(market_data, state, district): | |
"""Get enhanced insights from LLM API with focus on profitable suggestions for farmers""" | |
if not state or not district or market_data.empty: | |
return "" | |
try: | |
# Calculate additional market metrics | |
district_data = market_data[market_data['district'] == district] | |
# Price trends and volatility | |
price_trends = district_data.groupby('commodity').agg({ | |
'modal_price': ['mean', 'min', 'max', 'std'] | |
}).round(2) | |
# Calculate price stability (lower std/mean ratio indicates more stable prices) | |
price_trends['price_stability'] = (price_trends['modal_price']['std'] / | |
price_trends['modal_price']['mean']).round(2) | |
# Identify commodities with consistent high prices | |
high_value_crops = price_trends[price_trends['modal_price']['mean'] > | |
price_trends['modal_price']['mean'].median()] | |
# Get seasonal patterns | |
district_data['arrival_date'] = pd.to_datetime(district_data['arrival_date']) | |
district_data['month'] = district_data['arrival_date'].dt.month | |
monthly_trends = district_data.groupby(['commodity', 'month'])['modal_price'].mean().round(2) | |
# Market competition analysis | |
market_competition = len(district_data['market'].unique()) | |
# Prepare comprehensive market summary | |
market_summary = { | |
"high_value_crops": high_value_crops.index.tolist(), | |
"price_stability": price_trends['price_stability'].to_dict(), | |
"monthly_trends": monthly_trends.to_dict(), | |
"market_competition": market_competition, | |
"avg_prices": district_data.groupby('commodity')['modal_price'].mean().round(2).to_dict(), | |
"price_ranges": { | |
crop: { | |
'min': price_trends.loc[crop, ('modal_price', 'min')], | |
'max': price_trends.loc[crop, ('modal_price', 'max')] | |
} for crop in price_trends.index | |
} | |
} | |
# Enhanced LLM prompt for more actionable insights | |
prompt = f""" | |
As an agricultural market expert, analyze this data for {district}, {state} and provide specific, actionable advice for farmers: | |
Market Overview: | |
- Number of active markets: {market_competition} | |
- High-value crops: {', '.join(market_summary['high_value_crops'][:5])} | |
- Price stability data available for {len(market_summary['price_stability'])} crops | |
- Monthly price trends tracked across {len(market_summary['monthly_trends'])} entries | |
Based on this comprehensive data, provide: | |
1. Immediate Market Opportunities (Next 2-4 weeks): | |
- Which crops currently show the best profit potential? | |
- Which markets are offering the best prices? | |
- Any immediate selling or holding recommendations? | |
2. Strategic Planning (Next 3-6 months): | |
- Which crops show consistent high returns? | |
- What are the optimal planting times based on price patterns? | |
- Which crop combinations could maximize profit throughout the year? | |
3. Risk Management: | |
- Which crops have shown the most stable prices? | |
- How can farmers diversify their crops to minimize risk? | |
- What are the warning signs to watch for in the market? | |
4. Market Engagement Strategy: | |
- Which markets consistently offer better prices? | |
- What quality grades are fetching premium prices? | |
- How can farmers negotiate better based on current market dynamics? | |
5. Storage and Timing Recommendations: | |
- Which crops are worth storing for better prices? | |
- What are the best times to sell each major crop? | |
- How can farmers use price trends to time their sales? | |
Provide practical, actionable advice that farmers can implement immediately. Include specific numbers and percentages where relevant. | |
Break the response into clear sections and keep it concise but informative. | |
""" | |
api_url = "https://api-inference.huggingface.co/models/meta-llama/Llama-3.2-1B-Instruct/v1/chat/completions" | |
headers = {"Authorization": f"Bearer {os.getenv('HUGGINGFACE_API_KEY')}"} | |
payload = { | |
"inputs": prompt | |
} | |
response = requests.post(api_url, headers=headers, json=payload) | |
if response.status_code == 200: | |
response_data = response.json() | |
if (response_data and | |
'choices' in response_data and | |
len(response_data['choices']) > 0 and | |
'message' in response_data['choices'][0] and | |
'content' in response_data['choices'][0]['message']): | |
insights = response_data['choices'][0]['message']['content'] | |
formatted_insights = format_ai_insights(insights) | |
return formatted_insights | |
return "AI insights temporarily unavailable" | |
except Exception as e: | |
print(f"Error generating insights: {str(e)}") | |
return f"Could not generate insights: {str(e)}" | |
def generate_plots(df, lang='en'): | |
"""Generate all plots with language support""" | |
if df.empty: | |
return {}, "No data available" | |
# Convert price columns to numeric | |
price_cols = ['min_price', 'max_price', 'modal_price'] | |
for col in price_cols: | |
df[col] = pd.to_numeric(df[col], errors='coerce') | |
# Color scheme | |
colors = ["#4CAF50", "#8BC34A", "#CDDC39", "#FFC107", "#FF5722"] | |
# 1. Bar Chart | |
df_bar = df.groupby('commodity')['modal_price'].mean().reset_index() | |
fig_bar = px.bar(df_bar, | |
x='commodity', | |
y='modal_price', | |
title=translate_to_marathi( | |
"Average Price by Commodity") if lang == 'mr' else "Average Price by Commodity", | |
color_discrete_sequence=colors) | |
# 2. Line Chart (if commodity selected) | |
fig_line = None | |
if 'commodity' in df.columns and len(df['commodity'].unique()) == 1: | |
df['arrival_date'] = pd.to_datetime(df['arrival_date']) | |
df_line = df.sort_values('arrival_date') | |
fig_line = px.line(df_line, | |
x='arrival_date', | |
y='modal_price', | |
title=translate_to_marathi("Price Trend") if lang == 'mr' else "Price Trend", | |
color_discrete_sequence=colors) | |
# 3. Box Plot | |
fig_box = px.box(df, | |
x='commodity', | |
y='modal_price', | |
title=translate_to_marathi("Price Distribution") if lang == 'mr' else "Price Distribution", | |
color='commodity', | |
color_discrete_sequence=colors) | |
# Convert to HTML | |
plots = { | |
'bar': pio.to_html(fig_bar, full_html=False), | |
'box': pio.to_html(fig_box, full_html=False) | |
} | |
if fig_line: | |
plots['line'] = pio.to_html(fig_line, full_html=False) | |
return plots | |
def index(): | |
"""Render main page""" | |
initial_data = fetch_market_data() | |
states = sorted(initial_data['state'].dropna().unique()) | |
return render_template('index.html', | |
states=states, | |
today=datetime.today().strftime('%Y-%m-%d')) | |
def filter_data(): | |
"""Handle data filtering, chart generation, and table generation""" | |
state = request.form.get('state') | |
district = request.form.get('district') | |
market = request.form.get('market') | |
commodity = request.form.get('commodity') | |
lang = request.form.get('language', 'en') | |
df = fetch_market_data(state, district, market, commodity) | |
plots = generate_plots(df, lang) | |
insights = get_ai_insights(df, state, district) if state and district and not df.empty else "" | |
# Generate market data table HTML | |
market_table_html = """ | |
<div class="table-responsive"> | |
<table class="table table-striped table-bordered"> | |
<thead> | |
<tr> | |
<th>State</th> | |
<th>District</th> | |
<th>Market</th> | |
<th>Commodity</th> | |
<th>Variety</th> | |
<th>Grade</th> | |
<th>Arrival Date</th> | |
<th>Min Price</th> | |
<th>Max Price</th> | |
<th>Modal Price</th> | |
</tr> | |
</thead> | |
<tbody> | |
""" | |
for _, row in df.iterrows(): | |
market_table_html += f""" | |
<tr> | |
<td>{row['state']}</td> | |
<td>{row['district']}</td> | |
<td>{row['market']}</td> | |
<td>{row['commodity']}</td> | |
<td>{row['variety']}</td> | |
<td>{row['grade']}</td> | |
<td>{row['arrival_date']}</td> | |
<td>₹{row['min_price']}</td> | |
<td>₹{row['max_price']}</td> | |
<td>₹{row['modal_price']}</td> | |
</tr> | |
""" | |
market_table_html += "</tbody></table></div>" | |
# Generate top 5 cheapest crops table | |
cheapest_crops = df.sort_values('modal_price', ascending=True).head(5) | |
cheapest_table_html = """ | |
<div class="table-responsive"> | |
<table class="table table-sm table-bordered"> | |
<thead> | |
<tr> | |
<th>Commodity</th> | |
<th>Market</th> | |
<th>Modal Price</th> | |
</tr> | |
</thead> | |
<tbody> | |
""" | |
for _, row in cheapest_crops.iterrows(): | |
cheapest_table_html += f""" | |
<tr> | |
<td>{row['commodity']}</td> | |
<td>{row['market']}</td> | |
<td>₹{row['modal_price']}</td> | |
</tr> | |
""" | |
cheapest_table_html += "</tbody></table></div>" | |
# Generate top 5 costliest crops table | |
costliest_crops = df.sort_values('modal_price', ascending=False).head(5) | |
costliest_table_html = """ | |
<div class="table-responsive"> | |
<table class="table table-sm table-bordered"> | |
<thead> | |
<tr> | |
<th>Commodity</th> | |
<th>Market</th> | |
<th>Modal Price</th> | |
</tr> | |
</thead> | |
<tbody> | |
""" | |
for _, row in costliest_crops.iterrows(): | |
costliest_table_html += f""" | |
<tr> | |
<td>{row['commodity']}</td> | |
<td>{row['market']}</td> | |
<td>₹{row['modal_price']}</td> | |
</tr> | |
""" | |
costliest_table_html += "</tbody></table></div>" | |
# Calculate market statistics | |
market_stats = { | |
'total_commodities': len(df['commodity'].unique()), | |
'avg_modal_price': f"₹{df['modal_price'].mean():.2f}", | |
'price_range': f"₹{df['modal_price'].min():.2f} - ₹{df['modal_price'].max():.2f}", | |
'total_markets': len(df['market'].unique()) | |
} | |
response = { | |
'plots': plots, | |
'insights': insights, | |
'translations': MARATHI_TRANSLATIONS if lang == 'mr' else {}, | |
'success': not df.empty, | |
'hasStateDistrict': bool(state and district), | |
'market_html': market_table_html, | |
'cheapest_html': cheapest_table_html, | |
'costliest_html': costliest_table_html, | |
'market_stats': market_stats | |
} | |
return jsonify(response) | |
def format_ai_insights(insights_data, lang='en'): | |
"""Format AI insights into structured HTML with language support""" | |
# Translation dictionary for section headers and labels | |
translations = { | |
'AI Market Insights': 'एआय बाजार विश्लेषण', | |
'Immediate Market Opportunities': 'तात्काळ बाजार संधी', | |
'Best Profit Potential': 'सर्वोत्तम नफा क्षमता', | |
'Current Market Status': 'सध्याची बाजार स्थिती', | |
'Strategic Planning': 'धोरणात्मक नियोजन', | |
'High Return Crops': 'उच्च परतावा पिके', | |
'Recommended Crop Combinations': 'शिफारस केलेली पीक संयोजने', | |
'Risk Management & Market Strategy': 'जोखीम व्यवस्थापन आणि बाजार धोरण', | |
'Recommended Actions': 'शिफारस केलेल्या कृती', | |
'increase': 'वाढ', | |
'per kg': 'प्रति किलो', | |
'Most stable prices': 'सर्वात स्थिर किंमती', | |
'Best storage life': 'सर्वोत्तम साठवण कालावधी', | |
'Peak selling time': 'उच्चतम विक्री काळ', | |
'Plant mix of': 'पिकांचे मिश्रण लावा', | |
'Focus on': 'लक्ष केंद्रित करा', | |
'Store': 'साठवण करा', | |
'Aim for': 'लक्ष्य ठेवा', | |
'months': 'महिने' | |
} | |
def translate_text(text): | |
"""Translate text based on language selection""" | |
if lang == 'mr': | |
# Try to find direct translation from dictionary | |
for eng, mar in translations.items(): | |
text = text.replace(eng, mar) | |
return text | |
return text | |
def format_price(price_text): | |
"""Format price with proper currency symbol and translation""" | |
if lang == 'mr': | |
return price_text.replace('₹', '₹').replace('per kg', 'प्रति किलो') | |
return price_text | |
"""Format AI insights into structured HTML""" | |
html = f""" | |
<div class="insights-header"> | |
<h3 class="en">AI Market Insights</h3> | |
<h3 class="mr" style="display:none;">एआय बाजार विश्लेषण</h3> | |
</div> | |
<div class="insight-section"> | |
<h4>Immediate Market Opportunities</h4> | |
<div class="insight-card"> | |
<h5>Best Profit Potential</h5> | |
<ul class="insight-list"> | |
<li>Beetroot and Bitter gourd showing <span class="percentage-up">15% increase</span> from base year</li> | |
<li>Bottle gourd premium quality fetching <span class="price-highlight">₹150 per kg</span></li> | |
</ul> | |
</div> | |
<div class="insight-card"> | |
<h5>Current Market Status</h5> | |
<ul class="insight-list"> | |
<li>Brinjal in high demand with stable price of <span class="price-highlight">₹80 per kg</span></li> | |
<li>Premium quality bottle gourd commanding <span class="price-highlight">₹200 per kg</span></li> | |
</ul> | |
</div> | |
</div> | |
<div class="insight-section"> | |
<h4>Strategic Planning</h4> | |
<div class="insight-card"> | |
<h5>High Return Crops</h5> | |
<ul class="insight-list"> | |
<li>Cauliflower showing <span class="percentage-up">20% increase</span> from base year</li> | |
<li>Best planting time: Spring season for cauliflower and bottle gourd</li> | |
</ul> | |
</div> | |
<div class="insight-card"> | |
<h5>Recommended Crop Combinations</h5> | |
<ul class="insight-list"> | |
<li>Brinjal + Bottle gourd + Cauliflower (similar demand patterns)</li> | |
</ul> | |
</div> | |
</div> | |
<div class="insight-section"> | |
<h4>Risk Management & Market Strategy</h4> | |
<div class="insight-card"> | |
<ul class="insight-list"> | |
<li>Most stable prices: Brinjal, Bottle gourd, Cauliflower</li> | |
<li>Best storage life: 6-9 months for Cauliflower, Brinjal, and Bottle gourd</li> | |
<li>Peak selling time for Cauliflower: March-April</li> | |
</ul> | |
</div> | |
</div> | |
<div class="action-box"> | |
<h5>Recommended Actions</h5> | |
<ul class="action-list"> | |
<li>Plant mix of beetroot, bitter gourd, bottle gourd, brinjal, and cauliflower</li> | |
<li>Focus on stable price markets for cauliflower and bottle gourd</li> | |
<li>Store cauliflower for March-April peak prices</li> | |
<li>Aim for premium quality grades to maximize profits</li> | |
</ul> | |
</div> | |
""" | |
if lang == 'mr': | |
html = translate_text(html) | |
# print(html | |
return html | |
return html | |
def get_districts(): | |
"""Get districts for selected state""" | |
state = request.form.get('state') | |
df = fetch_market_data(state=state) | |
districts = sorted(df['district'].dropna().unique()) | |
return jsonify(districts) | |
def get_markets(): | |
"""Get markets for selected district""" | |
district = request.form.get('district') | |
df = fetch_market_data(district=district) | |
markets = sorted(df['market'].dropna().unique()) | |
return jsonify(markets) | |
def get_commodities(): | |
"""Get commodities for selected market""" | |
market = request.form.get('market') | |
df = fetch_market_data(market=market) | |
commodities = sorted(df['commodity'].dropna().unique()) | |
return jsonify(commodities) | |
if __name__== '__main__': | |
app.run(host='0.0.0.0', port=7860) |