RAG 到底是怎么工作的?从用户提问到模型回答的完整链路

大模型很聪明,但它通常不知道企业内部文档,也不知道刚刚更新的业务规则。

如果直接问模型:

公司退款需要几天到账?

模型可能根据训练数据猜一个答案,也可能一本正经地编错。

RAG(Retrieval-Augmented Generation,检索增强生成)的作用,就是在模型回答之前,先从企业知识库里找到相关资料,再让模型基于这些资料作答。

可以把它理解成一次"开卷考试":

普通大模型依赖记忆答题;RAG 先帮模型翻书,再让模型根据找到的内容答题。

一句话理解 RAG

RAG 的核心流程是:

text 复制代码
用户提问
  → 从知识库检索相关资料
  → 筛选出少量可靠原文
  → 将问题和原文一起交给大模型
  → 大模型生成答案

它不是重新训练模型,也不是把整个知识库发送给模型。

RAG 的完整工作流程

RAG 通常分为两个阶段:

  • 离线阶段:构建知识库。
  • 在线阶段:检索资料并生成答案。

一、离线阶段:知识库是怎么建成的

1. 解析原始资料

企业数据可能来自很多地方:

  • PDF、Word、Excel;
  • 产品说明和操作手册;
  • 内部 Wiki;
  • 数据库记录;
  • 客服 FAQ;
  • 网页和接口。

系统首先需要提取正文、标题、表格和层级关系,同时清除页眉、页脚、导航栏和重复内容等噪声。

如果输入内容本身就是错的,后面的模型再强也没有用。

2. 将长文档切成 Chunk

一份几十页的文档一般不会整体存成一个检索单元,而是拆成多个文本片段,也就是 Chunk。

例如:

text 复制代码
退款规则.md

Chunk 1:退款申请条件
Chunk 2:退款审核流程
Chunk 3:退款到账时间
Chunk 4:特殊情况处理

切分主要有两个原因:

  • 一个问题通常只与文档中的一小部分有关;
  • 整篇文档放进模型上下文既浪费 Token,也容易稀释重点。

Chunk 不是越小越好。

切得太小,语义可能不完整;切得太大,又会包含太多无关内容。因此,文档切分策略会直接影响 RAG 的最终效果。

3. 添加 Metadata

除了原文,每个 Chunk 通常还会附带一些元数据:

json 复制代码
{
  "documentId": "refund-policy-2026",
  "title": "退款到账时间",
  "department": "finance",
  "tenantId": "1001",
  "securityLevel": 2,
  "updatedAt": "2026-09-01"
}

这些信息可以用于:

  • 用户权限过滤;
  • 租户隔离;
  • 按部门检索;
  • 排除过期文档;
  • 展示答案引用来源。

生产环境中,权限过滤的重要性往往不低于检索准确率。

4. 使用 Embedding 模型生成向量

Embedding 模型会把文本转换成一组数字:

text 复制代码
"退款一般在 3~5 个工作日到账"
                ↓
[0.018, -0.231, 0.764, ...]

这些数字表达文本的语义特征。

语义相近的内容,在向量空间中的距离通常也比较接近。因此:

text 复制代码
退款多久到账
退款到账时间
退款几天能收到

虽然文字不同,但它们可能被检索到一起。

需要注意:

Embedding 向量不是答案,也不代表模型已经学会了这段内容。它主要用于查找语义相近的文本。

5. 写入向量数据库

最终保存的通常不只是向量,还包括:

text 复制代码
向量
+ 原始文本或文本 ID
+ 文档来源
+ 权限信息
+ 其他 Metadata

至此,离线知识库准备完成。

二、在线阶段:用户提问后发生了什么

假设用户提出问题:

退款需要多久才能到账?

1. 客户端只负责提交问题

客户端一般只提交:

json 复制代码
{
  "question": "退款需要多久才能到账?",
  "conversationId": "c-123"
}

同时携带用户登录凭证。

客户端不应该:

  • 下载整个知识库;
  • 自己过滤知识库内容;
  • 保存模型或知识库密钥;
  • 决定用户是否有权查看某份文档。

这些工作应当在服务端完成。

2. 服务端处理问题

RAG 后端收到问题后,可能先进行:

  • 错别字修正;
  • 指代消解;
  • 多轮对话补全;
  • 查询改写;
  • 关键词提取;
  • 租户和用户权限解析。

例如,用户追问:

那节假日呢?

系统可能结合上一轮对话,将它改写为:

退款在节假日期间需要多久才能到账?

3. 将问题转换成查询向量

系统使用 Embedding 模型,把问题转换成查询向量:

text 复制代码
"退款需要多久才能到账?"
              ↓
Query Embedding

然后使用查询向量搜索知识库中距离较近的文档向量。

4. 召回候选资料

向量数据库可能返回:

text 复制代码
0.92  退款一般在 3~5 个工作日到账
0.86  节假日期间退款可能顺延
0.78  退款申请提交后进入审核
0.61  发票通常在订单完成后开具

这个阶段通常会适当多取一些候选资料,例如 Top-K 取 20 条。

原因是初次向量检索强调"不要漏掉",后面还可以继续筛选。

有些系统还会同时执行关键词检索:

text 复制代码
向量检索:擅长语义相近
关键词检索:擅长编号、名称和专业术语

两种结果合并后,就是混合检索。

三、相似度不会直接生成答案

这是 RAG 中最容易误解的地方。

相似度的作用是:

决定哪些资料更值得交给大模型阅读。

它并不直接决定最终答案怎么写。

text 复制代码
相似度检索
  → 选择参考资料

大模型
  → 阅读参考资料并生成答案

例如相似度是 0.92,并不意味着模型按照 92% 的权重生成某句话。

这个分数主要用于候选资料的筛选和排序。最终答案仍然由大模型根据 Prompt,逐个预测 Token 生成。

四、为什么还需要过滤和 Rerank

向量检索速度快,但初次返回的内容不一定足够准确。

因此,候选资料通常还要经过几层处理。

权限过滤

系统需要根据当前用户身份过滤资料:

text 复制代码
用户所属租户必须匹配
用户部门必须具备访问权限
文档安全等级不能超过用户等级

权限过滤必须在资料发送给模型之前完成。

否则,即使最终页面没有展示敏感引用,敏感内容也可能已经被发送给模型。

Metadata 过滤

系统还可以限定:

  • 只检索当前产品;
  • 只检索已经生效的规则;
  • 排除过期文档;
  • 只查询指定业务类型。

Rerank 重排

Rerank 模型会把用户问题和每个候选片段放在一起,重新判断相关性。

典型流程如下:

text 复制代码
向量数据库快速召回 20 条
        ↓
Rerank 精确重新排序
        ↓
选择最终 3~5 条

可以把向量检索理解为初筛,把 Rerank 理解为复筛。

五、最终发送给大模型的是什么

系统不会把整个向量数据库发送给模型。

一般只会发送:

  • 系统回答规则;
  • 用户问题;
  • 筛选出的少量原文;
  • 必要的对话历史。

例如:

text 复制代码
系统规则:
你只能根据参考资料回答。
如果参考资料不足,请明确回答无法确定。
回答时标注资料编号,不要自行补充业务规则。

用户问题:
退款需要多久才能到账?

参考资料:
[1] 退款审核通过后,一般在 3~5 个工作日到账。
[2] 如遇法定节假日,到账时间可能顺延。

模型最后生成:

退款审核通过后,一般会在 3~5 个工作日到账;如遇法定节假日,到账时间可能顺延。12

所以更准确的说法是:

服务端先筛选模型需要阅读的资料,模型再根据这些资料组织答案。

六、各个组件分别负责什么

组件 主要职责
客户端 提交问题、携带用户凭证、展示答案和引用
业务后端 鉴权、检索编排、Prompt 组装和异常处理
Embedding 模型 将问题或文档转换为语义向量
向量数据库 快速召回相似的候选资料
Rerank 模型 对候选资料进行更精确的重新排序
大模型 阅读最终原文并生成答案

简单概括:后端负责调度,向量数据库负责初筛,Rerank 负责精选,大模型负责生成。

如果使用托管 RAG 服务,这些组件可能由一个平台内部完成,但职责边界依然存在。

七、用伪代码看一次完整调用

不考虑具体框架,一次问答大致可以写成:

java 复制代码
String question = request.question();

// 解析用户、租户和文档权限。
AccessScope scope = permissionService.resolve(request.userId());

// 从知识库中召回较多候选资料。
List<Document> candidates =
        knowledgeBase.search(question, scope, 20);

// 删除无权限、已过期或者分数过低的资料。
List<Document> filtered =
        documentFilter.filter(candidates, scope);

// 对候选资料重新排序,并取最终五条。
List<Document> context =
        reranker.rerank(question, filtered).stream()
                .limit(5)
                .toList();

// 没有可靠资料时停止回答,避免模型猜测。
if (context.isEmpty()) {
    return "现有资料不足,暂时无法确定。";
}

// 将规则、问题和原文组装成 Prompt。
Prompt prompt = promptBuilder.build(question, context);

