ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

谷歌ARTEMIS:视觉理解+动作生成,破解移动端自动化死结

谷歌ARTEMIS:视觉理解+动作生成,破解移动端自动化死结

移动端自动化这个方向,过去几年一直有个尴尬的瓶颈:要么是基于坐标点击的脚本,界面一改就全废;要么是基于无障碍节点的方案,遇到自绘控件或者游戏引擎渲染的界面就抓瞎。真正能做到"像人一样看屏幕、理解界面、然后动手操作"的方案,少之又少。谷歌开源的 ARTEMIS 就是冲着这个痛点来的——它把视觉理解和操作执行串成了一条完整的链路,让 AI 助手能真正"看懂"手机屏幕上的内容,再决定点哪里、输入什么、怎么滑动。这套东西适合谁?做移动端测试自动化的、搞 RPA 流程的、研究多模态 Agent 落地的,以及单纯想折腾 AI 操作手机这个方向的开发者。我花了两天时间把它的架构和核心流程摸了一遍,下面把关键的东西拆开讲。

1. ARTEMIS 到底在解决移动端自动化的哪个死结

1.1 传统方案的三种路线及其天花板

要理解 ARTEMIS 的价值,得先看清楚它之前的路是怎么走的。移动端自动化大致分三条技术路线,每条都有自己的硬伤。

第一条是坐标脚本路线,代表就是早期的按键精灵、ADB 的input tap x y。原理简单粗暴:记录屏幕坐标,到点就点。问题是分辨率一变、界面一改、弹窗一冒出来,坐标全错位。维护成本高得离谱,一个 App 版本更新可能就要重录一遍脚本。

第二条是无障碍节点路线,代表是 Android 的 AccessibilityService 和 UiAutomator。它通过系统提供的节点树来定位控件,比坐标稳。但它的死穴在于:节点树只对标准控件有效。一旦界面是 Canvas 自绘的、是 Flutter 或 Unity 渲染的、是 WebView 里套的 H5,节点树要么是空的,要么给一堆无意义的容器节点。你根本拿不到"这个按钮叫什么"。

第三条是图像模板匹配路线,用 OpenCV 做特征点或者模板匹配。比坐标灵活,但模板图得提前准备,界面换个主题色、换个字体大小,匹配率就掉。而且它只能识别"我预先见过的东西",遇到没见过的界面就无能为力。

这三条路线的共同问题是:它们都不具备"理解"能力。它们只是在执行预设的规则,而不是在理解当前屏幕上发生了什么。

1.2 ARTEMIS 的核心思路:把"看"和"做"解耦再重组

ARTEMIS 的思路完全不同。它不依赖节点树,也不依赖预设模板,而是走视觉理解 + 动作生成的路线。整个流程可以拆成三个环节:

  • 感知层:截取当前屏幕画面,把图像交给多模态模型去理解,识别出界面上有哪些可交互元素、它们的位置和语义是什么。
  • 决策层:根据当前任务目标和感知结果,决定下一步该做什么动作——点击某个元素、输入文本、滑动、返回等等。
  • 执行层:把决策结果翻译成 Android 系统能执行的底层指令,通过 ADB 或者设备端的执行器落地。

这个架构最关键的地方在于,感知和决策是解耦的。感知层只负责"屏幕上有什么",决策层只负责"基于这些信息该干什么"。这意味着你可以替换任意一层——换个更强的视觉模型、换个不同的决策策略,整个系统还能跑。这种模块化设计是它能适配多种场景的根本原因。

1.3 为什么"像人一样操作"这个描述不是营销话术

"像人一样操作手机"这句话听起来像宣传语,但放在 ARTEMIS 的语境下是准确的。因为它的工作方式和人类操作手机的逻辑高度一致:人看屏幕,是靠眼睛识别出"这里有个搜索框""那里有个确认按钮",而不是去读什么节点树;人决定点哪里,是基于对界面语义的理解,而不是基于坐标记忆。

