项目面试题:RAG 知识问答系统

围绕 RAG 知识问答系统(Itcast qa system)整理的高频面试题,覆盖分块、混合检索、重排序、幻觉治理、微调部署与评估,附参考答案

RAG 知识问答系统(Itcast_qa_system)项目面试题。点击折叠区查看答案。

一、RAG 知识问答系统(Itcast_qa_system)

1:分块策略怎么做的?为什么用父子块?

查看答案
  • 切分参数:子块 300、父块 1200、重叠 50;检索用子块,喂模型给父块

  • 结论:子块用于精准召回,父块为模型生成提供完整上下文;

设置召回topK=10,召回太多噪音大,太少可能答不全

切分基于 LangChain 递归切分器改造:自定义中文分隔符优先级(段落、换行、标点符号),标点保留句尾保语义,超长块递归降级再切;另做表格表头回填,防止切断丢失列名上下文。

2:多少条进入 rerank?最终保留多少条给 LLM?

查看答案
父文档用 BGE-Reranker 重排序(精排)后,保留 Top-2 父文档给 LLM,平衡质量与 token 成本(两千多字够用了)。

3:说一下混合检索?

查看答案

BGE-M3 支持混合检索的核心是:一次输入生成三组向量——稠密向量、稀疏向量和多向量。

我使用稠密 + 稀疏双路召回:

  • 稠密向量走 IVF_FLAT 索引做语义检索(主力权重 1.0),负责泛化理解用户问法

  • 稀疏向量走倒排索引(Inverted Index)做关键词匹配(辅助权重 0.7),负责术语精确匹配防止漂移

  • 最后用 WeightedRanker 加权融合两路结果

4:BM25 和 embedding 区别?

查看答案
  • BM25:基于词频精确匹配,适合 FAQ 快查

  • embedding:基于语义向量,能理解同义问法

本项目用 BM25 先匹配高频 FAQ,未命中再走 embedding 的 RAG 检索。

5:RAG 系统中的重排序(Rerank)是如何设计的?为什么需要它?

查看答案

为什么需要:向量粗召回(双塔模型)精度有限;rerank 做精排提升相关性

模型与算法:bge-reranker-large(交叉编码器CrossEncoder),query 与文档拼接后逐 token 深度交互打分,中文效果好

两阶段设计:

  1. 粗召回:BGE-M3+Milvus 快速召回 10 个候选(IVF_FLAT + 倒排索引)
  2. 精排:GPU 批量 rerank(无 GPU 时自动降级 CPU),取前 2 个父块进 Prompt

优化思路:粗筛控制候选数 + GPU 批量推理 → 兼顾效果、速度、token 成本

6:四种检索策略怎么路由的?

查看答案
template="""
你负责分析企业知识查询 {{query}} 和对话历史,选择合适的检索策略组合。

请以 JSON 格式返回,格式如下:
{
  "primary_strategy": "主策略(直接检索/上下文改写/子查询检索/回溯问题检索)",
  "needs_context_rewrite": true/false,  // 是否需要上下文改写
  "needs_subquery_split": true/false,  // 是否需要拆分子查询
  "rewritten_queries": ["最终改写后的查询列表"]
}
...
**决策逻辑:**
1. 如果有指代词但只是单一问题 → 上下文改写
2. 如果涉及多个实体/维度比较 → 子查询检索(在子查询中融入上下文)
3. 如果既需要上下文改写又需要拆分 → 子查询检索(子查询已隐含上下文)
4. 如果问题完整且简单 → 直接检索
"""

7:为什么需要问题改写?

查看答案
每个节点复用历史会多读一遍;改写为独立问题,避免冗余

8:RAG 场景中,如何要求模型只根据检索知识回答并减少幻觉?

查看答案
在提示词中把规律立死,没有依据必须拒答。

9:检索结果不足时能不能让模型按常识回答?

查看答案
检索不足时通用常识问题允许回答,企业知识问题必须拒答。

10:拒答率太高,用户体验不会变差吗?

查看答案
总比答错了强。

11:如何处理检索不足的情况?

查看答案

目标:检索策略路由 + 答案生成。

检索不足时由 router 选择上下文改写、子查询、回溯问题等策略再次召回;仍不足则按问题类型兜底——通用常识问题允许回答,企业知识问题必须拒答。

12:微调的训练数据是怎么构造的?

查看答案
数据构造走知识蒸馏路线:让 qwen-max 作为教师模型基于真实检索上下文生成训练样本,再全量人工审核剔除编造数据,最后用于 LoRA 微调学生模型。

13:讲讲你的双 LoRA 微调方案?为什么是"双"LoRA?

查看答案
同 7B 基座挂两个独立 LoRA 适配器——router 用 rank 8 负责检索策略路由,answer 用 rank 16 负责答案生成,两个任务解耦、互不干扰;部署时 vLLM 加 enable-lora 同时挂载,按请求动态切换,显存多 1GB 左右。

14:微调完怎么部署上线的?

查看答案
vLLM 私有化部署:enable-lora 同时挂载 router 和 answer 两个适配器,按请求动态切换;对外暴露 OpenAI 兼容 API,业务侧只需把 base_url 指向本地,代码零改动。

