核心要点

  • 索引阶段(离线):DocumentLoader 加载 → TextSplitter 切块 → Embeddings 向量化 → VectorStore 入库

  • 查询阶段(在线):Retriever 召回相关块 →(可选 Rerank/上下文压缩)→ 拼进 PromptLLM 生成答案

  • 用 LCEL 把 retriever | prompt | llm | output_parser 用管道串成一条可组合的链

  • 生产化补充:返回来源引用(citation)便于溯源,接入 Memory 支持多轮对话

标准回答

整体分两个阶段

RAG 的本质是「先检索、再生成」,工程上拆成离线索引阶段和在线查询阶段,两者通过同一个向量库连接。索引可批量预处理,查询要求低延迟。

索引阶段:把知识灌进向量库

按顺序串四个组件:① DocumentLoader 从 PDF、Markdown、网页、数据库等来源加载原始文档;② TextSplitter(如 RecursiveCharacterTextSplitter)按语义边界切块并设 chunk_size 与 overlap,避免切碎语义;③ Embeddings 把每个文本块编码成向量;④ VectorStoreFAISSChromaMilvus、pgvector 等)持久化「向量 + 原文 + 元数据」,建好索引供检索。

查询阶段:检索增强生成

用户提问后:① Retriever 从向量库做相似度召回 Top-K 相关块;② 可选加 Rerank(交叉编码器精排)或上下文压缩,过滤噪声、提升相关性;③ 把召回内容与问题填进 Prompt 模板,明确要求「仅依据给定上下文作答,缺信息就说不知道」;④ 交给 LLM 生成,再经 OutputParser 整理输出。

用 LCEL 串联

LangChain 表达式语言(LCEL)用管道符把组件拼成链,例如 chain = {"context": retriever, "question": RunnablePassthrough()} | prompt | llm | parser,天然支持流式、异步与并行,便于替换任意环节。

生产化两件事

一是来源引用:在 Prompt 中要求标注引用,并把检索块的 metadata(标题、URL、页码)回传给前端,方便用户溯源、降低幻觉风险;二是多轮记忆:接入 Memory 或基于历史的 Retriever,先把追问改写成独立问题再检索,支撑连续对话。

常见误区

⚠️ 常见踩坑

只堆组件却忽视切块质量——chunk 太大引入噪声、太小切碎语义,overlap 设置不当导致召回失败;查询时用的 Embeddings 模型与建库时不一致导致向量空间错配;不加「仅依据上下文作答」约束和来源引用,模型照样幻觉且无法溯源。

追问

追问 1召回质量差、答案不相关,从哪些环节排查?

按数据流逐段定位:① 切块——chunk_size/overlap 是否合理、是否切碎了语义单元,可换语义切分或调小块;② Embedding——建库与查询是否用同一模型、模型是否适配中文/领域;③ 检索——Top-K 是否过小、是否需要混合检索(向量 + BM25 关键词)覆盖专有名词;④ 精排——加 Rerank 交叉编码器对召回结果重排;⑤ Prompt——上下文是否被截断、指令是否明确。建一套带标注的评测集逐项做消融,才能定位真正瓶颈。

追问 2文档频繁更新,如何维护向量库的增量同步?

给每个文档块带稳定的来源 ID 和内容哈希作为 metadata。更新时对比哈希:内容未变跳过,变了则按文档 ID 删除旧块再写入新块(upsert),删除的文档同步清理对应向量。LangChain 的 indexing API(RecordManager)可自动做去重与增量同步,避免重复 embedding 浪费成本,也防止脏数据残留导致召回过期内容。

追问 3如何评估 RAG 系统的好坏?

分检索与生成两层。检索层看 Recall@K、MRR、命中率,衡量该召回的内容是否被召回。生成层看答案的忠实度(faithfulness,是否只依据上下文、有无幻觉)、相关性(answer relevance)和上下文精确率,可用 RAGAS、LangSmith 等做自动评测,再辅以人工抽检。最好维护一套覆盖典型问法和边界 case 的回归测试集,每次改动跑一遍防退化。

🔗 相似问题

同一考点的不同问法,面试官可能换着问,一起刷更稳

没找到想看的面试题?把你想看的告诉我们 →

延伸学习

按主题分类的相关资源,便于系统复习