lmnr 0.4.53.dev0__py3-none-any.whl → 0.7.26__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 (133) hide show
  1. lmnr/__init__.py +32 -11
  2. lmnr/cli/__init__.py +270 -0
  3. lmnr/cli/datasets.py +371 -0
  4. lmnr/cli/evals.py +111 -0
  5. lmnr/cli/rules.py +42 -0
  6. lmnr/opentelemetry_lib/__init__.py +70 -0
  7. lmnr/opentelemetry_lib/decorators/__init__.py +337 -0
  8. lmnr/opentelemetry_lib/litellm/__init__.py +685 -0
  9. lmnr/opentelemetry_lib/litellm/utils.py +100 -0
  10. lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/__init__.py +849 -0
  11. lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/config.py +13 -0
  12. lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/event_emitter.py +211 -0
  13. lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/event_models.py +41 -0
  14. lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/span_utils.py +401 -0
  15. lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/streaming.py +425 -0
  16. lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/utils.py +332 -0
  17. lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/version.py +1 -0
  18. lmnr/opentelemetry_lib/opentelemetry/instrumentation/claude_agent/__init__.py +451 -0
  19. lmnr/opentelemetry_lib/opentelemetry/instrumentation/claude_agent/proxy.py +144 -0
  20. lmnr/opentelemetry_lib/opentelemetry/instrumentation/cua_agent/__init__.py +100 -0
  21. lmnr/opentelemetry_lib/opentelemetry/instrumentation/cua_computer/__init__.py +476 -0
  22. lmnr/opentelemetry_lib/opentelemetry/instrumentation/cua_computer/utils.py +12 -0
  23. lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/__init__.py +599 -0
  24. lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/config.py +9 -0
  25. lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/schema_utils.py +26 -0
  26. lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/utils.py +330 -0
  27. lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/__init__.py +488 -0
  28. lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/config.py +8 -0
  29. lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/event_emitter.py +143 -0
  30. lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/event_models.py +41 -0
  31. lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/span_utils.py +229 -0
  32. lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/utils.py +92 -0
  33. lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/version.py +1 -0
  34. lmnr/opentelemetry_lib/opentelemetry/instrumentation/kernel/__init__.py +381 -0
  35. lmnr/opentelemetry_lib/opentelemetry/instrumentation/kernel/utils.py +36 -0
  36. lmnr/opentelemetry_lib/opentelemetry/instrumentation/langgraph/__init__.py +121 -0
  37. lmnr/opentelemetry_lib/opentelemetry/instrumentation/langgraph/utils.py +60 -0
  38. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/__init__.py +61 -0
  39. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/__init__.py +472 -0
  40. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/chat_wrappers.py +1185 -0
  41. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/completion_wrappers.py +305 -0
  42. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/config.py +16 -0
  43. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py +312 -0
  44. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/event_emitter.py +100 -0
  45. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/event_models.py +41 -0
  46. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/image_gen_wrappers.py +68 -0
  47. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/utils.py +197 -0
  48. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v0/__init__.py +176 -0
  49. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/__init__.py +368 -0
  50. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py +325 -0
  51. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py +135 -0
  52. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/responses_wrappers.py +786 -0
  53. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/version.py +1 -0
  54. lmnr/opentelemetry_lib/opentelemetry/instrumentation/openhands_ai/__init__.py +388 -0
  55. lmnr/opentelemetry_lib/opentelemetry/instrumentation/opentelemetry/__init__.py +69 -0
  56. lmnr/opentelemetry_lib/opentelemetry/instrumentation/skyvern/__init__.py +191 -0
  57. lmnr/opentelemetry_lib/opentelemetry/instrumentation/threading/__init__.py +197 -0
  58. lmnr/opentelemetry_lib/tracing/__init__.py +263 -0
  59. lmnr/opentelemetry_lib/tracing/_instrument_initializers.py +516 -0
  60. lmnr/{openllmetry_sdk → opentelemetry_lib}/tracing/attributes.py +21 -8
  61. lmnr/opentelemetry_lib/tracing/context.py +200 -0
  62. lmnr/opentelemetry_lib/tracing/exporter.py +153 -0
  63. lmnr/opentelemetry_lib/tracing/instruments.py +140 -0
  64. lmnr/opentelemetry_lib/tracing/processor.py +193 -0
  65. lmnr/opentelemetry_lib/tracing/span.py +398 -0
  66. lmnr/opentelemetry_lib/tracing/tracer.py +57 -0
  67. lmnr/opentelemetry_lib/tracing/utils.py +62 -0
  68. lmnr/opentelemetry_lib/utils/package_check.py +18 -0
  69. lmnr/opentelemetry_lib/utils/wrappers.py +11 -0
  70. lmnr/sdk/browser/__init__.py +0 -0
  71. lmnr/sdk/browser/background_send_events.py +158 -0
  72. lmnr/sdk/browser/browser_use_cdp_otel.py +100 -0
  73. lmnr/sdk/browser/browser_use_otel.py +142 -0
  74. lmnr/sdk/browser/bubus_otel.py +71 -0
  75. lmnr/sdk/browser/cdp_utils.py +518 -0
  76. lmnr/sdk/browser/inject_script.js +514 -0
  77. lmnr/sdk/browser/patchright_otel.py +151 -0
  78. lmnr/sdk/browser/playwright_otel.py +322 -0
  79. lmnr/sdk/browser/pw_utils.py +363 -0
  80. lmnr/sdk/browser/recorder/record.umd.min.cjs +84 -0
  81. lmnr/sdk/browser/utils.py +70 -0
  82. lmnr/sdk/client/asynchronous/async_client.py +180 -0
  83. lmnr/sdk/client/asynchronous/resources/__init__.py +6 -0
  84. lmnr/sdk/client/asynchronous/resources/base.py +32 -0
  85. lmnr/sdk/client/asynchronous/resources/browser_events.py +41 -0
  86. lmnr/sdk/client/asynchronous/resources/datasets.py +131 -0
  87. lmnr/sdk/client/asynchronous/resources/evals.py +266 -0
  88. lmnr/sdk/client/asynchronous/resources/evaluators.py +85 -0
  89. lmnr/sdk/client/asynchronous/resources/tags.py +83 -0
  90. lmnr/sdk/client/synchronous/resources/__init__.py +6 -0
  91. lmnr/sdk/client/synchronous/resources/base.py +32 -0
  92. lmnr/sdk/client/synchronous/resources/browser_events.py +40 -0
  93. lmnr/sdk/client/synchronous/resources/datasets.py +131 -0
  94. lmnr/sdk/client/synchronous/resources/evals.py +263 -0
  95. lmnr/sdk/client/synchronous/resources/evaluators.py +85 -0
  96. lmnr/sdk/client/synchronous/resources/tags.py +83 -0
  97. lmnr/sdk/client/synchronous/sync_client.py +191 -0
  98. lmnr/sdk/datasets/__init__.py +94 -0
  99. lmnr/sdk/datasets/file_utils.py +91 -0
  100. lmnr/sdk/decorators.py +163 -26
  101. lmnr/sdk/eval_control.py +3 -2
  102. lmnr/sdk/evaluations.py +403 -191
  103. lmnr/sdk/laminar.py +1080 -549
  104. lmnr/sdk/log.py +7 -2
  105. lmnr/sdk/types.py +246 -134
  106. lmnr/sdk/utils.py +151 -7
  107. lmnr/version.py +46 -0
  108. {lmnr-0.4.53.dev0.dist-info → lmnr-0.7.26.dist-info}/METADATA +152 -106
  109. lmnr-0.7.26.dist-info/RECORD +116 -0
  110. lmnr-0.7.26.dist-info/WHEEL +4 -0
  111. lmnr-0.7.26.dist-info/entry_points.txt +3 -0
  112. lmnr/cli.py +0 -101
  113. lmnr/openllmetry_sdk/.python-version +0 -1
  114. lmnr/openllmetry_sdk/__init__.py +0 -72
  115. lmnr/openllmetry_sdk/config/__init__.py +0 -9
  116. lmnr/openllmetry_sdk/decorators/base.py +0 -185
  117. lmnr/openllmetry_sdk/instruments.py +0 -38
  118. lmnr/openllmetry_sdk/tracing/__init__.py +0 -1
  119. lmnr/openllmetry_sdk/tracing/content_allow_list.py +0 -24
  120. lmnr/openllmetry_sdk/tracing/context_manager.py +0 -13
  121. lmnr/openllmetry_sdk/tracing/tracing.py +0 -884
  122. lmnr/openllmetry_sdk/utils/in_memory_span_exporter.py +0 -61
  123. lmnr/openllmetry_sdk/utils/package_check.py +0 -7
  124. lmnr/openllmetry_sdk/version.py +0 -1
  125. lmnr/sdk/datasets.py +0 -55
  126. lmnr-0.4.53.dev0.dist-info/LICENSE +0 -75
  127. lmnr-0.4.53.dev0.dist-info/RECORD +0 -33
  128. lmnr-0.4.53.dev0.dist-info/WHEEL +0 -4
  129. lmnr-0.4.53.dev0.dist-info/entry_points.txt +0 -3
  130. /lmnr/{openllmetry_sdk → opentelemetry_lib}/.flake8 +0 -0
  131. /lmnr/{openllmetry_sdk → opentelemetry_lib}/utils/__init__.py +0 -0
  132. /lmnr/{openllmetry_sdk → opentelemetry_lib}/utils/json_encoder.py +0 -0
  133. /lmnr/{openllmetry_sdk/decorators/__init__.py → py.typed} +0 -0
@@ -0,0 +1,36 @@
1
+ # import base64
2
+ import base64
3
+ from copy import deepcopy
4
+ from typing import Any
5
+
6
+ from lmnr.sdk.utils import json_dumps
7
+ from pydantic import BaseModel
8
+
9
+
10
+ def screenshot_tool_output_formatter(output: Any) -> str:
11
+ # output is of type BinaryAPIResponse, which implements
12
+ # the iter_bytes method from httpx.Response
13
+
14
+ return "<BINARY_BLOB_SCREENSHOT>"
15
+ # The below implementation works, but it may consume the entire iterator,
16
+ # making the response unusable after the formatter is called.
17
+ # This is UNLESS somewhere in code output.read() (httpx.Response.read())
18
+ # is called.
19
+ # We cannot rely on that now, so we return a placeholder.
20
+ # response_bytes = []
21
+ # for chunk in output.iter_bytes():
22
+ # response_bytes.append(chunk)
23
+ # response_base64 = base64.b64encode(response_bytes).decode("utf-8")
24
+ # return f"data:image/png;base64,{response_base64}"
25
+
26
+
27
+ def process_tool_output_formatter(output: Any) -> str:
28
+ if not isinstance(output, (dict, BaseModel)):
29
+ return json_dumps(output)
30
+
31
+ output = output.model_dump() if isinstance(output, BaseModel) else deepcopy(output)
32
+ if "stderr_b64" in output:
33
+ output["stderr"] = base64.b64decode(output["stderr_b64"]).decode("utf-8")
34
+ if "stdout_b64" in output:
35
+ output["stdout"] = base64.b64decode(output["stdout_b64"]).decode("utf-8")
36
+ return json_dumps(output)
@@ -0,0 +1,121 @@
1
+ """OpenTelemetry Langgraph instrumentation"""
2
+
3
+ import json
4
+ import logging
5
+ from typing import Collection
6
+
7
+ from .utils import (
8
+ with_tracer_wrapper,
9
+ )
10
+
11
+ from langchain_core.runnables.graph import Graph
12
+ from opentelemetry.trace import Tracer
13
+ from wrapt import wrap_function_wrapper
14
+ from opentelemetry.trace import get_tracer
15
+ from opentelemetry.context import get_value, attach, set_value
16
+
17
+ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
18
+ from opentelemetry.instrumentation.utils import unwrap
19
+
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+ _instruments = ("langgraph >= 0.1.0",)
24
+
25
+
26
+ @with_tracer_wrapper
27
+ def wrap_pregel_stream(tracer: Tracer, to_wrap, wrapped, instance, args, kwargs):
28
+ graph: Graph = instance.get_graph()
29
+ nodes = [
30
+ {
31
+ "id": node.id,
32
+ "name": node.name,
33
+ "metadata": node.metadata,
34
+ }
35
+ for node in graph.nodes.values()
36
+ ]
37
+ edges = [
38
+ {
39
+ "source": edge.source,
40
+ "target": edge.target,
41
+ "conditional": edge.conditional,
42
+ }
43
+ for edge in graph.edges
44
+ ]
45
+ d = {
46
+ "langgraph.edges": json.dumps(edges),
47
+ "langgraph.nodes": json.dumps(nodes),
48
+ }
49
+ association_properties = get_value("lmnr.langgraph.graph") or {}
50
+ association_properties.update(d)
51
+ attach(set_value("lmnr.langgraph.graph", association_properties))
52
+ return wrapped(*args, **kwargs)
53
+
54
+
55
+ @with_tracer_wrapper
56
+ async def async_wrap_pregel_stream(
57
+ tracer: Tracer, to_wrap, wrapped, instance, args, kwargs
58
+ ):
59
+ graph: Graph = await instance.aget_graph()
60
+ nodes = [
61
+ {
62
+ "id": node.id,
63
+ "name": node.name,
64
+ "metadata": node.metadata,
65
+ }
66
+ for node in graph.nodes.values()
67
+ ]
68
+ edges = [
69
+ {
70
+ "source": edge.source,
71
+ "target": edge.target,
72
+ "conditional": edge.conditional,
73
+ }
74
+ for edge in graph.edges
75
+ ]
76
+
77
+ d = {
78
+ "langgraph.edges": json.dumps(edges),
79
+ "langgraph.nodes": json.dumps(nodes),
80
+ }
81
+ association_properties = get_value("lmnr.langgraph.graph") or {}
82
+ association_properties.update(d)
83
+ attach(set_value("lmnr.langgraph.graph", association_properties))
84
+
85
+ async for item in wrapped(*args, **kwargs):
86
+ yield item
87
+
88
+
89
+ class LanggraphInstrumentor(BaseInstrumentor):
90
+ """An instrumentor for Langgraph."""
91
+
92
+ def __init__(self):
93
+ super().__init__()
94
+
95
+ def instrumentation_dependencies(self) -> Collection[str]:
96
+ return _instruments
97
+
98
+ def _instrument(self, **kwargs):
99
+ tracer_provider = kwargs.get("tracer_provider")
100
+ tracer = get_tracer(__name__, "0.0.1a0", tracer_provider)
101
+
102
+ wrap_function_wrapper(
103
+ module="langgraph.pregel",
104
+ name="Pregel.stream",
105
+ wrapper=wrap_pregel_stream(tracer, "Pregel.stream"),
106
+ )
107
+ wrap_function_wrapper(
108
+ module="langgraph.pregel",
109
+ name="Pregel.astream",
110
+ wrapper=async_wrap_pregel_stream(tracer, "Pregel.astream"),
111
+ )
112
+
113
+ def _uninstrument(self, **kwargs):
114
+ unwrap(
115
+ module="langgraph.pregel",
116
+ name="Pregel.stream",
117
+ )
118
+ unwrap(
119
+ module="langgraph.pregel",
120
+ name="Pregel.astream",
121
+ )
@@ -0,0 +1,60 @@
1
+ import logging
2
+ import traceback
3
+
4
+ import pydantic
5
+ from opentelemetry.trace import Span
6
+ from typing import Any
7
+
8
+
9
+ def set_span_attribute(span: Span, name: str, value: str):
10
+ if value is not None:
11
+ if value != "":
12
+ span.set_attribute(name, value)
13
+ return
14
+
15
+
16
+ def dont_throw(func):
17
+ """
18
+ A decorator that wraps the passed in function and logs exceptions instead of throwing them.
19
+
20
+ @param func: The function to wrap
21
+ @return: The wrapper function
22
+ """
23
+ # Obtain a logger specific to the function's module
24
+ logger = logging.getLogger(func.__module__)
25
+
26
+ def wrapper(*args, **kwargs):
27
+ try:
28
+ return func(*args, **kwargs)
29
+ except Exception:
30
+ logger.debug(
31
+ "Laminar failed to trace in %s, error: %s",
32
+ func.__name__,
33
+ traceback.format_exc(),
34
+ )
35
+
36
+ return wrapper
37
+
38
+
39
+ def to_dict(obj: pydantic.BaseModel | dict) -> dict[str, Any]:
40
+ try:
41
+ if isinstance(obj, pydantic.BaseModel):
42
+ return obj.model_dump()
43
+ elif isinstance(obj, dict):
44
+ return obj
45
+ else:
46
+ return dict(obj)
47
+ except Exception:
48
+ return dict(obj)
49
+
50
+
51
+ def with_tracer_wrapper(func):
52
+ """Helper for providing tracer for wrapper functions."""
53
+
54
+ def _with_tracer(tracer, to_wrap):
55
+ def wrapper(wrapped, instance, args, kwargs):
56
+ return func(tracer, to_wrap, wrapped, instance, args, kwargs)
57
+
58
+ return wrapper
59
+
60
+ return _with_tracer
@@ -0,0 +1,61 @@
1
+ """
2
+ Initially copied over from openllmetry, commit
3
+ b3a18c9f7e6ff2368c8fb0bc35fd9123f11121c4
4
+ """
5
+
6
+ from typing import Callable, Collection, Optional
7
+
8
+ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
9
+ from .shared.config import Config
10
+ from .utils import is_openai_v1
11
+ from typing_extensions import Coroutine
12
+
13
+ _instruments = ("openai >= 0.27.0",)
14
+
15
+
16
+ class OpenAIInstrumentor(BaseInstrumentor):
17
+ """An instrumentor for OpenAI's client library."""
18
+
19
+ def __init__(
20
+ self,
21
+ enrich_assistant: bool = False,
22
+ enrich_token_usage: bool = False,
23
+ exception_logger=None,
24
+ get_common_metrics_attributes: Callable[[], dict] = lambda: {},
25
+ upload_base64_image: Optional[
26
+ Callable[[str, str, str, str], Coroutine[None, None, str]]
27
+ ] = lambda *args: "",
28
+ enable_trace_context_propagation: bool = True,
29
+ use_legacy_attributes: bool = True,
30
+ ):
31
+ super().__init__()
32
+ Config.enrich_assistant = enrich_assistant
33
+ Config.enrich_token_usage = enrich_token_usage
34
+ Config.exception_logger = exception_logger
35
+ Config.get_common_metrics_attributes = get_common_metrics_attributes
36
+ Config.upload_base64_image = upload_base64_image
37
+ Config.enable_trace_context_propagation = enable_trace_context_propagation
38
+ Config.use_legacy_attributes = use_legacy_attributes
39
+
40
+ def instrumentation_dependencies(self) -> Collection[str]:
41
+ return _instruments
42
+
43
+ def _instrument(self, **kwargs):
44
+ if is_openai_v1():
45
+ from .v1 import OpenAIV1Instrumentor
46
+
47
+ OpenAIV1Instrumentor().instrument(**kwargs)
48
+ else:
49
+ from .v0 import OpenAIV0Instrumentor
50
+
51
+ OpenAIV0Instrumentor().instrument(**kwargs)
52
+
53
+ def _uninstrument(self, **kwargs):
54
+ if is_openai_v1():
55
+ from .v1 import OpenAIV1Instrumentor
56
+
57
+ OpenAIV1Instrumentor().uninstrument(**kwargs)
58
+ else:
59
+ from .v0 import OpenAIV0Instrumentor
60
+
61
+ OpenAIV0Instrumentor().uninstrument(**kwargs)