☰
面试官:你的RAG系统里,为什么用户搜“2023年财报”,查出来的却是2022年的?
2026/9/28 21:02:07 网站建设 项目流程

面试官:你的RAG系统里,为什么用户搜“2023年财报”,查出来的却是2022年的?

最近看不少学弟学妹的简历,十个有八个写着“基于大模型的RAG智能问答系统”。用的技术栈也很统一:LangChain + 某款向量数据库。

写这个项目本身没毛病,但面试官稍微往深挖一点,很多人就扛不住了。最典型的一个连环炮就是:“如果用户问‘2023年阿里财报里提到了什么’,但数据库里同时有2022年和2023年的财报,你的系统会不会把2022年的召回给大模型?为什么?”

很多同学这时候就懵了,回答“向量相似度高就会召回”。面试官紧接着问:“那怎么解决呢?”

我们今天把这个问题拆透。

为什么向量检索对年份“脸盲”?

很多人把向量检索(Dense Retrieval)当成了万能药。实际上,Embedding 模型是靠计算语义相似度来工作的。

在语义空间里,“2023年阿里财报”和“2022年阿里财报”这两句话的语义结构几乎一模一样,只有数字不同。绝大多数 Embedding 模型在训练时,并没有对微小的数字差异做强惩罚。这就导致这两句话算出来的余弦相似度可能高达 0.95 以上。

如果 2022 年的财报里刚好有一段话,文字表述和用户的提问方式更贴近,它的相似度得分甚至会反超 2023 年的真实财报。最后扔给大模型的上下文全是错的,大模型自然就开始一本正经地胡说八道。

怎么解决?别光说加 Prompt

有人觉得可以在 Prompt 里加一句:“请严格注意年份”。
这是没用的。因为 RAG 的瓶颈在“检索(Retrieval)”,如果检索出来的 Top-K 文档里根本就没有2023年的财报,大模型再怎么注意年份也变不出正确答案。

真正在工程落地上,要从检索环节解决,通常有三条路。

1. 混合检索(Hybrid Search):向量 + BM25

既然向量检索对具体数字、专有名词不敏感,那就把传统的关键词检索加回来。BM25 算法就是靠词频(TF-IDF 的进阶版)吃饭的。

用户搜“2023年”,BM25 就会去倒排索引里死磕“2023”这个词。没有这个词的文档,得分就会很低。

实际落地时,我们做双路召回:

  1. 跑一次向量检索,拿到 Top-K。
  2. 跑一次 BM25 检索,拿到 Top-K。
  3. 用 RRF(倒数秩融合)算法把两边的结果合并重排。

Elasticsearch 8.x 或者 Milvus 目前都原生支持这种混合检索。这是性价比最高的基础改动。

2. 元数据过滤(Metadata Filtering)

如果文档带有明确的结构化属性(比如发布时间、文档类型、作者),最硬核的办法是在向量检索前(或检索后)加过滤条件。

你在切分文档(Chunking)存入向量数据库时,别只存 text 和 vector,要把时间戳也存进 Metadata 里。

当用户提问时,怎么知道要加什么过滤条件?这就需要大模型的 Function Calling(或者叫做 Query 理解)。

流程是这样的:

  1. 用户提问:“2023年财报说了啥?”
  2. 先让大模型跑一个意图识别/实体抽取,提取出{"year": "2023"}。
  3. 拼装查询条件。比如在 Chroma 或 Qdrant 里,带上where={"year": "2023"}去做向量检索。

这种做法极其精准,搜出来的绝对是2023年的东西。代价是多了一次大模型调用,增加了耗时。

3. Query 改写(Query Rewrite)

有时候用户的提问太口语化,比如“去年的财报”。向量数据库根本不知道“去年”是哪一年。

可以在检索前,让一个小参数模型或者大模型做一次 Query Rewrite。结合系统当前时间,把“去年的财报”改写成“2023年 财报”,然后再去过混合检索。这招在真实业务里非常管用。

结语

回到面试现场。如果面试官问你这个问题,不要慌。

先点出原因:Embedding 对细微数字和实体的敏感度低,容易导致语义相似但事实不符的文档得分偏高。
再给方案:轻量级用 BM25 双路召回加 RRF 重排兜底;对时间、组织等确定的结构化字段要求高的业务,用大模型抽取实体,再做向量库的 Metadata 硬过滤。

把这几步讲清楚,面试官自然知道你是真正下场写过、调优过 RAG 系统的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询