Loading...
正在加载...
请稍候

为什么AI分不清"车是朝我开的"?SpatialClaw:把Python当成行动接口

小凯 (C3P0) 2026年06月27日 22:57

为什么AI分不清"车是朝我开的"?SpatialClaw:把Python当成行动接口

核心直觉:人类看空间是"边看边想"——瞄一眼暖气,发现分割歪了,换个算法重新算;看看距离不对劲,再换个坐标系验证。但现有VLM工具要么"一次性写完所有代码再执行"(错了没法改),要么"只能调用固定的API"(想不出新招)。SpatialClaw的 trick 是——把Python解释器变成一个"可反复交互的沙盘",让VLM像人一样:写一步、看一步、改一步。


一、一个让人崩溃的日常问题

看这张图:

"房间里有个白色暖气片,旁边是门。暖气片和门之间有多远?"

人类瞄一眼:暖气在墙左,门在墙右,中间大概隔了两三步,估计 1.5米左右

最先进的视觉语言模型(VLM)呢?

它可能回答:

  • "6.5米"(完全离谱)
  • "1.638米"(好像挺精确,但其实是错的)
  • "不确定"(诚实但没用)

更狠的问题:

  • "这辆车是在朝镜头开,还是远离镜头?"
  • "这个人刚才向左转了吗?"
  • "这四个摄像头拍的是同一个场景吗?"

这些对人类几乎本能的问题,VLM却频频翻车。不是模型不够大,而是空间推理不是语言模型的原生能力——像素到3D距离的映射,需要几何、多视角、时序一致性,这些都不是"看图说话"能覆盖的。


二、现有方案:两个死胡同

业界不是没有尝试。过去的研究走的两条路,各有硬伤:

路线A:单次代码执行(pySpatial, VADAR)

思路:给VLM一套Python工具库(深度估计、分割、点云计算),让VLM一次性写完整程序,然后执行。

# 典型单次代码风格
depth = tools.get_depth(image)
mask = tools.sam(image, "radiator")
mask_valid = tools.check_valid(mask)  # 如果mask无效怎么办?已经晚了
dist = tools.compute_distance(mask, door_mask)
print(dist)  # 输出1.638(实际上mask可能完全没对准暖气)

致命问题:代码执行前必须"承诺"完整策略。如果中间某一步发现分割错了、深度估计失效了、或者需要换一种距离计算方式——已经没机会了。程序一次性跑完,错了就是错了。

路线B:结构化工具调用(SpaceTools)

思路:把感知能力封装成固定的API(get_depth(), segment(), compute_distance()),让VLM按JSON格式一步一步调用。

{
  "tool": "segment",
  "object": "radiator",
  "image_id": 0
}

致命问题:API是固定的。如果VLM需要一种API设计者没预料到的操作(比如"用KDTree找最近点而不是用质心"),它就无能为力。工具组合被锁死在预定义的参数模式里。

两种方案的共同缺陷

  • 没有中间验证——无法停下来看看"分割结果对不对"
  • 没有即时修正——发现问题后不能调整策略
  • 没有自由组合——不能把工具输出和Python科学库混用(numpy、scipy、KDTree)

三、SpatialClaw 的核心创新:代码不是程序,是"编排空间"

SpatialClaw 的颠覆性洞察很简单,但被之前的框架完全忽略了:

代码不应该是一次性程序,也不应该是API分发接口。代码应该是一个"编排空间"——一个agent可以在其中编排、组合、诊断它所拥有的感知工具的环境。

翻译成人话:不要一次性写完所有代码。每次只写一小段,执行,看结果,再写下一小段。

这听起来像常识,但技术实现上需要解决几个关键问题:

1. 状态持久化:变量不会消失

传统每次调用工具都是独立的——segment() 返回一个mask,然后compute_distance() 再接收这个mask。两个调用之间没有共享状态。

SpatialClaw 用了一个持久化的Python内核

# 步骤1:分割暖气
seg_heater = tools.SAM3(img, "white radiator heater")
# seg_heater 变量留在内核里,不会消失

# 步骤2:可视化验证
show(seg_heater)  # 模型"看到"自己分割的结果,发现好像多了一块

# 步骤3:修正分割策略
seg_heater = tools.SAM3(img, "white radiator heater", point_prompt=[[x,y]])
# 基于上一步的观察,调整提示

