Files
crm-ai/docs/architecture.md

87 lines
4.2 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.
# 架构说明(新栈 · 方案 B)
> 2026-10-21 决策:完全新建,采用 **LibreDesk 内置 AI** 承接客户对话,bridge 收缩为业务工具/集成服务;Twenty 为全新独立实例。
## 1. 组件与职责
| 组件 | 技术 | 负责 | 不负责 |
|---|---|---|---|
| LibreDesk :9000 | Go 单二进制 + Vue | 渠道(Live chat / Email / WhatsApp*)、会话、坐席工作台、**AI Assistant 回复客户**、snippets RAG、内置 OTP、自动化、SLA/CSAT、报表 | 不访问业务库、不写 CRM |
| bridge :4100 | Node 24,零外部依赖 | 商品/订单/库存查询、Twenty 商机写入、身份头二次校验;后续承载质量旁路(指标/评估/飞轮) | 不保存会话、不生成客户回复 |
| Twenty :3100 | NestJS + React | 公司/联系人/商机/备注/任务 | — |
| 业务 RPC | Hyperf JSON-RPC over TCP | 商品推荐、订单、库存/ETA、会员 | — |
| imap-id-proxy | Node 24 | 给 LibreDesk 的 IMAP 连接注入 ID 命令,兼容 163 | 仅本地 POC |
\* WhatsApp 需 LibreDesk v2.9 RC;当前镜像 `v2.9.0-rc.10`。
## 2. 数据流
```
访客(widget / 邮件 / WhatsApp)
│
▼
LibreDesk 创建会话 → Automation 分配给 AI Assistant
│
├─ snippets 向量检索(知识库)
├─ 需要业务数据 → POST http://bridge:4100/tools/<name>
│ ├─ 平台注入 X-Libredesk-Contact-* / Conversation-UUID / Inbox-Id
│ ├─ 工具配置里带 X-Tools-Key
│ └─ 返回扁平 JSON
└─ 无法处理 / 超 max turns / 超时 → handoff 到兜底团队
```
### 工具调用与验证
- **身份来源**:LibreDesk 服务端注入 `X-Libredesk-Contact-Email`、`X-Libredesk-Contact-Verified`,模型不可见/不可改。
- **平台侧验证**:工具设置 `requires_verification=true`;平台先让客户邮箱收码,通过后才调用。
- **服务端二次校验(fail-closed)**:bridge 仍检查 `verified === true`,否则 403。
- **邮箱作用域**:订单/商机工具的邮箱只取身份头,忽略参数;订单号先按邮箱反查再匹配(防 IDOR)。
### CRM 写入
`create_opportunity` 一次完成:按邮箱找 Person → 查重(已有商机直接返回 `created:false`)→ 公司同名复用/创建 → 建 Opportunity → 备注(公司/联系人/需求/渠道)→ 3 天跟进任务。
## 3. 端口与隔离
| 资源 | 新栈 | 旧栈(crm-ai-demo) |
|---|---|---|
| LibreDesk / Chatwoot | 9000 | 3001 |
| Twenty | 3100 | 3000 |
| bridge | 4100 | 4000 |
| Postgres | localhost:5440 | localhost:5432 |
| Redis | localhost:6390 | localhost:6379 |
新栈 Postgres 内含三个库:`libredesk` / `twenty` / `bridge`;Redis 分 db:LibreDesk=2、Twenty=1、bridge=3。
## 4. 为什么选 B(以及代价)
选择理由:代码量最少、维护面最小、直接获得平台渠道/工作台/OTP/CSAT;bridge 只保留无法内建的业务与质量能力。
已知代价(相对旧 bridge 编排):
- RAG:纯向量 snippets,无 hybrid/rerank/翻译兜底
- 缺情绪识别、3 级升级策略(用 max turns + fallback team 近似)
- 缺引用打分/幻觉检测、离线评估、数据飞轮、A/B、注入防护(可后续在 bridge 做 webhook 旁路补齐)
- LibreDesk AI 仍是 beta
## 5. 后续补齐路径(bridge 质量旁路)
LibreDesk webhook(`message.created` / `conversation.*`)可推给 bridge,bridge 做只读分析并回写标签/备注/告警:
1. 指标:延迟、工具调用、升级率 → `bridge` 库
2. 引用/幻觉:比对 assistant 回复与命中 snippets(需 LibreDesk 侧接口或日志)
3. 评估:golden 问题 → assistant preview API
4. 飞轮:低分会话 → 人工标注 → snippets 回流
注意:LibreDesk webhook **无重试、5s 超时**,bridge 必须立即 ACK + 异步处理,并加轮询补偿。
## 6. 环境变量
见 `../.env.example`。要点:
| 变量 | 作用 |
|---|---|
| `TOOLS_SHARED_KEY` | LibreDesk 工具 Header 与 bridge 共享密钥 |
| `TOOLS_PUBLIC_BASE_URL` | compose 内固定 `http://bridge:4100` |
| `TWENTY_*` | Twenty 连接 + API key(首次注册后填) |
| `RECOMMEND_URL` / `ORDER_API_URL` / `INVENTORY_API_URL` | 业务 RPC |