smallestai 4.0.1__tar.gz → 4.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of smallestai might be problematic. Click here for more details.
- {smallestai-4.0.1/smallestai.egg-info → smallestai-4.1.0}/PKG-INFO +1 -1
- {smallestai-4.0.1 → smallestai-4.1.0}/pyproject.toml +1 -1
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/waves/async_waves_client.py +63 -10
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/waves/exceptions.py +4 -4
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/waves/models.py +8 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/waves/utils.py +19 -1
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/waves/waves_client.py +47 -10
- {smallestai-4.0.1 → smallestai-4.1.0/smallestai.egg-info}/PKG-INFO +1 -1
- {smallestai-4.0.1 → smallestai-4.1.0}/LICENSE +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/README.md +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/setup.cfg +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/__init__.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/__init__.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/api/__init__.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/api/agent_templates_api.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/api/agents_api.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/api/calls_api.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/api/campaigns_api.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/api/knowledge_base_api.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/api/logs_api.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/api/organization_api.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/api/user_api.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/api_client.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/api_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/atoms_client.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/configuration.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/exceptions.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/__init__.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_agent_id_webhook_subscriptions_delete200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_agent_id_webhook_subscriptions_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_agent_id_webhook_subscriptions_get404_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_agent_id_webhook_subscriptions_post201_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_agent_id_webhook_subscriptions_post400_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_agent_id_webhook_subscriptions_post_request.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_dto.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_dto_language.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_dto_language_switching.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_dto_synthesizer.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_dto_synthesizer_voice_config.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_from_template_post200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_get200_response_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_delete200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_patch200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_patch_request.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_patch_request_language.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_patch_request_language_switching.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_patch_request_synthesizer.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_patch_request_synthesizer_voice_config.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_patch_request_synthesizer_voice_config_one_of.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_patch_request_synthesizer_voice_config_one_of1.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_workflow_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_workflow_get200_response_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_workflow_get200_response_data_edges_inner.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_workflow_get200_response_data_edges_inner_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_workflow_get200_response_data_edges_inner_marker_end.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_workflow_get200_response_data_nodes_inner.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_workflow_get200_response_data_nodes_inner_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_workflow_get200_response_data_nodes_inner_data_variables.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_workflow_get200_response_data_nodes_inner_data_variables_data_inner.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_workflow_get200_response_data_nodes_inner_position.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_workflow_get404_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_template_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_template_get200_response_data_inner.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/api_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_get200_response_data_inner.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_delete200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_delete400_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_get400_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_get403_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_get404_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_delete200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_delete200_response_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_delete_request.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_get200_response_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_get200_response_data_members_inner.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_get400_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_get500_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_post200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_post200_response_data_inner.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_post200_response_data_inner_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_post400_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_post403_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_post_request.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_search_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_search_get200_response_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_search_get200_response_data_search_info.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_search_get400_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_search_get500_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_post200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_post200_response_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_post400_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/bad_request_error_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/campaign_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/campaign_get200_response_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/campaign_get_request.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/campaign_id_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/campaign_id_get200_response_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/campaign_post201_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/campaign_post_request.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/conversation_id_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/conversation_id_get200_response_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/conversation_outbound_post200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/conversation_outbound_post200_response_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/conversation_outbound_post_request.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/create_agent_from_template_request.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/create_agent_request.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/create_agent_request_language.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/create_agent_request_language_synthesizer.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/create_agent_request_language_synthesizer_voice_config.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/internal_server_error_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/knowledge_base.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/knowledge_base_item.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/knowledgebase_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/knowledgebase_id_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/knowledgebase_id_items_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/knowledgebase_id_items_upload_text_post_request.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/knowledgebase_post201_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/knowledgebase_post_request.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/organization_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/organization_get200_response_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/organization_get200_response_data_members_inner.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/organization_get200_response_data_subscription.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/product_phone_numbers_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/product_phone_numbers_get200_response_data_inner.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/product_phone_numbers_get200_response_data_inner_attributes.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/unauthorized_error_reponse.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/user_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/user_get200_response_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_agent.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_event.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_get200_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_get200_response_data.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_id_delete404_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_post201_response.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_post_request.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_post_request_events_inner.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_subscription.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_subscription_populated.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/py.typed +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/rest.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/waves/__init__.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai/waves/stream_tts.py +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai.egg-info/SOURCES.txt +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai.egg-info/dependency_links.txt +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai.egg-info/requires.txt +0 -0
- {smallestai-4.0.1 → smallestai-4.1.0}/smallestai.egg-info/top_level.txt +0 -0
|
@@ -6,8 +6,8 @@ import aiofiles
|
|
|
6
6
|
import requests
|
|
7
7
|
from typing import Optional, Union, List
|
|
8
8
|
|
|
9
|
-
from smallestai.waves.exceptions import
|
|
10
|
-
from smallestai.waves.utils import (TTSOptions, validate_input,
|
|
9
|
+
from smallestai.waves.exceptions import InvalidError, APIError
|
|
10
|
+
from smallestai.waves.utils import (TTSOptions, validate_input, validate_asr_input,
|
|
11
11
|
get_smallest_languages, get_smallest_models, ALLOWED_AUDIO_EXTENSIONS, API_BASE_URL)
|
|
12
12
|
|
|
13
13
|
|
|
@@ -52,7 +52,7 @@ class AsyncWavesClient:
|
|
|
52
52
|
"""
|
|
53
53
|
self.api_key = api_key or os.environ.get("SMALLEST_API_KEY")
|
|
54
54
|
if not self.api_key:
|
|
55
|
-
raise
|
|
55
|
+
raise InvalidError()
|
|
56
56
|
if model == "lightning-large" and voice_id is None:
|
|
57
57
|
voice_id = "lakshya"
|
|
58
58
|
|
|
@@ -150,7 +150,7 @@ class AsyncWavesClient:
|
|
|
150
150
|
- Otherwise, returns the synthesized audio content as bytes.
|
|
151
151
|
|
|
152
152
|
Raises:
|
|
153
|
-
-
|
|
153
|
+
- InvalidError: If the provided file name does not have a .wav or .mp3 extension when `save_as` is specified.
|
|
154
154
|
- APIError: If the API request fails or returns an error.
|
|
155
155
|
- ValueError: If an unexpected parameter is passed in `kwargs`.
|
|
156
156
|
"""
|
|
@@ -223,17 +223,17 @@ class AsyncWavesClient:
|
|
|
223
223
|
- str: The response from the API as a formatted JSON string.
|
|
224
224
|
|
|
225
225
|
Raises:
|
|
226
|
-
-
|
|
226
|
+
- InvalidError: If the file does not exist or is not a valid audio file.
|
|
227
227
|
- APIError: If the API request fails or returns an error.
|
|
228
228
|
"""
|
|
229
229
|
url = f"{API_BASE_URL}/lightning-large/add_voice"
|
|
230
230
|
|
|
231
231
|
if not os.path.exists(file_path):
|
|
232
|
-
raise
|
|
232
|
+
raise InvalidError("Invalid file path. File does not exist.")
|
|
233
233
|
|
|
234
234
|
file_extension = os.path.splitext(file_path)[1].lower()
|
|
235
235
|
if file_extension not in ALLOWED_AUDIO_EXTENSIONS:
|
|
236
|
-
raise
|
|
236
|
+
raise InvalidError(f"Invalid file type. Supported formats are: {ALLOWED_AUDIO_EXTENSIONS}")
|
|
237
237
|
|
|
238
238
|
headers = {
|
|
239
239
|
'Authorization': f"Bearer {self.api_key}",
|
|
@@ -255,7 +255,7 @@ class AsyncWavesClient:
|
|
|
255
255
|
if res.status != 200:
|
|
256
256
|
raise APIError(f"Failed to add voice: {await res.text()}. For more information, visit https://waves.smallest.ai/")
|
|
257
257
|
|
|
258
|
-
return
|
|
258
|
+
return await res.json()
|
|
259
259
|
|
|
260
260
|
finally:
|
|
261
261
|
if should_cleanup and self.session:
|
|
@@ -290,8 +290,61 @@ class AsyncWavesClient:
|
|
|
290
290
|
if res.status != 200:
|
|
291
291
|
raise APIError(f"Failed to delete voice: {await res.text()}. For more information, visit https://waves.smallest.ai/")
|
|
292
292
|
|
|
293
|
-
return
|
|
293
|
+
return await res.json()
|
|
294
294
|
finally:
|
|
295
295
|
if should_cleanup and self.session:
|
|
296
296
|
await self.session.close()
|
|
297
|
-
self.session = None
|
|
297
|
+
self.session = None
|
|
298
|
+
|
|
299
|
+
async def transcribe(
|
|
300
|
+
self,
|
|
301
|
+
file_path: str,
|
|
302
|
+
language: Optional[str] = "en",
|
|
303
|
+
word_timestamps: Optional[bool] = False,
|
|
304
|
+
age_detection: Optional[bool] = False,
|
|
305
|
+
gender_detection: Optional[bool] = False,
|
|
306
|
+
emotion_detection: Optional[bool] = False,
|
|
307
|
+
model: Optional[str] = "lightning"
|
|
308
|
+
) -> dict:
|
|
309
|
+
validate_asr_input(file_path, model, language)
|
|
310
|
+
|
|
311
|
+
url = f"{API_BASE_URL}/speech-to-text"
|
|
312
|
+
headers = {
|
|
313
|
+
'Authorization': f"Bearer {self.api_key}",
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
should_cleanup = await self._ensure_session()
|
|
317
|
+
|
|
318
|
+
try:
|
|
319
|
+
file_extension = os.path.splitext(file_path)[1].lower()
|
|
320
|
+
content_type = f"audio/{file_extension[1:]}" if file_extension else "application/octet-stream"
|
|
321
|
+
|
|
322
|
+
async with aiofiles.open(file_path, 'rb') as f:
|
|
323
|
+
file_data = await f.read()
|
|
324
|
+
|
|
325
|
+
form = aiohttp.FormData()
|
|
326
|
+
form.add_field(
|
|
327
|
+
'file',
|
|
328
|
+
file_data,
|
|
329
|
+
filename=os.path.basename(file_path),
|
|
330
|
+
content_type=content_type
|
|
331
|
+
)
|
|
332
|
+
# Send options as multipart form fields (not query params)
|
|
333
|
+
form.add_field('model', model)
|
|
334
|
+
form.add_field('language', language)
|
|
335
|
+
form.add_field('word_timestamps', str(bool(word_timestamps)).lower())
|
|
336
|
+
form.add_field('age_detection', str(bool(age_detection)).lower())
|
|
337
|
+
form.add_field('gender_detection', str(bool(gender_detection)).lower())
|
|
338
|
+
form.add_field('emotion_detection', str(bool(emotion_detection)).lower())
|
|
339
|
+
|
|
340
|
+
async with self.session.post(url, headers=headers, data=form) as res:
|
|
341
|
+
if res.status != 200:
|
|
342
|
+
raise APIError(
|
|
343
|
+
f"Failed to transcribe audio: {await res.text()}. "
|
|
344
|
+
"For more information, visit https://waves-docs.smallest.ai/v4.0.0/content/api-references/asr-post-api"
|
|
345
|
+
)
|
|
346
|
+
return await res.json()
|
|
347
|
+
finally:
|
|
348
|
+
if should_cleanup and self.session:
|
|
349
|
+
await self.session.close()
|
|
350
|
+
self.session = None
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
class
|
|
1
|
+
class InvalidError(Exception):
|
|
2
2
|
"""Base exception for TTS SDK"""
|
|
3
3
|
default_message = "API key is required. Please set the `SMALLEST_API_KEY` environment variable or visit https://waves.smallest.ai/ to obtain your API key."
|
|
4
4
|
|
|
5
5
|
def __init__(self, message=None):
|
|
6
6
|
super().__init__(message or self.default_message)
|
|
7
7
|
|
|
8
|
-
class APIError(
|
|
8
|
+
class APIError(InvalidError):
|
|
9
9
|
"""Raised when the API returns an error"""
|
|
10
10
|
pass
|
|
11
11
|
|
|
12
|
-
class ValidationError(
|
|
12
|
+
class ValidationError(InvalidError):
|
|
13
13
|
"""Raised when input validation fails"""
|
|
14
14
|
pass
|
|
15
15
|
|
|
16
|
-
class AuthenticationError(
|
|
16
|
+
class AuthenticationError(InvalidError):
|
|
17
17
|
"""Raised when authentication fails"""
|
|
18
18
|
pass
|
|
@@ -6,3 +6,11 @@ TTSModels = [
|
|
|
6
6
|
"lightning-large",
|
|
7
7
|
"lightning-v2"
|
|
8
8
|
]
|
|
9
|
+
ASRLanguages_lightning = [
|
|
10
|
+
"it", "es", "en", "pt", "hi", "de", "fr", "uk", "ru", "kn", "ml", "pl",
|
|
11
|
+
"mr", "gu", "cs", "sk", "te", "or", "nl", "bn", "lv", "et", "ro", "pa",
|
|
12
|
+
"fi", "sv", "bg", "ta", "hu", "da", "lt", "mt", "multi"
|
|
13
|
+
]
|
|
14
|
+
ASRModels = [
|
|
15
|
+
"lightning"
|
|
16
|
+
]
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import os
|
|
1
2
|
from typing import List
|
|
2
3
|
from typing import Optional
|
|
3
4
|
from dataclasses import dataclass
|
|
4
5
|
|
|
5
6
|
from smallestai.waves.exceptions import ValidationError
|
|
6
|
-
from smallestai.waves.models import TTSModels, TTSLanguages_lightning, TTSLanguages_lightning_large, TTSLanguages_lightning_v2
|
|
7
|
+
from smallestai.waves.models import TTSModels, TTSLanguages_lightning, TTSLanguages_lightning_large, TTSLanguages_lightning_v2, ASRModels, ASRLanguages_lightning
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
API_BASE_URL = "https://waves-api.smallest.ai/api/v1"
|
|
@@ -25,7 +26,24 @@ class TTSOptions:
|
|
|
25
26
|
enhancement: int
|
|
26
27
|
language: str
|
|
27
28
|
output_format: str
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class ASROptions:
|
|
32
|
+
model: str
|
|
33
|
+
api_key: str
|
|
34
|
+
language: str
|
|
35
|
+
word_timestamps: bool
|
|
36
|
+
age_detection: bool
|
|
37
|
+
gender_detection: bool
|
|
38
|
+
emotion_detection: bool
|
|
28
39
|
|
|
40
|
+
def validate_asr_input(file_path: str, model: str, language: str):
|
|
41
|
+
if not os.path.isfile(file_path):
|
|
42
|
+
raise ValidationError("Invalid file path. File does not exist.")
|
|
43
|
+
if model not in ASRModels:
|
|
44
|
+
raise ValidationError(f"Invalid model: {model}. Must be one of {ASRModels}")
|
|
45
|
+
if language not in ASRLanguages_lightning:
|
|
46
|
+
raise ValidationError(f"Invalid language: {language}. Must be one of {ASRLanguages_lightning}")
|
|
29
47
|
|
|
30
48
|
def validate_input(text: str, model: str, sample_rate: int, speed: float, consistency: Optional[float] = None, similarity: Optional[float] = None, enhancement: Optional[int] = None):
|
|
31
49
|
if not text:
|
|
@@ -4,8 +4,8 @@ import copy
|
|
|
4
4
|
import requests
|
|
5
5
|
from typing import Optional, Union, List
|
|
6
6
|
|
|
7
|
-
from smallestai.waves.exceptions import
|
|
8
|
-
from smallestai.waves.utils import (TTSOptions, validate_input,
|
|
7
|
+
from smallestai.waves.exceptions import InvalidError, APIError
|
|
8
|
+
from smallestai.waves.utils import (TTSOptions, validate_input, validate_asr_input,
|
|
9
9
|
get_smallest_languages, get_smallest_models, ALLOWED_AUDIO_EXTENSIONS, API_BASE_URL)
|
|
10
10
|
|
|
11
11
|
class WavesClient:
|
|
@@ -48,7 +48,7 @@ class WavesClient:
|
|
|
48
48
|
"""
|
|
49
49
|
self.api_key = api_key or os.environ.get("SMALLEST_API_KEY")
|
|
50
50
|
if not self.api_key:
|
|
51
|
-
raise
|
|
51
|
+
raise InvalidError()
|
|
52
52
|
if model == "lightning-large" and voice_id is None:
|
|
53
53
|
voice_id = "lakshya"
|
|
54
54
|
|
|
@@ -125,7 +125,7 @@ class WavesClient:
|
|
|
125
125
|
- Otherwise, returns the synthesized audio content as bytes.
|
|
126
126
|
|
|
127
127
|
Raises:
|
|
128
|
-
-
|
|
128
|
+
- InvalidError: If the provided file name does not have a .wav or .mp3 extension when `save_as` is specified.
|
|
129
129
|
- APIError: If the API request fails or returns an error.
|
|
130
130
|
"""
|
|
131
131
|
opts = copy.deepcopy(self.opts)
|
|
@@ -184,15 +184,15 @@ class WavesClient:
|
|
|
184
184
|
- str: The response from the API as a formatted JSON string.
|
|
185
185
|
|
|
186
186
|
Raises:
|
|
187
|
-
-
|
|
187
|
+
- InvalidError: If the file does not exist or is not a valid audio file.
|
|
188
188
|
- APIError: If the API request fails or returns an error.
|
|
189
189
|
"""
|
|
190
190
|
if not os.path.isfile(file_path):
|
|
191
|
-
raise
|
|
191
|
+
raise InvalidError("Invalid file path. File does not exist.")
|
|
192
192
|
|
|
193
193
|
file_extension = os.path.splitext(file_path)[1].lower()
|
|
194
194
|
if file_extension not in ALLOWED_AUDIO_EXTENSIONS:
|
|
195
|
-
raise
|
|
195
|
+
raise InvalidError(f"Invalid file type. Supported formats are: {ALLOWED_AUDIO_EXTENSIONS}")
|
|
196
196
|
|
|
197
197
|
url = f"{API_BASE_URL}/lightning-large/add_voice"
|
|
198
198
|
payload = {'displayName': display_name}
|
|
@@ -206,8 +206,8 @@ class WavesClient:
|
|
|
206
206
|
response = requests.post(url, headers=headers, data=payload, files=files)
|
|
207
207
|
if response.status_code != 200:
|
|
208
208
|
raise APIError(f"Failed to add voice: {response.text}. For more information, visit https://waves.smallest.ai/")
|
|
209
|
-
|
|
210
|
-
return
|
|
209
|
+
|
|
210
|
+
return response.json()
|
|
211
211
|
|
|
212
212
|
|
|
213
213
|
def delete_voice(self, voice_id: str) -> str:
|
|
@@ -234,4 +234,41 @@ class WavesClient:
|
|
|
234
234
|
if response.status_code != 200:
|
|
235
235
|
raise APIError(f"Failed to delete voice: {response.text}. For more information, visit https://waves.smallest.ai/")
|
|
236
236
|
|
|
237
|
-
return
|
|
237
|
+
return response.json()
|
|
238
|
+
|
|
239
|
+
def transcribe(
|
|
240
|
+
self,
|
|
241
|
+
file_path: str,
|
|
242
|
+
language: Optional[str] = "en",
|
|
243
|
+
word_timestamps: Optional[bool] = False,
|
|
244
|
+
age_detection: Optional[bool] = False,
|
|
245
|
+
gender_detection: Optional[bool] = False,
|
|
246
|
+
emotion_detection: Optional[bool] = False,
|
|
247
|
+
model: Optional[str] = "lightning"
|
|
248
|
+
) -> dict:
|
|
249
|
+
validate_asr_input(file_path, model, language)
|
|
250
|
+
|
|
251
|
+
url = f"{API_BASE_URL}/speech-to-text"
|
|
252
|
+
headers = {
|
|
253
|
+
'Authorization': f"Bearer {self.api_key}",
|
|
254
|
+
}
|
|
255
|
+
payload = {
|
|
256
|
+
'model': model,
|
|
257
|
+
'language': language,
|
|
258
|
+
'word_timestamps': str(bool(word_timestamps)).lower(),
|
|
259
|
+
'age_detection': str(bool(age_detection)).lower(),
|
|
260
|
+
'gender_detection': str(bool(gender_detection)).lower(),
|
|
261
|
+
'emotion_detection': str(bool(emotion_detection)).lower()
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
file_extension = os.path.splitext(file_path)[1].lower()
|
|
265
|
+
content_type = f"audio/{file_extension[1:]}" if file_extension else "application/octet-stream"
|
|
266
|
+
|
|
267
|
+
with open(file_path, 'rb') as f:
|
|
268
|
+
files = {'file': (os.path.basename(file_path), f, content_type)}
|
|
269
|
+
response = requests.post(url, headers=headers, files=files, data=payload)
|
|
270
|
+
|
|
271
|
+
if response.status_code != 200:
|
|
272
|
+
raise APIError(f"Failed to transcribe audio: {response.text}. For more information, visit https://waves-docs.smallest.ai/v4.0.0/content/api-references/asr-post-api")
|
|
273
|
+
|
|
274
|
+
return response.json()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_dto_language_switching.py
RENAMED
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_dto_synthesizer_voice_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_delete200_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_patch_request_language.py
RENAMED
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_patch_request_synthesizer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_workflow_get200_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_id_workflow_get404_response.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/agent_template_get200_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_get200_response_data_inner.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_delete200_response.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_delete400_response.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_get200_response.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_get400_response.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_get403_response.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_get404_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_delete_request.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_get200_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_get400_response.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_get500_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_id_members_post_request.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/audience_post200_response_data.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/campaign_get200_response_data.py
RENAMED
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/campaign_id_get200_response.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/campaign_id_get200_response_data.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/conversation_id_get200_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/conversation_outbound_post_request.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/create_agent_from_template_request.py
RENAMED
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/create_agent_request_language.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/internal_server_error_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/knowledgebase_get200_response.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/knowledgebase_id_get200_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/knowledgebase_post201_response.py
RENAMED
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/organization_get200_response.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/organization_get200_response_data.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_get200_response_data.py
RENAMED
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_id_delete404_response.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_post_request_events_inner.py
RENAMED
|
File without changes
|
|
File without changes
|
{smallestai-4.0.1 → smallestai-4.1.0}/smallestai/atoms/models/webhook_subscription_populated.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|