lmnr 0.4.57__tar.gz → 0.4.59__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.
Files changed (35) hide show
  1. {lmnr-0.4.57 → lmnr-0.4.59}/PKG-INFO +51 -51
  2. lmnr-0.4.59/pyproject.toml +122 -0
  3. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/config/__init__.py +3 -0
  4. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/decorators/base.py +45 -27
  5. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/tracing/attributes.py +1 -0
  6. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/tracing/tracing.py +16 -1
  7. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/sdk/browser/playwright_patch.py +93 -40
  8. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/sdk/decorators.py +16 -3
  9. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/sdk/evaluations.py +2 -3
  10. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/sdk/laminar.py +37 -14
  11. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/sdk/types.py +5 -3
  12. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/sdk/utils.py +1 -1
  13. lmnr-0.4.57/pyproject.toml +0 -122
  14. {lmnr-0.4.57 → lmnr-0.4.59}/LICENSE +0 -0
  15. {lmnr-0.4.57 → lmnr-0.4.59}/README.md +0 -0
  16. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/__init__.py +0 -0
  17. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/cli.py +0 -0
  18. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/.flake8 +0 -0
  19. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/.python-version +0 -0
  20. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/__init__.py +0 -0
  21. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/decorators/__init__.py +0 -0
  22. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/instruments.py +0 -0
  23. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/tracing/__init__.py +0 -0
  24. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/tracing/content_allow_list.py +0 -0
  25. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/tracing/context_manager.py +0 -0
  26. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/utils/__init__.py +0 -0
  27. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/utils/in_memory_span_exporter.py +0 -0
  28. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/utils/json_encoder.py +0 -0
  29. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/utils/package_check.py +0 -0
  30. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/openllmetry_sdk/version.py +0 -0
  31. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/sdk/__init__.py +0 -0
  32. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/sdk/browser/__init__.py +0 -0
  33. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/sdk/datasets.py +0 -0
  34. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/sdk/eval_control.py +0 -0
  35. {lmnr-0.4.57 → lmnr-0.4.59}/src/lmnr/sdk/log.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: lmnr
3
- Version: 0.4.57
3
+ Version: 0.4.59
4
4
  Summary: Python SDK for Laminar
5
5
  License: Apache-2.0
6
6
  Author: lmnr.ai
@@ -45,60 +45,60 @@ Requires-Dist: grpcio (<1.68.0)
45
45
  Requires-Dist: opentelemetry-api (>=1.28.0)
46
46
  Requires-Dist: opentelemetry-exporter-otlp-proto-grpc (>=1.28.0)
47
47
  Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.28.0)
48
- Requires-Dist: opentelemetry-instrumentation-alephalpha (>=0.36.1) ; extra == "alephalpha"
49
- Requires-Dist: opentelemetry-instrumentation-alephalpha (>=0.36.1) ; extra == "all"
50
- Requires-Dist: opentelemetry-instrumentation-anthropic (>=0.36.1) ; extra == "all"
51
- Requires-Dist: opentelemetry-instrumentation-anthropic (>=0.36.1) ; extra == "anthropic"
52
- Requires-Dist: opentelemetry-instrumentation-bedrock (>=0.36.1) ; extra == "all"
53
- Requires-Dist: opentelemetry-instrumentation-bedrock (>=0.36.1) ; extra == "bedrock"
54
- Requires-Dist: opentelemetry-instrumentation-chromadb (>=0.36.1) ; extra == "all"
55
- Requires-Dist: opentelemetry-instrumentation-chromadb (>=0.36.1) ; extra == "chromadb"
56
- Requires-Dist: opentelemetry-instrumentation-cohere (>=0.36.1) ; extra == "all"
57
- Requires-Dist: opentelemetry-instrumentation-cohere (>=0.36.1) ; extra == "cohere"
58
- Requires-Dist: opentelemetry-instrumentation-google-generativeai (>=0.36.1) ; extra == "all"
59
- Requires-Dist: opentelemetry-instrumentation-google-generativeai (>=0.36.1) ; extra == "google-generativeai"
60
- Requires-Dist: opentelemetry-instrumentation-groq (>=0.36.1) ; extra == "all"
61
- Requires-Dist: opentelemetry-instrumentation-groq (>=0.36.1) ; extra == "groq"
62
- Requires-Dist: opentelemetry-instrumentation-haystack (>=0.36.1) ; extra == "all"
63
- Requires-Dist: opentelemetry-instrumentation-haystack (>=0.36.1) ; extra == "haystack"
64
- Requires-Dist: opentelemetry-instrumentation-lancedb (>=0.36.1) ; extra == "all"
65
- Requires-Dist: opentelemetry-instrumentation-lancedb (>=0.36.1) ; extra == "lancedb"
66
- Requires-Dist: opentelemetry-instrumentation-langchain (>=0.36.1) ; extra == "all"
67
- Requires-Dist: opentelemetry-instrumentation-langchain (>=0.36.1) ; extra == "langchain"
68
- Requires-Dist: opentelemetry-instrumentation-llamaindex (>=0.36.1) ; extra == "all"
69
- Requires-Dist: opentelemetry-instrumentation-llamaindex (>=0.36.1) ; extra == "llamaindex"
70
- Requires-Dist: opentelemetry-instrumentation-marqo (>=0.36.1) ; extra == "all"
71
- Requires-Dist: opentelemetry-instrumentation-marqo (>=0.36.1) ; extra == "marqo"
72
- Requires-Dist: opentelemetry-instrumentation-milvus (>=0.36.1) ; extra == "all"
73
- Requires-Dist: opentelemetry-instrumentation-milvus (>=0.36.1) ; extra == "milvus"
74
- Requires-Dist: opentelemetry-instrumentation-mistralai (>=0.36.1) ; extra == "all"
75
- Requires-Dist: opentelemetry-instrumentation-mistralai (>=0.36.1) ; extra == "mistralai"
76
- Requires-Dist: opentelemetry-instrumentation-ollama (>=0.36.1) ; extra == "all"
77
- Requires-Dist: opentelemetry-instrumentation-ollama (>=0.36.1) ; extra == "ollama"
78
- Requires-Dist: opentelemetry-instrumentation-openai (>=0.36.1) ; extra == "all"
79
- Requires-Dist: opentelemetry-instrumentation-openai (>=0.36.1) ; extra == "openai"
80
- Requires-Dist: opentelemetry-instrumentation-pinecone (>=0.36.1) ; extra == "all"
81
- Requires-Dist: opentelemetry-instrumentation-pinecone (>=0.36.1) ; extra == "pinecone"
82
- Requires-Dist: opentelemetry-instrumentation-qdrant (>=0.36.1) ; extra == "all"
83
- Requires-Dist: opentelemetry-instrumentation-qdrant (>=0.36.1) ; extra == "qdrant"
84
- Requires-Dist: opentelemetry-instrumentation-replicate (>=0.36.1) ; extra == "all"
85
- Requires-Dist: opentelemetry-instrumentation-replicate (>=0.36.1) ; extra == "replicate"
48
+ Requires-Dist: opentelemetry-instrumentation-alephalpha (>=0.37.1) ; extra == "alephalpha"
49
+ Requires-Dist: opentelemetry-instrumentation-alephalpha (>=0.37.1) ; extra == "all"
50
+ Requires-Dist: opentelemetry-instrumentation-anthropic (>=0.37.1) ; extra == "all"
51
+ Requires-Dist: opentelemetry-instrumentation-anthropic (>=0.37.1) ; extra == "anthropic"
52
+ Requires-Dist: opentelemetry-instrumentation-bedrock (>=0.37.1) ; extra == "all"
53
+ Requires-Dist: opentelemetry-instrumentation-bedrock (>=0.37.1) ; extra == "bedrock"
54
+ Requires-Dist: opentelemetry-instrumentation-chromadb (>=0.37.1) ; extra == "all"
55
+ Requires-Dist: opentelemetry-instrumentation-chromadb (>=0.37.1) ; extra == "chromadb"
56
+ Requires-Dist: opentelemetry-instrumentation-cohere (>=0.37.1) ; extra == "all"
57
+ Requires-Dist: opentelemetry-instrumentation-cohere (>=0.37.1) ; extra == "cohere"
58
+ Requires-Dist: opentelemetry-instrumentation-google-generativeai (>=0.37.1) ; extra == "all"
59
+ Requires-Dist: opentelemetry-instrumentation-google-generativeai (>=0.37.1) ; extra == "google-generativeai"
60
+ Requires-Dist: opentelemetry-instrumentation-groq (>=0.37.1) ; extra == "all"
61
+ Requires-Dist: opentelemetry-instrumentation-groq (>=0.37.1) ; extra == "groq"
62
+ Requires-Dist: opentelemetry-instrumentation-haystack (>=0.37.1) ; extra == "all"
63
+ Requires-Dist: opentelemetry-instrumentation-haystack (>=0.37.1) ; extra == "haystack"
64
+ Requires-Dist: opentelemetry-instrumentation-lancedb (>=0.37.1) ; extra == "all"
65
+ Requires-Dist: opentelemetry-instrumentation-lancedb (>=0.37.1) ; extra == "lancedb"
66
+ Requires-Dist: opentelemetry-instrumentation-langchain (>=0.37.1) ; extra == "all"
67
+ Requires-Dist: opentelemetry-instrumentation-langchain (>=0.37.1) ; extra == "langchain"
68
+ Requires-Dist: opentelemetry-instrumentation-llamaindex (>=0.37.1) ; extra == "all"
69
+ Requires-Dist: opentelemetry-instrumentation-llamaindex (>=0.37.1) ; extra == "llamaindex"
70
+ Requires-Dist: opentelemetry-instrumentation-marqo (>=0.37.1) ; extra == "all"
71
+ Requires-Dist: opentelemetry-instrumentation-marqo (>=0.37.1) ; extra == "marqo"
72
+ Requires-Dist: opentelemetry-instrumentation-milvus (>=0.37.1) ; extra == "all"
73
+ Requires-Dist: opentelemetry-instrumentation-milvus (>=0.37.1) ; extra == "milvus"
74
+ Requires-Dist: opentelemetry-instrumentation-mistralai (>=0.37.1) ; extra == "all"
75
+ Requires-Dist: opentelemetry-instrumentation-mistralai (>=0.37.1) ; extra == "mistralai"
76
+ Requires-Dist: opentelemetry-instrumentation-ollama (>=0.37.1) ; extra == "all"
77
+ Requires-Dist: opentelemetry-instrumentation-ollama (>=0.37.1) ; extra == "ollama"
78
+ Requires-Dist: opentelemetry-instrumentation-openai (>=0.37.1) ; extra == "all"
79
+ Requires-Dist: opentelemetry-instrumentation-openai (>=0.37.1) ; extra == "openai"
80
+ Requires-Dist: opentelemetry-instrumentation-pinecone (>=0.37.1) ; extra == "all"
81
+ Requires-Dist: opentelemetry-instrumentation-pinecone (>=0.37.1) ; extra == "pinecone"
82
+ Requires-Dist: opentelemetry-instrumentation-qdrant (>=0.37.1) ; extra == "all"
83
+ Requires-Dist: opentelemetry-instrumentation-qdrant (>=0.37.1) ; extra == "qdrant"
84
+ Requires-Dist: opentelemetry-instrumentation-replicate (>=0.37.1) ; extra == "all"
85
+ Requires-Dist: opentelemetry-instrumentation-replicate (>=0.37.1) ; extra == "replicate"
86
86
  Requires-Dist: opentelemetry-instrumentation-requests (>=0.50b0)
87
- Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.36.1) ; extra == "all"
88
- Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.36.1) ; extra == "sagemaker"
87
+ Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.37.1) ; extra == "all"
88
+ Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.37.1) ; extra == "sagemaker"
89
89
  Requires-Dist: opentelemetry-instrumentation-sqlalchemy (>=0.50b0)
90
90
  Requires-Dist: opentelemetry-instrumentation-threading (>=0.50b0)
91
- Requires-Dist: opentelemetry-instrumentation-together (>=0.36.1) ; extra == "all"
92
- Requires-Dist: opentelemetry-instrumentation-together (>=0.36.1) ; extra == "together"
93
- Requires-Dist: opentelemetry-instrumentation-transformers (>=0.36.1) ; extra == "all"
94
- Requires-Dist: opentelemetry-instrumentation-transformers (>=0.36.1) ; extra == "transformers"
91
+ Requires-Dist: opentelemetry-instrumentation-together (>=0.37.1) ; extra == "all"
92
+ Requires-Dist: opentelemetry-instrumentation-together (>=0.37.1) ; extra == "together"
93
+ Requires-Dist: opentelemetry-instrumentation-transformers (>=0.37.1) ; extra == "all"
94
+ Requires-Dist: opentelemetry-instrumentation-transformers (>=0.37.1) ; extra == "transformers"
95
95
  Requires-Dist: opentelemetry-instrumentation-urllib3 (>=0.50b0)
96
- Requires-Dist: opentelemetry-instrumentation-vertexai (>=0.36.1) ; extra == "all"
97
- Requires-Dist: opentelemetry-instrumentation-vertexai (>=0.36.1) ; extra == "vertexai"
98
- Requires-Dist: opentelemetry-instrumentation-watsonx (>=0.36.1) ; extra == "all"
99
- Requires-Dist: opentelemetry-instrumentation-watsonx (>=0.36.1) ; extra == "watsonx"
100
- Requires-Dist: opentelemetry-instrumentation-weaviate (>=0.36.1) ; extra == "all"
101
- Requires-Dist: opentelemetry-instrumentation-weaviate (>=0.36.1) ; extra == "weaviate"
96
+ Requires-Dist: opentelemetry-instrumentation-vertexai (>=0.37.1) ; extra == "all"
97
+ Requires-Dist: opentelemetry-instrumentation-vertexai (>=0.37.1) ; extra == "vertexai"
98
+ Requires-Dist: opentelemetry-instrumentation-watsonx (>=0.37.1) ; extra == "all"
99
+ Requires-Dist: opentelemetry-instrumentation-watsonx (>=0.37.1) ; extra == "watsonx"
100
+ Requires-Dist: opentelemetry-instrumentation-weaviate (>=0.37.1) ; extra == "all"
101
+ Requires-Dist: opentelemetry-instrumentation-weaviate (>=0.37.1) ; extra == "weaviate"
102
102
  Requires-Dist: opentelemetry-sdk (>=1.28.0)
103
103
  Requires-Dist: opentelemetry-semantic-conventions-ai (>=0.4.2)
104
104
  Requires-Dist: pydantic (>=2.0.3)
@@ -0,0 +1,122 @@
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.4.59"
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.9,<4"
16
+ license = "Apache-2.0"
17
+ dependencies = [
18
+ "pydantic (>=2.0.3)",
19
+ "requests (>=2.0)",
20
+ "python-dotenv (>=1.0)",
21
+ "opentelemetry-api (>=1.28.0)",
22
+ "opentelemetry-sdk (>=1.28.0)",
23
+ "opentelemetry-exporter-otlp-proto-http (>=1.28.0)",
24
+ "opentelemetry-exporter-otlp-proto-grpc (>=1.28.0)",
25
+ "opentelemetry-instrumentation-requests (>=0.50b0)",
26
+ "opentelemetry-instrumentation-sqlalchemy (>=0.50b0)",
27
+ "opentelemetry-instrumentation-urllib3 (>=0.50b0)",
28
+ "opentelemetry-instrumentation-threading (>=0.50b0)",
29
+ "opentelemetry-semantic-conventions-ai (>=0.4.2)",
30
+ "tqdm (>=4.0)",
31
+ "argparse (>=1.0)",
32
+ "aiohttp (>=3.0)",
33
+ "tenacity (>=8.0)",
34
+ # explicitly freeze grpcio. Since 1.68.0, grpcio writes a warning message
35
+ # that looks scary, but is harmless.
36
+ # WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
37
+ # E0000 00:00:1737439981.199902 9456033 init.cc:229] grpc_wait_for_shutdown_with_timeout() timed out.
38
+ #
39
+ # Related issue:
40
+ # 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
41
+ # https://github.com/grpc/grpc/issues/38490
42
+ "grpcio<1.68.0",
43
+ ]
44
+
45
+ [project.scripts]
46
+ lmnr = "lmnr.cli:cli"
47
+
48
+ [project.optional-dependencies]
49
+ # List of all possible extras. You can specify one or more of these extras
50
+ # when installing the package, using any of the following examples:
51
+ # `pip install 'lmnr[anthropic,openai]'`
52
+ # `uv pip install 'lmnr[anthropic,openai]'`
53
+ # `uv add lmnr --extra anthropic --extra openai`
54
+ # `poetry add 'lmnr[anthropic,openai]'`
55
+
56
+ alephalpha=["opentelemetry-instrumentation-alephalpha>=0.37.1"]
57
+ anthropic=["opentelemetry-instrumentation-anthropic>=0.37.1"]
58
+ bedrock=["opentelemetry-instrumentation-bedrock>=0.37.1"]
59
+ chromadb=["opentelemetry-instrumentation-chromadb>=0.37.1"]
60
+ cohere=["opentelemetry-instrumentation-cohere>=0.37.1"]
61
+ google-generativeai=["opentelemetry-instrumentation-google-generativeai>=0.37.1"]
62
+ groq=["opentelemetry-instrumentation-groq>=0.37.1"]
63
+ haystack=["opentelemetry-instrumentation-haystack>=0.37.1"]
64
+ lancedb=["opentelemetry-instrumentation-lancedb>=0.37.1"]
65
+ langchain=["opentelemetry-instrumentation-langchain>=0.37.1"]
66
+ llamaindex=["opentelemetry-instrumentation-llamaindex>=0.37.1"]
67
+ marqo=["opentelemetry-instrumentation-marqo>=0.37.1"]
68
+ milvus=["opentelemetry-instrumentation-milvus>=0.37.1"]
69
+ mistralai=["opentelemetry-instrumentation-mistralai>=0.37.1"]
70
+ ollama=["opentelemetry-instrumentation-ollama>=0.37.1"]
71
+ openai=["opentelemetry-instrumentation-openai>=0.37.1"]
72
+ pinecone=["opentelemetry-instrumentation-pinecone>=0.37.1"]
73
+ qdrant=["opentelemetry-instrumentation-qdrant>=0.37.1"]
74
+ replicate=["opentelemetry-instrumentation-replicate>=0.37.1"]
75
+ sagemaker=["opentelemetry-instrumentation-sagemaker>=0.37.1"]
76
+ together=["opentelemetry-instrumentation-together>=0.37.1"]
77
+ transformers=["opentelemetry-instrumentation-transformers>=0.37.1"]
78
+ vertexai=["opentelemetry-instrumentation-vertexai>=0.37.1"]
79
+ watsonx=["opentelemetry-instrumentation-watsonx>=0.37.1"]
80
+ weaviate=["opentelemetry-instrumentation-weaviate>=0.37.1"]
81
+ # `all` is the group added for convenience, if you want to install all
82
+ # the instrumentations.
83
+ all = [
84
+ "opentelemetry-instrumentation-alephalpha>=0.37.1",
85
+ "opentelemetry-instrumentation-anthropic>=0.37.1",
86
+ "opentelemetry-instrumentation-bedrock>=0.37.1",
87
+ "opentelemetry-instrumentation-chromadb>=0.37.1",
88
+ "opentelemetry-instrumentation-cohere>=0.37.1",
89
+ "opentelemetry-instrumentation-google-generativeai>=0.37.1",
90
+ "opentelemetry-instrumentation-groq>=0.37.1",
91
+ "opentelemetry-instrumentation-haystack>=0.37.1",
92
+ "opentelemetry-instrumentation-lancedb>=0.37.1",
93
+ "opentelemetry-instrumentation-langchain>=0.37.1",
94
+ "opentelemetry-instrumentation-llamaindex>=0.37.1",
95
+ "opentelemetry-instrumentation-marqo>=0.37.1",
96
+ "opentelemetry-instrumentation-milvus>=0.37.1",
97
+ "opentelemetry-instrumentation-mistralai>=0.37.1",
98
+ "opentelemetry-instrumentation-ollama>=0.37.1",
99
+ "opentelemetry-instrumentation-openai>=0.37.1",
100
+ "opentelemetry-instrumentation-pinecone>=0.37.1",
101
+ "opentelemetry-instrumentation-qdrant>=0.37.1",
102
+ "opentelemetry-instrumentation-replicate>=0.37.1",
103
+ "opentelemetry-instrumentation-sagemaker>=0.37.1",
104
+ "opentelemetry-instrumentation-together>=0.37.1",
105
+ "opentelemetry-instrumentation-transformers>=0.37.1",
106
+ "opentelemetry-instrumentation-vertexai>=0.37.1",
107
+ "opentelemetry-instrumentation-watsonx>=0.37.1",
108
+ "opentelemetry-instrumentation-weaviate>=0.37.1"
109
+ ]
110
+
111
+ [dependency-groups]
112
+ dev = [
113
+ "autopep8",
114
+ "flake8",
115
+ "pytest>=8.3.4",
116
+ "pytest-sugar",
117
+ "pytest-asyncio>=0.25.2"
118
+ ]
119
+
120
+ [build-system]
121
+ requires = ["poetry-core"]
122
+ build-backend = "poetry.core.masonry.api"
@@ -7,3 +7,6 @@ def is_tracing_enabled() -> bool:
7
7
 
