o
    {qiiy                     @  s  d Z ddlmZ ddlZddlZddlmZmZmZm	Z	 ddl
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,Z-dS ) zQBase classes for OpenAI large language models. Chat models are in `chat_models/`.    )annotationsN)AsyncIterator
CollectionIteratorMapping)AnyLiteralOptional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$   a/home/app/PaddleOCR-VL/.venv_paddleocr/lib/python3.10/site-packages/langchain_openai/llms/base.py_update_token_usage   s   r&   stream_responser   c                 C  sT   | d s	t ddS t | d d d pd| 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r+   r,   r*   generation_info)r   get)r'   r$   r$   r%   $_stream_response_to_generation_chunk&   s   
r1   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 )
BaseOpenAIu  Base OpenAI large language model class.

    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_name: str
            Name of OpenAI model to use.
        temperature: float
            Sampling temperature.
        max_tokens: int
            Max number of tokens to generate.
        top_p: float
            Total probability mass of tokens to consider at each step.
        frequency_penalty: float
            Penalizes repeated tokens according to frequency.
        presence_penalty: float
            Penalizes repeated tokens.
        n: int
            How many completions to generate for each prompt.
        best_of: int
            Generates best_of completions server-side and returns the "best".
        logit_bias: Optional[dict[str, float]]
            Adjust the probability of specific tokens being generated.
        seed: Optional[int]
            Seed for generation.
        logprobs: Optional[int]
            Include the log probabilities on the logprobs most likely output tokens.
        streaming: bool
            Whether to stream the results or not.

    Key init args — client params:
        openai_api_key: Optional[SecretStr]
            OpenAI API key. If not passed in will be read from env var
            ``OPENAI_API_KEY``.
        openai_api_base: Optional[str]
            Base URL path for API requests, leave blank if not using a proxy or
            service emulator.
        openai_organization: Optional[str]
            OpenAI organization ID. If not passed in will be read from env
            var ``OPENAI_ORG_ID``.
        request_timeout: Union[float, tuple[float, float], Any, None]
            Timeout for requests to OpenAI completion API.
        max_retries: int
            Maximum number of retries to make when generating.
        batch_size: int
            Batch size to use when passing multiple documents to generate.

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

    Instantiate:
        .. code-block:: python

            from langchain_openai.llms.base import BaseOpenAI

            llm = BaseOpenAI(
                model_name="gpt-3.5-turbo-instruct",
                temperature=0.7,
                max_tokens=256,
                top_p=1,
                frequency_penalty=0,
                presence_penalty=0,
                # openai_api_key="...",
                # openai_api_base="...",
                # openai_organization="...",
                # other params...
            )

    Invoke:
        .. code-block:: python

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

        .. code-block::

            "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::

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

    Async:
        .. code-block:: python

            response = await llm.ainvoke(input_text)

            # stream:
            # async for chunk in llm.astream(input_text):
            #     print(chunk, end="")

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

        .. code-block::

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

    NT)defaultexcluder   clientasync_clientgpt-3.5-turbo-instructmodel)r3   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)r3   )r9   rG   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]seedr,   Fbool	streamingzUnion[Literal['all'], set[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   )clsrg   Zall_required_field_namesr$   r$   r%   build_extra  s   
zBaseOpenAI.build_extraafterr   c                 C  s   | j dk rd}t|| jr| j dkrd}t|| jr'| jdkr'd}t|| jr/| j nd| j| j| j| j	| j
| jd}| jsSd| ji}tjdi ||j| _| jsgd| ji}tjdi ||j| _| S )	z?Validate that api key and python package exists in environment.rA   zn must be at least 1.z!Cannot stream results when n > 1.z'Cannot stream results when best_of > 1.N)rI   rO   rL   rT   rX   r`   ra   rb   r$   )rE   
ValueErrorr[   rF   rK   Zget_secret_valuerP   rN   rU   rX   r`   ra   r5   rb   openaiOpenAIZcompletionsr6   rc   ZAsyncOpenAI)selfmsgZclient_paramsZsync_specificZasync_specificr$   r$   r%   validate_environment  s<   


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.)r=   rB   rC   rD   rE   rY   r,   NrV   r@   rd   rA   rF   )r=   rB   rC   rD   rE   rY   r,   rV   r@   rd   rF   rH   )rn   Znormal_paramsr$   r$   r%   _default_params0  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streamTrr   r,   )chunkverboser,   r$   )_invocation_paramsget_sub_promptsr5   create
isinstancedict
model_dumpr1   on_llm_new_tokenr*   r|   r/   rn   rr   rs   ru   rw   paramsZstream_respr{   r$   r$   r%   _streamM  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 ry   )r}   r~   r6   r   r   r   r   r1   r   r*   r|   r/   r   r$   r$   r%   _astreamh  s,   


zBaseOpenAI._astreamprompts	list[str]r   c                 K  s`  | j }i ||}| |||}g }i }h d}	d}
|D ]}| jrqt|dkr-d}t|d}| j|d ||fi |D ]}|du rE|}q<||7 }q<|du rTd}t|||j|jra|j	dnd|jrk|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 )a  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.
            run_manager: Optional callback manager to use for the call.

        Returns:
            The full LLM output.

        Example:
            .. code-block:: python

                response = openai.generate(["Tell me a joke."])

           Zcompletion_tokensZprompt_tokensZtotal_tokensNrA   ,Cannot stream results with multiple prompts.r   $Generation is empty after streaming.r+   r,   r*   r+   r,   rr   errorr(   system_fingerprintr   r$   )r}   r~   r[   lenrk   r   appendr*   r/   r0   r5   r   r   r   r   extendr&   create_llm_resultrn   r   rs   ru   rw   r   Zsub_promptsr(   r   Z_keysr   Z_promptsro   Z
generationr{   r   r$   r$   r%   	_generate  sV   




zBaseOpenAI._generatec                   sL  | j }i ||}| |||}g }i }h d}	d}
|D ]~}| jrwt|dkr.d}t|d}| j|d ||fi |2 z3 dH W }|du rJ|}q=||7 }q=6 |du rZd}t|||j|jrg|j	dnd|jrq|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   NrA   r   r   r   r+   r,   r   rr   r(   r   r$   )r}   r~   r[   r   rk   r   r   r*   r/   r0   r6   r   r   r   r   r   r&   r   r   r$   r$   r%   
_agenerate  sX   



zBaseOpenAI._agenerater   list[list[str]]c                   sh   |dur||d< |d dkr#t  dkrd}t| d |d<  fdd	tdt  jD S )
z!Get the sub prompts for llm call.Nrs   r@   rA   z7max_tokens set to -1 not supported for multiple inputs.r   c                   s   g | ]} ||j   qS r$   )rS   ).0ir   rn   r$   r%   
<listcomp>#  s    z.BaseOpenAI.get_sub_prompts.<locals>.<listcomp>)r   rk   max_tokens_for_promptrangerS   )rn   r   r   rs   ro   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.rE   rA   c                 S  s.   g | ]}t |d  |d|dddqS )r*   r+   r,   r-   r.   )r   r0   )r   choicer$   r$   r%   r   7  s    z0BaseOpenAI.create_llm_result.<locals>.<listcomp>)r   r;   r   )generations
llm_output)r0   rE   	enumerater   r;   r   )rn   r(   r   r   r   r   r   rE   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.)rq   rn   r$   r$   r%   r}   G  s   zBaseOpenAI._invocation_paramsMapping[str, Any]c                 C  s   d| j i| jS )zGet the identifying parameters.r;   )r;   rq   r   r$   r$   r%   _identifying_paramsL  s   zBaseOpenAI._identifying_paramsc                 C     dS )zReturn type of llm.rl   r$   r   r$   r$   r%   	_llm_typeQ     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.NrA      Zcl100k_base)r\   r^   )Zcustom_get_token_idssysversion_infosuperget_num_tokensr_   r;   tiktokenZencoding_for_modelKeyErrorZget_encodingencoder\   r^   )rn   r*   r;   enc	__class__r$   r%   get_token_idsV  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 u rftd!|  d"d#|  |S )$ap  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-0613r7   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, )splitr0   rk   joinr   )r   Zmodel_token_mappingZcontext_sizer$   r$   r%   modelname_to_contextsizej  sr   	
 

