上下文管理完全指南:GhostCoder消息历史与压缩策略如何防止Prompt爆炸
【免费下载链接】ghostcoderSolving the problems of merging incomplete code written by an LLM and splitting up code for embedding and indexing in a vector store.项目地址: https://gitcode.com/gh_mirrors/gh/ghostcoder
GhostCoder(Moatless)是一个面向自动编码的开源 LLM Agent 框架,其上下文管理核心位于消息历史模块,通过消息历史生成器与多级压缩策略,帮助长任务 Agent 防止 Prompt 爆炸。本文带你快速看懂它的 5 种历史生成器、Token 限额裁剪机制与增量上下文注入技巧,新手也能照着配置自己的 Agent 记忆策略。
为什么 LLM Agent 会遭遇"Prompt 爆炸"?
想象一个自主编程 Agent 连续工作 30 步:每一步都调用工具(读代码、跑测试、改文件),工具返回的观察结果(Observation)动辄数千 Token。如果把这些全部原样塞回给大模型,会出现两个致命问题:
- 超出上下文窗口:模型直接报错,任务中断
- 注意力稀释:模型"忘记"最初的任务描述,开始跑偏
GhostCoder 的解决方案是把"历史怎么喂给模型"抽象成一个可插拔组件——Memory(记忆生成器),所有策略都实现同一个接口 generate_messages,由 Agent 在每轮推理前自动调用。
消息历史模块全景:5 种生成器一览
整个上下文管理逻辑集中在 message_history 目录,按策略从"全量"到"重度压缩"排布:
| 生成器 | 文件 | 适用场景 | 压缩力度 |
|---|---|---|---|
| MessageHistoryGenerator | message_history.py | 通用工具调用 Agent | ⭐⭐ |
| CompactMessageHistoryGenerator | compact.py | 长任务、省 Token | ⭐⭐⭐⭐ |
| ReactMessageHistoryGenerator | react.py | ReAct 纯文本格式 | ⭐⭐ |
| ReactCompactMessageHistoryGenerator | react_compact.py | ReAct + 压缩 | ⭐⭐⭐⭐ |
| SummaryMessageHistoryGenerator | summary.py | 单条消息打包历史 | ⭐⭐⭐ |
所有生成器都继承自 base.py 中的BaseMemory抽象类,Agent 侧的接入点很简单:agent.py 中有一个memory字段,默认就是MessageHistoryGenerator,每轮推理前执行messages = await self.memory.generate_messages(node, workspace),你可以随时替换成别的策略。
核心策略一:Token 限额 + "最新优先"裁剪
这是 message_history.py 中最关键的防线。设置max_tokens后,生成器会这样筛选历史:
- 永远保留第一条消息(用户原始任务描述),确保模型不"失忆"
- 从最新消息往回倒序填充:最新的对话优先级最高,逐步吃掉剩余 Token 预算
- 塞不下就跳过该条消息,最后再按原始顺序排回
💡 设计精髓:模型对"最近发生了什么"最敏感,对"很久以前的细节"容忍度高。倒序填充恰好符合这个特性。
还有一个细节参数max_tokens_per_observation:对非最新节点的观察结果,如果超过单条限额,就自动换成简短的summary(摘要),只有最近一步保留完整输出——既省 Token,又不损失当下判断所需的信息。
核心策略二:Compact 压缩——只保留"模型真正需要的"
compact.py 是压缩策略集大成者,内置了 4 个去重/增量技巧:
① 观察摘要替代全文非最近步骤的工具输出,优先取observation.summary(一行摘要)而不是完整 message,Token 消耗直降一个数量级。
② 已看过的文件不重复贴用shown_files集合跟踪哪些文件已展示过。同一个文件被 ViewCode 读三次,历史里只保留第一次的完整代码,其余步骤不再重复注入。
③ Git Diff 只在首次编辑时出现shown_diff标志保证整个历史中只插入一份"当前工作区改动",避免每次修改代码都重复贴一份 patch。
④ 测试结果只在状态变化时更新last_test_status跟踪上次测试状态:只有测试从"失败"变"通过"(或反之)时才把结果写进历史。首次运行展示完整失败详情,后续只带一行摘要。
核心策略三:File Context 与 Git Patch 的按需注入
SummaryMessageHistoryGenerator 演示了另一种思路:把整段历史打包进一条user 消息。它的组装顺序是:
- 任务描述 +
<history>标签包裹的分步历史(非最后一步用摘要) - 已查看代码清单(
include_file_context开关控制) - 当前 git diff(
include_git_patch开关控制)
代码上下文的 Token 预算由 file_context.py 统一管理:context_size()实时统计当前已占用 Token,available_context_size()给出剩余空间,模型"能看多少代码"始终有数。Token 计数统一走 tokenizer.py 的count_tokens,保证各模块口径一致。
如何选型:3 种场景对应 3 种记忆策略
| 你的场景 | 推荐生成器 | 理由 |
|---|---|---|
| 短任务(<10 步)、窗口充足 | MessageHistoryGenerator | 信息全保真,模型决策质量最高 |
| 长任务、多轮测试、大上下文窗口紧张 | Compact 系列 | 4 个去重技巧大幅压降 Token |
| 使用纯文本 ReAct 协议的模型 | React 系列 | Thought/Action/Observation 文本格式 |
想自己动手验证效果?tests/memory/ 下有两个可直接运行的用例:test_message_history_generator.py和test_react_compact_message_history.py。
快速检查清单:防 Prompt 爆炸的 5 个配置点
- ✅设置
max_tokens:给历史生成器一个全局预算(如模型窗口的 70%) - ✅设置
max_tokens_per_observation:给单条观察结果设上限,超限自动换摘要 - ✅长任务切换到 Compact 生成器:启用文件去重与 diff 增量
- ✅按需关闭
include_file_context/include_git_patch:纯搜索类任务可省一大块 - ✅优先使用观察结果的
summary字段:每个 Action 的 Observation 都该提供一行摘要
小结
GhostCoder 的上下文管理哲学可以浓缩为一句话:模型不需要"全部历史",只需要"足够决策的最小历史"。通过消息历史生成器这一可插拔组件,配合 Token 限额裁剪、观察摘要、文件去重、diff 增量与测试状态跟踪五道闸门,即使 Agent 连跑几十步,Prompt 也能稳定控制在模型窗口之内。理解这套机制后,你也能在自己的 Agent 项目中复刻同样的防爆炸能力。
【免费下载链接】ghostcoderSolving the problems of merging incomplete code written by an LLM and splitting up code for embedding and indexing in a vector store.项目地址: https://gitcode.com/gh_mirrors/gh/ghostcoder
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考