From 795e74349f3b9fb426fbba512240e51555b24393 Mon Sep 17 00:00:00 2001 From: sephiroth <102894885+sephiroth233@users.noreply.github.com> Date: Wed, 23 Jul 2025 10:16:41 +0800 Subject: [PATCH] add pro-api --- pro-api/README.md | 359 ++++++++++++++++++++++++++++++ pro-api/data.yml | 18 ++ pro-api/latest/data.yml | 24 ++ pro-api/latest/docker-compose.yml | 21 ++ pro-api/logo.png | Bin 0 -> 4768 bytes 5 files changed, 422 insertions(+) create mode 100644 pro-api/README.md create mode 100644 pro-api/data.yml create mode 100644 pro-api/latest/data.yml create mode 100644 pro-api/latest/docker-compose.yml create mode 100644 pro-api/logo.png diff --git a/pro-api/README.md b/pro-api/README.md new file mode 100644 index 000000000..8aeee7c2f --- /dev/null +++ b/pro-api/README.md @@ -0,0 +1,359 @@ +# pro-api + +

+ + docker pull + +

+ +[English](./README.md) +[简体中文](./README_CN.md) + + +## 介绍 + +这是一个统一管理大模型API的项目,可以通过OpenAI 的API接口格式调用多个后端服务。该项目旨在简化与不同AI模型的交互,支持多种后端服务的调用。 + +## 支持的后端服务 + +目前支持的后端服务有:OpenAI、Anthropic、Gemini、Vertex、Cloudflare、DeepBricks、OpenRouter等。 + +## 后台功能 + +后台提供请求日志查询和使用统计查询。若不启动后台,则仅进行请求转发,不记录任何信息。 + + +![image-20240912122715188](./assets/image-20240912122715188.png) + +![image-20240912122804912](./assets/image-20240912122804912.png) + +![image-20240912122347488](./assets/image-20240912122347488.png) + +## 配置 + +使用 `api.yaml` 配置文件,可以配置多个模型,每个模型可以配置多个后端服务,支持负载均衡。以下是 `api.yaml` 配置文件的示例: + + +api.yaml +``` +providers: + - provider: openai # 服务提供商 + name: 智谱清言 # 服务名称 + base_url: https://open.bigmodel.cn/api/paas/v4 # 服务地址 + api_key: 请填写你的api_key + model: + - glm-4-flash # 模型名称 + + + - provider: gemini + name: Gemini + base_url: https://generativelanguage.googleapis.com/v1beta + api_key: 请填写你的api_key + model: + - gemini-1.5-pro + - gemini-1.5-flash + - gemini-1.5-flash: gpt-4o + balance: # 配置负载均衡 不配置默认为1 + - gemini-1.5-pro: 1 #表示这个名称下的模型权重是1 + - gemini-1.5-flash: 1 #表示这个名称下的模型权重是2 + - gemini-flash: 1 #表示这个名称下的模型权重是2 + + + - provider: openai + name: 豆包 + base_url: https://ark.cn-beijing.volces.com/api/v3 + api_key: 请填写你的api_key + model: + - ep-20240906033439-zrc2x: doubao-pro-128k # 可以简化模型名称为 doubao-pro-128k + - ep-20240613130011-c2zgx: doubao-pro-32k + - ep-20240729175503-5bbf7: moonshot-v1-128k + + - provider: openai + name: 硅基流动 + base_url: https://api.siliconflow.cn/v1 + api_key: 请填写你的api_key + model: + - Qwen/Qwen2-72B-Instruct: qwen2-72b + - Qwen/Qwen1.5-110B-Chat: qwen1.5-110b + - deepseek-ai/DeepSeek-V2-Chat: deepseek-chat + - deepseek-ai/DeepSeek-Coder-V2-Instruct: deepseek-coder + - Qwen/Qwen2-7B-Instruct: qwen2-7b + - Qwen/Qwen2-7B-Instruct: gpt-3.5-turbo + - Qwen/Qwen2-1.5B-Instruct: qwen2-1.5b + - Qwen/Qwen1.5-7B-Chat: qwen1.5-7b-chat + - THUDM/glm-4-9b-chat: glm-4-9b-chat + - THUDM/chatglm3-6b: chatglm3-6b + - 01-ai/Yi-1.5-9B-Chat-16K: yi-1.5-9b-chat-16k + - 01-ai/Yi-1.5-6B-Chat: yi-1.5-6b-chat + - google/gemma-2-9b-it: gemma-2-9b + - internlm/internlm2_5-7b-chat: internlm-7b-chat + - meta-llama/Meta-Llama-3-8B-Instruct: meta-llama-3-8b + - meta-llama/Meta-Llama-3.1-8B-Instruct: meta-llama-3.1-8b + - mistralai/Mistral-7B-Instruct-v0.2: mistral-7b + + + - provider: openai + name: deepseek + base_url: https://api.deepseek.com/v1 + api_key: 请填写你的api_key + model: + - deepseek-chat + - deepseek-coder + + + - provider: vertexai_claude + name: vertexai_claude + PROJECT_ID: 请填写 + CLIENT_ID: 请填写 + CLIENT_SECRET: 请填写 + REFRESH_TOKEN: 请填写 + model: + - claude-3-5-sonnet@20240620 + - claude-3-5-sonnet@20240620: claude-3-5-sonnet + + - provider: vertexai_gemini + name: vertexai_gemini + PROJECT_ID: 请填写 + CLIENT_ID: 请填写 + CLIENT_SECRET: 请填写 + REFRESH_TOKEN: 请填写 + model: + - gemini-1.5-flash-001 + + + - provider: cohere + name: cohere + base_url: https://api.cohere.com/v1 + api_key: 请填写 + model: + - command-r-plus-08-2024 + - command-r-plus-04-2024: gpt-4 + - command-r-plus + - command-nightly + - command-light + - command-light-nightly + + - provider: cloudflare + name: cloudflare + api_key: 请填写 + account_id: 请填写 + model: + - "@cf/qwen/qwen1.5-14b-chat-awq": qwen1.5-14b + - "@hf/thebloke/deepseek-coder-6.7b-instruct-awq" + + + - provider: openai + name: openrouter + base_url: https://openrouter.ai/api/v1 + api_key: s请填写 + model: + - mattshumer/reflection-70b:free: reflection-70b + - nousresearch/hermes-3-llama-3.1-405b:free: llama-3.1-405b + + + +tokens: + - api_key: sk-111111 + model: + - glm* # 可以使用通配符* + - all # all 代表全部都可以 + + - api_key: sk-222222 + model: + - gpt-3.5-turbo + +server: + default_model: glm-4-flash # 如果匹配不到,则使用这个默认的模型 + debug: false + admin_server: false # 是否启动后台功能 如果不启动则只转发不作任何记录 + db_cache: false # 相同内容的情况下返回上一次成功的回复 + save_log_file: false + db_path: sqlite:///./data/request_log.db + username: admin # 后台用户名 + password: admin # 后台密码 + jwt_secret_key: admin # 随便填不填就随机 +``` + +[vertexai的参数获取教程](./docs/vertexai的参数获取教程.md) + +# 配置负载均衡 + +可以对相同模型名称的模型进行负载均衡 + +默认权重为1 + +``` + - provider: gemini + name: Gemini1 + base_url: https://generativelanguage.googleapis.com/v1beta + api_key: 请填写 + model: + - gemini-1.5-pro + - gemini-1.5-flash + - gemini-1.5-flash : gemini-flash + balance: # 负载均衡 + - gemini-1.5-pro: 1 #表示这个名称下的模型权重是1 + - gemini-1.5-flash: 1 #表示这个名称下的模型权重是2 + - gemini-flash: 1 #表示这个名称下的模型权重是2 + + - provider: gemini + name: Gemini2 + base_url: https://generativelanguage.googleapis.com/v1beta + api_key: 请填写 + model: + - gemini-1.5-pro + - gemini-1.5-flash + - gemini-1.5-flash : gemini-flash + balance: # 负载均衡 + - gemini-1.5-pro: 2 #表示这个名称下的模型权重是1 + - gemini-1.5-flash: 2 #表示这个名称下的模型权重是2 + - gemini-flash: 3 #表示这个名称下的模型权重是2 +``` +以上配置讲解: + +比如: + +当前权重信息 + +* Gemini1 的 gemini-1.5-flash 权重1 +* Gemini2 的 gemini-1.5-flash 权重2 + +请求 gemini-1.5-flash 的时候 + +- 第1次 Gemini1 的 gemini-1.5-flash +- 第2次 Gemini2 的 gemini-1.5-flash +- 第3次 Gemini2 的 gemini-1.5-flash +- 第4次 Gemini1 的 gemini-1.5-flash +- 第5次 Gemini2 的 gemini-1.5-flash + + +## vercel 部署 + + +点击下面的按钮一键部署到 Vercel: + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fduolabmeng6%2Fpro-api&env=config_url,secret_key&project-name=pro-api&repository-name=pro-api) + +部署时需要设置以下环境变量: + +- `config_url`: 远程配置文件的 URL +- `secret_key`: 用于加密的密钥(如果不需要加密,可以留空)如果需要加密,请使用 aes-128-ecb 加密 不加密就给明文的配置内容 + +部署完成后,访问 Vercel 分配的域名即可使用 API。 + +注意:请确保您的远程配置文件 (`config_url`) 可以被公开访问,否则 Vercel 将无法获取配置信息。 + +这里我给一个最简单配置内容 + +config_url=https://可以访问下载配置的地址/api.yaml + +``` +providers: + - provider: openai + name: deepseek + base_url: https://api.deepseek.com/v1 + api_key: sk-xxxxxxxxxxxxx + model: + - deepseek-chat + - deepseek-coder + +tokens: + - api_key: sk-123456 + model: + - all + +server: + default_model: deepseek-chat + +``` + + +## Docker 本地部署 + +启动容器 + +1. 使用本地api.yaml配置文件启动 +```bash +docker run -d \ + --name pro-api \ + -p 8001:8000 \ + -v $(pwd)/api.yaml:/app/api.yaml \ + -v $(pwd)/data:/app/data:rw \ + duolabmeng/pro-api:latest +``` + +2. 使用远程api.yaml配置文件启动 +```bash +docker run -d \ + --name pro-api \ + -e config_url=http://你的服务器/api.yaml \ + -e secret_key=123456789 \ + -p 8001:8000 \ + -v $(pwd)/api.yaml:/app/api.yaml \ + -v $(pwd)/data:/app/data:rw \ + duolabmeng/pro-api:latest +``` +config_url 自动下载远程的配置文件 +secret_key 用aes加密,ECB,128位,如果你要安全记得启动aes密码,不填就给明文的配置内容 + + +3. 如果你想使用 Docker Compose +```yaml +services: + pro-api: + container_name: pro-api + image: duolabmeng/pro-api:latest + environment: + - config_url=http://file_url/api.yaml + - secret_key=123456789 + ports: + - 8001:8000 + volumes: + - ./api.yaml:/app/api.yaml + - ./data/:/app/data:rw +``` + +比如你在某个平台不方便修改配置文件,可以把配置文件传到某个托管服务,可以提供直链给 pro-api 下载,config_url 就是这个直链。 +如果你不想重启容器更新配置访问 /reload_config 即可重新下载刷新配置。 + + +一键重启 Docker 映像 + +```bash +set -eu +docker pull duolabmeng/pro-api:latest +docker rm -f pro-api +docker run --user root -p 8001:8000 -dit --name pro-api \ +-v ./api.yaml:/app/api.yaml \ +duolabmeng/pro-api:latest +docker logs -f pro-api +``` + +RESTful curl 测试 + +```bash +curl -X POST http://127.0.0.1:8000/v1/chat/completions \ +-H "Content-Type: application/json" \ +-H "Authorization: Bearer ${API}" \ +-d '{"model": "gpt-4o","messages": [{"role": "user", "content": "Hello"}],"stream": true}' +``` + +# 帮助 + +1.如果在一些云平台不能安装依赖那么你可以直接把依赖安装到运行的目录然后启动 + +```shell +pip install -r requirements.txt --no-user -t ./app + +``` + +## Star 记录 + + Star History Chart + + +# 赞赏 + +如果觉得项目对你有帮助,可以请作者喝杯咖啡 + +![赞赏](./assets/swskm.jpg) \ No newline at end of file diff --git a/pro-api/data.yml b/pro-api/data.yml new file mode 100644 index 000000000..a669e7c6b --- /dev/null +++ b/pro-api/data.yml @@ -0,0 +1,18 @@ +name: pro-api +tags: +- AI / 大模型 +title: 统一管理大模型 API 的项目,可以通过一个统一的API 接口调用多种不同提供商的服务,统一转换为 OpenAI 格式。 +description: 这是一个统一管理大模型API的项目,可以通过OpenAI 的API接口格式调用多个后端服务。该项目旨在简化与不同AI模型的交互,支持多种后端服务的调用 +additionalProperties: + key: pro-api + name: pro-api + tags: + - AI这是一个统一管理大模型API的项目,可以通过OpenAI 的API接口格式调用多个后端服务。该项目旨在简化与不同AI模型的交互,支持多种后端服务的调用这是一个统一管理大模型 API 的项目,可以通过一个统一的API 接口调用多种不同提供商的服务,统一转换为 OpenAI 格式,支持负载均衡。目前支持的后端服务有:OpenAI、Anthropic、Gemini、Vertex、Azure、xai、Cohere、Groq、Cloudflare、OpenRouter 等。 + shortDescEn: This is a project that centrally manages a large model API and can call multiple backend services through OpenAI's API interface format. The project aims to simplify interactions with different AI models and support the calling of multiple backend services + type: tool + crossVersionUpdate: true + limit: 0 + recommend: 0 + website: https://github.com/duolabmeng6/pro-api + github: https://github.com/duolabmeng6/pro-api + document: https://github.com/duolabmeng6/pro-api/blob/main/README_CN.md diff --git a/pro-api/latest/data.yml b/pro-api/latest/data.yml new file mode 100644 index 000000000..e108c46d1 --- /dev/null +++ b/pro-api/latest/data.yml @@ -0,0 +1,24 @@ +additionalProperties: + formFields: + - default: ./config + edit: true + envKey: LOCAL_CONFIG_PATH + labelEn: local config file path + labelZh: 本地配置文件地址 + required: true + type: text + - default: ./data + edit: true + envKey: DATA_PATH + labelEn: uni-api data path + labelZh: uni-api数据存储路径 + required: true + type: text + - default: 8000 + edit: true + envKey: PANEL_APP_PORT_HTTP + labelEn: Port + labelZh: 端口 + required: true + rule: paramPort + type: number diff --git a/pro-api/latest/docker-compose.yml b/pro-api/latest/docker-compose.yml new file mode 100644 index 000000000..270b52334 --- /dev/null +++ b/pro-api/latest/docker-compose.yml @@ -0,0 +1,21 @@ +services: + pro-api: + image: duolabmeng/pro-api:latest + container_name: ${CONTAINER_NAME} + restart: always + ports: + - ${PANEL_APP_PORT_HTTP}:8000 + volumes: + - "${DATA_PATH}:/app/data:rw" + - "${LOCAL_CONFIG_PATH}:/app/api.yaml" + environment: + - PYTHONUNBUFFERED=1 + networks: + - 1panel-network + labels: + createdBy: "Apps" + + +networks: + 1panel-network: + external: true diff --git a/pro-api/logo.png b/pro-api/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9cec3e62d1817bf3fe702d0d21ccdd15beb049a2 GIT binary patch literal 4768 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

!}0k@$uIak@e=yjlY=N3BnWaKW~gk*dW)%cD3KH zwneSf(5a7)G8=QG9&G%o^pIm^L|i@bbY{D?PdIy50b`l(y!p* u)zeQLhv-{v{-Yu3Xm({aFaH6