1
00:00:00,100 --> 00:00:02,105
你好，欢迎收听。

2
00:00:02,105 --> 00:00:06,201
上一集我们讲了 ReAct，那个边想边做的循环。

3
00:00:06,201 --> 00:00:13,004
这一集讲两种跟它风格很不一样的范式，一个讲究先谋后动，一个讲究事后复盘。

4
00:00:13,004 --> 00:00:22,391
本内容改编自 Datawhale《Hello-Agents：从零开始构建智能体》，采用 CC BY-NC-SA 4.0 授权，为二次演绎配音版。

5
00:00:22,391 --> 00:00:31,250
授权再说一遍，本内容改编自 Datawhale《Hello-Agents》，采用 CC BY-NC-SA 4.0 授权，为二次演绎配音版。

6
00:00:31,250 --> 00:00:34,519
为什么讲完互相补充的三种还不够。

7
00:00:34,519 --> 00:00:42,247
因为 ReAct 有个天然短板，它是走一步看一步的，遇到需要长远规划的复杂任务容易在半路迷失。

8
00:00:42,247 --> 00:00:46,310
而再好的方案，第一次写出来也常常有漏洞。

9
00:00:46,310 --> 00:00:51,262
这一集的两个范式，一个解决规划，一个解决自我纠错。

10
00:00:51,262 --> 00:00:52,872
我们开始。

11
00:00:53,020 --> 00:00:58,931
先说第一种，它把任务处理明确分成两个阶段，先规划，后执行。

12
00:00:58,931 --> 00:01:00,167
打个比方。

13
00:01:00,167 --> 00:01:15,628
如果说 ReAct 像一个经验丰富的侦探，根据现场的蛛丝马迹一步步推理，随时调整调查方向；那么这种范式更像一位建筑师，在动工之前必须先画出完整的蓝图，然后严格按照蓝图施工。

14
00:01:15,628 --> 00:01:21,770
现在我们常用的很多大模型工具的智能体模式，其实都融入了这种设计。

15
00:01:21,770 --> 00:01:30,351
它是二零二三年提出的，核心动机是为了解决思维链在处理多步骤、复杂问题时容易偏离轨道的问题。

16
00:01:30,351 --> 00:01:36,157
你让模型一路推下去，推到第五步它可能已经忘了第一步要干什么了。

17
00:01:36,157 --> 00:01:38,993
它把整个流程解耦成两个阶段。

18
00:01:38,993 --> 00:01:41,000
第一个是规划阶段。

19
00:01:41,000 --> 00:01:51,926
智能体接收用户的完整问题，它的第一个任务不是直接解题或者调用工具，而是把问题分解，制定出一个清晰、分步骤的行动计划。

20
00:01:51,926 --> 00:01:56,373
请注意，这个计划本身就是一次模型调用的产物。

21
00:01:56,373 --> 00:01:58,380
第二个是执行阶段。

22
00:01:58,380 --> 00:02:05,111
拿到完整计划之后，智能体进入执行，严格按照计划里的步骤逐一执行。

23
00:02:05,111 --> 00:02:15,544
每一步的执行可能是一次独立的模型调用，也可能是对上一步结果的加工处理，直到计划中的所有步骤都完成，最终得出答案。

24
00:02:15,544 --> 00:02:33,672
形式化一点说，先由规划模型根据原始问题生成一个包含若干步骤的计划；随后在执行阶段，执行模型逐一完成计划中的步骤，而每一步的生成都同时依赖原始问题、完整计划，以及之前所有步骤的执行结果。

25
00:02:33,672 --> 00:02:37,170
最后的答案就是最后一个步骤的结果。

26
00:02:37,170 --> 00:02:47,543
这种先谋后动的策略，让智能体在处理需要长远规划的复杂任务时能保持更高的目标一致性，避免在中间步骤里迷失方向。

27
00:02:47,543 --> 00:03:07,258
它尤其适合结构性强、可以被清晰分解的任务，比如多步数学应用题，要先列出计算步骤再逐一求解；需要整合多个信息源的报告撰写，要先规划好结构再逐一填充内容；还有代码生成，要先构思好函数、类和模块的结构，再逐一实现。

28
00:03:07,396 --> 00:03:14,545
我们用一个不依赖工具、纯靠提示词设计的推理任务，来凸显它在结构化推理上的优势。

