Spaces:
Running
Running
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
- 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(
|
| 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 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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(
|