Files
crm-ai/docs/libredesk-setup.md

237 lines
10 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.
# LibreDesk 后台配置步骤
> 面向 `crm-new` 全栈(方案 B:LibreDesk 内置 AI 回复客户)。
> 本栈已通过 `scripts/setup-defaults.js` 自动建好 Inbox / Assistant / Automation;本文用于手工核对或重建。
> 登录:用户 `System`,密码见 `.env` 的 `LIBREDESK_SYSTEM_USER_PASSWORD`。
## 0. 前置检查
```bash
bash scripts/bootstrap.sh # LibreDesk 已启动
bash scripts/start-tools.sh # 另开终端,tools 服务 :4010
curl -s http://localhost:4100/healthz
```
## 1. AI Provider(必须先配)
`Admin → AI → Providers`,两个 provider 都要配(LibreDesk 要求 OpenAI 兼容端点):
| 项 | Completion | Embedding |
|---|---|---|
| Base URL | `https://dashscope.aliyuncs.com/compatible-mode/v1` | 同左 |
| API Key | DashScope key(与旧项目 `kb.config.json` 同一个) | 同左 |
| Model | `qwen-plus-latest` | `text-embedding-v4` |
| Dimensions | — | **1024**(必须与模型输出一致,否则报维度不匹配) |
| Temperature | 0.3 | — |
| Max tokens | 800 | — |
点 **Test connection** 两个都通过再继续。改 embedding 模型/维度会自动重新嵌入全部 snippets。
成本上限在 `config/config.toml` 的 `[ai_agent]`:`max_steps`、`max_history_messages`、`worker_count`。
## 2. 知识库(帮助中心文章)
本栈已把旧 `customer-service-kb` 导入为**帮助中心文章**(而不是 snippets),原因:只有文章能被 AI 引用(`[[cite:id]]`),并且同时进入帮助中心站内搜索。
公开地址:`http://localhost:9000/hc/yehwang-help/en`(1 个帮助中心 / 9 个 collection / 108 篇文章,全部 `published + ai_enabled`)。
重新导入(幂等):
```bash
cd /home/dev/code/crm-new
node scripts/import-kb-helpcenter.js --dry-run # 只解析
node scripts/import-kb-helpcenter.js # 登录 System 并导入
```
以下为 LibreDesk 原生 snippets 的用法(内部/敏感内容才用):
1. **手工**:一条 Q&A 一个 snippet,正文写完整答案(不要写片段)
2. **Import from URL**:抓取官网 FAQ 页面
3. **API 批量导入**(迁移旧 KB 时用):
```bash
curl -X POST http://localhost:9000/api/v1/ai/snippets \
-H "Authorization: token ${LIBREDESK_API_KEY}:${LIBREDESK_API_SECRET}" \
-H 'Content-Type: application/json' \
-d '{"title":"Minimum order","content":"The minimum order value is €30.","enabled":true}'
```
迁移建议:旧 `customer-service-kb/*.md` 按 `### Q:` 切块,标题用问题,正文用答案,逐条 POST。Import from URL 走 `POST /api/v1/ai/snippets/import-url`。
> RAG 差异:LibreDesk 是 **纯向量 top-k**,没有旧 bridge 的「向量+全文+RRF+rerank+翻译兜底」。EU 语种召回需要用真实问题抽检。
## 3. 注册业务工具
### 方式 A:自动(推荐)
1. `Admin → Teammates → System → API Key` 生成 key/secret,填进 `.env`:
```
LIBREDESK_API_KEY=...
LIBREDESK_API_SECRET=...
```
2. 执行:
```bash
node scripts/register-tools.js
```
### 方式 B:手工
`Admin → AI → Tools → New tool`,4 个工具按下面填:
| 字段 | search_products | search_orders | search_inventory | create_opportunity |
|---|---|---|---|---|
| URL | `http://bridge:4100/tools/search_products` | `.../search_orders` | `.../search_inventory` | `.../create_opportunity` |
| Method | POST | POST | POST | POST |
| Header | `X-Tools-Key: <TOOLS_SHARED_KEY>` | 同 | 同 | 同 |
| Parameters | 见 `GET /tools/manifest` | 同 | 同 | 同 |
| Require verified contact | 否 | **是** | 否 | **是** |
| Copilot / Generate reply | 开 | 开 | 开 | 开 |
| Require agent approval | 否 | 否 | 否 | 否 |
`GET http://localhost:4100/tools/manifest`(带 `X-Tools-Key`)会输出每个工具的完整 JSON Schema,可直接复制。
## 4. 创建 AI Assistant
`Admin → AI → Assistants → New assistant`:
| 项 | 建议值 |
|---|---|
| Name | `Yehwang Assistant` |
| Tone / Length | Friendly / Concise |
| Languages | English, Dutch, German, French, Spanish, Italian(留空=跟随客户) |
| Max turns | 8–10 |
| Fallback team | `Support`(先建团队) |
| Offer handoff | 开 |
| Tools | 勾选上一步的 4 个工具 |
**Instructions 草稿(可直接改)**:
```
You are the Yehwang B2B customer assistant for stainless-steel jewelry wholesale.
- Always reply in the customer's language.
- For product questions call search_products; never invent catalog items.
- For order questions call search_orders. If the result says verification is required,
ask the customer to verify their email with the one-time code, then retry.
- For stock questions call search_inventory with the SKU digits.
- When you have company + contact name + product/need, call create_opportunity once.
- Never quote prices, discounts or stock that did not come from a tool result.
- If you cannot help or the customer asks for a human, hand off to the Support team.
```
**Guardrails**:
```
Never reveal another customer's data. Never promise discounts above the published tiers.
Never create an opportunity before the contact is verified.
```
> AI Assistant 目前是 **beta**,官方建议先在低流量 inbox 验证。
## 5. 自动路由(关键)
Assistant **只有被分配给会话才会回复**。配置:
`Admin → Automations → New rule`
- 触发:`new_conversation`
- 条件:`inbox = Live chat`(如需只处理工作时间,再加 business hours 条件)
- 动作:`assign_user` → `Yehwang Assistant`
可选第二条规则:`conversation_update` + `status = Resolved` → 发送 CSAT。
人工一旦在会话里回复,assistant 会自动 handoff 并取消分配。
## 6. Live Chat Inbox 与 Widget
1. `Admin → Inboxes → New inbox → Live chat`
- Name:`Website`
- Brand / Website URL:`https://www.yehwang.com`
2. **Security** 标签:生成 widget **Secret key**(用于签 JWT,绝不能放前端)
3. **Installation** 标签复制 snippet:
```html
<script>
window.LibredeskSettings = {
baseURL: 'http://localhost:9000',
inboxID: 'YOUR_INBOX_UUID'
};
</script>
<script async src="http://localhost:9000/widget.js"></script>
```
### 登录用户身份锚定(已实现)
bridge 提供 `POST /identity`:站点 JWT → member RPC 取邮箱 → 用 inbox secret 签 LibreDesk widget JWT。
本地 POC 也可用 `IDENTITY_DEV_MODE=true` 直接传 email 生成。前端拿到 `userJWT` 后传给 widget。
### 原始说明(LibreDesk 侧)
已在网站登录的客户,服务端用 inbox Secret 签 HS256 JWT 传给 `userJWT`:
```js
// 服务端(Node 示例,密钥只在服务端)
const payload = {
external_user_id: String(user.id), // 与旧栈 yw_uid 对齐
email: user.email, // 这才是可信邮箱
first_name: user.firstName,
last_name: user.lastName,
contact_custom_attributes: { site: 'www', locale: user.locale },
exp: Math.floor(Date.now() / 1000) + 3600
};
// HS256(payload, inboxSecret) → window.LibredeskSettings.userJWT
```
多站点(www / US)建两个 livechat inbox,各自 widget + secret;联系人按 email 全局共享,注意隐私口径。
参考 `us-site/ai-snippet.js`(旧栈 Chatwoot 版)需要改写的点:`$chatwoot.setUser` → `userJWT`,`setCustomAttributes` → `contact_custom_attributes`。
## 7. Email Inbox(可选)
`Admin → Inboxes → New inbox → Other provider`:
| 项 | 值 |
|---|---|
| IMAP | `imap.163.com:993`,SSL/TLS |
| SMTP | `smtp.163.com:465`,SSL |
| 用户名/密码 | 163 邮箱 + 授权码 |
| Scan interval | `5m`(默认) |
接完后旧桥的 `bridge/mail/`(IMAP 轮询 + 自动回复)可以退役;邮件摘要改为定时调 LibreDesk 报表 API。
## 8. WhatsApp(当前 v2.9.0-rc.10 已可用)
> **版本现状**:本套已运行 `v2.9.0-rc.10`,`channels` 枚举为 `email / livechat / whatsapp`,`whatsapp_templates` 表已就绪。
> RC 属于预发布版本,生产使用前评估稳定性;回滚见 README「回滚到稳定版」。
1. Meta 侧准备:Business Account、WABA ID、Phone Number ID、Permanent Access Token、App Secret、Webhook Verify Token
2. `Admin → Inboxes → New inbox → WhatsApp`,填上述凭据
3. Meta App 的 Webhook 指向 `https://你的域名/webhooks/whatsapp`(以实际路由为准),订阅 `messages`
4. 模板:`whatsapp_templates` 表 + 后台模板管理;24 小时窗口外的主动消息必须用已审核模板
5. **AI 对 WhatsApp 的支持文档未覆盖**(文档只写 email + live chat),需实测 assistant 是否在 WhatsApp 会话触发
切换镜像:`.env` 里改 `LIBREDESK_IMAGE=libredesk/libredesk:v2.9.0-rc.9`(若 Docker Hub 无该 tag,则按官方文档从 `v2.9.0-rc.9` 源码构建)。
## 9. 验收清单
- [ ] `Admin → AI → Providers` 两个 Test connection 通过
- [ ] Snippets 至少 10 条,问一个政策问题能引用
- [ ] Tools 4 个,`crm-tools` 日志能看到调用
- [ ] Assistant 已建 + automation 已分配
- [ ] widget 能开聊,收到 AI 回复
- [ ] 未验证时问订单 → AI 引导验证;验证后能查单
- [ ] 说“我要人工” → handoff 到 Support 团队
- [ ] `curl -s http://localhost:4100/healthz` 正常
## 10. 常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| 登录后立刻掉登录 | 用 http 访问但 cookie 是 Secure | `config.toml` 里 `disable_secure_cookies = true` |
| 容器反复重启,日志提示 `system user password is not strong` | System 密码不满足规则(10–72 位,含大小写+数字+特殊字符) | 改 `.env` 的 `LIBREDESK_SYSTEM_USER_PASSWORD`,再 `docker compose up -d --force-recreate app` |
| 工具 401 | `X-Tools-Key` 与 `TOOLS_SHARED_KEY` 不一致 | 核对 `.env` 和工具 Header |
| 工具 403 verification_required | 未验证联系人 / 工具未开验证 | 先走 OTP 验证,或该工具不需要验证则关掉 `requires_verification` |
| 工具 503 tools_key_not_configured | tools 服务未配置共享密钥 | 重启 `start-tools.sh` |
| AI 不回复 | 会话未分配给 assistant / 会话不是 open | 检查 automation 规则与状态 |
| embedding 维度报错 | dimensions 与模型不符 | `text-embedding-v4` 用 1024 |
| 容器访问不了 tools | `host.docker.internal` 未解析 | compose 已配 `extra_hosts`;Linux 需 Docker 20.10+ |