Add turn-completion fields to LLMSettings and handle them in the typed-service-settings path.

`filter_incomplete_user_turns` and `user_turn_completion_config` were only handled in the legacy dict-based `_update_settings` code path. This adds them to `LLMSettings` and introduces `LLMService._update_settings_from_typed` so the typed path handles them too.
This commit is contained in:
Paul Kompfner
2026-02-13 10:31:25 -05:00
parent 8a4ab611be
commit 444cbb6499
2 changed files with 39 additions and 2 deletions

View File

@@ -59,7 +59,7 @@ from pipecat.processors.aggregators.llm_response import (
from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
from pipecat.processors.frame_processor import FrameDirection
from pipecat.services.ai_service import AIService
from pipecat.services.settings import ServiceSettings
from pipecat.services.settings import LLMSettings, ServiceSettings, is_given
from pipecat.turns.user_turn_completion_mixin import UserTurnCompletionLLMServiceMixin
from pipecat.utils.context.llm_context_summarization import (
LLMContextSummarizationUtil,
@@ -311,6 +311,29 @@ class LLMService(UserTurnCompletionLLMServiceMixin, AIService):
await self._cancel_sequential_runner_task()
await self._cancel_summary_task()
async def _update_settings_from_typed(self, update: LLMSettings) -> set[str]:
"""Apply a typed settings update, handling turn-completion fields.
Args:
update: A typed LLM settings delta.
Returns:
Set of field names whose values actually changed.
"""
changed = await super()._update_settings_from_typed(update)
if "filter_incomplete_user_turns" in changed:
self._filter_incomplete_user_turns = self._settings.filter_incomplete_user_turns
logger.info(
f"{self}: Incomplete turn filtering "
f"{'enabled' if self._filter_incomplete_user_turns else 'disabled'}"
)
if "user_turn_completion_config" in changed and self._filter_incomplete_user_turns:
self.set_user_turn_completion_config(self._settings.user_turn_completion_config)
return changed
async def _update_settings(self, settings: Mapping[str, Any]):
"""Update LLM service settings.

View File

@@ -31,10 +31,13 @@ from __future__ import annotations
import copy
from dataclasses import dataclass, field, fields
from typing import Any, ClassVar, Dict, Mapping, Optional, Set, Type, TypeVar
from typing import TYPE_CHECKING, Any, ClassVar, Dict, Mapping, Optional, Set, Type, TypeVar
from loguru import logger
if TYPE_CHECKING:
from pipecat.turns.user_turn_completion_mixin import UserTurnCompletionConfig
# ---------------------------------------------------------------------------
# NOT_GIVEN sentinel
# ---------------------------------------------------------------------------
@@ -258,6 +261,13 @@ class LLMSettings(ServiceSettings):
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.
"""
temperature: Any = field(default_factory=lambda: NOT_GIVEN)
@@ -267,6 +277,10 @@ class LLMSettings(ServiceSettings):
frequency_penalty: Any = field(default_factory=lambda: NOT_GIVEN)
presence_penalty: Any = field(default_factory=lambda: NOT_GIVEN)
seed: Any = field(default_factory=lambda: NOT_GIVEN)
filter_incomplete_user_turns: bool | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
user_turn_completion_config: UserTurnCompletionConfig | _NotGiven = field(
default_factory=lambda: NOT_GIVEN
)
@dataclass