【有奖征文】基于哪吒平台下大语言赋能边缘设备
1、项目背景
目前我们通过借助OpenVINO 平台可以在Intel平台上快速实现各种AI 能力,如目标检测、文生图、语音识别、语音生成、LLM等多种AI能力。但对于移动端或者边缘计算设备(树莓派、低成本MCU)支持不是特别的好,虽然在Android、树莓派等边缘计算设备或者移动设备上已经具备了TF Lite或者其他的小型AI推理框架,但对于推理设备还是有一定的要求,且部署需要一定的学习能力。所以项目构思成一个通过服务能力达到开箱即用、使用简单特性,加上边缘设备的网络能力结合,通过Intel平台上赋能边缘设备。
目前我们可以参考之前国外比较火的设备rabbit R1(https://www.rabbit.tech/),可以在很小的便携设备上进行大模型交互,这种感觉不要太棒了。我们来简单分析一下,如果设备通过本地进行推理,那么需要比较强大的计算平台,同时功耗和温升也不会带来较差的体验,所以设备可能是通过与云端进行交互,然后本地处理结果。这种方式复合项目构思,我们通过服务端部署本地大语言模型,然后提供API供边缘设备调用。
2、项目选型
2.1、推理平台
目前OpenVINO xxxx对于大语言模型支持相对比较好,原则上核显推理一些比较基本的模型均能够带动,但还是建议采用Intel Core i5 8代 + 内存8G 以上的硬件架构,虽然远古硬件能带动和体验不可兼得。本项目采用哪吒平台。哪吒(Nezha)开发套件以信用卡大小(85 x 56mm)的开发板-哪吒(Nezha)为核心,采用英特尔®处理器 N97(Alder Lake-N),结合了高性能和低功耗的特性。它支持四核 SoC,时钟频率高达 3.60GHz,TDP 仅为 12W。 其内置 GPU 用于 高分辨率显示。哪吒保持了 85mm x 56mm 信用卡大小的外形尺寸,与树莓派相同,包括高达 8GB 的 LPDDR5 系统内存、高达 64GB 的 eMMC 存储、板载 TPM 2.0、40 针 GPIO 连接器,并支持 Windows 和 Linux 操作系统。这些功能与无风扇冷却器相结合,为各种应用构建了高效的解决方案,适用于教育、物联网**、数字标牌和机器人等应用。
内置 Intel® UHD Graphics Gen12,最多 24 个执行单元,这也是一个强大的 AI 引擎,可用于 AI 推理。它是基于 Xe 架构的新一代 GPU。支持包括 INT8 在内的主要数据类型。通过HDMI 1.4b端口,它支持30Hz的4K UHD(3840×2160)以实现高分辨率显示。
40引脚HAT GPIO可配置为PWM、UART、I2C、I2S、SPI和ADC。它为开发人员提供了构建解决方案的自由。
(https://www.intel.cn/content/www/cn/zh/developer/topic-technology/edge-5g/hardware/nezha-dev-kit.html)
2.2、边缘计算平台
边缘计算平台我们可以用多种选型,我们想随时随地使用可以通过Android或者iPhone做平台。想在家里使用或者车机上做一个私人助理,可以通过树莓派、香橙派这种微型的设备做上层系统。当然如果想节约成本可以使用STM32、ESP32等嵌入式MCU做上位机,然后通过触控屏做屏幕即可,成本约150.本项目采用ESP32(https://www.espressif.com.cn/zh-hans).
ESP32-S3 是一款集成 2.4 GHz Wi-Fi 和 Bluetooth 5 (LE) 的 MCU 芯片,支持远距离模式 (Long Range)。ESP32-S3 搭载 Xtensa® 32 位 LX7 双核处理器,主频高达 240 MHz,内置 512 KB SRAM (TCM),具有 45 个可编程 GPIO 管脚和丰富的通信接口。ESP32-S3 支持更大容量的高速 Octal SPI flash 和片外 RAM,支持用户配置数据缓存与指令缓存。
2.3、前端界面框架
由于前面采用ESP32-S3做MCU,这里使用LVGL(https://lvgl.io/)做界面框架,当然这一套也适合树莓派这些设备。如果采用iOS或者Android设备,采用标准的开发流程或者跨平台开发技术即可。
LVGL 是最流行的免费开源嵌入式图形库,可用于为任何 MCU、MPU 和显示器类型创建漂亮的 UI。从消费电子产品到工业自动化,任何应用程序都可以利用 LVGL 的 30 多个内置小部件、100 多个样式属性、受 Web 启发的布局和支持多种语言的排版系统。
3、细节实现
服务端搭建我们可以采用官方的LLMChatbot例子进行改造,我们只需要提前下载好pycharm或者VSCode等这些Python开发IDE,然后设置好虚拟Python环境即可。
官方可用例子列表: https://github.com/openvinotoolkit/openvino_notebooks/tree/latest/notebooks/llm-chatbot
https://github.com/openvinotoolkit/openvino_notebook***lob/latest/notebooks/llm-question-answering
本文为了通用性采用了https://github.com/openvinotoolkit/openvino_notebook***lob/latest/notebooks/llm-chatbot/llm-chatbot.ipynb。同时采用了一个脚小的语言模型做文章参考,如果本身电脑比较强大,可以替换模型即可。
3.1、依赖安装
%pip install -Uq pip
%pip uninstall -q -y optimum optimum-intel
%pip install --pre -Uq "openvino>=2024.2.0" openvino-tokenizers[transformers] --extra-index-url https://storage.openvinotoolkit.org/simple/wheels/nightly
%pip install -q --extra-index-url https://download.pytorch.org/whl/cpu\
"git+https://github.com/eaidova/optimum-intel.git@transformers_4.43"\
"git+https://github.com/openvinotoolkit/nncf.git"\
"torch>=2.1"\
"datasets" \
"accelerate"\
"gradio>=4.19"\
"onnx" "einops" "transformers_stream_generator" "tiktoken" "transformers>=4.40" "bitsandbytes"
%pip install -q "transformers>=4.43" --extra-index-url https://download.pytorch.org/whl/cpu
通常第一步为下载依赖环境,下面是例子钟的依赖列表,建议执行该步骤时,电脑预留5G空间(如果不缓存的话可以少一点),安装后大约占用存储2G左右。
3.2、下载模型
建议下载一个比较小的模型:TinyLlama/TinyLlama-1.1B-Chat-v1.0.该模型同样最好预留5G的空间,实际模型转换为OpenVINO.XML大小大约600MB,电脑大约8G 左右,然后CPU 或者 GPU推理都可以带动。需要改动的地方为:
model_id = widgets.Dropdown(
option***odel_ids,
value=model_ids[1],
description="Model:",
disabled=False,
)
所有模型配置可以看:https://github.com/openvinotoolkit/openvino_notebook***lob/latest/utils/llm_config.py SUPPORTED_LLM_MODELS 就是所有支持的模型,建议是下载TinyLlama/TinyLlama-1.1B-Chat-v1.0,当然如果你具备好的CPU+GPU,可以下载比较好的模型进行测试。
3.3、编写websocket服务端
当前面的步骤完成之后,理论上我们的LLM模型已经可以通过OpenVINO™进行推理了,所以接下来需要创建一个Websocket的服务器。
import websockets
async def handler(websocket, path):
# 当有新客户端连接时,将其加入连接**
chats.add(websocket)
print("new socjer")
try:
async for message in websocket:
# 收到消息后,向所有客户端广播消息]
psss
except Exception as e:
# 捕获异常并打印异常信息
print("websocket an exception:", e)
finally:
# 当客户端断开连接时,将其从连接**中移除
chats.remove(websocket)
start_server = websockets.serve(handler,"当前主机IP", 18765)
server = await start_server
3.4、MCU客户端编写
import websockets
async def handler(websocket, path):
# 当有新客户端连接时,将其加入连接**
chats.add(websocket)
print("new socjer")
try:
async for message in websocket:
# 收到消息后,向所有客户端广播消息]
psss
except Exception as e:
# 捕获异常并打印异常信息
print("websocket an exception:", e)
finally:
# 当客户端断开连接时,将其从连接**中移除
chats.remove(websocket)
start_server = websockets.serve(handler,"当前主机IP", 18765)
server = await start_server
所有步骤完成之后,我们在MCU上编写连接WiFi的代码,然后通过MCU连到该websocket,以下是参考代码。
#include "esp_websocket_client.h"
esp_websocket_client_config_t websocket_cfg = {};
websocket_cfg.uri = "ws://电脑ip:18765";
esp_websocket_client_handle_t websocket_client = esp_websocket_client_init(&websocket_cfg);
esp_websocket_register_events(websocket_client, WEBSOCKET_EVENT_ANY, websocket_event_handler, (void *)websocket_client);
esp_websocket_client_start(websocket_client);
static void websocket_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
switch (event_id) {
case WEBSOCKET_EVENT_CONNECTED:
ESP_LOGI(TAG, "WEBSOCKET_EVENT_CONNECTED");
break;
case WEBSOCKET_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "WEBSOCKET_EVENT_DISCONNECTED");
break;
case WEBSOCKET_EVENT_DATA:
ESP_LOGI(TAG, "WEBSOCKET_EVENT_DATA");
break;
case WEBSOCKET_EVENT_ERROR:
ESP_LOGI(TAG, "WEBSOCKET_EVENT_ERROR");
break;
}
}
然后给lvgl的button绑定点击事件,当点击之后,我们就通过websocket发送给llmchatbot即可。
4、总结
到这里我们给边缘设备赋能的事情基本结束了,但是不太够,我想在任何地方地点怎么做。通常有两种做法,第一种花钱方案,就是架设专门的服务器做数据转发,第二种使用免费的服务做数据转发。但不论那种方式都需要遵守国内法规。
结合文章,大家可以在本地部署自己大语言模型,当然如果自己的硬件足够强大,那么则可以部署更加好的模型,或者加入本地知识库,变成自己的私人助理。