
1. 先搞清楚在树莓派上跑AI到底要解决什么问题在树莓派上折腾AI尤其是像Gemma这样的语言模型核心要解决的不是“能不能跑起来”而是“在资源极度受限的环境下如何稳定、高效地完成推理任务”。很多人一上来就找各种模型和框架结果卡在编译、内存不足或者速度慢到无法忍受。这篇文章要聊的就是如何用LiteRT这个轻量级运行时在树莓派上把Gemma模型跑起来并且跑得像个样子。边缘AI的价值在于本地化、低延迟和隐私保护。你不用把数据传到云端就在设备上完成处理。但树莓派的算力尤其是CPU和有限的内存是硬伤。所以整个过程的重点不是追求极致的性能而是找到资源消耗、推理速度和模型效果之间的平衡点。如果你手头有树莓派4B或5想尝试部署一个能进行文本生成或对话的小模型而不是仅仅跑个目标检测那么这套组合值得一试。LiteRT的核心思路是“精简”和“适配”它去掉了大型深度学习框架里很多用不上的组件专门为ARM架构和有限内存优化。而Gemma是Google推出的轻量级开源语言模型家族有2B、7B等参数版本相比动辄上百亿参数的大模型它更有可能在边缘设备上运行。但“有可能”不等于“开箱即用”中间的环境配置、模型转换、参数调优才是真正的门槛。2. 环境准备别在第一步就踩坑在开始写任何代码之前先把环境理顺。树莓派上的环境问题能卡住90%的人。2.1 硬件与系统选择首先看你的树莓派型号。树莓派4B 4GB/8GB内存版本是起步门槛2GB内存的版本基本不用考虑跑语言模型。树莓派5的性能更强体验会好很多。存储方面至少使用一张32GB以上的高速MicroSD卡A1/V30标准以上或者更好的是外接USB 3.0的SSD这会极大改善模型加载和交换文件的速度。操作系统首选64位的Raspberry Pi OSBullseye或Bookworm。32位系统无法利用全部内存且很多现代AI库只提供64位预编译包。使用官方的Raspberry Pi Imager工具刷写系统时如果遇到下载慢对应热搜词“raspberry pi imager慢”可以尝试更换软件源镜像站或者在网络环境更好的时候操作。刷好系统后第一件事是扩容文件系统sudo raspi-config-Advanced Options-Expand Filesystem并更新软件源为国内镜像如清华源、中科大源这能避免后续安装包时漫长的等待。2.2 基础依赖安装通过SSH连接到你的树莓派或者直接在桌面环境打开终端。先进行系统更新并安装基础编译工具sudo apt update sudo apt upgrade -y sudo apt install -y python3-pip python3-venv git cmake build-essential对于AI相关的计算虽然树莓派GPUVideoCore支持有限但我们可以利用一些优化库。安装OpenBLAS作为基础的数学运算加速sudo apt install -y libopenblas-dev libatlas-base-dev重要提示树莓派上不建议直接使用pip安装大型包到系统Python环境。务必使用Python虚拟环境。python3 -m venv ~/venv_litert source ~/venv_litert/bin/activate激活虚拟环境后命令提示符前会出现(venv_litert)字样。2.3 LiteRT的获取与准备LiteRT可能不是一个直接pip install就能搞定的包它更可能是一个需要从源码构建的运行时库。我们需要先获取它的源代码。cd ~ git clone LiteRT的仓库地址 # 此处地址需替换为实际地址例如 https://github.com/example/litert cd litert查阅仓库的README.md或docs目录找到针对Linux ARM架构尤其是aarch64的编译指南。编译过程通常如下mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelease -DARCH_TYPEaarch64 make -j$(nproc) # 使用所有核心编译编译成功后你会得到核心的库文件如liblitert.so。你需要将其安装到系统路径或者设置LD_LIBRARY_PATH环境变量让Python能够找到它。同时通常还会有Python绑定包如python目录下的setup.py需要用它来安装LiteRT的Python接口。cd ../python pip install -e . # 以可编辑模式安装方便调试如果仓库提供了针对树莓派的预编译wheel包那将省去编译的麻烦直接pip install即可。请以官方仓库的说明为准。3. 搞定Gemma模型从下载到转换模型是另一个重头戏。你不能直接把从Hugging Face下载的原始PyTorch或TensorFlow模型扔给LiteRT通常需要一个转换步骤。3.1 获取Gemma模型Gemma模型可以在Hugging Face Model Hub上找到。例如我们可以使用transformers库来下载2B参数版本的模型。由于树莓派内存和磁盘空间有限建议从有更好网络环境的机器上下载再传输到树莓派。在你的开发机比如笔记本电脑上# 在开发机上操作 python3 -c “from transformers import AutoTokenizer, AutoModelForCausalLM; modelAutoModelForCausalLM.from_pretrained(‘google/gemma-2b’); model.save_pretrained(‘./gemma-2b’); tokenizerAutoTokenizer.from_pretrained(‘google/gemma-2b’); tokenizer.save_pretrained(‘./gemma-2b’)”这将把模型和分词器下载到本地的gemma-2b文件夹。然后使用scp或U盘将这个文件夹拷贝到树莓派的~/models/目录下。注意确保你遵守Gemma模型的许可协议并且有权限下载和使用。3.2 模型格式转换LiteRT很可能支持的是特定的模型格式比如ONNX、TFLite或者其自定义的格式。你需要使用LiteRT提供的转换工具将PyTorch格式的Gemma模型转换成运行时支持的格式。假设LiteRT提供了一个名为litert-convert的工具转换过程可能像这样cd ~/litert/tools # 假设转换工具在此目录 python convert_to_litert.py \ --input_model ~/models/gemma-2b \ --output_model ~/models/gemma-2b-litert.bin \ --model_type gemma \ --quantize int8 # 量化是边缘设备的关键步骤大幅减少内存占用和加速推理量化Quantization是这里的核心操作。它将模型参数从32位浮点数FP32转换为8位整数INT8等更低精度的格式牺牲微不足道的精度换来内存占用减半甚至更多、推理速度提升的巨大收益。对于树莓派INT8量化几乎是必须的。转换成功后你会得到一个或多个二进制文件如gemma-2b-litert.bin这就是LiteRT运行时可以直接加载的模型。4. 编写并运行你的第一个推理脚本环境好了模型也转换了现在来写一个最简单的Python脚本验证整个流程。4.1 最小化推理代码在树莓派上创建一个测试脚本test_gemma.py#!/usr/bin/env python3 import sys sys.path.append(‘/home/pi/litert/python’) # 如果LiteRT Python包未全局安装添加路径 import litert import numpy as np import time # 1. 初始化LiteRT运行时 runtime litert.Runtime() runtime.init() # 2. 加载转换后的模型 model_path “/home/pi/models/gemma-2b-litert.bin” model runtime.load_model(model_path) # 3. 准备输入 # 假设我们有一个简单的文本编码函数这里需要替换为实际的Gemma分词逻辑 # 这里仅为示例实际需使用正确的tokenizer input_text “Explain the concept of edge AI in one sentence.” # 使用正确的分词器将文本转换为token ids # token_ids tokenizer.encode(input_text, return_tensors“np”) # 这里我们模拟一个形状为 [1, 10] 的输入 token_ids np.array([[1, 234, 567, 890, 1234, 5678, 9012, 3456, 7890, 1011]], dtypenp.int32) # 4. 创建输入输出Tensor input_tensor litert.Tensor.from_numpy(token_ids) output_tensor litert.Tensor(shape(1, 10), dtypelitert.DataType.INT32) # 输出形状需根据模型定义 # 5. 执行推理 start_time time.time() model.run([input_tensor], [output_tensor]) inference_time time.time() - start_time # 6. 处理输出 # 将输出Tensor转回numpy并解码为文本 output_ids output_tensor.to_numpy() # output_text tokenizer.decode(output_ids[0]) print(f“Inference took {inference_time:.2f} seconds”) print(f“Output token ids: {output_ids}”) # print(f“Generated text: {output_text}”) # 7. 清理 model.release() runtime.release()这个脚本包含了从初始化、加载模型、准备数据、运行推理到释放资源的完整流程。最关键的是第3步和第6步你需要集成正确的Gemma分词器Tokenizer否则输入输出都是乱码。分词器可以从你之前下载的gemma-2b文件夹里加载。4.2 处理分词器集成修改脚本集成真正的分词器from transformers import AutoTokenizer # 加载分词器 tokenizer AutoTokenizer.from_pretrained(“/home/pi/models/gemma-2b”) input_text “Explain the concept of edge AI in one sentence.” inputs tokenizer(input_text, return_tensors“np”) input_ids inputs[“input_ids”].astype(np.int32) # 确保数据类型匹配LiteRT要求 # … 后续推理 … # 获取输出后解码 output_ids output_tensor.to_numpy() generated_text tokenizer.decode(output_ids[0], skip_special_tokensTrue) print(f“Generated text: {generated_text}”)4.3 首次运行与问题排查在虚拟环境中运行脚本cd ~ source ~/venv_litert/bin/activate python test_gemma.py你大概率会遇到第一个错误。别慌按顺序排查导入错误ImportErrorNo module named ‘litert’。这说明LiteRT的Python包没有正确安装。回到~/litert/python目录确认pip install -e .成功执行并且当前虚拟环境路径正确。库加载错误Cannot open shared object file: No such file or directory。这是动态链接库问题。确保编译生成的liblitert.so所在的目录在LD_LIBRARY_PATH环境变量中。可以临时设置export LD_LIBRARY_PATH/home/pi/litert/build:$LD_LIBRARY_PATH然后再次运行脚本。模型加载失败提示模型格式错误或损坏。确认转换步骤成功并且转换工具的参数如模型类型、量化方式与当前LiteRT运行时版本兼容。内存不足Killed这是树莓派上最常见的问题。运行htop命令观察内存占用。如果模型加载时就被系统终止说明模型即使量化后仍然太大。考虑换用更小的模型如Gemma-2B的INT4量化版本或者增加树莓派的交换空间swapsudo dphys-swapfile swapoff sudo nano /etc/dphys-swapfile # 修改CONF_SWAPSIZE2048 (单位MB) sudo dphys-swapfile setup sudo dphys-swapfile swapon注意交换空间使用SD卡频繁读写会降低寿命和速度这只是权宜之计。推理速度极慢首次推理可能很慢因为涉及模型加载和初始化。后续推理会快一些。如果持续很慢检查CPU频率是否被限制vcgencmd get_throttled # 查看是否因过热而降频 cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq # 查看当前频率确保树莓派散热良好。5. 性能调优与生产化考量当单次推理能跑通后我们要考虑如何让它更实用。5.1 关键参数调优LiteRT运行时和模型加载通常有一些可配置参数在初始化时可以设置config { “num_threads”: 4, # 设置推理使用的CPU线程数通常设为树莓派的核心数4 “use_arena”: True, # 使用内存池减少动态内存分配开销 “arena_size”: 256 * 1024 * 1024, # 内存池大小根据模型大小调整 } runtime.init_with_config(config)对于生成式模型如Gemma推理时的生成参数至关重要max_length: 生成文本的最大长度。越长越耗时耗内存。在边缘建议设置为50-128。temperature: 采样温度控制随机性。0.0为贪婪解码确定性高可能重复1.0更随机。边缘应用通常设低一些如0.7以保证输出稳定。top_p (nucleus sampling): 另一种控制随机性的方法。通常与temperature配合使用。这些参数需要在调用模型生成时传入具体方式取决于LiteRT的API设计可能是在model.run时通过额外的参数字典传入。5.2 实现流式输出对于交互式应用等待模型生成完整句子再返回体验很差。可以实现流式输出每生成一个token就返回一次。这需要你能够分步调用模型的“forward”函数而不是一次性生成全部。查阅LiteRT的API看是否支持获取模型的“next_token”概率然后自行实现采样循环。# 伪代码展示流式概念 input_ids tokenizer.encode(prompt, return_tensors“np”) for _ in range(max_length): # 单步推理获取下一个token的logits next_token_logits model.step(input_ids) # 根据temperature和top_p采样下一个token next_token_id sample_from_logits(next_token_logits, temperature, top_p) # 将新token加入输入序列 input_ids np.append(input_ids, [[next_token_id]], axis-1) # 解码并输出当前token对应的文本 word tokenizer.decode([next_token_id], skip_special_tokensTrue) print(word, end“”, flushTrue) if next_token_id tokenizer.eos_token_id: break5.3 设计简单的服务接口要让其他应用调用可以封装一个简单的Web服务。使用轻量级的框架如Flask或FastAPI注意FastAPI依赖较多可能较重。安装Flaskpip install flask创建一个app.pyfrom flask import Flask, request, jsonify, Response import numpy as np import litert # … 加载模型和分词器的代码 … app Flask(__name__) app.route(‘/generate’, methods[‘POST’]) def generate(): data request.json prompt data.get(‘prompt’, ‘’) max_length data.get(‘max_length’, 50) # 调用之前封装好的推理函数 generated_text run_inference(prompt, max_length) return jsonify({‘text’: generated_text}) # 流式生成端点 app.route(‘/generate_stream’, methods[‘POST’]) def generate_stream(): data request.json prompt data.get(‘prompt’, ‘’) def stream(): # 这里实现上述流式生成的循环 for token_text in stream_inference(prompt): yield f“data: {token_text}\n\n” return Response(stream(), mimetype‘text/event-stream’) if __name__ ‘__main__’: # 仅在本地监听生产环境需使用WSGI服务器如gunicorn app.run(host‘0.0.0.0’, port5000, threadedFalse) # 单线程避免GIL和内存问题重要提醒树莓派资源有限不要使用多线程或多进程处理并发请求。使用队列Queue或者将服务设计为单请求顺序处理。对于真正的生产场景更推荐使用专门的推理服务器框架如Triton Inference Server的ARM版本但配置更为复杂。6. 常见陷阱与长期运行建议把Demo跑起来只是第一步要稳定运行还得避开这些坑。6.1 内存管理是生命线树莓派上最大的敌人就是内存。除了之前提到的增加交换空间更要做好内存监控。监控工具使用htop或free -m实时查看。关注RES常驻内存和SWAP使用量。内存泄漏排查长期运行服务后如果内存持续增长可能是Python或LiteRT底层有内存未释放。尝试定期重启推理服务例如每处理100个请求后重启一次进程这是一个简单粗暴但有效的策略。模型卸载如果不持续使用考虑在空闲一段时间后卸载模型model.release()需要时再加载。但这会带来加载延迟。6.2 温度与稳定性持续高负载的CPU推理会使树莓派芯片温度飙升触发温控降频throttling导致性能骤降。强制散热必须安装散热片和风扇。被动散热在AI负载下基本不够用。监控温度vcgencmd measure_temp。长期运行最好保持在70°C以下。性能模式可以在/boot/config.txt中设置arm_freq、over_voltage等参数进行超频但会进一步增加发热和不稳定风险不推荐新手操作。6.3 输入输出与日志输入长度限制严格限制用户输入的文本长度。Gemma模型有上下文窗口限制如8192 tokens超长输入会导致推理错误或内存溢出。在API入口处进行截断。输出清理模型生成的内容可能包含特殊标记或不可见字符做好后处理。日志记录将服务请求、推理时间、内存状态、错误信息记录到文件。这不仅是调试的需要也能帮助你分析服务性能和瓶颈。使用Python的logging模块并设置日志轮转避免日志文件撑满SD卡。6.4 备选方案与降级策略如果Gemma-2B在树莓派上仍然吃力可以考虑以下方向更小的模型寻找参数量更小的模型例如1B甚至几百M参数的语言模型。或者使用专门为移动端/边缘端设计的模型架构如MobileLLM、Phi系列等。更强的量化从INT8尝试INT4甚至二值化量化虽然精度损失更大但速度和内存收益也更大。任务简化如果你的应用不需要生成长文本而是分类、问答或提取可以只使用模型的编码器Encoder部分或者使用专门为下游任务微过的小模型。硬件升级考虑使用带有NPU神经网络处理单元的边缘设备如Jetson Nano、RK3588开发板等它们对AI推理有专门的硬件加速。在树莓派上部署像Gemma这样的语言模型是一次对“边缘AI”概念的深度实践。它考验的不是你调用API的能力而是对硬件限制的深刻理解、对软件栈的细致把控以及解决问题的耐心。整个过程的核心思路是“裁剪”和“适配”用LiteRT裁剪运行时开销用量化裁剪模型体积用参数调优裁剪资源消耗。成功的关键往往不在于第一步的顺利而在于遇到内存溢出、加载失败、速度缓慢时那一层层的排查和尝试。从这个项目出发你可以将这套方法论应用到其他模型和边缘场景中。