RAG
下面的是目前整理的有关RAG的面试题,如果有谬误欢迎指正,大部分都来自小林coding
1. 什么是 RAG?详细描述一个完整 RAG 系统的详细工作流程?
RAG 全称是 Retrieval-Augmented Generation,就是检索增强生成。我理解它解决的核心问题是,LLM 的知识在训练完之后就固定了,遇到私有数据或者最新的信息它就答不上来。RAG 的做法是在生成答案之前,先去外部知识库里检索相关内容,然后把检索结果和用户的问题一起交给 LLM,让它基于这些上下文来回答。本质上就是给 LLM 开了一个开卷考试的口子,不用再靠死记硬背了。
一个完整的 RAG 系统分离线和在线两个阶段。离线阶段的目标很明确:在用户提问之前,就把知识库建好。这一阶段只做一次,建好了后面反复用。第一步是文档加载。把各种格式的原始数据读取进来,可以是 PDF、Word、Markdown、网页、数据库记录等。接下来是文档切割(Chunking),然后是整个离线阶段最核心的一步,Embedding(向量化)。最后一步是入库,把每个 chunk 的向量和原始文本一起存进向量数据库。
在线阶段是每次用户提问时实时执行的,对响应速度有要求。第一步是Query 处理。然后是向量检索(粗排)。把用户的问题也转成向量,然后去向量库里做相似度搜索,找出向量距离最近的 Top-K 个 chunk。接下来是Rerank(精排),这一步就是为了弥补粗排的不足。最后是生成,把用户问题 + 精排后的 chunk 拼成 prompt,交给 LLM 生成最终答案。
2. 大模型的 RAG 主要用来解决什么问题?
RAG 主要解决三个问题。第一是知识时效性,LLM 训练完知识就固定了,训练截止日期之后发生的事它一无所知;第二是私有知识覆盖,公司内部文档、行业专有数据根本没有机会进训练集,LLM 对这些内容是空白的;第三是幻觉问题,没有知识依据时 LLM 容易「自己发挥」编出一个听起来合理但实际错误的答案,给了它参考资料之后幻觉就少很多。这三个问题的根源都是同一件事,知识被固化在了模型参数里。RAG 的解法是把知识存到外部,用的时候实时检索注入,彻底绕开了参数里的知识限制。
3. 相比直接微调 LLM,RAG 解决了什么问题?微调和 RAG 各自的优劣势是什么?
我的理解是这两个东西解决的不是同一层面的问题,不是谁替代谁的关系。微调是把新知识直接烧进模型参数里,适合改变模型的行为风格或者培养深度的专业能力;RAG 是在推理的时候实时检索注入知识,适合知识需要频繁更新、或者需要有溯源的场景。如果非要让我选一个,知识库类的问答系统我会首选 RAG,成本低而且可以随时更新。如果是要让模型学会特定的输出格式或者行业语气,那微调更合适。实际上这两个方案也可以组合用,先微调再套 RAG,微调解决「怎么说」,RAG 解决「说什么」。
4. RAG 中的文档是怎么存的?粒度是多大?详细说说文档切割(Chunking)策略?
文档不能直接存进向量库,必须先切成小块也就是 chunk,每个 chunk 分别向量化之后存成一条记录。每条记录我理解有三个核心部分:向量用于相似度检索,原始文本是检索命中之后塞给 LLM 读的内容,metadata 是来源文件、页码这些附加信息,用于过滤和溯源。这两个东西缺一不可,向量负责找到,原文负责阅读。切割粒度没有固定答案,通常 500 到 1000 个 token 是一个合理的起点,但更重要的是根据文档类型来选策略,普通文本用固定大小加重叠,有标题结构的文档按语义边界切,代码按函数切,如果既要检索精度又要上下文完整的话,我会用父子切割,也就是小块检索、大块返回。
5. 怎么规避语义被切割掉的问题?
我的思路是从两个方向来规避这个问题。第一个方向是切的时候就不要在语义中间截断,用重叠切割和语义边界切割来保证每个 chunk 内容是完整的,也就是按句子、段落这些自然的边界来切。
第二个方向是切完之后用检索策略把上下文补回来,核心方案是句子窗口检索,命中一个句子就把周围几句一起返回给 LLM;另外还有父子切割,小块检索命中、大块内容输出。
还有一个我觉得比较有价值的方案,是 Anthropic 提出的 Contextual Retrieval,在做 Embedding 之前先让大模型看着整篇文档为每个 chunk 生成一段背景说明,把这段背景和 chunk 拼在一起再向量化,从根本上解决孤立 chunk 没头没尾的问题。
6. 在 RAG 中 Embedding 究竟是什么?如何选择和评估一个 Embedding 模型?
Embedding 我理解就是把一段文本转成一串数字向量的过程。它有一个很关键的特性,就是语义相近的文本,转出来的向量在数学空间里的距离也近。RAG 里的语义检索就是靠这个实现的,不是关键词匹配,而是看两段内容的意思相不相近。选模型的话,我主要看三个维度:第一是中文支持,中文场景我会优先选 BGE 系列,效果其实比 OpenAI 的模型还要好;第二是向量维度,维度越高精度越好,但存储成本也越大;第三是最大输入长度,这个决定了能处理多长的 chunk。评估这块我的建议是不要只看通用排行榜,一定要在自己的业务数据上跑召回测试(Hit@K测试),那个才是真正有参考价值的。(「中文场景用 bge-large-zh-v1.5 或 Qwen3-Embedding,在自己的业务数据上 Hit@5 达到 0.8 以上,最终根据测评结果选的」)
7. Embedding 有哪几种算法你了解过吗?
Embedding 算法大致经历了三代演进。第一代是静态词向量,以 Word2Vec 和 GloVe 为代表,把每个词映射成固定向量,但同一个词不管上下文是什么,向量永远不变,处理不了多义词。第二代是以 BERT 为代表的上下文相关向量,同一个词在不同语境下有不同的向量,表达能力大幅提升,但 BERT 本身输出的是 token 级别的向量,两个句子要比较相似度就必须拼在一起跑,百万条文档就要跑百万次,检索速度完全不可接受。第三代是以 SBERT、SimCSE、BGE 为代表的句子级对比学习 Embedding,专门为「两段文本有多相似」这个任务优化,能提前把所有文档向量算好存起来,查询时只需算一次,是 RAG 场景的标配
8. 什么是向量数据库?有没有做过向量数据库的对比选型?
向量数据库是专门用来存储和检索高维向量的数据库,核心能力是近似最近邻搜索,也叫 ANN,能在百万甚至亿级的向量里快速找出最相似的几条。普通关系型数据库的索引结构对高维向量基本上是失效的,所以需要专门的数据库来处理这个场景。我自己做过一些选型,本地开发阶段我用 Chroma,零配置上手极快;生产环境的中小规模我推荐 Qdrant,性能不错、API 也比较简洁;如果到了超大规模就要考虑 Milvus 了,字节和小米都在用;不想自己运维的话 Pinecone 是一个云托管的选项;如果项目里已经有 PostgreSQL,也可以直接用 pgvector 插件,不用引入新组件。
向量数据库之所以能做到毫秒级检索,秘密全在索引算法上。目前主流的索引算法有两种:先说 HNSW,这是目前精度最高的 ANN 算法之一。它构建的是一个多层图结构,查询时从最上层的稀疏图开始导航,逐层收窄范围,最终在底层找到最近邻。HNSW 的优点是召回率高、查询速度快;缺点是建索引时内存消耗大,不适合内存极度受限的场景。Qdrant、Milvus、Chroma 默认都用 HNSW。
IVF是另一种思路,它先对向量做聚类,把相似的向量分进同一个「桶」里,查询时只搜最相关的几个桶,而不是全量遍历。IVF 的优点是内存占用小、适合超大规模;缺点是精度比 HNSW 略低,需要调参。Milvus 在超大规模场景下会用 IVF 系列索引。
HNSW 的内存消耗和向量数量成正比,到了亿级规模内存可能扛不住。IVF 用聚类换内存,牺牲一点精度就能处理超大规模数据,两者各有适用场景
9. 讲讲你用的向量数据库?数据量级是多大?性能如何?遇到过性能瓶颈吗?
我们生产环境用的是 Milvus,数据量级在百万条向量左右,每条是 1024 维,用 HNSW 索引,单次查询的延迟在 20 到 50 毫秒。选 Milvus 主要是因为它支持分布式部署和读写分离,适合数据量大、并发高的场景。我遇到过两个比较典型的瓶颈。第一个是内存压力,百万级的 1024 维向量光原始数据就要好几个 GB,后来我们开启了标量量化 SQ8,把 float32 压成 int8,内存直接降到原来的四分之一。第二个是大批量写入的时候会触发后台 Segment 合并,影响查询延迟,我们的解法是把批量写入改到业务低峰期,分批小批次写入。
10. 你使用 RAG 给大模型一个输入,系统是怎样的工作流程?
当你把一个问题输入给 RAG 系统,它不会直接丢给大模型,而是先经历一套「检索 -> 整理 -> 生成」的流水线。具体来说:系统先对问题做预处理(改写成更适合检索的形式),然后把问题向量化,去向量库里找最相关的文档片段,再经过精排筛掉噪音,最后把筛选出来的片段和问题一起拼成 Prompt 交给大模型,大模型基于这些「参考资料」生成最终答案。整个流程的核心目标只有一个:让大模型在回答时有真实的知识作为依据,而不是凭空发挥。
11. 请你介绍一下向量检索和关键词检索的区别?
关键词检索(BM25 这类)靠的是词频统计,看查询词在文档里出现了多少次,擅长精确命中;向量检索靠的是语义空间里的距离,能理解「换了种表达方式的同一个意思」,擅长模糊语义匹配。两者各有盲区:BM25 遇到同义词就没辙,向量检索遇到专有名词、产品型号这类精确词就容易漏。所以 RAG 系统里通常两路都跑,向量检索捕获语义相关的内容,BM25 精准命中关键词,再用 RRF 算法把两路结果合并,这样覆盖面比单路宽很多。
12. 如何润色用户的 Query(Query Rewrite)?目的是什么?
我用 Query Rewrite 主要是为了弥补用户提问方式和知识库文档表述之间的语义鸿沟。用户的问题往往口语化、模糊、带缩写,而文档写的是正式书面语,向量相似度天然偏低,导致该召回的内容没被召回。我接触过的方法主要有四种:第一是直接改写,让 LLM 把口语化的问题转成更精准的表述;第二是 Query 扩展,补充相关关键词;第三是 HyDE,让 LLM 先生成一个假设答案,然后用答案的向量去检索;第四是 Step-back Prompting,把具体问题往上抽象一层,检索更通用的背景知识。
13. 什么是多路召回?具体怎么做?
多路召回就是同时用多种不同的检索方式去捞候选内容,然后合并排序,而不是只靠单一的向量检索。我理解核心出发点是向量检索和关键词检索各有盲区,向量检索擅长语义相似,但对精确词语比如产品型号、缩写、数字效果比较差;BM25 关键词检索正好相反,精确匹配强,但不理解语义。我在项目里常用的组合是向量检索加 BM25 混合检索,再加上多 Query 扩展,也就是把用户问题改写成多个版本分别检索。多路的结果用 RRF 算法融合,最后送进 Rerank 精排。
14. RAG 检索优化策略有哪些?
我理解 RAG 的检索优化可以从四个层次来看:索引层决定知识怎么存,查询层决定问题怎么转换,召回层决定从哪些路径去找,重排序层决定最终哪些内容进入 prompt。每一层都有对应的优化手段,我的经验是单独优化一个层次往往效果有限,线上系统我会组合来用,先靠索引优化和多路召回来保证覆盖率,再用 Rerank 保证精度,如果用户提问质量比较差,再额外加上查询优化。(Parent-Child 索引 + 多Query扩展+多路召回 + Rerank)
15. 了解哪些更复杂的 RAG 范式?
在我的了解里,RAG 的发展经历了三代演进,Naive RAG 是基础的检索加生成;Advanced RAG 在检索前后都加了优化,比如 Query 改写、Rerank、混合检索这些;Modular RAG 是把各个环节做成模块可以任意组合。在这之上还有几个我觉得值得关注的高级范式:Self-RAG 是让 LLM 自己来决定要不要检索,以及评估检索质量;CRAG 是检索质量差的时候自动降级到网络搜索;GraphRAG 是微软推的方案,用知识图谱的社区发现和层次摘要来增强全局理解能力;Agentic RAG 是把 RAG 做成 Agent,支持多轮的动态检索。
16. 在什么场景下,你会选择使用图数据库来增强传统的向量检索?
我的判断是,当业务问题涉及多个实体之间的关联推理的时候,就需要考虑引入图数据库来增强。向量检索有一个根本的局限,它只能做单跳检索,找和问题直接相关的文档,没办法沿着实体之间的关系链做推理。比如你问公司 A 的投资方和公司 B 有什么交集,单纯向量检索就很难处理了,因为答案不在某一段文档里,而是藏在多个节点之间的关系上。这时候图数据库就能发挥作用,沿着关系边一跳一跳地把关联信息收集回来。我接触过的典型场景有企业关系分析、医疗知识图谱、代码依赖关系查询、供应链溯源这些。
17. 如何规避 RAG 系统中大模型的幻觉?
我遇到过的 RAG 幻觉主要有两类。第一类是检索没有召回到相关内容,LLM 没有可用的上下文,靠自身知识在编造答案。第二类是检索内容召回了但 LLM 没有严格遵循,在文档内容的基础上加了自己的推断。我用来规避幻觉的策略主要有四个方向:第一是 Prompt 强约束,明确告知 LLM 只能根据提供的资料回答,资料里没有的就说不知道;第二是检索质量门控,Rerank 分数低于阈值就直接拒答,不让 LLM 在低质量上下文上硬撑;第三是生成后引用核查,每个关键的声明都要在 chunk 里找到来源依据;第四是结构化输出强制溯源,让 LLM 输出 JSON,每条结论必须附上来源编号。其中 Prompt 强约束加检索质量门控是我觉得成本最低、收效最快的组合,生产系统上线前这两个必须做。
18. 怎么量化你的 RAG 效果?
我评估 RAG 效果是分两层来看的。检索层看该召回的有没有召回到,我用 Hit@K 和 MRR 来衡量。生成层看答案对不对、有没有幻觉、和问题相不相关,我主要用 RAGAs 框架,里面的 Faithfulness、Answer Relevancy 和 Context Recall 这三个指标是最核心的。我的建议是一定要在自己的业务数据上跑,不能只看通用排行榜,那个不能代表你的场景。另外线上指标,就是用户的点踩率、追问率、转人工率这些,才是最终的衡量标准,离线指标只是辅助。
19. RAG 知识库如何实现动态与持续更新?
我理解知识库更新的核心挑战是,文档变了,对应的 chunk 和向量都要跟着变,而且要做到增量处理,不能每次全量重建。我们的通用方案是给每个文档算一个内容 hash,通过轮询或者监听数据源变更,检测到文档新增、修改、删除的时候,先清掉旧的向量,再重新切割入库。对于实时性要求比较高的场景,我会用消息队列比如 Kafka 做变更事件驱动,实现秒级的入库。
20. 在实际落地中,你觉得 RAG 最难的地方是哪里?
我觉得 RAG 最难的不是把它跑起来,一个基础的 Demo 一两天就能搭起来,难的是把它调好。工程上最让我头疼的有三块。第一是文档预处理,原始数据的格式五花八门,PDF 里面的表格、图片、嵌套的格式,处理不好就是一堆乱码进了知识库,进去的是垃圾出来的也是垃圾。第二是检索质量的调优,向量召回不准是整个系统效果的天花板,但问题来源很多,Chunking、Embedding、Query 改写,任何一个环节出问题都会影响结果,排查起来很费劲。第三是效果评估,答案对不对很难系统性地衡量,不知道是哪个环节出了问题,优化就变成了瞎猜。