openlit 1.34.29__py3-none-any.whl → 1.34.31__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.
Files changed (168) hide show
  1. openlit/__helpers.py +235 -86
  2. openlit/__init__.py +16 -13
  3. openlit/_instrumentors.py +2 -1
  4. openlit/evals/all.py +50 -21
  5. openlit/evals/bias_detection.py +47 -20
  6. openlit/evals/hallucination.py +53 -22
  7. openlit/evals/toxicity.py +50 -21
  8. openlit/evals/utils.py +54 -30
  9. openlit/guard/all.py +61 -19
  10. openlit/guard/prompt_injection.py +34 -14
  11. openlit/guard/restrict_topic.py +46 -15
  12. openlit/guard/sensitive_topic.py +34 -14
  13. openlit/guard/utils.py +58 -22
  14. openlit/instrumentation/ag2/__init__.py +24 -8
  15. openlit/instrumentation/ag2/ag2.py +34 -13
  16. openlit/instrumentation/ag2/async_ag2.py +34 -13
  17. openlit/instrumentation/ag2/utils.py +133 -30
  18. openlit/instrumentation/ai21/__init__.py +43 -14
  19. openlit/instrumentation/ai21/ai21.py +47 -21
  20. openlit/instrumentation/ai21/async_ai21.py +47 -21
  21. openlit/instrumentation/ai21/utils.py +299 -78
  22. openlit/instrumentation/anthropic/__init__.py +21 -4
  23. openlit/instrumentation/anthropic/anthropic.py +28 -17
  24. openlit/instrumentation/anthropic/async_anthropic.py +28 -17
  25. openlit/instrumentation/anthropic/utils.py +145 -35
  26. openlit/instrumentation/assemblyai/__init__.py +11 -2
  27. openlit/instrumentation/assemblyai/assemblyai.py +15 -4
  28. openlit/instrumentation/assemblyai/utils.py +120 -25
  29. openlit/instrumentation/astra/__init__.py +43 -10
  30. openlit/instrumentation/astra/astra.py +28 -5
  31. openlit/instrumentation/astra/async_astra.py +28 -5
  32. openlit/instrumentation/astra/utils.py +151 -55
  33. openlit/instrumentation/azure_ai_inference/__init__.py +43 -10
  34. openlit/instrumentation/azure_ai_inference/async_azure_ai_inference.py +53 -21
  35. openlit/instrumentation/azure_ai_inference/azure_ai_inference.py +53 -21
  36. openlit/instrumentation/azure_ai_inference/utils.py +307 -83
  37. openlit/instrumentation/bedrock/__init__.py +21 -4
  38. openlit/instrumentation/bedrock/bedrock.py +63 -25
  39. openlit/instrumentation/bedrock/utils.py +139 -30
  40. openlit/instrumentation/chroma/__init__.py +89 -16
  41. openlit/instrumentation/chroma/chroma.py +28 -6
  42. openlit/instrumentation/chroma/utils.py +167 -51
  43. openlit/instrumentation/cohere/__init__.py +63 -18
  44. openlit/instrumentation/cohere/async_cohere.py +63 -24
  45. openlit/instrumentation/cohere/cohere.py +63 -24
  46. openlit/instrumentation/cohere/utils.py +286 -73
  47. openlit/instrumentation/controlflow/__init__.py +35 -9
  48. openlit/instrumentation/controlflow/controlflow.py +66 -33
  49. openlit/instrumentation/crawl4ai/__init__.py +25 -10
  50. openlit/instrumentation/crawl4ai/async_crawl4ai.py +78 -31
  51. openlit/instrumentation/crawl4ai/crawl4ai.py +78 -31
  52. openlit/instrumentation/crewai/__init__.py +111 -24
  53. openlit/instrumentation/crewai/async_crewai.py +114 -0
  54. openlit/instrumentation/crewai/crewai.py +104 -131
  55. openlit/instrumentation/crewai/utils.py +615 -0
  56. openlit/instrumentation/dynamiq/__init__.py +46 -12
  57. openlit/instrumentation/dynamiq/dynamiq.py +74 -33
  58. openlit/instrumentation/elevenlabs/__init__.py +23 -4
  59. openlit/instrumentation/elevenlabs/async_elevenlabs.py +16 -4
  60. openlit/instrumentation/elevenlabs/elevenlabs.py +16 -4
  61. openlit/instrumentation/elevenlabs/utils.py +128 -25
  62. openlit/instrumentation/embedchain/__init__.py +11 -2
  63. openlit/instrumentation/embedchain/embedchain.py +68 -35
  64. openlit/instrumentation/firecrawl/__init__.py +24 -7
  65. openlit/instrumentation/firecrawl/firecrawl.py +46 -20
  66. openlit/instrumentation/google_ai_studio/__init__.py +45 -10
  67. openlit/instrumentation/google_ai_studio/async_google_ai_studio.py +67 -44
  68. openlit/instrumentation/google_ai_studio/google_ai_studio.py +67 -44
  69. openlit/instrumentation/google_ai_studio/utils.py +180 -67
  70. openlit/instrumentation/gpt4all/__init__.py +22 -7
  71. openlit/instrumentation/gpt4all/gpt4all.py +67 -29
  72. openlit/instrumentation/gpt4all/utils.py +285 -61
  73. openlit/instrumentation/gpu/__init__.py +128 -47
  74. openlit/instrumentation/groq/__init__.py +21 -4
  75. openlit/instrumentation/groq/async_groq.py +33 -21
  76. openlit/instrumentation/groq/groq.py +33 -21
  77. openlit/instrumentation/groq/utils.py +192 -55
  78. openlit/instrumentation/haystack/__init__.py +70 -24
  79. openlit/instrumentation/haystack/async_haystack.py +28 -6
  80. openlit/instrumentation/haystack/haystack.py +28 -6
  81. openlit/instrumentation/haystack/utils.py +196 -74
  82. openlit/instrumentation/julep/__init__.py +69 -19
  83. openlit/instrumentation/julep/async_julep.py +53 -27
  84. openlit/instrumentation/julep/julep.py +53 -28
  85. openlit/instrumentation/langchain/__init__.py +74 -63
  86. openlit/instrumentation/langchain/callback_handler.py +1100 -0
  87. openlit/instrumentation/langchain_community/__init__.py +13 -2
  88. openlit/instrumentation/langchain_community/async_langchain_community.py +23 -5
  89. openlit/instrumentation/langchain_community/langchain_community.py +23 -5
  90. openlit/instrumentation/langchain_community/utils.py +35 -9
  91. openlit/instrumentation/letta/__init__.py +68 -15
  92. openlit/instrumentation/letta/letta.py +99 -54
  93. openlit/instrumentation/litellm/__init__.py +43 -14
  94. openlit/instrumentation/litellm/async_litellm.py +51 -26
  95. openlit/instrumentation/litellm/litellm.py +51 -26
  96. openlit/instrumentation/litellm/utils.py +312 -101
  97. openlit/instrumentation/llamaindex/__init__.py +267 -90
  98. openlit/instrumentation/llamaindex/async_llamaindex.py +28 -6
  99. openlit/instrumentation/llamaindex/llamaindex.py +28 -6
  100. openlit/instrumentation/llamaindex/utils.py +204 -91
  101. openlit/instrumentation/mem0/__init__.py +11 -2
  102. openlit/instrumentation/mem0/mem0.py +50 -29
  103. openlit/instrumentation/milvus/__init__.py +10 -2
  104. openlit/instrumentation/milvus/milvus.py +31 -6
  105. openlit/instrumentation/milvus/utils.py +166 -67
  106. openlit/instrumentation/mistral/__init__.py +63 -18
  107. openlit/instrumentation/mistral/async_mistral.py +63 -24
  108. openlit/instrumentation/mistral/mistral.py +63 -24
  109. openlit/instrumentation/mistral/utils.py +277 -69
  110. openlit/instrumentation/multion/__init__.py +69 -19
  111. openlit/instrumentation/multion/async_multion.py +57 -26
  112. openlit/instrumentation/multion/multion.py +57 -26
  113. openlit/instrumentation/ollama/__init__.py +39 -18
  114. openlit/instrumentation/ollama/async_ollama.py +57 -26
  115. openlit/instrumentation/ollama/ollama.py +57 -26
  116. openlit/instrumentation/ollama/utils.py +226 -50
  117. openlit/instrumentation/openai/__init__.py +156 -32
  118. openlit/instrumentation/openai/async_openai.py +147 -67
  119. openlit/instrumentation/openai/openai.py +150 -67
  120. openlit/instrumentation/openai/utils.py +660 -186
  121. openlit/instrumentation/openai_agents/__init__.py +6 -2
  122. openlit/instrumentation/openai_agents/processor.py +409 -537
  123. openlit/instrumentation/phidata/__init__.py +13 -5
  124. openlit/instrumentation/phidata/phidata.py +67 -32
  125. openlit/instrumentation/pinecone/__init__.py +48 -9
  126. openlit/instrumentation/pinecone/async_pinecone.py +27 -5
  127. openlit/instrumentation/pinecone/pinecone.py +27 -5
  128. openlit/instrumentation/pinecone/utils.py +153 -47
  129. openlit/instrumentation/premai/__init__.py +22 -7
  130. openlit/instrumentation/premai/premai.py +51 -26
  131. openlit/instrumentation/premai/utils.py +246 -59
  132. openlit/instrumentation/pydantic_ai/__init__.py +49 -22
  133. openlit/instrumentation/pydantic_ai/pydantic_ai.py +69 -16
  134. openlit/instrumentation/pydantic_ai/utils.py +89 -24
  135. openlit/instrumentation/qdrant/__init__.py +19 -4
  136. openlit/instrumentation/qdrant/async_qdrant.py +33 -7
  137. openlit/instrumentation/qdrant/qdrant.py +33 -7
  138. openlit/instrumentation/qdrant/utils.py +228 -93
  139. openlit/instrumentation/reka/__init__.py +23 -10
  140. openlit/instrumentation/reka/async_reka.py +17 -11
  141. openlit/instrumentation/reka/reka.py +17 -11
  142. openlit/instrumentation/reka/utils.py +138 -36
  143. openlit/instrumentation/together/__init__.py +44 -12
  144. openlit/instrumentation/together/async_together.py +50 -27
  145. openlit/instrumentation/together/together.py +50 -27
  146. openlit/instrumentation/together/utils.py +301 -71
  147. openlit/instrumentation/transformers/__init__.py +2 -1
  148. openlit/instrumentation/transformers/transformers.py +13 -3
  149. openlit/instrumentation/transformers/utils.py +139 -36
  150. openlit/instrumentation/vertexai/__init__.py +81 -16
  151. openlit/instrumentation/vertexai/async_vertexai.py +33 -15
  152. openlit/instrumentation/vertexai/utils.py +123 -27
  153. openlit/instrumentation/vertexai/vertexai.py +33 -15
  154. openlit/instrumentation/vllm/__init__.py +12 -5
  155. openlit/instrumentation/vllm/utils.py +121 -31
  156. openlit/instrumentation/vllm/vllm.py +16 -10
  157. openlit/otel/events.py +35 -10
  158. openlit/otel/metrics.py +32 -24
  159. openlit/otel/tracing.py +24 -9
  160. openlit/semcov/__init__.py +101 -7
  161. {openlit-1.34.29.dist-info → openlit-1.34.31.dist-info}/METADATA +2 -1
  162. openlit-1.34.31.dist-info/RECORD +166 -0
  163. openlit/instrumentation/langchain/async_langchain.py +0 -102
  164. openlit/instrumentation/langchain/langchain.py +0 -102
  165. openlit/instrumentation/langchain/utils.py +0 -252
  166. openlit-1.34.29.dist-info/RECORD +0 -166
  167. {openlit-1.34.29.dist-info → openlit-1.34.31.dist-info}/LICENSE +0 -0
  168. {openlit-1.34.29.dist-info → openlit-1.34.31.dist-info}/WHEEL +0 -0
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Mistral OpenTelemetry instrumentation utility functions
3
3
  """
4
+
4
5
  import time
5
6
 
6
7
  from opentelemetry.trace import Status, StatusCode
@@ -17,6 +18,7 @@ from openlit.__helpers import (
17
18
  )
18
19
  from openlit.semcov import SemanticConvention
19
20
 
21
+
20
22
  def format_content(messages):
21
23
  """
