目录
任务简介
终端处理的基本逻辑
代码修改
测试
任务简介
在上一篇博文中,我们介绍了聆思大模型平台的在线编排能力,利用其出色的低代码能力,我们可以在云平台上完成语音识别、语音合成以及对用户的语言的理解。开发板主要负责语音的采集、上传、接收云平台的处理结果。今天来介绍一下,如何修改LLM_control示例来实现对云平台返回的结果进行处理。
终端处理的基本逻辑
在前面的博文中,已经介绍了LLM_control示例的架构流程,其中main.c文件的consumer_thread线程是端侧处理的核心代码,该函数负责对云端返回的数据处理。
在介绍云端编排时,我们在处理代码中给出了如下的数据模板,这个模板就是开发板收到的数据的基本格式,每次的差别主要是其中value字段。
//数据模版,不建议直接修改 const intentTemplate = { "text": "", "rc": 0, "data": { "result": [{ "id": "xxx", "type": "Decimal", "value": "1" }] }, "answer": { "text": "已完成设置", "type": "T" }, "service": "floor", "service_pkg": "media", "category": "LISTENAI.floor"
我们所提供的电梯服务和厂商所提供的其他服务的差别主要在于service字段,我们的服务中这个字段为floor。所以我们可以对厂商提供的代码可以基本不做修改,只是添加一个服务处理的分支。
代码修改
在代码中我们只关注AIUI_ZBUS_NLP这部分,其他的代码都是处理语音识别和语音播放的,我们可以保留不变。在这部分,我们判断service字段,如果为floor就进入我们的代码分支。
ZBUS_SUBSCRIBER_DEFINE(main_sub, 4); static void consumer_thread(void) { // int ret = 0; zbus_chan_add_obs(&wifi_zbus_channel, &main_sub, K_FOREVER); zbus_chan_add_obs(&aiui_zbus_channel, &main_sub, K_FOREVER); const struct zbus_channel *chan; wifi_zbus_msg_t wifi_msg = {}; aiui_zbus_msg_t aiui_msg = {}; while (!zbus_sub_wait(&main_sub, &chan, K_FOREVER)) { LOG_INF("Channel %s", zbus_chan_name(chan)); if (&wifi_zbus_channel == chan) { zbus_chan_read(&wifi_zbus_channel, &wifi_msg, K_MSEC(500)); LOG_INF("------------get wifi evt: %x", wifi_msg.event); switch(wifi_msg.event){ case WIFI_ZBUS_CONNECTED: is_wifi_connected = true; break; case WIFI_ZBUS_DISCONNECTED: is_wifi_connected = false; if(is_aiui_initialized){ aiui_disconnect(aiui_handle); } break; case WIFI_ZBUS_GOT_IP: if(is_aiui_initialized){ k_timer_start(&aiui_reconnect_timer, K_NO_WAIT, K_NO_WAIT); } break; default: break; } } else if (&aiui_zbus_channel == chan) { zbus_chan_read(&aiui_zbus_channel, &aiui_msg, K_MSEC(500)); LOG_INF("------------get aiui evt: %x", aiui_msg.event); if (aiui_msg.event == AIUI_ZBUS_GOT_VAD) { // 此处代码省略 } else if (aiui_msg.event == AIUI_ZBUS_NLP) { cJSON *root = cJSON_Parse(aiui_msg.data); if(root != NULL) { cJSON *intent = cJSON_GetObjectItem(root, "intent"); if(intent != NULL) { cJSON *service = cJSON_GetObjectItem(intent, "service"); if(service != NULL){ if(!strcmp(service->valuestring, "LLMDrawing")){ // 此处代码省略 } }else if(!strcmp(service->valuestring, "bgColor")){ // 此处代码省略 } }else if(!strcmp(service->valuestring, "floor")){ cJSON *data = cJSON_GetObjectItem(intent, "data"); if(data != NULL){ cJSON *result = cJSON_GetObjectItem(data, "result"); if(result != NULL){ // int size = cJSON_GetArraySize(result); cJSON *item = cJSON_GetArrayItem(result, 0); cJSON *type = cJSON_GetObjectItem(item, "type"); cJSON *value = cJSON_GetObjectItem(item, "value"); LOG_INF("service=%s: type=%s, value=%s", service->valuestring, type->valuestring, value->valuestring); int32_t floor = 0; sscanf(value->valuestring, "%d", &floor); LOG_INF("floor value: %d", floor); ui_set_layer(floor); } } }else { LOG_ERR("Unknown service: %s", service->valuestring); } }else{ LOG_ERR("func: %s, line: %d", __FUNCTION__, __LINE__); } }else{ LOG_ERR("func: %s, line: %d", __FUNCTION__, __LINE__); } cJSON_Delete(root); }else{ LOG_ERR("func: %s, line: %d", __FUNCTION__, __LINE__); } csk_free(aiui_msg.data); } else if (aiui_msg.event == AIUI_ZBUS_INVALID_TOKEN) { is_invalid_token = true; } } } }
在这部分代码中,我们主要是提取并解析了value字段的值,通过在控制台输出可以方便地看到云端返回的结果。
完整的代码参见
https://download.csdn.net/download/bit_mike/88959552https://download.csdn.net/download/bit_mike/88959552
测试
我们可以使用下面的命令编译程序:
lisa zep build -b csk6_duomotai_devkit apps\LLM_control
这里我们没有加-p参数,这样工具会进行增量编译,从而节省编译的时间。
下载后就可以提供串口观察程序运行的结果。
通过我们用红框标出的三个关键点可以看出,当我们说出“到5层”后,云端争取地返回了处理结果,我们也在开发板上正确地实现了数据解析。
在下一篇博文中介绍如何修改程序的显示部分,使得这个结果可以正确地在屏幕上进行显示。