对应作品:谈锋 · 过程记录:2025年6月周报

谈锋要解决的问题很具体:非结构化面试里,对话又长又绕,模型和人都需要「刚才到底问了什么、答了什么」。我把面试材料丢进 RAG 之后,第一次检索几乎不能用。

这不是一篇工具安利。只写我改过的三处,以及现在仍然差的地方。

差在哪

相关文档召回率偏低,表现不是「完全搜不到」,而是搜到一堆沾边但不该回答的段落。

典型情况:

  • 当前问题在追问「你刚才那个项目的失败原因」,检索却把上一轮自我介绍的开场词送回来。
  • 一段对话从中间被切断,召回结果只有半句,模型补全时开始编。
  • 同义问法(「为什么停」「后来为啥不做了」)对不上同一段复盘。

所以问题不在「有没有向量库」,在切分、向量、排序三步各自把错误放大。

chunk:不要按固定字数一刀切

最初按固定长度切。面试材料的自然边界是一轮问答,不是第 500 个字。固定窗口会把「问题」和「回答」拆开,检索到半截。

我改成按面试轮次 / 问题块切:一轮问答应尽量落在同一个 chunk 里,过长再在轮次内部按段落拆,而不是从句子中间切开。

改完之后,召回结果至少是「一整轮」,模型才有上下文可写。这是我亲手改过、也最愿意被追问的一步。

embedding:通用向量分不清「追问」

换 embedding 之前,同类追问散得很开。通用中文向量对「刚才那个 / 上一问 / 继续说」这种指代几乎没帮助。

我换成更贴中文问答的模型之后,同一问题的变体才开始聚在一起。这里不写型号排行——型号会过时,后面有空再单独记一次对比。

重排:先多召回,再往当前问题靠

只做向量检索时,「相关」很多,真正能当面试上下文的很少。我加了重排:先多取一些候选,再用和当前问题更贴的分数往前排。

重排前后的差别,用现象说:

  • 重排前:列表里前几条看起来都和「项目」有关,但不是这一问。
  • 重排后:和当前问句同轮次、同主题的段落才会到前面。

没有内部数据可以公开对比表。能讲的是动作:多召回 → 重排 → 再送给模型。不是接完向量库就结束。

还没解决什么

口语化指代仍然不稳。「刚才那个」指向哪一轮,检索经常猜错。渐进式总结能把长对话压短,但压错重点比检索错更难发现。

MCP 那一块,我不是只读了文档。当时资料少、官方说明偏抽象,我对照开源实现把一次完整调用跑通,才看清模型和外部工具怎么解耦。多 agent 早期会改同一处代码互相覆盖,后来靠模块划分和接口约定才压下去——那是协作问题,不是 RAG 本身。

还可以继续想的

  • 为什么不继续加长 chunk,而要按轮次切?
  • 重排和换 embedding,哪一步对你当时的召回更关键?
  • 指代消解你准备怎么做,还是决定先不做?

答不出数字的地方我不会编。能讲的是:我改过切分、换过向量、加过重排,以及现在卡在哪。

谈锋:RAG 检索从差到能用

作者

Jiangwei

发布日期

2026 - 08 - 28