CJHauser commited on
Commit
f69bc37
Β·
verified Β·
1 Parent(s): 1654ca1

Update README.md

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