
    qi?                        d Z ddl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mZ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	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(m)Z)m*Z*m+Z+m,Z, dd
l-m.Z.m/Z/ ddl0m1Z1m2Z2 ddl3m4Z4 ddl5m6Z6 ddl7m8Z8 ddl9m:Z: ddl;m<Z< ddl=m>Z>m?Z? e	dged   f   Z@ G d de      ZAe G d d             ZBe G d d             ZCe G d d             ZD G d de<e8      ZEy)zMBase classes for Large Language Model services with function calling support.    N)	dataclass)	Any	AwaitableCallableDictMappingOptionalProtocolSequenceType)logger)BaseLLMAdapter)DirectFunctionDirectFunctionWrapper)OpenAILLMAdapter)CancelFrameEndFrameFrameFunctionCallCancelFrameFunctionCallFromLLMFunctionCallInProgressFrameFunctionCallResultFrameFunctionCallResultPropertiesFunctionCallsStartedFrameInterruptionFrameLLMConfigureOutputFrameLLMContextSummaryRequestFrameLLMContextSummaryResultFrameLLMFullResponseEndFrameLLMFullResponseStartFrameLLMTextFrameLLMUpdateSettingsFrame
StartFrameUserImageRequestFrame)
LLMContextLLMSpecificMessage)LLMAssistantAggregatorParamsLLMUserAggregatorParams)OpenAILLMContext)FrameDirection)	AIService)LLMSettings)!UserTurnCompletionLLMServiceMixin)DEFAULT_SUMMARIZATION_TIMEOUTLLMContextSummarizationUtilFunctionCallParamsc                   0    e Zd ZdZdddedee   ddfdZy)FunctionCallResultCallbackzlProtocol for function call result callbacks.

    Handles the result of an LLM function call execution.
    N
propertiesresultr4   returnc                   K   yw)zCall the result callback.

        Args:
            result: The result of the function call.
            properties: Optional properties for the result.
        N )selfr5   r4   s      N/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/services/llm_service.py__call__z#FunctionCallResultCallback.__call__P   s      	s   )__name__
__module____qualname____doc__r   r	   r   r;   r8       r:   r2   r2   J   s1     TX		*23O*P			r@   r2   c                   ^    e Zd ZU dZeed<   eed<   eeef   ed<   ded<   ee	z  ed<   e
ed<   y	)
r0   a  Parameters for a function call.

    Parameters:
        function_name: The name of the function being called.
        tool_call_id: A unique identifier for the function call.
        arguments: The arguments for the function.
        llm: The LLMService instance being used.
        context: The LLM context.
        result_callback: Callback to handle the result of the function call.
    function_nametool_call_id	arguments
LLMServicellmcontextresult_callbackN)r<   r=   r>   r?   str__annotations__r   r   r)   r%   r2   r8   r@   r:   r0   r0   \   s;    	 sCx  	
**//r@   c                   Z    e Zd ZU dZee   ed<   edz  ed<   eed<   eed<   dZ	ee
   ed<   y)	FunctionCallRegistryItema  Represents an entry in the function call registry.

    This is what the user registers when calling register_function.

    Parameters:
        function_name: The name of the function (None for catch-all handler).
        handler: The handler for processing function call parameters.
        cancel_on_interruption: Whether to cancel the call on interruption.
        timeout_secs: Optional per-tool timeout in seconds. Overrides the global
            ``function_call_timeout_secs`` for this specific function.
    rB   r   handlercancel_on_interruptionhandler_deprecatedNtimeout_secs)r<   r=   r>   r?   r	   rI   rJ   FunctionCallHandlerboolrP   floatr8   r@   r:   rL   rL   q   s9    
 C=  #:::  $(L(5/(r@   rL   c                   h    e Zd ZU dZeed<   eed<   eed<   eeef   ed<   e	e
z  ed<   dZee   ed<   y)	FunctionCallRunnerItema  Internal function call entry for the function call runner.

    The runner executes function calls in order.

    Parameters:
        registry_item: The registry item containing handler information.
        function_name: The name of the function.
        tool_call_id: A unique identifier for the function call.
        arguments: The arguments for the function.
        context: The LLM context.
        run_llm: Optional flag to control LLM execution after function call.
    registry_itemrB   rC   rD   rG   Nrun_llm)r<   r=   r>   r?   rL   rJ   rI   r   r   r)   r%   rW   r	   rR   r8   r@   r:   rU   rU      sC     ,+sCx  
