Skip to content

Repository files navigation

Qwen-Proxy

通义千问 OpenAI / Anthropic / Gemini 三协议兼容代理
支持 Vercel / Docker / Render 一键部署,零持久化存储

Deploy with Vercel   Deploy to Netlify

功能快速开始部署架构API 文档


功能特性

功能 说明
三协议兼容 同一后端同时暴露 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 文档

快速开始

1. 安装

git clone https://github.com/Git-think/Qwen-Proxy.git
cd Qwen-Proxy
npm install
cd webui && npm install && cd ..

2. 配置

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=INFO

3. 构建前端 + 启动

npm run build:webui   # 构建前端到 webui/dist/
npm start             # 生产模式(同时托管前端 + 后端)
npm run dev           # 开发模式(自动重启后端)

前端开发模式:cd webui && npm run dev(默认 5173,已配置代理转发到 3000)。

访问 http://localhost:3000 查看管理面板。

4. 测试

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 一键部署(推荐)

Deploy with Vercel

点击按钮后:

  1. Vercel 会自动 fork 仓库到你的 GitHub
  2. 填写环境变量:
    • API_KEY — 你的 API 密钥(如 sk-xxx
    • ACCOUNTS — 通义千问账号(如 email@example.com:password,多个用逗号分隔)
  3. 点击 Deploy,等待部署完成

vercel.json 自动执行:

  • cd webui && npm install && npm run build 构建前端到 webui/dist
  • api/index.js 作为 Serverless Function 处理所有 API 请求
  • SPA 路由 fallback 到 index.html

DATA_SAVE_MODE 默认为 none,所有状态保存在内存中,冷启动时自动登录获取 Token。

启用 Vercel 同步面板(可选)

部署后可在 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 部署

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

Render 部署

  1. 创建 Web Service,连接 GitHub
  2. Build Command: npm install && npm run build:webui
  3. Start Command: npm start
  4. 环境变量:API_KEYACCOUNTS

⚠️ Render 免费版无持久磁盘(容器休眠 / 重启即清空),DATA_SAVE_MODE=file 会丢数据。免费版部署强烈建议 DATA_SAVE_MODE=redis + Upstash(见下文 数据持久化模式)。Render 付费 Disks 服务才支持 file 模式。

Netlify 部署

Deploy to Netlify

点按钮后 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,其余路径回退到 SPA index.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 模式。

其他平台(Railway / Fly.io)

Node.js 18+,先 npm run build:webuinpm start 即可。

Railway / Fly.io 默认有持久卷(volume)支持,可用 DATA_SAVE_MODE=file(需挂卷到 data/);嫌麻烦也可以直接用 redis 模式,跨平台一致。

Cloudflare Workers / Pages Functions 暂不支持(不是 Node.js 运行时),路线图与 workaround 见 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:

  1. fingerprint.js 合成 37 字段浏览器指纹
  2. cookie-generator.js 随机化 → LZW 压缩 → Base64 → ssxmod_itna + ssxmod_itna2
  3. ssxmod-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)

Tool Calling

Qwen3 模型原生支持 Function Calling。工作方式:

  1. 客户端按 OpenAI 格式在 messages 中携带 tools 定义
  2. 中间件将所有消息序列化为文本上下文
  3. Qwen3 模型从上下文理解工具协议,自动生成结构化 tool_calls
  4. 实测 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=fileredis,见下文):代理 untested/available/failed 状态和账号绑定关系写入存储,重启秒级恢复。none 模式不持久(重启重新探测)
  • 四级优先级:先 可用且未占用 → 再 未测试(首次探测)→ 再 已失败(再探测,可能恢复)→ 最后 可用且共享(按占用最少优先)
  • 故障转移:上游请求出现 TCP/SOCKS 类网络错误时自动标记代理失败、换绑、重试(最多 PROXY_MAX_RETRIES 次)
  • 增量去重:从 PROXIES 环境变量 + 持久化记录合并加载,按 URL 去重

管理面板提供 GET /api/proxy/statusPOST /api/proxy/addDELETE /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 模式。

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。

Vercel 部署的三种 Redis 配置

方式 A:Vercel Marketplace 集成 Upstash for Redis(最省事)

  1. Vercel 项目 → StorageCreate Database → 选 Upstash for Redis
  2. 关联到本项目 → 自动注入 KV_REST_API_URL / KV_REST_API_TOKEN
  3. 仅需手动加 DATA_SAVE_MODE=redis,Redeploy

方式 B:Upstash 直连

  1. console.upstash.com 创建 Redis 数据库
  2. REST API 选项卡复制 URL 和 Token
  3. 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

API 接口文档

OpenAI 格式

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 动态获取。

Anthropic Messages 格式

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 等)。

Gemini 格式

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/models

图片 / 视频

POST /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

About

No description, website, or topics provided.

Resources

Contributing

Stars

30 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages