Fix issues

This commit is contained in:
Urtzi Alfaro
2025-08-17 10:28:58 +02:00
parent 8914786973
commit 109961ef6e
10 changed files with 450 additions and 176 deletions

View File

@@ -137,42 +137,7 @@ class EnhancedTrainingService:
await self._init_repositories(session)
try:
# Pre-flight check: Verify sales data exists before starting training
from app.services.data_client import DataClient
data_client = DataClient()
sales_data = await data_client.fetch_sales_data(tenant_id, fetch_all=True)
if not sales_data or len(sales_data) == 0:
error_msg = f"No sales data available for tenant {tenant_id}. Please import sales data before starting training."
logger.error("Training aborted - no sales data", tenant_id=tenant_id, job_id=job_id)
raise ValueError(error_msg)
# Debug: Analyze the sales data structure to understand product distribution
sales_df_debug = pd.DataFrame(sales_data)
if 'inventory_product_id' in sales_df_debug.columns:
unique_products_found = sales_df_debug['inventory_product_id'].unique()
product_counts = sales_df_debug['inventory_product_id'].value_counts().to_dict()
logger.info("Pre-flight sales data analysis",
tenant_id=tenant_id,
job_id=job_id,
total_sales_records=len(sales_data),
unique_products_count=len(unique_products_found),
unique_products=unique_products_found.tolist(),
records_per_product=product_counts)
if len(unique_products_found) == 1:
logger.warning("POTENTIAL ISSUE: Only ONE unique product found in all sales data",
tenant_id=tenant_id,
single_product=unique_products_found[0],
record_count=len(sales_data))
else:
logger.warning("No 'inventory_product_id' column found in sales data",
tenant_id=tenant_id,
columns=list(sales_df_debug.columns))
logger.info(f"Pre-flight check passed: {len(sales_data)} sales records found",
tenant_id=tenant_id, job_id=job_id)
# Pre-flight check moved to orchestrator to eliminate duplicate sales data fetching
# Check if training log already exists, create if not
existing_log = await self.training_log_repo.get_log_by_job_id(job_id)
@@ -202,12 +167,13 @@ class EnhancedTrainingService:
step_details="Data"
)
# Step 1: Prepare training dataset
logger.info("Step 1: Preparing and aligning training data")
# Step 1: Prepare training dataset (includes sales data validation)
logger.info("Step 1: Preparing and aligning training data (with validation)")
await self.training_log_repo.update_log_progress(
job_id, 10, "data_validation", "running"
)
# Orchestrator now handles sales data validation to eliminate duplicate fetching
training_dataset = await self.orchestrator.prepare_training_data(
tenant_id=tenant_id,
bakery_location=bakery_location,
@@ -216,6 +182,10 @@ class EnhancedTrainingService:
job_id=job_id
)
# Log the results from orchestrator's unified sales data fetch
logger.info(f"Sales data validation completed: {len(training_dataset.sales_data)} records",
tenant_id=tenant_id, job_id=job_id)
await self.training_log_repo.update_log_progress(
job_id, 30, "data_preparation_complete", "running"
)
@@ -285,6 +255,27 @@ class EnhancedTrainingService:
# Make sure all data is JSON-serializable before saving to database
json_safe_result = make_json_serializable(final_result)
# Ensure results is a proper dict for database storage
if not isinstance(json_safe_result, dict):
logger.warning("JSON safe result is not a dict, wrapping it", result_type=type(json_safe_result))
json_safe_result = {"training_data": json_safe_result}
# Double-check JSON serialization by attempting to serialize
import json
try:
json.dumps(json_safe_result)
logger.debug("Results successfully JSON-serializable", job_id=job_id)
except (TypeError, ValueError) as e:
logger.error("Results still not JSON-serializable after cleaning",
job_id=job_id, error=str(e))
# Create a minimal safe result
json_safe_result = {
"status": "completed",
"job_id": job_id,
"models_created": final_result.get("products_trained", 0),
"error": "Result serialization failed"
}
await self.training_log_repo.complete_training_log(
job_id, results=json_safe_result
)
@@ -313,6 +304,9 @@ class EnhancedTrainingService:
"completed_at": datetime.now().isoformat()
}
# Ensure error result is JSON serializable
error_result = make_json_serializable(error_result)
return self._create_detailed_training_response(error_result)
async def _store_trained_models(