**"GXd^"r@   rU   c                   ,    e Zd ZU dZeed<   eZee	   ed<   	 	 	 dHde
ded	ee   f fd
Zde	fdZdedefdZ	 	 dIdeez  dee   dee   dee   fdZ e        e       ddedededefdZdef fdZdef fdZdef fdZd Z dede!eef   f fdZ"de#de$f fdZ%e$jL                  fde#de$f fd Z'd!efd"Z(d#e)fd$Z*de+fd%Z,de+fd&Z-de+de.eef   fd'Z/	 dJddd(d)ee   d*ed+e
d,ee   fd-Z0ddd(d*e1d+e
d,ee   fd.Z2d)ee   fd/Z3d*efd0Z4d)efd1Z5d2e6e7   fd3Z8dddddd4d5ed)ee   d6ee   d7ee   d8ee   d9ee   fd:Z9d; Z:d< Z;d= Z<d> Z=d?e6e>   fd@Z?d?e6e>   fdAZ@deez  d)efdBZAdCe>fdDZBd)ee   fdEZCdFeDj                  fdGZF xZGS )KrE   ac  Base class for all LLM services.

    Handles function calling registration and execution with support for both
    parallel and sequential execution modes. Provides event handlers for
    completion timeouts and function call lifecycle events.

    The service supports the following event handlers:

    - on_completion_timeout: Called when an LLM completion timeout occurs
    - on_function_calls_started: Called when function calls are received and
      execution is about to start

    Example::

        @task.event_handler("on_completion_timeout")
        async def on_completion_timeout(service):
            logger.warning("LLM completion timed out")

        @task.event_handler("on_function_calls_started")
        async def on_function_calls_started(service, function_calls):
            logger.info(f"Starting {len(function_calls)} function calls")
    	_settingsadapter_classT      $@Nrun_in_parallelfunction_call_timeout_secssettingsc                 :   t        |   dd|xs
 t               i| || _        || _        d| _        d| _        i | _        | j                         | _	        i | _
        i | _        d| _        d| _        d| _        | j                  d       | j                  d       y)a  Initialize the LLM service.

        Args:
            run_in_parallel: Whether to run function calls in parallel or sequentially.
                Defaults to True.
            function_call_timeout_secs: Timeout in seconds for deferred function calls.
                Defaults to 10.0 seconds.
            settings: The runtime-updatable settings for the LLM service.
            **kwargs: Additional arguments passed to the parent AIService.

        r^   FNon_function_calls_startedon_completion_timeoutr8   )super__init__r,   _run_in_parallel_function_call_timeout_secs_filter_incomplete_user_turns_base_system_instruction_start_callbacksrZ   _adapter
_functions_function_call_tasks_sequential_runner_task	_skip_tts_summary_task_register_event_handler)r9   r\   r]   r^   kwargs	__class__s        r:   rc   zLLMService.__init__   s    $ 	 	
  }		

 	
 !0+E(38*7;% "**,IKZ\!?C$)-59$$%@A$$%<=r@   r6   c                     | j                   S )zuGet the LLM adapter instance.

        Returns:
            The adapter instance used for LLM communication.
        )ri   r9   s    r:   get_llm_adapterzLLMService.get_llm_adapter   s     }}r@   messagec                 @    | j                         j                  |      S )zCreate an LLM-specific message (as opposed to a standard message) for use in an LLMContext.

        Args:
            message: The message content.

        Returns:
            A LLMSpecificMessage instance.
        )rt   create_llm_specific_message)r9   ru   s     r:   rw   z&LLMService.create_llm_specific_message   s     ##%AA'JJr@   rG   
