输入关键词搜索

服务端控制

更新时间: 2025/10/14 18:31:12

本文介绍使用网易云信嵌入式 SDK(NERTC SDK)在 AI 对话过程中,AI 服务端如何通过 OnAiData 回调下发控制指令,以实现对设备功能的调用或状态通知。

消息类型

服务端下发的消息主要分为三大类型:工具控制(tool)事件通知(event)内容传递(content)。这三种类型在单次回调中是互斥的,即每次 OnAiData 回调的 type 字段只会是其中一种。

工具控制(Tool)

用于执行具体的设备功能调用,例如调节音量、控制播放等。当 AI 识别到用户意图需要操作设备时,会下发此类消息。

工具功能 描述 arguments 参数示例
音量控制 调节设备音量 {"volume": 50}
播放控制 控制音乐播放 {"action": "play", "song": "歌曲名"}
设备控制 控制智能设备 {"device": "light", "state": "on"}
信息查询 查询设备状态 {"type": "battery"}

然后,当用户表露对应的意图时,智能体将会调用工具函数,并对参数赋值(例如 {"action": "play", "song": "歌曲名"}),最终透传至终端嵌入式 SDK,触发 OnAiData 回调。业务层获取方向与步数后,驱动硬件层完成对应的行为。

事件通知(Event)

用于将 AI 的内部状态变化通知给设备端,例如 AI 开始或结束说话。

当前支持的事件类型:

  • audio.agent.speech_started: AI 开始说话。
  • audio.agent.speech_stopped: AI 结束说话。

内容传递(Content)

用于从服务端向设备端传递结构化的内容,例如情绪识别结果。设备端可以根据这些内容执行相应的表现,如播放动画。例如,情绪传递:

  • 配置:在 网易云信智能体管理平台 配置情绪识别规则(如 happysad)。
  • 触发:当对话内容命中规则时,服务端下发 content 消息。
  • 数据typeemotionmessage 为具体情绪值(如 happy)。

前提条件

根据本文操作前,请确保您已经完成了:

实现流程

  1. 配置智能体:在 网易云信智能体管理平台 配置可用的工具、内容识别规则等。平台使用指南请参考 配置智能体

    工具控制配置示例
    im-android-flutter.png
    情感识别配置示例
    im-android-flutter.png
  2. AI 决策:AI 根据用户对话内容和后台配置,决定是调用工具、通知事件还是传递内容。

  3. 下发指令:服务端通过 on_ai_data 回调向设备端下发指令。

  4. 设备执行:设备端解析回调数据,并根据消息类型执行相应操作。

回调数据格式

on_ai_data 回调的 data 字段是一个 JSON 字符串,其核心结构如下。其中 toolCallseventcontent 字段根据顶层 type 的值三选一存在。

json{
    "uid": 123,
    "type": "tool",  // 下发类型: "tool"、"content"、或 "event"
    "data": {
        "timestamp": 1754654765,
        "request": "把声音调大一点",
        // --- 以下三者根据 type 的值互斥存在 ---
        // 1. type 为 "tool" 时的数据
        "toolCalls": [{
            "id": "call_123",
            "type": "function",
            "function": {
                "name": "SetVolume",
                "arguments": "{\"volume\": 80}"
            }
        }],
        // 2. type 为 "event" 时的数据
        "event": "audio.agent.speech_stopped",
        // 3. type 为 "content" 时的数据
        "content": {
            "type": "emotion",
            "message": "happy"
        }
    }
}

解析指令数据

您需要解析 on_ai_data 回调中的数据,首先判断顶层 type 字段,然后根据不同类型处理 data 对象中的具体内容。

以下为解析三种不同类型消息的 C++ 示例代码:

C++#include "cJSON.h" // 假设使用 cJSON 库

