openlit 1.32.6__py3-none-any.whl → 1.32.8__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.
openlit/__helpers.py CHANGED
@@ -133,7 +133,7 @@ def get_image_model_cost(model, pricing_info, size, quality):
133
133
  cost = 0
134
134
  return cost
135
135
 
136
- def get_audio_model_cost(model, pricing_info, prompt):
136
+ def get_audio_model_cost(model, pricing_info, prompt, duration=None):
137
137
  """
138
138
  Retrieve the cost of processing for a given model based on prompt.
139
139
 
@@ -146,7 +146,10 @@ def get_audio_model_cost(model, pricing_info, prompt):
146
146
  float: The calculated cost for the operation.
147
147
  """
148
148
  try:
149
- cost = (len(prompt) / 1000) * pricing_info["audio"][model]
149
+ if prompt:
150
+ cost = (len(prompt) / 1000) * pricing_info["audio"][model]
151
+ else:
152
+ cost = duration * pricing_info["audio"][model]
150
153
  except:
151
154
  cost = 0
152
155
  return cost
openlit/__init__.py CHANGED
@@ -38,6 +38,7 @@ from openlit.instrumentation.vllm import VLLMInstrumentor
38
38
  from openlit.instrumentation.google_ai_studio import GoogleAIStudioInstrumentor
39
39
  from openlit.instrumentation.reka import RekaInstrumentor
40
40
  from openlit.instrumentation.premai import PremAIInstrumentor
41
+ from openlit.instrumentation.assemblyai import AssemblyAIInstrumentor
41
42
  from openlit.instrumentation.azure_ai_inference import AzureAIInferenceInstrumentor
42
43
  from openlit.instrumentation.langchain import LangChainInstrumentor
43
44
  from openlit.instrumentation.llamaindex import LlamaIndexInstrumentor
@@ -256,6 +257,7 @@ def init(environment="default", application_name="default", tracer=None, otlp_en
256
257
  "astra": "astrapy",
257
258
  "ai21": "ai21",
258
259
  "controlflow": "controlflow",
260
+ "assemblyai": "assemblyai",
259
261
  }
260
262
 
