Skip to content

[Feature] 上下文压缩阈值可配置化 #9252

Description

@Fronut

Description / 描述

上下文压缩的触发阈值 compression_threshold = 0.82 在两个压缩器中均硬编码,不可配置,也不随模型的最大输出能力动态调整。

硬编码位置

astrbot/core/agent/context/compressor.py

# TruncateByTurnsCompressor.__init__ (line 66)
class TruncateByTurnsCompressor:
    def __init__(self, truncate_turns: int = 1,
                 compression_threshold: float = 0.82):  # ← 硬编码

# LLMSummaryCompressor.__init__ (line 131)
class LLMSummaryCompressor:
    def __init__(self, provider, keep_recent_ratio: float = 0.15,
                 compression_threshold: float = 0.82):  # ← 硬编码

ContextConfigcontext/config.py)根本没有 compression_threshold 字段:

@dataclass
class ContextConfig:
    max_context_tokens: int = 0
    enforce_max_turns: int = -1
    truncate_turns: int = 1
    llm_compress_keep_recent_ratio: float = 0.15
    # compression_threshold  ← 不存在

astr_main_agent.py 构造 ContextManager 时也未传此参数。

为什么 82% 不够

82% 是一个通用值,不考虑模型的最大输出。以 deepseek-v4-pro 为例:

指标
上下文窗口 1M
82% 阈值 820K
预留空间 ~180K
模型最大输出 384K

预留 180K < 最大输出 384K。压缩触发了,剩下的空间仍然不够装一次完整生成。对一个大输出模型来说,合理的阈值应该是 1 - max_output/context_window

合理阈值 = 1 - 384K / 1M = 1 - 0.375 = 62.5%

也就是说 deepseek-v4-pro 应该在 62.5% 就触发压缩,而不是 82%。

反过来,如果一个模型最大输出只有 4K(如部分 embedding 模型或小模型),阈值 82% 又太保守了——可以放到 95%+。

「LLM 压缩」策略的静默降级

另一个问题:用户在前端选择了 llm_compress,以为优雅地用模型做摘要。但实际可能无声降级为硬截断:

上下文 > 82% → LLM 压缩发起
  ├─ 全量上下文 > 压缩用模型的窗口 → 压缩失败,return messages(原样返回)
  ├─ LLM 返回空摘要 → return messages
  └─ 压缩成功但 double check 仍超标 → truncate_by_halving(对半硬砍)

用户永远不知道「LLM 压缩」在背后退化成了什么。前端策略选项给了一个虚假的安心感。

期望行为

  1. compression_threshold 可配置:在 ContextConfig 中新增字段,允许用户通过前端设置(如「在上下文达到 __% 时压缩」)
  2. 智能默认值:初始值不再固定 82%,而是使用 max(1 - max_output_tokens / max_context_tokens, 0.5),确保预留空间 ≥ 模型最大输出
  3. 策略降级可视化:当 LLM 压缩失败 fallback 到硬截断时,向用户发送一条消息说明发生了什么(「上下文压缩未成功,已改用轮次截断,可能会丢失部分对话历史」)

依赖

#9251(三段式圆环)互补——三段式圆环在前端揭示「预留空间够不够」,可配置的阈值在后端解决「预留空间从何而来」。

Use Case / 使用场景

  1. 大输出模型(如 deepseek-v4-pro, 384K max output):用户将阈值设为 60%,确保压缩后有足够空间给生成,不会等到 82% 才反应过来
  2. 小输出模型(如 embedding 模型,4K max output):用户将阈值设为 95%,避免过早压缩、浪费上下文
  3. 调试与调优:用户对比不同阈值下的 agent 表现,找到自己工作流的 sweet spot
  4. 策略降级感知:用户看到「压缩未成功,改用轮次截断」后,可以手动调整阈值或切换到更大的压缩模型

Willing to Submit PR? / 是否愿意提交PR?

  • Yes, I am willing to submit a PR. / 是的,我愿意提交 PR。

Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:coreThe bug / feature is about astrbot's core, backendenhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions