openlit 1.33.17__py3-none-any.whl → 1.33.19__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.
@@ -0,0 +1,252 @@
1
+ """
2
+ AWS Bedrock OpenTelemetry instrumentation utility functions
3
+ """
4
+ import time
5
+
6
+ from opentelemetry.sdk.resources import SERVICE_NAME, TELEMETRY_SDK_NAME, DEPLOYMENT_ENVIRONMENT
7
+ from opentelemetry.trace import Status, StatusCode
8
+
9
+ from openlit.__helpers import (
10
+ calculate_ttft,
11
+ response_as_dict,
12
+ calculate_tbt,
13
+ extract_and_format_input,
14
+ get_chat_model_cost,
15
+ create_metrics_attributes,
16
+ otel_event,
17
+ concatenate_all_contents
18
+ )
19
+ from openlit.semcov import SemanticConvetion
20
+
21
+ def process_chunk(self, chunk):
22
+ """
23
+ Process a chunk of response data and update state.
24
+ """
25
+
26
+ end_time = time.time()
27
+ # Record the timestamp for the current chunk
28
+ self._timestamps.append(end_time)
29
+
30
+ if len(self._timestamps) == 1:
31
+ # Calculate time to first chunk
32
+ self._ttft = calculate_ttft(self._timestamps, self._start_time)
33
+
34
+ chunked = response_as_dict(chunk)
35
+
36
+ # Collect message IDs and input token from events
37
+ if chunked.get('type') == 'message_start':
38
+ self._response_id = chunked.get('message').get('id')
39
+ self._input_tokens = chunked.get('message').get('usage').get('input_tokens')
40
+ self._response_model = chunked.get('message').get('model')
41
+ self._response_role = chunked.get('message').get('role')
42
+
43
+ # Collect message IDs and aggregated response from events
44
+ if chunked.get('type') == 'content_block_delta':
45
+ if chunked.get('delta').get('text'):
46
+ self._llmresponse += chunked.get('delta').get('text')
47
+ elif chunked.get('delta').get('partial_json'):
48
+ self._tool_arguments += chunked.get('delta').get('partial_json')
49
+
50
+ if chunked.get('type') == 'content_block_start':
51
+ if chunked.get('content_block').get('id'):
52
+ self._tool_id = chunked.get('content_block').get('id')
53
+ if chunked.get('content_block').get('name'):
54
+ self._tool_name = chunked.get('content_block').get('name')
55
+
56
+ # Collect output tokens and stop reason from events
57
+ if chunked.get('type') == 'message_delta':
58
+ self._output_tokens = chunked.get('usage').get('output_tokens')
59
+ self._finish_reason = chunked.get('delta').get('stop_reason')
60
+
61
+ def common_chat_logic(scope, pricing_info, environment, application_name, metrics,
62
+ event_provider, capture_message_content, disable_metrics, version, llm_config, is_stream):
63
+ """
64
+ Process chat request and generate Telemetry
65
+ """
66
+
67
+ scope._end_time = time.time()
68
+ if len(scope._timestamps) > 1:
69
+ scope._tbt = calculate_tbt(scope._timestamps)
70
+
71
+ formatted_messages = extract_and_format_input(scope._kwargs.get('messages', ''))
72
+ print(formatted_messages)
73
+ request_model = scope._kwargs.get('model', 'claude-3-opus-20240229')
74
+
75
+ cost = get_chat_model_cost(request_model, pricing_info, scope._input_tokens, scope._output_tokens)
76
+
77
+ # Set Span attributes (OTel Semconv)
78
+ scope._span.set_attribute(TELEMETRY_SDK_NAME, 'openlit')
79
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_OPERATION, SemanticConvetion.GEN_AI_OPERATION_TYPE_CHAT)
80
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_SYSTEM, SemanticConvetion.GEN_AI_SYSTEM_AWS_BEDROCK)
81
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_REQUEST_MODEL, request_model)
82
+ scope._span.set_attribute(SemanticConvetion.SERVER_PORT, scope._server_port)
83
+
84
+ # List of attributes and their config keys
85
+ attributes = [
86
+ (SemanticConvetion.GEN_AI_REQUEST_FREQUENCY_PENALTY, 'frequencyPenalty'),
87
+ (SemanticConvetion.GEN_AI_REQUEST_MAX_TOKENS, 'maxTokens'),
88
+ (SemanticConvetion.GEN_AI_REQUEST_PRESENCE_PENALTY, 'presencePenalty'),
89
+ (SemanticConvetion.GEN_AI_REQUEST_STOP_SEQUENCES, 'stopSequences'),
90
+ (SemanticConvetion.GEN_AI_REQUEST_TEMPERATURE, 'temperature'),
91
+ (SemanticConvetion.GEN_AI_REQUEST_TOP_P, 'topP'),
92
+ (SemanticConvetion.GEN_AI_REQUEST_TOP_K, 'topK'),
93
+ ]
94
+
95
+ # Set each attribute if the corresponding value exists and is not None
96
+ for attribute, key in attributes:
97
+ value = llm_config.get(key)
98
+ if value is not None:
99
+ scope._span.set_attribute(attribute, value)
100
+
101
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_RESPONSE_FINISH_REASON, [scope._finish_reason])
102
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_RESPONSE_ID, scope._response_id)
103
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_RESPONSE_MODEL, scope._response_model)
104
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_USAGE_INPUT_TOKENS, scope._input_tokens)
105
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_USAGE_OUTPUT_TOKENS, scope._output_tokens)
106
+ scope._span.set_attribute(SemanticConvetion.SERVER_ADDRESS, scope._server_address)
107
+
108
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_OUTPUT_TYPE,
109
+ 'text' if isinstance(scope._llmresponse, str) else 'json')
110
+
111
+ scope._span.set_attribute(DEPLOYMENT_ENVIRONMENT, environment)
112
+ scope._span.set_attribute(SERVICE_NAME, application_name)
113
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_REQUEST_IS_STREAM, is_stream)
114
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_CLIENT_TOKEN_USAGE, scope._input_tokens + scope._output_tokens)
115
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_USAGE_COST, cost)
116
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_SERVER_TBT, scope._tbt)
117
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_SERVER_TTFT, scope._ttft)
118
+ scope._span.set_attribute(SemanticConvetion.GEN_AI_SDK_VERSION, version)
119
+
120
+ # To be removed one the change to log events (from span events) is complete
121
+ prompt = concatenate_all_contents(formatted_messages)
122
+ if capture_message_content:
123
+ scope._span.add_event(
124
+ name=SemanticConvetion.GEN_AI_CONTENT_PROMPT_EVENT,
125
+ attributes={
126
+ SemanticConvetion.GEN_AI_CONTENT_PROMPT: prompt,
127
+ },
128
+ )
129
+ scope._span.add_event(
130
+ name=SemanticConvetion.GEN_AI_CONTENT_COMPLETION_EVENT,
131
+ attributes={
132
+ SemanticConvetion.GEN_AI_CONTENT_COMPLETION: scope._llmresponse,
133
+ },
134
+ )
135
+
136
+ choice_event_body = {
137
+ 'finish_reason': scope._finish_reason,
138
+ 'index': 0,
139
+ 'message': {
140
+ **({'content': scope._llmresponse} if capture_message_content else {}),
141
+ 'role': scope._response_role
142
+ }
143
+ }
144
+
145
+ # Emit events
146
+ for role in ['user', 'system', 'assistant', 'tool']:
147
+ if formatted_messages.get(role, {}).get('content', ''):
148
+ event = otel_event(
149
+ name=getattr(SemanticConvetion, f'GEN_AI_{role.upper()}_MESSAGE'),
150
+ attributes={
151
+ SemanticConvetion.GEN_AI_SYSTEM: SemanticConvetion.GEN_AI_SYSTEM_AWS_BEDROCK
152
+ },
153
+ body = {
154
+ # pylint: disable=line-too-long
155
+ **({'content': formatted_messages.get(role, {}).get('content', '')} if capture_message_content else {}),
156
+ 'role': formatted_messages.get(role, {}).get('role', []),
157
+ **({
158
+ 'tool_calls': {
159
+ 'function': {
160
+ # pylint: disable=line-too-long
161
+ 'name': (scope._tool_calls[0].get('function', {}).get('name', '') if scope._tool_calls else ''),
162
+ 'arguments': (scope._tool_calls[0].get('function', {}).get('arguments', '') if scope._tool_calls else '')
163
+ },
164
+ 'id': (scope._tool_calls[0].get('id', '') if scope._tool_calls else ''),
165
+ 'type': 'function'
166
+ }
167
+ } if role == 'assistant' else {}),
168
+ **({
169
+ 'id': (scope._tool_calls[0].get('id', '') if scope._tool_calls else '')
170
+ } if role == 'tool' else {})
171
+ }
172
+ )
173
+ event_provider.emit(event)
174
+
175
+ choice_event = otel_event(
176
+ name=SemanticConvetion.GEN_AI_CHOICE,
177
+ attributes={
178
+ SemanticConvetion.GEN_AI_SYSTEM: SemanticConvetion.GEN_AI_SYSTEM_AWS_BEDROCK
179
+ },
180
+ body=choice_event_body
181
+ )
182
+ event_provider.emit(choice_event)
183
+
184
+ scope._span.set_status(Status(StatusCode.OK))
185
+
186
+ if not disable_metrics:
187
+ metrics_attributes = create_metrics_attributes(
188
+ service_name=application_name,
189
+ deployment_environment=environment,
190
+ operation=SemanticConvetion.GEN_AI_OPERATION_TYPE_CHAT,
191
+ system=SemanticConvetion.GEN_AI_SYSTEM_AWS_BEDROCK,
192
+ request_model=request_model,
193
+ server_address=scope._server_address,
194
+ server_port=scope._server_port,
195
+ response_model=scope._response_model,
196
+ )
197
+
198
+ metrics['genai_client_usage_tokens'].record(scope._input_tokens + scope._output_tokens, metrics_attributes)
199
+ metrics['genai_client_operation_duration'].record(scope._end_time - scope._start_time, metrics_attributes)
200
+ metrics['genai_server_tbt'].record(scope._tbt, metrics_attributes)
201
+ metrics['genai_server_ttft'].record(scope._ttft, metrics_attributes)
202
+ metrics['genai_requests'].add(1, metrics_attributes)
203
+ metrics['genai_completion_tokens'].add(scope._output_tokens, metrics_attributes)
204
+ metrics['genai_prompt_tokens'].add(scope._input_tokens, metrics_attributes)
205
+ metrics['genai_cost'].record(cost, metrics_attributes)
206
+
207
+ def process_streaming_chat_response(self, pricing_info, environment, application_name, metrics,
208
+ event_provider, capture_message_content=False, disable_metrics=False, version='', llm_config=''):
209
+
210
+ """
211
+ Process chat request and generate Telemetry
212
+ """
213
+ if self._tool_id != '':
214
+ self._tool_calls = {
215
+ 'id': self._tool_id,
216
+ 'name': self._tool_name,
217
+ 'input': self._tool_arguments
218
+ }
219
+
220
+ common_chat_logic(self, pricing_info, environment, application_name, metrics,
221
+ event_provider, capture_message_content, disable_metrics, version, llm_config, is_stream=True)
222
+
223
+ def process_chat_response(response, request_model, pricing_info, server_port, server_address, environment,
224
+ application_name, metrics, event_provider, start_time, span, capture_message_content=False,
225
+ disable_metrics=False, version='1.0.0', llm_config='', **kwargs):
226
+
227
+ """
228
+ Process chat request and generate Telemetry
229
+ """
230
+
231
+ self = type('GenericScope', (), {})()
232
+ response_dict = response_as_dict(response)
233
+
234
+ # pylint: disable = no-member
235
+ self._start_time = start_time
236
+ self._end_time = time.time()
237
+ self._span = span
238
+ self._llmresponse = response_dict.get('output').get('message').get('content')[0].get('text')
239
+ self._response_role = 'assistant'
240
+ self._input_tokens = response_dict.get('usage').get('inputTokens')
241
+ self._output_tokens = response_dict.get('usage').get('outputTokens')
242
+ self._response_model = request_model
243
+ self._finish_reason = response_dict.get('stopReason', '')
244
+ self._response_id = response_dict.get('ResponseMetadata').get('RequestId')
245
+ self._timestamps = []
246
+ self._ttft, self._tbt = self._end_time - self._start_time, 0
247
+ self._server_address, self._server_port = server_address, server_port
248
+ self._kwargs = kwargs
249
+ common_chat_logic(self, pricing_info, environment, application_name, metrics,
250
+ event_provider, capture_message_content, disable_metrics, version, llm_config, is_stream=False)
251
+
252
+ return response
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: openlit
3
- Version: 1.33.17
3
+ Version: 1.33.19
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=9K9nz_RunwtnFeAk591uOJZiY3J88HsYv7T2H8elHWA,10262
1
+ openlit/__helpers.py,sha256=ob20aAkpzPLn2cjaPMCf-_fwt-8YNJUobdT3f6xEj58,9061
2
2
  openlit/__init__.py,sha256=iHGwg8XB2DhNVCktU3FLFqubAOiQVQCp1F7L7OHp6cg,23921
