过去一年,Search Agent 在 BrowseComp 等评测上的准确率从约 30% 快速提升到 90% 以上。这个数字说明模型进步很快,也暴露出一个评测难题:当大多数强模型都能取得高分,基准便难以继续区分它们的搜索、推理和证据组织能力。
美团开源 LoHoSearch,试图用知识图谱校准我们对搜索智能体能力的判断。它值得关注的不只是更难的题目,而是一种评测思路的变化:不要只检查最终答案,还要关注智能体能否沿着多条实体关系找到信息、拼接证据,并形成可验证的结论。
90% 准确率为什么未必意味着问题已经解决
一个搜索基准接近饱和,通常存在几种可能:模型确实掌握了目标能力;题型已经被训练数据或固定策略覆盖;评分指标只检查最终文本,没有充分检查推理路径;题目需要的搜索深度不足,模型通过一次检索或常识猜测就能答对。
因此,单个准确率很难回答下面这些工程问题:
- 智能体是否找到了正确实体,还是碰巧生成了正确答案?
- 它引用的页面是否真正支持结论?
- 答案需要跨越多个关系时,是否遗漏了中间节点?
- 搜索失败来自检索、实体消歧、路径规划,还是最终归纳?
- 面对同名人物、时间变化和互相冲突的来源,结果是否稳定?
当模型得分都集中在 90% 到 95% 之间时,这些差异会被一个总分掩盖。更有价值的评测需要扩大能力差异,并解释分数为什么不同。
知识图谱让“复杂搜索”变得可测量
知识图谱可以把一道搜索题表示为实体、关系和约束。例如,一个问题可能要求智能体从某位人物出发,找到其参与的组织,再找到组织发布的项目,最后核对项目发生的时间。对应路径可以抽象为:
人物 --任职于--> 组织 --发布--> 项目 --发生时间--> 年份
这种表示带来三个直接收益。
第一,出题者可以控制路径长度和分支数量。两跳问题与五跳问题不再只是主观上的“简单”和“困难”,而是可以按图结构分层。
第二,评测可以定位错误。智能体可能找对人物,却连接到了错误组织;也可能路径完全正确,但使用了过期时间。节点和边提供了比“答案错误”更细的诊断信号。
第三,图结构适合构造干扰项。同名实体、相邻年份、关系相似但方向相反的节点,都能测试智能体是否真正完成了消歧与约束检查。
不过,知识图谱不是天然正确的裁判。图谱可能缺边、关系可能过期,现实世界也可能存在多个都合理的答案。因此,高质量评测仍需要保留证据快照、时间边界和人工复核机制。
不要只打一个分:拆开搜索链路
对于基于知识图谱的搜索评测,可以同时记录以下指标:
| 指标 | 关注的问题 |
|---|---|
| 最终答案准确率 | 结论是否正确 |
| 实体命中率 | 是否识别并访问了关键实体 |
| 关系覆盖率 | 是否完成了必要的图路径 |
| 证据支持率 | 引用内容是否支撑对应陈述 |
| 路径效率 | 是否进行了大量无关搜索 |
| 稳定性 | 多次运行是否得到一致结论 |
这套拆分尤其适合评估工具调用型智能体。两个模型可能最终答案相同,但一个用了三次有效搜索,另一个发起二十次请求并引用了无关页面。只看准确率时两者没有区别,部署成本和可靠性却完全不同。
评分也不宜盲目奖励最短路径。真实搜索中,交叉验证本身有价值。更合理的做法是惩罚无关调用,同时允许智能体为关键事实寻找第二来源。
可以这样实践:实现一个最小图路径评测器
下面是一个不依赖第三方库的最小示例。它不是 LoHoSearch 的官方接口,而是根据“用知识图谱诊断搜索过程”这一思路构造的可运行原型。保存为 evaluate_agent.py 后,可直接使用 Python 3 运行。
from dataclasses import dataclass
from typing import Iterable
@dataclass(frozen=True)
class Edge:
source: str
relation: str
target: str
# 评测集给出的标准证据路径
GOLD_PATH = [
Edge("研究员甲", "任职于", "机构乙"),
Edge("机构乙", "发布", "项目丙"),
Edge("项目丙", "发布日期", "2024"),
]
GOLD_ANSWER = "2024"
def evaluate(answer: str, trace: Iterable[Edge]) -> dict:
trace = list(trace)
gold_edges = set(GOLD_PATH)
predicted_edges = set(trace)
matched = gold_edges & predicted_edges
irrelevant = predicted_edges - gold_edges
return {
"answer_correct": answer.strip() == GOLD_ANSWER,
"relation_coverage": round(len(matched) / len(gold_edges), 3),
"irrelevant_edge_count": len(irrelevant),
"missing_edges": [
f"{e.source} --{e.relation}--> {e.target}"
for e in GOLD_PATH
if e not in predicted_edges
],
}
if __name__ == "__main__":
# 将这里替换为智能体实际返回的结构化搜索轨迹
agent_trace = [
Edge("研究员甲", "任职于", "机构乙"),
Edge("机构乙", "发布", "项目丙"),
Edge("项目丙", "发布日期", "2023"),
]
result = evaluate(answer="2023", trace=agent_trace)
for key, value in result.items():
print(f"{key}: {value}")
运行命令:
python evaluate_agent.py
这个例子会指出答案错误、路径只覆盖了三条标准关系中的两条,并明确列出缺失的时间关系。接入真实智能体时,可以把每次检索产生的实体和关系写入 JSON,再转换为 Edge 对象进行评估。
实践中还应增加三类数据:每条关系对应的证据 URL 或文档编号、证据采集时间,以及实体别名列表。这样才能区分“模型没找到”“名称没有对齐”和“事实已经发生变化”。
引入新基准时应检查什么
LoHoSearch 所代表的方向提醒我们,基准的目标不是制造一个更难看的排行榜,而是持续暴露系统尚未解决的问题。团队在采用这类评测时,可以检查以下事项:
- 题目是否覆盖不同路径长度、分支数和实体歧义程度。
- 标准答案是否绑定证据与时间,避免把动态事实当成永久真值。
- 是否同时保存最终答案和工具调用轨迹。
- 评分是否区分检索失败、路径失败、证据失败与生成失败。
- 是否评估多次运行的波动,而不是只保留最好的一次。
- 是否隔离评测集,降低题目和答案进入训练数据的风险。
更困难的题目只能暂时延缓饱和。真正可持续的搜索智能体评测,应把图结构、证据质量、执行成本和稳定性放进同一套观测体系。这样,当模型再次拿到 90% 以上的准确率时,我们仍然能够回答最关键的问题:它究竟掌握了哪种能力,又在哪一步仍然不可靠。