lmnr 0.6.3__py3-none-any.whl → 0.6.5__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.
Files changed (35) hide show
  1. lmnr/cli.py +1 -2
  2. lmnr/opentelemetry_lib/__init__.py +6 -7
  3. lmnr/opentelemetry_lib/decorators/__init__.py +9 -9
  4. lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/__init__.py +2 -2
  5. lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/config.py +4 -4
  6. lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/utils.py +19 -19
  7. lmnr/opentelemetry_lib/tracing/__init__.py +6 -7
  8. lmnr/opentelemetry_lib/tracing/_instrument_initializers.py +34 -35
  9. lmnr/opentelemetry_lib/tracing/context_properties.py +2 -3
  10. lmnr/opentelemetry_lib/tracing/exporter.py +4 -5
  11. lmnr/opentelemetry_lib/tracing/instruments.py +5 -6
  12. lmnr/opentelemetry_lib/tracing/processor.py +6 -7
  13. lmnr/sdk/browser/utils.py +4 -3
  14. lmnr/sdk/client/asynchronous/async_client.py +26 -11
  15. lmnr/sdk/client/asynchronous/resources/__init__.py +2 -0
  16. lmnr/sdk/client/asynchronous/resources/agent.py +89 -91
  17. lmnr/sdk/client/asynchronous/resources/evals.py +7 -8
  18. lmnr/sdk/client/asynchronous/resources/tags.py +89 -0
  19. lmnr/sdk/client/synchronous/resources/__init__.py +2 -1
  20. lmnr/sdk/client/synchronous/resources/agent.py +91 -91
  21. lmnr/sdk/client/synchronous/resources/evals.py +7 -8
  22. lmnr/sdk/client/synchronous/resources/tags.py +89 -0
  23. lmnr/sdk/client/synchronous/sync_client.py +28 -13
  24. lmnr/sdk/decorators.py +27 -29
  25. lmnr/sdk/evaluations.py +49 -46
  26. lmnr/sdk/laminar.py +67 -59
  27. lmnr/sdk/types.py +45 -39
  28. lmnr/sdk/utils.py +3 -3
  29. lmnr/version.py +1 -1
  30. {lmnr-0.6.3.dist-info → lmnr-0.6.5.dist-info}/METADATA +1 -1
  31. lmnr-0.6.5.dist-info/RECORD +56 -0
  32. lmnr-0.6.3.dist-info/RECORD +0 -54
  33. {lmnr-0.6.3.dist-info → lmnr-0.6.5.dist-info}/LICENSE +0 -0
  34. {lmnr-0.6.3.dist-info → lmnr-0.6.5.dist-info}/WHEEL +0 -0
  35. {lmnr-0.6.3.dist-info → lmnr-0.6.5.dist-info}/entry_points.txt +0 -0
lmnr/sdk/evaluations.py CHANGED
@@ -3,7 +3,7 @@ import re
3
3
  import uuid
4
4
 
5
5
  from tqdm import tqdm
6
- from typing import Any, Awaitable, Optional, Set, Union
6
+ from typing import Any, Awaitable
7
7
 
8
8
  from lmnr.opentelemetry_lib.tracing.instruments import Instruments
9
9
  from lmnr.opentelemetry_lib.tracing.attributes import SPAN_TYPE
@@ -33,7 +33,7 @@ MAX_EXPORT_BATCH_SIZE = 64
33
33
 
34
34
 
35
35
  def get_evaluation_url(
36
- project_id: str, evaluation_id: str, base_url: Optional[str] = None
36
+ project_id: str, evaluation_id: str, base_url: str | None = None
37
37
  ):
38
38
  if not base_url or base_url == "https://api.lmnr.ai":
39
39
  base_url = "https://www.lmnr.ai"
@@ -95,32 +95,34 @@ class EvaluationReporter:
95
95
  class Evaluation:
96
96
  def __init__(
97
97
  self,
98
- data: Union[EvaluationDataset, list[Union[Datapoint, dict]]],
98
+ data: EvaluationDataset | list[Datapoint | dict],
99
99
  executor: Any,
100
100
  evaluators: dict[str, EvaluatorFunction],
101
101
  human_evaluators: list[HumanEvaluator] = [],
102
- name: Optional[str] = None,
103
- group_name: Optional[str] = None,
102
+ name: str | None = None,
103
+ group_name: str | None = None,
104
104
  concurrency_limit: int = DEFAULT_BATCH_SIZE,
105
- project_api_key: Optional[str] = None,
106
- base_url: Optional[str] = None,
107
- http_port: Optional[int] = None,
108
- grpc_port: Optional[int] = None,
109
- instruments: Optional[Set[Instruments]] = None,
110
- max_export_batch_size: Optional[int] = MAX_EXPORT_BATCH_SIZE,
111
- trace_export_timeout_seconds: Optional[int] = None,
105
+ project_api_key: str | None = None,
106
+ base_url: str | None = None,
107
+ http_port: int | None = None,
108
+ grpc_port: int | None = None,
109
+ instruments: set[Instruments] | None = None,
110
+ max_export_batch_size: int | None = MAX_EXPORT_BATCH_SIZE,
111
+ trace_export_timeout_seconds: int | None = None,
112
112
  ):
113
113
  """
114
114
  Initializes an instance of the Evaluation class.
115
115
 
116
116
  Parameters:
117
- data (Union[List[EvaluationDatapoint|dict], EvaluationDataset]):\
117
+ data (list[Datapoint|dict] | EvaluationDataset):\
118
118
  List of data points to evaluate or an evaluation dataset.
119
- `data` is the input to the executor function,
120
- `target` is the input to the evaluator function.
119
+ `data` is the input to the executor function.
120
+ `target` is the input to the evaluator function.
121
+ `metadata` is optional metadata to associate with the\
122
+ datapoint.
121
123
  executor (Callable[..., Any]): The executor function.\
122
- Takes the data point + any additional arguments\
123
- and returns the output to evaluate.
124
+ Takes the data point + any additional arguments and returns\
125
+ the output to evaluate.
124
126
  evaluators (dict[str, Callable[..., Any]]): Evaluator functions and\
125
127
  names. Each evaluator function takes the output of the executor\
126
128
  _and_ the target data, and returns a score. The score can be a\
@@ -132,30 +134,31 @@ class Evaluation:
132
134
  [Beta] List of instances of HumanEvaluator. For now, human\
133
135
  evaluator only holds the queue name.
134
136
  Defaults to an empty list.
135
- name (Optional[str], optional): Optional name of the evaluation.\
137
+ name (str | None, optional): Optional name of the evaluation.\
136
138
  Used to identify the evaluation in the group.\
137
139
  If not provided, a random name will be generated.
138
140
  Defaults to None.
139
- group_name (Optional[str], optional): an identifier to group\
141
+ group_name (str | None, optional): an identifier to group\
140
142
  evaluations. Only evaluations within the same group_name can be\
141
143
  visually compared. If not provided, "default" is assigned.
142
144
  Defaults to None
143
- concurrency_limit (int, optional): The concurrency limit for evaluation. This many\
144
- data points will be evaluated in parallel with a pool of workers.
145
+ concurrency_limit (int, optional): The concurrency limit for\
146
+ evaluation. This many data points will be evaluated in parallel\
147
+ with a pool of workers.
145
148
  Defaults to DEFAULT_BATCH_SIZE.
146
- project_api_key (Optional[str], optional): The project API key.\
149
+ project_api_key (str | None, optional): The project API key.\
147
150
  If not provided, LMNR_PROJECT_API_KEY environment variable is\
148
151
  used.
149
152
  Defaults to an empty string.
150
- base_url (Optional[str], optional): The base URL for Laminar API.\
153
+ base_url (str | None, optional): The base URL for Laminar API.\
151
154
  Useful if self-hosted. Do NOT include the port, use `http_port`\
152
155
  and `grpc_port` instead.
153
156
  Defaults to "https://api.lmnr.ai".
154
- http_port (Optional[int], optional): The port for Laminar API\
157
+ http_port (int | None, optional): The port for Laminar API\
155
158
  HTTP service. Defaults to 443 if not specified.
156
- grpc_port (Optional[int], optional): The port for Laminar API\
159
+ grpc_port (int | None, optional): The port for Laminar API\
157
160
  gRPC service. Defaults to 8443 if not specified.
158
- instruments (Optional[Set[Instruments]], optional): Set of modules\
161
+ instruments (set[Instruments] | None, optional): Set of modules\
159
162
  to auto-instrument. If None, all available instruments will be\
160
163
  used.
161
164
  See https://docs.lmnr.ai/tracing/automatic-instrumentation
@@ -393,21 +396,21 @@ class Evaluation:
393
396
 
394
397
 
395
398
  def evaluate(
396
- data: Union[EvaluationDataset, list[Union[Datapoint, dict]]],
399
+ data: EvaluationDataset | list[Datapoint | dict],
397
400
  executor: ExecutorFunction,
398
401
  evaluators: dict[str, EvaluatorFunction],
399
402
  human_evaluators: list[HumanEvaluator] = [],
400
- name: Optional[str] = None,
401
- group_name: Optional[str] = None,
403
+ name: str | None = None,
404
+ group_name: str | None = None,
402
405
  concurrency_limit: int = DEFAULT_BATCH_SIZE,
403
- project_api_key: Optional[str] = None,
404
- base_url: Optional[str] = None,
405
- http_port: Optional[int] = None,
406
- grpc_port: Optional[int] = None,
407
- instruments: Optional[Set[Instruments]] = None,
408
- max_export_batch_size: Optional[int] = MAX_EXPORT_BATCH_SIZE,
409
- trace_export_timeout_seconds: Optional[int] = None,
410
- ) -> Optional[Awaitable[None]]:
406
+ project_api_key: str | None = None,
407
+ base_url: str | None = None,
408
+ http_port: int | None = None,
409
+ grpc_port: int | None = None,
410
+ instruments: set[Instruments] | None = None,
411
+ max_export_batch_size: int | None = MAX_EXPORT_BATCH_SIZE,
412
+ trace_export_timeout_seconds: int | None = None,
413
+ ) -> Awaitable[None] | None:
411
414
  """
