gooddata-eval 1.76.1.dev2__py3-none-any.whl → 1.76.1.dev3__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.
@@ -13,12 +13,15 @@ module is the single place to swap — the runner only depends on the ChatBacken
13
13
  protocol, not on this class.
14
14
  """
15
15
 
16
+ import functools
16
17
  import json
17
18
  import logging
18
19
  import os
20
+ import re
19
21
  import time
20
22
  from dataclasses import dataclass, field
21
23
  from typing import Any, Callable, Iterable, TypeVar
24
+ from urllib.parse import quote
22
25
 
23
26
  import httpx
24
27
 
@@ -135,6 +138,45 @@ _TURN_TIMEOUT_S = _float_env("GOODDATA_EVAL_CHAT_TURN_TIMEOUT_S", 0.0)
135
138
  # 4-turn conversation run to 4x the budget, which is not what a user would sit through.
136
139
  _ITEM_TIMEOUT_S = _float_env("GOODDATA_EVAL_CHAT_ITEM_TIMEOUT_S", 0.0)
137
140
 
141
+ # Comma-separated `key=value` labels, e.g. `model_version=gpt-5.2,github_run_id=42`, sent as
142
+ # W3C baggage on every chat request. gen-ai's Langfuse span processor copies `langfuse_*`
143
+ # baggage onto each span it starts, so every observation of the conversation -- the cost-bearing
144
+ # generations, retries and the title trace included -- carries them from creation. Langfuse v4
145
+ # cannot add them to an observation afterwards. A value cannot contain a comma, and a key must be
146
+ # a plain token (letters, digits, `_`, `-`); any other key is skipped with a warning, because httpx
147
+ # refuses a non-ASCII header and gen-ai's OTel propagator drops or rewrites the rest.
148
+ _TRACE_LABELS_ENV = "GOODDATA_EVAL_TRACE_LABELS"
149
+ _TRACE_LABEL_KEY = re.compile(r"[A-Za-z0-9_-]+")
150
+
151
+
152
+ @functools.cache
153
+ def _warn_skipped_trace_label(key: str) -> None:
154
+ """Warn once per key per process: every ChatClient re-reads the labels."""
155
+ _log.warning("%s: skipping label with key %r, keys must match [A-Za-z0-9_-]+", _TRACE_LABELS_ENV, key)
156
+
157
+
158
+ def _trace_baggage() -> dict[str, str]:
159
+ """The `baggage` header for the labels in ``GOODDATA_EVAL_TRACE_LABELS``, or none.
160
+
161
+ Each label becomes trace metadata, and ``model_version`` -- the combo the report groups
162
+ on -- also becomes the observation ``version``, the dimension Langfuse groups cost by.
163
+ Values are percent-encoded: a space or comma would otherwise end the baggage entry.
164
+ """
165
+ labels: dict[str, str] = {}
166
+ for pair in os.getenv(_TRACE_LABELS_ENV, "").split(","):
167
+ key, sep, value = pair.partition("=")
168
+ key = key.strip()
169
+ if not sep or not key:
170
+ continue
171
+ if _TRACE_LABEL_KEY.fullmatch(key):
172
+ labels[key] = value.strip()
173
+ else:
174
+ _warn_skipped_trace_label(key)
175
+ entries = [f"langfuse_metadata_{k}={quote(v, safe='')}" for k, v in labels.items()]
176
+ if labels.get("model_version"):
177
+ entries.insert(0, f"langfuse_version={quote(labels['model_version'], safe='')}")
178
+ return {"baggage": ",".join(entries)} if entries else {}
179
+
138
180
 
139
181
  def set_default_turn_timeout(seconds: float | None) -> None:
140
182
  """Set the per-turn budget every ChatClient built afterwards inherits.
@@ -470,7 +512,7 @@ class ChatClient:
470
512
  the ``enableAiContextSetup`` feature flag is on for the organization.
