跳到主要内容

Browser Use Web UI — 架构与原理

30 秒导读: browser-use 是一个让 AI 用浏览器替你点网页的 Python 库,但它只有代码接口。本项目给它套了一个 Gradio 网页界面:你在浏览器里填任务、选模型、看实时截图,AI 就去另一个浏览器里替你操作。它还额外做了两件大事——接了一打 LLM 厂商 + MCP 工具,以及内置一个深度研究 agent(自动拆解题目、并行开多个浏览器去查、最后综合成 Markdown 报告)。


1. 这是什么(零基础也能懂)

一句话定义: 它是 browser-use 的官方网页操作台——把“写 Python 调 agent”变成“在网页上点几下”。

它本身不发明 agent。 真正“看网页 → 决定点哪 → 执行点击”的大脑在上游库 browser-use==0.1.48 里(见 requirements.txt:1)。本仓库做的是外壳与编排:界面、配置、多模型接入、人工介入、以及一个更高层的研究 agent。

解决什么问题 / 给谁用:

  • 想用 AI 操作浏览器、但不想写代码的人 —— 填个框就能跑。
  • 想换不同 LLM 试效果的人 —— UI 里下拉切 OpenAI / Anthropic / Google / DeepSeek / Ollama 等。
  • 想用自己已登录的 Chrome 的人 —— 指向本机浏览器,省去重新登录、过验证码。
  • 想做“深度调研”的人 —— 给个题目,让它自动开多个浏览器并行查资料、写报告。

它能做什么(功能):

  • 网页 UI 跑 browser-use agent,实时看每一步的截图 + 模型的 JSON 决策
  • 暂停 / 恢复 / 停止 / 清空正在跑的任务。
  • agent 卡住时向人求助(human-in-the-loop),你在聊天框回一句它再继续。
  • 保存 / 加载整套 UI 配置;任务结束产出历史 JSON + 录制 GIF
  • 一个独立的 Deep Research tab:自动调研 + 写报告,且可中断后用 task_id 续跑

用起来什么样: 装好后一行命令起服务(README.md),浏览器开 127.0.0.1:7788

# 真实启动命令,见 webui.py:main
python webui.py --ip 127.0.0.1 --port 7788

入口极简(webui.py:6-15):解析 --ip/--port/--theme,调 create_ui() 拿到 Gradio Blocksdemo.queue().launch(...) 起服务。queue() 是关键——后面所有“实时刷新”都靠 Gradio 的队列 + 流式返回撑着。

一句话直觉/类比: 把它想成汽车的仪表盘和方向盘,而 browser-use 是发动机。本项目不造发动机,它造了一个好用的驾驶舱(还顺手接了好几种油箱 = 不同 LLM)。


2. 顶层全景(它大概怎么转)

整个系统就三层:Gradio UI 层 → 编排/包装层 → 上游 browser-use 引擎。UI 层收集你填的参数,编排层把参数组装成 agent 并驱动它跑,引擎层真正去操作浏览器。

你(浏览器里的网页)
│ 填任务 / 选模型 / 点 Submit

┌─────────────────────────────────────────────┐
│ Gradio UI 层 src/webui/ │
│ interface.create_ui() ── 5 个 tab 拼成界面 │
│ WebuiManager ── 全局状态 + 组件↔id 注册表 │
└───────────────┬─────────────────────────────┘
│ run_agent_task() 读所有组件值

┌─────────────────────────────────────────────┐
│ 编排/包装层 src/agent src/browser ... │
│ ┌────────────────┐ ┌───────────────────┐ │
│ │ BrowserUseAgent│ │ DeepResearchAgent │ │
│ │ (薄子类, 加停止│ │ (LangGraph 状态机,│ │
│ │ 与方法选择) │ │ 内部又调左边那个)│ │
│ └───────┬────────┘ └─────────┬─────────┘ │
│ CustomBrowser / CustomController / llm_provider│
└───────────────┬─────────────────────────────┘
│ super() 调用

┌─────────────────────────────────────────────┐
│ 上游引擎 browser-use==0.1.48 (pip 包) │
│ Agent.step() 看 DOM→问 LLM→产出动作→执行 │
│ Playwright 真正驱动 Chromium │
└─────────────────────────────────────────────┘

部件一句话职责:

部件干什么在哪个文件
create_ui拼 5 个 tab 成一个 Gradio Blockssrc/webui/interface.py:22
WebuiManager全局状态容器 + “组件对象↔字符串 id”双向注册表src/webui/webui_manager.py:22
BrowserUseAgent上游 Agent 的薄子类,重写工具调用方式选择与 runsrc/agent/browser_use/browser_use_agent.py:30
CustomController上游 Controller 子类,注册“求助/传文件/MCP”等自定义动作src/controller/custom_controller.py:39
CustomBrowser上游 Browser 子类,自定义 Chromium 启动参数与防检测src/browser/custom_browser.py:34
get_llm_model一个工厂,按 provider 名返回对应 LangChain 聊天模型src/utils/llm_provider.py:152
DeepResearchAgentLangGraph 状态机:计划→执行→综合,可恢复src/agent/deep_research/deep_research_agent.py:982
setup_mcp_client_and_tools连 MCP 服务器、把外部工具拉进来src/utils/mcp_client.py:17

主线走一遍(高层、不进代码):

  1. 你在 Run Agent tab 填任务、在 Agent/Browser Settings tab 选模型与浏览器,点 Submit。
  2. run_agent_task所有 tab 的组件值一把抓进来(Gradio 把它们打包成一个 {组件: 值} 字典),按前缀(agent_settings. / browser_settings.)取出来。
  3. get_llm_model 造 LLM、CustomBrowser 造浏览器、CustomController 造控制器,再造一个 BrowserUseAgent
  4. agent 在后台 asyncio 任务里跑;每走一步触发回调,把截图 + 模型 JSON塞进聊天记录;UI 用一个 while not task.done() 循环不断 yield 最新状态给前端。
  5. 跑完产出历史 JSON 与 GIF;按设置决定是否关浏览器。

阅读地图(建议顺序):


巧妙之处速览(细节见各章)

  • “组件字典”当函数签名:不给每个回调列一堆形参,而是把全部 UI 组件作为输入、回调内按 id 现取现用——加一个设置项不必改函数签名(01 章)。
  • 薄到极致的子类CustomBrowserContext 整个类体只有一句 super().__init__(src/browser/custom_context.py:22)——保留扩展点但当前零改动,诚实地告诉你“这里以后可能要改”。
  • 研究计划即 Markdown 即断点:深度研究的进度全写进 research_plan.md- [ ] / - [x] 复选框;恢复时反向解析这个 Markdown 找到第一个没打勾的任务接着跑(05 章)。
  • MCP 工具运行时变成 agent 动作:把任意 MCP 工具的 JSON Schema 反推成 Pydantic 模型,注册进动作表,agent 就能像调内置动作一样调它(04 章)。

边界与局限(诚实)

  • 它不是引擎:所有“看网页、决策、执行”的硬核逻辑在上游 browser-use 包里,本仓库代码读不到;本文只讲外壳与编排。
  • 强耦合上游版本:钉死 browser-use==0.1.48(requirements.txt:1),子类直接依赖上游 Agent.stateconfig 等内部字段(02 章),上游一升级就可能裂。
  • 深度研究的“浏览器搜索”默认串行max_parallel_browsers 默认 1,且工具会把超出的 query 直接截断(deep_research_agent.py:216)。
  • 单用户假设WebuiManager 是单实例、用实例属性存“当前任务/聊天记录”,并非为多人并发设计。

横向对比(同 shelf 的 browser-agents)

  • 与上游 browser-use 相比:本项目 = browser-use 的“前端 + 多模型适配 + 一个上层研究 agent”,自身不碰 DOM/视觉定位。
  • computer-use 类(操作整台电脑 GUI)相比:本项目只在浏览器内活动,靠 Playwright 的 DOM 可访问性,定位比纯视觉点像素更稳。
  • 编码类 agent 相比:同样是“LLM 出动作 → 落到真实目标”,但这里的“目标”是网页元素,容错点在“DOM 索引/截图”而非“代码块匹配”。

代码地图(导航索引)

主题文件关键符号
进程入口webui.pymain
UI 装配src/webui/interface.pycreate_ui, theme_map
全局状态/注册表src/webui/webui_manager.pyWebuiManager, add_components, save_config, load_config
主运行循环src/webui/components/browser_use_agent_tab.pyrun_agent_task, handle_submit, handle_stop, handle_pause_resume
agent 子类src/agent/browser_use/browser_use_agent.pyBrowserUseAgent, _set_tool_calling_method, run
控制器/动作src/controller/custom_controller.pyCustomController, _register_custom_actions, act, register_mcp_tools
浏览器子类src/browser/custom_browser.pyCustomBrowser, _setup_builtin_browser, new_context
LLM 工厂src/utils/llm_provider.pyget_llm_model, DeepSeekR1ChatOpenAI, DeepSeekR1ChatOllama
MCP 适配src/utils/mcp_client.pysetup_mcp_client_and_tools, create_tool_param_model, resolve_type
深度研究src/agent/deep_research/deep_research_agent.pyDeepResearchAgent, planning_node, research_execution_node, synthesis_node, should_continue