基于ChatGLM人工智能模型语音识别机器人

gec6818客户端

#include <stdio.h>

#include <fcntl.h>

#include <sys/mman.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netinet/ip.h> /* superset of previous */

#include <arpa/inet.h>

#include <unistd.h>

#include <string.h>

#include<stdlib.h>

#include <linux/input.h>


 

// 添加字库接口

#include "font.h"

// 刷颜色

void show_color(int *lcd, int color)

{

    for (int y = 0; y < 480; y++)

    {

        for (int x = 0; x < 800; x++)

        {

            *(lcd + y * 800 + x) = color;

        }

    }

}

// 映射LCD设备

void *mmap_lcd()

{ // 1.打开LCD设备

    int fd = open("/dev/fb0", O_RDWR);

    if (fd < 0)

    {

        printf("打开LCD设备失败\n");

        return NULL;

    }

    else

    {

        printf("打开LCD设备成功\n");

    }

    // 2.把硬件设备LCD的地址映射到应用层中

    void *p = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    if (p == MAP_FAILED)

    {

        printf("映射失败\n");

        return NULL;

    }

    else

    {

        printf("映射成功\n");

        return p;

    }

}

// 初始化字库

font *init_font(int size)

{

    // 3.加载字库文件

    font *f = fontLoad("/usr/share/fonts/DroidSansFallback.ttf");

    if (f == NULL)

    {

        printf("加载字库失败\n");

        return NULL;

    }

    // 4.设置字体大小

    fontSetSize(f, size);

}

// 显示汉字        框长     框高     框背景色             汉字框中距离       汉字文本   汉字颜色       换行               映射设备      框在lcd位置

void show_text(u32 b_w, u32 b_h, u32 b_color,font *f, s32 t_x, s32 t_y, char *text, u32 t_color, s32 maxWidth,unsigned int *lcd, int px, int py)

{

    // 创建一个字体输出框  ,并设置为绿色

    bitmap *bm = createBitmapWithInit(b_w, b_h, 4, b_color);

    // 放入文件到画框中

    fontPrint(f, bm, t_x, t_y, text, t_color, maxWidth);

    show_font_to_lcd(lcd, px, py, bm);

    // 销毁画板

    destroyBitmap(bm);

}

void LCD()

{

     // 1.映射LCD设备

    int *lcd = mmap_lcd();

    // 刷颜色

    show_color(lcd, 0xdddddd);

    // 2.初始化字库

    font *f = init_font(50);

    show_text(780, 50, getColor(0, 255, 255, 255), f, 0, 0, "问题显示", 0x0,780, lcd,10,10);

    show_text(780,340, getColor(0, 255, 255, 255), f, 0, 0, "答案显示", 0x0,780, lcd,10,70);

    show_text(200, 50, getColor(0, 255, 255, 255), f,25, 0, "语音输入", 0x0,  0, lcd,10,420);

    show_text(200, 50, getColor(0, 255, 255, 255), f,25, 0, "语义理解", 0x0,  0, lcd,300,420);

    show_text(200, 50, getColor(0, 255, 255, 255), f,25, 0, "历史记录", 0x0,  0, lcd,590,420);

}

//触摸屏模块

int cmp(int *x, int *y)

{  

    int fd = open("/dev/input/event0", O_RDWR);  

    if (fd < 0)

    {  

        printf("打开触摸屏失败\n");  

        return -1;  

    }  

    printf("点击触摸屏选择录制\n");  

    struct input_event ev;  

    int temp_x = 0, temp_y = 0;  

    while (1)

    {  

        if (read(fd, &ev, sizeof(ev)) < 0) {  

            perror("读取触摸屏设备失败");  

            close(fd);  

            return -1;  

        }  

        if (ev.type == EV_ABS)

        {  

            if (ev.code == ABS_X)

            {  

                temp_x = ev.value * 800 / 1024;  

            }

            else if (ev.code == ABS_Y)

            {  

                temp_y = ev.value * 480 / 600;  

            }  

            if (temp_x != 0 && temp_y != 0)

            {  

                *x = temp_x;  

                *y = temp_y;  

                break;  

            }  

        }  

    }  

    printf("x=%d, y=%d\n", *x, *y);  

    close(fd);  

    return 0;  

}

//客户端发送音频文件

int Get_Speech_Text(char *name, char *text)

{

    // 1.创建客户端通信对象

    int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);

    // 2.链接服务器

    struct sockaddr_in server_addr;

    server_addr.sin_family = AF_INET;    // IPV4

    server_addr.sin_port = htons(1204); // 设置端口

    server_addr.sin_addr.s_addr = inet_addr("192.168.46.62");

    if (connect(tcp_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)

    {

        printf("连接失败\n");

        return -1;

    }

    // 1.打开文件

    int fd = open(name, O_RDWR);

    if (fd < 0)

    {

        printf("打开文件失败\n");

        return -1;

    }

    while (1) // 不断把本地音频数据发送给服务器

    {

        // 2.读取文件的内容

        char buf[4096] = {0};

        int size = read(fd, buf, 4096);

        if (size <= 0)

        {

            printf("发送文件完毕,等待识别....\n");

            break;

        }

        // 3.发送到网络中

        write(tcp_socket, buf, size);

    }

    // 读取服务器返回的语义

    char msg[4096] = {0};

    read(tcp_socket, msg, 4096);

    // 保存语义

    strcpy(text, msg);

    // 关闭通信

    close(tcp_socket);

    close(fd);

}

int Get_Speech_Answer(char *question, char *answer)

{

   

    // 1.创建网络通信对象

    int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);

    // 2.链接服务器

    struct sockaddr_in server_addr;

    server_addr.sin_family = AF_INET;

    server_addr.sin_port = htons(1204);

    server_addr.sin_addr.s_addr = inet_addr("192.168.46.62");

    if (connect(tcp_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)

    {

        printf("链接服务器失败\n");

        return -1;

    }

    else

    {

        printf("链接服务器成功\n");

    }

        printf("\n\n问题是:%s\n\n", question);

        // 把问题发送给服务器

        write(tcp_socket, question, strlen(question));

        printf("发送问题完毕,等待识别....\n");

        // 读取服务器返回的语义

        char msg[4096] = {0};

        read(tcp_socket, msg, 4096);

        // 保存语义

        strcpy(answer, msg);

        close(tcp_socket);

        // 读取服务器返回的答案

        //read(tcp_socket, answer, sizeof(answer));

        //printf("答案:%s\n", answer);

        // 显示答案

        //show_text(780,340, getColor(0, 255, 255, 255), f, 0, 0, answer, 0x0,780, lcd,10,70);

   

}

char *Choose_part(char *part)

{

   

   // 1.创建网络通信对象

    int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);

    // 2.链接服务器

    struct sockaddr_in server_addr;

    server_addr.sin_family = AF_INET;

    server_addr.sin_port = htons(1204);

    server_addr.sin_addr.s_addr = inet_addr("192.168.46.62");

    if (connect(tcp_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)

    {

        printf("链接服务器失败\n");

        return NULL;

    }

    else

    {

        printf("链接服务器成功\n");

    }

    printf("功能模块确认中\n");

    write(tcp_socket, part, strlen(part));

    printf("发送完毕,等待服务器响应....\n");

   


 

}




 

int main()

{

   

        //初始化lcd

        LCD();

        font *f = init_font(50);

        font *f1 = init_font(25);

        int *lcd = mmap_lcd();

      while (1)

{  

        int x = 0, y = 0;

        char text2[1024];

        char answer[4096] = {0};

        char text[1024] = {0};

        cmp(&x,&y);

        printf("%d,%d\n",x,y);

   

        //语音输入

        if (x>10 && x<210 && y>420 && y<470)

        {  

           

           

            //选择功能块

            char part1[1024] = "1";

            Choose_part(part1);

            //执行对应功能

            printf("开始录音\n");

            system("arecord -d 5 -r 16000  -c 1 -f S16_LE -t wav test.wav");

            printf("录音完成\n\n");

            printf("传输文件\n");

            //char text[4096] = {0};

            Get_Speech_Text("test.wav", text); // 获取音频文件的语义

            printf("结果:%s\n", text);

            //char text2[1024] = {0};

           

            show_text(780, 50, getColor(0, 255, 255, 255), f, 0, 0,text, 0x0,780, lcd,10,10);

            strcpy(text2,text);

        }

        //语义分析

        else if (x>300 && x<500 && y>420 && y<470)

        {  

           

            //选择功能块

            char part2[1024] = "2";

            Choose_part(part2);

            //执行对应功能

            //char text[1024]="介绍一下无畏契约";

            Get_Speech_Answer(text2, answer);

            printf("答案是:%s\n\n",answer);

            show_text(780,340, getColor(0, 255, 255, 255), f1, 0, 0, answer, 0x0,780, lcd,10,70);

           

        }

        else if (x>590 && x<790 && y>420 && y<470)

        {  

            //选择功能块

            char part3[1024] = "3";

            Choose_part(part3);

            //执行对应功能

            printf("开始播放\n");

            system("aplay test.wav");

            printf("播放完成\n\n");

           

        }

           

 }

   

    return 0;

}

