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:
@@ -59,7 +59,7 @@ from pipecat.processors.aggregators.llm_response import (
|
|||||||
from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
|
from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
|
||||||
from pipecat.processors.frame_processor import FrameDirection
|
from pipecat.processors.frame_processor import FrameDirection
|
||||||
from pipecat.services.ai_service import AIService
|
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.turns.user_turn_completion_mixin import UserTurnCompletionLLMServiceMixin
|
||||||
from pipecat.utils.context.llm_context_summarization import (
|
from pipecat.utils.context.llm_context_summarization import (
|
||||||
LLMContextSummarizationUtil,
|
LLMContextSummarizationUtil,
|
||||||
@@ -311,6 +311,29 @@ class LLMService(UserTurnCompletionLLMServiceMixin, AIService):
|
|||||||
await self._cancel_sequential_runner_task()
|
await self._cancel_sequential_runner_task()
|
||||||
await self._cancel_summary_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]):
|
async def _update_settings(self, settings: Mapping[str, Any]):
|
||||||
"""Update LLM service settings.
|
"""Update LLM service settings.
|
||||||
|
|
||||||
|
|||||||
@@ -31,10 +31,13 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import copy
|
import copy
|
||||||
from dataclasses import dataclass, field, fields
|
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
|
from loguru import logger
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from pipecat.turns.user_turn_completion_mixin import UserTurnCompletionConfig
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# NOT_GIVEN sentinel
|
# NOT_GIVEN sentinel
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
@@ -258,6 +261,13 @@ class LLMSettings(ServiceSettings):
|
|||||||
frequency_penalty: Frequency penalty.
|
frequency_penalty: Frequency penalty.
|
||||||
presence_penalty: Presence penalty.
|
presence_penalty: Presence penalty.
|
||||||
seed: Random seed for reproducibility.
|
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)
|
temperature: Any = field(default_factory=lambda: NOT_GIVEN)
|
||||||
@@ -267,6 +277,10 @@ class LLMSettings(ServiceSettings):
|
|||||||
frequency_penalty: Any = field(default_factory=lambda: NOT_GIVEN)
|
frequency_penalty: Any = field(default_factory=lambda: NOT_GIVEN)
|
||||||
presence_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)
|
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
|
@dataclass
|
||||||
|
|||||||
Reference in New Issue
Block a user