3
3
  openlit/evals/__init__.py,sha256=nJe99nuLo1b5rf7pt9U9BCdSDedzbVi2Fj96cgl7msM,380
4
4
  openlit/evals/all.py,sha256=oWrue3PotE-rB5WePG3MRYSA-ro6WivkclSHjYlAqGs,7154
@@ -28,11 +28,13 @@ openlit/instrumentation/astra/__init__.py,sha256=-JG3_YHQQaOQUr4XtFzqfaYiQKqviAA
28
28
  openlit/instrumentation/astra/astra.py,sha256=JH2-7RJBbk6nM9kBEVgbxCXXnzgTuGT0KoBhVGBGeIs,1607
29
29
  openlit/instrumentation/astra/async_astra.py,sha256=mMG22exgduREIe-7s2TdqLM1Ub8wP_ttcIS8wJH5P1Y,1625
30
30
  openlit/instrumentation/astra/utils.py,sha256=-Af5R_g8-x9XeQiepLBW3Qa3Beji4EMxppDtiE_nmzM,4933
31
- openlit/instrumentation/azure_ai_inference/__init__.py,sha256=T45ideMzIPWFzVhWIjalVGEBP562ESWfCA9diZAoTtw,2573
32
- openlit/instrumentation/azure_ai_inference/async_azure_ai_inference.py,sha256=xI0GDqKmsbSp58IHalpNvEapM_h65oGYDbe24UVyXqg,29974
33
- openlit/instrumentation/azure_ai_inference/azure_ai_inference.py,sha256=dgQ8GuSO-j0J6K77tcwK0mZSK3JnIdmT60kjwAV1dt8,29870
34
- openlit/instrumentation/bedrock/__init__.py,sha256=ZdCBjgwK92cclnbFfF90NC6AsRreom3nT3CklbM7EmM,1555
35
- openlit/instrumentation/bedrock/bedrock.py,sha256=jBDzm005Y9rbcTLxo-yShOtRb65NCDFyUYtggi0XRF0,12264
31
+ openlit/instrumentation/azure_ai_inference/__init__.py,sha256=ZoMAX_MUNCNMJqLZgl0A_kQ_lsgoz3VddkHiDT3pVF8,2032
32
+ openlit/instrumentation/azure_ai_inference/async_azure_ai_inference.py,sha256=VPp0CF8GOtwFFJc_XggZVGq1wxjCs0VdsQIWK6cZ2AU,5056
33
+ openlit/instrumentation/azure_ai_inference/azure_ai_inference.py,sha256=82Jv5KYaRSjIrG_6WldUhRVx1XqPhDqnisJ93uS08Kw,4970
34
+ openlit/instrumentation/azure_ai_inference/utils.py,sha256=BLjWqRiwu1aYompMkxY5Jxvz-o4uL0UbCbWK_0PmncY,10997
35
+ openlit/instrumentation/bedrock/__init__.py,sha256=Sfd0vm4Dfm1t-N7vBPRwU57GLTlZP2M4rVYRek_JHXY,1625
36
+ openlit/instrumentation/bedrock/bedrock.py,sha256=e2wG9l7j5CaBQ7Uq074nGwWx5h1vhANoXzJOGSWvW7I,2815
37
+ openlit/instrumentation/bedrock/utils.py,sha256=OFwMcH0F12XklRV4Vtq6agIPYI7xO4nXGbRml0EaVE8,11597
36
38
  openlit/instrumentation/chroma/__init__.py,sha256=4ZeHY1OInRKQbb4qg8BVvGJtWN1XdzW6mosqi7-6ruE,3353