22
24
  Process a list of messages to extract content.
@@ -29,8 +31,9 @@ def format_content(messages):
29
31
 
30
32
  if isinstance(content, list):
31
33
  content_str = ", ".join(
32
- f'{item["type"]}: {item["text"] if "text" in item else item.get("image_url", "")}'
33
- if "type" in item else f'text: {item.get("text", "")}'
34
+ f"{item['type']}: {item['text'] if 'text' in item else item.get('image_url', '')}"
35
+ if "type" in item
36
+ else f"text: {item.get('text', '')}"
34
37
  for item in content
35
38
  )
36
39
  formatted_messages.append(f"{role}: {content_str}")
@@ -39,6 +42,7 @@ def format_content(messages):
39
42
 
40
43
  return "\n".join(formatted_messages)
41
44
 
45
+
42
46
  def process_chunk(scope, chunk):
43
47
  """
44
48
  Process a chunk of response data and update state.
@@ -80,11 +84,18 @@ def process_chunk(scope, chunk):
80
84
  func = tool.get("function", {})
81
85
  scope._tools[idx] = {
82
86
  "id": tool["id"],
83
- "function": {"name": func.get("name", ""), "arguments": func.get("arguments", "")},
84
- "type": tool.get("type", "function")
87
+ "function": {
88
+ "name": func.get("name", ""),
89
+ "arguments": func.get("arguments", ""),
90
+ },
91
+ "type": tool.get("type", "function"),
85
92
  }
86
- elif scope._tools[idx] and "function" in tool: # Append args (id is None)
87
- scope._tools[idx]["function"]["arguments"] += tool["function"].get("arguments", "")
93
+ elif (
94
+ scope._tools[idx] and "function" in tool
95
+ ): # Append args (id is None)
96
+ scope._tools[idx]["function"]["arguments"] += tool[
97
+ "function"
98
+ ].get("arguments", "")
88
99
 
89
100
  # Handle usage information (typically only in final chunk)
90
101
  if data.get("usage"):
@@ -92,11 +103,23 @@ def process_chunk(scope, chunk):
92
103
  scope._output_tokens = data.get("usage").get("completion_tokens", 0)
93
104
  scope._response_id = data.get("id")
94
105
  scope._response_model = data.get("model")
95
- scope._finish_reason = choices[0].get("finish_reason", "") if choices else ""
106
+ scope._finish_reason = (
107
+ choices[0].get("finish_reason", "") if choices else ""
108
+ )
96
109
  scope._end_time = time.time()
97
110
 
98
- def common_chat_logic(scope, pricing_info, environment, application_name, metrics,
99
- capture_message_content, disable_metrics, version, is_stream):
111
+
112
+ def common_chat_logic(
113
+ scope,
114
+ pricing_info,
115
+ environment,
116
+ application_name,
117
+ metrics,
118
+ capture_message_content,
119
+ disable_metrics,
120
+ version,
121
+ is_stream,
122
+ ):
100
123
  """
