Web Voyager是一个基于多模态大模型(Multi-modal Agent)的AI Agent,旨在通过浏览器API与网页交互,完成用户提出的任务。其核心功能是根据用户的“问题、图像或请求”(Question, Image, or Request),生成网页操作的“工具响应”(Tool Responses),并最终返回“最终答案”(Final Answer)。
它的工作原理是查看每次轮次带注释的浏览器屏幕截图,然后选择下一步操作。该代理架构是一个基本的推理和行动 (ReAct) 循环。该代理的独特之处在于:
它使用类似标记集的图像注释作为代理的 UI 功能。
它通过使用工具控制鼠标和键盘,在浏览器中实现应用。
整体设计如下所示:
从示意图来看,其流程包括:
- 输入:用户提供问题、图像或请求。
- 处理:
- 多模态Agent(Multi-modal Agent)接收输入,分析网页内容(Webpage Object)。
- Agent通过工具模式(Tool Modes)生成下一步操作(Type、Scroll、Click、Wait、Jump to Search、GoBack)。
- 借助浏览器API执行操作,获取新的网页状态。
- 输出:最终答案。

定义状态(State)
LangGraph的工作流需要定义一个状态对象,用于在节点之间传递信息。Web Voyager的状态可能包括:
- 当前网页的截图(base64编码)。
- 用户的请求。
- 当前的操作历史(Trajectory)。
- 工具调用的结果。
from typing import TypedDict, List
class WebVoyagerState(TypedDict):
user_request: str # 用户的请求
webpage_screenshot: str # 当前网页截图(base64编码)
trajectory: List[str] # 操作历史
tool_response: str # 工具调用的响应
final_answer: str # 最终答案
(3) 定义工具(Tools)
Web Voyager的核心是工具模式(Tool Modes),包括 Type、Scroll、Click 等操作。这些操作通过浏览器API(如Playwright)实现。
@tool
async def click_element(element_id: str) -> str:
"""点击网页中的某个元素"""
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
# 假设已经在某个页面上
await page.click(f"#{element_id}")
screenshot = await page.screenshot()
await browser.close()
return base64.b64encode(screenshot).decode("utf-8")
@tool
async def type_text(text: str, element_id: str) -> str:
"""在网页的某个元素中输入文本"""
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
await page.fill(f"#{element_id}", text)
screenshot = await page.screenshot()
await browser.close()
return base64.b64encode(screenshot).decode("utf-8")
@tool
async def scroll_page(direction: str) -> str:
"""滚动网页"""
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page()
if direction == "down":
await page.evaluate("window.scrollBy(0, window.innerHeight)")
screenshot = await page.screenshot()
await browser.close()
return base64.b64encode(screenshot).decode("utf-8")
# 其他工具:wait、jump_to_search、go_back 等
(4) 定义多模态Agent
多模态Agent基于用户请求和网页截图,决定下一步操作。它通常使用一个提示模板(PromptTemplate)来引导模型推理。
定义提示模板
prompt = PromptTemplate(
input_variables=["user_request", "webpage_screenshot", "trajectory"],
template="""
你是一个网页导航Agent。用户请求:{user_request}
当前网页截图(base64编码):{webpage_screenshot}
操作历史:{trajectory}
基于当前网页状态,决定下一步操作。可能的工具包括:
- click_element(element_id): 点击某个元素
- type_text(text, element_id): 输入文本
- scroll_page(direction): 滚动页面
- wait(): 等待
- jump_to_search(): 跳转到搜索
- go_back(): 返回上一页
返回下一步操作的工具调用,例如:{{"tool": "click_element", "args": {{"element_id": "button1"}}}}
如果任务已完成,返回最终答案,例如:{{"final_answer": "任务完成"}}
"""
)
# 初始化多模态模型
llm = ChatOpenAI(model="gpt-4o", temperature=0) # 使用支持多模态的模型
agent = llm.bind_tools([click_element, type_text, scroll_page])
(5) 定义LangGraph工作流
LangGraph的工作流由节点和边组成。Web Voyager可能包含以下节点:
- agent_node:调用多模态Agent,生成下一步操作。
- tool_node:执行工具操作,更新网页状态。
- end_node:输出最终答案。
定义图
workflow = StateGraph(WebVoyagerState)
# 节点:Agent决策
def agent_node(state: WebVoyagerState) -> WebVoyagerState:
response = agent.invoke({
"user_request": state["user_request"],
"webpage_screenshot": state["webpage_screenshot"],
"trajectory": state["trajectory"]
})
if "final_answer" in response:
state["final_answer"] = response["final_answer"]
return state
state["tool_response"] = response
return state
# 节点:工具执行
async def tool_node(state: WebVoyagerState) -> WebVoyagerState:
tool_call = state["tool_response"]
tool_name = tool_call["tool"]
args = tool_call["args"]
if tool_name == "click_element":
screenshot = await click_element(args["element_id"])
elif tool_name == "type_text":
screenshot = await type_text(args["text"], args["element_id"])
elif tool_name == "scroll_page":
screenshot = await scroll_page(args["direction"])
# 其他工具调用...
state["webpage_screenshot"] = screenshot
state["trajectory"].append(f"执行工具:{tool_name},参数:{args}")
return state
# 添加节点
workflow.add_node("agent", agent_node)
workflow.add_node("tool", tool_node)
# 添加边
workflow.set_entry_point("agent")
workflow.add_conditional_edges(
"agent",
lambda state: "end" if state.get("final_answer") else "tool",
{"end": END, "tool": "tool"}
)
workflow.add_edge("tool", "agent")
# 编译图
app = workflow.compile()
Paragoger衍生者AI训练营。发布者:稻草人,转载请注明出处:https://www.shxcj.com/archives/9673