lmnr 0.4.12b2__py3-none-any.whl → 0.4.12b4__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.
@@ -0,0 +1,8 @@
1
+ SPAN_INPUT = "lmnr.span.input"
2
+ SPAN_OUTPUT = "lmnr.span.output"
3
+ SPAN_TYPE = "lmnr.span.type"
4
+
5
+ ASSOCIATION_PROPERTIES = "lmnr.association.properties"
6
+ SESSION_ID = "session_id"
7
+ USER_ID = "user_id"
8
+ TRACE_TYPE = "trace_type"
@@ -3,7 +3,6 @@ import logging
3
3
  import os
4
4
 
5
5
 
6
- from colorama import Fore
7
6
  from opentelemetry import trace
8
7
  from opentelemetry.exporter.otlp.proto.http.trace_exporter import (
9
8
  OTLPSpanExporter as HTTPExporter,
@@ -24,17 +23,16 @@ from opentelemetry.trace import get_tracer_provider, ProxyTracerProvider
24
23
  from opentelemetry.context import get_value, attach, set_value
25
24
  from opentelemetry.instrumentation.threading import ThreadingInstrumentor
26
25
 
27
- from opentelemetry.semconv_ai import SpanAttributes
28
-
29
26
  # from lmnr.traceloop_sdk import Telemetry
30
27
  from lmnr.traceloop_sdk.instruments import Instruments
28
+ from lmnr.traceloop_sdk.tracing.attributes import ASSOCIATION_PROPERTIES
31
29
  from lmnr.traceloop_sdk.tracing.content_allow_list import ContentAllowList
32
30
  from lmnr.traceloop_sdk.utils import is_notebook
33
31
  from lmnr.traceloop_sdk.utils.package_check import is_package_installed
34
32
  from typing import Dict, Optional, Set
35
33
 
36
34
 
37
- TRACER_NAME = "traceloop.tracer"
35
+ TRACER_NAME = "lmnr.tracer"
38
36
  EXCLUDED_URLS = """
39
37
  iam.cloud.ibm.com,
40
38
  dataplatform.cloud.ibm.com,
@@ -44,7 +42,7 @@ EXCLUDED_URLS = """
44
42
  api.anthropic.com,
45
43
  api.cohere.ai,
46
44
  pinecone.io,
47
- traceloop.com,
45
+ api.lmnr.ai,
48
46
  posthog.com,
49
47
  sentry.io,
50
48
  bedrock-runtime,
@@ -130,138 +128,103 @@ class TracerWrapper(object):
130
128
  for instrument in instruments:
131
129
  if instrument == Instruments.OPENAI:
132
130
  if not init_openai_instrumentor(should_enrich_metrics):
133
- print(Fore.RED + "Warning: OpenAI library does not exist.")
134
- print(Fore.RESET)
131
+ print("Warning: OpenAI library does not exist.")
135
132
  elif instrument == Instruments.ANTHROPIC:
136
133
  if not init_anthropic_instrumentor(should_enrich_metrics):
137
134
  print(
138
- Fore.RED + "Warning: Anthropic library does not exist."
135
+ "Warning: Anthropic library does not exist."
139
136
  )
140
- print(Fore.RESET)
141
137
  elif instrument == Instruments.COHERE:
142
138
  if not init_cohere_instrumentor():
143
- print(Fore.RED + "Warning: Cohere library does not exist.")
144
- print(Fore.RESET)
139
+ print("Warning: Cohere library does not exist.")
145
140
  elif instrument == Instruments.PINECONE:
146
141
  if not init_pinecone_instrumentor():
147
142
  print(
148
- Fore.RED + "Warning: Pinecone library does not exist."
143
+ "Warning: Pinecone library does not exist."
149
144
  )
150
- print(Fore.RESET)
151
145
  elif instrument == Instruments.CHROMA:
152
146
  if not init_chroma_instrumentor():
153
- print(Fore.RED + "Warning: Chroma library does not exist.")
154
- print(Fore.RESET)
147
+ print("Warning: Chroma library does not exist.")
155
148
  elif instrument == Instruments.GOOGLE_GENERATIVEAI:
156
149
  if not init_google_generativeai_instrumentor():
157
- print(
158
- Fore.RED
159
- + "Warning: Google Generative AI library does not exist."
160
- )
161
- print(Fore.RESET)
150
+ print("Warning: Google Generative AI library does not exist.")
162
151
  elif instrument == Instruments.LANGCHAIN:
163
152
  if not init_langchain_instrumentor():
164
153
  print(
165
- Fore.RED + "Warning: LangChain library does not exist."
154
+ "Warning: LangChain library does not exist."
166
155
  )
167
- print(Fore.RESET)
168
156
  elif instrument == Instruments.MISTRAL:
169
157
  if not init_mistralai_instrumentor():
170
158
  print(
171
- Fore.RED + "Warning: MistralAI library does not exist."
159
+ "Warning: MistralAI library does not exist."
172
160
  )
173
- print(Fore.RESET)
174
161
  elif instrument == Instruments.OLLAMA:
175
162
  if not init_ollama_instrumentor():
176
- print(Fore.RED + "Warning: Ollama library does not exist.")
177
- print(Fore.RESET)
163
+ print("Warning: Ollama library does not exist.")
178
164
  elif instrument == Instruments.LLAMA_INDEX:
179
165
  if not init_llama_index_instrumentor():
180
166
  print(
181
- Fore.RED + "Warning: LlamaIndex library does not exist."
167
+ "Warning: LlamaIndex library does not exist."
182
168
  )
183
- print(Fore.RESET)
184
169
  elif instrument == Instruments.MILVUS:
185
170
  if not init_milvus_instrumentor():
186
- print(Fore.RED + "Warning: Milvus library does not exist.")
187
- print(Fore.RESET)
171
+ print("Warning: Milvus library does not exist.")
188
172
  elif instrument == Instruments.TRANSFORMERS:
189
173
  if not init_transformers_instrumentor():
190
- print(
191
- Fore.RED
192
- + "Warning: Transformers library does not exist."
193
- )
194
- print(Fore.RESET)
174
+ print("Warning: Transformers library does not exist.")
195
175
  elif instrument == Instruments.TOGETHER:
196
176
  if not init_together_instrumentor():
197
177
  print(
198
- Fore.RED + "Warning: TogetherAI library does not exist."
178
+ "Warning: TogetherAI library does not exist."
199
179
  )
200
- print(Fore.RESET)
201
180
  elif instrument == Instruments.REQUESTS:
202
181
  if not init_requests_instrumentor():
203
182
  print(
204
- Fore.RED + "Warning: Requests library does not exist."
183
+ "Warning: Requests library does not exist."
205
184
  )
206
- print(Fore.RESET)
207
185
  elif instrument == Instruments.URLLIB3:
208
186
  if not init_urllib3_instrumentor():
209
- print(Fore.RED + "Warning: urllib3 library does not exist.")
210
- print(Fore.RESET)
187
+ print("Warning: urllib3 library does not exist.")
211
188
  elif instrument == Instruments.PYMYSQL:
212
189
  if not init_pymysql_instrumentor():
213
- print(Fore.RED + "Warning: PyMySQL library does not exist.")
214
- print(Fore.RESET)
190
+ print("Warning: PyMySQL library does not exist.")
215
191
  elif instrument == Instruments.BEDROCK:
216
192
  if not init_bedrock_instrumentor(should_enrich_metrics):
217
- print(Fore.RED + "Warning: Bedrock library does not exist.")
218
- print(Fore.RESET)
193
+ print("Warning: Bedrock library does not exist.")
219
194
  elif instrument == Instruments.REPLICATE:
220
195
  if not init_replicate_instrumentor():
221
196
  print(
222
- Fore.RED + "Warning: Replicate library does not exist."
197
+ "Warning: Replicate library does not exist."
223
198
  )
224
- print(Fore.RESET)
225
199
  elif instrument == Instruments.VERTEXAI:
226
200
  if not init_vertexai_instrumentor():
227
201
  print(
228
- Fore.RED + "Warning: Vertex AI library does not exist."
202
+ "Warning: Vertex AI library does not exist."
229
203
  )
230
- print(Fore.RESET)
231
204
  elif instrument == Instruments.WATSONX:
232
205
  if not init_watsonx_instrumentor():
233
- print(Fore.RED + "Warning: Watsonx library does not exist.")
234
- print(Fore.RESET)
206
+ print("Warning: Watsonx library does not exist.")
235
207
  elif instrument == Instruments.WEAVIATE:
236
208
  if not init_weaviate_instrumentor():
237
209
  print(
238
- Fore.RED + "Warning: Weaviate library does not exist."
210
+ "Warning: Weaviate library does not exist."
239
211
  )
240
- print(Fore.RESET)
241
212
  elif instrument == Instruments.ALEPHALPHA:
242
213
  if not init_alephalpha_instrumentor():
243
- print(
244
- Fore.RED
245
- + "Warning: Aleph Alpha library does not exist."
246
- )
247
- print(Fore.RESET)
214
+ print("Warning: Aleph Alpha library does not exist.")
248
215
  elif instrument == Instruments.MARQO:
249
216
  if not init_marqo_instrumentor():
250
- print(Fore.RED + "Warning: marqo library does not exist.")
251
- print(Fore.RESET)
217
+ print("Warning: marqo library does not exist.")
252
218
  elif instrument == Instruments.LANCEDB:
253
219
  if not init_lancedb_instrumentor():
254
- print(Fore.RED + "Warning: LanceDB library does not exist.")
255
- print(Fore.RESET)
220
+ print("Warning: LanceDB library does not exist.")
256
221
  elif instrument == Instruments.REDIS:
257
222
  if not init_redis_instrumentor():
258
- print(Fore.RED + "Warning: redis library does not exist.")
259
- print(Fore.RESET)
223
+ print("Warning: redis library does not exist.")
260
224
 
261
225
  else:
262
226
  print(
263
- Fore.RED
264
- + "Warning: "
227
+ "Warning: "
265
228
  + instrument
266
229
  + " instrumentation does not exist."
267
230
  )
@@ -270,7 +233,6 @@ class TracerWrapper(object):
270
233
  + "from lmnr.traceloop_sdk.instruments import Instruments\n"
271
234
  + 'Traceloop.init(app_name="...", instruments=set([Instruments.OPENAI]))'
272
235
  )
