尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

视觉AI Agent实战:从零构建能“看懂”网页的自动化工程师

视觉AI Agent实战:从零构建能“看懂”网页的自动化工程师 在自动化网页操作和界面交互领域开发者们常常面临一个选择是依赖网站提供的API接口还是另辟蹊径传统的自动化脚本如Selenium、Playwright虽然强大但面对频繁变化的网页结构、复杂的验证码或缺乏稳定API的网站时往往显得力不从心。而近期兴起的AI Agent技术特别是结合了视觉模型Vision Model的智能体正在为这一难题提供全新的、更接近人类交互方式的解决方案。本文将深入探讨为什么视觉模型驱动的AI Agent比单纯依赖API调用更具优势并提供一个从零开始的实战项目手把手教你构建一个能够“看懂”网页并执行任务的AI Engineer。1. 核心概念API驱动 vs. 视觉驱动在深入技术细节之前我们首先要厘清两种自动化范式的根本区别。1.1 传统API驱动自动化API应用程序编程接口驱动是程序与程序之间通信的标准方式。其核心思想是目标网站或应用提供一套定义良好的接口如RESTful API、GraphQL我们的程序通过发送结构化的HTTP请求包含特定的参数、认证信息来获取数据或触发操作。优点高效稳定直接与后端服务交互速度快不受前端UI变化影响只要API契约不变。数据结构化返回的数据通常是JSON或XML格式易于解析和处理。官方支持通常意味着更高的可靠性和合法性。局限与挑战可用性限制并非所有网站或应用都对外开放API特别是很多ToC产品。权限与配额开放的API通常有调用频率限制、需要申请密钥且可能收费。功能覆盖不全API可能只暴露部分核心功能许多用户界面上的操作无法通过API完成。对抗性设计一些网站为防止爬虫会故意不提供或隐藏API甚至设置反爬机制。当API不可用或功能不全时开发者往往会转向模拟浏览器操作。1.2 视觉模型驱动自动化视觉模型驱动自动化的核心是“所见即所得”。它不关心网页的底层HTML结构或提供了哪些API而是模仿人类用户通过“看”屏幕或网页截图理解屏幕上有什么元素按钮、输入框、文本然后生成相应的操作指令点击、输入、滚动。核心组件视觉感知Vision Perception使用多模态大模型如GPT-4V、Claude 3 Opus、DeepSeek-V4-Vision分析屏幕截图识别UI元素及其状态如“这是一个登录按钮”“这是一个显示‘余额100元’的文本区域”“这个输入框是空的”。任务规划与推理Task Planning Reasoning基于用户指令如“登录并查询余额”和当前屏幕状态AI Agent会规划一系列原子操作步骤“首先找到用户名输入框并输入然后找到密码输入框并输入然后找到登录按钮并点击最后找到余额显示区域并读取文本”。动作执行Action Execution将规划出的原子操作如click(x, y),type(text),read_text(region)通过自动化框架如Playwright、pyautogui在真实浏览器或应用中执行。为什么这是“正解”普适性强只要能“看到”的界面理论上就能操作。不依赖特定的API或稳定的HTML结构。更接近真实用户行为模式与人类一致能更好地处理动态内容、验证码结合专项OCR模型和复杂交互。适应性强即使UI布局改变只要视觉模型能识别出新元素Agent就能适应无需重写针对DOM结构的定位代码。意图驱动开发者只需用自然语言描述“做什么”而不需要详细编程“怎么做”提升了开发效率。2. 环境准备与核心工具选型在开始构建我们的视觉AI Agent之前需要搭建好开发环境并选择合适的技术栈。2.1 基础环境操作系统Windows 10/11, macOS, 或 Linux (Ubuntu 20.04)。本文示例基于macOS/LinuxWindows用户请注意路径差异。Python版本Python 3.9 或 3.10。推荐使用3.10以获得更好的兼容性。包管理工具pip(建议使用虚拟环境venv或conda)。2.2 核心库与工具我们将构建一个轻量级但功能完整的项目主要依赖以下库Playwright一个强大的浏览器自动化框架。比Selenium更现代API更友好且自带浏览器无需单独管理驱动。pip install playwright # 安装Playwright所需的浏览器Chromium, Firefox, WebKit playwright install chromiumOpenAI SDK (或其他多模态模型SDK)用于调用具备视觉能力的多模态大模型API。本文以OpenAI GPT-4V为例你也可以替换为Claude、DeepSeek-V4-Vision等。pip install openai你需要一个有效的OpenAI API Key并确保账户有权限调用GPT-4V模型。Pillow (PIL)Python图像处理库用于处理截图。pip install pillowPyAutoGUI(可选)用于更底层的桌面自动化如操作原生应用。本文主要用Playwright操作浏览器。pip install pyautogui2.3 项目结构规划创建一个清晰的项目目录便于管理vision_ai_agent/ ├── main.py # 主程序入口 ├── agent/ │ ├── __init__.py │ ├── vision_agent.py # AI Agent核心逻辑 │ └── actions.py # 动作执行器定义 ├── utils/ │ ├── __init__.py │ ├── screenshot.py # 截图工具 │ └── parser.py # 解析模型返回结果 ├── config.py # 配置文件API Key等 └── requirements.txt # 项目依赖3. 视觉AI Agent的核心原理拆解一个完整的视觉驱动AI Agent工作流可以分解为以下几个关键环节理解它们对后续开发和调试至关重要。3.1 工作流闭环用户指令 - Agent接收 - 截取当前屏幕 - 视觉模型分析 - 生成动作规划 - 解析并执行动作 - 观察结果 - 循环直至任务完成或失败这是一个典型的感知-规划-执行循环Perception-Planning-Action Loop。3.2 视觉提示工程如何让大模型“看懂”屏幕并给出正确操作指令是提示工程的关键。一个有效的系统提示词System Prompt应包含角色定义明确告诉模型它是一个控制计算机的AI助手。屏幕描述说明提供给它的是一张屏幕截图。目标明确清晰告知用户想要完成的任务。动作规范严格定义它可以输出的动作格式JSON或特定文本格式例如{action: click, coordinates: [x, y]}或{action: type, text: hello}。推理要求要求模型先描述它看到了什么再决定下一步做什么。3.3 动作空间设计Agent能执行的动作必须是具体且可被程序执行的。常见的原子动作包括click(x, y)在指定坐标点击。double_click(x, y)双击。right_click(x, y)右键点击。type(text)输入文本。press(key)按下某个键如Enter, Tab。scroll(delta_x, delta_y)滚动。drag_and_drop(start_x, start_y, end_x, end_y)拖拽。wait(seconds)等待。screenshot()重新截图进入下一轮循环。坐标(x, y)通常是相对于截图左上角的像素坐标。在实际执行时可能需要根据屏幕缩放比例进行转换。4. 完整实战构建一个网页自动登录与信息查询Agent接下来我们将实现一个具体的AI Agent它能够打开一个模拟的登录页面完成登录并查询页面上的用户信息。我们将使用一个本地运行的简单Flask应用作为目标网站。4.1 创建目标测试网站首先创建一个简单的Flask应用来模拟一个需要登录的网站。文件demo_website/app.pyfrom flask import Flask, render_template_string, request, session, redirect, url_for import os app Flask(__name__) app.secret_key os.urandom(24) # 一个简单的HTML登录和信息页面 LOGIN_PAGE !DOCTYPE html html headtitleDemo Login/title/head body h2欢迎来到测试网站/h2 {% if not session.get(logged_in) %} form methodpost action/login div label用户名:/label input typetext nameusername idusername_input placeholder输入admin/ /div div label密码:/label input typepassword namepassword idpassword_input placeholder输入123456/ /div button typesubmit idlogin_button登录/button /form p stylecolor:red;{{ error }}/p {% else %} h3登录成功/h3 p当前用户: strong iduser_display{{ session[username] }}/strong/p p账户余额: strong idbalance_display¥ 1,234.56/strong/p p会员等级: strong idlevel_display黄金会员/strong/p br/ a href/logoutbutton idlogout_button退出登录/button/a {% endif %} /body /html app.route(/, methods[GET]) def index(): error request.args.get(error) return render_template_string(LOGIN_PAGE, errorerror) app.route(/login, methods[POST]) def login(): username request.form.get(username) password request.form.get(password) # 简单的硬编码验证 if username admin and password 123456: session[logged_in] True session[username] username return redirect(url_for(index)) else: return redirect(url_for(index, error用户名或密码错误)) app.route(/logout) def logout(): session.clear() return redirect(url_for(index)) if __name__ __main__: app.run(debugTrue, port5000)运行这个应用python app.py。访问http://localhost:5000即可看到登录页面。4.2 构建视觉AI Agent核心模块第一步创建配置文件文件config.pyimport os from dotenv import load_dotenv load_dotenv() # 从 .env 文件加载环境变量 class Config: # OpenAI API 配置 OPENAI_API_KEY os.getenv(OPENAI_API_KEY) OPENAI_BASE_URL os.getenv(OPENAI_BASE_URL, https://api.openai.com/v1) # 支持自定义Base URL VISION_MODEL gpt-4-vision-preview # 或 gpt-4o, claude-3-5-sonnet-20241022等 # 浏览器配置 HEADLESS False # 调试时设为False可以看到浏览器操作生产环境可设为True BROWSER_TYPE chromium # chromium, firefox, webkit # 动作执行延迟秒避免操作过快被识别为机器人 ACTION_DELAY 0.5 # 确保API Key存在 assert Config.OPENAI_API_KEY, 请设置 OPENAI_API_KEY 环境变量或在 .env 文件中配置在项目根目录创建.env文件OPENAI_API_KEYsk-your-openai-api-key-here第二步实现截图工具文件utils/screenshot.pyfrom PIL import Image import io import base64 from playwright.sync_api import Page def take_screenshot(page: Page, full_page: bool False) - Image.Image: 使用Playwright对当前页面进行截图并返回PIL Image对象。 # Playwright截图返回的是bytes screenshot_bytes page.screenshot(full_pagefull_page) # 将bytes转换为PIL Image image Image.open(io.BytesIO(screenshot_bytes)) return image def image_to_base64(image: Image.Image) - str: 将PIL Image转换为Base64编码字符串用于发送给视觉API。 buffered io.BytesIO() # 保存为JPEG格式以减小体积也可用PNG image.save(buffered, formatJPEG, quality85) img_str base64.b64encode(buffered.getvalue()).decode(utf-8) return img_str第三步定义动作执行器文件agent/actions.pyimport time from playwright.sync_api import Page from config import Config class ActionExecutor: 执行AI Agent规划出的具体动作。 def __init__(self, page: Page): self.page page def execute(self, action_dict: dict): 根据动作字典执行操作。 动作字典格式示例: {action: click, coordinates: [100, 200]} action_type action_dict.get(action) if not action_type: raise ValueError(动作字典中缺少 action 字段) # 模拟人类操作延迟 time.sleep(Config.ACTION_DELAY) if action_type click: x, y action_dict.get(coordinates, [0, 0]) self.page.mouse.click(x, y) print(f[执行] 点击坐标 ({x}, {y})) elif action_type type: text action_dict.get(text, ) # 这里简化处理直接在当前焦点元素输入。更复杂的实现需要先点击输入框。 self.page.keyboard.type(text) print(f[执行] 输入文本: {text}) elif action_type press: key action_dict.get(key, Enter) self.page.keyboard.press(key) print(f[执行] 按下按键: {key}) elif action_type scroll: delta_x action_dict.get(delta_x, 0) delta_y action_dict.get(delta_y, 300) # 默认向下滚动 self.page.mouse.wheel(delta_x, delta_y) print(f[执行] 滚动: delta_x{delta_x}, delta_y{delta_y}) elif action_type wait: seconds action_dict.get(seconds, 2) time.sleep(seconds) print(f[执行] 等待 {seconds} 秒) elif action_type screenshot: print(f[执行] 请求重新截图) # 这个动作本身不执行操作由主循环处理 pass else: raise ValueError(f不支持的动作类型: {action_type})第四步构建AI Agent核心视觉模型交互与规划这是最核心的部分负责与视觉模型对话将截图和指令转化为动作。文件agent/vision_agent.pyimport json import openai from PIL import Image from config import Config from utils.screenshot import image_to_base64 class VisionAIAgent: def __init__(self): self.client openai.OpenAI( api_keyConfig.OPENAI_API_KEY, base_urlConfig.OPENAI_BASE_URL ) # 系统提示词定义了Agent的角色和能力 self.system_prompt 你是一个控制计算机的AI助手。你的任务是分析用户提供的屏幕截图理解当前界面状态并规划出下一步要执行的具体操作来完成用户的目标。 你可以执行以下类型的操作请严格按照JSON格式输出 1. 点击{action: click, coordinates: [x, y]} (x, y是截图上的像素坐标) 2. 输入文本{action: type, text: 要输入的文本} 3. 按下按键{action: press, key: Enter} (常见键Enter, Tab, Escape, ArrowUp等) 4. 滚动{action: scroll, delta_x: 0, delta_y: 300} (正数向下/向右) 5. 等待{action: wait, seconds: 2} 6. 重新截图进入下一轮分析{action: screenshot} 请按以下步骤思考 1. 描述你从截图中看到了什么例如这是一个登录页面有用户名输入框、密码输入框和登录按钮。 2. 根据用户目标和当前状态判断下一步最佳操作是什么。 3. 输出一个且仅一个JSON对象。 如果任务看起来已经完成例如成功登录并显示了用户信息你可以输出一个特殊的完成标记{status: complete, message: 任务完成描述}。 当前用户目标是{user_goal}。请开始分析。 def analyze_and_plan(self, screenshot_image: Image.Image, user_goal: str) - dict: 分析截图规划下一步动作。 返回一个动作字典或完成状态字典。 # 1. 将图片转为Base64 base64_image image_to_base64(screenshot_image) # 2. 构建消息 messages [ { role: system, content: self.system_prompt.format(user_goaluser_goal) }, { role: user, content: [ { type: text, text: 这是当前的屏幕截图。请分析并给出下一步动作的JSON。 }, { type: image_url, image_url: { url: fdata:image/jpeg;base64,{base64_image} } } ] } ] # 3. 调用视觉模型 try: response self.client.chat.completions.create( modelConfig.VISION_MODEL, messagesmessages, max_tokens500, temperature0.1, # 低温度保证输出稳定 ) response_text response.choices[0].message.content print(f[AI响应] 原始响应:\n{response_text}) # 4. 尝试从响应中提取JSON # 模型可能在JSON前后添加了描述我们需要提取出JSON部分 lines response_text.strip().split(\n) json_str None for line in lines: line line.strip() if line.startswith({) and line.endswith(}): json_str line break # 有时JSON被包裹在json 标记中 if json in line: start_idx response_text.find(json) 7 end_idx response_text.find(, start_idx) json_str response_text[start_idx:end_idx].strip() break if not json_str: # 如果没找到明确的JSON尝试将整个响应解析为JSON有时模型只输出JSON json_str response_text action_dict json.loads(json_str) return action_dict except json.JSONDecodeError as e: print(f[错误] 无法解析AI响应为JSON: {e}) print(f原始响应: {response_text}) # 返回一个安全动作等待并重新截图 return {action: wait, seconds: 3} except Exception as e: print(f[错误] 调用AI API失败: {e}) return {action: wait, seconds: 5}第五步编写主程序串联整个流程文件main.pyimport time from playwright.sync_api import sync_playwright from config import Config from utils.screenshot import take_screenshot from agent.vision_agent import VisionAIAgent from agent.actions import ActionExecutor def run_agent(user_goal: str, max_steps: int 20): 运行视觉AI Agent的主函数。 :param user_goal: 用户目标自然语言描述。 :param max_steps: 最大执行步骤防止无限循环。 print(f 开始执行任务: {user_goal}) print(*50) # 初始化Playwright浏览器 with sync_playwright() as p: # 启动浏览器headlessFalse便于观察 browser p.chromium.launch(headlessConfig.HEADLESS, slow_mo100) # slow_mo让动作变慢方便观察 context browser.new_context(viewport{width: 1280, height: 800}) page context.new_page() # 打开我们的测试网站 page.goto(http://localhost:5000) print( 已打开目标网站) time.sleep(2) # 等待页面加载 # 初始化Agent和执行器 agent VisionAIAgent() executor ActionExecutor(page) step_count 0 task_complete False while step_count max_steps and not task_complete: step_count 1 print(f\n 步骤 {step_count}) # 1. 感知截图 print( 截取屏幕...) screenshot take_screenshot(page) # screenshot.save(fdebug_step_{step_count}.jpg) # 调试时可保存截图 # 2. 规划AI分析截图并决定动作 print( AI分析中...) action_or_status agent.analyze_and_plan(screenshot, user_goal) # 3. 检查任务是否完成 if action_or_status.get(status) complete: print(f✅ 任务完成: {action_or_status.get(message)}) task_complete True break # 4. 执行执行AI规划的动作 if action in action_or_status: print(f 规划动作: {action_or_status}) try: executor.execute(action_or_status) except Exception as e: print(f❌ 动作执行失败: {e}) # 失败后等待一下再继续 time.sleep(2) else: print(f⚠️ AI返回了无法理解的内容: {action_or_status}) time.sleep(2) # 短暂暂停让页面状态更新 time.sleep(1) # 循环结束 if not task_complete: print(f\n⏰ 已达到最大步骤限制 ({max_steps})任务未完成。) # 保持浏览器打开一段时间供观察 print(\n任务执行结束。浏览器将保持打开10秒...) time.sleep(10) browser.close() if __name__ __main__: # 定义用户目标 goal 登录网站用户名admin密码123456然后找到并读出页面上显示的‘账户余额’和‘会员等级’信息。 # 运行Agent run_agent(goal, max_steps15)4.3 运行与验证启动测试网站在一个终端窗口进入demo_website目录运行python app.py。确保网站运行在http://localhost:5000。运行AI Agent在项目根目录确保已安装所有依赖并配置好.env文件中的API Key。然后运行python main.py观察执行过程浏览器窗口会自动打开并访问测试网站。你会看到AI Agent在控制台输出思考过程并自动执行点击、输入等操作。最终它应该能成功登录并在控制台输出任务完成的信息。预期控制台输出示例 开始执行任务: 登录网站用户名admin密码123456然后找到并读出页面上显示的‘账户余额’和‘会员等级’信息。 已打开目标网站 步骤 1 截取屏幕... AI分析中... [AI响应] 原始响应: 这是一个登录页面包含“用户名”和“密码”输入框以及一个“登录”按钮。用户目标是登录并查询信息。第一步是输入用户名。 {action: type, text: admin} 规划动作: {action: type, text: admin} [执行] 输入文本: admin 步骤 2 ... 步骤 5 截取屏幕... AI分析中... [AI响应] 原始响应: 登录成功。页面显示了用户信息“当前用户: admin”、“账户余额: ¥ 1,234.56”、“会员等级: 黄金会员”。用户目标是读取余额和等级信息这些信息已清晰显示。任务完成。 {status: complete, message: 已成功登录并获取信息账户余额为 ¥ 1,234.56会员等级为 黄金会员。} ✅ 任务完成: 已成功登录并获取信息账户余额为 ¥ 1,234.56会员等级为 黄金会员。5. 常见问题与排查思路在实际开发和使用视觉AI Agent时你可能会遇到以下问题问题现象可能原因排查与解决思路AI返回的动作JSON解析失败1. 模型没有严格按格式输出。2. 响应中包含多余的解释文本。1.强化系统提示词在提示词中更严格地要求“只输出JSON”。2.改进解析逻辑像我们代码中那样尝试从响应文本中提取{...}部分或json ...部分。3.使用Function Calling如果模型支持可以定义“动作”函数让模型以工具调用的方式返回结构化数据。Agent点击位置不准1. 坐标计算错误截图坐标 vs 屏幕坐标。2. 浏览器窗口位置或缩放比例影响。3. 页面动态加载元素位置变化。1.使用相对坐标让模型输出基于截图比例的相对坐标如百分比然后在执行时换算为绝对坐标。2.结合DOM定位混合模式先用视觉模型识别元素如“登录按钮”然后用Playwright的locator通过文本或属性来精准定位并点击这比纯坐标更稳定。3.增加重试和等待在执行动作前等待元素稳定。任务陷入死循环1. AI对状态判断错误如认为未登录但实际上已登录。2. 动作执行后页面状态未如预期变化。1.设置最大步数如我们代码中的max_steps。2.增强状态感知在提示词中要求AI更详细地描述状态变化或引入“历史截图”对比来判断是否进展。3.定义明确的终止状态在系统提示词中清晰定义“任务完成”的标准。API调用超时或报错1. 网络问题。2. API密钥无效或额度不足。3. 模型暂时不可用。1. 检查网络连接和API Base URL。2. 验证API Key权限和余额。3. 实现重试机制和降级策略如换用备用模型。4. 错误400 the thinking_budget parameter must be a positive integer通常是特定API的参数错误检查调用参数。处理复杂验证码或动态内容纯视觉模型可能无法可靠识别扭曲验证码或极快闪动的内容。1.集成专用OCR服务如Tesseract或商业OCR API处理验证码。2.使用更强大的多模态模型如GPT-4o或Claude 3.5 Sonnet在视觉理解上更强。3.人为干预设计对于无法逾越的障碍设计流程暂停并请求人工帮助。6. 最佳实践与工程化建议将视觉AI Agent从实验原型变为可靠的生产力工具需要考虑以下工程化因素6.1 提示词优化分步引导对于复杂任务可以设计多轮提示。第一轮让模型描述整体界面和可选操作第二轮再生成具体动作。提供示例在系统提示词中提供1-2个输入输出示例Few-shot Learning能显著提升模型输出格式的准确性。元素描述标准化鼓励模型使用一致的词汇描述UI元素如“左上角的搜索框”、“蓝色的提交按钮”便于后续处理。6.2 动作执行的鲁棒性混合定位策略不要完全依赖坐标。结合视觉识别和Playwright的语义定位如page.get_by_role(button, name登录)是更稳健的方案。动作后验证执行一个动作后等待并检查页面是否发生预期变化如URL改变、特定元素出现/消失再决定下一步。异常处理与重试对点击、输入等操作添加try-except失败后可以重试或尝试替代方案。6.3 性能与成本控制截图优化截取全屏可能不必要且增加API负载。可以只截取页面可视区域或者通过DOM分析预判关键区域进行局部截图。缓存与记忆让Agent记住已经尝试过的操作和结果避免重复分析相同状态的截图。模型选择根据任务复杂度选择性价比合适的模型。简单的元素识别可能不需要最顶级的视觉模型。6.4 安全与合规合法授权仅对你有权自动化的网站或应用使用此技术。遵守网站的robots.txt和服务条款。速率限制模拟人类操作速度添加随机延迟避免对目标服务器造成负载攻击。数据隐私截图可能包含敏感信息。确保传输到云端API的图片数据符合隐私政策或考虑使用本地部署的视觉模型。视觉模型驱动的AI Agent为自动化打开了一扇新的大门它不再受制于API的有无而是直接与图形界面交互更通用、更灵活。虽然目前其在复杂任务的成功率、执行速度和成本上可能还无法完全替代精心编写的传统自动化脚本但对于快速原型开发、处理无API的遗留系统或应对频繁变化的UI来说它无疑是一个强大的工具。
返回列表