opentelemetry-instrumentation-openai 0.18.1__py3-none-any.whl → 0.18.2__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.
Potentially problematic release.
This version of opentelemetry-instrumentation-openai might be problematic. Click here for more details.
- opentelemetry/instrumentation/openai/shared/__init__.py +7 -1
- opentelemetry/instrumentation/openai/shared/chat_wrappers.py +228 -25
- opentelemetry/instrumentation/openai/version.py +1 -1
- {opentelemetry_instrumentation_openai-0.18.1.dist-info → opentelemetry_instrumentation_openai-0.18.2.dist-info}/METADATA +1 -1
- {opentelemetry_instrumentation_openai-0.18.1.dist-info → opentelemetry_instrumentation_openai-0.18.2.dist-info}/RECORD +7 -7
- {opentelemetry_instrumentation_openai-0.18.1.dist-info → opentelemetry_instrumentation_openai-0.18.2.dist-info}/WHEEL +0 -0
- {opentelemetry_instrumentation_openai-0.18.1.dist-info → opentelemetry_instrumentation_openai-0.18.2.dist-info}/entry_points.txt +0 -0
|
@@ -112,7 +112,9 @@ def _set_request_attributes(span, kwargs):
|
|
|
112
112
|
_set_span_attribute(
|
|
113
113
|
span, SpanAttributes.LLM_REQUEST_MAX_TOKENS, kwargs.get("max_tokens")
|
|
114
114
|
)
|
|
115
|
-
_set_span_attribute(
|
|
115
|
+
_set_span_attribute(
|
|
116
|
+
span, SpanAttributes.LLM_REQUEST_TEMPERATURE, kwargs.get("temperature")
|
|
117
|
+
)
|
|
116
118
|
_set_span_attribute(span, SpanAttributes.LLM_REQUEST_TOP_P, kwargs.get("top_p"))
|
|
117
119
|
_set_span_attribute(
|
|
118
120
|
span, SpanAttributes.LLM_FREQUENCY_PENALTY, kwargs.get("frequency_penalty")
|
|
@@ -139,6 +141,10 @@ def _set_response_attributes(span, response):
|
|
|
139
141
|
|
|
140
142
|
_set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, response.get("model"))
|
|
141
143
|
|
|
144
|
+
_set_span_attribute(
|
|
145
|
+
span, "gen_ai.openai.system_fingerprint", response.get("system_fingerprint")
|
|
146
|
+
)
|
|
147
|
+
|
|
142
148
|
usage = response.get("usage")
|
|
143
149
|
if not usage:
|
|
144
150
|
return
|
|
@@ -87,18 +87,32 @@ def chat_wrapper(
|
|
|
87
87
|
|
|
88
88
|
if is_streaming_response(response):
|
|
89
89
|
# span will be closed after the generator is done
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
90
|
+
if is_openai_v1():
|
|
91
|
+
return ChatStream(
|
|
92
|
+
span,
|
|
93
|
+
response,
|
|
94
|
+
instance,
|
|
95
|
+
token_counter,
|
|
96
|
+
choice_counter,
|
|
97
|
+
duration_histogram,
|
|
98
|
+
streaming_time_to_first_token,
|
|
99
|
+
streaming_time_to_generate,
|
|
100
|
+
start_time,
|
|
101
|
+
kwargs,
|
|
102
|
+
)
|
|
103
|
+
else:
|
|
104
|
+
return _build_from_streaming_response(
|
|
105
|
+
span,
|
|
106
|
+
response,
|
|
107
|
+
instance,
|
|
108
|
+
token_counter,
|
|
109
|
+
choice_counter,
|
|
110
|
+
duration_histogram,
|
|
111
|
+
streaming_time_to_first_token,
|
|
112
|
+
streaming_time_to_generate,
|
|
113
|
+
start_time,
|
|
114
|
+
kwargs,
|
|
115
|
+
)
|
|
102
116
|
|
|
103
117
|
duration = end_time - start_time
|
|
104
118
|
|
|
@@ -161,18 +175,32 @@ async def achat_wrapper(
|
|
|
161
175
|
|
|
162
176
|
if is_streaming_response(response):
|
|
163
177
|
# span will be closed after the generator is done
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
178
|
+
if is_openai_v1():
|
|
179
|
+
return ChatStream(
|
|
180
|
+
span,
|
|
181
|
+
response,
|
|
182
|
+
instance,
|
|
183
|
+
token_counter,
|
|
184
|
+
choice_counter,
|
|
185
|
+
duration_histogram,
|
|
186
|
+
streaming_time_to_first_token,
|
|
187
|
+
streaming_time_to_generate,
|
|
188
|
+
start_time,
|
|
189
|
+
kwargs,
|
|
190
|
+
)
|
|
191
|
+
else:
|
|
192
|
+
return _abuild_from_streaming_response(
|
|
193
|
+
span,
|
|
194
|
+
response,
|
|
195
|
+
instance,
|
|
196
|
+
token_counter,
|
|
197
|
+
choice_counter,
|
|
198
|
+
duration_histogram,
|
|
199
|
+
streaming_time_to_first_token,
|
|
200
|
+
streaming_time_to_generate,
|
|
201
|
+
start_time,
|
|
202
|
+
kwargs,
|
|
203
|
+
)
|
|
176
204
|
|
|
177
205
|
duration = end_time - start_time
|
|
178
206
|
|
|
@@ -359,7 +387,9 @@ def _set_streaming_token_metrics(
|
|
|
359
387
|
prompt_content = ""
|
|
360
388
|
# setting the default model_name as gpt-4. As this uses the embedding "cl100k_base" that
|
|
361
389
|
# is used by most of the other model.
|
|
362
|
-
model_name =
|
|
390
|
+
model_name = (
|
|
391
|
+
request_kwargs.get("model") or complete_response.get("model") or "gpt-4"
|
|
392
|
+
)
|
|
363
393
|
for msg in request_kwargs.get("messages"):
|
|
364
394
|
if msg.get("content"):
|
|
365
395
|
prompt_content += msg.get("content")
|
|
@@ -403,6 +433,16 @@ def _set_streaming_token_metrics(
|
|
|
403
433
|
|
|
404
434
|
|
|
405
435
|
class ChatStream(ObjectProxy):
|
|
436
|
+
_span = None
|
|
437
|
+
_instance = None
|
|
438
|
+
_token_counter = None
|
|
439
|
+
_choice_counter = None
|
|
440
|
+
_duration_histogram = None
|
|
441
|
+
_streaming_time_to_first_token = None
|
|
442
|
+
_streaming_time_to_generate = None
|
|
443
|
+
_start_time = None
|
|
444
|
+
_request_kwargs = None
|
|
445
|
+
|
|
406
446
|
def __init__(
|
|
407
447
|
self,
|
|
408
448
|
span,
|
|
@@ -539,3 +579,166 @@ class ChatStream(ObjectProxy):
|
|
|
539
579
|
|
|
540
580
|
self._span.set_status(Status(StatusCode.OK))
|
|
541
581
|
self._span.end()
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
# Backward compatibility with OpenAI v0
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
@dont_throw
|
|
588
|
+
def _build_from_streaming_response(
|
|
589
|
+
span,
|
|
590
|
+
response,
|
|
591
|
+
instance=None,
|
|
592
|
+
token_counter=None,
|
|
593
|
+
choice_counter=None,
|
|
594
|
+
duration_histogram=None,
|
|
595
|
+
streaming_time_to_first_token=None,
|
|
596
|
+
streaming_time_to_generate=None,
|
|
597
|
+
start_time=None,
|
|
598
|
+
request_kwargs=None,
|
|
599
|
+
):
|
|
600
|
+
complete_response = {"choices": [], "model": ""}
|
|
601
|
+
|
|
602
|
+
first_token = True
|
|
603
|
+
time_of_first_token = start_time # will be updated when first token is received
|
|
604
|
+
|
|
605
|
+
for item in response:
|
|
606
|
+
span.add_event(name="llm.content.completion.chunk")
|
|
607
|
+
|
|
608
|
+
item_to_yield = item
|
|
609
|
+
|
|
610
|
+
if first_token and streaming_time_to_first_token:
|
|
611
|
+
time_of_first_token = time.time()
|
|
612
|
+
streaming_time_to_first_token.record(time_of_first_token - start_time)
|
|
613
|
+
first_token = False
|
|
614
|
+
|
|
615
|
+
_accumulate_stream_items(item, complete_response)
|
|
616
|
+
|
|
617
|
+
yield item_to_yield
|
|
618
|
+
|
|
619
|
+
shared_attributes = {
|
|
620
|
+
"gen_ai.response.model": complete_response.get("model") or None,
|
|
621
|
+
"server.address": _get_openai_base_url(instance),
|
|
622
|
+
"stream": True,
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
if not is_azure_openai(instance):
|
|
626
|
+
_set_streaming_token_metrics(
|
|
627
|
+
request_kwargs, complete_response, span, token_counter, shared_attributes
|
|
628
|
+
)
|
|
629
|
+
|
|
630
|
+
# choice metrics
|
|
631
|
+
if choice_counter and complete_response.get("choices"):
|
|
632
|
+
_set_choice_counter_metrics(
|
|
633
|
+
choice_counter, complete_response.get("choices"), shared_attributes
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
# duration metrics
|
|
637
|
+
if start_time and isinstance(start_time, (float, int)):
|
|
638
|
+
duration = time.time() - start_time
|
|
639
|
+
else:
|
|
640
|
+
duration = None
|
|
641
|
+
if duration and isinstance(duration, (float, int)) and duration_histogram:
|
|
642
|
+
duration_histogram.record(duration, attributes=shared_attributes)
|
|
643
|
+
if streaming_time_to_generate and time_of_first_token:
|
|
644
|
+
streaming_time_to_generate.record(time.time() - time_of_first_token)
|
|
645
|
+
|
|
646
|
+
_set_response_attributes(span, complete_response)
|
|
647
|
+
|
|
648
|
+
if should_send_prompts():
|
|
649
|
+
_set_completions(span, complete_response.get("choices"))
|
|
650
|
+
|
|
651
|
+
span.set_status(Status(StatusCode.OK))
|
|
652
|
+
span.end()
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
@dont_throw
|
|
656
|
+
async def _abuild_from_streaming_response(
|
|
657
|
+
span,
|
|
658
|
+
response,
|
|
659
|
+
instance=None,
|
|
660
|
+
token_counter=None,
|
|
661
|
+
choice_counter=None,
|
|
662
|
+
duration_histogram=None,
|
|
663
|
+
streaming_time_to_first_token=None,
|
|
664
|
+
streaming_time_to_generate=None,
|
|
665
|
+
start_time=None,
|
|
666
|
+
request_kwargs=None,
|
|
667
|
+
):
|
|
668
|
+
complete_response = {"choices": [], "model": ""}
|
|
669
|
+
|
|
670
|
+
first_token = True
|
|
671
|
+
time_of_first_token = start_time # will be updated when first token is received
|
|
672
|
+
|
|
673
|
+
async for item in response:
|
|
674
|
+
span.add_event(name="llm.content.completion.chunk")
|
|
675
|
+
|
|
676
|
+
item_to_yield = item
|
|
677
|
+
|
|
678
|
+
if first_token and streaming_time_to_first_token:
|
|
679
|
+
time_of_first_token = time.time()
|
|
680
|
+
streaming_time_to_first_token.record(time_of_first_token - start_time)
|
|
681
|
+
first_token = False
|
|
682
|
+
|
|
683
|
+
_accumulate_stream_items(item, complete_response)
|
|
684
|
+
|
|
685
|
+
yield item_to_yield
|
|
686
|
+
|
|
687
|
+
shared_attributes = {
|
|
688
|
+
"gen_ai.response.model": complete_response.get("model") or None,
|
|
689
|
+
"server.address": _get_openai_base_url(instance),
|
|
690
|
+
"stream": True,
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
if not is_azure_openai(instance):
|
|
694
|
+
_set_streaming_token_metrics(
|
|
695
|
+
request_kwargs, complete_response, span, token_counter, shared_attributes
|
|
696
|
+
)
|
|
697
|
+
|
|
698
|
+
# choice metrics
|
|
699
|
+
if choice_counter and complete_response.get("choices"):
|
|
700
|
+
_set_choice_counter_metrics(
|
|
701
|
+
choice_counter, complete_response.get("choices"), shared_attributes
|
|
702
|
+
)
|
|
703
|
+
|
|
704
|
+
# duration metrics
|
|
705
|
+
if start_time and isinstance(start_time, (float, int)):
|
|
706
|
+
duration = time.time() - start_time
|
|
707
|
+
else:
|
|
708
|
+
duration = None
|
|
709
|
+
if duration and isinstance(duration, (float, int)) and duration_histogram:
|
|
710
|
+
duration_histogram.record(duration, attributes=shared_attributes)
|
|
711
|
+
if streaming_time_to_generate and time_of_first_token:
|
|
712
|
+
streaming_time_to_generate.record(time.time() - time_of_first_token)
|
|
713
|
+
|
|
714
|
+
_set_response_attributes(span, complete_response)
|
|
715
|
+
|
|
716
|
+
if should_send_prompts():
|
|
717
|
+
_set_completions(span, complete_response.get("choices"))
|
|
718
|
+
|
|
719
|
+
span.set_status(Status(StatusCode.OK))
|
|
720
|
+
span.end()
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
def _accumulate_stream_items(item, complete_response):
|
|
724
|
+
if is_openai_v1():
|
|
725
|
+
item = model_as_dict(item)
|
|
726
|
+
|
|
727
|
+
complete_response["model"] = item.get("model")
|
|
728
|
+
|
|
729
|
+
for choice in item.get("choices"):
|
|
730
|
+
index = choice.get("index")
|
|
731
|
+
if len(complete_response.get("choices")) <= index:
|
|
732
|
+
complete_response["choices"].append(
|
|
733
|
+
{"index": index, "message": {"content": "", "role": ""}}
|
|
734
|
+
)
|
|
735
|
+
complete_choice = complete_response.get("choices")[index]
|
|
736
|
+
if choice.get("finish_reason"):
|
|
737
|
+
complete_choice["finish_reason"] = choice.get("finish_reason")
|
|
738
|
+
|
|
739
|
+
delta = choice.get("delta")
|
|
740
|
+
|
|
741
|
+
if delta and delta.get("content"):
|
|
742
|
+
complete_choice["message"]["content"] += delta.get("content")
|
|
743
|
+
if delta and delta.get("role"):
|
|
744
|
+
complete_choice["message"]["role"] = delta.get("role")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.18.
|
|
1
|
+
__version__ = "0.18.2"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: opentelemetry-instrumentation-openai
|
|
3
|
-
Version: 0.18.
|
|
3
|
+
Version: 0.18.2
|
|
4
4
|
Summary: OpenTelemetry OpenAI instrumentation
|
|
5
5
|
Home-page: https://github.com/traceloop/openllmetry/tree/main/packages/opentelemetry-instrumentation-openai
|
|
6
6
|
License: Apache-2.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
opentelemetry/instrumentation/openai/__init__.py,sha256=xl3Kvqry9glVhu8VtdknfUE9FpXQ7KWAFqtVlpjE-40,1344
|
|
2
|
-
opentelemetry/instrumentation/openai/shared/__init__.py,sha256=
|
|
3
|
-
opentelemetry/instrumentation/openai/shared/chat_wrappers.py,sha256=
|
|
2
|
+
opentelemetry/instrumentation/openai/shared/__init__.py,sha256=5kEyVhz2YDHvuq2SDQOsDhtjbG7R7GCn793oLq2_J_k,7490
|
|
3
|
+
opentelemetry/instrumentation/openai/shared/chat_wrappers.py,sha256=6gJUpjp1tq3eYviTVTRNq5RcF4yduhI6yAKJBSEGToI,23344
|
|
4
4
|
opentelemetry/instrumentation/openai/shared/completion_wrappers.py,sha256=-JHfgyxic5I3Wr3Uc_L-U7ztDVFcyovtF37tNLtaW3s,6604
|
|
5
5
|
opentelemetry/instrumentation/openai/shared/config.py,sha256=5uekQEnmYo1o6tsTD2IGc-cVmHUo5KmUC4pOVdrFFNk,102
|
|
6
6
|
opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py,sha256=6I6I98T1a5Np0ZjcGZQbId4ZyEmMI6o9wVm8qoRpO9o,6595
|
|
@@ -10,8 +10,8 @@ opentelemetry/instrumentation/openai/v0/__init__.py,sha256=ngmmYyfTwRQSjTZAvNpBI
|
|
|
10
10
|
opentelemetry/instrumentation/openai/v1/__init__.py,sha256=6XHk11JhkpZixgMDsjb0b-efd8LlBTG0jjMCyf0fOSo,8652
|
|
11
11
|
opentelemetry/instrumentation/openai/v1/assistant_wrappers.py,sha256=T6Vtdp1fAZdcYjGiTMZwkn4F4DgsltD4p4xLEFW-GhI,5874
|
|
12
12
|
opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py,sha256=SAzYoun2yyOloofyOWtxpm8E2M9TL3Nm8TgKdNyXHuY,2779
|
|
13
|
-
opentelemetry/instrumentation/openai/version.py,sha256=
|
|
14
|
-
opentelemetry_instrumentation_openai-0.18.
|
|
15
|
-
opentelemetry_instrumentation_openai-0.18.
|
|
16
|
-
opentelemetry_instrumentation_openai-0.18.
|
|
17
|
-
opentelemetry_instrumentation_openai-0.18.
|
|
13
|
+
opentelemetry/instrumentation/openai/version.py,sha256=GYySpgpz2Cs3F3nz_H9h8KIG60jkP6f1a--08qCTJCQ,23
|
|
14
|
+
opentelemetry_instrumentation_openai-0.18.2.dist-info/METADATA,sha256=8_mfPUYiS7Wxf5kBberCnJ4KEm4VjYtk7ESz_tXiSZ0,2255
|
|
15
|
+
opentelemetry_instrumentation_openai-0.18.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
16
|
+
opentelemetry_instrumentation_openai-0.18.2.dist-info/entry_points.txt,sha256=vTBfiX5yXji5YHikuJHEOoBZ1TFdPQ1EI4ctd2pZSeE,93
|
|
17
|
+
opentelemetry_instrumentation_openai-0.18.2.dist-info/RECORD,,
|
|
File without changes
|