273
- print(Fore.RESET)
274
236
 
275
237
  obj.__content_allow_list = ContentAllowList()
276
238
 
@@ -293,49 +255,6 @@ class TracerWrapper(object):
293
255
  else:
294
256
  attach(set_value("override_enable_content_tracing", False))
295
257
 
296
- if is_llm_span(span):
297
- managed_prompt = get_value("managed_prompt")
298
- if managed_prompt is not None:
299
- span.set_attribute(
300
- SpanAttributes.TRACELOOP_PROMPT_MANAGED, managed_prompt
301
- )
302
-
303
- prompt_key = get_value("prompt_key")
304
- if prompt_key is not None:
305
- span.set_attribute(SpanAttributes.TRACELOOP_PROMPT_KEY, prompt_key)
306
-
307
- prompt_version = get_value("prompt_version")
308
- if prompt_version is not None:
309
- span.set_attribute(
310
- SpanAttributes.TRACELOOP_PROMPT_VERSION, prompt_version
311
- )
312
-
313
- prompt_version_name = get_value("prompt_version_name")
314
- if prompt_version_name is not None:
315
- span.set_attribute(
316
- SpanAttributes.TRACELOOP_PROMPT_VERSION_NAME, prompt_version_name
317
- )
318
-
319
- prompt_version_hash = get_value("prompt_version_hash")
320
- if prompt_version_hash is not None:
321
- span.set_attribute(
322
- SpanAttributes.TRACELOOP_PROMPT_VERSION_HASH, prompt_version_hash
323
- )
324
-
325
- prompt_template = get_value("prompt_template")
326
- if prompt_template is not None:
327
- span.set_attribute(
328
- SpanAttributes.TRACELOOP_PROMPT_TEMPLATE, prompt_template
329
- )
330
-
331
- prompt_template_variables = get_value("prompt_template_variables")
332
- if prompt_template_variables is not None:
333
- for key, value in prompt_template_variables.items():
334
- span.set_attribute(
335
- f"{SpanAttributes.TRACELOOP_PROMPT_TEMPLATE_VARIABLES}.{key}",
336
- value,
337
- )
338
-
339
258
  # Call original on_start method if it exists in custom processor
