端插件是扣子插件的一种类型,能够使智能体直接与本地设备进行交互,实现对本地设备的控制和信息获取。当大模型推断出需要调用端插件时,会通过消息机制与本地设备建立连接,获取设备的执行结果并返回给大模型继续推理。
用户对本地设备下达指令,指令传递给智能体后,大模型根据端插件的描述判断是否需要调用端插件。若需调用,端插件将直接调用集成的本地设备的能力,实现对设备的控制和信息获取。例如,端插件集成了蓝牙音箱的能力,用户可以通过语音控制蓝牙音箱的音量。
步骤1
在原有Chat对话流程的基础上,扣子API会返回一个调用消息到端侧,即 server.conversation.chat.requires_action
在这个消息中,扣子会返回需要调用的 方法 及 参数
"required_action": {
"type": "submit_tool_outputs",
"submit_tool_outputs": {
"tool_calls": [
{
"id": "BUJJREJHEkpGEhBeQRdCRF5HS0ERXhIRS0JeQ0oRRUsSRxFASxZFSUI=",
"type": "function",
"function": {
"name": "op_torch_crl",
"arguments": "{"enable":"1"}"
}
}
]
}
},
比如上面这个required_action : 要求端侧调用一个函数 op_torch_crl ****调用参数 :{"enable":"1"}
这其实就是一个 Function Call (或者 Tool Call)
步骤2
端侧在本地调用函数,并返回结果
https://www.coze.cn/open/docs/guides/use_local_plugin
比如
在端侧调用本地函数
// 端插件能力
// 定义 op_torch_crl 函数
const op_torch_crl = (enable: string): string => {
// 这里是 op_torch_crl 的具体实现
// 假设返回一个字符串结果
return `手电操作完成!: ${enable}`;
};
上报本地运行结果(react 版)
const submitToolOutputs = async (conversationId: string, chatId: string, toolCallId: string, output: string) => {
const url = 'https://api.coze.cn/v3/chat/submit_tool_outputs';
const body = {
conversation_id: conversationId,
chat_id: chatId,
tool_outputs: [
{
tool_call_id: toolCallId,
output: output
}
],
stream: false
};
console.log('-- conversationId :',conversationId)
console.log('-- toolCallId :',toolCallId)
console.log('-- chatId :',chatId)
console.log('-- output :',output)
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
});
if (!response.ok) {
throw new Error(`Failed to submit tool outputs: ${response.statusText}`);
}
console.log('Tool outputs submitted successfully');
} catch (error) {
console.error('Error submitting tool outputs:', error);
}
};
我们来实现一个明星智能体: 周杰伦智能体
实现的方法
- 利用扣子语音克隆功能,复制周杰伦的声音。https://www.coze.cn/open/playground/clone_voice
- 实现2个端插件,用于播放音乐和控制音量
- 实现一个 周杰伦的人设智能体
创建端插件:音乐播放
1 在工作空间,选择 资源 -- 插件
-
创建播放音乐端插件
填写端插件名称,创建方式选择 端侧插件
3 继续创建插件
4.增加输入参数和输出参数描述
1 编辑输入参数 2 输入参数名称 3描述参数作用 4 参数类型 5 函数返回参数 6返回参数说明 7 返回参数类型
5.试运行中直接点击完成
这里主要是定义一个方法,不需要实现具体内容(在MacBook上实现该方法)
5.类似方法可以创建 控制音量的端插件
添加处理conversation.chat.requires_action 的方法
解析出需要调用的方法 functionName 和 需要执行的参数 args.music_name
if (eventName === 'server.conversation.chat.requires_action') {
const { required_action } = data.data;
console.log('--------required_action------>', required_action)
if (required_action.type === 'submit_tool_outputs') {
const toolCall = required_action.submit_tool_outputs.tool_calls[0];
const functionName = toolCall.function.name;
const args = JSON.parse(toolCall.function.arguments);
if (functionName === 'play_music') {
console.log('-- music_name:', args.music_name)
const result = play_music(args.music_name);
submitToolOutputs(
String(data.data.conversation_id),
String(data.data.id),
String(toolCall.id),
String(result)
)
}
实现音乐播放的本地方法
前端使用 react, 把音乐文件放在本地
const audioRef = useRef<HTMLAudioElement | null>(null);
...
const play_music = (musicName: string): string => {
if (audioRef.current) {
// 停止播放
if (musicName === 'music_stop') {
stopMusic();
return 'Music stopped';
}
// 检查URL 音乐
const isUrl = musicName.startsWith('https://');
audioRef.current.src = isUrl ? musicName : `/assets/${musicName}.mp3`;//播放本地文件
audioRef.current.play().catch(error => {
console.error('Error playing audio:', error);
});
setCurrentMusic(musicName);
setIsMusicPlaying(true);
return `Playing music done: ${musicName}`;
}
返回播放结果
...
const result = play_music(args.music_name);
submitToolOutputs(
String(data.data.conversation_id),
String(data.data.id),
String(toolCall.id),
String(result)
制作一个 周杰伦智能体
将端插件配置到智能体
效果演示
https://www.bilibili.com/video/BV1LEXWYYEiU/
暂时无法在飞书文档外展示此内容