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/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: diff --git a/src/assistant/lib/models/__init__.py b/src/assistant/lib/models/__init__.py index 8641d86..70993c4 100644 --- a/src/assistant/lib/models/__init__.py +++ b/src/assistant/lib/models/__init__.py @@ -1,4 +1,20 @@ from .orm import Base, IdCreatedUpdatedBaseMixin from .token import Token +from .tts import * -__all__ = ["Base", "IdCreatedUpdatedBaseMixin", "Token"] +__all__ = [ + "AVAILABLE_MODELS_TYPE", + "Base", + "BaseLanguageCodesEnum", + "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 new file mode 100644 index 0000000..2eabaf4 --- /dev/null +++ b/src/assistant/lib/models/tts/__init__.py @@ -0,0 +1,16 @@ +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/models.py b/src/assistant/lib/models/tts/models.py new file mode 100644 index 0000000..712dee3 --- /dev/null +++ b/src/assistant/lib/models/tts/models.py @@ -0,0 +1,31 @@ +import pydantic + +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: AVAILABLE_MODELS_TYPE + text: str + + +class TTSCreateResponseModel(pydantic.BaseModel): + audio_content: bytes + + +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/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/voice/languages.py b/src/assistant/lib/models/tts/voice/languages.py new file mode 100644 index 0000000..08f5db8 --- /dev/null +++ b/src/assistant/lib/models/tts/voice/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/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/__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..1064aa8 --- /dev/null +++ b/src/assistant/lib/tts/models/__init__.py @@ -0,0 +1,5 @@ +from .protocols import * + +__all__ = [ + "TTSRepositoryProtocol", +] 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/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", +] diff --git a/src/assistant/lib/tts/repositories/base.py b/src/assistant/lib/tts/repositories/base.py new file mode 100644 index 0000000..cabbfc5 --- /dev/null +++ b/src/assistant/lib/tts/repositories/base.py @@ -0,0 +1,57 @@ +import abc + +import lib.models as 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) -> models.LIST_VOICE_MODELS_TYPE: + ... + + @abc.abstractmethod + 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: + """ + 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[models.AVAILABLE_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: + 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] diff --git a/src/assistant/lib/tts/services.py b/src/assistant/lib/tts/services.py new file mode 100644 index 0000000..1d6a337 --- /dev/null +++ b/src/assistant/lib/tts/services.py @@ -0,0 +1,35 @@ +import lib.app.settings as app_settings +import lib.models as models +import lib.tts.models as tts_models + + +class TTSService: + def __init__( + self, + settings: app_settings.Settings, + repositories: dict[models.VoiceModelProvidersEnum, tts_models.TTSRepositoryProtocol], + ): + self.settings = settings + self.repositories = repositories + + 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.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[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) + return response_models 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" diff --git a/src/assistant/pyproject.toml b/src/assistant/pyproject.toml index 0edf988..fe80947 100644 --- a/src/assistant/pyproject.toml +++ b/src/assistant/pyproject.toml @@ -27,7 +27,7 @@ fastapi = "0.103.1" greenlet = "^2.0.2" httpx = "^0.25.0" openai = "^0.28.1" -orjson = "^3.9.7" +orjson = "3.9.7" psycopg2-binary = "^2.9.9" pydantic = {extras = ["email"], version = "^2.3.0"} pydantic-settings = "^2.0.3"