340
259
  if self.__spans_processor_original_on_start:
341
260
  self.__spans_processor_original_on_start(span, parent_context)
@@ -360,11 +279,7 @@ class TracerWrapper(object):
360
279
  if (os.getenv("TRACELOOP_SUPPRESS_WARNINGS") or "false").lower() == "true":
361
280
  return False
362
281
 
363
- print(
364
- Fore.RED
365
- + "Warning: Traceloop not initialized, make sure you call Traceloop.init()"
366
- )
367
- print(Fore.RESET)
282
+ print("Warning: Laminar not initialized, make sure to initialize")
368
283
  return False
369
284
 
370
285
  def flush(self):
@@ -399,7 +314,7 @@ def update_association_properties(properties: dict) -> None:
399
314
  def _set_association_properties_attributes(span, properties: dict) -> None:
400
315
  for key, value in properties.items():
401
316
  span.set_attribute(
402
- f"{SpanAttributes.TRACELOOP_ASSOCIATION_PROPERTIES}.{key}", value
317
+ f"{ASSOCIATION_PROPERTIES}.{key}", value
403
318
  )
404
319
 
405
320
 
@@ -427,10 +342,6 @@ def set_external_prompt_tracing_context(
427
342
  attach(set_value("prompt_template_variables", variables))
428
343
 
429
344
 
430
- def is_llm_span(span) -> bool:
431
- return span.attributes.get(SpanAttributes.LLM_REQUEST_TYPE) is not None
432
-
433
-
434
345
  def init_spans_exporter(api_endpoint: str, headers: Dict[str, str]) -> SpanExporter:
435
346
  if "http" in api_endpoint.lower() or "https" in api_endpoint.lower():
436
347
  return HTTPExporter(endpoint=f"{api_endpoint}/v1/traces", headers=headers)
@@ -499,7 +410,6 @@ def init_openai_instrumentor(should_enrich_metrics: bool):
499
410
  # exception_logger=lambda e: Telemetry().log_exception(e),
500
411
  enrich_assistant=should_enrich_metrics,
501
412
  enrich_token_usage=should_enrich_metrics,
502
- get_common_metrics_attributes=metrics_common_attributes,
503
413
  )
