/ examples / werewolf_game / evals / utils.py
utils.py
  1  """
  2  Filename: MetaGPT/examples/werewolf_game/evals/utils.py
  3  Created Date: Oct 11, 2023
  4  Revised Date: Oct 20, 2023
  5  Author: [Aria](https://github.com/ariafyy)
  6  """
  7  import glob
  8  import os
  9  import re
 10  from pathlib import Path
 11  
 12  from metagpt.const import METAGPT_ROOT
 13  
 14  
 15  class Utils:
 16      """Utils: utils of logs"""
 17  
 18      @staticmethod
 19      def polish_log(in_logfile, out_txtfile):
 20          """polish logs for evaluation"""
 21          pattern_text = r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}) \| (\w+) +\| ([\w\.]+:\w+:\d+) - (.*\S)"
 22          pattern_player = r"(Player(\d{1}): \w+)"
 23          pattern_start = False
 24          json_start = False
 25  
 26          with open(in_logfile, "r") as f, open(out_txtfile, "w") as out:
 27              for line in f.readlines():
 28                  matches = re.match(pattern_text, line)
 29                  if matches:
 30                      message = matches.group(4).strip()
 31                      pattern_start = True
 32                      json_start = False
 33  
 34                      if (
 35                          "Moderator(Moderator) ready to InstructSpeak" not in message
 36                          and "Moderator(Moderator) ready to ParseSpeak" not in message
 37                          and "Total running cost:" not in message
 38                      ):
 39                          out.write("- " + message + "\n")
 40                      else:
 41                          out.write("\n")
 42  
 43                  elif pattern_start and not matches:
 44                      if "gpt-4 may update over time" in line:
 45                          line = ""
 46                      out.write(line)
 47  
 48                  elif line.strip().startswith("{"):
 49                      out.write(line.strip())
 50                      json_start = True
 51  
 52                  elif json_start and not line.strip().endswith("}"):
 53                      out.write(line.strip())
 54  
 55                  elif json_start and line.strip().endswith("}"):
 56                      out.write(line.strip())
 57                      json_start = False
 58  
 59                  elif (
 60                      line.startswith("(User):") or line.startswith("********** STEP:") or re.search(pattern_player, line)
 61                  ):
 62                      out.write(line)
 63  
 64                  else:
 65                      out.write("\n")
 66  
 67      @staticmethod
 68      def pick_vote_log(in_logfile, out_txtfile):
 69          """
 70          pick the vote log from the log file.
 71          ready to AnnounceGameResult serves as the 'HINT_TEXT ' which indicates the end of the game.
 72          based on bservation and reflection, then discuss is not in vote session.
 73          """
 74          pattern_vote = r"(Player\d+)\(([A-Za-z]+)\): (\d+) \| (I vote to eliminate Player\d+)"
 75          ignore_text = """reflection"""
 76          HINT_TEXT = r"ready to AnnounceGameResult"
 77          pattern_moderator = r"\[([^\]]+)\]\. Say ONLY: I vote to eliminate ..."
 78          in_valid_block = False
 79  
 80          with open(in_logfile, "r") as f:
 81              lines = f.read()
 82              split_lines = lines.split(HINT_TEXT)
 83  
 84              if len(split_lines) < 2:
 85                  print(f"Key text :{HINT_TEXT} not found in {in_logfile}")
 86                  return
 87  
 88              relevant_lines = split_lines[1].split("\n")
 89              with open(out_txtfile, "w") as out:
 90                  for line in relevant_lines:
 91                      if re.search(pattern_moderator, line):
 92                          in_valid_block = True
 93                          out.write(line.lstrip() + "\n")
 94  
 95                      elif in_valid_block and re.search(pattern_vote, line):
 96                          out.write(line + "\n")
 97                      elif ignore_text in line:
 98                          in_valid_block = False
 99  
100      @staticmethod
101      def get_file_list(path: str) -> list:
102          file_pattern = os.path.join(path, "*.txt")
103          files_list = glob.glob(file_pattern)
104          return files_list
105  
106      @staticmethod
107      def filename_to_foldername(out_txtfile: str):
108          """
109          convert filename into its parent folder name
110          input:"....../# 01-10_10132100.txt"
111          output:# 01-10
112          """
113          s = Path(out_txtfile).stem
114          pattern_folder = r"([^_]*)_"
115          match = re.match(pattern_folder, s)
116          if match:
117              folder = match.group(1)
118              return folder
119  
120      @staticmethod
121      def float_to_percent(decimal: float) -> str:
122          """
123          input:  1.00
124          output: 100.00%
125          """
126          percent = decimal * 100
127          return f"{percent:.2f}%"
128  
129  
130  if __name__ == "__main__":
131      in_logfile = METAGPT_ROOT / "logs/log.txt"
132      out_txtfile = "input your wish path"
133      # Utils().polish_log(in_logfile, out_txtfile)
134      Utils().pick_vote_log(in_logfile, out_txtfile)