o
    i*                     @   s  d dl mZ d dl mZ d dlmZ d dlmZ d dlmZ d dl	m
Z
 d dl	mZ d dl	mZ d d	l	mZ d d
l	mZ d dl	mZ d dl	mZ d dl	mZ d dl	mZ d dl	mZ d dl	mZ d dl	mZ d dl	mZ d dl	mZ d dl	mZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlm Z  d dlm!Z! d dl"m#Z# d dl"m$Z$ d dl%m&Z& d dl'm(Z( ee)Z*d Z+G d!d" d"eZ,d#S )$    )Any)Optional)	COMPONENT)
get_logger)parse_version)"CACHE_READ_INPUT_TOKENS_METRIC_KEY)INPUT_DOCUMENTS)INPUT_TOKENS_METRIC_KEY)INPUT_VALUE)METADATA)METRICS)
MODEL_NAME)MODEL_PROVIDER)NAME)OUTPUT_TOKENS_METRIC_KEY)OUTPUT_VALUE)PROXY_REQUEST)"REASONING_OUTPUT_TOKENS_METRIC_KEY)	SPAN_KIND)TOTAL_TOKENS_METRIC_KEY)BaseLLMIntegration)_compute_completion_tokens)_compute_prompt_tokens)openai_set_meta_tags_from_chat)$openai_set_meta_tags_from_completion)"openai_set_meta_tags_from_response)(update_proxy_workflow_input_output_value)	_get_attr)	safe_json)Document)Span)
completionchatresponsec                       s:  e Zd ZdZ fddZd!dededeeef de	f fd	d
Z
de	ddfddZdd Z		d"de	dee deeef dee deddfddZede	deeef deddfddZede	deeef deddfddZede	dededeeef deeeef  f
ddZdeeef dee fdd Z  ZS )#OpenAIIntegrationopenaic                    s   t  | || _d | _d S )N)super__init___openai_client)selfintegration_configr%   	__class__ W/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/llmobs/_integrations/openai.pyr'   +   s   
zOpenAIIntegration.__init__Foperation_idsubmit_to_llmobskwargsreturnc                    s2   d}||v rd}t d| t j||fi |S )N)createCompletioncreateChatCompletioncreateEmbeddingcreateResponseparseChatCompletionparseResponseTz*Creating LLM span for openai operation: %s)logdebugr&   trace)r*   r0   r1   r2   traced_operationsr,   r.   r/   r<   4   s
   zOpenAIIntegration.tracespanNc                 K   sF   | t| jj d}| |drd}n| |drd}| d| d S )NOpenAIazureAzureOpenAIdeepseekDeepseekzopenai.request.provider)_set_tag_strr   r+   integration_name_is_provider)r*   r>   r2   clientr.   r.   r/   _set_base_span_tagsB   s   z%OpenAIIntegration._set_base_span_tagsc                 C   sf   d}t | jjjdkrt| jdd}nt| jdd}|r t|nd}|r)t|ts+dS | | v S )z9Check if the traced operation is from the given provider.N)   r   r   	_base_urlapi_baseF)	r   r(   versionVERSIONgetattrr)   str
isinstancelower)r*   r>   providerbase_urlr.   r.   r/   rF   L   s   zOpenAIIntegration._is_provider argsr#   	operationc           
   
   C   s  | trdn|tv rdn|}|dp|dpd}d}| |dr&d}n| |d	r.d	}|d
