1. Agent评估体系的设计背景与挑战
在传统软件开发中,我们使用单元测试来保证代码质量。比如测试一个加法函数:
go复制func TestAdd(t *testing.T) {
assert.Equal(t, 3, Add(1, 2)) // 确定性:1+2永远等于3
}
但当我们开发基于大语言模型的Agent时,情况完全不同。当用户问"帮我规划去日本的旅行"时,Agent可能给出无数种合理的回答方案。我们无法用简单的assert.Equal来判断对错,这就是Agent评估面临的核心挑战。
1.1 传统测试与Agent测试的差异
| 维度 | 传统单元测试 | Agent评估 |
|---|---|---|
| 输入空间 | 有限、可枚举 | 无限(自然语言) |
| 输出形式 | 确定性 | 概率性、多样性 |
| 判断标准 | 精确匹配 | 语义理解、质量评分 |
| 测试覆盖 | 可接近100% | 永远无法穷举 |
这种差异源于大语言模型的概率性本质。Agent开发更像是"概率性编程"——我们追求的不是"绝对正确",而是"足够好且可持续改进"。
1.2 评估体系的核心目标
一个完善的Agent质量保障体系需要实现三个核心目标:
- 可测量:建立量化的评估指标,避免主观判断
- 可迭代:支持持续改进的反馈循环
- 可扩展:适应不同场景和业务需求
2. 评估框架的架构设计
2.1 整体架构组件
一个完整的评估框架包含以下核心组件:
code复制评估数据集(EvalSet) → 评估指标(Metric) → 评估器(Evaluator)
↗ ↘
规则评估器 LLM评估器
2.1.1 评估数据集设计
评估数据集是评估的基础,包含测试用例及其预期结果。数据结构示例:
go复制type EvalSet struct {
Name string // 数据集名称
Invocations []*Invocation // 测试用例列表
}
type Invocation struct {
UserContent string // 用户输入
FinalResponse string // Agent实际输出
Expected *Expected // 预期结果
}
type Expected struct {
FinalResponse string // 预期的最终回复
ToolCalls []ToolCall // 预期的工具调用
}
数据集设计原则:
- 场景覆盖:基础场景(60%) + 边界场景(20%) + 对抗场景(10%) + 多样性场景(10%)
- 持续补充:根据线上反馈不断扩充
- 分层管理:按功能模块或用户意图分类
2.2 评估指标类型
评估指标定义了"什么是好的输出"。主要分为两大类:
2.2.1 规则类指标(Rule-based)
- 特点:确定性算法,速度快、成本低
- 适用场景:有明确正确答案的情况
- 典型指标:
rule_exact_match:精确匹配rule_json_match:JSON字段校验rule_regex_match:正则匹配
2.2.2 LLM类指标(LLM-as-Judge)
- 特点:使用大语言模型作为裁判,能理解语义
- 适用场景:开放式问答
- 典型指标:
llm_compare_answer:答案对比llm_rubric_response:按评分标准评估llm_rubric_knowledge_recall:RAG检索质量评估
3. 核心评估指标实现原理
3.1 规则类指标详解
3.1.1 精确匹配(rule_exact_match)
go复制func ExactMatch(expected, actual string) float64 {
expected = strings.TrimSpace(expected)
actual = strings.TrimSpace(actual)
if expected == actual {
return 1.0
}
return 0.0
}
适用场景:数学计算结果、单选题答案等有唯一正确答案的情况。
注意事项:
- 对大小写和空格敏感
- 不适用于自然语言回答的评估
- 建议先进行标准化处理(如统一大小写、去除标点)
3.1.2 JSON字段匹配(rule_json_match)
go复制func JSONMatch(expected, actual string) float64 {
var expectedMap, actualMap map[string]interface{}
json.Unmarshal([]byte(expected), &expectedMap)
json.Unmarshal([]byte(actual), &actualMap)
matchCount := 0
totalCount := len(expectedMap)
for key, expectedValue := range expectedMap {
if actualValue, exists := actualMap[key]; exists {
if reflect.DeepEqual(expectedValue, actualValue) {
matchCount++
}
}
}
return float64(matchCount) / float64(totalCount)
}
适用场景:API返回值校验、结构化信息提取等。
实操技巧:
- 可以配置关键字段的权重
- 支持嵌套JSON结构的比较
- 对数值类型可以设置误差范围
3.2 LLM类指标详解
3.2.1 答案对比(llm_compare_answer)
评估流程:
- 将用户问题、预期答案和实际回答提供给Judge模型
- Judge模型判断语义一致性
- 返回评分(0.0/0.5/1.0)
Prompt模板示例:
code复制# Task
Compare the actual answer with the expected answer.
## User Question
{user_question}
## Expected Answer
{expected_answer}
## Actual Answer
{actual_answer}
## Scoring
- 1.0: Semantically identical
- 0.5: Partially correct
- 0.0: Incorrect
优化技巧:
- 使用更强大的Judge模型(如GPT-4)提高准确性
- 添加示例few-shot提高一致性
- 对争议案例进行人工复核
3.2.2 Rubric评分(llm_rubric_response)
评估流程:
- 定义评分标准(Rubric)
- Judge模型逐项检查回复是否符合标准
- 计算总分
示例Rubric:
- 是否包含具体日期?
- 是否包含预算信息?
- 是否提供备选方案?
优势:
- 适用于没有标准答案的场景
- 可以评估回复的多维度质量
- 更容易发现系统性缺陷
4. 工具调用评估
4.1 为什么需要专门评估工具调用?
对于具备工具调用能力的Agent,仅评估最终回复是不够的。因为:
- 正确的结果可能来自错误的工具调用路径
- 需要确保Agent选择了最合适的工具
- 工具参数的正确性直接影响执行结果
4.2 评估的三个维度
| 维度 | 说明 | 示例 |
|---|---|---|
| 工具名 | 调用的工具是否正确 | get_weather vs search_hotel |
| 参数 | 传入的参数是否正确 | city: "北京" vs city: "上海" |
| 顺序 | 工具调用顺序是否合理 | 先查天气再订票 |
4.3 实现示例
go复制func ToolCallMatch(expected, actual []ToolCall) float64 {
nameScore := evaluateToolNames(expected, actual)
argsScore := evaluateToolArguments(expected, actual)
orderScore := evaluateToolOrder(expected, actual)
return nameScore*0.4 + argsScore*0.4 + orderScore*0.2
}
评估模式选择:
- 严格模式:完全匹配工具、参数和顺序
- 宽松模式:只要求工具正确,参数部分匹配
- 语义模式:用LLM判断意图是否一致
5. 生产环境质量保障
5.1 评估与监控的区别
| 阶段 | 评估 | 监控 |
|---|---|---|
| 时机 | 开发测试阶段 | 线上运行阶段 |
| 目的 | 质量验证 | 异常检测 |
| 延迟 | 允许较高(秒级) | 必须很低(毫秒级) |
| 成本 | 可以较高 | 必须控制 |
5.2 多层防护体系
- 输入Guardrails:敏感词检测、意图识别
- Agent执行:核心业务逻辑
- 输出Guardrails:合规检查、幻觉检测
- 异步监控:采样评估、用户反馈
5.3 持续改进流程
code复制线上问题 → 添加到评估集 → 修复 → 评估通过 → 重新发布
关键指标:
- 评估通过率
- 线上问题发现速度
- 问题修复周期
6. 实践建议
6.1 指标选择策略
根据场景特点选择合适的指标组合:
| 场景 | 推荐指标 |
|---|---|
| 问答机器人 | llm_compare_answer + llm_rubric_response |
| RAG系统 | llm_rubric_knowledge_recall + llm_compare_answer |
| 数据提取 | rule_json_match + rule_regex_match |
| 工具调用Agent | tool_call_match + llm_rubric_response |
6.2 评估数据集构建
- 从真实用户问题开始
- 覆盖主要业务场景
- 包含边界测试用例
- 持续收集线上问题补充
6.3 性能优化技巧
- 对确定性场景优先使用规则评估
- 对LLM评估进行结果缓存
- 实现评估的并行执行
- 对大规模评估进行采样
7. 常见问题与解决方案
7.1 评估结果不一致
问题:相同输入在不同时间评估结果不同
解决方案:
- 固定Judge模型的temperature=0
- 使用更详细的评分标准
- 对争议案例进行人工标注
7.2 评估成本过高
问题:LLM评估消耗大量token
解决方案:
- 对简单场景使用规则评估
- 实现评估结果缓存
- 使用更小的Judge模型
7.3 评估覆盖率不足
问题:测试集无法覆盖所有线上场景
解决方案:
- 建立线上问题收集机制
- 实现自动化测试生成
- 定期扩充评估数据集
在实际项目中,我们通过这套评估体系将关键场景的准确率从初期的65%提升到了92%,同时将线上问题的发现时间从平均3天缩短到4小时。最重要的是,它建立了一个可持续改进的质量闭环,让团队能够客观地衡量Agent的表现并持续优化。