公司动态
手机端小模型评测:从跑分到可复现的工程方法
手机端能跑的模型越来越大但“哪个模型在我手机上表现最好”这个问题反而越来越难回答。你翻厂商宣传每家的榜单都把自己排第一你翻开源评测同一个模型在不同框架、不同量化格式下成绩能差出一大截你准备在真机上一一验证光是把模型包和推理框架组合起来就够折腾好几天。手机端小模型评测早就不是“跑分”的问题而是“怎么让跑分可信、可复现、可落到业务决策”的工程问题。最近Artificial Analysis 联合 Liquid AI 发布手机端小模型评测我认为这条信息值得开发者关注的真正原因不是它又给出一份“手机端模型排行榜”而是它把端侧模型评价这件事往“可复现、可对比、可解释”的方向推了一步。本文会从端侧评测为什么难、哪些指标真正影响部署效果、如何自己搭建一套本地评测流程以及上线前如何做回归验证这几个角度展开。读完你会明白手机端小模型的评测不是简单地跑一遍公共 benchmark而是一套需要结合模型、推理框架、真机资源和业务场景反复校准的工程方法。1. 为什么手机端小模型评测成了“硬需求”过去两年大模型评测的主流注意力都在云端模型上大家比的是 MMLU、GPQA、HumanEval 这类智力榜单。但随着端侧 AI 成为新方向手机端小模型的处境其实非常尴尬论智力它比不过云端大模型论部署它又不像云端那样有统一的 GPU 环境和 API 网关。你可以在服务端方便地横向对比 7B、14B、70B 模型但在手机端1B 模型配上不同量化方案就是完全不同的产品体验。更麻烦的是手机端小模型的评测维度比云端模型多得多。云端模型只需要关注“回答对不对”和“每秒输出多少个 token”而在手机上你还需要关心模型量化后是否还能保持稳定的中文理解能力首 token 延迟是否控制在用户可感知的 300ms 以内峰值内存会不会把低端机直接压到后台被杀长时间推理时发热和降频到底有多严重每万次请求的端侧推理功耗是否影响手机续航。这些指标用传统的云端评测脚本一个都测不出来必须放到真实的端侧推理环境里看。所以“手机端小模型评测”天然就是一个系统工程而不是简单地把 HellaSwag 或 CMMLU 跑一遍、算个准确率。另一个被低估的问题是选择成本。现在开源社区里适合端侧的模型数量已经不少从 0.5B、1.5B 到 3B、4B加上各种量化格式和推理框架组合数量轻松超过几十种。如果没有一套统一的评测方法团队很容易陷入“每个人都认为自己的方案最好但谁也没法说服谁”的僵局。这也是 Artificial Analysis 这类第三方评测平台与模型厂商合作做端侧评测时最值得关注的信号端侧模型开始进入“用同一把尺子量不同方案”的阶段。2. 从 Artificial Analysis 与 Liquid AI 的合作看端侧评测的范式变化在展开具体指标之前先聊聊这次合作背后反映出的趋势变化。Artificial Analysis 是独立的大模型评测与分析平台核心方式是设置统一提示词、统一评估流程把不同厂商、不同规模模型的“智力”“速度”“成本”放到同一张图表里做横向对比。它解决的是“各说各话”的问题让模型能力从宣传文案变成可比较的量化数据。Liquid AI 则是一家更强调架构效率的 AI 公司。从公开信息看它旗下的 LFM 系列模型主打低内存占用、高效推理和可控的部署成本方向恰恰就是端侧和边缘场景。这次 Artificial Analysis 选择与 Liquid AI 联合做手机端小模型评测说明端侧模型评测不再是“模型厂商自己放出的成绩单”而是第三方评测机构入场把一个更中立的评价体系带到移动端。这个变化的深层原因是端侧模型的商业模式正在变化。过去手机厂商说“AI 能力”更多是 PPT 上的展示现在应用开发者真的要把模型塞进 App真实的性能、功耗、内存数据变成采购决策依据。没有第三方评测开发者既没办法在模型 A 和模型 B 之间做选择也没办法向采购方解释“为什么这个模型比那个贵但值得用”。所以我认为这次评测的真正价值在于把“手机端小模型”从技术展示品变成了“可以被产品化度量的标准组件”。它对开发者的影响是以后评估一个手机端模型不能只看官方说的智能跑分还要看它在一套公开、可复现的评测流程下能否达到你业务要求的延迟、内存和功耗指标。3. 手机端小模型评测的核心指标有哪些要搭建一套端侧评测体系第一步不是找评测集而是明确这一轮评测要回答什么问题。我把手机端小模型常用指标分成四类实际项目里通常要组合使用。指标类别典型指标关注原因常用工具/方式智力能力MMLU / MMLU-Pro 子集、CMMLU、CEval衡量模型知识面和推理能力的底线不能低于业务可接受水平lm-evaluation-harness、自建 prompt 评测脚本代码能力HumanEval、MBPP 子集端侧模型作为编码助手或工具调用底座时需要自建或公开评测框架指令遵循IFEval、自建指令集判断模型能否按要求输出格式影响产品交互稳定性自建指令集 规则校验速度体验首 token 延迟 TTFT、解码速度 tokens/s、预填充速度 tokens/s直接影响用户等待体感llama-bench、MLC-LLM benchmark、真机打点资源占用峰值内存、模型文件大小、CPU 占用率、发热、功耗决定模型能否稳定运行在低端机上是否影响续航Android Profiler、Instruments、系统级打点这里特别说一下“智力指标”在端侧的局限。MMLU 这类 benchmark 对云端大模型有区分度但对端侧小模型的区分度正在下降。很多 1B 级模型在 MMLU 上做到 50 多分看起来只差几个点但实际业务场景里可能一个能稳定输出 JSON另一个经常格式崩塌。因此端侧评测一定要在通用指标之外加入真实业务样例。此外tokenizer 效率也很值得注意。同样是 500 字的中文回答有的模型需要 700 个 token有的只需要 400 个 token。在端侧推理场景中token 数量直接决定首 token 延迟和总生成时长。所以评测报告里如果只看 tokens/s不看“生成相同内容所需的 token 数”很可能做出错误判断。4. 端侧推理框架与评测环境怎么选评测结果和推理框架强相关。同一个模型在同一台手机上用不同框架跑出来的速度和内存占用可能相差很大。原因很简单端侧芯片的异构计算单元复杂CPU、GPU、NPU 分别适合不同算子推理框架对算子的调度策略直接决定性能。目前项目里常见的端侧推理框架主要有这几类框架主要平台特点适用场景llama.cppAndroid / iOS / Linux / WindowsCPU 优化成熟量化支持好易于集成快速验证、CPU 推理、统一基准测试MLC-LLMAndroid / iOS / WebGPU基于 TVM 编译支持 GPU 加速和多种硬件后端追求端侧 GPU 性能释放ExecuTorchAndroid / iOSPyTorch 官方端侧运行时与 PyTorch 生态衔接好已有 PyTorch 模型需要完整 PyTorch 工具链ONNX Runtime MobileAndroid / iOSONNX 生态跨框架转换方便已有 ONNX 模型或异构方案Core MLiOSApple 官方方案NPU/GPU/CPU 调度能力强只做 iOS 端时的优先考虑Qualcomm QNNAndroid骁龙可调用骁龙 NPU深度适配旗舰安卓机我的建议是评测阶段优先用 llama.cpp因为它的llama-bench工具简单直接能快速得到可对比的速度数据正式产品阶段再根据目标用户机型决定是否上 MLC-LLM 或 QNN。要特别注意评测框架版本必须固定。llama.cpp 不同 commit 的性能差异很大今天用 A 版本跑出 30 tokens/s下周换 B 版本可能变成 25 tokens/s但这不代表模型变差了。评测环境还需要遵循“先 PC 粗筛再真机验证”的原则。PC 评测速度快适合从十几个模型里筛出前三名真机评测则负责回答“这个模型在用户主力机型上到底卡不卡、烫不烫、费不费电”。真机测试不要只用模拟器CPU 调度、内存限制、温控策略都是真机才有。5. 评测数据准备与任务设计评测数据是整套体系的灵魂。直接下载公共数据集跑一遍固然省事但很容易遇到两个坑一是公共 benchmark 样本可能出现在模型的训练数据里准确率虚高二是公共数据集的语言和格式不一定符合你的真实业务。比较稳妥的做法是采用“公共数据集 业务回归集”的双层结构。公共数据集用于横向对比和外部参考业务回归集用于验证“这个模型到底能不能完成我们产品的关键任务”。业务回归集的样本不需要太多但必须覆盖核心链路。比如你做的是客服助手就应该准备 200 到 500 条真实脱敏对话标准答案由产品负责人审核后冻结如果你做的是写作辅助就要覆盖不同体裁、不同字数的输入。重点是样本要来自真实使用场景而不是临时编造。在设计 prompt 时还要注意“评测 prompt 和线上 prompt 不一致”的问题。比如线上你用了加了 system prompt 的模型服务评测时也必须在同样的 system prompt 下测试否则测出来的能力不能代表线上行为。评测脚本里最好把 prompt 模板抽出来作为配置文件管理避免模型、模板、评测数据三者版本错位。下面是一个简单但完整的评测数据格式示例推荐用 JSON 保存[ { id: case-001, task_type: choice, question: 手机端小模型评测中首 token 延迟主要影响以下哪个体验, choices: [ 模型下载速度, 用户等待第一个字出现的时间, 手机的屏幕亮度, 应用安装包大小 ], answer: B, source: business-regression-v1 } ]这份 JSON 的特点是既包含评测集本身也包含答案和来源方便后续追溯。业务回归集一旦建立建议作为团队资产固定下来任何模型升级、框架更换、量化位宽调整都需要重新跑一遍。6. 完整示例在本地跑通一个小模型评测流程下面以一个通用的端侧小模型评测流程为例演示从环境准备、基础推理、准确率计算到速度测试的完整过程。这个流程适合在 PC 上先跑通代码也可以继续复用到真机验证中。6.1 环境准备建议使用 Python 3.9 以上版本创建独立虚拟环境python -m venv .eval_env source .eval_env/bin/activate pip install transformers torch accelerate也可以把依赖写进requirements.txttransformers4.40.0 torch2.1.0 accelerate0.30.0这里不限定具体版本以实际安装时的稳定版本为准。评测脚本的核心目的是跑通“输入提示词、得到输出、解析结果”这一链路后续再进行速度和内存测试。6.2 基础推理示例以当前常见的端侧小模型为例先写一个最基础的单条推理脚本# 文件basic_inference.py from transformers import AutoModelForCausalLM, AutoTokenizer model_id Qwen/Qwen2.5-0.5B-Instruct tokenizer AutoTokenizer.from_pretrained(model_id, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained( model_id, torch_dtypeauto, device_mapauto, trust_remote_codeTrue, ) messages [{role: user, content: 用一句话解释什么是端侧AI推理。}] prompt tokenizer.apply_chat_template( messages, tokenizeFalse, add_generation_promptTrue, ) inputs tokenizer(prompt, return_tensorspt).to(model.device) outputs model.generate( **inputs, max_new_tokens128, do_sampleFalse, ) response tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokensTrue) print(response)运行验证方法python basic_inference.py如果正常会输出一句中文解释。这里有两个关键点一是apply_chat_template会按模型官方模板拼接对话避免不同模型模板不一致的问题二是do_sampleFalse保证评测结果是确定性输出方便复现。评测阶段不建议开启随机采样否则同一道题跑两次结果不一样难以定位是模型问题还是评测脚本问题。6.3 评测脚本核心逻辑下面是更接近真实评测的脚本包含 prompt 构造、答案解析和准确率计算。仍然以单选题为例# 文件eval_choice.py import json from transformers import AutoModelForCausalLM, AutoTokenizer def build_choice_prompt(question, choices): lines [f题目{question}] labels [A, B, C, D] for i, choice in enumerate(choices): lines.append(f{labels[i]}. {choice}) lines.append(请直接输出正确选项的字母例如 A。) return \n.join(lines) def parse_answer(raw_text): text raw_text.strip().upper() for ch in text: if ch in ABCD: return ch return None def evaluate_subset(model, tokenizer, examples, max_new_tokens16): correct 0 for ex in examples: prompt build_choice_prompt(ex[question], ex[choices]) messages [{role: user, content: prompt}] formatted tokenizer.apply_chat_template( messages, tokenizeFalse, add_generation_promptTrue, ) inputs tokenizer(formatted, return_tensorspt).to(model.device) outputs model.generate( **inputs, max_new_tokensmax_new_tokens, do_sampleFalse, ) decoded tokenizer.decode( outputs[0][inputs.input_ids.shape[1]:], skip_special_tokensTrue, ) if parse_answer(decoded) ex[answer]: correct 1 return correct / len(examples) if examples else 0.0 if __name__ __main__: model_id Qwen/Qwen2.5-0.5B-Instruct tokenizer AutoTokenizer.from_pretrained(model_id, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained( model_id, torch_dtypeauto, device_mapauto, trust_remote_codeTrue, ) with open(eval_set.json, r, encodingutf-8) as f: data json.load(f) acc evaluate_subset(model, tokenizer, data) print(f准确率: {acc:.2%})这个脚本把“评测”抽象成了三个环节根据数据构造 prompt、把模型输出解析成结构化结果、与标准答案比较。你只需要把eval_set.json替换成自己的业务回归集就能得到一个最简但完整的评估闭环。6.4 用 llama.cpp 基准工具测速度上面的脚本验证了“模型会不会”接下来要测“跑得多快”。速度评测建议使用 llama.cpp 自带的llama-bench./llama-bench -m ./models/qwen2.5-0.5b-instruct-q4_k_m.gguf -p 128 -n 64 -t 4参数含义分别是-m模型文件路径建议统一使用 Q4_K_M 这类内存占用适中的量化版本-p预填充 token 数模拟用户输入长度-n生成 token 数模拟模型回答长度-t线程数可按真机 CPU 核心数调整。预期输出会类似model size params backend ngl threads test t/s qwen2.5-0.5b-instruct-q4_k_m 422 MB 0.62B CPU - 4 pp128 ... qwen2.5-0.5b-instruct-q4_k_m 422 MB 0.62B CPU - 4 tg64 ...pp128和tg64分别表示预填充和生成两个阶段。生成阶段的 t/s 值就是通常大家说的“每秒吐多少个 token”。把这个命令固定下来作为团队的基准测试基线以后每次换模型、换框架版本都跑一遍数据就可比、可回归。7. 如何解读评测结果避免被跑分误导评测流程跑通之后真正难的是解读结果。首先要区分“能力基准”和“用户体验”。一个模型公共 benchmark 准确率领先但中文回答总是啰嗦、尾缀乱码很可能在业务上反而不如分数稍低但输出格式稳定的模型。端侧小模型尤其如此它的能力上限比云端大模型低用户对“稳定性”的敏感度远高于“偶尔惊艳”。其次量化格式会显著影响评测结论。同一个模型Q4_K_M 和 Q8_0 的准确率可能只差 1 到 2 个百分点但速度可能差 20% 以上。评测报告如果不说清楚量化格式结论基本无法复用。我的建议是所有评测记录里都要带上这五个字段模型版本、量化格式、推理框架版本、热身状态、设备型号。第三要注意 benchmark 污染。很多模型在预训练阶段已经把 MMLU、CMMLU 的题目见过一遍这对大模型时代的评测司空见惯但端侧模型领域更严重因为小模型要突出“高性能”很容易在公开数据集上花心思。判断方法也很简单把评测集顺序打乱或者按时间留出近期业务数据再观察分数是否出现明显下跌。第四不要只盯着 tokens/s。不同 tokenizer 的 token 密度差异巨大同样回答 200 字中文A 模型消费 500 tokenB 模型消费 350 token。此时 B 模型即使单 token 速度略慢实际用户体验也可能更好。更合理的对比方式是“生成相同目标文本所需的总时间”而不是简单比较 tokens/s。最后建议把所有评测结果沉淀成一份可检索的基线文档。哪种模型、哪种量化、在什么任务上跑出多少分全部记录在案。这样以后面对新模型时只需要跑同一个评测集就能快速判断新模型是提升了还是只是换了个壳。8. 常见问题与排查思路手机端小模型评测过程中常遇到的问题集中在依赖、同步和结果稳定性三方面。下面整理了一个排查表可以直接对照操作。问题现象可能原因排查方式解决方案模型加载报错transformers 版本过旧或依赖冲突查看完整堆栈执行pip list检查版本升级到当前稳定版重新安装依赖评测脚本输出乱码模板拼接错误或 tokenizer 未按 chat 模板处理打印模型输入 prompt人工检查使用apply_chat_template统一处理准确率与官方结果不一致prompt 模板、评测集子集、解码参数不同对比官方评测脚本参数固定 prompt、固定do_sampleFalse记录参数同一模型两次速度测试差异大手机温度、后台进程、框架版本变化保证真机重启后统一场景再测固定预热轮数和测试环境多轮取中位数同一模型在不同手机上表现悬殊芯片平台、内存带宽、框架后端不同分别记录 CPU/GPU/NPU 调度情况按目标用户机型做分档评测而不是只看平均值模型端侧推理内存溢出量化位宽过大或 context 长度过长用 Android Profiler / Instruments 观察峰值内存降低量化位宽、减小max_new_tokens或换更小模型排查时最重要的原则是“先固定变量”。测准确率时prompt、解码参数、评测集都要保持不变测速度时框架版本、线程数、输入长度都要保持一致。如果变量没有固定任何结论都是不可复现的也就失去了评测的意义。9. 最佳实践与工程建议最后把我在实际项目中积累的几条手机端小模型评测经验分享出来这些建议比跑分本身更重要。第一把所有评测配置代码化。模型版本、量化格式、prompt 模板、评测集版本都应该作为配置文件维护而不是散落在脚本里。哪怕是一个人维护的项目三个月后回看也需要能知道“当时这个分数是用哪套配置跑出来的”。第二建立多档位机型回归矩阵。不要只在主力测试机上评测。建议按用户设备分布选三个档位旗舰机、中端机、低端机。每个档位跑同一套业务回归集记录速度、内存、温度三个硬指标。如果低端机上首 token 延迟超过 1 秒这个方案就不具备上线条件。第三把评测嵌入发布流程。模型升级、推理框架升级、量化方案调整都要触发一次全量回归。最好写一个简单的 CI 脚本把业务回归集放到固定目录跑完自动输出报告。发布一个端侧 AI 版本之前必须保证评测报告和版本号一一对应。第四不盲目追求新模型。端侧模型的更新速度快但每次都换新模型对产品稳定性伤害很大。新模型要接入至少要同时满足三个条件业务回归集准确率不低于现网模型、解码速度不慢于现网模型、内存占用不超过现网模型。三个条件都满足再谈上线。第五注意安全和隐私边界。端侧评测使用的业务回归集原则上只用脱敏数据。如果评测过程需要真实用户请求必须先获得明确授权并限定在最小范围内。这也是合规建设的基本要求。下一步你可以先从自己的业务回归集做起用文中的脚本跑通第一版评测链路然后再接入 llama-bench 做速度基线逐步搭建起属于团队的端侧模型评测体系。等评测体系稳定后再结合第三方平台给出的横向对比数据做最终选型。这样下次面对“到底选哪个模型”的问题时你手里有的就是一套可量化的证据链而不是一家之言。