Repository: microsoft/qlib
File: qlib/finco/log.py (Python)

Code before:
    END = '\033[0m'
    WHITE = '\033[97m'
    GRAY = '\033[90m'
    BLACK = '\033[30m'


@contextmanager
def formatting_log(logger, title="Info"):
    """
    a context manager, print liens before and after a function
    """
    length = {"Task": 120, "Info": 0}.get(title, 60)
    start = int((length - len(title)) / 2)
    pad = 1 if len(title) % 2 else 0
    color, bold = (LogColors.YELLOW, LogColors.BOLD) if title in ["Info", "Task"] else (LogColors.CYAN, '')
    logger.info("")
    logger.info(f"{color}{bold}{'-' * (start + pad)} {title} {'-' * start}{LogColors.END}")
    yield
    logger.info("")


class FinCoLog(Singleton):
    # TODO:
    # - config to file logger and save it into workspace
    def __init__(self) -> None:
        # self.logger = get_module_logger("interactive")
        self.logger = logging.Logger("interactive")

        handler = logging.StreamHandler()
        handler.setFormatter(logging.Formatter('%(message)s'))
        self.logger.addHandler(handler)
        self.logger.setLevel(logging.INFO)

    def log_message(self, messages: List[Dict[str, str]]):
        """
        messages is some info like this  [
            {
                "role": "system",
                "content": system_prompt,
            },
            {
                "role": "user",
                "content": user_prompt,
            },
        ]
        """
        with formatting_log(self.logger, "GPT Messages"):
            for m in messages:
                self.logger.info(
                    f"\n{LogColors.MAGENTA}{LogColors.BOLD}Role:{LogColors.END} "
                    f"{LogColors.CYAN}{m['role']}{LogColors.END}\n"

Review comment (suggestion):
```suggestion
        self.logger = logging.Logger("interactive")
        # TODO:  merge these with Qlib's default logger.  We can do the same thing by changing the default log dict of Qlib.
        #  Reference: https://github.com/microsoft/qlib/blob/main/qlib/config.py#L155
```

Code after:
    END = "\033[0m"
    WHITE = "\033[97m"
    GRAY = "\033[90m"
    BLACK = "\033[30m"
    # TODO: Provide  better interface to render text. (e.g. render(text, color.., style ..))


@contextmanager
def formatting_log(logger, title="Info"):
    """
    a context manager, print liens before and after a function
    """
    length = {"Start": 120, "Task": 120, "Info": 60}.get(title, 60)
    color, bold = (LogColors.YELLOW, LogColors.BOLD) if title in ["Start", "Info", "Task"] else (LogColors.CYAN, "")
    logger.info("")
    logger.info(f"{color}{bold}{'-'} {title} {'-' * (length - len(title))}{LogColors.END}")
    yield
    logger.info("")


class FinCoLog(Singleton):
    # TODO:
    # - config to file logger and save it into workspace
    def __init__(self) -> None:
        # self.logger = get_module_logger("interactive")
        self.logger = logging.Logger("interactive")
        # TODO:  merge these with Qlib's default logger.
        #  We can do the same thing by changing the default log dict of Qlib.
        #  Reference: https://github.com/microsoft/qlib/blob/main/qlib/config.py#L155

        handler = logging.StreamHandler()
        handler.setFormatter(logging.Formatter("%(message)s"))
        self.logger.addHandler(handler)
        self.logger.setLevel(logging.INFO)

    def log_message(self, messages: List[Dict[str, str]]):
        """
        messages is some info like this  [
            {
                "role": "system",
                "content": system_prompt,
            },
            {
                "role": "user",
                "content": user_prompt,
            },
        ]
        """
        with formatting_log(self.logger, "GPT Messages"):
            for m in messages:
                self.logger.info(