ESP-AI成神之路——服务端自建复刻-ESP32论坛-极客爱好者-青柠博客

ESP-AI成神之路——服务端自建复刻

服务端搭建说明

搭建之前必须满足两点

nodejs版本:v18.20.4

npm   版本:9.3.1

如果你的npm版本不是9.3.1,请用下面命令安装以下

npm install -g npm@9.3.1 --registry=https://registry.npm.taobao.org  --strict-ssl=false

创建配置文件

随便创建一个文件夹,并在这个文件夹里创建index.js,比如我创建了一个espai文件夹

20240918192326216-image

我们用vscode打开目录,为了方便,我去掉了官方多余注释,并且这里以讯飞平台作为演示,这样代码看起来更加简洁

const espAi = require("esp-ai"); 
const config = { 
    /**
     * 可以根据业务需求用这个方法去库中请求配置等...
     * 客户端配置生成,主要是生成 IAT/LLM/TTS 配置。客户端首次连接时会执行或者在某个空闲时刻内部会有自动更新策略 
     * @param {object} params 参数为客户端中配置的参数, 这里会解析为字面量对象,开发者直接使用 key 方式引用即可。 
     */
    gen_client_config: (params)=>{
        return { 
            iat_server: "xun_fei",
            // iat_server: "esp-ai-plugin-iat-example", // 插件
            iat_config: {
                // 讯飞:https://console.xfyun.cn/services/iat  。打开网址后,右上角三个字段复制进来即可。
                appid: "",
                apiSecret: "",
                apiKey: "", 
                // 静默时间,多少时间检测不到说话就算结束,单位 ms
                vad_eos: 1500,

            },

            llm_server: "xun_fei",
            
            llm_config: {
                // 讯飞:https://console.xfyun.cn/services/iat  。打开网址后,右上角三个字段复制进来即可。
                appid: "",
                apiSecret: "",
                apiKey: "",
                llm: "v4.0",
            },

            tts_server: "xun_fei",
            
            tts_config: {
                // 讯飞:https://console.xfyun.cn/services/iat  。打开网址后,右上角三个字段复制进来即可。
                appid: "",
                apiSecret: "",
                apiKey: "",
 

                
            },
            
            /**
             * LLM 初始化提示词
            */
            llm_init_messages: [
                { role: 'system', content: '你是小明同学,是一个无所不能的智能助手。' },
            ],

            
            /**
             * 意图表:当用户唤醒 小明同学 后,小明同学可以做下面的任务
            */
            intention: [
                {
                    // 关键词
                    key: ["帮我开灯", "开灯", "打开灯"],
                    // 向客户端发送的指令
                    instruct: "device_open_001",
                    message: "开啦!还有什么需要帮助的吗?"
                },
                {
                    // 关键词
                    key: ["帮我关灯", "关灯", "关闭灯"],
                    // 向客户端发送的指令
                    instruct: "device_close_001",
                    message: "关啦!还有什么需要帮助的吗?"
                },
                {
                    // 关键词
                    key: ["退下吧", "退下"],
                    // 内置的睡眠指令
                    instruct: "__sleep__",
                    message: "我先退下了,有需要再叫我。"
                }, 
                {
                    /**
                     * 正则匹配
                     * 如:播放音乐最后的倔强  
                     * 返回匹配的字符串为匹配成功
                    */
                    key: async (text = "", llm_historys) => {
                        const regex = /^(播放音乐)(.*)$/;
                        const match = text.match(regex);
                        if (match) {
                            const songName = match[2];
                            console.log("音乐名称:", songName);
                            return songName;
                        } else {
                            return false;
                        }
                    },
                    // 向客户端发送的指令
                    instruct: "__play_music__",
                    message: "好的!",
                    /**
                     * 用于返回音频地址和播放进度
                     * 目前只支持 mp3、wav 格式
                     * @param {String} name 是歌曲名称
                     * @return {number} seek 进度: (以秒为单位)
                     * @return {message} 找不到数据时的TTS
                    */ 
                    music_server: async (name, { user_config }) => { 
                        return {
                            url:"[https](https://xiaomingio.top/music.mp3)",
                            seek: 0,
                            message: message
                        };
                    },
                    /**
                     * 当音频结束后的回调
                     * @param {object} arg.break_second  停止时的进度,单位秒。也就是用户播放了到了多少秒(seek+play_time)
                     * @param {object} arg.play_time     实际播放音频的时间,单位秒。
                     * @param {object} arg.seek          音频开始播放时间,其实也就是 music_server 函数中返回的 seek 值
                     * @param {object} arg.start_time    开始播放音频的 Unix 毫秒数时间戳
                     * @param {object} arg.end_time      结束播放音频的 Unix 毫秒数时间戳
                     * @param {object} arg.event         结束原因: "user_break" 用户打断 | play_end 播放完毕 | foo 未知事件 
                    */
                    on_end: (arg) => {
                        // 请求业务服务器保存进度信息 ...
                        console.log(arg);
                    }
                },
            ],
        }
    }
}
espAi(config);

