在 Raspberry Pi 上运行大型语言模型
介绍了在人工智能快速发展的背景下,边缘计算如何为传统集中式服务器所保留的能力提供分散化的可能。作者提出了将小型化的LLMs集成到树莓派5中的实践方案,将边缘设备转变为能够实时现场数据处理的AI中心。
标签
边缘计算
Raspberry pi
大模型
Ollama
refdesignshare
更新2024-07-26
1763

项目来自:Running Large Language Models on Raspberry Pi at the Edge - Hackster.io

介绍

在快速增长的人工智能领域,边缘计算提供了一个机会,可以分散传统上为强大的集中式服务器保留的功能。本教程探讨了将传统大型语言模型 (LLMs) 的小型版本实际集成到 Raspberry Pi 5 中,将该边缘设备转变为能够进行实时现场数据处理的 AI 中心。

我们的目标是探索 Ollama 的安装和使用,Ollama 是一个开源框架,允许我们在我们的机器(可以是我们的桌面或边缘设备,如 Raspberry Pis 或 NVidia Jetsons)上本地运行 LLMs。Ollama 旨在高效、可扩展且易于使用,使其成为部署 Llama、Phi、LLaVa(多模态)和 TinyLLama 等 AI 模型的不错选择。我们将使用 Python 的生态系统将其中一些模型集成到项目中,探索它们在现实世界场景中的潜力(或至少指向这个方向)。

硬件设置

Raspberry Pi 5 是一个强大的平台,与之前的版本4相比有了巨大的飞跃。配备了 Broadcom BCM2712,这是一款 2.4GHz 四核 64 位 Arm Cortex-A76 CPU,具有加密扩展和增强的缓存功能。它拥有 VideoCore VII GPU、带 HDR 的双 4Kp60 HDMI® 输出和 4Kp60 HEVC 解码器。内存选项包括 4GB 和 8GB(我们选择运行 LLM)的高速LPDDR4X SDRAM。连接性全面,提供双频 802.11ac Wi-Fi®、蓝牙 5.0/BLE、支持 PoE+ 的千兆以太网和各种 USB 端口。它还具有通过 microSD 卡插槽扩展的存储、用于快速外设的 PCIe 2.0 接口以及通过 USB-C 和 Power Delivery 的 5V/5A 直流电源输入。其他功能包括实时时钟、电源按钮和标准 40 引脚 GPIO 接头,使其成为实际应用的多功能选择。

顺便说一句,正如 Alasdair Allan 所讨论的那样,边缘的一些推理任务可能不再需要自定义加速器硬件,因为直接在 Raspberry Pi 5 CPU 上进行推理(没有 GPU 加速)现在与 Coral TPU 的性能相当。

图片来自 Alasdair Allan 在 Hackester 上的文章

有关更多信息,请参阅完整文章:在 Raspberry Pi 5 上对 TensorFlow 和 TensorFlow Lite 进行基准测试。

Raspberry Pi 主动式散热器

对于本项目,我们建议为 Raspberry Pi 5 安装一款主动式散热装置,这是一款专为其设计的夹扣式散热解决方案。它通过结合铝制散热片和温控风扇,能够在高负载情况下,如运行大型语言模型时(LLMs),确保 Raspberry Pi 5 的稳定和舒适运行。

这款主动冷却器具有用于传热的预涂导热垫,并使用弹簧加载的图钉直接安装到 Raspberry Pi 5 板上。Raspberry Pi 的固件会动态控制散热器的工作:在 60°C 时,鼓风机的风扇将打开;在67.5°C时,风扇转速会增加;最后,在 75°C 时,风扇会提升至最高转速。当温度降至这些阈值以下时,风扇会自动降低转速。

为了防止过热,所有树莓派板在温度达到 80°C 时开始限制处理器,当温度达到 85°C 时,进一步限制处理器。 更多细节,请点击这里

安装操作系统

要使用 Raspberry Pi,我们需要一个操作系统。默认情况下,树莓派会检查插槽中插入的任何SD卡上的操作系统,因此我们应该使用树莓派镜像工具(Raspberry Pi Imager)来安装操作系统。

Raspberry Pi Imager 是一款用于在 macOS、Windows 和 Linux 上下载和写入镜像的软件。它包含了许多为树莓派设计的流行操作系统镜像。我们还将使用镜像工具来预配置登录凭证和远程访问设置。

下载并安装镜像工具到你的电脑后,使用一张新的空白SD卡。选择设备 (RASPBERRY PI 5)、操作系统 (RASPBERRY PI OS (64-BIT)) 和存储设备:

要使用 Ollama,我们应该使用 64 位版本

