为什么有了大模型还需要RAG?幻觉、私有知识、时效性四大问题
假设你们公司有几千份内部文档:产品手册、操作规范、历史项目经验、客户合同……领导想做一个 AI 问答系统,让员工随时可以问"我们的退款政策是什么"、"这个客户签了哪些条款",系统能直接给出准确答案。
你直接用大模型来做,第一轮测试效果还不错——但很快发现几个绕不开的问题:
- 模型对公司内部文档一无所知,回答全靠"编"
- 产品文档上周刚更新,但模型说的还是老版本的内容
- 模型回答的很流畅,但根本无法知道它说的是真是假,也无法追溯来源
- 文档加载到 Prompt 里,token 成本高到无法接受
这不是模型能力不够的问题,而是大模型作为一种技术,有几个根本性的天花板——而 RAG 就是为了突破这些天花板而诞生的。
目录
1.RAG–定义
1.1.适合的场景
1.2.面试官可能会问
2.RAG–完整链路
2.1.离线阶段
2.2.在线阶段
2.3.核心认知
2.4.面试官可能会问
3.Embedding 是什么
3.1.Embedding –压缩语义
3.2.Embedding 模型怎么选?
3.3.面试官可能会问
4.向量数据库
4.1.MySQL 不行
4.2.向量索引:ANN很快
4.3.向量数据库功能
4.4.面试官可能会问
5.RAG 切片策略
5.1.Overlap
5.2.面试官可能会问
1.RAG–定义
RAG 的全称是 Retrieval-Augmented Generation,检索增强生成。它的核心思路非常直觉:在让模型回答之前,先去知识库里检索出最相关的内容,把这些内容作为上下文一起喂给模型,让模型"看着资料"来回答。
下面这张图展示了 RAG 如何对应地解决上面四个问题:

RAG 针对四个问题各有应对:
对幻觉问题: 检索到的原文片段作为上下文传入模型,模型被要求"根据以下资料回答",而不是凭空生成。有了事实依据的约束,幻觉概率大幅降低——但注意,不是归零,这个后面会讲。
对私有知识问题: 知识库完全由你自己构建和维护,可以包含任何内部文档。模型不需要知道这些内容,只需要在被检索到的片段基础上进行推理和组织语言。
对知识更新问题: 更新知识库不需要重新训练模型,只需要更新文档、重新做向量化索引即可。知识的新鲜度完全由知识库决定,和模型训练截止日期解耦。
对可追溯性问题: 每次检索都能知道具体命中了哪份文档的哪个片段,可以在答案里附上引用来源,用户可以自行核查。
1.1.适合的场景
很多人看到 RAG 的思路后,产生了一个误区:是不是所有大模型应用都应该加 RAG?不是的。
适合 RAG 的场景:
知识密集型的问答系统,比如企业内部知识库、产品手册问答、法律法规查询——这类场景对事实准确性要求高,内容量大,且需要明确的来源追溯。
内容频繁更新的业务,比如新闻摘要、竞品分析、政策解读——这类场景下知识库可以持续接入实时数据,而模型本身不需要动。
长尾事实查询,比如"我们公司在上海的办公地址是什么""这个合同的甲方是谁"——这类问题的答案藏在特定文档里,必须检索才能找到。
1.2.面试官可能会问
Q:为什么有了大模型还需要 RAG?
参考思路:大模型有几个局限性——幻觉、私有知识盲区、知识时效性、无法溯源。RAG 通过在回答前先检索外部知识库,把相关文档片段注入上下文,让模型"看资料回答",从而有针对性地缓解以上问题。
Q:RAG 能解决幻觉问题吗?
参考思路:能显著缓解,但无法根治。有了检索到的事实作为锚点,模型乱编的概率大幅降低,且答案可以附上来源供核查。但模型仍然可能在检索结果上做出错误推理,或者在检索质量差时进行"补充生成"。RAG 降低幻觉概率,不消灭幻觉根因。
Q:什么场景下你会推荐用 RAG,什么场景下不用?
参考思路:适合 RAG 的是知识密集、内容频繁更新、需要溯源的场景,比如企业知识库问答、法规查询。不适合的是创意生成、强推理任务、以及模型训练数据已良好覆盖的稳定领域——在这些场景下,RAG 只是增加延迟和成本,没有实质收益。
2.RAG–完整链路
先用一张图把整条链路建立起来,再逐段拆解:现在逐段拆解这条链路上的每个环节。
整条链路分两段:离线侧负责"把知识存进去",在线侧负责"把相关知识找出来、组合出答案"。

