Python Wrapper Layer around GWDG's AI Services.
2
stars
43
commits
Python
primary language
Jul 19, 2026
updated
A Python wrapper for the GWDG SAIA (Scalable AI Accelerator) platform REST API.
SAIA provides self-hosted, OpenAI-compatible AI services at GWDG, including chat completions, voice transcription/translation, document conversion, and RAG (ARCANA). This library wraps the REST API so you can use it from Python — both as an object-oriented client and as standalone functions.
pip install saia-python
Or from source:
git clone https://github.com/fschwar4/saia_python.git
cd saia_python
pip install -e .
from saia_python import SAIAClient
# API key auto-discovered from SAIA_API_KEY env var, .saia_api, or .env file
client = SAIAClient()
# List available models
print(client.models.list_ids())
# Chat completion
response = client.chat.completions(
model="meta-llama-3.1-8b-instruct",
messages=[{"role": "user", "content": "Hello!"}],
)
print(response["choices"][0]["message"]["content"])
# Check your rate limits
print(client.get_rate_limits())
All services are also available as standalone functions:
from saia_python import list_model_ids, chat_completion
list_model_ids()
chat_completion(model="meta-llama-3.1-8b-instruct", messages=[...])
For concurrent workloads (e.g. an ASGI service), install the [async] extra and
use AsyncSAIAClient — the httpx.AsyncClient twin of the data plane, carrying
the same RetryPolicy and rate-limit handling as the sync client (not the
openai_async shim, which bypasses them):
pip install saia-python[async]
import asyncio
from saia_python.aio import AsyncSAIAClient
async def main():
async with AsyncSAIAClient() as client:
# Non-streaming RAG chat
answer = await client.arcana.chat(
model="openai-gpt-oss-120b",
messages=[{"role": "user", "content": "Summarise the DLBCL first line."}],
arcana_id="owner/kb",
)
print(answer["choices"][0]["message"]["content"])
# Streaming plain chat — retry=False fails fast with an informative 429
stream = await client.chat.completions(
model="meta-llama-3.1-8b-instruct",
messages=[{"role": "user", "content": "Hello!"}],
stream=True,
retry=False,
)
async for chunk in stream:
...
asyncio.run(main())
Async covers the data plane (chat, ARCANA RAG chat, streaming) plus the
read-only control-plane calls (models, arcana version/heartbeat/list/
get, health_check). File upload/index/sync, voice, and document conversion
remain synchronous on SAIAClient — see
ADR-0007.
| Service | Description | GWDG Docs |
|---|---|---|
| Chat AI | Chat completions with streaming and tool calling | Chat AI |
| Voice AI | Audio transcription and translation (Whisper) | Voice AI |
| ARCANA | RAG — knowledge base management and retrieval-augmented chat | ARCANA |
| Documents | PDF/document conversion via Docling | SAIA API |
| Models | List available models, probe tool-calling support | SAIA API |
| Tokenizers | Download model tokenizers; count chat-template tokens, special-token overhead, and subword fertility (opt-in [tokenizer] extra) | Chat AI Models |
| Rate Limits | Inspect current quota and usage | SAIA API |
saia-python/
├── saia_python/ # Main package
│ ├── __init__.py # Public API, version, functional wrappers
│ ├── client.py # SAIAClient — composes all services
│ ├── chat.py # ChatService — completions + streaming
│ ├── voice.py # VoiceService — transcribe + translate
│ ├── arcana.py # ArcanaService — RAG / knowledge bases
│ ├── models.py # ModelsService — list available models
│ ├── tokenizer.py # Tokenizers — download, chat-template token counting
│ ├── documents.py # DocumentService — Docling conversion
│ ├── openai_compat.py # OpenAI SDK compatibility layer
│ ├── auth.py # Credential and config discovery
│ ├── rate_limits.py # RateLimitInfo dataclass + parser
│ ├── exceptions.py # SAIAError hierarchy + raise_for_status
│ ├── _streaming.py # Shared SSE iterator
│ └── py.typed # PEP 561 typing marker
├── docs/ # Sphinx documentation (PyData theme)
│ ├── conf.py
│ ├── index.rst
│ ├── quickstart.rst
│ ├── explanations.rst
│ ├── architecture.rst
│ ├── implementation.rst
│ ├── configuration.rst
│ ├── api/ # API reference (one page per module)
│ ├── development.rst
│ ├── dev_notes.rst
│ ├── testing.rst
│ ├── roadmap.rst
│ └── CHANGELOG.md
├── tests/ # Unit tests
├── examples/
│ ├── saia_python_demo.ipynb # Interactive demo
│ ├── openai_compatible_proxy.ipynb # OpenAI-compatible proxy example
│ ├── config.toml.example # Template for structured config
│ └── .env.example # Template for secrets (.env)
├── .github/workflows/ # CI/CD (tests, docs, PyPI publish)
├── pyproject.toml # Package metadata + dependencies
├── CITATION.cff # Citation metadata (CFF 1.2.0)
├── .gitignore
└── README.md
Online documentation: https://fschwar4.github.io/saia_python/
Build the docs locally:
pip install -e ".[docs]"
sphinx-build -b html -w warnings_sphinx_build.txt docs docs/_build/html
python3 -m http.server 8000 --directory docs/_build/html
If you use saia-python in your work, please cite it. Citation metadata lives in
CITATION.cff; GitHub's "Cite this repository" button renders it
as APA or BibTeX. A Zenodo DOI will be added here once the first release is
archived.
43 commits
Python
100.0%
Python Wrapper Layer around GWDG's AI Services.
2
stars
43
commits
Python
primary language
Jul 19, 2026
updated
A Python wrapper for the GWDG SAIA (Scalable AI Accelerator) platform REST API.
SAIA provides self-hosted, OpenAI-compatible AI services at GWDG, including chat completions, voice transcription/translation, document conversion, and RAG (ARCANA). This library wraps the REST API so you can use it from Python — both as an object-oriented client and as standalone functions.
pip install saia-python
Or from source:
git clone https://github.com/fschwar4/saia_python.git
cd saia_python
pip install -e .
from saia_python import SAIAClient
# API key auto-discovered from SAIA_API_KEY env var, .saia_api, or .env file
client = SAIAClient()
# List available models
print(client.models.list_ids())
# Chat completion
response = client.chat.completions(
model="meta-llama-3.1-8b-instruct",
messages=[{"role": "user", "content": "Hello!"}],
)
print(response["choices"][0]["message"]["content"])
# Check your rate limits
print(client.get_rate_limits())
All services are also available as standalone functions:
from saia_python import list_model_ids, chat_completion
list_model_ids()
chat_completion(model="meta-llama-3.1-8b-instruct", messages=[...])
For concurrent workloads (e.g. an ASGI service), install the [async] extra and
use AsyncSAIAClient — the httpx.AsyncClient twin of the data plane, carrying
the same RetryPolicy and rate-limit handling as the sync client (not the
openai_async shim, which bypasses them):
pip install saia-python[async]
import asyncio
from saia_python.aio import AsyncSAIAClient
async def main():
async with AsyncSAIAClient() as client:
# Non-streaming RAG chat
answer = await client.arcana.chat(
model="openai-gpt-oss-120b",
messages=[{"role": "user", "content": "Summarise the DLBCL first line."}],
arcana_id="owner/kb",
)
print(answer["choices"][0]["message"]["content"])
# Streaming plain chat — retry=False fails fast with an informative 429
stream = await client.chat.completions(
model="meta-llama-3.1-8b-instruct",
messages=[{"role": "user", "content": "Hello!"}],
stream=True,
retry=False,
)
async for chunk in stream:
...
asyncio.run(main())
Async covers the data plane (chat, ARCANA RAG chat, streaming) plus the
read-only control-plane calls (models, arcana version/heartbeat/list/
get, health_check). File upload/index/sync, voice, and document conversion
remain synchronous on SAIAClient — see
ADR-0007.
| Service | Description | GWDG Docs |
|---|---|---|
| Chat AI | Chat completions with streaming and tool calling | Chat AI |
| Voice AI | Audio transcription and translation (Whisper) | Voice AI |
| ARCANA | RAG — knowledge base management and retrieval-augmented chat | ARCANA |
| Documents | PDF/document conversion via Docling | SAIA API |
| Models | List available models, probe tool-calling support | SAIA API |
| Tokenizers | Download model tokenizers; count chat-template tokens, special-token overhead, and subword fertility (opt-in [tokenizer] extra) | Chat AI Models |
| Rate Limits | Inspect current quota and usage | SAIA API |
saia-python/
├── saia_python/ # Main package
│ ├── __init__.py # Public API, version, functional wrappers
│ ├── client.py # SAIAClient — composes all services
│ ├── chat.py # ChatService — completions + streaming
│ ├── voice.py # VoiceService — transcribe + translate
│ ├── arcana.py # ArcanaService — RAG / knowledge bases
│ ├── models.py # ModelsService — list available models
│ ├── tokenizer.py # Tokenizers — download, chat-template token counting
│ ├── documents.py # DocumentService — Docling conversion
│ ├── openai_compat.py # OpenAI SDK compatibility layer
│ ├── auth.py # Credential and config discovery
│ ├── rate_limits.py # RateLimitInfo dataclass + parser
│ ├── exceptions.py # SAIAError hierarchy + raise_for_status
│ ├── _streaming.py # Shared SSE iterator
│ └── py.typed # PEP 561 typing marker
├── docs/ # Sphinx documentation (PyData theme)
│ ├── conf.py
│ ├── index.rst
│ ├── quickstart.rst
│ ├── explanations.rst
│ ├── architecture.rst
│ ├── implementation.rst
│ ├── configuration.rst
│ ├── api/ # API reference (one page per module)
│ ├── development.rst
│ ├── dev_notes.rst
│ ├── testing.rst
│ ├── roadmap.rst
│ └── CHANGELOG.md
├── tests/ # Unit tests
├── examples/
│ ├── saia_python_demo.ipynb # Interactive demo
│ ├── openai_compatible_proxy.ipynb # OpenAI-compatible proxy example
│ ├── config.toml.example # Template for structured config
│ └── .env.example # Template for secrets (.env)
├── .github/workflows/ # CI/CD (tests, docs, PyPI publish)
├── pyproject.toml # Package metadata + dependencies
├── CITATION.cff # Citation metadata (CFF 1.2.0)
├── .gitignore
└── README.md
Online documentation: https://fschwar4.github.io/saia_python/
Build the docs locally:
pip install -e ".[docs]"
sphinx-build -b html -w warnings_sphinx_build.txt docs docs/_build/html
python3 -m http.server 8000 --directory docs/_build/html
If you use saia-python in your work, please cite it. Citation metadata lives in
CITATION.cff; GitHub's "Cite this repository" button renders it
as APA or BibTeX. A Zenodo DOI will be added here once the first release is
archived.
43 commits
Python
100.0%