o
    Zh,i                     @  s  d dl m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Zd dl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" d d	l#m$Z$m%Z%m&Z&m'Z' d d
l(m)Z) e*e+Z,dddZ-dddZ.G dd deZ/G dd de/Z0dS )    )annotationsN)AbstractSetAnyAsyncIterator
CollectionDictIteratorListLiteralMappingOptionalSetTupleUnion)AsyncCallbackManagerForLLMRunCallbackManagerForLLMRun)BaseLLM)
GenerationGenerationChunk	LLMResult)get_pydantic_field_names)_build_model_kwargsfrom_envsecret_from_env)
ConfigDictField	SecretStrmodel_validator)SelfkeysSet[str]responseDict[str, Any]token_usagereturnNonec                 C  sN   |  |d }|D ]}||vr|d | ||< q	||  |d | 7  < q	dS )zUpdate token usage.usageN)intersection)r   r!   r#   Z_keys_to_use_key r)   Q/var/www/html/lang_env/lib/python3.10/site-packages/langchain_openai/llms/base.py_update_token_usage%   s   r+   stream_responser   c                 C  sR   | d s	t ddS t | d d d t| d d dd| d d ddd	d
S )z0Convert a stream response to a generation chunk.choices )textr   r/   finish_reasonNlogprobsr0   r1   r/   generation_info)r   dictget)r,   r)   r)   r*   $_stream_response_to_generation_chunk1   s   
r7   c                      s  e Zd ZU 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< 	 dZ
ded< 	 dZded< 	 dZded< 	 dZded< 	 dZded< 	 dZded< 	 eedZded< 	 ededddd Zd!ed"< 	 ed#ed$ddd Zd%ed&< 	 ed'ed(d)gddd Zd%ed*< 	 eed+dddZd%ed,< d-Zded.< 	 edd/d
Zd0ed1< 	 dZd2ed3< 	 d4Zded5< 	 dZd6ed7< 	 dZd6ed8< 	 d9Zd:ed;< 	 e Z d<ed=< 	 d>Z!d?ed@< 	 dZ"d%edA< 	 dZ#dBedC< dZ$dDedE< dZ%dFedG< 	 dZ&dFedH< 	 dZ'dIedJ< 	 e(ddKZ)e*dLdMe+ddPdQZ,e*dRdMddTdUZ-e.ddVdWZ/		ddd_d`Z0		dddcddZ1		dddhdiZ2		dddjdkZ3	dddndoZ4ddpddudvZ5e.ddwdxZ6e.ddzd{Z7e.dd|d}Z8d fddZ9e:dddZ;e.dddZ<dddZ=  Z>S )
BaseOpenAIz'Base OpenAI large language model class.NT)defaultexcluder   clientasync_clientgpt-3.5-turbo-instructmodel)r9   aliasstr
model_namegffffff?floattemperature   int
max_tokens   top_pr   frequency_penaltypresence_penaltynbest_of)default_factoryr"   model_kwargsapi_keyOPENAI_API_KEY)r9   )r?   rM   zOptional[SecretStr]openai_api_keybase_urlZOPENAI_API_BASEOptional[str]openai_api_baseorganizationZOPENAI_ORG_IDZOPENAI_ORGANIZATIONopenai_organizationZOPENAI_PROXYopenai_proxy   
batch_sizetimeoutz,Union[float, Tuple[float, float], Any, None]request_timeoutzOptional[Dict[str, float]]
logit_bias   max_retrieszOptional[int]seedr1   Fbool	streamingz'Union[Literal['all'], AbstractSet[str]]allowed_specialallz&Union[Literal['all'], Collection[str]]disallowed_specialtiktoken_model_namezUnion[Mapping[str, str], None]default_headersz!Union[Mapping[str, object], None]default_queryzUnion[Any, None]http_clienthttp_async_clientzOptional[Mapping[str, Any]]
extra_body)Zpopulate_by_namebefore)modevaluesr$   c                 C  s   t | }t||}|S )z>Build extra kwargs from additional params that were passed in.)r   r   )clsrm   Zall_required_field_namesr)   r)   r*   build_extra   s   
zBaseOpenAI.build_extraafterr   c                 C  s   | j dk r	td| jr| j dkrtd| jr!| jdkr!td| jr)| j nd| j| j| j| j	| j
| jd}| jsMd| ji}tjdi ||j| _| jsad| ji}tjdi ||j| _| S )	z?Validate that api key and python package exists in environment.rG   zn must be at least 1.z!Cannot stream results when n > 1.z'Cannot stream results when best_of > 1.N)rO   rU   rR   rZ   r^   rf   rg   rh   r)   )rK   
ValueErrorra   rL   rQ   Zget_secret_valuerV   rT   r[   r^   rf   rg   r;   rh   openaiOpenAIZcompletionsr<   ri   ZAsyncOpenAI)selfZclient_paramsZsync_specificZasync_specificr)   r)   r*   validate_environment   s6   


