a
    pDfh                     @  s  d 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 ddl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 ddl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' eG dd dZ(G dd de"Z)dS )z
The interface module provides an even higher-level API for interacting
with a list of `ChatMessage` objects compared to the `ChatFeed`
through a frontend input UI.
    )annotations)	dataclass)partial)BytesIO)AnyCallableClassVarDictListN   )CDN_DIST)RowTabs)	ImageBase)Viewable)Widget)Button)	FileInput	TextInput   )CallbackStateChatFeed)ChatAreaInput)ChatMessage_FileInputMessagec                   @  sN   e Zd ZU dZded< ded< ded< ded< ded	< d
ed< dZded< dS )_ChatButtonDataa-  
    A dataclass to hold the metadata and data related to the
    chat buttons.

    Parameters
    ----------
    index : int
        The index of the button.
    name : str
        The name of the button.
    icon : str
        The icon to display.
    objects : List
        The objects to display.
    buttons : List
        The buttons to display.
    callback : Callable
        The callback to execute when the button is clicked.
    js_on_click : dict | str | None
        The JavaScript `code` and `args` to execute when the button is clicked.
    intindexstrnameiconr
   objectsbuttonsr   callbackNzdict | str | Nonejs_on_click)__name__
__module____qualname____doc____annotations__r$    r*   r*   a/nfs/NAS7/SABIOD/METHODE/ermites/ermites_venv/lib/python3.9/site-packages/panel/chat/interface.pyr      s   
r   c                      s  e Zd ZU dZejddZejee	e
efddZejdddZejdd	dZejdd
dZejdddZejdddZejdddZejdddZejdddZejeefdddZeji ddZeji dddZejeddZejeefddZ eji ddZ!eji ddZ"e# dgZ$de%d<  fdd Z&d!d"d#d$Z'ej(d%dd&d'd( Z)ej(d)d*dd&d+d, Z*dkd.d.d/d0d1d2Z+dld3d4d5d6d7d8Z,dmd3d4d9d6d:d;Z-d<d=d>d?Z.d@d9dAdBdCZ/dDdE Z0dnd3d4d5d6dFdGZ1dod3d4d5d6dHdIZ2dpd3d4d5d6dJdKZ3e4dLd=dMdNZ5e4d<d=dOdPZ6e6j7d<d5dQdRdPZ6dqdTdUdVdWdXdY fdZd[Z8ej(d\dd&d]d^ Z9 fd_d`Z:drdadVdbd9dcdd fdedfZ;dsdgdVdbdcd9dcdh fdidjZ<  Z=S )tChatInterfacear  
    High level widget that contains the chat log and the chat input.

    Reference: https://panel.holoviz.org/reference/chat/ChatInterface.html

    :Example:

    >>> async def repeat_contents(contents, user, instance):
    >>>     yield contents

    >>> chat_interface = ChatInterface(
        callback=repeat_contents, widgets=[TextInput(), FileInput()]
    )
    z
        The widget types to automatically send when the user presses enter
        or clicks away from the widget. If not provided, defaults to
        `[TextInput]`.)docz
        The avatar to use for the user. Can be a single character text, an emoji,
        or anything supported by `pn.pane.Image`. If not set, uses the
        first character of the name.)class_r-   Tzl
        Whether to reset the widget's value after sending a message;
        has no effect for `TextInput`.)defaultr-   z)
        Whether to show the send button.z
        Whether to show the stop button temporarily replacing the send button during
        callback; has no effect if `callback` is not async.z*
        Whether to show the rerun button.z)
        Whether to show the undo button.z*
        Whether to show the clear button.Nz)
        Whether to show the button name.ZUserz(
        Name of the ChatInterface user.FzZ
        Widgets to use for the input. If not provided, defaults to
        `[TextInput]`.)r.   
allow_refsr-   a  
        Allows addition of functionality or customization of buttons
        by supplying a mapping from the button name to a dictionary
        containing the `icon`, `callback`, `post_callback`, and/or `js_on_click` keys.

        If the button names correspond to default buttons
        (send, rerun, undo, clear), the default icon can be
        updated and if a `callback` key value pair is provided,
        the specified callback functionality runs before the existing one.

        For button names that don't match existing ones,
        new buttons are created and must include a
        `callback`, `post_callback`, and/or `js_on_click` key.

        The provided callbacks should have a signature that accepts
        two positional arguments: instance (the ChatInterface instance)
        and event (the button click event).

        The `js_on_click` key should be a str or dict. If str,
        provide the JavaScript code; else if dict, it must have a
        `code` key, containing the JavaScript code
        to execute when the button is clicked, and optionally an `args` key,
        containing dictionary of arguments to pass to the JavaScript
        code.
        z
        The input widgets.)r/   r0   r-   z
        The input message row that wraps the input layout (Tabs / Row)
        to easily swap between Tabs and Rows, depending on
        number of widgets.z:
        The input layout that contains the input widgets.z2
        Metadata and data related to the buttons.z
        The rendered buttons.zcss/chat_interface.csszClassVar[List[str]]_stylesheetsc                   s   | d}|d u r$tddg|d< nt|ts8|g|d< |dd }t j|i | tdg| jd| _	| 
  |   |d ur|| _| jjj| jj| j	g dgd d S )	NwidgetszSend a message)placeholderactivezchat-interface-input-container)css_classesstylesheetszchat-interface)r!   r5   )getr   
isinstancelistpopsuper__init__r   r1   _input_container_update_input_width_init_widgetsr4   Z_cardparamupdater!   )selfr!   paramsr2   r4   	__class__r*   r+   r<      s&    


zChatInterface.__init__r   )objc                 C  s6   dD ],}t ||t| | | j|fi ||i qdS )zg
        Link the disabled and loading attributes of the chat box to the
        given object.
        )disabledZloadingN)setattrgetattrlink)rB   rF   attrr*   r*   r+   _link_disabled_loading   s    z$ChatInterface._link_disabled_loadingwidth)watchc                 C  s$   | j du r | jdu p| jdk| _ dS )z)
        Update the input width.
        Ni  )show_button_namerM   rB   r*   r*   r+   r>      s    
z!ChatInterface._update_input_widthr2   button_propertiesc                 C  s  d| j dd| jdd| jdd| jdd| jdd}t| jdk| _i || j}t|	 D ]\}\}}|
 }|d	}|d
}|d}||pi }	|	r|	d }
|dus|dur| j|||d|
n|
}nf|dur|dur| j|d|}nD|du r|dur|}n*|du r@|du r@|s@td|d|dpT|	d}t|||g g ||d| j|< qb| j}t| jtr| jg}i | _g }|D ]N}|jp|jj}t|tr| }| j||ur|| j|< || q| j}|dur&d|v sd|v rd}nd|v r&d}t|dg| jdd}| j	 D ]\}}t|t| jpnt|ttfv }|r||v rt | jd j!| }|j"#|d |j"j$ddgd t|tr| j%|dd i | _&| j' D ]8}|j}z"|d kr| j"d!|  nd"}W n t(y"   d}Y n0 | j"j)* }t+|j*,|j- d#|j.d|j*,d$d%d&d'd(|d)}|d krx| /| |j!rt |j!| }|0| |j1r|j1}t|t2rd*|vrtd+|d,|j1|d-i |d* d. nt|t3r|j1|d/ || j&|< |j4| qt5|gt6| j&' R dd0g| jd1d2}|||f qDt| jd3krl|d }|g| j7_8|| _9dS )4zk
        Initialize the input widgets.

        Returns
        -------
        The input widgets.
        send)r    _default_callbackzplayer-stoprepeatz
arrow-backZtrash)rR   stopZrerunundoclearr   r#   post_callbackr$   rS   Nr#   rX   r   )rX   z%A 'callback' key is required for the z buttonr    )r   r   r    r!   r"   r#   r$   ZbothZscale_heightZstretch_widthheightzchat-interface-input-tabsT)sizing_moder5   r6   Zdynamicvaluezchat-interface-input-widget)r[   r5   Zdisabled_enter)rG   rU   Zshow_F Z   -   2   )r      r   r   center)r   r    r[   	max_widthZ
max_heightmarginalignvisiblecodez!A 'code' key is required for the z button's 'js_on_click' keyargs)rh   rg   )rg   zchat-interface-input-rowstart)r[   r5   r6   re   r   ):_click_send_click_stop_click_rerun_click_undo_click_clearlenrQ   _allow_revert	enumerateitemslowerr7   _wrap_callbacks
ValueErrorr   _button_datar2   r8   r   _widgetsr   rE   r%   typeappendr[   r   r1   tupleauto_send_typesr   r   r   r#   r@   rN   rA   rJ   _buttonsvaluesKeyErrorrO   rxr   wheretitler    rL   Zon_clickr$   dictr   r"   r   r9   r=   r!   _input_layout)rB   Zdefault_button_propertiesrQ   r   r   Z
propertiesr#   rX   r$   Zdefault_propertiesdefault_callbackr    r2   Znew_widgetsZwidgetkeyr[   Zinput_layoutZ	auto_sendbutton_dataactionrf   Z	show_exprbuttonZmessage_rowr*   r*   r+   r?      s   












"









zChatInterface._init_widgetsr]   zCallable | Noner   rY   c                   s   dd fdd}|S )zR
        Wrap the callback and post callback around the default callback.
        r   r   c                   s   dd fdd}|S )Nzparam.parameterized.Event)eventc                   sz   dkr| j jsd S  d ur@zd| _ | | W d| _nd| _0 | | d urvzd| _| | W d| _nd| _0 d S )NrR   TF)active_widgetr\   rG   )rB   r   )r#   r   r   rX   r*   r+   wrapperp  s    
z@ChatInterface._wrap_callbacks.<locals>.decorate.<locals>.wrapperr*   )r   r   r#   r   rX   r   r+   decorateo  s    z/ChatInterface._wrap_callbacks.<locals>.decorater*   )rB   r#   rX   r   r   r*   r   r+   rt   f  s    	zChatInterface._wrap_callbacksz param.parameterized.Event | Nonez'ChatInterface' | NoneNone)r   instancereturnc                 C  s   | j r
dS | j}|j}|s*t|dr*|j}|rt|trJt||j|j	d}t
|tu s\| jrddi}t|drvd|d< z:t|  |j| W d   n1 s0    Y  W q ty   Y q0 ndS |   | j|| j| jdd dS )z=
        Send the input when the user presses Enter.
        Nvalue_input)contents	mime_type	file_namer\   r]   T)r\   useravatarrespond)rG   r   r\   hasattrr   r8   r   r   r   filenamerx   r   reset_on_sendr@   Zdiscard_eventsrA   ru   _reset_button_datarR   r   r   )rB   r   r   r   r\   Zupdatesr*   r*   r+   rj     s2    


.zChatInterface._click_sendboolc                 C  s   |   S )zL
        Cancel the callback when the user presses the Stop button.
        )rU   )rB   r   r   r*   r*   r+   rk     s    zChatInterface._click_stopr   )r   c                 C  s<   | j ddd }t|dD ]\}}|j| jkr|  S qdS )z9
        Get the index of the last user message.
        Nr   r   )r!   rq   r   )rB   messagesr   messager*   r*   r+   _get_last_user_entry_index  s
    
