Files
2026-09-22 15:42:25 +08:00

288 lines
19 KiB
Markdown
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 阶段五 · 小点 4:Agent 评估与评测
> 所属:阶段五 进阶技术:能力增强与优化
> 定位:怎么证明你的 Agent 「变好了」?评估是 Agent 工程的「回归测试」——没有评测集,改 prompt / 换模型全靠玄学。这一讲讲清五大指标、公开/自建评测集的取舍、LLM-as-judge 三原则,以及让 Agent 持续变好的 Bad-case 迭代闭环。
## 精简大纲
1. 五大核心指标
2. 公开 Benchmark vs 自建业务评测集
3. LLM-as-judge(模型当裁判)三原则
4. Bad-case 四分类与迭代闭环
5. 一个可运行的 evaluate 骨架
## 学习内容详情
> 原则:公开 Benchmark 只做选型参考;**业务效果必须用自己的评测集说话**。
### 1. 五大核心指标
```mermaid
graph TD
A[五大核心指标] --> B[任务成功率 ★核心]
A --> C[工具调用准确率]
A --> D[步骤数/token成本]
A --> E[幻觉率]
A --> F[平均完成耗时]
```
1. **任务成功率**:评测集里「完整达成用户意图」的占比——最核心指标。
2. **工具调用准确率**:该调的调了 + 不该调的没调(闲聊触发检索也算错——过度调用浪费 token 且拖慢响应)。
3. **步骤数量 / token 成本**:完成任务用了几轮循环、烧了多少 token;同等成功率下步骤越少越优秀——**无限循环的 Agent 就是被这个指标暴露的**。
4. **幻觉率**:回答中「编造事实」的比例,靠 LLM 裁判 + 人工抽检结合评估。
5. **平均完成耗时**:延迟体感指标。
> 🔬 **深度理解 · Agent 评估指标体系(成功率 / 工具准确率 vs 静态 Benchmark)**:
> 1. **本质**:Agent 评估不是"答对了没",而是把「意图达成 + 工具行为 + 效率 + 真实性 + 时延」多维拆成可在固定用例集上重复计算的量化指标,充当工程上的"回归测试"。
> 2. **机制**:任务成功率统计完整达成用户意图的比例(核心);工具调用准确率同时惩罚"该调没调"与"不该调却调"(如闲聊触发检索、浪费 token);步骤数 / token 成本暴露无限循环;幻觉率量化编造;平均耗时体现延迟体感。它们常需结合 LLM 裁判与人工抽检共同计算。
> 3. **为什么重要**:没有评测集,改 prompt / 换模型全靠玄学;有了它,任何改动都能用"指标是否回升/回落"客观验证,从而建立持续迭代闭环。MMLU-Pro / HumanEval 这类静态知识 / 代码题只衡量"知识 / 代码正确性(如 pass@k)",测不出"会用工具、会多步推理、不无限循环"的 Agent 能力——所以只做选型参考,业务评估必须用自建回归集。
> 4. **易错点**:把"答案对了"当成"任务成功了"——忽视了工具调用是否恰当与是否控制成本;另一个误区是只做一次性评估,不把失败样本固化成回归集,导致改 prompt 修好一例又弄坏别的。
### 2. 公开 Benchmark vs 自建业务评测集
| 维度 | 公开 Benchmark | 自建业务评测集 |
|-|-|-|
| 例子 | AgentBench / GAIA / MMLU-Pro / HumanEval | 你的真实业务问题整理成固定用例 |
| 作用 | 选模型时横向参考 | Agent 的「回归测试」 |
| 局限 | 题目 ≠ 你的业务 | 需要花时间维护 |
四个主流公开 Benchmark 各自考什么(评测维度对照):
| Benchmark | 评测维度 |
|-|-|
| **AgentBench** | 多环境工具使用综合(办公 / 游戏 / 数据库等多环境下的工具调用能力) |
| **GAIA** | 通用助手多步推理(多步推理 + 工具 + 检索的通用助手能力) |
| **MMLU-Pro** | 知识问答加强版(更难、干扰项更多的知识选择题) |
| **HumanEval** | 代码生成(函数级代码正确性,pass@k) |
- **自建业务评测集**:把真实业务问题整理成固定用例集:**输入 + 期望要点**(该调什么工具、答案含什么关键词、来源是什么)。每次改 prompt / 换模型后重跑——这就是 Agent 的「回归测试」。
```python
# 自建评测集示例: 每条用例 = 输入 + 期望要点
EVAL_CASES = [
{"input": "北京明天天气如何?",
"expect": {"tool": "get_weather", "keyword": ["北京"]}}, # 应调天气工具
{"input": "你好",
"expect": {"tool": None, "keyword": []}}, # 闲聊不应调工具
{"input": "报销流程是什么?",
"expect": {"tool": "kb_search", "keyword": ["报销", "发票"]}},
]
```
> ⏳ **短期可不深究**:MMLU-Pro / HumanEval(含 pass@k)这类公开 Benchmark 的评测协议细节(如何出题、如何计 pass@k)只用于选型参考,第一遍不必深究;业务评估的重心是把自己场景的用例固化成回归集,静态评测协议用到再看。
### 3. LLM-as-judge 三原则
> LLM 当裁判省人工,但会错。三条铁律缺一不可。
1. **裁判模型要比被测模型强**(否则判不准)。
2. **评分标准与输出格式必须固定**(否则结果不可比)。
3. **抽 10% 人工复核**(裁判自己也会幻觉)。
```python
JUDGE_PROMPT = """你是评测裁判。请仅依据给定标准判断回答是否达成用户意图。
评分标准(必须返回 JSON): {{"success": true/false, "reason": "..."}}
用例来源必须存在, 编造内容判 false。
作答:{answer}"""
def judge_success(answer: str, keyword: list) -> bool:
"""简化裁判: 检查期望关键词是否出现。生产用 LLM 裁判 + 人工抽检。"""
return all(k in answer for k in keyword)
```
> 🔬 **深度理解 · LLM-as-judge 机制与偏差**:
> 1. **本质**:用更强的模型作为"裁判"来替代部分人工判分,本质是把"评估"本身也模型化——它带来了规模化,但把模型自身的偏差也引入了评估链路。
> 2. **机制**:规定好评分标准与输出格式(常为固定 JSON schema),给裁判被测样本,让其按标准返回 score/reason;为对抗裁判幻觉与偏好,抽样(如 10%)人工复核兜底。它的可靠性受限于裁判模型能力、提示稳定性和个人偏好 / 顺序偏好(position bias)。
> 3. **为什么重要**:人工判分慢且贵,LLM-as-judge 让"改 prompt → 重跑 → 自动打分"的迭代闭环可以规模化地天天跑;它缓解了"没有人工就打不了分"的瓶颈。
> 4. **易错点**:裁判模型不比被测模型强时判不准;评分标准不固定则结果不可比;不抽人工复核则裁判自己的幻觉会悄悄变成系统性误判。还要警惕位置偏差(先出现的答案更容易被选)与格式敏感——这也是为什么"裁判更强 + 模板固定 + 人工抽检"三条铁律缺一不可。
### 4. Bad-case 四分类与迭代闭环
```mermaid
graph TD
A[失败样本归因四分类] --> B[Prompt 问题<br/>指令不清/约束缺失]
A --> C[模型问题<br/>能力不足]
A --> D[工具问题<br/>执行失败/脏数据]
A --> E[检索问题<br/>没召回/召回无关]
B --> F[对应修法: 改prompt]
C --> G[换模型]
D --> H[修工具]
E --> I[调检索]
```
- 失败样本归因四类:**prompt 问题**(指令不清 / 约束缺失)、**模型问题**(能力不足)、**工具问题**(执行失败 / 返回脏数据)、**检索问题**(没召回 / 召回了无关内容)。
- **分类决定修法**:改 prompt / 换模型 / 修工具 / 调检索——**别用改 prompt 去治工具的病**。
- **迭代闭环**:改 prompt / 修工具 → 重跑 evaluate → 指标回升 = 修对了;指标回落 = 改坏了别处(回归测试防「按下葫芦浮起瓢」)。
```mermaid
graph LR
A[改 prompt/修工具] --> B[重跑 evaluate]
B --> C{指标?}
C -->|回升| D[修对了 ✓]
C -->|回落| E[改坏了别处<br/>定位回归]
```
### 5. 一个可运行的 evaluate 骨架
把上述指标落到代码,跑了就能得到一份「Agent 健康报告」。
```python
import time
class Evaluator:
"""对一批评测用例跑 Agent, 统计五大指标"""
def __init__(self, cases: list, agent_call):
self.cases, self.agent_call = cases, agent_call
def run(self) -> dict:
succ = ok_tool = steps = hal = lat = 0
for c in self.cases:
t0 = time.time()
result = self.agent_call(c["input"] or "") # → (answer, used_tool, n_steps)
lat += time.time() - t0
answer, used_tool, n_steps = result
# ① 任务成功率: 期望关键词都命中
if c["expect"].get("keyword", []) and \
all(k in answer for k in c["expect"]["keyword"]):
succ += 1
# ② 工具调用准确率: 该调的调了/不该调的没调
if used_tool == c["expect"].get("tool"):
ok_tool += 1
steps += n_steps # ③ 步骤数(越低越好)
if "编造" in answer: # ④ 简化幻觉计数
hal += 1
n = len(self.cases)
return {
"任务成功率": round(succ / n, 3),
"工具调用准确率": round(ok_tool / n, 3),
"平均步骤数": round(steps / n, 2), # ③ 无限循环在此暴露
"幻觉率": round(hal / n, 3),
"平均耗时(s)": round(lat / n, 3), # ⑤ 延迟体感
}
# 用法: ev = Evaluator(EVAL_CASES, my_agent.run); print(ev.run())
```
### 6. 评估工具链落地(LangSmith / Ragas / Langfuse)
自建 evaluate 骨架解决「有没有」,工具链解决「效率与规模化」——trace 全链路可视化、评估结果面板化、团队共享同一套回归集。
#### 6.1 LangSmith:LangChain 生态的追踪 + 评估平台
- **trace 全链路**:Agent 每一步的输入输出(LLM 调用 / 工具执行 / 检索)全记录——bad-case 定位从「翻日志」变成「点开看」;
- **数据集管理**:评测用例云端版本化,团队共享同一套回归集;
- **LLM-as-judge 评估器**:内置裁判评估器,跑完自动打分(对照上文三原则);
- **生产监控**:线上延迟 / token 消耗 / 失败率实时看板。
```bash
# 最小接入: 装包 + 两个环境变量, LangChain/LangGraph 的调用自动上报
pip install langsmith
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=...
```
```python
from langsmith import Client
client = Client()
client.create_dataset(dataset_name="kb-qa-regression") # 建评测数据集(用例可逐条加)
# 跑评估: 指定数据集 + 被测对象 + 评估器, 结果直接进面板
client.run_on_dataset(
dataset_name="kb-qa-regression",
llm_or_chain_factory=my_agent, # 被测的 Agent/链
evaluation=my_judge_evaluator, # LLM-as-judge 或自定义评估器
)
```
> ⏳ **短期可不深究**:LangSmith / Langfuse 这类工具链的云端接入细节(环境变量、API Key、`run_on_dataset` 参数)第一遍知道"装包 + 配环境变量即可自动上报"就行,具体接入跟着官方文档走即可,不必背参数。
#### 6.2 Ragas:RAG 专用评估库
RAG 效果光看「答案对不对」不够,还要拆开看「检索质量」——Ragas 的四个核心指标把锅分清楚:
- **faithfulness(忠实度)**:答案是否只基于检索内容、不夹带私货——幻觉率的量化版;
- **answer_relevancy(答案相关性)**:答案是否切题;
- **context_precision / context_recall(检索质量)**:召回的片段里多少真有用 / 该召回的召回了多少——直接定位「是检索的锅还是生成的锅」。
> ⚠️ **版本提示**:以下示例对应 Ragas **≤0.1.x 的旧式声明式 API**(`from ragas.metrics import faithfulness`)。Ragas 0.4+ 已把指标重构为**类式 API**(如 `AnswerRelevancy` / `ResponseRelevancy` 等类及对应 `Input/Output`),导入路径与指标名有所变化。实际使用时请按所装版本,以官方迁移文档为准:https://docs.ragas.io/en/stable/howtos/migrations/migrate_from_v0_to_v1/
```python
# pip install ragas
from ragas import evaluate
from ragas.dataset_schema import EvaluationDataset
from ragas.metrics import (
faithfulness, answer_relevancy, context_precision, context_recall,
)
ds = EvaluationDataset.from_list([{
"user_input": "报销流程是什么?",
"retrieved_contexts": ["报销需附发票, 三个工作日内提交..."], # 检索到的片段
"response": "报销需附发票, 三个工作日内提交审批。", # Agent 的答案
}])
report = evaluate(dataset=ds,
metrics=[faithfulness, answer_relevancy,
context_precision, context_recall])
```
> ⏳ **短期可不深究**:Ragas 的具体导入路径与指标名因版本迭代变化较快(本文已提示 0.4+ 改为类式 API),第一遍只需理解"忠实度 / 相关性 / 检索质量"这四个维度分别说什么,写代码时按所装版本的官方迁移文档来即可,不必死记 API。
> 🔬 **深度理解 · Ragas 与检索指标(RAG 评估为什么不能只看答案)**:
> 1. **本质**:Ragas 把 RAG 的"答案"和"检索"拆成两个可分开定位的环节,用专门指标回答"锅到底在生成层还是检索层",避免"答案不对"这种笼统结论掩盖真实病灶。
> 2. **机制**:faithfulness(忠实度)度量答案是否只基于检索到的上下文、不夹带私货——即"幻觉率的量化版";answer_relevancy 度量答案是否切题;context_precision 度量召回的片段中有多少真有用(检出有用达标),context_recall 度量该召回的到底召回了没有(尽量不漏)。四者结合定位"是检索的锅还是生成的锅"。
> 3. **为什么重要**:光看"答案对不对",检索召回空洞但生成能猜、或检索丰富但生成瞎编,都无法归因;拆开这些指标才能对症修——context_precision/recall 低去调检索,faithfulness 低去约束生成。
> 4. **易错点**:把"忠实度"当成"正确率"(它只管"是否忠于检索内容",不保证这个内容本身对);只报一个总指标会掩盖检索与生成的问题叠加;用旧版 API 与新库混装会直接报错或结果不可比——先明确所装版本再选指标。
与 LangSmith 集成后,Ragas 的评估结果直接挂到 trace 面板上——检索质量与生成质量在同一视图对齐。
#### 6.3 Langfuse:开源可自托管替代
- 与 LangSmith 同类(trace + 评估 + 监控),但**开源自托管**、OTLP 协议接入,数据不出内网;
- 对**数据合规敏感的团队**(金融 / 医疗 / 政企)首选——LangSmith 是 SaaS,trace 里难免携带业务数据。
#### 6.4 三者定位对比
| 工具 | 定位 | 一句话取舍 |
|-|-|-|
| **LangSmith** | LangChain 生态绑定最深 | 追踪 + 评估 + 监控开箱即用,上手最快 |
| **Ragas** | RAG 指标专精 | 只管评估不记 trace,与前两者配合使用 |
| **Langfuse** | 开源可自托管 | 数据合规敏感团队首选,代价是自运维 |
> ⚠️ **先自建小评测集跑通闭环,再接工具链放大效率**:工具链是放大器不是替代品——评测集才是评估的根,没有它,面板再漂亮也只是「看戏更清楚」;有了它,工具链让回归跑得更快、看得更清。
## 本节自检
- [ ] 能构建包含 3 个以上业务用例的评测集并跑出五大指标
- [ ] 能对失败样本完成四分类归因并给出对应修法
- [ ] 能说清 LLM-as-judge 三原则并演示一个 evaluate 骨架
## 本节常见面试题(深度解析)
> 针对本节核心知识的面试高频点,配合"本质+机制"式理解,能让你答得既有深度又有广度。
### 面试题 1:怎么给一个 Agent 做量化评估?五大指标各自衡量什么、为什么"任务成功率"不能单看"答案对没对"?
- **面试官想考察**:是否能从"意图 + 工具行为 + 效率 + 真实性 + 时延"多维建模评估,而不只懂"答得对不对"。
- **专业作答(含深度)**:
- 任务成功率:完整达成用户意图的占比,是核心但非全部。
- 工具调用准确率:同时惩罚"该调没调"与"不该调却调"(闲聊触发检索也计入错误,白烧 token 拖慢响应)。
- 步骤数 / token 成本:同等成功率下越少越优,专门暴露无限循环。
- 幻觉率:靠 LLM 裁判 + 人工抽检量化编造;平均耗时管延迟体感。
- 为什么要综合:答案对但多绕了几圈、或答案对却乱调工具,单看成功率完全发现不了;且静态 Benchmark(MMLU-Pro/HumanEval)只测知识与代码正确性,测不出会用工具、不绕圈的能力,所以业务必须用自建回归集。
- **加分亮点 / 深度追问**:可主动点出"工具调用准确率防的是过度调用/误调用",追问常是"怎么自动判断工具该不该调"——答:用用例里预置的 `expect.tool` 期望值与实际调用比对,本质上是行为级校验。
### 面试题 2:LLM-as-judge 有哪些天然缺陷?三条铁律分别解决什么问题?
- **面试官想考察**:是否知道"裁判也是模型"这个前提,并理解偏差与校准手段,而不只是把三原则背下来。
- **专业作答(含深度)**:
- 裁判模型本身会幻觉、有偏好与位置偏差(position bias),且其强弱点会传导为评估偏差。
- 三条铁律:① 裁判比被测强——弱裁判判不准强的答案;② 评分标准与输出格式固定——否则结果不可比、无法回归;③ 抽 10% 人工复核——兜住裁判的系统性幻觉与偏好。
- 额外注意:固定 JSON schema 可抵御格式漂移;必要时用多个裁判交叉或引入人工锚点校准。
- **加分亮点 / 深度追问**:可主动提"位置偏差"这类细颗粒风险,追问常是"裁判评测结果和人工不一致怎么办"——答:不一致即信号,用于校准/修正评估维度,而不是默认裁判对。
### 面试题 3:RAG 评估为什么不能只看"答案对不对"?faithfulness 与 context_precision/recall 各自定位什么?
- **面试官想考察**:是否理解"生成层"与"检索层"要分开归因,Ragas 四个指标分别解决什么问题。
- **专业作答(含深度)**:
- 只对答案打分,检索空洞但生成能猜、或检索丰富但生成瞎编,都无法定位是谁的锅。
- faithfulness(忠实度):答案是否只基于检索上下文、不夹带私货——幻觉率的量化版,属于"生成层"。
- answer_relevancy:答案是否切题。
- context_precision:召回的片段有多少真有用;context_recall:该召回的召回没有——这两者属"检索层"。
- 对症下药:precision/recall 低去调检索(切分、embedding、top-k),faithfulness 低去约束生成。
- **加分亮点 / 深度追问**:可主动指出"忠实度高 ≠ 答案正确"(只证明没编造,不保证检索内容本身对),追问常是"想同时查检索和生成,怎么集成"——答:Ragas 出指标、LangSmith 挂 trace,检索质量与生成质量在同一视图对齐。