关键词唤醒(KWS)

概述

关键词唤醒(KWS)是众多语音识别系统的核心,使设备能够响应特定词语或短语。这项技术不仅支撑了 Google Assistant、Amazon Alexa 等流行设备,也完全可以在小型、低功耗设备上实现。本实验将带你在 XIAO ESP32S3 微控制器板上,基于 TinyML 实现 KWS 系统。

XIAO ESP32S3 搭载乐鑫 ESP32-S3 芯片,体积小巧但性能强劲,拥有双核 Xtensa LX7 处理器,集成 Wi-Fi 和蓝牙,兼具算力、能效与多样连接能力,是 TinyML 应用的理想平台。配合扩展板,还可使用摄像头、SD 卡和数字麦克风。本项目中,集成麦克风和 SD 卡将发挥关键作用。

我们将使用 Edge Impulse Studio ,这是一个强大且易用的平台,可简化边缘设备机器学习模型的创建与部署。我们将逐步训练 KWS 模型,并优化后部署到 XIAO ESP32S3 Sense 上。

本实验的模型将识别可用于唤醒设备或触发特定动作(如“YES”)的关键词,让你的项目具备语音激活能力。

借助我们在 TensorFlow Lite for Microcontrollers(EI Studio 底层引擎)的经验,将打造一个能在设备端实时推理的 KWS 系统。

实验将详细拆解每个流程环节——从数据采集与准备,到模型训练与部署,帮助你全面理解如何在微控制器上实现 KWS 系统。

学习目标

  • 理解语音助手架构,包括级联检测系统及边缘 KWS 在语音处理流程中的作用
  • 掌握音频数据采集技巧,涵盖离线(XIAO ESP32S3 麦克风+SD 卡)与在线(手机集成 EI Studio)两种方式
  • 实现音频数字信号处理,包括 I2S 协议基础、16kHz/16bit 采样、时域与频域(MFCC)特征转换
  • 训练卷积神经网络进行音频分类,掌握迁移学习、数据增强与四分类(YES、NO、NOISE、UNKNOWN)模型优化
  • 在微控制器上部署优化模型,包括 INT8 量化、PSRAM 内存管理、嵌入式实时推理优化
  • 开发完整后处理管道,如置信度阈值、GPIO 控制、OLED 显示、打造独立 AI 传感器系统
  • 对比无代码平台与传统嵌入式开发流程,理解 TinyML 应用的多种开发路径

KWS 项目简介

语音助手是如何工作的?

关键词唤醒(KWS)是语音助手的关键,使设备能响应特定词语。以 Google Home、Amazon Echo-Dot 为例,只有在检测到特定唤醒词(如“Hey Google”“Alexa”)后,设备才会响应。

图 1: 语音助手唤醒流程示意图
图 1: 语音助手唤醒流程示意图

换句话说,语音命令识别采用多级模型(级联检测):

图 2: 级联检测流程图
图 2: 级联检测流程图

第一阶段:设备内的小型微处理器持续监听环境声音,等待关键词出现。此阶段采用边缘 TinyML 模型(KWS 应用)。

第二阶段:仅当 KWS 检测到关键词后,才将数据上传云端,由更大模型进一步处理。

下方视频演示了用树莓派模拟 Google Assistant(第二阶段),Arduino Nano 33 BLE 作为 TinyML 设备(第一阶段)的案例。

想深入了解完整项目,可参考: Building an Intelligent Voice Assistant From Scratch

本实验聚焦第一阶段(KWS),使用 XIAO ESP32S3 Sense 的数字麦克风实现关键词检测。

推理流程

下图展示了最终 KWS 应用的推理流程:

图 3: KWS 推理流程图
图 3: KWS 推理流程图

本项目将识别四类声音:

  • YES(关键词 1)
  • NO(关键词 2)
  • NOISE(仅背景噪声,无关键词)
  • UNKNOWN(除 YES/NO 外的其他词)

实际项目建议加入“噪声/背景”和“未知”类,提高模型稳健性。

机器学习工作流

KWS 应用的核心是模型。我们需用目标关键词、噪声及其他词(unknown)训练模型:

图 4: KWS 训练流程图
图 4: KWS 训练流程图

数据集

