Skip to main content

addisai (Python)

The official Addis AI SDK for Python — voice (text‑to‑speech), chat/LLM with system prompts, personas and function calling, speech‑to‑text, and translation, with examples for Amharic (am), Afaan Oromo (om), and Tigrinya (ti).

Mirrors the Node.js SDK surface, Pythonic and snake_case.

pip install addisai

Requires Python 3.8+.

Quickstart

from addisai import AddisAI

addis = AddisAI()  # reads ADDIS_API_KEY from the environment

# Text-to-speech
clip = addis.voice.generate(voice_id="am-hamen", text="ሰላም ለዓለም።", language="am")
clip.to_file("welcome.mp3")

# Chat
res = addis.chat.completions.create(
    language="am",
    system="Answer in concise bullet points.",
    messages=[{"role": "user", "content": "ስለ አዲስ አበባ ንገረኝ"}],
)
print(res["choices"][0]["message"]["content"])

Configuration

addis = AddisAI(
    api_key="...",        # or set ADDIS_API_KEY
    timeout=60.0,          # seconds (voice.generate raises this to >= 95s)
    max_retries=2,         # backoff on 408/409/425/429/5xx
)

The key is read from api_key= or ADDIS_API_KEY, never logged, and redacted in repr(). The SDK only talks to the Cloudflare‑wrapped API and refuses raw *.supabase.co hosts.

Languages

Language Code Example voice Voice ID
Amharic am Hamen am-hamen
Afaan Oromo om Bikila om-bikila
Tigrinya ti Berhane ti-berhane

Voice generation and real-time sessions support these three languages. Other language codes are rejected locally before any API request or socket connection. Use a matching language and voice ID. voices.list returns this three-language catalog so you can choose another available voice.

Voice (text‑to‑speech)

clip = addis.voice.generate(
    voice_id="am-hamen",
    text="ሰላም።",
    language="am",
    output_format="mp3_44100",                 # mp3_44100 | wav_44100 | pcm_16000
    voice_settings={"speed": 50, "stability": 50, "similarity": 50, "style": 0},
)
clip.audio_url
clip.usage          # {"credits_used": ..., "currency": "ETB", ...}
data = clip.content()   # bytes
clip.to_file("out.mp3")

Idempotency keys are generated automatically and reused across retries so a retry is never double‑billed. Pass client_request_id= for full control.

addis.voices.list(language="am", gender="female")
addis.voice.estimate(voice_id="am-hamen", text="ሰላም", language="am")
addis.voice.usage()
for clip in addis.voice.clips.list(language="am"):  # auto-paginates
    print(clip.id)
addis.voice.clips.delete("clip_123")

Real-time voice

from uuid import uuid4

# Select a matching pair from the Languages table.
voice_id, language = "ti-berhane", "ti"
text = "ሰላም፣ እንቋዕ ናብ ኣዲስ ኤኣይ ብደሓን መጻእኩም።"

# HTTP streaming: no extra dependency needed.
audio = addis.voice.stream(
    voice_id=voice_id, language=language, text=text,
    client_request_id=str(uuid4()),
)
audio.to_file("speech.mp3")
print(audio.metadata["usage"])

# Persistent sockets: pip install "addisai[realtime]"
with addis.realtime.connect(voice_id=voice_id, language=language) as voice:
    with open("speech.mp3", "wb") as output:
        for chunk in voice.speak(text, str(uuid4())):
            output.write(chunk)
    print(voice.last_completion["usage"])

realtime.create_session() creates a scoped, one-use ticket valid for 60 seconds; connect_realtime(ticket) opens its socket without a developer key. Keep keys on your application server. Sessions last up to 10 minutes, allow one utterance at a time, and carry a cumulative text budget of up to 5,000 characters. Cancellation mutes delivery; an already-started synthesis completes and is billed.

Use append() and commit() to buffer a complete generated utterance before synthesis. For early WAV pieces, select audio_format="wav_mp3", iterate raw audio.delta events and use decode_realtime_audio(event); play each piece according to its format. speak() yields concatenatable MP3 and requires an mp3 session. Use any matching voice and language pair from the Languages table. HTTP streams support MP3 only. Keep request IDs stable when recovering a failed request in a new session to avoid a second charge; use a fresh ID for each new utterance.

See examples/realtime.py.

Run the same example with any of the documented languages:

ADDIS_VOICE_LANGUAGE=am ADDIS_VOICE_ID=am-hamen python examples/realtime.py "ሰላም፣ እንኳን ወደ አዲስ ኤአይ በደህና መጡ።"
ADDIS_VOICE_LANGUAGE=om ADDIS_VOICE_ID=om-bikila python examples/realtime.py "Nagaa, gara Addis AI baga nagaan dhuftan."
ADDIS_VOICE_LANGUAGE=ti ADDIS_VOICE_ID=ti-berhane python examples/realtime.py "ሰላም፣ እንቋዕ ናብ ኣዲስ ኤኣይ ብደሓን መጻእኩም።"