29
00:03:14,545 --> 00:03:21,214
规划阶段的目标是让模型接收原始问题，输出一个清晰、分步骤的行动计划。

30
00:03:21,214 --> 00:03:26,719
这个计划必须是结构化的，好让代码能轻松解析并逐一执行。

31
00:03:26,719 --> 00:03:37,584
所以设计的提示词要明确告诉模型它的角色和任务，并给出输出格式的范例，比如一个列表，里面依次是第一步、第二步、第三步。

32
00:03:37,584 --> 00:03:42,235
这个提示词通过三点确保输出的质量和稳定性。

33
00:03:42,235 --> 00:03:48,774
第一是角色设定，比如告诉它你是顶级的规划专家，用角色激发模型的专业能力。

34
00:03:48,774 --> 00:03:54,026
第二是任务描述，清晰地定义「分解问题」这个目标，不要含糊。

35
00:03:54,026 --> 00:03:59,507
第三是格式约束，强制要求输出为一个结构化的列表字符串。

36
00:03:59,507 --> 00:04:05,589
这一点极大简化了后续代码的解析工作，比解析自然语言稳定可靠得多。

37
00:04:05,589 --> 00:04:12,632
很多人做规划阶段翻车，翻在没约束格式上，模型给你一整段话，你还得想办法切开。

38
00:04:12,632 --> 00:04:19,363
接下来把这段提示词逻辑封装成一个规划器类，它唯一的任务就是出计划。

39
00:04:19,516 --> 00:04:24,922
规划器画完蓝图，就需要执行器来逐一完成计划里的任务。

40
00:04:24,922 --> 00:04:32,156
执行器不只是调用模型解决每个子问题，它还承担一个至关重要的角色，状态管理。

41
00:04:32,156 --> 00:04:41,916
它必须记录每一步的执行结果，并把这些结果作为上下文提供给后续步骤，确保信息在整个任务链条里顺畅流动。

42
00:04:41,916 --> 00:04:45,221
执行器的提示词跟规划器不一样。

43
00:04:45,221 --> 00:04:52,024
它的目标不是分解问题，而是在已有上下文的基础上，专注解决当前这一个步骤。

44
00:04:52,024 --> 00:04:55,954
所以它的提示词需要包含四个关键信息。

45
00:04:55,954 --> 00:05:00,533
第一，原始问题，确保模型始终了解最终目标。

46
00:05:00,533 --> 00:05:07,036
第二，完整计划，让模型知道当前步骤在整个任务里处在什么位置。

47
00:05:07,036 --> 00:05:14,464
第三，历史步骤与结果，提供到目前为止已经完成的工作，作为当前步骤的直接输入。

48
00:05:14,464 --> 00:05:20,004
第四，当前步骤，明确指示模型现在要解决哪一个具体任务。

49
00:05:20,004 --> 00:05:21,976
少了哪一项都不行。

50
00:05:21,976 --> 00:05:34,608
没有原始问题，模型会跑偏；没有完整计划，它不知道还剩多少；没有历史结果，算到第三步就接不上第二步的数；没有当前步骤，它不知道这轮该干嘛。

51
00:05:34,608 --> 00:05:42,312
把执行逻辑封装成执行器类，它循环遍历计划，逐步调用模型，并维护一份历史记录。

52
00:05:42,312 --> 00:05:52,637
最后再把规划器和执行器整合到一个统一的智能体里，这个类本身不包含复杂逻辑，只是作为协调者依次调用内部组件。

53
00:05:52,637 --> 00:06:00,257
这体现了组合优于继承的原则，改规划就动规划器，改执行就动执行器，彼此不打架。

54
00:06:00,412 --> 00:06:14,811
我们看一个真实运行，目标问题是这样，一个水果店周一卖出了十五个苹果，周二卖出的数量是周一的两倍，周三卖出的数量比周二少了五个，请问这三天总共卖出了多少个苹果。

55
00:06:14,811 --> 00:06:22,659
这个问题对模型来说不算难，但它包含一条清晰的逻辑链条，正好用来观察范式怎么工作。

56
00:06:22,659 --> 00:06:29,991
规划阶段，智能体调用规划器，把这个应用题分解成一个包含四个逻辑步骤的列表。

