Soumik555 commited on
Commit
8aab038
·
1 Parent(s): 7972f38

robust null checking for process_response

Browse files
Files changed (1) hide show
  1. python_code_executor_service.py +63 -73
python_code_executor_service.py CHANGED
@@ -43,10 +43,8 @@ class AnalysisOperation(BaseModel):
43
  class CsvChatResult(BaseModel):
44
  """Structured response for CSV-related AI interactions"""
45
  casual_response: str
46
- # analysis_operations: List[AnalysisOperation]
47
- # charts: Optional[List[ChartSpecification]] = None
48
- analysis_operations: Optional[AnalysisOperation] = None
49
- charts: Optional[ChartSpecification] = None
50
 
51
 
52
  class PythonExecutor:
@@ -196,82 +194,74 @@ class PythonExecutor:
196
  return str(result)
197
 
198
  async def process_response(self, response: CsvChatResult, chat_id: str) -> str:
199
- """Process the response with comprehensive error handling"""
200
- if not response or not response.casual_response:
201
- return "⚠️ Error: Empty response received"
202
-
203
- output_parts = [response.casual_response]
204
 
205
- # Process analysis operation if present and valid
206
- if hasattr(response, 'analysis_operations') and response.analysis_operations:
207
- try:
208
- operation = response.analysis_operations
209
-
210
- # Validate operation structure
211
- if not hasattr(operation, 'code') or not operation.code:
212
- output_parts.append("\n⚠️ Analysis operation missing code")
213
- elif not hasattr(operation.code, 'code') or not operation.code.code:
214
- output_parts.append("\n⚠️ Analysis operation has empty code")
215
- elif not hasattr(operation, 'result_var') or not operation.result_var:
216
- output_parts.append("\n⚠️ Analysis operation missing result variable")
217
- else:
218
- # Execute the operation if all checks pass
219
- execution_result = self.execute_code(operation.code.code)
220
 
221
- if execution_result.get('error'):
222
- output_parts.append(f"\n❌ Error in analysis operation:")
223
- output_parts.append("```python\n" + execution_result['error']['message'] + "\n```")
224
- else:
225
  result = self.exec_locals.get(operation.result_var)
226
-
227
- if result is None:
228
- output_parts.append(f"\n⚠️ Operation completed but no result found in variable '{operation.result_var}'")
229
- elif hasattr(result, '__len__') and len(result) == 0:
230
- output_parts.append("\n⚠️ Operation returned empty results")
 
 
 
 
 
 
231
  else:
232
- output_parts.append(f"\n🔹 Operation results:")
233
- output_parts.append("```python\n" + self._format_result(result) + "\n```")
234
-
235
- if execution_result.get('output'):
236
- output_parts.append("Console output:\n```\n" + execution_result['output'] + "\n```")
237
-
238
- except Exception as e:
239
- output_parts.append(f"\n❌ Unexpected error processing analysis operation: {str(e)}")
 
240
 
241
- # Process chart if present and valid
242
- if hasattr(response, 'charts') and response.charts:
243
- try:
244
  chart = response.charts
245
-
246
- # Validate chart structure
247
- if not hasattr(chart, 'image_description') or not chart.image_description:
248
- output_parts.append("\n⚠️ Chart missing description")
249
- elif not hasattr(chart, 'code') or not chart.code:
250
- output_parts.append("\n⚠️ Chart specification missing code")
251
- else:
252
- chart_result = self.execute_code(chart.code)
253
-
254
- if chart_result.get('error'):
255
- output_parts.append(f"\n❌ Error generating chart '{chart.image_description}':")
256
- output_parts.append("```python\n" + chart_result['error']['message'] + "\n```")
257
- elif not chart_result.get('plots'):
258
- output_parts.append(f"\n⚠️ No chart generated for '{chart.image_description}'")
 
 
 
 
 
 
 
 
259
  else:
260
- output_parts.append("\n📊 Visualization:")
261
- for plot_data in chart_result['plots']:
262
- try:
263
- public_url = await self.save_plot_to_supabase(
264
- plot_data=plot_data,
265
- description=chart.image_description,
266
- chat_id=chat_id
267
- )
268
- output_parts.append(f"\n🖼️ {chart.image_description}")
269
- output_parts.append(f"![{chart.image_description}]({public_url})")
270
- except Exception as upload_error:
271
- output_parts.append(f"\n⚠️ Failed to upload chart: {str(upload_error)}")
272
-
273
- except Exception as e:
274
- output_parts.append(f"\n❌ Unexpected error processing chart: {str(e)}")
275
 
276
  return "\n".join(output_parts)
277
 
 
43
  class CsvChatResult(BaseModel):
44
  """Structured response for CSV-related AI interactions"""
45
  casual_response: str
46
+ analysis_operations: Optional[AnalysisOperation]
47
+ charts: Optional[ChartSpecification]
 
 
48
 
49
 
50
  class PythonExecutor:
 
194
  return str(result)
195
 
196
  async def process_response(self, response: CsvChatResult, chat_id: str) -> str:
197
+ """Process the response with proper variable handling and error checking"""
198
+ output_parts = [response.casual_response]
 
 
 
199
 
200
+ # Initialize execution_result to avoid reference before assignment
201
+ execution_result = None
202
+ operation = None
203
+
204
+ # Process analysis operation if it exists
205
+ if response.analysis_operations is not None:
206
+ try:
207
+ operation = response.analysis_operations
208
+ if operation and operation.code and operation.code.code:
209
+ execution_result = self.execute_code(operation.code.code)
 
 
 
 
 
210
 
211
+ # Get the result from locals
 
 
 
212
  result = self.exec_locals.get(operation.result_var)
213
+
214
+ if execution_result.get('error'):
215
+ output_parts.append(f"\n Error in operation '{operation.result_var}':")
216
+ output_parts.append("```python\n" + execution_result['error']['message'] + "\n```")
217
+ elif result is not None:
218
+ # Handle empty/None results
219
+ if result is None or (hasattr(result, '__len__') and len(result) == 0):
220
+ output_parts.append(f"\n⚠️ Values are missing - Operation '{operation.result_var}' returned no data")
221
+ else:
222
+ output_parts.append(f"\n🔹 Result for '{operation.result_var}':")
223
+ output_parts.append("```python\n" + self._format_result(result) + "\n```")
224
  else:
225
+ output_str = execution_result.get('output', '').strip()
226
+ if output_str:
227
+ output_parts.append("```\n" + output_str + "\n```")
228
+ else:
229
+ output_parts.append("\n⚠️ Invalid analysis operation - missing code or result variable")
230
+ except Exception as e:
231
+ output_parts.append(f"\n❌ Error processing analysis operation: {str(e)}")
232
+ if operation:
233
+ output_parts.append(f"Operation: {operation.result_var}")
234
 
235
+ # Process chart if it exists
236
+ if response.charts is not None:
237
+ output_parts.append("\n📊 Visualizations:")
238
  chart = response.charts
239
+ try:
240
+ if chart and (chart.code or chart.image_description):
241
+ if chart.code:
242
+ chart_result = self.execute_code(chart.code)
243
+ if chart_result.get('plots'):
244
+ for plot_data in chart_result['plots']:
245
+ try:
246
+ public_url = await self.save_plot_to_supabase(
247
+ plot_data=plot_data,
248
+ description=chart.image_description,
249
+ chat_id=chat_id
250
+ )
251
+ output_parts.append(f"\n🖼️ {chart.image_description}")
252
+ output_parts.append(f"![{chart.image_description}]({public_url})")
253
+ except Exception as e:
254
+ output_parts.append(f"\n⚠️ Error uploading chart: {str(e)}")
255
+ elif chart_result.get('error'):
256
+ output_parts.append("```python\n" + f"Error generating {chart.image_description}: {chart_result['error']['message']}" + "\n```")
257
+ else:
258
+ output_parts.append(f"\n⚠️ No chart generated for '{chart.image_description}'")
259
+ else:
260
+ output_parts.append(f"\n⚠️ No code provided for chart: {chart.image_description}")
261
  else:
262
+ output_parts.append("\n⚠️ Invalid chart specification")
263
+ except Exception as e:
264
+ output_parts.append(f"\n❌ Error processing chart: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
265
 
266
  return "\n".join(output_parts)
267