机器学习流程的关键是数据集。确定关键词(如 YES、NO)后,可利用 Pete Warden 提供的 Speech Commands 数据集 ,包含 35 个关键词(每类 1000+ 样本),如 yes、no、stop、go。我们可获得 yesno 各 1500 条样本。

可从 Edge Studio 下载精简版数据集( 关键词预置数据集 ),涵盖本项目四类样本:yes、no、noise、background。步骤如下:

尽管 Pete 的数据集样本丰富,建议补充自录音频。与加速度传感器实验类似,音频分类更依赖于采集设备本身。

声音与音频的本质区别在于能量形态。声音是介质中的机械波能(纵波),音频是电信号(模拟或数字),用于电气表示声音。

说出关键词时,声波需转换为音频数据。转换过程需用麦克风以 16kHz 采样率、16bit 深度采样。

只要设备能生成 16kHz/16bit 音频数据(如 XIAO ESP32S3 Sense、电脑或手机)均可用作采集工具。

图 5: 声音与音频关系图
图 5: 声音与音频关系图

用 Edge Impulse + 手机在线采集音频

在运动分类与异常检测实验中,我们用设备直连 Edge Impulse Studio 采集数据(50~100Hz)。但音频(16kHz)速率过高,EI CLI 的 Data Forwarder 不适用。采集到的数字音频需转为 WAV 文件,通过 Data Uploader 上传 Studio(与 Pete 数据集操作一致)。

若需直接在 Studio 采集音频,可用手机在线连接,详见 EI 官方文档

用 XIAO ESP32S3 Sense 离线采集音频

板载麦克风为 MSM261D3526H1CPM ,PDM 数字输出 MEMS 麦克风,通过 I2S 总线连接 ESP32S3,IO41(数据)、IO42(时钟)。

图 6: 麦克风与 I2S 连接示意
图 6: 麦克风与 I2S 连接示意

I2S 简介

I2S(Inter-IC Sound)是数字音频传输标准,由飞利浦半导体(现 NXP)开发,广泛用于数字信号处理器、音频处理器及带音频功能的微控制器。

I2S 至少包含三根线:

图 7: I2S 协议示意图
图 7: I2S 协议示意图
  • 1. 时钟线(BCLK/CLK):指示新数据位开始(IO42)
  • 2. 字选择线(WS):指示新字开始(左/右声道),WS 频率决定采样率。本项目麦克风 L/R 接地,仅用左声道(单声道)。
  • 3. 数据线(SD):传输音频数据(IO41)

I2S 数据流以帧为单位,每帧含左/右声道数据,适合立体声,也可用于单声道或多声道。

下面演示如何用麦克风采集原始数据。可参考 GitHub 项目 下载 XIAOEsp2s3_Mic_Test 示例:

⚠️ 注意

  • Xiao ESP32S3 必须启用 PSRAM。可在 Arduino IDE 菜单栏 Tools–> PSRAM:OPI PSRAM 检查
  • Arduino Library(esp32 by Espressif Systems)应为 2.017 版本,请勿升级
/*
  XIAO ESP32S3 简单麦克风测试
*/

#include <I2S.h>

void setup() {
  Serial.begin(115200);
  while (!Serial) {
  }

  // 16kHz,16bit 采样
  I2S.setAllPins(-1, 42, 41, -1, -1);
  if (!I2S.begin(PDM_MONO_MODE, 16000, 16)) {
    Serial.println("Failed to initialize I2S!");
    while (1); // do nothing
  }
}

void loop() {
  // 读取采样
  int sample = I2S.read();

  if (sample && sample != -1 && sample != 1) {
    Serial.println(sample);
  }
}

该代码通过 I2S 接口采集 16kHz/16bit 音频,并持续输出采样值到串口监视器。

主要流程:

  • 引入 I2S 库,配置 I2S 时钟(42)与数据(41)引脚
  • 初始化 I2S,PDM 单声道,16kHz/16bit
  • 循环读取音频采样,输出到串口

串口绘图器可实时观察音量变化:

图 8: 麦克风采样曲线
图 8: 麦克风采样曲线

保存录音样本

使用板载 SD 卡保存 .wav 音频,需先启用 PSRAM。

ESP32-S3 芯片内存有限,XIAO 板载 8MB PSRAM,可通过 SPI 与主控通信,需在 Arduino IDE Tools->PSRAM:"OPI PSRAM"->OPI PSRAM 启用。