我们还需要在“常规”选项卡中设置主机名、用户名、密码以及局域网配置,并在“服务”选项卡中特别启用 SSH 服务。您可以通过安全外壳协议(SSH),在同一网络内的其他计算机上远程访问 Raspberry Pi 的终端。

将操作系统烧录到SD卡后,将其插入Raspi5的SD卡槽并接通5V电源。

通过 SSH 与 Rasp5 交互

与 Rasp-Zero 交互的最简单方法是通过 SSH(“Headless”)。您可以使用终端 (MAC/Linux) 或 PuTTy (Windows)。

在终端中输入:

ssh mjrovai@rpi-5.local

您应该将“ mjrovai ”替换为您的用户名,并将“ rpi-5 ”替换为在设置过程中选择的主机名。

当你看到提示时:

mjrovai@rpi-5:~ $

这意味着您正在与 Rasp5 进行远程交互。

定期更新系统是一种很好的做法。为此,您应该运行:

sudo apt-get update

Pip 是一种用于在 Raspberry Pi 上安装外部 Python 模块的工具。但是,在最近的操作系统版本中尚未启用它。要启用它,你应该运行以下命令(只需一次):

sudo rm /usr/lib/python3.11/EXTERNALLY-MANAGED

远程运行 Raspberry Pi 桌面版本

一旦我们运行了完整的 Raspberry Pi OS 版本,我们就可以与其桌面版本进行交互。为此,我们应该通过终端启用VNC服务器。

通过命令运行 Raspi5 配置器:

sudo raspi-config

并选择:3 Interface Options

到达那里后,选择:I2 VNC

你会收到一个弹出窗口请求确认。按“<YES>”确认后,接着按“<OK>”。之后你应该返回到主屏幕。使用Tab键,选择“<Finish>”。

现在,您应该在计算机上安装 VNC 查看器。安装后,应确认 Rasp5 IP 地址。例如,在终端上,您可以使用:

hostname -I

运行 VNC 查看器,启动新连接,并指定名称(例如,RPi-5):

您应该会收到一个新的弹出窗口,要求确认 Rasp5 用户名和密码:

就是这样!Raspberry Pi 5 Desktop 应该出现在您的计算机显示器上。

默认情况下,桌面的分辨率不高,但可以通过访问菜单(左上角的树莓图标)并为显示器选择最佳屏幕清晰度:

在 Rasp5 和桌面之间传输文件

在 Rasp5 和我们的主计算机之间传输文件可以使用U盘或者通过网络上的FTP程序来完成。对于后者,我们使用FileZilla FTP客户端。

按照说明安装适用于你的桌面操作系统的程序。

必须知道 Rasp5 IP 地址,和以前一样,在终端上使用:

hostname -I

使用此 IP 作为文件中的主机:

sftp://192.168.4.209

然后输入您的 Rasp5 用户名和密码。按下 将打开两个单独的窗口,一个用于桌面(右),另一个用于 Rasp5(左)。Quickconnect

安装 Ollama

运行以下命令安装Ollama:

curl https://ollama.ai/install.sh | sh

因此,API 将在 127.0.0.1:11434(就我而言)的后台运行。从现在开始,您可以通过终端运行 Ollama。

不幸的是,Ollama 没有使用 Rasp5 GPU 来加快推理速度。我们希望这种情况在未来能够改变,并且可以使用更多像 Raspberry Pi AI KIT 这样的新设备。

可以通过运行以下命令来验证 Ollama 是否正确安装:

ollama list

我们还没有安装任何模型时,你应该看到一个空列表。让我们安装并运行我们的第一个模型 TinyLlama,这是一个在 3 万亿个代币上预训练的 1.1B Llama 模型。

TinyLlama 是一个很小但仍然很强大的语言模型,可用于许多应用程序,例如部署在内存和计算能力有限的边缘设备上,用于无需互联网连接的实时机器翻译等功能(4位量化的TinyLlama-1.1B的重量仅占用637 MB),从而在视频游戏和家庭自动化中使用实时对话。

安装模型

ollama pull tinyllama

现在,再次运行:

ollama list

您应该看到已安装一个大小为636MB的新模型。

运行模型

ollama run tinyllama

现在,使用之前的命令运行模型,你应该能够使用 Ollama 提示符输入问题,并开始与大型语言模型(LLM)进行对话:

例子:

>>> What is the capital of France?

法国的首都是巴黎。这座城市的正式名称是“巴黎”,它的旧名是“光之城”。然而,使用“光之城”作为法语巴黎的官方名称并不常见。相反,它通常以其缩写名称“巴黎”来称呼。

>>> What is the distance between Paris and Santiago, Chile?

