AI Agent 学习day4 从 RAG 检索到 Function Call:一文理解大模型问答系统的完整链路

从 RAG 检索到 Function Call:理解大模型应用的完整问答链路

前言

最近在学习 RAG 和 AI Agent 相关内容时,我逐渐意识到一个问题:

很多人一开始理解 RAG,只会停留在一句话上:

RAG = 检索增强生成,也就是先查资料,再让大模型回答。

这句话没错,但还不够。

一个真正可用的 RAG 系统,至少要解决三个关键问题:

  1. 怎么把相关资料准确检索出来?

  2. 检索出来之后,怎么让大模型基于资料回答,而不是乱编?

  3. 如果用户的问题不在知识库里,而是要查实时数据或调用业务接口,该怎么办?

这三件事分别对应:

复制代码
RAG 检索策略
RAG 生成策略
Function Call 工具调用

本文就按照这个顺序,把 RAG 从"查资料"到"生成答案",再到"调用工具"的完整链路梳理一遍。


一、RAG 的整体流程

先看一个完整 RAG 系统的大致流程。

1. 离线建库阶段

离线阶段的目标是:把原始资料处理成可以被检索的知识库。

流程大致是:

复制代码
原始文档
→ 文本提取
→ 分 chunk
→ 给 chunk 添加元数据
→ 向量化
→ 存入向量数据库

这里每一步都有自己的作用:

  • 文本提取:从 PDF、Word、网页等文件中提取纯文本。

  • 分 chunk:把长文档切成适合检索的小段。

  • 元数据:给每个 chunk 加上来源、标题、时间、权限等信息。

  • 向量化:把文本转换成向量,方便做语义检索。

  • 向量数据库:存储向量和对应 chunk,支持后续相似度搜索。

简单说,离线阶段就是:

把资料切好、标好、向量化,然后放进知识库。


2. 在线问答阶段

用户真正提问时,进入在线阶段。

流程大致是:

复制代码
用户提问
→ 问题向量化
→ 检索相关 chunk
→ 混合检索召回
→ Reranker 重排序
→ 取 Top-K chunk
→ 组装 Prompt
→ 调用大模型生成答案
→ 返回答案和引用来源

这就是 RAG 问答的核心链路。

但要注意,RAG 不是简单地:

复制代码
检索到资料 → 扔给大模型 → 自动得到正确答案

真正的生产级 RAG 要同时关注:

复制代码
检索质量
生成质量
答案可追溯性

下面分别展开。


二、RAG 检索策略:不能只靠向量检索

很多人刚学 RAG,会以为有了向量数据库就够了。

但实际上,生产环境里的 RAG 不能只依赖向量检索。

因为向量检索擅长语义理解,但不擅长精准关键词匹配。


1. 向量检索:擅长语义理解

向量检索的核心思路是:

把文本转成向量,然后找语义上相近的内容。

它适合处理:

  • 同义表达

  • 模糊问题

  • 自然语言提问

  • 语义相似内容

比如用户问:

复制代码
买了一周的东西还能退吗?

向量检索可能匹配到:

复制代码
七天无理由退货政策

这就是向量检索的优势:它不要求用户和文档使用完全一样的词,只要语义接近,就能召回。

但是向量检索也有短板。

它对下面这类信息不够敏感:

复制代码
订单号
商品型号
年份
缩写
专有名词

比如:

复制代码
订单号 2026012345 的物流状态是什么?

这个问题的关键不是"物流状态"这几个字,而是具体的订单号 2026012345

如果只靠向量检索,系统可能返回:

复制代码
物流配送时效说明
订单物流查询入口
物流异常处理流程

这些内容看起来相关,但没有真正命中具体订单。


2. BM25:擅长关键词精准匹配

BM25 是一种经典关键词检索算法,它主要根据关键词匹配程度来判断文档相关性。

它关注三个核心因素:

复制代码
词频 TF
词的稀有度 IDF
文档长度归一化

可以简单理解为:

  • 一个词出现得越多,文档可能越相关。

  • 一个词越稀有,区分度越高。

  • 长文档不能因为字多就天然占便宜。

BM25 的优势是:精准命中关键词。

比如:

复制代码
订单号 2026012345
iPhone 16 Pro Max
RMA
2026 年春节

这些词如果出现在某个 chunk 里,很可能就是用户真正需要的内容。

但 BM25 不擅长理解语义。

比如用户问:

复制代码
买了一周的东西还能退吗?

如果文档里写的是:

