为什么评估 LLM 如此困难
评估 LLM 的独特挑战
传统软件的测试很简单:输入 A 应该得到输出 B。但 LLM 的输出是非确定性的、开放式的,这让评估变得异常困难。
graph TB
A[LLM 评估挑战] --> B[非确定性]
A --> C[开放式输出]
A --> D[主观性]
A --> E[多维度]
B --> B1[相同输入可能不同输出]
B --> B2[temperature 影响结果]
C --> C1[没有唯一正确答案]
C --> C2[多种表述都可能正确]
D --> D1[好坏因人而异]
D --> D2[场景决定标准]
E --> E1[准确 但不安全]
E --> E2[流畅 但有幻觉]
E --> E3[创意 但不可控]
style A fill:#e3f2fd,stroke:#1976d2,stroke-width:3px
传统软件 vs LLM 测试:
| 维度 | 传统软件 | LLM 应用 |
|---|---|---|
| 正确答案 | 唯一确定 | 多种可能 |
| 输出确定性 | 完全确定 | 概率性的 |
| 评估标准 | 客观 | 主客观混合 |
| 测试覆盖 | 可穷举关键路径 | 难以穷举 |
| 回归检测 | 简单 | 困难 |
评估的三大维度
graph LR
A[评估维度] --> B[质量]
A --> C[安全]
A --> D[效率]
B --> B1[准确性]
B --> B2[相关性]
B --> B3[完整性]
B --> B4[一致性]
C --> C1[无有害内容]
C --> C2[无偏见歧视]
C --> C3[无隐私泄露]
C --> C4[抗攻击能力]
D --> D1[延迟]
D --> D2[吞吐量]
D --> D3[Token 成本]
style A fill:#e3f2fd,stroke:#1976d2,stroke-width:3px
style B fill:#c8e6c9,stroke:#388e3c,stroke-width:2px
style C fill:#ffcdd2,stroke:#c62828,stroke-width:2px
style D fill:#fff3e0,stroke:#f57c00,stroke-width:2px
评估方法分类
"""
LLM 评估方法分类
"""
class EvaluationApproach:
"""评估方法"""
@staticmethod
def automated_metrics():
"""自动化指标评估"""
return {
"BLEU/ROUGE": "与参考答案的文本匹配度",
"F1 Score": "实体级别的精确率和召回率",
"Exact Match": "完全匹配率",
"Perplexity": "语言模型困惑度",
}
@staticmethod
def model_based():
"""基于模型的评估(LLM-as-a-Judge)"""
return {
"GPT-4 评估": "用强模型评估弱模型",
"成对比较": "让 LLM 比较两个回答",
"多维评分": "LLM 从多维度打分",
}
@staticmethod
def human_evaluation():
"""人工评估"""
return {
"专家评审": "领域专家打分",
"众包标注": "多人标注取均值",
"A/B 测试": "用户实际选择",
}
@staticmethod
def benchmark():
"""基准测试"""
return {
"MMLU": "多任务语言理解",
"HumanEval": "代码生成能力",
"HellaSwag": "常识推理",
"TruthfulQA": "事实准确性",
}
# 打印各方法
for name, method in [
("自动化指标", EvaluationApproach.automated_metrics()),
("模型评估", EvaluationApproach.model_based()),
("人工评估", EvaluationApproach.human_evaluation()),
("基准测试", EvaluationApproach.benchmark()),
]:
print(f"\n{name}:")
for k, v in method.items():
print(f" {k}: {v}")
选择评估策略
不同任务需要不同的评估策略:
| 任务类型 | 推荐评估方法 | 关键指标 |
|---|---|---|
| 问答系统 | 自动指标 + LLM Judge | 准确性、完整性 |
| 聊天对话 | 人工评估 + A/B 测试 | 自然度、有用性 |
| 文本摘要 | ROUGE + LLM Judge | 忠实度、简洁性 |
| 代码生成 | Pass@K + 单元测试 | 正确性、效率 |
| 内容审核 | F1 + 误报率 | 准确率、召回率 |
| RAG 系统 | 检索指标 + 生成指标 | 忠实度、相关性 |
评估心智模型
"""
评估流程框架
"""
class EvaluationPipeline:
"""评估流水线"""
def __init__(self, name: str):
self.name = name
self.steps = []
def add_step(self, step_name: str, evaluator, weight: float = 1.0):
"""添加评估步骤"""
self.steps.append({
"name": step_name,
"evaluator": evaluator,
"weight": weight,
})
return self
def evaluate(self, predictions: list[dict]) -> dict:
"""运行完整评估"""
results = {}
for step in self.steps:
print(f" 运行评估: {step['name']}...")
score = step["evaluator"](predictions)
results[step["name"]] = {
"score": score,
"weight": step["weight"],
"weighted_score": score * step["weight"],
}
# 加权平均
total_weight = sum(s["weight"] for s in self.steps)
weighted_avg = sum(
r["weighted_score"] for r in results.values()
) / total_weight
results["overall"] = round(weighted_avg, 4)
print(f"\n=== {self.name} 评估结果 ===")
for name, r in results.items():
if isinstance(r, dict):
print(f" {name}: {r['score']:.4f} (权重: {r['weight']})")
else:
print(f" 综合得分: {r}")
return results
# 使用示例
pipeline = EvaluationPipeline("QA 系统评估")
pipeline.add_step("准确性", lambda preds: 0.85, weight=0.4)
pipeline.add_step("完整性", lambda preds: 0.78, weight=0.3)
pipeline.add_step("安全性", lambda preds: 0.95, weight=0.3)
results = pipeline.evaluate([])
本章小结
- LLM 评估因非确定性、开放式输出和主观性而格外困难
- 评估需要从质量、安全、效率三个维度进行
- 四种评估方法:自动指标、模型评估、人工评估、基准测试
- 不同任务需要不同的评估策略组合
- 建立系统化的评估流水线是关键
下一章:深入学习各种评估指标的原理和使用。