// 调用大模型生成最终答案。
String answer = chatModel.generate(prompt);

// 返回答案以及对应的文档来源。
return responseBuilder.build(answer, context);

这段代码体现了 RAG 的本质:

text 复制代码
Retrieve:检索资料
Augment:把资料加入上下文
Generate:模型生成答案

八、RAG 最容易出问题的地方

1. 文档切分不合理

如果标题和正文被拆开,或者一个业务规则被切成几个不完整片段,检索结果即使相似,也可能无法回答问题。

2. 只使用向量相似度

专有名词、错误码、订单号和精确编号通常更适合关键词检索。因此,生产系统经常使用混合检索。

3. 没有权限过滤

如果只追求召回率,没有把用户权限带入检索条件,就可能产生越权访问和数据泄露。

4. 检索多少内容都交给模型

内容太少可能漏掉答案,内容太多则会增加成本、延迟和干扰信息。

Top-K 和最终 Top-N 应通过测试集评估,而不是随便设置。

5. 没有拒答机制

资料不足时仍然强制模型回答,很容易产生幻觉。

一个可靠的 RAG 系统应该允许回答:

根据当前知识库资料无法确定。

6. 知识库没有及时更新

RAG 能读取新知识,不代表它会自动知道知识已经变化。

文档新增、修改或者删除后,需要同步更新索引。

7. 不记录检索过程

出现错误时,需要知道:

  • 用户原始问题是什么;
  • 改写后的查询是什么;
  • 召回了哪些片段;
  • 每条资料的分数是多少;
  • 最终给模型发送了什么;
  • 模型引用了哪些资料。

否则很难判断问题究竟出在检索阶段,还是生成阶段。

九、如何评价一个 RAG 系统

RAG 不能只看"回答听起来是否自然"。

至少需要分开评估三个方面。

检索质量

  • 正确资料是否被召回;
  • 无关资料是否过多;
  • 正确资料的排名是否足够靠前;
  • 权限过滤是否正确。

生成质量

  • 答案是否得到参考资料支持;
  • 是否添加了资料中不存在的内容;
  • 引用是否准确;
  • 资料不足时是否正确拒答。

工程指标

  • 接口耗时;
  • 模型 Token 消耗;
  • 知识库和模型调用成功率;
  • 超时、降级和重试情况。

检索错误和生成错误必须分开定位。模型答错了,不一定是模型能力不足,也可能是系统根本没有给它正确资料。

总结

RAG 并不是一个神秘的新模型,它是一套"检索、上下文组装、模型生成"的工程流程。

完整链路可以归纳为:

text 复制代码
文档解析
  → 文本切分
  → Embedding
  → 向量入库
  → 用户提问
  → 相似度召回
  → 权限过滤
  → Rerank
  → 选择少量原文
  → 组装 Prompt
  → 大模型生成
  → 返回答案和引用

其中最重要的几个边界是:

  • 客户端只提交问题,不负责过滤知识库;
  • 相似度负责选择资料,不直接生成答案;
  • 模型只接收筛选后的少量原文,不会读取整个向量数据库;
  • RAG 后端负责鉴权、检索编排、上下文组装和异常处理;
  • 资料不足时,可靠的系统应该拒绝猜测。

下一篇进入代码层面:

《知识库已经有了,Java 程序员还要做什么?Spring AI 实战》

相关推荐
Joy T1 小时前
Spring AI 2.0 Agent 进阶:Memory、State 与 Context Engineering 常见技术全景
java·人工智能·后端·spring·agent入门·agent state
wangruofeng2 小时前
把AI判断做成「智能if语句」!Jev实测:一次调用3个判断,置信度直接路由
aigc·agent·ai编程
全栈技术负责人2 小时前
让 Agent 动手前先“听懂人话”:意图识别插件的设计与实践
ai·ai编程
桃西西呀3 小时前
别被"秒回"骗了:推理模型背后那只"吞金兽",吃的是你看不见的预算
人工智能·llm·ai编程
全栈弄潮儿3 小时前
用 AI 快速读懂陌生项目:代码库导览工作流
aigc·openai·ai编程
龙智DevSecOps解决方案3 小时前
JFrog供应链流量控制器架构解析:如何通过 SASE 集成阻断 AI 智能体的恶意依赖拉取?
ai编程·devops·jfrog·软件供应链安全
wno7044 小时前
Spring Security短信验证码登录
java·python·spring
步行cgn4 小时前
Spring util 命名空间详解
java·后端·spring
MayBaymax7 小时前
Spring AI Alibaba Graph 快速上手:黑板、节点、边
java·spring·ai·ai编程