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 = "579b464db66ec23bdd000001189bbb99e979428764bdbe8fdd44ebb7" | |
| 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 Gemini 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 Gemini API prompt | |
| 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. | |
| """ | |
| gemini_api_key = os.getenv("GEMINI_API_KEY") | |
| gemini_api_url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key={gemini_api_key}" | |
| headers = { | |
| "Content-Type": "application/json" | |
| } | |
| payload = { | |
| "contents": [ | |
| { | |
| "parts": [ | |
| {"text": prompt} | |
| ] | |
| } | |
| ] | |
| } | |
| response = requests.post(gemini_api_url, headers=headers, json=payload) | |
| if response.status_code == 200: | |
| response_data = response.json() | |
| if response_data and "candidates" in response_data and len(response_data["candidates"]) > 0: | |
| candidate = response_data["candidates"][0] | |
| insights = candidate.get("output", {}).get("text", "") or candidate.get("text", "") | |
| 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 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(debug=True, host='0.0.0.0', port=7860) | |