Aniket2006 commited on
Commit
fb59133
·
1 Parent(s): 1699b79

Add time_series_data support for LLM context with historical + forecast data

Browse files
Files changed (2) hide show
  1. app.py +1 -0
  2. llm_analysis.py +57 -4
app.py CHANGED
@@ -134,6 +134,7 @@ class HeatmapRequest(BaseModel):
134
  metric: str # e.g., "soil_moisture", "pest_risk"
135
  gaussian_sigma: float = 1.5
136
  show_field_boundary: bool = True
 
137
 
138
 
139
  class HeatmapResponse(BaseModel):
 
134
  metric: str # e.g., "soil_moisture", "pest_risk"
135
  gaussian_sigma: float = 1.5
136
  show_field_boundary: bool = True
137
+ time_series_data: Optional[Dict[str, Any]] = None # Historical + forecast time series from Flutter cache
138
 
139
 
140
  class HeatmapResponse(BaseModel):
llm_analysis.py CHANGED
@@ -58,7 +58,7 @@ def call_gemini_with_fallback(prompt: str) -> str:
58
  return call_groq(prompt)
59
 
60
  def prepare_indices_context(summary_report: Dict, crop_type: str, farmer_context: Dict,
61
- temporal_stats: Dict = None) -> str:
62
  """
63
  Prepare a comprehensive context string for the LLM including temporal statistics.
64
 
@@ -126,6 +126,57 @@ VEGETATION INDICES DATA (ALL 13 INDICES):
126
  latest_rolling = float(np.nanmean(t_stats['rolling_avg_3'][-1]))
127
  context += f"\n - Latest Rolling Average (3-period): {latest_rolling:.4f}"
128
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  return context
130
 
131
  def format_stress_context(stress_context: Dict) -> str:
@@ -185,7 +236,8 @@ def format_stress_context(stress_context: Dict) -> str:
185
 
186
  def analyze_with_llm(summary_report: Dict, crop_type: str, farmer_context: Dict,
187
  center_lat: float, center_lon: float, field_size_hectares: float,
188
- temporal_stats: Dict = None, stress_context: Dict = None) -> Dict[str, Any]:
 
189
  """
190
  Analyze vegetation indices using Gemini LLM and extract soil insights.
191
 
@@ -198,12 +250,13 @@ def analyze_with_llm(summary_report: Dict, crop_type: str, farmer_context: Dict,
198
  field_size_hectares: Field size
199
  temporal_stats: Dictionary with temporal statistics
200
  stress_context: Dictionary with stress detection results (clustering, anomalies)
 
201
 
202
  Returns:
203
  Dictionary with structured LLM analysis results
204
  """
205
- # Prepare context with temporal statistics
206
- indices_context = prepare_indices_context(summary_report, crop_type, farmer_context, temporal_stats)
207
 
208
  # Prepare stress context
209
  stress_text = format_stress_context(stress_context)
 
58
  return call_groq(prompt)
59
 
60
  def prepare_indices_context(summary_report: Dict, crop_type: str, farmer_context: Dict,
61
+ temporal_stats: Dict = None, time_series_data: Dict = None) -> str:
62
  """
63
  Prepare a comprehensive context string for the LLM including temporal statistics.
64
 
 
126
  latest_rolling = float(np.nanmean(t_stats['rolling_avg_3'][-1]))
127
  context += f"\n - Latest Rolling Average (3-period): {latest_rolling:.4f}"
128
 
129
+ # Add time series data if provided (from Flutter cached data)
130
+ if time_series_data:
131
+ context += "\n\nTIME SERIES DATA (HISTORICAL + FORECAST):\n"
132
+ context += "=" * 45 + "\n"
133
+
134
+ for index_name, ts_data in time_series_data.items():
135
+ context += f"\n{index_name}:\n"
136
+
137
+ # Historical data summary
138
+ if 'historical' in ts_data and ts_data['historical']:
139
+ hist = ts_data['historical']
140
+ hist_count = len(hist)
141
+ if hist_count > 0:
142
+ # Get first and last values
143
+ first_hist = hist[0]
144
+ last_hist = hist[-1]
145
+ first_val = first_hist.get('value', 0)
146
+ last_val = last_hist.get('value', 0)
147
+ first_date = first_hist.get('date', 'N/A')
148
+ last_date = last_hist.get('date', 'N/A')
149
+
150
+ context += f" Historical ({hist_count} data points):\n"
151
+ context += f" - Start: {first_date} = {first_val:.4f}\n"
152
+ context += f" - End: {last_date} = {last_val:.4f}\n"
153
+ context += f" - Historical Change: {'+' if last_val > first_val else ''}{last_val - first_val:.4f}\n"
154
+
155
+ # Calculate average
156
+ avg_hist = sum(h.get('value', 0) for h in hist) / hist_count
157
+ context += f" - Average: {avg_hist:.4f}\n"
158
+
159
+ # Forecast data summary
160
+ if 'forecast' in ts_data and ts_data['forecast']:
161
+ fcast = ts_data['forecast']
162
+ fcast_count = len(fcast)
163
+ if fcast_count > 0:
164
+ first_fcast = fcast[0]
165
+ last_fcast = fcast[-1]
166
+ first_val = first_fcast.get('value', 0)
167
+ last_val = last_fcast.get('value', 0)
168
+ first_date = first_fcast.get('date', 'N/A')
169
+ last_date = last_fcast.get('date', 'N/A')
170
+
171
+ context += f" Forecast ({fcast_count} days ahead):\n"
172
+ context += f" - Start: {first_date} = {first_val:.4f}\n"
173
+ context += f" - End: {last_date} = {last_val:.4f}\n"
174
+ context += f" - Predicted Change: {'+' if last_val > first_val else ''}{last_val - first_val:.4f}\n"
175
+
176
+ # Calculate forecast average
177
+ avg_fcast = sum(f.get('value', 0) for f in fcast) / fcast_count
178
+ context += f" - Forecast Average: {avg_fcast:.4f}\n"
179
+
180
  return context
181
 
182
  def format_stress_context(stress_context: Dict) -> str:
 
236
 
237
  def analyze_with_llm(summary_report: Dict, crop_type: str, farmer_context: Dict,
238
  center_lat: float, center_lon: float, field_size_hectares: float,
239
+ temporal_stats: Dict = None, stress_context: Dict = None,
240
+ time_series_data: Dict = None) -> Dict[str, Any]:
241
  """
242
  Analyze vegetation indices using Gemini LLM and extract soil insights.
243
 
 
250
  field_size_hectares: Field size
251
  temporal_stats: Dictionary with temporal statistics
252
  stress_context: Dictionary with stress detection results (clustering, anomalies)
253
+ time_series_data: Dictionary with historical and forecast time series from Flutter cache
254
 
255
  Returns:
256
  Dictionary with structured LLM analysis results
257
  """
258
+ # Prepare context with temporal statistics and time series data
259
+ indices_context = prepare_indices_context(summary_report, crop_type, farmer_context, temporal_stats, time_series_data)
260
 
261
  # Prepare stress context
262
  stress_text = format_stress_context(stress_context)