Skip to content

feat: make context compression threshold configurable#9261

Open
Fronut wants to merge 1 commit into
AstrBotDevs:masterfrom
Fronut:feat/9252-configurable-compression-threshold
Open

feat: make context compression threshold configurable#9261
Fronut wants to merge 1 commit into
AstrBotDevs:masterfrom
Fronut:feat/9252-configurable-compression-threshold

Conversation

@Fronut

@Fronut Fronut commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Resolves #9252

上下文压缩此前固定在上下文占用达到 $82%$ 时触发。该固定值无法适应不同模型的最大输出能力:对于最大输出较大的模型,压缩触发后剩余空间可能不足以容纳一次完整生成;对于最大输出较小的模型,又可能过早压缩并损失可用上下文。

本次修改将压缩阈值改为可配置策略,并支持结合模型上下文窗口与最大输出预算计算阈值:

$$ T_{\text{output}}=\max\left(0,1-\frac{O}{C}\right) $$

其中 $C$ 为有效上下文窗口,$O$ 为有效最大输出预算。系统支持以下四种模式:

模式 有效阈值
percentage 使用用户设置的固定百分比
output_reserve 使用 $T_{\text{output}}$,为最大输出预留空间
min 使用固定百分比与 $T_{\text{output}}$ 中较小者
max 使用固定百分比与 $T_{\text{output}}$ 中较大者

当模型最大输出元数据不可用时,依赖输出预算的模式会安全退化到用户设置的固定百分比。

最关键的是,后端实际压缩阈值与前端展示使用同一个解析结果:运行时通过 resolve_compression_threshold() 计算并传入压缩器,Dashboard API 也调用该函数返回 effective_threshold。前端只消费后端结果,不复制阈值公式,从而避免显示值与实际压缩边界不一致。

Modifications / 改动点

  • 修改 astrbot/core/agent/context/config.py

    • 新增 resolve_compression_threshold(),统一解析压缩阈值;
    • 支持 percentageoutput_reserveminmax 四种模式;
    • 对模式、百分比、上下文窗口和输出预算进行规范化;
    • 输出 effective_thresholdoutput_threshold 和降级原因等结构化信息;
    • ContextConfig 中保存最终生效的 compression_threshold
  • 修改 astrbot/core/astr_main_agent.py 及 Agent 上下文创建流程:

    • 根据当前模型的有效上下文窗口和最大输出预算解析阈值;
    • 将同一个有效阈值传入主 Agent、工具循环 Agent 和内部子阶段;
    • 确保轮次截断压缩器与 LLM 摘要压缩器使用一致的触发边界。
  • 修改 astrbot/core/config/default.py

    • 新增压缩阈值模式配置;
    • 新增固定百分比配置;
    • 新增最大输出 Token 覆盖配置,允许在模型元数据缺失或需要手动调整时指定输出预算;
    • 补充配置项元数据与校验范围。
  • 修改 astrbot/dashboard/services/config_service.py

    • 在 Provider 列表响应中返回后端解析后的 compression_thresholds
    • 每个 Provider 返回规范化输入、输出预算阈值、最终有效阈值和降级原因;
    • 不修改或污染原始 Provider 配置对象。
  • 修改 dashboard/src/api/v1.ts

    • 增加后端压缩阈值响应的 TypeScript 类型;
    • 前端可直接使用后端返回的 effective_threshold,无需重新实现公式。
  • 修改中、英、俄三种配置元数据:

    • 增加四种策略及相关配置项的名称和说明。
  • 新增测试:

    • 覆盖四种阈值模式;
    • 覆盖缺失最大输出元数据时的降级行为;
    • 覆盖非法模式、百分比越界和输出预算大于上下文窗口等边界情况;
    • 验证两种压缩器使用同一个有效阈值及准确触发边界;
    • 验证 Dashboard 返回的阈值与后端解析结果一致;
    • 验证 Provider 原始配置不会被响应组装过程污染。

本 PR 聚焦于 #9252 的“压缩阈值可配置化”以及前后端阈值一致性。Issue 中提到的“LLM 压缩失败时向用户展示策略降级信息”属于独立的运行时通知行为,不包含在本次修改中,适合后续单独实现。

  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

验证步骤

  1. 运行上下文管理与 Dashboard API 测试:
uv run pytest tests/agent/test_context_manager.py tests/test_fastapi_v1_dashboard.py -q

结果:

135 passed, 1 warning in 25.27s

