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 ModelGate, ModelGateConfig

async def main():
    client = ModelGate(ModelGateConfig(
        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 ModelGateError — provider-specific error formats never leak to your code:

ModelGateError
├── 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            # ModelGateError hierarchy
├── client.py            # ModelGate 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.1.tar.gz (35.5 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.1-py3-none-any.whl (27.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: modelgate-0.1.1.tar.gz
  • Upload date:
  • Size: 35.5 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.1.tar.gz
Algorithm Hash digest
SHA256 a9a828bc291ed7e7ca5e8d60b62f9457bc686ed53df0875e6284a06e5d72b251
MD5 47074d925224ea5dfa9039ab89c4dd92
BLAKE2b-256 c794560d9094ddea186f26ede4e5ccc4536c39a962c7c3d5c8b1e3366d4e3190

See more details on using hashes here.

Provenance

The following attestation bundles were made for modelgate-0.1.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: modelgate-0.1.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8d0ec6ac02eedd9de60bf974401f11e9ba91c9f503311b7ec857f826f0d23620
MD5 f18bcaa38a9ce687e94cf89d7ea6e124
BLAKE2b-256 f19688c2b1626cd17c2740b84242c3ec83426101f9c4c3e0f0313b8860364ae2

See more details on using hashes here.

Provenance

The following attestation bundles were made for modelgate-0.1.1-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