本地 RAG 知识库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

16 KiB

Chat SDK 第三方系统集成指南

本文档说明第三方系统如何接入 AI 智能客服的 Chat SDK,完成从创建 API Key 到嵌入对话组件的全流程。


目录

  1. 集成架构总览
  2. 第一步:创建 API Key
  3. 第二步:绑定客服角色(可选)
  4. 第三步:后端换取 SDK Token
  5. 第四步:前端嵌入 Chat SDK
  6. API 接口参考
  7. SDK 配置参数参考
  8. 错误码与排查
  9. 安全建议

1. 集成架构总览

┌─────────────────┐     ┌──────────────────┐     ┌──────────────────┐
│  第三方前端      │     │  第三方后端       │     │  AI 客服后端      │
│  (嵌入 SDK)     │     │  (你的服务)       │     │  (本系统)         │
│                 │     │                  │     │                  │
│  Chat SDK ──────┼─────┼──────────────────┼─────┼─► /ai/** 对话    │
│   ↑ token       │     │                  │     │                  │
│                 │     │  ① 携带 API Key   │     │  ② 返回 JWT Token│
│                 │     │  POST /open-api/  │─────┼─► /auth/token    │
│                 │     │  auth/token       │     │                  │
└─────────────────┘     └──────────────────┘     └──────────────────┘

两段式鉴权流程:

  1. 管理后台:管理员创建 API Key,可选绑定客服角色
  2. 第三方后端:用 API Key 换取短期 JWT Token + 可用角色列表
  3. 第三方前端:Chat SDK 携带 JWT Token 请求 /ai/** 接口进行对话

2. 第一步:创建 API Key

在管理后台「系统设置 → API Key 管理」页面创建。

管理后台操作

  1. 登录管理后台 http://localhost:9090/index.html
  2. 进入「系统设置 → API Key 管理」
  3. 点击「+ 新建 API Key」
  4. 填写名称、描述、频率限制等参数
  5. (可选) 在创建弹窗中勾选需要绑定的客服角色
  6. 创建后立即复制保存 Key,关闭后无法再次查看

API Key 格式

sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(sk_ 前缀 + 32 位 UUID)

3. 第二步:绑定客服角色(可选)

客服角色决定 AI 的人设、知识库范围和 MCP 工具权限。

角色绑定规则

role_ids 状态 Token 换取行为
空数组 [](默认) 返回所有启用的客服角色(向后兼容)
非空 [1, 2, 3] 仅返回绑定的角色

通过管理后台绑定

在 API Key 列表中点击「绑定角色」按钮,勾选需要的角色后保存。

通过 API 绑定

PUT /api-key/{keyId}/roles
Content-Type: application/json
Authorization: Bearer {管理后台 JWT Token}

{
  "roleIds": [1, 2, 3]
}

响应:

{
  "success": true,
  "message": "角色绑定更新成功"
}

4. 第三步:后端换取 SDK Token

⚠️ 重要:Token 换取必须在第三方后端完成,不可在前端暴露 API Key。

请求

POST /open-api/auth/token
Content-Type: application/json
X-API-Key: sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

{
  "ttl": 7200
}
参数 类型 必填 说明
X-API-Key Header 创建的 API Key
ttl Body Token 有效期(秒),默认 7200(2 小时),范围 [300, 86400]

成功响应

{
  "success": true,
  "token": "eyJhbGciOiJIUzI1NiJ9...",
  "expiresIn": 7200,
  "roles": [
    { "id": "1", "key": "general", "name": "通用客服" },
    { "id": "2", "key": "finance", "name": "财务顾问" }
  ]
}
字段 说明
token SDK JWT Token,传给前端使用
expiresIn 过期时间(秒)
roles 可用客服角色列表,前端用于展示角色选择器

错误响应

HTTP 状态码 说明
401 API Key 无效或已禁用
403 无可用客服角色

5. 第四步:前端嵌入 Chat SDK

使用测试面板快速验证

访问 http://localhost:9090/sdk/test.html 打开测试面板:

  1. 在「🔐 SDK Token 鉴权」区域输入 API Key
  2. 点击「获取 Token」按钮自动换取(或手动粘贴已有的 Token)
  3. Token 获取成功后,integrateId 会自动填充为第一个可用角色
  4. 点击「🚀 初始化 SDK」即可测试对话功能

测试面板支持所有 P0/P1/P2 测试用例的自动化运行,包括 API 连通性验证。

5.1 引入 SDK

<script src="https://your-domain.com/sdk/chatbot-sdk.js"></script>

5.2 初始化

const chatbot = ChatbotSDK.init({
  // ========== 必填参数 ==========
  integrateId: '1',                              // 客服角色 ID(从 Token 换取接口的 roles 中选择)
  requestDomain: 'https://your-domain.com',       // AI 客服后端域名

  // ========== 鉴权参数(推荐) ==========
  token: 'eyJhbGciOiJIUzI1NiJ9...',               // 后端换取的 SDK Token
  roles: [                                        // 可用角色列表(传多个时 SDK header 显示角色切换下拉框)
    { id: '1', key: 'general', name: '通用客服' },
    { id: '2', key: 'finance', name: '财务顾问' }
  ],

  // ========== 可选参数 ==========
  userId: 'user_12345',                           // 用户标识(用于会话隔离)
  title: 'AI 智能助手',                            // 对话窗口标题
  theme: 'light',                                 // 主题:light / dark
  primaryColor: '#4F46E5',                         // 主题色(十六进制)
  streaming: true,                                // 启用流式回复(默认 true)
  enableRag: true,                                 // 启用 RAG 知识库检索(默认 true)
  quickReplies: ['如何退款?', '联系人工客服'],       // 快捷问题
  position: 'right-bottom',                        // 悬浮按钮位置:right-bottom / left-bottom
  width: 380,                                      // 窗口宽度(px)
  height: 520,                                     // 窗口高度(px)
  debug: true,                                     // 控制台调试日志

  // ========== 回调函数 ==========
  onReady: function() { console.log('SDK 就绪'); },
  onMessage: function(msg) { console.log('收到消息', msg); },
  onError: function(err) { console.error('SDK 错误', err); }
});

5.3 SDK 方法

// 销毁实例(移除 DOM 和事件监听)
chatbot.destroy();

5.4 不使用 Token 的兼容模式

如果暂时不接入后端 Token 换取,可直接使用兼容模式(不推荐用于生产环境):

ChatbotSDK.init({
  integrateId: '1',                    // 直接指定角色 ID
  requestDomain: 'https://your-domain.com'
  // 不传 token 和 roles
});

兼容模式下,integrateId 直接作为 roleId 传递给后端,无需 Token 换取步骤。由于不传 roles,SDK 不会显示角色选择器,用户只能使用初始指定的单一角色。

5.5 角色切换

roles 数组长度 > 1 时,SDK 会在聊天窗口头部自动显示角色选择下拉框,用户可随时切换当前使用的客服角色。

触发条件:

  • ChatbotSDK.init() 时传入的 roles 数组包含 2 个及以上角色

切换行为:

  1. 自动保存当前对话到 localStorage(与旧角色关联)
  2. 清空当前消息列表
  3. 生成新的 chatId(与新角色关联)
  4. 尝试从 localStorage 恢复新角色的缓存消息
  5. 异步从后端加载新角色的历史会话

示例:

// 1. 后端换取 Token,获取可用角色列表
const data = await fetch('/api/chatbot/token').then(r => r.json());

// 2. 初始化 SDK,传入角色列表
ChatbotSDK.init({
  integrateId: data.roles[0].id,        // 默认使用第一个角色
  requestDomain: 'https://your-domain.com',
  token: data.token,
  roles: data.roles,                     // 传入多个角色 → header 显示角色选择器
  userId: 'current_user_id'
});

安全说明:

  • 角色切换由 SDK 前端发起,后端 SdkAuthFilter 会校验 JWT Token 中的 rids claim,确保用户只能切换到被授权的角色
  • 切换角色不需要重新换取 Token,JWT 中已包含允许的角色 ID 列表

6. API 接口参考

6.1 Token 换取

POST /open-api/auth/token

详见 第三步:后端换取 SDK Token

6.2 对话接口(SDK 内部调用,无需手动对接)

接口 方法 说明
/ai/assistant_app/chat/sync GET 同步对话(返回完整文本)
/ai/assistant_app/chat/sse GET SSE 流式对话
/ai/assistant_app/chat/rag/sse GET RAG 增强流式对话
/ai/assistant_app/rag/sources GET 获取 RAG 引用来源
/ai/sdk/conversation/list GET 会话列表
/ai/sdk/conversation/{id}/messages GET 会话消息
/ai/sdk/conversation/{id} DELETE 删除会话
/ai/sdk/conversation/{id}/export GET 导出会话
/category/tree GET 知识库分类树
/feedback POST 消息反馈

通用请求参数(对话接口):

参数 类型 必填 说明
message Query 用户消息
chatId Query 会话 ID(SDK 自动管理)
roleId Query 客服角色 ID
accountId Query 用户标识
categoryId Query 知识库分类 ID
rewriteStrategy Query RAG 查询重写策略:REWRITE / TRANSLATION / COMPRESSION / MULTI_QUERY

认证方式: 所有 /ai/** 请求自动在 Header 中携带 Authorization: Bearer {token}

6.3 管理接口(需要管理后台 JWT)

接口 方法 说明
/api-key/list GET API Key 列表(admin)
/api-key POST 创建 API Key(admin)
/api-key/{id}/revoke PUT 吊销 API Key(admin)
/api-key/{id}/enable PUT 启用 API Key(admin)
/api-key/{id} DELETE 删除 API Key(admin)
/api-key/{id}/roles PUT 更新角色绑定(admin)
/role/list GET 客服角色列表(admin)
/role/all GET 全部角色含停用(admin)

7. SDK 配置参数参考

参数 类型 默认值 说明
integrateId String/Number 必填 客服角色 ID
requestDomain String 必填 后端域名
token String - SDK JWT Token(推荐)
roles Array - 角色列表 [{id, key, name}],长度 > 1 时 header 显示切换下拉框
userId String - 用户标识(会话隔离)
categoryId String - 默认知识库分类 ID
showCategorySwitch Boolean false 显示分类切换器
title String 'AI 智能助手' 窗口标题
width Number 380 窗口宽度(px)
height Number 520 窗口高度(px,最小 300)
position String 'right-bottom' 悬浮按钮位置
primaryColor String '#4F46E5' 主题色
launcherTheme String - 按钮主题:dream-purple / mint-tech / coral-peach / sky-blue
launcherIcon String (内置) 自定义悬浮按钮 SVG
theme String 'light' 界面主题:light / dark
streaming Boolean true 流式回复
enableRag Boolean true RAG 知识库检索
rewriteStrategy String 'REWRITE' 查询重写策略
quickReplies String[] [] 快捷问题列表
showClear Boolean true 显示清空按钮
showAdminPanel Boolean false 显示管理入口
showTeaser Boolean true 显示提示气泡
teaserText String '' 提示气泡文本
sound Boolean false 消息提示音
notification Boolean false 浏览器通知
locale String 'zh-CN' 语言:zh-CN / en
debug Boolean true 调试日志
onReady Function - SDK 就绪回调
onMessage Function - 消息回调
onError Function - 错误回调

8. 错误码与排查

Token 换取阶段

错误 原因 解决方案
401 API Key 鉴权失败 X-API-Key 无效或缺失 检查 Header 是否正确携带
401 API Key 已被禁用 Key 被吊销 在管理后台重新启用或创建新 Key
401 API Key 已过期 Key 超过有效期 创建新的 API Key
403 无可用客服角色 未绑定角色且系统无启用角色 在管理后台创建并启用客服角色

SDK 对话阶段

HTTP 状态码 SDK 提示 原因
401 鉴权失败 Token 过期或无效,需重新换取
403 无访问权限 roleId 不在 Token 允许范围内
429 请求过于频繁 超过 API Key 频率限制
500 服务器异常 后端错误,查看服务端日志
502/503 服务暂不可用 后端未启动或正在部署

常见问题

Q: Token 过期后怎么办? A: Token 默认 2 小时过期。建议在第三方后端实现 Token 缓存和自动刷新逻辑:检测到 401 时重新调用 /open-api/auth/token 换取新 Token。

Q: 如何让用户只能使用特定角色? A: 在 API Key 上绑定角色(PUT /api-key/{id}/roles),SDK 初始化时只传入绑定的角色 ID。

Q: 多个第三方系统可以用同一个 API Key 吗? A: 可以,但建议每个系统使用独立的 API Key,便于独立管控频率限制和角色权限。


9. 安全建议

  1. API Key 仅在后端使用:永远不要将 API Key 暴露到前端代码中
  2. Token 短有效期:生产环境建议 TTL 设为 1-2 小时,配合自动刷新
  3. 角色最小权限:只绑定必要的客服角色,避免授予过多权限
  4. 频率限制:根据业务量设置合理的 rateLimit(默认 60 次/分钟)
  5. HTTPS:生产环境必须使用 HTTPS,防止 Token 被中间人截获
  6. 定期轮换 Key:定期吊销旧 Key 并创建新 Key

附录:完整对接示例(Node.js)

// ==================== 第三方后端示例 ====================
const express = require('express');
const app = express();

const AI_DOMAIN = 'https://your-ai-domain.com';
const API_KEY = 'sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

// Token 缓存
let cachedToken = null;
let tokenExpireAt = 0;

// 换取 Token(带缓存)
async function getSdkToken() {
  if (cachedToken && Date.now() < tokenExpireAt) {
    return cachedToken;
  }

  const res = await fetch(`${AI_DOMAIN}/open-api/auth/token`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY
    },
    body: JSON.stringify({ ttl: 7200 })
  });

  const data = await res.json();
  if (!data.success) throw new Error(data.message);

  cachedToken = data.token;
  tokenExpireAt = Date.now() + (data.expiresIn - 300) * 1000; // 提前 5 分钟刷新
  return { token: data.token, roles: data.roles };
}

// 给前端提供 Token
app.get('/api/chatbot/token', async (req, res) => {
  try {
    const data = await getSdkToken();
    res.json({ success: true, ...data });
  } catch (e) {
    res.status(500).json({ success: false, message: e.message });
  }
});

app.listen(3000);
<!-- ==================== 第三方前端示例 ==================== -->
<script src="https://your-ai-domain.com/sdk/chatbot-sdk.js"></script>
<script>
  // 从自己后端获取 Token
  fetch('/api/chatbot/token')
    .then(r => r.json())
    .then(data => {
      if (data.success) {
        ChatbotSDK.init({
          integrateId: data.roles[0].id,    // 默认使用第一个角色
          requestDomain: 'https://your-ai-domain.com',
          token: data.token,
          roles: data.roles,                // 传入多个角色时自动显示角色选择器
          userId: 'current_user_id',
          title: '在线客服',
          theme: 'light',
          quickReplies: ['如何退款?', '查看订单', '联系人工']
        });
      }
    });
</script>