504
414
  if not instrumentor.is_instrumented_by_opentelemetry:
505
415
  instrumentor.instrument()
@@ -520,7 +430,6 @@ def init_anthropic_instrumentor(should_enrich_metrics: bool):
520
430
  instrumentor = AnthropicInstrumentor(
521
431
  # exception_logger=lambda e: Telemetry().log_exception(e),
522
432
  enrich_token_usage=should_enrich_metrics,
523
- get_common_metrics_attributes=metrics_common_attributes,
524
433
  )
525
434
  if not instrumentor.is_instrumented_by_opentelemetry:
526
435
  instrumentor.instrument()
@@ -988,23 +897,3 @@ def init_groq_instrumentor():
988
897
  logging.error(f"Error initializing Groq instrumentor: {e}")
989
898
  # Telemetry().log_exception(e)
990
899
  return False
991
-
992
-
993
- def metrics_common_attributes():
994
- common_attributes = {}
995
- workflow_name = get_value("workflow_name")
996
- if workflow_name is not None:
997
- common_attributes[SpanAttributes.TRACELOOP_WORKFLOW_NAME] = workflow_name
998
-
999
- entity_name = get_value("entity_name")
1000
- if entity_name is not None:
1001
- common_attributes[SpanAttributes.TRACELOOP_ENTITY_NAME] = entity_name
1002
-
1003
- association_properties = get_value("association_properties")
1004
- if association_properties is not None:
1005
- for key, value in association_properties.items():
1006
- common_attributes[
1007
- f"{SpanAttributes.TRACELOOP_ASSOCIATION_PROPERTIES}.{key}"
1008
- ] = value
1009
-
1010
- return common_attributes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lmnr
3
- Version: 0.4.12b2
3
+ Version: 0.4.12b4
4
4
  Summary: Python SDK for Laminar AI
5
5
  License: Apache-2.0
6
6
  Author: lmnr.ai
@@ -14,7 +14,6 @@ Classifier: Programming Language :: Python :: 3.12
14
14
  Requires-Dist: argparse (>=1.0,<2.0)
15
15
  Requires-Dist: asyncio (>=3.0,<4.0)
16
16
  Requires-Dist: backoff (>=2.0,<3.0)
17
- Requires-Dist: colorama (>=0.4,<0.5)
18
17
  Requires-Dist: deprecated (>=1.0,<2.0)
19
18
  Requires-Dist: jinja2 (>=3.0,<4.0)
20
19
  Requires-Dist: opentelemetry-api (>=1.27.0,<2.0.0)
@@ -197,7 +196,7 @@ L.initialize(project_api_key=os.environ["LMNR_PROJECT_API_KEY"], instruments={In
197
196
 
198
197
  If you want to fully disable any kind of autoinstrumentation, pass an empty set as `instruments=set()` to `.initialize()`.
199
198
 
200
- Majority of the autoinstrumentations are provided by Traceloop's [OpenLLMetry](https://github.com/traceloop/openllmetry).
199
+ Autoinstrumentations are provided by Traceloop's [OpenLLMetry](https://github.com/traceloop/openllmetry).
201
200
 
202
201
  ## Sending events
203
202
 
@@ -267,13 +266,14 @@ Evaluation takes in the following parameters:
267
266
  - `name` – the name of your evaluation. If no such evaluation exists in the project, it will be created. Otherwise, data will be pushed to the existing evaluation
268
267
  - `data` – an array of `EvaluationDatapoint` objects, where each `EvaluationDatapoint` has two keys: `target` and `data`, each containing a key-value object. Alternatively, you can pass in dictionaries, and we will instantiate `EvaluationDatapoint`s with pydantic if possible
269
268
  - `executor` – the logic you want to evaluate. This function must take `data` as the first argument, and produce any output. *
270
- - `evaluators` – evaluaton logic. List of functions that take output of executor as the first argument, `target` as the second argument and produce a numeric scores. Each function can produce either a single number or `dict[str, int|float]` of scores.
269
+ - `evaluators` – evaluaton logic. Functions that take output of executor as the first argument, `target` as the second argument and produce a numeric scores. Pass a dict from evaluator name to a function. Each function can produce either a single number or `dict[str, int|float]` of scores.
271
270
 
272
271
  \* If you already have the outputs of executors you want to evaluate, you can specify the executor as an identity function, that takes in `data` and returns only needed value(s) from it.
273
272
 
274
- ### Example
273
+ ### Example code
275
274
 
276
275
  ```python
276
+ from lmnr import evaluate
277
277
  from openai import AsyncOpenAI
278
278
  import asyncio
279
279
  import os
@@ -304,20 +304,25 @@ data = [
304
304
  ]
305
305
 
306
306
 
307
- def evaluator_A(output, target):
307
+ def correctness(output, target):
308
308
  return 1 if output == target["capital"] else 0
309
309
 
310
310
 
311
311
  # Create an Evaluation instance
312
- e = Evaluation(
313
- name="py-evaluation-async",
312
+ e = evaluate(
313
+ name="my-evaluation",
314
314
  data=data,
315
315
  executor=get_capital,
316
- evaluators=[evaluator_A],
316
+ evaluators={"correctness": correctness},
317
317
  project_api_key=os.environ["LMNR_PROJECT_API_KEY"],
318
318
  )
319
-
320
- # Run the evaluation
321
- asyncio.run(e.run())
322
319
  ```
323
320
 
321
+ ### Running from CLI.
322
+
323
+ 1. Make sure `lmnr` is installed in a venv. CLI does not work with a global env
324
+ 1. Run `lmnr path/to/my/eval.py`
325
+
326
+ ### Running from code
327
+
328
+ Simply execute the function, e.g. `python3 path/to/my/eval.py`
@@ -1,21 +1,19 @@
1
1
  lmnr/__init__.py,sha256=5Ks8UIicCzCBgwSz0MOX3I7jVruPMUO3SmxIwUoODzQ,231
2
2
  lmnr/cli.py,sha256=Ptvm5dsNLKUY5lwnN8XkT5GtCYjzpRNi2WvefknB3OQ,1079
3
3
  lmnr/sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- lmnr/sdk/decorators.py,sha256=O8S4PI6LUfdWPkbroigl5khtnkyhp24J8qzSdlvCs44,2227
5
- lmnr/sdk/evaluations.py,sha256=V-oupZNkEmBVHtlbvMhH4Rb8dDIETYi79Dvy7de2M9c,10018
6
- lmnr/sdk/laminar.py,sha256=r9jTmIg4ljPlMiy6RVkmldd2i8l4p16ixmvVwyI8jOE,19001
4
+ lmnr/sdk/decorators.py,sha256=ii7Bqp6flaanIFSK6M1_ZZV-izp4o3hkR1MmY7wnFQQ,2227
5
+ lmnr/sdk/evaluations.py,sha256=kVf6cZAF53HMYIdmlaTV5YD0UdPsv_YCzvs1Mts9Zps,13587
6
+ lmnr/sdk/laminar.py,sha256=3LqzqhsSOHxz11_lxAdvqy_awtOnTdPTeYxYEZ3F4Go,19407
7
7
  lmnr/sdk/log.py,sha256=EgAMY77Zn1bv1imCqrmflD3imoAJ2yveOkIcrIP3e98,1170
8
- lmnr/sdk/types.py,sha256=nSN6Z4CDVFJ0o-vjzIT1qzwRiJ70pReGpqdNOcjXKic,4062
9
- lmnr/sdk/utils.py,sha256=ZsGJ86tq8lIbvOhSb1gJWH5K3GylO_lgX68FN6rG2nM,3358
8
+ lmnr/sdk/types.py,sha256=QB89q6WeN715x15ukoRVufXk6FSP_1pGn8QsUSIJG5U,5062
9
+ lmnr/sdk/utils.py,sha256=s81p6uJehgJSaLWy3sR5fTpEDH7vzn3i_UujUHChl6M,3346
10
10
  lmnr/traceloop_sdk/.flake8,sha256=bCxuDlGx3YQ55QHKPiGJkncHanh9qGjQJUujcFa3lAU,150
11
11
  lmnr/traceloop_sdk/.python-version,sha256=9OLQBQVbD4zE4cJsPePhnAfV_snrPSoqEQw-PXgPMOs,6
12
- lmnr/traceloop_sdk/__init__.py,sha256=-wa25NtU7BeTgqjT6rpVIEdaVP4aOjLgbYrc3B3-JaM,3932
13
- lmnr/traceloop_sdk/config/__init__.py,sha256=EGN3ixOt_ORbMxqaQdLaC14kmO-gyG4mnGJ2GfN-R-E,364
12
+ lmnr/traceloop_sdk/__init__.py,sha256=hp3q1OsFaGgaQCEanJrL38BJN32hWqCNVCSjYpndEsY,2957
13
+ lmnr/traceloop_sdk/config/__init__.py,sha256=DliMGp2NjYAqRFLKpWQPUKjGMHRO8QsVfazBA1qENQ8,248
14
14
  lmnr/traceloop_sdk/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- lmnr/traceloop_sdk/decorators/base.py,sha256=wcqXF0iVQgRXMyWTcJ5QvL_6q2y_gttwsX8dllmAtWM,4891
15
+ lmnr/traceloop_sdk/decorators/base.py,sha256=5YCzAErlhv1bMDO1C9LBlLWYk3bwku0RLjGLR-TkR4c,5128
16
16
  lmnr/traceloop_sdk/instruments.py,sha256=oMvIASueW3GeChpjIdH-DD9aFBVB8OtHZ0HawppTrlI,942
17
- lmnr/traceloop_sdk/metrics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- lmnr/traceloop_sdk/metrics/metrics.py,sha256=AlQ2a2os1WcZbfBd155u_UzBbPrbuPia6O_HbojV9Wc,5055
19
17
  lmnr/traceloop_sdk/tests/__init__.py,sha256=RYnG0-8zbXL0-2Ste1mEBf5sN4d_rQjGTCgPBuaZC74,20
20
18
  lmnr/traceloop_sdk/tests/cassettes/test_association_properties/test_langchain_and_external_association_properties.yaml,sha256=26g0wRA0juicHg_XrhcE8H4vhs1lawDs0o0aLFn-I7w,3103
21
19
  lmnr/traceloop_sdk/tests/cassettes/test_association_properties/test_langchain_association_properties.yaml,sha256=FNlSWlYCsWc3w7UPZzfGjDnxS3gAOhL-kpsu4BTxsDE,3061
@@ -37,17 +35,17 @@ lmnr/traceloop_sdk/tests/test_sdk_initialization.py,sha256=fRaf6lrxFzJIN94P1Tav_
37
35
  lmnr/traceloop_sdk/tests/test_tasks.py,sha256=xlEx8BKp4yG83SCjK5WkPGfyC33JSrx4h8VyjVwGbgw,906
38
36
  lmnr/traceloop_sdk/tests/test_workflows.py,sha256=RVcfY3WAFIDZC15-aSua21aoQyYeWE7KypDyUsm-2EM,9372
39
37
  lmnr/traceloop_sdk/tracing/__init__.py,sha256=Ckq7zCM26VdJVB5tIZv0GTPyMZKyfso_KWD5yPHaqdo,66
38
+ lmnr/traceloop_sdk/tracing/attributes.py,sha256=Rvglt_2IeZzKJ-mumrp9qAtTwHza34CrNgv4CvYihk0,221
40
39
  lmnr/traceloop_sdk/tracing/content_allow_list.py,sha256=3feztm6PBWNelc8pAZUcQyEGyeSpNiVKjOaDk65l2ps,846
41
40
  lmnr/traceloop_sdk/tracing/context_manager.py,sha256=csVlB6kDmbgSPsROHwnddvGGblx55v6lJMRj0wsSMQM,304
42
- lmnr/traceloop_sdk/tracing/manual.py,sha256=RPwEreHHdzmw7g15u4G21GqhHOvRp7d72ylQNLG1jRM,1841
43
- lmnr/traceloop_sdk/tracing/tracing.py,sha256=5e8AsiFKaIO6zqAbMfhw242glVsQUkxbNhTWP7QDqSg,40108
41
+ lmnr/traceloop_sdk/tracing/tracing.py,sha256=8plGdX6nErrPERgYXQDQRyBTtVgv2Ies46ph-msLLQE,35443
44
42
  lmnr/traceloop_sdk/utils/__init__.py,sha256=pNhf0G3vTd5ccoc03i1MXDbricSaiqCbi1DLWhSekK8,604
45
43
  lmnr/traceloop_sdk/utils/in_memory_span_exporter.py,sha256=H_4TRaThMO1H6vUQ0OpQvzJk_fZH0OOsRAM1iZQXsR8,2112
46
44
  lmnr/traceloop_sdk/utils/json_encoder.py,sha256=dK6b_axr70IYL7Vv-bu4wntvDDuyntoqsHaddqX7P58,463
47
45
  lmnr/traceloop_sdk/utils/package_check.py,sha256=TZSngzJOpFhfUZLXIs38cpMxQiZSmp0D-sCrIyhz7BA,251
48
46
  lmnr/traceloop_sdk/version.py,sha256=OlatFEFA4ttqSSIiV8jdE-sq3KG5zu2hnC4B4mzWF3s,23
49
- lmnr-0.4.12b2.dist-info/LICENSE,sha256=67b_wJHVV1CBaWkrKFWU1wyqTPSdzH77Ls-59631COg,10411
50
- lmnr-0.4.12b2.dist-info/METADATA,sha256=UJhERILRPT7Mdqv-kKlRtE9qEhrKaxDmRCys3Bs2LrQ,11992
51
- lmnr-0.4.12b2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
52
- lmnr-0.4.12b2.dist-info/entry_points.txt,sha256=K1jE20ww4jzHNZLnsfWBvU3YKDGBgbOiYG5Y7ivQcq4,37
53
- lmnr-0.4.12b2.dist-info/RECORD,,
47
+ lmnr-0.4.12b4.dist-info/LICENSE,sha256=67b_wJHVV1CBaWkrKFWU1wyqTPSdzH77Ls-59631COg,10411
48
+ lmnr-0.4.12b4.dist-info/METADATA,sha256=u8pLIuLaw6if3D60lp5ekTKpVoJGxt3Z-gcjVKoDj7g,12196
49
+ lmnr-0.4.12b4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
50
+ lmnr-0.4.12b4.dist-info/entry_points.txt,sha256=K1jE20ww4jzHNZLnsfWBvU3YKDGBgbOiYG5Y7ivQcq4,37
51
+ lmnr-0.4.12b4.dist-info/RECORD,,
File without changes
@@ -1,176 +0,0 @@
1
- from collections.abc import Sequence
2
- from typing import Dict
3
-
4
- from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
5
- OTLPMetricExporter as GRPCExporter,
6
- )
7
- from opentelemetry.exporter.otlp.proto.http.metric_exporter import (
8
- OTLPMetricExporter as HTTPExporter,
9
- )
10
- from opentelemetry.semconv_ai import Meters
11
- from opentelemetry.sdk.metrics import MeterProvider
12
- from opentelemetry.sdk.metrics.export import (
13
- PeriodicExportingMetricReader,
14
- MetricExporter,
15
- )
16
- from opentelemetry.sdk.metrics.view import View, ExplicitBucketHistogramAggregation
17
- from opentelemetry.sdk.resources import Resource
18
-
19
- from opentelemetry import metrics
20
-
21
-
22
- class MetricsWrapper(object):
23
- resource_attributes: dict = {}
24
- endpoint: str = None
25
- # if it needs headers?
26
- headers: Dict[str, str] = {}
27
- __metrics_exporter: MetricExporter = None
28
- __metrics_provider: MeterProvider = None
29
-
30
- def __new__(cls, exporter: MetricExporter = None) -> "MetricsWrapper":
31
- if not hasattr(cls, "instance"):
32
- obj = cls.instance = super(MetricsWrapper, cls).__new__(cls)
33
- if not MetricsWrapper.endpoint:
34
- return obj
35
-
36
- obj.__metrics_exporter = (
37
- exporter
38
- if exporter
39
- else init_metrics_exporter(
40
- MetricsWrapper.endpoint, MetricsWrapper.headers
41
- )
42
- )
43
-
44
- obj.__metrics_provider = init_metrics_provider(
45
- obj.__metrics_exporter, MetricsWrapper.resource_attributes
46
- )
47
-
48
- return cls.instance
49
-
50
- @staticmethod
51
- def set_static_params(
52
- resource_attributes: dict,
53
- endpoint: str,
54
- headers: Dict[str, str],
55
- ) -> None:
56
- MetricsWrapper.resource_attributes = resource_attributes
57
- MetricsWrapper.endpoint = endpoint
58
- MetricsWrapper.headers = headers
59
-
60
-
61
- def init_metrics_exporter(endpoint: str, headers: Dict[str, str]) -> MetricExporter:
62
- if "http" in endpoint.lower() or "https" in endpoint.lower():
63
- return HTTPExporter(endpoint=f"{endpoint}/v1/metrics", headers=headers)
64
- else:
65
- return GRPCExporter(endpoint=endpoint, headers=headers)
66
-
67
-
68
- def init_metrics_provider(
69
- exporter: MetricExporter, resource_attributes: dict = None
70
- ) -> MeterProvider:
71
- resource = (
72
- Resource.create(resource_attributes)
73
- if resource_attributes
74
- else Resource.create()
75
- )
76
- reader = PeriodicExportingMetricReader(exporter)
77
- provider = MeterProvider(
78
- metric_readers=[reader],
79
- resource=resource,
80
- views=metric_views(),
81
- )
82
-
83
- metrics.set_meter_provider(provider)
84
- return provider
85
-
86
-
87
- def metric_views() -> Sequence[View]:
88
- return [
89
- View(
90
- instrument_name=Meters.LLM_TOKEN_USAGE,
91
- aggregation=ExplicitBucketHistogramAggregation(
92
- [
93
- 0.01,
94
- 0.02,
95
- 0.04,
96
- 0.08,
97
- 0.16,
98
- 0.32,
99
- 0.64,
100
- 1.28,
101
- 2.56,
102
- 5.12,
103
- 10.24,
104
- 20.48,
105
- 40.96,
106
- 81.92,
107
- ]
108
- ),
109
- ),
110
- View(
111
- instrument_name=Meters.LLM_OPERATION_DURATION,
112
- aggregation=ExplicitBucketHistogramAggregation(
113
- [
114
- 1,
115
- 4,
116
- 16,
117
- 64,
118
- 256,
119
- 1024,
120
- 4096,
121
- 16384,
122
- 65536,
123
- 262144,
124
- 1048576,
125
- 4194304,
126
- 16777216,
127
- 67108864,
128
- ]
129
- ),
130
- ),
131
- View(
132
- instrument_name=Meters.PINECONE_DB_QUERY_DURATION,
133
- aggregation=ExplicitBucketHistogramAggregation(
134
- [
135
- 0.01,
136
- 0.02,
137
- 0.04,
138
- 0.08,
139
- 0.16,
140
- 0.32,
141
- 0.64,
142
- 1.28,
143
- 2.56,
144
- 5.12,
145
- 10.24,
146
- 20.48,
147
- 40.96,
148
- 81.92,
149
- ]
150
- ),
151
- ),
152
- View(
153
- instrument_name=Meters.PINECONE_DB_QUERY_SCORES,
154
- aggregation=ExplicitBucketHistogramAggregation(
155
- [
156
- -1,
157
- -0.875,
158
- -0.75,
159
- -0.625,
160
- -0.5,
161
- -0.375,
162
- -0.25,
163
- -0.125,
164
- 0,
165
- 0.125,
166
- 0.25,
167
- 0.375,
168
- 0.5,
169
- 0.625,
170
- 0.75,
171
- 0.875,
172
- 1,
173
- ]
174
- ),
175
- ),
176
- ]