从“胡言乱语”到“逻辑专家”:深度解析 RAG, ReAct 与 PAL 三大架构
文章目录
尽管 GPT-4 等大语言模型展现出了令人惊叹的语言天赋,但在面对私有知识空白、逻辑幻觉以及复杂数学运算时,它们依然会暴露出“复读机”的本质。为了让 AI 真正具备专业性与可靠性,开发者们探索出了三条不同的进化路径:RAG 为模型外接了实时更新的知识库,ReAct 赋予了模型观察与行动的能力,而 PAL 则让模型学会了用代码逻辑解决精密计算。本文将带你拆解这三大核心架构,探究它们是如何共同构建起下一代 AI Agent 的基石。
RAG:检索增强生成 (Retrieval-Augmented Generation)
先看一个例子:
你问大模型:“我们公司今年的年假政策是什么?”
模型自信地回答:“根据《劳动法》规定,员工每年享有5天带薪年假。”
但你们公司实际政策是:入职满一年享10天,满三年享15天。
结果——模型在瞎编。
这就是大模型的经典问题:训练数据里没有你公司的内部文档,它只能“闭卷考试”,靠记忆回答。一旦知识陈旧或私有,必然出错。
RAG 的核心思想
RAG 全称 Retrieval-Augmented Generation,翻译过来就是 检索增强生成。
它的做法很简单:在让大模型回答问题之前,先从一个外部知识库里把相关的资料“查”出来,连同问题一起喂给模型。
换句话说:
传统 LLM = 闭卷考试(全靠记忆)
RAG = 开卷考试(先翻书,再答题)
RAG 的工作流程