巴黎和智利圣地亚哥之间的距离约为 7,042 英里或 11,329 公里。乘汽车或飞机旅行大约需要 18 小时 56 分钟。飞行距离可能因航空公司和其他因素而异。

>>> what is the latitude and longitude of Par

巴黎的经纬度如下:

纬度: 48.853° 至 49.624°

经度: -0.17° to -0.83°

这些坐标可用于查找巴黎与地球表面各个点(例如城市、地标和其他位置)之间的距离。

令人惊奇的是,像Rasp5这样的边缘设备上,如此小的模型可以完全离线工作。考虑到我们仅使用了CPU,响应速度已经非常好了。

我们还可以在调用模型时使用有关模型推理性能的统计数据。--verbose

首先,我们应该停止使用模型:

>>> /bye

然后再次运行:

ollama run tinyllama --verbose

例如,我们再次问法国的首都是什么。这一次,模型给出了一个简短的答案,与之前的回答不同,但同样是正确的。此外,我们还收到了一些关于在 Raspberry Pi 上运行的语言模型 (LLM) 的性能和计时指标的统计数据。

每个指标都提供了有关模型如何处理输入和生成输出的见解。以下是每个指标的含义:

  • 总耗时 (3.761616043s):这是从命令开始到响应完成所花费的完整时间。它包括加载模型、处理输入提示和生成响应的时间。
  • 加载耗时 (1.319068ms):这个非常短的持续时间表示将模型或必要组件加载到内存中的时间。鉴于其简洁性,它表明该模型已预加载或只需要最少的设置。
  • 提示评估次数(41 tokens):输入提示中的token数量。在 NLP 中,tokens通常是单词或子单词,因此这个计数包括了模型评估以理解和响应查询的所有token。
  • 提示评估耗时(3.016907s):用于测量模型评估或处理输入提示的时间。它占总持续时间的大部分,这意味着理解查询和准备响应是该过程中最耗时的部分。
  • 提示评估速率 (13.59 tokens/s):此速率表示模型处理来自输入提示的标记的速度。它反映了模型在自然语言理解方面的速度。
  • 评估次数(8个token):这是模型响应中的标记数,在本例中为“法国首都是巴黎”。
  • 评估耗时 (613.67ms):这是根据评估的输入生成输出所需的时间。它比提示评估要短得多,这表明生成响应比理解提示更简单或计算密集。
  • 评估速率(13.04 个token/秒):与提示评估率类似,这表示模型生成输出令牌的速度。这是了解模型在输出生成方面的效率的关键指标。

这种详细的分解有助于理解在 Raspberry Pi 5 等边缘设备上运行 TinyLlama 等 LLM 的计算需求和性能特征。它表明,虽尽管提示评估更耗时,但实际生成响应的速度相对较快。这种分析对于优化性能和诊断实时应用程序中的潜在瓶颈至关重要。

检查本地资源

使用 ,您可以轻松监控设备上运行的资源。在终端上使用命令输入:htop

htop

重新启动后,我们可以看到系统运行的是424MB的8GB SRAM,而4个协处理器没有做太多工作。让我们再次运行 TinyLlama模型。

ollama run tinyllama --verbose

内存约为 100Mb

我们可以看到所有 4 个 CPU 都以 100% 的容量运行。

监测温度也很重要。你可以在任务栏上显示温度:

当你没有进行任何操作时,CPU以1%的负载运行,温度大约是48°C。在进行推理时,如果CPU满负荷运行(100%),温度会上升到62°C。

这是正常的,意味着主动式散热器正在工作,将温度保持在80°C/85°C以下(即其极限温度)。

拉动更大的模型

让我们尝试使用PHI3模型,这是微软提供的一系列轻量级的3B(迷你版)和14B(中等版)最先进的开放模型。我们将运行3B模型:

ollama run phi3 --verbose

请注意,我们不使用命令,而是直接使用命令 。这样做的原因是 Ollama 会记录已经下载的模型。一旦 PHI3 模型不存在,Ollama在运行之前会自动先下载它。 llama pull modelrun

让我们使用之前使用的相同提示输入:

>>> What is the capital of France?

法国的首都是巴黎。它不仅是该国最大的城市,也是全球艺术、时尚、美食和文化中心。其行政范围内的 19 世纪大都市人口为 2, 175, 601(2018 年为城市水平)。巴黎位于法国中北部,是该国人口最多的城市。截至 2019 年 1 月,该市面积为 105 平方公里(41 平方英里),总人口约为 2,273,961 名居民。

答案有点“冗长”,其“评估率”为 3.51 tokens/s(比 TinyLlama 慢 3 到 4 倍),但我们可以指定一个更好的提示:

>>> What is the capital of France? Give me a short answer with less than 10 tokens.

巴黎。

