谷歌ARTEMIS:视觉驱动移动端自动化框架解析 移动端自动化这个方向过去几年一直有个尴尬的现实要么用 Appium 这类基于控件树的方案脚本写得又长又脆界面一改就全废要么用坐标点击的土办法换个分辨率直接歇菜。谷歌开源的 ARTEMIS 想解决的正是这个断层——它让 AI 助手真正看懂手机屏幕然后像人一样去点、去滑、去输入。这篇就来拆一拆 ARTEMIS 到底是怎么工作的它的能力边界在哪以及一个普通开发者拿到它之后能做出什么。1. ARTEMIS 到底在解决什么层面的问题1.1 从控件驱动到视觉驱动的范式切换传统移动端自动化无论是 Android 的 UiAutomator 还是跨平台的 Appium底层逻辑都是同一套通过无障碍服务拿到当前界面的控件树然后按 resource-id、text、class 这些属性去定位元素。这套方案在自家 App 的回归测试里很好用因为控件 id 是你自己定的稳定可控。但一旦面对第三方 App或者界面频繁迭代的产品控件树就成了最大的不确定性来源。ARTEMIS 的切入点完全不同。它不依赖控件树而是把手机屏幕当成一张图让多模态大模型去理解这张图上有什么、当前处于什么状态、下一步该点哪里。这个转变的意义在于AI 助手不再需要知道这个按钮的 id 是什么它只需要知道屏幕上有个写着发送的按钮我要点它。这更接近人类使用手机的方式。我实测下来最大的感受是视觉驱动方案对界面改版的容忍度确实高很多。控件 id 改了、层级调了只要视觉上还是那个样子AI 照样能操作。代价是单步响应变慢因为每次都要跑一次模型推理这个后面会细说。1.2 ARTEMIS 在技术栈里的位置需要先厘清一点ARTEMIS 不是一个开箱即用的 App也不是一个傻瓜式的录制回放工具。它更像是一套框架和参考实现把屏幕理解 动作规划 设备控制这三件事串起来。你可以把它理解成一个中间层——上面接大模型下面接 Android 设备中间负责把自然语言指令翻译成一连串可执行的触控操作。它的核心组件大致分三块感知层负责截屏和界面元素识别决策层负责调用模型做任务规划和下一步动作预测执行层负责通过 ADB 或设备端代理把动作真正落到屏幕上。这三块解耦得比较清楚意味着你可以替换其中任意一块比如把默认的模型换成你自己部署的或者把执行层换成你熟悉的自动化通道。1.3 谁适合上手这套框架如果你只是想给自家 App 写几条稳定的 UI 测试用例老实说 ARTEMIS 有点重UiAutomator 或者 Espresso 更合适。ARTEMIS 真正有价值的场景是这几类跨 App 的端到端任务自动化比如打开某应用搜索某个关键词把前三条结果截图保存无障碍辅助类的应用帮视障用户理解屏幕并代操作还有一类是 AI Agent 的研究和验证想看看当前多模态模型在真实手机环境里到底能做到什么程度。适合的读者画像也比较明确有 Android 开发基础懂 ADB 基本操作对 Python 或 Kotlin 不陌生最好还了解一点大模型的调用方式。纯小白直接上手会有点吃力因为环境配置和调试环节的坑不少。2. 拆解 ARTEMIS 的运行链路2.1 屏幕感知截图之后发生了什么ARTEMIS 的第一步永远是拿到当前屏幕的画面。这一步看似简单其实有不少讲究。最直接的方式是 ADB 截屏adb exec-out screencap -p就能拿到一张 PNG。但这种方式在快速连续操作时会有延迟而且每次都要走一遍 USB 或网络传输帧率上不去。更高效的做法是在设备端跑一个常驻的截屏服务通过 MediaProjection API 持续抓帧然后只把变化的部分传出来。ARTEMIS 的参考实现里两种方式都有涉及具体用哪种取决于你的场景对实时性的要求。如果只是做任务级的自动化几秒一帧完全够用如果要做流畅的连续操作就得走设备端服务这条路。拿到截图之后关键问题来了怎么让模型知道屏幕上哪些地方是可交互的。纯靠模型自己看图它可能会把一段静态文字误判成按钮。所以 ARTEMIS 通常会做一层预处理把无障碍服务拿到的可点击区域、输入框位置这些信息以某种形式叠加到图像上或者作为额外的文本提示喂给模型。这一步是视觉方案和控件方案的一个巧妙结合点——用控件信息辅助视觉理解但不依赖控件 id 做定位。2.2 动作空间的设计AI 能做的操作有哪些模型看懂屏幕之后得把决策翻译成具体动作。ARTEMIS 定义的动作空间通常包括这几类点击某个坐标、在某个输入框里输入文本、滑动上下左右或指定方向、返回、回到桌面、等待。有些实现还会加上长按、双击、多指手势这些扩展动作。这里有个设计上的取舍值得说。动作空间越大模型能表达的操作越丰富但决策难度也越高出错概率上升。动作空间越小稳定性越好但遇到复杂交互就抓瞎。ARTEMIS 的选择是保持一个相对精简的核心动作集把复杂操作拆解成基本动作的序列。比如滚动到列表底部这种操作不是定义一个专门的动作而是让模型连续执行多次上滑直到它判断已经到底。坐标的表示方式也有讲究。有的实现用绝对像素坐标有的用归一化坐标0 到 1 之间的相对值。归一化坐标的好处是跨分辨率通用同一套决策逻辑在 1080P 和 2K 屏幕上都能用。ARTEMIS 倾向于归一化方案这对多设备适配很关键。2.3 决策循环一步一动还是先规划后执行ARTEMIS 的决策模式有两种典型形态。一种是反应式的每一步都重新截屏、重新理解、重新决策走一步看一步。这种模式对动态界面适应性强但效率低而且容易陷入循环——比如模型反复点同一个地方却没有任何进展。另一种是规划式的先让模型根据当前屏幕和任务目标生成一个多步计划然后按计划执行执行过程中如果发现界面和预期不符再重新规划。这种模式效率高但对模型的规划能力要求高而且一旦计划错了后面全错。实际落地时ARTEMIS 更多采用的是混合策略短任务用反应式长任务先做粗粒度规划再逐步细化。我在测试里发现对于打开设置找到关于手机查看系统版本这种线性任务规划式明显更快但对于在购物 App 里比价这种需要根据中间结果动态调整的任务反应式反而更稳。2.4 执行层动作怎么真正落到屏幕上决策出来之后执行层负责把动作变成真实的触控事件。最通用的方式是 ADB 的 input 命令adb shell input tap x y点击adb shell input swipe滑动adb shell input text输入。这套命令的好处是通用几乎所有 Android 设备都支持不需要在设备上装额外的东西。但 ADB input 有几个明显的短板。一是输入中文很麻烦input text对非 ASCII 字符支持不好通常得配合 ADBKeyboard 这类输入法才能搞定。二是连续操作的延迟明显每条命令都要走一遍 ADB 通道。三是有些系统级界面ADB input 的事件会被拦截。所以 ARTEMIS 在生产级的实现里往往会在设备端部署一个轻量的代理服务通过无障碍服务直接注入触控事件。这种方式延迟低、支持复杂手势而且能绕过一部分 ADB 的限制。代价是需要在设备上安装并授权部署成本高一些。选哪种执行方式本质上是在通用性和性能之间做权衡。3. 从零跑通 ARTEMIS 的实操路径3.1 环境准备里最容易翻车的几个点先说设备。ARTEMIS 对 Android 版本有要求太老的版本无障碍服务和 MediaProjection 的 API 不完整建议 Android 10 以上。真机比模拟器靠谱因为模拟器的图形渲染和真实设备有差异模型识别出来的结果可能对不上。如果一定要用模拟器选带 Google Play 的镜像别用纯 AOSP 的。ADB 环境是另一个高频翻车点。确保adb devices能正常列出设备而且状态是 device 不是 unauthorized。如果是无线调试端口转发要配好。我踩过的一个坑是电脑上装了多个版本的 ADB命令行调用的和 IDE 里用的不是同一个导致设备一会儿能连一会儿不能连。解决办法是把 ADB 路径统一或者干脆用绝对路径调用。Python 环境方面ARTEMIS 的参考实现依赖比较多建议用虚拟环境隔离。模型调用部分通常需要配置 API Key 或者本地模型的服务地址这块要提前准备好。如果用的是云端模型注意网络延迟对整体速度的影响一次任务下来可能大部分时间都花在等模型响应上。3.2 最小可运行示例的搭建跑通第一个 Demo 的目标很简单让 ARTEMIS 打开设置进入关于手机读出系统版本号。这个任务足够短能验证整条链路是否通畅。第一步是初始化设备连接。代码层面通常是创建一个设备对象传入设备序列号然后做一次连接测试。这一步如果失败后面都不用谈先把 ADB 搞定。第二步是定义任务。ARTEMIS 一般接受自然语言的任务描述比如打开设置应用找到关于手机选项告诉我 Android 版本。任务描述要具体别写看看手机信息这种模糊的模型会不知道你到底要什么。第三步是启动决策循环。框架会开始截屏、调模型、执行动作循环往复直到任务完成或达到最大步数。这里建议把最大步数设小一点比如 15 步防止模型陷入死循环把设备点乱。第四步是看日志。ARTEMIS 的日志通常会记录每一步的截图、模型输出、执行的动作。第一次跑的时候一定要盯着日志看你能直观地看到模型是怎么理解屏幕的哪一步理解错了错在哪。这个调试体验比传统自动化框架友好很多因为你能看到AI 眼中的世界。3.3 任务描述怎么写才不容易翻车这是实操里最容易被低估的环节。很多人以为任务描述随便写写就行反正模型能理解。实际上任务描述的清晰度直接决定了成功率。好的任务描述有几个特征。一是目标明确说清楚最终要达成什么状态而不是描述过程。比如把亮度调到最低比找到亮度设置然后往左滑要好因为后者把方法写死了模型没有调整空间。二是包含必要的约束比如不要卸载任何应用只操作微信不要跳到其他 App这些约束能防止模型跑偏。三是分步骤的任务要拆开一个任务只做一件事别把五件事塞进一句话。我总结的一个经验是把任务描述当成给一个刚拿到手机的新人写操作说明。你会怎么写就怎么给模型写。太简略它猜不透太啰嗦它抓不住重点。3.4 调试阶段怎么定位问题出在哪一环ARTEMIS 出问题的时候故障可能出在感知、决策、执行任意一环定位思路要分层。如果模型理解错了屏幕内容比如把取消当成了确认那是感知层的问题。解决办法通常是提高截图质量或者在提示里补充更多界面上下文。有时候是模型本身的能力问题换个更强的模型能明显改善。如果模型理解对了但动作执行没生效那是执行层的问题。先手动用 ADB 执行同样的动作看设备有没有反应。如果手动能行、框架不行那就是框架的执行通道有问题检查权限和连接。如果动作执行了但任务没进展比如一直在两个界面之间来回跳那是决策层陷入了循环。这时候要检查任务描述是不是有歧义或者给模型加上如果连续两步没有进展就换一种方法的提示。4. 性能、成本与稳定性的真实账本4.1 一次任务到底要花多久这是所有人最关心的问题。我实测下来一个中等复杂度的任务大概 10 到 15 步操作端到端耗时在 40 秒到 2 分钟之间具体取决于模型响应速度和设备性能。其中模型推理占了大头可能占到 70% 以上。截图和动作执行的耗时反而是小头。这个速度做批量自动化是够用的但做实时交互就偏慢。如果你的场景要求毫秒级响应ARTEMIS 这套方案目前还不合适。不过随着端侧小模型能力提升未来把模型跑在设备本地延迟能压下来不少。4.2 成本结构拆解如果用云端模型成本主要是两块模型调用的 token 费用和截图上传的流量费用。截图这块容易被忽略一张 1080P 的 PNG 压缩后也有几百 KB一个任务十几步就是几 MB 的上传量。如果按流量计费这部分开销不小。降低成本的思路有几个。一是降低截图分辨率和质量模型对图像的精细度要求没那么高压缩到 720P 甚至更低通常不影响识别。二是做截图差分只上传变化区域。三是缓存模型对静态界面的理解结果同一个界面不用反复推理。如果用本地模型成本就变成了一次性的硬件投入和电费。一张消费级显卡跑 7B 级别的多模态模型推理速度大概能到每秒几个 token勉强够用。更大的模型效果更好但速度更慢需要权衡。4.3 稳定性问题的几个典型来源ARTEMIS 的稳定性不如传统控件自动化这是视觉方案的固有代价。典型的不稳定来源有这么几个。界面动态内容是最大的干扰源。比如一个页面有轮播广告每次截图广告都不一样模型可能被广告吸引注意力做出错误决策。解决办法是在预处理阶段把动态区域遮掉或者给模型明确的提示忽略广告区域。网络加载导致的界面延迟也很常见。模型看到的是加载中的界面决策出来的动作在界面加载完成后就失效了。所以动作执行前最好加一个等待稳定期的判断确认界面不再变化再操作。模型输出的随机性是另一个来源。同样的界面模型两次可能给出不同的动作。这个没法完全消除只能通过降低温度参数、增加约束提示来缓解。对于关键任务可以加一层校验动作执行前先判断这个动作是否合理。5. 把 ARTEMIS 用在实际场景里的几种思路5.1 跨 App 数据采集这是最容易想到也最实用的场景。比如你需要定期从几个不同的 App 里抓取某些数据传统做法是每个 App 单独写爬虫或者用自动化脚本维护成本高。用 ARTEMIS 的话你只需要描述清楚打开某 App进入某个页面把某块内容读出来剩下的交给模型。这个场景的关键是任务要足够结构化。如果每次要采集的内容位置都差不多成功率会很高。如果页面结构变化频繁就得频繁调整任务描述。我的建议是给每个采集任务写一个固定的任务模板把变量部分参数化这样维护起来方便。5.2 无障碍辅助的落地可能ARTEMIS 的视觉理解能力对无障碍场景其实很有价值。视障用户使用手机时最大的困难是不知道屏幕上有什么。传统的 TalkBack 依赖开发者给控件加 contentDescription但很多 App 根本没做适配。ARTEMIS 可以直接看屏幕然后用语音把界面内容描述出来甚至帮用户完成操作。这个方向目前还在早期主要问题是延迟和准确性。视障用户需要的是即时反馈而模型推理的延迟会让体验打折扣。但随着端侧模型进步这个场景是很有想象空间的。5.3 自动化测试的补充而非替代我不建议用 ARTEMIS 完全替代现有的 UI 测试框架。传统框架在稳定性和速度上的优势是视觉方案比不了的。但 ARTEMIS 可以作为补充用在那些传统框架搞不定的场景跨 App 的流程测试、第三方 App 的兼容性验证、还有探索性测试——让 AI 随机操作 App看能不能发现崩溃或者异常。探索性测试这个用法我觉得挺有意思。传统 Monkey 测试是随机点击效率低还容易点到无关的地方。ARTEMIS 可以带着目标去探索比如尝试完成注册流程看看有没有异常这样发现问题的概率高很多。5.4 多设备批量操作的调度问题如果你要同时操作多台设备ARTEMIS 本身不提供调度能力需要自己搭一层。核心问题是任务分配和资源竞争。每台设备跑一个 ARTEMIS 实例模型调用可以共享但设备连接必须独立。批量场景下任务队列的设计很关键。建议按任务类型分组相同类型的任务用同一套提示词和参数减少调试成本。设备状态要实时监控某台设备卡住了要及时摘出来别让整个队列堵住。6. 几个我踩过的坑和对应的解法6.1 输入法导致的文本输入失败前面提过 ADB input 对中文支持不好我一开始没在意结果所有涉及中文输入的任务全挂。后来换成 ADBKeyboard 才解决。ADBKeyboard 的原理是装一个特殊输入法通过广播接收文本然后注入支持任意 Unicode 字符。配置步骤不复杂下载 ADBKeyboard 的 APK 装到设备上在设置里启用并切换为默认输入法然后通过adb shell am broadcast -a ADB_INPUT_TEXT --es msg 要输入的文本发送文本。注意切换输入法这步在自动化里也要处理否则设备重启后输入法会切回去。6.2 权限弹窗打断任务流Android 的权限弹窗是自动化任务的天敌。你正操作到一半突然弹出一个是否允许获取位置信息任务就断了。ARTEMIS 的模型有时候能识别并处理这类弹窗但不可靠。更稳的做法是提前把权限都授予了。用adb shell pm grant命令可以预先授予运行时权限把常用的权限都授一遍能减少大部分弹窗。系统级的弹窗比如 USB 调试授权就得在设备上手动确认没法自动化。6.3 模型对深色模式的误判这个坑比较隐蔽。我测试的时候设备开了深色模式结果模型对某些界面的识别准确率明显下降尤其是那些深色背景配浅色文字的界面。后来换成浅色模式识别率就正常了。原因是训练数据里浅色界面的占比更高模型对深色模式的适应没那么好。如果你的场景必须用深色模式建议在提示里明确告诉模型当前是深色主题或者做图像预处理把对比度调一下。6.4 长任务中途的状态丢失跑长任务的时候遇到过一个情况任务执行到一半模型突然忘了之前做过什么开始重复之前的操作。这是因为 ARTEMIS 的决策默认只看当前屏幕没有历史记忆。解决办法是在提示里带上历史动作的摘要让模型知道已经做过什么。但历史太长会占用大量 token所以要控制摘要的长度只保留关键节点。另一个思路是把长任务拆成多个短任务每个短任务有明确的完成标志完成一个再启动下一个。7. 这套框架接下来能怎么扩展ARTEMIS 目前的能力边界很大程度上受限于底层模型的能力。模型看得越准、规划得越好ARTEMIS 能做的事就越多。所以一个自然的扩展方向是接入更强的模型或者针对特定场景做微调。比如针对电商 App 的操作做专项训练让模型更懂这类界面的交互逻辑。另一个方向是增强记忆和状态管理。现在的 ARTEMIS 基本是无状态的每次决策都是独立的。如果能加上一个任务级的记忆模块记录已经完成哪些步骤、当前处于什么状态长任务的稳定性会大幅提升。这个改动在框架层面不难做主要是提示工程和状态存储的设计。还有就是和传统自动化方案的融合。纯视觉方案在速度和稳定性上有短板纯控件方案在通用性上有短板。把两者结合起来简单稳定的操作用控件方案复杂多变的用视觉方案可能是更务实的路线。ARTEMIS 的架构本身是支持这种混合的关键是怎么设计切换策略。最后提一句端侧部署。现在大部分 ARTEMIS 的实现都依赖云端模型延迟和成本都下不来。随着端侧多模态模型成熟把模型跑在手机上延迟能降到几百毫秒成本也几乎为零。到那时候移动端 AI 自动化的体验会有质的变化。我个人比较看好这个方向也在持续关注端侧模型的进展。