我叫周明远,干了六年嵌入式开发,两年前因为项目需要开始往AI部署方向转。手头最常见的就是各种边缘盒子、工控机,显存从4GB到12GB不等,没有A100,更别提H100。去年年底,公司打算把法律咨询和医疗问诊的两个内部原型推到准生产环境,要求模型必须本地化部署,不能触网——这是合规底线。留给我的硬件是一台带RTX 3060 12GB的工作站,以及未来可能量产的ARM边缘设备。
一开始技术选型只盯着7B、13B模型,但很快发现连推理都吃紧,更别提微调。于是把目光转向SLM(Small Language Model)。当时市面上有几个火热的小模型:Google的Gemma 2(2.6B参数版本)、微软的Phi-3-mini(3.8B参数)以及阿里的Qwen-1.8B。参数小,口碑不错,但在我这一亩三分地里到底哪个真能打,没人能给我确切答案。我没兴趣看跑分榜单,只想算一笔账:每一块钱的GPU投入,能换来多少真实场景下的准确率提升。这篇文章就是我在两周内反复折腾、烧掉近800块云GPU费用后,得出的一份硬核算命。
30秒速览
- - 在RTX 3060 12GB上,Qwen-1.8B全参数和QLoRA均可行,Gemma 2 2B全参数勉强能跑,Phi-3-mini全参数必OOM,只能QLoRA。
- - 综合法律+医疗专家盲评,Gemma 2全参数平均分82.35,QLoRA 79.9;Phi-3 QLoRA 77.85;Qwen QLoRA 75.7。差距集中在事实准确性和安全性。
- - 边际ROI计算显示,从最差方案Qwen QLoRA提升到Gemma QLoRA只多花0.34元,却换来4.2分提升,性价比最高;而Phi-3 QLoRA虽然边际成本极低,但绝对分数天花板低。
- - 生产选型上,低资源设备选Qwen,主流实时场景选Gemma QLoRA,极致准确率且可接受云端考虑Gemma全参数,Phi-3因量化能力损失和硬件挑剔不建议作为首选。
- - 全程6条核心避坑建议,涵盖tokenizer、LoRA合并、chat模板、显存管理、专家评测必要性和数据分布控制。
把2万条专业指令塞进三个小模型:法律/医疗微调数据集构建的真实挑战
垂直领域微调的第一道坎不是模型,而是数据。网上能找到的法律、医疗公开数据集要么过于宽泛,要么只有几千条,根本覆盖不了我们需要的“合同条款解释”“劳动仲裁咨询”“常见病用药问答”等高频场景。我决定自己造,但造数据是个体力活,而且要控制成本。
用大型LLM合成初稿,再用专家抽检清洗
我找了三名有法律背景的实习生和一位退役护士,先花了两天时间梳理出法律领域的12个高频话题和医疗领域的10个常见科别,每个话题/科别拟定50个种子问题。把这些种子问题喂给GPT-4o,让它按照“角色-场景-问题”的格式扩写出500-800条指令,同时生成标准答案。GPT-4o的API费用花了大概20美元,合人民币140多块。但这只是粗胚,幻觉和错误不少。(延伸阅读:放弃8张A100后,我把LLaMA 3 8B预训练成本从$0.12砍到$0.032/百万token——Trainium2迁移调优全记录)
清洗环节我采用了“抽检+回填”的策略:从每个话题下随机抽20条,让领域专家严格批改。结果发现,法律类数据中有约7%的答案存在明显错误(例如引用了废止的法规),医疗类更严峻,大约11%的建议存在安全隐患(如药物剂量不准确)。我们把这些错误修正后,根据错误模式编写了20条fix规则,用脚本批量清洗了整个数据集。最终得到法律指令10052条,医疗指令10012条,共计20064条。每条都包含系统提示(如“你是一位严谨的法律顾问”)、用户输入和标准回答,格式统一成ChatML,方便后续不同模型适配。
评测集的“均衡性”比数量更重要
很多人做微调时评测集就是随机切10%,但这在垂直领域很容易造成评测失真——可能训练集里全是常见病,测试集也全是常见病,模型记性好就能拿高分,一到罕见病就瞎说。我把数据集按“常见/少见”进行了分层抽样:法律类中复杂案例(如涉及多重法律交叠)占比30%,医疗类中罕见病或复杂用药场景占比25%。最终测试集法律、医疗各500条,每条都配有标准答案和专家盲评所需的评分维度说明。整个数据准备耗时5天,人力成本大概2000元,但为后续所有对比打下了一个坚实的评测地基。
我还专门写了一个脚本检查数据泄漏,确保测试集的指令不曾在训练集中出现,甚至检查了相似的指令。这一步救了后面模型评测的可信度。
# 数据分层抽样与格式转换示例
import json
import random
from collections import defaultdict
def load_and_stratify(file_path, domain, rare_ratio=0.3):
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
# 假设数据中有"difficulty"字段,取值"common"或"rare"
common = [item for item in data if item.get('difficulty') == 'common']
rare = [item for item in data if item.get('difficulty') == 'rare']
# 按比例抽取
target_total = 500
rare_count = int(target_total * rare_ratio)
common_count = target_total - rare_count
rare_sample = random.sample(rare, min(rare_count, len(rare)))
common_sample = random.sample(common, min(common_count, len(common)))
test_set = rare_sample + common_sample
random.shuffle(test_set)
# 转为ChatML格式
chatml_examples = []
for ex in test_set:
system_msg = f"你是一位{domain}专家,请准确回答用户问题。"
chatml_examples.append({
"messages": [
{"role": "system", "content": system_msg},
{"role": "user", "content": ex["instruction"]},
{"role": "assistant", "content": ex["output"]}
],
"metadata": {"domain": domain, "difficulty": ex.get("difficulty")}
})
return chatml_examples
law_test = load_and_stratify("law_train.json", "法律", rare_ratio=0.3)
med_test = load_and_stratify("med_train.json", "医疗", rare_ratio=0.25)
with open("final_test.json", "w", encoding='utf-8') as f:
json.dump(law_test + med_test, f, ensure_ascii=False, indent=2)
print(f"评测集生成完成,法律{len(law_test)}条,医疗{len(med_test)}条")
12GB显存上的三个模型博弈:从OOM到勉强跑通的全参数微调手记
我的硬件是RTX 3060 12GB,Ubuntu 22.04,CUDA 12.1,PyTorch 2.1。微调框架选用Hugging Face TRL的SFTTrainer,搭配flash-attn 2。最开始我打算“公平”地给三个模型都做全参数微调,结果第一个模型就给我上了一课。
Qwen-1.8B的全参数微调:显存友好但需要耐心
Qwen-1.8B只有1.8B参数,FP32占7.2GB,在12GB卡上看起来轻松。但训练时激活、优化器状态会占用大量额外显存。我用batch_size=1,max_seq_length=1024,勾选了gradient_checkpointing,实际显存峰值跑到8.2GB,剩余空间绰绰有余。训练法律+医疗混合数据,跑完一个epoch(20064条)耗时3小时27分钟。整个过程稳定无报错,只是生成效果后面才见分晓。
Gemma 2 2.6B:12GB卡在悬崖边上跳舞
Gemma 2 2B实际参数量2.6B,比Qwen大了一圈。同样的训练参数,显存占用直接飙到10.5GB。CUDA内核偶尔报warning,但没崩。为了安全,我不得不把max_seq_length降到768,减少了一些长文本样本。训练一个epoch耗时4小时10分钟。有几次显存瞬间冲到11.8GB,风扇狂转,幸好没OOM。我意识到这已经是这块卡全参数微调的极限了。(延伸阅读:在Jetson Orin上跑LangChain安全护栏:512MB内存预算下,我把注入拦截延迟压到1.8ms)
Phi-3-mini 3.8B:OOM把我逼到角落
Phi-3-mini参数量3.8B,一启动训练就OOM,即使batch_size=1且开启gradient_checkpointing,模型初始化后就已经占用11.2GB,优化器状态一叠加直接爆到12.3GB。尝试降低max_seq_length到512,仍无济于事。想用CPU offload,但SFTTrainer对device_map的配合不完美,我折腾了两个小时还是放弃。这意味着在消费级12GB卡上,Phi-3-mini的全参数微调走不通——除非上多卡或使用更激进的技巧,但那违背了我“有限资源”的设定。这是我踩到的第一个大坑,也直接促使我把QLoRA加入对比方案。
不过,我为了拿到全参数微调的对比数据,还是租了一台云上的V100 32GB(3元/小时),把Phi-3-mini全参数训练跑完了,耗时2小时50分钟。加上Qwen和Gemma的训练时长,全参数阶段我用掉了约10小时本地GPU闲置时间(算电费不计)和3小时云GPU费用9元。
# 使用SFTTrainer进行全参数微调的核心代码(以Qwen-1.8B为例)
from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments
from trl import SFTTrainer
from datasets import load_dataset
import torch
model_id = "Qwen/Qwen-1.8B"
tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)
tokenizer.pad_token = tokenizer.eos_token # Qwen需要设置pad_token
model = AutoModelForCausalLM.from_pretrained(
model_id,
torch_dtype=torch.float16,
trust_remote_code=True,
device_map="auto",
use_cache=False
)
dataset = load_dataset("json", data_files="train_20064.json", split="train")
training_args = TrainingArguments(
output_dir="./qwen_full_finetune",
num_train_epochs=1,
per_device_train_batch_size=1,
gradient_accumulation_steps=4,
gradient_checkpointing=True,
logging_steps=50,
save_steps=500,
learning_rate=2e-5,
bf16=False,
fp16=True,
max_grad_norm=0.3,
warmup_ratio=0.03,
lr_scheduler_type="cosine",
report_to="none",
optim="adamw_torch",
)
trainer = SFTTrainer(
model=model,
args=training_args,
train_dataset=dataset,
tokenizer=tokenizer,
max_seq_length=1024,
formatting_func=lambda x: tokenizer.apply_chat_template(
x["messages"], tokenize=False, add_generation_prompt=False
),
)
trainer.train()
QLoRA的甜蜜与苦涩:4bit微调如何用0.6%精度换回40%显存
全参数微调的结果虽然拿到了,但Phi-3在本地根本没法复现,而且我未来要面对的是ARM边缘设备,模型体积和推理内存占用不能太大。QLoRA是必然要走的路。
显存悬崖消融:三个模型全部降入安全区
我用bitsandbytes的NF4量化,配合LoRA rank=16、alpha=32,在三个模型上实施QloRA微调。结果立竿见影:
- Qwen-1.8B QLoRA:显存从8.2GB暴降到4.6GB,训练一个epoch时间3小时5分钟(比全参数还快了一点,因为运算量减少)。
- Gemma 2 2.6B QLoRA:显存从10.5GB降到5.8GB,训练时间3小时48分钟。
- Phi-3-mini 3.8B QLoRA:显存从无法运行降到7.5GB,训练时间3小时12分钟。终于能在本地12GB卡上训练了!量化虽然引入了一点精度损失,但让我可以把三个模型放在同一块卡上公平对比。
精度折损实测:不是所有模型都适合4bit
训练完成后,我在同样的法律测试集上先跑了一轮Rouge-L和BertScore。结果让我有些意外:Qwen-1.8B全参数微调Rouge-L为0.381,QLoRA版本0.379,仅下降了0.002,几乎无感。Gemma 2全参数Rouge-L 0.412,QLoRA版0.408,下降0.004。而Phi-3-mini全参数Rouge-L 0.405,QLoRA版0.391,下降了0.014——这个差距在后续专家盲评中被放大了,Phi-3在复杂的法律推理上明显不如全参数版本,有时会漏掉关键法条引用。
医疗测试集趋势类似,但Phi-3的退化更明显。后来我分析,Phi-3-mini的权重分布可能对量化更敏感,或者是因为它的全参数版本在V100 32GB上训练时用了更充足的上下文(1024),而QLoRA版本只能妥协到768长度。这提醒我,QLoRA不是无损压缩,对于某些模型架构,4bit确实会吞掉部分能力。(延伸阅读:我们在Optimus Gen-3上刷出了99.2%搬运精度,但仿真到实机的坑烧掉了三台关节电机)
但考虑到现实约束,Phi-3全参数在边缘设备上根本不现实,QLoRA是其唯一的落地路径。我们后面算ROI会把这个“不可部署”的隐性成本也考虑进去。
别只看Rouge——领域专家盲评揭开三个模型的能力断层
Rouge和BertScore是自动化指标,但它们对专业领域的事实正确性、逻辑严密性缺乏判断力。我请了四位同事(两位法律背景,两位医疗背景)进行双盲评测:每个模型在500条测试集上的回答,混合打乱后发给四位专家,按1-5分打分,评分维度包括准确性(权重40%)、完整性(30%)、语言流畅度(20%)、安全性(10%)。最终得分换算成百分制。
法律场景:Gemma 2靠逻辑取胜,Qwen输在法条幻觉
法律测试中,Gemma 2全参数版本得了83.2分,QLoRA版本81.7分,位居第一。专家反馈它能够准确引用《民法典》相关条款,推理链条清晰。Phi-3全参数80.5分,QLoRA只有76.3分,退化明显,主要问题是偶尔混淆司法解释日期。Qwen-1.8B全参数77.1分,QLoRA 76.9分,分数垫底但差距不大。问题出在Qwen倾向于编造案例编号,尤其在复杂劳动仲裁场景中,专家指出“回答看似通顺,但经不起推敲”。这验证了小型模型的知识边界——强行让它输出它不知道的信息,就容易幻觉。
医疗场景:Phi-3的保守策略反而救了它
医疗测试上排名却出现反转。Phi-3 QLoRA以79.4分(全参数81.5分)拿了第一,因为它的回答方式极为谨慎,遇到不确定的用药问题时总是反复强调“请咨询医生”,没有出现危险误判。Gemma 2 QLoRA 78.1分,Qwen-1.8B 74.6分。但是专家在评语中指出,Phi-3这种极度保守的策略虽然安全,但信息量不足,很多时候没有直接回答用户的实际问题,而是绕开了。这在真实产品中可能导致用户满意度下降。Gemma 2在提供有用信息和保持安全之间平衡更好,但偶有剂量建议不够精确的情况。
综合两个领域的平均专家分,我得到了一个更接近真实应用场景的能力排序:Gemma 2 (82.5) > Phi-3 (78.8) > Qwen-1.8B (75.8)。注意,这里的平均分是将法律和医疗等权重合并的。
| 模型+方案 | 法律专家分 | 医疗专家分 | 平均专家分 | Rouge-L | 显存占用 |
|---|---|---|---|---|---|
| Qwen-1.8B全参数 | 77.1 | 74.6 | 75.85 | 0.381 | 8.2 GB |
| Qwen-1.8B QLoRA | 76.9 | 74.5 | 75.70 | 0.379 | 4.6 GB |
| Gemma 2 2B全参数 | 83.2 | 81.5 | 82.35 | 0.412 | 10.5 GB |
| Gemma 2 QLoRA | 81.7 | 78.1 | 79.90 | 0.408 | 5.8 GB |
| Phi-3-mini全参数* | 80.5 | 81.5 | 81.0 | 0.405 | — (V100 32GB) |
| Phi-3-mini QLoRA | 76.3 | 79.4 | 77.85 | 0.391 | 7.5 GB |
*全参数Phi-3仅在云端V100训练,本地无法部署。评测使用云端模型进行对比。
这张表是我后续计算ROI的起点。可以看到,全参数微调普遍优于QLoRA,但差距在0.2到3.1个百分点之间。如果显存和预算充裕,全参数是最佳选择;但12GB环境下只有Qwen和Gemma的全参数方案可行,Phi-3只能上QLoRA。(延伸阅读:用Ollama + LangChain构建本地隐私聊天机器人,30行代码搞定!)
一元的购买力:云GPU时、推理延迟与边际准确率提升的ROI方程式
准确率数字好看不代表性价比高。我要给公司一个清晰的决策依据:花多少钱,能换来多少业务价值的提升?我把所有成本折算成人民币,统一单位。
训练成本核算:本地闲置算力不等于免费
虽然多数训练我在本地RTX 3060上完成,但电费和硬件折旧仍然存在。按机器功率300W(仅显卡满载150W+平台)和每度电0.8元计算,每小时电费0.24元。折旧按机器4年寿命、整机成本8000元算,每小时折旧0.23元。那么本地训练每小时成本约0.47元。而我在云端租的V100 32GB是3元/小时。训练时长和费用如下:
- Qwen-1.8B全参数:3.45小时本地,费用1.62元
- Gemma 2 2B全参数:4.17小时本地,费用1.96元
- Phi-3-mini全参数:2.83小时云V100,费用8.49元
- Qwen QLoRA:3.08小时本地,费用1.45元
- Gemma QLoRA:3.80小时本地,费用1.79元
- Phi-3 QLoRA:3.20小时本地,费用1.50元
数据准备成本摊到每个模型上约333元(2000元人力/6个方案),但这相对固定,不影响选型比较。
推理延迟与部署内存:从RTX 3060到边缘设备的映射
用同一台RTX 3060测试推理性能,使用vLLM 0.4.2引擎,以单并发、prompt长度128 tokens、生成最大200 tokens,测平均首token延迟和总延迟(P50/P99)。结果如下:
- Qwen-1.8B全参数/QLoRA:模型小,首token 180ms,总耗时1.2s,P99在1.6s内
- Gemma 2 QLoRA:首token 220ms,总耗时1.5s,P99 2.1s;全参数版本因显存满载,vLLM需要开启swap导致延迟略高,首token 250ms,总1.7s
- Phi-3 QLoRA:首token 260ms,总1.8s,P99 2.4s;全参数在V100上很快(首token 90ms),但不具备边缘可行性。
对于未来要部署的ARM边缘设备(假设8GB内存),Qwen-1.8B int8量化后仅需1.8GB内存,Gemma 2需要2.6GB,Phi-3需要3.2GB。推理延迟会更高,但目前阶段我们先用RTX 3060的数据做基线。
计算每1%准确率提升的边际成本
这里我定义准确率基点为最弱的方案:Qwen-1.8B QLoRA,平均专家分75.70,训练成本1.45元。然后计算其他方案相对于它的增量成本和增量分数,得出每提升1%专家分平均需要多少钱。结果触目惊心:
- Qwen全参数:成本+0.17元,分数+0.15,边际成本1.13元/1%
- Gemma QLoRA:成本+0.34元,分数+4.20,边际成本0.081元/1% — 性价比极高
- Gemma全参数:成本+0.51元,分数+6.65,边际成本0.077元/1% — 最佳ROI
- Phi-3 QLoRA:成本+0.05元,分数+2.15,边际成本0.023元/1% — 看上去很美,但不能只看这个,因为其绝对分数仍低于Gemma
- Phi-3全参数(云端):成本+7.04元,分数+5.30,边际成本1.33元/1% — 贵且不可部署
如果单纯看钱,Phi-3 QLoRA每1%提升只要2分钱,但它的天花板太低,最终分数只有77.85。而Gemma全参数虽然绝对成本高一点点,却带给你最高的分数82.35,且边际成本极低。如果业务对准确率有硬性要求(比如法律场景不能低于80分),那只有Gemma系列达标,Qwen和Phi-3都出局,这时候ROI计算就简单了——你根本没得选。(延伸阅读:凌晨三点被CFO的成本警报叫醒:大模型推理正在吞噬利润,我用FinOps工具链砍掉了40%账单)
我把推理延迟也转化为成本:假设每次API调用的成本(含服务器折旧)0.002元,每天1万次请求,全年费用7300元。延迟越高,需要的计算资源越多,成本相应增加。粗略折算到“每提升1%准确率且延迟低于2秒”的综合评分,Gemma QLoRA依然是综合最优解。
# 推理性能测试脚本(vLLM)
from vllm import LLM, SamplingParams
import time
model_path = "./gemma2_qlora_merged" # 合并LoRA后的模型路径或原始模型
llm = LLM(model=model_path, max_model_len=1024, gpu_memory_utilization=0.85)
prompts = ["你是一位法律顾问,请解释合同违约的赔偿原则。"] * 100 # 100次重复测试
sampling_params = SamplingParams(temperature=0.1, max_tokens=200, ignore_eos=False)
start = time.time()
outputs = llm.generate(prompts, sampling_params)
elapsed = time.time() - start
latencies = []
for out in outputs:
first_token = out.metrics.first_token_time - out.metrics.arrival_time
total = out.metrics.last_token_time - out.metrics.arrival_time
latencies.append((first_token, total))
first_times = [l[0] for l in latencies]
total_times = [l[1] for l in latencies]
first_times.sort()
total_times.sort()
print(f"P50首Token: {first_times[50]*1000:.0f}ms, P99: {first_times[99]*1000:.0f}ms")
print(f"P50总耗时: {total_times[50]:.2f}s, P99: {total_times[99]:.2f}s")
print(f"吞吐: {100 / elapsed:.2f} requests/s")
面对生产环境,你的选择只有一个:最终推荐矩阵与部署条件
做完上面的功课,结论已经浮现。我根据三种典型的资源预算和延迟约束,制作了一个推荐矩阵。
场景一:预算极度有限,延迟要求宽松(如内部工单系统)
如果你连一块12GB的卡都没有,只能在8GB内存的CPU机器或者超低功耗ARM上跑,而且用户能接受3-5秒的响应时间,那Qwen-1.8B QLoRA是唯一解。模型小,int8量化后不到2GB,CPU推理也能在4秒内完成。虽然准确率垫底,但总比没有好。训练成本1.45元,几乎可以忽略。
场景二:预算中等,实时性要求高(如在线法律咨询)
这是最典型的商业场景。目标P99延迟低于2秒,准确率80分以上。只有Gemma 2 QLoRA能满足:显存5.8GB,可在RTX 3060或同等算力设备上流畅运行,推理P99 2.1s,专家分79.9,经过少量prompt调优后能稳定在80+。训练成本1.79元,加上数据准备分摊也不到400元。Gemma全参数能达到82.35分,但显存要求10.5GB,部署时可能影响并发能力,权衡后我推荐QLoRA版本。
场景三:准确率绝对优先,可以接受云GPU成本(如医疗辅助诊断)
这里“准确率”关乎安全,预算可以放宽。Phi-3全参数在医疗上的安全性最高(保守策略),但显存和推理要求让它只能在云端部署。它的边际成本1.33元/1%远高于Gemma,但如果你已经确定了必须上云,那这个成本差异就不重要了。我更推荐Gemma全参数方案,综合分最高,且可以在多卡环境扩展。
对于我自己的项目,最终选择了Gemma-2B QLoRA版本作为主力,法律和医疗场景都使用。Qwen作为备用的低资源兜底方案,在ARM边缘上跑通。Phi-3被放弃——不是因为能力不行,而是因为它对硬件太挑剔,量化后能力退化又过于明显。
| 约束条件 | 推荐方案 | 一次训练成本 | 部署显存 | 推理P99延迟 | 平均专家分 |
|---|---|---|---|---|---|
| 极低预算+低资源设备 | Qwen-1.8B QLoRA | 1.45元 | 1.8 GB(int8) | 1.6s (RTX3060) | 75.7 |
| 主流实时服务 | Gemma 2 2B QLoRA | 1.79元 | 5.8 GB | 2.1s | 79.9 |
| 准确率严苛+云端部署 | Gemma 2 2B 全参数 | 1.96元(本地) | 10.5 GB | 1.7s | 82.4 |
避坑清单:我在两周里烧掉¥800换来的六条铁律
最后的最后,我把这次折腾中碰到的血泪教训整理成清单。每一条都是用时间和金钱换来的。
1. Phi-3的pad_token坑:不设置就会静默失败
使用Phi-3-mini时,它的tokenizer默认没有pad_token。如果用SFTTrainer不手动设置,训练可能正常进行,但评估时生成句子全是乱码。必须加上tokenizer.pad_token = tokenizer.eos_token,并且在生成时传入pad_token_id。
2. QLoRA的融合顺序:先merge再推理,否则慢一半
很多人用PEFT加载adapter后直接推理,导致每次forward都要计算LoRA的增量,推理速度慢30-50%。正确做法是训练后用model.merge_and_unload()将adapter权重合并到基础模型中,再保存为完整模型。不仅速度提升,还能避免显存中的额外开销。
3. Chat模板不一致,微调直接废掉
三个模型使用了不同的对话模板:Qwen是ChatML风格,Gemma有自己的一套Google格式,Phi-3也是ChatML但细节不同。微调时必须用tokenizer.apply_chat_template统一格式,且在训练数据中保持一致。我一开始没注意,Qwen微调出来后总是生一个不完整的开头,后来才发现是把Gemma模板错喂给了Qwen。
4. 盲目追求全参数微调:12GB上除了OEM还有隐性代价
即使Gemma全参数没OOM,10.5GB的显存占用量意味着你几乎不能同时做其他事情,并发推理时显存碎片也会导致延迟抖动。生产环境中,QLoRA不仅省显存,还提供了更好的稳定性。
5. 指标≠体验,专家盲评的钱不能省
Rouge-L的差距可能只有0.02,但实际用户感知可以天差地别。我这次请专家花了大概1500元劳务费,但直接避免了上线后面临客诉的风险。如果条件有限,至少对关键场景做人工抽检,不要只看自动化分数。
6. 数据量够了,但数据分布才是核心
2万条数据看起来不少,如果全集中在几个高频主题上,模型会“偏科”严重。一定要做主题分布分析,确保评测集和实际请求分布匹配。我当初用GPT-4o合成数据时,就发现它天然倾向生成特定句式,后来通过人工重写20%样本打破了这种模式。
整个项目下来,我最大的感受是:SLM选型没有银弹,只有合不合适。算清楚每一块钱换来的准确率,你就不再迷茫。希望这份硬核账单能帮你在下一个项目里少走弯路。