From 15ca7dc675afe95d038fc8b950cf6cef9a6f4fec Mon Sep 17 00:00:00 2001 From: Paulo V C Medeiros Date: Sun, 3 Mar 2024 00:56:51 +0100 Subject: [PATCH] Make some configs unchangeble Some fOr technical reasons (compatibility between the the webrtcvad packages), some because they don't affect user experience or can be unclear to some users (e.g., speech_likelihood_threshold). --- pyrobbot/app/multipage.py | 9 ++++++--- pyrobbot/argparse_wrapper.py | 10 +++++++++- pyrobbot/chat_configs.py | 12 ++++++++++-- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/pyrobbot/app/multipage.py b/pyrobbot/app/multipage.py index 542c9c6..18d361f 100644 --- a/pyrobbot/app/multipage.py +++ b/pyrobbot/app/multipage.py @@ -769,6 +769,12 @@ def _set_page(page): def _handle_chat_configs_value_selection(self, current_chat_configs, model_fields): updates_to_chat_configs = {} for field_name, field in model_fields.items(): + extra_info = field.json_schema_extra or {} + + # Skip fields that are not allowed to be changed + if not extra_info.get("changeable", True): + continue + title = field_name.replace("_", " ").title() choices = VoiceChatConfigs.get_allowed_values(field=field_name) description = VoiceChatConfigs.get_description(field=field_name) @@ -776,9 +782,6 @@ def _handle_chat_configs_value_selection(self, current_chat_configs, model_field # Check if the field is frozen and disable corresponding UI element if so chat_started = self.selected_page.state.get("chat_started", False) - extra_info = field.json_schema_extra - if extra_info is None: - extra_info = {} disable_ui_element = extra_info.get("frozen", False) and ( chat_started or any(msg["role"] == "user" for msg in self.selected_page.chat_history) diff --git a/pyrobbot/argparse_wrapper.py b/pyrobbot/argparse_wrapper.py index d9aa1bc..d72517a 100644 --- a/pyrobbot/argparse_wrapper.py +++ b/pyrobbot/argparse_wrapper.py @@ -1,8 +1,11 @@ #!/usr/bin/env python3 """Wrappers for argparse functionality.""" import argparse +import contextlib import sys +from pydantic import BaseModel + from . import GeneralDefinitions from .chat_configs import ChatOptions, VoiceChatConfigs from .command_definitions import ( @@ -13,14 +16,19 @@ ) -def _populate_parser_from_pydantic_model(parser, model): +def _populate_parser_from_pydantic_model(parser, model: BaseModel): _argarse2pydantic = { "type": model.get_type, "default": model.get_default, "choices": model.get_allowed_values, "help": model.get_description, } + for field_name, field in model.model_fields.items(): + with contextlib.suppress(AttributeError): + if not field.json_schema_extra.get("changeable", True): + continue + args_opts = { key: _argarse2pydantic[key](field_name) for key in _argarse2pydantic diff --git a/pyrobbot/chat_configs.py b/pyrobbot/chat_configs.py index aa1a6ac..73c07a9 100644 --- a/pyrobbot/chat_configs.py +++ b/pyrobbot/chat_configs.py @@ -179,17 +179,20 @@ class VoiceAssistantConfigs(BaseConfigModel): exit_expressions: list[str] = Field( default=["bye-bye", "ok bye-bye", "okay bye-bye"], description="Expression(s) to use in order to exit the chat", + json_schema_extra={"changeable": False}, ) cancel_expressions: list[str] = Field( default=["ok", "okay", "cancel", "stop", "listen"], description="Word(s) to use in order to cancel the current reply", + json_schema_extra={"changeable": False}, ) min_speech_duration_seconds: float = Field( default=0.1, gt=0, description="Minimum duration of speech (in seconds) for the assistant to listen", + json_schema_extra={"changeable": False}, ) inactivity_timeout_seconds: int = Field( default=1, @@ -202,14 +205,19 @@ class VoiceAssistantConfigs(BaseConfigModel): ge=0.0, le=1.0, description="Accept audio as speech if the likelihood is above this threshold", + json_schema_extra={"changeable": False}, ) # sample_rate and frame_duration have to be consistent with the values uaccepted by # the webrtcvad package sample_rate: Literal[8000, 16000, 32000, 48000] = Field( - default=48000, description="Sample rate for audio recording, in Hz." + default=48000, + description="Sample rate for audio recording, in Hz.", + json_schema_extra={"changeable": False}, ) frame_duration: Literal[10, 20, 30] = Field( - default=20, description="Frame duration for audio recording, in milliseconds." + default=20, + description="Frame duration for audio recording, in milliseconds.", + json_schema_extra={"changeable": False}, ) reply_only_as_text: Optional[bool] = Field( default=None, description="Reply only as text. The assistant will not speak."