ARTEMIS 把多模态模型当作"眼睛"和"大脑",把 ADB 当作"手指",这个类比是成立的。它带来的直接好处是泛化能力:一个训练好的视觉模型,面对从没见过的 App 界面,依然能识别出常见的 UI 元素模式——按钮、输入框、列表项、开关。这是坐标脚本和模板匹配永远做不到的。

注意:泛化能力不等于 100% 准确。视觉模型在复杂界面、低对比度、动态内容场景下依然会出错,后面会专门讲怎么处理这些情况。

2. 拆开 ARTEMIS 的架构:感知、决策、执行三层怎么协作

2.1 感知层:截图之后发生了什么

感知层的第一步是屏幕捕获。Android 上截屏有几种方式:adb shell screencap是最通用的,兼容性好但速度受限于 ADB 传输;设备端可以用 MediaProjection API 做实时捕获,延迟低但需要用户授权。ARTEMIS 在不同部署模式下会选用不同的捕获方式,核心考量是延迟和稳定性的平衡。

拿到截图之后,关键的一步是界面元素解析。这里 ARTEMIS 会把图像送进多模态模型,让模型输出结构化的界面描述。典型的输出格式是一组元素列表,每个元素包含:

字段含义示例
type元素类型button / input / text / icon
text元素上的文字"搜索"
bbox边界框坐标[x1, y1, x2, y2]
confidence置信度0.92
interactable是否可交互true

这个结构化输出是后续决策的基础。注意 bbox 用的是归一化坐标还是绝对像素坐标,这直接影响执行层的换算逻辑。实践中建议统一用归一化坐标(0到1之间),这样换设备、换分辨率时不用重新标定。

2.2 决策层:从"看到什么"到"该做什么"

决策层拿到感知结果后,要结合任务目标来决定动作。这里的任务目标可以是一句自然语言指令,比如"帮我在设置里把蓝牙打开",也可以是一个结构化的步骤序列。

决策的核心逻辑是状态匹配 + 动作选择。模型需要判断:当前界面状态距离目标状态还差几步?下一步最有效的动作是什么?这个判断过程涉及几个关键考量:

  • 动作空间的定义:ARTEMIS 支持的动作通常包括 tap(点击)、type(输入)、swipe(滑动)、back(返回)、home(回主页)、wait(等待)等。动作空间越小,决策越稳定,但表达能力越弱;动作空间越大,灵活但容易选错。
  • 历史上下文:单看一帧画面往往不够,比如一个加载中的界面,你需要知道上一帧是什么样,才能判断是"还在加载"还是"加载失败"。所以决策层通常会维护一个短期记忆,记录最近几步的操作和界面变化。
  • 失败回退:如果某个动作执行后界面没有预期变化,需要有重试或者换策略的机制。这是实际落地时最容易忽略、也最影响成功率的部分。

2.3 执行层:ADB 指令的封装与优化

执行层把决策结果翻译成具体指令。最基础的是 ADB 命令:

# 点击坐标 adb shell input tap 540 1200 # 输入文本(注意中文需要特殊处理) adb shell input text "hello" # 滑动 adb shell input swipe 540 1800 540 600 300 # 返回键 adb shell input keyevent 4

看起来简单,但实际用起来坑不少。中文输入就是经典问题,input text对非 ASCII 字符支持很差,通常需要配合 ADBKeyboard 这类输入法方案。滑动速度的参数(最后一个数字是持续时间毫秒)直接影响是否被识别为滑动还是点击。点击的落点如果正好在两个可点击区域的边界,可能触发错误的元素。

ARTEMIS 在执行层做了封装,把这些细节抽象成统一的动作接口,同时加入了执行确认机制——动作执行后重新截图,确认界面确实发生了变化,而不是盲目地往下走。

2.4 三层之间的数据流与反馈闭环

