Skip to content

Commit

Permalink
Feature/enable intuitive logs for community challenge step 1 (Signifi…
Browse files Browse the repository at this point in the history
  • Loading branch information
waynehamadi authored May 3, 2023
1 parent 479c746 commit 26c6cfe
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 5 deletions.
31 changes: 28 additions & 3 deletions autogpt/agent/agent.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from datetime import datetime

from colorama import Fore, Style

from autogpt.app import execute_command, get_command
Expand All @@ -6,6 +8,11 @@
from autogpt.json_utils.utilities import LLM_DEFAULT_RESPONSE_FORMAT, validate_json
from autogpt.llm import chat_with_ai, create_chat_completion, create_chat_message
from autogpt.llm.token_counter import count_string_tokens
from autogpt.log_cycle.log_cycle import (
FULL_MESSAGE_HISTORY_FILE_NAME,
NEXT_ACTION_FILE_NAME,
LogCycleHandler,
)
from autogpt.logs import logger, print_assistant_thoughts
from autogpt.speech import say_text
from autogpt.spinner import Spinner
Expand Down Expand Up @@ -68,22 +75,33 @@ def __init__(
self.system_prompt = system_prompt
self.triggering_prompt = triggering_prompt
self.workspace = Workspace(workspace_directory, cfg.restrict_to_workspace)
self.created_at = datetime.now().strftime("%Y%m%d_%H%M%S")
self.cycle_count = 0
self.log_cycle_handler = LogCycleHandler()

def start_interaction_loop(self):
# Interaction Loop
cfg = Config()
loop_count = 0
self.cycle_count = 0
command_name = None
arguments = None
user_input = ""

while True:
# Discontinue if continuous limit is reached
loop_count += 1
self.cycle_count += 1
self.log_cycle_handler.log_count_within_cycle = 0
self.log_cycle_handler.log_cycle(
self.config.ai_name,
self.created_at,
self.cycle_count,
self.full_message_history,
FULL_MESSAGE_HISTORY_FILE_NAME,
)
if (
cfg.continuous_mode
and cfg.continuous_limit > 0
and loop_count > cfg.continuous_limit
and self.cycle_count > cfg.continuous_limit
):
logger.typewriter_log(
"Continuous Limit Reached: ", Fore.YELLOW, f"{cfg.continuous_limit}"
Expand Down Expand Up @@ -122,6 +140,13 @@ def start_interaction_loop(self):

except Exception as e:
logger.error("Error: \n", str(e))
self.log_cycle_handler.log_cycle(
self.config.ai_name,
self.created_at,
self.cycle_count,
assistant_reply_json,
NEXT_ACTION_FILE_NAME,
)

if not cfg.continuous_mode and self.next_action_count == 0:
# ### GET USER AUTHORIZATION TO EXECUTE COMMAND ###
Expand Down
8 changes: 8 additions & 0 deletions autogpt/llm/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from autogpt.llm.base import Message
from autogpt.llm.llm_utils import create_chat_completion
from autogpt.llm.token_counter import count_message_tokens
from autogpt.log_cycle.log_cycle import PROMPT_NEXT_ACTION_FILE_NAME
from autogpt.logs import logger
from autogpt.memory_management.store_memory import (
save_memory_trimmed_from_context_window,
Expand Down Expand Up @@ -231,6 +232,13 @@ def chat_with_ai(
logger.debug(f"{message['role'].capitalize()}: {message['content']}")
logger.debug("")
logger.debug("----------- END OF CONTEXT ----------------")
agent.log_cycle_handler.log_cycle(
agent.config.ai_name,
agent.created_at,
agent.cycle_count,
current_context,
PROMPT_NEXT_ACTION_FILE_NAME,
)

# TODO: use a model defined elsewhere, so that model can contain
# temperature and other settings we care about
Expand Down
Empty file added autogpt/log_cycle/__init__.py
Empty file.
20 changes: 20 additions & 0 deletions autogpt/log_cycle/json_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import json
import logging


class JsonFileHandler(logging.FileHandler):
def __init__(self, filename, mode="a", encoding=None, delay=False):
super().__init__(filename, mode, encoding, delay)

def emit(self, record):
json_data = json.loads(self.format(record))
with open(self.baseFilename, "w", encoding="utf-8") as f:
json.dump(json_data, f, ensure_ascii=False, indent=4)


import logging


class JsonFormatter(logging.Formatter):
def format(self, record):
return record.msg
80 changes: 80 additions & 0 deletions autogpt/log_cycle/log_cycle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import json
import os
from typing import Any, Dict, Union

from autogpt.logs import logger

DEFAULT_PREFIX = "agent"
FULL_MESSAGE_HISTORY_FILE_NAME = "full_message_history.json"
PROMPT_NEXT_ACTION_FILE_NAME = "prompt_next_action.json"
NEXT_ACTION_FILE_NAME = "next_action.json"


class LogCycleHandler:
"""
A class for logging cycle data.
"""

def __init__(self):
self.log_count_within_cycle = 0

@staticmethod
def create_directory_if_not_exists(directory_path: str) -> None:
if not os.path.exists(directory_path):
os.makedirs(directory_path, exist_ok=True)

def create_outer_directory(self, ai_name: str, created_at: str) -> str:
log_directory = logger.get_log_directory()

if os.environ.get("OVERWRITE_DEBUG") == "1":
outer_folder_name = "auto_gpt"
else:
ai_name_short = ai_name[:15] if ai_name else DEFAULT_PREFIX
outer_folder_name = f"{created_at}_{ai_name_short}"

outer_folder_path = os.path.join(log_directory, "DEBUG", outer_folder_name)
self.create_directory_if_not_exists(outer_folder_path)

return outer_folder_path

def create_inner_directory(self, outer_folder_path: str, cycle_count: int) -> str:
nested_folder_name = str(cycle_count).zfill(3)
nested_folder_path = os.path.join(outer_folder_path, nested_folder_name)
self.create_directory_if_not_exists(nested_folder_path)

return nested_folder_path

def create_nested_directory(
self, ai_name: str, created_at: str, cycle_count: int
) -> str:
outer_folder_path = self.create_outer_directory(ai_name, created_at)
nested_folder_path = self.create_inner_directory(outer_folder_path, cycle_count)

return nested_folder_path

def log_cycle(
self,
ai_name: str,
created_at: str,
cycle_count: int,
data: Union[Dict[str, Any], Any],
file_name: str,
) -> None:
"""
Log cycle data to a JSON file.
Args:
data (Any): The data to be logged.
file_name (str): The name of the file to save the logged data.
"""
nested_folder_path = self.create_nested_directory(
ai_name, created_at, cycle_count
)

json_data = json.dumps(data, ensure_ascii=False, indent=4)
log_file_path = os.path.join(
nested_folder_path, f"{self.log_count_within_cycle}_{file_name}"
)

logger.log_json(json_data, log_file_path)
self.log_count_within_cycle += 1
35 changes: 33 additions & 2 deletions autogpt/logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import re
import time
from logging import LogRecord
from typing import Any

from colorama import Fore, Style

from autogpt.log_cycle.json_handler import JsonFileHandler, JsonFormatter
from autogpt.singleton import Singleton
from autogpt.speech import say_text

Expand Down Expand Up @@ -74,6 +76,11 @@ def __init__(self):
self.logger.addHandler(error_handler)
self.logger.setLevel(logging.DEBUG)

self.json_logger = logging.getLogger("JSON_LOGGER")
self.json_logger.addHandler(self.file_handler)
self.json_logger.addHandler(error_handler)
self.json_logger.setLevel(logging.DEBUG)

self.speak_mode = False
self.chat_plugins = []

Expand Down Expand Up @@ -152,6 +159,26 @@ def double_check(self, additionalText=None):

self.typewriter_log("DOUBLE CHECK CONFIGURATION", Fore.YELLOW, additionalText)

def log_json(self, data: Any, file_name: str) -> None:
# Define log directory
this_files_dir_path = os.path.dirname(__file__)
log_dir = os.path.join(this_files_dir_path, "../logs")

# Create a handler for JSON files
json_file_path = os.path.join(log_dir, file_name)
json_data_handler = JsonFileHandler(json_file_path)
json_data_handler.setFormatter(JsonFormatter())

# Log the JSON data using the custom file handler
self.json_logger.addHandler(json_data_handler)
self.json_logger.debug(data)
self.json_logger.removeHandler(json_data_handler)

def get_log_directory(self):
this_files_dir_path = os.path.dirname(__file__)
log_dir = os.path.join(this_files_dir_path, "../logs")
return os.path.abspath(log_dir)


"""
Output stream to console using simulated typing
Expand Down Expand Up @@ -199,12 +226,16 @@ def format(self, record: LogRecord) -> str:
if hasattr(record, "color"):
record.title_color = (
getattr(record, "color")
+ getattr(record, "title")
+ getattr(record, "title", "")
+ " "
+ Style.RESET_ALL
)
else:
record.title_color = getattr(record, "title")
record.title_color = getattr(record, "title", "")

# Add this line to set 'title' to an empty string if it doesn't exist
record.title = getattr(record, "title", "")

if hasattr(record, "msg"):
record.message_no_color = remove_color_codes(getattr(record, "msg"))
else:
Expand Down

0 comments on commit 26c6cfe

Please sign in to comment.