File size: 6,215 Bytes
43668cf f69bc37 43668cf f69bc37 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | ---
title: Unified AI Proxy
emoji: π
colorFrom: blue
colorTo: indigo
sdk: docker
pinned: false
---
# π Unified AI Proxy
A self-hosted, OpenAI-compatible API gateway that routes requests to any AI provider from a single endpoint. Manage all your provider keys through a clean dashboard and hit one URL for everything.
---
## Features
- **Single endpoint** for OpenAI, Anthropic, Groq, Together, Mistral, Cohere, DeepSeek, OpenRouter, or any OpenAI-compatible API
- **Provider routing** via `providerName/model-name` prefix in the model field
- **Streaming support** β SSE responses forwarded without buffering
- **Unified model list** β `GET /v1/models` aggregates all providers, prefixed by name
- **Dashboard** β add/edit/delete providers, view request logs, manage your master key
- **Persistent SQLite** β data survives Space restarts (mount `/data` as persistent storage)
- **Env var seeding** β pre-seed providers via `PROVIDER_<NAME>_URL` + `PROVIDER_<NAME>_KEY`
---
## Quick Start
### 1. Deploy to Hugging Face Spaces
1. Create a new Space β SDK: **Docker**
2. Upload these files: `Dockerfile`, `main.py`, `requirements.txt`, `README.md`
3. Enable **Persistent Storage** in Space settings β mount at `/data`
4. The Space starts and prints your **Master API Key** to the build logs β copy it
### 2. Open the Dashboard
Navigate to your Space URL. Enter your master key to unlock the dashboard.
### 3. Add Providers
In the **Providers** tab, add any OpenAI-compatible backend:
| Provider | Base URL |
|----------|----------|
| OpenAI | `https://api.openai.com/v1` |
| Anthropic | `https://api.anthropic.com/v1` |
| Groq | `https://api.groq.com/openai/v1` |
| Together | `https://api.together.xyz/v1` |
| Mistral | `https://api.mistral.ai/v1` |
| Cohere | `https://api.cohere.ai/compatibility/v1` |
| DeepSeek | `https://api.deepseek.com/v1` |
| OpenRouter | `https://openrouter.ai/api/v1` |
### 4. Make Requests
Use your Space URL as the base URL in any OpenAI-compatible client:
```bash
# Route to a specific provider using providerName/ prefix
curl https://your-space.hf.space/v1/chat/completions \
-H "Authorization: Bearer YOUR_MASTER_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "groq/llama3-8b-8192",
"messages": [{"role": "user", "content": "Hello!"}]
}'
# Together AI with a nested model path
curl https://your-space.hf.space/v1/chat/completions \
-H "Authorization: Bearer YOUR_MASTER_KEY" \
-d '{
"model": "together/meta-llama/Llama-3-70b-chat-hf",
"messages": [{"role": "user", "content": "Hi"}],
"stream": true
}'
# Use default provider (no prefix needed)
curl https://your-space.hf.space/v1/chat/completions \
-H "Authorization: Bearer YOUR_MASTER_KEY" \
-d '{"model": "gpt-4o", "messages": [{"role": "user", "content": "Hello"}]}'
# List all models across all providers
curl https://your-space.hf.space/v1/models \
-H "Authorization: Bearer YOUR_MASTER_KEY"
```
### Use with the OpenAI Python SDK
```python
from openai import OpenAI
client = OpenAI(
base_url="https://your-space.hf.space/v1",
api_key="YOUR_MASTER_KEY",
)
# Route to Groq
response = client.chat.completions.create(
model="groq/llama3-8b-8192",
messages=[{"role": "user", "content": "Hello!"}],
)
# Route to Anthropic (via OpenAI-compat layer)
response = client.chat.completions.create(
model="anthropic/claude-3-5-sonnet-20241022",
messages=[{"role": "user", "content": "Hello!"}],
)
```
---
## Environment Variable Seeding
Pre-seed providers without touching the dashboard by setting Space secrets:
```
PROVIDER_OPENAI_URL=https://api.openai.com/v1
PROVIDER_OPENAI_KEY=sk-...
PROVIDER_GROQ_URL=https://api.groq.com/openai/v1
PROVIDER_GROQ_KEY=gsk_...
PROVIDER_TOGETHER_URL=https://api.together.xyz/v1
PROVIDER_TOGETHER_KEY=...
```
These are imported on startup if the provider name doesn't already exist in the database.
---
## API Reference
| Route | Auth | Description |
|-------|------|-------------|
| `GET /` | Master key (dashboard login) | Web dashboard |
| `GET /health` | None | Health check + provider count |
| `GET /v1/models` | Master key | Aggregated model list from all providers |
| `POST /v1/chat/completions` | Master key | Proxied chat completions |
| `POST /v1/completions` | Master key | Proxied text completions |
| `POST /v1/embeddings` | Master key | Proxied embeddings |
| `GET /v1/*` | Master key | Any other OpenAI-compatible endpoint |
---
## Model Routing
The proxy determines which provider to use based on the `model` field:
1. **With prefix** β `groq/llama3-8b-8192` β routes to the provider named `Groq`, forwards model as `llama3-8b-8192`
2. **Nested paths** β `together/meta-llama/Llama-3-70b` β routes to `Together`, forwards `meta-llama/Llama-3-70b`
3. **No prefix** β uses the provider marked as **Default** in Settings
4. **No default set** β uses the first enabled provider
Matching is **case-insensitive**: `GROQ/`, `groq/`, and `Groq/` all route to a provider named `Groq`.
---
## Dashboard Tabs
### Providers
Add, edit, enable/disable, and delete providers. Set one as the default. API keys are stored encrypted in SQLite and only the last 4 characters are ever displayed.
### Logs
Auto-refreshing table (every 5s) of the last 200 requests: timestamp, provider, model, endpoint, status code, and latency. Automatically truncated at 500 stored rows.
### Settings
View and copy your master key, regenerate it (invalidates immediately), and set the default provider.
---
## Security Notes
- Provider API keys are **never returned** by any API endpoint β only the last 4 characters are shown in the dashboard
- The master key protects all `/v1/*` endpoints and the dashboard
- CORS is open (`*`) so the proxy can be called from any frontend β restrict this in production if needed
- The dashboard login stores the master key in `sessionStorage` (cleared on tab close)
---
## Local Development
```bash
pip install fastapi uvicorn httpx sqlalchemy
uvicorn main:app --reload --port 7860
# Open http://localhost:7860
# Master key printed to terminal on first run
```
Data is stored in `./db.sqlite` when `/data` doesn't exist. |