在这个教程中,我们将学习如何使用 DSPy 优化一个语言模型驱动的智能体(Agent),让它在复杂的游戏任务中表现更出色。通过优化提示和微调模型权重,我们将从一个基础表现的智能体出发,最终构建一个高效的游戏玩家。
🛠️ 安装依赖并下载数据
首先,安装最新版本的 DSPy 和所需的依赖项:
pip install -U --pre dspy
pip install -U alfworld==0.3.5 multiprocess
alfworld-download
推荐设置 MLflow 来追踪优化进程并可视化结果:
pip install mlflow>=2.20
mlflow ui --port 5000
在代码中连接 MLflow:
import mlflow
mlflow.set_tracking_uri("http://localhost:5000")
mlflow.set_experiment("DSPy")
mlflow.dspy.autolog()
🤖 设置语言模型
我们将使用两个模型:
- GPT-4o:用于提示优化和生成高质量示例。
- GPT-4o-mini:一个更小的模型,经过微调后将成为最终的智能体。
import dspy
gpt4o_mini = dspy.LM('gpt-4o-mini-2024-07-18')
gpt4o = dspy.LM('openai/gpt-4o')
dspy.configure(experimental=True)
加载 AlfWorld 数据集(一个家庭模拟任务数据集):
from dspy.datasets.alfworld import AlfWorld
alfworld = AlfWorld()
trainset, devset = alfworld.trainset[:200], alfworld.devset[-200:]
len(trainset), len(devset)
🧑💻 定义智能体程序
智能体的核心是一个简单的 DSPy 模块,名为 Agent
。它包含一个子模块 self.react
,用于根据任务、轨迹和可能的动作生成下一步行动。
class Agent(dspy.Module):
def __init__(self, max_iters=50, verbose=False):
self.max_iters = max_iters
self.verbose = verbose
self.react = dspy.Predict("task, trajectory, possible_actions: list[str] -> action")
def forward(self, idx):
with alfworld.POOL.session() as env:
trajectory = []
task, info = env.init(idx)
if self.verbose:
print(f"Task: {task}")
for _ in range(self.max_iters):
trajectory_ = "\n".join(trajectory)
possible_actions = info["admissible_commands"][0] + ["think: ${...thoughts...}"]
prediction = self.react(task=task, trajectory=trajectory_, possible_actions=possible_actions)
trajectory.append(f"> {prediction.action}")
if prediction.action.startswith("think:"):
trajectory.append("OK.")
continue
obs, reward, done, info = env.step(prediction.action)
obs, reward, done = obs[0], reward[0], done[0]
trajectory.append(obs)
if self.verbose:
print("\n".join(trajectory[-2:]))
if done:
break
assert reward == int(info["won"][0]), (reward, info["won"][0])
return dspy.Prediction(trajecotry=trajectory, success=reward)
🧪 零样本评估(Zero-Shot Evaluation)
在未优化的情况下,直接测试智能体的表现:
agent_4o = Agent()
agent_4o.set_lm(gpt4o)
agent_4o.verbose = True
example = trainset[0]
agent_4o(**example.inputs())
通过评估整个开发集的表现,查看平均成功率:
metric = lambda x, y, trace=None: y.success
evaluate = dspy.Evaluate(devset=devset, metric=metric, display_progress=True, num_threads=16)
agent_4o.verbose = False
evaluate(agent_4o)
结果显示:
- GPT-4o:约 57.5% 的成功率。
- GPT-4o-mini:仅 15% 的成功率。
✨ 提示优化(Prompt Optimization)
我们将使用 MIPROv2
优化器对 GPT-4o 的提示进行轻量级优化:
optimizer = dspy.MIPROv2(metric=metric, auto="light", num_threads=16, prompt_model=gpt4o)
config = dict(max_bootstrapped_demos=1, max_labeled_demos=0, minibatch_size=40)
optimized_4o = optimizer.compile(agent_4o, trainset=trainset, **config, requires_permission_to_run=False)
🔧 微调 GPT-4o-mini
接下来,我们将使用优化后的 GPT-4o 作为教师模型,微调 GPT-4o-mini:
student_4o_mini = optimized_4o.deepcopy()
student_4o_mini.set_lm(gpt4o_mini)
optimizer = dspy.BootstrapFinetune(metric=metric, num_threads=16)
finetuned_4o_mini = optimizer.compile(student_4o_mini, teacher=optimized_4o, trainset=trainset)
📊 评估微调后的智能体
微调后,GPT-4o-mini 的成功率显著提升:
evaluate(finetuned_4o_mini)
结果显示成功率达到 71.5%,如果使用更多训练数据(如 500 个任务),成功率甚至可以提升到 82%。
💾 保存和加载优化后的智能体
将优化后的智能体保存到文件中:
finetuned_4o_mini.save('finetuned_4o_mini_001.pkl')
稍后可以通过以下方式加载并使用:
loaded = Agent()
loaded.load('finetuned_4o_mini_001.pkl')
🚀 总结
通过 DSPy 的提示优化和微调技术,我们成功将一个基础的 GPT-4o-mini 智能体从 15% 的成功率提升到超过 70%。这种方法不仅高效,还能充分利用小数据集的潜力,为复杂任务提供强大的解决方案。
准备好让你的智能体更智能了吗?快试试 DSPy 吧!🎉