openlit 1.34.10__py3-none-any.whl → 1.34.11__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 +23 -0
- openlit/instrumentation/groq/__init__.py +7 -9
- openlit/instrumentation/groq/async_groq.py +50 -374
- openlit/instrumentation/groq/groq.py +49 -373
- openlit/instrumentation/groq/utils.py +199 -0
- openlit/instrumentation/ollama/async_ollama.py +3 -2
- openlit/instrumentation/ollama/ollama.py +3 -2
- openlit/instrumentation/ollama/utils.py +10 -6
- openlit/instrumentation/premai/utils.py +3 -73
- openlit/instrumentation/reka/utils.py +3 -51
- {openlit-1.34.10.dist-info → openlit-1.34.11.dist-info}/METADATA +1 -1
- {openlit-1.34.10.dist-info → openlit-1.34.11.dist-info}/RECORD +14 -13
- {openlit-1.34.10.dist-info → openlit-1.34.11.dist-info}/LICENSE +0 -0
- {openlit-1.34.10.dist-info → openlit-1.34.11.dist-info}/WHEEL +0 -0
@@ -0,0 +1,199 @@
|
|
1
|
+
"""
|
2
|
+
Groq OpenTelemetry instrumentation utility functions
|
3
|
+
"""
|
4
|
+
import time
|
5
|
+
|
6
|
+
from opentelemetry.trace import Status, StatusCode
|
7
|
+
|
8
|
+
from openlit.__helpers import (
|
9
|
+
calculate_ttft,
|
10
|
+
response_as_dict,
|
11
|
+
calculate_tbt,
|
12
|
+
get_chat_model_cost,
|
13
|
+
common_span_attributes,
|
14
|
+
record_completion_metrics,
|
15
|
+
)
|
16
|
+
from openlit.semcov import SemanticConvention
|
17
|
+
|
18
|
+
def format_content(messages):
|
19
|
+
"""
|
20
|
+
Process a list of messages to extract content.
|
21
|
+
"""
|
22
|
+
|
23
|
+
formatted_messages = []
|
24
|
+
for message in messages:
|
25
|
+
role = message["role"]
|
26
|
+
content = message["content"]
|
27
|
+
|
28
|
+
if isinstance(content, list):
|
29
|
+
content_str = ", ".join(
|
30
|
+
f'{item["type"]}: {item["text"] if "text" in item else item["image_url"]}'
|
31
|
+
if "type" in item else f'text: {item["text"]}'
|
32
|
+
for item in content
|
33
|
+
)
|
34
|
+
formatted_messages.append(f"{role}: {content_str}")
|
35
|
+
else:
|
36
|
+
formatted_messages.append(f"{role}: {content}")
|
37
|
+
|
38
|
+
return "\n".join(formatted_messages)
|
39
|
+
|
40
|
+
def process_chunk(scope, chunk):
|
41
|
+
"""
|
42
|
+
Process a chunk of response data and update state.
|
43
|
+
"""
|
44
|
+
|
45
|
+
end_time = time.time()
|
46
|
+
# Record the timestamp for the current chunk
|
47
|
+
scope._timestamps.append(end_time)
|
48
|
+
|
49
|
+
if len(scope._timestamps) == 1:
|
50
|
+
# Calculate time to first chunk
|
51
|
+
scope._ttft = calculate_ttft(scope._timestamps, scope._start_time)
|
52
|
+
|
53
|
+
chunked = response_as_dict(chunk)
|
54
|
+
|
55
|
+
# Collect message IDs and aggregated response from events
|
56
|
+
if (len(chunked.get("choices", [])) > 0 and
|
57
|
+
"delta" in chunked.get("choices")[0] and
|
58
|
+
"content" in chunked.get("choices")[0].get("delta", {})):
|
59
|
+
|
60
|
+
content = chunked.get("choices")[0].get("delta").get("content")
|
61
|
+
if content:
|
62
|
+
scope._llmresponse += content
|
63
|
+
|
64
|
+
if chunked.get('x_groq') is not None:
|
65
|
+
if chunked.get('x_groq').get('usage') is not None:
|
66
|
+
scope._input_tokens = chunked.get('x_groq').get('usage').get('prompt_tokens')
|
67
|
+
scope._output_tokens = chunked.get('x_groq').get('usage').get('completion_tokens')
|
68
|
+
scope._response_id = chunked.get('x_groq').get('id')
|
69
|
+
scope._response_model = chunked.get('x_groq').get('model')
|
70
|
+
scope._finish_reason = chunked.get('choices', [{}])[0].get('finish_reason')
|
71
|
+
scope._system_fingerprint = chunked.get('x_groq').get('system_fingerprint')
|
72
|
+
scope._end_time = time.time()
|
73
|
+
|
74
|
+
|
75
|
+
def common_chat_logic(scope, pricing_info, environment, application_name, metrics,
|
76
|
+
capture_message_content, disable_metrics, version, is_stream):
|
77
|
+
"""
|
78
|
+
Process chat request and generate Telemetry
|
79
|
+
"""
|
80
|
+
|
81
|
+
if len(scope._timestamps) > 1:
|
82
|
+
scope._tbt = calculate_tbt(scope._timestamps)
|
83
|
+
|
84
|
+
prompt = format_content(scope._kwargs.get("messages", []))
|
85
|
+
request_model = scope._kwargs.get("model", "mixtral-8x7b-32768")
|
86
|
+
|
87
|
+
cost = get_chat_model_cost(request_model, pricing_info, scope._input_tokens, scope._output_tokens)
|
88
|
+
|
89
|
+
# Common Span Attributes
|
90
|
+
common_span_attributes(scope,
|
91
|
+
SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT, SemanticConvention.GEN_AI_SYSTEM_GROQ,
|
92
|
+
scope._server_address, scope._server_port, request_model, scope._response_model,
|
93
|
+
environment, application_name, is_stream, scope._tbt, scope._ttft, version)
|
94
|
+
|
95
|
+
# Span Attributes for Request parameters
|
96
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_SEED, scope._kwargs.get("seed", ""))
|
97
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_FREQUENCY_PENALTY, scope._kwargs.get("frequency_penalty", 0.0))
|
98
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MAX_TOKENS, scope._kwargs.get("max_completion_tokens", -1))
|
99
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_PRESENCE_PENALTY, scope._kwargs.get("presence_penalty", 0.0))
|
100
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_STOP_SEQUENCES, scope._kwargs.get("stop", []))
|
101
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TEMPERATURE, scope._kwargs.get("temperature", 1.0))
|
102
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_TOP_P, scope._kwargs.get("top_p", 1.0))
|
103
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_USER, scope._kwargs.get("user", ""))
|
104
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_SERVICE_TIER, scope._kwargs.get("service_tier", "on_demand"))
|
105
|
+
|
106
|
+
# Span Attributes for Response parameters
|
107
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_ID, scope._response_id)
|
108
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_FINISH_REASON, [scope._finish_reason])
|
109
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_SYSTEM_FINGERPRINT, scope._system_fingerprint)
|
110
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_OUTPUT_TYPE, "text" if isinstance(scope._llmresponse, str) else "json")
|
111
|
+
|
112
|
+
# Span Attributes for Cost and Tokens
|
113
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_INPUT_TOKENS, scope._input_tokens)
|
114
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_OUTPUT_TOKENS, scope._output_tokens)
|
115
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_CLIENT_TOKEN_USAGE, scope._input_tokens + scope._output_tokens)
|
116
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
|
117
|
+
|
118
|
+
# Span Attributes for Tools
|
119
|
+
if scope._tools:
|
120
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_NAME, scope._tools.get("function", {}).get("name", ""))
|
121
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_CALL_ID, str(scope._tools.get("id", "")))
|
122
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_ARGS, str(scope._tools.get("function", {}).get("arguments", "")))
|
123
|
+
|
124
|
+
# Span Attributes for Content
|
125
|
+
if capture_message_content:
|
126
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_PROMPT, prompt)
|
127
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_CONTENT_COMPLETION, scope._llmresponse)
|
128
|
+
|
129
|
+
# To be removed one the change to span_attributes (from span events) is complete
|
130
|
+
scope._span.add_event(
|
131
|
+
name=SemanticConvention.GEN_AI_CONTENT_PROMPT_EVENT,
|
132
|
+
attributes={
|
133
|
+
SemanticConvention.GEN_AI_CONTENT_PROMPT: prompt,
|
134
|
+
},
|
135
|
+
)
|
136
|
+
scope._span.add_event(
|
137
|
+
name=SemanticConvention.GEN_AI_CONTENT_COMPLETION_EVENT,
|
138
|
+
attributes={
|
139
|
+
SemanticConvention.GEN_AI_CONTENT_COMPLETION: scope._llmresponse,
|
140
|
+
},
|
141
|
+
)
|
142
|
+
|
143
|
+
scope._span.set_status(Status(StatusCode.OK))
|
144
|
+
|
145
|
+
# Metrics
|
146
|
+
if not disable_metrics:
|
147
|
+
record_completion_metrics(metrics, SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT, SemanticConvention.GEN_AI_SYSTEM_GROQ,
|
148
|
+
scope._server_address, scope._server_port, request_model, scope._response_model, environment,
|
149
|
+
application_name, scope._start_time, scope._end_time, scope._input_tokens, scope._output_tokens,
|
150
|
+
cost, scope._tbt, scope._ttft)
|
151
|
+
|
152
|
+
def process_streaming_chat_response(scope, pricing_info, environment, application_name, metrics,
|
153
|
+
capture_message_content=False, disable_metrics=False, version=""):
|
154
|
+
"""
|
155
|
+
Process chat request and generate Telemetry
|
156
|
+
"""
|
157
|
+
|
158
|
+
common_chat_logic(scope, pricing_info, environment, application_name, metrics,
|
159
|
+
capture_message_content, disable_metrics, version, is_stream=True)
|
160
|
+
|
161
|
+
def process_chat_response(response, request_model, pricing_info, server_port, server_address,
|
162
|
+
environment, application_name, metrics, start_time, span, capture_message_content=False,
|
163
|
+
disable_metrics=False, version="1.0.0", **kwargs):
|
164
|
+
"""
|
165
|
+
Process chat request and generate Telemetry
|
166
|
+
"""
|
167
|
+
|
168
|
+
# Create scope object
|
169
|
+
scope = type("GenericScope", (), {})()
|
170
|
+
response_dict = response_as_dict(response)
|
171
|
+
|
172
|
+
scope._start_time = start_time
|
173
|
+
scope._end_time = time.time()
|
174
|
+
scope._span = span
|
175
|
+
scope._llmresponse = " ".join(
|
176
|
+
(choice.get("message", {}).get("content") or "")
|
177
|
+
for choice in response_dict.get("choices", [])
|
178
|
+
)
|
179
|
+
scope._response_id = response_dict.get("id")
|
180
|
+
scope._response_model = response_dict.get("model")
|
181
|
+
scope._input_tokens = response_dict.get("usage", {}).get("prompt_tokens", 0)
|
182
|
+
scope._output_tokens = response_dict.get("usage", {}).get("completion_tokens", 0)
|
183
|
+
scope._timestamps = []
|
184
|
+
scope._ttft, scope._tbt = scope._end_time - scope._start_time, 0
|
185
|
+
scope._server_address, scope._server_port = server_address, server_port
|
186
|
+
scope._kwargs = kwargs
|
187
|
+
scope._system_fingerprint = response_dict.get("system_fingerprint")
|
188
|
+
scope._finish_reason = str(response_dict.get("choices", [])[0].get("finish_reason", ""))
|
189
|
+
|
190
|
+
# Handle tool calls
|
191
|
+
if scope._kwargs.get("tools"):
|
192
|
+
scope._tools = response_dict.get("choices", [{}])[0].get("message", {}).get("tool_calls")
|
193
|
+
else:
|
194
|
+
scope._tools = None
|
195
|
+
|
196
|
+
common_chat_logic(scope, pricing_info, environment, application_name, metrics,
|
197
|
+
capture_message_content, disable_metrics, version, is_stream=False)
|
198
|
+
|
199
|
+
return response
|
@@ -42,7 +42,7 @@ def async_chat(version, environment, application_name,
|
|
42
42
|
self._llmresponse = ""
|
43
43
|
self._response_model = ""
|
44
44
|
self._finish_reason = ""
|
45
|
-
self.
|
45
|
+
self._tools = []
|
46
46
|
self._input_tokens = 0
|
47
47
|
self._output_tokens = 0
|
48
48
|
self._response_role = ""
|
@@ -102,7 +102,8 @@ def async_chat(version, environment, application_name,
|
|
102
102
|
streaming = kwargs.get("stream", False)
|
103
103
|
|
104
104
|
server_address, server_port = set_server_address_and_port(instance, "127.0.0.1", 11434)
|
105
|
-
|
105
|
+
json_body = kwargs.get("json", {}) or {}
|
106
|
+
request_model = json_body.get("model") or kwargs.get("model")
|
106
107
|
|
107
108
|
span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}"
|
108
109
|
|
@@ -42,7 +42,7 @@ def chat(version, environment, application_name,
|
|
42
42
|
self._llmresponse = ""
|
43
43
|
self._response_model = ""
|
44
44
|
self._finish_reason = ""
|
45
|
-
self.
|
45
|
+
self._tools = []
|
46
46
|
self._input_tokens = 0
|
47
47
|
self._output_tokens = 0
|
48
48
|
self._response_role = ""
|
@@ -102,7 +102,8 @@ def chat(version, environment, application_name,
|
|
102
102
|
streaming = kwargs.get("stream", False)
|
103
103
|
|
104
104
|
server_address, server_port = set_server_address_and_port(instance, "127.0.0.1", 11434)
|
105
|
-
|
105
|
+
json_body = kwargs.get("json", {}) or {}
|
106
|
+
request_model = json_body.get("model") or kwargs.get("model")
|
106
107
|
|
107
108
|
span_name = f"{SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT} {request_model}"
|
108
109
|
|
@@ -57,7 +57,7 @@ def process_chunk(self, chunk):
|
|
57
57
|
self._llmresponse += chunked.get("message", {}).get("content", "")
|
58
58
|
|
59
59
|
if chunked.get("message", {}).get("tool_calls"):
|
60
|
-
self.
|
60
|
+
self._tools = chunked["message"]["tool_calls"]
|
61
61
|
|
62
62
|
if chunked.get("eval_count"):
|
63
63
|
self._response_role = chunked.get("message", {}).get("role", "")
|
@@ -138,10 +138,10 @@ def common_chat_logic(scope, gen_ai_endpoint, pricing_info, environment, applica
|
|
138
138
|
scope._span.set_attribute(SemanticConvention.GEN_AI_USAGE_COST, cost)
|
139
139
|
|
140
140
|
# Span Attributes for Tools
|
141
|
-
if
|
142
|
-
|
143
|
-
scope._span.set_attribute(SemanticConvention.
|
144
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_ARGS, str(
|
141
|
+
if scope._tools is not None:
|
142
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_NAME, scope._tools.get("function","")).get("name","")
|
143
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_CALL_ID, str(scope._tools.get("id","")))
|
144
|
+
scope._span.set_attribute(SemanticConvention.GEN_AI_TOOL_ARGS, str(scope._tools.get("function","").get("arguments","")))
|
145
145
|
|
146
146
|
# Span Attributes for Content
|
147
147
|
if capture_message_content:
|
@@ -244,7 +244,11 @@ def process_chat_response(response, gen_ai_endpoint, pricing_info, server_port,
|
|
244
244
|
scope._tbt = 0
|
245
245
|
scope._server_address, scope._server_port = server_address, server_port
|
246
246
|
scope._kwargs = kwargs
|
247
|
-
|
247
|
+
|
248
|
+
if scope._kwargs.get("tools"):
|
249
|
+
scope._tools = response_dict.get("choices")[0].get("message").get("tool_calls")
|
250
|
+
else:
|
251
|
+
scope._tools = None
|
248
252
|
|
249
253
|
common_chat_logic(scope, gen_ai_endpoint, pricing_info, environment, application_name, metrics,
|
250
254
|
capture_message_content, disable_metrics, version)
|
@@ -3,7 +3,6 @@ PremAI OpenTelemetry instrumentation utility functions
|
|
3
3
|
"""
|
4
4
|
import time
|
5
5
|
|
6
|
-
from opentelemetry.sdk.resources import SERVICE_NAME, TELEMETRY_SDK_NAME, DEPLOYMENT_ENVIRONMENT
|
7
6
|
from opentelemetry.trace import Status, StatusCode
|
8
7
|
|
9
8
|
from openlit.__helpers import (
|
@@ -13,7 +12,9 @@ from openlit.__helpers import (
|
|
13
12
|
get_chat_model_cost,
|
14
13
|
get_embed_model_cost,
|
15
14
|
general_tokens,
|
16
|
-
|
15
|
+
common_span_attributes,
|
16
|
+
record_completion_metrics,
|
17
|
+
record_embedding_metrics,
|
17
18
|
)
|
18
19
|
from openlit.semcov import SemanticConvention
|
19
20
|
|
@@ -66,77 +67,6 @@ def process_chunk(scope, chunk):
|
|
66
67
|
scope._response_model = chunked.get("model")
|
67
68
|
scope._end_time = time.time()
|
68
69
|
|
69
|
-
def common_span_attributes(scope, gen_ai_operation, gen_ai_system, server_address, server_port,
|
70
|
-
request_model, response_model, environment, application_name, is_stream, tbt, ttft, version):
|
71
|
-
"""
|
72
|
-
Set common span attributes for both chat and RAG operations.
|
73
|
-
"""
|
74
|
-
|
75
|
-
scope._span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
|
76
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_OPERATION, gen_ai_operation)
|
77
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_SYSTEM, gen_ai_system)
|
78
|
-
scope._span.set_attribute(SemanticConvention.SERVER_ADDRESS, server_address)
|
79
|
-
scope._span.set_attribute(SemanticConvention.SERVER_PORT, server_port)
|
80
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL, request_model)
|
81
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_MODEL, response_model)
|
82
|
-
scope._span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
|
83
|
-
scope._span.set_attribute(SERVICE_NAME, application_name)
|
84
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_IS_STREAM, is_stream)
|
85
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_SERVER_TBT, tbt)
|
86
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_SERVER_TTFT, ttft)
|
87
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_SDK_VERSION, version)
|
88
|
-
|
89
|
-
def record_completion_metrics(metrics, gen_ai_operation, gen_ai_system, server_address, server_port,
|
90
|
-
request_model, response_model, environment, application_name, start_time, end_time,
|
91
|
-
input_tokens, output_tokens, cost, tbt=None, ttft=None):
|
92
|
-
"""
|
93
|
-
Record completion-specific metrics for the operation.
|
94
|
-
"""
|
95
|
-
|
96
|
-
attributes = create_metrics_attributes(
|
97
|
-
operation=gen_ai_operation,
|
98
|
-
system=gen_ai_system,
|
99
|
-
server_address=server_address,
|
100
|
-
server_port=server_port,
|
101
|
-
request_model=request_model,
|
102
|
-
response_model=response_model,
|
103
|
-
service_name=application_name,
|
104
|
-
deployment_environment=environment,
|
105
|
-
)
|
106
|
-
metrics["genai_client_operation_duration"].record(end_time - start_time, attributes)
|
107
|
-
metrics["genai_requests"].add(1, attributes)
|
108
|
-
metrics["genai_prompt_tokens"].add(input_tokens, attributes)
|
109
|
-
metrics["genai_completion_tokens"].add(output_tokens, attributes)
|
110
|
-
metrics["genai_client_usage_tokens"].record(input_tokens + output_tokens, attributes)
|
111
|
-
metrics["genai_cost"].record(cost, attributes)
|
112
|
-
if tbt is not None:
|
113
|
-
metrics["genai_server_tbt"].record(tbt, attributes)
|
114
|
-
if ttft is not None:
|
115
|
-
metrics["genai_server_ttft"].record(ttft, attributes)
|
116
|
-
|
117
|
-
def record_embedding_metrics(metrics, gen_ai_operation, gen_ai_system, server_address, server_port,
|
118
|
-
request_model, response_model, environment, application_name, start_time, end_time,
|
119
|
-
input_tokens, cost):
|
120
|
-
"""
|
121
|
-
Record embedding-specific metrics for the operation.
|
122
|
-
"""
|
123
|
-
|
124
|
-
attributes = create_metrics_attributes(
|
125
|
-
operation=gen_ai_operation,
|
126
|
-
system=gen_ai_system,
|
127
|
-
server_address=server_address,
|
128
|
-
server_port=server_port,
|
129
|
-
request_model=request_model,
|
130
|
-
response_model=response_model,
|
131
|
-
service_name=application_name,
|
132
|
-
deployment_environment=environment,
|
133
|
-
)
|
134
|
-
metrics["genai_client_usage_tokens"].record(input_tokens, attributes)
|
135
|
-
metrics["genai_client_operation_duration"].record(end_time - start_time, attributes)
|
136
|
-
metrics["genai_requests"].add(1, attributes)
|
137
|
-
metrics["genai_prompt_tokens"].add(input_tokens, attributes)
|
138
|
-
metrics["genai_cost"].record(cost, attributes)
|
139
|
-
|
140
70
|
def common_chat_logic(scope, pricing_info, environment, application_name, metrics,
|
141
71
|
capture_message_content, disable_metrics, version, is_stream):
|
142
72
|
"""
|
@@ -3,14 +3,14 @@ Reka OpenTelemetry instrumentation utility functions
|
|
3
3
|
"""
|
4
4
|
import time
|
5
5
|
|
6
|
-
from opentelemetry.sdk.resources import SERVICE_NAME, TELEMETRY_SDK_NAME, DEPLOYMENT_ENVIRONMENT
|
7
6
|
from opentelemetry.trace import Status, StatusCode
|
8
7
|
|
9
8
|
from openlit.__helpers import (
|
10
9
|
response_as_dict,
|
11
10
|
calculate_tbt,
|
12
11
|
get_chat_model_cost,
|
13
|
-
|
12
|
+
common_span_attributes,
|
13
|
+
record_completion_metrics,
|
14
14
|
)
|
15
15
|
from openlit.semcov import SemanticConvention
|
16
16
|
|
@@ -36,54 +36,6 @@ def format_content(messages):
|
|
36
36
|
|
37
37
|
return "\n".join(formatted_messages)
|
38
38
|
|
39
|
-
def common_span_attributes(scope, gen_ai_operation, gen_ai_system, server_address, server_port,
|
40
|
-
request_model, response_model, environment, application_name, is_stream, tbt, ttft, version):
|
41
|
-
"""
|
42
|
-
Set common span attributes for both chat and RAG operations.
|
43
|
-
"""
|
44
|
-
|
45
|
-
scope._span.set_attribute(TELEMETRY_SDK_NAME, "openlit")
|
46
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_OPERATION, gen_ai_operation)
|
47
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_SYSTEM, gen_ai_system)
|
48
|
-
scope._span.set_attribute(SemanticConvention.SERVER_ADDRESS, server_address)
|
49
|
-
scope._span.set_attribute(SemanticConvention.SERVER_PORT, server_port)
|
50
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_MODEL, request_model)
|
51
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_RESPONSE_MODEL, response_model)
|
52
|
-
scope._span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
|
53
|
-
scope._span.set_attribute(SERVICE_NAME, application_name)
|
54
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_REQUEST_IS_STREAM, is_stream)
|
55
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_SERVER_TBT, tbt)
|
56
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_SERVER_TTFT, ttft)
|
57
|
-
scope._span.set_attribute(SemanticConvention.GEN_AI_SDK_VERSION, version)
|
58
|
-
|
59
|
-
def record_common_metrics(metrics, gen_ai_operation, gen_ai_system, server_address, server_port,
|
60
|
-
request_model, response_model, environment, application_name, start_time, end_time,
|
61
|
-
input_tokens, output_tokens, cost, tbt=None, ttft=None):
|
62
|
-
"""
|
63
|
-
Record common metrics for the operation.
|
64
|
-
"""
|
65
|
-
|
66
|
-
attributes = create_metrics_attributes(
|
67
|
-
operation=gen_ai_operation,
|
68
|
-
system=gen_ai_system,
|
69
|
-
server_address=server_address,
|
70
|
-
server_port=server_port,
|
71
|
-
request_model=request_model,
|
72
|
-
response_model=response_model,
|
73
|
-
service_name=application_name,
|
74
|
-
deployment_environment=environment,
|
75
|
-
)
|
76
|
-
metrics["genai_client_operation_duration"].record(end_time - start_time, attributes)
|
77
|
-
metrics["genai_requests"].add(1, attributes)
|
78
|
-
metrics["genai_prompt_tokens"].add(input_tokens, attributes)
|
79
|
-
metrics["genai_completion_tokens"].add(output_tokens, attributes)
|
80
|
-
metrics["genai_client_usage_tokens"].record(input_tokens + output_tokens, attributes)
|
81
|
-
metrics["genai_cost"].record(cost, attributes)
|
82
|
-
if tbt is not None:
|
83
|
-
metrics["genai_server_tbt"].record(tbt, attributes)
|
84
|
-
if ttft is not None:
|
85
|
-
metrics["genai_server_ttft"].record(ttft, attributes)
|
86
|
-
|
87
39
|
def common_chat_logic(scope, pricing_info, environment, application_name, metrics,
|
88
40
|
capture_message_content, disable_metrics, version, is_stream):
|
89
41
|
"""
|
@@ -151,7 +103,7 @@ def common_chat_logic(scope, pricing_info, environment, application_name, metric
|
|
151
103
|
|
152
104
|
# Metrics
|
153
105
|
if not disable_metrics:
|
154
|
-
|
106
|
+
record_completion_metrics(metrics, SemanticConvention.GEN_AI_OPERATION_TYPE_CHAT, SemanticConvention.GEN_AI_SYSTEM_REKAAI,
|
155
107
|
scope._server_address, scope._server_port, request_model, scope._response_model, environment,
|
156
108
|
application_name, scope._start_time, scope._end_time, scope._input_tokens, scope._output_tokens,
|
157
109
|
cost, scope._tbt, scope._ttft)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: openlit
|
3
|
-
Version: 1.34.
|
3
|
+
Version: 1.34.11
|
4
4
|
Summary: OpenTelemetry-native Auto instrumentation library for monitoring LLM Applications and GPUs, facilitating the integration of observability into your GenAI-driven projects
|
5
5
|
License: Apache-2.0
|
6
6
|
Keywords: OpenTelemetry,otel,otlp,llm,tracing,openai,anthropic,claude,cohere,llm monitoring,observability,monitoring,gpt,Generative AI,chatGPT,gpu
|
@@ -1,4 +1,4 @@
|
|
1
|
-
openlit/__helpers.py,sha256=
|
1
|
+
openlit/__helpers.py,sha256=gIFD6pDsj_zd4_D936aRptUq-TKUQ-0GgJBf6PoEDlo,14883
|
2
2
|
openlit/__init__.py,sha256=ris6-GY0ePSbK_jvawHTXymGClVF7yeKdIT95IRBl18,24086
|
3
3
|
openlit/evals/__init__.py,sha256=nJe99nuLo1b5rf7pt9U9BCdSDedzbVi2Fj96cgl7msM,380
|
4
4
|
openlit/evals/all.py,sha256=oWrue3PotE-rB5WePG3MRYSA-ro6WivkclSHjYlAqGs,7154
|
@@ -66,9 +66,10 @@ openlit/instrumentation/gpt4all/__init__.py,sha256=kXciJbQMZYnTeAYLCjriVYXV7XzUU
|
|
66
66
|
openlit/instrumentation/gpt4all/gpt4all.py,sha256=6VkJbaPIDv5sbFXFiadH4IB0KljljnOZ1HaGAPuyp_E,6704
|
67
67
|
openlit/instrumentation/gpt4all/utils.py,sha256=clyoIy1_ib-1_keQFMvyzTOcbWHeWPRpDhV-w2CtIAU,12470
|
68
68
|
openlit/instrumentation/gpu/__init__.py,sha256=QQCFVEbRfdeTjmdFe-UeEiy19vEEWSIBpj2B1wYGhUs,11036
|
69
|
-
openlit/instrumentation/groq/__init__.py,sha256=
|
70
|
-
openlit/instrumentation/groq/async_groq.py,sha256=
|
71
|
-
openlit/instrumentation/groq/groq.py,sha256=
|
69
|
+
openlit/instrumentation/groq/__init__.py,sha256=MEcks6t-YqTe4hZXrQ6uGI60vb3OY84d3XjHH_emAyM,1739
|
70
|
+
openlit/instrumentation/groq/async_groq.py,sha256=hp3AN8B98cUbX4C0GksTbNb6kpg31FJUlhW32Wo8CnI,5113
|
71
|
+
openlit/instrumentation/groq/groq.py,sha256=XfJakQCfEszvVJxzpemYBIVE73b5WVj8bAlDaeVKBMU,4994
|
72
|
+
openlit/instrumentation/groq/utils.py,sha256=0ttCMcKmyDrSnmQtM20U5Yo6OllUPW5iBNBE5qW0jGk,9072
|
72
73
|
openlit/instrumentation/haystack/__init__.py,sha256=jZPAXRilKTD1vww_4_K4jhYWNrMXngcs5pI29NTnFvI,1788
|
73
74
|
openlit/instrumentation/haystack/haystack.py,sha256=kPkuCJDrccNgAg3yDAHbvEytzyfMOee_LDBhzrcfpkc,3927
|
74
75
|
openlit/instrumentation/julep/__init__.py,sha256=g-hwXjvXAb5IDs5DR_P8rKsnD4beB9tupAzuuviQT3k,3216
|
@@ -95,9 +96,9 @@ openlit/instrumentation/multion/__init__.py,sha256=Wr3lcDyG_YbOLkCUzBFhraAedF6E1
|
|
95
96
|
openlit/instrumentation/multion/async_multion.py,sha256=XutZnayCJOZ_NA9bvE1NUoej41KOGR7FRn2tpoGKMEU,6092
|
96
97
|
openlit/instrumentation/multion/multion.py,sha256=-WqRAcu5qiEMY9XDmlJTQHuQiWfdwms9JDn127QCNb8,6074
|
97
98
|
openlit/instrumentation/ollama/__init__.py,sha256=WxjqjuR8ovMU5dR08OELNqClbuM7ns4hDRiwWg9NXJk,3587
|
98
|
-
openlit/instrumentation/ollama/async_ollama.py,sha256=
|
99
|
-
openlit/instrumentation/ollama/ollama.py,sha256=
|
100
|
-
openlit/instrumentation/ollama/utils.py,sha256=
|
99
|
+
openlit/instrumentation/ollama/async_ollama.py,sha256=ORXwem8lgSrhOcci55NkChIK9SNc3IYIpLjF_ogsGA8,6666
|
100
|
+
openlit/instrumentation/ollama/ollama.py,sha256=8mvrWfU1c5h1L7lxWo47YBJ7g2u7QZmSZuuP0URtTDo,6538
|
101
|
+
openlit/instrumentation/ollama/utils.py,sha256=TIE3_ur2U-iyCclna7TzwjDIFC9PZjRnZqNDV6NfG-0,11958
|
101
102
|
openlit/instrumentation/openai/__init__.py,sha256=y9Ox5aYWTb2nAa_d0ic3Mkv4wEKmUGqslW9nHKg6NnY,6320
|
102
103
|
openlit/instrumentation/openai/async_openai.py,sha256=JyA8MDxWCM38Te6mJzBdfonRgIIlo2ziLn7HOmzqxxo,81398
|
103
104
|
openlit/instrumentation/openai/openai.py,sha256=5fgRyK5dUN2zUdrN0vBSZFnSEAXf2dKS0qnq_85-mQE,81175
|
@@ -109,7 +110,7 @@ openlit/instrumentation/pinecone/__init__.py,sha256=0guSEPmObaZiOF8yHExpOGY-qW_e
|
|
109
110
|
openlit/instrumentation/pinecone/pinecone.py,sha256=7hVUlC0HOj0yQyvLasfdb6kS46hRJQdoSRzZQ4ixIkk,8850
|
110
111
|
openlit/instrumentation/premai/__init__.py,sha256=3YlqyV-eNA_4aVUHDVUQUvGJRW8iVVcRtREw91yhbyw,1728
|
111
112
|
openlit/instrumentation/premai/premai.py,sha256=rWRqfoIZUbTz-M7zgC2Z92gTVv9fCj1Z4iJcsG86YeI,6438
|
112
|
-
openlit/instrumentation/premai/utils.py,sha256=
|
113
|
+
openlit/instrumentation/premai/utils.py,sha256=K7EKGRDDh1X3OznG4z8H506zzFOHN6MH3oqtxM5eUyM,11409
|
113
114
|
openlit/instrumentation/pydantic_ai/__init__.py,sha256=mq52QanFI4xDx6JK-qW5yzhFPXwznJqIYsuxRoBA2Xg,2023
|
114
115
|
openlit/instrumentation/pydantic_ai/pydantic_ai.py,sha256=2F2hrowGqcPjTDLG9IeLY8OO-lXZKhLSU93XtZ3tt5A,1868
|
115
116
|
openlit/instrumentation/pydantic_ai/utils.py,sha256=b0TqhSDnRqkPdM_qsOgMuXT3lwTvHzMYpaBv2qibiVo,4307
|
@@ -119,7 +120,7 @@ openlit/instrumentation/qdrant/qdrant.py,sha256=pafjlAzMPzYLRYFfTtWXsLKYVQls-grk
|
|
119
120
|
openlit/instrumentation/reka/__init__.py,sha256=wI5KUYyTAD8ni4E98uziy9WPqoQqlzybDXanFOqDan0,1720
|
120
121
|
openlit/instrumentation/reka/async_reka.py,sha256=CZk5rr7njThDkmrauRAJmNtMBgsLarTbQ54raPQb92A,1909
|
121
122
|
openlit/instrumentation/reka/reka.py,sha256=wou7vVdN_1Y5UZd4tpkLpTPAtgmAl6gmh_onLn4k4GE,1908
|
122
|
-
openlit/instrumentation/reka/utils.py,sha256=
|
123
|
+
openlit/instrumentation/reka/utils.py,sha256=qt1ZIsWkuFGX6iPMiUJ993dh1njvc81QJECD3BnSOpE,6632
|
123
124
|
openlit/instrumentation/together/__init__.py,sha256=0UmUqQtppyK3oopb4lTjX2LITgVCR8VtH46IAV1rpA8,2484
|
124
125
|
openlit/instrumentation/together/async_together.py,sha256=0-h5fKw6rIwN_fvWVpGuvVqizIuM9xFCzz8Z4oGgOj0,6822
|
125
126
|
openlit/instrumentation/together/together.py,sha256=nY6mzHmHgoMbbnB_9eL0EBQjP0ltJVdkQj4pbamHAj0,6723
|
@@ -137,7 +138,7 @@ openlit/otel/events.py,sha256=VrMjTpvnLtYRBHCiFwJojTQqqNpRCxoD4yJYeQrtPsk,3560
|
|
137
138
|
openlit/otel/metrics.py,sha256=GM2PDloBGRhBTkHHkYaqmOwIAQkY124ZhW4sEqW1Fgk,7086
|
138
139
|
openlit/otel/tracing.py,sha256=tjV2bEbEDPUB1Z46gE-UsJsb04sRdFrfbhIDkxViZc0,3103
|
139
140
|
openlit/semcov/__init__.py,sha256=ptyo37PY-FHDx_PShEvbdns71cD4YvvXw15bCRXKCKM,13461
|
140
|
-
openlit-1.34.
|
141
|
-
openlit-1.34.
|
142
|
-
openlit-1.34.
|
143
|
-
openlit-1.34.
|
141
|
+
openlit-1.34.11.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
142
|
+
openlit-1.34.11.dist-info/METADATA,sha256=uupRffQvhiozgD4kGsKu_uQ3Sc7hrYyfX32l3EmiKSk,23470
|
143
|
+
openlit-1.34.11.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
144
|
+
openlit-1.34.11.dist-info/RECORD,,
|
File without changes
|
File without changes
|