Spaces:
Sleeping
Sleeping
| """Brain class - composes Perception + Lens + 3 Subagents + Brain Executive. | |
| Per cortex/CLAUDE.md: each brain has a deterministic Python Perception | |
| + Lens, three LLM subagents (router-callable), and a deterministic | |
| Python Brain Executive. The Brain class wires these together. | |
| Multi-model deployment: each Brain holds a SINGLE LLMClient instance | |
| passed at construction. Different brains can use different models by | |
| constructing each Brain with a different LLMClient (e.g., Qwen for epi, | |
| Llama for logistics). NO module-level state, NO shared singletons. | |
| """ | |
| from __future__ import annotations | |
| from typing import List, Literal | |
| from cortex.lenses import lens_for | |
| from cortex.schemas import ( | |
| BeliefState, | |
| BrainLensedObservation, | |
| BrainRecommendation, | |
| CandidatePlan, | |
| CriticReport, | |
| PerceptionReport, | |
| SubagentInput, | |
| ) | |
| from cortex.subagents import ( | |
| CriticSubagent, | |
| PlannerSubagent, | |
| WorldModelerSubagent, | |
| perception_for, | |
| ) | |
| from cortex.subagents._base import _LLMClientLike | |
| from CrisisWorldCortex.models import CrisisworldcortexObservation | |
| from ._executive import aggregate_brain_outputs | |
| _BrainId = Literal["epidemiology", "logistics", "governance"] | |
| class Brain: | |
| """Per-brain pipeline holder. | |
| Each Brain instance owns its own LLMClient. The orchestration layer | |
| (Session 12 Council, Workstream B trainers) instantiates one Brain | |
| per brain id, optionally with different LLMClients pointing to | |
| different models. The Brain class itself has NO module-level state | |
| and NO forced singleton. | |
| Args: | |
| brain_id: One of "epidemiology", "logistics", "governance". | |
| llm_client: This brain's LLM client. Subagents are constructed | |
| with the SAME client so token billing aggregates correctly. | |
| wm: WorldModeler subagent. | |
| planner: Planner subagent. | |
| critic: Critic subagent. | |
| """ | |
| def __init__( | |
| self, | |
| brain_id: _BrainId, | |
| llm_client: _LLMClientLike, | |
| wm: WorldModelerSubagent, | |
| planner: PlannerSubagent, | |
| critic: CriticSubagent, | |
| ) -> None: | |
| self.brain_id = brain_id | |
| self.llm_client = llm_client | |
| self.wm = wm | |
| self.planner = planner | |
| self.critic = critic | |
| # ------------------------------------------------------------------ | |
| # Deterministic Python pieces (no LLM) | |
| # ------------------------------------------------------------------ | |
| def compute_perception(self, obs: CrisisworldcortexObservation) -> PerceptionReport: | |
| """Run this brain's Perception. Pure Python; no LLM.""" | |
| return perception_for(self.brain_id, obs) | |
| def compute_lens( | |
| self, obs: CrisisworldcortexObservation, last_reward: float | |
| ) -> BrainLensedObservation: | |
| """Run this brain's Lens. Pure Python; no LLM.""" | |
| return lens_for(self.brain_id, obs, last_reward) | |
| def aggregate( | |
| self, | |
| perception: PerceptionReport, | |
| beliefs: List[BeliefState], | |
| plans: List[CandidatePlan], | |
| critics: List[CriticReport], | |
| tokens_used: int = 0, | |
| ) -> BrainRecommendation: | |
| """Run this brain's Brain Executive. Pure Python; no LLM.""" | |
| return aggregate_brain_outputs( | |
| brain_id=self.brain_id, | |
| perception=perception, | |
| beliefs=beliefs, | |
| plans=plans, | |
| critics=critics, | |
| tokens_used=tokens_used, | |
| ) | |
| # ------------------------------------------------------------------ | |
| # High-level convenience: round-1 single tick | |
| # ------------------------------------------------------------------ | |
| def run_tick( | |
| self, | |
| obs: CrisisworldcortexObservation, | |
| last_reward: float, | |
| tick: int, | |
| round_: int = 1, | |
| ) -> BrainRecommendation: | |
| """Round-1 single-tick pipeline (Session 11 smoke). | |
| Round 2 is orchestrated by the Council Executive (Session 12) | |
| via the fine-grained methods (compute_perception, compute_lens, | |
| wm.run / planner.run / critic.run, aggregate). Calling this | |
| convenience method with ``round_!=1`` raises NotImplementedError | |
| to prevent accidental misuse before the Council exists. | |
| """ | |
| if round_ != 1: | |
| raise NotImplementedError( | |
| f"Round {round_} orchestration is the Council Executive's " | |
| f"responsibility (Session 12). Use Brain.compute_perception/" | |
| f"compute_lens + WorldModelerSubagent.run/PlannerSubagent.run/" | |
| f"CriticSubagent.run + Brain.aggregate directly." | |
| ) | |
| perception = self.compute_perception(obs) | |
| # Lens is computed for completeness; Session 11 doesn't yet plumb | |
| # it into SubagentInput (M-FR-4 step indices fixed). Session 12 | |
| # Council will extend the SubagentInput contract to carry lens | |
| # output if subagents need it. | |
| _ = self.compute_lens(obs, last_reward) | |
| # WorldModeler (step_idx=0) | |
| wm_input = SubagentInput( | |
| brain=self.brain_id, | |
| role="world_modeler", | |
| tick=tick, | |
| round=round_, | |
| perception=perception, | |
| prior_belief=None, | |
| prior_plans=[], | |
| target_plan_id=None, | |
| last_reward=last_reward, | |
| recent_action_log_excerpt=list(obs.recent_action_log), | |
| ) | |
| belief = self.wm.run(wm_input, step_idx=0) | |
| # Planner (step_idx=1) | |
| planner_input = SubagentInput( | |
| brain=self.brain_id, | |
| role="planner", | |
| tick=tick, | |
| round=round_, | |
| perception=perception, | |
| prior_belief=belief, | |
| prior_plans=[], | |
| target_plan_id=None, | |
| last_reward=last_reward, | |
| recent_action_log_excerpt=list(obs.recent_action_log), | |
| ) | |
| plan = self.planner.run(planner_input, step_idx=1) | |
| # Critic (step_idx=2) | |
| critic_input = SubagentInput( | |
| brain=self.brain_id, | |
| role="critic", | |
| tick=tick, | |
| round=round_, | |
| perception=perception, | |
| prior_belief=belief, | |
| prior_plans=[plan], | |
| target_plan_id="plan-0", | |
| last_reward=last_reward, | |
| recent_action_log_excerpt=list(obs.recent_action_log), | |
| ) | |
| critic = self.critic.run(critic_input, step_idx=2) | |
| # Tally tokens billed to this brain's caller_ids. | |
| caller_id_base = f"cortex:{self.brain_id}" | |
| tokens_used = sum( | |
| self.llm_client.tokens_used_for(f"{caller_id_base}:{role}:t{tick}:r{round_}:s{idx}") | |
| for role, idx in ( | |
| ("world_modeler", 0), | |
| ("planner", 1), | |
| ("critic", 2), | |
| ) | |
| ) | |
| return self.aggregate( | |
| perception=perception, | |
| beliefs=[belief], | |
| plans=[plan], | |
| critics=[critic], | |
| tokens_used=tokens_used, | |
| ) | |