Metadata-Version: 2.4
Name: easy-ai-clients
Version: 0.4.0
Summary: Unified multi-provider Python client for text, image, and audio AI APIs.
Project-URL: Homepage, https://pypi.org/project/easy-ai-clients/
Project-URL: Repository, https://github.com/reiarthur/easy-ai-clients
Project-URL: Issues, https://github.com/reiarthur/easy-ai-clients/issues
Author-email: Arthur <arthur@sart.dev>
License: MIT License
        
        Copyright (c) 2026 King Arthur
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: ai,anthropic,black-forest-labs,claude,cohere,deepgram,deepinfra,deepseek,elevenlabs,fal,fireworks,gemini,google,groq,huggingface,image-editing,image-generation,llm,mistral,multimodal,openai,openrouter,rev-ai,speech-to-text,speechmatics,stability,stt,text-generation,text-to-speech,together,tts,vision,xai
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Multimedia :: Graphics
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Requires-Dist: audioop-lts>=0.2; python_version >= '3.13'
Requires-Dist: httpx<1,>=0.28
Requires-Dist: imageio-ffmpeg<1,>=0.5
Requires-Dist: pillow<13,>=10
Requires-Dist: pydub<1,>=0.25
Requires-Dist: python-dotenv<2,>=1
Requires-Dist: requests<3,>=2.32
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: ruff>=0.11; extra == 'dev'
Requires-Dist: twine>=6.1; extra == 'dev'
Description-Content-Type: text/markdown

# easy-ai-clients

