lmnr 0.6.19__tar.gz → 0.6.20__tar.gz
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.
- {lmnr-0.6.19 → lmnr-0.6.20}/PKG-INFO +1 -1
- {lmnr-0.6.19 → lmnr-0.6.20}/pyproject.toml +1 -1
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/asynchronous/async_client.py +13 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/asynchronous/resources/__init__.py +2 -0
- lmnr-0.6.20/src/lmnr/sdk/client/asynchronous/resources/evaluators.py +85 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/asynchronous/resources/tags.py +4 -10
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/synchronous/resources/__init__.py +2 -1
- lmnr-0.6.20/src/lmnr/sdk/client/synchronous/resources/evaluators.py +85 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/synchronous/resources/tags.py +4 -10
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/synchronous/sync_client.py +14 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/utils.py +23 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/version.py +1 -1
- {lmnr-0.6.19 → lmnr-0.6.20}/README.md +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/cli.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/.flake8 +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/decorators/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/litellm/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/litellm/utils.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/config.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/schema_utils.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/utils.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/langgraph/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/langgraph/utils.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/chat_wrappers.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/completion_wrappers.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/config.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/event_emitter.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/event_models.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/image_gen_wrappers.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/utils.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v0/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/responses_wrappers.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/version.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/opentelemetry/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/skyvern/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/tracing/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/tracing/_instrument_initializers.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/tracing/attributes.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/tracing/context_properties.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/tracing/exporter.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/tracing/instruments.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/tracing/processor.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/tracing/tracer.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/utils/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/utils/json_encoder.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/utils/package_check.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/py.typed +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/browser/__init__.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/browser/browser_use_otel.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/browser/patchright_otel.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/browser/playwright_otel.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/browser/pw_utils.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/browser/rrweb/rrweb.umd.min.cjs +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/browser/utils.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/asynchronous/resources/agent.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/asynchronous/resources/base.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/asynchronous/resources/browser_events.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/asynchronous/resources/evals.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/synchronous/resources/agent.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/synchronous/resources/base.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/synchronous/resources/browser_events.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/client/synchronous/resources/evals.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/datasets.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/decorators.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/eval_control.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/evaluations.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/laminar.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/log.py +0 -0
- {lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/sdk/types.py +0 -0
@@ -12,6 +12,7 @@ from lmnr.sdk.client.asynchronous.resources import (
|
|
12
12
|
AsyncBrowserEvents,
|
13
13
|
AsyncEvals,
|
14
14
|
AsyncTags,
|
15
|
+
AsyncEvaluators
|
15
16
|
)
|
16
17
|
from lmnr.sdk.utils import from_env
|
17
18
|
|
@@ -74,6 +75,9 @@ class AsyncLaminarClient:
|
|
74
75
|
self.__evals = AsyncEvals(
|
75
76
|
self.__client, self.__base_url, self.__project_api_key
|
76
77
|
)
|
78
|
+
self.__evaluators = AsyncEvaluators(
|
79
|
+
self.__client, self.__base_url, self.__project_api_key
|
80
|
+
)
|
77
81
|
self.__browser_events = AsyncBrowserEvents(
|
78
82
|
self.__client, self.__base_url, self.__project_api_key
|
79
83
|
)
|
@@ -115,6 +119,15 @@ class AsyncLaminarClient:
|
|
115
119
|
"""
|
116
120
|
return self.__tags
|
117
121
|
|
122
|
+
@property
|
123
|
+
def evaluators(self) -> AsyncEvaluators:
|
124
|
+
"""Get the Evaluators resource.
|
125
|
+
|
126
|
+
Returns:
|
127
|
+
Evaluators: The Evaluators resource instance.
|
128
|
+
"""
|
129
|
+
return self.__evaluators
|
130
|
+
|
118
131
|
def is_closed(self) -> bool:
|
119
132
|
return self.__client.is_closed
|
120
133
|
|
@@ -2,10 +2,12 @@ from lmnr.sdk.client.asynchronous.resources.agent import AsyncAgent
|
|
2
2
|
from lmnr.sdk.client.asynchronous.resources.browser_events import AsyncBrowserEvents
|
3
3
|
from lmnr.sdk.client.asynchronous.resources.evals import AsyncEvals
|
4
4
|
from lmnr.sdk.client.asynchronous.resources.tags import AsyncTags
|
5
|
+
from lmnr.sdk.client.asynchronous.resources.evaluators import AsyncEvaluators
|
5
6
|
|
6
7
|
__all__ = [
|
7
8
|
"AsyncAgent",
|
8
9
|
"AsyncEvals",
|
9
10
|
"AsyncBrowserEvents",
|
10
11
|
"AsyncTags",
|
12
|
+
"AsyncEvaluators"
|
11
13
|
]
|
@@ -0,0 +1,85 @@
|
|
1
|
+
"""Evaluators resource for creating evaluator scores."""
|
2
|
+
|
3
|
+
import uuid
|
4
|
+
from typing import Any
|
5
|
+
|
6
|
+
from lmnr.sdk.client.asynchronous.resources.base import BaseAsyncResource
|
7
|
+
from lmnr.sdk.utils import format_id
|
8
|
+
|
9
|
+
|
10
|
+
class AsyncEvaluators(BaseAsyncResource):
|
11
|
+
"""Resource for creating evaluator scores."""
|
12
|
+
|
13
|
+
async def score(
|
14
|
+
self,
|
15
|
+
*,
|
16
|
+
name: str,
|
17
|
+
trace_id: str | int | uuid.UUID | None = None,
|
18
|
+
span_id: str | int | uuid.UUID | None = None,
|
19
|
+
metadata: dict[str, Any] | None = None,
|
20
|
+
score: float,
|
21
|
+
) -> None:
|
22
|
+
"""Create a score for a span.
|
23
|
+
|
24
|
+
Args:
|
25
|
+
name (str): Name of the score
|
26
|
+
trace_id (str | int | uuid.UUID | None, optional): The trace ID to score (will be attached to root span)
|
27
|
+
span_id (str | int | uuid.UUID | None, optional): The span ID to score
|
28
|
+
metadata (dict[str, Any] | None, optional): Additional metadata. Defaults to None.
|
29
|
+
score (float): The score value (float)
|
30
|
+
|
31
|
+
Raises:
|
32
|
+
ValueError: If there's an error creating the score.
|
33
|
+
|
34
|
+
Example:
|
35
|
+
Score by trace ID (will attach to root span):
|
36
|
+
|
37
|
+
>>> await laminar_client.evaluators.score(
|
38
|
+
... name="quality",
|
39
|
+
... trace_id="trace-id-here",
|
40
|
+
... score=0.95,
|
41
|
+
... metadata={"model": "gpt-4"}
|
42
|
+
... )
|
43
|
+
|
44
|
+
Score by span ID:
|
45
|
+
|
46
|
+
>>> await laminar_client.evaluators.score(
|
47
|
+
... name="relevance",
|
48
|
+
... span_id="span-id-here",
|
49
|
+
... score=0.87
|
50
|
+
... )
|
51
|
+
"""
|
52
|
+
if trace_id is not None and span_id is not None:
|
53
|
+
raise ValueError("Cannot provide both trace_id and span_id. Please provide only one.")
|
54
|
+
if trace_id is None and span_id is None:
|
55
|
+
raise ValueError("Either 'trace_id' or 'span_id' must be provided.")
|
56
|
+
|
57
|
+
if trace_id is not None:
|
58
|
+
formatted_trace_id = format_id(trace_id)
|
59
|
+
payload = {
|
60
|
+
"name": name,
|
61
|
+
"traceId": formatted_trace_id,
|
62
|
+
"metadata": metadata,
|
63
|
+
"score": score,
|
64
|
+
"source": "Code",
|
65
|
+
}
|
66
|
+
else:
|
67
|
+
formatted_span_id = format_id(span_id)
|
68
|
+
payload = {
|
69
|
+
"name": name,
|
70
|
+
"spanId": formatted_span_id,
|
71
|
+
"metadata": metadata,
|
72
|
+
"score": score,
|
73
|
+
"source": "Code",
|
74
|
+
}
|
75
|
+
|
76
|
+
response = await self._client.post(
|
77
|
+
self._base_url + "/v1/evaluators/score",
|
78
|
+
json=payload,
|
79
|
+
headers=self._headers(),
|
80
|
+
)
|
81
|
+
|
82
|
+
if response.status_code != 200:
|
83
|
+
if response.status_code == 401:
|
84
|
+
raise ValueError("Unauthorized. Please check your project API key.")
|
85
|
+
raise ValueError(f"Error creating evaluator score: {response.text}")
|
@@ -5,6 +5,7 @@ import uuid
|
|
5
5
|
|
6
6
|
from lmnr.sdk.client.asynchronous.resources.base import BaseAsyncResource
|
7
7
|
from lmnr.sdk.log import get_default_logger
|
8
|
+
from lmnr.sdk.utils import format_id
|
8
9
|
|
9
10
|
logger = get_default_logger(__name__)
|
10
11
|
|
@@ -54,18 +55,11 @@ class AsyncTags(BaseAsyncResource):
|
|
54
55
|
```
|
55
56
|
"""
|
56
57
|
trace_tags = tags if isinstance(tags, list) else [tags]
|
57
|
-
|
58
|
-
trace_id = str(trace_id)
|
59
|
-
elif isinstance(trace_id, int):
|
60
|
-
trace_id = str(uuid.UUID(int=trace_id))
|
61
|
-
elif isinstance(trace_id, str):
|
62
|
-
uuid.UUID(trace_id) # Will raise ValueError if invalid
|
63
|
-
else:
|
64
|
-
raise ValueError(f"Invalid trace id: {trace_id}")
|
58
|
+
formatted_trace_id = format_id(trace_id)
|
65
59
|
|
66
60
|
url = self._base_url + "/v1/tag"
|
67
61
|
payload = {
|
68
|
-
"traceId":
|
62
|
+
"traceId": formatted_trace_id,
|
69
63
|
"names": trace_tags,
|
70
64
|
}
|
71
65
|
response = await self._client.post(
|
@@ -78,7 +72,7 @@ class AsyncTags(BaseAsyncResource):
|
|
78
72
|
|
79
73
|
if response.status_code == 404:
|
80
74
|
logger.warning(
|
81
|
-
f"Trace {
|
75
|
+
f"Trace {formatted_trace_id} not found. The trace may have not been ended yet."
|
82
76
|
)
|
83
77
|
return []
|
84
78
|
|
@@ -2,5 +2,6 @@ from lmnr.sdk.client.synchronous.resources.agent import Agent
|
|
2
2
|
from lmnr.sdk.client.synchronous.resources.browser_events import BrowserEvents
|
3
3
|
from lmnr.sdk.client.synchronous.resources.evals import Evals
|
4
4
|
from lmnr.sdk.client.synchronous.resources.tags import Tags
|
5
|
+
from lmnr.sdk.client.synchronous.resources.evaluators import Evaluators
|
5
6
|
|
6
|
-
__all__ = ["Agent", "Evals", "BrowserEvents", "Tags"]
|
7
|
+
__all__ = ["Agent", "Evals", "Evaluators", "BrowserEvents", "Tags"]
|
@@ -0,0 +1,85 @@
|
|
1
|
+
"""Evaluators resource for creating evaluator scores."""
|
2
|
+
|
3
|
+
import uuid
|
4
|
+
from typing import Any
|
5
|
+
|
6
|
+
from lmnr.sdk.client.synchronous.resources.base import BaseResource
|
7
|
+
from lmnr.sdk.utils import format_id
|
8
|
+
|
9
|
+
|
10
|
+
class Evaluators(BaseResource):
|
11
|
+
"""Resource for creating evaluator scores."""
|
12
|
+
|
13
|
+
def score(
|
14
|
+
self,
|
15
|
+
*,
|
16
|
+
name: str,
|
17
|
+
trace_id: str | int | uuid.UUID | None = None,
|
18
|
+
span_id: str | int | uuid.UUID | None = None,
|
19
|
+
metadata: dict[str, Any] | None = None,
|
20
|
+
score: float,
|
21
|
+
) -> None:
|
22
|
+
"""Create a score for a span.
|
23
|
+
|
24
|
+
Args:
|
25
|
+
name (str): Name of the score
|
26
|
+
trace_id (str | int | uuid.UUID | None, optional): The trace ID to score (will be attached to root span)
|
27
|
+
span_id (str | int | uuid.UUID | None, optional): The span ID to score
|
28
|
+
metadata (dict[str, Any] | None, optional): Additional metadata. Defaults to None.
|
29
|
+
score (float): The score value (float)
|
30
|
+
|
31
|
+
Raises:
|
32
|
+
ValueError: If there's an error creating the score.
|
33
|
+
|
34
|
+
Example:
|
35
|
+
Score by trace ID (will attach to root span):
|
36
|
+
|
37
|
+
>>> laminar_client.evaluators.score(
|
38
|
+
... name="quality",
|
39
|
+
... trace_id="trace-id-here",
|
40
|
+
... score=0.95,
|
41
|
+
... metadata={"model": "gpt-4"}
|
42
|
+
... )
|
43
|
+
|
44
|
+
Score by span ID:
|
45
|
+
|
46
|
+
>>> laminar_client.evaluators.score(
|
47
|
+
... name="relevance",
|
48
|
+
... span_id="span-id-here",
|
49
|
+
... score=0.87
|
50
|
+
... )
|
51
|
+
"""
|
52
|
+
if trace_id is not None and span_id is not None:
|
53
|
+
raise ValueError("Cannot provide both trace_id and span_id. Please provide only one.")
|
54
|
+
if trace_id is None and span_id is None:
|
55
|
+
raise ValueError("Either 'trace_id' or 'span_id' must be provided.")
|
56
|
+
|
57
|
+
if trace_id is not None:
|
58
|
+
formatted_trace_id = format_id(trace_id)
|
59
|
+
payload = {
|
60
|
+
"name": name,
|
61
|
+
"traceId": formatted_trace_id,
|
62
|
+
"metadata": metadata,
|
63
|
+
"score": score,
|
64
|
+
"source": "Code",
|
65
|
+
}
|
66
|
+
else:
|
67
|
+
formatted_span_id = format_id(span_id)
|
68
|
+
payload = {
|
69
|
+
"name": name,
|
70
|
+
"spanId": formatted_span_id,
|
71
|
+
"metadata": metadata,
|
72
|
+
"score": score,
|
73
|
+
"source": "Code",
|
74
|
+
}
|
75
|
+
|
76
|
+
response = self._client.post(
|
77
|
+
self._base_url + "/v1/evaluators/score",
|
78
|
+
json=payload,
|
79
|
+
headers=self._headers(),
|
80
|
+
)
|
81
|
+
|
82
|
+
if response.status_code != 200:
|
83
|
+
if response.status_code == 401:
|
84
|
+
raise ValueError("Unauthorized. Please check your project API key.")
|
85
|
+
raise ValueError(f"Error creating evaluator score: {response.text}")
|
@@ -5,6 +5,7 @@ import uuid
|
|
5
5
|
|
6
6
|
from lmnr.sdk.client.synchronous.resources.base import BaseResource
|
7
7
|
from lmnr.sdk.log import get_default_logger
|
8
|
+
from lmnr.sdk.utils import format_id
|
8
9
|
|
9
10
|
logger = get_default_logger(__name__)
|
10
11
|
|
@@ -54,18 +55,11 @@ class Tags(BaseResource):
|
|
54
55
|
```
|
55
56
|
"""
|
56
57
|
trace_tags = tags if isinstance(tags, list) else [tags]
|
57
|
-
|
58
|
-
trace_id = str(trace_id)
|
59
|
-
elif isinstance(trace_id, int):
|
60
|
-
trace_id = str(uuid.UUID(int=trace_id))
|
61
|
-
elif isinstance(trace_id, str):
|
62
|
-
uuid.UUID(trace_id)
|
63
|
-
else:
|
64
|
-
raise ValueError(f"Invalid trace id: {trace_id}")
|
58
|
+
formatted_trace_id = format_id(trace_id)
|
65
59
|
|
66
60
|
url = self._base_url + "/v1/tag"
|
67
61
|
payload = {
|
68
|
-
"traceId":
|
62
|
+
"traceId": formatted_trace_id,
|
69
63
|
"names": trace_tags,
|
70
64
|
}
|
71
65
|
response = self._client.post(
|
@@ -78,7 +72,7 @@ class Tags(BaseResource):
|
|
78
72
|
|
79
73
|
if response.status_code == 404:
|
80
74
|
logger.warning(
|
81
|
-
f"Trace {
|
75
|
+
f"Trace {formatted_trace_id} not found. The trace may have not been ended yet."
|
82
76
|
)
|
83
77
|
return []
|
84
78
|
|
@@ -11,6 +11,7 @@ from lmnr.sdk.client.synchronous.resources import (
|
|
11
11
|
Agent,
|
12
12
|
BrowserEvents,
|
13
13
|
Evals,
|
14
|
+
Evaluators,
|
14
15
|
Tags,
|
15
16
|
)
|
16
17
|
from lmnr.sdk.utils import from_env
|
@@ -27,6 +28,7 @@ class LaminarClient:
|
|
27
28
|
__agent: Agent | None = None
|
28
29
|
__evals: Evals | None = None
|
29
30
|
__tags: Tags | None = None
|
31
|
+
__evaluators: Evaluators | None = None
|
30
32
|
|
31
33
|
def __init__(
|
32
34
|
self,
|
@@ -74,6 +76,9 @@ class LaminarClient:
|
|
74
76
|
# Initialize resource objects
|
75
77
|
self.__agent = Agent(self.__client, self.__base_url, self.__project_api_key)
|
76
78
|
self.__evals = Evals(self.__client, self.__base_url, self.__project_api_key)
|
79
|
+
self.__evaluators = Evaluators(
|
80
|
+
self.__client, self.__base_url, self.__project_api_key
|
81
|
+
)
|
77
82
|
self.__browser_events = BrowserEvents(
|
78
83
|
self.__client, self.__base_url, self.__project_api_key
|
79
84
|
)
|
@@ -115,6 +120,15 @@ class LaminarClient:
|
|
115
120
|
"""
|
116
121
|
return self.__tags
|
117
122
|
|
123
|
+
@property
|
124
|
+
def evaluators(self) -> Evaluators:
|
125
|
+
"""Get the Evaluators resource.
|
126
|
+
|
127
|
+
Returns:
|
128
|
+
Evaluators: The Evaluators resource instance.
|
129
|
+
"""
|
130
|
+
return self.__evaluators
|
131
|
+
|
118
132
|
def shutdown(self):
|
119
133
|
"""Shutdown the client by closing underlying connections."""
|
120
134
|
self.__client.close()
|
@@ -128,3 +128,26 @@ def is_otel_attribute_value_type(value: typing.Any) -> bool:
|
|
128
128
|
)
|
129
129
|
return True
|
130
130
|
return False
|
131
|
+
|
132
|
+
|
133
|
+
def format_id(id_value: str | int | uuid.UUID) -> str:
|
134
|
+
"""Format trace/span/evaluation ID to a UUID string, or return valid UUID strings as-is.
|
135
|
+
|
136
|
+
Args:
|
137
|
+
id_value: The ID in various formats (UUID, int, or valid UUID string)
|
138
|
+
|
139
|
+
Returns:
|
140
|
+
str: UUID string representation
|
141
|
+
|
142
|
+
Raises:
|
143
|
+
ValueError: If id_value cannot be converted to a valid UUID
|
144
|
+
"""
|
145
|
+
if isinstance(id_value, uuid.UUID):
|
146
|
+
return str(id_value)
|
147
|
+
elif isinstance(id_value, int):
|
148
|
+
return str(uuid.UUID(int=id_value))
|
149
|
+
elif isinstance(id_value, str):
|
150
|
+
uuid.UUID(id_value)
|
151
|
+
return id_value
|
152
|
+
else:
|
153
|
+
raise ValueError(f"Invalid ID type: {type(id_value)}")
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{lmnr-0.6.19 → lmnr-0.6.20}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/utils.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|