主机服务端

/*

 * 语音听写(iFly Auto Transform)技术能够实时地将语音转换成对应的文字。

 */

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netinet/ip.h> /* superset of previous */

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <fcntl.h>

#include "msp_cmn.h"

#include "msp_errors.h"

#include "qisr.h"

#define BUFFER_SIZE 4096

#define FRAME_LEN 640

#define HINTS_SIZE 100

// 识别音频文件

void run_iat(const char *audio_file, const char *session_begin_params, char *text)

{

    const char *session_id = NULL;

    char rec_result[BUFFER_SIZE] = {0};

    char hints[HINTS_SIZE] = {0}; // hints为结束本次会话的原因描述,由用户自定义

    unsigned int total_len = 0;

    int aud_stat = MSP_AUDIO_SAMPLE_CONTINUE; // 音频状态

    int ep_stat = MSP_EP_LOOKING_FOR_SPEECH;  // 端点检测

    int rec_stat = MSP_REC_STATUS_SUCCESS;    // 识别状态

    int errcode = MSP_SUCCESS;

    FILE *f_pcm = NULL;

    char *p_pcm = NULL;

    long pcm_count = 0;

    long pcm_size = 0;

    long read_size = 0;

    if (NULL == audio_file)

        goto iat_exit;

    f_pcm = fopen(audio_file, "rb");

    if (NULL == f_pcm)

    {

        printf("\nopen [%s] failed! \n", audio_file);

        goto iat_exit;

    }

    fseek(f_pcm, 0, SEEK_END);

    pcm_size = ftell(f_pcm); // 获取音频文件大小

    fseek(f_pcm, 0, SEEK_SET);

    p_pcm = (char *)malloc(pcm_size);

    if (NULL == p_pcm)

    {

        printf("\nout of memory! \n");

        goto iat_exit;

    }

    read_size = fread((void *)p_pcm, 1, pcm_size, f_pcm); // 读取音频文件内容

    if (read_size != pcm_size)

    {

        printf("\nread [%s] error!\n", audio_file);

        goto iat_exit;

    }

    printf("\n开始语音听写 ...\n");

    session_id = QISRSessionBegin(NULL, session_begin_params, &errcode); // 听写不需要语法,第一个参数为NULL

    if (MSP_SUCCESS != errcode)

    {

        printf("\nQISRSessionBegin failed! error code:%d\n", errcode);

        goto iat_exit;

    }

    while (1)

    {

        unsigned int len = 10 * FRAME_LEN; // 每次写入200ms音频(16k,16bit):1帧音频20ms,10帧=200ms。16k采样率的16位音频,一帧的大小为640Byte

        int ret = 0;

        if (pcm_size < 2 * len)

            len = pcm_size;

        if (len <= 0)

            break;

        aud_stat = MSP_AUDIO_SAMPLE_CONTINUE;

        if (0 == pcm_count)

            aud_stat = MSP_AUDIO_SAMPLE_FIRST;

        printf(">");

        ret = QISRAudioWrite(session_id, (const void *)&p_pcm[pcm_count], len, aud_stat, &ep_stat, &rec_stat);

        if (MSP_SUCCESS != ret)

        {

            printf("\nQISRAudioWrite failed! error code:%d\n", ret);

            goto iat_exit;

        }

        pcm_count += (long)len;

        pcm_size -= (long)len;

        if (MSP_REC_STATUS_SUCCESS == rec_stat) // 已经有部分听写结果

        {

            const char *rslt = QISRGetResult(session_id, &rec_stat, 0, &errcode);

            if (MSP_SUCCESS != errcode)

            {

                printf("\nQISRGetResult failed! error code: %d\n", errcode);

                goto iat_exit;

            }

            if (NULL != rslt)

            {

                unsigned int rslt_len = strlen(rslt);

                total_len += rslt_len;

                if (total_len >= BUFFER_SIZE)

                {

                    printf("\nno enough buffer for rec_result !\n");

                    goto iat_exit;

                }

                strncat(rec_result, rslt, rslt_len);

            }

        }

        if (MSP_EP_AFTER_SPEECH == ep_stat)

            break;

        usleep(200 * 1000); // 模拟人说话时间间隙。200ms对应10帧的音频

    }

    errcode = QISRAudioWrite(session_id, NULL, 0, MSP_AUDIO_SAMPLE_LAST, &ep_stat, &rec_stat);

    if (MSP_SUCCESS != errcode)

    {

        printf("\nQISRAudioWrite failed! error code:%d \n", errcode);

        goto iat_exit;

    }

    while (MSP_REC_STATUS_COMPLETE != rec_stat)

    {

        const char *rslt = QISRGetResult(session_id, &rec_stat, 0, &errcode);

        if (MSP_SUCCESS != errcode)

        {

            printf("\nQISRGetResult failed, error code: %d\n", errcode);

            goto iat_exit;

        }

        if (NULL != rslt)

        {

            unsigned int rslt_len = strlen(rslt);

            total_len += rslt_len;

            if (total_len >= BUFFER_SIZE)

            {

                printf("\nno enough buffer for rec_result !\n");

                goto iat_exit;

            }

            strncat(rec_result, rslt, rslt_len);

        }

        usleep(150 * 1000); // 防止频繁占用CPU

    }

    printf("\n语音听写结束\n");

    // printf("%s\n", rec_result);

    strcpy(text, rec_result); // 保存识别结果

iat_exit:

    if (NULL != f_pcm)

    {

        fclose(f_pcm);

        f_pcm = NULL;

    }

    if (NULL != p_pcm)

    {

        free(p_pcm);

        p_pcm = NULL;

    }

    QISRSessionEnd(session_id, hints);

}

