docs(项目启动): SRS/SDD 文档入库 + README/PROGRESS + 仓库初始化

This commit is contained in:
ericwyuan
2026-08-23 08:24:56 +08:00
commit 557ec170da
5 changed files with 843 additions and 0 deletions

View File

@@ -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 反向代理模块
**职责**
- 对外仅暴露 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. 域名与证书由紫川自行准备,还是需要方案建议