diff --git a/src/assistant/lib/models/__init__.py b/src/assistant/lib/models/__init__.py index 8641d86..00fea5c 100644 --- a/src/assistant/lib/models/__init__.py +++ b/src/assistant/lib/models/__init__.py @@ -1,4 +1,18 @@ from .orm import Base, IdCreatedUpdatedBaseMixin from .token import Token +from .tts import * -__all__ = ["Base", "IdCreatedUpdatedBaseMixin", "Token"] +__all__ = [ + "Base", + "BaseLanguageCodesEnum", + "BaseVoiceModel", + "BaseVoiceModel", + "ElevenLabsLanguageCodesEnum", + "IdCreatedUpdatedBaseMixin", + "LANGUAGE_CODES_ENUM_TYPE", + "TTSCreateRequestModel", + "TTSCreateResponseModel", + "TTSSearchVoiceRequestModel", + "Token", + "YandexLanguageCodesEnum", +] diff --git a/src/assistant/lib/models/tts/__init__.py b/src/assistant/lib/models/tts/__init__.py new file mode 100644 index 0000000..e26941c --- /dev/null +++ b/src/assistant/lib/models/tts/__init__.py @@ -0,0 +1,13 @@ +from .base import * +from .languages import * + +__all__ = [ + "BaseLanguageCodesEnum", + "BaseVoiceModel", + "ElevenLabsLanguageCodesEnum", + "LANGUAGE_CODES_ENUM_TYPE", + "TTSCreateRequestModel", + "TTSCreateResponseModel", + "TTSSearchVoiceRequestModel", + "YandexLanguageCodesEnum", +] diff --git a/src/assistant/lib/models/tts/base.py b/src/assistant/lib/models/tts/base.py new file mode 100644 index 0000000..7be9b6a --- /dev/null +++ b/src/assistant/lib/models/tts/base.py @@ -0,0 +1,45 @@ +import typing + +import pydantic + +import lib.models.tts.languages as models_tts_languages + + +class TTSCreateRequestModel(pydantic.BaseModel): + model_config = pydantic.ConfigDict(use_enum_values=True) + + voice_model_name: str + text: str + + +class TTSCreateResponseModel(pydantic.BaseModel): + audio_content: bytes + + +class BaseVoiceModel(pydantic.BaseModel): + voice_id: str + voice_name: str | None = None + languages: list[models_tts_languages.LANGUAGE_CODES_ENUM_TYPE] + company_name: str + + @pydantic.model_validator(mode="before") + @classmethod + def check_voice_name_exists(cls, data: typing.Any) -> typing.Any: + voice_id = data.get("voice_id") + voice_name = data.get("voice_name") + if not voice_name and voice_id: + data["voice_name"] = voice_id + return data + + +class TTSSearchVoiceRequestModel(pydantic.BaseModel): + voice_id: str | None = None + voice_name: str | None = None + languages: list[models_tts_languages.LANGUAGE_CODES_ENUM_TYPE] | None = None + company_name: str | None = None + + @pydantic.model_validator(mode="after") + def check_at_least_one_field(self): + if not any((self.voice_name, self.languages, self.company_name)): + raise ValueError("At least one field required") + return self diff --git a/src/assistant/lib/models/tts/languages.py b/src/assistant/lib/models/tts/languages.py new file mode 100644 index 0000000..08f5db8 --- /dev/null +++ b/src/assistant/lib/models/tts/languages.py @@ -0,0 +1,83 @@ +import enum + + +class BaseLanguageCodesEnum(enum.Enum): + RUSSIAN = "ru" + ENGLISH = "en" + KAZAKH = "kk" + GERMAN = "de" + HEBREW = "he" + UZBEK = "uz" + JAPANESE = "ja" + CHINESE = "zh" + HINDI = "hi" + FRENCH = "fr" + KOREAN = "ko" + PORTUGUESE = "pt" + ITALIAN = "it" + SPANISH = "es" + INDONESIAN = "id" + DUTCH = "nl" + TURKISH = "tr" + FILIPINO = "fil" + POLISH = "pl" + SWEDISH = "sv" + BULGARIAN = "bg" + ROMANIAN = "ro" + ARABIC = "ar" + CZECH = "cs" + GREEK = "el" + FINNISH = "fi" + CROATIAN = "hr" + MALAY = "ms" + SLOVAK = "sk" + DANISH = "da" + TAMIL = "ta" + UKRAINIAN = "uk" + + +class ElevenLabsLanguageCodesEnum(enum.Enum): + RUSSIAN = "ru" + ENGLISH = "en" + KAZAKH = "kk" + GERMAN = "de" + HEBREW = "he" + UZBEK = "uz" + JAPANESE = "ja" + CHINESE = "zh" + HINDI = "hi" + FRENCH = "fr" + KOREAN = "ko" + PORTUGUESE = "pt" + ITALIAN = "it" + SPANISH = "es" + INDONESIAN = "id" + DUTCH = "nl" + TURKISH = "tr" + FILIPINO = "fil" + POLISH = "pl" + SWEDISH = "sv" + BULGARIAN = "bg" + ROMANIAN = "ro" + ARABIC = "ar" + CZECH = "cs" + GREEK = "el" + FINNISH = "fi" + CROATIAN = "hr" + MALAY = "ms" + SLOVAK = "sk" + DANISH = "da" + TAMIL = "ta" + UKRAINIAN = "uk" + + +class YandexLanguageCodesEnum(enum.Enum): + RUSSIAN = "ru-RU" + ENGLISH = "en-US" + KAZAKH = "kk-KK" + GERMAN = "de-DE" + HEBREW = "he-IL" + UZBEK = "uz-UZ" + + +LANGUAGE_CODES_ENUM_TYPE = BaseLanguageCodesEnum | ElevenLabsLanguageCodesEnum | YandexLanguageCodesEnum diff --git a/src/assistant/lib/tts/models/__init__.py b/src/assistant/lib/tts/models/__init__.py index f3a089c..fd5289e 100644 --- a/src/assistant/lib/tts/models/__init__.py +++ b/src/assistant/lib/tts/models/__init__.py @@ -1,11 +1,17 @@ -from .models import * +from .repository import * +from .service import * +from .utils import * from .voice import * __all__ = [ - "LanguageCodes", - "TTSRequestModel", - "TTSResponseModel", - "VoiceModel", - "YandexVoiceModelNamesString", - "YandexVoiceModels", + "ElevenLabsListVoiceModelsModel", + "ElevenLabsVoiceModel", + "LIST_VOICE_MODELS_TYPE", + "LIST_VOICE_MODELS_TYPE", + "TTSCreateRequestServiceModel", + "TTSCreateResponseServiceModel", + "TTSRepositoryProtocol", + "VOICE_MODELS_TYPE", + "YandexListVoiceModelsModel", + "YandexVoiceModel", ] diff --git a/src/assistant/lib/tts/models/models.py b/src/assistant/lib/tts/models/models.py deleted file mode 100644 index 2cf44bb..0000000 --- a/src/assistant/lib/tts/models/models.py +++ /dev/null @@ -1,14 +0,0 @@ -import pydantic - -import lib.tts.models.voice as tts_models_voice - - -class TTSRequestModel(pydantic.BaseModel): - model_config = pydantic.ConfigDict(use_enum_values=True) - - voice_model_name: tts_models_voice.YandexVoiceModelNamesString - text: str - - -class TTSResponseModel(pydantic.BaseModel): - audio_content: bytes diff --git a/src/assistant/lib/tts/models/repository.py b/src/assistant/lib/tts/models/repository.py new file mode 100644 index 0000000..142d7c5 --- /dev/null +++ b/src/assistant/lib/tts/models/repository.py @@ -0,0 +1,17 @@ +import typing + +import lib.models as models +import lib.tts.models.utils as tts_models_utils + + +class TTSRepositoryProtocol(typing.Protocol): + def get_audio_as_bytes_from_text(self, text: str) -> models.TTSCreateResponseModel: + ... + + def get_voice_model_by_name(self, voice_model_name: str) -> models.BaseVoiceModel | None: + ... + + def get_voice_models_by_fields( + self, fields: models.TTSSearchVoiceRequestModel + ) -> tts_models_utils.LIST_VOICE_MODELS_TYPE: + ... diff --git a/src/assistant/lib/tts/models/service.py b/src/assistant/lib/tts/models/service.py new file mode 100644 index 0000000..694770e --- /dev/null +++ b/src/assistant/lib/tts/models/service.py @@ -0,0 +1,9 @@ +import lib.models as models + + +class TTSCreateRequestServiceModel(models.TTSCreateRequestModel): + ... + + +class TTSCreateResponseServiceModel(models.TTSCreateResponseModel): + ... diff --git a/src/assistant/lib/tts/models/utils.py b/src/assistant/lib/tts/models/utils.py new file mode 100644 index 0000000..1a653b5 --- /dev/null +++ b/src/assistant/lib/tts/models/utils.py @@ -0,0 +1,4 @@ +import lib.tts.models.voice as tts_models_voice + +VOICE_MODELS_TYPE = tts_models_voice.YandexVoiceModel | tts_models_voice.ElevenLabsVoiceModel +LIST_VOICE_MODELS_TYPE = tts_models_voice.YandexListVoiceModelsModel | tts_models_voice.ElevenLabsListVoiceModelsModel diff --git a/src/assistant/lib/tts/models/voice/__init__.py b/src/assistant/lib/tts/models/voice/__init__.py index ce1a9cf..7ca63ac 100644 --- a/src/assistant/lib/tts/models/voice/__init__.py +++ b/src/assistant/lib/tts/models/voice/__init__.py @@ -1,9 +1,9 @@ -from .base import * +from .eleven_labs import * from .yandex import * __all__ = [ - "LanguageCodes", - "VoiceModel", - "YandexVoiceModelNamesString", - "YandexVoiceModels", + "ElevenLabsListVoiceModelsModel", + "ElevenLabsVoiceModel", + "YandexListVoiceModelsModel", + "YandexVoiceModel", ] diff --git a/src/assistant/lib/tts/models/voice/base.py b/src/assistant/lib/tts/models/voice/base.py deleted file mode 100644 index 65082f1..0000000 --- a/src/assistant/lib/tts/models/voice/base.py +++ /dev/null @@ -1,20 +0,0 @@ -import enum - -import pydantic - - -class LanguageCodes(enum.Enum): - RUSSIAN = "ru-RU" - ENGLISH = "en-US" - KAZAKH = "kk-KK" - GERMAN = "de-DE" - HEBREW = "he-IL" - UZBEK = "uz-UZ" - - -class VoiceModel(pydantic.BaseModel): - model_config = pydantic.ConfigDict(use_enum_values=True) - - voice_name: str - role: str | None = None - lang: LanguageCodes diff --git a/src/assistant/lib/tts/models/voice/eleven_labs.py b/src/assistant/lib/tts/models/voice/eleven_labs.py new file mode 100644 index 0000000..1e989c1 --- /dev/null +++ b/src/assistant/lib/tts/models/voice/eleven_labs.py @@ -0,0 +1,73 @@ +import typing + +import pydantic + +import lib.models as models + + +class ElevenLabsVoiceModel(models.BaseVoiceModel): + voice_id: str + voice_name: str | None = None + languages: list[models.LANGUAGE_CODES_ENUM_TYPE] + company_name: str = "eleven labs" + + +class ElevenLabsListVoiceModelsModel(pydantic.BaseModel): + models: list[ElevenLabsVoiceModel] = [ + ElevenLabsVoiceModel( + voice_id="eleven_multilingual_v1", + languages=[ + models.ElevenLabsLanguageCodesEnum.ENGLISH, + models.ElevenLabsLanguageCodesEnum.GERMAN, + models.ElevenLabsLanguageCodesEnum.POLISH, + models.ElevenLabsLanguageCodesEnum.SPANISH, + models.ElevenLabsLanguageCodesEnum.ITALIAN, + models.ElevenLabsLanguageCodesEnum.FRENCH, + models.ElevenLabsLanguageCodesEnum.PORTUGUESE, + models.ElevenLabsLanguageCodesEnum.HINDI, + models.ElevenLabsLanguageCodesEnum.ARABIC, + ], + ), + ElevenLabsVoiceModel( + voice_id="eleven_multilingual_v2", + languages=[ + models.ElevenLabsLanguageCodesEnum.ENGLISH, + models.ElevenLabsLanguageCodesEnum.JAPANESE, + models.ElevenLabsLanguageCodesEnum.CHINESE, + models.ElevenLabsLanguageCodesEnum.GERMAN, + models.ElevenLabsLanguageCodesEnum.HINDI, + models.ElevenLabsLanguageCodesEnum.FRENCH, + models.ElevenLabsLanguageCodesEnum.KOREAN, + models.ElevenLabsLanguageCodesEnum.PORTUGUESE, + models.ElevenLabsLanguageCodesEnum.ITALIAN, + models.ElevenLabsLanguageCodesEnum.SPANISH, + models.ElevenLabsLanguageCodesEnum.INDONESIAN, + models.ElevenLabsLanguageCodesEnum.DUTCH, + models.ElevenLabsLanguageCodesEnum.TURKISH, + models.ElevenLabsLanguageCodesEnum.FILIPINO, + models.ElevenLabsLanguageCodesEnum.POLISH, + models.ElevenLabsLanguageCodesEnum.SWEDISH, + models.ElevenLabsLanguageCodesEnum.BULGARIAN, + models.ElevenLabsLanguageCodesEnum.ROMANIAN, + models.ElevenLabsLanguageCodesEnum.ARABIC, + models.ElevenLabsLanguageCodesEnum.CZECH, + models.ElevenLabsLanguageCodesEnum.GREEK, + models.ElevenLabsLanguageCodesEnum.FINNISH, + models.ElevenLabsLanguageCodesEnum.CROATIAN, + models.ElevenLabsLanguageCodesEnum.MALAY, + models.ElevenLabsLanguageCodesEnum.SLOVAK, + models.ElevenLabsLanguageCodesEnum.DANISH, + models.ElevenLabsLanguageCodesEnum.TAMIL, + models.ElevenLabsLanguageCodesEnum.UKRAINIAN, + ], + ), + ElevenLabsVoiceModel( + voice_id="eleven_multilingual_v2", + languages=[models.ElevenLabsLanguageCodesEnum.ENGLISH], + ), + ] + + @classmethod + def from_api(cls, voice_models_from_api: list[dict[str, typing.Any]]) -> typing.Self: + voice_models = [ElevenLabsVoiceModel.model_validate(voice_model) for voice_model in voice_models_from_api] + return ElevenLabsListVoiceModelsModel(models=voice_models) diff --git a/src/assistant/lib/tts/models/voice/yandex.py b/src/assistant/lib/tts/models/voice/yandex.py index 3a47c6b..099acde 100644 --- a/src/assistant/lib/tts/models/voice/yandex.py +++ b/src/assistant/lib/tts/models/voice/yandex.py @@ -1,126 +1,60 @@ -import enum +import typing -import lib.tts.models.voice.base as tts_models_voice_base +import pydantic + +import lib.models as models -class YandexVoiceModelNamesString(enum.Enum): - ERMIL_NEUTRAL = "ermil neutral" - ERMIL_GOOD = "ermil good" - ALENA_NEUTRAL = "alena neutral" - ALENA_GOOD = "alena good" - JANE_NEUTRAL = "jane neutral" - JANE_GOOD = "jane good" - JANE_EVIL = "jane evil" - OMAZH_NEUTRAL = "omazh neutral" - OMAZH_EVIL = "omazh evil" - ZAHAR_NEUTRAL = "zahar neutral" - ZAHAR_GOOD = "zahar good" - FILIPP = "filipp" - MADIRUS = "madirus" - DASHA = "dasha" - JULIA = "julia" - LERA = "lera" - MARINA = "marina" - ALEXANDER = "alexander" - KIRILL = "kirill" - ANTON = "anton" - # English - JOHN = "john" - # Kazakh - AMIRA = "amira" - MADI = "madi" - # German - LEA = "lea" - # HEBREW - NAOMI_MODERN = "naomi modern" - NAOMI_CLASSIC = "naomi classic" - # Uzbek - NIGORA = "nigora" +class YandexVoiceModel(models.BaseVoiceModel): + voice_id: str + voice_name: str | None = None + languages: list[models.LANGUAGE_CODES_ENUM_TYPE] + company_name: str = "yandex" + role: str | None = None + + @pydantic.model_validator(mode="before") + @classmethod + def check_voice_name_exists(cls, data: typing.Any) -> typing.Any: + voice_id = data.get("voice_id") + voice_name = data.get("voice_name") + role = data.get("role") + if not voice_name and voice_id: + data["voice_name"] = f"{voice_id} {role}" if role else voice_id + return data -class YandexVoiceModels(enum.Enum): - # Russian - ERMIL_NEUTRAL = tts_models_voice_base.VoiceModel( - voice_name="ermil", role="neutral", lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - ERMIL_GOOD = tts_models_voice_base.VoiceModel( - voice_name="ermil", role="good", lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - ALENA_NEUTRAL = tts_models_voice_base.VoiceModel( - voice_name="alena", role="neutral", lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - ALENA_GOOD = tts_models_voice_base.VoiceModel( - voice_name="alena", role="good", lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - JANE_NEUTRAL = tts_models_voice_base.VoiceModel( - voice_name="jane", role="neutral", lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - JANE_GOOD = tts_models_voice_base.VoiceModel( - voice_name="jane", role="good", lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - JANE_EVIL = tts_models_voice_base.VoiceModel( - voice_name="jane", role="evil", lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - OMAZH_NEUTRAL = tts_models_voice_base.VoiceModel( - voice_name="omazh", role="neutral", lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - OMAZH_EVIL = tts_models_voice_base.VoiceModel( - voice_name="omazh", role="evil", lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - ZAHAR_NEUTRAL = tts_models_voice_base.VoiceModel( - voice_name="zahar", role="neutral", lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - ZAHAR_GOOD = tts_models_voice_base.VoiceModel( - voice_name="zahar", role="good", lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - FILIPP = tts_models_voice_base.VoiceModel( - voice_name="filipp", role=None, lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - MADIRUS = tts_models_voice_base.VoiceModel( - voice_name="madirus", role=None, lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - DASHA = tts_models_voice_base.VoiceModel( - voice_name="dasha", role=None, lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - JULIA = tts_models_voice_base.VoiceModel( - voice_name="julia", role=None, lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - LERA = tts_models_voice_base.VoiceModel( - voice_name="lera", role=None, lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - MARINA = tts_models_voice_base.VoiceModel( - voice_name="marina", role=None, lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - ALEXANDER = tts_models_voice_base.VoiceModel( - voice_name="alexander", role=None, lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - KIRILL = tts_models_voice_base.VoiceModel( - voice_name="kirill", role=None, lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - ANTON = tts_models_voice_base.VoiceModel( - voice_name="anton", role=None, lang=tts_models_voice_base.LanguageCodes.RUSSIAN - ) - # English - JOHN = tts_models_voice_base.VoiceModel( - voice_name="john", role=None, lang=tts_models_voice_base.LanguageCodes.ENGLISH - ) - # Kazakh - AMIRA = tts_models_voice_base.VoiceModel( - voice_name="amira", role=None, lang=tts_models_voice_base.LanguageCodes.KAZAKH - ) - MADI = tts_models_voice_base.VoiceModel( - voice_name="madi", role=None, lang=tts_models_voice_base.LanguageCodes.KAZAKH - ) - # German - LEA = tts_models_voice_base.VoiceModel(voice_name="lea", role=None, lang=tts_models_voice_base.LanguageCodes.GERMAN) - # HEBREW - NAOMI_MODERN = tts_models_voice_base.VoiceModel( - voice_name="naomi", role="modern", lang=tts_models_voice_base.LanguageCodes.HEBREW - ) - NAOMI_CLASSIC = tts_models_voice_base.VoiceModel( - voice_name="naomi", role="classic", lang=tts_models_voice_base.LanguageCodes.HEBREW - ) - # Uzbek - NIGORA = tts_models_voice_base.VoiceModel( - voice_name="nigora", role=None, lang=tts_models_voice_base.LanguageCodes.UZBEK - ) +class YandexListVoiceModelsModel(pydantic.BaseModel): + models: list[YandexVoiceModel] = [ + YandexVoiceModel(voice_id="ermil", role="neutral", languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="ermil", role="good", languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="alena", role="neutral", languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="alena", role="good", languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="jane", role="neutral", languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="jane", role="good", languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="jane", role="evil", languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="omazh", role="neutral", languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="omazh", role="evil", languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="zahar", role="neutral", languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="zahar", role="good", languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="filipp", role=None, languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="madirus", role=None, languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="dasha", role=None, languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="julia", role=None, languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="lera", role=None, languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="marina", role=None, languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="alexander", role=None, languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="kirill", role=None, languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="anton", role=None, languages=[models.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="john", role=None, languages=[models.YandexLanguageCodesEnum.ENGLISH]), + YandexVoiceModel(voice_id="amira", role=None, languages=[models.YandexLanguageCodesEnum.KAZAKH]), + YandexVoiceModel(voice_id="madi", role=None, languages=[models.YandexLanguageCodesEnum.KAZAKH]), + YandexVoiceModel(voice_id="lea", role=None, languages=[models.YandexLanguageCodesEnum.GERMAN]), + YandexVoiceModel(voice_id="naomi", role="modern", languages=[models.YandexLanguageCodesEnum.HEBREW]), + YandexVoiceModel(voice_id="naomi", role="classic", languages=[models.YandexLanguageCodesEnum.HEBREW]), + YandexVoiceModel(voice_id="nigora", role=None, languages=[models.YandexLanguageCodesEnum.UZBEK]), + ] + + @classmethod + def from_api(cls, voice_models_from_api: list[dict[str, typing.Any]]) -> typing.Self: + voice_models = [YandexVoiceModel.model_validate(voice_model) for voice_model in voice_models_from_api] + return YandexListVoiceModelsModel(models=voice_models) diff --git a/src/assistant/lib/tts/repositories/__init__.py b/src/assistant/lib/tts/repositories/__init__.py new file mode 100644 index 0000000..45a1941 --- /dev/null +++ b/src/assistant/lib/tts/repositories/__init__.py @@ -0,0 +1,5 @@ +from .base import * + +__all__ = [ + "TTSBaseRepository", +]