a
    pDfP~                     @  s>  d Z ddlmZ ddl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 ddlmZ ddlmZmZmZmZmZmZmZ ddl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l"m#Z# ddl$m%Z% ddl&m'Z' erddl(m)Z) ddl*m+Z+ ddl,m-Z- dZ.G dd deZ/G dd de0Z1G dd deZ2dS )z}
The feed module provides a high-level API for interacting
with a list of `ChatMessage` objects through the backend methods.
    )annotationsN)Enum)
isasyncgenisasyncgenfunctionisawaitableiscoroutinefunctionisgeneratorisgeneratorfunction)BytesIO)TYPE_CHECKINGAnyCallableClassVarDictListLiteral   )Margin)CDN_DIST)Feed	ListPanel)Card)VSpacer)SVG   )ChatMessage)Document)Model)Comma  
    <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-loader-3" width="35" height="35" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
        <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
        <path d="M3 12a9 9 0 0 0 9 9a9 9 0 0 0 9 -9a9 9 0 0 0 -9 -9"></path>
        <path d="M17 12a5 5 0 1 0 -5 5"></path>
    </svg>
c                   @  s    e Zd ZdZdZdZdZdZdS )CallbackStateZidleZrunningZ
generatingZstoppingstoppedN)__name__
__module____qualname__IDLERUNNING
GENERATINGSTOPPINGSTOPPED r)   r)   \/nfs/NAS7/SABIOD/METHODE/ermites/ermites_venv/lib/python3.9/site-packages/panel/chat/feed.pyr   .   s
   r   c                   @  s   e Zd ZdS )StopCallbackN)r!   r"   r#   r)   r)   r)   r*   r+   6   s   r+   c                      sh  e Zd ZU dZejddddZejdddZej	d	g d
ddZ
ejdddZeji ddZejddddZejdddZeji ddZejddZedddZejg ddZejdddZejdddZejdi dddd dZejd!dd"dZejd#dZejd$dd%dZ ejd&dd'dZ!ejdd(dZ"ejdd)dZ#ej$e%dd*d+Z&ej	e'e(d,d-Z)ej*d.dZ+ejd/dZ,e- d0gZ.d1e/d2<  fd3d4Z0dd6d7d7d8d9d:d;d<Z1d=d>d9d9d6d8d?d@dAdBZ2dd7d?dC fdDdEZ3ej4dFdGdHddIdJdK Z5ej4dLddIdMdN Z6ej4dOdPdddQdRdS Z7ddTd?dUdVdWZ8ddXdYdZdTd[d\d]Z9dd^dTdTd_d`daZ:dbd^dUdcddZ;d^dTdedfdgZ<dhdid?djdkdlZ=dmdn Z>dodpdqdrZ?d?dsdtduZ@dvdw ZAddxdYdZdydTdzd{d|ZBdd}dYdZdTdydTd~ddZCdd ZDdydsddZEddiddddZFddsddZGddddYdddddZHddddddddZIdddZJ  ZKS )ChatFeedu  
    A widget to display a list of `ChatMessage` objects and interact with them.

    This widget provides methods to:
    - Send (append) messages to the chat log.
    - Stream tokens to the latest `ChatMessage` in the chat log.
    - Execute callbacks when a user sends a message.
    - Undo a number of sent `ChatMessage` objects.
    - Clear the chat log of all `ChatMessage` objects.

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

    :Example:

    >>> async def say_welcome(contents, user, instance):
    >>>    yield "Welcome!"
    >>>    yield "Glad you're here!"

    >>> chat_feed = ChatFeed(callback=say_welcome, header="Welcome Feed")
    >>> chat_feed.send("Hello World!", user="New User", avatar="😊")
       )r   Nz
        Max pixel distance from the latest object in the Column to
        activate automatic scrolling upon update. Setting to 0
        disables auto-scrolling.)defaultZboundsdocFz
        Callback to execute when a user sends a message or
        when `respond` is called. The signature must include
        the previous message value `contents`, the previous `user` name,
        and the component `instance`.)
allow_refsr/   summary)raiser1   verboseignorea/  
        How to handle exceptions raised by the callback.
        If "raise", the exception will be raised.
        If "summary", a summary will be sent to the chat feed.
        If "verbose", the full traceback will be sent to the chat feed.
        If "ignore", the exception will be ignored.
        )r.   objectsr/   Z	AssistantzO
        The default user name to use for the message provided by the callback.)r.   r/   zY
        Params to pass to Card, like `header`, `header_background`, `header_color`, etc.Tz?
        Whether the Card should be expandable and collapsible.)r.   readonlyr/   z%
       Whether the feed is disabled.z
        Params to pass to each ChatMessage, like `reaction_icons`, `timestamp_format`,
        `show_avatar`, `show_user`, and `show_timestamp`. Params passed
        that are not ChatFeed params will be forwarded into `message_params`.zl
        The header of the chat feed; commonly used for the title.
        Can be a string, pane, or widget.)r/      z
        Allows to create additional space around the component. May
        be specified as a two-tuple of the form (vertical, horizontal)
        or a four-tuple (top, right, bottom, left).z;
        The list of child objects that make up the layout. a  
        If provided, initializes a chat message in the chat log
        using the provided help text as the message object and
        `help` as the user. This is useful for providing instructions,
        and will not be included in the `serialize` method by default.z:
        The text to display next to the placeholder icon. )userZreaction_iconsZshow_copy_iconZshow_timestampz
        Params to pass to the placeholder ChatMessage, like `reaction_icons`,
        `timestamp_format`, `show_avatar`, `show_user`, `show_timestamp`.
        r   z
        Min duration in seconds of buffering before displaying the placeholder.
        If 0, the placeholder will be disabled.a)  
        A callable or list of callables that accept the value and return a
        Panel object to render the value. If a list is provided, will
        attempt to use the first renderer that does not raise an
        exception. If None, will attempt to infer the renderer
        from the value.2   z
        The number of objects loaded on each side of the visible objects.
        When scrolled halfway into the buffer, the feed will automatically
        load additional objects while unloading objects on the opposite side.d   z
        Min pixel distance from the latest object in the Column to
        display the scroll button. Setting to 0
        disables the scroll button.zj
        Whether to show an activity dot on the ChatMessage while
        streaming the callback response.zu
        Whether to scroll to the latest object on init. If not
        enabled the view will be on the first object.z~
        The placeholder wrapped in a ChatMessage object;
        primarily to prevent recursion error in _update_placeholder.)class_r0   r/   z+
        The current state of the callback.)r5   r/   z!Triggers the callback to respond.z1
        The previous disabled state of the feed.zcss/chat_feed.csszClassVar[List[str]]_stylesheetsc           	        s  d | _ |dr,t|d ts,|d g|d< |dd u rP|dd u rPd|d< |di }| D ]&}|| jvrd|tjv rd||||< qd||d< t j	|i | | j
rt| j
ddg| j| _t| jj| jj| jj| jj| jj| jjd}t| j| j| j| j| jd	g| jd
|| _d | j_| }| j| jj  | jj dg  }|j| jj| jj | jj!| jj| jj! j"dddg| jj#  dg| jj$| jj%dgddi|d | j }|dd  || | j&| jddd t'| jt( fi || _)| j*| j+d d S )N	rendererswidthsizing_modeZstretch_widthmessage_paramsZHelp)r:   )designrA   r@   	max_width	min_widthvisiblezchat-feed-log)load_bufferauto_scroll_limitscroll_button_thresholdview_latestcss_classesstylesheetsrL   )Nr8   Fz	chat-feedzchat-feed-headerzchat-feed-titlepaddingZ0px)marginalignheaderheightZhide_headercollapsiblerK   Zheader_css_classes
max_height
min_heightZtitle_css_classesZstylesrL   r5   T)r5   bidirectional_callback_trigger),_callback_futureget
isinstancelistcopyparamr   popsuper__init__	help_textr5   dictrC   rA   r@   rD   rE   rF   r   rG   rH   rI   rJ   r>   	_chat_logrQ   rL   rxcard_paramsupdaterN   rO   rP   Zin_rK   rS   rT   linkr   r   _cardwatch_prepare_response)	selfr5   paramsrB   Z	param_keyZlinked_paramsrd   Zcard_stylesheetsZcard_overrides	__class__r)   r*   r_      s    	



zChatFeed.__init__Nr   zModel | NonezComm | Noner   )r/   rootparentcommreturnc                 C  s2   | j ||||}|p|jd }||f| j|< |S )Nid)rg   
_get_modelrefZ_models)rj   r/   rn   ro   rp   modelrt   r)   r)   r*   rs   
  s    zChatFeed._get_modelz$Dict[str, param.parameterized.Event]zDict[str, Any]None)eventsmsgrn   ru   r/   rp   rq   c                 C  s   d S Nr)   )rj   rw   rx   rn   ru   r/   rp   r)   r)   r*   _update_model  s    zChatFeed._update_model)rn   rq   c                   s   | j | t | d S ry   )rg   _cleanupr^   )rj   rn   rl   r)   r*   r{     s    zChatFeed._cleanuprG   rH   rI   )rh   c                 C  s"   | j | j_ | j| j_| j| j_d S ry   )rG   rb   rH   rI   rj   r)   r)   r*   _update_chat_log_params  s    

z ChatFeed._update_chat_log_paramsrd   c                 C  s.   | j  }|dd  | jjjf i | d S )NrL   )rd   r[   r]   rg   r\   re   )rj   rd   r)   r)   r*   _update_card_params#  s    
zChatFeed._update_card_paramsplaceholder_textplaceholder_params)rh   Zon_initc                 C  s6   t tddddgd}t| jf|dgd| j| _d S )Nfixed#   zrotating-placeholder)rA   r@   rQ   rK   message)avatarrK   )r   PLACEHOLDER_SVGr   r   r   _placeholder)rj   Zloading_avatarr)   r)   r*   _update_placeholder)  s    zChatFeed._update_placeholderzChatMessage | None)r   rq   c              	   C  sf   t j| F |dur | | z| | j W n tyB   Y n0 W d   n1 sX0    Y  dS )z
        Replace the placeholder from the chat log with the message
        if placeholder, otherwise simply append the message.
        Replacing helps lessen the chat log jumping around.
        N)r\   parameterizedbatch_call_watchersappendremover   
ValueError)rj   r   r)   r)   r*   _replace_placeholder6  s    
zChatFeed._replace_placeholderra   z
str | Nonezstr | bytes | BytesIO | None)valuer:   r   rq   c                 C  s   d|v r d|v r t d|n.d|v r8|d|d< nd|vrNt d|t|fd| ji| j}|rr||d< |r~||d< | jrt| jd |d	< tf i |}|S )
z6
        Builds a ChatMessage from the value.
        r   objectz4Cannot pass both 'value' and 'object' together; got z[If 'value' is a dict, it must contain an 'object' key, e.g. {'object': 'Hello World'}; got r?   r:   r   P   r@   )r   r]   ra   r?   rB   r@   intr   )rj   r   r:   r   rB   r   r)   r)   r*   _build_messageE  s&    	zChatFeed._build_messager   )r   r   rq   c                 C  s   | j tjk}| jduo| j }|du r,dS |s4|r<td| j}d}t|trf|	d|}|	d}|durt|t
r|j}|j}|j}|j|||d |S t|t
r| | |S t|tsd|i}| j|||d}| | |S )z|
        Replace the placeholder message with the response or update
        the message's value with the response.
        NCallback was stopped.r:   r   r:   r   r   )_callback_stater   r'   rW   	cancelledr+   callback_userrY   ra   rX   r   r:   r   r   re   r   r   )rj   r   r   Zis_stoppingZ
is_stoppedr:   r   Znew_messager)   r)   r*   _upsert_messageb  s4    






zChatFeed._upsert_messager   c                 C  sL   |j }t|dr|j}n(t|dr*|j}nt|dr<|j}n|}||j| fS )zH
        Extracts the contents from the message's panel object.
        r   r5   r   )Z_object_panelhasattrr   r5   r   r:   )rj   r   r   contentsr)   r)   r*   _gather_callback_args  s    


zChatFeed._gather_callback_args)responserq   c                   s   d}zt |r@tj| _|2 z 3 dH W }| ||}| j|_q6 nXt|rptj| _|D ]}| ||}| j|_qTn(t|r| |I dH |}n| ||}W |rd|_n|rd|_0 |S )zh
        Serializes the response by iterating over it and
        updating the message's value.
        NF)r   r   r&   r   r   show_activity_dotr   r   )rj   r   Zresponse_messagetokenr)   r)   r*   _serialize_response  s(    zChatFeed._serialize_responsezasyncio.Taskr   )tasknum_entriesrq   c                   sz   | j dkrdS t  }| sv|t| jkrvt  | }|| j ksT| jdu rd| | j	 dS t
dI dH  qdS )z
        Schedules the placeholder to be added to the chat log
        if the callback takes longer than the placeholder threshold.
        r   Ng?)placeholder_thresholdasyncioget_event_looptimedonelenrb   rW   r   r   sleep)rj   r   r   startdurationr)   r)   r*   _schedule_placeholder  s    	
