从零构建AI Agent:基于LangChain与Playwright的网页自动化实践

📅 2026/8/8 12:56:23
从零构建AI Agent:基于LangChain与Playwright的网页自动化实践
最近在AI Agent领域一个名为“Handoff”的新模型引起了广泛关注。根据公开信息Hark公司发布的这款“上网办事AI”在特定评测基准上取得了97.7分据称超过了GPT-5.4等模型的表现。对于开发者而言这不仅仅是一个新闻热点更预示着AI Agent智能体技术正朝着更实用、更自主的方向快速演进。本文将从一个技术实践者的角度深入探讨“Handoff”这类AI Agent所代表的技术方向、其潜在的工作原理、以及作为开发者我们如何理解和跟进这一波技术浪潮。我们将避开浮夸的对比聚焦于可落地的技术概念、架构思路以及当前开源生态中可供学习与实验的工具。1. 理解“Handoff”与AI Agent的核心概念在讨论具体模型之前我们需要先厘清几个关键概念。所谓“上网办事AI”其本质是一个智能体AI Agent它能够理解用户的自然语言指令自主规划并执行一系列操作来完成特定任务例如信息检索、表单填写、在线购物等。这与传统的对话式AI如仅用于问答的ChatGPT有本质区别。1.1 什么是AI AgentAI Agent通常指一个具备感知Perception、决策Decision、执行Action能力的智能系统。它通过工具Tools与环境通常是网页、操作系统或API进行交互。感知理解用户的指令和当前环境的状态如网页的HTML结构。规划与决策将复杂任务分解为可执行的子步骤并决定每一步该调用哪个工具。执行通过调用具体的工具如点击按钮、输入文本、导航来改变环境状态逐步逼近任务目标。1.2 Handoff可能涉及的技术栈虽然Handoff的详细架构未公开但结合当前AI Agent领域的最佳实践我们可以推测其技术栈可能包含以下层次强大的基础模型LLM作为Agent的“大脑”负责理解、规划和推理。需要极强的上下文理解、指令遵循和复杂任务分解能力。工具调用Tool Calling能力模型必须能够精确地识别何时、以及如何使用外部工具如浏览器操作、API调用。环境感知与状态管理如何将图形化的网页或软件界面转化为模型可以理解的文本或结构化数据如通过DOM树、辅助功能树或视觉模型。记忆与反思机制Agent需要记住之前的操作和结果并在遇到错误时能够反思并调整策略。安全与可控性确保Agent的操作符合预期避免执行危险或未经授权的动作。1.3 相关评测基准Online-Mind2WebHandoff提到的97.7分很可能是在某个类似Online-Mind2Web的基准测试上取得的。Mind2Web是一个用于评估AI Agent在真实网站环境中完成任务能力的权威数据集。它包含了跨越多个领域的复杂、多步骤任务如“在航班预订网站上为我找到下周一从纽约到洛杉矶最便宜的机票”。在这个基准上获得高分意味着Handoff在理解网页、规划复杂操作序列方面表现非常出色。2. 环境准备搭建一个简单的AI Agent实验环境我们无法直接复现Handoff但可以通过开源工具搭建一个简化版的“上网AI”来理解其核心技术。这里我们使用基于LangChain和Playwright的方案这是一个在开发者中非常流行的组合。2.1 基础环境与工具选择操作系统Windows 10/11, macOS, 或 Linux (Ubuntu 20.04)编程语言Python 3.9核心库langchain用于构建基于LLM的应用程序框架提供Agent、Tools、Chains等高级抽象。langchain-openai/langchain-anthropic用于接入OpenAI GPT或Claude等大模型。playwright一个强大的浏览器自动化库比Selenium更现代执行速度更快。BeautifulSoup4/lxml用于解析HTML备用方案。IDEVS Code 或 PyCharm。大模型API你需要一个诸如OpenAI、Anthropic或国内合规大模型的API密钥。本文示例将使用OpenAI GPT-4o的API格式。2.2 创建项目并安装依赖首先创建一个新的项目目录并设置虚拟环境。# 创建项目目录 mkdir simple-web-agent cd simple-web-agent # 创建并激活虚拟环境 (以Linux/macOS为例) python -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate # 安装核心依赖 pip install langchain langchain-openai playwright beautifulsoup4 # 安装Playwright的浏览器驱动 playwright install chromium2.3 项目结构规划一个清晰的项目结构有助于管理代码。simple-web-agent/ ├── requirements.txt ├── .env # 用于存储API密钥等环境变量 ├── agent_core.py # Agent核心逻辑 ├── web_tools.py # 自定义的网页操作工具集 └── main.py # 主程序入口将依赖项写入requirements.txtlangchain0.1.0 langchain-openai0.0.5 playwright1.40.0 beautifulsoup44.12.2 python-dotenv1.0.0在.env文件中配置你的API密钥OPENAI_API_KEYyour_openai_api_key_here3. 核心组件拆解构建Agent的工具与大脑一个能“上网办事”的Agent其核心是“工具”和“规划器”。下面我们一步步构建它们。3.1 创建网页操作工具Tools工具是Agent的手臂。我们使用Playwright来封装几个基础的网页操作。文件web_tools.pyimport asyncio from langchain.tools import tool from playwright.async_api import async_playwright from typing import Optional class WebNavigator: def __init__(self): self.browser None self.context None self.page None self.playwright None async def start(self): 启动浏览器实例 self.playwright await async_playwright().start() self.browser await self.playwright.chromium.launch(headlessFalse) # 非无头模式便于观察 self.context await self.browser.new_context() self.page await self.context.new_page() async def stop(self): 关闭浏览器实例 if self.browser: await self.browser.close() if self.playwright: await self.playwright.stop() # 创建全局导航器实例 navigator WebNavigator() tool async def navigate_to_website(url: str) - str: 导航到指定的网址。 Args: url: 要访问的完整网址例如 https://www.baidu.com Returns: 操作结果描述例如“已成功导航至 https://www.baidu.com” try: await navigator.page.goto(url, wait_untilnetworkidle) title await navigator.page.title() return f成功导航至 {url}。页面标题是{title}。 except Exception as e: return f导航到 {url} 时出错{str(e)} tool async def extract_page_info(selector: Optional[str] None) - str: 提取当前页面的关键信息。可以提取整个页面的文本或特定CSS选择器下的内容。 Args: selector: 可选的CSS选择器用于定位特定元素。如果为None则提取整个body的文本。 Returns: 提取到的文本内容摘要。 try: if selector: element await navigator.page.wait_for_selector(selector, stateattached, timeout5000) content await element.inner_text() else: # 获取页面主要可见文本一个简单的实现是获取body内容 content await navigator.page.inner_text(body) # 截取前2000个字符作为摘要避免上下文过长 summary content[:2000] (... if len(content) 2000 else ) return f页面信息摘要{summary} except Exception as e: return f提取页面信息时出错{str(e)} tool async def perform_search(keyword: str, search_box_selector: str input[nameq], input[typesearch]) - str: 在页面的搜索框中输入关键词并执行搜索。 此工具会尝试自动查找页面上的搜索框。 Args: keyword: 要搜索的关键词。 search_box_selector: 搜索框的CSS选择器。默认尝试匹配常见搜索框。 Returns: 搜索操作的结果描述。 try: # 尝试定位搜索框 search_box await navigator.page.wait_for_selector(search_box_selector, stateattached, timeout5000) await search_box.fill() # 清空原有内容 await search_box.fill(keyword) await search_box.press(Enter) await navigator.page.wait_for_load_state(networkidle) return f已成功搜索关键词 {keyword}页面已刷新。 except Exception as e: return f执行搜索时出错{str(e)}。可能未找到搜索框请检查页面或提供明确的选择器。 # 工具列表供Agent使用 WEB_TOOLS [navigate_to_website, extract_page_info, perform_search]3.2 构建Agent核心大脑我们将使用LangChain的ReAct框架来创建Agent它结合了推理Reasoning和行动Acting。文件agent_core.pyimport os from langchain.agents import AgentExecutor, create_react_agent from langchain_openai import ChatOpenAI from langchain.prompts import PromptTemplate from web_tools import WEB_TOOLS, navigator from dotenv import load_dotenv # 加载环境变量 load_dotenv() def create_web_agent(): 创建并返回一个配置好的网页操作Agent执行器。 # 1. 初始化大语言模型 llm ChatOpenAI( modelgpt-4o, # 或使用 gpt-3.5-turbo但复杂任务规划能力较弱 temperature0, # 设置为0以获得更确定性的输出 api_keyos.getenv(OPENAI_API_KEY) ) # 2. 定义ReAct风格的提示词模板 # 这个模板指导模型如何思考Reason和选择工具Act prompt PromptTemplate.from_template( 你是一个专业的网页操作助手。你的目标是通过使用工具帮助用户完成在网页上的任务。 你可以使用的工具如下 {tools} 请严格按照以下格式回应 思考你需要先思考当前情况分析用户的目标并决定下一步该做什么。 行动你需要调用的工具名称必须是上面列出的工具之一 行动输入调用该工具所需的输入必须是一个合法的JSON字符串例如 {{url: https://example.com}} 当你认为任务已经完成或者无法继续时请使用以下格式回应 最终答案你的回答总结任务结果。 开始 之前的交互记录如果有 {history} 当前用户指令{input} 你的回应 ) # 3. 创建ReAct Agent agent create_react_agent( llmllm, toolsWEB_TOOLS, promptprompt ) # 4. 创建Agent执行器控制交互流程 agent_executor AgentExecutor( agentagent, toolsWEB_TOOLS, verboseTrue, # 设置为True可以看到Agent的思考过程便于调试 handle_parsing_errorsTrue, # 处理解析错误 max_iterations10, # 防止Agent陷入死循环 early_stopping_methodgenerate # 当Agent输出“最终答案”时停止 ) return agent_executor, navigator # 导出一个便捷的全局Agent实例 agent_executor, navigator create_web_agent()4. 完整实战案例让Agent自动搜索并获取信息现在我们将上述组件组合起来完成一个具体的任务“打开百度搜索‘今日天气’并返回第一页的简要信息。”文件main.pyimport asyncio from agent_core import agent_executor, navigator async def main(): 主函数启动浏览器创建Agent执行任务。 print(正在启动Web Agent...) # 1. 启动浏览器 await navigator.start() print(浏览器已启动。) # 2. 定义用户任务 user_task 请打开百度首页https://www.baidu.com在搜索框里输入‘今日天气’然后执行搜索。最后把搜索结果第一页的主要信息摘要告诉我。 print(f\n执行任务{user_task}) print(- * 50) try: # 3. 运行Agent执行任务 # LangChain的Agent执行器默认是同步的我们需要在异步环境中运行它。 # 这里使用asyncio.to_thread在单独的线程中运行同步代码。 result await asyncio.to_thread( agent_executor.invoke, {input: user_task, history: } ) print(\n *50) print(任务执行完成) print(f最终输出{result[output]}) except Exception as e: print(f\n任务执行过程中出现错误{e}) finally: # 4. 任务完成或出错后关闭浏览器 input(\n按回车键关闭浏览器并退出...) await navigator.stop() print(浏览器已关闭。) if __name__ __main__: asyncio.run(main())4.1 运行与结果分析在终端运行python main.py。程序会自动打开一个Chromium浏览器窗口。在控制台你会看到类似以下的verbose日志因为我们在AgentExecutor中设置了verboseTrue正在启动Web Agent... 浏览器已启动。 执行任务请打开百度首页https://www.baidu.com在搜索框里输入‘今日天气’然后执行搜索。最后把搜索结果第一页的主要信息摘要告诉我。 -------------------------------------------------- 进入新的AgentExecutor链... 思考用户想要我打开百度搜索“今日天气”并返回搜索结果摘要。我需要按顺序使用工具。首先导航到百度。 行动navigate_to_website 行动输入{url: https://www.baidu.com} 观察成功导航至 https://www.baidu.com。页面标题是百度一下你就知道。 思考我已经在百度首页。现在需要在搜索框中输入“今日天气”并搜索。我应该使用perform_search工具。 行动perform_search 行动输入{keyword: 今日天气} 观察已成功搜索关键词 今日天气页面已刷新。 思考搜索已完成。现在需要提取搜索结果页面的信息。我应该使用extract_page_info工具来获取摘要。 行动extract_page_info 行动输入{} 观察页面信息摘要百度为您找到相关结果约100,000,000个...此处为实际抓取的搜索结果文本摘要... 思考我已经完成了所有步骤导航、搜索、提取信息。现在可以给出最终答案了。 最终答案已成功完成您的指令。首先打开了百度首页随后在搜索框中输入“今日天气”并执行了搜索。当前搜索结果页面显示约有1亿条相关结果。页面摘要信息主要包括各大天气网站如中国天气网、2345天气王等提供的今日天气查询链接、部分地区如北京、上海的实时天气概况温度、天气状况、风力等以及相关的新闻资讯。请注意具体天气信息需点击相应链接查看详情。 AgentExecutor链结束。 任务执行完成 最终输出已成功完成您的指令。首先打开了百度首页随后在搜索框中输入“今日天气”并执行了搜索。当前搜索结果页面显示约有1亿条相关结果。页面摘要信息主要包括各大天气网站如中国天气网、2345天气王等提供的今日天气查询链接、部分地区如北京、上海的实时天气概况温度、天气状况、风力等以及相关的新闻资讯。请注意具体天气信息需点击相应链接查看详情。4.2 案例代码解读与局限性这个简单的案例演示了一个AI Agent的基本工作流程任务解析AgentLLM理解用户指令将其分解为“导航 - 搜索 - 提取信息”三个子任务。工具调用依次调用我们定义的三个工具函数。状态迭代根据每个工具返回的“观察Observation”决定下一步行动直到任务完成。然而这个示例距离“Handoff”级别的能力还有巨大差距主要体现在网页理解粗糙我们仅提取了页面文本而复杂的交互如下拉菜单选择、表格填写需要更精细的DOM元素定位和理解。工具集有限只有三个基础工具。真实场景需要点击、滚动、下拉选择、文件上传等数十种工具。规划能力简单依赖于基础LLM的规划能力对于异常情况如页面元素未加载、弹窗出现缺乏鲁棒的处理逻辑。无记忆与反思每次任务独立无法从历史错误中学习。5. 进阶挑战与常见问题排查当你尝试扩展这个基础Agent时可能会遇到以下典型问题。5.1 常见问题与解决方案问题现象可能原因排查与解决思路Agent陷入循环不断重复相同操作1. LLM未能正确理解任务完成状态。2. 工具返回的观察结果未能提供足够信息让LLM判断终止。1.优化提示词在系统提示中更明确地定义任务完成的标志。2.改进工具输出让工具返回更结构化、信息更丰富的观察结果例如包含“任务已完成”的标识。3.设置迭代限制如代码中的max_iterations10强制停止。工具调用失败如元素找不到1. 页面加载未完成。2. CSS选择器不准确或页面结构动态变化。3. iframe或Shadow DOM内的元素。1.增加等待在工具中使用page.wait_for_selector并设置合理的超时和状态state“attached”或“visible”。2.使用更鲁棒的选择器优先使用id、name或具有唯一性的>LLM无法正确解析工具参数工具函数的参数描述不够清晰或LLM生成的JSON格式有误。1.完善工具描述在tool装饰器的docstring中清晰定义每个参数的类型和示例。2.使用Pydantic工具LangChain支持使用Pydantic模型来严格定义工具输入能显著提高解析成功率。处理复杂、多页面的任务当前Agent是单次会话缺乏跨步骤的持久化记忆。1.引入对话记忆使用ConversationBufferMemory等组件让Agent记住之前的交互。2.任务分解与状态机设计一个上层控制器先将复杂任务分解为子任务再让Agent逐个执行并管理整体状态。运行速度慢1. LLM API调用延迟。2. 网页操作等待时间过长。1.模型选择在非关键推理步骤使用更快的模型如GPT-3.5-Turbo。2.并行化对于可并行的子任务考虑异步并发执行。3.优化等待策略根据页面特点调整wait_for_load_state的策略如“domcontentloaded”比“networkidle”更快。5.2 安全与伦理考量在开发此类自动化Agent时必须高度重视遵守Robots协议检查目标网站的robots.txt尊重其爬虫规则。控制访问频率避免对目标网站造成DoS攻击式的请求压力。用户隐私与数据安全Agent操作可能涉及用户凭证或敏感信息必须确保本地安全存储绝不泄露。明确使用边界Agent不应用于欺诈、爬取受版权保护内容、绕过安全机制等非法或不道德用途。6. 工程最佳实践与优化方向要构建一个更接近“Handoff”的、可用于实际场景的Web Agent需要在基础框架上进行深度工程化。6.1 增强网页感知能力结构化页面表示不要只传递原始HTML或文本给LLM。可以提取关键元素的可访问性树Accessibility Tree它比DOM更简洁更能反映用户可见的界面结构。屏幕截图与多模态理解结合视觉模型如GPT-4V分析屏幕截图让Agent能“看到”按钮、图标和布局这对于处理复杂UI和验证码需在合法合规前提下至关重要。微调元素定位描述训练一个小模型或使用Few-shot学习将LLM的指令如“点击登录按钮”精准映射到页面的具体CSS选择器或坐标。6.2 设计鲁棒的任务规划与执行引擎分层规划Hierarchical Planning不是所有任务都适合让LLM直接一步步思考。可以设计一个高层规划器Planner将“预订机票”分解为“搜索航班-选择航班-填写乘客信息-支付”等子目标再由底层LLM Agent去执行每个子目标。验证与回滚机制每个操作执行后进行结果验证。例如点击“提交”后检查是否出现成功提示或错误信息。如果失败触发预设的回滚或重试策略。异常处理流程为网络超时、元素消失、意外弹窗等常见异常设计专用的处理工具和恢复流程。6.3 记忆、学习与效率优化向量记忆库将成功执行的任务步骤、遇到的页面结构、有效的元素选择器存入向量数据库。当遇到相似任务或页面时Agent可以先进行检索复用历史经验减少试错。技能库Skill Library将通用的操作序列如“登录Gmail”、“在亚马逊搜索商品”封装成可复用的“技能”。新任务可以组合这些技能而非从头规划。缓存与提速对LLM的响应、不变的页面结构进行缓存。对于批量任务可以预先加载和解析页面。6.4 可观测性与调试详细日志记录记录Agent的每一步思考、行动、观察并保存当时的屏幕截图和HTML快照。这是排查复杂任务失败原因的唯一途径。可视化回放开发一个工具能够像视频一样回放Agent的完整操作过程便于人工审查和算法优化。定义评估指标针对你的业务场景定义成功率、完成步骤数、耗时等关键指标用于持续评估和优化Agent性能。7. 总结与学习路线通过本文的实践我们从零构建了一个简易的Web AI Agent并深入探讨了其背后的技术原理、面临的挑战以及进阶的工程化方向。虽然与Hark Handoff这样的尖端系统相比仍有云泥之别但我们已掌握了其核心骨架。回顾核心要点AI Agent LLM大脑 Tools手脚 Planning规划。Handoff的高分源于在这三个方面的极致优化。环境感知是瓶颈如何让机器准确“理解”不断变化的图形化网页界面是Web Agent领域的关键挑战。工程化决定上限可靠的Agent系统离不开鲁棒的错误处理、状态管理、记忆模块和效率优化。对于希望深入该领域的开发者建议的学习路线如下巩固基础熟练掌握Python异步编程、Playwright/Selenium等自动化工具、以及LangChain/LlamaIndex等AI应用框架。深入原理阅读ReAct、Toolformer、WebGPT等相关论文理解规划、工具使用等核心思想的演进。参与开源关注并尝试使用一些优秀的开源Web Agent项目如agentkit、browser-use、OpenAI的WebGPT等阅读其源码。专注场景从解决一个具体的、小规模的自动化任务开始如自动生成周报、监控商品价格逐步迭代复杂度和鲁棒性。关注评估了解Mind2Web、WebArena等评测基准知道业界如何科学地衡量Agent的能力。AI Agent的实用化浪潮已经到来。作为开发者理解其原理并动手构建是跟上这波趋势的最佳方式。本文的代码示例可以作为一个起点你可以在此基础上针对更具体的业务需求不断扩展工具集、优化规划逻辑、增强系统稳定性最终打造出真正能为你“上网办事”的智能助手。