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
@app.route('/')
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'))
@app.route('/filter_data', methods=['POST'])
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 = """
State |
District |
Market |
Commodity |
Variety |
Grade |
Arrival Date |
Min Price |
Max Price |
Modal Price |
"""
for _, row in df.iterrows():
market_table_html += f"""
{row['state']} |
{row['district']} |
{row['market']} |
{row['commodity']} |
{row['variety']} |
{row['grade']} |
{row['arrival_date']} |
₹{row['min_price']} |
₹{row['max_price']} |
₹{row['modal_price']} |
"""
market_table_html += "
"
# Generate top 5 cheapest crops table
cheapest_crops = df.sort_values('modal_price', ascending=True).head(5)
cheapest_table_html = """
Commodity |
Market |
Modal Price |
"""
for _, row in cheapest_crops.iterrows():
cheapest_table_html += f"""
{row['commodity']} |
{row['market']} |
₹{row['modal_price']} |
"""
cheapest_table_html += "
"
# Generate top 5 costliest crops table
costliest_crops = df.sort_values('modal_price', ascending=False).head(5)
costliest_table_html = """
Commodity |
Market |
Modal Price |
"""
for _, row in costliest_crops.iterrows():
costliest_table_html += f"""
{row['commodity']} |
{row['market']} |
₹{row['modal_price']} |
"""
costliest_table_html += "
"
# 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"""
Immediate Market Opportunities
Best Profit Potential
- Beetroot and Bitter gourd showing 15% increase from base year
- Bottle gourd premium quality fetching ₹150 per kg
Current Market Status
- Brinjal in high demand with stable price of ₹80 per kg
- Premium quality bottle gourd commanding ₹200 per kg
Strategic Planning
High Return Crops
- Cauliflower showing 20% increase from base year
- Best planting time: Spring season for cauliflower and bottle gourd
Recommended Crop Combinations
- Brinjal + Bottle gourd + Cauliflower (similar demand patterns)
Risk Management & Market Strategy
- Most stable prices: Brinjal, Bottle gourd, Cauliflower
- Best storage life: 6-9 months for Cauliflower, Brinjal, and Bottle gourd
- Peak selling time for Cauliflower: March-April
Recommended Actions
- Plant mix of beetroot, bitter gourd, bottle gourd, brinjal, and cauliflower
- Focus on stable price markets for cauliflower and bottle gourd
- Store cauliflower for March-April peak prices
- Aim for premium quality grades to maximize profits
"""
if lang == 'mr':
html = translate_text(html)
# print(html
return html
return html
@app.route('/get_districts', methods=['POST'])
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)
@app.route('/get_markets', methods=['POST'])
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)
@app.route('/get_commodities', methods=['POST'])
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)