唯一警告为项目既有的 Python audioop 弃用提示,与本次修改无关。

  1. 运行前端 TypeScript 类型检查:
cd dashboard
pnpm typecheck

结果:vue-tsc --noEmit 执行通过。

  1. 关键行为验证:
场景 结果
percentage 模式 使用用户配置的固定百分比
output_reserve 模式,$C=1000$、$O=400$ 有效阈值为 $0.6$
min 模式,固定值 $0.82$、输出预算阈值 $0.6$ 有效阈值为 $0.6$
max 模式,固定值 $0.82$、输出预算阈值 $0.6$ 有效阈值为 $0.82$
最大输出预算缺失 安全退化为固定百分比并返回降级原因
最大输出预算大于上下文窗口 输出预算阈值限制为 $0$
轮次截断与 LLM 摘要压缩 均使用同一个后端有效阈值
Dashboard 阈值展示 读取后端返回的 effective_threshold,与实际压缩边界一致

Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc.
    / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。

  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above.
    / 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”

  • 🤓 I have ensured that no new dependencies are introduced, OR if new dependencies are introduced, they have been added to the appropriate locations in requirements.txt and pyproject.toml.
    / 我确保没有引入新依赖库,或者引入了新依赖库的同时将其添加到 requirements.txtpyproject.toml 文件相应位置。

  • 😮 My changes do not introduce malicious code.
    / 我的更改没有引入恶意代码。

Summary by Sourcery

Make context compression thresholds configurable and shared between backend runtime and dashboard, using model context and output limits to compute an effective trigger ratio.

New Features:

  • Introduce configurable context compression threshold strategies (percentage, output_reserve, min, max) that account for model context window and maximum output tokens.
  • Expose backend-resolved compression thresholds via the dashboard provider APIs so the UI can display the actual effective compression boundary.

Enhancements:

  • Add a unified threshold resolution helper and wire the resolved effective threshold through main agent, tool-loop agent, and context manager so all compressors use the same trigger point.
  • Extend provider configuration defaults and metadata (including i18n labels) to support the new compression threshold strategy and output token settings.

Tests:

  • Add tests covering all threshold modes, fallback behavior when max output tokens are unavailable, edge cases such as invalid modes and oversized outputs, compressor trigger boundaries, and dashboard exposure of resolved thresholds.

@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. area:core The bug / feature is about astrbot's core, backend area:webui The bug / feature is about webui(dashboard) of astrbot. labels Jul 13, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • In build_main_agent the max_context_tokens passed to resolve_compression_threshold comes only from provider.provider_config.get("max_context_tokens", 0) and ignores model metadata or fallback_max_context_tokens, while the dashboard service uses those fallbacks; this can lead to different effective thresholds between runtime and dashboard and should be reconciled.
  • The fallback_reason values returned by resolve_compression_threshold (e.g. "max_output_tokens_unavailable") are currently hard-coded strings; consider centralizing them in constants or an enum-like structure to avoid typos and make future handling more robust.
  • The normalization of percentage in resolve_compression_threshold clamps to a minimum of 0.01, meaning an explicit configuration of 0 silently becomes 1%; if this is not intentional, you may want to either allow 0 or raise/validate on out-of-range values instead of coercing them.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `build_main_agent` the `max_context_tokens` passed to `resolve_compression_threshold` comes only from `provider.provider_config.get("max_context_tokens", 0)` and ignores model metadata or `fallback_max_context_tokens`, while the dashboard service uses those fallbacks; this can lead to different effective thresholds between runtime and dashboard and should be reconciled.
- The `fallback_reason` values returned by `resolve_compression_threshold` (e.g. `"max_output_tokens_unavailable"`) are currently hard-coded strings; consider centralizing them in constants or an enum-like structure to avoid typos and make future handling more robust.
- The normalization of `percentage` in `resolve_compression_threshold` clamps to a minimum of `0.01`, meaning an explicit configuration of `0` silently becomes `1%`; if this is not intentional, you may want to either allow `0` or raise/validate on out-of-range values instead of coercing them.

## Individual Comments