// 全局变量,所有函数都可以使用

int new_socket = 0;

// 通过服务器socket 获取客户端发送的音频文件

char *Get_Network_File(int tcp_socket)

{

    // 接收客户端的链接请求

    printf("等待客户端发生识别文件.....\n");

    new_socket = accept(tcp_socket, NULL, NULL);

    if (new_socket < 0)

    {

        printf("客户端链接失败\n");

        return NULL;

    }

    // 不断接收客户端的发送的内容

    //  1.打开文件

    int fd = open("test.wav", O_RDWR | O_CREAT | O_TRUNC, 0777);

    if (fd < 0)

    {

        printf("创建文件失败\n");

        return NULL;

    }

    int down_size = 0;

    while (1) // 不断读取客户端发送过来的数据

    {

        // 2.读取文件的内容

        char buf[4096] = {0};

        int size = read(new_socket, buf, 4096);

        // 3.发送到网络中

        write(fd, buf, size);

        down_size += size; // 记录当前接收的总大小

        if (down_size >= 160996)

        {

            printf("接收完毕开始识别.....\n");

            close(fd);

            break;

        }

    }

    // 返回识别的文件名

    return "test.wav";

}

// 调用ChatGLM函数,qustion 问题, answer 答案

int ChatGLM(char *qustion, char *answer)

{

    // 定义一个缓存区

    char cmd[1024] = {0};

    sprintf(cmd, "python3  ChatGLM_rebot.py  %s", qustion);

    // 加载python脚本

    FILE *fp = popen(cmd, "r");

    if (fp == NULL)

    {

        printf("加载脚本失败\n");

        return -1;

    }

    char buf[4096] = {0};

    // 不断读取脚本返回的数据

    while (1)

    {

        // 读取脚本返回的数据 到 buf 中

        char *ret = fgets(buf, sizeof(buf), fp);

        if (ret == NULL)

        {

            break;

        }

    }

    // 处理前面的无关信息

    char *p = strstr(buf, "content=");

    // 处理后面的无关信息

    char *q = strstr(buf, "role=");

    *(q - 2) = '\0';

    // 输出处理后的数据

    strcpy(answer, p + 8); // 存储答案

    // 关闭文件流

    pclose(fp);

}

char *Get_Network_Text(int tcp_socket,char *buf)

