|
| 1 | +import logging |
| 2 | +import os |
| 3 | +from typing import Any, Dict, Optional |
| 4 | + |
| 5 | +from auto_agent.agent import root_agent |
| 6 | +from auto_agent.agent_client.auto_agent_client import AutoAgentClient |
| 7 | +from auto_agent.subagents.pipeline_agent import AutonomousPipelineAgent |
| 8 | +from auto_search.graph import EvaluationResult, Node |
| 9 | + |
| 10 | +logger = logging.getLogger(__name__) |
| 11 | + |
| 12 | + |
| 13 | +class ADKSessionWorker: |
| 14 | + async def expand_node( |
| 15 | + self, |
| 16 | + session_id: str, |
| 17 | + parent_node: Node, |
| 18 | + session_dir: str, |
| 19 | + strategy: Optional[str] = None, |
| 20 | + agent_config: Optional[Dict[str, Any]] = None, |
| 21 | + ) -> Node: |
| 22 | + """Expand an ADK session to get a new optimized kernel.""" |
| 23 | + os.makedirs(session_dir, exist_ok=True) |
| 24 | + |
| 25 | + # Prepare inputs files for the agent based on parent_node |
| 26 | + self._prepare_inputs(session_dir, parent_node) |
| 27 | + |
| 28 | + # Run the agent and process results |
| 29 | + try: |
| 30 | + state = await self._run_agent( |
| 31 | + session_id=session_id, |
| 32 | + session_dir=session_dir, |
| 33 | + strategy=strategy, |
| 34 | + agent_config=agent_config, |
| 35 | + ) |
| 36 | + return self._process_results( |
| 37 | + session_id=session_id, |
| 38 | + parent_node=parent_node, |
| 39 | + strategy=strategy, |
| 40 | + state=state, |
| 41 | + ) |
| 42 | + except Exception as e: |
| 43 | + logger.exception(f"Session {session_id} failed: {e}") |
| 44 | + return Node( |
| 45 | + node_id=session_id, |
| 46 | + parent_id=parent_node.node_id, |
| 47 | + session_id=session_id, |
| 48 | + code="", |
| 49 | + plan="", |
| 50 | + depth=parent_node.depth + 1, |
| 51 | + strategy_applied=strategy, |
| 52 | + execution_status="FAIL", |
| 53 | + execution_error=str(e), |
| 54 | + evaluation=EvaluationResult(correct=False), |
| 55 | + ) |
| 56 | + |
| 57 | + def _prepare_inputs(self, session_dir: str, parent_node: Node) -> None: |
| 58 | + """Writes the parent node code and plan to the session directory.""" |
| 59 | + base_kernel_path = os.path.join(session_dir, "base_kernel.py") |
| 60 | + with open(base_kernel_path, "w") as f: |
| 61 | + f.write(parent_node.code) |
| 62 | + |
| 63 | + optimized_kernel_path = os.path.join(session_dir, "optimized_kernel.py") |
| 64 | + with open(optimized_kernel_path, "w") as f: |
| 65 | + f.write(parent_node.code) |
| 66 | + |
| 67 | + kernel_plan_path = None |
| 68 | + if parent_node.plan: |
| 69 | + kernel_plan_path = os.path.join(session_dir, "base_kernel_plan.md") |
| 70 | + with open(kernel_plan_path, "w") as f: |
| 71 | + f.write(parent_node.plan) |
| 72 | + |
| 73 | + async def _run_agent( |
| 74 | + self, |
| 75 | + session_id: str, |
| 76 | + session_dir: str, |
| 77 | + strategy: Optional[str], |
| 78 | + agent_config: Optional[Dict[str, Any]] = None, |
| 79 | + ) -> Dict[str, Any]: |
| 80 | + """Sets up a custom AutonomousPipelineAgent and runs the client.""" |
| 81 | + agent_config = agent_config or {} |
| 82 | + |
| 83 | + custom_agent = AutonomousPipelineAgent( |
| 84 | + name="AutonomousPipelineAgent", |
| 85 | + plan_agent=root_agent.plan_agent, |
| 86 | + implement_agent=root_agent.implement_agent, |
| 87 | + validate_agent=root_agent.validate_agent, |
| 88 | + test_gen_agent=root_agent.test_gen_agent, |
| 89 | + test_run_agent=root_agent.test_run_agent, |
| 90 | + autotune_agent=root_agent.autotune_agent, |
| 91 | + profile_agent=root_agent.profile_agent, |
| 92 | + session_dir=session_dir, |
| 93 | + **agent_config, |
| 94 | + ) |
| 95 | + |
| 96 | + strategy_query = f"Focus on: {strategy}. " if strategy else "" |
| 97 | + query = ( |
| 98 | + "Optimize the code for peak performance with pallas kernel. " |
| 99 | + f"{strategy_query}" |
| 100 | + "Base code is at base_kernel.py." |
| 101 | + ) |
| 102 | + client = AutoAgentClient( |
| 103 | + user_id="orchestrator", |
| 104 | + session_id=session_id, |
| 105 | + query=query, |
| 106 | + agent=custom_agent, |
| 107 | + ) |
| 108 | + await client.create_session() |
| 109 | + await client.run_async() |
| 110 | + return client.get_state() |
| 111 | + |
| 112 | + def _process_results( |
| 113 | + self, |
| 114 | + session_id: str, |
| 115 | + parent_node: Node, |
| 116 | + strategy: Optional[str], |
| 117 | + state: Dict[str, Any], |
| 118 | + ) -> Node: |
| 119 | + """Reads optimized code/plan and extracts metrics to construct a new Node.""" |
| 120 | + history = state.get("history", []) |
| 121 | + best_iter = state.get("best_iteration", -1) |
| 122 | + |
| 123 | + best_run = {} |
| 124 | + if best_iter != -1: |
| 125 | + best_run = next( |
| 126 | + (run for run in history if run.get("iteration") == best_iter), {} |
| 127 | + ) |
| 128 | + elif history: |
| 129 | + best_run = history[-1] |
| 130 | + |
| 131 | + comp_status = best_run.get("compilation_status", {}) |
| 132 | + compiled = comp_status.get("success", False) |
| 133 | + compilation_error = comp_status.get("message") if not compiled else None |
| 134 | + |
| 135 | + test_status = best_run.get("test_status", {}) |
| 136 | + correct = test_status.get("success", False) |
| 137 | + test_error = test_status.get("output") if not correct else None |
| 138 | + |
| 139 | + latency_ms = best_run.get("latency_ms") |
| 140 | + profiling_summary = best_run.get("profiling_summary") |
| 141 | + |
| 142 | + # Read optimized code if it exists |
| 143 | + opt_path = state.get("optimized_kernel_path") |
| 144 | + optimized_code = "" |
| 145 | + if opt_path and os.path.exists(opt_path): |
| 146 | + with open(opt_path, "r") as f: |
| 147 | + optimized_code = f.read() |
| 148 | + |
| 149 | + # Read optimized plan if it exists |
| 150 | + plan_path = state.get("kernel_plan_path") |
| 151 | + optimized_plan = "" |
| 152 | + if plan_path and os.path.exists(plan_path): |
| 153 | + with open(plan_path, "r") as f: |
| 154 | + optimized_plan = f.read() |
| 155 | + |
| 156 | + return Node( |
| 157 | + node_id=session_id, |
| 158 | + parent_id=parent_node.node_id, |
| 159 | + session_id=session_id, |
| 160 | + code=optimized_code, |
| 161 | + plan=optimized_plan, |
| 162 | + depth=parent_node.depth + 1, |
| 163 | + strategy_applied=strategy, |
| 164 | + execution_status="SUCCESS", |
| 165 | + evaluation=EvaluationResult( |
| 166 | + compiled=compiled, |
| 167 | + correct=correct, |
| 168 | + latency_ms=latency_ms, |
| 169 | + profiling_summary=profiling_summary, |
| 170 | + compilation_error=compilation_error, |
| 171 | + test_error=test_error, |
| 172 | + ), |
| 173 | + ) |
0 commit comments