检索、引用与工具轨迹的分层评估
RAG答错可能是没有召回证据、重排丢掉证据、模型忽略证据或引用指向错误文档;只给最终答案一分,不能知道该改哪里。Agent最终结果偶然正确,也可能经过越权工具,过程安全必须单独评估。
检索排名指标
完整标准库实验:相关集合含A和C,检索顺序为B、A、C。
import math
relevant={"A","C"}
ranked=["B","A","C"]
def retrieval_metrics(ranked,relevant,k):
if k<=0 or not relevant:raise ValueError("need positive k and labels")
top=ranked[:k] # 保留原始名次;不能先压缩重复项再把 k 外结果补入。
seen=set()
hits=[]
for item in top:
hits.append(int(item in relevant and item not in seen))
seen.add(item)
precision=sum(hits)/k
recall=sum(hits)/len(relevant)
rr=next((1/(i+1) for i,x in enumerate(top) if x in relevant),0)
dcg=sum(v/math.log2(i+2) for i,v in enumerate(hits))
ideal=sum(1/math.log2(i+2) for i in range(min(k,len(relevant))))
return precision,recall,rr,dcg/ideal
p,r,rr,n=retrieval_metrics(ranked,relevant,2)
assert p==.5 and r==.5 and rr==.5 and 0<n<1
assert retrieval_metrics(['B','B','A'],{'A'},2)[:3]==(0,0,0)
assert retrieval_metrics(['B','B','A'],{'A'},3)[2]==1/3
print(p,r,rr,n)Precision@k按本题固定k作分母,少于k个结果仍保留惩罚;Recall@k分母是真实相关文档数;MRR是多查询RR平均;NDCG比较当前位置折损与理想排序,本例为二值相关。重复项仍占原始排名位置,但同一相关ID只获得一次命中信用;Precision、Recall与DCG不重复奖励,RR按原始位置计算。若检索系统本身在排序前去重,应把那个实际输出作为另一套待测结果,不能评估时偷偷压缩名次。无答案查询单独测是否错误召回/幻答,不强行令其recall为1。
证据与答案分开判
上下文相关性问资料能否帮助回答,忠实度问答案是否被提供资料支持,正确性问现实或标注事实是否成立。模型忠实复述过期政策仍可能现实错误。引用准确性检查文档ID存在、位置可达与片段支持命题,不能只数方括号数量。
工具轨迹检查是否需要调用、工具选择、参数、服务端权限、错误处理、重试与停止。使用任务验收查询效果账本,不能靠模型“已退款”判断。反事实实验分别移除证据、替换错误工具结果、撤销权限,观察是否拒答或改路径;每次只改一个条件。
记录回放能验证解析与控制流,但真实工具集成、模型选择与质量要另测。写工具回放在沙箱或使用记录替身,禁止重放线上副作用。失败分类保留数据、检索、prompt、模型、工具、解析与业务bug,修复后向固定集补样本。
练习
k=3时precision应2/3、recall为1、RR仍0.5;加入重复A不应超过recall=1。再定义轨迹检查:工具名不在allowed时即失败,即使最终answer正确。