2.1.离线阶段
1.原始文档(解析)
RAG 系统的知识来源可以多种多样:PDF 报告、Word 文档、网页、Markdown 文件、数据库记录、邮件……不同格式的文档需要不同的解析方式,这一步通常叫做 文档加载(Document Loading)。
值得注意的是,这一步的质量直接影响整个系统的上限。如果原始文档本身是扫描件或排版混乱的 PDF,解析出来的文本就会充满噪声,后续所有环节都会受损。"垃圾进,垃圾出"在 RAG 里体现得非常明显。
2.文档处理(清洗与预处理)
解析出来的原始文本往往不能直接用,需要做一轮清洗:去掉页眉页脚、无意义的格式符号、重复内容;识别并保留文档的标题结构;过滤掉表格乱码、图片占位符等。
这一步看起来琐碎,但在实际项目里,文档预处理往往是工程量最大、最容易被低估的部分。
3.切片(Chunking)
清洗好的文档不能整篇塞进向量库,需要切成更小的片段(chunk)。这是 RAG 系统里设计决策最多的一个环节,直接影响后续检索的精准度。
为什么要切?原因很直接:一篇 20 页的文档,用户的问题可能只和其中的某一段相关。如果把整篇文档作为一个单元存储和检索,要么检索粒度太粗(命中了整篇但相关内容被淹没),要么上下文太长(放不进模型或者注意力被稀释)。
切多大合适?这没有通用答案,需要根据文档类型、模型的上下文窗口、业务问题的颗粒度来决定。
4.向量化(Embedding)
切好的每个 chunk,都需要通过 Embedding 模型转换成一个向量(一个高维浮点数数组),这个向量代表了这段文字的"语义"。
向量化的关键点是:用户问题和文档 chunk 必须用同一个 Embedding 模型来处理,这样两者的向量才处于同一个语义空间,相似度计算才有意义。
同时还需要存储对应的元数据:这个 chunk 来自哪份文档、原文在哪一页、文档的创建时间等。元数据在过滤检索结果时非常重要,比如"只看最近三个月的文档"这类需求,就需要依赖元数据来实现。
5.存入向量数据库
向量和元数据分别存入向量数据库(如 Milvus、Weaviate、Chroma、Pinecone 等)和普通数据库/文档存储。向量数据库的核心能力是近似最近邻搜索(ANN),能在数百万向量中毫秒级找到与查询向量最相似的 top-K 结果。
文档解析 –>文档处理 –> 切片 –>向量化 –>存入向量数据库
2.2.在线阶段
下面这张图单独展示在线检索链路的各个环节,以及常见的优化分叉点:

1. Query 处理(改写/拓展/优化)
输入:用户原始自然语言问题 输出:用于检索的查询字符串 / 多条子 query
Query 改写
- 作用:口语转书面、消歧义、复杂问题拆分子问题
- 示例: 原始:公司报销怎么弄,最多能报多少? 改写拆分:
- 适用场景:用户问句长、多意图、口语化;基础版本可以直接使用原 query 跳过。
Query 扩展
- 作用:同义词、相关术语扩充 query,解决用户用词和文档用词不一致导致召回失败
- 示例:离职补偿 → 扩展离职赔偿金、辞退补偿
- 实现方式:大模型生成扩展、同义词词典;小体量知识库可以不开启,避免引入无关检索方向。
注意:改写 / 扩展是可选,过度扩展会引入噪声,反而降低检索质量。
2. Retrieval 检索
输入:处理后的 Query 输出:粗排候选 chunk 列表 (top‑K)
方法一 :纯向量检索
- 优点:抓语义,同义词也能召回
- 缺点:关键词精确匹配弱,专有名词、编号容易漏。
方法二 :混合检索 Hybrid Search(工业常用)
两路并行检索:
优势:兼顾语义理解 + 关键词精准命中,解决纯向量容易丢失专有名词的问题。
举个例子:
pip install rank-bm25 jieba
import jieba
from rank_bm25 import BM25Okapi
# ———————- 1. 准备知识库 chunk ———————-
corpus = [
"国内出差住宿标准:一线城市单人上限600元/晚,二线城市450元/晚。出差机票优先经济舱。",
"公司为异地员工提供住房补贴,一线城市每月补贴1500元,二线城市1000元。",
"供应商住宿接待标准,一类城市不超过800元每晚。",
"出差报销需要发票、行程单,提交OA流程审批。",
]
# 给每个chunk标记来源id
chunk_ids = [0, 1, 2, 3]
# 中文分词:BM25需要分词后的词列表
tokenized_corpus = [list(jieba.cut(doc)) for doc in corpus]
# 构建BM25索引(纯内存倒排索引,无训练)
bm25 = BM25Okapi(tokenized_corpus)
# ———————- 2. BM25检索函数 ———————-
def bm25_search(query: str, top_n=3):
query_tokens = list(jieba.cut(query))
scores = bm25.get_scores(query_tokens)
# (score, chunk_id, text)
scored = [(scores[i], chunk_ids[i], corpus[i]) for i in range(len(scores))]
scored.sort(key=lambda x: x[0], reverse=True)
return scored[:top_n]
# ———————- 3. 模拟向量检索(真实场景调用Embedding+向量库,这里模拟输出排名) ———————-
def mock_vector_search(query: str, top_n=3):
"""模拟向量检索返回结果,格式:(sim_score, chunk_id, text)
对应前面例子:向量召回顺序 0,1,2
"""
# 模拟向量相似度分数
mock_ret = [
(0.92, 0, corpus[0]),
(0.78, 1, corpus[1]),
(0.71, 2, corpus[2]),
]
return mock_ret[:top_n]
# ———————- 4. RRF 排名融合算法 Reciprocal Rank Fusion ———————-
def rrf_fuse(list_a, list_b, k=6):
"""
list_a / list_b: [(score, chunk_id, text), …]
k: RRF常数,一般取6
return: 融合后排序列表 [(rrf_score, chunk_id, text)]
"""
rrf_dict = {}
# 处理第一路结果
for rank, item in enumerate(list_a):
_, cid, text = item
rrf_score = 1.0 / (rank + 1 + k)
if cid not in rrf_dict:
rrf_dict[cid] = {"score": 0.0, "text": text}
rrf_dict[cid]["score"] += rrf_score
# 处理第二路结果
for rank, item in enumerate(list_b):
_, cid, text = item
rrf_score = 1.0 / (rank + 1 + k)
if cid not in rrf_dict:
rrf_dict[cid] = {"score": 0.0, "text": text}
rrf_dict[cid]["score"] += rrf_score
# 降序排序
fused = sorted(rrf_dict.items(), key=lambda x: x[1]["score"], reverse=True)
out = [(v["score"], cid, v["text"]) for cid, v in fused]
return out
# ———————- 5. 运行测试 ———————-
if __name__ == "__main__":
user_query = "国内出差一线城市住宿报销标准是多少?"
bm25_res = bm25_search(user_query, top_n=3)
vec_res = mock_vector_search(user_query, top_n=3)
print("==== BM25检索结果 ====")
for s, cid, txt in bm25_res:
print(f"score={s:.3f}, id={cid}: {txt}")
print("\\n==== 模拟向量检索结果 ====")
for s, cid, txt in vec_res:
print(f"sim={s:.3f}, id={cid}: {txt}")
fused_result = rrf_fuse(bm25_res, vec_res, k=6)
print("\\n==== RRF混合检索融合结果 ====")
for s, cid, txt in fused_result:
print(f"rrf={s:.3f}, id={cid}: {txt}")

3. Rerank 精排(召回后,可选但性价比极高)
输入:粗排得到的 top‑K 候选 chunk 输出:重新打分排序后的短列表(一般截取 top‑2~top‑4 送入 LLM)
流程:
- 优点:RAG 优化中收益最高的手段,过滤掉语义向量相似但实际无关的碎片
- 代价:额外模型推理,增加推理延迟;候选集不能太大,否则速度很慢。
实践范式:粗召回 K=8‑10 → rerank → 筛选 top‑3‑4 给 LLM。
- 优点:chunk 可以提前向量化入库;检索速度快。
- 缺点:query 和 chunk 没有交互,只能粗粒度语义,细粒度相关性判断弱。