261
263
  invalid_instrumentors = [
@@ -348,6 +350,7 @@ def init(environment="default", application_name="default", tracer=None, otlp_en
348
350
  "astra": AstraInstrumentor(),
349
351
  "ai21": AI21Instrumentor(),
350
352
  "controlflow": ControlFlowInstrumentor(),
353
+ "assemblyai": AssemblyAIInstrumentor(),
351
354
  }
352
355
 
353
356
  # Initialize and instrument only the enabled instrumentors
@@ -0,0 +1,43 @@
1
+ # pylint: disable=useless-return, bad-staticmethod-argument, disable=duplicate-code
2
+ """Initializer of Auto Instrumentation of AssemblyAI Functions"""
3
+
4
+ from typing import Collection
5
+ import importlib.metadata
6
+ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
7
+ from wrapt import wrap_function_wrapper
8
+
9
+ from openlit.instrumentation.assemblyai.assemblyai import (
10
+ transcribe
11
+ )
12
+
13
+ _instruments = ("assemblyai >= 0.35.1",)
14
+
15
+ class AssemblyAIInstrumentor(BaseInstrumentor):
16
+ """
17
+ An instrumentor for AssemblyAI's client library.
18
+ """
19
+
20
+ def instrumentation_dependencies(self) -> Collection[str]:
21
+ return _instruments
22
+
23
+ def _instrument(self, **kwargs):
24
+ application_name = kwargs.get("application_name", "default")
25
+ environment = kwargs.get("environment", "default")
26
+ tracer = kwargs.get("tracer")
27
+ metrics = kwargs.get("metrics_dict")
28
+ pricing_info = kwargs.get("pricing_info", {})
29
+ trace_content = kwargs.get("trace_content", False)
30
+ disable_metrics = kwargs.get("disable_metrics")
31
+ version = importlib.metadata.version("assemblyai")
32
+
33
+ # sync transcribe
34
+ wrap_function_wrapper(
35
+ "assemblyai.transcriber",
36
+ "Transcriber.transcribe",
37
+ transcribe("assemblyai.transcribe", version, environment, application_name,
38
+ tracer, pricing_info, trace_content, metrics, disable_metrics),
39
+ )
40
+
41
+ def _uninstrument(self, **kwargs):
42
+ # Proper uninstrumentation logic to revert patched methods
43
+ pass
@@ -0,0 +1,127 @@
1
+ # pylint: disable=duplicate-code, broad-exception-caught, too-many-statements, unused-argument, possibly-used-before-assignment
2
+ """
3
+ Module for monitoring Assembly AI API calls.
4
+ """
5
+
6
+ import logging
7
+ from opentelemetry.trace import SpanKind, Status, StatusCode
8
+ from opentelemetry.sdk.resources import TELEMETRY_SDK_NAME
9
+ from openlit.__helpers import get_audio_model_cost
10
+ from openlit.__helpers import handle_exception
11
+ from openlit.semcov import SemanticConvetion
12
+
13
+ # Initialize logger for logging potential issues and operations
14
+ logger = logging.getLogger(__name__)
15
+
16
+ def transcribe(gen_ai_endpoint, version, environment, application_name,
17
+ tracer, pricing_info, trace_content, metrics, disable_metrics):
18
+ """
19
+ Generates a telemetry wrapper for creating speech audio to collect metrics.
20
+
21
+ Args:
22
+ gen_ai_endpoint: Endpoint identifier for logging and tracing.
23
+ version: Version of the monitoring package.
24
+ environment: Deployment environment (e.g., production, staging).
25
+ application_name: Name of the application using the Assembly AI API.
26
+ tracer: OpenTelemetry tracer for creating spans.
27
+ pricing_info: Information used for calculating the cost of generating speech audio.
28
+ trace_content: Flag indicating whether to trace the input text and generated audio.
29
+
30
+ Returns:
31
+ A function that wraps the speech audio creation method to add telemetry.
32
+ """
33
+
34
+ def wrapper(wrapped, instance, args, kwargs):
35
+ """
36
+ Wraps the 'generate' API call to add telemetry.
37
+
38
+ This collects metrics such as execution time, cost, and handles errors
39
+ gracefully, adding details to the trace for observability.
40
+
41
+ Args:
42
+ wrapped: The original 'generate' method to be wrapped.
43
+ instance: The instance of the class where the original method is defined.
44
+ args: Positional arguments for the 'generate' method.
45
+ kwargs: Keyword arguments for the 'generate' method.
46
+
47
+ Returns:
48
+ The response from the original 'transcribe' method.
49
+ """
50
+
51
+ with tracer.start_as_current_span(gen_ai_endpoint, kind= SpanKind.CLIENT) as span:
52
+ response = wrapped(*args, **kwargs)
53
+
54
+ try:
55
+ llm_model = response.speech_model if response.speech_model else "best"
56
+
57
+ # Calculate cost of the operation
58
+ cost = get_audio_model_cost(llm_model,
59
+ pricing_info, None, response.audio_duration)
60
+
61
+ # Set Span attributes
62
+ span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
63
+ span.set_attribute(SemanticConvetion.GEN_AI_SYSTEM,
64
+ SemanticConvetion.GEN_AI_SYSTEM_ASSEMBLYAI)
65
+ span.set_attribute(SemanticConvetion.GEN_AI_TYPE,
66
+ SemanticConvetion.GEN_AI_TYPE_AUDIO)
67
+ span.set_attribute(SemanticConvetion.GEN_AI_ENDPOINT,
68
+ gen_ai_endpoint)
69
+ span.set_attribute(SemanticConvetion.GEN_AI_ENVIRONMENT,
70
+ environment)
71
+ span.set_attribute(SemanticConvetion.GEN_AI_APPLICATION_NAME,
72
+ application_name)
73
+ span.set_attribute(SemanticConvetion.GEN_AI_RESPONSE_ID,
74
+ response.id)
75
+ span.set_attribute(SemanticConvetion.GEN_AI_REQUEST_MODEL,
76
+ llm_model)
77
+ span.set_attribute(SemanticConvetion.GEN_AI_REQUEST_AUDIO_DURATION,
78
+ response.audio_duration)
79
+ span.set_attribute(SemanticConvetion.GEN_AI_USAGE_COST,
80
+ cost)
81
+
82
+ if trace_content:
83
+ span.add_event(
84
+ name=SemanticConvetion.GEN_AI_CONTENT_PROMPT_EVENT,
85
+ attributes={
86
+ SemanticConvetion.GEN_AI_CONTENT_PROMPT: response.audio_url,
87
+ },
88
+ )
89
+ span.add_event(
90
+ name=SemanticConvetion.GEN_AI_CONTENT_COMPLETION_EVENT,
91
+ attributes={
92
+ SemanticConvetion.GEN_AI_CONTENT_COMPLETION: response.text,
93
+ },
94
+ )
95
+
96
+ span.set_status(Status(StatusCode.OK))
97
+
98
+ if disable_metrics is False:
99
+ attributes = {
100
+ TELEMETRY_SDK_NAME:
101
+ "openlit",
102
+ SemanticConvetion.GEN_AI_APPLICATION_NAME:
103
+ application_name,
104
+ SemanticConvetion.GEN_AI_SYSTEM:
105
+ SemanticConvetion.GEN_AI_SYSTEM_ASSEMBLYAI,
106
+ SemanticConvetion.GEN_AI_ENVIRONMENT:
107
+ environment,
108
+ SemanticConvetion.GEN_AI_TYPE:
109
+ SemanticConvetion.GEN_AI_TYPE_AUDIO,
110
+ SemanticConvetion.GEN_AI_REQUEST_MODEL:
111
+ llm_model,
112
+ }
113
+
114
+ metrics["genai_requests"].add(1, attributes)
115
+ metrics["genai_cost"].record(cost, attributes)
116
+
117
+ # Return original response
118
+ return response
119
+
120
+ except Exception as e:
121
+ handle_exception(span, e)
122
+ logger.error("Error in trace creation: %s", e)
123
+
124
+ # Return original response
125
+ return response
126
+
127
+ return wrapper
@@ -71,6 +71,12 @@ WRAPPED_METHODS = [
71
71
  "endpoint": "langchain.chat_models",
72
72
  "wrapper": achat,
73
73
  },
74
+ {
75
+ "package": "langchain.chains.base",
76
+ "object": "Chain.invoke",
77
+ "endpoint": "langchain.chain.invoke",
78
+ "wrapper": chat,
79
+ }
74
80
  ]
