Update LLMs
This commit is contained in:
@@ -75,10 +75,12 @@ class AWSBedrockLLMSettings(LLMSettings):
|
|||||||
"""Settings for AWS Bedrock LLM services.
|
"""Settings for AWS Bedrock LLM services.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
stop_sequences: List of strings that stop generation.
|
||||||
latency: Performance mode - "standard" or "optimized".
|
latency: Performance mode - "standard" or "optimized".
|
||||||
additional_model_request_fields: Additional model-specific parameters.
|
additional_model_request_fields: Additional model-specific parameters.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
stop_sequences: List[str] | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||||
latency: str | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
latency: str | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||||
additional_model_request_fields: Dict[str, Any] | _NotGiven = field(
|
additional_model_request_fields: Dict[str, Any] | _NotGiven = field(
|
||||||
default_factory=lambda: NOT_GIVEN
|
default_factory=lambda: NOT_GIVEN
|
||||||
@@ -810,6 +812,10 @@ class AWSBedrockLLMService(LLMService):
|
|||||||
deprecated parameters and *settings* are provided, *settings*
|
deprecated parameters and *settings* are provided, *settings*
|
||||||
values take precedence.
|
values take precedence.
|
||||||
stop_sequences: List of strings that stop generation.
|
stop_sequences: List of strings that stop generation.
|
||||||
|
|
||||||
|
.. deprecated:: 0.0.105
|
||||||
|
Use ``settings=AWSBedrockLLMSettings(stop_sequences=...)`` instead.
|
||||||
|
|
||||||
client_config: Custom boto3 client configuration.
|
client_config: Custom boto3 client configuration.
|
||||||
retry_timeout_secs: Request timeout in seconds for retry logic.
|
retry_timeout_secs: Request timeout in seconds for retry logic.
|
||||||
retry_on_timeout: Whether to retry the request once if it times out.
|
retry_on_timeout: Whether to retry the request once if it times out.
|
||||||
@@ -828,6 +834,7 @@ class AWSBedrockLLMService(LLMService):
|
|||||||
seed=None,
|
seed=None,
|
||||||
filter_incomplete_user_turns=False,
|
filter_incomplete_user_turns=False,
|
||||||
user_turn_completion_config=None,
|
user_turn_completion_config=None,
|
||||||
|
stop_sequences=None,
|
||||||
latency=None,
|
latency=None,
|
||||||
additional_model_request_fields={},
|
additional_model_request_fields={},
|
||||||
)
|
)
|
||||||
@@ -836,6 +843,9 @@ class AWSBedrockLLMService(LLMService):
|
|||||||
if model is not None:
|
if model is not None:
|
||||||
_warn_deprecated_param("model", AWSBedrockLLMSettings, "model")
|
_warn_deprecated_param("model", AWSBedrockLLMSettings, "model")
|
||||||
default_settings.model = model
|
default_settings.model = model
|
||||||
|
if stop_sequences is not None:
|
||||||
|
_warn_deprecated_param("stop_sequences", AWSBedrockLLMSettings, "stop_sequences")
|
||||||
|
default_settings.stop_sequences = stop_sequences
|
||||||
|
|
||||||
# 3. Apply params overrides — only if settings not provided
|
# 3. Apply params overrides — only if settings not provided
|
||||||
if params is not None:
|
if params is not None:
|
||||||
@@ -844,6 +854,8 @@ class AWSBedrockLLMService(LLMService):
|
|||||||
default_settings.max_tokens = params.max_tokens
|
default_settings.max_tokens = params.max_tokens
|
||||||
default_settings.temperature = params.temperature
|
default_settings.temperature = params.temperature
|
||||||
default_settings.top_p = params.top_p
|
default_settings.top_p = params.top_p
|
||||||
|
if params.stop_sequences:
|
||||||
|
default_settings.stop_sequences = params.stop_sequences
|
||||||
default_settings.latency = params.latency
|
default_settings.latency = params.latency
|
||||||
if isinstance(params.additional_model_request_fields, dict):
|
if isinstance(params.additional_model_request_fields, dict):
|
||||||
default_settings.additional_model_request_fields = (
|
default_settings.additional_model_request_fields = (
|
||||||
@@ -856,14 +868,6 @@ class AWSBedrockLLMService(LLMService):
|
|||||||
|
|
||||||
super().__init__(settings=default_settings, **kwargs)
|
super().__init__(settings=default_settings, **kwargs)
|
||||||
|
|
||||||
# Handle stop_sequences (not a settings field)
|
|
||||||
if stop_sequences is not None:
|
|
||||||
self._stop_sequences = stop_sequences
|
|
||||||
elif params is not None:
|
|
||||||
self._stop_sequences = params.stop_sequences or []
|
|
||||||
else:
|
|
||||||
self._stop_sequences = []
|
|
||||||
|
|
||||||
# Initialize the AWS Bedrock client
|
# Initialize the AWS Bedrock client
|
||||||
if not client_config:
|
if not client_config:
|
||||||
client_config = Config(
|
client_config = Config(
|
||||||
@@ -915,6 +919,8 @@ class AWSBedrockLLMService(LLMService):
|
|||||||
inference_config["temperature"] = self._settings.temperature
|
inference_config["temperature"] = self._settings.temperature
|
||||||
if self._settings.top_p is not None:
|
if self._settings.top_p is not None:
|
||||||
inference_config["topP"] = self._settings.top_p
|
inference_config["topP"] = self._settings.top_p
|
||||||
|
if self._settings.stop_sequences:
|
||||||
|
inference_config["stopSequences"] = self._settings.stop_sequences
|
||||||
return inference_config
|
return inference_config
|
||||||
|
|
||||||
async def run_inference(
|
async def run_inference(
|
||||||
|
|||||||
@@ -191,12 +191,12 @@ class AWSNovaSonicLLMSettings(LLMSettings):
|
|||||||
"""Settings for AWS Nova Sonic LLM service.
|
"""Settings for AWS Nova Sonic LLM service.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
voice_id: Voice for speech synthesis.
|
voice: Voice identifier for speech synthesis.
|
||||||
endpointing_sensitivity: Controls how quickly Nova Sonic decides the
|
endpointing_sensitivity: Controls how quickly Nova Sonic decides the
|
||||||
user has stopped speaking. Can be "LOW", "MEDIUM", or "HIGH".
|
user has stopped speaking. Can be "LOW", "MEDIUM", or "HIGH".
|
||||||
"""
|
"""
|
||||||
|
|
||||||
voice_id: str | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
voice: str | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||||
endpointing_sensitivity: str | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
endpointing_sensitivity: str | None | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||||
|
|
||||||
|
|
||||||
@@ -250,7 +250,7 @@ class AWSNovaSonicLLMService(LLMService):
|
|||||||
- Nova Sonic (the older model): see https://docs.aws.amazon.com/nova/latest/userguide/available-voices.html.
|
- Nova Sonic (the older model): see https://docs.aws.amazon.com/nova/latest/userguide/available-voices.html.
|
||||||
|
|
||||||
.. deprecated::
|
.. deprecated::
|
||||||
Use ``settings=AWSNovaSonicLLMSettings(voice_id=...)`` instead.
|
Use ``settings=AWSNovaSonicLLMSettings(voice=...)`` instead.
|
||||||
|
|
||||||
params: Model parameters for audio configuration and inference.
|
params: Model parameters for audio configuration and inference.
|
||||||
|
|
||||||
@@ -273,7 +273,7 @@ class AWSNovaSonicLLMService(LLMService):
|
|||||||
# 1. Initialize default_settings with hardcoded defaults
|
# 1. Initialize default_settings with hardcoded defaults
|
||||||
default_settings = AWSNovaSonicLLMSettings(
|
default_settings = AWSNovaSonicLLMSettings(
|
||||||
model="amazon.nova-2-sonic-v1:0",
|
model="amazon.nova-2-sonic-v1:0",
|
||||||
voice_id="matthew",
|
voice="matthew",
|
||||||
temperature=0.7,
|
temperature=0.7,
|
||||||
max_tokens=1024,
|
max_tokens=1024,
|
||||||
top_p=0.9,
|
top_p=0.9,
|
||||||
@@ -291,8 +291,8 @@ class AWSNovaSonicLLMService(LLMService):
|
|||||||
_warn_deprecated_param("model", AWSNovaSonicLLMSettings, "model")
|
_warn_deprecated_param("model", AWSNovaSonicLLMSettings, "model")
|
||||||
default_settings.model = model
|
default_settings.model = model
|
||||||
if voice_id != "matthew":
|
if voice_id != "matthew":
|
||||||
_warn_deprecated_param("voice_id", AWSNovaSonicLLMSettings, "voice_id")
|
_warn_deprecated_param("voice_id", AWSNovaSonicLLMSettings, "voice")
|
||||||
default_settings.voice_id = voice_id
|
default_settings.voice = voice_id
|
||||||
|
|
||||||
# 3. Apply params overrides — only if settings not provided
|
# 3. Apply params overrides — only if settings not provided
|
||||||
if params is not None:
|
if params is not None:
|
||||||
@@ -811,7 +811,7 @@ class AWSNovaSonicLLMService(LLMService):
|
|||||||
"sampleRateHertz": {self._output_sample_rate},
|
"sampleRateHertz": {self._output_sample_rate},
|
||||||
"sampleSizeBits": {self._output_sample_size},
|
"sampleSizeBits": {self._output_sample_size},
|
||||||
"channelCount": {self._output_channel_count},
|
"channelCount": {self._output_channel_count},
|
||||||
"voiceId": "{self._settings.voice_id}",
|
"voiceId": "{self._settings.voice}",
|
||||||
"encoding": "base64",
|
"encoding": "base64",
|
||||||
"audioType": "SPEECH"
|
"audioType": "SPEECH"
|
||||||
}}{tools_config}
|
}}{tools_config}
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ class AzureRealtimeLLMService(OpenAIRealtimeLLMService):
|
|||||||
real-time audio and text communication capabilities as the base OpenAI service.
|
real-time audio and text communication capabilities as the base OpenAI service.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: AzureRealtimeLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ class CerebrasLLMService(OpenAILLMService):
|
|||||||
maintaining full compatibility with OpenAI's interface and functionality.
|
maintaining full compatibility with OpenAI's interface and functionality.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: CerebrasLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ class DeepSeekLLMService(OpenAILLMService):
|
|||||||
maintaining full compatibility with OpenAI's interface and functionality.
|
maintaining full compatibility with OpenAI's interface and functionality.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: DeepSeekLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ class FireworksLLMService(OpenAILLMService):
|
|||||||
maintaining full compatibility with OpenAI's interface and functionality.
|
maintaining full compatibility with OpenAI's interface and functionality.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: FireworksLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -610,6 +610,7 @@ class GeminiLiveLLMSettings(LLMSettings):
|
|||||||
"""Settings for Gemini Live LLM services.
|
"""Settings for Gemini Live LLM services.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
voice: TTS voice identifier (e.g. ``"Charon"``).
|
||||||
modalities: Response modalities.
|
modalities: Response modalities.
|
||||||
language: Language for generation.
|
language: Language for generation.
|
||||||
media_resolution: Media resolution setting.
|
media_resolution: Media resolution setting.
|
||||||
@@ -620,6 +621,7 @@ class GeminiLiveLLMSettings(LLMSettings):
|
|||||||
proactivity: Proactivity configuration.
|
proactivity: Proactivity configuration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
voice: str | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||||
modalities: GeminiModalities | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
modalities: GeminiModalities | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||||
language: Language | str | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
language: Language | str | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||||
media_resolution: GeminiMediaResolution | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
media_resolution: GeminiMediaResolution | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||||
@@ -680,6 +682,9 @@ class GeminiLiveLLMService(LLMService):
|
|||||||
Use ``settings=GeminiLiveLLMSettings(model=...)`` instead.
|
Use ``settings=GeminiLiveLLMSettings(model=...)`` instead.
|
||||||
|
|
||||||
voice_id: TTS voice identifier. Defaults to "Charon".
|
voice_id: TTS voice identifier. Defaults to "Charon".
|
||||||
|
|
||||||
|
.. deprecated:: 0.0.105
|
||||||
|
Use ``settings=GeminiLiveLLMSettings(voice=...)`` instead.
|
||||||
start_audio_paused: Whether to start with audio input paused. Defaults to False.
|
start_audio_paused: Whether to start with audio input paused. Defaults to False.
|
||||||
start_video_paused: Whether to start with video input paused. Defaults to False.
|
start_video_paused: Whether to start with video input paused. Defaults to False.
|
||||||
system_instruction: System prompt for the model. Defaults to None.
|
system_instruction: System prompt for the model. Defaults to None.
|
||||||
@@ -712,6 +717,7 @@ class GeminiLiveLLMService(LLMService):
|
|||||||
# 1. Initialize default_settings with hardcoded defaults
|
# 1. Initialize default_settings with hardcoded defaults
|
||||||
default_settings = GeminiLiveLLMSettings(
|
default_settings = GeminiLiveLLMSettings(
|
||||||
model="models/gemini-2.5-flash-native-audio-preview-12-2025",
|
model="models/gemini-2.5-flash-native-audio-preview-12-2025",
|
||||||
|
voice="Charon",
|
||||||
frequency_penalty=None,
|
frequency_penalty=None,
|
||||||
max_tokens=4096,
|
max_tokens=4096,
|
||||||
presence_penalty=None,
|
presence_penalty=None,
|
||||||
@@ -736,6 +742,9 @@ class GeminiLiveLLMService(LLMService):
|
|||||||
if model is not None:
|
if model is not None:
|
||||||
_warn_deprecated_param("model", GeminiLiveLLMSettings, "model")
|
_warn_deprecated_param("model", GeminiLiveLLMSettings, "model")
|
||||||
default_settings.model = model
|
default_settings.model = model
|
||||||
|
if voice_id != "Charon":
|
||||||
|
_warn_deprecated_param("voice_id", GeminiLiveLLMSettings, "voice")
|
||||||
|
default_settings.voice = voice_id
|
||||||
|
|
||||||
# 3. Apply params overrides — only if settings not provided
|
# 3. Apply params overrides — only if settings not provided
|
||||||
if params is not None:
|
if params is not None:
|
||||||
@@ -776,7 +785,6 @@ class GeminiLiveLLMService(LLMService):
|
|||||||
|
|
||||||
self._last_sent_time = 0
|
self._last_sent_time = 0
|
||||||
self._base_url = base_url
|
self._base_url = base_url
|
||||||
self._voice_id = voice_id
|
|
||||||
self._language_code = params.language if params is not None else Language.EN_US
|
self._language_code = params.language if params is not None else Language.EN_US
|
||||||
|
|
||||||
self._system_instruction_from_init = system_instruction
|
self._system_instruction_from_init = system_instruction
|
||||||
@@ -1184,7 +1192,7 @@ class GeminiLiveLLMService(LLMService):
|
|||||||
response_modalities=[Modality(self._settings.modalities.value)],
|
response_modalities=[Modality(self._settings.modalities.value)],
|
||||||
speech_config=SpeechConfig(
|
speech_config=SpeechConfig(
|
||||||
voice_config=VoiceConfig(
|
voice_config=VoiceConfig(
|
||||||
prebuilt_voice_config={"voice_name": self._voice_id}
|
prebuilt_voice_config={"voice_name": self._settings.voice}
|
||||||
),
|
),
|
||||||
language_code=self._settings.language,
|
language_code=self._settings.language,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ class GeminiLiveVertexLLMService(GeminiLiveLLMService):
|
|||||||
responses, and tool usage.
|
responses, and tool usage.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: GeminiLiveVertexLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
@@ -90,6 +92,9 @@ class GeminiLiveVertexLLMService(GeminiLiveLLMService):
|
|||||||
Use ``settings=GeminiLiveLLMSettings(model=...)`` instead.
|
Use ``settings=GeminiLiveLLMSettings(model=...)`` instead.
|
||||||
|
|
||||||
voice_id: TTS voice identifier. Defaults to "Charon".
|
voice_id: TTS voice identifier. Defaults to "Charon".
|
||||||
|
|
||||||
|
.. deprecated:: 0.0.105
|
||||||
|
Use ``settings=GeminiLiveVertexLLMSettings(voice=...)`` instead.
|
||||||
start_audio_paused: Whether to start with audio input paused. Defaults to False.
|
start_audio_paused: Whether to start with audio input paused. Defaults to False.
|
||||||
start_video_paused: Whether to start with video input paused. Defaults to False.
|
start_video_paused: Whether to start with video input paused. Defaults to False.
|
||||||
system_instruction: System prompt for the model. Defaults to None.
|
system_instruction: System prompt for the model. Defaults to None.
|
||||||
@@ -132,6 +137,7 @@ class GeminiLiveVertexLLMService(GeminiLiveLLMService):
|
|||||||
# 1. Initialize default_settings with hardcoded defaults
|
# 1. Initialize default_settings with hardcoded defaults
|
||||||
default_settings = GeminiLiveVertexLLMSettings(
|
default_settings = GeminiLiveVertexLLMSettings(
|
||||||
model="google/gemini-live-2.5-flash-native-audio",
|
model="google/gemini-live-2.5-flash-native-audio",
|
||||||
|
voice="Charon",
|
||||||
frequency_penalty=None,
|
frequency_penalty=None,
|
||||||
max_tokens=4096,
|
max_tokens=4096,
|
||||||
presence_penalty=None,
|
presence_penalty=None,
|
||||||
@@ -156,6 +162,9 @@ class GeminiLiveVertexLLMService(GeminiLiveLLMService):
|
|||||||
if model is not None:
|
if model is not None:
|
||||||
_warn_deprecated_param("model", GeminiLiveVertexLLMSettings, "model")
|
_warn_deprecated_param("model", GeminiLiveVertexLLMSettings, "model")
|
||||||
default_settings.model = model
|
default_settings.model = model
|
||||||
|
if voice_id != "Charon":
|
||||||
|
_warn_deprecated_param("voice_id", GeminiLiveVertexLLMSettings, "voice")
|
||||||
|
default_settings.voice = voice_id
|
||||||
|
|
||||||
# 3. Apply params overrides — only if settings not provided
|
# 3. Apply params overrides — only if settings not provided
|
||||||
if params is not None:
|
if params is not None:
|
||||||
@@ -193,7 +202,6 @@ class GeminiLiveVertexLLMService(GeminiLiveLLMService):
|
|||||||
# api_key is required by parent class, but actually not used with
|
# api_key is required by parent class, but actually not used with
|
||||||
# Vertex
|
# Vertex
|
||||||
api_key="dummy",
|
api_key="dummy",
|
||||||
voice_id=voice_id,
|
|
||||||
start_audio_paused=start_audio_paused,
|
start_audio_paused=start_audio_paused,
|
||||||
start_video_paused=start_video_paused,
|
start_video_paused=start_video_paused,
|
||||||
system_instruction=system_instruction,
|
system_instruction=system_instruction,
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ class GoogleLLMOpenAIBetaService(OpenAILLMService):
|
|||||||
https://ai.google.dev/gemini-api/docs/openai
|
https://ai.google.dev/gemini-api/docs/openai
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: GoogleOpenAILLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ class GoogleVertexLLMService(GoogleLLMService):
|
|||||||
https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference
|
https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/inference
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: GoogleVertexLLMSettings
|
||||||
|
|
||||||
class InputParams(GoogleLLMService.InputParams):
|
class InputParams(GoogleLLMService.InputParams):
|
||||||
"""Input parameters specific to Vertex AI.
|
"""Input parameters specific to Vertex AI.
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ class GrokLLMService(OpenAILLMService):
|
|||||||
processing and reports final totals.
|
processing and reports final totals.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: GrokLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ https://docs.x.ai/docs/guides/voice/agent
|
|||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
@@ -56,7 +56,7 @@ from pipecat.processors.aggregators.llm_response_universal 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.llm_service import FunctionCallFromLLM, LLMService
|
from pipecat.services.llm_service import FunctionCallFromLLM, LLMService
|
||||||
from pipecat.services.settings import NOT_GIVEN, LLMSettings, _NotGiven, _warn_deprecated_param
|
from pipecat.services.settings import LLMSettings
|
||||||
from pipecat.utils.time import time_now_iso8601
|
from pipecat.utils.time import time_now_iso8601
|
||||||
|
|
||||||
from . import events
|
from . import events
|
||||||
@@ -88,15 +88,9 @@ class CurrentAudioResponse:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class GrokRealtimeLLMSettings(LLMSettings):
|
class GrokRealtimeLLMSettings(LLMSettings):
|
||||||
"""Settings for Grok Realtime LLM services.
|
"""Settings for Grok Realtime LLM services."""
|
||||||
|
|
||||||
Parameters:
|
pass
|
||||||
session_properties: Grok Realtime session configuration.
|
|
||||||
"""
|
|
||||||
|
|
||||||
session_properties: events.SessionProperties | _NotGiven = field(
|
|
||||||
default_factory=lambda: NOT_GIVEN
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class GrokRealtimeLLMService(LLMService):
|
class GrokRealtimeLLMService(LLMService):
|
||||||
@@ -137,19 +131,13 @@ class GrokRealtimeLLMService(LLMService):
|
|||||||
base_url: WebSocket base URL for the realtime API.
|
base_url: WebSocket base URL for the realtime API.
|
||||||
Defaults to "wss://api.x.ai/v1/realtime".
|
Defaults to "wss://api.x.ai/v1/realtime".
|
||||||
session_properties: Configuration properties for the realtime session.
|
session_properties: Configuration properties for the realtime session.
|
||||||
|
|
||||||
.. deprecated::
|
|
||||||
Use ``settings=GrokRealtimeLLMSettings(session_properties=...)``
|
|
||||||
instead.
|
|
||||||
|
|
||||||
If None, uses default SessionProperties with voice "Ara".
|
If None, uses default SessionProperties with voice "Ara".
|
||||||
To set a different voice, configure it in session_properties:
|
To set a different voice, configure it in session_properties:
|
||||||
|
|
||||||
session_properties = events.SessionProperties(voice="Rex")
|
session_properties = events.SessionProperties(voice="Rex")
|
||||||
|
|
||||||
Available voices: Ara, Rex, Sal, Eve, Leo.
|
Available voices: Ara, Rex, Sal, Eve, Leo.
|
||||||
settings: Grok Realtime LLM settings. If provided together with deprecated
|
settings: Runtime-updatable settings for this service.
|
||||||
top-level parameters, the ``settings`` values take precedence.
|
|
||||||
start_audio_paused: Whether to start with audio input paused. Defaults to False.
|
start_audio_paused: Whether to start with audio input paused. Defaults to False.
|
||||||
**kwargs: Additional arguments passed to parent LLMService.
|
**kwargs: Additional arguments passed to parent LLMService.
|
||||||
"""
|
"""
|
||||||
@@ -165,17 +153,9 @@ class GrokRealtimeLLMService(LLMService):
|
|||||||
seed=None,
|
seed=None,
|
||||||
filter_incomplete_user_turns=False,
|
filter_incomplete_user_turns=False,
|
||||||
user_turn_completion_config=None,
|
user_turn_completion_config=None,
|
||||||
session_properties=events.SessionProperties(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 2. Apply direct init arg overrides (deprecated)
|
# 2. Apply settings delta (canonical API, always wins)
|
||||||
if session_properties is not None:
|
|
||||||
_warn_deprecated_param(
|
|
||||||
"session_properties", GrokRealtimeLLMSettings, "session_properties"
|
|
||||||
)
|
|
||||||
default_settings.session_properties = session_properties
|
|
||||||
|
|
||||||
# 4. Apply settings delta (canonical API, always wins)
|
|
||||||
if settings is not None:
|
if settings is not None:
|
||||||
default_settings.apply_update(settings)
|
default_settings.apply_update(settings)
|
||||||
|
|
||||||
@@ -187,6 +167,7 @@ class GrokRealtimeLLMService(LLMService):
|
|||||||
|
|
||||||
self.api_key = api_key
|
self.api_key = api_key
|
||||||
self.base_url = base_url
|
self.base_url = base_url
|
||||||
|
self._session_properties = session_properties or events.SessionProperties()
|
||||||
|
|
||||||
self._audio_input_paused = start_audio_paused
|
self._audio_input_paused = start_audio_paused
|
||||||
self._websocket = None
|
self._websocket = None
|
||||||
@@ -235,13 +216,13 @@ class GrokRealtimeLLMService(LLMService):
|
|||||||
Configured sample rate or None if not manually configured.
|
Configured sample rate or None if not manually configured.
|
||||||
For PCMU/PCMA formats, returns 8000 Hz (G.711 standard).
|
For PCMU/PCMA formats, returns 8000 Hz (G.711 standard).
|
||||||
"""
|
"""
|
||||||
if not self._settings.session_properties.audio:
|
if not self._session_properties.audio:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
audio_config = (
|
audio_config = (
|
||||||
self._settings.session_properties.audio.input
|
self._session_properties.audio.input
|
||||||
if direction == "input"
|
if direction == "input"
|
||||||
else self._settings.session_properties.audio.output
|
else self._session_properties.audio.output
|
||||||
)
|
)
|
||||||
|
|
||||||
if audio_config and audio_config.format:
|
if audio_config and audio_config.format:
|
||||||
@@ -271,8 +252,8 @@ class GrokRealtimeLLMService(LLMService):
|
|||||||
|
|
||||||
def _is_turn_detection_enabled(self) -> bool:
|
def _is_turn_detection_enabled(self) -> bool:
|
||||||
"""Check if server-side VAD is enabled."""
|
"""Check if server-side VAD is enabled."""
|
||||||
if self._settings.session_properties.turn_detection:
|
if self._session_properties.turn_detection:
|
||||||
return self._settings.session_properties.turn_detection.type == "server_vad"
|
return self._session_properties.turn_detection.type == "server_vad"
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def _handle_interruption(self):
|
async def _handle_interruption(self):
|
||||||
@@ -339,7 +320,7 @@ class GrokRealtimeLLMService(LLMService):
|
|||||||
input_sample_rate: Sample rate for audio input (Hz).
|
input_sample_rate: Sample rate for audio input (Hz).
|
||||||
output_sample_rate: Sample rate for audio output (Hz).
|
output_sample_rate: Sample rate for audio output (Hz).
|
||||||
"""
|
"""
|
||||||
props = self._settings.session_properties
|
props = self._session_properties
|
||||||
if not props.audio:
|
if not props.audio:
|
||||||
props.audio = events.AudioConfiguration()
|
props.audio = events.AudioConfiguration()
|
||||||
if not props.audio.input:
|
if not props.audio.input:
|
||||||
@@ -395,7 +376,12 @@ class GrokRealtimeLLMService(LLMService):
|
|||||||
# directly. The frame.delta path falls through to super, which calls
|
# directly. The frame.delta path falls through to super, which calls
|
||||||
# _update_settings → our override handles the rest.
|
# _update_settings → our override handles the rest.
|
||||||
if isinstance(frame, LLMUpdateSettingsFrame) and frame.delta is None:
|
if isinstance(frame, LLMUpdateSettingsFrame) and frame.delta is None:
|
||||||
self._settings.session_properties = events.SessionProperties(**frame.settings)
|
# Capture current audio config before replacing session properties.
|
||||||
|
input_rate = self._get_configured_sample_rate("input")
|
||||||
|
output_rate = self._get_configured_sample_rate("output")
|
||||||
|
self._session_properties = events.SessionProperties(**frame.settings)
|
||||||
|
if input_rate and output_rate:
|
||||||
|
self._ensure_audio_config(input_rate, output_rate)
|
||||||
await self._send_session_update()
|
await self._send_session_update()
|
||||||
await self.push_frame(frame, direction)
|
await self.push_frame(frame, direction)
|
||||||
return
|
return
|
||||||
@@ -498,29 +484,14 @@ class GrokRealtimeLLMService(LLMService):
|
|||||||
await self.push_error(error_msg=f"Error sending client event: {e}", exception=e)
|
await self.push_error(error_msg=f"Error sending client event: {e}", exception=e)
|
||||||
|
|
||||||
async def _update_settings(self, delta):
|
async def _update_settings(self, delta):
|
||||||
"""Apply a settings delta, sending a session update if needed."""
|
"""Apply a settings delta."""
|
||||||
# Capture current sample rates before the update replaces them.
|
|
||||||
input_rate = self._get_configured_sample_rate("input")
|
|
||||||
output_rate = self._get_configured_sample_rate("output")
|
|
||||||
|
|
||||||
changed = await super()._update_settings(delta)
|
changed = await super()._update_settings(delta)
|
||||||
|
self._warn_unhandled_updated_settings(changed.keys())
|
||||||
if "session_properties" in changed:
|
|
||||||
if input_rate and output_rate:
|
|
||||||
self._ensure_audio_config(input_rate, output_rate)
|
|
||||||
else:
|
|
||||||
logger.warning(
|
|
||||||
"Attempting to apply session properties update without configured sample rates. "
|
|
||||||
"Audio configuration may be incomplete."
|
|
||||||
)
|
|
||||||
await self._send_session_update()
|
|
||||||
|
|
||||||
self._warn_unhandled_updated_settings(changed.keys() - {"session_properties"})
|
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
async def _send_session_update(self):
|
async def _send_session_update(self):
|
||||||
"""Update session settings on the server."""
|
"""Update session settings on the server."""
|
||||||
settings = self._settings.session_properties
|
settings = self._session_properties
|
||||||
adapter: GrokRealtimeLLMAdapter = self.get_llm_adapter()
|
adapter: GrokRealtimeLLMAdapter = self.get_llm_adapter()
|
||||||
|
|
||||||
if self._context:
|
if self._context:
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ class GroqLLMService(OpenAILLMService):
|
|||||||
maintaining full compatibility with OpenAI's interface and functionality.
|
maintaining full compatibility with OpenAI's interface and functionality.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: GroqLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ class MistralLLMService(OpenAILLMService):
|
|||||||
maintaining full compatibility with OpenAI's interface and functionality.
|
maintaining full compatibility with OpenAI's interface and functionality.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: MistralLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ class NvidiaLLMService(OpenAILLMService):
|
|||||||
in token usage reporting between NIM (incremental) and OpenAI (final summary).
|
in token usage reporting between NIM (incremental) and OpenAI (final summary).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: NvidiaLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ class OLLamaLLMService(OpenAILLMService):
|
|||||||
providing a compatible interface for running large language models locally.
|
providing a compatible interface for running large language models locally.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: OllamaLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -53,11 +53,9 @@ class OpenAILLMSettings(LLMSettings):
|
|||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
max_completion_tokens: Maximum completion tokens to generate.
|
max_completion_tokens: Maximum completion tokens to generate.
|
||||||
service_tier: Service tier to use (e.g., "auto", "flex", "priority").
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
max_completion_tokens: int | _NotGiven = field(default_factory=lambda: _NOT_GIVEN)
|
max_completion_tokens: int | _NotGiven = field(default_factory=lambda: _NOT_GIVEN)
|
||||||
service_tier: str | _NotGiven = field(default_factory=lambda: _NOT_GIVEN)
|
|
||||||
|
|
||||||
|
|
||||||
class BaseOpenAILLMService(LLMService):
|
class BaseOpenAILLMService(LLMService):
|
||||||
@@ -118,6 +116,7 @@ class BaseOpenAILLMService(LLMService):
|
|||||||
organization=None,
|
organization=None,
|
||||||
project=None,
|
project=None,
|
||||||
default_headers: Optional[Mapping[str, str]] = None,
|
default_headers: Optional[Mapping[str, str]] = None,
|
||||||
|
service_tier: Optional[str] = None,
|
||||||
params: Optional[InputParams] = None,
|
params: Optional[InputParams] = None,
|
||||||
settings: Optional[OpenAILLMSettings] = None,
|
settings: Optional[OpenAILLMSettings] = None,
|
||||||
retry_timeout_secs: Optional[float] = 5.0,
|
retry_timeout_secs: Optional[float] = 5.0,
|
||||||
@@ -138,6 +137,7 @@ class BaseOpenAILLMService(LLMService):
|
|||||||
organization: OpenAI organization ID.
|
organization: OpenAI organization ID.
|
||||||
project: OpenAI project ID.
|
project: OpenAI project ID.
|
||||||
default_headers: Additional HTTP headers to include in requests.
|
default_headers: Additional HTTP headers to include in requests.
|
||||||
|
service_tier: Service tier to use (e.g., "auto", "flex", "priority").
|
||||||
params: Input parameters for model configuration and behavior.
|
params: Input parameters for model configuration and behavior.
|
||||||
|
|
||||||
.. deprecated:: 0.0.105
|
.. deprecated:: 0.0.105
|
||||||
@@ -161,7 +161,6 @@ class BaseOpenAILLMService(LLMService):
|
|||||||
top_k=None,
|
top_k=None,
|
||||||
max_tokens=NOT_GIVEN,
|
max_tokens=NOT_GIVEN,
|
||||||
max_completion_tokens=NOT_GIVEN,
|
max_completion_tokens=NOT_GIVEN,
|
||||||
service_tier=NOT_GIVEN,
|
|
||||||
filter_incomplete_user_turns=False,
|
filter_incomplete_user_turns=False,
|
||||||
user_turn_completion_config=None,
|
user_turn_completion_config=None,
|
||||||
extra={},
|
extra={},
|
||||||
@@ -180,7 +179,6 @@ class BaseOpenAILLMService(LLMService):
|
|||||||
default_settings.top_p = params.top_p
|
default_settings.top_p = params.top_p
|
||||||
default_settings.max_tokens = params.max_tokens
|
default_settings.max_tokens = params.max_tokens
|
||||||
default_settings.max_completion_tokens = params.max_completion_tokens
|
default_settings.max_completion_tokens = params.max_completion_tokens
|
||||||
default_settings.service_tier = params.service_tier
|
|
||||||
if isinstance(params.extra, dict):
|
if isinstance(params.extra, dict):
|
||||||
default_settings.extra = params.extra
|
default_settings.extra = params.extra
|
||||||
|
|
||||||
@@ -192,6 +190,7 @@ class BaseOpenAILLMService(LLMService):
|
|||||||
settings=default_settings,
|
settings=default_settings,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
|
self._service_tier = service_tier
|
||||||
self._retry_timeout_secs = retry_timeout_secs
|
self._retry_timeout_secs = retry_timeout_secs
|
||||||
self._retry_on_timeout = retry_on_timeout
|
self._retry_on_timeout = retry_on_timeout
|
||||||
self._system_instruction = system_instruction
|
self._system_instruction = system_instruction
|
||||||
@@ -321,7 +320,7 @@ class BaseOpenAILLMService(LLMService):
|
|||||||
"top_p": self._settings.top_p,
|
"top_p": self._settings.top_p,
|
||||||
"max_tokens": self._settings.max_tokens,
|
"max_tokens": self._settings.max_tokens,
|
||||||
"max_completion_tokens": self._settings.max_completion_tokens,
|
"max_completion_tokens": self._settings.max_completion_tokens,
|
||||||
"service_tier": self._settings.service_tier,
|
"service_tier": self._service_tier,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Messages, tools, tool_choice
|
# Messages, tools, tool_choice
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ class OpenAILLMService(BaseOpenAILLMService):
|
|||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
model: Optional[str] = None,
|
model: Optional[str] = None,
|
||||||
|
service_tier: Optional[str] = None,
|
||||||
params: Optional[BaseOpenAILLMService.InputParams] = None,
|
params: Optional[BaseOpenAILLMService.InputParams] = None,
|
||||||
settings: Optional[OpenAILLMSettings] = None,
|
settings: Optional[OpenAILLMSettings] = None,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
@@ -88,6 +89,7 @@ class OpenAILLMService(BaseOpenAILLMService):
|
|||||||
.. deprecated:: 0.0.105
|
.. deprecated:: 0.0.105
|
||||||
Use ``settings=OpenAILLMSettings(model=...)`` instead.
|
Use ``settings=OpenAILLMSettings(model=...)`` instead.
|
||||||
|
|
||||||
|
service_tier: Service tier to use (e.g., "auto", "flex", "priority").
|
||||||
params: Input parameters for model configuration.
|
params: Input parameters for model configuration.
|
||||||
|
|
||||||
.. deprecated:: 0.0.105
|
.. deprecated:: 0.0.105
|
||||||
@@ -108,7 +110,6 @@ class OpenAILLMService(BaseOpenAILLMService):
|
|||||||
top_k=None,
|
top_k=None,
|
||||||
max_tokens=NOT_GIVEN,
|
max_tokens=NOT_GIVEN,
|
||||||
max_completion_tokens=NOT_GIVEN,
|
max_completion_tokens=NOT_GIVEN,
|
||||||
service_tier=NOT_GIVEN,
|
|
||||||
filter_incomplete_user_turns=False,
|
filter_incomplete_user_turns=False,
|
||||||
user_turn_completion_config=None,
|
user_turn_completion_config=None,
|
||||||
extra={},
|
extra={},
|
||||||
@@ -119,6 +120,10 @@ class OpenAILLMService(BaseOpenAILLMService):
|
|||||||
_warn_deprecated_param("model", OpenAILLMSettings, "model")
|
_warn_deprecated_param("model", OpenAILLMSettings, "model")
|
||||||
default_settings.model = model
|
default_settings.model = model
|
||||||
|
|
||||||
|
# Handle service_tier from deprecated params
|
||||||
|
if params is not None and not settings and params.service_tier is not NOT_GIVEN:
|
||||||
|
service_tier = service_tier or params.service_tier
|
||||||
|
|
||||||
# 3. Apply params overrides — only if settings not provided
|
# 3. Apply params overrides — only if settings not provided
|
||||||
if params is not None:
|
if params is not None:
|
||||||
_warn_deprecated_param("params", OpenAILLMSettings)
|
_warn_deprecated_param("params", OpenAILLMSettings)
|
||||||
@@ -130,7 +135,6 @@ class OpenAILLMService(BaseOpenAILLMService):
|
|||||||
default_settings.top_p = params.top_p
|
default_settings.top_p = params.top_p
|
||||||
default_settings.max_tokens = params.max_tokens
|
default_settings.max_tokens = params.max_tokens
|
||||||
default_settings.max_completion_tokens = params.max_completion_tokens
|
default_settings.max_completion_tokens = params.max_completion_tokens
|
||||||
default_settings.service_tier = params.service_tier
|
|
||||||
if isinstance(params.extra, dict):
|
if isinstance(params.extra, dict):
|
||||||
default_settings.extra = params.extra
|
default_settings.extra = params.extra
|
||||||
|
|
||||||
@@ -138,7 +142,7 @@ class OpenAILLMService(BaseOpenAILLMService):
|
|||||||
if settings is not None:
|
if settings is not None:
|
||||||
default_settings.apply_update(settings)
|
default_settings.apply_update(settings)
|
||||||
|
|
||||||
super().__init__(settings=default_settings, **kwargs)
|
super().__init__(service_tier=service_tier, settings=default_settings, **kwargs)
|
||||||
|
|
||||||
def create_context_aggregator(
|
def create_context_aggregator(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import base64
|
|||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
@@ -59,7 +59,7 @@ from pipecat.processors.aggregators.openai_llm_context import (
|
|||||||
)
|
)
|
||||||
from pipecat.processors.frame_processor import FrameDirection
|
from pipecat.processors.frame_processor import FrameDirection
|
||||||
from pipecat.services.llm_service import FunctionCallFromLLM, LLMService
|
from pipecat.services.llm_service import FunctionCallFromLLM, LLMService
|
||||||
from pipecat.services.settings import NOT_GIVEN, LLMSettings, _NotGiven, _warn_deprecated_param
|
from pipecat.services.settings import LLMSettings, _warn_deprecated_param
|
||||||
from pipecat.transcriptions.language import Language
|
from pipecat.transcriptions.language import Language
|
||||||
from pipecat.utils.time import time_now_iso8601
|
from pipecat.utils.time import time_now_iso8601
|
||||||
from pipecat.utils.tracing.service_decorators import traced_openai_realtime, traced_stt
|
from pipecat.utils.tracing.service_decorators import traced_openai_realtime, traced_stt
|
||||||
@@ -93,15 +93,9 @@ class CurrentAudioResponse:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class OpenAIRealtimeLLMSettings(LLMSettings):
|
class OpenAIRealtimeLLMSettings(LLMSettings):
|
||||||
"""Settings for OpenAI Realtime LLM services.
|
"""Settings for OpenAI Realtime LLM services."""
|
||||||
|
|
||||||
Parameters:
|
pass
|
||||||
session_properties: OpenAI Realtime session configuration.
|
|
||||||
"""
|
|
||||||
|
|
||||||
session_properties: events.SessionProperties | _NotGiven = field(
|
|
||||||
default_factory=lambda: NOT_GIVEN
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class OpenAIRealtimeLLMService(LLMService):
|
class OpenAIRealtimeLLMService(LLMService):
|
||||||
@@ -145,15 +139,8 @@ class OpenAIRealtimeLLMService(LLMService):
|
|||||||
base_url: WebSocket base URL for the realtime API.
|
base_url: WebSocket base URL for the realtime API.
|
||||||
Defaults to "wss://api.openai.com/v1/realtime".
|
Defaults to "wss://api.openai.com/v1/realtime".
|
||||||
session_properties: Configuration properties for the realtime session.
|
session_properties: Configuration properties for the realtime session.
|
||||||
|
If None, uses default SessionProperties.
|
||||||
.. deprecated::
|
settings: Runtime-updatable settings for this service.
|
||||||
Use ``settings=OpenAIRealtimeLLMSettings(session_properties=...)``
|
|
||||||
instead.
|
|
||||||
|
|
||||||
These are session-level settings that can be updated during the session
|
|
||||||
(except for voice and model). If None, uses default SessionProperties.
|
|
||||||
settings: Realtime LLM settings. If provided together with deprecated
|
|
||||||
top-level parameters, the ``settings`` values take precedence.
|
|
||||||
start_audio_paused: Whether to start with audio input paused. Defaults to False.
|
start_audio_paused: Whether to start with audio input paused. Defaults to False.
|
||||||
start_video_paused: Whether to start with video input paused. Defaults to False.
|
start_video_paused: Whether to start with video input paused. Defaults to False.
|
||||||
video_frame_detail: Detail level for video processing. Can be "auto", "low", or "high".
|
video_frame_detail: Detail level for video processing. Can be "auto", "low", or "high".
|
||||||
@@ -192,20 +179,14 @@ class OpenAIRealtimeLLMService(LLMService):
|
|||||||
seed=None,
|
seed=None,
|
||||||
filter_incomplete_user_turns=False,
|
filter_incomplete_user_turns=False,
|
||||||
user_turn_completion_config=None,
|
user_turn_completion_config=None,
|
||||||
session_properties=events.SessionProperties(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 2. Apply direct init arg overrides (deprecated)
|
# 2. Apply direct init arg overrides (deprecated)
|
||||||
if model is not None:
|
if model is not None:
|
||||||
_warn_deprecated_param("model", OpenAIRealtimeLLMSettings, "model")
|
_warn_deprecated_param("model", OpenAIRealtimeLLMSettings, "model")
|
||||||
default_settings.model = model
|
default_settings.model = model
|
||||||
if session_properties is not None:
|
|
||||||
_warn_deprecated_param(
|
|
||||||
"session_properties", OpenAIRealtimeLLMSettings, "session_properties"
|
|
||||||
)
|
|
||||||
default_settings.session_properties = session_properties
|
|
||||||
|
|
||||||
# 4. Apply settings delta (canonical API, always wins)
|
# 3. Apply settings delta (canonical API, always wins)
|
||||||
if settings is not None:
|
if settings is not None:
|
||||||
default_settings.apply_update(settings)
|
default_settings.apply_update(settings)
|
||||||
|
|
||||||
@@ -220,6 +201,7 @@ class OpenAIRealtimeLLMService(LLMService):
|
|||||||
|
|
||||||
self.api_key = api_key
|
self.api_key = api_key
|
||||||
self.base_url = full_url
|
self.base_url = full_url
|
||||||
|
self._session_properties = session_properties or events.SessionProperties()
|
||||||
self._audio_input_paused = start_audio_paused
|
self._audio_input_paused = start_audio_paused
|
||||||
self._video_input_paused = start_video_paused
|
self._video_input_paused = start_video_paused
|
||||||
self._video_frame_detail = video_frame_detail
|
self._video_frame_detail = video_frame_detail
|
||||||
@@ -282,12 +264,12 @@ class OpenAIRealtimeLLMService(LLMService):
|
|||||||
|
|
||||||
def _is_modality_enabled(self, modality: str) -> bool:
|
def _is_modality_enabled(self, modality: str) -> bool:
|
||||||
"""Check if a specific modality is enabled, "text" or "audio"."""
|
"""Check if a specific modality is enabled, "text" or "audio"."""
|
||||||
modalities = self._settings.session_properties.output_modalities or ["audio", "text"]
|
modalities = self._session_properties.output_modalities or ["audio", "text"]
|
||||||
return modality in modalities
|
return modality in modalities
|
||||||
|
|
||||||
def _get_enabled_modalities(self) -> list[str]:
|
def _get_enabled_modalities(self) -> list[str]:
|
||||||
"""Get the list of enabled modalities."""
|
"""Get the list of enabled modalities."""
|
||||||
modalities = self._settings.session_properties.output_modalities or ["audio", "text"]
|
modalities = self._session_properties.output_modalities or ["audio", "text"]
|
||||||
# API only supports single modality responses: either ["text"] or ["audio"]
|
# API only supports single modality responses: either ["text"] or ["audio"]
|
||||||
if "audio" in modalities:
|
if "audio" in modalities:
|
||||||
return ["audio"]
|
return ["audio"]
|
||||||
@@ -360,9 +342,9 @@ class OpenAIRealtimeLLMService(LLMService):
|
|||||||
# None and False are different. Check for False. None means we're using OpenAI's
|
# None and False are different. Check for False. None means we're using OpenAI's
|
||||||
# built-in turn detection defaults.
|
# built-in turn detection defaults.
|
||||||
turn_detection_disabled = (
|
turn_detection_disabled = (
|
||||||
self._settings.session_properties.audio
|
self._session_properties.audio
|
||||||
and self._settings.session_properties.audio.input
|
and self._session_properties.audio.input
|
||||||
and self._settings.session_properties.audio.input.turn_detection is False
|
and self._session_properties.audio.input.turn_detection is False
|
||||||
)
|
)
|
||||||
if turn_detection_disabled:
|
if turn_detection_disabled:
|
||||||
await self.send_client_event(events.InputAudioBufferClearEvent())
|
await self.send_client_event(events.InputAudioBufferClearEvent())
|
||||||
@@ -382,9 +364,9 @@ class OpenAIRealtimeLLMService(LLMService):
|
|||||||
# None and False are different. Check for False. None means we're using OpenAI's
|
# None and False are different. Check for False. None means we're using OpenAI's
|
||||||
# built-in turn detection defaults.
|
# built-in turn detection defaults.
|
||||||
turn_detection_disabled = (
|
turn_detection_disabled = (
|
||||||
self._settings.session_properties.audio
|
self._session_properties.audio
|
||||||
and self._settings.session_properties.audio.input
|
and self._session_properties.audio.input
|
||||||
and self._settings.session_properties.audio.input.turn_detection is False
|
and self._session_properties.audio.input.turn_detection is False
|
||||||
)
|
)
|
||||||
if turn_detection_disabled:
|
if turn_detection_disabled:
|
||||||
await self.send_client_event(events.InputAudioBufferCommitEvent())
|
await self.send_client_event(events.InputAudioBufferCommitEvent())
|
||||||
@@ -457,7 +439,7 @@ class OpenAIRealtimeLLMService(LLMService):
|
|||||||
# directly. The frame.delta path falls through to super, which calls
|
# directly. The frame.delta path falls through to super, which calls
|
||||||
# _update_settings → our override handles the rest.
|
# _update_settings → our override handles the rest.
|
||||||
if isinstance(frame, LLMUpdateSettingsFrame) and frame.delta is None:
|
if isinstance(frame, LLMUpdateSettingsFrame) and frame.delta is None:
|
||||||
self._settings.session_properties = events.SessionProperties(**frame.settings)
|
self._session_properties = events.SessionProperties(**frame.settings)
|
||||||
await self._send_session_update()
|
await self._send_session_update()
|
||||||
await self.push_frame(frame, direction)
|
await self.push_frame(frame, direction)
|
||||||
return
|
return
|
||||||
@@ -576,15 +558,13 @@ class OpenAIRealtimeLLMService(LLMService):
|
|||||||
await self.push_error(error_msg=f"Error sending client event: {e}", exception=e)
|
await self.push_error(error_msg=f"Error sending client event: {e}", exception=e)
|
||||||
|
|
||||||
async def _update_settings(self, delta):
|
async def _update_settings(self, delta):
|
||||||
"""Apply a settings delta, sending a session update if needed."""
|
"""Apply a settings delta."""
|
||||||
changed = await super()._update_settings(delta)
|
changed = await super()._update_settings(delta)
|
||||||
if "session_properties" in changed:
|
self._warn_unhandled_updated_settings(changed.keys())
|
||||||
await self._send_session_update()
|
|
||||||
self._warn_unhandled_updated_settings(changed.keys() - {"session_properties"})
|
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
async def _send_session_update(self):
|
async def _send_session_update(self):
|
||||||
settings = self._settings.session_properties
|
settings = self._session_properties
|
||||||
adapter: OpenAIRealtimeLLMAdapter = self.get_llm_adapter()
|
adapter: OpenAIRealtimeLLMAdapter = self.get_llm_adapter()
|
||||||
|
|
||||||
if self._context:
|
if self._context:
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ class AzureRealtimeBetaLLMService(OpenAIRealtimeBetaLLMService):
|
|||||||
real-time audio and text communication capabilities as the base OpenAI service.
|
real-time audio and text communication capabilities as the base OpenAI service.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: AzureRealtimeBetaLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import base64
|
|||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
import warnings
|
import warnings
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
@@ -54,7 +54,7 @@ from pipecat.processors.aggregators.openai_llm_context import (
|
|||||||
from pipecat.processors.frame_processor import FrameDirection
|
from pipecat.processors.frame_processor import FrameDirection
|
||||||
from pipecat.services.llm_service import FunctionCallFromLLM, LLMService
|
from pipecat.services.llm_service import FunctionCallFromLLM, LLMService
|
||||||
from pipecat.services.openai.llm import OpenAIContextAggregatorPair
|
from pipecat.services.openai.llm import OpenAIContextAggregatorPair
|
||||||
from pipecat.services.settings import NOT_GIVEN, LLMSettings, _NotGiven, _warn_deprecated_param
|
from pipecat.services.settings import LLMSettings, _warn_deprecated_param
|
||||||
from pipecat.transcriptions.language import Language
|
from pipecat.transcriptions.language import Language
|
||||||
from pipecat.utils.time import time_now_iso8601
|
from pipecat.utils.time import time_now_iso8601
|
||||||
from pipecat.utils.tracing.service_decorators import traced_openai_realtime, traced_stt
|
from pipecat.utils.tracing.service_decorators import traced_openai_realtime, traced_stt
|
||||||
@@ -94,15 +94,9 @@ class CurrentAudioResponse:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class OpenAIRealtimeBetaLLMSettings(LLMSettings):
|
class OpenAIRealtimeBetaLLMSettings(LLMSettings):
|
||||||
"""Settings for OpenAI Realtime Beta LLM services.
|
"""Settings for OpenAI Realtime Beta LLM services."""
|
||||||
|
|
||||||
Parameters:
|
pass
|
||||||
session_properties: OpenAI Realtime session configuration.
|
|
||||||
"""
|
|
||||||
|
|
||||||
session_properties: events.SessionProperties | _NotGiven = field(
|
|
||||||
default_factory=lambda: NOT_GIVEN
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class OpenAIRealtimeBetaLLMService(LLMService):
|
class OpenAIRealtimeBetaLLMService(LLMService):
|
||||||
@@ -146,14 +140,8 @@ class OpenAIRealtimeBetaLLMService(LLMService):
|
|||||||
base_url: WebSocket base URL for the realtime API.
|
base_url: WebSocket base URL for the realtime API.
|
||||||
Defaults to "wss://api.openai.com/v1/realtime".
|
Defaults to "wss://api.openai.com/v1/realtime".
|
||||||
session_properties: Configuration properties for the realtime session.
|
session_properties: Configuration properties for the realtime session.
|
||||||
|
|
||||||
.. deprecated::
|
|
||||||
Use ``settings=OpenAIRealtimeBetaLLMSettings(session_properties=...)``
|
|
||||||
instead.
|
|
||||||
|
|
||||||
If None, uses default SessionProperties.
|
If None, uses default SessionProperties.
|
||||||
settings: Realtime Beta LLM settings. If provided together with deprecated
|
settings: Runtime-updatable settings for this service.
|
||||||
top-level parameters, the ``settings`` values take precedence.
|
|
||||||
start_audio_paused: Whether to start with audio input paused. Defaults to False.
|
start_audio_paused: Whether to start with audio input paused. Defaults to False.
|
||||||
send_transcription_frames: Whether to emit transcription frames. Defaults to True.
|
send_transcription_frames: Whether to emit transcription frames. Defaults to True.
|
||||||
**kwargs: Additional arguments passed to parent LLMService.
|
**kwargs: Additional arguments passed to parent LLMService.
|
||||||
@@ -179,20 +167,13 @@ class OpenAIRealtimeBetaLLMService(LLMService):
|
|||||||
seed=None,
|
seed=None,
|
||||||
filter_incomplete_user_turns=False,
|
filter_incomplete_user_turns=False,
|
||||||
user_turn_completion_config=None,
|
user_turn_completion_config=None,
|
||||||
session_properties=events.SessionProperties(),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 2. Apply direct init arg overrides (deprecated)
|
# 2. Apply direct init arg overrides (deprecated)
|
||||||
if model is not None:
|
if model is not None:
|
||||||
_warn_deprecated_param("model", OpenAIRealtimeBetaLLMSettings, "model")
|
_warn_deprecated_param("model", OpenAIRealtimeBetaLLMSettings, "model")
|
||||||
default_settings.model = model
|
default_settings.model = model
|
||||||
if session_properties is not None:
|
# 3. Apply settings delta (canonical API, always wins)
|
||||||
_warn_deprecated_param(
|
|
||||||
"session_properties", OpenAIRealtimeBetaLLMSettings, "session_properties"
|
|
||||||
)
|
|
||||||
default_settings.session_properties = session_properties
|
|
||||||
|
|
||||||
# 4. Apply settings delta (canonical API, always wins)
|
|
||||||
if settings is not None:
|
if settings is not None:
|
||||||
default_settings.apply_update(settings)
|
default_settings.apply_update(settings)
|
||||||
|
|
||||||
@@ -205,6 +186,7 @@ class OpenAIRealtimeBetaLLMService(LLMService):
|
|||||||
|
|
||||||
self.api_key = api_key
|
self.api_key = api_key
|
||||||
self.base_url = full_url
|
self.base_url = full_url
|
||||||
|
self._session_properties = session_properties or events.SessionProperties()
|
||||||
self._audio_input_paused = start_audio_paused
|
self._audio_input_paused = start_audio_paused
|
||||||
self._send_transcription_frames = send_transcription_frames
|
self._send_transcription_frames = send_transcription_frames
|
||||||
self._websocket = None
|
self._websocket = None
|
||||||
@@ -243,12 +225,12 @@ class OpenAIRealtimeBetaLLMService(LLMService):
|
|||||||
|
|
||||||
def _is_modality_enabled(self, modality: str) -> bool:
|
def _is_modality_enabled(self, modality: str) -> bool:
|
||||||
"""Check if a specific modality is enabled, "text" or "audio"."""
|
"""Check if a specific modality is enabled, "text" or "audio"."""
|
||||||
modalities = self._settings.session_properties.modalities or ["audio", "text"]
|
modalities = self._session_properties.modalities or ["audio", "text"]
|
||||||
return modality in modalities
|
return modality in modalities
|
||||||
|
|
||||||
def _get_enabled_modalities(self) -> list[str]:
|
def _get_enabled_modalities(self) -> list[str]:
|
||||||
"""Get the list of enabled modalities."""
|
"""Get the list of enabled modalities."""
|
||||||
return self._settings.session_properties.modalities or ["audio", "text"]
|
return self._session_properties.modalities or ["audio", "text"]
|
||||||
|
|
||||||
async def retrieve_conversation_item(self, item_id: str):
|
async def retrieve_conversation_item(self, item_id: str):
|
||||||
"""Retrieve a conversation item by ID from the server.
|
"""Retrieve a conversation item by ID from the server.
|
||||||
@@ -315,7 +297,7 @@ class OpenAIRealtimeBetaLLMService(LLMService):
|
|||||||
async def _handle_interruption(self):
|
async def _handle_interruption(self):
|
||||||
# None and False are different. Check for False. None means we're using OpenAI's
|
# None and False are different. Check for False. None means we're using OpenAI's
|
||||||
# built-in turn detection defaults.
|
# built-in turn detection defaults.
|
||||||
if self._settings.session_properties.turn_detection is False:
|
if self._session_properties.turn_detection is False:
|
||||||
await self.send_client_event(events.InputAudioBufferClearEvent())
|
await self.send_client_event(events.InputAudioBufferClearEvent())
|
||||||
await self.send_client_event(events.ResponseCancelEvent())
|
await self.send_client_event(events.ResponseCancelEvent())
|
||||||
await self._truncate_current_audio_response()
|
await self._truncate_current_audio_response()
|
||||||
@@ -332,7 +314,7 @@ class OpenAIRealtimeBetaLLMService(LLMService):
|
|||||||
async def _handle_user_stopped_speaking(self, frame):
|
async def _handle_user_stopped_speaking(self, frame):
|
||||||
# None and False are different. Check for False. None means we're using OpenAI's
|
# None and False are different. Check for False. None means we're using OpenAI's
|
||||||
# built-in turn detection defaults.
|
# built-in turn detection defaults.
|
||||||
if self._settings.session_properties.turn_detection is False:
|
if self._session_properties.turn_detection is False:
|
||||||
await self.send_client_event(events.InputAudioBufferCommitEvent())
|
await self.send_client_event(events.InputAudioBufferCommitEvent())
|
||||||
await self.send_client_event(events.ResponseCreateEvent())
|
await self.send_client_event(events.ResponseCreateEvent())
|
||||||
|
|
||||||
@@ -403,7 +385,7 @@ class OpenAIRealtimeBetaLLMService(LLMService):
|
|||||||
# directly. The frame.delta path falls through to super, which calls
|
# directly. The frame.delta path falls through to super, which calls
|
||||||
# _update_settings → our override handles the rest.
|
# _update_settings → our override handles the rest.
|
||||||
if isinstance(frame, LLMUpdateSettingsFrame) and frame.delta is None:
|
if isinstance(frame, LLMUpdateSettingsFrame) and frame.delta is None:
|
||||||
self._settings.session_properties = events.SessionProperties(**frame.settings)
|
self._session_properties = events.SessionProperties(**frame.settings)
|
||||||
await self._send_session_update()
|
await self._send_session_update()
|
||||||
await self.push_frame(frame, direction)
|
await self.push_frame(frame, direction)
|
||||||
return
|
return
|
||||||
@@ -520,14 +502,13 @@ class OpenAIRealtimeBetaLLMService(LLMService):
|
|||||||
await self.push_error(error_msg=f"Error sending client event: {e}", exception=e)
|
await self.push_error(error_msg=f"Error sending client event: {e}", exception=e)
|
||||||
|
|
||||||
async def _update_settings(self, delta):
|
async def _update_settings(self, delta):
|
||||||
"""Apply a settings delta, sending a session update if needed."""
|
"""Apply a settings delta."""
|
||||||
changed = await super()._update_settings(delta)
|
changed = await super()._update_settings(delta)
|
||||||
if "session_properties" in changed:
|
self._warn_unhandled_updated_settings(changed.keys())
|
||||||
await self._send_session_update()
|
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
async def _send_session_update(self):
|
async def _send_session_update(self):
|
||||||
settings = self._settings.session_properties
|
settings = self._session_properties
|
||||||
# tools given in the context override the tools in the session properties
|
# tools given in the context override the tools in the session properties
|
||||||
if self._context and self._context.tools:
|
if self._context and self._context.tools:
|
||||||
settings.tools = self._context.tools
|
settings.tools = self._context.tools
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ class OpenPipeLLMService(OpenAILLMService):
|
|||||||
for model training and evaluation.
|
for model training and evaluation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: OpenPipeLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ class OpenRouterLLMService(OpenAILLMService):
|
|||||||
maintaining full compatibility with OpenAI's interface and functionality.
|
maintaining full compatibility with OpenAI's interface and functionality.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: OpenRouterLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ class PerplexityLLMService(OpenAILLMService):
|
|||||||
in token usage reporting between Perplexity (incremental) and OpenAI (final summary).
|
in token usage reporting between Perplexity (incremental) and OpenAI (final summary).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: PerplexityLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ class QwenLLMService(OpenAILLMService):
|
|||||||
maintaining full compatibility with OpenAI's interface and functionality.
|
maintaining full compatibility with OpenAI's interface and functionality.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: QwenLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ class SambaNovaLLMService(OpenAILLMService): # type: ignore
|
|||||||
maintaining full compatibility with OpenAI's interface and functionality.
|
maintaining full compatibility with OpenAI's interface and functionality.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: SambaNovaLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ class TogetherLLMService(OpenAILLMService):
|
|||||||
maintaining full compatibility with OpenAI's interface and functionality.
|
maintaining full compatibility with OpenAI's interface and functionality.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_settings: TogetherLLMSettings
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|||||||
Reference in New Issue
Block a user