File size: 6,893 Bytes
3ecfe58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
---
title: ONYX
emoji: "🚀"
colorFrom: blue
colorTo: green
sdk: docker
app_port: 7860
pinned: false
---

# onyx2api

把 [Onyx Cloud](https://cloud.onyx.app) 包装成标准的 OpenAI / Anthropic API,Go 写的,单文件,零依赖,编译出来就一个二进制。

说白了:你有 Onyx 的 Key,这东西帮你把它变成任何支持 OpenAI 或 Anthropic 协议的客户端都能直接用的接口。ChatGPT-Next-Web、LobeChat、Cursor、随便什么客户端,填个地址就能连。

> [!NOTE]
> 仅供学习和技术研究,请遵守 Onyx 使用条款及当地法律法规。

## 跑起来

三种方式,挑一个适合自己的。

### 直接编译运行

```bash
git clone https://github.com/smysle/onyx2api-go.git
cd onyx2api-go
go build -o onyx2api .

ONYX_KEYS="on_tenant_xxx" CLIENT_API_KEY="sk-456789" ./onyx2api
```

默认监听 `0.0.0.0:9898`,想换端口就加个 `PORT=7860`### Docker

```bash
docker build -t onyx2api:latest .
docker run --rm -p 7860:7860 \
  -e PORT=7860 \
  -e ONYX_KEYS=on_tenant_xxx \
  -e CLIENT_API_KEY=sk-456789 \
  onyx2api:latest
```

镜像用的 distroless,编译产物就几 MB,启动秒开。

### 丢到 Hugging Face Spaces

最省事的部署方式,白嫖 HF 的容器,不用自己搞服务器。

参考实例:`https://huggingface.co/spaces/smyslenny/ONYX`(可以直接 Duplicate)

**步骤:**

1. 把代码推到你自己的 Space:

```bash
git clone https://github.com/smysle/onyx2api-go.git
cd onyx2api-go
git remote add hf https://huggingface.co/spaces/<你的用户名>/ONYX
git push hf main
```

如果要求输密码,Username 填 HF 用户名,Password 填 Access Token(要有 write 权限)。

2. 去 Space 的 **Settings → Variables and secrets** 里加两个 Secret:

   - `ONYX_KEYS` = 你的 Onyx Key(多个用逗号隔开)
   - `CLIENT_API_KEY` = 自己定一个密钥,给客户端用的

3. 等它 Build 完,接口地址就是 `https://<你的用户名>-onyx.hf.space/v1`

> [!TIP]
> 别人 Duplicate 你的 Space 也能用,但 Secret 不会跟过去,得自己配。

## 它能干什么

**双协议兼容** — 同时暴露 OpenAI 和 Anthropic 两套接口,一个服务顶两个用:

- `POST /v1/chat/completions` — OpenAI 格式,`Authorization: Bearer xxx` 鉴权
- `POST /v1/messages` — Anthropic 格式,`x-api-key: xxx` 鉴权

两个接口都支持流式(SSE)和非流式响应。

**多 Key 轮询**`ONYX_KEYS` 里填多个 Key(逗号分隔),请求会自动轮着用,原子操作无锁,不会有并发问题。

**自动重试** — 遇到 502 / 503 / 504 / 429 会自动重试,最多 3 次,间隔 2s → 5s → 10s 递增。重试时还会自动换 Key(如果有多个的话)。

**Reasoning 透传** — Onyx 返回的推理过程(thinking)会被正确翻译。OpenAI 格式走 `reasoning_content` 字段,Anthropic 格式走 `thinking` content block,下游客户端能正常展示思考链。

**工具调用可视化** — Onyx 的搜索、网页抓取、代码执行、图片生成、深度研究等工具事件,都会被转成可读的文本块插入回复里,不会丢失上下文。

## 接口一览

| 方法 | 路径 | 用途 |
|------|------|------|
| `GET` | `/` | 服务信息,返回版本号和接口列表 |
| `GET` | `/health` | 健康检查,顺便告诉你加载了几个 Key |
| `GET` | `/v1/models` | 模型列表(OpenAI 格式) |
| `POST` | `/v1/chat/completions` | OpenAI 兼容接口 |
| `POST` | `/v1/messages` | Anthropic 兼容接口 |

### 用 curl 试一下

健康检查:

```bash
curl http://127.0.0.1:9898/health
# {"status":"ok","version":"0.5.0","keys":1}
```

OpenAI 格式:

```bash
curl http://127.0.0.1:9898/v1/chat/completions \
  -H "Authorization: Bearer sk-456789" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o",
    "messages": [{"role":"user","content":"你好"}],
    "stream": false
  }'
```

Anthropic 格式:

```bash
curl http://127.0.0.1:9898/v1/messages \
  -H "x-api-key: sk-456789" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-6",
    "messages": [{"role":"user","content":"你好"}],
    "stream": false
  }'
```

## 客户端接入

大多数支持自定义 API 地址的客户端都能用。配置方法:

| 配置项 | 本地部署 | HF Spaces |
|--------|---------|-----------|
| Base URL | `http://localhost:9898/v1` | `https://<用户名>-onyx.hf.space/v1` |
| API Key | 你设的 `CLIENT_API_KEY` 值 | 同左 |

Python 里用 `openai` 库的话:

```python
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:9898/v1",
    api_key="sk-456789",
)

resp = client.chat.completions.create(
    model="claude-sonnet-4-6",
    messages=[{"role": "user", "content": "你好"}],
)
print(resp.choices[0].message.content)
```

## 支持的模型

内置了主流模型的映射,直接用模型名就行:

**Anthropic**
`claude-opus-4-6` · `claude-opus-4-5` · `claude-sonnet-4-6` · `claude-sonnet-4-5` · `claude-sonnet-4` · `claude-3-5-sonnet` · `claude-3-5-haiku` · `claude-3-opus` · `claude-haiku-4-5`

**OpenAI**
`gpt-4o` · `gpt-4o-mini` · `gpt-4-turbo` · `gpt-4` · `o1` · `o1-mini` · `o3-mini`

**Google**
`gemini-2.0-flash` · `gemini-2.5-pro`

不在列表里的模型也能用,传 Onyx 的原始格式 `Provider__api__model_version` 就行,比如 `OpenAI__api__gpt-4o`。找不到映射的模型名会默认当 Anthropic 处理。

## 环境变量

| 变量 | 说明 | 默认 |
|------|------|------|
| `ONYX_KEYS` | Onyx API Key,多个逗号分隔 | **必填** |
| `CLIENT_API_KEY` | 客户端鉴权密钥 | 空(不鉴权) |
| `CLIENT_API_KEYS` | 多个客户端密钥,逗号分隔,设了这个会忽略上面那个 | 空 |
| `PORT` | 监听端口 | `9898` |
| `LISTEN_ADDR` | 完整监听地址,比如 `0.0.0.0:8080`,设了会忽略 `PORT` | 空 |

请求体里还可以传一个 `persona_id`(整数),对应 Onyx 的 Persona,默认 `1`## 常见问题

**Q: Duplicate / Fork 了别人的项目,跑起来没反应?**

Secret 不会跟着代码走。你得自己去 Space Settings 里把 `ONYX_KEYS``CLIENT_API_KEY` 填上。

**Q: `/health` 返回的 `keys` 是 0?**

说明没读到 `ONYX_KEYS`。本地跑检查一下环境变量有没有传对,HF 上检查 Space Secrets 配了没。

**Q: 不设 `CLIENT_API_KEY` 行不行?**

能跑,但公网部署别这么干。没有鉴权谁都能调,你的 Onyx 配额会被白嫖光。

**Q: 流式响应断了 / 超时了?**

默认请求超时 5 分钟。如果模型响应特别长(比如深度研究),可能会超。另外检查一下中间有没有反向代理在限制连接时长。

**Q: 模型名写错了会怎样?**

不会报错,会被当成 Anthropic 模型透传给 Onyx。Onyx 那边认不认就看它了。