通义千问 OpenAI / Anthropic / Gemini 三协议兼容代理
支持 Vercel / Docker / Render 一键部署,零持久化存储
| 功能 | 说明 |
|---|---|
| 三协议兼容 | 同一后端同时暴露 OpenAI / Anthropic Messages / Google Gemini 三种 API 格式 |
| Tool Calling | Qwen3.x 模型原生支持 Function Calling,工具调用通过上下文传递,模型自动识别并生成结构化调用 |
| 多账号轮询 | 最近最少使用 (LRU) 调度 + 失败冷却机制 + 自动故障转移 |
| 自动刷新 | 用户名密码登录,每 6 小时自动重新登录刷新 JWT Token |
| 流式输出 | 完整 SSE 流式响应,兼容 stream: true |
| 思维链 | 推理模型通过 OpenAI 标准 reasoning_content 字段输出,模型名加 -thinking 后缀启用 |
| 联网搜索 | 搜索增强生成,模型名加 -search 后缀,返回来源引用 |
| 图片生成 | 文生图 /v1/images/generations,支持多种尺寸 |
| 图片编辑 | /v1/images/edits,支持 multipart 上传 |
| 视频生成 | 文生视频 /v1/videos |
| 反爬绕过 | 内置 ssxmod 浏览器指纹 Cookie 自动生成,每 15 分钟刷新 |
| 代理支持 | HTTP / HTTPS / SOCKS5 代理 |
| Vercel 部署 | 部署即同时构建前端 + Serverless 后端 |
| Docker 部署 | 多阶段 Alpine 镜像构建 |
| 管理面板 | React 暗色主题面板 + 内置聊天(支持版本化重试) + 交互式 API 文档 |
git clone https://github.com/Git-think/Qwen-Proxy.git
cd Qwen-Proxy
npm install
cd webui && npm install && cd ..cp .env.example .env编辑 .env:
# 必填
API_KEY=sk-your-key-here
ACCOUNTS=your-email@example.com:your-password
# 可选
SERVICE_PORT=3000
DATA_SAVE_MODE=none
LOG_LEVEL=INFOnpm run build:webui # 构建前端到 webui/dist/
npm start # 生产模式(同时托管前端 + 后端)
npm run dev # 开发模式(自动重启后端)前端开发模式:cd webui && npm run dev(默认 5173,已配置代理转发到 3000)。
访问 http://localhost:3000 查看管理面板。
OpenAI 格式:
curl http://localhost:3000/v1/chat/completions \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{"model":"qwen3.6-plus","messages":[{"role":"user","content":"你好"}],"stream":true}'Anthropic 格式:
curl http://localhost:3000/v1/messages \
-H "x-api-key: sk-your-key" \
-H "Content-Type: application/json" \
-d '{"model":"qwen3.6-plus","max_tokens":1024,"messages":[{"role":"user","content":"你好"}]}'Gemini 格式:
curl "http://localhost:3000/v1beta/models/qwen3.6-plus:generateContent" \
-H "x-goog-api-key: sk-your-key" \
-H "Content-Type: application/json" \
-d '{"contents":[{"role":"user","parts":[{"text":"你好"}]}]}'点击按钮后:
- Vercel 会自动 fork 仓库到你的 GitHub
- 填写环境变量:
API_KEY— 你的 API 密钥(如sk-xxx)ACCOUNTS— 通义千问账号(如email@example.com:password,多个用逗号分隔)
- 点击 Deploy,等待部署完成
vercel.json 自动执行:
cd webui && npm install && npm run build构建前端到webui/distapi/index.js作为 Serverless Function 处理所有 API 请求- SPA 路由 fallback 到
index.html
DATA_SAVE_MODE 默认为 none,所有状态保存在内存中,冷启动时自动登录获取 Token。
部署后可在 Web 面板里直接管理 Vercel 环境变量并一键重新部署,需要再添加 2 个环境变量:
| 变量 | 必需 | 获取方式 |
|---|---|---|
VERCEL_TOKEN |
是 | vercel.com/account/tokens 创建 Personal Token |
VERCEL_PROJECT_ID |
是 | 项目 Settings → General → Project ID |
VERCEL_TEAM_ID |
否 | 仅团队账户需要;个人账户留空 |
Vercel 在 runtime 不会自动注入
VERCEL_PROJECT_ID(不同于VERCEL/VERCEL_ENV/VERCEL_URL),必须手动在 Settings → Environment Variables 里添加。
配置完成后重新部署一次,左侧导航会出现 Vercel 同步 入口。
💡 Vercel 同步是可选的:它的主要用途是把
ACCOUNTS写回 Vercel env 让重部署后保留。如果你已经用了DATA_SAVE_MODE=redis,账号和代理状态直接持久化在 Redis,通过管理面板(/admin)就能增删账号——不需要再配 Vercel 同步。Redis 模式更通用,跨平台一致。两种方式二选一。
docker compose up -d
# 或手动
docker build -t qwen-proxy .
docker run -d -p 3000:3000 \
-e API_KEY=sk-your-key \
-e ACCOUNTS=email:password \
qwen-proxy需要持久化存储时加 -e DATA_SAVE_MODE=file -v ./data:/app/data。
仓库已配置 GitHub Actions 自动构建并发布镜像到 GHCR / Release,详见 .github/workflows。
- 创建 Web Service,连接 GitHub
- Build Command:
npm install && npm run build:webui - Start Command:
npm start - 环境变量:
API_KEY、ACCOUNTS
⚠️ Render 免费版无持久磁盘(容器休眠 / 重启即清空),DATA_SAVE_MODE=file会丢数据。免费版部署强烈建议DATA_SAVE_MODE=redis+ Upstash(见下文 数据持久化模式)。Render 付费 Disks 服务才支持 file 模式。
点按钮后 Netlify 会要求授权 GitHub、fork 仓库、选择团队,最后跳到 Site Configuration 页让你填环境变量。仓库自带 netlify.toml,构建会自动:
- 安装根 +
webui/依赖,构建前端到webui/dist - 把
netlify/functions/api.js(用serverless-http包 Express)作为 Functions 入口 - 把所有
/v1/*/v1beta/*/anthropic/*/api/*/verify/health重定向到该 Function,其余路径回退到 SPAindex.html
环境变量需要的设置(Site → Environment variables):
API_KEY=sk-your-api-key-here
ACCOUNTS=your-email@example.com:your-password
DATA_SAVE_MODE=redis # Netlify Functions 也是无持久磁盘
REDIS_URL=https://... # Upstash 或兼容 HTTP Redis
REDIS_TOKEN=...
⚠️ Netlify Functions 无持久磁盘,与 Vercel 同理;务必用redis模式。
Node.js 18+,先 npm run build:webui 再 npm start 即可。
Railway / Fly.io 默认有持久卷(volume)支持,可用
DATA_SAVE_MODE=file(需挂卷到data/);嫌麻烦也可以直接用redis模式,跨平台一致。
Cloudflare Workers / Pages Functions 暂不支持(不是 Node.js 运行时),路线图与 workaround 见 docs/cloudflare-workers.md。
- 提交代码 / PR:见 docs/contributing.md
- 提交 issue:见 docs/issues.md
- API 详细文档:见 docs/api.md
- 架构与功能实现:见 docs/architecture.md
- Cloudflare Workers 适配路线图:见 docs/cloudflare-workers.md
Tool calling 子系统的设计思路来自 CJackHwang/ds2api——一个用 prompt 注入 + DSML XML 解析让上游模型支持 OpenAI tools 协议的 Go 项目。本仓库参考了它的 DSML 标记选择、四级候选解析、流式 sieve 状态机思路并完整重写为 Node.js 实现,未直接复用其代码。感谢作者的开源工作给了我们一个可行参照。
- Linux DO —— 不一样的中文技术社区,本项目的灵感、反馈与折腾乐趣大多源自这里。
客户端(OpenAI SDK / Claude SDK / Gemini SDK / NextChat / ChatBox)
│
▼ HTTP / SSE
┌──────────────────────────────────────┐
│ Qwen-Proxy(Express.js) │
│ │
│ 协议适配 → API Key 鉴权 → 格式转换 → 账号轮询 │
│ │ │
│ ▼ │
│ 请求模块 + ssxmod Cookie + 代理 │
└────────┬─────────────────────────────┘
│ HTTPS
▼
┌──────────────────────────────────────┐
│ 通义千问 API(chat.qwen.ai) │
│ 登录 / 创建会话 / 聊天 / 模型列表 │
└──────────────────────────────────────┘
三协议适配层:所有非 OpenAI 协议(Anthropic / Gemini)请求统一在 src/adapters/ 中转换为 OpenAI 内部表示,复用同一套上游请求与流式解析。
项目根目录/
├── api/index.js # Vercel Serverless 入口
├── netlify/
│ └── functions/api.js # Netlify Functions 入口(serverless-http 包 Express)
├── netlify.toml # Netlify build + redirects
├── docs/ # 详细文档
│ ├── api.md # 三协议 API 全量参考
│ ├── architecture.md # 架构与功能实现
│ ├── contributing.md # 提交代码 / PR 流程
│ ├── issues.md # 提交 Issue 模板
│ └── cloudflare-workers.md # CF Workers 适配路线图
├── src/
│ ├── adapters/
│ │ ├── anthropic.js # Anthropic ↔ OpenAI 转换 + SSE 重写
│ │ └── gemini.js # Gemini ↔ OpenAI 转换 + SSE 重写
│ ├── config/index.js # 环境变量配置(含代理列表 / 禁用账号)
│ ├── controllers/ # 控制器(聊天、图片视频、模型)
│ ├── middlewares/ # 中间件(鉴权、tool-call gate、格式转换)
│ ├── models/models-map.js # 动态模型获取与缓存
│ ├── routes/
│ │ ├── chat.js # /v1/chat/completions、images、videos
│ │ ├── anthropic.js # /v1/messages、/anthropic/v1/messages
│ │ ├── gemini.js # /v1(beta)/models/{model}:generate*
│ │ ├── models.js # /v1/models
│ │ ├── accounts.js # /api/* 账号 + 智能代理 + 禁用切换
│ │ ├── verify.js # /verify
│ │ └── vercel.js # Vercel 同步面板辅助接口
│ ├── utils/
│ │ ├── account.js # 账号管理器(核心单例 + 禁用切换)
│ │ ├── account-rotator.js # LRU 负载均衡(跳过 disabled)
│ │ ├── token-manager.js # Token 登录/验证/刷新
│ │ ├── data-persistence.js # 存储层(none / file / redis)
│ │ ├── redis-client.js # Upstash REST Redis 客户端
│ │ ├── proxy-helper.js # http(s) / socks5 代理 agent 工厂
│ │ ├── proxy-pool.js # 智能代理池(四级优先 + 故障转移 + 持久化)
│ │ ├── vercel-sync.js # 把代理 / 禁用列表 写回 Vercel env(serverless 持久化)
│ │ ├── request.js # 上游 HTTP 请求 + 代理重试循环
│ │ ├── toolcall.js # DSML tool-call prompt + 流式 sieve + JSON repair
│ │ ├── chat-helpers.js # 消息解析与模型匹配
│ │ ├── cookie-generator.js # ssxmod Cookie(LZW 压缩)
│ │ ├── fingerprint.js # 浏览器指纹合成
│ │ ├── ssxmod-manager.js # Cookie 生命周期(15分钟刷新)
│ │ ├── upload.js # 阿里云 OSS 上传
│ │ ├── precise-tokenizer.js # token usage 估算
│ │ ├── logger.js # 日志
│ │ └── tools.js # SHA-256 / JWT / UUID
│ ├── server.js # Express 应用
│ └── start.js # 启动器
├── webui/ # React 前端(Vite + Tailwind)
│ ├── src/
│ │ ├── pages/ # Login / Chat / Admin / Docs / Vercel
│ │ ├── components/ # Sidebar / AccountCard / MessageBubble / ...
│ │ ├── hooks/ # useChat / useApi / useToast
│ │ └── utils/ # api / storage / constants / markdown
│ ├── vite.config.js # 构建期 inject 版本号
│ └── package.json
├── vercel.json # Vercel build + SPA rewrites
├── Dockerfile
├── docker-compose.yml
├── .github/workflows/ # docker-build / release / quality-gates
├── package.json # 改 version 即触发 release.yml
└── .env.example
| 步骤 | 实现 |
|---|---|
| 密码处理 | SHA-256 哈希明文密码 |
| 登录 | POST chat.qwen.ai/api/v1/auths/signin |
| Token | JWT 格式,包含过期时间 exp |
| 自动刷新 | 每 6 小时重新登录(刷新 = 重新登录) |
| 刷新阈值 | 剩余有效期 < 24 小时时触发 |
- LRU 策略:优先选择最久未使用的账号
- 失败冷却:连续失败 3 次 → 5 分钟冷却 → 自动重置
- 负载均衡:多账号自动分散请求压力
通义千问 API 要求浏览器指纹 Cookie:
fingerprint.js合成 37 字段浏览器指纹cookie-generator.js随机化 → LZW 压缩 → Base64 →ssxmod_itna+ssxmod_itna2ssxmod-manager.js每 15 分钟自动刷新
1. 客户端发送 OpenAI / Anthropic / Gemini 格式请求
2. 鉴权中间件(按协议匹配 Authorization / x-api-key / x-goog-api-key)
3. 适配器把请求转换为内部 OpenAI 表示
4. Chat 中间件转换格式:
- 解析模型后缀(-thinking / -search 等)
- 匹配上游模型 ID
- 转换消息为 Qwen 格式
5. Request 模块:
- 选取账号 Token
- 生成 ssxmod Cookie
- 创建会话 → 发送请求
6. Chat 控制器处理响应:
- 解析 SSE(phase=think → reasoning_content,phase=answer → content)
- 按客户端协议封装为对应格式(OpenAI Chunk / Anthropic Event / Gemini Candidate)
Qwen3 模型原生支持 Function Calling。工作方式:
- 客户端按 OpenAI 格式在
messages中携带tools定义 - 中间件将所有消息序列化为文本上下文
- Qwen3 模型从上下文理解工具协议,自动生成结构化
tool_calls - 实测 OpenAI SDK 的 function calling 可正常使用
| 项目 | 说明 |
|---|---|
| 框架 | React 18 + Hooks |
| 构建 | Vite 5,产物 webui/dist/ |
| 样式 | Tailwind CSS 3,暗色主题,毛玻璃 |
| 路由 | React Router 6 |
| 聊天 | fetch + ReadableStream SSE 流式解析;重试不重发消息,新版本作为 versions[] 追加并支持左右切换 |
| 存储 | localStorage 聊天历史 |
| 渲染 | marked + highlight.js 代码高亮 |
| 文档页 | OpenAI / Anthropic / Gemini / 管理 / 公共 五分类切换 |
页面:聊天界面 / 管理面板 / API 文档 / 登录
cd webui && npm install && npm run build # 构建
cd webui && npm run dev # 开发| 变量 | 说明 | 默认值 | 必填 |
|---|---|---|---|
API_KEY |
API 密钥,逗号分隔,第一个为管理员 | — | ✅ |
ACCOUNTS |
账号 email:pass,email2:pass2 |
— | ✅ |
SERVICE_PORT |
端口 | 3000 |
— |
DATA_SAVE_MODE |
none(内存)/ file(文件)/ redis(HTTP Redis) |
none |
— |
REDIS_URL |
Redis HTTP 端点(仅 redis 模式;最高优先级) |
— | — |
REDIS_TOKEN |
Redis Bearer Token(仅 redis 模式;最高优先级) |
— | — |
KV_REST_API_URL / KV_REST_API_TOKEN |
Vercel Marketplace 集成(Upstash for Redis)自动注入 | — | — |
UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN |
Upstash 控制台直连(兼容) | — | — |
LISTEN_ADDRESS |
监听地址 | 所有接口 | — |
OUTPUT_THINK |
输出思考内容 | false |
— |
SEARCH_INFO_MODE |
搜索显示 text / table |
text |
— |
SIMPLE_MODEL_MAP |
简化模型列表 | false |
— |
LOG_LEVEL |
日志级别 | INFO |
— |
PROXY_URL |
单代理(legacy,会合并进 PROXIES) |
— | — |
PROXIES |
代理池,逗号分隔(socks5:// / http:// / https://) |
— | — |
PROXY_MAX_RETRIES |
代理失败时的重试次数 | 3 |
— |
QWEN_CHAT_PROXY_URL |
自定义 API 地址 | https://chat.qwen.ai |
— |
PROXIES 配置后启用代理池模式:
- 状态持久化(
DATA_SAVE_MODE=file或redis,见下文):代理untested/available/failed状态和账号绑定关系写入存储,重启秒级恢复。none模式不持久(重启重新探测) - 四级优先级:先 可用且未占用 → 再 未测试(首次探测)→ 再 已失败(再探测,可能恢复)→ 最后 可用且共享(按占用最少优先)
- 故障转移:上游请求出现 TCP/SOCKS 类网络错误时自动标记代理失败、换绑、重试(最多
PROXY_MAX_RETRIES次) - 增量去重:从
PROXIES环境变量 + 持久化记录合并加载,按 URL 去重
管理面板提供 GET /api/proxy/status、POST /api/proxy/add、DELETE /api/proxy 三个接口(需要管理员 API Key)。
| 模式 | 使用场景 | 存储位置 |
|---|---|---|
none(默认) |
任何平台 | 内存;重启即丢,账号靠 ACCOUNTS env 重新登录 |
file |
本地 / Docker / VPS / Render | data/data.json |
redis |
Vercel / Netlify / Cloudflare Workers 等 serverless | Redis-over-HTTP(兼容 Upstash REST 协议) |
⚠️ Vercel 不支持file模式:serverless 容器无持久磁盘,每次冷启动data/data.json都会丢失,账号 token 和代理状态都会重置。Vercel 部署请用redis模式。
后端按以下顺序自动检测,任选其一即可:
| 优先级 | 环境变量对 | 使用场景 |
|---|---|---|
| 1 | REDIS_URL + REDIS_TOKEN |
通用(推荐手动配置时使用) |
| 2 | KV_REST_API_URL + KV_REST_API_TOKEN |
Vercel Marketplace 集成(如 Upstash for Redis)自动注入 |
| 3 | UPSTASH_REDIS_REST_URL + UPSTASH_REDIS_REST_TOKEN |
Upstash 控制台直连 |
三种凭证最终都走 Upstash REST 协议(HTTPS + JSON)。Vercel 已不再提供"原生 KV" —— 所谓"Vercel KV"现在是通过 Vercel Marketplace 集成的 Upstash for Redis,走的就是这套协议。如果你的 Redis 提供商只支持 RESP/TCP(自建 Redis / Aiven / Redis Cloud 直连),目前还不能用
redis模式——可以走file模式部署到 VPS / Docker。
方式 A:Vercel Marketplace 集成 Upstash for Redis(最省事)
- Vercel 项目 → Storage → Create Database → 选 Upstash for Redis
- 关联到本项目 → 自动注入
KV_REST_API_URL/KV_REST_API_TOKEN - 仅需手动加
DATA_SAVE_MODE=redis,Redeploy
方式 B:Upstash 直连
- console.upstash.com 创建 Redis 数据库
- REST API 选项卡复制 URL 和 Token
- Vercel Environment Variables 添加:
DATA_SAVE_MODE=redis UPSTASH_REDIS_REST_URL=https://xxxxx.upstash.io UPSTASH_REDIS_REST_TOKEN=AXxxxxxxxxxxxxxxxxxxxxxxx
方式 C:通用 REDIS_URL
任何兼容 Upstash REST 协议的服务(包括上面两种)都可以用通用名:
DATA_SAVE_MODE=redis
REDIS_URL=https://your-endpoint
REDIS_TOKEN=your-bearer-token
POST /v1/chat/completions
Authorization: Bearer sk-your-key
{"model":"qwen3.6-plus","messages":[{"role":"user","content":"你好"}],"stream":true}模型后缀:无(标准) / -thinking(思维链) / -search(搜索) / -thinking-search / -image / -video / -image-edit
常用基础模型示例:qwen3.6-plus。完整列表通过 GET /v1/models 动态获取。
POST /v1/messages (或 /anthropic/v1/messages)
x-api-key: sk-your-key
Content-Type: application/json
{
"model": "qwen3.6-plus",
"max_tokens": 1024,
"messages": [{"role":"user","content":"你好"}],
"stream": true
}也接受 Authorization: Bearer ...。流式响应遵循 Anthropic SSE 事件类型(message_start / content_block_delta / message_stop 等)。
POST /v1beta/models/qwen3.6-plus:generateContent
x-goog-api-key: sk-your-key
Content-Type: application/json
{"contents":[{"role":"user","parts":[{"text":"你好"}]}]}也支持:
- 流式:
/v1beta/models/{model}:streamGenerateContent - v1 路径:
/v1/models/{model}:generateContent、/v1/models/{model}:streamGenerateContent - 鉴权:
x-goog-api-key头、?key=...查询参数、Authorization: Bearer ...
GET /v1/modelsPOST /v1/images/generations
{"prompt":"海上日落","size":"1024x1024"}
POST /v1/images/edits (multipart)
POST /v1/videos (multipart)| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/getAllAccounts |
获取账号列表(支持分页) |
| POST | /api/setAccount |
添加账号 |
| DELETE | /api/deleteAccount |
删除账号 |
| POST | /api/refreshAccount |
刷新单账号 Token |
| POST | /api/refreshAllAccounts |
批量刷新(支持 thresholdHours) |
GET /health → {"status":"ok"}
POST /verify {"apiKey":"sk-..."} → {"valid":true}Token 过期? — 自动刷新,每 6 小时重新登录。也可在管理面板手动刷新。
Vercel 冷启动慢? — 首次请求需登录账号(几秒),后续直接使用内存中的 Token。
支持哪些客户端? — 任何 OpenAI / Anthropic / Gemini 客户端均可:OpenAI SDK、@anthropic-ai/sdk、@google/generative-ai、NextChat、ChatBox、Open WebUI、Lobe Chat、Claude Code 等。
Tool Calling 怎么用? — 按 OpenAI function calling 格式发送即可,Qwen3 自动识别。
多账号? — ACCOUNTS=email1:pass1,email2:pass2,email3:pass3 或管理面板批量添加。
前端重试会丢失上一次回答吗? — 不会。新一轮回答作为新版本追加到同一条 assistant 消息,可以用消息底部的 < 1/N > 控件随时切回旧版本。
MIT