AgentScope 2

AgentScope Java 2.0中的上下文压缩

前面介绍了说ASJ 2中把Memory给干掉了,但是我们介绍ASJ 1.0的时候,说过一个上下文自动压缩,他也是基于Memory机制扩展的。那么2.0中又是则呢么做的呢? 2.0 里这套机制部以 middleware 形式插到 on…

TL;DR

前面介绍了说ASJ 2中把Memory给干掉了,但是我们介绍ASJ 1.0的时候,说过一个上下文自动压缩,他也是基于Memory机制扩展的。那么2.0中又是则呢么做的呢? 2.0 里这套机制部以 middleware 形式插到 on…

前面介绍了说ASJ 2中把Memory给干掉了,但是我们介绍ASJ 1.0的时候,说过一个上下文自动压缩,他也是基于Memory机制扩展的。那么2.0中又是则呢么做的呢? 2.0 里这套机制部以 middleware 形式插到 onReasoning 钩子上,自动运行、可独立开关: | 策略 | 处理的问题维度 | 实现 | | --- | --- | --- | | 对话摘要压缩 | context 的 | CompactionMiddleware | | 大工具结果外置 | context 的 | ToolResultEvictionMiddleware | | 溢出兜底重试 | 模型端仍抛 context_length_exceeded | HarnessAgent.recoverFromOverflow | | 预压缩参数截断/结果精简 | 老消息里的 tool_call 参数与 tool_result 数据太长 | CompactionConfig.TruncateArgsConfig |

四条策略默认全开、也可以单独关闭。

对话摘要压缩

CompactionMiddleware 是一个Middleware,重写了onReasoning方法。

public Flux<AgentEvent> onReasoning(Agent agent, RuntimeContext ctx,
                                     ReasoningInput input,
                                     Function<ReasoningInput, Flux<AgentEvent>> next) {
    // ① 拆 system 与 conversation
    Msg systemMsg  = /* messages[0] if SYSTEM */;
    List<Msg> conv = /* rest */;

    // ② 动态阈值展开
    CompactionConfig eff = resolveEffectiveConfig();

    // ③ 交给 ConversationCompactor
    return compactor.compactIfNeeded(ctx, conv, eff, agentId, sessionId)
            .flatMapMany(opt -> {
                if (opt.isPresent()) {
                    // ④ 就地覆写 AgentState.contextMutable()
                    applyToContext(state, opt.get());
                    // ⑤ 构造新 ReasoningInput
                    List<Msg> newMsgs = withSystem(systemMsg, opt.get());
                    return next.apply(new ReasoningInput(newMsgs,
                                                        input.tools(),
                                                        input.options()));
                }
                return next.apply(input);         // ⑥ 未压缩透传
            })
            .onErrorResume(e -> next.apply(input)); // ⑦ 任何异常降级
}

核心压缩算法在ConversationCompactor中,执行流程如下

messages
   │
   ▼
【1】truncateArgs          ← 非-LLM,只对老 ASSISTANT.tool_use 入参截断
   │
   ▼
【2】pruneToolResults      ← 非-LLM,精简老 TOOL 结果(保留最近 40K tokens)
   │
   ▼
【3】shouldCompact?        ← messages 数或 token 数超阈值
   │ 是
   ▼
【4】determineCutoffIndex  ← 按 keepTokens 或 keepMessages 找切点
   │   └─ findSafeCutoffPoint:不拆 ASSISTANT/TOOL pair
   │
   ▼
【5】prefix + tail = split(messages, cutoff)
   │   └─ prefix 会先 filterSummaryMessages() 剔掉老的 __compaction_summary__
   │
   ▼
【6】flushBeforeCompact?   ← 抽取事实到 daily ledger / MEMORY.md
   │
   ▼
【7】offloadBeforeCompact? ← 整段 messages 追加到 sessions/<sessionId>.log.jsonl
   │                        取回落盘路径供 summary 消息引用
   │
   ▼
【8】summarizePrefix       ← 一次 model.stream(),用结构化 prompt 生成摘要
   │
   ▼
compacted = [summaryMsg(role=USER, name="__compaction_summary__")] + tail
版本提示

模型、框架与接口会持续变化。涉及版本号、参数与生产配置时,请在实践前对照对应官方文档。

LLMentor系统化学习大模型应用工程

内容来自个人课程知识库备份,并经过结构化整理。技术版本持续演进,生产使用前请结合官方文档验证。