| | --- |
| | 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 那边认不认就看它了。 |
| |
|