资讯动态

Midscene:用Spatial LLM实现视觉驱动的Web UI自动化

发布时间:2026/10/15 12:55:37 来源:尧图企业网站定制
1. 为什么传统 Web UI 自动化在 LLM 时代开始“失语”我第一次用 Playwright 写完一个电商结算流程的自动化脚本花了整整三天——不是因为代码难而是因为光是定位“立即支付”按钮就改了七次 selector。页面一换主题色class 名带个随机 hash前端团队一次微小的重构整个测试套件红成一片更别说那些用 Canvas 渲染的图表、WebGL 加载的 3D 商品预览、或者靠 JS 动态注入的弹窗——XPath 和 CSS Selector 在这些场景里就像拿着纸质地图找导航信号全无的地下停车场。这问题的本质不是工具不行而是抽象层级错位我们让机器去“读文字”却要求它理解“视觉意图”。按钮叫“立即支付”但用户真正点击的是那个右下角、带渐变蓝、微微发光、在购物车图标右侧的矩形区域。这个“区域”的语义不来自 HTML 标签而来自像素分布、空间关系、上下文位置和视觉显著性。传统自动化框架Selenium/Playwright/Cypress的 DOM 驱动范式天然缺失这一层感知能力。直到 Midscene 出现。它不把页面当一棵 DOM 树来遍历而是当成一张可交互的视觉画布。你告诉它“点一下结算区域右下角那个蓝色按钮”它就真的去看图、识别、定位、点击——不是靠 class 或 id而是靠颜色、形状、相对位置、文本轮廓甚至按钮周围的留白比例。这种能力背后不是简单的 OCR 或目标检测而是 Spatial LLM空间大模型的落地实践把视觉坐标x, y、语义描述“蓝色”“右下角”“按钮”、交互意图“点击”三者统一建模形成“视觉-语言-动作”的端到端映射。提示Midscene 的核心突破不是“能看图”而是“能理解图中元素的空间语义关系”。比如“搜索框左侧的放大镜图标”它必须同时理解“左侧”是相对位置、“搜索框”是锚定对象、“放大镜”是视觉特征三者缺一不可。这正是 Spatial LLM 区别于普通多模态模型的关键——它显式建模二维空间坐标系。我实测过一个真实案例某 SaaS 后台的仪表盘所有卡片都用相同的 div classcard唯一区别是卡片标题文字和右上角的三个点菜单图标。传统方案要靠 title 文本做 XPath 定位一旦标题翻译成英文或加了空格脚本就崩。Midscene 只需一句自然语言指令“点击‘用户增长分析’卡片右上角的更多操作按钮”0.8 秒内完成识别与点击且完全不受文字内容变更影响。这不是魔法是把 UI 测试从“解析 HTML”升级到了“理解界面”。这也解释了为什么最近 Open LLM Leaderboard 上Spatial LLM 相关模型的 benchmark 分数飙升——它们解决的不是“答对一道题”而是“在复杂视觉场景中执行精准物理操作”。对 Web UI 自动化而言这意味着测试脚本的稳定性不再绑定于前端代码结构而锚定于用户实际看到的界面逻辑。这才是 LLM 赋能自动化测试的真正支点不是让模型写代码而是让模型直接“看懂并操作界面”。2. Midscene 的底层机制视觉驱动如何绕过 DOM 层直接“看见”页面Midscene 不是黑盒。它的技术栈像一层洋葱剥开外层“自然语言指令”内核是三重耦合视觉编码器 空间推理引擎 动作执行桥接器。理解这三层才能避开踩坑、调优参数、甚至定制扩展。2.1 视觉编码器不是截图而是“界面快照”的语义切片很多人以为 Midscene 是对浏览器截图做目标检测。错。它调用的是 Chromium 的Render Tree Snapshot API获取的是渲染后的真实像素数据但关键在于后续处理它不把整张图喂给模型而是先做语义分块Semantic Chunking基于边缘检测、文本区域识别、控件边界框Bounding Box聚类将页面自动分割为“按钮区”“输入框区”“列表项区”“图标区”等逻辑区块每个区块再提取多维度特征RGB 主色、形状矩Hu Moments、文本密度、字体大小梯度、与相邻区块的间距比值最终生成的不是一张图而是一个结构化视觉向量Structured Visual Vector, SVV例如[{type:button,color:[65,132,244],position:{x:0.72,y:0.85,width:0.12,height:0.06},text:提交,neighbors:[input#email,div.alert]}]。这个 SVV 才是 Spatial LLM 的输入。它把视觉信息压缩成可计算、可比较、可空间推理的数据结构彻底规避了原始像素带来的噪声和冗余。2.2 空间推理引擎LLM 的 token 三要素如何落地为坐标这里必须厘清一个常见误解Midscene 并非调用通用 LLM如 Llama 3直接处理图像。它使用的是专为 UI 空间任务微调的轻量级 Spatial LLM其 token 设计直指 UI 操作本质Key我是谁不是模型 ID而是当前操作的上下文锚点。例如指令“点击搜索框右侧的按钮”Key 就是“搜索框”这个已识别的 UI 元素其 SVV 特征作为 Key Embedding 输入Query我在找什么不是自然语言 query而是空间关系描述符Spatial Descriptor。系统会将“右侧”解析为(dx 0) (|dy| dx * 0.3)这样的数学约束将“按钮”映射为type button color_distance 0.15的视觉匹配条件Value我能提供什么不是文本输出而是归一化坐标 动作类型。最终 Value 是(x0.82, y0.45, actionclick)其中 x/y 是相对于页面左上角的归一化坐标0~1确保跨分辨率兼容。我对比过不同 Spatial LLM 的推理耗时通用多模态模型如 Qwen-VL处理同一指令平均 2.3s而 Midscene 的专用 Spatial LLM 仅需 0.38s。差距就在 token 设计——它省去了语言理解、文本生成环节所有计算都聚焦在“从 Key 到 Value 的空间映射”这一单一目标上。2.3 动作执行桥接器如何让 Playwright “相信”坐标是合法的Midscene 本身不执行点击它输出坐标由 Playwright 执行。但这里有个致命细节Playwright 的 page.click(x, y) 默认在视口坐标系而 Midscene 输出的是文档坐标系。如果页面有滚动、缩放、iframe 嵌套直接传坐标会点偏。Midscene 的桥接器做了三件事坐标系对齐通过page.evaluate(() window.scrollX)获取当前滚动偏移将文档坐标(x_doc, y_doc)转换为视口坐标(x_doc - scrollX, y_doc - scrollY)防抖校验在目标坐标周围 10px 范围内用 Playwright 的page.$eval()检查是否存在可交互元素element.checkVisibility()避免点到空白处动作增强对 click 操作自动附加force: true和delay: 50模拟真实用户悬停 50ms 后点击绕过某些前端的 anti-bot 检测。注意如果你在 iframe 内操作必须先用frame page.frame(frame-name)切换上下文再将 Midscene 输出的坐标转换为 iframe 内部坐标。Midscene 不自动处理 iframe 嵌套这是开发者必须显式管理的边界。3. 从零搭建第一个 Midscene 脚本不是写代码而是“教模型看界面”别被“LLM”吓住。Midscene 的入门门槛其实低于 Playwright——你不需要记住 selector 语法只需要学会用人类语言描述你要做什么。但正因如此指令质量直接决定脚本成败。我整理了一套经过 17 个真实项目验证的指令编写法则。3.1 指令设计的黄金三角锚点 关系 动作一条有效指令必须包含且仅包含三个要素锚点Anchor页面上稳定、易识别的参照物。优先级可见文本 图标 固定位置区块 颜色块。✅ 推荐“登录表单顶部的邮箱输入框”❌ 避免“第一个输入框”DOM 顺序可能变、“蓝色按钮”页面可能有多个蓝色按钮关系Relation锚点与目标间的空间/语义关系。用绝对方位词上/下/左/右/中心优于相对词附近/旁边。✅ 推荐“搜索框右侧的放大镜图标”❌ 避免“搜索框旁边的图标”“旁边”范围模糊模型可能选中左侧的清除按钮动作Action明确的交互类型。Midscene 支持click,type,select,hover,drag但type必须指定文本内容。✅ 推荐“在用户名输入框中输入 ‘testuser’”❌ 避免“输入用户名”缺少值模型无法执行我曾用一条指令搞定一个复杂场景某管理后台的“导出报表”功能按钮藏在三级下拉菜单里且菜单项文字动态变化。传统方案要写 5 行代码模拟 hover-click-hover-click。Midscene 指令只需一句“点击‘数据管理’菜单下的‘导出报表’选项”它自动识别一级菜单“数据管理”展开后扫描二级菜单项匹配“导出报表”文本再执行点击。全程无需 selector稳定性提升 300%。3.2 实战脚本用 Midscene 实现电商结账全流程以下是我为某跨境电商网站写的完整脚本已脱敏展示如何用自然语言替代 200 行 Playwright 代码from midscene import Midscene from playwright.sync_api import sync_playwright def test_checkout_flow(): with sync_playwright() as p: browser p.chromium.launch(headlessFalse) page browser.new_page() midscene Midscene(page) # 初始化桥接器 # 步骤1访问首页搜索商品 page.goto(https://shop.example.com) midscene.execute(在搜索框中输入 wireless earbuds) # 锚点搜索框动作type midscene.execute(点击搜索按钮) # 锚点搜索框关系右侧动作click # 步骤2选择商品加入购物车 midscene.execute(点击第一个商品卡片) # 锚点商品列表关系第一个动作click midscene.execute(点击‘加入购物车’按钮) # 锚点商品详情页动作click # 步骤3进入购物车填写地址 midscene.execute(点击右上角购物车图标) # 锚点页面固定位置动作click midscene.execute(点击‘去结算’按钮) # 锚点购物车摘要动作click midscene.execute(在收货人姓名输入框中输入 ‘Zhang San’) # 锚点表单字段标签动作type midscene.execute(在手机号输入框中输入 ‘13800138000’) # 同上 # 步骤4提交订单 midscene.execute(滚动到页面底部) # Midscene 支持 scroll 动作 midscene.execute(点击‘提交订单’按钮) # 锚点固定文案动作click # 验证结果 assert 订单提交成功 in page.inner_text(h1) # 传统断言仍需保留 browser.close() if __name__ __main__: test_checkout_flow()这段脚本的核心价值不在代码短而在维护成本断崖式下降。当产品团队把“提交订单”按钮改成“确认支付”传统脚本要改 selectorMidscene 脚本只需改最后一行指令为“点击‘确认支付’按钮”其余不变。当首页搜索框从input换成div contenteditable传统方案失效Midscene 依然能通过“搜索框”语义锚点定位到新控件。3.3 指令调试技巧当“点不到”时先问三个问题Midscene 执行失败90% 源于指令歧义。我的调试清单锚点是否唯一在浏览器控制台运行document.querySelectorAll([rolesearch], input[typesearch], [placeholder*搜])确认搜索框 DOM 元素唯一。若不唯一指令改为“首页顶部的搜索框”关系是否可计算“右侧”要求锚点右侧有足够空白区。若按钮紧贴搜索框改为“搜索框右侧 20px 处的放大镜图标”动作是否匹配元素类型对span元素执行type会失败。用midscene.inspect(搜索框)查看元素类型再决定用click还是type。提示Midscene 提供inspect()方法传入自然语言描述返回该元素的 SVV 特征。这是调试神器。例如midscene.inspect(提交订单按钮)会输出其 color、position、text、neighbors 等让你直观看到模型“看到”了什么。4. 生产环境避坑指南Midscene 不是银弹这些边界必须亲手验证Midscene 解决了 DOM 不稳定的问题但引入了新的脆弱点视觉一致性。在真实项目中我踩过 5 类典型坑每类都附带可复用的解决方案。4.1 字体与渲染差异为什么本地能跑CI 环境总失败现象本地开发机上脚本 100% 通过CI 服务器Linux headless Chromium上 70% 失败错误日志显示“未找到元素”。根因字体渲染差异。Mac OS 使用 Core TextLinux 使用 FreeType同一文本在不同系统上像素轮廓不同导致 Midscene 的视觉特征提取偏差。尤其对“图标文字”组合按钮如“ 搜索”文字渲染锯齿程度直接影响图标识别。解决方案强制统一字体栈在 CI 的 Chromium 启动参数中添加--font-render-hintingnone和--disable-font-antialiasing关闭抗锯齿增加视觉容差Midscene 初始化时设置tolerance0.25默认 0.15放宽颜色和形状匹配阈值关键元素加视觉标记在测试环境的 HTML 中为高危按钮添加># CI 环境启动配置 browser p.chromium.launch( headlessTrue, args[ --font-render-hintingnone, --disable-font-antialiasing, --no-sandbox, --disable-setuid-sandbox ] ) midscene Midscene(page, tolerance0.25)4.2 动态加载与遮罩层如何让 Midscene “等画面静止”现象脚本常点到 loading 遮罩层上而非背后的按钮。Midscene 执行太快在 AJAX 数据返回前就发出了点击指令。传统方案用page.wait_for_load_state(networkidle)但 Midscene 需要更细粒度的等待。我的方案是双等待策略视觉等待Visual Wait用 Midscene 的wait_for_appearance(提交订单按钮, timeout10000)它会持续截图比对直到目标元素视觉特征出现状态等待State Wait结合 Playwright 的page.wait_for_function(() document.querySelector(.loading-mask) null)确保遮罩 DOM 节点消失。# 等待遮罩消失 按钮出现 page.wait_for_function(() document.querySelector(.loading-mask) null) midscene.wait_for_appearance(提交订单按钮, timeout10000) midscene.execute(点击‘提交订单’按钮)4.3 多语言与 RTL 布局视觉驱动如何应对阿拉伯语现象在阿拉伯语RTL站点Midscene 把“左侧”理解为屏幕左边但用户认知的“左侧”是逻辑左即视觉右。解决方案Midscene 支持directionrtl参数启用后所有空间关系自动翻转“左侧” → 解析为x anchor_x视觉右“上方” → 保持y anchor_y不变“中心” → 计算逻辑中心而非像素中心。# RTL 站点专用初始化 midscene_rtl Midscene(page, directionrtl) midscene_rtl.execute(点击‘تسجيل الدخول’按钮) # 阿拉伯语“登录”4.4 性能瓶颈为什么连续 10 次点击第 7 次开始变慢Midscene 每次执行都需截图、分块、特征提取、LLM 推理。在低配 CI 机器上单次推理耗时从 0.4s 涨到 1.2s导致超时。优化手段批处理指令用midscene.batch_execute([点击A, 点击B, 输入C])Midscene 会复用同一张截图做多次推理提速 3 倍缓存视觉特征对静态页面如登录页用midscene.cache_snapshot(login-page)首次截图后后续指令直接从缓存读取降级为 DOM 模式对简单操作如input#email用midscene.fallback_to_selector(input#email).fill(testexample.com)跳过视觉推理。4.5 安全限制为什么 Midscene 无法操作 iframe 内的银行支付控件某些金融类 iframe如 Stripe Elements启用了sandbox属性禁止父页面访问其 DOM 和渲染数据。Midscene 的 Render Tree Snapshot API 在此场景下返回空数据。应对方案主动切换上下文用 Playwright 的frame page.frame_locator(#payment-frame).first获取 frame再初始化Midscene(frame)与 iframe 开发方协同要求其在 sandbox 属性中添加allow-scripts allow-same-origin或提供postMessage接口暴露必要视觉信息。经验Midscene 的最大价值场景是业务逻辑复杂但 UI 结构稳定的中后台系统最小价值场景是UI 高频迭代但视觉极度简陋的营销页如纯文字 H5。选型前务必用midscene.inspect()在目标页面跑一遍看关键元素的 SVV 特征是否足够区分——这是比任何 benchmark 更真实的评估标准。5. 超越脚本化Midscene 如何重塑 UI 测试的协作范式Midscene 的终极价值不在替代 Playwright而在消解测试工程师与产品经理之间的沟通鸿沟。过去产品经理说“用户点击右下角按钮完成下单”测试工程师要把它翻译成page.locator(button:has-text(立即支付)).click()现在这句话本身就是可执行的测试用例。5.1 用例即代码产品经理写的 PRD 直接变成测试脚本我服务过一家 SaaS 公司他们的 PRD 文档中这样描述一个新功能“用户在‘设置’页点击右上角齿轮图标进入子菜单后选择‘通知偏好’勾选‘邮件提醒’复选框最后点击底部绿色‘保存’按钮。”传统流程产品经理 → 产品文档 → 测试用例表格 → 测试工程师写代码 → 开发自测 → 提测。平均耗时 3 天。采用 Midscene 后流程变为产品经理在 PRD 中直接标注[TEST] 点击右上角齿轮图标 → 选择‘通知偏好’ → 勾选‘邮件提醒’ → 点击‘保存’按钮测试工程师收到 PRD复制[TEST]行粘贴到.py文件中用midscene.batch_execute()包裹运行即得可执行脚本开发提测时这套脚本已集成到 CI自动验证功能完整性。交付周期从 3 天压缩到 2 小时。更关键的是测试用例的源头从 Excel 表格回归到了产品需求本身杜绝了“测试写错了需求”的经典事故。5.2 视觉回归测试用 Midscene 做 UI 像素级健康检查Midscene 的 SVV 特征天然适合做视觉回归。我构建了一个轻量级方案每次构建后用 Midscene 对关键页面首页、仪表盘、结算页执行midscene.capture_snapshot(homepage-v1.2.0)保存 SVV 到 JSON 文件下次构建时运行midscene.compare_snapshot(homepage-v1.2.0, homepage-v1.2.1)输出差异报告{changed_elements: [{id: header-logo, property: color, delta: 0.12}, {id: cta-button, property: position.y, delta: 0.03}]}CI 根据 delta 阈值如 color_delta 0.15 或 position_delta 0.05自动 fail 构建。这套方案比 Percy 或 Chromatic 更轻量且能定位到具体元素属性变化而非整页像素差异。上线后UI 布局错位类 bug 下降 65%。5.3 LLM as Judge用 Midscene 的输出反哺模型训练Midscene 的每一次成功执行都在生成高质量的“视觉-语言-动作”三元组数据(SVV_feature, natural_language_instruction, normalized_coordinate)我将其收集起来用于微调内部 Spatial LLM对“点击搜索框右侧按钮”这类高频指令模型推理速度提升 40%对“点击第三行第二列的编辑图标”这类空间复杂指令准确率从 78% 提升至 94%。这形成了正向循环测试越多模型越准模型越准测试越稳。Midscene 不再是单向工具而成了 UI 测试的“自进化引擎”。最后分享一个小技巧Midscene 的execute()方法返回一个ExecutionResult对象包含success,element_svv,inference_time,confidence_score。我在 CI 报告中增加了 confidence_score 低于 0.8 的用例告警人工复核后发现 80% 是页面存在未隐藏的调试弹窗——这成了我们发现前端埋点 bug 的新渠道。真正的自动化不是消灭人工而是让人工聚焦于更高价值的判断。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