### Comment 1
<location path="astrbot/dashboard/services/config_service.py" line_range="1592-1595" />
<code_context>
+                model_metadata[model_id] = model_info
+            settings = self.config.get("provider_settings", {})
+            metadata_limit = model_info.get("limit", {}) if model_info else {}
+            context_tokens = int(
+                provider_response.get("max_context_tokens", 0)
+                or metadata_limit.get("context", 0)
+                or settings.get("fallback_max_context_tokens", 128000)
+            )
+            configured_output_tokens = max(
</code_context>
<issue_to_address>
**suggestion:** Avoid hardcoding `128000` as a fallback context window; centralize or derive it.

Because `128000` is a domain-specific value, hardcoding it here makes future changes easy to miss and creates a second source of truth. Please either read this default from shared configuration/constants, or reuse the existing fallback logic for computing context windows so this value is defined in one place only.

Suggested implementation:

```python
                or metadata_limit.get("context", 0)
                or settings.get(
                    "fallback_max_context_tokens", DEFAULT_FALLBACK_MAX_CONTEXT_TOKENS
                )

```

To fully centralize the fallback context window, you should also:
1. Define `DEFAULT_FALLBACK_MAX_CONTEXT_TOKENS` once at module level (near the top of `config_service.py`), e.g.:
   ```python
   DEFAULT_FALLBACK_MAX_CONTEXT_TOKENS = 128000
   ```
   or import it from a shared constants/config module if one already exists.
2. If there is an existing mechanism or helper for computing default context windows elsewhere in the codebase, consider replacing `DEFAULT_FALLBACK_MAX_CONTEXT_TOKENS` with a call to that helper or a constant defined there, so the default is maintained in a single shared place.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread astrbot/dashboard/services/config_service.py Outdated

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces configurable context compression thresholds for Astrbot, allowing users to choose how percentage and output-reserve limits are combined (e.g., via percentage, output reserve, min, or max modes). It implements threshold resolution logic, integrates it across the agent runner, main agent, pipeline stages, and dashboard config service, and adds corresponding unit tests. The review feedback highlights several opportunities to improve robustness by safely converting configuration values (such as token limits and percentages) to integers or floats with proper fallbacks and error handling to prevent potential TypeErrors or ValueErrors at runtime.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread astrbot/core/agent/context/config.py
Comment thread astrbot/core/agent/runners/tool_loop_agent_runner.py Outdated
Comment thread astrbot/dashboard/services/config_service.py Outdated
@Fronut Fronut force-pushed the feat/9252-configurable-compression-threshold branch from 0ab3bcd to d20b2aa Compare July 13, 2026 16:03
@Fronut

Fronut commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces configurable context compression thresholds and modes (percentage, output_reserve, min, max) to dynamically resolve context compression behavior. It updates the configuration structures, agent runners, main agent builder, and dashboard services to support these new settings, alongside adding helper functions for float configuration coercion and corresponding unit tests. The review feedback highlights a potential AttributeError in both astr_main_agent.py and config_service.py if the 'limit' key in model metadata is explicitly set to null, suggesting a safer fallback mechanism.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread astrbot/core/astr_main_agent.py Outdated
Comment thread astrbot/dashboard/services/config_service.py Outdated
@Fronut Fronut force-pushed the feat/9252-configurable-compression-threshold branch from d20b2aa to 7cc6d42 Compare July 13, 2026 16:17
@Fronut

Fronut commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces configurable context compression thresholds for LLM agents, supporting multiple threshold modes ('percentage', 'output_reserve', 'min', 'max') and adding helper functions to resolve and coerce configuration values. The review feedback suggests adding a warn parameter to resolve_compression_threshold and passing it to coercion functions to prevent log pollution during frequent dashboard API requests. Additionally, it is recommended to handle None values explicitly in coerce_float_config to avoid warning logs for unset configurations.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread astrbot/core/agent/context/config.py
Comment thread astrbot/core/agent/context/config.py
Comment thread astrbot/dashboard/services/config_service.py
Comment thread astrbot/core/utils/config_number.py Outdated
@Fronut Fronut force-pushed the feat/9252-configurable-compression-threshold branch from 7cc6d42 to 43dcfe3 Compare July 13, 2026 16:23
@Fronut

Fronut commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces configurable context compression thresholds for the agent context manager. It adds a new resolve_compression_threshold utility supporting multiple modes ('percentage', 'output_reserve', 'min', 'max') to determine when context compression is triggered. Additionally, it introduces coerce_float_config for safe float configuration parsing, updates default configurations, adds localization strings for the dashboard, and includes comprehensive unit tests. There are no review comments, so I have no feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core The bug / feature is about astrbot's core, backend area:webui The bug / feature is about webui(dashboard) of astrbot. size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant