
    qi\                         d Z ddlmZmZmZ ddlmZ ddlmZm	Z	m
Z
mZmZ ddlmZ ddlmZmZ ddlmZ  G d d	e      Zy
)zBase AI service implementation.

Provides the foundation for all AI services in the Pipecat framework, including
model management, settings handling, and frame processing lifecycle methods.
    )AnyAsyncGeneratorDict)logger)CancelFrameEndFrame
ErrorFrameFrame
StartFrame)MetricsData)FrameDirectionFrameProcessor)ServiceSettingsc                        e Zd ZdZddedz  f fdZ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d Zdedef fdZdeedz  df   fdZdefdZde	fdZdefdZ xZS )	AIServicea'  Base class for all AI services.

    Provides common functionality for AI services including model management,
    settings handling, session properties, and frame processing lifecycle.
    Subclasses should implement specific AI functionality while leveraging
    this base infrastructure.
    Nsettingsc                     t        |   di | |xs
 t               | _        | j	                          i | _        d| _        d| _        y)zInitialize the AI service.

        Args:
            settings: The runtime-updatable settings for the AI service.
            **kwargs: Additional arguments passed to the parent FrameProcessor.
        FN )super__init__r   	_settings_sync_model_name_to_metrics_session_properties_tracing_enabled_tracing_context)selfr   kwargs	__class__s      M/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/services/ai_service.pyr   zAIService.__init__&   sR     	"6" !  	 	 	((*35 &+ $    c                     | j                  t        | j                  | j                  j                  xs d             y)ak  Sync the current AI model name (in `self._settings.model`) for usage in metrics.

        We don't store model name here because there's already a single source
        of truth for it in `self._settings.model`. This method is just for
        syncing the model name to the metrics data.

        Args:
            model: The name of the AI model to use.
         )	processormodelN)set_core_metrics_datar   namer   r$   )r   s    r   r   z%AIService._sync_model_name_to_metrics9   s/     	""$))4>>3G3G3M2N	
r    framec                    K   | j                   j                          |j                  | _        |j                  | _        yw)a  Start the AI service.

        Called when the service should begin processing. Subclasses should
        override this method to perform service-specific initialization.

        Args:
            frame: The start frame containing initialization parameters.
        N)r   validate_completeenable_tracingr   tracing_contextr   r   r'   s     r   startzAIService.startG   s4      	((* % 4 4 % 5 5s   >A c                    K   yw)zStop the AI service.

        Called when the service should stop processing. Subclasses should
        override this method to perform cleanup operations.

        Args:
            frame: The end frame.
        Nr   r,   s     r   stopzAIService.stopT         	   c                    K   yw)zCancel the AI service.

        Called when the service should cancel all operations. Subclasses should
        override this method to handle cancellation logic.

        Args:
            frame: The cancel frame.
        Nr   r,   s     r   cancelzAIService.cancel_   r0   r1   deltareturnc                    K   | j                   j                  |      }d|v r| j                          |r-t        j                  | j
                   dt        |              |S w)ag  Apply a settings delta and return the changed fields.

        The delta is applied to ``_settings`` and a dict mapping each changed
        field name to its **pre-update** value is returned.  The ``model``
        field is handled specially: when it changes, ``set_model_name`` is
        called.

        Concrete services should override this method (calling ``super()``)
        to react to specific changed fields (e.g. reconnect on voice change).

        Args:
            delta: A delta-mode settings object.

        Returns:
            Dict mapping changed field names to their previous values.
        r$   z: updated settings fields: )r   apply_updater   r   infor&   set)r   r4   changeds      r   _update_settingszAIService._update_settingsj   sX     " ..--e4g,,.KK499+%@WOPs   A!A#c                     |r@dj                  t        |            }t        j                  | j                   d| d       yy)a;  Log a warning for settings changes that won't take effect at runtime.

        Convenience helper for ``_update_settings`` overrides.  Accepts any
        iterable of field names (a ``dict``, ``set``, ``dict_keys``, etc.).

        Args:
            unhandled: Field names that changed but are not applied.
        z, z: runtime update of [z] is not currently supportedN)joinsortedr   warningr&   )r   	unhandledfieldss      r    _warn_unhandled_updated_settingsz*AIService._warn_unhandled_updated_settings   s>     YYvi01FNNdii[(=fXEabc r    	directionc                 J  K   t         |   ||       d{    t        |t              r| j	                  |       d{    yt        |t
              r| j                  |       d{    yt        |t              r| j                  |       d{    yy7 7 \7 47 w)a"  Process frames and handle service lifecycle.

        Automatically handles StartFrame, EndFrame, and CancelFrame by calling
        the appropriate lifecycle methods.

        Args:
            frame: The frame to process.
            direction: The direction of frame processing.
        N)	r   process_frame
isinstancer   _startr   _stopr   _cancel)r   r'   rC   r   s      r   rE   zAIService.process_frame   s      g#E9555eZ(++e$$$x(**U###{+,,u%%% , 	6 %#%sE   B#B(B# B)B#*B+)B#B!B#B#B#!B#	generatorc                    K   |2 3 d{   }|st        |t              r| j                  |       d{    6| j                  |       d{    P7 K7 !7 	6 yw)a  Process frames from an async generator.

        Takes an async generator that yields frames and processes each one,
        handling error frames specially by pushing them as errors.

        Args:
            generator: An async generator that yields Frame objects or None.
        N)rF   r	   push_error_frame
push_frame)r   rJ   fs      r   process_generatorzAIService.process_generator   s_      ! 	- 	-!a,//222//!,,,	- 3, !sL   AAAAA$AAAAAAAAAc                    K   	 | j                  |       d {    y 7 # t        $ r'}t        j                  |  d| d|        Y d }~y d }~ww xY wwNz: exception processing z: )r-   	Exceptionr   errorr   r'   es      r   rG   zAIService._start   sP     	G**U### 	GLLD6!8r!EFF	G6   A    A  	AAAAAc                    K   	 | j                  |       d {    y 7 # t        $ r'}t        j                  |  d| d|        Y d }~y d }~ww xY wwrQ   )r/   rR   r   rS   rT   s      r   rH   zAIService._stop   sP     	G))E""" 	GLLD6!8r!EFF	GrV   c                    K   	 | j                  |       d {    y 7 # t        $ r'}t        j                  |  d| d|        Y d }~y d }~ww xY wwrQ   )r3   rR   r   rS   rT   s      r   rI   zAIService._cancel   sP     	G++e$$$ 	GLLD6!8r!EFF	GrV   )N)__name__
__module____qualname____doc__r   r   r   r   r-   r   r/   r   r3   r   strr   r;   rB   r
   r   rE   r   rO   rG   rH   rI   __classcell__)r   s   @r   r   r      s    %4!7 %&
6 6	 		+ 	O S#X 6d& &> &&-d@R1S - G* GG GG; Gr    r   N)r\   typingr   r   r   logurur   pipecat.frames.framesr   r   r	   r
   r   pipecat.metrics.metricsr   "pipecat.processors.frame_processorr   r   pipecat.services.settingsr   r   r   r    r   <module>re      s:    - ,   0 M 5hG hGr    