528 lines
13 KiB
Markdown
528 lines
13 KiB
Markdown
# CRM-NEW 上线文档
|
||
|
||
| 项 | 内容 |
|
||
|---|---|
|
||
| 上线日期 | 2026-10-23 |
|
||
| 上线范围 | 方案 A:bridge 接管 Live chat AI;Email/WhatsApp 人工处理 |
|
||
| 当前状态 | Live chat 已切 bridge AI;Email/WhatsApp 已切人工团队;Twenty 商机已打通 |
|
||
| 变更窗口 | 建议低峰期,预留 30–60 分钟 |
|
||
| 负责人 | 待填 |
|
||
|
||
---
|
||
|
||
## 1. 上线范围
|
||
|
||
### 上线内容
|
||
|
||
- LibreDesk:Live chat / Email / WhatsApp 三个渠道
|
||
- bridge AI:Live chat 的 LLM、工具、RAG、OTP、输出护栏、质量指标
|
||
- Twenty CRM:联系人、公司、商机、备注、3 天跟进任务
|
||
- Email/WhatsApp:不再由 AI 回复,进入 `Wholesale Support` 人工团队
|
||
- 旧 bridge KB:Hybrid RAG(parent-child + 向量 + 全文 + RRF)
|
||
- 全量商品页 sitemap:www 32,691 / us 22,625
|
||
- 质量:逐会话指标、URL/数字审计、质量日报、离线评测
|
||
|
||
### 不在本次上线范围
|
||
|
||
- Email / WhatsApp 的 bridge AI 回复
|
||
- WhatsApp 模板消息 / 媒体 / 语音
|
||
- 邮件每日 digest
|
||
- A/B 实验
|
||
- 多副本/高可用部署
|
||
- PII 自动保留/删除策略
|
||
- 真实客户邮件历史 ingest(当前 `kb_mail_docs` 只有测试邮件)
|
||
|
||
---
|
||
|
||
## 2. 当前架构
|
||
|
||
```
|
||
Live chat (inbox 1)
|
||
LibreDesk widget
|
||
→ LibreDesk webhook message.created
|
||
→ bridge /libredesk/webhook
|
||
→ bridge AI(LLM + 工具 + RAG + OTP + 输出护栏)
|
||
→ LibreDesk API 回写 agent 消息
|
||
|
||
Email (inbox 2) / WhatsApp (inbox 3)
|
||
→ LibreDesk 自动化规则
|
||
→ assign_team = Wholesale Support
|
||
→ 人工团队队列
|
||
→ 不调用 AI
|
||
```
|
||
|
||
---
|
||
|
||
## 2.1 环境差异(本地开发 vs 测试/生产)
|
||
|
||
> 详见 [environments.md](environments.md)。
|
||
|
||
- `scripts/rpc-tunnel.sh`:**仅本地开发**,因为 RPC 端口外网不可达
|
||
- `scripts/public-https.sh`:**仅本地联调**,Cloudflare Quick Tunnel
|
||
- 测试/生产:RPC 直接配内网地址,公网 HTTPS 用正式域名 + Ingress/Nginx/ALB
|
||
- 测试/生产不应运行上述两个脚本
|
||
|
||
---
|
||
|
||
## 3. 访问入口
|
||
|
||
| 服务 | 地址 | 备注 |
|
||
|---|---|---|
|
||
| LibreDesk | `http://localhost:9000` | 管理端 / 工作台 |
|
||
| Twenty CRM | `http://localhost:3100` | CRM |
|
||
| bridge | `http://localhost:4100` | 内部工具/健康检查 |
|
||
| Widget 测试页 | `http://localhost:8088/demo.html` | 本机测试用 |
|
||
| 公网入口 | `.env` 的 `PUBLIC_BASE_URL` | Cloudflare Quick Tunnel,**URL 会变** |
|
||
| Postgres | `localhost:5440` | 仅本机 |
|
||
| Redis | `localhost:6390` | 仅本机 |
|
||
| IMAP proxy | `localhost:1993` | 仅本机 |
|
||
|
||
---
|
||
|
||
## 4. 当前切流配置
|
||
|
||
### Live chat
|
||
|
||
| 项 | 状态 |
|
||
|---|---|
|
||
| bridge webhook | 启用 |
|
||
| LibreDesk 规则 1“分配新会话给 AI Assistant” | 关闭 |
|
||
| bridge inbox 过滤 | `LIBREDESK_WEBHOOK_INBOX_IDS=1` |
|
||
|
||
### Email / WhatsApp
|
||
|
||
| 项 | 状态 |
|
||
|---|---|
|
||
| 团队 | `Wholesale Support`(id=1) |
|
||
| 团队类型 | `Round robin` |
|
||
| 成员 | agent1 (26)、agent2 (27) |
|
||
| 规则 4 | Email inbox 2 → assign_team 1 |
|
||
| 规则 5 | WhatsApp inbox 3 → assign_team 1 |
|
||
| AI Assistant 分配 | 已移除 |
|
||
|
||
> agent1/agent2 当前是 `offline`。Round robin 只有坐席在线/可用时才会进一步分到个人;离线时停留在团队队列。若希望永远只进团队队列,可把团队类型改为 `Manual`。
|
||
|
||
---
|
||
|
||
## 5. 上线前检查
|
||
|
||
- [ ] `.env` 已备份,且权限为 `600`
|
||
- [ ] `docker compose config -q` 通过
|
||
- [ ] 本地开发:RPC 隧道可用;测试/生产:RPC 内网地址可直达
|
||
- [ ] LibreDesk webhook `Bridge AI` 为启用状态
|
||
- [ ] LibreDesk 规则 1 关闭
|
||
- [ ] 规则 4/5 指向 `Wholesale Support`
|
||
- [ ] agent1/agent2 可登录,必要时设为在线
|
||
- [ ] WhatsApp access token 未过期(当前 token 有到期时间)
|
||
- [ ] 本地开发:Quick Tunnel 与 Meta webhook 已同步;测试/生产:正式域名与 Meta webhook 已同步
|
||
- [ ] 163 SMTP / IMAP 可用
|
||
- [ ] 已做数据库备份
|
||
- [ ] bridge 测试通过
|
||
- [ ] 质量告警 cron 已配置(或本次上线后立即配置)
|
||
|
||
---
|
||
|
||
## 6. 部署/启动步骤
|
||
|
||
### 6.1 当前机器上启动
|
||
|
||
```bash
|
||
cd /home/dev/code/crm-new
|
||
|
||
# 1) 校验 compose
|
||
docker compose config -q
|
||
|
||
# 2) 启动/更新
|
||
docker compose up -d
|
||
|
||
# 3) 重建 bridge(代码变更时必须)
|
||
docker compose up -d --build --force-recreate bridge
|
||
|
||
# 4) 查看状态
|
||
docker compose ps
|
||
```
|
||
|
||
### 6.2 首次部署/新环境
|
||
|
||
```bash
|
||
cd /home/dev/code/crm-new
|
||
bash scripts/bootstrap.sh
|
||
```
|
||
|
||
首次部署后还需要:
|
||
|
||
```bash
|
||
node scripts/setup-defaults.js
|
||
node scripts/twenty-bootstrap.js
|
||
node scripts/register-tools.js
|
||
node scripts/configure-email.js
|
||
```
|
||
|
||
> 已有环境不要直接重跑 `bootstrap.sh`,会覆盖 `.env`/配置。
|
||
|
||
### 6.3 数据准备
|
||
|
||
#### 有旧 bridge / 旧 products 库时
|
||
|
||
```bash
|
||
# 重建 KB parent-child 索引(KB 更新后;会先备份旧表)
|
||
bash scripts/rebuild-kb-index.sh
|
||
|
||
# 旧 KB 补 text_tsv/parent_id(已执行过,幂等)
|
||
node scripts/upgrade-kb-schema.js
|
||
```
|
||
|
||
#### 测试/生产没有旧 bridge 时(推荐)
|
||
|
||
不要运行 `rebuild-kb-index.sh`。直接导入仓库里的 KB 快照:
|
||
|
||
```bash
|
||
# 默认导入到 crmnew-postgres / bridge 库
|
||
bash scripts/import-kb-snapshot.sh
|
||
|
||
# 或导入到 products 库
|
||
TARGET_PG_DB=products bash scripts/import-kb-snapshot.sh
|
||
|
||
# 验证
|
||
docker exec crmnew-postgres psql -U crmnew -d bridge -tAc \
|
||
"select count(*), count(*) filter (where chunk_type='parent'), count(*) filter (where chunk_type='child') from kb_docs;"
|
||
```
|
||
|
||
预期:
|
||
|
||
```
|
||
361 | 292 | 69
|
||
```
|
||
|
||
然后把测试环境 `.env` 的 `RAG_PG_URL` 指向该库,例如:
|
||
|
||
```env
|
||
RAG_PG_URL=postgres://crmnew:<password>@postgres:5432/bridge
|
||
```
|
||
|
||
> 快照文件:`deploy/seeds/kb_docs.sql.gz`(只包含 `kb_docs` 知识库,不含邮件/客户数据)
|
||
> 当前环境如需重新生成:`bash scripts/export-kb-snapshot.sh`
|
||
|
||
#### 全量商品页站点地图
|
||
|
||
```bash
|
||
node scripts/build-site-map.js www us
|
||
```
|
||
|
||
### 6.4 RPC 隧道(仅本地开发)
|
||
|
||
> 测试/生产不需要这一步;直接配置内网 RPC 地址即可。
|
||
|
||
本地 RPC 端口外网不可达时才需要:
|
||
|
||
```bash
|
||
bash scripts/rpc-tunnel.sh
|
||
```
|
||
|
||
隧道断了会导致 `search_products/search_orders/search_inventory` 失败。
|
||
|
||
### 6.5 公网 HTTPS / WhatsApp webhook(仅本地联调)
|
||
|
||
> 测试/生产不要用 Cloudflare Quick Tunnel;使用正式域名 + Ingress/Nginx/ALB + TLS。
|
||
|
||
本地联调:
|
||
|
||
```bash
|
||
bash scripts/public-https.sh
|
||
```
|
||
|
||
Cloudflare Quick Tunnel URL 每次重启可能变化,需要同步:
|
||
|
||
- LibreDesk `app.root_url`
|
||
- Meta WhatsApp callback URL
|
||
|
||
---
|
||
|
||
## 7. 验收清单
|
||
|
||
### 7.1 基础健康
|
||
|
||
```bash
|
||
curl -s http://localhost:4100/healthz
|
||
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:3100/healthz
|
||
cd bridge && npm test
|
||
```
|
||
|
||
预期:
|
||
|
||
- bridge `{"ok":true,...}`
|
||
- Twenty `200`
|
||
- tests **75/75**
|
||
|
||
### 7.2 Live chat JWT
|
||
|
||
```bash
|
||
node scripts/e2e-widget-jwt.js "What is the minimum order value?"
|
||
```
|
||
|
||
预期:
|
||
|
||
- AI 回复 €30
|
||
- 调用 `search_kb`
|
||
- 回复为 HTML
|
||
- 无未验证 URL
|
||
|
||
### 7.3 匿名 OTP
|
||
|
||
```bash
|
||
node scripts/e2e-anon-otp.js
|
||
```
|
||
|
||
预期:
|
||
|
||
- AI 先要求验证
|
||
- 收到验证码邮件
|
||
- 输入后 verified
|
||
- 能查订单(或明确无订单)
|
||
|
||
> 该脚本会读取 163 邮箱并创建测试会话,生产环境谨慎执行。
|
||
|
||
### 7.4 商机
|
||
|
||
```bash
|
||
node scripts/e2e-widget-jwt.js "I want to buy 500 pieces of stainless steel rings"
|
||
```
|
||
|
||
然后发:
|
||
|
||
```
|
||
Our company is Test Buyer BV, contact name Jan Jansen.
|
||
```
|
||
|
||
到 Twenty 检查:
|
||
|
||
- Company / Person / Opportunity
|
||
- Opportunity 名称为 `<company> — <need>`
|
||
- Note 已关联
|
||
- Task 3 天后到期
|
||
|
||
### 7.5 离线评测
|
||
|
||
```bash
|
||
node scripts/eval-offline.js
|
||
node scripts/eval-live.js
|
||
```
|
||
|
||
预期:
|
||
|
||
- 确定性评测 **18/18**
|
||
- 真实模型 smoke **4/4**
|
||
|
||
### 7.6 质量指标
|
||
|
||
```bash
|
||
node scripts/quality-report.js 24
|
||
node scripts/quality-alert.js 1 --dry-run
|
||
```
|
||
|
||
预期:
|
||
|
||
- 无错误/无未验证 URL 告警
|
||
- 当前健康时输出 `{"ok":true,...}`
|
||
|
||
---
|
||
|
||
## 8. 监控与告警
|
||
|
||
### 质量告警 cron
|
||
|
||
```cron
|
||
*/30 * * * * cd /home/dev/code/crm-new && node scripts/quality-alert.js 1 >> logs/quality-alert.log 2>&1
|
||
```
|
||
|
||
阈值:
|
||
|
||
- AI 错误率 > 10%
|
||
- 工具错误率 > 10%
|
||
- 未验证 URL 占比 > 15%
|
||
- 平均延迟 > 8000ms
|
||
|
||
### 必看日志
|
||
|
||
```bash
|
||
docker logs -f crmnew-bridge
|
||
docker logs -f crmnew-libredesk
|
||
docker logs -f crmnew-twenty-server
|
||
docker logs -f crmnew-cloudflared
|
||
```
|
||
|
||
bridge 关键日志:
|
||
|
||
- `webhook: message.created`
|
||
- `agent: tool`
|
||
- `agent: output_guard`
|
||
- `agent: replied`
|
||
- `crm: stage_advanced`
|
||
|
||
### 外部依赖巡检
|
||
|
||
- 本地开发:RPC 隧道进程
|
||
- 本地开发:Cloudflare tunnel 状态
|
||
- 测试/生产:内网 RPC 可达性、Ingress/证书、WhatsApp token 剩余有效期
|
||
- 163 SMTP/IMAP
|
||
- 未分配/团队队列积压
|
||
|
||
---
|
||
|
||
## 9. 日常运维
|
||
|
||
```bash
|
||
# 重启 bridge
|
||
docker compose restart bridge
|
||
|
||
# 重建 bridge
|
||
docker compose up -d --build --force-recreate bridge
|
||
|
||
# 查看资源
|
||
docker stats
|
||
|
||
# 数据库备份
|
||
docker exec crmnew-postgres pg_dump -U crmnew -d libredesk > backup-libredesk-$(date +%F).sql
|
||
docker exec crmnew-postgres pg_dump -U crmnew -d bridge > backup-bridge-$(date +%F).sql
|
||
docker exec crm-postgres pg_dump -U postgres -d products > backup-products-$(date +%F).sql
|
||
```
|
||
|
||
详细命令见 [runbook.md](runbook.md)。
|
||
|
||
---
|
||
|
||
## 10. 回滚方案
|
||
|
||
### 10.1 Live chat 回滚(最常用)
|
||
|
||
```bash
|
||
# 1) 停用 bridge webhook
|
||
# LibreDesk 后台 Webhooks → Bridge AI → 停用
|
||
|
||
# 2) 重新开启规则 1
|
||
# Automations → Assign new conversations to AI Assistant → 启用
|
||
|
||
# 3) 可选:停止 bridge
|
||
docker compose stop bridge
|
||
```
|
||
|
||
效果:Live chat 回到 LibreDesk 自带 AI。
|
||
|
||
### 10.2 Email / WhatsApp 回滚
|
||
|
||
```bash
|
||
# 规则 4/5 改回 assign_user = AI Assistant(id=3)
|
||
```
|
||
|
||
或直接停用规则 4/5,由人工在未分配队列处理。
|
||
|
||
### 10.3 数据回滚
|
||
|
||
- KB 旧表:`kb_docs_v1`
|
||
- rebuild 前备份:`kb_docs_backup_20261022`
|
||
- 恢复前先确认表结构/索引
|
||
- Twenty 测试数据删除需按 ID 精确操作,不要批量删
|
||
|
||
### 10.4 代码回滚
|
||
|
||
- 保留上一版 bridge 镜像/commit
|
||
- `docker compose up -d --build --force-recreate bridge`
|
||
- 回滚后必须重跑:
|
||
- `npm test`
|
||
- `scripts/eval-offline.js`
|
||
- 一条 Live chat smoke
|
||
|
||
---
|
||
|
||
## 11. 已知限制与风险
|
||
|
||
### 高
|
||
|
||
1. **单点**:bridge 只有一个实例;bridge 挂了 Live chat 无 AI 回复。
|
||
2. **RPC 隧道(仅本地开发)**:依赖本机 SSH 隧道,断了商品/订单/库存工具不可用。测试/生产应直连内网 RPC。
|
||
3. **公网 URL(仅本地开发)**:Cloudflare Quick Tunnel URL 不固定,重启可能失效。测试/生产使用正式域名。
|
||
4. **WhatsApp token**:临时 token 有到期时间,需要提前续期。
|
||
5. **Email 历史数据为空**:`kb_mail_docs` 只有测试邮件,真实客户历史未 ingest。
|
||
|
||
### 中
|
||
|
||
6. **商机币种**:`USD 1000` 目前存为 EUR。
|
||
7. **productNeed**:可能把整句需求写入商机名。
|
||
8. **输出护栏是规则型**:可能漏掉未覆盖措辞,或重写后语句略生硬。
|
||
9. **告警未落 cron/看板**:需要上线后配置。
|
||
10. **PII**:日志/指标可能包含客户消息片段;无自动保留/删除策略。
|
||
11. **agent1/agent2 offline**:Email/WhatsApp 会停在团队队列,需要人工上线/认领。
|
||
12. **bridge 4100 暴露在局域网**:建议防火墙限制,仅允许 LibreDesk/内网访问。
|
||
|
||
### 低
|
||
|
||
13. KB/索引/sitemap 仍以手动脚本刷新为主。
|
||
14. 无 A/B、无真实邮件 digest、无 WhatsApp 模板/媒体。
|
||
15. 无多副本/跨机高可用。
|
||
|
||
---
|
||
|
||
## 12. 上线后待办
|
||
|
||
| 优先级 | 事项 |
|
||
|---|---|
|
||
| P0 | 配置质量告警 cron + 确认邮件送达 |
|
||
| P0 | 确认 agent1/agent2 上线流程和团队队列 SLA |
|
||
| P0 | 续期 WhatsApp token、固定公网域名 |
|
||
| P1 | Email/WhatsApp bridge AI 切流 |
|
||
| P1 | 真实邮件 ingest + 索引 |
|
||
| P1 | 商机币种 + productNeed 归一 |
|
||
| P1 | 数据备份自动化 |
|
||
| P2 | 告警看板、离线评测接 CI |
|
||
| P2 | PII 保留/删除策略 |
|
||
| P3 | A/B 实验、WhatsApp 模板/媒体 |
|
||
|
||
---
|
||
|
||
## 13. 附录:关键配置
|
||
|
||
### bridge 关键环境变量
|
||
|
||
```
|
||
LIBREDESK_BASE_URL
|
||
LIBREDESK_API_KEY
|
||
LIBREDESK_API_SECRET
|
||
LIBREDESK_WEBHOOK_SECRET
|
||
LIBREDESK_WEBHOOK_INBOX_IDS=1
|
||
LLM_BASE_URL / LLM_API_KEY / LLM_MODEL
|
||
RAG_PG_URL
|
||
EMB_BASE_URL / EMB_API_KEY / EMB_MODEL / EMB_DIM
|
||
SMTP_HOST / SMTP_PORT / SMTP_USER / SMTP_PASS / SMTP_FROM
|
||
TWENTY_BASE_URL / TWENTY_API_KEY
|
||
```
|
||
|
||
### 关键数据表
|
||
|
||
- `libredesk`:conversations、messages、automation_rules、webhooks
|
||
- `bridge`:bridge_ai_metrics、bridge_llm_cache、bridge_site_map_urls
|
||
- `products`(旧 bridge 库):kb_docs、kb_mail_docs
|
||
|
||
### 关键脚本
|
||
|
||
```
|
||
scripts/bootstrap.sh
|
||
scripts/rpc-tunnel.sh # 仅本地开发
|
||
scripts/public-https.sh # 仅本地联调
|
||
scripts/build-site-map.js
|
||
scripts/rebuild-kb-index.sh
|
||
scripts/e2e-widget-jwt.js
|
||
scripts/e2e-anon-otp.js
|
||
scripts/eval-offline.js
|
||
scripts/eval-live.js
|
||
scripts/quality-report.js
|
||
scripts/quality-alert.js
|
||
```
|
||
|
||
---
|
||
|
||
## 14. 变更记录
|
||
|
||
| 日期 | 变更 | 操作人 |
|
||
|---|---|---|
|
||
| 2026-10-23 | 初版上线文档 | 待填 |
|