具体每一步:
-
预处理(离线阶段)
- 把你所有的文档(PDF、Word、网页、数据库记录)切成小段。
- 每段通过嵌入模型(Embedding Model)转成向量。
- 存入向量数据库(如 Milvus、Pinecone、Chroma)。
-
检索(在线阶段)
- 用户提问后,将问题也转换成同一个向量空间的向量。
- 在向量数据库里搜索最相似的 K 个文档片段(K 通常为 3~10)。
-
生成(在线阶段)
- 构造一个 Prompt,把检索到的片段作为“参考资料”,再加上用户的原始问题。
- 例如:
参考以下信息: 1. 公司年假政策:入职满1年享10天,满3年享15天。 2. 年假需在次年3月底前休完。 问题:我们公司的年假有多少天?- 将 Prompt 送给大模型,模型基于资料生成答案,不再依赖自己的记忆。
为什么 RAG 这么受欢迎?
| 优点 | 说明 |
|---|---|
| 知识可控 | 你可以随时增删知识库内容,不用重新训练模型。 |
| 成本低廉 | 相比微调(Fine-tuning),RAG 不需要 GPU 训练,只需一次嵌入计算。 |
| 可溯源 | 模型可以同时返回引用的文档来源,减少“幻觉”。 |
| 实时更新 | 新文档加入知识库后立刻生效。 |
常见应用场景
- 企业知识库问答:员工手册、技术文档、客服知识库。
- 医疗/法律咨询:基于最新的临床指南或法律条文回答问题。
- 单独商品问答:针对用户“这个充电宝能带上飞机吗?”结合商品详情页和航空规定回答。
- 实时新闻总结:先搜索最新新闻,再生成摘要。
当然很多地方都会用到RAG
冷知识:
你所使用的AI应用软件中的 “添加文件”,背后所使用的就是 RAG
一句话总结 RAG:
RAG = 给大模型配一个随时可查的“外挂硬盘”,让回答不再靠瞎猜,而是有凭有据。
ReAct:推理与行动 (Reason + Act)
再举个例子:
用户问:“帮我查一下本周五北京到上海的机票,要下午到达、经济舱,预算1500元以内。”
你用 RAG 去查知识库?知识库里根本没有实时机票数据。
你让大模型直接回答?它只能根据训练记忆编造一个“可能的价格”。
这里缺少的是什么?行动能力——调用外部工具(如航班查询API),并根据结果做决策。
而且,这个任务不是一步完成的:可能需要先查航班,发现价格超预算,再改日期或换航空公司。
ReAct 就是为这种多步交互任务而生的。
重要提醒:ReAct(Reason+Act)与前端框架 React 是两个完全不同的事物。
- React(前端库):由 Meta 开发,用于构建用户界面。
- ReAct(AI 范式):由论文提出,用于增强语言模型的交互能力。
写法上,AI 领域的 ReAct 通常采用 R-e-Act 这样的拼写强调,但标准的正确写法就是 ReAct。
ReAct 的核心思想
ReAct 全称是 Reason + Act,由 Google Research 和 Princeton 大学在 2022 年提出。
它的核心模式非常简单,却非常强大:
思考(Thought) → 行动(Action) → 观察(Observation) → 再思考 → 再行动 → … → 最终答案(Final Answer)
- 思考:模型描述当前要解决什么问题、下一步该做什么。
- 行动:调用外部工具(搜索引擎、数据库、计算器、API、代码解释器等)。
- 观察:工具返回的结果。
- 循环:根据观察结果继续思考下一步,直到可以给出最终答案。
通俗比喻:就像一个侦探,先想“我需要知道嫌疑人的不在场证明”,然后去查监控(行动),看到监控结果(观察),再想“还需要指纹信息”,接着行动……最终推理出真相。
ReAct完整的工作流程
让我们用上面的机票任务模拟一个 ReAct 轨迹:
问题:本周五北京到上海的机票,下午到达,经济舱,1500元以内。
第1轮:
Thought: 我需要先查询周五北京飞上海的所有航班信息。
Action: 调用航班查询API,参数:日期=本周五,出发=北京,到达=上海
Observation: [结果] 东航MU5128 14:00-16:30 价格1800元;国航CA1500 16:30-19:00 价格1200元;……
第2轮:
Thought: 国航有一班16:30出发,19:00到达,价格1200元,符合下午到达且预算内。但用户说“下午到达”,16:30出发算下午吗?可能需要确认一下。另外,是否还有其他低价选项?
Action: 搜索“国航CA1500 评价 准点率”
Observation: 该航班经常延误,平均延误45分钟。
第3轮:
Thought: 延误风险较高,用户可能介意。再看东航价格1800元超预算,不选。是否需要推荐另一个临近时段?再查一下其他航司。
Action: 调用航班查询API,加入条件:价格<1500元,起飞时间在12:00-18:00之间
Observation: 还有南航CZ3900 15:00-17:30 价格1350元;海航HU7608 17:00-19:30 价格1400元。
第4轮:
Thought: 南航CZ3900 15:00出发,17:30到达,价格1350元,准点率90%以上,符合所有条件。推荐这个。
Action: 最终答案:南航CZ3900,15:00起飞,17:30到达,票价1350元,准点率高。是否预订?
注意:这个轨迹中的 Thought、Action、Observation 都是模型生成的(Action 参数由模型选择,Observation 由真实工具返回)。
ReAct vs 普通链式调用(Chain-of-Thought, CoT)
| 维度 | CoT(思维链) | ReAct |
|---|---|---|
| 输出 | 仅文本推理 | 文本推理 + 具体行动指令 |
| 是否调用外部工具 | 否 | 是 |
| 是否与环境交互 | 否 | 是 |
| 能否获取实时信息 | 否 | 能 |
| 错误恢复能力 | 无,线性推理 | 有,根据观察调整下一步 |
简单说:CoT 是“闭上眼睛思考”,ReAct 是“睁开眼睛伸手做事”。
常见工具集成(模型可以调用的行动)
- 搜索引擎:获取实时新闻、最新事件。
- 维基百科/文档库:查找定义、背景知识(可视为内置 RAG)。
- 计算器/代码解释器:执行精确运算(与 PAL 相通)。
- 数据库查询:获取结构化数据。
- 第三方 API:订票、发邮件、查天气、调用企业内部系统。
可能遇到的问题与应对
| 问题 | 说明 | 应对方案 |
|---|---|---|
| 死循环 | 模型反复做相同的行动而没有进展 | 设置最大步数限制(如10步),超时终止。 |
| 无效行动 | 模型生成的工具参数错误或不存在 | 用 Pydantic 结构化输出,或让模型生成 JSON 后验证。 |
| 推理混乱 | 思考与行动无关,或忘记之前观察 | 用更强的模型(GPT-4 优于 GPT-3.5);在 Prompt 中要求维护记忆。 |
| 成本高 | 每次行动+思考都调用 LLM,token 消耗大 | 小任务用单次 ReAct,或微调一个小模型专门做代理。 |
常见应用场景
- 智能助手:帮助用户订餐厅、查航班、设置提醒。
- 科研文献综述:先查论文→总结→再查相关引用→写综述。
- 代码调试:模型运行代码→看报错→思考→修改代码→再运行。
- 多跳问答:问题需要分步查询多个数据源(例如“XX公司CEO的母校在哪?”需要先查CEO是谁,再查其教育背景)。
跟 RAG 一样也有很多地方会用到 ReAct
冷知识:
你所使用的AI应用软件中的 “联网搜索”,常常就会用到 ReAct
一句话总结 ReAct
ReAct = 让大模型像一个能调用工具的智能体,通过“思考→行动→观察”的循环,完成多步真实世界任务。
PAL:程序辅助语言模型 (Program-Aided Language Models)
还是先来举个例子
问:“一个长方形的长是 12.5 米,宽是 4.8 米,求面积。然后如果每平方米需要 0.25 升油漆,总共需要多少升?”
大模型开始推理:“面积 = 12.5 × 4.8 = 60.0 平方米,油漆 = 60.0 × 0.25 = 15.0 升。”
看起来对了?
换个题:“(1398 × 0.172) ÷ (5830 ÷ 12) + 4.2³”
模型开始输出:……“结果大约是 3.14159……不对,我重算……是 9.87……”——它开始编数字了。
问题根源:大模型本质是语言模型(也可以理解为猜词机器),不是计算器。它通过训练记住了很多算术结果,但遇到复杂的、带括号的、小数混合运算时,它会近似、跳步、甚至瞎猜。更可怕的是,它不会告诉你“我不会算”,而是自信地输出一个错误答案。
PAL 就是来解决这个问题的。
PAL 的核心思想
PAL 全称 Program-Aided Language Models,由 Luyu Gao 等人在 2022 年提出。
它的思路非常直接:
大模型不直接输出答案,而是输出一段可执行的代码(通常是 Python)。
外部解释器执行这段代码,返回精确的计算结果。
换句话说:
- 传统 LLM = 心算(可能错)
- PAL = 列算式 + 用计算器算(绝对精确)
PAL 的工作流程