在本例中,评估率为 4.99 tokens/s,但总时间几乎相同:44 s。

选择最合适的提示是 LLM 使用的最重要的技能之一,无论其大小如何。

我们可以将这样的模型用作重要的助手,因为它的速度不错

多模态模型

多模态模型是人工智能 (AI) 系统,可以处理和理解来自多个来源的信息,例如图像、文本、音频和视频。在我们的上下文中,多模态大型语言模型(LLMs)可以处理包括文本、图像和音频在内的各种输入作为提示,并将这些提示转换成各种输出,而不仅仅是源类型。

我们将在这里使用 LLaVA-Phi-3-mini,这是一个经过微调的来自Phi 3 Mini 4k的LLaVA模型。它具有强大的性能基准,与原始的 LLaVA(大型语言和视觉助手)模型相当。

LLaVA-Phi-3-mini 是一种端到端训练的大型多模态模型,旨在根据视觉输入(图像)和文本指令来理解和生成内容。它结合了视觉编码器和语言模型的功能,以处理和响应多模态输入。

让我们安装模型:

ollama run llava-phi3 --verbose

让我们从文本输入开始:

>>> You are a helpful AI assistant. What is the capital of France?

法国的首都是巴黎。

响应需要 6.4 秒,评估率为 4.5 tokens/s!不错!

但是让我们知道以图像作为输入输入。为此,让我们创建一个用于工作的目录:

cd Documents/
mkdir OLLAMA
cd OLLAMA

让我们从互联网上下载一张图片,例如(维基百科:法国巴黎):

已将名为 VGA 的版本下载到 OLLAMA 目录中。复制完整的图像路径: image_test_1.jpgCopy Path(s)

/home/mjrovai/Documents/OLLAMA/image_test_1.jpg

让我们输入以下提示:

>>> Describe the image

/home/mjrovai/Documents/OLLAMA/image_test_1.jpg

结果非常棒,但总体延迟相当高;进行推理几乎需要4分钟。

让我们试着愚弄模型。下载美国内华达州拉斯维加斯埃菲尔铁塔的图片,并将其命名为:image_test_2.jpg


让我们输入以下提示:

>>> Describe the image

/home/mjrovai/Documents/OLLAMA/image_test_2.jpg

图像的描述是准确的,但不幸的是,我们误导了模型。

可能是因为水加上塔让模型将其描述为巴黎。让我们尝试同一地方(拉斯维加斯)的另一张图片,但使用不同的角度且没有水:

太好了!模型正确理解了图片。

在资源方面,系统在2.7GB的SRAM上运行,四个CPU全速运转,温度为 74°C。

Ollama Python 库

到目前为止,我们已经在终端上使用命令行探索了 LLMs 的聊天功能。然而,我们想要将这些模型集成到我们的项目中,所以Python似乎是正确的选择。好消息是,Ollama正好拥有这样一个库。

Ollama Python 库简化了与高级 LLM 模型的交互,实现了更复杂的响应和功能,此外还提供了将 Python 3.8+ 项目与 Ollama 集成的最简单方法。

为了更好地理解如何使用 Ollama 和 Python 创建应用程序,我强烈推荐 Matt Williams 的视频

安装

pip install ollama

已经默认安装了一些IDE,如Thonny和Geany,你可以通过菜单访问它们。如果你倾向于使用其他IDE,例如Visual Studio Code,你可以从菜单中的“偏好设置”下的“推荐软件”进行下载。当弹出窗口时,进入“编程”部分,选择你想要的选项,并点击[Apply]。[Menu] [Programming][Menu][Preferences][Recomended Software][Programming]

让我们从一个非常简单的脚本开始:

import ollama

MODEL = 'llava-phi3'
PROMPT = 'What is the capital of France?'

res = ollama.generate(model=MODEL, prompt=PROMPT)
print (res)

将其保存为文件,比如命名为“test_ollama.py”。我们可以通过 IDE 来执行这个脚本,或者也可以直接在命令行终端中运行。

python test_ollama.py

因此,我们将获得 JSON 格式的模型响应:

{
'model': 'llava-phi3',
'created_at': '2024-06-13T15:50:13.496874744Z',
'response': ' The capital of France is Paris. It is also the largest city in the country and serves as a major center for culture, politics, and economics. The French government, including both the executive branch led by the President and the legislative branch with the National Assembly and Senate, are located in Paris. The official residence of the president is at the Élysée Palace, while the French Parliament meets in the Palais Bourbon.',
'done': True,
'done_reason': 'stop',
'context': [32010, 1724, 338, 278, 7483, 310, 3444, 29973, 32007, 32001, 450, 7483, 310, 3444, 338, 3681, 29889, 739, 338, 884, 278, 10150, 4272, 297, 278, 4234, 322, 19700, 408, 263, 4655, 4818, 363, 9257, 29892, 22661, 29892, 322, 7766, 1199, 29889, 450, 5176, 5874, 29892, 3704, 1716, 278, 22760, 5443, 5331, 491, 278, 7178, 322, 278, 13332, 1230, 5443, 411, 278, 3086, 13266, 322, 18148, 29892, 526, 5982, 297, 3681, 29889, 450, 6221, 25488, 310, 278, 6673, 338, 472, 278, 3067, 368, 29879, 1318, 24537, 29892, 1550, 278, 5176, 13212, 28103, 297, 278, 3793, 1759, 12340, 6718, 29889, 32007],
'total_duration': 23629377147,
'load_duration': 1122936,
'prompt_eval_duration': 244490000,
'eval_count': 89,
'eval_duration': 23254762000
}

正如我们所看到的,生成了几条信息,例如:

  • 'context ':表示模型使用的输入和上下文的标记 ID。标记是用于语言模型处理的文本的数字表示形式。
  • ' response ':模型响应我们的提示生成的主要输出文本。

性能指标:

  • total_duration:操作所花费的总时间(以纳秒为单位)。在这种情况下,大约 23.63 秒。
  • load_duration:加载模型或组件所需的时间(以纳秒为单位)。大约 1.12 毫秒。
  • prompt_eval_duration:评估提示所需的时间(以纳秒为单位)。大约 0.24 秒。
  • eval_count:生成过程中评估的代币数量。在这里,有 89 tokens。
  • eval_duration:模型生成响应所需的时间(以纳秒为单位)。大约 23.25 秒。

但是,我们想要的是纯文本形式的“响应”内容,以及可能用于分析的推理总耗时,所以让我们修改代码,从JSON中提取这些信息:

import ollama

MODEL = 'llava-phi3'
PROMPT = 'What is the capital of France?'

res = ollama.generate(model=MODEL, prompt=PROMPT)
print(f"\n{res['response']}")
print(f"\n [INFO] Total Duration: {(res['total_duration']/1e9):.2f} seconds")

现在,我们得到了:

法国的首都是巴黎。它不仅是国家最大的城市,也是文化、经济和政治的重要中心。巴黎以其丰富的历史、美丽的建筑和世界知名的地标而闻名,如埃菲尔铁塔、巴黎圣母院和卢浮宫博物馆。该市的人口约为 214 万人,周边大都市区还有 860 万人。巴黎每年吸引数以百万计的游客前来探索其著名的博物馆、艺术画廊、餐厅和充满活力的夜生活场所。

[INFO] 总耗时:35.34秒

使用 Ollama.chat()

获得我们响应的另一种方法是使用ollama.chat():

import ollama

MODEL = 'llava-phi3'
PROMPT_1 = 'What is the capital of France?'

response = ollama.chat(model=MODEL, messages=[
{'role': 'user','content': PROMPT_1,},])
resp_1 = response['message']['content']
print(f"\n{resp_1}")
print(f"\n [INFO] Total Duration: {(res['total_duration']/1e9):.2f} seconds")p

法国的首都是巴黎。它是欧洲的主要城市,以其文化、历史和建筑而闻名。

[信息]总时长:6.27 秒

一个重要的考虑是,使用 ollama.generate() 后,响应会在推理结束后从模型的“记忆”中“清除”(只使用一次),但如果我们想要保持对话,我们必须使用 ollama.chat()。让我们看看它在实际操作中的情况:

import ollama

MODEL = 'llava-phi3'

PROMPT_1 = 'What is the capital of France?'
response = ollama.chat(model=MODEL, messages=[
{'role': 'user','content': PROMPT_1,},])
resp_1 = response['message']['content']
print(f"\n{resp_1}")
print(f"\n [INFO] Total Duration: {(response['total_duration']/1e9):.2f} seconds")

PROMPT_2 = 'and of Italy?'
response = ollama.chat(model=MODEL, messages=[
{'role': 'user','content': PROMPT_1,},
{'role': 'assistant','content': resp_1,},
{'role': 'user','content': PROMPT_2,},])
resp_2 = response['message']['content']
print(f"\n{resp_2}")
print(f"\n [INFO] Total Duration: {(response['total_duration']/1e9):.2f} seconds")

在上面的代码中,我们正在运行两个查询,第二个提示会考虑第一个查询的结果。

以下是模型的响应方式:

获取图像描述

就像我们在命令行中使用 LlaVa-PHI-3 模型来分析图像一样,这里也可以使用 Python 来做同样的事情。让我们使用相同的巴黎图像,但现在使用:ollama.generate()

import ollama

MODEL = 'llava-phi3'
PROMPT = "Describe this picture"

