avartha-python-sdk 0.0.1__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.
- avartha/__init__.py +42 -0
- avartha/_config.py +140 -0
- avartha/_realtime_tts.py +138 -0
- avartha/_version.py +24 -0
- avartha/client.py +159 -0
- avartha/control.py +441 -0
- avartha/conversational_ai/__init__.py +19 -0
- avartha/conversational_ai/conversation.py +19 -0
- avartha/conversational_ai/default_audio_interface.py +5 -0
- avartha/elevenlabs.py +120 -0
- avartha/errors.py +35 -0
- avartha/openai.py +106 -0
- avartha/py.typed +0 -0
- avartha_python_sdk-0.0.1.dist-info/METADATA +417 -0
- avartha_python_sdk-0.0.1.dist-info/RECORD +18 -0
- avartha_python_sdk-0.0.1.dist-info/WHEEL +5 -0
- avartha_python_sdk-0.0.1.dist-info/licenses/LICENSE +23 -0
- avartha_python_sdk-0.0.1.dist-info/top_level.txt +1 -0
avartha/openai.py
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Import-compatible OpenAI clients configured for Avartha.
|
|
2
|
+
|
|
3
|
+
Resource methods, response objects, errors, SSE and Realtime connections are
|
|
4
|
+
provided by the official openai package. Continue importing types from openai.
|
|
5
|
+
|
|
6
|
+
Subclassing alone does not keep an Avartha key on an Avartha host. The official
|
|
7
|
+
constructor reads OPENAI_* variables for credentials, identifiers and headers,
|
|
8
|
+
and accepts arguments that recompute the base URL, so both are fenced below.
|
|
9
|
+
copy() and with_options() rebuild through __init__ and inherit the same fence.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from collections.abc import Callable, Mapping
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from openai import AsyncOpenAI as _AsyncOpenAI
|
|
16
|
+
from openai import OpenAI as _OpenAI
|
|
17
|
+
|
|
18
|
+
from . import _config
|
|
19
|
+
from ._config import ConfigurationError, Tier
|
|
20
|
+
|
|
21
|
+
VENDOR_IDENTITY = ("organization", "project", "webhook_secret", "admin_api_key")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _arguments(
|
|
25
|
+
api_key: str | Callable[[], str] | None,
|
|
26
|
+
base_url: str | None,
|
|
27
|
+
tier: Tier,
|
|
28
|
+
kwargs: dict[str, Any],
|
|
29
|
+
) -> dict[str, Any]:
|
|
30
|
+
"""Upstream constructor arguments, with vendor routing refused."""
|
|
31
|
+
if kwargs.pop("data_residency", None) is not None:
|
|
32
|
+
raise ConfigurationError(
|
|
33
|
+
"data_residency selects an OpenAI-hosted region. Use base_url or tier to "
|
|
34
|
+
"choose an Avartha service instead."
|
|
35
|
+
)
|
|
36
|
+
websocket_base_url = kwargs.pop("websocket_base_url", None)
|
|
37
|
+
return {
|
|
38
|
+
"api_key": api_key if callable(api_key) else _config.api_key(api_key),
|
|
39
|
+
"base_url": _config.openai_url(tier=tier)
|
|
40
|
+
if base_url is None
|
|
41
|
+
else _config.not_vendor_host(_config.http_url(str(base_url)), field="base_url"),
|
|
42
|
+
"websocket_base_url": None
|
|
43
|
+
if websocket_base_url is None
|
|
44
|
+
else _config.websocket_override(str(websocket_base_url)),
|
|
45
|
+
**kwargs,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _seal(client: Any, arguments: Mapping[str, Any]) -> None:
|
|
50
|
+
"""Restore the caller's identity and headers, then confirm the routing.
|
|
51
|
+
|
|
52
|
+
Upstream sources the identity arguments from OPENAI_* variables and merges
|
|
53
|
+
OPENAI_CUSTOM_HEADERS into the default headers, where an Authorization entry
|
|
54
|
+
overrides the Avartha bearer. Reinstating exactly what the caller passed
|
|
55
|
+
discards all of it without re-parsing the environment. Private attribute
|
|
56
|
+
access is confined here; see the pinned range in pyproject.toml.
|
|
57
|
+
"""
|
|
58
|
+
for name in VENDOR_IDENTITY:
|
|
59
|
+
setattr(client, name, arguments.get(name))
|
|
60
|
+
client._custom_headers = dict(arguments.get("default_headers") or {})
|
|
61
|
+
client._ambient_authorizations = frozenset()
|
|
62
|
+
_config.not_vendor_host(str(client.base_url), field="base_url")
|
|
63
|
+
if client.websocket_base_url is not None:
|
|
64
|
+
_config.not_vendor_host(str(client.websocket_base_url), field="websocket_base_url")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class _WebSocketURL:
|
|
68
|
+
"""Keep constructor, copy, and later assignments on the same URL contract."""
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def websocket_base_url(self) -> str | None:
|
|
72
|
+
return self._avartha_websocket_base_url
|
|
73
|
+
|
|
74
|
+
@websocket_base_url.setter
|
|
75
|
+
def websocket_base_url(self, value: str | None) -> None:
|
|
76
|
+
self._avartha_websocket_base_url = (
|
|
77
|
+
None if value is None else _config.websocket_override(str(value))
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class OpenAI(_WebSocketURL, _OpenAI):
|
|
82
|
+
def __init__(
|
|
83
|
+
self,
|
|
84
|
+
*,
|
|
85
|
+
api_key: str | Callable[[], str] | None = None,
|
|
86
|
+
base_url: str | None = None,
|
|
87
|
+
tier: Tier = "serverless",
|
|
88
|
+
**kwargs: Any,
|
|
89
|
+
) -> None:
|
|
90
|
+
arguments = _arguments(api_key, base_url, tier, kwargs)
|
|
91
|
+
super().__init__(**arguments)
|
|
92
|
+
_seal(self, arguments)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class AsyncOpenAI(_WebSocketURL, _AsyncOpenAI):
|
|
96
|
+
def __init__(
|
|
97
|
+
self,
|
|
98
|
+
*,
|
|
99
|
+
api_key: str | Callable[[], str] | None = None,
|
|
100
|
+
base_url: str | None = None,
|
|
101
|
+
tier: Tier = "serverless",
|
|
102
|
+
**kwargs: Any,
|
|
103
|
+
) -> None:
|
|
104
|
+
arguments = _arguments(api_key, base_url, tier, kwargs)
|
|
105
|
+
super().__init__(**arguments)
|
|
106
|
+
_seal(self, arguments)
|
avartha/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: avartha-python-sdk
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Python clients for Avartha inference, voice agents, and platform management
|
|
5
|
+
Author-email: "Avartha Inc." <team@avartha.ai>
|
|
6
|
+
License-Expression: LicenseRef-Avartha-Proprietary
|
|
7
|
+
Project-URL: Repository, https://github.com/avartha/avartha-python-sdk
|
|
8
|
+
Project-URL: Issues, https://github.com/avartha/avartha-python-sdk/issues
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Typing :: Typed
|
|
17
|
+
Requires-Python: >=3.12
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: openai[realtime]<4,>=3.13.0
|
|
21
|
+
Requires-Dist: elevenlabs<2.69,>=2.68.0
|
|
22
|
+
Requires-Dist: httpx<0.29,>=0.28.1
|
|
23
|
+
Requires-Dist: websockets<16,>=15.0.1
|
|
24
|
+
Requires-Dist: pydantic<3,>=2.11
|
|
25
|
+
Provides-Extra: audio
|
|
26
|
+
Requires-Dist: elevenlabs[pyaudio]<2.69,>=2.68.0; extra == "audio"
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest<10,>=8; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-asyncio<2,>=1; extra == "dev"
|
|
30
|
+
Requires-Dist: ruff<0.17,>=0.16; extra == "dev"
|
|
31
|
+
Requires-Dist: mypy<3,>=2.3; extra == "dev"
|
|
32
|
+
Requires-Dist: build<2,>=1; extra == "dev"
|
|
33
|
+
Requires-Dist: setuptools-scm<9,>=8; extra == "dev"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
# Avartha Python SDK
|
|
37
|
+
|
|
38
|
+
Synchronous and asynchronous Python clients for Avartha Realtime LLMs,
|
|
39
|
+
streaming speech, and platform management. Requires Python 3.12+.
|
|
40
|
+
|
|
41
|
+
**Drop-in Python interfaces for OpenAI Realtime and ElevenLabs speech.** Change
|
|
42
|
+
the client import and configure Avartha credentials, URLs, and model IDs. Keep
|
|
43
|
+
the upstream resource methods, request types, response objects, and event loops:
|
|
44
|
+
|
|
45
|
+
```diff
|
|
46
|
+
-from openai import OpenAI, AsyncOpenAI
|
|
47
|
+
+from avartha import OpenAI, AsyncOpenAI
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
```diff
|
|
51
|
+
-from elevenlabs.client import ElevenLabs, AsyncElevenLabs
|
|
52
|
+
+from avartha import ElevenLabs, AsyncElevenLabs
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
These classes extend the official SDKs. Compatibility depends on the server's
|
|
56
|
+
supported endpoints. Avartha managed inference is **WebSocket-only**; legacy
|
|
57
|
+
Chat Completions, Responses, and HTTP speech calls are retired. Preview testing
|
|
58
|
+
also found ASR and TTS mismatches with the official ElevenLabs client defaults.
|
|
59
|
+
[Migration details](docs/migration.md) · [Protocol audit and triage](docs/audit/report.md) · [Initial live test results](docs/preview-testing.md)
|
|
60
|
+
|
|
61
|
+
## Documentation
|
|
62
|
+
|
|
63
|
+
- [Drop-in migration from OpenAI and ElevenLabs](docs/migration.md)
|
|
64
|
+
- [Compatibility and endpoint coverage](docs/compatibility.md)
|
|
65
|
+
- [Protocol audit: defaults, message sequences, errors, and triage](docs/audit/report.md)
|
|
66
|
+
- [Platform management](docs/platform.md)
|
|
67
|
+
- [Runnable examples](examples)
|
|
68
|
+
- [Contributing](CONTRIBUTING.md)
|
|
69
|
+
|
|
70
|
+
## Installation
|
|
71
|
+
|
|
72
|
+
The repository is private and the package has not been published to PyPI.
|
|
73
|
+
With GitHub access configured, install from source:
|
|
74
|
+
|
|
75
|
+
```sh
|
|
76
|
+
git clone https://github.com/avartha/avartha-python-sdk.git
|
|
77
|
+
python -m pip install ./avartha-python-sdk
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Set your Avartha API key and platform root:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
export AVARTHA_API_KEY='avk_...'
|
|
84
|
+
export AVARTHA_BASE_URL='https://platform.avartha.ai'
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
For preview, set `AVARTHA_BASE_URL=https://platform.preview.avartha.ai`.
|
|
88
|
+
Both protocol clients derive their service URLs from this root. Use model and
|
|
89
|
+
voice IDs from the selected environment; vendor IDs are not mapped automatically.
|
|
90
|
+
|
|
91
|
+
## Usage
|
|
92
|
+
|
|
93
|
+
Use the OpenAI Realtime interface for LLM inference. The client reads
|
|
94
|
+
`AVARTHA_API_KEY` from the environment; `api_key` can also be passed explicitly.
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from avartha import OpenAI
|
|
98
|
+
|
|
99
|
+
with OpenAI() as client:
|
|
100
|
+
with client.realtime.connect(model="google/gemma-4-26b-a4b-it") as connection:
|
|
101
|
+
connection.session.update(session={"type": "realtime", "output_modalities": ["text"]})
|
|
102
|
+
connection.conversation.item.create(
|
|
103
|
+
item={
|
|
104
|
+
"type": "message",
|
|
105
|
+
"role": "user",
|
|
106
|
+
"content": [{"type": "input_text", "text": "Explain Python dictionaries."}],
|
|
107
|
+
}
|
|
108
|
+
)
|
|
109
|
+
connection.response.create()
|
|
110
|
+
for event in connection:
|
|
111
|
+
if event.type == "response.output_text.delta":
|
|
112
|
+
print(event.delta, end="", flush=True)
|
|
113
|
+
elif event.type == "response.done":
|
|
114
|
+
break
|
|
115
|
+
elif event.type == "error":
|
|
116
|
+
raise RuntimeError(event.error.message)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Keep the connection open for additional turns. Create another conversation item
|
|
120
|
+
and response on the same connection to preserve conversation state.
|
|
121
|
+
|
|
122
|
+
To discover available models and their enabled protocols:
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
from avartha import OpenAI
|
|
126
|
+
|
|
127
|
+
with OpenAI() as client:
|
|
128
|
+
for model in client.models.list():
|
|
129
|
+
print(model.id, model.to_dict().get("protocols", []))
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The preview catalog currently includes Gemma for `openai_realtime`, Qwen for
|
|
133
|
+
`elevenlabs_tts`, and Voxtral for `elevenlabs_asr`. Availability is workspace-
|
|
134
|
+
and tier-specific; discovery is authoritative for your key.
|
|
135
|
+
|
|
136
|
+
## Async usage
|
|
137
|
+
|
|
138
|
+
Use `AsyncOpenAI`, await operations, and iterate with `async for`. Request
|
|
139
|
+
parameters and event types remain the upstream SDK's own.
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
import asyncio
|
|
143
|
+
from avartha import AsyncOpenAI
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
async def main():
|
|
147
|
+
async with AsyncOpenAI() as client:
|
|
148
|
+
async with client.realtime.connect(model="google/gemma-4-26b-a4b-it") as connection:
|
|
149
|
+
await connection.session.update(
|
|
150
|
+
session={"type": "realtime", "output_modalities": ["text"]}
|
|
151
|
+
)
|
|
152
|
+
await connection.conversation.item.create(
|
|
153
|
+
item={
|
|
154
|
+
"type": "message",
|
|
155
|
+
"role": "user",
|
|
156
|
+
"content": [{"type": "input_text", "text": "Explain Python dictionaries."}],
|
|
157
|
+
}
|
|
158
|
+
)
|
|
159
|
+
await connection.response.create()
|
|
160
|
+
async for event in connection:
|
|
161
|
+
if event.type == "response.output_text.delta":
|
|
162
|
+
print(event.delta, end="", flush=True)
|
|
163
|
+
elif event.type == "response.done":
|
|
164
|
+
break
|
|
165
|
+
elif event.type == "error":
|
|
166
|
+
raise RuntimeError(event.error.message)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
asyncio.run(main())
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
[Complete Realtime example](examples/realtime.py).
|
|
173
|
+
|
|
174
|
+
## Streaming speech
|
|
175
|
+
|
|
176
|
+
`ElevenLabs()` defaults to the same Avartha platform root and serverless tier.
|
|
177
|
+
Its method names and wire messages come from the official ElevenLabs package.
|
|
178
|
+
|
|
179
|
+
### Text to speech
|
|
180
|
+
|
|
181
|
+
Discover voices for the selected TTS model using the upstream request options:
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
from avartha import ElevenLabs
|
|
185
|
+
|
|
186
|
+
with ElevenLabs() as client:
|
|
187
|
+
voices = client.voices.get_all(
|
|
188
|
+
request_options={
|
|
189
|
+
"additional_query_parameters": {"model_id": "qwen/qwen3-tts-12hz-1.7b-base"}
|
|
190
|
+
}
|
|
191
|
+
)
|
|
192
|
+
for voice in voices.voices:
|
|
193
|
+
print(voice.voice_id)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Stream text over a WebSocket with `convert_realtime`. Avartha returns PCM;
|
|
197
|
+
select a sample rate supported by your model and write a WAV header for playback.
|
|
198
|
+
This example uses Qwen's 24 kHz output:
|
|
199
|
+
|
|
200
|
+
```python
|
|
201
|
+
import wave
|
|
202
|
+
from avartha import ElevenLabs
|
|
203
|
+
|
|
204
|
+
with ElevenLabs() as client:
|
|
205
|
+
audio = client.text_to_speech.convert_realtime(
|
|
206
|
+
voice_id="carol",
|
|
207
|
+
model_id="qwen/qwen3-tts-12hz-1.7b-base",
|
|
208
|
+
output_format="pcm_24000",
|
|
209
|
+
text=iter(["Welcome. ", "How can I help?"]),
|
|
210
|
+
)
|
|
211
|
+
with wave.open("welcome.wav", "wb") as output:
|
|
212
|
+
output.setnchannels(1)
|
|
213
|
+
output.setsampwidth(2)
|
|
214
|
+
output.setframerate(24000)
|
|
215
|
+
for chunk in audio:
|
|
216
|
+
output.writeframes(chunk)
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
The official TTS helper currently fails on preview: Vajra requires
|
|
220
|
+
`auto_mode=true` and rejects the helper's hardcoded `try_trigger_generation`
|
|
221
|
+
and `generation_config` fields. Raw single- and multi-context TTS both succeeded
|
|
222
|
+
with native pacing, so this is a client/runtime contract mismatch, not a model
|
|
223
|
+
outage. See [the diagnosis](docs/preview-testing.md#tts-vajra-rejects-official-client-defaults).
|
|
224
|
+
The example above preserves the vendor interface and requires that mismatch to
|
|
225
|
+
be resolved on the service.
|
|
226
|
+
|
|
227
|
+
`convert_realtime` is synchronous, matching upstream. The pinned ElevenLabs SDK
|
|
228
|
+
has no multi-context helper; the platform's `multi-stream-input` WebSocket is a
|
|
229
|
+
separate vendor protocol surface. HTTP `text_to_speech.stream` and `.convert`
|
|
230
|
+
remain inherited methods but are not supported by managed inference.
|
|
231
|
+
[Runnable TTS example](examples/tts.py).
|
|
232
|
+
|
|
233
|
+
### Speech to text
|
|
234
|
+
|
|
235
|
+
Realtime ASR uses `await client.speech_to_text.realtime.connect(...)` on both
|
|
236
|
+
ElevenLabs client variants. Send mono PCM16 audio and await a committed transcript.
|
|
237
|
+
[The complete example](examples/realtime_asr.py) reads a WAV file, registers
|
|
238
|
+
transcript/error callbacks, streams chunks, commits, and closes the connection:
|
|
239
|
+
|
|
240
|
+
```sh
|
|
241
|
+
python examples/realtime_asr.py mistralai/voxtral-mini-4b-realtime-2602 speech-16k.wav
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Preview workaround:** pass `previous_text=""` in each `connection.send` data
|
|
245
|
+
dictionary when you have no context. The official SDK otherwise sends
|
|
246
|
+
`previous_text: null`, which preview currently rejects. Both sync-client and
|
|
247
|
+
async-client ASR sessions passed with the empty-string workaround. This is an
|
|
248
|
+
application option, not a change to the SDK's wire protocol.
|
|
249
|
+
|
|
250
|
+
File-based HTTP `speech_to_text.convert` is retired on managed inference.
|
|
251
|
+
|
|
252
|
+
## Agents
|
|
253
|
+
|
|
254
|
+
The SDK retains the complete ElevenLabs `conversational_ai` namespace, including
|
|
255
|
+
agent creation, tools, knowledge-base documents, and conversations. **Managed
|
|
256
|
+
Avartha agent CRUD does not currently implement the ElevenLabs endpoints.**
|
|
257
|
+
Its native control API uses a different schema. Preview's ElevenLabs-shaped
|
|
258
|
+
conversation-list endpoint did respond successfully.
|
|
259
|
+
|
|
260
|
+
Against a service that implements ElevenLabs agent management, the original
|
|
261
|
+
calls work unchanged:
|
|
262
|
+
|
|
263
|
+
```python
|
|
264
|
+
from avartha import ElevenLabs
|
|
265
|
+
|
|
266
|
+
with ElevenLabs(base_url="https://your-compatible-agent-service") as client:
|
|
267
|
+
agent = client.conversational_ai.agents.create(
|
|
268
|
+
name="Support",
|
|
269
|
+
conversation_config={
|
|
270
|
+
"agent": {
|
|
271
|
+
"first_message": "What can I help you with?",
|
|
272
|
+
"prompt": {"prompt": "Help customers find concise, accurate answers."},
|
|
273
|
+
},
|
|
274
|
+
"tts": {"voice_id": "your-voice"},
|
|
275
|
+
},
|
|
276
|
+
)
|
|
277
|
+
print(agent.agent_id)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
`Conversation`, `AsyncConversation`, and `ClientTools` are the upstream classes,
|
|
281
|
+
also available from `avartha.conversational_ai`. `AsyncConversation` takes a
|
|
282
|
+
**sync** ElevenLabs client, matching upstream. Agent session execution has local
|
|
283
|
+
contract coverage; it was not exercised against a published preview agent.
|
|
284
|
+
|
|
285
|
+
- [Agent, tool, and knowledge-base example](examples/agents.py)
|
|
286
|
+
- [Conversation with client tools](examples/conversation.py)
|
|
287
|
+
|
|
288
|
+
## Using types
|
|
289
|
+
|
|
290
|
+
Continue importing types and exceptions from the upstream packages. The adapter
|
|
291
|
+
returns their original objects:
|
|
292
|
+
|
|
293
|
+
```python
|
|
294
|
+
from avartha import OpenAI
|
|
295
|
+
from openai.types import Model
|
|
296
|
+
|
|
297
|
+
with OpenAI() as client:
|
|
298
|
+
models: list[Model] = client.models.list().data
|
|
299
|
+
print([model.to_dict() for model in models])
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Use `openai.types` and `elevenlabs.types` for their full type catalogs.
|
|
303
|
+
`avartha.types` is not a replacement namespace. Platform management responses
|
|
304
|
+
are JSON dictionaries and lists.
|
|
305
|
+
|
|
306
|
+
## Handling errors
|
|
307
|
+
|
|
308
|
+
Keep existing vendor exception handlers. For HTTP discovery:
|
|
309
|
+
|
|
310
|
+
```python
|
|
311
|
+
import openai
|
|
312
|
+
from avartha import OpenAI
|
|
313
|
+
|
|
314
|
+
with OpenAI() as client:
|
|
315
|
+
try:
|
|
316
|
+
client.models.list()
|
|
317
|
+
except openai.APIConnectionError as error:
|
|
318
|
+
print("Connection failed:", error)
|
|
319
|
+
except openai.APIStatusError as error:
|
|
320
|
+
print("Request failed:", error.status_code, error.request_id)
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Realtime server errors are events, so handle `event.type == "error"` in the
|
|
324
|
+
receive loop. Inspect `response.done.response.status` for completion, failure,
|
|
325
|
+
or cancellation; a terminal event alone does not prove successful inference.
|
|
326
|
+
Connection failures can raise WebSocket exceptions.
|
|
327
|
+
|
|
328
|
+
ElevenLabs HTTP/TTS helper errors remain `elevenlabs.core.api_error.ApiError`;
|
|
329
|
+
ASR also emits `RealtimeEvents.ERROR`. The upstream TTS helper can omit a
|
|
330
|
+
server error's details when the gateway closes the socket.
|
|
331
|
+
|
|
332
|
+
Management failures use `avartha.PlatformAPIError`, retaining the HTTP status,
|
|
333
|
+
response body, field errors, request ID, and `Retry-After` header. Management
|
|
334
|
+
network failures are `httpx` exceptions.
|
|
335
|
+
|
|
336
|
+
## Retries and timeouts
|
|
337
|
+
|
|
338
|
+
Upstream constructor options pass through:
|
|
339
|
+
|
|
340
|
+
```python
|
|
341
|
+
from avartha import OpenAI
|
|
342
|
+
|
|
343
|
+
with OpenAI(timeout=30.0, max_retries=0) as client:
|
|
344
|
+
print(client.models.list())
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
HTTP and WebSocket retry settings are separate. The pinned OpenAI client accepts
|
|
348
|
+
`client.realtime.connect(..., max_retries=0)` to disable automatic reconnection,
|
|
349
|
+
and `websocket_connection_options` for transport settings. Use `asyncio.timeout`
|
|
350
|
+
when an async operation needs an overall deadline. Close active sessions when
|
|
351
|
+
cancelling. ElevenLabs `timeout` does not bound every WebSocket receive; the
|
|
352
|
+
live smoke runner isolates its synchronous TTS helper to enforce a deadline.
|
|
353
|
+
Control-plane writes are never retried automatically.
|
|
354
|
+
|
|
355
|
+
## Configuration
|
|
356
|
+
|
|
357
|
+
| Client | Meaning of explicit `base_url` |
|
|
358
|
+
| --- | --- |
|
|
359
|
+
| `OpenAI`, `AsyncOpenAI` | Full inference base: `https://platform.avartha.ai/inference/serverless/openai/v1` |
|
|
360
|
+
| `ElevenLabs`, `AsyncElevenLabs` | Dialect root before `/v1`: `https://platform.avartha.ai/inference/serverless/elevenlabs` |
|
|
361
|
+
| `Avartha`, `AsyncAvartha`, `Control`, `AsyncControl` | Platform root: `https://platform.avartha.ai` |
|
|
362
|
+
|
|
363
|
+
Without an explicit URL, protocol clients derive their URL from
|
|
364
|
+
`AVARTHA_BASE_URL`. Set `tier="dedicated"` for dedicated inference; there is no
|
|
365
|
+
automatic fallback between tiers. An explicit protocol `base_url` takes
|
|
366
|
+
precedence over `tier`. `AVARTHA_ELEVENLABS_BASE_URL` overrides the derived speech
|
|
367
|
+
root, and an explicit ElevenLabs `base_url` overrides that environment variable.
|
|
368
|
+
|
|
369
|
+
Keys are read at construction from `AVARTHA_API_KEY` or `api_key`.
|
|
370
|
+
Vendor default keys and base URL variables are not substituted. Keep custom
|
|
371
|
+
upstream transports and type imports where needed; OpenAI 3 uses HTTPX2.
|
|
372
|
+
[Migration configuration](docs/migration.md#configuration).
|
|
373
|
+
|
|
374
|
+
Always close clients or use context managers. OpenAI retains its upstream
|
|
375
|
+
HTTP-client ownership behavior. ElevenLabs and Control close only clients they
|
|
376
|
+
created. Close active WebSocket sessions separately.
|
|
377
|
+
|
|
378
|
+
## Platform management
|
|
379
|
+
|
|
380
|
+
Use the combined `Avartha` client for inference plus management:
|
|
381
|
+
|
|
382
|
+
```python
|
|
383
|
+
from avartha import Avartha
|
|
384
|
+
|
|
385
|
+
with Avartha() as client:
|
|
386
|
+
print(client.control.catalog.models())
|
|
387
|
+
print(client.control.catalog.skus(provider="modal"))
|
|
388
|
+
print(client.control.organizations.list())
|
|
389
|
+
print(client.control.organizations.limits("your-workspace-id"))
|
|
390
|
+
print(client.control.endpoints.list(workspace_id="your-workspace-id"))
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
`client.openai` and `client.elevenlabs` are the protocol clients;
|
|
394
|
+
`client.realtime` is a shortcut to the OpenAI resource. `AsyncAvartha`, `Control`,
|
|
395
|
+
and `AsyncControl` are available too. Endpoint creation, readiness waiting,
|
|
396
|
+
scaling, routing, stopping, and deletion are described in the
|
|
397
|
+
[management guide](docs/platform.md).
|
|
398
|
+
|
|
399
|
+
## Examples and development
|
|
400
|
+
|
|
401
|
+
For local microphone/speaker support, install the `audio` extra from the
|
|
402
|
+
repository (`python -m pip install '.[audio]'`) and PortAudio.
|
|
403
|
+
|
|
404
|
+
```sh
|
|
405
|
+
python -m venv .venv
|
|
406
|
+
. .venv/bin/activate
|
|
407
|
+
make install-dev
|
|
408
|
+
make check
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
On images without `ensurepip`, install `uv` and use
|
|
412
|
+
`make check BUILD_FLAGS=--installer=uv`. CI runs on Python 3.12–3.14. Default
|
|
413
|
+
tests use mock HTTP transports and local WebSockets without cloud inference.
|
|
414
|
+
`make build` produces wheel and source archives; publication is separate.
|
|
415
|
+
|
|
416
|
+
Live testing is explicit and consumes inference credits. See
|
|
417
|
+
[preview testing](docs/preview-testing.md) for the runner and current results.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
avartha/__init__.py,sha256=8Lu-1TX1d0p7p0F4llqBn4uUWW5FjFzw28VAu7xqA3Q,1288
|
|
2
|
+
avartha/_config.py,sha256=aH56waOtEHCZiEcS4HmqeL74C28KjSteWhH9fJWTOKQ,5300
|
|
3
|
+
avartha/_realtime_tts.py,sha256=-v1QVEoCKKbvHYCoSBzic_yAmgGtv44dVxG5PyJEn70,5552
|
|
4
|
+
avartha/_version.py,sha256=8OsTLsIVB9D0HdPTmt5rVwyVUBe9xTVGkRslXicxzkM,520
|
|
5
|
+
avartha/client.py,sha256=71fjDILDN4wn0yfJu8I8LtkrD80hG7tG6KlOpb981eg,5520
|
|
6
|
+
avartha/control.py,sha256=X3OGXkpxYmSc418a_g6cQsbW9-2K2y6iEA_eRb3j1c0,14970
|
|
7
|
+
avartha/elevenlabs.py,sha256=WBSO0wnkrBQrtIvCdopQj_5sW_O3riWEWNYJUkNit9k,3946
|
|
8
|
+
avartha/errors.py,sha256=ywIQTnYzZ5Jm8P-lIwlwyRuH7QcOQE-iIB-yi5PjU6w,1333
|
|
9
|
+
avartha/openai.py,sha256=f4o0tDHEMgYQzSQTYJs049cOx0ZtXYT430ya4bD54So,3950
|
|
10
|
+
avartha/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
avartha/conversational_ai/__init__.py,sha256=0-A3bhDzfIugXIkilT36io-4x9SluP61Uuakvu8WI28,407
|
|
12
|
+
avartha/conversational_ai/conversation.py,sha256=CBUsG4VVjh1p6UoSQldG64WtS0ihF_bjfA-M3mKsA4Q,431
|
|
13
|
+
avartha/conversational_ai/default_audio_interface.py,sha256=jxx1V6zJTZgH--MalNUynrnRxXic6gXYoYzzBwQTkME,203
|
|
14
|
+
avartha_python_sdk-0.0.1.dist-info/licenses/LICENSE,sha256=1ulXrK7aq7kBXX1scK6IiOgnbwqpmK6kWIB3CYznVG8,1135
|
|
15
|
+
avartha_python_sdk-0.0.1.dist-info/METADATA,sha256=wjoXaOGIo1YMsX1NL_X6QelNGDvHi9CmzET4BttV4I8,15898
|
|
16
|
+
avartha_python_sdk-0.0.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
17
|
+
avartha_python_sdk-0.0.1.dist-info/top_level.txt,sha256=cj2kDXl33tO2IPWPduSTukcwozPnYKOsVUVE9QZRUr0,8
|
|
18
|
+
avartha_python_sdk-0.0.1.dist-info/RECORD,,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Copyright (c) 2026 Avartha Inc. All Rights Reserved.
|
|
2
|
+
|
|
3
|
+
This software and its associated documentation (the "Software") are the
|
|
4
|
+
proprietary and confidential property of Avartha Inc.
|
|
5
|
+
|
|
6
|
+
No license or other right to use, copy, modify, distribute, sublicense,
|
|
7
|
+
publish, display, perform, transmit, or create derivative works of the
|
|
8
|
+
Software is granted except under a separate written agreement with
|
|
9
|
+
Avartha Inc. Any use of the Software without such authorization is strictly
|
|
10
|
+
prohibited.
|
|
11
|
+
|
|
12
|
+
THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
13
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
14
|
+
FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
15
|
+
AVARTHA INC. BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY ARISING
|
|
16
|
+
FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR ITS USE.
|
|
17
|
+
|
|
18
|
+
Third-Party Software
|
|
19
|
+
|
|
20
|
+
The Software may include or interact with third-party components. Those
|
|
21
|
+
components remain subject to their respective license terms and notices.
|
|
22
|
+
Nothing in this license limits or supersedes rights granted by third-party
|
|
23
|
+
licenses or claims ownership of third-party copyrights.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
avartha
|