
    qiF                       U d Z ddlmZ ddlZddlZddlmZmZmZ ddl	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 e
rddlmZ 	 	 d	 	 	 	 	 	 	 dd	Z G d
 d      Z e       Zded<   	 ddZ edd      Ze G d d             Ze G d de             Ze G d de             Z e G d de             Z!e G d de             Z"e G d de             Z#y)u@  Settings infrastructure for Pipecat AI services.

Each service type has a settings dataclass (``LLMSettings``, ``TTSSettings``,
``STTSettings``, or a service-specific subclass).  The same class is used in
two distinct modes:

**Store mode** — the service's ``self._settings`` object that holds the full
current state.  Every field must have a real value; ``NOT_GIVEN`` is never
valid here.  Services that don't support an inherited field should set it to
``None``.  ``validate_complete()`` (called automatically in
``AIService.start()``) enforces this invariant.

**Delta mode** — a sparse update object carried by an
``*UpdateSettingsFrame``.  Only the fields the caller wants to change are set;
all others remain at their default of ``NOT_GIVEN``.  ``apply_update()``
merges a delta into a store, skipping any ``NOT_GIVEN`` fields.

Key helpers:

- ``NOT_GIVEN`` / ``is_given()`` — sentinel and check for "field not provided
  in this delta".
- ``apply_update(delta)`` — merge a delta into a store, returning changed
  fields.
- ``from_mapping(dict)`` — build a delta from a plain dict (for backward
  compatibility with dict-based ``*UpdateSettingsFrame``).
- ``validate_complete()`` — assert that a store has no ``NOT_GIVEN`` fields.
- ``extra`` dict — overflow for service-specific keys that don't map to a
  declared field.
    )annotationsN)	dataclassfieldfields)TYPE_CHECKINGAnyClassVarDictMappingOptionalTypeTypeVar)logger)Language)UserTurnCompletionConfigc                    |j                   }|rd|  d| d| d}n	d|  d| d}t        j                         5  t        j                  d       t        j                  |t
        |       ddd       y# 1 sw Y   yxY w)	a  Emit DeprecationWarning for a deprecated init parameter.

    Args:
        param_name: Name of the deprecated parameter.
        settings_class: The settings class to use instead.
        settings_field: Specific field on the settings class, if different
            from *param_name*.
        stacklevel: Stack depth for the warning.  Default ``3`` targets
            the caller's caller (i.e. user code that instantiated the service).
    zThe `z)` parameter is deprecated. Use `settings=(zB=...)` instead. If both are provided, `settings` takes precedence.zB(...)` instead. If both are provided, `settings` takes precedence.always)
stacklevelN)__name__warningscatch_warningssimplefilterwarnDeprecationWarning)
param_namesettings_classsettings_fieldr   settings_class_namemsgs         K/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/services/settings.py_warn_deprecated_paramr"   9   s      )11J<  01>2B CAB 	 J<  01 2AB 	
 
	 	 	" Fh'c-*EF F Fs   2A44A=c                  D     e Zd ZU dZdZded<   d fdZd	dZd
dZ xZ	S )	_NotGivenu  Sentinel meaning "this field was not included in the delta".

    ``NOT_GIVEN`` is distinct from ``None`` (which is a valid stored value,
    typically meaning "this service doesn't support this field").  Every
    settings field defaults to ``NOT_GIVEN`` so that delta-mode objects are
    sparse by default and ``apply_update`` can skip untouched fields.

    ``NOT_GIVEN`` must never appear in a store-mode object — see
    ``validate_complete()``.
    NzOptional[_NotGiven]	_instancec                \    | j                   t        | 	  |       | _         | j                   S N)r%   super__new__)cls	__class__s    r!   r)   z_NotGiven.__new__n   s'    == !GOC0CM}}    c                     y)N	NOT_GIVEN selfs    r!   __repr__z_NotGiven.__repr__s   s    r,   c                     y)NFr/   r0   s    r!   __bool__z_NotGiven.__bool__v   s    r,   )returnr$   )r5   str)r5   bool)
r   
__module____qualname____doc__r%   __annotations__r)   r2   r4   __classcell__)r+   s   @r!   r$   r$   `   s$    	 &*I")
r,   r$   r.   c                $    t        | t               S )a  Check whether a delta field was explicitly provided.

    Typically used when processing a delta to decide whether a field
    should be applied::

        if is_given(delta.voice):
            # caller wants to change the voice
            ...

    For store-mode objects this always returns ``True`` (since
    ``validate_complete`` ensures no ``NOT_GIVEN`` fields remain).

    Args:
        value: The value to check.

    Returns:
        ``True`` if *value* is anything other than ``NOT_GIVEN``.
    )
isinstancer$   )values    r!   is_givenr@      s    & %+++r,   _SServiceSettings)boundc                      e Zd ZU dZ ed       Zded<   	  ee      Zded<   	 i Z	ded	<   	 dd
Z
ddZedd       ZddZddZy)rB   u  Base class for runtime-updatable service settings.

    These settings capture the subset of a service's configuration that can
    be changed **while the pipeline is running** (e.g. switching the model or
    changing the voice).  They are *not* meant to capture every constructor
    parameter — only those that support live updates via
    ``*UpdateSettingsFrame``.

    Every AI service type (LLM, TTS, STT) extends this with its own fields.
    Each instance operates in one of two modes (see module docstring):

    - **Store mode** (``self._settings``): holds the full current state.
      Every field must be a real value — ``NOT_GIVEN`` is never valid.
      Use ``None`` for inherited fields the service doesn't support.
      Enforced at runtime by ``validate_complete()``.
    - **Delta mode** (``*UpdateSettingsFrame``): a sparse update.
      Only fields the caller wants to change are set; all others stay at
      the default ``NOT_GIVEN`` and are skipped by ``apply_update()``.

    Parameters:
        model: The model identifier used by the service.  Set to ``None``
            in store mode if the service has no model concept.
        extra: Overflow dict for service-specific keys that don't map to a
            declared field.
    c                     t         S r'   r.   r/   r,   r!   <lambda>zServiceSettings.<lambda>       ) r,   default_factorystr | None | _NotGivenmodelDict[str, Any]extraClassVar[Dict[str, str]]_aliasesc                    i }t        |       D ]C  }|j                  dk(  rt        | |j                        }t        |      s5|||j                  <   E |j	                  | j
                         |S )a  Return a dict of only the fields that are not ``NOT_GIVEN``.

        Primarily useful for delta-mode objects to inspect which fields were
        set.  For a store-mode object this returns all declared fields (since
        none should be ``NOT_GIVEN``).

        Skips the ``extra`` field itself but merges its entries into the
        returned dict at the top level.

        Returns:
            Dictionary mapping field names to their provided values.
        rN   )r   namegetattrr@   updaterN   )r1   resultfvals       r!   given_fieldszServiceSettings.given_fields   sf     "$ 	%Avv $'C}!$qvv	% 	djj!r,   c                   i }t        |       D ]{  }|j                  dk(  rt        ||j                  t              }t	        |      s:t        | |j                        }||k7  sVt        | |j                  |       |||j                  <   } |j                  j                         D ]?  \  }}| j                  j                  |t              }||k7  s,|| j                  |<   |||<   A |S )a  Merge a delta-mode object into this store-mode object.

        Only fields in *delta* that are **given** (i.e. not ``NOT_GIVEN``)
        are considered.  A field is "changed" if its new value differs from
        the current value.

        The ``extra`` dicts are merged: keys present in the delta overwrite
        keys in the target.

        Args:
            delta: A delta-mode settings object of the same type.

        Returns:
            A dict mapping each changed field name to its **pre-update** value.
            Use ``changed.keys()`` for the set of names, or index with
            ``changed["field"]`` to inspect the old value.

        Examples::

            # store-mode object (all fields given)
            current = TTSSettings(voice="alice", language="en")
            # delta-mode object (only voice is set)
            delta = TTSSettings(voice="bob")
            changed = current.apply_update(delta)
            # changed == {"voice": "alice"}
            # current.voice == "bob", current.language == "en"
        rN   )	r   rR   rS   r.   r@   setattrrN   itemsget)r1   deltachangedrV   new_valold_valkeys          r!   apply_updatezServiceSettings.apply_update   s    8 #% 		*Avv eQVVY7GG$dAFF+G'!affg.")		* "KK--/ 	'LCjjnnS)4G'!")

3&		' r,   c                
   t        |       D ch c]  }|j                   c}dhz
  }i }i }|j                         D ]0  \  }}| j                  j	                  ||      }||v r|||<   ,|||<   2  | di |}	||	_        |	S c c}w )a  Build a **delta-mode** settings object from a plain dictionary.

        This exists for backward compatibility with code that passes plain
        dicts via ``*UpdateSettingsFrame(settings={...})``.  The returned
        object is a delta: only the keys present in *settings* are set;
        all other fields remain ``NOT_GIVEN``.

        Keys are matched to dataclass fields by name.  Keys listed in
        ``_aliases`` are translated to their canonical name first.  Any
        remaining unrecognized keys are placed into ``extra``.

        Args:
            settings: A dictionary of setting names to values.

        Returns:
            A new delta-mode settings instance.

        Examples::

            delta = TTSSettings.from_mapping({"voice_id": "alice", "speed": 1.2})
            # delta.voice == "alice"  (via alias)
            # delta.language is NOT_GIVEN  (not in the dict)
            # delta.extra == {"speed": 1.2}
        rN   r/   )r   rR   r[   rP   r\   rN   )