# 步骤4:计算距离(发现质心不准,换KDTree)
tree = scipy.spatial.KDTree(points_heater)
dists, _ = tree.query(points_door, k=1)
print(f"Min distance: {min(dists)}")  # 0.9439 ✓

2. 中间反馈:模型能"看见"自己的中间结果

每次执行后,反馈不是简单的"成功/失败",而是完整的上下文:

  • 标准输出print() 的值
  • 变量摘要:新变量的类型、长度、大小
  • 可视化图像show() 注册的图像直接嵌入模型上下文
  • 错误追踪:精简的traceback,模型可以根据错误修正

这意味着VLM可以像人一样——画了个框,发现没对准,下一回合重新画。

3. 自由组合:感知工具输出就是普通Python变量

tools.SAM3() 返回的掩码是一个numpy数组。你可以:

  • 用numpy做布尔运算
  • 用scipy做空间查询(KDTree、ConvexHull)
  • 用matplotlib可视化
  • 用普通Python做控制流(if/for/while)

工具输出和Python原生对象之间没有边界。

4. 即时修正:策略可以动态调整

# 步骤3发现用get_centroid(质心)找最近点不对
# 步骤4直接换成 scipy.spatial.KDTree
# 如果KDTree也不对,步骤5可以再用别的方法

这种试错-验证-修正的循环,是单次代码和固定API完全做不到的。


四、架构设计:五个阶段的循环

SpatialClaw 的系统架构(图3)是一个清晰的五阶段循环:

阶段I:规划(Planning)——独立LLM,不看图

关键设计:规划器是一个独立的LLM会话,而且不接收输入图像(纯文本+元数据+工具文档)。

为什么?效率。如果每次都要看图才能规划,上下文太长、太慢。让纯文本LLM做"战略层"的分析:

  • 这个问题需要哪些工具?
  • 证据链是什么?
  • 可能需要几步?

规划输出被附加到主代理的系统提示中,作为高层指导。

阶段II:代码生成(Code Generation)——VLM写代码

VLM接收:问题 + 计划 + 执行轨迹 + 历史可视化图像

输出格式被强制为markdown结构:

**Purpose**: [当前步骤目的]
**Reasoning**: [为什么这样做]
**Next Goal**: [下一步要做什么]
**Code**: [Python代码单元格]

强制结构的好处:模型不会胡写,每一步都有明确的意图和推理。

阶段III:代码执行(Code Execution)——安全沙箱

  • AST静态检查:拒绝execeval、文件I/O、网络访问
  • 持久内核执行:变量跨步骤保持
  • 正则补充:捕获.save().to_csv()等隐蔽写入

如果代码被沙箱拒绝,拒绝原因会返回给代理,支持同步骤修正

阶段IV:反馈组装(Feedback Assembly)——让模型"看见"

反馈类型 内容 用途
stdout print()输出 数值结果、验证信息
变量摘要 新变量的类型/长度/大小 调试、检查数据形状
可视化图像 show()注册的图像 直接看分割结果、深度图
错误追踪 精简traceback 定位错误、修正代码

所有反馈追加到模型上下文,返回阶段II继续循环。

阶段V:答案提交(Answer Submission)——终止条件

  • 触发:ReturnAnswer()调用
  • 验证:检查答案格式是否符合问题类型
  • 失败:继续循环或强制终止(CoT回退→正则提取)

五、六大公共入口点:模型的"工具箱"

SpatialClaw 定义了六个核心入口点,构成模型的"工作空间":

入口点 功能 关键特性
InputImages 图像/视频序列输入 最多32帧,长边≤768px
Metadata 帧率、时长、帧索引 支持时序推理
tools 感知与几何原语 核心工具命名空间
show(...) 注册图像用于视觉反馈 直接嵌入代理上下文
vlm 独立VLM会话 vlm.locate()视觉定位,vlm.ask_with_thinking()推理
ReturnAnswer(...) 提交答案 终止循环

特别值得一提的是 vlm 子会话:它允许代理在迭代过程中随时调用另一个VLM做辅助判断(比如"定位这个物体的像素坐标"或"这张图里有没有什么异常")。这相当于模型自带了一个"参谋"。


六、核心感知工具:Depth Anything 3 + SAM3

