feat: make context compression policy configurable and stabilize compression UX
This commit is contained in:
parent
7e03e3cd5f
commit
bc939a0098
@ -23,6 +23,19 @@ MAX_CONSIDERATION_ITEMS = 10
|
|||||||
TONE_PRESETS = ["健谈", "幽默", "直言不讳", "鼓励性", "诗意", "企业商务", "打破常规", "同理心"]
|
TONE_PRESETS = ["健谈", "幽默", "直言不讳", "鼓励性", "诗意", "企业商务", "打破常规", "同理心"]
|
||||||
THINKING_INTERVAL_MIN = 1
|
THINKING_INTERVAL_MIN = 1
|
||||||
THINKING_INTERVAL_MAX = 50
|
THINKING_INTERVAL_MAX = 50
|
||||||
|
DEFAULT_SHALLOW_COMPRESS_TRIGGER_TOKENS = 80_000
|
||||||
|
DEFAULT_SHALLOW_COMPRESS_KEEP_RECENT_TOOLS = 15
|
||||||
|
DEFAULT_SHALLOW_COMPRESS_MAX_REPLACE_PER_ROUND = 10
|
||||||
|
DEFAULT_SHALLOW_COMPRESS_TRIGGER_TOOL_CALLS_INTERVAL = 10
|
||||||
|
DEFAULT_DEEP_COMPRESS_TRIGGER_TOKENS = 150_000
|
||||||
|
MIN_COMPRESSION_TRIGGER_TOKENS = 1_000
|
||||||
|
MAX_COMPRESSION_TRIGGER_TOKENS = 2_000_000
|
||||||
|
MIN_SHALLOW_KEEP_RECENT_TOOLS = 0
|
||||||
|
MAX_SHALLOW_KEEP_RECENT_TOOLS = 500
|
||||||
|
MIN_SHALLOW_MAX_REPLACE_PER_ROUND = 1
|
||||||
|
MAX_SHALLOW_MAX_REPLACE_PER_ROUND = 200
|
||||||
|
MIN_SHALLOW_TRIGGER_TOOL_CALLS_INTERVAL = 1
|
||||||
|
MAX_SHALLOW_TRIGGER_TOOL_CALLS_INTERVAL = 200
|
||||||
|
|
||||||
DEFAULT_PERSONALIZATION_CONFIG: Dict[str, Any] = {
|
DEFAULT_PERSONALIZATION_CONFIG: Dict[str, Any] = {
|
||||||
"enabled": False,
|
"enabled": False,
|
||||||
@ -44,6 +57,11 @@ DEFAULT_PERSONALIZATION_CONFIG: Dict[str, Any] = {
|
|||||||
"image_compression": "original", # original / 1080p / 720p / 540p
|
"image_compression": "original", # original / 1080p / 720p / 540p
|
||||||
"auto_shallow_compress_enabled": False,
|
"auto_shallow_compress_enabled": False,
|
||||||
"auto_deep_compress_enabled": False,
|
"auto_deep_compress_enabled": False,
|
||||||
|
"shallow_compress_trigger_tokens": None,
|
||||||
|
"shallow_compress_keep_recent_tools": None,
|
||||||
|
"shallow_compress_max_replace_per_round": None,
|
||||||
|
"shallow_compress_trigger_tool_calls_interval": None,
|
||||||
|
"deep_compress_trigger_tokens": None,
|
||||||
"silent_tool_disable": False, # 禁用工具时不向模型插入提示
|
"silent_tool_disable": False, # 禁用工具时不向模型插入提示
|
||||||
"enhanced_tool_display": True, # 增强工具显示
|
"enhanced_tool_display": True, # 增强工具显示
|
||||||
}
|
}
|
||||||
@ -58,6 +76,8 @@ __all__ = [
|
|||||||
"ensure_personalization_config",
|
"ensure_personalization_config",
|
||||||
"build_personalization_prompt",
|
"build_personalization_prompt",
|
||||||
"sanitize_personalization_payload",
|
"sanitize_personalization_payload",
|
||||||
|
"resolve_context_compression_settings",
|
||||||
|
"validate_context_compression_settings",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -198,6 +218,71 @@ def sanitize_personalization_payload(
|
|||||||
else:
|
else:
|
||||||
base["auto_deep_compress_enabled"] = bool(base.get("auto_deep_compress_enabled", False))
|
base["auto_deep_compress_enabled"] = bool(base.get("auto_deep_compress_enabled", False))
|
||||||
|
|
||||||
|
if "shallow_compress_trigger_tokens" in data:
|
||||||
|
base["shallow_compress_trigger_tokens"] = _sanitize_optional_int(
|
||||||
|
data.get("shallow_compress_trigger_tokens"),
|
||||||
|
min_value=MIN_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
max_value=MAX_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
base["shallow_compress_trigger_tokens"] = _sanitize_optional_int(
|
||||||
|
base.get("shallow_compress_trigger_tokens"),
|
||||||
|
min_value=MIN_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
max_value=MAX_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
)
|
||||||
|
|
||||||
|
if "shallow_compress_keep_recent_tools" in data:
|
||||||
|
base["shallow_compress_keep_recent_tools"] = _sanitize_optional_int(
|
||||||
|
data.get("shallow_compress_keep_recent_tools"),
|
||||||
|
min_value=MIN_SHALLOW_KEEP_RECENT_TOOLS,
|
||||||
|
max_value=MAX_SHALLOW_KEEP_RECENT_TOOLS,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
base["shallow_compress_keep_recent_tools"] = _sanitize_optional_int(
|
||||||
|
base.get("shallow_compress_keep_recent_tools"),
|
||||||
|
min_value=MIN_SHALLOW_KEEP_RECENT_TOOLS,
|
||||||
|
max_value=MAX_SHALLOW_KEEP_RECENT_TOOLS,
|
||||||
|
)
|
||||||
|
|
||||||
|
if "shallow_compress_max_replace_per_round" in data:
|
||||||
|
base["shallow_compress_max_replace_per_round"] = _sanitize_optional_int(
|
||||||
|
data.get("shallow_compress_max_replace_per_round"),
|
||||||
|
min_value=MIN_SHALLOW_MAX_REPLACE_PER_ROUND,
|
||||||
|
max_value=MAX_SHALLOW_MAX_REPLACE_PER_ROUND,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
base["shallow_compress_max_replace_per_round"] = _sanitize_optional_int(
|
||||||
|
base.get("shallow_compress_max_replace_per_round"),
|
||||||
|
min_value=MIN_SHALLOW_MAX_REPLACE_PER_ROUND,
|
||||||
|
max_value=MAX_SHALLOW_MAX_REPLACE_PER_ROUND,
|
||||||
|
)
|
||||||
|
|
||||||
|
if "deep_compress_trigger_tokens" in data:
|
||||||
|
base["deep_compress_trigger_tokens"] = _sanitize_optional_int(
|
||||||
|
data.get("deep_compress_trigger_tokens"),
|
||||||
|
min_value=MIN_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
max_value=MAX_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
base["deep_compress_trigger_tokens"] = _sanitize_optional_int(
|
||||||
|
base.get("deep_compress_trigger_tokens"),
|
||||||
|
min_value=MIN_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
max_value=MAX_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
)
|
||||||
|
|
||||||
|
if "shallow_compress_trigger_tool_calls_interval" in data:
|
||||||
|
base["shallow_compress_trigger_tool_calls_interval"] = _sanitize_optional_int(
|
||||||
|
data.get("shallow_compress_trigger_tool_calls_interval"),
|
||||||
|
min_value=MIN_SHALLOW_TRIGGER_TOOL_CALLS_INTERVAL,
|
||||||
|
max_value=MAX_SHALLOW_TRIGGER_TOOL_CALLS_INTERVAL,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
base["shallow_compress_trigger_tool_calls_interval"] = _sanitize_optional_int(
|
||||||
|
base.get("shallow_compress_trigger_tool_calls_interval"),
|
||||||
|
min_value=MIN_SHALLOW_TRIGGER_TOOL_CALLS_INTERVAL,
|
||||||
|
max_value=MAX_SHALLOW_TRIGGER_TOOL_CALLS_INTERVAL,
|
||||||
|
)
|
||||||
|
|
||||||
# 静默禁用工具提示
|
# 静默禁用工具提示
|
||||||
if "silent_tool_disable" in data:
|
if "silent_tool_disable" in data:
|
||||||
base["silent_tool_disable"] = bool(data.get("silent_tool_disable"))
|
base["silent_tool_disable"] = bool(data.get("silent_tool_disable"))
|
||||||
@ -242,6 +327,7 @@ def save_personalization_config(base_dir: PathLike, payload: Dict[str, Any]) ->
|
|||||||
"""Persist sanitized personalization config and return it."""
|
"""Persist sanitized personalization config and return it."""
|
||||||
existing = load_personalization_config(base_dir)
|
existing = load_personalization_config(base_dir)
|
||||||
config = sanitize_personalization_payload(payload, fallback=existing)
|
config = sanitize_personalization_payload(payload, fallback=existing)
|
||||||
|
validate_context_compression_settings(config)
|
||||||
path = _to_path(base_dir)
|
path = _to_path(base_dir)
|
||||||
_ensure_parent(path)
|
_ensure_parent(path)
|
||||||
with open(path, "w", encoding="utf-8") as f:
|
with open(path, "w", encoding="utf-8") as f:
|
||||||
@ -249,6 +335,78 @@ def save_personalization_config(base_dir: PathLike, payload: Dict[str, Any]) ->
|
|||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
|
def _sanitize_optional_int(value: Any, *, min_value: int, max_value: int) -> Optional[int]:
|
||||||
|
if value is None or value == "":
|
||||||
|
return None
|
||||||
|
if isinstance(value, bool):
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
parsed = int(value)
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return None
|
||||||
|
if parsed < min_value:
|
||||||
|
return min_value
|
||||||
|
if parsed > max_value:
|
||||||
|
return max_value
|
||||||
|
return parsed
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_context_compression_settings(config: Optional[Dict[str, Any]]) -> Dict[str, int]:
|
||||||
|
data = config or {}
|
||||||
|
shallow_trigger = _sanitize_optional_int(
|
||||||
|
data.get("shallow_compress_trigger_tokens"),
|
||||||
|
min_value=MIN_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
max_value=MAX_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
) or DEFAULT_SHALLOW_COMPRESS_TRIGGER_TOKENS
|
||||||
|
shallow_keep_recent = _sanitize_optional_int(
|
||||||
|
data.get("shallow_compress_keep_recent_tools"),
|
||||||
|
min_value=MIN_SHALLOW_KEEP_RECENT_TOOLS,
|
||||||
|
max_value=MAX_SHALLOW_KEEP_RECENT_TOOLS,
|
||||||
|
)
|
||||||
|
if shallow_keep_recent is None:
|
||||||
|
shallow_keep_recent = DEFAULT_SHALLOW_COMPRESS_KEEP_RECENT_TOOLS
|
||||||
|
shallow_max_replace = _sanitize_optional_int(
|
||||||
|
data.get("shallow_compress_max_replace_per_round"),
|
||||||
|
min_value=MIN_SHALLOW_MAX_REPLACE_PER_ROUND,
|
||||||
|
max_value=MAX_SHALLOW_MAX_REPLACE_PER_ROUND,
|
||||||
|
) or DEFAULT_SHALLOW_COMPRESS_MAX_REPLACE_PER_ROUND
|
||||||
|
shallow_trigger_interval = _sanitize_optional_int(
|
||||||
|
data.get("shallow_compress_trigger_tool_calls_interval"),
|
||||||
|
min_value=MIN_SHALLOW_TRIGGER_TOOL_CALLS_INTERVAL,
|
||||||
|
max_value=MAX_SHALLOW_TRIGGER_TOOL_CALLS_INTERVAL,
|
||||||
|
) or DEFAULT_SHALLOW_COMPRESS_TRIGGER_TOOL_CALLS_INTERVAL
|
||||||
|
deep_trigger = _sanitize_optional_int(
|
||||||
|
data.get("deep_compress_trigger_tokens"),
|
||||||
|
min_value=MIN_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
max_value=MAX_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
) or DEFAULT_DEEP_COMPRESS_TRIGGER_TOKENS
|
||||||
|
if deep_trigger <= shallow_trigger:
|
||||||
|
deep_trigger = shallow_trigger + 1
|
||||||
|
return {
|
||||||
|
"shallow_trigger_tokens": shallow_trigger,
|
||||||
|
"shallow_keep_recent_tools": shallow_keep_recent,
|
||||||
|
"shallow_max_replace_per_round": shallow_max_replace,
|
||||||
|
"shallow_trigger_tool_calls_interval": shallow_trigger_interval,
|
||||||
|
"deep_trigger_tokens": deep_trigger,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def validate_context_compression_settings(config: Optional[Dict[str, Any]]) -> None:
|
||||||
|
data = config or {}
|
||||||
|
shallow_trigger = _sanitize_optional_int(
|
||||||
|
data.get("shallow_compress_trigger_tokens"),
|
||||||
|
min_value=MIN_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
max_value=MAX_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
) or DEFAULT_SHALLOW_COMPRESS_TRIGGER_TOKENS
|
||||||
|
deep_trigger = _sanitize_optional_int(
|
||||||
|
data.get("deep_compress_trigger_tokens"),
|
||||||
|
min_value=MIN_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
max_value=MAX_COMPRESSION_TRIGGER_TOKENS,
|
||||||
|
) or DEFAULT_DEEP_COMPRESS_TRIGGER_TOKENS
|
||||||
|
if deep_trigger <= shallow_trigger:
|
||||||
|
raise ValueError("深压缩触发上下文必须大于浅压缩触发上下文")
|
||||||
|
|
||||||
|
|
||||||
def build_personalization_prompt(
|
def build_personalization_prompt(
|
||||||
config: Optional[Dict[str, Any]],
|
config: Optional[Dict[str, Any]],
|
||||||
include_header: bool = True
|
include_header: bool = True
|
||||||
|
|||||||
@ -38,6 +38,7 @@ from modules.personalization_manager import (
|
|||||||
save_personalization_config,
|
save_personalization_config,
|
||||||
THINKING_INTERVAL_MIN,
|
THINKING_INTERVAL_MIN,
|
||||||
THINKING_INTERVAL_MAX,
|
THINKING_INTERVAL_MAX,
|
||||||
|
resolve_context_compression_settings,
|
||||||
)
|
)
|
||||||
from modules.skill_hint_manager import SkillHintManager
|
from modules.skill_hint_manager import SkillHintManager
|
||||||
from modules.upload_security import UploadSecurityError
|
from modules.upload_security import UploadSecurityError
|
||||||
@ -566,11 +567,12 @@ async def handle_task_with_sender(terminal: WebTerminal, workspace: UserWorkspac
|
|||||||
personal_config = load_personalization_config(workspace.data_dir)
|
personal_config = load_personalization_config(workspace.data_dir)
|
||||||
except Exception:
|
except Exception:
|
||||||
personal_config = {}
|
personal_config = {}
|
||||||
|
compression_settings = resolve_context_compression_settings(personal_config)
|
||||||
auto_deep_enabled = bool(personal_config.get("auto_deep_compress_enabled", False))
|
auto_deep_enabled = bool(personal_config.get("auto_deep_compress_enabled", False))
|
||||||
current_tokens_for_deep = web_terminal.context_manager.get_current_context_tokens(conversation_id)
|
current_tokens_for_deep = web_terminal.context_manager.get_current_context_tokens(conversation_id)
|
||||||
if (
|
if (
|
||||||
auto_deep_enabled
|
auto_deep_enabled
|
||||||
and current_tokens_for_deep > 150_000
|
and current_tokens_for_deep > compression_settings["deep_trigger_tokens"]
|
||||||
and not web_terminal.context_manager.is_compression_in_progress()
|
and not web_terminal.context_manager.is_compression_in_progress()
|
||||||
):
|
):
|
||||||
web_terminal.context_manager._set_meta_flag("is_ultra_long_conversation", True)
|
web_terminal.context_manager._set_meta_flag("is_ultra_long_conversation", True)
|
||||||
|
|||||||
@ -12,8 +12,9 @@ from .security import compact_web_search_result
|
|||||||
from .chat_flow_helpers import detect_tool_failure
|
from .chat_flow_helpers import detect_tool_failure
|
||||||
from .chat_flow_runner_helpers import resolve_monitor_path, resolve_monitor_memory, capture_monitor_snapshot
|
from .chat_flow_runner_helpers import resolve_monitor_path, resolve_monitor_memory, capture_monitor_snapshot
|
||||||
from utils.tool_result_formatter import format_tool_result_for_context
|
from utils.tool_result_formatter import format_tool_result_for_context
|
||||||
|
from utils.context_manager import AUTO_SHALLOW_PLACEHOLDER
|
||||||
from config import TOOL_CALL_COOLDOWN
|
from config import TOOL_CALL_COOLDOWN
|
||||||
from modules.personalization_manager import load_personalization_config
|
from modules.personalization_manager import load_personalization_config, resolve_context_compression_settings
|
||||||
from .deep_compression import run_deep_compression
|
from .deep_compression import run_deep_compression
|
||||||
|
|
||||||
|
|
||||||
@ -457,12 +458,21 @@ async def execute_tool_calls(*, web_terminal, tool_calls, sender, messages, clie
|
|||||||
personal_config = load_personalization_config(workspace_data_dir) if workspace_data_dir else {}
|
personal_config = load_personalization_config(workspace_data_dir) if workspace_data_dir else {}
|
||||||
except Exception:
|
except Exception:
|
||||||
personal_config = {}
|
personal_config = {}
|
||||||
|
compression_settings = resolve_context_compression_settings(personal_config)
|
||||||
auto_shallow_enabled = bool(personal_config.get("auto_shallow_compress_enabled", False))
|
auto_shallow_enabled = bool(personal_config.get("auto_shallow_compress_enabled", False))
|
||||||
auto_deep_enabled = bool(personal_config.get("auto_deep_compress_enabled", False))
|
auto_deep_enabled = bool(personal_config.get("auto_deep_compress_enabled", False))
|
||||||
compressed_count = 0
|
compressed_count = 0
|
||||||
try:
|
try:
|
||||||
compressed_count = int(
|
compressed_count = int(
|
||||||
web_terminal.context_manager.on_tool_call_finished(function_name, enable_shallow=auto_shallow_enabled) or 0
|
web_terminal.context_manager.on_tool_call_finished(
|
||||||
|
function_name,
|
||||||
|
enable_shallow=auto_shallow_enabled,
|
||||||
|
shallow_trigger_tokens=compression_settings["shallow_trigger_tokens"],
|
||||||
|
deep_trigger_tokens=compression_settings["deep_trigger_tokens"],
|
||||||
|
shallow_batch_size=compression_settings["shallow_max_replace_per_round"],
|
||||||
|
shallow_keep_recent_tools=compression_settings["shallow_keep_recent_tools"],
|
||||||
|
shallow_trigger_tool_calls_interval=compression_settings["shallow_trigger_tool_calls_interval"],
|
||||||
|
) or 0
|
||||||
)
|
)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
debug_log(f"[ContextCompression] 工具后浅压缩检测失败: {exc}")
|
debug_log(f"[ContextCompression] 工具后浅压缩检测失败: {exc}")
|
||||||
@ -470,8 +480,34 @@ async def execute_tool_calls(*, web_terminal, tool_calls, sender, messages, clie
|
|||||||
sender('shallow_compression', {
|
sender('shallow_compression', {
|
||||||
"conversation_id": conversation_id,
|
"conversation_id": conversation_id,
|
||||||
"compressed_count": compressed_count,
|
"compressed_count": compressed_count,
|
||||||
"keep_recent_tools": 15,
|
"keep_recent_tools": compression_settings["shallow_keep_recent_tools"],
|
||||||
})
|
})
|
||||||
|
# 关键修复:同一轮工具循环里,API 继续调用使用的是本地 messages(不是每次重建上下文),
|
||||||
|
# 因此需要把已打标的旧 tool 结果同步替换为占位符,避免日志看起来“弹窗触发但请求未替换”。
|
||||||
|
if auto_shallow_enabled and messages:
|
||||||
|
try:
|
||||||
|
marked_keys = set()
|
||||||
|
for item in (web_terminal.context_manager.conversation_history or []):
|
||||||
|
if not isinstance(item, dict) or item.get("role") != "tool":
|
||||||
|
continue
|
||||||
|
item_meta = item.get("metadata") or {}
|
||||||
|
if not item_meta.get("auto_shallow_compacted"):
|
||||||
|
continue
|
||||||
|
marked_keys.add((str(item.get("tool_call_id") or ""), str(item.get("name") or "")))
|
||||||
|
|
||||||
|
if marked_keys:
|
||||||
|
replaced_in_loop = 0
|
||||||
|
for msg in messages:
|
||||||
|
if not isinstance(msg, dict) or msg.get("role") != "tool":
|
||||||
|
continue
|
||||||
|
key = (str(msg.get("tool_call_id") or ""), str(msg.get("name") or ""))
|
||||||
|
if key in marked_keys and msg.get("content") != AUTO_SHALLOW_PLACEHOLDER:
|
||||||
|
msg["content"] = AUTO_SHALLOW_PLACEHOLDER
|
||||||
|
replaced_in_loop += 1
|
||||||
|
if replaced_in_loop > 0:
|
||||||
|
debug_log(f"[ContextCompression] 同步替换本轮 messages 中已压缩 tool 结果: {replaced_in_loop}")
|
||||||
|
except Exception as exc:
|
||||||
|
debug_log(f"[ContextCompression] 同步替换本轮 messages 失败: {exc}")
|
||||||
debug_log(f"💾 增量保存:工具结果 {function_name}")
|
debug_log(f"💾 增量保存:工具结果 {function_name}")
|
||||||
if function_name != "wait_sub_agent":
|
if function_name != "wait_sub_agent":
|
||||||
system_message = result_data.get("system_message") if isinstance(result_data, dict) else None
|
system_message = result_data.get("system_message") if isinstance(result_data, dict) else None
|
||||||
@ -483,7 +519,7 @@ async def execute_tool_calls(*, web_terminal, tool_calls, sender, messages, clie
|
|||||||
current_context_tokens = web_terminal.context_manager.get_current_context_tokens(conversation_id)
|
current_context_tokens = web_terminal.context_manager.get_current_context_tokens(conversation_id)
|
||||||
if (
|
if (
|
||||||
auto_deep_enabled
|
auto_deep_enabled
|
||||||
and current_context_tokens > 150_000
|
and current_context_tokens > compression_settings["deep_trigger_tokens"]
|
||||||
and not web_terminal.context_manager.is_compression_in_progress()
|
and not web_terminal.context_manager.is_compression_in_progress()
|
||||||
):
|
):
|
||||||
web_terminal.context_manager._set_meta_flag("is_ultra_long_conversation", True)
|
web_terminal.context_manager._set_meta_flag("is_ultra_long_conversation", True)
|
||||||
|
|||||||
@ -250,7 +250,7 @@
|
|||||||
:tool-settings="toolSettings"
|
:tool-settings="toolSettings"
|
||||||
:tool-settings-loading="toolSettingsLoading"
|
:tool-settings-loading="toolSettingsLoading"
|
||||||
:settings-open="settingsOpen"
|
:settings-open="settingsOpen"
|
||||||
:compressing="compressing"
|
:compressing="compressing || compressionInProgress"
|
||||||
:current-conversation-id="currentConversationId"
|
:current-conversation-id="currentConversationId"
|
||||||
:icon-style="iconStyle"
|
:icon-style="iconStyle"
|
||||||
:tool-category-icon="toolCategoryIcon"
|
:tool-category-icon="toolCategoryIcon"
|
||||||
|
|||||||
@ -51,7 +51,12 @@ export const taskPollingMethods = {
|
|||||||
|
|
||||||
// 检查事件的 conversation_id 是否匹配当前对话
|
// 检查事件的 conversation_id 是否匹配当前对话
|
||||||
// 如果不匹配,忽略该事件(避免切换对话后旧任务的事件显示到新对话中)
|
// 如果不匹配,忽略该事件(避免切换对话后旧任务的事件显示到新对话中)
|
||||||
if (eventType !== 'shallow_compression' && eventData.conversation_id && this.currentConversationId) {
|
const crossConversationAllowed = new Set([
|
||||||
|
'shallow_compression',
|
||||||
|
'conversation_resolved',
|
||||||
|
'compression_finished'
|
||||||
|
]);
|
||||||
|
if (!crossConversationAllowed.has(eventType) && eventData.conversation_id && this.currentConversationId) {
|
||||||
if (eventData.conversation_id !== this.currentConversationId) {
|
if (eventData.conversation_id !== this.currentConversationId) {
|
||||||
console.log(`[DEBUG_AWAITING] 忽略不匹配的事件`, {
|
console.log(`[DEBUG_AWAITING] 忽略不匹配的事件`, {
|
||||||
eventType,
|
eventType,
|
||||||
@ -935,9 +940,19 @@ export const taskPollingMethods = {
|
|||||||
if (!data || typeof data !== 'object') {
|
if (!data || typeof data !== 'object') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const wasInProgress = !!this.compressionInProgress;
|
||||||
this.compressionInProgress = !!data.in_progress;
|
this.compressionInProgress = !!data.in_progress;
|
||||||
this.compressionMode = data.mode || '';
|
this.compressionMode = data.mode || '';
|
||||||
this.compressionStage = data.stage || '';
|
this.compressionStage = data.stage || '';
|
||||||
|
if (this.compressionInProgress && !wasInProgress) {
|
||||||
|
const modeLabel = this.compressionMode === 'manual' ? '手动' : '自动';
|
||||||
|
this.uiPushToast({
|
||||||
|
title: '压缩中',
|
||||||
|
message: `对话正在${modeLabel}压缩,请稍候…`,
|
||||||
|
type: 'info',
|
||||||
|
duration: 2600
|
||||||
|
});
|
||||||
|
}
|
||||||
if (!this.compressionInProgress) {
|
if (!this.compressionInProgress) {
|
||||||
this.compressionError = data.error || '';
|
this.compressionError = data.error || '';
|
||||||
}
|
}
|
||||||
@ -952,6 +967,16 @@ export const taskPollingMethods = {
|
|||||||
if (newId && newId !== this.currentConversationId) {
|
if (newId && newId !== this.currentConversationId) {
|
||||||
await this.loadConversation(newId, { force: true });
|
await this.loadConversation(newId, { force: true });
|
||||||
}
|
}
|
||||||
|
this.conversationsOffset = 0;
|
||||||
|
if (typeof this.loadConversationsList === 'function') {
|
||||||
|
await this.loadConversationsList();
|
||||||
|
}
|
||||||
|
this.uiPushToast({
|
||||||
|
title: '压缩完成',
|
||||||
|
message: '已自动切换到压缩后的新对话',
|
||||||
|
type: 'success',
|
||||||
|
duration: 2400
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
handleShallowCompression(data: any, eventIdx?: number) {
|
handleShallowCompression(data: any, eventIdx?: number) {
|
||||||
|
|||||||
@ -522,6 +522,76 @@
|
|||||||
</span>
|
</span>
|
||||||
<span>自动深层压缩</span>
|
<span>自动深层压缩</span>
|
||||||
</label>
|
</label>
|
||||||
|
<div class="compression-custom-grid">
|
||||||
|
<label class="compression-input-row">
|
||||||
|
<span>浅压缩触发上下文</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min="1000"
|
||||||
|
step="1"
|
||||||
|
placeholder="默认 80000"
|
||||||
|
:value="form.shallow_compress_trigger_tokens ?? ''"
|
||||||
|
@input="handleCompressionNumberInput('shallow_compress_trigger_tokens', $event)"
|
||||||
|
@focus="personalization.clearFeedback()"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label class="compression-input-row">
|
||||||
|
<span>浅压缩保留最近 Tool 条数</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
step="1"
|
||||||
|
placeholder="默认 15"
|
||||||
|
:value="form.shallow_compress_keep_recent_tools ?? ''"
|
||||||
|
@input="handleCompressionNumberInput('shallow_compress_keep_recent_tools', $event)"
|
||||||
|
@focus="personalization.clearFeedback()"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label class="compression-input-row">
|
||||||
|
<span>浅压缩每轮最多替换条数</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
step="1"
|
||||||
|
placeholder="默认 10"
|
||||||
|
:value="form.shallow_compress_max_replace_per_round ?? ''"
|
||||||
|
@input="handleCompressionNumberInput('shallow_compress_max_replace_per_round', $event)"
|
||||||
|
@focus="personalization.clearFeedback()"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label class="compression-input-row">
|
||||||
|
<span>浅压缩触发间隔(Tool 调用次数)</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
step="1"
|
||||||
|
placeholder="默认 10"
|
||||||
|
:value="form.shallow_compress_trigger_tool_calls_interval ?? ''"
|
||||||
|
@input="handleCompressionNumberInput('shallow_compress_trigger_tool_calls_interval', $event)"
|
||||||
|
@focus="personalization.clearFeedback()"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label class="compression-input-row">
|
||||||
|
<span>深压缩触发上下文</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min="1000"
|
||||||
|
step="1"
|
||||||
|
placeholder="默认 150000"
|
||||||
|
:value="form.deep_compress_trigger_tokens ?? ''"
|
||||||
|
@input="handleCompressionNumberInput('deep_compress_trigger_tokens', $event)"
|
||||||
|
@focus="personalization.clearFeedback()"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="compression-actions-row">
|
||||||
|
<button type="button" class="compression-reset-btn" @click.prevent="restoreCompressionDefaults">
|
||||||
|
恢复默认
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p class="field-desc compression-custom-hint">
|
||||||
|
自定义项留空则使用默认值;深压缩触发上下文必须大于浅压缩触发上下文。
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="behavior-field">
|
<div class="behavior-field">
|
||||||
<div class="behavior-field-header">
|
<div class="behavior-field-header">
|
||||||
@ -939,6 +1009,12 @@ const activeTab = ref<PersonalTab>('preferences');
|
|||||||
const swipeState = ref<{ startY: number; active: boolean }>({ startY: 0, active: false });
|
const swipeState = ref<{ startY: number; active: boolean }>({ startY: 0, active: false });
|
||||||
|
|
||||||
type RunModeValue = 'fast' | 'thinking' | 'deep' | null;
|
type RunModeValue = 'fast' | 'thinking' | 'deep' | null;
|
||||||
|
type CompressionField =
|
||||||
|
| 'shallow_compress_trigger_tokens'
|
||||||
|
| 'shallow_compress_keep_recent_tools'
|
||||||
|
| 'shallow_compress_max_replace_per_round'
|
||||||
|
| 'shallow_compress_trigger_tool_calls_interval'
|
||||||
|
| 'deep_compress_trigger_tokens';
|
||||||
|
|
||||||
const runModeOptions: Array<{ id: string; label: string; desc: string; value: RunModeValue; badge?: string }> = [
|
const runModeOptions: Array<{ id: string; label: string; desc: string; value: RunModeValue; badge?: string }> = [
|
||||||
{ id: 'fast', label: '快速模式', desc: '追求响应速度,跳过思考模型', value: 'fast' },
|
{ id: 'fast', label: '快速模式', desc: '追求响应速度,跳过思考模型', value: 'fast' },
|
||||||
@ -1289,6 +1365,28 @@ const restoreThinkingInterval = () => {
|
|||||||
personalization.setThinkingInterval(null);
|
personalization.setThinkingInterval(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCompressionNumberInput = (key: CompressionField, event: Event) => {
|
||||||
|
const target = event.target as HTMLInputElement | null;
|
||||||
|
if (!target || !target.value) {
|
||||||
|
personalization.updateField({ key, value: null });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const parsed = Number(target.value);
|
||||||
|
if (!Number.isFinite(parsed)) {
|
||||||
|
personalization.updateField({ key, value: null });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
personalization.updateField({ key, value: Math.round(parsed) });
|
||||||
|
};
|
||||||
|
|
||||||
|
const restoreCompressionDefaults = () => {
|
||||||
|
personalization.updateField({ key: 'shallow_compress_trigger_tokens', value: null });
|
||||||
|
personalization.updateField({ key: 'shallow_compress_keep_recent_tools', value: null });
|
||||||
|
personalization.updateField({ key: 'shallow_compress_max_replace_per_round', value: null });
|
||||||
|
personalization.updateField({ key: 'shallow_compress_trigger_tool_calls_interval', value: null });
|
||||||
|
personalization.updateField({ key: 'deep_compress_trigger_tokens', value: null });
|
||||||
|
};
|
||||||
|
|
||||||
const isPresetActive = (value: number) => {
|
const isPresetActive = (value: number) => {
|
||||||
if (form.value.thinking_interval === null || typeof form.value.thinking_interval === 'undefined') {
|
if (form.value.thinking_interval === null || typeof form.value.thinking_interval === 'undefined') {
|
||||||
return value === thinkingIntervalDefault.value;
|
return value === thinkingIntervalDefault.value;
|
||||||
@ -1362,6 +1460,55 @@ const applyThemeOption = (theme: ThemeKey) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.compression-custom-grid {
|
||||||
|
margin-top: 10px;
|
||||||
|
display: grid;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compression-input-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
color: var(--claude-text-secondary);
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compression-input-row input {
|
||||||
|
border: 1px solid var(--claude-border);
|
||||||
|
border-radius: 10px;
|
||||||
|
background: var(--claude-panel);
|
||||||
|
color: var(--claude-text);
|
||||||
|
padding: 8px 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compression-custom-hint {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compression-actions-row {
|
||||||
|
margin-top: 4px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compression-reset-btn {
|
||||||
|
border: 1px solid var(--claude-border);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
background: var(--claude-panel);
|
||||||
|
color: var(--claude-text);
|
||||||
|
font-size: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.18s ease, box-shadow 0.18s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compression-reset-btn:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 8px 18px rgba(61, 57, 41, 0.14);
|
||||||
|
}
|
||||||
|
|
||||||
.usage-summary-page {
|
.usage-summary-page {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@ -24,6 +24,11 @@ interface PersonalForm {
|
|||||||
image_compression: string;
|
image_compression: string;
|
||||||
auto_shallow_compress_enabled: boolean;
|
auto_shallow_compress_enabled: boolean;
|
||||||
auto_deep_compress_enabled: boolean;
|
auto_deep_compress_enabled: boolean;
|
||||||
|
shallow_compress_trigger_tokens: number | null;
|
||||||
|
shallow_compress_keep_recent_tools: number | null;
|
||||||
|
shallow_compress_max_replace_per_round: number | null;
|
||||||
|
shallow_compress_trigger_tool_calls_interval: number | null;
|
||||||
|
deep_compress_trigger_tokens: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LiquidGlassPosition {
|
interface LiquidGlassPosition {
|
||||||
@ -60,6 +65,8 @@ interface PersonalizationState {
|
|||||||
|
|
||||||
const DEFAULT_INTERVAL = 10;
|
const DEFAULT_INTERVAL = 10;
|
||||||
const DEFAULT_INTERVAL_RANGE = { min: 1, max: 50 };
|
const DEFAULT_INTERVAL_RANGE = { min: 1, max: 50 };
|
||||||
|
const DEFAULT_SHALLOW_COMPRESS_TRIGGER_TOKENS = 80000;
|
||||||
|
const DEFAULT_DEEP_COMPRESS_TRIGGER_TOKENS = 150000;
|
||||||
const RUN_MODE_OPTIONS: RunMode[] = ['fast', 'thinking', 'deep'];
|
const RUN_MODE_OPTIONS: RunMode[] = ['fast', 'thinking', 'deep'];
|
||||||
const EXPERIMENT_STORAGE_KEY = 'agents_personalization_experiments';
|
const EXPERIMENT_STORAGE_KEY = 'agents_personalization_experiments';
|
||||||
|
|
||||||
@ -83,7 +90,12 @@ const defaultForm = (): PersonalForm => ({
|
|||||||
default_model: 'kimi-k2.5',
|
default_model: 'kimi-k2.5',
|
||||||
image_compression: 'original',
|
image_compression: 'original',
|
||||||
auto_shallow_compress_enabled: false,
|
auto_shallow_compress_enabled: false,
|
||||||
auto_deep_compress_enabled: false
|
auto_deep_compress_enabled: false,
|
||||||
|
shallow_compress_trigger_tokens: null,
|
||||||
|
shallow_compress_keep_recent_tools: null,
|
||||||
|
shallow_compress_max_replace_per_round: null,
|
||||||
|
shallow_compress_trigger_tool_calls_interval: null,
|
||||||
|
deep_compress_trigger_tokens: null
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultExperimentState = (): ExperimentState => ({
|
const defaultExperimentState = (): ExperimentState => ({
|
||||||
@ -234,10 +246,29 @@ export const usePersonalizationStore = defineStore('personalization', {
|
|||||||
default_model: typeof data.default_model === 'string' ? data.default_model : fallbackModel,
|
default_model: typeof data.default_model === 'string' ? data.default_model : fallbackModel,
|
||||||
image_compression: typeof data.image_compression === 'string' ? data.image_compression : 'original',
|
image_compression: typeof data.image_compression === 'string' ? data.image_compression : 'original',
|
||||||
auto_shallow_compress_enabled: !!data.auto_shallow_compress_enabled,
|
auto_shallow_compress_enabled: !!data.auto_shallow_compress_enabled,
|
||||||
auto_deep_compress_enabled: !!data.auto_deep_compress_enabled
|
auto_deep_compress_enabled: !!data.auto_deep_compress_enabled,
|
||||||
|
shallow_compress_trigger_tokens: this.normalizeCompressionNumber(data.shallow_compress_trigger_tokens),
|
||||||
|
shallow_compress_keep_recent_tools: this.normalizeCompressionNumber(data.shallow_compress_keep_recent_tools),
|
||||||
|
shallow_compress_max_replace_per_round: this.normalizeCompressionNumber(data.shallow_compress_max_replace_per_round),
|
||||||
|
shallow_compress_trigger_tool_calls_interval: this.normalizeCompressionNumber(data.shallow_compress_trigger_tool_calls_interval),
|
||||||
|
deep_compress_trigger_tokens: this.normalizeCompressionNumber(data.deep_compress_trigger_tokens)
|
||||||
};
|
};
|
||||||
this.clearFeedback();
|
this.clearFeedback();
|
||||||
},
|
},
|
||||||
|
normalizeCompressionNumber(value: any): number | null {
|
||||||
|
if (value === null || typeof value === 'undefined' || value === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const parsed = Number(value);
|
||||||
|
if (!Number.isFinite(parsed)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const rounded = Math.round(parsed);
|
||||||
|
if (rounded <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return rounded;
|
||||||
|
},
|
||||||
applyPersonalizationMeta(payload: any) {
|
applyPersonalizationMeta(payload: any) {
|
||||||
if (payload && typeof payload.thinking_interval_default === 'number') {
|
if (payload && typeof payload.thinking_interval_default === 'number') {
|
||||||
this.thinkingIntervalDefault = payload.thinking_interval_default;
|
this.thinkingIntervalDefault = payload.thinking_interval_default;
|
||||||
@ -325,6 +356,13 @@ export const usePersonalizationStore = defineStore('personalization', {
|
|||||||
this.status = '';
|
this.status = '';
|
||||||
this.error = '';
|
this.error = '';
|
||||||
try {
|
try {
|
||||||
|
const shallowTrigger =
|
||||||
|
this.normalizeCompressionNumber(this.form.shallow_compress_trigger_tokens) ?? DEFAULT_SHALLOW_COMPRESS_TRIGGER_TOKENS;
|
||||||
|
const deepTrigger =
|
||||||
|
this.normalizeCompressionNumber(this.form.deep_compress_trigger_tokens) ?? DEFAULT_DEEP_COMPRESS_TRIGGER_TOKENS;
|
||||||
|
if (deepTrigger <= shallowTrigger) {
|
||||||
|
throw new Error('深压缩触发上下文必须大于浅压缩触发上下文');
|
||||||
|
}
|
||||||
const resp = await fetch('/api/personalization', {
|
const resp = await fetch('/api/personalization', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
|||||||
@ -544,7 +544,17 @@ class ContextManager:
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print(f"[ContextCompression] 更新压缩状态失败: {exc}")
|
print(f"[ContextCompression] 更新压缩状态失败: {exc}")
|
||||||
|
|
||||||
def on_tool_call_finished(self, tool_name: Optional[str] = None, *, enable_shallow: bool = True) -> int:
|
def on_tool_call_finished(
|
||||||
|
self,
|
||||||
|
tool_name: Optional[str] = None,
|
||||||
|
*,
|
||||||
|
enable_shallow: bool = True,
|
||||||
|
shallow_trigger_tokens: int = 80_000,
|
||||||
|
deep_trigger_tokens: int = 150_000,
|
||||||
|
shallow_batch_size: int = 10,
|
||||||
|
shallow_keep_recent_tools: int = 15,
|
||||||
|
shallow_trigger_tool_calls_interval: int = 10,
|
||||||
|
) -> int:
|
||||||
"""每次工具调用完成后触发:更新计数并执行自动浅压缩。返回本轮浅压缩条数。"""
|
"""每次工具调用完成后触发:更新计数并执行自动浅压缩。返回本轮浅压缩条数。"""
|
||||||
if not self.current_conversation_id:
|
if not self.current_conversation_id:
|
||||||
return 0
|
return 0
|
||||||
@ -563,9 +573,22 @@ class ContextManager:
|
|||||||
self._set_meta_flag("tool_call_count", tool_count, save=False)
|
self._set_meta_flag("tool_call_count", tool_count, save=False)
|
||||||
|
|
||||||
current_tokens = self.get_current_context_tokens(self.current_conversation_id)
|
current_tokens = self.get_current_context_tokens(self.current_conversation_id)
|
||||||
if current_tokens > 80_000 and not self._get_meta_flag("is_long_conversation", False):
|
shallow_trigger_tokens = max(1, int(80_000 if shallow_trigger_tokens is None else shallow_trigger_tokens))
|
||||||
|
deep_trigger_tokens = max(
|
||||||
|
shallow_trigger_tokens + 1,
|
||||||
|
int(150_000 if deep_trigger_tokens is None else deep_trigger_tokens),
|
||||||
|
)
|
||||||
|
shallow_batch_size = max(1, int(10 if shallow_batch_size is None else shallow_batch_size))
|
||||||
|
shallow_keep_recent_tools = max(0, int(15 if shallow_keep_recent_tools is None else shallow_keep_recent_tools))
|
||||||
|
shallow_trigger_tool_calls_interval = max(
|
||||||
|
1,
|
||||||
|
int(10 if shallow_trigger_tool_calls_interval is None else shallow_trigger_tool_calls_interval),
|
||||||
|
)
|
||||||
|
was_long_conversation = bool(self._get_meta_flag("is_long_conversation", False))
|
||||||
|
if current_tokens > shallow_trigger_tokens and not was_long_conversation:
|
||||||
self._set_meta_flag("is_long_conversation", True, save=False)
|
self._set_meta_flag("is_long_conversation", True, save=False)
|
||||||
if current_tokens > 150_000 and not self._get_meta_flag("is_ultra_long_conversation", False):
|
just_marked_long = (not was_long_conversation) and bool(self._get_meta_flag("is_long_conversation", False))
|
||||||
|
if current_tokens > deep_trigger_tokens and not self._get_meta_flag("is_ultra_long_conversation", False):
|
||||||
self._set_meta_flag("is_ultra_long_conversation", True, save=False)
|
self._set_meta_flag("is_ultra_long_conversation", True, save=False)
|
||||||
|
|
||||||
# 每 10 次工具调用触发一次浅压缩(当 long 已标记)
|
# 每 10 次工具调用触发一次浅压缩(当 long 已标记)
|
||||||
@ -573,12 +596,19 @@ class ContextManager:
|
|||||||
should_try_shallow = (
|
should_try_shallow = (
|
||||||
bool(enable_shallow)
|
bool(enable_shallow)
|
||||||
and bool(self._get_meta_flag("is_long_conversation", False))
|
and bool(self._get_meta_flag("is_long_conversation", False))
|
||||||
and (tool_count - last_checkpoint >= 10)
|
and (
|
||||||
|
just_marked_long
|
||||||
|
or (last_checkpoint <= 0 and tool_count > 0)
|
||||||
|
or (tool_count - last_checkpoint >= shallow_trigger_tool_calls_interval)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
changed = False
|
changed = False
|
||||||
compressed_count = 0
|
compressed_count = 0
|
||||||
if should_try_shallow:
|
if should_try_shallow:
|
||||||
compressed = self._run_auto_shallow_compression(batch_size=10, keep_recent_tools=15)
|
compressed = self._run_auto_shallow_compression(
|
||||||
|
batch_size=shallow_batch_size,
|
||||||
|
keep_recent_tools=shallow_keep_recent_tools,
|
||||||
|
)
|
||||||
self._set_meta_flag("last_shallow_compress_tool_count", tool_count, save=False)
|
self._set_meta_flag("last_shallow_compress_tool_count", tool_count, save=False)
|
||||||
compressed_count = max(0, int(compressed or 0))
|
compressed_count = max(0, int(compressed or 0))
|
||||||
changed = compressed > 0
|
changed = compressed > 0
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user