openlit 1.33.18__py3-none-any.whl → 1.33.20__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 +11 -41
- openlit/__init__.py +3 -3
- openlit/evals/utils.py +7 -7
- openlit/guard/utils.py +7 -7
- openlit/instrumentation/ag2/ag2.py +24 -24
- openlit/instrumentation/ai21/ai21.py +3 -3
- openlit/instrumentation/ai21/async_ai21.py +3 -3
- openlit/instrumentation/ai21/utils.py +59 -59
- openlit/instrumentation/anthropic/anthropic.py +2 -2
- openlit/instrumentation/anthropic/async_anthropic.py +2 -2
- openlit/instrumentation/anthropic/utils.py +34 -34
- openlit/instrumentation/assemblyai/assemblyai.py +24 -24
- openlit/instrumentation/astra/astra.py +3 -3
- openlit/instrumentation/astra/async_astra.py +3 -3
- openlit/instrumentation/astra/utils.py +39 -39
- openlit/instrumentation/azure_ai_inference/async_azure_ai_inference.py +10 -10
- openlit/instrumentation/azure_ai_inference/azure_ai_inference.py +10 -10
- openlit/instrumentation/azure_ai_inference/utils.py +38 -38
- openlit/instrumentation/bedrock/__init__.py +2 -1
- openlit/instrumentation/bedrock/bedrock.py +32 -214
- openlit/instrumentation/bedrock/utils.py +252 -0
- openlit/instrumentation/chroma/chroma.py +57 -57
- openlit/instrumentation/cohere/async_cohere.py +88 -88
- openlit/instrumentation/cohere/cohere.py +88 -88
- openlit/instrumentation/controlflow/controlflow.py +15 -15
- openlit/instrumentation/crawl4ai/async_crawl4ai.py +14 -14
- openlit/instrumentation/crawl4ai/crawl4ai.py +14 -14
- openlit/instrumentation/crewai/crewai.py +22 -22
- openlit/instrumentation/dynamiq/dynamiq.py +19 -19
- openlit/instrumentation/elevenlabs/async_elevenlabs.py +24 -25
- openlit/instrumentation/elevenlabs/elevenlabs.py +23 -25
- openlit/instrumentation/embedchain/embedchain.py +15 -15
- openlit/instrumentation/firecrawl/firecrawl.py +10 -10
- openlit/instrumentation/google_ai_studio/async_google_ai_studio.py +33 -33
- openlit/instrumentation/google_ai_studio/google_ai_studio.py +33 -33
- openlit/instrumentation/gpt4all/gpt4all.py +78 -78
- openlit/instrumentation/gpu/__init__.py +8 -8
- openlit/instrumentation/groq/async_groq.py +74 -74
- openlit/instrumentation/groq/groq.py +74 -74
- openlit/instrumentation/haystack/haystack.py +6 -6
- openlit/instrumentation/julep/async_julep.py +14 -14
- openlit/instrumentation/julep/julep.py +14 -14
- openlit/instrumentation/langchain/async_langchain.py +39 -39
- openlit/instrumentation/langchain/langchain.py +39 -39
- openlit/instrumentation/letta/letta.py +26 -26
- openlit/instrumentation/litellm/async_litellm.py +94 -94
- openlit/instrumentation/litellm/litellm.py +94 -94
- openlit/instrumentation/llamaindex/llamaindex.py +7 -7
- openlit/instrumentation/mem0/mem0.py +13 -13
- openlit/instrumentation/milvus/milvus.py +47 -47
- openlit/instrumentation/mistral/async_mistral.py +88 -88
- openlit/instrumentation/mistral/mistral.py +88 -88
- openlit/instrumentation/multion/async_multion.py +21 -21
- openlit/instrumentation/multion/multion.py +21 -21
- openlit/instrumentation/ollama/async_ollama.py +3 -3
- openlit/instrumentation/ollama/ollama.py +3 -3
- openlit/instrumentation/ollama/utils.py +50 -50
- openlit/instrumentation/openai/async_openai.py +225 -225
- openlit/instrumentation/openai/openai.py +225 -225
- openlit/instrumentation/openai_agents/openai_agents.py +11 -11
- openlit/instrumentation/phidata/phidata.py +15 -15
- openlit/instrumentation/pinecone/pinecone.py +43 -43
- openlit/instrumentation/premai/premai.py +86 -86
- openlit/instrumentation/qdrant/async_qdrant.py +95 -95
- openlit/instrumentation/qdrant/qdrant.py +99 -99
- openlit/instrumentation/reka/async_reka.py +33 -33
- openlit/instrumentation/reka/reka.py +33 -33
- openlit/instrumentation/together/async_together.py +90 -90
- openlit/instrumentation/together/together.py +90 -90
- openlit/instrumentation/transformers/transformers.py +26 -26
- openlit/instrumentation/vertexai/async_vertexai.py +64 -64
- openlit/instrumentation/vertexai/vertexai.py +64 -64
- openlit/instrumentation/vllm/vllm.py +24 -24
- openlit/otel/metrics.py +11 -11
- openlit/semcov/__init__.py +3 -3
- {openlit-1.33.18.dist-info → openlit-1.33.20.dist-info}/METADATA +8 -8
- openlit-1.33.20.dist-info/RECORD +131 -0
- {openlit-1.33.18.dist-info → openlit-1.33.20.dist-info}/WHEEL +1 -1
- openlit-1.33.18.dist-info/RECORD +0 -130
- {openlit-1.33.18.dist-info → openlit-1.33.20.dist-info}/LICENSE +0 -0
openlit/__helpers.py
CHANGED
@@ -12,7 +12,7 @@ import requests
|
|
12
12
|
from opentelemetry.sdk.resources import SERVICE_NAME, TELEMETRY_SDK_NAME, DEPLOYMENT_ENVIRONMENT
|
13
13
|
from opentelemetry.trace import Status, StatusCode
|
14
14
|
from opentelemetry._events import Event
|
15
|
-
from openlit.semcov import
|
15
|
+
from openlit.semcov import SemanticConvention
|
16
16
|
|
17
17
|
# Set up logging
|
18
18
|
logger = logging.getLogger(__name__)
|
@@ -176,12 +176,12 @@ def create_metrics_attributes(
|
|
176
176
|
TELEMETRY_SDK_NAME: 'openlit',
|
177
177
|
SERVICE_NAME: service_name,
|
178
178
|
DEPLOYMENT_ENVIRONMENT: deployment_environment,
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
179
|
+
SemanticConvention.GEN_AI_OPERATION: operation,
|
180
|
+
SemanticConvention.GEN_AI_SYSTEM: system,
|
181
|
+
SemanticConvention.GEN_AI_REQUEST_MODEL: request_model,
|
182
|
+
SemanticConvention.SERVER_ADDRESS: server_address,
|
183
|
+
SemanticConvention.SERVER_PORT: server_port,
|
184
|
+
SemanticConvention.GEN_AI_RESPONSE_MODEL: response_model
|
185
185
|
}
|
186
186
|
|
187
187
|
def set_server_address_and_port(client_instance: Any,
|
@@ -237,27 +237,21 @@ def extract_and_format_input(messages):
|
|
237
237
|
them into fixed roles like 'user', 'assistant', 'system', 'tool'.
|
238
238
|
"""
|
239
239
|
|
240
|
-
fixed_roles = ['user', 'assistant', 'system', 'tool']
|
241
|
-
# Initialize the dictionary with fixed keys and empty structures
|
240
|
+
fixed_roles = ['user', 'assistant', 'system', 'tool', 'developer']
|
242
241
|
formatted_messages = {role_key: {'role': '', 'content': ''} for role_key in fixed_roles}
|
243
242
|
|
244
243
|
for message in messages:
|
245
|
-
# Normalize the message structure
|
246
244
|
message = response_as_dict(message)
|
247
245
|
|
248
|
-
# Extract role and content
|
249
246
|
role = message.get('role')
|
250
247
|
if role not in fixed_roles:
|
251
|
-
continue
|
248
|
+
continue
|
252
249
|
|
253
250
|
content = message.get('content', '')
|
254
251
|
|
255
|
-
# Prepare content as a string
|
252
|
+
# Prepare content as a string, handling both list and str
|
256
253
|
if isinstance(content, list):
|
257
|
-
content_str = ", ".join(
|
258
|
-
f'{item.get("type", "text")}: {extract_text_from_item(item)}'
|
259
|
-
for item in content
|
260
|
-
)
|
254
|
+
content_str = ", ".join(str(item) for item in content)
|
261
255
|
else:
|
262
256
|
content_str = content
|
263
257
|
|
@@ -272,30 +266,6 @@ def extract_and_format_input(messages):
|
|
272
266
|
|
273
267
|
return formatted_messages
|
274
268
|
|
275
|
-
def extract_text_from_item(item):
|
276
|
-
"""
|
277
|
-
Extract text from inpit message
|
278
|
-
"""
|
279
|
-
|
280
|
-
#pylint: disable=no-else-return
|
281
|
-
if item.get('type') == 'text':
|
282
|
-
return item.get('text', '')
|
283
|
-
elif item.get('type') == 'image':
|
284
|
-
# Handle image content specifically checking for 'url' or 'base64'
|
285
|
-
source = item.get('source', {})
|
286
|
-
if isinstance(source, dict):
|
287
|
-
if source.get('type') == 'base64':
|
288
|
-
# Return the actual base64 data if present
|
289
|
-
return source.get('data', '[Missing base64 data]')
|
290
|
-
elif source.get('type') == 'url':
|
291
|
-
return source.get('url', '[Missing URL]')
|
292
|
-
elif item.get('type') == 'image_url':
|
293
|
-
# New format: Handle the 'image_url' type
|
294
|
-
image_url = item.get('image_url', {})
|
295
|
-
if isinstance(image_url, dict):
|
296
|
-
return image_url.get('url', '[Missing image URL]')
|
297
|
-
return ''
|
298
|
-
|
299
269
|
# To be removed one the change to log events (from span events) is complete
|
300
270
|
def concatenate_all_contents(formatted_messages):
|
301
271
|
"""
|
openlit/__init__.py
CHANGED
@@ -18,7 +18,7 @@ import requests
|
|
18
18
|
from opentelemetry import trace as t
|
19
19
|
from opentelemetry.trace import SpanKind, Status, StatusCode, Span
|
20
20
|
from opentelemetry.sdk.resources import SERVICE_NAME, DEPLOYMENT_ENVIRONMENT
|
21
|
-
from openlit.semcov import
|
21
|
+
from openlit.semcov import SemanticConvention
|
22
22
|
from openlit.otel.tracing import setup_tracing
|
23
23
|
from openlit.otel.metrics import setup_meter
|
24
24
|
from openlit.otel.events import setup_events
|
@@ -573,7 +573,7 @@ def trace(wrapped):
|
|
573
573
|
try:
|
574
574
|
response = wrapped(*args, **kwargs)
|
575
575
|
span.set_attribute(
|
576
|
-
|
576
|
+
SemanticConvention.GEN_AI_CONTENT_COMPLETION, response or ""
|
577
577
|
)
|
578
578
|
span.set_status(Status(StatusCode.OK))
|
579
579
|
except Exception as e:
|
@@ -632,7 +632,7 @@ class TracedSpan:
|
|
632
632
|
result: The result to be set as an attribute on the span.
|
633
633
|
"""
|
634
634
|
|
635
|
-
self._span.set_attribute(
|
635
|
+
self._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_COMPLETION, result)
|
636
636
|
|
637
637
|
def set_metadata(self, metadata: Dict):
|
638
638
|
"""
|
openlit/evals/utils.py
CHANGED
@@ -10,7 +10,7 @@ from opentelemetry.metrics import get_meter
|
|
10
10
|
from opentelemetry.sdk.resources import TELEMETRY_SDK_NAME
|
11
11
|
from anthropic import Anthropic
|
12
12
|
from openai import OpenAI
|
13
|
-
from openlit.semcov import
|
13
|
+
from openlit.semcov import SemanticConvention
|
14
14
|
|
15
15
|
# Initialize logger for logging potential issues and operations
|
16
16
|
logger = logging.getLogger(__name__)
|
@@ -238,7 +238,7 @@ def eval_metrics():
|
|
238
238
|
)
|
239
239
|
|
240
240
|
guard_requests = meter.create_counter(
|
241
|
-
name=
|
241
|
+
name=SemanticConvention.EVAL_REQUESTS,
|
242
242
|
description="Counter for evaluation requests",
|
243
243
|
unit="1"
|
244
244
|
)
|
@@ -262,14 +262,14 @@ def eval_metric_attributes(verdict, score, validator, classification, explanatio
|
|
262
262
|
return {
|
263
263
|
TELEMETRY_SDK_NAME:
|
264
264
|
"openlit",
|
265
|
-
|
265
|
+
SemanticConvention.EVAL_VERDICT:
|
266
266
|
verdict,
|
267
|
-
|
267
|
+
SemanticConvention.EVAL_SCORE:
|
268
268
|
score,
|
269
|
-
|
269
|
+
SemanticConvention.EVAL_VALIDATOR:
|
270
270
|
validator,
|
271
|
-
|
271
|
+
SemanticConvention.EVAL_CLASSIFICATION:
|
272
272
|
classification,
|
273
|
-
|
273
|
+
SemanticConvention.EVAL_EXPLANATION:
|
274
274
|
explanation,
|
275
275
|
}
|
openlit/guard/utils.py
CHANGED
@@ -11,7 +11,7 @@ from opentelemetry.metrics import get_meter
|
|
11
11
|
from opentelemetry.sdk.resources import TELEMETRY_SDK_NAME
|
12
12
|
from anthropic import Anthropic
|
13
13
|
from openai import OpenAI
|
14
|
-
from openlit.semcov import
|
14
|
+
from openlit.semcov import SemanticConvention
|
15
15
|
|
16
16
|
# Initialize logger for logging potential issues and operations
|
17
17
|
logger = logging.getLogger(__name__)
|
@@ -202,7 +202,7 @@ def guard_metrics():
|
|
202
202
|
)
|
203
203
|
|
204
204
|
guard_requests = meter.create_counter(
|
205
|
-
name=
|
205
|
+
name=SemanticConvention.GUARD_REQUESTS,
|
206
206
|
description="Counter for Guard requests",
|
207
207
|
unit="1"
|
208
208
|
)
|
@@ -224,9 +224,9 @@ def guard_metric_attributes(verdict, score, validator, classification, explanati
|
|
224
224
|
"""
|
225
225
|
return {
|
226
226
|
TELEMETRY_SDK_NAME: "openlit",
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
227
|
+
SemanticConvention.GUARD_VERDICT: verdict,
|
228
|
+
SemanticConvention.GUARD_SCORE: score,
|
229
|
+
SemanticConvention.GUARD_VALIDATOR: validator,
|
230
|
+
SemanticConvention.GUARD_CLASSIFICATION: classification,
|
231
|
+
SemanticConvention.GUARD_EXPLANATION: explanation,
|
232
232
|
}
|
@@ -11,7 +11,7 @@ from openlit.__helpers import (
|
|
11
11
|
get_chat_model_cost,
|
12
12
|
otel_event,
|
13
13
|
)
|
14
|
-
from openlit.semcov import
|
14
|
+
from openlit.semcov import SemanticConvention
|
15
15
|
|
16
16
|
# Initialize logger for logging potential issues and operations
|
17
17
|
logger = logging.getLogger(__name__)
|
@@ -29,17 +29,17 @@ def set_span_attributes(span, version, operation_name, environment,
|
|
29
29
|
|
30
30
|
# Set Span attributes (OTel Semconv)
|
31
31
|
span.set_attribute(TELEMETRY_SDK_NAME, 'openlit')
|
32
|
-
span.set_attribute(
|
33
|
-
span.set_attribute(
|
34
|
-
span.set_attribute(
|
35
|
-
span.set_attribute(
|
36
|
-
span.set_attribute(
|
37
|
-
span.set_attribute(
|
32
|
+
span.set_attribute(SemanticConvention.GEN_AI_OPERATION, operation_name)
|
33
|
+
span.set_attribute(SemanticConvention.GEN_AI_SYSTEM, SemanticConvention.GEN_AI_SYSTEM_AG2)
|
34
|
+
span.set_attribute(SemanticConvention.GEN_AI_AGENT_NAME, AGENT_NAME)
|
35
|
+
span.set_attribute(SemanticConvention.SERVER_ADDRESS, server_address)
|
36
|
+
span.set_attribute(SemanticConvention.SERVER_PORT, server_port)
|
37
|
+
span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL, request_model)
|
38
38
|
|
39
39
|
# Set Span attributes (Extras)
|
40
40
|
span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
|
41
41
|
span.set_attribute(SERVICE_NAME, application_name)
|
42
|
-
span.set_attribute(
|
42
|
+
span.set_attribute(SemanticConvention.GEN_AI_SDK_VERSION, version)
|
43
43
|
|
44
44
|
def calculate_tokens_and_cost(response, request_model, pricing_info):
|
45
45
|
"""
|
@@ -64,13 +64,13 @@ def emit_events(response, event_provider, capture_message_content):
|
|
64
64
|
"""
|
65
65
|
for chat in response.chat_history:
|
66
66
|
event_type = (
|
67
|
-
|
68
|
-
else
|
67
|
+
SemanticConvention.GEN_AI_CHOICE if chat['role'] == 'user'
|
68
|
+
else SemanticConvention.GEN_AI_USER_MESSAGE
|
69
69
|
)
|
70
70
|
choice_event = otel_event(
|
71
71
|
name=event_type,
|
72
72
|
attributes={
|
73
|
-
|
73
|
+
SemanticConvention.GEN_AI_SYSTEM: SemanticConvention.GEN_AI_SYSTEM_AG2
|
74
74
|
},
|
75
75
|
body={
|
76
76
|
'index': response.chat_history.index(chat),
|
@@ -97,7 +97,7 @@ def conversable_agent(version, environment, application_name,
|
|
97
97
|
SYSTEM_MESSAGE = kwargs.get('system_message', '')
|
98
98
|
MODEL_AND_NAME_SET = True
|
99
99
|
|
100
|
-
span_name = f'{
|
100
|
+
span_name = f'{SemanticConvention.GEN_AI_OPERATION_TYPE_CREATE_AGENT} {AGENT_NAME}'
|
101
101
|
|
102
102
|
with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
|
103
103
|
try:
|
@@ -105,11 +105,11 @@ def conversable_agent(version, environment, application_name,
|
|
105
105
|
response = wrapped(*args, **kwargs)
|
106
106
|
end_time = time.time()
|
107
107
|
|
108
|
-
set_span_attributes(span, version,
|
108
|
+
set_span_attributes(span, version, SemanticConvention.GEN_AI_OPERATION_TYPE_CREATE_AGENT,
|
109
109
|
environment, application_name, server_address, server_port, REQUEST_MODEL)
|
110
|
-
span.set_attribute(
|
111
|
-
span.set_attribute(
|
112
|
-
span.set_attribute(
|
110
|
+
span.set_attribute(SemanticConvention.GEN_AI_AGENT_DESCRIPTION, SYSTEM_MESSAGE)
|
111
|
+
span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_MODEL, REQUEST_MODEL)
|
112
|
+
span.set_attribute(SemanticConvention.GEN_AI_SERVER_TTFT, end_time - start_time)
|
113
113
|
|
114
114
|
span.set_status(Status(StatusCode.OK))
|
115
115
|
|
@@ -130,7 +130,7 @@ def agent_run(version, environment, application_name,
|
|
130
130
|
def wrapper(wrapped, instance, args, kwargs):
|
131
131
|
server_address, server_port = '127.0.0.1', 80
|
132
132
|
|
133
|
-
span_name = f'{
|
133
|
+
span_name = f'{SemanticConvention.GEN_AI_OPERATION_TYPE_EXECUTE_AGENT_TASK} {AGENT_NAME}'
|
134
134
|
|
135
135
|
with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT) as span:
|
136
136
|
try:
|
@@ -141,14 +141,14 @@ def agent_run(version, environment, application_name,
|
|
141
141
|
input_tokens, output_tokens, cost = calculate_tokens_and_cost(response, REQUEST_MODEL, pricing_info)
|
142
142
|
response_model = list(response.cost.get('usage_including_cached_inference', {}).keys())[1]
|
143
143
|
|
144
|
-
set_span_attributes(span, version,
|
144
|
+
set_span_attributes(span, version, SemanticConvention.GEN_AI_OPERATION_TYPE_EXECUTE_AGENT_TASK,
|
145
145
|
environment, application_name, server_address, server_port, REQUEST_MODEL)
|
146
|
-
span.set_attribute(
|
147
|
-
span.set_attribute(
|
148
|
-
span.set_attribute(
|
149
|
-
span.set_attribute(
|
150
|
-
span.set_attribute(
|
151
|
-
span.set_attribute(
|
146
|
+
span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_MODEL, response_model)
|
147
|
+
span.set_attribute(SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, input_tokens)
|
148
|
+
span.set_attribute(SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens)
|
149
|
+
span.set_attribute(SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE, input_tokens + output_tokens)
|
150
|
+
span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
|
151
|
+
span.set_attribute(SemanticConvention.GEN_AI_SERVER_TTFT, end_time - start_time)
|
152
152
|
|
153
153
|
emit_events(response, event_provider, capture_message_content)
|
154
154
|
span.set_status(Status(StatusCode.OK))
|
@@ -16,7 +16,7 @@ from openlit.instrumentation.ai21.utils import (
|
|
16
16
|
process_chat_rag_response
|
17
17
|
)
|
18
18
|
|
19
|
-
from openlit.semcov import
|
19
|
+
from openlit.semcov import SemanticConvention
|
20
20
|
|
21
21
|
# Initialize logger for logging potential issues and operations
|
22
22
|
logger = logging.getLogger(__name__)
|
@@ -113,7 +113,7 @@ def chat(version, environment, application_name,
|
|
113
113
|
server_address, server_port = set_server_address_and_port(instance, 'api.ai21.com', 443)
|
114
114
|
request_model = kwargs.get('model', 'jamba-1.5-mini')
|
115
115
|
|
116
|
-
span_name = f'{
|
116
|
+
span_name = f'{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}'
|
117
117
|
|
118
118
|
# pylint: disable=no-else-return
|
119
119
|
if streaming:
|
@@ -163,7 +163,7 @@ def chat_rag(version, environment, application_name,
|
|
163
163
|
server_address, server_port = set_server_address_and_port(instance, 'api.ai21.com', 443)
|
164
164
|
request_model = kwargs.get('model', 'jamba-1.5-mini')
|
165
165
|
|
166
|
-
span_name = f'{
|
166
|
+
span_name = f'{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}'
|
167
167
|
|
168
168
|
with tracer.start_as_current_span(span_name, kind= SpanKind.CLIENT) as span:
|
169
169
|
start_time = time.time()
|
@@ -16,7 +16,7 @@ from openlit.instrumentation.ai21.utils import (
|
|
16
16
|
process_chat_rag_response
|
17
17
|
)
|
18
18
|
|
19
|
-
from openlit.semcov import
|
19
|
+
from openlit.semcov import SemanticConvention
|
20
20
|
|
21
21
|
# Initialize logger for logging potential issues and operations
|
22
22
|
logger = logging.getLogger(__name__)
|
@@ -113,7 +113,7 @@ def async_chat(version, environment, application_name,
|
|
113
113
|
server_address, server_port = set_server_address_and_port(instance, 'api.ai21.com', 443)
|
114
114
|
request_model = kwargs.get('model', 'jamba-1.5-mini')
|
115
115
|
|
116
|
-
span_name = f'{
|
116
|
+
span_name = f'{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}'
|
117
117
|
|
118
118
|
# pylint: disable=no-else-return
|
119
119
|
if streaming:
|
@@ -163,7 +163,7 @@ def async_chat_rag(version, environment, application_name,
|
|
163
163
|
server_address, server_port = set_server_address_and_port(instance, 'api.ai21.com', 443)
|
164
164
|
request_model = kwargs.get('model', 'jamba-1.5-mini')
|
165
165
|
|
166
|
-
span_name = f'{
|
166
|
+
span_name = f'{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}'
|
167
167
|
|
168
168
|
with tracer.start_as_current_span(span_name, kind= SpanKind.CLIENT) as span:
|
169
169
|
start_time = time.time()
|
@@ -19,7 +19,7 @@ from openlit.__helpers import (
|
|
19
19
|
otel_event,
|
20
20
|
concatenate_all_contents
|
21
21
|
)
|
22
|
-
from openlit.semcov import
|
22
|
+
from openlit.semcov import SemanticConvention
|
23
23
|
|
24
24
|
def setup_common_span_attributes(span, request_model, kwargs, tokens,
|
25
25
|
server_port, server_address, environment,
|
@@ -30,32 +30,32 @@ def setup_common_span_attributes(span, request_model, kwargs, tokens,
|
|
30
30
|
|
31
31
|
# Base attributes from SDK and operation settings.
|
32
32
|
span.set_attribute(TELEMETRY_SDK_NAME, 'openlit')
|
33
|
-
span.set_attribute(
|
34
|
-
span.set_attribute(
|
35
|
-
span.set_attribute(
|
36
|
-
span.set_attribute(
|
37
|
-
span.set_attribute(
|
38
|
-
span.set_attribute(
|
39
|
-
span.set_attribute(
|
40
|
-
span.set_attribute(
|
41
|
-
span.set_attribute(
|
42
|
-
span.set_attribute(
|
43
|
-
span.set_attribute(
|
33
|
+
span.set_attribute(SemanticConvention.GEN_AI_OPERATION, SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT)
|
34
|
+
span.set_attribute(SemanticConvention.GEN_AI_SYSTEM, SemanticConvention.GEN_AI_SYSTEM_AI21)
|
35
|
+
span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL, request_model)
|
36
|
+
span.set_attribute(SemanticConvention.SERVER_PORT, server_port)
|
37
|
+
span.set_attribute(SemanticConvention.GEN_AI_REQUEST_SEED, kwargs.get('seed', ''))
|
38
|
+
span.set_attribute(SemanticConvention.GEN_AI_REQUEST_FREQUENCY_PENALTY, kwargs.get('frequency_penalty', 0.0))
|
39
|
+
span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MAX_TOKENS, kwargs.get('max_tokens', -1))
|
40
|
+
span.set_attribute(SemanticConvention.GEN_AI_REQUEST_PRESENCE_PENALTY, kwargs.get('presence_penalty', 0.0))
|
41
|
+
span.set_attribute(SemanticConvention.GEN_AI_REQUEST_STOP_SEQUENCES, kwargs.get('stop', []))
|
42
|
+
span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TEMPERATURE, kwargs.get('temperature', 0.4))
|
43
|
+
span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TOP_P, kwargs.get('top_p', 1.0))
|
44
44
|
|
45
45
|
# Add token-related attributes if available.
|
46
46
|
if 'finish_reason' in tokens:
|
47
|
-
span.set_attribute(
|
47
|
+
span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_FINISH_REASON, [tokens['finish_reason']])
|
48
48
|
if 'response_id' in tokens:
|
49
|
-
span.set_attribute(
|
49
|
+
span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_ID, tokens['response_id'])
|
50
50
|
if 'input_tokens' in tokens:
|
51
|
-
span.set_attribute(
|
51
|
+
span.set_attribute(SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, tokens['input_tokens'])
|
52
52
|
if 'output_tokens' in tokens:
|
53
|
-
span.set_attribute(
|
53
|
+
span.set_attribute(SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS, tokens['output_tokens'])
|
54
54
|
if 'total_tokens' in tokens:
|
55
|
-
span.set_attribute(
|
55
|
+
span.set_attribute(SemanticConvention.GEN_AI_USAGE_TOTAL_TOKENS, tokens['total_tokens'])
|
56
56
|
|
57
|
-
span.set_attribute(
|
58
|
-
span.set_attribute(
|
57
|
+
span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_MODEL, request_model)
|
58
|
+
span.set_attribute(SemanticConvention.SERVER_ADDRESS, server_address)
|
59
59
|
# Environment and service identifiers.
|
60
60
|
span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
|
61
61
|
span.set_attribute(SERVICE_NAME, application_name)
|
@@ -73,8 +73,8 @@ def record_common_metrics(metrics, application_name, environment, request_model,
|
|
73
73
|
attributes = create_metrics_attributes(
|
74
74
|
service_name=application_name,
|
75
75
|
deployment_environment=environment,
|
76
|
-
operation=
|
77
|
-
system=
|
76
|
+
operation=SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT,
|
77
|
+
system=SemanticConvention.GEN_AI_SYSTEM_AI21,
|
78
78
|
request_model=request_model,
|
79
79
|
server_address=server_address,
|
80
80
|
server_port=server_port,
|
@@ -121,15 +121,15 @@ def emit_common_events(event_provider, choices, finish_reason, llmresponse, form
|
|
121
121
|
}
|
122
122
|
})
|
123
123
|
event = otel_event(
|
124
|
-
name=
|
125
|
-
attributes={
|
124
|
+
name=SemanticConvention.GEN_AI_CHOICE,
|
125
|
+
attributes={SemanticConvention.GEN_AI_SYSTEM: SemanticConvention.GEN_AI_SYSTEM_AI21},
|
126
126
|
body=choice_event_body
|
127
127
|
)
|
128
128
|
event_provider.emit(event)
|
129
129
|
else:
|
130
130
|
event = otel_event(
|
131
|
-
name=
|
132
|
-
attributes={
|
131
|
+
name=SemanticConvention.GEN_AI_CHOICE,
|
132
|
+
attributes={SemanticConvention.GEN_AI_SYSTEM: SemanticConvention.GEN_AI_SYSTEM_AI21},
|
133
133
|
body=choice_event_body
|
134
134
|
)
|
135
135
|
event_provider.emit(event)
|
@@ -144,8 +144,8 @@ def emit_common_events(event_provider, choices, finish_reason, llmresponse, form
|
|
144
144
|
}
|
145
145
|
}
|
146
146
|
event = otel_event(
|
147
|
-
name=
|
148
|
-
attributes={
|
147
|
+
name=SemanticConvention.GEN_AI_CHOICE,
|
148
|
+
attributes={SemanticConvention.GEN_AI_SYSTEM: SemanticConvention.GEN_AI_SYSTEM_AI21},
|
149
149
|
body=choice_event_body
|
150
150
|
)
|
151
151
|
event_provider.emit(event)
|
@@ -175,8 +175,8 @@ def emit_common_events(event_provider, choices, finish_reason, llmresponse, form
|
|
175
175
|
if tool_calls:
|
176
176
|
event_body['id'] = tool_calls[0].get('id', '')
|
177
177
|
event = otel_event(
|
178
|
-
name=getattr(
|
179
|
-
attributes={
|
178
|
+
name=getattr(SemanticConvention, f'GEN_AI_{role.upper()}_MESSAGE'),
|
179
|
+
attributes={SemanticConvention.GEN_AI_SYSTEM: SemanticConvention.GEN_AI_SYSTEM_AI21},
|
180
180
|
body=event_body
|
181
181
|
)
|
182
182
|
event_provider.emit(event)
|
@@ -233,13 +233,13 @@ def common_chat_logic(scope, pricing_info, environment, application_name, metric
|
|
233
233
|
'total_tokens': scope._input_tokens + scope._output_tokens,
|
234
234
|
}
|
235
235
|
extra_attrs = {
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
236
|
+
SemanticConvention.GEN_AI_REQUEST_IS_STREAM: is_stream,
|
237
|
+
SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE: scope._input_tokens + scope._output_tokens,
|
238
|
+
SemanticConvention.GEN_AI_USAGE_COST: cost,
|
239
|
+
SemanticConvention.GEN_AI_SERVER_TBT: scope._tbt,
|
240
|
+
SemanticConvention.GEN_AI_SERVER_TTFT: scope._ttft,
|
241
|
+
SemanticConvention.GEN_AI_SDK_VERSION: version,
|
242
|
+
SemanticConvention.GEN_AI_OUTPUT_TYPE: 'text' if isinstance(scope._llmresponse, str) else 'json'
|
243
243
|
}
|
244
244
|
# Set span attributes.
|
245
245
|
setup_common_span_attributes(scope._span, request_model, scope._kwargs, tokens,
|
@@ -249,12 +249,12 @@ def common_chat_logic(scope, pricing_info, environment, application_name, metric
|
|
249
249
|
# Optionally add events capturing the prompt and completion.
|
250
250
|
if capture_message_content:
|
251
251
|
scope._span.add_event(
|
252
|
-
name=
|
253
|
-
attributes={
|
252
|
+
name=SemanticConvention.GEN_AI_CONTENT_PROMPT_EVENT,
|
253
|
+
attributes={SemanticConvention.GEN_AI_CONTENT_PROMPT: prompt},
|
254
254
|
)
|
255
255
|
scope._span.add_event(
|
256
|
-
name=
|
257
|
-
attributes={
|
256
|
+
name=SemanticConvention.GEN_AI_CONTENT_COMPLETION_EVENT,
|
257
|
+
attributes={SemanticConvention.GEN_AI_CONTENT_COMPLETION: scope._llmresponse},
|
258
258
|
)
|
259
259
|
|
260
260
|
# Emit events for each choice and message role.
|
@@ -336,15 +336,15 @@ def process_chat_rag_response(response, request_model, pricing_info, server_port
|
|
336
336
|
# Create tokens dict and RAG-specific extra attributes.
|
337
337
|
tokens = {'response_id': response_dict.get('id'), 'input_tokens': input_tokens}
|
338
338
|
extra_attrs = {
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
339
|
+
SemanticConvention.GEN_AI_REQUEST_IS_STREAM: False,
|
340
|
+
SemanticConvention.GEN_AI_SERVER_TTFT: end_time - start_time,
|
341
|
+
SemanticConvention.GEN_AI_SDK_VERSION: version,
|
342
|
+
SemanticConvention.GEN_AI_RAG_MAX_SEGMENTS: kwargs.get('max_segments', -1),
|
343
|
+
SemanticConvention.GEN_AI_RAG_STRATEGY: kwargs.get('retrieval_strategy', 'segments'),
|
344
|
+
SemanticConvention.GEN_AI_RAG_SIMILARITY_THRESHOLD: kwargs.get('retrieval_similarity_threshold', -1),
|
345
|
+
SemanticConvention.GEN_AI_RAG_MAX_NEIGHBORS: kwargs.get('max_neighbors', -1),
|
346
|
+
SemanticConvention.GEN_AI_RAG_FILE_IDS: str(kwargs.get('file_ids', '')),
|
347
|
+
SemanticConvention.GEN_AI_RAG_DOCUMENTS_PATH: kwargs.get('path', '')
|
348
348
|
}
|
349
349
|
# Set common span attributes.
|
350
350
|
setup_common_span_attributes(span, request_model, kwargs, tokens,
|
@@ -354,8 +354,8 @@ def process_chat_rag_response(response, request_model, pricing_info, server_port
|
|
354
354
|
# Record the prompt event if requested.
|
355
355
|
if capture_message_content:
|
356
356
|
span.add_event(
|
357
|
-
name=
|
358
|
-
attributes={
|
357
|
+
name=SemanticConvention.GEN_AI_CONTENT_PROMPT_EVENT,
|
358
|
+
attributes={SemanticConvention.GEN_AI_CONTENT_PROMPT: prompt},
|
359
359
|
)
|
360
360
|
|
361
361
|
output_tokens = 0
|
@@ -368,13 +368,13 @@ def process_chat_rag_response(response, request_model, pricing_info, server_port
|
|
368
368
|
aggregated_completion.append(content)
|
369
369
|
output_tokens += general_tokens(content)
|
370
370
|
if kwargs.get('tools'):
|
371
|
-
span.set_attribute(
|
371
|
+
span.set_attribute(SemanticConvention.GEN_AI_TOOL_CALLS,
|
372
372
|
str(choices[i].get('message', {}).get('tool_calls')))
|
373
373
|
# Set output type based on actual content type.
|
374
374
|
if isinstance(content, str):
|
375
|
-
span.set_attribute(
|
375
|
+
span.set_attribute(SemanticConvention.GEN_AI_OUTPUT_TYPE, 'text')
|
376
376
|
elif content is not None:
|
377
|
-
span.set_attribute(
|
377
|
+
span.set_attribute(SemanticConvention.GEN_AI_OUTPUT_TYPE, 'json')
|
378
378
|
|
379
379
|
# Concatenate completion responses.
|
380
380
|
llmresponse = ''.join(aggregated_completion)
|
@@ -382,16 +382,16 @@ def process_chat_rag_response(response, request_model, pricing_info, server_port
|
|
382
382
|
tokens['total_tokens'] = input_tokens + output_tokens
|
383
383
|
|
384
384
|
cost = get_chat_model_cost(request_model, pricing_info, input_tokens, output_tokens)
|
385
|
-
span.set_attribute(
|
386
|
-
span.set_attribute(
|
387
|
-
span.set_attribute(
|
385
|
+
span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
|
386
|
+
span.set_attribute(SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS, output_tokens)
|
387
|
+
span.set_attribute(SemanticConvention.GEN_AI_USAGE_TOTAL_TOKENS, input_tokens + output_tokens)
|
388
388
|
|
389
389
|
span.set_status(Status(StatusCode.OK))
|
390
390
|
# Emit a single aggregated completion event.
|
391
391
|
if capture_message_content:
|
392
392
|
span.add_event(
|
393
|
-
name=
|
394
|
-
attributes={
|
393
|
+
name=SemanticConvention.GEN_AI_CONTENT_COMPLETION_EVENT,
|
394
|
+
attributes={SemanticConvention.GEN_AI_CONTENT_COMPLETION: llmresponse},
|
395
395
|
)
|
396
396
|
# Emit the rest of the events (choice and role-based events) as before.
|
397
397
|
n = kwargs.get('n', 1)
|
@@ -14,7 +14,7 @@ from openlit.instrumentation.anthropic.utils import (
|
|
14
14
|
process_chat_response,
|
15
15
|
process_streaming_chat_response,
|
16
16
|
)
|
17
|
-
from openlit.semcov import
|
17
|
+
from openlit.semcov import SemanticConvention
|
18
18
|
|
19
19
|
# Initialize logger for logging potential issues and operations
|
20
20
|
logger = logging.getLogger(__name__)
|
@@ -113,7 +113,7 @@ def messages(version, environment, application_name, tracer, event_provider,
|
|
113
113
|
server_address, server_port = set_server_address_and_port(instance, 'api.anthropic.com', 443)
|
114
114
|
request_model = kwargs.get('model', 'claude-3-5-sonnet-latest')
|
115
115
|
|
116
|
-
span_name = f'{
|
116
|
+
span_name = f'{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}'
|
117
117
|
|
118
118
|
# pylint: disable=no-else-return
|
119
119
|
if streaming:
|
@@ -14,7 +14,7 @@ from openlit.instrumentation.anthropic.utils import (
|
|
14
14
|
process_chat_response,
|
15
15
|
process_streaming_chat_response,
|
16
16
|
)
|
17
|
-
from openlit.semcov import
|
17
|
+
from openlit.semcov import SemanticConvention
|
18
18
|
|
19
19
|
# Initialize logger for logging potential issues and operations
|
20
20
|
logger = logging.getLogger(__name__)
|
@@ -113,7 +113,7 @@ def async_messages(version, environment, application_name, tracer, event_provide
|
|
113
113
|
server_address, server_port = set_server_address_and_port(instance, 'api.anthropic.com', 443)
|
114
114
|
request_model = kwargs.get('model', 'claude-3-5-sonnet-latest')
|
115
115
|
|
116
|
-
span_name = f'{
|
116
|
+
span_name = f'{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}'
|
117
117
|
|
118
118
|
# pylint: disable=no-else-return
|
119
119
|
if streaming:
|