Update AIService.set_model_name to AIService._sync_model_name_to_metrics to:
- indicate clearly that it's not meant for public use - make it clear the `self._settings` is the single source of truth for model information - set the stage for an upcoming change where `AIService` subclasses won't have to ever worry about explicitly calling an `AIService` method to sync model name to metrics Across all services, switch from accessing `self._model_name` or `self.model_name` in favor of `self._settings.model`.
This commit is contained in:
@@ -42,27 +42,25 @@ class AIService(FrameProcessor):
|
||||
**kwargs: Additional arguments passed to the parent FrameProcessor.
|
||||
"""
|
||||
super().__init__(**kwargs)
|
||||
self._model_name: str = ""
|
||||
self._settings: ServiceSettings = ServiceSettings()
|
||||
self._settings: ServiceSettings = ServiceSettings(model="")
|
||||
self._session_properties: Dict[str, Any] = {}
|
||||
|
||||
@property
|
||||
def model_name(self) -> str:
|
||||
"""Get the current model name.
|
||||
def _sync_model_name_to_metrics(self):
|
||||
"""Sync the current AI model name (in `self._settings.model`) for usage in metrics.
|
||||
|
||||
Returns:
|
||||
The name of the AI model being used.
|
||||
"""
|
||||
return self._model_name
|
||||
We don't store model name here because there's already a single source
|
||||
of truth for it in `self._settings.model`. This method is just for
|
||||
syncing the model name to the metrics data.
|
||||
|
||||
def set_model_name(self, model: str):
|
||||
"""Set the AI model name and update metrics.
|
||||
TODO: as a next step we should make it so that service classes pass
|
||||
model into `super().__init__` and `AIService` can be responsible for
|
||||
syncing its initial value to metrics, just as it's responsible for
|
||||
syncing any updates to its value to metrics via `_update_settings`.
|
||||
|
||||
Args:
|
||||
model: The name of the AI model to use.
|
||||
"""
|
||||
self._model_name = model
|
||||
self.set_core_metrics_data(MetricsData(processor=self.name, model=self._model_name))
|
||||
self.set_core_metrics_data(MetricsData(processor=self.name, model=self._settings.model))
|
||||
|
||||
async def start(self, frame: StartFrame):
|
||||
"""Start the AI service.
|
||||
@@ -117,7 +115,7 @@ class AIService(FrameProcessor):
|
||||
changed = self._settings.apply_update(update)
|
||||
|
||||
if "model" in changed:
|
||||
self.set_model_name(self._settings.model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
if changed:
|
||||
logger.info(f"{self.name}: updated settings fields: {set(changed)}")
|
||||
|
||||
@@ -237,7 +237,6 @@ class AnthropicLLMService(LLMService):
|
||||
self._client = client or AsyncAnthropic(
|
||||
api_key=api_key
|
||||
) # if the client is provided, use it and remove it, otherwise create a new one
|
||||
self.set_model_name(model)
|
||||
self._retry_timeout_secs = retry_timeout_secs
|
||||
self._retry_on_timeout = retry_on_timeout
|
||||
self._settings = AnthropicLLMSettings(
|
||||
@@ -258,6 +257,7 @@ class AnthropicLLMService(LLMService):
|
||||
thinking=params.thinking,
|
||||
extra=params.extra if isinstance(params.extra, dict) else {},
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def can_generate_metrics(self) -> bool:
|
||||
"""Check if this service can generate usage metrics.
|
||||
@@ -324,7 +324,7 @@ class AnthropicLLMService(LLMService):
|
||||
|
||||
# Build params using the same method as streaming completions
|
||||
params = {
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
"max_tokens": max_tokens if max_tokens is not None else self._settings.max_tokens,
|
||||
"stream": False,
|
||||
"temperature": self._settings.temperature,
|
||||
@@ -438,7 +438,7 @@ class AnthropicLLMService(LLMService):
|
||||
await self.start_ttfb_metrics()
|
||||
|
||||
params = {
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
"max_tokens": self._settings.max_tokens,
|
||||
"stream": True,
|
||||
"temperature": self._settings.temperature,
|
||||
|
||||
@@ -171,8 +171,7 @@ class AsyncAITTSService(AudioContextTTSService):
|
||||
if params.language
|
||||
else None,
|
||||
)
|
||||
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._receive_task = None
|
||||
self._keepalive_task = None
|
||||
@@ -513,7 +512,7 @@ class AsyncAIHttpTTSService(TTSService):
|
||||
if params.language
|
||||
else None,
|
||||
)
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._session = aiohttp_session
|
||||
|
||||
@@ -562,7 +561,7 @@ class AsyncAIHttpTTSService(TTSService):
|
||||
voice_config = {"mode": "id", "id": self._settings.voice}
|
||||
await self.start_ttfb_metrics()
|
||||
payload = {
|
||||
"model_id": self._model_name,
|
||||
"model_id": self._settings.model,
|
||||
"transcript": text,
|
||||
"voice": voice_config,
|
||||
"output_format": {
|
||||
|
||||
@@ -820,7 +820,6 @@ class AWSBedrockLLMService(LLMService):
|
||||
"config": client_config,
|
||||
}
|
||||
|
||||
self.set_model_name(model)
|
||||
self._retry_timeout_secs = retry_timeout_secs
|
||||
self._retry_on_timeout = retry_on_timeout
|
||||
self._settings = AWSBedrockLLMSettings(
|
||||
@@ -833,6 +832,7 @@ class AWSBedrockLLMService(LLMService):
|
||||
if isinstance(params.additional_model_request_fields, dict)
|
||||
else {},
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
logger.info(f"Using AWS Bedrock model: {model}")
|
||||
|
||||
@@ -895,7 +895,7 @@ class AWSBedrockLLMService(LLMService):
|
||||
inference_config["maxTokens"] = max_tokens
|
||||
|
||||
request_params = {
|
||||
"modelId": self.model_name,
|
||||
"modelId": self._settings.model,
|
||||
"messages": messages,
|
||||
"additionalModelRequestFields": self._settings.additional_model_request_fields,
|
||||
}
|
||||
@@ -1052,7 +1052,7 @@ class AWSBedrockLLMService(LLMService):
|
||||
|
||||
# Prepare request parameters
|
||||
request_params = {
|
||||
"modelId": self.model_name,
|
||||
"modelId": self._settings.model,
|
||||
"messages": messages,
|
||||
"additionalModelRequestFields": self._settings.additional_model_request_fields,
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ class AWSNovaSonicLLMService(LLMService):
|
||||
top_p=params.top_p,
|
||||
endpointing_sensitivity=params.endpointing_sensitivity,
|
||||
)
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
# Audio I/O config (hardware settings, not runtime-tunable)
|
||||
self._input_sample_rate = params.input_sample_rate
|
||||
|
||||
@@ -54,7 +54,8 @@ class AzureImageGenServiceREST(ImageGenService):
|
||||
self._api_key = api_key
|
||||
self._azure_endpoint = endpoint
|
||||
self._api_version = api_version
|
||||
self.set_model_name(model)
|
||||
self._settings.model = model
|
||||
self._sync_model_name_to_metrics()
|
||||
self._image_size = image_size
|
||||
self._aiohttp_session = aiohttp_session
|
||||
|
||||
|
||||
@@ -236,8 +236,7 @@ class CambTTSService(TTSService):
|
||||
),
|
||||
user_instructions=params.user_instructions,
|
||||
)
|
||||
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._client = None
|
||||
|
||||
@@ -272,7 +271,7 @@ class CambTTSService(TTSService):
|
||||
|
||||
# Use model-specific sample rate if not explicitly specified
|
||||
if not self._init_sample_rate:
|
||||
self._sample_rate = MODEL_SAMPLE_RATES.get(self.model_name, 22050)
|
||||
self._sample_rate = MODEL_SAMPLE_RATES.get(self._settings.model, 22050)
|
||||
|
||||
@traced_tts
|
||||
async def run_tts(self, text: str, context_id: str) -> AsyncGenerator[Frame, None]:
|
||||
@@ -300,12 +299,12 @@ class CambTTSService(TTSService):
|
||||
"text": text,
|
||||
"voice_id": self._settings.voice,
|
||||
"language": self._settings.language,
|
||||
"speech_model": self.model_name,
|
||||
"speech_model": self._settings.model,
|
||||
"output_configuration": StreamTtsOutputConfiguration(format="pcm_s16le"),
|
||||
}
|
||||
|
||||
# Add user instructions if using mars-instruct model
|
||||
if self._model_name == "mars-instruct" and self._settings.user_instructions:
|
||||
if self._settings.model == "mars-instruct" and self._settings.user_instructions:
|
||||
tts_kwargs["user_instructions"] = self._settings.user_instructions
|
||||
|
||||
await self.start_tts_usage_metrics(text)
|
||||
|
||||
@@ -201,7 +201,7 @@ class CartesiaSTTService(WebsocketSTTService):
|
||||
language=merged_options.get("language"),
|
||||
encoding=merged_options.get("encoding", "pcm_s16le"),
|
||||
)
|
||||
self.set_model_name(merged_options["model"])
|
||||
self._sync_model_name_to_metrics()
|
||||
self._api_key = api_key
|
||||
self._base_url = base_url or "api.cartesia.ai"
|
||||
self._receive_task = None
|
||||
|
||||
@@ -330,6 +330,7 @@ class CartesiaTTSService(AudioContextWordTTSService):
|
||||
self._cartesia_version = cartesia_version
|
||||
self._url = url
|
||||
self._settings = CartesiaTTSSettings(
|
||||
model=model,
|
||||
output_container=container,
|
||||
output_encoding=encoding,
|
||||
output_sample_rate=0,
|
||||
@@ -342,7 +343,7 @@ class CartesiaTTSService(AudioContextWordTTSService):
|
||||
pronunciation_dict_id=params.pronunciation_dict_id,
|
||||
voice=voice_id,
|
||||
)
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._context_id = None
|
||||
self._receive_task = None
|
||||
@@ -457,7 +458,7 @@ class CartesiaTTSService(AudioContextWordTTSService):
|
||||
"transcript": text,
|
||||
"continue": continue_transcript,
|
||||
"context_id": self._context_id,
|
||||
"model_id": self.model_name,
|
||||
"model_id": self._settings.model,
|
||||
"voice": voice_config,
|
||||
"output_format": {
|
||||
"container": self._settings.output_container,
|
||||
@@ -465,7 +466,7 @@ class CartesiaTTSService(AudioContextWordTTSService):
|
||||
"sample_rate": self._settings.output_sample_rate,
|
||||
},
|
||||
"add_timestamps": add_timestamps,
|
||||
"use_original_timestamps": False if self.model_name == "sonic" else True,
|
||||
"use_original_timestamps": False if self._settings.model == "sonic" else True,
|
||||
}
|
||||
|
||||
if is_given(self._settings.language) and self._settings.language:
|
||||
@@ -741,7 +742,7 @@ class CartesiaHttpTTSService(TTSService):
|
||||
generation_config=params.generation_config,
|
||||
pronunciation_dict_id=params.pronunciation_dict_id,
|
||||
)
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._client = AsyncCartesia(
|
||||
api_key=api_key,
|
||||
@@ -829,7 +830,7 @@ class CartesiaHttpTTSService(TTSService):
|
||||
}
|
||||
|
||||
payload = {
|
||||
"model_id": self._model_name,
|
||||
"model_id": self._settings.model,
|
||||
"transcript": text,
|
||||
"voice": voice_config,
|
||||
"output_format": output_format,
|
||||
|
||||
@@ -66,7 +66,7 @@ class CerebrasLLMService(OpenAILLMService):
|
||||
Dictionary of parameters for the chat completion request.
|
||||
"""
|
||||
params = {
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
"stream": True,
|
||||
"seed": self._settings.seed,
|
||||
"temperature": self._settings.temperature,
|
||||
|
||||
@@ -212,7 +212,7 @@ class DeepgramFluxSTTService(WebsocketSTTService):
|
||||
tag=params.tag or [],
|
||||
min_confidence=params.min_confidence,
|
||||
)
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
self._api_key = api_key
|
||||
self._url = url
|
||||
self._should_interrupt = should_interrupt
|
||||
|
||||
@@ -143,13 +143,13 @@ class DeepgramSTTService(STTService):
|
||||
if "language" in merged_options and isinstance(merged_options["language"], Language):
|
||||
merged_options["language"] = merged_options["language"].value
|
||||
|
||||
self.set_model_name(merged_options["model"])
|
||||
merged_live_options = LiveOptions(**merged_options)
|
||||
self._settings = DeepgramSTTSettings(
|
||||
model=merged_options.get("model"),
|
||||
language=merged_options.get("language"),
|
||||
live_options=merged_live_options,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._addons = addons
|
||||
self._should_interrupt = should_interrupt
|
||||
@@ -225,7 +225,7 @@ class DeepgramSTTService(STTService):
|
||||
elif "live_options" in changed and self._settings.live_options.model is not None:
|
||||
# Only live_options was given → pull model up.
|
||||
self._settings.model = self._settings.live_options.model
|
||||
self.set_model_name(self._settings.model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
# --- Sync language -----------------------------------------------
|
||||
if language_given:
|
||||
|
||||
@@ -143,13 +143,13 @@ class DeepgramSageMakerSTTService(STTService):
|
||||
if "language" in merged_options and isinstance(merged_options["language"], Language):
|
||||
merged_options["language"] = merged_options["language"].value
|
||||
|
||||
self.set_model_name(merged_options["model"])
|
||||
merged_live_options = LiveOptions(**merged_options)
|
||||
self._settings = DeepgramSageMakerSTTSettings(
|
||||
model=merged_options.get("model"),
|
||||
language=merged_options.get("language"),
|
||||
live_options=merged_live_options,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._client: Optional[SageMakerBidiClient] = None
|
||||
self._response_task: Optional[asyncio.Task] = None
|
||||
@@ -193,7 +193,7 @@ class DeepgramSageMakerSTTService(STTService):
|
||||
elif "live_options" in changed and self._settings.live_options.model is not None:
|
||||
# Only live_options was given → pull model up.
|
||||
self._settings.model = self._settings.live_options.model
|
||||
self.set_model_name(self._settings.model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
# --- Sync language -----------------------------------------------
|
||||
if language_given:
|
||||
|
||||
@@ -65,7 +65,7 @@ class DeepSeekLLMService(OpenAILLMService):
|
||||
Dictionary of parameters for the chat completion request.
|
||||
"""
|
||||
params = {
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
"stream": True,
|
||||
"stream_options": {"include_usage": True},
|
||||
"frequency_penalty": self._settings.frequency_penalty,
|
||||
|
||||
@@ -281,7 +281,7 @@ class ElevenLabsSTTService(SegmentedSTTService):
|
||||
else "eng",
|
||||
tag_audio_events=params.tag_audio_events,
|
||||
)
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def can_generate_metrics(self) -> bool:
|
||||
"""Check if the service can generate processing metrics.
|
||||
@@ -531,7 +531,7 @@ class ElevenLabsRealtimeSTTService(WebsocketSTTService):
|
||||
enable_logging=params.enable_logging,
|
||||
include_language_detection=params.include_language_detection,
|
||||
)
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def can_generate_metrics(self) -> bool:
|
||||
"""Check if the service can generate processing metrics.
|
||||
|
||||
@@ -423,7 +423,7 @@ class ElevenLabsTTSService(AudioContextWordTTSService):
|
||||
enable_logging=params.enable_logging,
|
||||
apply_text_normalization=params.apply_text_normalization,
|
||||
)
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._output_format = "" # initialized in start()
|
||||
self._voice_settings = self._set_voice_settings()
|
||||
@@ -607,7 +607,7 @@ class ElevenLabsTTSService(AudioContextWordTTSService):
|
||||
logger.debug("Connecting to ElevenLabs")
|
||||
|
||||
voice_id = self._settings.voice
|
||||
model = self.model_name
|
||||
model = self._settings.model
|
||||
output_format = self._output_format
|
||||
url = f"{self._url}/v1/text-to-speech/{voice_id}/multi-stream-input?model_id={model}&output_format={output_format}&auto_mode={self._settings.auto_mode}"
|
||||
|
||||
@@ -929,7 +929,7 @@ class ElevenLabsHttpTTSService(WordTTSService):
|
||||
speed=params.speed,
|
||||
apply_text_normalization=params.apply_text_normalization,
|
||||
)
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
self._output_format = "" # initialized in start()
|
||||
self._voice_settings = self._set_voice_settings()
|
||||
self._pronunciation_dictionary_locators = params.pronunciation_dictionary_locators
|
||||
@@ -1100,7 +1100,7 @@ class ElevenLabsHttpTTSService(WordTTSService):
|
||||
|
||||
payload: Dict[str, Union[str, Dict[str, Union[float, bool]]]] = {
|
||||
"text": text,
|
||||
"model_id": self._model_name,
|
||||
"model_id": self._settings.model,
|
||||
}
|
||||
|
||||
# Include previous text as context if available
|
||||
@@ -1122,7 +1122,7 @@ class ElevenLabsHttpTTSService(WordTTSService):
|
||||
payload["apply_text_normalization"] = self._settings.apply_text_normalization
|
||||
|
||||
language = self._settings.language
|
||||
if self._model_name in ELEVENLABS_MULTILINGUAL_MODELS and language:
|
||||
if self._settings.model in ELEVENLABS_MULTILINGUAL_MODELS and language:
|
||||
payload["language_code"] = language
|
||||
logger.debug(f"Using language code: {language}")
|
||||
elif language:
|
||||
|
||||
@@ -78,7 +78,8 @@ class FalImageGenService(ImageGenService):
|
||||
**kwargs: Additional arguments passed to parent ImageGenService.
|
||||
"""
|
||||
super().__init__(**kwargs)
|
||||
self.set_model_name(model)
|
||||
self._settings.model = model
|
||||
self._sync_model_name_to_metrics()
|
||||
self._params = params
|
||||
self._aiohttp_session = aiohttp_session
|
||||
if key:
|
||||
@@ -103,7 +104,7 @@ class FalImageGenService(ImageGenService):
|
||||
logger.debug(f"Generating image from prompt: {prompt}")
|
||||
|
||||
response = await fal_client.run_async(
|
||||
self.model_name,
|
||||
self._settings.model,
|
||||
arguments={"prompt": prompt, **self._params.model_dump(exclude_none=True)},
|
||||
)
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ class FireworksLLMService(OpenAILLMService):
|
||||
Dictionary of parameters for the chat completion request.
|
||||
"""
|
||||
params = {
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
"stream": True,
|
||||
"frequency_penalty": self._settings.frequency_penalty,
|
||||
"presence_penalty": self._settings.presence_penalty,
|
||||
|
||||
@@ -176,6 +176,7 @@ class FishAudioTTSService(InterruptibleTTSService):
|
||||
self._request_id = None
|
||||
|
||||
self._settings = FishAudioTTSSettings(
|
||||
model=model_id,
|
||||
voice=reference_id,
|
||||
fish_sample_rate=0,
|
||||
latency=params.latency,
|
||||
@@ -185,8 +186,7 @@ class FishAudioTTSService(InterruptibleTTSService):
|
||||
prosody_volume=params.prosody_volume,
|
||||
reference_id=reference_id,
|
||||
)
|
||||
|
||||
self.set_model_name(model_id)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def can_generate_metrics(self) -> bool:
|
||||
"""Check if this service can generate processing metrics.
|
||||
@@ -267,7 +267,7 @@ class FishAudioTTSService(InterruptibleTTSService):
|
||||
|
||||
logger.debug("Connecting to Fish Audio")
|
||||
headers = {"Authorization": f"Bearer {self._api_key}"}
|
||||
headers["model"] = self.model_name
|
||||
headers["model"] = self._settings.model
|
||||
self._websocket = await websocket_connect(self._base_url, additional_headers=headers)
|
||||
|
||||
# Send initial start message with ormsgpack
|
||||
|
||||
@@ -279,9 +279,9 @@ class GladiaSTTService(WebsocketSTTService):
|
||||
self._api_key = api_key
|
||||
self._region = region
|
||||
self._url = url
|
||||
self.set_model_name(model)
|
||||
self._receive_task = None
|
||||
self._settings = GladiaSTTSettings(model=model, input_params=params)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
# Session management
|
||||
self._session_url = None
|
||||
@@ -328,7 +328,7 @@ class GladiaSTTService(WebsocketSTTService):
|
||||
"bit_depth": params.bit_depth or 16,
|
||||
"sample_rate": self.sample_rate,
|
||||
"channels": params.channels or 1,
|
||||
"model": self._model_name,
|
||||
"model": self._settings.model,
|
||||
}
|
||||
|
||||
# Add custom_metadata if provided
|
||||
|
||||
@@ -701,7 +701,6 @@ class GeminiLiveLLMService(LLMService):
|
||||
|
||||
self._last_sent_time = 0
|
||||
self._base_url = base_url
|
||||
self.set_model_name(model)
|
||||
self._voice_id = voice_id
|
||||
self._language_code = params.language
|
||||
|
||||
@@ -763,6 +762,7 @@ class GeminiLiveLLMService(LLMService):
|
||||
proactivity=params.proactivity or {},
|
||||
extra=params.extra if isinstance(params.extra, dict) else {},
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._file_api_base_url = file_api_base_url
|
||||
self._file_api: Optional[GeminiFileAPI] = None
|
||||
@@ -1230,7 +1230,9 @@ class GeminiLiveLLMService(LLMService):
|
||||
await self.push_error(error_msg=f"Initialization error: {e}", exception=e)
|
||||
|
||||
async def _connection_task_handler(self, config: LiveConnectConfig):
|
||||
async with self._client.aio.live.connect(model=self._model_name, config=config) as session:
|
||||
async with self._client.aio.live.connect(
|
||||
model=self._settings.model, config=config
|
||||
) as session:
|
||||
logger.info("Connected to Gemini service")
|
||||
|
||||
# Mark connection start time
|
||||
|
||||
@@ -79,7 +79,9 @@ class GoogleImageGenService(ImageGenService):
|
||||
http_options = update_google_client_http_options(http_options)
|
||||
|
||||
self._client = genai.Client(api_key=api_key, http_options=http_options)
|
||||
self.set_model_name(self._params.model)
|
||||
|
||||
self._settings.model = self._params.model
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def can_generate_metrics(self) -> bool:
|
||||
"""Check if this service can generate processing metrics.
|
||||
|
||||
@@ -797,7 +797,6 @@ class GoogleLLMService(LLMService):
|
||||
|
||||
params = params or GoogleLLMService.InputParams()
|
||||
|
||||
self.set_model_name(model)
|
||||
self._api_key = api_key
|
||||
self._system_instruction = system_instruction
|
||||
self._http_options = update_google_client_http_options(http_options)
|
||||
@@ -811,6 +810,7 @@ class GoogleLLMService(LLMService):
|
||||
thinking=params.thinking,
|
||||
extra=params.extra if isinstance(params.extra, dict) else {},
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
self._tools = tools
|
||||
self._tool_config = tool_config
|
||||
|
||||
@@ -870,7 +870,7 @@ class GoogleLLMService(LLMService):
|
||||
|
||||
# Use the new google-genai client's async method
|
||||
response = await self._client.aio.models.generate_content(
|
||||
model=self._model_name,
|
||||
model=self._settings.model,
|
||||
contents=messages,
|
||||
config=generation_config,
|
||||
)
|
||||
@@ -930,10 +930,10 @@ class GoogleLLMService(LLMService):
|
||||
# There's no way to introspect on model capabilities, so
|
||||
# to check for models that we know default to thinkin on
|
||||
# and can be configured to turn it off.
|
||||
if not self._model_name.startswith("gemini-2.5-flash"):
|
||||
if not self._settings.model.startswith("gemini-2.5-flash"):
|
||||
return
|
||||
# If we have an image model, we don't use a budget either.
|
||||
if "image" in self._model_name:
|
||||
if "image" in self._settings.model:
|
||||
return
|
||||
# If thinking_config is already set, don't override it.
|
||||
if "thinking_config" in generation_params:
|
||||
@@ -974,7 +974,7 @@ class GoogleLLMService(LLMService):
|
||||
|
||||
await self.start_ttfb_metrics()
|
||||
return await self._client.aio.models.generate_content_stream(
|
||||
model=self._model_name,
|
||||
model=self._settings.model,
|
||||
contents=messages,
|
||||
config=generation_config,
|
||||
)
|
||||
|
||||
@@ -62,7 +62,7 @@ class GroqSTTService(BaseWhisperSTTService):
|
||||
# Build kwargs dict with only set parameters
|
||||
kwargs = {
|
||||
"file": ("audio.wav", audio, "audio/wav"),
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
# Use verbose_json to get probability metrics
|
||||
"response_format": "verbose_json" if self._include_prob_metrics else "json",
|
||||
"language": self._language,
|
||||
|
||||
@@ -108,7 +108,6 @@ class GroqTTSService(TTSService):
|
||||
params = params or GroqTTSService.InputParams()
|
||||
|
||||
self._api_key = api_key
|
||||
self._model_name = model_name
|
||||
self._output_format = output_format
|
||||
self._params = params
|
||||
|
||||
@@ -120,6 +119,7 @@ class GroqTTSService(TTSService):
|
||||
speed=params.speed,
|
||||
groq_sample_rate=sample_rate,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._client = AsyncGroq(api_key=self._api_key)
|
||||
|
||||
@@ -149,7 +149,7 @@ class GroqTTSService(TTSService):
|
||||
|
||||
try:
|
||||
response = await self._client.audio.speech.create(
|
||||
model=self._model_name,
|
||||
model=self._settings.model,
|
||||
voice=self._settings.voice,
|
||||
response_format=self._output_format,
|
||||
input=text,
|
||||
|
||||
@@ -105,8 +105,7 @@ class HathoraSTTService(SegmentedSTTService):
|
||||
language=params.language,
|
||||
config=params.config,
|
||||
)
|
||||
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def can_generate_metrics(self) -> bool:
|
||||
"""Check if this service can generate processing metrics.
|
||||
|
||||
@@ -123,8 +123,7 @@ class HathoraTTSService(TTSService):
|
||||
speed=params.speed,
|
||||
config=params.config,
|
||||
)
|
||||
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def can_generate_metrics(self) -> bool:
|
||||
"""Check if this service can generate processing metrics.
|
||||
|
||||
@@ -173,7 +173,7 @@ class InworldHttpTTSService(WordTTSService):
|
||||
|
||||
self._cumulative_time = 0.0
|
||||
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def can_generate_metrics(self) -> bool:
|
||||
"""Check if this service can generate processing metrics.
|
||||
@@ -562,7 +562,7 @@ class InworldTTSService(AudioContextWordTTSService):
|
||||
# Track the end time of the last word in the current generation
|
||||
self._generation_end_time = 0.0
|
||||
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def can_generate_metrics(self) -> bool:
|
||||
"""Check if this service can generate processing metrics.
|
||||
|
||||
@@ -122,13 +122,13 @@ class LmntTTSService(InterruptibleTTSService):
|
||||
)
|
||||
|
||||
self._api_key = api_key
|
||||
self.set_model_name(model)
|
||||
self._settings = LmntTTSSettings(
|
||||
model=model,
|
||||
voice=voice_id,
|
||||
language=self.language_to_service_language(language),
|
||||
format="raw",
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
self._receive_task = None
|
||||
self._context_id: Optional[str] = None
|
||||
|
||||
@@ -238,7 +238,7 @@ class LmntTTSService(InterruptibleTTSService):
|
||||
"format": self._settings.format,
|
||||
"sample_rate": self.sample_rate,
|
||||
"language": self._settings.language,
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
}
|
||||
|
||||
# Connect to LMNT's websocket directly
|
||||
|
||||
@@ -235,7 +235,6 @@ class MiniMaxHttpTTSService(TTSService):
|
||||
self._group_id = group_id
|
||||
self._base_url = f"{base_url}?GroupId={group_id}"
|
||||
self._session = aiohttp_session
|
||||
self._model_name = model
|
||||
|
||||
# Create voice settings
|
||||
self._settings = MiniMaxTTSSettings(
|
||||
@@ -249,9 +248,7 @@ class MiniMaxHttpTTSService(TTSService):
|
||||
audio_format="pcm",
|
||||
audio_channel=1,
|
||||
)
|
||||
|
||||
# Set model
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
# Add language boost if provided
|
||||
if params.language:
|
||||
@@ -318,14 +315,6 @@ class MiniMaxHttpTTSService(TTSService):
|
||||
"""
|
||||
return language_to_minimax_language(language)
|
||||
|
||||
def set_model_name(self, model: str):
|
||||
"""Set the TTS model to use.
|
||||
|
||||
Args:
|
||||
model: The model name to use for synthesis.
|
||||
"""
|
||||
self._model_name = model
|
||||
|
||||
async def start(self, frame: StartFrame):
|
||||
"""Start the MiniMax TTS service.
|
||||
|
||||
@@ -382,7 +371,7 @@ class MiniMaxHttpTTSService(TTSService):
|
||||
"stream": self._settings.stream,
|
||||
"voice_setting": voice_setting,
|
||||
"audio_setting": audio_setting,
|
||||
"model": self._model_name,
|
||||
"model": self._settings.model,
|
||||
"text": text,
|
||||
}
|
||||
if is_given(self._settings.language_boost):
|
||||
|
||||
@@ -180,7 +180,7 @@ class MistralLLMService(OpenAILLMService):
|
||||
fixed_messages = self._apply_mistral_fixups(params_from_context["messages"])
|
||||
|
||||
params = {
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
"stream": True,
|
||||
"messages": fixed_messages,
|
||||
"tools": params_from_context["tools"],
|
||||
|
||||
@@ -81,7 +81,8 @@ class MoondreamService(VisionService):
|
||||
"""
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self.set_model_name(model)
|
||||
self._settings.model = model
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
if not use_cpu:
|
||||
device, dtype = detect_device()
|
||||
|
||||
@@ -181,10 +181,10 @@ class NvidiaSTTService(STTService):
|
||||
self._function_id = model_function_map.get("function_id")
|
||||
|
||||
self._settings = NvidiaSTTSettings(
|
||||
model=model_function_map.get("model_name"),
|
||||
language=params.language,
|
||||
)
|
||||
|
||||
self.set_model_name(model_function_map.get("model_name"))
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._asr_service = None
|
||||
self._queue = None
|
||||
@@ -282,7 +282,7 @@ class NvidiaSTTService(STTService):
|
||||
if not self._thread_task:
|
||||
self._thread_task = self.create_task(self._thread_task_handler())
|
||||
|
||||
logger.debug(f"Initialized NvidiaSTTService with model: {self.model_name}")
|
||||
logger.debug(f"Initialized NvidiaSTTService with model: {self._settings.model}")
|
||||
|
||||
async def stop(self, frame: EndFrame):
|
||||
"""Stop the NVIDIA Riva STT service and clean up resources.
|
||||
@@ -467,9 +467,6 @@ class NvidiaSegmentedSTTService(SegmentedSTTService):
|
||||
|
||||
params = params or NvidiaSegmentedSTTService.InputParams()
|
||||
|
||||
# Set model name
|
||||
self.set_model_name(model_function_map.get("model_name"))
|
||||
|
||||
# Initialize NVIDIA Riva settings
|
||||
self._api_key = api_key
|
||||
self._server = server
|
||||
@@ -488,6 +485,7 @@ class NvidiaSegmentedSTTService(SegmentedSTTService):
|
||||
self._config = None
|
||||
self._asr_service = None
|
||||
self._settings = NvidiaSegmentedSTTSettings(
|
||||
model=model_function_map.get("model_name"),
|
||||
language=self.language_to_service_language(params.language or Language.EN_US)
|
||||
or "en-US",
|
||||
profanity_filter=params.profanity_filter,
|
||||
@@ -496,6 +494,7 @@ class NvidiaSegmentedSTTService(SegmentedSTTService):
|
||||
boosted_lm_words=params.boosted_lm_words,
|
||||
boosted_lm_score=params.boosted_lm_score,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def language_to_service_language(self, language: Language) -> Optional[str]:
|
||||
"""Convert pipecat Language enum to NVIDIA Riva's language code.
|
||||
@@ -578,7 +577,7 @@ class NvidiaSegmentedSTTService(SegmentedSTTService):
|
||||
await super().start(frame)
|
||||
self._initialize_client()
|
||||
self._config = self._create_recognition_config()
|
||||
logger.debug(f"Initialized NvidiaSegmentedSTTService with model: {self.model_name}")
|
||||
logger.debug(f"Initialized NvidiaSegmentedSTTService with model: {self._settings.model}")
|
||||
|
||||
async def _update_settings(self, update: STTSettings) -> dict[str, Any]:
|
||||
"""Apply a settings update and sync internal state.
|
||||
|
||||
@@ -112,11 +112,12 @@ class NvidiaTTSService(TTSService):
|
||||
self._function_id = model_function_map.get("function_id")
|
||||
self._use_ssl = use_ssl
|
||||
self._settings = NvidiaTTSSettings(
|
||||
model=model_function_map.get("model_name"),
|
||||
voice=voice_id,
|
||||
language=params.language,
|
||||
quality=params.quality,
|
||||
)
|
||||
self.set_model_name(model_function_map.get("model_name"))
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._service = None
|
||||
self._config = None
|
||||
@@ -192,7 +193,7 @@ class NvidiaTTSService(TTSService):
|
||||
await super().start(frame)
|
||||
self._initialize_client()
|
||||
self._config = self._create_synthesis_config()
|
||||
logger.debug(f"Initialized NvidiaTTSService with model: {self.model_name}")
|
||||
logger.debug(f"Initialized NvidiaTTSService with model: {self._settings.model}")
|
||||
|
||||
@traced_tts
|
||||
async def run_tts(self, text: str, context_id: str) -> AsyncGenerator[Frame, None]:
|
||||
|
||||
@@ -151,7 +151,7 @@ class BaseOpenAILLMService(LLMService):
|
||||
)
|
||||
self._retry_timeout_secs = retry_timeout_secs
|
||||
self._retry_on_timeout = retry_on_timeout
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
self._full_model_name: str = ""
|
||||
self._client = self.create_client(
|
||||
api_key=api_key,
|
||||
@@ -265,7 +265,7 @@ class BaseOpenAILLMService(LLMService):
|
||||
Dictionary of parameters for the chat completion request.
|
||||
"""
|
||||
params = {
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
"stream": True,
|
||||
"stream_options": {"include_usage": True},
|
||||
"frequency_penalty": self._settings.frequency_penalty,
|
||||
|
||||
@@ -53,7 +53,8 @@ class OpenAIImageGenService(ImageGenService):
|
||||
model: DALL-E model to use for generation. Defaults to "dall-e-3".
|
||||
"""
|
||||
super().__init__()
|
||||
self.set_model_name(model)
|
||||
self._settings.model = model
|
||||
self._sync_model_name_to_metrics()
|
||||
self._image_size = image_size
|
||||
self._client = AsyncOpenAI(api_key=api_key, base_url=base_url)
|
||||
self._aiohttp_session = aiohttp_session
|
||||
@@ -70,7 +71,7 @@ class OpenAIImageGenService(ImageGenService):
|
||||
logger.debug(f"Generating image from prompt: {prompt}")
|
||||
|
||||
image = await self._client.images.generate(
|
||||
prompt=prompt, model=self.model_name, n=1, size=self._image_size
|
||||
prompt=prompt, model=self._settings.model, n=1, size=self._image_size
|
||||
)
|
||||
|
||||
image_url = image.data[0].url
|
||||
|
||||
@@ -175,12 +175,12 @@ class OpenAIRealtimeLLMService(LLMService):
|
||||
|
||||
self.api_key = api_key
|
||||
self.base_url = full_url
|
||||
self.set_model_name(model)
|
||||
|
||||
self._settings = OpenAIRealtimeLLMSettings(
|
||||
model=model,
|
||||
session_properties=session_properties or events.SessionProperties(),
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
self._audio_input_paused = start_audio_paused
|
||||
self._video_input_paused = start_video_paused
|
||||
self._video_frame_detail = video_frame_detail
|
||||
|
||||
@@ -100,24 +100,24 @@ class OpenAISTTService(BaseWhisperSTTService):
|
||||
# Build kwargs dict with only set parameters
|
||||
kwargs = {
|
||||
"file": ("audio.wav", audio, "audio/wav"),
|
||||
"model": self.model_name,
|
||||
"language": self._language,
|
||||
"model": self._settings.model,
|
||||
"language": self._settings.language,
|
||||
}
|
||||
|
||||
if self._include_prob_metrics:
|
||||
# GPT-4o-transcribe models only support logprobs (not verbose_json)
|
||||
if self.model_name in ("gpt-4o-transcribe", "gpt-4o-mini-transcribe"):
|
||||
if self._settings.model in ("gpt-4o-transcribe", "gpt-4o-mini-transcribe"):
|
||||
kwargs["response_format"] = "json"
|
||||
kwargs["include"] = ["logprobs"]
|
||||
else:
|
||||
# Whisper models support verbose_json
|
||||
kwargs["response_format"] = "verbose_json"
|
||||
|
||||
if self._prompt is not None:
|
||||
kwargs["prompt"] = self._prompt
|
||||
if self._settings.prompt is not None:
|
||||
kwargs["prompt"] = self._settings.prompt
|
||||
|
||||
if self._temperature is not None:
|
||||
kwargs["temperature"] = self._temperature
|
||||
if self._settings.temperature is not None:
|
||||
kwargs["temperature"] = self._settings.temperature
|
||||
|
||||
return await self._client.audio.transcriptions.create(**kwargs)
|
||||
|
||||
@@ -226,7 +226,6 @@ class OpenAIRealtimeSTTService(WebsocketSTTService):
|
||||
|
||||
self._api_key = api_key
|
||||
self._base_url = base_url
|
||||
self.set_model_name(model)
|
||||
|
||||
self._prompt = prompt
|
||||
self._turn_detection = turn_detection
|
||||
@@ -238,6 +237,7 @@ class OpenAIRealtimeSTTService(WebsocketSTTService):
|
||||
language=language,
|
||||
prompt=prompt,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._receive_task = None
|
||||
self._session_ready = False
|
||||
@@ -437,7 +437,7 @@ class OpenAIRealtimeSTTService(WebsocketSTTService):
|
||||
|
||||
async def _send_session_update(self):
|
||||
"""Send ``session.update`` to configure the transcription session."""
|
||||
transcription: dict = {"model": self.model_name}
|
||||
transcription: dict = {"model": self._settings.model}
|
||||
|
||||
language_code = (
|
||||
self._language_to_code(self._settings.language) if self._settings.language else None
|
||||
|
||||
@@ -134,7 +134,6 @@ class OpenAITTSService(TTSService):
|
||||
)
|
||||
super().__init__(sample_rate=sample_rate, **kwargs)
|
||||
|
||||
self.set_model_name(model)
|
||||
self._client = AsyncOpenAI(api_key=api_key, base_url=base_url)
|
||||
|
||||
if instructions or speed:
|
||||
@@ -154,6 +153,7 @@ class OpenAITTSService(TTSService):
|
||||
instructions=params.instructions if params else instructions,
|
||||
speed=params.speed if params else speed,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def can_generate_metrics(self) -> bool:
|
||||
"""Check if this service can generate processing metrics.
|
||||
@@ -194,7 +194,7 @@ class OpenAITTSService(TTSService):
|
||||
# Setup API parameters
|
||||
create_params = {
|
||||
"input": text,
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
"voice": VALID_VOICES[self._settings.voice],
|
||||
"response_format": "pcm",
|
||||
}
|
||||
|
||||
@@ -160,12 +160,12 @@ class OpenAIRealtimeBetaLLMService(LLMService):
|
||||
|
||||
self.api_key = api_key
|
||||
self.base_url = full_url
|
||||
self.set_model_name(model)
|
||||
|
||||
self._settings = OpenAIRealtimeBetaLLMSettings(
|
||||
model=model,
|
||||
session_properties=session_properties or events.SessionProperties(),
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
self._audio_input_paused = start_audio_paused
|
||||
self._send_transcription_frames = send_transcription_frames
|
||||
self._websocket = None
|
||||
|
||||
@@ -72,8 +72,7 @@ class OpenRouterLLMService(OpenAILLMService):
|
||||
Transformed parameters ready for the API call.
|
||||
"""
|
||||
params = super().build_chat_completion_params(params_from_context)
|
||||
model = getattr(self, "model_name", getattr(self, "model", "")).lower()
|
||||
if "gemini" in model:
|
||||
if "gemini" in self._settings.model.lower():
|
||||
messages = params.get("messages", [])
|
||||
if not messages:
|
||||
return params
|
||||
|
||||
@@ -66,7 +66,7 @@ class PerplexityLLMService(OpenAILLMService):
|
||||
Dictionary of parameters for the chat completion request.
|
||||
"""
|
||||
params = {
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
"stream": True,
|
||||
"messages": params_from_context["messages"],
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ class PlayHTTTSService(InterruptibleTTSService):
|
||||
speed=params.speed,
|
||||
seed=params.seed,
|
||||
)
|
||||
self.set_model_name(voice_engine)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def can_generate_metrics(self) -> bool:
|
||||
"""Check if this service can generate processing metrics.
|
||||
@@ -545,6 +545,7 @@ class PlayHTHttpTTSService(TTSService):
|
||||
voice_engine = voice_engine.replace("-ws", "")
|
||||
|
||||
self._settings = PlayHTTTSSettings(
|
||||
model=voice_engine,
|
||||
voice=voice_url,
|
||||
language=self.language_to_service_language(params.language)
|
||||
if params.language
|
||||
@@ -554,7 +555,7 @@ class PlayHTHttpTTSService(TTSService):
|
||||
speed=params.speed,
|
||||
seed=params.seed,
|
||||
)
|
||||
self.set_model_name(voice_engine)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
async def start(self, frame: StartFrame):
|
||||
"""Start the PlayHT HTTP TTS service.
|
||||
|
||||
@@ -75,7 +75,6 @@ class RimeTTSSettings(TTSSettings):
|
||||
"""Settings for Rime WS JSON and HTTP TTS services.
|
||||
|
||||
Parameters:
|
||||
modelId: Rime model identifier.
|
||||
audioFormat: Audio output format.
|
||||
samplingRate: Audio sample rate.
|
||||
lang: Rime language code.
|
||||
@@ -86,7 +85,6 @@ class RimeTTSSettings(TTSSettings):
|
||||
inlineSpeedAlpha: Inline speed control markup.
|
||||
"""
|
||||
|
||||
modelId: str | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
audioFormat: str | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
samplingRate: int | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
lang: str | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
@@ -104,7 +102,6 @@ class RimeNonJsonTTSSettings(TTSSettings):
|
||||
"""Settings for Rime non-JSON WS TTS service.
|
||||
|
||||
Parameters:
|
||||
modelId: Rime model identifier.
|
||||
audioFormat: Audio output format.
|
||||
samplingRate: Audio sample rate.
|
||||
lang: Rime language code.
|
||||
@@ -114,7 +111,6 @@ class RimeNonJsonTTSSettings(TTSSettings):
|
||||
top_p: Cumulative probability threshold (0.0-1.0).
|
||||
"""
|
||||
|
||||
modelId: str | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
audioFormat: str | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
samplingRate: int | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
lang: str | _NotGiven = field(default_factory=lambda: NOT_GIVEN)
|
||||
@@ -210,7 +206,7 @@ class RimeTTSService(AudioContextWordTTSService):
|
||||
self._model = model
|
||||
self._settings = RimeTTSSettings(
|
||||
voice=voice_id,
|
||||
modelId=model,
|
||||
model=model,
|
||||
audioFormat="pcm",
|
||||
samplingRate=0,
|
||||
lang=self.language_to_service_language(params.language) if params.language else "eng",
|
||||
@@ -219,6 +215,7 @@ class RimeTTSService(AudioContextWordTTSService):
|
||||
pauseBetweenBrackets=json.dumps(params.pause_between_brackets),
|
||||
phonemizeBetweenBrackets=json.dumps(params.phonemize_between_brackets),
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
# State tracking
|
||||
self._context_id = None # Tracks current turn
|
||||
@@ -353,7 +350,7 @@ class RimeTTSService(AudioContextWordTTSService):
|
||||
f"{k}={v}"
|
||||
for k, v in {
|
||||
"speaker": self._settings.voice,
|
||||
"modelId": self._settings.modelId,
|
||||
"modelId": self._settings.model,
|
||||
"audioFormat": self._settings.audioFormat,
|
||||
"samplingRate": self._settings.samplingRate,
|
||||
"lang": self._settings.lang,
|
||||
@@ -589,6 +586,7 @@ class RimeHttpTTSService(TTSService):
|
||||
self._session = aiohttp_session
|
||||
self._base_url = "https://users.rime.ai/v1/rime-tts"
|
||||
self._settings = RimeTTSSettings(
|
||||
model=model,
|
||||
lang=self.language_to_service_language(params.language) if params.language else "eng",
|
||||
speedAlpha=params.speed_alpha,
|
||||
reduceLatency=params.reduce_latency,
|
||||
@@ -597,7 +595,7 @@ class RimeHttpTTSService(TTSService):
|
||||
inlineSpeedAlpha=params.inline_speed_alpha if params.inline_speed_alpha else NOT_GIVEN,
|
||||
voice=voice_id,
|
||||
)
|
||||
self.set_model_name(model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def can_generate_metrics(self) -> bool:
|
||||
"""Check if this service can generate processing metrics.
|
||||
@@ -648,7 +646,7 @@ class RimeHttpTTSService(TTSService):
|
||||
payload["inlineSpeedAlpha"] = self._settings.inlineSpeedAlpha
|
||||
payload["text"] = text
|
||||
payload["speaker"] = self._settings.voice
|
||||
payload["modelId"] = self._model_name
|
||||
payload["modelId"] = self._settings.model
|
||||
payload["samplingRate"] = self.sample_rate
|
||||
|
||||
# Arcana does not support PCM audio
|
||||
@@ -769,7 +767,7 @@ class RimeNonJsonTTSService(InterruptibleTTSService):
|
||||
self._model = model
|
||||
self._settings = RimeNonJsonTTSSettings(
|
||||
voice=voice_id,
|
||||
modelId=model,
|
||||
model=model,
|
||||
audioFormat=audio_format,
|
||||
samplingRate=sample_rate,
|
||||
lang=self.language_to_service_language(params.language)
|
||||
@@ -782,6 +780,7 @@ class RimeNonJsonTTSService(InterruptibleTTSService):
|
||||
temperature=params.temperature if params.temperature is not None else NOT_GIVEN,
|
||||
top_p=params.top_p if params.top_p is not None else NOT_GIVEN,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
# Add any extra parameters for future compatibility
|
||||
if params.extra:
|
||||
self._settings.extra.update(params.extra)
|
||||
@@ -863,7 +862,7 @@ class RimeNonJsonTTSService(InterruptibleTTSService):
|
||||
# Build URL with query parameters (only given, non-None values)
|
||||
settings_dict = {
|
||||
"speaker": self._settings.voice,
|
||||
"modelId": self._settings.modelId,
|
||||
"modelId": self._settings.model,
|
||||
"audioFormat": self._settings.audioFormat,
|
||||
"samplingRate": self._settings.samplingRate,
|
||||
}
|
||||
@@ -981,10 +980,6 @@ class RimeNonJsonTTSService(InterruptibleTTSService):
|
||||
"""
|
||||
changed = await super()._update_settings(update)
|
||||
|
||||
# Sync model to settings dict field
|
||||
if "model" in changed:
|
||||
self._settings.modelId = self._model_name
|
||||
|
||||
if changed:
|
||||
logger.debug("Settings changed, reconnecting WebSocket with new parameters")
|
||||
await self._disconnect()
|
||||
|
||||
@@ -84,7 +84,7 @@ class SambaNovaLLMService(OpenAILLMService): # type: ignore
|
||||
Dictionary of parameters for the chat completion request.
|
||||
"""
|
||||
params = {
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
"stream": True,
|
||||
"stream_options": {"include_usage": True},
|
||||
"temperature": self._settings.temperature,
|
||||
|
||||
@@ -72,7 +72,7 @@ class SambaNovaSTTService(BaseWhisperSTTService): # type: ignore
|
||||
# Build kwargs dict with only set parameters
|
||||
kwargs = {
|
||||
"file": ("audio.wav", audio, "audio/wav"),
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
"response_format": "json",
|
||||
"language": self._language,
|
||||
}
|
||||
|
||||
@@ -225,7 +225,6 @@ class SarvamSTTService(STTService):
|
||||
|
||||
super().__init__(sample_rate=sample_rate, ttfs_p99_latency=ttfs_p99_latency, **kwargs)
|
||||
|
||||
self.set_model_name(model)
|
||||
self._api_key = api_key
|
||||
|
||||
# Store connection parameters
|
||||
@@ -257,6 +256,7 @@ class SarvamSTTService(STTService):
|
||||
vad_signals=params.vad_signals,
|
||||
high_vad_sensitivity=params.high_vad_sensitivity,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
if params.vad_signals:
|
||||
self._register_event_handler("on_speech_started")
|
||||
@@ -322,7 +322,7 @@ class SarvamSTTService(STTService):
|
||||
if is_given(update.language) and update.language is not None:
|
||||
if not self._config.supports_language:
|
||||
raise ValueError(
|
||||
f"Model '{self.model_name}' does not support language parameter "
|
||||
f"Model '{self._settings.model}' does not support language parameter "
|
||||
"(auto-detects language)."
|
||||
)
|
||||
|
||||
@@ -330,11 +330,13 @@ class SarvamSTTService(STTService):
|
||||
if is_given(update.prompt) and update.prompt is not None:
|
||||
if not self._config.supports_prompt:
|
||||
raise ValueError(
|
||||
f"Model '{self.model_name}' does not support prompt parameter."
|
||||
f"Model '{self._settings.model}' does not support prompt parameter."
|
||||
)
|
||||
if is_given(update.mode) and update.mode is not None:
|
||||
if not self._config.supports_mode:
|
||||
raise ValueError(f"Model '{self.model_name}' does not support mode parameter.")
|
||||
raise ValueError(
|
||||
f"Model '{self._settings.model}' does not support mode parameter."
|
||||
)
|
||||
|
||||
changed = await super()._update_settings(update)
|
||||
|
||||
@@ -374,11 +376,13 @@ class SarvamSTTService(STTService):
|
||||
|
||||
if not self._config.supports_prompt:
|
||||
if prompt is not None:
|
||||
raise ValueError(f"Model '{self.model_name}' does not support prompt parameter.")
|
||||
raise ValueError(
|
||||
f"Model '{self._settings.model}' does not support prompt parameter."
|
||||
)
|
||||
# If prompt is None and model doesn't support prompts, silently return (no-op)
|
||||
return
|
||||
|
||||
logger.info(f"Updating {self.model_name} prompt.")
|
||||
logger.info(f"Updating {self._settings.model} prompt.")
|
||||
self._settings.prompt = prompt
|
||||
await self._disconnect()
|
||||
await self._connect()
|
||||
@@ -460,7 +464,7 @@ class SarvamSTTService(STTService):
|
||||
try:
|
||||
# Build common connection parameters
|
||||
connect_kwargs = {
|
||||
"model": self.model_name,
|
||||
"model": self._settings.model,
|
||||
"sample_rate": str(self.sample_rate),
|
||||
}
|
||||
|
||||
|
||||
@@ -489,6 +489,7 @@ class SarvamHttpTTSService(TTSService):
|
||||
model=model,
|
||||
voice=voice_id,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
# Add parameters based on model support
|
||||
if self._config.supports_pitch:
|
||||
@@ -506,8 +507,6 @@ class SarvamHttpTTSService(TTSService):
|
||||
elif params.temperature != 0.6:
|
||||
logger.warning(f"temperature parameter is ignored for {model}")
|
||||
|
||||
self.set_model_name(model)
|
||||
|
||||
def can_generate_metrics(self) -> bool:
|
||||
"""Check if this service can generate processing metrics.
|
||||
|
||||
@@ -559,7 +558,7 @@ class SarvamHttpTTSService(TTSService):
|
||||
"speaker": self._settings.voice,
|
||||
"sample_rate": self.sample_rate,
|
||||
"enable_preprocessing": self._settings.enable_preprocessing,
|
||||
"model": self._model_name,
|
||||
"model": self._settings.model,
|
||||
"pace": self._settings.pace if is_given(self._settings.pace) else 1.0,
|
||||
}
|
||||
|
||||
@@ -828,7 +827,6 @@ class SarvamTTSService(InterruptibleTTSService):
|
||||
# WebSocket endpoint URL with model query parameter
|
||||
self._websocket_url = f"{url}?model={model}"
|
||||
self._api_key = api_key
|
||||
self.set_model_name(model)
|
||||
|
||||
# Validate and clamp pace to model's valid range
|
||||
pace = params.pace
|
||||
@@ -854,6 +852,7 @@ class SarvamTTSService(InterruptibleTTSService):
|
||||
model=model,
|
||||
voice=voice_id,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
# Add parameters based on model support
|
||||
if self._config.supports_pitch:
|
||||
|
||||
@@ -195,13 +195,13 @@ class SonioxSTTService(WebsocketSTTService):
|
||||
|
||||
self._api_key = api_key
|
||||
self._url = url
|
||||
self.set_model_name(params.model)
|
||||
self._vad_force_turn_endpoint = vad_force_turn_endpoint
|
||||
|
||||
self._settings = SonioxSTTSettings(
|
||||
model=params.model,
|
||||
input_params=params,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._final_transcription_buffer = []
|
||||
self._last_tokens_received: Optional[float] = None
|
||||
@@ -247,7 +247,7 @@ class SonioxSTTService(WebsocketSTTService):
|
||||
elif "input_params" in changed and self._settings.input_params.model is not None:
|
||||
# Only input_params was given → pull model up.
|
||||
self._settings.model = self._settings.input_params.model
|
||||
self.set_model_name(self._settings.model)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
# TODO: someday we could reconnect here to apply updated settings.
|
||||
# Code might look something like the below:
|
||||
@@ -380,7 +380,7 @@ class SonioxSTTService(WebsocketSTTService):
|
||||
# Send the initial configuration message.
|
||||
config = {
|
||||
"api_key": self._api_key,
|
||||
"model": self._model_name,
|
||||
"model": self._settings.model,
|
||||
"audio_format": params.audio_format,
|
||||
"num_channels": params.num_channels or 1,
|
||||
"enable_endpoint_detection": enable_endpoint_detection,
|
||||
|
||||
@@ -459,7 +459,7 @@ class SpeechmaticsSTTService(STTService):
|
||||
|
||||
# Model + metrics (operating_point comes from the SDK config/preset)
|
||||
self._settings.model = self._config.operating_point.value
|
||||
self.set_model_name(self._config.operating_point.value)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
# Message queue
|
||||
self._stt_msg_queue: asyncio.Queue[dict[str, Any]] = asyncio.Queue()
|
||||
|
||||
@@ -492,7 +492,7 @@ class STTService(AIService):
|
||||
if self.metrics_enabled:
|
||||
ttfb_data = TTFBMetricsData(
|
||||
processor=self.name,
|
||||
model=self.model_name,
|
||||
model=self._settings.model,
|
||||
value=ttfb,
|
||||
)
|
||||
await super().push_frame(MetricsFrame(data=[ttfb_data]))
|
||||
|
||||
@@ -156,7 +156,6 @@ class BaseWhisperSTTService(SegmentedSTTService):
|
||||
**kwargs: Additional arguments passed to SegmentedSTTService.
|
||||
"""
|
||||
super().__init__(ttfs_p99_latency=ttfs_p99_latency, **kwargs)
|
||||
self.set_model_name(model)
|
||||
self._client = self._create_client(api_key, base_url)
|
||||
self._language = self.language_to_service_language(language or Language.EN)
|
||||
self._prompt = prompt
|
||||
@@ -170,6 +169,7 @@ class BaseWhisperSTTService(SegmentedSTTService):
|
||||
prompt=self._prompt,
|
||||
temperature=self._temperature,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
def _create_client(self, api_key: Optional[str], base_url: Optional[str]):
|
||||
return AsyncOpenAI(api_key=api_key, base_url=base_url)
|
||||
|
||||
@@ -236,7 +236,6 @@ class WhisperSTTService(SegmentedSTTService):
|
||||
super().__init__(**kwargs)
|
||||
self._device: str = device
|
||||
self._compute_type = compute_type
|
||||
self.set_model_name(model if isinstance(model, str) else model.value)
|
||||
self._no_speech_prob = no_speech_prob
|
||||
self._model: Optional[WhisperModel] = None
|
||||
|
||||
@@ -247,6 +246,7 @@ class WhisperSTTService(SegmentedSTTService):
|
||||
compute_type=self._compute_type,
|
||||
no_speech_prob=self._no_speech_prob,
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
self._load()
|
||||
|
||||
@@ -281,7 +281,7 @@ class WhisperSTTService(SegmentedSTTService):
|
||||
|
||||
logger.debug("Loading Whisper model...")
|
||||
self._model = WhisperModel(
|
||||
self.model_name, device=self._device, compute_type=self._compute_type
|
||||
self._settings.model, device=self._device, compute_type=self._compute_type
|
||||
)
|
||||
logger.debug("Loaded Whisper model")
|
||||
except ModuleNotFoundError as e:
|
||||
@@ -370,7 +370,6 @@ class WhisperSTTServiceMLX(WhisperSTTService):
|
||||
# Skip WhisperSTTService.__init__ and call its parent directly
|
||||
SegmentedSTTService.__init__(self, **kwargs)
|
||||
|
||||
self.set_model_name(model if isinstance(model, str) else model.value)
|
||||
self._no_speech_prob = no_speech_prob
|
||||
self._temperature = temperature
|
||||
|
||||
@@ -381,6 +380,7 @@ class WhisperSTTServiceMLX(WhisperSTTService):
|
||||
temperature=self._temperature,
|
||||
engine="mlx",
|
||||
)
|
||||
self._sync_model_name_to_metrics()
|
||||
|
||||
# No need to call _load() as MLX Whisper loads models on demand
|
||||
|
||||
@@ -421,7 +421,7 @@ class WhisperSTTServiceMLX(WhisperSTTService):
|
||||
chunk = await asyncio.to_thread(
|
||||
mlx_whisper.transcribe,
|
||||
audio_float,
|
||||
path_or_hf_repo=self.model_name,
|
||||
path_or_hf_repo=self._settings.model,
|
||||
temperature=self._temperature,
|
||||
language=self._settings.language,
|
||||
)
|
||||
|
||||
@@ -44,6 +44,23 @@ T = TypeVar("T")
|
||||
R = TypeVar("R")
|
||||
|
||||
|
||||
def _get_model_name(service) -> str:
|
||||
"""Get the model name from a service instance.
|
||||
|
||||
This is a bit of a mess — there were multiple places a model name could live.
|
||||
Soon, self._settings should be the only source of truth about model name.
|
||||
In fact...it might already be the case, but juuuuust to be safe, we'll
|
||||
check all the places we used to store it.
|
||||
"""
|
||||
return (
|
||||
getattr(getattr(service, "_settings", None), "model", None)
|
||||
or getattr(service, "_full_model_name", None)
|
||||
or getattr(service, "model_name", None)
|
||||
or getattr(service, "_model_name", None)
|
||||
or "unknown"
|
||||
)
|
||||
|
||||
|
||||
def _noop_decorator(func):
|
||||
"""No-op fallback decorator when tracing is unavailable.
|
||||
|
||||
@@ -194,7 +211,7 @@ def traced_tts(func: Optional[Callable] = None, *, name: Optional[str] = None) -
|
||||
add_tts_span_attributes(
|
||||
span=span,
|
||||
service_name=service_class_name,
|
||||
model=getattr(self, "model_name") or "unknown",
|
||||
model=_get_model_name(self),
|
||||
voice_id=getattr(settings, "voice", "unknown"),
|
||||
text=text,
|
||||
settings=settings,
|
||||
@@ -311,7 +328,7 @@ def traced_stt(func: Optional[Callable] = None, *, name: Optional[str] = None) -
|
||||
add_stt_span_attributes(
|
||||
span=current_span,
|
||||
service_name=service_class_name,
|
||||
model=getattr(self, "model_name") or settings.get("model", "unknown"),
|
||||
model=_get_model_name(self),
|
||||
transcript=transcript,
|
||||
is_final=is_final,
|
||||
language=str(language) if language else None,
|
||||
@@ -491,10 +508,7 @@ def traced_llm(func: Optional[Callable] = None, *, name: Optional[str] = None) -
|
||||
# Add all available attributes to the span
|
||||
attribute_kwargs = {
|
||||
"service_name": service_class_name,
|
||||
"model": getattr(self, "_full_model_name", None)
|
||||
or getattr(self, "model_name", None)
|
||||
or params.get("model")
|
||||
or "unknown",
|
||||
"model": _get_model_name(self),
|
||||
"stream": True, # Most LLM services use streaming
|
||||
"parameters": params,
|
||||
}
|
||||
@@ -593,11 +607,7 @@ def traced_gemini_live(operation: str) -> Callable:
|
||||
) as current_span:
|
||||
try:
|
||||
# Base service attributes
|
||||
model_name = (
|
||||
getattr(self, "model_name", None)
|
||||
or getattr(self, "_model_name", None)
|
||||
or "unknown"
|
||||
)
|
||||
model_name = _get_model_name(self)
|
||||
voice_id = getattr(self, "_voice_id", None)
|
||||
language_code = getattr(self, "_language_code", None)
|
||||
settings = getattr(self, "_settings", {})
|
||||
@@ -900,11 +910,7 @@ def traced_openai_realtime(operation: str) -> Callable:
|
||||
) as current_span:
|
||||
try:
|
||||
# Base service attributes
|
||||
model_name = (
|
||||
getattr(self, "model_name", None)
|
||||
or getattr(self, "_model_name", None)
|
||||
or "unknown"
|
||||
)
|
||||
model_name = _get_model_name(self)
|
||||
|
||||
# Operation-specific attribute collection
|
||||
operation_attrs = {}
|
||||
|
||||
Reference in New Issue
Block a user