Files
libredesk/docs/PLAN-bridge-tools-only.md
wangliang 39986f10f2 初始化 LibreDesk 本地实例部署仓库
- 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/
2026-10-29 13:24:13 +08:00

148 lines
11 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.
# 方案: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?