412
415
  If added to the file which is called through `lmnr eval` command, then
413
416
  registers the evaluation; otherwise, runs the evaluation.
@@ -418,7 +421,7 @@ def evaluate(
418
421
  You must await the call to `evaluate`.
419
422
 
420
423
  Parameters:
421
- data (Union[list[EvaluationDatapoint|dict]], EvaluationDataset]):\
424
+ data (list[EvaluationDatapoint|dict] | EvaluationDataset):\
422
425
  List of data points to evaluate or an evaluation dataset.
423
426
  `data` is the input to the executor function,
424
427
  `target` is the input to the evaluator function.
@@ -437,33 +440,33 @@ def evaluate(
437
440
  [Beta] List of instances of HumanEvaluator. For now, human\
438
441
  evaluator only holds the queue name.
439
442
  Defaults to an empty list.
440
- name (Optional[str], optional): Optional name of the evaluation.\
443
+ name (str | None, optional): Optional name of the evaluation.\
441
444
  Used to identify the evaluation in the group. If not provided, a\
442
445
  random name will be generated.
443
446
  Defaults to None.
444
- group_name (Optional[str], optional): An identifier to group evaluations.\
447
+ group_name (str | None, optional): An identifier to group evaluations.\
445
448
  Only evaluations within the same group_name can be visually compared.\
446
449
  If not provided, set to "default".
447
450
  Defaults to None
448
451
  concurrency_limit (int, optional): The concurrency limit for evaluation.
449
452
  Defaults to DEFAULT_BATCH_SIZE.
450
- project_api_key (Optional[str], optional): The project API key.
453
+ project_api_key (str | None, optional): The project API key.
451
454
  Defaults to None.
452
- base_url (Optional[str], optional): The base URL for Laminar API.\
455
+ base_url (str | None, optional): The base URL for Laminar API.\
453
456
  Useful if self-hosted elsewhere. Do NOT include the\
454
457
  port, use `http_port` and `grpc_port` instead.
455
458
  Defaults to "https://api.lmnr.ai".
456
- http_port (Optional[int], optional): The port for Laminar API's HTTP\
459
+ http_port (int | None, optional): The port for Laminar API's HTTP\
457
460
  service. 443 is used if not specified.
458
461
  Defaults to None.
459
- grpc_port (Optional[int], optional): The port for Laminar API's gRPC\
462
+ grpc_port (int | None, optional): The port for Laminar API's gRPC\
460
463
  service. 8443 is used if not specified.
461
464
  Defaults to None.
462
- instruments (Optional[Set[Instruments]], optional): Set of modules to\
465
+ instruments (set[Instruments] | None, optional): Set of modules to\
463
466
  auto-instrument. If None, all available instruments\
464
467
  will be used.
465
468
  Defaults to None.
466
- trace_export_timeout_seconds (Optional[int], optional): The timeout for\
469
+ trace_export_timeout_seconds (int | None, optional): The timeout for\
467
470
  trace export on OpenTelemetry exporter. Defaults to None.
468
471
  """
469
472
  evaluation = Evaluation(
lmnr/sdk/laminar.py CHANGED
@@ -12,10 +12,11 @@ from lmnr.opentelemetry_lib import MAX_MANUAL_SPAN_PAYLOAD_SIZE
12
12
  from lmnr.opentelemetry_lib.decorators import json_dumps
13
13
  from opentelemetry import context as context_api, trace
14
14
  from opentelemetry.context import attach, detach
15
+ from opentelemetry.trace import INVALID_TRACE_ID
15
16
  from opentelemetry.sdk.trace.id_generator import RandomIdGenerator
16
17
  from opentelemetry.util.types import AttributeValue
17
18
 
18
- from typing import Any, Literal, Optional, Set, Union
19
+ from typing import Any, Literal
19
20
 
20
21
  import copy
21
22
  import datetime
@@ -48,22 +49,22 @@ from .types import (
48
49
 
49
50
 
50
51
  class Laminar:
51
- __project_api_key: Optional[str] = None
52
+ __project_api_key: str | None = None
52
53
  __initialized: bool = False
53
- __base_http_url: Optional[str] = None
54
+ __base_http_url: str | None = None
54
55
 
55
56
  @classmethod
56
57
  def initialize(
57
58
  cls,
58
- project_api_key: Optional[str] = None,
59
- base_url: Optional[str] = None,
60
- http_port: Optional[int] = None,
61
- grpc_port: Optional[int] = None,
62
- instruments: Optional[Set[Instruments]] = None,
63
- disabled_instruments: Optional[Set[Instruments]] = None,
59
+ project_api_key: str | None = None,
60
+ base_url: str | None = None,
61
+ http_port: int | None = None,
62
+ grpc_port: int | None = None,
63
+ instruments: set[Instruments] | None = None,
64
+ disabled_instruments: set[Instruments] | None = None,
64
65
  disable_batch: bool = False,
65
- max_export_batch_size: Optional[int] = None,
66
- export_timeout_seconds: Optional[int] = None,
66
+ max_export_batch_size: int | None = None,
67
+ export_timeout_seconds: int | None = None,
67
68
  set_global_tracer_provider: bool = True,
68
69
  otel_logger_level: int = logging.ERROR,
69
70
  ):
@@ -72,31 +73,31 @@ class Laminar:
72
73
  decorators.
73
74
 
74
75
  Args:
75
- project_api_key (Optional[str], optional): Laminar project api key.\
76
+ project_api_key (str | None, optional): Laminar project api key.\
76
77
  You can generate one by going to the projects\
77
78
  settings page on the Laminar dashboard.\
78
79
  If not specified, it will try to read from the\
79
80
  LMNR_PROJECT_API_KEY environment variable\
80
81
  in os.environ or in .env file.
81
82
  Defaults to None.
82
- base_url (Optional[str], optional): Laminar API url. Do NOT include\
83
+ base_url (str | None, optional): Laminar API url. Do NOT include\
83
84
  the port number, use `http_port` and `grpc_port`.\
84
85
  If not specified, defaults to https://api.lmnr.ai.
85
- http_port (Optional[int], optional): Laminar API http port.\
86
+ http_port (int | None, optional): Laminar API http port.\
86
87
  If not specified, defaults to 443.
87
- grpc_port (Optional[int], optional): Laminar API grpc port.\
88
+ grpc_port (int | None, optional): Laminar API grpc port.\
88
89
  If not specified, defaults to 8443.
89
- instruments (Optional[Set[Instruments]], optional): Instruments to\
90
+ instruments (set[Instruments] | None, optional): Instruments to\
90
91
  enable. Defaults to all instruments. You can pass\
91
92
  an empty set to disable all instruments. Read more:\
92
93
  https://docs.lmnr.ai/tracing/automatic-instrumentation
93
- disabled_instruments (Optional[Set[Instruments]], optional): Instruments to\
94
+ disabled_instruments (set[Instruments] | None, optional): Instruments to\
94
95
  disable. Defaults to None.
95
96
  disable_batch (bool, optional): If set to True, spans will be sent\
96
97
  immediately to the backend. Useful for debugging, but\
97
98
  may cause performance overhead in production.
98
99
  Defaults to False.
99
- export_timeout_seconds (Optional[int], optional): Timeout for the OTLP\
100
+ export_timeout_seconds (int | None, optional): Timeout for the OTLP\
100
101
  exporter. Defaults to 30 seconds (unlike the\
101
102
  OpenTelemetry default of 10 seconds).
102
103
  Defaults to None.
@@ -176,8 +177,8 @@ class Laminar:
176
177
  def event(
177
178
  cls,
178
179
  name: str,
179
- value: Optional[AttributeValue] = None,
180
- timestamp: Optional[Union[datetime.datetime, int]] = None,
180
+ value: AttributeValue | None = None,
181
+ timestamp: datetime.datetime | int | None = None,
181
182
  ):
182
183
  """Associate an event with the current span. If using manual\
183
184
  instrumentation, use raw OpenTelemetry `span.add_event()` instead.\
@@ -185,14 +186,13 @@ class Laminar:
185
186
 
186
187
  Args:
187
188
  name (str): event name
188
- value (Optional[AttributeValue]): event value. Must be a primitive\
189
- type. Boolean true is assumed in the backend if\
190
- `value` is None.
191
- Defaults to None.
192
- timestamp (Optional[Union[datetime.datetime, int]], optional):\
193
- If int, must be epoch nanoseconds. If not\
194
- specified, relies on the underlying OpenTelemetry\
195
- implementation. Defaults to None.
189
+ value (AttributeValue | None, optional): event value. Must be a\
190
+ primitive type. Boolean `True` is assumed in the backend if\
191
+ `value` is None.
192
+ Defaults to None.
193
+ timestamp (datetime.datetime | int | None, optional): If int, must\
194
+ be epoch nanoseconds. If not specified, relies on the underlying\
195
+ OpenTelemetry implementation. Defaults to None.
196
196
  """
197
197
  if timestamp and isinstance(timestamp, datetime.datetime):
198
198
  timestamp = int(timestamp.timestamp() * 1e9)
@@ -220,12 +220,10 @@ class Laminar:
220
220
  cls,
221
221
  name: str,
222
222
  input: Any = None,
223
- span_type: Union[
224
- Literal["DEFAULT"], Literal["LLM"], Literal["TOOL"]
225
- ] = "DEFAULT",
226
- context: Optional[Context] = None,
227
- labels: Optional[list[str]] = None,
228
- parent_span_context: Optional[LaminarSpanContext] = None,
223
+ span_type: Literal["DEFAULT", "LLM", "TOOL"] = "DEFAULT",
224
+ context: Context | None = None,
225
+ labels: list[str] | None = None,
226
+ parent_span_context: LaminarSpanContext | None = None,
229
227
  ):
230
228
  """Start a new span as the current span. Useful for manual
231
229
  instrumentation. If `span_type` is set to `"LLM"`, you should report
@@ -243,12 +241,12 @@ class Laminar:
243
241
  name (str): name of the span
244
242
  input (Any, optional): input to the span. Will be sent as an\
245
243
  attribute, so must be json serializable. Defaults to None.
246
- span_type (Union[Literal["DEFAULT"], Literal["LLM"]], optional):\
244
+ span_type (Literal["DEFAULT", "LLM", "TOOL"], optional):\
247
245
  type of the span. If you use `"LLM"`, you should report usage\
248
246
  and response attributes manually. Defaults to "DEFAULT".
249
- context (Optional[Context], optional): raw OpenTelemetry context\
247
+ context (Context | None, optional): raw OpenTelemetry context\
250
248
  to attach the span to. Defaults to None.
251
- parent_span_context (Optional[LaminarSpanContext], optional): parent\
249
+ parent_span_context (LaminarSpanContext | None, optional): parent\
252
250
  span context to use for the span. Useful for continuing traces\
253
251
  across services. If parent_span_context is a\
254
252
  raw OpenTelemetry span context, or if it is a dictionary or string\
@@ -258,7 +256,7 @@ class Laminar:
258
256
  `Laminar.get_span_context`, `Laminar.get_span_context_dict` and\
259
257
  `Laminar.get_span_context_str` for more information.
260
258
  Defaults to None.
261
- labels (Optional[list[str]], optional): labels to set for the\
259
+ labels (list[str] | None, optional): labels to set for the\
262
260
  span. Defaults to None.
263
261
  """
264
262
 
@@ -321,7 +319,7 @@ class Laminar:
321
319
 
322
320
  @classmethod
323
321
  @contextmanager
324
- def with_labels(cls, labels: list[str], context: Optional[Context] = None):
322
+ def with_labels(cls, labels: list[str], context: Context | None = None):
325
323
  """Set labels for spans within this `with` context. This is useful for
326
324
  adding labels to the spans created in the auto-instrumentations.
327
325
 
@@ -363,12 +361,10 @@ class Laminar:
363
361
  cls,
364
362
  name: str,
365
363
  input: Any = None,
366
- span_type: Union[
367
- Literal["DEFAULT"], Literal["LLM"], Literal["TOOL"]
368
- ] = "DEFAULT",
369
- context: Optional[Context] = None,
370
- parent_span_context: Optional[LaminarSpanContext] = None,
371
- labels: Optional[dict[str, str]] = None,
364
+ span_type: Literal["DEFAULT", "LLM", "TOOL"] = "DEFAULT",
365
+ context: Context | None = None,
366
+ parent_span_context: LaminarSpanContext | None = None,
367
+ labels: dict[str, str] | None = None,
372
368
  ):
373
369
  """Start a new span. Useful for manual instrumentation.
374
370
  If `span_type` is set to `"LLM"`, you should report usage and response
@@ -405,12 +401,12 @@ class Laminar:
405
401
  name (str): name of the span
406
402
  input (Any, optional): input to the span. Will be sent as an\
407
403
  attribute, so must be json serializable. Defaults to None.
408
- span_type (Union[Literal["DEFAULT"], Literal["LLM"]], optional):\
404
+ span_type (Literal["DEFAULT", "LLM", "TOOL"], optional):\
409
405
  type of the span. If you use `"LLM"`, you should report usage\
410
406
  and response attributes manually. Defaults to "DEFAULT".
411
- context (Optional[Context], optional): raw OpenTelemetry context\
407
+ context (Context | None, optional): raw OpenTelemetry context\
412
408
  to attach the span to. Defaults to None.
413
- parent_span_context (Optional[LaminarSpanContext], optional): parent\
409
+ parent_span_context (LaminarSpanContext | None, optional): parent\
414
410
  span context to use for the span. Useful for continuing traces\
415
411
  across services. If parent_span_context is a\
416
412
  raw OpenTelemetry span context, or if it is a dictionary or string\
@@ -420,7 +416,7 @@ class Laminar:
420
416
  `Laminar.get_span_context`, `Laminar.get_span_context_dict` and\
421
417
  `Laminar.get_span_context_str` for more information.
422
418
  Defaults to None.
423
- labels (Optional[dict[str, str]], optional): labels to set for the\
419
+ labels (dict[str, str] | None, optional): labels to set for the\
424
420
  span. Defaults to None.
425
421
  """
