☰
开源大模型落地选型:8B/70B、显存量化与微调部署实战
2026/10/26 6:47:15 网站建设 项目流程

1. 权重放出来那天,我把手里的选型表撕了重写

做应用落地的人应该都有过这种体验:方案评审到一半,采购流程走到一半,突然某家把旗舰级模型的权重直接扔到公网上了。我那天正在给一个客服质检系统做模型选型,桌面上的对比表格还热乎着,看到消息的第一反应不是兴奋,而是"前面两周的评测白跑了"。但冷静下来之后我发现,这次开源真正值得关注的地方,根本不在"又多了个能下载的模型"这件事上,而在于它把一条原本需要付费、需要走审批、需要担心数据出境的链路,变成了一条本地就能闭环的链路。后面我把整套方案推翻重做,落地的效果比原方案好不少。这篇就把我这段时间踩过的东西、算过的账、翻过的车,完整写一遍,给同样在做落地选型的人做个参考。

先明确一下这篇适合谁看。如果你只是想拿个网页版聊天工具写写周报,那这篇对你价值不大;但如果你正在做这几类事情——企业知识库问答、文档结构化抽取、代码辅助补全、私有化部署的对话中枢,或者单纯想在自己机器上把大模型跑起来做实验——那这篇基本能覆盖你从选型、部署、微调到排障的全部关键环节。我会把参数怎么算、显存怎么估、量化怎么选、微调怎么配这些"文档里只写一半"的东西讲透,也会把我在实际项目里遇到的坑原样摆出来。为了行文方便,后面统一用"L3 系列"来指代这套开源的模型家族,用"某海外头部团队"指代发布方,具体名字大家心里有数就行,重点在方法不在名字。

有一点必须先说在前面:这次开源带来的最大变化,不是模型能力突然拔高了一个代际,而是能力/成本曲线整体向下平移了一段。这句话听起来抽象,翻译成人话就是——原来你需要 70B 级别才能勉强通过的评测项,现在 8B 级别可能就够用了;原来你要租四张卡才能跑的东西,现在两张卡甚至一张卡就能撑住线上流量。这个变化对做预算的人意义极大,因为很多项目不是死在效果上,是死在"效果达标但成本压不下来"上。

1.1 从"能跑"到"能上线",中间隔着三道坎

很多人对开源的想象是"下载下来就能用",实际上从权重文件到线上服务,中间至少有三道坎要过,而且每一道都能让项目延期。

第一道坎是推理效率。原始权重是训练格式,直接加载做自回归生成,吞吐会非常难看。一个不做任何优化的 8B 模型,单卡并发跑十几个请求就开始排队,首 token 延迟飙到两三秒。你必须在部署层做量化、做批处理、做 KV Cache 管理,才能把吞吐拉到可用区间。

第二道坎是效果对齐。基础模型只会续写,不会听话。你问它"帮我总结这段合同的风险点",它可能给你续一段合同文本。所以你需要的是经过指令微调的那一版权重,而且还要针对自己的业务场景做领域适配。

第三道坎是可观测与可回归。上线之后你会发现模型行为会漂移——不是权重变了,是输入分布变了。用户开始问一些你训练集里根本没有的问题,输出质量就会断崖式下跌。没有一套评测集和监控指标,你根本不知道自己什么时候开始变差。

这三道坎我在不同项目里都栽过。最典型的一次是给某公司的内部工单系统做自动分类,模型在测试集上准确率 91%,上线一周掉到 78%。排查了半天发现是新业务线接入后出现了一批全新的话术,模型没见过,全部分到了错误类目。后来补了在线采样 + 每周增量微调的机制才稳住。这件事让我彻底改变了对"上线"的定义:能返回结果不叫上线,能持续返回正确结果才叫上线。

1.2 这次升级里最容易被忽略的三个技术点

大家都在讨论参数量和榜单分数,但真正影响落地体验的其实是几个不起眼的工程改动。

