Spaces:
Sleeping
Sleeping
Tracy André
commited on
Commit
·
1bfbe17
1
Parent(s):
d13ece1
updated
Browse files- mcp_server.py +13 -160
- test_clean_app.py +50 -0
mcp_server.py
CHANGED
|
@@ -108,38 +108,7 @@ def get_available_crops_resource() -> str:
|
|
| 108 |
except Exception as e:
|
| 109 |
return f"Error loading crops: {str(e)}"
|
| 110 |
|
| 111 |
-
@gr.mcp.resource("agricultural://years")
|
| 112 |
-
def get_available_years_resource() -> str:
|
| 113 |
-
"""Get range of years available in the dataset"""
|
| 114 |
-
try:
|
| 115 |
-
df = analyzer.load_data()
|
| 116 |
-
years = sorted(df['year'].dropna().unique())
|
| 117 |
-
return f"Available years: {min(years)}-{max(years)} ({len(years)} years total)"
|
| 118 |
-
except Exception as e:
|
| 119 |
-
return f"Error loading years: {str(e)}"
|
| 120 |
|
| 121 |
-
@gr.mcp.resource("agricultural://dataset-info")
|
| 122 |
-
def get_dataset_info() -> str:
|
| 123 |
-
"""Get comprehensive information about the agricultural dataset"""
|
| 124 |
-
try:
|
| 125 |
-
df = analyzer.load_data()
|
| 126 |
-
herbicide_data = df[df['is_herbicide'] == True]
|
| 127 |
-
|
| 128 |
-
info = f"""
|
| 129 |
-
Agricultural Dataset Information:
|
| 130 |
-
- Total records: {len(df):,}
|
| 131 |
-
- Years covered: {df['year'].min()}-{df['year'].max()}
|
| 132 |
-
- Number of plots: {df['plot_name'].nunique()}
|
| 133 |
-
- Number of crop types: {df['crop_type'].nunique()}
|
| 134 |
-
- Number of intervention types: {df['intervention_type'].nunique()}
|
| 135 |
-
- Herbicide applications: {len(herbicide_data):,}
|
| 136 |
-
- Average IFT (herbicides): {herbicide_data.groupby(['plot_name', 'year']).size().mean():.2f}
|
| 137 |
-
- Data source: Station Expérimentale de Kerguéhennec
|
| 138 |
-
- Last updated: 2025
|
| 139 |
-
"""
|
| 140 |
-
return info.strip()
|
| 141 |
-
except Exception as e:
|
| 142 |
-
return f"Error loading dataset info: {str(e)}"
|
| 143 |
|
| 144 |
@gr.mcp.resource("agricultural://plot/{plot_name}")
|
| 145 |
def get_plot_info(plot_name: str) -> str:
|
|
@@ -220,24 +189,7 @@ Year Summary: {year}
|
|
| 220 |
- Most active plot: {year_data['plot_name'].value_counts().index[0]} ({year_data['plot_name'].value_counts().iloc[0]} interventions)
|
| 221 |
- Most common crop: {year_data['crop_type'].value_counts().index[0]} ({year_data['crop_type'].value_counts().iloc[0]} interventions)
|
| 222 |
- Most common intervention: {year_data['intervention_type'].value_counts().index[0]} ({year_data['intervention_type'].value_counts().iloc[0]} interventions)
|
| 223 |
-
|
| 224 |
-
return info.strip()
|
| 225 |
-
except Exception as e:
|
| 226 |
-
return f"Error loading year summary: {str(e)}"
|
| 227 |
-
|
| 228 |
-
@gr.mcp.resource("agricultural://herbicide-usage")
|
| 229 |
-
def get_herbicide_usage_summary() -> str:
|
| 230 |
-
"""Get comprehensive summary of herbicide usage patterns"""
|
| 231 |
-
try:
|
| 232 |
-
df = analyzer.load_data()
|
| 233 |
-
herbicide_data = df[df['is_herbicide'] == True]
|
| 234 |
-
|
| 235 |
-
if len(herbicide_data) == 0:
|
| 236 |
-
return "No herbicide data available"
|
| 237 |
-
|
| 238 |
-
# Calculate IFT by plot and year
|
| 239 |
-
ift_data = herbicide_data.groupby(['plot_name', 'year']).size().reset_index(name='applications')
|
| 240 |
-
ift_data['ift'] = ift_data['applications'] / herbicide_data.groupby(['plot_name', 'year'])['plot_surface'].first().values
|
| 241 |
|
| 242 |
avg_ift = ift_data['ift'].mean()
|
| 243 |
max_ift = ift_data['ift'].max()
|
|
@@ -328,32 +280,6 @@ Sensitive Crop Recommendations (Pois, Haricot):
|
|
| 328 |
except Exception as e:
|
| 329 |
return f"Error loading recommendations summary: {str(e)}"
|
| 330 |
|
| 331 |
-
@gr.mcp.resource("agricultural://plot/{plot_name}/predictions")
|
| 332 |
-
def get_plot_predictions(plot_name: str) -> str:
|
| 333 |
-
"""Get weed pressure predictions for a specific plot"""
|
| 334 |
-
try:
|
| 335 |
-
predictions = analyzer.predict_weed_pressure()
|
| 336 |
-
plot_predictions = predictions[predictions['plot_name'] == plot_name]
|
| 337 |
-
|
| 338 |
-
if len(plot_predictions) == 0:
|
| 339 |
-
return f"No predictions available for plot '{plot_name}' - insufficient historical data"
|
| 340 |
-
|
| 341 |
-
plot_predictions = plot_predictions.sort_values('year')
|
| 342 |
-
|
| 343 |
-
info = f"""
|
| 344 |
-
Predictions for {plot_name}:
|
| 345 |
-
"""
|
| 346 |
-
for _, pred in plot_predictions.iterrows():
|
| 347 |
-
info += f"- {pred['year']}: IFT {pred['predicted_ift']:.2f} ({pred['risk_level']} risk)\n"
|
| 348 |
-
|
| 349 |
-
info += f"- Historical average IFT: {plot_predictions['historical_avg_ift'].iloc[0]:.2f}\n"
|
| 350 |
-
info += f"- Recent crops: {plot_predictions['recent_crops'].iloc[0]}\n"
|
| 351 |
-
info += f"- Recommendation: {'Suitable for sensitive crops' if plot_predictions['risk_level'].iloc[0] == 'Faible' else 'Not recommended for sensitive crops'}"
|
| 352 |
-
|
| 353 |
-
return info.strip()
|
| 354 |
-
except Exception as e:
|
| 355 |
-
return f"Error loading plot predictions: {str(e)}"
|
| 356 |
-
|
| 357 |
@gr.mcp.resource("agricultural://resources")
|
| 358 |
def list_mcp_resources() -> str:
|
| 359 |
"""List all available MCP resources with their URIs and descriptions"""
|
|
@@ -909,93 +835,20 @@ def create_mcp_interface():
|
|
| 909 |
with gr.Row():
|
| 910 |
resource_output = gr.Markdown(label="Résultat de la resource")
|
| 911 |
|
| 912 |
-
# Fonctions wrapper pour éviter les problèmes de lambda
|
| 913 |
-
def safe_plots():
|
| 914 |
-
try:
|
| 915 |
-
return get_available_plots_resource()
|
| 916 |
-
except Exception as e:
|
| 917 |
-
return f"Error: {str(e)}"
|
| 918 |
-
|
| 919 |
-
def safe_crops():
|
| 920 |
-
try:
|
| 921 |
-
return get_available_crops_resource()
|
| 922 |
-
except Exception as e:
|
| 923 |
-
return f"Error: {str(e)}"
|
| 924 |
-
|
| 925 |
-
def safe_years():
|
| 926 |
-
try:
|
| 927 |
-
return get_available_years_resource()
|
| 928 |
-
except Exception as e:
|
| 929 |
-
return f"Error: {str(e)}"
|
| 930 |
-
|
| 931 |
-
def safe_dataset():
|
| 932 |
-
try:
|
| 933 |
-
return get_dataset_info()
|
| 934 |
-
except Exception as e:
|
| 935 |
-
return f"Error: {str(e)}"
|
| 936 |
-
|
| 937 |
-
def safe_herbicide():
|
| 938 |
-
try:
|
| 939 |
-
return get_herbicide_usage_summary()
|
| 940 |
-
except Exception as e:
|
| 941 |
-
return f"Error: {str(e)}"
|
| 942 |
-
|
| 943 |
-
def safe_predictions():
|
| 944 |
-
try:
|
| 945 |
-
return get_predictions_summary()
|
| 946 |
-
except Exception as e:
|
| 947 |
-
return f"Error: {str(e)}"
|
| 948 |
-
|
| 949 |
-
def safe_recommendations():
|
| 950 |
-
try:
|
| 951 |
-
return get_recommendations_summary()
|
| 952 |
-
except Exception as e:
|
| 953 |
-
return f"Error: {str(e)}"
|
| 954 |
-
|
| 955 |
-
def safe_resources():
|
| 956 |
-
try:
|
| 957 |
-
return list_mcp_resources()
|
| 958 |
-
except Exception as e:
|
| 959 |
-
return f"Error: {str(e)}"
|
| 960 |
-
|
| 961 |
-
def safe_plot_info(plot):
|
| 962 |
-
try:
|
| 963 |
-
return get_plot_info(plot)
|
| 964 |
-
except Exception as e:
|
| 965 |
-
return f"Error: {str(e)}"
|
| 966 |
-
|
| 967 |
-
def safe_crop_info(crop):
|
| 968 |
-
try:
|
| 969 |
-
return get_crop_info(crop)
|
| 970 |
-
except Exception as e:
|
| 971 |
-
return f"Error: {str(e)}"
|
| 972 |
-
|
| 973 |
-
def safe_year_summary(year):
|
| 974 |
-
try:
|
| 975 |
-
return get_year_summary(int(year))
|
| 976 |
-
except Exception as e:
|
| 977 |
-
return f"Error: {str(e)}"
|
| 978 |
-
|
| 979 |
-
def safe_plot_predictions(plot):
|
| 980 |
-
try:
|
| 981 |
-
return get_plot_predictions(plot)
|
| 982 |
-
except Exception as e:
|
| 983 |
-
return f"Error: {str(e)}"
|
| 984 |
-
|
| 985 |
# Connexions des boutons
|
| 986 |
-
static_btn1.click(
|
| 987 |
-
static_btn2.click(
|
| 988 |
-
static_btn3.click(
|
| 989 |
-
static_btn4.click(
|
| 990 |
-
static_btn5.click(
|
| 991 |
-
static_btn6.click(
|
| 992 |
-
static_btn7.click(
|
| 993 |
-
static_btn8.click(
|
| 994 |
|
| 995 |
-
plot_btn.click(
|
| 996 |
-
crop_btn.click(
|
| 997 |
-
year_btn.click(
|
| 998 |
-
pred_plot_btn.click(
|
| 999 |
|
| 1000 |
return demo
|
| 1001 |
|
|
|
|
| 108 |
except Exception as e:
|
| 109 |
return f"Error loading crops: {str(e)}"
|
| 110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
|
| 113 |
@gr.mcp.resource("agricultural://plot/{plot_name}")
|
| 114 |
def get_plot_info(plot_name: str) -> str:
|
|
|
|
| 189 |
- Most active plot: {year_data['plot_name'].value_counts().index[0]} ({year_data['plot_name'].value_counts().iloc[0]} interventions)
|
| 190 |
- Most common crop: {year_data['crop_type'].value_counts().index[0]} ({year_data['crop_type'].value_counts().iloc[0]} interventions)
|
| 191 |
- Most common intervention: {year_data['intervention_type'].value_counts().index[0]} ({year_data['intervention_type'].value_counts().iloc[0]} interventions)
|
| 192 |
+
groupby(['plot_name', 'year'])['plot_surface'].first().values
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
|
| 194 |
avg_ift = ift_data['ift'].mean()
|
| 195 |
max_ift = ift_data['ift'].max()
|
|
|
|
| 280 |
except Exception as e:
|
| 281 |
return f"Error loading recommendations summary: {str(e)}"
|
| 282 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 283 |
@gr.mcp.resource("agricultural://resources")
|
| 284 |
def list_mcp_resources() -> str:
|
| 285 |
"""List all available MCP resources with their URIs and descriptions"""
|
|
|
|
| 835 |
with gr.Row():
|
| 836 |
resource_output = gr.Markdown(label="Résultat de la resource")
|
| 837 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 838 |
# Connexions des boutons
|
| 839 |
+
static_btn1.click(lambda: get_available_plots_resource(), outputs=[resource_output])
|
| 840 |
+
static_btn2.click(lambda: get_available_crops_resource(), outputs=[resource_output])
|
| 841 |
+
static_btn3.click(lambda: get_available_years_resource(), outputs=[resource_output])
|
| 842 |
+
static_btn4.click(lambda: get_dataset_info(), outputs=[resource_output])
|
| 843 |
+
static_btn5.click(lambda: get_herbicide_usage_summary(), outputs=[resource_output])
|
| 844 |
+
static_btn6.click(lambda: get_predictions_summary(), outputs=[resource_output])
|
| 845 |
+
static_btn7.click(lambda: get_recommendations_summary(), outputs=[resource_output])
|
| 846 |
+
static_btn8.click(lambda: list_mcp_resources(), outputs=[resource_output])
|
| 847 |
|
| 848 |
+
plot_btn.click(lambda plot: get_plot_info(plot), inputs=[plot_input], outputs=[resource_output])
|
| 849 |
+
crop_btn.click(lambda crop: get_crop_info(crop), inputs=[crop_input], outputs=[resource_output])
|
| 850 |
+
year_btn.click(lambda year: get_year_summary(int(year)), inputs=[year_input], outputs=[resource_output])
|
| 851 |
+
pred_plot_btn.click(lambda plot: get_plot_predictions(plot), inputs=[pred_plot_input], outputs=[resource_output])
|
| 852 |
|
| 853 |
return demo
|
| 854 |
|
test_clean_app.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Test de l'application après suppression des fonctions safe_*
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
import os
|
| 6 |
+
from mcp_server import create_mcp_interface
|
| 7 |
+
|
| 8 |
+
# Hugging Face configuration
|
| 9 |
+
hf_token = os.environ.get("HF_TOKEN")
|
| 10 |
+
if hf_token:
|
| 11 |
+
os.environ["HF_TOKEN"] = hf_token
|
| 12 |
+
os.environ["DATASET_ID"] = "HackathonCRA/2024"
|
| 13 |
+
|
| 14 |
+
def test_clean_app():
|
| 15 |
+
"""Test de l'application après nettoyage"""
|
| 16 |
+
print("🧪 Test de l'application après suppression des fonctions safe_*...")
|
| 17 |
+
|
| 18 |
+
try:
|
| 19 |
+
demo = create_mcp_interface()
|
| 20 |
+
print("✅ Interface créée avec succès")
|
| 21 |
+
|
| 22 |
+
# Test des resources MCP
|
| 23 |
+
from mcp_server import (
|
| 24 |
+
get_available_plots_resource,
|
| 25 |
+
get_dataset_info,
|
| 26 |
+
get_plot_info,
|
| 27 |
+
list_mcp_resources
|
| 28 |
+
)
|
| 29 |
+
|
| 30 |
+
print("\n📋 Test des resources MCP:")
|
| 31 |
+
print("Plots:", get_available_plots_resource()[:100] + "...")
|
| 32 |
+
print("Dataset:", get_dataset_info()[:100] + "...")
|
| 33 |
+
print("Plot info:", get_plot_info("Champ ferme W du sol")[:100] + "...")
|
| 34 |
+
|
| 35 |
+
print("\n🎯 Application nettoyée et fonctionnelle !")
|
| 36 |
+
print("📋 5 onglets disponibles")
|
| 37 |
+
print("🔧 12 resources MCP avec @gr.mcp.resource")
|
| 38 |
+
print("✅ Fonctions safe_* supprimées")
|
| 39 |
+
print("🚀 Prêt pour déploiement")
|
| 40 |
+
|
| 41 |
+
return True
|
| 42 |
+
|
| 43 |
+
except Exception as e:
|
| 44 |
+
print(f"❌ Erreur: {e}")
|
| 45 |
+
import traceback
|
| 46 |
+
traceback.print_exc()
|
| 47 |
+
return False
|
| 48 |
+
|
| 49 |
+
if __name__ == "__main__":
|
| 50 |
+
test_clean_app()
|