final changes

This commit is contained in:
Madhu 2025-01-14 22:29:10 +05:30
parent 1df6d6d62f
commit d47f8d479d
3 changed files with 73 additions and 76 deletions

View file

@ -2,7 +2,7 @@
This is a simple Chess game that uses an AI agents - Player black and player white to play the game. There's also a board proxy agent to execute the tools and manage the game. It is important to use a board proxy as a non-LLM "guard rail" to ensure the game is played correctly and to prevent agents from making illegal moves.
Two agents (player_white and player_black) are initialized using the OpenAI API key. These agents are configured to play chess as white and black, respectively.
Two agents (agent_white and agent_black) are initialized using the OpenAI API key. These agents are configured to play chess as white and black, respectively.
A board_proxy agent is created to manage the board state and validate moves.
Functions (make_move and available_moves) are registered with the agents to allow them to interact with the board.
@ -29,10 +29,3 @@ pip install -r requirements.txt
streamlit run ai_chess_agents.py
```
## Requirements
- autogen
- numpy
- openai
- streamlit
- chess

View file

@ -3,7 +3,6 @@ import chess.svg
import streamlit as st
from autogen import ConversableAgent, register_function
# Initialize session state for the OpenAI API key and game state
if "openai_api_key" not in st.session_state:
st.session_state.openai_api_key = None
if "board" not in st.session_state:
@ -14,49 +13,64 @@ if "board_svg" not in st.session_state:
st.session_state.board_svg = None
if "move_history" not in st.session_state:
st.session_state.move_history = []
if "max_turns" not in st.session_state:
st.session_state.max_turns = 5
# Streamlit sidebar for OpenAI API key input
st.sidebar.title("Chess Agent Configuration")
openai_api_key = st.sidebar.text_input("Enter your OpenAI API key:", type="password")
if openai_api_key:
st.session_state.openai_api_key = openai_api_key
st.sidebar.success("API key saved!")
# Function to get legal moves
st.sidebar.info("""
For a complete chess game with potential checkmate, it would take max_turns > 200 approximately.
However, this will consume significant API credits and a lot of time.
For demo purposes, using 5-10 turns is recommended.
""")
max_turns_input = st.sidebar.number_input(
"Enter the number of turns (max_turns):",
min_value=1,
max_value=1000,
value=st.session_state.max_turns,
step=1
)
if max_turns_input:
st.session_state.max_turns = max_turns_input
st.sidebar.success(f"Max turns of total chess moves set to {st.session_state.max_turns}!")
st.title("Chess with AutoGen Agents")
def available_moves() -> str:
available_moves = [str(move) for move in st.session_state.board.legal_moves]
return "Available moves are: " + ",".join(available_moves)
# Function to make a move
def make_move(move: str) -> str:
def execute_move(move: str) -> str:
try:
chess_move = chess.Move.from_uci(move)
if chess_move not in st.session_state.board.legal_moves:
return f"Invalid move: {move}. Please call get_legal_moves() to see valid moves."
return f"Invalid move: {move}. Please call available_moves() to see valid moves."
st.session_state.board.push(chess_move)
st.session_state.made_move = True
# Render board visualization
board_svg = chess.svg.board(
st.session_state.board,
arrows=[(chess_move.from_square, chess_move.to_square)],
fill={chess_move.from_square: "gray"},
size=400
)
st.session_state.board_svg = board_svg # Save SVG to session state
st.session_state.move_history.append(board_svg) # Save move history
st.session_state.board_svg = board_svg
st.session_state.move_history.append(board_svg)
# Get moved piece details
moved_piece = st.session_state.board.piece_at(chess_move.to_square)
piece_unicode = moved_piece.unicode_symbol()
piece_type_name = chess.piece_name(moved_piece.piece_type)
piece_name = piece_type_name.capitalize() if piece_unicode.isupper() else piece_type_name
# Build move description
move_desc = f"Moved {piece_name} ({piece_unicode}) from {chess.SQUARE_NAMES[chess_move.from_square]} to {chess.SQUARE_NAMES[chess_move.to_square]}."
# Check game state
if st.session_state.board.is_checkmate():
winner = 'White' if st.session_state.board.turn == chess.BLACK else 'Black'
move_desc += f"\nCheckmate! {winner} wins!"
@ -71,7 +85,6 @@ def make_move(move: str) -> str:
except ValueError:
return f"Invalid move format: {move}. Please use UCI format (e.g., 'e2e4')."
# Check if the player has made a move, and reset the flag if move is made.
def check_made_move(msg):
if st.session_state.made_move:
st.session_state.made_move = False
@ -79,119 +92,112 @@ def check_made_move(msg):
else:
return False
# Initialize players and proxy agent if API key is provided
if st.session_state.openai_api_key:
try:
player_white_config_list = [
agent_white_config_list = [
{
"model": "gpt-4o-mini",
"api_key": st.session_state.openai_api_key,
},
]
player_black_config_list = [
agent_black_config_list = [
{
"model": "gpt-4o-mini",
"api_key": st.session_state.openai_api_key,
},
]
player_white = ConversableAgent(
name="Player_White",
agent_white = ConversableAgent(
name="Agent_White",
system_message="You are a professional chess player and you play as white. "
"First call get_legal_moves() first, to get list of legal moves. "
"Then call make_move(move) to make a move.",
llm_config={"config_list": player_white_config_list, "cache_seed": None},
"First call available_moves() first, to get list of legal moves. "
"Then call execute_move(move) to make a move.",
llm_config={"config_list": agent_white_config_list, "cache_seed": None},
)
player_black = ConversableAgent(
name="Player_Black",
agent_black = ConversableAgent(
name="Agent_Black",
system_message="You are a professional chess player and you play as black. "
"First call get_legal_moves() first, to get list of legal moves. "
"Then call make_move(move) to make a move.",
llm_config={"config_list": player_black_config_list, "cache_seed": None},
"First call available_moves() first, to get list of legal moves. "
"Then call execute_move(move) to make a move.",
llm_config={"config_list": agent_black_config_list, "cache_seed": None},
)
# Proxy agent to manage the board and validate moves
board_proxy = ConversableAgent(
name="Board_Proxy",
game_master = ConversableAgent(
name="Game_Master",
llm_config=False,
is_termination_msg=check_made_move,
default_auto_reply="Please make a move.",
human_input_mode="NEVER",
)
# Register functions for both players
register_function(
make_move,
caller=player_white,
executor=board_proxy,
name="make_move",
execute_move,
caller=agent_white,
executor=game_master,
name="execute_move",
description="Call this tool to make a move.",
)
register_function(
available_moves,
caller=player_white,
executor=board_proxy,
caller=agent_white,
executor=game_master,
name="available_moves",
description="Get legal moves.",
)
register_function(
make_move,
caller=player_black,
executor=board_proxy,
name="make_move",
execute_move,
caller=agent_black,
executor=game_master,
name="execute_move",
description="Call this tool to make a move.",
)
register_function(
available_moves,
caller=player_black,
executor=board_proxy,
caller=agent_black,
executor=game_master,
name="available_moves",
description="Get legal moves.",
)
# Register nested chats for both players
player_white.register_nested_chats(
trigger=player_black,
agent_white.register_nested_chats(
trigger=agent_black,
chat_queue=[
{
"sender": board_proxy,
"recipient": player_white,
"sender": game_master,
"recipient": agent_white,
"summary_method": "last_msg",
}
],
)
player_black.register_nested_chats(
trigger=player_white,
agent_black.register_nested_chats(
trigger=agent_white,
chat_queue=[
{
"sender": board_proxy,
"recipient": player_black,
"sender": game_master,
"recipient": agent_black,
"summary_method": "last_msg",
}
],
)
# Streamlit UI for playing the game
st.title("Chess with AG2 Agents")
st.info("""
This chess game is played between two AutoGen AI agents:
- **Player White**: A GPT-4o-mini powered chess player controlling white pieces
- **Player Black**: A GPT-4o-mini powered chess player controlling black pieces
This chess game is played between two AG2 AI agents:
- **Agent White**: A GPT-4o-mini powered chess player controlling white pieces
- **Agent Black**: A GPT-4o-mini powered chess player controlling black pieces
The game is managed by a **Board Proxy Agent** that:
The game is managed by a **Game Master** that:
- Validates all moves
- Updates the chess board
- Manages turn-taking between players
- Provides legal move information
""")
# Display the initial board state before the game starts
initial_board_svg = chess.svg.board(st.session_state.board, size=300)
st.subheader("Initial Board")
st.image(initial_board_svg)
@ -199,28 +205,26 @@ The game is managed by a **Board Proxy Agent** that:
if st.button("Start Game"):
st.session_state.board.reset()
st.session_state.made_move = False
st.session_state.move_history = [] # Reset move history
st.session_state.move_history = []
st.session_state.board_svg = chess.svg.board(st.session_state.board, size=300)
st.info("The AI agents will now play against each other. Each agent will analyze the board, "
"request legal moves, and make strategic decisions.")
"request legal moves from the Game Master (proxy agent), and make strategic decisions.")
st.success("You can view the interaction between the agents in the terminal output, after the turns between agents end, you get view all the chess board moves displayed below!")
st.write("Game started! White's turn.")
# Initiate the chat between Player_White and Board_Proxy
chat_result = player_black.initiate_chat(
recipient=player_white,
chat_result = agent_black.initiate_chat(
recipient=agent_white,
message="Let's play chess! You go first, its your move.",
max_turns=5,
max_turns=st.session_state.max_turns,
summary_method="reflection_with_llm"
)
st.markdown(chat_result.summary)
# Display the move history (boards for each move)
st.subheader("Move History")
for i, move_svg in enumerate(st.session_state.move_history):
st.write(f"Move {i + 1}")
st.image(move_svg)
# Reset Game button
if st.button("Reset Game"):
st.session_state.board.reset()
st.session_state.made_move = False

View file

@ -1,5 +1,5 @@
streamlit
python-chess
autogen
chess==1.11.1
autogen==0.6.1
cairosvg
pillow