Paper

把轨迹提升为逻辑:NSI 用神经符号学习归纳可执行技能

8 min read ·

一句话总结:NSI 把 agent 走过的轨迹「提升」成带 if/while 控制流的逻辑程序,再用反思式规划让这些技能图在部署时自我修复——把每次运行时失败,永久变成一条新的逻辑分支。

长程 agentic 任务上,基础模型反复栽在同一个地方:它能当场推理出一条路径,但这种推理是「一次性」的,做完就蒸发,下一次遇到几乎一样的任务还得从头想一遍。本文要读的这篇论文,给出的不是「更强的 prompt」,而是一种把经验固化成可执行逻辑的机制。

论文基本信息

核心问题:瞬态推理 + 状态无关脚本

要理解 NSI,先得看清它对准的两个老毛病。

第一个毛病是瞬态推理(transient reasoning)。 纯 prompting 的 agent(典型如 ReAct)在每个 step 让 LLM 现场「想」下一步该做什么。这套推理过程不会被保存下来——它存在于一次前向传播里,输出动作之后就消散了。结果就是,agent 在 100 个相似任务上,会把同一个推理重新做 100 遍。长程任务里 step 数动辄几十上百,瞬态推理意味着规划视野(planning horizon)始终压不下来,错误也容易在长链条里累积放大。

第二个毛病出在「修补」方案本身。 业界早就想到要把经验沉淀下来,于是有了技能归纳(skill induction):把成功的轨迹蒸馏成可复用的「技能」。但主流做法蒸馏出的是状态无关的参数化脚本(state-blind parameterized scripts)——本质是一串固定动作序列,外加几个可替换的参数槽。

这种脚本的致命缺陷是:它假设世界永远沿着归纳时见过的那条路径展开。可现实是,长程环境充满了分叉。要找的物品不在预想的抽屉里、网页上目标商品缺货、合成某个道具前缺了前置材料……线性脚本没有「如果……那么……」的能力,状态一偏离,它就直接执行到错误的动作上,然后崩溃。

💡 关键洞察:鲁棒执行需要的是条件逻辑(conditional logic),而不是更长的动作序列。一个能根据当前状态分支的小程序,远比一条死板的长脚本可靠。

NSI 方法:把轨迹提升为逻辑程序

NSI 的核心动作,论文用了一个很准的词——lift(提升)。它把底层的交互轨迹(interaction traces),提升为高层的、模块化的、逻辑接地(logic-grounded)的程序。

这个「提升」具体合成两样东西:

1. 显式控制流(control flow)。 NSI 不再把轨迹看成一条直线,而是从多条轨迹里归纳出 if / while / 分支结构。比如观察到「物品有时在桌上、有时在抽屉里」,它就合成一个 if 物品在桌上 then 直接拿 else 去抽屉找 的分支,而不是赌它一定在某处。

2. 动态变量绑定(dynamic variable binding)。 脚本里的变量不再是归纳时写死的常量,而是在运行时根据观测动态绑定。target_location 不是「抽屉 3」,而是「当前观测中检测到目标物品的那个容器」。

二者合起来,让技能从「做什么」(what)升级为「何时做、为什么做」(when & why)。这正是状态无关脚本永远给不出的东西。

而「神经符号」这个名字,对应的是提议与固化的分工:

LLM 负责想,符号结构负责管住。这是 NSI 比纯神经方案稳、比纯符号方案灵活的根本原因。

Reflective Planning:让技能图自我生长

NSI 最有工程味道的部分,是反思式规划(Reflective Planning)

归纳出的技能图不是一次成型、此后不变的死物。在部署阶段,agent 自主地修复并生长这些技能图:

  1. 执行技能图,走到某个节点时执行失败
  2. agent 不是简单重试(重试对线性脚本无效),而是定位失败的逻辑节点,分析失败的状态条件;
  3. 合成一条新的分支或条件,把这个之前没覆盖到的情形吸收进来;
  4. 把改进永久写回技能图。

于是机制变成了:失败一次,逻辑就补一次,下次不再犯。 运行时的每一次失败,都不再是白白损失的一个 episode,而是被转化为技能图上一条永久的逻辑改进。技能图随着部署使用越来越完备,覆盖的边界情况越来越多。

这与瞬态推理形成了鲜明对照:ReAct 式 agent 每次失败学不到任何可沉淀的东西;NSI 把失败变成了资产。

伪代码对比:线性脚本 vs 逻辑图

为了让差异更直观,下面用 ALFWorld 风格的「把某物加热后放到指定位置」任务,对比两种归纳产物。

传统 skill induction 产出的线性脚本:

# 状态无关的参数化脚本:直来直去,赌环境按归纳路径展开
def heat_and_place(obj, target):
    go_to("countertop")        # 赌 obj 在 countertop 上
    take(obj)
    go_to("microwave")
    open("microwave")
    put(obj, "microwave")
    toggle("microwave")        # 加热
    take(obj)
    go_to(target)
    put(obj, target)
    # 一旦 obj 不在 countertop、或 microwave 被占用 -> 直接崩溃

NSI 提升后的带控制流逻辑图(伪代码):

# 逻辑接地的技能程序:带控制流 + 动态变量绑定
def heat_and_place(obj, target):
    # 动态变量绑定:运行时定位 obj,而非写死位置
    loc = find_location(obj)              # 扫描观测,绑定 obj 当前所在容器
    if loc is None:
        loc = search_containers(obj)      # 控制流:找不到就逐个容器搜索
    go_to(loc); take(obj)

    # 控制流:选一个可用的加热器
    heater = first_available(["microwave", "stoveburner"])
    if is_closed(heater):
        open(heater)                      # 条件:关着才开
    put(obj, heater); toggle(heater)
    wait_until(state(obj) == "hot")       # while 循环式等待,而非固定步数
    take(obj)

    # 反思式规划在此处补丁:若 target 满了,先腾位
    if is_full(target):
        clear_one_slot(target)            # 这条分支来自上一次的运行时失败
    go_to(target); put(obj, target)

差别一目了然:线性脚本把每个假设都写死成「赌」;NSI 程序把每个假设都变成可分支、可绑定、可补丁的逻辑节点。注释里标出的 clear_one_slot 那条分支,正是反思式规划把一次「目标位置已满」的运行时失败,固化成的永久逻辑。

实验与结果

论文在三个跨域环境上验证 NSI,刻意覆盖了差异极大的任务类型:

环境域类型任务特征
ALFWorld具身(embodied)文本化的家务,需多步导航与物体操作
WebShop网页(web)模拟网购,需理解页面、搜索、筛选、下单
TextCraft游戏(game)文本合成游戏,需满足前置依赖逐级合成

对比的基线覆盖了几条主流技术路线:

结论是:NSI 在三个环境上均显著超越上述 SOTA 基线。 按论文的定性描述,它的优势体现在几个方面:

⚠️ 说明:本文不给出精确 benchmark 百分比,论文以「显著超越」等定性结论为主。重点不在某个绝对分数,而在「带控制流的逻辑图」这条路线相对「线性脚本」的系统性优势。

工程意义:对 agent 开发者意味着什么

把这篇论文翻译成工程语言,有几条值得落到实际系统里:

1. 别把技能存成「动作录像」,要存成「程序」。 很多团队做 agent 记忆 / workflow 复用时,存的是成功轨迹的回放或参数化模板。NSI 提醒我们:这类产物天然脆。值得投入的方向是把轨迹编译成带分支的小程序,哪怕只是简单的 if/while,鲁棒性也会有质变。

2. 失败应该是可沉淀的资产,而不是被丢弃的 episode。 反思式规划的工程价值在于:给 agent 一个明确的「失败 → 定位节点 → 合成补丁 → 写回」回路。生产系统里完全可以借鉴——把线上 agent 的失败 case 结构化地回写进技能库,而不是只记一条日志。

3. 神经符号分工是控制 LLM 不确定性的实用手段。 让 LLM 只负责「提议」结构,再用可执行、可验证的符号骨架去约束和固化,是在保留灵活性的同时压住幻觉与不稳定性的务实做法。这条思路不止适用于技能归纳,对任何需要 LLM 生成结构化产物的场景都成立。

4. 压缩规划视野直接关系到成本与延迟。 长程任务里每个 step 都要调一次大模型,token 与延迟成本随视野线性增长。把可复用部分固化成技能图、让 agent 跳过重复推理,是实打实的降本路径。

小结

NSI 的贡献,可以浓缩成一次「提升」和一个「回路」。

「提升」是把交互轨迹从线性动作序列,提升为带显式控制流和动态变量绑定的逻辑程序——这一步解决了状态无关脚本的脆弱性,让技能知道何时、为什么行动。「回路」是反思式规划,让技能图在部署时自主修复、持续生长,把运行时失败永久转化为逻辑改进。

在 ALFWorld、WebShop、TextCraft 三个跨域环境上超越 ReAct、Reflexion、AWM、ASI 等基线,证明了「神经提议 + 符号固化」这条路线对长程 agentic 任务的价值。对 agent 开发者而言,最值得带走的一句话是:别让 agent 一遍遍重新想同一件事——把它想明白的逻辑,编译成程序存下来,并让失败成为下一次的分支。

Frequently asked questions

NSI 解决的核心问题是什么?
基础模型驱动的 agent 在长程任务上的推理是瞬态的——靠 prompt 当场推理,做完就忘,无法沉淀。已有的技能归纳方法虽然能蒸馏经验,但产出的是状态无关的线性脚本,捕捉不到鲁棒执行所需的条件逻辑。NSI 把轨迹提升为带控制流的逻辑程序,让 agent 学会何时、为什么行动。
什么是状态无关的参数化脚本,为什么它不够用?
传统 skill induction 把成功轨迹抽象成一串固定的动作序列,只做参数替换(比如把具体物品名换成变量)。它假设环境永远按同一条路径展开,一旦真实状态偏离预期(物品不在预想的位置、页面结构变了),脚本没有分支能力就直接崩溃。NSI 用 if/while 显式编码这些条件逻辑。
Reflective Planning 反思式规划是怎么工作的?
agent 在部署时执行技能图,一旦某条路径执行失败,它不是简单重试,而是定位失败的逻辑节点,合成新的分支或条件把这个失败情形覆盖掉,永久写回技能图。这样失败一次、逻辑补一次,技能图随使用不断生长,下次遇到同类情形就不再犯错。
NSI 为什么叫神经符号方法?
神经部分是 LLM,负责提议候选的控制流结构、变量绑定和分支条件——它有常识和语言理解能力。符号部分是程序化的逻辑图本身,提供可执行、可验证、可组合的结构化骨架。LLM 提议,符号结构约束并固化,二者结合既灵活又稳定。
NSI 在哪些环境上验证,对比了哪些基线?
在 ALFWorld(具身家务)、WebShop(网页购物)、TextCraft(文本游戏合成)三个跨域环境上验证,覆盖具身、网页、游戏三类任务。对比了 ReAct、Reflexion、AWM、ASI 等 SOTA 基线,NSI 在这些环境上均显著超越,并展现出 few-shot 归纳和对未见目标的灵活适配能力。
// next.txt ›

Some outbound links in this post are affiliate links — see disclosure.