Eric Botti
commited on
Commit
·
172af0f
1
Parent(s):
1a8a579
added game and player level logging
Browse files- src/game.py +28 -13
- src/game_utils.py +7 -0
- src/main.py +2 -0
- src/player.py +13 -1
src/game.py
CHANGED
@@ -11,13 +11,15 @@ NUMBER_OF_PLAYERS = 5
|
|
11 |
|
12 |
class Game:
|
13 |
log_dir = os.path.join(os.pardir, "experiments")
|
14 |
-
player_log_file = "{
|
15 |
parser_log_file = "{game_id}-parser.jsonl"
|
|
|
16 |
|
17 |
-
def __init__(
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
21 |
|
22 |
# Game ID
|
23 |
self.game_id = game_id()
|
@@ -28,6 +30,7 @@ class Game:
|
|
28 |
self.human_index = random_index(number_of_players)
|
29 |
else:
|
30 |
ai_names = random_names(number_of_players)
|
|
|
31 |
|
32 |
# Choose Chameleon
|
33 |
self.chameleon_index = random_index(number_of_players)
|
@@ -47,10 +50,14 @@ class Game:
|
|
47 |
else:
|
48 |
role = "herd"
|
49 |
|
50 |
-
|
51 |
-
self.player_log_file.format(game_id=self.game_id, role=role, player_num=i))
|
52 |
|
53 |
-
|
|
|
|
|
|
|
|
|
|
|
54 |
|
55 |
# Game State
|
56 |
self.player_responses = []
|
@@ -74,9 +81,9 @@ class Game:
|
|
74 |
self.player_responses = []
|
75 |
herd_animal = random_animal()
|
76 |
|
77 |
-
|
78 |
|
79 |
-
while not
|
80 |
# Phase I: Collect Player Animal Descriptions
|
81 |
for player in self.players:
|
82 |
if player.role == "chameleon":
|
@@ -113,10 +120,8 @@ class Game:
|
|
113 |
output = await self.parser.parse(prompt, response, ChameleonGuessAnimalModel)
|
114 |
|
115 |
if output.animal == herd_animal:
|
116 |
-
game_over = True
|
117 |
winner = "chameleon"
|
118 |
else:
|
119 |
-
game_over = True
|
120 |
winner = "herd"
|
121 |
|
122 |
else:
|
@@ -142,7 +147,6 @@ class Game:
|
|
142 |
accused_player = count_chameleon_votes(player_votes)
|
143 |
|
144 |
if accused_player:
|
145 |
-
game_over = True
|
146 |
if accused_player == self.players[self.chameleon_index].name:
|
147 |
winner = "herd"
|
148 |
else:
|
@@ -156,3 +160,14 @@ class Game:
|
|
156 |
# Herd Wins by Correctly Guessing Chameleon - 2 points (each)
|
157 |
|
158 |
# Log Game Info
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
12 |
class Game:
|
13 |
log_dir = os.path.join(os.pardir, "experiments")
|
14 |
+
player_log_file = "{player_id}.jsonl"
|
15 |
parser_log_file = "{game_id}-parser.jsonl"
|
16 |
+
game_log_file = "{game_id}-game.jsonl"
|
17 |
|
18 |
+
def __init__(
|
19 |
+
self,
|
20 |
+
human_name: str = None,
|
21 |
+
number_of_players: int = NUMBER_OF_PLAYERS
|
22 |
+
):
|
23 |
|
24 |
# Game ID
|
25 |
self.game_id = game_id()
|
|
|
30 |
self.human_index = random_index(number_of_players)
|
31 |
else:
|
32 |
ai_names = random_names(number_of_players)
|
33 |
+
self.human_index = None
|
34 |
|
35 |
# Choose Chameleon
|
36 |
self.chameleon_index = random_index(number_of_players)
|
|
|
50 |
else:
|
51 |
role = "herd"
|
52 |
|
53 |
+
player_id = f"{self.game_id}-{i + 1}-{role}"
|
|
|
54 |
|
55 |
+
log_path = os.path.join(
|
56 |
+
self.log_dir,
|
57 |
+
self.player_log_file.format(player_id=player_id)
|
58 |
+
)
|
59 |
+
|
60 |
+
self.players.append(Player(name, controller, role, player_id, log_filepath=log_path))
|
61 |
|
62 |
# Game State
|
63 |
self.player_responses = []
|
|
|
81 |
self.player_responses = []
|
82 |
herd_animal = random_animal()
|
83 |
|
84 |
+
winner = None
|
85 |
|
86 |
+
while not winner:
|
87 |
# Phase I: Collect Player Animal Descriptions
|
88 |
for player in self.players:
|
89 |
if player.role == "chameleon":
|
|
|
120 |
output = await self.parser.parse(prompt, response, ChameleonGuessAnimalModel)
|
121 |
|
122 |
if output.animal == herd_animal:
|
|
|
123 |
winner = "chameleon"
|
124 |
else:
|
|
|
125 |
winner = "herd"
|
126 |
|
127 |
else:
|
|
|
147 |
accused_player = count_chameleon_votes(player_votes)
|
148 |
|
149 |
if accused_player:
|
|
|
150 |
if accused_player == self.players[self.chameleon_index].name:
|
151 |
winner = "herd"
|
152 |
else:
|
|
|
160 |
# Herd Wins by Correctly Guessing Chameleon - 2 points (each)
|
161 |
|
162 |
# Log Game Info
|
163 |
+
game_log = {
|
164 |
+
"game_id": self.game_id,
|
165 |
+
"herd_animal": herd_animal,
|
166 |
+
"number_of_players": len(self.players),
|
167 |
+
"human_player": self.players[self.human_index].id if self.human_index else "None",
|
168 |
+
"chameleon": self.players[self.chameleon_index].id,
|
169 |
+
"winner": winner
|
170 |
+
}
|
171 |
+
game_log_path = os.path.join(self.log_dir, self.game_log_file.format(game_id=self.game_id))
|
172 |
+
|
173 |
+
log(game_log, game_log_path)
|
src/game_utils.py
CHANGED
@@ -3,6 +3,7 @@ Utilities for the game including random selections and prompts.
|
|
3 |
"""
|
4 |
import random
|
5 |
import string
|
|
|
6 |
from collections import Counter
|
7 |
|
8 |
ALPHABET = string.ascii_lowercase + string.digits
|
@@ -46,6 +47,12 @@ def count_chameleon_votes(player_votes: list[str]) -> str | None:
|
|
46 |
return None
|
47 |
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
def fetch_prompt(prompt_name):
|
50 |
return prompts[prompt_name]
|
51 |
|
|
|
3 |
"""
|
4 |
import random
|
5 |
import string
|
6 |
+
import json
|
7 |
from collections import Counter
|
8 |
|
9 |
ALPHABET = string.ascii_lowercase + string.digits
|
|
|
47 |
return None
|
48 |
|
49 |
|
50 |
+
def log(log_object, log_file):
|
51 |
+
with open(log_file, "a+") as f:
|
52 |
+
f.write(json.dumps(log_object) + "\n")
|
53 |
+
|
54 |
+
|
55 |
+
# Prompt Stuff
|
56 |
def fetch_prompt(prompt_name):
|
57 |
return prompts[prompt_name]
|
58 |
|
src/main.py
CHANGED
@@ -8,6 +8,8 @@ def main():
|
|
8 |
|
9 |
game = Game(human_name=name)
|
10 |
|
|
|
|
|
11 |
asyncio.run(game.start())
|
12 |
|
13 |
|
|
|
8 |
|
9 |
game = Game(human_name=name)
|
10 |
|
11 |
+
# game = Game()
|
12 |
+
|
13 |
asyncio.run(game.start())
|
14 |
|
15 |
|
src/player.py
CHANGED
@@ -1,10 +1,12 @@
|
|
1 |
import os
|
|
|
2 |
import asyncio
|
3 |
|
4 |
import openai
|
5 |
from agents import LogMessagesKani
|
6 |
from kani.engines.openai import OpenAIEngine
|
7 |
|
|
|
8 |
|
9 |
# Using TGI Inference Endpoints from Hugging Face
|
10 |
# api_type = "tgi"
|
@@ -24,8 +26,9 @@ openai_engine = OpenAIEngine(model="gpt-3.5-turbo")
|
|
24 |
|
25 |
|
26 |
class Player:
|
27 |
-
def __init__(self, name: str, controller_type: str, role: str, log_filepath: str = None):
|
28 |
self.name = name
|
|
|
29 |
self.controller = controller_type
|
30 |
if controller_type == "ai":
|
31 |
self.kani = LogMessagesKani(openai_engine, log_filepath=log_filepath)
|
@@ -33,6 +36,15 @@ class Player:
|
|
33 |
self.role = role
|
34 |
self.messages = []
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
async def respond_to(self, prompt: str) -> str:
|
37 |
"""Makes the player respond to a prompt. Returns the response."""
|
38 |
# Generate a response from the controller
|
|
|
1 |
import os
|
2 |
+
import json
|
3 |
import asyncio
|
4 |
|
5 |
import openai
|
6 |
from agents import LogMessagesKani
|
7 |
from kani.engines.openai import OpenAIEngine
|
8 |
|
9 |
+
from game_utils import log
|
10 |
|
11 |
# Using TGI Inference Endpoints from Hugging Face
|
12 |
# api_type = "tgi"
|
|
|
26 |
|
27 |
|
28 |
class Player:
|
29 |
+
def __init__(self, name: str, controller_type: str, role: str, id: str = None, log_filepath: str = None):
|
30 |
self.name = name
|
31 |
+
self.id = id
|
32 |
self.controller = controller_type
|
33 |
if controller_type == "ai":
|
34 |
self.kani = LogMessagesKani(openai_engine, log_filepath=log_filepath)
|
|
|
36 |
self.role = role
|
37 |
self.messages = []
|
38 |
|
39 |
+
if log_filepath:
|
40 |
+
player_info = {
|
41 |
+
"id": self.id,
|
42 |
+
"name": self.name,
|
43 |
+
"role": self.role,
|
44 |
+
"controller": controller_type,
|
45 |
+
}
|
46 |
+
log(player_info, log_filepath)
|
47 |
+
|
48 |
async def respond_to(self, prompt: str) -> str:
|
49 |
"""Makes the player respond to a prompt. Returns the response."""
|
50 |
# Generate a response from the controller
|