把三层串起来看,一个完整的操作循环是这样的:

  1. 截图 → 感知层解析出界面元素
  2. 感知结果 + 任务目标 + 历史 → 决策层输出动作
  3. 动作 → 执行层落地为 ADB 指令
  4. 执行后重新截图 → 回到第 1 步,形成闭环

这个闭环的循环频率很关键。太快了浪费算力,太慢了任务执行效率低。实践中一次循环(截图+推理+执行)通常在 2 到 5 秒之间,主要瓶颈在多模态模型的推理速度。如果用的是本地小模型,可以压到 1 秒以内;如果用云端大模型,延迟就取决于网络和 API 响应。

3. 从零跑通 ARTEMIS:环境搭建与第一个自动化任务

3.1 环境准备里最容易翻车的几个点

在动手之前,有几个环境问题必须先解决,否则后面会卡得你怀疑人生。

ADB 环境是基础中的基础。需要确保adb devices能正常列出你的设备。如果是真机,记得打开开发者选项里的 USB 调试。如果是模拟器,注意模拟器的 ADB 端口可能和默认的不一样,需要adb connect指定端口。

Python 环境方面,ARTEMIS 这类框架通常依赖较新的 Python 版本(3.9+),建议用虚拟环境隔离,避免和系统里的其他包冲突。依赖安装时最容易出问题的是和图像处理、深度学习相关的库,比如 OpenCV、PyTorch 这些,版本不匹配会直接导致 import 失败。

模型接入是另一个关键点。ARTEMIS 需要多模态模型来做视觉理解,你需要决定用哪种接入方式:

接入方式优点缺点适用场景
云端 API模型能力强,无需本地算力有网络延迟,可能产生费用快速验证、复杂界面
本地小模型延迟低,数据不出本地能力有限,需要 GPU隐私敏感、简单界面
混合模式兼顾能力和成本架构复杂生产环境

提示:初次跑通建议先用云端 API,把流程走通再考虑本地化。上来就折腾本地模型部署,很容易在环境问题上耗掉一整天。

3.2 设备连接与截图链路的验证

环境装好后,第一步不是急着跑任务,而是单独验证截图链路。因为截图是整个系统的输入源,如果截图有问题,后面全是白搭。

验证方法很简单,写个最小脚本:

import subprocess def capture_screen(output_path="screen.png"): result = subprocess.run( ["adb", "exec-out", "screencap", "-p"], capture_output=True ) with open(output_path, "wb") as f: f.write(result.stdout) return output_path capture_screen()

跑完之后打开screen.png,确认三件事:画面是不是当前手机屏幕、分辨率对不对、有没有花屏或者黑屏。如果截图是黑的,通常是权限问题或者设备处于安全界面(比如锁屏、支付页面),这些界面系统不允许截屏。

3.3 写第一个任务:让 AI 打开设置并进入蓝牙页面

跑通截图后,可以尝试第一个完整任务。任务描述用自然语言写:"打开设置,进入蓝牙设置页面"。

这个任务看似简单,但涵盖了感知、决策、执行的完整链路。执行过程中你会观察到几个现象:

  • 模型首先识别出桌面上的"设置"图标,点击进入
  • 进入设置后,识别出"蓝牙"相关的菜单项,可能需要滑动才能找到
  • 点击进入蓝牙页面,任务完成

第一次跑大概率不会一次成功。可能的问题包括:模型把某个图标认错了、滑动距离不够没找到目标、点击后界面没反应。这些都是正常的,关键是要有日志,能看到每一步的截图、识别结果和决策动作,才能定位问题。

3.4 任务描述怎么写才不容易翻车

任务描述(prompt)的写法直接决定成功率。几个实测有效的原则:

  • 目标明确,路径模糊:说清楚"要达成什么",但不要规定"必须怎么走"。比如写"打开蓝牙",而不是"点击设置图标,然后点蓝牙菜单"。让模型自己找路径,泛化性更好。
  • 避免歧义:如果界面上有多个相似元素,描述里要加限定。比如"点击右上角的搜索图标",而不是"点击搜索"。
  • 分步骤拆解复杂任务:一个任务如果需要十几步,建议拆成几个子任务。太长的任务链中间任何一步出错都会导致整体失败,而且很难定位是哪一步的问题。

