Ali Abid
commited on
Commit
•
9357dc3
1
Parent(s):
467bc3a
changes
Browse files- .gitignore +0 -0
- README.md +5 -7
- game_manager.py +212 -0
- prompt.txt +3 -0
- requirements.txt +1 -0
- run.py +112 -0
- style.css +8 -0
.gitignore
ADDED
File without changes
|
README.md
CHANGED
@@ -1,13 +1,11 @@
|
|
1 |
---
|
2 |
-
title: Gpt Who
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: gradio
|
7 |
sdk_version: 3.23.0
|
8 |
-
app_file:
|
9 |
pinned: false
|
10 |
license: openrail
|
11 |
---
|
12 |
-
|
13 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
1 |
---
|
2 |
+
title: Gpt Who?
|
3 |
+
emoji: 🦹🏼
|
4 |
+
colorFrom: white
|
5 |
+
colorTo: purple
|
6 |
sdk: gradio
|
7 |
sdk_version: 3.23.0
|
8 |
+
app_file: run.py
|
9 |
pinned: false
|
10 |
license: openrail
|
11 |
---
|
|
|
|
game_manager.py
ADDED
@@ -0,0 +1,212 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import threading
|
2 |
+
import openai
|
3 |
+
import os
|
4 |
+
import time
|
5 |
+
import random
|
6 |
+
|
7 |
+
openai.api_key = os.environ["OPENAI_KEY"]
|
8 |
+
|
9 |
+
games = {}
|
10 |
+
all_games_lock = threading.Lock()
|
11 |
+
TIME_TO_SUBMIT = 30
|
12 |
+
TIME_TO_VOTE = 30
|
13 |
+
TIME_TO_REVEAL = 10
|
14 |
+
|
15 |
+
GUESS_AI_PTS = 2
|
16 |
+
GUESSED_AS_AI_PTS = 1
|
17 |
+
|
18 |
+
with open("prompt.txt", "r") as f:
|
19 |
+
PROMPT = f.read()
|
20 |
+
|
21 |
+
|
22 |
+
def new_minigame():
|
23 |
+
return "Write a poem about mice!"
|
24 |
+
|
25 |
+
|
26 |
+
def ai_response(question):
|
27 |
+
prompt = PROMPT.format(
|
28 |
+
question,
|
29 |
+
)
|
30 |
+
completions = openai.Completion.create(
|
31 |
+
engine="gpt-3.5-turbo", prompt=prompt, max_tokens=200, n=1, temperature=0.5
|
32 |
+
)
|
33 |
+
response = completions["choices"][0]["text"]
|
34 |
+
return response
|
35 |
+
|
36 |
+
|
37 |
+
class Game:
|
38 |
+
def __init__(self, room_name):
|
39 |
+
self.room_name = room_name
|
40 |
+
self.command = None
|
41 |
+
self.players = []
|
42 |
+
self.prompts = []
|
43 |
+
self.prompts_completed = 0
|
44 |
+
self.responses = {}
|
45 |
+
self.response_list = []
|
46 |
+
self.ai_response_index = None
|
47 |
+
self.lock = threading.Lock()
|
48 |
+
self.started = False
|
49 |
+
self.stage = None
|
50 |
+
self.stage_start_time = None
|
51 |
+
self.stage_time_remaining = None
|
52 |
+
self.total_stage_time = None
|
53 |
+
self.complete = False
|
54 |
+
self.last_update_index = 0
|
55 |
+
self.input_allowed = False
|
56 |
+
self.last_update_time = time.time()
|
57 |
+
self.chat = []
|
58 |
+
self.player_status = {}
|
59 |
+
self.player_scores = {}
|
60 |
+
self.player_guess = {}
|
61 |
+
self.ai_answer = None
|
62 |
+
|
63 |
+
games[room_name] = self
|
64 |
+
|
65 |
+
def update(self):
|
66 |
+
self.last_update_index += 1
|
67 |
+
self.last_update_time = time.time()
|
68 |
+
|
69 |
+
def start(self):
|
70 |
+
self.started = True
|
71 |
+
self.stage = "START"
|
72 |
+
self.update()
|
73 |
+
|
74 |
+
def get_player_state(self):
|
75 |
+
return [
|
76 |
+
[player, self.player_status[player], self.player_scores[player]]
|
77 |
+
for player in self.players
|
78 |
+
]
|
79 |
+
|
80 |
+
def format_chat(self, player_name):
|
81 |
+
formatted_chat = [[None, self.command]]
|
82 |
+
if self.stage == "COLLECTING_RESPONSSES":
|
83 |
+
if player_name in self.responses:
|
84 |
+
formatted_chat.append([self.responses[player_name], None])
|
85 |
+
elif self.stage == "COLLECTING_VOTES":
|
86 |
+
for msg_player, msg in self.response_list:
|
87 |
+
if msg_player == player_name:
|
88 |
+
formatted_chat.append([msg, None])
|
89 |
+
else:
|
90 |
+
formatted_chat.append([None, msg])
|
91 |
+
elif self.stage == "REVEALING":
|
92 |
+
for msg_player, msg in self.response_list:
|
93 |
+
output_msg = f"**{msg_player or 'GPT'}**: {msg}\nGuessed by: {', '.join(player for player, guess in self.player_guess.items() if guess == msg_player)}"
|
94 |
+
if msg_player == player_name:
|
95 |
+
formatted_chat.append([output_msg, None])
|
96 |
+
else:
|
97 |
+
formatted_chat.append([None, output_msg])
|
98 |
+
return formatted_chat
|
99 |
+
|
100 |
+
def add_player(self, player_name, player_prompt):
|
101 |
+
with self.lock:
|
102 |
+
self.players.append(player_name)
|
103 |
+
self.prompts.append(player_prompt)
|
104 |
+
self.player_status[player_name] = None
|
105 |
+
self.player_scores[player_name] = 0
|
106 |
+
if len(self.players) == 1:
|
107 |
+
self.command = f"You have entered the game."
|
108 |
+
else:
|
109 |
+
self.command = f"{', '.join(self.players[:-1])} and {self.players[-1]} are in this room."
|
110 |
+
self.update()
|
111 |
+
|
112 |
+
def add_chat(self, player, message):
|
113 |
+
with self.lock:
|
114 |
+
self.player_status[player] = "Submitted"
|
115 |
+
self.responses[player] = message
|
116 |
+
|
117 |
+
def select_chat(self, player, index):
|
118 |
+
with self.lock:
|
119 |
+
if self.stage != "COLLECTING_VOTES":
|
120 |
+
return
|
121 |
+
index = index - 1
|
122 |
+
selected_player = self.response_list[index][0]
|
123 |
+
self.player_guess[player] = selected_player
|
124 |
+
self.player_status[player] = "Voted"
|
125 |
+
|
126 |
+
|
127 |
+
def new_game(room_name):
|
128 |
+
with all_games_lock:
|
129 |
+
if room_name in games:
|
130 |
+
game = games[room_name]
|
131 |
+
return game
|
132 |
+
return Game(room_name)
|
133 |
+
|
134 |
+
|
135 |
+
def game_thread():
|
136 |
+
while True:
|
137 |
+
now = time.time()
|
138 |
+
for room_name, game in games.items():
|
139 |
+
if not game.started or game.complete:
|
140 |
+
continue
|
141 |
+
with game.lock:
|
142 |
+
if game.stage == "START":
|
143 |
+
prompt = game.prompts[game.prompts_completed]
|
144 |
+
game.command = (
|
145 |
+
f"**{game.players[game.prompts_completed]}**: {prompt}"
|
146 |
+
)
|
147 |
+
game.input_allowed = True
|
148 |
+
game.player_status = {player: None for player in game.players}
|
149 |
+
game.player_guess = {player: None for player in game.players}
|
150 |
+
game.ai_answer = ai_response(prompt)
|
151 |
+
game.stage = "COLLECTING_RESPONSES"
|
152 |
+
game.responses = {}
|
153 |
+
game.stage_start_time = now
|
154 |
+
game.total_stage_time = TIME_TO_SUBMIT
|
155 |
+
game.stage_time_remaining = TIME_TO_SUBMIT
|
156 |
+
game.update()
|
157 |
+
|
158 |
+
stage_time_remaining = int(
|
159 |
+
game.total_stage_time - (now - game.stage_start_time)
|
160 |
+
)
|
161 |
+
if stage_time_remaining != game.stage_time_remaining:
|
162 |
+
game.stage_time_remaining = stage_time_remaining
|
163 |
+
game.update()
|
164 |
+
out_of_time = stage_time_remaining <= 0
|
165 |
+
|
166 |
+
if game.stage == "COLLECTING_RESPONSES":
|
167 |
+
if out_of_time or all(
|
168 |
+
val == "Submitted" for val in game.player_status.values()
|
169 |
+
):
|
170 |
+
game.stage = "COLLECTING_VOTES"
|
171 |
+
game.stage_start_time = now
|
172 |
+
game.total_stage_time = TIME_TO_VOTE
|
173 |
+
game.command = "Select the AI response!"
|
174 |
+
game.player_status = {player: None for player in game.players}
|
175 |
+
game.response_list = list(game.responses.items())
|
176 |
+
game.input_allowed = False
|
177 |
+
ai_answer = (None, game.ai_answer)
|
178 |
+
game.response_list.append(ai_answer)
|
179 |
+
random.shuffle(game.response_list)
|
180 |
+
game.ai_response_index = game.response_list.index(ai_answer)
|
181 |
+
game.update()
|
182 |
+
|
183 |
+
if game.stage == "COLLECTING_VOTES":
|
184 |
+
if out_of_time or all(
|
185 |
+
val == "Voted" for val in game.player_status.values()
|
186 |
+
):
|
187 |
+
game.stage = "REVEALING"
|
188 |
+
game.command = "Here's the results!"
|
189 |
+
game.stage_start_time = now
|
190 |
+
game.total_stage_time = TIME_TO_REVEAL
|
191 |
+
for player, guess in game.player_guess.items():
|
192 |
+
if guess == None:
|
193 |
+
game.player_scores[player] += GUESS_AI_PTS
|
194 |
+
else:
|
195 |
+
game.player_scores[guess] += GUESSED_AS_AI_PTS
|
196 |
+
game.update()
|
197 |
+
|
198 |
+
if game.stage == "REVEALING":
|
199 |
+
if out_of_time:
|
200 |
+
game.stage = "START"
|
201 |
+
game.prompts_completed += 1
|
202 |
+
if game.prompts_completed == len(game.players):
|
203 |
+
game.complete = True
|
204 |
+
game.command = f"Game complete! Winners: {', '.join(player for player, score in game.player_scores.items() if score == max(game.player_scores.values()))}"
|
205 |
+
game.update()
|
206 |
+
|
207 |
+
time.sleep(0.1)
|
208 |
+
|
209 |
+
|
210 |
+
thread = threading.Thread(target=game_thread)
|
211 |
+
thread.daemon = True
|
212 |
+
thread.start()
|
prompt.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
Return a brief response around 20 words for the following prompt:
|
2 |
+
|
3 |
+
{}
|
requirements.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
openai
|
run.py
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import random
|
3 |
+
from game_manager import games, new_game
|
4 |
+
import uuid
|
5 |
+
|
6 |
+
with gr.Blocks(css="style.css") as app:
|
7 |
+
game_var = gr.Variable()
|
8 |
+
last_update = gr.Variable(0)
|
9 |
+
|
10 |
+
with gr.Column() as opening:
|
11 |
+
gr.Markdown("# GPT Who?")
|
12 |
+
gr.Markdown(
|
13 |
+
"""
|
14 |
+
Welcome to 'GPT Who?', a game played with multiple humans and one AI. Here are the rules:
|
15 |
+
|
16 |
+
- Every player in a room will submit a prompt.
|
17 |
+
- For every prompt, there will be a round. Every player submits a response to the prompt of the round.
|
18 |
+
- GPT will also respond to the prompt.
|
19 |
+
- Every player will vote on which response they think is the AI's response.
|
20 |
+
- Player's get 2 points for guessing which response was GPT, as well 1 point for every player that thought they were GPT.
|
21 |
+
|
22 |
+
That's it!
|
23 |
+
"""
|
24 |
+
)
|
25 |
+
|
26 |
+
player_name = gr.Text(label="Player Name")
|
27 |
+
player_prompt = gr.Text(label="Prompt", info="Pick something fun, like 'Write a joke involving a banana.' or 'Why are children so dumb?'.")
|
28 |
+
random_room_btn = gr.Button("Join Random Room!")
|
29 |
+
with gr.Row():
|
30 |
+
room_name = gr.Text(label="Room Name")
|
31 |
+
open_room_btn = gr.Button("Create / Join Room!")
|
32 |
+
|
33 |
+
with gr.Column(visible=False) as game_col:
|
34 |
+
chat_history = gr.Chatbot(label="Game")
|
35 |
+
start_game_btn = gr.Button("Start Game", visible=False)
|
36 |
+
with gr.Row(visible=False) as text_row:
|
37 |
+
text_input = gr.Textbox(label="Input")
|
38 |
+
with gr.Row():
|
39 |
+
player_states = gr.DataFrame(
|
40 |
+
label="Players", headers=["Player", "Status", "Score"]
|
41 |
+
)
|
42 |
+
time_remaining = gr.Label(label="Time Remaining", elem_id="time_remaining")
|
43 |
+
|
44 |
+
def add_submission(player, text, game):
|
45 |
+
game.add_chat(player, text)
|
46 |
+
return {
|
47 |
+
text_input: gr.Textbox.update(value=""),
|
48 |
+
}
|
49 |
+
|
50 |
+
text_input.submit(add_submission, [player_name, text_input, game_var], [text_input])
|
51 |
+
|
52 |
+
def select_ai_response(game, player, selected: gr.SelectData):
|
53 |
+
if selected.index[0] != 0 and selected.index[1] == 1:
|
54 |
+
game.select_chat(player, selected.index[0])
|
55 |
+
|
56 |
+
chat_history.select(select_ai_response, [game_var, player_name], None)
|
57 |
+
|
58 |
+
def open_room(data):
|
59 |
+
game = new_game(data[room_name])
|
60 |
+
game.add_player(data[player_name], data[player_prompt])
|
61 |
+
return {
|
62 |
+
opening: gr.Column.update(visible=False),
|
63 |
+
game_col: gr.Column.update(visible=True),
|
64 |
+
game_var: game,
|
65 |
+
chat_history: gr.Chatbot.update(label=data[room_name]),
|
66 |
+
start_game_btn: gr.Button.update(visible=len(game.players) == 1),
|
67 |
+
}
|
68 |
+
|
69 |
+
def random_room():
|
70 |
+
for game in random.sample(list(games.values()), len(games)):
|
71 |
+
if not game.started:
|
72 |
+
return game.room_name
|
73 |
+
return "room_" + str(uuid.uuid4())[:8]
|
74 |
+
|
75 |
+
def update_game(data):
|
76 |
+
game = data[game_var]
|
77 |
+
if data[last_update] == game.last_update_index:
|
78 |
+
return {chat_history: gr.skip()}
|
79 |
+
else:
|
80 |
+
return {
|
81 |
+
chat_history: game.format_chat(data[player_name]),
|
82 |
+
text_row: gr.Row.update(visible=game.input_allowed),
|
83 |
+
player_states: game.get_player_state(),
|
84 |
+
time_remaining: game.stage_time_remaining,
|
85 |
+
}
|
86 |
+
|
87 |
+
def start_game_on(evt):
|
88 |
+
evt(
|
89 |
+
open_room,
|
90 |
+
{room_name, player_name, player_prompt},
|
91 |
+
{opening, game_col, game_var, chat_history, start_game_btn},
|
92 |
+
).then(
|
93 |
+
update_game,
|
94 |
+
{game_var, last_update, player_name},
|
95 |
+
{chat_history, text_row, player_states, time_remaining},
|
96 |
+
every=1,
|
97 |
+
)
|
98 |
+
|
99 |
+
start_game_on(open_room_btn.click)
|
100 |
+
start_game_on(random_room_btn.click(random_room, None, room_name).success)
|
101 |
+
|
102 |
+
def start_game_click(data):
|
103 |
+
game = data[game_var]
|
104 |
+
game.start()
|
105 |
+
return {
|
106 |
+
start_game_btn: gr.Button.update(visible=False),
|
107 |
+
}
|
108 |
+
|
109 |
+
start_game_btn.click(start_game_click, {game_var}, {start_game_btn, text_input})
|
110 |
+
|
111 |
+
|
112 |
+
app.queue().launch()
|
style.css
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.generating {
|
2 |
+
border: none !important;
|
3 |
+
}
|
4 |
+
#time_remaining {
|
5 |
+
display: flex;
|
6 |
+
justify-content: center;
|
7 |
+
align-items: center;
|
8 |
+
}
|