U
    hTy                     @  s*  d dl m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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 d dl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( d dl)m*Z*m+Z+ d dl,m-Z- dddddgZ.edddddddddddddZ/edAdddddddddddddZ/edBdddddddddddddZ/e dCddddddd ddd!dd"dZ/dd#ddddd$d%d&Z0d'd(d)d*d+d,d-d.d/d0d1d2d3d4hZ1ddd5d6d7Z2dd8d9d:d;Z3dddd<d=d>Z4d?Z5G d@d de#eef Z6dS )D    )annotationsN)util)AnyAsyncIteratorCallableDictIteratorListLiteralOptionalSequenceTupleTypeUnioncastoverload)beta)BaseChatModelLanguageModelInputSimpleChatModel)agenerate_from_streamgenerate_from_stream)
AnyMessageBaseMessage)	BaseModel)RunnableRunnableConfig)StreamEvent)BaseTool)RunLogRunLogPatch)	TypeAliasinit_chat_modelr   r   r   r   )model_providerconfigurable_fieldsconfig_prefixstrzOptional[str]zLiteral[None]r   )modelr#   r$   r%   kwargsreturnc                K  s   d S N r'   r#   r$   r%   r(   r+   r+   >/tmp/pip-unpacked-wheel-bo69hh5q/langchain/chat_models/base.pyr"   2   s    _ConfigurableModelc                K  s   d S r*   r+   r,   r+   r+   r-   r"   =   s    .1Union[Literal['any'], List[str], Tuple[str, ...]]c                K  s   d S r*   r+   r,   r+   r+   r-   r"   H   s    z;Optional[Union[Literal['any'], List[str], Tuple[str, ...]]]z(Union[BaseChatModel, _ConfigurableModel]c                K  sv   | s|sd}|pd}|r.|s.t d|d |sLttt| fd|i|S | rX| |d< |rd||d< t|||dS dS )	a  Initialize a ChatModel from the model name and provider.

    Must have the integration package corresponding to the model provider installed.

    .. versionadded:: 0.2.7

    .. versionchanged:: 0.2.8

        Support for ``configurable_fields`` and ``config_prefix`` added.

    .. versionchanged:: 0.2.12

        Support for Ollama via langchain-ollama package added. Previously
        langchain-community version of Ollama (now deprecated) was installed by default.

    Args:
        model: The name of the model, e.g. "gpt-4o", "claude-3-opus-20240229".
        model_provider: The model provider. Supported model_provider values and the
            corresponding integration package:
                - openai (langchain-openai)
                - anthropic (langchain-anthropic)
                - azure_openai (langchain-openai)
                - google_vertexai (langchain-google-vertexai)
                - google_genai (langchain-google-genai)
                - bedrock (langchain-aws)
                - cohere (langchain-cohere)
                - fireworks (langchain-fireworks)
                - together (langchain-together)
                - mistralai (langchain-mistralai)
                - huggingface (langchain-huggingface)
                - groq (langchain-groq)
                - ollama (langchain-ollama)  [support added in langchain==0.2.12]

            Will attempt to infer model_provider from model if not specified. The
            following providers will be inferred based on these model prefixes:
                - gpt-3... or gpt-4... -> openai
                - claude... -> anthropic
                - amazon.... -> bedrock
                - gemini... -> google_vertexai
                - command... -> cohere
                - accounts/fireworks... -> fireworks
        configurable_fields: Which model parameters are
            configurable:
                - None: No configurable fields.
                - "any": All fields are configurable. *See Security Note below.*
                - Union[List[str], Tuple[str, ...]]: Specified fields are configurable.

            Fields are assumed to have config_prefix stripped if there is a
            config_prefix. If model is specified, then defaults to None. If model is
            not specified, then defaults to ``("model", "model_provider")``.

            ***Security Note***: Setting ``configurable_fields="any"`` means fields like
            api_key, base_url, etc. can be altered at runtime, potentially redirecting
            model requests to a different service/user. Make sure that if you're
            accepting untrusted configurations that you enumerate the
            ``configurable_fields=(...)`` explicitly.

        config_prefix: If config_prefix is a non-empty string then model will be
            configurable at runtime via the
            ``config["configurable"]["{config_prefix}_{param}"]`` keys. If
            config_prefix is an empty string then model will be configurable via
            ``config["configurable"]["{param}"]``.
        kwargs: Additional keyword args to pass to
            ``<<selected ChatModel>>.__init__(model=model_name, **kwargs)``.

    Returns:
        A BaseChatModel corresponding to the model_name and model_provider specified if
        configurability is inferred to be False. If configurable, a chat model emulator
        that initializes the underlying model at runtime once a config is passed in.

    Raises:
        ValueError: If model_provider cannot be inferred or isn't supported.
        ImportError: If the model provider integration package is not installed.

    Initialize non-configurable models:
        .. code-block:: python

            # pip install langchain langchain-openai langchain-anthropic langchain-google-vertexai
            from langchain.chat_models import init_chat_model

            gpt_4o = init_chat_model("gpt-4o", model_provider="openai", temperature=0)
            claude_opus = init_chat_model("claude-3-opus-20240229", model_provider="anthropic", temperature=0)
            gemini_15 = init_chat_model("gemini-1.5-pro", model_provider="google_vertexai", temperature=0)

            gpt_4o.invoke("what's your name")
            claude_opus.invoke("what's your name")
            gemini_15.invoke("what's your name")


    Create a partially configurable model with no default model:
        .. code-block:: python

            # pip install langchain langchain-openai langchain-anthropic
            from langchain.chat_models import init_chat_model

            # We don't need to specify configurable=True if a model isn't specified.
            configurable_model = init_chat_model(temperature=0)

            configurable_model.invoke(
                "what's your name",
                config={"configurable": {"model": "gpt-4o"}}
            )
            # GPT-4o response

            configurable_model.invoke(
                "what's your name",
                config={"configurable": {"model": "claude-3-5-sonnet-20240620"}}
            )
            # claude-3.5 sonnet response

    Create a fully configurable model with a default model and a config prefix:
        .. code-block:: python

            # pip install langchain langchain-openai langchain-anthropic
            from langchain.chat_models import init_chat_model

            configurable_model_with_default = init_chat_model(
                "gpt-4o",
                model_provider="openai",
                configurable_fields="any",  # this allows us to configure other params like temperature, max_tokens, etc at runtime.
                config_prefix="foo",
                temperature=0
            )

            configurable_model_with_default.invoke("what's your name")
            # GPT-4o response with temperature 0

            configurable_model_with_default.invoke(
                "what's your name",
                config={
                    "configurable": {
                        "foo_model": "claude-3-5-sonnet-20240620",
                        "foo_model_provider": "anthropic",
                        "foo_temperature": 0.6
                    }
                }
            )
            # Claude-3.5 sonnet response with temperature 0.6

    Bind tools to a configurable model:
        You can call any ChatModel declarative methods on a configurable model in the
        same way that you would with a normal model.

        .. code-block:: python

            # pip install langchain langchain-openai langchain-anthropic
            from langchain.chat_models import init_chat_model
            from langchain_core.pydantic_v1 import BaseModel, Field

            class GetWeather(BaseModel):
                '''Get the current weather in a given location'''

                location: str = Field(..., description="The city and state, e.g. San Francisco, CA")

            class GetPopulation(BaseModel):
                '''Get the current population in a given location'''

                location: str = Field(..., description="The city and state, e.g. San Francisco, CA")

            configurable_model = init_chat_model(
                "gpt-4o",
                configurable_fields=("model", "model_provider"),
                temperature=0
            )

            configurable_model_with_tools = configurable_model.bind_tools([GetWeather, GetPopulation])
            configurable_model_with_tools.invoke(
                "Which city is hotter today and which is bigger: LA or NY?"
            )
            # GPT-4o response with tool calls

            configurable_model_with_tools.invoke(
                "Which city is hotter today and which is bigger: LA or NY?",
                config={"configurable": {"model": "claude-3-5-sonnet-20240620"}}
            )
            # Claude-3.5 sonnet response with tools
    )r'   r#    zconfig_prefix=z has been set but no fields are configurable. Set `configurable_fields=(...)` to specify the model params that are configurable.r#   r'   )default_configr%   r$   N)warningswarn_init_chat_model_helperr   r&   r.   r,   r+   r+   r-   r"   V   s2     =
)r#   )r'   r#   r(   r)   c                K  s>  |p
t | }|s td| d|dd }|dkr^td ddlm} |f d	| i|S |d
krtd ddlm} |f d	| i|S |dkrtd ddlm	} |f d	| i|S |dkrtd ddl
m} |f d	| i|S |dkrtd ddlm} |f d	| i|S |dkrHtd ddlm} |f d	| i|S |dkrxtd ddlm}	 |	f d	| i|S |dkrztd ddlm}
 W nN tk
