You need to enable JavaScript to run this app.
文档中心
实时音视频

实时音视频

复制全文
下载 pdf
用户指南
使用 Function Calling
复制全文
下载 pdf
使用 Function Calling
Function Calling 功能允许智能体识别用户话语中的特定意图,并调用外部函数以完成大模型无法独立完成的任务,例如查询实时信息(如天气)、控制设备(如调节音量)等。本教程将以实现一个“调节音量”的功能为例,指导客户端开发者为硬件对话智能体集成 Function Calling 功能。​
使用限制​
Function Calling 功能适用于以下大模型(LLM):​
  • 支持 Function Calling 功能的第三方大模型/Agent。​
  • 请确保您的大模型/Agent 已开启 Function Calling 功能。​
功能介绍​
一次完整的 Function Calling 交互包含以下阶段:​
  1. 准备阶段:​
  • 您需要在客户端应用程序中,定义好具体的本地函数(例如,一个能够根据指令调节设备音量的 adjust_volume 函数),然后向智能体中添加该函数的描述。​
  1. 交互阶段:​
  1. 用户向智能体提问:“把音量调大一点”。​
  1. 服务端上的 LLM 识别出用户的意图,并判断需要调用 adjust_volume 函数。​
  1. 服务端向客户端发送一条包含函数名和参数({ "action": "increase", "step": 10 })的指令。​
  1. 客户端的 SDK 监听到该指令,执行本地的 adjust_volume("increase", 10) 函数,并获取到返回值,例如 "当前音量已调至 50%"。​
  1. 客户端通过 SDK 将此返回值上报给服务端。​
  1. 服务端在收到客户端上报的函数执行结果后,生成音频回复,由客户端负责接收和播放。​
实现概览​
在客户端实现 Function Calling,开发者的主要工作是监听并解析服务端下发的函数调用指令,执行本地函数,并将结果返回给服务端。​
实现方案​
您可以通过低负载(WebSocket)或高质量(RTC)两种方案来实现,这两种方案在消息数据格式上存在如下差异:​
  • 低负载方案 (WebSocket):标准 JSON 格式。​
  • 高质量方案 (RTC):自定义二进制格式,头部 8 字节为消息类型(4 字节)和消息长度(4 字节,大端序),JSON Payload 部分为标准 JSON 字符串。​
下文将分别介绍两种方案的实现细节。​
使用的 API​
整个实现过程主要依赖以下客户端 API:​
  • 这是一个回调函数。当服务端下发工具调用指令时,SDK 会通过此回调将指令内容传递给客户端。​
  • ​
    void (*on_volc_message_data)(volc_engine_t handle, const void* data_ptr, size_t data_len, volc_message_info_t* info_ptr, void* user_data);​
    ​
  • 这是一个主动调用接口。客户端通过此接口,可以向服务端发送自定义消息,例如返回函数执行结果。​
  • ​
    int volc_send_message(volc_engine_t handle, const void* data_ptr, size_t data_len, volc_message_info_t* info_ptr);​
    ​
  • 这是一个主动调用接口。客户端通过此接口,可以向服务端直接发送文本消息,例如播报安抚语的 TTS 请求。​
实现步骤​
前提条件​
您已经在客户端程序中集成了硬件对话智能体。​
准备工作​
在开始具体的编码工作前,您需要完成以下通用的准备环节。​
1. 定义本地函数​
您需要在客户端应用程序中,预先定义好希望智能体调用的本地函数。​
在本文的示例中,我们假设您已定义了 adjust_volume(const char* action, int step) 函数,它能根据传入的指令调节设备音量。​
2. 在控制台配置函数​
无论是创建新智能体还是编辑现有智能体,您都需要在控制台中为设备所关联的智能体开启 Function Calling 功能,并对 adjust_volume 函数进行详细描述。​
  1. 在左侧导航栏,单击 智能体管理。​
  1. 找到您的产品或设备当前关联的智能体,单击智能体卡片上的 编辑。​
  1. 在左侧导航栏,单击 高级配置。​
  1. 找到 Function Calling 区域,创建一个工具。​
  1. 单击 创建工具。​
  1. 在 创建 Function calling 工具 对话框,完成以下配置,然后单击 保存。​
  • ​​​
  • ​
    配置项​
    说明​
    工具名称​
    设置工具的唯一标识符,用于程序调用。​
    工具描述​
    详细说明该工具的功能、使用场景和作用,以便 LLM 能够理解并正确调用。​
    工具类型​
    定义工具的参数类型。可选项:string、number、boolean、integer、object、array。​
    工具参数​
    定义工具的参数结构,包含 参数名称、参数类型、参数描述、枚举、必填 信息。​
    单击 + 添加条目 可为该工具新增一个参数配置。​
    ​
低负载方案实现步骤​
低负载方案通过 WebSocket 实现。当识别到工具调用意图时,服务端会先发送一条不含参数的“通知”消息,再发送一条包含完整参数的“指令”消息。​
步骤 1:接收通知与指令​
您需要在 on_volc_message_data 回调中,通过判断消息的 type 字段来区分并处理两种不同的消息。​
  1. 接收工具调用通知消息。​
  • 当 LLM 识别出工具调用意图后,您会先收到一条 type 为 conversation.item.created 的通知消息,其中 item.type 为 function_call。收到此消息后,您可以选择性地播报安抚语(见步骤 2(可选):播报安抚语)。​
  • 以下是 on_volc_message_data 回调中 data_ptr 参数的示例数据:​
  • ​
    {​
    "event_id": "event_KJIMveRvR",​
    "type": "conversation.item.created",​
    "item": {​
    "type": "function_call",​
    "status": "in_progress",​
    "call_id": "call_fluqrfiiea80klxscs9gf8ut",​
    "name": "adjust_volume",​
    "object": "realtime.item"​
    }​
    } ​
    ​
  1. 接收工具调用指令消息。​
  • 随后,您会收到一条 type 为 response.function_call_arguments.done 的指令消息。收到此消息后,您必须解析其 name 字段获取函数名,解析 arguments 字段获取函数参数,并执行相应的本地函数。​
  • 以下是 on_volc_message_data 回调中 data_ptr 参数的示例数据:​
  • ​
    {​
    "event_id": "event_ssSMDeRvR",​
    "type": "response.function_call_arguments.done",​
    "response_id": "resp_round_1",​
    "item_id": "",​
    "output_index": 0,​
    "call_id": "call_fluqrfiiea80klxscs9gf8ut",​
    "arguments": "{\"action\": \"increase\", \"step\": 10}",​
    "name": "adjust_volume"​
    }​
    ​
  • arguments 字段的值是一个字符串,而不是一个 JSON 对象。您在客户端解析时,需要先获取这个字符串,然后再对这个字符串本身进行一次 JSON 解析,才能得到内部的参数(如 action)。​
步骤 2(可选):播报安抚语​
由于函数执行可能耗费较长时间,为了避免用户在等待过程中感到焦虑或不舒适,您可以在收到步骤 1 的通知消息后,调用 volc_send_message 接口,发送一个 conversation.item.create 事件来播报安抚语。通过播放安抚语,您可以安抚用户的情绪,提升用户体验。​
说明​
若在播放安抚语过程中收到返回的 Function Calling 最终答复,会在安抚语播放完毕后,继续播放 Function Calling 最终答复。​
以下是 volc_send_message 请求中 data_ptr 参数的示例数据:​
​
{​
"event_id": "event_XLLz0egvR",​
"type": "conversation.item.create",​
"item": {​
"type": "message",​
"role": "user",​
"content": [​
{​
"type": "input_tts",​
"text": "好的,正在调节音量"​
}​
],​
"interrupt_mode": 2​
}​
}​
​
其中,interrupt_mode 用于控制文本播报内容的优先级。取值:​
  • 1:高优先级。智能体会终止当前交互,直接播放传入的文本内容。​
  • 2:中优先级。智能体会在当前交互结束后,播放传入的文本内容。​
  • 3:低优先级。如果此时智能体正在交互,智能体会直接丢弃传入的文本内容。如果未在交互,智能体会播放传入的文本内容。​
步骤 3:执行函数并返回结果​
函数执行完成后,您需要调用 volc_send_message 接口,通过 conversation.item.create 事件将执行结果返回给服务端。​
  • 方式 1:直接播报(不经 LLM 处理)​
  • 如果函数返回的结果是一句完整的话(如“音量已调大”),您可以将其包装成 input_tts 类型的消息发送给服务端进行 TTS 处理,处理结果由客户端直接播报。这种方式适用于回复无需润色或其他二次处理、回复的句子较长等场景。​
  • 以下是 volc_send_message 请求中 data_ptr 参数的示例数据:​
  • ​
    {​
    "event_id": "event_XLLz0egvR",​
    "type": "conversation.item.create",​
    "item": {​
    "type": "message",​
    "role": "user",​
    "content": [​
    {​
    "type": "input_tts",​
    "text": "音量已调大"​
    }​
    ],​
    "interrupt_mode": 1​
    }​
    }​
    ​
  • 方式 2:经 LLM 处理后播报​
  • 如果希望通过 LLM 对函数返回的结果进行总结、润色,您可将其包装成 input_text 类型的消息发送回服务端。服务端会先通过 LLM 生成更自然流畅的回复(如“音量已调至 50%”)再进行 TTS 处理,处理结果返回给客户端进行播报。​
  • 以下是 volc_send_message 请求中 data_ptr 参数的示例数据:​
  • ​
    {​
    "event_id": "event_XLLz0egvR",​
    "type": "conversation.item.create",​
    "item": {​
    "type": "message",​
    "role": "user",​
    "content": [​
    {​
    "type": "input_text",​
    "text": "当前音量 50%"​
    }​
    ],​
    "interrupt_mode": 1​
    }​
    }​
    ​
完成上述步骤后,用户会收到智能体根据函数执行结果生成的音频回复消息。​
高质量方案实现步骤​
高质量方案通过 RTC SDK 实现。当识别到工具调用意图时,服务端会先发送一条不含参数的“通知”消息,再发送一条包含完整参数的“指令”消息。​
所有 RTC 的自定义消息(data_ptr)都采用的是“8 字节头部 + JSON Payload”的二进制格式。8 字节头部的具体结构为:​
  • 前 4 字节:消息类型标识符(如工具调用指令的标识符为 "tool",函数调用结果的标识符为 "func" 等)​
  • 后 4 字节:JSON Payload 的字符串长度(大端序)​
头部之后是 JSON 文本内容(即 JSON Payload)。下文将提供 C 语言代码示例,演示如何解析和构造自定义消息。​
步骤 1:接收通知与指令​
您需要在 on_volc_message_data 回调中,通过判断消息头部的 4 字节标识符来区分并处理工具调用通知与指令。​
  1. 接收工具调用通知消息。​
  • 当 LLM 识别出工具调用意图后,您会先收到一条类型为 info 的工具调用通知消息。收到此消息后,您可以选择性地播报安抚语(见步骤 2(可选):播报安抚语)。​
  • JSON Payload 示例(消息头部的 4 字节标识符为 info)​
  • ​
    {​
    "event_type": "function_calling", // 事件类型,固定为此值​
    "function": "adjust_volume", // 被触发的函数名​
    "tool_call_id": "call_12345", // 本次函数调用的唯一ID,后续回传结果时需要用到​
    "response_id": "resp_abcde" // 本次响应的唯一ID,可用于问题排查​
    }​
    ​
  • C 语言代码示例 - 解析工具调用通知消息​
  • ​
    static void __on_volc_message_data(volc_engine_t handle, const void *message, size_t size, volc_message_info_t *info_ptr, void *user_data){​
    /*​
    {​
    "event_type": "function_calling", // 事件类型,固定为此值​
    "function": "adjust_volume", // 被触发的函数名​
    "tool_call_id": "call_12345", // 本次函数调用的唯一ID,后续回传结果时需要用到​
    "response_id": "resp_abcde" // 本次响应的唯一ID,可用于问题排查​
    }​
    */ ​
    cJSON *event_type_obj = cJSON_GetObjectItemCaseSensitive(root, "event_type");​
    if(event_type_obj && strcmp(event_type_obj->valuestring, "function_calling") == 0 ) {​
    cJSON *function_obj = cJSON_GetObjectItemCaseSensitive(root, "function");​
    if(function_obj && strcmp(function_obj->valuestring, "adjust_volume") == 0){​
    volc_conv_service_t conv_service = get_conv_ai_service();​
    volc_send_text_to_agent(conv_service.engine, "别着急,我来给你调整音量", VOLC_AGENT_TYPE_TTS,2);​
    }​
    }​
    cJSON_Delete(root);​
    } ​
    ​
    static char message_buffer[4096];​
    if (size > 8 && size < 4096) {​
    memcpy(message_buffer, message, size);​
    message_buffer[size] = 0;​
    message_buffer[size + 1] = 0;​
    cJSON *root = cJSON_Parse(message_buffer + 8);​
    if (root != NULL) {​
    if (message_buffer[0] == 'i' && message_buffer[1] == 'n' && message_buffer[2] == 'f' && message_buffer[3] == 'o') {​
    // 生产代码中需要异步,避免回调线程阻塞​
    __on_function_calling_trigger(root);​
    }​
    }​
    }​
    ​
    }​
    ​
  1. 接收工具调用指令消息。​
  • 随后,您会收到一条类型为 tool 的工具调用指令。收到此消息后,您必须解析其 name 字段获取函数名,解析 arguments 字段获取函数参数,并执行相应的本地函数。​