z(ChatInterface._get_last_user_entry_indexr   )r   r4   c                 C  sZ   |j D ]N}|r"|jr"dddd}n&d| jr4|j nd| jr@dndd}|j| qdS )	zk
        Toggle the button's icon and name to indicate
        whether the action can be reverted.
        warningZRevertr^   )Zbutton_typer   rM   r/   r]   r_   N)r"   r!   rO   r   r   r@   rA   )rB   r   r4   r   Zbutton_updater*   r*   r+   _toggle_revert  s    

zChatInterface._toggle_revertc                 C  s*   | j  D ]}|j  | |d q
dS )zY
        Clears all the objects in the button data
        to prevent reverting.
        FN)rv   r}   r!   rW   r   )rB   r   r*   r*   r+   r     s    
z ChatInterface._reset_button_datac                 C  s0   |   }| |}|sdS | j|d dd dS )z|
        Upon clicking the rerun button, rerun the last user message,
        which can trigger the callback again.
        Nr   T)r\   r   )r   rV   rR   )rB   r   r   countr   r*   r*   r+   rl     s
    	
zChatInterface._click_rerunc                 C  sb   | j d }|j}|sL|   |  }| ||_| jrD| |d q^g |_n| | |   dS )z
        Upon clicking the undo button, undo (remove) messages
        up to the last user message. If the button is clicked
        again without performing any other actions, revert the undo.
        rV   TN)rv   r!   r   r   rV   rp   r   extend)rB   r   r   Z	undo_dataZundo_objectsr   r*   r*   r+   rm     s    


zChatInterface._click_undoc                 C  s^   | j d }|j}|sB|   |  |_| jr:| |d qZg |_n| | dd< |   dS )z
        Upon clicking the clear button, clear the chat log.
        If the button is clicked again without performing any
        other actions, revert the clear.
        rW   TN)rv   r!   r   rW   rp   r   copy)rB   r   r   Z
clear_dataZclear_objectsr*   r*   r+   rn   	  s    


zChatInterface._click_clearr   c                 C  s*   t | jtr| j| j jd S | jjd S )zj
        The currently active widget.

        Returns
        -------
        The active widget.
        r   )r8   r   r   r4   r!   rP   r*   r*   r+   r      s    	zChatInterface.active_widgetc                 C  s   t | jtr| jjS dS )z
        The currently active input widget tab index;
        -1 if there is only one widget available
        which is not in a tab.

        Returns
        -------
        The active input widget tab index.
        r   r8   r   r   r4   rP   r*   r*   r+   r4   -  s    zChatInterface.active)r   r   c                 C  s   t | jtr|| j_dS )z
        Set the active input widget tab index.

        Arguments
        ---------
        index : int
            The active index to set.
        Nr   )rB   r   r*   r*   r+   r4   <  s    
	assistantzList[ChatMessage]z!Dict[str, str | List[str]] | Nonez
