AI Chat UI SDK 使用教程
面向第三方页面接入方。基于
@ant-design/x的 AI 聊天窗口,被打包为单文件 SDK,只需引入一个<script>即可在你的页面中嵌入聊天能力,无需额外引入任何库。
1. 概述
| 项 | 说明 |
|---|---|
| 产物 | dist-sdk/datam-chat.js(约 2.6MB,gzip 约 854KB) |
| 全局入口 | window.DatamChat.init(container, options) |
| 能力 | 流式输出、Markdown + 代码高亮、思考过程折叠、工具调用状态、历史分页、深浅主题、自定义前端函数(Bridge) |
| 通信 | WebSocket(消息流)+ HTTP(历史 / 清空) |
2. 快速开始
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>AI 助手</title>
</head>
<body>
<!-- 1. 占位容器,必须给定高度 -->
<div id="my-chat" style="height: 100vh;"></div>
<!-- 2. 引入 SDK -->
<script src="http://your-server/ai/assets/datam-chat.js"></script>
<!-- 3. 初始化 -->
<script>
DatamChat.init('#my-chat', {
host: 'your-server:3001', // 仅 host[:port],不要带协议
eId: 'siptea',
ckey: 'your-api-key', // 可选;不传走 session 认证
dataSetId: 'pksse_news_DB', // 可选;RAG 数据集
theme: 'darkAlgorithm', // 可选
});
</script>
</body>
</html>
3. API:DatamChat.init(container, options)
3.1 container
要挂载聊天窗口的容器,两种形式:
DatamChat.init('#my-chat', {...}) // CSS 选择器字符串
DatamChat.init(document.getElementById('my-chat'), {...}) // HTMLElement
容器内部内容会被清空后重建,请勿在容器里放其它节点。
3.2 options 参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
host |
string |
否 | 当前页面域名 | 后端地址,仅 host[:port],不要带 http(s):// |
eId |
string |
是 | — | 项目 / 企业 ID,用于鉴权与会话隔离 |
ckey |
string |
否 | — | API 密钥。传入走 ckey 认证(/api/ai),不传走 session 认证(/editor/ai) |
dataSetId |
string |
否 | — | 数据集 ID,启用 RAG 检索(顶栏显示橙色标签) |
theme |
string |
否 | defaultAlgorithm |
darkAlgorithm / compactAlgorithm / defaultAlgorithm |
functions |
Array |
否 | [] |
自定义前端函数,AI 可经 Bridge 调用(见 §6) |
示例:
DatamChat.init('#chat', {
host: '10.0.0.8:3001',
eId: 'siptea',
ckey: 'sk-xxxx',
dataSetId: 'news_DB',
theme: 'compactAlgorithm',
});
注意:
init会把eId、dataSetId、theme追加到当前页面 URL 的 query 上(不刷新页面)。若你的页面另有 query 逻辑,注意避免冲突。
4. 认证方式
SDK 通过 ckey 自动在两条路径间切换:
| 模式 | 触发条件 | WS 路径 | HTTP 前缀 | 适用场景 |
|---|---|---|---|---|
| Session 登录 | 未传 ckey |
/dm/v1/editor/ai/ws |
/dm/v1/editor/ai/ |
编辑器内嵌(浏览器 cookie 自动携带) |
| API ckey 认证 | 传入 ckey |
/dm/v1/api/ai/ws?eId=..&ckey=.. |
/dm/v1/api/ai/ |
第三方 / SDK 调用 |
ckey 会自动拼接到 WebSocket 与 HTTP 请求的 query 中,SDK 据此选择认证路径。
鉴权失败:后端关闭 WebSocket(code 4001),聊天窗口显示失败原因,并禁用输入框与清空按钮。
5. host 与跨域部署(重要)
SDK 对 WebSocket 与 HTTP 使用了不同的地址来源,接入时务必理解:
| 通道 | 地址来源 | 说明 |
|---|---|---|
| WebSocket | host 参数 |
ws(s)://{host}{path},协议由当前页面 https 自动推导 wss |
| HTTP(历史 / 清空) | 当前页面自身域名 | 使用相对路径 /dm/v1/...,不受 host 参数影响 |
因此:
host只作用于 WebSocket,且只能传host[:port](如localhost:3001、api.example.com),不要传http://localhost:3001,否则会拼成错误的ws://http://...。- 历史加载、清空会话、清空记忆等 HTTP 接口走的是嵌入页面自身同源的
/dm/v1/...。若第三方页面与后端不同源,需要在第三方域名上做反向代理把/dm转发到后端(或用同域部署),否则这些接口会请求失败。
推荐部署方式:由后端同源托管 SDK 与页面(或在前置网关反代 /dm),既满足 HTTP 同源,又能让 WebSocket 直接连后端。
6. 自定义前端函数(Bridge)
AI 可以在对话中调用你注册的前端函数,并拿到返回结果继续推理。这是 SDK 与宿主页面交互的核心能力。
6.1 函数格式
{
name: string; // 函数名,AI 调用时的标识
description: string; // 给模型看的用途描述(写清楚何时用、返回什么)
params: Array<{ name: string; type: string; description: string }>,
handler: (...args: any[]) => any, // 实际执行函数;参数按 params 顺序展开
}
params三个字段(name/type/description)都要写全,模型才能准确理解参数类型和用途。handler的返回值会作为函数执行结果回传给 AI;若handler抛出异常,SDK 会把错误信息回传后端。
6.2 示例
DatamChat.init('#chat', {
host: 'your-server:3001',
eId: 'siptea',
ckey: 'sk-xxxx',
functions: [
{
name: 'navigateTo',
description: '跳转到指定页面;用户要求打开/跳转某页面时调用',
params: [
{ name: 'url', type: 'string', description: '目标页面地址' },
{ name: 'newTab', type: 'boolean', description: '是否在新标签页打开' },
],
handler(url, newTab) {
if (newTab) window.open(url, '_blank');
else location.href = url;
return { navigated: true };
},
},
{
name: 'getUserInfo',
description: '获取当前登录用户信息',
params: [],
handler() {
return { name: 'Alice', role: 'admin' };
},
},
],
});
7. 主题
theme 对应 antd 主题算法:
| 取值 | 效果 |
|---|---|
defaultAlgorithm(默认) |
浅色 |
darkAlgorithm |
深色(代码高亮自动切 coldarkDark) |
compactAlgorithm |
紧凑 |
8. 完整示例
<div id="chat" style="height: 100vh;"></div>
<script src="/ai/assets/datam-chat.js"></script>
<script>
DatamChat.init('#chat', {
host: 'datam.example.com', // 仅 host[:port]
eId: 'siptea',
ckey: 'your-api-key', // 不传则走 session 认证
dataSetId: 'pksse_news_DB',
theme: 'darkAlgorithm',
functions: [
{
name: 'openReport',
description: '打开指定编号的报表页面',
params: [{ name: 'reportId', type: 'string', description: '报表编号' }],
handler(reportId) {
location.href = '/report?id=' + reportId;
return { opened: true };
},
},
],
});
</script>
9. 注意事项 / 已知限制
- 无销毁方法:
init无返回值,也没有destroy/unmount。请勿对同一容器重复调用init(会叠加创建 root)。如需重挂载,先清空容器并刷新页面逻辑。 - 自定义函数注册时序(当前版本缺陷):SDK 在脚本加载时读取一次函数列表,而
init({ functions })是在其后才写入的,因此直接通过init传入的函数可能不会被注册。- 临时规避:在加载 SDK 脚本之前先声明全局变量:
<script>window.__dmChatFunctions__ = [ /* ...同 functions 格式... */ ];</script> <script src="/ai/assets/datam-chat.js"></script> - 后续版本修复该时序后,即可直接使用
init({ functions })。
- 临时规避:在加载 SDK 脚本之前先声明全局变量:
- HTTP 接口走当前页面同源:历史 / 清空等请求用相对路径,跨域嵌入需反代
/dm(见 §5)。 host不带协议:只传host[:port],协议由页面自动推导ws/wss。