基于多模态大模型的网页交互智能体:视觉感知与记忆驱动的自动化实践

基于多模态大模型的网页交互智能体:视觉感知与记忆驱动的自动化实践 1. 项目概述当AI学会“看见”与“记忆”最近在折腾一个挺有意思的东西我把它叫做“能看会记的多模态网页导航智能体”。简单来说就是造一个能像人一样浏览网页的AI助手。它不仅能“看见”网页上的文字、图片、按钮还能“记住”自己刚才点了哪里、看到了什么然后决定下一步该做什么。这听起来是不是有点像给浏览器装了个会思考的大脑这个想法的核心源于一个很实际的痛点现在的自动化工具无论是RPA机器人流程自动化还是基于API的脚本在处理现代动态网页时都显得力不从心。它们要么依赖脆弱的XPath或CSS选择器页面结构一变就崩要么需要网站提供完善的API这往往是奢望。而一个融合了视觉“See”和记忆“Remember”能力的智能体目标就是突破这些限制实现更通用、更鲁棒的网页交互自动化。想象一下这些场景你需要每天登录某个内部系统手动查询几十条数据并整理成报表或者你想自动比价但目标商品信息散落在不同电商平台结构迥异的页面上又或者你需要从一堆学术论文网站里按照特定逻辑点击、筛选、下载文献。这些任务对人来说繁琐对传统自动化工具来说棘手但恰恰是“能看会记”的智能体大显身手的地方。它不关心后台代码怎么变它像人一样用眼睛看屏幕用大脑记步骤最终完成任务。接下来我就把自己从零搭建这样一个智能体的思路、踩过的坑和最终方案详细拆解一遍。2. 核心设计思路模拟人类浏览的认知闭环要造一个能真正“浏览”网页的智能体不能只靠蛮力。我的设计核心是模拟人类与网页交互的完整认知闭环感知Perception、理解Comprehension、规划Planning、行动Action、记忆Memory。这五步形成一个循环让智能体越用越“聪明”。2.1 感知层超越HTML的“视觉”理解传统网页自动化严重依赖解析HTML DOM树。但现代网页大量使用JavaScript动态渲染元素ID随机生成CSS类名混淆压缩导致DOM结构极其不稳定。依赖它就像在流沙上盖房子。因此我的智能体首要且核心的感知方式是基于视觉的。我使用无头浏览器如Playwright或Selenium来加载和渲染网页然后定期对页面进行截图。但这不仅仅是截图关键在于下一步使用多模态大模型MLLM进行视觉问答VQA。我将整个屏幕截图或者通过算法聚焦到的可能交互区域如按钮、输入框的截图连同我的文本指令例如“请找出页面上的‘登录’按钮”一起输入给MLLM。MLLM会像人一样“看”图并直接用坐标框bounding box或描述告诉我目标在哪里。注意这里MLLM的选择至关重要。你需要权衡精度、速度和成本。开源模型如LLaVA、Qwen-VL在本地部署可控但识别精度和复杂布局理解可能稍逊闭源API如GPT-4V、Gemini Pro Vision精度高但会产生API调用费用和延迟。我的经验是对于常规按钮、文本识别当前的开源模型已堪用对于极其复杂或模糊的界面偶尔调用一次顶级闭源API作为补充性价比很高。除了视觉DOM和可访问性Accessibility树信息作为重要的补充感知通道。虽然不稳定但DOM中的button、input标签以及ARIA属性如aria-label能提供视觉难以捕捉的语义信息例如一个图标按钮的功能。我将视觉信息和有限的、高可信度的DOM信息如标签名、关键属性融合形成对当前页面状态的综合理解。2.2 记忆与状态管理给智能体一个“工作记忆”这是实现“Remember”的关键。智能体不能是“金鱼脑”它必须记住我来自哪个页面我刚刚做了什么我的目标是什么当前页面有什么我设计了一个分层的记忆系统会话记忆Session Memory存储本次任务的核心目标、已完成的步骤列表、遇到的关键异常如弹窗、验证码。这相当于智能体的“任务清单”。页面记忆Page Memory对于当前页面智能体需要记住一个简化的“心智地图”。这不仅仅是截图而是通过MLLM对页面进行摘要后得到的关键信息结构。例如“这是一个商品详情页顶部有导航栏中间是商品图片和标题‘XXX手机’价格是‘2999’下方有一个蓝色的‘加入购物车’按钮。” 这个结构化摘要比纯图像更易于后续的规划和决策。历史轨迹History Trail按顺序记录每一次行动点击、输入、滚动和行动前后的页面摘要。当智能体陷入循环或需要回溯时这个轨迹是重要的诊断依据。实现上我使用向量数据库如ChromaDB、FAISS来存储页面摘要的嵌入embedding。当智能体进入一个新页面时它会将当前页面摘要与记忆中的历史页面摘要进行相似度搜索。如果发现高度相似它就能“回忆”起“哦这个页面我来过上次我点了这里然后成功了/失败了。” 这能有效避免在相似页面间无限循环。2.3 规划与决策引擎从目标到动作的翻译器有了感知和记忆智能体需要决定“现在该做什么”。这就是规划器的职责。我采用了基于大语言模型LLM的规划器。我会将以下信息构造成提示词Prompt输入给LLM任务目标用户想要什么例如“在XX网站搜索‘无线耳机’按价格排序将前三名商品标题和价格保存下来”当前页面摘要来自页面记忆。行动历史最近几步做了什么。可用动作集智能体能执行的基本操作如click(x, y),type(text),scroll(direction),wait(seconds),extract_text(region)等。LLM基于这些上下文输出下一个最合理的动作以及执行该动作所需的参数例如click(‘蓝色登录按钮’)。这里LLM的强大推理能力得以发挥它能理解“要搜索得先找到搜索框”也能处理“如果登录失败我应该尝试找回密码”这样的异常分支。实操心得规划器的Prompt工程是成败的关键。你需要明确界定LLM的角色“你是一个网页浏览助手”给出清晰、具体的输出格式要求比如严格规定用JSON格式输出{“action”: “click”, “target”: “登录按钮”, “reason”: “...”}并提供大量高质量的例子Few-shot Learning。否则LLM可能会输出天马行空、无法执行的指令。2.4 行动执行器从指令到浏览器操作的桥梁决策引擎输出一个抽象指令如“点击登录按钮”行动执行器负责将其转化为具体的、可执行的操作。这涉及到从“登录按钮”这个描述到屏幕上具体坐标(x, y)的映射。这个过程通常分两步目标定位再次调用MLLM将当前屏幕截图和“请高亮标出‘登录’按钮”的指令传入获取该按钮的精确坐标框。操作执行通过无头浏览器的自动化接口如Playwright的page.mouse.click(x, y)在坐标中心点执行点击。对于输入操作则可能需要先点击输入框定位再执行键盘输入。执行后执行器会等待页面进入一个“稳定状态”例如网络请求基本完成主要元素加载完毕然后触发新一轮的感知开始下一个循环。3. 技术栈选型与搭建实战理论说完了我们来点实在的。下面是我经过多次迭代后认为比较稳定和高效的一个技术栈组合和搭建过程。3.1 核心组件选型解析浏览器自动化框架Playwright为什么是它相比SeleniumPlaywright为现代Web而生对动态页面、单页应用SPA的支持更好API更现代简洁。它内置了自动等待机制能减少很多“元素未加载”的坑。其强大的截图、录制和调试工具也对开发非常友好。替代方案Puppeteer但生态稍逊于Playwright、Selenium更传统社区资源多。多模态大模型MLLMQwen-VL-Plus / GPT-4V本地部署优选Qwen-VL系列。通义千问的开源视觉模型表现相当不错支持中英文对常见UI元素的识别精度能满足大部分需求。使用Ollama或直接调用其开源代码可以本地部署数据隐私有保障无调用成本。云端API备用GPT-4V或Gemini Pro Vision。当遇到非常棘手的界面如极度复杂的图表、验证码或者需要更深度的图像推理时可以偶尔调用这些顶级API。将它们作为“专家顾问”而非主力。大语言模型LLM规划器DeepSeek / GPT-4主力DeepSeek。国内可顺畅访问性能强悍上下文窗口长支持128K价格极具竞争力。其推理能力足够胜任网页遍历的规划任务。关键点无论用哪个LLM一定要开启函数调用Function Calling能力。这样你可以预定义好click,type等动作函数让LLM直接返回结构化的调用参数极大简化后续处理。记忆模块ChromaDB SQLite向量记忆ChromaDB。轻量级易于使用适合存储页面摘要的向量嵌入用于快速相似度检索。结构化记忆SQLite。用于存储任务日志、行动历史、会话状态等关系型数据。简单可靠无需额外服务。开发语言Python生态无敌。Playwright、各种AI模型客户端、数据库驱动在Python上都有最成熟的支持。3.2 环境搭建与核心代码结构假设我们的项目名为web_agent目录结构如下web_agent/ ├── agent.py # 智能体主循环 ├── perception.py # 感知模块截图、MLLM调用 ├── memory.py # 记忆模块向量库、历史存储 ├── planner.py # 规划模块LLM调用、决策 ├── executor.py # 执行模块操作浏览器 ├── config.yaml # 配置文件API密钥、模型路径等 └── requirements.txt1. 环境准备与依赖安装requirements.txt示例playwright1.40.0 openai1.0.0 # 如需用GPT qianfan0.3.0 # 或其他Qwen SDK chromadb0.4.0 sqlalchemy2.0.0 pyyaml6.0安装后别忘记安装Playwright的浏览器内核playwright install chromium2. 感知模块核心代码片段perception.py中的关键函数展示了如何用Qwen-VL进行元素定位import base64 from io import BytesIO from PIL import Image # 假设使用百度千帆的Qwen-VL API本地部署可调用类似ollama import qianfan class VisualPerceptor: def __init__(self, api_key, secret_key): self.visual_model qianfan.ChatCompletion(akapi_key, sksecret_key) def locate_element(self, screenshot_pil_image, instruction): 给定截图和指令返回目标元素的坐标 # 将PIL图像转换为base64 buffered BytesIO() screenshot_pil_image.save(buffered, formatPNG) img_base64 base64.b64encode(buffered.getvalue()).decode(utf-8) # 构建给MLLM的Prompt messages [ { role: user, content: [ {type: text, text: f请仔细查看这张网页截图。{instruction} 请直接以JSON格式回答包含x1, y1, x2, y2四个键代表目标元素左上角和右下角的坐标。如果未找到返回null。}, {type: image_url, image_url: {url: fdata:image/png;base64,{img_base64}}}, ] } ] try: resp self.visual_model.do(messagesmessages, modelQwen-VL-Plus) # 解析返回的JSON这里需要处理模型输出的文本实际中需要更健壮的解析 result_text resp[body][result] # 示例从result_text中提取坐标此处简化 # 实际应用中需要使用正则表达式或JSON解析库来提取结构化的坐标数据 import json import re json_match re.search(r\{.*\}, result_text, re.DOTALL) if json_match: coord json.loads(json_match.group()) return coord return None except Exception as e: print(f视觉定位失败: {e}) return None3. 智能体主循环逻辑agent.py中的简化主循环体现了“感知-规划-行动-记忆”的闭环class WebTraversalAgent: def __init__(self, task_goal): self.task_goal task_goal self.playwright sync_playwright().start() self.browser self.playwright.chromium.launch(headlessFalse) # 调试时可设为False self.page self.browser.new_page() self.memory MemoryManager() self.planner PlannerLLM() self.perceptor VisualPerceptor() self.executor ActionExecutor(self.page) def run(self, start_url): self.page.goto(start_url) self.memory.record_session_start(self.task_goal, start_url) max_steps 50 for step in range(max_steps): # 1. 感知获取当前页面状态 screenshot self.page.screenshot() page_summary self.perceptor.summarize_page(screenshot) # 调用MLLM生成页面摘要 current_state { page_summary: page_summary, url: self.page.url, step: step } # 2. 记忆更新并检索相关记忆 self.memory.update_page_memory(current_state) relevant_history self.memory.retrieve_similar_history(page_summary) # 3. 规划决定下一步行动 action_plan self.planner.decide( goalself.task_goal, current_statecurrent_state, historyrelevant_history ) if action_plan.action FINISH: print(任务完成) break # 4. 执行在页面上执行动作 success self.executor.execute(action_plan, screenshot) # 5. 记忆记录本次行动及结果 self.memory.record_action(action_plan, success, current_state) # 6. 等待页面稳定 self.page.wait_for_load_state(networkidle) time.sleep(1) # 适当等待防止过快 self.browser.close() self.playwright.stop()4. 关键挑战与实战避坑指南在实际开发中理想很丰满现实很骨感。下面是我趟过的一些深水区希望能帮你绕开。4.1 动态内容与等待策略现代网页大量使用异步加载。你刚截完图内容就变了你让点击一个按钮按钮还没渲染出来。问题智能体基于过时的页面信息做出决策导致操作失败。解决方案双重等待在执行任何操作前结合使用Playwright的page.wait_for_load_state(“networkidle”)等待网络空闲和page.wait_for_selector(“selector”, state”visible”, timeout5000)等待关键元素可见。即使我们主要靠视觉但DOM的稳定是一个重要参考。感知后置在规划器决定行动后、执行器执行前重新进行一次针对性的快速感知。例如规划器说“点击搜索框”执行器在点击前再次调用视觉模型确认“搜索框”确实在当前视图中并获取最新坐标。这能应对点击前最后一刻的UI变化。设置超时与重试任何操作都应包裹在重试逻辑中。一次点击失败等待片刻如2秒重新感知页面再尝试规划或执行。4.2 多模态模型的“幻觉”与精度MLLM并非完美它可能会“看到”不存在的东西幻觉或者把按钮A误认为按钮B。问题错误的目标定位导致后续所有操作失败。解决方案提示词工程在给MLLM的指令中要极其具体和限制性。例如不说“找到按钮”而说“找到页面主要区域中文字内容为‘提交申请’的蓝色矩形按钮”。可以要求模型按置信度排序返回多个候选结果。多模型投票对于关键操作如登录按钮可以同时调用两个不同的轻量级MLLM例如Qwen-VL和一个小型的本地视觉模型。如果它们返回的坐标区域高度重叠则可信度高如果差异大则触发更保守的策略如滚动页面、调用更强的GPT-4V仲裁。结合DOM验证如果视觉模型返回了一个“登录”按钮的坐标可以尝试用这个坐标附近的DOM元素信息进行交叉验证。比如检查该坐标点附近的元素是否包含button标签或onclick属性。4.3 任务规划的长程依赖与迷失复杂任务可能需要很多步如登录-搜索-筛选-加购-下单。LLM规划器可能会在中途忘记最终目标或陷入局部循环。问题智能体在任务中途开始做无关操作或重复刷新同一页面。解决方案强化记忆检索在每一步规划时不仅提供最近几步历史还要主动从向量记忆中检索与当前页面和最终目标都相关的过去成功轨迹。这相当于给LLM看了“攻略”。子目标分解不要让LLM一次性规划50步。将大任务拆解成明确的子任务序列如[“登录网站” “搜索关键词X” “按价格排序” “提取前N个结果”]。规划器只负责完成当前子任务内的几步规划完成后由上层控制器推进到下一个子任务。这大大降低了规划的复杂度。死循环检测在记忆模块中实现简单的死循环检测。如果连续多个步骤的页面摘要向量相似度超过阈值且执行的动作也类似则判定可能陷入循环。此时可以强制触发一个“突围”动作比如滚动到页面底部、点击浏览器回退或向LLM规划器注入一个“警告你可能陷入了循环请尝试不同操作”的系统提示。4.4 处理弹窗、验证码与非标准控件这些是网页自动化的传统噩梦对智能体亦然。弹窗通过定期如每步操作后检查屏幕中央或特定区域是否有弹窗特征蒙层、固定定位的小窗口来感知。一旦检测到立即中断当前任务流将“处理弹窗”设为最高优先级子任务。弹窗的关闭按钮通常比较标准可用视觉模型定位。验证码这是目前完全自动化难以逾越的障碍。务实的做法是设计“中断点”。当视觉模型识别出验证码并有一定置信度时智能体应暂停通过日志、通知等方式告知人类干预。也可以集成第三方验证码识别服务但稳定性和成本需考量但这属于另一个专业领域。滑块、拖拽等非标准控件需要扩展执行器的能力。例如对于滑块定位滑块和轨道后使用Playwright的page.mouse.down()、page.mouse.move()、page.mouse.up()模拟拖拽。轨迹可以模拟人类先快后慢加入随机抖动。5. 效果评估与迭代优化方向搭建出原型只是第一步如何让它变得更可靠、更高效5.1 构建测试用例集不要用生产任务直接测试。建立一套涵盖不同难度的测试网页和任务简单静态页面点击链接填写表单。中等单页应用如React/Vue构建动态加载列表模态框操作。困难电商全流程搜索、筛选、加购、复杂后台管理系统导航。记录每个用例的成功率、平均步骤数、耗时。这是衡量改进效果的基线。5.2 核心优化指标任务完成率最核心的指标。有多少任务能从头到尾无需人工干预跑通平均步骤数衡量智能体的“智能”程度。步骤越少说明规划越高效绕路越少。单步操作成功率每次点击、输入等原子操作的成功比例。这直接反映感知模块的精度。耗时完成一个任务的总时间。其中包含大量的模型调用延迟是性能瓶颈所在。5.3 持续迭代策略根据测试结果有针对性地迭代如果单步操作失败率高重点优化感知模块改进MLLM提示词、引入多模型投票、增加DOM验证。如果任务完成率低常在中途迷失重点优化规划器和记忆模块改进子任务拆解算法、增强历史轨迹检索的相关性、添加更严格的死循环检测。如果耗时过长考虑优化模型调用策略对简单、重复的元素识别是否可以缓存结果是否可以用更小更快的模型能否将多个识别请求批量处理。5.4 未来的想象空间目前这个智能体还处于“项目”阶段但已经展示了强大的潜力。未来可以探索的方向自我演进让智能体从失败中学习。当任务失败时自动分析日志将“错误页面-错误操作”对作为负样本存入记忆下次遇到类似情况时优先规避。多智能体协作复杂的任务可以分解给多个 specialized 的智能体协作完成一个负责导航一个负责数据提取一个负责异常处理。与RPA工具结合将这套视觉-记忆智能体作为“先锋”处理最变化莫测的网页交互部分待进入稳定状态如数据查询结果页后再交由传统的、但更快速稳定的RPA工具进行结构化数据抓取。从我自己的实践来看构建这样一个“能看会记”的智能体最大的收获不是做出了一个多么完美的工具而是真正深入理解了让机器去“理解”和“操作”人类界面的复杂性。它不再是与后端API对话而是在前端的、为人类设计的、充满不确定性的视觉环境中进行推理和探索。每一次调试都像是在教一个孩子认识世界过程充满挑战但每当它成功完成一个复杂任务时那种成就感也是无与伦比的。这条路还很长但起点或许就从让AI学会“看见”并“记住”一个网页开始。