with open('image_test_1.jpg', 'rb') as image_file:
img = image_file.read()

response = ollama.generate(
model=MODEL,
prompt=PROMPT,
images= [img]
)
print(f"\n{response['response']}")
print(f"\n [INFO] Total Duration: {(res['total_duration']/1e9):.2f} seconds")

结果如下:

该模型花了将近 4 分钟的时间才返回详细的图像描述。

函数调用

到目前为止,我们可以看到,将模型的("response")回答赋值给一个变量,我们可以很容易地使用它并将其集成到现实世界项目中。它在理论上是可行的,但一个大问题是模型对同一提示的响应总是不同的。假设我们喜欢的,正如模型在上一个例子中的回答,仅仅是一个给定国家的首都名称,仅此而已。我们可以使用 Ollama function 的调用,它与 OpenAI API 完美兼容。

但究竟什么是“函数调用”?

在现代人工智能中,使用大型语言模型 (LLMs) 进行函数调用允许这些模型执行生成文本以外的操作。通过与外部函数或 API 集成,LLMs能够访问实时数据,自动化任务,并与各种系统交互。

例如,LLM 不仅可以响应有关天气的查询,还可以调用天气 API 来获取当前条件并提供准确、最新的信息。这种能力增强了模型回应的相关性和准确性,并使其成为一个强大的工具,用于推动工作流程和自动化流程,将其转变为现实世界应用中的积极参与者。

让我们创建一个项目

我们想要创建一个应用程序,在这个程序中,用户输入一个国家的名字,程序会输出该国家首都与应用程序位置之间的距离(单位为公里)。为了简化,我将使用我的位置——智利的圣地亚哥作为参照点。

用户输入国家/地区名称后,模型将返回其首都城市的名称(以字符串形式)以及该城市的纬度和经度(浮点数)。使用这些坐标,我们可以使用一个简单的 Python 库 (haversine) 来计算这两个点之间的距离。

该项目的想法是演示语言模型交互 (IA)、使用 Pydantic 进行结构化数据处理以及使用 Haversine 公式(传统计算)进行地理空间计算的组合。

首先,让我们安装一些库。除了 Haversine,主要的是 OpenAI Python 库,它为任何 Python 3.7+ 应用程序提供了方便访问 OpenAI REST API 的途径。另一个是 Pydantic(和 instructor),这是一个由 Python 设计的强大数据验证和设置管理库,旨在增强代码库的健壮性和可靠性。简而言之,Pydantic 将有助于确保我们模型的响应始终保持一致。

pip install haversine
pip install openai
pip install pydantic
pip install instructor

现在,我们应该创建一个 Python 脚本,旨在与我们的模型 (LLM) 进行交互,以确定一个国家首都的坐标,并计算从智利圣地亚哥到该首都的距离。

让我们回顾一下代码:

1. 导入库

import sys
from haversine import haversine
from openai import OpenAI
from pydantic import BaseModel, Field
import instructor
  • sys:提供对系统特定参数和函数的访问。它用于获取命令行参数。
  • haversine:库中的一个函数 ,它使用哈弗正弦公式计算两个地理点之间的距离。haversine
  • OpenAI:用于与 OpenAI API 交互的模块(尽管它与本地设置 Ollama 结合使用)。这里的一切都是离线的。
  • pydantic:使用 Python 类型的注释提供数据验证和设置管理。它用于定义预期响应数据的结构。
  • instructor:一个模块用于修补 OpenAI 客户端以在特定模式下工作(可能与结构化数据处理有关)。

2. 定义输入和模型

country = sys.argv[1]  # Get the country from command-line arguments
MODEL = 'llava-phi3' # The name of the model to be used
mylat = -33.33 # Latitude of Santiago de Chile
mylon = -70.51 # Longitude of Santiago de Chile
  • country:脚本需要国家/地区名称作为命令行参数。
  • MODEL:指定正在使用的模型,即 .llava-phi3
  • mylat 和 mylon:智利圣地亚哥的坐标,用作距离计算的起点。

3. 定义响应数据结构

class CityCoord(BaseModel):
city: str = Field(..., description="Name of the city")
lat: float = Field(..., description="Decimal Latitude of the city")
lon: float = Field(..., description="Decimal Longitude of the city")
  • CityCoord:一个 Pydantic 模型,用于定义 LLM 响应的预期结构。它需要三个字段:(城市名称)、 (纬度)和 (经度)。citylatlon

4. 设置 OpenAI 客户端

