- docker compose 部署:app / db / redis / tls(nginx) / bridge-tools,宿主端口错开避免与本机服务冲突 - bridge-tools 内联进仓库(compose build 路径改为 ./bridge-tools),仓库自包含可部署 - 部署说明 README、crm-new 对照与 bridge-tools 方案文档、备份与隧道脚本 - .gitignore 排除 .env、config.toml、uploads/、tls 私钥/证书、backups/、logs/
148 lines
11 KiB
Markdown
148 lines
11 KiB
Markdown
# 方案:bridge 只保留 tools,其余用 LibreDesk 内置能力
|
||
|
||
> 2026-10-28 评估。依据:LibreDesk v2.9.1 源码(`internal/aiagent/`、`internal/ai/tools.go`、`schema.sql`)+ crm-new 运行数据。
|
||
> 结论:**可行**,而且 LibreDesk 内置能力比预期多——bridge 可以从 11 个工具收缩到 4–6 个业务工具。
|
||
|
||
## 0. 已确认的决策(2026-10-28)
|
||
|
||
| 决策点 | 结论 |
|
||
| --- | --- |
|
||
| bridge-tools 部署 | **方案 A**:并入本实例 compose(服务名 `bridge-tools`,同 `libredesk` 网络) |
|
||
| `create_opportunity`(Twenty) | **先不留** |
|
||
| `search_email_history` / `collect_info` | **先删** |
|
||
| 程序化输出护栏 | **先接受降级**(后续用 LibreDesk webhook 外采质量指标) |
|
||
| `get_customer_info` | **保留**(业务需要) |
|
||
| 保留工具清单 | `search_products` / `search_orders` / `search_inventory` / `get_customer_info` |
|
||
|
||
## 1. 关键证据:LibreDesk v2.9.1 已经内置了什么
|
||
|
||
AI agent 每次回复时自动注册的内置工具(`internal/aiagent/worker.go:290-314`):
|
||
|
||
| 内置工具 | 作用 | 对应 crm-new bridge 的什么 |
|
||
| --- | --- | --- |
|
||
| `search_knowledge_base` | 检索 snippets + 帮助中心文章(向量),支持引用计数 | `search_kb`(bridge 的 pgvector RAG) |
|
||
| `handoff`(`handoff_enabled`) | 转人工(`fallback_team_id`) | `handoff_to_human` |
|
||
| `get_previous_conversations` | 拉该客户近 N 天其他会话 | `search_email_history`(部分覆盖) |
|
||
| `send_email_verification` | 发 OTP 到联系人邮箱(走通知邮箱 SMTP;Redis 存码,10 分钟有效,30 分钟验证态) | `send_verification_code` |
|
||
| `check_email_verification` | 校验 OTP,3 次尝试上限、重发上限 | `verify_email_code` |
|
||
| `set_contact_email` | 访客改邮箱后再发码 | (bridge 无对应,新增能力) |
|
||
| `resolve` | 结束时给会话打结果 | 无 |
|
||
|
||
其他内置:
|
||
|
||
- **工具调用上下文自动注入**(`internal/ai/tools.go:250-270`):`X-Libredesk-Contact-Id` / `-External-Id` / `-Type` / `-Email` / `-Verified` / `X-Libredesk-Conversation-UUID` / `X-Libredesk-Inbox-Id` —— bridge 的多站点路由(sites.json)和身份判断可以直接用这些头,不再需要自己发验证 token。
|
||
- **工具级验证开关** `ai_tools.requires_verification`:不验证的客户调私有数据工具会被拦,并引导模型走内置 OTP 流程(`tools.go:186`)。
|
||
- **工具鉴权** `ai_tools.auth`(自定义 header,支持加密存储):bridge 的 shared key 直接配在工具上。
|
||
- **AI 助手配置**:instructions / guardrails / expectation / tone / response_length / max_turns / fallback_team_id / handoff_enabled / citations_enabled / languages / enabled。
|
||
- **知识库**:`ai_knowledge_base`(snippet 类)+ 帮助中心文章都会作为 embedding 源(`internal/ai/embedsource.go`)。
|
||
- **Widget 身份**:inbox secret 的 JWT 校验(`cmd/chat.go`),站点后端签 JWT 即可,不需要 bridge 的 identity 服务。
|
||
- **通知邮件 / OTP 发信**:`notification.email.*`(crm-new 里就是 163 SMTP)。
|
||
|
||
## 1.5 落地进度
|
||
|
||
| 期 | 状态 | 说明 |
|
||
| --- | --- | --- |
|
||
| P0 root_url / timezone | ✅ 完成 | `root_url=https://192.168.31.61:9443`、`timezone=Europe/Berlin`(API 已写入并回读) |
|
||
| P0 SMTP / embedding key | ✅ 完成 | 复用 crm-new 的 163 SMTP(smtp.163.com:465 TLS)和 DashScope key;completion 实际用 **qwen-max**(见下) |
|
||
| P2 瘦身 bridge | ✅ 完成 | `bridge-tools/`(零第三方依赖,4 个工具,9 个单测通过),已并入 compose 并 healthy |
|
||
| P3 工具注册 | ✅ 完成 | LibreDesk `ai_tools` 已注册 4 个,`search_orders`/`get_customer_info` 带 `requires_verification` |
|
||
| P1 帮助中心/assistant | ✅ 完成 | Team「Wholesale Support」+ 帮助中心(108 篇,已嵌入)+ Assistant「Yehwang Assistant」(4 个工具、fallback team、handoff/citations 开);预览已能基于文章回答并返回 sources |
|
||
| P4 渠道 | 🟡 部分完成 | **Website livechat 已建 + 自动化分配到 Assistant + 端到端验证通过**(含 OTP → search_orders);email / WhatsApp 待做 |
|
||
|
||
### ⚠️ 模型选择的关键发现
|
||
|
||
`qwen-plus-latest` / `qwen-plus` 在 LibreDesk 这套较长的 system prompt 下**不会调用工具**(实测 tool_calls=0),直接凭模型自身知识作答,还会编造 `[[cite:45]]` 这种不存在的引用(第一次预览回答「30 天退货」,而知识库实际是「非质量问题不退,质量问题 7 天内」)。
|
||
换成 **`qwen-max`** 后工具调用正常(sources 命中 5 篇,score 0.33–0.61),回答与知识库一致。因此 completion 配置为 `qwen-max`;如果以后换模型,务必用「退货政策/预购时效」这类问题验证是否会调用 `search_knowledge_base`。
|
||
|
||
## 2. bridge 收缩后保留什么
|
||
|
||
| crm-new 现有工具 | 处理 | 说明 |
|
||
| --- | --- | --- |
|
||
| `search_products` | **保留** | 业务 RPC 商品搜索,LibreDesk 无替代 |
|
||
| `search_orders` | **保留**(`requires_verification=true`) | 私有数据,用内置 OTP 把关 |
|
||
| `search_inventory` | **保留** | 库存/ETA |
|
||
| `get_customer_info` | 保留(可选) | 若 Twenty 客户资料要查;也可并进 orders |
|
||
| `create_opportunity` | 保留(可选) | Twenty 商机写入,LibreDesk 无替代;不做 CRM 则去掉 |
|
||
| `search_kb` | **删除** | 用内置 `search_knowledge_base`;108 篇帮助文章已在 LibreDesk 里 |
|
||
| `search_email_history` | 先删 | 内置 `get_previous_conversations` 覆盖「本系统内历史」;旧邮件库不再接入 |
|
||
| `collect_info` | 先删(可选保留) | lead 槽位采集改为 assistant 指令 + 联系人自定义属性;要做销售漏斗再保留 |
|
||
| `handoff_to_human` | **删除** | 内置 handoff + fallback_team_id |
|
||
| `send_verification_code` | **删除** | 内置 OTP 工具 |
|
||
| `verify_email_code` | **删除** | 内置 OTP 工具 |
|
||
|
||
**结果:bridge = 一个只暴露 3–5 个 HTTP 工具的瘦服务**(+ 多站点配置、RPC 客户端、Twenty 客户端、shared key 鉴权、健康检查)。
|
||
|
||
## 3. 明确会被「降级」的能力(要接受或后补)
|
||
|
||
| 现有能力 | 用内置后的状态 | 建议 |
|
||
| --- | --- | --- |
|
||
| 程序化输出护栏(URL 白名单、价格/库存数字校验、幻觉重写) | **没有等价物**;只有 assistant 的 `guardrails` 提示词约束 | 先接受(低流量验证);需要时用 LibreDesk webhook → 独立质量服务补 |
|
||
| 质量飞轮 / 指标 / 日报 / 引用检查 / A-B | 无等价物;LibreDesk 只有基础报表 | 后续用 webhook 采集到外部(bridge 加一个 consumer,不做实时改回复) |
|
||
| 旧 bridge Hybrid RAG(parent-child + 向量 + 全文 + RRF + rerank) | 退化为向量 top-k(snippets + 文章) | 用真实问题跑检索评测对比;不满意可把 snippet 切细或补 FAQ |
|
||
| 邮件历史检索(旧 `kb_mail_docs`) | 只覆盖 LibreDesk 内会话 | 需要历史邮件时再做离线 ingest |
|
||
| lead 槽位(Redis 跨轮) | 没有 | 用 assistant instructions + 自定义属性;或保留 `collect_info` 工具 |
|
||
|
||
## 4. 实施分期
|
||
|
||
### P0 前置(0.5h)
|
||
|
||
- 配置 `notification.email.*`(OTP + 通知都依赖它,必须有可用 SMTP);
|
||
- AI provider:completion + **embedding**(内置 KB 检索依赖 embedding,必须配);
|
||
- 修 `root_url`、`timezone`(见时区方案)。
|
||
|
||
### P1 LibreDesk 内置能力配置(2–4h)
|
||
|
||
1. 帮助中心 + 108 篇文章(从 crm-new 导出后导入,或按原源重灌);
|
||
2. 需要时补 snippets(FAQ 短答案);
|
||
3. AI assistant:instructions / guardrails / tone / max_turns / languages / citations / fallback_team_id / handoff_enabled;
|
||
4. 团队(Wholesale Support)+ 自动化规则(AI 分配、邮件/WhatsApp 转人工)。
|
||
|
||
验收:AI 能基于帮助中心回答并带引用;越界/复杂问题按 fallback_team 转人工;OTP 流程能发码、验码(先用 livechat 访客验证)。
|
||
|
||
### P2 瘦身 bridge(0.5–1d)
|
||
|
||
- **新建目录 `bridge-tools/`(从 `crm-new/bridge` 裁剪,不改 crm-new 本身)**,保留:
|
||
`server.js`(只留工具路由 + healthz)、`tools.js`(裁剪)、`rpc.js`、`product-query.js`、`sitemap.js`、`opportunity.js` / `twenty.js`(若保留)、`redis.js`、`auth.js`、`config.js`、`security.js` + 对应测试;
|
||
- 删除:agent.js、prompts.js、llm*.js、rag.js、kb-*.js、embedding.js、reranker.js、verification.js、smtp.js、identity.js、jwt.js、libredesk-webhook.js、metrics/quality/citation-checker/output-guard/flywheel/audit/experiments/trace 等;
|
||
- 依赖精简:PG 可去掉(若不做 lead/质量库),Redis 保留(RPC 缓存/限流);
|
||
- 单测裁剪后必须 `npm test` 通过。
|
||
|
||
验收:`/healthz` 正常;5 个工具逐个用 curl + shared key 调通;容器内存/镜像明显变小。
|
||
|
||
### P3 工具注册到 LibreDesk(2–4h)
|
||
|
||
- 适配 `register-tools.js`:URL 指向 `bridge-tools:4100`,`auth` 带 shared key header;
|
||
- `search_orders` / `create_opportunity` 设 `requires_verification=true`;
|
||
- 绑定 assistant 的 tool allowlist;
|
||
- 多站点:`X-Libredesk-Inbox-Id` 映射 sites.json(不需要改协议,LibreDesk 已经带)。
|
||
|
||
验收:livechat 里问「查订单」→ 触发 OTP → 验码后返回订单;问商品 → 返回价格/库存/链接。
|
||
|
||
### P4 渠道(2–4h)
|
||
|
||
- Live Chat inbox + widget(站点用 inbox secret 签 JWT 做身份锚定);
|
||
- Email inbox(决定用 163 走 imap-proxy,还是换企业邮箱直连);
|
||
- WhatsApp(依赖公网域名/隧道,单独排期)。
|
||
|
||
### P5 公网/运维/质量(按需)
|
||
|
||
- 固定域名 + 证书 + public-gateway 白名单;
|
||
- 备份定时化、监控、smoke/e2e、上线文档;
|
||
- 若需要质量护栏:LibreDesk webhook → 轻量质量服务(不改 AI 回复,只记指标)。
|
||
|
||
## 5. 风险与前提
|
||
|
||
- **SMTP 必须可用**:内置 OTP 依赖通知邮箱,livechat 访客验证走它;没有就会卡住「查订单」这类工具。
|
||
- **embedding provider 必须配**:内置 KB 检索是向量检索,缺 key 时 `search_knowledge_base` 不可用。
|
||
- **RPC 网络**:bridge-tools 仍需要访问 yehwang RPC(crm-new 是靠外部网络 `spug-net`),新 compose 要接同一网络或走隧道。
|
||
- **内置 OTP 的边界**:只对「email 渠道会话」或「非 contact 类型联系人(访客)」提供;已存在且非访客的 contact 不会自动有 OTP 工具(`worker.go:308`),要确认业务场景。
|
||
- **检索质量下降**:内置 top-k vs 旧 hybrid;上线前用 20–30 个真实问题对比命中率。
|
||
- **两套并存**:bridge-tools 与 crm-new bridge 可共用 RPC/Redis 配置,但建议独立 redis db 和独立 shared key。
|
||
|
||
## 6. 需要拍板
|
||
|
||
1. `create_opportunity` / Twenty 商机要不要保留?(决定 bridge 留 3 个还是 5 个工具)
|
||
2. `search_email_history`、`collect_info` 先删还是保留?
|
||
3. 程序化输出护栏:先接受降级,还是一开始就按 webhook 方案补?
|
||
4. bridge-tools 部署位置:同一台机新 compose,还是并到本实例 compose?
|