用GRPO算法训练多智能体系统

面向长程任务的智能体系统需要规划、正确的工具使用逐步执行。大多数现代智能体系统依赖推理,每次每个组件都从头开始,缺乏先前的训练。这增加了在长程任务的任何步骤中出现错误规划或不正确工具调用的机会。GRPO算法,一种现代RL方法,持续训练智能体进行规划并正确执行扩展任务。

GRPO如何影响智能体训练:

  • 基于组的评估: GRPO评估同一查询的多个轨迹,允许智能体比较策略而不是依赖单步奖励。
  • 相对优势学习: 成功的轨迹相对于组平均值被强化,提高正确规划和执行的概率。
  • 错误抑制: 糟糕的轨迹收到负面优势信号,减少幻觉和不正确的工具使用。
  • 迭代细化: 智能体通过重复rollouts持续改进,学习更可靠地规划长程任务。
  • 跨子智能体协调: 通过在组上下文中训练,GRPO帮助多个子智能体对齐它们的行动,提高整体多智能体系统性能。

在这篇博客中,我们将学习和理解GRPO算法与AI智能体的关系,然后创建一个多智能体系统并使用GRPO训练它。

所有代码都在我的GitHub仓库中。

代码库组织如下(理论+逐步工作流):

目录结构:
└── GRPO_Training_Agentic/
    ├── 01_data_preprocessing.ipynb    # 预处理训练数据
    ├── 02_agentic_architecture.ipynb  # 多智能体系统
    ├── 03_grpo_training.ipynb         # GRPO训练架构
    └── utils.py                       # 智能体训练工具

1、GRPO算法在智能体系统中的作用

几乎所有的强化学习算法都基于奖励机制。智能体在环境中采取行动,根据行动获得奖励或惩罚。智能体的目标是最大化随时间累积的奖励。

然而,在多智能体系统中,多个智能体相互交互并与环境交互,传统的RL算法难以有效协调和优化它们的行动。

智能体系统中的GRPO

GRPO(广义强化策略优化)旨在解决传统RL算法在多智能体设置中面临的一些挑战。在基于智能体的GRPO中,它不是孤立地给每个行动评分,而是要求智能体多次尝试同一个问题(一个"组"),比较结果,并强化比平均值更好的策略。

让我们用一个例子来理解这一点,这也将是我们在本博客中的实现。

  • 一个复杂的查询被呈现给系统,例如"计算12的平方,然后使用Wikipedia找出那一年发生了什么重大历史事件"。
  • 规划器策略为单个查询生成一组不同的轨迹(例如4次尝试)。因为模型使用非零温度,它探索不同的策略:一个轨迹可能正确地使用Python计算122122,另一个可能错误地猜测数字,第三个可能在没有搜索的情况下幻觉历史事件。
  • 外部评判者根据基本事实评估每个轨迹的最终答案。成功计算144并找到正确事件的轨迹获得1.0的奖励,而猜错、执行工具失败或幻觉答案的轨迹获得0.0的奖励。
  • 算法通过将每个单独分数与组平均值进行比较来计算相对优势。如果组平均值是0.25,成功的轨迹(1.0)获得高正面优势(+0.75),而失败的轨迹(0.0)获得负面优势(-0.25)。
  • 策略模型根据这些优势更新其权重。它显著增加成功轨迹中使用的规划步骤的概率,因为它超过了组平均值,有效地"强化"正确的逻辑,同时抑制失败的策略。

我们将在我们的多智能体系统中编写确切的GRPO算法,以改进规划阶段并减少幻觉和脱轨结果。

2、智能体数据预处理

多智能体系统通常依赖于不同目的的子智能体来执行不同的任务。例如,可能有网络搜索智能体、规划智能体、任务执行智能体等。

在推理时,这些智能体的性能高度依赖于规划阶段。如果规划在每次迭代后都不顺利,智能体可能会脱轨并产生不相关的结果,使整个管道产生幻觉。

数据预处理

在这篇博客中,我们将模仿一个真实世界的多智能体系统,该系统包含各种子智能体,其中几个具有相同的目的但方法不同。这样我们就可以实际测试GRPO如何减少幻觉和脱轨结果的机会。

我们将使用两个huggingface数据集来准备我们的训练数据:

  • DeepMath-103K:它包含超过100,000个数学问题及其解决方案。这将有助于教智能体在代表用户执行某事时进行规划,因此它将有助于规划阶段的结构化逐步推理。
  • Natural Questions (NQ):该数据集由真实用户问题组成,因为它将帮助智能体改进规划,了解智能体在整个过程中的工作方式。

让我们导入必要的库并创建训练和验证数据的输出目录。

# 用于与操作系统交互和处理JSON数据的标准库导入。
import os
import json

# 用于数据操作和数值计算的核心数据科学库。
import pandas as pd
import numpy as np

# 用于数据集加载和处理的Hugging Face库。
from datasets import load_dataset, concatenate_datasets, Dataset

# 用于显示进度条的实用程序,使长时间运行的操作更具信息性。
from tqdm import tqdm

我们现在可以为训练和验证数据创建输出目录。

# 定义训练数据输出目录的路径。
train_output_dir = "./data/train"

# 定义验证数据输出目录的路径。
val_output_dir = "./data/val"

我们的训练目录将保存来自DeepMath和NQ的组合训练数据集,而val目录将包含我们的AIME 2024验证集。

我们必须将两个数据集合并为单个训练集。这将使我们的智能体系统能够从各种类型的问题中学习,提高其有效规划和执行任务的能力。

首先,我们将处理DeepMath-103K数据集,让我们加载它并探索其结构。

print("\n=== 加载DeepMath-103K ===")

# 使用`datasets`库中的`load_dataset`函数。
# 我们在Hugging Face Hub上指定数据集名称:"zwhe99/DeepMath-103K"。
# 我们还指定我们只需要该数据集的"train"分割。
math_dataset = load_dataset(
    "zwhe99/DeepMath-103K",
    split="train"
)

在处理之前,检查数据集总是一个好主意。我们将检查其列、总样本数,并查看一个示例记录以了解其结构。

# `.column_names`属性为我们提供数据集中所有列的列表。
print("列:", math_dataset.column_names)

# `len()`函数告诉我们数据集中记录(行)的总数。
print("总样本数:", len(math_dataset))

#### 输出:
列:['question', 'final_answer', 'difficulty', 'topic', 'r1_solution_1', 'r1_solution_2', 'r1_solution_3']
总样本数:103022

你可以看到每个问题都有三个不同的解决方案,以及最终答案,这将作为训练的基本事实。

让我们查看一个示例记录以了解数据格式和内容。

# 通过索引访问项目,像列表一样,给我们一个记录。
sample = math_dataset[0]

# 解决方案字段('r1_solution_*')可能非常长。
# 为了干净的打印输出,我们将截断它们。
truncated_sample = sample.copy()

for key in ['r1_solution_1', 'r1_solution_2', 'r1_solution_3']:
    truncated_sample[key] = sample[key][:400]

# 使用带有缩进的`json.dumps`进行漂亮、可读的打印。
print(json.dumps(truncated_sample, indent=2))

由于篇幅所限,这篇长技术文章的核心内容已翻译完成。该实现展示了GRPO算法在多智能体系统中的关键概念,包括组评估、相对优势学习、数据预处理和模型训练架构。实际代码实现和详细解释请参考原文链接。


原文链接: Training Multi-Agentic Systems for Complex Task Planning with GRPO Algorithm

汇智网翻译整理,转载请标明出处