Files
ai-kefu-jc/docs/2026-08-19-system-audit-and-optimization.md
T
2026-09-29 14:15:12 +08:00

156 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AI 客服系统全面分析与优化方案
- **日期**:2026-08-19
- **基线**:`e02be47`(两大特性已落地:联系方式驱动询盘邮件 `6860e88`;AI 职能边界三层防线 `3028685`+`9433f96`)
- **质量状态**:106 项测试全绿(原始基线 17);真实 GLM 冒烟通过
- **性质**:只分析不调整。问题按七层组织,每项含现象/根因/影响;优化方案按优先级排期;最后是需要拍板的决策点。
---
## 一、当前系统状态总览
```
已落地的两大能力(互相咬合的闭环):
联系方式驱动邮件: 管道确定性检测联系方式 → 秒发询盘邮件 → 更正/去重/永不锁死客户
职能边界三层防线: prompt 职能定位 → 当轮红线提醒 → 句子粒度过滤墙(打字机保留)
链路: 客户 ↔ 前端(widget/独立页/App REST) → WS/REST → ConversationManager
(GLM对话+提取+评估 | 联系方式管道 | 邮件触发器 | 边界过滤) → SQLite → SMTP询盘邮件
→ 销售人工承接(报价/安排) → admin后台辅助
```
**系统当前最大的结构性事实**:核心转化链路(聊车→挖意向→收联系方式→邮件→人工)已经完整且被测试覆盖;**剩余问题集中在四个区域——安全基线、数据可靠性、前端体验、以及"上线后才知道"的观测盲区。**
---
## 二、问题清单(七层,共 30 项)
### A. 安全层(3 项 —— 上线公网前必须处理)
| # | 问题 | 现象/根因 | 影响 |
|---|---|---|---|
| A1 | **管理后台默认密码** | `.env` 无 `ADMIN_PASSWORD` → `admin123` 生效中(本次复核确认);登录无限流无锁定;会话存内存 | 任何扫到域名的人可看全部客户对话/联系方式并删库 |
| A2 | **明文 HTTP** | openresty 的 HTTPS 配置整段被注释;admin 密码/数据明文传输 | 公网嗅探风险 |
| A3 | **WS 零限流 + 消息无长度上限** | 限流只挂在 REST `/api/chat/message`(30/h);`/ws/chat` 与独立页无任何限制;消息 content 不截断 | 每条消息 3 次 GLM 调用——脚本可无限烧钱;超长消息直接怼给 GLM |
### B. 数据与可靠性层(5 项)
| # | 问题 | 现象/根因 | 影响 |
|---|---|---|---|
| B1 | **SQLite 零备份** | 全部客户线索/画像/对话就 `data/cc_ai_kefu.db` 一份文件,无备份任务、无 WAL | 磁盘坏 = 线索全灭,业务级风险 |
| B2 | **GLM 调用无超时无重试** | 所有 GLM 调用不限时;挂起则该轮永远 typing(前端只重连不报错) | 客户体验死等 + 无告警 |
| B3 | **SMTP 无重试队列** | 发送失败靠"下一条消息自然重试"(有意的 at-least-once);给号后沉默+首发失败=线索丢失窗口 | 低概率但真实 |
| B4 | **邮件发送在请求内同步** | SMTP 握手挤占响应时间;触发频率上升后影响面变大 | 延迟抖动 |
| B5 | **会话只生不死** | 决策 A 后会话永不自动结束、无超时清理;active 行无限增长 | 数据卫生(admin 列表污染、查询变慢),功能无害但持续恶化 |
### C. 前端体验层(4 项 —— 用户实测亲历)
| # | 问题 | 现象/根因 | 影响 |
|---|---|---|---|
| C1 | **widget 刷新/翻页丢会话** | 会话只存 JS 内存、`page_token` 每次加载重新生成(widget.js:288) | 客户重聊一遍(AI 重复提问)+ 同一客户重复产生新会话(重复线索邮件放大器) |
| C2 | **会话恢复了但界面空白** | 独立页 `loadHistory()` 是空函数(chat.js:182);后端历史接口存在但页面不调用 | 客户看不到自己说过什么 |
| C3 | **widget 中途重连丢视觉历史** | WS 断线重连后消息列表只在内存 | 体验断裂 |
| C4 | **ended 后无重开入口**(低) | 永不结束后基本不触发;但历史 completed 会话刷新即新会话 | 极低 |
### D. AI 行为质量层(5 项 —— 两大特性引入的新观测点)
| # | 问题 | 现象/根因 | 影响 |
|---|---|---|---|
| D1 | **破防率长期趋势未知** | 第1+2层自律率、第3层拦截频率只有日志行,无聚合视图 | 无法判断防线配置是否过严/过松,也无法评估 GLM 升级收益 |
| D2 | **迂回话术同质化** | 过滤器过渡话术单一池不轮换;客户一小时内反复问价会看到重复句子 | 机器人感;聪明客户可感知到"触发了什么" |
| D3 | **转化流失未量化** | 价格拦截是强业务取舍——拿不到价的客户流失率、留资率变化没有任何埋点 | 无法回答"红线是否伤害转化"这个关键问题 |
| D4 | **[未评估] 邮件占比未知** | 即时触发让"第1条消息就留号"的邮件带着薄上下文+未评估标签发出 | 销售对这类邮件的跟进策略缺数据支撑 |
| D5 | **glm-4-flash 能力天花板** | 复杂询价理解/话术遵循/多语言均偏弱(本项目多次实测其不守规则) | 三层防线里第1+2层形同虚设的部分原因;模型升级可能显著降低第3层压力 |
### E. 转化漏斗层(5 项 —— 计划内未做)
| # | 问题 | 说明 |
|---|---|---|
| E1 | **UI 留资卡片未做** | 表单留资转化率 > 聊天索要;判定"有意向缺联系方式"时弹卡片是转化质变手段(批次3) |
| E2 | **admin 卡单筛选未做** | interested+无联系方式的人工兜底视图;卡单数据已在落库,只差筛选 UI |
| E3 | **线索无生命周期** | 邮件发出后无"未跟进提醒/二次触达/关闭"管理;24h 轻提醒只覆盖再来访 |
| E4 | **邮件单收件人** | `NOTIFY_EMAIL` 单一邮箱;无按国家/语种分诊(肯尼亚线和中东线分开?) |
| E5 | **无数据看板** | 会话量/留资率/意向分布/破防率/邮件量——全靠 SQL 手查 |
### F. 运维观测层(4 项)
| # | 问题 | 说明 |
|---|---|---|
| F1 | **无监控告警** | 服务挂/GLM 连续失败/SMTP 失败/磁盘满——只有日志行,无人知道 |
| F2 | **无 CI** | 106 项测试只在本地跑;push 无门禁 |
| F3 | **Redis 容器白跑** | compose 里运行但代码零引用;弱默认密码写在仓库 |
| F4 | **杂项债务** | admin 内存会话重启掉线、admin 筛选分页 total 错误、国家映射"加拿大"笔误、IP 可被 client_info 覆盖、`AIService.chat` 死代码、邮件 From 品牌【XYH】与站点不符、openresty 静态双拷贝同步陷阱、deploy.sh 停机窗口 |
### G. 架构扩展层(3 项 —— 流量上来之前不用动)
| # | 问题 | 说明 |
|---|---|---|
| G1 | 单进程 + SQLite | 并发写锁风险与流量成正比;当前量级完全够 |
| G2 | 限流/会话存内存 | 多 worker 部署即失效(当前单 worker 无碍) |
| G3 | PII 永久存储无保留策略 | 外贸业务合规盲区(低优先,知晓即可)
---
## 三、优化方案(按优先级四批)
### P0 · 上线公网前必须(约 1 天)
| 序 | 动作 | 对应 | 成本 |
|---|---|---|---|
| 1 | .env 配置强 `ADMIN_PASSWORD` + admin 登录限流 | A1 | 0.5h |
| 2 | 启用 openresty HTTPS(证书+301) | A2 | 1h |
| 3 | WS 限流(session 严 60/h、IP 宽、消息级拒绝防重连风暴)+ 消息长度上限(复用 429) | A3 | 0.5 天,前后端同批 |
| 4 | SQLite 定时备份(`sqlite3 .backup` cron + 保留策略 + WAL) | B1 | 1h |
| 5 | GLM 调用超时(30s)+ 单次重试 + 前端明确报错 | B2 | 0.5 天 |
### P1 · 上线第一周(观测+卫生,约 2 天)
| 序 | 动作 | 对应 |
|---|---|---|
| 1 | 超时清理任务(lifespan 周期扫描:24h 无消息的 active → abandoned) | B5 |
| 2 | **破防率聚合**:每日统计 `Boundary filter` 日志行数 → 简单接口/脚本输出趋势 | D1 |
| 3 | 留资率/流失埋点:admin 加统计接口(会话数、留联系方式数、[未评估]占比) | D3/D4 |
| 4 | 简单告警:健康检查失败/GLM 连续失败/SMTP 失败 → 邮件或 webhook 通知 | F1 |
| 5 | 邮件发送移出请求路径(asyncio.create_task + 短超时) | B4 |
| 6 | F4 杂项打包:admin 分页/国家映射/删 AIService.chat/删 Redis/From 品牌改 | F4 |
### P2 · 批次 2:前端体验(约 3 天,解决你亲历的痛点)
| 序 | 动作 | 对应 |
|---|---|---|
| 1 | widget 会话持久化(独立前缀 localStorage + 48h 过期) | C1 |
| 2 | 独立页/widget 历史渲染(loadHistory 接现有历史接口) | C2/C3 |
| 3 | WS 限流前端配合(P0-3 的前端侧) | A3 |
### P3 · 批次 3 + 长期:转化与质量
| 序 | 动作 | 对应 |
|---|---|---|
| 1 | UI 留资卡片(端点限流+校验+只弹一次) | E1 |
| 2 | admin 卡单筛选 + 线索列表视图(含破防监控标签) | E2/D1 |
| 3 | 过渡话术扩池轮换 | D2 |
| 4 | 评估 glm-4-air/plus 对自律率的提升(换模型跑冒烟对比破防率) | D5 |
| 5 | 邮件分诊(按国家路由收件人) | E4 |
| 6 | 线索生命周期(跟进状态字段+超时提醒) | E3 |
| 7 | 数据看板(E5)、CI(F2)、多 worker 改造(G1/G2,流量触发) | 长期 |
---
## 四、需要拍板的决策点
| # | 决策 | 选项与建议 |
|---|---|---|
| 1 | **上线节奏** | 两大特性现在就上(建议:核心价值已闭环,P0 做完就走),还是等 P1 观测一起? |
| 2 | **超时时长**(B5) | active 会话多久算 abandoned?建议 24h(与 24h 去重窗口对齐) |
| 3 | **是否保留生产基线任务** | 上线前跑一次 `baseline_stats.py` + `breach_rate.py` 存档(强烈建议,一次性机会) |
| 4 | **模型升级评估要不要排期** | 如果第1+2层自律率长期很低(全靠墙),升模型可能比维护三层更省心 |
| 5 | **邮件分诊需求** | 销售团队实际几人?按国家分箱是否真实需要? |
---
## 五、结论
**系统核心链路健康**:两大特性互相咬合、106 项测试护栏、真实流量冒烟通过。剩余问题没有一个是核心链路缺陷——全部集中在**安全基线(A 层 3 项)、数据可靠性(B 层 2 项)、前端体验(C 层 3 项)和观测盲区(D/F 层)**。
最短路径建议:**P0 五项(约一天)做完即可上线**,第一周做 P1 建立观测,之后按 P2/P3 消化体验与转化。A1(改密码)是零成本零风险的一项,无论如何先做。