Prompt实战之构建基于 LLM 的 BabyAI 智能体系统 1)环境准备与基础配置

本部分主要目标是构建系统的基础环境,包括依赖导入、OpenAI 客户端初始化以及 BabyAI 环境的初步配置。

文章目录

    • 1.1 导入依赖模块
      • 实战演示
      • 技巧提示
      • 练习建议
    • 1.2 初始化 OpenAI 客户端
      • 实战演示
      • 技巧提示
      • 练习建议
    • 1.3 BabyAI 环境简介与环境类型分类方法
      • 环境类型说明
      • 环境分类函数 `separate_types`
      • 实战演示
      • 技巧提示
      • 练习建议
    • 1.4 动作列表及环境描述 (Prompt) 构造
      • 动作列表
      • 环境描述与 Prompt 设计
      • 实战演示
      • 技巧提示
      • 练习建议

1.1 导入依赖模块

在正式搭建智能体之前,需要导入一系列 Python 模块,以便后续进行环境操作、并行运算、数据处理以及与 OpenAI API 进行交互。常用模块包括:

  • os:操作系统相关功能(文件路径、并行执行等)。
  • openai:调用 OpenAI API 进行语言模型对话。
  • backoff:实现调用 API 时的重试机制。
  • json:用于 JSON 序列化与反序列化。
  • gym:使用 Gym 接口构造强化学习环境,BabyAI 就是基于 Gym 封装的。
  • babyai_text:针对 BabyAI 环境的工具包。
  • numpy:科学计算与数组处理。
  • collections:存储队列、字典以及有序字典等数据结构,方便状态管理。
  • random:随机数生成,用于策略测试。
  • matplotlib.pyplot:用于结果的可视化展示。
  • concurrent.futures:支持多线程或多进程执行,加快实验速度。
  • tqdm:提供进度条,便于观察长时间运行时的程序状态。
  • argparse:解析命令行参数,便于灵活配置实验参数。
  • pickle:保存实验数据(例如图像序列)。
  • copy:实现对象深拷贝,确保状态在复用时不被破坏。
  • plan 模块:包含生成计划与评估方法。

实战演示

下面代码片段展示了所有依赖模块的导入步骤,确保你的开发环境中安装了相应的包(如有缺失,可使用 pip install 模块名 命令进行安装):

import os
import openai
import backoff
import json
from openai import OpenAI
import gym
import babyai_text
import numpy as np
from collections import deque, defaultdict, OrderedDict
import random
import matplotlib.pyplot as plt
from concurrent.futures import ProcessPoolExecutor
import tqdm
import argparse
import pickle
import copy
from plan import gen_plan, evaluate

技巧提示

  • 模块管理:建议使用虚拟环境(例如 virtualenv 或 conda)来管理依赖,避免不同项目之间发生包版本冲突。

  • 错误检查:在导入模块时,如遇找不到模块的错误,确认各个依赖包已通过 pip 安装,并核对 Python 版本兼容性。

  • 注释说明:在代码文件中添加模块用途的注释,后续维护时便于快速定位需要修改的部分。

  • OpenAI库: 关于openai库的安装见博客:《Prompt工程之OpenAI库》 1)安装教程(阿里云百炼平台)

  • babyai_text 安装教程

    git clone https://github.com/flowersteam/Grounding_LLMs_with_online_RL.git
    cd Grounding_LLMs_with_online_RL
    pip install blosc
    cd babyai-text/babyai
    pip install -e .
    cd ../gym-minigrid
    pip install -e .
    cd ..
    pip install -e .
    

练习建议

  • 练习 1:在自己的开发环境中创建一个新的 Python 项目,尝试导入上述所有依赖,并用 print 输出当前 Python 版本和各模块的版本,确保所有依赖模块正常工作。
  • 练习 2:给每个导入的模块添加注释说明其主要用途,撰写一份模块使用说明文档,并提交到项目的 README 文件中。

1.2 初始化 OpenAI 客户端

在项目中,我们将调用 OpenAI 的 API 与语言模型进行交互。初始化 OpenAI 客户端时需要提供 API Key 与 Base URL(可依据使用的 API 服务进行配置)。示例代码如下:

client = OpenAI(
    api_key="YOUR_API_KEY_HERE",
    base_url="YOUR_BASE_URL_HERE"
)

实战演示

  1. 注册并获取 API Key:访问 OpenAI 的官方网站,注册账号并获取你的 API Key。
  2. 修改代码:将示例代码中的 "YOUR_API_KEY_HERE" 替换为你的实际 API Key。如果你使用代理或本地部署模型,也可配置 base_url

技巧提示

  • 安全管理:不要将 API Key 明文保存在代码中。可以将其存储在环境变量中,然后使用 os.environ 读取,以避免泄露。
  • 错误处理:建议为 API 请求添加重试或异常捕获机制(后面会讲到 backoff 使用),确保由于网络波动导致的请求失败不会影响整体程序。

练习建议

  • 练习 3:修改代码,将 API Key 和 Base URL 通过环境变量传递,编写一个简单的测试函数,用于调用 OpenAI 的一个简单接口并打印返回结果,以验证 API Key 是否配置正确。
  • 练习 4:阅读 OpenAI 官方文档,了解更多关于 API 配置的细节与最佳实践,为后续的智能体对话做好准备。