4. 上下文构建 Context Construction
输入:rerank 筛选后的 chunk 片段 输出:组装完成的 Prompt 上下文
模板示例:
你是一个企业知识库助手。请根据以下资料回答问题,如果资料中没有相关信息,请明确说明。
参考资料:
[来源:产品手册第3页]
……chunk内容……
[来源:财务制度V2.0]
……chunk内容……
用户问题:我们的退款政策是什么?
⚠️关键点:控制总 token 长度,防止上下文溢出;chunk 不要无限制堆砌。
5. Generation LLM 生成
输入:完整 Prompt 输出:最终回答给用户
核心约束写在 Prompt 指令中:
2.3.核心认知
| 各环节对质量的影响各不相同 |
1. Chunking:决定能不能检索到相关内容 2. Embedding 模型:决定语义理解是否准确 3. Rerank:决定召回 top 结果是否真的最相关 4. Prompt 设计:决定LLM 能否正确利用上下文 |
优化 RAG 优先定位薄弱环节,不要所有环节盲目调参 |
| 离线‑在线链路必须对齐 | 文本清洗、分词、Embedding 模型,离线建索引和在线检索必须完全一致;索引用模型 A,检索用模型 B,向量空间不一致,相似度计算失效 | 上线前校验预处理链路一致性;不要随意更换 embedding 模型 |
| 检索追求精准,而非片面追求召回数量 | 少量高质量 chunk(top‑3)优于大量混杂的 top‑20 结果;上下文 token 越长,LLM 注意力越分散,信噪比下降 | 控制粗召回候选数量,依靠 Rerank 过滤噪声,精简送入 LLM 的上下文 |
2.4.面试官可能会问
Q:请描述一个完整的 RAG 链路。
参考思路:分两段回答。
离线侧:文档加载 → 清洗预处理 → Chunking → Embedding 向量化 → 存入向量数据库(同时存元数据)。
在线侧:用户 Query →(可选 Query 改写)→ Query 向量化→向量检索召回 top-K →(可选混合检索、Rerank 精排)→ 拼装 Context + Prompt → LLM 生成 → 输出带来源引用的答案。
元数据有什么用?
{
"vector": [0.123,0.456, …],
"content": "国内出差住宿标准:一线城市单人上限600元/晚…",
"metadata": {
"doc_id": "doc_005",
"doc_name": "差旅管理规定V3.pdf",
"page": 4,
"chunk_index": 12,
"department": "财务部",
"version": "V3",
"create_time": "2026‑01‑10"
}
}
RAG 很多线上问题根源就是元数据缺失:文档更新后旧向量清不掉、答案无法溯源、没法做权限过滤。
Q:RAG 里哪些环节最影响效果?
参考思路:
离线侧最关键的是 Chunking 策略(决定检索粒度)和 Embedding 模型选型(决定语义理解质量)。
在线侧最关键的是 Prompt 设计(引导模型正确利用上下文)。其中文档质量是前提,再好的系统也处理不好乱码和结构混乱的输入。
Q:Embedding 模型在离线和在线需要保持一致吗?为什么?
参考思路:必须一致。
Embedding 模型把文本映射到一个高维向量空间,不同模型的向量空间是不同的。离线用 A 模型建的索引,在线用 B 模型生成 Query 向量,两者处于不同空间,余弦相似度计算完全失去意义,检索结果会非常混乱。
3.Embedding 是什么
面试官:用户问‘出差能不能报销坐飞机’,你的知识库明明有答案,为什么搜不出来?
他:可能是关键词没匹配上,我再多加几个同义词。
面试官:文档里写的是‘民用航空器’,不是‘飞机’,再想想。
他沉默了几秒:是不是搜索词库不够全?
面试官摇摇头:你加再多同义词也没用。你的检索到底在匹配什么?是文字,还是语义?
他:我就是按关键词搜索啊……
面试官:那用户说‘飞机’,你怎么匹配‘民用航空器’?
他:(́◉◞౪◟◉‵)……
传统搜索在拼文字,而 Embedding,就是让机器读懂人类的语言。
今天我们把 Embedding 向量检索,从头到尾拆清楚。
语义压缩、模型选型、和 Rerank 的区别
Embedding 是一种将文本(或图片、音频等)映射到高维向量空间的技术。一个句子经过 Embedding 模型处理后,会变成一个由几百到几千个浮点数组成的数组,比如 [0.23, -0.87, 0.14, …, 0.56](维度通常是 384、768 或 1536 维)。
关键不在于这串数字本身,而在于它在空间里的位置:语义相似的文本,它们的向量在这个高维空间里彼此距离近;语义不相关的文本,距离远。
这是 Embedding 的核心承诺:用空间距离来表达语义相似度。
(在高维 Embedding 空间,余弦相似度衡量两个向量指向的语义方向有多接近)
下面这张图用二维空间来直觉化这件事。真实的向量是几百到几千维,但投影到二维平面后,语义聚类的模式仍然清晰可见:

图中的每个点都是一段文本经过 Embedding 后在向量空间中的位置。真实维度远不止两维(通常是几百到几千维),但语义聚类的规律是一致的:出行报销类的文档彼此靠近,动物类、编程类各自聚集。
用户的 Query 向量化后,系统计算它与所有文档向量的距离,找到最近的几个,这就是向量检索的本质。
3.1.Embedding –压缩语义
Embedding 不是生成文本,是在压缩语义
这里有一个经常被混淆的概念,值得单独说清楚。
生成式大模型(如 GPT、Claude)的目标是输出文字,给你一段输入,生成下一段内容。
Embedding 模型的目标完全不同——它的输出不是文字,而是一个向量表示,目的是把一段文字的"语义"压缩到一个固定维度的数字数组里,保留语义信息,丢掉格式和措辞细节。
同一个语义,即使换各式各样的说法,经过一个好的 Embedding 模型,得到的向量应该非常接近。这就是语义搜索能跨越措辞差异找到相关内容的根本原因。
3.2.Embedding 模型怎么选?
在实际工程中选 Embedding 模型,有几个维度需要考量:
向量维度
维度越高,理论上能表达的语义越细腻,但存储开销和检索速度也会相应增加。常见维度有 384 维(轻量)、768 维(均衡)、1536 维(高精度)。大多数中等规模业务选 768 维是合理起点。
最大 token 限制
每个 Embedding 模型都有输入长度上限,超过上限的内容会被截断。这个限制直接约束了 Chunk 的最大大小。比如 bge-small-zh 支持最多 512 token,那你的 chunk 就不能超过这个限制。选模型前一定要核对这个参数。
中文支持
这是中文 RAG 场景最关键的选型依据。通用的英文 Embedding 模型(如 OpenAI 的 text-embedding-ada-002)对中文的支持质量明显不如专门优化过中文的模型。目前中文场景下口碑较好的开源选项包括 BGE 系列和 M3E 系列,都在评测榜上有较好表现。
是否支持非对称检索
RAG 里有一个典型的非对称场景:Query 是一个简短的问题("退款政策是什么"),而文档片段是一段较长的说明文字。有些模型为这类非对称的 Query-Document 对做了专门优化,检索效果明显更好,比如 BGE 系列支持为 Query 加特殊前缀 "Represent this sentence for searching relevant passages:" 来提升检索效果。
| 使用场景 | 句对相似度、去重、问题‑问题匹配 | RAG 检索:短 Query 检索长 Passage |
| 输入处理 | Query、Passage 完全相同处理,不加特殊前缀 | Query 加检索指令前缀;Passage 直接原文,不加前缀 |
| 训练数据 | (普通句子,普通句子) | (带指令的 query,原始 passage) |
| 示例输入 | Q: 退款政策是什么P: 退款政策:xxx | Q: Represent this sentence for searching relevant passages: 退款政策是什么P: 退款政策:xxx |
| BGE 模型使用模式 | bge‑small‑zh 对称 | bge‑m3‑zh、bge‑v3支持非对称模式 |
3.3.面试官可能会问
Q:Embedding 模型怎么选?
参考思路:从四个维度回答。
第一,语言场景——中文业务优先选中文优化模型(BGE、M3E),不要直接用英文通用模型;第二,输入长度——模型的最大 token 限制直接决定 chunk 大小的上限;
第三,向量维度——根据存储资源和精度要求权衡,768 维通常是合理起点;
第四,任务类型——非对称检索(短 Query 找长文档)和对称检索(相似问题匹配)的最优模型不同,要看具体业务场景。
Q:Embedding 和 Rerank 有什么区别?
参考思路:Embedding(双塔/Bi-Encoder)对 Query 和文档分别独立编码成向量,通过向量相似度召回,优点是文档向量可离线预计算、检索极快,可处理百万量级,适合粗筛;
Rerank(Cross-Encoder)把 Query 和每个候选文档拼接后联合输入,直接输出相关性分数,模型能看到两者的深度交互,精准度更高,但无法预计算、需逐对推理,只适合对少量候选做精排。两者是流水线关系:Embedding 粗筛召回候选池,Rerank 精排过滤出最终传给 LLM 的上下文。
4.向量数据库
你做了一个 RAG 系统,有 100 万个文档 chunk,每个 chunk 都经过 Embedding 变成了一个 768 维的向量。
现在用户提了一个问题,你把这个问题也向量化了。接下来你要做的事情是:找到 100 万个向量里,和这个 Query 向量最相似的 top-5 个。
听起来不难,实际做起来很麻烦。
最直接的方法是"暴力搜索":把 Query 向量和全部 100 万个向量逐一计算余弦相似度,排序,取 top-5。在一台普通服务器上,这个操作大概需要几百毫秒到几秒——对于实时对话场景来说完全不可接受。
而且,当向量数量增长到 1000 万、1 亿时,暴力搜索的耗时线性增长,根本无法用于生产。
这就是向量数据库要解决的核心问题:在海量高维向量中,如何在毫秒级内找到最相似的结果?
4.1.MySQL 不行
这是面试里最常问的问题之一。答案不只是"MySQL 不支持",而是有本质的技术原因。
传统关系型数据库的查询本质上是精确匹配或范围扫描——比如 WHERE age > 25 AND city = '北京',通过 B-Tree 索引可以快速定位到符合条件的行。
向量相似度搜索完全不同。你不是在问"哪些向量等于某个值",而是在问"哪些向量和我的查询向量最接近"——这是一个在高维连续空间里的几何问题。
传统数据库的索引结构(B-Tree、Hash Index)对这类问题完全无效,因为它们设计之初没有考虑"高维几何相似度"这个维度。即便 PostgreSQL 的 pgvector 扩展支持向量存储,在大规模场景下的性能仍然远不如专门的向量数据库。

4.2.向量索引:ANN很快
要在百万量级向量中做毫秒级检索,关键是向量索引。向量数据库不做暴力全量计算,而是预先构建一个特殊的索引结构,让检索时只需访问一小部分向量就能找到近似的最近邻——这就是 ANN(Approximate Nearest Neighbor,近似最近邻搜索)。
"近似"两字需要注意。ANN 不保证找到绝对最近邻,但在实践中找到的结果精准度足够高(通常 95%+),而速度提升是数量级的。
目前最主流的两类向量索引算法是:
HNSW(Hierarchical Navigable Small World)
HNSW 构建了一个层级结构的图:最顶层是少量节点,形成"高速公路";底层是所有节点,形成"街道网络"。检索时从顶层入口进入,沿图中的邻居边快速导航,逐层下降,像 GPS 导航一样越来越精细,最终定位到目标附近的最近邻。

HNSW 的优势是查询速度极快、精度高,是 Milvus、Qdrant、Weaviate 等主流向量数据库的默认索引。代价是构建索引时内存占用较大。
IVF(Inverted File Index)
IVF 先对所有向量做 K-Means 聚类,把相似的向量分组到同一个"货架"里。检索时先找到 Query 向量最近的几个货架,只在这些货架内做精细查找,而不是全量扫描。
IVF 的优势是内存占用较低,适合超大规模数据集。缺点是如果 Query 向量恰好落在两个货架的边界,可能会漏掉一些相关结果(边界效应)。
4.3.向量数据库功能
向量数据库不只是"存向量、搜向量"这么简单,它还有几个在 RAG 工程里非常重要的能力:
元数据过滤(Metadata Filtering)
每个向量可以附带结构化的元数据,比如文档来源、创建时间、部门归属、文档类型等。检索时可以在向量相似度搜索的同时附加元数据条件——比如"只在最近三个月的文档里搜索"、"只搜索产品部门的文档"。这让 RAG 系统可以做到语义相关 + 业务过滤的组合查询。
混合检索(Hybrid Search)
主流向量数据库(如 Weaviate、Elasticsearch with dense vectors)支持同时运行向量搜索和关键词搜索,然后用融合算法(如 RRF,Reciprocal Rank Fusion)合并两路结果。这对中文专业术语场景尤其有用,因为有些专有名词的语义表示很弱,必须依赖关键词精确匹配。
向量更新和删除
知识库需要持续更新——文档修改了、删除了,向量索引也需要对应更新。不同向量数据库对这个操作的支持成本差异很大,选型时需要考虑业务的更新频率。
| 专用向量数据库 | Milvus、Qdrant、Weaviate、Pinecone | 原生以向量检索为核心;完善的元数据过滤、混合检索、分片扩容;性能强 | 百万及以上向量,生产环境;需要混合检索、高并发;Pinecone 为云端托管免运维 | Pinecone 为海外云服务;自建需要运维部署成本 |
| 传统数据库向量扩展 | PostgreSQL+pgvector、Elasticsearch(dense vectors) | 复用现有数据库基础设施;支持向量 + 原有业务查询;ES 原生支持 BM25 + 向量做混合检索 | 已有 PG/ES 运维体系,中小规模业务 | 百万向量以上,检索性能弱于专用向量库;扩缩容复杂 |
| 轻量级本地向量库 | FAISS、Chroma | FAISS:纯索引库,非完整数据库,无持久化 / 元数据管理;Chroma:开箱即用轻量库 | 原型开发、本地调试、小规模测试(几十万向量以内) | 不适合线上高并发大流量生产环境 |
4.4.面试官可能会问
Q:为什么不用 MySQL 做相似检索?
参考思路:分两个层面回答。
第一,功能层面:传统关系型数据库的查询模型是精确匹配和范围扫描,基于 B-Tree 等索引结构,这类结构无法支持"找高维空间中的近似最近邻"这种几何问题;
第二,性能层面:即便通过扩展支持向量存储和计算(如 pgvector),在百万级向量时全量计算余弦相似度的复杂度是 O(N),远远无法满足毫秒级检索需求。向量数据库通过 HNSW、IVF 等专门的近似索引结构,把检索复杂度降低到近似 O(log N)。
Q:向量数据库为什么能加速召回?
参考思路:向量数据库的核心是 ANN(近似最近邻搜索),通过预先构建向量索引来避免全量计算。以 HNSW 为例,它构建了分层的可导航小世界图,检索时从顶层稀疏图的入口快速导航,逐层定位到目标区域,只访问极少数节点就能找到近似最近邻,速度比暴力搜索快几个数量级。代价是"近似"——不保证绝对最近邻,但实践中 recall 精度 95%+ 足以满足 RAG 场景需求。
5.RAG 切片策略
内容有点多了,这个我重新出一个章节。
切片:【LLM&&AI应用开发 八股文】–RAG的分块策略-CSDN博客
5.1.Overlap

