lmnr 0.4.65__py3-none-any.whl → 0.5.0__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 (37) hide show
  1. lmnr/__init__.py +30 -0
  2. lmnr/openllmetry_sdk/__init__.py +4 -15
  3. lmnr/openllmetry_sdk/tracing/attributes.py +0 -1
  4. lmnr/openllmetry_sdk/tracing/tracing.py +24 -9
  5. lmnr/sdk/browser/browser_use_otel.py +11 -12
  6. lmnr/sdk/browser/playwright_otel.py +214 -229
  7. lmnr/sdk/browser/pw_utils.py +289 -0
  8. lmnr/sdk/browser/utils.py +18 -53
  9. lmnr/sdk/client/asynchronous/async_client.py +157 -0
  10. lmnr/sdk/client/asynchronous/resources/__init__.py +13 -0
  11. lmnr/sdk/client/asynchronous/resources/agent.py +215 -0
  12. lmnr/sdk/client/asynchronous/resources/base.py +32 -0
  13. lmnr/sdk/client/asynchronous/resources/browser_events.py +40 -0
  14. lmnr/sdk/client/asynchronous/resources/evals.py +64 -0
  15. lmnr/sdk/client/asynchronous/resources/pipeline.py +89 -0
  16. lmnr/sdk/client/asynchronous/resources/semantic_search.py +60 -0
  17. lmnr/sdk/client/synchronous/resources/__init__.py +7 -0
  18. lmnr/sdk/client/synchronous/resources/agent.py +209 -0
  19. lmnr/sdk/client/synchronous/resources/base.py +32 -0
  20. lmnr/sdk/client/synchronous/resources/browser_events.py +40 -0
  21. lmnr/sdk/client/synchronous/resources/evals.py +102 -0
  22. lmnr/sdk/client/synchronous/resources/pipeline.py +89 -0
  23. lmnr/sdk/client/synchronous/resources/semantic_search.py +60 -0
  24. lmnr/sdk/client/synchronous/sync_client.py +170 -0
  25. lmnr/sdk/datasets.py +7 -2
  26. lmnr/sdk/evaluations.py +53 -27
  27. lmnr/sdk/laminar.py +22 -175
  28. lmnr/sdk/types.py +121 -23
  29. lmnr/sdk/utils.py +10 -0
  30. lmnr/version.py +6 -6
  31. {lmnr-0.4.65.dist-info → lmnr-0.5.0.dist-info}/METADATA +88 -38
  32. lmnr-0.5.0.dist-info/RECORD +55 -0
  33. lmnr/sdk/client.py +0 -313
  34. lmnr-0.4.65.dist-info/RECORD +0 -39
  35. {lmnr-0.4.65.dist-info → lmnr-0.5.0.dist-info}/LICENSE +0 -0
  36. {lmnr-0.4.65.dist-info → lmnr-0.5.0.dist-info}/WHEEL +0 -0
  37. {lmnr-0.4.65.dist-info → lmnr-0.5.0.dist-info}/entry_points.txt +0 -0
lmnr/__init__.py CHANGED
@@ -1,12 +1,18 @@
1
+ from .sdk.client.synchronous.sync_client import LaminarClient
2
+ from .sdk.client.asynchronous.async_client import AsyncLaminarClient
1
3
  from .sdk.datasets import EvaluationDataset, LaminarDataset
2
4
  from .sdk.evaluations import evaluate
3
5
  from .sdk.laminar import Laminar
4
6
  from .sdk.types import (
7
+ AgentOutput,
8
+ FinalOutputChunkContent,
5
9
  ChatMessage,
6
10
  HumanEvaluator,
7
11
  NodeInput,
8
12
  PipelineRunError,
9
13
  PipelineRunResponse,
14
+ RunAgentResponseChunk,
15
+ StepChunkContent,
10
16
  TracingLevel,
11
17
  )
12
18
  from .sdk.decorators import observe
@@ -14,3 +20,27 @@ from .sdk.types import LaminarSpanContext
14
20
  from .openllmetry_sdk import Instruments
15
21
  from .openllmetry_sdk.tracing.attributes import Attributes
16
22
  from opentelemetry.trace import use_span
23
+
24
+ __all__ = [
25
+ "AgentOutput",
26
+ "AsyncLaminarClient",
27
+ "Attributes",
28
+ "ChatMessage",
29
+ "EvaluationDataset",
30
+ "FinalOutputChunkContent",
31
+ "HumanEvaluator",
32
+ "Instruments",
33
+ "Laminar",
34
+ "LaminarClient",
35
+ "LaminarDataset",
36
+ "LaminarSpanContext",
37
+ "NodeInput",
38
+ "PipelineRunError",
39
+ "PipelineRunResponse",
40
+ "RunAgentResponseChunk",
41
+ "StepChunkContent",
42
+ "TracingLevel",
43
+ "evaluate",
44
+ "observe",
45
+ "use_span",
46
+ ]
@@ -16,7 +16,7 @@ from lmnr.openllmetry_sdk.tracing.tracing import TracerWrapper
16
16
  from typing import Dict
