diff --git a/poetry.lock b/poetry.lock index fed8992..e15afb0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3083,13 +3083,13 @@ files = [ [[package]] name = "zipp" -version = "3.20.1" +version = "3.20.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.20.1-py3-none-any.whl", hash = "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064"}, - {file = "zipp-3.20.1.tar.gz", hash = "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b"}, + {file = "zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350"}, + {file = "zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29"}, ] [package.extras] diff --git a/src/hume/core/http_client.py b/src/hume/core/http_client.py index 361c017..b07401b 100644 --- a/src/hume/core/http_client.py +++ b/src/hume/core/http_client.py @@ -1,3 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + import asyncio import email.utils import json @@ -88,7 +90,8 @@ def _should_retry(response: httpx.Response) -> bool: def remove_omit_from_dict( - original: typing.Dict[str, typing.Optional[typing.Any]], omit: typing.Optional[typing.Any] + original: typing.Dict[str, typing.Optional[typing.Any]], + omit: typing.Optional[typing.Any], ) -> typing.Dict[str, typing.Any]: if omit is None: return original @@ -140,6 +143,7 @@ def get_request_body( # If both data and json are None, we send json data in the event extra properties are specified json_body = maybe_filter_request_body(json, request_options, omit) + # If you have an empty JSON body, you should just send None return (json_body if json_body != {} else None), data_body if data_body != {} else None diff --git a/src/hume/core/pydantic_utilities.py b/src/hume/core/pydantic_utilities.py index 0bc7687..a0875ac 100644 --- a/src/hume/core/pydantic_utilities.py +++ b/src/hume/core/pydantic_utilities.py @@ -79,15 +79,39 @@ def to_jsonable_with_fallback( class UniversalBaseModel(pydantic.BaseModel): if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict( + # Allow fields begining with `model_` to be used in the model protected_namespaces=(), - json_encoders={dt.datetime: serialize_datetime}, ) # type: ignore # Pydantic v2 + + @pydantic.model_serializer(mode="wrap", when_used="json") # type: ignore # Pydantic v2 + def serialize_model(self, handler: pydantic.SerializerFunctionWrapHandler) -> typing.Any: # type: ignore # Pydantic v2 + serialized = handler(self) + data = {k: serialize_datetime(v) if isinstance(v, dt.datetime) else v for k, v in serialized.items()} + return data + else: class Config: smart_union = True json_encoders = {dt.datetime: serialize_datetime} + @classmethod + def model_construct( + cls: type[Model], _fields_set: typing.Optional[typing.Set[str]] = None, **values: typing.Any + ) -> Model: + dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read") + return cls.construct(_fields_set, **dealiased_object) + + @classmethod + def construct( + cls: type[Model], _fields_set: typing.Optional[typing.Set[str]] = None, **values: typing.Any + ) -> Model: + dealiased_object = convert_and_respect_annotation_metadata(object_=values, annotation=cls, direction="read") + if IS_PYDANTIC_V2: + return super().model_construct(_fields_set, **dealiased_object) # type: ignore # Pydantic v2 + else: + return super().construct(_fields_set, **dealiased_object) + def json(self, **kwargs: typing.Any) -> str: kwargs_with_defaults: typing.Any = { "by_alias": True, @@ -104,34 +128,68 @@ def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]: Override the default dict method to `exclude_unset` by default. This function patches `exclude_unset` to work include fields within non-None default values. """ - _fields_set = self.__fields_set__ + # Note: the logic here is multi-plexed given the levers exposed in Pydantic V1 vs V2 + # Pydantic V1's .dict can be extremely slow, so we do not want to call it twice. + # + # We'd ideally do the same for Pydantic V2, but it shells out to a library to serialize models + # that we have less control over, and this is less intrusive than custom serializers for now. + if IS_PYDANTIC_V2: + kwargs_with_defaults_exclude_unset: typing.Any = { + **kwargs, + "by_alias": True, + "exclude_unset": True, + "exclude_none": False, + } + kwargs_with_defaults_exclude_none: typing.Any = { + **kwargs, + "by_alias": True, + "exclude_none": True, + "exclude_unset": False, + } + dict_dump = deep_union_pydantic_dicts( + super().model_dump(**kwargs_with_defaults_exclude_unset), # type: ignore # Pydantic v2 + super().model_dump(**kwargs_with_defaults_exclude_none), # type: ignore # Pydantic v2 + ) - fields = _get_model_fields(self.__class__) - for name, field in fields.items(): - if name not in _fields_set: - default = _get_field_default(field) + else: + _fields_set = self.__fields_set__ - # If the default values are non-null act like they've been set - # This effectively allows exclude_unset to work like exclude_none where - # the latter passes through intentionally set none values. - if default != None: - _fields_set.add(name) + fields = _get_model_fields(self.__class__) + for name, field in fields.items(): + if name not in _fields_set: + default = _get_field_default(field) - kwargs_with_defaults_exclude_unset: typing.Any = { - "by_alias": True, - "exclude_unset": True, - "include": _fields_set, - **kwargs, - } + # If the default values are non-null act like they've been set + # This effectively allows exclude_unset to work like exclude_none where + # the latter passes through intentionally set none values. + if default != None: + _fields_set.add(name) - if IS_PYDANTIC_V2: - dict_dump = super().model_dump(**kwargs_with_defaults_exclude_unset) # type: ignore # Pydantic v2 - else: - dict_dump = super().dict(**kwargs_with_defaults_exclude_unset) + kwargs_with_defaults_exclude_unset_include_fields: typing.Any = { + "by_alias": True, + "exclude_unset": True, + "include": _fields_set, + **kwargs, + } + + dict_dump = super().dict(**kwargs_with_defaults_exclude_unset_include_fields) return convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write") +def deep_union_pydantic_dicts( + source: typing.Dict[str, typing.Any], destination: typing.Dict[str, typing.Any] +) -> typing.Dict[str, typing.Any]: + for key, value in source.items(): + if isinstance(value, dict): + node = destination.setdefault(key, {}) + deep_union_pydantic_dicts(value, node) + else: + destination[key] = value + + return destination + + if IS_PYDANTIC_V2: class V2RootModel(UniversalBaseModel, pydantic.RootModel): # type: ignore # Pydantic v2 @@ -156,11 +214,11 @@ def encode_by_type(o: typing.Any) -> typing.Any: return encoder(o) -def update_forward_refs(model: typing.Type["Model"]) -> None: +def update_forward_refs(model: typing.Type["Model"], **localns: typing.Any) -> None: if IS_PYDANTIC_V2: model.model_rebuild(raise_errors=False) # type: ignore # Pydantic v2 else: - model.update_forward_refs() + model.update_forward_refs(**localns) # Mirrors Pydantic's internal typing diff --git a/tests/empathic_voice/test_configs.py b/tests/empathic_voice/test_configs.py index 2ec6d70..8717ad4 100644 --- a/tests/empathic_voice/test_configs.py +++ b/tests/empathic_voice/test_configs.py @@ -1,18 +1,15 @@ # This file was auto-generated by Fern from our API Definition. +from hume import HumeClient +from hume import AsyncHumeClient import typing - -from hume.client import AsyncHumeClient, HumeClient -from hume.empathic_voice import ( - PostedEllmModel, - PostedEventMessageSpec, - PostedEventMessageSpecs, - PostedLanguageModel, - PostedPromptSpec, - PostedVoice, -) - from ..utilities import validate_response +from hume.empathic_voice import PostedConfigPromptSpec +from hume.empathic_voice import PostedVoice +from hume.empathic_voice import PostedLanguageModel +from hume.empathic_voice import PostedEventMessageSpecs +from hume.empathic_voice import PostedEventMessageSpec +from hume.empathic_voice import PostedEllmModel async def test_list_configs(client: HumeClient, async_client: AsyncHumeClient) -> None: @@ -28,6 +25,7 @@ async def test_list_configs(client: HumeClient, async_client: AsyncHumeClient) - "name": "Weather Assistant Config", "created_on": 1715267200693, "modified_on": 1715267200693, + "evi_version": "2", "prompt": { "id": "af699d45-2985-42cc-91b9-af9e5da3bac5", "version": 0, @@ -38,7 +36,20 @@ async def test_list_configs(client: HumeClient, async_client: AsyncHumeClient) - "modified_on": 1715267200693, "text": "You are an AI weather assistant providing users with accurate and up-to-date weather information. Respond to user queries concisely and clearly. Use simple language and avoid technical jargon. Provide temperature, precipitation, wind conditions, and any weather alerts. Include helpful tips if severe weather is expected.", }, - "voice": {"provider": "HUME_AI", "name": "KORA"}, + "voice": { + "provider": "HUME_AI", + "name": "SAMPLE VOICE", + "custom_voice": { + "id": "00aa8ee9-c50e-4ea1-9af0-7b08ad451704", + "version": 1, + "name": "SAMPLE VOICE", + "created_on": 1724704587367, + "modified_on": 1725489961583, + "base_voice": "KORA", + "parameter_model": "20240715-4parameter", + "parameters": {"gender": -7, "huskiness": -2, "nasality": -8, "pitch": -9}, + }, + }, "language_model": { "model_provider": "ANTHROPIC", "model_resource": "claude-3-5-sonnet-20240620", @@ -73,6 +84,7 @@ async def test_list_configs(client: HumeClient, async_client: AsyncHumeClient) - "name": None, "created_on": None, "modified_on": None, + "evi_version": None, "prompt": { "id": None, "version": "integer", @@ -83,7 +95,25 @@ async def test_list_configs(client: HumeClient, async_client: AsyncHumeClient) - "modified_on": None, "text": None, }, - "voice": {"provider": None, "name": None}, + "voice": { + "provider": None, + "name": None, + "custom_voice": { + "id": None, + "version": "integer", + "name": None, + "created_on": None, + "modified_on": None, + "base_voice": None, + "parameter_model": None, + "parameters": { + "gender": "integer", + "huskiness": "integer", + "nasality": "integer", + "pitch": "integer", + }, + }, + }, "language_model": {"model_provider": None, "model_resource": None, "temperature": None}, "ellm_model": {"allow_short_responses": None}, "tools": ("list", {}), @@ -116,6 +146,7 @@ async def test_create_config(client: HumeClient, async_client: AsyncHumeClient) "name": "Weather Assistant Config", "created_on": 1715275452390, "modified_on": 1715275452390, + "evi_version": "2", "prompt": { "id": "af699d45-2985-42cc-91b9-af9e5da3bac5", "version": 0, @@ -126,7 +157,20 @@ async def test_create_config(client: HumeClient, async_client: AsyncHumeClient) "modified_on": 1715267200693, "text": "You are an AI weather assistant providing users with accurate and up-to-date weather information. Respond to user queries concisely and clearly. Use simple language and avoid technical jargon. Provide temperature, precipitation, wind conditions, and any weather alerts. Include helpful tips if severe weather is expected.", }, - "voice": {"provider": "HUME_AI", "name": "KORA"}, + "voice": { + "provider": "HUME_AI", + "name": "SAMPLE VOICE", + "custom_voice": { + "id": "00aa8ee9-c50e-4ea1-9af0-7b08ad451704", + "version": 1, + "name": "SAMPLE VOICE", + "created_on": 1724704587367, + "modified_on": 1725489961583, + "base_voice": "KORA", + "parameter_model": "20240715-4parameter", + "parameters": {"gender": -7, "huskiness": -2, "nasality": -8, "pitch": -9}, + }, + }, "language_model": { "model_provider": "ANTHROPIC", "model_resource": "claude-3-5-sonnet-20240620", @@ -152,6 +196,7 @@ async def test_create_config(client: HumeClient, async_client: AsyncHumeClient) "name": None, "created_on": None, "modified_on": None, + "evi_version": None, "prompt": { "id": None, "version": "integer", @@ -162,7 +207,20 @@ async def test_create_config(client: HumeClient, async_client: AsyncHumeClient) "modified_on": None, "text": None, }, - "voice": {"provider": None, "name": None}, + "voice": { + "provider": None, + "name": None, + "custom_voice": { + "id": None, + "version": "integer", + "name": None, + "created_on": None, + "modified_on": None, + "base_voice": None, + "parameter_model": None, + "parameters": {"gender": "integer", "huskiness": "integer", "nasality": "integer", "pitch": "integer"}, + }, + }, "language_model": {"model_provider": None, "model_resource": None, "temperature": None}, "ellm_model": {"allow_short_responses": None}, "tools": ("list", {}), @@ -179,8 +237,9 @@ async def test_create_config(client: HumeClient, async_client: AsyncHumeClient) } response = client.empathic_voice.configs.create_config( name="Weather Assistant Config", - prompt=PostedPromptSpec(id="af699d45-2985-42cc-91b9-af9e5da3bac5", version=0), - voice=PostedVoice(name="KORA"), + prompt=PostedConfigPromptSpec(id="af699d45-2985-42cc-91b9-af9e5da3bac5", version=0), + evi_version="2", + voice=PostedVoice(name="SAMPLE VOICE"), language_model=PostedLanguageModel( model_provider="ANTHROPIC", model_resource="claude-3-5-sonnet-20240620", temperature=1.0 ), @@ -194,8 +253,9 @@ async def test_create_config(client: HumeClient, async_client: AsyncHumeClient) async_response = await async_client.empathic_voice.configs.create_config( name="Weather Assistant Config", - prompt=PostedPromptSpec(id="af699d45-2985-42cc-91b9-af9e5da3bac5", version=0), - voice=PostedVoice(name="KORA"), + prompt=PostedConfigPromptSpec(id="af699d45-2985-42cc-91b9-af9e5da3bac5", version=0), + evi_version="2", + voice=PostedVoice(name="SAMPLE VOICE"), language_model=PostedLanguageModel( model_provider="ANTHROPIC", model_resource="claude-3-5-sonnet-20240620", temperature=1.0 ), @@ -221,6 +281,7 @@ async def test_list_config_versions(client: HumeClient, async_client: AsyncHumeC "name": "Weather Assistant Config", "created_on": 1715275452390, "modified_on": 1715275452390, + "evi_version": "2", "prompt": { "id": "af699d45-2985-42cc-91b9-af9e5da3bac5", "version": 0, @@ -231,7 +292,20 @@ async def test_list_config_versions(client: HumeClient, async_client: AsyncHumeC "modified_on": 1715267200693, "text": "You are an AI weather assistant providing users with accurate and up-to-date weather information. Respond to user queries concisely and clearly. Use simple language and avoid technical jargon. Provide temperature, precipitation, wind conditions, and any weather alerts. Include helpful tips if severe weather is expected.", }, - "voice": {"provider": "HUME_AI", "name": "KORA"}, + "voice": { + "provider": "HUME_AI", + "name": "SAMPLE VOICE", + "custom_voice": { + "id": "00aa8ee9-c50e-4ea1-9af0-7b08ad451704", + "version": 1, + "name": "SAMPLE VOICE", + "created_on": 1724704587367, + "modified_on": 1725489961583, + "base_voice": "KORA", + "parameter_model": "20240715-4parameter", + "parameters": {"gender": -7, "huskiness": -2, "nasality": -8, "pitch": -9}, + }, + }, "language_model": { "model_provider": "ANTHROPIC", "model_resource": "claude-3-5-sonnet-20240620", @@ -266,6 +340,7 @@ async def test_list_config_versions(client: HumeClient, async_client: AsyncHumeC "name": None, "created_on": None, "modified_on": None, + "evi_version": None, "prompt": { "id": None, "version": "integer", @@ -276,7 +351,25 @@ async def test_list_config_versions(client: HumeClient, async_client: AsyncHumeC "modified_on": None, "text": None, }, - "voice": {"provider": None, "name": None}, + "voice": { + "provider": None, + "name": None, + "custom_voice": { + "id": None, + "version": "integer", + "name": None, + "created_on": None, + "modified_on": None, + "base_voice": None, + "parameter_model": None, + "parameters": { + "gender": "integer", + "huskiness": "integer", + "nasality": "integer", + "pitch": "integer", + }, + }, + }, "language_model": {"model_provider": None, "model_resource": None, "temperature": None}, "ellm_model": {"allow_short_responses": None}, "tools": ("list", {}), @@ -311,6 +404,7 @@ async def test_create_config_version(client: HumeClient, async_client: AsyncHume "name": "Weather Assistant Config", "created_on": 1715275452390, "modified_on": 1722642242998, + "evi_version": "2", "prompt": { "id": "af699d45-2985-42cc-91b9-af9e5da3bac5", "version": 0, @@ -321,7 +415,20 @@ async def test_create_config_version(client: HumeClient, async_client: AsyncHume "modified_on": 1715267200693, "text": "You are an AI weather assistant providing users with accurate and up-to-date weather information. Respond to user queries concisely and clearly. Use simple language and avoid technical jargon. Provide temperature, precipitation, wind conditions, and any weather alerts. Include helpful tips if severe weather is expected.", }, - "voice": {"provider": "HUME_AI", "name": "ITO"}, + "voice": { + "provider": "HUME_AI", + "name": "ITO", + "custom_voice": { + "id": "00aa8ee9-c50e-4ea1-9af0-7b08ad451704", + "version": 1, + "name": "SAMPLE VOICE", + "created_on": 1724704587367, + "modified_on": 1725489961583, + "base_voice": "KORA", + "parameter_model": "20240715-4parameter", + "parameters": {"gender": -7, "huskiness": -2, "nasality": -8, "pitch": -9}, + }, + }, "language_model": { "model_provider": "ANTHROPIC", "model_resource": "claude-3-5-sonnet-20240620", @@ -347,6 +454,7 @@ async def test_create_config_version(client: HumeClient, async_client: AsyncHume "name": None, "created_on": None, "modified_on": None, + "evi_version": None, "prompt": { "id": None, "version": "integer", @@ -357,7 +465,20 @@ async def test_create_config_version(client: HumeClient, async_client: AsyncHume "modified_on": None, "text": None, }, - "voice": {"provider": None, "name": None}, + "voice": { + "provider": None, + "name": None, + "custom_voice": { + "id": None, + "version": "integer", + "name": None, + "created_on": None, + "modified_on": None, + "base_voice": None, + "parameter_model": None, + "parameters": {"gender": "integer", "huskiness": "integer", "nasality": "integer", "pitch": "integer"}, + }, + }, "language_model": {"model_provider": None, "model_resource": None, "temperature": None}, "ellm_model": {"allow_short_responses": None}, "tools": ("list", {}), @@ -375,7 +496,8 @@ async def test_create_config_version(client: HumeClient, async_client: AsyncHume response = client.empathic_voice.configs.create_config_version( id="1b60e1a0-cc59-424a-8d2c-189d354db3f3", version_description="This is an updated version of the Weather Assistant Config.", - prompt=PostedPromptSpec(id="af699d45-2985-42cc-91b9-af9e5da3bac5", version=0), + evi_version="2", + prompt=PostedConfigPromptSpec(id="af699d45-2985-42cc-91b9-af9e5da3bac5", version=0), voice=PostedVoice(name="ITO"), language_model=PostedLanguageModel( model_provider="ANTHROPIC", model_resource="claude-3-5-sonnet-20240620", temperature=1.0 @@ -392,7 +514,8 @@ async def test_create_config_version(client: HumeClient, async_client: AsyncHume async_response = await async_client.empathic_voice.configs.create_config_version( id="1b60e1a0-cc59-424a-8d2c-189d354db3f3", version_description="This is an updated version of the Weather Assistant Config.", - prompt=PostedPromptSpec(id="af699d45-2985-42cc-91b9-af9e5da3bac5", version=0), + evi_version="2", + prompt=PostedConfigPromptSpec(id="af699d45-2985-42cc-91b9-af9e5da3bac5", version=0), voice=PostedVoice(name="ITO"), language_model=PostedLanguageModel( model_provider="ANTHROPIC", model_resource="claude-3-5-sonnet-20240620", temperature=1.0 @@ -409,16 +532,32 @@ async def test_create_config_version(client: HumeClient, async_client: AsyncHume async def test_delete_config(client: HumeClient, async_client: AsyncHumeClient) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert client.empathic_voice.configs.delete_config(id="1b60e1a0-cc59-424a-8d2c-189d354db3f3") is None # type: ignore[func-returns-value] + assert ( + client.empathic_voice.configs.delete_config(id="1b60e1a0-cc59-424a-8d2c-189d354db3f3") # type: ignore[func-returns-value] + is None + ) - assert await async_client.empathic_voice.configs.delete_config(id="1b60e1a0-cc59-424a-8d2c-189d354db3f3") is None # type: ignore[func-returns-value] + assert ( + await async_client.empathic_voice.configs.delete_config(id="1b60e1a0-cc59-424a-8d2c-189d354db3f3") # type: ignore[func-returns-value] + is None + ) async def test_update_config_name(client: HumeClient, async_client: AsyncHumeClient) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert client.empathic_voice.configs.update_config_name(id="1b60e1a0-cc59-424a-8d2c-189d354db3f3", name="Updated Weather Assistant Config Name") is '' # type: ignore[func-returns-value] + assert ( + client.empathic_voice.configs.update_config_name( + id="1b60e1a0-cc59-424a-8d2c-189d354db3f3", name="Updated Weather Assistant Config Name" + ) # type: ignore[func-returns-value] + == "" + ) - assert await async_client.empathic_voice.configs.update_config_name(id="1b60e1a0-cc59-424a-8d2c-189d354db3f3", name="Updated Weather Assistant Config Name") is '' # type: ignore[func-returns-value] + assert ( + await async_client.empathic_voice.configs.update_config_name( + id="1b60e1a0-cc59-424a-8d2c-189d354db3f3", name="Updated Weather Assistant Config Name" + ) # type: ignore[func-returns-value] + == "" + ) async def test_get_config_version(client: HumeClient, async_client: AsyncHumeClient) -> None: @@ -429,6 +568,7 @@ async def test_get_config_version(client: HumeClient, async_client: AsyncHumeCli "name": "Weather Assistant Config", "created_on": 1715275452390, "modified_on": 1715275452390, + "evi_version": "2", "prompt": { "id": "af699d45-2985-42cc-91b9-af9e5da3bac5", "version": 0, @@ -439,7 +579,20 @@ async def test_get_config_version(client: HumeClient, async_client: AsyncHumeCli "modified_on": 1715267200693, "text": "You are an AI weather assistant providing users with accurate and up-to-date weather information. Respond to user queries concisely and clearly. Use simple language and avoid technical jargon. Provide temperature, precipitation, wind conditions, and any weather alerts. Include helpful tips if severe weather is expected.", }, - "voice": {"provider": "HUME_AI", "name": "KORA"}, + "voice": { + "provider": "HUME_AI", + "name": "SAMPLE VOICE", + "custom_voice": { + "id": "00aa8ee9-c50e-4ea1-9af0-7b08ad451704", + "version": 1, + "name": "SAMPLE VOICE", + "created_on": 1724704587367, + "modified_on": 1725489961583, + "base_voice": "KORA", + "parameter_model": "20240715-4parameter", + "parameters": {"gender": -7, "huskiness": -2, "nasality": -8, "pitch": -9}, + }, + }, "language_model": { "model_provider": "ANTHROPIC", "model_resource": "claude-3-5-sonnet-20240620", @@ -465,6 +618,7 @@ async def test_get_config_version(client: HumeClient, async_client: AsyncHumeCli "name": None, "created_on": None, "modified_on": None, + "evi_version": None, "prompt": { "id": None, "version": "integer", @@ -475,7 +629,20 @@ async def test_get_config_version(client: HumeClient, async_client: AsyncHumeCli "modified_on": None, "text": None, }, - "voice": {"provider": None, "name": None}, + "voice": { + "provider": None, + "name": None, + "custom_voice": { + "id": None, + "version": "integer", + "name": None, + "created_on": None, + "modified_on": None, + "base_voice": None, + "parameter_model": None, + "parameters": {"gender": "integer", "huskiness": "integer", "nasality": "integer", "pitch": "integer"}, + }, + }, "language_model": {"model_provider": None, "model_resource": None, "temperature": None}, "ellm_model": {"allow_short_responses": None}, "tools": ("list", {}), @@ -501,9 +668,17 @@ async def test_get_config_version(client: HumeClient, async_client: AsyncHumeCli async def test_delete_config_version(client: HumeClient, async_client: AsyncHumeClient) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert client.empathic_voice.configs.delete_config_version(id="1b60e1a0-cc59-424a-8d2c-189d354db3f3", version=1) is None # type: ignore[func-returns-value] + assert ( + client.empathic_voice.configs.delete_config_version(id="1b60e1a0-cc59-424a-8d2c-189d354db3f3", version=1) # type: ignore[func-returns-value] + is None + ) - assert await async_client.empathic_voice.configs.delete_config_version(id="1b60e1a0-cc59-424a-8d2c-189d354db3f3", version=1) is None # type: ignore[func-returns-value] + assert ( + await async_client.empathic_voice.configs.delete_config_version( + id="1b60e1a0-cc59-424a-8d2c-189d354db3f3", version=1 + ) # type: ignore[func-returns-value] + is None + ) async def test_update_config_description(client: HumeClient, async_client: AsyncHumeClient) -> None: @@ -514,6 +689,7 @@ async def test_update_config_description(client: HumeClient, async_client: Async "name": "Weather Assistant Config", "created_on": 1715275452390, "modified_on": 1715275452390, + "evi_version": "2", "prompt": { "id": "af699d45-2985-42cc-91b9-af9e5da3bac5", "version": 0, @@ -524,7 +700,20 @@ async def test_update_config_description(client: HumeClient, async_client: Async "modified_on": 1715267200693, "text": "You are an AI weather assistant providing users with accurate and up-to-date weather information. Respond to user queries concisely and clearly. Use simple language and avoid technical jargon. Provide temperature, precipitation, wind conditions, and any weather alerts. Include helpful tips if severe weather is expected.", }, - "voice": {"provider": "HUME_AI", "name": "KORA"}, + "voice": { + "provider": "HUME_AI", + "name": "SAMPLE VOICE", + "custom_voice": { + "id": "00aa8ee9-c50e-4ea1-9af0-7b08ad451704", + "version": 1, + "name": "SAMPLE VOICE", + "created_on": 1724704587367, + "modified_on": 1725489961583, + "base_voice": "KORA", + "parameter_model": "20240715-4parameter", + "parameters": {"gender": -7, "huskiness": -2, "nasality": -8, "pitch": -9}, + }, + }, "language_model": { "model_provider": "ANTHROPIC", "model_resource": "claude-3-5-sonnet-20240620", @@ -550,6 +739,7 @@ async def test_update_config_description(client: HumeClient, async_client: Async "name": None, "created_on": None, "modified_on": None, + "evi_version": None, "prompt": { "id": None, "version": "integer", @@ -560,7 +750,20 @@ async def test_update_config_description(client: HumeClient, async_client: Async "modified_on": None, "text": None, }, - "voice": {"provider": None, "name": None}, + "voice": { + "provider": None, + "name": None, + "custom_voice": { + "id": None, + "version": "integer", + "name": None, + "created_on": None, + "modified_on": None, + "base_voice": None, + "parameter_model": None, + "parameters": {"gender": "integer", "huskiness": "integer", "nasality": "integer", "pitch": "integer"}, + }, + }, "language_model": {"model_provider": None, "model_resource": None, "temperature": None}, "ellm_model": {"allow_short_responses": None}, "tools": ("list", {}), diff --git a/tests/empathic_voice/test_prompts.py b/tests/empathic_voice/test_prompts.py index 302e338..8b7cef3 100644 --- a/tests/empathic_voice/test_prompts.py +++ b/tests/empathic_voice/test_prompts.py @@ -1,9 +1,8 @@ # This file was auto-generated by Fern from our API Definition. +from hume import HumeClient +from hume import AsyncHumeClient import typing - -from hume.client import AsyncHumeClient, HumeClient - from ..utilities import validate_response @@ -124,16 +123,32 @@ async def test_create_prompt_verison(client: HumeClient, async_client: AsyncHume async def test_delete_prompt(client: HumeClient, async_client: AsyncHumeClient) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert client.empathic_voice.prompts.delete_prompt(id="af699d45-2985-42cc-91b9-af9e5da3bac5") is None # type: ignore[func-returns-value] + assert ( + client.empathic_voice.prompts.delete_prompt(id="af699d45-2985-42cc-91b9-af9e5da3bac5") # type: ignore[func-returns-value] + is None + ) - assert await async_client.empathic_voice.prompts.delete_prompt(id="af699d45-2985-42cc-91b9-af9e5da3bac5") is None # type: ignore[func-returns-value] + assert ( + await async_client.empathic_voice.prompts.delete_prompt(id="af699d45-2985-42cc-91b9-af9e5da3bac5") # type: ignore[func-returns-value] + is None + ) async def test_update_prompt_name(client: HumeClient, async_client: AsyncHumeClient) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert client.empathic_voice.prompts.update_prompt_name(id="af699d45-2985-42cc-91b9-af9e5da3bac5", name="Updated Weather Assistant Prompt Name") is '' # type: ignore[func-returns-value] + assert ( + client.empathic_voice.prompts.update_prompt_name( + id="af699d45-2985-42cc-91b9-af9e5da3bac5", name="Updated Weather Assistant Prompt Name" + ) # type: ignore[func-returns-value] + == "" + ) - assert await async_client.empathic_voice.prompts.update_prompt_name(id="af699d45-2985-42cc-91b9-af9e5da3bac5", name="Updated Weather Assistant Prompt Name") is '' # type: ignore[func-returns-value] + assert ( + await async_client.empathic_voice.prompts.update_prompt_name( + id="af699d45-2985-42cc-91b9-af9e5da3bac5", name="Updated Weather Assistant Prompt Name" + ) # type: ignore[func-returns-value] + == "" + ) async def test_get_prompt_version(client: HumeClient, async_client: AsyncHumeClient) -> None: @@ -168,9 +183,17 @@ async def test_get_prompt_version(client: HumeClient, async_client: AsyncHumeCli async def test_delete_prompt_version(client: HumeClient, async_client: AsyncHumeClient) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert client.empathic_voice.prompts.delete_prompt_version(id="af699d45-2985-42cc-91b9-af9e5da3bac5", version=1) is None # type: ignore[func-returns-value] + assert ( + client.empathic_voice.prompts.delete_prompt_version(id="af699d45-2985-42cc-91b9-af9e5da3bac5", version=1) # type: ignore[func-returns-value] + is None + ) - assert await async_client.empathic_voice.prompts.delete_prompt_version(id="af699d45-2985-42cc-91b9-af9e5da3bac5", version=1) is None # type: ignore[func-returns-value] + assert ( + await async_client.empathic_voice.prompts.delete_prompt_version( + id="af699d45-2985-42cc-91b9-af9e5da3bac5", version=1 + ) # type: ignore[func-returns-value] + is None + ) async def test_update_prompt_description(client: HumeClient, async_client: AsyncHumeClient) -> None: diff --git a/tests/empathic_voice/test_tools.py b/tests/empathic_voice/test_tools.py index 196f5ce..db3f592 100644 --- a/tests/empathic_voice/test_tools.py +++ b/tests/empathic_voice/test_tools.py @@ -1,12 +1,8 @@ # This file was auto-generated by Fern from our API Definition. +from hume import HumeClient +from hume import AsyncHumeClient import typing - -import pytest - -from hume.client import AsyncHumeClient, HumeClient - - from ..utilities import validate_response @@ -157,17 +153,32 @@ async def test_create_tool_version(client: HumeClient, async_client: AsyncHumeCl async def test_delete_tool(client: HumeClient, async_client: AsyncHumeClient) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert client.empathic_voice.tools.delete_tool(id="00183a3f-79ba-413d-9f3b-609864268bea") is None # type: ignore[func-returns-value] + assert ( + client.empathic_voice.tools.delete_tool(id="00183a3f-79ba-413d-9f3b-609864268bea") # type: ignore[func-returns-value] + is None + ) - assert await async_client.empathic_voice.tools.delete_tool(id="00183a3f-79ba-413d-9f3b-609864268bea") is None # type: ignore[func-returns-value] + assert ( + await async_client.empathic_voice.tools.delete_tool(id="00183a3f-79ba-413d-9f3b-609864268bea") # type: ignore[func-returns-value] + is None + ) -@pytest.mark.skip("Untested.") async def test_update_tool_name(client: HumeClient, async_client: AsyncHumeClient) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert client.empathic_voice.tools.update_tool_name(id="00183a3f-79ba-413d-9f3b-609864268bea", name="get_current_temperature") is None # type: ignore[func-returns-value] + assert ( + client.empathic_voice.tools.update_tool_name( + id="00183a3f-79ba-413d-9f3b-609864268bea", name="get_current_temperature" + ) # type: ignore[func-returns-value] + == "" + ) - assert await async_client.empathic_voice.tools.update_tool_name(id="00183a3f-79ba-413d-9f3b-609864268bea", name="get_current_temperature") is None # type: ignore[func-returns-value] + assert ( + await async_client.empathic_voice.tools.update_tool_name( + id="00183a3f-79ba-413d-9f3b-609864268bea", name="get_current_temperature" + ) # type: ignore[func-returns-value] + == "" + ) async def test_get_tool_version(client: HumeClient, async_client: AsyncHumeClient) -> None: @@ -208,9 +219,17 @@ async def test_get_tool_version(client: HumeClient, async_client: AsyncHumeClien async def test_delete_tool_version(client: HumeClient, async_client: AsyncHumeClient) -> None: # Type ignore to avoid mypy complaining about the function not being meant to return a value - assert client.empathic_voice.tools.delete_tool_version(id="00183a3f-79ba-413d-9f3b-609864268bea", version=1) is None # type: ignore[func-returns-value] + assert ( + client.empathic_voice.tools.delete_tool_version(id="00183a3f-79ba-413d-9f3b-609864268bea", version=1) # type: ignore[func-returns-value] + is None + ) - assert await async_client.empathic_voice.tools.delete_tool_version(id="00183a3f-79ba-413d-9f3b-609864268bea", version=1) is None # type: ignore[func-returns-value] + assert ( + await async_client.empathic_voice.tools.delete_tool_version( + id="00183a3f-79ba-413d-9f3b-609864268bea", version=1 + ) # type: ignore[func-returns-value] + is None + ) async def test_update_tool_description(client: HumeClient, async_client: AsyncHumeClient) -> None: