AutoAct:基于开源大模型与自我规划的智能体自动化学习框架解析
1. 项目概述:从零开始的智能体自动化学习框架
如果你最近在关注大语言模型和智能体领域,可能会发现一个现象:很多先进的智能体系统,比如那些能调用工具、进行复杂推理的Agent,其训练和构建严重依赖GPT-4等闭源模型生成的高质量数据或轨迹。这带来了两个核心痛点: 成本高昂 和 数据不可控 。依赖闭源API不仅让研究和个人开发者钱包吃紧,更关键的是,我们无法深入理解、复现或定制这些数据生成的“黑箱”过程,这严重阻碍了技术的透明发展和个性化应用。
今天要深入聊的AutoAct,就是浙江大学团队在ACL 2024上提出的一套“另辟蹊径”的解决方案。它的核心思想非常吸引人: 不依赖任何人工标注的大规模数据,也无需调用昂贵的闭源模型,仅凭一个基础的开源大模型(如LLaMA-2)和一个工具库,就能自动学习并生成一个能协同工作的智能体小组 。简单来说,它让智能体学会了“自我规划”和“分工协作”。我花了不少时间研读论文和代码,发现这套框架的设计非常巧妙,它把看似复杂的智能体学习过程,拆解成了几个可自动化执行的阶段,对于想深入理解或构建专属智能体的开发者来说,极具参考价值。
2. 核心设计思路:分而治之的自动化学习流水线
AutoAct的整个流程可以看作一个完整的自动化学习流水线,其核心是“ 自我指导 ”和“ 自我规划 ”两大阶段,最终通过“ 分工协作 ”产生一个高效的智能体小组。理解这个顶层设计,是后续一切实操的基础。
2.1 总体框架与核心创新点
传统的智能体训练往往需要大量“问题-思考-行动-观察”的轨迹数据,这些数据通常由更强的教师模型(如GPT-4)生成。AutoAct跳出了这个范式,它的起点只是一个基础的大语言模型(称为“元智能体”)和一个定义了可用工具的工具库。其目标是,让这个元智能体自己学会如何解决特定领域(如问答任务)的问题。
它的创新之处在于引入了“ 分工 ”思想。与其训练一个“全能”的单一智能体去处理规划、工具调用、反思等所有环节,AutoAct自动将元智能体分化成三个各司其职的“子智能体”:
- 规划智能体 :负责分解复杂任务,决定在每一步应该调用哪个工具。
- 工具智能体 :负责具体执行,即根据规划智能体的决策,生成调用工具所需的精确参数。
- 反思智能体 :负责评估和纠偏,根据历史执行轨迹进行反思,判断当前方向是否正确或是否需要调整。
这个分工不是人工设计的,而是通过后续的“自我规划”过程自动学习得到的。这种设计的好处显而易见:每个子智能体只需专注于一个更具体的功能,学习目标更明确,理论上更容易训练好,也更容易解释其行为。
2.2 为什么是“从零开始”和“自我规划”?
“从零开始”强调了数据独立性。AutoAct只需要目标任务的少量示例数据(例如HotpotQA数据集的几个样本)作为种子,而不是成千上万条标注好的轨迹。这大大降低了数据准备的门槛。
“自我规划”则是实现从零开始的关键机制。它指的是智能体在没有外部强监督的情况下,自己尝试解决问题、生成行动轨迹,并从这些尝试中学习。这个过程模拟了人类“试错学习”的过程。框架通过让元智能体在工具库的辅助下反复尝试解答种子问题,生成大量可能成功也可能失败的轨迹。然后,它像一个严格的教练,只筛选出那些完全正确的轨迹作为“黄金标准”,用于后续训练子智能体。这样一来,高质量的训练数据就从智能体自身的探索中“生长”出来了,完全摆脱了对闭源模型的依赖。
3. 环境搭建与数据准备实操
理论很美好,但落到实处才是关键。要复现或基于AutoAct进行实验,第一步就是搭建环境。官方代码库基于Python,依赖相对清晰。
3.1 基础环境安装与关键配置
首先克隆仓库并安装依赖,这一步比较常规:
git clone https://github.com/zjunlp/AutoAct
cd AutoAct
pip install -r requirements.txt
依赖主要包括
transformers
,
deepspeed
,
langchain
,
accelerate
等常用的大模型训练和推理库。这里需要注意你的CUDA和PyTorch版本兼容性,建议在虚拟环境中操作。
一个容易被忽略但至关重要的配置是
搜索工具
。AutoAct在轨迹合成阶段,为了回答需要事实核查的问题(如HotpotQA),会调用Bing搜索API。你需要前往微软Azure门户申请一个Bing Web Search API密钥。请注意,该服务有免费额度限制,超出后会产生费用。申请成功后,你需要将密钥以环境变量或配置文件的形式提供给代码。通常,代码中会通过
os.environ[“BING_SEARCH_KEY”]
来读取。
务必妥善保管你的API密钥,避免泄露。
注意 :如果你研究的任务不依赖于外部搜索(例如某些封闭领域的推理任务),可以修改或跳过搜索工具的使用。但这需要你深入理解
Tool_Selection和Traj_Syn模块中工具调用的逻辑,可能涉及自定义工具的实现。
3.2 种子数据准备与自我指导
AutoAct的起点是“自我指导”阶段,目标是利用极少的种子数据,扩展出更多样化的任务描述。这步对应
Self_Instruct
目录。
你需要准备一个种子数据文件,例如
Meta_Hotpotqa.json
。这个文件通常包含少量(如5-10条)来自目标数据集的问题和答案对。格式是标准的JSON,每条数据包含
question
和
answer
字段。
运行数据生成命令:
python Self_Instruct/data_generation.py \
--source_data Self_Instruct/Meta_sample/Meta_Hotpotqa.json \
--target_data Self_Instruct/hotpotqa_metaqa.json \
--dataset_name hotpotqa \
--generate_all_num 800 \
--generate_per_round_num 10 \
--model_name llama-2-13b-chat \
这里有几个参数需要根据你的实际情况调整:
-
--generate_all_num 800:你想生成的总数据量。不宜过少,否则后续轨迹合成样本不足;也不宜过多,以免生成质量下降且耗费算力。800-2000是一个常见的范围。 -
--generate_per_round_num 10:每轮生成的数量。分批生成可以加入多样性策略,避免模型陷入重复模式。 -
--model_name:指定用于生成的基础模型。你需要确保该模型已通过Hugging Face下载到本地,或你的环境能正确访问。模型名称需与transformers库的命名一致。
这个脚本的工作原理是,让元智能体(llama-2-13b-chat)学习种子数据中的问题模式,然后通过自我对话、改写、泛化等方式,创造出新的、类似但非重复的问题。生成的数据将保存在
target_data
路径,作为下一阶段“自我规划”的输入。
4. 自我规划核心流程详解
这是AutoAct最核心、最精妙的部分。自我规划阶段的目标是,让智能体利用工具库,尝试解决自我指导阶段生成的问题,并从中筛选出成功的解决方案轨迹,作为训练子智能体的“教材”。
4.1 自动化工具选择
不是所有工具对每个任务都有用。首先,我们需要让元智能体为当前任务(如“科学问答ScienceQA”)从工具库中筛选出最相关、最可能被用到的工具。
python Self_Planning/Tool_Selection/tool_selected.py \
--model_name llama-2-13b-chat \
--task_name ScienceQA \
--top_k 40 \
--top_p 0.75 \
--max_tokens 1024 \
--tool_save_path Self_Planning/Tool_Selection/{task_name}_Tools.json
这个过程本质上是让LLM根据任务描述,理解每个工具的功能(工具描述已内嵌在提示词中),并做出选择。
top_k
和
top_p
是采样参数,影响选择的多样性。输出的JSON文件包含了被选中的工具列表及其描述,这缩小了后续轨迹合成时智能体的行动空间,提高了效率。
4.2 轨迹合成与质量过滤
接下来,重头戏上演:让元智能体使用筛选后的工具,去尝试解决自我指导生成的那些问题。
python Self_Plan/Traj_Syn/run_task.py \
--agent_name ZeroshotThink_HotPotQA_run_Agent \
--llm_name llama-2-13b-chat \
--max_context_len 4096 \
--task Hotpotqa \
--task_path Self_Instruct/hotpotqa_metaqa.json \
--save_path Self_Plan/Traj_Syn/output/hotpotqa_train_data.jsonl
这个脚本会启动一个交互循环:对于每个问题,智能体进行多轮“思考-行动-观察”。思考决定下一步做什么(调用哪个工具或直接给出答案),行动是执行工具调用(如搜索),观察是接收工具返回的结果。这个循环直到智能体给出最终答案或达到步数限制为止。每一步的完整记录(包括内部思考、工具调用、观察结果)就是一条“轨迹”。
生成的轨迹质量参差不齐。因此,必须进行严格过滤:
python Scripts/filter_data.py \
--source_path Self_Plan/Traj_Syn/output/hotpotqa_train_data.jsonl \
--save_path Self_Plan/Traj_Syn/output \
--task_name HotpotQA \
--filter_num 200
过滤逻辑很简单:只保留那些最终答案完全正确的轨迹(
reward=1
)。
filter_num
参数指定最多保留多少条高质量轨迹。这些“黄金轨迹”是后续训练的基石。
这里有一个关键经验:轨迹的数量和质量需要平衡。太少的轨迹(如<50)可能导致子智能体训练不充分,学习到的策略泛化能力差。建议至少保留100-200条高质量轨迹。
4.3 自我分化:训练专属的子智能体
拿到高质量的轨迹后,我们不是直接用它们去微调一个“大而全”的模型,而是进行“自我分化”。我们需要从这些完整的轨迹中,分离出专门用于训练三个子智能体的数据。
1. 数据分化 观察一条完整的轨迹,它混合了三种类型的步骤:
- 规划步骤 :例如“我需要先搜索A概念,再搜索B概念”。这部分数据被提取出来,用于训练 规划智能体 ,学习如何分解问题。
- 工具调用步骤 :例如“调用搜索工具,查询关键词为‘A概念的定义’”。这部分数据用于训练 工具智能体 ,学习如何将抽象规划转化为具体的工具参数。
- 反思步骤 :例如“上一步搜索的结果与问题无关,我应该调整搜索关键词”。这部分数据用于训练 反思智能体 ,学习评估当前状态并提供修正建议。
代码中通常有一个预处理脚本(可能需要根据你的数据格式稍作调整)来完成这种数据分离,生成
data_plan.json
,
data_tool.json
,
data_reflect.json
三个文件。
2. 使用LoRA进行高效微调 分化出数据后,我们使用参数高效微调技术LoRA来训练每个子智能体。这样做的好处是训练快、资源消耗少,且能保持基础模型的大部分原有知识。
# 以训练规划智能体为例,工具和反思智能体训练命令类似
CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 deepspeed Self_Plan/Train/train_lora.py \
--model_name_or_path llama-2-13b-chat \
--lora_r 8 \ # LoRA秩,影响参数量,通常8或16
--lora_alpha 16 \ # 缩放参数,一般设为r的2倍
--lora_dropout 0.05 \ # 防止过拟合
--data_path Self_Plan/Traj_Syn/output/data_plan.json \
--output_dir ./lora_weights/hotpotqa_plan_agent \
--num_train_epochs 5 \
--per_device_train_batch_size 2 \
--gradient_accumulation_steps 1 \
--learning_rate 1e-4 \ # 微调典型学习率
--fp16 True \
--deepspeed Self_Plan/Train/deepspeed_config_s3.json
关键参数解析 :
-
lora_r和lora_alpha:控制LoRA适配器的大小和强度。对于13B模型,r=8是常用起点。如果任务复杂,可尝试r=16。alpha通常设为2*r,这是一个经验值。 -
num_train_epochs:训练轮数。由于是高质量轨迹,3-5个epoch通常足够,需监控验证集损失防止过拟合。 -
per_device_train_batch_size和gradient_accumulation_steps:共同决定有效批次大小。需根据你的GPU内存调整。batch_size * gradient_accumulation_steps * GPU数量是总的批次大小。 -
deepspeed:使用DeepSpeed进行分布式训练和混合精度训练,可以大幅减少显存占用、加速训练。配置文件deepspeed_config_s3.json定义了ZeRO优化阶段和混合精度策略。
实操心得 :训练三个智能体时,建议依次进行,并分别保存检查点。虽然论文中使用了多卡并行,但如果你资源有限,完全可以依次在单张或多张卡上训练。训练反思智能体时,其数据量可能远少于规划和工具智能体,因为不是每一步都需要反思。这时可以适当减少
num_train_epochs或增加gradient_accumulation_steps来稳定训练。
5. 群体规划:子智能体协同工作流
训练好三个子智能体后,就进入了“群体规划”阶段。这是检验成果的时刻,看它们能否像一支训练有素的小队一样协同解决新问题。
5.1 协同推理流程解析
群体规划的运行脚本如下:
python Self_Planning/Group_Planning/run_eval.py \
--agent_name ZeroshotThink_HotPotQA_run_Agent \
--plan_agent ./lora_weights/hotpotqa_plan_agent \
--tool_agent ./lora_weights/hotpotqa_tool_agent \
--reflect_agent ./lora_weights/hotpotqa_reflect_agent \
--max_context_len 4096 \
--task HotpotQA \
--task_path ./eval_questions.json \
--save_path ./group_planning_output
这个流程是一个精心设计的循环:
- 规划智能体先动 :拿到一个新问题,规划智能体首先分析问题,并生成第一步的规划,例如“第一步:搜索‘迈克尔·乔丹的职业生涯’”。
-
工具智能体执行
:规划结果被传递给工具智能体。工具智能体根据这个规划,生成具体的工具调用指令,例如“调用
search_bing工具,参数query为‘迈克尔·乔丹 职业生涯 总冠军’”。 - 环境执行与观察 :系统执行工具调用,获取结果(如搜索返回的网页摘要),并将结果作为“观察”返回。
- 反思智能体评估 :将当前的问题、历史规划、行动、观察全部传递给反思智能体。反思智能体判断当前进展:是否偏离方向?信息是否足够?是否需要调整策略?它可能输出“当前信息已足够回答关于冠军数量的问题,可以进入下一步”或“上一步搜索未找到关键信息,建议尝试搜索‘迈克尔·乔丹 公牛队 冠军年份’”。
- 循环或终止 :根据反思结果,流程要么回到第1步(规划智能体基于新观察做下一步规划),要么判断可以给出最终答案,由规划或工具智能体合成最终回复。
这个过程模拟了一个高效的团队:规划者是“指挥官”,工具执行者是“士兵”,反思者是“参谋”。三者各司其职,通过对话协同推进任务。
5.2 提示词工程的关键作用
整个AutoAct框架的运作极度依赖提示词。在
Prompts
目录下,存放着各个阶段、各个智能体使用的提示词模板。例如:
- 轨迹合成提示词 :指导元智能体如何逐步思考和使用工具。它定义了ReAct(Reasoning + Acting)的格式。
- 子智能体训练提示词 :将轨迹中的每一步转换成适合该子智能体学习的问答对格式。例如,对于规划智能体,输入是“当前问题和历史”,输出是“下一步规划”。
- 群体规划提示词 :定义了三个子智能体在协同工作时,各自的角色、职责和输入输出格式。
修改或适配新任务时,最大的工作量往往就在提示词工程上 。你需要确保提示词清晰定义了任务边界、工具描述和输出格式。一个常见的技巧是,在提示词中提供1-2个清晰的示例(Few-shot Learning),能显著提升智能体行为的稳定性和准确性。
6. 实验配置、调优与问题排查
在实际运行AutoAct进行自己的实验时,你会遇到各种配置和性能问题。这里分享一些从代码和实践中总结的关键点。
6.1 模型与超参数选择策略
-
基础模型选择
:论文主要使用了LLaMA-2 (7B, 13B, 70B)。对于大多数研究者和开发者,
LLaMA-2-13B-Chat
是一个平衡点,它在效果和资源消耗之间取得了较好平衡。如果你资源有限,可以尝试更小的模型如
Llama-2-7B-Chat或Mistral-7B,但需要预期性能会有折损。切记使用Chat版本,因为其对话格式与框架中的提示词模板更匹配。 -
上下文长度
:
max_context_len默认4096。如果你的问题或工具返回内容很长,可能需要考虑使用支持更长上下文(如8K, 16K)的模型,并相应调整此参数。否则,关键信息可能会被截断。 -
LoRA超参数
:
-
learning_rate:LoRA微调的学习率通常在1e-4到5e-4之间。1e-4是一个安全且有效的起点。 -
num_train_epochs:对于几百条高质量轨迹,3-5个epoch通常足够。可以通过观察训练损失曲线来判断:当损失不再明显下降时即可停止,避免过拟合。 -
per_device_train_batch_size:在24GB显存的GPU上,对于13B模型,batch_size=1或2是常见的。通过gradient_accumulation_steps来累积梯度,模拟更大的批次大小。
-
6.2 常见运行错误与解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 导入错误或模块找不到 | 依赖未完全安装或环境路径问题 |
1. 确认在
AutoAct
项目根目录下运行。
2. 尝试
pip install -e .
以可编辑模式安装。
3. 检查
requirements.txt
中所有包是否成功安装,特别注意
deepspeed
可能需要单独安装或与CUDA版本匹配。
|
| CUDA out of memory | 模型或批次过大,超出GPU显存 |
1. 减小
per_device_train_batch_size
。
2. 增大
gradient_accumulation_steps
以补偿。
3. 启用
gradient_checkpointing
(在训练脚本中通常已启用)。
4. 使用
deepspeed
并配置更激进的ZeRO阶段(如stage 3)和优化器offload。
|
| 轨迹合成时智能体“卡住”或循环 | 提示词引导不力,或模型无法理解工具输出 |
1. 检查并优化轨迹合成阶段的提示词,确保包含了明确的停止条件(如“最终答案:”)。
2. 在工具调用步骤后,强制在观察中插入清晰的分隔符,帮助模型区分不同部分。 3. 为工具调用设置最大尝试次数(如10步),避免无限循环。 |
| 子智能体训练损失不下降 | 学习率不合适、数据格式错误或数据量太少 |
1. 尝试调整学习率(如5e-5, 2e-4)。
2. 检查分化后的训练数据(
data_plan.json
等)格式是否正确,是否为标准的指令-响应对。
3. 增加高质量轨迹的过滤数量(
filter_num
),确保训练数据充足且有代表性。
|
| 群体规划时智能体协作混乱 | 子智能体未训练好,或群体规划提示词冲突 |
1. 首先单独测试每个子智能体:给规划智能体一个问题看规划是否合理;给工具智能体一个规划看参数生成是否准确。
2. 仔细检查群体规划中三个智能体的提示词,确保角色定义清晰,输入输出格式无缝衔接,没有互相矛盾的指令。 |
6.3 效果评估与迭代改进
AutoAct论文在HotpotQA、ScienceQA等基准上进行了评估。如果你想评估自己的智能体:
- 构建测试集 :准备一组模型在训练时未见过的、来自目标领域的问题。
-
运行群体规划
:在测试集上运行
run_eval.py,保存输出轨迹。 -
设计评估指标
:
- 任务准确率 :最终答案是否正确(精确匹配或模糊匹配)。
- 轨迹效率 :平均需要多少步(工具调用)才能解决问题。步数越少,通常说明规划和反思越有效。
- 工具使用准确率 :调用的工具是否恰当,参数是否合理(可能需要人工或规则判断)。
-
迭代改进
:如果效果不佳,不要急于调整所有部分。可以系统性地排查:
- 数据质量 :回顾“黄金轨迹”是否真的高质量?是否存在侥幸正确的轨迹?
- 提示词 :各个阶段的提示词是否有歧义?是否提供了足够清晰的示例?
- 模型能力 :基础模型是否足够强大以理解任务?考虑升级基础模型或使用更好的Chat版本。
- 分工设计 :对于你的特定任务,“规划-工具-反思”的三分法是否最优?是否需要增加或合并某些角色?
7. 扩展思考与应用前景
AutoAct框架为我们提供了一种构建专用智能体的自动化范式。它的价值不仅在于在学术数据集上取得了不错的成绩,更在于其方法论上的启发性。
首先,它验证了“分工协作”智能体架构的可行性。 将一个复杂任务分解给多个各司其职的专家模型,比让一个通用模型学习所有技能,在数据效率和最终性能上可能更具优势。这为后续的智能体架构设计指明了方向。
其次,它极大地降低了高质量智能体训练数据的获取门槛。 摆脱对GPT-4等闭源模型的依赖,使得在小规模、特定领域构建智能体成为可能,有利于隐私敏感或成本敏感的应用场景。
在实际项目中,你可以将AutoAct的思路进行迁移和改造。例如:
- 领域适配 :将工具库替换成你业务内部的API,如数据库查询、内部知识库检索、业务系统调用等,即可自动化构建一个解决内部任务的智能体小组。
- 架构变体 :三分法不是金科玉律。对于更复杂的任务,你可以尝试分化出更多的角色,如“审核智能体”、“总结智能体”。或者,对于简单任务,可以尝试“规划-执行”二分法。
- 基础模型升级 :随着更强的开源模型不断涌现(如Llama 3、Qwen2.5、DeepSeek等),用它们作为元智能体,有望生成更高质量的初始轨迹,从而训练出更强大的子智能体。
最后,一个重要的实践提醒 :整个AutoAct流程的计算开销依然不小,尤其是在轨迹合成和模型微调阶段。在开始大规模实验前,建议先用一个非常小的数据集(如生成10条数据,合成20条轨迹)跑通全流程,确保代码、环境和配置全部正确无误。这能帮你节省大量时间和算力成本。智能体的训练和评估是一个迭代过程,耐心和系统性的实验记录是成功的关键。
更多推荐
所有评论(0)