chess-agent / app.py
czakop's picture
bump required version of chessboard component
402894f
import asyncio
import os
import chess
import gradio as gr
from gradio_chessboard import Chessboard
from langchain_core.messages import HumanMessage
from utils.helpers import call_agent, create_agent
from utils.tools import create_base_tools, create_mcp_tools
MODEL_DEFAULTS = {
"anthropic": {
"model_name": "claude-sonnet-4-20250514",
"provider": "anthropic",
"api_key": os.getenv("ANTHROPIC_API_KEY", ""),
},
"mistral": {
"model_name": "mistral-large-latest",
"provider": "mistralai",
"api_key": os.getenv("MISTRAL_API_KEY", ""),
},
"openai": {
"model_name": "gpt-4o",
"provider": "openai",
"api_key": os.getenv("OPENAI_API_KEY", ""),
},
}
async def main():
board = chess.Board()
base_tools = create_base_tools(board)
mcp_tools = await create_mcp_tools(
url="https://agents-mcp-hackathon-chess-mcp-server.hf.space/gradio_api/mcp/sse",
transport="sse",
)
async def chat_entrypoint(
fen, prompt, messages, model_name, model_provider, api_key
):
"""Entrypoint for the chat interaction."""
board.set_fen(fen)
messages.append(gr.ChatMessage(role="user", content=prompt))
yield messages, board.fen()
real_prompt = HumanMessage(
content=f"{prompt}\nCurrent board state: {board.fen()}"
)
agent = create_agent(
model_name, model_provider, api_key, base_tools + mcp_tools
)
async for messages in call_agent(agent, messages, real_prompt):
yield messages, board.fen()
async def move_entrypoint(fen, messages, model_name, model_provider, api_key):
"""Entrypoint for the chess move interaction."""
board.set_fen(fen)
messages.append(
gr.ChatMessage(
role="user",
content="Your turn! Make a move.",
)
)
yield messages, board.fen()
real_prompt = HumanMessage(
content=f"Make a move with {'white' if board.turn == chess.WHITE else 'black'}, current board state: {fen}. Use can use tools to analyze the position."
)
agent = create_agent(
model_name, model_provider, api_key, base_tools + mcp_tools
)
async for messages in call_agent(agent, messages, real_prompt):
yield messages, board.fen()
with gr.Blocks(fill_height=True) as chessagent:
gr.Markdown("# Play Chess with an AI Agent ♔ and see its thoughts 💭")
with gr.Row():
with gr.Column(min_width=500):
with gr.Row():
model_provider = gr.Dropdown(
choices=["Anthropic", "Mistral", "OpenAI"],
value="Anthropic",
label="Model Provider",
type="value",
interactive=True,
allow_custom_value=False,
)
model_name = gr.Textbox(
value=MODEL_DEFAULTS["anthropic"]["model_name"],
label="Model Name",
placeholder="Enter model name",
interactive=True,
)
api_key = gr.Textbox(
value=MODEL_DEFAULTS["anthropic"]["api_key"],
label="API Key",
placeholder="Enter your API key",
type="password",
interactive=True,
)
model_provider.change(
fn=lambda provider: MODEL_DEFAULTS[provider.lower()][
"model_name"
],
inputs=model_provider,
outputs=model_name,
)
model_provider.change(
fn=lambda provider: MODEL_DEFAULTS[provider.lower()]["api_key"],
inputs=model_provider,
outputs=api_key,
)
board_component = Chessboard(game_mode=True, label="Chess Board")
chatbot = gr.Chatbot(
type="messages",
label="Chess Agent",
avatar_images=(
"https://chessboardjs.com/img/chesspieces/wikipedia/wK.png",
"https://chessboardjs.com/img/chesspieces/wikipedia/bK.png",
),
min_height=650,
render=False,
)
board_component.move(
fn=move_entrypoint,
inputs=[
board_component,
chatbot,
model_name,
model_provider,
api_key,
],
outputs=[chatbot, board_component],
)
with gr.Column():
chatbot.render()
input_box = gr.Textbox(lines=1, label="Chat Message")
input_box.submit(
fn=chat_entrypoint,
inputs=[
board_component,
input_box,
chatbot,
model_name,
model_provider,
api_key,
],
outputs=[chatbot, board_component],
)
input_box.submit(lambda: "", None, [input_box], queue=False)
chessagent.launch()
if __name__ == "__main__":
asyncio.run(main())