讲 Chunking 绕不开一个关键参数:overlap(重叠)。
设想一段文字,中间某句话恰好落在两个 chunk 的边界:前半句在 chunk 1,后半句在 chunk 2。当用户提问这句话相关的内容时,单独检索到 chunk 1 或 chunk 2,拿到的都是一半,信息不完整,生成的答案就会出错。
Overlap 的解决思路是:相邻 chunk 之间保留一段重叠的内容。比如 chunk 大小设为 512 token,overlap 设为 64 token,那么 chunk 2 的前 64 个 token 和 chunk 1 的后 64 个 token 是完全相同的。
这样,边界附近的信息在两个 chunk 里都有备份,不管检索命中哪个,都能拿到完整的上下文。

5.2.面试官可能会问
Q:你们项目里 chunk 是怎么切的?
参考思路:
先说选择了什么策略及原因,再说具体参数(chunk size、overlap),最后说是如何评估和调整的。
例如:"我们的文档是有章节结构的产品手册,所以用了结构感知切分,按二级标题划分。每个 chunk 控制在 600 token 以内,overlap 设了 80 token。后来发现部分技术规格内容跨段落,把 overlap 调大到 120 token 后,相关问题的召回率有明显提升。"
Q:chunk 过大过小分别有什么问题?
参考思路:
过小会导致语义不完整,单个 chunk 缺乏上下文,向量表示语义模糊,检索精准度低。
过大会导致 Context 里的噪声增多,模型注意力被分散,同时每个 chunk 的向量是多话题混合的平均,语义匹配变差。两个方向的问题都直接影响最终的生成质量。
Q:为什么要设置 overlap?
参考思路:
overlap 是为了防止重要信息落在 chunk 边界被割裂,通过让相邻 chunk 共享一段内容来保证边界附近的信息在两侧都能被完整检索到。
网硕互联帮助中心



评论前必须登录!
注册