str | Noner   zList[Dict[str, Any]])r   
role_namesdefault_rolecustom_serializerr   c                   s,   |du r| j g| jgd}t ||||S )a  
        Exports the chat log for use with transformers.

        Arguments
        ---------
        messages : list(ChatMessage)
            A list of ChatMessage objects to serialize.
        role_names : dict(str, str | list(str)) | None
            A dictionary mapping the role to the ChatMessage's user name.
            Defaults to `{"user": [self.user], "assistant": [self.callback_user]}`
            if not set. The keys and values are case insensitive as the strings
            will all be lowercased. The values can be a string or a list of strings,
            e.g. `{"user": "user", "assistant": ["executor", "langchain"]}`.
        default_role : str
            The default role to use if the user name is not found in role_names.
            If this is set to None, raises a ValueError if the user name is not found.
        custom_serializer : callable
            A custom function to format the ChatMessage's object. The function must
            accept one positional argument, the ChatMessage object, and return a string.
            If not provided, uses the serialize method on ChatMessage.

        Returns
        -------
        A list of dictionaries with a role and content keys.
        N)r   r   )r   Zcallback_userr;   _serialize_for_transformers)rB   r   r   r   r   rD   r*   r+   r   I  s
     z)ChatInterface._serialize_for_transformers_callback_statec                   s   t jt jf}| jr&| j|vs&| jd u rltj| ( d| j	d _
d| j	d _
W d    q1 s`0    Y  nDtj| ( d| j	d _
d| j	d _
W d    n1 s0    Y  d S )NTrR   FrU   )r   ZRUNNINGZ
GENERATING	show_stopr   Z_callback_futurer@   ZparameterizedZbatch_call_watchersr|   rf   )rB   Zbusy_statesr*   r*   r+   _update_input_disabledp  s    ,z$ChatInterface._update_input_disabledc                   s"   t   I dH  |  I dH  dS )zF
        Events to always execute after the callback is done.
        N)r;   _cleanup_responser   rP   rD   r*   r+   r   |  s    zChatInterface._cleanup_responsezChatMessage | dict | Anyzstr | bytes | BytesIO | NonezChatMessage | None)r\   r   r   r   r   c                   s:   t |ts&|du r| j}|du r&| j}t j||||dS )a  
        Sends a value and creates a new message in the chat log.

        If `respond` is `True`, additionally executes the callback, if provided.

        Arguments
        ---------
        value : ChatMessage | dict | Any
            The message contents to send.
        user : str | None
            The user to send as; overrides the message message's user if provided.
            Will default to the user parameter.
        avatar : str | bytes | BytesIO | None
            The avatar to use; overrides the message message's avatar if provided.
            Will default to the avatar parameter.
        respond : bool
            Whether to execute the callback.

        Returns
        -------
        The message that was created.
        N)r   r   r   )r8   r   r   r   r;   rR   )rB   r\   r   r   r   rD   r*   r+   rR     s    
zChatInterface.sendzstr | dict | ChatMessage)r\   r   r   r   replacer   c                   s4   t |ts|p| j}|p| j}t j|||||dS )aR  
        Streams a token and updates the provided message, if provided.
        Otherwise creates a new message in the chat log, so be sure the
        returned message is passed back into the method, e.g.
        `message = chat.stream(token, message=message)`.

        This method is primarily for outputs that are not generators--
        notably LangChain. For most cases, use the send method instead.

        Arguments
        ---------
        value : str | dict | ChatMessage
            The new token value to stream.
        user : str | None
            The user to stream as; overrides the message's user if provided.
            Will default to the user parameter.
        avatar : str | bytes | BytesIO | None
            The avatar to use; overrides the message's avatar if provided.
            Will default to the avatar parameter.
        message : ChatMessage | None
            The message to update.
        replace : bool
            Whether to replace the existing text when streaming a string or dict.

        Returns
        -------
        The message that was updated.
        )r   r   r   r   )r8   r   r   r   r;   stream)rB   r\   r   r   r   r   rD   r*   r+   r     s    $


zChatInterface.stream)NNr]   )NN)NN)NN)NN)NN)Nr   N)NNT)NNNF)>r%   r&   r'   r(   r@   r
   r{   ZClassSelectorr   r   bytesr   r   Booleanr   Z	show_sendr   Z
show_rerunZ	show_undoZ
show_clearrO   Stringr   r   r9   r2   r	   rQ   rw   r   r=   r   r   rv   r|   r   r1   r)   r<   rL   dependsr>   r?   rt   rj   rk   r   r   r   rl   rm   rn   propertyr   r4   setterr   r   r   rR   r   __classcell__r*   r*   rD   r+   r,   ?   s   
	

    #  ,  

         '
   '    r,   )*r(   
__future__r   Zdataclassesr   	functoolsr   ior   typingr   r   r   r	   r
   r@   Zio.resourcesr   Zlayoutr   r   Z
pane.imager   Zviewabler   Zwidgets.baser   Zwidgets.buttonr   Zwidgets.inputr   r   feedr   r   inputr   r   r   r   r   r,   r*   r*   r*   r+   <module>   s&    