复制代码
签收后 7 天内支持无理由退货

BM25 可能因为关键词不完全一致而匹配不好。


3. 混合检索:向量检索 + BM25

所以在 RAG 中,真正更稳的方案是混合检索:

复制代码
向量检索负责语义召回
BM25 负责关键词精准匹配

流程大致是:

复制代码
用户问题
→ 向量检索召回一批 chunk
→ BM25 检索召回一批 chunk
→ 融合两路结果
→ 得到候选 Top-K

两者是互补关系:

检索方式 擅长 短板
向量检索 语义理解、同义表达、模糊问题 容易丢数字、编号、型号、专有名词
BM25 精准关键词、订单号、缩写、型号 不理解语义,同义词容易匹配不上

所以实际项目里不应该纠结:

复制代码
到底用向量检索还是 BM25?

而应该考虑:

复制代码
怎么把向量检索和关键词检索结合起来?

4. RRF:融合两路检索结果

混合检索会产生一个问题:

向量检索和 BM25 的分数不是一个尺度,不能直接相加。

比如:

复制代码
向量相似度:0.84
BM25 分数:3.8

这两个分数没有可比性。

所以常见做法是使用 RRF,也就是基于排名的融合方法。

RRF 的思想很简单:

一个 chunk 如果在向量检索和 BM25 中都排得靠前,那它大概率更相关。

它不直接比较分数,而是比较排名,因此更适合工程落地。


5. Rerank:对候选结果做精排

混合检索解决的是"召回"问题,但召回出来的结果不一定顺序最优。

所以通常还会加 Reranker。

流程是:

复制代码
混合检索召回 Top-20 / Top-50
→ Reranker 判断 query 和 chunk 的相关性
→ 重新排序
→ 取 Top-3 / Top-5 给大模型

这里有一个关键点:

LLM 最终只能看到放进上下文的那几个 chunk,所以 Top-K 的质量非常重要。

如果最相关的 chunk 没有排到前面,大模型后面再强也很难回答好。

所以调优顺序应该是:

复制代码
先保证关键 chunk 能被召回
再优化排序质量
最后看业务效果

如果召回阶段已经漏掉了关键内容,后面的 Rerank 也救不回来。


三、RAG 生成策略:检索到不代表答得对

很多人会有一个误区:

只要检索到正确 chunk,大模型自然会回答正确。

这是不一定的。

即使 Top-K chunk 很准,大模型仍然可能出现问题:

复制代码
用自己的通用知识覆盖知识库内容
编造 chunk 中没有的数字、日期、金额
把多个 chunk 的信息混在一起
回答相关内容,但没有真正回答用户问题
不给引用来源,用户无法验证

所以 RAG 的最后一公里不是检索,而是生成。


1. RAG Prompt 的三段式结构

一个标准 RAG Prompt 通常包含三部分:

复制代码
System Prompt
Retrieved Context
User Query

可以这样理解:

复制代码
System Prompt:规定模型行为
Retrieved Context:提供事实依据
User Query:明确用户问题

一句话总结:

System Prompt 管行为,Context 管事实,User Query 管目标。


2. System Prompt 的作用

System Prompt 不是简单写一句:

复制代码
你是一个客服助手,请回答用户问题。

这种 Prompt 约束太弱,大模型很容易自由发挥。

在 RAG 场景下,System Prompt 最核心的任务是:

限制模型只能基于参考资料回答。

常见规则包括:

复制代码
只基于参考资料回答
资料不足就明确说不知道
不要编造资料中没有的数字、日期、金额
回答时引用资料编号
多条资料冲突时指出冲突
控制回答语气和长度

其中最关键的是前三条:

复制代码
只基于资料回答
不知道就说不知道
不要编造资料中没有的信息

这三条是抑制幻觉的底线。


3. 检索上下文要带编号和来源

推荐的上下文格式是:

复制代码
【参考资料】

[1] 来源:退货政策文档 | 更新时间:2026-01-15
iPhone 16 Pro Max 拆封后不支持七天无理由退货。

[2] 来源:通用退货规则 | 更新时间:2026-01-10
标准商品在签收后 7 天内可申请无理由退货。

这样设计有三个好处:

  1. 编号 :方便模型在回答中引用 [1][2]

  2. 来源:方便用户追溯答案依据。

  3. 更新时间:当资料冲突时,可以判断哪条资料更新。

这也是元数据在 RAG 系统中的重要价值。


4. 不要塞太多 chunk

Top-K 不是越多越好。

chunk 太多会带来几个问题:

复制代码
关键信息被稀释
模型容易被无关内容干扰
中间信息容易被忽略
成本和延迟增加

一般经验是:

复制代码
简单事实问答:3~5 个 chunk
复杂对比问题:5~8 个 chunk
总结类问题:8~10 个 chunk

如果已经用了 Reranker,通常 Top 3 到 Top 5 个高质量 chunk 就够了。

宁可给少量高质量资料,也不要塞一堆低质量资料。


四、幻觉抑制:让模型别乱编

RAG 生成阶段最怕的就是幻觉。

这里的幻觉不是指模型胡言乱语,而是:

模型生成了看起来合理、读起来流畅,但实际上不符合资料内容的答案。

RAG 场景下常见幻觉有三类。


1. 篡改事实

chunk 里说 A,模型回答 B。

比如:

复制代码
chunk:iPhone 16 Pro Max 拆封后不支持七天无理由退货。
模型:iPhone 16 Pro Max 支持七天无理由退货。

这是最严重的幻觉。

它说明模型没有严格服从知识库,而是用自己的通用知识覆盖了资料。


2. 凭空捏造

chunk 里没有的信息,模型自己补出来。

比如:

复制代码
chunk:质量问题退货,运费由商家承担。
模型:质量问题退货,运费由商家承担,退款将在 3-5 个工作日内到账。

这里的"3-5 个工作日"就是模型编出来的。

这类幻觉在数字、日期、金额上特别常见。


3. 张冠李戴

模型把不同 chunk 的信息混在一起。

比如:

复制代码
chunk1:AirPods Pro 默认保修 1 年。
chunk2:AppleCare+ 可将保修期延长至 2 年。
模型:AirPods Pro 的保修期是 2 年。

正确说法应该是:

复制代码
AirPods Pro 默认保修 1 年;
如果购买 AppleCare+,可以延长至 2 年。

4. 抑制幻觉的核心方法

常用方法有:

复制代码
明确限定知识来源
加"不知道就说不知道"的兜底指令
禁止编造具体细节
要求回答必须带引用
降低 Temperature

RAG 场景下,模型参数也要偏保守:

复制代码
Temperature:0 ~ 0.3
Top-P:0.9 ~ 0.95

因为 RAG 追求的是准确性,不是创造力。

所以可以记住一句话:

RAG 场景下,要把模型自由发挥的空间压到最低。


五、引用对齐:让答案可追溯

企业级 RAG 中,答案不能只是"看起来对",还要能追溯来源。

引用对齐的核心是:

模型回答中的关键结论,都能对应到具体 chunk。

实现方式一般是:

复制代码
每个 chunk 带编号
Prompt 要求模型引用编号
后端解析回答中的 [1][2]
前端把引用渲染成可点击来源

比如模型回答:

复制代码
iPhone 16 Pro Max 拆封后不支持七天无理由退货 [1]。

用户点击 [1],可以看到对应的退货政策文档。

引用对齐的价值有三个:

复制代码
用户能验证答案
出错后能定位问题来源
金融、医疗、法律等场景方便合规审计

所以生产级 RAG 不是只返回一个 answer,而是最好返回:

复制代码
answer
citations
source metadata

六、Function Call:让 RAG 从"查资料"升级到"调工具"

前面的 RAG 解决了一个问题:

用户问知识库里的问题,系统可以检索资料并生成答案。

但现实业务里,用户不一定只问静态知识。

比如:

复制代码
公司的年假制度是什么?

这个问题可以查知识库。

但如果用户问:

复制代码
我还剩几天年假?

这个答案就不在知识库里,而在 HR 系统里。

再比如:

复制代码
订单 #12345 到哪了?

这个答案也不在知识库里,而在订单系统或物流系统里。

这就是 RAG 的能力边界:

RAG 能查资料,但不能天然查实时数据、调业务接口、执行业务动作。

Function Call 就是为了解决这个问题。


1. Function Call 的本质

Function Call 的本质不是让大模型真的执行函数,而是:

让大模型输出一个结构化的函数调用意图。

比如模型输出:

复制代码
{
  "name": "getUserAnnualLeave",
  "arguments": {
    "userId": "user_12345"
  }
}

这表示:

复制代码
模型判断这个问题需要调用 getUserAnnualLeave 工具,
参数是 userId = user_12345。

然后真正执行的是后端代码:

复制代码
getUserAnnualLeave("user_12345");

所以角色分工是:

复制代码
大模型:理解意图,选择工具,生成参数
后端代码:执行函数,查数据库 / 调接口 / 查知识库
大模型:根据工具结果生成自然语言回答

一句话总结:

模型负责选工具和填参数,后端负责真正执行工具。


2. Function Call 的完整流程

标准流程是:

复制代码
1. 后端定义工具列表
2. 把工具列表和用户问题一起发给大模型
3. 大模型判断是否需要调用工具
4. 如果需要,返回 tool_calls
5. 后端解析 tool_calls
6. 后端执行对应函数
7. 把函数执行结果返回给大模型
8. 大模型生成最终答案

也就是说,Function Call 通常是两轮模型调用:

复制代码
第一轮:模型选择工具
第二轮:模型根据工具结果生成答案

第一轮模型可能不会直接回答用户,而是返回:

复制代码
{
  "tool_calls": [
    {
      "function": {
        "name": "getUserAnnualLeave",
        "arguments": "{\"userId\":\"user_12345\"}"
      }
    }
  ]
}

后端执行后得到:

复制代码
{
  "remainingDays": 5,
  "totalDays": 10,
  "usedDays": 5
}

第二轮再把这个结果发给模型,模型最终回答:

复制代码
你还剩 5 天年假,总共 10 天,已使用 5 天。

3. 工具定义:name、description、parameters

一个工具定义通常包括:

复制代码
name:工具名
description:工具描述
parameters:参数定义

示例:

复制代码
{
  "type": "function",
  "function": {
    "name": "getUserAnnualLeave",
    "description": "查询用户的年假余额,包括总天数、已使用天数、剩余天数",
    "parameters": {
      "type": "object",
      "properties": {
        "userId": {
          "type": "string",
          "description": "用户 ID"
        }
      },
      "required": ["userId"]
    }
  }
}

其中最重要的是 description。

因为模型主要根据 description 判断:

复制代码
这个工具能干什么?
当前用户问题该不该调用它?

如果 description 写得太模糊,模型就可能选错工具。


4. parameters 是参数说明书

parameters 使用 JSON Schema 描述函数参数。

比如:

复制代码
{
  "type": "object",
  "properties": {
    "userId": {
      "type": "string",
      "description": "用户 ID"
    },
    "year": {
      "type": "integer",
      "description": "查询年份"
    }
  },
  "required": ["userId"]
}

它表示:

复制代码
参数整体是一个对象
对象里有 userId 和 year 两个字段
userId 是字符串,必填
year 是整数,可选

可以类比 Java 方法:

复制代码
queryLeave(String userId, Integer year)

七、Function Call 在 RAG 中的作用:意图路由

Function Call 可以作为 RAG 系统里的意图路由机制。

比如定义三个工具:

复制代码
searchKnowledgeBase:查询知识库
getUserAnnualLeave:查询用户年假余额
getOrderStatus:查询订单状态

用户问:

复制代码
年假制度是什么?

模型应该选择:

复制代码
searchKnowledgeBase

用户问:

复制代码
我还剩几天年假?

模型应该选择:

复制代码
getUserAnnualLeave

用户问:

复制代码
订单 #12345 到哪了?

模型应该选择:

复制代码
getOrderStatus

更复杂的情况还可以组合使用。

比如用户问:

复制代码
我的订单 #12345 能退货吗?

这个问题既要查订单状态,也要查退货政策。

可能流程是:

复制代码
1. 调 getOrderStatus 查询订单是否签收、是否拆封、购买时间
2. 调 searchKnowledgeBase 查询退货政策
3. 大模型综合订单状态和退货规则生成答案

这就实现了:

复制代码
知识检索 + 工具调用

也就是说:

RAG 让系统能查资料,Function Call 让系统能选工具,后端接口让系统真正干活。


八、Function Call 的局限性

Function Call 很有用,但不是万能的。

它本身只是一个协议,真正落地还要处理很多工程问题。

主要包括:

复制代码
工具定义维护成本高
跨语言、跨系统集成复杂
权限和安全控制要后端自己做
工具调用日志和链路追踪要自己实现

尤其是权限问题,不能交给模型。

比如用户 A 问:

复制代码
帮我查用户 B 的年假余额

模型可能真的生成:

复制代码
{
  "name": "getUserAnnualLeave",
  "arguments": {
    "userId": "user_B"
  }
}

但用户 A 有没有权限查用户 B,这是后端必须校验的。

所以一定要记住:

模型可以决定"想调用什么",但后端必须决定"能不能调用"。

实际项目里,Function Call 后端至少要做:

复制代码
工具白名单
参数校验
权限校验
异常处理
日志记录

九、完整链路总结

把三部分串起来,一个更完整的大模型应用链路大概是:

复制代码
原始文档
→ 文本提取
→ 分 chunk
→ 添加元数据
→ 向量化
→ 存入向量数据库

用户提问
→ 模型判断意图
→ 如果是知识库问题:走 RAG 检索
→ 如果是实时数据问题:走 Function Call 调接口
→ 如果是复杂问题:知识库检索 + 工具调用组合
→ 获取相关资料或工具结果
→ 组装 Prompt
→ 大模型生成最终答案
→ 返回答案和引用来源

可以进一步压缩成一句话:

RAG 负责查静态知识,Function Call 负责调动态工具,Prompt 负责约束模型生成可靠答案。


十、面试表达版

如果在面试中被问到 RAG 检索、生成和 Function Call,可以这样回答:

RAG 系统一般分为离线建库和在线问答两个阶段。离线阶段会对原始文档进行文本提取、分 chunk、添加元数据、向量化,并存入向量数据库。在线阶段用户提问后,会先进行检索召回,生产环境中通常不会只依赖向量检索,而是采用向量检索和 BM25 的混合检索,再通过 RRF 做融合排序,必要时用 Reranker 对候选 chunk 进行精排,最后选出 Top-K chunk 交给大模型。

在生成阶段,RAG 不能简单地把 chunk 丢给模型,因为模型可能会用自身知识覆盖资料、编造细节或者混淆不同 chunk 的信息。因此一般会使用三段式 Prompt,也就是 System Prompt、Retrieved Context 和 User Query。System Prompt 用来限制模型只能基于参考资料回答;Retrieved Context 会带上 chunk 编号、来源、更新时间;User Query 是用户原始问题。同时要求模型引用资料编号,并在后端解析引用,实现答案可追溯。

但 RAG 本身主要解决静态知识问答,如果用户问的是实时数据,比如年假余额、订单状态、考勤记录,就需要 Function Call。Function Call 的本质不是让模型真的执行函数,而是让模型根据工具描述输出 tool_calls,包括函数名和参数。后端解析 tool_calls 后真正执行接口或数据库查询,再把结果返回给模型,由模型生成最终答案。实际项目中,还必须在后端做好参数校验、权限控制、工具白名单和日志追踪。


十一、最终记忆版

最后可以用这几句话记住整套逻辑:

复制代码
RAG 检索不能只靠向量。
向量检索懂语义,但容易丢精准词;
BM25 不懂语义,但擅长订单号、型号、年份、缩写等精准匹配;
生产级 RAG 通常是向量检索 + BM25 + RRF 融合 + Rerank 精排。

RAG 生成不能只把 chunk 丢给大模型。
要用 System Prompt 限制模型只基于资料回答,
资料不足就说不知道,
不要编造数字、日期、金额,
并通过引用编号实现答案可追溯。

Function Call 不是模型真的执行函数。
模型只负责理解用户意图、选择工具、生成参数;
后端负责真正执行接口、查数据库、查知识库,并做权限校验和参数校验。

最核心的一句话:

生产级大模型问答系统 = 混合检索保证找得准,Prompt 约束保证答得稳,Function Call 扩展系统能力边界。

相关推荐
BullSmall13 小时前
JMeter AI 插件
人工智能·jmeter
AI服务老曹13 小时前
解耦安全中台:基于 Docker 部署与 GB28181/RTSP 统一接入的边缘计算 AI 视频管理平台(附源码交付与 API 架构解析)
人工智能·安全·docker
土拨鼠烧电路13 小时前
第3章:裂痕——Siri、Copilot与寄生者入侵
人工智能·copilot
爱学习的程序媛13 小时前
C 语言全景指南:从底层原理到工业级实战
c++·c#·c
数字化转型202513 小时前
新能源企业AI数字化转型核心议题、内容及实施策略方案
大数据·人工智能·产品运营
十铭忘13 小时前
infoGCN++的训练2——论文复现
人工智能
魔法阵维护师13 小时前
从零开发游戏需要学习的c#模块,第二十九章(经验值与升级系统)
学习·游戏·c#
watersink13 小时前
检索增强生成(RAG)原理与实战培训文档
人工智能
一切皆是因缘际会13 小时前
AI进入普惠化落地新时代
人工智能·深度学习·ai·重构