kr9t||| n.|dkrDt||| n#|dkrP| ||| n|dkr\t||||  n|dkrg| 	||| t
|| | ||||}	|t|t|t|t|	i dS )z@Sets meta tags and metrics for span events to be sent to LLMObs.workflowllmzopenai.response.modelzopenai.request.modelunknown_modelr%   r@   azure_openairB   r!   r"   	embeddingr#   toolN)_get_ctx_itemr   OPENAI_LLM_OPERATIONSget_tagrF   r   r   $_llmobs_set_meta_tags_from_embeddingr   _llmobs_set_tags_from_toolr   _extract_llmobs_metrics_tags_set_ctx_itemsr   r   r   r   )
r*   r>   rU   r2   r#   rV   	span_kind
model_namemodel_providermetricsr.   r.   r/   _llmobs_set_tagsX   s6   
z"OpenAIIntegration._llmobs_set_tagsrespc           	      C   s   | dpd}d|i}| dr| d|d< | dd}t|ts)t|d tr,|g}g }|D ]}|tt|d q0| t|t|i | j	sK|sMdS |dkrht
|jd j}| td	t
|j| dS | td
t
|j dS )zVExtract prompt tags from an embedding and set them as temporary "_ml_obs.meta.*" tags.encoding_formatfloat
dimensionsinputrT   r   )textNz'[{} embedding(s) returned with size {}]z[{} embedding(s) returned])getrP   rO   intappendr   rc   r   r   errorlendatar[   _set_ctx_itemr   format)	r>   r2   ri   rj   metadataembedding_inputsinput_documentsdocembedding_dimr.   r.   r/   r`      s(   

z6OpenAIIntegration._llmobs_set_meta_tags_from_embeddingc                 C   s|   | dd}| dd}| d}|}d|}|| _| tdt|t|dur*t|nd	t|dur4t|nd	t	d|ii dS )
zaExtract tool name, arguments, and output from the request and response to be submitted to LLMObs.tool_idunknown_tool_idnameunknown_tool	argumentszMCP Client Tool Call: {}r\   NrT   )
ro   rv   r~   rc   r   r   r
   r   r   r   )r>   r2   r#   r|   	tool_nametool_argumentstool_output	span_namer.   r.   r/   ra      s   

z,OpenAIIntegration._llmobs_set_tags_from_toolrd   c                 C   st  |dkrdS d}|r t |tr t|d ddr t|d di }n|r.t|ddr.t|di }|durt|dd}t|dd}t|dd}t|dd}|pM|}|pQ|}t|t|t|| i}	t|d	i pgt|d
i }
t|
dd}|durv||	t< t|di pt|di }t|dd}|dur||	t< |	S |dr|durt	|dd|dd}t
|}|| }t|t|t|iS dS )zYExtract metrics from a chat/completion and set them as a temporary "_ml_obs.metrics" tag.rW   Nr   usageprompt_tokenscompletion_tokensinput_tokensoutput_tokensprompt_tokens_detailsinput_tokens_detailscached_tokenscompletion_tokens_detailsoutput_tokens_detailsreasoning_tokensstreampromptmessages)rP   listr   r	   r   r   r   r   ro   r   r   )r>   ri   rd   r2   token_usager   r   r   r   rg   r   r   reasoning_output_tokens_detailsreasoning_output_tokenstotal_tokensr.   r.   r/   rb      sP   z.OpenAIIntegration._extract_llmobs_metrics_tagsc                 K   s:   | d}t|dd }|rt|dd nd }|rt|S d S )Ninstancer)   rJ   )ro   rN   rO   )r*   r2   r   rG   rS   r.   r.   r/   _get_base_url   s   
zOpenAIIntegration._get_base_url)F)NrT   )__name__
__module____qualname___integration_namer'   rO   booldictr   r    r<   rH   rF   r   r   rh   staticmethodr`   ra   rb   r   __classcell__r.   r.   r,   r/   r$   (   sL    (	


'$$
&7r$   N)-typingr   r   ddtrace.internal.constantsr   ddtrace.internal.loggerr   ddtrace.internal.utils.versionr   ddtrace.llmobs._constantsr   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   !ddtrace.llmobs._integrations.baser   "ddtrace.llmobs._integrations.utilsr   r   r   r   r   r   ddtrace.llmobs._utilsr   r   ddtrace.llmobs.typesr   ddtrace.tracer    r   r:   r^   r$   r.   r.   r.   r/   <module>   sD    