max_tokenssystem_instructionc                 N   K   t        d| j                  j                         w)a  Run a one-shot, out-of-band (i.e. out-of-pipeline) inference with the given LLM context.

        Must be implemented by subclasses.

        Args:
            context: The LLM context containing conversation history.
            max_tokens: Optional maximum number of tokens to generate. If provided,
                overrides the service's default max_tokens/max_completion_tokens setting.
            system_instruction: Optional system instruction to use for this inference.
                If provided, overrides any system instruction in the context.

        Returns:
            The LLM's response as a string, or None if no response is generated.
        z!run_inference() not supported by )NotImplementedErrorrq   r<   )r9   rG   rx   ry   s       r:   run_inferencezLLMService.run_inference   s&     ( "$EdnnF]F]E^"_``s   #%)user_paramsassistant_paramsr}   r~   c                    t        j                         5  t        j                  d       t        j                  dt        d       ddd       y# 1 sw Y   yxY w)a  Create a context aggregator for managing LLM conversation context.

        Must be implemented by subclasses.

        Args:
            context: The LLM context to create an aggregator for.
            user_params: Parameters for user message aggregation.
            assistant_params: Parameters for assistant message aggregation.

        Returns:
            A context aggregator instance.

        .. deprecated:: 0.0.99
            `create_context_aggregator()` is deprecated and will be removed in a future version.
            Use the universal `LLMContext` and `LLMContextAggregatorPair` instead.
            See `OpenAILLMContext` docstring for migration guide.
        alwayszcreate_context_aggregator() is deprecated and will be removed in a future version. Use the universal LLMContext and LLMContextAggregatorPair directly instead. See OpenAILLMContext docstring for migration guide.   
stacklevelN)warningscatch_warningssimplefilterwarnDeprecationWarning)r9   rG   r}   r~   s       r:   create_context_aggregatorz$LLMService.create_context_aggregator  sR    0 $$& 	!!(+MMF #	 		 	s   2AAframec                    K   t         |   |       d{    | j                  s| j                          d{    yy7 *7 w)zRStart the LLM service.

        Args:
            frame: The start frame.
        N)rb   startrd   _create_sequential_runner_taskr9   r   rq   s     r:   r   zLLMService.start/  sD      gmE"""$$55777 % 	#7s   AA#AAAAc                    K   t         |   |       d{    | j                  s| j                          d{    | j	                          d{    y7 A7 7 	w)zOStop the LLM service.

        Args:
            frame: The end frame.
        N)rb   stoprd   _cancel_sequential_runner_task_cancel_summary_taskr   s     r:   r   zLLMService.stop9  sU      gl5!!!$$55777''))) 	"7)1   AA#AAAAAAAc                    K   t         |   |       d{    | j                  s| j                          d{    | j	                          d{    y7 A7 7 	w)zTCancel the LLM service.

        Args:
            frame: The cancel frame.
        N)rb   cancelrd   r   r   r   s     r:   r   zLLMService.cancelD  sU      gnU###$$55777''))) 	$7)r   c                     | j                   }| j                  j                  }|r| d| | j                  _        y|| j                  _        y)zCompose system_instruction by appending turn completion instructions.

        Combines the base system instruction with turn completion instructions
        and writes the result to ``self._settings.system_instruction``.
        z

N)rg   _user_turn_completion_configcompletion_instructionsrY   ry   )r9   baser   s      r:   _compose_system_instructionz&LLMService._compose_system_instructionO  sI     ,,"&"C"C"["[37&=T<U0VDNN-0GDNN-r@   deltac                   K   t         |   |       d{   }d|v r| j                  j                  xs d| _        t        j                  |  d| j                  rdnd        | j                  r,| j                  j                  | _        | j                          n"| j                  | j                  _        d| _        d|v rA| j                  r5| j                  | j                  j                         | j                          d|v r;| j                  r/d|vr+| j                  j                  | _        | j                          |S 7 0w)	zApply a settings delta, handling turn-completion fields.

        Args:
            delta: An LLM settings delta.

        Returns:
            Dict mapping changed field names to their previous values.
        Nfilter_incomplete_user_turnsFz: Incomplete turn filtering enableddisableduser_turn_completion_configry   )rb   _update_settingsrY   r   rf   r   infory   rg   r   set_user_turn_completion_configr   )r9   r   changedrq   s      r:   r   zLLMService._update_settings\  s(     077)W4;;Du . KK&4 $ B B9
SU 11040Q0Q-002 594Q4Q104-(G38Z8Z001[1[\,,. !G+22.g= -1NN,M,MD),,.C 8s   E	ED0E		directionc                    K   t         |   ||       d{    t        |t              r| j	                  |       d{    yt        |t
              r|j                  | _        yt        |t              r|j                  $| j                  |j                         d{    y|j                  rt        j                         5  t        j                  d       t        j                  dt         d       ddd       t#        | j$                        j'                  |j                        }| j                  |       d{    yyt        |t(              r| j+                  |       d{    yy7 _7 97 # 1 sw Y   xY w7 E7 w)zProcess a frame.

        Args:
            frame: The frame to process.
            direction: The direction of frame processing.
        Nr   zPassing a dict via LLMUpdateSettingsFrame(settings={...}) is deprecated since 0.0.104, use LLMUpdateSettingsFrame(delta=LLMSettings(...)) instead.r   r   )rb   process_frame
isinstancer   _handle_interruptionsr   skip_ttsrm   r"   r   r   r^   r   r   r   r   r   typerY   from_mappingr   _handle_summary_request)r9   r   r   r   rq   s       r:   r   zLLMService.process_frame  sG     g#E9555e./,,U33367"^^DN56{{&++EKK888,,. ))(3MMe*#$	 T^^,99%..I++E222   <=..u555 >+ 	6 4
 9  35sk   FE6(F E9A!F"E<#%F2E>:A
FF
*F/F0F9F<F>FFFc                    K   t        |t        t        t        f      r| j                  | j                  |_        t        |   ||       d{    y7 w)zPushes a frame.

        Args:
            frame: The frame to push.
            direction: The direction of frame pushing.
        N)r   r!   r    r   rm   r   rb   
push_frame)r9   r   r   rq   s      r:   r   zLLMService.push_frame  sF      el,EG^_`~~)!%g 	222s   AAAAtextc                    K   | j                   r| j                  |       d{    y| j                  t        |             d{    y7 (7 w)a   Push LLM text, using turn completion detection if enabled.

        This helper method simplifies text pushing in LLM implementations by
        handling the conditional logic for turn completion internally.

        Args:
            text: The text content from the LLM to push.
        N)rf   _push_turn_textr   r!   )r9   r   s     r:   _push_llm_textzLLMService._push_llm_text  sE      --&&t,,,//,t"4555 -5s!   !AA"AAAA_c                    K   | j                   j                         D ]+  \  }}|j                  s| j                  |       d {    - y 7 wN)rj   itemsrN   _cancel_function_call)r9   r   rB   entrys       r:   r   z LLMService._handle_interruptions  sI     $(OO$9$9$; 	@ M5++00???	@?s   -AAAAc                    K   t        j                  |  d|j                          | j                  | j	                  |            | _        yw)a  Handle context summarization request from aggregator.

        Processes a summarization request by generating a compressed summary
        of conversation history. Uses the adapter to format the summary
        according to the provider's requirements. Broadcasts the result back
        to the aggregator for context reconstruction.

        Args:
            frame: The summary request frame containing context and parameters.
        z#: Processing summarization request N)r   debug
request_idcreate_task_generate_summary_taskrn   )r9   r   s     r:   r   z"LLMService._handle_summary_request  sG      	v@AQAQ@RST "--d.I.I%.PQs   AAc                   K   d}d}d}|j                   xs t        }	 t        j                  | j	                  |      |       d{   \  }}| j                  t        |j                  |||
       d{    d| _        y7 ;# t        j
                  $ r" | j                  d| d       d{  7   Y jt        $ r+}d| }| j                  ||	       d{  7   Y d}~d}~ww xY w7 xw)zBackground task to generate summary without blocking the pipeline.

        Args:
            frame: The summary request frame containing context and parameters.
         N)timeoutz&Context summarization timed out after s)	error_msgz"Error generating context summary: )	exception)r   summarylast_summarized_indexerror)summarization_timeoutr.   asynciowait_for_generate_summaryTimeoutError
push_error	Exceptionbroadcast_framer   r   rn   )r9   r   r   
last_indexr   r   es          r:   r   z!LLMService._generate_summary_task  s     
--N1N		6(/(8(8&&u-) #GZ ""(''", # 
 	
 	
 "%# ## 	a//.TU\T]]^,_/``` 	68<E//%1/555	6	
sp   C1)B BB 'C16C/7C1B ,C,1B42C,7C19C,C'CC'"C1'C,,C1c           	      >  K   t        j                  |j                  |j                        }|j                  s#t        j                  |  d       t        d      t        j                  |  dt        |j                         d|j                   d|j                          t        j                  |j                        }t        dd| dg	      }	 | j                  ||j                  |j                  
       d{   }|st        d      |j%                         }t        j&                  |  dt        |       dt        |j                         d       ||j                  fS 7 i# t        $ r$ t        d| j                   j"                   d      w xY ww)a@  Generate a compressed summary of conversation context.

        Uses the message selection logic to identify which messages
        to summarize, formats them as a transcript, and invokes the LLM to
        generate a concise summary. The summary is formatted according to the
        LLM provider's requirements using the adapter.

        Args:
            frame: The summary request frame containing context and configuration.

        Returns:
            Tuple of (formatted summary message, last_summarized_index).

        Raises:
            RuntimeError: If there are no messages to summarize, the service doesn't
                support run_inference(), or the LLM returns an empty summary.

        Note:
            Requires the service to implement run_inference() method for
            synchronous LLM calls.
        z: No messages to summarizezNo messages to summarizez: Generating summary for z messages (index 0 to z), target_context_tokens=userzConversation history:
)rolecontent)messages)rx   ry   NzLLM service z! does not implement run_inferencezLLM returned empty summaryz: Generated summary of z characters for z	 messages)r/   get_messages_to_summarizerG   min_messages_to_keepr   r   r   RuntimeErrorlenr   target_context_tokensformat_messages_for_summaryr%   r|   summarization_promptr{   rq   r<   stripr   )r9   r   r5   
transcriptsummary_contextsummary_texts         r:   r   zLLMService._generate_summary  s    . -FFMM555
 LLD6!;<=9::f-c&//.B-C D!778 9%%*%@%@$AC	
 1LLV__]
$%4KJ<2XYZ
		!%!3!3 66#(#=#= "4 " L ;<<#))+f+C,=+> ?v'(	3	

 V9999'
 # 	t~~6677XY 	s1   CF+E- E+E- A%F+E- --FF)rN   rP   rB   rM   rN   rP   c                    t        j                  |      }t        |j                        dkD  }|rLt	        j
                         5  t	        j                  d       t	        j                  dt               ddd       t        |||||      | j                  |<   |r\t	        j
                         5  t	        j                  d       t	        j                  dt               ddd       || j                  |<   yy# 1 sw Y   xY w# 1 sw Y   &xY w)a  Register a function handler for LLM function calls.

        Args:
            function_name: The name of the function to handle. Use None to handle
                all function calls with a catch-all handler.
            handler: The function handler. Should accept a single FunctionCallParams
                parameter.
            start_callback: Legacy callback function (deprecated). Put initialization
                code at the top of your handler instead.

                .. deprecated:: 0.0.59
                    The `start_callback` parameter is deprecated and will be removed in a future version.

            cancel_on_interruption: Whether to cancel this function call when an
                interruption occurs. Defaults to True.
            timeout_secs: Optional per-tool timeout in seconds. Overrides the global
                ``function_call_timeout_secs`` for this specific function. Defaults to
                None, which uses the global timeout.
           r   zFunction calls with parameters `(function_name, tool_call_id, arguments, llm, context, result_callback)` are deprecated, use a single `FunctionCallParams` parameter instead.NrB   rM   rN   rO   rP   zhParameter 'start_callback' is deprecated, just put your code on top of the actual function call instead.)inspect	signaturer   
parametersr   r   r   r   r   rL   rj   rh   )r9   rB   rM   start_callbackrN   rP   r   rO   s           r:   register_functionzLLMService.register_function;  s    8 %%g.	 !5!56:((* %%h/ D& *B'#91%*
& ((* %%h/~& 4BD!!-0 % & s   0C8/0D8DDc                |    t        |      }t        |j                  ||d|      | j                  |j                  <   y)a  Register a direct function handler for LLM function calls.

        Direct functions have their metadata automatically extracted from their
        signature and docstring, eliminating the need for accompanying
        configurations (as FunctionSchemas or in provider-specific formats).

        Args:
            handler: The direct function to register. Must follow DirectFunction protocol.
            cancel_on_interruption: Whether to cancel this function call when an
                interruption occurs. Defaults to True.
            timeout_secs: Optional per-tool timeout in seconds. Overrides the global
                ``function_call_timeout_secs`` for this specific function. Defaults to
                None, which uses the global timeout.
        Fr   N)r   rL   namerj   )r9   rM   rN   rP   wrappers        r:   register_direct_functionz#LLMService.register_direct_functionv  s8    * (0(@!,,#9$%)
%r@   c                 V    | j                   |= || j                  v r| j                  |= yy)zRemove a registered function handler.

        Args:
            function_name: The name of the function handler to remove.
        N)rj   rh   r9   rB   s     r:   unregister_functionzLLMService.unregister_function  s1     OOM*D111%%m4 2r@   c                 H    t        |      }| j                  |j                  = y)zRemove a registered direct function handler.

        Args:
            handler: The direct function handler to remove.
        N)r   rj   r   )r9   rM   r   s      r:   unregister_direct_functionz%LLMService.unregister_direct_function  s     (0OOGLL)r@   c                 t    d| j                   j                         v ry|| j                   j                         v S )zCheck if a function handler is registered.

        Args:
            function_name: The name of the function to check.

        Returns:
            True if the function is registered or if a catch-all handler (None)
            is registered.
        NT)rj   keysr   s     r:   has_functionzLLMService.has_function  s4     4??'')) 4 4 666r@   function_callsc           
        K   t        |      dk(  ry| j                  d|       d{    | j                  t        |       d{    g }|D ]  }|j                  | j
                  j                         v r| j
                  |j                     }nRd| j
                  j                         v r| j
                  d   }n&t        j                  |  d|j                   d       |j                  t        ||j                  |j                  |j                  |j                                | j                  r| j                  |       d{    y| j!                  |       d{    y7 F7 *7 %7 w)a#  Execute a sequence of function calls from the LLM.

        Triggers the on_function_calls_started event and executes functions
        either in parallel or sequentially based on the run_in_parallel setting.

        Args:
            function_calls: The function calls to execute.
        r   Nr`   )r   z is calling 'z', but it's not registered.)rV   rB   rC   rD   rG   )r   _call_event_handlerr   r   rB   rj   r   r   warningappendrU   rC   rD   rG   rd   _run_parallel_function_calls_run_sequential_function_calls)r9   r   runner_itemsfunction_callitems        r:   run_function_callszLLMService.run_function_calls  s]     ~!#&&'BNSSS""#<^"\\\+ 	M**doo.B.B.DD}'B'BC--//t,fM-*E*E)FFab &"&"/"="=!.!;!;+55)11	*   33LAAA55lCCC; 	T\2 BCsF   %E7E-E7E0DE7E3E7'E5(E70E73E75E7)rB   rC   text_contentvideo_sourcer   user_idrC   r  r  r   c          
      .  K   t        j                         5  t        j                  d       t        j                  dt               ddd       | j                  t        ||d|||      t        j                         d{    y# 1 sw Y   AxY w7 w)a  Request an image from a user.

        Pushes a UserImageRequestFrame upstream to request an image from the
        specified user. The user image can then be processed by the LLM.

        Use this function from a function call if you want the LLM to process
        the image. If you expect the image to be processed by a vision service,
        you might want to push a UserImageRequestFrame upstream directly.

        .. deprecated:: 0.0.92
            This method is deprecated, push a `UserImageRequestFrame` instead.

        Args:
            user_id: The ID of the user to request an image from.
            function_name: Optional function name associated with the request.
            tool_call_id: Optional tool call ID associated with the request.
            text_content: Optional text content/context for the image request.
            video_source: Optional video source identifier.
            timeout: Optional timeout for the requested image to be added to the LLM context.

        r   zUMethod `request_image_frame()` is deprecated, push a `UserImageRequestFrame` instead.NT)r  r   append_to_contextrB   rC   rG   )	r   r   r   r   r   r   r$   r*   UPSTREAM)r9   r  rB   rC   r  r  r   s          r:   request_image_framezLLMService.request_image_frame  s     > $$& 	!!(+MMg"	 oo!!"&+)$ ##
 	
 	
	 		
s(   B0B:BBBBBc                    K   | j                   s>t        j                         | _        | j	                  | j                               | _         y y wr   )rl   r   Queue_sequential_runner_queuer   _sequential_runner_handlerrs   s    r:   r   z)LLMService._create_sequential_runner_task  s>     ++,3MMOD)+/+;+;D<[<[<]+^D( ,s   AAc                 ~   K   | j                   r+| j                  | j                          d {    d | _         y y 7 wr   )rl   cancel_taskrs   s    r:   r   z)LLMService._cancel_sequential_runner_task  s9     ''""4#?#?@@@+/D( (@   +=;=c                 ~   K   | j                   r+| j                  | j                          d {    d | _         y y 7 wr   )rn   r  rs   s    r:   r   zLLMService._cancel_summary_task  s9     ""4#5#5666!%D 6r  c                    K   	 | j                   j                          d {   }| j                  | j                  |            }|| j                  |<   | d {    | j                  |= i7 K7 wr   )r  getr   _run_function_callrk   )r9   runner_itemtasks      r:   r  z%LLMService._sequential_runner_handler"  sp      $ = = A A CCK##D$;$;K$HID.9D%%d+ JJ))$/ C
 s!   A1A-8A1A/A1/A1r   c                    K   g }|D ]]  }| j                  | j                  |            }|j                  |       || j                  |<   |j	                  | j
                         _ y wr   )r   r  r   rk   add_done_callback_function_call_task_finished)r9   r   tasksr  r  s        r:   r   z'LLMService._run_parallel_function_calls,  sg     ' 	FK##D$;$;K$HIDLL.9D%%d+""4#D#DE		Fs   A&A(c                 d   K   |D ]%  }| j                   j                  |       d {    ' y 7 wr   )r  put)r9   r   r  s      r:   r   z)LLMService._run_sequential_function_calls4  s4     ' 	AK//33K@@@	A@s   $0.0c                   K   || j                   j                         v r  | j                   |   || |       d {    y d | j                   j                         v r | j                   d    || |       d {   S y 7 A7 wr   )rh   r   )r9   rG   rB   s      r:   _call_start_functionzLLMService._call_start_function9  s      D1166886$''6}dGTTTT**//114..t4]D'RRR 2 URs!   7A?A;;A?5A=6A?=A?r  c                     K   j                    j                  j                         v r j                  j                      n-d  j                  j                         v r j                  d    ny t        j                    dj                    dj
                   dj                           j                  j                  j                          d {     j                  t        j                   j
                  j                  j                         d {    d d ddt        dt        t           f fd fd	} j                   |             	 t!        j"                  d
       d {    t%        j&                  t(              rgj&                  j+                  j                  t-        j                   j
                  j                   j                               d {    nj.                  rGj'                  j                   j
                  j                   j                         d {    nRt-        j                   j
                  j                   j                        }j'                  |       d {    r+j7                         s j9                         d {    y y y 7 7 7 _7 7 7 ?# t0        $ rS}dj                    d| }t        j2                    d|         j5                  ||d       d {  7   Y d }~d }~ww xY w7 u# r,j7                         s j9                         d {  7   w w w xY ww)Nz Calling function [:z] with arguments )rB   rC   rD   rN   r3   r5   r4   c          	        K   r)j                         sj                         d {    j                  t        j                  j
                  j                  | j                  |       d {    y 7 Q7 w)N)rB   rC   rD   r5   rW   r4   )doner  r   r   rB   rC   rD   rW   )r5   r4   r  r9   timeout_tasks     r:   function_call_result_callbackzDLLMService._run_function_call.<locals>.function_call_result_callback_  s      L$5$5$7&&|444&&')77(55%//#++% '    5s"   'B A<AB 6A>7B >B c            
      T  K   	 j                   j                   nj                  } t        j                  |        d {    t	        j
                   dj                   dj                   d|  d        d        d {    y 7 J7 # t        j                  $ r  w xY ww)N Function call [r  z] timed out after z seconds. You can increase this timeout by passing `timeout_secs` to `register_function()`, or set a global default via `function_call_timeout_secs` on the LLM constructor.)	rP   re   r   sleepr   r   rB   rC   CancelledError)effective_timeoutr#  r   r  r9   s    r:   timeout_handlerz6LLMService._run_function_call.<locals>.timeout_handlers  s      ((4 %%99 "
 mm$5666f,[-F-F,GqIaIaHbbt  vG  uH Hh i
 4D999 7 :)) sA   B(<B BAB BB B(B B B%%B(r   )rB   rC   rD   rF   rG   rH   )argsparamszError executing function call [z]:  F)r   r   fatal)rB   rj   r   r   r   rC   rD   r  rG   r   r   rN   r   r	   r   r   r   r&  r   rM   r   invoker0   rO   r   r   r   r!  r  )	r9   r  r)  r+  r   error_messager#  r   r"  s	   ``    @@@r:   r  zLLMService._run_function_callA  sN    $$(<(<(>>??;#<#<=DT__))++??4(Df'(A(A'B!KD\D\C]]noz  pE  pE  oF  G	

 ''(;(;[=V=VWWW ""'%33$11!++#'#>#> # 
 	
 	
 04 RV		(01M(N	(	" ''(9:-	5 --"""$,,(=>ll))$..-&1&?&?%0%=%="-"7"7  + 3 3(E * 
 
 
 **,,#11#00#--#++5   0&1&?&?%0%=%="-"7"7  + 3 3(EF ,,v... L$5$5$7&&|444 %8|I 	X	
