这是”AI Agent落地:业务系统智能化改造”系列的第六篇。前五篇讲了Agent怎么建、需要什么能力、怎么评测、怎么编排、怎么写Prompt。这篇讲Agent最常见的能力:RAG。


目录


引言:你做的RAG为什么效果不好

你搭了一个RAG系统,用向量数据库存了文档,用户提问时检索TopK结果,塞给大模型生成答案。上线后发现:检索不准、幻觉严重、改了Prompt不知道变好还是变差。

这是很多刚接触RAG的人会遇到的问题。原因很简单:RAG不是向量库+TopK,而是多环节管线的组合优化

向量检索只是RAG的一个环节。一个完整、稳定、可用的RAG系统,通常要经过7层:文档准备、索引构建、查询增强、多路召回、融合重排、上下文组织、生成控制。每一层都有多种技术选择,组合方式不同,效果差异很大。

这篇文章帮刚接触RAG的人建立全面认知:RAG是什么、怎么演进的、每个环节的作用、怎么选方案、常见踩坑有哪些。目标是让你在项目RAG设计这块心中有数。


一、RAG到底是什么

一句话定义

RAG是**检索增强生成**(Retrieval-Augmented Generation)的缩写。核心思想是:先从知识库中检索相关内容,再把检索结果作为上下文,让大模型基于这些内容生成答案。

简单说就是:先找资料,再回答问题。

为什么需要RAG

大模型有三个痛点,RAG能缓解:

痛点 说明 RAG怎么解决
知识过时 模型训练数据有截止日期,无法获取最新信息 实时检索最新文档
幻觉 模型会编造不存在的信息 基于真实文档生成,有据可依
隐私 敏感数据不能传给外部模型 本地知识库,数据不出域

RAG vs 长上下文 vs Fine-tuning

除了RAG,还有两种方式让大模型获取外部知识:

方式 原理 适用场景 局限
RAG 检索+生成 知识库大、需要实时更新、需要引用来源 检索质量影响生成效果
长上下文 把更多内容塞进模型输入窗口 知识库小(<100K token)、文档间关系复杂 成本高、有窗口限制
Fine-tuning 用特定数据微调模型参数 特定领域风格、格式要求严格 不能获取新知识、成本高

关键结论:三者互补而非替代。小库用长上下文,大库/动态知识用RAG,特定风格用Fine-tuning。很多生产系统是混合使用。


二、RAG的演进:从Naive到Agentic

RAG技术在过去三年经历了快速演进。了解这个脉络,能帮你判断当前项目应该用哪种方案。

Naive RAG(2023前):最简单的三步流程

最简单的RAG只有三步:

用户提问 → 向量检索TopK → 塞给模型生成答案

这种方案能跑通Demo,但生产环境问题很多:检索不准、上下文噪声大、无法处理复杂查询。

Advanced RAG(2024):7层管线优化

针对Naive RAG的问题,业界逐步优化出7层管线:

文档准备 → 索引构建 → 查询增强 → 多路召回 → 融合重排 → 上下文组织 → 生成控制

核心改进:

  • 查询增强:改写用户问题,提升召回率
  • 多路召回:全文+向量并行检索,互补短板
  • 融合重排:RRF合并+Rerank精排,提升准确率
  • 上下文压缩:裁剪、去重,减少噪声

这是当前主流方案,大多数生产系统都在这个阶段。

Agentic RAG(2024-2025最热):Agent动态决定检索

Agentic RAG的核心思想是:让Agent自己决定何时检索、检索什么、如何组合。

传统RAG是”被动检索”:用户问一个问题,系统固定走一遍检索流程。Agentic RAG是”主动检索”:Agent根据问题复杂度,动态决定要不要检索、检索几次、用什么查询词。

适用场景:复杂多步骤任务,比如”帮我分析这个政策对华东地区的影响”,Agent需要先检索政策内容,再检索华东地区数据,最后综合分析。

Self-RAG:模型自我反思决定是否需要检索

Self-RAG更进一步:模型自己判断”我需不需要检索”。

核心机制:模型生成答案时,会自问几个问题:

  • 这个问题我需要检索吗?
  • 检索结果和问题相关吗?
  • 我的答案有没有基于检索结果?
  • 我的答案有没有幻觉?

如果模型认为自己能回答,就不检索;如果不确定,再触发检索。这能减少不必要的检索调用,降低成本。


三、核心组件:每个环节的作用

理解RAG的每个环节,才能在项目中做出正确的技术选择。

3.1 文档处理:切片策略决定检索质量

什么是切片:把长文档拆成小段(Chunk),便于检索和拼接。切片质量直接影响检索效果。

常见切片方法

方法 做法 适用场景 注意
固定长度+重叠 按固定字符数切分,相邻块带overlap 快速搭基线、格式杂乱的文本 容易在句子中间截断
按文档结构 以标题、章节为边界 技术手册、政策条文 单节过长时需二次切分
语义切片 逐句向量化,相似度骤降处断开 话题频繁切换的长文 计算成本高,阈值敏感
Parent-Child 小块用于检索,大块用于生成 需要精确检索但上下文要完整 需要维护两级索引

组合策略:多数线上系统用”结构优先→超长二次切→overlap”,在召回率和索引体积之间折中。

3.2 索引构建:不只是向量

索引是”提前建好的目录结构”,用于快速定位内容。RAG有四类索引:

索引类型 原理 擅长 短板
全文索引(BM25) 按关键词匹配 专有名词、地名、年份、编号 不理解同义词
向量索引(Embedding) 把文本转成数字向量,按语义相似度查找 同义表达、改写问法 对精确词项不稳定
图索引(Graph RAG) 抽实体建关系,按关系链路查找 关系推理、多跳问题 构建维护成本高
树状索引 按目录/主题层级组织,先粗定位再下钻 长文档、结构化资料 跨层级灵活性差

工程组合:生产里通常不是四选一,而是组合:全文召回+向量召回并行,关系型问题补图检索,融合后做Rerank。

Embedding模型选型:不要只看排行榜,要在自有数据上评估。中文场景推荐BGE、M3E,英文推荐OpenAI text-embedding-3。

3.3 检索策略:混合检索是主流

什么是混合检索全文检索和向量检索并行执行,结果合并排序。

为什么需要混合检索?因为两种检索方式互补:

检索方式 擅长 不擅长
全文检索(BM25) “2024年产业园政策” — 精确匹配关键词 “怎么申请补贴” — 同义表达
向量检索 “怎么申请补贴” — 语义相近 “2024年产业园政策” — 精确词项

RRF融合算法:把两种检索结果合并的常用方法。核心思想是”多路都靠前的结果胜出”:

# RRF(Reciprocal Rank Fusion)公式
# score = Σ 1/(k + rank)
# k通常取60

def rrf_score(rank, k=60):
    return 1 / (k + rank)

# 示例:一个文档在全文检索排第3,向量检索排第5
# RRF分数 = 1/(60+3) + 1/(60+5) = 0.0159 + 0.0154 = 0.0313

查询增强:在检索前改写用户问题,提升召回率。比如用户问”销售额怎么样”,可以改写为”销售额趋势、销售额同比、销售额分区域”,分别检索再合并。

3.4 后处理:重排和压缩

为什么需要重排:召回是粗筛(找全),重排是精排(排对)。BM25和向量检索的分数不能直接比较,需要一个更精确的模型重新排序。

Rerank模型:用Cross-Encoder模型,把查询和每个候选结果一起输入,计算相关性分数。比Bi-Encoder(向量检索用的)更准,但更慢,所以只用于重排,不用于召回。

上下文压缩:减少塞给模型的token量,降低成本、提升质量。

  • 裁剪:只保留和查询相关的段落
  • 去重:移除重复或高度相似的内容
  • 摘要:对长段落生成摘要