r   ztd ddlm}
 W n tk
r   td Y nX Y nX |
f d	| i|S |dkr,td  dd!lm} |f d	| i|S |d"kr\td# dd$lm} |f d	| i|S |d%krtd& dd'lm} |f d(| i|S |d)krtd* dd+lm} |f d	| i|S |d,krtd- dd.lm} |f d(| i|S |d/krtd- dd0lm } |f d	| i|S d1!t"}td2|d3| d S )4Nz)Unable to infer model provider for model=z), please specify model_provider directly.-_openailangchain_openair   )
ChatOpenAIr'   	anthropiclangchain_anthropic)ChatAnthropicazure_openai)AzureChatOpenAIcoherelangchain_cohere)
ChatCoheregoogle_vertexailangchain_google_vertexai)ChatVertexAIgoogle_genailangchain_google_genai)ChatGoogleGenerativeAI	fireworkslangchain_fireworks)ChatFireworksollamalangchain_ollama)
ChatOllamaZlangchain_communitytogetherlangchain_together)ChatTogether	mistralailangchain_mistralai)ChatMistralAIhuggingfacelangchain_huggingface)ChatHuggingFaceZmodel_idgroqlangchain_groq)ChatGroqbedrocklangchain_aws)ChatBedrockbedrock_converse)ChatBedrockConversez, zUnsupported model_provider=z".

Supported model providers are: )#_attempt_infer_model_provider
ValueErrorreplacelower
_check_pkgr8   r9   r;   r<   r>   r@   rA   rC   rD   rF   rG   rI   rJ   rL   rM   ImportErrorZlangchain_community.chat_modelsrO   rP   rR   rS   rU   rV   rX   rY   r[   r\   r^   join_SUPPORTED_PROVIDERS)r'   r#   r(   r9   r<   r>   rA   rD   rG   rJ   rM   rP   rS   rV   rY   r\   r^   	supportedr+   r+   r-   r4   ,  s    











r4   r7   r:   r=   r?   rB   rE   rH   rK   rN   rQ   rT   rW   rZ   r]   )
model_namer)   c                 C  sf   |  ds|  drdS |  dr&dS |  dr4dS |  drBd	S |  d
rPdS |  dr^dS d S d S )Nzgpt-3zgpt-4r7   Zclauder:   commandr?   zaccounts/fireworksrH   ZgeminirB   zamazon.rZ   )
startswith)rh   r+   r+   r-   r_     s    




r_   None)pkgr)   c                 C  s0   t | s,| dd}td| d| dd S )Nr6   r5   zUnable to import z&. Please install with `pip install -U `)r   	find_specra   rd   )rl   Z	pkg_kebabr+   r+   r-   rc     s
    
rc   )sprefixr)   c                 C  s   |  |r| t|d  } | S r*   )rj   len)ro   rp   r+   r+   r-   _remove_prefix  s    
rr   )
bind_toolswith_structured_outputc                      s  e Zd Zddddddddd	d
dddZdddddZdedddddZdddddZdfddd dddZedddd Z	dgd!dddd"d#d$Z
dhd!dddd"d%d&Zdid!dd'd(d"d)d*Zdjd!dd'd+d"d,d-Zdkd.d/d0d1d2d'd3d4 fd5d6Zdld.d/d0d1d2d'd3d4 fd7d8Zdmd.d/d9d:d2dd;d4 fd<d=Zdnd.d/d9d:d2dd>d4 fd?d@ZdodAdd'd(d"dBdCZdpdDdd'd+d"dEdFZedqdGdGdddddddHdddId2dJdJdJdJdJdJddKdLdMdNZedrdGdddddddOdddPd2dJdJdJdJdJdJddQdLdRdNZdsdGdGdddddddHddd2d2dJdJdJdJdJdJddSdLdTdNZdtdddddddUdddVdJdJdJdJdJdJddWdXdYdZZd[dd\d]d^d_Zd`ddadbdcddZ  ZS )ur.   Nanyr0   r+   r1   r$   r%   queued_declarative_operationszOptional[dict]r/   r&   z!Sequence[Tuple[str, Tuple, Dict]]rk   )r1   r$   r%   rw   r)   c                C  sJ   |pi | _ |dkr|nt|| _|r6|ds6|d n|| _t|| _d S )Nru   r6   )_default_configlist_configurable_fieldsendswith_config_prefix_queued_declarative_operations)selfr1   r$   r%   rw   r+   r+   r-   __init__  s    

z_ConfigurableModel.__init__r   )namer)   c                   sv    t kr$dddd fdd}|S jrJ  }rJt| rJt| S   d}jrb|d7 }|d7 }t|d S )	Nr   r.   )argsr(   r)   c                    sJ   t j}| | |f ttjtjt r:t jnjj|dS )Nrv   )	ry   r}   appendr.   dictrx   
isinstancerz   r|   )r   r(   rw   r   r~   r+   r-   queue  s    
z-_ConfigurableModel.__getattr__.<locals>.queuez! is not a BaseChatModel attributez, and is not implemented on the default model.)_DECLARATIVE_METHODSrx   _modelhasattrgetattrAttributeError)r~   r   r   r'   msgr+   r   r-   __getattr__  s    

z_ConfigurableModel.__getattr__zOptional[RunnableConfig]r   )configr)   c                 C  s@   | j | |}tf |}| jD ]\}}}t||||}q |S r*   )rx   _model_paramsr4   r}   r   )r~   r   paramsr'   r   r   r(   r+   r+   r-   r     s
    
z_ConfigurableModel._modelr   c                   sJ   |pi } fdd| di  D } jdkrF fdd| D }|S )Nc                   s*   i | ]"\}}|  jrt| j|qS r+   )rj   r|   rr   .0kvr~   r+   r-   
<dictcomp>  s   
 z4_ConfigurableModel._model_params.<locals>.<dictcomp>configurableru   c                   s    i | ]\}}| j kr||qS r+   )rz   r   r   r+   r-   r   
  s    
  )getitemsrz   )r~   r   model_paramsr+   r   r-   r     s    


z _ConfigurableModel._model_params)r   r(   r)   c                   s   t f |p
i tt |}| dd | D } fdd|di  D |d< tj}|rz|ddd|if tj	 t
jtrtjnjj|dS )	z4Bind config to a Runnable, returning a new Runnable.c                 S  s   i | ]\}}|d kr||qS )r   r+   r   r+   r+   r-   r     s       z2_ConfigurableModel.with_config.<locals>.<dictcomp>c                   s&   i | ]\}}t |j kr||qS r+   )rr   r|   r   r   r~   r+   r-   r     s    r   with_configr+   r   rv   )r   r   r   r   r   ry   r}   r   r.   rx   r   rz   r|   )r~   r   r(   Zremaining_configrw   r+   r   r-   r     s&    



z_ConfigurableModel.with_configr!   )r)   c                 C  s*   ddl m}m} ttt||f tt f S )z%Get the input type for this runnable.r   )ChatPromptValueConcreteStringPromptValue)Zlangchain_core.prompt_valuesr   r   r   r&   r	   r   )r~   r   r   r+   r+   r-   	InputType+  s    
z_ConfigurableModel.InputTyper   )inputr   r(   r)   c                 K  s   |  |j|fd|i|S Nr   )r   invoker~   r   r   r(   r+   r+   r-   r   <  s    z_ConfigurableModel.invokec                   s"   |  |j|fd|i|I d H S r   )r   ainvoker   r+   r+   r-   r   D  s    z_ConfigurableModel.ainvokezOptional[Any]zIterator[Any]c                 k  s&   |  |j|fd|i|E d H  d S r   )r   streamr   r+   r+   r-   r   L  s    z_ConfigurableModel.streamzAsyncIterator[Any]c                 K s6   |  |j|fd|i|2 z3 d H W }|V  q6 d S r   )r   astreamr~   r   r   r(   xr+   r+   r-   r   T  s    (z_ConfigurableModel.astreamF)return_exceptionszList[LanguageModelInput]z5Optional[Union[RunnableConfig, List[RunnableConfig]]]boolz	List[Any])inputsr   r   r(   r)   c                  st   |pd }|d ks&t |ts&t|dkrVt |tr8|d }| |j|f||d|S t j|f||d|S d S N   r   )r   r   )r   r   rq   ry   r   batchsuperr~   r   r   r   r(   	__class__r+   r-   r   ]  s(    

  z_ConfigurableModel.batchc                  s   |pd }|d ks&t |ts&t|dkr\t |tr8|d }| |j|f||d|I d H S t j|f||d|I d H S d S r   )r   r   rq   ry   r   abatchr   r   r   r+   r-   r   t  s(    

  z_ConfigurableModel.abatchzSequence[LanguageModelInput]z9Optional[Union[RunnableConfig, Sequence[RunnableConfig]]]z+Iterator[Tuple[int, Union[Any, Exception]]]c                +  s   |pd }|d ks&t |ts&t|dkrdt |tr8|d }| tt|j|f||d|E d H  n t j|f||d|E d H  d S r   )	r   r   rq   ry   r   r   r   batch_as_completedr   r   r   r+   r-   r     s(    
  z%_ConfigurableModel.batch_as_completedzAsyncIterator[Tuple[int, Any]]c                 s   |pd }|d ks&t |ts&t|dkrtt |tr8|d }| tt|j|f||d|2 z3 d H W }|V  q\6 n0t j|f||d|2 z3 d H W }|V  q6 d S r   )	r   r   rq   ry   r   r   r   abatch_as_completedr   )r~   r   r   r   r(   r   r   r+   r-   r     s0    
  z&_ConfigurableModel.abatch_as_completedzIterator[LanguageModelInput]c                 k  s,   |  |j|fd|i|D ]
}|V  qd S r   )r   	transformr   r+   r+   r-   r     s     z_ConfigurableModel.transformz!AsyncIterator[LanguageModelInput]c                 K s6   |  |j|fd|i|2 z3 d H W }|V  q6 d S r   )r   
atransformr   r+   r+   r-   r     s    (z_ConfigurableModel.atransformT)diffwith_streamed_output_listinclude_namesinclude_typesinclude_tagsexclude_namesexclude_typesexclude_tagszLiteral[True]zOptional[Sequence[str]]zAsyncIterator[RunLogPatch])r   r   r   r   r   r   r   r   r   r   r(   r)   c                K  s   d S r*   r+   r~   r   r   r   r   r   r   r   r   r   r   r(   r+   r+   r-   astream_log  s    z_ConfigurableModel.astream_log)r   r   r   r   r   r   r   zLiteral[False]zAsyncIterator[RunLog]c                K  s   d S r*   r+   r   r+   r+   r-   r     s    z8Union[AsyncIterator[RunLogPatch], AsyncIterator[RunLog]]c                K sF   |  |j|f|||||||
|	|d	|2 z3 d H W }|V  q,6 d S )N)	r   r   r   r   r   r   r   r   r   )r   r   )r~   r   r   r   r   r   r   r   r   r   r   r(   r   r+   r+   r-   r     s     
)r   r   r   r   r   r   zLiteral[('v1', 'v2')]zAsyncIterator[StreamEvent])r   r   versionr   r   r   r   r   r   r(   r)   c                K sD   |  |j|f||||||	||d|
2 z3 d H W }|V  q*6 d S )N)r   r   r   r   r   r   r   r   )r   astream_events)r~   r   r   r   r   r   r   r   r   r   r(   r   r+   r+   r-   r     s    

z!_ConfigurableModel.astream_eventszDSequence[Union[Dict[str, Any], Type[BaseModel], Callable, BaseTool]]z)Runnable[LanguageModelInput, BaseMessage])toolsr(   r)   c                 K  s   |  d|f|S )Nrs   r   )r~   r   r(   r+   r+   r-   rs   ,  s    z_ConfigurableModel.bind_toolszUnion[Dict, Type[BaseModel]]z4Runnable[LanguageModelInput, Union[Dict, BaseModel]])schemar(   r)   c                 K  s   |  d|f|S )Nrt   r   )r~   r   r(   r+   r+   r-   rt   4  s    z)_ConfigurableModel.with_structured_output)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)N)__name__
__module____qualname__r   r   r   r   r   propertyr   r   r   r   r   r   r   r   r   r   r   r   r   r   rs   rt   __classcell__r+   r+   r   r-   r.     s              	 * * (! &)N)N)N)7
__future__r   r2   	importlibr   typingr   r   r   r   r   r	   r
   r   r   r   r   r   r   r   Zlangchain_core._apir   Zlangchain_core.language_modelsr   r   r   Z*langchain_core.language_models.chat_modelsr   r   Zlangchain_core.messagesr   r   Zlangchain_core.pydantic_v1r   Zlangchain_core.runnablesr   r   Zlangchain_core.runnables.schemar   Zlangchain_core.toolsr   Zlangchain_core.tracersr   r    Ztyping_extensionsr!   __all__r"   r4   rf   r_   rc   rr   r   r.   r+   r+   r+   r-   <module>   s   @

 
   Wd	