相似不等于相关
算出来最像的那几段,未必能回答你的问题。这是检索最大的误差来源。
算出来最像的那几段,未必能回答你的问题。这是检索最大的误差来源。 向量检索会给每段文字打一个相似度分数,然后取最高的几段送给模型。听起来很合理,但这里藏着一个致命的错位:分数高的,未必是能回答问题的。 你会遇到的现象:
- 知识库明明有正确答案,它就是没找出来
- 它引用了一段看起来很相关的原文,结论却是反的
- 调高召回数量之后好了一点,但成本和乱答也一起涨了
「像」和「有用」的落差
向量算的是用词和语境的接近程度,本质上是把词映射到高维空间再量距离。word-embedding-wiki而「能不能回答这个问题」是另一件事,两者只是大致相关,不是一回事。
看那张图。用户问「七天了还能退吗」,三个候选:
排第一的是一个目录页——标题里全是「退货」「常见问题」,用词高度重合,所以分数最高。但它只有标题没有内容,一句有用的话都没有。
排第二的是另一个类目的例外条款——「本类目商品不支持七天无理由退货」。用词几乎和问题一模一样,分数很高。但它说的是不支持,而且是另一个类目的。模型拿到这段,很可能直接答「不能退」。
真正的答案排第三。如果系统只取前两名,正确答案根本没进到模型眼前——而模型对此一无所知,它会用手上那两段,自信地给出一个错误回答。
这就是知识库问题里最难查的一类:**看起来它引用了原文,有理有据,结论却是错的。**用户会更容易相信它,因为它给了出处。
四种典型的误检
把常见情况归一下类,排查时能快很多。
空壳片段:目录、索引、标题列表、导航——关键词密度极高,但没有正文。
反向条款:「不支持」「除外」「以下情况不适用」——向量对否定不敏感,用词几乎一致。
邻近话题:问退款,找到了换货、售后、投诉——同一语义区域,距离确实很近。
过期版本:旧版政策、历史文档和新版用词几乎一样,向量分不出新旧。
后两类最危险,因为输出看起来完全合理,只有懂业务的人才能发现引用错了。「过期版本」这一类值得特别提醒:向量空间里没有时间概念,一份 2023 年的旧政策和 2026 年的新政策,坐标可能几乎重叠。光靠检索是分不出来的,必须在数据层面处理——要么下线旧文档,要么给每段带上生效时间并在检索时过滤。
怎么缓解
这个问题消灭不掉,但有几个手段能显著改善,按投入产出排序:rag-failure-points
**一、多召回,再重排。**这是最标准的做法。第一步用向量召回 20 到 50 段(宁多勿少),第二步用一个专门的重排模型,逐段判断「这段到底能不能回答这个问题」,取最好的三五段送给模型。
重排模型比向量更懂「相关性」,因为它是把问题和片段放在一起判断的,而不是各自算坐标再比距离。这一步通常是 RAG 效果提升最明显的一环,成本也不高。
**二、清理掉空壳内容。**目录页、导航、索引这类东西,在建库时就该排除掉。这一步几乎零成本,但能干掉一整类误检。
**三、给片段带上出处和时间。**每段存的时候附上来源文档、章节、生效日期。检索时可以按时间过滤,回答时也能让模型标明引用来源——标了出处,业务方一眼就能看出引用错没错,问题从「查不出来」变成「一看就知道」。
**四、设一条相似度下限。**如果最高分都很低,说明库里根本没有相关内容,这时候应该让它老实说不知道,而不是硬拿几段不相关的去编。这一条能挡掉不少幻觉。
**五、把测试样例建起来。**和提示词迭代一样:准备一组真实问题和它们对应的正确文档段,每次调整检索策略就跑一遍,看正确的那段有没有进前几名。没有这把尺子,所有的调优都是在猜。
