Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 46 additions & 3 deletions astrbot/core/agent/context/manager.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from astrbot import logger
from astrbot.core.platform.astr_message_event import AstrMessageEvent

from ..message import Message
from .compressor import LLMSummaryCompressor, TruncateByTurnsCompressor
Expand Down Expand Up @@ -42,12 +43,17 @@ def __init__(
)

async def process(
self, messages: list[Message], trusted_token_usage: int = 0
self,
messages: list[Message],
trusted_token_usage: int = 0,
event: AstrMessageEvent | None = None,
) -> list[Message]:
"""Process the messages.

Args:
messages: The original message list.
trusted_token_usage: Trusted token usage from conversation.
event: Optional event for triggering hooks.

Returns:
The processed message list.
Expand All @@ -72,28 +78,47 @@ async def process(
if self.compressor.should_compress(
result, total_tokens, self.config.max_context_tokens
):
result = await self._run_compression(result, total_tokens)
result = await self._run_compression(result, total_tokens, event)

return result
except Exception as e:
logger.error(f"Error during context processing: {e}", exc_info=True)
return messages

async def _run_compression(
self, messages: list[Message], prev_tokens: int
self,
messages: list[Message],
prev_tokens: int,
event: AstrMessageEvent | None = None,
) -> list[Message]:
"""
Compress/truncate the messages.

Args:
messages: The original message list.
prev_tokens: The token count before compression.
event: Optional event for triggering hooks.

Returns:
The compressed/truncated message list.
"""
logger.debug("Compress triggered, starting compression...")

# Trigger before compression hook
if event:
try:
from astrbot.core.pipeline.context_utils import call_event_hook
from astrbot.core.star.star_handler import EventType

await call_event_hook(
event,
EventType.OnBeforeContextCompressionEvent,
messages,
prev_tokens,
)
except Exception as e:
logger.warning(f"Hook OnBeforeContextCompressionEvent failed: {e}")

messages = await self.compressor(messages)

# double check
Expand All @@ -117,4 +142,22 @@ async def _run_compression(
# still need compress, truncate by half
messages = self.truncator.truncate_by_halving(messages)

# Recalculate token count after all truncation steps
final_tokens = self.token_counter.count_tokens(messages)

# Trigger after compression hook
if event:
try:
from astrbot.core.pipeline.context_utils import call_event_hook
from astrbot.core.star.star_handler import EventType

await call_event_hook(
event,
EventType.OnAfterContextCompressionEvent,
messages,
final_tokens,
)
except Exception as e:
logger.warning(f"Hook OnAfterContextCompressionEvent failed: {e}")

return messages
3 changes: 2 additions & 1 deletion astrbot/core/agent/runners/tool_loop_agent_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,9 @@ async def step(self):
# do truncate and compress
token_usage = self.req.conversation.token_usage if self.req.conversation else 0
self._simple_print_message_role("[BefCompact]")
event = getattr(self.run_context.context, "event", None)
self.run_context.messages = await self.context_manager.process(
self.run_context.messages, trusted_token_usage=token_usage
self.run_context.messages, trusted_token_usage=token_usage, event=event
)
self._simple_print_message_role("[AftCompact]")

Expand Down
2 changes: 2 additions & 0 deletions astrbot/core/star/star_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ class EventType(enum.Enum):
OnLLMToolRespondEvent = enum.auto() # 调用函数工具后
OnAfterMessageSentEvent = enum.auto() # 发送消息后
OnPluginErrorEvent = enum.auto() # 插件处理消息异常时
OnBeforeContextCompressionEvent = enum.auto() # 上下文压缩前事件
OnAfterContextCompressionEvent = enum.auto() # 上下文压缩后事件


H = TypeVar("H", bound=Callable[..., Any])
Expand Down