插入 FAT32 格式 SD 卡:

图 9: SD 卡插入示意
图 9: SD 卡插入示意

IDE 菜单启用 PSRAM:

图 10: PSRAM 设置
图 10: PSRAM 设置

该代码通过 I2S 录音,保存为 .wav 文件到 SD 卡,并可通过串口命令控制录音。文件名可自定义(建议用作训练标签),每次录音自动编号。支持音量增益。

主要流程:

#include <I2S.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
  • I2S.h:音频输入
  • FS.h:文件系统
  • SD.h:SD 卡操作
  • SPI.h:SPI 通信
#define RECORD_TIME   10
#define SAMPLE_RATE 16000U
#define SAMPLE_BITS 16
#define WAV_HEADER_SIZE 44
#define VOLUME_GAIN 2
  • RECORD_TIME:录音时长(秒)
  • SAMPLE_RATE/SAMPLE_BITS:音频质量
  • WAV_HEADER_SIZE:wav 头大小
  • VOLUME_GAIN:音量增益
int fileNumber = 1;
String baseFileName;
bool isRecording = false;
  • 文件编号、基础文件名、录音状态
void setup() {
  Serial.begin(115200);
  while (!Serial);

  I2S.setAllPins(-1, 42, 41, -1, -1);
  if (!I2S.begin(PDM_MONO_MODE, SAMPLE_RATE, SAMPLE_BITS)) {
    Serial.println("Failed to initialize I2S!");
    while (1);
  }

  if(!SD.begin(21)){
    Serial.println("Failed to mount SD Card!");
    while (1);
  }
  Serial.printf("Enter with the label name\n");
}
  • 初始化串口、I2S、SD 卡,失败则报错并停止
void loop() {
  if (Serial.available() > 0) {
    String command = Serial.readStringUntil('\n');
    command.trim();
    if (command == "rec") {
      isRecording = true;
    } else {
      baseFileName = command;
      fileNumber = 1;
      Serial.printf("Send rec for starting recording label \n");
    }
  }
  if (isRecording && baseFileName != "") {
    String fileName = "/" + baseFileName + "."
                      + String(fileNumber) + ".wav";
    fileNumber++;
    record_wav(fileName);
    delay(1000);
    isRecording = false;
  }
}
  • 串口输入标签名,输入 rec 开始录音,文件名自动编号
void record_wav(String fileName)
{
  ...

  File file = SD.open(fileName.c_str(), FILE_WRITE);
  ...
  rec_buffer = (uint8_t *)ps_malloc(record_size);
  ...

  esp_i2s::i2s_read(esp_i2s::I2S_NUM_0,
                    rec_buffer,
                    record_size,
                    &sample_size,
                    portMAX_DELAY);
  ...
}
  • 打开文件,分配 PSRAM 缓冲区,I2S 采集音频,写入 wav 文件
// 增加音量
for (uint32_t i = 0; i < sample_size; i += SAMPLE_BITS/8) {
  (*(uint16_t *)(rec_buffer+i)) <<= VOLUME_GAIN;
}
  • 音量增益处理
// 写入 wav 文件
Serial.printf("Writing to the file ...\n");
if (file.write(rec_buffer, record_size) != record_size)
  Serial.printf("Write file Failed!\n");

free(rec_buffer);
file.close();
Serial.printf("Recording complete: \n");
Serial.printf("Send rec for a new sample or enter
                a new label\n\n");
  • 写入数据,释放内存,关闭文件,提示下次操作
void generate_wav_header(uint8_t *wav_header,
             uint32_t wav_size,
             uint32_t sample_rate)
{
  ...
  memcpy(wav_header, set_wav_header, sizeof(set_wav_header));
}
  • 生成 wav 文件头

上传代码后,串口输入标签(如 yes),再输入 rec 开始录音,每次 rec 自动编号保存。更换标签后继续录音。

串口交互示例:

图 11: 串口录音标签输入
图 11: 串口录音标签输入

输入标签(如 yes),等待 rec 命令:

图 12: 等待 rec 命令
图 12: 等待 rec 命令

每次 rec 录音,文件自动编号保存:

图 13: 录音文件编号
图 13: 录音文件编号

最终 SD 卡保存的文件如下:

图 14: SD 卡录音文件
图 14: SD 卡录音文件

这些文件可直接上传至 Edge Impulse Studio。

离线音频采集 App

采集音频方式多样,最简单的是用手机或 PC 作为 Edge Impulse Studio 的“连接设备”。

采集音频需 16kHz 采样率、16bit 深度。

也可用专用 App,如 Voice Recorder Pro (iOS),录音保存为 .wav 文件后传至电脑。

图 15: Voice Recorder Pro 录音界面
图 15: Voice Recorder Pro 录音界面

使用 Edge Impulse Studio 训练模型

数据上传

当原始数据集(Pete 的数据集 + 自录关键词)准备好后,应在 Edge Impulse Studio 新建项目:

图 16: 新建项目界面
图 16: 新建项目界面

项目创建后,在数据采集(Data Acquisition)部分选择“Upload Existing Data”工具,选择要上传的文件:

图 17: 选择上传文件
图 17: 选择上传文件

将数据上传到 Studio(可自动划分训练/测试集)。对所有类别和原始数据重复此操作。

图 18: 上传进度界面
图 18: 上传进度界面

上传后,样本会出现在数据采集区:

图 19: 数据采集区样本展示
图 19: 数据采集区样本展示

Pete 数据集的样本长度均为 1 秒,但前面录制的样本为 10 秒,需拆分为 1 秒片段以兼容。

点击样本名后的三点菜单,选择“Split sample”:

图 20: 拆分样本操作
图 20: 拆分样本操作

进入工具后,将数据拆分为 1 秒片段。如有需要可增删片段:

图 21: 拆分片段界面
图 21: 拆分片段界面

所有样本均需重复此操作。

注意:若音频文件较长(数分钟),可先拆分为 10 秒片段,再用工具拆分为 1 秒片段。

如果上传时未自动划分训练/测试集,可手动操作(三点菜单单独移动样本),或在 Dashboard 的 Danger Zone 区域使用“Perform Train / Test Split”。

可通过 Data Explorer 标签页检查所有数据集。

创建 Impulse(预处理/模型定义)

Impulse 是指将原始数据通过信号处理提取特征,再用学习模块对新数据进行分类的流程。

图 22: Impulse 流程图
图 22: Impulse 流程图

首先,使用 1 秒窗口采集数据,进行数据增强,窗口每 500ms 滑动一次。注意启用 zero-pad data 选项,确保不足 1 秒的样本用零填充(有时为避免噪声和尖峰,会在拆分工具中缩短窗口)。

每个 1 秒音频样本需预处理并转为图像(如 $13\times 49\times 1$)。我们采用 MFCC(Mel 频率倒谱系数)特征提取,非常适合人声。

图 23: MFCC 特征提取界面
图 23: MFCC 特征提取界面

接下来选择 KERAS 作为分类器,构建卷积神经网络(CNN)进行图像分类。

预处理(MFCC)

下一步是生成用于训练的特征图像:

可保持默认参数,或使用 DSP Autotune 自动调参(本例采用自动调参)。

图 24: 自动调参界面
图 24: 自动调参界面

结果显示预处理仅需 16KB 内存,但估算处理时间较高(675ms,基于 Espressif ESP-EYE,240kHz 时钟,CPU 性能略低于 ESP32S3 的 LX7)。实际推理时间会更短。

如需进一步降低推理延迟,可返回预处理阶段,调整 FFT 长度(如降至 256)、系数数量等参数。

本例保持自动调参结果,保存参数并生成特征。

图 25: 特征生成界面
图 25: 特征生成界面

想深入了解时序数据转图像(如 FFT、频谱图等),可参考此 CoLab: Audio Raw Data Analysis.

模型设计与训练

本项目采用卷积神经网络(CNN)模型。基础结构为两组 Conv1D + MaxPooling(分别含 8 和 16 个神经元),加 0.25 Dropout,最后一层 Flatten 后输出 4 个神经元(对应四类):

图 26: CNN 结构图
图 26: CNN 结构图

超参数设置:学习率 0.005,训练 100 轮(epochs),并加入数据增强和噪声。训练结果良好:

图 27: 训练结果界面
图 27: 训练结果界面

如需深入理解,可下载数据集,在 Jupyter Notebook 中分析每轮准确率:

图 28: 训练过程准确率曲线
图 28: 训练过程准确率曲线

相关 CoLab Notebook 见: KWS Classifier Project - Looking “Under the hood” Training/xiao_esp32s3_keyword_spotting_project_nn_classifier.ipynb)。

测试

用预留的测试集测试模型,准确率约 87%:

图 29: 测试准确率界面
图 29: 测试准确率界面

F1 分数显示 YES 类为 0.95,非常理想(本项目用 YES 触发后处理,如点亮 LED);NO 类为 0.90,UNKNOWN 类略低但可接受。

可继续项目,也可在设备部署前用手机进行 Live Classification。进入 Live Classification,点击 Connect a Development board:

图 30: 连接开发板界面
图 30: 连接开发板界面

用手机扫码并访问链接:

图 31: 手机扫码界面
图 31: 手机扫码界面

手机连接 Studio 后,选择 Classification,实时测试关键词,验证模型效果:

图 32: 手机实时推理界面
图 32: 手机实时推理界面

部署与推理

Studio 会自动打包所需库、预处理函数和模型,下载到本地。选择 Arduino Library,底部菜单选 Quantized (Int8),点击 Build。

图 33: 下载 Arduino 库界面
图 33: 下载 Arduino 库界面

接下来进行真实推理测试。我们将修改 ESP32 示例代码(esp32_microphone),适配本设备。

在 Arduino IDE 的 File/Examples 中找到项目,选择 esp32/esp32_microphone:

图 34: 选择示例代码界面
图 34: 选择示例代码界面

该代码为 ESP-EYE 麦克风设计,需适配 XIAO ESP32S3。

首先更换 I2S 总线相关库:

图 35: 原始库引用
图 35: 原始库引用

替换为:

#include <I2S.h>
#define SAMPLE_RATE 16000U
#define SAMPLE_BITS 16

在 setup() 中初始化 I2S 麦克风:

void setup()
{
...
    I2S.setAllPins(-1, 42, 41, -1, -1);
    if (!I2S.begin(PDM_MONO_MODE, SAMPLE_RATE, SAMPLE_BITS)) {
      Serial.println("Failed to initialize I2S!");
    while (1) ;
...
}

在 static void capture_samples(void* arg) 函数中,将第 153 行读取 I2S 麦克风数据的代码:

图 36: 原始采样代码
图 36: 原始采样代码

替换为:

/* read data at once from i2s */
esp_i2s::i2s_read(esp_i2s::I2S_NUM_0,
                 (void*)sampleBuffer,
                 i2s_bytes_to_read,
                 &bytes_read, 100);

在 static bool microphone_inference_start(uint32_t n_samples) 函数中,注释或删除 198~200 行的麦克风初始化代码(setup() 已初始化,无需重复)。

图 37: 原始初始化代码
图 37: 原始初始化代码

最后,在 static void microphone_inference_end(void) 函数中,将第 243 行:

图 38: 原始释放内存代码
图 38: 原始释放内存代码

替换为:

static void microphone_inference_end(void)
{
    free(sampleBuffer);
    ei_free(inference.buffer);
}

完整代码见 项目 GitHub 。上传代码到开发板,测试实际推理效果:

⚠️ 注意

  • Xiao ESP32S3 必须启用 PSRAM。可在 Arduino IDE 菜单栏 Tools–> PSRAM:OPI PSRAM 检查
  • Arduino Library(esp32 by Espressif Systems)应为 2.017 版本,请勿升级
图 39: 推理测试界面
图 39: 推理测试界面

后处理

在边缘 AI 应用中,推理结果只有被有效利用才有价值。串口输出便于调试,但实际部署需即时、直观的人机反馈,无需外接显示器。

下面介绍两种后处理方式:用 XIAO 内置 LED 和 XIAOML Kit 的 OLED 显示屏。

LED 指示

模型能正确检测关键词后,可修改代码使每次检测到 YES 时点亮内置 LED。

初始化 LED:

#define LED_BUILT_IN 21
...
void setup()
{
...
  pinMode(LED_BUILT_IN, OUTPUT); // 设置为输出
  digitalWrite(LED_BUILT_IN, HIGH); // 关闭
...
}

在 loop() 的 // print the predictions 部分修改为:

int pred_index = 0;     // 初始化 pred_index
float pred_value = 0;   // 初始化 pred_value

// 输出预测结果
ei_printf("Predictions ");
ei_printf("(DSP: %d ms., Classification: %d ms., Anomaly: %d ms.)",
     result.timing.dsp, result.timing.classification,
     result.timing.anomaly);
ei_printf(": \n");
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
      ei_printf("    %s: ", result.classification[ix].label);
      ei_printf_float(result.classification[ix].value);
      ei_printf("\n");

      if (result.classification[ix].value > pred_value){
         pred_index = ix;
         pred_value = result.classification[ix].value;
      }
}

// 根据推理结果控制 LED
if (pred_index == 3){
    digitalWrite(LED_BUILT_IN, LOW); // 点亮
}
else{
   digitalWrite(LED_BUILT_IN, HIGH); // 熄灭
}

完整代码见 项目 GitHub 。上传后测试实际推理:

图 40: LED 指示效果
图 40: LED 指示效果

每次检测到 YES,LED 点亮。类似地,也可用作外部设备的触发信号。

OLED 显示

XIAOML Kit 配备的 0.42 英寸 OLED 显示屏(72×40 像素)是关键的后处理组件,可将 ML 推理结果直接以类别名和置信度显示在设备上,实现真正的独立边缘 AI 部署,适用于工业、农业、零售等场景,便于现场快速确认 AI 预测。

可修改代码自动适配 Edge Impulse 训练的模型,直接读取类别名和数量。代码见 GitHub: xiaoml-kit_kws_oled

运行效果如下:

图 41: OLED 显示推理结果
图 41: OLED 显示推理结果

总结

本实验完整演示了基于 XIAOML Kit 的关键词唤醒系统开发流程,展示了现代 TinyML 平台如何让复杂音频 AI 在资源受限设备上变得易用可落地。通过动手实践,我们将理论机器学习知识与嵌入式 AI 部署紧密结合。

技术亮点:

项目实现了从原始声音采集到实时推理的完整音频处理管道。利用 XIAO ESP32S3 集成数字麦克风,以专业级(16kHz/16bit)采集音频,并用 MFCC 特征提取。部署的 CNN 模型能高效区分目标关键词(“YES”、“NO”)与背景(“NOISE”、“UNKNOWN”),推理延迟适合实时应用。

平台集成:

Edge Impulse Studio 作为嵌入式 MLOps 平台,涵盖数据采集、标注、训练、优化与部署。云端训练与边缘部署无缝衔接,Arduino IDE 则为自定义后处理提供灵活性。

实际应用:

所学技术远不止关键词检测。语音控制、工业安全监测、医疗呼吸分析、环境声音监测等均可借鉴本项目音频处理方法。级联检测架构(边缘 KWS 触发云端处理)是现代语音助手的基础。

嵌入式 AI 原则:

本项目强调了 TinyML 的关键考量:功耗管理、PSRAM 内存优化、模型复杂度与推理速度权衡。神经网络在微控制器上实时音频分析,证明 AI 能力已从桌面走向电池供电设备。

开发方法论:

涵盖多种开发路径:离线 SD 卡采集与在线流式采集、Edge Impulse 自动库生成与 Arduino 自定义实现。灵活适配不同项目需求。

未来方向:

本实验为更高级音频 AI 应用打下基础。多关键词识别、说话人识别、情感检测、环境声音分类等均可基于本技术拓展。OLED 显示与 GPIO 控制集成,展示了 KWS 作为智能 IoT 接口的潜力。

声音分类远不止语音识别,相关技术可广泛应用于:

  • 安防:破窗、入侵、枪声检测
  • 工业 IoT:设备健康监测、异常检测
  • 医疗:睡眠监测、呼吸分析、老人护理
  • 环境监测:野生动物追踪、城市噪声分析、智能建筑声学管理
  • 智能家居:多房间语音控制、家电声音状态监测

核心收获:

XIAOML Kit 证明了专业级 AI 开发可用平价工具实现。强大硬件(ESP32S3+PSRAM+ 多传感器)、成熟平台(Edge Impulse Studio)、丰富软件库,让复杂 AI 概念变为可用系统。

本实验展示了 AI 的未来不仅在数据中心,更在能实时感知、理解和响应环境的智能边缘设备——为普惠、隐私友好、响应迅速的人工智能系统打开了新可能。

参考资源

文章导航

章节内容

这是章节的内容页面。

章节概览

评论区