01
compact_tool_result
按字节阈值截断超长工具输出。最近 3 条保留 50KB,更早的激进截断至 3KB。完整内容存到 tool_result/uuid.txt。
02
context_check
从尾部向前累积 token,切割为 to_compact + to_keep。保证 tool_use/tool_result 配对完整。
03
compact_summary
调用临时 ReActAgent(reme_compactor),用结构化 Prompt 生成 Markdown 摘要。首次压缩从零生成,后续增量更新。
04
mark_compressed
原始消息写入 dialog/YYYY-MM-DD.jsonl 归档。从内存中删除。摘要写入 memory 的 _compressed_summary 字段。
FULL_DECISION_FLOW // EVERY_REASONING_CYCLE
TRIGGER
每轮推理前 MemoryCompactionHook 触发。计算系统提示词 + 旧摘要的 token 数 → 剩余可用 = threshold - 已占用
GATE CHECK
剩余可用 ≤ 0 ? → 警告并跳过(系统提示词本身就超了)。剩余可用 > 0 → 进入 Step 01
STEP 01: compact_tool_result
按字节阈值截断超长工具输出(原地修改)。最近 3 条保留 50KB,更早的截断至 3KB。完整内容存 tool_result/uuid.txt
STEP 02: context_check
从尾部向前累积 token,切割为 to_compact + to_keep。保证 tool_use / tool_result 配对完整
BRANCH: to_compact 为空 ?
为空 → 不压缩,直接推理。不为空 → 进入 Step 03
STEP 03a / 03b: compact_summary
无 previous_summary → 首次压缩(initial_user_message Prompt)。有 previous_summary → 增量更新(update_user_message Prompt)
LLM CALL: reme_compactor
创建临时 ReActAgent,调用 LLM 生成结构化 Markdown 摘要
VALIDITY CHECK
摘要包含 ## 标题? → 有效继续。无效 → 保存原始数据到 JSON,跳过本次压缩
STEP 04: mark_compressed
旧消息写入 dialog/YYYY-MM-DD.jsonl → 从内存中删除 → update_compressed_summary 摘要写入 memory
RESULT: 直接推理
上下文已压缩。LLM 接收三层结构:System Prompt + compact_summary + recent messages
CONTEXT_CHECKER // MESSAGE_SPLITTING_ALGORITHM
输入: messages 列表
计算每条消息的 token 数
总 token < threshold ?
是 → 不切割,全部保留
否 → 进入配对分析
配对保护
收集 tool_use 和 tool_result 的配对关系。如果 tool_result 被保留,对应的 tool_use 也拉进保留区
尾部向前累积
从最后一条消息开始向前累积 token。累积 + 当前 > reserve → 停止,之前归入 to_compact
输出: to_compact + to_keep + is_valid
验证 to_keep 中的 tool_use / tool_result 配对完整性。reserve 硬上限 12.8K tokens
配对保护: tool_result 保留 → tool_use 同步保留
切割方向: 从尾部向前累积
硬上限: reserve = 12.8K tokens
TOOL_RESULT_COMPACTION // BYTE_THRESHOLD_STRATEGY
RECENT (recent_n=3)
低截断: recent_max_bytes = 50,000
保留较多内容
完整内容同时写入文件
消息中保留截断片段 + 文件路径引用
OLD (> recent_n)
高截断: old_max_bytes = 3,000
激进截断至 3KB
继续引用已有文件路径
Browser Use 类工具只保留文件引用
SPECIAL: BROWSER USE
首次调用保存原始 HTML 到文件,后续只保留文件引用
SPECIAL: FILE READ
大文件输出自动 Offload,只保留摘要
KEY DESIGN
原地修改 messages,不是生成新的"压缩层"
COMPACT_SUMMARY // INITIAL_VS_INCREMENTAL
3A // 首次压缩 (Initial)
CONDITION
memory 中无 previous_summary
PROMPT: initial_user_message
输入: # conversation + 旧对话。LLM 从零生成结构化摘要
// OUTPUT FORMAT
## 目标
## 约束和偏好
## 进展(已完成 / 进行中 / 阻塞)
## 关键决策
## 下一步
## 关键上下文
3B // 增量更新 (Incremental)
CONDITION
memory 中已有 previous_summary
PROMPT: update_user_message
输入: # conversation + 旧对话 + # previous-summary + 上次摘要。LLM 合并输出更新后的摘要
// UPDATE RULES
+ 保留先前摘要的所有现有信息
+ 从新消息添加新的进展、决策和上下文
+ 完成时将"进行中"移到"已完成"
+ 根据已完成内容更新"下一步"
+ 不再相关的内容可以删除
KEY INSIGHT: 如果对话经历了 5 次压缩,compact_summary 不是 5 份摘要拼在一起,而是一份不断被"更新"的活文档。LLM 每次拿到旧摘要 + 新对话,合并输出一份更新后的摘要。
LLM_COMPACTOR // TEMPORARY_REACT_AGENT
AGENT NAME
reme_compactor
TYPE
临时 ReActAgent
LIFECYCLE
仅存在于压缩过程
OUTPUT
纯文本 Markdown
VALIDATION
_is_valid_summary()
FAIL STRATEGY
保存原始 JSON + 跳过
VALIDITY RULE
必须包含 ## 标题才算有效。否则跳过压缩,保存原始数据到 JSON 供调试。压缩用的 LLM 可独立配置(如用便宜的小模型)
COMPACT_SUMMARY_EXAMPLE // OUTPUT_STRUCTURE
## 目标
用户希望深入研究 CoPaw 项目的架构设计,特别是上下文管理和技能广播机制
## 约束和偏好
- 报告需要写到 Obsidian 笔记中
- 使用 Obsidian Flavored Markdown 格式
- 需要源码级分析深度
## 进展
### 已完成
- [x] 通过 GitHub API 获取仓库基本信息
- [x] 读取 memory_compaction.py 源码
- [x] 分析 ReMeLight 记忆管理器实现
### 进行中
- [ ] 分析 compactor.py 的 Prompt 模板设计
- [ ] 确认 update 模式的增量合并策略
## 关键决策
- 使用 ReMeLight 作为记忆后端: 支持向量搜索 + 全文搜索双引擎
- 双轨 Offload 策略: 工具结果和对话历史分别处理
## 下一步
1. 完成 compactor Prompt 分析
2. 补充技能广播机制到报告
3. 修正 Mermaid 图表
## 关键上下文
- 项目地址: github.com/agentscope-ai/CoPaw
- ReMe 版本: 0.3.1.8
- compact_ratio: 0.7, reserve_ratio: 0.1
POST_PROCESSING // ARCHIVE_DELETE_UPDATE
A
_append_messages_to_dialog()
将被压缩的原始消息以 JSONL 格式追加到 dialog/ 目录
ARCHIVE
B
self.content = [msg for msg if msg.id not in msg_ids]
从内存消息列表中移除已归档的消息
DELETE
C
update_compressed_summary()
将新的摘要文本写入 memory 的 _compressed_summary 字段
UPDATE
FINAL_CONTEXT_STRUCTURE // SENT TO LLM
LAYER 1 // FIXED
系统提示词 System Prompt
Agent 角色设定 + 基础指令。始终保留,永不压缩。
LAYER 2 // DYNAMIC
compact_summary
结构化摘要(Goal / Progress / Decisions / Context)。首次压缩后生成,增量更新——不是多份摘要拼在一起,而是一份不断被"更新"的活文档。
LAYER 3 // RECENT
messages(最近 N 条)
工具输出已被截断,附带文件路径引用。保留区上限 12.8K tokens。
CONFIGURATION_PARAMETERS
max_input_length128,000
memory_compact_ratio0.7
memory_reserve_ratio0.1
recent_n3
old_max_bytes3,000
recent_max_bytes50,000
retention_days30
compact_threshold89,600