说明​
建议采用异步方式执行函数,避免阻塞回调线程,影响其他功能的正常运行。​
  • JSON Payload 示例(消息头部的 4 字节标识符为 tool)​
  • ​
    {​
    "subscriber_user_id" : "",​
    "tool_calls" : ​
    [​
    {​
    "function" : ​
    {​
    "arguments" : "{\\"action\\": \\"increase\\", \\"step\\": 10}",​
    "name" : "adjust_volume"​
    },​
    "id" : "call_py400kek0e3pczrqdxgnb3lo",​
    "type" : "function"​
    }​
    ]​
    }​
    ​
  • C 语言代码示例 - 解析工具调用指令​
  • ​
    static void __on_volc_message_data(volc_engine_t handle, const void *message, size_t size, volc_message_info_t *info_ptr, void *user_data){​
    cJSON *tool_obj_arr = cJSON_GetObjectItem(root, "tool_calls");​
    cJSON *obji = NULL;​
    cJSON_ArrayForEach(obji, tool_obj_arr)​
    {​
    cJSON *id_obj = cJSON_GetObjectItem(obji, "id");​
    cJSON *function_obj = cJSON_GetObjectItem(obji, "function");​
    if (id_obj && function_obj)​
    {​
    cJSON *arguments_obj = cJSON_GetObjectItem(function_obj, "arguments");​
    cJSON *name_obj = cJSON_GetObjectItem(function_obj, "name");​
    char *arguments_json_str = cJSON_GetStringValue(arguments_obj);​
    const char *func_name = cJSON_GetStringValue(name_obj);​
    const char *func_id = cJSON_GetStringValue(id_obj);​
    if (strcmp(func_name, "adjust_volume") == 0 && arguments_json_str)​
    {​
    // 调节音量并返回​
    }​
    }​
    static char message_buffer[4096];​
    if (size > 8 && size < 4096) {​
    memcpy(message_buffer, message, size);​
    message_buffer[size] = 0;​
    message_buffer[size + 1] = 0;​
    cJSON *root = cJSON_Parse(message_buffer + 8);​
    if (root != NULL) {​
    if (message_buffer[0] == 't' && message_buffer[1] == 'o' && message_buffer[2] == 'o' && message_buffer[3] == 'l') {​
    // 生产代码中需要异步,避免回调线程阻塞​
    __on_function_calling_message_received(root);​
    }​
    }​
    }​
    }​
    ​
步骤 2(可选):播报安抚语​
由于函数执行可能耗费较长时间,为了避免用户在等待过程中感到焦虑或不舒适,您可以在收到步骤 1 的通知消息后,调用 volc_send_text_to_agent 接口,发送一条 TTS 消息来播报安抚语。通过播放安抚语,您可以安抚用户的情绪,提升用户体验。​
说明​
若在播放安抚语过程中收到返回的 Function Calling 最终答复,会在安抚语播放完毕后,继续播放 Function Calling 最终答复。​
C 语言代码示例 - 发送安抚语​
​
// 场景:在执行耗时操作前,先安抚用户等待​
volc_send_text_to_agent(​
engine, ​
"好的,正在调节音量", // 安抚语内容​
VOLC_AGENT_TYPE_TTS, // 指定 TTS 进行语音播报​
2 // 中优先级,智能体在当前交互结束后,播放传入的文本内容​
);​
​
步骤 3:执行函数并返回结果​
函数执行完成后,您可以通过两种方式将执行结果返回给服务端,一种是直接播报(不经过 LLM 处理),一种是经 LLM 处理后播报。​
  • 方式 1:直接播报(不经 LLM 处理)​
  • 适用于回复无需润色或其他二次处理、回复的句子较长等场景。​
  • 与播放安抚语类似,您可以主动调用 volc_send_text_to_agent 接口,发送一条 TTS 消息来播报函数返回结果。​
  • C 语言代码示例 - 直接播报​
  • ​
    volc_send_text_to_agent(​
    engine, ​
    "音量已调大", // 执行结果文本​
    VOLC_AGENT_TYPE_TTS, // 指定 TTS 进行语音播报​
    2 // 中优先级,智能体在当前交互结束后,播放传入的文本内容​
    );​
    ​
  • 方式 2:经 LLM 处理后播报​
  • 适用于需要通过 LLM 对函数返回的结果进行总结、润色,生成更自然流畅的回复。​
  • 您需要调用 volc_send_message 接口,将执行结果返回给服务端。​
  • JSON Payload 示例(消息头部的 4 字节标识符为 func)​
  • ​
    {​
    "ToolCallID":"call_py400kek0e3pczrqdxgnb3lo",​
    "Content":"当前音量 50%"​
    }​
    ​
  • C 语言代码示例 - LLM 处理后播报​
  • ​
    cJSON *fc_obj = cJSON_CreateObject();​
    cJSON_AddStringToObject(fc_obj, "ToolCallID", func_id);​
    cJSON_AddStringToObject(fc_obj, "Content", "当前音量 50%");​
    char *json_string = cJSON_Print(fc_obj);​
    static char fc_message_buffer[256] = {'f', 'u', 'n', 'c'};​
    int json_str_len = strlen(json_string);​
    fc_message_buffer[4] = (json_str_len >> 24) & 0xff;​
    fc_message_buffer[5] = (json_str_len >> 16) & 0xff;​
    fc_message_buffer[6] = (json_str_len >> 8) & 0xff;​
    fc_message_buffer[7] = (json_str_len >> 0) & 0xff;​
    memcpy(fc_message_buffer + 8, json_string, json_str_len);​
    cJSON_Delete(fc_obj);​
    volc_message_info_t info = {0};​
    info.is_binary = 1;​
    volc_send_message(conv_service.engine, fc_message_buffer, json_str_len + 8, &info);​
    ​
完成上述步骤后,用户会收到智能体根据函数执行结果生成的音频回复消息。​
最佳实践​
通过系统提示词精准控制调用时机​
您可以通过设计系统提示词(Prompt),为大模型设定明确的规则,以限制函数调用的触发时机,避免在非必要的情况下执行函数调用,从而节约成本和系统资源。​
示例:​
为避免 LLM 对用户的日常闲聊(如“你叫什么名字?”)也尝试调用函数,您可以为智能体设置如下 Prompt:​
​
你是一个智能助理,负责控制智能家居设备和查询信息。​
​
你只能在收到以下意图时才能调用对应的 Function Call:​
1. 当用户明确表示要“调节音量”时,调用 `adjust_volume` 函数。​
2. 当用户明确表示要“调节屏幕亮度”时,调用 `adjust_brightness` 函数。​
3. 当用户查询“天气”、“时间”或“新闻”时,调用 `search_online_info` 函数。​
​
对于其他所有与上述意图无关的用户指令或闲聊,你都不能调用任何 Function Call,并应像一个普通 AI 助手一样直接回答。​
​
​​​
合理使用安抚语提升用户体验​
对于执行耗时较长(如网络请求)的函数,等待过程可能会让用户感到焦虑。因此,在调用这类函数前,主动播报一句安抚语(如“请稍等,正在为您查询”)是提升用户体验的关键。​
建议使用时机:​
  • 网络请求类函数:如查询天气、股票、新闻等,网络延迟是不可控因素。​
  • 耗时 I/O 操作:如读写大文件、查询本地数据库等。​
说明​
根据经验,对于任何预计执行时间可能超过 2 秒的函数,都建议您在调用前先播报安抚语。​
​
最近更新时间:2026.07.02 17:20:29
这个页面对您有帮助吗?
有用
有用
无用
无用