使用 Agent-lightning 训练第一个 Agent¶
欢迎!本教程是您使用 Agent-lightning 框架让 AI Agent 更智能的第一步。我们将向您展示如何采用一个简单的 Agent,并通过一种称为 自动 Prompt 优化 (APO) 的过程自动提高其性能。
Agent-lightning 的主要目标是提供一种结构化的方式来 训练您的 Agent。就像您使用数据训练机器学习模型一样,您可以使用任务数据集来训练 Agent。这可能涉及使用强化学习 (RL) 来教它新的行为,或者,正如我们今天所做的那样,优化其 Prompt 以使其更准确可靠。
提示
您可以在以下位置打开示例代码 room_selector_apo.py 和 room_selector.py 在阅读本教程时。
我们的示例:房间选择器 Agent¶
今天,我们将使用一个 Agent,它的工作是预订会议室。这是一项常见的但棘手的任务,具有多个约束。
Agent 的工作方式如下
- 输入: 它接收具有特定要求的任务,例如“
为 4 个人在上午 10:00 预订一个带有白板的房间。” - 操作: Agent 使用大型语言模型 (LLM) 来理解请求。它还可以使用工具,即预定义的函数,它可以调用这些函数来获取更多信息,例如检查外部数据库中的房间可用性。
- 输出: 它的最终决定是它找到的最佳房间的 ID,例如“
A103”。 - 奖励: 在 Agent 做出选择后,一个单独的“评分器”函数会根据 0 到 1 的比例评估其性能。这个分数被称为它的 奖励。完美的选项获得 1.0,而错误的选项获得 0.0。
Agent 的逻辑是合理的,但其性能在很大程度上取决于其初始 Prompt。措辞不当的 Prompt 会让 LLM 感到困惑,从而导致糟糕的决策。我们的目标是使用 Agent-lightning 自动找到最佳 Prompt。
更深入地了解 Agent 的逻辑
现代 LLM 不仅可以生成文本,还可以决定调用您提供的函数。这通常称为工具使用或函数调用。我们的 Agent 使用此功能做出明智的决策。如果您不熟悉这个概念,可以阅读更多关于它的内容 OpenAI 的文档。
以下是 Agent 逻辑的草图,紧密遵循 OpenAI API
# Pseudo-code for the Room Selector agent
import openai
import json
def room_selector_agent(task, prompt):
client = openai.OpenAI()
messages = [{"role": "user", "content": prompt.format(**task)}]
tools = [ ... ] # Tool definition for the LLM
# 1. First LLM call to decide if a tool is needed.
response = client.chat.completions.create(
model="gpt-5-mini",
messages=messages,
tools=tools,
tool_choice="auto",
)
response_message = response.choices[0].message
tool_calls = response_message.tool_calls
# 2. Check if the LLM wants to use a tool.
if tool_calls:
messages.append(response_message) # Append assistant's reply
# 3. Execute the tool and get the real-world data.
for tool_call in tool_calls:
function_name = tool_call.function.name
if function_name == "get_rooms_and_availability":
function_args = json.loads(tool_call.function.arguments)
# Query the local room database
function_response = get_rooms_and_availability(
date=function_args.get("date"),
time_str=function_args.get("time"),
duration_min=function_args.get("duration_min"),
)
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": json.dumps(function_response),
})
# 4. Second LLM call with the tool's output to get a final choice.
second_response = client.chat.completions.create(
model="gpt-5-mini",
messages=messages,
)
final_choice = second_response.choices[0].message.content
else:
final_choice = response_message.content
# 5. Grade the final choice to get a reward.
reward = grade_the_choice(final_choice, task["expected_choice"])
return reward
在 Agent-lightning 中,您将此逻辑包装在带有 @rollout 装饰器的 Python 函数中,以便 Agent-lightning 的运行程序和训练器可以管理和调整 Agent。算法调整的 prompt_template 作为参数传递。
import agentlightning as agl
@agl.rollout
def room_selector(task: RoomSelectionTask, prompt_template: agl.PromptTemplate) -> float:
# ... agent logic using the prompt_template ...
# The final reward is determined by a grader function
reward = room_selection_grader(client, final_message, task["expected_choice"])
return reward
核心概念:任务、Rollout、Span 和 Prompt 模板¶
要了解 Agent-lightning 的工作原理,您需要了解这些关键术语。
任务¶
任务是提供给 Agent 的特定输入或问题陈述。它定义了 Agent 需要完成什么。
类比:任务
如果 Agent 是厨师,那么任务就是食谱请求:“烘烤一个巧克力蛋糕。”
Rollout¶
Rollout 是 Agent 尝试解决给定 任务 的单个完整执行。这是从接收任务到生成最终结果和接收奖励的整个故事。Rollout 捕获 Agent 执行的完整跟踪。
类比:Rollout
Rollout 是厨师烘烤巧克力蛋糕的一次完整尝试,从收集配料到最终品尝测试。
Span¶
Span 代表 Rollout 中的单个工作单元或操作。Span 是跟踪的基础构建块。它们具有开始和结束时间,并包含有关特定操作的详细信息,例如 LLM 调用、工具执行或奖励计算。有关更精确的定义,请参阅 OpenTelemetry 文档。
类比:Span
如果 Rollout 是“烘烤蛋糕”,那么 Span 可以是“预热烤箱”、“混合面粉和糖”或“添加糖霜”。每个都是一个不同的步骤或工作单元。
下图来自 ADK 显示了一个典型的 Rollout,其中瀑布视图中的每个矩形可视化一个 Span。如可视化所示,Span 可以是顺序的、并行的或嵌套的。在其他框架中,术语可能略有不同。Agent-lightning 遵循 OpenTelemetry 使用的术语以避免混淆。

Prompt 模板¶
Prompt 模板是 Agent 的可重用指令,通常包含可以填充来自任务的特定详细信息的占位符。它是算法学习和改进随时间的 “资源” 的关键。
类比:资源(Prompt 模板)
如果任务是食谱请求,那么 Prompt 模板是厨师遵循的主食谱卡。算法的工作是编辑此食谱卡,使说明更清晰,最终菜肴更好。
训练循环:魔法发生的地方¶
Agent-lightning 中的训练围绕一个清晰、管理的循环,由 训练器 编排。下图说明了这种核心交互
循环说明
- 算法到 Agent(通过训练器): 算法(“大脑”)创建一个改进的 Prompt 模板 并选择 任务。然后,训练器将两者发送给 Agent。
- Agent 到算法(通过训练器): 对于收到的每个任务,Agent 使用提供的 Prompt 模板执行 Rollout,执行其逻辑并可能使用工具。在此 Rollout 期间,运行 Agent 的运行程序会捕获详细的 Span,详细说明每个步骤。Agent 还计算其在任务上的性能的奖励。这些 Span 和奖励然后通过训练器发送回算法。
- 算法学习: 然后,算法分析这些 Span 和奖励,以了解如何改进 Agent 的行为,例如通过生成更好的 Prompt。然后,改进的 Prompt 在下一次迭代的任务中使用。
此循环继续进行,允许 Agent 持续学习并提高解决任务的能力。
注意
在下一个教程中,我们将看到这里的“通过训练器”并不准确。实际上是通过运行程序和存储。
算法¶
算法是驱动改进的智能部分。在本教程中,我们使用 APO(自动 Prompt 优化)。它分几个步骤工作
- 评估: 算法首先要求运行 Rollout 使用当前的 Prompt 模板来查看其表现如何。
- 评论: 然后,它查看来自这些 Rollout 的详细 Span。使用强大的 LLM(
gpt-5-mini),它生成“文本梯度”,这是一种对 Prompt 的自然语言评论。例如:“Prompt 在处理房间平局的 tie-breakers 时含糊不清。” - 重写: 最后,它将评论和原始 Prompt 提供给另一个 LLM(
gpt-4.1-mini),并要求它应用编辑,生成一个新的改进的 Prompt 模板。
此循环重复进行,每一轮都会产生一个略好的 Prompt。要使用它,只需使用所需的超参数初始化 APO 类即可。
# In the main training script: run_apo.py
from openai import AsyncOpenAI
openai = AsyncOpenAI()
algo = agl.APO(openai)
提示
确保您已在环境变量中设置 OPENAI_API_KEY。
训练器¶
训练器是您将与之交互的中心组件。它连接所有内容并管理整个工作流程,通过运行上述循环。您配置训练器,提供算法、并行运行程序的数量和初始 Prompt。只需调用 trainer.fit() 即可启动整个过程!
# 1. Configure the Trainer with the algorithm and initial prompt
trainer = agl.Trainer(
algorithm=algo,
n_runners=8, # Run 8 agents in parallel to try out the prompts
initial_resources={
# The initial prompt template to be tuned
"prompt_template": prompt_template_baseline()
},
# This is used to convert the span data into a message format consumable by APO algorithm
adapter=agl.TraceToMessages(),
)
# 2. Load datasets: They can be list of task objects consumable by `room_selector`.
dataset_train, dataset_val = ...
# 3. Start the training process!
trainer.fit(
agent=room_selector,
train_dataset=dataset_train,
val_dataset=dataset_val
)
提示
TraceToMessages 是一个方便的适配器,可将 Span 转换为 OpenAI 聊天消息。它需要安装 openai >= 1.100.0。
训练结果¶
APO 算法成功地提高了 Agent 的性能。我们使用以下超参数运行示例
val_batch_size= 10gradient_batch_size= 4beam_width= 2branch_factor= 2beam_rounds= 2
在 29 个样本的数据集上,验证准确率稳步从 0.569(基线)提高到 0.721(第 2 轮之后)。使用 8 个运行程序进行调整大约需要 10 分钟。我们运行了两次,结果如图所示。
这证明了 Agent-lightning 可以使用几行代码有效地自动增强 Agent 的能力。