包含多个会话的累积代码变更: - 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>
317 lines
12 KiB
Markdown
317 lines
12 KiB
Markdown
# P15:AI 监控后台 + 测试重建 + 回填
|
||
|
||
> 状态:Draft | 创建日期:2026-03-21 | 依赖:P14(DashScope 迁移 + 调度器完善)
|
||
> 前置条件:P14 全部完成并验证通过后,方可开始 P15 实施
|
||
|
||
---
|
||
|
||
## 一、执行摘要
|
||
|
||
P14 完成 SDK 迁移和调度器修复后,本 PRD 覆盖三个方面:
|
||
1. admin-web AI 监控后台(运行总览、调度状态、调用明细、手动操作)
|
||
2. 测试体系重建(旧脚本归档、新全链路测试、属性测试更新)
|
||
3. 历史数据回填(半年内活跃会员,<100 人)
|
||
|
||
### 问题覆盖
|
||
|
||
本 PRD 覆盖 `docs/reports/2026-03-21__ai_module_issues.md` 中的:
|
||
- P2-1:App5 话术缺分类
|
||
- P2-2:MCP 无健康检查
|
||
- P2-4:全链路测试不完整
|
||
- P3-3:Prompt 版本管理(仅监控展示部分)
|
||
|
||
---
|
||
|
||
## 二、admin-web AI 监控后台
|
||
|
||
### 2.1 技术基础
|
||
|
||
- 框架:React + Vite + Ant Design(已有 8 个页面,加页面即可)
|
||
- 认证:JWT Bearer Token,复用现有 admin 权限体系
|
||
- API 前缀:`/api/admin/ai/*`
|
||
- 权限:系统管理员全量可见,不脱敏,点开详情看原文
|
||
- 门店筛选:支持按 `site_id` 筛选查看
|
||
|
||
### 2.2 页面规划
|
||
|
||
#### 页面 1:AI 运行总览(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)
|
||
- 企业微信/邮件告警推送(后续迭代)
|