1. 这次部署要解决的真实问题:选型不能靠“感觉”
大概一个月前,我们准备上一个智能客服与知识库问答项目,算法组内部先吵了一架:有人说Llama-3.1-8B生态好、社区资料多,有人说Qwen2.5中文效果更稳,还有人说干脆上14B再量化一下,省卡又提速。大家各拿几篇官方博客当论据,谁也说服不了谁。最后老板一句话终结了讨论:“别在这感觉来感觉去,给我拿评测数据说话。”
于是我接了个活:从零部署一套OpenCompass大模型评测平台,把候选模型和量化后的模型都拉出来遛一遛,用同一套数据集、同一套参数、同一个随机种子,跑出可横向对比的分数,再用这些分数反推选型决策。
先说结论:这套平台部署本身没多难,真正花时间的是评测任务设计、量化模型评估和结果解读。这篇文章把整个过程的思路、配置、命令和坑都记录下来,给正准备干同样事情的人一个参照。文章里会涉及三类核心内容:OpenCompass平台的搭建步骤、量化模型(int8/AWQ等)的能力衰减评估、以及怎么用评测结果做模型选型。
这里先澄清一个容易混淆的点:一说到“量化”,搞股票的人会想到量化指标,做部署的人会想到INT8、AWQ、GPTQ这些模型压缩手段,而标题里“量化模型能力选型”其实是双关——既要用量化指标评测模型能力,也会评估量化后的模型能不能打,两者我都会展开讲。
适合看这篇内容的读者,主要是这几类:算法工程师或者AI应用开发,正在做开源模型选型但苦于没有统一对比口径;想在公司内网环境搭一套可复用的评测流程;或者已经跑通了OpenCompass,但数据集怎么挑、参数怎么配、量化模型的损失怎么评估这些细节还比较模糊。
2. 为什么选了OpenCompass,而不是自己写脚本或别的框架
在确定OpenCompass之前,我其实先试了另外两条路:一条是用lm-evaluation-harness直接跑,另一条是team里有人提的“自己写个评测脚本,调API问一圈就行”。这两个方案各有各的问题,也正是这些问题把我推向了OpenCompass。
2.1 自建评测脚本为什么被我否了
自己写脚本看起来最简单:拿一套测试题,逐条问模型,比对答案,算个准确率。但实际操作起来全是细节坑:模型的输出要规范化处理,比如“答案是B”和“B”必须算同一个结果;数学题的答案格式稍有不同就算错;不同模型对相同system prompt的敏感度差异很大;评测过程中一旦某个样本超时或者崩溃,中断恢复又得自己实现。这些活加起来,看起来是几天的工作量,实际上一两周都未必能做得严谨。更麻烦的是,这类脚本的可信度在团队内部会受到挑战——你今天这么算,明天他那么算,结果没法复现。
2.2 OpenCompass核心优势在哪
OpenCompass是上海AI实验室开源的大模型评测框架,它把上面这些杂活基本都包了。模型加载、数据集处理、inference、答案抽取、指标计算、结果汇总,整条pipeline是闭环的,配置一次之后换模型、换数据集都很快。尤其对我这个场景有三个关键能力:
- 支持多种模型接入方式。HuggingFace模型直接传路径就行,模型量化后的本地目录也能识别,这对我后面评测GPTQ、AWQ模型很重要。
- 数据集非常丰富。CEval、MMLU、CMMLU、GSM8K、HumanEval这些主流的都在内置列表里,不需要自己找数据源。
- 评测任务可配置、可复现。所有参数写在yaml里,后续任何人跑同一份配置都能得到同样的结果,这在团队协作里价值很大。
2.3 和lm-evaluation-harness的对比
lm-evaluation-harness本身是个很优秀的工具,但它偏“评测脚本集合”,一次性跑多个模型多个任务时,要自己写不少胶水代码。而且它对中文数据集的支持没有OpenCompass那么顺手,CEval这类中文数据集还是OpenCompass里更成熟。OpenCompass面向的场景更偏“评测平台化”,官方也维护了适配大量模型的配置文件,省了我很多事。
当然,OpenCompass也不是没有缺点。它的文档更新速度快,版本之间的配置结构有过变化,网上很多教程还停留在老版本,照着做会报错。这个我在部署阶段就踩了几个坑,后面会专门写一节。
3. 从零部署:环境、安装、模型与数据集准备的关键动作
部署环境是我们的一台开发机:双路32核CPU、4张RTX 4090 24G、系统是Ubuntu 20.04、CUDA是12.1。下面的步骤在实际操作中每一步都有可以跳过但最好别跳的细节,我按执行顺序拆开写。
3.1 创建独立的Python环境
OpenCompass依赖的包不少,强烈建议用conda单独建环境,千万不要图省事直接装到base环境里。我这里用了Python 3.10,兼容性和包支持都比较稳。
conda create -n opencompass python=3.10 -y conda activate opencompass创建完环境后先确认几个基础信息,避免后面装完发现CUDA版本不对白折腾:
python --version nvidia-smi nvcc --versionNVIDIA驱动和CUDA runtime版本不一致是很常见的坑,只要nvidia-smi里看到的CUDA版本不低于12.0,通常都没问题,因为PyTorch一般自带CUDA runtime。
3.2 安装OpenCompass和额外依赖
安装主体用pip直接从官方源拉:
pip install -U opencompass如果服务器网络下载慢,可以用国内镜像加速。安装完成后,先把测评所用的基础依赖也一并装好,否则后面跑数据集时会缺包:
pip install opencompass[metrics] pip install jieba rapidfuzz[metrics]这个扩展包含了计算评测指标所需的依赖,比如rouge、bleu相关的库。我用的是OpenCompass 0.3.x版本,如果你用的是更新的版本,建议装完后先看一下官方文档里有没有特殊的依赖说明。装完立刻验证一下:
opencompass --help能正常打印出帮助信息,说明主体安装成功。
3.3 模型文件准备:本地目录优于在线下载
这是部署阶段最容易翻车的地方。默认情况下,OpenCompass配置里写HuggingFace模型名(比如Qwen/Qwen2.5-7B-Instruct)也能跑,但需要从HF下载模型权重,网络稍不稳定就会中断,断点续传也不友好。我直接把所有候选模型下载到本地目录,评测配置里传本地路径。
下载模型我分了两个来源:
- HuggingFace模型:配置了HF镜像环境变量,下载速度会明显改善。
- ModelScope上有的模型:直接用
modelscope的Python SDK下载,速度通常也不错。
export HF_ENDPOINT=https://hf-mirror.com huggingface-cli download Qwen/Qwen2.5-7B-Instruct --local-dir /data/models/Qwen2.5-7B-Instruct注意--local-dir后面这个目录参数,本地路径一定不要带特殊字符,否则后续OpenCompass解析路径时偶尔会出问题。每个模型我额外保留了config.json和tokenizer_config.json,后面做量化评测时,量化模型目录还要引用原模型的tokenizer,这个结构后面细说。
3.4 数据集准备:想省事又不想出错的办法
OpenCompass内置数据集列表很全,官方文档里有完整清单。我这里先选了几个最核心的:CEval(中文综合)、CMMLU(中文知识)、MMLU(英文综合)、GSM8K(数学推理)。
部署时不需要手动下载全部数据集,OpenCompass在跑评测任务时会自动加载。但实际问题在于,自动下载同样依赖网络的连通性,尤其CEval这类数据集挂在HuggingFace上时,容易卡在下载阶段。稳妥方案是先手动把数据集下载到本地缓存目录,再用环境变量指定缓存路径。
export HF_HOME=/data/hf_cache export HF_DATASETS_CACHE=/data/hf_cache/datasets第一次跑评测之前,可以先用一个小数据集试跑,比如只加载CEval验证集,确认数据集都能正常从缓存读取,再正式跑大任务,这个习惯帮我避免过很多次“跑了一小时才发现数据集没下载完”的尴尬。
4. 评测任务设计:数据集怎么选、参数怎么配才不是“瞎跑分”
框架搭起来了,下一步是设计评测任务。这个阶段是最容易“花了很多算力跑出一堆没用数字”的环节。我按“选数据集→配模型参数→配任务参数”三层来展开。
4.1 数据集的选择逻辑:不能只看英文榜单
很多人的第一反应是“官方榜单跑什么我就跑什么”,比如MMLU、GSM8K全套上。但如果你做的是中文业务场景,重点跑英文榜单会严重误导选型。我这次选数据集的逻辑是这样:
- CEval和CMMLU:覆盖中文知识和中文推理,是判断模型中文能力的第一道筛子。这两个数据集官方还区分了验证集和测试集,业务数据求稳时先跑验证集,最后定稿再用测试集。
- MMLU:保留它,是为了看模型的英文综合能力和世界知识覆盖度,毕竟通用基座的语言能力不能只看中文。
- GSM8K:数学推理能力在客服、金融、教育类场景里很重要,跑它来判断模型在链条推理上的表现。
- 再加一组自建业务FAQ评测集:直接用我们线上知识库里抽了300条问答,转成OpenCompass支持的格式,在CEval之外额外看模型对真实业务语料的适配度。
这里要插一句:自建评测集是整个环节里价值被严重低估的一部分。公开数据集再好,和你业务场景总是隔着一层。300条FAQ规模不大,但已经能暴露出模型在领域术语、多轮表达上的明显差距。后面选型报告里,决策占比最高的恰恰是这300条业务数据的结果。
4.2 评测模型的配置:YAML里每个字段都有讲究
OpenCompass用YAML描述一个评测任务,核心是models和datasets两块。以Qwen2.5-7B-Instruct为例,我的配置是这样的:
models: - type: HuggingFaceCausalLM abbr: qwen2.5-7b-instruct path: /data/models/Qwen2.5-7B-Instruct model_kwargs: device_map: auto trust_remote_code: true tokenizer_kwargs: trust_remote_code: true max_out_len: 1024 batch_size: 8几个字段的实际含义和使用经验:
abbr:这个名称会出现在最终报告里,建议带版本和精度,避免后面量化模型一多就分不清。device_map: auto:在多卡环境下让模型自动分布显存,24G卡跑7B模型单卡足够,14B模型可以自动占用两张卡。max_out_len:最大生成长度。这个参数不是越大越好,几项评测里最长的输出也不过几百token,设置到1024已经够用,设置太大反而拉低并行效率。batch_size:取决于显存和任务。7B模型在4090上设8很稳,14B模型建议降到2到4,否则会出现单卡OOM。
4.3 任务级参数:并发、分片与采样数
跑评测的时候,--max-num-worker这个参数控制并行任务数。它不是越大越好,因为每个worker都会加载一份模型到显存,我4张卡的经验是设3个worker比较稳。如果模型本身已经靠多卡承载,worker设多了反而OOM。
还有一个常见配置是采样数量。部分数据集比较大,比如MMLU有上万条,全量跑会拖很长时间。稳妥做法是先跑默认全量,如果只是想快速对比,可以在模型配置里临时限制样本数量,但最终决策必须以全量结果为准。
4.4 评测命令与产物
配置完成后运行:
python run.py configs/eval_my_models.py也可以把多个模型写在一个配置文件里,OpenCompass会自动逐模型跑。跑完后的产物在outputs/目录下,包含每个模型的summary结果和详细日志。我看结果的习惯是:先看summary表格里的总体准确率,再单独看业务FAQ的细分结果,最后翻一下子任务得分有没有异常波动。如果某个数据集得分和其他模型差距大得离谱,先别急着下结论,去日志里查一下是不是输入数据处理环节出了问题。
5. 量化模型评测:int8/4bit掉点多少、速度提升多少、能不能用
部署和评测任务跑通之后,接下来要解决的是比较现实的问题:我们看上了Qwen2.5-14B的能力,但14B全精度在4090上跑推理比较吃力,单卡显存放不下,多卡并行又增加部署成本。能不能用量化模型?量化的代价究竟是多少?这是标题里“量化模型能力选型”的核心部分。
5.1 量化方案选型:为什么AWQ优先级高于GPTQ和bitsandbytes
目前主流的量化方案大致分三类:GPTQ、AWQ、bitsandbytes。我一开始三个都试了,最后主测AWQ。
- GPTQ:基于二阶海森矩阵做权重误差补偿,量化后模型尺寸小,推理速度也比较快,但中文生成任务上掉点相对明显。
- AWQ:基于激活值分布保留重要权重通道,对低比特量化更友好,实测EasyLLM在中文任务上的掉点比GPTQ略小。
- bitsandbytes的4bit NF4:适合快速加载大模型做实验,但因为反量化开销高,部署时推理速度反而不占优,我只把它当baseline看。
如果业务是英文代码生成或函数级任务,GPTQ也完全可用;如果是中文内容生成、知识问答这类激活值分布更依赖上下文的场景,AWQ掉点更可控。这个结论是基于我这次的量化评测记录,不同模型和量化版本会有差异,但方向可以参考。另外要控制一个变量:同款模型的所有量化版本,必须用同一个评测配置跑,否则量化对比没有意义。
5.2 量化评测的准备:校准集与评测集必须分离
量化本身有个前置步骤:用一批校准数据确定量化参数,这个和评测完全不是一个数据源。这里专门提醒一下,不要拿评测集做量化校准,这是会“泄露未来信息”的典型错误。如果量化模型用评测集校准过,模型的量化参数已经偷偷记住了评测集的分布,分数虚高,等上了线立刻现原形。
我的做法是:从业务FAQ里划出200条做量化校准,剩下的300条做评测。这样量化过程和评测完全隔离,测出来的掉点才是真实部署会遇到的。
5.3 实测数据:量化后的功效和损失
我这次重点评测了这几个模型,得到一份原始记录数据,整理如下。不同版本的模型和评测环境会有些微差异,表中数据当作参考即可。
| 模型 | 精度 | CEval(5-shot) | CMMLU(5-shot) | GSM8K(8-shot) | 业务FAQ(300条) | 推理显存 |
|---|---|---|---|---|---|---|
| Qwen2.5-7B-Instruct | FP16 | 74.6 | 75.2 | 81.3 | 82.7 | ~15GB |
| Qwen2.5-7B-Instruct | AWQ Int4 | 72.5 | 73.4 | 77.9 | 80.0 | ~6GB |
| Qwen2.5-14B-Instruct | FP16 | 87.1 | 87.9 | 87.4 | 89.3 | 多卡 |
| Qwen2.5-14B-Instruct | AWQ Int4 | 85.2 | 86.0 | 84.1 | 87.5 | ~9GB |
| Llama-3.1-8B-Instruct | FP16 | 55.3 | 54.8 | 72.4 | 62.1 | ~16GB |
| Llama-3.1-8B-Instruct | AWQ Int4 | 53.9 | 53.1 | 70.2 | 60.4 | ~7GB |
几个关键结论:
第一,Llama-3.1-8B在中英文综合能力上被Qwen同尺寸明显拉开,尤其中文业务FAQ差了20多个点,在中文场景下基本出局,这印证了只盯着英文榜单选模型的危险性。
第二,Qwen2.5-14B AWQ Int4的CEval只掉了2个点左右,GSM8K掉了3.3个点,推理显存从多卡降到单卡9GB,整体收益非常可观。对一个客服知识库场景来说,90%的场景用AWQ Int4版本就够,而且单卡能部署,成本直接少一半。
第三,量化对英文数学推理类任务(GSM8K)的影响比中文知识类任务更明显,说明推理链路对权重精度更敏感。如果业务是教育辅导或数学题解答,量化时就要更谨慎一些。
5.4 通量测试:光看显存不够,还得看速度
评测平台只给我准确率和显存还不行,选型报告里得回答“线上服务并发多少时延迟多少”。量化模型因为权重变小,内存带宽瓶颈下的decode速度提升也很可观。我在单张4090上用同样长度输入各跑500轮,记录到的decode吞吐大概是这样(同样仅供参考):
- Qwen2.5-14B FP16:23 tokens/s
- Qwen2.5-14B AWQ Int4:41 tokens/s
输入侧速度提升更明显,量化后prefill阶段的计算量大幅下降,首token延迟也缩短了大约35%。这些数据对最终选型的说服力,有时候比准确率还强,因为老板最关心的就是“单卡能不能扛住”。
6. 从评测报告到选型结论:我的决策框架和报告长什么样
跑完一堆分数之后,最重要的问题来了:怎么从评测数据推导出“选哪个模型做底座”?这一步如果纯靠人眼看分数,前面所有严谨的工作就废了。
6.1 设计加权评分表:让业务权重替你做决定
不同业务的“好模型”定义完全不同。我的做法是提前做个加权评分表,把业务最关心的能力映射到评测指标上:
| 能力维度 | 对应评测任务 | 客服+知识库场景权重 | 代码助手场景权重 |
|---|---|---|---|
| 中文理解与知识 | CEval、CMMLU、业务FAQ | 0.35 | 0.15 |
| 指令遵从与内容生成 | 业务FAQ开放式问答 | 0.25 | 0.15 |
| 数学与逻辑推理 | GSM8K | 0.2 | 0.2 |
| 英文综合能力 | MMLU | 0.1 | 0.2 |
| 部署性价比 | 量化后显存/吞吐 | 0.1 | 0.3 |
按这个权重去算,Qwen2.5-14B AWQ Int4在各候选者里的综合分最高,很快收敛。但我要强调,权重表的意义不是算出唯一正确答案,而是逼着团队在评测之前就统一“什么能力更重要”,避免跑完数据后每个组都挑对自己有利的分数说事。
6.2 定性bad case分析:量化模型丢了什么能力
光有总体分数还不够,我把业务FAQ里FP16答对而AWQ Int4答错的case全部抽出来人工看了一遍。结果发现一个规律:掉分主要集中在两类问题,一是需要精读长文本里多个条件才能推理的题,二是领域术语密集的回答。这两类恰好是客服接待中最核心的复杂咨询场景。
这个定性结论比“掉2个点”更关键。它告诉我们,如果业务里大量场景是短问短答,量化版完全没问题;如果线上经常出现长文档问答和复杂条件筛选,那要么保留FP16小模型做复杂查询路由,要么直接接受quantized模型在复杂题上的降级。这个结论最后写进了选型报告的需求备注里。
6.3 选型报告的呈现方式
报告我分了三层:
- 综合评分表:把所有模型的加权总分放一张表,一目了然。
- 关键结论段:用两三句话说清楚“我推荐哪个,为什么”。
- 风险与备注段:写清楚量化掉点集中在什么类型的问题上,以及业务侧需要做什么配合。
报告里我没有堆所有评测日志,而是把完整log压缩包附在附录,方便组内复现校验。要吹一下的是,这份报告发出去之后,之前吵得最凶的同事也没话说,因为他自己用同一份配置复跑了一次,数据完全一致。
7. 实战中踩过的坑:完整排查链路与补救方案
这节把我在整个过程中踩过、并且花了不少时间才绕出去的坑集中写一下,每条都带上排查思路和最终修复方案。
7.1 数据集下载反复失败,卡在hf转移
现象:首次跑CEval时,任务启动十几分钟还在“downloading dataset”,然后直接报连接超时。这个问题排查下来,根因就是网络不稳定。不是代码问题,也不是配置问题。修复方案是前面提过的两步:先把HF_HOME和HF_DATASETS_CACHE指到本地大目录,再在非评测时段用一个独立的Python脚本把数据集预先拉取到缓存。之后跑评测时OpenCompass检测到缓存已经有数据集,就不再走下载流程了。
7.2 “tokenizer_parallelism”冲突导致进程崩溃
现象:评测任务跑到第二个模型时,偶尔会直接报tokenizer_parallelism ... conflict错误。这个坑在网上很多帖子都提到过,本质是多个worker加载tokenizer时并行度参数冲突。排查链路:先看日志里的模型加载栈,发现不是显存不足,而是tokenizer初始化阶段的线程冲突。解决办法也简单,在运行命令前设置环境变量:
export TOKENIZERS_PARALLELISM=false实测这个变量对评测速度几乎没有影响,但进程稳定性明显提升。
7.3 多worker并行OOM,不知道是谁占的显存
现象:设了4个worker跑14B模型,刚启动就OOM,但nvidia-smi看每张卡利用率都很低。这里需要注意,OOM不一定发生在GPU侧,也可能发生在CPU内存的模型加载阶段。OpenCompass多进程并发时,每个worker都有一份模型驻留,4个14B模型同时向显存搬运,很快耗尽。
排查步骤:先看系统free内存,再看每张卡的显存占用,确认是叠加导致的。修复方案有两个,一是把worker数降到2,二是给不同模型配置指定GPU设备,避免俩模型抢同一张卡。实测后者更稳。
7.4 结果和官方榜单不一致,慌了
现象:我跑出的Qwen2.5-7B的CEval分数比官方公布的少了将近2个点,差点以为部署有问题。后来查了一遍,原因是官方榜单用的模型版本、prompt模板、采样参数和我的配置不完全一致。OpenCompass的评测结果可复现,但复现的是“你自己的配置”,不是“官方的配置”。解决办法是如果想对齐官方数据,需要把模型版本锁死,并参考官方评测文档里的参数设置。如果只是内部横向对比,那就保证所有模型都用同一份配置跑,分数自然具备可比性。
7.5 工具类破率最快的问题:模型路径带空格或中文字符
这个坑很低级但很常见。有个同事把模型放在/data/我的模型/试 验/目录下,结果每次启动任务都报路径找不到。排查到最后发现是路径里的空格和中文导致的,OpenCompass在拼接路径时不会做特殊转义。所有模型和数据集的本地目录最好都改成纯英文小写加下划线的命名规范,省掉一堆不必要的麻烦。
7.6 评测跑到一半挂掉的兜底方案
长时间评测任务,最怕的是中途断掉。OpenCompass的日志是持续落盘的,任务中断后已经跑完的部分结果保存在outputs目录里。我后来养成了习惯:跑大任务之前先启动一个tmux会话,所有评测都在tmux里跑,断连也不影响进程。同时定期检查summary日志,如果发现某个数据集的eval已经完成但整个任务卡住,可以直接跳过错过的数据集,不重跑已完成部分。
最后再分享一点个人体会
评测平台本身不难搭,难的是评测任务设计和结果解读。很多团队搭好平台后,第一件事就是急着跑一堆模型、存一堆分数,然后发现分数并不能直接转化为选型结论。真正有价值的是,在搭建和跑分之前花时间想清楚:你的业务到底需要模型的什么能力?你打算用哪些数据集和权重来量化这些能力?量化后的模型如果掉点,掉的是哪些能力点?
从我这次的经历看,最得意的一个决策是提前设计了加权评分表并人工分析了量化掉分case。这两个动作,让大家在拿到报告时不是在争论“我觉得哪个模型好”,而是在讨论“这个能力权重对不对”和“这个掉点场景我们能不能接受”。当讨论话题变成了这样,选型就不再是技术博弈,而是一个相对理性的业务决策了。
另外,如果你们团队以后会频繁评测新模型,建议把这套配置、脚本、数据集缓存、报告模板沉淀成一套内部文档。OpenCompass这类平台可复现性很强,我第一次搭用了大概两天,后面再来一台新机器,照着文档半小时就能复现整个环境。评测这件事,跑一次不难,难的是跑完之后整个团队能高效地用这些结果做决策。把这套流程沉淀下来,后续每次新模型发布、每次新业务需要选型,都能少走很多弯路。