lmnr 0.4.28__py3-none-any.whl → 0.4.29__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.
- lmnr/__init__.py +8 -1
- lmnr/sdk/evaluations.py +33 -12
- lmnr/sdk/laminar.py +66 -1
- lmnr/sdk/types.py +34 -20
- lmnr/sdk/utils.py +5 -5
- lmnr/traceloop_sdk/instruments.py +15 -11
- lmnr/traceloop_sdk/tracing/tracing.py +175 -260
- {lmnr-0.4.28.dist-info → lmnr-0.4.29.dist-info}/METADATA +2 -1
- {lmnr-0.4.28.dist-info → lmnr-0.4.29.dist-info}/RECORD +12 -12
- {lmnr-0.4.28.dist-info → lmnr-0.4.29.dist-info}/LICENSE +0 -0
- {lmnr-0.4.28.dist-info → lmnr-0.4.29.dist-info}/WHEEL +0 -0
- {lmnr-0.4.28.dist-info → lmnr-0.4.29.dist-info}/entry_points.txt +0 -0
lmnr/__init__.py
CHANGED
@@ -1,7 +1,14 @@
|
|
1
1
|
from .sdk.datasets import EvaluationDataset, LaminarDataset
|
2
2
|
from .sdk.evaluations import evaluate
|
3
3
|
from .sdk.laminar import Laminar
|
4
|
-
from .sdk.types import
|
4
|
+
from .sdk.types import (
|
5
|
+
ChatMessage,
|
6
|
+
HumanEvaluator,
|
7
|
+
NodeInput,
|
8
|
+
PipelineRunError,
|
9
|
+
PipelineRunResponse,
|
10
|
+
)
|
5
11
|
from .sdk.decorators import observe
|
6
12
|
from .traceloop_sdk import Instruments
|
7
13
|
from .traceloop_sdk.tracing.attributes import Attributes
|
14
|
+
from opentelemetry.trace import use_span
|
lmnr/sdk/evaluations.py
CHANGED
@@ -18,6 +18,7 @@ from .types import (
|
|
18
18
|
EvaluationResultDatapoint,
|
19
19
|
EvaluatorFunction,
|
20
20
|
ExecutorFunction,
|
21
|
+
HumanEvaluator,
|
21
22
|
Numeric,
|
22
23
|
NumericTypes,
|
23
24
|
SpanType,
|
@@ -99,6 +100,7 @@ class Evaluation:
|
|
99
100
|
data: Union[EvaluationDataset, list[Union[Datapoint, dict]]],
|
100
101
|
executor: Any,
|
101
102
|
evaluators: dict[str, EvaluatorFunction],
|
103
|
+
human_evaluators: list[HumanEvaluator] = [],
|
102
104
|
name: Optional[str] = None,
|
103
105
|
group_id: Optional[str] = None,
|
104
106
|
batch_size: int = DEFAULT_BATCH_SIZE,
|
@@ -126,6 +128,10 @@ class Evaluation:
|
|
126
128
|
If the score is a single number, it will be named after the\
|
127
129
|
evaluator function. Evaluator function names must contain only\
|
128
130
|
letters, digits, hyphens, underscores, or spaces.
|
131
|
+
human_evaluators (list[HumanEvaluator], optional):\
|
132
|
+
[Beta] List of instances of HumanEvaluator. For now, human\
|
133
|
+
evaluator only holds the queue name.
|
134
|
+
Defaults to an empty list.
|
129
135
|
name (Optional[str], optional): Optional name of the evaluation.\
|
130
136
|
Used to identify the evaluation in the group.\
|
131
137
|
If not provided, a random name will be generated.
|
@@ -159,9 +165,9 @@ class Evaluation:
|
|
159
165
|
if not evaluators:
|
160
166
|
raise ValueError("No evaluators provided")
|
161
167
|
|
162
|
-
|
168
|
+
evaluator_name_regex = re.compile(r"^[\w\s-]+$")
|
163
169
|
for evaluator_name in evaluators:
|
164
|
-
if not
|
170
|
+
if not evaluator_name_regex.match(evaluator_name):
|
165
171
|
raise ValueError(
|
166
172
|
f'Invalid evaluator key: "{evaluator_name}". '
|
167
173
|
"Keys must only contain letters, digits, hyphens,"
|
@@ -183,6 +189,7 @@ class Evaluation:
|
|
183
189
|
self.name = name
|
184
190
|
self.batch_size = batch_size
|
185
191
|
self._logger = get_default_logger(self.__class__.__name__)
|
192
|
+
self.human_evaluators = human_evaluators
|
186
193
|
L.initialize(
|
187
194
|
project_api_key=project_api_key,
|
188
195
|
base_url=base_url,
|
@@ -202,9 +209,7 @@ class Evaluation:
|
|
202
209
|
return loop.run_until_complete(self._run())
|
203
210
|
|
204
211
|
async def _run(self) -> None:
|
205
|
-
self.reporter.start(
|
206
|
-
len(self.data),
|
207
|
-
)
|
212
|
+
self.reporter.start(len(self.data))
|
208
213
|
|
209
214
|
try:
|
210
215
|
result_datapoints = await self._evaluate_in_batches()
|
@@ -212,13 +217,19 @@ class Evaluation:
|
|
212
217
|
self.reporter.stopWithError(e)
|
213
218
|
self.is_finished = True
|
214
219
|
return
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
220
|
+
|
221
|
+
# For now add all human evaluators to all result datapoints
|
222
|
+
# In the future, we will add ways to specify which human evaluators
|
223
|
+
# to add to which result datapoints, e.g. sample some randomly
|
224
|
+
for result_datapoint in result_datapoints:
|
225
|
+
result_datapoint.human_evaluators = self.human_evaluators or {}
|
226
|
+
|
227
|
+
evaluation = L.create_evaluation(
|
228
|
+
data=result_datapoints, group_id=self.group_id, name=self.name
|
229
|
+
)
|
230
|
+
average_scores = get_average_scores(result_datapoints)
|
231
|
+
self.reporter.stop(average_scores, evaluation.projectId, evaluation.id)
|
232
|
+
self.is_finished = True
|
222
233
|
|
223
234
|
async def _evaluate_in_batches(self) -> list[EvaluationResultDatapoint]:
|
224
235
|
result_datapoints = []
|
@@ -256,6 +267,9 @@ class Evaluation:
|
|
256
267
|
else self.executor(datapoint.data)
|
257
268
|
)
|
258
269
|
L.set_span_output(output)
|
270
|
+
executor_span_id = uuid.UUID(
|
271
|
+
int=executor_span.get_span_context().span_id
|
272
|
+
)
|
259
273
|
target = datapoint.target
|
260
274
|
|
261
275
|
# Iterate over evaluators
|
@@ -285,6 +299,7 @@ class Evaluation:
|
|
285
299
|
executor_output=output,
|
286
300
|
scores=scores,
|
287
301
|
trace_id=trace_id,
|
302
|
+
executor_span_id=executor_span_id,
|
288
303
|
)
|
289
304
|
|
290
305
|
|
@@ -292,6 +307,7 @@ def evaluate(
|
|
292
307
|
data: Union[EvaluationDataset, list[Union[Datapoint, dict]]],
|
293
308
|
executor: ExecutorFunction,
|
294
309
|
evaluators: dict[str, EvaluatorFunction],
|
310
|
+
human_evaluators: list[HumanEvaluator] = [],
|
295
311
|
name: Optional[str] = None,
|
296
312
|
group_id: Optional[str] = None,
|
297
313
|
batch_size: int = DEFAULT_BATCH_SIZE,
|
@@ -326,6 +342,10 @@ def evaluate(
|
|
326
342
|
If the score is a single number, it will be named after the\
|
327
343
|
evaluator function. Evaluator function names must contain only\
|
328
344
|
letters, digits, hyphens, underscores, or spaces.
|
345
|
+
human_evaluators (list[HumanEvaluator], optional):\
|
346
|
+
[Beta] List of instances of HumanEvaluator. For now, human\
|
347
|
+
evaluator only holds the queue name.
|
348
|
+
Defaults to an empty list.
|
329
349
|
name (Optional[str], optional): Optional name of the evaluation.\
|
330
350
|
Used to identify the evaluation in the group.\
|
331
351
|
If not provided, a random name will be generated.
|
@@ -359,6 +379,7 @@ def evaluate(
|
|
359
379
|
executor=executor,
|
360
380
|
evaluators=evaluators,
|
361
381
|
group_id=group_id,
|
382
|
+
human_evaluators=human_evaluators,
|
362
383
|
name=name,
|
363
384
|
batch_size=batch_size,
|
364
385
|
project_api_key=project_api_key,
|
lmnr/sdk/laminar.py
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
from contextvars import Context
|
1
2
|
import re
|
2
3
|
from lmnr.traceloop_sdk.instruments import Instruments
|
3
4
|
from opentelemetry import context
|
@@ -294,6 +295,7 @@ class Laminar:
|
|
294
295
|
name: str,
|
295
296
|
input: Any = None,
|
296
297
|
span_type: Union[Literal["DEFAULT"], Literal["LLM"]] = "DEFAULT",
|
298
|
+
context: Optional[Context] = None,
|
297
299
|
):
|
298
300
|
"""Start a new span as the current span. Useful for manual
|
299
301
|
instrumentation. If `span_type` is set to `"LLM"`, you should report
|
@@ -314,10 +316,12 @@ class Laminar:
|
|
314
316
|
span_type (Union[Literal["DEFAULT"], Literal["LLM"]], optional):\
|
315
317
|
type of the span. If you use `"LLM"`, you should report usage\
|
316
318
|
and response attributes manually. Defaults to "DEFAULT".
|
319
|
+
context (Optional[Context], optional): raw OpenTelemetry context\
|
320
|
+
to attach the span to. Defaults to None.
|
317
321
|
"""
|
318
322
|
with get_tracer() as tracer:
|
319
323
|
span_path = get_span_path(name)
|
320
|
-
ctx = set_value("span_path", span_path)
|
324
|
+
ctx = set_value("span_path", span_path, context)
|
321
325
|
ctx_token = attach(ctx)
|
322
326
|
with tracer.start_as_current_span(
|
323
327
|
name,
|
@@ -338,6 +342,67 @@ class Laminar:
|
|
338
342
|
except Exception:
|
339
343
|
pass
|
340
344
|
|
345
|
+
@classmethod
|
346
|
+
def start_span(
|
347
|
+
cls,
|
348
|
+
name: str,
|
349
|
+
input: Any = None,
|
350
|
+
span_type: Union[Literal["DEFAULT"], Literal["LLM"]] = "DEFAULT",
|
351
|
+
context: Optional[Context] = None,
|
352
|
+
):
|
353
|
+
"""Start a new span. Useful for manual instrumentation.
|
354
|
+
If `span_type` is set to `"LLM"`, you should report usage and response
|
355
|
+
attributes manually. See `Laminar.set_span_attributes` for more
|
356
|
+
information.
|
357
|
+
|
358
|
+
Usage example:
|
359
|
+
```python
|
360
|
+
from src.lmnr import Laminar, use_span
|
361
|
+
def foo(span):
|
362
|
+
with use_span(span):
|
363
|
+
with Laminar.start_as_current_span("foo_inner"):
|
364
|
+
some_function()
|
365
|
+
|
366
|
+
def bar():
|
367
|
+
with use_span(span):
|
368
|
+
openai_client.chat.completions.create()
|
369
|
+
|
370
|
+
span = Laminar.start_span("outer")
|
371
|
+
foo(span)
|
372
|
+
bar(span)
|
373
|
+
# IMPORTANT: End the span manually
|
374
|
+
span.end()
|
375
|
+
|
376
|
+
# Results in:
|
377
|
+
# | outer
|
378
|
+
# | | foo
|
379
|
+
# | | | foo_inner
|
380
|
+
# | | bar
|
381
|
+
# | | | openai.chat
|
382
|
+
```
|
383
|
+
|
384
|
+
Args:
|
385
|
+
name (str): name of the span
|
386
|
+
input (Any, optional): input to the span. Will be sent as an\
|
387
|
+
attribute, so must be json serializable. Defaults to None.
|
388
|
+
span_type (Union[Literal["DEFAULT"], Literal["LLM"]], optional):\
|
389
|
+
type of the span. If you use `"LLM"`, you should report usage\
|
390
|
+
and response attributes manually. Defaults to "DEFAULT".
|
391
|
+
context (Optional[Context], optional): raw OpenTelemetry context\
|
392
|
+
to attach the span to. Defaults to None.
|
393
|
+
"""
|
394
|
+
with get_tracer() as tracer:
|
395
|
+
span_path = get_span_path(name)
|
396
|
+
ctx = set_value("span_path", span_path, context)
|
397
|
+
span = tracer.start_span(name, context=ctx)
|
398
|
+
if input is not None:
|
399
|
+
span.set_attribute(
|
400
|
+
SPAN_INPUT,
|
401
|
+
json_dumps(input),
|
402
|
+
)
|
403
|
+
span.set_attribute(SPAN_TYPE, span_type)
|
404
|
+
return span
|
405
|
+
|
341
406
|
@classmethod
|
342
407
|
def set_span_output(cls, output: Any = None):
|
343
408
|
"""Set the output of the current span. Useful for manual
|
lmnr/sdk/types.py
CHANGED
@@ -77,18 +77,17 @@ class PipelineRunError(Exception):
|
|
77
77
|
return super().__str__()
|
78
78
|
|
79
79
|
|
80
|
-
EvaluationDatapointData =
|
81
|
-
EvaluationDatapointTarget =
|
82
|
-
EvaluationDatapointMetadata = Optional[
|
80
|
+
EvaluationDatapointData = Any # non-null, must be JSON-serializable
|
81
|
+
EvaluationDatapointTarget = Optional[Any] # must be JSON-serializable
|
82
|
+
EvaluationDatapointMetadata = Optional[Any] # must be JSON-serializable
|
83
83
|
|
84
84
|
|
85
85
|
# EvaluationDatapoint is a single data point in the evaluation
|
86
86
|
class Datapoint(pydantic.BaseModel):
|
87
|
-
# input to the executor function.
|
87
|
+
# input to the executor function.
|
88
88
|
data: EvaluationDatapointData
|
89
89
|
# input to the evaluator function (alongside the executor output).
|
90
|
-
|
91
|
-
target: EvaluationDatapointTarget
|
90
|
+
target: EvaluationDatapointTarget = pydantic.Field(default=None)
|
92
91
|
metadata: EvaluationDatapointMetadata = pydantic.Field(default=None)
|
93
92
|
|
94
93
|
|
@@ -110,6 +109,13 @@ EvaluatorFunction = Callable[
|
|
110
109
|
]
|
111
110
|
|
112
111
|
|
112
|
+
class HumanEvaluator(pydantic.BaseModel):
|
113
|
+
queueName: str
|
114
|
+
|
115
|
+
def __init__(self, queue_name: str):
|
116
|
+
super().__init__(queueName=queue_name)
|
117
|
+
|
118
|
+
|
113
119
|
class CreateEvaluationResponse(pydantic.BaseModel):
|
114
120
|
id: uuid.UUID
|
115
121
|
createdAt: datetime.datetime
|
@@ -123,23 +129,31 @@ class EvaluationResultDatapoint(pydantic.BaseModel):
|
|
123
129
|
target: EvaluationDatapointTarget
|
124
130
|
executor_output: ExecutorFunctionReturnType
|
125
131
|
scores: dict[str, Numeric]
|
132
|
+
human_evaluators: list[HumanEvaluator] = pydantic.Field(default_factory=list)
|
126
133
|
trace_id: uuid.UUID
|
134
|
+
executor_span_id: uuid.UUID
|
127
135
|
|
128
136
|
# uuid is not serializable by default, so we need to convert it to a string
|
129
137
|
def to_dict(self):
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
138
|
+
try:
|
139
|
+
return {
|
140
|
+
"data": serialize(self.data),
|
141
|
+
"target": serialize(self.target),
|
142
|
+
"executorOutput": serialize(self.executor_output),
|
143
|
+
"scores": self.scores,
|
144
|
+
"traceId": str(self.trace_id),
|
145
|
+
"humanEvaluators": [
|
146
|
+
(
|
147
|
+
v.model_dump()
|
148
|
+
if isinstance(v, pydantic.BaseModel)
|
149
|
+
else serialize(v)
|
150
|
+
)
|
151
|
+
for v in self.human_evaluators
|
152
|
+
],
|
153
|
+
"executorSpanId": str(self.executor_span_id),
|
154
|
+
}
|
155
|
+
except Exception as e:
|
156
|
+
raise ValueError(f"Error serializing EvaluationResultDatapoint: {e}")
|
143
157
|
|
144
158
|
|
145
159
|
class SpanType(Enum):
|
@@ -153,7 +167,7 @@ class SpanType(Enum):
|
|
153
167
|
|
154
168
|
class TraceType(Enum):
|
155
169
|
DEFAULT = "DEFAULT"
|
156
|
-
EVENT = "EVENT" #
|
170
|
+
EVENT = "EVENT" # deprecated
|
157
171
|
EVALUATION = "EVALUATION"
|
158
172
|
|
159
173
|
|
lmnr/sdk/utils.py
CHANGED
@@ -50,7 +50,7 @@ def is_iterator(o: typing.Any) -> bool:
|
|
50
50
|
|
51
51
|
|
52
52
|
def serialize(obj: typing.Any) -> dict[str, typing.Any]:
|
53
|
-
def
|
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")
|
56
56
|
elif o is None:
|
@@ -68,17 +68,17 @@ def serialize(obj: typing.Any) -> dict[str, typing.Any]:
|
|
68
68
|
elif isinstance(o, pydantic.BaseModel):
|
69
69
|
return o.model_dump()
|
70
70
|
elif isinstance(o, (tuple, set, frozenset)):
|
71
|
-
return [
|
71
|
+
return [serialize_inner(item) for item in o]
|
72
72
|
elif isinstance(o, list):
|
73
|
-
return [
|
73
|
+
return [serialize_inner(item) for item in o]
|
74
74
|
elif isinstance(o, dict):
|
75
|
-
return {
|
75
|
+
return {serialize_inner(k): serialize_inner(v) for k, v in o.items()}
|
76
76
|
elif isinstance(o, queue.Queue):
|
77
77
|
return type(o).__name__
|
78
78
|
|
79
79
|
return str(o)
|
80
80
|
|
81
|
-
return
|
81
|
+
return serialize_inner(obj)
|
82
82
|
|
83
83
|
|
84
84
|
def get_input_from_func_args(
|
@@ -4,27 +4,31 @@ from enum import Enum
|
|
4
4
|
class Instruments(Enum):
|
5
5
|
# The list of libraries which will be autoinstrumented
|
6
6
|
# if no specific instruments are provided to initialize()
|
7
|
-
|
7
|
+
ALEPHALPHA = "alephalpha"
|
8
8
|
ANTHROPIC = "anthropic"
|
9
|
-
|
10
|
-
PINECONE = "pinecone"
|
9
|
+
BEDROCK = "bedrock"
|
11
10
|
CHROMA = "chroma"
|
11
|
+
COHERE = "cohere"
|
12
12
|
GOOGLE_GENERATIVEAI = "google_generativeai"
|
13
|
+
GROQ = "groq"
|
14
|
+
HAYSTACK = "haystack"
|
15
|
+
LANCEDB = "lancedb"
|
13
16
|
LANGCHAIN = "langchain"
|
14
|
-
MISTRAL = "mistral"
|
15
|
-
OLLAMA = "ollama"
|
16
17
|
LLAMA_INDEX = "llama_index"
|
18
|
+
MARQO = "marqo"
|
17
19
|
MILVUS = "milvus"
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
MISTRAL = "mistral"
|
21
|
+
OLLAMA = "ollama"
|
22
|
+
OPENAI = "openai"
|
23
|
+
PINECONE = "pinecone"
|
24
|
+
QDRANT = "qdrant"
|
21
25
|
REPLICATE = "replicate"
|
26
|
+
SAGEMAKER = "sagemaker"
|
27
|
+
TOGETHER = "together"
|
28
|
+
TRANSFORMERS = "transformers"
|
22
29
|
VERTEXAI = "vertexai"
|
23
30
|
WATSONX = "watsonx"
|
24
31
|
WEAVIATE = "weaviate"
|
25
|
-
ALEPHALPHA = "alephalpha"
|
26
|
-
MARQO = "marqo"
|
27
|
-
LANCEDB = "lancedb"
|
28
32
|
|
29
33
|
# The following libraries will not be autoinstrumented unless
|
30
34
|
# specified explicitly in the initialize() call.
|
@@ -23,7 +23,6 @@ from opentelemetry.trace import get_tracer_provider, ProxyTracerProvider
|
|
23
23
|
from opentelemetry.context import get_value, attach, set_value
|
24
24
|
from opentelemetry.instrumentation.threading import ThreadingInstrumentor
|
25
25
|
|
26
|
-
# from lmnr.traceloop_sdk import Telemetry
|
27
26
|
from lmnr.traceloop_sdk.instruments import Instruments
|
28
27
|
from lmnr.traceloop_sdk.tracing.attributes import (
|
29
28
|
ASSOCIATION_PROPERTIES,
|
@@ -50,6 +49,7 @@ EXCLUDED_URLS = """
|
|
50
49
|
posthog.com,
|
51
50
|
sentry.io,
|
52
51
|
bedrock-runtime,
|
52
|
+
sagemaker-runtime,
|
53
53
|
googleapis.com,
|
54
54
|
githubusercontent.com,
|
55
55
|
openaipublic.blob.core.windows.net"""
|
@@ -79,27 +79,9 @@ class TracerWrapper(object):
|
|
79
79
|
obj.__resource = Resource(attributes=TracerWrapper.resource_attributes)
|
80
80
|
obj.__tracer_provider = init_tracer_provider(resource=obj.__resource)
|
81
81
|
if processor:
|
82
|
-
# Telemetry().capture("tracer:init", {"processor": "custom"})
|
83
82
|
obj.__spans_processor: SpanProcessor = processor
|
84
83
|
obj.__spans_processor_original_on_start = processor.on_start
|
85
84
|
else:
|
86
|
-
# if exporter:
|
87
|
-
# Telemetry().capture(
|
88
|
-
# "tracer:init",
|
89
|
-
# {
|
90
|
-
# "exporter": "custom",
|
91
|
-
# "processor": "simple" if disable_batch else "batch",
|
92
|
-
# },
|
93
|
-
# )
|
94
|
-
# else:
|
95
|
-
# Telemetry().capture(
|
96
|
-
# "tracer:init",
|
97
|
-
# {
|
98
|
-
# "exporter": TracerWrapper.endpoint,
|
99
|
-
# "processor": "simple" if disable_batch else "batch",
|
100
|
-
# },
|
101
|
-
# )
|
102
|
-
|
103
85
|
obj.__spans_exporter: SpanExporter = (
|
104
86
|
exporter
|
105
87
|
if exporter
|
@@ -126,99 +108,16 @@ class TracerWrapper(object):
|
|
126
108
|
# this makes sure otel context is propagated so we always want it
|
127
109
|
ThreadingInstrumentor().instrument()
|
128
110
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
elif instrument == Instruments.COHERE:
|
140
|
-
if not init_cohere_instrumentor():
|
141
|
-
print("Warning: Cohere library does not exist.")
|
142
|
-
elif instrument == Instruments.PINECONE:
|
143
|
-
if not init_pinecone_instrumentor():
|
144
|
-
print("Warning: Pinecone library does not exist.")
|
145
|
-
elif instrument == Instruments.CHROMA:
|
146
|
-
if not init_chroma_instrumentor():
|
147
|
-
print("Warning: Chroma library does not exist.")
|
148
|
-
elif instrument == Instruments.GOOGLE_GENERATIVEAI:
|
149
|
-
if not init_google_generativeai_instrumentor():
|
150
|
-
print(
|
151
|
-
"Warning: Google Generative AI library does not exist."
|
152
|
-
)
|
153
|
-
elif instrument == Instruments.LANGCHAIN:
|
154
|
-
if not init_langchain_instrumentor():
|
155
|
-
print("Warning: LangChain library does not exist.")
|
156
|
-
elif instrument == Instruments.MISTRAL:
|
157
|
-
if not init_mistralai_instrumentor():
|
158
|
-
print("Warning: MistralAI library does not exist.")
|
159
|
-
elif instrument == Instruments.OLLAMA:
|
160
|
-
if not init_ollama_instrumentor():
|
161
|
-
print("Warning: Ollama library does not exist.")
|
162
|
-
elif instrument == Instruments.LLAMA_INDEX:
|
163
|
-
if not init_llama_index_instrumentor():
|
164
|
-
print("Warning: LlamaIndex library does not exist.")
|
165
|
-
elif instrument == Instruments.MILVUS:
|
166
|
-
if not init_milvus_instrumentor():
|
167
|
-
print("Warning: Milvus library does not exist.")
|
168
|
-
elif instrument == Instruments.TRANSFORMERS:
|
169
|
-
if not init_transformers_instrumentor():
|
170
|
-
print("Warning: Transformers library does not exist.")
|
171
|
-
elif instrument == Instruments.TOGETHER:
|
172
|
-
if not init_together_instrumentor():
|
173
|
-
print("Warning: TogetherAI library does not exist.")
|
174
|
-
elif instrument == Instruments.REQUESTS:
|
175
|
-
if not init_requests_instrumentor():
|
176
|
-
print("Warning: Requests library does not exist.")
|
177
|
-
elif instrument == Instruments.URLLIB3:
|
178
|
-
if not init_urllib3_instrumentor():
|
179
|
-
print("Warning: urllib3 library does not exist.")
|
180
|
-
elif instrument == Instruments.PYMYSQL:
|
181
|
-
if not init_pymysql_instrumentor():
|
182
|
-
print("Warning: PyMySQL library does not exist.")
|
183
|
-
elif instrument == Instruments.BEDROCK:
|
184
|
-
if not init_bedrock_instrumentor(should_enrich_metrics):
|
185
|
-
print("Warning: Bedrock library does not exist.")
|
186
|
-
elif instrument == Instruments.REPLICATE:
|
187
|
-
if not init_replicate_instrumentor():
|
188
|
-
print("Warning: Replicate library does not exist.")
|
189
|
-
elif instrument == Instruments.VERTEXAI:
|
190
|
-
if not init_vertexai_instrumentor():
|
191
|
-
print("Warning: Vertex AI library does not exist.")
|
192
|
-
elif instrument == Instruments.WATSONX:
|
193
|
-
if not init_watsonx_instrumentor():
|
194
|
-
print("Warning: Watsonx library does not exist.")
|
195
|
-
elif instrument == Instruments.WEAVIATE:
|
196
|
-
if not init_weaviate_instrumentor():
|
197
|
-
print("Warning: Weaviate library does not exist.")
|
198
|
-
elif instrument == Instruments.ALEPHALPHA:
|
199
|
-
if not init_alephalpha_instrumentor():
|
200
|
-
print("Warning: Aleph Alpha library does not exist.")
|
201
|
-
elif instrument == Instruments.MARQO:
|
202
|
-
if not init_marqo_instrumentor():
|
203
|
-
print("Warning: marqo library does not exist.")
|
204
|
-
elif instrument == Instruments.LANCEDB:
|
205
|
-
if not init_lancedb_instrumentor():
|
206
|
-
print("Warning: LanceDB library does not exist.")
|
207
|
-
elif instrument == Instruments.REDIS:
|
208
|
-
if not init_redis_instrumentor():
|
209
|
-
print("Warning: redis library does not exist.")
|
210
|
-
|
211
|
-
else:
|
212
|
-
print(
|
213
|
-
"Warning: "
|
214
|
-
+ instrument
|
215
|
-
+ " instrumentation does not exist."
|
216
|
-
)
|
217
|
-
print(
|
218
|
-
"Usage:\n"
|
219
|
-
+ "from lmnr.traceloop_sdk.instruments import Instruments\n"
|
220
|
-
+ 'Traceloop.init(app_name="...", instruments=set([Instruments.OPENAI]))'
|
221
|
-
)
|
111
|
+
instrument_set = init_instrumentations(
|
112
|
+
should_enrich_metrics,
|
113
|
+
instruments,
|
114
|
+
)
|
115
|
+
|
116
|
+
if not instrument_set:
|
117
|
+
logging.warning(
|
118
|
+
"Warning: No valid instruments set. Remove 'instrument' "
|
119
|
+
"argument to use all instruments, or set a valid instrument."
|
120
|
+
)
|
222
121
|
|
223
122
|
obj.__content_allow_list = ContentAllowList()
|
224
123
|
|
@@ -364,47 +263,140 @@ def init_tracer_provider(resource: Resource) -> TracerProvider:
|
|
364
263
|
return provider
|
365
264
|
|
366
265
|
|
367
|
-
def init_instrumentations(
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
266
|
+
def init_instrumentations(
|
267
|
+
should_enrich_metrics: bool,
|
268
|
+
instruments: Optional[Set[Instruments]] = None,
|
269
|
+
block_instruments: Optional[Set[Instruments]] = None,
|
270
|
+
):
|
271
|
+
block_instruments = block_instruments or set()
|
272
|
+
# These libraries are not instrumented by default,
|
273
|
+
# but if the user wants, they can manually specify them
|
274
|
+
default_off_instruments = set(
|
275
|
+
[
|
276
|
+
Instruments.REQUESTS,
|
277
|
+
Instruments.URLLIB3,
|
278
|
+
Instruments.REDIS,
|
279
|
+
Instruments.PYMYSQL,
|
280
|
+
]
|
281
|
+
)
|
282
|
+
|
283
|
+
instruments = instruments or (set(Instruments) - default_off_instruments)
|
284
|
+
|
285
|
+
# Remove any instruments that were explicitly blocked
|
286
|
+
instruments = instruments - block_instruments
|
287
|
+
|
288
|
+
instrument_set = False
|
289
|
+
for instrument in instruments:
|
290
|
+
if instrument == Instruments.ALEPHALPHA:
|
291
|
+
if init_alephalpha_instrumentor():
|
292
|
+
instrument_set = True
|
293
|
+
elif instrument == Instruments.ANTHROPIC:
|
294
|
+
if init_anthropic_instrumentor(should_enrich_metrics):
|
295
|
+
instrument_set = True
|
296
|
+
elif instrument == Instruments.BEDROCK:
|
297
|
+
if init_bedrock_instrumentor(should_enrich_metrics):
|
298
|
+
instrument_set = True
|
299
|
+
elif instrument == Instruments.CHROMA:
|
300
|
+
if init_chroma_instrumentor():
|
301
|
+
instrument_set = True
|
302
|
+
elif instrument == Instruments.COHERE:
|
303
|
+
if init_cohere_instrumentor():
|
304
|
+
instrument_set = True
|
305
|
+
elif instrument == Instruments.GOOGLE_GENERATIVEAI:
|
306
|
+
if init_google_generativeai_instrumentor():
|
307
|
+
instrument_set = True
|
308
|
+
elif instrument == Instruments.GROQ:
|
309
|
+
if init_groq_instrumentor():
|
310
|
+
instrument_set = True
|
311
|
+
elif instrument == Instruments.HAYSTACK:
|
312
|
+
if init_haystack_instrumentor():
|
313
|
+
instrument_set = True
|
314
|
+
elif instrument == Instruments.LANCEDB:
|
315
|
+
if init_lancedb_instrumentor():
|
316
|
+
instrument_set = True
|
317
|
+
elif instrument == Instruments.LANGCHAIN:
|
318
|
+
if init_langchain_instrumentor():
|
319
|
+
instrument_set = True
|
320
|
+
elif instrument == Instruments.LLAMA_INDEX:
|
321
|
+
if init_llama_index_instrumentor():
|
322
|
+
instrument_set = True
|
323
|
+
elif instrument == Instruments.MARQO:
|
324
|
+
if init_marqo_instrumentor():
|
325
|
+
instrument_set = True
|
326
|
+
elif instrument == Instruments.MILVUS:
|
327
|
+
if init_milvus_instrumentor():
|
328
|
+
instrument_set = True
|
329
|
+
elif instrument == Instruments.MISTRAL:
|
330
|
+
if init_mistralai_instrumentor():
|
331
|
+
instrument_set = True
|
332
|
+
elif instrument == Instruments.OLLAMA:
|
333
|
+
if init_ollama_instrumentor():
|
334
|
+
instrument_set = True
|
335
|
+
elif instrument == Instruments.OPENAI:
|
336
|
+
if init_openai_instrumentor(should_enrich_metrics):
|
337
|
+
instrument_set = True
|
338
|
+
elif instrument == Instruments.PINECONE:
|
339
|
+
if init_pinecone_instrumentor():
|
340
|
+
instrument_set = True
|
341
|
+
elif instrument == Instruments.PYMYSQL:
|
342
|
+
if init_pymysql_instrumentor():
|
343
|
+
instrument_set = True
|
344
|
+
elif instrument == Instruments.QDRANT:
|
345
|
+
if init_qdrant_instrumentor():
|
346
|
+
instrument_set = True
|
347
|
+
elif instrument == Instruments.REDIS:
|
348
|
+
if init_redis_instrumentor():
|
349
|
+
instrument_set = True
|
350
|
+
elif instrument == Instruments.REPLICATE:
|
351
|
+
if init_replicate_instrumentor():
|
352
|
+
instrument_set = True
|
353
|
+
elif instrument == Instruments.REQUESTS:
|
354
|
+
if init_requests_instrumentor():
|
355
|
+
instrument_set = True
|
356
|
+
elif instrument == Instruments.SAGEMAKER:
|
357
|
+
if init_sagemaker_instrumentor(should_enrich_metrics):
|
358
|
+
instrument_set = True
|
359
|
+
elif instrument == Instruments.TOGETHER:
|
360
|
+
if init_together_instrumentor():
|
361
|
+
instrument_set = True
|
362
|
+
elif instrument == Instruments.TRANSFORMERS:
|
363
|
+
if init_transformers_instrumentor():
|
364
|
+
instrument_set = True
|
365
|
+
elif instrument == Instruments.URLLIB3:
|
366
|
+
if init_urllib3_instrumentor():
|
367
|
+
instrument_set = True
|
368
|
+
elif instrument == Instruments.VERTEXAI:
|
369
|
+
if init_vertexai_instrumentor():
|
370
|
+
instrument_set = True
|
371
|
+
elif instrument == Instruments.WATSONX:
|
372
|
+
if init_watsonx_instrumentor():
|
373
|
+
instrument_set = True
|
374
|
+
elif instrument == Instruments.WEAVIATE:
|
375
|
+
if init_weaviate_instrumentor():
|
376
|
+
instrument_set = True
|
377
|
+
else:
|
378
|
+
logging.warning(f"Warning: {instrument} instrumentation does not exist.")
|
379
|
+
logging.warning(
|
380
|
+
"Usage:\n"
|
381
|
+
"from lmnr import Laminar, Instruments\n"
|
382
|
+
"Laminar.init(instruments=set([Instruments.OPENAI]))"
|
383
|
+
)
|
384
|
+
|
385
|
+
if not instrument_set:
|
386
|
+
logging.warning(
|
387
|
+
"Warning: No valid instruments set. "
|
388
|
+
+ "Specify instruments or remove 'instruments' argument to use all instruments."
|
389
|
+
)
|
390
|
+
|
391
|
+
return instrument_set
|
398
392
|
|
399
393
|
|
400
394
|
def init_openai_instrumentor(should_enrich_metrics: bool):
|
401
395
|
try:
|
402
396
|
if is_package_installed("openai"):
|
403
|
-
# Telemetry().capture("instrumentation:openai:init")
|
404
397
|
from opentelemetry.instrumentation.openai import OpenAIInstrumentor
|
405
398
|
|
406
399
|
instrumentor = OpenAIInstrumentor(
|
407
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
408
400
|
enrich_assistant=should_enrich_metrics,
|
409
401
|
enrich_token_usage=should_enrich_metrics,
|
410
402
|
)
|
@@ -414,18 +406,15 @@ def init_openai_instrumentor(should_enrich_metrics: bool):
|
|
414
406
|
|
415
407
|
except Exception as e:
|
416
408
|
logging.error(f"Error initializing OpenAI instrumentor: {e}")
|
417
|
-
# Telemetry().log_exception(e)
|
418
409
|
return False
|
419
410
|
|
420
411
|
|
421
412
|
def init_anthropic_instrumentor(should_enrich_metrics: bool):
|
422
413
|
try:
|
423
414
|
if is_package_installed("anthropic"):
|
424
|
-
# Telemetry().capture("instrumentation:anthropic:init")
|
425
415
|
from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
|
426
416
|
|
427
417
|
instrumentor = AnthropicInstrumentor(
|
428
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
429
418
|
enrich_token_usage=should_enrich_metrics,
|
430
419
|
upload_base64_image=None,
|
431
420
|
)
|
@@ -434,246 +423,193 @@ def init_anthropic_instrumentor(should_enrich_metrics: bool):
|
|
434
423
|
return True
|
435
424
|
except Exception as e:
|
436
425
|
logging.error(f"Error initializing Anthropic instrumentor: {e}")
|
437
|
-
# Telemetry().log_exception(e)
|
438
426
|
return False
|
439
427
|
|
440
428
|
|
441
429
|
def init_cohere_instrumentor():
|
442
430
|
try:
|
443
431
|
if is_package_installed("cohere"):
|
444
|
-
# Telemetry().capture("instrumentation:cohere:init")
|
445
432
|
from opentelemetry.instrumentation.cohere import CohereInstrumentor
|
446
433
|
|
447
|
-
instrumentor = CohereInstrumentor(
|
448
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
449
|
-
)
|
434
|
+
instrumentor = CohereInstrumentor()
|
450
435
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
451
436
|
instrumentor.instrument()
|
452
437
|
return True
|
453
438
|
except Exception as e:
|
454
439
|
logging.error(f"Error initializing Cohere instrumentor: {e}")
|
455
|
-
# Telemetry().log_exception(e)
|
456
440
|
return False
|
457
441
|
|
458
442
|
|
459
443
|
def init_pinecone_instrumentor():
|
460
444
|
try:
|
461
445
|
if is_package_installed("pinecone"):
|
462
|
-
# Telemetry().capture("instrumentation:pinecone:init")
|
463
446
|
from opentelemetry.instrumentation.pinecone import PineconeInstrumentor
|
464
447
|
|
465
|
-
instrumentor = PineconeInstrumentor(
|
466
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
467
|
-
)
|
448
|
+
instrumentor = PineconeInstrumentor()
|
468
449
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
469
450
|
instrumentor.instrument()
|
470
451
|
return True
|
471
452
|
except Exception as e:
|
472
453
|
logging.error(f"Error initializing Pinecone instrumentor: {e}")
|
473
|
-
# Telemetry().log_exception(e)
|
474
454
|
return False
|
475
455
|
|
476
456
|
|
477
457
|
def init_qdrant_instrumentor():
|
478
458
|
try:
|
479
459
|
if is_package_installed("qdrant_client"):
|
480
|
-
# Telemetry().capture("instrumentation:qdrant:init")
|
481
460
|
from opentelemetry.instrumentation.qdrant import QdrantInstrumentor
|
482
461
|
|
483
|
-
instrumentor = QdrantInstrumentor(
|
484
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
485
|
-
)
|
462
|
+
instrumentor = QdrantInstrumentor()
|
486
463
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
487
464
|
instrumentor.instrument()
|
488
465
|
except Exception as e:
|
489
466
|
logging.error(f"Error initializing Qdrant instrumentor: {e}")
|
490
|
-
# Telemetry().log_exception(e)
|
491
467
|
return False
|
492
468
|
|
493
469
|
|
494
470
|
def init_chroma_instrumentor():
|
495
471
|
try:
|
496
472
|
if is_package_installed("chromadb"):
|
497
|
-
# Telemetry().capture("instrumentation:chromadb:init")
|
498
473
|
from opentelemetry.instrumentation.chromadb import ChromaInstrumentor
|
499
474
|
|
500
|
-
instrumentor = ChromaInstrumentor(
|
501
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
502
|
-
)
|
475
|
+
instrumentor = ChromaInstrumentor()
|
503
476
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
504
477
|
instrumentor.instrument()
|
505
478
|
return True
|
506
479
|
except Exception as e:
|
507
480
|
logging.error(f"Error initializing Chroma instrumentor: {e}")
|
508
|
-
# Telemetry().log_exception(e)
|
509
481
|
return False
|
510
482
|
|
511
483
|
|
512
484
|
def init_google_generativeai_instrumentor():
|
513
485
|
try:
|
514
486
|
if is_package_installed("google.generativeai"):
|
515
|
-
# Telemetry().capture("instrumentation:gemini:init")
|
516
487
|
from opentelemetry.instrumentation.google_generativeai import (
|
517
488
|
GoogleGenerativeAiInstrumentor,
|
518
489
|
)
|
519
490
|
|
520
|
-
instrumentor = GoogleGenerativeAiInstrumentor(
|
521
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
522
|
-
)
|
491
|
+
instrumentor = GoogleGenerativeAiInstrumentor()
|
523
492
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
524
493
|
instrumentor.instrument()
|
525
494
|
return True
|
526
495
|
except Exception as e:
|
527
496
|
logging.error(f"Error initializing Gemini instrumentor: {e}")
|
528
|
-
# Telemetry().log_exception(e)
|
529
497
|
return False
|
530
498
|
|
531
499
|
|
532
500
|
def init_haystack_instrumentor():
|
533
501
|
try:
|
534
502
|
if is_package_installed("haystack"):
|
535
|
-
# Telemetry().capture("instrumentation:haystack:init")
|
536
503
|
from opentelemetry.instrumentation.haystack import HaystackInstrumentor
|
537
504
|
|
538
|
-
instrumentor = HaystackInstrumentor(
|
539
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
540
|
-
)
|
505
|
+
instrumentor = HaystackInstrumentor()
|
541
506
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
542
507
|
instrumentor.instrument()
|
543
508
|
return True
|
544
509
|
except Exception as e:
|
545
510
|
logging.error(f"Error initializing Haystack instrumentor: {e}")
|
546
|
-
# Telemetry().log_exception(e)
|
547
511
|
return False
|
548
512
|
|
549
513
|
|
550
514
|
def init_langchain_instrumentor():
|
551
515
|
try:
|
552
516
|
if is_package_installed("langchain"):
|
553
|
-
# Telemetry().capture("instrumentation:langchain:init")
|
554
517
|
from opentelemetry.instrumentation.langchain import LangchainInstrumentor
|
555
518
|
|
556
|
-
instrumentor = LangchainInstrumentor(
|
557
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
558
|
-
)
|
519
|
+
instrumentor = LangchainInstrumentor()
|
559
520
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
560
521
|
instrumentor.instrument()
|
561
522
|
return True
|
562
523
|
except Exception as e:
|
563
|
-
# FIXME:
|
524
|
+
# FIXME: silencing this error temporarily, it appears to not be critical
|
564
525
|
if str(e) != "No module named 'langchain_community'":
|
565
526
|
logging.error(f"Error initializing LangChain instrumentor: {e}")
|
566
|
-
# Telemetry().log_exception(e)
|
567
527
|
return False
|
568
528
|
|
569
529
|
|
570
530
|
def init_mistralai_instrumentor():
|
571
531
|
try:
|
572
532
|
if is_package_installed("mistralai"):
|
573
|
-
# Telemetry().capture("instrumentation:mistralai:init")
|
574
533
|
from opentelemetry.instrumentation.mistralai import MistralAiInstrumentor
|
575
534
|
|
576
|
-
instrumentor = MistralAiInstrumentor(
|
577
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
578
|
-
)
|
535
|
+
instrumentor = MistralAiInstrumentor()
|
579
536
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
580
537
|
instrumentor.instrument()
|
581
538
|
return True
|
582
539
|
except Exception as e:
|
583
540
|
logging.error(f"Error initializing MistralAI instrumentor: {e}")
|
584
|
-
# Telemetry().log_exception(e)
|
585
541
|
return False
|
586
542
|
|
587
543
|
|
588
544
|
def init_ollama_instrumentor():
|
589
545
|
try:
|
590
546
|
if is_package_installed("ollama"):
|
591
|
-
# Telemetry().capture("instrumentation:ollama:init")
|
592
547
|
from opentelemetry.instrumentation.ollama import OllamaInstrumentor
|
593
548
|
|
594
|
-
instrumentor = OllamaInstrumentor(
|
595
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
596
|
-
)
|
549
|
+
instrumentor = OllamaInstrumentor()
|
597
550
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
598
551
|
instrumentor.instrument()
|
599
552
|
return True
|
600
553
|
except Exception as e:
|
601
554
|
logging.error(f"Error initializing Ollama instrumentor: {e}")
|
602
|
-
# Telemetry().log_exception(e)
|
603
555
|
return False
|
604
556
|
|
605
557
|
|
606
558
|
def init_transformers_instrumentor():
|
607
559
|
try:
|
608
560
|
if is_package_installed("transformers"):
|
609
|
-
# Telemetry().capture("instrumentation:transformers:init")
|
610
561
|
from opentelemetry.instrumentation.transformers import (
|
611
562
|
TransformersInstrumentor,
|
612
563
|
)
|
613
564
|
|
614
|
-
instrumentor = TransformersInstrumentor(
|
615
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
616
|
-
)
|
565
|
+
instrumentor = TransformersInstrumentor()
|
617
566
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
618
567
|
instrumentor.instrument()
|
619
568
|
return True
|
620
569
|
except Exception as e:
|
621
570
|
logging.error(f"Error initializing Transformers instrumentor: {e}")
|
622
|
-
# Telemetry().log_exception(e)
|
623
571
|
return False
|
624
572
|
|
625
573
|
|
626
574
|
def init_together_instrumentor():
|
627
575
|
try:
|
628
576
|
if is_package_installed("together"):
|
629
|
-
# Telemetry().capture("instrumentation:together:init")
|
630
577
|
from opentelemetry.instrumentation.together import TogetherAiInstrumentor
|
631
578
|
|
632
|
-
instrumentor = TogetherAiInstrumentor(
|
633
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
634
|
-
)
|
579
|
+
instrumentor = TogetherAiInstrumentor()
|
635
580
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
636
581
|
instrumentor.instrument()
|
637
582
|
return True
|
638
583
|
except Exception as e:
|
639
584
|
logging.error(f"Error initializing TogetherAI instrumentor: {e}")
|
640
|
-
# Telemetry().log_exception(e)
|
641
585
|
return False
|
642
586
|
|
643
587
|
|
644
588
|
def init_llama_index_instrumentor():
|
645
589
|
try:
|
646
590
|
if is_package_installed("llama-index") or is_package_installed("llama_index"):
|
647
|
-
# Telemetry().capture("instrumentation:llamaindex:init")
|
648
591
|
from opentelemetry.instrumentation.llamaindex import LlamaIndexInstrumentor
|
649
592
|
|
650
|
-
instrumentor = LlamaIndexInstrumentor(
|
651
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
652
|
-
)
|
593
|
+
instrumentor = LlamaIndexInstrumentor()
|
653
594
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
654
595
|
instrumentor.instrument()
|
655
596
|
return True
|
656
597
|
except Exception as e:
|
657
598
|
logging.error(f"Error initializing LlamaIndex instrumentor: {e}")
|
658
|
-
# Telemetry().log_exception(e)
|
659
599
|
return False
|
660
600
|
|
661
601
|
|
662
602
|
def init_milvus_instrumentor():
|
663
603
|
try:
|
664
604
|
if is_package_installed("pymilvus"):
|
665
|
-
# Telemetry().capture("instrumentation:milvus:init")
|
666
605
|
from opentelemetry.instrumentation.milvus import MilvusInstrumentor
|
667
606
|
|
668
|
-
instrumentor = MilvusInstrumentor(
|
669
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
670
|
-
)
|
607
|
+
instrumentor = MilvusInstrumentor()
|
671
608
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
672
609
|
instrumentor.instrument()
|
673
610
|
return True
|
674
611
|
except Exception as e:
|
675
612
|
logging.error(f"Error initializing Milvus instrumentor: {e}")
|
676
|
-
# Telemetry().log_exception(e)
|
677
613
|
return False
|
678
614
|
|
679
615
|
|
@@ -688,7 +624,6 @@ def init_requests_instrumentor():
|
|
688
624
|
return True
|
689
625
|
except Exception as e:
|
690
626
|
logging.error(f"Error initializing Requests instrumentor: {e}")
|
691
|
-
# Telemetry().log_exception(e)
|
692
627
|
return False
|
693
628
|
|
694
629
|
|
@@ -703,7 +638,6 @@ def init_urllib3_instrumentor():
|
|
703
638
|
return True
|
704
639
|
except Exception as e:
|
705
640
|
logging.error(f"Error initializing urllib3 instrumentor: {e}")
|
706
|
-
# Telemetry().log_exception(e)
|
707
641
|
return False
|
708
642
|
|
709
643
|
|
@@ -718,7 +652,6 @@ def init_pymysql_instrumentor():
|
|
718
652
|
return True
|
719
653
|
except Exception as e:
|
720
654
|
logging.error(f"Error initializing SQLAlchemy instrumentor: {e}")
|
721
|
-
# Telemetry().log_exception(e)
|
722
655
|
return False
|
723
656
|
|
724
657
|
|
@@ -728,7 +661,6 @@ def init_bedrock_instrumentor(should_enrich_metrics: bool):
|
|
728
661
|
from opentelemetry.instrumentation.bedrock import BedrockInstrumentor
|
729
662
|
|
730
663
|
instrumentor = BedrockInstrumentor(
|
731
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
732
664
|
enrich_token_usage=should_enrich_metrics,
|
733
665
|
)
|
734
666
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
@@ -736,43 +668,34 @@ def init_bedrock_instrumentor(should_enrich_metrics: bool):
|
|
736
668
|
return True
|
737
669
|
except Exception as e:
|
738
670
|
logging.error(f"Error initializing Bedrock instrumentor: {e}")
|
739
|
-
# Telemetry().log_exception(e)
|
740
671
|
return False
|
741
672
|
|
742
673
|
|
743
674
|
def init_replicate_instrumentor():
|
744
675
|
try:
|
745
676
|
if is_package_installed("replicate"):
|
746
|
-
# Telemetry().capture("instrumentation:replicate:init")
|
747
677
|
from opentelemetry.instrumentation.replicate import ReplicateInstrumentor
|
748
678
|
|
749
|
-
instrumentor = ReplicateInstrumentor(
|
750
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
751
|
-
)
|
679
|
+
instrumentor = ReplicateInstrumentor()
|
752
680
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
753
681
|
instrumentor.instrument()
|
754
682
|
return True
|
755
683
|
except Exception as e:
|
756
684
|
logging.error(f"Error initializing Replicate instrumentor: {e}")
|
757
|
-
# Telemetry().log_exception(e)
|
758
685
|
return False
|
759
686
|
|
760
687
|
|
761
688
|
def init_vertexai_instrumentor():
|
762
689
|
try:
|
763
690
|
if is_package_installed("vertexai"):
|
764
|
-
# Telemetry().capture("instrumentation:vertexai:init")
|
765
691
|
from opentelemetry.instrumentation.vertexai import VertexAIInstrumentor
|
766
692
|
|
767
|
-
instrumentor = VertexAIInstrumentor(
|
768
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
769
|
-
)
|
693
|
+
instrumentor = VertexAIInstrumentor()
|
770
694
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
771
695
|
instrumentor.instrument()
|
772
696
|
return True
|
773
697
|
except Exception as e:
|
774
698
|
logging.warning(f"Error initializing Vertex AI instrumentor: {e}")
|
775
|
-
# Telemetry().log_exception(e)
|
776
699
|
return False
|
777
700
|
|
778
701
|
|
@@ -781,84 +704,65 @@ def init_watsonx_instrumentor():
|
|
781
704
|
if is_package_installed("ibm-watsonx-ai") or is_package_installed(
|
782
705
|
"ibm-watson-machine-learning"
|
783
706
|
):
|
784
|
-
# Telemetry().capture("instrumentation:watsonx:init")
|
785
707
|
from opentelemetry.instrumentation.watsonx import WatsonxInstrumentor
|
786
708
|
|
787
|
-
instrumentor = WatsonxInstrumentor(
|
788
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
789
|
-
)
|
709
|
+
instrumentor = WatsonxInstrumentor()
|
790
710
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
791
711
|
instrumentor.instrument()
|
792
712
|
return True
|
793
713
|
except Exception as e:
|
794
714
|
logging.warning(f"Error initializing Watsonx instrumentor: {e}")
|
795
|
-
# Telemetry().log_exception(e)
|
796
715
|
return False
|
797
716
|
|
798
717
|
|
799
718
|
def init_weaviate_instrumentor():
|
800
719
|
try:
|
801
720
|
if is_package_installed("weaviate"):
|
802
|
-
# Telemetry().capture("instrumentation:weaviate:init")
|
803
721
|
from opentelemetry.instrumentation.weaviate import WeaviateInstrumentor
|
804
722
|
|
805
|
-
instrumentor = WeaviateInstrumentor(
|
806
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
807
|
-
)
|
723
|
+
instrumentor = WeaviateInstrumentor()
|
808
724
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
809
725
|
instrumentor.instrument()
|
810
726
|
return True
|
811
727
|
except Exception as e:
|
812
728
|
logging.warning(f"Error initializing Weaviate instrumentor: {e}")
|
813
|
-
# Telemetry().log_exception(e)
|
814
729
|
return False
|
815
730
|
|
816
731
|
|
817
732
|
def init_alephalpha_instrumentor():
|
818
733
|
try:
|
819
734
|
if is_package_installed("aleph_alpha_client"):
|
820
|
-
# Telemetry().capture("instrumentation:alephalpha:init")
|
821
735
|
from opentelemetry.instrumentation.alephalpha import AlephAlphaInstrumentor
|
822
736
|
|
823
|
-
instrumentor = AlephAlphaInstrumentor(
|
824
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
825
|
-
)
|
737
|
+
instrumentor = AlephAlphaInstrumentor()
|
826
738
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
827
739
|
instrumentor.instrument()
|
828
740
|
return True
|
829
741
|
except Exception as e:
|
830
742
|
logging.error(f"Error initializing Aleph Alpha instrumentor: {e}")
|
831
|
-
# Telemetry().log_exception(e)
|
832
743
|
return False
|
833
744
|
|
834
745
|
|
835
746
|
def init_marqo_instrumentor():
|
836
747
|
try:
|
837
748
|
if is_package_installed("marqo"):
|
838
|
-
# Telemetry().capture("instrumentation:marqo:init")
|
839
749
|
from opentelemetry.instrumentation.marqo import MarqoInstrumentor
|
840
750
|
|
841
|
-
instrumentor = MarqoInstrumentor(
|
842
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
843
|
-
)
|
751
|
+
instrumentor = MarqoInstrumentor()
|
844
752
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
845
753
|
instrumentor.instrument()
|
846
754
|
return True
|
847
755
|
except Exception as e:
|
848
756
|
logging.error(f"Error initializing marqo instrumentor: {e}")
|
849
|
-
# Telemetry().log_exception(e)
|
850
757
|
return False
|
851
758
|
|
852
759
|
|
853
760
|
def init_lancedb_instrumentor():
|
854
761
|
try:
|
855
762
|
if is_package_installed("lancedb"):
|
856
|
-
# Telemetry().capture("instrumentation:lancedb:init")
|
857
763
|
from opentelemetry.instrumentation.lancedb import LanceInstrumentor
|
858
764
|
|
859
|
-
instrumentor = LanceInstrumentor(
|
860
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
861
|
-
)
|
765
|
+
instrumentor = LanceInstrumentor()
|
862
766
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
863
767
|
instrumentor.instrument()
|
864
768
|
return True
|
@@ -877,23 +781,34 @@ def init_redis_instrumentor():
|
|
877
781
|
return True
|
878
782
|
except Exception as e:
|
879
783
|
logging.error(f"Error initializing redis instrumentor: {e}")
|
880
|
-
# Telemetry().log_exception(e)
|
881
784
|
return False
|
882
785
|
|
883
786
|
|
884
787
|
def init_groq_instrumentor():
|
885
788
|
try:
|
886
789
|
if is_package_installed("groq"):
|
887
|
-
# Telemetry().capture("instrumentation:groq:init")
|
888
790
|
from opentelemetry.instrumentation.groq import GroqInstrumentor
|
889
791
|
|
890
|
-
instrumentor = GroqInstrumentor(
|
891
|
-
# exception_logger=lambda e: Telemetry().log_exception(e),
|
892
|
-
)
|
792
|
+
instrumentor = GroqInstrumentor()
|
893
793
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
894
794
|
instrumentor.instrument()
|
895
795
|
return True
|
896
796
|
except Exception as e:
|
897
797
|
logging.error(f"Error initializing Groq instrumentor: {e}")
|
898
|
-
|
798
|
+
return False
|
799
|
+
|
800
|
+
|
801
|
+
def init_sagemaker_instrumentor(should_enrich_metrics: bool):
|
802
|
+
try:
|
803
|
+
if is_package_installed("boto3"):
|
804
|
+
from opentelemetry.instrumentation.sagemaker import SageMakerInstrumentor
|
805
|
+
|
806
|
+
instrumentor = SageMakerInstrumentor(
|
807
|
+
enrich_token_usage=should_enrich_metrics,
|
808
|
+
)
|
809
|
+
if not instrumentor.is_instrumented_by_opentelemetry:
|
810
|
+
instrumentor.instrument()
|
811
|
+
return True
|
812
|
+
except Exception as e:
|
813
|
+
logging.error(f"Error initializing SageMaker instrumentor: {e}")
|
899
814
|
return False
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: lmnr
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.29
|
4
4
|
Summary: Python SDK for Laminar AI
|
5
5
|
License: Apache-2.0
|
6
6
|
Author: lmnr.ai
|
@@ -39,6 +39,7 @@ Requires-Dist: opentelemetry-instrumentation-pinecone (>=0.33.5)
|
|
39
39
|
Requires-Dist: opentelemetry-instrumentation-qdrant (>=0.33.5)
|
40
40
|
Requires-Dist: opentelemetry-instrumentation-replicate (>=0.33.5)
|
41
41
|
Requires-Dist: opentelemetry-instrumentation-requests (>=0.48b0,<0.49)
|
42
|
+
Requires-Dist: opentelemetry-instrumentation-sagemaker (>=0.33.5)
|
42
43
|
Requires-Dist: opentelemetry-instrumentation-sqlalchemy (>=0.48b0,<0.49)
|
43
44
|
Requires-Dist: opentelemetry-instrumentation-threading (>=0.48b0,<0.49)
|
44
45
|
Requires-Dist: opentelemetry-instrumentation-together (>=0.33.5)
|
@@ -1,20 +1,20 @@
|
|
1
|
-
lmnr/__init__.py,sha256=
|
1
|
+
lmnr/__init__.py,sha256=bIkXw003GaigTxNfGE_gwVtTDGdSdAPUr6CS_nN51oA,430
|
2
2
|
lmnr/cli.py,sha256=Ptvm5dsNLKUY5lwnN8XkT5GtCYjzpRNi2WvefknB3OQ,1079
|
3
3
|
lmnr/sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
lmnr/sdk/datasets.py,sha256=w8U9E6fvetAo65Cb2CbYzlfhY8CfXAR-VysrakG6-4I,1591
|
5
5
|
lmnr/sdk/decorators.py,sha256=ZSDaEZyjo-RUzRCltsNbe6x0t9SKl2xRQ2q4uaKvXtk,2250
|
6
|
-
lmnr/sdk/evaluations.py,sha256=
|
7
|
-
lmnr/sdk/laminar.py,sha256=
|
6
|
+
lmnr/sdk/evaluations.py,sha256=5Vfyp0aIjuGpqfuM3cqsaaLpcoO7z6lcOOKxnyHCNHk,16264
|
7
|
+
lmnr/sdk/laminar.py,sha256=jToA51Yy7c37CWYvgAo3mrfsqvf1huQepck6twgwP4s,21148
|
8
8
|
lmnr/sdk/log.py,sha256=cZBeUoSK39LMEV-X4-eEhTWOciULRfHaKfRK8YqIM8I,1532
|
9
|
-
lmnr/sdk/types.py,sha256=
|
10
|
-
lmnr/sdk/utils.py,sha256=
|
9
|
+
lmnr/sdk/types.py,sha256=qGD1tkGszd-_sZJaZ_Zx9U_CdUYzoDkUeN2g-o48Gls,5588
|
10
|
+
lmnr/sdk/utils.py,sha256=Uk8y15x-sd5tP2ERONahElLDJVEy_3dA_1_5g9A6auY,3358
|
11
11
|
lmnr/traceloop_sdk/.flake8,sha256=bCxuDlGx3YQ55QHKPiGJkncHanh9qGjQJUujcFa3lAU,150
|
12
12
|
lmnr/traceloop_sdk/.python-version,sha256=9OLQBQVbD4zE4cJsPePhnAfV_snrPSoqEQw-PXgPMOs,6
|
13
13
|
lmnr/traceloop_sdk/__init__.py,sha256=hp3q1OsFaGgaQCEanJrL38BJN32hWqCNVCSjYpndEsY,2957
|
14
14
|
lmnr/traceloop_sdk/config/__init__.py,sha256=DliMGp2NjYAqRFLKpWQPUKjGMHRO8QsVfazBA1qENQ8,248
|
15
15
|
lmnr/traceloop_sdk/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
16
|
lmnr/traceloop_sdk/decorators/base.py,sha256=SeImd8SAeqdC8LV1bvoQUq0d_TLkOLyd5HCe7vXKhNU,5559
|
17
|
-
lmnr/traceloop_sdk/instruments.py,sha256=
|
17
|
+
lmnr/traceloop_sdk/instruments.py,sha256=CGGUEELldrXkQwAzAkDeAtDq07_pjhz7i14a92P7C_E,1036
|
18
18
|
lmnr/traceloop_sdk/tests/__init__.py,sha256=RYnG0-8zbXL0-2Ste1mEBf5sN4d_rQjGTCgPBuaZC74,20
|
19
19
|
lmnr/traceloop_sdk/tests/cassettes/test_association_properties/test_langchain_and_external_association_properties.yaml,sha256=26g0wRA0juicHg_XrhcE8H4vhs1lawDs0o0aLFn-I7w,3103
|
20
20
|
lmnr/traceloop_sdk/tests/cassettes/test_association_properties/test_langchain_association_properties.yaml,sha256=FNlSWlYCsWc3w7UPZzfGjDnxS3gAOhL-kpsu4BTxsDE,3061
|
@@ -39,14 +39,14 @@ lmnr/traceloop_sdk/tracing/__init__.py,sha256=Ckq7zCM26VdJVB5tIZv0GTPyMZKyfso_KW
|
|
39
39
|
lmnr/traceloop_sdk/tracing/attributes.py,sha256=QeqItpCCwUipkwgXG7J7swJCD0yk9uuI28aepPhemtE,1201
|
40
40
|
lmnr/traceloop_sdk/tracing/content_allow_list.py,sha256=3feztm6PBWNelc8pAZUcQyEGyeSpNiVKjOaDk65l2ps,846
|
41
41
|
lmnr/traceloop_sdk/tracing/context_manager.py,sha256=csVlB6kDmbgSPsROHwnddvGGblx55v6lJMRj0wsSMQM,304
|
42
|
-
lmnr/traceloop_sdk/tracing/tracing.py,sha256=
|
42
|
+
lmnr/traceloop_sdk/tracing/tracing.py,sha256=hFqTp7OGMCZnfxVtrmRq3wP3Ph5YvHq3fz9p00_Yk-Q,29433
|
43
43
|
lmnr/traceloop_sdk/utils/__init__.py,sha256=pNhf0G3vTd5ccoc03i1MXDbricSaiqCbi1DLWhSekK8,604
|
44
44
|
lmnr/traceloop_sdk/utils/in_memory_span_exporter.py,sha256=H_4TRaThMO1H6vUQ0OpQvzJk_fZH0OOsRAM1iZQXsR8,2112
|
45
45
|
lmnr/traceloop_sdk/utils/json_encoder.py,sha256=dK6b_axr70IYL7Vv-bu4wntvDDuyntoqsHaddqX7P58,463
|
46
46
|
lmnr/traceloop_sdk/utils/package_check.py,sha256=TZSngzJOpFhfUZLXIs38cpMxQiZSmp0D-sCrIyhz7BA,251
|
47
47
|
lmnr/traceloop_sdk/version.py,sha256=OlatFEFA4ttqSSIiV8jdE-sq3KG5zu2hnC4B4mzWF3s,23
|
48
|
-
lmnr-0.4.
|
49
|
-
lmnr-0.4.
|
50
|
-
lmnr-0.4.
|
51
|
-
lmnr-0.4.
|
52
|
-
lmnr-0.4.
|
48
|
+
lmnr-0.4.29.dist-info/LICENSE,sha256=67b_wJHVV1CBaWkrKFWU1wyqTPSdzH77Ls-59631COg,10411
|
49
|
+
lmnr-0.4.29.dist-info/METADATA,sha256=e8-yJiO243QVOTNOMeoEcojnAflYXF8XNh8az7Y75h4,10688
|
50
|
+
lmnr-0.4.29.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
51
|
+
lmnr-0.4.29.dist-info/entry_points.txt,sha256=K1jE20ww4jzHNZLnsfWBvU3YKDGBgbOiYG5Y7ivQcq4,37
|
52
|
+
lmnr-0.4.29.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|