Tracy André commited on
Commit
6b78689
·
1 Parent(s): 1bfbe17
Files changed (3) hide show
  1. app.py +1 -1
  2. mcp_server.py +0 -279
  3. test_fixed_syntax.py +36 -0
app.py CHANGED
@@ -12,4 +12,4 @@ if hf_token:
12
  os.environ["DATASET_ID"] = "HackathonCRA/2024"
13
 
14
  demo = create_mcp_interface()
15
- demo.launch(share=True, mcp_server=True)
 
12
  os.environ["DATASET_ID"] = "HackathonCRA/2024"
13
 
14
  demo = create_mcp_interface()
15
+ demo.launch(share=True)
mcp_server.py CHANGED
@@ -89,237 +89,8 @@ class WeedPressureAnalyzer:
89
  # Initialize analyzer
90
  analyzer = WeedPressureAnalyzer()
91
 
92
- # MCP Resources - Using Gradio's built-in @gr.mcp.resource decorator
93
- @gr.mcp.resource("agricultural://plots")
94
- def get_available_plots_resource() -> str:
95
- """Get list of all available agricultural plots from the dataset"""
96
- try:
97
- plots = get_available_plots()
98
- return f"Available plots ({len(plots)-1}): " + ", ".join(plots[1:6]) + f" ... and {len(plots)-6} more"
99
- except Exception as e:
100
- return f"Error loading plots: {str(e)}"
101
-
102
- @gr.mcp.resource("agricultural://crops")
103
- def get_available_crops_resource() -> str:
104
- """Get list of all crop types in the dataset"""
105
- try:
106
- crops = get_available_crops()
107
- return f"Available crops ({len(crops)-1}): " + ", ".join(crops[1:6]) + f" ... and {len(crops)-6} more"
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:
115
- """Get detailed information about a specific agricultural plot"""
116
- try:
117
- df = analyzer.load_data()
118
- plot_data = df[df['plot_name'] == plot_name]
119
-
120
- if len(plot_data) == 0:
121
- return f"Plot '{plot_name}' not found in dataset"
122
-
123
- herbicide_data = plot_data[plot_data['is_herbicide'] == True]
124
- years = sorted(plot_data['year'].unique())
125
-
126
- info = f"""
127
- Plot Information: {plot_name}
128
- - Total interventions: {len(plot_data):,}
129
- - Years active: {min(years)}-{max(years)} ({len(years)} years)
130
- - Herbicide applications: {len(herbicide_data):,}
131
- - Average IFT: {herbicide_data.groupby('year').size().mean():.2f}
132
- - Surface: {plot_data['plot_surface'].iloc[0]:.2f} hectares
133
- - Main crops: {', '.join(plot_data['crop_type'].value_counts().head(3).index.tolist())}
134
- - Main interventions: {', '.join(plot_data['intervention_type'].value_counts().head(3).index.tolist())}
135
- """
136
- return info.strip()
137
- except Exception as e:
138
- return f"Error loading plot info: {str(e)}"
139
 
140
- @gr.mcp.resource("agricultural://crop/{crop_type}")
141
- def get_crop_info(crop_type: str) -> str:
142
- """Get information about a specific crop type and its cultivation patterns"""
143
- try:
144
- df = analyzer.load_data()
145
- crop_data = df[df['crop_type'] == crop_type]
146
-
147
- if len(crop_data) == 0:
148
- return f"Crop type '{crop_type}' not found in dataset"
149
-
150
- herbicide_data = crop_data[crop_data['is_herbicide'] == True]
151
- years = sorted(crop_data['year'].unique())
152
- plots = crop_data['plot_name'].nunique()
153
-
154
- info = f"""
155
- Crop Information: {crop_type}
156
- - Total interventions: {len(crop_data):,}
157
- - Years cultivated: {min(years)}-{max(years)} ({len(years)} years)
158
- - Number of plots: {plots}
159
- - Herbicide applications: {len(herbicide_data):,}
160
- - Average IFT: {herbicide_data.groupby(['plot_name', 'year']).size().mean():.2f}
161
- - Main plots: {', '.join(crop_data['plot_name'].value_counts().head(3).index.tolist())}
162
- - Main interventions: {', '.join(crop_data['intervention_type'].value_counts().head(3).index.tolist())}
163
- """
164
- return info.strip()
165
- except Exception as e:
166
- return f"Error loading crop info: {str(e)}"
167
-
168
- @gr.mcp.resource("agricultural://year/{year}")
169
- def get_year_summary(year: int) -> str:
170
- """Get summary of agricultural activities for a specific year"""
171
- try:
172
- df = analyzer.load_data()
173
- year_data = df[df['year'] == year]
174
-
175
- if len(year_data) == 0:
176
- return f"No data available for year {year}"
177
-
178
- herbicide_data = year_data[year_data['is_herbicide'] == True]
179
- plots = year_data['plot_name'].nunique()
180
- crops = year_data['crop_type'].nunique()
181
-
182
- info = f"""
183
- Year Summary: {year}
184
- - Total interventions: {len(year_data):,}
185
- - Active plots: {plots}
186
- - Crop types: {crops}
187
- - Herbicide applications: {len(herbicide_data):,}
188
- - Average IFT: {herbicide_data.groupby('plot_name').size().mean():.2f}
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()
196
- min_ift = ift_data['ift'].min()
197
-
198
- # Risk distribution
199
- low_risk = len(ift_data[ift_data['ift'] < 1.0])
200
- moderate_risk = len(ift_data[(ift_data['ift'] >= 1.0) & (ift_data['ift'] < 2.0)])
201
- high_risk = len(ift_data[ift_data['ift'] >= 2.0])
202
-
203
- info = f"""
204
- Herbicide Usage Summary:
205
- - Total applications: {len(herbicide_data):,}
206
- - Plots with herbicides: {herbicide_data['plot_name'].nunique()}
207
- - Years with data: {herbicide_data['year'].nunique()}
208
- - Average IFT: {avg_ift:.2f}
209
- - IFT range: {min_ift:.2f} - {max_ift:.2f}
210
- - Risk distribution:
211
- * Low risk (IFT < 1.0): {low_risk} plot-years ({low_risk/len(ift_data)*100:.1f}%)
212
- * Moderate risk (1.0 ≤ IFT < 2.0): {moderate_risk} plot-years ({moderate_risk/len(ift_data)*100:.1f}%)
213
- * High risk (IFT ≥ 2.0): {high_risk} plot-years ({high_risk/len(ift_data)*100:.1f}%)
214
- - Most used herbicides: {', '.join(herbicide_data['produit'].value_counts().head(3).index.tolist())}
215
- """
216
- return info.strip()
217
- except Exception as e:
218
- return f"Error loading herbicide usage summary: {str(e)}"
219
 
220
- @gr.mcp.resource("agricultural://predictions/2025-2027")
221
- def get_predictions_summary() -> str:
222
- """Get summary of weed pressure predictions for 2025-2027"""
223
- try:
224
- predictions = analyzer.predict_weed_pressure()
225
-
226
- if len(predictions) == 0:
227
- return "No predictions available - insufficient historical data"
228
-
229
- low_risk = len(predictions[predictions['risk_level'] == 'Faible'])
230
- moderate_risk = len(predictions[predictions['risk_level'] == 'Modéré'])
231
- high_risk = len(predictions[predictions['risk_level'] == 'Élevé'])
232
-
233
- avg_ift = predictions['predicted_ift'].mean()
234
-
235
- info = f"""
236
- Weed Pressure Predictions 2025-2027:
237
- - Total predictions: {len(predictions)}
238
- - Average predicted IFT: {avg_ift:.2f}
239
- - Risk distribution:
240
- * Low risk (IFT < 1.0): {low_risk} predictions ({low_risk/len(predictions)*100:.1f}%)
241
- * Moderate risk (1.0 ≤ IFT < 2.0): {moderate_risk} predictions ({moderate_risk/len(predictions)*100:.1f}%)
242
- * High risk (IFT ≥ 2.0): {high_risk} predictions ({high_risk/len(predictions)*100:.1f}%)
243
- - Best plots (lowest IFT): {', '.join(predictions.nsmallest(3, 'predicted_ift')['plot_name'].tolist())}
244
- - Method: Linear regression on historical IFT data
245
- """
246
- return info.strip()
247
- except Exception as e:
248
- return f"Error loading predictions summary: {str(e)}"
249
-
250
- @gr.mcp.resource("agricultural://recommendations/sensitive-crops")
251
- def get_recommendations_summary() -> str:
252
- """Get summary of plot recommendations for sensitive crops (pois, haricot)"""
253
- try:
254
- predictions = analyzer.predict_weed_pressure()
255
- suitable_plots = predictions[predictions['risk_level'] == "Faible"].copy()
256
-
257
- if len(suitable_plots) == 0:
258
- return "No plots recommended for sensitive crops - all plots have high predicted weed pressure"
259
-
260
- suitable_plots['recommendation_score'] = 100 - (suitable_plots['predicted_ift'] * 30)
261
- suitable_plots = suitable_plots.sort_values('recommendation_score', ascending=False)
262
-
263
- top_plots = suitable_plots.head(5)
264
- avg_score = suitable_plots['recommendation_score'].mean()
265
-
266
- info = f"""
267
- Sensitive Crop Recommendations (Pois, Haricot):
268
- - Suitable plots: {len(suitable_plots)}
269
- - Average recommendation score: {avg_score:.1f}/100
270
- - Top 5 recommended plots:
271
- """
272
- for i, (_, plot) in enumerate(top_plots.iterrows(), 1):
273
- info += f" {i}. {plot['plot_name']} - Score: {plot['recommendation_score']:.1f}, IFT: {plot['predicted_ift']:.2f}\n"
274
-
275
- info += f"- Criteria: IFT < 1.0 (low weed pressure)\n"
276
- info += f"- Score formula: 100 - (predicted_ift × 30)\n"
277
- info += f"- Method: Based on 2025-2027 predictions"
278
-
279
- return info.strip()
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"""
286
- return """## Available MCP Resources
287
-
288
- ### `agricultural://plots`
289
- **Description:** Get list of all available agricultural plots from the dataset
290
-
291
- ### `agricultural://crops`
292
- **Description:** Get list of all crop types in the dataset
293
-
294
- ### `agricultural://years`
295
- **Description:** Get range of years available in the dataset
296
-
297
- ### `agricultural://dataset-info`
298
- **Description:** Get comprehensive information about the agricultural dataset
299
-
300
- ### `agricultural://plot/{plot_name}`
301
- **Description:** Get detailed information about a specific agricultural plot
302
-
303
- ### `agricultural://crop/{crop_type}`
304
- **Description:** Get information about a specific crop type and its cultivation patterns
305
-
306
- ### `agricultural://year/{year}`
307
- **Description:** Get summary of agricultural activities for a specific year
308
-
309
- ### `agricultural://herbicide-usage`
310
- **Description:** Get comprehensive summary of herbicide usage patterns
311
-
312
- ### `agricultural://predictions/2025-2027`
313
- **Description:** Get summary of weed pressure predictions for 2025-2027
314
-
315
- ### `agricultural://recommendations/sensitive-crops`
316
- **Description:** Get summary of plot recommendations for sensitive crops (pois, haricot)
317
-
318
- ### `agricultural://plot/{plot_name}/predictions`
319
- **Description:** Get weed pressure predictions for a specific plot
320
-
321
- ### `agricultural://resources`
322
- **Description:** List all available MCP resources with their URIs and descriptions"""
323
 