15:系统效果是怎么评估的?

查看答案

主要使用 RAGAS 做系统级评估,需要构造测试数据集(常用 CSV 格式)。

四大核心指标

  1. 检索质量

    • context_recall:上下文召回率,必要信息是否都被召回

    • context_precision:上下文精度,召回文档的相关性和排序

  2. 生成质量

    • faithfulness(忠实度):答案是否由上下文推导而来,检测幻觉

    • answer_relevancy(相关性):答案与问题的匹配度

💡 常见问题定位:

  • faithfulness 低 → 容易产生幻觉

  • context_recall 低 → 信息遗漏严重

  • answer_relevancy 低 → 回答偏离意图

  • context_precision 低 → 检索结果冗余

16:验证集和 badcase 数据集怎么构造?

查看答案
  • 验证集:从真实提问抽样,覆盖高频和边缘问题,配上标准答案跑 RAGAS 打分

  • badcase:从线上回答里挑错的,按检索不准、答案跑偏归类回流优化

17:上下文截断为什么是 4096,会不会语义丢失?

查看答案

影响不大:

  • 截断很少触发,多层处理,最后异常膨胀时才会截

  • 截断的也是不重要的排序靠后的内容

18:Milvus 的索引方式有哪些?你用的哪个?为什么?

查看答案

Milvus 有 FLAT、IVF 系列、HNSW、DISKANN 等索引。

  • 稠密向量:用 IVF_FLAT,数据量不大时它在召回率和查询速度间平衡好、参数简单

  • 稀疏向量:配套用倒排索引,支持混合检索

要点补充(备追问):数据量大或要更高召回可换 HNSW,但内存占用和构建成本更高。

扩展详解
Milvus 索引
├── FLAT            ← 独立的、最朴素的暴力搜索
├── IVF 系列        ← 一个"家族",前缀相同,后缀不同
│   ├── IVF_FLAT    ← IVF + 簇内精确计算
│   ├── IVF_SQ8     ← IVF + 8bit 标量量化
│   └── IVF_PQ      ← IVF + 乘积量化
├── HNSW
└── DISKANN

19:为什么选 Milvus?

查看答案
FAISS 和 Chroma 都只做稠密向量检索,没有原生混合检索能力,得外挂 BM25 再手写融合;Milvus 原生支持稀疏 + 稠密联合查询和 RRF 融合,这也是我选它的原因。

20:Milvus 只存向量吗?原文存哪里?

查看答案
Milvus 不只存向量。我在 schema 里用 VARCHAR 字段把子块原文和父块原文一起存进去,检索命中后直接取出原文,不用二次回查文档库。

21:向量库元数据怎么设计?

查看答案
元数据像图书标签,存作者、时间等属性。用于过滤筛选,提升检索精度。设计要简洁、可索引、业务相关。

22:溯源具体是怎么实现的?

查看答案
建库时把文档名、知识域、更新时间等元数据随知识块写入 Milvus;检索命中后元数据进 Prompt,答案标来源,前端可点击查看原文。

23:知识库更新和保鲜怎么做?

查看答案
我用内容哈希做主键,文档变了哈希就变,文档变更时先按路径+文件名删旧文档,然后 upsert 增量入库不重不漏;更新时间用于冲突仲裁和溯源展示。

24:知识库答案互相冲突怎么办?

查看答案
  • 检索时:先去重、再用重排序模型只留最相关的两条,减少冲突源

  • 上下文:附上文档更新时间,并在 Prompt 里明确约束:内容冲突时优先采用较新版本的资料

25:跨页表格如何处理?

查看答案
表头回填。

26:多栏排版、页眉页脚、水印如何处理?

查看答案
用 python-docx 读取的时候不在内容中,不去特意读取就算规避掉了。

27:MinerU / PyMuPDF 都能做 PDF 解析,优缺点各是什么?

查看答案
  • PyMuPDF:轻量快速,纯本地解析文本,还能按需提取大图做 OCR

  • MinerU:深度学习版式分析,依赖模型和 GPU,适合复杂排版

本项目 PDF 结构简单,选 PyMuPDF 更高效灵活。

28:如何判断问题出在切块、embedding、召回还是生成?

查看答案
  • 没召回:是切块或 embedding 问题

  • 召回了但答错:是生成问题

29:检索召回的时候有没有遇到什么问题,你是怎么解决的?

查看答案

遇到两个问题:

  • 口语化查询召回不准:用查询改写多路召回解决

  • 单路向量召回噪声大:加混合检索加重排优化

30:在检索向量库时,底层有没有做过其他的优化处理?

查看答案
  • 查询改写

  • 混合检索

  • 重排序

31:如何解决 prompt 和数据库检索不一致?

查看答案
  • Prompt 侧:强约束——只准依据检索上下文回答,不足就明确说未找到,并引用真实文档名溯源

  • 检索侧:混合检索加重排,保证上下文与问题一致

32:如何防止提示词注入?

查看答案
  1. 输入校验:过滤可疑指令(本项目已做无效查询拦截)
  2. 隔离:系统提示词与用户输入隔离,限定仅基于检索内容作答
  3. 白名单:约束输出格式