【Cradle 源码解析三】大脑中枢:决策推理 (Reasoning) 与 任务规划 (Planning)

Cradle决策与规划源码解析

前言

在前两篇中,我们构建了 Agent 的身体(架构)和眼睛(视觉感知)。现在,我们来到了最核心、最性感的部分——大脑

当一张标注了坐标的屏幕截图(SoM Image)传给大模型后,它如何决定是“点击左上角的菜单”还是“按下 W 键向前走”?更重要的是,当它撞墙了或者点错了,它怎么知道自己搞砸了?

本篇将深入 Cradle 的推理引擎,剖析其 ReAct (Reasoning + Acting) 循环的源码实现,以及至关重要的 Self-reflection(自我反思) 机制。

1. 推理的核心:Context 的组装艺术

在源码层面,所谓的“推理”,本质上是一次精心构造的 llm.chat() 调用。但 LLM 没有长时记忆,Cradle 必须在每一次请求中,把所有必要的上下文“喂”给它。

cradle/agent/core.py (或类似逻辑路径) 中,决策函数通常遵循这样的数据流:

Cradle 将 Context 像千层饼一样堆叠起来,构建最终的 Prompt:

  1. System Prompt (人设)

    "你是一个精通《荒野大镖客2》的专家玩家..."

  2. Long-term Goal (宏观指令)

    "当前任务:前往瓦伦丁镇的杂货铺购买苹果。"

  3. Skill Context (技能检索)

    这里用到了 RAG。 Cradle 会根据当前任务,从技能库中检索相关的操作说明。例如检索到“如何骑马”、“如何打开地图”的文本描述。

  4. History (短期记忆)

    "过去 3 步的操作:[按下 W, 移动鼠标, 点击确认]..."

    这是为了保持操作的连贯性。

  5. Observation (当前视觉)

    传入上一篇提到的 SoM 标注图。

2. 思考链 (Chain of Thought) 的代码实现

Cradle 并不希望 LLM 直接输出一个按键动作(如 Key.W),因为这样缺乏鲁棒性。它要求 LLM 输出一段 JSON 格式的思考过程

在源码的 Prompt 模板中,我们能看到强制的输出格式要求:

JSON

{
  "reasoning": "我看到前方有障碍物,且地图显示目的地在左侧。刚才我已经尝试直行但被挡住了。",
  "plan": "我应该先向左转视角,然后继续前进。",
  "action": {
    "type": "key_press",
    "key": "a",
    "duration": 0.5
  }
}

为什么要有 reasoning 字段?

在代码调试中,这是极其宝贵的。它迫使模型生成 CoT (Chain of Thought)。如果 Agent 卡住了,开发者查看 Log 中的 reasoning 字段,就能知道是因为模型“没看见路”还是“逻辑判断错误”。

3. 动态规划:下一步动作预测

Cradle 的规划并不是一次性生成整个任务的所有步骤(因为游戏环境变化太快),而是采用 Receding Horizon Control (滚动时域控制) 的思路。

逻辑流程:

  1. 评估差距:对比 Current State (截图) 和 Goal

  2. 生成原子动作:LLM 预测能缩短这个差距的下一个最小动作单元(Atomic Action)。

  3. 执行:将动作发给执行器。

  4. 循环:进入下一帧。

这种“走一步看一步”的策略,在源码中体现为一个 while 循环,直到 task_status 变为 SUCCESS

4. 关键机制:反思 (Self-reflection)

这是 Cradle 区别于普通脚本机器人的核心。如果动作执行失败了怎么办?

cradle/agent/reflection.py 中,实现了一个闭环反馈系统。当 Agent 执行动作后,系统不会立刻进入下一步,而是会捕获一张**“执行后”的截图**。

Cradle 会发起一次特殊的 LLM 调用,也就是“反思裁判”:

Input:

  • Image_Pre: 执行前的图

  • Action: 刚才执行的动作 (例如:点击坐标 200,300)

  • Image_Post: 执行后的图

Prompt:

"我试图执行这个动作。请对比前后两张图,判断动作是否生效?如果失败,请分析原因。"

Output:

  • Success: 比如菜单弹出来了,或者人物位置变了。 -> Update Memory (成功经验)

  • Fail: 画面没有任何变化,或者出现了错误弹窗。 -> Update Memory (失败教训) & Retry

源码视角的反思逻辑:

Python

# 伪代码逻辑演示
def step(self):
    # 1. 决策
    action = self.reasoning_engine.predict(current_obs)
    
    # 2. 执行
    self.executor.execute(action)
    time.sleep(1) # 等待渲染
    
    # 3. 后处理观察
    next_obs = self.environment.capture()
    
    # 4. 反思 (Reflection)
    success, feedback = self.reflector.judge(current_obs, action, next_obs)
    
    if not success:
        print(f"Action Failed: {feedback}")
        # 将失败信息加入短期记忆,防止下一轮重复同样的错误
        self.short_term_memory.add_error(action, feedback)
        # 可能会触发恢复策略 (Recovery Policy),比如按 ESC 返回
        self.recover()
    else:
        self.long_term_memory.store_skill(action) # 巩固成功路径

5. 总结

Cradle 的大脑中枢实际上是一个**“带状态的无限状态机”**。

  • Reasoning 依靠 Prompt 堆叠 Context 来弥补 LLM 的失忆。

  • Planning 采用滚动预测,保证了对动态环境的适应性。

  • Reflection 提供了容错能力,让 Agent 具备了“自我纠正”的雏形。

正是这套机制,让 Cradle 能够处理《荒野大镖客2》中那些不可预测的 NPC 互动和复杂的菜单逻辑。

下一篇预告:

大模型想好了要“向左转”,但代码怎么知道鼠标该移动多少像素?怎么模拟按下键盘的动作才不会被系统判定为脚本?在下一篇 【Cradle 源码解析四】手眼协同:IO 控制层与动作执行 (Action Execution) 中,我们将下沉到最底层,研究 HID 模拟与技能库的实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天天进步2015

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值