commit 557ec170da18a84b44384e3446cc3819e0d36617 Author: ericwyuan Date: Sun Aug 23 08:24:56 2026 +0800 docs(项目启动): SRS/SDD 文档入库 + README/PROGRESS + 仓库初始化 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..69cce6c --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Env / Secrets (contains real API keys, NEVER commit) +.env +.env.local +*.env +!.env.example + +# Docker persistent data +one-api-data/ +mysql-data/ +certs/ + +# Logs +logs/ +*.log + +# OS / IDE +.DS_Store +Thumbs.db +.idea/ +.vscode/ +*.swp +*.swo + +# Python +__pycache__/ +*.py[cod] +venv/ +.venv +dist/ +build/ diff --git a/PROGRESS.md b/PROGRESS.md new file mode 100644 index 0000000..f08decf --- /dev/null +++ b/PROGRESS.md @@ -0,0 +1,49 @@ +# 项目进度追踪 + +> 最后更新: 2026-08-23 + +## 服务运行状态 + +| 服务 | 节点 | 状态 | 说明 | +|------|------|------|------| +| Nginx | 美国服务器(待申请) | ⏳ 未部署 | HTTPS 反向代理层 | +| LobeChat | 美国服务器(待申请) | ⏳ 未部署 | 前端对话界面 | +| One-API | 美国服务器(待申请) | ⏳ 未部署 | 网关聚合层 | +| MySQL | 美国服务器(待申请) | ⏳ 未部署 | One-API 数据存储 | + +## 2026-08-23 项目启动:文档入库 + 仓库初始化 + +- **决策**:采用成熟开源组件(Nginx + LobeChat + One-API + MySQL)容器化搭建,不重复造轮子;网关对外统一暴露 `auto-vision` / `auto-text` 两个聚合模型名。 +- **文档**:`docs/01-软件需求文档-SRS.md`(V1.0)+ `docs/02-软件设计文档-SDD.md`(V1.0)入库;README 汇总架构/服务器访问信息/提交规范。 +- **安全**:Gemini 与 NVIDIA 的旧 API Key 不写入仓库(将申请新值);所有 Key 计划通过服务器 `.env` 管理(已加入 .gitignore)。 +- **仓库**:本地初始化,推送 Gitea `http://192.168.50.64:3000/ericwyuan/NexusAI`。 + +## 任务进度 + +### 已完成 + +| # | 任务 | 日期 | +|---|------|------| +| 1 | 软件需求文档(SRS V1.0)入库 | 2026-08-23 | +| 2 | 软件设计文档(SDD V1.0)入库 | 2026-08-23 | +| 3 | README(架构/服务器信息/提交规范) | 2026-08-23 | +| 4 | 仓库初始化 + 推送 Gitea | 2026-08-23 | + +### 待完成 + +| # | 任务 | 依赖 | 优先级 | +|---|------|------|--------| +| 1 | 申请美国服务器(网关部署目标) | - | 高 | +| 2 | 申请新 Gemini / NVIDIA API Key | - | 高 | +| 3 | 生成部署骨架(docker-compose.yml / nginx.conf / .env.example) | 文档 | 高 | +| 4 | 实际部署 + One-API 渠道配置(5 家)+ Failover 验证 | 服务器/Key | 高 | +| 5 | HTTPS 域名与证书 | 服务器 | 中 | +| 6 | 确认 Server-Side 模式 / 管理端口访问方式 / 监控方案 | 决策 | 中 | + +## 技术决策记录 + +1. **不重复造轮子** - 网关用 One-API、前端用 LobeChat,仅做配置层工作;前端、网关、各 AI 渠道间均走 OpenAI 兼容接口,任一组件可替换 +2. **模型映射** - 前端只感知 `auto-vision`(图文)与 `auto-text`(纯文本)两个聚合模型名,多渠道不同模型映射到统一对外模型名 +3. **优先级路由** - 渠道优先级数字越小越优先,同优先级内按权重轮询分摊负载 +4. **冷却恢复** - 渠道连续失败超阈值(5 次/5 分钟)进入冷却禁用,冷却期(10 分钟)后自动恢复参与路由 +5. **最小暴露面** - 仅 Nginx 80/443 对公网暴露,One-API 后台与 MySQL 端口仅容器内网可访问 diff --git a/README.md b/README.md new file mode 100644 index 0000000..b3291de --- /dev/null +++ b/README.md @@ -0,0 +1,195 @@ +# NexusAI — 自建多模态 AI 网关系统(AI Gateway System) + +> 聚合多家免费多模态 AI API 的统一对话网关:Nginx + LobeChat + One-API + MySQL 容器化部署。 +> 单一渠道不可用时自动故障转移(Failover),用户无感知。 +> 最后更新:2026-08-23(文档入库,尚未部署) + +--- + +## 1. 项目简介与设计目标 + +公司内网直连 NVIDIA NIM、Gemini 等免费大模型 API 不稳定,本系统部署在美国服务器上,聚合 5 家免费多模态 API(Gemini、NVIDIA NIM、Groq、OpenRouter、Mistral),通过 One-API 网关统一路由,实现"一个渠道不可用自动切换下一个"的高可用能力,并提供接近 Gemini 首页体验的 Web 对话界面(LobeChat),支持图片 + 文字混合输入问答。 + +### 1.1 核心价值 + +- **聚合免费额度 + 高可用**:用户只需在统一界面提问/上传图片,无需关心调用哪家模型 +- **配置驱动**:渠道增删、优先级调整通过 One-API 后台界面完成,不改代码 +- **全部免费**:仅使用各平台免费额度,不产生 API 调用费用 + +### 1.2 文档 + +- [软件需求规格说明书(SRS)V1.0](docs/01-软件需求文档-SRS.md) +- [软件设计说明书(SDD)V1.0](docs/02-软件设计文档-SDD.md) + +--- + +## 2. 系统架构 + +``` +浏览器 / 移动端浏览器(公司内网) + │ HTTPS (443) + ▼ +Nginx(反向代理,HTTPS 终止,流式透传)──► LobeChat(前端,:3210)──► One-API(网关,:3000 仅内网)──► MySQL + │ + ┌──────────────┬──────────────┬──────────────┐ + ▼ ▼ ▼ ▼ + Gemini NVIDIA NIM Groq OpenRouter Mistral +``` + +| 层级 | 组件 | 职责 | +|---|---|---| +| 接入层 | Nginx | HTTPS 终止、反向代理、访问入口统一 | +| 表现层 | LobeChat | 对话界面渲染、图片上传、Access Code 鉴权、对话历史(IndexedDB) | +| 网关层 | One-API | 协议转换、渠道路由、Failover、用量统计 | +| 数据层 | MySQL | 渠道配置 / Token / 调用日志持久化 | + +### 2.1 渠道设计(优先级数字越小越优先) + +| 渠道名 | Base URL | 优先级 | 支持视觉 | +|---|---|---|---| +| nvidia-nim | integrate.api.nvidia.com/v1 | 1 | 部分模型 | +| gemini | generativelanguage.googleapis.com/v1beta | 1 | 是 | +| openrouter | openrouter.ai/api/v1 | 2 | 部分模型(:free) | +| groq | api.groq.com/openai/v1 | 2 | 有限 | +| mistral | api.mistral.ai/v1 | 3 | Pixtral 系列 | + +### 2.2 模型映射(前端只感知两个聚合模型名) + +| 对外模型名 | 用途 | 关联渠道 | +|---|---|---| +| `auto-vision` | 图文混合问答 | Gemini、NVIDIA(视觉模型)、OpenRouter(视觉模型)、Mistral(Pixtral) | +| `auto-text` | 纯文本问答 | 上述全部 + Groq | + +### 2.3 故障转移策略 + +1. 请求按 `auto-vision` / `auto-text` 匹配渠道池,按优先级从高到低尝试 +2. 渠道返回 429/5xx/超时 → 标记本次失败,自动尝试下一渠道 +3. 连续失败超阈值 → 渠道进入"冷却禁用",冷却期后自动恢复 +4. 全部渠道失败 → 向前端返回明确错误提示(不静默失败) + +--- + +## 3. 部署概览 + +- **方式**:单机 Docker Compose,所有服务在同一 `ai-network` 内,仅 Nginx 80/443 对公网暴露 +- **目录结构**:`docker-compose.yml` / `.env`(敏感变量,不入库)/ `nginx.conf` / `certs/` / `one-api-data/` / `mysql-data/` +- **详细部署步骤**:见 [SDD 第 6 章](docs/02-软件设计文档-SDD.md#6-部署设计) + +### 3.1 容器服务 + +| 服务 | 镜像 | 端口 | 说明 | +|---|---|---|---| +| nginx | nginx:alpine | 80/443(公网) | HTTPS 终止、反向代理 | +| lobe-chat | lobehub/lobe-chat:latest | 3210(内网) | 前端对话界面 | +| one-api | justsong/one-api:latest | 3000(内网) | 网关聚合层 | +| mysql | mysql:8.0 | 3306(内网) | One-API 数据存储 | + +### 3.2 安全要点 + +- One-API 后台端口(3000)不映射公网,远程管理走 SSH 隧道 / VPN +- 所有 API Key 通过服务器 `.env` 注入容器环境变量,`.env` 不入库(见 [SDD 第 5 章](docs/02-软件设计文档-SDD.md#5-安全设计)) +- 前端强制 `ACCESS_CODE` 校验;Nginx 全站 HTTPS + +--- + +## 4. 服务器访问信息 + +### 4.1 Synology NAS(FAM-Core + FAM-UI + MariaDB + Gitea) + +| 项目 | 值 | +|---|---| +| IP | 192.168.50.64 | +| SSH 端口 | 2222(scp 禁用,用 stdin 管道传文件) | +| SSH 用户 / 密码 | ericwyuan / iLoveJava5 | +| 系统 | Synology DS220+ (Geminilake), DSM 7 | +| Tailscale IP | 100.70.234.39(userspace 模式,端口不通待修) | +| 登录命令 | `ssh -p 2222 ericwyuan@192.168.50.64` | + +### 4.2 MariaDB(NAS) + +| 项目 | 值 | +|---|---| +| 版本 | MariaDB 10.11.11 | +| Socket | /run/mysqld/mysqld10.sock | +| Root 密码 | iLoveJava5! | +| 连接 | `/usr/local/mariadb10/bin/mysql -S /run/mysqld/mysqld10.sock -u root -p` | + +### 4.3 Oracle Cloud(FAM-Edge + Ollama + FFmpeg) + +| 项目 | 值 | +|---|---| +| 公网 IP | 129.146.203.203 | +| SSH 用户 | ubuntu(密钥 `~/.ssh/oracle_sentinel`) | +| 系统 | aarch64 (Ampere A1 2C12G), Ubuntu 20.04 LTS | +| Tailscale | 100.74.137.126(已安装在线,与 NAS 端口不通) | +| 登录命令 | `ssh -i ~/.ssh/oracle_sentinel ubuntu@129.146.203.203` | + +### 4.4 Gitea 代码仓库 + +| 项目 | 值 | +|---|---| +| URL | http://192.168.50.64:3000/ericwyuan/NexusAI | +| 账号 / 密码 | ericwyuan / iLoveJava5 | + +> 美国服务器(AI 网关部署目标)访问信息待补充。 + +--- + +## 5. AI 渠道 API Key(服务器 `.env` 管理,不入库) + +> ⚠️ Gemini 与 NVIDIA 的 Key 将申请新值,此处不写入旧 Key,配置于美国服务器 `.env` 的占位变量。 + +| 渠道 | 模型 / 端点 | Key 环境变量(服务器 .env) | +|---|---|---| +| Gemini | `generativelanguage.googleapis.com/v1beta`,模型 `gemini-flash-latest` | `${GEMINI_API_KEY}`(新 Key 待申请) | +| NVIDIA NIM | `integrate.api.nvidia.com/v1`,默认 `meta/llama-3.2-11b-vision-instruct` | `${NVIDIA_API_KEY}`(新 Key 待申请) | +| Groq | `api.groq.com/openai/v1` | `${GROQ_API_KEY}` | +| OpenRouter | `openrouter.ai/api/v1` | `${OPENROUTER_API_KEY}` | +| Mistral | `api.mistral.ai/v1` | `${MISTRAL_API_KEY}` | + +> 各渠道 Key 申请后填入美国服务器 `.env`,One-API 后台添加渠道时引用,切勿提交版本库。 + +--- + +## 6. 提交规范(AI Agent 必读) + +**工作流程(强制)**: + +1. **开工前**:仓库根目录 `git pull --rebase` +2. **每完成一项验收子任务**:立即 `git add` + `git commit` + `git push`,一任务一 commit,不批量合并 +3. **遇到阻塞**:先 commit 可工作部分,message 加 `[WIP]` 前缀 +4. **修 Bug**:单独 commit,格式 `fix(模块): 问题简述` + +**commit message 格式**: + +- 任务:`[阶段X.Y子任务号] 子任务名称 - 完成内容简述` +- Bug:`fix(模块): 问题简述` +- 性能/文档:`perf(...)` / `docs(...)` + +**禁止**:不 commit 直接继续;一次 commit 多个子任务;`git push --force`;跳过 hooks(`--no-verify`)。 + +**自检清单**:任务对应哪一行验收标准?是否已 commit + push?message 是否合规?开工前是否 pull --rebase? + +--- + +## 7. 当前进度与待办 + +### 已完成(截至 2026-08-23) + +- 软件需求文档(SRS V1.0)与软件设计文档(SDD V1.0)入库(`docs/`) +- 项目仓库初始化(Gitea: ericwyuan/NexusAI) + +### 待办(见 SDD 第 8 章待确认事项) + +| # | 任务 | 优先级 | +|---|------|--------| +| 1 | 申请美国服务器,确认访问信息 | 高 | +| 2 | 申请新 Gemini / NVIDIA API Key | 高 | +| 3 | 确认 HTTPS 域名与证书方案 | 中 | +| 4 | 生成部署骨架(docker-compose.yml / nginx.conf / .env.example) | 高 | +| 5 | 实际部署 + One-API 渠道配置 + Failover 验证 | 高 | +| 6 | 确认 Server-Side 模式 / 管理端口访问方式 / 监控方案 | 中 | + +--- + +文档结束 diff --git a/docs/01-软件需求文档-SRS.md b/docs/01-软件需求文档-SRS.md new file mode 100644 index 0000000..1960792 --- /dev/null +++ b/docs/01-软件需求文档-SRS.md @@ -0,0 +1,199 @@ +# 软件需求规格说明书(SRS) +## 自建多模态 AI 网关系统(AI Gateway System) + +| 项目 | 内容 | +|---|---| +| 文档版本 | V1.0 | +| 编写日期 | 2026-08-23 | +| 项目负责人 | 紫川 | +| 文档状态 | 草案 | + +--- + +## 1. 引言 + +### 1.1 编写目的 + +本文档描述"自建多模态 AI 网关系统"的功能需求、非功能需求与约束条件,作为后续软件设计说明书(SDD)编写和开发实现的依据。 + +### 1.2 项目背景 + +由于公司内网访问 NVIDIA NIM、Gemini 等免费大模型 API 不稳定,希望在自有美国服务器上搭建一套类似 Gemini 首页体验的对话系统,聚合多个免费 AI API 渠道,实现"一个渠道不可用自动切换下一个"的高可用能力,同时支持图文多模态问答。 + +### 1.3 项目目标 + +- 提供稳定、统一的 Web 对话入口,界面体验接近 Gemini 首页 +- 聚合至少 5 家免费多模态 API(Gemini、NVIDIA NIM、Groq、OpenRouter、Mistral) +- 单一渠道失败时自动故障转移(Failover),用户无感知 +- 支持图片 + 文字混合输入的问答 +- 部署在美国服务器,规避公司内网对海外 API 的直连限制 +- 全部使用免费额度,不产生 API 调用费用 + +### 1.4 术语定义 + +| 术语 | 说明 | +|---|---| +| 渠道(Channel) | 指某一家 AI API 提供商的接入配置,如 Gemini 渠道、Groq 渠道 | +| 网关(Gateway) | 统一转发、聚合多个渠道请求的中间层服务,本项目采用 One-API | +| Failover | 故障转移,某渠道不可用时自动切换到下一优先级渠道 | +| 多模态(Multimodal) | 同时支持文本与图像作为输入的模型能力 | +| RPM | Requests Per Minute,每分钟请求数限制 | + +--- + +## 2. 总体描述 + +### 2.1 产品定位 + +本系统是一个**私有部署的 AI 对话网关**,面向单用户(紫川本人,未来可扩展至团队),核心价值是"聚合免费额度 + 高可用" —— 让用户无需关心具体调用了哪家模型,只需要在统一界面里提问、上传图片,系统自动选择当前可用的免费渠道完成响应。 + +### 2.2 用户角色 + +| 角色 | 描述 | +|---|---| +| 终端用户 | 使用 LobeChat 前端进行日常图文问答的人(紫川本人) | +| 系统管理员 | 配置渠道、监控用量、调整优先级的人(紫川本人,同一人身兼两角) | + +### 2.3 运行环境 + +- 部署位置:美国服务器(无地区网络限制) +- 访问方来源:公司内网(网络不稳定,仅需保证到本服务器一段链路可用) +- 容器化部署:Docker + Docker Compose +- 操作系统:Linux(Ubuntu/Debian 系) + +### 2.4 约束与假设 + +- 假设:美国服务器可稳定访问 Google、NVIDIA、Groq、OpenRouter、Mistral 官方域名 +- 约束:仅使用各平台免费额度,不产生付费调用 +- 约束:不做未成年人相关内容、不涉及企业内部代码泄露到公网模型(需用户自行注意脱敏) +- 假设:公司内网到美国服务器的连接比公司内网直连各 API 官方域名更稳定 + +--- + +## 3. 功能需求 + +### FR-1 统一对话界面 + +| 编号 | 描述 | 优先级 | +|---|---|---| +| FR-1.1 | 提供 Web 端对话界面,支持文本输入 | 高 | +| FR-1.2 | 支持图片上传并随文本一起提问(多模态输入) | 高 | +| FR-1.3 | 支持流式输出(打字机效果) | 中 | +| FR-1.4 | 支持多轮对话上下文保留 | 高 | +| FR-1.5 | 支持对话历史保存与查看 | 中 | +| FR-1.6 | 界面访问需密码验证(Access Code) | 高 | + +### FR-2 多渠道聚合与路由 + +| 编号 | 描述 | 优先级 | +|---|---|---| +| FR-2.1 | 支持接入 Gemini、NVIDIA NIM、Groq、OpenRouter、Mistral 五家渠道 | 高 | +| FR-2.2 | 支持为渠道设置优先级与权重 | 高 | +| FR-2.3 | 支持将多个渠道的不同模型映射为统一对外模型名 | 高 | +| FR-2.4 | 请求失败(限流/超时/额度耗尽)时自动切换下一优先级渠道 | 高 | +| FR-2.5 | 渠道故障后自动禁用,冷却期后自动恢复重试 | 中 | + +### FR-3 多模态能力 + +| 编号 | 描述 | 优先级 | +|---|---|---| +| FR-3.1 | 图文问答仅路由到支持视觉的渠道/模型 | 高 | +| FR-3.2 | 纯文本问答可路由到所有渠道(含无视觉能力的 Groq) | 中 | + +### FR-4 渠道管理(管理员) + +| 编号 | 描述 | 优先级 | +|---|---|---| +| FR-4.1 | 支持在后台新增/编辑/删除渠道 | 高 | +| FR-4.2 | 支持查看每个渠道的调用次数、成功率、余额/额度状态 | 中 | +| FR-4.3 | 支持手动启用/禁用某个渠道 | 中 | +| FR-4.4 | 支持生成/吊销对外 Token | 高 | + +### FR-5 安全与访问控制 + +| 编号 | 描述 | 优先级 | +|---|---|---| +| FR-5.1 | 前端需 Access Code 才能进入对话界面 | 高 | +| FR-5.2 | 后台管理端口不直接暴露公网 | 高 | +| FR-5.3 | 全站启用 HTTPS | 高 | +| FR-5.4 | API Key 等敏感信息通过环境变量管理,不写入代码仓库 | 高 | + +--- + +## 4. 非功能需求 + +### 4.1 性能需求 + +| 指标 | 目标值 | +|---|---| +| 单次请求响应首字延迟 | < 3 秒(视具体渠道而定) | +| Failover 切换耗时 | < 5 秒 | +| 并发用户数 | 支持 1~5 人同时使用(当前阶段单用户为主) | + +### 4.2 可用性需求 + +- 系统整体可用性目标:99%(不含各免费 API 官方自身故障) +- 任一单个渠道不可用不应导致整体服务中断 + +### 4.3 可维护性需求 + +- 渠道配置修改无需重新部署代码,后台界面操作即可生效 +- 日志需可追溯每次请求实际路由到了哪个渠道,便于排查 + +### 4.4 兼容性需求 + +- 前端需兼容主流桌面浏览器(Chrome/Edge/Safari)及移动端浏览器 +- 网关对外接口需兼容 OpenAI API 格式,便于未来接入其他客户端(如 Claude Code、第三方 App) + +### 4.5 安全需求 + +- 所有对外 API Key 不得硬编码在配置文件中提交至版本库 +- HTTPS 全站加密传输 +- 访问密码需具备一定复杂度 + +--- + +## 5. 外部接口需求 + +### 5.1 用户接口 + +- Web 浏览器访问,响应式布局,适配桌面与移动端 + +### 5.2 外部 API 接口 + +| 渠道 | Base URL | 认证方式 | +|---|---|---| +| Gemini | generativelanguage.googleapis.com/v1beta | API Key(Header/Query) | +| NVIDIA NIM | integrate.api.nvidia.com/v1 | Bearer Token(OpenAI 兼容) | +| Groq | api.groq.com/openai/v1 | Bearer Token(OpenAI 兼容) | +| OpenRouter | openrouter.ai/api/v1 | Bearer Token(OpenAI 兼容) | +| Mistral | api.mistral.ai/v1 | Bearer Token(OpenAI 兼容) | + +--- + +## 6. 数据需求 + +| 数据项 | 存储位置 | 说明 | +|---|---|---| +| 对话历史 | LobeChat(浏览器 IndexedDB 或 PostgreSQL) | 视部署模式而定 | +| 渠道配置、API Key | One-API 数据库(MySQL) | 敏感信息,需备份加密 | +| 调用日志 | One-API 数据库 | 用于用量统计与故障排查 | + +--- + +## 7. 验收标准 + +1. 通过 Web 界面可正常发起文本对话并获得响应 +2. 上传图片后可正常获得图片理解相关的回答 +3. 手动关闭优先级最高的渠道后,系统能自动切换到下一渠道且用户侧无明显感知 +4. 后台可查看各渠道当日调用次数 +5. 全站访问强制 HTTPS,非法访问无法进入后台管理端口 + +--- + +## 8. 后续可扩展需求(非本期范围) + +- 多用户账号体系与权限隔离 +- 语音输入/输出支持 +- 与紫川的 FAM(家庭 AI 监控系统)前端集成展示 +- 接入更多免费渠道(如 Cerebras、阿里云百炼等) diff --git a/docs/02-软件设计文档-SDD.md b/docs/02-软件设计文档-SDD.md new file mode 100644 index 0000000..782f1b5 --- /dev/null +++ b/docs/02-软件设计文档-SDD.md @@ -0,0 +1,370 @@ +# 软件设计说明书(SDD) +## 自建多模态 AI 网关系统(AI Gateway System) + +| 项目 | 内容 | +|---|---| +| 文档版本 | V1.0 | +| 编写日期 | 2026-08-23 | +| 对应需求文档 | 01-软件需求文档-SRS.md V1.0 | + +--- + +## 1. 设计概述 + +### 1.1 设计目标 + +在满足 SRS 中全部功能需求与非功能需求的前提下,采用**成熟开源组件 + 容器化编排**的方式快速搭建系统,降低自研成本,优先保证 Failover 可靠性与部署可维护性。 + +### 1.2 设计原则 + +- **不重复造轮子**:网关、前端均采用成熟开源方案(One-API + LobeChat),仅做配置层工作 +- **松耦合**:前端、网关、各 AI 渠道之间通过标准 OpenAI 兼容接口通信,任一组件可替换 +- **配置驱动**:渠道增删、优先级调整通过后台界面完成,不需改代码重新部署 +- **最小暴露面**:仅前端端口对公网开放,管理端口和数据库端口仅内网可访问 + +--- + +## 2. 系统架构设计 + +### 2.1 总体架构图 + +``` +┌───────────────────────────────────────────────────────────────┐ +│ 公司内网(用户侧) │ +│ 浏览器 / 移动端浏览器 │ +└──────────────────────────┬────────────────────────────────────┘ + │ HTTPS (443) + ▼ +┌───────────────────────────────────────────────────────────────┐ +│ 美国服务器(Docker 宿主机) │ +│ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ Nginx(反向代理层) │ │ +│ │ - HTTPS 终止 / 证书管理 │ │ +│ │ - 请求转发至 LobeChat │ │ +│ │ - 流式响应透传(proxy_buffering off) │ │ +│ └───────────────────────┬─────────────────────────────────┘ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ LobeChat(前端应用层) 端口 3210 │ │ +│ │ - 对话界面渲染 │ │ +│ │ - 图片上传处理 │ │ +│ │ - Access Code 鉴权 │ │ +│ │ - 对话历史管理(IndexedDB / PostgreSQL) │ │ +│ └───────────────────────┬─────────────────────────────────┘ │ +│ │ OpenAI 兼容协议 │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ One-API(网关聚合层) 端口 3000(仅内网) │ │ +│ │ - 渠道管理 / 优先级路由 │ │ +│ │ - 模型名映射 │ │ +│ │ - 失败重试 / 自动禁用 / 冷却恢复 │ │ +│ │ - 调用日志 / 用量统计 │ │ +│ └───────────────────────┬─────────────────────────────────┘ │ +│ │ │ +│ ┌─────────────────────────────────────────────────────────┐ │ +│ │ MySQL(网关数据存储) │ │ +│ │ - 渠道配置表 / Token 表 / 调用日志表 │ │ +│ └─────────────────────────────────────────────────────────┘ │ +└──────────────────────────┬────────────────────────────────────┘ + │ 各家官方 HTTPS API + ┌───────────┬───────────┬───────────┬───────────┐ + ▼ ▼ ▼ ▼ ▼ + Gemini NVIDIA NIM Groq OpenRouter Mistral +``` + +### 2.2 分层说明 + +| 层级 | 组件 | 职责 | +|---|---|---| +| 接入层 | Nginx | HTTPS 终止、反向代理、访问入口统一 | +| 表现层 | LobeChat | 用户交互、对话渲染、多模态输入采集 | +| 网关层 | One-API | 协议转换、渠道路由、故障转移、用量统计 | +| 数据层 | MySQL | 网关配置与日志持久化 | +| 外部服务层 | 5 家 AI API | 实际推理能力提供方 | + +### 2.3 部署视图 + +单机 Docker Compose 部署,各服务以容器形式运行在同一 Docker 网络(`ai-network`)内,服务间通过容器名互相寻址,仅 Nginx 的 80/443 端口对公网暴露。 + +--- + +## 3. 模块设计 + +### 3.1 Nginx 反向代理模块 + +**职责** +- 对外仅暴露 443(HTTPS)与 80(HTTP 跳转 443) +- 将请求转发至 `lobe-chat:3210` +- 关闭代理缓冲以支持流式输出(SSE) + +**关键配置片段** +```nginx +server { + listen 443 ssl; + server_name ; + + ssl_certificate /etc/nginx/certs/fullchain.pem; + ssl_certificate_key /etc/nginx/certs/privkey.pem; + + location / { + proxy_pass http://lobe-chat:3210; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_buffering off; + proxy_cache off; + } +} + +server { + listen 80; + server_name ; + return 301 https://$host$request_uri; +} +``` + +### 3.2 LobeChat 前端模块 + +**职责** +- 渲染对话界面、处理用户输入(含图片) +- 通过 `OPENAI_PROXY_URL` 将请求发送至 One-API,而非直连任一具体厂商 +- 校验 `ACCESS_CODE` 完成访问控制 + +**关键环境变量设计** + +| 变量名 | 说明 | 示例值 | +|---|---|---| +| `OPENAI_API_KEY` | 填 One-API 生成的聚合 Token(非各厂商原始 Key) | `sk-xxxxx` | +| `OPENAI_PROXY_URL` | 指向 One-API 的 v1 路径 | `http://one-api:3000/v1` | +| `ACCESS_CODE` | 前端访问密码 | 自定义 | +| `DEFAULT_LANG` | 默认语言 | `zh-CN` | +| `OPENAI_MODEL_LIST` | 控制模型下拉菜单显示项 | 见 3.3 模型映射设计 | + +**数据存储**:本期采用 Client-Side(IndexedDB),后续如需多端同步再切换 Server-Side(PostgreSQL)。 + +### 3.3 One-API 网关模块 + +**职责** +- 维护渠道(Channel)配置表:Base URL、Key、支持模型、优先级、权重 +- 维护 Token 表:对外暴露给 LobeChat 使用的聚合密钥 +- 请求路由:按优先级+权重选择渠道,失败时按策略重试下一渠道 +- 日志记录:每次请求实际路由渠道、耗时、成功/失败状态 + +**渠道设计表** + +| 渠道名 | 类型 | Base URL | 优先级 | 支持视觉 | +|---|---|---|---|---| +| nvidia-nim | 自定义(OpenAI兼容) | `integrate.api.nvidia.com/v1` | 1 | 部分模型 | +| gemini | Google Gemini | `generativelanguage.googleapis.com/v1beta` | 1 | 是 | +| openrouter | 自定义(OpenAI兼容) | `openrouter.ai/api/v1` | 2 | 部分模型(:free) | +| groq | 自定义(OpenAI兼容) | `api.groq.com/openai/v1` | 2 | 有限 | +| mistral | 自定义(OpenAI兼容) | `api.mistral.ai/v1` | 3 | Pixtral系列 | + +> 优先级数字越小越优先;同优先级内按权重轮询分摊负载。 + +**模型映射设计** + +对外统一暴露两个聚合模型名,前端只需感知这两个名字: + +| 对外模型名 | 用途 | 关联渠道 | +|---|---|---| +| `auto-vision` | 图文混合问答 | Gemini、NVIDIA(视觉模型)、OpenRouter(视觉模型)、Mistral(Pixtral) | +| `auto-text` | 纯文本问答 | 上述全部 + Groq | + +**故障转移策略** + +1. 请求到达 One-API,按 `auto-vision` 或 `auto-text` 匹配渠道池 +2. 按优先级从高到低尝试,同优先级内按权重随机/轮询选择 +3. 若渠道返回 429(限流)/5xx(服务错误)/超时,标记该渠道本次失败,自动尝试下一渠道 +4. 连续失败次数超过阈值(如 5 次/5 分钟),该渠道进入"冷却禁用"状态,冷却期(如 10 分钟)后自动恢复参与路由 +5. 全部渠道均失败时,向前端返回明确错误提示(而非静默失败) + +### 3.4 MySQL 数据模块 + +**职责**:持久化 One-API 的渠道配置、Token、调用日志 + +**核心表设计(概念级,实际以 One-API 内建 schema 为准)** + +| 表 | 关键字段 | 说明 | +|---|---|---| +| channels | id, name, base_url, key, priority, weight, models, status | 渠道配置 | +| tokens | id, key, name, quota, status | 对外令牌 | +| logs | id, channel_id, model, status_code, latency, created_at | 调用日志 | + +--- + +## 4. 接口设计 + +### 4.1 前端 ↔ 网关接口 + +遵循 OpenAI `/v1/chat/completions` 协议,支持多模态 `content` 数组格式: + +```json +{ + "model": "auto-vision", + "messages": [ + { + "role": "user", + "content": [ + { "type": "text", "text": "这张图片里有什么?" }, + { "type": "image_url", "image_url": { "url": "data:image/jpeg;base64,..." } } + ] + } + ], + "stream": true +} +``` + +### 4.2 网关 ↔ 各 AI 渠道接口 + +| 渠道 | 协议特点 | 转换要点 | +|---|---|---| +| Gemini | 原生协议与 OpenAI 不同(`contents`/`parts`结构) | One-API 内建适配器自动转换 | +| NVIDIA NIM | OpenAI 兼容 | 直接透传,仅替换 Base URL 和 Key | +| Groq | OpenAI 兼容 | 直接透传 | +| OpenRouter | OpenAI 兼容 | 直接透传,模型名需带 `:free` 后缀 | +| Mistral | OpenAI 兼容 | 直接透传,视觉模型指定 `pixtral-*` | + +--- + +## 5. 安全设计 + +| 风险点 | 设计对策 | +|---|---| +| 后台管理端口暴露 | One-API 的 3000 端口不映射到公网,仅容器内网可访问;如需远程管理,走 SSH 隧道或 VPN | +| API Key 泄露 | 所有 Key 通过 `.env` 文件注入容器环境变量,`.env` 加入 `.gitignore`,不提交版本库 | +| 未授权访问前端 | LobeChat `ACCESS_CODE` 强制校验 | +| 传输层安全 | Nginx 强制 HTTPS,HTTP 请求 301 跳转 | +| 密钥被盗用后的止损 | One-API 后台可随时吊销/轮换 Token,不影响各渠道原始 Key | + +--- + +## 6. 部署设计 + +### 6.1 目录结构 + +``` +~/ai-gateway/ +├── docker-compose.yml +├── .env # 敏感变量,不提交版本库 +├── nginx.conf +├── certs/ # HTTPS 证书 +├── one-api-data/ # One-API 持久化数据 +└── mysql-data/ # MySQL 持久化数据 +``` + +### 6.2 Docker Compose 设计 + +```yaml +version: '3.8' + +services: + one-api: + image: justsong/one-api:latest + container_name: one-api + restart: always + ports: + - "3000:3000" # 建议后续改为仅内网映射 + volumes: + - ./one-api-data:/data + environment: + - SQL_DSN=root:${MYSQL_ROOT_PASSWORD}@tcp(mysql:3306)/oneapi + - TZ=Asia/Shanghai + depends_on: + - mysql + networks: + - ai-network + + mysql: + image: mysql:8.0 + container_name: one-api-mysql + restart: always + environment: + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} + - MYSQL_DATABASE=oneapi + volumes: + - ./mysql-data:/var/lib/mysql + networks: + - ai-network + + lobe-chat: + image: lobehub/lobe-chat:latest + container_name: lobe-chat + restart: always + ports: + - "3210:3210" + environment: + - OPENAI_API_KEY=${ONE_API_TOKEN} + - OPENAI_PROXY_URL=http://one-api:3000/v1 + - ACCESS_CODE=${LOBE_ACCESS_CODE} + - DEFAULT_LANG=zh-CN + depends_on: + - one-api + networks: + - ai-network + + nginx: + image: nginx:alpine + container_name: nginx-proxy + restart: always + ports: + - "80:80" + - "443:443" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./certs:/etc/nginx/certs:ro + depends_on: + - lobe-chat + networks: + - ai-network + +networks: + ai-network: + driver: bridge +``` + +### 6.3 部署步骤 + +1. 服务器安装 Docker + Docker Compose +2. 按 6.1 结构创建目录,放置 `docker-compose.yml`、`.env`、`nginx.conf` +3. 申请 HTTPS 证书(Let's Encrypt/certbot)放入 `certs/` +4. 执行 `docker-compose up -d` 启动全部服务 +5. 访问 `http://<服务器IP>:3000` 完成 One-API 初始化(设置管理员密码) +6. 后台按 3.3 节渠道设计表逐个添加渠道,设置优先级 +7. 创建对外 Token,写入 `.env` 的 `ONE_API_TOKEN` +8. `docker-compose restart lobe-chat` 使配置生效 +9. 访问 `https://<域名>` 验证前端可正常对话、上传图片、触发 Failover + +### 6.4 运维监控设计 + +| 监控项 | 方式 | +|---|---| +| 渠道可用性 | One-API 后台"渠道"页面查看状态与最近调用日志 | +| 免费额度消耗 | 各厂商官方控制台 + One-API 用量统计页面双重核对 | +| 容器健康状态 | `docker-compose ps` / 可选接入 Prometheus+Grafana(后续扩展) | +| 证书到期提醒 | certbot 自动续期 + 到期前邮件提醒(后续扩展) | + +--- + +## 7. 设计与需求追溯表 + +| SRS 需求编号 | 对应设计章节 | +|---|---| +| FR-1 统一对话界面 | 3.2 LobeChat 前端模块 | +| FR-2 多渠道聚合与路由 | 3.3 One-API 网关模块 | +| FR-3 多模态能力 | 3.3 模型映射设计 | +| FR-4 渠道管理 | 3.3 / 3.4 | +| FR-5 安全与访问控制 | 第 5 章 安全设计 | +| 非功能-可用性 | 3.3 故障转移策略 | +| 非功能-可维护性 | 6.4 运维监控设计 | + +--- + +## 8. 待确认事项 + +1. 是否需要 Server-Side 模式支持多端对话同步(涉及是否额外部署 PostgreSQL) +2. 后台管理端口是否需要通过 VPN/SSH 隧道访问,还是接受当前仅内网暴露的方案 +3. 是否需要接入 Prometheus/Grafana 做可视化监控(当前为后续扩展项,非本期必做) +4. 域名与证书由紫川自行准备,还是需要方案建议