37
39
  openlit/instrumentation/chroma/chroma.py,sha256=Ar0IYfNtCzFbtBl_irn6xpsKlyAPu5TZ_LYpttW1ixk,10583
38
40
  openlit/instrumentation/cohere/__init__.py,sha256=TIRq1obu-zqBji0HhMbFGfI2q5m-zw0nWbToKeZqpg4,2905
@@ -123,7 +125,7 @@ openlit/otel/events.py,sha256=VrMjTpvnLtYRBHCiFwJojTQqqNpRCxoD4yJYeQrtPsk,3560
123
125
  openlit/otel/metrics.py,sha256=Iwx6baEiCZPNqsFf92K5mDWU8are8DOF0uQAuNZsCKg,6826
124
126
  openlit/otel/tracing.py,sha256=tjV2bEbEDPUB1Z46gE-UsJsb04sRdFrfbhIDkxViZc0,3103
125
127
  openlit/semcov/__init__.py,sha256=lM0Y3wMYYmCvfcNGD3k0xSn1XZUiGw-bKgCuwcGsOp8,13302
126
- openlit-1.33.17.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
127
- openlit-1.33.17.dist-info/METADATA,sha256=e1xpVcwlcHM70if9z1q85FuYXYFPu3hlj_EnaOG6M3U,23471
128
- openlit-1.33.17.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
129
- openlit-1.33.17.dist-info/RECORD,,
128
+ openlit-1.33.19.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
129
+ openlit-1.33.19.dist-info/METADATA,sha256=VLxhVb9GGUeVPxv5V_ZjxNzfMMuJJqOF1ruVOEbNiAU,23471
130
+ openlit-1.33.19.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
131
+ openlit-1.33.19.dist-info/RECORD,,