一句话总结:NSI 把 agent 走过的轨迹「提升」成带 if/while 控制流的逻辑程序,再用反思式规划让这些技能图在部署时自我修复——把每次运行时失败,永久变成一条新的逻辑分支。
长程 agentic 任务上,基础模型反复栽在同一个地方:它能当场推理出一条路径,但这种推理是「一次性」的,做完就蒸发,下一次遇到几乎一样的任务还得从头想一遍。本文要读的这篇论文,给出的不是「更强的 prompt」,而是一种把经验固化成可执行逻辑的机制。
论文基本信息
- 标题:Lifting Traces to Logic: Programmatic Skill Induction with Neuro-Symbolic Learning for Long-Horizon Agentic Tasks
- arXiv:2605.01293
- 作者:Jie-Jing Shao 等 8 人(南京大学 / A*STAR 相关团队)
- 关键词:Neuro-Symbolic Learning、Skill Induction、Long-Horizon Agent、Control Flow Synthesis、Reflective Planning
- 方法简称:NSI(Neuro-Symbolic Skill Induction)
核心问题:瞬态推理 + 状态无关脚本
要理解 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 提议):LLM 凭语言理解和常识,提出候选的控制流结构、可能的分支条件、变量该绑定到哪个观测量。这一步需要的是灵活的、开放域的猜测能力。
- 符号(程序化逻辑):提议被组织进一张可执行、可组合、可验证的技能图(skill graph)。图结构提供了硬约束——它能被严格执行、能复用、能在出错时精确定位到某个节点。
LLM 负责想,符号结构负责管住。这是 NSI 比纯神经方案稳、比纯符号方案灵活的根本原因。
Reflective Planning:让技能图自我生长
NSI 最有工程味道的部分,是反思式规划(Reflective Planning)。
归纳出的技能图不是一次成型、此后不变的死物。在部署阶段,agent 自主地修复并生长这些技能图:
- 执行技能图,走到某个节点时执行失败;
- agent 不是简单重试(重试对线性脚本无效),而是定位失败的逻辑节点,分析失败的状态条件;
- 合成一条新的分支或条件,把这个之前没覆盖到的情形吸收进来;
- 把改进永久写回技能图。
于是机制变成了:失败一次,逻辑就补一次,下次不再犯。 运行时的每一次失败,都不再是白白损失的一个 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) | 文本合成游戏,需满足前置依赖逐级合成 |
对比的基线覆盖了几条主流技术路线:
- ReAct:纯 prompting 的推理—行动交替,瞬态推理的代表;
- Reflexion:带自我反思的口头反馈,但反思仍是文本记忆、未结构化为可执行逻辑;
- AWM(Agent Workflow Memory):归纳工作流记忆的代表;
- ASI:状态相关技能归纳的相关工作。
结论是:NSI 在三个环境上均显著超越上述 SOTA 基线。 按论文的定性描述,它的优势体现在几个方面:
- few-shot 归纳:只需少量示例就能归纳出可用的技能图,不依赖海量轨迹;
- 对未见目标的灵活适配:技能图的控制流让它能泛化到归纳时没见过的目标(unseen goals);
- 压缩规划视野:复用结构化技能后,agent 不必每步从零推理,长程任务的有效规划视野被显著压缩;
- 高效泛化:跨具身 / 网页 / 游戏三类域都成立,说明方法不是对某个环境过拟合。
⚠️ 说明:本文不给出精确 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 一遍遍重新想同一件事——把它想明白的逻辑,编译成程序存下来,并让失败成为下一次的分支。