Skip to main content

Type-safe, zero-SDK adapter layer that normalizes any LLM provider into one consistent interface.

Project description

unifai

A minimalist, model-agnostic adapter layer for LLMs. No massive SDKs, strict type-safe normalization, zero-overhead abstraction — just pydantic, httpx, and boto3. Unlike LiteLLM, unifai calls provider APIs directly rather than wrapping heavyweight SDKs, giving you a predictable canonical schema with nothing hidden underneath.

Install

pip install -e .

# With dev dependencies
pip install -e ".[dev]"

Quick Start

import asyncio
from unifai import UnifAI, UnifAIConfig

async def main():
    client = UnifAI(UnifAIConfig(
        openai_api_key="sk-...",
        anthropic_api_key="sk-ant-...",
    ))

    # Non-streaming
    response = await client.chat(
        model="anthropic/claude-3-5-sonnet-20241022",
        messages=[{"role": "user", "content": "What is 2+2?"}],
    )
    print(response.text)       # "4"
    print(response.tool_calls) # [] — same shape for ALL providers

    # Streaming (yields ContentBlock chunks, then a final Usage)
    async for chunk in client.stream(
        model="openai/gpt-4o",
        messages=[{"role": "user", "content": "Tell me a story"}],
    ):
        if chunk.type == "text":
            print(chunk.text, end="", flush=True)

asyncio.run(main())

Supported Providers

Provider Model string format Adapter Status
OpenAI openai/<model-id> OpenAIAdapter ✅ Full
Anthropic anthropic/<model-id> AnthropicAdapter ✅ Full
AWS Bedrock bedrock/<model-id> BedrockAdapter ✅ Full
Groq groq/<model-id> GenericOpenAIAdapter ✅ Full
Ollama ollama/<model-id> GenericOpenAIAdapter ✅ Full
Gemini gemini/<model-id> GeminiAdapter ✅ Full
Vertex AI vertex/<model-id> VertexAdapter ⚠️ Not Tested

Any OpenAI-compatible API can be added by pointing GenericOpenAIAdapter at a new base_url — no new adapter code required.

Tool Use

Tools produce the exact same ContentBlock shape regardless of provider:

from unifai import Tool, ToolParameter

weather_tool = Tool(
    name="get_weather",
    description="Get current weather for a location",
    parameters={
        "location": ToolParameter(type="string", description="City name"),
    },
    required=["location"],
)

response = await client.chat(
    model="anthropic/claude-3-5-sonnet-20241022",
    messages=[{"role": "user", "content": "Weather in NYC?"}],
    tools=[weather_tool],
)

for tc in response.tool_calls:
    print(tc.tool_name)   # "get_weather"
    print(tc.tool_input)  # {"location": "NYC"} — always a dict, never a string

Error Handling

Every adapter catches raw httpx.HTTPStatusError and re-raises as a typed UnifAIError — provider-specific error formats never leak to your code:

UnifAIError
├── AuthenticationError   # 401 — invalid or missing API key
├── RateLimitError        # 429 — provider rate limit exceeded
├── InvalidRequestError   # 400 — malformed input
├── ProviderError         # 5xx — unexpected provider failure
│   ├── BedrockError
│   └── VertexError
└── StreamingError        # error mid-stream
from unifai import RateLimitError, AuthenticationError

try:
    response = await client.chat(
        model="openai/gpt-4o",
        messages=[{"role": "user", "content": "Hello"}],
    )
except RateLimitError:
    # retry with backoff
except AuthenticationError:
    # bad key

Architecture

src/unifai/
├── __init__.py          # Public API surface
├── types.py             # Pydantic v2 canonical schemas
├── errors.py            # UnifAIError hierarchy
├── client.py            # UnifAI entry point + provider routing
└── providers/
    ├── base.py          # BaseProvider ABC
    ├── openai.py        # OpenAI adapter
    ├── anthropic.py     # Anthropic adapter
    ├── bedrock.py       # AWS Bedrock Converse API
    ├── gemini.py        # Gemini (stub)
    ├── vertex.py        # Vertex AI (stub)
    └── generic_openai.py  # OpenAI-compatible fallback

Testing

pytest tests/ -v

Dependencies

  • pydantic — type-safe models
  • httpx — async HTTP (no provider SDKs)
  • boto3 — AWS credential signing only

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

modelgate-0.1.0.tar.gz (35.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

modelgate-0.1.0-py3-none-any.whl (27.6 kB view details)

Uploaded Python 3

File details

Details for the file modelgate-0.1.0.tar.gz.

File metadata

  • Download URL: modelgate-0.1.0.tar.gz
  • Upload date:
  • Size: 35.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for modelgate-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7060a0d25761c298597e5e282808a72ccc1bae27f1b36234dbcc8e39178ff81c
MD5 23a40da144b60c77e126a3648e32bd6c
BLAKE2b-256 b4f1c6b601818192e93c871ba070c398abc4a3be6b2a9c26615982b0dfb6d930

See more details on using hashes here.

Provenance

The following attestation bundles were made for modelgate-0.1.0.tar.gz:

Publisher: publish.yml on PavanPapiReddy22/modelgate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file modelgate-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: modelgate-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 27.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for modelgate-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b68287bcb5c65e3e88c5b81f063717a02837407613632c4dde47da5478d852e3
MD5 0e50a2fa87432df7b8891221c9a86ae5
BLAKE2b-256 cf9aa6d7cf8aea7885360bbbed3653a53c45ddbc2fbbe78f11e4a34a7049c5ac

See more details on using hashes here.

Provenance

The following attestation bundles were made for modelgate-0.1.0-py3-none-any.whl:

Publisher: publish.yml on PavanPapiReddy22/modelgate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page