Agent 面试通关 / 09

RAG 与检索系统:从 chunk 设计到多路召回

RAG 是 Agent 系统的“外部知识接口”。面试官考 RAG 时不想听“向量数据库”四个字——他想知道的是离线怎么切片、在线怎么召回、召回后怎么排序,以及面对复杂查询时怎么做改写和意图识别。


检索基础与原理

Q:RAG 的检索如何实现?

来源:阿里 AI Agent 开发一面

新手答:“用向量数据库做相似度搜索。”

高手答

RAG 检索分离线在线两部分。

离线侧负责文档清洗、切片、去重、embedding 计算和向量入库。在线侧的流程是:

  1. 用 query 编码成向量,去向量库做召回
  2. 结合 BM25 或关键词检索做混合召回
  3. 用 rerank 模型重排
  4. 把最相关的证据拼接给大模型生成答案
# 简化版 RAG 检索流程
query_vec = embed(query)
candidates = vector_db.search(query_vec)
bm25_docs = bm25.search(query)
merged = merge_and_dedup(candidates, bm25_docs)
reranked = reranker.rank(query, merged)
context = "\n".join(doc.text for doc in reranked[:top_k])
answer = llm.generate(query, context)

切片策略直接影响效果:块太大召回不准,块太小上下文断裂。通常用滑窗切割 + overlap,对长文档还会给每个 chunk 带上标题、章节路径、来源元信息,提升召回相关性。

差距在哪:新手只说了“向量数据库”——这是一个组件,不是方案。高手的回答覆盖了离线和在线两条链路,且点出了 chunk 设计这个影响效果的关键因素。面试官考的是你对 RAG 工程的完整认知。


Q:多维度的查询改写是什么?改写遇到需要用户补充信息时怎么设计?

来源:抖音基础架构 Agent 一面

新手答:“用大模型把用户的查询扩展一下。”

高手答

多维度查询改写是指同时从多个角度对原始 query 做变换,提升召回的全面性:

原始 query:"北京周末带娃去哪玩"

维度1-意图展开:亲子活动 / 儿童乐园 / 博物馆 / 户外游
维度2-实体补全:北京市 → 朝阳区/海淀区/...
维度3-同义改写:"带娃" → "亲子" / "儿童" / "适合小朋友"
维度4-约束提取:时间=周末,地点=北京,人群=有孩子的家庭

需要用户补充信息时,用槽位填充 + 主动澄清机制:

  1. 意图识别后,检查必要槽位是否完整(比如“订酒店”需要日期、城市、人数)
  2. 缺失槽位时,不是笼统地问“你能说得更清楚吗”,而是生成具体的选择题:“你想去哪个城市?”或“入住日期是什么时候?”
  3. 多个槽位都缺时,按优先级排序,先问最关键的

技术实现上,查询改写用模型生成 + 规则约束混合:模型负责语义理解和改写,规则负责实体标准化和格式校验。槽位检测用一个轻量分类器判断缺失情况,避免每次都调大模型。

差距在哪:新手的”扩展一下”是单维度思考。高手的多维度改写覆盖了意图、实体、同义、约束四个角度,且有用户交互的槽位填充机制。面试官考的是你对查询理解链路的完整认知。

追问:Query 改写为什么能提升召回精准度?底层原理是什么?

改写不是”让 query 变长”,而是解决 query 和文档之间的三类鸿沟

鸿沟类型 问题 改写如何解决 示例
词汇鸿沟 用户用词 ≠ 文档用词 同义扩展弥合词汇差异 “手机卡” → “SIM 卡 / 流量卡 / 电话卡”
意图鸿沟 短 query 意图模糊 意图展开消除歧义 “苹果” → “Apple 公司 / 苹果水果”(结合上下文选择)
粒度鸿沟 query 太宽泛或太细碎 拆分/合并调整检索粒度 “怎么部署” → “Docker 部署 + K8s 部署 + 物理机部署”

为什么多维度改写比单次改写效果好:单次改写只能沿一个方向扩展,可能强化了某个意图但遗漏了其他。多维度改写用多条路径并行检索再合并,Recall 提升显著(实测 +15~25%),但 Precision 可能下降——所以改写后必须接 Rerank 精排过滤噪声。


Q:并行化意图识别是什么?为什么要并行化?如何实现的?

来源:抖音基础架构 Agent 一面

新手答:“用多线程跑意图分类。”

高手答

并行化意图识别是指同时执行多个意图维度的判断,而不是串行地先判大类再判小类

串行方案的问题是链路长、延迟高。比如先判“是不是搜索意图” → 再判“搜索什么品类” → 再判“有没有比较意图”,三级串行加起来可能 300ms+。而且前一级判断错了,后面全错——错误级联放大。

并行化把多个维度同时发出去

              ┌→ 意图大类分类器(搜索/导航/交易)
user query ──┼→ 品类识别器(美食/旅游/购物/...)
              ├→ 行为意图检测器(比较/推荐/查询/...)
              └→ 情感倾向检测器(正面/负面/中性)

每个分类器独立运行,结果汇总后做融合决策。实现关键点:

  1. 各分类器用异步并发执行(asyncio.gather 或线程池),总延迟 = 最慢的那个
  2. 每个分类器可以用不同规模的模型——简单维度用小模型,复杂维度用大模型
  3. 设置超时兜底:某个分类器超时不影响其他维度,用默认值填充

差距在哪:新手的“多线程”只答了实现手段,没答为什么要并行化。高手先解释了串行方案的问题(延迟高 + 错误级联),再给出并行化的架构和融合策略。面试官考的是性能优化思维。


Q:讲一下项目里召回的流程

来源:抖音基础架构 Agent 一面

新手答:“用向量搜索召回相关文档。”

高手答

召回是一个多路召回 → 合并去重 → 精排的三阶段流程:

第一阶段:多路召回

              ┌→ 向量召回(语义相似度,覆盖同义表达)
改写后 query ──┼→ 关键词召回(BM25,覆盖精确匹配)
              ├→ 标签召回(实体/品类标签匹配)
              └→ 图召回(知识图谱关联路径)

每路召回各取 top-K,各有优势:向量召回抓语义,关键词召回抓精确词,标签召回抓结构化属性,图召回抓实体关系。

第二阶段:合并去重

多路结果合并,同一文档被多路召回的加分。去重用文档 ID 做精确去重 + 内容指纹做近重复去重。

第三阶段:精排

用 Cross-Encoder 或精排模型对候选集做细粒度相关性打分。精排模型能看到 query 和文档的交互特征,精度远高于召回阶段的双塔模型。关键工程细节:每路召回的 K 值怎么定——K 太小漏结果,K 太大精排压力大,通常根据各路历史准确率动态调整。

差距在哪:新手只知道向量检索一路。高手的多路召回 + 精排是搜索系统的标准范式,面试官考的是你对召回-精排两阶段架构的完整理解。


Q:如果 RAG 召回了很多相互矛盾的文档,Agent 应该怎么处理,而不是直接让模型自己总结?

来源:腾讯大模型应用开发二面

新手答:“让模型自己综合判断。”

高手答

不能直接把矛盾文档一股脑丢给模型让它自己“综合”,那样很容易生成一个看起来圆滑但实际上没有依据的答案。

更合理的做法是先做证据归一化和冲突检测

  1. 分组:按来源、时间、可信度对召回文档分组
  2. 冲突检测:抽取同一字段的不同取值,判断冲突类型——是时间差异导致的,还是来源本身互相打架
  3. 冲突消解
    • 时间敏感信息 → 新版本优先
    • 来源权威性不同 → 官方文档优先
    • 无法判断 → 明确告诉用户存在冲突,说明目前最可信的依据

Agent 在这里更像证据调解器,而不是万能总结器。核心是在模型生成前就把冲突处理好,而不是让模型在矛盾信息中自己编一个“看起来合理”的答案。

差距在哪:新手直接把矛盾丢给模型——这会生成看似合理但无依据的答案。高手在模型生成前加了冲突检测和消解层,按时间、权威性、可判断性三个维度做处理。面试官考的是你有没有意识到 RAG 不只是“召回 + 生成”,中间还需要证据治理。


检索算法与微调

Q:Embedding 和 ReRank 模型具体怎么做的微调?

来源:腾讯 AI 应用开发 【腾讯AI应用开发一面追问:重排序完整实现流程】

新手答:“用自己的数据训练一下。”

高手答

Embedding 模型微调

目标是让模型在业务领域里,把语义相近的 query 和文档映射到向量空间中的相近位置。

训练数据格式:(query, positive_doc, negative_doc) 三元组。hard negative 越难越好——随机采样的 negative 太简单,模型学不到有区分度的表示。用 BM25 或当前模型 top-K 中的非相关文档做 hard negative。

常用 loss:

  • MultipleNegativesRankingLoss(sentence-transformers 最常用):batch 内其他 query 的 positive 自动作为 negative,不需显式构造
  • InfoNCE / Contrastive Loss:拉近 positive pair,推远 negative pair
  • Triplet Lossmax(0, d(q, pos) - d(q, neg) + margin)

框架:sentence-transformers 最成熟,支持 BGE、E5、GTE 等预训练模型的微调。

ReRank 模型微调

ReRank 是 Cross-Encoder——输入是 (query, doc) 拼接后一起过模型,输出相关性分数。比 Embedding 双塔精度高,但计算量大,只用于精排。

训练数据:(query, doc, label),label 是相关性分数或 0/1 标签。Loss 用 BCE 或 MSE。

微调关键细节

  1. Hard Negative Mining:negative 质量决定微调效果
  2. 评估指标:用 Recall@K、MRR、NDCG 在验证集上评估,不是看 loss 降了就行
  3. 防止过拟合:微调轮数不宜过多(1-3 epoch),否则通用检索能力退化

差距在哪:新手只说了“用数据训”。高手覆盖了完整链路——数据构造(三元组 + hard negative)、loss 选择、框架、评估、防过拟合。面试官考的是你有没有真正微调过检索模型。


Q:双路召回的 TopK,K 是如何确定的?有没有试过一个多召回点、一个少召回点?

来源:腾讯 AI 应用开发

新手答:“K 就取 10 或 20。”

高手答

K 值要根据召回路的特性和下游精排的承载能力来定

BM25 关键词召回:K = 10~20(精确匹配路,召回量不需要太大)
Embedding 向量召回:K = 20~50(语义路,覆盖面要大一些)
ReRank 精排后最终 TopK:K = 3~5(给模型的上下文不宜太多)

K 值调优方法:Grid Search 在评估集上搜索最优组合——固定一路 K,遍历另一路(5、10、20、30、50),合并去重后精排,用 Recall@K 和最终生成质量评判。

一多一少的策略:实际中确实会对不同路设不同 K:

  • 向量路 K 大、BM25 路 K 小:向量覆盖面广但精度稍低,多召回交给 ReRank 筛;BM25 精确率高,少量就够
  • 反过来也有场景:精确查询(订单号、型号)时 BM25 路 K 调大

关键权衡:K 越大覆盖率越高但噪声也多(ReRank 负担重、延迟增加);K 越小精度高但可能漏掉相关文档。生产环境通常还有延迟约束(“总检索时间不超过 200ms”),K 值要在 Recall 和延迟之间找平衡。

差距在哪:新手随便定一个 K。高手有系统的调优方法论——Grid Search + 不同路不同 K + 延迟约束。面试官考的是你调 RAG 参数时有没有数据驱动的方法。


Q:如何用通俗易懂的方式向非技术人员解释 RAG?有没有好的类比?

来源:携程 Agent 开发实习一面

新手答:“就是让模型先搜索再回答。”

高手答

给非技术同事解释 RAG,我会这么说:

一句话版本:RAG 就是让 AI 在回答问题之前,先去翻资料,而不是纯靠记忆回答。

图书馆类比(最直观):

flowchart LR
  subgraph no_rag["❌ 没有 RAG"]
    direction LR
    Q1["你提问"] --> E1["专家凭记忆回答"]
    E1 --> R1["知识可能过时\n细节可能记错\n还可能自信地编答案"]
  end

  subgraph with_rag["✅ 有 RAG"]
    direction LR
    Q2["你提问"] --> S["检索员去书架\n找最相关的资料"]
    S --> E2["专家翻阅资料后回答"]
    E2 --> R2["答案有据可查\n知识随时可更新"]
  end

核心价值(三点):

  1. 知识实时性:模型训练数据有截止日期,但外部知识库可以随时更新——今天新上线的产品文档,明天就能被检索到
  2. 可追溯性:回答附带引用来源,用户可以点击查看原文,建立信任
  3. 降低幻觉:有资料做依据,模型不容易“编”答案

主要应用场景:企业知识库问答(内部文档/FAQ)、客服系统(产品手册检索)、法律/医疗等需要精确引用的领域、代码文档助手。

差距在哪:新手的解释太技术化,非技术人员听不懂。高手用图书馆类比把 RAG 的三个角色(用户 → 检索员 → 专家)讲清楚了,再用三点核心价值说明“为什么需要”。面试官考的不只是你懂不懂 RAG,还考你能不能把复杂概念讲给不同背景的人听——这是工程师的沟通能力。


Q:如何快速上手一个没接触过的技术(如向量数据库)?

来源:携程 Agent 开发实习一面

新手答:“看官方文档,跑个 Demo。”

高手答

快速上手一个新技术,我的方法论是“倒金字塔学习法”——从应用场景倒推,不从底层原理开始

第一步:搞清楚“它解决什么问题”(30 分钟)

不是先看原理,而是先理解:传统方案的痛点是什么?向量数据库比传统数据库多解决了什么?答案是——传统数据库只能精确匹配,而向量数据库能做语义相似度检索。这一步决定了你后面学的所有东西有没有方向感。

第二步:跑通一个最小可用的 Demo(2-3 小时)

选一个主流方案(如 Milvus / Qdrant / Chroma),跑通“文本 → Embedding → 入库 → 查询 → 返回结果”的最短路径。不要一开始就研究分布式部署、索引类型选择这些细节。

# 最小 Demo:Chroma
import chromadb
client = chromadb.Client()
collection = client.create_collection("demo")
collection.add(documents=["北京今天晴天", "上海明天下雨"], ids=["1", "2"])
results = collection.query(query_texts=["天气怎么样"], n_results=1)

第三步:对标项目需求,补齐关键知识点(1-2 天)

Demo 跑通后,对照项目需求列一个清单:需要什么索引类型(HNSW / IVF)?数据量级多大?需不需要过滤?需不需要持久化?然后按需深入,不铺开学。

第四步:踩坑 → 查 Issue → 形成经验(持续)

真正的理解来自踩坑。遇到问题先查 GitHub Issue 和社区讨论,很多坑别人已经踩过了。

差距在哪:新手的“看文档跑 Demo”没有方法论,容易在原理细节里迷失方向。高手的倒金字塔方法有明确的四步节奏——先理解价值、再跑通最短路径、再按需深入、最后靠实践沉淀。面试官考的是你的学习效率和自驱能力。


Q:RAG 系统检索到的文档很多但回答质量差,怎么排查?

来源:携程 Agent 开发实习一面

新手答:“可能是模型不够好,换个更强的模型。”

高手答

“检索多但回答差”说明问题大概率不在模型,而在检索质量和上下文组装。排查按链路从前到后逐段定位:

1. 检索相关性差(召回了但不准)

  • 症状:返回的文档和用户问题表面相关但实际不对口
  • 排查:抽样看 top-K 文档和 query 的匹配度,计算 Recall@K / Precision@K
  • 常见原因 + 解法
    • Embedding 模型领域适配差 → 用业务数据微调 Embedding
    • Chunk 切分不合理(太大导致噪声多,太小导致上下文断裂)→ 调整 chunk size 和 overlap
    • 缺少多路召回 → 加 BM25 关键词路补充精确匹配

2. 排序失效(相关文档排在后面)

  • 症状:相关文档确实被召回了,但排在第 8、9 位,top-3 都是噪声
  • 排查:对比有无 ReRank 时的排序效果
  • 解法:加 Cross-Encoder ReRank 模型做精排;或微调 ReRank 模型

3. 上下文组装问题(给模型的信息太杂)

  • 症状:top-K 文档质量还行,但模型回答仍然差
  • 排查:直接看拼给模型的 context,是不是信息太多、互相矛盾、或关键信息被淹没
  • 解法:减少 top-K(从 10 降到 3-5);对召回文档做摘要提取再喂给模型;加冲突检测

4. Prompt 模板问题

  • 症状:换了更好的检索结果,回答质量还是没提升
  • 排查:检查 Prompt 是否清晰指示模型“基于以下资料回答,如果资料不足请说明”
  • 解法:优化 Prompt 模板,加引用约束