8
8
  def is_content_tracing_enabled() -> bool:
9
9
  return (os.getenv("TRACELOOP_TRACE_CONTENT") or "true").lower() == "true"
10
+
11
+
12
+ MAX_MANUAL_SPAN_PAYLOAD_SIZE = 1024 * 1024 # 1MB
@@ -4,7 +4,7 @@ import logging
4
4
  import os
5
5
  import pydantic
6
6
  import types
7
- from typing import Any, Optional
7
+ from typing import Any, Literal, Optional, Union
8
8
 
9
9
  from opentelemetry import trace
10
10
  from opentelemetry import context as context_api
@@ -12,9 +12,10 @@ from opentelemetry.trace import Span
12
12
 
13
13
  from lmnr.sdk.utils import get_input_from_func_args, is_method
14
14
  from lmnr.openllmetry_sdk.tracing import get_tracer
15
- from lmnr.openllmetry_sdk.tracing.attributes import SPAN_INPUT, SPAN_OUTPUT
15
+ from lmnr.openllmetry_sdk.tracing.attributes import SPAN_INPUT, SPAN_OUTPUT, SPAN_TYPE
16
16
  from lmnr.openllmetry_sdk.tracing.tracing import TracerWrapper
17
17
  from lmnr.openllmetry_sdk.utils.json_encoder import JSONEncoder
18
+ from lmnr.openllmetry_sdk.config import MAX_MANUAL_SPAN_PAYLOAD_SIZE
18
19
 
19
20
 
20
21
  class CustomJSONEncoder(JSONEncoder):
@@ -38,6 +39,9 @@ def json_dumps(data: dict) -> str:
38
39
 
39
40
  def entity_method(
40
41
  name: Optional[str] = None,
42
+ ignore_input: bool = False,
43
+ ignore_output: bool = False,
44
+ span_type: Union[Literal["DEFAULT"], Literal["LLM"], Literal["TOOL"]] = "DEFAULT",
41
45
  ):
42
46
  def decorate(fn):
43
47
  @wraps(fn)