client = instructor.patch(
OpenAI(
base_url="http://localhost:11434/v1", # Local API base URL (Ollama)
api_key="ollama", # API key (not used)
),
mode=instructor.Mode.JSON, # Mode for structured JSON output
)
  • OpenAI:这个设置初始化了一个OpenAI客户端,它使用本地基础URL和API密钥(ollama)。客户端连接到一个本地服务器。
  • instructor.patch:通过对OpenAI客户端进行补丁处理,使其以JSON模式工作,从而能够输出与Pydantic模型匹配的结构化数据。

5. 生成响应

resp = client.chat.completions.create(
model=MODEL,
messages=[
{
"role": "user",
"content": f"return the decimal latitude and decimal longitude of the capital of the {country}."
}
],
response_model=CityCoord,
max_retries=10
)
  • client.chat.completions.create:调用 LLM 生成响应。
  • model:指定要使用的模型 ()。llava-phi3
  • messages:包含 LLM 的提示,询问指定国家/地区首都的纬度和经度。
  • response_model:指示响应应符合 模型。CityCoord
  • max_retries:请求失败时的最大重试次数。

6. 计算距离

distance = haversine((mylat, mylon), (resp.lat, resp.lon), unit='km')
print(f"Santiago de Chile is about {int(round(distance, -1)):,} kilometers away from {resp.city}.")
  • haversine:使用各自的坐标计算智利圣地亚哥和LLM返回的首都之间的距离。
  • (mylat, mylon): 智利圣地亚哥的坐标。
  • (resp.lat, resp.lon):首都的坐标由LLM回复提供。
  • unit='km':指定距离应以公里为单位计算。
  • print:输出的距离数值四舍五入到最近的10公里,并使用千位分隔符以提高可读性。

运行代码

我们可以注意到,我们总是收到相同的结构化信息:

智利圣地亚哥距离华盛顿特区约 8,060 公里。

智利圣地亚哥距离波哥大约 4,250 公里。

智利圣地亚哥距离巴黎约 11,630 公里。

而且计算相当不错!

添加图像

现在到了将迄今为止的所有内容整合起来的时刻了!让我们修改这个“应用程序”,使用户不是输入国家名称(作为文本),而是上传一张图片,然后大型语言模型(LLM)将返回图片中的城市及其地理位置。有了这些数据,我们可以像之前一样计算距离。


为了简化,我们将分两步实施这段新代码。首先,大型语言模型(LLM)将分析图像并创建一个描述(文本)。这个文本将被传递给另一个实例,在这个实例中,模型将提取需要继续传递的信息。

代码如下:

import sys
from haversine import haversine
import ollama
from openai import OpenAI
from pydantic import BaseModel, Field
import instructor
import time

start_time = time.perf_counter() # Start timing

img = sys.argv[1]
MODEL = 'llava-phi3'
mylat = -33.33
mylon = -70.51

def image_description(img):
with open(img, 'rb') as file:
response = ollama.chat(
model=MODEL,
messages=[
{
'role': 'user',
'content': 'return the decimal latitude and decimal longitude of the city in the image, its name, and what country it is located',
'images': [file.read()],
},
],
options = {
'temperature': 0,
}
)
#print(response['message']['content'])
return response['message']['content']


class CityCoord(BaseModel):
city: str = Field(..., description="Name of the city in the image")
country: str = Field(..., description="Name of the country where the city in the image is located")
lat: float = Field(..., description="Decimal Latitude of the city in the image")
lon: float = Field(..., description="Decimal Longitude of the city in the image")

# enables `response_model` in create call
client = instructor.patch(
OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama",
),
mode=instructor.Mode.JSON,
)

image_description = image_description(img)
# Send this description to the model
resp = client.chat.completions.create(
model=MODEL,
messages=[
{
"role": "user",
"content": image_description,
}
],
response_model=CityCoord,
max_retries=10,
temperature=0,
)

distance = haversine((mylat, mylon), (resp.lat, resp.lon), unit='km')

print(f"\n The image shows {resp.city}, with lat:{round(resp.lat, 2)} and long: {round(resp.lon, 2)}, located in {resp.country} and about {int(round(distance, -1)):,} kilometers away from Santiago, Chile.\n")

end_time = time.perf_counter() # End timing
elapsed_time = end_time - start_time # Calculate elapsed time
print(f" [INFO] ==> The code (running {MODEL}), took {elapsed_time} seconds to execute.\n")

让我们用一张图片输入:

结果很棒!

图为马丘比丘,纬度:-13.16,长度:-72.54,位于秘鲁,距离智利圣地亚哥约2,250公里。


巴黎怎么样?

图为巴黎,纬度:48.86,经度:2.35,位于法国,距离智利圣地亚哥约11,630公里。

当然,有很多方法可以优化这里使用的代码,但本教程的整个想法是提醒人们注意在边缘运行的 LLM 的巨大潜力。

