o
    Zho                     @  s  d Z ddlmZ ddlZddlZddlZddl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mZmZ ddlmZ ddlmZmZ ddlmZ ddlmZmZm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* ddl+m,Z,m-Z-m.Z. ddl/m0Z0 ddl1m2Z2 ddl3m4Z4m5Z5m6Z6 ddl7m8Z8m9Z9m:Z:m;Z; ddl<m=Z=m>Z> ddl?m@Z@ erddlAZAeBeCZDd2ddZE	d3d4ddZF	d3d5dd ZGd6d&d'ZHd7d+d,ZIed-d.d/d0G d1d deZJdS )8zOpenAI chat wrapper.    )annotationsN)TYPE_CHECKINGAnyAsyncIteratorCallableDictIteratorListMappingOptionalSequenceTupleTypeUnion)
deprecated)AsyncCallbackManagerForLLMRunCallbackManagerForLLMRun)LanguageModelInput)BaseChatModelagenerate_from_streamgenerate_from_stream)create_base_retry_decorator)AIMessageChunkBaseMessageBaseMessageChunkChatMessageChunkFunctionMessageChunkHumanMessageChunkSystemMessageChunkToolMessageChunk)ChatGenerationChatGenerationChunk
ChatResult)Runnable)BaseTool)get_from_dict_or_envget_pydantic_field_namespre_init)	BaseModel
ConfigDictFieldmodel_validator)convert_dict_to_messageconvert_message_to_dict)is_openai_v1returnr   c                  C  s&   zdd l } W | S  ty   tdw )Nr   zCould not import tiktoken python package. This is needed in order to calculate get_token_ids. Please install it with `pip install tiktoken`.)tiktokenImportError)r0    r2   ]/var/www/html/lang_env/lib/python3.10/site-packages/langchain_community/chat_models/openai.py_import_tiktokenF   s   
r4   llm
ChatOpenAIrun_managerHOptional[Union[AsyncCallbackManagerForLLMRun, CallbackManagerForLLMRun]]Callable[[Any], Any]c                 C  s:   dd l }|jj|jj|jj|jj|jjg}t|| j|dS )Nr   )Zerror_typesmax_retriesr7   )	openaierrorTimeoutZAPIErrorZAPIConnectionErrorZRateLimitErrorZServiceUnavailableErrorr   r:   )r5   r7   r;   errorsr2   r2   r3   _create_retry_decoratorR   s   r?   'Optional[AsyncCallbackManagerForLLMRun]kwargsc                   sR   t  r jjdi |I dH S t |d}|d	 fdd}|di |I dH S )
z0Use tenacity to retry the async completion call.Nr7   rA   r   r/   c                    s    j jdi | I d H S Nr2   )clientZacreaterA   r5   r2   r3   _completion_with_retryq   s   z6acompletion_with_retry.<locals>._completion_with_retryr2   rA   r   r/   r   )r.   async_clientcreater?   )r5   r7   rA   retry_decoratorrG   r2   rF   r3   acompletion_with_retryf   s   rL   _dictMapping[str, Any]default_classType[BaseMessageChunk]r   c                 C  s  |  d}|  dpd}i }|  dr+t| d }d|v r'|d d u r'd|d< ||d< |  dr6| d |d< |dks>|tkrCt|dS |d	ksK|tkrQt||d
S |dksY|tkr^t|dS |dksf|tkrnt|| d dS |dksv|tkr~t|| d dS |s|tkrt||dS ||dS )Nrolecontent function_callnameZ
tool_callsuser)rR   Z	assistant)rR   additional_kwargssystemfunction)rR   rU   Ztooltool_call_id)rR   rZ   )rR   rQ   )getdictr   r   r   r   r   r   )rM   rO   rQ   rR   rW   rT   r2   r2   r3   _convert_delta_to_message_chunky   s.   





r]   overall_token_usageUnion[int, dict]	new_usagec                   s   t |trt  tstdt| dt  |  S t |tr?t  ts4tdt| dt   fdd| D S tdt|  |S )Nz%Got different types for token usage: z and c                   s$   i | ]\}}|t  |d |qS )r   )_update_token_usager[   ).0kvr^   r2   r3   
<dictcomp>   s    z'_update_token_usage.<locals>.<dictcomp>z!Unexpected type for token usage: )
isinstanceint
ValueErrortyper\   itemswarningswarn)r^   r`   r2   re   r3   ra      s0   




ra   z0.0.10z1.0zlangchain_openai.ChatOpenAI)ZsinceZremovalZalternative_importc                      s  e Zd ZU dZedddZedddZedd
dZedddZ	e
dddZded< e
dddZded< e
dddZded< 	 dZded< 	 e
edZd	ed< 	 e
dddZd ed!< 	 e
dd"dZd ed#< 	 e
dd$dZd ed%< 	 dZd ed&< e
dd'dZd(ed)< 	 e
d*d+Zd,ed-< 	 d.Zded/< 	 d0Zd,ed1< 	 dZd2ed3< 	 dZd ed4< 	 dZd5ed6< dZd7ed8< dZd9ed:< 	 edd;Z e!d<d=edd?d@Z"e#ddBdCZ$eddDdEZ%	dddIdJZ&ddNdOZ'		dddUdVZ(			dddZd[Z)dd]d^Z*ddadbZ+		dddedfZ,			dddgdhZ-eddidjZ.eddkdlZ/	dd fdmdnZ0eddodpZ1ddrdsZ2d fdvdwZ3	dd fdzd{Z4	dd fddZ5  Z6S )r6   a  `OpenAI` Chat large language models API.

    To use, you should have the ``openai`` python package installed, and the
    environment variable ``OPENAI_API_KEY`` set with your API key.

    Any parameters that are valid to be passed to the openai.create call can be passed
    in, even if not explicitly saved on this class.

    Example:
        .. code-block:: python

            from langchain_community.chat_models import ChatOpenAI
            openai = ChatOpenAI(model="gpt-3.5-turbo")
    r/   Dict[str, str]c                 C  s   ddiS )Nopenai_api_keyOPENAI_API_KEYr2   selfr2   r2   r3   
lc_secrets   s   zChatOpenAI.lc_secrets	List[str]c                 C  s   g dS )z*Get the namespace of the langchain object.)Z	langchainZchat_modelsr;   r2   clsr2   r2   r3   get_lc_namespace   s   zChatOpenAI.get_lc_namespaceDict[str, Any]c                 C  s8   i }| j r
| j |d< | jr| j|d< | jr| j|d< |S )Nopenai_organizationopenai_api_baseopenai_proxy)ry   rz   r{   )rr   
attributesr2   r2   r3   lc_attributes   s   


zChatOpenAI.lc_attributesboolc                 C     dS )z9Return whether this model can be serialized by Langchain.Tr2   ru   r2   r2   r3   is_lc_serializable      zChatOpenAI.is_lc_serializableNT)defaultexcluder   rD   rI   gpt-3.5-turbomodel)r   aliasstr
model_namegffffff?floattemperature)default_factorymodel_kwargsapi_keyOptional[str]ro   base_urlrz   organizationry   r{   timeoutz,Union[float, Tuple[float, float], Any, None]request_timeout   r   rh   r:   F	streaming   nzOptional[int]
max_tokenstiktoken_model_namezUnion[Mapping[str, str], None]default_headersz!Union[Mapping[str, object], None]default_queryzUnion[Any, None]http_client)Zpopulate_by_namebefore)modevaluesc              
   C  s   t | }|di }t|D ](}||v rtd| d||vr6td| d| d| d ||||< q|| }|rHtd| d	||d< |S )
z>Build extra kwargs from additional params that were passed in.r   zFound z supplied twice.z	WARNING! z/ is not default parameter.
                    zJ was transferred to model_kwargs.
                    Please confirm that z is what you intended.zParameters za should be specified explicitly. Instead they were passed in as part of `model_kwargs` parameter.)	r&   r[   listri   loggerwarningpopintersectionkeys)rv   r   Zall_required_field_namesextra
field_nameZinvalid_model_kwargsr2   r2   r3   build_extra  s,   
zChatOpenAI.build_extrar   c              	   C  sP  |d dk r
t d|d dkr|d rt dt|dd|d< |d p-td	p-td
|d< |d p8td|d< t|dddd|d< zddl}W n tyV   tdw t r|d |d |d |d |d |d |d |d d}|ds|jdi |j	j
|d< |ds|jdi |j	j
|d< |S |ds|j|d< |S 	 |S )z?Validate that api key and python package exists in environment.r   r   zn must be at least 1.r   zn must be 1 when streaming.ro   rp   ry   ZOPENAI_ORG_IDZOPENAI_ORGANIZATIONrz   ZOPENAI_API_BASEr{   ZOPENAI_PROXYrS   r   r   NzTCould not import openai python package. Please install it with `pip install openai`.r   r:   r   r   r   )r   r   r   r   r:   r   r   r   rD   rI   r2   )ri   r%   osgetenvr;   r1   r.   r[   ZOpenAIZchatZcompletionsZAsyncOpenAIZChatCompletion)rv   r   r;   Zclient_paramsr2   r2   r3   validate_environment3  sh   




zChatOpenAI.validate_environmentc                 C  sN   | j | j| j| jd| j}| jdur| j|d< | jdur%t s%| j|d< |S )z2Get the default parameters for calling OpenAI API.)r   streamr   r   Nr   r   )r   r   r   r   r   r   r   r.   )rr   paramsr2   r2   r3   _default_paramsn  s   


zChatOpenAI._default_paramsr7   "Optional[CallbackManagerForLLMRun]rA   c                   sD   t  r jjdi |S t |d}|d	 fdd}|di |S )
z*Use tenacity to retry the completion call.rB   rA   r   r/   c                    s    j jdi | S rC   )rD   rJ   rE   rq   r2   r3   rG     s   z@ChatOpenAI.completion_with_retry.<locals>._completion_with_retryNr2   rH   )r.   rD   rJ   r?   )rr   r7   rA   rK   rG   r2   rq   r3   completion_with_retry~  s   z ChatOpenAI.completion_with_retryllm_outputsList[Optional[dict]]r\   c           	      C  s   i }d }|D ]3}|d u rq|d }|d ur0|  D ]\}}||v r+t|| |||< q|||< q|d u r9|d}q|| jd}|rF||d< |S )Ntoken_usagesystem_fingerprint)r   r   )rk   ra   r[   r   )	rr   r   r^   r   outputr   rc   rd   combinedr2   r2   r3   _combine_llm_outputs  s(   


zChatOpenAI._combine_llm_outputsmessagesList[BaseMessage]stopOptional[List[str]]Iterator[ChatGenerationChunk]c                 k  s    |  ||\}}i ||ddi}t}| jd||d|D ]N}t|ts+| }t|d dkr4q |d d }	|	d d u rAq t|	d |}|	d}
|
d urVt|
dnd }|j}t	||d	}|rk|j
|j|d
 |V  q d S )Nr   Tr   r7   choicesr   deltafinish_reasonr   messagegeneration_info)chunkr2   )_create_message_dictsr   r   rg   r\   lenr]   r[   	__class__r!   on_llm_new_tokentextrr   r   r   r7   rA   message_dictsr   Zdefault_chunk_classr   choicer   r   Zcg_chunkr2   r2   r3   _stream  s<   


zChatOpenAI._streamr   Optional[bool]r"   c                 K  s   |d ur|n| j }|r| j|f||d|}t|S | ||\}}	i |	|d ur.d|ini |}	| jd||d|	}
| |
S )Nr   r7   r   r   r2   )r   r   r   r   r   _create_chat_resultrr   r   r   r7   r   rA   Zshould_streamZstream_iterr   r   responser2   r2   r3   	_generate  s0   
zChatOpenAI._generate+Tuple[List[Dict[str, Any]], Dict[str, Any]]c                 C  s<   | j }|d urd|v rtd||d< dd |D }||fS )Nr   z2`stop` found in both the input and default params.c                 S     g | ]}t |qS r2   r-   rb   mr2   r2   r3   
<listcomp>      z4ChatOpenAI._create_message_dicts.<locals>.<listcomp>)_client_paramsri   )rr   r   r   r   r   r2   r2   r3   r     s   z ChatOpenAI._create_message_dictsr   Union[dict, BaseModel]c           	      C  s   g }t |ts| }|d D ]%}t|d }t|dd}d|v r)|d |d< t||d}|| q|di }|| j|dd	d
}t||dS )Nr   r   r   r   Zlogprobsr   usager   rS   )r   r   r   )generations
llm_output)rg   r\   r,   r[   r    appendr   r"   )	rr   r   r   resr   r   genr   r   r2   r2   r3   r     s&   

zChatOpenAI._create_chat_resultr@   "AsyncIterator[ChatGenerationChunk]c                 K s   |  ||\}}i ||ddi}t}t| f||d|I d H 2 zU3 d H W }t|ts2| }t|d dkr;q#|d d }	|	d d u rHq#t|	d |}|	d}
|
d ur]t|
dnd }|j}t	||d	}|ru|j
|j|d
I d H  |V  q#6 d S )Nr   Tr   r   r   r   r   r   r   )tokenr   )r   r   rL   rg   r\   r   r]   r[   r   r!   r   r   r   r2   r2   r3   _astream  s@   

zChatOpenAI._astreamc                   s   |d ur|n| j }|r| j|f||d|}t|I d H S | ||\}}	i |	|d ur2d|ini |}	t| f||d|	I d H }
| |
S )Nr   r   r   )r   r   r   r   rL   r   r   r2   r2   r3   
_agenerate&  s6   
zChatOpenAI._ageneratec                 C  s   i d| j i| jS )zGet the identifying parameters.r   )r   r   rq   r2   r2   r3   _identifying_params@  s   zChatOpenAI._identifying_paramsc                 C  sT   d| j i}t s|| j| j| jd | jr#ddl}| j| jd|_i | j	|S )z.Get the parameters used for the openai client.r   )r   Zapi_baser   r   N)httphttps)
r   r.   updatero   rz   ry   r{   r;   proxyr   )rr   Zopenai_credsr;   r2   r2   r3   r   E  s   zChatOpenAI._client_paramsc                   s"   d| j it j|d| j|S )z,Get the parameters used to invoke the model.r   )r   )r   super_get_invocation_paramsr   )rr   r   rA   r   r2   r3   r   Y  s   z!ChatOpenAI._get_invocation_paramsc                 C  r   )zReturn type of chat model.zopenai-chatr2   rq   r2   r2   r3   	_llm_typed  r   zChatOpenAI._llm_typeTuple[str, tiktoken.Encoding]c                 C  s~   t  }| jd ur| j}n| j}|dkrd}n|dkrd}z
||}W ||fS  ty>   td d}||}Y ||fS w )Nr   gpt-3.5-turbo-0301gpt-4z
gpt-4-0314z5Warning: model not found. Using cl100k_base encoding.Zcl100k_base)r4   r   r   Zencoding_for_modelKeyErrorr   r   Zget_encoding)rr   Z	tiktoken_r   encodingr2   r2   r3   _get_encoding_modeli  s"   

zChatOpenAI._get_encoding_modelr   	List[int]c                   s0   t jd dkrt |S |  \}}||S )z9Get the tokens present in the text with tiktoken package.r      )sysversion_infor   get_token_idsr   encode)rr   r   _Zencoding_modelr   r2   r3   r     s   
zChatOpenAI.get_token_idstoolsCOptional[Sequence[Union[Dict[str, Any], Type, Callable, BaseTool]]]c                   s   |dur	t d tjd dkrt |S |  \}}|dr&d}d}n|ds0|d	r5d
}d}ntd| dd}dd |D }|D ]"}	||7 }|		 D ]\}
}|t
|t|7 }|
dkri||7 }qRqH|d
7 }|S )zCalculate num tokens for gpt-3.5-turbo and gpt-4 with tiktoken package.

        Official documentation: https://github.com/openai/openai-cookbook/blob/
        main/examples/How_to_format_inputs_to_ChatGPT_models.ipynbNzECounting tokens in tool schemas is not yet supported. Ignoring tools.r   r   r      r   r      zFget_num_tokens_from_messages() is not presently implemented for model zy.See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens.r   c                 S  r   r2   r   r   r2   r2   r3   r     r   z;ChatOpenAI.get_num_tokens_from_messages.<locals>.<listcomp>rU   )rl   rm   r   r   r   get_num_tokens_from_messagesr   
startswithNotImplementedErrorrk   r   r   r   )rr   r   r   r   r   Ztokens_per_messageZtokens_per_nameZ
num_tokensZmessages_dictr   keyvaluer   r2   r3   r    s<   
z'ChatOpenAI.get_num_tokens_from_messages	functions:Sequence[Union[Dict[str, Any], Type[BaseModel], Callable]]rT   )Runnable[LanguageModelInput, BaseMessage]c                   s   ddl m   fdd|D }|dur@t|dkrtd|d d |kr4td	| d
|d d  dd|i}i |d|i}t jdd|i|S )a  Bind functions (and other objects) to this chat model.

        Args:
            functions: A list of function definitions to bind to this chat model.
                Can be  a dictionary, pydantic model, or callable. Pydantic
                models and callables will be automatically converted to
                their schema dictionary representation.
            function_call: Which function to require the model to call.
                Must be the name of the single provided function or
                "auto" to automatically determine which function to call
                (if any).
            kwargs: Any additional parameters to pass to the
                :class:`~langchain.runnable.Runnable` constructor.
        r   convert_to_openai_functionc                   s   g | ]} |qS r2   r2   )rb   fnr  r2   r3   r     r   z-ChatOpenAI.bind_functions.<locals>.<listcomp>Nr   zGWhen specifying `function_call`, you must provide exactly one function.rU   zFunction call z3 was specified, but the only provided function was .rT   r  r2   )Z&langchain.chains.openai_functions.baser  r   ri   r   bind)rr   r  rT   rA   Zformatted_functionsZfunction_call_r   r  r3   bind_functions  s(   

zChatOpenAI.bind_functions)r/   rn   )r/   rt   )r/   rx   )r/   r~   )r   rx   r/   r   )r   r   r/   r   N)r7   r   rA   r   r/   r   )r   r   r/   r\   )NN)
r   r   r   r   r7   r   rA   r   r/   r   )NNN)r   r   r   r   r7   r   r   r   rA   r   r/   r"   )r   r   r   r   r/   r   )r   r   r/   r"   )
r   r   r   r   r7   r@   rA   r   r/   r   )r   r   r   r   r7   r@   r   r   rA   r   r/   r"   )r   r   rA   r   r/   rx   )r/   r   )r/   r   )r   r   r/   r   )r   r   r   r   r/   rh   )r  r	  rT   r   rA   r   r/   r
  )7__name__
__module____qualname____doc__propertyrs   classmethodrw   r}   r   r*   rD   __annotations__rI   r   r   r\   r   ro   rz   ry   r{   r   r:   r   r   r   r   r   r   r   r)   Zmodel_configr+   r   r'   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  __classcell__r2   r2   r   r3   r6      s   
 	:
'

'
2)r/   r   r  )r5   r6   r7   r8   r/   r9   )r5   r6   r7   r@   rA   r   r/   r   )rM   rN   rO   rP   r/   r   )r^   r_   r`   r_   r/   r_   )Kr  
__future__r   loggingr   r   rl   typingr   r   r   r   r   r   r	   r
   r   r   r   r   r   Zlangchain_core._api.deprecationr   Zlangchain_core.callbacksr   r   Zlangchain_core.language_modelsr   Z*langchain_core.language_models.chat_modelsr   r   r   Z#langchain_core.language_models.llmsr   Zlangchain_core.messagesr   r   r   r   r   r   r   r   Zlangchain_core.outputsr    r!   r"   Zlangchain_core.runnablesr#   Zlangchain_core.toolsr$   Zlangchain_core.utilsr%   r&   r'   Zpydanticr(   r)   r*   r+   Z#langchain_community.adapters.openair,   r-   Z langchain_community.utils.openair.   r0   	getLoggerr  r   r4   r?   rL   r]   ra   r6   r2   r2   r2   r3   <module>   sD    <(




