小模型竞技场横评:从评测指标到端侧部署实践

发布时间:2026/9/2 8:26:38
小模型竞技场横评:从评测指标到端侧部署实践 过去一年多大模型领域的热度一直集中在动辄几十B、上百B参数的超大模型上。但在实际业务落地时很多团队会发现一个尴尬的现实模型能力再强部署成本、响应速度、硬件门槛一旦不匹配最终也只能停留在 Demo 阶段。反而是参数规模在 1B 到 7B 之间的小模型凭借低显存占用、高推理速度和灵活的端侧部署能力成了很多生产环境里的“性价比担当”。karminski 发布的小模型竞技场横评恰好把 8 款主流小模型放到同一套评测体系下做了全面对比。本文不打算只做一个结果复读机而是结合这类竞技场评测的常见思路拆解小模型选型时需要关注的核心指标、评测方法、部署验证方式以及从工程角度如何真正把一个小模型用起来。全文包含可直接复用的评测脚本、结果分析思路和踩坑记录无论你是刚接触小模型的初学者还是已经在做端侧部署的开发者都能从中获得一套可落地的参考方案。1. 小模型竞技场是什么1.1 竞技场评测与传统 Benchmark 的区别“竞技场”这个词在 AI 圈并不陌生。最早的大模型竞技场LMArena采用的是“盲测投票”模式用户同时输入同一个问题两个模型各自给出回答用户根据回答质量投票最终通过胜负关系计算模型排行。这种方式更接近真实使用体验但缺点也很明显——人工评测成本高、结果受主观影响大不适合快速迭代。小模型竞技场横评则是一种更工程化的做法它把多款小模型放进同一套自动化评测流程里在相同硬件环境、相同推理框架、相同评测集的条件下对模型的生成质量、推理性能、资源占用等维度做横向对比。换句话说它既保留了“多个模型同台竞技”的形式又用可量化的指标替代了人工投票得出的结论更适合作为技术选型的依据。1.2 为什么小模型突然成了焦点小模型的走红和端侧 AI 的快速发展直接相关。以“微信小程序运行深度学习模型”为代表的一类场景对模型体积、推理延迟和内存占用提出了严格限制。一个 7B 模型量化后如果能控制在 4GB 左右就能在部分移动设备或边缘设备上运行而 1B 级别的模型经过量化甚至可以低于 500MB这为小程序、App 端、嵌入式设备上的智能功能提供了可能。除此之外小模型还具备几个关键优势部署门槛低单张消费级显卡甚至 CPU 就能跑不需要 A100/H100 这类高端硬件。推理成本低单次请求的算力开销小适合高频调用场景。响应速度快参数量小生成 token 的速度通常更快对实时性要求高的场景更友好。易于定制在特定领域数据上做微调成本远低于大模型。1.3 本文的评测范围karminski 的横评覆盖了 8 款模型。为了便于说明整套评测方法本文采用一组当前主流的开源小模型作为示例对象包括 Qwen2.5-1.5B-Instruct、Qwen2.5-3B-Instruct、Llama-3.2-1B-Instruct、Llama-3.2-3B-Instruct、Gemma-2-2B-it、Phi-3-mini-4k-instruct、Mistral-7B-Instruct-v0.3 以及一款经过量化的 4-bit Qwen2.5-3B 变体。需要说明的是实际评测数据会随着框架版本、量化参数和硬件环境的变化而不同本文重点演示的是评测方法和分析思路而不是固化某一组不可复现的分数。2. 小模型评测的核心指标在做横评之前先要把“比什么”想清楚。如果只盯着某一个指标很容易被单一维度的优劣带偏。下面这四类指标是竞技场横评中最常用、也最值得关注的。2.1 生成质量类指标生成质量是模型能力的直接体现常见评测方式包括标准数据集得分如 MMLU多任务语言理解、C-Eval中文知识能力、GSM8K数学推理、HumanEval代码生成。特定任务人工评估针对业务场景构造一批 Prompt由人工或高级模型对回答打分。回答稳定性同一个问题多次提问观察答案的一致性和逻辑连贯性。需要注意的是小模型在标准数据集上的绝对分数通常低于大模型但分数差距并不一定等于业务效果差距。在垂直领域微调后小模型完全可能在特定任务上超过通用大模型。2.2 推理性能指标推理性能直接决定用户体验和部署成本。横评中最常用的性能指标有三个首 token 延迟TTFTTime To First Token用户发起请求到收到第一个 token 的时间影响“第一印象”。生成速度Tokens/s每秒生成的 token 数量影响长文本输出场景的等待时间。吞吐量Requests/s系统在并发场景下每秒能处理的请求数影响服务容量规划。这组指标的测量必须保证硬件和框架一致否则没有可比性。2.3 资源占用指标资源占用决定了模型能在什么设备上跑。主要看三个维度GPU 显存占用加载模型和推理时的峰值显存。CPU 内存占用CPU 推理或模型加载时的内存开销。模型文件大小直接影响分发和部署的便利性尤其在移动端。量化Quantization是降低资源占用的核心技术。把模型权重从 FP16 降到 INT8 或 INT4体积可以减少 50% 到 75%显存占用同步降低推理速度在某些硬件上还能提升。2.4 综合可用性指标这一部分容易被忽略但恰恰是工程落地中最关键的上下文窗口长度小模型常见 4K、8K、32K 不等影响多轮对话和长文档处理能力。指令遵循能力模型是否能严格按照 Prompt 中的格式要求输出例如 JSON 输出。中文能力对国内业务来说中文表达质量和中文知识覆盖度非常重要。框架兼容性是否支持 llama.cpp、Ollama、Transformers、ONNX Runtime、TensorFlow Lite 等常用部署方式。3. 竞技场评测环境搭建评测环境如果不统一横向对比就失去了意义。本节给出一个可复现的评测环境搭建方案包括硬件配置、软件依赖和评测数据集准备。3.1 硬件与操作系统为了模拟真实的生产环境推荐使用消费级显卡进行评测这类硬件更贴近大多数团队的实际条件。本文示例环境如下项目配置操作系统Ubuntu 22.04 LTSGPUNVIDIA GeForce RTX 4090 24GB单卡CPUIntel Xeon Gold 6330内存128GB DDR4硬盘NVMe SSD 1TBCUDA12.2Python3.10如果读者手里没有同样的硬件也不要紧。测试结果本身会随硬件浮动关键是保证 8 款模型在同一个环境下跑完这样对比结论只反映模型差异而不是硬件差异。3.2 软件依赖安装评测过程主要使用 Hugging Face Transformers 做模型加载使用 vLLM 或 llama.cpp 做推理性能测试。不同工具侧重点不同建议都装好。# 创建虚拟环境 python3 -m venv eval_env source eval_env/bin/activate # 安装基础依赖 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu122 pip install transformers datasets accelerate evaluate pip install vllm pip install llama-cpp-python这里特别说一下版本问题。Transformers、vLLM 这类库的迭代速度很快不同版本对模型架构的支持程度不同。如果遇到模型加载报错优先检查 Transformers 版本是否需要升级。建议安装时固定版本便于结果复现pip install transformers4.46.0 vllm0.6.33.3 评测数据集准备竞技场横评需要一组覆盖面足够的评测集一般分成两类通用能力集和业务场景集。通用能力集可以直接使用公开数据集例如MMLU57 个学科的多选题覆盖人文、社科、理工等。C-Eval中文基础模型评测集包含 52 个学科。GSM8K小学数学应用题考察数学推理。HumanEval代码补全任务考察代码生成能力。业务场景集需要根据实际场景构造。比如做客服机器人就整理一批真实客服对话做内容审核就构造一批需要分类判断的文本。业务评测集不需要太大一两百条精心设计的 Prompt 往往比几万条自动生成的样本更有参考价值。下面是一个简单的业务评测集示例格式[ { id: 1, category: 客服, instruction: 用户说你们家的物流太慢了等了三天都没到我要退货, expected: 先表达歉意说明物流延迟原因给出加速处理和退货两个方案, metric: 是否包含歉意和解决方案 }, { id: 2, category: 内容分类, instruction: 将下面这句话分类为科技、体育、娱乐、财经。句子苹果发布新款M4芯片性能提升明显。, expected: 科技, metric: 分类是否准确 } ]4. 编写竞技场评测脚本整个横评的核心是评测脚本。下面给出一个经过整理的评测脚本它包含两个部分生成质量评测与性能评测。4.1 批量生成评测脚本这个脚本负责加载模型、逐条执行 Prompt、记录输出结果。考虑到 8 款模型的加载耗时较长建议把每条评测结果实时保存到 JSON 文件中避免中途崩溃导致数据丢失。# 文件路径eval_generation.py import json import time import torch from transformers import AutoModelForCausalLM, AutoTokenizer MODELS [ Qwen/Qwen2.5-1.5B-Instruct, Qwen/Qwen2.5-3B-Instruct, meta-llama/Llama-3.2-1B-Instruct, meta-llama/Llama-3.2-3B-Instruct, google/gemma-2-2b-it, microsoft/Phi-3-mini-4k-instruct, mistralai/Mistral-7B-Instruct-v0.3, ] def load_model(model_name): # device_mapauto 让模型自动分配到可用设备 tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained( model_name, torch_dtypetorch.float16, device_mapauto, trust_remote_codeTrue, ) model.eval() return tokenizer, model def generate_response(tokenizer, model, prompt, max_new_tokens512): messages [{role: user, content: prompt}] text tokenizer.apply_chat_template( messages, tokenizeFalse, add_generation_promptTrue ) inputs tokenizer(text, return_tensorspt) inputs {k: v.to(model.device) for k, v in inputs.items()} with torch.no_grad(): outputs model.generate( **inputs, max_new_tokensmax_new_tokens, do_sampleFalse, temperature0.1, top_p0.9, ) generated outputs[0][inputs[input_ids].shape[1]:] response tokenizer.decode(generated, skip_special_tokensTrue) return response.strip() def run_eval(model_name, eval_data): tokenizer, model load_model(model_name) results [] for item in eval_data: try: prompt item[instruction] response generate_response(tokenizer, model, prompt) results.append({ id: item[id], category: item[category], prompt: prompt, response: response, expected: item[expected], }) print(f[{model_name}] id{item[id]} 完成) except Exception as e: print(f[{model_name}] id{item[id]} 出错: {e}) # 释放显存为下一个模型腾出空间 del model torch.cuda.empty_cache() return results if __name__ __main__: with open(eval_data.json, r, encodingutf-8) as f: eval_data json.load(f) # 如果要加入量化模型可以在 MODELS 里追加 Qwen/Qwen2.5-3B-Instruct-GPTQ-Int4 for model_name in MODELS: print(f开始评测{model_name}) results run_eval(model_name, eval_data) safe_name model_name.replace(/, _) with open(fresults_{safe_name}.json, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2) print(f完成并保存{model_name})这段脚本有几个地方值得注意。第一do_sampleFalse配合temperature0.1是为了让模型输出尽量确定减少随机性对评测结果的影响。如果想要测试模型在不同温度下的表现可以单独设置。第二trust_remote_codeTrue只有当模型仓库确实需要自定义代码时才建议打开一般官方模型可以不开。第三每个模型跑完后手动删除模型对象并调用torch.cuda.empty_cache()避免多个模型连续加载时出现显存溢出。4.2 推理性能评测脚本生成质量评测关心的是“答得好不好”性能评测关心的是“跑得快不快”。性能评测推荐使用 vLLM它对连续批处理和高并发场景的模拟更贴近线上环境。这里用 Python API 写一个简单的延迟与吞吐测试# 文件路径eval_performance.py import time from vllm import LLM, SamplingParams def benchmark_vllm(model_name, prompts, max_tokens256): llm LLM(modelmodel_name, dtypefloat16, gpu_memory_utilization0.8) sampling_params SamplingParams( temperature0.1, top_p0.9, max_tokensmax_tokens, ) # 预热让 CUDA kernel 完成初始化 _ llm.generate([你好], sampling_params) # 正式测试 start time.time() outputs llm.generate(prompts, sampling_params) elapsed time.time() - start total_tokens sum(len(output.outputs[0].token_ids) for output in outputs) total_prompt_tokens sum(len(output.prompt_token_ids) for output in outputs) print(f模型{model_name}) print(f总耗时{elapsed:.2f} 秒) print(f生成总 token 数{total_tokens}) print(f生成速度{total_tokens / elapsed:.2f} tokens/s) print(f请求吞吐{len(prompts) / elapsed:.2f} requests/s) return outputs if __name__ __main__: test_prompts [ 请介绍一下人工智能的发展历史。, 写一段 Python 代码实现快速排序算法。, 解释什么是量子计算并举例说明应用场景。, ] * 10 # 30 条请求 model_list [ Qwen/Qwen2.5-1.5B-Instruct, Qwen/Qwen2.5-3B-Instruct, meta-llama/Llama-3.2-1B-Instruct, meta-llama/Llama-3.2-3B-Instruct, ] for model_name in model_list: try: benchmark_vllm(model_name, test_prompts) except Exception as e: print(f{model_name} 评测失败: {e})4.3 结果可视化评测完成后可以把结果整理成一张对比表。CSV 格式最适合后续分析用一个简单脚本把上面的 JSON 结果和性能数据汇总起来# 文件路径merge_results.py import csv import json models [ Qwen_Qwen2.5-1.5B-Instruct, Qwen_Qwen2.5-3B-Instruct, meta-llama_Llama-3.2-1B-Instruct, meta-llama_Llama-3.2-3B-Instruct, ] with open(eval_summary.csv, w, newline, encodingutf-8) as f: writer csv.writer(f) writer.writerow([模型, 平均响应长度, 首token延迟ms, 生成速度tokens_s, 显存占用MB]) for model_name in models: try: with open(fresults_{model_name}.json, r, encodingutf-8) as fr: results json.load(fr) avg_len sum(len(item[response]) for item in results) / len(results) # 性能数据需要从 vllm 日志或上一步的输出中获取 # 这里先预留占位 writer.writerow([model_name, round(avg_len, 2), --, --, --]) print(f{model_name} 汇总完成平均响应长度 {avg_len:.2f}) except FileNotFoundError: print(f缺失结果文件{model_name})5. 横评结果分析方法假设评测已经跑完下面用一个模拟结果表来演示如何分析数据。表格中的数据为示例值仅用于展示分析方法实际数值会因环境而异。模型参数量模型大小(FP16)MMLUC-Eval生成速度(tokens/s)显存占用Qwen2.5-1.5B1.5B3.0GB56.259.882.56.2GBQwen2.5-3B3B6.0GB64.567.358.38.4GBQwen2.5-3B-INT43B1.8GB61.364.161.53.6GBLlama-3.2-1B1B2.0GB48.141.595.24.5GBLlama-3.2-3B3B6.0GB58.949.755.88.1GBGemma-2-2B2B4.0GB57.845.361.26.8GBPhi-3-mini3.8B7.6GB69.252.647.69.7GBMistral-7B7B14.0GB63.847.236.415.2GB从这张模拟表能得出几个重要结论。第一中文能力与英文能力并不完全正相关。Qwen 系列在 C-Eval 上明显领先说明中文语料的预训练质量直接决定了中文业务场景的表现。如果做英文为主的业务Phi-3 和 Mistral 更有竞争力。第二量化模型会带来几个百分点的精度损失但显存占用下降明显。Qwen2.5-3B 从 FP16 量化到 INT4 后MMLU 下降约 3 个点C-Eval 下降约 3 个点但模型体积从 6.0GB 降到 1.8GB显存占用从 8.4GB 降到 3.6GB。对于显存有限的设备来说这种权衡通常是划算的。第三模型越大单看生成质量确实越好但生成速度会下降。Mistral-7B 的生成速度只有 36.4 tokens/s是 1B 模型的三分之一左右。这里需要特别提醒在业务选型时除了评测集分数还要考虑用户的等待耐心。如果一个 7B 模型回答质量只比 3B 模型高 2 个点但速度慢了一半那在实时交互场景里未必是更好的选择。6. 小模型端侧部署实战横评的终点不是选出一个模型而是把选出的模型真正部署到目标环境里。考虑到“微信小程序运行深度学习模型”这类需求的兴起本节重点介绍小模型在端侧部署的两种常见思路。6.1 思路一服务端部署 端侧调用这是目前最稳妥、也是大多数小程序采用的方式。模型部署在云端 GPU 服务器上小程序通过 HTTPS 请求调用推理接口。参考流程如下使用 FastAPI 封装模型推理服务。将模型通过 vLLM 或 TGI 部署为高性能服务。小程序端通过 wx.request 发起请求携带用户输入。服务端返回推理结果小程序端渲染展示。示例服务端代码如下# 文件路径server.py from fastapi import FastAPI from pydantic import BaseModel from vllm import LLM, SamplingParams app FastAPI() llm LLM(modelQwen/Qwen2.5-3B-Instruct, dtypefloat16) class ChatRequest(BaseModel): prompt: str max_tokens: int 512 class ChatResponse(BaseModel): response: str app.post(/chat, response_modelChatResponse) def chat(req: ChatRequest): sampling_params SamplingParams( temperature0.1, top_p0.9, max_tokensreq.max_tokens, ) outputs llm.generate([req.prompt], sampling_params) response_text outputs[0].outputs[0].text.strip() return ChatResponse(responseresponse_text)这种部署方式的优点是模型能力保留完整、方便迭代升级缺点是需要持续的服务器成本且受网络延迟影响。6.2 思路二端侧推理 WebAssembly如果希望模型完全运行在用户设备上可以通过 WebAssembly 技术把量化后的小模型跑在小程序 WebView 环境中。当前比较成熟的方案是使用 ONNX Runtime Web 或 Transformers.js把模型转换为 ONNX 格式后配合 WebAssembly 后端在浏览器中执行。核心思路如下使用optimum-cli将 PyTorch 模型导出为 ONNX 格式。对模型进行 INT8 或 INT4 量化控制体积。在 JavaScript 侧加载 ONNX 模型执行推理。将推理结果作为小程序的智能回复来源。ONNX 导出命令示例pip install optimum onnx onnxruntime optimum-cli export onnx --model Qwen/Qwen2.5-0.5B-Instruct qwen05b_onnx/这里必须提醒端侧推理目前更适合 1B 以下的极小型模型3B 以上模型在移动端 WebView 场景下会因为内存和算力限制出现明显的卡顿。另外小程序包体积限制也需要考虑模型文件通常需要放到 CDN 上按需下载并配合本地缓存策略。微信小程序端调用 ONNX 模型的基本逻辑可以这样理解// pages/index/index.js 中的关键伪代码 Page({ async onLoad() { // 初始化推理引擎 this.session await ort.InferenceSession.create(https://cdn.example.com/qwen05b_int8.onnx); }, async handleInput(e) { const inputText e.detail.value; // 文本转 token ID const inputIds this.tokenizer.encode(inputText); // 执行推理 const results await this.session.run({ input_ids: inputIds }); // 解析输出并渲染 const reply this.tokenizer.decode(results.output_ids); this.setData({ reply }); } })这段代码只是展示整体逻辑不同 Tokenizer 的实现细节差异很大实际开发时需要按具体模型和框架的 API 调整。7. 常见问题与排查思路在小模型横评和部署过程中下面几类问题出现频率最高。问题现象常见原因解决思路模型加载时 OOM显存不足或未释放上一个模型的显存使用torch.cuda.empty_cache()按顺序加载用完即删开启量化生成结果包含大量重复内容温度设置过高或未设置重复惩罚降低 temperature开启no_repeat_ngram_size中文回答质量差模型预训练语料中中文占比低优先选择 Qwen 等中文优化模型考虑中文数据微调vLLM 不支持某模型架构Transformers 版本过旧或模型太新升级 Transformers或检查 vLLM 支持的模型列表ONNX 推理结果与 PyTorch 差异明显量化精度损失动态轴设置错误比较 FP32 ONNX 与量化后 ONNX 的差异优先使用 INT8端侧推理速度慢模型过大设备算力不足使用 1B 以下模型开启 WebAssembly SIMD减少上下文长度评测结果不稳定机器负载波动、未预热正式评测前先预热多轮取平均固定推理参数这里特别强调评测稳定性问题。GPU 的时钟频率、温度、同机其他进程的干扰都会影响性能数据。建议每个模型跑三遍取平均值并且评测期间关闭无关进程。8. 小模型选型的最佳实践基于横评经验和多个项目的落地情况这里总结几条实用的选型和部署建议。8.1 明确业务优先级选模型不是选“最好的”而是选“最合适的”。先明确业务最看重什么如果追求中文效果优先考虑 Qwen 系列。如果追求极致速度选择 1B 级别模型。如果只有 CPU 环境考虑 INT4 量化后的模型。如果要跑在移动端优先考虑 1B 以下并搭配量化。8.2 建立自己的评测集公开评测集只能作为参考。每个业务都有自己的数据分布和表达习惯建议维护一个 200 条左右的私有评测集包含真实用户输入和期望输出。每次迭代模型或调整参数后用同一套评测集回归才能保证效果不劣化。8.3 量化要放在最后做推荐的开发顺序是先用 FP16 模型验证效果确定模型架构后再做量化。如果一开始就基于量化模型调试 Prompt往往分不清效果不好是模型能力问题还是量化损失问题。8.4 注意上下文窗口的限制小模型的上下文窗口普遍较小2K 到 8K 是常见范围。在实际项目中需要做好长文本的截断或摘要处理。在 Prompt 中塞入过多历史对话不仅会超出窗口限制还会显著拖慢推理速度。8.5 建立服务监控体系模型上线后需要监控几个核心指标请求延迟、Tokens/s、显存占用、错误率、输入输出 token 数。特别是输出 token 数一旦模型在异常输入下疯狂生成会导致服务成本飙升。建议在服务端设置max_tokens上限并对单次请求的生成长度做硬限制。8.6 安全与权限边界涉及端侧部署时要注意模型文件的安全性。模型文件放在 CDN 上时建议做访问鉴权避免被恶意刷量下载。服务端接口要限制请求频率防止被脚本调用造成成本损耗。涉及敏感内容的场景需要在模型输出后增加一层内容安全过滤不能只依赖模型自身的安全对齐。9. 总结与下一步通过这套完整的竞技场横评流程我们可以掌握从评测环境搭建、批量生成脚本编写、性能测试到结果分析的完整方法。衡量一个模型是否适合业务不能只看某一项指标而要把生成质量、推理性能、资源占用和部署可行性放在一起权衡。下一步可以沿着三个方向继续深入学习 LLM 微调技术使用 LoRA 在垂直领域数据上提升小模型效果。深入 ONNX Runtime 和 TensorFlow Lite 的端侧部署优化掌握 INT8/INT4 量化的核心原理。研究 RAG 检索增强生成用外部知识库弥补小模型本身知识容量不足的问题。在实际项目中优先关注的是评测集的构建质量和部署约束的确认。把这两件事做好小模型选型就不会出现大的偏差。如果这篇文章对你有帮助可以收藏备用也欢迎在评论区分享你的小模型使用经验。