我们只关注和修改红框里的代码

20240918193514892-image

注册讯飞平台

注册完成之后,打开这个网址

https://console.xfyun.cn/services/iat

我们所需要的都在这里

20240918193658475-image

注意,这里有一个细节,你可能需要免费开通大模型4.0

开通地址:https://console.xfyun.cn/sale/buy?wareId=9126&packageId=9126001&serviceName=Spark4.0%20Ultra&businessId=bm4

20240918193944418-image

修改配置文件

回到代码中,将APPIDAPISecretAPIKey 复制到代码中

20240918194402209-image

安装依赖并启动服务

npm install esp-ai  --registry=https://registry.npm.taobao.org  --strict-ssl=false

回到文件夹中,点击这里输入cmd回车

20240918194551462-image

20240918194639711-image

出现上面界面就表示成功了

启动服务

node ./index.js

到现在为止,服务端搭建完成

20240918195620653-image

如果你想使用docker快速搭建,可以参考这篇文章

ESP-AI成神之路——服务端自建复刻(docker版本)-青柠博客

客户端搭建说明

Arduino IDE:最新版即可

Arduino IDE esp32插件: 2.x

20240919201527292-image

Arduino IDE环境搭建

参考这篇文章

Arduino IDE+Esp32环境搭建-青柠博客

安装库文件

所有需要的文件都在这里

https://www.123pan.com/s/i5h0Vv-Ex7tv

20240918202043806-image

将这些文件全部导入Arduino IDE

依次点击  项目=》导入库=》添加.ZIP库

代码编译

  1. 创建一个文件 example/example.ino ,注意:文件必须放到一个文件夹里,文件夹名字必须和文件一样
  2. 用 Arduino IDE 打开 example.ino 文件
  3. 写入下面代码,然后上传到开发板中,一定是下面代码,修改你的wifi账号和密码,并且将服务配置填写为你的ip和端口
#include <esp-ai.h>

ESP_AI esp_ai;
 

void setup() {
  Serial.begin(115200);
  // [必  填] 是否调试模式, 会输出更多信息
  bool debug = true;
  // [必  填] wifi 配置: { wifi 账号, wifi 密码 }  注意:要用双引号!
  ESP_AI_wifi_config wifi_config = { "Xiaomi_FANFAN", "yangfan0522", "ESP-AI"  };
  // 用开发者平台,只需要配置为空
  //ESP_AI_server_config server_config = { };
  // [必  填] 服务配置: { 服务IP, 服务端口, "请求参数,用多个参数&号分割" }
  ESP_AI_server_config server_config = { "192.168.31.108", 8088, "api-key=your_api_key&p2=test" };
  // [必  填] 离线唤醒方案:{ 方案, 识别阈值 }, "edge_impulse" | "diy",为 "diy" 时可调用 esp_ai.wakeUp() 方法进行唤醒

  ESP_AI_wake_up_config wake_up_config = {};
  strcpy(wake_up_config.wake_up_scheme, "asrpro");  // 唤醒方案
  strcpy(wake_up_config.str, "start");              // 串口和天问asrpro 唤醒时需要配置的字符串,也就是从另一个开发版发送来的字符串
  // strcpy(wake_up_config.threshold,  0.95);  //  内置语音唤醒时需要配置 唤醒阈值 0-1
  //strcpy(wake_up_config.str, "10");  // 引脚高低电平唤醒时需要的引脚IO

  // [可留空] 麦克风引脚配置:{ bck_io_num, ws_io_num, data_in_num }
  ESP_AI_i2s_config_mic i2s_config_mic = { 4, 5, 6 };
  // [可留空] 扬声器引脚配置:{ bck_io_num, ws_io_num, data_in_num, 采样率 }
  ESP_AI_i2s_config_speaker i2s_config_speaker = { 16, 17, 15, 16000 };
  // [可留空] 音量调节配置:{ 输入引脚,输入最大值(1024|4096),默认音量(0-1) }
  ESP_AI_volume_config volume_config = { 34, 4096, 1 };
  // 开始运行 ESP-AI 
  esp_ai.begin({debug, wifi_config, server_config, wake_up_config, volume_config, i2s_config_mic, i2s_config_speaker});
}

void loop() {
  esp_ai.loop(); 
  
}

简单的解释一下,开发板和我选择的一样,服务端填这里的信息

20240918202817230-image

编译上传

20240918203646141-image

这样就表示成功了,同时你会听到“后台连接成功”

20240918204022109-image

 
请登录后发表评论

    没有回复内容