Spaces:
Sleeping
Sleeping
| """ | |
| π Policy Agent β Main decision maker. | |
| Proposes tax rates, budget allocations, and subsidies | |
| based on current state and memory of past decisions. | |
| """ | |
| from __future__ import annotations | |
| from civicai.models import Action, Observation, AgentMessage, Vote, SubsidyPolicy | |
| class PolicyAgent: | |
| """Rule-based policy agent with heuristic decision-making.""" | |
| name = "PolicyAgent" | |
| role = "π Policy Agent" | |
| def __init__(self) -> None: | |
| self.memory: list[dict] = [] | |
| def analyze(self, obs: Observation) -> AgentMessage: | |
| proposal = self._generate_proposal(obs) | |
| reasoning = self._build_reasoning(obs) | |
| return AgentMessage( | |
| agent_name=self.name, | |
| agent_role=self.role, | |
| proposal=proposal, | |
| reasoning=reasoning, | |
| vote=Vote.APPROVE, | |
| ) | |
| def propose_action(self, obs: Observation) -> Action: | |
| """Generate a policy action based on current observation.""" | |
| tax = self._compute_tax(obs) | |
| hc = self._compute_healthcare(obs) | |
| edu = self._compute_education(obs) | |
| police = self._compute_police(obs) | |
| subsidy = self._compute_subsidy(obs) | |
| emergency = self._compute_emergency(obs) | |
| action = Action( | |
| tax_rate=tax, healthcare_budget=hc, education_budget=edu, | |
| police_budget=police, subsidy_policy=subsidy, emergency_response=emergency, | |
| ) | |
| self.memory.append({"turn": obs.turn, "action": action.model_dump()}) | |
| return action | |
| def _compute_tax(self, obs: Observation) -> float: | |
| if obs.inflation > 0.08: | |
| return min(0.35, 0.25 + (obs.inflation - 0.06) * 2) | |
| if obs.budget_balance < -0.1: | |
| return 0.30 | |
| if obs.employment_rate > 0.90 and obs.inflation < 0.04: | |
| return 0.20 | |
| return 0.25 | |
| def _compute_healthcare(self, obs: Observation) -> float: | |
| base = 0.20 | |
| if obs.health_index < 0.50: | |
| base = 0.35 | |
| elif obs.health_index < 0.65: | |
| base = 0.28 | |
| if "pandemic_wave" in obs.active_events: | |
| base = min(0.40, base + 0.10) | |
| return base | |
| def _compute_education(self, obs: Observation) -> float: | |
| if obs.employment_rate < 0.75: | |
| return 0.20 | |
| return 0.15 | |
| def _compute_police(self, obs: Observation) -> float: | |
| if obs.crime_rate > 0.20: | |
| return 0.18 | |
| if obs.crime_rate > 0.12: | |
| return 0.12 | |
| return 0.08 | |
| def _compute_subsidy(self, obs: Observation) -> SubsidyPolicy: | |
| if obs.resources.get("food", 1) < 0.4: | |
| return SubsidyPolicy.AGRICULTURE | |
| if obs.employment_rate < 0.80: | |
| return SubsidyPolicy.INDUSTRY | |
| return SubsidyPolicy.TECHNOLOGY | |
| def _compute_emergency(self, obs: Observation) -> str | None: | |
| if "pandemic_wave" in obs.active_events and obs.health_index < 0.40: | |
| return "lockdown" | |
| if obs.employment_rate < 0.60: | |
| return "stimulus" | |
| return None | |
| def _generate_proposal(self, obs: Observation) -> str: | |
| action = self.propose_action(obs) | |
| parts = [f"Tax: {action.tax_rate:.0%}", f"Healthcare: {action.healthcare_budget:.0%}", | |
| f"Education: {action.education_budget:.0%}", f"Police: {action.police_budget:.0%}", | |
| f"Subsidy: {action.subsidy_policy.value}"] | |
| if action.emergency_response: | |
| parts.append(f"Emergency: {action.emergency_response}") | |
| return " | ".join(parts) | |
| def _build_reasoning(self, obs: Observation) -> str: | |
| reasons = [] | |
| if obs.inflation > 0.06: | |
| reasons.append(f"Inflation at {obs.inflation:.1%} requires fiscal tightening") | |
| if obs.employment_rate < 0.80: | |
| reasons.append(f"Employment at {obs.employment_rate:.1%} needs stimulus") | |
| if obs.health_index < 0.60: | |
| reasons.append("Health crisis requires increased healthcare spending") | |
| if obs.crime_rate > 0.15: | |
| reasons.append(f"Crime at {obs.crime_rate:.1%} demands police funding") | |
| return ". ".join(reasons) if reasons else "Maintaining balanced policy approach" | |