smallestai 2.1.0__py3-none-any.whl → 3.0.0__py3-none-any.whl

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.

Files changed (96) hide show
  1. smallestai/__init__.py +95 -0
  2. smallestai/atoms/__init__.py +182 -0
  3. smallestai/atoms/api/__init__.py +12 -0
  4. smallestai/atoms/api/agent_templates_api.py +573 -0
  5. smallestai/atoms/api/agents_api.py +1465 -0
  6. smallestai/atoms/api/calls_api.py +320 -0
  7. smallestai/atoms/api/campaigns_api.py +1689 -0
  8. smallestai/atoms/api/knowledge_base_api.py +2271 -0
  9. smallestai/atoms/api/logs_api.py +305 -0
  10. smallestai/atoms/api/organization_api.py +285 -0
  11. smallestai/atoms/api/user_api.py +285 -0
  12. smallestai/atoms/api_client.py +797 -0
  13. smallestai/atoms/api_response.py +21 -0
  14. smallestai/atoms/atoms_client.py +560 -0
  15. smallestai/atoms/configuration.py +582 -0
  16. smallestai/atoms/exceptions.py +216 -0
  17. smallestai/atoms/models/__init__.py +72 -0
  18. smallestai/atoms/models/agent_dto.py +130 -0
  19. smallestai/atoms/models/agent_dto_language.py +91 -0
  20. smallestai/atoms/models/agent_dto_synthesizer.py +99 -0
  21. smallestai/atoms/models/agent_dto_synthesizer_voice_config.py +111 -0
  22. smallestai/atoms/models/api_response.py +89 -0
  23. smallestai/atoms/models/bad_request_error_response.py +89 -0
  24. smallestai/atoms/models/create_agent_from_template200_response.py +89 -0
  25. smallestai/atoms/models/create_agent_from_template_request.py +91 -0
  26. smallestai/atoms/models/create_agent_request.py +113 -0
  27. smallestai/atoms/models/create_agent_request_language.py +124 -0
  28. smallestai/atoms/models/create_agent_request_language_synthesizer.py +110 -0
  29. smallestai/atoms/models/create_agent_request_language_synthesizer_voice_config.py +137 -0
  30. smallestai/atoms/models/create_campaign200_response.py +93 -0
  31. smallestai/atoms/models/create_campaign200_response_data.py +106 -0
  32. smallestai/atoms/models/create_campaign200_response_inner.py +106 -0
  33. smallestai/atoms/models/create_campaign201_response.py +93 -0
  34. smallestai/atoms/models/create_campaign201_response_data.py +104 -0
  35. smallestai/atoms/models/create_campaign_request.py +93 -0
  36. smallestai/atoms/models/create_knowledge_base201_response.py +89 -0
  37. smallestai/atoms/models/create_knowledge_base_request.py +89 -0
  38. smallestai/atoms/models/delete_agent200_response.py +87 -0
  39. smallestai/atoms/models/get_agent_by_id200_response.py +93 -0
  40. smallestai/atoms/models/get_agent_templates200_response.py +97 -0
  41. smallestai/atoms/models/get_agent_templates200_response_data_inner.py +97 -0
  42. smallestai/atoms/models/get_agents200_response.py +93 -0
  43. smallestai/atoms/models/get_agents200_response_data.py +101 -0
  44. smallestai/atoms/models/get_campaign_by_id200_response.py +93 -0
  45. smallestai/atoms/models/get_campaign_by_id200_response_data.py +114 -0
  46. smallestai/atoms/models/get_campaigns200_response.py +97 -0
  47. smallestai/atoms/models/get_campaigns200_response_data_inner.py +118 -0
  48. smallestai/atoms/models/get_campaigns200_response_data_inner_agent.py +89 -0
  49. smallestai/atoms/models/get_campaigns200_response_data_inner_audience.py +89 -0
  50. smallestai/atoms/models/get_campaigns_request.py +89 -0
  51. smallestai/atoms/models/get_conversation200_response.py +93 -0
  52. smallestai/atoms/models/get_conversation200_response_data.py +125 -0
  53. smallestai/atoms/models/get_conversation_logs200_response.py +93 -0
  54. smallestai/atoms/models/get_conversation_logs200_response_data.py +125 -0
  55. smallestai/atoms/models/get_current_user200_response.py +93 -0
  56. smallestai/atoms/models/get_current_user200_response_data.py +99 -0
  57. smallestai/atoms/models/get_knowledge_base_by_id200_response.py +93 -0
  58. smallestai/atoms/models/get_knowledge_base_items200_response.py +97 -0
  59. smallestai/atoms/models/get_knowledge_bases200_response.py +97 -0
  60. smallestai/atoms/models/get_organization200_response.py +93 -0
  61. smallestai/atoms/models/get_organization200_response_data.py +105 -0
  62. smallestai/atoms/models/get_organization200_response_data_members_inner.py +89 -0
  63. smallestai/atoms/models/get_organization200_response_data_subscription.py +87 -0
  64. smallestai/atoms/models/internal_server_error_response.py +89 -0
  65. smallestai/atoms/models/knowledge_base_dto.py +93 -0
  66. smallestai/atoms/models/knowledge_base_item_dto.py +124 -0
  67. smallestai/atoms/models/start_outbound_call200_response.py +93 -0
  68. smallestai/atoms/models/start_outbound_call200_response_data.py +87 -0
  69. smallestai/atoms/models/start_outbound_call_request.py +89 -0
  70. smallestai/atoms/models/unauthorized_error_reponse.py +89 -0
  71. smallestai/atoms/models/update_agent200_response.py +89 -0
  72. smallestai/atoms/models/update_agent_request.py +119 -0
  73. smallestai/atoms/models/update_agent_request_language.py +99 -0
  74. smallestai/atoms/models/update_agent_request_synthesizer.py +110 -0
  75. smallestai/atoms/models/update_agent_request_synthesizer_voice_config.py +137 -0
  76. smallestai/atoms/models/update_agent_request_synthesizer_voice_config_one_of.py +111 -0
  77. smallestai/atoms/models/update_agent_request_synthesizer_voice_config_one_of1.py +99 -0
  78. smallestai/atoms/models/upload_text_to_knowledge_base_request.py +89 -0
  79. smallestai/atoms/py.typed +0 -0
  80. smallestai/atoms/rest.py +258 -0
  81. smallestai/waves/__init__.py +5 -0
  82. smallest/async_tts.py → smallestai/waves/async_waves_client.py +60 -47
  83. smallestai/waves/stream_tts.py +272 -0
  84. {smallest → smallestai/waves}/utils.py +8 -8
  85. smallest/tts.py → smallestai/waves/waves_client.py +58 -46
  86. {smallestai-2.1.0.dist-info → smallestai-3.0.0.dist-info}/METADATA +194 -43
  87. smallestai-3.0.0.dist-info/RECORD +92 -0
  88. {smallestai-2.1.0.dist-info → smallestai-3.0.0.dist-info}/WHEEL +1 -1
  89. smallestai-3.0.0.dist-info/top_level.txt +1 -0
  90. smallest/__init__.py +0 -5
  91. smallest/stream_tts.py +0 -161
  92. smallestai-2.1.0.dist-info/RECORD +0 -12
  93. smallestai-2.1.0.dist-info/top_level.txt +0 -1
  94. {smallest → smallestai/waves}/exceptions.py +0 -0
  95. {smallest → smallestai/waves}/models.py +0 -0
  96. {smallestai-2.1.0.dist-info → smallestai-3.0.0.dist-info/licenses}/LICENSE +0 -0
