Project 5: 用大语言模型做积木世界规划

简介
在过去的项目中,我们用搜索和强化学习让智能体完成任务。本次项目,我们换一个主角:让 大语言模型(LLM) 来做符号规划——给定一个"积木世界(Blocksworld)"的初始摆放和目标摆放,让模型规划出一串合法动作,把积木按要求堆好。
本项目你只写 Prompt 和少量胶水代码,不用自己实现环境,也不用写 BFS/DFS/A* 这类搜索算法。核心是学习提示词工程(Prompt Engineering):怎样把任务讲清楚、怎样约束输出格式、怎样让模型把自然语言准确翻译成结构化状态。
你要完成两道题,两题共用同一套环境和 25 个任务,最后用 evaluate.py 统一打分:
| 题目 | 做法 | 你要改的文件 |
|---|---|---|
| Q1 | 让 LLM 直接输出动作序列 | my_planner/q1_llm_prompt_planner.py |
| Q2 | 让 LLM 生成 PDDL,再交给规划器求解 | my_planner/q2_llm_pddl_planner.py |
本次作业所需的文件为:blockworld_student.zip。解压后阅读其中的 STUDENT_GUIDE.md 获取完整说明(含提交要求)。
规则:
- 不能写 BFS / DFS / A* 等搜索算法;不能按
task_id硬编码答案。 - 不能修改
env/、pddl/、tasks/、run_*.py、evaluate.py。 - 只动
my_planner/一个目录。
你需要编辑的文件
| 文件 | 作用 |
|---|---|
my_planner/q1_llm_prompt_planner.py | Q1:填 3 个函数(拼 Prompt、解析输出、串流程)。 |
my_planner/q2_llm_pddl_planner.py | Q2:填 4 个函数(生成 PDDL、清洗、调规划器、串流程)。 |
my_planner/prompt_templates/ | Prompt 草稿(可选,便于组织结构)。 |
积木世界长什么样
状态由 5 个谓词描述:ontable(A)(A 在桌上)、on(A,B)(A 摞在 B 上)、clear(A)(A 顶上没东西)、holding(A)(手拿着 A)、handempty(手空)。
只有 4 个动作,且必须满足前提条件才合法:
| 动作 | 什么时候能用 |
|---|---|
PICKUP(x) | x 在桌上、顶上没东西、手是空的 |
PUTDOWN(x) | 手正拿着 x |
UNSTACK(x,y) | x 摞在 y 上、x 顶上没东西、手是空的 |
STACK(x,y) | 手拿着 x、y 顶上没东西 |
LLM 最常犯的错就是用了不满足前提的动作——这正是你要在 Prompt 里解决的问题。
任务分层(25 个任务)
| 层级 | 目录 | 数量 | 状态形式 |
|---|---|---|---|
| 公开 | tasks/public/ | 4 | 结构化状态 + 自然语言(调试用) |
| 纯自然语言 | tasks/nl_only/ | 5 | 仅自然语言 |
| 隐藏 | tasks/hidden/ | 3 | 仅自然语言 |
| 困难 | tasks/hard/ | 3 | 仅自然语言 |
| 极限 | tasks/extreme/ | 10 | 仅自然语言(最多 9 块、26 步) |
注意: 只有 4 个公开任务带结构化的 initial_state/goal_state,其余 21 个任务在评测时只给自然语言。你的 Prompt 必须能从自然语言里准确读出状态——这才是真正拉开差距的地方。
环境与配置
安装依赖(Q2 需要 PDDL 规划器 pyperplan):
pip install -r requirements.txt # 含 openai、pyperplan 等
为保证评测公平,本项目统一使用 deepseek-chat 模型,模型名与接口地址已固定,你只需提供自己的 API Key。先到 https://platform.deepseek.com/api_keys 注册并创建一个 API Key,然后通过环境变量配置(避免把 Key 写进代码):
export OPENAI_API_KEY="你的deepseek-key" # 只需改这一行
export LLM_PROVIDER="openai-compatible"
export LLM_BASE_URL="https://api.deepseek.com" # 固定,请勿修改
export LLM_MODEL="deepseek-chat" # 固定,请勿修改
注意: 评测模型与接口地址固定为 deepseek-chat / https://api.deepseek.com,请勿改用其它模型或服务,以保证所有同学在同一模型上公平评测。跑完全部 25 个任务(Q1+Q2)的 API 花费不到 1 元人民币,新注册账号通常带有免费额度即可正常完成本项目。每次关闭终端后环境变量会失效,重新打开终端需再次 export。
Q1:让 LLM 直接输出动作
填好 q1_llm_prompt_planner.py 中的 3 个函数(签名已给好,不要改):
def build_prompt(task) -> str: # 拼出发给 LLM 的 Prompt
def parse_llm_output(response) -> list: # 从回复里抽出动作序列
def plan_with_llm(task, llm_client): # build -> llm_client.chat() -> parse
调用 LLM 只需一行:response = llm_client.chat(prompt)。写好 Prompt 的关键:把每个动作的前提条件写进 Prompt;给一个"输入 → 正确输出"的示例(few-shot);要求一行一个动作、只输出动作(不要解释、不要 markdown)。
Q2:让 LLM 写 PDDL,规划器来解
LLM 不直接想答案,只负责把题目"翻译"成 problem.pddl,正确性交给规划器保证。填好 4 个函数:
def build_pddl_prompt(task, domain_pddl) -> str: # 生成 problem.pddl 的 Prompt
def generate_problem_pddl(task, domain_pddl, llm_client): # 调 LLM 并清洗输出
def solve_pddl(domain_path, problem_path) -> list: # 用 pyperplan 求解
def plan_with_llm_pddl(task, domain_path, llm_client): # 串起全流程
一个合法的 problem.pddl 示例(参数用空格分隔,(on A B) ✅ / (on A,B) ❌;所有积木都要写进 :objects;域名固定 blocksworld):
(define (problem task_02)
(:domain blocksworld)
(:objects A B C - block)
(:init (on C A) (ontable A) (ontable B) (clear C) (clear B) (handempty))
(:goal (and (on A B) (on B C) (ontable C))))
怎么跑
在 student/ 目录下:
# 调试单个任务
python run_q1.py --task tasks/public/task_01.json
python run_q2.py --task tasks/public/task_02.json
# 一键自测全部 25 个任务,生成 results.json(提交用)
python evaluate.py --output results.json
开发节奏:先用公开任务跑通流程 → 改 Prompt 提高通过率 → 最后攻克"只有自然语言"的任务。
🌟 附加题(3 分):用世界模型做规划
本项目里 LLM 是在符号层上规划(谓词 / PDDL)。附加题让你换一个视角:直接在像素/状态空间里用一个"世界模型"(World Model)做规划,体会基于学习的规划与符号规划的差别。
任务:部署 LeWorldModel(LeWM)环境,加载老师提供的预训练权重,在 TwoRoom 任务上跑通评估流程(基于世界模型的 MPC 规划 + 成功率指标)。无需训练模型,有 GPU 用 GPU,没 GPU 用 CPU 也能跑通。
- 代码与详细步骤:lewm_challenge.zip,解压后阅读其中的
LEWM_GUIDE.md。 - 模型权重与数据集:tworoom_student_data.zip,按
LEWM_GUIDE.md解压到仓库内data/即可,无需自己下载或训练。
通过标准: 终端打印出 success_rate,并在 data/tworoom/ 下生成结果文件与可视化视频 env_*.mp4,即视为跑通。
附加题提交(并入实验报告或单独附页):①运行截图(含 success_rate 那一行);②结果文件 tworoom(_cpu)_results.txt;③任意一个 env_*.mp4;④一段简短说明:部署步骤、遇到的问题及解决,以及你对"世界模型 + MPC 规划"与本项目"LLM + 符号规划"两种思路的对比理解。
代码提交与评分
将以下内容打包为 学号_姓名.zip 提交(细节见 STUDENT_GUIDE.md 第 7 节):my_planner/(两个 .py + prompt 模板)、evaluate.py 跑出的 results.json、以及 实验报告.pdf。
学号_姓名.zip
│
├── my_planner/
│ ├── q1_llm_prompt_planner.py
│ ├── q2_llm_pddl_planner.py
│ └── prompt_templates/
├── results.json
└── 实验报告.pdf
报告建议包含:Q1/Q2 各自的 Prompt 设计、25 个任务的结果表、2–3 个失败案例分析、Q1 vs Q2 对比、总结。
| 评分模块 | 分值 |
|---|---|
| Q1 Prompt 规划 | 25 |
| Q2 LLM + PDDL | 30 |
| 接口规范(不改教师代码、不硬编码) | 15 |
| 实验分析(对比 + 失败诊断) | 20 |
| 报告质量 | 10 |
| 小计 | 100 |
| 🌟 附加题:LeWM 世界模型评估 | +3 |
附加题为加分项,与日常课堂问答加分累计计算,一共不超过3分,不做附加题不影响主项目满分。
注意: results.json 必须由 evaluate.py 生成,不要手动编辑。教师会用相同的 LLM 后端重新评测以验证结果真实性;如发现硬编码答案或结果造假,按学术不端处理。
致谢
本项目积木世界规划部分参考了经典 Blocksworld / PDDL 教学设计;附加题基于 LeWorldModel(LeWM)及 stable-worldmodel 相关工作改写,所有使用及改写均遵循相关协议。感谢相关社区的贡献。