Pulastya B commited on
Commit
ba50130
·
1 Parent(s): bdf714a

fix: Support follow-up requests without re-uploading file

Browse files

- Made file parameter optional in /run endpoint
- Follow-up requests use session memory to resolve file path
- Fixes 422 error when asking follow-up questions
- Enables: Upload Report Train Model workflow

Files changed (1) hide show
  1. src/api/app.py +65 -3
src/api/app.py CHANGED
@@ -116,11 +116,12 @@ class AnalysisRequest(BaseModel):
116
 
117
  @app.post("/run")
118
  async def run_analysis(
119
- file: UploadFile = File(..., description="Dataset file (CSV or Parquet)"),
120
  task_description: str = Form(..., description="Natural language task description"),
121
  target_col: Optional[str] = Form(None, description="Target column name for prediction"),
122
  use_cache: bool = Form(True, description="Enable caching for expensive operations"),
123
- max_iterations: int = Form(20, description="Maximum workflow iterations")
 
124
  ) -> JSONResponse:
125
  """
126
  Run complete data science workflow on uploaded dataset.
@@ -148,7 +149,68 @@ async def run_analysis(
148
  if agent is None:
149
  raise HTTPException(status_code=503, detail="Agent not initialized")
150
 
151
- # Validate file format
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  filename = file.filename.lower()
153
  if not (filename.endswith('.csv') or filename.endswith('.parquet')):
154
  raise HTTPException(
 
116
 
117
  @app.post("/run")
118
  async def run_analysis(
119
+ file: Optional[UploadFile] = File(None, description="Dataset file (CSV or Parquet) - optional for follow-up requests"),
120
  task_description: str = Form(..., description="Natural language task description"),
121
  target_col: Optional[str] = Form(None, description="Target column name for prediction"),
122
  use_cache: bool = Form(True, description="Enable caching for expensive operations"),
123
+ max_iterations: int = Form(20, description="Maximum workflow iterations"),
124
+ session_id: Optional[str] = Form(None, description="Session ID for follow-up requests")
125
  ) -> JSONResponse:
126
  """
127
  Run complete data science workflow on uploaded dataset.
 
149
  if agent is None:
150
  raise HTTPException(status_code=503, detail="Agent not initialized")
151
 
152
+ # Handle follow-up requests (no file, using session memory)
153
+ if file is None:
154
+ logger.info(f"Follow-up request without file, using session memory")
155
+ logger.info(f"Task: {task_description}")
156
+
157
+ try:
158
+ # Agent's session memory should resolve file_path from context
159
+ result = agent.analyze(
160
+ file_path="", # Empty - will be resolved by session memory
161
+ task_description=task_description,
162
+ target_col=target_col,
163
+ use_cache=use_cache,
164
+ max_iterations=max_iterations
165
+ )
166
+
167
+ logger.info(f"Follow-up analysis completed: {result.get('status')}")
168
+
169
+ # Make result JSON serializable
170
+ def make_json_serializable(obj):
171
+ if isinstance(obj, dict):
172
+ return {k: make_json_serializable(v) for k, v in obj.items()}
173
+ elif isinstance(obj, list):
174
+ return [make_json_serializable(item) for item in obj]
175
+ elif hasattr(obj, '__class__') and obj.__class__.__name__ in ['Figure', 'Axes', 'Artist']:
176
+ return f"<{obj.__class__.__name__} object - see artifacts>"
177
+ elif isinstance(obj, (str, int, float, bool, type(None))):
178
+ return obj
179
+ else:
180
+ try:
181
+ return str(obj)
182
+ except:
183
+ return f"<{type(obj).__name__}>"
184
+
185
+ serializable_result = make_json_serializable(result)
186
+
187
+ return JSONResponse(
188
+ content={
189
+ "success": result.get("status") == "success",
190
+ "result": serializable_result,
191
+ "metadata": {
192
+ "filename": "session_context",
193
+ "task": task_description,
194
+ "target": target_col,
195
+ "provider": agent.provider,
196
+ "follow_up": True
197
+ }
198
+ },
199
+ status_code=200
200
+ )
201
+
202
+ except Exception as e:
203
+ logger.error(f"Follow-up analysis failed: {str(e)}", exc_info=True)
204
+ raise HTTPException(
205
+ status_code=500,
206
+ detail={
207
+ "error": str(e),
208
+ "error_type": type(e).__name__,
209
+ "message": "Follow-up request failed. Make sure you've uploaded a file first."
210
+ }
211
+ )
212
+
213
+ # Validate file format for new uploads
214
  filename = file.filename.lower()
215
  if not (filename.endswith('.csv') or filename.endswith('.parquet')):
216
  raise HTTPException(