r*   settingsrV   field_nameskwargsrN   ra   r?   	canonicalinstances
             r!   from_mappingzServiceSettings.from_mapping  s    4 (.c{3!qvv3wi?!# ""..* 	#JC((c2IK'$)y!"c
	# == 4s   B c           	     <   t        |       D cg c]A  }|j                  dk7  r0t        t        | |j                        t              r|j                  C }}|r@dj                  |      }t        j                  t        |       j                   d| d       yyc c}w )uQ  Check that this is a valid store-mode object (no ``NOT_GIVEN`` fields).

        Called automatically by ``AIService.start()`` to catch fields that a
        service forgot to initialize in its ``__init__``.  Can also be called
        manually after constructing a store-mode settings object.

        Logs a warning for each uninitialized field.  Failure to initialize
        all fields may or may not cause runtime issues — it depends on
        whether and how the service actually reads the field — but it indicates
        a deviation from expectations and should be fixed.
        rN   z, z&: the following fields are NOT_GIVEN: zh. All settings fields should be initialized in the service's __init__ (use None for unsupported fields).N)
r   rR   r>   rS   r$   joinr   errortyper   )r1   rV   missingnamess       r!   validate_completez!ServiceSettings.validate_completeD  s     D\
vv Zaff0Ey%Q FF
 

 IIg&ELL:&&''MeW U> ? 
s   ABc                ,    t        j                  |       S )zReturn a deep copy of this settings instance.

        Returns:
            A new settings object with the same field values.
        )copydeepcopyr0   s    r!   rr   zServiceSettings.copy]  s     }}T""r,   N)r5   rM   )r1   rA   r]   rA   r5   rM   )r*   zType[_S]rd   zMapping[str, Any]r5   rA   )r5   None)r1   rA   r5   rA   )r   r8   r9   r:   r   rL   r;   dictrN   rP   rX   rb   classmethodri   rp   rr   r/   r,   r!   rB   rB      so    8 %*:K$LE!L "$7E>7J *,H&+./b ' 'R2#r,   c                      e Zd ZdZy)ImageGenSettingsu   Runtime-updatable settings for image generation services.

    Used in both store and delta mode — see ``ServiceSettings``.

    Parameters:
        model: Image generation model identifier.
    Nr   r8   r9   r:   r/   r,   r!   rx   rx   k      r,   rx   c                      e Zd ZdZy)VisionSettingsu   Runtime-updatable settings for vision services.

    Used in both store and delta mode — see ``ServiceSettings``.

    Parameters:
        model: Vision model identifier.
    Nry   r/   r,   r!   r|   r|   v  rz   r,   r|   c                  >   e Zd ZU dZ ed       Zded<    ed       Zded<    ed	       Zd
ed<    ed       Z	ded<    ed       Z
d
ed<    ed       Zded<    ed       Zded<    ed       Zd
ed<    ed       Zded<    ed       Zded<   y)LLMSettingsu  Runtime-updatable settings for LLM services.

    Used in both store and delta mode — see ``ServiceSettings``.

    These fields are common across LLM providers.  Not every provider supports
    every field; in store mode, set unsupported fields to ``None`` (e.g. a
    service that doesn't support ``seed`` should initialize it as
    ``seed=None``).

    Parameters:
        model: LLM model identifier.
        system_instruction: System instruction/prompt for the model.
        temperature: Sampling temperature.
        max_tokens: Maximum tokens to generate.
        top_p: Nucleus sampling probability.
        top_k: Top-k sampling parameter.
        frequency_penalty: Frequency penalty.
        presence_penalty: Presence penalty.
        seed: Random seed for reproducibility.
        filter_incomplete_user_turns: Enable LLM-based turn completion detection
            to suppress bot responses when the user was cut off mid-thought.
            See ``examples/foundational/22-filter-incomplete-turns.py`` and
            ``UserTurnCompletionLLMServiceMixin``.
        user_turn_completion_config: Configuration for turn completion behavior
            when ``filter_incomplete_user_turns`` is enabled. Controls timeouts
            and prompts for incomplete turns.
    c                     t         S r'   rF   r/   r,   r!   rG   zLLMSettings.<lambda>      y r,   rI   rK   system_instructionc                     t         S r'   rF   r/   r,   r!   rG   zLLMSettings.<lambda>  s    ) r,   zfloat | None | _NotGiventemperaturec                     t         S r'   rF   r/   r,   r!   rG   zLLMSettings.<lambda>  s    y r,   zint | None | _NotGiven
