在本文中,您将学习在长期运行的 AI 代理应用程序中管理上下文窗口的五种实用策略,以及每种方法引入的关键权衡。
我们将讨论的主题包括:
- 为什么上下文窗口成为专为持续自主操作而设计的基于代理的人工智能系统的关键瓶颈。
- 五种不同的上下文管理策略:滑动窗口、递归摘要、结构化状态管理、通过 RAG 的临时上下文以及动态上下文路由。
- 每种策略固有的权衡,从内存丢失和信息压缩到检索盲点和维护复杂性。
介绍
长期代理 是那些能够随着时间的推移表现出持续自主执行的人。在这些基于代理的应用程序中——在与用户或其他系统的交互的推动下,信息迅速滚雪球—— 上下文窗口 是一个关键瓶颈。可以说,代理和大型语言模型(简称 LLM)是现代人工智能系统中同一枚硬币的两个侧面。因此,从“LLM 作为即时响应引擎”转变为“(代理赋予的)LLM 作为长期运行的后台进程”,将上下文窗口变成了主要的 AI 工程瓶颈。
出于所有这些原因,从长远来看,管理上下文窗口需要特定的策略,例如滑动窗口、分层内存和动态摘要。本文为此提出了五种不同的运营策略,以及它们不可避免的权衡。
1. 滑动窗
想象一下一个只能记住最后十分钟工作的人工智能代理。滑动窗口方法只是管理内存限制:它们删除最旧的消息,为最新的消息腾出空间,只有核心指令被“锁定”在上下文的顶部。
以下是滑动窗口实现的示例(该代码本身并不可执行;仅出于说明目的而显示):
def manage_sliding_window(system_prompt, message_history, max_turns=10): “””Keep the permanent system instructions, and drop the oldest chat turns when history gets too long. “”” if len(message_history) > max_turns: # Trim history to keep only the ‘X’ most recent messages message_history = message_history[-max_turns:]# 始终在系统提示符前面添加,以便代理记住其身份返回 [system_prompt] + 消息历史记录
|
定义 管理滑动窗口(系统提示符, 消息历史记录, 最大转数=10): ””“Keep the permanent system instructions, and drop the oldest chat turns 当历史变得太长的时候。 ””” 如果 伦(消息历史记录) > 最大转数: # 修剪历史记录以仅保留“X”条最新消息 消息历史记录 = 消息历史记录[–max_turns:] # 始终在前面添加系统提示符,以便代理记住其身份 返回 [system_prompt] + 消息历史记录 |
虽然由于不需要额外的人工智能处理而非常便宜且快速,但该策略有一个警告:“数字健忘症”。换句话说,如果智能体遇到一个小时前已经解决过的问题,它会完全忘记如何处理它,这可能会使其陷入永无止境的循环中。
2. 递归总结
可以将其视为类似于 JPEG 的图像压缩协议,但应用于上下文窗口领域。递归摘要不是像滑动窗口那样删除遥远的过去,而是定期将旧消息压缩成摘要。这有助于在长时间的操作过程中保持整个特工的“任务和情节”活跃,但当然,就像在模糊的 JPEG 文件中一样,与细节相关的信息会丢失,这会让特工对过去的事件留下长期但模糊的记忆。
3. 结构化状态管理
在此策略中,正在运行的聊天记录完全被保留。为了替换它们,代理保留了一个可管理的 JSON 对象,用于跟踪目标、事实和错误——充当结构化的“便签本”。在每个回合或步骤中,原始对话都会被丢弃,并且仅向 AI 代理传递核心指令、更新的 JSON 对象以及当前的新输入。这无疑是一种非常高效的策略。然而,这在很大程度上取决于开发人员对于到底应该跟踪什么的实施标准。如果意外但关键的变量超出预定义的模式边界,代理将不可避免地忽略它们。
这是该策略实施的简化示例:
def run_scratchpad_turn(system_prompt, scrappad_state, new_input): “””完全擦除对话历史记录。代理仅使用其核心指令、当前状态和新任务进行导航。 “”” # 将刚性状态与新输入组合成单个提示提示 = f”{system_prompt}\nMEMORIZED STATE: {scratchpad_state}\nNEW INPUT: {new_input}” # AI处理提示,返回其下一个操作以及更新后的状态 ai_output = call_llm(prompt, response_format=”json”) return ai_output[“chosen_action”]ai_输出[“updated_scratchpad”]
|
定义 运行_scratchpad_turn(系统提示符, 暂存器状态, 新输入): ””“完全擦除对话历史记录。代理仅进行导航 使用他们的核心指令、当前状态和新任务。 ””” # 将刚性状态与新输入组合成单个提示 迅速的 = f“{system_prompt}\n记忆状态:{scratchpad_state}\n新输入:{new_input}” # AI 处理提示,返回其下一步操作以及更新的状态 ai_输出 = 呼叫_llm(迅速的, 响应格式=“json”) 返回 ai_输出[“chosen_action”], ai_输出[“updated_scratchpad”] |
4. 通过 RAG 的临时上下文
基于 RAG 的策略将累积上下文中的所有内容卸载到外部数据库(矢量数据库) RAG系统,如所解释的 这里)。这是强制代理将其历史记录保留在活动内存中的替代方法,以便静默搜索取回 仅有的 根据相关性,将最相关的过去事件添加到当前提示中。理论上,这可以让代理无限期地运行,而不会出现上下文过载问题。然而,它也有一个缺点:检索盲点,特别是当代理需要重新连接两个明显不相关的过去事件时。依赖检索器及其底层搜索策略可能会导致丢失相关上下文,否则这些上下文将连接重要的“心理片段”。
5. 动态上下文路由
该策略旨在平衡能力和成本。它使两个不同的人工智能模型协同工作。主代理依赖于管理较小上下文窗口的更快、更便宜的模型来运行高频、重复性任务。同时,当发生异常事件时(例如连续三次任务失败),完整的原始历史记录将转发到一个大背景、强大的模型,该模型分析全局并向更便宜的模型提供更清晰的指令集。这是一种相当经济高效的策略,但可靠地准确识别较便宜的模型何时陷入困境所需的代码可能极难维护和微调。
总结
本文概述了在使用长期运行的基于代理的 AI 应用程序时优化上下文窗口管理的五种策略及其不可避免的权衡。但请记住:最终,构建成功的自主代理应用程序并不是追求无限内存的幻想,而是构建更智能的架构和底层逻辑,帮助确定必须记住什么以及代理可以忘记什么。

