先分清是哪一环的问题
回答质量差时要先判断问题在召回还是在重排:用人工挑出的理想片段做对照,看它有没有进入检索候选池。理想片段根本不在候选池里,是召回问题(切分、embedding、过滤条件、索引参数);在池内却没进最终上下文,是重排或截断问题(重排模型、候选数量、上下文预算)。两者修复动作完全不同,判断错了会白花力气。
基本信息
| 召回覆盖 | gold 片段出现在 top-k 候选池中的比例 |
|---|---|
| 终选覆盖 | gold 片段出现在最终送入生成的片段中的比例 |
| 诊断顺序 | 先看候选池,再看终选,最后才动生成参数 |
| 常见结论 | 召回低改切分与模型,终选低改重排与预算 |
典型使用场景
- 效果下滑排查:先定位层次再动参数,避免盲目换模型
- 重排上线验证:确认重排把候选池里的 good 片段提到了前面
- 上下文预算调整:终选覆盖低时检查是不是片段数被截断
- 切分方案评审:用召回覆盖数据判断切分是否把答案切碎
- 模型选型对比:候选池覆盖率是比最终答案更干净的对照指标
分层定位脚本
分层定位脚本
pool = {q: [c.id for c in retrieve(q, top_k=50)] for q in queries} # 候选池
final = {q: [c.id for c in final_top8[q]] for q in queries} # 送生成
gold_in_pool = {q: [g in pool[q] for g in gold[q]] for q in queries}
gold_in_final = {q: [g in final[q] for g in gold[q]] for q in queries}
print("召回覆盖:", sum(map(all, gold_in_pool.values())) / len(queries))
print("终选覆盖:", sum(map(all, gold_in_final.values())) / len(queries))
症状与修复方向
| 现象 | 优先排查 | 修复方向 |
|---|---|---|
| 候选池里没有 gold | 召回环节 | 切分粒度、embedding 模型、过滤条件、top-k 大小 |
| 池内有 gold 但没进最终上下文 | 重排环节 | 重排模型、候选数量、上下文预算与截断 |
| 两者覆盖率都低 | 切分与数据质量 | 先查解析是否丢内容,再看切片是否割裂 |
| 指标忽高忽低 | 参数与语料版本 | 核对索引参数与语料快照是否一致 |
召回覆盖高、终选覆盖低,就优先看重排与截断;两者都低,先看切分与 embedding 质量,再考虑换库或加混合检索。
top-k 是候选池的边界:设得太小,正确答案先天进不来,后续无论怎么调重排都救不回来,排查时先把它放宽一档做对照。