先说结论:手机跑本地知识库加大模型,不是博眼球的玩具,但你也没法把电脑上 Dify 那套东西原封不动压进手机里。去年我在一台骁龙 8 Gen2 的安卓机上,把 3B 量化模型和一套自建知识库完整跑通,回答质量虽然比不过云端 GPT-4 级别,但胜在隐私数据不出本机,断网也能用。这篇文章不聊“未来手机一定能跑大模型”这种空话,只讲今天就能落地的事:怎么选机型、怎么选模型、怎么搭知识库索引、怎么把推理引擎集成进移动 App、怎么调速度调发热。适合接私活想给客户做离线 AI 助手的朋友,也适合想在平板上给自己搭一个随身知识库的开发者。
1. 移动端跑这事的边界:不是硬件不行,是很多人方向不对
1.1 手机能跑什么量级的模型
先解决一个最常见的误解。不少人以为手机上跑大模型,就必须是 70B、百亿参数起步的大家伙。实际上移动端真正能流畅跑的范围非常明确:2B 到 8B 的开源模型,配合 4-bit 量化。再往上不是不能跑,而是生成速度和内存占用会让人崩溃。
我自己的判断基准很简单:每秒生成 8 个 token 以上,才算“能用”。按这个标准,去年主流旗舰机动辄 12GB/16GB 内存,跑 3B 到 4B 的 Q4 量化模型,速度能到 10-20 token/s,体验接近打字机;跑 7B 量化模型,速度掉到 4-8 token/s,够用但明显能感觉到卡顿。如果只有 8GB 内存,建议老老实实待在 3B 这个档位,否则后台微信一开,系统就开始杀进程。
除了参数规模,上下文长度是另一个隐性门槛。移动端内存有限,模型权重只占一部分,真正吃内存的是 KV Cache。同样是 7B 模型,4K 上下文和 8K 上下文的推理内存能差出 1GB 以上。所以移动端做知识库问答,尽量把上下文控制在 2K-4K,别被“长文本能力”冲昏头。
1.2 五大瓶颈逐个梳理
移动端部署这件事,卡点从来不是一个,而是五个一起上。我把它们按影响程度排个序:
内存是最先爆的。系统本身占 2-3GB,模型权重占 2-4GB,KV Cache 占 0.5-1.5GB,应用多开几个页面,内存就被吃干净了。算力反而不是第一瓶颈,现在的旗舰 SoC 跑 3B 量化模型,浮点吞吐是够的,真正受限的是内存带宽和 NPU 适配程度。存储问题我见过很多人忽略:一个 7B Q4 模型就要 4.4GB,加上 embedding 索引和 App 本体,轻松突破 6GB,用户的 128GB 手机也经不起这么造。功耗在手机上比在电脑上痛一百倍,连续推理五分钟,机身温度能到 45 度,直接触发系统降频。系统约束则是移动端独有的坑,iOS 后台几秒就挂,Android 厂商五花八门的省电策略随时会在推理到一半时把进程杀死。
1.3 什么场景适合移动端本地部署
直接说结论:适合文档量小(几百到几千个切片)、实时性要求低、隐私要求极高、网络环境不可控的场景。比如医疗咨询的离线初筛、工业设备现场检修辅助、审计人员外出取证时的资料查询,这些场景数据不能出本机,又不能在野外依赖信号。
反过来,如果知识库有几十万篇文档、业务要求高并发多用户、或者回答质量必须对标云端旗舰模型,就别硬在手机本地折腾了。这时候更合理的方案是“本地模型做隐私分流 + 云端大模型做复杂推理”的混合架构,后面我会细说。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 硬件门槛与内存规划:先把机型和配置算清楚
2.1 最低标准和推荐配置
我做了张表,方便你直接对着自己的目标机型估算。注意,手机厂商的系统调度差异极大,同芯片不同机型表现可以差出一倍,所以这张表只是经验参考。
| 目标模型档位 | 量化格式 | 最低内存 | 推荐内存 | 典型速度(旗舰SoC) | 发热情况 |
|---|---|---|---|---|---|
| 1B-2B(如 Qwen2.5-1.5B、Phi-3.5-mini) | Q4_K_M | 4GB | 6GB | 25-40 token/s | 轻微 |
| 3B-4B(如 Qwen2.5-3B、Llama-3.2-3B) | Q4_K_M | 6GB | 8GB | 12-20 token/s | 可感知 |
| 7B-8B(如 Llama-3.1-8B、Qwen2.5-7B) | Q4_K_M | 12GB | 16GB | 4-8 token/s | 明显发热 |
这里多说一句:内存不是越大越好,系统可用内存才是关键。有些 16GB 的安卓机,厂商把一半内存预留给相机和游戏,实际可用只有 8GB,跑 7B 照样崩。选测试机时,别只看参数,要看你能锁住多少个后台进程不会被杀。
2.2 内存计算:模型权重、KV Cache、系统预留
想判断一台手机能不能跑,要会用一条经验公式估算峰值内存:
code复制峰值内存 ≈ 系统基础占用(1.5-2.5GB) + 模型权重(GB) + KV Cache(约0.5-1.5GB) + 应用自身(100-300MB)
KV Cache 的具体值取决于层数、头数和上下文长度。以 Llama-3.2-3B 为例,4K 上下文 Q4 模型,KV Cache 大约 0.6GB;换成 7B 模型 4K 上下文,KV Cache 直接翻倍到 1.2GB。这也是为什么移动端部署时不建议盲目调大上下文——你以为在省事,实际在烧内存。
2.3 存储和索引包体怎么规划
存储规划很多人没概念。一个 3B Q4 模型约 1.9GB,一个 7B Q4 模型约 4.4GB。知识库向量索引这边,假设你要索引 1000 个文档切片,每个切片用 768 维向量表示,FLOAT32 存储约 3MB,加上 HNSW 图结构和元数据,通常还要翻 1.5-2 倍,最终不到 10MB。真正占空间的反而是原始文档附件,所以移动端知识库一般只保留切片后的正文,不带原始 PDF。
如果你做的是离线 App,还要考虑首次启动的资源解压时间和更新机制。我的做法是:模型文件和索引文件都做成独立版本化文件,启动时校验版本,需要更新才下载增量包。
3. 模型、推理框架与知识库引擎的选型逻辑
3.1 模型选型:先看任务再看参数
没有“最好的移动端模型”,只有“最合适当前任务的模型”。我按使用场景给几个成熟方向:
- 通用闲聊、信息抽取、简单运维问答:Qwen2.5-3B-Instruct 或 Llama-3.2-3B-Instruct,中文能力强,量化后体积约 1.9GB,8GB 内存机很稳。
- 复杂文档问答、逻辑推理较多:Qwen2.5-7B-Instruct,配合 Q4_K_M 量化,需要 12GB 内存,速度慢但回答质量上了一个台阶。
- 极低内存设备(4-6GB):Phi-3.5-mini 或 Qwen2.5-1.5B-Instruct。Phi 系列小模型在英文任务上表现亮眼,中文稍弱;Qwen 1.5B 是中文兜底。
- 端上专属Agent/工具调用:如果 App 需要模型输出结构化 JSON,优先选带 function calling 的指令版本,比如 Qwen2.5 系列,别用 base 模型自己拼提示词。
多提一句,别被“模型越大越好”绑架。知识库问答场景里,大部分问题靠检索到的片段就能答,模型的作用是“把片段组织成通顺回答”,3B 模型完全够用。模型选太大,检索做得再好也会因为速度问题让用户失去耐心。
3.2 量化等级:Q4_K_M 是甜点位
量化是把模型权重从 16bit/32bit 压到 4bit 或 8bit 的过程,代价是精度损失,收益是体积和内存大幅下降。移动端我优先推荐 Q4_K_M,它在体积和效果之间最平衡。Q8_0 精度更好,但体积直接翻倍,速度却不会提升;Q2_K 虽然能把模型压到 1GB 以内,但回答基本开始胡言乱语,尤其是中文场景,不建议用。
如果你要测试不同量化版本,我建议把每个版本的模型跑同一组 20 道测试题,人工对比答案,而不是只看困惑度这种指标。困惑度降了 0.1,用户可能感知不到;但某个日期被量化吃掉,用户一定投诉。
3.3 推理框架:安卓和 iOS 要分开看
移动端推理框架选择,本质是在“兼容性”和“性能”之间找平衡。目前我最常用的是这几个:
- llama.cpp:跨平台、生态最活跃,社区贡献了大量移动端硬件的加速补丁。优点是内存控制非常精细,可以逐层控制 mmap、mlock;缺点是需要自己写 JNI 桥接,没有官方现成 App 组件。
- MLC-LLM:基于 TVM 生态,支持 Vulkan/Metal 后端。在 iOS 上表现很好,可以一次编译多端;在 Android 上依赖 Vulkan,部分老机型支持不佳。
- MNN 或 ncnn:国内团队维护的移动端推理框架,擅长 CNN,LLM 图优化也在追。如果后续要集成视觉能力(比如 OCR、图像分类),选这俩更顺手。
- 苹果 Core ML:只适合 iOS 闭环生态,用 coremltools 转换后再用 Xcode 集成,隐私性最好,但调试深度不如前几个。
我的经验是:Android 优先 llama.cpp,iOS 优先 MLC-LLM 或 Core ML,别追求“一套代码两端跑”这个伪需求,移动端两端底层差异太大,强行统一反而两边都优化不到位。
3.4 知识库引擎:别把 Docker 里的 Dify 搬进来
看到很多新手热衷于在手机上搞 Dify、Chroma、Milvus,我的态度很明确:这些是为服务器设计的,依赖 Docker、Python 运行时、大量内存,手机根本扛不住。Dify 的核心价值是可视化编排和工作流管理,但那是后台管理端的事,不是移动端运行时该干的事。
移动端知识库的正确姿势是:用 SQLite 加向量扩展(如 sqlite-vec)或者一个轻量 HNSW 索引文件,直接把向量检索能力嵌进 App 进程里。不需要启动独立服务,不需要跨进程通信,加载一个 10MB 的索引文件,内存开销只有几十 MB,毫秒级返回结果。这才是移动端该有的体量。
Embedding 模型用 bge-small-zh-v1.5 或 bge-m3 的量化版本,前者体积约 24MB,int8 量化后更小,在手机 CPU 上跑一个短文本向量化只需要几十毫秒,完全能接受。
4. 数据链路设计:从文档到可检索向量的完整流程
4.1 整体架构拆成三段
移动端知识库与大模型的联动,核心链路是:文档预处理 -> 向量检索 -> 提示词拼接 -> 本地推理 -> 流式输出。我建议你把这条链路拆成离线构建和在线推理两大部分,不要在用户的手机上做重活。
离线侧负责:文档解析(PDF/Word/Markdown)、文本清洗、语义分块、Embedding 向量化、构建向量索引。这些工作在电脑或 CI 服务器上完成,最终产物是一个索引文件加一份文档切片的元数据表。在线侧只负责:加载索引、接收用户问题、问题向量化、TopK 检索、拼提示词、调推理引擎输出。这样设计的好处是,手机端不需要 Python 环境,不需要重型解析库,包体能控制住。
4.2 分块策略:按语义切,不要按字节数硬切
知识库效果差,八成问题出在分块上。移动端尤其明显——按固定字符数截断,一个完整段落被拦腰斩断,Embedding 后语义残缺,检索召回率惨不忍睹。
我的分块规则是:优先按 Markdown 标题、段落、列表层级做结构分块,再把超过 512 token 的长段落二次切分,重叠 32-64 token。中文场景还要注意,切分点尽量落在句号、问号、换行符之后,避免把一句话拆成两半。这个规则可以用 LangChain 或自己写几十行代码实现,但移动端运行时不要做这个操作,统一放到离线侧预处理。
4.3 Embedding 在什么环节计算
手机上直接算全部文档的 Embedding 是不现实的,尤其是首次加载时,CPU 会被打满,界面卡成 PPT。正确做法是离线批量算完,把向量索引作为二进制资产随 App 发布。用户新增知识库文档时,先在 App 内做小批量 Embedding(一次 10-20 段就够),后台逐步追加入库,别让主线程碰这些重计算。
这里有个容易踩的坑:Embedding 模型必须固定版本。离线构建用的 bge-small-zh-v1.5,和线上增量用的模型不一致,会导致同一个句子的向量空间不同,检索质量直接崩。我在版本管理时会把模型文件、索引文件、Embedding 模型 hash 一起打进资源包的版本号里,索引和模型必须配套升级。
4.4 检索时怎么拼接提示词
检索到了候选片段,不是全部塞给大模型。移动端上下文寸土寸金,提示词拼得太长,既浪费 KV Cache,又拖慢首 token 延迟。我的策略是:先做向量召回 Top20,再用轻量重排(可以按 BM25 分数与向量分数的加权和)取 Top3-5 段,每段控制在 200-300 个字符,拼成一个“分段式”提示词。格式大致是:
code复制请基于以下资料回答问题。如果资料中没有相关信息,请直接说明“当前资料不足”。
资料1:{...}
资料2:{...}
资料3:{...}
问题:{user_question}
回答:
这个模板看起来简单,但能解决 80% 的“答非所问”问题。比把十万字文档全塞进 prompt 再让模型“总结”要靠谱得多。
5. Android 实操:从 Termux 验证全链路到 App 内集成
5.1 先用 Termux 跑通命令行链路
真机调试时,我强烈建议先装 Termux,别一上来就写 Java/Kotlin 代码。Termux 里跑通命令行的好处是:环境变量、依赖、崩溃日志一目了然,排查速度快很多。
bash复制pkg update && pkg upgrade -y
pkg install git cmake make clang -y
git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j4
编译完成后,把量化好的 gguf 模型放到 /sdcard/Download/models/ 下,然后直接跑一个测试命令:
bash复制./llama-cli \
-m /sdcard/Download/models/qwen2.5-3b-instruct-q4_k_m.gguf \
-p "用一句话解释什么是检索增强生成?" \
-n 128
这一步能同时验证三件事:模型文件是否完好、芯片对当前量化格式的兼容性、实际生成速度。我遇到过好多“App 里黑屏崩溃,命令行一跑原来是模型文件下载损坏”的情况,所以这个步骤别省。
5.2 JNI 集成 llama.cpp 的现实路径
Termux 里验证通过后,再进入 Android Studio 工程集成。步骤大致是:
- 在
CMakeLists.txt里引入 llama.cpp 源码,编译出libllama.so。 - 自己写一层薄薄的 JNI 封装,暴露
init(modelPath)、chat(prompt, callback)、release()三个方法。 - 模型加载时把
gguf文件路径透传给 native 层,用llama_model_load_from_file加载。 - 推理时用流式回调把 token 逐段传回 Java/Kotlin,实现打字机效果。
核心注意点:加载模型是重操作,必须在子线程,禁止在主线程跑。我曾经在低端机上测试,3B 模型 mmap 加载也要 2-5 秒,期间 UI 线程如果被占住,ANR 弹窗马上就来。
JNI 层的崩溃是最难调试的。一定要在 native 层做好日志输出,用 __android_log_print 把 llama.cpp 的日志打到 Logcat 里。否则遇到 SIGSEGV,你连崩在哪一步都不知道。
5.3 App 内资源放置与流式输出
模型文件不建议打进 APK,因为 APK 体积会暴涨。更合理的做法是:首次启动引导用户下载模型和索引文件,或者依赖应用市场的“资源包”更新机制。文件放在 getExternalFilesDir() 或 getFilesDir() 下都行,但注意 getExternalFilesDir() 在某些机型上读取速度不如内部存储稳定,所以模型这种大文件放外部,索引放在内部存储更稳。
流式输出方面,Kotlin 侧用协程接收 JNI 回调,每次拿到一个 token 就更新 UI。这里有个体验优化小技巧:连续的空格和换行符合并渲染,可以显著降低 UI 刷新频率。不然每 token 刷一次界面,低端机直接卡成幻灯片。
5.4 一个极简 App 的结构参考
实际项目中,我不会一上来写完整架构,而是先做一个最小闭环的“测试骨架”:
- 一个
MainActivity:放输入框、消息列表、发送按钮。 - 一个
NativeEngine单例:持有 native 层的 model 和 context 引用。 - 一个
VectorStore类:用 SQLite-vec 做 TopK 检索。 - 一个
PromptBuilder:把检索结果和用户问题拼成模板。
先跑通这个骨架,再考虑加设置页、历史记录、主题皮肤。很多人一上来就画复杂架构图,结果热力图还没画完就失去了动力。移动端部署最忌讳的就是想太多、跑太少。
6. iOS 实操:Core ML 与 MLC-LLM 两条路怎么选
6.1 MLC-LLM:跨端效率和后续维护
如果你既做 Android 又做 iOS,MLC-LLM 是相对省心的选择。它基于 TVM,能直接把 HuggingFace 模型编译成针对 Metal 后端的动态库。在 iOS 上,MLC-LLM 官方仓库提供了 iOS 示例工程,可以在 Xcode 里直接跑起来。
用 MLC-LLM 的流程是:先用 Python 把模型编译成 .so 静态库,再集成进 Xcode 工程。首次推理时 Metal shader 编译会产生明显卡顿,所以我建议 App 启动后先在后台做一次 1-2 token 的“预热推理”,让 Metal 把 shader 编译缓存好,这样用户真正提问时首 token 延迟能缩短一大截。
6.2 Core ML 转换路线
另一个选择是 Core ML。流程是把 GGUF 模型或 PyTorch 模型导出为 ONNX,再用 coremltools 转成 .mlpackage。模型转换时要注意精度,尤其是量化敏感层。Core ML 支持 4-bit 量化,但默认的不对称量化在中文任务上损失偏大,我实测下来用 6-bit 或 8-bit 量化配合分位数量化方案,回答质量更稳。
集成 Core ML 的好处是直接调用 MLModel API,权限控制和后台调度交给系统,Kill 风险比自研 JNI 低。坏处是排查问题不便,模型内部跑崩了你只能看到一个笼统的错误码。所以我的建议是:项目周期紧、团队小,选 MLC-LLM;如果有专门的 ML 工程师,可以深入 Core ML 做性能打磨。
6.3 iOS 端内存和后台限制的应对
iOS 上没有“内存不够再申请”这回事,App 内存占用过高,系统直接 Jetsam 杀掉。跑 7B 模型时,App 内存可能飙到 5GB 以上,这时候必须严格控制其他模块的开销。我的建议是:模型加载前先释放图像缓存、关闭 WebView 实例,推理完成后立即释放模型 context,别让它常驻。
还有一个容易被忽略的点:iOS 后台执行时间极短,不要指望用户切到后台后模型还在线。正确做法是:回到前台时重新加载模型,加载过程中用进度条或“正在准备离线引擎”占位。反正 3B 模型的 mmap 加载在 A 系列芯片上只要 1-2 秒,用户体验完全能接受。
7. 性能调优、发热控制与实测参考
7.1 不同机型与模型组合的实测参考区间
下面是我在多台设备上的实测经验区间。不同散热条件、系统版本、固件调度差异很大,所以给的是区间而不是精确值。如果你想复现,建议按这个区间判断自己是否调偏了。
| 设备芯片 | 模型 | 量化 | 内存占用 | 生成速度 | 首token延迟 |
|---|---|---|---|---|---|
| 骁龙 8 Gen2 | Qwen2.5-3B | Q4_K_M | 约3.5GB | 12-16 token/s | 0.3-0.8s |
| 骁龙 8 Gen3 | Llama-3.2-3B | Q4_K_M | 约3.8GB | 14-20 token/s | 0.2-0.6s |
| 骁龙 8 Gen2 | Qwen2.5-7B | Q4_K_M | 约6.5GB | 4-7 token/s | 1-2s |
| 天玑 9300 | Qwen2.5-3B | Q4_K_M | 约4GB | 12-18 token/s | 0.3-0.9s |
| A17 Pro | Qwen2.5-3B | MLC-LLM Metal | 约4.2GB | 15-22 token/s | 0.2-0.5s |
注意看首 token 延迟,这个指标比总生成速度更重要。用户输入问题后,如果超过 1 秒还没开始吐字,再快的总速度都白搭。
7.2 线程数、批大小与上下文裁剪
llama.cpp 的参数里,n_threads 不是越大越好。手机 CPU 通常有 8 个核心,但大小核混合架构下,盲目开 8 线程反而会因为调度冲突导致性能下降。我实测下来,旗舰机开 4-6 线程最稳,中端机开 2-4 线程。
batch_size 影响 prompt 预填充速度,我一般设 256 或 512。太大会增加内存峰值,太小会拖慢首 token 延迟。上下文长度上面说过,不要追求 8192,移动端 2048 足够大多数问答场景。--mlock 这种把模型锁进物理内存的选项,能提速但会挤压系统可用内存,低内存设备慎用。
7.3 发热控制:从软硬两侧下手
连续生成 1000 token 后,机身温度很容易到 43 度以上。温度一高,SoC 降频,速度直线下跌,形成恶性循环。
软件侧的缓解手段有几种:限制单次回答的最大 token 数(比如默认 512);在设置页提供“性能模式”和“省电模式”,省电模式下把线程数减半;连续回答超过 3-5 轮后提醒用户休息。硬件侧能做的就是选择散热好的机型做主力测试机,以及用 Android 的性能配置把推理线程绑到大核上。
7.4 模型预热和首次加载体验
首次加载模型时,系统要做 mmap 映射、权重校验、KV Cache 分配,这些操作很容易让用户误以为 App 卡死了。务必在进度提示里说明“正在加载本地模型,需要约 5-10 秒”,而不是给一个转圈图标。
iOS 的 Metal 预热前面提过,Android 这边也有类似问题——首次调用 GPU 后端时,驱动要编译 shader,可能卡住 2-3 秒。所以我的习惯是:App 启动后,趁用户在阅读欢迎页时,在后台线程把模型和 shader 都预热一遍。
8. 真实踩坑记录与落地建议
8.1 系统把 App 杀掉的“元凶”排查
移动端最让人崩溃的问题不是模型回答错误,而是推理到一半进程被系统杀死。我在调试时发现,很多“崩溃”其实是内存压力触发了 init 进程的 Low Memory Killer。排查方法很简单:Android 上用 adb shell dumpsys meminfo <package> 看 dalvik heap 和 native heap 占用;iOS 上检查 Jetsam 日志。
对策有几个:降低上下文长度、避免常驻多个模型实例、把 WebView 换成轻量原生组件、关闭图片懒加载。很多人忘了 WebView 是吃内存大户,一个简单的配置页如果用 WebView 实现,能轻松吃掉 300MB,直接压垮 8GB 设备。
8.2 中文分块切碎导致的检索失败
这是我见过最多人踩的坑。离线构建时用英文的字符截断逻辑处理中文,结果一个完整句子被从中间切开。Embedding 模型拿到的是残缺文本,语义混乱,用户问“这个设备的最大功率是多少”,检索到的片段是“最大功”+“率是多少”,匹配质量自然很差。
现在我做离线分块时,会先做一次简单的句子边界识别:把文本按 。!?; 和换行切分,再按 256-512 token 聚合。这个逻辑不复杂,但效果提升非常明显。如果你用的是 LangChain 之类的工具,一定要检查 RecursiveCharacterTextSplitter 的 separators 顺序,把中文标点排在第一个。
8.3 索引和模型版本不配套导致的“灵异现象”
有一次我升级了 embedding 模型,但忘了更新已发布的索引文件结果用户端召回质量断崖式下跌。问题排查了两天才发现,跟推理模型完全没关系,是索引向量空间变了。从那以后,我把 embedding 模型和索引文件绑成一个“知识库版本”,App 启动时校验版本号,不匹配就直接提示更新,而不是默默跑一个坏索引。
8.4 什么时候别自己造轮子
如果你的项目只是临时演示,或者团队没有移动端原生开发能力,完全没有必要从零搞底层集成。现在市面上有一些开源 App 和 SDK 已经做了封装,比如支持离线模型和知识库的移动端方案,直接改配置接数据就能用。自己造轮子的成本真的比想象中高,光是一个流式输出的光标管理就能耗掉一整天。
8.5 我这几个月沉淀下来的一点心得
移动端部署本地知识库加模型,本质上是一个“资源有限的嵌入式系统”问题。它考验的不是你会不会调 API,而是愿不愿意在内存、速度、质量、发热之间做痛苦的取舍。我的习惯是:离线底座做好之后,再给应用加一个“在线可选”开关。本地模型做隐私过滤和快速闲聊,云端模型负责复杂推理,两者共享同一个向量索引。这样既能保住隐私卖点,又不至于在演示时翻车。
真的想动手的朋友,我建议按这个顺序来:先在 Termux 里把命令行链路跑通,再写 App 集成,最后再回头调速度和发热。顺序一旦反了,你会被各种环境问题搞到怀疑人生。等你把 3B 模型在手机上跑出 15 token/s 的那一刻,你会觉得前面踩过的所有坑都值了。