Chat / LLM

res = addis.chat.completions.create(
    language="am",
    system="Be concise.",
    persona="You are RecipeBot by AcmeCorp.",
    messages=[{"role": "user", "content": "የእንጀራ አሰራር አስተምረኝ"}],
    temperature=0.7,
    max_tokens=1200,
)

The model is selected by Addis AI; responses report the id addis-1-alef.

Chat accepts am, om, and ti for text, attachments, and audio input.

Function calling

def get_order_status(args):
    return {"status": "shipped", "eta": "tomorrow"}

final = addis.chat.run_tools(
    language="am",
    messages=[{"role": "user", "content": "Check order 123 and summarize it."}],
    tools=[{
        "type": "function",
        "function": {
            "name": "get_order_status",
            "description": "Fetch order status by order ID.",
            "parameters": {"type": "object", "properties": {"order_id": {"type": "string"}}, "required": ["order_id"]},
            "callable": get_order_status,
        },
    }],
)
print(final["choices"][0]["message"]["content"])

Streaming (beta)

stream=True returns a ChatStream — iterate for OpenAI‑style chunk dicts, or use the accumulators:

stream = addis.chat.completions.create(
    language="am", messages=[{"role": "user", "content": "Capital?"}], stream=True
)
for chunk in stream:
    print(chunk["choices"][0]["delta"].get("content", ""), end="", flush=True)

# or, instead of iterating:
text = addis.chat.completions.create(language="am", messages=[...], stream=True).final_text()
completion = addis.chat.completions.create(language="am", messages=[...], stream=True).final_completion()

Streaming is beta and not available with tools.

Speech‑to‑text & translation

with open("call.wav", "rb") as f:
    t = addis.speech.transcribe(audio=f, language="am")  # am|om|ti|en|ha|sw
print(t["text"])

out = addis.translate.create(text="Hello", source="en", target="am")  # am|om|ti|en
print(out["text"])

Speech recognition uses /api/v2/stt; confidence may be None.

Legacy audio (deprecated)

# ⚠️ deprecated — use addis.voice.generate
out = addis.legacy.audio.generate(text="ሰላም", language="am")
out.to_file("legacy.wav")

# streaming bridge — yields audio bytes, handles both legacy encodings
audio = addis.legacy.audio.stream(text="ሰላም", language="am")
audio.to_file("legacy.wav")        # or: data = audio.read()

Errors

from addisai import InsufficientCreditsError, RateLimitError, APIError

try:
    addis.voice.generate(voice_id="am-hamen", text="ሰላም", language="am")
except InsufficientCreditsError as e:
    show_top_up(e.available_balance)
except RateLimitError as e:
    sleep(e.retry_after or 1)
except APIError as e:
    print(e.status, e.code, e.details)

Not yet in the Python SDK

An async client (AsyncAddisAI) is the one planned follow‑up. Everything else — including streaming — is at parity with the Node SDK.

Live smoke test

scripts/smoke.py exercises the real API end-to-end. It is not a PR gate — the smoke workflow runs on manual dispatch and a daily schedule, only where the repo secret ADDIS_SMOKE_API_KEY (a low-balance sandbox key) is set. Run locally with ADDIS_API_KEY=<key> python scripts/smoke.py.

License

MIT

Metadata

Release files for addisai 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for addisai 0.3.1
File Size Uploaded Provenance
addisai-0.3.1.tar.gz 28.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for addisai 0.3.1
File Interpreter ABI Platform
addisai-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 56.0 kB

Release files / addisai-0.3.1.tar.gz

Download URL addisai-0.3.1.tar.gz
Size 28.1 kB
Tags Source
SHA-256 checksum
How to use checksums
472ec62a1c495fe118344f7041494294db8f49bac88f25066fe8db10805d52ca
BLAKE2b-256 checksum
How to use checksums
09915b2fa061d8d371a368dbef1129ed6063f2fec96e4b8d40ff928af7c15012
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / addisai-0.3.1-py3-none-any.whl

Download URL addisai-0.3.1-py3-none-any.whl
Size 27.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e03e5dc987a82a85c1c5915467a5ea811ad2e58f2d787430adc455df91a58be7
BLAKE2b-256 checksum
How to use checksums
d96948dc2a7578929d71ab285197f636d876d4ffe23d550e57dec12be819708c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for addisai 0.3.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page