1.3 BabyAI 环境简介与环境类型分类方法

BabyAI 环境基于 OpenAI Gym,提供了多种任务情境。系统内设有不同的任务类别(例如:gotopickupputnext 等),每种任务对智能体的操作时间步(horizon)有所不同。本节通过以下步骤帮助你完成环境的初始化与分类:

环境类型说明

代码中定义了环境类型列表,并为每个任务设定了 horizon(允许的最大步数),例如:

env_types = ['goto', 'pickup', 'putnext', 'open', 'pick up seq go to']

环境分类函数 separate_types

该函数通过多次调用 gym.make 创建环境,依据环境内的 action_kind 属性对环境进行分类,确保每一种类型的环境至少选取一个实例,用于之后的实验:

def separate_types(env_name):
    envs = {key: None for key in env_types}
    num_envs = len(env_types)
    num_envs_so_far = 0

    for _ in range(1000):
        env = gym.make(env_name)
        action_kind = env.env.action_kinds[0]
        if action_kind in envs and envs[action_kind] is None:
            envs[action_kind] = env
            num_envs_so_far += 1
            if num_envs_so_far == num_envs:
                break

    assert num_envs_so_far == num_envs

    return envs

实战演示

  1. 创建环境实例:编写一个简短的脚本,调用 separate_types 方法,传入你选择的环境名称(如 BabyAI-MixedTestLocal-v0),观察终端输出,确保每个任务类型都有相应的环境实例。
  2. 调试检查:在断言语句附近添加 print 语句,打印每个环境的 action_kind,确认分类是否正确。

技巧提示

  • 循环次数与资源消耗:此函数在最坏情况下可能创建多达 1000 个环境实例,请在调试时注意内存占用,必要时设置合理的超时时间或减少循环次数。
  • 健壮性设计:函数最后通过断言确保所有类型均已成功创建,如调试失败,检查环境是否支持所有指定的 action_kind

练习建议

  • 练习 5:运行并调试 separate_types 函数,尝试修改环境名称参数,观察不同环境中 action_kind 的变化,并记录每种类型下的不同表现。
  • 练习 6:扩展环境分类函数,为每个环境输出更多信息(例如环境的 horizon 设置),以便后续实验中能更直观地调试问题。

1.4 动作列表及环境描述 (Prompt) 构造

为了让 OpenAI 的语言模型能够理解当前环境及任务目标,我们需要定义一个动作列表以及一份环境描述(Prompt)。这份描述不仅包括环境的基本规则,还说明了任务目标和允许的动作。

动作列表

动作列表对应了智能体可以选择的操作(例如:转向、前进、拾取、丢弃等),代码片段如下:

action_list = {
    0: "turn left",
    1: "turn right",
    2: "go forward",
    3: "pick up",
    4: "drop",
    5: "toggle",
}
num_actions = len(action_list)

环境描述与 Prompt 设计

环境描述详细介绍了任务场景、视角、可操作对象及动作规则。该描述会作为系统消息(system message)的一部分传递给 LLM,确保模型能根据情境进行动作决策。示例描述如下:

env_description = '''You are an agent in an 8x8 partially-observable 2D text-based environment.
You see the 6x6 grid in front of you, and can face north, south, east, or west.
The possible actions are turn left, turn right, go forward, pick up, drop, and toggle.
At each turn, you will receive a history of the last observations and actions.
Your aim is to complete the task described in the goal.
Each tile in the grid can only contain at most one object.
Objects cannot be crossed, and may need to be bypassed or moved.
You can only move onto an empty tile or on a tile containing an open door.
You can only hold one object at a time, using pick up when they are one step in front.
Objects are dropped one tile in front and cannot be dropped when there is another object in front.
Doors are unlocked with keys of the same color using the toggle action.
Actions are deterministic, do not repeat actions if they have no effect.
You have #HORIZON# steps to complete the task.'''

实战演示

  1. 观察动作列表:运行简单的打印语句,输出 action_list,确认索引与动作名称一一对应。
  2. 构建完整 Prompt:结合上述描述与命令格式(JSON 格式返回选项),生成完整的系统消息内容,便于后续发送给 LLM 进行交互。

例如,将环境描述与选择动作提示合并:

json_instruction = '''Reply concisely and exactly with the following JSON format:
{"choice": X}
where X is the index of the desired choice.'''

default_system_message = env_description.replace('#HORIZON#', '64') + '\n\n' + \
                         'You will be prompted at each turn to choose actions.' + '\n\n' + json_instruction

print(default_system_message)

技巧提示

  • 模板设计:在实际应用中,prompt 模板需要适应不同的任务场景,可以设计多个模板(如 React 型、系统探索型),以便灵活调用。
  • 占位符替换:利用字符串替换(如 .replace('#HORIZON#', '64'))来适应不同任务时长,有助于提高代码的复用性。

练习建议

  • 练习 7:尝试编写不同任务场景下的 prompt 模板,例如更换 grid 尺寸或动作描述,使其更符合你的实际需求。
  • 练习 8:在已有模板基础上扩展 JSON 格式的要求,比如让返回格式包含更多选项(例如包含推理过程等),以提升语言模型的回答准确性。

你可能感兴趣的:(prompt)