324
  def analyze_herbicide_trends(year_start, year_end, plot_filter):
325
  """
@@ -799,56 +570,6 @@ def create_mcp_interface():
799
  outputs=[data_plot, data_summary]
800
  )
801
 
802
- with gr.Tab("🔧 Resources MCP"):
803
- gr.Markdown("### Resources MCP disponibles pour les LLM")
804
- gr.Markdown("""
805
- Ces resources fournissent un accès structuré aux données agricoles pour les LLM via le protocole MCP.
806
- """)
807
-
808
- with gr.Row():
809
- with gr.Column():
810
- gr.Markdown("#### Resources statiques")
811
- static_btn1 = gr.Button("📋 Plots disponibles", variant="secondary")
812
- static_btn2 = gr.Button("🌾 Cultures disponibles", variant="secondary")
813
- static_btn3 = gr.Button("📅 Années disponibles", variant="secondary")
814
- static_btn4 = gr.Button("📊 Info dataset", variant="secondary")
815
- static_btn5 = gr.Button("🧪 Usage herbicides", variant="secondary")
816
- static_btn6 = gr.Button("🔮 Prédictions 2025-2027", variant="secondary")
817
- static_btn7 = gr.Button("🌱 Recommandations", variant="secondary")
818
- static_btn8 = gr.Button("📋 Liste Resources", variant="primary")
819
-
820
- with gr.Column():
821
- gr.Markdown("#### Resources paramétrées")
822
- with gr.Row():
823
- plot_input = gr.Textbox(label="Nom de parcelle", placeholder="Champ ferme W du sol")
824
- plot_btn = gr.Button("🏞️ Info parcelle", variant="secondary")
825
- with gr.Row():
826
- crop_input = gr.Textbox(label="Type de culture", placeholder="blé tendre hiver")
827
- crop_btn = gr.Button("🌾 Info culture", variant="secondary")
828
- with gr.Row():
829
- year_input = gr.Number(label="Année", value=2023, precision=0)
830
- year_btn = gr.Button("📅 Résumé année", variant="secondary")
831
- with gr.Row():
832
- pred_plot_input = gr.Textbox(label="Parcelle pour prédictions", placeholder="Etang 5")
833
- pred_plot_btn = gr.Button("🔮 Prédictions parcelle", variant="secondary")
834
-
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
 
 
89
  # Initialize analyzer
90
  analyzer = WeedPressureAnalyzer()
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
  def analyze_herbicide_trends(year_start, year_end, plot_filter):
96
  """
 
570
  outputs=[data_plot, data_summary]
571
  )
572
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
573
 
574
  return demo
575
 
test_fixed_syntax.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Test de l'application après correction de l'erreur de syntaxe
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_fixed_syntax():
15
+ """Test de l'application après correction de l'erreur de syntaxe"""
16
+ print("🧪 Test de l'application après correction de l'erreur de syntaxe...")
17
+
18
+ try:
19
+ demo = create_mcp_interface()
20
+ print("✅ Interface créée avec succès")
21
+
22
+ print("\n🎯 Application corrigée et fonctionnelle !")
23
+ print("📋 4 onglets disponibles (sans Resources MCP)")
24
+ print("✅ Erreur de syntaxe corrigée")
25
+ print("🚀 Prêt pour déploiement")
26
+
27
+ return True
28
+
29
+ except Exception as e:
30
+ print(f"❌ Erreur: {e}")
31
+ import traceback
32
+ traceback.print_exc()
33
+ return False
34
+
35
+ if __name__ == "__main__":
36
+ test_fixed_syntax()