词表扩容。这次词表从三万多扩到了十二万八千,翻了四倍。很多人觉得这只是支持更多语种,其实对中文场景的收益非常直接——同样一段中文文本,编码后的 token 数量明显减少,意味着同样长度的上下文窗口能塞进更多实际内容,也意味着推理时的计算量下降。我实测过同一份两万字的技术文档,旧词表要切到一万八千多个 token,新词表大概一万二到一万三,省下来的那部分就是实打实的显存和延迟。这一点在长文档处理场景里影响巨大,做合同审阅、财报分析的同学要特别注意。

分组查询注意力的进一步收敛。注意力头的分组方式做了调整,KV Cache 的显存占用进一步压缩。这个改动的意义在于,长上下文场景下的显存压力从"必须多卡"降到"单卡也能试试"。KV Cache 的显存估算公式大致是:2 × 层数 × 序列长度 × 分组数 × 头维度 × 精度字节数,分组数越小,缓存越省。原来跑 8K 上下文就吃紧的卡,现在跑 8K 基本能留出余量给并发。

训练数据规模与配比的调整。这一版的训练 token 量级比上一代提升了一个数量级,其中相当比例是非英文语料。对中文用户来说直观感受就是:不需要额外做大量的中文继续预训练,直接上手指令微调就能有不错的效果。我对比过某次任务里两代模型的中文指令遵循表现,新一代表现明显更稳定,尤其是在"按照指定格式输出"这类约束性任务上,格式错误率下降得很明显。

提示:这三个点里,词表变化对成本的直接影响最大,做长文本业务的同学建议先自己实测一遍 token 数变化,不要直接沿用历史估算。

1.3 谁该立刻动手,谁可以再等等

不是所有人都需要第一时间切过来。我给一个比较实用的判断标准。

建议立刻动手的:已经在做私有化部署、数据不能出门的场景;对长上下文有强需求、被 token 数量卡脖子的场景;正在用上一代开源模型做微调、效果遇到瓶颈的团队;需要做大量离线批量推理、对单次推理成本极度敏感的场景。这几类场景的收益是立竿见影的。

可以再观察一阵的:已经基于闭源 API 把产品跑通、且调用量不大的小团队;对延迟极度敏感、必须走边缘设备且在跑的旧硬件规格很低的场景;以及那种"模型换不换其实用户感知不到"的后台任务。这几类换模型的收益不足以覆盖迁移成本,等生态工具链再成熟一两个月更划算。

我见过最不划算的一种决策,是为了"用上新模型"而把整个技术栈推倒重来。模型是流水线里的一个零件,不是流水线本身。真要动手,先做小范围灰度,用同一套评测集跑A/B,数据说话比追热点靠谱得多。

2. 选 8B 还是 70B,这本质是一道算术题

每次开源模型发布,群里最热闹的话题永远是"你跑起来了吗",但真正决定项目成败的是"你算清楚账了吗"。参数量选错,后面所有的部署方案、微调策略、成本模型全部要重来。这一节我把选型的算法完整拆开,你照着套就能得出自己场景下的答案。

2.1 显存估算:把公式摊开算一遍

先讲一个最常被问的问题:跑某个尺寸的模型到底需要多少显存。很多人以为看参数量就行,实际上要分三种情况算,差得很远。

推理场景(FP16/BF16 原始精度),粗略公式是:显存 ≈ 参数量 × 精度字节数 × 1.2。那个 1.2 是留给激活值、中间张量和框架开销的余量,实际上下限可以到 1.1,上限能到 1.5,取决于上下文长度和批大小。按这个公式,8B 模型大约需要 16GB 出头,70B 模型大约需要 140GB 上下。这意味着 8B 一张 24GB 的消费级卡就能跑得挺舒服,70B 至少需要两张 80GB 的卡。