@@ -48,21 +52,22 @@ def entity_method(
48
52
  span_name = name or fn.__name__
49
53
 
50
54
  with get_tracer() as tracer:
51
- span = tracer.start_span(span_name)
55
+ span = tracer.start_span(span_name, attributes={SPAN_TYPE: span_type})
52
56
 
53
57
  ctx = trace.set_span_in_context(span, context_api.get_current())
54
58
  ctx_token = context_api.attach(ctx)
55
59
 
56
60
  try:
57
- if _should_send_prompts():
58
- span.set_attribute(
59
- SPAN_INPUT,
60
- json_dumps(
61
- get_input_from_func_args(
62
- fn, is_method(fn), args, kwargs
63
- )
64
- ),
61
+ if _should_send_prompts() and not ignore_input:
62
+ inp = json_dumps(
63
+ get_input_from_func_args(fn, is_method(fn), args, kwargs)
65
64
  )
65
+ if len(inp) > MAX_MANUAL_SPAN_PAYLOAD_SIZE:
66
+ span.set_attribute(
67
+ SPAN_INPUT, "Laminar: input too large to record"
68
+ )
69
+ else:
70
+ span.set_attribute(SPAN_INPUT, inp)
66
71
  except TypeError:
67
72
  pass
68
73
 
@@ -78,11 +83,14 @@ def entity_method(
78
83
  return _handle_generator(span, res)
79
84
 
80
85
  try:
81
- if _should_send_prompts():
82
- span.set_attribute(
83
- SPAN_OUTPUT,
84
- json_dumps(res),
85
- )
86
+ if _should_send_prompts() and not ignore_output:
87
+ output = json_dumps(res)
88
+ if len(output) > MAX_MANUAL_SPAN_PAYLOAD_SIZE:
89
+ span.set_attribute(
90
+ SPAN_OUTPUT, "Laminar: output too large to record"
91
+ )
92
+ else:
93
+ span.set_attribute(SPAN_OUTPUT, output)
86
94
  except TypeError:
87
95
  pass
88
96
 
@@ -99,6 +107,9 @@ def entity_method(
99
107
  # Async Decorators
100
108
  def aentity_method(
101
109
  name: Optional[str] = None,
110
+ ignore_input: bool = False,
111
+ ignore_output: bool = False,
112
+ span_type: Union[Literal["DEFAULT"], Literal["LLM"], Literal["TOOL"]] = "DEFAULT",
102
113
  ):
103
114
  def decorate(fn):
104
115
  @wraps(fn)
@@ -109,21 +120,22 @@ def aentity_method(
109
120
  span_name = name or fn.__name__
110
121
 
111
122
  with get_tracer() as tracer:
112
- span = tracer.start_span(span_name)
123
+ span = tracer.start_span(span_name, attributes={SPAN_TYPE: span_type})
113
124
 
114
125
  ctx = trace.set_span_in_context(span, context_api.get_current())
115
126
  ctx_token = context_api.attach(ctx)
116
127
 
117
128
  try:
118
- if _should_send_prompts():
119
- span.set_attribute(
120
- SPAN_INPUT,
121
- json_dumps(
122
- get_input_from_func_args(
123
- fn, is_method(fn), args, kwargs
124
- )
125
- ),
129
+ if _should_send_prompts() and not ignore_input:
130
+ inp = json_dumps(
131
+ get_input_from_func_args(fn, is_method(fn), args, kwargs)
126
132
  )
133
+ if len(inp) > MAX_MANUAL_SPAN_PAYLOAD_SIZE:
134
+ span.set_attribute(
135
+ SPAN_INPUT, "Laminar: input too large to record"
136
+ )
137
+ else:
138
+ span.set_attribute(SPAN_INPUT, inp)
127
139
  except TypeError:
128
140
  pass
129
141
 
@@ -139,8 +151,14 @@ def aentity_method(
139
151
  return await _ahandle_generator(span, ctx_token, res)
140
152
 
141
153
  try:
142
- if _should_send_prompts():
143
- span.set_attribute(SPAN_OUTPUT, json_dumps(res))
154
+ if _should_send_prompts() and not ignore_output:
155
+ output = json_dumps(res)
156
+ if len(output) > MAX_MANUAL_SPAN_PAYLOAD_SIZE:
157
+ span.set_attribute(
158
+ SPAN_OUTPUT, "Laminar: output too large to record"
159
+ )
160
+ else:
161
+ span.set_attribute(SPAN_OUTPUT, output)
144
162
  except TypeError:
145
163
  pass
146
164
 
@@ -5,6 +5,7 @@ SPAN_INPUT = "lmnr.span.input"
5
5
  SPAN_OUTPUT = "lmnr.span.output"
6
6
  SPAN_TYPE = "lmnr.span.type"
7
7
  SPAN_PATH = "lmnr.span.path"
8
+ SPAN_IDS_PATH = "lmnr.span.ids_path"
8
9
  SPAN_INSTRUMENTATION_SOURCE = "lmnr.span.instrumentation_source"
9
10
  OVERRIDE_PARENT_SPAN = "lmnr.internal.override_parent_span"
10
11
 
@@ -1,7 +1,7 @@
1
1
  import atexit
2
2
  import copy
3
3
  import logging
4
-
4
+ import uuid
5
5
 
6
6
  from contextvars import Context
7
7
  from lmnr.sdk.log import VerboseColorfulFormatter
@@ -9,6 +9,7 @@ from lmnr.openllmetry_sdk.instruments import Instruments
9
9
  from lmnr.sdk.browser import init_browser_tracing
10
10
  from lmnr.openllmetry_sdk.tracing.attributes import (
11
11
  ASSOCIATION_PROPERTIES,
12
+ SPAN_IDS_PATH,
12
13
  SPAN_INSTRUMENTATION_SOURCE,
13
14
  SPAN_PATH,
14
15
  TRACING_LEVEL,
@@ -72,6 +73,7 @@ class TracerWrapper(object):
72
73
  __tracer_provider: TracerProvider = None
73
74
  __logger: logging.Logger = None
74
75
  __span_id_to_path: dict[int, list[str]] = {}
76
+ __span_id_lists: dict[int, list[str]] = {}
75
77
 
76
78
  def __new__(
77
79
  cls,
@@ -162,10 +164,18 @@ class TracerWrapper(object):
162
164
  parent_span_path = span_path_in_context or (
163
165
  self.__span_id_to_path.get(span.parent.span_id) if span.parent else None
164
166
  )
167
+ parent_span_ids_path = (
168
+ self.__span_id_lists.get(span.parent.span_id, []) if span.parent else []
169
+ )
165
170
  span_path = parent_span_path + [span.name] if parent_span_path else [span.name]
171
+ span_ids_path = parent_span_ids_path + [
172
+ str(uuid.UUID(int=span.get_span_context().span_id))
173
+ ]
166
174
  span.set_attribute(SPAN_PATH, span_path)
175
+ span.set_attribute(SPAN_IDS_PATH, span_ids_path)
167
176
  set_value("span_path", span_path, get_current())
168
177
  self.__span_id_to_path[span.get_span_context().span_id] = span_path
178
+ self.__span_id_lists[span.get_span_context().span_id] = span_ids_path
169
179
 
170
180
  span.set_attribute(SPAN_INSTRUMENTATION_SOURCE, "python")
171
181
 
@@ -203,6 +213,7 @@ class TracerWrapper(object):
203
213
  def clear(cls):
204
214
  # Any state cleanup. Now used in between tests
205
215
  cls.__span_id_to_path = {}
216
+ cls.__span_id_lists = {}
206
217
 
207
218
  def flush(self):
208
219
  self.__spans_processor.force_flush()
@@ -432,6 +443,10 @@ def init_openai_instrumentor(should_enrich_metrics: bool):
432
443
  instrumentor = OpenAIInstrumentor(
433
444
  enrich_assistant=should_enrich_metrics,
434
445
  enrich_token_usage=should_enrich_metrics,
446
+ # Default in the package provided is an empty function, which
447
+ # results in dropping the image data if we don't explicitly
448
+ # set it to None.
449
+ upload_base64_image=None,
435
450
  )
436
451
  if not instrumentor.is_instrumented_by_opentelemetry:
437
452
  instrumentor.instrument()
@@ -1,6 +1,10 @@
1
1
  import opentelemetry
2
2
  import uuid
3
3
  import asyncio
4
+ import logging
5
+ import time
6
+
7
+ logger = logging.getLogger(__name__)
4
8
 
5
9
  try:
6
10
  from playwright.async_api import BrowserContext, Page
@@ -56,7 +60,6 @@ INJECT_PLACEHOLDER = """
56
60
  'Authorization': `Bearer ${projectApiKey}`
57
61
  },
58
62
  body: blob,
59
- compress: false,
60
63
  credentials: 'omit',
61
64
  mode: 'cors',
62
65
  cache: 'no-cache',
@@ -98,9 +101,44 @@ INJECT_PLACEHOLDER = """
98
101
  def init_playwright_tracing(http_url: str, project_api_key: str):
99
102
 
100
103
  def inject_rrweb(page: SyncPage):
104
+ # Wait for the page to be in a ready state first
105
+ page.wait_for_load_state("domcontentloaded")
106
+
107
+ # First check if rrweb is already loaded
108
+ is_loaded = page.evaluate(
109
+ """
110
+ () => typeof window.rrweb !== 'undefined'
111
+ """
112
+ )
113
+
114
+ if not is_loaded:
115
+ try:
116
+ # Add retry logic for script loading
117
+ retries = 3
118
+ for attempt in range(retries):
119
+ try:
120
+ page.add_script_tag(
121
+ url="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.min.js"
122
+ )
123
+ # Verify script loaded successfully
124
+ page.wait_for_function(
125
+ """(() => typeof window.rrweb !== 'undefined')""",
126
+ timeout=5000,
127
+ )
128
+ break
129
+ except Exception:
130
+ if attempt == retries - 1: # Last attempt
131
+ raise
132
+ time.sleep(0.5) # Wait before retry
133
+ except Exception as script_error:
134
+ logger.error("Failed to load rrweb after all retries: %s", script_error)
135
+ return
136
+
101
137
  # Get current trace ID from active span
102
138
  current_span = opentelemetry.trace.get_current_span()
103
- current_span.set_attribute("lmnr.internal.has_browser_session", True)
139
+ if current_span.is_recording():
140
+ current_span.set_attribute("lmnr.internal.has_browser_session", True)
141
+
104
142
  trace_id = format(current_span.get_span_context().trace_id, "032x")
105
143
  session_id = str(uuid.uuid4().hex)
106
144
 
@@ -113,11 +151,6 @@ def init_playwright_tracing(http_url: str, project_api_key: str):
113
151
  [trace_id, session_id],
114
152
  )
115
153
 
116
- # Load rrweb from CDN
117
- page.add_script_tag(
118
- url="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.min.js"
119
- )
120
-
121
154
  # Update the recording setup to include trace ID
122
155
  page.evaluate(
123
156
  INJECT_PLACEHOLDER,
@@ -125,41 +158,61 @@ def init_playwright_tracing(http_url: str, project_api_key: str):
125
158
  )
126
159
 
127
160
  async def inject_rrweb_async(page: Page):
128
- try:
129
- # Wait for the page to be in a ready state first
130
- await page.wait_for_load_state("domcontentloaded")
131
161
 
132
- # Get current trace ID from active span
133
- current_span = opentelemetry.trace.get_current_span()
162
+ # Wait for the page to be in a ready state first
163
+ await page.wait_for_load_state("domcontentloaded")
164
+
165
+ # First check if rrweb is already loaded
166
+ is_loaded = await page.evaluate(
167
+ """
168
+ () => typeof window.rrweb !== 'undefined'
169
+ """
170
+ )
171
+
172
+ if not is_loaded:
173
+ try:
174
+ # Add retry logic for script loading
175
+ retries = 3
176
+ for attempt in range(retries):
177
+ try:
178
+ await page.add_script_tag(
179
+ url="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.min.js"
180
+ )
181
+ # Verify script loaded successfully
182
+ await page.wait_for_function(
183
+ """(() => typeof window.rrweb !== 'undefined')""",
184
+ timeout=5000,
185
+ )
186
+ break
187
+ except Exception:
188
+ if attempt == retries - 1: # Last attempt
189
+ raise
190
+ await asyncio.sleep(0.5) # Wait before retry
191
+ except Exception as script_error:
192
+ logger.error("Failed to load rrweb after all retries: %s", script_error)
193
+ return
194
+ # Get current trace ID from active span
195
+ current_span = opentelemetry.trace.get_current_span()
196
+ if current_span.is_recording():
134
197
  current_span.set_attribute("lmnr.internal.has_browser_session", True)
135
- trace_id = format(current_span.get_span_context().trace_id, "032x")
136
- session_id = str(uuid.uuid4().hex)
137
-
138
- # Generate UUID session ID and set trace ID
139
- await page.evaluate(
140
- """([traceId, sessionId]) => {
141
- window.rrwebSessionId = sessionId;
142
- window.traceId = traceId;
143
- }""",
144
- [trace_id, session_id],
145
- )
146
-
147
- # Load rrweb from CDN
148
- await page.add_script_tag(
149
- url="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.min.js"
150
- )
151
-
152
- await page.wait_for_function(
153
- """(() => window.rrweb || 'rrweb' in window)"""
154
- )
155
-
156
- # Update the recording setup to include trace ID
157
- await page.evaluate(
158
- INJECT_PLACEHOLDER,
159
- [http_url, project_api_key],
160
- )
161
- except Exception as e:
162
- print(f"Error injecting rrweb: {e}")
198
+
199
+ trace_id = format(current_span.get_span_context().trace_id, "032x")
200
+ session_id = str(uuid.uuid4().hex)
201
+
202
+ # Generate UUID session ID and set trace ID
203
+ await page.evaluate(
204
+ """([traceId, sessionId]) => {
205
+ window.rrwebSessionId = sessionId;
206
+ window.traceId = traceId;
207
+ }""",
208
+ [trace_id, session_id],
209
+ )
210
+
211
+ # Update the recording setup to include trace ID
212
+ await page.evaluate(
213
+ INJECT_PLACEHOLDER,
214
+ [http_url, project_api_key],
215
+ )
163
216
 
164
217
  def handle_navigation(page: SyncPage):
165
218
  def on_load():
@@ -4,7 +4,7 @@ from lmnr.openllmetry_sdk.decorators.base import (
4
4
  )
5
5
  from opentelemetry.trace import INVALID_SPAN, get_current_span
6
6
 
7
- from typing import Callable, Optional, TypeVar, cast
7
+ from typing import Callable, Literal, Optional, TypeVar, Union, cast
8
8
  from typing_extensions import ParamSpec
9
9
 
10
10
  from lmnr.openllmetry_sdk.tracing.attributes import SESSION_ID
@@ -21,6 +21,9 @@ def observe(
21
21
  *,
22
22
  name: Optional[str] = None,
23
23
  session_id: Optional[str] = None,
24
+ ignore_input: bool = False,
25
+ ignore_output: bool = False,
26
+ span_type: Union[Literal["DEFAULT"], Literal["LLM"], Literal["TOOL"]] = "DEFAULT",
24
27
  ) -> Callable[[Callable[P, R]], Callable[P, R]]:
25
28
  """The main decorator entrypoint for Laminar. This is used to wrap
26
29
  functions and methods to create spans.
@@ -50,9 +53,19 @@ def observe(
50
53
  association_properties["session_id"] = session_id
51
54
  update_association_properties(association_properties)
52
55
  return (
53
- aentity_method(name=name)(func)
56
+ aentity_method(
57
+ name=name,
58
+ ignore_input=ignore_input,
59
+ ignore_output=ignore_output,
60
+ span_type=span_type,
61
+ )(func)
54
62
  if is_async(func)
55
- else entity_method(name=name)(func)
63
+ else entity_method(
64
+ name=name,
65
+ ignore_input=ignore_input,
66
+ ignore_output=ignore_output,
67
+ span_type=span_type,
68
+ )(func)
56
69
  )
57
70
 
58
71
  return cast(Callable, decorator)
@@ -222,9 +222,6 @@ class Evaluation:
222
222
  self.is_finished = True
223
223
  return
224
224
 
225
- for result_datapoint in result_datapoints:
226
- result_datapoint.human_evaluators = self.human_evaluators or {}
227
-
228
225
  average_scores = get_average_scores(result_datapoints)
229
226
  self.reporter.stop(average_scores, evaluation.projectId, evaluation.id)
230
227
  self.is_finished = True
@@ -342,6 +339,7 @@ def evaluate(
342
339
  http_port: Optional[int] = None,
343
340
  grpc_port: Optional[int] = None,
344
341
  instruments: Optional[Set[Instruments]] = None,
342
+ max_export_batch_size: Optional[int] = MAX_EXPORT_BATCH_SIZE,
345
343
  ) -> Optional[Awaitable[None]]:
346
344
  """
347
345
  If added to the file which is called through `lmnr eval` command, then
@@ -422,6 +420,7 @@ def evaluate(
422
420
  http_port=http_port,
423
421
  grpc_port=grpc_port,
424
422
  instruments=instruments,
423
+ max_export_batch_size=max_export_batch_size,
425
424
  )
426
425
 
427
426
  if PREPARE_ONLY.get():
@@ -9,6 +9,7 @@ from lmnr.openllmetry_sdk.tracing.attributes import (
9
9
  SPAN_TYPE,
10
10
  OVERRIDE_PARENT_SPAN,
11
11
  )
12
+ from lmnr.openllmetry_sdk.config import MAX_MANUAL_SPAN_PAYLOAD_SIZE
12
13
  from lmnr.openllmetry_sdk.decorators.base import json_dumps
13
14
  from opentelemetry import context as context_api, trace
14
15
  from opentelemetry.context import attach, detach
@@ -47,7 +48,6 @@ from lmnr.openllmetry_sdk.tracing.tracing import (
47
48
  from .log import VerboseColorfulFormatter
48
49
 
49
50
  from .types import (
50
- HumanEvaluator,
51
51
  InitEvaluationResponse,
52
52
  EvaluationResultDatapoint,
53
53
  GetDatapointsResponse,
@@ -323,7 +323,9 @@ class Laminar:
323
323
  cls,
324
324
  name: str,
325
325
  input: Any = None,
326
- span_type: Union[Literal["DEFAULT"], Literal["LLM"]] = "DEFAULT",
326
+ span_type: Union[
327
+ Literal["DEFAULT"], Literal["LLM"], Literal["TOOL"]
328
+ ] = "DEFAULT",
327
329
  context: Optional[Context] = None,
328
330
  trace_id: Optional[uuid.UUID] = None,
329
331
  labels: Optional[dict[str, str]] = None,
@@ -402,10 +404,17 @@ class Laminar:
402
404
  if trace_id is not None and isinstance(trace_id, uuid.UUID):
403
405
  span.set_attribute(OVERRIDE_PARENT_SPAN, True)
404
406
  if input is not None:
405
- span.set_attribute(
406
- SPAN_INPUT,
407
- json_dumps(input),
408
- )
407
+ serialized_input = json_dumps(input)
408
+ if len(serialized_input) > MAX_MANUAL_SPAN_PAYLOAD_SIZE:
409
+ span.set_attribute(
410
+ SPAN_INPUT,
411
+ "Laminar: input too large to record",
412
+ )
413
+ else:
414
+ span.set_attribute(
415
+ SPAN_INPUT,
416
+ serialized_input,
417
+ )
409
418
  yield span
410
419
 
411
420
  # TODO: Figure out if this is necessary
@@ -454,7 +463,9 @@ class Laminar:
454
463
  cls,
455
464
  name: str,
456
465
  input: Any = None,
457
- span_type: Union[Literal["DEFAULT"], Literal["LLM"]] = "DEFAULT",
466
+ span_type: Union[
467
+ Literal["DEFAULT"], Literal["LLM"], Literal["TOOL"]
468
+ ] = "DEFAULT",
458
469
  context: Optional[Context] = None,
459
470
  trace_id: Optional[uuid.UUID] = None,
460
471
  labels: Optional[dict[str, str]] = None,
@@ -546,10 +557,17 @@ class Laminar:
546
557
  if trace_id is not None and isinstance(trace_id, uuid.UUID):
547
558
  span.set_attribute(OVERRIDE_PARENT_SPAN, True)
548
559
  if input is not None:
549
- span.set_attribute(
550
- SPAN_INPUT,
551
- json_dumps(input),
552
- )
560
+ serialized_input = json_dumps(input)
561
+ if len(serialized_input) > MAX_MANUAL_SPAN_PAYLOAD_SIZE:
562
+ span.set_attribute(
563
+ SPAN_INPUT,
564
+ "Laminar: input too large to record",
565
+ )
566
+ else:
567
+ span.set_attribute(
568
+ SPAN_INPUT,
569
+ serialized_input,
570
+ )
553
571
  return span
554
572
 
555
573
  @classmethod
@@ -563,7 +581,14 @@ class Laminar:
563
581
  """
564
582
  span = trace.get_current_span()
565
583
  if output is not None and span != trace.INVALID_SPAN:
566
- span.set_attribute(SPAN_OUTPUT, json_dumps(output))
584
+ serialized_output = json_dumps(output)
585
+ if len(serialized_output) > MAX_MANUAL_SPAN_PAYLOAD_SIZE:
586
+ span.set_attribute(
587
+ SPAN_OUTPUT,
588
+ "Laminar: output too large to record",
589
+ )
590
+ else:
591
+ span.set_attribute(SPAN_OUTPUT, serialized_output)
567
592
 
568
593
  @classmethod
569
594
  @contextmanager
@@ -713,7 +738,6 @@ class Laminar:
713
738
  eval_id: uuid.UUID,
714
739
  datapoints: list[EvaluationResultDatapoint],
715
740
  groupName: Optional[str] = None,
716
- human_evaluators: Optional[list[HumanEvaluator]] = None,
717
741
  ):
718
742
  async with aiohttp.ClientSession() as session:
719
743
 
@@ -722,7 +746,6 @@ class Laminar:
722
746
  json={
723
747
  "points": [datapoint.to_dict() for datapoint in datapoints],
724
748
  "groupName": groupName,
725
- "humanEvaluators": human_evaluators,
726
749
  },
727
750
  headers=cls._headers(),
728
751
  ) as response:
@@ -164,9 +164,11 @@ class EvaluationResultDatapoint(pydantic.BaseModel):
164
164
  def to_dict(self):
165
165
  try:
166
166
  return {
167
- "data": serialize(self.data),
168
- "target": serialize(self.target),
169
- "executorOutput": serialize(self.executor_output),
167
+ # preserve only preview of the data, target and executor output
168
+ # (full data is in trace)
169
+ "data": str(serialize(self.data))[:100],
170
+ "target": str(serialize(self.target))[:100],
171
+ "executorOutput": str(serialize(self.executor_output))[:100],
170
172
  "scores": self.scores,
171
173
  "traceId": str(self.trace_id),
172
174
  "humanEvaluators": [
@@ -49,7 +49,7 @@ def is_iterator(o: typing.Any) -> bool:
49
49
  return hasattr(o, "__iter__") and hasattr(o, "__next__")
50
50
 
51
51
 
52
- def serialize(obj: typing.Any) -> dict[str, typing.Any]:
52
+ def serialize(obj: typing.Any) -> typing.Union[str, dict[str, typing.Any]]:
53
53
  def serialize_inner(o: typing.Any):
54
54
  if isinstance(o, (datetime.datetime, datetime.date)):
55
55
  return o.strftime("%Y-%m-%dT%H:%M:%S.%f%z")
@@ -1,122 +0,0 @@
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.4.57"
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.9,<4"
16
- license = "Apache-2.0"
17
- dependencies = [
18
- "pydantic (>=2.0.3)",
19
- "requests (>=2.0)",
20
- "python-dotenv (>=1.0)",
21
- "opentelemetry-api (>=1.28.0)",
22
- "opentelemetry-sdk (>=1.28.0)",
23
- "opentelemetry-exporter-otlp-proto-http (>=1.28.0)",
24
- "opentelemetry-exporter-otlp-proto-grpc (>=1.28.0)",
25
- "opentelemetry-instrumentation-requests (>=0.50b0)",
26
- "opentelemetry-instrumentation-sqlalchemy (>=0.50b0)",
27
- "opentelemetry-instrumentation-urllib3 (>=0.50b0)",
28
- "opentelemetry-instrumentation-threading (>=0.50b0)",
29
- "opentelemetry-semantic-conventions-ai (>=0.4.2)",
30
- "tqdm (>=4.0)",
31
- "argparse (>=1.0)",
32
- "aiohttp (>=3.0)",
33
- "tenacity (>=8.0)",
34
- # explicitly freeze grpcio. Since 1.68.0, grpcio writes a warning message
35
- # that looks scary, but is harmless.
36
- # WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
37
- # E0000 00:00:1737439981.199902 9456033 init.cc:229] grpc_wait_for_shutdown_with_timeout() timed out.
38
- #
39
- # Related issue:
40
- # 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
41
- # https://github.com/grpc/grpc/issues/38490
42
- "grpcio<1.68.0",
43
- ]
44
-
45
- [project.scripts]
46
- lmnr = "lmnr.cli:cli"
47
-
48
- [project.optional-dependencies]
49
- # List of all possible extras. You can specify one or more of these extras
50
- # when installing the package, using any of the following examples:
51
- # `pip install 'lmnr[anthropic,openai]'`
52
- # `uv pip install 'lmnr[anthropic,openai]'`
53
- # `uv add lmnr --extra anthropic --extra openai`
54
- # `poetry add 'lmnr[anthropic,openai]'`
55
-
56
- alephalpha=["opentelemetry-instrumentation-alephalpha>=0.36.1"]
57
- anthropic=["opentelemetry-instrumentation-anthropic>=0.36.1"]
58
- bedrock=["opentelemetry-instrumentation-bedrock>=0.36.1"]
59
- chromadb=["opentelemetry-instrumentation-chromadb>=0.36.1"]
60
- cohere=["opentelemetry-instrumentation-cohere>=0.36.1"]
61
- google-generativeai=["opentelemetry-instrumentation-google-generativeai>=0.36.1"]
62
- groq=["opentelemetry-instrumentation-groq>=0.36.1"]
63
- haystack=["opentelemetry-instrumentation-haystack>=0.36.1"]
64
- lancedb=["opentelemetry-instrumentation-lancedb>=0.36.1"]
65
- langchain=["opentelemetry-instrumentation-langchain>=0.36.1"]
66
- llamaindex=["opentelemetry-instrumentation-llamaindex>=0.36.1"]
67
- marqo=["opentelemetry-instrumentation-marqo>=0.36.1"]
68
- milvus=["opentelemetry-instrumentation-milvus>=0.36.1"]
69
- mistralai=["opentelemetry-instrumentation-mistralai>=0.36.1"]
70
- ollama=["opentelemetry-instrumentation-ollama>=0.36.1"]
71
- openai=["opentelemetry-instrumentation-openai>=0.36.1"]
72
- pinecone=["opentelemetry-instrumentation-pinecone>=0.36.1"]
73
- qdrant=["opentelemetry-instrumentation-qdrant>=0.36.1"]
74
- replicate=["opentelemetry-instrumentation-replicate>=0.36.1"]
75
- sagemaker=["opentelemetry-instrumentation-sagemaker>=0.36.1"]
76
- together=["opentelemetry-instrumentation-together>=0.36.1"]
77
- transformers=["opentelemetry-instrumentation-transformers>=0.36.1"]
78
- vertexai=["opentelemetry-instrumentation-vertexai>=0.36.1"]
79
- watsonx=["opentelemetry-instrumentation-watsonx>=0.36.1"]
80
- weaviate=["opentelemetry-instrumentation-weaviate>=0.36.1"]
81
- # `all` is the group added for convenience, if you want to install all
82
- # the instrumentations.
83
- all = [
84
- "opentelemetry-instrumentation-alephalpha>=0.36.1",
85
- "opentelemetry-instrumentation-anthropic>=0.36.1",
86
- "opentelemetry-instrumentation-bedrock>=0.36.1",
87
- "opentelemetry-instrumentation-chromadb>=0.36.1",
88
- "opentelemetry-instrumentation-cohere>=0.36.1",
89
- "opentelemetry-instrumentation-google-generativeai>=0.36.1",
90
- "opentelemetry-instrumentation-groq>=0.36.1",
91
- "opentelemetry-instrumentation-haystack>=0.36.1",
92
- "opentelemetry-instrumentation-lancedb>=0.36.1",
93
- "opentelemetry-instrumentation-langchain>=0.36.1",
94
- "opentelemetry-instrumentation-llamaindex>=0.36.1",
95
- "opentelemetry-instrumentation-marqo>=0.36.1",
96
- "opentelemetry-instrumentation-milvus>=0.36.1",
97
- "opentelemetry-instrumentation-mistralai>=0.36.1",
98
- "opentelemetry-instrumentation-ollama>=0.36.1",
99
- "opentelemetry-instrumentation-openai>=0.36.1",
100
- "opentelemetry-instrumentation-pinecone>=0.36.1",
101
- "opentelemetry-instrumentation-qdrant>=0.36.1",
102
- "opentelemetry-instrumentation-replicate>=0.36.1",
103
- "opentelemetry-instrumentation-sagemaker>=0.36.1",
104
- "opentelemetry-instrumentation-together>=0.36.1",
105
- "opentelemetry-instrumentation-transformers>=0.36.1",
106
- "opentelemetry-instrumentation-vertexai>=0.36.1",
107
- "opentelemetry-instrumentation-watsonx>=0.36.1",
108
- "opentelemetry-instrumentation-weaviate>=0.36.1"
109
- ]
110
-
111
- [dependency-groups]
112
- dev = [
113
- "autopep8",
114
- "flake8",
115
- "pytest>=8.3.4",
116
- "pytest-sugar",
117
- "pytest-asyncio>=0.25.2"
118
- ]
119
-
120
- [build-system]
121
- requires = ["poetry-core"]
122
- build-backend = "poetry.core.masonry.api"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes