o
    i)                     @  s  d dl mZ d dlZd dlZd dlZd dl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 dd	l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 ed ejdZ eG dd dZ!eG dd dZ"G dd deed  Z#G dd deZ$dS )    )annotationsN)AsyncIterable)	dataclass)AnyClassVarLiteral   )APIConnectionErrorAPIError)logger)DEFAULT_API_CONNECT_OPTIONS	NOT_GIVENAPIConnectOptions
NotGivenOr   )ChatContext)LLM	ChatChunk	LLMStream)Tool
ToolChoice)	max_retrytimeoutc                   @     e Zd ZU ded< ded< dS )
_LLMStatusbool	availablezasyncio.Task[None] | Nonerecovering_taskN__name__
__module____qualname____annotations__ r#   r#   e/var/www/html/livekit_bhavya/venv/lib/python3.10/site-packages/livekit/agents/llm/fallback_adapter.pyr         
 r   c                   @  r   )AvailabilityChangedEventr   llmr   r   Nr   r#   r#   r#   r$   r&      r%   r&   c                      sr   e Zd Zdddddd0 fddZed1ddZed1ddZdeeeedd2d'd(Z	d3d)d*Z
d4d.d/Z  ZS )5FallbackAdapterg      @r   g      ?F)attempt_timeoutmax_retry_per_llmretry_intervalretry_on_chunk_sentr'   	list[LLM]r)   floatr*   intr+   r,   r   returnNonec                  sl   t |dk r
tdt   || _|| _|| _|| _|| _dd | jD | _	| jD ]	}|
d| j q*dS )a  FallbackAdapter is an LLM that can fallback to a different LLM if the current LLM fails.

        Args:
            llm (list[LLM]): List of LLM instances to fallback to.
            attempt_timeout (float, optional): Timeout for each LLM attempt. Defaults to 5.0.
            max_retry_per_llm (int, optional): Internal retries per LLM. Defaults to 0, which means no
                internal retries, the failed LLM will be skipped and the next LLM will be used.
            retry_interval (float, optional): Interval between retries. Defaults to 0.5.
            retry_on_chunk_sent (bool, optional): Whether to retry when a LLM failed after chunks
                are sent. Defaults to False.

        Raises:
            ValueError: If no LLM instances are provided.
        r   z+at least one LLM instance must be provided.c                 S  s   g | ]}t d ddqS )TN)r   r   )r   ).0_r#   r#   r$   
<listcomp>H   s    z,FallbackAdapter.__init__.<locals>.<listcomp>metrics_collectedN)len
ValueErrorsuper__init___llm_instances_attempt_timeout_max_retry_per_llm_retry_interval_retry_on_chunk_sent_statuson_on_metrics_collected)selfr'   r)   r*   r+   r,   llm_instance	__class__r#   r$   r9   %   s   

zFallbackAdapter.__init__strc                 C     dS )Nr(   r#   rB   r#   r#   r$   modelO      zFallbackAdapter.modelc                 C  rG   )Nlivekitr#   rH   r#   r#   r$   providerS   rJ   zFallbackAdapter.providerN)toolsconn_optionsparallel_tool_callstool_choiceextra_kwargschat_ctxr   rM   list[Tool] | NonerN   r   rO   NotGivenOr[bool]rP   NotGivenOr[ToolChoice]rQ   NotGivenOr[dict[str, Any]]r   c             	   C  s   t | |||pg |||dS )N)r'   rN   rR   rM   rO   rP   rQ   )FallbackLLMStream)rB   rR   rM   rN   rO   rP   rQ   r#   r#   r$   chatW   s   
zFallbackAdapter.chatc                   s    | j D ]	}|d| j qd S Nr5   )r:   offrA   )rB   rC   r#   r#   r$   aclosek   s   
zFallbackAdapter.acloseargsr   kwargsc                 O  s   | j dg|R i | d S rY   )emit)rB   r\   r]   r#   r#   r$   rA   o   s   z%FallbackAdapter._on_metrics_collected)r'   r-   r)   r.   r*   r/   r+   r.   r,   r   r0   r1   )r0   rF   )rR   r   rM   rS   rN   r   rO   rT   rP   rU   rQ   rV   r0   r   r0   r1   )r\   r   r]   r   r0   r1   )r   r    r!   r9   propertyrI   rL   $DEFAULT_FALLBACK_API_CONNECT_OPTIONSr   rX   r[   rA   __classcell__r#   r#   rD   r$   r(   "   s$    *
r(   llm_availability_changedc                      s   e Zd ZU dZded< eeedd* fddZed+ddZed,ddZ	ddd-d!d"Z
d.d#d$Zd/d%d&Zd0d(d)Z  ZS )1rW   llm_fallback_adapterzClassVar[str]_llm_request_span_name)rO   rP   rQ   r'   r(   rR   r   rM   
list[Tool]rN   r   rO   rT   rP   rU   rQ   rV   r0   r1   c                  s6   t  j||||d || _|| _|| _|| _d | _d S )N)rR   rM   rN   )r8   r9   _fallback_adapter_parallel_tool_calls_tool_choice_extra_kwargs_current_stream)rB   r'   rR   rM   rN   rO   rP   rQ   rD   r#   r$   r9   v   s   
zFallbackLLMStream.__init__c                 C     | j d u r| jS | j jS N)rk   	_chat_ctxrR   rH   r#   r#   r$   rR         
zFallbackLLMStream.chat_ctxc                 C  rl   rm   )rk   _toolsrM   rH   r#   r#   r$   rM      ro   zFallbackLLMStream.toolsF)check_recoveryr   rq   r   AsyncIterable[ChatChunk]c                C sj  zT|j | j| j| j| j| jtj| j| j	j
| j	j| j	jdd4 I dH $}| }|2 z3 dH W }|r7d}|| _|V  q*6 W d  I dH  W dS 1 I dH sNw   Y  W dS  tjys   |rit|j d  t|j d   ty } z|rtj|j d|d  tj|j d	|d  d}~w ty   |rt|j d
  t|j d  w )ao  
        Try to generate with the given LLM.

        Args:
            llm: The LLM instance to generate with
            check_recovery: When True, indicates this is a background recovery check and the
                          result will not be used. Recovery checks verify if a previously
                          failed LLM has become available again.
        )r   r   r+   )rR   rM   rO   rP   rQ   rN   NFz recovery timed outz! timed out, switching to next LLMz recovery failed)exc_infoz failed, switching to next LLMz recovery unexpected errorz( unexpected error, switching to next LLM)rX   rn   rp   rh   ri   rj   dataclassesreplace_conn_optionsrg   r<   r;   r=   rk   asyncioTimeoutErrorr   warninglabelr
   	Exception	exception)rB   r'   rq   streamshould_set_currentchunker#   r#   r$   _try_generate   sp   2




zFallbackLLMStream._try_generatec                   sR   j jj j|   jd u s j r'd fdd}t|| _d S d S )Nr'   r   r0   r1   c                   sl   z*j | dd2 z3 d H W }q	6 d _td| j d jdt| dd W d S  ty5   Y d S w )NTr'   rq   zllm.FallbackAdapter, z
 recoveredrc   r'   r   )	r   r   r   inforz   rg   r^   r&   r{   )r'   r3   
llm_statusrB   r#   r$   _recover_llm_task   s   

z:FallbackLLMStream._try_recovery.<locals>._recover_llm_taskr'   r   r0   r1   )rg   r?   r:   indexr   donerw   create_task)rB   r'   r   r#   r   r$   _try_recovery   s   zFallbackLLMStream._try_recoveryc                   s|  t   }tdd | jjD }|rtd t| jjD ]\}}| jj| }|js,|rd}g }z3| j	|dd2 z&3 d H W }|j
rX|j
jrK||j
j7 }|j
jD ]}	||	j qO| j| q86 W  d S  ty   |jr{d|_| jdt|dd |s|r||d	}
| jjstj|j d
|
d  tj|j d|
d Y nw | | qtddd | jjD  dt   |  d)Nc                 s  s    | ]}|j  V  qd S rm   )r   )r2   r   r#   r#   r$   	<genexpr>   s    z)FallbackLLMStream._run.<locals>.<genexpr>z$all LLMs are unavailable, retrying.. Fr   rc   r   )	text_senttool_calls_sentzy failed after sending chunk, skip retrying. Set `retry_on_chunk_sent` to `True` to enable retrying after chunks are sent.)extraz' failed after sending chunk, retrying..zall LLMs failed (c                 S  s   g | ]}|j qS r#   )rz   )r2   r'   r#   r#   r$   r4      s    z*FallbackLLMStream._run.<locals>.<listcomp>z) after z seconds)timeallrg   r?   r   error	enumerater:   r   r   deltacontent
tool_callsappendname	_event_chsend_nowaitr{   r^   r&   r>   rz   ry   r   r	   )rB   
start_time
all_failedir'   r   r   r   result	tool_callr   r#   r#   r$   _run   sZ   

	



&zFallbackLLMStream._runevent_aiterc                   s   d S rm   r#   )rB   r   r#   r#   r$   _metrics_monitor_task#  s   z'FallbackLLMStream._metrics_monitor_task)r'   r(   rR   r   rM   rf   rN   r   rO   rT   rP   rU   rQ   rV   r0   r1   )r0   r   )r0   rf   )r'   r   rq   r   r0   rr   r   r_   )r   rr   r0   r1   )r   r    r!   re   r"   r   r9   r`   rR   rM   r   r   r   r   rb   r#   r#   rD   r$   rW   s   s   
 	
D
4rW   )%
__future__r   rw   rt   r   collections.abcr   r   typingr   r   r   _exceptionsr	   r
   logr   typesr   r   r   r   chat_contextr   r'   r   r   r   tool_contextr   r   r   ra   r   r&   r(   rW   r#   r#   r#   r$   <module>   s0    

Q