From 6184d3e2fbbdcdb4bca7ce977eef283d1aac3efc Mon Sep 17 00:00:00 2001 From: Hans Raaf Date: Tue, 31 Oct 2023 00:01:37 +0100 Subject: [PATCH] I made dump showing more message and added a count (the last x) There seem to be some changes about the implementation so that the current dump message helper functions do not show a lot of useful info. I changed it so that you can `dump 5` (last 5 messages) and that it will print user readable output. This lets you get some more understanding about what is going on. As some messages are still not shown I also show the index (reverse) of the printed message, so one can see what to "pop" to reach a special point without geting into the drumpraw. --- README.md | 4 +-- memgpt/interface.py | 72 +++++++++++++++++++++++++++++++++------------ memgpt/main.py | 17 ++++++----- 3 files changed, 66 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 6647336142..25ceae7f3b 100644 --- a/README.md +++ b/README.md @@ -286,8 +286,8 @@ While using MemGPT via the CLI (not Discord!) you can run various commands: save a checkpoint of the current agent/conversation state /load load a saved checkpoint -/dump - view the current message log (see the contents of main context) +/dump + view the last messages (all if is omitted) /memory print the current contents of agent memory /pop diff --git a/memgpt/interface.py b/memgpt/interface.py index b9b95be6fd..4ba2dd585a 100644 --- a/memgpt/interface.py +++ b/memgpt/interface.py @@ -32,11 +32,14 @@ async def memory_message(msg): print(f"{Fore.LIGHTMAGENTA_EX}{Style.BRIGHT}🧠 {Fore.LIGHTMAGENTA_EX}{msg}{Style.RESET_ALL}") -async def system_message(msg): - printd(f"{Fore.MAGENTA}{Style.BRIGHT}🖥️ [system] {Fore.MAGENTA}{msg}{Style.RESET_ALL}") +async def system_message(msg, dump=False): + if DEBUG: + printd(f"{Fore.MAGENTA}{Style.BRIGHT}🖥️ [system] {Fore.MAGENTA}{msg}{Style.RESET_ALL}") + elif dump: + print(f"{Fore.MAGENTA}{Style.BRIGHT}🖥️ [system] {Fore.MAGENTA}{msg}{Style.RESET_ALL}") -async def user_message(msg, raw=False): +async def user_message(msg, raw=False, dump=False): if isinstance(msg, str): if raw: printd(f"{Fore.GREEN}{Style.BRIGHT}🧑 {Fore.GREEN}{msg}{Style.RESET_ALL}") @@ -48,22 +51,30 @@ async def user_message(msg, raw=False): printd(f"Warning: failed to parse user message into json") printd(f"{Fore.GREEN}{Style.BRIGHT}🧑 {Fore.GREEN}{msg}{Style.RESET_ALL}") return - - if msg_json["type"] == "user_message": - msg_json.pop("type") - printd(f"{Fore.GREEN}{Style.BRIGHT}🧑 {Fore.GREEN}{msg_json}{Style.RESET_ALL}") - elif msg_json["type"] == "heartbeat": + else: # not what we thought it is + return + msg_type = msg_json["type"] + if msg_type == "user_message": + if dump: + message = msg_json.get("message") + print(f"{Fore.GREEN}{Style.BRIGHT}🧑 {Fore.GREEN}{message}{Style.RESET_ALL}") + else: + msg_json.pop("type") + printd(f"{Fore.GREEN}{Style.BRIGHT}🧑 {Fore.GREEN}{msg_json}{Style.RESET_ALL}") + elif msg_type == "heartbeat": if DEBUG: msg_json.pop("type") printd(f"{Fore.GREEN}{Style.BRIGHT}💓 {Fore.GREEN}{msg_json}{Style.RESET_ALL}") - elif msg_json["type"] == "system_message": + elif msg_type == "system_message": msg_json.pop("type") printd(f"{Fore.GREEN}{Style.BRIGHT}🖥️ {Fore.GREEN}{msg_json}{Style.RESET_ALL}") + elif msg_type == "login": + printd(f"{Fore.GREEN}{Style.BRIGHT}🧑 {Fore.GREEN}{msg_json}{Style.RESET_ALL}") else: printd(f"{Fore.GREEN}{Style.BRIGHT}🧑 {Fore.GREEN}{msg_json}{Style.RESET_ALL}") -async def function_message(msg): +async def function_message(msg, dump=False): if isinstance(msg, dict): printd(f"{Fore.RED}{Style.BRIGHT}⚡ [function] {Fore.RED}{msg}{Style.RESET_ALL}") return @@ -106,32 +117,57 @@ async def function_message(msg): try: msg_dict = json.loads(msg) if "status" in msg_dict and msg_dict["status"] == "OK": - printd(f"{Fore.GREEN}{Style.BRIGHT}⚡ [function] {Fore.GREEN}{msg}{Style.RESET_ALL}") + if dump: + print(f"{Fore.GREEN}{Style.BRIGHT}⚡ {Fore.GREEN}OK{Style.RESET_ALL}") + else: + printd(f"{Fore.GREEN}{Style.BRIGHT}⚡ [function] {Fore.GREEN}{msg}{Style.RESET_ALL}") + elif "status" in msg_dict and msg_dict["status"] != "OK": + if dump: + status = msg_dict["status"] + print(f"{Fore.GREEN}{Style.BRIGHT}⚡ {Fore.RED}{status}{Style.RESET_ALL}") + else: + printd(f"{Fore.GREEN}{Style.BRIGHT}⚡ [function] {Fore.RED}{msg}{Style.RESET_ALL}") + else: + if dump: + printd(f"{Fore.GREEN}{Style.BRIGHT}⚡ [function] {Fore.RED}{msg}{Style.RESET_ALL}") + else: + printd(f"{Fore.GREEN}{Style.BRIGHT}⚡ [function] {Fore.RED}{msg}{Style.RESET_ALL}") except Exception: - printd(f"Warning: did not recognize function message {type(msg)} {msg}") - printd(f"{Fore.RED}{Style.BRIGHT}⚡ [function] {Fore.RED}{msg}{Style.RESET_ALL}") + if dump: + printd(f"Warning: did not recognize function message {type(msg)} {msg}") + printd(f"{Fore.RED}{Style.BRIGHT}⚡ [function] {Fore.RED}{msg}{Style.RESET_ALL}") + else: + print(f"Warning: did not recognize function message {type(msg)} {msg}") + print(f"{Fore.RED}{Style.BRIGHT}⚡ [function] {Fore.RED}{msg}{Style.RESET_ALL}") -async def print_messages(message_sequence): +async def print_messages(message_sequence, dump=False): + idx = len(message_sequence) for msg in message_sequence: + if dump: + print(f"{idx}. ", end="") + idx -= 1 role = msg["role"] content = msg["content"] if role == "system": - await system_message(content) + await system_message(content, dump=dump) elif role == "assistant": # Differentiate between internal monologue, function calls, and messages if msg.get("function_call"): if content is not None: await internal_monologue(content) - await function_message(msg["function_call"]) + # I think the next one is not up to date + #await function_message(msg["function_call"]) + args = json.loads(msg["function_call"].get("arguments")) + await assistant_message(args.get("message")) # assistant_message(content) else: await internal_monologue(content) elif role == "user": - await user_message(content) + await user_message(content, dump=dump) elif role == "function": - await function_message(content) + await function_message(content, dump=dump) else: print(f"Unknown role: {content}") diff --git a/memgpt/main.py b/memgpt/main.py index 2df9846199..fc97622455 100644 --- a/memgpt/main.py +++ b/memgpt/main.py @@ -14,6 +14,7 @@ from rich.console import Console from prettytable import PrettyTable +from .interface import print_messages console = Console() @@ -446,18 +447,20 @@ async def run_agent_loop(memgpt_agent, first, no_verify=False, cfg=None, legacy= load(memgpt_agent=memgpt_agent, filename=filename) continue - elif user_input.lower() == "/dump": - await memgpt.interface.print_messages(memgpt_agent.messages) + elif user_input.lower() == "/dump" or user_input.lower().startswith("/dump "): + # Check if there's an additional argument that's an integer + command = user_input.strip().split() + amount = int(command[1]) if len(command) > 1 and command[1].isdigit() else 0 + if amount == 0: + await print_messages(memgpt_agent.messages, dump=True) + else: + await print_messages(memgpt_agent.messages[-min(amount, len(memgpt_agent.messages)) :], dump=True) continue elif user_input.lower() == "/dumpraw": await memgpt.interface.print_messages_raw(memgpt_agent.messages) continue - elif user_input.lower() == "/dump1": - await memgpt.interface.print_messages(memgpt_agent.messages[-1]) - continue - elif user_input.lower() == "/memory": print(f"\nDumping memory contents:\n") print(f"{str(memgpt_agent.memory)}") @@ -553,7 +556,7 @@ async def run_agent_loop(memgpt_agent, first, no_verify=False, cfg=None, legacy= ("/exit", "exit the CLI"), ("/save", "save a checkpoint of the current agent/conversation state"), ("/load", "load a saved checkpoint"), - ("/dump", "view the current message log (see the contents of main context)"), + ("/dump ", "view the last messages (all if is omitted)"), ("/memory", "print the current contents of agent memory"), ("/pop", "undo the last message in the conversation"), ("/heartbeat", "send a heartbeat system message to the agent"),