U
    h='                  	   @  s  d dl mZ d dlZd dlZd dlmZ d dlmZmZm	Z	m
Z
mZmZmZmZmZmZmZ d dlmZ d dlmZ d dlmZ d dlmZmZmZ erd d	lmZmZ d d
lm Z m!Z!m"Z" d dl#m$Z$ ededdef dZ%e&e'Z(ej)ddddZ*dddddZ+dddddZ,dddddZ-d dd!d"d#Z.d$dd!d%d&Z/dd'd(d)d*Z0d+d,d-d.Z1d>d/dd/d0d1d1d/d2d3d4Z2G d5d6 d6ed7d8Z3dd9dd:dd0dddd;d<d=Z4dS )?    )annotationsN)defaultdict)TYPE_CHECKINGAnyCallableDefaultDictDictListMappingOptionalTypeTypeVarUnion)	TypedDict)client)run_helpers)InputTokenDetailsOutputTokenDetailsUsageMetadata)AsyncOpenAIOpenAI)ChatCompletionChunkChoiceChoiceDeltaToolCall)
CompletionCr   r   )boundzOptional[Type])returnc                  C  s.   zddl m}  | W S  tk
r(   Y d S X d S )Nr   NotGiven)Zopenai._typesr   ImportErrorr    r!   >/tmp/pip-unpacked-wheel-cqvhoa9t/langsmith/wrappers/_openai.py_get_not_given(   s
    r#   dict)dr   c              
     sl   z,t    d kr| W S  fdd|  D W S  tk
rf } ztd|  |  W Y S d }~X Y nX d S )Nc                   s    i | ]\}}t | s||qS r!   )
isinstance.0kvZ	not_givenr!   r"   
<dictcomp>7   s     
  z$_strip_not_given.<locals>.<dictcomp>zError stripping NotGiven: )r#   items	Exceptionloggererror)r%   er!   r+   r"   _strip_not_given2   s    r2   str)
model_typekwargsc                 C  sP   t |}|d}|r&t|tr&|g}d| |dd |dd |dd |dS )NstopopenaimodelZtemperatureZ
max_tokens)Zls_providerZls_model_typeZls_model_nameZls_temperatureZls_max_tokensZls_stop)r2   getr&   r3   )r4   r5   strippedr6   r!   r!   r"   _infer_invocation_params=   s    



r;   zList[Choice])choicesr   c           
      C  s  t t| }ddd}|D ]}|jjr|jj|d<  q8qtt }| D ]}|jjrd|d  |jj7  < |jjr|dsddd|d< |jjjr|d d  |jjj7  < |jjj	r|d d	  |jjj	7  < |jj
rD|jj
D ]}||j | qqD|rd
d | D |d< | D ]\}}|tdd |D d tdd |D d d|d |< |D ]}|jrX|d | dsddd|d | d< |jjr|d | d }	|	d  |jj7  < |jj	rX|d | d }	|	d	  |jj	7  < qXq| d jtdd |D d |dS )N	assistant rolecontentr@   rA   function_call)name	argumentsrC   rD   c                 S  s   g | ]}d qS Nr!   )r(   _r!   r!   r"   
<listcomp>g   s     z#_reduce_choices.<locals>.<listcomp>
tool_callsc                 s  s   | ]}|j r|j V  qd S rE   )idr(   cr!   r!   r"   	<genexpr>k   s      z"_reduce_choices.<locals>.<genexpr>c                 s  s   | ]}|j r|j V  qd S rE   )typerJ   r!   r!   r"   rL   l   s      )indexrI   rM   functionr   c                 s  s   | ]}|j r|j V  qd S rE   )finish_reasonrJ   r!   r!   r"   rL   ~   s      )rN   rP   message)listreverseddeltar@   r   rA   rB   r9   rC   rD   rH   rN   appendkeysr-   nextrO   )
r<   Zreversed_choicesrQ   rK   rH   Z	tool_callrN   Ztool_call_chunkschunkZfn_r!   r!   r"   _reduce_choicesN   s`    




rY   zList[ChatCompletionChunk])
all_chunksr   c                 C  s   t t}| D ] }|jD ]}||j | qq| rV| d  }dd | D |d< ndddddigi}|d	d }|rt|nd |d
< |S )Nc                 S  s   g | ]}t |qS r!   )rY   )r(   r<   r!   r!   r"   rG      s    z _reduce_chat.<locals>.<listcomp>r<   rQ   r=   r>   r?   usageusage_metadata)	r   rR   r<   rN   rU   
model_dumpvaluespop_create_usage_metadata)rZ   Zchoices_by_indexrX   choicer%   oai_token_usager!   r!   r"   _reduce_chat   s    
rd   zList[Completion]c                 C  sh   g }| D ]"}|j d j}|d k	r|| qd|}| rV| d  }d|ig|d< ndd|igi}|S )Nr   r>   r[   textr<   )r<   re   rU   joinr^   )rZ   Zall_contentrX   rA   r%   r!   r!   r"   _reduce_completions   s    
rg   r   )rc   r   c              
   C  s   |  dpd}|  dpd}|  dp,|| }|  dp:i  d|  dpLi  dd}|  d	pdi  d|  d	pvi  d
d}t|||tf dd | D tf dd | D dS )NZprompt_tokensr   Zcompletion_tokenstotal_tokensZprompt_tokens_detailsZaudio_tokensZcached_tokens)audioZ
cache_readZcompletion_tokens_detailsZreasoning_tokens)ri   Z	reasoningc                 S  s   i | ]\}}|d k	r||qS rE   r!   r'   r!   r!   r"   r,      s       z*_create_usage_metadata.<locals>.<dictcomp>c                 S  s   i | ]\}}|d k	r||qS rE   r!   r'   r!   r!   r"   r,      s       )input_tokensoutput_tokensrh   input_token_detailsoutput_token_details)r9   r   r   r-   r   )rc   rj   rk   rh   rl   rm   r!   r!   r"   ra      s8    	ra   r   )outputsc              
   C  sr   z.|   }|dd }|r"t|nd |d< |W S  tk
rl } z td|  d| i W Y S d }~X Y nX d S )Nr\   r]   z"Error processing chat completion: output)r^   r`   ra   BaseExceptionr/   debug)rn   Zrdictrc   r1   r!   r!   r"   _process_chat_completion   s    rr   r   zOptional[TracingExtra]zOptional[Callable])original_createrC   	reduce_fntracing_extrainvocation_params_fnprocess_outputsr   c              	     sr   |pi t dddd fdd}t dddd fdd}trn|S |S )NF)streamboolc              	     s<   t jf d| rnd t d}||d| i|S Nllm)rC   Zrun_typert   Zprocess_inputsZ_invocation_params_fnrw   rx   )r   	traceabler2   rx   argsr5   	decoratorrv   rC   rs   rw   rt   Ztextrar!   r"   create   s    

z_get_wrapper.<locals>.createc              	     sJ   t |}tjf d| rnd t  d}||d| i|I d H S rz   )r2   r   r|   r}   r   r!   r"   acreate   s    
	z_get_wrapper.<locals>.acreate)	functoolswrapsr   Zis_async)rs   rC   rt   ru   rv   rw   r   r   r!   r   r"   _get_wrapper   s    $$r   c                   @  s&   e Zd ZU ded< ded< ded< dS )TracingExtrazOptional[Mapping[str, Any]]metadatazOptional[List[str]]tagszOptional[ls_client.Client]r   N)__name__
__module____qualname____annotations__r!   r!   r!   r"   r     s   
r   F)totalZ
ChatOpenAI)ru   	chat_namecompletions_name)r   ru   r   r   r   c             	   C  sN   t | jjj|t|ttdtd| jj_t | jj|t	|ttdd| j_| S )a)  Patch the OpenAI client to make it traceable.

    Args:
        client (Union[OpenAI, AsyncOpenAI]): The client to patch.
        tracing_extra (Optional[TracingExtra], optional): Extra tracing information.
            Defaults to None.
        chat_name (str, optional): The run name for the chat completions endpoint.
            Defaults to "ChatOpenAI".
        completions_name (str, optional): The run name for the completions endpoint.
            Defaults to "OpenAI".

    Returns:
        Union[OpenAI, AsyncOpenAI]: The patched client.

    chat)ru   rv   rw   r{   )ru   rv   )
r   r   Zcompletionsr   rd   r   partialr;   rr   rg   )r   ru   r   r   r!   r!   r"   wrap_openai  s     


r   )NNN)5
__future__r   r   loggingcollectionsr   typingr   r   r   r   r   r	   r
   r   r   r   r   Ztyping_extensionsr   Z	langsmithr   Z	ls_clientr   Zlangsmith.schemasr   r   r   r7   r   r   Z'openai.types.chat.chat_completion_chunkr   r   r   Zopenai.types.completionr   r   	getLoggerr   r/   	lru_cacher#   r2   r;   rY   rd   rg   ra   rr   r   r   r   r!   r!   r!   r"   <module>   s@   4
	7!   )	