ReMe/reme/memory/file_based/components/compactor.py
jinliyl 9a6cf2b994
Dev/token (#159)
* update

* refactor(memory): remove unnecessary type check and update error logging

* refactor(core): standardize logger import and update agentscope dependency

* fix(memory): disable console output and add logging for summarizer component

* feat(core): replace OpenAI token counter with custom ReMe token counter

- Replace OpenAITokenCounter with ReMeTokenCounter implementation
- Add support for HuggingFace mirror and configurable tokenizer
- Register ReMeTokenCounter as default token counter in registry
- Update config to use hf backend with Qwen2.5-7B-Instruct model

refactor(memory): convert token counting methods to async in message handlers

- Change count_str_token, stat_message, count_msgs_token to async methods
- Update format_msgs_to_str and context_check to use async token counting
- Modify _format_tool_result_output to support async token counting
- Adjust all dependent methods to await async token counting calls

feat(memory): add dialog persistence to in-memory storage

- Implement _append_messages_to_dialog for saving messages to JSONL files
- Add dialog_path parameter to ReMeInMemoryMemory constructor
- Persist messages to daily JSONL files based on timestamp grouping
- Update mark_messages_compressed to save and remove compressed messages
- Modify clear_content to persist all messages before clearing memory

refactor(ops): update token counter type hints and initialization

- Change BaseOp to use HuggingFaceTokenCounter instead of TokenCounterBase
- Update type annotations for as_token_counter property and parameters
- Remove direct token counter injection from Compactor and ContextChecker
- Pass as_token_counter parameter through service context mechanism

style(logging): improve error logging with exception details

- Replace logger.error with logger.exception in browser control tool
- Change logger.error to logger.exception in memory get tool error handling
- Add proper exception logging with stack trace information

chore(config): add token counter configuration to light YAML

- Add as_token_counters section with default hf backend configuration
- Configure Qwen/Qwen2.5-7B-Instruct model with mirror support enabled
- Set up pretrained_model_name_or_path and use_mirror parameters

test(context): update context check tests to async implementation

- Convert verify_context_check_invariants to async function
- Update context check test methods to use async calls
- Change stat_message calls to await async implementation
- Modify test_empty_messages and test_below_threshold_returns_all to async

* feat(core): implement context checking and memory management features

* refactor(core): replace direct loguru import with logger utility function

* refactor(reme): remove RuntimeContext dependency and simplify context checking

* feat(docs): add raw conversation persistence to ReMe framework
2026-03-17 11:07:31 +08:00

79 lines
2.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()
class Compactor(BaseOp):
"""Compactor class for compacting memory messages."""
def __init__(
self,
memory_compact_threshold: int,
console_enabled: bool = False,
**kwargs,
):
super().__init__(**kwargs)
self.memory_compact_threshold: int = memory_compact_threshold
self.console_enabled: bool = console_enabled
async def execute(self):
messages: list[Msg] = self.context.get("messages", [])
previous_summary: str = self.context.get("previous_summary", "")
if not messages:
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,
)
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}")
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:
prefix: str = self.get_prompt("update_user_message_prefix")
suffix: str = self.get_prompt("update_user_message_suffix")
user_message: str = (
f"<conversation>\n{history_formatted_str}\n</conversation>\n\n"
f"{prefix}\n\n"
f"<previous-summary>\n{previous_summary}\n</previous-summary>\n\n"
f"{suffix}"
)
else:
user_message: str = f"<conversation>\n{history_formatted_str}\n</conversation>\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()
logger.info(f"Compactor Result:\n{history_compact}")
return history_compact