四、方案选型:心中有数

4.1 技术方案对比

方案 原理 适用场景 复杂度
纯向量检索 只用Embedding+向量数据库 Demo、PoC、小规模
混合检索 全文+向量并行,RRF融合 大多数生产场景
Graph RAG 知识图谱+图检索 关系推理、多跳问题
长上下文 把文档塞进模型输入窗口 小库(<100K token)

当前共识:混合检索是主流,BM25+向量的组合被广泛采用。

4.2 技术方案选型:SQLite、PG、ES还是混合检索

很多人的RAG选型止步于”选哪个向量数据库”。但真正的技术方案要回答三个问题:检索用什么引擎、数据怎么存、两者怎么配合。

我调研了业内主流的几种方案,发现它们走了完全不同的路:

SQLite全家桶:一个文件搞定一切

SQLite + FTS5 + sqlite-vec + 本地rerank的组合,核心思想是:一个本地数据库文件里把全文检索和向量检索都做掉。

为什么很多人喜欢它?因为很”收敛”——零外部依赖、本地开发调试简单、数据直接落文件、部署成本低。sqlite-vec是Mozilla Builders项目(4K+ GitHub stars),背后有Mozilla、Fly.io、Turso等赞助。

真实案例:SQLite Cloud文档搜索(182个文档,查询平均370ms)、NBC新闻标题搜索(14,500条,FTS5+sqlite-vec+RRF融合)、Hermes Agent的session_search(FTS5做对话历史检索)。

维度 分析
优势 架构简单可靠、零依赖零运维、数据主权完整(数据不离开设备)、支持混合检索(FTS5+sqlite-vec+RRF)
劣势 sqlite-vec仍偏新、高并发能力有限、水平扩展能力弱
适用 用户量少、知识库<50万文档、本地应用、快速验证
不适用 已有成熟服务端、需要高并发、十亿级向量规模

PostgreSQL + pgvector:生产稳健选择

把向量检索直接放进PostgreSQL体系——PG负责关系数据、过滤、元数据、事务,pgvector负责向量列与近邻搜索,配上全文检索/BM25能力,就能在一个数据库里做混合检索。

为什么很多团队选它?不是因为性能一定最强,而是系统整体更简单:运维熟悉、备份恢复成熟、权限审计成熟、与现有业务库集成容易、数据同步链路更短。

RAGFlow:MySQL/PG + Elasticsearch双引擎

RAGFlow把业务数据存MySQL/PG,分块原文和向量都存Elasticsearch。每个租户一个ES索引,分块原文和向量在同一个索引里,检索时不需要二次查询。全文检索权重0.05、向量权重0.95。

优点是ES天然支持分布式,性能强。缺点是部署复杂——需要MySQL + ES + MinIO + Redis四个组件。

Hybrid Search:不是产品,是架构模式

混合检索不是某一个具体产品,而是一类检索架构:BM25做关键词召回 + Vector Search做语义召回 + Reranking做最终排序。

单一路线都有明显缺陷:只有BM25听不懂改写和语义,只有Vector抓不住精确词和专有名词,只有Rerank前面召回不对重排也救不回来。混合检索就是把三者的职责拆清楚。

工程实现:并行召回(全文+向量各一份)→ 结果融合(RRF)→ 候选重排(BGE Reranker/Cross-Encoder)。

我的选择:参考MaxKB,PostgreSQL + pgvector

考量 说明
规模 167个文档、约3000个分块,不需要ES的分布式能力
运维 单一数据库,不用维护ES+MySQL+Redis
事务 ACID保证数据一致性
扩展 后续加用户权限、多租户,PG原生支持

不选SQLite是因为需要后续多用户并发和管理功能。不选RAGFlow是因为167个文档用ES过度。不选纯向量库是因为缺乏关系型数据管理能力。