l #
" / 	U=k>W>W=XX[\][^_MLLD6=/23//MQe/TTT	U 5 L$5$5$7&&|444 %8|s   CM>KA	M>&K'AM>*K* K!A?K* K$AK* K&AK* (K()K* -&M>M	M>M>!K* $K* &K* (K* *	M3AM6L97M<M MM 	M>'M;2M53M;;M>c           	      F  K   t               }| j                  j                         D ]  \  }}|j                  j                  |k(  s |j                  }|j
                  }t        j                  |  d| d| d       |rE|j                  | j                         | j                  |       d {    |j                  |       | j                  t        ||       d {    t        j                  |  d| d| d        |D ]  }| j                  |        y 7 n7 ?w)Nz Cancelling function call [r  z]...)rB   rC   r%  z] has been cancelled)setrk   r   rV   rB   rC   r   r   remove_done_callbackr  r  addr   r   )r9   rB   cancelled_tasksr  r  r   rC   s          r:   r   z LLMService._cancel_function_call  s)    %!%!:!:!@!@!B 	aD+((66-G"00*77v%@a~UYZ[ --d.O.OP**4000#''-**+4l +    v%5dV1\NJ^_`'	a, $ 	4D--d3	4 1s+   AD!A'D!.D/0D!D >D!D!r  c                 <    || j                   v r| j                   |= y y r   )rk   )r9   r  s     r:   r  z'LLMService._function_call_task_finished  s#    4,,,))$/ -r@   )Tr[   N)NNr   )Hr<   r=   r>   r?   r,   rJ   r   rZ   r   r   rR   rS   r	   rc   rt   r   r&   rw   r%   r)   intrI   r|   r(   r'   r   r#   r   r   r   r   r   r   dictr   r   r*   r   
DOWNSTREAMr   r   r   r   r   r   r   tupler   r   r   r   r   r   r   r   r   r  r  r   r   r   r  rU   r   r   r  r  r   r   Taskr  __classcell__)rq   s   @r:   rE   rE      st   .  +;M4': !%,0*.	&>&> %*&> ;'	&>P 	K3 	K;M 	K %),0	a..a SMa %SM	a
 
