88from util .config import load_yaml_config
99from mp import mprunner
1010from work .agentgenwork import AgentGenWork
11+ from evaluator .simulateduser import SimulatedUser
12+ from work .agentscorework import AgentScoreWork
13+ import json
14+ import subprocess
15+ from typing import Dict
1116
1217
1318class AgentEvaluator :
@@ -68,7 +73,14 @@ def _evaluate_gemini_cli(
6873 }
6974
7075 for item in dataset :
71- work = AgentGenWork (self .generator , self .agent_version , item , job_id = job_id , metadata = metadata )
76+ simulated_user = SimulatedUser (self .config )
77+ work = AgentGenWork (
78+ processor = self .process_scenario ,
79+ eval_result = item ,
80+ job_id = job_id ,
81+ metadata = metadata ,
82+ simulated_user = simulated_user
83+ )
7284 self .agentrunner .execute_work (work )
7385
7486 for future in concurrent .futures .as_completed (self .agentrunner .futures ):
@@ -80,3 +92,117 @@ def _evaluate_gemini_cli(
8092 scoring_results .extend (item .scoring_results )
8193
8294 return eval_outputs , scoring_results
95+
96+ def process_scenario (
97+ self ,
98+ scenario : Dict [str , Any ],
99+ eval_result : Any ,
100+ job_id : str ,
101+ metadata : Dict [str , Any ],
102+ simulated_user : Any = None
103+ ):
104+ """Processes a single scenario."""
105+ current_prompt = scenario ["starting_prompt" ]
106+ env = scenario .get ("env" , {})
107+ max_turns = scenario .get ("max_turns" , 1 )
108+ conversation_plan = scenario .get ("conversation_plan" , "" )
109+ conversation_history = []
110+ accumulated_tools = []
111+ last_result = None
112+
113+ for turn in range (max_turns ):
114+ logging .info (f"Turn { turn + 1 } /{ max_turns } - Prompt: { current_prompt } " )
115+
116+ if isinstance (self .generator , GeminiCliGenerator ):
117+ cli_cmd = self .generator .create_command (
118+ cli = self .agent_version ,
119+ prompt = current_prompt ,
120+ env = env ,
121+ resume = (turn > 0 )
122+ )
123+ result = self .generator .safe_generate (cli_cmd )
124+ else :
125+ result = self .generator .generate (current_prompt )
126+
127+ last_result = result
128+
129+ self ._log_cli_result (turn , max_turns , result )
130+
131+ tools = []
132+ if isinstance (self .generator , GeminiCliGenerator ):
133+ tools = self .generator .extract_tools (result .stdout )
134+ accumulated_tools .extend (tools )
135+
136+ conversation_history .append ({
137+ "user" : current_prompt ,
138+ "agent" : result .stdout
139+ })
140+
141+ if turn < max_turns - 1 :
142+ if simulated_user :
143+ next_response = simulated_user .get_next_response (
144+ conversation_plan ,
145+ conversation_history ,
146+ result .stdout
147+ )
148+ if "TERMINATE" in next_response :
149+ logging .info ("Simulated user terminated conversation." )
150+ break
151+ current_prompt = next_response
152+ else :
153+ break
154+
155+ if last_result :
156+ self ._finalize_scenario (
157+ scenario ,
158+ last_result ,
159+ conversation_history ,
160+ accumulated_tools ,
161+ eval_result ,
162+ job_id ,
163+ metadata
164+ )
165+
166+ def _log_cli_result (self , turn : int , max_turns : int , result : subprocess .CompletedProcess ):
167+ logging .info (f"Turn { turn + 1 } /{ max_turns } - Gemini CLI exit code: { result .returncode } " )
168+ logging .info (f"Turn { turn + 1 } /{ max_turns } - Gemini CLI stdout: { result .stdout } " )
169+ logging .info (f"Turn { turn + 1 } /{ max_turns } - Gemini CLI stderr: { result .stderr } " )
170+
171+ def _finalize_scenario (
172+ self ,
173+ scenario : Dict [str , Any ],
174+ last_result : subprocess .CompletedProcess ,
175+ conversation_history : List [Dict [str , str ]],
176+ accumulated_tools : List [str ],
177+ eval_result : Any ,
178+ job_id : str ,
179+ metadata : Dict [str , Any ]
180+ ):
181+ """Finalizes the scenario by scoring and appending results."""
182+ # Prepare intermediate eval_output with all necessary data for scoring
183+ eval_output_data = {
184+ "eval_id" : scenario ["id" ],
185+ "stdout" : last_result .stdout ,
186+ "stderr" : last_result .stderr ,
187+ "returncode" : last_result .returncode ,
188+ "prompt_generator_error" : None ,
189+ "generated_error" : None ,
190+ "sql_generator_error" : None ,
191+ "golden_error" : None ,
192+ "generated_sql" : "skipped" ,
193+ "prompt" : scenario ["starting_prompt" ],
194+ "conversation_history" : json .dumps (conversation_history , indent = 2 ),
195+ "scenario" : scenario ,
196+ "accumulated_tools" : accumulated_tools ,
197+ "job_id" : job_id ,
198+ "metadata" : metadata
199+ }
200+
201+ score_work = AgentScoreWork (
202+ config = metadata ,
203+ eval_output = eval_output_data ,
204+ scoring_results = eval_result .scoring_results
205+ )
206+ score_work .run ()
207+
208+ eval_result .agent_results .append (eval_output_data )
0 commit comments