4. 实测中暴露的问题与针对性优化

4.1 视觉识别的误判:从"认错按钮"说起

实测中最常见的问题就是元素误判。模型把一个"取消"按钮认成"确认",或者把广告位认成功能入口。这类问题的根源通常是:界面元素视觉相似度高、文字太小、或者被遮挡。

应对策略有几个层次。第一层是提高截图质量,确保分辨率足够、没有压缩失真。第二层是在 prompt 里加入约束,比如"只点击明确标注为XX的按钮,不确定时不要操作"。第三层是加验证,动作执行后检查界面是否符合预期,不符合就回退重试。

我实测下来,加验证这一步的收益最大。因为误判不可能完全避免,但只要能检测到"点错了",就能补救。比如点击后如果界面没变化,或者出现了非预期的弹窗,就触发重新感知和决策。

4.2 动态界面的处理:加载中、弹窗、动画

移动端界面是动态的,这是和桌面自动化最大的区别。你截图的那一瞬间,界面可能正在加载、正在播放动画、或者弹了个广告。

处理动态界面的核心是等待策略。不能截完图立刻决策,要先判断界面是否"稳定"。判断方法可以是连续截两帧对比,如果差异很小就认为稳定了。也可以检测界面上有没有 loading 相关的元素,有就等。

弹窗是另一个麻烦。系统弹窗、App 内弹窗、权限请求弹窗,形态各异。ARTEMIS 的决策层需要能识别出"这是个弹窗",并决定是关闭它还是处理它。实践中建议在任务描述里预先说明可能遇到的弹窗类型和处理方式,比如"如果出现权限请求,选择允许"。

4.3 执行延迟与循环节奏的调优

前面提到一次循环 2 到 5 秒,这个延迟在长任务里会累积。一个 20 步的任务,光等待就要一两分钟。优化方向有几个:

  • 并行化:截图和模型推理可以部分重叠,截图的同时上一帧的推理还在进行。
  • 缓存:如果连续几帧界面没变化,可以复用上一次的感知结果,跳过推理。
  • 动作批处理:对于确定的连续动作(比如连续输入多个字符),可以合并成一次执行。

但要注意,优化不能牺牲稳定性。把循环压得太快,可能导致动作还没生效就截了下一帧,反而出错。我的经验是,宁可慢一点稳一点,尤其是在生产环境。

4.4 失败重试机制的设计

一个健壮的自动化系统,必须有失败重试。ARTEMIS 的重试逻辑通常包含几个维度:

  • 动作级重试:单个动作失败(比如点击没反应),重试 2 到 3 次。
  • 步骤级重试:某个步骤反复失败,回退到上一步重新决策。
  • 任务级重试:整个任务失败,从头再来,但限制总重试次数。

重试的关键是要有退避,不能疯狂重试。每次重试之间加个短等待,给界面反应时间。同时要记录重试次数,超过阈值就放弃并报错,避免死循环。

5. ARTEMIS 能落地的真实场景与边界

5.1 移动端自动化测试:回归测试的降本利器

最直接的应用场景是App 回归测试。传统自动化测试要写大量脚本,界面一改就维护不过来。用 ARTEMIS 这类视觉方案,测试用例可以用自然语言描述,界面改版后只要功能还在,用例大概率还能跑。

具体做法是把测试用例写成任务描述,比如"登录后进入个人中心,检查昵称是否显示正确"。系统自动执行并截图,人工只需要看结果截图判断对错。这能大幅降低脚本维护成本。

但要注意,测试场景对准确性要求极高。误判一个按钮可能导致测试结果错误,所以测试场景下建议加人工复核环节,或者用更严格的验证逻辑。

5.2 RPA 流程自动化:跨 App 的数据搬运

另一个场景是跨 App 的流程自动化。比如从聊天软件里提取订单信息,填到另一个管理系统里。这类任务人工做很枯燥,用传统 RPA 又因为界面复杂难以实现。

ARTEMIS 的视觉方案在这种场景下有优势,因为它不依赖具体的 App 实现,只要能"看到"界面就能操作。但跨 App 场景的挑战在于数据传递——怎么把 A 界面读到的信息,准确传到 B 界面。这需要在框架层面做数据抽取和注入的支持。

5.3 无障碍辅助:让操作门槛降下来

从更广的视角看,这类技术对无障碍辅助也有价值。行动不便的用户可以用自然语言指挥 AI 完成手机操作,不需要精确点击。这是技术向善的一个方向,也是 ARTEMIS 这类框架社会价值的一部分。

5.4 当前的能力边界:哪些事它现在还做不好

说了这么多优点,也得说清楚边界。ARTEMIS 目前做不好的事情包括:

  • 高频操作场景:比如游戏里的连招,需要毫秒级响应,视觉推理的延迟根本跟不上。
  • 精细操作场景:比如绘图、修图,需要像素级精度,视觉方案的误差太大。
  • 强安全场景:比如支付确认,涉及资金安全,不能让 AI 自主决策。
  • 超长流程:步骤超过几十步的任务,中间出错概率累积,成功率会明显下降。

认清这些边界,才能把技术用在合适的地方。它不是万能的,但在"中低频、中等复杂度、容错性尚可"的场景里,它是目前最接近实用的方案。

6. 把 ARTEMIS 用好的几个实战心得

6.1 日志和可视化是排错的生命线

我踩过最大的坑,就是一开始没做可视化。任务失败了,只知道"没成功",不知道哪一步出的问题。后来加了每步截图 + 识别结果 + 决策动作的完整日志,排错效率提升了不止一个量级。

建议的做法是:每一步都保存截图,标注出模型识别到的元素框和置信度,记录决策的动作和理由。这样回看的时候,一眼就能看出是"没看到"还是"看到了但决策错了"。

6.2 任务拆解比模型能力更重要

很多人以为换个更强的模型就能解决所有问题,实测下来任务拆解的影响更大。一个设计良好的任务序列,用中等模型就能跑通;一个设计糟糕的巨型任务,用最强模型也容易翻车。

拆解的原则是:每个子任务有明确的成功判据。比如"进入设置页面"这个子任务,成功判据就是"当前界面包含设置相关的标题或菜单"。有了判据,才能判断子任务是否完成,才能决定是否进入下一步。

6.3 别追求 100% 自动化,留人工兜底

生产环境里,100% 自动化是个陷阱。总会有意外情况,总会有模型搞不定的界面。聪明的做法是设计人机协作流程:AI 处理常规情况,遇到不确定的就暂停,等人确认后再继续。

这样既享受了自动化的效率,又避免了全自动出错的风险。尤其是在涉及重要操作的场景,人工兜底是必须的。

6.4 持续收集失败案例反哺优化

ARTEMIS 这类系统的优化是个持续过程。每次失败都是宝贵的样本。建议建立一个失败案例库,记录失败的界面截图、任务描述、失败原因。积累到一定量后,你会发现失败是有模式的——某类界面特别容易出错、某种描述特别容易歧义。针对这些模式做优化,比盲目调参有效得多。

我在实际使用中最大的体会是,这类视觉驱动的自动化框架,它的上限取决于模型能力,但它的下限取决于工程细节。模型再强,如果截图链路不稳、重试机制缺失、日志不完善,照样跑不起来。反过来,即使用中等模型,把工程细节做扎实,也能在特定场景下跑出很高的成功率。所以别一上来就纠结用哪个模型,先把链路跑通、把日志做全、把重试加上,这些基础工作做到位了,再考虑模型升级的事。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进