demo seed change
This commit is contained in:
416
shared/schemas/reasoning_types.py
Normal file → Executable file
416
shared/schemas/reasoning_types.py
Normal file → Executable file
@@ -9,7 +9,7 @@ Backend only stores type codes and parameters.
|
||||
"""
|
||||
|
||||
from enum import Enum
|
||||
from typing import Dict, Any, Optional
|
||||
from typing import Dict, Any, Optional, List
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
@@ -47,6 +47,34 @@ class ConsequenceSeverity(str, Enum):
|
||||
LOW = "low" # Minor impact
|
||||
|
||||
|
||||
class PredictionFactorType(str, Enum):
|
||||
"""Types of factors that contribute to demand prediction"""
|
||||
HISTORICAL_PATTERN = "historical_pattern" # Historical sales/demand patterns
|
||||
WEATHER_SUNNY = "weather_sunny" # Sunny weather impact
|
||||
WEATHER_RAINY = "weather_rainy" # Rainy weather impact
|
||||
WEATHER_COLD = "weather_cold" # Cold weather impact
|
||||
WEATHER_HOT = "weather_hot" # Hot weather impact
|
||||
WEEKEND_BOOST = "weekend_boost" # Weekend demand increase
|
||||
WEEKDAY_PATTERN = "weekday_pattern" # Day-of-week pattern
|
||||
LOCAL_EVENT = "local_event" # Local event impact
|
||||
HOLIDAY = "holiday" # Holiday impact
|
||||
INVENTORY_LEVEL = "inventory_level" # Current inventory consideration
|
||||
TREND_SEASONAL = "trend_seasonal" # Seasonal trend
|
||||
PROMOTION_ACTIVE = "promotion_active" # Active promotion
|
||||
|
||||
class PredictionFactor(BaseModel):
|
||||
"""Individual factor contributing to demand prediction"""
|
||||
factor: PredictionFactorType = Field(..., description="Type of prediction factor")
|
||||
weight: float = Field(..., description="Weight of this factor (0-1)", ge=0, le=1)
|
||||
contribution: float = Field(..., description="Absolute contribution to demand")
|
||||
description: Optional[str] = Field(None, description="Human-readable description")
|
||||
weather_data: Optional[Dict[str, Any]] = Field(None, description="Weather-specific data")
|
||||
inventory_data: Optional[Dict[str, Any]] = Field(None, description="Inventory-specific data")
|
||||
historical_data: Optional[Dict[str, Any]] = Field(None, description="Historical pattern data")
|
||||
event_data: Optional[Dict[str, Any]] = Field(None, description="Event-specific data")
|
||||
confidence: Optional[float] = Field(None, description="Confidence score for this factor", ge=0, le=1)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# Reasoning Data Models
|
||||
# ============================================================
|
||||
@@ -440,31 +468,113 @@ def create_po_reasoning_manual_request(
|
||||
def create_batch_reasoning_forecast_demand(
|
||||
product_name: str,
|
||||
predicted_demand: float,
|
||||
current_stock: float,
|
||||
production_needed: float,
|
||||
target_date: str,
|
||||
confidence_score: float = 0.85
|
||||
current_stock: float = None,
|
||||
production_needed: float = None,
|
||||
target_date: str = None,
|
||||
historical_average: float = None,
|
||||
variance_percent: float = None,
|
||||
variance_reason: str = None,
|
||||
confidence_score: float = 0.85,
|
||||
factors: Optional[List[Dict[str, Any]]] = None,
|
||||
urgency_level: str = "normal",
|
||||
ready_by_time: str = "08:00",
|
||||
forecast_id: Optional[str] = None,
|
||||
target_sales: float = None,
|
||||
weather_impact: Dict[str, Any] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Create reasoning data for forecast-based production"""
|
||||
"""
|
||||
Create unified reasoning data for forecast-based production with optional enhanced factors
|
||||
|
||||
This function consolidates both basic and enhanced forecast demand reasoning.
|
||||
|
||||
Args:
|
||||
product_name: Name of the product
|
||||
predicted_demand: Predicted demand quantity
|
||||
current_stock: Current stock level (optional for basic reasoning)
|
||||
production_needed: Needed production quantity (optional for basic reasoning)
|
||||
target_date: Target date for production (optional for basic reasoning)
|
||||
historical_average: Historical average demand (for enhanced reasoning)
|
||||
variance_percent: Percentage variance from historical average (for enhanced reasoning)
|
||||
variance_reason: Reason for variance (for enhanced reasoning)
|
||||
confidence_score: Confidence score (0-1)
|
||||
factors: List of factors contributing to the prediction (for enhanced reasoning)
|
||||
urgency_level: Urgency level ("normal", "medium", "high", "urgent")
|
||||
ready_by_time: Time when batch should be ready
|
||||
forecast_id: UUID of the forecast for traceability
|
||||
target_sales: Target sales figures
|
||||
weather_impact: Detailed weather impact data
|
||||
|
||||
Returns:
|
||||
Reasoning data with appropriate level of detail based on provided parameters
|
||||
"""
|
||||
# Build parameters dict
|
||||
params = {
|
||||
"product_name": product_name,
|
||||
"predicted_demand": round(predicted_demand, 1),
|
||||
}
|
||||
|
||||
# Add basic reasoning parameters if provided
|
||||
if current_stock is not None:
|
||||
params["current_stock"] = round(current_stock, 1)
|
||||
if production_needed is not None:
|
||||
params["production_needed"] = round(production_needed, 1)
|
||||
if target_date is not None:
|
||||
params["target_date"] = target_date
|
||||
if target_sales is not None:
|
||||
params["target_sales"] = round(target_sales, 1)
|
||||
if weather_impact is not None:
|
||||
params["weather_impact"] = weather_impact
|
||||
|
||||
# Add enhanced reasoning parameters if provided
|
||||
if historical_average is not None:
|
||||
params["historical_average"] = round(historical_average, 1)
|
||||
if variance_percent is not None:
|
||||
params["variance_percent"] = round(variance_percent, 1)
|
||||
if variance_reason is not None:
|
||||
params["variance_reason"] = variance_reason
|
||||
if factors:
|
||||
# Ensure factors is a list
|
||||
factors_list = factors or []
|
||||
# Convert factors to proper format if they're not already PredictionFactor objects
|
||||
formatted_factors = []
|
||||
for factor in factors_list:
|
||||
if isinstance(factor, dict):
|
||||
# Already in dict format
|
||||
formatted_factors.append(factor)
|
||||
else:
|
||||
# Convert PredictionFactor to dict
|
||||
formatted_factors.append({
|
||||
"factor": factor.factor.value if hasattr(factor, 'factor') else str(factor.factor),
|
||||
"weight": factor.weight,
|
||||
"contribution": factor.contribution,
|
||||
"description": factor.description,
|
||||
"weather_data": factor.weather_data,
|
||||
"inventory_data": factor.inventory_data,
|
||||
"historical_data": factor.historical_data,
|
||||
"event_data": factor.event_data,
|
||||
"confidence": factor.confidence
|
||||
})
|
||||
params["factors"] = formatted_factors
|
||||
|
||||
return {
|
||||
"type": ProductionBatchReasoningType.FORECAST_DEMAND.value,
|
||||
"parameters": {
|
||||
"product_name": product_name,
|
||||
"predicted_demand": round(predicted_demand, 1),
|
||||
"current_stock": round(current_stock, 1),
|
||||
"production_needed": round(production_needed, 1),
|
||||
"target_date": target_date,
|
||||
"confidence_score": round(confidence_score * 100, 1)
|
||||
},
|
||||
"parameters": params,
|
||||
"urgency": {
|
||||
"level": "normal",
|
||||
"ready_by_time": "08:00",
|
||||
"level": urgency_level,
|
||||
"ready_by_time": ready_by_time,
|
||||
"customer_commitment": False
|
||||
},
|
||||
"metadata": {
|
||||
"trigger_source": "orchestrator_auto",
|
||||
"confidence_score": confidence_score,
|
||||
"ai_assisted": True
|
||||
"ai_assisted": True,
|
||||
"enhanced_reasoning": any([
|
||||
historical_average is not None,
|
||||
variance_percent is not None,
|
||||
variance_reason is not None,
|
||||
factors is not None and len(factors) > 0,
|
||||
weather_impact is not None
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -632,3 +742,275 @@ def create_batch_reasoning_urgent_order(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def create_production_batch_reasoning(
|
||||
product_name: str,
|
||||
predicted_demand: float,
|
||||
current_stock: float = None,
|
||||
production_needed: float = None,
|
||||
target_date: str = None,
|
||||
historical_average: float = None,
|
||||
variance_percent: float = None,
|
||||
variance_reason: str = None,
|
||||
confidence_score: float = 0.85,
|
||||
factors: Optional[List[Dict[str, Any]]] = None,
|
||||
urgency_level: str = "normal",
|
||||
ready_by_time: str = "08:00",
|
||||
forecast_id: Optional[str] = None,
|
||||
target_sales: float = None,
|
||||
weather_impact: Dict[str, Any] = None,
|
||||
base_demand: float = None,
|
||||
weather_data: Dict[str, Any] = None,
|
||||
weather_adjustment_factor: float = None,
|
||||
production_type: str = "forecast_demand" # Add this to allow different production reasoning types
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Create unified reasoning data for production batches that combines both forecast demand and weather influence
|
||||
|
||||
This function consolidates both basic and enhanced forecast demand reasoning as well as weather-influenced production reasoning.
|
||||
|
||||
Args:
|
||||
product_name: Name of the product
|
||||
predicted_demand: Predicted demand quantity
|
||||
current_stock: Current stock level (optional for basic reasoning)
|
||||
production_needed: Needed production quantity (optional for basic reasoning)
|
||||
target_date: Target date for production (optional for basic reasoning)
|
||||
historical_average: Historical average demand (for enhanced reasoning)
|
||||
variance_percent: Percentage variance from historical average (for enhanced reasoning)
|
||||
variance_reason: Reason for variance (for enhanced reasoning)
|
||||
confidence_score: Confidence score (0-1)
|
||||
factors: List of factors contributing to the prediction (for enhanced reasoning)
|
||||
urgency_level: Urgency level ("normal", "medium", "high", "urgent")
|
||||
ready_by_time: Time when batch should be ready
|
||||
forecast_id: UUID of the forecast for traceability
|
||||
target_sales: Target sales figures
|
||||
weather_impact: Detailed weather impact data
|
||||
base_demand: Base demand without weather influence (for weather-influenced reasoning)
|
||||
weather_data: Weather information affecting production, with keys:
|
||||
- temperature: Current/future temperature
|
||||
- condition: Weather condition (sunny, rainy, snowy, etc.)
|
||||
- humidity: Humidity level
|
||||
- impact_factor: Multiplier for weather impact on demand
|
||||
weather_adjustment_factor: Factor by which weather adjusted the demand
|
||||
production_type: Type of production reasoning ("forecast_demand", "weather_influenced", "forecast_and_weather", etc.)
|
||||
|
||||
Returns:
|
||||
Reasoning data with appropriate level of detail based on provided parameters
|
||||
"""
|
||||
# Build parameters dict
|
||||
params = {
|
||||
"product_name": product_name,
|
||||
"predicted_demand": round(predicted_demand, 1),
|
||||
}
|
||||
|
||||
# Add basic reasoning parameters if provided
|
||||
if current_stock is not None:
|
||||
params["current_stock"] = round(current_stock, 1)
|
||||
if production_needed is not None:
|
||||
params["production_needed"] = round(production_needed, 1)
|
||||
if target_date is not None:
|
||||
params["target_date"] = target_date
|
||||
if target_sales is not None:
|
||||
params["target_sales"] = round(target_sales, 1)
|
||||
|
||||
# Add weather-related data if provided
|
||||
if weather_data is not None:
|
||||
# Calculate weather impact details
|
||||
weather_impact_factor = weather_adjustment_factor or weather_data.get('impact_factor', 1.0)
|
||||
temperature = weather_data.get('temperature', 'N/A')
|
||||
condition = weather_data.get('condition', 'unknown')
|
||||
humidity = weather_data.get('humidity', 'N/A')
|
||||
|
||||
# Calculate weather-adjusted base demand if not provided
|
||||
if base_demand is None:
|
||||
base_demand = predicted_demand / weather_impact_factor if weather_impact_factor != 0 else predicted_demand
|
||||
|
||||
params["base_demand"] = round(base_demand, 1)
|
||||
params["weather_adjustment_factor"] = round(weather_impact_factor, 2)
|
||||
params["weather_data"] = weather_data
|
||||
params["weather_condition"] = condition
|
||||
params["temperature"] = temperature
|
||||
params["humidity"] = humidity
|
||||
|
||||
elif weather_impact is not None:
|
||||
# Handle legacy weather_impact parameter
|
||||
params["weather_impact"] = weather_impact
|
||||
|
||||
# Add enhanced reasoning parameters if provided
|
||||
if historical_average is not None:
|
||||
params["historical_average"] = round(historical_average, 1)
|
||||
if variance_percent is not None:
|
||||
params["variance_percent"] = round(variance_percent, 1)
|
||||
if variance_reason is not None:
|
||||
params["variance_reason"] = variance_reason
|
||||
if factors:
|
||||
# Ensure factors is a list
|
||||
factors_list = factors or []
|
||||
# Convert factors to proper format if they're not already PredictionFactor objects
|
||||
formatted_factors = []
|
||||
for factor in factors_list:
|
||||
if isinstance(factor, dict):
|
||||
# Already in dict format
|
||||
formatted_factors.append(factor)
|
||||
else:
|
||||
# Convert PredictionFactor to dict
|
||||
formatted_factors.append({
|
||||
"factor": factor.factor.value if hasattr(factor, 'factor') else str(factor.factor),
|
||||
"weight": factor.weight,
|
||||
"contribution": factor.contribution,
|
||||
"description": factor.description,
|
||||
"weather_data": factor.weather_data,
|
||||
"inventory_data": factor.inventory_data,
|
||||
"historical_data": factor.historical_data,
|
||||
"event_data": factor.event_data,
|
||||
"confidence": factor.confidence
|
||||
})
|
||||
params["factors"] = formatted_factors
|
||||
|
||||
# Determine the production type and set accordingly
|
||||
actual_type = ProductionBatchReasoningType.FORECAST_DEMAND.value
|
||||
|
||||
# Create metadata
|
||||
metadata = {
|
||||
"trigger_source": "orchestrator_auto",
|
||||
"confidence_score": confidence_score,
|
||||
"ai_assisted": True,
|
||||
"enhanced_reasoning": any([
|
||||
historical_average is not None,
|
||||
variance_percent is not None,
|
||||
variance_reason is not None,
|
||||
factors is not None and len(factors) > 0,
|
||||
weather_impact is not None,
|
||||
weather_data is not None
|
||||
])
|
||||
}
|
||||
|
||||
# Add weather-specific metadata if applicable
|
||||
if weather_data is not None or weather_impact is not None:
|
||||
metadata["weather_influenced"] = True
|
||||
|
||||
return {
|
||||
"type": actual_type,
|
||||
"parameters": params,
|
||||
"urgency": {
|
||||
"level": urgency_level,
|
||||
"ready_by_time": ready_by_time,
|
||||
"customer_commitment": False
|
||||
},
|
||||
"metadata": metadata
|
||||
}
|
||||
|
||||
|
||||
def create_batch_reasoning_weather_influenced(
|
||||
product_name: str,
|
||||
predicted_demand: float,
|
||||
weather_data: Dict[str, Any],
|
||||
base_demand: float = None,
|
||||
current_stock: float = None,
|
||||
production_needed: float = None,
|
||||
target_date: str = None,
|
||||
confidence_score: float = 0.85,
|
||||
factors: Optional[List[Dict[str, Any]]] = None,
|
||||
urgency_level: str = "normal",
|
||||
ready_by_time: str = "08:00",
|
||||
forecast_id: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Create reasoning data for production batches influenced by weather factors
|
||||
|
||||
This function specifically handles weather-influenced production reasoning,
|
||||
which is important for bakery operations where weather significantly impacts demand.
|
||||
|
||||
Args:
|
||||
product_name: Name of the product
|
||||
predicted_demand: Predicted demand quantity considering weather impact
|
||||
weather_data: Weather information affecting production, with keys:
|
||||
- temperature: Current/future temperature
|
||||
- condition: Weather condition (sunny, rainy, snowy, etc.)
|
||||
- humidity: Humidity level
|
||||
- impact_factor: Multiplier for weather impact on demand
|
||||
base_demand: Base demand without weather influence (optional)
|
||||
current_stock: Current stock level
|
||||
production_needed: Needed production quantity
|
||||
target_date: Target date for production
|
||||
confidence_score: Confidence score (0-1)
|
||||
factors: Additional prediction factors
|
||||
urgency_level: Urgency level ("normal", "medium", "high", "urgent")
|
||||
ready_by_time: Time when batch should be ready
|
||||
forecast_id: UUID of the forecast for traceability
|
||||
|
||||
Returns:
|
||||
Reasoning data with detailed weather influence information
|
||||
"""
|
||||
# Calculate weather impact details
|
||||
weather_impact_factor = weather_data.get('impact_factor', 1.0)
|
||||
temperature = weather_data.get('temperature', 'N/A')
|
||||
condition = weather_data.get('condition', 'unknown')
|
||||
humidity = weather_data.get('humidity', 'N/A')
|
||||
|
||||
# Calculate weather-adjusted base demand
|
||||
if base_demand is None:
|
||||
base_demand = predicted_demand / weather_impact_factor
|
||||
|
||||
# Build parameters
|
||||
params = {
|
||||
"product_name": product_name,
|
||||
"predicted_demand": round(predicted_demand, 1),
|
||||
"base_demand": round(base_demand, 1),
|
||||
"weather_adjustment_factor": round(weather_impact_factor, 2),
|
||||
"weather_data": weather_data,
|
||||
"weather_condition": condition,
|
||||
"temperature": temperature,
|
||||
"humidity": humidity
|
||||
}
|
||||
|
||||
# Add optional basic reasoning parameters
|
||||
if current_stock is not None:
|
||||
params["current_stock"] = round(current_stock, 1)
|
||||
if production_needed is not None:
|
||||
params["production_needed"] = round(production_needed, 1)
|
||||
if target_date is not None:
|
||||
params["target_date"] = target_date
|
||||
|
||||
# Add enhanced reasoning parameters if provided
|
||||
if factors:
|
||||
# Ensure factors is a list
|
||||
factors_list = factors or []
|
||||
# Convert factors to proper format if they're not already PredictionFactor objects
|
||||
formatted_factors = []
|
||||
for factor in factors_list:
|
||||
if isinstance(factor, dict):
|
||||
# Already in dict format
|
||||
formatted_factors.append(factor)
|
||||
else:
|
||||
# Convert PredictionFactor to dict
|
||||
formatted_factors.append({
|
||||
"factor": factor.factor.value if hasattr(factor, 'factor') else str(factor.factor),
|
||||
"weight": factor.weight,
|
||||
"contribution": factor.contribution,
|
||||
"description": factor.description,
|
||||
"weather_data": factor.weather_data,
|
||||
"inventory_data": factor.inventory_data,
|
||||
"historical_data": factor.historical_data,
|
||||
"event_data": factor.event_data,
|
||||
"confidence": factor.confidence
|
||||
})
|
||||
params["factors"] = formatted_factors
|
||||
|
||||
return {
|
||||
"type": ProductionBatchReasoningType.FORECAST_DEMAND.value,
|
||||
"parameters": params,
|
||||
"urgency": {
|
||||
"level": urgency_level,
|
||||
"ready_by_time": ready_by_time,
|
||||
"customer_commitment": False
|
||||
},
|
||||
"metadata": {
|
||||
"trigger_source": "orchestrator_auto",
|
||||
"confidence_score": confidence_score,
|
||||
"ai_assisted": True,
|
||||
"enhanced_reasoning": True,
|
||||
"weather_influenced": True
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user