推理场景(量化后)。4bit 量化下,权重的显存占用约为参数量 × 0.5字节,再加上量化带来的反量化开销。8B 大约 5-6GB 权重,70B 大约 40GB 上下。这就是为什么大家都在喊量化——它把硬件门槛直接砍掉了三分之二。

微调场景。这是最容易翻车的地方。全参数微调的显存需求大概是推理的 4 到 6 倍,因为要存优化器状态、梯度、激活值。70B 的全参微调基本不是个人能碰的规模。所以实际做业务基本都是 LoRA 或 QLoRA,后者把基座模型量化到 4bit 后再挂低秩适配器,8B 模型在单张 24GB 卡上可以做,70B 大概需要两张 48GB 或四张 24GB。

我给出一个更细的对照表,方便你直接对号入座:

场景模型规模精度/方案权重显存建议硬件备注
本地实验8BBF16约 16GB单卡 24GB上下文 4K 以内
本地实验8B4bit 量化约 6GB单卡 12GB 可试质量有轻微损失
线上服务8BBF16 + 批处理16GB + KV单卡 48GB并发 16-32
线上服务70B4bit 量化约 40GB双卡 48GB 或单卡 80GB并发控制在 8 以内
微调8BQLoRA约 12-14GB单卡 24GB数据量万级以内
微调70BQLoRA约 50-60GB双卡 48GB需要梯度检查点
全参微调8BBF16约 80GB+多卡一般不建议个人操作

这张表里的数字是我在几套不同硬件上实测出来的经验值,会比理论公式略保守一点,因为实际运行时要留余量给框架本身和突发流量。如果你按理论最小值去配卡,大概率会在压力测试那天翻车。

2.2 效果差距到底值不值那个成本差

这是选型时最核心的决策点。70B 比 8B 强多少?答案取决于任务类型,而且差距远没有参数量差距(接近 9 倍)那么大。

我整理了一组自己实测的感受性结论,不同任务类型的表现差异如下:

任务类型8B 表现70B 表现推荐选择
文本分类、情感判定够用,准确率接近略好8B
结构化抽取(JSON 输出)需要严格约束,偶有格式错误格式稳定性明显更好看数据量,量大选 8B + 约束解码
长文档摘要长文容易丢细节明显更完整70B
多轮复杂对话容易忘记早期约束稳定性更好70B
代码补全简单片段够用复杂逻辑更强按需
数学与逻辑推理多步推理易断链优势明显70B

关键判断是:如果你的任务能用规则 + 小模型 + 约束解码解决,就别上大模型。我在一个发票信息抽取的项目里就吃过这个亏——一开始用 70B 追求"一步到位",单张发票推理成本是后来的三倍多,延迟还顶不住。后来改成 8B + JSON Schema 约束解码 + 少量规则后处理,准确率反而涨了,因为约束解码把格式错误这个最大的错误源给掐掉了。

2.3 三个绕不过去的硬约束

除了成本和效果,选型还有三个经常被忽略但足以一票否决的约束。

延迟约束。8B 模型在单卡上的首 token 延迟大概在 200-400ms 区间,70B 通常在 800ms 以上,量化后能压到 500ms 左右。如果你的产品是实时补全类的(比如输入法、代码编辑器内联提示),超过 500ms 用户就能明显感到卡顿。这类场景基本没得选,只能往小模型 + 量化 + 更激进的批处理策略上走。

显存碎片约束。这个特别隐蔽。长时间运行的服务,显存会因为请求长度不一致产生碎片,跑着跑着就 OOM。解决办法是限制最大序列长度、对请求做长度分桶、给 KV Cache 预分配固定块。我在一个项目里就是因为没做分桶,服务跑两天必挂一次,日志里全是显存分配失败。

并发约束。并发不是线性叠加的。8B 模型在单卡上跑 32 并发可能还稳,跑到 64 就开始排队;70B 在双卡上跑 8 并发是舒服区,跑 16 延迟就翻倍。做容量规划时,一定要做压测,把"最大稳定并发"这个数字测出来,而不是拍脑袋。

注意:所有容量规划都必须在你自己的真实数据分布下做压测,公开的 benchmark 数字只能用来做初筛,不能用来做决策。

3. 从零把服务跑起来:环境、量化与并发调优

理论算完,接下来是动手环节。这一节我按实际操作顺序走一遍,把每一步的意图和易错点都标出来。假设你的机器是一张 24GB 显存的卡,想先把 8B 模型跑起来验证效果。

3.1 环境准备:先解决依赖地狱

第一步永远是环境。这一步耗时最长,也最容易让人放弃。我建议用容器化的方式来做隔离,不要在宿主机上直接装,否则不同框架的 CUDA 版本冲突能折腾你一整天。

核心依赖就三样:显卡驱动、CUDA 运行时、推理框架。驱动版本决定了你能用哪个版本的 CUDA,CUDA 版本决定了你能装哪个版本的推理框架,这个链条是单向的,从下往上卡。所以第一件事是确认驱动版本,命令很简单:

nvidia-smi

看右上角那个 CUDA Version,它表示驱动支持的最高 CUDA 版本。如果显示 12.1,那你装 12.1 及以下的运行时都不会有问题。

然后建一个干净的 Python 环境。我习惯用 conda,因为依赖隔离做得比较彻底:

conda create -n llm-test python=3.10 -y conda activate llm-test

选 Python 3.10 是有理由的,3.9 太老有些新库不兼容,3.12 太新有些编译型依赖还没跟上预编译包,3.10 和 3.11 是目前最稳的区间。

接下来装推理框架。这里我不指定具体包名,因为生态变化很快,你去框架的官方仓库看最新安装命令更靠谱。但有几个通用原则值得记:优先装带预编译 wheel 的版本,源码编译在你没有完整工具链的机器上会花掉一两个小时;先装 PyTorch 再装推理框架,让推理框架去适配已有的 torch,而不是反过来;装完立刻验证,跑一行import加打印版本号,确认没有 CUDA 版本不匹配的警告。

# 通用验证思路(伪代码) import torch print(torch.__version__, torch.cuda.is_available(), torch.cuda.device_count())

如果is_available()返回 False,别急着往下走,先解决这个。九成的原因是 CUDA 版本和 torch 编译版本对不上,重新装一次对应版本就行。

3.2 首次加载:先把最小可用路径跑通

环境好了之后,别一上来看复杂配置。先用最小配置把模型加载起来,生成一句话,确认整条链路是通的。这个"最小可用路径"非常重要,因为它把变量降到最少——只有模型加载和生成两件事,出问题好定位。

加载时有两个参数必须显式指定,不要用默认值:一个是精度类型,一个是设备映射。精度用 bfloat16 优先,比 float16 数值更稳定,不容易出现 NaN;设备映射设为自动,让框架自己把层分配到可用显卡上,多卡场景尤其重要。

# 加载与生成的通用写法(参数含义通用,框架名按你的环境替换) model = AutoModelForCausalLM.from_pretrained( model_path, torch_dtype="bfloat16", device_map="auto", low_cpu_mem_usage=True, ) tokenizer = AutoTokenizer.from_pretrained(model_path)

low_cpu_mem_usage=True这个参数很多人不加,它能让加载过程先读权重元信息再分配内存,避免加载时内存峰值翻倍。对于内存不宽裕的机器,这个参数是救命用的。

然后做一次生成,重点看三件事:能不能出结果、首 token 延迟多少、显存占用多少。

inputs = tokenizer("用三句话解释什么是向量数据库", return_tensors="pt").to("cuda") outputs = model.generate(**inputs, max_new_tokens=200, do_sample=False) print(tokenizer.decode(outputs[0], skip_special_tokens=True))

do_sample=False是贪心解码,用来测试时最合适,因为结果是确定的,方便对比。上线时再换成采样。