更进一步

测试的小型LLM模型在边缘设备上无论是处理文本还是图像都表现良好,但当然,在图像处理方面它们有较高的延迟。结合特定的专用模型可以带来更好的结果;例如,在实际情况中,一个对象检测模型(如YOLO)可以获取图像上对象的一般描述和数量,一旦这些信息传递给LLM,就可以帮助提取重要的洞察和行动。

根据 Hailo 的首席技术官 Avi Baum 的说法,

在广阔的人工智能 (AI) 领域,最有趣的旅程之一是 AI 在边缘的演变。这段旅程将我们从经典的机器视觉带到了判别性人工智能、增强型人工智能领域,以及现在的生成式人工智能的开创性前沿。每一步都让我们更接近一个未来,在这个未来,智能系统与我们的日常生活无缝集成,提供身临其境的体验,不仅可以感知,还可以在我们的手掌中创造。

说到Hailo,我们应该很快就会看到一款新产品,Hailo-10H AI处理器。 该设备有望提供高达每秒 40 万亿次运算 (TOPS) 的性能;它的性能明显优于所有其他边缘 AI 处理器。它使 RPi5 等边缘设备能够比传统解决方案更高效、更有效地全面运行深度学习应用程序,同时显著降低成本。因此,我们应该看到该设备处理生成式 AI 模型,包括 CPU/GPU 负载最小的 LLM,功耗低于 3.5W。Hailo-10H 将使用适合 Raspberry Pi 5 的标准 M.2 外形尺寸,作为新发布的 Raspberry Pi AI 套件(使用 Hailo-8L 协处理器):

结论

本教程演示了如何将 Raspberry Pi 5 转变为一个强大的 AI 中心,能够使用Ollama和Python运行大型语言模型(LLMs),以实现实时、现场的数据分析和洞察。Raspberry Pi 的多功能性和功能,加上 TinyLlama 和 LLaVa-Phi-3-mini 等轻量级 LLMs 的功能,使其成为边缘计算应用的绝佳平台。

在边缘运行LLMs的潜力远远超出了本教程示例中简单的数据处理。以下是一些使用这个项目的创新建议:

1. 智能家居自动化:

  • 将 LLMs 集成到智能家居系统中,用于解释语音命令或分析传感器数据,实现智能家庭自动化。这可以包括实时监控和控制家居设备、安全系统和能源管理,所有这些都在本地处理,不依赖云服务。

2. 现场数据收集与分析:

  • 在偏远或移动设置中部署 LLMs,用于实时数据收集和分析。这可以用于农业监测作物健康、环境研究中的野生动物跟踪,或灾难响应中的情况感知和资源管理。

3. 教育工具:

  • 创建交互式教育工具,利用 LLMs 提供即时反馈、语言翻译和辅导。这在技术先进和互联网连接有限的发展中地区尤其有用。

4. 医疗应用:

  • 使用 LLMs 进行医学诊断和患者监测,提供症状的实时分析并建议潜在的治疗方法。这可以集成到远程医疗平台或便携式健康设备中。

5. 本地商业智能:

  • 在零售或小型商业环境中实施 LLMs,分析客户行为、管理库存和优化运营。本地处理数据的能力确保了隐私并减少了对外部服务的依赖。

6. 工业物联网:

  • 将 LLMs 集成到工业物联网系统中,用于预测性维护、质量控制和流程优化。树莓派可以作为本地数据处理单元,减少延迟并提高自动化系统的可靠性。

7. 自动驾驶汽车:

  • 使用 LLMs 处理自动驾驶车辆的感官数据,实现实时决策和导航。这可以应用于无人机、机器人和自动驾驶汽车,增强自主性和安全性。

8. 文化遗产与旅游:

  • 实施 LLMs 提供交互式和信息丰富的文化遗产地和博物馆指南。游客可以使用这些系统获取实时信息和洞察,增强体验,无需互联网连接。

9. 艺术和创意项目:

  • 使用 LLMs 分析和生成创意内容,如音乐、艺术和文学。这可以促进创意产业中的创新项目,并允许在展览和表演中进行独特的交互体验。

10. 定制辅助技术:

  • 为残障人士开发辅助技术,通过实时文本转语音、语言翻译和其他无障碍工具提供个性化和自适应支持。

了解更多

如果你想了解有关 AI、LLMs 和嵌入式机器学习 (TinyML) 的更多信息,请参阅以下参考资料:

TinyML4D 网站上,你可以找到大量关于TinyML的教育材料。它们都是免费且开源的,供教育使用——我们要求如果你使用了这些材料,请引用它们!TinyML4D是一项旨在让全球每个人都能获得TinyML教育的倡议。


团队介绍
MJRoBot
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号