From 62bd0a7b999e7b82276a4040cf245d760ce860a5 Mon Sep 17 00:00:00 2001 From: ksieuk Date: Wed, 4 Oct 2023 18:41:28 +0300 Subject: [PATCH 01/12] feat: [#28] add tts models --- src/assistant/lib/tts/__init__.py | 0 src/assistant/lib/tts/models/__init__.py | 11 ++ src/assistant/lib/tts/models/models.py | 13 ++ .../lib/tts/models/voice/__init__.py | 9 ++ src/assistant/lib/tts/models/voice/base.py | 20 +++ src/assistant/lib/tts/models/voice/yandex.py | 126 ++++++++++++++++++ 6 files changed, 179 insertions(+) create mode 100644 src/assistant/lib/tts/__init__.py create mode 100644 src/assistant/lib/tts/models/__init__.py create mode 100644 src/assistant/lib/tts/models/models.py create mode 100644 src/assistant/lib/tts/models/voice/__init__.py create mode 100644 src/assistant/lib/tts/models/voice/base.py create mode 100644 src/assistant/lib/tts/models/voice/yandex.py diff --git a/src/assistant/lib/tts/__init__.py b/src/assistant/lib/tts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/assistant/lib/tts/models/__init__.py b/src/assistant/lib/tts/models/__init__.py new file mode 100644 index 0000000..f3a089c --- /dev/null +++ b/src/assistant/lib/tts/models/__init__.py @@ -0,0 +1,11 @@ +from .models import * +from .voice import * + +__all__ = [ + "LanguageCodes", + "TTSRequestModel", + "TTSResponseModel", + "VoiceModel", + "YandexVoiceModelNamesString", + "YandexVoiceModels", +] diff --git a/src/assistant/lib/tts/models/models.py b/src/assistant/lib/tts/models/models.py new file mode 100644 index 0000000..14ee677 --- /dev/null +++ b/src/assistant/lib/tts/models/models.py @@ -0,0 +1,13 @@ +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 + + +class TTSResponseModel(pydantic.BaseModel): + audio_content: bytes diff --git a/src/assistant/lib/tts/models/voice/__init__.py b/src/assistant/lib/tts/models/voice/__init__.py new file mode 100644 index 0000000..ce1a9cf --- /dev/null +++ b/src/assistant/lib/tts/models/voice/__init__.py @@ -0,0 +1,9 @@ +from .base import * +from .yandex import * + +__all__ = [ + "LanguageCodes", + "VoiceModel", + "YandexVoiceModelNamesString", + "YandexVoiceModels", +] diff --git a/src/assistant/lib/tts/models/voice/base.py b/src/assistant/lib/tts/models/voice/base.py new file mode 100644 index 0000000..65082f1 --- /dev/null +++ b/src/assistant/lib/tts/models/voice/base.py @@ -0,0 +1,20 @@ +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/yandex.py b/src/assistant/lib/tts/models/voice/yandex.py new file mode 100644 index 0000000..3a47c6b --- /dev/null +++ b/src/assistant/lib/tts/models/voice/yandex.py @@ -0,0 +1,126 @@ +import enum + +import lib.tts.models.voice.base as tts_models_voice_base + + +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 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 + ) From 90735ca14eab5e35c32706b3e0132c5209acd47b Mon Sep 17 00:00:00 2001 From: ksieuk Date: Wed, 4 Oct 2023 18:41:44 +0300 Subject: [PATCH 02/12] feat: [#28] add base tts service --- src/assistant/lib/tts/services.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/assistant/lib/tts/services.py diff --git a/src/assistant/lib/tts/services.py b/src/assistant/lib/tts/services.py new file mode 100644 index 0000000..904157a --- /dev/null +++ b/src/assistant/lib/tts/services.py @@ -0,0 +1,16 @@ +import abc + +import lib.app.settings as app_settings +import lib.tts.models as tts_models + + +class BaseTTSService(abc.ABC): + def __init__( + self, + settings: app_settings.Settings, + ): + self.settings = settings + + @abc.abstractmethod + def get_tts(self, tts_request: tts_models.TTSRequestModel) -> tts_models.TTSResponseModel: + raise NotImplementedError() From f59b097cfa893e46d3a84ad1f728378802453034 Mon Sep 17 00:00:00 2001 From: ksieuk Date: Wed, 4 Oct 2023 18:46:53 +0300 Subject: [PATCH 03/12] fix: [#28] add audio_content to request model --- src/assistant/lib/tts/models/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/assistant/lib/tts/models/models.py b/src/assistant/lib/tts/models/models.py index 14ee677..1b28da1 100644 --- a/src/assistant/lib/tts/models/models.py +++ b/src/assistant/lib/tts/models/models.py @@ -7,6 +7,7 @@ class TTSRequestModel(pydantic.BaseModel): model_config = pydantic.ConfigDict(use_enum_values=True) voice_model_name: tts_models_voice.YandexVoiceModelNamesString + audio_content: bytes class TTSResponseModel(pydantic.BaseModel): From d70375956c33b5caeba25a0081d2967980c19e0f Mon Sep 17 00:00:00 2001 From: ksieuk Date: Wed, 4 Oct 2023 18:49:23 +0300 Subject: [PATCH 04/12] fix(typo): [#28] audio_content -> text --- src/assistant/lib/tts/models/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assistant/lib/tts/models/models.py b/src/assistant/lib/tts/models/models.py index 1b28da1..2cf44bb 100644 --- a/src/assistant/lib/tts/models/models.py +++ b/src/assistant/lib/tts/models/models.py @@ -7,7 +7,7 @@ class TTSRequestModel(pydantic.BaseModel): model_config = pydantic.ConfigDict(use_enum_values=True) voice_model_name: tts_models_voice.YandexVoiceModelNamesString - audio_content: bytes + text: str class TTSResponseModel(pydantic.BaseModel): From 61e968c33b762773f65082781979656737afe5f6 Mon Sep 17 00:00:00 2001 From: ksieuk Date: Tue, 10 Oct 2023 18:33:33 +0300 Subject: [PATCH 05/12] feat: [#28] models update --- src/assistant/lib/models/__init__.py | 16 +- src/assistant/lib/models/tts/__init__.py | 13 ++ src/assistant/lib/models/tts/base.py | 45 +++++ src/assistant/lib/models/tts/languages.py | 83 +++++++++ src/assistant/lib/tts/models/__init__.py | 20 +- src/assistant/lib/tts/models/models.py | 14 -- src/assistant/lib/tts/models/repository.py | 17 ++ src/assistant/lib/tts/models/service.py | 9 + src/assistant/lib/tts/models/utils.py | 4 + .../lib/tts/models/voice/__init__.py | 10 +- src/assistant/lib/tts/models/voice/base.py | 20 -- .../lib/tts/models/voice/eleven_labs.py | 73 ++++++++ src/assistant/lib/tts/models/voice/yandex.py | 176 ++++++------------ .../lib/tts/repositories/__init__.py | 5 + 14 files changed, 337 insertions(+), 168 deletions(-) create mode 100644 src/assistant/lib/models/tts/__init__.py create mode 100644 src/assistant/lib/models/tts/base.py create mode 100644 src/assistant/lib/models/tts/languages.py delete mode 100644 src/assistant/lib/tts/models/models.py create mode 100644 src/assistant/lib/tts/models/repository.py create mode 100644 src/assistant/lib/tts/models/service.py create mode 100644 src/assistant/lib/tts/models/utils.py delete mode 100644 src/assistant/lib/tts/models/voice/base.py create mode 100644 src/assistant/lib/tts/models/voice/eleven_labs.py create mode 100644 src/assistant/lib/tts/repositories/__init__.py 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", +] From 741a470d8921b9a98ed1301da815ac044164a018 Mon Sep 17 00:00:00 2001 From: ksieuk Date: Tue, 10 Oct 2023 18:33:49 +0300 Subject: [PATCH 06/12] feat: [#28] add base repository --- src/assistant/lib/tts/repositories/base.py | 59 ++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/assistant/lib/tts/repositories/base.py diff --git a/src/assistant/lib/tts/repositories/base.py b/src/assistant/lib/tts/repositories/base.py new file mode 100644 index 0000000..238b873 --- /dev/null +++ b/src/assistant/lib/tts/repositories/base.py @@ -0,0 +1,59 @@ +import abc + +import lib.models as models +import lib.tts.models as tts_models + + +class HttpClient: # Mocked class todo remove and use real http client from lib.clients.http_client + ... + + +class TTSBaseRepository(abc.ABC): + def __init__(self, client: HttpClient, is_models_from_api: bool = False): + self.http_client = client + self.is_models_from_api = is_models_from_api + + @property + @abc.abstractmethod + def voice_models(self) -> tts_models.LIST_VOICE_MODELS_TYPE: + ... + + @abc.abstractmethod + def get_audio_as_bytes_from_text(self, text: str) -> models.TTSCreateResponseModel: + raise NotImplementedError + + def get_voice_model_by_name(self, voice_model_name: str) -> models.BaseVoiceModel | None: + """ + Search voice model by name + :param voice_model_name: String name + :return: Voice model that match the name + """ + for voice_model in self.voice_models.models: + if voice_model.voice_name == voice_model_name: + return voice_model + + def get_list_voice_models_by_fields( + self, fields: models.TTSSearchVoiceRequestModel + ) -> list[tts_models.VOICE_MODELS_TYPE]: + """ + Search voice model by fields + :param fields: Any fields from TTSSearchVoiceRequestModel + :return: All voice models that match the fields + """ + fields_dump = fields.model_dump(exclude_none=True) + voice_models_response = [] + for voice_model in self.voice_models.models: + voice_model: tts_models.VOICE_MODELS_TYPE + for field, field_value in fields_dump.items(): + if field == "languages": # language is a list + language_names: set[str] = {item.name for item in field_value} + voice_model_language_names: set[str] = {item.name for item in voice_model.languages} + if language_names.issubset(voice_model_language_names): + continue + break + voice_model_dump = voice_model.model_dump() + if voice_model_dump[field] != field_value.name: + break + else: + voice_models_response.append(voice_model) + return voice_models_response # type: ignore[reportUnknownVariableType] From 0ef28afa227e78afceff4d4568375a89ca0eb7bf Mon Sep 17 00:00:00 2001 From: ksieuk Date: Tue, 10 Oct 2023 18:34:05 +0300 Subject: [PATCH 07/12] feat: [#28] add base service --- src/assistant/lib/tts/services.py | 35 +++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/assistant/lib/tts/services.py b/src/assistant/lib/tts/services.py index 904157a..df8a00b 100644 --- a/src/assistant/lib/tts/services.py +++ b/src/assistant/lib/tts/services.py @@ -1,16 +1,39 @@ -import abc - import lib.app.settings as app_settings +import lib.models as models import lib.tts.models as tts_models -class BaseTTSService(abc.ABC): +class TTSService: def __init__( self, settings: app_settings.Settings, + tts_repositories: list[tts_models.TTSRepositoryProtocol], ): self.settings = settings + self.tts_repositories = tts_repositories - @abc.abstractmethod - def get_tts(self, tts_request: tts_models.TTSRequestModel) -> tts_models.TTSResponseModel: - raise NotImplementedError() + def get_audio_as_bytes_from_text(self, tts_request: models.TTSCreateRequestModel) -> models.TTSCreateResponseModel: + for repository in self.tts_repositories: + voice_model = repository.get_voice_model_by_name(tts_request.voice_model_name) + if voice_model: + audio_response = repository.get_audio_as_bytes_from_text(tts_request.text) + break + else: + raise ValueError(f"Voice model {tts_request.voice_model_name} not found") + return audio_response + + def get_voice_model_by_name(self, voice_model_name: str) -> models.BaseVoiceModel | None: + for repository in self.tts_repositories: + voice_model = repository.get_voice_model_by_name(voice_model_name) + if voice_model: + return voice_model + + def get_list_voice_models_by_fields( + self, fields: models.TTSSearchVoiceRequestModel + ) -> list[tts_models.VOICE_MODELS_TYPE]: + response_models: list[tts_models.VOICE_MODELS_TYPE] = [] + for repository in self.tts_repositories: + voice_models = repository.get_voice_models_by_fields(fields) + if voice_models.models: + response_models.extend(voice_models.models) + return response_models From 48a6f4e1675eb6e9639c04510359be42533801b0 Mon Sep 17 00:00:00 2001 From: ksieuk Date: Wed, 11 Oct 2023 18:41:10 +0300 Subject: [PATCH 08/12] fix: [#28] review fixes --- src/assistant/lib/models/__init__.py | 4 +- src/assistant/lib/models/tts/__init__.py | 7 +- .../lib/models/tts/{base.py => models.py} | 26 ++--- .../lib/models/tts/voice/__init__.py | 17 ++++ src/assistant/lib/models/tts/voice/base.py | 27 ++++++ .../lib/models/tts/voice/eleven_labs.py | 75 ++++++++++++++ .../lib/models/tts/{ => voice}/languages.py | 0 src/assistant/lib/models/tts/voice/yandex.py | 97 +++++++++++++++++++ src/assistant/lib/tts/models/__init__.py | 14 +-- src/assistant/lib/tts/models/protocols.py | 14 +++ src/assistant/lib/tts/models/repository.py | 17 ---- src/assistant/lib/tts/models/service.py | 9 -- src/assistant/lib/tts/models/utils.py | 4 - .../lib/tts/models/voice/__init__.py | 9 -- .../lib/tts/models/voice/eleven_labs.py | 73 -------------- src/assistant/lib/tts/models/voice/yandex.py | 60 ------------ src/assistant/lib/tts/repositories/base.py | 8 +- src/assistant/lib/tts/services.py | 24 ++--- 18 files changed, 258 insertions(+), 227 deletions(-) rename src/assistant/lib/models/tts/{base.py => models.py} (53%) create mode 100644 src/assistant/lib/models/tts/voice/__init__.py create mode 100644 src/assistant/lib/models/tts/voice/base.py create mode 100644 src/assistant/lib/models/tts/voice/eleven_labs.py rename src/assistant/lib/models/tts/{ => voice}/languages.py (100%) create mode 100644 src/assistant/lib/models/tts/voice/yandex.py create mode 100644 src/assistant/lib/tts/models/protocols.py delete mode 100644 src/assistant/lib/tts/models/repository.py delete mode 100644 src/assistant/lib/tts/models/service.py delete mode 100644 src/assistant/lib/tts/models/utils.py delete mode 100644 src/assistant/lib/tts/models/voice/__init__.py delete mode 100644 src/assistant/lib/tts/models/voice/eleven_labs.py delete mode 100644 src/assistant/lib/tts/models/voice/yandex.py diff --git a/src/assistant/lib/models/__init__.py b/src/assistant/lib/models/__init__.py index 00fea5c..70993c4 100644 --- a/src/assistant/lib/models/__init__.py +++ b/src/assistant/lib/models/__init__.py @@ -3,16 +3,18 @@ from .token import Token from .tts import * __all__ = [ + "AVAILABLE_MODELS_TYPE", "Base", "BaseLanguageCodesEnum", "BaseVoiceModel", - "BaseVoiceModel", "ElevenLabsLanguageCodesEnum", "IdCreatedUpdatedBaseMixin", "LANGUAGE_CODES_ENUM_TYPE", + "LIST_VOICE_MODELS_TYPE", "TTSCreateRequestModel", "TTSCreateResponseModel", "TTSSearchVoiceRequestModel", "Token", + "VoiceModelProvidersEnum", "YandexLanguageCodesEnum", ] diff --git a/src/assistant/lib/models/tts/__init__.py b/src/assistant/lib/models/tts/__init__.py index e26941c..2eabaf4 100644 --- a/src/assistant/lib/models/tts/__init__.py +++ b/src/assistant/lib/models/tts/__init__.py @@ -1,13 +1,16 @@ -from .base import * -from .languages import * +from .models import * +from .voice import * __all__ = [ + "AVAILABLE_MODELS_TYPE", "BaseLanguageCodesEnum", "BaseVoiceModel", "ElevenLabsLanguageCodesEnum", "LANGUAGE_CODES_ENUM_TYPE", + "LIST_VOICE_MODELS_TYPE", "TTSCreateRequestModel", "TTSCreateResponseModel", "TTSSearchVoiceRequestModel", + "VoiceModelProvidersEnum", "YandexLanguageCodesEnum", ] diff --git a/src/assistant/lib/models/tts/base.py b/src/assistant/lib/models/tts/models.py similarity index 53% rename from src/assistant/lib/models/tts/base.py rename to src/assistant/lib/models/tts/models.py index 7be9b6a..712dee3 100644 --- a/src/assistant/lib/models/tts/base.py +++ b/src/assistant/lib/models/tts/models.py @@ -1,14 +1,16 @@ -import typing - import pydantic -import lib.models.tts.languages as models_tts_languages +import lib.models.tts.voice as models_tts_voice +import lib.models.tts.voice.languages as models_tts_languages + +AVAILABLE_MODELS_TYPE = models_tts_voice.YandexVoiceModel | models_tts_voice.ElevenLabsVoiceModel +LIST_VOICE_MODELS_TYPE = models_tts_voice.YandexListVoiceModelsModel | models_tts_voice.ElevenLabsListVoiceModelsModel class TTSCreateRequestModel(pydantic.BaseModel): model_config = pydantic.ConfigDict(use_enum_values=True) - voice_model_name: str + voice_model: AVAILABLE_MODELS_TYPE text: str @@ -16,22 +18,6 @@ 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 diff --git a/src/assistant/lib/models/tts/voice/__init__.py b/src/assistant/lib/models/tts/voice/__init__.py new file mode 100644 index 0000000..f82a8ce --- /dev/null +++ b/src/assistant/lib/models/tts/voice/__init__.py @@ -0,0 +1,17 @@ +from .base import * +from .eleven_labs import * +from .languages import * +from .yandex import * + +__all__ = [ + "BaseLanguageCodesEnum", + "BaseVoiceModel", + "ElevenLabsLanguageCodesEnum", + "ElevenLabsListVoiceModelsModel", + "ElevenLabsVoiceModel", + "LANGUAGE_CODES_ENUM_TYPE", + "VoiceModelProvidersEnum", + "YandexLanguageCodesEnum", + "YandexListVoiceModelsModel", + "YandexVoiceModel", +] diff --git a/src/assistant/lib/models/tts/voice/base.py b/src/assistant/lib/models/tts/voice/base.py new file mode 100644 index 0000000..45c3960 --- /dev/null +++ b/src/assistant/lib/models/tts/voice/base.py @@ -0,0 +1,27 @@ +import enum +import typing + +import pydantic + +import lib.models.tts.voice.languages as models_tts_languages + + +class VoiceModelProvidersEnum(enum.Enum): + YANDEX = "yandex" + ELEVEN_LABS = "eleven_labs" + + +class BaseVoiceModel(pydantic.BaseModel): + voice_id: str + voice_name: str | None = None + languages: list[models_tts_languages.LANGUAGE_CODES_ENUM_TYPE] + provider: VoiceModelProvidersEnum + + @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 diff --git a/src/assistant/lib/models/tts/voice/eleven_labs.py b/src/assistant/lib/models/tts/voice/eleven_labs.py new file mode 100644 index 0000000..80804b4 --- /dev/null +++ b/src/assistant/lib/models/tts/voice/eleven_labs.py @@ -0,0 +1,75 @@ +import typing + +import pydantic + +import lib.models.tts.voice.base as models_tts_base +import lib.models.tts.voice.languages as models_tts_languages + + +class ElevenLabsVoiceModel(models_tts_base.BaseVoiceModel): + model_config = pydantic.ConfigDict(use_enum_values=True) + voice_id: str + voice_name: str | None = None + languages: list[models_tts_languages.LANGUAGE_CODES_ENUM_TYPE] + provider: models_tts_base.VoiceModelProvidersEnum = models_tts_base.VoiceModelProvidersEnum.ELEVEN_LABS + + +class ElevenLabsListVoiceModelsModel(pydantic.BaseModel): + models: list[ElevenLabsVoiceModel] = [ + ElevenLabsVoiceModel( + voice_id="eleven_multilingual_v1", + languages=[ + models_tts_languages.ElevenLabsLanguageCodesEnum.ENGLISH, + models_tts_languages.ElevenLabsLanguageCodesEnum.GERMAN, + models_tts_languages.ElevenLabsLanguageCodesEnum.POLISH, + models_tts_languages.ElevenLabsLanguageCodesEnum.SPANISH, + models_tts_languages.ElevenLabsLanguageCodesEnum.ITALIAN, + models_tts_languages.ElevenLabsLanguageCodesEnum.FRENCH, + models_tts_languages.ElevenLabsLanguageCodesEnum.PORTUGUESE, + models_tts_languages.ElevenLabsLanguageCodesEnum.HINDI, + models_tts_languages.ElevenLabsLanguageCodesEnum.ARABIC, + ], + ), + ElevenLabsVoiceModel( + voice_id="eleven_multilingual_v2", + languages=[ + models_tts_languages.ElevenLabsLanguageCodesEnum.ENGLISH, + models_tts_languages.ElevenLabsLanguageCodesEnum.JAPANESE, + models_tts_languages.ElevenLabsLanguageCodesEnum.CHINESE, + models_tts_languages.ElevenLabsLanguageCodesEnum.GERMAN, + models_tts_languages.ElevenLabsLanguageCodesEnum.HINDI, + models_tts_languages.ElevenLabsLanguageCodesEnum.FRENCH, + models_tts_languages.ElevenLabsLanguageCodesEnum.KOREAN, + models_tts_languages.ElevenLabsLanguageCodesEnum.PORTUGUESE, + models_tts_languages.ElevenLabsLanguageCodesEnum.ITALIAN, + models_tts_languages.ElevenLabsLanguageCodesEnum.SPANISH, + models_tts_languages.ElevenLabsLanguageCodesEnum.INDONESIAN, + models_tts_languages.ElevenLabsLanguageCodesEnum.DUTCH, + models_tts_languages.ElevenLabsLanguageCodesEnum.TURKISH, + models_tts_languages.ElevenLabsLanguageCodesEnum.FILIPINO, + models_tts_languages.ElevenLabsLanguageCodesEnum.POLISH, + models_tts_languages.ElevenLabsLanguageCodesEnum.SWEDISH, + models_tts_languages.ElevenLabsLanguageCodesEnum.BULGARIAN, + models_tts_languages.ElevenLabsLanguageCodesEnum.ROMANIAN, + models_tts_languages.ElevenLabsLanguageCodesEnum.ARABIC, + models_tts_languages.ElevenLabsLanguageCodesEnum.CZECH, + models_tts_languages.ElevenLabsLanguageCodesEnum.GREEK, + models_tts_languages.ElevenLabsLanguageCodesEnum.FINNISH, + models_tts_languages.ElevenLabsLanguageCodesEnum.CROATIAN, + models_tts_languages.ElevenLabsLanguageCodesEnum.MALAY, + models_tts_languages.ElevenLabsLanguageCodesEnum.SLOVAK, + models_tts_languages.ElevenLabsLanguageCodesEnum.DANISH, + models_tts_languages.ElevenLabsLanguageCodesEnum.TAMIL, + models_tts_languages.ElevenLabsLanguageCodesEnum.UKRAINIAN, + ], + ), + ElevenLabsVoiceModel( + voice_id="eleven_multilingual_v2", + languages=[models_tts_languages.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/models/tts/languages.py b/src/assistant/lib/models/tts/voice/languages.py similarity index 100% rename from src/assistant/lib/models/tts/languages.py rename to src/assistant/lib/models/tts/voice/languages.py diff --git a/src/assistant/lib/models/tts/voice/yandex.py b/src/assistant/lib/models/tts/voice/yandex.py new file mode 100644 index 0000000..476a1f0 --- /dev/null +++ b/src/assistant/lib/models/tts/voice/yandex.py @@ -0,0 +1,97 @@ +import typing + +import pydantic + +import lib.models.tts.voice.base as models_tts_base +import lib.models.tts.voice.languages as models_tts_languages + + +class YandexVoiceModel(models_tts_base.BaseVoiceModel): + voice_id: str + voice_name: str | None = None + languages: list[models_tts_languages.LANGUAGE_CODES_ENUM_TYPE] + provider: models_tts_base.VoiceModelProvidersEnum = models_tts_base.VoiceModelProvidersEnum.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 YandexListVoiceModelsModel(pydantic.BaseModel): + models: list[YandexVoiceModel] = [ + YandexVoiceModel( + voice_id="ermil", role="neutral", languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="ermil", role="good", languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="alena", role="neutral", languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="alena", role="good", languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="jane", role="neutral", languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="jane", role="good", languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="jane", role="evil", languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="omazh", role="neutral", languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="omazh", role="evil", languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="zahar", role="neutral", languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="zahar", role="good", languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="filipp", role=None, languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="madirus", role=None, languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel(voice_id="dasha", role=None, languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="julia", role=None, languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="lera", role=None, languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel( + voice_id="marina", role=None, languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="alexander", role=None, languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel( + voice_id="kirill", role=None, languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN] + ), + YandexVoiceModel(voice_id="anton", role=None, languages=[models_tts_languages.YandexLanguageCodesEnum.RUSSIAN]), + YandexVoiceModel(voice_id="john", role=None, languages=[models_tts_languages.YandexLanguageCodesEnum.ENGLISH]), + YandexVoiceModel(voice_id="amira", role=None, languages=[models_tts_languages.YandexLanguageCodesEnum.KAZAKH]), + YandexVoiceModel(voice_id="madi", role=None, languages=[models_tts_languages.YandexLanguageCodesEnum.KAZAKH]), + YandexVoiceModel(voice_id="lea", role=None, languages=[models_tts_languages.YandexLanguageCodesEnum.GERMAN]), + YandexVoiceModel( + voice_id="naomi", role="modern", languages=[models_tts_languages.YandexLanguageCodesEnum.HEBREW] + ), + YandexVoiceModel( + voice_id="naomi", role="classic", languages=[models_tts_languages.YandexLanguageCodesEnum.HEBREW] + ), + YandexVoiceModel(voice_id="nigora", role=None, languages=[models_tts_languages.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/models/__init__.py b/src/assistant/lib/tts/models/__init__.py index fd5289e..1064aa8 100644 --- a/src/assistant/lib/tts/models/__init__.py +++ b/src/assistant/lib/tts/models/__init__.py @@ -1,17 +1,5 @@ -from .repository import * -from .service import * -from .utils import * -from .voice import * +from .protocols import * __all__ = [ - "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/protocols.py b/src/assistant/lib/tts/models/protocols.py new file mode 100644 index 0000000..5774c08 --- /dev/null +++ b/src/assistant/lib/tts/models/protocols.py @@ -0,0 +1,14 @@ +import typing + +import lib.models as models + + +class TTSRepositoryProtocol(typing.Protocol): + def get_audio_as_bytes(self, request: models.TTSCreateRequestModel) -> 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) -> models.LIST_VOICE_MODELS_TYPE: + ... diff --git a/src/assistant/lib/tts/models/repository.py b/src/assistant/lib/tts/models/repository.py deleted file mode 100644 index 142d7c5..0000000 --- a/src/assistant/lib/tts/models/repository.py +++ /dev/null @@ -1,17 +0,0 @@ -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 deleted file mode 100644 index 694770e..0000000 --- a/src/assistant/lib/tts/models/service.py +++ /dev/null @@ -1,9 +0,0 @@ -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 deleted file mode 100644 index 1a653b5..0000000 --- a/src/assistant/lib/tts/models/utils.py +++ /dev/null @@ -1,4 +0,0 @@ -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 deleted file mode 100644 index 7ca63ac..0000000 --- a/src/assistant/lib/tts/models/voice/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from .eleven_labs import * -from .yandex import * - -__all__ = [ - "ElevenLabsListVoiceModelsModel", - "ElevenLabsVoiceModel", - "YandexListVoiceModelsModel", - "YandexVoiceModel", -] diff --git a/src/assistant/lib/tts/models/voice/eleven_labs.py b/src/assistant/lib/tts/models/voice/eleven_labs.py deleted file mode 100644 index 1e989c1..0000000 --- a/src/assistant/lib/tts/models/voice/eleven_labs.py +++ /dev/null @@ -1,73 +0,0 @@ -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 deleted file mode 100644 index 099acde..0000000 --- a/src/assistant/lib/tts/models/voice/yandex.py +++ /dev/null @@ -1,60 +0,0 @@ -import typing - -import pydantic - -import lib.models as models - - -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 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/base.py b/src/assistant/lib/tts/repositories/base.py index 238b873..cabbfc5 100644 --- a/src/assistant/lib/tts/repositories/base.py +++ b/src/assistant/lib/tts/repositories/base.py @@ -1,7 +1,6 @@ import abc import lib.models as models -import lib.tts.models as tts_models class HttpClient: # Mocked class todo remove and use real http client from lib.clients.http_client @@ -15,11 +14,11 @@ class TTSBaseRepository(abc.ABC): @property @abc.abstractmethod - def voice_models(self) -> tts_models.LIST_VOICE_MODELS_TYPE: + def voice_models(self) -> models.LIST_VOICE_MODELS_TYPE: ... @abc.abstractmethod - def get_audio_as_bytes_from_text(self, text: str) -> models.TTSCreateResponseModel: + def get_audio_as_bytes(self, request: models.TTSCreateRequestModel) -> models.TTSCreateResponseModel: raise NotImplementedError def get_voice_model_by_name(self, voice_model_name: str) -> models.BaseVoiceModel | None: @@ -34,7 +33,7 @@ class TTSBaseRepository(abc.ABC): def get_list_voice_models_by_fields( self, fields: models.TTSSearchVoiceRequestModel - ) -> list[tts_models.VOICE_MODELS_TYPE]: + ) -> list[models.AVAILABLE_MODELS_TYPE]: """ Search voice model by fields :param fields: Any fields from TTSSearchVoiceRequestModel @@ -43,7 +42,6 @@ class TTSBaseRepository(abc.ABC): fields_dump = fields.model_dump(exclude_none=True) voice_models_response = [] for voice_model in self.voice_models.models: - voice_model: tts_models.VOICE_MODELS_TYPE for field, field_value in fields_dump.items(): if field == "languages": # language is a list language_names: set[str] = {item.name for item in field_value} diff --git a/src/assistant/lib/tts/services.py b/src/assistant/lib/tts/services.py index df8a00b..1d6a337 100644 --- a/src/assistant/lib/tts/services.py +++ b/src/assistant/lib/tts/services.py @@ -7,32 +7,28 @@ class TTSService: def __init__( self, settings: app_settings.Settings, - tts_repositories: list[tts_models.TTSRepositoryProtocol], + repositories: dict[models.VoiceModelProvidersEnum, tts_models.TTSRepositoryProtocol], ): self.settings = settings - self.tts_repositories = tts_repositories + self.repositories = repositories - def get_audio_as_bytes_from_text(self, tts_request: models.TTSCreateRequestModel) -> models.TTSCreateResponseModel: - for repository in self.tts_repositories: - voice_model = repository.get_voice_model_by_name(tts_request.voice_model_name) - if voice_model: - audio_response = repository.get_audio_as_bytes_from_text(tts_request.text) - break - else: - raise ValueError(f"Voice model {tts_request.voice_model_name} not found") + def get_audio_as_bytes(self, request: models.TTSCreateRequestModel) -> models.TTSCreateResponseModel: + model = request.voice_model + repository = self.repositories[model.provider] + audio_response = repository.get_audio_as_bytes(request) return audio_response def get_voice_model_by_name(self, voice_model_name: str) -> models.BaseVoiceModel | None: - for repository in self.tts_repositories: + for repository in self.repositories.values(): voice_model = repository.get_voice_model_by_name(voice_model_name) if voice_model: return voice_model def get_list_voice_models_by_fields( self, fields: models.TTSSearchVoiceRequestModel - ) -> list[tts_models.VOICE_MODELS_TYPE]: - response_models: list[tts_models.VOICE_MODELS_TYPE] = [] - for repository in self.tts_repositories: + ) -> list[models.AVAILABLE_MODELS_TYPE]: + response_models: list[models.AVAILABLE_MODELS_TYPE] = [] + for repository in self.repositories.values(): voice_models = repository.get_voice_models_by_fields(fields) if voice_models.models: response_models.extend(voice_models.models) From 395ed7057dc10c0f28f5d6ae39bd019d636616e1 Mon Sep 17 00:00:00 2001 From: Artem Litvinov Date: Thu, 12 Oct 2023 15:21:29 +0100 Subject: [PATCH 09/12] fix: orjson to 3.9.7 (github can't find 3.9.8) --- src/assistant/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assistant/pyproject.toml b/src/assistant/pyproject.toml index 2fd27e0..a3a4a2c 100644 --- a/src/assistant/pyproject.toml +++ b/src/assistant/pyproject.toml @@ -25,7 +25,7 @@ asyncpg = "^0.28.0" fastapi = "0.103.1" greenlet = "^2.0.2" httpx = "^0.25.0" -orjson = "^3.9.7" +orjson = "3.9.7" psycopg2 = "^2.9.7" pydantic = {extras = ["email"], version = "^2.3.0"} pydantic-settings = "^2.0.3" From cd8d13f6b70a1c141bd4e7f91cc715d796e00273 Mon Sep 17 00:00:00 2001 From: Artem Litvinov Date: Thu, 12 Oct 2023 15:24:38 +0100 Subject: [PATCH 10/12] fix: poetry.lock --- src/assistant/poetry.lock | 86 ++++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 20 deletions(-) diff --git a/src/assistant/poetry.lock b/src/assistant/poetry.lock index 055d58f..259f36a 100644 --- a/src/assistant/poetry.lock +++ b/src/assistant/poetry.lock @@ -1041,25 +1041,71 @@ wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1 [[package]] name = "orjson" -version = "3.9.8" +version = "3.9.7" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "orjson-3.9.8-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:823525bfb27b804b492acc59a45dc0973ea629d97557eac81dde7b34b5267611"}, - {file = "orjson-3.9.8-cp310-none-win32.whl", hash = "sha256:2bcc9dc53f9e1d679515349bf299ed5e75310146c755d2ba227a7e37851ab3fb"}, - {file = "orjson-3.9.8-cp310-none-win_amd64.whl", hash = "sha256:423774c85e73054acfef10fc3328f35c8d3e0193a7247d47308ebfccde70695d"}, - {file = "orjson-3.9.8-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:8a1c92f467f5fd0f8fb79273006b563364b1e45667b3760423498348dc2e22fa"}, - {file = "orjson-3.9.8-cp311-none-win32.whl", hash = "sha256:a119c73520192c2882d0549151b9cdd65e0bb5396bedf8951ba5f70d6a873879"}, - {file = "orjson-3.9.8-cp311-none-win_amd64.whl", hash = "sha256:764306f6370e6c76cbbf3139dd9b05be9c4481ee0b15966bd1907827a5777216"}, - {file = "orjson-3.9.8-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:af8e6185516ce0c93d6ce1f4105918504da629c631fd969686f32a1be3ed3c9b"}, - {file = "orjson-3.9.8-cp312-none-win_amd64.whl", hash = "sha256:5c818f19315251d68954c529f5d8322053f1c35b500b47d008e968bf2d32ed97"}, - {file = "orjson-3.9.8-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e6a267c0fc64fc4d0b8fb146e1a060a40f570441a9390ec4bc6de0b5fda148cd"}, - {file = "orjson-3.9.8-cp38-none-win32.whl", hash = "sha256:9df23493a72f073b2ab1005e628a963248dc577a2816e9c82caf09ff74908414"}, - {file = "orjson-3.9.8-cp38-none-win_amd64.whl", hash = "sha256:34eec476141a043d478651d1efbf218162cdd57add24dfa659ac89e1a001477a"}, - {file = "orjson-3.9.8-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c9ae634b8a55539c3d5a53813552325733ab3da3601feef8e99f91cef634f3c4"}, - {file = "orjson-3.9.8-cp39-none-win32.whl", hash = "sha256:ca4f3e15517bdcdb573dfe6c97d4171247ce50ec82e3a7b708941b53d5f4bc29"}, - {file = "orjson-3.9.8-cp39-none-win_amd64.whl", hash = "sha256:52c0480d5be12697b10b4d748b86acd4999f47e1d8e44e49486d0a550f30fcba"}, + {file = "orjson-3.9.7-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:b6df858e37c321cefbf27fe7ece30a950bcc3a75618a804a0dcef7ed9dd9c92d"}, + {file = "orjson-3.9.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5198633137780d78b86bb54dafaaa9baea698b4f059456cd4554ab7009619221"}, + {file = "orjson-3.9.7-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e736815b30f7e3c9044ec06a98ee59e217a833227e10eb157f44071faddd7c5"}, + {file = "orjson-3.9.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a19e4074bc98793458b4b3ba35a9a1d132179345e60e152a1bb48c538ab863c4"}, + {file = "orjson-3.9.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80acafe396ab689a326ab0d80f8cc61dec0dd2c5dca5b4b3825e7b1e0132c101"}, + {file = "orjson-3.9.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:355efdbbf0cecc3bd9b12589b8f8e9f03c813a115efa53f8dc2a523bfdb01334"}, + {file = "orjson-3.9.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3aab72d2cef7f1dd6104c89b0b4d6b416b0db5ca87cc2fac5f79c5601f549cc2"}, + {file = "orjson-3.9.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:36b1df2e4095368ee388190687cb1b8557c67bc38400a942a1a77713580b50ae"}, + {file = "orjson-3.9.7-cp310-none-win32.whl", hash = "sha256:e94b7b31aa0d65f5b7c72dd8f8227dbd3e30354b99e7a9af096d967a77f2a580"}, + {file = "orjson-3.9.7-cp310-none-win_amd64.whl", hash = "sha256:82720ab0cf5bb436bbd97a319ac529aee06077ff7e61cab57cee04a596c4f9b4"}, + {file = "orjson-3.9.7-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1f8b47650f90e298b78ecf4df003f66f54acdba6a0f763cc4df1eab048fe3738"}, + {file = "orjson-3.9.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f738fee63eb263530efd4d2e9c76316c1f47b3bbf38c1bf45ae9625feed0395e"}, + {file = "orjson-3.9.7-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:38e34c3a21ed41a7dbd5349e24c3725be5416641fdeedf8f56fcbab6d981c900"}, + {file = "orjson-3.9.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:21a3344163be3b2c7e22cef14fa5abe957a892b2ea0525ee86ad8186921b6cf0"}, + {file = "orjson-3.9.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23be6b22aab83f440b62a6f5975bcabeecb672bc627face6a83bc7aeb495dc7e"}, + {file = "orjson-3.9.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5205ec0dfab1887dd383597012199f5175035e782cdb013c542187d280ca443"}, + {file = "orjson-3.9.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8769806ea0b45d7bf75cad253fba9ac6700b7050ebb19337ff6b4e9060f963fa"}, + {file = "orjson-3.9.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f9e01239abea2f52a429fe9d95c96df95f078f0172489d691b4a848ace54a476"}, + {file = "orjson-3.9.7-cp311-none-win32.whl", hash = "sha256:8bdb6c911dae5fbf110fe4f5cba578437526334df381b3554b6ab7f626e5eeca"}, + {file = "orjson-3.9.7-cp311-none-win_amd64.whl", hash = "sha256:9d62c583b5110e6a5cf5169ab616aa4ec71f2c0c30f833306f9e378cf51b6c86"}, + {file = "orjson-3.9.7-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:1c3cee5c23979deb8d1b82dc4cc49be59cccc0547999dbe9adb434bb7af11cf7"}, + {file = "orjson-3.9.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a347d7b43cb609e780ff8d7b3107d4bcb5b6fd09c2702aa7bdf52f15ed09fa09"}, + {file = "orjson-3.9.7-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:154fd67216c2ca38a2edb4089584504fbb6c0694b518b9020ad35ecc97252bb9"}, + {file = "orjson-3.9.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ea3e63e61b4b0beeb08508458bdff2daca7a321468d3c4b320a758a2f554d31"}, + {file = "orjson-3.9.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1eb0b0b2476f357eb2975ff040ef23978137aa674cd86204cfd15d2d17318588"}, + {file = "orjson-3.9.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b9a20a03576c6b7022926f614ac5a6b0914486825eac89196adf3267c6489d"}, + {file = "orjson-3.9.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:915e22c93e7b7b636240c5a79da5f6e4e84988d699656c8e27f2ac4c95b8dcc0"}, + {file = "orjson-3.9.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f26fb3e8e3e2ee405c947ff44a3e384e8fa1843bc35830fe6f3d9a95a1147b6e"}, + {file = "orjson-3.9.7-cp312-none-win_amd64.whl", hash = "sha256:d8692948cada6ee21f33db5e23460f71c8010d6dfcfe293c9b96737600a7df78"}, + {file = "orjson-3.9.7-cp37-cp37m-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:7bab596678d29ad969a524823c4e828929a90c09e91cc438e0ad79b37ce41166"}, + {file = "orjson-3.9.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63ef3d371ea0b7239ace284cab9cd00d9c92b73119a7c274b437adb09bda35e6"}, + {file = "orjson-3.9.7-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f8fcf696bbbc584c0c7ed4adb92fd2ad7d153a50258842787bc1524e50d7081"}, + {file = "orjson-3.9.7-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:90fe73a1f0321265126cbba13677dcceb367d926c7a65807bd80916af4c17047"}, + {file = "orjson-3.9.7-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:45a47f41b6c3beeb31ac5cf0ff7524987cfcce0a10c43156eb3ee8d92d92bf22"}, + {file = "orjson-3.9.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a2937f528c84e64be20cb80e70cea76a6dfb74b628a04dab130679d4454395c"}, + {file = "orjson-3.9.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b4fb306c96e04c5863d52ba8d65137917a3d999059c11e659eba7b75a69167bd"}, + {file = "orjson-3.9.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:410aa9d34ad1089898f3db461b7b744d0efcf9252a9415bbdf23540d4f67589f"}, + {file = "orjson-3.9.7-cp37-none-win32.whl", hash = "sha256:26ffb398de58247ff7bde895fe30817a036f967b0ad0e1cf2b54bda5f8dcfdd9"}, + {file = "orjson-3.9.7-cp37-none-win_amd64.whl", hash = "sha256:bcb9a60ed2101af2af450318cd89c6b8313e9f8df4e8fb12b657b2e97227cf08"}, + {file = "orjson-3.9.7-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:5da9032dac184b2ae2da4bce423edff7db34bfd936ebd7d4207ea45840f03905"}, + {file = "orjson-3.9.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7951af8f2998045c656ba8062e8edf5e83fd82b912534ab1de1345de08a41d2b"}, + {file = "orjson-3.9.7-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b8e59650292aa3a8ea78073fc84184538783966528e442a1b9ed653aa282edcf"}, + {file = "orjson-3.9.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9274ba499e7dfb8a651ee876d80386b481336d3868cba29af839370514e4dce0"}, + {file = "orjson-3.9.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca1706e8b8b565e934c142db6a9592e6401dc430e4b067a97781a997070c5378"}, + {file = "orjson-3.9.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83cc275cf6dcb1a248e1876cdefd3f9b5f01063854acdfd687ec360cd3c9712a"}, + {file = "orjson-3.9.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:11c10f31f2c2056585f89d8229a56013bc2fe5de51e095ebc71868d070a8dd81"}, + {file = "orjson-3.9.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cf334ce1d2fadd1bf3e5e9bf15e58e0c42b26eb6590875ce65bd877d917a58aa"}, + {file = "orjson-3.9.7-cp38-none-win32.whl", hash = "sha256:76a0fc023910d8a8ab64daed8d31d608446d2d77c6474b616b34537aa7b79c7f"}, + {file = "orjson-3.9.7-cp38-none-win_amd64.whl", hash = "sha256:7a34a199d89d82d1897fd4a47820eb50947eec9cda5fd73f4578ff692a912f89"}, + {file = "orjson-3.9.7-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e7e7f44e091b93eb39db88bb0cb765db09b7a7f64aea2f35e7d86cbf47046c65"}, + {file = "orjson-3.9.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01d647b2a9c45a23a84c3e70e19d120011cba5f56131d185c1b78685457320bb"}, + {file = "orjson-3.9.7-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0eb850a87e900a9c484150c414e21af53a6125a13f6e378cf4cc11ae86c8f9c5"}, + {file = "orjson-3.9.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f4b0042d8388ac85b8330b65406c84c3229420a05068445c13ca28cc222f1f7"}, + {file = "orjson-3.9.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd3e7aae977c723cc1dbb82f97babdb5e5fbce109630fbabb2ea5053523c89d3"}, + {file = "orjson-3.9.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c616b796358a70b1f675a24628e4823b67d9e376df2703e893da58247458956"}, + {file = "orjson-3.9.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c3ba725cf5cf87d2d2d988d39c6a2a8b6fc983d78ff71bc728b0be54c869c884"}, + {file = "orjson-3.9.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4891d4c934f88b6c29b56395dfc7014ebf7e10b9e22ffd9877784e16c6b2064f"}, + {file = "orjson-3.9.7-cp39-none-win32.whl", hash = "sha256:14d3fb6cd1040a4a4a530b28e8085131ed94ebc90d72793c59a713de34b60838"}, + {file = "orjson-3.9.7-cp39-none-win_amd64.whl", hash = "sha256:9ef82157bbcecd75d6296d5d8b2d792242afcd064eb1ac573f8847b52e58f677"}, + {file = "orjson-3.9.7.tar.gz", hash = "sha256:85e39198f78e2f7e054d296395f6c96f5e02892337746ef5b6a1bf3ed5910142"}, ] [[package]] @@ -1425,13 +1471,13 @@ pytest = ">=4.6" [[package]] name = "pyright" -version = "1.1.330.post0" +version = "1.1.331" description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" files = [ - {file = "pyright-1.1.330.post0-py3-none-any.whl", hash = "sha256:2e9e0878298685b66485b340a0aaa16342129eb03ff9ed0e3c1ab66b8bfbe914"}, - {file = "pyright-1.1.330.post0.tar.gz", hash = "sha256:8e5b09cc5d1cfa0bcbf8824b0316d21c43fe229da7cef0a09cd12fcf6cb3eedd"}, + {file = "pyright-1.1.331-py3-none-any.whl", hash = "sha256:d200a01794e7f2a04d5042a6c3abee36ce92780287d3037edfc3604d45488f0e"}, + {file = "pyright-1.1.331.tar.gz", hash = "sha256:c3e7b86154cac86c3bd61ea0f963143d001c201e246825aaabdddfcce5d04293"}, ] [package.dependencies] @@ -2005,4 +2051,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "157772e2b31120df8d850525c30b56685e3db6c5318f6fba677c6cfcd1f0e467" +content-hash = "64e70d8e6e21863567fed017ba25f061ab0af9b99b6281b50ff6eceb7bc4cb7b" From 453d3ce38e1509bc80a2543235e7cfde5be5522f Mon Sep 17 00:00:00 2001 From: Artem Litvinov Date: Thu, 12 Oct 2023 15:41:16 +0100 Subject: [PATCH 11/12] fix: make lint-fix --- src/assistant/lib/app/split_settings/__init__.py | 1 - src/assistant/pyproject.toml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/assistant/lib/app/split_settings/__init__.py b/src/assistant/lib/app/split_settings/__init__.py index 90343d5..3aa53b4 100644 --- a/src/assistant/lib/app/split_settings/__init__.py +++ b/src/assistant/lib/app/split_settings/__init__.py @@ -7,7 +7,6 @@ from .project import * from .proxy import * from .voice import * - __all__ = [ "ApiSettings", "AppSettings", diff --git a/src/assistant/pyproject.toml b/src/assistant/pyproject.toml index b20e9e7..fe80947 100644 --- a/src/assistant/pyproject.toml +++ b/src/assistant/pyproject.toml @@ -26,8 +26,8 @@ dill = "^0.3.7" fastapi = "0.103.1" greenlet = "^2.0.2" httpx = "^0.25.0" -orjson = "3.9.7" openai = "^0.28.1" +orjson = "3.9.7" psycopg2-binary = "^2.9.9" pydantic = {extras = ["email"], version = "^2.3.0"} pydantic-settings = "^2.0.3" From 3129d52a86b6dd7479710d94800aca0311888b4e Mon Sep 17 00:00:00 2001 From: Artem Litvinov Date: Thu, 12 Oct 2023 16:14:36 +0100 Subject: [PATCH 12/12] fix: added type ignore --- src/assistant/lib/clients/http_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assistant/lib/clients/http_client.py b/src/assistant/lib/clients/http_client.py index efc6a53..532759d 100644 --- a/src/assistant/lib/clients/http_client.py +++ b/src/assistant/lib/clients/http_client.py @@ -17,7 +17,7 @@ class AsyncHttpClient(httpx.AsyncClient): self.proxies = self.__get_proxies_from_settings() self.client_params = client_params - super().__init__(base_url=self.base_url, proxies=self.proxies, **client_params) + super().__init__(base_url=self.base_url, proxies=self.proxies, **client_params) # type: ignore[reportGeneralTypeIssues] def __get_proxies_from_settings(self) -> dict[str, str] | None: if not self.proxy_settings.enable: