docs: initialize AIwelink project
This commit is contained in:
@@ -0,0 +1,403 @@
|
||||
# AIwelink 技术实现规则
|
||||
|
||||
本文补充 [AIwelink 技术方案](./technology-stack.md)。
|
||||
文档说明请求怎样进入系统、代码怎样分层、数据怎样保存。
|
||||
文档也列出第一阶段的部署和测试要求。
|
||||
|
||||
## 1. Web 和 API 使用一个域名
|
||||
|
||||
### 1.1 请求路径
|
||||
|
||||
第一阶段对外使用一个公网域名:
|
||||
|
||||
```text
|
||||
https://aiwelink.com/ -> Next.js Web
|
||||
https://aiwelink.com/api/v1/... -> REST API
|
||||
```
|
||||
|
||||
入口代理(例如 Nginx)按路径转发:
|
||||
|
||||
```text
|
||||
客户端
|
||||
|
|
||||
v
|
||||
Nginx
|
||||
|-- /api/v1/* -> api:3000
|
||||
|-- /* -> web:3000
|
||||
```
|
||||
|
||||
NestJS 设置全局前缀 `/api/v1`。代理和应用要统一路径处理方式,避免请求出现两次 `/api/v1`。
|
||||
|
||||
### 1.2 这样安排的好处
|
||||
|
||||
- 浏览器通过同域名直接访问 API,开发和生产使用相同请求路径;
|
||||
- HttpOnly Cookie 的会话处理更简单;
|
||||
- 分享页、公开机会页和登录后的工作台使用同一域名;
|
||||
- 本地、测试和生产环境可以使用相同的请求路径;
|
||||
- 将来改用 `api.aiwelink.com` 时,资源路径仍可以保持稳定。
|
||||
|
||||
### 1.3 入口代理要配置的规则
|
||||
|
||||
- Web 和 API 使用各自的超时、缓存和安全策略;
|
||||
- Next.js 负责页面,业务规则统一放在 API;
|
||||
- Next.js 服务端调用 API 时优先走 Docker 内网;
|
||||
- 未来接入 App、第三方赛事系统或开放平台时,再单独设计 CORS、Token 和 API 子域名;
|
||||
- 未来使用 SSE 时,代理关闭响应缓冲,并设置足够长的连接超时。
|
||||
|
||||
## 2. NestJS 和 Fastify
|
||||
|
||||
NestJS 提供模块、依赖注入、Guard、拦截器、异常过滤器和 OpenAPI 集成。
|
||||
Fastify Adapter 负责底层 HTTP 服务。
|
||||
这个组合适合授权、项目、邀请、积分和订单等规则较多的业务。
|
||||
|
||||
代码按以下规则编写:
|
||||
|
||||
- 使用兼容 Fastify 的 NestJS 插件;
|
||||
- Controller 只接收请求、调用应用服务并组织响应;
|
||||
- 复杂业务规则放在应用服务;
|
||||
- Guard 和资源归属检查共同完成权限校验;
|
||||
- 所有输入使用 DTO 校验;
|
||||
- API 响应使用专门的响应类型,数据库实体只在数据访问层使用;
|
||||
- 错误格式统一,并带 `requestId`;
|
||||
- API 路径使用 `/api/v1`,JSON 字段使用 `camelCase`,URL 使用小写短横线。
|
||||
|
||||
推荐的目录如下:
|
||||
|
||||
```text
|
||||
src/
|
||||
modules/
|
||||
identity/
|
||||
users/
|
||||
profiles/
|
||||
consents/
|
||||
projects/
|
||||
opportunities/
|
||||
invitations/
|
||||
points/
|
||||
commerce/
|
||||
recommendations/
|
||||
operations/
|
||||
common/
|
||||
guards/
|
||||
filters/
|
||||
interceptors/
|
||||
decorators/
|
||||
infrastructure/
|
||||
database/
|
||||
storage/
|
||||
cache/
|
||||
```
|
||||
|
||||
## 3. REST API 规则
|
||||
|
||||
### 3.1 用资源设计路径
|
||||
|
||||
资源名使用名词和复数形式:
|
||||
|
||||
```text
|
||||
GET /api/v1/projects
|
||||
GET /api/v1/projects/{projectId}
|
||||
POST /api/v1/projects
|
||||
PATCH /api/v1/projects/{projectId}
|
||||
DELETE /api/v1/projects/{projectId}
|
||||
```
|
||||
|
||||
明确的从属关系使用嵌套资源:
|
||||
|
||||
```text
|
||||
GET /api/v1/projects/{projectId}/members
|
||||
POST /api/v1/projects/{projectId}/applications
|
||||
```
|
||||
|
||||
生成报告等耗时动作建模为报告资源或任务资源。
|
||||
客户端先创建任务,再查询任务进度和结果。
|
||||
|
||||
### 3.2 HTTP 状态码
|
||||
|
||||
| 状态码 | 使用场景 |
|
||||
| --- | --- |
|
||||
| `200` | 读取或更新成功 |
|
||||
| `201` | 创建资源成功 |
|
||||
| `202` | 异步任务已接受 |
|
||||
| `204` | 成功且没有响应内容 |
|
||||
| `400` | 请求格式错误 |
|
||||
| `401` | 未登录或会话失效 |
|
||||
| `403` | 当前用户没有权限 |
|
||||
| `404` | 资源不存在 |
|
||||
| `409` | 当前资源状态不允许这次操作 |
|
||||
| `422` | 字段校验失败 |
|
||||
| `429` | 请求频率超过限制 |
|
||||
| `500` | 服务端出现未处理异常 |
|
||||
|
||||
### 3.3 响应和错误格式
|
||||
|
||||
成功响应统一使用 `data` 字段。列表响应在 `meta` 中返回游标和分页信息。
|
||||
|
||||
错误响应采用 `application/problem+json`。
|
||||
响应至少包含 `type`、`title`、`status`、`code`、`detail` 和 `requestId`。
|
||||
|
||||
### 3.4 可重复提交的写操作
|
||||
|
||||
订单创建、积分发放、邀请接受、付费权益创建和报告任务等操作支持 `Idempotency-Key`。
|
||||
服务端保存请求结果,客户端重试时返回同一结果。
|
||||
|
||||
权限由 API 服务端统一检查,前端按钮只负责展示状态。
|
||||
|
||||
## 4. Identity 身份模块
|
||||
|
||||
### 4.1 职责
|
||||
|
||||
`Identity` 负责用户身份和会话。
|
||||
个人资料、能力画像、项目经历和测评结果由其他模块管理。
|
||||
|
||||
建议的核心表:
|
||||
|
||||
```text
|
||||
users
|
||||
user_identities
|
||||
sessions
|
||||
email_verifications
|
||||
login_events
|
||||
```
|
||||
|
||||
### 4.2 登录方式
|
||||
|
||||
- 微信扫码或授权登录作为主入口;
|
||||
- 邮箱用于绑定、验证、通知和账号恢复;
|
||||
- 登录方式和用户主体分开保存,同一用户可以绑定多种登录方式;
|
||||
- 会话使用 HttpOnly、Secure Cookie;
|
||||
- 服务端保存会话状态和撤销记录;
|
||||
- 长期 Token 放在服务端会话中管理。
|
||||
|
||||
未来可以增加手机号、学校身份验证或其他第三方身份,统一挂在 `users` 用户主体下。
|
||||
|
||||
## 5. Drizzle 和原生 SQL
|
||||
|
||||
### 5.1 选择规则
|
||||
|
||||
| 场景 | 访问方式 |
|
||||
| --- | --- |
|
||||
| 普通增删改查 | Drizzle |
|
||||
| 普通事务 | Drizzle transaction |
|
||||
| JSONB 复杂筛选 | Drizzle + SQL |
|
||||
| `pgvector` 相似度查询 | SQL Repository |
|
||||
| 推荐排序 | SQL Repository |
|
||||
| 全文搜索 | SQL Repository |
|
||||
| 报表和聚合 | SQL Repository |
|
||||
|
||||
原生 SQL 使用参数绑定。查询条件和排序字段经过代码校验后再拼接。
|
||||
|
||||
### 5.2 数据访问顺序
|
||||
|
||||
```text
|
||||
Controller
|
||||
↓
|
||||
Application Service
|
||||
↓
|
||||
Repository Interface
|
||||
↓
|
||||
Drizzle Repository 或 SQL Repository
|
||||
↓
|
||||
PostgreSQL
|
||||
```
|
||||
|
||||
Controller 通过 Repository 读取数据,这样业务规则和具体数据库工具可以分别测试和替换。
|
||||
|
||||
### 5.3 数据库迁移
|
||||
|
||||
- 数据库结构用版本化迁移保存;
|
||||
- 普通表由 Drizzle Schema 和迁移工具维护;
|
||||
- `pgvector`、特殊索引、函数和分区可以使用手写迁移 SQL;
|
||||
- 生产环境的每次表结构变化都要留下迁移记录。
|
||||
|
||||
## 6. PostgreSQL、JSONB 和 pgvector
|
||||
|
||||
### 6.1 PostgreSQL 保存什么
|
||||
|
||||
PostgreSQL 保存需要事务一致性的业务数据。
|
||||
这些数据包括用户、身份、授权、项目、成员、申请、积分、订单、报告信息和推荐记录。
|
||||
|
||||
Redis 负责速度和临时状态。最终业务状态仍以 PostgreSQL 为准。
|
||||
|
||||
### 6.2 JSONB 适合保存什么
|
||||
|
||||
JSONB 适合保存:
|
||||
|
||||
- 灵活的用户偏好;
|
||||
- AI 输出的结构化报告内容;
|
||||
- 带版本号的推荐特征快照;
|
||||
- 运营可以调整的配置字段。
|
||||
|
||||
用户身份、权限、订单金额和状态,使用结构化字段。
|
||||
积分流水和项目成员关系,也使用结构化字段。
|
||||
数据库约束负责保证这些关系的一致性。
|
||||
|
||||
### 6.3 pgvector 怎样使用
|
||||
|
||||
`pgvector` 用于项目、课程、学科和公开内容的语义检索。每条向量记录至少保存:
|
||||
|
||||
- 来源资源 ID;
|
||||
- Embedding 模型名称;
|
||||
- 模型版本;
|
||||
- 向量维度;
|
||||
- 生成时间;
|
||||
- 来源内容版本。
|
||||
|
||||
测评原始回答等敏感数据的向量化需要单独评估,并保留可解释的推荐理由。
|
||||
|
||||
## 7. 数据表和生命周期
|
||||
|
||||
### 7.1 业务分层
|
||||
|
||||
建议按下面的业务层组织表:
|
||||
|
||||
```text
|
||||
身份层:users、user_identities、sessions
|
||||
资料层:profile_basics、profile_preferences、public_profiles
|
||||
认知层:assessment_sessions、assessment_answers、insight_snapshots
|
||||
证据层:insight_evidence、project_reviews、behavior_events
|
||||
授权层:consent_grants、consent_audits
|
||||
项目层:opportunities、projects、project_members、applications
|
||||
增长层:referral_events、point_ledger
|
||||
审计层:audit_logs
|
||||
```
|
||||
|
||||
### 7.2 大表处理
|
||||
|
||||
现在按业务功能拆表,方便权限、索引和数据保存周期管理。
|
||||
大型追加型表按以下顺序处理:
|
||||
|
||||
1. 建立合理索引;
|
||||
2. 优化时间范围查询;
|
||||
3. 归档冷数据;
|
||||
4. 为特殊查询建立单独的 SQL Repository;
|
||||
5. 数据量持续增长后,再评估 PostgreSQL 分区。
|
||||
|
||||
## 8. Redis 的用途
|
||||
|
||||
Redis 用于:
|
||||
|
||||
- 热点数据缓存;
|
||||
- 请求限流;
|
||||
- 短期验证码和临时状态;
|
||||
- 异步任务队列;
|
||||
- 幂等键状态;
|
||||
- 短期排行榜。
|
||||
|
||||
最终积分余额、订单状态、授权记录和用户画像原始数据,统一从 PostgreSQL 读取。
|
||||
项目成员关系也由 PostgreSQL 保存。
|
||||
|
||||
## 9. 阿里云 OSS 文件流程
|
||||
|
||||
```text
|
||||
API 创建临时凭证
|
||||
↓
|
||||
浏览器直接上传 OSS
|
||||
↓
|
||||
上传完成后通知 API
|
||||
↓
|
||||
PostgreSQL 写入文件信息
|
||||
↓
|
||||
按需解析、审核或建立索引
|
||||
```
|
||||
|
||||
数据库保存的文件信息包括:
|
||||
|
||||
```text
|
||||
fileId
|
||||
ownerId
|
||||
objectKey
|
||||
mimeType
|
||||
size
|
||||
hash
|
||||
visibility
|
||||
createdAt
|
||||
```
|
||||
|
||||
私有文件通过短期签名 URL 访问。上传流程检查文件类型、大小、哈希和归属关系。
|
||||
|
||||
## 10. ECS 和 Docker Compose
|
||||
|
||||
### 10.1 第一阶段服务
|
||||
|
||||
```text
|
||||
nginx
|
||||
web
|
||||
api
|
||||
worker(AI 助手方案待决定)
|
||||
postgres
|
||||
redis
|
||||
```
|
||||
|
||||
应用容器配置健康检查和自动重启。镜像推送到镜像仓库,生产环境使用固定版本标签。
|
||||
|
||||
### 10.2 为未来 Kubernetes 做准备
|
||||
|
||||
现在就按以下方式运行:
|
||||
|
||||
- Web、API 和 Worker 分开成容器;
|
||||
- 应用服务保持无状态;
|
||||
- 配置通过环境变量或 Secret 注入;
|
||||
- 文件放在 OSS;
|
||||
- 数据库迁移独立执行;
|
||||
- 服务之间通过内部 DNS 或配置发现通信。
|
||||
|
||||
### 10.3 数据服务的运维要求
|
||||
|
||||
如果 PostgreSQL 和 Redis 运行在 ECS 上,至少准备独立数据盘,并安排:
|
||||
|
||||
- 自动备份;
|
||||
- 备份保留周期;
|
||||
- 恢复演练;
|
||||
- 磁盘空间监控;
|
||||
- 数据库升级和回滚方案。
|
||||
|
||||
## 11. Uptime Kuma 和测试
|
||||
|
||||
### 11.1 可用性检查
|
||||
|
||||
建议提供两个健康检查接口:
|
||||
|
||||
```text
|
||||
GET /api/v1/health/live
|
||||
GET /api/v1/health/ready
|
||||
```
|
||||
|
||||
`live` 只检查进程是否存活。`ready` 检查 PostgreSQL、Redis 和必要配置是否可用。
|
||||
|
||||
Uptime Kuma 监控首页、两个健康接口、TCP 端口和 HTTPS 证书到期时间。
|
||||
|
||||
### 11.2 测试范围
|
||||
|
||||
第一阶段至少安排:
|
||||
|
||||
- TypeScript 类型检查;
|
||||
- Lint;
|
||||
- API 单元测试和集成测试;
|
||||
- 关键流程端到端测试;
|
||||
- 发布前数据库迁移检查。
|
||||
|
||||
核心流程按下面的顺序覆盖:
|
||||
|
||||
```text
|
||||
微信登录
|
||||
→ 绑定邮箱
|
||||
→ 创建个人资料
|
||||
→ 创建项目
|
||||
→ 发送邀请
|
||||
→ 授权共享
|
||||
→ 提交项目申请
|
||||
→ 记录积分流水
|
||||
```
|
||||
|
||||
## 12. 仍需决定的技术事项
|
||||
|
||||
以下内容等产品流程和数据量更清楚后再决定:
|
||||
|
||||
- AI 助手使用的模型供应商和模型路由;
|
||||
- AI 助手的对话编排框架;
|
||||
- 长报告和复杂任务使用哪种队列;
|
||||
- 推荐系统是否拆成独立服务;
|
||||
- 是否引入专用搜索引擎;
|
||||
- Kubernetes 的发行版和部署方式;
|
||||
- 完整的日志、指标和链路追踪方案。
|
||||
@@ -0,0 +1,151 @@
|
||||
# AIwelink 技术方案
|
||||
|
||||
本文说明第一阶段的 Web、业务 API、数据存储、文件存储、部署和基础监控方案。
|
||||
|
||||
AI 助手的模型供应商、对话编排方式和后台任务方案列为后续技术决定。
|
||||
本文先约定接口和职责,具体实现等业务流程确定后再选。
|
||||
|
||||
## 1. 总体方案
|
||||
|
||||
第一阶段使用模块清楚、可以逐步扩展的架构:
|
||||
|
||||
- Web 页面和业务 API 分开部署;
|
||||
- Web 和 API 通过一个域名对外提供服务,API 统一使用 `/api/v1` 路径;
|
||||
- PostgreSQL 保存需要事务保证的数据,并使用 `JSONB`、全文搜索和 `pgvector`;
|
||||
- Redis 处理缓存、限流和异步任务;
|
||||
- 阿里云 OSS 保存简历、作品、报告和项目附件;
|
||||
- Web、API 和任务程序都运行在 Docker 容器中;
|
||||
- 第一阶段使用自有 ECS 和 Docker Compose,规模增长后再迁移到 Kubernetes;
|
||||
- 用户身份、个人资料、项目行为和授权记录按敏感程度分开保存;
|
||||
- 初期用 Uptime Kuma 检查网站和 API 是否可访问。
|
||||
|
||||
## 2. 已确定的技术选型
|
||||
|
||||
| 领域 | 当前选择 |
|
||||
| --- | --- |
|
||||
| Web 前端 | Next.js + React + TypeScript |
|
||||
| 业务 API | NestJS + Fastify Adapter |
|
||||
| API 形式 | REST API,路径前缀 `/api/v1` |
|
||||
| 数据访问 | Drizzle ORM;复杂查询使用参数化原生 SQL |
|
||||
| 主数据库 | PostgreSQL |
|
||||
| 向量检索 | PostgreSQL 的 `pgvector` 扩展 |
|
||||
| 缓存和任务队列 | Redis |
|
||||
| 文件存储 | 阿里云 OSS |
|
||||
| 运行环境 | Docker |
|
||||
| 第一阶段部署 | 自有 ECS + Docker Compose |
|
||||
| 后续部署 | Kubernetes |
|
||||
| 身份系统 | API 内部的 `Identity` 模块 |
|
||||
| 初期监控 | Uptime Kuma |
|
||||
|
||||
## 3. 服务怎样连接
|
||||
|
||||
```text
|
||||
浏览器
|
||||
|
|
||||
v
|
||||
Nginx 或其他入口代理
|
||||
|-- / -> Next.js Web 容器
|
||||
|-- /api/v1/* -> NestJS + Fastify API 容器
|
||||
|
|
||||
Drizzle / SQL Repository
|
||||
|
|
||||
PostgreSQL + pgvector
|
||||
|
|
||||
Redis
|
||||
|
|
||||
阿里云 OSS
|
||||
```
|
||||
|
||||
Next.js 负责页面和交互。
|
||||
NestJS 负责业务规则和 REST API。
|
||||
浏览器通过同一个域名下的 `/api/v1/...` 路径调用 API。
|
||||
|
||||
## 4. API 内部模块
|
||||
|
||||
API 按业务模块组织,第一阶段至少包含:
|
||||
|
||||
- `Identity`:微信登录、邮箱绑定、会话和登录记录;
|
||||
- `Users`:基础资料、学校、专业和年级;
|
||||
- `Profiles`:个人画像、公开画像和画像版本;
|
||||
- `Consents`:画像共享授权、撤销和授权记录;
|
||||
- `Projects`:竞赛、项目、队伍、成员和申请;
|
||||
- `Invitations`:邀请链接、接受记录和邀请关系;
|
||||
- `Points`:积分流水、任务和兑换权益;
|
||||
- `Commerce`:课程、API 权益、订单和退款记录;
|
||||
- `Recommendations`:推荐内容、推荐理由和用户反馈;
|
||||
- `Operations`:内容审核、举报、活动和运营配置。
|
||||
|
||||
AI 助手先通过独立接口接入。
|
||||
模型、任务队列和报告生成流程确定后,再决定服务是否单独部署。
|
||||
|
||||
## 5. 数据怎样分层
|
||||
|
||||
数据按业务含义和敏感程度安排存储位置:
|
||||
|
||||
- 身份信息和联系方式;
|
||||
- 原始测评回答;
|
||||
- AI 生成的个人画像;
|
||||
- 真实项目行为和合作证据;
|
||||
- 用户主动公开的画像;
|
||||
- 授权记录和审计记录。
|
||||
|
||||
大表先使用合理的表结构、索引和归档策略。
|
||||
数据量和查询方式出现明确需求后,再评估 PostgreSQL 分区或其他存储方式。
|
||||
|
||||
## 6. 文件和媒体
|
||||
|
||||
简历、作品、报告和项目附件保存到阿里云 OSS,流程如下:
|
||||
|
||||
1. API 创建临时上传凭证;
|
||||
2. 浏览器直接上传 OSS;
|
||||
3. API 接收上传完成通知;
|
||||
4. PostgreSQL 保存文件信息和权限关系;
|
||||
5. 后台任务按需解析、审核或建立搜索索引。
|
||||
|
||||
应用服务器只处理上传授权和文件信息,不承担大文件的长期保存。
|
||||
|
||||
## 7. 部署和后续扩展
|
||||
|
||||
第一阶段用 Docker Compose 管理这些服务:
|
||||
|
||||
- Web 容器;
|
||||
- API 容器;
|
||||
- Worker 容器,用于异步任务;
|
||||
- PostgreSQL;
|
||||
- Redis。
|
||||
|
||||
生产环境逐步把应用容器和 PostgreSQL、Redis 分开部署,或改用托管服务。
|
||||
同时设置备份、恢复和升级流程。
|
||||
|
||||
迁移 Kubernetes 时,应用服务保持无状态。
|
||||
配置通过环境变量或 Secret 注入,文件继续放在 OSS,数据库迁移单独执行。
|
||||
|
||||
## 8. 监控和测试
|
||||
|
||||
Uptime Kuma 负责基础可用性检查:
|
||||
|
||||
- 首页是否能打开;
|
||||
- `/api/v1/health/live` 是否返回进程存活;
|
||||
- `/api/v1/health/ready` 是否确认 PostgreSQL、Redis 和必要配置可用;
|
||||
- HTTPS 证书和端口是否正常。
|
||||
|
||||
测试单独建设,至少覆盖 TypeScript 类型检查、Lint、API 测试和关键流程端到端测试。
|
||||
发布前还要检查数据库迁移。
|
||||
核心流程包括登录、授权、邀请、项目申请和积分流水。
|
||||
|
||||
## 9. 第一阶段的工作重点
|
||||
|
||||
先完成用户登录、个人资料、自我认知、机会浏览、邀请共享、项目申请和积分记录。
|
||||
再根据真实使用数据决定以下能力的时间:
|
||||
|
||||
- 微服务拆分;
|
||||
- Kubernetes 生产部署;
|
||||
- 独立向量数据库;
|
||||
- Elasticsearch 或 OpenSearch;
|
||||
- ClickHouse;
|
||||
- MongoDB;
|
||||
- 复杂机器学习推荐服务;
|
||||
- 专门的 AI 助手编排框架。
|
||||
|
||||
这些能力都保留后续空间。
|
||||
当前开发围绕用户找到机会、组成队伍并完成项目展开。
|
||||
Reference in New Issue
Block a user