101
124
  Process chat request and generate Telemetry
102
125
  """
@@ -107,54 +130,117 @@ def common_chat_logic(scope, pricing_info, environment, application_name, metric
107
130
  prompt = format_content(scope._kwargs.get("messages", []))
108
131
  request_model = scope._kwargs.get("model", "mistral-small-latest")
109
132
 
110
- cost = get_chat_model_cost(request_model, pricing_info, scope._input_tokens, scope._output_tokens)
133
+ cost = get_chat_model_cost(
134
+ request_model, pricing_info, scope._input_tokens, scope._output_tokens
135
+ )
111
136
 
112
137
  # Common Span Attributes
113
- common_span_attributes(scope,
114
- SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT, SemanticConvention.GEN_AI_SYSTEM_MISTRAL,
115
- scope._server_address, scope._server_port, request_model, scope._response_model,
116
- environment, application_name, is_stream, scope._tbt, scope._ttft, version)
138
+ common_span_attributes(
139
+ scope,
140
+ SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
141
+ SemanticConvention.GEN_AI_SYSTEM_MISTRAL,
142
+ scope._server_address,
143
+ scope._server_port,
144
+ request_model,
145
+ scope._response_model,
146
+ environment,
147
+ application_name,
148
+ is_stream,
149
+ scope._tbt,
150
+ scope._ttft,
151
+ version,
152
+ )
117
153
 
118
154
  # Span Attributes for Request parameters
119
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_SEED, scope._kwargs.get("seed", ""))
120
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_FREQUENCY_PENALTY, scope._kwargs.get("frequency_penalty", 0.0))
121
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MAX_TOKENS, scope._kwargs.get("max_tokens", -1))
122
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_PRESENCE_PENALTY, scope._kwargs.get("presence_penalty", 0.0))
123
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_STOP_SEQUENCES, scope._kwargs.get("stop_sequences", []))
124
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TEMPERATURE, scope._kwargs.get("temperature", 0.3))
125
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TOP_K, scope._kwargs.get("k", 1.0))
126
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TOP_P, scope._kwargs.get("p", 1.0))
155
+ scope._span.set_attribute(
156
+ SemanticConvention.GEN_AI_REQUEST_SEED, scope._kwargs.get("seed", "")
157
+ )
158
+ scope._span.set_attribute(
159
+ SemanticConvention.GEN_AI_REQUEST_FREQUENCY_PENALTY,
160
+ scope._kwargs.get("frequency_penalty", 0.0),
161
+ )
162
+ scope._span.set_attribute(
163
+ SemanticConvention.GEN_AI_REQUEST_MAX_TOKENS,
164
+ scope._kwargs.get("max_tokens", -1),
165
+ )
166
+ scope._span.set_attribute(
167
+ SemanticConvention.GEN_AI_REQUEST_PRESENCE_PENALTY,
168
+ scope._kwargs.get("presence_penalty", 0.0),
169
+ )
170
+ scope._span.set_attribute(
171
+ SemanticConvention.GEN_AI_REQUEST_STOP_SEQUENCES,
172
+ scope._kwargs.get("stop_sequences", []),
173
+ )
174
+ scope._span.set_attribute(
175
+ SemanticConvention.GEN_AI_REQUEST_TEMPERATURE,
176
+ scope._kwargs.get("temperature", 0.3),
177
+ )
178
+ scope._span.set_attribute(
179
+ SemanticConvention.GEN_AI_REQUEST_TOP_K, scope._kwargs.get("k", 1.0)
180
+ )
181
+ scope._span.set_attribute(
182
+ SemanticConvention.GEN_AI_REQUEST_TOP_P, scope._kwargs.get("p", 1.0)
183
+ )
127
184
 
128
185
  # Span Attributes for Response parameters
129
186
  scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_ID, scope._response_id)
130
- scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_FINISH_REASON, [scope._finish_reason])
131
- scope._span.set_attribute(SemanticConvention.GEN_AI_OUTPUT_TYPE, "text" if isinstance(scope._llmresponse, str) else "json")
187
+ scope._span.set_attribute(
188
+ SemanticConvention.GEN_AI_RESPONSE_FINISH_REASON, [scope._finish_reason]
189
+ )
190
+ scope._span.set_attribute(
191
+ SemanticConvention.GEN_AI_OUTPUT_TYPE,
192
+ "text" if isinstance(scope._llmresponse, str) else "json",
193
+ )
132
194
 
133
195
  # Span Attributes for Cost and Tokens
134
- scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, scope._input_tokens)
135
- scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS, scope._output_tokens)
136
- scope._span.set_attribute(SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE, scope._input_tokens + scope._output_tokens)
196
+ scope._span.set_attribute(
197
+ SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, scope._input_tokens
198
+ )
199
+ scope._span.set_attribute(
200
+ SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS, scope._output_tokens
201
+ )
202
+ scope._span.set_attribute(
203
+ SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE,
204
+ scope._input_tokens + scope._output_tokens,
205
+ )
137
206
  scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
138
207
 
139
208
  # Span Attributes for Tools - optimized
140
209
  if scope._tools:
141
210
  tools = scope._tools if isinstance(scope._tools, list) else [scope._tools]
142
211
 
143
- names, ids, args = zip(*[
144
- (t.get("function", {}).get("name", ""),
145
- str(t.get("id", "")),
146
- str(t.get("function", {}).get("arguments", "")))
147
- for t in tools if isinstance(t, dict) and t
148
- ]) if tools else ([], [], [])
212
+ names, ids, args = (
213
+ zip(
214
+ *[
215
+ (
216
+ t.get("function", {}).get("name", ""),
217
+ str(t.get("id", "")),
218
+ str(t.get("function", {}).get("arguments", "")),
219
+ )
220
+ for t in tools
221
+ if isinstance(t, dict) and t
222
+ ]
223
+ )
224
+ if tools
225
+ else ([], [], [])
226
+ )
149
227
 
150
- scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_NAME, ", ".join(filter(None, names)))
151
- scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_CALL_ID, ", ".join(filter(None, ids)))
152
- scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_ARGS, ", ".join(filter(None, args)))
228
+ scope._span.set_attribute(
229
+ SemanticConvention.GEN_AI_TOOL_NAME, ", ".join(filter(None, names))
230
+ )
231
+ scope._span.set_attribute(
232
+ SemanticConvention.GEN_AI_TOOL_CALL_ID, ", ".join(filter(None, ids))
233
+ )
234
+ scope._span.set_attribute(
235
+ SemanticConvention.GEN_AI_TOOL_ARGS, ", ".join(filter(None, args))
236
+ )
153
237
 
154
238
  # Span Attributes for Content
155
239
  if capture_message_content:
156
240
  scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_PROMPT, prompt)
157
- scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_COMPLETION, scope._llmresponse)
241
+ scope._span.set_attribute(
242
+ SemanticConvention.GEN_AI_CONTENT_COMPLETION, scope._llmresponse
243
+ )
158
244
 
159
245
  # To be removed once the change to span_attributes (from span events) is complete
160
246
  scope._span.add_event(
@@ -174,23 +260,69 @@ def common_chat_logic(scope, pricing_info, environment, application_name, metric
174
260
 
175
261
  # Metrics
176
262
  if not disable_metrics:
177
- record_completion_metrics(metrics, SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT, SemanticConvention.GEN_AI_SYSTEM_MISTRAL,
178
- scope._server_address, scope._server_port, request_model, scope._response_model, environment,
179
- application_name, scope._start_time, scope._end_time, scope._input_tokens, scope._output_tokens,
180
- cost, scope._tbt, scope._ttft)
263
+ record_completion_metrics(
264
+ metrics,
265
+ SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
266
+ SemanticConvention.GEN_AI_SYSTEM_MISTRAL,
267
+ scope._server_address,
268
+ scope._server_port,
269
+ request_model,
270
+ scope._response_model,
271
+ environment,
272
+ application_name,
273
+ scope._start_time,
274
+ scope._end_time,
275
+ scope._input_tokens,
276
+ scope._output_tokens,
277
+ cost,
278
+ scope._tbt,
279
+ scope._ttft,
280
+ )
281
+
181
282
 
182
- def process_streaming_chat_response(scope, pricing_info, environment, application_name, metrics,
183
- capture_message_content=False, disable_metrics=False, version=""):
283
+ def process_streaming_chat_response(
284
+ scope,
285
+ pricing_info,
286
+ environment,
287
+ application_name,
288
+ metrics,
289
+ capture_message_content=False,
290
+ disable_metrics=False,
291
+ version="",
292
+ ):
184
293
  """
185
294
  Process streaming chat request and generate Telemetry
186
295
  """
187
296
 
188
- common_chat_logic(scope, pricing_info, environment, application_name, metrics,
189
- capture_message_content, disable_metrics, version, is_stream=True)
297
+ common_chat_logic(
298
+ scope,
299
+ pricing_info,
300
+ environment,
301
+ application_name,
302
+ metrics,
303
+ capture_message_content,
304
+ disable_metrics,
305
+ version,
306
+ is_stream=True,
307
+ )
190
308
 
191
- def process_chat_response(response, request_model, pricing_info, server_port, server_address,
192
- environment, application_name, metrics, start_time, span, capture_message_content=False,
193
- disable_metrics=False, version="1.0.0", **kwargs):
309
+
310
+ def process_chat_response(
311
+ response,
312
+ request_model,
313
+ pricing_info,
314
+ server_port,
315
+ server_address,
316
+ environment,
317
+ application_name,
318
+ metrics,
319
+ start_time,
320
+ span,
321
+ capture_message_content=False,
322
+ disable_metrics=False,
323
+ version="1.0.0",
324
+ **kwargs,
325
+ ):
194
326
  """
195
327
  Process chat request and generate Telemetry
196
328
  """
@@ -214,21 +346,45 @@ def process_chat_response(response, request_model, pricing_info, server_port, se
214
346
  scope._ttft, scope._tbt = scope._end_time - scope._start_time, 0
215
347
  scope._server_address, scope._server_port = server_address, server_port
216
348
  scope._kwargs = kwargs
217
- scope._finish_reason = str(response_dict.get("choices", [])[0].get("finish_reason", "")) if response_dict.get("choices") else ""
349
+ scope._finish_reason = (
350
+ str(response_dict.get("choices", [])[0].get("finish_reason", ""))
351
+ if response_dict.get("choices")
352
+ else ""
353
+ )
218
354
 
219
355
  # Handle tool calls
220
356
  if kwargs.get("tools"):
221
- scope._tools = response_dict.get("choices", [{}])[0].get("message", {}).get("tool_calls")
357
+ scope._tools = (
358
+ response_dict.get("choices", [{}])[0].get("message", {}).get("tool_calls")
359
+ )
222
360
  else:
223
361
  scope._tools = None
224
362
 
225
- common_chat_logic(scope, pricing_info, environment, application_name, metrics,
226
- capture_message_content, disable_metrics, version, is_stream=False)
363
+ common_chat_logic(
364
+ scope,
365
+ pricing_info,
366
+ environment,
367
+ application_name,
368
+ metrics,
369
+ capture_message_content,
370
+ disable_metrics,
371
+ version,
372
+ is_stream=False,
373
+ )
227
374
 
228
375
  return response
229
376
 
230
- def common_embedding_logic(scope, pricing_info, environment, application_name, metrics,
231
- capture_message_content, disable_metrics, version):
377
+
378
+ def common_embedding_logic(
379
+ scope,
380
+ pricing_info,
381
+ environment,
382
+ application_name,
383
+ metrics,
384
+ capture_message_content,
385
+ disable_metrics,
386
+ version,
387
+ ):
232
388
  """
