browser-use:AI 驱动的浏览器自动化神器——MessageManager

browser-use:AI 驱动的浏览器自动化神器——MessageManager

技术教程gslnedu2025-06-21 20:06:481A+A-

browser-use 中 LLM 本身是无状态的,它无法记住之前的对话,为了让 LLM 能够理解上下文并能做出连贯的决策, agent 就需要将相关的对话历史和当前的状态信息一起发送给它。 MessageManager 就是负责管理这个 “记忆” 与 “沟通” 过程的关键组件。


一、MessageManager 作用

上下文管理: 追踪对话历史,包括系统指令、用户任务、智能体的思考、执行的动作、动作结果以及浏览器状态。

状态格式化: 将复杂的浏览器状态(DOM 树、截图)转换为 LLM 能够理解的文本和图像格式。

Token 限制: LLM 的输入有长度限制(Token Limit)。当对话历史变得过长时,需要有策略地进行删减,以确保最重要的信息得以保留。

敏感数据处理: 在将信息发送给 LLM 之前,自动过滤或替换掉配置中的敏感信息(如密码、API 密钥)。


二、_init_messages

MessageManager 在通过 _init_messages 初始化时,会构建一个基顾贩对话开端,通常包含以下内容:

系统消息 (SystemMessage): 来自 system_prompt.md,定义了智能体的角色、能力、规则和输出格式。

上下文消息 (HumanMessage): (可选) 任务的额外背景信息。

任务消息 (HumanMessage): 清晰地陈述最终目标。

敏感数据提示 (HumanMessage): (可选) 告知 LLM 存在敏感数据占位符以及如何使用它们(例如 <secret>password</secret>)。

示例输出 (HumanMessage, AIMessage, ToolMessage): 给 LLM 一个清晰的、符合格式要求的输出示例,帮助它理解期望的 JSON 结构和动作调用方式。

历史占位符 (HumanMessage): 标记任务历史记忆的开始位置。

可用文件路径 (HumanMessage): (可选) 告知 LLM 可以访问哪些本地文件。


三、add_state_message

当 agent 获取到新的浏览器状态(BrowserState)时,add_state_message 方法会将浏览器状态转化成一条 HumanMessage 。

具体代码实现如下:

# add_state_message 简化逻辑
def add_state_message(self, state: BrowserState, result: Optional[List[ActionResult]] = None, ...) -> None:
    # 处理上一步的结果/错误,如果需要直接加入记忆
    if result:
        for r in result:
            if r.include_in_memory:
                # 将需要记忆的结果/错误直接添加为单独的 HumanMessage
                if r.extracted_content:
                    self._add_message_with_tokens(HumanMessage(content='Action result: ' + str(r.extracted_content)))
                if r.error:
                    self._add_message_with_tokens(HumanMessage(content='Action error: ' + r.error.split('\n')[-1]))
                result = None # 标记已处理,避免重复添加

    # 使用 AgentMessagePrompt 格式化当前状态
    state_message_prompt = AgentMessagePrompt(state, result, ...)
    # 获取包含文本描述和可选截图的 HumanMessage
    state_message = state_message_prompt.get_user_message(use_vision)

    # 将格式化后的状态消息添加到历史记录
    self._add_message_with_tokens(state_message)

AgentMessagePrompt (在 prompts.py 中定义) 负责具体的格式化工作。它会提取下面的内容:

  • 当前 URL
  • 打开的标签页列表
  • 视口内可交互元素的文本表示(例如 [1]<button>Login</button>, [2]<input type="text">Username</input>),并根据配置包含指定的 HTML 属性 (include_attributes)。
  • 页面滚动信息(例如 ... 500 pixels above ..., ... 1200 pixels below ...)。
  • 当前步骤信息和时间。
  • 截图的 Base64 编码(如果 use_vision=True 且存在截图),嵌入到消息中。

四、Token 管理

LLM 的上下文窗口(能处理的最大 Token 数)是有限的。随着对话进行,消息历史会越来越长,最终可能超出限制。MessageManager 通过以下方式处理这个问题:

Token 计算 (_count_tokens, _add_message_with_tokens): 在添加每条消息时,估算其 Token 数量(文本按字符数估算,图片按固定值 image_tokens 计算),并累加到 MessageHistory 的 current_tokens 中。

历史裁剪 (cut_messages): 当 current_tokens 超过 max_input_tokens 时,触发裁剪逻辑:

优先移除图片: 如果最后一条消息包含图片,先将其移除,因为图片通常占用大量 Token(例如 800 个)。

截断最后一条消息: 如果移除图片后仍然超限,则按比例截断最后一条(通常是状态消息)的文本内容,直到 Token 总数低于限制。


五、_filter_sensitive_data

在将任何消息添加到历史记录之前,_add_message_with_tokens 会调用 _filter_sensitive_data。这个方法会遍历消息内容,查找 settings.sensitive_data 字典中定义的值(例如,用户密码明文),并将其替换为占位符(例如 <secret>user_password</secret>)。这样可以防止敏感信息被发送给 LLM 或记录在日志/历史文件中。


六、message_manager/views.py

ManagedMessage: 将 Langchain 的 BaseMessage(如 HumanMessage, AIMessage)与 MessageMetadata(目前只有 tokens)封装在一起。它还实现了自定义的 Pydantic 序列化/反序列化逻辑,利用 Langchain 的 dumpd 和 load 来正确处理各种消息类型。

MessageHistory: 存储 ManagedMessage 列表,并维护 current_tokens 总数。提供了添加、获取、移除消息的方法。

MessageManagerState: 保存 MessageManager 的整体状态,主要是 MessageHistory 和下一个 ToolMessage 需要使用的 tool_id。

点击这里复制本文地址 以上内容由朽木教程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

朽木教程网 © All Rights Reserved.  蜀ICP备2024111239号-8