Spaces:
Running
Fix hyperparameter_tuning output_path bug: save to both artifact store AND user-requested path
Browse filesCRITICAL BUG FIX:
- hyperparameter_tuning was saving models to artifact store temp paths (e.g., tmpa4t7tgci.pkl)
- But LLM was looking for models at user-specified output_path (e.g., hyperparameter_tuned_model.pkl)
- This caused generate_model_report and subsequent tools to fail with 'File not found'
SOLUTION:
- Don't overwrite output_path variable with artifact store's temp path
- Save to BOTH locations: artifact store (for internal tracking) AND user-requested path (for LLM)
- Return user-requested path in model_path field so LLM can find it
CHANGES:
1. hyperparameter_tuning(): Save to both artifact store AND output_path
2. ensemble_models() voting/stacking: Save to both locations
3. ensemble_models() blending: Save to both locations
All three functions now:
- Use actual_model_path for artifact store internal path
- Keep output_path unchanged for LLM
- Save model to output_path so LLM can find it
- Return output_path in result's model_path field
This was NOT a streaming bug - tool implementation bug that existed before streaming.
|
@@ -293,9 +293,11 @@ def hyperparameter_tuning(
|
|
| 293 |
}
|
| 294 |
|
| 295 |
# Save model if output path provided
|
|
|
|
| 296 |
if output_path:
|
| 297 |
if ARTIFACT_STORE_AVAILABLE:
|
| 298 |
-
|
|
|
|
| 299 |
model_data=final_model,
|
| 300 |
filename=os.path.basename(output_path),
|
| 301 |
metadata={
|
|
@@ -306,10 +308,15 @@ def hyperparameter_tuning(
|
|
| 306 |
"test_metrics": test_metrics
|
| 307 |
}
|
| 308 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 309 |
else:
|
| 310 |
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
| 311 |
joblib.dump(final_model, output_path)
|
| 312 |
-
|
|
|
|
| 313 |
|
| 314 |
return {
|
| 315 |
'status': 'success',
|
|
@@ -512,9 +519,11 @@ def train_ensemble_models(
|
|
| 512 |
}
|
| 513 |
|
| 514 |
# Save for blending
|
|
|
|
| 515 |
if output_path:
|
| 516 |
if ARTIFACT_STORE_AVAILABLE:
|
| 517 |
-
|
|
|
|
| 518 |
model_data={
|
| 519 |
'base_models': dict(base_models),
|
| 520 |
'meta_model': meta_model,
|
|
@@ -528,6 +537,13 @@ def train_ensemble_models(
|
|
| 528 |
"num_base_models": len(base_models)
|
| 529 |
}
|
| 530 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 531 |
else:
|
| 532 |
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
| 533 |
joblib.dump({
|
|
@@ -535,6 +551,7 @@ def train_ensemble_models(
|
|
| 535 |
'meta_model': meta_model,
|
| 536 |
'ensemble_type': 'blending'
|
| 537 |
}, output_path)
|
|
|
|
| 538 |
|
| 539 |
return {
|
| 540 |
'status': 'success',
|
|
@@ -573,9 +590,11 @@ def train_ensemble_models(
|
|
| 573 |
improvement = ensemble_metrics['r2'] - best_individual_metric
|
| 574 |
|
| 575 |
# Save model
|
|
|
|
| 576 |
if output_path:
|
| 577 |
if ARTIFACT_STORE_AVAILABLE:
|
| 578 |
-
|
|
|
|
| 579 |
model_data=ensemble,
|
| 580 |
filename=os.path.basename(output_path),
|
| 581 |
metadata={
|
|
@@ -585,10 +604,15 @@ def train_ensemble_models(
|
|
| 585 |
"improvement_pct": float(improvement * 100)
|
| 586 |
}
|
| 587 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 588 |
else:
|
| 589 |
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
| 590 |
joblib.dump(ensemble, output_path)
|
| 591 |
-
|
|
|
|
| 592 |
|
| 593 |
return {
|
| 594 |
'status': 'success',
|
|
|
|
| 293 |
}
|
| 294 |
|
| 295 |
# Save model if output path provided
|
| 296 |
+
actual_model_path = None
|
| 297 |
if output_path:
|
| 298 |
if ARTIFACT_STORE_AVAILABLE:
|
| 299 |
+
# Save using artifact store (returns internal storage path)
|
| 300 |
+
actual_model_path = save_model_with_store(
|
| 301 |
model_data=final_model,
|
| 302 |
filename=os.path.basename(output_path),
|
| 303 |
metadata={
|
|
|
|
| 308 |
"test_metrics": test_metrics
|
| 309 |
}
|
| 310 |
)
|
| 311 |
+
# Also save to user-requested path for LLM to find it
|
| 312 |
+
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
| 313 |
+
joblib.dump(final_model, output_path)
|
| 314 |
+
print(f"💾 Model saved to: {output_path} (artifact store: {actual_model_path})")
|
| 315 |
else:
|
| 316 |
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
| 317 |
joblib.dump(final_model, output_path)
|
| 318 |
+
actual_model_path = output_path
|
| 319 |
+
print(f"💾 Model saved to: {output_path}")
|
| 320 |
|
| 321 |
return {
|
| 322 |
'status': 'success',
|
|
|
|
| 519 |
}
|
| 520 |
|
| 521 |
# Save for blending
|
| 522 |
+
actual_model_path = None
|
| 523 |
if output_path:
|
| 524 |
if ARTIFACT_STORE_AVAILABLE:
|
| 525 |
+
# Save using artifact store (returns internal storage path)
|
| 526 |
+
actual_model_path = save_model_with_store(
|
| 527 |
model_data={
|
| 528 |
'base_models': dict(base_models),
|
| 529 |
'meta_model': meta_model,
|
|
|
|
| 537 |
"num_base_models": len(base_models)
|
| 538 |
}
|
| 539 |
)
|
| 540 |
+
# Also save to user-requested path for LLM to find it
|
| 541 |
+
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
| 542 |
+
joblib.dump({
|
| 543 |
+
'base_models': dict(base_models),
|
| 544 |
+
'meta_model': meta_model,
|
| 545 |
+
'ensemble_type': 'blending'
|
| 546 |
+
}, output_path)
|
| 547 |
else:
|
| 548 |
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
| 549 |
joblib.dump({
|
|
|
|
| 551 |
'meta_model': meta_model,
|
| 552 |
'ensemble_type': 'blending'
|
| 553 |
}, output_path)
|
| 554 |
+
actual_model_path = output_path
|
| 555 |
|
| 556 |
return {
|
| 557 |
'status': 'success',
|
|
|
|
| 590 |
improvement = ensemble_metrics['r2'] - best_individual_metric
|
| 591 |
|
| 592 |
# Save model
|
| 593 |
+
actual_model_path = None
|
| 594 |
if output_path:
|
| 595 |
if ARTIFACT_STORE_AVAILABLE:
|
| 596 |
+
# Save using artifact store (returns internal storage path)
|
| 597 |
+
actual_model_path = save_model_with_store(
|
| 598 |
model_data=ensemble,
|
| 599 |
filename=os.path.basename(output_path),
|
| 600 |
metadata={
|
|
|
|
| 604 |
"improvement_pct": float(improvement * 100)
|
| 605 |
}
|
| 606 |
)
|
| 607 |
+
# Also save to user-requested path for LLM to find it
|
| 608 |
+
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
| 609 |
+
joblib.dump(ensemble, output_path)
|
| 610 |
+
print(f"💾 Ensemble model saved to: {output_path} (artifact store: {actual_model_path})")
|
| 611 |
else:
|
| 612 |
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
| 613 |
joblib.dump(ensemble, output_path)
|
| 614 |
+
actual_model_path = output_path
|
| 615 |
+
print(f"💾 Ensemble model saved to: {output_path}")
|
| 616 |
|
| 617 |
return {
|
| 618 |
'status': 'success',
|