有 8 GB RAM 的 Raspberry Pi 允许我们运行7B LLaMA-2 GPT[1]模型,其在 4 位量化模式下的内存占用约为 5 GB。
有2 或 4 GB RAM的设备允许我们运行像TinyLlama-1B[2]这样的较小模型。这个模型也更快,但正如我们稍后将看到的,它的答案可能有点不那么“聪明”。
Raspberry Pi 是一台成熟的 Linux 计算机,我们可以通过 SSH 轻松地在终端中看到输出。但它不够有趣,也不适合像机器人这样的移动终端设备。对于 Raspberry Pi,我将使用单色128x64 I2C OLED 显示屏。该显示器仅需要 4 根线即可连接:
显示器可以在淘宝上以十几元的价格购买;无需焊接,在 Raspberry Pi 设置中启用 I2C 接口即可;关于这一点有足够的教程。为了简单起见,我将在这里省略硬件部分,只关注 Python 代码。
我将从显示器开始,因为在测试过程中最好在屏幕上看到一些东西。Adafruit_CircuitPython_SSD1306库允许我们在 OLED 显示屏上显示任何图像。该库有一个低级接口;它只能从内存缓冲区中绘制像素或单色位图。为了使用可滚动文本,我创建了一个存储文本缓冲区的数组和一个_display_update绘制文本的方法:
PILImage,ImageDraw,ImageFont : board adafruit_ssd1306 i2c=board.I2C() oled=adafruit_ssd1306.SSD1306_I2C(pixels_size[],pixels_size[],i2c) ImportError: oled= char_h= rpi_font_poath= font=ImageFont.truetype(rpi_font_poath,char_h) pixels_size=(,) max_x,max_y=, display_lines=[] (): oled image=Image.new(,pixels_size) draw=ImageDraw.Draw(image) y,line(display_lines): draw.text((,y*char_h),line,font=font,fill=,align=) oled: oled.fill() oled.image(image) oled.show()
这里,一个(22, 5)变量包含我们可以显示的行数和列数。如果发生这种情况,变量oled也可以是 NoneImportError;例如,如果我们在笔记本电脑而不是 Raspberry Pi 上运行此代码。为了模拟文本滚动,我还创建了两个辅助方法:
(): display_lines text_chunks=[text[i:i+max_x]i(,(text),max_x)] texttext_chunks: linetext.split(): display_lines.append(line) display_lines=display_lines[-max_y:] _display_update() (): display_lines last_line=display_lines.pop() new_line=last_line+text add_display_line(new_line)
第一种方法是在显示中添加新行;如果字符串太长,该方法会自动将其分成几行。第二种方法是添加不带“回车符”的文本标记;我将使用它来显示 GPT 模型的答案。调用add_display_line方法:
p(): add_display_line() time.sleep()
如果一切运行正常,树莓派会重复打印当前时间:
对于 ASR,我将使用HuggingFace的Transformers[3]库,调用它,通过几行 Python 代码实现语音识别:
transformerspipeline transformers..ffmpeg_microphone_live asr_model_id= transcriber=(, model=asr_model_id, device=)
这里,我使用了Whisper-tiny-en[4]模型,该模型经过 68 万小时的语音数据训练。这是最小的 Whisper 型号;它的文件大小为 151MB。当模型加载后,我们可以使用该ffmpeg_microphone_live方法从麦克风获取数据:
(chunk_length_s->: transcriber Sample_rate=transcriber.feature_extractor.sampling_rate mic=ffmpeg_microphone_live( Sample_rate=sampling_rate, chunk_length_s=chunk_length_s, stream_chunk_s=chunk_length_s, ) result= itemtranscriber(mic): result=item[] item[][]: Break result.strip()
Raspberry Pi 没有麦克风,但任何 USB 麦克风都可以完成这项工作。该代码也可以在笔记本电脑上测试;在笔记本上,将使用内置麦克风。
现在,让我们添加大语言模型。首先,我们需要安装所需的库:
pip3installllama-cpp-python pip3installhuggingface-hubsentence-transformerslangchain
在使用LLM之前,我们需要下载它。正如之前所讨论的,我们有两种选择。对于 8GB Raspberry Pi,我们可以使用 7B 型号。对于 2GB 设备,1B的tiny LLM是唯一可行的选择;较大的模型无法载入RAM。要下载模型,我们可以使用该huggingface-cli工具:
huggingface-clidownloadTheBloke/Llama--b-Chat-GGUFllama--b-chat.Q4_K_M.gguf---dir.---dir--symlinksFalse OR huggingface-clidownloadTheBloke/TinyLlama-B-Chat-v1.-GGUFtinyllama-b-chat-v1..Q4_K_M.gguf---dir.---dir--symlinksFalse
我使用了 Llama-2–7b-Chat-GGUF和 TinyLlama-1–1B-Chat-v1-0-GGUF模型。较小的模型运行速度更快,但较大的模型可能会提供更好的结果。
下载模型后,我们可以使用它:
langchain.llmsLlamaCpp
langchain.callbacks.managerCallbackManager
langchain.callbacks.streaming_stdoutStreamingStdOutCallbackHandler
langchain.promptsPromptTemplate
langchain.schema.output_parserStrOutputParser
llm:[LlamaCpp]=
callback_manager:=
model_file=
template_tiny=
template_llama=
template=template_tiny
():
llm,callback_manager
callback_manager=CallbackManager([StreamingCustomCallbackHandler()])
llm=LlamaCpp(
model_path=model_file,
temperature=,
n_gpu_layers=,
n_batch=,
callback_manager=callback_manager,
verbose=,
)
():
llm,template
prompt=PromptTemplate(template=template,input_variables=[])
chain=prompt|llm|StrOutputParser()
chain.invoke({:question},config={})使用该模型很简单,但接下来:我们需要在 OLED 屏幕上流式地显示答案。为此,我将使用自定义回调,每当 LLM 生成新令牌时都会执行该回调:
(): ()->: () ()->: () ()->: (,end=) add_display_tokens(token)
最后,组合所有部分。代码很简单:
__name__==: add_display_line() asr_init() add_display_line() llm_init() : add_display_line() add_display_line() question=transcribe_mic(chunk_length_s=) (question)>: add_display_tokens() add_display_line() llm_start(question)
这里,Raspberry Pi 在 5 秒内录制音频,然后语音识别模型将音频转换为文本;最后,将识别出的文本发送给LLM。结束后,重复该过程。这种方法可以改进,例如,通过使用自动音频电平阈值,但对于一个weekend demo来说,它已经足够好了。
在树莓派上运行成功后
,输出如下所示:在这里,我们可以看到 Raspberry Pi 4 上的 1B LLM 推理速度。Raspberry Pi 5 应该快 30-40%。
我没有使用任何基准(例如 BLEU 或 ROUGE)来比较 1B 和 7B 型号的质量。主观上,7B 模型提供了更正确、信息更丰富的答案,但它也需要更多 RAM、更多加载时间(文件大小分别为 4.6 和 0.7GB),并且运行速度慢 3-5 倍。至于功耗,Raspberry Pi 4 在运行模型、连接 OLED 屏幕和 USB 麦克风的情况下平均需要 3-5W。
在本文中,我们在树莓派上运行了语音识别和大语言模型,使得树莓派能够理解我们的语音并做出回复。这样的demo也是边缘端GPT模型的一个有趣的里程碑:GPT正在进入智能设备时代,这些设备将能够理解人类语音、响应文本命令或执行不同的操作。
从视频中我们可以看到,LLM的回复速度还是有点慢。但根据摩尔定律, 5-10 年后,相同的模型将轻松运行在 1 美元的芯片上,就像现在我们可以运行成熟的 PDP-11 模拟器(PDP在80年代的时候价值10 万美元)在 5 美元的 ESP32 板上。
| 欢迎光临 链载Ai (https://www.lianzai.com/) | Powered by Discuz! X3.5 |