具体步骤:
-
代码生成
将用户的问题(尤其是数学、数据计算类)喂给大模型,并要求它只输出 Python 代码,不输出自然语言答案。Prompt 通常包含示例,教会模型如何把计算问题转化为代码。 -
代码执行
用一个安全的沙箱环境(如 Python eval、Exec、或受限的代码解释器)运行这段代码,捕获输出。 -
答案返回
把执行结果作为最终答案,或者连同自然语言解释一起返回。
3.4 对比示例:不用 PAL vs 用 PAL
问题:
某公司第一季度营收 120 万元,第二季度增长 15%,第三季度比第二季度少 5 万元,第四季度是前两个季度之和的 0.8 倍。求全年总营收。
❌ 不用 PAL(模型直接口算)
模型可能输出:
“第一季度 120,第二季度 120×1.15=138,第三季度 138-5=133,第四季度 (120+138)×0.8=206.4,总和 = 120+138+133+206.4=597.4 万元。”
看着没问题?但如果改一下数字,或者加入除法、幂运算,模型很容易算错步骤。
✅ 用 PAL(模型生成代码)
模型输出的内容(不是答案,是代码):
q1 = 120
q2 = q1 * 1.15
q3 = q2 - 5
q4 = (q1 + q2) * 0.8
total = q1 + q2 + q3 + q4
print(total)
执行这段代码,解释器输出:597.4。
绝对精确,且可重复验证。
那为什么 PAL 比“让模型直接计算”更可靠?
| 维度 | 直接计算(LLM) | PAL(生成代码) |
|---|---|---|
| 计算精度 | 可能出错,尤其是多步、小数、混合运算 | 完全精确(浮点数精度由解释器保证) |
| 计算过程 | 隐含在模型中,无法审计 | 代码可见,可调试 |
| 复杂逻辑 | 容易混淆顺序 | 代码逻辑显式,括号、优先级明确 |
| 中间结果 | 模型可能省略 | 变量保存,可打印 |
| 可复用性 | 无 | 代码可保存、修改、重用 |
PAL的进阶技巧
PAL 不止能做加减乘除,还可以让模型生成代码来处理:
- 数据统计:
sum(data) / len(data) - 单位换算:
km_to_miles = km * 0.621371 - 日期运算:计算两个日期间隔天数
- 逻辑判断:if 条件嵌套,比如根据营收决定奖金级别
- 调用第三方库:例如
math.sqrt(),pandas做简单数据分析
甚至可以生成多行代码、函数定义、循环来处理批量数据。
PAL与 ReAct 的关系
注意:PAL 和 ReAct 不是互斥的,而是可以嵌套的。
在 ReAct 框架中,当模型“思考”到需要做数值计算时,它可以“行动”为 生成一段 Python 代码,然后观察执行结果,继续推理。
这就是二者的典型组合:
Thought: 需要计算今年的增长率,用去年和今年的营收。
Action: 执行 PAL,生成代码 (去年=500, 今年=620, 增长率=(今年-去年)/去年)
Observation: 代码返回 0.24
Thought: 增长率为24%,现在可以回答用户问题了。
安全注意事项
让大模型生成代码并在你的服务器上执行,有潜在风险。务必:
- 使用沙箱环境:如 Docker 容器、受限的 Python 解释器(禁用
os,subprocess,eval的危险用法)。 - 限制执行时间:防止死循环(例如设置 timeout=5秒)。
- 限制内存和 CPU:避免资源耗尽。
- 过滤危险字符:不要让模型生成
__import__('os').system('rm -rf /')之类的恶意代码。
建议使用现成的安全代码执行库,如 ExecPython (LangChain 的 PythonREPL 工具) 或 RestrictedPython。
什么时候应该用 PAL?
| 场景 | 是否推荐 PAL |
|---|---|
| 简单四则运算(10以内整数) | 不一定需要(LLM 通常能算对) |
| 多步混合运算、小数、括号 | ✅ 强烈推荐 |
| 涉及单位换算、日期计算 | ✅ 推荐 |
| 需要调用数学函数(如 sqrt, sin, log) | ✅ 必须用(LLM 几乎算不准) |
| 需要批量处理列表/数据 | ✅ 推荐 |
| 作为 ReAct 智能体的一个计算工具 | ✅ 最佳实践 |
一句话总结 PAL
PAL = 遇到数学问题,大模型不再“心算”而是“写算式并交给电脑算”,从而保证 100% 精确、过程透明、可复现。
一张表格秒懂:RAG、ReAct、PAL 到底有什么不一样?
三个技术听起来都像在“增强大模型”,但它们的出发点和解决的问题完全不同。下面这张表格帮你快速区分。
核心差异对比表
| 对比维度 | RAG(检索增强生成) | ReAct(推理+行动) | PAL(程序辅助语言模型) |
|---|---|---|---|
| 一句话定义 | 让模型先查资料再回答 | 让模型边思考边调用工具 | 让模型写代码来精确计算 |
| 解决什么痛点 | 知识过时、私有知识缺失、幻觉问题 | 需要多步交互、调用外部工具、实时信息 | 算术不准、复杂计算易错 |
| 核心机制 | 检索 → 注入 Prompt → 生成 | Thought → Action → Observation 循环 | 生成 Python 代码 → 执行 → 返回结果 |
| 输出形式 | 自然语言答案(可附引用) | 自然语言 + 工具调用记录 + 最终答案 | 可执行代码(执行后返回数值/字符串) |
| 是否需要外部系统 | 向量数据库、文档存储 | 工具集(API、搜索引擎、数据库等) | 代码解释器(Python 沙箱) |
| 典型任务示例 | “公司今年的年假政策是什么?” | “帮我订周五北京到上海的机票,预算1500。” | “(1398 × 0.172) ÷ (5830 ÷ 12) + 4.2³ = ?” |
| 信息获取方式 | 静态检索(从固定知识库) | 动态交互(每次行动获取新信息) | 不需要外部信息,只需计算 |
| 是否改变模型参数 | 否(无需训练/微调) | 否(仅改变推理流程) | 否 |
| 可解释性 | 较高(可引用检索来源) | 最高(每一步思考/行动/观察都记录) | 高(代码逻辑可见) |
| 主要失败模式 | 检索到不相关内容 → 答非所问 | 死循环、无效行动、推理混乱 | 代码语法错误或逻辑错误 |
| 组合方式 | 可作为 ReAct 的一个行动(检索工具) | 可调用 RAG 作为行动,也可调用 PAL 作为行动 | 可作为 ReAct 的一个行动(计算工具) |
三个技术的本质区别(换个角度理解)
- RAG 解决 “知道什么” —— 扩充模型的知识边界,让它能回答训练数据之外的问题。
- ReAct 解决 “做些什么” —— 赋予模型使用外部工具和进行多步规划的能力。
- PAL 解决 “算得准” —— 把计算任务卸载给确定的执行环境,避免语言模型的本征缺陷。
这三个技术不是互斥的,而是从不同维度扩展大模型的能力。在实际应用中,它们经常被组合使用:
- ReAct 作为“大脑”:负责规划任务、决定下一步做什么。
- RAG 作为“长期记忆”:当需要外部知识时,ReAct 调用 RAG 检索。
- PAL 作为“计算器”:当需要精确计算时,ReAct 调用 PAL 生成代码。
一个典型的组合流程:
用户提问 → ReAct 思考“需要查资料” → Action 调用 RAG 检索 → 观察得到数字 → 思考“需要计算” → Action 调用 PAL 写代码 → 观察计算结果 → 思考“可以回答” → 输出最终答案。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)