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): # ← 硬编码
ContextConfig(context/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 压缩」在背后退化成了什么。前端策略选项给了一个虚假的安心感。
期望行为
compression_threshold 可配置:在 ContextConfig 中新增字段,允许用户通过前端设置(如「在上下文达到 __% 时压缩」)
- 智能默认值:初始值不再固定 82%,而是使用
max(1 - max_output_tokens / max_context_tokens, 0.5),确保预留空间 ≥ 模型最大输出
- 策略降级可视化:当 LLM 压缩失败 fallback 到硬截断时,向用户发送一条消息说明发生了什么(「上下文压缩未成功,已改用轮次截断,可能会丢失部分对话历史」)
依赖
和 #9251(三段式圆环)互补——三段式圆环在前端揭示「预留空间够不够」,可配置的阈值在后端解决「预留空间从何而来」。
Use Case / 使用场景
- 大输出模型(如 deepseek-v4-pro, 384K max output):用户将阈值设为 60%,确保压缩后有足够空间给生成,不会等到 82% 才反应过来
- 小输出模型(如 embedding 模型,4K max output):用户将阈值设为 95%,避免过早压缩、浪费上下文
- 调试与调优:用户对比不同阈值下的 agent 表现,找到自己工作流的 sweet spot
- 策略降级感知:用户看到「压缩未成功,改用轮次截断」后,可以手动调整阈值或切换到更大的压缩模型
Willing to Submit PR? / 是否愿意提交PR?
Code of Conduct
Description / 描述
上下文压缩的触发阈值
compression_threshold = 0.82在两个压缩器中均硬编码,不可配置,也不随模型的最大输出能力动态调整。硬编码位置
astrbot/core/agent/context/compressor.py:ContextConfig(context/config.py)根本没有compression_threshold字段:astr_main_agent.py构造 ContextManager 时也未传此参数。为什么 82% 不够
82% 是一个通用值,不考虑模型的最大输出。以 deepseek-v4-pro 为例:
预留 180K < 最大输出 384K。压缩触发了,剩下的空间仍然不够装一次完整生成。对一个大输出模型来说,合理的阈值应该是
1 - max_output/context_window:也就是说 deepseek-v4-pro 应该在 62.5% 就触发压缩,而不是 82%。
反过来,如果一个模型最大输出只有 4K(如部分 embedding 模型或小模型),阈值 82% 又太保守了——可以放到 95%+。
「LLM 压缩」策略的静默降级
另一个问题:用户在前端选择了
llm_compress,以为优雅地用模型做摘要。但实际可能无声降级为硬截断:用户永远不知道「LLM 压缩」在背后退化成了什么。前端策略选项给了一个虚假的安心感。
期望行为
compression_threshold可配置:在ContextConfig中新增字段,允许用户通过前端设置(如「在上下文达到 __% 时压缩」)max(1 - max_output_tokens / max_context_tokens, 0.5),确保预留空间 ≥ 模型最大输出依赖
和 #9251(三段式圆环)互补——三段式圆环在前端揭示「预留空间够不够」,可配置的阈值在后端解决「预留空间从何而来」。
Use Case / 使用场景
Willing to Submit PR? / 是否愿意提交PR?
Code of Conduct