From d47f8d479d2b02c31962a30efc0c30445ac87b14 Mon Sep 17 00:00:00 2001 From: Madhu Date: Tue, 14 Jan 2025 22:29:10 +0530 Subject: [PATCH] final changes --- ai_agent_tutorials/ai_chess_game/README.md | 9 +- .../ai_chess_game/ai_chess_agents.py | 136 +++++++++--------- .../ai_chess_game/requirements.txt | 4 +- 3 files changed, 73 insertions(+), 76 deletions(-) diff --git a/ai_agent_tutorials/ai_chess_game/README.md b/ai_agent_tutorials/ai_chess_game/README.md index d1b841f..ae559f0 100644 --- a/ai_agent_tutorials/ai_chess_game/README.md +++ b/ai_agent_tutorials/ai_chess_game/README.md @@ -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 \ No newline at end of file diff --git a/ai_agent_tutorials/ai_chess_game/ai_chess_agents.py b/ai_agent_tutorials/ai_chess_game/ai_chess_agents.py index 0f179a0..b27f964 100644 --- a/ai_agent_tutorials/ai_chess_game/ai_chess_agents.py +++ b/ai_agent_tutorials/ai_chess_game/ai_chess_agents.py @@ -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 diff --git a/ai_agent_tutorials/ai_chess_game/requirements.txt b/ai_agent_tutorials/ai_chess_game/requirements.txt index 5e78602..7f38e3d 100644 --- a/ai_agent_tutorials/ai_chess_game/requirements.txt +++ b/ai_agent_tutorials/ai_chess_game/requirements.txt @@ -1,5 +1,5 @@ streamlit -python-chess -autogen +chess==1.11.1 +autogen==0.6.1 cairosvg pillow