57
00:06:29,991 --> 00:06:41,746
第一步算出周一的十五个，第二步用周一乘以二算出周二的三十个，第三步用周二减五算出周三的二十五个，第四步把三天加起来算出总数七十个。

58
00:06:41,746 --> 00:06:45,556
这个结构化的计划为后续执行打下了基础。

59
00:06:45,556 --> 00:06:50,868
执行阶段，执行器严格按照生成的计划一步一步往下走。

60
00:06:50,868 --> 00:06:55,976
每一步都把历史结果作为上下文，确保信息正确传递。

61
00:06:55,976 --> 00:07:03,176
第二步正确使用了第一步的十五个，第三步也正确使用了第二步的三十个，最后得出七十个。

62
00:07:03,176 --> 00:07:07,671
整个过程逻辑清晰、步骤明确，中间没有跑偏。

63
00:07:07,671 --> 00:07:16,902
对比一下，如果直接让模型一路心算到底，中间某一步算错的概率要高得多，而且错了你也看不出错在哪一步。

64
00:07:16,902 --> 00:07:22,587
拆成显式步骤之后，每一步都可验证，出了问题能立刻定位。

65
00:07:22,732 --> 00:07:25,037
好，讲第二种范式。

66
00:07:25,037 --> 00:07:30,732
在前面两种范式里，智能体一旦完成任务，工作流程就结束了。

67
00:07:30,732 --> 00:07:38,641
但它们生成的初始答案，不管是行动轨迹还是最终结果，都可能存在谬误或者有待改进的地方。

68
00:07:38,641 --> 00:07:49,446
反思机制的核心思想，就是给智能体引入一个事后的自我校正循环，让它能像人类一样审视自己的工作，发现不足，迭代优化。

69
00:07:49,446 --> 00:07:56,333
这个机制的灵感来自人类的学习过程，我们写完初稿会校对，解完数学题会验算。

70
00:07:56,333 --> 00:08:05,107
它二零二三年被系统性地提出，核心流程可以概括成一个简洁的三步循环，执行、反思、优化。

71
00:08:05,107 --> 00:08:06,766
第一步是执行。

72
00:08:06,766 --> 00:08:16,394
智能体用我们熟悉的方法，比如前面讲的两种范式，尝试完成任务，生成一个初步的解决方案或者行动轨迹。

73
00:08:16,394 --> 00:08:18,521
这可以看成是初稿。

74
00:08:18,521 --> 00:08:20,312
第二步是反思。

75
00:08:20,312 --> 00:08:29,014
智能体进入反思阶段，它会调用一个独立的、或者带有特殊提示词的模型实例，来扮演评审员的角色。

76
00:08:29,014 --> 00:08:34,110
这个评审员会审视刚才那份初稿，并从多个维度评估。

77
00:08:34,110 --> 00:08:39,362
有没有事实性错误，有没有跟常识或者已知事实相悖的内容。

78
00:08:39,362 --> 00:08:44,278
有没有逻辑漏洞，推理过程有没有不连贯或者矛盾的地方。

79
00:08:44,278 --> 00:08:49,086
有没有效率问题，是不是存在更直接、更简洁的路径。

80
00:08:49,086 --> 00:08:53,485
有没有遗漏信息，是不是忽略了问题里某些关键约束。

81
00:08:53,485 --> 00:08:59,687
根据评估，它会生成一段结构化的反馈，指出具体问题和改进建议。

82
00:08:59,687 --> 00:09:01,550
第三步是优化。

83
00:09:01,550 --> 00:09:10,817
智能体把初稿和反馈作为新的上下文，再次调用模型，让它根据反馈修正初稿，生成一个更完善的修订稿。

84
00:09:10,817 --> 00:09:18,076
这个循环可以重复多次，直到反思阶段不再发现新问题，或者达到预设的迭代次数上限。

85
00:09:18,076 --> 00:09:21,982
跟前两种范式相比，反思的价值有三条。

86
00:09:21,982 --> 00:09:30,480
第一，它提供了内部纠错回路，不再完全依赖外部工具的反馈，因此能修正更高层次的逻辑和策略错误。

87
00:09:30,480 --> 00:09:37,704
第二，它把一次性执行变成了持续优化，显著提升复杂任务的成功率和答案质量。

88
00:09:37,704 --> 00:09:46,970
第三，它为智能体构建了短期的记忆，整条执行、反思、优化的轨迹本身就是一份宝贵的经验记录。

89
00:09:47,116 --> 00:09:52,029
要做反思，就得先能记住之前的尝试和得到的反馈。

90
00:09:52,029 --> 00:09:59,888
所以一个短期记忆模块是这个范式的必需品，它负责存储每一次执行与反思循环的完整轨迹。

91
00:09:59,888 --> 00:10:02,016
这个类设计得很简洁。

92
00:10:02,016 --> 00:10:06,174
用一个列表按顺序存储每一次的行动和反思。

93
00:10:06,174 --> 00:10:09,684
提供一个添加记录的方法负责往里写。

94
00:10:09,684 --> 00:10:21,354
核心是一个获取轨迹的方法，它把记忆里的内容序列化成一段文本，可以直接插进后续的提示词里，为模型反思和优化提供完整上下文。

95
00:10:21,354 --> 00:10:27,028
另外还有一个方便的方法，用来取出最新的那份初稿供反思使用。

96
00:10:27,028 --> 00:10:30,321
这里有个工程上的考量值得记一下。

97
00:10:30,321 --> 00:10:39,347
反思通常要存储和提取信息，如果上下文很长，想让评审员直接看到所有信息，往往会传入大量冗余。

98
00:10:39,347 --> 00:10:44,948
所以这个记忆模块不只是存取，它还决定了你给评审员看什么。

99
00:10:44,948 --> 00:10:49,936
给太多，注意力被稀释；给太少，评审员看不出问题。

100
00:10:49,936 --> 00:10:53,854
有了记忆模块，就可以构建反思智能体了。

101
00:10:53,854 --> 00:11:00,585
跟前面的范式不同，反思机制需要多个不同角色的提示词协同工作，一共三种。

102
00:11:00,585 --> 00:11:10,249
第一种是初始执行提示词，这是智能体首次尝试解决问题的提示词，内容相对直接，只要求模型完成指定任务。

103
00:11:10,249 --> 00:11:14,479
第二种是反思提示词，这是整个机制的灵魂。

104
00:11:14,479 --> 00:11:23,770
它指示模型扮演代码评审员的角色，对上一轮生成的内容做批判性分析，并给出具体的、可操作的反馈。

105
00:11:23,770 --> 00:11:32,208
这里的关键是「极其严格」和「专注」，比如明确要求它专注算法效率，而不是泛泛地说请提出改进意见。

106
00:11:32,208 --> 00:11:41,186
第三种是优化提示词，当收到反馈之后，这个提示词引导模型根据反馈内容修正和优化原有产出。

107
00:11:41,332 --> 00:11:45,584
我们用一个代码生成的例子来看它实际怎么跑。

108
00:11:45,584 --> 00:11:50,414
目标任务是编写一个函数，找出一到 n 之间所有的素数。

109
00:11:50,414 --> 00:11:55,847
这个任务是检验反思机制的绝佳场景，因为它满足三个条件。

110
00:11:55,847 --> 00:12:03,383
第一，存在明确的优化路径，模型初次生成的代码很可能是个简单但效率低下的实现。

111
00:12:03,383 --> 00:12:10,727
第二，反思点清晰，可以通过反思发现时间复杂度过高或者存在重复计算的问题。

112
00:12:10,727 --> 00:12:16,436
第三，优化方向明确，可以根据反馈改成更高效的迭代版本。

113
00:12:16,436 --> 00:12:19,344
实际运行的演进过程是这样的。

114
00:12:19,344 --> 00:12:37,473
第一轮反思，由于反思提示词里明确要求极其严格并且专注算法效率，智能体没有满足于功能正确的初版代码，而是精准地指出了它 n 乘以根号 n 的时间复杂度瓶颈，并提出了算法层面的改进建议，用埃拉托斯特尼筛法重写。

115
00:12:37,473 --> 00:12:47,882
第一轮优化，智能体接到明确反馈后，成功实现了更高效的筛法，把复杂度降到了 n 乘以 log log n，完成了第一次有意义的自我迭代。

116
00:12:47,882 --> 00:13:03,343
第二轮反思，智能体面对已经高效的筛法，展现出了更深的知识，它不仅肯定了当前算法的效率，甚至提到分段筛法等更高级的优化方向，但最终做出了在一般情况下无需改进的正确判断。

117
00:13:03,343 --> 00:13:07,826
这个判断触发了终止条件，优化过程就此收敛。

118
00:13:07,826 --> 00:13:18,222
这个案例说明一件事，设计良好的反思机制，价值不只是修复错误，更在于驱动解决方案在质量和效率上实现阶梯式提升。

119
00:13:18,222 --> 00:13:24,965
注意最后那一步很关键，好的反思必须能判断「够好了」，否则会无限迭代下去。

120
00:13:25,108 --> 00:13:29,589
但这种能力不是免费的，我们做个成本收益分析。

121
00:13:29,589 --> 00:13:31,089
先看成本。

122
00:13:31,089 --> 00:13:41,534
第一，模型调用开销增加，每迭代一轮至少要额外调用两次模型，一次反思一次优化，多轮下来成本和算力消耗成倍增加。

123
00:13:41,534 --> 00:13:50,705
第二，任务延迟显著提高，它是串行过程，每一轮优化都得等上一轮反思完成，不适合实时性要求高的场景。

124
00:13:50,705 --> 00:14:04,190
第三，提示工程复杂度上升，它的成功很大程度上依赖高质量、有针对性的提示词，为执行、反思、优化三个阶段分别设计和调试提示词，要投入更多精力。

125
00:14:04,190 --> 00:14:05,633
再看收益。

126
00:14:05,633 --> 00:14:20,452
第一，解决方案质量的跃迁，它能把一个合格的初始方案迭代优化成优秀的最终方案，这种从功能正确到性能高效、从逻辑粗糙到逻辑严谨的提升，在关键任务里至关重要。

127
00:14:20,452 --> 00:14:30,224
第二，鲁棒性增强，通过内部自我纠错，能发现并修复初始方案里的逻辑漏洞、事实性错误或者边界情况处理不当。

128
00:14:30,224 --> 00:14:34,623
一句话概括，反思是典型的以成本换质量。

129
00:14:34,623 --> 00:14:49,130
它适合对最终质量、准确性、可靠性要求极高，而对实时性要求宽松的场景，比如生成关键业务代码或技术报告、科学研究里的复杂逻辑推演、需要深度分析的决策支持。

130
00:14:49,130 --> 00:14:56,510
反过来，如果要快速响应，或者大致正确就够了，用更轻量的那两种范式更划算。

131
00:14:56,510 --> 00:15:01,546
好，我们把这一集收一下，给你几条能直接带走的判断依据。

132
00:15:01,546 --> 00:15:09,659
第一，记住那个比方，ReAct 像侦探，走一步看一步；先规划后执行像建筑师，先出蓝图再施工。

133
00:15:09,659 --> 00:15:14,262
任务需要长远规划、结构清晰可分解，就选后者。

134
00:15:14,262 --> 00:15:20,645
第二，规划阶段的提示词抓住三点，角色设定、任务描述、格式约束。

135
00:15:20,645 --> 00:15:26,101
格式约束最容易被忽略，但它决定了你的代码能不能稳定解析。

136
00:15:26,101 --> 00:15:35,885
第三，执行器的关键是状态管理，它的提示词必须包含原始问题、完整计划、历史步骤与结果、当前步骤这四样。

137
00:15:35,885 --> 00:15:38,421
缺一样，信息链就断了。

138
00:15:38,421 --> 00:15:49,395
第四，反思是执行、反思、优化三步循环，它需要一个短期记忆模块存轨迹，需要执行、反思、优化三种角色提示词。

139
00:15:49,395 --> 00:15:55,548
评审员看什么由记忆模块决定，给太多会稀释注意力，给太少看不出问题。

140
00:15:55,548 --> 00:16:01,221
第五，也是最能指导选型的一条，先问你要的是速度还是质量。

141
00:16:01,221 --> 00:16:09,875
要速度、大致正确就够，用 ReAct 或先规划后执行；要质量、容错成本高、允许慢，才上反思。

142
00:16:09,875 --> 00:16:16,594
而且反思一定要有明确的终止条件，好反思的标志是能判断什么时候够好了。

143
00:16:16,594 --> 00:16:18,733
这一集我们就到这里。

144
00:16:18,733 --> 00:16:21,919
下一集我们继续讲下一个经典范式。

145
00:16:21,919 --> 00:16:24,911
感谢你的收听，我们下期见。
