Spaces:
Sleeping
Sleeping
"""Interface to play against the model. | |
""" | |
import huggingface_hub | |
import chess | |
import chess.svg | |
import uuid | |
import random | |
import wandb | |
import gradio as gr | |
from . import constants | |
model_name = "yp-edu/gpt2-stockfish-debug" | |
headers = {"X-Wait-For-Model": "true"} | |
client = huggingface_hub.InferenceClient( | |
model=model_name, headers=headers | |
) | |
inference_fn = client.text_generation | |
def plot_board( | |
board: chess.Board, | |
): | |
try: | |
last_move = board.peek() | |
arrows = [(last_move.from_square, last_move.to_square)] | |
except IndexError: | |
arrows = [] | |
if board.is_check(): | |
check = board.king(board.turn) | |
else: | |
check = None | |
svg_board = chess.svg.board( | |
board, | |
check=check, | |
size=350, | |
arrows=arrows, | |
) | |
id = str(uuid.uuid4()) | |
with open(f"{constants.FIGURE_DIRECTORY}/board_{id}.svg", "w") as f: | |
f.write(svg_board) | |
return f"{constants.FIGURE_DIRECTORY}/board_{id}.svg" | |
def render_board( | |
current_board: chess.Board, | |
): | |
fen = current_board.fen() | |
pgn = current_board.root().variation_san(current_board.move_stack) | |
image_board = plot_board(current_board) | |
return fen, pgn, image_board | |
def play_user_move( | |
uci_move: str, | |
current_board: chess.Board, | |
): | |
current_board.push_uci(uci_move) | |
return current_board | |
def play_ai_move( | |
current_board: chess.Board, | |
temperature: float = 0.1, | |
top_k: int = 3, | |
): | |
print(f"Playing AI move with temperature {temperature}") | |
uci_move = inference_fn( | |
prompt=f"FEN: {current_board.fen()}\nMOVE:", | |
temperature=temperature, | |
top_k=top_k, | |
) | |
current_board.push_uci(uci_move.strip()) | |
return current_board | |
def try_play_move( | |
username: str, | |
move_to_play: str, | |
current_board: chess.Board, | |
): | |
if current_board.is_game_over(): | |
gr.Warning("The game is already over") | |
return *render_board(current_board), current_board | |
try: | |
current_board = play_user_move(move_to_play, current_board) | |
if current_board.is_game_over(): | |
gr.Info(f"Congratulations, {username}!") | |
with wandb.init(project="gpt2-stockfish-debug", entity="yp-edu") as run: | |
run.log( | |
{ | |
"username": username, | |
"winin": current_board.fullmove_number, | |
"pgn": current_board.variation_san(current_board.move_stack), | |
} | |
) | |
run.finish() | |
return *render_board(current_board), current_board | |
except: | |
gr.Warning("Invalid move") | |
return *render_board(current_board), current_board | |
temperature_retries = [ | |
(i+1)/10 for i in range(10) | |
] | |
for temperature in temperature_retries: | |
try: | |
current_board = play_ai_move(current_board, temperature=temperature) | |
break | |
except: | |
gr.Warning(f"AI move failed with temperature {temperature}") | |
else: | |
gr.Warning("AI move failed with all temperatures") | |
current_board.pop() | |
return *render_board(current_board), current_board | |
with gr.Blocks() as interface: | |
with gr.Row(): | |
with gr.Column(): | |
username = gr.Textbox( | |
label="Username to record on leaderboard (should you win)", | |
lines=1, | |
max_lines=1, | |
value="", | |
) | |
current_fen = gr.Textbox( | |
label="Board FEN", | |
lines=1, | |
max_lines=1, | |
value=chess.STARTING_FEN, | |
) | |
current_pgn = gr.Textbox( | |
label="Action sequence", | |
lines=1, | |
value="", | |
) | |
with gr.Row(): | |
move_to_play = gr.Textbox( | |
label="Move to play (UCI)", | |
lines=1, | |
max_lines=1, | |
value="", | |
) | |
play_button = gr.Button("Play") | |
reset_button = gr.Button("Reset") | |
with gr.Column(): | |
image_board = gr.Image(label="Board") | |
static_inputs = [ | |
username, | |
move_to_play, | |
] | |
static_outputs = [ | |
current_fen, | |
current_pgn, | |
image_board, | |
] | |
is_ai_white = random.choice([True, False]) | |
init_board = chess.Board() | |
if is_ai_white: | |
init_board = play_ai_move(init_board) | |
state_board = gr.State(value=init_board) | |
play_button.click( | |
try_play_move, | |
inputs=[*static_inputs, state_board], | |
outputs=[*static_outputs, state_board], | |
) | |
def reset_board(): | |
board = chess.Board() | |
is_ai_white = random.choice([True, False]) | |
if is_ai_white: | |
board = play_ai_move(board) | |
return *render_board(board), board | |
reset_button.click( | |
reset_board, | |
outputs=[*static_outputs, state_board], | |
) | |
interface.load(render_board, inputs=[state_board], outputs=[*static_outputs]) | |