cli-client


Namecli-client JSON
Version 0.1.0 PyPI version JSON
download
home_pagehttps://github.com/your_username/cli-client
SummaryCLI клиент для взаимодействия с Model Provider API
upload_time2025-02-18 02:37:14
maintainerNone
docs_urlNone
authorSensoryLAB
requires_python>=3.8
licenseNone
keywords cli api aiohttp client
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 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"
}
        
Elapsed time: 1.00220s