U
    hD                     @   sf  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 d dl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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-m.Z.m/Z/ d dl0m1Z1m2Z2m3Z3 d dl4m5Z5m6Z6 d dl7m8Z8 d dl9m:Z: e;e<Z=G dd deZ>e$e?dddZ@e!e?dddZAdS )    N)AnyCallableDictIteratorListLiteralMappingOptionalSequenceTypeUnioncast)urlparse)CallbackManagerForLLMRun)BaseChatModel)LanguageModelInput)	AIMessageAIMessageChunkBaseMessageBaseMessageChunkChatMessageChatMessageChunkFunctionMessageHumanMessageHumanMessageChunkInvalidToolCallSystemMessageSystemMessageChunkToolCallToolMessageToolMessageChunk)tool_call_chunk)make_invalid_tool_callparse_tool_call)ChatGenerationChatGenerationChunk
ChatResult)	BaseModelFieldPrivateAttr)RunnableRunnableConfig)BaseToolconvert_to_openai_toolc                       s  e Zd ZU dZeed< eed< dZeed< dZe	ed< dZ
eee  ed	< dZee	 ed
< eedZeed< e Zeed< ed fddZeedddZddddZeeeef dddZd>ee eee  eeeef dddZd?ee eee  ee eedddZd@ddeee  eee  ee!e" d fd d!Z#dAee eee  ee ee!e$ dd"d#Z%eeeef dd$d%Z&dBeee  eeeef d& fd'd(Z'eedd)d*Z(e)e*eef ed+d,d-Z+e)e*eef ee"d.d/d0Z,e)ddd1d2Z-e)eed3d4d5Z.e)e*eef ed6d7d8Z/dd9e0e1eeef e2e3 e4e5f  ee1eee6d: e7f  ee8eef d; fd<d=Z9  Z:S )C
ChatMlflowa  `MLflow` chat models API.

    To use, you should have the `mlflow[genai]` python package installed.
    For more information, see https://mlflow.org/docs/latest/llms/deployments.

    Example:
        .. code-block:: python

            from langchain_community.chat_models import ChatMlflow

            chat = ChatMlflow(
                target_uri="http://localhost:5000",
                endpoint="chat",
                temperature-0.1,
            )
    endpoint
target_urig        temperature   nNstop
max_tokens)default_factoryextra_params_client)kwargsc              
      sn   t  jf | |   zddlm} || j| _W n6 tk
rh } ztd| j d|W 5 d }~X Y nX d S )Nr   )get_deploy_clientz;Failed to create the client. Please run `pip install mlflowz#` to install required dependencies.)	super__init___validate_uriZmlflow.deploymentsr;   r1   r9   ImportError_mlflow_extras)selfr:   r;   e	__class__ J/tmp/pip-unpacked-wheel-9gdii04g/langchain_community/chat_models/mlflow.pyr=   [   s    zChatMlflow.__init__)returnc                 C   s   dS )Nz[genai]rE   rA   rE   rE   rF   r@   i   s    zChatMlflow._mlflow_extrasc                 C   sD   | j dkrd S dddg}t| j j|kr@td| j  d| dd S )NZ
databrickshttphttpszInvalid target URI: z. The scheme must be one of .)r1   r   scheme
ValueError)rA   allowedrE   rE   rF   r>   m   s    

zChatMlflow._validate_uric                 C   s&   | j | j| j| j| j| j| jd}|S )Nr1   r0   r2   r4   r5   r6   r8   rO   )rA   paramsrE   rE   rF   _default_paramsw   s    	zChatMlflow._default_params)messagesr5   r:   rG   c                 K   sT   dd |D }|| j | jd| j|}| jp.| }r<||d< | jd k	rP| j|d< |S )Nc                 S   s   g | ]}t |qS rE   )r/   _convert_message_to_dict).0messagerE   rE   rF   
<listcomp>   s    z.ChatMlflow._prepare_inputs.<locals>.<listcomp>)rR   r2   r4   r5   r6   )r2   r4   r8   r5   r6   )rA   rR   r5   r:   Zmessage_dictsdatarE   rE   rF   _prepare_inputs   s    

zChatMlflow._prepare_inputs)rR   r5   run_managerr:   rG   c                 K   s,   | j ||f|}| jj| j|d}t|S )Nr0   inputs)rX   r9   Zpredictr0   r/   _create_chat_result)rA   rR   r5   rY   r:   rW   resprE   rE   rF   	_generate   s    zChatMlflow._generate)r5   )inputconfigr5   r:   rG   c                +   sR   t | jds.tt| j|f||d|V  n t j||fd|i|E d H  d S )Npredict_stream)r`   r5   r5   )hasattrr9   r   r   Zinvoker<   stream)rA   r_   r`   r5   r:   rC   rE   rF   rc      s    
 zChatMlflow.streamc                 k   s   | j ||f|}| jj| j|d}d }|D ]}|d r*|d d }	|	d }
|d kr\|
d}t|
|}i }|	d }r||d< |	d }r||d< t||pd d}|r|j|j	||d	 |V  q*q*q*d S )
NrZ   choicesr   deltarolefinish_reasonlogprobsrU   generation_info)chunkrh   )
rX   r9   ra   r0   getr/   _convert_delta_to_message_chunkr%   Zon_llm_new_tokentext)rA   rR   r5   rY   r:   rW   Z
chunk_iterZfirst_chunk_rolerk   choiceZchunk_deltaZchunk_messagerj   rg   rh   rE   rE   rF   _stream   sF    
    zChatMlflow._streamc                 C   s   | j S )N)rQ   rH   rE   rE   rF   _identifying_params   s    zChatMlflow._identifying_params)r5   r:   rG   c                    s   | j t jf d|i|S )z>Get the parameters used to invoke the model FOR THE CALLBACKS.r5   )rQ   r<   _get_invocation_params)rA   r5   r:   rC   rE   rF   rr      s    z!ChatMlflow._get_invocation_paramsc                 C   s   dS )zReturn type of chat model.zmlflow-chatrE   rH   rE   rE   rF   	_llm_type   s    zChatMlflow._llm_type)_dictrG   c           	      C   s   | d }t t| d}|dkr*t|dS |dkr|p8d}i }g }g }| d }r||d< |D ]R}z|t|dd	 W q` tk
r } z|t|t| W 5 d }~X Y q`X q`t||| d
||dS |dkrt	|dS t
||dS d S )Nrf   contentuserru   	assistant 
tool_callsT)Z	return_idid)ru   additional_kwargsr{   rz   invalid_tool_callssystemru   rf   )r   strrl   r   appendr#   	Exceptionr"   r   r   r   )	rt   rf   ru   r|   rz   r}   raw_tool_callsZraw_tool_callrB   rE   rE   rF   _convert_dict_to_message   s<    


z#ChatMlflow._convert_dict_to_message)rt   default_rolerG   c                 C   s   |  d|}|  dpd}|dkr,t|dS |dkri }g }|  d }rz||d< zdd	 |D }W n tk
rx   Y nX t|||  d
|dS |dkrt|dS |dkrt|| d |  d
dS t||dS d S )Nrf   ru   ry   rv   rw   rx   rz   c                 S   s:   g | ]2}t |d  d|d  d|d|d dqS )functionname	argumentsr{   index)r   argsr{   r   )r!   rl   )rT   ZrtcrE   rE   rF   rV   .  s   z>ChatMlflow._convert_delta_to_message_chunk.<locals>.<listcomp>r{   )ru   r|   r{   tool_call_chunksr~   tooltool_call_id)ru   r   r{   r   )rl   r   KeyErrorr   r   r    r   )rt   r   rf   ru   r|   r   r   rE   rE   rF   rm      s<    

	
  z*ChatMlflow._convert_delta_to_message_chunkc                   C   s   t dd S )N~Function messages are not supported by Databricks. Please create a feature request at https://github.com/mlflow/mlflow/issues.)rM   rE   rE   rE   rF   _raise_functions_not_supportedH  s    z)ChatMlflow._raise_functions_not_supported)rU   rG   c                    s  d| j i}| jp| jd }d k	r,||d< t| trD| j|d< n,t| trZd|d< nt| trd|d< | j	sx| j
rdd | j	D dd | j
D  |d	< n>d	| jkr| jd	 |d	< d
ddhfdd|d	 D |d	< n d	|kr|d pd |d< nzt| trd|d< ndt| trLd|d< | j|d< dddh  fdd| D }n$t| trbtdntd|  d| jkrt  |S )Nru   r   rf   rv   rx   c                 S   s   g | ]}t |qS rE   )!_lc_tool_call_to_openai_tool_callrT   ZtcrE   rE   rF   rV   [  s    z7ChatMlflow._convert_message_to_dict.<locals>.<listcomp>c                 S   s   g | ]}t |qS rE   ))_lc_invalid_tool_call_to_openai_tool_callr   rE   rE   rF   rV   ]  s   rz   r{   typer   c                    s"   g | ]} fd d|  D qS )c                    s   i | ]\}}| kr||qS rE   rE   rT   kvtool_call_supported_propsrE   rF   
<dictcomp>e  s    zBChatMlflow._convert_message_to_dict.<locals>.<listcomp>.<dictcomp>)items)rT   	tool_callr   rE   rF   rV   d  s   
r~   r   r   c                    s   i | ]\}}| kr||qS rE   rE   r   )supported_propsrE   rF   r   w  s      z7ChatMlflow._convert_message_to_dict.<locals>.<dictcomp>r   zGot unknown message type: Zfunction_call)ru   r   r|   rl   
isinstancer   rf   r   r   rz   r}   r   r   r   r   r   rM   r/   r   )rU   Zmessage_dictr   rE   )r   r   rF   rS   O  sT    











z#ChatMlflow._convert_message_to_dict)responserG   c                 C   sZ   g }| d D ]4}t |d }|di }t||d}|| q| di }t||dS )Nrd   rU   usageri   )generationsZ
llm_output)r/   r   rl   r$   r   r&   )r   r   ro   rU   r   genrE   rE   rF   r\     s    zChatMlflow._create_chat_resulttool_choice)autononerequiredany)toolsr   r:   rG   c                   s   dd |D } rt  tr4 dkrdd id nTt  trzdd |D }t fdd	|D std
  d| dntd   |d< t jf d|i|S )a  Bind tool-like objects to this chat model.

        Assumes model is compatible with OpenAI tool-calling API.

        Args:
            tools: A list of tool definitions to bind to this chat model.
                Can be  a dictionary, pydantic model, callable, or BaseTool. Pydantic
                models, callables, and BaseTools will be automatically converted to
                their schema dictionary representation.
            tool_choice: Which tool to require the model to call.
                Options are:
                name of the tool (str): calls corresponding tool;
                "auto": automatically selects a tool (including no tool);
                "none": model does not generate any tool calls and instead must
                    generate a standard assistant message;
                "required": the model picks the most relevant tool in tools and
                    must generate a tool call;

                or a dict of the form:
                {"type": "function", "function": {"name": <<tool_name>>}}.
            **kwargs: Any additional parameters to pass to the
                :class:`~langchain.runnable.Runnable` constructor.
        c                 S   s   g | ]}t |qS rE   r-   )rT   r   rE   rE   rF   rV     s     z)ChatMlflow.bind_tools.<locals>.<listcomp>)r   r   r   r   r   )r   r   c                 S   s   g | ]}|d  d qS )r   r   rE   )rT   Zformatted_toolrE   rE   rF   rV     s   c                 3   s   | ]}| d  d kV  qdS )r   r   NrE   )rT   Z	tool_namer   rE   rF   	<genexpr>  s   z(ChatMlflow.bind_tools.<locals>.<genexpr>zTool choice z1 was specified, but the only provided tools were rK   zEUnrecognized tool_choice type. Expected str, bool or dict. Received: r   r   )r   r   dictr   rM   r<   bind)rA   r   r   r:   Zformatted_toolsZ
tool_namesrC   r   rF   
bind_tools  s,     

zChatMlflow.bind_tools)N)NN)N)NN)N);__name__
__module____qualname____doc__r   __annotations__r2   floatr4   intr5   r	   r   r6   r(   r   r8   r)   r9   r   r=   propertyr@   r>   r   rQ   r   rX   r   r&   r^   r   r+   r   r   rc   r%   rp   rq   rr   rs   staticmethodr   r   rm   r   rS   r\   r
   r   r   r'   r   r,   r   boolr*   r   __classcell__rE   rE   rC   rF   r/   9   s   

 

  
 
  
/ 
 
	!
 '6
r/   )r   rG   c                 C   s$   d| d | d t | d ddS Nr   r{   r   r   )r   r   )r   r{   r   )jsondumps)r   rE   rE   rF   r     s    r   )invalid_tool_callrG   c                 C   s   d| d | d | d ddS r   rE   )r   rE   rE   rF   r     s    r   )Br   loggingtypingr   r   r   r   r   r   r   r	   r
   r   r   r   urllib.parser   Zlangchain_core.callbacksr   Zlangchain_core.language_modelsr   Z#langchain_core.language_models.baser   Zlangchain_core.messagesr   r   r   r   r   r   r   r   r   r   r   r   r   r   r    Zlangchain_core.messages.toolr!   Z*langchain_core.output_parsers.openai_toolsr"   r#   Zlangchain_core.outputsr$   r%   r&   Zlangchain_core.pydantic_v1r'   r(   r)   Zlangchain_core.runnablesr*   r+   Zlangchain_core.toolsr,   Z%langchain_core.utils.function_callingr.   	getLoggerr   loggerr/   r   r   r   rE   rE   rE   rF   <module>   s.   8D
   