Commit 46a27e6
committed
feat(gooddata-eval): add KDA-skill agentic evaluator
Adds kda_skill.py to gooddata-eval, evaluating the chatbot's
create_key_driver_analysis/execute_key_driver_analysis tool calls against the
agent_kda_skill Langfuse dataset. Scope is completion (kda_triggered ->
executed -> success -> turn_completed), not per-field correctness -- per-field
checks are computed and logged as kda_-prefixed informational scores for a
follow-up ticket (QA-28699), and are None (not False) both when
expected_output has no key for a field AND when that field's own
precondition (kda_triggered, or executed+success for Summary) isn't met.
Latency is measured directly by the harness, not re-derived from Langfuse
after the fact: ChatResult.turn_wall_clock_sec is set by ChatClient around
the SSE read itself (after the connection opens, excluding any transient
retry's backoff sleep), stamped on both the successful result and any
ChatError.partial_result so a turn that dies mid-stream after KDA already
succeeded still gets a number. KdaRunResult.kda_turn_sec captures it in
_run_once at the exact point create_args gets set -- atomic with the
kda_triggered signal, not a separate step that can fail independently.
Logged as the kda_wall_clock_sec Langfuse score; combo_report.py (gdc-nas)
reads it directly, with no trace re-querying or observation-shape matching
needed on that side anymore.
Adds ChatResult.stream_ended (from the SSE response_ended event, derived --
not a raw server field, see sse_client.py's _RESPONSE_ENDED_EVENT comment).
turn_completed requires both stream_ended AND a non-empty text_response -- a
stream that ends cleanly but delivers nothing to the user isn't a completed
turn either, and a turn cut off mid-answer can still emit partial, non-empty
text before dying.
Fixes from review:
- kda_ prefix pass_at_k/pass_power_k Langfuse scores -- unprefixed, "pass_at_2"
at k=2 collides with visualization.py's own score name that gdc-nas's
combo_report.py.verdict() checks first, silently misfiling every KDA record
as visualization once KDA_RUN_K=2 is ever set.
- Relative (not absolute) tolerance for Summary's revenue-scale values by
default; change is checked against reference_value's scale, not against
itself. Also recognizes an explicit absolute_tolerance key -- every real
agent_kda_skill dataset item uses it, which this module never read before,
silently running ~3000x looser than the dataset author intended. Warns on
any other *tolerance* key so a future typo surfaces instead of repeating.
- Filters compared as canonicalized sets, not order-sensitive lists.
- except Exception (not except ChatError) around send_message -- a stream cut
off mid-turn raises a raw httpx transport error, which a narrower catch
would let escape uncaught, skipping Langfuse scoring entirely for that run.
- ChatError/TransientChatError carry partial_result so tool calls that
already succeeded before a later, unrelated stream error aren't discarded
and misreported as "the agent never called KDA at all".
- turn_completed resets to False on an exception, so a crash on a later
disambiguation iteration can't leave a stale True from an earlier iteration.
- kda_disambiguated logged and immediately nulls the six *_correct
informational fields: the simulated user reply names the acceptable
candidate(s) drawn from expected_output itself, so those fields aren't an
independent signal once a run went through disambiguation.
- KDA-specific _is_asking_clarification instead of a heuristic shared with
metric_skill.py/conversation.py, which had silently drifted apart; strips a
leading "to clarify, " discourse marker before its substring checks, since
that phrase means "in other words" in a final answer, not a request for one.
- run_agentic_kda_skill rejects k < 1 -- the single initial run happens
unconditionally regardless of k, so a bad env-driven KDA_RUN_K value (0, a
typo, negative) previously ran silently once instead of surfacing the bad
config, indistinguishable from a deliberate k=1.
- Regression tests for find_traces_per_conversation's None-safety and
_filters_match's isinstance guard.
JIRA: QA-288001 parent 676da68 commit 46a27e6
7 files changed
Lines changed: 2028 additions & 7 deletions
File tree
- packages/gooddata-eval
- src/gooddata_eval/core
- agentic
- chat
- tests
Lines changed: 14 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
33 | 41 | | |
34 | 42 | | |
35 | 43 | | |
| |||
56 | 64 | | |
57 | 65 | | |
58 | 66 | | |
| 67 | + | |
59 | 68 | | |
60 | 69 | | |
61 | 70 | | |
| |||
69 | 78 | | |
70 | 79 | | |
71 | 80 | | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
72 | 84 | | |
73 | 85 | | |
74 | 86 | | |
| |||
81 | 93 | | |
82 | 94 | | |
83 | 95 | | |
| 96 | + | |
84 | 97 | | |
85 | 98 | | |
86 | 99 | | |
87 | 100 | | |
88 | 101 | | |
89 | 102 | | |
90 | 103 | | |
| 104 | + | |
91 | 105 | | |
92 | 106 | | |
93 | 107 | | |
| |||
Lines changed: 689 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 66 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
31 | 34 | | |
32 | 35 | | |
33 | 36 | | |
34 | 37 | | |
35 | 38 | | |
36 | 39 | | |
37 | | - | |
| 40 | + | |
38 | 41 | | |
39 | | - | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
40 | 59 | | |
41 | 60 | | |
42 | 61 | | |
| 62 | + | |
43 | 63 | | |
44 | 64 | | |
45 | 65 | | |
| |||
109 | 129 | | |
110 | 130 | | |
111 | 131 | | |
| 132 | + | |
112 | 133 | | |
113 | 134 | | |
114 | 135 | | |
| |||
187 | 208 | | |
188 | 209 | | |
189 | 210 | | |
| 211 | + | |
190 | 212 | | |
191 | 213 | | |
192 | 214 | | |
193 | 215 | | |
194 | 216 | | |
195 | 217 | | |
196 | | - | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
197 | 232 | | |
198 | | - | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
199 | 243 | | |
200 | 244 | | |
201 | 245 | | |
202 | 246 | | |
203 | 247 | | |
204 | 248 | | |
205 | 249 | | |
| 250 | + | |
206 | 251 | | |
207 | 252 | | |
208 | 253 | | |
| |||
213 | 258 | | |
214 | 259 | | |
215 | 260 | | |
216 | | - | |
217 | | - | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
218 | 265 | | |
219 | 266 | | |
220 | 267 | | |
| |||
293 | 340 | | |
294 | 341 | | |
295 | 342 | | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
296 | 348 | | |
297 | 349 | | |
298 | | - | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
299 | 358 | | |
300 | 359 | | |
301 | 360 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
100 | 100 | | |
101 | 101 | | |
102 | 102 | | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
103 | 108 | | |
104 | 109 | | |
105 | 110 | | |
| |||
0 commit comments