426
422
  if not cls.is_initialized():
@@ -574,8 +570,8 @@ class Laminar:
574
570
 
575
571
  @classmethod
576
572
  def get_laminar_span_context(
577
- cls, span: Optional[trace.Span] = None
578
- ) -> Optional[LaminarSpanContext]:
573
+ cls, span: trace.Span | None = None
574
+ ) -> LaminarSpanContext | None:
579
575
  """Get the laminar span context for a given span.
580
576
  If no span is provided, the current active span will be used.
581
577
  """
@@ -590,15 +586,15 @@ class Laminar:
590
586
 
591
587
  @classmethod
592
588
  def get_laminar_span_context_dict(
593
- cls, span: Optional[trace.Span] = None
594
- ) -> Optional[dict]:
589
+ cls, span: trace.Span | None = None
590
+ ) -> dict | None:
595
591
  span_context = cls.get_laminar_span_context(span)
596
592
  if span_context is None:
597
593
  return None
598
594
  return span_context.model_dump()
599
595
 
600
596
  @classmethod
601
- def serialize_span_context(cls, span: Optional[trace.Span] = None) -> Optional[str]:
597
+ def serialize_span_context(cls, span: trace.Span | None = None) -> str | None:
602
598
  """Get the laminar span context for a given span as a string.
603
599
  If no span is provided, the current active span will be used.
604
600
 
@@ -632,9 +628,7 @@ class Laminar:
632
628
  return str(span_context)
633
629
 
634
630
  @classmethod
635
- def deserialize_span_context(
636
- cls, span_context: Union[dict, str]
637
- ) -> LaminarSpanContext:
631
+ def deserialize_span_context(cls, span_context: dict | str) -> LaminarSpanContext:
638
632
  return LaminarSpanContext.deserialize(span_context)
639
633
 
640
634
  @classmethod
@@ -657,14 +651,14 @@ class Laminar:
657
651
  @classmethod
658
652
  def set_session(
659
653
  cls,
660
- session_id: Optional[str] = None,
654
+ session_id: str | None = None,
661
655
  ):
662
656
  """Set the session and user id for the current span and the context
663
657
  (i.e. any children spans created from the current span in the current
664
658
  thread).
665
659
 
666
660
  Args:
667
- session_id (Optional[str], optional): Custom session id.\
661
+ session_id (str | None, optional): Custom session id.\
668
662
  Useful to debug and group long-running\
669
663
  sessions/conversations.
670
664
  Defaults to None.
@@ -710,6 +704,20 @@ class Laminar:
710
704
  def get_project_api_key(cls):
711
705
  return cls.__project_api_key
712
706
 
707
+ @classmethod
708
+ def get_trace_id(cls) -> uuid.UUID | None:
709
+ """Get the trace id for the current active span represented as a UUID.
710
+ Returns None if there is no active span.
711
+
712
+ Returns:
713
+ uuid.UUID | None: The trace id for the current span, or None if\
714
+ there is no active span.
715
+ """
716
+ trace_id = trace.get_current_span().get_span_context().trace_id
717
+ if trace_id == INVALID_TRACE_ID:
718
+ return None
719
+ return uuid.UUID(int=trace_id)
720
+
713
721
  @classmethod
714
722
  def _headers(cls):
715
723
  assert cls.__project_api_key is not None, "Project API key is not set"