差距在哪:新手第一反应是“换模型”——这是最贵且通常无效的做法。高手按 RAG 链路逐段排查(检索 → 排序 → 组装 → Prompt),每段都有具体的症状、排查方法和解法。面试官考的是你排查问题时的系统性思维。


Q:什么是余弦相似度?在 RAG 系统中用来做什么?

来源:携程 Agent 开发实习一面

新手答:“衡量两个向量的相似程度。”

高手答

余弦相似度衡量的是两个向量方向的接近程度,不关心长度,只关心角度:

cos(A, B) = (A · B) / (|A| × |B|)

值域:[-1, 1]
  1  = 方向完全一致(语义最相似)
  0  = 正交(语义无关)
 -1  = 方向完全相反(语义相反)

为什么用余弦而不是欧氏距离

Embedding 模型输出的向量,不同文本的向量长度(模)可能差异很大。如果用欧氏距离,一段长文本和一段短文本即使语义相同,距离也可能很远(因为向量模不同)。余弦相似度归一化了长度,只比较方向——语义相同的文本,无论长短,余弦相似度都接近 1。

在 RAG 系统中的用途

  1. 检索阶段:用户 query 向量和文档库中所有文档向量计算余弦相似度,取 top-K 作为候选
  2. 去重阶段:两个 chunk 的余弦相似度 > 0.95,判定为近重复,去掉一个
  3. 阈值过滤:相似度低于阈值(如 0.6)的文档直接丢弃,不进入精排——避免把完全不相关的文档喂给模型

补充:实际向量数据库(Milvus / Qdrant)在 ANN 检索时用的是近似最近邻算法(HNSW / IVF),不是暴力遍历所有向量。精确的余弦计算只在小规模候选集上做。

差距在哪:新手只背了定义。高手从公式、为什么选余弦而非欧氏、在 RAG 中的三个具体用途(检索/去重/过滤)做了完整解释,且补充了工程实现细节。面试官考的是你理解了这个指标的设计动机,而不只是会算。


Q:什么是嵌入(Embedding)?为什么 RAG 系统需要将文本转为向量?

来源:携程 Agent 开发实习一面

新手答:“把文本变成数字,方便计算。”

高手答

嵌入(Embedding)是把文本映射到一个高维向量空间中的过程——每段文本变成一个固定长度的数字数组(如 768 维或 1536 维),这个数组就叫这段文本的“向量表示”。

关键特性:语义相近的文本,在向量空间中的位置也相近。

"北京今天天气很好"  →  [0.12, -0.45, 0.78, ...]  ─┐
"今日北京晴朗"      →  [0.11, -0.43, 0.76, ...]  ─┘ 向量接近

"明天股市走势如何"  →  [-0.67, 0.23, -0.11, ...] ← 向量远离

为什么 RAG 需要向量化

传统检索靠关键词匹配——用户搜“怎么退货”,系统只能找到包含“退货”两个字的文档。但用户可能问的是“买错了怎么办”“商品不满意能换吗”——意思一样,但没有一个共同关键词。

向量化解决的是语义匹配问题——“怎么退货”和“商品不满意能换吗”的 Embedding 向量很接近,即使没有共同关键词也能检索到。

Embedding 模型的选型考量

  • 通用模型:OpenAI text-embedding-3、BGE、E5、GTE——开箱即用,适合大部分场景
  • 领域微调:如果业务术语多(医疗、法律、金融),通用模型可能把业务术语和日常用语混淆,需要用业务数据做微调
  • 维度和性能的权衡:维度越高表达力越强,但存储和计算成本也越高。768 维是常见平衡点

差距在哪:新手的”变成数字”没有解释为什么要这么做。高手从语义匹配的角度解释了向量化的动机——解决关键词匹配的语义鸿沟问题,且覆盖了模型选型的实际考量。面试官考的是你理不理解 Embedding 在 RAG 管线中的核心作用。

追问:Embedding 的本质是什么?向量的每个维度代表什么含义?

来源:小红书 AI应用开发

Embedding 的本质是将离散符号映射到连续向量空间,使语义关系可以用几何距离衡量。但很多人会追问:向量的每个维度到底是什么意思?

每个维度不是一个可解释的特征——这是 Embedding 和传统特征工程的根本区别:

对比 传统特征向量 Embedding 向量
每个维度 有明确含义(年龄、价格、频率) 无单一可解释含义
表示方式 人工设计的特征 模型自动学到的潜在特征
信息分布 每维独立编码一种信息 一种语义分布在多个维度上
术语 特征工程 分布式表示(Distributed Representation)

什么是分布式表示:一个语义概念(如”食物”)不是由某一个维度单独表达,而是由多个维度的组合模式来表达。反过来,一个维度也参与了多个语义概念的编码。这就是为什么单看某一维的数值没有意义,但整体向量之间的距离能反映语义相似性。

维度数量的工程权衡

低维(256-384):存储小、速度快,但语义区分度有限,适合简单场景
中维(768):  最常见的平衡点,大多数场景够用
高维(1024-3072):区分度更高,能捕获更细粒度的语义差异,但存储和计算成本线性增长

面试加分点:如果面试官继续追问”能不能让每个维度可解释”,可以提到 Sparse Embedding(如 SPLADE)——它在词表维度上做稀疏编码,每个维度对应一个 token,可解释性强但维度极高(30000+)。这也是为什么实际系统常用 Dense + Sparse 混合检索——Dense 捕获语义,Sparse 保留精确匹配能力。


Q:RAG 中如何提高文档召回率?

来源:蚂蚁集团智能体与大模型应用一面

新手答:“换更好的 Embedding 模型。”

高手答

召回率低意味着正确文档没有进入候选集——模型连看到正确答案的机会都没有。提升召回率要从离线和在线两端同时入手:

离线端——提升文档的“可被检索性”

  1. Chunk 策略优化
    • 块太大 → 一个 chunk 混了多个主题,语义被平均化,精准匹配变弱
    • 块太小 → 上下文断裂,语义不完整
    • 最佳实践:语义分块(按段落/标题/逻辑边界切割)+ overlap(相邻 chunk 重叠 10-20%)
  2. 文档增强:给每个 chunk 附加元信息——标题、所属章节、关键词标签、生成摘要。检索时不只匹配 chunk 正文,还匹配元信息
  3. Embedding 模型适配:通用模型在专业领域(医疗/法律/代码)的表现可能大幅下降。用业务数据微调 Embedding 模型,Recall 通常能提升 10-20%

在线端——提升查询的“被理解度”

  1. 查询改写:用大模型对用户 query 做多维度改写(同义替换、意图展开、实体补全),从不同角度匹配文档
  2. 混合召回:不只用向量检索,同时用 BM25 关键词检索 + 标签检索,多路结果合并。向量路抓语义,关键词路抓精确匹配,互补覆盖
  3. HyDE(Hypothetical Document Embeddings):让模型先生成一个“假设性答案”,用这个答案的 embedding 去检索——因为答案和文档的语义更接近,比直接用 query 检索效果好
flowchart TB
    Q["用户 Query"] --> QR["查询改写\n(多维度)"]
    Q --> HY["HyDE\n生成假设答案"]
    QR --> VR["向量召回"]
    QR --> KR["关键词召回"]
    QR --> TR["标签召回"]
    HY --> VR2["向量召回"]
    VR --> M["合并去重"]
    KR --> M
    TR --> M
    VR2 --> M
    M --> RR["ReRank 精排"]
    RR --> TOP["Top-K 结果"]

效果最大的三板斧:根据实践经验,混合召回 > chunk 优化 > Embedding 微调。很多团队一上来就微调模型,其实先加一路 BM25 召回就能显著提升 Recall。

差距在哪:新手只想到换模型。高手从离线端(chunk/文档增强/Embedding 微调)和在线端(查询改写/混合召回/HyDE)六个方向给出了完整方案,且点出了优先级排序。面试官考的不是你知不知道某个技术,而是你能不能系统性地优化一条 RAG 管线。


Q:RAG 为什么需要向量检索?和传统关键词检索有什么本质区别?

来源:蚂蚁集团智能体与大模型应用一面

新手答:“向量检索更准。”

高手答

不是“更准”——是解决了不同的问题。传统检索和向量检索的核心差异在于匹配方式:

维度 传统关键词检索(BM25) 向量检索(Embedding)
匹配方式 词级精确匹配 语义级相似度匹配
核心算法 TF-IDF / BM25 ANN(近似最近邻)
能处理同义词 ❌ “退货”搜不到“退款” ✅ 语义相近就能匹配
能处理精确术语 ✅ 搜“order_id=123”直接命中 ❌ 向量化后精确性丢失
计算成本 低(倒排索引,O(1)级) 高(向量距离计算 + ANN 索引)
索引存储 小(倒排表) 大(每条文档一个高维向量)
对新词/专业术语 好(只要文档里有就能匹配) 差(模型没见过的词 embedding 质量低)

RAG 为什么需要向量检索

用户提问的方式和文档的表述方式几乎不可能完全一样。用户问“服务器老是挂”,文档里写的是“服务可用性异常”——没有一个共同关键词,但语义完全匹配。传统检索在这种场景下召回率为零,向量检索能轻松解决。

但向量检索不能完全替代关键词检索

查具体的错误码(ERR_CONNECTION_REFUSED)、精确的文件路径、特定的 API 名称——这些场景关键词检索比向量检索更快更准。向量化反而会把精确信息“模糊化”。

生产环境的最佳实践是混合检索

向量检索(语义匹配)─┐
                     ├→ 合并去重 → ReRank 精排 → Top-K
关键词检索(精确匹配)─┘

两路互补:向量路保证语义覆盖,关键词路保证精确命中。合并后用 ReRank 统一排序。

差距在哪:新手用“更准”一词概括——其实向量检索在精确匹配上反而不如关键词检索。高手明确了两者的优劣势互补关系,且指出生产环境用混合检索。面试官考的是你对检索系统的工程认知——不是“哪个更好”,而是“什么场景用什么”。


Q:如果用全量生产文档做关联性检索,用户每个问题要交互多少轮?有没有更高效的方案?

来源:蚂蚁集团智能体与大模型应用二面

新手答:“文档多了就慢一点,多检索几次。”

高手答

全量文档场景的核心挑战是文档量级和查询效率的矛盾——几万甚至几十万份文档,用户一个问题不可能遍历所有文档找关联。

传统 RAG 的局限

标准 RAG 是 query → embedding → top-K 召回。但当文档量大且内容跨领域时,单次召回很难覆盖所有相关信息。用户可能需要多轮追问才能拿到完整答案——每轮交互本质上是在“逐步缩小检索范围”。

更高效的方案

1. 文档预处理——建立关联索引

不等用户查询时才找关联,离线阶段就把文档间的关联性预计算好:

  • 文档聚类:按主题对文档自动分组,查询时先定位到相关组,缩小搜索范围
  • 知识图谱:从文档中抽取实体和关系,建立文档间的语义关联图。查询时沿着图谱做多跳检索,找到间接关联的文档
  • 摘要索引:每份文档生成摘要,先用摘要做粗筛,再用原文做精排——两级检索比全量检索快很多

2. Multi-hop RAG——一次查询找到链式关联

flowchart LR
    Q["用户提问:\n这个服务为什么延迟高?"]
    Q --> R1["第一跳:找到\n服务架构文档"]
    R1 --> R2["第二跳:从架构文档\n发现依赖 Redis"]
    R2 --> R3["第三跳:找到\nRedis 配置变更记录"]
    R3 --> A["综合三份文档回答"]

Multi-hop RAG 让 Agent 自动做多轮检索,每一跳基于上一跳的结果生成新的子查询,沿关联链逐步深入。用户只问一次,Agent 内部自动完成多轮检索。

3. GraphRAG——结构化关联检索

微软提出的 GraphRAG 方案:先从全量文档构建知识图谱和社区摘要,查询时在图上检索而非在文档上检索。优势是能找到文档间的隐式关联——两份文档没有共同关键词,但通过实体关系链接在一起。

差距在哪:新手认为全量文档只能“多搜几次”。高手给出了三种更高效的方案——预计算关联索引、Multi-hop RAG 自动多跳检索、GraphRAG 结构化关联。面试官考的是你对 RAG 架构演进方向的认知——从单次检索到多跳检索到图检索,是检索系统面对大规模文档的自然演化路径。


RAG 在 Agent 中的角色

Q:RAG 在 Agent 体系里应该被看成工具、记忆,还是推理前置步骤?

来源:Agent 开发面试 30 题

新手答:“RAG 就是个工具,需要的时候调一下。”

高手答

RAG 在 Agent 体系里的定位取决于使用方式,三种定位都成立,适用场景不同:

当工具用——按需调用

Agent 在执行过程中判断“我需要查资料”,主动调用 RAG 检索。这时 RAG 和其他工具(搜索、计算器)是同级的。

适用场景:开放性任务,Agent 不一定每次都需要检索。比如用户问“1+1 等于几”不需要 RAG,问“公司休假制度”才需要。

当记忆用——上下文扩展

每次对话开始时,自动检索和当前话题相关的历史文档注入上下文。RAG 充当的是“长期记忆的检索接口”。

适用场景:垂直领域问答,几乎每次都需要外部知识。比如客服机器人,每个问题都要查产品文档。

当推理前置步骤——先检索再思考

RAG 不是可选步骤,而是必经环节——先检索证据,再基于证据推理。模型不允许在没有证据的情况下直接回答。

适用场景:高准确性要求的场景(法律、医疗),必须有据可依。

定位 触发方式 适用场景 典型架构
工具 Agent 主动调用 开放性任务 ReAct + RAG Tool
记忆 每轮自动注入 垂直领域问答 RAG-augmented Chat
前置步骤 强制先检索 高准确性要求 Retrieve-then-Read

实际生产中这三种往往混合使用:基础知识自动注入(记忆模式),需要深入查找时主动调用(工具模式),关键结论必须有证据支撑(前置步骤模式)。

差距在哪:新手把 RAG 固定为“工具”一种定位。高手看到了 RAG 在 Agent 体系中的三种不同角色,且说清了各自的适用场景和触发方式。面试官考的是你对 RAG 和 Agent 系统集成方式的灵活理解。


Q:如果检索结果很多但质量参差不齐,你会把控制点放在召回、重排,还是 Agent 规划层?

来源:Agent 开发面试 30 题

新手答:“加 ReRank 重排就行。”

高手答

三个控制点都需要,但投入产出比不同:

召回层——控制“进来什么”

问题:召回 50 条,30 条不相关
解法:① 优化 query(多维度改写)② 收紧召回阈值 ③ 加关键词路补充精确匹配
效果:减少噪声进入下游,降低精排压力

召回层的控制是成本最低、效果最直接的——垃圾在入口就拦住,比在后面处理便宜得多。

重排层——控制“排在前面的是什么”

问题:相关文档被召回了,但排在第 8 位,top-3 都是噪声
解法:用 Cross-Encoder 精排,把真正相关的推到前面
效果:精度提升显著,但增加延迟和计算成本

重排层解决的是顺序问题,前提是相关文档已经被召回了。如果召回阶段就漏了,重排也救不了。

Agent 规划层——控制“怎么用检索结果”

问题:top-3 文档质量还行,但信息分散,模型拼出了错误答案
解法:Agent 在使用检索结果前做质量判断——
      "这些证据是否足够回答问题?是否有矛盾?需不需要再查一次?"
效果:提升最终回答质量,但增加一轮模型调用

规划层是最后一道防线,也是唯一能做“再查一次”决策的地方。

优先级排序

投入优先级:召回优化(成本低效果大)> ReRank(精度提升明显)> 规划层判断(兜底)

先把召回质量做好,再加精排提升排序,最后在 Agent 层做质量兜底。很多团队跳过前两步直接在 Agent 层“让模型自己判断”,这是最贵且最不可靠的做法。

差距在哪:新手只想到 ReRank 一个点。高手从召回、重排、规划三层分别分析了控制方法和投入产出比,且给出了明确的优先级排序。面试官考的是你对 RAG 质量控制的全链路思维。


Q:Agent 场景下,什么时候该做一次检索、多次使用;什么时候该边执行边检索?

来源:Agent 开发面试 30 题

新手答:“复杂问题多查几次。”

高手答

判断标准是信息需求在任务开始时是否完全可知

一次检索、多次使用(Retrieve-once)

适用条件:
- 任务开始时就能确定需要什么信息
- 信息需求不会随执行过程变化
- 检索结果在整个任务周期内有效

典型场景:
- 客服问答:用户问"退货政策是什么"→ 一次检索产品文档,回答完整问题
- 报告生成:给定主题,一次性检索所有相关数据,然后生成报告
- FAQ 类问答:一问一答,信息需求明确

优势是延迟低、成本低,只调用一次检索管线。

边执行边检索(Iterative Retrieval)

适用条件:
- 下一步需要查什么取决于上一步的结果
- 任务目标可能在过程中细化或变化
- 单次检索无法覆盖所有需要的信息

典型场景:
- 故障排查:"服务挂了"→ 查架构文档 → 发现依赖 Redis → 查 Redis 变更记录 → 定位根因
- 竞品分析:查到竞品 A 的信息后,发现需要对比的维度,再查竞品 B
- 多跳推理:答案分布在多个文档中,需要逐步追溯

优势是信息覆盖全,但延迟和成本成倍增加。

工程上的混合策略

先做一次广泛的初始检索,如果 Agent 判断信息不足再触发增量检索。设一个检索预算上限(如最多 3 次),避免无限检索。

第一次:广泛检索,覆盖主要信息需求
执行中判断:信息够 → 继续执行。信息不够 → 生成更精确的子查询,再检索一次
最多追加 2 次,超过后用已有信息给出最优答案

差距在哪:新手用“复杂度”判断。高手用“信息需求是否可预知”做精确判断,且给出了一次检索和迭代检索的各自适用场景,以及“初始广泛 + 按需增量”的混合策略。面试官考的是你在 RAG 和 Agent 结合时的架构设计能力。


Q:如果 RAG 返回了看似可信但实际过时的信息,你会怎么降低 Agent 被误导的概率?

来源:Agent 开发面试 30 题

新手答:“定期更新知识库。”

高手答

定期更新是必要的,但更新和检索之间一定有时间差——今天更新的文档可能要到明天才入库,而在这个窗口期内返回的就是过时信息。更根本的问题是:很多文档没有明确的“过期时间”,系统不知道它过时了

需要多层防线

第一层:离线端——给文档打时间标签和可信度标签

  • 每个 chunk 存储文档创建时间、最后更新时间、来源权威等级
  • 有明确时效性的内容(价格、政策、版本号)标记为“时效敏感”
  • 建立文档更新监控——源文档变更后自动触发重新入库

第二层:检索端——时间感知的检索和排序

  • 检索时对结果按时间新鲜度加权——同等相关性下,新文档排在前面
  • 对“时效敏感”标签的 chunk,如果超过 TTL(如 30 天)直接降权或过滤
  • 返回结果时附带时间元信息,让 Agent 知道证据的时效性

第三层:Agent 端——生成前做时效性判断

在 Prompt 中明确要求模型:

注意:以下检索结果附带了文档日期。如果信息可能已过时(如价格、政策、版本号),
请在回答中标注"此信息来源于 YYYY-MM-DD 的文档,建议确认是否仍然有效"。

模型看到日期后会主动判断时效性,并在回答中加上免责提示。

第四层:用户端——可追溯的引用

回答中附带引用来源和日期,让用户自行判断信息是否过时。这是最后一道防线——即使系统没发现过时,用户看到“来源:2024 年 3 月的文档”也会自己注意。

差距在哪:新手只想到“更新知识库”——这是必要但不充分的。高手从离线(时间标签)、检索(时间加权)、Agent(时效性判断)、用户(可追溯引用)四层构建了防过时信息的完整体系。面试官考的是你对 RAG 系统“证据可靠性”这个核心问题的工程化思考。


Q:在渐进式披露的架构下,还需要 RAG 吗?RAG 的角色会怎么变?

来源:蚂蚁集团 Agent 开发二面

新手答:“模型上下文窗口越来越大,RAG 可能不需要了。”

高手答

RAG 不会消失,但角色会发生本质变化——从“弥补模型知识不足”变成“渐进式披露架构的信息供给层”。

为什么上下文窗口变大不能替代 RAG

即使窗口有 100 万 token,也不能把所有文档都塞进去:

  1. 成本问题:塞 100 万 token 的成本是塞 1 万 token 的 100 倍
  2. 精度问题:信息越多,模型在噪声中迷失的概率越大(Lost in the Middle)
  3. 实时性问题:长上下文解决不了“信息需要实时更新”的问题

所以不是“要不要 RAG”,而是“RAG 在新架构里扮演什么角色”。

RAG 在渐进式披露架构中的新角色

传统 RAG:用户提问 → 检索文档 → 塞进上下文 → 生成回答(一次性、静态)
新角色 RAG:Agent 执行到某阶段 → 按需检索该阶段需要的知识 → 精确注入 → 继续执行(多次、动态)
维度 传统 RAG 渐进式架构下的 RAG
触发时机 用户提问时一次性触发 Agent 执行过程中多次按需触发
检索粒度 和用户 query 匹配 和当前执行阶段的子目标匹配
结果用途 直接喂给模型生成答案 作为当前阶段的决策依据
生命周期 检索一次用到结束 阶段切换后可能需要重新检索

具体变化

  1. 从“回答前检索”到“执行中检索”:RAG 不只在开头检索一次,而是 Agent 在规划、执行、验证各阶段都可能触发检索,每次检索的 query 不同
  2. 从“通用检索”到“阶段感知检索”:同一个用户问题,规划阶段需要检索的是“方法论文档”,执行阶段需要的是“API 文档”,验证阶段需要的是“规范标准”——检索策略随阶段变化
  3. 从“替代模型知识”到“精确注入运行时上下文”:RAG 的价值从“给模型不知道的知识”转变为“在正确的时机给出正确的精确信息”

差距在哪:新手用“窗口大了不需要 RAG”的线性思维。高手看到了 RAG 在新架构下的角色转变——从一次性的知识注入变成多阶段的动态信息供给。面试官考的是你对 RAG 技术演进方向的理解,以及能不能把 RAG 放到更大的架构图景中思考。


召回与排序优化

Q:RAG 中为什么引入父子索引?

来源:快手 AI Agent 开发一面

新手答:“为了更精确地检索。”

高手答

父子索引解决的是 chunk 粒度的两难问题——检索精度和生成质量对 chunk 大小的需求是矛盾的

小 chunk(100-200 字):
  ✅ Embedding 语义集中,检索精度高
  ❌ 上下文断裂,模型拿到的信息不完整

大 chunk(500-1000 字):
  ✅ 上下文完整,模型能理解前因后果
  ❌ Embedding 被多个主题稀释,检索精度下降

父子索引的设计思路是解耦检索粒度和上下文粒度

flowchart TB
    D["原始文档"] --> P1["父 chunk 1(500字,完整段落)"]
    D --> P2["父 chunk 2(500字)"]
    P1 --> C1["子 chunk 1a(150字)"]
    P1 --> C2["子 chunk 1b(150字)"]
    P1 --> C3["子 chunk 1c(150字)"]
    P2 --> C4["子 chunk 2a(150字)"]
    P2 --> C5["子 chunk 2b(150字)"]

检索时用子 chunk(小粒度,精度高),返回时取父 chunk(大粒度,上下文完整)。这样同时拿到了检索精度和生成上下文质量。

实现方式:

  1. 离线阶段把文档切成大块(父 chunk),再把每个父 chunk 切成若干小块(子 chunk),子 chunk 记录 parent_id
  2. 对子 chunk 做 embedding 入向量库
  3. 检索时用 query 匹配子 chunk,拿到结果后通过 parent_id 取出对应的父 chunk
  4. 父 chunk 去重后送入 rerank 和 LLM

进阶:还可以做多级索引——文档摘要作为最顶层,段落作为中间层,句子作为最底层。先粗筛文档,再定位段落,最后精确到句子,逐层缩小范围。

差距在哪:新手只说了“更精确”但不知道为什么需要两层。高手点出了核心矛盾——检索需要小 chunk 精度、生成需要大 chunk 上下文——父子索引用“小粒度检索、大粒度返回”同时满足两个需求。面试官考的是你对 chunk 策略的深入理解。


Q:为什么在检索阶段引入BM25?它和向量检索怎样组合?

来源:快手 AI Agent 开发一面 【字节二面同题:多路检索 + 向量/关键词各解决什么】【淘天Agent开发同题:为什么加 BM25 + 具体解决了什么 bad case】

新手答:“BM25 是传统检索方法,加上它可以互补。”

高手答

为什么引入 BM25:向量检索擅长语义匹配,但在三类场景下表现很差:

  1. 精确术语:错误码 ERR_OOM_KILL、API 名称 getUserProfile——向量化后精确信息被稀释
  2. 低频专业词:Embedding 模型对训练数据中低频的词 embedding 质量差
  3. 新词/缩写:近期出现的产品名、术语,Embedding 模型没见过

BM25 基于词频和逆文档频率做精确匹配,恰好弥补这三个短板。实际项目中,加一路 BM25 召回通常能把整体 Recall 提升 10-15%。

组合方式:主流有两种融合策略:

方案一:分数融合(Score Fusion)
  final_score = α × normalize(vector_score) + (1-α) × normalize(bm25_score)
  需要先对两路分数做归一化(min-max 或 z-score),否则量纲不同无法直接加权

方案二:倒数排名融合(Reciprocal Rank Fusion, RRF)
  RRF_score(d) = Σ 1/(k + rank_i(d))
  只看排名不看分数,对分数分布差异免疫,k 通常取 60

比例怎么设:不是拍脑袋定的。初始值用 0.7 向量 + 0.3 BM25,然后在评估集上做 grid search:

遍历 α = [0.5, 0.6, 0.7, 0.8, 0.9]
对每个 α,计算 Recall@10 和最终回答质量
选最优 α。不同业务场景最优值不同:
  技术文档 → BM25 权重可以更高(精确术语多)
  日常对话 → 向量权重更高(同义表达多)

完整检索流程(从 query 到最终上下文):

flowchart LR
    Q["用户 Query"] --> QR["Query 预处理\n改写/扩展/意图识别"]
    QR --> V["向量检索\nTop-K₁"]
    QR --> B["BM25 检索\nTop-K₂"]
    V --> M["合并去重\n分数融合"]
    B --> M
    M --> RR["Rerank 精排\nCross-Encoder"]
    RR --> TK["Top-K 截断\n3~5 块"]
    TK --> CTX["上下文组装\n拼接 Prompt"]
    CTX --> LLM["LLM 生成回答"]
  1. Query 预处理:意图识别、查询改写、关键词提取
  2. 双路并行召回:向量路取 Top-20~50,BM25 路取 Top-10~20,并行执行
  3. 合并去重:按文档 ID 去重,同一文档被多路命中的加分
  4. Rerank 精排:用 Cross-Encoder(如 bge-reranker-v2、Cohere rerank)对 query-doc pair 做精细打分
  5. Top-K 截断:取精排后 Top-3~5 作为最终上下文
  6. Prompt 组装:把检索结果按相关度排序拼入 Prompt,交给 LLM 生成回答

更广义的多路检索策略

BM25 + 向量检索只是多路检索的起点。生产级 RAG 系统的多路检索可以更丰富:

检索路径 原理 擅长 不擅长
向量检索 语义相似度 同义改写、模糊表述 精确关键词、专有名词
BM25 词频-逆文档频率 精确关键词、专有名词 同义词、语义理解
元数据过滤 结构化字段匹配 时间范围、类别筛选 语义理解
知识图谱 实体关系遍历 多跳推理、关联查询 模糊意图

融合策略

多路召回后需要融合排序,主流方案:

  1. RRF(Reciprocal Rank Fusion)score = Σ 1/(k + rank_i),不需要归一化,简单有效
  2. 加权分数融合score = α × vector_score + β × bm25_score,需要分数归一化到同一量纲
  3. 级联融合:第一路做粗召回(高召回率),第二路在结果集上做精排(高精确率)

实际生产中,RRF 是默认首选——不需要调权重,对不同分布的分数天然鲁棒。

差距在哪:新手只说了”互补”两个字。高手说清了 BM25 解决的三类具体问题、两种融合方案的差异、比例调优方法论,以及完整的端到端检索流程。面试官考的是你对混合检索的工程化认知——不只是”加了 BM25”,而是知道怎么组合、怎么调参、怎么评估。

追问:RRF 融合中 K 参数一般取值多少?大一点、小一点对结果有什么影响?

RRF 公式:score(d) = Σ 1/(K + rank_i(d)),K 是一个平滑常数,决定了排名差异的敏感度

K 值 效果 适用场景
K 很小(如 1~10) Top-1 和 Top-2 的分数差异极大,”赢家通吃” 某一路检索质量明显优于其他路,希望它主导结果
K=60(默认值) 排名差异被适度平滑,各路贡献相对均衡 多路检索质量相当,需要综合各路信号
K 很大(如 200+) 排名差异几乎被抹平,趋近于”被多少路命中”的计数 更看重文档被多路召回的次数,而非在单路的排名

实际调参方法

1. 默认 K=60,大多数场景不需要调
2. 如果发现某一路检索远强于其他路 → 减小 K,让强路主导
3. 如果各路检索互补性强(向量找语义、BM25 找关键词) → 保持或增大 K
4. 在评测集上做 grid search:K ∈ {10, 30, 60, 100},看 Recall@K 和 MRR 变化

RRF 相比加权分数融合的核心优势:不需要归一化。不同检索路径的分数量纲和分布可能差异巨大(向量余弦 0~1,BM25 可能 0~50),RRF 只看排名不看分数,天然免疫分布差异。

追问:长尾或语义模糊的查询,怎么提升召回准确率?

长尾查询的核心问题是信息量不足——query 太短、太模糊、或用了非标准表述,导致检索系统无法精准匹配。

分层应对策略

flowchart TB
    Q[“长尾/模糊 Query”] --> D{“诊断 Query 类型”}
    D -->|”太短(1-2词)”| E1[“Query 扩展\nLLM 生成多个子查询”]
    D -->|”非标准表述”| E2[“同义改写\n术语标准化”]
    D -->|”意图不明”| E3[“多意图并行检索\n各意图独立召回再合并”]
    D -->|”领域专业词”| E4[“领域词典匹配\n+BM25 精确检索”]
    E1 --> R[“合并多路结果\nRRF 融合”]
    E2 --> R
    E3 --> R
    E4 --> R
    R --> RK[“Rerank 精排\n过滤噪声”]
策略 原理 适用场景
HyDE(假设性文档嵌入) 让 LLM 先”编”一篇假想答案,用假想答案的 embedding 去检索 query 极短但意图明确
Query 扩展 一条 query 变 3~5 条子 query,多路召回合并 query 模糊、可能有多种理解
领域词典 + BM25 对专业术语做标准化映射,用 BM25 精确匹配 医疗、法律、金融等术语密集领域
伪相关反馈(PRF) 第一轮检索的 Top-K 结果作为反馈,扩展 query 做第二轮检索 初始召回有部分相关结果但不够
渐进式放宽 初始用严格条件检索,无结果则逐步放宽约束 用户需求精确但知识库覆盖不足

实测中,HyDE 对短 query 提升最大(Recall +20~30%),但会增加一次 LLM 调用的延迟。Query 扩展是性价比最高的通用方案。

追问:基于 Milvus,BM25 与向量检索的分数归一化具体怎么做?

来源:阿里淘天 AI应用开发一面

两路检索的分数量纲完全不同——BM25 分数是无界的(取决于文档长度和词频),向量余弦相似度在 [-1, 1] 区间。不归一化直接加权会导致一路完全压过另一路。

三种归一化方案

方案 做法 优点 缺点
Min-Max 归一化 每路取当前 batch 的 min/max 映射到 [0,1] 简单直观 不同 query 的 min/max 波动大,不稳定
Z-Score 归一化 减均值除标准差 统计稳定 需要维护全局统计量
RRF(Reciprocal Rank Fusion) 不看分数只看排名:score = Σ 1/(K+rank_i) 无需归一化,对异常值鲁棒 K 参数需调优

Milvus 实战:Milvus 2.4+ 原生支持 hybrid search,内置 RRF 和 WeightedRanker 两种融合策略。推荐先用 RRF(K=60 是常用起点),如果对精排效果不满意再切 WeightedRanker 手动调权重。


Q:Rerank 后一般返回几个块?TopK 截断策略怎么设计?

来源:快手 AI Agent 开发一面 【字节二面追问:Re-rank 的作用 + 为什么有了向量相似度还需要它】【淘天Agent开发追问:低分阈值提前过滤策略】

新手答:“返回 5 个左右。”

高手答

通常返回 3~5 个块,这个范围是多个因素权衡的结果:

太少(1-2 个):信息可能不完整,复杂问题需要多个证据源佐证
太多(8-10 个):
  ① 噪声增加——低相关度的块干扰模型判断
  ② Lost in the Middle——模型对中间位置的信息关注度下降
  ③ Token 成本线性增长
  ④ 生成延迟增加

验证方法:在评估集上做消融实验:

固定其他参数,遍历 K = [1, 2, 3, 5, 8, 10]
对每个 K 计算:
  - 回答准确率(人工评判或 LLM-as-Judge)
  - Faithfulness(回答是否忠于检索结果)
  - Token 消耗和延迟
通常 K=3~5 是准确率和成本的甜点区间

TopK 截断策略

不建议用固定 K 一刀切。更好的做法是分数阈值 + 上限 K + 断崖检测三条件组合:

def adaptive_topk(reranked, max_k=5, min_score=0.6, score_drop=0.3):
    selected = []
    for i, result in enumerate(reranked[:max_k]):
        if result.score < min_score:
            break
        if i > 0 and (selected[-1].score - result.score) > score_drop:
            break
        selected.append(result)
    return selected if selected else [reranked[0]]

三个截断条件:

  1. 硬上限:最多取 max_k 个,防止上下文过长
  2. 绝对阈值:低于 min_score 的块直接丢弃——质量太差的证据不如没有
  3. 分数断崖检测:相邻块分数骤降超过阈值时截断——说明后面的块相关度显著下降

上下文过长/过短的处理

情况 处理策略
上下文过长 ① 对每个块提取关键句而非全文 ② 截断低分块 ③ 只保留和 query 最相关的段落
上下文过短 ① 增大召回 K 值,降低召回阈值 ② 启用父 chunk 扩展上下文 ③ 查询改写后重新检索 ④ 兜底:告知用户“知识库中未找到足够信息”

差距在哪:新手随便说了个数。高手用消融实验确定 K 值,用三条件自适应截断代替固定 K,且对上下文过长/过短都有处理方案。面试官考的是你调参时有没有数据支撑的方法论,以及面对边界情况的工程化处理。


Q:如何系统性提升 RAG 的检索相关度与生成效果?

来源:快手 AI Agent 开发一面

新手答:“换更好的 Embedding 模型。”

高手答

优化要分检索阶段生成阶段,两者瓶颈不同、手段不同:

检索阶段优化(提升相关度)

优化方向 具体手段 预期效果
Query 侧 查询改写、意图识别、HyDE 提升 query 和文档的匹配度
索引侧 父子索引、语义分块、元信息增强 提升文档的可检索性
模型侧 Embedding 微调、ReRank 微调 提升语义匹配精度
召回策略 混合检索(BM25 + 向量)、多路召回 提升覆盖率

生成阶段优化(提升回答效果)

优化方向 具体手段 预期效果
上下文质量 精排后截断、去除低分块、冲突检测 减少噪声干扰
Prompt 工程 引用约束、格式要求、拒答指令 提升回答的忠实度和格式规范
模型选择 复杂问题用强模型、简单问题用轻量模型 平衡质量和成本
后处理 答案事实性校验、引用来源标注 降低幻觉风险

优先级排序(投入产出比从高到低):

① 混合检索(加 BM25 路,成本几乎为零,Recall 提升 10-15%)
② Chunk 策略优化(父子索引、语义分块,一次性投入,长期受益)
③ 查询改写(显著提升长尾 query 的召回率)
④ ReRank 引入/微调(精排对最终质量影响大)
⑤ Embedding 微调(效果好但需要标注数据,成本较高)
⑥ Prompt 优化(持续迭代,每次小幅提升)

如何验证优化是否有效

离线评估:
  检索指标:Recall@K、MRR、NDCG
  生成指标:Faithfulness、Answer Relevancy、Completeness
  工具:RAGAS 框架自动化评估

在线验证:
  A/B 测试:新旧方案同时上线,对比用户满意度和任务完成率
  灰度发布:先 10% 流量验证,确认无回退再全量

关键原则:每次只改一个变量,否则无法归因

差距在哪:新手只想到换模型——这是最贵且不一定有效的做法。高手把优化拆成检索和生成两阶段,每个阶段有明确的手段和优先级排序,且有离线+在线的验证体系。面试官考的是你优化 RAG 系统时有没有系统性的方法论和效果验证闭环。

追问:实际项目中召回不准,你做过哪些改进?效果如何?

这种问题考的是实战排查方法论,而不是罗列技术。回答结构应该是“定位 → 归因 → 方案 → 效果”:

典型排查流程:

1. 定位:抽 100 条 bad case,标注失败原因
   → 发现 60% 是"召回了但排名靠后",30% 是"根本没召回",10% 是"召回正确但生成忽略"

2. 归因:
   "召回了但排名靠后" → Rerank 模型对当前领域的区分度不够
   "根本没召回" → query 用词和文档差异大(词汇鸿沟)
   "召回正确但生成忽略" → 上下文中噪声 chunk 干扰了模型

3. 方案(按投入产出比排序):
   ① 加 BM25 路 → 解决词汇鸿沟问题,0.5 天
   ② Query 改写 → 用 LLM 做同义扩展,1 天
   ③ Rerank 模型换成 bge-reranker-v2 → 精排能力提升,0.5 天
   ④ 上下文截断策略从 Top-5 改为"分数阈值 + Top-3 兜底" → 减少噪声,0.5 天

4. 效果:Recall@10 从 72% → 85%,端到端回答准确率从 68% → 81%

关键认知:优化不是“把所有方法都堆上去”,而是先做归因分析,找到占比最大的失败模式,针对性解决。每次改一个变量,用评测集验证,确认有效后再上线。


Q:RAG 系统的端到端性能如何优化?

来源:快手 AI Agent 开发一面

新手答:“用更快的向量数据库。”

高手答

RAG 的端到端延迟 = 检索延迟 + 排序延迟 + LLM 生成延迟。优化从三个层面切入:

检索层优化

① ANN 索引调优:HNSW 的 ef_construction 和 M 参数影响召回率和速度的平衡
② 预过滤:先用元数据(时间范围、文档类别)缩小候选集,再做向量检索
③ 并行召回:BM25 和向量检索并行执行,总延迟 = max(两路) 而非 sum(两路)
④ Embedding 缓存:高频 query 的 embedding 结果缓存,避免重复计算

模型层优化

① 流式输出(Streaming):用户不用等完整回答生成完才看到内容
② 模型路由:简单问题用小模型快速回答,复杂问题用大模型保证质量
③ 上下文压缩:减少送入 LLM 的 token 数——token 越少生成越快、成本越低
④ KV Cache 复用:相同 system prompt 部分的 KV cache 可以跨请求复用

架构层优化

flowchart LR
    Q["用户 Query"] --> C{"语义缓存\n命中?"}
    C -->|"命中"| R["直接返回缓存结果"]
    C -->|"未命中"| P["并行检索"]
    P --> RR["Rerank"]
    RR --> LLM["LLM 生成"]
    LLM --> W["写入缓存"]
    W --> R2["返回结果"]
① 语义缓存:用 embedding 相似度判断——"RAG 是什么"和"什么是 RAG"命中同一缓存
   命中率高的场景能减少 40-60% 的 LLM 调用
② 异步预处理:文档入库时预计算 embedding、预生成摘要,查询时直接用
③ 请求合并:短时间内相同/相似 query 合并为一次检索
④ 分级 SLA:核心业务走低延迟链路,非核心走高质量链路

各优化手段的延迟收益估算

优化手段 典型延迟收益 实现成本
并行召回 -30~50ms
语义缓存 命中时 -500ms+
流式输出 首 token 提前 200-500ms
Embedding 缓存 -20~50ms
模型路由 简单问题 -300ms+
上下文压缩 -100~300ms

差距在哪:新手只想到”换更快的数据库”——这只是检索层的一个点。高手从检索、模型、架构三层拆解了完整的性能优化方案,且给出了每个手段的延迟收益估算。面试官考的是你对 RAG 系统全链路延迟的分析和优化能力。


知识库与索引工程

Q:GraphRAG 在处理 Agent 复杂关联查询时的优势在哪里?

来源:淘天 AI Agent 一面 【蚂蚁AI应用开发二面同题:GraphRAG 理解与应用】【字节二面追问:多跳推理/复杂逻辑查询场景下 RAG 架构优化】

新手答:”用知识图谱检索,比向量搜索更准。”

高手答

先说清一个常见误解:GraphRAG ≠ 知识图谱检索。传统知识图谱检索是在预构建的三元组上做 SPARQL 查询,而 GraphRAG 是微软提出的一套完整架构——从文档自动构建知识图谱 + 社区摘要 + 本地/全局双搜索

传统 RAG 的瓶颈

传统 RAG 的检索单元是”文本块”(chunk),本质是扁平的。当用户的问题涉及多跳推理(A 和 B 的关系 → B 和 C 的关系 → 推导 A 和 C 的关系)或跨文档关联(信息分散在多个文档中)时,靠向量相似度只能找到局部相关的片段,无法把分散的信息串联起来。

传统 RAG 的困境:
用户问:”项目 A 的技术负责人和项目 B 的技术负责人之间有什么合作关系?”

文档1 提到:张三是项目 A 的技术负责人
文档2 提到:李四是项目 B 的技术负责人
文档3 提到:张三和李四共同发表了论文 X

→ 向量检索可能只召回文档1和文档2,漏掉关键的文档3
→ 即使三个都召回了,模型也需要自己做推理串联

GraphRAG 的架构与流程

flowchart TB
    D[“源文档集合”] --> EE[“实体与关系抽取\n(LLM 逐段提取)”]
    EE --> G[“构建知识图谱\n(实体节点 + 关系边)”]
    G --> CD[“社区检测\n(Leiden 算法)”]
    CD --> CS[“社区摘要生成\n(LLM 为每个社区\n生成主题摘要)”]
    
    Q[“用户查询”] --> R{“查询路由”}
    R -->|”具体实体/关系查询”| LS[“本地搜索\nLocal Search”]
    R -->|”全局性/主题性查询”| GS[“全局搜索\nGlobal Search”]
    
    LS --> G
    LS --> D
    LS -->|”从目标实体出发\n沿关系边遍历\n收集关联实体和原文”| A1[“聚合上下文”]
    
    GS --> CS
    GS -->|”遍历社区摘要\n提取相关主题\n逐层汇总”| A2[“Map-Reduce 聚合”]
    
    A1 --> LLM[“LLM 生成最终回答”]
    A2 --> LLM

GraphRAG 的三大核心优势

1. 多跳推理能力

知识图谱天然支持关系链遍历。上面那个例子,在图中就是:项目A → 技术负责人 → 张三 → 合作论文 → 李四 → 技术负责人 → 项目B。沿着关系边走两三跳就能拿到完整的关联信息,不需要模型自己推理。

2. 全局理解能力

这是 GraphRAG 最大的创新——社区摘要。通过社区检测算法把图中紧密关联的实体聚成社区,再用 LLM 为每个社区生成主题摘要。当用户问”这个领域的整体趋势是什么”这类全局性问题时,传统 RAG 只能拼凑零散的片段,GraphRAG 可以直接基于社区摘要回答。

3. 结构化实体消歧

同一个实体在不同文档中可能有不同的名称(”OpenAI”、”openai”、”Open AI”),图构建过程中会做实体合并和消歧,保证检索的一致性。

不同查询类型下的对比

查询类型 传统 RAG GraphRAG
单跳事实题(”X 是什么”) 效果好,向量检索足够 效果好,但构建成本更高
多跳关系题(”A 和 C 什么关系”) 容易漏召回,依赖模型推理 图遍历直接获取关系链
全局摘要题(”整体趋势是什么”) 只能拼凑片段,质量差 社区摘要直接回答,质量显著更好
对比分析题(”X 和 Y 的异同”) 需要分别检索再交叉,效果不稳定 两个实体的关联属性在图中直接可比
时序关系题(”先发生什么后发生什么”) 缺乏时序建模 可在关系边上标注时间属性

什么时候该用 GraphRAG

适合 GraphRAG 的场景:
✓ 文档集中有大量实体间的关系信息
✓ 用户经常问多跳推理或全局摘要类问题
✓ 实体消歧是痛点(同一实体多种写法)
✓ 需要可解释的推理路径

不适合 GraphRAG 的场景:
✗ 文档量小(<100篇),图太稀疏没有意义
✗ 查询以单跳事实题为主,传统 RAG 就够了
✗ 对实时性要求极高——图构建和社区摘要是离线批处理,延迟高
✗ 预算有限——图构建需要大量 LLM 调用(实体抽取 + 社区摘要)

成本方面,GraphRAG 的图构建阶段需要对每个文档段落调用 LLM 提取实体和关系,再对每个社区调用 LLM 生成摘要。对于 10 万篇文档的知识库,图构建的 LLM 调用成本可能是传统 RAG embedding 计算的 10-50 倍。但构建完成后,查询阶段的成本差异不大。

差距在哪:新手把 GraphRAG 等同于”知识图谱检索”——这忽略了 GraphRAG 最核心的创新:社区摘要和本地/全局双搜索架构。高手的回答从传统 RAG 的瓶颈讲起,解释了 GraphRAG 的完整管线(实体抽取 → 图构建 → 社区检测 → 摘要生成 → 双路搜索),并用对比表格说清了不同查询类型下的效果差异和适用边界。面试官考的不是”你知不知道 GraphRAG”,而是”你能不能说清楚它比传统 RAG 好在哪、什么时候该用、什么时候不该用”。

追问:GraphRAG 召回海量关联信息后,生成阶段如何用 Self-Reflection 或 CoT 策略过滤检索噪声?

来源:蚂蚁 AI应用开发 二面

GraphRAG 的 Community Summary + 三元组召回会返回大量关联信息,其中不少是”图上相关但问题无关”的噪声。生成阶段的过滤策略:

CoT 策略(生成前过滤):在生成 Prompt 中要求模型先做一步”证据筛选”——逐条判断每个召回片段与当前问题的相关性,只保留高相关的片段再生成回答。这相当于在生成阶段内置了一个轻量 Rerank。

Self-Reflection 策略(生成后校验):先基于全部召回信息生成初版回答,然后用反思 Prompt 检查:”回答中是否引用了与问题无关的信息?是否遗漏了关键关联?” 发现问题后定向修正。

两者结合:CoT 做前置过滤降低噪声,Self-Reflection 做后置校验捕获遗漏。前者减少”答非所问”,后者减少”漏答关键点”。

追问:GraphRAG 的三元组是用 LLM 抽取的吗?怎么保证不幻觉?

来源:腾讯 AI 应用开发二面

是的,三元组(实体-关系-实体)通常由 LLM 抽取,但不能无条件信任 LLM 的抽取结果

抽取流程

文档段落 → LLM 提取实体 + 关系 → 结构化三元组 → 合并去重 → 入图

幻觉控制的四层防线

  1. Prompt 约束:在抽取 Prompt 中明确要求”只提取文本中明确提到的实体和关系,不推断”。给出具体的输出格式和 Few-shot 示例,减少模型自由发挥的空间
  2. Schema 约束:预定义允许的实体类型和关系类型(如医学领域只允许”疾病-症状-药物-基因”四类实体)。LLM 抽出的实体必须属于预定义类型,否则丢弃
  3. 多轮验证:同一段文本让 LLM 抽取两次,只保留两次结果一致的三元组(投票机制)。或者用一个 Critic 模型检查抽取结果是否有文本依据
  4. 溯源校验:每个三元组保留源文本引用。后续使用时可以回查原文验证

实体抽取错误的排查方法

  • 随机抽样检查:从抽取结果中随机抽 100 条三元组,人工校验准确率
  • 高频实体审查:按实体出现频次排序,高频实体更值得校验(一个错误的高频实体会污染大量关系)
  • 孤立节点检查:只有一条边的实体往往是噪声

追问:Community Summary 的设计思路是什么?

来源:腾讯 AI 应用开发二面

Community Summary 是 GraphRAG 最核心的创新——把知识图谱从”查询时遍历”变成”预计算摘要”。

设计思路

  1. 社区检测:用 Leiden 算法对知识图谱做社区划分,把紧密关联的实体聚成社区(类似”话题簇”)
  2. 层次化摘要:对每个社区调用 LLM 生成一段自然语言摘要,描述”这个社区里的实体之间有什么关系、核心主题是什么”
  3. 多层级:社区可以递归聚合——小社区合成大社区,大社区有更宏观的摘要。查询时根据问题的抽象程度选择合适的层级

为什么这样设计:传统知识图谱回答全局性问题(”这个领域的整体趋势是什么”)需要遍历大量节点,成本高且容易遗漏。Community Summary 把全局知识预压缩成摘要,查询时直接检索摘要即可——用离线计算换在线效率。

追问:GraphRAG 的叶子节点在智能客服中如何触发?

来源:币安 AI大模型实习一面

GraphRAG 的图结构是分层的:根节点(全局摘要)→ 社区节点(主题簇摘要)→ 实体节点 → 叶子节点(原始文档 chunk / 三元组细节)。不同粒度的问题触达不同层级。

触发机制——Global Search vs Local Search

用户问题类型 搜索模式 是否触达叶子节点 示例
全局性/概览性 Global Search 否,社区摘要足够 “你们有什么售后服务”
具体实体细节 Local Search 是,需要原始文档细节 “iPhone 15 能不能 7 天无理由退”
需要外部数据 Local + API 调用 是,且需调用外部系统 “我的订单 123456 什么时候到”

叶子节点的触发流程

flowchart LR
    Q[“用户 query”] --> NER[“实体识别\n提取产品名/订单号/功能名”]
    NER --> LOC[“图定位\n在知识图谱中找到目标实体节点”]
    LOC --> TRAV[“关系遍历\n沿实体的关系边向下到叶子节点”]
    TRAV --> AGG[“上下文聚合\n叶子内容 + 关系链 + 社区摘要”]
    AGG --> LLM[“LLM 生成回答”]

工程实现要点:用意图分类器判断问题粒度——粗粒度走 Global(快但粗),细粒度走 Local 到叶子节点(慢但准)。两者可以级联:先 Global 判断主题范围确认实体所属社区,再 Local 深入到叶子节点获取具体细节。

智能客服中的典型场景:用户问”我买的 XX 产品能退吗” → 实体识别提取产品名 → 图中定位到该产品节点 → 沿”退货政策”关系边遍历到叶子节点(具体退货条件、时间限制、操作步骤)→ 聚合上下文生成精确回答。


Q:Embedding 模型怎么选?选型时考虑哪些因素?

来源:高德 AI 应用开发实习一面

新手答:“用 OpenAI 的就行。”

高手答

Embedding 模型选型不是“哪个最有名用哪个”,而是要从六个维度系统评估

维度 考虑因素 说明
语言支持 中文/英文/多语言 中文场景优先选中文优化模型
向量维度 768/1024/1536 维度越高精度越好但存储和检索成本越大
检索精度 MTEB/C-MTEB 排名 用公开基准评估基础能力
推理速度 tokens/sec 影响索引构建和在线检索延迟
部署成本 模型大小、GPU 需求 小模型可 CPU 部署
最大长度 512/8192 tokens 影响 chunk 大小设计

主流模型对比

模型 来源 特点
BGE 系列 BAAI(智源) 中文效果好,开源,多尺寸可选
M3E Moka 中文优化,轻量
text-embedding-3 OpenAI 效果好但需 API 调用,成本高
jina-embeddings-v3 Jina AI 多语言,支持长文本
GTE Alibaba 中英文均衡

实际选型决策流程

flowchart TB
    S["开始选型"] --> L["确定语言需求"]
    L -->|"中文为主"| CN["优先 BGE / M3E / GTE"]
    L -->|"英文为主"| EN["优先 E5 / GTE / OpenAI"]
    L -->|"多语言"| ML["优先 jina-embeddings-v3"]
    CN --> EV["在自己的数据上做评估"]
    EN --> EV
    ML --> EV
    EV --> COST["对比部署成本"]
    COST --> FT{"是否需要微调?"}
    FT -->|"领域术语多"| YES["选开源模型\n用业务数据微调"]
    FT -->|"通用场景"| NO["直接部署\n定期评估效果"]
  1. 先确定语言需求:中文场景优先选中文优化模型,不要盲目选英文模型
  2. 跑 domain-specific evaluation:不只看 MTEB/C-MTEB 排名,必须在自己的数据上评估。公开 benchmark 上排名第一的模型,在你的业务数据上可能排第五
  3. 对比部署成本:API 调用模型(如 OpenAI)按量计费,自部署模型有 GPU 成本。数据量大时自部署更划算
  4. 考虑是否需要微调:领域术语多的场景(医疗、法律、金融),通用模型的 embedding 质量会明显下降,这时选开源模型做微调是更好的路径

关键认知:公开 benchmark 排名不等于你的场景效果。必须在自己的数据上做 A/B 评测——构建几百条 (query, relevant_doc) 的评估集,跑 Recall@K 和 MRR,用数据说话。

差距在哪:新手直接选最有名的模型。高手从六个维度系统评估,坚持在业务数据上做 domain-specific evaluation,而不是盲目跟 benchmark 排名。面试官考的是你选型时有没有工程化的方法论,以及对“通用模型 vs 领域适配”这个 tradeoff 的理解。


Q:知识库整体怎么设计?

来源:高德 AI 应用开发实习一面 【字节二面同题:RAG 完整流程从文档切块到生成】

新手答:“把文档存到向量数据库。”

高手答

知识库不是“把文档扔进向量数据库”——它是一个完整的系统,涵盖文档处理、存储索引、检索召回、质量保障和运维五个层面。

整体架构

flowchart TB
    subgraph offline["离线处理"]
        direction TB
        RAW["原始文档\nPDF / Word / HTML / Markdown"] --> PRE["预处理\n格式转换、清洗、去噪"]
        PRE --> CHK["分块\n递归分块 / 语义分块"]
        CHK --> EMB["Embedding 计算"]
        CHK --> META["元数据提取\n来源、日期、类别"]
        EMB --> VDB["向量数据库\nMilvus / Qdrant"]
        META --> MDB["元数据库\nElasticsearch / PostgreSQL"]
        CHK --> INV["倒排索引\nElasticsearch"]
    end

    subgraph online["在线检索"]
        direction TB
        Q["用户 Query"] --> QR["查询改写"]
        QR --> MR["多路检索\n向量 + BM25 + 元数据过滤"]
        MR --> RR["Rerank 精排"]
        RR --> CA["上下文组装"]
        CA --> LLM["LLM 生成回答"]
    end

五层设计

1. 文档处理层——把非结构化文档变成可检索的结构化数据:

  • 格式解析:PDF / Word / HTML → 纯文本。不同格式的解析难度差异很大——PDF 的表格和多栏排版是重灾区
  • 清洗去噪:去掉页眉页脚、广告、导航栏等无关内容
  • 元数据提取:来源、创建日期、类别、作者——这些元信息在检索时用于过滤和排序

2. 索引层——三种索引各司其职:

  • 向量索引(FAISS / Milvus):语义检索,处理同义改写和模糊表述
  • 倒排索引(Elasticsearch):关键词检索,处理精确术语和专有名词
  • 元数据索引(过滤字段):结构化筛选,处理时间范围、文档类别等约束

为什么需要三种?因为不同类型的查询需要不同的索引——“退货政策”需要语义检索,“ERR_OOM_KILL”需要关键词检索,“最近一周的变更记录”需要元数据过滤。

3. 检索层——查询理解 + 多路召回 + 精排:

  • 查询改写(多维度扩展用户意图)
  • 多路召回(向量 + BM25 + 元数据过滤并行)
  • Rerank 精排(Cross-Encoder 细粒度打分)
  • 上下文组装(Top-K 截断、信息去冗余)

4. 质量保障层——知识库不是建完就不管了:

  • 文档去重:内容指纹检测近重复文档
  • 新鲜度追踪:过期文档标记或降权
  • 冲突检测:同一主题的矛盾信息标记提醒
  • 覆盖分析:哪些主题的文档充足,哪些有缺口

5. 运维层——保证知识库持续可用:

  • 增量更新管线:新文档自动入库,变更文档自动重新索引
  • 版本管理:文档变更可追溯
  • 访问控制:不同用户看到不同范围的文档
  • 监控:检索命中率、用户反馈、知识库健康度

关键设计决策

决策点 选项 权衡
Chunk 大小 256 / 512 / 1024 tokens 粒度越小检索越精确,但上下文越不完整
单索引 vs 多索引 只用向量 vs 向量 + BM25 + 元数据 多索引召回率高,但系统复杂度增加
实时更新 vs 批量更新 文档变更立即入库 vs 每天定时批量处理 实时性 vs 系统稳定性和计算成本

差距在哪:新手认为知识库就是向量数据库。高手设计了五层系统——文档处理、索引、检索、质量保障、运维——覆盖了从数据入库到持续运维的完整生命周期。面试官考的是你对知识库的认知是“一个组件”还是“一套系统”。


Q:分块策略怎么设计?不同策略的优缺点?

来源:高德 AI 应用开发实习一面

新手答:“按 500 字切一段。”

高手答

分块(Chunking)是 RAG 中影响效果最大的单一设计决策——切得不好,后面的检索和生成再怎么优化都救不回来。

五种主流分块策略对比

策略 原理 优点 缺点 适用场景
固定长度分块 按 token 数切分 实现简单、大小可控 可能切断语义 结构不清晰的纯文本
语义分块 按段落/章节/标题切分 保持语义完整 块大小不均匀 有清晰结构的文档
递归分块 先尝试大单元分割,不满足再细分 平衡语义和大小 实现复杂 通用场景首选
Sliding Window 固定大小 + 重叠区域 防止边界信息丢失 存储冗余 精度要求高的场景
Agentic Chunking 用 LLM 判断分块边界 最智能 成本高、速度慢 高价值文档

关键参数设计

Chunk Size(块大小):256 ~ 1024 tokens
  太小(< 200 tokens)→ 语义不完整,一个 chunk 可能只有半句话
  太大(> 1500 tokens)→ 噪声多,embedding 被多个主题稀释,召回精度低

Overlap(重叠区域):chunk size 的 10 ~ 20%
  作用:防止切断句子或段落,保证边界处的信息在相邻 chunk 中都有

Metadata(元信息):每个 chunk 保留——
  source:来源文档标识
  page:所在页码
  section_title:所属章节标题
  parent_doc_id:父文档 ID(用于父子索引)

父子索引策略——同时解决检索精度和上下文完整性:

flowchart TB
    DOC["原始文档"] --> PARENT["父 chunk(500-1000 tokens)\n完整段落,上下文丰富"]
    PARENT --> CHILD1["子 chunk A(150-300 tokens)\n精确语义,检索用"]
    PARENT --> CHILD2["子 chunk B(150-300 tokens)"]
    PARENT --> CHILD3["子 chunk C(150-300 tokens)"]

    Q["用户 Query"] --> SEARCH["用 Query 匹配子 chunk\n(小粒度,精度高)"]
    SEARCH --> RETURN["返回对应的父 chunk\n(大粒度,上下文完整)"]

用小 chunk 做检索(精度高),返回大 chunk 给 LLM(上下文完整)——两全其美。

递归分块的实现逻辑

分割优先级:
  1. 先按 "\n\n"(段落)分割
  2. 段落仍然太大 → 按 "\n"(换行)分割
  3. 还是太大 → 按 "。"(句号)分割
  4. 再不行 → 按空格或字符数强制切分

每一级都尽可能保持语义完整,只有上一级切不够小时才降到下一级。

实践建议:从递归分块(LangChain 的 RecursiveCharacterTextSplitter)作为 baseline 开始,然后根据文档类型和评估结果调整。不同类型的文档用不同策略——技术文档用语义分块(按标题切),日志文件用固定长度分块,合同文档用 Agentic Chunking。

差距在哪:新手用固定长度一刀切,不考虑语义。高手对比了五种策略的优劣势,理解 chunk size 和语义完整性的 tradeoff,用父子索引同时满足检索精度和上下文质量,并且知道分块策略必须根据文档类型和评估结果来调整——不存在”万能的分块方案”。面试官考的是你对 RAG 管线中最关键的预处理环节有没有深入的工程理解。

追问:chunk 切分的边界修正怎么做?比如表格被切成了两半怎么处理?

来源:腾讯 AI 应用开发二面

边界修正是分块策略中最容易被忽视的工程细节。切错边界比不切更糟——一个被拦腰截断的表格,检索到任何一半都无法提供完整信息。

主流边界修正策略

  1. 结构感知切分:先用文档解析器识别出结构元素(标题、段落、表格、代码块、列表),以完整结构元素为最小切分单位,绝不从结构内部切断
  2. Overlap(重叠窗口):相邻 chunk 之间保留 10-20% 的重叠区域。即使切断了,下一个 chunk 的开头会包含上一个的结尾,信息不会完全丢失
  3. 表格特殊处理:表格作为独立 chunk,不参与常规切分。如果表格超长,按行切分但每个子 chunk 都保留表头(表头是理解表格的关键)

表格被切成两半的检测和修复

检测:解析文档时标记所有表格的起止位置 → 切分后检查是否有 chunk 边界
     落在表格内部 → 有则标记为”边界异常”
修复:把跨越表格的两个 chunk 合并,或者把表格提取为独立 chunk

实际工程中,最稳的做法是先提取后切分:先用文档解析器把表格、图片、代码块等结构化元素单独提取出来,剩余的纯文本再做常规分块。这样结构化元素天然不会被切断。

追问:领域文档(法律/医疗)的语义单元跨 chunk 被切散,怎么办?

来源:字节 AI 一面(法律 RAG 项目深挖)

法律文档中,“第三条第二款”和“第三条之二”是完全不同的法律概念——前者是第三条下的第二个分款,后者是独立的第三条之二。如果切片把这类语义单元切散,模型会混淆引用关系,直接导致回答错误。

领域感知切片的四层方案

层级 做什么 具体实现
结构解析 用领域规则识别语义边界 法律:条/款/项层级正则;医疗:诊断-处方-医嘱分段
边界保护 语义单元不可被切断 将“第X条”到“第X+1条”之间的内容视为原子块
层级 metadata 每个 chunk 携带完整的上下文链 {law: "民法典", chapter: "第三编", article: "第三条", clause: "第二款"}
交叉引用 法条互相引用时双向关联 “依据第五条”→ 在 chunk metadata 中标记依赖关系

核心原则:通用切片策略(按 token 数、按段落)是 baseline,领域文档必须叠加领域感知的边界规则。切片粒度不是工程参数,是业务决策——需要和领域专家一起定义“什么是不可切断的最小语义单元”。


Q:为什么 Claude Code 不用 RAG 检索代码,而是直接用 grep?

来源:字节 Agent 开发实习一面

新手答:“可能是还没来得及实现 RAG。”

高手答

这道题非常好,它直接挑战了“RAG 万能论”的假设。答案是:对于代码检索场景,grep 在多个维度上优于 RAG,这是一个深思熟虑的架构选择,而不是技术局限。

grep 胜过 RAG 的五个原因

维度 grep RAG
精确性 grep "functionName" 精确匹配,100% 准确率 向量检索返回“语义相似”的结果,可能漏掉目标函数
实时性 直接操作当前文件系统,永远是最新的 需要索引,代码一改索引就可能过时(开发时代码频繁变动)
成本 纯 CPU 计算,免费,耗时 <100ms 需要 Embedding 计算、向量数据库,索引需随代码变更重建
可解释性 结果确定且可追溯——匹配到哪个文件第几行一清二楚 结果取决于 Embedding 质量,无法解释“为什么返回这个结果”
代码结构利用 代码高度结构化(函数、类、import 有固定模式),grep + 正则能精准利用这种结构 Embedding 会丢失代码的结构信息,把代码当成普通文本处理

什么时候 RAG 比 grep 更好

grep 不是万能的,以下场景 RAG 占优:

自然语言查询:"认证逻辑在哪里?"
  → grep 无法处理,因为代码中没有"认证逻辑"这个字符串
  → RAG 的语义检索能找到 auth_middleware.py、login_handler.py

概念级搜索:"找到类似的实现"
  → grep 只能匹配精确字符串
  → 向量检索能找到语义相似的代码片段

跨模块依赖分析:"哪些模块依赖了这个服务?"
  → grep 能做简单的 import 搜索,但知识图谱 / RAG 能发现间接依赖

Claude Code 的实际策略——渐进式披露(Progressive Disclosure)

flowchart TB
    Q["需要查找代码信息"] --> C1{"精确符号查找?"}
    C1 -->|"是"| G["grep / find\n(免费、精确、实时)"]
    C1 -->|"否"| C2{"需要目录结构?"}
    C2 -->|"是"| LS["ls / directory listing\n(零成本)"]
    C2 -->|"否"| C3{"需要语义理解?"}
    C3 -->|"是"| R["Read 文件内容\n(按需加载)"]
    C3 -->|"否"| G

核心原则是从最廉价、最精确的工具开始,按需逐步升级到更昂贵的工具。grep 和 find 是第一层(零成本、高精度),读文件是第二层(中等成本),只有在前两层无法满足需求时才考虑更重的检索手段。

这道题的 meta 启示

最佳检索方法取决于查询类型。不要默认使用 RAG——有时候更简单的工具反而更好。这个原则不仅适用于代码检索,也适用于所有 Agent 的工具选择:先用廉价精确的工具,只在必要时才升级到昂贵复杂的工具。这就是渐进式披露在工具选择层面的体现。

