关于 evaluation-harness
evaluation-harness 是用于系统评估 LLM 应用的技能,面向构建和维护模型应用的开发者。它围绕黄金数据集、评分标准、阈值和回归报告组织评估流程,并可用于持续评估。
主要功能
- 01定义黄金数据集格式
- 02实现精确匹配和语义相似度评分
- 03按类别设置通过阈值
- 04对比基线并生成回归报告
- 05在 CI 中运行持续评估
适用场景
- 01评估代码生成或摘要任务
- 02比较模型输出与基线结果
- 03在提交时发现模型表现回归
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ patricio0312rev/ skills --skill evaluation-harness安装后在 Claude Code 中输入/evaluation-harness确认已加载。
详细介绍
评估测试框架
为大模型应用构建系统化评估框架。
黄金数据集格式
[
{
"id": "test_001",
"category": "code_generation",
"input": "Write a Python function to reverse a string",
"expected_output": "def reverse_string(s: str) -> str:\n return s[::-1]",
"rubric": {
"correctness": 1.0,
"style": 0.8,
"documentation": 0.5
},
"metadata": {
"difficulty": "easy",
"tags": ["python", "strings"]
}
}
]
评分标准
from typing import Dict, Any
def score_exact_match(actual: str, expected: str) -> float:
"""Binary score: 1.0 if exact match, 0.0 otherwise"""
return 1.0 if actual.strip() == expected.strip() else 0.0
def score_semantic_similarity(actual: str, expected: str) -> float:
"""Cosine similarity of embeddings"""
actual_emb = get_embedding(actual)
expected_emb = get_embedding(expected)
return cosine_similarity(actual_emb, expected_emb)
def score_contains_keywords(actual: str, keywords: List[str]) -> float:
"""Percentage of required keywords present"""
found = sum(1 for kw in keywords if kw.lower() in actual.lower())
return found / len(keywords)
def score_with_llm(actual: str, expected: str, rubric: Dict[str, float]) -> Dict[str, float]:
"""Use LLM as judge"""
prompt = f"""
Grade this output on a scale of 0-1 for each criterion:
Expected: {expected}
Actual: {actual}
Criteria: {', '.join(rubric.keys())}
Return JSON with scores.
"""
return json.loads(llm(prompt))
测试运行器
class EvaluationHarness:
def __init__(self, dataset_path: str):
self.dataset = self.load_dataset(dataset_path)
self.results = []
def run_evaluation(self, model_fn):
for test_case in self.dataset:
# Generate output
actual = model_fn(test_case["input"])
# Score
scores = self.score_output(
actual,
test_case["expected_output"],
test_case["rubric"]
)
# Record result
self.results.append({
"test_id": test_case["id"],
"category": test_case["category"],
"scores": scores,
"passed": self.check_threshold(scores, test_case),
"actual_output": actual,
})
return self.generate_report()
def score_output(self, actual, expected, rubric):
return {
"exact_match": score_exact_match(actual, expected),
"semantic_similarity": score_semantic_similarity(actual, expected),
**score_with_llm(actual, expected, rubric)
}
def check_threshold(self, scores, test_case):
min_scores = test_case.get("min_scores", {})
for metric, threshold in min_scores.items():
if scores.get(metric, 0) < threshold:
return False
return True
阈值与通过标准
# Define thresholds per category
THRESHOLDS = {
"code_generation": {
"correctness": 0.9,
"style": 0.7,
},
"summarization": {
"semantic_similarity": 0.8,
"brevity": 0.7,
},
"classification": {
"exact_match": 1.0,
}
}
def check_test_passed(result: Dict) -> bool:
category = result["category"]
thresholds = THRESHOLDS.get(category, {})
for metric, threshold in thresholds.items():
if result["scores"].get(metric, 0) < threshold:
return False
return True
回归报告
def generate_regression_report(baseline_results, current_results):
report = {
"summary": {},
"regressions": [],
"improvements": [],
"unchanged": 0
}
for baseline, current in zip(baseline_results, current_results):
assert baseline["test_id"] == current["test_id"]
baseline_passed = baseline["passed"]
current_passed = current["passed"]
if baseline_passed and not current_passed:
report["regressions"].append({
"test_id": baseline["test_id"],
"category": baseline["category"],
"baseline_scores": baseline["scores"],
"current_scores": current["scores"],
})
elif not baseline_passed and current_passed:
report["improvements"].append(baseline["test_id"])
else:
report["unchanged"] += 1
report["summary"] = {
"total_tests": len(baseline_results),
"regressions": len(report["regressions"]),
"improvements": len(report["improvements"]),
"unchanged": report["unchanged"],
}
return report
持续评估
# Run evaluation on every commit
def ci_evaluation():
harness = EvaluationHarness("golden_dataset.json")
results = harness.run_evaluation(production_model)
# Check for regressions
baseline = load_baseline("baseline_results.json")
report = generate_regression_report(baseline, results)
# Fail CI if regressions
if report["summary"]["regressions"] > 0:
print(f"❌ {report['summary']['regressions']} regressions detected!")
sys.exit(1)
print("✅ All tests passed!")
最佳实践
- 具有代表性的数据集:覆盖边界情况
- 多种指标:不要只依赖一项分数
- 人工验证:审核大模型裁判给出的分数
- 对数据集进行版本管理:跟踪变化
- 在 CI 中自动化:及早发现回归问题
- 定期更新:添加新的测试用例
输出检查清单
- 已创建黄金数据集(50+ 个示例)
- 多个评分函数
- 已定义通过/失败阈值
- 已实现测试运行器
- 回归比较
- 报告生成
- CI 集成
- 已建立基线
评论
支持 Markdown