diff --git a/README.md b/README.md index 14de2d4..bb37992 100644 --- a/README.md +++ b/README.md @@ -1,208 +1,267 @@ -# AI Study Product API +# 知习 API Server -AI 学习产品的后端 API 服务(v0.1),基于 NestJS + TypeScript 构建。 +AI-first 系统化学习平台后端,NestJS 11 + TypeScript。 -## 功能模块 +## 架构 -| 模块 | 说明 | 状态 | -|------|------|------| -| health | 健康检查 | ✅ | -| auth | 用户认证(dev-login / Apple / 刷新 / 登出) | ✅ | -| users | 用户管理 | ✅ | -| knowledge-base | 知识库 CRUD → Prisma | ✅ | -| knowledge-items | 知识点 CRUD → Prisma | ✅ | -| ai | AI 三层架构(Provider → Gateway → Workflow)15 文件 | ✅ | -| ai-analysis | AI 分析结果查询 → Prisma | ✅ | -| active-recall | 主动回忆(提交答案触发分析)→ Prisma | ✅ | -| learning-session | 学习会话 → Prisma | ✅ | -| review | 间隔重复复习 → Prisma | ✅ | -| focus-items | 待巩固项 → Prisma | ✅ | -| learning-activity | 学习活跃统计 → Prisma | ✅ | -| document-import | 文档导入 → Prisma | ✅ | -| notifications | 通知 → Prisma | ✅ | -| feedback | 用户反馈 → Prisma | ✅ | -| waitlist | 等待名单 → Prisma | ✅ | +``` +Nginx (:80/:443) + └── /api/* → NestJS API (:3000) + +┌─────────────────────────────────────┐ +│ API 进程 (main.ts) │ +│ - REST API (50+ 业务模块) │ +│ - Swagger (/api-docs) │ +│ - Admin API (/admin-api/*) │ +│ - Internal API (/internal/*) │ +└─────────────────────────────────────┘ + +┌─────────────────────────────────────┐ +│ Worker 进程 (worker.main.ts) │ +│ - BullMQ 队列消费 │ +│ - AI 分析 / 文档导入 / 通知 │ +└─────────────────────────────────────┘ + +┌──────────┬──────────┬──────────┬──────────┐ +│ MySQL 8 │ Redis 7 │ Qdrant │ COS │ +└──────────┴──────────┴──────────┴──────────┘ +``` + +## 技术栈 + +| 类别 | 技术 | +|------|------| +| 框架 | NestJS 11 | +| 语言 | TypeScript | +| ORM | Prisma 5 | +| 数据库 | MySQL 8.0 | +| 缓存/队列 | Redis 7 + BullMQ | +| 向量库 | Qdrant | +| 对象存储 | 腾讯云 COS(支持 local 模式) | +| AI | DeepSeek API + SiliconFlow Embedding | +| 认证 | JWT (用户) + JWT (管理员) + Internal API Key + httpOnly Cookie (Admin) | +| 文档 | Swagger (开发默认开启,生产 Basic Auth) | ## 快速开始 ```bash -# 安装依赖 +# 1. 安装依赖 npm install -# 开发模式 -npm run start:dev +# 2. 启动基础设施(OrbStack Docker) +docker compose -f docker-compose.local.yml up -d -# 生产模式 -npm run build && npm run start:prod +# 3. 初始化数据库 +npx prisma migrate deploy + +# 4. 配置环境变量 +cp .env.example .env.local +# 编辑 .env.local + +# 5. 启动 API(开发模式) +npm run start:dev # → http://localhost:3000 + +# 6. 启动 Worker(另一个终端) +npm run start:worker ``` -## 接口文档 +### 基础设施(docker-compose.local.yml) -### 本地开发环境 - -启动服务后,访问: - -- **Swagger UI**: http://localhost:3000/api-docs -- **OpenAPI JSON**: http://localhost:3000/api-docs-json - -本地开发环境默认启用 Swagger,无需认证。 - -### 服务器内测环境 - -生产环境启用 Swagger 后,Swagger UI 和 OpenAPI JSON 均受 **Basic Auth** 保护: - -- **Swagger UI**: https://api.longde.cloud/api-docs -- **OpenAPI JSON**: https://api.longde.cloud/api-docs-json - -Apifox 导入时在 URL 中带上认证: -`https://admin:your_password@api.longde.cloud/api-docs-json` - -配置环境变量: - -```env -NODE_ENV=production -ENABLE_SWAGGER=true -SWAGGER_USER=your_admin_username -SWAGGER_PASSWORD=your_secure_password -``` - -如需临时开启内网访问,配置同上并设置强密码。 +| 服务 | 端口 | 说明 | +|------|------|------| +| MySQL 8.0 | 127.0.0.1:3306 | `zhixi_prod` 数据库 | +| Redis 7 | 127.0.0.1:6379 | BullMQ + 缓存 | +| Qdrant | 127.0.0.1:6333 | 向量检索 | ## 环境变量 -复制 `.env.example` 为 `.env` 并配置: +| 变量 | 必需 | 说明 | +|------|------|------| +| `DATABASE_URL` | ✅ | MySQL 连接字符串 | +| `REDIS_HOST` | ✅ | Redis 地址 | +| `REDIS_PORT` | ✅ | Redis 端口 | +| `REDIS_PASSWORD` | 否 | Redis 密码 | +| `JWT_SECRET` | ✅ | 用户 JWT 密钥 | +| `ADMIN_JWT_ACCESS_SECRET` | ✅ | 管理员 JWT 密钥 | +| `ADMIN_JWT_REFRESH_SECRET` | 否 | 管理员刷新密钥 | +| `INTERNAL_API_KEY` | ✅ | Worker 内部调用密钥 | +| `CREDENTIAL_ENCRYPTION_KEY` | ✅ | 凭据加密密钥 | +| `DEEPSEEK_API_KEY` | 否 | DeepSeek API Key | +| `SILICONFLOW_API_KEY` | 否 | SiliconFlow Embedding Key | +| `QDRANT_URL` | 否 | Qdrant 地址 | +| `STORAGE_DRIVER` | 否 | `cos` 或 `local`(默认) | +| `COS_SECRET_ID` | 否 | 腾讯云 COS SecretId | +| `COS_SECRET_KEY` | 否 | 腾讯云 COS SecretKey | +| `COS_BUCKET` | 否 | COS Bucket 名称 | +| `COS_REGION` | 否 | COS 区域 | +| `ENABLE_SWAGGER` | 否 | 生产环境启用 Swagger | +| `SWAGGER_USER` | 否 | Swagger Basic Auth 用户名 | +| `SWAGGER_PASSWORD` | 否 | Swagger Basic Auth 密码 | -```env -PORT=3000 -DATABASE_URL="mysql://user:password@localhost:3306/ai_study" -REDIS_HOST=localhost -REDIS_PORT=6379 -AI_PROVIDER=mock -AI_API_KEY= -AI_BASE_URL= -JWT_SECRET=change_me_in_production +完整配置参考 `.env.example`。 -NODE_ENV=development -ENABLE_SWAGGER=true -SWAGGER_USER=admin -SWAGGER_PASSWORD=change_me -``` +## 模块清单(50+) -| 变量 | 说明 | 默认值 | -|------|------|--------| -| PORT | 服务端口 | 3000 | -| NODE_ENV | 运行环境 | development | -| ENABLE_SWAGGER | 是否启用 Swagger | true (开发) / false (生产) | -| SWAGGER_USER | Swagger 用户名 | admin | -| SWAGGER_PASSWORD | Swagger 密码 | change_me | +### 用户端 API -## API 端点概览 +| 模块 | 路由前缀 | 说明 | +|------|---------|------| +| auth | `/api/auth` | 用户认证(登录/注册/刷新/登出/Apple) | +| users | `/api/users` | 用户管理 | +| knowledge-base | `/api/knowledge-bases` | 知识库 CRUD | +| ai | `/api/ai` | AI 对话/分析 | +| ai-analysis | `/api/ai-analysis` | AI 分析结果 | +| ai-job | — | AI 作业调度(Worker) | +| ai-runtime | — | AI 运行时(Worker) | +| active-recall | `/api/active-recall` | 主动回忆 | +| review | `/api/review` | 间隔重复复习 | +| quiz | `/api/quiz` | 测验 | +| focus-items | `/api/focus-items` | 待巩固项 | +| learning-session | `/api/learning-session` | 学习会话 | +| learning-activity | `/api/learning-activity` | 学习活跃统计 | +| document-import | `/api/document-import` | 文档导入 | +| rag-chat | `/api/rag/chat` | RAG 知识库对话 | +| notifications | `/api/notifications` | 通知 | +| feedback | `/api/feedback` | 用户反馈 | +| waitlist | `/api/waitlist` | 等待名单 | +| membership | `/api/membership` | 会员/订阅 | +| files | `/api/files` | 文件管理 | +| workspace | `/api/workspace` | 工作区 | +| content-safety | — | 内容安全检测 | +| secrets | — | 密钥管理 | -### 健康检查 -- `GET /` - 服务健康检查 +### 管理端 API -### 认证 -- `POST /auth/login` - 用户登录 -- `POST /auth/register` - 用户注册 -- `POST /auth/refresh` - 刷新 Token -- `POST /auth/logout` - 退出登录 +| 模块 | 路由前缀 | 说明 | +|------|---------|------| +| admin-auth | `/admin-api/auth` | 管理员认证(登录/刷新/登出) | +| admin-users | `/admin-api/admin-users` | 管理员 CRUD | +| dashboard | `/admin-api/dashboard` | 数据看板 | +| audit | `/admin-api/audit` | 审计日志 | +| billing | `/admin-api/billing` | API 用量/成本 | +| config | `/admin-api/config` | 系统配置 | +| servers | `/admin-api/servers` | 服务器监控 | +| ai-gateway | `/admin-api/ai-gateway` | AI 网关路由 | +| compliance | `/admin-api/compliance` | 合规安全 | +| release | `/admin-api/release` | 发布决策 | +| learning | `/admin-api/learning` | 学习数据总览 | +| imports | `/admin-api/imports` | 文档导入监控 | +| notifications-admin | `/admin-api/notifications` | 通知管理 | +| backup | `/admin-api/backup` | 备份清理 | +| vector | `/admin-api/vector` | 向量检索 | +| metrics | `/admin-api/metrics` | 接口监控 | +| throttle | `/admin-api/throttle` | 限流管理 | -### 用户 -- `POST /users` - 创建用户 -- `GET /users/:id` - 获取用户信息 -- `GET /users/:id/profile` - 获取用户详情(含统计数据) -- `PATCH /users/:id` - 更新用户信息 -- `GET /users` - 用户列表 +### 内部 API(Worker 调用) -### 知识库 -- `GET /knowledge/categories` - 获取分类 -- `GET /knowledge/articles` - 获取文章列表 -- `GET /knowledge/articles/:id` - 获取文章详情 - -### 学习 -- `GET /learning/paths` - 获取所有学习路径 -- `GET /learning/paths/:id` - 获取学习路径详情 -- `GET /learning/paths/:id/courses` - 获取课程列表 -- `GET /learning/courses/:id` - 获取课程详情 -- `GET /learning/lessons/:id` - 获取课时详情 -- `GET /learning/records?userId=` - 获取用户学习记录 -- `PATCH /learning/progress` - 更新学习进度 - -### AI -- `POST /ai/analyze-recall` - AI 主动回忆分析 -- `GET /ai/models` - 查看模型分流配置 -- `POST /ai-analysis` - 提交 AI 分析 -- `GET /ai-analysis/:id` - 获取分析结果 - -### 主动回忆 -- `GET /active-recalls` - 获取问题列表 -- `POST /active-recalls/:id/submit` - 提交回答(自动触发 AI 分析) - -### 复习 -- `GET /learning/review?userId=` - 获取复习任务 -- `POST /learning/review` - 创建复习任务 - -### 反馈 -- `POST /feedback` - 提交反馈 -- `GET /feedback` - 获取反馈列表 -- `GET /feedback/stats` - 反馈统计 -- `PATCH /feedback/:id/status` - 更新反馈状态 - -### 等待名单 -- `POST /waitlist` - 加入等待名单 -- `GET /waitlist` - 获取所有报名 -- `GET /waitlist/stats` - 报名统计 - -## 技术栈 - -- NestJS 11.x -- TypeScript -- class-validator / class-transformer -- @nestjs/swagger +| 路由 | 说明 | +|------|------| +| `POST /internal/rag/jobs/next` | 获取下一个导入任务 | +| `POST /internal/rag/jobs/:id/claim` | 认领任务 | +| `POST /internal/rag/jobs/:id/heartbeat` | 心跳 | +| `POST /internal/rag/jobs/:id/status` | 更新状态 | +| `POST /internal/rag/chunks` | 批量保存 Chunk | +| `POST /internal/rag/candidates` | 保存候选知识点 | ## 目录结构 ``` src/ -├── main.ts # 入口 -├── app.module.ts # 根模块 -├── config/ # 配置(app / jwt / ai / database / redis) -├── common/ # 公共(guard / decorator / filter / pipe) -├── infrastructure/ # 基础设施(Prisma / Redis / Storage / Logger / Queue) -│ └── ai/ # ❌ 已删除,迁至 modules/ai/ -└── modules/ - ├── auth/ # 认证模块(dev-login / Apple / refresh / logout) - ├── users/ # 用户模块 - ├── knowledge-base/ # 知识库模块 - ├── knowledge-items/ # 知识点模块 - ├── active-recall/ # 主动回忆模块(提交答案 → 触发 AI 分析) - ├── ai/ # ✅ 三层 AI 架构(Provider → Gateway → Workflow) - │ ├── gateway/ # AiGatewayService(选模型、记日志、JSON容错、超时重试) - │ ├── providers/ # DeepSeek / MiniMax / Mock - │ ├── prompts/ # System Prompt + Zod Schema - │ ├── usage/ # UsageLog + CostCalculator - │ └── workflows/ # ActiveRecallAnalysisWorkflow - ├── ai-analysis/ # AI 分析结果查询 - ├── review/ # 复习模块 - ├── learning-session/ # 学习会话 - ├── learning-activity/ # 学习活跃 - ├── focus-items/ # 待巩固项 - ├── document-import/ # 文档导入 - ├── notifications/ # 通知 - ├── feedback/ # 用户反馈 - ├── waitlist/ # 等待名单 - └── system/ # 系统状态 +├── main.ts # API 进程入口 +├── worker.main.ts # Worker 进程入口 +├── app.module.ts # 根模块 +├── modules/ # 50+ 业务模块 +│ ├── auth/ +│ ├── admin-auth/ +│ ├── ai/ +│ ├── knowledge-base/ +│ ├── rag-chat/ +│ ├── quiz/ +│ ├── membership/ +│ ├── files/ +│ └── ... +├── common/ # 公共 +│ ├── guards/ # Auth Guards (JWT, Admin, Roles, Internal) +│ ├── decorators/ # @AdminPublic, @AdminRoles, @InternalApiKey +│ ├── filters/ # 异常过滤器 +│ ├── interceptors/ # 拦截器 (HTTP 日志等) +│ └── utils/ # 工具函数 +├── infrastructure/ # 基础设施层 +│ ├── database/ # Prisma Service +│ ├── redis/ # Redis Service +│ ├── queue/ # BullMQ 注册 +│ ├── storage/ # 存储 (local/COS) +│ └── outbox/ # Outbox 模式 +├── workers/ # Worker 处理器 +├── config/ # 配置 +└── test/ # 测试 ``` -## 后续规划 +## 接口文档 -- [x] 接入真实 AI API(DeepSeek + MiniMax 三层架构) -- [x] JWT 认证中间件 -- [x] 数据库持久化(Prisma + MySQL) -- [x] 12 个业务 Repository 从内存 Map 迁到 Prisma -- [x] 全局 JwtAuthGuard -- [x] Swagger 端点 Basic Auth 保护 -- [ ] 更多 AI Workflow(知识导入、费曼分析、复习卡片生成) -- [ ] AI 联调 + Prompt 调优 -- [ ] 添加 Redis 缓存 -- [ ] iOS 集成 \ No newline at end of file +- **本地**:http://localhost:3000/api-docs(无需认证) +- **生产**:https://api.longde.cloud/api-docs(Basic Auth) +- **Apifox 导入**:`https://admin:password@api.longde.cloud/api-docs-json` + +## 认证体系 + +``` +用户端: + JWT Bearer token (Authorization: Bearer ) + Refresh token 存储在 RefreshToken 表 + +管理员: + httpOnly Cookie (admin_access_token) — Web Admin + Authorization: Bearer — API 调用(兼容 iOS) + x-api-key — 自动化 + +Worker: + x-internal-api-key header +``` + +## 部署 + +### CI/CD(Gitea Actions) + +推送 `main` → 构建 → 集成测试 → 向后兼容测试 → 部署 + +``` +rsync dist/ + node_modules/ → /opt/zhixi/backend/ +systemctl restart zhixi-api + zhixi-nest-worker +``` + +### 生产服务器 + +| 组件 | 运行方式 | 位置 | +|------|---------|------| +| NestJS API | systemd (`zhixi-api`) | `/opt/zhixi/backend/` | +| NestJS Worker | systemd (`zhixi-nest-worker`) | `/opt/zhixi/backend/` | +| MySQL 8.0 | Docker | `/data/mysql/` | +| Redis 7 | Docker | `/data/redis/` | +| Qdrant | Docker | `/data/qdrant/` | +| RAG Worker | systemd (`zhixi-worker`) | `/opt/zhixi/rag-worker/` | + +### 手动部署 + +```bash +npm run build +rsync -av --delete dist/ node_modules/ prisma/ package.json ubuntu@120.53.227.155:/opt/zhixi/backend/ +ssh ubuntu@120.53.227.155 'cd /opt/zhixi/backend && npx prisma generate && sudo systemctl restart zhixi-api zhixi-nest-worker' +``` + +### 常用运维命令 + +```bash +# 服务状态 +systemctl status zhixi-api zhixi-nest-worker + +# 查看日志 +journalctl -u zhixi-api -f +journalctl -u zhixi-nest-worker -f + +# 数据库迁移 +cd /opt/zhixi/backend && npx prisma migrate deploy + +# 健康检查 +curl http://127.0.0.1:3000/health +```