1818)
1919from gooddata_eval .core .chat .sse_client import ChatClient
2020from gooddata_eval .core .config import ReasoningEffort
21- from gooddata_eval .core .models import AgenticAssertionError , AgenticEvalOutcome , ToolCallEvent
21+ from gooddata_eval .core .models import (
22+ AgenticAssertionError ,
23+ AgenticEvalOutcome ,
24+ ChatResult ,
25+ ReasoningStepEvent ,
26+ ToolCallEvent ,
27+ build_latency_breakdown ,
28+ shift_and_index_events ,
29+ )
2230
2331_log = logging .getLogger (__name__ )
2432
@@ -170,6 +178,8 @@ class KdaRunResult:
170178 turn_wall_clock_sec : float | None = None
171179 reasoning_steps : list [str ] = field (default_factory = list )
172180 response_id : str | None = None
181+ tool_call_events : list [ToolCallEvent ] = field (default_factory = list )
182+ reasoning_step_events : list [ReasoningStepEvent ] = field (default_factory = list )
173183
174184
175185@dataclass
@@ -240,6 +250,22 @@ def _run_once(conv_id: str) -> KdaRunResult:
240250 current_question = question
241251 reasoning_steps : list [str ] = []
242252 response_id : str | None = None
253+ all_tool_call_events : list [ToolCallEvent ] = []
254+ all_reasoning_step_events : list [ReasoningStepEvent ] = []
255+ turn_offset = 0.0 # each turn's call_ts/ts restarts near 0 -- shift by prior turns' wall time
256+ tool_index_offset = 0
257+ reasoning_index_offset = 0
258+
259+ def _accumulate (result : ChatResult ) -> None :
260+ nonlocal turn_offset , tool_index_offset , reasoning_index_offset
261+ turn_offset , tool_index_offset , reasoning_index_offset = shift_and_index_events (
262+ result ,
263+ turn_offset = turn_offset ,
264+ tool_index_offset = tool_index_offset ,
265+ reasoning_index_offset = reasoning_index_offset ,
266+ )
267+ all_tool_call_events .extend (result .tool_call_events or [])
268+ all_reasoning_step_events .extend (result .reasoning_step_events or [])
243269
244270 for iteration in range (max_iterations ):
245271 try :
@@ -250,13 +276,15 @@ def _run_once(conv_id: str) -> KdaRunResult:
250276 if partial is not None :
251277 reasoning_steps .extend (partial .reasoning_steps or [])
252278 response_id = partial .response_id or response_id
279+ _accumulate (partial )
253280 create_args , execute_result = _extract_kda_calls (partial .tool_call_events or [])
254281 if create_args is not None :
255282 turn_wall_clock_sec = partial .turn_wall_clock_sec
256283 turn_completed = False
257284 break
258285 reasoning_steps .extend (chat_result .reasoning_steps or [])
259286 response_id = chat_result .response_id or response_id
287+ _accumulate (chat_result )
260288 create_args , execute_result = _extract_kda_calls (chat_result .tool_call_events or [])
261289 response_text = (chat_result .text_response or "" ).strip ()
262290 turn_completed = chat_result .stream_ended and bool (response_text )
@@ -295,6 +323,8 @@ def _run_once(conv_id: str) -> KdaRunResult:
295323 turn_wall_clock_sec = turn_wall_clock_sec ,
296324 reasoning_steps = reasoning_steps ,
297325 response_id = response_id ,
326+ tool_call_events = all_tool_call_events ,
327+ reasoning_step_events = all_reasoning_step_events ,
298328 )
299329
300330 try :
@@ -451,6 +481,7 @@ def _write_scores(ctx: RunTraceContext) -> None:
451481 "disambiguated" : ev .disambiguated ,
452482 "actual_create_args" : best .actual_create_args ,
453483 "actual_execute_result" : best .actual_execute_result ,
484+ "latency_breakdown" : build_latency_breakdown (best .tool_call_events , best .reasoning_step_events ),
454485 }
455486
456487 if not summary .pass_at_k :
0 commit comments