gooddata-eval 1.78.1.dev3__py3-none-any.whl → 1.78.1.dev4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gooddata_eval/core/agentic/document_skill.py +25 -5
- gooddata_eval/core/chat/sse_client.py +21 -2
- gooddata_eval/core/config.py +19 -0
- {gooddata_eval-1.78.1.dev3.dist-info → gooddata_eval-1.78.1.dev4.dist-info}/METADATA +2 -2
- {gooddata_eval-1.78.1.dev3.dist-info → gooddata_eval-1.78.1.dev4.dist-info}/RECORD +8 -8
- {gooddata_eval-1.78.1.dev3.dist-info → gooddata_eval-1.78.1.dev4.dist-info}/WHEEL +0 -0
- {gooddata_eval-1.78.1.dev3.dist-info → gooddata_eval-1.78.1.dev4.dist-info}/entry_points.txt +0 -0
- {gooddata_eval-1.78.1.dev3.dist-info → gooddata_eval-1.78.1.dev4.dist-info}/licenses/LICENSE.txt +0 -0
|
@@ -32,7 +32,7 @@ from gooddata_eval.core.agentic._trace_linker import (
|
|
|
32
32
|
from gooddata_eval.core.agentic.dashboard_skill import _extract_tool_result, _skill_activated
|
|
33
33
|
from gooddata_eval.core.chat.render import render_answer_text
|
|
34
34
|
from gooddata_eval.core.chat.sse_client import ChatClient
|
|
35
|
-
from gooddata_eval.core.config import ReasoningEffort
|
|
35
|
+
from gooddata_eval.core.config import DocumentFormat, ReasoningEffort, normalize_document_format
|
|
36
36
|
from gooddata_eval.core.evaluators._llm_judge import JudgeResponseError, LLMJudge, score_run
|
|
37
37
|
from gooddata_eval.core.langfuse.item_scope import item_scope
|
|
38
38
|
from gooddata_eval.core.models import (
|
|
@@ -801,18 +801,24 @@ def run_agentic_document_skill(
|
|
|
801
801
|
agent_id: str | None = None,
|
|
802
802
|
judge: LLMJudge | None = None,
|
|
803
803
|
user_context: dict | None = None,
|
|
804
|
+
document_format: DocumentFormat | None = None,
|
|
804
805
|
) -> AgenticDocumentSummary:
|
|
805
806
|
"""Run the document-skill agentic evaluation K times and return a summary.
|
|
806
807
|
|
|
807
808
|
The narrative judge is built only for a fixture that states a ``narrative``, so an item
|
|
808
809
|
without one needs neither the llm-judge extra nor ``OPENAI_API_KEY``.
|
|
809
810
|
|
|
811
|
+
``document_format`` is sent on every turn of every run, see ``ChatClient``; None leaves
|
|
812
|
+
the format to the server's ``enablePublisherV2`` feature flag.
|
|
813
|
+
|
|
810
814
|
Raises:
|
|
811
815
|
ValueError: the fixture is unusable — see ``_validate_expectation`` and
|
|
812
|
-
``_validate_user_context
|
|
816
|
+
``_validate_user_context``, or ``document_format`` is not a format gen-ai
|
|
817
|
+
accepts. Raised before any chat request.
|
|
813
818
|
"""
|
|
814
819
|
_validate_expectation(expected_output)
|
|
815
820
|
_validate_user_context(user_context)
|
|
821
|
+
document_format = normalize_document_format(document_format)
|
|
816
822
|
if judge is None and _has_narrative(expected_output):
|
|
817
823
|
judge = LLMJudge(_NARRATIVE_EVALUATION_STEPS)
|
|
818
824
|
run_results: list[DocumentRunResult] = []
|
|
@@ -823,6 +829,7 @@ def run_agentic_document_skill(
|
|
|
823
829
|
reasoning_effort=reasoning_effort,
|
|
824
830
|
agent_id=agent_id,
|
|
825
831
|
user_context=user_context,
|
|
832
|
+
document_format=document_format,
|
|
826
833
|
)
|
|
827
834
|
|
|
828
835
|
try:
|
|
@@ -882,20 +889,32 @@ def evaluate_agentic_document_skill(
|
|
|
882
889
|
gate: EvalGate = DEFAULT_GATE,
|
|
883
890
|
judge: LLMJudge | None = None,
|
|
884
891
|
user_context: dict | None = None,
|
|
892
|
+
document_format: DocumentFormat | None = None,
|
|
885
893
|
) -> AgenticEvalOutcome:
|
|
886
894
|
"""Run document-skill evaluation, log to Langfuse, and raise on failure.
|
|
887
895
|
|
|
888
896
|
Returns the best run's outcome on success; on failure the same values are attached to the
|
|
889
897
|
raised ``DocumentSkillAssertionError`` so callers can retrieve them either way.
|
|
890
898
|
|
|
899
|
+
``document_format`` (``aac-v1``/``aac-v2``) asks gen-ai for that document content format
|
|
900
|
+
on every turn and is recorded as ``document_format`` in the dataset-run metadata; None
|
|
901
|
+
leaves it to the server's ``enablePublisherV2`` feature flag.
|
|
902
|
+
|
|
891
903
|
Raises:
|
|
892
904
|
DocumentSkillAssertionError: the gate did not pass.
|
|
893
|
-
ValueError: the fixture is unusable
|
|
894
|
-
``_validate_user_context``. Raised before any
|
|
895
|
-
|
|
905
|
+
ValueError: the fixture is unusable, see ``_validate_expectation`` and
|
|
906
|
+
``_validate_user_context``. Raised before any chat request, so it means a
|
|
907
|
+
fixture to fix rather than a result to read. Also raised, equally before any
|
|
908
|
+
request, when the caller passes a ``document_format`` gen-ai does not accept.
|
|
896
909
|
JudgeResponseError: the fixture states a narrative and the judge returned no readable
|
|
897
910
|
verdict for any run -- an item without a result, not K failures.
|
|
898
911
|
"""
|
|
912
|
+
document_format = normalize_document_format(document_format)
|
|
913
|
+
if document_format is not None:
|
|
914
|
+
# Metadata only, not part of the run name: it tells runs apart only when their names
|
|
915
|
+
# already differ, so two runs that share a run_timestamp, dataset and model but not the
|
|
916
|
+
# format still collide on one dataset-run name.
|
|
917
|
+
run_metadata_extra = {**(run_metadata_extra or {}), "document_format": document_format}
|
|
899
918
|
identity = RunIdentity(
|
|
900
919
|
host,
|
|
901
920
|
token,
|
|
@@ -921,6 +940,7 @@ def evaluate_agentic_document_skill(
|
|
|
921
940
|
agent_id=agent_id,
|
|
922
941
|
judge=judge,
|
|
923
942
|
user_context=user_context,
|
|
943
|
+
document_format=document_format,
|
|
924
944
|
)
|
|
925
945
|
|
|
926
946
|
if langfuse is not None and dataset_item_id:
|
|
@@ -26,7 +26,12 @@ from urllib.parse import quote
|
|
|
26
26
|
import httpx
|
|
27
27
|
|
|
28
28
|
from gooddata_eval.core._retry import RETRYABLE_STATUS_CODES, float_env, int_env, retry_transient
|
|
29
|
-
from gooddata_eval.core.config import
|
|
29
|
+
from gooddata_eval.core.config import (
|
|
30
|
+
DocumentFormat,
|
|
31
|
+
ReasoningEffort,
|
|
32
|
+
normalize_document_format,
|
|
33
|
+
normalize_reasoning_effort,
|
|
34
|
+
)
|
|
30
35
|
from gooddata_eval.core.langfuse.item_scope import JoinedRun, baggage_entries, current_scope, mark_joined, trace_ids_for
|
|
31
36
|
from gooddata_eval.core.models import ChatResult, DatasetItem
|
|
32
37
|
from gooddata_eval.core.timing import note_trace_latency
|
|
@@ -460,6 +465,7 @@ class ChatClient:
|
|
|
460
465
|
reasoning_effort: ReasoningEffort | None = None,
|
|
461
466
|
agent_id: str | None = None,
|
|
462
467
|
user_context: dict[str, Any] | None = None,
|
|
468
|
+
document_format: DocumentFormat | None = None,
|
|
463
469
|
):
|
|
464
470
|
"""Create a chat client bound to one workspace.
|
|
465
471
|
|
|
@@ -476,6 +482,13 @@ class ChatClient:
|
|
|
476
482
|
back to it: a caller that changes or clears the context per message builds the
|
|
477
483
|
client without one. The server grounds answers in it only while
|
|
478
484
|
the ``enableAiContextSetup`` feature flag is on for the organization.
|
|
485
|
+
|
|
486
|
+
``document_format`` (``aac-v1``/``aac-v2``) is sent as ``options.documentFormat``
|
|
487
|
+
on every message and selects the document content format gen-ai drafts in for
|
|
488
|
+
that turn. gen-ai keeps a draft in the format of the turn that wrote it and a
|
|
489
|
+
turn in the other format cannot continue it, so follow-up and clarification
|
|
490
|
+
turns carry it too. When None the key is omitted and the server picks the format
|
|
491
|
+
from the ``enablePublisherV2`` feature flag. Any other value raises ``ValueError``.
|
|
479
492
|
"""
|
|
480
493
|
self._base = f"{host.rstrip('/')}/api/v1/ai/workspaces/{workspace_id}/chat/conversations"
|
|
481
494
|
self._auth = {"Authorization": f"Bearer {token}", **_trace_baggage()}
|
|
@@ -494,6 +507,7 @@ class ChatClient:
|
|
|
494
507
|
self._client = httpx.Client(timeout=http_timeout)
|
|
495
508
|
self._preserve_failed = preserve_failed
|
|
496
509
|
self._reasoning_effort = normalize_reasoning_effort(reasoning_effort)
|
|
510
|
+
self._document_format = normalize_document_format(document_format)
|
|
497
511
|
self._agent_id = agent_id
|
|
498
512
|
self._user_context = user_context
|
|
499
513
|
# Run index of each conversation this client has sent to, in first-send order: every
|
|
@@ -531,8 +545,13 @@ class ChatClient:
|
|
|
531
545
|
join_headers, joined = self._join_item_trace(conversation_id)
|
|
532
546
|
headers = {**self._auth, "Accept": "text/event-stream", "Content-Type": "application/json", **join_headers}
|
|
533
547
|
body: dict[str, Any] = {"item": {"role": "user", "content": {"type": "text", "text": question}}}
|
|
548
|
+
options: dict[str, str] = {}
|
|
534
549
|
if self._reasoning_effort is not None:
|
|
535
|
-
|
|
550
|
+
options["reasoningEffort"] = self._reasoning_effort
|
|
551
|
+
if self._document_format is not None:
|
|
552
|
+
options["documentFormat"] = self._document_format
|
|
553
|
+
if options:
|
|
554
|
+
body["options"] = options
|
|
536
555
|
# A per-call context overrides the client's. Only sent when there is one: gen-ai
|
|
537
556
|
# accepts an explicit null, so assigning unconditionally would quietly change every
|
|
538
557
|
# request that has no attachment.
|
gooddata_eval/core/config.py
CHANGED
|
@@ -33,6 +33,9 @@ def judge_model() -> str:
|
|
|
33
33
|
ReasoningEffort = Literal["LOW", "MEDIUM", "HIGH"]
|
|
34
34
|
"""Effort values the AI chat endpoint accepts, uppercase as the server enum requires."""
|
|
35
35
|
|
|
36
|
+
DocumentFormat = Literal["aac-v1", "aac-v2"]
|
|
37
|
+
"""Document content formats the AI chat endpoint accepts as ``options.documentFormat``."""
|
|
38
|
+
|
|
36
39
|
EvalGate = Literal["any", "power"]
|
|
37
40
|
"""`any` = pass@K, `power` = pass^K. Behaviour is in core/agentic/_gate.py; the type lives here
|
|
38
41
|
because putting it there would make config import the agentic package, whose __init__ imports
|
|
@@ -73,6 +76,22 @@ def normalize_reasoning_effort(value: str | None) -> ReasoningEffort | None:
|
|
|
73
76
|
return cast("ReasoningEffort", candidate)
|
|
74
77
|
|
|
75
78
|
|
|
79
|
+
def normalize_document_format(value: str | None) -> DocumentFormat | None:
|
|
80
|
+
"""Canonical document format, or None when unset.
|
|
81
|
+
|
|
82
|
+
gen-ai rejects any value outside `DocumentFormat`, so an unknown value raises here,
|
|
83
|
+
before a run sends its first request.
|
|
84
|
+
"""
|
|
85
|
+
if value is None:
|
|
86
|
+
return None
|
|
87
|
+
candidate = value.strip().lower()
|
|
88
|
+
if not candidate:
|
|
89
|
+
return None
|
|
90
|
+
if candidate not in get_args(DocumentFormat):
|
|
91
|
+
raise ValueError(f"Invalid document format {value!r}; expected one of {', '.join(get_args(DocumentFormat))}.")
|
|
92
|
+
return cast("DocumentFormat", candidate)
|
|
93
|
+
|
|
94
|
+
|
|
76
95
|
@dataclass
|
|
77
96
|
class RunConfig:
|
|
78
97
|
host: str
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: gooddata-eval
|
|
3
|
-
Version: 1.78.1.
|
|
3
|
+
Version: 1.78.1.dev4
|
|
4
4
|
Summary: Evaluate the GoodData AI agent against your own questions and models.
|
|
5
5
|
Project-URL: Source, https://github.com/gooddata/gooddata-python-sdk
|
|
6
6
|
Author-email: GoodData <support@gooddata.com>
|
|
@@ -17,7 +17,7 @@ Classifier: Topic :: Scientific/Engineering
|
|
|
17
17
|
Classifier: Topic :: Software Development
|
|
18
18
|
Classifier: Typing :: Typed
|
|
19
19
|
Requires-Python: >=3.10
|
|
20
|
-
Requires-Dist: gooddata-sdk~=1.78.1.
|
|
20
|
+
Requires-Dist: gooddata-sdk~=1.78.1.dev4
|
|
21
21
|
Requires-Dist: httpx<1.0,>=0.27
|
|
22
22
|
Requires-Dist: jsonpatch<2.0,>=1.33
|
|
23
23
|
Requires-Dist: orjson<4.0.0,>=3.9.15
|
|
@@ -6,7 +6,7 @@ gooddata_eval/cli/main.py,sha256=ZZv9pViwV4h21LPMrBOUCH99-oyM9dd2AFpGj9NWEJI,344
|
|
|
6
6
|
gooddata_eval/core/__init__.py,sha256=U54lANKm34yjqm7dZL9KkGouPbwAaQWC9wiAmb5B5g4,32
|
|
7
7
|
gooddata_eval/core/_output.py,sha256=sFbNtKg1lx431jpb15jISLlOXGTZ-r_KodfaTVyka6I,580
|
|
8
8
|
gooddata_eval/core/_retry.py,sha256=86ZPWu6ahCYC2GLvcbwjHTtj2RrGPOuxIFlCbtmNpvw,2990
|
|
9
|
-
gooddata_eval/core/config.py,sha256=
|
|
9
|
+
gooddata_eval/core/config.py,sha256=hla5t294uHC5Q9bzrhPjsdkwEcetLsEH-GqGAhs94b4,4823
|
|
10
10
|
gooddata_eval/core/connection.py,sha256=mh-Do5-Ti0-DXXikfCIH10eTTUbKuZUAS_sLoPNDJ5I,1229
|
|
11
11
|
gooddata_eval/core/granularity.py,sha256=CbniwgxtVj0oyf41UjeeZbBzOpeisSBlAfdkL79e6O0,3932
|
|
12
12
|
gooddata_eval/core/interaction.py,sha256=PUaJ1zdMwXBKjoNXNFXVgt_b8_i0LWdbMZndEQ3F6UM,2093
|
|
@@ -27,7 +27,7 @@ gooddata_eval/core/agentic/alert_skill.py,sha256=Me7YrAAGWG6iqzJR18JdhVsri4LG4J1
|
|
|
27
27
|
gooddata_eval/core/agentic/anomaly_detection.py,sha256=H_rKx6fCX3S11HzGAQGhy092YMmGj4foFBmrx6U-LHE,27701
|
|
28
28
|
gooddata_eval/core/agentic/conversation.py,sha256=_OLlST1twnSPnOQGfuuFCFKu92uwLVh2YBBA_nOW-5w,60004
|
|
29
29
|
gooddata_eval/core/agentic/dashboard_skill.py,sha256=PnFq1JjaMpAjQkzgklRkEFFKEs4WWhORikDVw5qjbaE,84630
|
|
30
|
-
gooddata_eval/core/agentic/document_skill.py,sha256=
|
|
30
|
+
gooddata_eval/core/agentic/document_skill.py,sha256=Uukqc6voa3lXbcSVgfzQyPH_kEFu3jrbrN9EDIMIuYA,45231
|
|
31
31
|
gooddata_eval/core/agentic/general_question.py,sha256=pOVYlJF9eKZwTqdPVsrH4X1OC-tXI7CMCFDdPNdBIMw,17758
|
|
32
32
|
gooddata_eval/core/agentic/guardrail.py,sha256=1Yz5QVVWo5GCOA8OKSy5efeysaaXB3bXcr_BT-Qu8tY,16398
|
|
33
33
|
gooddata_eval/core/agentic/kda_skill.py,sha256=2mav9itclavID28U4fORSR9p-iVTrddMyTHLKh8HxdE,26154
|
|
@@ -38,7 +38,7 @@ gooddata_eval/core/agentic/visualization.py,sha256=o4RVS-nRCVbVXjbE_jHuGzgW8x3hR
|
|
|
38
38
|
gooddata_eval/core/agentic/what_if.py,sha256=v5u9Yl45QGpVD2IHvPhVW_XOixI10IK4N-5_zP9Yymw,26365
|
|
39
39
|
gooddata_eval/core/chat/__init__.py,sha256=U54lANKm34yjqm7dZL9KkGouPbwAaQWC9wiAmb5B5g4,32
|
|
40
40
|
gooddata_eval/core/chat/render.py,sha256=CqsKN8__DlaiJj_bmcPZ1poc5LfUqtz7EzKRDbks4gU,2082
|
|
41
|
-
gooddata_eval/core/chat/sse_client.py,sha256=
|
|
41
|
+
gooddata_eval/core/chat/sse_client.py,sha256=yGUbWg7gr7ycVfEpvpmGUCIQ38nW0jiMmuJB9_va4UY,31921
|
|
42
42
|
gooddata_eval/core/dataset/__init__.py,sha256=U54lANKm34yjqm7dZL9KkGouPbwAaQWC9wiAmb5B5g4,32
|
|
43
43
|
gooddata_eval/core/dataset/from_insights.py,sha256=2eYh_84070t2BMeW2XPLAwzrJs7vKbFYMeCppvkDiEo,40880
|
|
44
44
|
gooddata_eval/core/dataset/langfuse_source.py,sha256=II-6fenEPhdyfckrL0iVdJpavjv67wUvy7OIuvHntrg,8697
|
|
@@ -77,8 +77,8 @@ gooddata_eval/core/summary/http_client.py,sha256=Umae42fiiJQ0e4hv63NRROHYvcFAGgX
|
|
|
77
77
|
gooddata_eval/core/takeaway/__init__.py,sha256=U54lANKm34yjqm7dZL9KkGouPbwAaQWC9wiAmb5B5g4,32
|
|
78
78
|
gooddata_eval/core/takeaway/evaluate.py,sha256=ei7DLSlG_Ove_R551Ofdw8WISf178XknU58jBWxB_is,11585
|
|
79
79
|
gooddata_eval/core/takeaway/http_client.py,sha256=yc3FNPArjfcSdAE7naRf7g_aW7BbJhwsfSEvAFd67Ik,4141
|
|
80
|
-
gooddata_eval-1.78.1.
|
|
81
|
-
gooddata_eval-1.78.1.
|
|
82
|
-
gooddata_eval-1.78.1.
|
|
83
|
-
gooddata_eval-1.78.1.
|
|
84
|
-
gooddata_eval-1.78.1.
|
|
80
|
+
gooddata_eval-1.78.1.dev4.dist-info/METADATA,sha256=uQZy3GjLJ3V1W9B9RR9kX6fLzD5-Var8lEQApCzH3iA,60351
|
|
81
|
+
gooddata_eval-1.78.1.dev4.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
82
|
+
gooddata_eval-1.78.1.dev4.dist-info/entry_points.txt,sha256=28nFp5Viknx4haPYgzK9QHlwPFfC6rPF6RmjC2ht8EI,56
|
|
83
|
+
gooddata_eval-1.78.1.dev4.dist-info/licenses/LICENSE.txt,sha256=LVfVlC9maU3K9lgMwdZnClQQsOIbOekdcdVKr9qzJtk,256836
|
|
84
|
+
gooddata_eval-1.78.1.dev4.dist-info/RECORD,,
|
|
File without changes
|
{gooddata_eval-1.78.1.dev3.dist-info → gooddata_eval-1.78.1.dev4.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{gooddata_eval-1.78.1.dev3.dist-info → gooddata_eval-1.78.1.dev4.dist-info}/licenses/LICENSE.txt
RENAMED
|
File without changes
|