如果你和我一样,家里还压着一台卖不掉的旧手机,那这个项目应该能给你一点启发。标题里那台2017年的华硕手机,我翻箱底找了出来,硬是把 Qwen2.5:0.5B 这个小模型跑通了。IttyBittyAI 这个名字是我随手起的,既调侃它参数小得可怜,又指这套方案本身足够轻量——不联网、不上云、不靠高端硬件,只用 Termux、GGUF 量化和 llama.cpp 的组合,就能让六年前的手机变成一个本地 AI 助手。这篇文章把整个过程拆开讲清楚:为什么选 0.5B 而不是 7B、部署时哪些步骤最容易翻车、以及实测速度到底有多“感人”。如果你正打算在旧设备上跑本地模型,或者想搞懂移动端推理的参数取舍,这篇应该能帮你少踩几个坑。
1. 项目整体思路:为什么非要用一台2017年的手机跑Qwen
1.1 旧手机的性能底牌到底行不行
先给这台2017年的华硕手机画个像:那个年代的主流配置大概是骁龙660/630级别处理器、4GB运行内存、eMMC闪存,没有专用的NPU,也没有太多散热余量。放在当时还算台能打的机器,但放到现在,连千元机都算不上。
可就是这样的“电子古董”,要跑 Qwen2.5:0.5B 反而是可行的。为什么?因为 0.5B 模型的体量非常小。以 GGUF 格式的 Q4_K_M 量化版本为例,权重文件大约在 400MB 到 500MB 之间,加上运行时需要的 KV cache 和其他数据,整个进程的内存占用大概在 800MB 到 1GB 左右。4GB 内存虽然吃紧,但通过合理设置 context 长度、线程数和内存锁,还是能稳定运行的。如果你硬要把 7B 模型塞进这台手机,那基本是另一种结局——光模型文件就接近 4GB,内存直接爆掉,CPU 推理速度慢到每秒钟只能出两三个 token,体验完全不可用。所以项目的第一步不是选工具,而是认清硬件上限:在 2017 年手机上跑 0.5B 是“可以做”,跑 7B 是“没必要”。
1.2 IttyBittyAI 到底是个什么“AI”
先别被 IttyBittyAI 这个名字唬住,它并不是一个庞然大物式的推理框架,更像是一套被我自己揉在一起的工具链。核心组件有三个:
- Termux:在 Android 上运行的终端模拟器,用来执行命令行工具。
- llama.cpp:能在 CPU 上高效推理量化模型的 C++ 库,这是整个方案的引擎。
- GGUF 格式的 Qwen2.5-0.5B 模型文件:这是模型本体,负责“回答问题”。
这三样东西,单独跑都不稀奇,但组合起来就有意思了。我做了一个很薄的启动脚本,把依赖安装、模型检查、参数调优封装成一条命令,让没有 Linux 经验的人也能直接在手机终端里把模型拉起来。这也是它和 Ollama 的区别——Ollama 在 Windows 上装 Qwen2.5:7b 确实方便,一条命令搞定,但 Ollama 瞄准的是桌面端那套硬件环境,旧手机上有系统版本、内存、指令集各种限制,不能直接照搬。IttyBittyAI 的思路是“少依赖、轻封装、强制走 CPU 路径”,针对移动端场景做了专门的参数预算,所以才能在六年前的手机上跑通。
2. 核心细节解析:模型、量化与推理引擎的选择
2.1 为什么偏偏是 Qwen2.5:0.5B
选择 Qwen2.5:0.5B 其实做过一轮比较。当时备选有 0.5B、1.5B 和 3B 三个档位,更小的没有中文能力不错的,更大的在手机上跑不动。0.5B 这个档位非常微妙:它只有约 5 亿参数,但因为这个体量经过比较好的指令微调,在摘要、问答、代码片段生成这些轻量任务上表现得足够“能看”。如果硬要追求 1.5B 或 3B 的推理质量,这台 2017 年手机会立刻变成吞内存怪兽,而且速度会慢到让人怀疑人生。
更重要的是,0.5B 的模型能塞进手机的内存预算。我做过一个粗略计算:Q4_K_M 量化后权重约 450MB,KV cache 按 context 长度 512 计算大概占用 30MB 左右,加上推理期间的中间激活值,整体运行内存占用控制在 800MB 上下。这样进程不会被 Android 系统立刻杀掉,还能留下富余给系统本身。如果换成 1.5B 模型,量化后也接近 1GB,加上交互缓存,4GB 内存手机基本到临界点了,后台切一下就可能被杀进程。这是我自己在实测中碰到的真实边界。
2.2 量化的分寸:不是越激进越好
GGUF 格式有多种量化级别,常见的有 q4_k_m、q5_k_m、q8_0。在 0.5B 这个规模上,我最终选的是 q4_k_m。原因有三:
- 体积合适:q4_k_m 版本大约 450MB,比 fp16 原版(约 950MB)小了一半,能在存储和内存两个层面降低成本。
- 速度达标:量化后内存带宽压力小,CPU 推理速度能提升到可接受范围。
- 精度损失可控:q4_k_m 对注意力层和部分敏感层采取了更高精度的补偿,在短文本生成任务上,表现足够稳定。
如果有人想尝试更高精度,比如 q8_0,也不是不行,但文件会膨胀到约 800MB,速度大概下降 30% 左右。我个人认为,在手机这种资源受限设备上,q4_k_m 是精度和性能的平衡点。
2.3 推理引擎:为什么 llama.cpp 是终极答案
移动端能跑 LLM 的方案不少,比如 TensorFlow Lite、PyTorch Mobile、MNN,还有各种商用的 SDK。但论开源、轻量、适配性好,llama.cpp 依然是最靠谱的选择。它的优势很直接:
- 纯 CPU 推理,不依赖 GPU/NPU,对老设备友好。
- 针对 ARM 指令集做了大量优化,能利用手机的 NEON 特性。
- 支持 GGUF 格式,搭配不同量级的模型文件,灵活度极高。
- 编译产物简单,二进制文件只有几MB,方便复制到手机里。
当然,llama.cpp 也有它的脾气。它默认为主流桌面场景优化,在移动端跑的时候需要手动指定线程数和 batch size,不能无脑用默认参数。另外它的编译需要设置针对移动端的优化开关,比如打开 ARM 相关的内建函数,否则性能和未优化版本差很多。这些都是实操中会遇到的细节,也是很多“官方教程”不会告诉你的事。
2.4 部署路径对比:Termux 方案 vs 打包成 APK
跑 Qwen2.5 到手机上,最直接的方案是打包成一个独立 APK 应用,用户安装后用聊天界面交互。但相比把推理内核编译进 APK,Termux + 命令行方案几乎零成本,缺点是界面不够友好。对我个人来说,命令行就够用了。尤其做性能和参数调优,终端反而比图形界面更直观,你可以直接看到 token 流式输出和日志。
如果想把模型分享给身边的非技术朋友,那打包 APK 是必然选择。操作上大致需要:
- 下载 Android NDK 并交叉编译 llama.cpp。
- 用 JNI 把 llama.cpp 封装成 Java/Kotlin 可调用的接口。
- 将 GGUF 文件作为 assets 打包,启动时拷贝到 app 内部存储。
- 自己写一个简单的聊天页面,绑定“发送—推理—返回”的逻辑。
这个流程并不算难,但是步骤多、联调繁琐,对只是想试试老手机性能的人来说,不如先用 Termux 打通全流程,确认推理质量没问题,再考虑 APK 化。
3. 完整实操:从零在旧手机上跑通 Qwen2.5
3.1 环境准备与依赖安装
这一步只在第一次部署时要做,前提是手机已经安装了 Termux。我用的是 F-Droid 分支的应用商店版本,因为 Google Play 版本的 Termux 限制较多,很多依赖包会装不上。装好后,先更新软件源,再安装基础依赖:
pkg update && pkg upgrade -y pkg install git cmake gcc make build-essential pkg install libgomp其中 build-essential 和 libgomp 是编译 llama.cpp 的关键,前者提供编译器,后者提供 OpenMP 并行支持。没有 OpenMP,CPU 多线程推理就白搭,性能直接砍半,这一点容易忽略。
接着拉取 llama.cpp 源码并编译:
git clone https://github.com/ggerganov/llama.cpp cd llama.cpp mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release -DLLAMA_OPENMP=ON -DLLAMA_NATIVE=ON make -j4这里的-DLLAMA_NATIVE=ON很关键,它会让编译器针对当前手机的 ARM 架构生成优化指令。如果你要交叉编译给其他 ARM 设备用,则需要设置对应的 -march 参数。编译完成后,在 build 目录下会生成llama-cli和llama-server两个可执行文件,后续推理用llama-cli就足够了。
3.2 模型下载与文件校验
Qwen2.5 模型有官方发布渠道,Hugging Face 上有 Qwen2.5-0.5B-Instruct-GGUF 官方仓库,里面按不同量化精度拆好了文件。下载时不要贪大,选q4_k_m版本,文件名里通常包含Q4_K_M.gguf字样。在手机上直接用wget或curl下载就行:
cd ~ wget https://huggingface.co/Qwen/Qwen2.5-0.5B-Instruct-GGUF/resolve/main/qwen2.5-0.5b-instruct-q4_k_m.gguf文件大概 450MB,下载完成后最好用 sha256 校验一下,防止网络传输导致文件损坏。一旦 GGUF 文件缺失或损坏,llama.cpp 会直接报“format error”之类的错误,排查起来反而浪费时间。校验命令:
sha256sum qwen2.5-0.5b-instruct-q4_k_m.gguf把输出和仓库页面给出的哈希值对比,一致再继续。
3.3 IttyBittyAI 启动命令与参数归零
启动命令看起来很简单,但每个参数都决定成败。我的启动脚本大致长这样:
./llama-cli \ -m qwen2.5-0.5b-instruct-q4_k_m.gguf \ -p "请用中文简单介绍一下你自己。" \ -n 128 \ -t 4 \ -c 512 \ -b 128 \ --single-turn逐个拆开解释:
-m:指定模型文件路径。-n:生成的最大 token 数,手机端建议控制在 128 到 256 之间。太长的话,生成后期速度会明显下滑。-t:线程数。千万不要设成跟 CPU 核心数一样多。这台手机是八核处理器,但 2017 年的 CPU 核心调度策略比较保守,开 8 个线程反而会引起严重的缓存争用。实测 4 线程是性能最优区间。-c:context 长度,也就是模型能记住的上下文窗口。手机内存有限,我建议 512,最高不要超过 768,否则 KV cache 会吃掉大量内存。-b:batch size,控制每一步同时处理的 token 数量。128 是比较稳妥的值,能提升预处理速度,又不会撑爆内存。--single-turn:如果只是测试,单轮对话可以省下维护上下文的开销。
还有两个隐藏参数值得试:--mlock可以把模型锁进内存,防止被 Android 系统换出导致推理变慢;--no-mmap在某些 eMMC 存储上反而更稳定。建议先用默认配置,跑通了再逐项调。
3.4 实测:这段代码到底能跑多快
跑起来之后,我心里其实没抱太高期待,但结果还算能接受。在 2017 年华硕手机(骁龙660 级别)上,纯 CPU 推理,Q4_K_M 量化,上下文 512,实测大约每秒 7 到 12 个 token。也就是说,让它生成一段 100 字的回答,大约需要 10 到 15 秒。
这个速度跟你现在用的云服务比,当然像蜗牛一样慢,但考虑到这是一台没有 NPU、没有独立 DSP 的六年前手机,已经非常值得欣慰了。而且推理过程虽然偏热,但并没有到烫手的程度,手机背面温温热,可以接受。
内存方面,用free -h观察,整个进程高峰期占用约 1.1GB,系统剩余内存还有 1.5GB 左右。只要不开什么大型应用,不会触发系统杀后台。
4. 常见问题与避坑实录
4.1 跑得像乌龟,一堆 token 要等半天
这是手机上跑大模型最常见的抱怨。遇到速度问题,别急着换模型,先按以下顺序排查:
- 线程数是否过高?试着从 2 到 6 依次测试,找到吞吐量最高的那个点。
- 是否关闭了
--mlock?如果模型被换到交换分区,速度会严重下降。 - batch size 是否太小?把
-b提到 128 以上,能明显加快 prompt 预处理阶段。 - 存储是不是满到爆炸?eMMC 剩余空间低于 10% 时,读写性能会断崖式下降,模型映射加载速度直接受影响。
- context 是否太大?比如 2048 的 context,在 CPU 上会额外消耗大量计算,每秒速度会再掉两三成。
4.2 进程动不动就被系统杀掉
2017 年的 Android 系统对后台进程管理比现在严格得多,尤其是在内存不足时,后台推理进程经常是被清理的“头号目标”。我的经验是这么解决:
- 在 Termux 里用
nohup启动推理命令,这样即使终端被折叠,进程也能继续跑。 - 关掉所有不用的后台应用,把内存预留出来。
- 如果系统有“锁定应用”或“保持在前台”的开关,手动操作一下。
- 杀进程实在太频繁,可以把
-c降到 256,KV cache 占用会小不少,虽然牺牲了一部分上下文能力,但换来的是稳定性。
4.3 输出中文乱码或中英混杂
Qwen2.5 的中文能力本身不错,但如果提示词不给明确约束,它很容易用英文回答,偶尔还会混入繁体字或奇怪符号。解决的办法很简单,把系统提示里加上“请始终用简体中文回答”这类强制约束。另外,llama.cpp 输出流式 token 时,偶尔会遇到半个 UTF-8 字符的问题,那是 Bash 终端的编码显示问题,一般不影响完整回答。
如果输出实在太差,考虑换用更高精度的 q5_k_m 量化版本,虽然速度下降一点,但变体说明文字会更纯净。还有一点值得提醒:0.5B 模型不适合复杂推理题,如果你拿它做数学题、多步逻辑题,出错是很正常的,这不是配置问题,是模型能力边界。
4.4 和桌面端 Ollama 跑 7B 的体验差距
网上很多人问“Ollama Windows 安装 Qwen2.5:7b 怎么搞”,那是因为桌面端跑 7B 是另一套玩法。在 Windows 上,一行ollama run qwen2.5:7b就能加载 7B 模型,内存只要 8GB 以上基本就能跑。但这依赖的是桌面系统的内存调度能力和多核缓存,手机上完全不一样。手机端的核心瓶颈是内存带宽和发热,所以你即便把它强行移植到桌面,也不能把 7B 的体验强行塞进 0.5B 的小身板里。
我的建议很简单:别把它们放在同一条起跑线上比。如果你想要高质量长回答,就用电脑。如果你想体验随时随地断网也能问问题的乐趣,那 0.5B 就是手机上的极限选择。两者是互补关系而不是替代关系。
4.5 模型文件明确下载失败或者卡住
很多新手在手机上下载大文件时会在中途失败,尤其是从 Hugging Face 拉取模型。这时候最靠谱的做法是先在电脑上下载好,再用数据线传入手机,然后放到 Termux 能访问的目录(比如~/storage/downloads)。额外说一句,如果电脑上已经装过 Ollama,并且下载过完整的模型文件,理论上也可以把 Ollama 缓存里的 GGUF 文件导出出来用于手机端,省去重新下载的流量。不过请注意,两种工具对文件路径和格式命名要求不完全一样,导出后要确认文件有没有被额外打包,否则 llama.cpp 会认不出来。
5. 实用性能对比速查
为了让你对模型大小、内存和速度有直观感受,我整理了一个粗略的对比表,以这台 2017 年手机为基准,仅供参考。
| 模型档位 | 量化格式 | 文件大小 | 运行内存峰值 | 预期速度 | 适合场景 |
|---|---|---|---|---|---|
| Qwen2.5:0.5B | q4_k_m | 约 450MB | 约 1.1GB | 7-12 token/s | 闲聊、摘要、短问答 |
| Qwen2.5:0.5B | q8_0 | 约 800MB | 约 1.6GB | 4-7 token/s | 需要更高输出质量 |
| Qwen2.5:1.5B | q4_k_m | 约 1GB | 约 2GB | 2-4 token/s | 勉强可用,体验不佳 |
| Qwen2.5:7B | q4_k_m | 约 4.4GB | 超过 4GB | 低于 1 token/s | 不适合手机 |
这张表是我根据实际测试和模型体量推导出来的,不同机型的调度器和闪存速度都会影响结果,但它能帮你快速判断自己的手机能否跑得动。总的来说,0.5B 是手机端最乐观的甜点位,1.5B 已经明显吃力,7B 完全不建议。
最后再分享一个我很喜欢的小技巧:如果只是为了在手机上临时跑个 AI 助手,不需要开机自动启动,那直接把 llama.cpp 的llama-server跑起来,让它监听手机本地的 8080 端口,再用浏览器访问页面,就能得到一个带界面的本地 AI 聊天服务。这样手机既当服务器又当客户端,同时绕开了命令行输出的“地板问题”,以后当你换了新手机,那台 2017 年的华硕手机也不用吃灰,改装成家里的小朋友专属的离线 AI 玩具,还挺有意思的。