# CLI Client для Model Provider API
**CLI Client** – это асинхронная библиотека для взаимодействия с API-сервером, предоставляющим расширенный функционал:
• Генерация текстов
• Создание изображений
• Транскрибация аудио
• Синтез речи
• Получение доступных моделей по провайдеру и типу возможности
Библиотека позволяет использовать как синхронный, так и потоковый (streaming) режим работы через HTTP (aiohttp). Кроме того, она уже интегрирована с консольной утилитой, позволяющей вызывать основные функции напрямую из терминала.
------------------------------------------------------------
## Требования и установка
Для работы клиента необходим Python 3.8+ и следующие зависимости:
- asyncio
- aiohttp (для HTTP-запросов)
- (для разработки/тестирования) pytest, pytest-asyncio
Установку библиотеки из PyPI можно выполнить командой:
```
pip install cli-client
```
Если вы разрабатываете локально, установите зависимости через pip:
```
pip install aiohttp pytest pytest-asyncio
```
------------------------------------------------------------
## Быстрый старт
Ниже приведён пример базового использования клиента:
```
import asyncio
from cli_client import APIClient, Provider
async def main():
# Инициализация клиента с указанием базового URL сервера
client = APIClient(base_url="http://your-api-server:8000")
# Пример генерации текста
result_text = await client.generate_text(
message="Привет, расскажи анекдот",
provider=Provider.OPENAI
)
print("Сгенерированный текст:", result_text)
# Пример генерации изображения
result_image = await client.generate_image(
prompt="A futuristic cityscape",
provider=Provider.OPENAI,
size="1024x1024"
)
print("Результат генерации изображения:", result_image)
# Пример транскрибации аудио (файл читается как бинарные данные)
with open("audio_sample.mp3", "rb") as f:
audio_data = f.read()
transcription = await client.process_audio(
audio_file=audio_data,
provider=Provider.OPENAI,
format_output="json"
)
print("Результат транскрипции аудио:", transcription)
# Пример синтеза речи
voice_result = await client.generate_voice(
text="Привет, как дела?",
provider=Provider.OPENAI
)
print("Результаты синтеза речи:", voice_result)
# Пример получения доступных моделей для текстовой генерации
models = await client.get_available_models(provider=Provider.OPENAI, capability="text")
print("Доступные модели для текста:", models)
await client.close()
asyncio.run(main())
```
Также клиент можно запускать через консольную утилиту:
```
cli-client --ip http://localhost:8000 --provider openai --endpoint text --message "Привет, расскажи анекдот"
```
------------------------------------------------------------
## Основные функции и их возможности
### 1. Генерация текста – generate_text
Функция позволяет получить сгенерированный текст с учетом дополнительных параметров. При необходимости можно передать изображение в виде байтов или base64-строки для создания контекста.
**Параметры:**
- **message** (str): Основной текст запроса.
- **provider** (Provider): Провайдер генерации (например, OPENAI, GEMINI и др.).
- **model** (Optional[str]): Название модели, если требуется.
- **image_bytes** (Optional[Union[bytes, str]]): Байты изображения или base64-строка.
- **max_tokens** (int): Максимальное число токенов (по умолчанию 150).
- **temperature** (float): Параметр «тёплоты» генерации (по умолчанию 0.7).
- **stream** (bool): Если True, функция возвращает асинхронный генератор для потокового вывода.
**Пример использования:**
```
result = await client.generate_text(
message="Расскажи интересную историю",
provider=Provider.ANTHROPIC,
max_tokens=300
)
print(result)
```
------------------------------------------------------------
### 2. Генерация изображения – generate_image
Функция отправляет текстовое описание (prompt) и возвращает сгенерированное изображение (например, URL).
**Параметры:**
- **prompt** (str): Описание изображения.
- **provider** (Provider): Провайдер генерации изображений.
- **model** (Optional[str]): Название модели (если требуется).
- **size** (str): Размер изображения (например, "1024x1024").
**Пример использования:**
```
result = await client.generate_image(
prompt="A serene landscape with mountains",
provider=Provider.OPENAI
)
print(result)
```
------------------------------------------------------------
### 3. Обработка аудио – process_audio
Позволяет передать аудиофайл для транскрибации (распознавания речи).
**Параметры:**
- **audio_file** (bytes): Байты аудиофайла.
- **provider** (Provider): Провайдер обработки аудио.
- **mode** (Optional[str]): Режим обработки (если имеется несколько).
- **format_output** (str): Формат вывода ("text" или "json").
- **async_process** (bool): Флаг асинхронной обработки (True – возвращается job_id).
- **transcriptions** (Optional[Dict[str, Any]]): Дополнительные параметры транскрипции.
**Пример использования:**
```
with open("audio_sample.mp3", "rb") as f:
audio_data = f.read()
transcription = await client.process_audio(
audio_file=audio_data,
provider=Provider.OPENAI,
format_output="json",
transcriptions={"task": "transcribe"}
)
print(transcription)
```
------------------------------------------------------------
### 4. Синтез речи – generate_voice
Функция для преобразования текста в речь. Возвращает словарь с результатами (например, аудио в формате base64).
**Параметры:**
- **text** (str): Исходный текст для озвучивания.
- **provider** (Provider): Провайдер синтеза речи.
- **model** (Optional[str]): Название модели (если требуется).
**Пример использования:**
```
voice_data = await client.generate_voice(
text="Добрый день!",
provider=Provider.OPENAI
)
print(voice_data)
```
------------------------------------------------------------
### 5. Получение доступных моделей – get_available_models
Позволяет получить список моделей, доступных у провайдера для конкретной функциональности (например, текст, изображение, аудио).
**Параметры:**
- **provider** (Optional[Union[Provider, str]]): Имя провайдера.
- **capability** (Optional[Union[Capability, str]]): Тип функциональности (например, "text", "vision").
**Пример использования:**
```
models = await client.get_available_models(provider=Provider.OPENAI, capability="text")
print("Доступные модели:", models)
```
------------------------------------------------------------
## Модель данных для управления отправкой запроса
Для валидации и корректной упаковки параметров можно использовать Pydantic-модель. Например:
```
from pydantic import BaseModel, Field
from typing import List, Optional, Union
class TextGenerationRequest(BaseModel):
message: str
provider: str
model: Optional[str] = None
max_tokens: int = Field(default=150, ge=1)
temperature: float = Field(default=0.7, ge=0, le=1)
stream: bool = False
system: Optional[str] = ""
messages: Optional[List[dict]] = []
reasoning_effort: Optional[str] = None
image_bytes: Optional[Union[str, bytes]] = None
```
Такой подход позволит гарантировать корректность типов и упростить дальнейшую отладку и расширение функционала.
------------------------------------------------------------
## Структура проекта
Пример рекомендуемой структуры клиентского проекта:
```
MyClientCLI/
├── cli_client/ # Основной пакет библиотеки
│ ├── __init__.py
│ ├── client.py # Класс APIClient с реализацией функций generate_text, generate_image, process_audio, generate_voice, get_available_models
│ ├── config.py # Загрузка конфигураций из переменных окружения и INI-файлов
│ ├── exceptions.py # Пользовательские исключения (APIClientError, ServerError, AuthenticationError, ProviderNotImplementedError)
│ ├── utils.py # Вспомогательные классы и перечисления (Provider, Capability)
│ ├── models.py # Вспомогательные классы
│ └── __main__.py # Точка входа для CLI (функция main)
├── tests/ # Тесты (например, test_client.py)
│ └── test_client.py
├── LICENSE # Лицензия проекта
├── README.md # Данный файл описания
└── pyproject.toml # Конфигурация сборки и метаданные пакета
```
------------------------------------------------------------
## Дальнейшие возможности расширения функционала
Помимо описанных функций, возможны следующие доработки:
• Реализация асинхронного контекстного менеджера (добавить методы __aenter__ и __aexit__) для удобного использования:
```
async with APIClient(base_url="http://localhost:8000") as client:
# работа с клиентом
```
• Интеграция расширенного логирования (модуль logging) для отладки запросов и ответов.
• Механизм повторных попыток (retries) с экспоненциальной задержкой для временных сбоев подключения.
• Локальное кэширование результатов вызова get_available_models и других часто запрашиваемых данных.
• Расширение возможностей CLI (добавление новых аргументов, настройка дополнительных эндпоинтов и поддержки websocket‑подключений).
• Автоматизированное тестирование (с использованием pytest и CI/CD сервисов).
------------------------------------------------------------
## Лицензия
Этот проект распространяется под лицензией MIT. Подробности смотрите в файле [LICENSE](LICENSE).
------------------------------------------------------------
## Вывод
**CLI Client для Model Provider API** представляет собой мощное решение для интеграции с сервером генерации контента. Библиотека поддерживает не только базовые функции (текст, изображение, аудио), но и расширенные возможности потоковой обработки и асинхронного взаимодействия. Рекомендуется ознакомиться с примерами использования, протестировать работу на тестовом сервере и при необходимости расширять функционал с учётом требований вашего проекта.
Для любых вопросов или предложений по улучшению, пожалуйста, обращайтесь к разработчику.
------------------------------------------------------------
Raw data
{
"_id": null,
"home_page": "https://github.com/your_username/cli-client",
"name": "cli-client",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "cli, api, aiohttp, client",
"author": "SensoryLAB",
"author_email": "SensoryLAB <fox@sensorylab.ru>",
"download_url": "https://files.pythonhosted.org/packages/ca/43/a83428599709b9d4bf7a158f7f6e52f92fedc7e9623a5601bd110e216e37/cli_client-0.1.0.tar.gz",
"platform": null,
"description": "# CLI Client \u0434\u043b\u044f Model Provider API\r\n\r\n**CLI Client** \u2013 \u044d\u0442\u043e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 API-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u043c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b:\r\n \r\n\u2022 \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u043e\u0432 \r\n\u2022 \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \r\n\u2022 \u0422\u0440\u0430\u043d\u0441\u043a\u0440\u0438\u0431\u0430\u0446\u0438\u044f \u0430\u0443\u0434\u0438\u043e \r\n\u2022 \u0421\u0438\u043d\u0442\u0435\u0437 \u0440\u0435\u0447\u0438 \r\n\u2022 \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u043f\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0443 \u0438 \u0442\u0438\u043f\u0443 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438\r\n\r\n\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439, \u0442\u0430\u043a \u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0439 (streaming) \u0440\u0435\u0436\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u044b \u0447\u0435\u0440\u0435\u0437 HTTP (aiohttp). \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043e\u043d\u0430 \u0443\u0436\u0435 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0441 \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u043e\u0439 \u0443\u0442\u0438\u043b\u0438\u0442\u043e\u0439, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0435\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0438\u0437 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430.\r\n\r\n------------------------------------------------------------\r\n## \u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430\r\n\r\n\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c Python 3.8+ \u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:\r\n\r\n- asyncio\r\n- aiohttp (\u0434\u043b\u044f HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432)\r\n- (\u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438/\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f) pytest, pytest-asyncio\r\n\r\n\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438\u0437 PyPI \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439:\r\n```\r\npip install cli-client\r\n```\r\n\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0447\u0435\u0440\u0435\u0437 pip:\r\n```\r\npip install aiohttp pytest pytest-asyncio\r\n```\r\n------------------------------------------------------------\r\n## \u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u0442\u0430\u0440\u0442\r\n\r\n\u041d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d \u043f\u0440\u0438\u043c\u0435\u0440 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430:\r\n```\r\nimport asyncio\r\nfrom cli_client import APIClient, Provider\r\n\r\nasync def main():\r\n # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e URL \u0441\u0435\u0440\u0432\u0435\u0440\u0430\r\n client = APIClient(base_url=\"http://your-api-server:8000\")\r\n \r\n # \u041f\u0440\u0438\u043c\u0435\u0440 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0442\u0435\u043a\u0441\u0442\u0430\r\n result_text = await client.generate_text(\r\n message=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0438 \u0430\u043d\u0435\u043a\u0434\u043e\u0442\",\r\n provider=Provider.OPENAI\r\n )\r\n print(\"\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442:\", result_text)\r\n \r\n # \u041f\u0440\u0438\u043c\u0435\u0440 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f\r\n result_image = await client.generate_image(\r\n prompt=\"A futuristic cityscape\",\r\n provider=Provider.OPENAI,\r\n size=\"1024x1024\"\r\n )\r\n print(\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f:\", result_image)\r\n \r\n # \u041f\u0440\u0438\u043c\u0435\u0440 \u0442\u0440\u0430\u043d\u0441\u043a\u0440\u0438\u0431\u0430\u0446\u0438\u0438 \u0430\u0443\u0434\u0438\u043e (\u0444\u0430\u0439\u043b \u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435)\r\n with open(\"audio_sample.mp3\", \"rb\") as f:\r\n audio_data = f.read()\r\n transcription = await client.process_audio(\r\n audio_file=audio_data,\r\n provider=Provider.OPENAI,\r\n format_output=\"json\"\r\n )\r\n print(\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0442\u0440\u0430\u043d\u0441\u043a\u0440\u0438\u043f\u0446\u0438\u0438 \u0430\u0443\u0434\u0438\u043e:\", transcription)\r\n \r\n # \u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u0438\u043d\u0442\u0435\u0437\u0430 \u0440\u0435\u0447\u0438\r\n voice_result = await client.generate_voice(\r\n text=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u043a\u0430\u043a \u0434\u0435\u043b\u0430?\",\r\n provider=Provider.OPENAI\r\n )\r\n print(\"\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0438\u043d\u0442\u0435\u0437\u0430 \u0440\u0435\u0447\u0438:\", voice_result)\r\n \r\n # \u041f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0434\u043b\u044f \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438\r\n models = await client.get_available_models(provider=Provider.OPENAI, capability=\"text\")\r\n print(\"\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u043b\u044f \u0442\u0435\u043a\u0441\u0442\u0430:\", models)\r\n \r\n await client.close()\r\n\r\nasyncio.run(main())\r\n```\r\n\u0422\u0430\u043a\u0436\u0435 \u043a\u043b\u0438\u0435\u043d\u0442 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u0443\u044e \u0443\u0442\u0438\u043b\u0438\u0442\u0443:\r\n```\r\ncli-client --ip http://localhost:8000 --provider openai --endpoint text --message \"\u041f\u0440\u0438\u0432\u0435\u0442, \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0438 \u0430\u043d\u0435\u043a\u0434\u043e\u0442\"\r\n```\r\n------------------------------------------------------------\r\n## \u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u0438\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438\r\n\r\n### 1. \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u2013 generate_text\r\n\r\n\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. \u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432 \u0432\u0438\u0434\u0435 \u0431\u0430\u0439\u0442\u043e\u0432 \u0438\u043b\u0438 base64-\u0441\u0442\u0440\u043e\u043a\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430.\r\n\r\n**\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:**\r\n- **message** (str): \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0442\u0435\u043a\u0441\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.\r\n- **provider** (Provider): \u041f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, OPENAI, GEMINI \u0438 \u0434\u0440.).\r\n- **model** (Optional[str]): \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438, \u0435\u0441\u043b\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f.\r\n- **image_bytes** (Optional[Union[bytes, str]]): \u0411\u0430\u0439\u0442\u044b \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 base64-\u0441\u0442\u0440\u043e\u043a\u0430.\r\n- **max_tokens** (int): \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0442\u043e\u043a\u0435\u043d\u043e\u0432 (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e 150).\r\n- **temperature** (float): \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u00ab\u0442\u0451\u043f\u043b\u043e\u0442\u044b\u00bb \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e 0.7).\r\n- **stream** (bool): \u0415\u0441\u043b\u0438 True, \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0433\u043e \u0432\u044b\u0432\u043e\u0434\u0430.\r\n\r\n**\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:**\r\n```\r\nresult = await client.generate_text(\r\n message=\"\u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0443\u044e \u0438\u0441\u0442\u043e\u0440\u0438\u044e\",\r\n provider=Provider.ANTHROPIC,\r\n max_tokens=300\r\n)\r\nprint(result)\r\n```\r\n------------------------------------------------------------\r\n### 2. \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u2013 generate_image\r\n\r\n\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 (prompt) \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, URL).\r\n\r\n**\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:**\r\n- **prompt** (str): \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f.\r\n- **provider** (Provider): \u041f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439.\r\n- **model** (Optional[str]): \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 (\u0435\u0441\u043b\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f).\r\n- **size** (str): \u0420\u0430\u0437\u043c\u0435\u0440 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \"1024x1024\").\r\n\r\n**\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:**\r\n```\r\nresult = await client.generate_image(\r\n prompt=\"A serene landscape with mountains\",\r\n provider=Provider.OPENAI\r\n)\r\nprint(result)\r\n```\r\n------------------------------------------------------------\r\n### 3. \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0430\u0443\u0434\u0438\u043e \u2013 process_audio\r\n\r\n\u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0430\u0443\u0434\u0438\u043e\u0444\u0430\u0439\u043b \u0434\u043b\u044f \u0442\u0440\u0430\u043d\u0441\u043a\u0440\u0438\u0431\u0430\u0446\u0438\u0438 (\u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u043d\u0438\u044f \u0440\u0435\u0447\u0438).\r\n\r\n**\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:**\r\n- **audio_file** (bytes): \u0411\u0430\u0439\u0442\u044b \u0430\u0443\u0434\u0438\u043e\u0444\u0430\u0439\u043b\u0430.\r\n- **provider** (Provider): \u041f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0430\u0443\u0434\u0438\u043e.\r\n- **mode** (Optional[str]): \u0420\u0435\u0436\u0438\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 (\u0435\u0441\u043b\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e).\r\n- **format_output** (str): \u0424\u043e\u0440\u043c\u0430\u0442 \u0432\u044b\u0432\u043e\u0434\u0430 (\"text\" \u0438\u043b\u0438 \"json\").\r\n- **async_process** (bool): \u0424\u043b\u0430\u0433 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 (True \u2013 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f job_id).\r\n- **transcriptions** (Optional[Dict[str, Any]]): \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0442\u0440\u0430\u043d\u0441\u043a\u0440\u0438\u043f\u0446\u0438\u0438.\r\n\r\n**\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:**\r\n```\r\nwith open(\"audio_sample.mp3\", \"rb\") as f:\r\n audio_data = f.read()\r\n\r\ntranscription = await client.process_audio(\r\n audio_file=audio_data,\r\n provider=Provider.OPENAI,\r\n format_output=\"json\",\r\n transcriptions={\"task\": \"transcribe\"}\r\n)\r\nprint(transcription)\r\n```\r\n------------------------------------------------------------\r\n### 4. \u0421\u0438\u043d\u0442\u0435\u0437 \u0440\u0435\u0447\u0438 \u2013 generate_voice\r\n\r\n\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u0440\u0435\u0447\u044c. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043b\u043e\u0432\u0430\u0440\u044c \u0441 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u043c\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0430\u0443\u0434\u0438\u043e \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 base64).\r\n\r\n**\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:**\r\n- **text** (str): \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u043e\u0437\u0432\u0443\u0447\u0438\u0432\u0430\u043d\u0438\u044f.\r\n- **provider** (Provider): \u041f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u0441\u0438\u043d\u0442\u0435\u0437\u0430 \u0440\u0435\u0447\u0438.\r\n- **model** (Optional[str]): \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 (\u0435\u0441\u043b\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f).\r\n\r\n**\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:**\r\n```\r\nvoice_data = await client.generate_voice(\r\n text=\"\u0414\u043e\u0431\u0440\u044b\u0439 \u0434\u0435\u043d\u044c!\",\r\n provider=Provider.OPENAI\r\n)\r\nprint(voice_data)\r\n```\r\n------------------------------------------------------------\r\n### 5. \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u2013 get_available_models\r\n\r\n\u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0443 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0435\u043a\u0441\u0442, \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0430\u0443\u0434\u0438\u043e).\r\n\r\n**\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:**\r\n- **provider** (Optional[Union[Provider, str]]): \u0418\u043c\u044f \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430.\r\n- **capability** (Optional[Union[Capability, str]]): \u0422\u0438\u043f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \"text\", \"vision\").\r\n\r\n**\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:**\r\n```\r\nmodels = await client.get_available_models(provider=Provider.OPENAI, capability=\"text\")\r\nprint(\"\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438:\", models)\r\n```\r\n------------------------------------------------------------\r\n## \u041c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\r\n\r\n\u0414\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Pydantic-\u043c\u043e\u0434\u0435\u043b\u044c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:\r\n```\r\nfrom pydantic import BaseModel, Field\r\nfrom typing import List, Optional, Union\r\n\r\nclass TextGenerationRequest(BaseModel):\r\n message: str\r\n provider: str\r\n model: Optional[str] = None\r\n max_tokens: int = Field(default=150, ge=1)\r\n temperature: float = Field(default=0.7, ge=0, le=1)\r\n stream: bool = False\r\n system: Optional[str] = \"\"\r\n messages: Optional[List[dict]] = []\r\n reasoning_effort: Optional[str] = None\r\n image_bytes: Optional[Union[str, bytes]] = None\r\n```\r\n\u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c \u0442\u0438\u043f\u043e\u0432 \u0438 \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0443\u044e \u043e\u0442\u043b\u0430\u0434\u043a\u0443 \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430.\r\n\r\n------------------------------------------------------------\r\n## \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\r\n\r\n\u041f\u0440\u0438\u043c\u0435\u0440 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430:\r\n```\r\nMyClientCLI/\r\n\u251c\u2500\u2500 cli_client/ # \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u0430\u043a\u0435\u0442 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438\r\n\u2502 \u251c\u2500\u2500 __init__.py\r\n\u2502 \u251c\u2500\u2500 client.py # \u041a\u043b\u0430\u0441\u0441 APIClient \u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 generate_text, generate_image, process_audio, generate_voice, get_available_models\r\n\u2502 \u251c\u2500\u2500 config.py # \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439 \u0438\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0438 INI-\u0444\u0430\u0439\u043b\u043e\u0432\r\n\u2502 \u251c\u2500\u2500 exceptions.py # \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f (APIClientError, ServerError, AuthenticationError, ProviderNotImplementedError)\r\n\u2502 \u251c\u2500\u2500 utils.py # \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u0438 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f (Provider, Capability)\r\n\u2502 \u251c\u2500\u2500 models.py # \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \r\n\u2502 \u2514\u2500\u2500 __main__.py # \u0422\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u0434\u043b\u044f CLI (\u0444\u0443\u043d\u043a\u0446\u0438\u044f main)\r\n\u251c\u2500\u2500 tests/ # \u0422\u0435\u0441\u0442\u044b (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, test_client.py)\r\n\u2502 \u2514\u2500\u2500 test_client.py\r\n\u251c\u2500\u2500 LICENSE # \u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430\r\n\u251c\u2500\u2500 README.md # \u0414\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f\r\n\u2514\u2500\u2500 pyproject.toml # \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u0430\r\n```\r\n------------------------------------------------------------\r\n## \u0414\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430\r\n\r\n\u041f\u043e\u043c\u0438\u043c\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438:\r\n\r\n\u2022 \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0430 (\u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b __aenter__ \u0438 __aexit__) \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:\r\n```\r\nasync with APIClient(base_url=\"http://localhost:8000\") as client:\r\n # \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u043c\r\n```\r\n\u2022 \u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0433\u043e \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u043c\u043e\u0434\u0443\u043b\u044c logging) \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u043e\u0442\u0432\u0435\u0442\u043e\u0432.\r\n\r\n\u2022 \u041c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0445 \u043f\u043e\u043f\u044b\u0442\u043e\u043a (retries) \u0441 \u044d\u043a\u0441\u043f\u043e\u043d\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439 \u0434\u043b\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0441\u0431\u043e\u0435\u0432 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f.\r\n\r\n\u2022 \u041b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0432\u044b\u0437\u043e\u0432\u0430 get_available_models \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0447\u0430\u0441\u0442\u043e \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.\r\n\r\n\u2022 \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 CLI (\u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u044b\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u043e\u0432 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 websocket\u2011\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439).\r\n\r\n\u2022 \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 (\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c pytest \u0438 CI/CD \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432).\r\n\r\n------------------------------------------------------------\r\n## \u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f\r\n\r\n\u042d\u0442\u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0435\u0439 MIT. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0432 \u0444\u0430\u0439\u043b\u0435 [LICENSE](LICENSE).\r\n\r\n------------------------------------------------------------\r\n## \u0412\u044b\u0432\u043e\u0434\r\n\r\n**CLI Client \u0434\u043b\u044f Model Provider API** \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043c\u043e\u0449\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 (\u0442\u0435\u043a\u0441\u0442, \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0430\u0443\u0434\u0438\u043e), \u043d\u043e \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f, \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043d\u0430 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0438 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430.\r\n\r\n\u0414\u043b\u044f \u043b\u044e\u0431\u044b\u0445 \u0432\u043e\u043f\u0440\u043e\u0441\u043e\u0432 \u0438\u043b\u0438 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043f\u043e \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044e, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043e\u0431\u0440\u0430\u0449\u0430\u0439\u0442\u0435\u0441\u044c \u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443.\r\n\r\n------------------------------------------------------------\r\n",
"bugtrack_url": null,
"license": null,
"summary": "CLI \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 Model Provider API",
"version": "0.1.0",
"project_urls": {
"Homepage": "https://github.com/your_username/cli-client"
},
"split_keywords": [
"cli",
" api",
" aiohttp",
" client"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "f1e782de31d49734dbc52964ca9afe721983f4fa7fb3bd6c0367ddd6b31a1bfa",
"md5": "ac58ace0194a6fc7c8b7ce88379cfce4",
"sha256": "246ba08a2b8e6de5714e0fe0363104e5c08dba24a82e61254cfc6aa69753c354"
},
"downloads": -1,
"filename": "cli_client-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ac58ace0194a6fc7c8b7ce88379cfce4",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 13696,
"upload_time": "2025-02-18T02:37:13",
"upload_time_iso_8601": "2025-02-18T02:37:13.169841Z",
"url": "https://files.pythonhosted.org/packages/f1/e7/82de31d49734dbc52964ca9afe721983f4fa7fb3bd6c0367ddd6b31a1bfa/cli_client-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "ca43a83428599709b9d4bf7a158f7f6e52f92fedc7e9623a5601bd110e216e37",
"md5": "4635fe1bcd6131c1572a119f66f81ac2",
"sha256": "f7ba9ccbaf35adb086f83bdbc1413208c5b1ea0b29555bad5f6204edf17fe9c9"
},
"downloads": -1,
"filename": "cli_client-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "4635fe1bcd6131c1572a119f66f81ac2",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 17526,
"upload_time": "2025-02-18T02:37:14",
"upload_time_iso_8601": "2025-02-18T02:37:14.469661Z",
"url": "https://files.pythonhosted.org/packages/ca/43/a83428599709b9d4bf7a158f7f6e52f92fedc7e9623a5601bd110e216e37/cli_client-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-02-18 02:37:14",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "your_username",
"github_project": "cli-client",
"github_not_found": true,
"lcname": "cli-client"
}