From 43852ae871f00908efe0f9849efb1fa34111e15e Mon Sep 17 00:00:00 2001
From: arch3rPro <30855883+arch3rPro@users.noreply.github.com>
Date: Sun, 27 Jul 2025 20:20:38 +0800
Subject: [PATCH] feat: add app One-Hub
---
README.md | 15 +++-
apps/one-hub/0.14.22-allinone/data.yml | 37 ++++++++
.../0.14.22-allinone/docker-compose.yml | 60 +++++++++++++
apps/one-hub/0.14.22/data.yml | 26 ++++++
apps/one-hub/0.14.22/docker-compose.yml | 26 ++++++
apps/one-hub/README.md | 80 ++++++++++++++++++
apps/one-hub/data.yml | 19 +++++
apps/one-hub/latest/data.yml | 26 ++++++
apps/one-hub/latest/docker-compose.yml | 26 ++++++
apps/one-hub/logo.png | Bin 0 -> 18577 bytes
10 files changed, 312 insertions(+), 3 deletions(-)
create mode 100644 apps/one-hub/0.14.22-allinone/data.yml
create mode 100644 apps/one-hub/0.14.22-allinone/docker-compose.yml
create mode 100644 apps/one-hub/0.14.22/data.yml
create mode 100644 apps/one-hub/0.14.22/docker-compose.yml
create mode 100644 apps/one-hub/README.md
create mode 100644 apps/one-hub/data.yml
create mode 100644 apps/one-hub/latest/data.yml
create mode 100644 apps/one-hub/latest/docker-compose.yml
create mode 100644 apps/one-hub/logo.png
diff --git a/README.md b/README.md
index 6549c6d..4278e4c 100644
--- a/README.md
+++ b/README.md
@@ -439,7 +439,7 @@ AI驱动的开源代码知识库与文档协作平台,支持多模型、多数
-|
+ |
@@ -451,10 +451,19 @@ AI驱动的开源代码知识库与文档协作平台,支持多模型、多数
0.8.7.5 • [官网链接](https://docs.newapi.pro/)
|
-
+ |
+
+
+
+ One-Hub
+
+
+🔗 统一的AI模型管理和调用平台,支持多种大语言模型集成
+
+0.14.22 • [官网链接](https://github.com/one-hub/one-hub)
|
-
+ |
|
diff --git a/apps/one-hub/0.14.22-allinone/data.yml b/apps/one-hub/0.14.22-allinone/data.yml
new file mode 100644
index 0000000..cfe5c05
--- /dev/null
+++ b/apps/one-hub/0.14.22-allinone/data.yml
@@ -0,0 +1,37 @@
+additionalProperties:
+ formFields:
+ - default: newapi
+ edit: true
+ envKey: PANEL_DB_NAME
+ labelEn: Database
+ labelZh: 数据库名
+ random: true
+ required: true
+ rule: paramCommon
+ type: text
+ - default: newapi
+ edit: true
+ envKey: PANEL_DB_ROOT_PASSWORD
+ labelEn: Password
+ labelZh: 数据库密码
+ random: true
+ required: true
+ rule: paramComplexity
+ type: password
+ - default: 9khGG1O59Ih4ZWrpsiFKTf8bW7ZqJR01
+ edit: true
+ envKey: USER_TOKEN_SECRET
+ labelEn: Password
+ labelZh: 用户Token
+ random: true
+ required: true
+ rule: paramComplexity
+ type: password
+ - default: 3000
+ edit: true
+ envKey: PANEL_APP_PORT_HTTP
+ labelEn: Port
+ labelZh: 端口
+ required: true
+ rule: paramPort
+ type: number
diff --git a/apps/one-hub/0.14.22-allinone/docker-compose.yml b/apps/one-hub/0.14.22-allinone/docker-compose.yml
new file mode 100644
index 0000000..3fe33cc
--- /dev/null
+++ b/apps/one-hub/0.14.22-allinone/docker-compose.yml
@@ -0,0 +1,60 @@
+services:
+ one-hub:
+ image: martialbe/one-api:v0.14.22
+ container_name: ${CONTAINER_NAME}
+ restart: always
+ ports:
+ - ${PANEL_APP_PORT_HTTP}:3000
+ networks:
+ - 1panel-network
+ command: --log-dir /app/logs
+ volumes:
+ - ./data:/data
+ - ./logs:/app/logs
+ environment:
+ - SQL_DSN=root:${PANEL_DB_ROOT_PASSWORD}@tcp(${CONTAINER_NAME}-mysql:3306)/${PANEL_DB_NAME} # 修改此行,或注释掉以使用 SQLite 作为数据库
+ - TZ=Asia/Shanghai
+ - REDIS_CONN_STRING=redis://${CONTAINER_NAME}-redis
+ - USER_TOKEN_SECRET=${USER_TOKEN_SECRET}
+ - ERROR_LOG_ENABLED=true # 是否启用错误日志记录
+ # - STREAMING_TIMEOUT=120 # 流模式无响应超时时间,单位秒,默认120秒,如果出现空补全可以尝试改为更大值
+ # - SESSION_SECRET=random_string # 多机部署时设置,必须修改这个随机字符串!!!!!!!
+ # - NODE_TYPE=slave # Uncomment for slave node in multi-node deployment
+ # - SYNC_FREQUENCY=60 # Uncomment if regular database syncing is needed
+ # - FRONTEND_BASE_URL=https://openai.justsong.cn # Uncomment for multi-node deployment with front-end URL
+ depends_on:
+ - redis
+ - mysql
+ healthcheck:
+ test: ["CMD-SHELL", "wget -q -O - http://localhost:3000/api/status | grep -o '\"success\":\\s*true' | awk -F: '{print $$2}'"]
+ interval: 30s
+ timeout: 10s
+ retries: 3
+ labels:
+ createdBy: "Apps"
+
+ mysql:
+ image: mysql:8.2
+ container_name: ${CONTAINER_NAME}-mysql
+ restart: always
+ volumes:
+ - onehub-mysql_data:/var/lib/mysql
+ environment:
+ - MYSQL_ROOT_PASSWORD=${PANEL_DB_ROOT_PASSWORD} # MySQL root用户密码
+ - MYSQL_DATABASE=${PANEL_DB_NAME} # 创建的数据库名
+ networks:
+ - 1panel-network
+
+ redis:
+ image: redis:latest
+ container_name: ${CONTAINER_NAME}-redis
+ restart: always
+ networks:
+ - 1panel-network
+
+volumes:
+ onehub-mysql_data:
+
+networks:
+ 1panel-network:
+ external: true
diff --git a/apps/one-hub/0.14.22/data.yml b/apps/one-hub/0.14.22/data.yml
new file mode 100644
index 0000000..c3896c3
--- /dev/null
+++ b/apps/one-hub/0.14.22/data.yml
@@ -0,0 +1,26 @@
+additionalProperties:
+ formFields:
+ - default: 3000
+ edit: true
+ envKey: PANEL_APP_PORT_HTTP
+ labelEn: Port
+ labelZh: 端口
+ required: true
+ rule: paramPort
+ type: number
+ - default: Asia/Shanghai
+ edit: true
+ envKey: TZ
+ labelEn: Time Zone
+ labelZh: 时区
+ required: true
+ type: text
+ - default: 9khGG1O59Ih4ZWrpsiFKTf8bW7ZqJR01
+ edit: true
+ envKey: USER_TOKEN_SECRET
+ labelEn: Password
+ labelZh: 用户Token
+ random: true
+ required: true
+ rule: paramComplexity
+ type: password
\ No newline at end of file
diff --git a/apps/one-hub/0.14.22/docker-compose.yml b/apps/one-hub/0.14.22/docker-compose.yml
new file mode 100644
index 0000000..811f29f
--- /dev/null
+++ b/apps/one-hub/0.14.22/docker-compose.yml
@@ -0,0 +1,26 @@
+services:
+ one-hub:
+ image: martialbe/one-api:v0.14.22
+ container_name: ${CONTAINER_NAME}
+ restart: always
+ ports:
+ - ${PANEL_APP_PORT_HTTP}:3000
+ networks:
+ - 1panel-network
+ command: --log-dir /app/logs
+ volumes:
+ - ./data:/data
+ - ./logs:/app/logs
+ environment:
+ - TZ=${TZ}
+ - USER_TOKEN_SECRET=${USER_TOKEN_SECRET}
+# - SESSION_SECRET=${SESSION_SECRET}
+# - REDIS_CONN_STRING=redis://redis
+# - NODE_TYPE=slave # 多机部署时从节点取消注释该行
+# - SYNC_FREQUENCY=60 # 需要定期从数据库加载数据时取消注释该行
+# - FRONTEND_BASE_URL=https://openai.justsong.cn # 多机部署时从节点取消注释该行
+ labels:
+ createdBy: "Apps"
+networks:
+ 1panel-network:
+ external: true
diff --git a/apps/one-hub/README.md b/apps/one-hub/README.md
new file mode 100644
index 0000000..7b0e5d1
--- /dev/null
+++ b/apps/one-hub/README.md
@@ -0,0 +1,80 @@
+
+# One Hub
+
+OpenAI 接口管理 & 分发系统,改自songquanpeng/one-api。支持更多模型,加入统计页面,完善非openai模型的函数调用。
+
+
+
+
+
+> 管理员默认账号密码为 root:123456,请登录后及时修改
+
+**请不要和原版混用,因为新增功能,数据库与原版不兼容**
+
+**为了更加简洁,本项目之后,除了新增供应商时会更新程序自带的模型列表,平常不再更新程序自带的模型列表。**
+
+**如果发现缺少新模型,请在`后台-模型价格-更新价格`中更新新增的模型**
+
+
+> [!WARNING]
+> 本项目为个人学习使用,不保证稳定性,且不提供任何技术支持,使用者必须在遵循 OpenAI 的使用条款以及法律法规的情况下使用,不得用于非法用途。
+> 根据[《生成式人工智能服务管理暂行办法》](http://www.cac.gov.cn/2023-07/13/c_1690898327029107.htm)的要求,请勿对中国地区公众提供一切未经备案的生成式人工智能服务。
+
+## 功能变化
+
+- 全新的 UI 界面
+- 新增用户仪表盘
+- 新增管理员分析数据统计界面
+- 重构了中转`供应商`模块
+- 支持使用`Azure Speech`模拟`TTS`功能
+- 渠道可配置单独的 http/socks5 代理
+- 支持动态返回用户模型列表
+- 支持自定义测速模型
+- 日志增加请求耗时
+- 支持和优化非 OpenAI 模型的函数调用(支持的模型可以在 lobe-chat 直接使用)
+- 支持完成倍率自定义
+- 支持完整的分页和排序
+- 支持`Telegram bot`
+- 支持模型按次收费
+- 支持模型通配符
+- 支持使用配置文件启动程序
+- 支持模型价格更新
+- 支持自动获取供应商模型
+- 支持仅聊天,开启后如果有传入`function call`参数会跳过该渠道
+- 支持支付
+- 支持配置用户组 RPM
+- 支持`Prometheus`监控
+
+## 文档
+
+请查看[文档](https://github.com/MartialBE/one-hub/wiki)
+
+## 当前支持的供应商
+
+| 供应商 | Chat | Embeddings | Audio | Images | 其他 |
+| --------------------------------------------------------------------- | ------------------------ | ---------- | ------ | ----------- | ---------------------------------------------------------------- |
+| [OpenAI](https://platform.openai.com/docs/api-reference/introduction) | ✅ | ✅ | ✅ | ✅ | - |
+| [Azure OpenAI](https://oai.azure.com/) | ✅ | ✅ | ✅ | ✅ | - |
+| [Azure Speech](https://portal.azure.com/) | - | - | ⚠️ tts | - | - |
+| [Anthropic](https://www.anthropic.com/) | ✅ | - | - | - | - |
+| [Gemini](https://aistudio.google.com/) | ✅ | - | - | - | - |
+| [百度文心](https://console.bce.baidu.com/qianfan/overview) | ✅ | ✅ | - | - | - |
+| [通义千问](https://dashscope.console.aliyun.com/overview) | ✅ | ✅ | - | - | - |
+| [讯飞星火](https://console.xfyun.cn/) | ✅ | - | - | - | - |
+| [智谱](https://open.bigmodel.cn/overview) | ✅ | ✅ | - | ⚠️ 图片生成 | - |
+| [腾讯混元](https://cloud.tencent.com/product/hunyuan) | ✅ | - | - | - | - |
+| [百川](https://platform.baichuan-ai.com/console/apikey) | ✅ | ✅ | - | - | - |
+| [MiniMax](https://www.minimaxi.com/user-center/basic-information) | ✅ | ✅ | - | - | - |
+| [Deepseek](https://platform.deepseek.com/usage) | ✅ | - | - | - | - |
+| [Moonshot](https://moonshot.ai/) | ✅ | - | - | - | - |
+| [Mistral](https://mistral.ai/) | ✅ | ✅ | - | - | - |
+| [Groq](https://console.groq.com/keys) | ✅ | - | - | - | - |
+| [Amazon Bedrock](https://console.aws.amazon.com/bedrock/home) | ⚠️ 仅支持 Anthropic 模型 | - | - | - | - |
+| [零一万物](https://platform.lingyiwanwu.com/details) | ✅ | - | - | - | - |
+| [Cloudflare AI](https://ai.cloudflare.com/) | ✅ | - | ⚠️ stt | ⚠️ 图片生成 | - |
+| [Midjourney](https://www.midjourney.com/) | - | - | - | - | [midjourney-proxy](https://github.com/novicezk/midjourney-proxy) |
+| [Cohere](https://cohere.com/) | ✅ | - | - | - | - |
+| [Stability AI](https://platform.stability.ai/account/credits) | - | - | - | ⚠️ 图片生成 | - |
+| [Coze](https://www.coze.com/open/docs/chat?_lang=zh) | ✅ | - | - | - | - |
+| [Ollama](https://github.com/ollama/ollama) | ✅ | ✅ | - | - | - |
+| [Suno](https://suno.com/) | - | - | - | - | [Suno-API](https://github.com/Suno-API/Suno-API) |
diff --git a/apps/one-hub/data.yml b/apps/one-hub/data.yml
new file mode 100644
index 0000000..238e9d8
--- /dev/null
+++ b/apps/one-hub/data.yml
@@ -0,0 +1,19 @@
+name: One-Hub
+tags:
+ - AI / 大模型
+title: OpenAI 接口管理 & 分发系统
+description: OpenAI 接口管理 & 分发系统
+additionalProperties:
+ key: one-hub
+ name: One-Hub
+ tags:
+ - AI
+ shortDescZh: AI模型接口管理与分发系统,OpenAI 接口管理 & 分发系统,改自songquanpeng/one-api。支持更多模型,加入统计页面,完善非openai模型的函数调用。
+ shortDescEn: Access all LLM through the standard OpenAI API format, easy to deploy & use
+ type: website
+ crossVersionUpdate: true
+ limit: 0
+ recommend: 0
+ website: https://one-hub.xiao5.info/
+ github: https://github.com/MartialBE/one-hub
+ document: https://github.com/MartialBE/one-hub/blob/main/README.md
diff --git a/apps/one-hub/latest/data.yml b/apps/one-hub/latest/data.yml
new file mode 100644
index 0000000..c3896c3
--- /dev/null
+++ b/apps/one-hub/latest/data.yml
@@ -0,0 +1,26 @@
+additionalProperties:
+ formFields:
+ - default: 3000
+ edit: true
+ envKey: PANEL_APP_PORT_HTTP
+ labelEn: Port
+ labelZh: 端口
+ required: true
+ rule: paramPort
+ type: number
+ - default: Asia/Shanghai
+ edit: true
+ envKey: TZ
+ labelEn: Time Zone
+ labelZh: 时区
+ required: true
+ type: text
+ - default: 9khGG1O59Ih4ZWrpsiFKTf8bW7ZqJR01
+ edit: true
+ envKey: USER_TOKEN_SECRET
+ labelEn: Password
+ labelZh: 用户Token
+ random: true
+ required: true
+ rule: paramComplexity
+ type: password
\ No newline at end of file
diff --git a/apps/one-hub/latest/docker-compose.yml b/apps/one-hub/latest/docker-compose.yml
new file mode 100644
index 0000000..62c3b9b
--- /dev/null
+++ b/apps/one-hub/latest/docker-compose.yml
@@ -0,0 +1,26 @@
+services:
+ one-hub:
+ image: martialbe/one-api:latest
+ container_name: ${CONTAINER_NAME}
+ restart: always
+ ports:
+ - ${PANEL_APP_PORT_HTTP}:3000
+ networks:
+ - 1panel-network
+ command: --log-dir /app/logs
+ volumes:
+ - ./data:/data
+ - ./logs:/app/logs
+ environment:
+ - TZ=${TZ}
+ - USER_TOKEN_SECRET=${USER_TOKEN_SECRET}
+# - SESSION_SECRET=${SESSION_SECRET}
+# - REDIS_CONN_STRING=redis://redis
+# - NODE_TYPE=slave # 多机部署时从节点取消注释该行
+# - SYNC_FREQUENCY=60 # 需要定期从数据库加载数据时取消注释该行
+# - FRONTEND_BASE_URL=https://openai.justsong.cn # 多机部署时从节点取消注释该行
+ labels:
+ createdBy: "Apps"
+networks:
+ 1panel-network:
+ external: true
diff --git a/apps/one-hub/logo.png b/apps/one-hub/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..da6602d6b6499ea9856e1e240fba957119342e07
GIT binary patch
literal 18577
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