openlit 1.34.30__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.
- openlit/__helpers.py +235 -86
- openlit/__init__.py +16 -13
- openlit/_instrumentors.py +2 -1
- openlit/evals/all.py +50 -21
- openlit/evals/bias_detection.py +47 -20
- openlit/evals/hallucination.py +53 -22
- openlit/evals/toxicity.py +50 -21
- openlit/evals/utils.py +54 -30
- openlit/guard/all.py +61 -19
- openlit/guard/prompt_injection.py +34 -14
- openlit/guard/restrict_topic.py +46 -15
- openlit/guard/sensitive_topic.py +34 -14
- openlit/guard/utils.py +58 -22
- openlit/instrumentation/ag2/__init__.py +24 -8
- openlit/instrumentation/ag2/ag2.py +34 -13
- openlit/instrumentation/ag2/async_ag2.py +34 -13
- openlit/instrumentation/ag2/utils.py +133 -30
- openlit/instrumentation/ai21/__init__.py +43 -14
- openlit/instrumentation/ai21/ai21.py +47 -21
- openlit/instrumentation/ai21/async_ai21.py +47 -21
- openlit/instrumentation/ai21/utils.py +299 -78
- openlit/instrumentation/anthropic/__init__.py +21 -4
- openlit/instrumentation/anthropic/anthropic.py +28 -17
- openlit/instrumentation/anthropic/async_anthropic.py +28 -17
- openlit/instrumentation/anthropic/utils.py +145 -35
- openlit/instrumentation/assemblyai/__init__.py +11 -2
- openlit/instrumentation/assemblyai/assemblyai.py +15 -4
- openlit/instrumentation/assemblyai/utils.py +120 -25
- openlit/instrumentation/astra/__init__.py +43 -10
- openlit/instrumentation/astra/astra.py +28 -5
- openlit/instrumentation/astra/async_astra.py +28 -5
- openlit/instrumentation/astra/utils.py +151 -55
- openlit/instrumentation/azure_ai_inference/__init__.py +43 -10
- openlit/instrumentation/azure_ai_inference/async_azure_ai_inference.py +53 -21
- openlit/instrumentation/azure_ai_inference/azure_ai_inference.py +53 -21
- openlit/instrumentation/azure_ai_inference/utils.py +307 -83
- openlit/instrumentation/bedrock/__init__.py +21 -4
- openlit/instrumentation/bedrock/bedrock.py +63 -25
- openlit/instrumentation/bedrock/utils.py +139 -30
- openlit/instrumentation/chroma/__init__.py +89 -16
- openlit/instrumentation/chroma/chroma.py +28 -6
- openlit/instrumentation/chroma/utils.py +167 -51
- openlit/instrumentation/cohere/__init__.py +63 -18
- openlit/instrumentation/cohere/async_cohere.py +63 -24
- openlit/instrumentation/cohere/cohere.py +63 -24
- openlit/instrumentation/cohere/utils.py +286 -73
- openlit/instrumentation/controlflow/__init__.py +35 -9
- openlit/instrumentation/controlflow/controlflow.py +66 -33
- openlit/instrumentation/crawl4ai/__init__.py +25 -10
- openlit/instrumentation/crawl4ai/async_crawl4ai.py +78 -31
- openlit/instrumentation/crawl4ai/crawl4ai.py +78 -31
- openlit/instrumentation/crewai/__init__.py +40 -15
- openlit/instrumentation/crewai/async_crewai.py +32 -7
- openlit/instrumentation/crewai/crewai.py +32 -7
- openlit/instrumentation/crewai/utils.py +159 -56
- openlit/instrumentation/dynamiq/__init__.py +46 -12
- openlit/instrumentation/dynamiq/dynamiq.py +74 -33
- openlit/instrumentation/elevenlabs/__init__.py +23 -4
- openlit/instrumentation/elevenlabs/async_elevenlabs.py +16 -4
- openlit/instrumentation/elevenlabs/elevenlabs.py +16 -4
- openlit/instrumentation/elevenlabs/utils.py +128 -25
- openlit/instrumentation/embedchain/__init__.py +11 -2
- openlit/instrumentation/embedchain/embedchain.py +68 -35
- openlit/instrumentation/firecrawl/__init__.py +24 -7
- openlit/instrumentation/firecrawl/firecrawl.py +46 -20
- openlit/instrumentation/google_ai_studio/__init__.py +45 -10
- openlit/instrumentation/google_ai_studio/async_google_ai_studio.py +67 -44
- openlit/instrumentation/google_ai_studio/google_ai_studio.py +67 -44
- openlit/instrumentation/google_ai_studio/utils.py +180 -67
- openlit/instrumentation/gpt4all/__init__.py +22 -7
- openlit/instrumentation/gpt4all/gpt4all.py +67 -29
- openlit/instrumentation/gpt4all/utils.py +285 -61
- openlit/instrumentation/gpu/__init__.py +128 -47
- openlit/instrumentation/groq/__init__.py +21 -4
- openlit/instrumentation/groq/async_groq.py +33 -21
- openlit/instrumentation/groq/groq.py +33 -21
- openlit/instrumentation/groq/utils.py +192 -55
- openlit/instrumentation/haystack/__init__.py +70 -24
- openlit/instrumentation/haystack/async_haystack.py +28 -6
- openlit/instrumentation/haystack/haystack.py +28 -6
- openlit/instrumentation/haystack/utils.py +196 -74
- openlit/instrumentation/julep/__init__.py +69 -19
- openlit/instrumentation/julep/async_julep.py +53 -27
- openlit/instrumentation/julep/julep.py +53 -28
- openlit/instrumentation/langchain/__init__.py +74 -63
- openlit/instrumentation/langchain/callback_handler.py +1100 -0
- openlit/instrumentation/langchain_community/__init__.py +13 -2
- openlit/instrumentation/langchain_community/async_langchain_community.py +23 -5
- openlit/instrumentation/langchain_community/langchain_community.py +23 -5
- openlit/instrumentation/langchain_community/utils.py +35 -9
- openlit/instrumentation/letta/__init__.py +68 -15
- openlit/instrumentation/letta/letta.py +99 -54
- openlit/instrumentation/litellm/__init__.py +43 -14
- openlit/instrumentation/litellm/async_litellm.py +51 -26
- openlit/instrumentation/litellm/litellm.py +51 -26
- openlit/instrumentation/litellm/utils.py +304 -102
- openlit/instrumentation/llamaindex/__init__.py +267 -90
- openlit/instrumentation/llamaindex/async_llamaindex.py +28 -6
- openlit/instrumentation/llamaindex/llamaindex.py +28 -6
- openlit/instrumentation/llamaindex/utils.py +204 -91
- openlit/instrumentation/mem0/__init__.py +11 -2
- openlit/instrumentation/mem0/mem0.py +50 -29
- openlit/instrumentation/milvus/__init__.py +10 -2
- openlit/instrumentation/milvus/milvus.py +31 -6
- openlit/instrumentation/milvus/utils.py +166 -67
- openlit/instrumentation/mistral/__init__.py +63 -18
- openlit/instrumentation/mistral/async_mistral.py +63 -24
- openlit/instrumentation/mistral/mistral.py +63 -24
- openlit/instrumentation/mistral/utils.py +277 -69
- openlit/instrumentation/multion/__init__.py +69 -19
- openlit/instrumentation/multion/async_multion.py +57 -26
- openlit/instrumentation/multion/multion.py +57 -26
- openlit/instrumentation/ollama/__init__.py +39 -18
- openlit/instrumentation/ollama/async_ollama.py +57 -26
- openlit/instrumentation/ollama/ollama.py +57 -26
- openlit/instrumentation/ollama/utils.py +226 -50
- openlit/instrumentation/openai/__init__.py +156 -32
- openlit/instrumentation/openai/async_openai.py +147 -67
- openlit/instrumentation/openai/openai.py +150 -67
- openlit/instrumentation/openai/utils.py +657 -185
- openlit/instrumentation/openai_agents/__init__.py +5 -1
- openlit/instrumentation/openai_agents/processor.py +110 -90
- openlit/instrumentation/phidata/__init__.py +13 -5
- openlit/instrumentation/phidata/phidata.py +67 -32
- openlit/instrumentation/pinecone/__init__.py +48 -9
- openlit/instrumentation/pinecone/async_pinecone.py +27 -5
- openlit/instrumentation/pinecone/pinecone.py +27 -5
- openlit/instrumentation/pinecone/utils.py +153 -47
- openlit/instrumentation/premai/__init__.py +22 -7
- openlit/instrumentation/premai/premai.py +51 -26
- openlit/instrumentation/premai/utils.py +246 -59
- openlit/instrumentation/pydantic_ai/__init__.py +49 -22
- openlit/instrumentation/pydantic_ai/pydantic_ai.py +69 -16
- openlit/instrumentation/pydantic_ai/utils.py +89 -24
- openlit/instrumentation/qdrant/__init__.py +19 -4
- openlit/instrumentation/qdrant/async_qdrant.py +33 -7
- openlit/instrumentation/qdrant/qdrant.py +33 -7
- openlit/instrumentation/qdrant/utils.py +228 -93
- openlit/instrumentation/reka/__init__.py +23 -10
- openlit/instrumentation/reka/async_reka.py +17 -11
- openlit/instrumentation/reka/reka.py +17 -11
- openlit/instrumentation/reka/utils.py +138 -36
- openlit/instrumentation/together/__init__.py +44 -12
- openlit/instrumentation/together/async_together.py +50 -27
- openlit/instrumentation/together/together.py +50 -27
- openlit/instrumentation/together/utils.py +301 -71
- openlit/instrumentation/transformers/__init__.py +2 -1
- openlit/instrumentation/transformers/transformers.py +13 -3
- openlit/instrumentation/transformers/utils.py +139 -36
- openlit/instrumentation/vertexai/__init__.py +81 -16
- openlit/instrumentation/vertexai/async_vertexai.py +33 -15
- openlit/instrumentation/vertexai/utils.py +123 -27
- openlit/instrumentation/vertexai/vertexai.py +33 -15
- openlit/instrumentation/vllm/__init__.py +12 -5
- openlit/instrumentation/vllm/utils.py +121 -31
- openlit/instrumentation/vllm/vllm.py +16 -10
- openlit/otel/events.py +35 -10
- openlit/otel/metrics.py +32 -24
- openlit/otel/tracing.py +24 -9
- openlit/semcov/__init__.py +72 -6
- {openlit-1.34.30.dist-info → openlit-1.34.31.dist-info}/METADATA +2 -1
- openlit-1.34.31.dist-info/RECORD +166 -0
- openlit/instrumentation/langchain/async_langchain.py +0 -102
- openlit/instrumentation/langchain/langchain.py +0 -102
- openlit/instrumentation/langchain/utils.py +0 -252
- openlit-1.34.30.dist-info/RECORD +0 -168
- {openlit-1.34.30.dist-info → openlit-1.34.31.dist-info}/LICENSE +0 -0
- {openlit-1.34.30.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
|
33
|
-
if "type" in item
|
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": {
|
84
|
-
|
87
|
+
"function": {
|
88
|
+
"name": func.get("name", ""),
|
89
|
+
"arguments": func.get("arguments", ""),
|
90
|
+
},
|
91
|
+
"type": tool.get("type", "function"),
|
85
92
|
}
|
86
|
-
elif
|
87
|
-
scope._tools[idx]
|
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 =
|
106
|
+
scope._finish_reason = (
|
107
|
+
choices[0].get("finish_reason", "") if choices else ""
|
108
|
+
)
|
96
109
|
scope._end_time = time.time()
|
97
110
|
|
98
|
-
|
99
|
-
|
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(
|
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(
|
114
|
-
|
115
|
-
|
116
|
-
|
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(
|
120
|
-
|
121
|
-
|
122
|
-
scope._span.set_attribute(
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
scope._span.set_attribute(
|
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(
|
131
|
-
|
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(
|
135
|
-
|
136
|
-
|
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 =
|
144
|
-
(
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
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(
|
151
|
-
|
152
|
-
|
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(
|
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(
|
178
|
-
|
179
|
-
|
180
|
-
|
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(
|
183
|
-
|
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(
|
189
|
-
|
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
|
-
|
192
|
-
|
193
|
-
|
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 =
|
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 =
|
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(
|
226
|
-
|
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
|
-
|
231
|
-
|
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(
|
243
|
-
|
244
|
-
|
245
|
-
|
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(
|
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(
|
252
|
-
|
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(
|
272
|
-
|
273
|
-
|
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
|
-
|
276
|
-
|
277
|
-
|
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(
|
296
|
-
|
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(
|
42
|
-
|
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(
|
48
|
-
|
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(
|
54
|
-
|
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(
|
62
|
-
|
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(
|
68
|
-
|
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(
|
74
|
-
|
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
|