void MyAppClass::OnAiData(const nertc_sdk_callback_context_t* ctx, nertc_sdk_ai_data_result_t* ai_data) {
    if (!ai_data || ai_data->data_len == 0) {
        return;
    }

    std::string payload(ai_data->data, ai_data->data_len);
    RTC_LOGI(TAG, "NERtc OnAiData payload: %s", payload.c_str());

    cJSON* root_json = cJSON_Parse(payload.c_str());
    if (!root_json) {
        RTC_LOGE(TAG, "Failed to parse root JSON.");
        return;
    }

    cJSON* type_item = cJSON_GetObjectItem(root_json, "type");
    cJSON* data_item = cJSON_GetObjectItem(root_json, "data");

    if (!cJSON_IsString(type_item) || !cJSON_IsObject(data_item)) {
        RTC_LOGE(TAG, "Invalid data structure: 'type' or 'data' field is missing or wrong type.");
        cJSON_Delete(root_json);
        return;
    }

    std::string type_str = type_item->valuestring;

    if (type_str == "tool") {
        // --- 处理工具调用 ---
        cJSON* tool_calls_item = cJSON_GetObjectItem(data_item, "toolCalls");
        if (cJSON_IsArray(tool_calls_item)) {
            cJSON* tool_call;
            cJSON_ArrayForEach(tool_call, tool_calls_item) {
                cJSON* function_item = cJSON_GetObjectItem(tool_call, "function");
                if (!cJSON_IsObject(function_item)) continue;

                cJSON* name_item = cJSON_GetObjectItem(function_item, "name");
                cJSON* args_item = cJSON_GetObjectItem(function_item, "arguments");

                if (cJSON_IsString(name_item) && cJSON_IsString(args_item)) {
                    std::string func_name = name_item->valuestring;
                    std::string func_args = args_item->valuestring;
                    RTC_LOGI(TAG, "Tool call: %s, args: %s", func_name.c_str(), func_args.c_str());
                    
                    // 示例:处理音量设置
                    if (func_name == "SetVolume") {
                        cJSON* args_json = cJSON_Parse(func_args.c_str());
                        if (args_json) {
                            cJSON* volume_item = cJSON_GetObjectItem(args_json, "volume");
                            if (cJSON_IsNumber(volume_item)) {
                                int volume = volume_item->valueint;
                                RTC_LOGI(TAG, "Setting volume to %d", volume);
                                // 在此处调用设备音量调节的实际接口
                                // example: set_device_volume(volume);
                            }
                            cJSON_Delete(args_json);
                        }
                    }
                }
            }
        }
    } else if (type_str == "event") {
        // --- 处理事件通知 ---
        cJSON* event_item = cJSON_GetObjectItem(data_item, "event");
        if (cJSON_IsString(event_item)) {
            std::string event_str = event_item->valuestring;
            RTC_LOGI(TAG, "Received AI event: %s", event_str.c_str());
            // 在此处根据事件类型执行相应操作
            // if (event_str == "audio.agent.speech_started") { ... }
        }
    } else if (type_str == "content") {
        // --- 处理内容传递 ---
        cJSON* content_item = cJSON_GetObjectItem(data_item, "content");
        if (cJSON_IsObject(content_item)) {
            cJSON* content_type_item = cJSON_GetObjectItem(content_item, "type");
            cJSON* message_item = cJSON_GetObjectItem(content_item, "message");
            if (cJSON_IsString(content_type_item) && cJSON_IsString(message_item)) {
                std::string content_type = content_type_item->valuestring;
                std::string message = message_item->valuestring;
                RTC_LOGI(TAG, "Received content. Type: %s, Message: %s", content_type.c_str(), message.c_str());
                // 示例:处理情绪内容
                if (content_type == "emotion") {
                    // 在此处根据情绪 message 执行对应动画或其他表现
                    // example: play_emotion_animation(message);
                }
            }
        }
    }

    cJSON_Delete(root_json);
}
此文档是否对你有帮助?
有帮助
去反馈
  • 消息类型
  • 工具控制(Tool)
  • 事件通知(Event)
  • 内容传递(Content)
  • 前提条件
  • 实现流程
  • 回调数据格式
  • 解析指令数据