MemoraX Code 在长对话中的记忆压缩与摘要策略

文章导读
面对长时间 Coding Agent 对话,记忆压缩的目标不是把所有旧消息压成一条完整记录,而是把已经讨论过的需求、技术选型和决定提取出来,腾出上下文空间给后续任务。MemoraX Code 本身维护一份带 token 统计的记忆列表,通过配置压缩阈值并调用外部模型生成结构化摘要,可以在不丢失关键信息的前提下控制输入规模。需要明确的是,摘要只能近似还原对话,不适合用来保存需要逐字核对的接口字段或错
📋 目录
  1. A 监控当前记忆条数与 token 大小
  2. B 开启自动压缩开关并设置阈值
  3. C 调用外部模型生成摘要并回调存储
  4. D 保留关键实体和决定,丢弃中断对话
  5. E 验证压缩后上下文信息不丢失
A A

面对长时间 Coding Agent 对话,记忆压缩的目标不是把所有旧消息压成一条完整记录,而是把已经讨论过的需求、技术选型和决定提取出来,腾出上下文空间给后续任务。MemoraX Code 本身维护一份带 token 统计的记忆列表,通过配置压缩阈值并调用外部模型生成结构化摘要,可以在不丢失关键信息的前提下控制输入规模。需要明确的是,摘要只能近似还原对话,不适合用来保存需要逐字核对的接口字段或错误信息,这类内容应在摘要之外单独保留。

适用场景:Coding Agent 连续多轮交互后记忆条数或 token 体积接近上下文限制。操作动作:先监控 memories 和 total_size 增长,在配置中设置 compression_threshold=200 与 compress_batch_size=50,触发后调用外部摘要接口生成 JSON 结果并回写更新。验证方式:压缩后向 Agent 追问之前讨论过的具体决定和 action_items,检查是否从摘要中可提取。风险边界:摘要质量受模型能力和 prompt 影响,中断对话中的临时猜测可能被丢弃,必要时应保留原始日志。

监控当前记忆条数与 token 大小

压缩前必须确认增长曲线。MemoraX Code 的管理接口通常会暴露当前记忆列表和整体体积,建议先记录以下字段:每个 memory 的唯一 ID、创建时间、token 估算值,以及整个上下文的 total_size。若接口返回 memories 数组,可以用一段简单脚本定时抓取:

# 通用示例:根据实际接口路径调整
import requests, time

resp = requests.get("http://127.0.0.1:8000/v1/memories", timeout=10)
data = resp.json()
print("count:", len(data["memories"]))
print("total_tokens:", data["total_size"])

建议每隔 10 分钟或每轮对话后记录一次,观察趋势。如果 total_size 增长快到上下文窗口的一半,就该准备设置压缩阈值。这里的记忆条数不等于 token 数,但条数过多会导致每次查询都要扫描大量条目,因此两者都需要关注。

开启自动压缩开关并设置阈值

MemoraX Code 提供自动压缩配置项,通常在 memora/config.toml 或启动参数中。最直接的触发条件是记忆条数超过阈值时,启动一批压缩任务。建议先设置:

compression_threshold = 200
compress_batch_size = 50

compression_threshold=200 表示当记忆条数达到 200 条时触发一次压缩;compress_batch_size=50 表示每次从最旧的记忆中取 50 条进行合并。这个阈值不是固定的,需要根据模型上下文窗口和平均每条记忆的 token 大小调整。如果单条记忆较长,可把条数阈值调低;如果上下文中代码占比高,则要预留更多空间。

开启自动压缩后,建议先观察触发频率。如果每两轮对话就压缩一次,说明阈值太小;如果超过很多轮还不触发,说明阈值偏大。触发频率不是越高越好,因为每次压缩都要调用外部模型。

调用外部模型生成摘要并回调存储

当压缩任务启动,需要把一批原始记忆发送给外部模型,生成结构化摘要,再通过 MemoraX Code 的更新接口把原记忆替换成新摘要。下面是一个使用 OpenAI 兼容接口的调用骨架,接口地址和 key 需要按实际环境替换:

MemoraX Code 在长对话中的记忆压缩与摘要策略
import json, requests

def generate_summary(memory_entries):
    prompt = {
        "role": "system",
        "content": "你是对话摘要器。根据给出的记忆条目生成 JSON 摘要,包含 decisions 和 action_items。"
    }
    messages = [prompt] + [{"role": "user", "content": json.dumps(memory_entries)}]
    resp = requests.post(
        "https://api.example.com/v1/chat/completions",
        headers={"Authorization": "Bearer YOUR_API_KEY"},
        json={
            "model": "gpt-4o-mini",
            "messages": messages,
            "response_format": {"type": "json_object"}
        }
    )
    return resp.json()["choices"][0]["message"]["content"]

# 调用后回写到 MemoraX Code,示意如下:
# update_memory(child_ids=old_memory_ids, new_summary=summary)

回调更新时,需要把旧记忆的 ID 列表传进去,让 MemoraX Code 将原始条目合并为一条新记忆。更新完成前建议先保留原始数据,确认摘要内容可用后再删除旧条目,避免压缩失败导致上下文丢失。

保留关键实体和决定,丢弃中断对话

摘要是否可用,取决于 prompt 是否强制提取决策必要信息。在摘要 prompt 中要求输出 decisions(最终决定的结论)和 action_items(下一步要做的事),并且用 JSON 格式。这样后续 Agent 查询记忆时,可以直接解析结构化字段,而不是从长文本中重读。可参考的 prompt 片段:

你正在整理编程对话记忆。请从对话中提取以下 JSON 字段:
- project: 项目名称
- decisions: 数组,每条包含 topic、choice、reason
- action_items: 数组,每条包含 task、status、owner
- key_entities: 数组,包含文件名、函数名、依赖名、版本号
忽略重复试错、临时猜测和中断对话的内容。
输出纯 JSON,不要额外的解释。

这里的 key_entities 是额外建议,可以自行添加。关键实体包括文件路径、包名、函数名、端口号等,这些比自然语言更容易丢失。丢弃中断对话的原则是:只保留已经达成的结论或明确要执行的事项,正在进行的思考过程不写入摘要。如果某段对话最后没有产出决定,它通常不值得占用记忆空间。

验证压缩后上下文信息不丢失

摘要写回后,需要立即验证 Agent 能否从新记忆里获取之前讨论的具体细节。不要只检查摘要文本是否通顺,而应该向 Agent 提问之前提到的技术选型、遗留 bug 和下一步计划。验证问题示例:

  • 我们之前决定用哪个缓存方案?有没有备选?
  • 刚才提到的 user_auth.timeout 问题,root cause 定位到哪个函数?
  • 下一步要改哪个文件,优先级是什么?
  • 依赖清单里是否加入了 pymongo 和 redis?

如果 Agent 能准确回答这些具体问题,说明摘要保留了关键实体和决定。如果是通过猜测回答或答成泛泛内容,则说明摘要 prompt 的提取粒度不够。此时需要回退到压缩前的记忆,重新调整 prompt,把遗漏的关键词加入提取规则。压缩不是一次性的,每次触发后都应该走一遍验证清单,确认新增加记忆路径上没有信息断层。