17
17
 
18
18
 
19
- class Traceloop:
19
+ class TracerManager:
20
20
  __tracer_wrapper: TracerWrapper
21
21
 
22
22
  @staticmethod
@@ -44,17 +44,6 @@ class Traceloop:
44
44
  if isinstance(headers, str):
45
45
  headers = parse_env_headers(headers)
46
46
 
47
- if (
48
- not exporter
49
- and not processor
50
- and api_endpoint == "https://api.lmnr.ai"
51
- and not api_key
52
- ):
53
- print(
54
- "Set the LMNR_PROJECT_API_KEY environment variable to your project API key"
55
- )
56
- return
57
-
58
47
  if api_key and not exporter and not processor and not headers:
59
48
  headers = {
60
49
  "Authorization": f"Bearer {api_key}",
@@ -65,7 +54,7 @@ class Traceloop:
65
54
  TracerWrapper.set_static_params(
66
55
  resource_attributes, enable_content_tracing, api_endpoint, headers
67
56
  )
68
- Traceloop.__tracer_wrapper = TracerWrapper(
57
+ TracerManager.__tracer_wrapper = TracerWrapper(
69
58
  disable_batch=disable_batch,
70
59
  processor=processor,
71
60
  propagator=propagator,
@@ -79,5 +68,5 @@ class Traceloop:
79
68
 
80
69
  @staticmethod
81
70
  def flush():
82
- if Traceloop.__tracer_wrapper:
83
- Traceloop.__tracer_wrapper.flush()
71
+ if getattr(TracerManager, "__tracer_wrapper", None):
72
+ TracerManager.__tracer_wrapper.flush()
@@ -9,7 +9,6 @@ SPAN_IDS_PATH = "lmnr.span.ids_path"
9
9
  SPAN_INSTRUMENTATION_SOURCE = "lmnr.span.instrumentation_source"
10
10
  SPAN_SDK_VERSION = "lmnr.span.sdk_version"
11
11
  SPAN_LANGUAGE_VERSION = "lmnr.span.language_version"
12
- OVERRIDE_PARENT_SPAN = "lmnr.internal.override_parent_span"
13
12
 
14
13
  ASSOCIATION_PROPERTIES = "lmnr.association.properties"
15
14
  SESSION_ID = "session_id"
@@ -4,6 +4,8 @@ import logging
4
4
  import uuid
5
5
 
6
6
  from contextvars import Context
7
+ from lmnr.sdk.client.asynchronous.async_client import AsyncLaminarClient
8
+ from lmnr.sdk.client.synchronous.sync_client import LaminarClient
7
9
  from lmnr.sdk.log import VerboseColorfulFormatter
8
10
  from lmnr.openllmetry_sdk.instruments import Instruments
9
11
  from lmnr.openllmetry_sdk.tracing.attributes import (
@@ -41,7 +43,7 @@ from opentelemetry.trace import get_tracer_provider, ProxyTracerProvider
41
43
 
42
44
  from typing import Dict, Optional, Set
43
45
 
44
- from lmnr.version import SDK_VERSION, PYTHON_VERSION
46
+ from lmnr.version import __version__, PYTHON_VERSION
45
47
 
46
48
  module_logger = logging.getLogger(__name__)
47
49
  console_log_handler = logging.StreamHandler()
@@ -80,6 +82,8 @@ class TracerWrapper(object):
80
82
  __logger: logging.Logger = None
81
83
  __span_id_to_path: dict[int, list[str]] = {}
82
84
  __span_id_lists: dict[int, list[str]] = {}
85
+ __client: LaminarClient = None
86
+ __async_client: AsyncLaminarClient = None
83
87
 
84
88
  def __new__(
85
89
  cls,
@@ -99,6 +103,15 @@ class TracerWrapper(object):
99
103
  if not TracerWrapper.endpoint:
100
104
  return obj
101
105
 
106
+ obj.__client = LaminarClient(
107
+ base_url=base_http_url,
108
+ project_api_key=project_api_key,
109
+ )
110
+ obj.__async_client = AsyncLaminarClient(
111
+ base_url=base_http_url,
112
+ project_api_key=project_api_key,
113
+ )
114
+
102
115
  obj.__resource = Resource(attributes=TracerWrapper.resource_attributes)
103
116
  obj.__tracer_provider = init_tracer_provider(resource=obj.__resource)
104
117
  if processor:
@@ -135,8 +148,8 @@ class TracerWrapper(object):
135
148
  instrument_set = init_instrumentations(
136
149
  should_enrich_metrics,
137
150
  instruments,
138
- base_http_url=base_http_url,
139
- project_api_key=project_api_key,
151
+ client=obj.__client,
152
+ async_client=obj.__async_client,
140
153
  )
141
154
 
142
155
  if not instrument_set:
@@ -184,7 +197,7 @@ class TracerWrapper(object):
184
197
  self.__span_id_lists[span.get_span_context().span_id] = span_ids_path
185
198
 
186
199
  span.set_attribute(SPAN_INSTRUMENTATION_SOURCE, "python")
187
- span.set_attribute(SPAN_SDK_VERSION, SDK_VERSION)
200
+ span.set_attribute(SPAN_SDK_VERSION, __version__)
188
201
  span.set_attribute(SPAN_LANGUAGE_VERSION, f"python@{PYTHON_VERSION}")
189
202
 
190
203
  association_properties = get_value("association_properties")
@@ -320,8 +333,8 @@ def init_instrumentations(
320
333
  should_enrich_metrics: bool,
321
334
  instruments: Optional[Set[Instruments]] = None,
322
335
  block_instruments: Optional[Set[Instruments]] = None,
323
- base_http_url: Optional[str] = None,
324
- project_api_key: Optional[str] = None,
336
+ client: Optional[LaminarClient] = None,
337
+ async_client: Optional[AsyncLaminarClient] = None,
325
338
  ):
326
339
  block_instruments = block_instruments or set()
327
340
  # These libraries are not instrumented by default,
@@ -434,7 +447,7 @@ def init_instrumentations(
434
447
  if init_weaviate_instrumentor():
435
448
  instrument_set = True
436
449
  elif instrument == Instruments.PLAYWRIGHT:
437
- if init_playwright_instrumentor():
450
+ if init_playwright_instrumentor(client, async_client):
438
451
  instrument_set = True
439
452
  elif instrument == Instruments.BROWSER_USE:
440
453
  if init_browser_use_instrumentor():
@@ -465,12 +478,14 @@ def init_browser_use_instrumentor():
465
478
  return False
466
479
 
467
480
 
468
- def init_playwright_instrumentor():
481
+ def init_playwright_instrumentor(
482
+ client: LaminarClient, async_client: AsyncLaminarClient
483
+ ):
469
484
  try:
470
485
  if is_package_installed("playwright"):
471
486
  from lmnr.sdk.browser.playwright_otel import PlaywrightInstrumentor
472
487
 
473
- instrumentor = PlaywrightInstrumentor()
488
+ instrumentor = PlaywrightInstrumentor(client, async_client)
474
489
  instrumentor.instrument()
475
490
  return True
476
491
  except Exception as e:
@@ -1,7 +1,7 @@
1
1
  from lmnr.openllmetry_sdk.decorators.base import json_dumps
2
- from lmnr.sdk.browser.utils import _with_tracer_wrapper
2
+ from lmnr.sdk.browser.utils import with_tracer_wrapper
3
3
  from lmnr.sdk.utils import get_input_from_func_args
4
- from lmnr.version import SDK_VERSION
4
+ from lmnr.version import __version__
5
5
 
6
6
  from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
7
7
  from opentelemetry.instrumentation.utils import unwrap
@@ -35,7 +35,7 @@ WRAPPED_METHODS = [
35
35
  "object": "Controller",
36
36
  "method": "act",
37
37
  "span_name": "controller.act",
38
- "ignore_input": False,
38
+ "ignore_input": True,
39
39
  "ignore_output": False,
40
40
  "span_type": "DEFAULT",
41
41
  },
@@ -50,7 +50,7 @@ WRAPPED_METHODS = [
50
50
  ]
51
51
 
52
52
 
53
- @_with_tracer_wrapper
53
+ @with_tracer_wrapper
54
54
  async def _wrap(tracer: Tracer, to_wrap, wrapped, instance, args, kwargs):
55
55
  span_name = to_wrap.get("span_name")
56
56
  attributes = {
@@ -58,13 +58,12 @@ async def _wrap(tracer: Tracer, to_wrap, wrapped, instance, args, kwargs):
58
58
  }
59
59
  if to_wrap.get("method") == "execute_action":
60
60
  span_name = args[0] if len(args) > 0 else kwargs.get("action_name", "action")
61
- elif to_wrap.get("method") == "execute_action":
62
- attributes["lmnr.span.input"] = {
63
- "action": span_name,
64
- "params": json_dumps(
65
- args[1] if len(args) > 1 else kwargs.get("params", {})
66
- ),
67
- }
61
+ attributes["lmnr.span.input"] = json_dumps(
62
+ {
63
+ "action": span_name,
64
+ "params": args[1] if len(args) > 1 else kwargs.get("params", {}),
65
+ }
66
+ )
68
67
  else:
69
68
  if not to_wrap.get("ignore_input"):
70
69
  attributes["lmnr.span.input"] = json_dumps(
@@ -87,7 +86,7 @@ class BrowserUseInstrumentor(BaseInstrumentor):
87
86
 
88
87
  def _instrument(self, **kwargs):
89
88
  tracer_provider = kwargs.get("tracer_provider")
90
- tracer = get_tracer(__name__, SDK_VERSION, tracer_provider)
89
+ tracer = get_tracer(__name__, __version__, tracer_provider)
91
90
 
92
91
  for wrapped_method in WRAPPED_METHODS:
93
92
  wrap_package = wrapped_method.get("package")