这里有个细节值得说:一定要看 token 数量,不要看字数。很多人估算成本时按字数算,误差能到一倍以上。中文在不同词表下切分差异很大,同一句话可能是 20 个 token 也可能是 40 个。我建议写个小工具,批量统计你的真实业务文本的 token 分布,取 P95 值来做容量规划,比取平均值靠谱得多。

3.3 量化方案怎么选:一张表说清楚

显存不够就必须量化。但量化不是无脑选最低位宽,不同方案的质量损失和速度收益差别很大。

方案位宽显存节省质量损失适用场景
BF16 原始16bit无无显存充足,追求极致效果
8bit 量化8bit约 50%极小,多数任务无感显存中等,通用场景首选
4bit(分组量化)4bit约 70%轻微,长文本和推理任务有感知显存紧张,分类抽取类可接受
4bit(激活也量化)4bit约 75%比上一种更明显极限压缩,实验性质

我的经验判断是:8bit 是甜点区。它在显存和质量之间取得了很好的平衡,大部分业务场景下和原始精度的输出差异小到评测集都测不出来。4bit 在纯生成类任务(摘要、改写、闲聊)上表现也不错,但在需要精确输出的任务(数字抽取、代码生成、多步推理)上会出现明显退化。

有个技巧可以缓解 4bit 的质量损失:只量化一部分层。通常注意力层和 MLP 层的敏感度不同,把敏感度低的那部分量化得更狠,保留敏感层的高精度,能在显存和效果之间找到更好的平衡点。不过这个需要做消融实验,不是开箱即用的配置。

还有一个坑要提醒:量化后的模型,推理速度不一定更快。因为量化节省的是显存带宽,但反量化本身有计算开销。在小 batch 场景下,4bit 可能比 BF16 还慢;只有在大 batch、显存带宽成为瓶颈时,量化的速度优势才体现出来。我见过有人为了"提速"去量化,结果延迟反而涨了,白折腾。

3.4 服务化:批处理才是吞吐的关键

模型能跑通只是第一步,要支撑线上流量,核心是批处理。原理很简单:GPU 是并行设备,一次处理一个请求和一次处理八个请求,时间差不了太多,但吞吐差了八倍。所以推理服务的核心优化就是把同一时刻到达的请求攒成一个批次一起算。

这里有个矛盾:攒批会增加等待时间,降低延迟。所以实际系统用的是"连续批处理"——不等所有请求到齐,谁先算完谁先走,新请求随时插入。这个机制在高吞吐框架里是默认实现的,你要做的就是配置对参数。

关键参数有三个:最大批大小、最大序列长度、显存利用率上限。

最大批大小决定了吞吐上限,但也决定了显存峰值。经验值是先从 16 开始,逐步往上加直到显存占用到 85% 左右。不要贪心设到 64,一旦某个长请求进来,显存直接爆掉。

最大序列长度这个参数一定要按业务实际设置。默认值往往是模型的训练上下文长度,可能是 8K 甚至更长,但你实际业务可能只用到 2K。设成 2K 能让 KV Cache 预分配少四分之三,这些省下来的显存全都能换成并发。

显存利用率上限这个参数,默认通常是 0.9,意思是允许框架占用 90% 的显存。建议调到 0.85 留点余量,因为显存碎片和运行时临时分配需要空间。这个数字调高一点吞吐会好,但稳定性会差,生产环境我一般设 0.85。

# 服务启动的参数思路(具体命令按你用的框架查文档) # --max-model-len 4096 按业务实际需要设置 # --gpu-memory-utilization 0.85 留出碎片余量 # --max-num-seqs 32 逐步试探出来的稳定并发 # --dtype bfloat16 精度优先 # --enable-prefix-caching 相同前缀的请求复用缓存,对系统提示词场景收益巨大

最后那个前缀缓存值得单独说。如果你的业务里所有请求都带同一段很长的系统提示词(比如角色设定、输出格式要求),开启前缀缓存能让这部分计算只做一次,后续请求直接复用。我在一个项目里靠着这个把首 token 延迟从 900ms 压到 300ms,收益比换硬件还大。

提示:压测不要用固定长度的测试脚本。真实流量是长短混合的,用固定长度压出来的并发上限,上线后一定撑不住。建议按真实数据的长度分布生成压测请求。

4. 微调:把通用模型变成"你的模型"

部署跑通之后,下一步绕不开的就是微调。通用模型在通用任务上表现不错,但一旦进入具体业务,问题就来了:术语不认识、格式不听话、语气不对味。这一节讲我实际做微调的流程和踩过的坑。

4.1 数据质量的重要性远超你的想象

先给一个可能有点反直觉的结论:微调效果的上限,几乎完全由数据质量决定,和数据量关系不大。我在一个法律文书摘要的项目里做过对比,500 条精标数据的微调效果,明显好于 5000 条机器粗标数据。原因很朴素——粗标数据里的噪声会被模型原样学过去,包括错误的格式、错误的术语和错误的推理路径。

所以数据准备阶段的投入应该占整个项目的一半以上。我通常按这个流程走:

第一步,定义输出规范。不要指望模型自己领悟你要什么格式,把输出格式写成明确的模板,包含字段名、字段顺序、空值怎么表示、多值怎么分隔。这个规范确定之后就不要改,改了数据要重标。

第二步,构造指令-输入-输出三元组。指令要写成多样化的表达,同一个任务至少准备 20 种不同的问法,否则模型会过拟合到某一种特定句式。输入用真实业务数据,不要用人工编造的"理想样本",因为模型要适应的是真实分布。

第三步,分层抽样做质量校验。从标注数据里随机抽 10%,人工逐条核对。如果错误率超过 5%,说明标注规范有歧义,回头改规范重标,不要带着噪声往下走。

第四步,划分训练集、验证集、测试集。比例大概是 8:1:1,但关键是要按业务维度分层,不能随机切。比如做多类目分类,每个类目在三个集合里的比例要一致,否则测试集上会出现某些类目完全没见过的尴尬情况。

一个特别容易忽略的点:要准备一定比例的"拒答"样本。业务场景里总有一些问题模型不应该回答(越界的、信息不足的、需要转人工的),如果训练集里全是正常问答,模型会强行给出一个看起来很自信的错误答案。加几百条"信息不足,建议转人工"的样本,能大幅降低这类幻觉。

4.2 LoRA 微调:参数怎么配才有意义

确定做微调之后,首选方案基本是 LoRA 或 QLoRA,因为成本可控、迭代快、可以同时挂多个适配器做A/B。核心参数就四个,但每个都有讲究。

秩(rank)。这个参数控制适配器的表达能力。设太小,模型学不动复杂任务;设太大,参数量暴涨且容易过拟合。经验值:简单任务(分类、格式转换)用 8 到 16;中等复杂度(摘要、改写)用 32;复杂任务(多步推理、领域知识注入)用 64 到 128。我的默认选择是 32,绝大多数场景够用。

缩放系数(alpha)。一般设成秩的两倍是常见做法,也有设成秩本身的。这个系数影响适配器输出在总输出里的权重。设得太大,训练容易不稳定;设得太小,适配器学不到东西。我一般用 alpha = 2 × rank,然后根据 loss 曲线微调。

学习率。LoRA 的学习率比全参微调可以大一些,常见区间是 1e-4 到 3e-4。太大 loss 会震荡甚至发散,太小会训到一半就平了。建议先跑 100 步看 loss 曲线,如果下降得太平缓就调大,如果上下跳动就调小。

目标模块。这个参数决定把适配器挂在哪些层上。只挂注意力的查询和值投影是最省的,效果也还行;挂上全部线性层(包括 MLP 的升维降维)效果更好但参数更多。我在大部分业务里用"全部线性层"这个配置,因为效果好,而且参数增加量在可接受范围。

# LoRA 配置的核心参数(框架通用概念) lora_config = { "r": 32, # 秩 "lora_alpha": 64, # 缩放系数,一般为 r 的 2 倍 "lora_dropout": 0.05, # 防过拟合,小数据集建议 0.1 "target_modules": ["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"], "task_type": "CAUSAL_LM", }

训练参数上,批大小受显存限制时用梯度累积来等效放大,比如单卡只能跑 batch=2,累积 8 步等效 batch=16。梯度检查点一定要开,它用重算换显存,能省下 60% 以上的激活值显存,代价是训练速度慢 20% 左右,很划算。

4.3 训练过程监控:看什么指标

训练过程中最忌讳的就是"跑完了才看结果"。我一般在训练循环里挂三个监控点。

训练 loss 曲线。正常形态是先快速下降然后缓慢收敛。如果一开始就平得离谱,大概率是学习率太小或者数据格式有问题;如果震荡剧烈,学习率太大;如果下降到某个点突然反弹,训练数据里有异常样本。

验证集 loss。这个是最重要的早停依据。训练 loss 一直降但验证 loss 开始升,就是过拟合的信号,立刻停。我一般设成每 50 步评估一次,连续 3 次验证 loss 不降就停。

生成样本抽样。每隔一段时间用手写的几个测试问题跑一遍推理,肉眼看输出质量。指标只是一方面,很多时候模型 loss 很好看但输出开始出现奇怪的重复或者格式混乱,这个只能靠眼睛发现。

我在一个项目里就吃过这个亏:只看 loss 觉得一切正常,训了三个 epoch,导出模型一测,输出全是重复的短语。回看数据发现训练集里有几百条样本的标签本身就是重复文本(标注工具出了bug)。如果中途抽样看过输出,两小时就能发现。

4.4 评测:别用感觉判断,建一套回归集

微调完必须要量化评测,不能凭感觉说"好像好一点了"。我建议建三层评测。

第一层是自动指标。分类任务看准确率和混淆矩阵,抽取任务看字段级的精确率和召回率,生成任务看词汇重叠度和语义相似度。这些指标能覆盖大部分情况。

第二层是用另一个模型打分。让一个更强的模型(或者同一模型但用不同的提示词)给输出打分,评判准确性、完整性、格式合规性。这层的成本低、覆盖面广,适合做大规模回归。但要注意打分模型自己有偏好,标准要在提示词里定义得非常明确。

第三层是人工抽检。每次迭代抽 50 到 100 条人工看,重点看那些自动指标判断不了的方面:语气、专业性、有没有编造。这层成本最高但最不可替代。

三层结合起来,能形成一个比较可靠的判断。我建议把这三层固化成一个回归脚本,每次改模型、改提示词、改后处理逻辑都跑一遍,记录分数变化。没有这套东西,你的迭代就是盲人摸象。

注意:评测集要定期更新,从线上真实流量里采样补充。用一年前的测试集评测今天的模型,结论是没有意义的,因为用户的问题分布早就变了。

5. 踩坑实录:那些文档里不会写的问题

这一节是这篇文章我觉得最有价值的部分。前面讲的是"应该怎么做",这里讲"实际会怎么坏"。下面这些问题我在不同项目里全部真实遇到过,排查过程也完整记录。

5.1 模型输出异常的四条排查路径

遇到输出不对,先别急着改代码,按下面的顺序排查,能省掉大量时间。

路径一:先确认输入对不对。九成的"模型胡说八道",根源是提示词被截断了或者模板拼接出错。特别是用了对话模板的时候,特殊 token 的拼接位置错一个,模型行为就完全变了。建议把最终送进模型的完整 token 序列打印出来,前几个和最后几个 token 一定要肉眼确认。

路径二:确认采样参数。温度设成 1.5 会让模型非常发散,top_p 设成 1.0 又没有温度控制的话输出会很不稳定。生产环境我一般用 temperature=0.1 到 0.3,top_p=0.9,需要确定性输出时直接贪心解码。这几个参数的影响比换模型还大,值得花时间调。

路径三:确认上下文长度。超出上下文窗口的部分会被静默截断(有些框架会报错,有些直接截),如果你把重要指令放在最前面,长对话几轮之后就被挤掉了。解决办法是把关键约束放在系统提示词里并在每轮重复,或者用支持更长窗口的配置。

路径四:确认量化损失。如果最近做了量化,把量化关掉对比一下,能快速定位是不是量化导致的退化。我遇到过一次 4bit 量化后模型开始大量输出重复内容,换回 8bit 就正常了。

5.2 常见问题速查表

现象可能原因排查方法解决方向
首 token 极慢(>3s)批处理未开启、前缀缓存未启用看框架的调度日志开启连续批处理与前缀缓存
输出大量重复温度过低、重复惩罚缺失、量化损失调高温度对比加重复惩罚,提升量化精度
跑一段时间 OOM显存碎片、长请求突发记录请求长度分布限制最大长度、长度分桶
中文输出夹杂英文系统提示词语言不一致、训练数据偏英文检查提示词语言提示词统一中文,微调补中文数据
格式不遵守提示词约束不够、缺少约束解码手动测试边界输入用结构化输出约束解码
微调后通用能力下降灾难性遗忘、数据分布过窄跑通用评测集对比混入通用数据、降低学习率
多卡推理速度还不如单卡通信开销大于并行收益对比单卡与多卡吞吐小模型用单卡,或改用张量并行
服务延迟随并发线性上升排队、KV Cache 不足压测看队列长度扩容或降低最大序列长度

这张表建议直接存下来,出问题先扫一遍,能跳过很多无效排查。

5.3 几条我认为最值钱的经验

第一条:先把评测集建起来,再动模型。这是我最想强调的一点。我见过太多团队是先换模型再想办法评估,结果就是"感觉好了"、"感觉差了",永远说不清。正确的顺序是先花两天时间把 200 条带标准答案的测试样本整理出来,再去折腾模型。这 200 条样本会成为你后面所有决策的依据。

第二条:不要一次性换掉所有变量。换模型、换量化方案、换提示词、换解码参数,一次只动一个,然后跑评测。同时动两个,出了问题你根本不知道是哪个导致的。这条听起来是常识,但实际做的时候特别容易犯。

第三条:给你的服务加输入长度分布监控。这个指标能提前预警很多问题。如果某天 P99 长度突然翻倍,说明有用户开始传长文档了,你的显存规划可能撑不住。我靠这个指标提前发现过三次容量问题。

第四条:微调不要追求一步到位。先做一轮最小可行微调(几百条数据、低秩、一个 epoch),把整条链路跑通,看效果提升多少,再决定要不要加大投入。很多人一上来就准备上万条数据、训三个 epoch,结果发现自己连数据格式都搞错了,白等一天。

第五条:留出降级方案。线上服务一定要有兜底——模型超时了走规则、模型不可用了走缓存、输出质量不达标了转人工。我经历过一次显存泄漏导致服务全挂,因为没有任何降级机制,业务停了两个小时。从那以后所有项目我都会加一层兜底逻辑。

第六条:把配置写进版本控制。模型版本、量化方案、推理框架版本、启动参数、提示词模板,全部要能追溯。出问题时第一件事是确认"上次能跑的时候这些参数是什么",没有版本控制你就只能靠记忆。

最后分享一个我最近的小习惯:每次做重大选型决策前,先花半天时间写一份"决策记录",把当时的备选方案、评测数据、选择理由和预期风险都写下来。过三个月回头看,这份记录能帮你判断当初的决策是对是错,也能帮新加入的同事快速理解来龙去脉。这个习惯不花什么成本,但长期收益比任何一次技术选型都大。技术迭代太快了,模型半年一换,工具链一年一变,真正沉淀下来的是判断力和方法论,而不是某个具体的参数配置。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询