zChatFeed._schedule_placeholderc                  s:   t    fdd}t|I d H }| u r.q6|V  qd S )Nc                     s&   z
t W S  ty      Y S 0 d S ry   )nextStopIterationr)   r   sync_genr)   r*   	safe_next  s    
z)ChatFeed._to_async_gen.<locals>.safe_next)r   r   	to_thread)rj   r   r   r   r)   r   r*   _to_async_gen  s    	zChatFeed._to_async_genzasyncio.BaseEventLoop)loopc                   s   |  |}t| jr&| j| I d H }nLt| jr<| j| }n6t| jrX| | j| }ntj| jg|R  I d H }| |I d H  d S ry   )	r   r   callbackr   r	   r   r   r   r   )rj   r   r   callback_argsr   r)   r)   r*   _handle_callback  s    



zChatFeed._handle_callback)rq   c              
     s  | j du rdS | j| j zztj|  d| _tj| _	W d   n1 sR0    Y  | j
d }t|tsW W |  I dH  dS t| j
}t }|| ||}|| _t| |||I dH  W n ty   tj| _	Y n ty } ztddd}| jdkr*| jd|d	fi | nZ| jd
krV| jdt  dfi | n.| jdkrW Y d}~W |  I dH  dS |W Y d}~n
d}~0 0 W |  I dH  n|  I dH  0 dS )zi
        Prepares the response by scheduling the placeholder and
        executing the callback.
        NT	ExceptionF)r:   respondr1   zEncountered `z@`. Set `callback_exception='verbose'` to see the full traceback.r3   z
```python
z
```r4   )r   _disabled_stackr   disabledr\   r   r   r   r%   r   rb   rY   r   _cleanup_responser   r   r   Zcreate_taskr   rW   Zgatherr   r+   r(   r   ra   callback_exceptionsend	traceback
format_exc)rj   _r   r   r   futureesend_kwargsr)   r)   r*   ri     sJ    
&



 zChatFeed._prepare_responsec                   sX   t j| 8 | d tj| _| jr0| j nd| _	W d   n1 sJ0    Y  dS )zF
        Events to always execute after the callback is done.
        NF)
r\   r   r   r   r   r$   r   r   r]   r   r|   r)   r)   r*   r     s    
zChatFeed._cleanup_responsezChatMessage | dict | Anybool)r   r:   r   r   rq   c                 C  sd   t |tr(|dus|dur"td|}n"t |ts:d|i}| j|||d}| | |r`|   |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.
        avatar : str | bytes | BytesIO | None
            The avatar to use; overrides the message message's avatar if provided.
        respond : bool
            Whether to execute the callback.

        Returns
        -------
        The message that was created.
        NzfCannot set user or avatar when explicitly sending a ChatMessage. Set them directly on the ChatMessage.r   r   )rY   r   r   ra   r   r   r   )rj   r   r:   r   r   r   r)   r)   r*   r      s    


zChatFeed.sendzstr | dict | ChatMessage)r   r:   r   r   replacerq   c                 C  s   | j dur| j  rtdt|tr@|dus6|dur@tdnJ|rt|ttfrv|j||d |rj||_	|r||_
n|j|||d |S t|tr|}n"t|tsd|i}| j|||d}| | |S )a  
        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.
        avatar : str | bytes | BytesIO | None
            The avatar to use; overrides the message's avatar if provided.
        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.
        Nr   zhCannot set user or avatar when explicitly streaming a ChatMessage. Set them directly on the ChatMessage.)r   r   r   )rW   r   r+   rY   r   r   strra   streamr:   r   re   r   r   )rj   r   r:   r   r   r   r)   r)   r*   r   K  s,    "


zChatFeed.streamc                 C  s   | j d dS )zP
        Executes the callback with the latest message in the chat log.
        rV   N)r\   triggerr|   r)   r)   r*   r     s    zChatFeed.respondc                 C  s\   | j du rd}n$| jtjkr*tj| _d}n
| j  }|rX| jrH| j nd| _| 	d |S )z
        Cancels the current callback task if possible.

        Returns
        -------
        Whether the task was successfully stopped or done.
        NFT)
rW   r   r   r&   r'   cancelr   r]   r   r   )rj   r   r)   r)   r*   stop  s    


zChatFeed.stopz	List[Any])countrq   c                 C  s8   |dkrg S | j j}|| d }|d|  | j _|S )a,  
        Removes the last `count` of messages from the chat log and returns them.

        Parameters
        ----------
        count : int
            The number of messages to remove, starting from the last message.

        Returns
        -------
        The messages that were removed.
        r   N)rb   r5   )rj   r   messagesZundone_entriesr)   r)   r*   undo  s    zChatFeed.undoc                 C  s   | j j}| j   |S )z
        Clears the chat log and returns the messages that were cleared.

        Returns
        -------
        The messages that were cleared.
        )rb   r5   clear)rj   Zcleared_entriesr)   r)   r*   r     s    
zChatFeed.clear	assistantzList[ChatMessage]z!Dict[str, str | List[str]] | Noner   zList[Dict[str, Any]])r   
role_namesdefault_rolecustom_serializerrq   c                 C  s   |du rdg| j gd}i }| D ].\}}t|tr<|g}|D ]}||| < q@q$g }	|D ]}
|
j }||vr|std|
jd|d|||}|r||
j}t|tstdt	| dnt|
}|	
||d	 q\|	S )
zA
        Exports the chat log for use with transformers.
        Nr:   )r:   r   zUser z not found in role_names; got .zCThe provided custom_serializer must return a string; it returned a z type)rolecontent)r   itemsrY   r   lowerr:   r   rX   r   typer   )rj   r   r   r   r   Z
names_roler   namesnameZserialized_messagesr   Zlowercase_namer   r)   r)   r*   _serialize_for_transformers  s>    





z$ChatFeed._serialize_for_transformerstransformerszList[str] | NonezCallable | NonezLiteral['transformers'])exclude_users	filter_byformatr   c                   sx    du rdg ndd  D   fddj jD }|durF||}|dkrdj|fd|i|S td|d	dS )
a  
        Exports the chat log.

        Arguments
        ---------
        format : str
            The format to export the chat log as; currently only
            supports "transformers".
        exclude_users : list(str) | None
            A list of user (case insensitive names) to exclude from serialization.
            If not provided, defaults to ["help"]. This will be executed before `filter_by`.
        filter_by : callable
            A function to filter the chat log by.
            The function must accept and return a list of ChatMessage objects.
        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.
        **serialize_kwargs
            Additional keyword arguments to use for the specified format.

            - format="transformers"
              role_names : dict(str, str | list(str)) | None
                  A dictionary mapping the role to the ChatMessage's user name.
                  Defaults to `{"user": ["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.

        Returns
        -------
        The chat log serialized in the specified format.
        Nhelpc                 S  s   g | ]}|  qS r)   )r   ).0r:   r)   r)   r*   
