Spaces:
Sleeping
Sleeping
| """ | |
| LogisticsShipmentRL — Models | |
| Pydantic schemas describing the Action, Observation, and State API contracts. | |
| """ | |
| from typing import Any, Dict, List, Literal, Optional | |
| from pydantic import BaseModel, Field | |
| # --------------------------------------------------------------------------- | |
| # Core Entities (Sub-models) | |
| # --------------------------------------------------------------------------- | |
| class ShipmentStatus(BaseModel): | |
| shipment_id: str | |
| origin: str | |
| destination: str | |
| cargo_type: Literal["standard", "perishable", "hazmat", "high_value"] | |
| cargo_description: str | |
| current_location: str | |
| current_status: Literal["in_transit", "delayed", "at_hub", "customs_hold", "delivered"] | |
| assigned_carrier: str | |
| assigned_route: str | |
| estimated_arrival: str # e.g., "+6h", or ISO timestamp | |
| sla_deadline: str | |
| sla_buffer_hours: float # Negative value means SLA breached | |
| current_delay_hours: float | |
| value_usd: float | |
| is_priority: bool | |
| notes: str | |
| class DisruptionEvent(BaseModel): | |
| event_id: str | |
| event_type: Literal["breakdown", "weather", "port_congestion", "customs_hold", | |
| "strike", "accident", "road_closure", "capacity_shortage"] | |
| location: str | |
| affected_routes: List[str] | |
| affected_shipments: List[str] | |
| severity: Literal["low", "medium", "high", "critical"] | |
| estimated_duration_hours: float | |
| estimated_additional_delay_hours: float | |
| description: str | |
| can_be_bypassed: bool | |
| class RouteOption(BaseModel): | |
| route_id: str | |
| route_name: str | |
| origin: str | |
| destination: str | |
| distance_km: float | |
| estimated_hours: float | |
| cost_usd: float | |
| carrier_options: List[str] | |
| current_congestion: Literal["clear", "light", "moderate", "high"] | |
| weather_risk: Literal["none", "low", "moderate", "high"] | |
| is_available: bool | |
| # --------------------------------------------------------------------------- | |
| # API Contracts: Action | |
| # --------------------------------------------------------------------------- | |
| class ReroutingDecision(BaseModel): | |
| new_route: str = Field(description="Route ID from available_routes (e.g., 'R2')") | |
| new_carrier: Optional[str] = Field(default=None, description="Carrier name, or None to keep existing") | |
| reason: str = Field(description="One-sentence justification for this re-routing") | |
| class LogisticsAction(BaseModel): | |
| """ | |
| The full action submitted by the AI agent per step. | |
| The agent receives a heavily delayed network and must repair it. | |
| """ | |
| reasoning: str = Field( | |
| description="Chain-of-thought analysis explaining strategy and risk assessment." | |
| ) | |
| rerouting_decisions: Dict[str, ReroutingDecision] = Field( | |
| default_factory=dict, | |
| description="Shipment ID -> Re-routing decision. Only include active changes.", | |
| ) | |
| priority_shipments: List[str] = Field( | |
| default_factory=list, | |
| description="Identify up to 3 shipment IDs to expedite handling.", | |
| ) | |
| customer_communications: Dict[str, str] = Field( | |
| default_factory=dict, | |
| description="ETA messages keyed by shipment ID, sent to customers.", | |
| ) | |
| escalations: List[str] = Field( | |
| default_factory=list, | |
| description="Shipments passing human limit, requiring a real dispatcher.", | |
| ) | |
| # --------------------------------------------------------------------------- | |
| # API Contracts: Observation | |
| # --------------------------------------------------------------------------- | |
| class LogisticsObservation(BaseModel): | |
| """Full network snapshot returned by the Environment.""" | |
| scenario_id: str | |
| scenario_title: str | |
| network_snapshot: str # Natural language context summary | |
| # State tracking | |
| active_shipments: List[ShipmentStatus] | |
| total_shipments: int | |
| delayed_shipments: int | |
| sla_at_risk_count: int # Shipments within 2 hrs of breaking SLA | |
| # Dynamics | |
| disruption_events: List[DisruptionEvent] | |
| active_disruptions_count: int | |
| available_routes: List[RouteOption] | |
| weather_forecast: str | |
| carrier_availability: Dict[str, int] # Name -> trucks available | |
| field_updates: List[str] # Alerts from the field | |
| # Global metrics | |
| current_total_delay_hours: float | |
| sla_violations: List[str] | |
| on_time_shipments: int | |
| # Turn metrics | |
| step_number: int | |
| max_steps: int | |
| episode_done: bool | |
| previous_action_feedback: str | |
| previous_reward: float | |
| previous_reward_breakdown: Dict[str, float] | |
| # Cumulative stats | |
| cumulative_reward: float | |
| total_delay_saved_hours: float | |
| total_rerouting_cost_usd: float | |
| sla_compliance_rate: float | |
| action_hint: str = ( | |
| "Re-route shipments impacted by disruptions to available routes to save delay time. " | |
| "Prioritize rescuing negative sla_buffer_hours shipments and write clear customer_communications." | |
| ) | |
| # --------------------------------------------------------------------------- | |
| # End-of-Episode State | |
| # --------------------------------------------------------------------------- | |
| class LogisticsState(BaseModel): | |
| """End-of-episode comprehensive metadata.""" | |
| episode_id: str | |
| step_count: int | |
| max_steps: int | |
| done: bool | |
| scenario_id: str | |
| total_shipments: int | |
| total_delay_saved_hours: float | |
| total_rerouting_cost_usd: float | |
| sla_violations_count: int | |
| sla_compliance_rate: float | |
| cumulative_reward: float | |
| reward_breakdown: Dict[str, float] | |
| class LogisticsStepResult(BaseModel): | |
| observation: LogisticsObservation | |
| reward: float | |
| done: bool | |
| info: Dict[str, Any] = Field(default_factory=dict) | |