lmnr 0.6.10__py3-none-any.whl → 0.6.11__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.
@@ -89,11 +89,11 @@ class AsyncLaminarClient:
89
89
  return self.__agent
90
90
 
91
91
  @property
92
- def _evals(self) -> AsyncEvals:
92
+ def evals(self) -> AsyncEvals:
93
93
  """Get the Evals resource.
94
94
 
95
95
  Returns:
96
- Evals: The Evals resource instance.
96
+ AsyncEvals: The Evals resource instance.
97
97
  """
98
98
  return self.__evals
99
99
 
@@ -144,3 +144,5 @@ class AsyncLaminarClient:
144
144
  "Content-Type": "application/json",
145
145
  "Accept": "application/json",
146
146
  }
147
+
148
+
@@ -1,5 +1,6 @@
1
1
  """Evals resource for interacting with Laminar evaluations API."""
2
2
 
3
+ from typing import Any
3
4
  import uuid
4
5
 
5
6
  from lmnr.sdk.client.asynchronous.resources.base import BaseAsyncResource
@@ -40,6 +41,64 @@ class AsyncEvals(BaseAsyncResource):
40
41
  resp_json = response.json()
41
42
  return InitEvaluationResponse.model_validate(resp_json)
42
43
 
44
+ async def create_evaluation(
45
+ self,
46
+ name: str | None = None,
47
+ group_name: str | None = None,
48
+ ) -> uuid.UUID:
49
+ """
50
+ Create a new evaluation and return its ID.
51
+
52
+ Parameters:
53
+ name (str | None, optional): Optional name of the evaluation.
54
+ group_name (str | None, optional): An identifier to group evaluations.
55
+
56
+ Returns:
57
+ uuid.UUID: The evaluation ID.
58
+ """
59
+ evaluation = await self.init(name=name, group_name=group_name)
60
+ return evaluation.id
61
+
62
+ async def create_datapoint(
63
+ self,
64
+ eval_id: uuid.UUID,
65
+ data: Any,
66
+ target: Any = None,
67
+ metadata: dict[str, Any] | None = None,
68
+ index: int | None = None,
69
+ trace_id: uuid.UUID | None = None,
70
+ ) -> uuid.UUID:
71
+ """
72
+ Create a datapoint for an evaluation.
73
+
74
+ Parameters:
75
+ eval_id (uuid.UUID): The evaluation ID.
76
+ data: The input data for the executor.
77
+ target: The target/expected output for evaluators.
78
+ metadata (dict[str, Any] | None, optional): Optional metadata.
79
+ index (int | None, optional): Optional index of the datapoint.
80
+ trace_id (uuid.UUID | None, optional): Optional trace ID.
81
+
82
+ Returns:
83
+ uuid.UUID: The datapoint ID.
84
+ """
85
+
86
+ datapoint_id = uuid.uuid4()
87
+
88
+ # Create a minimal datapoint first
89
+ partial_datapoint = PartialEvaluationDatapoint(
90
+ id=datapoint_id,
91
+ data=data,
92
+ target=target,
93
+ index=index or 0,
94
+ trace_id=trace_id or uuid.uuid4(),
95
+ executor_span_id=uuid.uuid4(), # Will be updated when executor runs
96
+ metadata=metadata,
97
+ )
98
+
99
+ await self.save_datapoints(eval_id, [partial_datapoint])
100
+ return datapoint_id
101
+
43
102
  async def save_datapoints(
44
103
  self,
45
104
  eval_id: uuid.UUID,
@@ -66,3 +125,34 @@ class AsyncEvals(BaseAsyncResource):
66
125
  )
67
126
  if response.status_code != 200:
68
127
  raise ValueError(f"Error saving evaluation datapoints: {response.text}")
