微调完 DeepSeek 模型后,领导问你:"新模型比旧模型好在哪里?"
如果你只回答"Loss 下降了 0.1",那大概率是过不了关的。Loss 只能反映拟合程度,不能反映生成质量。对于生成式 AI,我们需要构建一套多维度的评估体系,从自动化指标到人工盲测,全方位衡量模型的"智商"。
1. 自动化指标:快速筛选的"初试"
传统的 NLP 指标在生成式任务面前显得力不从心,但它们仍然是快速回归测试的基石。
1.1 词汇重叠度(Lexical Overlap)
- BLEU / ROUGE:比较生成文本和参考文本的 n-gram 重合度。
- 局限:模型回答"我不仅喜欢苹果,还喜欢香蕉"和"我不喜欢苹果,喜欢香蕉",BLEU 分可能很高,但语义完全相反。
- 适用:翻译、摘要等有标准答案的任务。
1.2 语义相似度(Semantic Similarity)
为了解决 BLEU 的缺陷,我们可以使用基于 Embedding 的指标,如 BERTScore 或 MoverScore。
- 原理:将模型生成结果和参考答案都映射为向量,计算余弦相似度。
- 优势:对同义词替换、语序变换具有鲁棒性。
1.3 任务特定指标
- 代码生成 :Pass@k。生成 k 个代码片段,只要有一个能通过单元测试就算成功。
- 数学逻辑 :Exact Match (EM)。答案数值是否完全一致。
2. LLM-as-a-Judge:用魔法打败魔法
既然人工评估太慢,传统指标太蠢,不如让更强的模型来做裁判。这就是 LLM-as-a-Judge 模式。通常使用 GPT-4 或 DeepSeek-V3(老师傅)来评估微调后的 DeepSeek-7B(徒弟)。
2.1 评估 Prompt 模板
python
JUDGE_PROMPT = """
你是一个公正的评判者。
【问题】:{question}
【参考答案】:{reference}
【模型A回答】:{answer_a}
【模型B回答】:{answer_b}
请对比模型A和模型B的回答,从以下维度进行打分(1-10分):
1. 准确性:事实是否正确。
2. 完整性:是否覆盖了问题的核心点。
3. 逻辑性:推理过程是否严密。
最后输出胜出者(A/B/Tie)及理由。
格式:{"winner": "A", "reason": "..."}
"""
这种方法与人类评估的一致性通常能达到 80% 以上,且成本极低,可以实现 CI/CD(持续集成) 中的自动化测试。
2.2 偏见缓解(Bias Mitigation)
LLM 裁判通常存在 位置偏见(Position Bias),倾向于给排在前面的答案高分。
- 解决方案 :Swap Test。将 A 和 B 的位置互换,再跑一次。只有两次结果一致,才算有效判决。
3. 人工评估(Human Eval):最后的防线
无论自动化指标多好看,上线前必须过人这一关。但人工评估不能随性,必须标准化。
3.1 SBS(Side-by-Side)盲测
开发一个简单的 Web 打分界面。
- 机制:左边显示模型 A,右边显示模型 B(随机打乱,隐去名字)。
- 标注员:最好是业务专家(如医生、律师),而非外包团队。
- 选项:A更好、B更好、平局、都烂。
3.2 Elo 积分系统
参考像国际象棋一样的排位机制。让不同版本的模型互相对战(通过人工 SBS 或 LLM Judge),计算 Elo 积分。
- 优势:可以直观地看到模型能力的演变趋势。如果 V2 版本的积分比 V1 低,绝对不能上线。
3.3 一致性检验(Cohen's Kappa)
不同的人对同一个回答可能有不同看法。我们需要计算 Inter-annotator Agreement (IAA)。如果 Kappa 值低于 0.6,说明评估标准模糊,需要重新培训标注员。
4. 评估集构建与 MLOps 集成
4.1 黄金测试集(Golden Set)
千万不要用训练集来评估!这是作弊。
- Hold-out Set:从原始数据中切分出的 20% 不参与训练的数据。
- Bad Case Set:收集线上用户的投诉和差评 Case,作为重点回归测试题。每次模型迭代,必须通过这些"错题本"的考核。
4.2 Python 评估脚本示例
python
import json
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
# 假设我们有一个 Embedding 模型 wrapper
from my_model import EmbeddingModel, LLMJudge
class ModelEvaluator:
def __init__(self):
self.embed_model = EmbeddingModel()
self.judge = LLMJudge()
def compute_bert_score(self, pred, ref):
"""计算语义相似度"""
vec_pred = self.embed_model.encode(pred)
vec_ref = self.embed_model.encode(ref)
return cosine_similarity([vec_pred], [vec_ref])[0][0]
def run_golden_set(self, model, golden_file):
"""运行黄金集测试"""
with open(golden_file) as f:
data = json.load(f)
scores = []
wins = 0
for item in data:
pred = model.generate(item['question'])
# 1. 自动化指标
sem_score = self.compute_bert_score(pred, item['reference'])
scores.append(sem_score)
# 2. LLM 裁判
judge_res = self.judge.evaluate(item['question'], pred, item['reference'])
if judge_res['score'] > 7:
wins += 1
print(f"Avg Semantic Score: {np.mean(scores):.4f}")
print(f"Win Rate (>7/10): {wins/len(data):.2%}")
5. 总结:质量与速度的权衡
在 2.10 压力测试实战 中,我们关注的是 TPS(速度);而在本文,我们关注的是 Quality(质量)。
这两者往往是矛盾的。引入 CoT(思维链)可以显著提升质量,但会使推理延迟翻倍。
最终的决策公式 :
Value=Quality×ThroughputLatency×Cost Value = \frac{Quality \times Throughput}{Latency \times Cost} Value=Latency×CostQuality×Throughput
只有建立起这套"自动化筛选 + 人工抽检"的评估闭环,我们才能在模型迭代的迷雾中看清方向,确保每一次微调都是真正的进化,而非原地踏步。