{

    new_socket = accept(tcp_socket, NULL, NULL);

    printf("服务器连接 %d\n",new_socket);

    char recv_buf[1024] = {0};

    read(new_socket, recv_buf, 1024);

    printf("接收到的数据内容:%s\n",recv_buf);

    strcpy(buf,recv_buf);

   

}

int main(int argc, char *argv[])

{

    int ret = MSP_SUCCESS;

    const char *login_params = "appid = 07bf224a, work_dir = ."; // 登录参数,appid与msc库绑定,请勿随意改动

    /*

     * sub:             请求业务类型

     * domain:          领域

     * language:            语言

     * accent:          方言

     * sample_rate:     音频采样率

     * result_type:     识别结果格式

     * result_encoding: 结果编码格式

     *

     */

    const char *session_begin_params = "sub = iat, domain = iat, language = zh_cn, accent = mandarin, sample_rate = 16000, result_type = plain, result_encoding = utf8";

    /* 用户登录 */

    ret = MSPLogin(NULL, NULL, login_params); // 第一个参数是用户名,第二个参数是密码,均传NULL即可,第三个参数是登录参数

    if (MSP_SUCCESS != ret)

    {

        printf("MSPLogin failed , Error code %d.\n", ret);

        goto exit; // 登录失败,退出登录

    }

    // 绑定网络服务器地址信息

    int tcp_socket = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in server_addr;

    server_addr.sin_family = AF_INET;

    server_addr.sin_port = htons(1112);

    server_addr.sin_addr.s_addr = inet_addr("192.168.46.54");

    if (bind(tcp_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)

    {

        printf("绑定服务器失败\n");

        return -1;

    }

    // 设置监听模型

    if (listen(tcp_socket, 5) < 0)

    {

        printf("监听失败\n");

        return -1;

    }

    while (1)

    {

        char buf[1024] ={0};

        char part1[1024] = "1";

        char part2[1024] = "2";

        Get_Network_Text(tcp_socket,buf);

        printf("buf:%s\n",buf);

        if((strcmp(buf,part1)) == 0)

        {

            // 获取网络识别文件

            char *file = Get_Network_File(tcp_socket);

            char text[4096] = {0};

            run_iat(file, session_begin_params, text); // iflytek02音频内容为“中美数控”;如果上传了用户词表,识别结果为:“中美速控”。

            // 把识别后的内容发生给客户端

            write(new_socket, text, strlen(text));

            printf("识别结果:%s\n", text);

            // 关闭客户端对象

            close(new_socket);  

        }

        else if((strcmp(buf,part2)) == 0)

        {

            char buf[1024] ={0};

            char msg[1024] ={0};

            char answer[1024] = {0};

            printf("开始运行\n");

            // 获取网络识别文件

            Get_Network_Text(tcp_socket,buf);

            printf("%s",buf);

            // 调用模型

            ChatGLM(buf, answer);

            // 把识别后的内容发生给客户端

            strcpy(msg,answer);

            write(new_socket, msg, strlen(msg));

            printf("发送内容为:%s",msg);

            // 关闭客户端对象

            close(new_socket);

           

        }

        else    

        {

            printf("未接收到命令\n");

            break;

        }

    }

exit:

    MSPLogout(); // 退出登录

    return 0;

}

ChatGLM模型

from zhipuai import ZhipuAI

#获取用户输入的命令行参数

import sys

#判断用户输入的参数是否为 2  

if len(sys.argv) != 2:

    print("请输入一个问题")

    sys.exit()

#获取用户输入的第一个参数

Problem = sys.argv[1]

client = ZhipuAI(api_key="1edc2f094de9d45c0f6cac2a39a52bf1.4v6s1XgdCDh74AXB")  #填写自己的API_KEY

response = client.chat.completions.create(

model="glm-4-flash",

    messages=[

        {

            "role": "system",

            "content": "你是一个乐于解答各种问题的助手,你的任务是为用户提供专业、准确、有见地的建议。"

        },

        {

            "role": "user",

            "content": Problem

        }

    ],

    top_p= 0.7,

    temperature= 0.95,

    max_tokens=400, #最大的返回字数

    tools = [{"type":"web_search","web_search":{"search_result":True}}],

)

print(response.choices[0].message)  #一次性输出所有结果

*本项目调用gec6818开发板的汉字库

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值