🚀 Chat 模块使用说明
💡 新手必读: 首次使用 Chat 模块?建议先阅读 核心概念文档 了解基础知识,这将帮助您更快上手!
🎯 模块简介
scp.chat 是基于 ChatPlugin 封装的智能体对话管理模块,为大模型应用提供完整的对话解决方案。该模块支持多智能体切换、会话管理、流式消息处理、生成中断等核心功能,专为现代AI应用场景设计。
核心特性:
- 🤖 多智能体管理与切换
- 💬 会话持久化与历史记录
- ⚡ 流式消息实时处理
- 🛑 生成过程可控中断
- 📡 实时消息推送(MQTT)
- 🎨 事件驱动架构
⚙️ 初始化Chat模块
await scp.chat.init({
agentCode: 'agent_code_123', // 必填:智能体唯一标识
emptyContent: '暂无回复内容', // 可选:自定义空回复提示文案
threadId: 'thread_id_456', // 可选:指定要加载的会话ID
assistant_id: 'agent', // 可选:助理id(场景id),如果初始化方法不传助理id,发送消息必传
isThreadRequired: false, // 可选:是否有会话。agentos3.0 没有会话列表,所以设置为 false。如果其他智能体开发需要有会话列表,必须设置为true
"metadata": {
"model_id": "reasoning", // 推理模型
"safe_mode": true, // 安全模式
"permission_mode": "plan" // 规划模式
}
});参数说明:
agentCode: 当前激活的智能体代码,用于标识不同的AI助手emptyContent: 当AI回复为空时显示的占位文本threadId: 指定要恢复的历史会话,不传则创建新会话
🔧 核心API详解
1. 消息发送 ✉️
入参接受参数有string | MsgItemPartsItem | MsgItemPartsItem[],具体格式查验 a2a文档。
发送用户消息到当前激活的智能体:
发送普通消息
// 发送文本消息
// 写法1:
await scp.chat.send('请帮我分析一下市场趋势');
// 写法2:
await scp.chat.send({
type: 'text',
text: "大模型应用场景",
});
// 写法3:
await scp.chat.send([
{
type: 'text',
text: "大模型应用场景",
}
]);
// 发送后会自动触发流式响应,通过事件监听获取回复内容发送一个文件
建议先查阅 https://a2a-protocol.org/latest/sdk/python/api/a2a.html#a2a.types.FilePart
await scp.chat.send({
type: 'document', // 注意:后端使用的分类名称,涵盖图片、文件等类型。语义上 'file' 更准确,但因接口已上线且被多方依赖,暂不调整
file: FileWithBytes | FileWithUri,
});发送数据库等其他信息
文档补充中...
2. 消息列表获取 📋
获取当前会话的完整消息历史:
const messages = scp.chat.getMessages();
// 返回消息数组,每个消息包含:
// {
// id: string, // 消息唯一ID
// role: 'user' | 'assistant', // 消息角色
// content: string, // 消息内容
// timestamp: number, // 时间戳
// status: 'sending' | 'sent' | 'error' // 消息状态
// }3. 智能体切换 🔄
动态切换到不同的智能体:
// 切换到指定智能体
await scp.chat.setAgentCode('new_agent_code');
// 切换后会自动重置会话状态,可配合会话切换使用4. 会话管理 📁
切换会话
// 切换到指定历史会话
await scp.chat.setThreadId('target_thread_id');
// 创建新会话(传入null或空字符串)
await scp.chat.setThreadId(null);删除会话
// 删除指定会话及其所有消息
await scp.chat.deleteThread('thread_id_to_delete');更新会话信息
// 更新会话名称或其他元数据
await scp.chat.updateThread('thread_id', {
name: '新的会话名称',
description: '会话描述'
});5. 生成控制 ⏯️
停止生成
// 中断当前正在进行的AI响应生成
scp.chat.stopGeneration();检查生成状态
// 检查是否正在生成回复
const isGenerating = await scp.chat.isGenerationActive();
if (isGenerating) {
console.log('AI正在思考中...');
}6. 切换 assistant_id(助理id、场景id)🔄
动态切换到不同的场景:
// 切换到指定场景
scp.chat.setAssistantId("agent");
// 切换后再开始对话,就围绕新设置的场景聊天7. 获取无会话列表时的对话消息列表数据
const chatPagination = reactive<{
total: number;
current: number;
size: number;
pages: number;
}>({
total: 0,
current: 1,
size: 5,
pages: 0
});
const getChatHistory = async (current: number = 1, size: number = chatPagination.size) => {
// 只要调用了 getNonThreadHistory 方法,会自动触发 `ChatEventType.MESSAGES_CHANGE` 事件更新消息
const { data } = await scp.chat.getNonThreadHistory({
current,
size
});
const { records: newRecords, ...obj } = data;
Object.assign(chatPagination, obj);
return newRecords || [];
};8. 手动更新消息列表数据
插件已实现,文档待补充
9. 中断恢复方法
当需要提交审批响应以恢复被中断的流程时,使用以下方法:
window.scp.chat.submitApprovalResponse(props.approvals.interrupt_id, selections.value, {});其中:
- 第一个参数
props.approvals.interrupt_id:中断的ID - 第二个参数
selections.value:用户的选择结果,是一个对象,例如:ts{ "您是否同意审批?": "同意", "请选择影响范围:": ["部门内", "全公司"], "紧急程度?": "高" } - 第三个参数
{}:额外的选项参数(可为空对象)
第二个参数 selections 是一个键值对对象,键为问题文本,值为用户的选择结果。对于单选题返回字符串,对于多选题返回数组。
💡 提示: 如果是在XUI技能中获取中断ID,可参考这篇文章:Form-Page 配置指南
📡 事件监听系统
1. 事件类型枚举
为了更好的类型安全和代码维护性,建议使用统一的事件类型枚举:
export enum ChatEventType {
MESSAGES_CHANGE = 'messages_change', // 消息列表变化
PUSHSPIN_CHANGE = 'pushspin_change', // 推送状态变化
STREAM_UPDATE = 'stream_update', // 流式内容更新
TOKEN_STATUS_CHANGE = 'tokenStatusChange', // Token状态变化
THREAD_CREATED = 'threadCreated', // 会话创建
THREAD_CHANGED = 'threadChanged', // 会话列表变化
SKILL_COMPLETED = 'skillCompleted', // 技能执行完成
SAPPROVAL_REQUEST = "approval_request" // 审批请求
}2. 统一事件监听(推荐)
使用统一的 on 方法监听所有事件,提供更好的类型提示和错误处理:
// 监听消息变化
const unsubscribeMessages = scp.chat.on(ChatEventType.MESSAGES_CHANGE, (newMessages, oldMessages) => {
console.log('消息更新:', newMessages.length, '条消息');
messages.value = newMessages;
// 自动滚动到最新消息
nextTick(() => {
scrollToBottom();
});
});
// 监听流式内容更新
const unsubscribeStream = scp.chat.on(
ChatEventType.STREAM_UPDATE,
(
msgId: string,
content: any[],
type: 'start' | 'content' | 'end' | 'error'
) => {
// console.log('-----流式更新:', { msgId, content, type });
switch (type) {
case 'start':
console.log('开始', msgId);
// showLoading(msgId);
isGenerating.value = true;
break;
case 'content':
// console.log('内容更新:', content);
console.log('parts:', content.parts);
if (content.toolCall) {
// 使用场景:智能体以辅助助手模式运行,可根据工具名称执行相应的操作,例如:更新地图坐标、修改表单绑定数据等
console.log('工具调用:', content.toolCall.id);
console.log('输入是否完整:', content.toolCall.isInputComplete);
console.log('执行状态:', content.toolCall.status);
}
break;
case 'end':
// finalizeMessage(msgId, content);
console.log('结束');
isGenerating.value = false;
break;
case 'error':
// showError(msgId, content);
isGenerating.value = false;
break;
}
}
);
// 监听Token状态变化
const unsubscribeTokenStatus = scp.chat.on(ChatEventType.TOKEN_STATUS_CHANGE, (status: string) => {
switch (status) {
case 'expired':
ElMessage.error('登录已过期,请重新登录');
router.push('/login');
break;
case 'invalid':
console.error('Token无效,请检查网络连接');
ElMessage.warning('认证失败,请重试');
break;
case 'valid':
console.log('Token验证通过');
break;
}
});
// 监听新会话创建
const unsubscribeThreadCreated = scp.chat.on(ChatEventType.THREAD_CREATED, (threadId: string) => {
console.log('新会话已创建:', threadId);
// 启动MQTT消息监听
listenMqttMessage(threadId);
// 更新当前活跃会话
activeThreadId.value = threadId;
// 更新路由
router.replace(`/chat/${activeAgentCode.value}/${threadId}`);
});
// 监听会话列表变化
const unsubscribeThreadChange = scp.chat.on(ChatEventType.THREAD_CHANGED, (newThreads, oldThreads) => {
console.log('会话列表已更新:', newThreads.length, '个会话');
threadList.value = newThreads;
// 更新侧边栏显示
updateSidebarThreads(newThreads);
});
// 监听中断用户确认消息变化
const unsubscribeApprovalsChange = scp.chat.on(ChatEventType.APPROVAL_REQUEST, (approvals, currentApproval) => {
console.log("APPROVAL_REQUEST:", approvals, currentApproval);
pendingApprovals.value = approvals;
});3. 事件清理管理
方式一:逐个清理
const cleanup = () => {
unsubscribeMessages?.();
unsubscribeStream?.();
unsubscribeTokenStatus?.();
unsubscribeThreadCreated?.();
unsubscribeThreadChange?.();
unsubscribeApprovalsChange?.();
};方式二:按类型清理(推荐)
const cleanup = () => {
scp.chat.off(ChatEventType.MESSAGES_CHANGE);
scp.chat.off(ChatEventType.STREAM_UPDATE);
scp.chat.off(ChatEventType.TOKEN_STATUS_CHANGE);
scp.chat.off(ChatEventType.THREAD_CREATED);
scp.chat.off(ChatEventType.THREAD_CHANGED);
scp.chat.off(ChatEventType.APPROVAL_REQUEST);
};方式三:一键清理所有
const cleanup = () => {
scp.chat.removeAllListeners();
};方式四:批量清理指定事件
const cleanup = () => {
scp.chat.offMultiple([
ChatEventType.MESSAGES_CHANGE,
ChatEventType.STREAM_UPDATE,
ChatEventType.TOKEN_STATUS_CHANGE,
ChatEventType.APPROVAL_REQUEST
]);
};4. 批量事件订阅
对于需要同时监听多个事件的场景,可以使用批量订阅方法:
const unsubscribeAll = scp.chat.subscribeEvents({
[ChatEventType.MESSAGES_CHANGE]: (newMessages, oldMessages) => {
messages.value = newMessages;
updateMessageCount(newMessages.length);
},
[ChatEventType.STREAM_UPDATE]: (msgId, content, type) => {
updateStreamingContent(msgId, content, type);
},
[ChatEventType.TOKEN_STATUS_CHANGE]: (status: string) => {
handleTokenStatusChange(status);
},
[ChatEventType.THREAD_CREATED]: (threadId: string) => {
handleNewThread(threadId);
},
[ChatEventType.THREAD_CHANGED]: (newThreads, oldThreads) => {
threadList.value = newThreads;
},
[ChatEventType.APPROVAL_REQUEST]: (approvals,currentApprova) => {
threadList.value = newThreads;
},
});
// 组件销毁时一次性清理所有订阅
onUnmounted(() => {
unsubscribeAll();
});5. 消息事件设计的核心
我来清晰地帮你划分:
🧭 STREAM_UPDATE 中 'start' | 'content' | 'end' | 'error' 的应用场景
这个事件是针对单条消息(msgId)的生命周期,用于粒度更细的 UI 控制。
✅ 使用场景分析:
1. 'start' 场景
| 场景 | 说明 |
|---|---|
| 显示该消息的 loading 状态 | 如:动画、打字机效果、loading 图标等 |
| 插入一条空白的 AI 消息 | 为后续内容做“承接占位” |
| 锁定某条消息 UI(如动画逐字加载) | 比如打字机效果逐字输入就是从这个点开始 |
2. 'content' 场景
| 场景 | 说明 |
|---|---|
| 渲染最新的 AI 消息内容 | 通常是 append 或 replace 内容 |
| 播放“语音播报” | 可以随着内容增量更新实时朗读 |
| 触发关键词命中高亮等实时分析 | 比如边生成边检查是否包含敏感词或命中某关键词 |
3. 'end' 场景
| 场景 | 说明 |
|---|---|
| 关闭 loading、展示完整内容 | 让消息 UI 变为静态、可复制 |
| 启用该条消息下方的“推荐”、“反馈”等功能 | 推荐按钮可能依赖生成完整后才能出现 |
| 滚动到该消息位置、动画收尾 | 比如 scrollIntoView 或焦点定位等 |
4. 'error' 场景
| 场景 | 说明 |
|---|---|
| 显示错误消息提示 | 如:“生成失败,请稍后再试” |
改变消息状态为 error | 供 UI 样式变红或加 icon |
| 提供重试按钮 | 可以在此时附加“重新生成”操作入口 |
📡 MQTT实时消息监听
MQTT配置与连接
Chat模块支持通过MQTT协议接收实时消息推送。以下是完整的MQTT集成示例:
import { useMqtt } from '@pt/hooks';
// MQTT连接配置
const mqttConfig = {
vhost: "mqtt",
password: "tudou-agentos",
webUri: "ws://bcapi-dev1.e-tudou.com:9080",
username: "tudou-agentos"
};
// 初始化MQTT连接
const { startMqtt, disconnect } = useMqtt({
mqttConfig,
satoken: token.value,
// basePath: "/agentos/" // 单域名部署时需要配置
});
// MQTT消息处理器映射
const handleMqttMessageMap: Record<string, (data: unknown) => void> = {
// 恢复连接处理
'restoreConnection': (data: any) => {
console.log('恢复MQTT连接:', data);
scp.chat.restoreConnection(data);
},
// 可扩展其他消息类型处理
'messageUpdate': (data: any) => {
console.log('消息更新推送:', data);
// 处理消息更新逻辑
},
'threadStatusChange': (data: any) => {
console.log('会话状态变化:', data);
// 处理会话状态变化
}
};
// 启动MQTT消息监听
const listenMqttMessage = async (threadId: string, callback?: (msg: any) => void) => {
console.log(`开始监听会话 ${threadId} 的MQTT消息`);
try {
await startMqtt(`MQTT/chat/${threadId}`, (topic: string, message: any) => {
console.log(`接收到MQTT消息 [${topic}]:`, message);
const msg = JSON.parse(message.toString());
// 执行自定义回调
if (callback) {
callback(msg);
}
try {
const sessionContent = JSON.parse(msg.sessionContent);
console.log('解析的会话内容:', sessionContent);
// 验证消息格式
if (!sessionContent.type) {
throw new Error("MQTT消息缺少type字段,请检查消息格式");
}
// 查找对应的处理器
const handler = handleMqttMessageMap[sessionContent.type];
if (!handler) {
console.warn(`未知的MQTT消息类型: ${sessionContent.type}`);
return;
}
// 执行消息处理
handler(sessionContent.data);
} catch (parseError) {
console.error("解析MQTT消息内容时出错:", parseError);
}
});
console.log(`MQTT监听启动成功: MQTT/chat/${threadId}`);
} catch (error) {
console.error("启动MQTT监听失败:", error);
}
};
// 断开MQTT连接(切换会话或组件销毁时调用)
const disconnectMqtt = () => {
disconnect();
console.log('MQTT连接已断开');
};MQTT 深入指南
MQTT 是 Chat 模块实现实时消息推送的核心技术。除了上述基础用法,您还可以深入了解更多高级特性和最佳实践:
🔗 相关资源
- useMqtt Hook 详解 - 完整的 MQTT Hook 使用指南,包括连接管理、消息订阅、错误处理等
- MQTT 工具函数 - 底层 MQTT 工具函数库,提供连接池、消息队列、重连机制等高级功能
🚀 快速导航
| 功能 | 文档链接 | 说明 |
|---|---|---|
| 基础使用 | useMqtt Hook | MQTT 连接和基本消息处理 |
| 高级配置 | useMqtt Hook | 连接池、重连策略、消息过滤 |
| 工具函数 | MQTT Utils | 底层 MQTT 操作和连接管理 |
| 故障排除 | useMqtt Hook | 常见问题和解决方案 |
💡 最佳实践提示
- 使用
useMqttHook 可以获得更好的 Vue 3 响应式支持 - 通过 MQTT 工具函数可以实现更精细的连接控制
- 建议结合两者使用以获得最佳的开发体验
🚀 AgentOS 3.0 Webhook 解决方案
AgentOS 3.0 计划采用 Webhook 技术 替代传统的 MQTT 推送机制,为聊天系统提供更加可靠和高效的实时通信解决方案。
🎯 核心优势
| 特性 | MQTT (当前) | Webhook (3.0) | 改进说明 |
|---|---|---|---|
| 连接稳定性 | 需要持续连接 | HTTP 请求驱动 | 无需维护长连接,更稳定 |
| 断线恢复 | 复杂的重连逻辑 | 自动重试机制 | 内置指数退避重试策略 |
| 消息可靠性 | 可能丢失消息 | 确认机制 | 保证消息送达,支持幂等性 |
| 开发复杂度 | 需要连接管理 | 标准 HTTP 接口 | 开发和调试更简单 |
| 扩展性 | 受连接数限制 | 无连接限制 | 支持大规模并发 |
🔧 主要应用场景
- 🔌 断开连接恢复: 网络中断后自动同步错过的消息和状态
- 📱 实时通知推送: 任务完成、消息到达等即时通知
- 🔄 状态同步: 多端会话状态实时同步
- ⚡ 长任务监控: AI 生成、文件处理等长时间任务的进度推送
📚 详细文档
想要了解 Webhook 的完整实现方案、集成指南和最佳实践,请查看:
该文档包含:
- 🚀 快速集成指南
- 🔒 安全验证机制
- 📊 性能优化策略
- 🐛 故障排除方案
- 💡 实际应用示例
🔄 技术迁移计划
对于现有使用 MQTT 的项目,我们提供平滑的迁移路径:
- 兼容性保证: 3.0 版本将同时支持 MQTT 和 Webhook
- 渐进式迁移: 可以逐步将功能迁移到 Webhook
- 迁移工具: 提供自动化迁移脚本和指导文档
- 技术支持: 专门的迁移支持团队协助升级
跳转到 /agents/modules/chat/webhook
💡 最佳实践示例
1. 完整的聊天界面实现
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import { ChatEventType } from '@/types/chat';
export default {
setup() {
const messages = ref([]);
const isGenerating = ref(false);
const inputText = ref('');
const activeThreadId = ref('');
const threadList = ref([]);
// 发送消息
const sendMessage = async () => {
if (!inputText.value.trim() || isGenerating.value) return;
const userMessage = inputText.value.trim();
inputText.value = '';
isGenerating.value = true;
try {
await scp.chat.send(userMessage);
} catch (error) {
console.error('发送消息失败:', error);
ElMessage.error('发送失败,请重试');
isGenerating.value = false;
}
};
// 停止生成
const stopGeneration = () => {
scp.chat.stopGeneration();
};
// 切换智能体
const switchAgent = async (agentCode: string) => {
try {
await scp.chat.setAgentCode(agentCode);
ElMessage.success('智能体切换成功');
} catch (error) {
console.error('切换智能体失败:', error);
ElMessage.error('切换失败,请重试');
}
};
// 选择会话
const selectThread = async (threadId: string) => {
try {
await scp.chat.setThreadId(threadId);
activeThreadId.value = threadId;
} catch (error) {
console.error('切换会话失败:', error);
ElMessage.error('切换会话失败');
}
};
// 创建新会话
const createNewThread = async () => {
try {
await scp.chat.setThreadId(null);
ElMessage.success('新会话已创建');
} catch (error) {
console.error('创建新会话失败:', error);
}
};
// 初始化和事件监听
onMounted(async () => {
try {
// 初始化chat模块
await scp.chat.init({
agentCode: 'default_agent',
emptyContent: '抱歉,我暂时无法回复您的问题。'
});
// 批量订阅事件
scp.chat.subscribeEvents({
[ChatEventType.MESSAGES_CHANGE]: (newMessages) => {
messages.value = newMessages;
nextTick(() => scrollToBottom());
},
[ChatEventType.STREAM_UPDATE]: (msgId, content, type) => {
// 实时更新流式内容
updateStreamMessage(msgId, content, type);
},
[ChatEventType.THREAD_CREATED]: (threadId) => {
activeThreadId.value = threadId;
listenMqttMessage(threadId);
},
[ChatEventType.THREAD_CHANGED]: (newThreads) => {
threadList.value = newThreads;
},
[ChatEventType.TOKEN_STATUS_CHANGE]: (status) => {
handleTokenStatus(status);
}
});
} catch (error) {
console.error('初始化失败:', error);
ElMessage.error('系统初始化失败');
}
});
// 清理资源
onUnmounted(() => {
scp.chat.removeAllListeners();
disconnectMqtt();
});
return {
messages,
isGenerating,
inputText,
activeThreadId,
threadList,
sendMessage,
stopGeneration,
switchAgent,
selectThread,
createNewThread
};
}
};2. 智能体切换与状态管理
// 智能体管理组件
const AgentManager = {
setup() {
const currentAgent = ref('');
const availableAgents = ref([
{ code: 'gpt-4', name: 'GPT-4 智能助手', description: '通用对话助手' },
{ code: 'code-helper', name: '代码助手', description: '编程问题解答' },
{ code: 'writer', name: '写作助手', description: '文案创作辅助' }
]);
const switchAgent = async (agentCode: string) => {
try {
// 显示切换loading
const loading = ElLoading.service({ text: '正在切换智能体...' });
await scp.chat.setAgentCode(agentCode);
currentAgent.value = agentCode;
// 可以选择是否保留当前会话或创建新会话
const shouldCreateNewThread = await ElMessageBox.confirm(
'是否为新智能体创建新会话?',
'切换智能体',
{
confirmButtonText: '创建新会话',
cancelButtonText: '继续当前会话'
}
).catch(() => false);
if (shouldCreateNewThread) {
await scp.chat.setThreadId(null);
}
loading.close();
ElMessage.success('智能体切换成功');
} catch (error) {
console.error('切换智能体失败:', error);
ElMessage.error('切换失败,请重试');
}
};
return {
currentAgent,
availableAgents,
switchAgent
};
}
};⚠️ 重要注意事项
1. 初始化顺序
- 必须先调用
scp.chat.init()完成初始化,再执行其他chat相关操作 - 所有依赖 chatStream 的功能(监听、状态检查等)都需要在初始化完成后使用
2. 内存管理
- 务必在组件销毁时清理事件监听器,避免内存泄漏
- 推荐使用
removeAllListeners()或offMultiple()进行批量清理 - MQTT连接也需要在适当时机断开
3. 错误处理
- 网络异常时要有适当的错误提示和重试机制
- Token过期要及时引导用户重新登录
- 生成过程中的异常要能够恢复到正常状态
4. 性能优化
- 使用
isGenerationActive()配合事件监听同步UI状态 - 流式内容更新时注意节流,避免过度渲染
- 长消息列表建议使用虚拟滚动
5. 开发调试
- 强烈建议在开发前先熟悉示例项目
- 项目仓库:
http://gitlab.e-tudou.com/tudou-application/agentos/tudou-agent-scp-web - 在线测试:
http://10.0.36.82:5436/chat/2607551164618825742 - 通过示例项目了解插件的完整能力和最佳实践
🔮 高级特性
1. 多智能体并行管理
// 支持同时管理多个智能体实例
const agents = {
'gpt-4': await scp.chat.createInstance({ agentCode: 'gpt-4' }),
'claude': await scp.chat.createInstance({ agentCode: 'claude' }),
'gemini': await scp.chat.createInstance({ agentCode: 'gemini' })
};
// 并行发送消息到不同智能体
await Promise.all([
agents['gpt-4'].send('分析市场趋势'),
agents['claude'].send('生成技术方案'),
agents['gemini'].send('撰写项目总结')
]);2. 自定义消息处理器
// 注册自定义消息类型处理器
scp.chat.registerMessageHandler('custom_action', (data) => {
console.log('处理自定义动作:', data);
// 执行自定义业务逻辑
});3. 外部组件通信
// 与iframe或外部组件通信
const iframeRef = ref();
// 推送数据到iframe
scp.push(iframeRef.value, {
type: 'chat_message',
data: currentMessage
});📚 快速上手指南
- 克隆示例项目:从GitLab获取完整示例代码
- 配置环境:设置token和接口地址
- 初始化模块:调用
scp.chat.init() - 监听事件:使用
subscribeEvents()批量订阅 - 发送消息:调用
scp.chat.send()开始对话 - 处理响应:在事件回调中更新UI
- 清理资源:组件销毁时移除监听器
通过以上步骤,您就可以快速构建一个功能完整的AI对话应用!
更多高级用法和API详情,请参考项目源码和示例应用。