judgeval 0.9.2__py3-none-any.whl → 0.9.4__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.
- judgeval/tracer/__init__.py +27 -43
- judgeval/tracer/processors/__init__.py +84 -6
- judgeval/utils/serialize.py +7 -1
- {judgeval-0.9.2.dist-info → judgeval-0.9.4.dist-info}/METADATA +2 -2
- {judgeval-0.9.2.dist-info → judgeval-0.9.4.dist-info}/RECORD +8 -8
- {judgeval-0.9.2.dist-info → judgeval-0.9.4.dist-info}/WHEEL +0 -0
- {judgeval-0.9.2.dist-info → judgeval-0.9.4.dist-info}/entry_points.txt +0 -0
- {judgeval-0.9.2.dist-info → judgeval-0.9.4.dist-info}/licenses/LICENSE.md +0 -0
judgeval/tracer/__init__.py
CHANGED
@@ -57,7 +57,7 @@ from judgeval.utils.serialize import safe_serialize
|
|
57
57
|
from judgeval.version import get_version
|
58
58
|
from judgeval.warnings import JudgmentWarning
|
59
59
|
|
60
|
-
from judgeval.tracer.keys import AttributeKeys,
|
60
|
+
from judgeval.tracer.keys import AttributeKeys, InternalAttributeKeys
|
61
61
|
from judgeval.api import JudgmentSyncClient
|
62
62
|
from judgeval.tracer.llm import wrap_provider
|
63
63
|
from judgeval.utils.url import url_for
|
@@ -65,6 +65,7 @@ from judgeval.tracer.local_eval_queue import LocalEvaluationQueue
|
|
65
65
|
from judgeval.tracer.processors import (
|
66
66
|
JudgmentSpanProcessor,
|
67
67
|
NoOpJudgmentSpanProcessor,
|
68
|
+
NoOpSpanProcessor,
|
68
69
|
)
|
69
70
|
from judgeval.tracer.utils import set_span_attribute, TraceScorerConfig
|
70
71
|
|
@@ -85,19 +86,6 @@ class AgentContext(TypedDict):
|
|
85
86
|
parent_agent_id: str | None
|
86
87
|
|
87
88
|
|
88
|
-
def resolve_project_id(
|
89
|
-
api_key: str, organization_id: str, project_name: str
|
90
|
-
) -> str | None:
|
91
|
-
try:
|
92
|
-
client = JudgmentSyncClient(
|
93
|
-
api_key=api_key,
|
94
|
-
organization_id=organization_id,
|
95
|
-
)
|
96
|
-
return client.projects_resolve({"project_name": project_name})["project_id"]
|
97
|
-
except Exception:
|
98
|
-
return None
|
99
|
-
|
100
|
-
|
101
89
|
class Tracer:
|
102
90
|
_active_tracers: List[Tracer] = []
|
103
91
|
|
@@ -188,38 +176,20 @@ class Tracer:
|
|
188
176
|
self.cost_context = ContextVar("current_cost_context", default=None)
|
189
177
|
|
190
178
|
if self.enable_monitoring:
|
191
|
-
project_id = resolve_project_id(
|
192
|
-
self.api_key, self.organization_id, self.project_name
|
193
|
-
)
|
194
|
-
|
195
|
-
resource_attributes = resource_attributes or {}
|
196
|
-
resource_attributes.update(
|
197
|
-
{
|
198
|
-
ResourceKeys.SERVICE_NAME: self.project_name,
|
199
|
-
ResourceKeys.TELEMETRY_SDK_NAME: "judgeval",
|
200
|
-
ResourceKeys.TELEMETRY_SDK_VERSION: get_version(),
|
201
|
-
}
|
202
|
-
)
|
203
|
-
|
204
|
-
if project_id is not None:
|
205
|
-
resource_attributes[ResourceKeys.JUDGMENT_PROJECT_ID] = project_id
|
206
|
-
else:
|
207
|
-
judgeval_logger.error(
|
208
|
-
f"Failed to resolve project {self.project_name}, please create it first at https://app.judgmentlabs.ai/projects. Skipping Judgment export."
|
209
|
-
)
|
210
|
-
|
211
|
-
resource = Resource.create(resource_attributes)
|
212
|
-
|
213
179
|
self.judgment_processor = JudgmentSpanProcessor(
|
214
180
|
self,
|
215
|
-
self.
|
181
|
+
self.project_name,
|
216
182
|
self.api_key,
|
217
183
|
self.organization_id,
|
218
184
|
max_queue_size=2**18,
|
219
185
|
export_timeout_millis=30000,
|
186
|
+
resource_attributes=resource_attributes,
|
220
187
|
)
|
221
|
-
|
188
|
+
|
189
|
+
resource = Resource.create(self.judgment_processor.resource_attributes)
|
222
190
|
self.provider = TracerProvider(resource=resource)
|
191
|
+
|
192
|
+
self.processors.append(self.judgment_processor)
|
223
193
|
for processor in self.processors:
|
224
194
|
self.provider.add_span_processor(processor)
|
225
195
|
|
@@ -253,6 +223,14 @@ class Tracer:
|
|
253
223
|
def get_current_cost_context(self):
|
254
224
|
return self.cost_context
|
255
225
|
|
226
|
+
def get_processor(self):
|
227
|
+
"""Get the judgment span processor instance.
|
228
|
+
|
229
|
+
Returns:
|
230
|
+
The JudgmentSpanProcessor or NoOpJudgmentSpanProcessor instance used by this tracer.
|
231
|
+
"""
|
232
|
+
return self.judgment_processor
|
233
|
+
|
256
234
|
def set_customer_id(self, customer_id: str) -> None:
|
257
235
|
span = self.get_current_span()
|
258
236
|
if span and span.is_recording():
|
@@ -913,11 +891,7 @@ class Tracer:
|
|
913
891
|
proper cleanup before program termination.
|
914
892
|
"""
|
915
893
|
try:
|
916
|
-
|
917
|
-
if not success:
|
918
|
-
judgeval_logger.warning(
|
919
|
-
"Some spans may not have been exported before program exit"
|
920
|
-
)
|
894
|
+
self.force_flush(timeout_millis=30000)
|
921
895
|
except Exception as e:
|
922
896
|
judgeval_logger.warning(f"Error during atexit flush: {e}")
|
923
897
|
|
@@ -1074,3 +1048,13 @@ def format_inputs(
|
|
1074
1048
|
return inputs
|
1075
1049
|
except Exception:
|
1076
1050
|
return {}
|
1051
|
+
|
1052
|
+
|
1053
|
+
# Export processor classes for direct access
|
1054
|
+
__all__ = [
|
1055
|
+
"Tracer",
|
1056
|
+
"wrap",
|
1057
|
+
"JudgmentSpanProcessor",
|
1058
|
+
"NoOpJudgmentSpanProcessor",
|
1059
|
+
"NoOpSpanProcessor",
|
1060
|
+
]
|
@@ -6,8 +6,13 @@ from opentelemetry.sdk.trace import ReadableSpan, Span, SpanProcessor, SpanConte
|
|
6
6
|
from opentelemetry.sdk.trace.export import (
|
7
7
|
BatchSpanProcessor,
|
8
8
|
)
|
9
|
+
from opentelemetry.sdk.resources import Resource
|
9
10
|
from judgeval.tracer.exporters import JudgmentSpanExporter
|
10
|
-
from judgeval.tracer.keys import AttributeKeys, InternalAttributeKeys
|
11
|
+
from judgeval.tracer.keys import AttributeKeys, InternalAttributeKeys, ResourceKeys
|
12
|
+
from judgeval.api import JudgmentSyncClient
|
13
|
+
from judgeval.logger import judgeval_logger
|
14
|
+
from judgeval.utils.url import url_for
|
15
|
+
from judgeval.version import get_version
|
11
16
|
|
12
17
|
if TYPE_CHECKING:
|
13
18
|
from judgeval.tracer import Tracer
|
@@ -31,15 +36,27 @@ class JudgmentSpanProcessor(BatchSpanProcessor):
|
|
31
36
|
def __init__(
|
32
37
|
self,
|
33
38
|
tracer: Tracer,
|
34
|
-
|
39
|
+
project_name: str,
|
35
40
|
api_key: str,
|
36
41
|
organization_id: str,
|
37
42
|
/,
|
38
43
|
*,
|
39
44
|
max_queue_size: int = 2**18,
|
40
45
|
export_timeout_millis: int = 30000,
|
46
|
+
resource_attributes: Optional[dict[str, Any]] = None,
|
41
47
|
):
|
42
48
|
self.tracer = tracer
|
49
|
+
self.project_name = project_name
|
50
|
+
self.api_key = api_key
|
51
|
+
self.organization_id = organization_id
|
52
|
+
|
53
|
+
# Resolve project_id
|
54
|
+
self.project_id = self._resolve_project_id()
|
55
|
+
|
56
|
+
# Set up resource attributes with project_id
|
57
|
+
self._setup_resource_attributes(resource_attributes or {})
|
58
|
+
|
59
|
+
endpoint = url_for("/otel/v1/traces")
|
43
60
|
super().__init__(
|
44
61
|
JudgmentSpanExporter(
|
45
62
|
endpoint=endpoint,
|
@@ -53,6 +70,38 @@ class JudgmentSpanProcessor(BatchSpanProcessor):
|
|
53
70
|
defaultdict(dict)
|
54
71
|
)
|
55
72
|
|
73
|
+
def _resolve_project_id(self) -> str | None:
|
74
|
+
"""Resolve project_id from project_name using the API."""
|
75
|
+
try:
|
76
|
+
client = JudgmentSyncClient(
|
77
|
+
api_key=self.api_key,
|
78
|
+
organization_id=self.organization_id,
|
79
|
+
)
|
80
|
+
return client.projects_resolve({"project_name": self.project_name})[
|
81
|
+
"project_id"
|
82
|
+
]
|
83
|
+
except Exception:
|
84
|
+
return None
|
85
|
+
|
86
|
+
def _setup_resource_attributes(self, resource_attributes: dict[str, Any]) -> None:
|
87
|
+
"""Set up resource attributes including project_id."""
|
88
|
+
resource_attributes.update(
|
89
|
+
{
|
90
|
+
ResourceKeys.SERVICE_NAME: self.project_name,
|
91
|
+
ResourceKeys.TELEMETRY_SDK_NAME: "judgeval",
|
92
|
+
ResourceKeys.TELEMETRY_SDK_VERSION: get_version(),
|
93
|
+
}
|
94
|
+
)
|
95
|
+
|
96
|
+
if self.project_id is not None:
|
97
|
+
resource_attributes[ResourceKeys.JUDGMENT_PROJECT_ID] = self.project_id
|
98
|
+
else:
|
99
|
+
judgeval_logger.error(
|
100
|
+
f"Failed to resolve project {self.project_name}, please create it first at https://app.judgmentlabs.ai/projects. Skipping Judgment export."
|
101
|
+
)
|
102
|
+
|
103
|
+
self.resource_attributes = resource_attributes
|
104
|
+
|
56
105
|
def _get_span_key(self, span_context: SpanContext) -> tuple[int, int]:
|
57
106
|
return (span_context.trace_id, span_context.span_id)
|
58
107
|
|
@@ -103,11 +152,18 @@ class JudgmentSpanProcessor(BatchSpanProcessor):
|
|
103
152
|
|
104
153
|
attributes = dict(current_span.attributes or {})
|
105
154
|
attributes[AttributeKeys.JUDGMENT_UPDATE_ID] = current_update_id
|
155
|
+
|
156
|
+
existing_resource_attrs = (
|
157
|
+
dict(current_span.resource.attributes) if current_span.resource else {}
|
158
|
+
)
|
159
|
+
merged_resource_attrs = {**existing_resource_attrs, **self.resource_attributes}
|
160
|
+
merged_resource = Resource.create(merged_resource_attrs)
|
161
|
+
|
106
162
|
partial_span = ReadableSpan(
|
107
163
|
name=current_span.name,
|
108
164
|
context=span_context,
|
109
165
|
parent=current_span.parent,
|
110
|
-
resource=
|
166
|
+
resource=merged_resource,
|
111
167
|
attributes=attributes,
|
112
168
|
events=current_span.events,
|
113
169
|
links=current_span.links,
|
@@ -137,11 +193,20 @@ class JudgmentSpanProcessor(BatchSpanProcessor):
|
|
137
193
|
attributes = dict(span.attributes or {})
|
138
194
|
attributes[AttributeKeys.JUDGMENT_UPDATE_ID] = 20
|
139
195
|
|
196
|
+
existing_resource_attrs = (
|
197
|
+
dict(span.resource.attributes) if span.resource else {}
|
198
|
+
)
|
199
|
+
merged_resource_attrs = {
|
200
|
+
**existing_resource_attrs,
|
201
|
+
**self.resource_attributes,
|
202
|
+
}
|
203
|
+
merged_resource = Resource.create(merged_resource_attrs)
|
204
|
+
|
140
205
|
final_span = ReadableSpan(
|
141
206
|
name=span.name,
|
142
207
|
context=span.context,
|
143
208
|
parent=span.parent,
|
144
|
-
resource=
|
209
|
+
resource=merged_resource,
|
145
210
|
attributes=attributes,
|
146
211
|
events=span.events,
|
147
212
|
links=span.links,
|
@@ -160,7 +225,7 @@ class JudgmentSpanProcessor(BatchSpanProcessor):
|
|
160
225
|
|
161
226
|
class NoOpJudgmentSpanProcessor(JudgmentSpanProcessor):
|
162
227
|
def __init__(self):
|
163
|
-
|
228
|
+
pass
|
164
229
|
|
165
230
|
def on_start(self, span: Span, parent_context: Optional[Context] = None) -> None:
|
166
231
|
pass
|
@@ -177,5 +242,18 @@ class NoOpJudgmentSpanProcessor(JudgmentSpanProcessor):
|
|
177
242
|
def emit_partial(self) -> None:
|
178
243
|
pass
|
179
244
|
|
245
|
+
def set_internal_attribute(
|
246
|
+
self, span_context: SpanContext, key: str, value: Any
|
247
|
+
) -> None:
|
248
|
+
pass
|
249
|
+
|
250
|
+
def get_internal_attribute(
|
251
|
+
self, span_context: SpanContext, key: str, default: Any = None
|
252
|
+
) -> Any:
|
253
|
+
return default
|
254
|
+
|
255
|
+
def increment_update_id(self, span_context: SpanContext) -> int:
|
256
|
+
return 0
|
257
|
+
|
180
258
|
|
181
|
-
__all__ =
|
259
|
+
__all__ = ["NoOpSpanProcessor", "JudgmentSpanProcessor", "NoOpJudgmentSpanProcessor"]
|
judgeval/utils/serialize.py
CHANGED
@@ -19,6 +19,8 @@ from pydantic import BaseModel
|
|
19
19
|
from pydantic.types import SecretBytes, SecretStr
|
20
20
|
import orjson
|
21
21
|
|
22
|
+
from judgeval.logger import judgeval_logger
|
23
|
+
|
22
24
|
|
23
25
|
"""
|
24
26
|
This module contains the encoders used by jsonable_encoder to convert Python objects to JSON serializable data types.
|
@@ -244,4 +246,8 @@ encoders_by_class_tuples = generate_encoders_by_class_tuples(ENCODERS_BY_TYPE)
|
|
244
246
|
|
245
247
|
# Seralize arbitrary object to a json string
|
246
248
|
def safe_serialize(obj: Any) -> str:
|
247
|
-
|
249
|
+
try:
|
250
|
+
return orjson.dumps(json_encoder(obj)).decode()
|
251
|
+
except Exception as e:
|
252
|
+
judgeval_logger.warning(f"Error serializing object: {e}")
|
253
|
+
return orjson.dumps(repr(obj)).decode()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: judgeval
|
3
|
-
Version: 0.9.
|
3
|
+
Version: 0.9.4
|
4
4
|
Summary: Judgeval Package
|
5
5
|
Project-URL: Homepage, https://github.com/JudgmentLabs/judgeval
|
6
6
|
Project-URL: Issues, https://github.com/JudgmentLabs/judgeval/issues
|
@@ -9,7 +9,7 @@ License-Expression: Apache-2.0
|
|
9
9
|
License-File: LICENSE.md
|
10
10
|
Classifier: Operating System :: OS Independent
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
12
|
-
Requires-Python: >=3.
|
12
|
+
Requires-Python: >=3.10
|
13
13
|
Requires-Dist: boto3>=1.40.11
|
14
14
|
Requires-Dist: click<8.2.0
|
15
15
|
Requires-Dist: dotenv
|
@@ -46,7 +46,7 @@ judgeval/scorers/judgeval_scorers/api_scorers/instruction_adherence.py,sha256=aQ
|
|
46
46
|
judgeval/scorers/judgeval_scorers/api_scorers/prompt_scorer.py,sha256=C-9Q7s9K7mcgFMcEL0I_7XQZMRqrL5MFRi9G6Dx8-v8,8505
|
47
47
|
judgeval/scorers/judgeval_scorers/api_scorers/tool_dependency.py,sha256=BhrLnIASZOTT9XJ6giYSoVfdR7NYsjRRTOTNioNtEiU,610
|
48
48
|
judgeval/scorers/judgeval_scorers/api_scorers/tool_order.py,sha256=bMu0WMJaXdMyDTN42sVLoWV-lrUHCEa8iDrCI_K7nlQ,808
|
49
|
-
judgeval/tracer/__init__.py,sha256=
|
49
|
+
judgeval/tracer/__init__.py,sha256=0DM6ixBI75FuVG7UMG_k-KHJm1MyFbRyhAUPm2GYu9A,36057
|
50
50
|
judgeval/tracer/constants.py,sha256=ae8tivAW97awJQxdRB9OMqX50wOLX3zqChT_AGkPBu0,85
|
51
51
|
judgeval/tracer/keys.py,sha256=qXPoZSkEhVF-YYfQ9-zeDMVdr4GtpPf2W7MPJaN2AQo,2889
|
52
52
|
judgeval/tracer/local_eval_queue.py,sha256=Amt7xkdmVJH1l2itm-ogiIW5oDaLnACisGfsdZjazn0,7228
|
@@ -58,7 +58,7 @@ judgeval/tracer/exporters/store.py,sha256=KQV3cyqteesByQjR-9VdPXT9OlUZ-6F08ogqj8
|
|
58
58
|
judgeval/tracer/exporters/utils.py,sha256=JRcoSQuEHxMDJbXfyrUIfA2SHBVkZM82h4bTbYGxkNw,1154
|
59
59
|
judgeval/tracer/llm/__init__.py,sha256=p9uwWPg9k-NcWjj9TbwQj55sHhBOqRYx2-Ld6YHaFUs,42625
|
60
60
|
judgeval/tracer/llm/providers.py,sha256=QQLJlSNnDjXRAc2Wqw78o254COJUSXX39D7D_mx3NVA,2651
|
61
|
-
judgeval/tracer/processors/__init__.py,sha256=
|
61
|
+
judgeval/tracer/processors/__init__.py,sha256=fjk3zGxQGp6adnj1-QdSaiRJk-VhyzuKG5vCalvbucI,8645
|
62
62
|
judgeval/trainer/__init__.py,sha256=h_DDVV7HFF7HUPAJFpt2d9wjqgnmEVcHxqZyB1k7pPQ,257
|
63
63
|
judgeval/trainer/config.py,sha256=8s0X8B334PJomorwONaUpb6K8cAMxRdYAeQdtx7HPHs,4258
|
64
64
|
judgeval/trainer/console.py,sha256=PJ0rCnDwC7aoW-VsLDS96ZyMyagh-l9EOJKff1ATIpo,4342
|
@@ -69,12 +69,12 @@ judgeval/utils/decorators.py,sha256=rdqY1w0zNL6O6GU6Wdeo0-x5EgpFTEhU2vkgiWsRYdc,
|
|
69
69
|
judgeval/utils/file_utils.py,sha256=3LI1YCZwO5ogTgJreyOgRgDksey3natO2Td1PQqaPyY,3252
|
70
70
|
judgeval/utils/guards.py,sha256=QBb6m6KElxdvt2bskLZCKh_zGHbBcqV-VfGzT63o3hY,807
|
71
71
|
judgeval/utils/meta.py,sha256=wQFCLJTNKF9yUdXcw37AT6mC-wqzZpAvjn5gP_6flD8,349
|
72
|
-
judgeval/utils/serialize.py,sha256=
|
72
|
+
judgeval/utils/serialize.py,sha256=QXR-8Nj5rqOrI9zLx0oRLdk6DW6Bc7j8eyF4zQ7PLxA,6256
|
73
73
|
judgeval/utils/testing.py,sha256=kJOq4LlEXaNThfg9oSIRqSK7IH8AwLgbukjn5uxMY7A,3661
|
74
74
|
judgeval/utils/url.py,sha256=Shf0v3XcbaWpL0m1eGJEEO_z4TsQCnDB2Rl25OTUmiI,195
|
75
75
|
judgeval/utils/version_check.py,sha256=kcF6SvB6GbVKI0Gv9QRVm-kvBn9_z-c3jmPORsXO3h0,1015
|
76
|
-
judgeval-0.9.
|
77
|
-
judgeval-0.9.
|
78
|
-
judgeval-0.9.
|
79
|
-
judgeval-0.9.
|
80
|
-
judgeval-0.9.
|
76
|
+
judgeval-0.9.4.dist-info/METADATA,sha256=Hr4y27-wt-658_DJd_D7oAUpDebQS5a9jfdQwGvfmbg,8869
|
77
|
+
judgeval-0.9.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
78
|
+
judgeval-0.9.4.dist-info/entry_points.txt,sha256=-eoeD-oDLn4A7MSgeBS9Akwanf3_0r0cgEleBcIOjg0,46
|
79
|
+
judgeval-0.9.4.dist-info/licenses/LICENSE.md,sha256=tKmCg7k5QOmxPK19XMfzim04QiQJPmgIm0pAn55IJwk,11352
|
80
|
+
judgeval-0.9.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|