一句话价值:在跳到 Agentic 之前,先把 Advanced RAG 搞清楚------它是工程上最成熟、最主流的一档优化,核心思路是"检索前 → 检索中 → 检索后"三段打磨。它的那些优化手段,到了 Agentic RAG 里会变成 LLM 按需调用的"工具"。所以它既是通往 Agentic 的必经之路,也是一套会被复用的组件库。
先看一个现实的坑
上一篇说纯语义检索会"认错人"------「高血糖」和「低血糖」语义相近,向量检索分不清。其实这只是朴素 RAG 众多毛病里的一个。更普遍的是:
- 用户口语化的问法,和知识库里的书面表达不在一个语义空间;
- top-k 检索回来的结果混着无关片段,还全塞进 prompt,既费 token 又诱导幻觉。
Advanced RAG 的思路很朴素:不改变"固定流水线"这个骨架,但把「检索」这一个环节拆成三段,每一段都打磨到位。
css
A[用户问题] --> B[① 检索前<br/>改写 / HyDE / 多路]
B --> C[② 检索中<br/>混合检索]
C --> D[③ 检索后<br/>重排 / 压缩]
D --> E[生成]
① 检索前:把"问得太差"的问题改好
朴素 RAG 直接拿用户原话去检索,问题在于 query 太短、太口语。三种手段对症下药:
Query Rewriting(查询改写)------把口语问题改写成适合检索的书面表述:
js
const rewritten = await llm.invoke(
`把下面口语问题改写成适合检索的关键词句:\n${question}`
)
// "阿朱最后怎么样了?" → "阿朱 结局 死亡 乔峰"
HyDE(假设文档嵌入)------先让 LLM 凭空写一个"假设答案",再用假设答案去检索。因为假设答案和真实文档是同一风格,语义距离更近:
js
const hypo = await llm.invoke(`针对问题写一段假设答案:${question}`)
const docs = await vectorStore.similaritySearch(hypo, k)
Multi-Query(多路查询)------一个 query 生成多个不同角度的 query,各自检索再合并,提高召回:
js
const queries = await llm.invoke(`把问题改写成 3 个不同角度的检索问题:${question}`)
const docs = (await Promise.all(queries.map(q => search(q)))).flat()
② 检索中:让关键词和语义互补
纯向量检索分不清「高血糖/低血糖」,但关键词检索(BM25)分得清------因为这两个词字符完全不同。反过来,纯关键词检索又抓不住"同义改写"。混合检索 = 两者并行 + 融合排序:
js
const [dense, sparse] = await Promise.all([
vectorStore.similaritySearch(q, k), // 稠密向量:语义
bm25.search(q, k), // 稀疏 BM25:关键词
])
const merged = reciprocalRankFusion(dense, sparse) // RRF 融合
同时,分块(chunk 大小、滑动窗口 overlap)决定了检索的"颗粒度",是检索质量的地基。
③ 检索后:把喂给 LLM 的料提纯
朴素 RAG 最被诟病的点:top-k 里混着无关片段,全塞进 prompt。
Rerank(重排)------向量检索是"双塔模型"(query 和 doc 分开编码),快但粗;rerank 用 cross-encoder 把 query 和 doc 一起过模型,精但慢。所以只对 top-N 候选精排:
js
const candidates = await vectorStore.similaritySearch(q, 50) // 先粗召回
const reranked = await reranker.rerank(q, candidates) // 再精排取 top-5
Context Compression(上下文压缩)------用 LLM 把检索内容压缩,只留和 query 相关的部分,省 token、降噪声。
Advanced 的天花板:还是那条固定流水线
三段优化做完,检索质量确实上了一个台阶------查得更准(混合)、喂得更纯(重排 + 压缩)、召得更多(改写 + 多路)。
但它优化的始终是"检索得好不好",不是"要不要检索、检索几次"。
js
// 无论问题多简单,next 仍然写死:永远走完这条线
.addEdge(START, "rewrite")
.addEdge("rewrite", "hybridRetrieve")
.addEdge("hybridRetrieve", "rerank")
.addEdge("rerank", "generate")
1 + 1 = ? 还是会被送去改写、混合检索、重排一遍。流水线变聪明了,但产品还是永远沿同一条传送带走。 这,就是 Advanced 的天花板,也是下一篇 Agentic RAG 要解决的问题。
本篇小结
- Advanced RAG 不改变"固定流水线"骨架,而是把「检索」拆成三段打磨。
- 检索前:改写 / HyDE / 多路查询,解决"问得差、召不全"。
- 检索中:混合检索(BM25 + 向量)+ 分块优化,解决"纯语义认错人"。
- 检索后:重排 + 上下文压缩,解决"喂的料不纯"。
- 天花板:它优化"检索质量",但不改变"每次都检索"的固定路径------这正是 Agentic 的切入点。
系列预告
- 下一篇:Agentic RAG 不是"加个路由"------路由不是 Agentic 独有,Advanced 也有;真正的质变是"控制权交给 LLM"。