Files
NexusAI/docs/02-软件设计文档-SDD.md

371 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 软件设计说明书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 反向代理模块
**职责**
- 对外仅暴露 443HTTPS与 80HTTP 跳转 443
- 将请求转发至 `lobe-chat:3210`
- 关闭代理缓冲以支持流式输出SSE
**关键配置片段**
```nginx
server {
listen 443 ssl;
server_name <domain-or-ip>;
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 <domain-or-ip>;
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-SideIndexedDB后续如需多端同步再切换 Server-SidePostgreSQL
### 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 强制 HTTPSHTTP 请求 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. 域名与证书由紫川自行准备,还是需要方案建议