lmnr 0.6.7__tar.gz → 0.6.9__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.7 → lmnr-0.6.9}/PKG-INFO +55 -55
- lmnr-0.6.9/pyproject.toml +142 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/cli.py +50 -24
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/decorators/__init__.py +12 -15
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/__init__.py +90 -15
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/utils.py +81 -58
- lmnr-0.6.9/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/langgraph/__init__.py +119 -0
- lmnr-0.6.9/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/langgraph/utils.py +60 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/tracing/_instrument_initializers.py +12 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/tracing/context_properties.py +14 -1
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/tracing/instruments.py +2 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/tracing/processor.py +1 -1
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/decorators.py +12 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/evaluations.py +4 -3
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/laminar.py +145 -28
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/types.py +2 -2
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/utils.py +15 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/version.py +1 -1
- lmnr-0.6.7/pyproject.toml +0 -138
- {lmnr-0.6.7 → lmnr-0.6.9}/LICENSE +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/README.md +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/.flake8 +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/config.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/tracing/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/tracing/attributes.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/tracing/exporter.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/tracing/tracer.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/utils/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/utils/json_encoder.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/opentelemetry_lib/utils/package_check.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/py.typed +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/browser/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/browser/browser_use_otel.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/browser/patchright_otel.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/browser/playwright_otel.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/browser/pw_utils.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/browser/rrweb/rrweb.umd.min.cjs +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/browser/utils.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/asynchronous/async_client.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/asynchronous/resources/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/asynchronous/resources/agent.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/asynchronous/resources/base.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/asynchronous/resources/browser_events.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/asynchronous/resources/evals.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/asynchronous/resources/tags.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/synchronous/resources/__init__.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/synchronous/resources/agent.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/synchronous/resources/base.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/synchronous/resources/browser_events.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/synchronous/resources/evals.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/synchronous/resources/tags.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/client/synchronous/sync_client.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/datasets.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/eval_control.py +0 -0
- {lmnr-0.6.7 → lmnr-0.6.9}/src/lmnr/sdk/log.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: lmnr
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.9
|
4
4
|
Summary: Python SDK for Laminar
|
5
5
|
License: Apache-2.0
|
6
6
|
Author: lmnr.ai
|
@@ -46,61 +46,61 @@ Requires-Dist: httpx (>=0.25.0)
|
|
46
46
|
Requires-Dist: opentelemetry-api (>=1.33.0)
|
47
47
|
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc (>=1.33.0)
|
48
48
|
Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.33.0)
|
49
|
-
Requires-Dist: opentelemetry-instrumentation-alephalpha (>=0.40.
|
50
|
-
Requires-Dist: opentelemetry-instrumentation-alephalpha (>=0.40.
|
51
|
-
Requires-Dist: opentelemetry-instrumentation-anthropic (>=0.40.
|
52
|
-
Requires-Dist: opentelemetry-instrumentation-anthropic (>=0.40.
|
53
|
-
Requires-Dist: opentelemetry-instrumentation-bedrock (>=0.40.
|
54
|
-
Requires-Dist: opentelemetry-instrumentation-bedrock (>=0.40.
|
55
|
-
Requires-Dist: opentelemetry-instrumentation-chromadb (>=0.40.
|
56
|
-
Requires-Dist: opentelemetry-instrumentation-chromadb (>=0.40.
|
57
|
-
Requires-Dist: opentelemetry-instrumentation-cohere (>=0.40.
|
58
|
-
Requires-Dist: opentelemetry-instrumentation-cohere (>=0.40.
|
59
|
-
Requires-Dist: opentelemetry-instrumentation-crewai (>=0.40.
|
60
|
-
Requires-Dist: opentelemetry-instrumentation-crewai (>=0.40.
|
61
|
-
Requires-Dist: opentelemetry-instrumentation-google-generativeai (>=0.40.
|
62
|
-
Requires-Dist: opentelemetry-instrumentation-google-generativeai (>=0.40.
|
63
|
-
Requires-Dist: opentelemetry-instrumentation-groq (>=0.40.
|
64
|
-
Requires-Dist: opentelemetry-instrumentation-groq (>=0.40.
|
65
|
-
Requires-Dist: opentelemetry-instrumentation-haystack (>=0.40.
|
66
|
-
Requires-Dist: opentelemetry-instrumentation-haystack (>=0.40.
|
67
|
-
Requires-Dist: opentelemetry-instrumentation-lancedb (>=0.40.
|
68
|
-
Requires-Dist: opentelemetry-instrumentation-lancedb (>=0.40.
|
69
|
-
Requires-Dist: opentelemetry-instrumentation-langchain (>=0.40.
|
70
|
-
Requires-Dist: opentelemetry-instrumentation-langchain (>=0.40.
|
71
|
-
Requires-Dist: opentelemetry-instrumentation-llamaindex (>=0.40.
|
72
|
-
Requires-Dist: opentelemetry-instrumentation-llamaindex (>=0.40.
|
73
|
-
Requires-Dist: opentelemetry-instrumentation-marqo (>=0.40.
|
74
|
-
Requires-Dist: opentelemetry-instrumentation-marqo (>=0.40.
|
75
|
-
Requires-Dist: opentelemetry-instrumentation-mcp (>=0.40.
|
76
|
-
Requires-Dist: opentelemetry-instrumentation-mcp (>=0.40.
|
77
|
-
Requires-Dist: opentelemetry-instrumentation-milvus (>=0.40.
|
78
|
-
Requires-Dist: opentelemetry-instrumentation-milvus (>=0.40.
|
79
|
-
Requires-Dist: opentelemetry-instrumentation-mistralai (>=0.40.
|
80
|
-
Requires-Dist: opentelemetry-instrumentation-mistralai (>=0.40.
|
81
|
-
Requires-Dist: opentelemetry-instrumentation-ollama (>=0.40.
|
82
|
-
Requires-Dist: opentelemetry-instrumentation-ollama (>=0.40.
|
83
|
-
Requires-Dist: opentelemetry-instrumentation-openai (>=0.40.
|
84
|
-
Requires-Dist: opentelemetry-instrumentation-openai (>=0.40.
|
85
|
-
Requires-Dist: opentelemetry-instrumentation-pinecone (>=0.40.
|
86
|
-
Requires-Dist: opentelemetry-instrumentation-pinecone (>=0.40.
|
87
|
-
Requires-Dist: opentelemetry-instrumentation-qdrant (>=0.40.
|
88
|
-
Requires-Dist: opentelemetry-instrumentation-qdrant (>=0.40.
|
89
|
-
Requires-Dist: opentelemetry-instrumentation-replicate (>=0.40.
|
90
|
-
Requires-Dist: opentelemetry-instrumentation-replicate (>=0.40.
|
91
|
-
Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.40.
|
92
|
-
Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.40.
|
49
|
+
Requires-Dist: opentelemetry-instrumentation-alephalpha (>=0.40.8) ; extra == "alephalpha"
|
50
|
+
Requires-Dist: opentelemetry-instrumentation-alephalpha (>=0.40.8) ; extra == "all"
|
51
|
+
Requires-Dist: opentelemetry-instrumentation-anthropic (>=0.40.8) ; extra == "all"
|
52
|
+
Requires-Dist: opentelemetry-instrumentation-anthropic (>=0.40.8) ; extra == "anthropic"
|
53
|
+
Requires-Dist: opentelemetry-instrumentation-bedrock (>=0.40.8) ; extra == "all"
|
54
|
+
Requires-Dist: opentelemetry-instrumentation-bedrock (>=0.40.8) ; extra == "bedrock"
|
55
|
+
Requires-Dist: opentelemetry-instrumentation-chromadb (>=0.40.8) ; extra == "all"
|
56
|
+
Requires-Dist: opentelemetry-instrumentation-chromadb (>=0.40.8) ; extra == "chromadb"
|
57
|
+
Requires-Dist: opentelemetry-instrumentation-cohere (>=0.40.8) ; extra == "all"
|
58
|
+
Requires-Dist: opentelemetry-instrumentation-cohere (>=0.40.8) ; extra == "cohere"
|
59
|
+
Requires-Dist: opentelemetry-instrumentation-crewai (>=0.40.8) ; extra == "all"
|
60
|
+
Requires-Dist: opentelemetry-instrumentation-crewai (>=0.40.8) ; extra == "crewai"
|
61
|
+
Requires-Dist: opentelemetry-instrumentation-google-generativeai (>=0.40.8) ; extra == "all"
|
62
|
+
Requires-Dist: opentelemetry-instrumentation-google-generativeai (>=0.40.8) ; extra == "google-generativeai"
|
63
|
+
Requires-Dist: opentelemetry-instrumentation-groq (>=0.40.8) ; extra == "all"
|
64
|
+
Requires-Dist: opentelemetry-instrumentation-groq (>=0.40.8) ; extra == "groq"
|
65
|
+
Requires-Dist: opentelemetry-instrumentation-haystack (>=0.40.8) ; extra == "all"
|
66
|
+
Requires-Dist: opentelemetry-instrumentation-haystack (>=0.40.8) ; extra == "haystack"
|
67
|
+
Requires-Dist: opentelemetry-instrumentation-lancedb (>=0.40.8) ; extra == "all"
|
68
|
+
Requires-Dist: opentelemetry-instrumentation-lancedb (>=0.40.8) ; extra == "lancedb"
|
69
|
+
Requires-Dist: opentelemetry-instrumentation-langchain (>=0.40.8) ; extra == "all"
|
70
|
+
Requires-Dist: opentelemetry-instrumentation-langchain (>=0.40.8) ; extra == "langchain"
|
71
|
+
Requires-Dist: opentelemetry-instrumentation-llamaindex (>=0.40.8) ; extra == "all"
|
72
|
+
Requires-Dist: opentelemetry-instrumentation-llamaindex (>=0.40.8) ; extra == "llamaindex"
|
73
|
+
Requires-Dist: opentelemetry-instrumentation-marqo (>=0.40.8) ; extra == "all"
|
74
|
+
Requires-Dist: opentelemetry-instrumentation-marqo (>=0.40.8) ; extra == "marqo"
|
75
|
+
Requires-Dist: opentelemetry-instrumentation-mcp (>=0.40.8) ; extra == "all"
|
76
|
+
Requires-Dist: opentelemetry-instrumentation-mcp (>=0.40.8) ; extra == "mcp"
|
77
|
+
Requires-Dist: opentelemetry-instrumentation-milvus (>=0.40.8) ; extra == "all"
|
78
|
+
Requires-Dist: opentelemetry-instrumentation-milvus (>=0.40.8) ; extra == "milvus"
|
79
|
+
Requires-Dist: opentelemetry-instrumentation-mistralai (>=0.40.8) ; extra == "all"
|
80
|
+
Requires-Dist: opentelemetry-instrumentation-mistralai (>=0.40.8) ; extra == "mistralai"
|
81
|
+
Requires-Dist: opentelemetry-instrumentation-ollama (>=0.40.8) ; extra == "all"
|
82
|
+
Requires-Dist: opentelemetry-instrumentation-ollama (>=0.40.8) ; extra == "ollama"
|
83
|
+
Requires-Dist: opentelemetry-instrumentation-openai (>=0.40.8) ; extra == "all"
|
84
|
+
Requires-Dist: opentelemetry-instrumentation-openai (>=0.40.8) ; extra == "openai"
|
85
|
+
Requires-Dist: opentelemetry-instrumentation-pinecone (>=0.40.8) ; extra == "all"
|
86
|
+
Requires-Dist: opentelemetry-instrumentation-pinecone (>=0.40.8) ; extra == "pinecone"
|
87
|
+
Requires-Dist: opentelemetry-instrumentation-qdrant (>=0.40.8) ; extra == "all"
|
88
|
+
Requires-Dist: opentelemetry-instrumentation-qdrant (>=0.40.8) ; extra == "qdrant"
|
89
|
+
Requires-Dist: opentelemetry-instrumentation-replicate (>=0.40.8) ; extra == "all"
|
90
|
+
Requires-Dist: opentelemetry-instrumentation-replicate (>=0.40.8) ; extra == "replicate"
|
91
|
+
Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.40.8) ; extra == "all"
|
92
|
+
Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.40.8) ; extra == "sagemaker"
|
93
93
|
Requires-Dist: opentelemetry-instrumentation-threading (>=0.54b0)
|
94
|
-
Requires-Dist: opentelemetry-instrumentation-together (>=0.40.
|
95
|
-
Requires-Dist: opentelemetry-instrumentation-together (>=0.40.
|
96
|
-
Requires-Dist: opentelemetry-instrumentation-transformers (>=0.40.
|
97
|
-
Requires-Dist: opentelemetry-instrumentation-transformers (>=0.40.
|
98
|
-
Requires-Dist: opentelemetry-instrumentation-vertexai (>=0.40.
|
99
|
-
Requires-Dist: opentelemetry-instrumentation-vertexai (>=0.40.
|
100
|
-
Requires-Dist: opentelemetry-instrumentation-watsonx (>=0.40.
|
101
|
-
Requires-Dist: opentelemetry-instrumentation-watsonx (>=0.40.
|
102
|
-
Requires-Dist: opentelemetry-instrumentation-weaviate (>=0.40.
|
103
|
-
Requires-Dist: opentelemetry-instrumentation-weaviate (>=0.40.
|
94
|
+
Requires-Dist: opentelemetry-instrumentation-together (>=0.40.8) ; extra == "all"
|
95
|
+
Requires-Dist: opentelemetry-instrumentation-together (>=0.40.8) ; extra == "together"
|
96
|
+
Requires-Dist: opentelemetry-instrumentation-transformers (>=0.40.8) ; extra == "all"
|
97
|
+
Requires-Dist: opentelemetry-instrumentation-transformers (>=0.40.8) ; extra == "transformers"
|
98
|
+
Requires-Dist: opentelemetry-instrumentation-vertexai (>=0.40.8) ; extra == "all"
|
99
|
+
Requires-Dist: opentelemetry-instrumentation-vertexai (>=0.40.8) ; extra == "vertexai"
|
100
|
+
Requires-Dist: opentelemetry-instrumentation-watsonx (>=0.40.8) ; extra == "all"
|
101
|
+
Requires-Dist: opentelemetry-instrumentation-watsonx (>=0.40.8) ; extra == "watsonx"
|
102
|
+
Requires-Dist: opentelemetry-instrumentation-weaviate (>=0.40.8) ; extra == "all"
|
103
|
+
Requires-Dist: opentelemetry-instrumentation-weaviate (>=0.40.8) ; extra == "weaviate"
|
104
104
|
Requires-Dist: opentelemetry-sdk (>=1.33.0)
|
105
105
|
Requires-Dist: opentelemetry-semantic-conventions (>=0.54b0)
|
106
106
|
Requires-Dist: opentelemetry-semantic-conventions-ai (>=0.4.8)
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# Laminar Python
|
2
|
+
|
3
|
+
# If you are looking for information about possible extras installations,
|
4
|
+
# i.e. what you can pass into `pip install 'lmnr[extra1,extra2]'`, please see the
|
5
|
+
# `[project.optional-dependencies]` section below.
|
6
|
+
|
7
|
+
[project]
|
8
|
+
name = "lmnr"
|
9
|
+
version = "0.6.9"
|
10
|
+
description = "Python SDK for Laminar"
|
11
|
+
authors = [
|
12
|
+
{ name = "lmnr.ai", email = "founders@lmnr.ai" }
|
13
|
+
]
|
14
|
+
readme = "README.md"
|
15
|
+
requires-python = ">=3.10,<4"
|
16
|
+
license = "Apache-2.0"
|
17
|
+
dependencies = [
|
18
|
+
"pydantic (>=2.0.3,<3.0.0)",
|
19
|
+
"python-dotenv (>=1.0)",
|
20
|
+
"opentelemetry-api (>=1.33.0)",
|
21
|
+
"opentelemetry-sdk (>=1.33.0)",
|
22
|
+
"opentelemetry-exporter-otlp-proto-http (>=1.33.0)",
|
23
|
+
"opentelemetry-exporter-otlp-proto-grpc (>=1.33.0)",
|
24
|
+
"opentelemetry-semantic-conventions (>=0.54b0)",
|
25
|
+
"opentelemetry-semantic-conventions-ai (>=0.4.8)",
|
26
|
+
"tqdm (>=4.0)",
|
27
|
+
"argparse (>=1.0)",
|
28
|
+
"tenacity (>=8.0)",
|
29
|
+
# Since 1.68.0, grpcio writes a warning message
|
30
|
+
# that looks scary, but is harmless.
|
31
|
+
# WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
|
32
|
+
# E0000 00:00:1737439981.199902 9456033 init.cc:229] grpc_wait_for_shutdown_with_timeout() timed out.
|
33
|
+
#
|
34
|
+
# Remove this comment when we make sure that grpcio has resolved this.
|
35
|
+
# Related issue:
|
36
|
+
# https://discuss.ai.google.dev/t/warning-all-log-messages-before-absl-initializelog-is-called-are-written-to-stderr-e0000-001731955515-629532-17124-init-cc-229-grpc-wait-for-shutdown-with-timeout-timed-out/50020
|
37
|
+
# https://github.com/grpc/grpc/issues/38490
|
38
|
+
"grpcio>=1",
|
39
|
+
"httpx>=0.25.0",
|
40
|
+
"opentelemetry-instrumentation-threading>=0.54b0",
|
41
|
+
]
|
42
|
+
|
43
|
+
[project.scripts]
|
44
|
+
lmnr = "lmnr.cli:cli"
|
45
|
+
|
46
|
+
[project.optional-dependencies]
|
47
|
+
# List of all possible extras. You can specify one or more of these extras
|
48
|
+
# when installing the package, using any of the following examples:
|
49
|
+
# `pip install 'lmnr[anthropic,openai]'`
|
50
|
+
# `uv pip install 'lmnr[anthropic,openai]'`
|
51
|
+
# `uv add lmnr --extra anthropic --extra openai`
|
52
|
+
# `poetry add 'lmnr[anthropic,openai]'`
|
53
|
+
|
54
|
+
alephalpha=["opentelemetry-instrumentation-alephalpha>=0.40.8"]
|
55
|
+
anthropic=["opentelemetry-instrumentation-anthropic>=0.40.8"]
|
56
|
+
bedrock=["opentelemetry-instrumentation-bedrock>=0.40.8"]
|
57
|
+
chromadb=["opentelemetry-instrumentation-chromadb>=0.40.8"]
|
58
|
+
cohere=["opentelemetry-instrumentation-cohere>=0.40.8"]
|
59
|
+
crewai=["opentelemetry-instrumentation-crewai>=0.40.8"]
|
60
|
+
google-generativeai=["opentelemetry-instrumentation-google-generativeai>=0.40.8"]
|
61
|
+
groq=["opentelemetry-instrumentation-groq>=0.40.8"]
|
62
|
+
haystack=["opentelemetry-instrumentation-haystack>=0.40.8"]
|
63
|
+
lancedb=["opentelemetry-instrumentation-lancedb>=0.40.8"]
|
64
|
+
langchain=["opentelemetry-instrumentation-langchain>=0.40.8"]
|
65
|
+
llamaindex=["opentelemetry-instrumentation-llamaindex>=0.40.8"]
|
66
|
+
marqo=["opentelemetry-instrumentation-marqo>=0.40.8"]
|
67
|
+
mcp=["opentelemetry-instrumentation-mcp>=0.40.8"]
|
68
|
+
milvus=["opentelemetry-instrumentation-milvus>=0.40.8"]
|
69
|
+
mistralai=["opentelemetry-instrumentation-mistralai>=0.40.8"]
|
70
|
+
ollama=["opentelemetry-instrumentation-ollama>=0.40.8"]
|
71
|
+
openai=["opentelemetry-instrumentation-openai>=0.40.8"]
|
72
|
+
pinecone=["opentelemetry-instrumentation-pinecone>=0.40.8"]
|
73
|
+
qdrant=["opentelemetry-instrumentation-qdrant>=0.40.8"]
|
74
|
+
replicate=["opentelemetry-instrumentation-replicate>=0.40.8"]
|
75
|
+
sagemaker=["opentelemetry-instrumentation-sagemaker>=0.40.8"]
|
76
|
+
together=["opentelemetry-instrumentation-together>=0.40.8"]
|
77
|
+
transformers=["opentelemetry-instrumentation-transformers>=0.40.8"]
|
78
|
+
vertexai=["opentelemetry-instrumentation-vertexai>=0.40.8"]
|
79
|
+
watsonx=["opentelemetry-instrumentation-watsonx>=0.40.8"]
|
80
|
+
weaviate=["opentelemetry-instrumentation-weaviate>=0.40.8"]
|
81
|
+
# `all` is the group added for convenience, if you want to install all
|
82
|
+
# the instrumentations.
|
83
|
+
# we suggest using package-manager-specific commands instead,
|
84
|
+
# like `uv add lmnr --all-extras`
|
85
|
+
all = [
|
86
|
+
"opentelemetry-instrumentation-alephalpha>=0.40.8",
|
87
|
+
"opentelemetry-instrumentation-anthropic>=0.40.8",
|
88
|
+
"opentelemetry-instrumentation-bedrock>=0.40.8",
|
89
|
+
"opentelemetry-instrumentation-chromadb>=0.40.8",
|
90
|
+
"opentelemetry-instrumentation-cohere>=0.40.8",
|
91
|
+
"opentelemetry-instrumentation-crewai>=0.40.8",
|
92
|
+
"opentelemetry-instrumentation-google-generativeai>=0.40.8",
|
93
|
+
"opentelemetry-instrumentation-groq>=0.40.8",
|
94
|
+
"opentelemetry-instrumentation-haystack>=0.40.8",
|
95
|
+
"opentelemetry-instrumentation-lancedb>=0.40.8",
|
96
|
+
"opentelemetry-instrumentation-langchain>=0.40.8",
|
97
|
+
"opentelemetry-instrumentation-llamaindex>=0.40.8",
|
98
|
+
"opentelemetry-instrumentation-marqo>=0.40.8",
|
99
|
+
"opentelemetry-instrumentation-mcp>=0.40.8",
|
100
|
+
"opentelemetry-instrumentation-milvus>=0.40.8",
|
101
|
+
"opentelemetry-instrumentation-mistralai>=0.40.8",
|
102
|
+
"opentelemetry-instrumentation-ollama>=0.40.8",
|
103
|
+
"opentelemetry-instrumentation-openai>=0.40.8",
|
104
|
+
"opentelemetry-instrumentation-pinecone>=0.40.8",
|
105
|
+
"opentelemetry-instrumentation-qdrant>=0.40.8",
|
106
|
+
"opentelemetry-instrumentation-replicate>=0.40.8",
|
107
|
+
"opentelemetry-instrumentation-sagemaker>=0.40.8",
|
108
|
+
"opentelemetry-instrumentation-together>=0.40.8",
|
109
|
+
"opentelemetry-instrumentation-transformers>=0.40.8",
|
110
|
+
"opentelemetry-instrumentation-vertexai>=0.40.8",
|
111
|
+
"opentelemetry-instrumentation-watsonx>=0.40.8",
|
112
|
+
"opentelemetry-instrumentation-weaviate>=0.40.8"
|
113
|
+
]
|
114
|
+
|
115
|
+
[dependency-groups]
|
116
|
+
dev = [
|
117
|
+
"autopep8>=2.3.2",
|
118
|
+
"flake8>=7.2.0",
|
119
|
+
"pytest>=8.3.5",
|
120
|
+
"pytest-sugar>=1.0.0",
|
121
|
+
"pytest-asyncio>=0.26.0",
|
122
|
+
"playwright>=1.52.0",
|
123
|
+
"vcrpy>=7.0.0",
|
124
|
+
"openai>=1.77.0",
|
125
|
+
"pytest-recording>=0.13.4",
|
126
|
+
"patchright>=1.52.3",
|
127
|
+
"google-genai>=1.19.0",
|
128
|
+
"langgraph>=0.4.8",
|
129
|
+
"langchain-core>=0.3.64",
|
130
|
+
"langchain>=0.3.25",
|
131
|
+
]
|
132
|
+
|
133
|
+
[build-system]
|
134
|
+
requires = ["poetry-core"]
|
135
|
+
build-backend = "poetry.core.masonry.api"
|
136
|
+
|
137
|
+
[tool.uv.workspace]
|
138
|
+
members = ["examples/fastapi-app"]
|
139
|
+
# we can move to uv_build, once it's more stable
|
140
|
+
# https://github.com/astral-sh/uv/issues/3957
|
141
|
+
# requires = ["uv_build>=0.6.16,<0.7"]
|
142
|
+
# build-backend = "uv_build"
|
@@ -1,6 +1,8 @@
|
|
1
1
|
from argparse import ArgumentParser
|
2
2
|
import asyncio
|
3
|
+
import glob
|
3
4
|
import importlib.util
|
5
|
+
import json
|
4
6
|
import os
|
5
7
|
import re
|
6
8
|
import sys
|
@@ -23,27 +25,27 @@ def add_cursor_rules():
|
|
23
25
|
"""Download laminar.mdc file from a hardcoded public URL and save it to .cursor/rules/laminar.mdc"""
|
24
26
|
# Hardcoded URL for the laminar.mdc file
|
25
27
|
url = "https://raw.githubusercontent.com/lmnr-ai/lmnr/dev/rules/laminar.mdc"
|
26
|
-
|
28
|
+
|
27
29
|
# Create .cursor/rules directory if it doesn't exist
|
28
30
|
rules_dir = Path(".cursor/rules")
|
29
31
|
rules_dir.mkdir(parents=True, exist_ok=True)
|
30
|
-
|
32
|
+
|
31
33
|
# Define the target file path
|
32
34
|
target_file = rules_dir / "laminar.mdc"
|
33
|
-
|
35
|
+
|
34
36
|
try:
|
35
37
|
LOG.info(f"Downloading laminar.mdc from {url}")
|
36
|
-
|
38
|
+
|
37
39
|
# Download the file
|
38
40
|
with urllib.request.urlopen(url) as response:
|
39
41
|
content = response.read()
|
40
|
-
|
42
|
+
|
41
43
|
# Write the content to the target file (this will overwrite if it exists)
|
42
|
-
with open(target_file,
|
44
|
+
with open(target_file, "wb") as f:
|
43
45
|
f.write(content)
|
44
|
-
|
46
|
+
|
45
47
|
LOG.info(f"Successfully downloaded laminar.mdc to {target_file}")
|
46
|
-
|
48
|
+
|
47
49
|
except urllib.error.URLError as e:
|
48
50
|
LOG.error(f"Failed to download file from {url}: {e}")
|
49
51
|
sys.exit(1)
|
@@ -55,7 +57,7 @@ def add_cursor_rules():
|
|
55
57
|
async def run_evaluation(args):
|
56
58
|
sys.path.append(os.getcwd())
|
57
59
|
|
58
|
-
if args.file
|
60
|
+
if len(args.file) == 0:
|
59
61
|
files = [
|
60
62
|
os.path.join(EVAL_DIR, f)
|
61
63
|
for f in os.listdir(EVAL_DIR)
|
@@ -71,9 +73,17 @@ async def run_evaluation(args):
|
|
71
73
|
LOG.info(f"Located {len(files)} evaluation files in {EVAL_DIR}")
|
72
74
|
|
73
75
|
else:
|
74
|
-
files = [
|
76
|
+
files = []
|
77
|
+
for pattern in args.file:
|
78
|
+
matches = glob.glob(pattern)
|
79
|
+
if matches:
|
80
|
+
files.extend(matches)
|
81
|
+
else:
|
82
|
+
# If no matches found, treat as literal filename
|
83
|
+
files.append(pattern)
|
75
84
|
|
76
85
|
prep_token = PREPARE_ONLY.set(True)
|
86
|
+
scores = []
|
77
87
|
try:
|
78
88
|
for file in files:
|
79
89
|
LOG.info(f"Running evaluation from {file}")
|
@@ -83,9 +93,9 @@ async def run_evaluation(args):
|
|
83
93
|
spec = importlib.util.spec_from_file_location(name, file)
|
84
94
|
if spec is None or spec.loader is None:
|
85
95
|
LOG.error(f"Could not load module specification from {file}")
|
86
|
-
if args.
|
87
|
-
|
88
|
-
|
96
|
+
if args.continue_on_error:
|
97
|
+
continue
|
98
|
+
return
|
89
99
|
mod = importlib.util.module_from_spec(spec)
|
90
100
|
sys.modules[name] = mod
|
91
101
|
|
@@ -93,19 +103,29 @@ async def run_evaluation(args):
|
|
93
103
|
evaluations: list[Evaluation] | None = EVALUATION_INSTANCES.get()
|
94
104
|
if evaluations is None:
|
95
105
|
LOG.warning("Evaluation instance not found")
|
96
|
-
if args.
|
97
|
-
|
98
|
-
|
106
|
+
if args.continue_on_error:
|
107
|
+
continue
|
108
|
+
return
|
99
109
|
|
100
110
|
LOG.info(f"Loaded {len(evaluations)} evaluations from {file}")
|
101
111
|
|
102
112
|
for evaluation in evaluations:
|
103
113
|
try:
|
104
|
-
await evaluation.run()
|
114
|
+
eval_scores = await evaluation.run()
|
115
|
+
scores.append(
|
116
|
+
{
|
117
|
+
"file": file,
|
118
|
+
"scores": eval_scores,
|
119
|
+
}
|
120
|
+
)
|
105
121
|
except Exception as e:
|
106
122
|
LOG.error(f"Error running evaluation: {e}")
|
107
|
-
if args.
|
123
|
+
if not args.continue_on_error:
|
108
124
|
raise
|
125
|
+
|
126
|
+
if args.output_file:
|
127
|
+
with open(args.output_file, "w") as f:
|
128
|
+
json.dump(scores, f, indent=2)
|
109
129
|
finally:
|
110
130
|
PREPARE_ONLY.reset(prep_token)
|
111
131
|
|
@@ -125,21 +145,27 @@ def cli():
|
|
125
145
|
)
|
126
146
|
parser_eval.add_argument(
|
127
147
|
"file",
|
128
|
-
nargs="
|
129
|
-
help="
|
148
|
+
nargs="*",
|
149
|
+
help="Files or a file containing the evaluation to run."
|
130
150
|
+ "If no file name is provided, all evaluation files in the `evals` directory are run as long"
|
131
151
|
+ "as they match *_eval.py or eval_*.py",
|
132
|
-
default=
|
152
|
+
default=[],
|
133
153
|
)
|
134
154
|
|
135
155
|
parser_eval.add_argument(
|
136
|
-
"--
|
156
|
+
"--continue-on-error",
|
137
157
|
action="store_true",
|
138
158
|
default=False,
|
139
|
-
help="
|
159
|
+
help="Continue execution upon errors",
|
160
|
+
)
|
161
|
+
|
162
|
+
parser_eval.add_argument(
|
163
|
+
"--output-file",
|
164
|
+
help="Output file to write the results to. Outputs are written in JSON format.",
|
165
|
+
nargs="?",
|
140
166
|
)
|
141
167
|
|
142
|
-
|
168
|
+
subparsers.add_parser(
|
143
169
|
"add-cursor-rules",
|
144
170
|
description="Download laminar.mdc file and add it to .cursor/rules",
|
145
171
|
help="Download laminar.mdc file and add it to .cursor/rules",
|
@@ -9,14 +9,15 @@ from opentelemetry import trace
|
|
9
9
|
from opentelemetry import context as context_api
|
10
10
|
from opentelemetry.trace import Span
|
11
11
|
|
12
|
-
from lmnr.opentelemetry_lib.tracing.context_properties import (
|
13
|
-
remove_association_properties,
|
14
|
-
update_association_properties,
|
15
|
-
)
|
16
12
|
from lmnr.sdk.utils import get_input_from_func_args, is_method
|
17
13
|
from lmnr.opentelemetry_lib import MAX_MANUAL_SPAN_PAYLOAD_SIZE
|
18
14
|
from lmnr.opentelemetry_lib.tracing.tracer import get_tracer
|
19
|
-
from lmnr.opentelemetry_lib.tracing.attributes import
|
15
|
+
from lmnr.opentelemetry_lib.tracing.attributes import (
|
16
|
+
ASSOCIATION_PROPERTIES,
|
17
|
+
SPAN_INPUT,
|
18
|
+
SPAN_OUTPUT,
|
19
|
+
SPAN_TYPE,
|
20
|
+
)
|
20
21
|
from lmnr.opentelemetry_lib.tracing import TracerWrapper
|
21
22
|
from lmnr.opentelemetry_lib.utils.json_encoder import JSONEncoder
|
22
23
|
|
@@ -56,11 +57,11 @@ def entity_method(
|
|
56
57
|
|
57
58
|
span_name = name or fn.__name__
|
58
59
|
|
59
|
-
if association_properties is not None:
|
60
|
-
update_association_properties(association_properties)
|
61
|
-
|
62
60
|
with get_tracer() as tracer:
|
63
61
|
span = tracer.start_span(span_name, attributes={SPAN_TYPE: span_type})
|
62
|
+
if association_properties is not None:
|
63
|
+
for key, value in association_properties.items():
|
64
|
+
span.set_attribute(f"{ASSOCIATION_PROPERTIES}.{key}", value)
|
64
65
|
|
65
66
|
ctx = trace.set_span_in_context(span, context_api.get_current())
|
66
67
|
ctx_token = context_api.attach(ctx)
|
@@ -119,8 +120,6 @@ def entity_method(
|
|
119
120
|
|
120
121
|
span.end()
|
121
122
|
context_api.detach(ctx_token)
|
122
|
-
if association_properties is not None:
|
123
|
-
remove_association_properties(association_properties)
|
124
123
|
return res
|
125
124
|
|
126
125
|
return wrap
|
@@ -145,11 +144,11 @@ def aentity_method(
|
|
145
144
|
|
146
145
|
span_name = name or fn.__name__
|
147
146
|
|
148
|
-
if association_properties is not None:
|
149
|
-
update_association_properties(association_properties)
|
150
|
-
|
151
147
|
with get_tracer() as tracer:
|
152
148
|
span = tracer.start_span(span_name, attributes={SPAN_TYPE: span_type})
|
149
|
+
if association_properties is not None:
|
150
|
+
for key, value in association_properties.items():
|
151
|
+
span.set_attribute(f"{ASSOCIATION_PROPERTIES}.{key}", value)
|
153
152
|
|
154
153
|
ctx = trace.set_span_in_context(span, context_api.get_current())
|
155
154
|
ctx_token = context_api.attach(ctx)
|
@@ -200,8 +199,6 @@ def aentity_method(
|
|
200
199
|
pass
|
201
200
|
|
202
201
|
span.end()
|
203
|
-
if association_properties is not None:
|
204
|
-
remove_association_properties(association_properties)
|
205
202
|
context_api.detach(ctx_token)
|
206
203
|
|
207
204
|
return res
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""OpenTelemetry Google Generative AI API instrumentation"""
|
2
2
|
|
3
3
|
from collections import defaultdict
|
4
|
+
import json
|
4
5
|
import logging
|
5
6
|
import os
|
6
7
|
from typing import AsyncGenerator, Callable, Collection, Generator
|
@@ -11,7 +12,9 @@ from .config import (
|
|
11
12
|
Config,
|
12
13
|
)
|
13
14
|
from .utils import (
|
15
|
+
ProcessedContentPart,
|
14
16
|
dont_throw,
|
17
|
+
get_content,
|
15
18
|
role_from_content_union,
|
16
19
|
set_span_attribute,
|
17
20
|
process_content_union,
|
@@ -159,7 +162,7 @@ def _set_request_attributes(span, args, kwargs):
|
|
159
162
|
set_span_attribute(
|
160
163
|
span,
|
161
164
|
f"{gen_ai_attributes.GEN_AI_PROMPT}.{i}.content",
|
162
|
-
process_content_union(system_instruction),
|
165
|
+
(get_content(process_content_union(system_instruction)) or {}).get("text", ""),
|
163
166
|
)
|
164
167
|
set_span_attribute(
|
165
168
|
span, f"{gen_ai_attributes.GEN_AI_PROMPT}.{i}.role", "system"
|
@@ -169,11 +172,42 @@ def _set_request_attributes(span, args, kwargs):
|
|
169
172
|
if not isinstance(contents, list):
|
170
173
|
contents = [contents]
|
171
174
|
for content in contents:
|
175
|
+
processed_content = process_content_union(content)
|
176
|
+
content_str = get_content(processed_content)
|
172
177
|
set_span_attribute(
|
173
178
|
span,
|
174
179
|
f"{gen_ai_attributes.GEN_AI_PROMPT}.{i}.content",
|
175
|
-
|
180
|
+
(
|
181
|
+
content_str
|
182
|
+
if isinstance(content_str, str)
|
183
|
+
else json.dumps(content_str)
|
184
|
+
),
|
176
185
|
)
|
186
|
+
blocks = (
|
187
|
+
processed_content
|
188
|
+
if isinstance(processed_content, list)
|
189
|
+
else [processed_content]
|
190
|
+
)
|
191
|
+
for j, block in enumerate(blocks):
|
192
|
+
block_dict = to_dict(block)
|
193
|
+
if not block_dict.get("function_call"):
|
194
|
+
continue
|
195
|
+
function_call = to_dict(block_dict.get("function_call", {}))
|
196
|
+
set_span_attribute(
|
197
|
+
span,
|
198
|
+
f"{gen_ai_attributes.GEN_AI_PROMPT}.{i}.tool_calls.{j}.name",
|
199
|
+
function_call.get("name"),
|
200
|
+
)
|
201
|
+
set_span_attribute(
|
202
|
+
span,
|
203
|
+
f"{gen_ai_attributes.GEN_AI_PROMPT}.{i}.tool_calls.{j}.id",
|
204
|
+
function_call.get("id"),
|
205
|
+
)
|
206
|
+
set_span_attribute(
|
207
|
+
span,
|
208
|
+
f"{gen_ai_attributes.GEN_AI_PROMPT}.{i}.tool_calls.{j}.arguments",
|
209
|
+
json.dumps(function_call.get("arguments")),
|
210
|
+
)
|
177
211
|
set_span_attribute(
|
178
212
|
span,
|
179
213
|
f"{gen_ai_attributes.GEN_AI_PROMPT}.{i}.role",
|
@@ -218,23 +252,64 @@ def _set_response_attributes(span, response: types.GenerateContentResponse):
|
|
218
252
|
)
|
219
253
|
|
220
254
|
if should_send_prompts():
|
221
|
-
|
222
|
-
|
255
|
+
set_span_attribute(
|
256
|
+
span, f"{gen_ai_attributes.GEN_AI_COMPLETION}.0.role", "model"
|
257
|
+
)
|
258
|
+
candidates_list = candidates if isinstance(candidates, list) else [candidates]
|
259
|
+
for i, candidate in enumerate(candidates_list):
|
260
|
+
processed_content = process_content_union(candidate.content)
|
261
|
+
if isinstance(processed_content, list):
|
262
|
+
if all(
|
263
|
+
isinstance(item, dict) and item.get("type") == "text"
|
264
|
+
for item in processed_content
|
265
|
+
):
|
266
|
+
content_str = processed_content[0]["text"]
|
267
|
+
elif all(
|
268
|
+
isinstance(item, ProcessedContentPart) and item.content
|
269
|
+
for item in processed_content
|
270
|
+
):
|
271
|
+
content_str = processed_content[0].content
|
272
|
+
else:
|
273
|
+
content_str = get_content(processed_content)
|
274
|
+
else:
|
275
|
+
content_str = get_content(processed_content)
|
276
|
+
set_span_attribute(
|
277
|
+
span, f"{gen_ai_attributes.GEN_AI_COMPLETION}.{i}.role", "model"
|
278
|
+
)
|
279
|
+
set_span_attribute(
|
280
|
+
span,
|
281
|
+
f"{gen_ai_attributes.GEN_AI_COMPLETION}.{i}.content",
|
282
|
+
(
|
283
|
+
content_str
|
284
|
+
if isinstance(content_str, str)
|
285
|
+
else json.dumps(content_str)
|
286
|
+
),
|
287
|
+
)
|
288
|
+
blocks = (
|
289
|
+
processed_content
|
290
|
+
if isinstance(processed_content, list)
|
291
|
+
else [processed_content]
|
292
|
+
)
|
293
|
+
for j, block in enumerate(blocks):
|
294
|
+
block_dict = to_dict(block)
|
295
|
+
if not block_dict.get("function_call"):
|
296
|
+
continue
|
297
|
+
function_call = to_dict(block_dict.get("function_call", {}))
|
223
298
|
set_span_attribute(
|
224
299
|
span,
|
225
|
-
f"{gen_ai_attributes.GEN_AI_COMPLETION}.{i}.
|
226
|
-
|
300
|
+
f"{gen_ai_attributes.GEN_AI_COMPLETION}.{i}.tool_calls.{j}.name",
|
301
|
+
function_call.get("name"),
|
227
302
|
)
|
228
303
|
set_span_attribute(
|
229
|
-
span,
|
304
|
+
span,
|
305
|
+
f"{gen_ai_attributes.GEN_AI_COMPLETION}.{i}.tool_calls.{j}.id",
|
306
|
+
function_call.get("id"),
|
307
|
+
)
|
308
|
+
set_span_attribute(
|
309
|
+
span,
|
310
|
+
f"{gen_ai_attributes.GEN_AI_COMPLETION}.{i}.tool_calls.{j}.arguments",
|
311
|
+
json.dumps(function_call.get("arguments")),
|
230
312
|
)
|
231
|
-
else:
|
232
|
-
set_span_attribute(
|
233
|
-
span, f"{gen_ai_attributes.GEN_AI_COMPLETION}.0.content", response.text
|
234
|
-
)
|
235
|
-
set_span_attribute(
|
236
|
-
span, f"{gen_ai_attributes.GEN_AI_COMPLETION}.0.role", "assistant"
|
237
|
-
)
|
238
313
|
|
239
314
|
|
240
315
|
@dont_throw
|
@@ -433,7 +508,7 @@ class GoogleGenAiSdkInstrumentor(BaseInstrumentor):
|
|
433
508
|
|
434
509
|
def _instrument(self, **kwargs):
|
435
510
|
tracer_provider = kwargs.get("tracer_provider")
|
436
|
-
tracer = get_tracer(__name__, "0.0.
|
511
|
+
tracer = get_tracer(__name__, "0.0.1a1", tracer_provider)
|
437
512
|
|
438
513
|
for wrapped_method in WRAPPED_METHODS:
|
439
514
|
wrap_function_wrapper(
|