[rStar] 搜索代理(MCTS/束搜索)

第2章:搜索代理(MCTS/束搜索)

欢迎回到rStar

在前一章中,我们学习了求解协调器,它就像是解决数学问题的项目经理。

它组织整个过程,但本身并不进行"思考",而是将这项工作委托给其专家团队。

今天,我们将认识这个团队中最重要的成员:搜索代理。它们是rStar的"思考者"或"策略家"。

什么是搜索代理?

想象我们在玩一个复杂的棋盘游戏,比如国际象棋。

我们不会随机选择一步棋;而是会前瞻思考。我们会考虑几种可能的走法,设想对手可能的应对,并尝试找到通往胜利的最佳路径。

rStar中的搜索代理正是做这样的事情,但针对的是数学问题

它们是"思考"并探索不同解决路径的核心算法。当面对复杂问题时,它们不会只尝试一种方法;而是构建一个潜在解决步骤的"树",探索各种想法,直到找到最佳方案。

rStar中,我们主要使用两种类型的搜索代理,每种都有其独特的策略:

  1. MCTS(蒙特卡洛树搜索):这个代理像一个策略性的棋盘游戏玩家,探索多种走法,从结果中学习,并专注于有希望的路径。
  2. 束搜索(Beam Search):这个代理像一个更简单的玩家,每一步都选择最好的几个走法,决策更直接。

让我们深入了解每一种代理,看看它们如何帮助rStar解决问题。

蒙特卡洛树搜索(MCTS)

将MCTS想象成一个非常好奇且策略性强的探索者。当面对数学问题时,它不会立即知道最佳路径,因此会尝试许多不同的路线。

以下是MCTS的简化工作流程:

  1. 探索(模拟):选择一条路径进行探索,尝试新的步骤。这就像在决策树中探索一个新的分支。
  2. 评估(推演)一旦到达一个"叶子"(潜在的终点或有趣的点),它会快速模拟问题的其余部分,猜测该路径可能有多好。这就像在脑海中快速推演游戏的剩余部分。
  3. 学习(反向传播:然后更新关于该路径所有步骤的知识。如果路径导致好的结果,这些步骤会得到更高的分数;如果导致坏的结果,则分数较低。
  4. 决策(选择)基于所有探索和学习,决定哪条路径最有希望进一步探索。它平衡尝试新事物(探索)和专注于之前表现良好的路径(利用)。

经过多次迭代,MCTS变得非常擅长识别解决数学问题最有希望的步骤序列。

rStar工作流中的MCTS

rStar中,MCTS代理从策略与奖励大语言模型获取想法,并构建一个复杂的搜索树。求解协调器通过探索和学习的循环指导它。

以下是MCTS一次"推演"或"迭代"的简化视图:

在这里插入图片描述

这个循环使MCTS能够逐步构建一个更健壮的搜索树,别更好的解决路径

树中的每个"节点"代表一个解决方案节点——通向答案的部分步骤。

束搜索(Beam Search)

现在,让我们看看束搜索。如果MCTS是一个策略性的深度思考者,束搜索更像是一个务实的=="当下最佳"决策者==。

以下是束搜索的工作方式:

  1. 生成想法:在问题的每一步,请求一组可能的下一步。
  2. 评估想法:评估所有这些可能的下一步。
  3. 选择最佳几个:不是探索所有路径,而是只保留N个最佳路径(N称为"束宽度")。立即丢弃其他不太有希望的路径。
  4. 重复:继续这个过程,始终只扩展前N个路径,逐步推进,直到找到解决方案或达到最大步数。

束搜索比MCTS更快,因为它不进行深度探索或复杂学习。它是一种"贪心"方法,始终尝试选择当前可用的最佳选项。

rStar工作流中的束搜索

rStar中的束搜索代理也使用策略与奖励大语言模型获取想法并评估它们。关键区别在于它如何处理这些评估以决定保留哪些路径。

MCTS与束搜索:快速比较

MCTS和束搜索都是强大的搜索代理,但在不同场景下表现优异:

特性蒙特卡洛树搜索(MCTS)束搜索
策略探索多条路径,学习,平衡探索/利用。贪心地选择每一步的最佳几个选项。
探索性——寻找新路径并从结果中学习。——专注于扩展已知的良好路径。
复杂性更复杂,涉及模拟和树更新。更简单,每一步评估和剪枝。
适用场景需要深度策略推理的问题;不确定性较高。良好的局部决策能导向良好全局结果的问题。
资源消耗通常需要更多计算和内存,因为树更深。通常更高效,但可能错过最优解

在这里插入图片描述

如何在rStar中使用搜索代理

我们不会直接"调用"MCTS或束搜索代理。相反,我们通过配置告诉求解协调器使用哪种类型的代理。协调器会为我们初始化和管理这些代理。

以下是如何在rStar中通过配置文件(如config/sample_mcts.yamlconfig/sft_eval_bs.yaml)指定代理类型:

# 来自config/sample_mcts.yaml
mode: "mcts"          # 这行告诉rStar使用MCTS!
# ... 其他MCTS特定设置,如'iterations'和'c_puct'
# 来自config/sft_eval_bs.yaml
mode: "bs"            # 这行告诉rStar使用束搜索!
# ... 其他束搜索特定设置,如'step_beam_width'

以下是求解协调器(来自第1章)如何根据我们的config创建和使用这些代理的概念性代码:

# 概念性Python代码,简化自main.py和solver.pyfrom rstar_deepthink.agents import MCTS, BS
from rstar_deepthink.solver import Solver
from omegaconf import OmegaConf # 用于加载配置文件# 1. 加载所需的配置
#    (例如,MCTS或束搜索的配置)
config = OmegaConf.load("config/sft_sample_mcts.yaml") # 或"config/sft_eval_bs.yaml"# 2. 初始化求解协调器
solver = Solver(config=config)# 3. 准备问题数据(例如,数学问题列表)
cur_data = [{"question": "2+2等于多少?", "answer": "4"}]# 4. 求解协调器根据配置中的'mode'创建代理
agents = []
for q in cur_data:if config.mode == "mcts":agents.append(MCTS(config=config, question=q['question'], ground_truth=q['answer']))elif config.mode == "bs":agents.append(BS(config=config, question=q['question'], ground_truth=q['answer']))else:raise ValueError("不支持的搜索模式配置!")# 5. 求解协调器指示这些代理解决问题
print(f"使用{config.mode}代理解决问题...")
solutions = solver.solve(agents, "results.jsonl", cur_data)print("找到解决方案!")
# 输出可能如下:
# 使用mcts代理解决问题...
# 推演处理: 100%|██████████| 48/48 [00:0X<00:00, X.X 推演/s]
# 找到解决方案!

在这个例子中,只需在配置文件中更改mode(并确保为该模式提供正确的设置),就可以切换rStar的核心问题解决策略

搜索代理内部:代码窥探

让我们快速看看这些代理在rStar代码库中是如何定义的。

rStar中的所有搜索代理都继承自一个共同的BaseTree类,该类提供了构建和导航解决方案树的共享功能。

# 来自rstar_deepthink/agents/__init__.py
# 此文件列出所有可用的代理类型
from .tree import BaseTree
from .beam_search import BS
from .mcts import MCTS__all__ = ['BaseTree','BS', # 我们的束搜索代理'MCTS', # 我们的MCTS代理
]

这告诉我们BSMCTS是主要的代理类。

BaseTree基础

BaseTree类(在rstar_deepthink/agents/tree.py中)为所有代理设置了通用结构。它保存问题questionconfig,以及最重要的,解决方案树的root节点。

# 来自rstar_deepthink/agents/tree.py(简化)class BaseTree(BaseModel):config: Anyquestion: strroot: Optional[Type[BaseNode]] = None # 解决方案树的起点current_node: Optional[Type[BaseNode]] = None # 当前在树中的位置def __init__(self, **kwargs) -> None:super().__init__(**kwargs)self.root = self.create_root() # 创建第一个节点self.current_node = self.rootdef create_root(self) -> Type[BaseNode]:# 此方法为问题创建第一个节点root = self.create_node()root.state["extra_info"] = f"question: {self.question}"return root@abstractmethoddef create_node(self, parent: Optional[Type[BaseNode]] = None) -> Type[BaseNode]:# 每个特定代理(MCTS,束搜索)将定义自己的节点类型passdef collect_partial_solution(self, node: Type[BaseNode]) -> str:# 帮助从节点回溯到根节点收集步骤trajectory = []while node:if node.state['text']:trajectory.append(node.state['text'])node = node.parentreturn "".join(reversed(trajectory))# ... 其他通用方法

每个代理通过create_root()创建一个root节点。create_node方法留空(@abstractmethod),因为每个代理将使用稍微不同类型的解决方案节点来存储其独特信息。collect_partial_solution方法对于重建迄今为止采取的步骤很有用。

束搜索(BS)实现

BS类(在rstar_deepthink/agents/beam_search.py中)实现了束搜索逻辑。其核心思想是维护一个current_top_num(我们的束宽度)的最佳路径。

# 来自rstar_deepthink/agents/beam_search.py(简化)from rstar_deepthink.nodes.base_node import BaseNode # 束搜索使用基本节点class BS(BaseTree):current_top_num: int = 1 # 这是束宽度(config.step_beam_width)current_nodes: List[Type[BaseNode]] = [] # 当前正在探索的节点candidate_nodes: List[Type[BaseNode]] = [] # 所有新生成的子节点def __init__(self, **kwargs) -> None:super().__init__(**kwargs)self.candidate_nodes.append(self.current_node) # 从根节点开始self.current_top_num = self.config.step_beam_width # 从配置设置束宽度def create_node(self, parent: Optional[Type[BaseNode]] = None) -> Type[BaseNode]:# 束搜索使用标准BaseNode作为其解决步骤return BaseNode(parent=parent, additional_state_keys=self.NODE_KEYS)def select_next_step(self, outputs=None, from_root=False) -> None:# 生成想法并获取值后,选择最佳的几个if outputs is not None:for candidate_node, output in zip(self.candidate_nodes, outputs):# 根据奖励模型输出更新节点值candidate_node.value = output.value_estimate if output.value_estimate is not None else 0# 按值(它们有多好)对所有候选节点排序self.candidate_nodes = sorted(self.candidate_nodes, key=lambda x: x.value, reverse=True)# 仅保留前'current_top_num'(束宽度)节点self.current_nodes = self.candidate_nodes[:self.current_top_num]# ... 也处理终端节点def generate_next_step(self, outputs: List[RequestOutput]) -> None:self.candidate_nodes = []for current_node, output in zip(self.current_nodes, outputs):self.current_node = current_node # 设置当前上下文# 为每个当前路径生成多个子步骤(来自LLM的想法)for idx, output in enumerate(output.outputs):step_result, parser_result = self.step_unwrap(output.text + output.stop_reason)self.create_child(step_result, parser_result, current_node)self.candidate_nodes.extend(current_node.children) # 将所有新子节点添加为候选

select_next_step方法是束搜索的关键:它获取所有新想法(子节点),获取它们的分数(值),排序它们,并仅保留step_beam_width个最佳节点。generate_next_step是代理向策略与奖励大语言模型请求多个下一步想法的地方,针对其当前最佳路径。

蒙特卡洛树搜索(MCTS)实现

MCTS类(在rstar_deepthink/agents/mcts.py中)更复杂,因为其探索-利用策略。它使用特殊的MCTSNode来跟踪访问次数和Q值。

# 来自rstar_deepthink/agents/mcts.py(简化)from rstar_deepthink.nodes import MCTSNode # MCTS使用特殊的MCTS节点
from .beam_search import BS # MCTS继承自束搜索,复用一些逻辑class MCTS(BS): # MCTS扩展束搜索,复用一些逻辑search_node: Type[MCTSNode] = None # 当前正在探索的特定节点def create_node(self, parent: Optional[Type[MCTSNode]] = None) -> Type[MCTSNode]:# MCTS使用MCTSNode,它跟踪访问次数和分数以进行决策return MCTSNode(parent=parent, additional_state_keys=self.NODE_KEYS, c_puct=self.config.c_puct)def selection(self, from_root=False) -> Optional[Type[MCTSNode]]:# 核心MCTS"选择"步骤:选择一个节点进行探索node = self.root if from_root else self.search_node# 此方法使用MCTSNode的PUCT值(利用和探索的平衡)# 来决定哪个子节点最有希望深入探索# ...(基于PUCT值选择最佳子节点的复杂逻辑)...return node # 返回选择的节点以进一步探索def expand_node(self, outputs: List[CompletionOutput], node: Type[MCTSNode]) -> None:# 核心MCTS"扩展"步骤:从LLM想法创建新的子节点for idx, output in enumerate(outputs):step_result, parser_result = self.step_unwrap(output.text + output.stop_reason)self.create_child(step_result, parser_result, node, idx)def eval_final_answer(self, node: Type[MCTSNode]) -> None:# 到达终端状态(或评估潜在答案)后,# 此方法将奖励"反向传播"到所有父节点if node.state["final_answer"] in [NO_VALID_CHILD, TOO_MANY_STEPS, TOO_MANY_CODE_ERRORS]:node.update(self.config.negative_reward) # 分配惩罚return# ... 检查答案是否正确并递归更新节点的逻辑# 这是MCTS学习的"反向传播"步骤,所有祖先节点都从这个结果中学习node.update_recursive(value_estimate, self.root)

selection方法是MCTS决定下一步探索哪条路径的地方,使用c_puct参数平衡已知信息(利用)和尝试新事物(探索)。expand_node从策略与奖励大语言模型提供的想法创建新的子节点。最后,eval_final_answer(包括"反向传播"步骤)对MCTS的学习至关重要;它更新导致特定结果的所有节点的分数和访问次数。

结论

现在我们已经认识了搜索代理——rStar背后的智能"思考者", 我们学习了:

  • 什么是搜索代理,以及它们如何构建潜在解决步骤的树。
  • MCTS,策略性探索者,学习并专注于有希望的路径
  • 束搜索,务实的决策者,总是选择最佳的几个选项
  • 如何配置rStar使用MCTS或束搜索。
  • 使这些代理工作的核心代码的简要介绍

这些代理之所以强大,是因为它们不只是猜测;而是系统地探索、评估和学习不同的解决路径。然而,它们严重依赖"专家"来提供好的想法和准确的评估

在下一章中,我们将探索这些"专家":策略与奖励大语言模型,它们是负责生成创造性步骤并评估其质量的大语言模型。

下一章:策略与奖励大语言模型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/96475.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/96475.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Electron 核心模块速查表

为了更全面地覆盖常用 API&#xff0c;以下表格补充了更多实用方法和场景化示例&#xff0c;同时保持格式清晰易读。 一、主进程模块 模块名核心用途关键用法 示例注意事项app应用生命周期管理• 退出应用&#xff1a;app.quit()• 重启应用&#xff1a;app.relaunch() 后需…

Qt C++ 图形绘制完全指南:从基础到进阶实战

Qt C 图形绘制完全指南&#xff1a;从基础到进阶实战 前言 Qt框架提供了强大的2D图形绘制能力&#xff0c;通过QPainter类及其相关组件&#xff0c;开发者可以轻松实现各种复杂的图形绘制需求。本文将系统介绍Qt图形绘制的核心技术&#xff0c;并通过实例代码演示各种绘制技巧…

二分搜索边界问题

在使用二分搜索的时候&#xff0c;更新条件不总是相同&#xff0c;虽然说使用bS目的就是为了target&#xff0c;但也有如下几种情况&#xff1a;求第一个target的索引求第一个>target的索引求第一个>target的索引求最后一个target的索引求最后一个<target的索引求最后…

【springboot+vue3】博客论坛管理系统(源码+文档+调试+基础修改+答疑)

目录 一、整体目录&#xff1a; 项目包含源码、调试、修改教程、调试教程、讲解视频、开发文档&#xff08;项目摘要、前言、技术介绍、可行性分析、流程图、结构图、ER属性图、数据库表结构信息、功能介绍、测试致谢等约1万字&#xff09; 二、运行截图 三、代码部分&…

20250907_梳理异地备份每日自动巡检Python脚本逻辑流程+安装Python+PyCharm+配置自动运行

一、逻辑流程(autocheckbackup.py在做什么) 1.连接Linux服务器 用 paramiko 登录你配置的 Linux 服务器(10.1.3.15, 10.1.3.26),进入指定目录(如 /home, /backup/mes),递归列出文件。 采集到的信息:服务器IP、目录、数据库名称、文件名、大小、修改时间。 2.连接Wind…

terraform-state详解

一、Treeaform-state的作用 Terraform-state是指Terroform的状态&#xff0c;是terraform不可缺少的生命周期元素。本质上来讲&#xff0c;terraform状态是你的基础设施配置的元数据存储库&#xff0c;terraform会把它管理的资源状态保存在一个状态文件里。 默认情况下&#xf…

四、kubernetes 1.29 之 Pod 生命周期

一、概述当容器与 pause 容器共享网络&#xff08;Network&#xff09;、IPC&#xff08;进程间通信&#xff09;和 PID&#xff08;进程命名空间&#xff09;后&#xff0c;二者形成了一种紧密的 "共享命名空间" 关系&#xff0c;共同构成了 Kubernetes 中 "Po…

AI与环保:礼貌用语背后的能源挑战与解决方案

程序员的技术管理推荐阅读 窄化效应&#xff1a;程序员与管理者的隐形情绪陷阱 从“激励”到“保健”&#xff1a;80后与90后程序员&#xff0c;到底想要什么&#xff1f; 从“激励”到“保健”&#xff1a;80后与90后程序员&#xff0c;到底想要什么&#xff1f; 场景引入&…

OpenCV C++ 特征提取:从角点检测到对象识别

特征提取是计算机视觉的核心技术,通过识别图像中具有代表性的关键点及其描述信息,实现图像匹配、对象识别、姿态估计等高级任务。本章将系统讲解从基础的图像金字塔、角点检测,到复杂的 ORB 和 SIFT 特征提取与匹配,最终实现基于特征的对象检测完整流程。 一、图像金字塔 …

Codeforces Round 1049 (Div. 2) D题题解记录

大致题意&#xff1a;给定nnn个区间(li,ri)(l_i,r_i)(li​,ri​)。每次选取两个尚未被标记的区间(l1,r1)(l_1,r_1)(l1​,r1​)与(l2,r2)(l_2,r_2)(l2​,r2​)&#xff0c;使得他们均被标记&#xff0c;同时可以任选x∈[l1,r1]&#xff0c;y∈[l2,r2]x\in[l_1,r_1]&#xff0c;y…

《WINDOWS 环境下32位汇编语言程序设计》第15章 注册表和INI文件

15.1 注册表和INI文件简介在一个操作系统中&#xff0c;无论是操作系统本身还是运行于其中的大部分应用程序&#xff0c;都需要使用某种方式保存配置信息。在DOS系统中&#xff0c;配置信息往往是软件的开发者根据自己的喜好用各种途径加以保存的&#xff0c;比如在磁盘上面写一…

JDK 17、OpenJDK 17、Oracle JDK 17 的说明

Java生态系统的核心概念&#xff1a;简单来说&#xff1a;JDK 17 是一个标准规范&#xff0c;定义了Java开发工具包第17个长期支持版应该包含什么功能。openjdk-17-jdk 是一个具体的实现&#xff0c;是遵循上述规范、由OpenJDK社区提供的开源软件包。下面我们通过一个表格和详细…

手写MyBatis第58弹:如何优雅输出可执行的SQL语句--深入理解MyBatis日志机制:

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

Spring Boot 监控实战:集成 Prometheus 与 Grafana,打造全方位监控体系

前言 在当今微服务架构盛行的时代&#xff0c;应用程序的监控变得尤为重要。Spring Boot 作为广泛使用的微服务框架&#xff0c;其监控需求也日益增加。Prometheus 和 Grafana 作为开源监控领域的佼佼者&#xff0c;为 Spring Boot 应用提供了强大的监控能力。本文将详细介绍如…

JS中的多线程——Web Worker

众所周知&#xff0c;JavaScript 是单线程运行的&#xff08;至于为什么是单线程可以看一下这篇文章——事件循环机制&#xff09;&#xff0c;当浏览器主线程被大量计算任务阻塞时&#xff0c;页面就会出现明显的卡顿现象。Web Worker 提供了在独立线程中运行 JavaScript 的能…

【SQL注入】延时盲注

sleep(n)​​: 核心延时函数。使数据库程序暂停 n秒。​​if(condition, true_expr, false_expr)​​: 条件判断函数。如果 condition为真&#xff0c;执行 true_expr&#xff0c;否则执行 false_expr。​​用于将延时与判断条件绑定​​。​​mid(a, b, c)​​: 字符串截取函数…

IntelliJ IDEA 2025.1 Java Stream Debugger 快速使用指南

1. 功能概览 Java Stream Debugger 提供 Trace Current Stream Chain 功能&#xff0c;用来在调试时分析和可视化 Stream 操作链。 主要用途&#xff1a; 在运行时查看流操作链的每一步输出找出 map/filter 等操作的问题避免手动加 peek() 打印调试2. 使用入口 在 IDEA 2025.1 …

ARM-指令集全解析:从基础到高阶应用

一、ARM 指令集体系结构版本ARM 公司定义了多个指令集版本&#xff1a;ARMv1&#xff1a;原型机 ARM1&#xff0c;没有用于商业产品。ARMv2&#xff1a;扩展 V1&#xff0c;包含 32 位乘法指令和协处理器指令。ARMv3&#xff1a;第一个微处理器 ARM6 核心&#xff0c;支持 Cach…

第3讲 机器学习入门指南

近年来&#xff0c;随着企业和个人生成的数据量呈指数级增长&#xff0c;机器学习已成为日益重要的技术领域。从自动驾驶汽车到流媒体平台的个性化推荐&#xff0c;机器学习算法已广泛应用于各个场景。让我们深入解析机器学习的核心要义。3.1 机器学习定义机器学习是人工智能的…

深入理解跳表:多层索引加速查找的经典实现

跳表&#xff08;Skip List&#xff09;是一种多层有序链表结构&#xff0c;通过引入多级索引加速查找&#xff0c;其核心设计类似于“立体高速公路系统”&#xff0c;底层是原始链表&#xff0c;上面有各种高度的"高架桥"。 高层道路跨度大&#xff0c;连接远方节点…