233
389
  Process embedding request and generate Telemetry
234
390
  """
@@ -239,17 +395,35 @@ def common_embedding_logic(scope, pricing_info, environment, application_name, m
239
395
  cost = get_embed_model_cost(request_model, pricing_info, scope._input_tokens)
240
396
 
241
397
  # Common Span Attributes
242
- common_span_attributes(scope,
243
- SemanticConvention.GEN_AI_OPERATION_TYPE_EMBEDDING, SemanticConvention.GEN_AI_SYSTEM_MISTRAL,
244
- scope._server_address, scope._server_port, request_model, scope._response_model,
245
- environment, application_name, False, 0, scope._ttft, version)
398
+ common_span_attributes(
399
+ scope,
400
+ SemanticConvention.GEN_AI_OPERATION_TYPE_EMBEDDING,
401
+ SemanticConvention.GEN_AI_SYSTEM_MISTRAL,
402
+ scope._server_address,
403
+ scope._server_port,
404
+ request_model,
405
+ scope._response_model,
406
+ environment,
407
+ application_name,
408
+ False,
409
+ 0,
410
+ scope._ttft,
411
+ version,
412
+ )
246
413
 
247
414
  # Span Attributes for Request parameters
248
- scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_ENCODING_FORMATS, [scope._kwargs.get("encoding_format", "float")])
415
+ scope._span.set_attribute(
416
+ SemanticConvention.GEN_AI_REQUEST_ENCODING_FORMATS,
417
+ [scope._kwargs.get("encoding_format", "float")],
418
+ )
249
419
 
250
420
  # Span Attributes for Cost and Tokens
251
- scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, scope._input_tokens)
252
- scope._span.set_attribute(SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE, scope._input_tokens)
421
+ scope._span.set_attribute(
422
+ SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, scope._input_tokens
423
+ )
424
+ scope._span.set_attribute(
425
+ SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE, scope._input_tokens
426
+ )
253
427
  scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
254
428
 
255
429
  # Span Attributes for Content
@@ -268,13 +442,39 @@ def common_embedding_logic(scope, pricing_info, environment, application_name, m
268
442
 
269
443
  # Metrics
270
444
  if not disable_metrics:
271
- record_embedding_metrics(metrics, SemanticConvention.GEN_AI_OPERATION_TYPE_EMBEDDING, SemanticConvention.GEN_AI_SYSTEM_MISTRAL,
272
- scope._server_address, scope._server_port, request_model, scope._response_model, environment,
273
- application_name, scope._start_time, scope._end_time, scope._input_tokens, cost)
445
+ record_embedding_metrics(
446
+ metrics,
447
+ SemanticConvention.GEN_AI_OPERATION_TYPE_EMBEDDING,
448
+ SemanticConvention.GEN_AI_SYSTEM_MISTRAL,
449
+ scope._server_address,
450
+ scope._server_port,
451
+ request_model,
452
+ scope._response_model,
453
+ environment,
454
+ application_name,
455
+ scope._start_time,
456
+ scope._end_time,
457
+ scope._input_tokens,
458
+ cost,
459
+ )
274
460
 
275
- def process_embedding_response(response, request_model, pricing_info, server_port, server_address,
276
- environment, application_name, metrics, start_time, span, capture_message_content=False,
277
- disable_metrics=False, version="1.0.0", **kwargs):
461
+
462
+ def process_embedding_response(
463
+ response,
464
+ request_model,
465
+ pricing_info,
466
+ server_port,
467
+ server_address,
468
+ environment,
469
+ application_name,
470
+ metrics,
471
+ start_time,
472
+ span,
473
+ capture_message_content=False,
474
+ disable_metrics=False,
475
+ version="1.0.0",
476
+ **kwargs,
477
+ ):
278
478
  """
279
479
  Process embedding request and generate Telemetry
280
480
  """
@@ -292,7 +492,15 @@ def process_embedding_response(response, request_model, pricing_info, server_por
292
492
  scope._server_address, scope._server_port = server_address, server_port
293
493
  scope._kwargs = kwargs
294
494
 
295
- common_embedding_logic(scope, pricing_info, environment, application_name, metrics,
296
- capture_message_content, disable_metrics, version)
495
+ common_embedding_logic(
496
+ scope,
497
+ pricing_info,
498
+ environment,
499
+ application_name,
500
+ metrics,
501
+ capture_message_content,
502
+ disable_metrics,
503
+ version,
504
+ )
297
505
 
298
506
  return response
@@ -6,16 +6,13 @@ import importlib.metadata
6
6
  from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
7
7
  from wrapt import wrap_function_wrapper
8
8
 
9
- from openlit.instrumentation.multion.multion import (
10
- multion_wrap
11
- )
9
+ from openlit.instrumentation.multion.multion import multion_wrap
12
10
 
13
- from openlit.instrumentation.multion.async_multion import (
14
- async_multion_wrap
15
- )
11
+ from openlit.instrumentation.multion.async_multion import async_multion_wrap
16
12
 
17
13
  _instruments = ("multion >= 1.3.8",)
18
14
 
15
+
19
16
  class MultiOnInstrumentor(BaseInstrumentor):
20
17
  """
21
18
  An instrumentor for multion's client library.
@@ -38,43 +35,96 @@ class MultiOnInstrumentor(BaseInstrumentor):
38
35
  wrap_function_wrapper(
39
36
  "multion.client",
40
37
  "MultiOn.browse",
41
- multion_wrap("multion.browse", version, environment, application_name,
42
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
38
+ multion_wrap(
39
+ "multion.browse",
40
+ version,
41
+ environment,
42
+ application_name,
43
+ tracer,
44
+ pricing_info,
45
+ capture_message_content,
46
+ metrics,
47
+ disable_metrics,
48
+ ),
43
49
  )
44
50
  wrap_function_wrapper(
45
51
  "multion.client",
46
52
  "MultiOn.retrieve",
47
- multion_wrap("multion.retrieve", version, environment, application_name,
48
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
53
+ multion_wrap(
54
+ "multion.retrieve",
55
+ version,
56
+ environment,
57
+ application_name,
58
+ tracer,
59
+ pricing_info,
60
+ capture_message_content,
61
+ metrics,
62
+ disable_metrics,
63
+ ),
49
64
  )
50
65
  wrap_function_wrapper(
51
66
  "multion.sessions.client",
52
67
  "SessionsClient.create",
53
- multion_wrap("multion.sessions.create", version, environment, application_name,
54
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
68
+ multion_wrap(
69
+ "multion.sessions.create",
70
+ version,
71
+ environment,
72
+ application_name,
73
+ tracer,
74
+ pricing_info,
75
+ capture_message_content,
76
+ metrics,
77
+ disable_metrics,
78
+ ),
55
79
  )
56
80
 
57
81
  # Asynchronus
58
82
  wrap_function_wrapper(
59
83
  "multion.client",
60
84
  "AsyncMultiOn.browse",
61
- async_multion_wrap("multion.browse", version, environment, application_name,
62
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
85
+ async_multion_wrap(
86
+ "multion.browse",
87
+ version,
88
+ environment,
89
+ application_name,
90
+ tracer,
91
+ pricing_info,
92
+ capture_message_content,
93
+ metrics,
94
+ disable_metrics,
95
+ ),
63
96
  )
64
97
  wrap_function_wrapper(
65
98
  "multion.client",
66
99
  "AsyncMultiOn.retrieve",
67
- async_multion_wrap("multion.retrieve", version, environment, application_name,
68
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
100
+ async_multion_wrap(
101
+ "multion.retrieve",
102
+ version,
103
+ environment,
104
+ application_name,
105
+ tracer,
106
+ pricing_info,
107
+ capture_message_content,
108
+ metrics,
109
+ disable_metrics,
110
+ ),
69
111
  )
70
112
  wrap_function_wrapper(
71
113
  "multion.sessions.client",
72
114
  "AsyncSessionsClient.create",
73
- async_multion_wrap("multion.sessions.create", version, environment, application_name,
74
- tracer, pricing_info, capture_message_content, metrics, disable_metrics),
115
+ async_multion_wrap(
116
+ "multion.sessions.create",
117
+ version,
118
+ environment,
119
+ application_name,
120
+ tracer,
121
+ pricing_info,
122
+ capture_message_content,
123
+ metrics,
124
+ disable_metrics,
125
+ ),
75
126
  )
76
127
 
77
-
78
128
  def _uninstrument(self, **kwargs):
79
129
  # Proper uninstrumentation logic to revert patched methods
80
130
  pass