128
+
129
+
130
+ async def update_datapoint(
131
+ self,
132
+ eval_id: uuid.UUID,
133
+ datapoint_id: uuid.UUID,
134
+ scores: dict[str, float | int],
135
+ executor_output: Any | None = None,
136
+ ) -> None:
137
+ """Update a datapoint with evaluation results.
138
+
139
+ Args:
140
+ eval_id (uuid.UUID): The evaluation ID.
141
+ datapoint_id (uuid.UUID): The datapoint ID.
142
+ executor_output (Any): The executor output.
143
+ scores (dict[str, float | int] | None, optional): The scores. Defaults to None.
144
+ """
145
+
146
+ response = await self._client.post(
147
+ self._base_url + f"/v1/evals/{eval_id}/datapoints/{datapoint_id}",
148
+ json={
149
+ "executorOutput": executor_output,
150
+ "scores": scores,
151
+ },
152
+ headers=self._headers(),
153
+ )
154
+
155
+ if response.status_code != 200:
156
+ raise ValueError(f"Error updating evaluation datapoint: {response.text}")
157
+
158
+
@@ -2,6 +2,7 @@
2
2
 
3
3
  import uuid
4
4
  import urllib.parse
5
+ from typing import Any
5
6
 
6
7
  from lmnr.sdk.client.synchronous.resources.base import BaseResource
7
8
  from lmnr.sdk.types import (
@@ -42,6 +43,64 @@ class Evals(BaseResource):
42
43
  resp_json = response.json()
43
44
  return InitEvaluationResponse.model_validate(resp_json)
44
45
 
46
+ def create_evaluation(
47
+ self,
48
+ name: str | None = None,
49
+ group_name: str | None = None,
50
+ ) -> uuid.UUID:
51
+ """
52
+ Create a new evaluation and return its ID.
53
+
54
+ Parameters:
55
+ name (str | None, optional): Optional name of the evaluation.
56
+ group_name (str | None, optional): An identifier to group evaluations.
57
+
58
+ Returns:
59
+ uuid.UUID: The evaluation ID.
60
+ """
61
+ evaluation = self.init(name=name, group_name=group_name)
62
+ return evaluation.id
63
+
64
+ def create_datapoint(
65
+ self,
66
+ eval_id: uuid.UUID,
67
+ data: Any,
68
+ target: Any = None,
69
+ metadata: dict[str, Any] | None = None,
70
+ index: int | None = None,
71
+ trace_id: uuid.UUID | None = None,
72
+ ) -> uuid.UUID:
73
+ """
74
+ Create a datapoint for an evaluation.
75
+
76
+ Parameters:
77
+ eval_id (uuid.UUID): The evaluation ID.
78
+ data: The input data for the executor.
79
+ target: The target/expected output for evaluators.
80
+ metadata (dict[str, Any] | None, optional): Optional metadata.
81
+ index (int | None, optional): Optional index of the datapoint.
82
+ trace_id (uuid.UUID | None, optional): Optional trace ID.
83
+
84
+ Returns:
85
+ uuid.UUID: The datapoint ID.
86
+ """
87
+
88
+ datapoint_id = uuid.uuid4()
89
+
90
+ # Create a minimal datapoint first
91
+ partial_datapoint = PartialEvaluationDatapoint(
92
+ id=datapoint_id,
93
+ data=data,
94
+ target=target,
95
+ index=index or 0,
96
+ trace_id=trace_id or uuid.uuid4(),
97
+ executor_span_id=uuid.uuid4(), # Will be updated when executor runs
98
+ metadata=metadata,
99
+ )
100
+
101
+ self.save_datapoints(eval_id, [partial_datapoint])
102
+ return datapoint_id
103
+
45
104
  def save_datapoints(
46
105
  self,
47
106
  eval_id: uuid.UUID,
@@ -69,6 +128,34 @@ class Evals(BaseResource):
69
128
  if response.status_code != 200:
70
129
  raise ValueError(f"Error saving evaluation datapoints: {response.text}")
71
130
 
131
+ def update_datapoint(
132
+ self,
133
+ eval_id: uuid.UUID,
134
+ datapoint_id: uuid.UUID,
135
+ scores: dict[str, float | int],
136
+ executor_output: Any | None = None,
137
+ ) -> None:
138
+ """Update a datapoint with evaluation results.
139
+
140
+ Args:
141
+ eval_id (uuid.UUID): The evaluation ID.
142
+ datapoint_id (uuid.UUID): The datapoint ID.
143
+ executor_output (Any): The executor output.
144
+ scores (dict[str, float | int] | None, optional): The scores. Defaults to None.
145
+ """
146
+
147
+ response = self._client.post(
148
+ self._base_url + f"/v1/evals/{eval_id}/datapoints/{datapoint_id}",
149
+ json={
150
+ "executorOutput": executor_output,
151
+ "scores": scores,
152
+ },
153
+ headers=self._headers(),
154
+ )
155
+
156
+ if response.status_code != 200:
157
+ raise ValueError(f"Error updating evaluation datapoint: {response.text}")
158
+
72
159
  def get_datapoints(
73
160
  self,
74
161
  dataset_name: str,
@@ -89,7 +89,7 @@ class LaminarClient:
89
89
  return self.__agent
90
90
 
91
91
  @property
92
- def _evals(self) -> Evals:
92
+ def evals(self) -> Evals:
93
93
  """Get the Evals resource.
94
94
 
95
95
  Returns:
@@ -155,3 +155,5 @@ class LaminarClient:
155
155
  "Content-Type": "application/json",
156
156
  "Accept": "application/json",
157
157
  }
158
+
159
+
lmnr/sdk/datasets.py CHANGED
@@ -38,7 +38,7 @@ class LaminarDataset(EvaluationDataset):
38
38
  f"dataset {self.name}. Fetching batch from {self._offset} to "
39
39
  + f"{self._offset + self._fetch_size}"
40
40
  )
41
- resp = self.client._evals.get_datapoints(
41
+ resp = self.client.evals.get_datapoints(
42
42
  self.name, self._offset, self._fetch_size
43
43
  )
44
44
  self._fetched_items += resp.items
lmnr/sdk/evaluations.py CHANGED
@@ -241,7 +241,7 @@ class Evaluation:
241
241
  )
242
242
  self.reporter.start(len(self.data))
243
243
  try:
244
- evaluation = await self.client._evals.init(
244
+ evaluation = await self.client.evals.init(
245
245
  name=self.name, group_name=self.group_name
246
246
  )
247
247
  result_datapoints = await self._evaluate_in_batches(evaluation.id)
@@ -326,7 +326,7 @@ class Evaluation:
326
326
  metadata=datapoint.metadata,
327
327
  )
328
328
  # First, create datapoint with trace_id so that we can show the dp in the UI
329
- await self.client._evals.save_datapoints(
329
+ await self.client.evals.save_datapoints(
330
330
  eval_id, [partial_datapoint], self.group_name
331
331
  )
332
332
  executor_span.set_attribute(SPAN_TYPE, SpanType.EXECUTOR.value)
@@ -384,7 +384,7 @@ class Evaluation:
384
384
 
385
385
  # Create background upload task without awaiting it
386
386
  upload_task = asyncio.create_task(
387
- self.client._evals.save_datapoints(eval_id, [datapoint], self.group_name)
387
+ self.client.evals.save_datapoints(eval_id, [datapoint], self.group_name)
388
388
  )
389
389
  self.upload_tasks.append(upload_task)
390
390
 
lmnr/version.py CHANGED
@@ -3,7 +3,7 @@ import httpx
3
3
  from packaging import version
4
4
 
5
5
 
6
- __version__ = "0.6.10"
6
+ __version__ = "0.6.11"
7
7
  PYTHON_VERSION = f"{sys.version_info.major}.{sys.version_info.minor}"
8
8
 
9
9
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lmnr
3
- Version: 0.6.10
3
+ Version: 0.6.11
4
4
  Summary: Python SDK for Laminar
5
5
  License: Apache-2.0
6
6
  Author: lmnr.ai
@@ -28,31 +28,31 @@ lmnr/sdk/browser/playwright_otel.py,sha256=LFg1iJXbez-BEgEIY9eaO_2T2uR6SxyfFL46f
28
28
  lmnr/sdk/browser/pw_utils.py,sha256=nFqVujQb7owVFzT-31_g09CbfbBwUIXKxs3JxuE47ws,10835
29
29
  lmnr/sdk/browser/rrweb/rrweb.umd.min.cjs,sha256=Ly2jiwC7hTEtgiXzBpoJNSE1Vkzu0lZPZS8brjusAW0,260896
30
30
  lmnr/sdk/browser/utils.py,sha256=SmaHdtKTgQjSX7zs1hyOFxCk2j5WIw1f78pZZN0J48E,2371
31
- lmnr/sdk/client/asynchronous/async_client.py,sha256=5Hb1Z4tPdUATHgmQ8R6laCqWCxvm5MbxyU4jMmRPnO8,4579
31
+ lmnr/sdk/client/asynchronous/async_client.py,sha256=2mIezUAzUrqk5tCZlzfkID4NzIy_JuyBQtDCAT-2Mro,4585
32
32
  lmnr/sdk/client/asynchronous/resources/__init__.py,sha256=9fkjlVJS8zhnCTITjhow173phBdZlyiae-X0LcTSWqM,381
33
33
  lmnr/sdk/client/asynchronous/resources/agent.py,sha256=Ong3K2KRLN7agx1_-aZxMGcT_OGF3_ZGtFLm8aPMbYw,17788
34
34
  lmnr/sdk/client/asynchronous/resources/base.py,sha256=aJ43Q1rltg23IQaI4eeaZKckxVTgDUbCJrChhQCUEoE,986
35
35
  lmnr/sdk/client/asynchronous/resources/browser_events.py,sha256=T-DUbbAfMQ2VqiVfgVplxuTaJZuoNcC1O6RCxdfw7UQ,1163
36
- lmnr/sdk/client/asynchronous/resources/evals.py,sha256=8a-G5ocsoBur6JRLombK9Avu1l8ILEw6ysOK3PonmxQ,2480
36
+ lmnr/sdk/client/asynchronous/resources/evals.py,sha256=dYFuHmXW_FFNsmKC7_NuhxowzCJVUrRmrxeAJ_7EzOA,5420
37
37
  lmnr/sdk/client/asynchronous/resources/tags.py,sha256=VbsBMp120d_8drGFr1Obp4xSRktzPC-3kOYcblZnvKA,2565
38
38
  lmnr/sdk/client/synchronous/resources/__init__.py,sha256=hDGyNARdG3J25lLAP8JnlER7r8JL-JQuPN1xdheiCw4,318
39
39
  lmnr/sdk/client/synchronous/resources/agent.py,sha256=mnTu6toN2LbgmEhQ-mdZ0CzNAnkrGiksrys0AyMwz2A,17809
40
40
  lmnr/sdk/client/synchronous/resources/base.py,sha256=ne1ZZ10UmNkMrECVvClcEJfcFJlSGvaXOC8K6mZTPdY,971
41
41
  lmnr/sdk/client/synchronous/resources/browser_events.py,sha256=9rFYWZesXQomnFgbZ590tGFMTaNj0OAzT9RcFwD8q_Y,1135
42
- lmnr/sdk/client/synchronous/resources/evals.py,sha256=N-hraO6Y2o5RojmMG4Wu1ii0gflLC9SEJSrN6hqA_jg,3789
42
+ lmnr/sdk/client/synchronous/resources/evals.py,sha256=odN9ZfZnUXKzFZJ6AQDrIjEljqnj8aQKP1ivY188WGo,6667
43
43
  lmnr/sdk/client/synchronous/resources/tags.py,sha256=cNMEzMDhlBNpI7J4x6xkFAANiNSq-Vuu_zi5NPk2kcA,2485
44
- lmnr/sdk/client/synchronous/sync_client.py,sha256=kPS14M0e99xMtLQ_yEOJrFpQWhstqARytkGIbfCoNVc,4906
45
- lmnr/sdk/datasets.py,sha256=jl5Wj5nEI9pww4Jwn4XKF8h0gXBU4TOIrhqNjTJsHZQ,1709
44
+ lmnr/sdk/client/synchronous/sync_client.py,sha256=IIzj-mAwHHoRuUX9KkJtrzTGi5UOygbA8wiA9Aqzf2E,4907
45
+ lmnr/sdk/datasets.py,sha256=P9hRxfl7-I6qhLFFGgU-r_I7RJfLtF6sL56g5fKIbAA,1708
46
46
  lmnr/sdk/decorators.py,sha256=1uu9xxBYgblFqlhQqH17cZYq7babAmB1lEtvBgTsP0E,4468
47
47
  lmnr/sdk/eval_control.py,sha256=KROUrDhcZTrptRZ-hxvr60_o_Gt_8u045jb4cBXcuoY,184
48
- lmnr/sdk/evaluations.py,sha256=mlyx0SS4QwCMBbE0nAxl_aOkWOk1D6xCF46vATYfxJQ,21025
48
+ lmnr/sdk/evaluations.py,sha256=i5c9wi9ZWV-L7vYbHEnLQC2V34n3tasPRowJAnSr-qQ,21022
49
49
  lmnr/sdk/laminar.py,sha256=oOVco_c9ZstT71HsquGsgbtFumXd2Ejz0rl_qpmMlTU,33996
50
50
  lmnr/sdk/log.py,sha256=nt_YMmPw1IRbGy0b7q4rTtP4Yo3pQfNxqJPXK3nDSNQ,2213
51
51
  lmnr/sdk/types.py,sha256=5tEX7yoemb9wYyXLy4aqdazudO5I8dglU5A-IegDhsQ,12653
52
52
  lmnr/sdk/utils.py,sha256=yrcHIhoADf9lWH9qJWZMmkRWYvd0DuxPSLP3mY6YFw0,4327
53
- lmnr/version.py,sha256=y4oHI20srMQ6p0il96_i2HLYlkUNf34uNTz8cKyQTOQ,1322
54
- lmnr-0.6.10.dist-info/LICENSE,sha256=67b_wJHVV1CBaWkrKFWU1wyqTPSdzH77Ls-59631COg,10411
55
- lmnr-0.6.10.dist-info/METADATA,sha256=WnN-N_tgmUHi4zfo6UTrf529hE8qK4_50ci8z9CzN18,15132
56
- lmnr-0.6.10.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
57
- lmnr-0.6.10.dist-info/entry_points.txt,sha256=K1jE20ww4jzHNZLnsfWBvU3YKDGBgbOiYG5Y7ivQcq4,37
58
- lmnr-0.6.10.dist-info/RECORD,,
53
+ lmnr/version.py,sha256=qnwKwsPBqcM4aZx6FBz8GRvhfVyvAhaXzQqQSfXM-k0,1322
54
+ lmnr-0.6.11.dist-info/LICENSE,sha256=67b_wJHVV1CBaWkrKFWU1wyqTPSdzH77Ls-59631COg,10411
55
+ lmnr-0.6.11.dist-info/METADATA,sha256=DpYsYjFiUQII2I71j7YJv6F10rgBqGsHCfG_lLQQfhQ,15132
56
+ lmnr-0.6.11.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
57
+ lmnr-0.6.11.dist-info/entry_points.txt,sha256=K1jE20ww4jzHNZLnsfWBvU3YKDGBgbOiYG5Y7ivQcq4,37
58
+ lmnr-0.6.11.dist-info/RECORD,,
File without changes
File without changes