数据库设计要点

知识库(knowledge_bases)
  └── 文档(documents)
        ├── 文字块(text_blocks) — content + embedding + search_vector
        ├── 表格(tables) — html_content + caption_embedding
        ├── 图片(images)
        └── RAG分块(chunks) — content + embedding + search_vector

关键设计:

  • 每个分块同时存embedding(向量)和search_vector(全文),支持混合检索
  • 中文全文检索需要安装zhparser扩展:CREATE EXTENSION zhparser; CREATE TEXT SEARCH CONFIGURATION chinese (PARSER = zhparser);
  • bbox字段记录原文在PDF中的位置,检索结果可以直接跳转到PDF对应位置
  • file_hash字段支持增量更新——文件没变就不重新处理

三种检索模式

模式 原理 适用
向量检索 pgvector cosine距离 语义相似的模糊查询
关键词检索 tsvector + ts_rank_cd 精确匹配(政策名、编号)
混合检索(推荐) 向量0.7 + 关键词0.3加权 大多数场景

混合检索的实现:用户问题同时走向量检索(Top-20)和关键词检索(Top-20),合并去重后加权排序,返回Top-5。这比纯向量检索的效果好很多,因为关键词检索能捕获向量检索容易漏掉的精确匹配(政策名、年份、编号)。

4.3 场景→方案映射

场景 技术方案 框架/工具 原因
快速原型验证 SQLite全家桶 Dify 零依赖,最快跑通
企业知识库 PG+pgvector+混合检索 LangChain/LlamaIndex 功能全面,可定制
文档问答(扫描件) PG+pgvector+混合检索 RAGFlow 文档解析能力强
关系推理/多跳 Graph RAG LangChain+Neo4j 支持图检索
小库(<100K token) 长上下文 直接塞模型窗口 简单直接
本地应用/桌面工具 SQLite全家桶 无框架 数据不离开设备
大规模/多租户 ES+混合检索 RAGFlow 分布式性能强

4.3 场景→方案映射

场景 技术方案 框架/工具 原因
快速原型验证 SQLite全家桶 Dify 零依赖,最快跑通
企业知识库 PG+pgvector+混合检索 LangChain/LlamaIndex 功能全面,可定制
文档问答(扫描件) PG+pgvector+混合检索 RAGFlow 文档解析能力强
关系推理/多跳 Graph RAG LangChain+Neo4j 支持图检索
小库(<100K token) 长上下文 直接塞模型窗口 简单直接
本地应用/桌面工具 SQLite全家桶 无框架 数据不离开设备
大规模/多租户 ES+混合检索 RAGFlow 分布式性能强

五、常见踩坑和优化

以下的前提是数据质量要过关,实际在生产中数据治理要花费更多的时间!

检索质量是第一瓶颈

RAG效果不好,80%的问题出在检索环节。优化方向:

  • 混合检索:全文+向量互补
  • 查询增强:改写、扩展、拆分用户问题
  • Rerank:用更精确的模型重新排序

分块策略决定成败

分块太大会引入噪声,太小会丢失上下文。建议:

  • 从500-1000字符开始,按业务场景调优
  • 用Parent-Child策略:小块检索,大块生成
  • 表格、代码块尽量作为原子单元

Embedding模型需自评

不要只看排行榜,要在自有数据上评估。建议:

  • 准备50-100个真实查询和期望结果
  • 对比不同模型的召回率
  • 中文场景优先选BGE、M3E

Prompt设计影响生成质量

Prompt要明确约束,减少幻觉:

  • 明确告诉模型”只基于提供的文档回答”
  • 要求模型引用来源
  • 没有相关信息时,让模型说”暂无数据”

语义缓存:降低40%成本

语义缓存的核心思想:相似的查询直接返回缓存结果,不走检索+生成流程。

适用场景:高频重复查询(如客服、FAQ)。实现方式:计算查询的Embedding,和缓存中的查询比较相似度,超过阈值直接返回。

