omniai-kit 1.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.
- omniai/__init__.py +117 -0
- omniai/_base.py +386 -0
- omniai/_constants.py +39 -0
- omniai/_version.py +4 -0
- omniai/client.py +316 -0
- omniai/exceptions.py +113 -0
- omniai/py.typed +1 -0
- omniai/resources/__init__.py +26 -0
- omniai/resources/chat.py +403 -0
- omniai/resources/livekit.py +71 -0
- omniai/resources/models.py +63 -0
- omniai/resources/router.py +1040 -0
- omniai/resources/tasks.py +171 -0
- omniai/types/__init__.py +27 -0
- omniai/types/chat.py +48 -0
- omniai/types/livekit.py +17 -0
- omniai/types/models.py +30 -0
- omniai/types/tasks.py +208 -0
- omniai_kit-1.0.0.dist-info/METADATA +270 -0
- omniai_kit-1.0.0.dist-info/RECORD +23 -0
- omniai_kit-1.0.0.dist-info/WHEEL +5 -0
- omniai_kit-1.0.0.dist-info/licenses/LICENSE +21 -0
- omniai_kit-1.0.0.dist-info/top_level.txt +1 -0
omniai/resources/chat.py
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
"""Chat completions resource for OmniAI."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from typing import TYPE_CHECKING, Any, AsyncGenerator, Dict, Generator, List, Optional, Type, TypeVar, Union
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
from omniai.types.tasks import clean_json_text
|
|
10
|
+
from omniai.exceptions import OmniaiValidationError
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from omniai._base import BaseClient, AsyncBaseClient
|
|
14
|
+
|
|
15
|
+
T = TypeVar("T")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CompletionsResource:
|
|
19
|
+
"""Synchronous completions endpoint resource."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, client: BaseClient):
|
|
22
|
+
self._client = client
|
|
23
|
+
|
|
24
|
+
def create(
|
|
25
|
+
self,
|
|
26
|
+
*,
|
|
27
|
+
model: str,
|
|
28
|
+
prompt: Optional[str] = None,
|
|
29
|
+
messages: Optional[List[Dict[str, str]]] = None,
|
|
30
|
+
response_model: Optional[Type[T]] = None,
|
|
31
|
+
tools: Optional[List[Any]] = None,
|
|
32
|
+
output_format: Optional[Union[str, Dict[str, Any]]] = None,
|
|
33
|
+
system_instruction: Optional[str] = None,
|
|
34
|
+
temperature: float = 0.1,
|
|
35
|
+
max_tokens: Optional[int] = None,
|
|
36
|
+
timeout: Optional[float] = None,
|
|
37
|
+
) -> Union[str, T]:
|
|
38
|
+
# Early provider validation
|
|
39
|
+
if ":" in model:
|
|
40
|
+
provider = model.split(":", 1)[0].strip().lower()
|
|
41
|
+
if provider not in ("openai", "gemini", "anthropic", "vllm", "openrouter", "ollama", "custom", "local"):
|
|
42
|
+
from omniai.exceptions import OmniaiUnsupportedProviderError
|
|
43
|
+
raise OmniaiUnsupportedProviderError(
|
|
44
|
+
f"Unsupported model provider '{provider}'. Strictly supported providers are: openai, gemini, anthropic, vllm, openrouter, ollama, custom, local."
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
payload: Dict[str, Any] = {
|
|
48
|
+
"model": model,
|
|
49
|
+
"temperature": temperature,
|
|
50
|
+
}
|
|
51
|
+
if prompt is not None:
|
|
52
|
+
payload["prompt"] = prompt
|
|
53
|
+
if messages is not None:
|
|
54
|
+
payload["messages"] = messages
|
|
55
|
+
if system_instruction is not None:
|
|
56
|
+
payload["system_instruction"] = system_instruction
|
|
57
|
+
if max_tokens is not None:
|
|
58
|
+
payload["max_tokens"] = max_tokens
|
|
59
|
+
if tools:
|
|
60
|
+
payload["tools"] = tools
|
|
61
|
+
if output_format:
|
|
62
|
+
payload["output_format"] = output_format
|
|
63
|
+
elif response_model and issubclass(response_model, BaseModel):
|
|
64
|
+
payload["output_format"] = response_model.model_json_schema()
|
|
65
|
+
|
|
66
|
+
response = self._client.client.post(
|
|
67
|
+
"/v1/chat/completions",
|
|
68
|
+
json=payload,
|
|
69
|
+
timeout=timeout or self._client.timeout,
|
|
70
|
+
)
|
|
71
|
+
if response.status_code != 200:
|
|
72
|
+
self._client._handle_error_response(response)
|
|
73
|
+
|
|
74
|
+
data = response.json()
|
|
75
|
+
raw_result = data.get("result", "")
|
|
76
|
+
|
|
77
|
+
if response_model and issubclass(response_model, BaseModel):
|
|
78
|
+
if isinstance(raw_result, dict):
|
|
79
|
+
try:
|
|
80
|
+
return response_model.model_validate(raw_result)
|
|
81
|
+
except Exception as e:
|
|
82
|
+
raise OmniaiValidationError(
|
|
83
|
+
f"Failed validating response dictionary against {response_model.__name__}: {e}",
|
|
84
|
+
raw_output=str(raw_result),
|
|
85
|
+
) from e
|
|
86
|
+
elif isinstance(raw_result, str):
|
|
87
|
+
cleaned = clean_json_text(raw_result)
|
|
88
|
+
try:
|
|
89
|
+
return response_model.model_validate_json(cleaned)
|
|
90
|
+
except Exception as e:
|
|
91
|
+
raise OmniaiValidationError(
|
|
92
|
+
f"Failed validating JSON string against {response_model.__name__}: {e}",
|
|
93
|
+
raw_output=raw_result,
|
|
94
|
+
) from e
|
|
95
|
+
|
|
96
|
+
return raw_result
|
|
97
|
+
|
|
98
|
+
def stream(
|
|
99
|
+
self,
|
|
100
|
+
*,
|
|
101
|
+
model: str,
|
|
102
|
+
prompt: Optional[str] = None,
|
|
103
|
+
messages: Optional[List[Dict[str, str]]] = None,
|
|
104
|
+
system_instruction: Optional[str] = None,
|
|
105
|
+
temperature: float = 0.1,
|
|
106
|
+
max_tokens: Optional[int] = None,
|
|
107
|
+
timeout: Optional[float] = None,
|
|
108
|
+
) -> Generator[str, None, None]:
|
|
109
|
+
"""Streams a chat completion chunk-by-chunk using Server-Sent Events."""
|
|
110
|
+
payload: Dict[str, Any] = {
|
|
111
|
+
"model": model,
|
|
112
|
+
"temperature": temperature,
|
|
113
|
+
"stream": True,
|
|
114
|
+
}
|
|
115
|
+
if prompt is not None:
|
|
116
|
+
payload["prompt"] = prompt
|
|
117
|
+
if messages is not None:
|
|
118
|
+
payload["messages"] = messages
|
|
119
|
+
if system_instruction is not None:
|
|
120
|
+
payload["system_instruction"] = system_instruction
|
|
121
|
+
if max_tokens is not None:
|
|
122
|
+
payload["max_tokens"] = max_tokens
|
|
123
|
+
|
|
124
|
+
with self._client.client.stream(
|
|
125
|
+
"POST",
|
|
126
|
+
"/v1/chat/completions",
|
|
127
|
+
json=payload,
|
|
128
|
+
timeout=timeout or self._client.timeout,
|
|
129
|
+
) as response:
|
|
130
|
+
if response.status_code != 200:
|
|
131
|
+
response.read()
|
|
132
|
+
self._client._handle_error_response(response)
|
|
133
|
+
|
|
134
|
+
for line in response.iter_lines():
|
|
135
|
+
if not line or not line.strip():
|
|
136
|
+
continue
|
|
137
|
+
line_str = line.strip()
|
|
138
|
+
if line_str.startswith("data: "):
|
|
139
|
+
content = line_str[6:].strip()
|
|
140
|
+
if content == "[DONE]":
|
|
141
|
+
break
|
|
142
|
+
try:
|
|
143
|
+
chunk = json.loads(content)
|
|
144
|
+
delta = (
|
|
145
|
+
chunk.get("choices", [{}])[0].get("delta", {}).get("content")
|
|
146
|
+
or chunk.get("content")
|
|
147
|
+
or chunk.get("delta")
|
|
148
|
+
or chunk.get("text", "")
|
|
149
|
+
)
|
|
150
|
+
if delta:
|
|
151
|
+
yield delta
|
|
152
|
+
except json.JSONDecodeError:
|
|
153
|
+
yield content
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class AsyncCompletionsResource:
|
|
157
|
+
"""Asynchronous completions endpoint resource."""
|
|
158
|
+
|
|
159
|
+
def __init__(self, client: AsyncBaseClient):
|
|
160
|
+
self._client = client
|
|
161
|
+
|
|
162
|
+
async def create(
|
|
163
|
+
self,
|
|
164
|
+
*,
|
|
165
|
+
model: str,
|
|
166
|
+
prompt: Optional[str] = None,
|
|
167
|
+
messages: Optional[List[Dict[str, str]]] = None,
|
|
168
|
+
response_model: Optional[Type[T]] = None,
|
|
169
|
+
tools: Optional[List[Any]] = None,
|
|
170
|
+
output_format: Optional[Union[str, Dict[str, Any]]] = None,
|
|
171
|
+
system_instruction: Optional[str] = None,
|
|
172
|
+
temperature: float = 0.1,
|
|
173
|
+
max_tokens: Optional[int] = None,
|
|
174
|
+
timeout: Optional[float] = None,
|
|
175
|
+
) -> Union[str, T]:
|
|
176
|
+
# Early provider validation
|
|
177
|
+
if ":" in model:
|
|
178
|
+
provider = model.split(":", 1)[0].strip().lower()
|
|
179
|
+
if provider not in ("openai", "gemini", "anthropic", "vllm", "openrouter", "ollama", "custom", "local"):
|
|
180
|
+
from omniai.exceptions import OmniaiUnsupportedProviderError
|
|
181
|
+
raise OmniaiUnsupportedProviderError(
|
|
182
|
+
f"Unsupported model provider '{provider}'. Strictly supported providers are: openai, gemini, anthropic, vllm, openrouter, ollama, custom, local."
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
payload: Dict[str, Any] = {
|
|
186
|
+
"model": model,
|
|
187
|
+
"temperature": temperature,
|
|
188
|
+
}
|
|
189
|
+
if prompt is not None:
|
|
190
|
+
payload["prompt"] = prompt
|
|
191
|
+
if messages is not None:
|
|
192
|
+
payload["messages"] = messages
|
|
193
|
+
if system_instruction is not None:
|
|
194
|
+
payload["system_instruction"] = system_instruction
|
|
195
|
+
if max_tokens is not None:
|
|
196
|
+
payload["max_tokens"] = max_tokens
|
|
197
|
+
if tools:
|
|
198
|
+
payload["tools"] = tools
|
|
199
|
+
if output_format:
|
|
200
|
+
payload["output_format"] = output_format
|
|
201
|
+
elif response_model and issubclass(response_model, BaseModel):
|
|
202
|
+
payload["output_format"] = response_model.model_json_schema()
|
|
203
|
+
|
|
204
|
+
response = await self._client.client.post(
|
|
205
|
+
"/v1/chat/completions",
|
|
206
|
+
json=payload,
|
|
207
|
+
timeout=timeout or self._client.timeout,
|
|
208
|
+
)
|
|
209
|
+
if response.status_code != 200:
|
|
210
|
+
self._client._handle_error_response(response)
|
|
211
|
+
|
|
212
|
+
data = response.json()
|
|
213
|
+
raw_result = data.get("result", "")
|
|
214
|
+
|
|
215
|
+
if response_model and issubclass(response_model, BaseModel):
|
|
216
|
+
if isinstance(raw_result, dict):
|
|
217
|
+
try:
|
|
218
|
+
return response_model.model_validate(raw_result)
|
|
219
|
+
except Exception as e:
|
|
220
|
+
raise OmniaiValidationError(
|
|
221
|
+
f"Failed validating response dictionary against {response_model.__name__}: {e}",
|
|
222
|
+
raw_output=str(raw_result),
|
|
223
|
+
) from e
|
|
224
|
+
elif isinstance(raw_result, str):
|
|
225
|
+
cleaned = clean_json_text(raw_result)
|
|
226
|
+
try:
|
|
227
|
+
return response_model.model_validate_json(cleaned)
|
|
228
|
+
except Exception as e:
|
|
229
|
+
raise OmniaiValidationError(
|
|
230
|
+
f"Failed validating JSON string against {response_model.__name__}: {e}",
|
|
231
|
+
raw_output=raw_result,
|
|
232
|
+
) from e
|
|
233
|
+
|
|
234
|
+
return raw_result
|
|
235
|
+
|
|
236
|
+
async def stream(
|
|
237
|
+
self,
|
|
238
|
+
*,
|
|
239
|
+
model: str,
|
|
240
|
+
prompt: Optional[str] = None,
|
|
241
|
+
messages: Optional[List[Dict[str, str]]] = None,
|
|
242
|
+
system_instruction: Optional[str] = None,
|
|
243
|
+
temperature: float = 0.1,
|
|
244
|
+
max_tokens: Optional[int] = None,
|
|
245
|
+
timeout: Optional[float] = None,
|
|
246
|
+
) -> AsyncGenerator[str, None]:
|
|
247
|
+
"""Streams an async chat completion chunk-by-chunk using Server-Sent Events."""
|
|
248
|
+
payload: Dict[str, Any] = {
|
|
249
|
+
"model": model,
|
|
250
|
+
"temperature": temperature,
|
|
251
|
+
"stream": True,
|
|
252
|
+
}
|
|
253
|
+
if prompt is not None:
|
|
254
|
+
payload["prompt"] = prompt
|
|
255
|
+
if messages is not None:
|
|
256
|
+
payload["messages"] = messages
|
|
257
|
+
if system_instruction is not None:
|
|
258
|
+
payload["system_instruction"] = system_instruction
|
|
259
|
+
if max_tokens is not None:
|
|
260
|
+
payload["max_tokens"] = max_tokens
|
|
261
|
+
|
|
262
|
+
async with self._client.client.stream(
|
|
263
|
+
"POST",
|
|
264
|
+
"/v1/chat/completions",
|
|
265
|
+
json=payload,
|
|
266
|
+
timeout=timeout or self._client.timeout,
|
|
267
|
+
) as response:
|
|
268
|
+
if response.status_code != 200:
|
|
269
|
+
await response.aread()
|
|
270
|
+
self._client._handle_error_response(response)
|
|
271
|
+
|
|
272
|
+
async for line in response.aiter_lines():
|
|
273
|
+
if not line or not line.strip():
|
|
274
|
+
continue
|
|
275
|
+
line_str = line.strip()
|
|
276
|
+
if line_str.startswith("data: "):
|
|
277
|
+
content = line_str[6:].strip()
|
|
278
|
+
if content == "[DONE]":
|
|
279
|
+
break
|
|
280
|
+
try:
|
|
281
|
+
chunk = json.loads(content)
|
|
282
|
+
delta = (
|
|
283
|
+
chunk.get("choices", [{}])[0].get("delta", {}).get("content")
|
|
284
|
+
or chunk.get("content")
|
|
285
|
+
or chunk.get("delta")
|
|
286
|
+
or chunk.get("text", "")
|
|
287
|
+
)
|
|
288
|
+
if delta:
|
|
289
|
+
yield delta
|
|
290
|
+
except json.JSONDecodeError:
|
|
291
|
+
yield content
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class ChatResource:
|
|
295
|
+
"""Synchronous chat resource with nested completions."""
|
|
296
|
+
|
|
297
|
+
def __init__(self, client: BaseClient):
|
|
298
|
+
self._client = client
|
|
299
|
+
self.completions = CompletionsResource(client)
|
|
300
|
+
|
|
301
|
+
def __call__(
|
|
302
|
+
self,
|
|
303
|
+
model: str,
|
|
304
|
+
prompt: Optional[str] = None,
|
|
305
|
+
messages: Optional[List[Dict[str, str]]] = None,
|
|
306
|
+
response_model: Optional[Type[T]] = None,
|
|
307
|
+
tools: Optional[List[Any]] = None,
|
|
308
|
+
output_format: Optional[Union[str, Dict[str, Any]]] = None,
|
|
309
|
+
system_instruction: Optional[str] = None,
|
|
310
|
+
temperature: float = 0.1,
|
|
311
|
+
max_tokens: Optional[int] = None,
|
|
312
|
+
timeout: Optional[float] = None,
|
|
313
|
+
) -> Union[str, T]:
|
|
314
|
+
"""Allows direct invocation: client.chat(...)"""
|
|
315
|
+
return self.completions.create(
|
|
316
|
+
model=model,
|
|
317
|
+
prompt=prompt,
|
|
318
|
+
messages=messages,
|
|
319
|
+
response_model=response_model,
|
|
320
|
+
tools=tools,
|
|
321
|
+
output_format=output_format,
|
|
322
|
+
system_instruction=system_instruction,
|
|
323
|
+
temperature=temperature,
|
|
324
|
+
max_tokens=max_tokens,
|
|
325
|
+
timeout=timeout,
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
def stream(
|
|
329
|
+
self,
|
|
330
|
+
model: str,
|
|
331
|
+
prompt: Optional[str] = None,
|
|
332
|
+
messages: Optional[List[Dict[str, str]]] = None,
|
|
333
|
+
system_instruction: Optional[str] = None,
|
|
334
|
+
temperature: float = 0.1,
|
|
335
|
+
max_tokens: Optional[int] = None,
|
|
336
|
+
timeout: Optional[float] = None,
|
|
337
|
+
) -> Generator[str, None, None]:
|
|
338
|
+
"""Allows direct streaming invocation: client.chat.stream(...)"""
|
|
339
|
+
return self.completions.stream(
|
|
340
|
+
model=model,
|
|
341
|
+
prompt=prompt,
|
|
342
|
+
messages=messages,
|
|
343
|
+
system_instruction=system_instruction,
|
|
344
|
+
temperature=temperature,
|
|
345
|
+
max_tokens=max_tokens,
|
|
346
|
+
timeout=timeout,
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
class AsyncChatResource:
|
|
351
|
+
"""Asynchronous chat resource with nested completions."""
|
|
352
|
+
|
|
353
|
+
def __init__(self, client: AsyncBaseClient):
|
|
354
|
+
self._client = client
|
|
355
|
+
self.completions = AsyncCompletionsResource(client)
|
|
356
|
+
|
|
357
|
+
async def __call__(
|
|
358
|
+
self,
|
|
359
|
+
model: str,
|
|
360
|
+
prompt: Optional[str] = None,
|
|
361
|
+
messages: Optional[List[Dict[str, str]]] = None,
|
|
362
|
+
response_model: Optional[Type[T]] = None,
|
|
363
|
+
tools: Optional[List[Any]] = None,
|
|
364
|
+
output_format: Optional[Union[str, Dict[str, Any]]] = None,
|
|
365
|
+
system_instruction: Optional[str] = None,
|
|
366
|
+
temperature: float = 0.1,
|
|
367
|
+
max_tokens: Optional[int] = None,
|
|
368
|
+
timeout: Optional[float] = None,
|
|
369
|
+
) -> Union[str, T]:
|
|
370
|
+
"""Allows direct async invocation: await client.chat(...)"""
|
|
371
|
+
return await self.completions.create(
|
|
372
|
+
model=model,
|
|
373
|
+
prompt=prompt,
|
|
374
|
+
messages=messages,
|
|
375
|
+
response_model=response_model,
|
|
376
|
+
tools=tools,
|
|
377
|
+
output_format=output_format,
|
|
378
|
+
system_instruction=system_instruction,
|
|
379
|
+
temperature=temperature,
|
|
380
|
+
max_tokens=max_tokens,
|
|
381
|
+
timeout=timeout,
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
def stream(
|
|
385
|
+
self,
|
|
386
|
+
model: str,
|
|
387
|
+
prompt: Optional[str] = None,
|
|
388
|
+
messages: Optional[List[Dict[str, str]]] = None,
|
|
389
|
+
system_instruction: Optional[str] = None,
|
|
390
|
+
temperature: float = 0.1,
|
|
391
|
+
max_tokens: Optional[int] = None,
|
|
392
|
+
timeout: Optional[float] = None,
|
|
393
|
+
) -> AsyncGenerator[str, None]:
|
|
394
|
+
"""Allows direct async streaming invocation: async for chunk in client.chat.stream(...)"""
|
|
395
|
+
return self.completions.stream(
|
|
396
|
+
model=model,
|
|
397
|
+
prompt=prompt,
|
|
398
|
+
messages=messages,
|
|
399
|
+
system_instruction=system_instruction,
|
|
400
|
+
temperature=temperature,
|
|
401
|
+
max_tokens=max_tokens,
|
|
402
|
+
timeout=timeout,
|
|
403
|
+
)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""LiveKit multimodal audio/video sessions resource for OmniAI."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Optional
|
|
6
|
+
from omniai.types.livekit import LiveSessionInfo
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from omniai._base import BaseClient, AsyncBaseClient
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class LiveKitResource:
|
|
13
|
+
"""Synchronous LiveKit multimodal resource."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, client: BaseClient):
|
|
16
|
+
self._client = client
|
|
17
|
+
|
|
18
|
+
def create_session(
|
|
19
|
+
self,
|
|
20
|
+
*,
|
|
21
|
+
model: str = "gemini:gemini-2.5-flash",
|
|
22
|
+
voice: str = "Aoede",
|
|
23
|
+
video_input: bool = False,
|
|
24
|
+
timeout: Optional[float] = None,
|
|
25
|
+
) -> LiveSessionInfo:
|
|
26
|
+
"""Requests room and participant credentials for a LiveKit WebRTC session."""
|
|
27
|
+
response = self._client.client.post(
|
|
28
|
+
"/v1/live/token",
|
|
29
|
+
json={
|
|
30
|
+
"model": model,
|
|
31
|
+
"voice": voice,
|
|
32
|
+
"video_input": video_input,
|
|
33
|
+
},
|
|
34
|
+
timeout=timeout or self._client.timeout,
|
|
35
|
+
)
|
|
36
|
+
if response.status_code != 200:
|
|
37
|
+
self._client._handle_error_response(response)
|
|
38
|
+
|
|
39
|
+
data = response.json()
|
|
40
|
+
return LiveSessionInfo.model_validate(data)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class AsyncLiveKitResource:
|
|
44
|
+
"""Asynchronous LiveKit multimodal resource."""
|
|
45
|
+
|
|
46
|
+
def __init__(self, client: AsyncBaseClient):
|
|
47
|
+
self._client = client
|
|
48
|
+
|
|
49
|
+
async def create_session(
|
|
50
|
+
self,
|
|
51
|
+
*,
|
|
52
|
+
model: str = "gemini:gemini-2.5-flash",
|
|
53
|
+
voice: str = "Aoede",
|
|
54
|
+
video_input: bool = False,
|
|
55
|
+
timeout: Optional[float] = None,
|
|
56
|
+
) -> LiveSessionInfo:
|
|
57
|
+
"""Requests room and participant credentials for a LiveKit WebRTC session asynchronously."""
|
|
58
|
+
response = await self._client.client.post(
|
|
59
|
+
"/v1/live/token",
|
|
60
|
+
json={
|
|
61
|
+
"model": model,
|
|
62
|
+
"voice": voice,
|
|
63
|
+
"video_input": video_input,
|
|
64
|
+
},
|
|
65
|
+
timeout=timeout or self._client.timeout,
|
|
66
|
+
)
|
|
67
|
+
if response.status_code != 200:
|
|
68
|
+
self._client._handle_error_response(response)
|
|
69
|
+
|
|
70
|
+
data = response.json()
|
|
71
|
+
return LiveSessionInfo.model_validate(data)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Models catalog resource for OmniAI."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, List, Optional
|
|
6
|
+
from omniai.types.models import ModelInfo, ModelList
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from omniai._base import BaseClient, AsyncBaseClient
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ModelsResource:
|
|
13
|
+
"""Synchronous models resource."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, client: BaseClient):
|
|
16
|
+
self._client = client
|
|
17
|
+
|
|
18
|
+
def list(self, timeout: Optional[float] = None) -> ModelList:
|
|
19
|
+
"""Fetches list of all AI models supported by the OmniAI platform."""
|
|
20
|
+
response = self._client.client.get(
|
|
21
|
+
"/v1/models",
|
|
22
|
+
timeout=timeout or self._client.timeout,
|
|
23
|
+
)
|
|
24
|
+
if response.status_code != 200:
|
|
25
|
+
self._client._handle_error_response(response)
|
|
26
|
+
return ModelList.model_validate(response.json())
|
|
27
|
+
|
|
28
|
+
def retrieve(self, model_id: str, timeout: Optional[float] = None) -> ModelInfo:
|
|
29
|
+
"""Retrieves metadata for a specific model."""
|
|
30
|
+
response = self._client.client.get(
|
|
31
|
+
f"/v1/models/{model_id}",
|
|
32
|
+
timeout=timeout or self._client.timeout,
|
|
33
|
+
)
|
|
34
|
+
if response.status_code != 200:
|
|
35
|
+
self._client._handle_error_response(response)
|
|
36
|
+
return ModelInfo.model_validate(response.json())
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class AsyncModelsResource:
|
|
40
|
+
"""Asynchronous models resource."""
|
|
41
|
+
|
|
42
|
+
def __init__(self, client: AsyncBaseClient):
|
|
43
|
+
self._client = client
|
|
44
|
+
|
|
45
|
+
async def list(self, timeout: Optional[float] = None) -> ModelList:
|
|
46
|
+
"""Fetches list of all AI models asynchronously."""
|
|
47
|
+
response = await self._client.client.get(
|
|
48
|
+
"/v1/models",
|
|
49
|
+
timeout=timeout or self._client.timeout,
|
|
50
|
+
)
|
|
51
|
+
if response.status_code != 200:
|
|
52
|
+
self._client._handle_error_response(response)
|
|
53
|
+
return ModelList.model_validate(response.json())
|
|
54
|
+
|
|
55
|
+
async def retrieve(self, model_id: str, timeout: Optional[float] = None) -> ModelInfo:
|
|
56
|
+
"""Retrieves metadata for a specific model asynchronously."""
|
|
57
|
+
response = await self._client.client.get(
|
|
58
|
+
f"/v1/models/{model_id}",
|
|
59
|
+
timeout=timeout or self._client.timeout,
|
|
60
|
+
)
|
|
61
|
+
if response.status_code != 200:
|
|
62
|
+
self._client._handle_error_response(response)
|
|
63
|
+
return ModelInfo.model_validate(response.json())
|