z#BaseOpenAI.modelname_to_contextsizec                 C  s   |  | jS )z$Get max context size for this model.)r   r;   r   r$   r$   r%   max_context_size  s   zBaseOpenAI.max_context_sizec                 C  s   |  |}| j| S )aq  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   )rn   rr   Z
num_tokensr$   r$   r%   r     s   

z BaseOpenAI.max_tokens_for_prompt)rg   r   r   r   )r   r   r   r   )NN)
rr   r:   rs   rt   ru   rv   rw   r   r   rx   )
rr   r:   rs   rt   ru   r   rw   r   r   r   )
r   r   rs   rt   ru   rv   rw   r   r   r   )
r   r   rs   rt   ru   r   rw   r   r   r   )N)r   r   r   r   rs   rt   r   r   )r(   r   r   r   r   r   r   r   r   rM   r   r   )r   r   )r   r:   )r*   r:   r   r   )r   r:   r   r?   )r   r?   )rr   r:   r   r?   )?__name__
__module____qualname____doc__r   r5   __annotations__r6   r;   r=   r@   rB   rC   rD   rE   rF   r   rH   r   rK   r   rN   rP   rQ   rS   rU   rV   rX   rY   r,   r[   setr\   r^   r_   r`   ra   rb   rc   rd   r   Zmodel_configr   classmethodri   rp   propertyrq   r   r   r   r   r~   r   r}   r   r   r   staticmethodr   r   r   __classcell__r$   r$   r   r%   r2   5   s   
 s
	
# X?<r2   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 )rm   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::

            "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::

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

        .. code-block:: python

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

        .. code-block::

            "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::

            "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llmsrl   r$   rh   r$   r$   r%   get_lc_namespace$     zOpenAI.get_lc_namespacerZ   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   d| j it jS )Nr8   )r;   r   r}   r   r   r$   r%   r}   .  s   zOpenAI._invocation_paramsdict[str, str]c                 C  s   ddiS )z0Mapping of secret keys to environment variables.rK   rJ   r$   r   r$   r$   r%   
lc_secrets2  r   zOpenAI.lc_secretsc                 C  s8   i }| j r
| j |d< | jr| j|d< | jr| j|d< |S )z$LangChain attributes for this class.rN   rP   rQ   )rN   rP   rQ   )rn   
attributesr$   r$   r%   lc_attributes7  s   


zOpenAI.lc_attributes)r   r   )r   rZ   r   )r   r   )r   r   r   r   r   r   r   r   r}   r   r   r   r$   r$   r   r%   rm     s    drm   )r   r   r   r   r   r   r   r    )r'   r   r   r   ).r   
__future__r   loggingr   collections.abcr   r   r   r   typingr   r   r	   r
   rl   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&   r1   r2   rm   r$   r$   r$   r%   <module>   s2    


     