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 |
+
}
|