差距在哪:新手假设 RAG 是万能的,认为不用 RAG 是技术缺陷。高手理解 grep 在精确性、实时性、成本、可解释性和代码结构利用五个维度上的优势,并且看到了 Claude Code 的渐进式披露策略是一个深思熟虑的架构选择——从廉价精确工具开始,按需升级。面试官考的是你能不能跳出“RAG 万能论”的思维定式,根据场景选择最合适的检索方案。


Q:向量数据库怎么选型?不同规模下该用什么方案?

来源:阿里国际 AI 应用研发二面 【淘天Agent开发追问:为什么选 pgvector 而不是其他向量数据库】

新手答:“用 Milvus 就行。”

高手答

向量数据库的选型不是“挑一个最有名的”,而是按数据规模分层选择,再根据业务需求做筛选

按数据规模分层推荐

小规模(< 10 万条向量):pgvector / SQLite-VSS

直接在现有关系型数据库上加向量扩展。运维成本几乎为零,不需要额外部署服务。对于早期项目和 PoC 阶段完全够用。

中等规模(10 万 - 1000 万条向量):Milvus Lite / Qdrant / Weaviate

需要专用的向量数据库。这个量级对索引类型(HNSW / IVF)、过滤能力、持久化都有要求。这三个都支持元数据过滤,且社区活跃、文档完善。

大规模(1000 万条以上):Milvus 集群 / Pinecone / Zilliz Cloud

需要分布式架构和水平扩展能力。Milvus 集群支持多副本和分片;Pinecone 和 Zilliz Cloud 是全托管服务,运维成本低但按量计费。

选型维度对比

选型维度 关键问题 影响选择
数据规模 当前多少条?预期增长到多少? 决定单机 vs 分布式
过滤需求 是否需要 metadata 过滤(按时间、类别筛选)? 排除不支持过滤的纯 ANN 方案
延迟要求 P99 延迟要求多少 ms? 影响索引类型和部署架构
运维复杂度 团队有没有专人运维? 决定自建 vs 托管服务
成本 预算约束是什么? 开源自建 vs 商业托管
混合检索 是否需要向量 + 关键词混合搜索? 部分方案原生支持(Qdrant、Weaviate),部分需要外接 ES

关键考量:大多数真实 Agent 场景都需要元数据过滤——比如“只检索最近 30 天的文档”“只查某个品类下的内容”。这个需求会直接淘汰一些纯 ANN 方案(如裸用 FAISS),因为它们不支持带条件的向量检索。

生产建议先简单后迁移。项目初期用 pgvector 快速验证效果,等数据量或性能真正成为瓶颈时再迁移到专用向量数据库。过早引入分布式向量数据库是典型的过度工程——你花两周部署 Milvus 集群,结果数据才 5 万条,pgvector 10ms 就能搞定。

差距在哪:新手只给一个品牌名。高手按数据规模分层推荐,且给出了选型维度和“先简单后迁移”的工程建议。面试官考的是你对向量检索基础设施的全面认知。


Q:升级 Embedding 模型后,怎么保证索引和检索向量的逻辑一致性?

来源:阿里国际 AI 应用研发二面

新手答:“重新跑一遍索引就行了。”

高手答

核心问题:旧文档用 Model_v1 编码入库,新查询用 Model_v2 编码检索——两个模型的向量空间不对齐,导致检索质量断崖式下降。即使两个模型都很强,它们学到的向量空间是不同的,v1 空间里的“近邻”在 v2 空间里可能完全不是近邻。

“全量重建索引”是正确的方向,但对于百万级文档,全量重建需要数小时甚至数天,在此期间系统要么不可用,要么用旧模型继续服务(效果变差)。所以真正的挑战不是“能不能重建”,而是“怎么平滑过渡”。

三种升级策略

策略一:双索引并行

在旧索引继续服务的同时,后台用新模型构建新索引。
新索引构建完成后,做一次原子切换——流量瞬间从旧索引切到新索引。

优点:切换瞬间完成,用户无感知。缺点:过渡期需要双倍存储成本,且切换前无法验证新索引的线上效果。

策略二:渐进式迁移

给每个文档向量打上 embedding_model_version 标签。
过渡期内,查询同时用 v1 和 v2 两个模型编码,分别检索对应版本的分区,合并结果。
后台逐步将旧文档用新模型重新编码,完成后删除旧分区。

优点:平滑过渡,任何时刻系统都可用。缺点:过渡期查询要编码两次、搜索两次,延迟翻倍。

策略三:版本化索引 + 灰度切换

新索引构建完成后,不立即全量切换,而是先导流 5-10% 到新索引。
对比新旧索引的线上指标(召回率、相关性、用户点击率)。
指标达标 → 逐步扩大流量比例直到全量切换。
指标异常 → 立即回滚到旧索引。

优点:风险最低,有数据验证。缺点:验证周期长,需要流量分配基础设施。

完整的双索引过渡流程

flowchart TB
    START["触发模型升级"] --> BUILD["后台构建新索引\n(Model_v2 编码全量文档)"]
    BUILD --> OLD["旧索引继续服务\n(Model_v1)"]
    BUILD --> DONE{"新索引\n构建完成?"}
    DONE -->|"否"| OLD
    DONE -->|"是"| CANARY["灰度切换\n5% 流量到新索引"]
    CANARY --> CHECK{"质量指标\n达标?"}
    CHECK -->|"是"| SCALE["逐步扩大流量\n10% → 50% → 100%"]
    CHECK -->|"否"| ROLLBACK["回滚到旧索引\n排查问题"]
    SCALE --> FULL["全量切换完成"]
    FULL --> CLEAN["清理旧索引\n释放存储"]

工程保障措施

  1. 始终存储原始文本:向量可以重算,原始文本不能丢。每个 chunk 必须保留原始文本,这样任何时候都能用新模型重新编码
  2. 版本标记每个向量embedding_model_version 字段必须持久化到向量记录中,方便区分哪些文档已迁移、哪些还没有
  3. 自动化质量回归测试:维护一组 (query, expected_relevant_docs) 的黄金测试集,每次模型升级后自动跑 Recall@K 和 MRR,低于阈值则阻断上线

差距在哪:新手只想到“重建”——这是正确的第一步但忽略了过渡期的可用性。高手给出了双索引并行、渐进式迁移、灰度切换三种策略,且强调了版本标记和自动化质量回归测试。面试官考的是你对向量检索系统升级的工程化思维——不是“能不能升级”,而是“怎么平滑升级”。


进阶检索架构

Q:Deep Research 在代码层面是怎么实现的?和普通 RAG 有什么区别?

来源:bilibili AI研发实习一面

新手答:“就是多搜几次,然后总结一下。”

高手答

Deep Research 不是“多搜几次”——它是一种Agent 驱动的迭代检索-合成架构,核心区别在于检索策略是动态的、由 Agent 在运行时根据已有信息决定下一步查什么。

和普通 RAG 的本质区别

维度 普通 RAG Deep Research
检索次数 一次(query → 检索 → 生成) 多次迭代(每轮检索结果影响下一轮查询)
查询生成 用户原始 query 或简单改写 Agent 根据已有信息动态生成子查询
知识综合 拼接检索结果给模型 逐步构建结构化的知识图,跨文档关联
覆盖判断 无——检索一次就结束 Agent 评估“信息是否足够”,不够则继续检索
输出 短回答 长篇结构化报告

代码层面的核心实现

用 LangGraph 实现 Deep Research 的典型架构:

flowchart TB
    Q["用户研究问题"] --> PLAN["规划节点\n生成研究大纲 + 子问题列表"]
    PLAN --> SEARCH["检索节点\n对当前子问题做多源检索"]
    SEARCH --> ANALYZE["分析节点\n提取关键信息 + 评估覆盖率"]
    ANALYZE --> CHECK{"覆盖率\n足够?"}
    CHECK -->|"否:发现知识缺口"| REFINE["改写节点\n生成新的子查询"]
    REFINE --> SEARCH
    CHECK -->|"是"| SYNTH["综合节点\n跨文档知识整合"]
    SYNTH --> REPORT["报告生成节点\n结构化输出 + 引用标注"]

关键实现细节

1. 规划节点——把大问题拆成可检索的子问题

def plan_node(state):
    prompt = f"""将以下研究问题拆解成 3-5 个具体的子问题,
    每个子问题应该能通过一次文献检索回答:
    
    研究问题:{state["research_question"]}
    """
    sub_questions = llm.invoke(prompt)
    return {"sub_questions": sub_questions, "current_index": 0}

2. 检索节点——对每个子问题做多源并行检索

async def search_node(state):
    query = state["sub_questions"][state["current_index"]]
    results = await asyncio.gather(
        search_semantic_scholar(query),
        search_arxiv(query),
        search_web(query),
    )
    merged = deduplicate(flatten(results))
    return {"search_results": merged}

和普通 RAG 只查一个向量库不同,Deep Research 通常并行查询多个数据源(学术数据库、网页、专利库),然后合并去重。

3. 分析节点——提取信息并评估覆盖率

这一步是 Deep Research 的核心——Agent 不只是检索,还要评估检索结果的充分性。如果发现知识缺口(某个子问题还没有足够的证据支撑),生成新的查询再检索。

def analyze_node(state):
    extracted = llm.invoke(f"""从以下检索结果中提取关键信息:
    {state["search_results"]}
    
    已有知识:{state.get("accumulated_knowledge", "")}
    当前子问题:{state["sub_questions"][state["current_index"]]}
    
    输出:1. 关键发现  2. 置信度评估  3. 知识缺口
    """)
    return {
        "accumulated_knowledge": state.get("accumulated_knowledge", "") + extracted.findings,
        "gaps": extracted.gaps,
        "coverage_sufficient": extracted.confidence > 0.8
    }

4. 迭代控制——防止无限检索

def should_continue(state):
    if state["coverage_sufficient"]:
        return "synthesize"
    if state["iteration_count"] >= MAX_ITERATIONS:  # 通常 3-5 轮
        return "synthesize"
    return "refine_query"

必须设置最大迭代次数,否则 Agent 可能陷入“总觉得信息不够”的无限循环。

5. 综合节点——跨文档知识整合

普通 RAG 直接把检索结果拼给模型生成答案。Deep Research 需要先做跨文档的知识整合——对比不同来源的观点、识别共识和争议、构建时间线和因果关系——然后基于整合后的结构化知识生成报告。

工程上的核心难点

难点 解决方案
迭代多轮导致上下文膨胀 每轮只保留结构化摘要,原始检索结果不进入下一轮上下文
多源检索结果质量参差不齐 来源权威性评分 + ReRank 精排
幻觉引用风险高 所有事实必须关联到具体检索结果的 ID,生成后做引用校验
检索成本高 设最大迭代次数 + 子问题优先级排序(先查最关键的)

差距在哪:新手把 Deep Research 理解为”多搜几次加总结”。高手在代码层面展示了完整的迭代检索-分析-改写循环,核心是 Agent 驱动的动态查询生成和覆盖率评估——每轮检索的 query 不是预设的,而是根据已有信息实时生成的。面试官考的是你能不能把 Deep Research 从产品概念转化为可实现的 Agent 管线。


Q:PDF 解析用什么工具?Layout-aware Parsing 是怎么做的?

来源:腾讯 AI 应用开发二面

新手答:”用 PyPDF 读文本就行。”

高手答

PyPDF 只能提取纯文本流,完全丢失版面布局信息——表格变成散乱的文字、双栏论文的左右栏被混在一起、图片标注和正文混淆。RAG 的质量上限取决于解析质量,解析错了后面全链路都救不回来。

主流 PDF 解析工具对比

工具 原理 优势 劣势 适合场景
PyPDF / pdfplumber 文本流提取 快、零依赖 丢失布局,表格乱 纯文本 PDF
Unstructured 规则 + ML 混合 支持多格式,社区活跃 表格准确率一般 通用文档
Marker 视觉模型 版面还原度高 速度慢 学术论文
MinerU (PDF-Extract-Kit) 版面检测 + OCR 表格还原强,开源 资源消耗大 复杂排版 PDF
商业方案(Azure Document Intelligence) 云端 ML 准确率最高 收费、数据出境 企业级生产

Layout-aware Parsing 的核心思路

flowchart LR
    A[“PDF 页面图像”] --> B[“版面检测\n(识别文本/表格/图片区域)”]
    B --> C[“区域分类\n(标题/正文/表格/脚注)”]
    C --> D[“分区提取\n(文本用OCR,表格用专门解析器)”]
    D --> E[“阅读顺序重建\n(双栏→单栏序列)”]
    E --> F[“结构化输出\n(带标签的文本块)”]

关键是先”看”再”读”——不是直接提取文本流,而是先用视觉模型识别页面上每个区域的类型和位置,然后按阅读顺序依次提取。

选型建议:学术论文用 Marker 或 MinerU(版面复杂但格式相对规范),企业文档用 Unstructured + 自定义后处理,对准确率要求极高的场景用商业方案。没有万能工具,必须横向对比——用同一批标注好的文档测试不同工具的准确率,选最适合自己文档类型的。

差距在哪:新手用 PyPDF 读文本,遇到表格和复杂排版就束手无策。高手理解 Layout-aware Parsing 的核心是”先视觉理解版面结构,再分区提取内容”,并能对比不同工具的适用场景做选型。面试官考的是你对 RAG 管线最上游(文档解析)的工程理解——这一步的质量决定了后续所有环节的上限。


Q:RAG 知识库的噪声剔除和文档去重怎么做?

来源:腾讯 AI 应用开发二面 【淘天Agent开发追问:防止 AI 批量生成虚假数据投毒】

新手答:”看着删。”

高手答

知识库的质量直接决定 RAG 的效果上限。垃圾进,垃圾出——再好的检索和生成也无法弥补知识库本身的噪声。

噪声剔除分三层

层次 噪声类型 剔除方法
文档级 空文档、格式损坏、非目标语言 规则过滤(长度/编码/语种检测)
段落级 页眉页脚、版权声明、目录、广告 正则匹配 + 分类器(训练一个轻量模型区分正文和噪声)
语义级 无信息量的废话、过时信息 信息密度评分(困惑度过低的段落往往是套话)

文档去重的三种策略

  1. 精确去重(URL / 文件哈希):对文档的 URL 或内容 MD5 去重,处理完全相同的文档。最快,但无法处理”内容相同但格式不同”的情况
  2. 近似去重(MinHash / SimHash):计算文档的指纹,相似度超过阈值(如 0.9)的文档只保留一篇。适合处理”同一篇文章的不同版本”
  3. 语义去重(Embedding 聚类):对所有文档做 Embedding,用 DBSCAN 聚类,同一簇内保留质量最高的一篇。计算成本高,但能处理”不同表述的相同内容”

重复片段识别

多篇文章中出现的重复段落(如”免责声明””公司简介”)比整篇重复更隐蔽。处理方法:

1. 对所有 chunk 计算 SimHash 指纹
2. 按指纹分桶,同桶内的 chunk 两两比较文本相似度
3. 相似度 > 0.85 的标记为重复片段
4. 保留出现次数最多的那一份,其余删除或标记为”低优先级”

差距在哪:新手要么不做清洗(让噪声进入检索),要么靠人工逐条检查(不可扩展)。高手从文档级/段落级/语义级三层做噪声剔除,用精确/近似/语义三种策略做去重,形成了可自动化、可扩展的知识库清洗管线。面试官考的是你对 RAG 数据质量的工程化管控能力。


Q:图检索、向量检索、混合检索有什么区别?怎么选?

来源:腾讯 AI 应用开发二面

新手答:”向量检索最常用,图检索更准。”

高手答

三种检索方式解决的是不同类型的查询问题,不存在”哪个更准”:

维度 向量检索 混合检索 图检索(GraphRAG)
检索原理 语义相似度匹配 语义 + 关键词双路 实体关系遍历 + 社区摘要
擅长的查询 “XX 是什么””如何做 XX” 既需要语义又需要精确匹配 “XX 和 YY 有什么关系””整体趋势”
不擅长的查询 多跳推理、关系型问题 全局性总结类问题 简单事实问答
索引构建成本 低(只需 Embedding) 中(Embedding + 倒排索引) 高(LLM 抽取实体 + 图构建)
查询延迟 毫秒级 毫秒级 秒级(需图遍历)
维护成本 低(增量更新简单) 高(实体变更需重建子图)

选型决策树

查询类型主要是什么?
├── 事实问答(”XX 的创始人是谁”)→ 混合检索(关键词精确 + 语义兜底)
├── 概念解释(”什么是 RAG”)→ 向量检索(语义匹配足够)
├── 关系推理(”A 和 B 有什么关联”)→ 图检索
├── 全局总结(”这个领域的趋势”)→ 图检索(Community Summary)
└── 混合场景 → 多路检索 + ReRank 融合

生产系统的常见做法:不选一种,而是多路并行、统一精排。向量检索和关键词检索作为基础双路,图检索作为补充路(只在检测到关系型查询时启用)。最后用 ReRank 模型统一排序,取 Top-K 送给生成模型。

差距在哪:新手把三种检索当成”好/更好/最好”的关系。高手理解它们解决的是不同类型的查询问题——向量检索擅长语义匹配,混合检索兼顾精确和语义,图检索擅长关系推理和全局总结。选型依据不是”哪个更先进”,而是”你的查询类型分布是什么”。面试官考的是你对多种检索范式的系统性理解和选型能力。


Q:多模态 Embedding 检索中,文本语义与图像视觉特征的权重怎么平衡?用户检索图纸参数却召回外观相似零件,根源是什么?

来源:阿里淘天 AI应用开发一面

新手答:“把文本和图片都转成向量,拼一起搜。”

高手答

多模态检索的核心矛盾是不同模态的语义空间天然不对齐——文本描述的是抽象概念(尺寸、材质、公差),图像编码的是视觉特征(颜色、形状、纹理)。“拼一起搜”忽略了这个根本问题。

两种融合方式

融合方式 原理 优点 缺点
Early Fusion(CLIP-style 联合空间) 文本和图像在训练时就映射到同一个向量空间 端到端优化,跨模态匹配能力强 通用模型学到的是“外观相似性”,不理解工程参数
Late Fusion(分别编码再加权) 文本和图像各自编码,检索时加权合并分数 权重可灵活调整,各模态可独立优化 跨模态交互弱,依赖权重调参

权重平衡方案

静态权重final_score = α × text_sim + (1-α) × image_sim,α 是固定值(如 0.6)。简单但不灵活——参数查询和外观查询用同一个权重显然不合理。

动态权重(更优方案):根据 query 类型自动调整权重——

Query 类型判断:
  "M8×1.25 螺栓 材质 304" → 参数查询 → α=0.9(几乎全靠文本)
  "这个零件长什么样"      → 外观查询 → α=0.2(主要靠图像)
  "找类似这张图纸的零件"  → 混合查询 → α=0.5(均衡)

实现方式:用一个轻量分类器(或规则引擎)先判断 query 类型,再动态设置 α。

图纸参数召回外观相似零件的根源分析

问题不在检索算法,在 Embedding 模型。通用视觉模型(如 CLIP)在预训练时学到的是外观级别的相似性——颜色、形状、轮廓。它不理解工程图纸中的参数语义(尺寸标注、公差范围、材质标签)。所以当用户搜“M8×1.25 不锈钢螺栓”时,模型返回的是外观最像螺栓的图片,而不是参数匹配的零件。

三种解决方案对比

方案 做法 优点 缺点 适用场景
通用视觉模型(CLIP) 直接用预训练模型做多模态检索 开箱即用,零成本 不理解工程参数,召回靠外观 PoC 阶段、外观检索
领域微调模型 用工程图纸 + 参数标注数据微调 Embedding 理解领域语义,参数匹配准确 需要标注数据,训练成本高 参数检索精度要求高
混合检索方案 参数字段走精确匹配,外观走向量检索 各取所长,参数精确、外观覆盖 系统复杂度高,需维护两套索引 生产环境首选

推荐的生产方案——混合检索

结构化参数(尺寸、材质、公差)→ 标量过滤(精确匹配 / 范围查询)
外观特征(形状、颜色)        → 向量检索(视觉相似度)
两路结果取交集或加权合并

结构化参数不应该走向量检索——“M8×1.25”这种精确规格用 Embedding 编码后会丢失精确性,直接用结构化字段过滤才是正确做法。向量检索只负责外观维度的相似度匹配。

差距在哪:新手把多模态当成“拼向量”。高手理解多模态检索的核心矛盾——不同模态的语义空间不对齐,权重平衡不是调参数,是选架构。面试官考的是你能不能从一个检索失败案例反推出系统设计缺陷。


Q:向量数据库中需要限定时间范围检索时,标量条件过滤怎么高效实现?

来源:阿里淘天 AI应用开发一面

新手答:“先向量检索再过滤掉不符合时间的。”

高手答

“先搜后滤”(Post-filter)是最直觉但最低效的方案——放大 K 倍检索再过滤,过滤率高时大量计算浪费,且可能凑不够 K 条结果。

三种策略对比

策略 做法 优点 缺点 适用场景
Pre-filter 先用标量索引(B-tree / bitmap)筛出时间范围内的文档 ID 集合,再在该子集上做 ANN 搜索 结果精确,不浪费向量计算 时间范围内文档太少时 ANN 效果退化(候选集不够大) 过滤条件选择性高(筛掉大部分数据)
Post-filter 先做 ANN 搜索取 top-K×M(放大 K),再用标量条件过滤 实现简单,不影响 ANN 索引结构 过滤率高时计算浪费严重,可能凑不够 K 条结果 过滤条件选择性低(只筛掉少量数据)
Hybrid 在 ANN 搜索过程中同时检查标量条件,边搜边滤 平衡精度和效率 实现复杂,需要索引层支持 通用场景

Pre-filter 的详细流程

1. 用标量索引快速筛选:SELECT doc_id FROM docs WHERE timestamp > 1700000000
   → 得到候选 ID 集合(毫秒级,B-tree 范围查询)
2. 在候选 ID 子集上做 ANN 搜索:只在这些向量上计算距离
   → 得到 top-K 结果(精确且无浪费)

Milvus 具体实现

Milvus 支持 boolean expression 做 pre-filter,底层在 segment 级做分区裁剪(partition pruning):

# Milvus pre-filter 示例
results = collection.search(
    data=[query_vector],
    anns_field="embedding",
    param={"metric_type": "COSINE", "params": {"nprobe": 10}},
    limit=10,
    expr="timestamp > 1700000000 and timestamp < 1710000000"  # 标量过滤
)

最佳实践

  1. 时间维度做 partition key:按时间范围(如按月)对数据做分区,查询时直接跳过不相关的分区,连标量过滤都省了
  2. 高基数标量字段建 scalar index:对 timestamp、category 等字段建标量索引,加速过滤
  3. Pre-filter 优先:除非过滤条件非常宽松(只筛掉 <10% 数据),否则 pre-filter 几乎总是优于 post-filter
  4. 监控过滤率:如果 post-filter 丢弃了超过 50% 的 ANN 结果,说明应该切换到 pre-filter
flowchart TB
    Q["用户 Query + 时间范围"] --> D{"过滤选择性?"}
    D -->|"高(筛掉 >50% 数据)"| PRE["Pre-filter\n先标量筛选再 ANN"]
    D -->|"低(筛掉 <10% 数据)"| POST["Post-filter\n先 ANN 再标量过滤"]
    D -->|"中等"| HYB["Hybrid\n边搜边滤"]
    PRE --> R["Top-K 结果"]
    POST --> R
    HYB --> R

差距在哪:新手用”先搜后滤”的暴力方案。高手对比了 pre/post/hybrid 三种策略,理解 Milvus partition pruning 机制。面试官考的是你对向量数据库工程实现的理解深度。


Q:Agentic RAG 是什么?和传统 RAG 的核心区别?

来源:美团Keeta Agent开发一面

新手答:「就是把 RAG 和 Agent 结合起来吧。」

高手答

传统 RAG 是单轮管线:query → 检索 → 生成,一次检索定胜负。Agentic RAG 的本质变化是把 Agent 的推理循环引入检索过程——检索不再是单次操作,而是 Agent 的一个可反复调用的工具。

两者的核心架构差异

flowchart LR
    subgraph trad[“传统 RAG”]
        Q1[“Query”] --> R1[“检索”] --> G1[“生成”]
    end

    subgraph agentic[“Agentic RAG”]
        Q2[“Query”] --> A[“Agent 推理”]
        A -->|”判断需要什么信息”| R2[“检索工具”]
        R2 -->|”结果不够/不对”| A
        A -->|”需要补充”| R3[“二次检索/换策略”]
        R3 --> A
        A -->|”信息充足”| G2[“生成”]
    end
维度 传统 RAG Agentic RAG
检索决策 固定管线,query 进来就检索 Agent 判断是否需要检索、检索什么
检索次数 单次 多次迭代,根据结果质量决定是否继续
Query 改写 预定义规则改写 Agent 根据上下文动态改写,甚至拆分子问题
结果评估 无(检索到什么就用什么) Agent 评估检索质量,不满意则换策略重检
工具组合 只有向量检索 可组合多种检索工具(向量、图谱、SQL、API)
适用场景 简单事实问答 复杂多跳推理、需要整合多源信息的任务

Agentic RAG 的三个关键能力

  1. 自主判断检索时机:不是每个 query 都需要检索——Agent 先评估自身知识是否足够,不足时才触发检索。避免了传统 RAG 对所有请求都检索的资源浪费
  2. 检索结果自我评估:检索完成后,Agent 判断结果是否能回答问题。如果召回的文档不相关或信息不完整,主动改写 query 或切换检索策略进行二次检索
  3. 多源检索编排:复杂问题拆成多个子问题,分别用不同的检索工具(向量库查概念、知识图谱查关系、SQL 查数据),最后综合推理

工程落地的权衡

Agentic RAG 的能力更强,但延迟和成本也更高——多次检索意味着多次 LLM 推理。生产中通常采用分级策略:简单 query 走传统 RAG 快速响应,复杂 query 才进入 Agentic RAG 循环。

差距在哪:新手把 Agentic RAG 简单理解为「RAG + Agent」的拼凑。高手理解核心区别在于检索从固定管线变成了 Agent 的可迭代工具——Agent 能自主决定是否检索、检索什么、结果够不够、要不要换策略。面试官考的是你对 RAG 范式演进的认知——从被动管线到主动推理。


Q:RAG 架构与模型微调(Fine-tuning)相比,各自的适用场景和优缺点是什么?

来源:字节后端 Agent 开发二面 【淘天转正实习一面追问:预训练语料已包含相关知识为什么还要RAG】

新手答:“RAG 不需要训练,Fine-tuning 效果更好。”

高手答

这两种方案不是互斥的,而是解决不同类型知识注入问题的工具。核心判断框架:

RAG 本质是「外挂知识」——检索时注入

维度 RAG
知识更新 改文档即生效,无需重新训练
可追溯性 每个回答都能追溯到来源文档
成本 无训练成本,主要是检索基础设施
知识容量 理论上无上限,取决于文档库规模
适用场景 知识频繁更新、需要引用来源、企业知识库

Fine-tuning 本质是「内化知识」——训练时注入

维度 Fine-tuning
知识更新 需重新训练和部署
可追溯性 无法追溯到具体来源
成本 训练 + 数据标注 + GPU 资源
知识容量 受模型参数量限制
适用场景 固化领域风格/格式、提升特定任务能力、降低推理成本

关键决策点

flowchart TD
    A["知识会频繁变化吗?"] -->|"是"| B["RAG"]
    A -->|"否"| C["需要引用来源吗?"]
    C -->|"是"| B
    C -->|"否"| D["是格式/风格问题\n还是知识问题?"]
    D -->|"格式/风格"| E["Fine-tuning"]
    D -->|"知识"| F["数据量够吗?"]
    F -->|"充足"| G["Fine-tuning + RAG 混合"]
    F -->|"不足"| B

最优解往往是混合方案:用 Fine-tuning 让模型学会领域的「语言」和「格式」(怎么说),用 RAG 注入具体的「事实」和「知识」(说什么)。例如医疗场景——微调让模型学会医学术语和问诊风格,RAG 提供最新的诊疗指南和药品信息。

差距在哪:新手把 RAG 和 Fine-tuning 当成二选一。高手理解两者解决不同问题——RAG 解决「知道什么」,Fine-tuning 解决「怎么表达」——且给出了决策框架和混合方案。面试官考的是你对知识注入手段的全局认知。


Q:如何处理 RAG 过程中的权限隔离和时效性问题?

来源:字节后端 Agent 开发二面

新手答:“给每个用户建一个单独的知识库。”

高手答

权限隔离和时效性是 RAG 上生产环境后最先暴露的两个安全问题。单独建库的方案在用户量大时不可行——需要系统性的工程方案:

一、权限隔离:检索前过滤,而非物理隔离

用户请求 → 鉴权(提取用户权限标签)
         → 在向量检索时注入 metadata filter
         → 只召回用户有权访问的文档

实现方式:

方案 实现 适用场景
元数据过滤 每个文档 chunk 存储权限标签(部门、角色、项目),检索时通过 pre-filter 过滤 权限维度明确、变更不频繁
多租户索引 按租户分索引(物理隔离),查询时路由到对应索引 租户间数据完全隔离(如 SaaS 多客户)
行级安全 在关系型数据库层面做权限控制,向量检索结果再和权限表 join 权限规则复杂、需要动态变更

关键工程细节:pre-filter(检索前过滤)vs post-filter(检索后过滤)的选择。pre-filter 在向量数据库层面直接过滤,效率高但可能影响召回质量(候选集变小);post-filter 先全量召回再权限过滤,召回质量高但有信息泄露风险(模型可能已经「看到」了无权限内容的 embedding 相似度信号)。生产中推荐 pre-filter

二、时效性:文档生命周期管理

策略 做法
时间戳标记 每个 chunk 存储文档创建/更新时间,检索时做时间衰减加权
增量更新 文档变更时只重新嵌入受影响的 chunk,不重建全量索引
版本管理 同一文档的多个版本共存,检索时优先返回最新版本
TTL 机制 设置文档过期时间,过期后自动降权或剔除

时效性的隐藏陷阱:用户问「最新的政策是什么」,如果召回了旧版本文档,模型会很自信地给出过时的答案——这比「不知道」更危险。防御方案:在生成阶段注入时间上下文(「以下文档更新于 2024-03-01,请注意时效性」),让模型自己判断是否需要提示用户信息可能过时。

差距在哪:新手只想到物理隔离(按用户建库)。高手给出了三层权限方案(元数据过滤、多租户索引、行级安全)和四种时效性策略,且点出了 pre-filter vs post-filter 的安全 trade-off。面试官考的是你对 RAG 工程化落地中安全问题的实战认知。


Q:补充检索是如何评估数据质量并触发的?怎么保证二次检索能搜到之前没搜到的内容?

来源:淘天 Agent 开发

新手答:“检索结果不好就再搜一次。”

高手答

「再搜一次」如果用同样的策略,结果不会有本质变化。补充检索的关键是先评估质量,再换策略重搜

一、什么时候触发补充检索?

需要一个质量评估门控,而不是每次都二次检索:

评估维度 检测方法 触发条件
召回数量 候选文档数 < 阈值 top-K 返回不足 3 条
相关性得分 Rerank 后最高分低于阈值 最高分 < 0.5(模型和数据相关)
覆盖度 query 中的关键实体/概念是否被召回文档覆盖 核心实体零命中
自洽性 让模型判断「基于这些文档能否回答问题」 模型输出「信息不足」信号

最实用的方案是相关性得分 + 模型自判组合:Rerank 分数兜底硬指标,模型自判捕捉语义层面的不足。

二、怎么保证二次检索搜到不同的内容?

核心是换检索策略,而不是重复同一策略:

flowchart LR
    A["首次检索失败"] --> B["策略切换"]
    B --> C["查询改写\n同义扩展/拆分子问题"]
    B --> D["换检索路\n向量→BM25\n或反过来"]
    B --> E["放宽约束\n扩大时间范围\n降低阈值"]
    B --> F["升级索引\n从chunk级→文档级\n或引入父子索引"]
    C --> G["二次检索"]
    D --> G
    E --> G
    F --> G
策略 做法 为什么能搜到新内容
查询改写 用 LLM 将原 query 改写为 2-3 个不同表述 弥补词汇鸿沟,触达不同文档
切换检索路 首次向量召回不好 → 换 BM25 精确匹配 两种检索的盲区不同
放宽约束 去掉时间/来源等过滤条件 扩大候选集
拆分子问题 复杂 query 拆成多个简单子 query 分别检索 每个子 query 更精准

三、防止无限循环

补充检索必须设上限(最多 2-3 轮)。如果多轮检索后质量仍不达标,应该诚实告知用户信息不足,而不是用低质量结果硬凑答案。

差距在哪:新手的「再搜一次」没有质量评估也没有策略切换——大概率搜出同样的结果。高手先用质量门控判断是否需要补充检索,再用策略切换保证二次检索有实质性差异。面试官考的是你对 RAG 检索链路的精细化控制能力。


Q:向量数据库中 IVF_FLAT 和 HNSW 索引的区别是什么?各自适合什么场景?

来源:快手AI应用开发一面

新手答:“都是加速向量搜索的索引,HNSW 更快。”

高手答

IVF_FLAT 和 HNSW 是两种完全不同的索引范式——一个基于分区量化,一个基于图遍历,适用场景差异很大:

维度 IVF_FLAT HNSW
核心思想 先聚类分桶,查询时只搜少数桶 构建多层跳表图,贪心遍历近邻
构建时间 快(kmeans 聚类) 慢(逐点插入建图)
内存占用 低(只存聚类中心 + 原始向量) 高(每个节点存多层邻居指针)
查询速度 中等(受 nprobe 参数控制) 极快(图遍历,路径短)
召回率 nprobe 小时召回低,大时接近精确 高(ef_search 调大后接近 100%)
增量更新 容易(新向量分配到最近的桶) 较难(插入需更新多层图结构)
数据规模 适合千万级以上(配合 PQ 压缩) 适合百万到千万级

IVF_FLAT 工作原理

建索引:对所有向量做 K-means 聚类 → 得到 nlist 个聚类中心
查询时:计算 query 与所有聚类中心的距离 → 选最近的 nprobe 个桶 → 在这些桶内暴力搜索

HNSW 工作原理

建索引:逐个插入向量,每个向量随机分配层级 → 在每层中与最近邻建立边
查询时:从顶层入口点开始 → 在每层贪心跳到最近邻 → 逐层下降直到底层 → 底层精搜 Top-K

选型决策

场景 推荐索引 原因
数据量大(>1000w)、内存有限 IVF_PQ(IVF + 量化压缩) HNSW 内存扛不住
数据量中等、要求低延迟 HNSW 查询速度最快,延迟稳定
数据频繁更新(实时写入) IVF_FLAT 增量更新成本低
离线批量检索、对延迟不敏感 IVF_FLAT(大 nprobe) 召回率高且节省内存
RAG 在线服务 HNSW 用户感知延迟要低,内存可以加机器解决

差距在哪:新手只知道”HNSW 更快”——这是结论不是理解。高手从数据结构原理(分桶 vs 图遍历)出发,推导出各自的性能特征和适用场景,且能给出具体的选型建议。面试官考的是你对向量检索底层机制的理解深度——不是会用 API,而是知道为什么这个参数要这样调。


Q:RAG 检索到的 Chunk 不足以回答问题,后续怎么处理?

来源:字节春招大模型测开一面

新手答:”让模型直接用自己的知识回答,或者告诉用户找不到。”

高手答

这是 RAG 系统最常见的退化场景之一。”Chunk 不足”有两种含义——检索到了但信息不够完整,或者根本没检索到相关内容。处理策略完全不同:

第一层:判断”不足”的程度

在生成前先做一步充分性评估(Sufficiency Check):用 LLM 判断当前检索结果能否支撑回答。评估维度:

  • 关键实体是否存在(问”A 和 B 的区别”,至少要有 A 和 B 的描述)
  • 时间/数值是否覆盖(问”2024年营收”,2023年的数据不算充分)
  • 逻辑链是否完整(问”为什么 X 导致 Y”,需要因果链条,不能只有结论)

第二层:补充检索策略

如果判定不足,触发 Agentic RAG 的补充检索:

flowchart TD
    A[“初次检索结果”] --> B{“充分性评估”}
    B -->|”充分”| C[“直接生成回答”]
    B -->|”不充分”| D[“策略切换”]
    D --> E[“查询改写\n换角度/拆子问题”]
    D --> F[“扩大召回\n放宽阈值/切换索引”]
    D --> G[“跨库检索\n换知识源/调外部API”]
    E & F & G --> H{“二次充分性评估”}
    H -->|”充分”| C
    H -->|”仍不足”| I[“诚实告知+给出部分答案+标注不确定性”]

关键策略:

  1. 查询改写 — 原始 query 可能太笼统或措辞偏离文档表达。拆成子问题、换同义词、补充上下文后重新检索
  2. 扩大召回范围 — 降低相似度阈值、增加 Top-K、切换到 BM25 关键词匹配(语义检索漏掉的关键词匹配可能命中)
  3. 跨库检索 — 如果本地知识库确实没有,可以调用外部搜索引擎、数据库查询、或调用其他系统的 API

第三层:生成策略

如果补充检索后仍不足:

  • 部分回答 + 标注 — “根据现有信息,X 部分的答案是…,但关于 Y 的具体数据暂未找到”
  • 不编造 — 绝对不能让模型用自身参数知识补充事实性信息(这是幻觉的主要来源)
  • 引导用户 — “您可以提供更具体的文档/关键词吗?”或”建议查阅 XX 系统获取最新数据”

差距在哪:新手的处理是二元的——“有就答,没有就说不知道”。高手有一套分级应对策略:先评估不足程度,再用查询改写/扩大召回/跨库检索做补充,最后仍不足时给出部分答案并标注不确定性。面试官考的是你对 RAG 系统边界情况的处理能力——生产环境中”检索不足”比”检索精准”出现得更频繁。


Q:向量数据库里两个同义词是什么关系?完全同义的词会在同一个点上吗?

来源:字节春招大模型测开一面

新手答:”同义词的向量应该一样,在同一个点上。”

高手答

同义词在向量空间中非常接近但不会完全重合。这涉及 Embedding 模型的本质工作方式:

为什么不在同一个点上

Embedding 模型编码的不仅是”词义”,还包括:

  • 使用语境差异 — “开心”和”高兴”虽然同义,但”开心果”和”高兴果”不等价。模型会捕捉到这些细微的搭配差异
  • 语域/正式度 — “逝世”和”死了”语义相同,但正式度不同,向量会有偏移
  • 训练语料分布 — 两个词在训练数据中的上下文分布不完全相同,导致编码略有差异

具体的空间关系

完全同义词(如 “AI” 和 “人工智能”):
  → 余弦相似度 > 0.95,几乎重合但有微小偏移

近义词(如 “开心” 和 “高兴”):
  → 余弦相似度 0.85-0.95,同一区域的邻近点

上下位关系(如 “狗” 和 “动物”):
  → 余弦相似度 0.6-0.8,有方向性偏移

反义词(如 “大” 和 “小”):
  → 余弦相似度可能 0.3-0.6(不一定对称分布在原点两侧)

对 RAG 的实际影响

同义词接近但不重合意味着:

  1. 查询 “AI应用” 可以召回包含 “人工智能应用” 的文档(相似度高)
  2. 但精确匹配度略低于完全相同的表述 → 这就是为什么需要查询改写(把 “AI” 扩展为 “AI/人工智能”)
  3. 也是为什么混合检索(向量 + BM25)有效 — BM25 处理精确匹配,向量处理语义近似

差距在哪:新手认为同义词 = 同一个点。高手理解 Embedding 空间是连续的高维空间,同义词是”近邻”而非”重合”,且能解释为什么——因为模型编码的是上下文分布而非字典定义。面试官通过这个问题考察你对 Embedding 的理解是停留在”API 调用”还是真正理解其数学含义。


Q:RAG 过程中如何处理文件里的图片?

来源:字节暑期agent实习二面

新手答:”把图片转成文字再检索。”

高手答

RAG 中图片处理是多模态 RAG 的核心问题,主流方案:

  1. 图片→文本描述(OCR + Caption):用 OCR 提取图中文字,用多模态模型(如 GPT-4V/Qwen-VL)生成图片描述,将描述文本一起做 Embedding 索引
  2. 多模态 Embedding 直接索引:用 CLIP 等模型直接将图片编码为向量,和文本向量放同一向量空间,支持跨模态检索
  3. 图文联合分块:在 chunk 切分时保持图片与其上下文段落的关联——图片属于哪个段落,chunk 就包含”段落文本 + 图片描述/图片引用”
  4. Layout-Aware 解析:用 PDF 解析工具(如 Unstructured、Marker)识别图片在文档中的位置和语义角色(图表?示意图?截图?),不同类型用不同处理策略
  5. 延迟处理:检索阶段只用文本索引,召回相关 chunk 后发现有关联图片时,再把图片和文本一起送多模态模型做最终回答

差距在哪:面试官关注你对”多模态信息如何融入检索链路”的工程思考——不是有 OCR 就够了,要考虑检索效果和成本的平衡。


Q:如何避免模型回复过度依赖检索到的外部知识,导致回答生硬、缺乏共情能力和自然度?

来源:阿里淘天 AI Agent应用开发二面

新手答:“在 Prompt 里加一句‘请用自然语言回答,不要直接复制文档内容’就行了。”

高手答

这个问题的本质是检索内容“绑架”了模型的生成自由度。模型把 RAG 返回的文档当成唯一信息源,逐句改写而非理解后重新组织,导致回答像“念文档”而非“对话”。

解法分三层:

1. 检索层——控制注入量和粒度

  • 不是检索到的东西全塞进 Prompt,而是只注入与当前轮次直接相关的片段
  • 设置相关性阈值:低于阈值的 chunk 不注入,让模型用自身知识补全
  • 对长段落做摘要后注入,而不是原文照搬——摘要后模型有更大的表达空间

2. Prompt 层——分离“知识”和“表达风格”

  • 系统 Prompt 中明确区分角色:你是一个友好的助手,参考资料只是辅助,回答要自然
  • 使用“参考但不照抄”的约束:以下资料供参考,请结合你的理解用口语化方式回答,不必逐条复述
  • 给模型留“自由发挥区”:允许在事实准确的前提下加入过渡语、共情表达、追问

3. 生成层——后处理与反馈闭环

  • 自然度评分:对生成结果用小模型打分(流畅性、重复率、文档复制比例),低分回退重生成
  • A/B 测试:对比“全量注入 vs 摘要注入 vs 无 RAG 回退”三种策略的用户满意度
  • 温度调节:对事实性回答用低温度保准确,对情感/共情类回答适当提高温度增加自然度

实际工程中常见的 Pattern:

  • 双通道生成:先让模型不看 RAG 结果生成一版“自然回答”,再与 RAG 检索结果做事实校验合并
  • 引用标记 + 自由组织:要求模型标注哪些内容来自文档、哪些是自己推理的,便于后续审计

差距在哪:面试官考的是你对“RAG 不只是拼 Prompt”的理解。检索是为了保证事实准确,但不能牺牲对话体验。高手会从注入策略、Prompt 设计、后处理三层分别控制“依赖度”,而不是只靠一句 Prompt 指令。


Q:随着大模型上下文窗口持续扩容(100K→1M+),传统 RAG 技术是否会被完全替代?

来源:阿里淘天 AI Agent应用开发二面

新手答:“窗口够大了就不需要 RAG 了,直接把所有文档塞进去就行。”

高手答

短期内不会被完全替代,长期会深度融合而非简单替代。核心论点:

RAG 不会消失的四个理由:

  1. 成本问题:1M token 的推理成本远高于“检索 5 个 chunk + 8K 上下文”。对高 QPS 场景(如客服),全量塞入的经济性不可接受
  2. 注意力稀释:即使窗口能装下,模型对中间位置信息的关注度仍然不均匀(Lost in the Middle 问题未根本解决),检索后精选 Top-K 反而提高相关信息的权重
  3. 实时性与权限:知识库持续更新,不可能每次请求都重新拼装全量文档;且不同用户有不同的数据权限,RAG 的过滤层天然支持权限隔离
  4. 可审计性:RAG 能明确告诉你“这个回答基于哪个文档的哪个片段”,全量塞入后模型引用溯源变得极困难

窗口扩容确实改变了什么:

  • RAG 的角色从“必须”变成“优化”:以前窗口不够必须检索,现在是为了提高质量和降本而检索
  • chunk 策略变粗:以前切 512 token 的小块,现在可以检索整段甚至整篇文档
  • 检索-生成边界模糊化:可以先粗检索一批大文档塞进长窗口,再让模型自己做“精排 + 生成”
  • 简单场景不再需要 RAG:FAQ、单文档问答等简单场景,直接全文塞入更省事

未来的融合形态:

graph TD
    A[用户 Query] --> B{复杂度判断}
    B -->|简单/单文档| C[直接全文塞入长窗口]
    B -->|复杂/多文档/高QPS| D[RAG 检索 + 精选注入]
    B -->|实时数据/权限隔离| E[必须经 RAG 过滤层]
    C --> F[生成回答]
    D --> F
    E --> F

差距在哪:这是开放观点题,面试官考的是技术判断力。新手非此即彼(要么 RAG 必须,要么窗口万能),高手能分场景讨论成本、注意力、实时性、可审计性四个维度,给出“不是替代而是融合”的结论,并能描述融合后的具体形态。


ES 切换向量检索的能力变化

Q:如果从 ElasticSearch 切换到向量检索,哪些能力会下降,哪些能力会提升?

来源:字节跳动 Agent开发实习生一面

新手答:“向量检索语义能力更强,ES 适合关键词。”

高手答

这不是简单的“好 vs 坏”,而是两种检索范式的能力互补。切换时要清楚你会失去什么、得到什么、以及怎么补回来

切换后提升的能力:

能力 原因
语义理解 “如何降低延迟”能匹配“性能优化方案”,ES 做不到
同义/改写鲁棒性 用户换种说法不影响召回质量
跨语言检索 多语言 Embedding 天然支持中英混搜
模糊意图处理 用户表达不精确时,语义相似度比关键词匹配更有效

切换后下降的能力:

能力 原因
精确匹配 搜“错误码 E4012”,向量检索可能返回语义相关但不是这个编码的文档
结构化过滤 ES 天然支持 range/term/bool 组合过滤,向量库需要额外的 metadata filter
实时索引 ES 近实时(1s),很多向量库批量索引有延迟
高亮/聚合 ES 内建 highlight、aggregation,向量库通常没有
可解释性 BM25 分数有明确含义(TF-IDF),向量相似度的 0.82 vs 0.79 难以解释

最佳实践——混合检索:

不要“切换”,而是“叠加”。用 ES 做精确匹配 + 结构化过滤,用向量库做语义召回,然后 RRF 或 Rerank 融合。把 ES 降级为精确匹配通道,而不是完全替换。

差距在哪:面试官考的是你对检索系统的完整理解。只说“向量比 ES 好”说明你没在生产环境用过 ES。能说出精确匹配下降、结构化过滤缺失、实时性差异,并给出混合方案,说明你做过检索系统的技术选型。


语义切分与文档聚类

Q:父文档是怎么得到的?语义切分具体是怎么做的?聚类后怎么区分不同文档?

来源:同程Agent开发实习一面

新手答:“按 512 token 切就行了,父文档就是原始文档。”

高手答

父子文档索引的核心思路是:子文档用于精准召回,父文档用于提供完整上下文。语义切分是让子文档在语义上自洽的关键。

语义切分流程:

flowchart TD
    A[原始文档] --> B[句子级分割]
    B --> C[逐句 Embedding]
    C --> D[相邻句子相似度计算]
    D --> E{相似度低于阈值?}
    E -->|是| F[标记为语义断点]
    E -->|否| G[继续]
    F --> H[按断点聚合为语义段落]
    H --> I[检查 token 上限]
    I -->|超限| J[段落内再按相似度二分]
    I -->|合格| K[生成子文档 chunk]
    K --> L[聚合同一来源的子文档 → 父文档]

具体步骤:

  1. 句子级分割:用标点/换行将文档拆成句子序列
  2. 逐句 Embedding:每句生成向量
  3. 滑动窗口余弦相似度:计算相邻句子之间的语义相似度,相似度骤降的位置即为语义断点
  4. 按断点聚合:断点之间的句子合并为一个语义段落(即子 chunk)
  5. token 限制兜底:如果某个语义段超过 max_tokens(如 512),在段内再找次级断点拆分

父文档的生成方式:

  • 最简单:父文档 = 原始文档(或原始文档的某一节)
  • 进阶:多个相邻子 chunk 共享同一父文档,父文档 = 子 chunks 的上下文窗口扩展(向前向后各扩展 N 句)

聚类后如何区分不同来源:

  • 每个 chunk 携带 metadata:{doc_id, section_id, chunk_index, parent_id}
  • 检索命中子 chunk 后,通过 parent_id 回溯父文档,返回更完整的上下文
  • 不同文档通过 doc_id 天然隔离,聚类只在单文档内部进行

差距在哪:面试官深挖切分细节是为了验证“你的 RAG 到底做了多深”。只说“按 token 切”说明你用了默认方案没调优。能说出语义断点检测 + 相似度骤降 + 父子回溯,说明你真的做过切分实验并理解效果差异。


这类题的答题模式

RAG 与检索题的核心是完整链路 + 工程细节

1. RAG 不是"向量搜索"——是离线切片 + 在线召回 + 精排的完整管线
2. 查询改写不是"扩展"——是多维度变换 + 槽位填充 + 主动澄清
3. 召回不是"一路搜索"——是多路召回 + 融合 + 精排
4. 性能优化用并行化——串行意图识别会引入延迟和错误级联

下一篇建议继续看: