Files
crm-ai/docs/runbook.md

205 lines
8.7 KiB
Markdown
Raw Permalink 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.
# 运维手册(crm-new)
## 启动 / 停止
```bash
cd /home/dev/code/crm-new
# 启动(生成 .env / 渲染配置 / 构建 bridge / 等健康)
bash scripts/bootstrap.sh
# 只启动,不重新生成
docker compose up -d
# 停止(保留数据)
docker compose down
# 停止并删除数据(危险:会清空 LibreDesk/Twenty/业务库)
# docker compose down -v
```
## 状态与日志
```bash
docker compose ps
docker compose logs -f --tail=100 libredesk
docker compose logs -f --tail=100 twenty-server
docker compose logs -f --tail=100 bridge
# 健康
curl -s http://localhost:9000/health
curl -s http://localhost:3100/healthz
curl -s http://localhost:4100/healthz
```
## 内容与 AI 配置脚本
```bash
# 导入/更新知识库(帮助中心文章,幂等)
node scripts/import-kb-helpcenter.js --dry-run
node scripts/import-kb-helpcenter.js
# 配置 DashScope(Completion + Embedding,自动触发重建向量)
node scripts/configure-ai.js
# 验证 RAG + 引用(创建临时助手跑 preview 后自动删除)
node scripts/verify-rag.js "What is the minimum order value?"
# 注册 4 个业务工具
node scripts/register-tools.js
# 创建/更新默认 Inbox + Assistant + Automation(幂等)
node scripts/setup-defaults.js
# Twenty:创建初始 workspace + 在库内生成 API key(不走 UI)
node scripts/twenty-bootstrap.js
# 有旧 bridge 时:重建 KB parent-child 索引(自动备份)
bash scripts/rebuild-kb-index.sh
# 没有旧 bridge 时:直接导入 KB 快照(测试/生产常用)
bash scripts/import-kb-snapshot.sh
# 或指定目标库:TARGET_PG_DB=products bash scripts/import-kb-snapshot.sh
# 从 sitemap 生成类目 KB
node scripts/build-site-kb.js
# KB 审计
RAG_PG_URL=postgres://crmnew:<password>@127.0.0.1:5440/bridge node scripts/kb-audit.js
# KB 备份列表 / 回滚
RAG_PG_URL=postgres://crmnew:<password>@127.0.0.1:5440/bridge node scripts/kb-version.js list
RAG_PG_URL=postgres://crmnew:<password>@127.0.0.1:5440/bridge node scripts/kb-version.js rollback kb_docs_v...
# 在线 FAQ 同步 + 重建 KB(不依赖旧 bridge)
# 宿主机执行时 RAG_PG_URL 用 127.0.0.1:5440/bridge
RAG_PG_URL=postgres://crmnew:<password>@127.0.0.1:5440/bridge node scripts/sync-kb-online.js
# 仅用本地 bridge/kb 重建
node scripts/sync-kb-online.js --local-only --force
# 从当前环境重新生成快照(可选)
bash scripts/export-kb-snapshot.sh
# 全量商品页站点地图(官网 sitemap → bridge 库)
node scripts/build-site-map.js www us
# Prometheus 指标
curl -s http://127.0.0.1:4100/metrics
# AI 质量日报(最近 24 小时;可传小时数)
node scripts/quality-report.js 24
# 质量告警(默认最近 1 小时;--dry-run 只打印不发邮件)
node scripts/quality-alert.js 1 --dry-run
# 建议 cron:
# */30 * * * * cd /home/dev/code/crm-new && node scripts/quality-alert.js 1 >> logs/quality-alert.log 2>&1
# 离线回归评测(确定性逻辑,不调 LLM)
node scripts/eval-offline.js
# RAG 检索评测
RAG_PG_URL=postgres://... node scripts/eval-retrieval.js
# 真实模型离线评测(fake LibreDesk,不写真实会话;会调 LLM/RPC)
node scripts/eval-live.js
# 公网 HTTPS(仅本地联调需要):Cloudflare Quick Tunnel + 路径白名单网关
# 测试/生产:不要跑这个脚本,使用正式域名 + Ingress/Nginx + TLS
bash scripts/public-https.sh
# 仅本地开发:测试服 RPC 端口外网被封时建 SSH 隧道
# 测试/生产:不要跑这个脚本,直接把 RPC URL 配成内网可达地址
bash scripts/rpc-tunnel.sh --apply
# 配置 163 SMTP(自动重启 LibreDesk)
node scripts/configure-email.js
# 配置 Email 渠道(163 收件走 imap-proxy + 默认外发模板 + AI 自动分配)
node scripts/add-email-inbox.js
# 本地静态测试页(widget 接入演示)
bash scripts/serve-web.sh # http://localhost:8088/demo.html
# 端到端验证 widget JWT(登录用户可查订单)
node scripts/e2e-widget-jwt.js "Can you check the status of my order SO-1?"
# 端到端模拟 widget 访客对话(等待 AI 回复)
node scripts/e2e-widget.js "What is the minimum order value?"
```
## 冒烟
```bash
bash scripts/smoke.sh
```
## 常用运维操作
```bash
# 修改 bridge 代码后
docker compose up -d --build bridge
# 修改 .env 后(如 Twenty API key)
docker compose up -d --force-recreate bridge
# 修改 LibreDesk 配置模板后
node scripts/render-config.js && docker compose up -d --force-recreate libredesk
# 备份数据库
docker exec crmnew-postgres pg_dump -U crmnew -d libredesk > backups/libredesk-$(date +%F).sql
docker exec crmnew-postgres pg_dump -U crmnew -d twenty > backups/twenty-$(date +%F).sql
# 备份 Twenty 文件存储
docker run --rm -v crm-new_twenty-data:/data -v "$PWD/backups":/backup alpine \
tar czf /backup/twenty-data-$(date +%F).tar.gz -C /data .
```
## 镜像升级(LibreDesk)
```bash
# 1. 备份
docker exec crmnew-postgres pg_dump -U crmnew -d libredesk > backups/libredesk-before-upgrade.sql
# 2. 修改 .env 的 LIBREDESK_IMAGE 后重建
docker compose up -d --force-recreate libredesk
# 3. 容器启动命令会自动执行 --upgrade;确认日志
docker compose logs --tail=50 libredesk
```
## 回滚
```bash
# 切回稳定版
sed -i 's#^LIBREDESK_IMAGE=.*#LIBREDESK_IMAGE=libredesk/libredesk:latest#' .env
docker compose up -d --force-recreate libredesk
# 跨大版本回滚数据库需恢复备份(升级前 pg_dump)
```
## 端口冲突排查
```bash
ss -ltnp | grep -E ':(9000|3100|4100|5440|6390)\s'
```
## 已知坑
| 现象 | 原因 | 处理 |
|---|---|---|
| 容器启动报 `database "xxx" does not exist` | 首次初始化脚本未执行 | `docker exec crmnew-postgres psql -U crmnew -d postgres -c 'CREATE DATABASE xxx;'` |
| bridge 健康检查 `connection refused` | 容器内 `localhost` 解析到 IPv6 | 健康检查固定用回环地址(避免 IPv6) |
| LibreDesk 反复重启 | System 密码不满足强度(10–72 位、大小写+数字+特殊字符) | 改 `.env` 的 `LIBREDESK_SYSTEM_USER_PASSWORD` 后重建 |
| 工具 401 | `X-Tools-Key` 与 `TOOLS_SHARED_KEY` 不一致 | 核对 `.env` 与 LibreDesk 工具 Header |
| 工具 403 verification_required | 联系人未验证 | 先走平台 OTP 验证,或该工具不需要验证时关闭 `requires_verification` |
| Twenty API 调用失败 | `TWENTY_API_KEY` / workspace 未配置 | 在 Twenty 后台创建 API key 填 `.env` 后重建 bridge |
| 163 邮箱报 `Unsafe Login` | LibreDesk 的 go-imap 不发 IMAP ID | 已加 `imap-id-proxy`,email inbox 的 IMAP host 指向 `imap-proxy:1993`,`tls_type=none` |
| 管理员后台实时更新不工作 | 通过 http + IP 访问时 agent websocket 拒绝非 HTTPS 来源 | POC 可忽略;生产用 HTTPS 或经 localhost 访问 |
| collect_info 槽位丢失 | Redis 不可用,退回了进程内存 | 检查 `REDIS_URL=redis://redis:6379/3` 和 `docker logs crmnew-bridge` 的 lead store 告警 |
| 多站点商品推荐串站 | `bridge/config/sites.json` 的 inbox 映射没配 | 把对应 inbox 数字 ID 指到 us/eu/www profile,重建 bridge |
| WhatsApp webhook 收不到 | 没有公网 HTTPS / Meta 回调地址不对 | 本地联调跑 `bash scripts/public-https.sh`;测试/生产使用正式域名,不要用 Quick Tunnel |
| 公网访问到管理后台 | 网关白名单配置 | `services/public-gateway` 只放行 `/webhooks/whatsapp/*`、`/hc/*`、`/widget*`、`/static/public/*`,其余 404 |
| AI 回复"系统暂时无法查询订单" | RPC 不可达,bridge 8s 超时 | 本地开发跑 `bash scripts/rpc-tunnel.sh --apply`;测试/生产检查内网 RPC 地址/网络策略,不要用开发机隧道 |
| WhatsApp 真实消息收不到,但 Meta "Send to My Server" 测试事件能到 | WABA 级 `override_callback_uri` 优先于 App 级 callback,且 Meta 对 override 的验证常返回 403(与目标 URL 无关) | `GET /<WABA_ID>/subscribed_apps` 确认 override;`DELETE /<WABA_ID>/subscribed_apps` 后重新 `POST`(不带 override)清掉,确认 App 级 callback 指向目标域名,再发真实消息验证 |
| 多个栈共用同一个 WhatsApp 号,消息被旧环境接走(旧环境 AI 回复、新环境无日志) | crm-new 与旧 crm-ai-demo 配置了同一 `WA_PHONE_NUMBER_ID` / WABA,旧栈 tunnel 仍在接收 | 停旧栈 WhatsApp 接收(停旧 tunnel / 禁用旧 inbox),或给新环境申请独立测试号;不要让两套同时接同一个号 |
| 新建 WhatsApp inbox 后 webhook 验证 403 `verify token mismatch` | 创建接口传入的 `webhook_verify_token` 可能未真正生效,inbox 仍是默认值;`GET /api/v1/inboxes/<id>` 返回的是掩码值,不能用来核对 | 用 `PUT /api/v1/inboxes/<id>` 带完整 config 重新保存一次,再请求 `GET /webhooks/whatsapp/<id>?hub.mode=subscribe&hub.verify_token=...&hub.challenge=...` 确认返回 200 |