75
81
 
76
82
  class LangChainInstrumentor(BaseInstrumentor):
@@ -1,4 +1,4 @@
1
- # pylint: disable=duplicate-code, broad-exception-caught, too-many-statements, unused-argument, unused-import
1
+ # pylint: disable=duplicate-code, broad-exception-caught, too-many-statements, unused-argument, unused-import, too-many-function-args
2
2
  """
3
3
  Module for monitoring Langchain applications.
4
4
  """
@@ -507,12 +507,25 @@ def chat(gen_ai_endpoint, version, environment, application_name,
507
507
  response = wrapped(*args, **kwargs)
508
508
 
509
509
  try:
510
- token_usage = response.response_metadata.get("token_usage", {})
511
- input_tokens = token_usage.get("prompt_tokens", 0)
512
- output_tokens = token_usage.get("completion_tokens", 0)
513
- model = response.response_metadata.get("model_name", "gpt-4")
514
-
515
- prompt = "" if isinstance(args[0], list) else args[0]
510
+ prompt = ""
511
+ if hasattr(response, 'response_metadata') and response.response_metadata:
512
+ token_usage = response.response_metadata.get("token_usage", {})
513
+ input_tokens = token_usage.get("prompt_tokens", 0)
514
+ output_tokens = token_usage.get("completion_tokens", 0)
515
+ model = response.response_metadata.get("model_name", "gpt-4")
516
+ prompt = "" if isinstance(args[0], list) else args[0]
517
+ else:
518
+ if not isinstance(response, dict) or "output_text" not in response:
519
+ return response
520
+ # Fallback: Calculate tokens manually if response_metadata is missing
521
+ model = "gpt-4o-mini" # Fallback model
522
+ input_texts = [
523
+ doc.page_content for doc in response.get("input_documents", [])
524
+ if isinstance(doc.page_content, str)
525
+ ]
526
+ input_tokens = sum(general_tokens(text, model) for text in input_texts)
527
+ output_text = response.get("output_text", "")
528
+ output_tokens = general_tokens(output_text, model)
516
529
 
517
530
  # Calculate cost of the operation
518
531
  cost = get_chat_model_cost(
@@ -556,10 +569,11 @@ def chat(gen_ai_endpoint, version, environment, application_name,
556
569
  SemanticConvetion.GEN_AI_CONTENT_PROMPT: prompt,
557
570
  },
558
571
  )
572
+ completion_content = getattr(response, 'content', "")
559
573
  span.add_event(
560
574
  name=SemanticConvetion.GEN_AI_CONTENT_COMPLETION_EVENT,
561
575
  attributes={
562
- SemanticConvetion.GEN_AI_CONTENT_COMPLETION: response.content,
576
+ SemanticConvetion.GEN_AI_CONTENT_COMPLETION: completion_content,
563
577
  },
564
578
  )
565
579
 
@@ -46,6 +46,7 @@ class SemanticConvetion:
46
46
  GEN_AI_REQUEST_AUDIO_RESPONSE_FORMAT = "gen_ai.request.audio_response_format"
47
47
  GEN_AI_REQUEST_AUDIO_SPEED = "gen_ai.request.audio_speed"
48
48
  GEN_AI_REQUEST_AUDIO_SETTINGS = "gen_ai.request.audio_settings"
49
+ GEN_AI_REQUEST_AUDIO_DURATION = "gen_ai.request.audio_duration"
49
50
  GEN_AI_REQUEST_FINETUNE_STATUS = "gen_ai.request.fine_tune_status"
50
51
  GEN_AI_REQUEST_FINETUNE_MODEL_SUFFIX = "gen_ai.request.fine_tune_model_suffix"
51
52
  GEN_AI_REQUEST_FINETUNE_MODEL_EPOCHS = "gen_ai.request.fine_tune_n_epochs"
@@ -129,6 +130,7 @@ class SemanticConvetion:
129
130
  GEN_AI_SYSTEM_JULEP = "julep"
130
131
  GEN_AI_SYSTEM_AI21 = "ai21"
131
132
  GEN_AI_SYSTEM_CONTROLFLOW = "controlflow"
133
+ GEN_AI_SYSTEM_ASSEMBLYAI = "assemblyai"
132
134
 
133
135
  # Vector DB
134
136
  DB_OPERATION_API_ENDPOINT = "db.operation.api_endpoint"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openlit
3
- Version: 1.32.6
3
+ Version: 1.32.8
4
4
  Summary: OpenTelemetry-native Auto instrumentation library for monitoring LLM Applications and GPUs, facilitating the integration of observability into your GenAI-driven projects
5
5
  Home-page: https://github.com/openlit/openlit/tree/main/openlit/python
6
6
  Keywords: OpenTelemetry,otel,otlp,llm,tracing,openai,anthropic,claude,cohere,llm monitoring,observability,monitoring,gpt,Generative AI,chatGPT,gpu
@@ -88,6 +88,7 @@ This project proudly follows and maintains the [Semantic Conventions](https://gi
88
88
  | [✅ Reka AI](https://docs.openlit.io/latest/integrations/reka) | | | |
89
89
  | [✅ xAI](https://docs.openlit.io/latest/integrations/xai) | | | |
90
90
  | [✅ Prem AI](https://docs.openlit.io/latest/integrations/premai) | | | |
91
+ | [✅ Assembly AI](https://docs.openlit.io/latest/integrations/assemblyai) | | | |
91
92
 
92
93
  ## Supported Destinations
93
94
  - [✅ OpenTelemetry Collector](https://docs.openlit.io/latest/connections/otelcol)
@@ -1,5 +1,5 @@
1
- openlit/__helpers.py,sha256=2OkGKOdsd9Hc011WxR70OqDlO6c4mZcu6McGuW1uAdA,6316
2
- openlit/__init__.py,sha256=FUNyEH5AnzoGuxiKOyngHcyoMjuRlGj76fmgQEEV9k0,21286
1
+ openlit/__helpers.py,sha256=bqMxdNndLW5NGO2wwpAoHEOnAFr_mhnmVLua3ifpSEc,6427
2
+ openlit/__init__.py,sha256=PXKZfrDNrQRxZGY1yowoSf1VHkKoLO_hE4pcEqj0qbY,21444
3
3
  openlit/evals/__init__.py,sha256=nJe99nuLo1b5rf7pt9U9BCdSDedzbVi2Fj96cgl7msM,380
4
4
  openlit/evals/all.py,sha256=oWrue3PotE-rB5WePG3MRYSA-ro6WivkclSHjYlAqGs,7154
5
5
  openlit/evals/bias_detection.py,sha256=mCdsfK7x1vX7S3psC3g641IMlZ-7df3h-V6eiICj5N8,8154
@@ -20,6 +20,8 @@ openlit/instrumentation/ai21/async_ai21.py,sha256=OVDKt9Ymlp0OTCNVEirvRwqMSL5VZH
20
20
  openlit/instrumentation/anthropic/__init__.py,sha256=oaU53BOPyfUKbEzYvLr1DPymDluurSnwo4Hernf2XdU,1955
21
21
  openlit/instrumentation/anthropic/anthropic.py,sha256=y7CEGhKOGHWt8G_5Phr4qPJTfPGRJIAr9Yk6nM3CcvM,16775
22
22
  openlit/instrumentation/anthropic/async_anthropic.py,sha256=Zz1KRKIG9wGn0quOoLvjORC-49IvHQpJ6GBdB-4PfCQ,16816
23
+ openlit/instrumentation/assemblyai/__init__.py,sha256=h5AADJkkqZA4IvUZ6rn8P32eVSmD15LgdcPlBX23Ve0,1560
24
+ openlit/instrumentation/assemblyai/assemblyai.py,sha256=muOq9C5JigG8N2Yd90j128LUKz8r-Gb3rOYSAjrarDM,5710
23
25
  openlit/instrumentation/astra/__init__.py,sha256=G4alCOR6hXQvUQPDCS8lY1rj0Mz-KmrW5vVWk5loO78,8054
24
26
  openlit/instrumentation/astra/astra.py,sha256=ddZuzwhsszQK1nsttJrQ01YKsvbOJ4I6HHNFAS2KdtY,12074
25
27
  openlit/instrumentation/astra/async_astra.py,sha256=4l6HlQdCjPKZNFmKRGqEO0LMkSvwxLbg4BJ6x5RrSu4,12086
@@ -57,8 +59,8 @@ openlit/instrumentation/haystack/haystack.py,sha256=oQIZiDhdp3gnJnhYQ1OouJMc9YT0
57
59
  openlit/instrumentation/julep/__init__.py,sha256=oonEVK41P5g4SYRm0E_H4zCVH9NM4aJ-UswXzF3Oiv0,3136
58
60
  openlit/instrumentation/julep/async_julep.py,sha256=OO8lIm9uUV1lhPo_klKBVyaDwgHhFJlohTeZItd5qwU,5273
59
61
  openlit/instrumentation/julep/julep.py,sha256=lDUmkEP4hXk7vgUUbNRD-mnfdfrZifXSFVVILs8Ttkw,5276
60
- openlit/instrumentation/langchain/__init__.py,sha256=0AI2Dnqw81IcJw3jM--gGkv_HRh2GtosOGJjvOpw7Zk,3431
61
- openlit/instrumentation/langchain/langchain.py,sha256=jZgWBBWYHYSNnkf5wKyNFF_z9M9YxaZKGI_uyfvtMBU,36909
62
+ openlit/instrumentation/langchain/__init__.py,sha256=gVtPZJifx-H8rqdZlU3GXdy3NtRF8yVb7PW7gE-ddJk,3592
63
+ openlit/instrumentation/langchain/langchain.py,sha256=fYtFDN95aW4DLUKIaldBQXbee4oR__yo1cWcZXqQkEk,37874
62
64
  openlit/instrumentation/litellm/__init__.py,sha256=Z-LsVHKJdPganHfJA_rWg7xAfQYkvLfpLdF-eckU4qY,2401
63
65
  openlit/instrumentation/litellm/async_litellm.py,sha256=1MKNZbvKaf1lFWbXi1MQy3qFNNeXawav34SDlOQ_H3w,27544
64
66
  openlit/instrumentation/litellm/litellm.py,sha256=4YqCQ4CEQ4sfDu7pTlnflL_AfUqYEQdJDTO7nHJ6noY,27450
@@ -103,8 +105,8 @@ openlit/instrumentation/vllm/__init__.py,sha256=OVWalQ1dXvip1DUsjUGaHX4J-2FrSp-T
103
105
  openlit/instrumentation/vllm/vllm.py,sha256=lDzM7F5pgxvh8nKL0dcKB4TD0Mc9wXOWeXOsOGN7Wd8,6527
104
106
  openlit/otel/metrics.py,sha256=y7SQDTyfLakMrz0V4DThN-WAeap7YZzyndeYGSP6nVg,4516
105
107
  openlit/otel/tracing.py,sha256=fG3vl-flSZ30whCi7rrG25PlkIhhr8PhnfJYCkZzCD0,3895
106
- openlit/semcov/__init__.py,sha256=oW2jh7dSKrOFsbO7tdXSA5yqUq6iN5A9QsgjfIeApGA,10516
107
- openlit-1.32.6.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
108
- openlit-1.32.6.dist-info/METADATA,sha256=xR9rBVB9PwR5FpQQEuK4zvFKQkSbwGIt1V6N4coxHuY,22441
109
- openlit-1.32.6.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
110
- openlit-1.32.6.dist-info/RECORD,,
108
+ openlit/semcov/__init__.py,sha256=9gCyLKqhV2iErzNMIb4H9-CAlzaMUUoNXJmRZbDdhfc,10628
109
+ openlit-1.32.8.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
110
+ openlit-1.32.8.dist-info/METADATA,sha256=w203C6GIfvP0D7jXDdE0BK3K7GU7SbnyYIKtVN_umLM,22670
111
+ openlit-1.32.8.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
112
+ openlit-1.32.8.dist-info/RECORD,,