L8 元认知与 Agent 评估:怎么知道 Agent 做得好不好
课程目标:掌握 Agent 自我反思(元认知)的实现方法,理解 Agent 评估的完整体系,能为自己的 Agent 设计评估方案。
一、一个让产品经理抓狂的问题#
你的 Agent 上线了,用户反馈"有时候准有时候不准"。老板问:
"这个 Agent 到底能不能用?准确率多少?"
你答不上来。
问题根源:传统软件测试有明确的"通过/失败"——程序要么对要么错。但 Agent 的输出是自然语言,每个输出都不一样,怎么定义"对"?
更糟的是,Agent 不只是"输出"——它还有"过程"(怎么一步步走到答案的)。过程错了但结果碰巧对了,算不算"对"?
这一课我们学习两件事:
元认知(Metacognition):让 Agent 知道自己"知不知道"——评估自己输出的可靠性
Agent 评估(Evaluation):作为开发者,怎么衡量 Agent 的整体质量
二、用一个比喻:Agent 评估 = 给一个员工做绩效考核#
把 Agent 比作新入职的员工:
评估维度对照#
| 员工评估 | Agent 评估 | 说明 |
|---|---|---|
| KPI 完成率 | 任务成功率 | 任务完成的百分比 |
| 工作过程 | 轨迹效率 | 用了多少步、调了几个工具 |
| 沟通能力 | 工具调用准确率 | 调用工具的参数是否正确 |
| 专业水平 | 答案质量 | 最终输出的准确性 |
| 稳定性 | pass^k(多次测试一致率) | 不同次跑结果是否一致 |
| 成本意识 | Token 消耗 / 延迟 | 完成任务的资源消耗 |
| 自我认知 | 元认知能力 | 知道什么时候"我不确定" |
一个反直觉的事实#
很多公司招 Agent 工程师最看重"自我认知"——能在不确定时主动说"我不知道",比自信地胡说更重要。
这正是元认知要解决的问题。
三、元认知(Metacognition):让 Agent 知道"自己知不知道"#
什么是元认知?#
元认知 = 对认知的认知。让 Agent 评估自己的输出是否可靠。
三个层级:
| 层级 | 含义 | 例子 |
|---|---|---|
| L1 感知 | 我做了什么? | "我调用了 search_web 工具" |
| L2 评估 | 我做的对吗? | "搜索结果相关,我可以基于它回答" |
| L3 反思 | 我应该改进什么? | "下次应该用更具体的关键词" |
为什么元认知重要?#
反例:普通 LLM 会"自信地胡说"。
用户:法国的首都是什么?
普通 LLM:法国的首都是柏林。(错误但很自信)
元认知 LLM:法国的首都是什么?我有 95% 的把握是巴黎,但让我确认一下...
四、元认知实现:Confidence Score(置信度评分)#
模式 1:让 LLM 自评置信度#
最简单的元认知——让 LLM 在输出时附带一个 0-1 的置信度分数:
CONFIDENCE_PROMPT = """请回答用户问题,并给出你的置信度(0-1)。
格式严格遵守:
ANSWER: <你的答案>
CONFIDENCE: <0-1 之间的数字,保留两位小数>
REASONING: <为什么是这个置信度>
用户问题:{question}"""
示例输出:
ANSWER: 法国的首都是巴黎
CONFIDENCE: 0.98
REASONING: 这是基本地理常识,模型训练数据中频繁出现
vs
ANSWER: 2030 年世界杯冠军是巴西
CONFIDENCE: 0.15
REASONING: 2030 年还未发生,无法预测
模式 2:Self-Consistency(自一致性)#
核心思想:同一个问题问多次,看答案是否一致。
def self_consistency(question: str, n: int = 5) -> tuple[str, float]:
"""多次问同一个问题,返回最一致的答案"""
answers = []
for _ in range(n):
response = llm.invoke(question, temperature=0.7)
answers.append(response.content)
# 投票:出现最多的答案作为最终答案
from collections import Counter
counter = Counter(answers)
most_common, count = counter.most_common(1)[0]
confidence = count / n
return most_common, confidence
直觉:如果 5 次问都得到同样答案,可信度高;如果 5 次问了 5 个不同答案,可信度低。
模式 3:Ensemble Agreement(多模型投票)#
def multi_model_consensus(question: str) -> tuple[str, float]:
"""用多个不同模型投票"""
models = [
ChatOpenAI(model="gpt-4o-mini"),
ChatAnthropic(model="claude-3-5-sonnet-latest"),
ChatOpenAI(model="gpt-4o"),
]
answers = [m.invoke(question).content for m in models]
# 用更强的模型当 Judge
judge_prompt = f"以下是对同一问题的三个回答,请判断哪个最正确:\n{answers}"
final_answer = judge_llm.invoke(judge_prompt).content
# 一致性 = 多数派占比
from collections import Counter
counter = Counter(answers)
consistency = counter.most_common(1)[0][1] / len(answers)
return final_answer, consistency
关键洞察:当多模型一致时,准确率显著高于单模型。这是集成学习的力量。
模式 4:Internal Knowledge Check(内部知识检测)#
让 LLM 在回答前先"自言自语"检查知识:
KNOWLEDGE_CHECK_PROMPT = """回答用户问题前,先做内部知识检查:
问题:{question}
步骤:
1. 你是否知道这个问题的答案?(yes/no/maybe)
2. 你的知识截止日期是什么时候?这问题是否在之后发生?
3. 这个问题的答案是否随时间变化?
4. 你是否有信心给出一个事实准确的答案?
输出格式:
HAS_KNOWLEDGE: yes/no/maybe
CONFIDENCE: <0-1>
SHOULD_SEARCH: yes/no # 是否需要查工具
"""
实战用法:当 HAS_KNOWLEDGE=no 或 SHOULD_SEARCH=yes 时,让 Agent 先调用搜索工具再回答。
五、Agent 评估:怎么衡量 Agent 系统的质量#
元认知是 Agent 评估自己,我们现在讨论开发者评估 Agent。
三大评估层级#
Layer 1:任务级评估(Task-Level)#
问题:Agent 整体表现如何?
核心指标:
| 指标 | 含义 | 计算方式 |
|---|---|---|
| Success Rate | 任务成功率 | 完成任务数 / 总任务数 |
| pass@k | k 次内至少成功 1 次的概率 | 通常 k=1, 3, 5 |
| pass^k | k 次全部成功的概率(衡量稳定性) | 比 pass@k 严格 |
| Cost per Task | 单任务成本 | Token 数 × 单价 |
| Latency | 任务完成时间 | 端到端秒数 |
例:你的 Agent 跑了 100 个任务,80 个成功,平均每个花了 0.05 美元,延迟 5 秒。
Layer 2:轨迹级评估(Trajectory-Level)#
问题:Agent 是怎么一步步走到答案的?
核心指标:
| 指标 | 含义 | 计算方式 |
|---|---|---|
| Step Efficiency | 步骤效率 | 最优步数 / 实际步数 |
| Tool-call Precision | 工具调用准确率 | 正确调用数 / 总调用数 |
| Tool-call Recall | 工具调用召回率 | 应该调用且调了的数 / 应该调用的总数 |
| Argument Accuracy | 参数准确率 | 参数完全正确的调用数 / 总调用数 |
| Hallucination Rate | 幻觉率 | 编造事实的步骤数 / 总步骤数 |
例:Agent 调用了 10 次工具,其中 8 次工具选对了,9 次参数填对了,2 次返回了无关信息。
Layer 3:体验级评估(Experience-Level)#
问题:用户用得爽不爽?
核心指标:
| 指标 | 含义 |
|---|---|
| Acceptance Rate | 用户接受答案的比例 |
| Interaction Rounds | 完成任务的平均对话轮次 |
| Disruption Rate | 用户中途打断/放弃的比例 |
| User Satisfaction (CSAT) | 用户满意度评分 |
评估层级关系#
Layer 3 体验级 ← 用户角度
↓
Layer 2 轨迹级 ← 过程质量
↓
Layer 1 任务级 ← 结果质量
实战中三层都要评估——只评估任务成功率会漏掉"任务成功但用户体验差"的情况。
六、评估方法:怎么测出这些指标?#
方法 1:人工标注(Human Evaluation)#
优点:金标准,最准确 缺点:慢、贵、主观
适用:核心场景上线前的最终评估
方法 2:执行式评估(Execution-Based)#
适用:Agent 产出可执行代码/可运行命令的场景
例:HumanEval(164 个 Python 函数问题)
def evaluate_humaneval(agent, problems: list[dict]) -> dict:
results = {"passed": 0, "failed": 0, "metrics": {}}
for problem in problems:
# 让 Agent 生成代码
generated_code = agent.run(problem["prompt"])
# 执行测试用例
try:
exec(generated_code)
passed = all(assert in generated_code for assert in problem["tests"])
except Exception:
passed = False
if passed:
results["passed"] += 1
else:
results["failed"] += 1
results["metrics"]["pass@1"] = results["passed"] / len(problems)
return results
优点:客观、可重复 缺点:只适用于"输出可执行"的场景
方法 3:LLM-as-Judge#
核心思想:用一个更强的 LLM 当裁判,评估另一个 LLM 的输出。
JUDGE_PROMPT = """请评估以下 Agent 的回答质量。
用户问题:{question}
Agent 答案:{answer}
参考答案:{reference}
按 1-5 分打分:
1 = 完全错误或无关
2 = 部分相关但有明显错误
3 = 基本正确但有遗漏
4 = 正确且完整
5 = 正确、完整、有洞见
输出格式:
SCORE: <1-5>
REASONING: <简短理由>"""
def llm_as_judge(question: str, answer: str, reference: str, judge_llm) -> int:
response = judge_llm.invoke(JUDGE_PROMPT.format(
question=question, answer=answer, reference=reference
))
score = int(re.search(r"SCORE:\s*(\d)", response.content).group(1))
return score
优点:可扩展、低成本 缺点:LLM 评判有 bias(位置 bias、长度 bias、自我偏好)
关键实践:用 GPT-4 评 GPT-3.5 输出,用 Claude 评 GPT 输出,避免自我偏好。
方法 4:Trajectory Evaluation(轨迹评估)#
对比 Agent 实际走的路径和"黄金路径":
def trajectory_similarity(actual_steps: list[str], golden_steps: list[str]) -> float:
"""计算轨迹相似度(基于工具调用顺序)"""
actual_tools = [extract_tool(step) for step in actual_steps]
golden_tools = [extract_tool(step) for step in golden_steps]
# 用 SequenceMatcher 计算相似度
from difflib import SequenceMatcher
similarity = SequenceMatcher(None, actual_tools, golden_tools).ratio()
return similarity
适用:自动化批量评估
七、主流 Benchmark 介绍#
HumanEval#
来源:OpenAI 2021
规模:164 个 Python 函数问题
指标:pass@k(k=1, 10, 100)
适用:代码生成 Agent
SWE-bench Verified#
来源:Princeton 2024
规模:500 个人工验证的真实 GitHub Issue
指标:Resolution Rate
适用:软件工程 Agent(Devin 类)
GAIA#
来源:Meta + HuggingFace 2024
规模:466 个真实世界任务
指标:准确率
适用:通用助手 Agent(HuggingFace Final Project 用这个)
WebArena#
来源:CMU 2024
规模:812 个真实网站任务
指标:任务成功率
适用:浏览器 Agent
AgentBench#
来源:清华 2023
规模:8 种环境(数据库、操作系统、网络购物等)
指标:综合得分
适用:通用 Agent 能力评估
选择建议:
代码 Agent → HumanEval + SWE-bench
通用助手 → GAIA
浏览器 Agent → WebArena
全场景评估 → AgentBench
八、实战评估框架:一个最小可用的 Eval Harness#
from dataclasses import dataclass
from typing import Callable
@dataclass
class TestCase:
"""单个测试用例"""
input: str # 用户输入
expected_output: str # 期望输出(可选)
expected_tools: list[str] # 期望调用的工具列表(可选)
metadata: dict = None # 额外元数据
@dataclass
class EvalResult:
"""单个用例的评估结果"""
test_case: TestCase
actual_output: str
success: bool
tool_calls: list[str]
trajectory_similarity: float
llm_judge_score: int
cost: float
latency: float
class AgentEvaluator:
"""Agent 评估器"""
def __init__(self, agent, judge_llm=None):
self.agent = agent
self.judge_llm = judge_llm or ChatOpenAI(model="gpt-4o")
def run(self, test_cases: list[TestCase]) -> dict:
results = []
for case in test_cases:
result = self.evaluate_one(case)
results.append(result)
return self.aggregate(results)
def evaluate_one(self, case: TestCase) -> EvalResult:
"""评估单个用例"""
import time
start = time.time()
# 运行 Agent(捕获工具调用)
tool_calls = []
original_call_tool = ... # 拦截工具调用
output = self.agent.run(case.input)
latency = time.time() - start
cost = self._estimate_cost(case.input, output)
# 多维度评估
success = self._check_success(output, case.expected_output)
traj_sim = self._trajectory_similarity(tool_calls, case.expected_tools)
judge_score = self._llm_judge(case.input, output, case.expected_output)
return EvalResult(
test_case=case,
actual_output=output,
success=success,
tool_calls=tool_calls,
trajectory_similarity=traj_sim,
llm_judge_score=judge_score,
cost=cost,
latency=latency
)
def aggregate(self, results: list[EvalResult]) -> dict:
"""汇总结果"""
return {
"success_rate": sum(r.success for r in results) / len(results),
"avg_trajectory_similarity": sum(r.trajectory_similarity for r in results) / len(results),
"avg_judge_score": sum(r.llm_judge_score for r in results) / len(results),
"avg_cost": sum(r.cost for r in results) / len(results),
"avg_latency": sum(r.latency for r in results) / len(results),
"total_cost": sum(r.cost for r in results),
"details": results
}
# ============ 使用示例 ============
test_cases = [
TestCase(
input="北京今天天气怎么样?",
expected_output="包含温度和天气状况的回答",
expected_tools=["get_weather"]
),
TestCase(
input="计算 (5 + 3) * 7",
expected_output="56",
expected_tools=["multiply", "add"]
),
]
evaluator = AgentEvaluator(my_agent)
report = evaluator.run(test_cases)
print(f"成功率: {report['success_rate']:.2%}")
print(f"平均成本: ${report['avg_cost']:.4f}/任务")
print(f"平均延迟: {report['avg_latency']:.2f}秒")
九、pass@k 与 pass^k:可靠性的两面#
pass@k:k 次内至少成功 1 次#
含义:给你 k 次机会,至少成功 1 次就算通过。
例:pass@1 = 70%,pass@3 = 90% 表示第一次成功率 70%,但给 3 次机会就能 90% 成功。
适用:评估 Agent 的潜力上限。
pass^k:k 次全部成功#
含义:k 次都得成功才算通过。
例:pass^3 = 50% 表示连测 3 次全部成功的概率只有 50%。
适用:评估 Agent 的可靠性(生产环境更需要)。
反直觉:很多 Agent pass@1 看着很高(80%+),但 pass^5 掉到 30%——稳定性差才是生产环境的真正瓶颈。
十、和 L1-L6 的连接#
| 课程 | 在评估体系中的位置 |
|---|---|
| L2 ReAct | 轨迹评估的基础(每一步都是评估单元) |
| L4 Tool Use | 工具调用准确率、参数准确率是核心评估指标 |
| L5 LangGraph | Checkpoint 让"轨迹回放"成为可能 |
| L6 多 Agent | Supervisor 评估 + Worker 评估 = 两层评估 |
| L7 Reflexion | 元认知评估(Agent 评估自己) |
十一、动手时间:30 分钟设计评估方案#
请你为以下两个 Agent 设计评估方案:
场景 A:自动 SQL 生成 Agent#
输入:自然语言问题(如"上月销量前 10 的商品") 输出:SQL 查询
请设计:
用什么评估方法?(HumanEval 式?LLM-as-Judge?人工?)
测试集怎么构造?
评估指标选哪些?
pass@k 还是 pass^k?
场景 B:客服对话 Agent#
输入:客户问题 输出:对话回复
请设计:
测试集怎么构造?(真实对话历史?人工编写?)
主要评估指标?(成功率?用户满意度?响应速度?)
LLM-as-Judge 的 prompt 怎么写?
怎么避免"位置 bias"(LLM 偏好第一个或最后一个选项)?
📋 场景 A 参考方案(点击展开)
场景 A:SQL 生成 Agent#
评估方法:执行式评估为主 + LLM-as-Judge 辅助
测试集:
从生产环境抓 100 个真实查询
准备 50 个标准答案(人工编写)
覆盖简单查询、复杂 JOIN、聚合、子查询等场景
评估指标:
主指标:执行成功率(在测试数据库上跑查询,成功返回结果)
次指标:结果准确率(结果与标准答案匹配)
体验指标:SQL 复杂度(行数越少越好)
成本指标:Token 消耗
pass@k:用 pass@3(给 Agent 3 次重新生成的机会)
优势:执行式评估绝对客观——要么 SQL 能跑通,要么不能。
十二、小结#
| 知识点 | 一句话回顾 |
|---|---|
| 元认知 | Agent 对自己输出的可靠性进行评估(置信度、自一致性、多模型投票) |
| 三大评估层级 | 任务级(结果)+ 轨迹级(过程)+ 体验级(用户) |
| 评估方法 | 人工 / 执行式 / LLM-as-Judge / 轨迹相似度 |
| pass@k vs pass^k | pass@k 评估潜力,pass^k 评估可靠性 |
| 主流 Benchmark | HumanEval(代码)/ SWE-bench(软件工程)/ GAIA(通用)/ WebArena(浏览器) |
| LLM-as-Judge 注意 | 避免位置 bias、长度 bias、自我偏好 |
十三、进阶模块完结 & 课程总结#
🎉 恭喜你完成了 L1-L8 主课程 + 进阶模块!
完整能力矩阵#
| 能力维度 | 对应课程 |
|---|---|
| 概念理解:解释 Agent、ReAct、Function Calling、Multi-Agent | L1-L2 |
| 实战能力:smolagents / 手写 / LangGraph 跑通 Agent | L3-L5 |
| 架构设计:多 Agent 系统设计、Planning 高级模式 | L6、L7 |
| 前沿协议:MCP 标准化、Agent 工程化 | L11 |
| 质量保障:元认知、评估体系、Benchmark | L8 |
转岗面试高频考点清单#
| 考点 | 复习哪节课 |
|---|---|
| "Agent 和 Chatbot 区别" | L1 |
| "ReAct 循环是什么" | L2 |
| "Tool Use 底层原理" | L4 |
| "Function Calling 怎么工作" | L4 |
| "LangGraph 的状态图怎么设计" | L5 |
| "多 Agent 怎么协作" | L6 |
| "MCP 协议是什么" | L11 |
| "Plan-and-Execute vs ReAct" | L7 |
| "Reflexion 为什么有效" | L7 |
| "怎么评估 Agent 质量" | L8 |
接下来可以做的实战项目#
个人助理 Agent(L3-L5 整合):能查日历、发邮件、订餐厅
自动代码审查系统(L6 Manager-Worker):输入 PR,输出审查报告
GAIA Final Project(HF 认证):完成 HF 课程的期末项目拿证书
自己的 MCP Server(L11):写一个对接内部系统的 MCP Server
生产级 Agent 评估平台(L8):基于上面的 Eval Harness 搭建
十四、Sources#
src-001 — Microsoft AI Agents for Beginners · T1 · 05-evaluation
src-002 — Hugging Face Agents Course · T1 · Course
NVIDIA Technical Blog · T1 · How to Evaluate AI Agents
HumanEval 论文 · T1 · arXiv:2107.03374
SWE-bench · T1 · swebench.com
Reflexion 论文 · T1 · arXiv:2303.11381
💬 有疑问? 试试问我:"我的 Agent pass@1 高但 pass^5 低怎么办?"、"LLM-as-Judge 的 bias 怎么消除?"、"生产环境的 Agent 评估该多久跑一次?"——我会用代码或比喻为你解答。
🎁 继续彩蛋:你已经有 9 节课的完整体系,可以让我帮你做任何深度拓展——比如"把 L5 LangGraph + L7 Plan-and-Execute + L8 元认知整合成一个生产级 Agent",或者"用 L6 + L11 做一个 MCP 多 Agent 系统"。告诉我你的目标。
1. 某 Agent 的 pass@1 为 80%,但 pass^5 只有 30%。这个结果最合理的解读是?
2. 下列哪种行为最典型地体现了元认知中的「反思」层(L3)?
3. 使用 LLM-as-Judge 评估 Agent 输出时,下列哪种做法可以有效减少评估偏差?