本文介绍AI助手集成常见问题及解决方案。
问题目录
悬浮框集成
引入 SDK
在您的 HTML 页面中引入SDK脚本:
<script src="https://o.alicdn.com/appflow/chatbot/v1/AppflowChatSDK.js"></script>初始化悬浮框
<script>
window.APPFLOW_CHAT_SDK.init({
integrateConfig: {
integrateId: '你的集成ID',
domain: {
requestDomain: 'https://xxx.appflow.aliyunnest.com'
}
}
});
</script>设置用户信息
使用setUser方法设置当前用户的信息,这些信息将在聊天接口中通过useInfo字段传递给大模型。
参数说明
参数名称 | 参数类型 | 是否必填 | 说明 |
userId | string | 否 | 用户唯一标识 |
userName | string | 否 | 用户名称 |
userAvatar | string | 否 | 用户头像 URL |
设置初始化时发送一条消息
通过设置参数initialMessage和initialMessageAutoSend来控制悬浮框初始化打开时候先发送一条消息到聊天框。
<script>
window.APPFLOW_CHAT_SDK.init({
integrateConfig: {
integrateId: '你的集成ID',
domain: {
requestDomain: 'https://xxx.appflow.aliyunnest.com'
},
initialMessage: '你好,欢迎你的到来',
initialMessageAutoSend: false,
}
});
</script>参数说明
参数名称 | 参数类型 | 是否必填 | 说明 |
initialMessage | string | 是 | 发送消息的内容 |
initialMessageAutoSend | string | 否 | 控制发送消息后是否需要AI的回复,默认是false,也就是只发送消息到聊天框,不去请求聊天接口获取并展示AI的回复 |
设置悬浮框是否可拖动和自动打开
通过设置参数draggable的值控制悬浮框是否可拖动,通过设置autoOpen控制悬浮框是否会在页面加载初始化的时候自动打开
<script>
window.APPFLOW_CHAT_SDK.init({
integrateConfig: {
integrateId: '集成ID',
domain: {
requestDomain: 'https://xxx.appflow.aliyunnest.com'
},
draggable: true,
autoOpen: true
},
});
</script>自定义悬浮框的样式
自定义悬浮框的样式通过设置customStyle字段的子属性实现,目前定义了两个,containerStyle和botBubbleStyle,具体含义如下:
通过设置
customStyle下的containerStyle的值,可调整悬浮框的宽度和高度,如截图所示,可设置的参数有四个,width、height、maxWidth、maxHeight。
通过设置
customStyle下的botBubbleStyle的值,可设置悬浮框AI回复消息区域的宽度,如截图所示,可设置的参数有两个,width、maxWidth。
<script> window.APPFLOW_CHAT_SDK.init({ integrateConfig: { integrateId: '集成ID', domain: { requestDomain: 'https://xxx.appflow.aliyunnest.com' }, customStyle: { containerStyle: { width: '800px', height: '90%', maxHeight: '700px', maxWidth: '800px' } } }, }); </script>
设置额外参数
使用setExtraInfo方法可以设置额外的参数,这些参数会在聊天接口中通过extraInfo字段传递给大模型
方法签名
setExtraInfo(extraInfo: any, isGlobal?: boolean): void参数说明
参数名称 | 参数类型 | 是否必填 | 默认值 | 说明 |
extraInfo | object | 是 | - | 要传递的额外参数对象 |
isGlobal | boolean | 否 | false | 是否为全局参数 |
全局参数与临时参数如何选择?
SDK 支持两种类型的额外参数:全局参数和临时参数。
全局参数(isGlobal: true)
持久化存储:设置后会一直保留,直到被新的全局参数覆盖。
每次发送都携带:每次发送消息时都会自动携带这些参数。
适用场景:用户身份信息、会话级别的配置等需要持续传递的数据。
// 设置全局参数 - 这些参数会在每次发送消息时都携带
window.APPFLOW_CHAT_SDK.setExtraInfo({
tenantId: 'tenant-001',
channel: 'web',
language: 'zh-CN',
}, true); // isGlobal = true临时参数(isGlobal: false 或不传)
使用:在下一次发送消息时携带。
适用场景:特定消息的上下文信息、一次性的业务数据。
// 设置临时参数 - 仅在下一次发送消息时携带
window.APPFLOW_CHAT_SDK.setExtraInfo({
currentPage: '/product/detail',
productId: 'SKU-12345',
timestamp: Date.now(),
}); // isGlobal 默认为 false
// 或者显式指定
window.APPFLOW_CHAT_SDK.setExtraInfo({
orderId: 'ORDER-001',
}, false);参数合并规则
当同时存在全局参数和临时参数时,两者会合并传递。如果存在同名字段,临时参数会覆盖全局参数。
// 先设置全局参数
window.APPFLOW_CHAT_SDK.setExtraInfo({
userId: 'user-001',
source: 'global',
}, true);
// 再设置临时参数
window.APPFLOW_CHAT_SDK.setExtraInfo({
source: 'temp',
orderId: 'ORDER-001',
});
// 发送消息时,实际传递的参数为:
// {
// userId: 'user-001', // 来自全局参数
// source: 'temp', // 临时参数覆盖了全局参数
// orderId: 'ORDER-001', // 来自临时参数
// }最佳实践
// 1. 在用户登录后设置全局用户信息
function onUserLogin(userInfo) {
window.APPFLOW_CHAT_SDK.setExtraInfo({
userId: userInfo.id,
userRole: userInfo.role,
tenantId: userInfo.tenantId,
}, true);
}
// 2. 在特定页面设置临时上下文
function onPageEnter(pageInfo) {
window.APPFLOW_CHAT_SDK.setExtraInfo({
currentPage: pageInfo.path,
pageTitle: pageInfo.title,
enterTime: Date.now(),
});
}消息发送前处理器
使用onBeforeSend方法可以注册一个处理器,在用户发送消息之前执行自定义逻辑。
方法签名
onBeforeSend(
handler: (params: { userMessage: UserMessage }) => void | Promise<void>,
options?: { async?: boolean }
): void参数说明
参数名称 | 参数类型 | 是否必填 | 说明 |
handler | function | 是 | 处理器函数,接收包含用户消息的参数对象 |
options.async | boolean | 否 | 是否异步执行,默认为 false |
处理器参数
处理器函数会接收一个参数对象。
参数名称 | 参数类型 | 说明 |
userMessage | UserMessage | 用户即将发送的消息内容 |
UserMessage对象通用字段
所有消息类型都包含以下通用字段。
参数名称 | 参数类型 | 是否必填 | 说明 |
messageType | string | 是 | 消息类型:'text' | 'rich' | 'audio' | 'event' | 'card_call_back' |
sessionId | string | 是 | 当前会话ID |
chatbotId | string | 是 | AI助手ID |
chatbotModelId | string | 是 | 模型ID |
userInfo | object | 否 | 用户信息对象(通过 setUser 设置) |
extraInfo | object | 否 | 额外参数对象(通过 setExtraInfo 设置) |
config | object | 否 | 配置信息(如联网搜索配置) |
不同消息类型的特定字段
text 类型(普通文本消息)
{
messageType: 'text',
sessionId: string,
chatbotId: string,
chatbotModelId: string,
text: {
content: string // 用户输入的文本内容
},
userInfo?: object,
extraInfo?: object,
config?: object
}rich 类型(富文本消息)
包含文本、图片、文件等多媒体内容的消息。
{
messageType: 'rich',
sessionId: string,
chatbotId: string,
chatbotModelId: string,
richText: Array<{
type: 'text' | 'image' | 'file',
content?: string, // type='text' 时的文本内容
mediaUrl?: string, // type='image' 或 'file' 时的媒体URL
mediaId?: string // type='file' 时的文件ID(可选)
}>,
userInfo?: object,
extraInfo?: object,
config?: object
}audio 类型(语音消息)
{
messageType: 'audio',
sessionId: string,
chatbotId: string,
chatbotModelId: string,
audio: {
mediaUrl: string, // 音频文件URL
mediaType: string // 音频类型,如 'wav'
},
userInfo?: object,
extraInfo?: object,
config?: object
}event 类型(系统事件)
{
messageType: 'event',
sessionId: string,
chatbotModelId: string,
event: {
eventType: string, // 事件类型,如 'uploadFile'
content: string // 事件内容(JSON字符串)
}
}card_call_back 类型(卡片回调)
用于审批等交互场景。
{
messageType: 'card_call_back',
sessionId: string,
cardCallBack: {
data: any // 卡片回调数据
}
}同步模式与异步模式如何选择?
同步模式(默认)
处理器函数执行后,立即发送消息。即使处理器返回 Promise,也不会等待 Promise 完成。适用于简单的日志记录、数据统计等不需要阻塞发送的场景
// 同步模式 - 处理器执行后立即发送消息
window.APPFLOW_CHAT_SDK.onBeforeSend((params) => {
console.log('用户即将发送消息:', params.userMessage);
// 记录埋点(不阻塞发送)
analytics.track('message_send', {
content: params.userMessage,
timestamp: Date.now(),
});
});异步模式(async: true)
处理器函数返回 Promise 时,会等待 Promise 完成后再发送消息。适用于需要在发送前进行异步操作的场景,如内容审核、数据预处理等。
// 异步模式 - 等待处理器完成后再发送消息
window.APPFLOW_CHAT_SDK.onBeforeSend(async (params) => {
console.log('用户即将发送消息:', params.userMessage);
// 异步操作:内容审核
const isValid = await contentModeration.check(params.userMessage);
if (!isValid) {
throw new Error('消息内容不合规');
}
// 异步操作:设置动态参数
const contextData = await fetchUserContext();
window.APPFLOW_CHAT_SDK.setExtraInfo({
context: contextData,
});
}, { async: true });使用示例
示例 1:简单日志记录(同步)
window.APPFLOW_CHAT_SDK.onBeforeSend((params) => {
console.log(`[${new Date().toISOString()}] 发送消息: ${params.userMessage}`);
});示例 2:动态设置额外参数(同步)
window.APPFLOW_CHAT_SDK.onBeforeSend((params) => {
// 根据消息内容动态设置参数
const keywords = extractKeywords(params.userMessage);
window.APPFLOW_CHAT_SDK.setExtraInfo({
keywords: keywords,
messageLength: params.userMessage.length,
sendTime: Date.now(),
});
});示例 3:异步内容预处理(异步)
window.APPFLOW_CHAT_SDK.onBeforeSend(async (params) => {
// 调用后端接口获取用户上下文
const response = await fetch('/api/user/context');
const userContext = await response.json();
// 设置额外参数
window.APPFLOW_CHAT_SDK.setExtraInfo({
userContext: userContext,
processedAt: Date.now(),
});
}, { async: true });注意事项
处理器只能注册一个:多次调用 onBeforeSend 会覆盖之前注册的处理器。
异步模式下的错误处理:如果异步处理器抛出错误,消息发送可能会受到影响。
性能考虑:异步模式会延迟消息发送,请确保异步操作尽可能快速完成。
消息发送后处理器
使用onAfterSend方法可以注册一个处理器,在消息发送完成后(AI 回复完成或发生错误时)执行自定义逻辑。
方法签名
onAfterSend(
handler: (params: AfterSendParams) => void | Promise<void>,
options?: { async?: boolean }
): void参数说明
参数名称 | 参数类型 | 是否必填 | 说明 |
handler | function | 是 | 处理器函数,接收包含发送结果的参数对象 |
options.async | boolean | 否 | 是否异步执行,默认为 false |
处理器参数
处理器函数会接收一个参数对象,根据发送结果不同,参数结构也不同:
成功时的参数
参数名称 | 参数类型 | 说明 |
userMessage | UserMessage | 用户发送的消息内容 |
assistantContent | string | AI 回复的完整内容 |
assistantReferences | array | 引用的文档/知识库信息列表 |
失败时的参数
参数名称 | 参数类型 | 说明 |
userMessage | UserMessage | 用户发送的消息内容 |
error | object | 错误信息对象 |
message | string | 错误描述信息 |
code | string | 错误代码 |
同步模式和异步模式如何选择?
同步模式(默认)
处理器函数执行后,不会阻塞后续操作即使处理器返回 Promise,也不会等待 Promise 完成。适用于日志记录、数据统计、UI 更新等不需要阻塞的场景。
// 同步模式
window.APPFLOW_CHAT_SDK.onAfterSend((params) => {
if (params.success) {
console.log('消息发送成功');
console.log('AI 回复:', params.assistantContent);
} else {
console.error('消息发送失败:', params.error.message);
}
});异步模式(async: true)
处理器函数返回 Promise 时,会等待 Promise 完成,适用于需要在回复完成后进行异步操作的场景,如数据持久化、后续 API 调用等。
// 异步模式
window.APPFLOW_CHAT_SDK.onAfterSend(async (params) => {
if (params.success) {
// 异步保存对话记录
await saveConversation({
question: params.userMessage,
answer: params.assistantContent,
references: params.assistantReferences,
});
}
}, { async: true });使用示例
示例 1:基础日志记录
window.APPFLOW_CHAT_SDK.onAfterSend((params) => {
const timestamp = new Date().toISOString();
if (params.success) {
console.log(`[${timestamp}] 对话完成`);
console.log(` 用户: ${params.userMessage}`);
console.log(` AI: ${params.assistantContent.substring(0, 100)}...`);
console.log(` 引用数量: ${params.assistantReferences.length}`);
} else {
console.error(`[${timestamp}] 对话失败`);
console.error(` 用户: ${params.userMessage}`);
console.error(` 错误: [${params.error.code}] ${params.error.message}`);
}
});示例 2:数据埋点统计
window.APPFLOW_CHAT_SDK.onAfterSend((params) => {
// 发送埋点数据
analytics.track('chat_completed', {
success: params.success,
userMessage: params.userMessage,
responseLength: params.success ? params.assistantContent.length : 0,
referenceCount: params.success ? params.assistantReferences.length : 0,
timestamp: Date.now(),
});
});示例 3:对话记录持久化(异步)
window.APPFLOW_CHAT_SDK.onAfterSend(async (params) => {
try {
await fetch('/api/conversation/save', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
question: params.userMessage,
answer: params.success ? params.assistantContent : null,
references: params.success ? params.assistantReferences : [],
error: params.success ? null : params.error,
timestamp: Date.now(),
}),
});
} catch (error) {
console.error('保存对话记录失败:', error);
}
}, { async: true });注意事项
处理器只能注册一个:多次调用 onAfterSend 会覆盖之前注册的处理器。
异步模式下的错误处理:建议在异步处理器中使用 try-catch 捕获错误,避免影响用户体验。
性能考虑:处理器中的操作应尽量轻量,避免影响聊天体验
关闭悬浮框
使用 close 方法可以关闭聊天悬浮框。
window.APPFLOW_CHAT_SDK.close();