[![PyPI version](https://img.shields.io/pypi/v/easy-ai-clients.svg)](https://pypi.org/project/easy-ai-clients/)
[![Python versions](https://img.shields.io/pypi/pyversions/easy-ai-clients.svg)](https://pypi.org/project/easy-ai-clients/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

A unified, batteries-included Python client for **text**, **audio**, and
**image** AI APIs across many providers. Every operation has a single function
that takes the same parameters and an explicit `api=` argument selecting the
underlying provider — so you can swap providers without rewriting your code.

## Supported operations

| Module | Function | Purpose | Providers |
| --- | --- | --- | --- |
| `text` | `generate` | Text-in / text-out generation | `anthropic`, `cohere`, `deepinfra`, `deepseek`, `fal`, `fireworks`, `google`, `groq`, `huggingface`, `mistral`, `openai`, `openrouter`, `together`, `xai` |
| `audio` | `generate` | Text-to-speech synthesis | `deepinfra`, `elevenlabs`, `google`, `mistral`, `openai`, `together`, `xai` |
| `audio` | `transcribe` | Speech-to-text transcription | `deepgram`, `elevenlabs`, `falai`, `fireworks`, `revai`, `speechmatics`, `together` |
| `image` | `generate` | Text-to-image generation | `bfl`, `falai`, `fireworks`, `google`, `openai`, `openrouter`, `stability`, `together`, `xai` |
| `image` | `edit` | Prompt + mask editing | `bfl`, `falai`, `fireworks`, `google`, `openai`, `openrouter`, `stability`, `together`, `xai` |
| `image` | `remix` | Reference-image guided generation | `bfl`, `falai`, `fireworks`, `google`, `openai`, `openrouter`, `stability`, `together`, `xai` |
| `image` | `analyze` | Vision/multimodal analysis | `anthropic`, `falai`, `fireworks`, `google`, `groq`, `openai`, `openrouter`, `together`, `xai` |

The full provider/model matrix and per-provider parameters are in
[`docs/providers.md`](docs/providers.md).

## Requirements

- Python `>= 3.11`
- Runtime dependencies are installed automatically by `pip`:
  `requests`, `httpx`, `Pillow`, `pydub`, `imageio-ffmpeg`, `python-dotenv`,
  and `audioop-lts` on Python `>= 3.13`.

## Install

```bash
pip install easy-ai-clients
```

## Checking the version

```python
import easy_ai_clients
print(easy_ai_clients.__version__)
```

## Configuration

`easy-ai-clients` does **not** auto-load `.env` from the package directory.
The recommended way is to set environment variables in your shell or load a
`.env` file explicitly with [`python-dotenv`](https://pypi.org/project/python-dotenv/):

```python
from dotenv import load_dotenv
load_dotenv()
```

Each provider only needs the credentials for the API you intend to call. See
[`.env.example`](.env.example) for the full list of recognised variables and
[`docs/configuration.md`](docs/configuration.md) for the credential resolution
flow.

## Quickstart

```python
from dotenv import load_dotenv
from easy_ai_clients import text, audio, image

load_dotenv()

# Text generation
result = text.generate(
    "Summarise the plot of Don Quixote in two sentences.",
    instruction="Answer in Brazilian Portuguese.",
    api="openai",
)
print(result["output_text"], "USD:", result["cost_usd"])

# Speech synthesis
speech = audio.generate(
    "Hello world from easy-ai-clients!",
    voice="alloy",
    language_code="en",
    api="openai",
)
speech["audio"].export("hello.mp3", format="mp3")

# Speech transcription
transcript = audio.transcribe("hello.mp3", api="deepgram")
print(transcript["text"])

# Image generation
import base64
img = image.generate("a corgi astronaut on the moon", api="openai")
with open("corgi.png", "wb") as fh:
    fh.write(base64.b64decode(img["base64"]))

# Image editing
edited = image.edit(
    "make it night with neon lights",
    "corgi.png",
    api="openai",
)

# Image remix (reference-image guided)
remix = image.remix(
    "studio ghibli style",
    ["corgi.png"],
    api="openai",
)

# Vision analysis
description = image.analyze(
    "Describe this image in one sentence.",
    "corgi.png",
    api="openai",
)
print(description["output"])
```

You can also import dispatchers directly:

```python
from easy_ai_clients.text import generate as text_generate
from easy_ai_clients.audio import transcribe
from easy_ai_clients.image import analyze
```

## Selecting an API

Every dispatcher accepts an `api` keyword argument. The string must match the
file name (without `.py`) of an internal provider module shipped with the
library. Inspect them programmatically:

```python
from easy_ai_clients import text, audio, image

text.available_apis()
audio.available_synthesize_apis()
audio.available_transcribe_apis()
image.available_generate_apis()
image.available_edit_apis()
image.available_remix_apis()
image.available_analyze_apis()
```

## Public return contracts

| Operation | Returns |
| --- | --- |
| `text.generate(...)` | `{"request_id", "cost_source", "cost_usd", "input_text", "instruction"?, "output_text"}` |
| `audio.generate(...)` | `{"cost_usd", "audio": pydub.AudioSegment, "words": [...]}` |
| `audio.transcribe(...)` | Normalised bundle with `text`, `words`, `segments`, `speakers`, `silences`, `cost_usd`, `request_id`, optional `mkd` markdown |
| `image.generate / edit / remix(...)` | `{"cust_usd", "base64", "warnings", "request_id"}` |
| `image.analyze(...)` | `{"request_id", "cost_usd", "input_text", "output"}` |

## Forwarding provider-native parameters

All dispatchers accept extra keyword arguments and forward them verbatim to the
underlying provider. Unsupported parameters are rejected with a clear error
message before any network call is made:

```python
text.generate(
    "ping",
    api="openai",
    model="gpt-5-mini",
    reasoning="minimal",
    temperature=0.2,
    max_output_tokens=80,
)

image.generate(
    "a serene lake at dawn",
    api="stability",
    model="stable-image-ultra",
    aspect_ratio="16:9",
    output_format="png",
)
```

## Error handling

Errors raise standard Python exceptions. Image operations also surface
provider-side problems via the `warnings` field in the public result instead
of raising, when the provider responds with a structured error.

```python
try:
    result = text.generate("hi", api="openai", thisparamdoesnotexist=True)
except ValueError as exc:
    print("rejected before sending:", exc)

try:
    result = text.generate("hi", api="openai")
except RuntimeError as exc:
    print("provider/network failure:", exc)
```

A complete reference is in [`docs/errors.md`](docs/errors.md).

## Additional documentation

- [`docs/configuration.md`](docs/configuration.md) — credentials and environment
  variables.
- [`docs/providers.md`](docs/providers.md) — provider-by-provider parameters and
  models.
- [`docs/errors.md`](docs/errors.md) — exception model and provider-specific
  failures.

## Contributing

Issues and pull requests are welcome. See [`CONTRIBUTING.md`](CONTRIBUTING.md)
for the local development workflow.

## License

MIT — see [`LICENSE`](LICENSE).
