elliottower commited on
Commit
4c2472a
1 Parent(s): ccb53cb

Update app.py to most recent chatarena version (#2)

Browse files

- Update app.py to most recent chatarena version (ed850c0872657469945611457a82087a1ce738d0)

Files changed (1) hide show
  1. app.py +307 -129
app.py CHANGED
@@ -1,14 +1,15 @@
1
- import re
2
  import json
3
- import gradio as gr
4
  from glob import glob
5
 
 
 
6
  from chatarena.arena import Arena, TooManyInvalidActions
7
  from chatarena.backends import BACKEND_REGISTRY
8
  from chatarena.backends.human import HumanBackendError
9
  from chatarena.config import ArenaConfig
 
10
  from chatarena.environments import ENV_REGISTRY
11
- from chatarena.database import log_arena, log_messages, SupabaseDB, supabase_available
12
  from chatarena.message import Message
13
 
14
  css = """#col-container {max-width: 90%; margin-left: auto; margin-right: auto; display: flex; flex-direction: column;}
@@ -41,9 +42,12 @@ def load_examples():
41
  # Load json config files from examples folder
42
  example_files = glob("examples/*.json")
43
  for example_file in example_files:
44
- with open(example_file, 'r') as f:
45
  example = json.load(f)
46
- example_configs[example["name"]] = example
 
 
 
47
  return example_configs
48
 
49
 
@@ -56,37 +60,108 @@ def get_moderator_components(visible=True):
56
  name = "Moderator"
57
  with gr.Row():
58
  with gr.Column():
59
- role_desc = gr.Textbox(label="Moderator role", lines=1, visible=visible, interactive=True,
60
- placeholder=f"Enter the role description for {name}")
61
- terminal_condition = gr.Textbox(show_label=False, lines=1, visible=visible, interactive=True,
62
- placeholder="Enter the end criteria for the conversation")
 
 
 
 
 
 
 
 
 
 
63
  with gr.Column():
64
- backend_type = gr.Dropdown(show_label=False, visible=visible, interactive=True,
65
- choices=list(BACKEND_REGISTRY.keys()), value=DEFAULT_BACKEND)
66
- with gr.Accordion(f"{name} Parameters", open=False, visible=visible) as accordion:
67
- temperature = gr.Slider(minimum=0, maximum=2.0, step=0.1, interactive=True, visible=visible,
68
- label=f"temperature", value=0.7)
69
- max_tokens = gr.Slider(minimum=10, maximum=500, step=10, interactive=True, visible=visible,
70
- label=f"max tokens", value=200)
71
-
72
- return [role_desc, terminal_condition, backend_type, accordion, temperature, max_tokens]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
 
75
  def get_player_components(name, visible):
76
  with gr.Row():
77
  with gr.Column():
78
- role_desc = gr.Textbox(label=name, lines=3, interactive=True, visible=visible,
79
- placeholder=f"Enter the role description for {name}")
 
 
 
 
 
 
 
 
 
 
 
 
80
  with gr.Column():
81
- backend_type = gr.Dropdown(show_label=False, choices=list(BACKEND_REGISTRY.keys()),
82
- interactive=True, visible=visible, value=DEFAULT_BACKEND)
83
- with gr.Accordion(f"{name} Parameters", open=False, visible=visible) as accordion:
84
- temperature = gr.Slider(minimum=0, maximum=2.0, step=0.1, interactive=True, visible=visible,
85
- label=f"temperature", value=0.7)
86
- max_tokens = gr.Slider(minimum=10, maximum=500, step=10, interactive=True, visible=visible,
87
- label=f"max tokens", value=200)
88
-
89
- return [role_desc, backend_type, accordion, temperature, max_tokens]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
 
92
  def get_empty_state():
@@ -98,19 +173,36 @@ with gr.Blocks(css=css) as demo:
98
  all_components = []
99
 
100
  with gr.Column(elem_id="col-container"):
101
- gr.Markdown("""# 🏟 ChatArena️<br>
102
- Prompting multiple AI agents to play games in a language-driven environment.
103
- **[Project Homepage](https://www.chatarena.org)**""", elem_id="header")
 
 
 
104
 
105
  with gr.Row():
106
- env_selector = gr.Dropdown(choices=list(ENV_REGISTRY.keys()), value=DEFAULT_ENV, interactive=True,
107
- label="Environment Type", show_label=True)
108
- example_selector = gr.Dropdown(choices=list(EXAMPLE_REGISTRY.keys()), interactive=True,
109
- label="Select Example", show_label=True)
 
 
 
 
 
 
 
 
 
110
 
111
  # Environment configuration
112
- env_desc_textbox = gr.Textbox(show_label=True, lines=2, visible=True, label="Environment Description",
113
- placeholder="Enter a description of a scenario or the game rules.")
 
 
 
 
 
114
 
115
  all_components += [env_selector, example_selector, env_desc_textbox]
116
 
@@ -118,14 +210,19 @@ Prompting multiple AI agents to play games in a language-driven environment.
118
  with gr.Column(elem_id="col-chatbox"):
119
  with gr.Tab("All", visible=True):
120
  chatbot = gr.Chatbot(
121
- elem_id="chatbox", visible=True, show_label=False)
 
122
 
123
  player_chatbots = []
124
  for i in range(MAX_NUM_PLAYERS):
125
  player_name = f"Player {i + 1}"
126
  with gr.Tab(player_name, visible=(i < DEFAULT_NUM_PLAYERS)):
127
- player_chatbot = gr.Chatbot(elem_id=f"chatbox-{i}", visible=i < DEFAULT_NUM_PLAYERS,
128
- label=player_name, show_label=False)
 
 
 
 
129
  player_chatbots.append(player_chatbot)
130
 
131
  all_components += [chatbot, *player_chatbots]
@@ -133,20 +230,29 @@ Prompting multiple AI agents to play games in a language-driven environment.
133
  with gr.Column(elem_id="col-config"): # Player Configuration
134
  # gr.Markdown("Player Configuration")
135
  parallel_checkbox = gr.Checkbox(
136
- label="Parallel Actions", value=False, visible=True)
 
137
  with gr.Accordion("Moderator", open=False, visible=True):
138
  moderator_components = get_moderator_components(True)
139
  all_components += [parallel_checkbox, *moderator_components]
140
 
141
  all_players_components, players_idx2comp = [], {}
142
  with gr.Blocks():
143
- num_player_slider = gr.Slider(2, MAX_NUM_PLAYERS, value=DEFAULT_NUM_PLAYERS, step=1,
144
- label="Number of players:")
 
 
 
 
 
145
  for i in range(MAX_NUM_PLAYERS):
146
  player_name = f"Player {i + 1}"
147
- with gr.Tab(player_name, visible=(i < DEFAULT_NUM_PLAYERS)) as tab:
 
 
148
  player_comps = get_player_components(
149
- player_name, visible=(i < DEFAULT_NUM_PLAYERS))
 
150
 
151
  players_idx2comp[i] = player_comps + [tab]
152
  all_players_components += player_comps + [tab]
@@ -160,20 +266,27 @@ Prompting multiple AI agents to play games in a language-driven environment.
160
  if i < k:
161
  for comp in players_idx2comp[i]:
162
  update_dict[comp] = gr.update(visible=True)
163
- update_dict[player_chatbots[i]
164
- ] = gr.update(visible=True)
165
  else:
166
  for comp in players_idx2comp[i]:
167
  update_dict[comp] = gr.update(visible=False)
168
- update_dict[player_chatbots[i]
169
- ] = gr.update(visible=False)
170
  return update_dict
171
 
172
  num_player_slider.change(
173
- variable_players, num_player_slider, all_players_components + player_chatbots)
174
-
175
- human_input_textbox = gr.Textbox(show_label=True, label="Human Input", lines=1, visible=True,
176
- interactive=True, placeholder="Enter your input here")
 
 
 
 
 
 
 
 
 
177
  with gr.Row():
178
  btn_step = gr.Button("Start")
179
  btn_restart = gr.Button("Clear")
@@ -183,13 +296,16 @@ Prompting multiple AI agents to play games in a language-driven environment.
183
  def _convert_to_chatbot_output(all_messages, display_recv=False):
184
  chatbot_output = []
185
  for i, message in enumerate(all_messages):
186
- agent_name, msg, recv = message.agent_name, message.content, str(
187
- message.visible_to)
188
- # Preprocess message for chatbot output
189
- new_msg = re.sub(r'\n+', '<br>', msg.strip())
 
 
 
 
190
  if display_recv:
191
- # Add role to the message
192
- new_msg = f"**{agent_name} (-> {recv})**: {new_msg}"
193
  else:
194
  new_msg = f"**{agent_name}**: {new_msg}"
195
 
@@ -206,26 +322,37 @@ Prompting multiple AI agents to play games in a language-driven environment.
206
  num_players = all_comps[num_player_slider]
207
  player_configs = []
208
  for i in range(num_players):
209
- player_name = f"Player {i + 1}"
210
- role_desc, backend_type, temperature, max_tokens = [
211
- all_comps[c] for c in players_idx2comp[i] if not isinstance(c, (gr.Accordion, gr.Tab))]
 
 
212
  player_config = {
213
- "name": player_name,
214
  "role_desc": role_desc,
215
  "global_prompt": env_desc,
216
  "backend": {
217
  "backend_type": backend_type,
218
  "temperature": temperature,
219
- "max_tokens": max_tokens
220
- }
221
  }
222
  player_configs.append(player_config)
223
 
224
  # Initialize the environment
225
  env_type = all_comps[env_selector]
226
  # Get moderator config
227
- mod_role_desc, mod_terminal_condition, moderator_backend_type, mod_temp, mod_max_tokens = [
228
- all_comps[c] for c in moderator_components if not isinstance(c, (gr.Accordion, gr.Tab))]
 
 
 
 
 
 
 
 
 
229
  moderator_config = {
230
  "role_desc": mod_role_desc,
231
  "global_prompt": env_desc,
@@ -233,25 +360,26 @@ Prompting multiple AI agents to play games in a language-driven environment.
233
  "backend": {
234
  "backend_type": moderator_backend_type,
235
  "temperature": mod_temp,
236
- "max_tokens": mod_max_tokens
237
- }
238
  }
239
  env_config = {
240
  "env_type": env_type,
241
  "parallel": all_comps[parallel_checkbox],
242
  "moderator": moderator_config,
243
  "moderator_visibility": "all",
244
- "moderator_period": "turn"
245
  }
246
 
247
  # arena_config = {"players": player_configs, "environment": env_config}
248
- arena_config = ArenaConfig(
249
- players=player_configs, environment=env_config)
250
  return arena_config
251
 
252
  def step_game(all_comps: dict):
253
- yield {btn_step: gr.update(value="Running...", interactive=False),
254
- btn_restart: gr.update(interactive=False)}
 
 
255
 
256
  cur_state = all_comps[state]
257
 
@@ -274,30 +402,43 @@ Prompting multiple AI agents to play games in a language-driven environment.
274
  timestep = None # Failed to get human input
275
  else:
276
  timestep = arena.environment.step(e.agent_name, human_input)
277
- except TooManyInvalidActions as e:
278
  timestep = arena.current_timestep
279
  timestep.observation.append(
280
- Message("System", "Too many invalid actions. Game over.", turn=-1, visible_to="all"))
 
 
 
 
 
 
281
  timestep.terminal = True
282
 
283
  if timestep is None:
284
- yield {human_input_textbox: gr.update(value="", placeholder="Please enter a valid input"),
285
- btn_step: gr.update(value="Next Step", interactive=True),
286
- btn_restart: gr.update(interactive=True)}
 
 
 
 
287
  else:
288
  all_messages = timestep.observation # user sees what the moderator sees
289
  log_messages(arena, all_messages, database=DB)
290
 
291
- chatbot_output = _convert_to_chatbot_output(
292
- all_messages, display_recv=True)
293
- update_dict = {human_input_textbox: gr.Textbox.update(value=""),
294
- chatbot: chatbot_output,
295
- btn_step: gr.update(value="Next Step", interactive=not timestep.terminal),
296
- btn_restart: gr.update(interactive=True), state: cur_state}
 
 
 
 
297
  # Get the visible messages for each player
298
  for i, player in enumerate(arena.players):
299
- player_messages = arena.environment.get_observation(
300
- player.name)
301
  player_output = _convert_to_chatbot_output(player_messages)
302
  # Update the player's chatbot output
303
  update_dict[player_chatbots[i]] = player_output
@@ -310,89 +451,126 @@ Prompting multiple AI agents to play games in a language-driven environment.
310
  def restart_game(all_comps: dict):
311
  cur_state = all_comps[state]
312
  cur_state["arena"] = None
313
- yield {chatbot: [], btn_restart: gr.update(interactive=False),
314
- btn_step: gr.update(interactive=False), state: cur_state}
 
 
 
 
315
 
316
  arena_config = _create_arena_config_from_components(all_comps)
317
  arena = Arena.from_config(arena_config)
318
  log_arena(arena, database=DB)
319
  cur_state["arena"] = arena
320
 
321
- yield {btn_step: gr.update(value="Start", interactive=True),
322
- btn_restart: gr.update(interactive=True), state: cur_state}
 
 
 
323
 
324
  # Remove Accordion and Tab from the list of components
325
- all_components = [comp for comp in all_components if not isinstance(
326
- comp, (gr.Accordion, gr.Tab))]
 
327
 
328
  # If any of the Textbox, Slider, Checkbox, Dropdown, RadioButtons is changed, the Step button is disabled
329
  for comp in all_components:
 
330
  def _disable_step_button(state):
331
  if state["arena"] is not None:
332
  return gr.update(interactive=False)
333
  else:
334
  return gr.update()
335
 
336
- if isinstance(comp,
337
- (gr.Textbox, gr.Slider, gr.Checkbox, gr.Dropdown, gr.Radio)) and comp is not human_input_textbox:
 
 
 
 
338
  comp.change(_disable_step_button, state, btn_step)
339
 
340
- btn_step.click(step_game, set(all_components + [state]),
341
- [chatbot, *player_chatbots, btn_step, btn_restart, state, human_input_textbox])
342
- btn_restart.click(restart_game, set(all_components + [state]),
343
- [chatbot, *player_chatbots, btn_step, btn_restart, state, human_input_textbox])
 
 
 
 
 
 
344
 
345
  # If an example is selected, update the components
346
-
347
  def update_components_from_example(all_comps: dict):
348
  example_name = all_comps[example_selector]
349
  example_config = EXAMPLE_REGISTRY[example_name]
350
  update_dict = {}
351
 
352
  # Update the environment components
353
- env_config = example_config['environment']
354
- update_dict[env_desc_textbox] = gr.update(
355
- value=example_config['global_prompt'])
356
- update_dict[env_selector] = gr.update(value=env_config['env_type'])
357
- update_dict[parallel_checkbox] = gr.update(
358
- value=env_config['parallel'])
359
 
360
  # Update the moderator components
361
  if "moderator" in env_config:
362
- mod_role_desc, mod_terminal_condition, moderator_backend_type, mod_temp, mod_max_tokens = [
363
- c for c in moderator_components if not isinstance(c, (gr.Accordion, gr.Tab))
364
- ]
 
 
 
 
 
 
 
 
365
  update_dict[mod_role_desc] = gr.update(
366
- value=env_config['moderator']['role_desc'])
 
367
  update_dict[mod_terminal_condition] = gr.update(
368
- value=env_config['moderator']['terminal_condition'])
 
369
  update_dict[moderator_backend_type] = gr.update(
370
- value=env_config['moderator']['backend']['backend_type'])
 
371
  update_dict[mod_temp] = gr.update(
372
- value=env_config['moderator']['backend']['temperature'])
 
373
  update_dict[mod_max_tokens] = gr.update(
374
- value=env_config['moderator']['backend']['max_tokens'])
 
375
 
376
  # Update the player components
377
- update_dict[num_player_slider] = gr.update(
378
- value=len(example_config['players']))
379
- for i, player_config in enumerate(example_config['players']):
380
- role_desc, backend_type, temperature, max_tokens = [
381
- c for c in players_idx2comp[i] if not isinstance(c, (gr.Accordion, gr.Tab))
382
- ]
383
- update_dict[role_desc] = gr.update(
384
- value=player_config['role_desc'])
 
 
385
  update_dict[backend_type] = gr.update(
386
- value=player_config['backend']['backend_type'])
 
387
  update_dict[temperature] = gr.update(
388
- value=player_config['backend']['temperature'])
 
389
  update_dict[max_tokens] = gr.update(
390
- value=player_config['backend']['max_tokens'])
 
391
 
392
  return update_dict
393
 
394
- example_selector.change(update_components_from_example, set(
395
- all_components + [state]), all_components + [state])
 
 
 
396
 
397
  demo.queue()
398
- demo.launch(debug=DEBUG)
 
 
1
  import json
2
+ import re
3
  from glob import glob
4
 
5
+ import gradio as gr
6
+
7
  from chatarena.arena import Arena, TooManyInvalidActions
8
  from chatarena.backends import BACKEND_REGISTRY
9
  from chatarena.backends.human import HumanBackendError
10
  from chatarena.config import ArenaConfig
11
+ from chatarena.database import SupabaseDB, log_arena, log_messages, supabase_available
12
  from chatarena.environments import ENV_REGISTRY
 
13
  from chatarena.message import Message
14
 
15
  css = """#col-container {max-width: 90%; margin-left: auto; margin-right: auto; display: flex; flex-direction: column;}
 
42
  # Load json config files from examples folder
43
  example_files = glob("examples/*.json")
44
  for example_file in example_files:
45
+ with open(example_file, encoding="utf-8") as f:
46
  example = json.load(f)
47
+ try:
48
+ example_configs[example["name"]] = example
49
+ except KeyError:
50
+ print(f"Example {example_file} is missing a name field. Skipping.")
51
  return example_configs
52
 
53
 
 
60
  name = "Moderator"
61
  with gr.Row():
62
  with gr.Column():
63
+ role_desc = gr.Textbox(
64
+ label="Moderator role",
65
+ lines=1,
66
+ visible=visible,
67
+ interactive=True,
68
+ placeholder=f"Enter the role description for {name}",
69
+ )
70
+ terminal_condition = gr.Textbox(
71
+ show_label=False,
72
+ lines=1,
73
+ visible=visible,
74
+ interactive=True,
75
+ placeholder="Enter the termination criteria",
76
+ )
77
  with gr.Column():
78
+ backend_type = gr.Dropdown(
79
+ show_label=False,
80
+ visible=visible,
81
+ interactive=True,
82
+ choices=list(BACKEND_REGISTRY.keys()),
83
+ value=DEFAULT_BACKEND,
84
+ )
85
+ with gr.Accordion(
86
+ f"{name} Parameters", open=False, visible=visible
87
+ ) as accordion:
88
+ temperature = gr.Slider(
89
+ minimum=0,
90
+ maximum=2.0,
91
+ step=0.1,
92
+ interactive=True,
93
+ visible=visible,
94
+ label="temperature",
95
+ value=0.7,
96
+ )
97
+ max_tokens = gr.Slider(
98
+ minimum=10,
99
+ maximum=500,
100
+ step=10,
101
+ interactive=True,
102
+ visible=visible,
103
+ label="max tokens",
104
+ value=200,
105
+ )
106
+
107
+ return [
108
+ role_desc,
109
+ terminal_condition,
110
+ backend_type,
111
+ accordion,
112
+ temperature,
113
+ max_tokens,
114
+ ]
115
 
116
 
117
  def get_player_components(name, visible):
118
  with gr.Row():
119
  with gr.Column():
120
+ role_name = gr.Textbox(
121
+ line=1,
122
+ show_label=False,
123
+ interactive=True,
124
+ visible=visible,
125
+ placeholder=f"Player name for {name}",
126
+ )
127
+ role_desc = gr.Textbox(
128
+ lines=3,
129
+ show_label=False,
130
+ interactive=True,
131
+ visible=visible,
132
+ placeholder=f"Enter the role description for {name}",
133
+ )
134
  with gr.Column():
135
+ backend_type = gr.Dropdown(
136
+ show_label=False,
137
+ choices=list(BACKEND_REGISTRY.keys()),
138
+ interactive=True,
139
+ visible=visible,
140
+ value=DEFAULT_BACKEND,
141
+ )
142
+ with gr.Accordion(
143
+ f"{name} Parameters", open=False, visible=visible
144
+ ) as accordion:
145
+ temperature = gr.Slider(
146
+ minimum=0,
147
+ maximum=2.0,
148
+ step=0.1,
149
+ interactive=True,
150
+ visible=visible,
151
+ label="temperature",
152
+ value=0.7,
153
+ )
154
+ max_tokens = gr.Slider(
155
+ minimum=10,
156
+ maximum=500,
157
+ step=10,
158
+ interactive=True,
159
+ visible=visible,
160
+ label="max tokens",
161
+ value=200,
162
+ )
163
+
164
+ return [role_name, role_desc, backend_type, accordion, temperature, max_tokens]
165
 
166
 
167
  def get_empty_state():
 
173
  all_components = []
174
 
175
  with gr.Column(elem_id="col-container"):
176
+ gr.Markdown(
177
+ """# 🏟 ChatArena️<br>
178
+ Prompting multiple AI agents to play games in a language-driven environment.
179
+ **[Project Homepage](https://github.com/chatarena/chatarena)**""",
180
+ elem_id="header",
181
+ )
182
 
183
  with gr.Row():
184
+ env_selector = gr.Dropdown(
185
+ choices=list(ENV_REGISTRY.keys()),
186
+ value=DEFAULT_ENV,
187
+ interactive=True,
188
+ label="Environment Type",
189
+ show_label=True,
190
+ )
191
+ example_selector = gr.Dropdown(
192
+ choices=list(EXAMPLE_REGISTRY.keys()),
193
+ interactive=True,
194
+ label="Select Example",
195
+ show_label=True,
196
+ )
197
 
198
  # Environment configuration
199
+ env_desc_textbox = gr.Textbox(
200
+ show_label=True,
201
+ lines=2,
202
+ visible=True,
203
+ label="Environment Description",
204
+ placeholder="Enter a description of a scenario or the game rules.",
205
+ )
206
 
207
  all_components += [env_selector, example_selector, env_desc_textbox]
208
 
 
210
  with gr.Column(elem_id="col-chatbox"):
211
  with gr.Tab("All", visible=True):
212
  chatbot = gr.Chatbot(
213
+ elem_id="chatbox", visible=True, show_label=False
214
+ )
215
 
216
  player_chatbots = []
217
  for i in range(MAX_NUM_PLAYERS):
218
  player_name = f"Player {i + 1}"
219
  with gr.Tab(player_name, visible=(i < DEFAULT_NUM_PLAYERS)):
220
+ player_chatbot = gr.Chatbot(
221
+ elem_id=f"chatbox-{i}",
222
+ visible=i < DEFAULT_NUM_PLAYERS,
223
+ label=player_name,
224
+ show_label=False,
225
+ )
226
  player_chatbots.append(player_chatbot)
227
 
228
  all_components += [chatbot, *player_chatbots]
 
230
  with gr.Column(elem_id="col-config"): # Player Configuration
231
  # gr.Markdown("Player Configuration")
232
  parallel_checkbox = gr.Checkbox(
233
+ label="Parallel Actions", value=False, visible=True
234
+ )
235
  with gr.Accordion("Moderator", open=False, visible=True):
236
  moderator_components = get_moderator_components(True)
237
  all_components += [parallel_checkbox, *moderator_components]
238
 
239
  all_players_components, players_idx2comp = [], {}
240
  with gr.Blocks():
241
+ num_player_slider = gr.Slider(
242
+ 2,
243
+ MAX_NUM_PLAYERS,
244
+ value=DEFAULT_NUM_PLAYERS,
245
+ step=1,
246
+ label="Number of players:",
247
+ )
248
  for i in range(MAX_NUM_PLAYERS):
249
  player_name = f"Player {i + 1}"
250
+ with gr.Tab(
251
+ player_name, visible=(i < DEFAULT_NUM_PLAYERS)
252
+ ) as tab:
253
  player_comps = get_player_components(
254
+ player_name, visible=(i < DEFAULT_NUM_PLAYERS)
255
+ )
256
 
257
  players_idx2comp[i] = player_comps + [tab]
258
  all_players_components += player_comps + [tab]
 
266
  if i < k:
267
  for comp in players_idx2comp[i]:
268
  update_dict[comp] = gr.update(visible=True)
269
+ update_dict[player_chatbots[i]] = gr.update(visible=True)
 
270
  else:
271
  for comp in players_idx2comp[i]:
272
  update_dict[comp] = gr.update(visible=False)
273
+ update_dict[player_chatbots[i]] = gr.update(visible=False)
 
274
  return update_dict
275
 
276
  num_player_slider.change(
277
+ variable_players,
278
+ num_player_slider,
279
+ all_players_components + player_chatbots,
280
+ )
281
+
282
+ human_input_textbox = gr.Textbox(
283
+ show_label=True,
284
+ label="Human Input",
285
+ lines=1,
286
+ visible=True,
287
+ interactive=True,
288
+ placeholder="Enter your input here",
289
+ )
290
  with gr.Row():
291
  btn_step = gr.Button("Start")
292
  btn_restart = gr.Button("Clear")
 
296
  def _convert_to_chatbot_output(all_messages, display_recv=False):
297
  chatbot_output = []
298
  for i, message in enumerate(all_messages):
299
+ agent_name, msg, recv = (
300
+ message.agent_name,
301
+ message.content,
302
+ str(message.visible_to),
303
+ )
304
+ new_msg = re.sub(
305
+ r"\n+", "<br>", msg.strip()
306
+ ) # Preprocess message for chatbot output
307
  if display_recv:
308
+ new_msg = f"**{agent_name} (-> {recv})**: {new_msg}" # Add role to the message
 
309
  else:
310
  new_msg = f"**{agent_name}**: {new_msg}"
311
 
 
322
  num_players = all_comps[num_player_slider]
323
  player_configs = []
324
  for i in range(num_players):
325
+ role_name, role_desc, backend_type, temperature, max_tokens = (
326
+ all_comps[c]
327
+ for c in players_idx2comp[i]
328
+ if not isinstance(c, (gr.Accordion, gr.Tab))
329
+ )
330
  player_config = {
331
+ "name": role_name,
332
  "role_desc": role_desc,
333
  "global_prompt": env_desc,
334
  "backend": {
335
  "backend_type": backend_type,
336
  "temperature": temperature,
337
+ "max_tokens": max_tokens,
338
+ },
339
  }
340
  player_configs.append(player_config)
341
 
342
  # Initialize the environment
343
  env_type = all_comps[env_selector]
344
  # Get moderator config
345
+ (
346
+ mod_role_desc,
347
+ mod_terminal_condition,
348
+ moderator_backend_type,
349
+ mod_temp,
350
+ mod_max_tokens,
351
+ ) = (
352
+ all_comps[c]
353
+ for c in moderator_components
354
+ if not isinstance(c, (gr.Accordion, gr.Tab))
355
+ )
356
  moderator_config = {
357
  "role_desc": mod_role_desc,
358
  "global_prompt": env_desc,
 
360
  "backend": {
361
  "backend_type": moderator_backend_type,
362
  "temperature": mod_temp,
363
+ "max_tokens": mod_max_tokens,
364
+ },
365
  }
366
  env_config = {
367
  "env_type": env_type,
368
  "parallel": all_comps[parallel_checkbox],
369
  "moderator": moderator_config,
370
  "moderator_visibility": "all",
371
+ "moderator_period": None,
372
  }
373
 
374
  # arena_config = {"players": player_configs, "environment": env_config}
375
+ arena_config = ArenaConfig(players=player_configs, environment=env_config)
 
376
  return arena_config
377
 
378
  def step_game(all_comps: dict):
379
+ yield {
380
+ btn_step: gr.update(value="Running...", interactive=False),
381
+ btn_restart: gr.update(interactive=False),
382
+ }
383
 
384
  cur_state = all_comps[state]
385
 
 
402
  timestep = None # Failed to get human input
403
  else:
404
  timestep = arena.environment.step(e.agent_name, human_input)
405
+ except TooManyInvalidActions:
406
  timestep = arena.current_timestep
407
  timestep.observation.append(
408
+ Message(
409
+ "System",
410
+ "Too many invalid actions. Game over.",
411
+ turn=-1,
412
+ visible_to="all",
413
+ )
414
+ )
415
  timestep.terminal = True
416
 
417
  if timestep is None:
418
+ yield {
419
+ human_input_textbox: gr.update(
420
+ value="", placeholder="Please enter a valid input"
421
+ ),
422
+ btn_step: gr.update(value="Next Step", interactive=True),
423
+ btn_restart: gr.update(interactive=True),
424
+ }
425
  else:
426
  all_messages = timestep.observation # user sees what the moderator sees
427
  log_messages(arena, all_messages, database=DB)
428
 
429
+ chatbot_output = _convert_to_chatbot_output(all_messages, display_recv=True)
430
+ update_dict = {
431
+ human_input_textbox: gr.Textbox.update(value=""),
432
+ chatbot: chatbot_output,
433
+ btn_step: gr.update(
434
+ value="Next Step", interactive=not timestep.terminal
435
+ ),
436
+ btn_restart: gr.update(interactive=True),
437
+ state: cur_state,
438
+ }
439
  # Get the visible messages for each player
440
  for i, player in enumerate(arena.players):
441
+ player_messages = arena.environment.get_observation(player.name)
 
442
  player_output = _convert_to_chatbot_output(player_messages)
443
  # Update the player's chatbot output
444
  update_dict[player_chatbots[i]] = player_output
 
451
  def restart_game(all_comps: dict):
452
  cur_state = all_comps[state]
453
  cur_state["arena"] = None
454
+ yield {
455
+ chatbot: [],
456
+ btn_restart: gr.update(interactive=False),
457
+ btn_step: gr.update(interactive=False),
458
+ state: cur_state,
459
+ }
460
 
461
  arena_config = _create_arena_config_from_components(all_comps)
462
  arena = Arena.from_config(arena_config)
463
  log_arena(arena, database=DB)
464
  cur_state["arena"] = arena
465
 
466
+ yield {
467
+ btn_step: gr.update(value="Start", interactive=True),
468
+ btn_restart: gr.update(interactive=True),
469
+ state: cur_state,
470
+ }
471
 
472
  # Remove Accordion and Tab from the list of components
473
+ all_components = [
474
+ comp for comp in all_components if not isinstance(comp, (gr.Accordion, gr.Tab))
475
+ ]
476
 
477
  # If any of the Textbox, Slider, Checkbox, Dropdown, RadioButtons is changed, the Step button is disabled
478
  for comp in all_components:
479
+
480
  def _disable_step_button(state):
481
  if state["arena"] is not None:
482
  return gr.update(interactive=False)
483
  else:
484
  return gr.update()
485
 
486
+ if (
487
+ isinstance(
488
+ comp, (gr.Textbox, gr.Slider, gr.Checkbox, gr.Dropdown, gr.Radio)
489
+ )
490
+ and comp is not human_input_textbox
491
+ ):
492
  comp.change(_disable_step_button, state, btn_step)
493
 
494
+ btn_step.click(
495
+ step_game,
496
+ set(all_components + [state]),
497
+ [chatbot, *player_chatbots, btn_step, btn_restart, state, human_input_textbox],
498
+ )
499
+ btn_restart.click(
500
+ restart_game,
501
+ set(all_components + [state]),
502
+ [chatbot, *player_chatbots, btn_step, btn_restart, state, human_input_textbox],
503
+ )
504
 
505
  # If an example is selected, update the components
 
506
  def update_components_from_example(all_comps: dict):
507
  example_name = all_comps[example_selector]
508
  example_config = EXAMPLE_REGISTRY[example_name]
509
  update_dict = {}
510
 
511
  # Update the environment components
512
+ env_config = example_config["environment"]
513
+ update_dict[env_desc_textbox] = gr.update(value=example_config["global_prompt"])
514
+ update_dict[env_selector] = gr.update(value=env_config["env_type"])
515
+ update_dict[parallel_checkbox] = gr.update(value=env_config["parallel"])
 
 
516
 
517
  # Update the moderator components
518
  if "moderator" in env_config:
519
+ (
520
+ mod_role_desc,
521
+ mod_terminal_condition,
522
+ moderator_backend_type,
523
+ mod_temp,
524
+ mod_max_tokens,
525
+ ) = (
526
+ c
527
+ for c in moderator_components
528
+ if not isinstance(c, (gr.Accordion, gr.Tab))
529
+ )
530
  update_dict[mod_role_desc] = gr.update(
531
+ value=env_config["moderator"]["role_desc"]
532
+ )
533
  update_dict[mod_terminal_condition] = gr.update(
534
+ value=env_config["moderator"]["terminal_condition"]
535
+ )
536
  update_dict[moderator_backend_type] = gr.update(
537
+ value=env_config["moderator"]["backend"]["backend_type"]
538
+ )
539
  update_dict[mod_temp] = gr.update(
540
+ value=env_config["moderator"]["backend"]["temperature"]
541
+ )
542
  update_dict[mod_max_tokens] = gr.update(
543
+ value=env_config["moderator"]["backend"]["max_tokens"]
544
+ )
545
 
546
  # Update the player components
547
+ update_dict[num_player_slider] = gr.update(value=len(example_config["players"]))
548
+ for i, player_config in enumerate(example_config["players"]):
549
+ role_name, role_desc, backend_type, temperature, max_tokens = (
550
+ c
551
+ for c in players_idx2comp[i]
552
+ if not isinstance(c, (gr.Accordion, gr.Tab))
553
+ )
554
+
555
+ update_dict[role_name] = gr.update(value=player_config["name"])
556
+ update_dict[role_desc] = gr.update(value=player_config["role_desc"])
557
  update_dict[backend_type] = gr.update(
558
+ value=player_config["backend"]["backend_type"]
559
+ )
560
  update_dict[temperature] = gr.update(
561
+ value=player_config["backend"]["temperature"]
562
+ )
563
  update_dict[max_tokens] = gr.update(
564
+ value=player_config["backend"]["max_tokens"]
565
+ )
566
 
567
  return update_dict
568
 
569
+ example_selector.change(
570
+ update_components_from_example,
571
+ set(all_components + [state]),
572
+ all_components + [state],
573
+ )
574
 
575
  demo.queue()
576
+ demo.launch(debug=DEBUG, server_port=8080)