@@ -1,11 +1,11 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: smallestai
3
- Version: 2.1.0
3
+ Version: 3.0.0
4
4
  Summary: Official Python client for the Smallest AI API
5
5
  Author-email: Smallest <support@smallest.ai>
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/smallest-inc/smallest-python-sdk
8
- Keywords: smallest,smallest.ai,tts,text-to-speech
8
+ Keywords: smallest,smallest.ai,tts,text-to-speech,waves,atoms
9
9
  Classifier: Intended Audience :: Developers
10
10
  Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Programming Language :: Python :: 3
@@ -15,15 +15,24 @@ License-File: LICENSE
15
15
  Requires-Dist: aiohttp
16
16
  Requires-Dist: aiofiles
17
17
  Requires-Dist: requests
18
- Requires-Dist: sacremoses
19
18
  Requires-Dist: pydub
19
+ Requires-Dist: urllib3<3.0.0,>=1.25.3
20
+ Requires-Dist: python-dateutil>=2.8.2
21
+ Requires-Dist: pydantic>=2
22
+ Requires-Dist: typing-extensions>=4.7.1
20
23
  Provides-Extra: test
21
24
  Requires-Dist: jiwer; extra == "test"
22
25
  Requires-Dist: httpx; extra == "test"
23
- Requires-Dist: pytest; extra == "test"
26
+ Requires-Dist: pytest>=7.2.1; extra == "test"
24
27
  Requires-Dist: pytest-asyncio; extra == "test"
25
28
  Requires-Dist: deepgram-sdk; extra == "test"
26
29
  Requires-Dist: python-dotenv; extra == "test"
30
+ Requires-Dist: pytest-cov>=2.8.1; extra == "test"
31
+ Requires-Dist: tox>=3.9.0; extra == "test"
32
+ Requires-Dist: flake8>=4.0.0; extra == "test"
33
+ Requires-Dist: types-python-dateutil>=2.8.19.14; extra == "test"
34
+ Requires-Dist: mypy>=1.5; extra == "test"
35
+ Dynamic: license-file
27
36
 