zBaseOpenAI.validate_environmentc                 C  s   | j | j| j| j| j| j| jd}| jdur| j|d< | jdur%| j|d< | j	dur/| j	|d< | j
dkr9| j
|d< i || jS )z2Get the default parameters for calling OpenAI API.)rC   rH   rI   rJ   rK   r_   r1   Nr\   rF   rj   rG   rL   )rC   rH   rI   rJ   rK   r_   r1   r\   rF   rj   rL   rN   )rt   Znormal_paramsr)   r)   r*   _default_params   s"   








zBaseOpenAI._default_paramspromptstopOptional[List[str]]run_manager"Optional[CallbackManagerForLLMRun]kwargsIterator[GenerationChunk]c                 k  s    i | j |ddi}| ||g| | jjdd|i|D ]'}t|ts*| }t|}|rC|j|j	|| j
|jr?|jd nd d |V  qd S NstreamTrw   r1   )chunkverboser1   r)   )_invocation_paramsget_sub_promptsr;   create
isinstancer5   
model_dumpr7   on_llm_new_tokenr/   r   r4   rt   rw   rx   rz   r|   paramsZstream_respr   r)   r)   r*   _stream   s$   

zBaseOpenAI._stream'Optional[AsyncCallbackManagerForLLMRun]AsyncIterator[GenerationChunk]c                 K s   i | j |ddi}| ||g| | jjdd|i|I d H 2 z.3 d H W }t|ts1| }t|}|rM|j|j	|| j
|jrF|jd nd dI d H  |V  q"6 d S r~   )r   r   r<   r   r   r5   r   r7   r   r/   r   r4   r   r)   r)   r*   _astream   s,   


zBaseOpenAI._astreamprompts	List[str]r   c                 K  sT  | j }i ||}| |||}g }i }h d}	d}
|D ]}| jrkt|dkr+tdd}| j|d ||fi |D ]}|du rC|}q:||7 }q:|dusNJ ||j|jr[|j	dnd|jre|j	dndd q| j
jdd	|i|}t|ts| }|	d
rt|	d
||d  t|	|| |
s|	d}
q| j|||||
dS )at  Call out to OpenAI's endpoint with k unique prompts.

        Args:
            prompts: The prompts to pass into the model.
            stop: Optional list of stop words to use when generating.

        Returns:
            The full LLM output.

        Example:
            .. code-block:: python

                response = openai.generate(["Tell me a joke."])
           Zcompletion_tokensZprompt_tokensZtotal_tokensNrG   ,Cannot stream results with multiple prompts.r   r0   r1   r/   r0   r1   rw   errorr-   system_fingerprintr   r)   )r   r   ra   lenrq   r   appendr/   r4   r6   r;   r   r   r5   r   extendr+   create_llm_resultrt   r   rx   rz   r|   r   sub_promptsr-   r#   Z_keysr   Z_promptsZ
generationr   r!   r)   r)   r*   	_generate  sP   




zBaseOpenAI._generatec                   s@  | j }i ||}| |||}g }i }h d}	d}
|D ]x}| jrqt|dkr,tdd}| j|d ||fi |2 z3 dH W }|du rH|}q;||7 }q;6 |dusTJ ||j|jra|j	dnd|jrk|j	dndd q| j
jdd	|i|I dH }t|ts| }||d
  t|	|| q| j|||||
dS )z:Call out to OpenAI's endpoint async with k unique prompts.r   NrG   r   r   r0   r1   r   rw   r-   r   r)   )r   r   ra   r   rq   r   r   r/   r4   r6   r<   r   r   r5   r   r   r+   r   r   r)   r)   r*   
_ageneratel  sR   



zBaseOpenAI._agenerater   List[List[str]]c                   sh   |dur||d< |d dkr!t  dkrtd d |d<  fdd	tdt  jD }|S )
z!Get the sub prompts for llm call.Nrx   rF   rG   z7max_tokens set to -1 not supported for multiple inputs.r   c                   s   g | ]} ||j   qS r)   )rY   ).0ir   rt   r)   r*   
<listcomp>  s    z.BaseOpenAI.get_sub_prompts.<locals>.<listcomp>)r   rq   max_tokens_for_promptrangerY   )rt   r   r   rx   r   r)   r   r*   r     s   zBaseOpenAI.get_sub_promptsr   r-   r#   Dict[str, int]r   c                C  st   g }| d| j}t|D ]\}}	||| |d |  }
|dd |
D  q|| jd}|r4||d< t||dS )z2Create the LLMResult from the choices and prompts.rK   rG   c              	   S  s0   g | ]}t |d  t|d|dddqS )r/   r0   r1   r2   r3   )r   r5   r6   )r   choicer)   r)   r*   r     s    z0BaseOpenAI.create_llm_result.<locals>.<listcomp>)r#   rA   r   )generations
llm_output)r6   rK   	enumerater   rA   r   )rt   r-   r   r   r#   r   r   rK   r   _Zsub_choicesr   r)   r)   r*   r     s   
zBaseOpenAI.create_llm_resultc                 C  s   | j S )z,Get the parameters used to invoke the model.)rv   rt   r)   r)   r*   r     s   zBaseOpenAI._invocation_paramsMapping[str, Any]c                 C  s   i d| j i| jS )zGet the identifying parameters.rA   )rA   rv   r   r)   r)   r*   _identifying_params  s   zBaseOpenAI._identifying_paramsc                 C     dS )zReturn type of llm.rr   r)   r   r)   r)   r*   	_llm_type     zBaseOpenAI._llm_typer/   	List[int]c                   sz   | j dur
|  |S tjd dk rt |S | jp| j}zt|}W n t	y2   t
d}Y nw |j|| j| jdS )z-Get the token IDs using the tiktoken package.NrG      Zcl100k_base)rb   rd   )Zcustom_get_token_idssysversion_infosuperget_num_tokensre   rA   tiktokenZencoding_for_modelKeyErrorZget_encodingencoderb   rd   )rt   r/   rA   enc	__class__r)   r*   get_token_ids  s   

zBaseOpenAI.get_token_ids	modelnamec                 C  s   i ddddddddddddd	d
dd
dd
dddddddddddddddddddddddddddd}d| v rN|  dd } || d }|d u rgtd!|  d"d#|  |S )$ao  Calculate the maximum number of tokens possible to generate for a model.

        Args:
            modelname: The modelname we want to know the context size for.

        Returns:
            The maximum context size

        Example:
            .. code-block:: python

                max_tokens = openai.modelname_to_contextsize("gpt-3.5-turbo-instruct")
        zgpt-4o-minii  zgpt-4ozgpt-4o-2024-05-13zgpt-4i    z
gpt-4-0314z
gpt-4-0613z	gpt-4-32ki   zgpt-4-32k-0314zgpt-4-32k-0613zgpt-3.5-turboi   zgpt-3.5-turbo-0301zgpt-3.5-turbo-0613zgpt-3.5-turbo-16ki@  zgpt-3.5-turbo-16k-0613r=   ztext-ada-001i  adai  i  iA  i   )ztext-babbage-001Zbabbageztext-curie-001ZcurieZdavinciztext-davinci-003ztext-davinci-002zcode-davinci-002zcode-davinci-001zcode-cushman-002zcode-cushman-001zft-:r   NzUnknown model: z=. Please provide a valid OpenAI model name.Known models are: z, )splitr6   rq   joinr   )r   Zmodel_token_mappingZcontext_sizer)   r)   r*   modelname_to_contextsize  sr   	
 
z#BaseOpenAI.modelname_to_contextsizec                 C  s   |  | jS )z$Get max context size for this model.)r   rA   r   r)   r)   r*   max_context_size7  s   zBaseOpenAI.max_context_sizec                 C  s   |  |}| j| S )ap  Calculate the maximum number of tokens possible to generate for a prompt.

        Args:
            prompt: The prompt to pass into the model.

        Returns:
            The maximum number of tokens to generate for a prompt.

        Example:
            .. code-block:: python

                max_tokens = openai.max_tokens_for_prompt("Tell me a joke.")
        )r   r   )rt   rw   Z
num_tokensr)   r)   r*   r   <  s   

z BaseOpenAI.max_tokens_for_prompt)rm   r"   r$   r   )r$   r   r$   r"   )NN)
rw   r@   rx   ry   rz   r{   r|   r   r$   r}   )
rw   r@   rx   ry   rz   r   r|   r   r$   r   )
r   r   rx   ry   rz   r{   r|   r   r$   r   )
r   r   rx   ry   rz   r   r|   r   r$   r   )N)r   r"   r   r   rx   ry   r$   r   )r-   r   r   r   r   r"   r#   r   r   rS   r$   r   )r$   r   )r$   r@   )r/   r@   r$   r   )r   r@   r$   rE   )r$   rE   )rw   r@   r$   rE   )?__name__
__module____qualname____doc__r   r;   __annotations__r<   rA   rC   rF   rH   rI   rJ   rK   rL   r5   rN   r   rQ   r   rT   rV   rW   rY   r[   r\   r^   r_   r1   ra   setrb   rd   re   rf   rg   rh   ri   rj   r   Zmodel_configr   classmethodro   ru   propertyrv   r   r   r   r   r   r   r   r   r   r   staticmethodr   r   r   __classcell__r)   r)   r   r*   r8   @   s   
 
	
  S<;r8   c                      s^   e Zd ZdZedddZedddZed fd
dZedddZ	edddZ
  ZS )rs   u  OpenAI completion model integration.

    Setup:
        Install ``langchain-openai`` and set environment variable ``OPENAI_API_KEY``.

        .. code-block:: bash

            pip install -U langchain-openai
            export OPENAI_API_KEY="your-api-key"

    Key init args — completion params:
        model: str
            Name of OpenAI model to use.
        temperature: float
            Sampling temperature.
        max_tokens: Optional[int]
            Max number of tokens to generate.
        logprobs: Optional[bool]
            Whether to return logprobs.
        stream_options: Dict
            Configure streaming outputs, like whether to return token usage when
            streaming (``{"include_usage": True}``).

    Key init args — client params:
        timeout: Union[float, Tuple[float, float], Any, None]
            Timeout for requests.
        max_retries: int
            Max number of retries.
        api_key: Optional[str]
            OpenAI API key. If not passed in will be read from env var OPENAI_API_KEY.
        base_url: Optional[str]
            Base URL for API requests. Only specify if using a proxy or service
            emulator.
        organization: Optional[str]
            OpenAI organization ID. If not passed in will be read from env
            var OPENAI_ORG_ID.

    See full list of supported init args and their descriptions in the params section.

    Instantiate:
        .. code-block:: python

            from langchain_openai import OpenAI

            llm = OpenAI(
                model="gpt-3.5-turbo-instruct",
                temperature=0,
                max_retries=2,
                # api_key="...",
                # base_url="...",
                # organization="...",
                # other params...
            )

    Invoke:
        .. code-block:: python

            input_text = "The meaning of life is "
            llm.invoke(input_text)

        .. code-block:: none

            "a philosophical question that has been debated by thinkers and scholars for centuries."

    Stream:
        .. code-block:: python

            for chunk in llm.stream(input_text):
                print(chunk, end="|")

        .. code-block:: none

            a| philosophical| question| that| has| been| debated| by| thinkers| and| scholars| for| centuries|.

        .. code-block:: python

            "".join(llm.stream(input_text))

        .. code-block:: none

            "a philosophical question that has been debated by thinkers and scholars for centuries."

    Async:
        .. code-block:: python

            await llm.ainvoke(input_text)

            # stream:
            # async for chunk in (await llm.astream(input_text)):
            #    print(chunk)

            # batch:
            # await llm.abatch([input_text])

        .. code-block:: none

            "a philosophical question that has been debated by thinkers and scholars for centuries."

    r$   r   c                 C  s   g dS )z*Get the namespace of the langchain object.)Z	langchainZllmsrr   r)   rn   r)   r)   r*   get_lc_namespace  s   zOpenAI.get_lc_namespacer`   c                 C  r   )z9Return whether this model can be serialized by Langchain.Tr)   r   r)   r)   r*   is_lc_serializable  r   zOpenAI.is_lc_serializabler"   c                   s   i d| j it jS )Nr>   )rA   r   r   r   r   r)   r*   r     s   zOpenAI._invocation_paramsDict[str, str]c                 C  s   ddiS )NrQ   rP   r)   r   r)   r)   r*   
lc_secrets  s   zOpenAI.lc_secretsc                 C  s8   i }| j r
| j |d< | jr| j|d< | jr| j|d< |S )NrT   rV   rW   )rT   rV   rW   )rt   
attributesr)   r)   r*   lc_attributes  s   


zOpenAI.lc_attributes)r$   r   )r$   r`   r   )r$   r   )r   r   r   r   r   r   r   r   r   r   r   r   r)   r)   r   r*   rs   N  s    drs   )r   r    r!   r"   r#   r"   r$   r%   )r,   r"   r$   r   )1
__future__r   loggingr   typingr   r   r   r   r   r   r	   r
   r   r   r   r   r   rr   r   Zlangchain_core.callbacksr   r   Z#langchain_core.language_models.llmsr   Zlangchain_core.outputsr   r   r   Zlangchain_core.utilsr   Zlangchain_core.utils.utilsr   r   r   Zpydanticr   r   r   r   Ztyping_extensionsr   	getLoggerr   loggerr+   r7   r8   rs   r)   r)   r)   r*   <module>   s,    <


    