Jerry
Upgrade: Premium Dashboard, Multi-Agent capacity logic, and GRPO training updates
c276e2c
Raw
History Blame Contribute Delete
3.33 kB
"""
LogisticsShipmentRL — Grader Module
"""
import sys, os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from typing import Any, Dict
from models import LogisticsAction
def calculate_delay_score(baseline_delay: float, new_delay: float) -> float:
"""40% Weight: Returns 0.0 to 1.0 based on hours of delay saved relative to do-nothing baseline."""
hours_saved = max(0.0, baseline_delay - new_delay)
# Assume 10 hours saved is a "perfect" score for normalization
return min(1.0, hours_saved / 10.0)
def calculate_cost_efficiency(base_cost: float, new_cost: float, penalties_avoided: float) -> float:
"""30% Weight: Re-routing cost relative to SLA breach penalty avoided."""
additional_cost = max(0.0, new_cost - base_cost)
if penalties_avoided == 0.0:
return 1.0 if additional_cost == 0.0 else 0.0
efficiency = max(0.0, 1.0 - (additional_cost / penalties_avoided))
return efficiency
def calculate_sla_compliance(shipments: list) -> float:
"""20% Weight: % of shipments mathematically still within SLA window."""
if not shipments:
return 1.0
on_time = sum(1 for s in shipments if s.sla_buffer_hours >= 0)
return on_time / len(shipments)
def grade_communication_quality(action: LogisticsAction) -> float:
"""10% Weight: Grades the LLM's text output via heuristics for clarity."""
score = 0.0
# Needs to actually send something if shipments are delayed
comms = action.customer_communications
if not comms:
return 0.5
avg_score = 0.0
for sms in comms.values():
txt = sms.lower()
sub = 0.0
# Check professional tone/clear ETA
if "sorry" in txt or "apolog" in txt:
sub += 0.3
if "eta" in txt or "arrive" in txt or "reschedule" in txt:
sub += 0.4
if "reason" in txt or "due to" in txt or "weather" in txt or "port" in txt:
sub += 0.3
avg_score += min(1.0, sub)
score = avg_score / len(comms)
return score
def compute_reward(action_dict: Dict[str, Any], state_info: Dict[str, Any]) -> tuple[float, Dict[str, float]]:
"""Root scorer aggregating the 4 values."""
action = LogisticsAction(**action_dict)
# Destructure metrics provided by environment's internal update simulation
baseline = state_info.get("baseline_delay", 10.0)
actual = state_info.get("new_delay", 10.0)
base_c = state_info.get("base_cost", 1000.0)
new_c = state_info.get("new_cost", 1000.0)
penalties = state_info.get("penalties_avoided", 5000.0)
shipments = state_info.get("agent_shipments", [])
d_score = calculate_delay_score(baseline, actual)
c_score = calculate_cost_efficiency(base_c, new_c, penalties)
s_score = calculate_sla_compliance(shipments)
m_score = grade_communication_quality(action)
weighted_sum = (
0.40 * d_score +
0.30 * c_score +
0.20 * s_score +
0.10 * m_score
)
# Meta Hackathon Phase 2 strict bounds requirement
weighted_sum = min(max(weighted_sum, 0.001), 0.999)
breakdown = {
"delay_score": d_score,
"cost_efficiency": c_score,
"sla_compliance": s_score,
"comm_quality": m_score
}
return weighted_sum, breakdown