目录
任务简介
在上一篇博文中,我们介绍了聆思大模型平台的在线编排能力,利用其出色的低代码能力,我们可以在云平台上完成语音识别、语音合成以及对用户的语言的理解。开发板主要负责语音的采集、上传、接收云平台的处理结果。今天来介绍一下,如何修改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字段的值,通过在控制台输出可以方便地看到云端返回的结果。
完整的代码参见
测试
我们可以使用下面的命令编译程序:
lisa zep build -b csk6_duomotai_devkit apps\LLM_control
这里我们没有加-p参数,这样工具会进行增量编译,从而节省编译的时间。
下载后就可以提供串口观察程序运行的结果。
通过我们用红框标出的三个关键点可以看出,当我们说出“到5层”后,云端争取地返回了处理结果,我们也在开发板上正确地实现了数据解析。
在下一篇博文中介绍如何修改程序的显示部分,使得这个结果可以正确地在屏幕上进行显示。