feat: 累积功能变更 — 聊天集成、租户管理、小程序更新、ETL 增强、迁移脚本

包含多个会话的累积代码变更:
- backend: AI 聊天服务、触发器调度、认证增强、WebSocket、调度器最小间隔
- admin-web: ETL 状态页、任务管理、调度配置、登录优化
- miniprogram: 看板页面、聊天集成、UI 组件、导航更新
- etl: DWS 新任务(finance_area_daily/board_cache)、连接器增强
- tenant-admin: 项目初始化
- db: 19 个迁移脚本(etl_feiqiu 11 + zqyy_app 8)
- packages/shared: 枚举和工具函数更新
- tools: 数据库工具、报表生成、健康检查
- docs: PRD/架构/部署/合约文档更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Neo
2026-04-06 00:03:48 +08:00
parent 70324d8542
commit 6f8f12314f
515 changed files with 76604 additions and 7456 deletions

View File

@@ -0,0 +1,316 @@
# P15AI 监控后台 + 测试重建 + 回填
> 状态Draft | 创建日期2026-03-21 | 依赖P14DashScope 迁移 + 调度器完善)
> 前置条件P14 全部完成并验证通过后,方可开始 P15 实施
---
## 一、执行摘要
P14 完成 SDK 迁移和调度器修复后,本 PRD 覆盖三个方面:
1. admin-web AI 监控后台(运行总览、调度状态、调用明细、手动操作)
2. 测试体系重建(旧脚本归档、新全链路测试、属性测试更新)
3. 历史数据回填(半年内活跃会员,<100 人)
### 问题覆盖
本 PRD 覆盖 `docs/reports/2026-03-21__ai_module_issues.md` 中的:
- P2-1App5 话术缺分类
- P2-2MCP 无健康检查
- P2-4全链路测试不完整
- P3-3Prompt 版本管理(仅监控展示部分)
---
## 二、admin-web AI 监控后台
### 2.1 技术基础
- 框架React + Vite + Ant Design已有 8 个页面,加页面即可)
- 认证JWT Bearer Token复用现有 admin 权限体系
- API 前缀:`/api/admin/ai/*`
- 权限:系统管理员全量可见,不脱敏,点开详情看原文
- 门店筛选:支持按 `site_id` 筛选查看
### 2.2 页面规划
#### 页面 1AI 运行总览Dashboard
| 区域 | 内容 | 数据来源 |
|------|------|---------|
| 顶部统计卡片 | 今日调用次数、成功率、Token 消耗、平均延迟 | `ai_run_logs` 聚合 |
| 趋势图 | 近 7 天调用量 + 成功率折线图 | `ai_run_logs` 按日聚合 |
| App 分布 | 各 App 调用占比饼图 | `ai_run_logs.app_type` 分组 |
| Token 预算 | 日/月预算使用进度条 | `ai_run_logs.tokens_used` 聚合 |
| 告警列表 | 最近失败/超时/熔断事件 | `ai_run_logs` WHERE status IN ('failed','timeout') |
#### 页面 2调度状态
| 区域 | 内容 | 数据来源 |
|------|------|---------|
| 触发任务列表 | 分页表格:事件类型、会员、状态、执行链、耗时 | `ai_trigger_jobs` |
| 筛选器 | event_type / status / site_id / 日期范围 | — |
| 操作列 | 查看详情、手动重跑 | — |
| 去重统计 | 今日跳过的重复事件数 | `ai_trigger_jobs` WHERE status='skipped_duplicate' |
#### 页面 3调用明细
| 区域 | 内容 | 数据来源 |
|------|------|---------|
| 调用记录表格 | app_type、trigger_type、member_id、tokens、延迟、状态 | `ai_run_logs` |
| 筛选器 | app_type / status / trigger_type / site_id / 日期范围 | — |
| 详情抽屉 | 点击行展开:完整 prompt、完整 response、error_message | `ai_run_logs` 单条 |
#### 页面 4手动操作
| 功能 | 说明 |
|------|------|
| 手动重跑 | 选择 App + 会员 + 门店,触发单次执行(标记 `is_forced=true` |
| 缓存失效 | 按 App / 会员 / 门店批量将 `ai_cache.status` 设为 `invalidated` |
| 成本二次确认 | 批量操作前展示预估调用次数和 Token 消耗,点"确认执行"后才真正执行 |
| 告警确认/忽略 | 对失败告警标记"已确认"或"忽略" |
### 2.3 后端 API 清单
```
GET /api/admin/ai/dashboard — 总览统计数据
GET /api/admin/ai/trigger-jobs — 调度任务列表(分页 + 筛选)
GET /api/admin/ai/trigger-jobs/:id — 调度任务详情
POST /api/admin/ai/trigger-jobs/:id/retry — 手动重跑
GET /api/admin/ai/run-logs — 调用记录列表(分页 + 筛选)
GET /api/admin/ai/run-logs/:id — 调用记录详情(含完整 prompt/response
POST /api/admin/ai/cache/invalidate — 批量缓存失效
GET /api/admin/ai/budget — Token 预算使用情况
POST /api/admin/ai/batch-run — 批量执行(需二次确认)
POST /api/admin/ai/batch-run/confirm — 确认批量执行
GET /api/admin/ai/alerts — 告警列表
POST /api/admin/ai/alerts/:id/ack — 确认告警
POST /api/admin/ai/alerts/:id/ignore — 忽略告警
```
### 2.4 成本二次确认流程
```
管理员选择批量操作(如:回填 50 个会员)
→ POST /api/admin/ai/batch-run
→ 后端计算50 会员 × 5 App = 250 次调用,预估 ~500K tokens
→ 返回 { batch_id, estimated_calls: 250, estimated_tokens: 500000 }
→ 前端展示确认弹窗:"本次将执行 250 次 AI 调用,预估消耗 50 万 tokens确认执行"
→ 管理员点"确认执行"
→ POST /api/admin/ai/batch-run/confirm { batch_id }
→ 后端异步执行
```
---
## 三、测试体系重建
### 3.1 旧测试脚本归档
以下 4 个脚本移至 `_archived/` 目录:
| 脚本 | 原位置 | 归档位置 |
|------|---------|---------|
| `ai_full_chain_test.py` | `scripts/ops/` | `scripts/ops/_archived/` |
| `test_chat_e2e.py` | `scripts/ops/` | `scripts/ops/_archived/` |
| `test_chat_ai_quality.py` | `scripts/ops/` | `scripts/ops/_archived/` |
| `test_bailian_apps.py` | `scripts/ops/` | `scripts/ops/_archived/` |
| `test_bailian_single.py` | `scripts/ops/` | `scripts/ops/_archived/` |
| `test_bailian_full.py` | `scripts/ops/` | `scripts/ops/_archived/` |
| `_run_ai_tests_remaining.py` | `scripts/ops/` | `scripts/ops/_archived/` |
| `test_ai_bailian.py` | `apps/backend/tests/` | `apps/backend/tests/_archived/` |
| `2026-03-21__ai_full_chain_test.md` | `docs/reports/` | `docs/reports/_archived/` |
归档时保留文件内容不变,仅移动位置。审计记录(`docs/audit/`)不删除,只停止引用。
### 3.2 新全链路测试
#### 测试覆盖矩阵
| 测试场景 | 覆盖 App | 验证点 |
|---------|---------|--------|
| App1 对话10 种入口) | App1 | SSE 流式、session_id 双轨、对话复用规则 |
| App2 定时预生成 | App2 | 8 个时间维度、缓存写入、JSON 合法性 |
| 消费事件触发链 | App3→App8→App7 | 事件传播、缓存写入、业务表写入 |
| 助教消费触发链 | App3→App8→App7→App4→App5 | 完整链路、助教关联 |
| 备注事件触发链 | App6→App8 | 备注分析、线索整合 |
| 任务分配触发链 | App4→App5 | 关系分析、话术生成 |
| 缓存命中 | App2~8 | 缓存有效期内直接返回、过期后重新生成 |
| 缓存失效 | App2~8 | admin-web 手动失效后重新生成 |
| 熔断触发 | 任意 App | 连续 5 次失败→熔断→半开→恢复 |
| Token 预算超限 | 任意 App | 超限后正确降级 |
| 失败记录 | 任意 App | `ai_run_logs` 记录完整、error_message 有值 |
| 后台可见性 | 全部 | admin-web 能看到所有运行记录和详情 |
| JSON 兜底 | App2~8 | 非法 JSON 重试 3 次 |
| 幂等验证 | App8 | 同一 member 同一天重复触发只执行一次 |
| 内容质量 | App2~8 | 返回内容包含必要字段、格式正确 |
#### App1 的 10 种入口
1. general通用对话始终新建
2. customer_detail客户详情页
3. coach_detail助教详情页
4. task_detail任务详情页
5. finance_overview财务总览页
6. member_list会员列表页
7. settlement_detail结算详情页
8. note_detail备注详情页
9. dashboard首页仪表盘
10. report报表页
### 3.3 属性测试更新
更新 `tests/` 下的 Hypothesis 属性测试:
| 属性测试 | 验证不变量 |
|---------|-----------|
| 熔断器状态机 | 状态转换合法性closed→open→half_open→closed/open |
| Token 预算计算 | 日/月聚合值 = 各条记录 tokens_used 之和 |
| 去重逻辑 | 相同 (event_type, member_id, site_id, date) 只产生一条非 skipped 记录 |
| 缓存过期 | expires_at 过期的缓存 status 必须为 expired |
| App8 幂等 | 同一 member 同一天的 member_retention_clue 只有一组记录 |
| session_id 重建 | 重建后的 messages 数组与本地 ai_messages 一致 |
| 限流计数 | 窗口内请求数不超过上限 |
---
## 四、历史数据回填
### 4.1 回填范围
半年内2025-09-21 ~ 2026-03-21三者并集
- 有消费记录的 member
- 有备注记录的 member
- 有任务变更的 member
预估规模:<100 会员。
门店范围:`site_id = 2790685415443269`(写死)。
### 4.2 回填策略
- 执行方式:专门脚本(`scripts/ops/ai_backfill.py`
- 分批执行:每批 10 个会员,批间间隔 5 秒
- 断点续跑:脚本记录已完成的 member_id 列表到本地文件,失败后从断点继续
- 不备份现有数据
- App8 写业务表(`member_retention_clue`DELETE + INSERT事务包裹
### 4.3 回填调用链
每个会员执行:
```
App3维客线索→ App8线索整理→ App7客户分析
如有助教关联:→ App4关系分析→ App5话术参考
如有备注:→ App6备注分析→ App8再次整合
```
### 4.4 成本预估
- 100 会员 × 平均 5 个 App = 500 次调用
- 每次约 2000 tokens → 总计约 100 万 tokens
- 执行前通过 admin-web 二次确认
---
## 五、数据保留策略
| 数据类型 | 保留策略 | 清理方式 |
|---------|---------|---------|
| App1 对话记录ai_conversations + ai_messages | 永久保留,不自动删除 | — |
| App2~8 缓存ai_cache | 每个 App 保留最新 20,000 条 | 定时任务:按 created_at 排序,超出部分 DELETE |
| AI 运行记录ai_run_logs | 保留 90 天 | 定时任务DELETE WHERE created_at < now() - 90 days |
| 调度记录ai_trigger_jobs | 保留 90 天 | 同上 |
清理定时任务建议每日凌晨 03:00 执行。
---
## 六、后端 API 变更汇总
### 新增路由文件
`apps/backend/app/routers/admin_ai.py`
### 新增 Service
`apps/backend/app/services/ai/admin_service.py` — 聚合查询、批量操作、告警管理
### 数据库查询优化
- `ai_run_logs` 的 Dashboard 聚合查询需要按日分区或添加 BRIN 索引
- `ai_trigger_jobs` 的去重查询已有复合索引§P14 六.2
---
## 七、问题修复映射
| 问题编号 | 优先级 | 描述 | 本 PRD 对应章节 |
|---------|--------|------|----------------|
| P2-1 | P2 | App5 话术缺分类 | 回填时验证 App5 输出包含分类字段 |
| P2-2 | P2 | MCP 无健康检查 | admin-web Dashboard 展示各 App 最近调用状态 |
| P2-4 | P2 | 全链路测试不完整 | §3.2(新全链路测试) |
| P3-3 | P3 | Prompt 版本管理 | admin-web 展示当前 App 配置(只读) |
---
## 八、收尾标准流程
### 8.1 DDL 迁移
本 PRD 无新增表P14 已创建)。如有字段调整:
1. 编写增量迁移脚本
2. 测试库验证
3. 合并基线
### 8.2 BD 手册更新
- 更新 `docs/database/BD_Manual_ai_tables.md`:补充 admin API 相关的查询模式说明
### 8.3 文档同步
| 文档 | 更新内容 |
|------|---------|
| `apps/admin-web/README.md` | 新增 AI 监控页面说明 |
| `apps/backend/README.md` | 新增 admin AI API 说明 |
| `docs/DOCUMENTATION-MAP.md` | 新增条目 |
| `docs/prd/ai-app-prompts.md` | 确认环境变量已全部更新 |
### 8.4 属性测试
- 新增 §3.3 中列出的 7 个属性测试
- 确保所有属性测试通过
### 8.5 最终检查点
- [ ] admin-web AI 监控 4 个页面功能正常
- [ ] 手动重跑功能正常,标记 forced
- [ ] 缓存失效功能正常
- [ ] 成本二次确认流程完整
- [ ] 旧测试脚本已归档到 `_archived/`
- [ ] 新全链路测试覆盖 15 个场景
- [ ] 属性测试全部通过
- [ ] 回填脚本执行完成,<100 会员数据完整
- [ ] 数据保留定时任务配置完成
- [ ] 所有文档已同步更新
---
## 九、风险与缓解
| 风险 | 影响 | 缓解措施 |
|------|------|---------|
| 回填触发大量 API 调用 | 成本突增 | 分批执行 + admin-web 二次确认 |
| 回填中途失败 | 部分会员数据不完整 | 断点续跑机制 |
| admin-web 查询大量 ai_run_logs 性能差 | 页面卡顿 | 分页 + 索引 + 90 天保留策略 |
| 全链路测试依赖真实百炼 API | 测试不稳定 | Mock 模式 + 真实 API 模式双轨 |
---
## 十、不在本 PRD 范围
- 多门店支持BACKLOG
- 消息队列(单独 PRD
- Prompt 版本管理的编辑功能BACKLOG本轮仅展示
- 前端刷新机制P1-5
- FDW 数据一致性P1-6
- 企业微信/邮件告警推送(后续迭代)