#a4 0G/H9U9W!!! -	!
 7! 
!F8 8	* 	*	*+ 	*H*K *DcN *X6 6> 6> JXIbIb 3e 3 36 6@-> @
R3P R "2O "BA:-J A:uUXZ]U] A:N 	9B (,(,9B}9B 9B !%9B uo9B~ (,(,

 !%	

 uo
<5# 5*# *7# 7)Dx@S7T )D^ (,&*&*&*#'0
0
  }	0

 sm0
 sm0
 sm0
 %0
d_
0
&
0FxH^?_ FAJ`Aa A
S'*4SEHSr54J r5h4# 460 0r@   rE   )Fr?   r   r   r   dataclassesr   typingr   r   r   r   r   r	   r
   r   r   logurur   !pipecat.adapters.base_llm_adapterr   (pipecat.adapters.schemas.direct_functionr   r   )pipecat.adapters.services.open_ai_adapterr   pipecat.frames.framesr   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   *pipecat.processors.aggregators.llm_contextr%   r&   +pipecat.processors.aggregators.llm_responser'   r(   1pipecat.processors.aggregators.openai_llm_contextr)   "pipecat.processors.frame_processorr*   pipecat.services.ai_servicer+   pipecat.services.settingsr,   (pipecat.turns.user_turn_completion_mixinr-   /pipecat.utils.context.llm_context_summarizationr.   r/   rQ   r2   r0   rL   rU   rE   r8   r@   r:   <module>rK     s    T    !
 
 
  < Z F     * O = 1 1 V  45yFG  $ 0 0 0( ) ) )( # # #,u02I u0r@   