<listcomp>(      z&ChatFeed.serialize.<locals>.<listcomp>c                   s(   g | ] }|j   vr|jur|qS r)   )r:   r   r   )r   r   r   rj   r)   r*   r   *  s   
r   r   zFormat z is not supported.)rb   r5   r   NotImplementedError)rj   r   r   r   r   Zserialize_kwargsr   r)   r   r*   	serialize  s"    ,zChatFeed.serializec                 C  sT   g }|du s:t |tr t | |s:t|rDt |tsD|| rD||  || j| S )a  
        Iterates over the ChatInterface and any potential children in the
        applying the selector.

        Arguments
        ---------
        selector: type or callable or None
          The selector allows selecting a subset of Viewables by
          declaring a type or callable function to filter by.

        Returns
        -------
        viewables: list(Viewable)
        N)rY   r   callabler   rg   select)rj   selectorselectedr)   r)   r*   r   9  s    
zChatFeed.select)NNN)N)N)NN)N)NNT)NNNF)r   )Nr   N)NNr   N)N)Lr!   r"   r#   __doc__r\   ZIntegerrH   r   r   ZObjectSelectorr   Stringr   r   rd   BooleanrR   r   rB   	ParameterrP   r   rN   r   r5   r`   r   r   Numberr   ZHookListr?   rG   rI   r   rJ   ZClassSelectorr   r   rZ   r   r   EventrV   r   r   r>   __annotations__r_   rs   rz   r{   dependsr}   r~   r   r   r   r   r   r   r   r   r   ri   r   r   r   r   r   r   r   r   r   r   __classcell__r)   r)   rl   r*   r,   :   s   

	M  	


   +-   .    >   4    @r,   )3r   
__future__r   r   r   enumr   inspectr   r   r   r   r   r	   ior
   typingr   r   r   r   r   r   r   r\   Z_paramr   Zio.resourcesr   Zlayoutr   r   Zlayout.cardr   Zlayout.spacerr   Z
pane.imager   r   r   Zbokeh.documentr   Zbokeh.modelr   Zpyviz_commsr   r   r   r   r+   r,   r)   r)   r)   r*   <module>   s.    $	