bstraehle commited on
Commit
ed306c8
1 Parent(s): 7aa6874

Create multi_agent.py

Browse files
Files changed (1) hide show
  1. multi_agent.py +178 -0
multi_agent.py ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import chess, chess.svg, math
2
+ from autogen import ConversableAgent, register_function
3
+ from typing_extensions import Annotated
4
+
5
+ board = None
6
+ board_svgs = None
7
+ made_move = None
8
+
9
+ def get_legal_moves() -> Annotated[str, "A list of legal moves in UCI format"]:
10
+ return "Possible moves are: " + ",".join(
11
+ [str(move) for move in board.legal_moves]
12
+ )
13
+
14
+ def make_move(move: Annotated[str, "A move in UCI format."]) -> Annotated[str, "Result of the move."]:
15
+ move = chess.Move.from_uci(move)
16
+ board.push_uci(str(move))
17
+ global made_move
18
+ made_move = True
19
+
20
+ board_svgs.append(chess.svg.board(
21
+ board,
22
+ arrows=[(move.from_square, move.to_square)],
23
+ fill={move.from_square: "gray"},
24
+ size=250
25
+ ))
26
+
27
+ piece = board.piece_at(move.to_square)
28
+ piece_symbol = piece.unicode_symbol()
29
+ piece_name = (
30
+ chess.piece_name(piece.piece_type).capitalize()
31
+ if piece_symbol.isupper()
32
+ else chess.piece_name(piece.piece_type)
33
+ )
34
+
35
+ return f"Moved {piece_name} ({piece_symbol}) from "\
36
+ f"{chess.SQUARE_NAMES[move.from_square]} to "\
37
+ f"{chess.SQUARE_NAMES[move.to_square]}."
38
+
39
+ def check_made_move(msg):
40
+ global made_move
41
+
42
+ if made_move:
43
+ made_move = False
44
+ return True
45
+ else:
46
+ return False
47
+
48
+ def get_num_turns(num_moves):
49
+ # Each turn includes two moves (one by each player)
50
+ # The first move by player black kicks off the chat
51
+ # The first move by player white starts the game
52
+
53
+ num_turns = math.ceil(num_moves / 2)
54
+
55
+ if num_moves % 2 == 0:
56
+ num_turns += 1
57
+
58
+ return num_turns
59
+
60
+ def initialize():
61
+ global board, board_svgs, made_move
62
+ board = chess.Board()
63
+ board_svgs = []
64
+ made_move = False
65
+
66
+ def run_multi_agent(llm_white, llm_black, num_moves):
67
+ initialize()
68
+
69
+ llm_config_white = {"model": llm_white}
70
+ llm_config_black = {"model": llm_black}
71
+
72
+ board_proxy = ConversableAgent(
73
+ name="Board Proxy",
74
+ llm_config=False,
75
+ is_termination_msg=check_made_move,
76
+ default_auto_reply="Please make a move.",
77
+ human_input_mode="NEVER",
78
+ )
79
+
80
+ player_white = ConversableAgent(
81
+ name="Player White",
82
+ system_message="You are a chess Grandmaster and you play as white. "
83
+ "First call get_legal_moves(), to get a list of legal moves. "
84
+ "Then call make_move(move) to make a legal move. "
85
+ "Analyze the move in 3 bullet points. Respond in format **Analysis:** move in UCI format, unordered list.",
86
+ llm_config=llm_config_white,
87
+ )
88
+
89
+ player_black = ConversableAgent(
90
+ name="Player Black",
91
+ system_message="You are a chess Grandmaster and you play as black. "
92
+ "First call get_legal_moves(), to get a list of legal moves. "
93
+ "Then call make_move(move) to make a legal move. "
94
+ "Analyze the move in 3 bullet points. Respond in format **Analysis:** move in UCI format, unordered list.",
95
+ llm_config=llm_config_black,
96
+ )
97
+
98
+ for caller in [player_white, player_black]:
99
+ register_function(
100
+ get_legal_moves,
101
+ caller=caller,
102
+ executor=board_proxy,
103
+ name="get_legal_moves",
104
+ description="Call this tool to get legal moves.",
105
+ )
106
+
107
+ register_function(
108
+ make_move,
109
+ caller=caller,
110
+ executor=board_proxy,
111
+ name="make_move",
112
+ description="Call this tool to make a move.",
113
+ )
114
+
115
+ player_white.register_nested_chats(
116
+ trigger=player_black,
117
+ chat_queue=[
118
+ {
119
+ "sender": board_proxy,
120
+ "recipient": player_white,
121
+ "summary_method": "last_msg",
122
+ "silent": False,
123
+ }
124
+ ],
125
+ )
126
+
127
+ player_black.register_nested_chats(
128
+ trigger=player_white,
129
+ chat_queue=[
130
+ {
131
+ "sender": board_proxy,
132
+ "recipient": player_black,
133
+ "summary_method": "last_msg",
134
+ "silent": False,
135
+ }
136
+ ],
137
+ )
138
+
139
+ chat_result = None
140
+ chat_history = []
141
+
142
+ try:
143
+ chat_result = player_black.initiate_chat(
144
+ player_white,
145
+ message="Let's play chess!",
146
+ max_turns=get_num_turns(num_moves),
147
+ verbose=True
148
+ )
149
+ except Exception as e:
150
+ print(f"Error: {e}")
151
+ finally:
152
+ if chat_result != None:
153
+ chat_history = chat_result.chat_history
154
+
155
+ result = ""
156
+ num_move = 0
157
+
158
+ for chat in chat_history:
159
+ player = ""
160
+
161
+ if num_move % 2 == 0:
162
+ player = "Player Black"
163
+ else:
164
+ player = "Player White"
165
+
166
+ if num_move > 0:
167
+ result += f"**{player}, Move {num_move}**<br>{chat.get('content')}<br>{board_svgs[num_move - 1]}<br><br>"
168
+
169
+ num_move += 1
170
+
171
+ if num_moves % 2 == 0 and num_move == num_moves + 1:
172
+ break
173
+
174
+ #print("===")
175
+ #print(result)
176
+ #print("===")
177
+
178
+ return result