28
37
  ![image](https://i.imgur.com/TJ2tT4g.png)
29
38
 
@@ -31,7 +40,6 @@ Requires-Dist: python-dotenv; extra == "test"
31
40
  <div align="center">
32
41
  <a href="https://twitter.com/smallest_AI">
33
42
  <img src="https://img.shields.io/twitter/url/https/twitter.com/smallest_AI.svg?style=social&label=Follow%20smallest_AI" alt="Twitter">
34
- </a>
35
43
  <a href="https://discord.gg/ywShEyXHBW">
36
44
  <img src="https://dcbadge.vercel.app/api/server/ywShEyXHBW?style=flat" alt="Discord">
37
45
  </a>
@@ -47,25 +55,30 @@ Requires-Dist: python-dotenv; extra == "test"
47
55
 
48
56
  Smallest AI builds high-speed multi-lingual voice models tailored for real-time applications, achieving ultra-realistic audio generation in as fast as ~100 milliseconds for 10 seconds of audio. With this sdk, you can easily convert text into high-quality audio with humanlike expressiveness.
49
57
 
50
- Currently, the library supports direct synthesis and the ability to synthesize streamed LLM output, both synchronously and asynchronously.
58
+ Currently, the WavesClient supports direct synthesis and the ability to synthesize streamed LLM output, both synchronously and asynchronously.
51
59
 
52
60
  ## Table of Contents
53
61
 
54
62
  - [Installation](#installation)
55
63
  - [Get the API Key](#get-the-api-key)
56
- - [Best Practices for Input Text](#best-practices-for-input-text)
57
- - [Examples](#examples)
58
- - [Synchronous](#Synchronous)
59
- - [Aynchronous](#Synchronous)
60
- - [LLM to Speech](#llm-to-speech)
61
- - [Add your Voice](#add-your-voice)
62
- - [Synchronously](#add-synchronously)
63
- - [Asynchronously](#add-asynchronously)
64
- - [Delete your Voice](#delete-your-voice)
65
- - [Synchronously](#delete-synchronously)
66
- - [Asynchronously](#delete-asynchronously)
67
- - [Available Methods](#available-methods)
68
- - [Technical Note: WAV Headers in Streaming Audio](#technical-note-wav-headers-in-streaming-audio)
64
+ - [Atoms Documentation](#atoms-documentation)
65
+ - [Getting Started](#getting-started)
66
+ - [Documentation for API Endpoints](#documentation-for-api-endpoints)
67
+ - [Documentation For Models](#documentation-for-models)
68
+ - [Waves Documentation](#waves-documentation)
69
+ - [Best Practices for Input Text](#best-practices-for-input-text)
70
+ - [Examples](#examples)
71
+ - [Synchronous](#synchronous)
72
+ - [Asynchronous](#asynchronous)
73
+ - [LLM to Speech](#llm-to-speech)
74
+ - [Add your Voice](#add-your-voice)
75
+ - [Synchronously](#add-synchronously)
76
+ - [Asynchronously](#add-asynchronously)
77
+ - [Delete your Voice](#delete-your-voice)
78
+ - [Synchronously](#delete-synchronously)
79
+ - [Asynchronously](#delete-asynchronously)
80
+ - [Available Methods](#available-methods)
81
+ - [Technical Note: WAV Headers in Streaming Audio](#technical-note-wav-headers-in-streaming-audio)
69
82
 
70
83
  ## Installation
71
84
 
@@ -78,24 +91,162 @@ When using an SDK in your application, make sure to pin to at least the major ve
78
91
 
79
92
  ## Get the API Key
80
93
 
81
- 1. Visit [waves.smallest.ai](https://waves.smallest.ai/) and sign up for an account or log in if you already have an account.
82
- 2. Navigate to `API Key` tab in your account dashboard.
94
+ 1. Visit [console.smallest.ai](https://console.smallest.ai//) and sign up for an account or log in if you already have an account.
95
+ 2. Navigate to `API Keys` tab in your account dashboard.
83
96
  3. Create a new API Key and copy it.
84
97
  4. Export the API Key in your environment with the name `SMALLEST_API_KEY`, ensuring that your application can access it securely for authentication.
85
98
 
86
99
 
87
- ## Examples
100
+ ## Atoms Documentation
101
+
102
+ ### Getting Started
103
+
104
+ Please follow the [installation procedure](#installation--usage) and then run the following:
105
+
106
+ ```python
107
+ import smallestai.atoms
108
+ from smallestai.atoms.rest import ApiException
109
+ from pprint import pprint
110
+
111
+ # Defining the host is optional and defaults to https://atoms-api.smallest.ai/api/v1
112
+ # See configuration.py for a list of all supported configuration parameters.
113
+ configuration = atoms.Configuration(
114
+ host = "https://atoms-api.smallest.ai/api/v1"
115
+ )
116
+
117
+ # The client must configure the authentication and authorization parameters
118
+ # in accordance with the API server security policy.
119
+ # Examples for each auth method are provided below, use the example that
120
+ # satisfies your auth use case.
121
+
122
+ # Configure Bearer authorization (JWT): BearerAuth
123
+ configuration = atoms.Configuration(
124
+ access_token = os.environ["BEARER_TOKEN"]
125
+ )
126
+
127
+ # Enter a context with an instance of the API client
128
+ with atoms.ApiClient(configuration) as api_client:
129
+ # Create an instance of the API class
130
+ api_instance = atoms.AgentTemplatesApi(api_client)
131
+ create_agent_from_template_request = atoms.CreateAgentFromTemplateRequest()
132
+
133
+ try:
134
+ # Create agent from template
135
+ api_response = api_instance.create_agent_from_template(create_agent_from_template_request)
136
+ print("The response of AgentTemplatesApi->create_agent_from_template:\n")
137
+ pprint(api_response)
138
+ except ApiException as e:
139
+ print("Exception when calling AgentTemplatesApi->create_agent_from_template: %s\n" % e)
140
+ ```
88
141
 
89
- ### Synchronous
142
+ ### Documentation for API Endpoints
143
+
144
+ All URIs are relative to *https://atoms-api.smallest.ai/api/v1*
145
+
146
+ Class | Method | HTTP request | Description
147
+ ------------ | ------------- | ------------- | -------------
148
+ *AgentTemplatesApi* | [**create_agent_from_template**](docs/atoms/AgentTemplatesApi.md#create_agent_from_template) | **POST** /agent/from-template | Create agent from template
149
+ *AgentTemplatesApi* | [**get_agent_templates**](docs/atoms/AgentTemplatesApi.md#get_agent_templates) | **GET** /agent/template | Get agent templates
150
+ *AgentsApi* | [**create_agent**](docs/atoms/AgentsApi.md#create_agent) | **POST** /agent | Create a new agent
151
+ *AgentsApi* | [**delete_agent**](docs/atoms/AgentsApi.md#delete_agent) | **DELETE** /agent/{id} | Delete an agent
152
+ *AgentsApi* | [**get_agent_by_id**](docs/atoms/AgentsApi.md#get_agent_by_id) | **GET** /agent/{id} | Get agent by ID
153
+ *AgentsApi* | [**get_agents**](docs/atoms/AgentsApi.md#get_agents) | **GET** /agent | Get all agents
154
+ *AgentsApi* | [**update_agent**](docs/atoms/AgentsApi.md#update_agent) | **PATCH** /agent/{id} | Update an agent
155
+ *CallsApi* | [**start_outbound_call**](docs/atoms/CallsApi.md#start_outbound_call) | **POST** /conversation/outbound | Start an outbound call
156
+ *CampaignsApi* | [**create_campaign**](docs/atoms/CampaignsApi.md#create_campaign) | **POST** /campaign | Create a campaign
157
+ *CampaignsApi* | [**delete_campaign**](docs/atoms/CampaignsApi.md#delete_campaign) | **DELETE** /campaign/{id} | Delete a campaign
158
+ *CampaignsApi* | [**get_campaign_by_id**](docs/atoms/CampaignsApi.md#get_campaign_by_id) | **GET** /campaign/{id} | Get a campaign
159
+ *CampaignsApi* | [**get_campaigns**](docs/atoms/CampaignsApi.md#get_campaigns) | **GET** /campaign | Retrieve all campaigns
160
+ *CampaignsApi* | [**pause_campaign**](docs/atoms/CampaignsApi.md#pause_campaign) | **POST** /campaign/{id}/pause | Pause a campaign
161
+ *CampaignsApi* | [**start_campaign**](docs/atoms/CampaignsApi.md#start_campaign) | **POST** /campaign/{id}/start | Start a campaign
162
+ *KnowledgeBaseApi* | [**create_knowledge_base**](docs/atoms/KnowledgeBaseApi.md#create_knowledge_base) | **POST** /knowledgebase | Create a knowledge base
163
+ *KnowledgeBaseApi* | [**delete_knowledge_base**](docs/atoms/KnowledgeBaseApi.md#delete_knowledge_base) | **DELETE** /knowledgebase/{id} | Delete a knowledge base
164
+ *KnowledgeBaseApi* | [**delete_knowledge_base_item**](docs/atoms/KnowledgeBaseApi.md#delete_knowledge_base_item) | **DELETE** /knowledgebase/{knowledgeBaseId}/items/{knowledgeBaseItemId} | Delete a knowledge base item
165
+ *KnowledgeBaseApi* | [**get_knowledge_base_by_id**](docs/atoms/KnowledgeBaseApi.md#get_knowledge_base_by_id) | **GET** /knowledgebase/{id} | Get a knowledge base
166
+ *KnowledgeBaseApi* | [**get_knowledge_base_items**](docs/atoms/KnowledgeBaseApi.md#get_knowledge_base_items) | **GET** /knowledgebase/{id}/items | Get all knowledge base items
167
+ *KnowledgeBaseApi* | [**get_knowledge_bases**](docs/atoms/KnowledgeBaseApi.md#get_knowledge_bases) | **GET** /knowledgebase | Get all knowledge bases
168
+ *KnowledgeBaseApi* | [**upload_media_to_knowledge_base**](docs/atoms/KnowledgeBaseApi.md#upload_media_to_knowledge_base) | **POST** /knowledgebase/{id}/items/upload-media | Upload a media to a knowledge base
169
+ *KnowledgeBaseApi* | [**upload_text_to_knowledge_base**](docs/atoms/KnowledgeBaseApi.md#upload_text_to_knowledge_base) | **POST** /knowledgebase/{id}/items/upload-text | Upload a text to a knowledge base
170
+ *LogsApi* | [**get_conversation_logs**](docs/atoms/LogsApi.md#get_conversation_logs) | **GET** /conversation/{id} | Get conversation logs
171
+ *OrganizationApi* | [**get_organization**](docs/atoms/OrganizationApi.md#get_organization) | **GET** /organization | Get organization details
172
+ *UserApi* | [**get_current_user**](docs/atoms/UserApi.md#get_current_user) | **GET** /user | Get user details
173
+
174
+ ### Documentation For Models
175
+
176
+ - [AgentDTO](docs/atoms/AgentDTO.md)
177
+ - [AgentDTOLanguage](docs/atoms/AgentDTOLanguage.md)
178
+ - [AgentDTOSynthesizer](docs/atoms/AgentDTOSynthesizer.md)
179
+ - [AgentDTOSynthesizerVoiceConfig](docs/atoms/AgentDTOSynthesizerVoiceConfig.md)
180
+ - [ApiResponse](docs/atoms/ApiResponse.md)
181
+ - [BadRequestErrorResponse](docs/atoms/BadRequestErrorResponse.md)
182
+ - [CreateAgentFromTemplate200Response](docs/atoms/CreateAgentFromTemplate200Response.md)
183
+ - [CreateAgentFromTemplateRequest](docs/atoms/CreateAgentFromTemplateRequest.md)
184
+ - [CreateAgentRequest](docs/atoms/CreateAgentRequest.md)
185
+ - [CreateAgentRequestLanguage](docs/atoms/CreateAgentRequestLanguage.md)
186
+ - [CreateAgentRequestLanguageSynthesizer](docs/atoms/CreateAgentRequestLanguageSynthesizer.md)
187
+ - [CreateAgentRequestLanguageSynthesizerVoiceConfig](docs/atoms/CreateAgentRequestLanguageSynthesizerVoiceConfig.md)
188
+ - [CreateCampaign201Response](docs/atoms/CreateCampaign201Response.md)
189
+ - [CreateCampaign201ResponseData](docs/atoms/CreateCampaign201ResponseData.md)
190
+ - [CreateCampaignRequest](docs/atoms/CreateCampaignRequest.md)
191
+ - [CreateKnowledgeBase201Response](docs/atoms/CreateKnowledgeBase201Response.md)
192
+ - [CreateKnowledgeBaseRequest](docs/atoms/CreateKnowledgeBaseRequest.md)
193
+ - [DeleteAgent200Response](docs/atoms/DeleteAgent200Response.md)
194
+ - [GetAgentById200Response](docs/atoms/GetAgentById200Response.md)
195
+ - [GetAgentTemplates200Response](docs/atoms/GetAgentTemplates200Response.md)
196
+ - [GetAgentTemplates200ResponseDataInner](docs/atoms/GetAgentTemplates200ResponseDataInner.md)
197
+ - [GetAgents200Response](docs/atoms/GetAgents200Response.md)
198
+ - [GetAgents200ResponseData](docs/atoms/GetAgents200ResponseData.md)
199
+ - [GetCampaignById200Response](docs/atoms/GetCampaignById200Response.md)
200
+ - [GetCampaignById200ResponseData](docs/atoms/GetCampaignById200ResponseData.md)
201
+ - [GetCampaigns200Response](docs/atoms/GetCampaigns200Response.md)
202
+ - [GetCampaigns200ResponseDataInner](docs/atoms/GetCampaigns200ResponseDataInner.md)
203
+ - [GetCampaigns200ResponseDataInnerAgent](docs/atoms/GetCampaigns200ResponseDataInnerAgent.md)
204
+ - [GetCampaigns200ResponseDataInnerAudience](docs/atoms/GetCampaigns200ResponseDataInnerAudience.md)
205
+ - [GetCampaignsRequest](docs/atoms/GetCampaignsRequest.md)
206
+ - [GetConversationLogs200Response](docs/atoms/GetConversationLogs200Response.md)
207
+ - [GetConversationLogs200ResponseData](docs/atoms/GetConversationLogs200ResponseData.md)
208
+ - [GetCurrentUser200Response](docs/atoms/GetCurrentUser200Response.md)
209
+ - [GetCurrentUser200ResponseData](docs/atoms/GetCurrentUser200ResponseData.md)
210
+ - [GetKnowledgeBaseById200Response](docs/atoms/GetKnowledgeBaseById200Response.md)
211
+ - [GetKnowledgeBaseItems200Response](docs/atoms/GetKnowledgeBaseItems200Response.md)
212
+ - [GetKnowledgeBases200Response](docs/atoms/GetKnowledgeBases200Response.md)
213
+ - [GetOrganization200Response](docs/atoms/GetOrganization200Response.md)
214
+ - [GetOrganization200ResponseData](docs/atoms/GetOrganization200ResponseData.md)
215
+ - [GetOrganization200ResponseDataMembersInner](docs/atoms/GetOrganization200ResponseDataMembersInner.md)
216
+ - [GetOrganization200ResponseDataSubscription](docs/atoms/GetOrganization200ResponseDataSubscription.md)
217
+ - [InternalServerErrorResponse](docs/atoms/InternalServerErrorResponse.md)
218
+ - [KnowledgeBaseDTO](docs/atoms/KnowledgeBaseDTO.md)
219
+ - [KnowledgeBaseItemDTO](docs/atoms/KnowledgeBaseItemDTO.md)
220
+ - [StartOutboundCall200Response](docs/atoms/StartOutboundCall200Response.md)
221
+ - [StartOutboundCall200ResponseData](docs/atoms/StartOutboundCall200ResponseData.md)
222
+ - [StartOutboundCallRequest](docs/atoms/StartOutboundCallRequest.md)
223
+ - [UnauthorizedErrorReponse](docs/atoms/UnauthorizedErrorReponse.md)
224
+ - [UpdateAgent200Response](docs/atoms/UpdateAgent200Response.md)
225
+ - [UpdateAgentRequest](docs/atoms/UpdateAgentRequest.md)
226
+ - [UpdateAgentRequestLanguage](docs/atoms/UpdateAgentRequestLanguage.md)
227
+ - [UpdateAgentRequestSynthesizer](docs/atoms/UpdateAgentRequestSynthesizer.md)
228
+ - [UpdateAgentRequestSynthesizerVoiceConfig](docs/atoms/UpdateAgentRequestSynthesizerVoiceConfig.md)
229
+ - [UpdateAgentRequestSynthesizerVoiceConfigOneOf](docs/atoms/UpdateAgentRequestSynthesizerVoiceConfigOneOf.md)
230
+ - [UpdateAgentRequestSynthesizerVoiceConfigOneOf1](docs/atoms/UpdateAgentRequestSynthesizerVoiceConfigOneOf1.md)
231
+ - [UploadTextToKnowledgeBaseRequest](docs/atoms/UploadTextToKnowledgeBaseRequest.md)
232
+
233
+ ## Waves Documentation
234
+
235
+ ### Best Practices for Input Text
236
+
237
+ ### Examples
238
+
239
+ #### Synchronous
90
240
  A synchronous text-to-speech synthesis client.
91
241
 
92
242
  **Basic Usage:**
93
243
  ```python
94
- from smallest import Smallest
244
+
245
+ from smallestai.waves import WavesClient
95
246
 
96
247
  def main():
97
- client = Smallest(api_key="SMALLEST_API_KEY")
98
- client.synthesize(
248
+ waves_client = WavesClient(api_key="SMALLEST_API_KEY")
249
+ waves_client.synthesize(
99
250
  text="Hello, this is a test for sync synthesis function.",
100
251
  save_as="sync_synthesize.wav"
101
252
  )
@@ -128,17 +279,17 @@ client.synthesize(
128
279
  ```
129
280
 
130
281
 
131
- ### Asynchronous
282
+ #### Asynchronous
132
283
  Asynchronous text-to-speech synthesis client.
133
284
 
134
285
  **Basic Usage:**
135
286
  ```python
136
287
  import asyncio
137
288
  import aiofiles
138
- from smallest import AsyncSmallest
289
+ import smallestai
139
290
 
140
291
  async def main():
141
- client = AsyncSmallest(api_key="SMALLEST_API_KEY")
292
+ client = smallestai.waves.AsyncWavesClient(api_key="SMALLEST_API_KEY")
142
293
  async with client as tts:
143
294
  audio_bytes = await tts.synthesize("Hello, this is a test of the async synthesis function.")
144
295
  async with aiofiles.open("async_synthesize.wav", "wb") as f:
@@ -187,11 +338,11 @@ audio_bytes = await tts.synthesize(
187
338
  )
188
339
  ```
189
340
 
190
- ### LLM to Speech
341
+ #### LLM to Speech
191
342
 
192
343
  The `TextToAudioStream` class provides real-time text-to-speech processing, converting streaming text into audio output. It's particularly useful for applications like voice assistants, live captioning, or interactive chatbots that require immediate audio feedback from text generation. Supports both synchronous and asynchronous TTS instance.
193
344
 
194
- #### Stream through a WebSocket
345
+ ##### Stream through a WebSocket
195
346
 
196
347
  ```python
197
348
  import asyncio
@@ -242,7 +393,7 @@ if __name__ == "__main__":
242
393
  asyncio.run(main())
243
394
  ```
244
395
 
245
- #### Save to a File
396
+ ##### Save to a File
246
397
  ```python
247
398
  import wave
248
399
  import asyncio
@@ -307,10 +458,10 @@ The processor yields raw audio data chunks without WAV headers for streaming eff
307
458
  - Streamed over a network
308
459
  - Further processed as needed
309
460
 
310
- ## Add your Voice
461
+ #### Add your Voice
311
462
  The Smallest AI SDK allows you to clone your voice by uploading an audio file. This feature is available both synchronously and asynchronously, making it flexible for different use cases. Below are examples of how to use this functionality.
312
463
 
313
- ### Add Synchronously
464
+ ##### Add Synchronously
314
465
  ```python
315
466
  from smallest import Smallest
316
467
 
@@ -323,7 +474,7 @@ if __name__ == "__main__":
323
474
  main()
324
475
  ```
325
476
 
326
- ### Add Asynchronously
477
+ ##### Add Asynchronously
327
478
  ```python
328
479
  import asyncio
329
480
  from smallest import AsyncSmallest
@@ -337,10 +488,10 @@ if __name__ == "__main__":
337
488
  asyncio.run(main())
338
489
  ```
339
490
 
340
- ## Delete your Voice
491
+ #### Delete your Voice
341
492
  The Smallest AI SDK allows you to delete your cloned voice. This feature is available both synchronously and asynchronously, making it flexible for different use cases. Below are examples of how to use this functionality.
342
493
 
343
- ### Delete Synchronously
494
+ ##### Delete Synchronously
344
495
  ```python
345
496
  from smallest import Smallest
346
497
 
@@ -353,7 +504,7 @@ if __name__ == "__main__":
353
504
  main()
354
505
  ```
355
506
 
356
- ### Delete Asynchronously
507
+ ##### Delete Asynchronously
357
508
  ```python
358
509
  import asyncio
359
510
  from smallest import AsyncSmallest
@@ -367,7 +518,7 @@ if __name__ == "__main__":
367
518
  asyncio.run(main())
368
519
  ```
369
520
 
370
- ## Available Methods
521
+ #### Available Methods
371
522
 
372
523
  ```python
373
524
  from smallest import Smallest
@@ -380,18 +531,18 @@ print(f"Available Voices: {client.get_cloned_voices()}")
380
531
  print(f"Available Models: {client.get_models()}")
381
532
  ```
382
533
 
383
- ## Technical Note: WAV Headers in Streaming Audio
534
+ #### Technical Note: WAV Headers in Streaming Audio
384
535
 
385
536
  When implementing audio streaming with chunks of synthesized speech, WAV headers are omitted from individual chunks because:
386
537
 
387
- #### Technical Issues
538
+ ##### Technical Issues
388
539
  - Each WAV header contains metadata about the entire audio file.
389
540
  - Multiple headers would make chunks appear as separate audio files and add redundancy.
390
541
  - Headers contain file-specific data (like total size) that's invalid for chunks.
391
542
  - Sequential playback of chunks with headers causes audio artifacts (pop sounds) when concatenating or playing audio sequentially.
392
543
  - Audio players would try to reinitialize audio settings for each chunk.
393
544
 
394
- ### Best Practices for Audio Streaming
545
+ ##### Best Practices for Audio Streaming
395
546
  1. Stream raw PCM audio data without headers
396
547
  2. Add a single WAV header only when:
397
548
  - Saving the complete stream to a file
@@ -0,0 +1,92 @@
1
+ smallestai/__init__.py,sha256=zVO8iaNFVgNErxEt58AuB1npc7MR8x8Oi9A-Z2t8Q6w,2624
2
+ smallestai/atoms/__init__.py,sha256=cn5_9tVsUwFQ_zdAZv263P4ow4N7dxRWCYAz82GjwuI,9342
3
+ smallestai/atoms/api_client.py,sha256=EcyN6nFp9U4u8TPJx3a9ZvbM2T4a9xrHGopQGLZuJpw,27448
4
+ smallestai/atoms/api_response.py,sha256=eMxw1mpmJcoGZ3gs9z6jM4oYoZ10Gjk333s9sKxGv7s,652
5
+ smallestai/atoms/atoms_client.py,sha256=iQEPbnjRaAWo-RFwqUDrYF5h3EMnZYm5b4J7wyVrlpc,23496
6
+ smallestai/atoms/configuration.py,sha256=Q9p86XIcH5dMXJmIus7ncra3DgAGlSejdBMUqq4ALuE,18340
7
+ smallestai/atoms/exceptions.py,sha256=bQu7s-V5DH5g-Vi1N7uSYPuO_-JYXlW2TfHFOL04KAo,6433
8
+ smallestai/atoms/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ smallestai/atoms/rest.py,sha256=rT86MlRRO9lPXDH6VuEaUwMyeNl5caRd00LubxM7N6s,9432
10
+ smallestai/atoms/api/__init__.py,sha256=9jxkzMH4nqlcBYyH3ixdJkwF3ZqgmBHL3h6LtVUGTYs,520
11
+ smallestai/atoms/api/agent_templates_api.py,sha256=7_jX4BNFZ6eRTJe2o8diyxEpro2HYB6Lioa0zA7_gRM,23365
12
+ smallestai/atoms/api/agents_api.py,sha256=0iYOxjQur0S74wGbIj1QiKgtW_M8Ei1KaSlbDyIydI0,56346
13
+ smallestai/atoms/api/calls_api.py,sha256=E0nFzkI1hiNH4KWE68S7wob-JnuYcj1KqGK7oGHsg8o,12511
14
+ smallestai/atoms/api/campaigns_api.py,sha256=D5HGDHd2U1lhNMKPn-TMUDVAZMSOXYzxdgbj97x3L7Y,64720
15
+ smallestai/atoms/api/knowledge_base_api.py,sha256=WezdHQoliU8T-PsjGNk2IYyq6u0aq-6e-nzb4XiwvhE,89734
16
+ smallestai/atoms/api/logs_api.py,sha256=1sojnF-08zKtMxSpcHOdentghj-1JoPqWTXH4cWbzzY,11830
17
+ smallestai/atoms/api/organization_api.py,sha256=Bduw_YTK6ioHKE8HTqbRVp7d_ZbDu7loXYprLSHqCrU,10608
18
+ smallestai/atoms/api/user_api.py,sha256=76zvKzMYCmROs_HQWAq0S0XCfzNB5Yf1GIzdeS60eEM,10562
19
+ smallestai/atoms/models/__init__.py,sha256=s5DxDG3njaXD34bQsdm3Qo31PwBaO79MtpNTcnQvP7A,5787
20
+ smallestai/atoms/models/agent_dto.py,sha256=5wW1Uerre-tDH_VOiKRoTeq2vzlF2pmB73QRmFNWCeg,5844
21
+ smallestai/atoms/models/agent_dto_language.py,sha256=6NQs9kVvWz0imE01mdWwwyLTnmeRsnUezJhkdKOnhbw,2934
22
+ smallestai/atoms/models/agent_dto_synthesizer.py,sha256=wlrnKMN3kF5azpfH-tmfuAKEPqwI7u7Ejoi7CL-eGw8,3850
23
+ smallestai/atoms/models/agent_dto_synthesizer_voice_config.py,sha256=zebSoOTv_u11POqKHM3WreKYWqr7QxGcMzLeINerkRo,3786
24
+ smallestai/atoms/models/api_response.py,sha256=2eCfbeDCg695blD8QKVacK1mwPIQC_0qXxJWE2kY3OI,2546
25
+ smallestai/atoms/models/bad_request_error_response.py,sha256=zkgU6NeDxddUzhAV0FunTRWrYsh6ex5HF_AuN_UuQhA,2614
26
+ smallestai/atoms/models/create_agent_from_template200_response.py,sha256=sgbUaQort1kw2uiiVZFQ6orqQioA2M0hNaMPP8KCLbI,2709
27
+ smallestai/atoms/models/create_agent_from_template_request.py,sha256=P-UOKqf-otmUoIhscdCKo1oSFFEsRQ21Ar1hy_BFt04,3067
28
+ smallestai/atoms/models/create_agent_request.py,sha256=JQEKniyPw-sshYB-LYXhdtt0Q8DmKeEh83XAnKgcCY8,4878
29
+ smallestai/atoms/models/create_agent_request_language.py,sha256=cZpex3ZXlMfYKYW1L8oLrlhsk94OX8ChXhXtTrU-a-g,5126
30
+ smallestai/atoms/models/create_agent_request_language_synthesizer.py,sha256=vupUNUwECH4CUql5yLEY4KdD6Ebcm6wqjg_xpEKClXs,4944
31
+ smallestai/atoms/models/create_agent_request_language_synthesizer_voice_config.py,sha256=2BiCvOWmkbSTm0STn9Hjw30EMDRZ9jAxZ-8HRza83zA,6636
32
+ smallestai/atoms/models/create_campaign200_response.py,sha256=zQyHb2r7A8EyRTMc2X7xVg_exGGLpLGvEYu2RfgcME4,2947
33
+ smallestai/atoms/models/create_campaign200_response_data.py,sha256=8pYT2O-sPyuz7tvLQE5yIfoLdhbB5IxfK0EA7ABkEqA,4302
34
+ smallestai/atoms/models/create_campaign200_response_inner.py,sha256=2HcU5wlCs2y5rpIhj-Fil3gvhFMkGFrJKfAyV85p8MY,4306
35
+ smallestai/atoms/models/create_campaign201_response.py,sha256=RQx7y-VSzAs1mdKt4FxayYWTXnXjE2YcbAQRkwG_ip8,2947
36
+ smallestai/atoms/models/create_campaign201_response_data.py,sha256=L5nw5MRREPh9wMAHyyZ5HCuwqlYHpTSZvn5fggRfcHY,4106
37
+ smallestai/atoms/models/create_campaign_request.py,sha256=SZHMqJLxgXINA2t4kBcz_AzY-Henm0YwSPb_t1Fkr80,2993
38
+ smallestai/atoms/models/create_knowledge_base201_response.py,sha256=vZNJsmAWrwaHJFJkyH9BYSqLy9YSmPYscFiXdma8T-Q,2628
39
+ smallestai/atoms/models/create_knowledge_base_request.py,sha256=kVo0dnKq-7sYXc2-1X4t5twz4X5CwZEBjQTP4Gd-DYo,2602
40
+ smallestai/atoms/models/delete_agent200_response.py,sha256=dSSek6FoWFPCGCTRJCN8w4QkdJY-CaNydX59oLgu5j4,2503
41
+ smallestai/atoms/models/get_agent_by_id200_response.py,sha256=xEcKYD9dr2Awpxxw09MXlPdopRS8g6VX5-b11BxHsas,2853
42
+ smallestai/atoms/models/get_agent_templates200_response.py,sha256=UEOLL0VVfMX157G47Kyhqd8FgAtiWPOEffjLpatIDNw,3175
43
+ smallestai/atoms/models/get_agent_templates200_response_data_inner.py,sha256=9JuxFh5RXFQ_YO_TQAb5RbpcjjLVK-tf_hj8fQ6Vp1E,3438
44
+ smallestai/atoms/models/get_agents200_response.py,sha256=n-eCwPRkqe0xNoYn8ZMBCYfN3bFvGIozbUJTMHrXL24,2907
45
+ smallestai/atoms/models/get_agents200_response_data.py,sha256=TCxAELpPdsaqNoq3PyQp4W_r_f9dhV_uGeX8YbyFBAw,3580
46
+ smallestai/atoms/models/get_campaign_by_id200_response.py,sha256=OyjuzVcL3fcxOau6CqfBS4LrqxyMg0iMSJYJzIhTDbA,2957
47
+ smallestai/atoms/models/get_campaign_by_id200_response_data.py,sha256=y5ntflRNWy0p-IfUSsmSWKjjHcovFfEZT4kzRR6_Jko,4953
48
+ smallestai/atoms/models/get_campaigns200_response.py,sha256=E5GJUwZJSx65ko-DNwK3PGDVUJ49Z7t5V6qQ6oPdzE4,3134
49
+ smallestai/atoms/models/get_campaigns200_response_data_inner.py,sha256=9PVbplsKyCk1TVBQh8XbzQKgfCV1DR7qckiyR5N151s,5409
50
+ smallestai/atoms/models/get_campaigns200_response_data_inner_agent.py,sha256=zzJ6gK8ug44xQgFYecSBMV4FZ5fJ0a9j-KPJQnxmGrQ,2752
51
+ smallestai/atoms/models/get_campaigns200_response_data_inner_audience.py,sha256=OW8PRKI5dKX2fHgTtqpezE-SbrsN13kvB5tqNgjY58U,2770
52
+ smallestai/atoms/models/get_campaigns_request.py,sha256=1tB18zGHiL3M3Yczz1AbCZdrV0POrV07qij3tcbeMTs,2812
53
+ smallestai/atoms/models/get_conversation200_response.py,sha256=XrpU7r2VSzvpdZQy7HCRtQwxRk9sRiM6L6DOvB1FAm4,2955
54
+ smallestai/atoms/models/get_conversation200_response_data.py,sha256=DccoFEcl1vgUsEsR87kzli7SpbKYz_VZPG8C2I-5ZTk,5538
55
+ smallestai/atoms/models/get_conversation_logs200_response.py,sha256=H-6PF1xoTiOGVQLgzY-wNWsx5tZmT-K3t6buL9JEMoQ,2988
56
+ smallestai/atoms/models/get_conversation_logs200_response_data.py,sha256=zzqJXer4nLxLkfX2SPYQVs7PSo8NxQ07MWkMDyZZR0o,5554
57
+ smallestai/atoms/models/get_current_user200_response.py,sha256=rtevZM7dONTycqlP03uKzMAW9AeIdUw_zxR1pUJ3GW0,2948
58
+ smallestai/atoms/models/get_current_user200_response_data.py,sha256=X5IYlJ6HomuiXk-0K1jAbetIEDYFJDRqsVhD-X0qGWs,3713
59
+ smallestai/atoms/models/get_knowledge_base_by_id200_response.py,sha256=r6RaK1IgXqCbdqGHy-t3zEwWqX2WXPr4A0sRrC6PTs4,2918
60
+ smallestai/atoms/models/get_knowledge_base_items200_response.py,sha256=j5fCzR7m-VwzwhD2IkpmZpWNSfPdeZ58ts_lTpPr92s,3121
61
+ smallestai/atoms/models/get_knowledge_bases200_response.py,sha256=0uGGEc5Y8lVZAyeFE6EJDW0vDtjL10Toidd6dXMcvk8,3088
62
+ smallestai/atoms/models/get_organization200_response.py,sha256=6Apea32DyZu7_8rskl8LJiWYGlAoSkQny3GjfjdLtE4,2955
63
+ smallestai/atoms/models/get_organization200_response_data.py,sha256=_5SMwLbQJguadHK2udbbTyS6PvYQQyHD9zqMNtIRxYM,3898
64
+ smallestai/atoms/models/get_organization200_response_data_members_inner.py,sha256=j_6wI3nvx2X3hMHZDtDjpOMsd2LQ3QD1xOtL59PsOn4,2740
65
+ smallestai/atoms/models/get_organization200_response_data_subscription.py,sha256=iNtjC5fAHunAWSo50MJlyssnS1vJGZphjeYMffUICzQ,2620
66
+ smallestai/atoms/models/internal_server_error_response.py,sha256=NOGEBUknHF1zOMhFTsMICk7YO0I0HXzsD4F7ir0LUFs,2630
67
+ smallestai/atoms/models/knowledge_base_dto.py,sha256=r2I3ZM0_VAOjbJNh3KC2qSE5OPqZ8WQXhd5pQeIrmhE,2999
68
+ smallestai/atoms/models/knowledge_base_item_dto.py,sha256=BGNxsYk-m8x2fNAdLsKyvKAfujYydqA80m9eMH9k3FM,4421
69
+ smallestai/atoms/models/start_outbound_call200_response.py,sha256=vHDFP8D6-xw2Z3U-Hlnk_-Oxhc6TUQZFC7MTP_Supq8,2972
70
+ smallestai/atoms/models/start_outbound_call200_response_data.py,sha256=o2knQgPpbyN7fqetsbH9O5noPnf9wYWYQfKpdGHz6qs,2664
71
+ smallestai/atoms/models/start_outbound_call_request.py,sha256=hAb7KYLJlA5FzAcA4v5_JBBua4pj5FvdvmLroKP-wgg,2745
72
+ smallestai/atoms/models/unauthorized_error_reponse.py,sha256=TVV4SKcvCelKOsbKXTa3rL-pSHbMfKk3QZN6bSu1tgE,2618
73
+ smallestai/atoms/models/update_agent200_response.py,sha256=Kj0uArlKlbKT2tbgKQ4caPYWn2y4fCDwF6fuyIFutfE,2661
74
+ smallestai/atoms/models/update_agent_request.py,sha256=c1thNk51LheLxnqtfPsx_hI2cBdEQbXCF1R-23Qu02g,5025
75
+ smallestai/atoms/models/update_agent_request_language.py,sha256=r4mEtJhbfwA-bBcMR4nfpT9qF732kXQh31ZfWVdzpUY,3419
76
+ smallestai/atoms/models/update_agent_request_synthesizer.py,sha256=2fRr23rZTWZegn4bCpGkt0RyoEHRAXA5LaNPFPYRtAo,4887
77
+ smallestai/atoms/models/update_agent_request_synthesizer_voice_config.py,sha256=txpS5fLeD0W1mNPj6gB5P3dNs_okEkBxZ9DWvZrvUs0,6572
78
+ smallestai/atoms/models/update_agent_request_synthesizer_voice_config_one_of.py,sha256=8nGPcJ_CRUlXXjy3vCjpmbHWVBwQo2ebFP1K0MZPAsk,3955
79
+ smallestai/atoms/models/update_agent_request_synthesizer_voice_config_one_of1.py,sha256=9AJxgngoNSMvDbceajIqnG23PY4rw84coTh7yUTNS3c,3487
80
+ smallestai/atoms/models/upload_text_to_knowledge_base_request.py,sha256=Sxg0vRv_naT15odE8fBUeyjwLpEYOmQwGcJuzRRr90A,2587
81
+ smallestai/waves/__init__.py,sha256=Hkq7N2nuz_wS7pC6QeUnIU1MzQnX_nrhfXGpjGSvFhQ,244
82
+ smallestai/waves/async_waves_client.py,sha256=hv9rQ8-ykWuHoAcmZPhwtX_-AAQT4H4G3H8c4BhO5-0,12658
83
+ smallestai/waves/exceptions.py,sha256=nY6I8fCXe2By54CytQ0-i3hFiYtt8TYAKj0g6OYsCjc,585
84
+ smallestai/waves/models.py,sha256=g2e_4nU5P48vyXZandKLWqZC1TkoEGeLvYKqJIqurSI,83
85
+ smallestai/waves/stream_tts.py,sha256=Ppjwp1jXpUSpyNkwCnesMYQbAdyzKLMj_1o1iTb3jaA,10958
86
+ smallestai/waves/utils.py,sha256=pyKx-JM6W112CJ_VvSVGqtlwKT6x2FOWp7X7DcHruXg,3365
87
+ smallestai/waves/waves_client.py,sha256=XKdPVWs-HZDzlxzF1x3cMdJQ_q71ZFS1P5oltzj2KO4,10740
88
+ smallestai-3.0.0.dist-info/licenses/LICENSE,sha256=kK3HNKhN7luQhkjkNWIvy9_gizbEDUM4mSv_HWq9uuM,1068
89
+ smallestai-3.0.0.dist-info/METADATA,sha256=Xepz60WIAImv-i8psOfjsVHGcanaqsZr1Nv0TdPrvk0,25487
90
+ smallestai-3.0.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
91
+ smallestai-3.0.0.dist-info/top_level.txt,sha256=pdJzm1VC2J6RxoobATz45L9U3cki4AFLigsfvETz7Io,11
92
+ smallestai-3.0.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.2)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1 @@
1
+ smallestai
smallest/__init__.py DELETED
@@ -1,5 +0,0 @@
1
- from smallest.tts import Smallest
2
- from smallest.async_tts import AsyncSmallest
3
- from smallest.stream_tts import TextToAudioStream
4
-
5
- __all__ = ["Smallest", "AsyncSmallest", "TextToAudioStream"]
smallest/stream_tts.py DELETED
@@ -1,161 +0,0 @@
1
- import asyncio
2
- from threading import Thread
3
- from queue import Queue, Empty
4
- from typing import AsyncGenerator, Optional, Union
5
-
6
- from smallest.tts import Smallest
7
- from smallest.exceptions import APIError
8
- from smallest.async_tts import AsyncSmallest
9
- from smallest.utils import SENTENCE_END_REGEX
10
-
11
- class TextToAudioStream:
12
- def __init__(
13
- self,
14
- tts_instance: Union[Smallest, AsyncSmallest],
15
- queue_timeout: Optional[float] = 5.0,
16
- max_retries: Optional[int] = 3
17
- ):
18
- """
19
- A real-time text-to-speech processor that converts streaming text into audio output.
20
- Useful for applications requiring immediate audio feedback from text generation,
21
- such as voice assistants, live captioning, or interactive chatbots.
22
-
23
- ⚠️ `add_wav_header` is disabled by default for streaming efficiency. Refer to the README for more information.
24
-
25
- Features:
26
- - Streams audio chunks as soon as text is available.
27
- - Handles both sync and async text-to-speech engines.
28
- - Automatically retries failed synthesis attempts.
29
- - Low latency between text generation and speech output.
30
-
31
- Args:
32
- tts_instance: The text-to-speech engine to use (Smallest or AsyncSmallest)
33
- queue_timeout: How long to wait for new text (seconds, default: 5.0)
34
- max_retries: Number of retry attempts for failed synthesis (default: 3)
35
- """
36
- self.tts_instance = tts_instance
37
- self.tts_instance.opts.add_wav_header = False
38
- self.sentence_end_regex = SENTENCE_END_REGEX
39
- self.queue_timeout = queue_timeout
40
- self.max_retries = max_retries
41
- self.queue = Queue()
42
- self.buffer_size = 250
43
- self.stop_flag = False
44
-
45
- if self.tts_instance.opts.model == 'lightning-large':
46
- self.buffer_size = 140
47
-
48
-
49
- async def _stream_llm_output(self, llm_output: AsyncGenerator[str, None]) -> None:
50
- """
51
- Streams the LLM output, splitting it into chunks based on sentence boundaries
52
- or space characters if no sentence boundary is found before reaching buffer_size.
53
-
54
- Parameters:
55
- - llm_output (AsyncGenerator[str, None]): An async generator yielding LLM output.
56
- """
57
- buffer = ""
58
-
59
- async for chunk in llm_output:
60
- buffer += chunk
61
-
62
- while len(buffer) > self.buffer_size:
63
- chunk_text = buffer[:self.buffer_size]
64
- last_break_index = -1
65
-
66
- # Find last sentence boundary using regex
67
- for i in range(len(chunk_text) - 1, -1, -1):
68
- if self.sentence_end_regex.match(chunk_text[:i + 1]):
69
- last_break_index = i
70
- break
71
-
72
- if last_break_index == -1:
73
- # Fallback to space if no sentence boundary found
74
- last_space = chunk_text.rfind(' ')
75
- if last_space != -1:
76
- last_break_index = last_space
77
- else:
78
- last_break_index = self.buffer_size - 1
79
-
80
- # Add chunk to queue and update buffer
81
- self.queue.put(f'{buffer[:last_break_index + 1].replace("—", " ").strip()} ')
82
- buffer = buffer[last_break_index + 1:].strip()
83
-
84
- # Don't forget the remaining text
85
- if buffer:
86
- self.queue.put(f'{buffer.replace("—", " ").strip()} ')
87
-
88
- self.stop_flag = True
89
-
90
-
91
- def _synthesize_sync(self, sentence: str, retries: int = 0) -> Optional[bytes]:
92
- """Synchronously synthesizes a given sentence."""
93
- try:
94
- return self.tts_instance.synthesize(sentence)
95
- except APIError as e:
96
- if retries < self.max_retries:
97
- return self._synthesize_sync(sentence, retries + 1)
98
- else:
99
- raise APIError(f"Error: {e}. Retries Exhausted, for more information, visit https://waves.smallest.ai/")
100
-
101
-
102
- async def _synthesize_async(self, sentence: str, retries: int = 0) -> Optional[bytes]:
103
- """Asynchronously synthesizes a given sentence."""
104
- try:
105
- return await self.tts_instance.synthesize(sentence)
106
- except APIError as e:
107
- if retries < self.max_retries:
108
- return await self._synthesize_async(sentence, retries + 1)
109
- else:
110
- raise APIError(f"Error: {e}. Retries Exhausted, for more information, visit https://waves.smallest.ai/")
111
-
112
-
113
- async def _run_synthesis(self) -> AsyncGenerator[bytes, None]:
114
- """
115
- Continuously synthesizes sentences from the queue, yielding audio content.
116
- If no sentences are in the queue, it waits until new data is available or streaming is complete.
117
- """
118
- while not self.stop_flag or not self.queue.empty():
119
- try:
120
- sentence = self.queue.get(timeout=self.queue_timeout)
121
- if isinstance(self.tts_instance, AsyncSmallest):
122
- audio_content = await self._synthesize_async(sentence)
123
- else:
124
- loop = asyncio.get_running_loop()
125
- audio_content = await loop.run_in_executor(None, self._synthesize_sync, sentence)
126
-
127
- if audio_content:
128
- yield audio_content
129
- except Empty:
130
- if self.stop_flag:
131
- break
132
- await asyncio.sleep(0.1) # avoid busy waiting if the queue is empty
133
-
134
-
135
- async def process(self, llm_output: AsyncGenerator[str, None]) -> AsyncGenerator[bytes, None]:
136
- """
137
- Convert streaming text into audio in real-time.
138
-
139
- Handles the entire pipeline from receiving text to producing audio,
140
- yielding audio chunks as soon as they're ready.
141
-
142
- Args:
143
- llm_output: An async generator that yields text chunks.
144
-
145
- Yields:
146
- Raw audio data chunks (without WAV headers) that can be:
147
- - Played directly through an audio device
148
- - Saved to a file
149
- - Streamed over a network
150
- - Further processed as needed
151
- """
152
- stream_task = asyncio.create_task(self._stream_llm_output(llm_output))
153
-
154
- try:
155
- async for audio_content in self._run_synthesis():
156
- yield audio_content
157
- except Exception as e:
158
- raise APIError(f"Error during synthesis processing: {e}")
159
-
160
- finally:
161
- await stream_task