# 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 ``` --- ## 3. 访问入口 | 服务 | 地址 | 备注 | |---|---|---| | LibreDesk | `http://192.168.31.61:9000` | 管理端 / 工作台 | | Twenty CRM | `http://192.168.31.61:3100` | CRM | | bridge | `http://192.168.31.61:4100` | 内部工具/健康检查 | | Widget 测试页 | `http://192.168.31.61:8088/demo.html` | 本机测试用 | | 公网入口 | `.env` 的 `PUBLIC_BASE_URL` | Cloudflare Quick Tunnel,**URL 会变** | | Postgres | `127.0.0.1:5440` | 仅本机 | | Redis | `127.0.0.1:6390` | 仅本机 | | IMAP proxy | `127.0.0.1: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 隧道可用(商品/订单/库存) - [ ] LibreDesk webhook `Bridge AI` 为启用状态 - [ ] LibreDesk 规则 1 关闭 - [ ] 规则 4/5 指向 `Wholesale Support` - [ ] agent1/agent2 可登录,必要时设为在线 - [ ] WhatsApp access token 未过期(当前 token 有到期时间) - [ ] 公网 URL 与 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 数据准备 ```bash # 全量商品页站点地图(每周/商品大更新后) node scripts/build-site-map.js www us # 重建 KB parent-child 索引(KB 更新后;会先备份旧表) bash scripts/rebuild-kb-index.sh # 旧 KB 补 text_tsv/parent_id(已执行过,幂等) node scripts/upgrade-kb-schema.js ``` ### 6.4 RPC 隧道 商品/订单/库存依赖本机到内网的 RPC 隧道: ```bash bash scripts/rpc-tunnel.sh ``` 隧道断了会导致 `search_products/search_orders/search_inventory` 失败。 ### 6.5 公网 HTTPS / WhatsApp webhook ```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://127.0.0.1:4100/healthz curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1: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 名称为 ` — ` - 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 隧道进程 - 163 SMTP/IMAP - WhatsApp token 剩余有效期 - Cloudflare tunnel 状态 - 未分配/团队队列积压 --- ## 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 隧道,断了商品/订单/库存工具不可用。 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 | 初版上线文档 | 待填 |