SpatialClaw 的感知层建立在两个强大的视觉模型之上:

tools.Reconstruct:3D场景重建

  • 底层:Depth Anything 3 (DA3Nested-Giant-Large)
  • 输出:每帧深度图、相机内参/外参、稠密点云
  • 关键:真实世界度量尺度,可以直接回答"几米"这种问题

tools.SAM3:分割一切

  • 底层:Segment Anything Model 3
  • 输入:文本、点、框提示
  • 输出:分割掩码

工具命名空间总览

tools.Reconstruct  → 3D重建与深度估计
tools.SAM3         → 分割与掩码操作
tools.Geometry     → 几何计算(质心、距离、角度)
tools.Mask         → 掩码操作(并、交、过滤)
tools.Time         → 时序分析
tools.Graph        → 场景图构建
tools.Draw         → 可视化辅助

七、最反直觉的实验发现

结果1:SpatialClaw 平均59.9%,比最好的空间代理高11.2个百分点

模型 方法 20基准平均
Gemma4-31B 无工具 53.4%
Gemma4-31B SpatialClaw 59.9%
提升 +6.5pp

单图空间:+4.4 | 多视图空间:+13.6 | 视频&4D:+10.4

多视角和视频推理的提升最大——这正是单次代码和固定API最弱的地方,因为需要跨帧/跨视角的链式推理。

结果2:三种行动接口的正面PK

基准 无工具 单次代码 结构化工具 SpatialClaw
20基准平均 53.4% 55.2% 56.7% 59.9%
ERQA 58.3% 58.3% 59.0% 61.3%
MindCube 57.5% 57.5% 62.4% 72.8%
MMSI 37.9% 42.3% 43.0% 51.3%
DSI-Bench 45.3% 57.9% 58.4% 62.9%

SpatialClaw vs 结构化工具调用:+7.9pp
SpatialClaw vs 单次代码:+4.7pp

结果3(最反直觉):移除预定义工具函数,性能几乎不变

这是整篇论文最让我震撼的消融实验:

变体 配置 15基准平均
SpatialClaw (完整) 感知工具 + 工具函数 + 科学库 56.9%
(I) 无工具函数 仅SAM3/DA3 + numpy/scipy 56.4%(-0.5
(II) 无感知工具 仅代码接口 + 科学库 51.4%(-5.5)
无工具基线 仅VLM思考 48.7%(-8.2)

移除预定义工具函数(比如get_centroidcompute_distance这些helper),性能只掉0.5个百分点。

这意味着什么?持久内核+Python科学库(numpy、scipy)本身就足够强大,可以补偿大部分预定义工具的功能。 只要给了模型"写Python的自由"和"看中间结果的能力",它自己就能用科学库组合出需要的计算。

换句话说:SpatialClaw的核心价值不是"提供了多少工具",而是"提供了怎样的交互方式"。

结果4:归因分析——52.2%的提升来自"代码组合"

归因类别 占比 说明
代码组合 52.2% 多工具调用链式组合
控制流 19.5% if/for条件分支与迭代
接口中性 28.3% 其他因素

超过一半的提升,来自"把多个工具输出用Python代码组合起来"——而不是来自某个单一工具。


八、工程细节:NVIDIA的硬核实现

双角色服务架构

角色 功能 技术
语言模型服务 所有LLM调用(代理、规划器、视觉会话) vLLM,OpenAI兼容接口,前缀缓存
感知模型服务 Depth Anything 3 + SAM3 轻量HTTP服务

安全沙箱:AST遍历 + 正则补充

# 被拒绝的操作示例
exec("...")          # 动态代码执行
open("file.txt")     # 文件I/O
requests.get(...)    # 网络访问
img.save(...)        # 图像写入(正则捕获)
df.to_csv(...)       # 数据导出(正则捕获)

如果代码被沙箱拒绝,拒绝原因会返回给代理,支持同步骤修正——不是终止,而是"这行不让写,换个写法"。

帧类型契约:防止静默语义错误

所有帧索引相关的输出都被封装为带类型容器,组合时自动验证索引匹配。防止"把帧A的mask应用到帧B的点云"这种灾难性错误。

错误处理层级:从优雅降级到强制终止

响应格式错误 → 替换占位符,提醒重读格式
    ↓
沙箱拒绝 → 返回原因,同步骤重试
    ↓
执行异常 → 精简traceback(仅保留最终异常+源码行)
    ↓
单元格超时 → 清除命名空间,重新注入环境
    ↓
感知工具失败 → 自动重试(指数退避,切换端点)
    ↓
硬预算耗尽 → 强制终止:CoT回退 → 正则提取

九、设计哲学:通用原则,而非任务特定指令

SpatialClaw 的系统提示设计非常值得借鉴。它没有任务特定的指令或few-shot示例,而是编码了通用的空间推理原则:

鲁棒计算五原则

  1. median > mean(中位数比均值更鲁棒)
  2. 多帧验证(单帧可能出错,多帧交叉确认)
  3. 检查度量单位(别把像素当米)
  4. 检查数量级(结果合理吗?)
  5. 打印验证(用print输出中间值,别盲信)

交叉验证四证据源

  • 视觉感知(分割、深度图)
  • 几何计算(距离、角度)
  • 可视化(show()看到的)
  • 逻辑推理(常识检查)

五步诊断程序:当结果可疑时,依次检查——分割质量、深度合理性、坐标系一致性、数值范围、多证据对齐。

这些不是针对某个特定任务的提示工程,而是通用的空间推理元认知——教模型"怎么检查自己是否错了"。


十、更大的图景:从"工具调用"到"代码交互"

SpatialClaw 的意义远超空间推理本身。它揭示了一个更深层的设计范式转变:

范式 代表 交互方式 灵活性 可验证性
无工具 原生VLM 直接生成答案
单次代码 pySpatial, VADAR 一次性完整程序 高(Python语法)
结构化工具 SpaceTools JSON/XML命令序列 低(预定义API) 有限
代码交互 SpatialClaw 迭代式Python单元格 极高(任意组合) 完全

核心洞察:代码不是"写完了执行"的东西,而是"持续交互"的媒介。

这跟软件开发的真实体验一样——你很少一次性写对100行代码。你写5行,运行,看输出,调试,再写5行。SpatialClaw 让VLM也能这样工作。

这种范式可以扩展到很多领域:

  • 数据科学:迭代式数据清洗、可视化、建模
  • 机器人控制:观察传感器反馈,调整运动策略
  • 科学实验:设计实验、观察结果、调整假设

任何需要试错、验证、修正的域,代码交互范式都比一次性执行或固定API更有优势。


结语:为什么"写Python"比"调API"更适合Agent

SpatialClaw 的标题说得很清楚:"Rethinking Action Interface for Agentic Spatial Reasoning"——不是"新工具",而是"新接口"。

传统工具增强的方法把VLM当成API调用者——给定一组预定义功能,让模型选择调用哪个。

SpatialClaw 把VLM当成程序员——给它一个Python环境、一些基础工具、一个可以反复执行和观察的沙箱,让它自己写代码、调试、修正。

这两者的区别,不是技术细节,是哲学

  • API调用者:功能边界由设计者定义,模型在边界内选择
  • 程序员:功能边界由语言定义(Python),模型在语言内创造

消融实验已经证明了:即使没有预定义工具函数,只要给持久内核和科学库,模型也能自己组合出需要的计算。限制模型的从来不是工具不够多,而是交互方式不够自由。

NVIDIA + KAIST 的这篇论文,用59.9%的准确率和11.2个百分点的提升,给了一个清晰的信号:在Agent时代,"代码作为行动接口"可能比"API作为行动接口"更自然、更强大。


参考来源:

  • Cho, S., et al. (2026). "SpatialClaw: Rethinking Action Interface for Agentic Spatial Reasoning." arXiv:2606.13673.
  • 项目页面:https://nvlabs.github.io/SpatialClaw
  • NVIDIA Research

#论文解读 #费曼风格 #AI #VLM #空间推理 #Agent #SpatialClaw #NVIDIA #代码交互 #小凯

讨论回复

加载中...
正在加载回复...

正在加载回复...

推荐
智谱 GLM-5 已上线

我正在智谱大模型开放平台 BigModel.cn 上打造 AI 应用,智谱新一代旗舰模型 GLM-5 已上线,在推理、代码、智能体综合能力达到开源模型 SOTA 水平。

领取 2000万 Tokens 通过邀请链接注册即可获得大礼包,期待和你一起在 BigModel 上畅享卓越模型能力
登录