2
2
3
3
from ddtrace .contrib .internal .openai .utils import TracedOpenAIAsyncStream
4
4
from ddtrace .contrib .internal .openai .utils import TracedOpenAIStream
5
- from ddtrace .contrib .internal .openai .utils import _format_openai_api_key
6
5
from ddtrace .contrib .internal .openai .utils import _is_async_generator
7
6
from ddtrace .contrib .internal .openai .utils import _is_generator
8
7
from ddtrace .contrib .internal .openai .utils import _loop_handler
9
8
from ddtrace .contrib .internal .openai .utils import _process_finished_stream
10
- from ddtrace .contrib .internal .openai .utils import _tag_tool_calls
11
9
from ddtrace .internal .utils .version import parse_version
12
10
13
11
@@ -57,22 +55,15 @@ def _record_request(self, pin, integration, instance, span, args, kwargs):
57
55
continue
58
56
if arg in self ._base_level_tag_args :
59
57
span .set_tag_str ("openai.%s" % arg , str (args [idx ]))
60
- elif arg == "organization" :
61
- span .set_tag_str ("openai.organization.id" , args [idx ])
62
- elif arg == "api_key" :
63
- span .set_tag_str ("openai.user.api_key" , _format_openai_api_key (args [idx ]))
64
- else :
65
- span .set_tag_str ("openai.request.%s" % arg , str (args [idx ]))
66
58
for kw_attr in self ._request_kwarg_params :
67
59
if kw_attr not in kwargs :
68
60
continue
61
+
69
62
if isinstance (kwargs [kw_attr ], dict ):
70
63
for k , v in kwargs [kw_attr ].items ():
71
64
span .set_tag_str ("openai.request.%s.%s" % (kw_attr , k ), str (v ))
72
- elif kw_attr == "engine" : # Azure OpenAI requires using "engine" instead of "model"
65
+ elif kw_attr == "engine" or kw_attr == "model" : # Azure OpenAI requires using "engine" instead of "model"
73
66
span .set_tag_str ("openai.request.model" , str (kwargs [kw_attr ]))
74
- else :
75
- span .set_tag_str ("openai.request.%s" % kw_attr , str (kwargs [kw_attr ]))
76
67
77
68
def handle_request (self , pin , integration , instance , span , args , kwargs ):
78
69
self ._record_request (pin , integration , instance , span , args , kwargs )
@@ -92,7 +83,7 @@ def _record_response(self, pin, integration, span, args, kwargs, resp, error):
92
83
93
84
94
85
class _BaseCompletionHook (_EndpointHook ):
95
- _request_arg_params = ("api_key" , "api_base" , "api_type" , "request_id" , "api_version" , "organization" )
86
+ _request_arg_params = ()
96
87
97
88
def _handle_streamed_response (self , integration , span , kwargs , resp , operation_type = "" ):
98
89
"""Handle streamed response objects returned from completions/chat/response endpoint calls.
@@ -166,34 +157,12 @@ class _CompletionHook(_BaseCompletionHook):
166
157
"model" ,
167
158
"engine" ,
168
159
"suffix" ,
169
- "max_tokens" ,
170
- "temperature" ,
171
- "top_p" ,
172
- "n" ,
173
- "stream" ,
174
- "logprobs" ,
175
- "echo" ,
176
- "stop" ,
177
- "presence_penalty" ,
178
- "frequency_penalty" ,
179
- "best_of" ,
180
- "logit_bias" ,
181
- "user" ,
182
160
)
183
- _response_attrs = ("created" , "id" , " model" )
161
+ _response_attrs = ("model" , )
184
162
ENDPOINT_NAME = "completions"
185
163
HTTP_METHOD_TYPE = "POST"
186
164
OPERATION_ID = "createCompletion"
187
165
188
- def _record_request (self , pin , integration , instance , span , args , kwargs ):
189
- super ()._record_request (pin , integration , instance , span , args , kwargs )
190
- if integration .is_pc_sampled_span (span ):
191
- prompt = kwargs .get ("prompt" , "" )
192
- if isinstance (prompt , str ):
193
- prompt = [prompt ]
194
- for idx , p in enumerate (prompt ):
195
- span .set_tag_str ("openai.request.prompt.%d" % idx , integration .trunc (str (p )))
196
-
197
166
def _record_response (self , pin , integration , span , args , kwargs , resp , error ):
198
167
resp = super ()._record_response (pin , integration , span , args , kwargs , resp , error )
199
168
if not resp :
@@ -202,13 +171,6 @@ def _record_response(self, pin, integration, span, args, kwargs, resp, error):
202
171
if kwargs .get ("stream" ) and error is None :
203
172
return self ._handle_streamed_response (integration , span , kwargs , resp , operation_type = "completion" )
204
173
integration .llmobs_set_tags (span , args = [], kwargs = kwargs , response = resp , operation = "completion" )
205
- if not resp :
206
- return
207
- for choice in resp .choices :
208
- span .set_tag_str ("openai.response.choices.%d.finish_reason" % choice .index , str (choice .finish_reason ))
209
- if integration .is_pc_sampled_span (span ):
210
- span .set_tag_str ("openai.response.choices.%d.text" % choice .index , integration .trunc (choice .text ))
211
- integration .record_usage (span , resp .usage )
212
174
return resp
213
175
214
176
@@ -217,40 +179,18 @@ class _CompletionWithRawResponseHook(_CompletionHook):
217
179
218
180
219
181
class _ChatCompletionHook (_BaseCompletionHook ):
220
- _request_arg_params = ("api_key" , "api_base" , "api_type" , "request_id" , "api_version" , "organization" )
182
+ _request_arg_params = ()
221
183
_request_kwarg_params = (
222
184
"model" ,
223
185
"engine" ,
224
- "temperature" ,
225
- "top_p" ,
226
- "n" ,
227
- "stream" ,
228
- "stop" ,
229
- "max_tokens" ,
230
- "presence_penalty" ,
231
- "frequency_penalty" ,
232
- "logit_bias" ,
233
- "user" ,
234
186
)
235
- _response_attrs = ("created" , "id" , " model" )
187
+ _response_attrs = ("model" , )
236
188
ENDPOINT_NAME = "chat/completions"
237
189
HTTP_METHOD_TYPE = "POST"
238
190
OPERATION_ID = "createChatCompletion"
239
191
240
192
def _record_request (self , pin , integration , instance , span , args , kwargs ):
241
193
super ()._record_request (pin , integration , instance , span , args , kwargs )
242
- for idx , m in enumerate (kwargs .get ("messages" , [])):
243
- role = getattr (m , "role" , "" )
244
- name = getattr (m , "name" , "" )
245
- content = getattr (m , "content" , "" )
246
- if isinstance (m , dict ):
247
- content = m .get ("content" , "" )
248
- role = m .get ("role" , "" )
249
- name = m .get ("name" , "" )
250
- if integration .is_pc_sampled_span (span ):
251
- span .set_tag_str ("openai.request.messages.%d.content" % idx , integration .trunc (str (content )))
252
- span .set_tag_str ("openai.request.messages.%d.role" % idx , str (role ))
253
- span .set_tag_str ("openai.request.messages.%d.name" % idx , str (name ))
254
194
if parse_version (OPENAI_VERSION ) >= (1 , 26 ) and kwargs .get ("stream" ):
255
195
stream_options = kwargs .get ("stream_options" , {})
256
196
if not isinstance (stream_options , dict ):
@@ -270,21 +210,6 @@ def _record_response(self, pin, integration, span, args, kwargs, resp, error):
270
210
if kwargs .get ("stream" ) and error is None :
271
211
return self ._handle_streamed_response (integration , span , kwargs , resp , operation_type = "chat" )
272
212
integration .llmobs_set_tags (span , args = [], kwargs = kwargs , response = resp , operation = "chat" )
273
- for choice in resp .choices :
274
- idx = choice .index
275
- finish_reason = getattr (choice , "finish_reason" , None )
276
- message = choice .message
277
- span .set_tag_str ("openai.response.choices.%d.finish_reason" % idx , str (finish_reason ))
278
- span .set_tag_str ("openai.response.choices.%d.message.role" % idx , choice .message .role )
279
- if integration .is_pc_sampled_span (span ):
280
- span .set_tag_str (
281
- "openai.response.choices.%d.message.content" % idx , integration .trunc (message .content or "" )
282
- )
283
- if getattr (message , "function_call" , None ):
284
- _tag_tool_calls (integration , span , [message .function_call ], idx )
285
- if getattr (message , "tool_calls" , None ):
286
- _tag_tool_calls (integration , span , message .tool_calls , idx )
287
- integration .record_usage (span , resp .usage )
288
213
return resp
289
214
290
215
@@ -293,34 +218,18 @@ class _ChatCompletionWithRawResponseHook(_ChatCompletionHook):
293
218
294
219
295
220
class _EmbeddingHook (_EndpointHook ):
296
- _request_arg_params = ("api_key" , "api_base" , "api_type" , "request_id" , "api_version" , "organization" )
297
- _request_kwarg_params = ("model" , "engine" , "user" )
221
+ _request_arg_params = ()
222
+ _request_kwarg_params = ("model" , "engine" )
298
223
_response_attrs = ("model" ,)
299
224
ENDPOINT_NAME = "embeddings"
300
225
HTTP_METHOD_TYPE = "POST"
301
226
OPERATION_ID = "createEmbedding"
302
227
303
- def _record_request (self , pin , integration , instance , span , args , kwargs ):
304
- """
305
- Embedding endpoint allows multiple inputs, each of which we specify a request tag for, so have to
306
- manually set them in _pre_response().
307
- """
308
- super ()._record_request (pin , integration , instance , span , args , kwargs )
309
- embedding_input = kwargs .get ("input" , "" )
310
- if integration .is_pc_sampled_span (span ):
311
- if isinstance (embedding_input , str ) or isinstance (embedding_input [0 ], int ):
312
- embedding_input = [embedding_input ]
313
- for idx , inp in enumerate (embedding_input ):
314
- span .set_tag_str ("openai.request.input.%d" % idx , integration .trunc (str (inp )))
315
-
316
228
def _record_response (self , pin , integration , span , args , kwargs , resp , error ):
317
229
resp = super ()._record_response (pin , integration , span , args , kwargs , resp , error )
318
230
integration .llmobs_set_tags (span , args = [], kwargs = kwargs , response = resp , operation = "embedding" )
319
231
if not resp :
320
232
return
321
- span .set_metric ("openai.response.embeddings_count" , len (resp .data ))
322
- span .set_metric ("openai.response.embedding-length" , len (resp .data [0 ].embedding ))
323
- integration .record_usage (span , resp .usage )
324
233
return resp
325
234
326
235
@@ -329,7 +238,7 @@ class _ListHook(_EndpointHook):
329
238
Hook for openai.ListableAPIResource, which is used by Model.list, File.list, and FineTune.list.
330
239
"""
331
240
332
- _request_arg_params = ("api_key" , "request_id" , "api_version" , "organization" , " api_base" , "api_type " )
241
+ _request_arg_params = ("api_base" , "api_version " )
333
242
_request_kwarg_params = ("user" ,)
334
243
ENDPOINT_NAME = None
335
244
HTTP_METHOD_TYPE = "GET"
@@ -372,7 +281,7 @@ class _FileListHook(_ListHook):
372
281
class _RetrieveHook (_EndpointHook ):
373
282
"""Hook for openai.APIResource, which is used by Model.retrieve, File.retrieve, and FineTune.retrieve."""
374
283
375
- _request_arg_params = (None , "api_key" , " request_id" , "request_timeout" )
284
+ _request_arg_params = (None , "request_id" , "request_timeout" )
376
285
_request_kwarg_params = ("user" ,)
377
286
_response_attrs = (
378
287
"id" ,
@@ -726,26 +635,7 @@ def _record_response(self, pin, integration, span, args, kwargs, resp, error):
726
635
class _ResponseHook (_BaseCompletionHook ):
727
636
_request_arg_params = ()
728
637
# Collecting all kwargs for responses
729
- _request_kwarg_params = (
730
- "model" ,
731
- "include" ,
732
- "instructions" ,
733
- "max_output_tokens" ,
734
- "metadata" ,
735
- "parallel_tool_calls" ,
736
- "previous_response_id" ,
737
- "reasoning" ,
738
- "service_tier" ,
739
- "store" ,
740
- "stream" ,
741
- "temperature" ,
742
- "text" ,
743
- "tool_choice" ,
744
- "tools" ,
745
- "top_p" ,
746
- "truncation" ,
747
- "user" ,
748
- )
638
+ _request_kwarg_params = ("model" ,)
749
639
_response_attrs = ("model" ,)
750
640
ENDPOINT_NAME = "responses"
751
641
HTTP_METHOD_TYPE = "POST"
@@ -759,5 +649,4 @@ def _record_response(self, pin, integration, span, args, kwargs, resp, error):
759
649
if kwargs .get ("stream" ) and error is None :
760
650
return self ._handle_streamed_response (integration , span , kwargs , resp , operation_type = "response" )
761
651
integration .llmobs_set_tags (span , args = [], kwargs = kwargs , response = resp , operation = "response" )
762
- integration .record_usage (span , resp .usage )
763
652
return resp
0 commit comments