471
513
  """
472
514
  self._base = f"{host.rstrip('/')}/api/v1/ai/workspaces/{workspace_id}/chat/conversations"
473
- self._auth = {"Authorization": f"Bearer {token}"}
515
+ self._auth = {"Authorization": f"Bearer {token}", **_trace_baggage()}
474
516
  # 0/None disables the cap. Also lowered onto the read timeout: the wall-clock check
475
517
  # fires between events, so a turn that goes silent needs the transport to give up too.
476
518
  budget = _TURN_TIMEOUT_S if turn_timeout_s is None else turn_timeout_s
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: gooddata-eval
3
- Version: 1.76.1.dev2
3
+ Version: 1.76.1.dev3
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.76.1.dev2
20
+ Requires-Dist: gooddata-sdk~=1.76.1.dev3
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
@@ -33,7 +33,7 @@ gooddata_eval/core/agentic/visualization.py,sha256=4g1nu-F7H54nttIdpmlBfipr6FS8m
33
33
  gooddata_eval/core/agentic/what_if.py,sha256=-1eJAvYiZdraTjb1m03JlMtJwQmyel52v2vGQEVd2Ts,24705
34
34
  gooddata_eval/core/chat/__init__.py,sha256=U54lANKm34yjqm7dZL9KkGouPbwAaQWC9wiAmb5B5g4,32
35
35
  gooddata_eval/core/chat/render.py,sha256=CqsKN8__DlaiJj_bmcPZ1poc5LfUqtz7EzKRDbks4gU,2082
36
- gooddata_eval/core/chat/sse_client.py,sha256=ikc8qfWWW3BiuX8rAYb5QItrz32OmSu7Piv92gFwYOs,27289
36
+ gooddata_eval/core/chat/sse_client.py,sha256=jvNAu1EXlc1ViqHJ1NC0C99A05An8QS7MMPj63_Wnw4,29420
37
37
  gooddata_eval/core/dataset/__init__.py,sha256=U54lANKm34yjqm7dZL9KkGouPbwAaQWC9wiAmb5B5g4,32
38
38
  gooddata_eval/core/dataset/from_insights.py,sha256=QxVprksX-l1Z4yLiOQOK8ZaUK5z64SCjdQym3cip99s,40520
39
39
  gooddata_eval/core/dataset/langfuse_source.py,sha256=6-nwFHbzVLEESkxEZoYPgDWRcPoXkohaYcdVKpxIRAY,7306
@@ -66,8 +66,8 @@ gooddata_eval/core/reporting/json_report.py,sha256=q3Jirc_Zhvzg5lkG_kM6JdnViNLe6
66
66
  gooddata_eval/core/reporting/report_template.html,sha256=vLkl95OZsm3dMdijv5zda-15wYPE5UvTs4uKeWnjCiI,22332
67
67
  gooddata_eval/core/summary/__init__.py,sha256=U54lANKm34yjqm7dZL9KkGouPbwAaQWC9wiAmb5B5g4,32
68
68
  gooddata_eval/core/summary/http_client.py,sha256=dPArJ6zoCu1W9xmYXFA1WMDNsSOkhn3gaCpYgCUp3gk,2174
69
- gooddata_eval-1.76.1.dev2.dist-info/METADATA,sha256=6TjchEqS9QacEVBSkYYAedl_7Dz91eRd2L6QZJOPTwk,37256
70
- gooddata_eval-1.76.1.dev2.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
71
- gooddata_eval-1.76.1.dev2.dist-info/entry_points.txt,sha256=28nFp5Viknx4haPYgzK9QHlwPFfC6rPF6RmjC2ht8EI,56
72
- gooddata_eval-1.76.1.dev2.dist-info/licenses/LICENSE.txt,sha256=LVfVlC9maU3K9lgMwdZnClQQsOIbOekdcdVKr9qzJtk,256836
73
- gooddata_eval-1.76.1.dev2.dist-info/RECORD,,
69
+ gooddata_eval-1.76.1.dev3.dist-info/METADATA,sha256=SwIoGDdCBtQkcQvZXliFCJ7eVqeMmTKVQjwyad8jDPE,37256
70
+ gooddata_eval-1.76.1.dev3.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
71
+ gooddata_eval-1.76.1.dev3.dist-info/entry_points.txt,sha256=28nFp5Viknx4haPYgzK9QHlwPFfC6rPF6RmjC2ht8EI,56
72
+ gooddata_eval-1.76.1.dev3.dist-info/licenses/LICENSE.txt,sha256=LVfVlC9maU3K9lgMwdZnClQQsOIbOekdcdVKr9qzJtk,256836
73
+ gooddata_eval-1.76.1.dev3.dist-info/RECORD,,