LXB-Framework: 通过先路由后执行(Route-Then-Act)的一次Mobile Agent降本增效的尝试

18 阅读10分钟

去年12月9日,智谱开源了AutoGLM,那天我特别兴奋。在我的想象中,Agent 应该是极其轻便且无处不在的:无论我身处何地,只要拿起手机输入指令,它就能在云端帮我精准执行任务,这种"指点江山"的感觉真的很酷。

但当我深入研究项目后,发现AutoGLM的底层是ADB,这在局域网或USB连接下表现完美,但对我这种没有公网IP、没有稳定服务器的学生党来说,远程部署成了难题。我思考能不能用内网穿透,如果换成对NAT穿透更友好的UDP,稳定性会不会好一点?

那阵子正赶上期末周,复习间隙,这些技术细节一直在脑子里转。或许是觉得纯粹端到端的架构显得有些"单薄",更复杂的架构显得更酷,某个下午,我突然进入了一种奇妙的"心流"状态:

我开始反思:每一帧页面都交给大模型做视觉分析和决策,真的最优吗?在那些逻辑确定的路径上,我们是否可以引入一些确定性的程序来分担大模型的压力,从而换取更高的精度和更低的开销?如果真的要换UDP,我这半吊子的技术储备又该如何去实现?

想得越多,坑就显得越深。最后我冒出了一个现在看来可能有些"自以为是"的念头:与其在别人的地基上修修补补,不如尝试从零开始,按自己的理解去搭一套架构试试?于是我寒假就尝试按自己的想法 Vibe Coding 了一下。


从一个问题出发——为什么要现场发挥?

整个项目其实源于一个很朴素的观察:

Agent执行某个任务的过程实际上就是先页面跳转,再执行任务。 纯 VLM 方案在每一步都截图、发请求、等响应,每一跳都要 2-5 秒,还可能在中间某步判断失误,或者点歪了,整条链路就断了。

如果导航路径是可以预先知道的,为什么每次都要让大模型"现场发挥"?就像人一样,我们对熟悉的软件,其实并不用每次都观察 “我要点朋友圈,要怎么点”,基本都是肌肉记忆。那么有没有办法也让架构拥有“肌肉记忆”?

这个问题促使我设计了 LXB 的核心思路:Route-Then-Act(先规划路线,再执行任务)


LXB 是什么

LXB 是一个跨设备手机自动化框架,核心思想是把手机自动化拆成两个阶段:

  • 路由阶段:用预先建好的导航图,通过 BFS 找到目标页面的路径,然后确定性地一步步点过去——全程零大模型调用
  • 执行阶段:到了目标页面,再召唤 VLM 来分析页面内容、执行具体任务

architecture.svg

三个技术模块

1. 自动建图:Node-Driven Exploration

在路由之前,得先有图。建图这件事听起来简单,但有个很实际的问题:

淘宝这类 App,许多页面其实共用一个 Android Activity。 传统的"页面指纹"方案(用页面截图或 Activity 名称做唯一标识)在这里会失效,因为动态内容太多了,且导航栏又是一样的,找不出合适的页面指纹构建方法(或许有办法,只是我不知道)。

LXB 的解法是换一个"驱动实体":不以页面状态为 BFS 队列的驱动单元,而以 UI 节点(导航元素本身) 为单元。每次从队列里取出一个未访问的导航节点,从主页回放路径点击它,记录到达的新页面,再把新页面上发现的导航元素入队。页面是点击节点的副产品,产出UI背后页面的语义描述和拥有功能,而不是探索的目标。我们不关注 “我现在在哪个页面” ,而是关注 “我要到这个页面要点什么节点”

这样就彻底避开了"页面指纹是否可靠"的问题:只要能够见节点全局唯一的locator,就可以用节点的唯一性替代页面指纹

建图过程演示:

map_building (speed x 5).gif

图可视化演示:

map_visualization.gif


2. 可靠定位:VLM-XML Fusion

建图过程中,如何可靠地识别"这个按钮是什么"并在未来重新找到它?

单纯依赖 VLM 的坐标输出不靠谱——换个设备分辨率就失效了。单纯依赖 XML 可访问性树也不够——单靠属性过滤经常不唯一。

LXB 的方案是把两者融合:

  1. VLM 负责语义理解:截图发给 VLM,让它用思维链过滤掉商品卡片、推荐流等动态内容,只保留"导航锚点"(Tab、设置按钮、跳转入口等),输出每个元素的中心坐标
  2. XML 负责精确定位:用 VLM 给出的坐标,在 dump_actions 返回的可点击节点列表里做点-包含匹配,找到包含该坐标的最小面积节点;如果精确命中失败,把边界扩大 20px 再试一次
  3. 构建全局唯一 Locator:命中节点后,用其 resource_idtextcontent_descclass_name 组合判断唯一性。不唯一就加上父节点的 resource_id 缩小范围;还不唯一(2-3个同类节点)就记录空间排序下的相对位置索引;超过 3 个同类节点则放弃这个元素

fusion_engine.svg

这个 Locator 完全由开发者分配的属性构成,跟屏幕分辨率无关,所以在 A 手机上建的图可以直接在 B 手机上回放——这就是"跨设备"的底层来源。


3. 执行引擎:Route-Then-Act

有了图,有了可靠的 Locator,执行阶段就分三步走:

Phase 1 · 规划:用户输入自然语言任务(比如"帮我查一下我的订单"),LLM 对照导航图里每个页面的语义描述(页面名称、功能说明、关键词),用纯文本查询找到目标页面——不需要截图,不需要 VLM

Phase 2 · 路由:BFS 计算从当前页面到目标页面的最短路径,然后按照路径依次用 Locator 强匹配点击每个导航元素——全程零大模型调用

Phase 3 · 执行:到达目标页面后,才调用 VLM 分析当前页面内容,执行具体的任务操作

下面的动图是架构根据需求 “帮我打开哔哩哔哩,发送一条动态,内容为test,标题为test” 执行的过程

Route-then-Act-Init-and-Planning (speed x 2).gif Route-then_act_routing(real time).gif Route-then-act-acting(speed x 5)).gif

执行过程中还有一套三级恢复机制——循环检测、弹窗处理规则、应用重启——尽可能在不中断任务的情况下自愈。


效果怎么样

在淘宝和 Bilibili 共 8 个真实任务上做了测试(每个任务重复 3 次,共 96 次运行),和几个纯 VLM 方案对比:

测试任务(都使用模型qwen3-vl-30b-a3b-instruct)

编号App指令难度
tb_s1淘宝查看消息页面浅层
tb_s3淘宝进入关注页面浅层
bili_s1B站查看消息页面浅层
bili_m1B站查看我收到的点赞中层
bili_m3B站查看每周必看视频列表中层
tb_d1淘宝查看我的订单列表深层
tb_d2淘宝进入淘宝 APP 设置页面深层
bili_d2B站进入鬼畜分区深层

浅层 = 从首页一跳直达;中/深层 = 需要经过 2 跳及以上的导航路径。

方法成功率平均模型调用次数平均 Token 消耗
LXB(本框架)100%1.0 次4,795
VLM-ReAct87.5%2.79 次8,618
Text-ReAct75.0%2.17 次4,029
VLM+语义地图91.7%2.38 次20,360

对于需要 2 跳以上导航的深层任务,LXB 成功率 100%,而 VLM-ReAct 是 80%、Text-ReAct 是 60%。模型调用次数减少了 74%(从 3.87 次降到 1.0 次),Token 消耗减少了 58.6%。

需要说明的是:这套测试设计上本就对 LXB 的优势场景更友好(导航任务,且都是map覆盖到的),泛化能力还有待更大规模的验证。数据只能说明在这个场景下思路是有效的,距离一个成熟的系统还有很长的路要走。


踩过的坑(部分)

随手列几个印象比较深的:

  • UDP 的选择:最初选 UDP 是因为想支持 NAT 穿透场景,后来测试发现局域网下 TCP 反而更稳。现在的自定义 ARQ 协议加了 Stop-and-Wait + CRC32,可靠性有保证,但如果重来一次,可能会在 TCP 和 UDP 之间再斟酌一下

  • 页面指纹 的坑:我做了半个月的页面指纹,不过技术有限,一直找不到合适的方法,阈值高了又容易多个页面都认为是一个页面,阈值低了又太敏感

  • VLM 坐标空间的差异:不同 VLM 的坐标输出方式不一样——有的是相对于原始图片像素,有的是固定在 0-1000 的归一化空间。用探针图像做一次运行时标定之后,才能正确映射到屏幕坐标。不过这种方式的可靠性我认为还有待商榷


现在的状态

目前框架的核心功能已经跑通。但坦白说,还有很多地方不完善:

  • WebView 渲染的内容(很多 H5 页面)无法获取 XML 节点,Fusion 会直接失败
  • 导航图是静态的,App 更新后,如果重要导航节点发生了属性的改变,需要重新建图
  • 测试任务数量偏少,泛化能力未经充分验证
  • 现在locator还没发做到覆盖所有的重要导航节点,一些特征不太鲜明的依然覆盖不到。

代码已经开源,感兴趣的朋友可以看看(顺便点个star):github.com/wuwei-crg/L…

如果你也在研究手机自动化相关的工作,或者有任何问题和建议,欢迎交流。作为第一次独立做系统性的工程项目,有很多地方一定考虑不周,欢迎指出 :)