评测是迭代的基础

用RAGAS框架评估RAG系统,核心指标:

  • Faithfulness:答案有没有基于检索结果
  • Answer Relevancy:答案和问题相不相关
  • Context Precision:检索结果精不精确
  • Context Recall:检索结果全不全

评测集需要定期校准,确保覆盖真实业务场景。

多轮对话的RAG处理

多轮对话场景比单次查询复杂。用户问”这个政策有什么要求?”,第二轮问”那申请流程呢?”,第二轮的”那”指的是第一轮的政策。处理方式:把对话历史和当前问题一起传给检索模块,或者用LLM先把指代消解成完整问题再检索。这部分的完整实现将在第二篇”RAG架构详解”中展开。


六、从哪里开始

第一步:跑通最简单的RAG

用LangChain RAG Tutorial,10行代码跑通最简单的流程:

from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.chains import RetrievalQA

# 1. 创建向量数据库
vectorstore = Chroma.from_documents(documents, OpenAIEmbeddings())

# 2. 创建RAG链
qa_chain = RetrievalQA.from_chain_type(
    llm=ChatOpenAI(model="deepseek-v4-flash"),
    retriever=vectorstore.as_retriever(search_kwargs={"k": 5}),
)

# 3. 提问
answer = qa_chain.invoke("2024年产业园申报有什么要求?")

第二步:加BM25混合检索

from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever

# BM25检索器
bm25_retriever = BM25Retriever.from_documents(documents)
bm25_retriever.k = 5

# 向量检索器
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 5})

# 混合检索
ensemble_retriever = EnsembleRetriever(
    retrievers=[bm25_retriever, vector_retriever],
    weights=[0.4, 0.6],  # BM25权重0.4,向量权重0.6
)

第三步:加Rerank模型

from langchain.retrievers import ContextualCompressionRetriever
from langchain_cohere import CohereRerank

# Rerank模型
reranker = CohereRerank(model="rerank-v3.5", top_n=3)

# 带Rerank的检索器
compression_retriever = ContextualCompressionRetriever(
    base_compressor=reranker,
    base_retriever=ensemble_retriever,
)

第四步:用RAGAS评测

from ragas import evaluate, SingleTurnSample, EvaluationDataset
from ragas.metrics import Faithfulness, AnswerRelevancy

# 构建评测样本
samples = [
    SingleTurnSample(
        user_input="2024年产业园申报有什么要求?",
        response="需要编制实施方案和资金使用方案...",
        retrieved_contexts=["创建阶段:编制实施方案、资金使用方案..."],
        reference="申请国家级产业园需要编制实施方案、资金使用方案、基本情况表",
    ),
]

# 运行评测
result = evaluate(
    dataset=EvaluationDataset(samples=samples),
    metrics=[Faithfulness(), AnswerRelevancy()],
)
print(result)

第五步:按业务场景调优

  • 调整分块大小和overlap
  • 调整BM25和向量的权重
  • 优化Prompt约束
  • 扩充评测集

完整代码示例将在第二篇”RAG架构详解”中展开。


总结

从”向量检索”到”理解RAG的完整体系”。 RAG不是向量库+TopK,而是7层管线的组合优化。每一层都有多种技术选择,组合方式不同,效果差异很大。

从”Demo能跑”到”生产能用”。 混合检索、Rerank、查询增强、语义缓存,这些Demo阶段不会遇到的优化,才是RAG能不能上线的关键。

关键不是选什么框架,而是理解每个环节的作用。 框架会变,但RAG的核心原理不会变。理解了每个环节的作用,不管用什么框架,都能做出好的RAG系统。欢迎评论区交流~


关键词:RAG、检索增强生成、向量检索、混合检索、BM25、Embedding、Rerank、Agentic RAG、RAGAS、LangChain、LlamaIndex、Dify、RAGFlow

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