Skip to content

AI语音聊天机器人

简介

本文介绍了一种基于YM310_X09模组的AI语音聊天机器人,通过深度融合百度ASR和kimi大语言模型,能够精准识别语音内容并智能理解语义内涵,为用户生动有趣的交互体验。

系统框图

USB描述符

框图中分为两个部分: * AI服务端:主要用到百度ASR和kimi大语言模型。 * AI客户端:主要用到YM310_X09模组+外接ES8311语音模块。

AI客户端上行通过YM310_X09模组+ES8311 采集用户说话,将音频流传输给AI服务端。AI服务端,通过百度ASR将用户的语音转换为文本,然后通过kimi大语言模型理解语义并处理,最后将处理后的文本转换为语音返回给AI客户端,再次通过YM310_X09模组TTS播放功能将文本转换为音频流,通过ES8311语音模块进行播放。

功能实现

语音识别

通过百度 ASR 模块将用户的语音转换为文本,然后通过 kimi 大语言模型理解语义并处理,最后将处理后的文本转换为语音返回给 AI 客户端。

语音合成

通过 YM310_X09本地TTS,将文本转语音模块将处理后的文本转换为语音返回给 AI 客户端,通过 YM310_X09 模块将音频流转换为语音,通过 8311codec+NS4150C 功放将语音转换为音频流,通过喇叭播放。

语音交互

经 YM310_X09 模块中麦克风采集为设备端音频流,通过用户上行音频流传输给百度 ASR 进行语音转文本。转换后的文本送入 kimi 大语言模型,理解语义并处理,同时可实时返回字幕。处理后的文本经 TTS 文本转语音,变为智能体下行音频流,通过喇叭播放,同时相关字幕可在显示设备呈现 。

环境准备

硬件环境

主要包含YM310_X09模块、ES8311语音模块、天线、喇叭等部件,连接情况如下:

引脚连接

对应的引脚连接图如下

ES8311 YM310_X09
引脚名称 引脚号 引脚名称 引脚号
I2C_SDA 19 I2C_SDA 66
I2C_SCK 1 I2C_SCL 67
I2S_MLCK 2 USIM2_RST 63
I2S_SCLK 6 USIM2_CLK 62
I2S_ASDOUT 7 AUX_RXD 28
I2S_LRCK 8 USIM2_DATA 64
I2S_DSDIN 9 AUX_TXD 29

电源连接

ES8311语音模块 YM310_X09
PA_VCC 5V/3.3V USB供电
VCC_IN 与YM310_X09开发板的VIN相连接
GND 与YM310_X09开发板的GND共地

软件环境

下载yopen代码

git clone https://gitee.com/yuge-info/yopen.git

关键代码

以下为应用代码demo_ai_main.c解析,主要包括以下部分

  • 语音模块相关硬件初始化
    //通过串口输出文本信息
    demo_rec_uart_init();

    //PIPE, 用于存储pcm数据, 录音和tts共用
    d->pipe = osiPipeCreate(DEMO_RECORD_PIPE_SIZE);

    if (d->pipe == NULL)
    {
        DEMO_AI_TRACE("error osiPipeCreate malloc %d false", DEMO_RECORD_PIPE_SIZE);
        yopen_rtos_task_delete(NULL);
    }

    //创建录音设备
    demo_rec_create(d->pipe);

    yopen_rtos_queue_create(&d->queue, sizeof(demo_ai_msg_e), 10);

    //powerkey初始化, 通过按键录音,按下录音,抬起结束录音
    yopen_pwrkey_init(pwrkey_callback);

  • 按键按下,开始录音
// 按键回调函数
static void pwrkey_callback(void)
{
    demo_ai_ctx_s *d = &s_ai_ctx;
    static uint32_t count = 0;
    uint8_t level;

    yopen_get_pwrkey_level(&level);

    if (level == 0)
    {
        //demo_ai_msg_send(DEMO_TEXT_TTS);
        if (demo_ai_status_get() == DEMO_AI_STATUS_REC_WAIT)
        {
            demo_ai_msg_send(DEMO_REC_START);
        }
    }
    else
    {
        if (demo_ai_status_get() == DEMO_AI_STATUS_REC_START)
        {
            demo_ai_msg_send(DEMO_REC_STOP);
        }
    }
}


// AI机器人关键事件处理
void demo_ai_task(void* argv)
{
    //...
    case DEMO_REC_START:
    {
        demo_ai_status_set(DEMO_AI_STATUS_REC_START);

        //开始录音
        demo_rec_start();
        break;
    }

    case DEMO_REC_STOP:
    {
        demo_ai_status_set(DEMO_AI_STATUS_REC_STOP);

        //停止录音
        demo_rec_stop();

        //识别pcm内容转成text
        demo_ai_msg_send(DEMO_PCM_TO_TEXT);
        break;
    }
}


  • 上报录音数据到ASR云端,并获取识别文字
void demo_ai_task(void* argv)
{
    //...
    case DEMO_PCM_TO_TEXT:
    {
        demo_ai_status_set(DEMO_AI_STATUS_PCM_TO_TEXT);

        //识别pcm内容输入text
        memset(d->text, 0, sizeof(d->text));
        //通过HTTP上传pipe中pcm内容到ASR云端,并获取识别文字到d->text中
        if (demo_pcm_to_text(d->pipe, d->text))
        {
            //识别成功,上报识别文字到AI大模型
        }

        demo_ai_status_set(DEMO_AI_STATUS_PCM_TO_TEXT_FAIL);

        break;
    }
}
  • 输出识别后的文字到日志串口
void demo_ai_task(void* argv)
{
    //...
    case DEMO_PCM_TO_TEXT:
    {
        //...
        if (strlen(d->text))
        {
            //串口输出识别文字
            demo_rec_uart_write("--> <",strlen("--> <"));
            yopen_rtos_task_sleep_ms(10);
            demo_rec_uart_write(d->text, strlen(d->text));
            yopen_rtos_task_sleep_ms(50);
            demo_rec_uart_write(">",1);
            demo_rec_uart_write("\r\n",2);
            //上报识别文字到AI大模型
            demo_ai_msg_send(DEMO_TEXT_INTERACTION);
            break;
        }
    }

}
  • 上报识别文字到AI大模型,并获取AI大模型应答文字
void demo_ai_task(void* argv)
{
    //...
    case DEMO_TEXT_INTERACTION:
    {
        demo_ai_status_set(DEMO_AI_STATUS_TEXT_INTERACTION);

        //AI 文本交互
        if (d->text > 0)
        {
            //...

            //上报对话上行文字,并获取AI大模型应答文字
            demo_kimi_text_interaction(d->text, d->tts_text);

            //通过TTS播放应答文字
            if (strlen(d->tts_text))
            {
                demo_ai_msg_send(DEMO_TEXT_TTS);
                break;
            }

            demo_ai_status_set(DEMO_AI_STATUS_TEXT_INTERACTION_FAIL);
        }
        break;
    }
}
  • 本地TTS播放文字
void demo_ai_task(void* argv)
{
    //...
    case DEMO_TEXT_TTS:
    {
        //串口输出tts_text
        demo_rec_uart_write("<-- <",strlen("<-- <"));
        yopen_rtos_task_sleep_ms(10);
        demo_rec_uart_write(d->tts_text, strlen(d->tts_text));
        yopen_rtos_task_sleep_ms(50);
        demo_rec_uart_write(">",1);
        demo_rec_uart_write("\r\n",2);
        demo_ai_status_set(DEMO_AI_STATUS_TTS);

        //本地TTS播放tts_text
        if (d->tts_text)
        {
            demo_tts_play(d->pipe, d->tts_text, strlen(d->tts_text));
        }
        //等待播放完成
        demo_ai_status_set(DEMO_AI_STATUS_REC_WAIT);

        break;
    }
}

工程编译

# 命令行下执行
build.bat YM310_X09S.U62 ai

固件下载

将编译好的固件烧录到YM310_X09模组中。

对话演示