mirror of
https://github.com/agentscope-ai/ReMe.git
synced 2026-09-16 23:41:10 +00:00
* style(memory): update message formatting and improve logging - Change default include_thinking parameter to True in as_msg_handler.py - Replace angle brackets with square brackets for block formatting in as_msg_stat.py - Add newline replacement in text truncation method in as_msg_stat.py - Add loading duration timing to embedding cache loading in base_embedding_model.py - Replace XML-style tags with markdown headers in compactor.py conversation format - Update compactor.yaml prompts to reference markdown-style headers instead of XML tags - Modify summarizer.py to use markdown-style conversation header format * refactor(file-watcher): replace scan_on_start with rebuild_index_on_start parameter - Replace scan_on_start and clear_on_start boolean parameters with single rebuild_index_on_start - Update BaseFileWatcher constructor to use rebuild_index_on_start instead of two separate flags - Modify initialization logic to clear and rescan when rebuild_index_on_start is True - Remove scan_on_start parameter from CLI and light configuration files - Update documentation to remove scan_on_start from quick start guides - Rename all test methods and classes from scan_on_start to rebuild_index_on_start - Add timezone-aware datetime helper method to summarizer component - Format log message with proper line breaks for readability * fix(core): resolve file watcher initialization issue and update version - Fixed file watcher task creation to properly handle rebuild index on start logic - Moved initialization and watch loop into async function to ensure proper execution order - Updated package version from 0.3.1.1 to 0.3.1.2 - Added missing comma in embedding model logging statement * fix(core): reduce max formatter text length limit - Changed _DEFAULT_MAX_FORMATTER_TEXT_LENGTH from 2000 to 1000 - Updated constant value in as_msg_stat.py schema module * fix(file-watcher): change default rebuild index behavior on start - Changed rebuild_index_on_start parameter default from False to True - This ensures index is rebuilt by default when file watcher starts - Maintains consistent state initialization for file watching operations * feat(compactor): add return_dict option and improve summary validation - Add _is_valid_summary function to validate summary content format - Introduce return_dict parameter to return structured results with validation - Update prompt templates with clearer task descriptions and formatting rules - Refactor update_user_message prompts to combine prefix and suffix logic - Return dictionary with user_message, history_compact, and is_valid fields when enabled - Add proper error handling for exception cases in memory compaction - Maintain backward compatibility with string return when return_dict=False * feat(memory): add thinking block configuration option - Add add_thinking_block parameter to compactor component - Pass include_thinking flag to message formatting in compactor - Add add_thinking_block parameter to reme_light compact function - Add add_thinking_block parameter to reme_light summarize function - Add add_thinking_block parameter to summarizer component - Pass include_thinking flag to message formatting in summarizer - Remove previous-summary tags from compressed summary format
110 lines
3.8 KiB
Python
110 lines
3.8 KiB
Python
"""Compactor module for memory compaction operations."""
|
|
|
|
from agentscope.agent import ReActAgent
|
|
from agentscope.message import Msg
|
|
|
|
from ..utils import AsMsgHandler
|
|
from ....core.op import BaseOp
|
|
from ....core.utils import get_logger
|
|
|
|
logger = get_logger()
|
|
|
|
|
|
def _is_valid_summary(content: str) -> bool:
|
|
"""Check if the summary content is valid.
|
|
|
|
Args:
|
|
content: The summary content to validate.
|
|
|
|
Returns:
|
|
True if valid, False otherwise.
|
|
"""
|
|
if not content or not content.strip():
|
|
return False
|
|
if "##" not in content:
|
|
return False
|
|
return True
|
|
|
|
|
|
class Compactor(BaseOp):
|
|
"""Compactor class for compacting memory messages."""
|
|
|
|
def __init__(
|
|
self,
|
|
memory_compact_threshold: int,
|
|
console_enabled: bool = False,
|
|
return_dict: bool = False,
|
|
add_thinking_block: bool = True,
|
|
**kwargs,
|
|
):
|
|
super().__init__(**kwargs)
|
|
self.memory_compact_threshold: int = memory_compact_threshold
|
|
self.console_enabled: bool = console_enabled
|
|
self.return_dict: bool = return_dict
|
|
self.add_thinking_block: bool = add_thinking_block
|
|
|
|
# pylint: disable=too-many-return-statements
|
|
async def execute(self):
|
|
messages: list[Msg] = self.context.get("messages", [])
|
|
previous_summary: str = self.context.get("previous_summary", "")
|
|
|
|
if not messages:
|
|
if self.return_dict:
|
|
return {"user_message": "", "history_compact": "", "is_valid": False}
|
|
return ""
|
|
|
|
msg_handler = AsMsgHandler(self.as_token_counter)
|
|
before_token_count = await msg_handler.count_msgs_token(messages)
|
|
history_formatted_str: str = await msg_handler.format_msgs_to_str(
|
|
messages=messages,
|
|
memory_compact_threshold=self.memory_compact_threshold,
|
|
include_thinking=self.add_thinking_block,
|
|
)
|
|
after_token_count = await msg_handler.count_str_token(history_formatted_str)
|
|
logger.info(f"Compactor before_token_count={before_token_count} after_token_count={after_token_count}")
|
|
|
|
if not history_formatted_str:
|
|
logger.warning(f"No history to compact. messages={messages}")
|
|
if self.return_dict:
|
|
return {"user_message": "", "history_compact": "", "is_valid": False}
|
|
return ""
|
|
|
|
agent = ReActAgent(
|
|
name="reme_compactor",
|
|
model=self.as_llm,
|
|
sys_prompt=self.get_prompt("system_prompt"),
|
|
formatter=self.as_llm_formatter,
|
|
)
|
|
agent.set_console_output_enabled(self.console_enabled)
|
|
|
|
if previous_summary:
|
|
user_message: str = (
|
|
f"# conversation\n{history_formatted_str}\n\n"
|
|
f"# previous-summary\n{previous_summary}\n\n" + self.get_prompt("update_user_message")
|
|
)
|
|
else:
|
|
user_message: str = f"# conversation\n{history_formatted_str}\n\n" + self.get_prompt("initial_user_message")
|
|
logger.info(f"Compactor sys_prompt={agent.sys_prompt} user_message={user_message}")
|
|
|
|
compact_msg: Msg = await agent.reply(
|
|
Msg(
|
|
name="reme",
|
|
role="user",
|
|
content=user_message,
|
|
),
|
|
)
|
|
|
|
history_compact: str = compact_msg.get_text_content()
|
|
is_valid: bool = _is_valid_summary(history_compact)
|
|
|
|
if not is_valid:
|
|
logger.warning(f"Invalid summary result: {history_compact[:200]}...")
|
|
if self.return_dict:
|
|
return {"user_message": user_message, "history_compact": history_compact, "is_valid": False}
|
|
return ""
|
|
|
|
logger.info(f"Compactor Result:\n{history_compact}")
|
|
|
|
if self.return_dict:
|
|
return {"user_message": user_message, "history_compact": history_compact, "is_valid": True}
|
|
return history_compact
|