ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

ARTEMIS 视觉驱动移动端自动化:从架构到实战的完整指南

ARTEMIS 视觉驱动移动端自动化:从架构到实战的完整指南 移动端自动化这个方向过去几年一直有个尴尬的瓶颈脚本能点、能滑、能截图但一旦界面稍有变化整套流程就崩了。传统方案靠的是控件树和固定坐标本质上是在背答案而不是理解题目。ARTEMIS 这个项目有意思的地方在于它把视觉理解和动作执行拆成了两层让 AI 真正去看屏幕、判断当前状态、再决定下一步点哪里。这套思路和市面上大多数移动端自动化框架都不一样也是我决定花时间把它跑通的原因。这篇文章适合两类人看一类是已经在做移动端测试或 RPA想了解视觉驱动方案到底能不能落地另一类是手上有重复的手机操作需求想找个能自己跑起来的自动化工具。我会从它的架构设计讲起把环境搭建、核心链路、实际跑通过程中踩的坑都摊开说最后给一份可以直接抄的配置清单。1. ARTEMIS 到底解决了移动端自动化的哪个死结1.1 传统移动端自动化的三条老路各自卡在哪要理解 ARTEMIS 的价值得先看清楚它之前的方案都栽在什么地方。移动端自动化走到今天主流就三条路每条路都有自己的天花板。第一条是基于控件树的方案代表就是 UiAutomator、Appium 这一类。它的逻辑是读取 Android 的 Accessibility 节点树找到目标控件的 id 或文本然后下发点击指令。这条路在标准控件上非常稳速度快、精度高。但问题也很明显一旦遇到自绘控件、游戏画面、Flutter 渲染的界面节点树里要么是空的要么全是无意义的容器节点根本定位不到东西。我做过一个 Flutter 电商 App 的自动化整个商品卡片在节点树里就是一个FlutterView里面什么都没有只能靠坐标硬点。第二条是基于图像模板匹配的方案Airtest、Sikuli 属于这一类。思路是截一张目标按钮的图然后在当前屏幕上做模板匹配找到位置再点。这条路绕开了控件树理论上什么界面都能处理。但它的死穴是脆弱分辨率一变、主题一换、按钮上文字改一个字匹配率就断崖式下跌。而且它只能回答这个按钮在不在回答不了现在这个页面是什么状态、我该做什么。第三条是基于坐标录制回放最原始也最直接。录一遍操作回放时按坐标点。这条路在固定设备、固定分辨率、固定版本的场景下能用但换个手机就全废属于一次性方案。三条路的共同问题是它们都在执行层面打转没有理解这一层。脚本不知道自己在干什么只是在机械地执行预设动作。界面一变它不会思考只会报错。1.2 ARTEMIS 的破局点把看和做分开ARTEMIS 的核心思路是把整个自动化拆成两个独立的层感知层和执行层。感知层负责看——截取当前屏幕用视觉模型理解画面上有什么、当前处于什么状态执行层负责做——根据感知结果决定下一步动作并下发。这个拆分听起来简单但它带来的变化是根本性的。传统方案里看和做是耦合的你写click(idsubmit)这一行代码既包含了找到 submit 按钮看也包含了点击它做。一旦看失败整行就崩了。ARTEMIS 把这两件事解耦后看这一层可以容忍模糊和变化——按钮位置挪了、文字改了、甚至换了个长得像的界面视觉模型依然能判断出这里有个可点击的提交入口。更关键的是感知层输出的不是坐标而是语义化的界面描述。比如它会告诉你当前是一个登录页有手机号输入框、验证码输入框、获取验证码按钮、登录按钮。执行层拿到这个描述再结合任务目标决定先填手机号再点获取验证码。这种基于语义的决策才是它和传统方案的本质区别。1.3 为什么这个时间点做移动端视觉自动化是成立的放在三年前这套方案跑不起来因为视觉模型又慢又贵又不准。但现在情况变了几个条件同时成熟了。模型能力上多模态模型对 UI 截图的理解已经相当可靠。给它一张手机截图它能准确识别出输入框、按钮、列表项、弹窗甚至能理解按钮上的文字含义。这个能力在 2023 年之前是不具备的。推理成本上小尺寸的视觉模型已经能在端侧或近端跑起来单次推理延迟压到了几百毫秒级别。对于移动端自动化这种不需要实时响应的场景这个延迟完全可以接受。工程链路上MCP 这类协议的出现让模型调用工具这件事有了标准接口。ARTEMIS 通过 MCP 把截图点击输入这些原子操作暴露给模型模型只需要输出我要点这个位置剩下的交给执行层。这条链路打通后整个系统的复杂度大幅下降。所以 ARTEMIS 不是凭空冒出来的它是踩在这几个条件成熟的时间点上。理解这一点你才能明白为什么现在值得投入精力去研究它。2. 拆开 ARTEMIS 的架构感知、决策、执行三层怎么咬合2.1 感知层截图之后模型到底看到了什么感知层是整个系统的入口它的任务是把一张原始截图转换成结构化的界面描述。这个过程分几步走。第一步是截图采集。ARTEMIS 通过 ADB 或设备端的 agent 拿到当前屏幕的原始图像。这里有个细节值得注意截图的分辨率会直接影响后续识别的准确率。太低看不清小字太高推理慢且浪费 token。实践中我一般把长边压到 1080 左右既能看清文字又不至于让模型处理过大的图。第二步是界面元素识别。模型拿到截图后会输出一组界面元素每个元素包含类型按钮/输入框/文本/图标、位置bounding box、以及语义描述比如登录按钮。这一步是纯视觉理解不依赖任何控件树信息。第三步是状态归纳。模型会根据识别出的元素组合判断当前页面属于什么状态。比如有手机号框验证码框登录按钮就归纳为登录页有商品图价格加购按钮就归纳为商品详情页。这个状态判断是后续决策的基础。这里有个容易踩的坑模型对密集列表的识别容易出错。比如一个长列表页模型可能只识别出前几个可见项或者把相邻两项合并成一个。解决办法是在 prompt 里明确要求逐项列出不要合并并且在截图时尽量保证列表项之间有清晰的视觉分隔。2.2 决策层从界面描述到动作序列的推理过程决策层拿到感知层的输出后要回答一个核心问题当前状态下为了达成目标下一步该做什么。这个推理过程不是简单的 if-else。ARTEMIS 的做法是把任务目标和当前界面状态一起喂给模型让模型输出下一步动作。比如任务是登录账号当前状态是登录页模型会输出在手机号框输入 138xxxx然后点击获取验证码。这里的关键设计是动作的原子化。ARTEMIS 定义了一组原子动作tap(x, y)、input(text)、swipe(direction)、wait(ms)、back()。模型每次只输出一个或一组原子动作执行层负责落地。这种设计的好处是模型不需要关心怎么点只需要关心点哪里、点什么。决策层还有一个重要机制是状态校验。每次动作执行后系统会重新截图、重新感知确认动作是否生效。如果点击后界面没变化说明这次点击可能没命中系统会重试或调整策略。这个闭环是传统脚本最缺的——传统脚本点完就往下走根本不管有没有点中。2.3 执行层MCP 协议如何把模型指令翻译成真实操作执行层是离设备最近的一层它通过 MCP 协议接收模型下发的动作指令翻译成 ADB 命令或设备端 API 调用。MCP 在这里扮演的角色是标准化的工具接口。它把点击输入滑动这些操作封装成模型可以调用的工具模型只需要按格式输出调用请求执行层负责解析和执行。这样做的好处是模型和执行层之间有了清晰的契约换模型、换设备都不影响另一层。具体到实现执行层通常包含这几个模块设备连接管理维护 ADB 连接或设备端 agent 的心跳断线自动重连。动作执行器把tap(x,y)翻译成adb shell input tap x y把input(text)翻译成对应的输入命令。结果回传执行完动作后把执行结果成功/失败/耗时回传给决策层。这里有个实操细节输入中文是个老大难。ADB 的input text命令对中文支持很差直接输入会乱码。常见的绕法是先用 ADB 把中文通过剪贴板写入再模拟粘贴操作。ARTEMIS 在执行层对这块做了封装但不同设备、不同输入法的表现还是有差异需要针对性地调。三层咬合起来整个流程就是截图 → 感知 → 决策 → 执行 → 再截图 → 再感知……形成一个闭环。这个闭环的稳定性直接决定了自动化任务能不能跑通。3. 从零把 ARTEMIS 跑起来环境、依赖、第一个任务3.1 环境准备里最容易被忽略的三个细节环境搭建这块官方文档给的是标准流程但实际跑起来有几个坑文档里不会写。第一个坑是 ADB 版本。ARTEMIS 依赖 ADB 做设备通信但不同版本的 ADB 对某些命令的支持不一样。我一开始用的是系统自带的旧版 ADB结果截图命令返回的图像格式和预期不符排查了半天才发现是版本问题。建议直接用 platform-tools 里最新的 ADB并且确保adb devices能正常列出设备。第二个坑是设备授权。Android 设备连接后需要在设备上确认 USB 调试授权这个大家都知道。但很多人不知道的是授权状态会在设备重启后失效而且有些定制系统比如某些国产 ROM会默认关闭USB 调试安全设置这个选项导致 ADB 能连上但无法模拟点击。这个选项在开发者选项里名字叫USB 调试安全设置必须打开否则input tap命令会静默失败。第三个坑是屏幕常亮和锁屏。自动化任务跑到一半屏幕熄了或者锁屏了整个流程就断了。解决办法是在开发者选项里打开不锁定屏幕并且用adb shell svc power stayon true保持屏幕常亮。把这三个细节处理好环境基本就稳了。3.2 依赖安装与配置一份可以直接抄的清单依赖这块ARTEMIS 主要需要 Python 环境、ADB、以及模型调用相关的 SDK。下面是我实测跑通的配置清单。组件版本要求说明Python3.103.9 以下部分依赖装不上ADBplatform-tools 34旧版本截图格式不兼容模型 SDK按官方要求需配置 API Key设备Android 8.0低版本部分命令不支持安装步骤大致是# 1. 克隆项目 git clone artemis-repo cd artemis # 2. 创建虚拟环境 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 3. 安装依赖 pip install -r requirements.txt # 4. 配置模型 API Key export ARTEMIS_API_KEYyour_key_here # 5. 验证设备连接 adb devices配置这块有个建议把 API Key 放在环境变量里不要硬编码在代码里。一方面是安全另一方面是方便切换不同的模型端点做对比测试。3.3 第一个任务让 AI 自动完成一次登录跑通环境后第一个任务建议从最简单的登录开始。这个任务足够简单能快速验证整条链路是否通畅又足够典型涵盖了输入、点击、状态判断这几个核心动作。任务定义大概长这样task { goal: 登录账号, steps_hint: [ 在手机号输入框输入 13800138000, 点击获取验证码按钮, 等待验证码到达, 在验证码输入框输入收到的验证码, 点击登录按钮 ] }注意这里的steps_hint只是提示不是硬性脚本。ARTEMIS 会根据实际界面状态动态调整如果界面上没有获取验证码按钮它会自己判断该怎么走。跑起来之后你会看到这样的日志流[感知] 当前页面登录页 [感知] 识别到元素手机号输入框、验证码输入框、获取验证码按钮、登录按钮 [决策] 下一步点击手机号输入框 [执行] tap(540, 620) - 成功 [感知] 当前页面登录页手机号框已聚焦 [决策] 下一步输入手机号 [执行] input(13800138000) - 成功 ...这个日志流是排查问题的关键。哪一步卡住了看日志就能定位是感知错了、决策错了、还是执行失败了。4. 实测中暴露的问题视觉自动化的边界在哪4.1 识别准确率不是 100%哪些界面最容易翻车跑了一段时间后我对 ARTEMIS 的识别能力有了比较清晰的认识。它在标准界面上表现很好但有几类界面特别容易翻车。第一类是密集小字界面。比如设置页里一长串开关项每项文字都很小模型容易看漏或者看错。我遇到过一次模型把自动同步识别成了自动同歩虽然意思差不多但如果后续逻辑依赖精确文本匹配就会出问题。第二类是动态内容界面。比如聊天列表、信息流内容一直在变模型每次识别出的元素都不一样。这种场景下靠视觉识别做精确操作很难更适合用大致定位相对操作的策略。第三类是弹窗和浮层。弹窗出现时底层界面还在模型可能同时识别出弹窗和底层元素导致决策混乱。解决办法是在 prompt 里明确要求优先处理最上层的弹窗忽略被遮挡的元素。第四类是加载中和骨架屏。页面还在加载时截图模型看到的是骨架屏识别出的元素是错的。这种情况需要在感知层加一个页面是否加载完成的判断比如检测是否有 loading 指示器。4.2 延迟与成本一次完整任务到底要花多少时间这是很多人关心的问题。我实测下来一次完整的登录任务从打开 App 到登录成功大概需要 8 到 15 次感知-决策-执行循环每次循环的耗时分布大致是环节耗时说明截图200-500ms取决于设备和分辨率感知推理800-2000ms取决于模型和图片大小决策推理500-1500ms取决于任务复杂度动作执行100-300msADB 命令开销状态校验200-500ms重新截图确认加起来单次循环大概 2 到 5 秒。一个登录任务跑完差不多 30 到 60 秒。这个速度比传统脚本慢很多——传统脚本跑登录可能 5 秒就完了。但传统脚本换个界面就崩ARTEMIS 能自适应这是用时间换鲁棒性。成本方面主要开销在模型推理。如果用的是按 token 计费的 API一次登录任务的成本大概在几毛钱到一块钱之间。对于高频任务这个成本需要认真算账。优化方向是减少不必要的感知循环比如连续输入多个字段时可以合并成一次决策以及用更小的模型做感知。4.3 什么时候该用 ARTEMIS什么时候该退回传统方案这是最实际的问题。我的判断标准是看界面的稳定性和任务的复杂度。如果界面非常稳定比如自家 App 的固定流程任务也很固定那传统方案更快更省。ARTEMIS 的优势在于处理变化如果根本没有变化它的优势就发挥不出来。如果界面经常变、或者要处理多个不同 App、或者任务本身需要一定的判断能力比如如果弹出了更新提示就点取消否则继续那 ARTEMIS 的价值就体现出来了。还有一个维度是开发成本。传统方案写脚本你得先熟悉控件树、调试定位遇到自绘控件还得想办法。ARTEMIS 的开发成本主要在任务描述和 prompt 调优上不需要深入理解每个界面的控件结构。对于不熟悉 Android 开发的同学ARTEMIS 的上手门槛反而更低。我的建议是先用 ARTEMIS 快速跑通如果发现某个环节特别稳定且高频再把这个环节用传统方案重写。混合方案往往是最优解。5. 把 ARTEMIS 用好的几个关键技巧5.1 任务描述怎么写模型才不容易跑偏任务描述的质量直接决定了自动化能不能跑通。我踩过的坑是描述写得太笼统模型不知道具体该干什么写得太细又变成了硬编码脚本失去了自适应的意义。好的任务描述应该说清楚目标和约束但不规定具体动作。比如差的描述点击屏幕中间偏下的按钮——太具体界面一变就废。差的描述完成登录——太笼统模型不知道从哪下手。好的描述使用手机号 13800138000 登录如果出现验证码就填 1234如果出现更新提示就跳过——说清了目标、提供了必要信息、给了异常处理方向。另外把已知的界面特征写进描述也很有帮助。比如登录页顶部有 App logo中间有两个输入框这样模型在感知时能更快确认当前状态。5.2 异常处理弹窗、广告、权限请求怎么绕移动端自动化的最大敌人不是界面变化而是无处不在的干扰。弹窗、广告、权限请求、更新提示这些在传统脚本里要一个个写判断在 ARTEMIS 里可以通过统一的异常处理策略来解决。我的做法是在任务描述里加一段通用异常处理规则如果出现任何弹窗优先寻找取消关闭跳过以后再说这类按钮并点击如果出现权限请求根据任务需要选择允许或拒绝如果出现广告寻找关闭按钮通常是右上角的 X。这段规则不需要针对每个弹窗单独写模型会根据当前界面自己判断。实测下来这套通用规则能覆盖 80% 以上的干扰场景。剩下 20% 是那些没有明显关闭按钮的弹窗比如全屏广告。这种情况需要特殊处理通常是等待几秒后自动消失或者用返回键退出。5.3 日志与回放出问题时怎么快速定位ARTEMIS 跑出问题时定位问题的关键是完整的日志和截图记录。我建议在配置里打开详细日志并且把每次感知的截图都存下来。排查问题的顺序是看最后一张截图确认界面实际长什么样和模型识别的是否一致。看感知日志模型识别出了哪些元素有没有漏识别或错识别。看决策日志模型基于识别结果做了什么决策这个决策合不合理。看执行日志动作有没有真正执行执行结果是什么。大部分问题在前两步就能定位。如果是感知错了就优化截图质量或调整 prompt如果是决策错了就优化任务描述如果是执行失败就检查设备连接和权限。我习惯把每次任务的完整日志和截图打包存档出问题时可以回放整个流程。这个习惯帮我省了很多排查时间。6. 这套方案还能往哪走ARTEMIS 目前的能力边界主要卡在感知的准确率和决策的稳定性上。往未来看有几个方向是明显可以继续深挖的。一个是感知层的增强。现在主要靠单帧截图如果引入连续帧分析就能判断界面是否在加载、是否有动画、是否有弹窗正在出现。这对提升鲁棒性帮助很大。另一个是决策层的记忆机制。现在每次决策都是独立的模型不记得之前做过什么。如果加入短期记忆让模型知道我刚才已经点过获取验证码了现在应该等验证码而不是再点一次就能避免很多重复操作。还有一个是多设备协同。现在 ARTEMIS 主要面向单设备如果扩展到多设备并行就能处理一些需要多机配合的场景。这个方向工程复杂度高但想象空间大。我自己在实际用下来最大的体会是视觉自动化不是要取代传统方案而是补上了传统方案够不着的那块。界面稳定、流程固定的场景传统方案依然是更优解界面多变、需要判断的场景ARTEMIS 这类方案才有用武之地。把两者结合起来才是移动端自动化的完整答案。最后分享一个小技巧如果你要跑的任务涉及多个 App 之间的跳转建议在每个 App 的入口处加一个状态锚点判断比如如果当前在微信首页就点击搜索框。这样即使跳转过程中出现了意外系统也能通过锚点重新定位而不是彻底迷失。这个技巧在我处理跨 App 任务时救过好几次场。
RELATED READING

延伸阅读

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