max_tokensc                     t         S r'   rF   r/   r,   r!   rG   zLLMSettings.<lambda>  s    I r,   top_pc                     t         S r'   rF   r/   r,   r!   rG   zLLMSettings.<lambda>  rH   r,   top_kc                     t         S r'   rF   r/   r,   r!   rG   zLLMSettings.<lambda>      PY r,   frequency_penaltyc                     t         S r'   rF   r/   r,   r!   rG   zLLMSettings.<lambda>  r   r,   presence_penaltyc                     t         S r'   rF   r/   r,   r!   rG   zLLMSettings.<lambda>  s     r,   seedc                     t         S r'   rF   r/   r,   r!   rG   zLLMSettings.<lambda>  s    Zc r,   zbool | None | _NotGivenfilter_incomplete_user_turnsc                     t         S r'   rF   r/   r,   r!   rG   zLLMSettings.<lambda>  s    	 r,   z+UserTurnCompletionConfig | None | _NotGivenuser_turn_completion_configN)r   r8   r9   r:   r   r   r;   r   r   r   r   r   r   r   r   r   r/   r,   r!   r~   r~     s    8 27GX1Y.Y,1BS,TK)T).?P)QJ&Q&+<M&NE#N$):K$LE!L27HY2Z/Z16GX1Y.Y#(9J#KD
 K<ARc<d "9dOT)P!L r,   r~   c                  `    e Zd ZU dZ ed       Zded<    ed       Zded<   d	diZd
ed<   y)TTSSettingsuP  Runtime-updatable settings for TTS services.

    Used in both store and delta mode — see ``ServiceSettings``.

    In store mode, set unsupported fields to ``None`` (e.g. ``language=None``
    if the service doesn't expose a language setting).

    Parameters:
        model: TTS model identifier.
        voice: Voice identifier or name.
        language: Language for speech synthesis.  The union type reflects the
            *input* side: callers may pass a ``Language`` enum or a raw string
            in a delta.  However, the **stored** value (in store mode) is
            always a service-specific string or ``None`` —
            ``TTSService._update_settings`` converts ``Language`` enums via
            ``language_to_service_language()`` before writing, and
            ``__init__`` methods do the same at construction time.
    c                     t         S r'   rF   r/   r,   r!   rG   zTTSSettings.<lambda>  s    9 r,   rI   zstr | _NotGivenvoicec                     t         S r'   rF   r/   r,   r!   rG   zTTSSettings.<lambda>  r   r,   !Language | str | None | _NotGivenlanguagevoice_idrO   rP   N)	r   r8   r9   r:   r   r   r;   r   rP   r/   r,   r!   r   r     s:    & #3DEE?E27HY2ZH/Z*4g)>H&>r,   r   c                  0    e Zd ZU dZ ed       Zded<   y)STTSettingsu  Runtime-updatable settings for STT services.

    Used in both store and delta mode — see ``ServiceSettings``.

    In store mode, set unsupported fields to ``None`` (e.g. ``language=None``
    if the service auto-detects language).

    Parameters:
        model: STT model identifier.
        language: Language for speech recognition.  The union type reflects the
            *input* side: callers may pass a ``Language`` enum or a raw string
            in a delta.  However, the **stored** value (in store mode) is
            always a service-specific string or ``None`` —
            ``STTService._update_settings`` converts ``Language`` enums via
            ``language_to_service_language()`` before writing, and
            ``__init__`` methods do the same at construction time.
    c                     t         S r'   rF   r/   r,   r!   rG   zSTTSettings.<lambda>  r   r,   rI   r   r   N)r   r8   r9   r:   r   r   r;   r/   r,   r!   r   r     s    $ 38HY2ZH/Zr,   r   )N   )r   r6   r   rm   r   z
str | Noner   int)r?   r   r5   r7   )$r:   
__future__r   rr   r   dataclassesr   r   r   typingr   r   r	   r
   r   r   r   r   logurur   pipecat.transcriptions.languager   (pipecat.turns.user_turn_completion_mixinr   r"   r$   r.   r;   r@   rA   rB   rx   r|   r~   r   r   r/   r,   r!   <module>r      s@  < #   0 0 W W W  4Q "&	FFF F 	FN 4 !{	9 ",4 T*+ C# C# C#V    _   (/ ( (V ?/ ? ?4 [/ [ [r,   