import re
import json
import gradio as gr
from glob import glob
from time import sleep
from chatarena.arena import Arena, TooManyInvalidActions
from chatarena.backends import BACKEND_REGISTRY
from chatarena.backends.human import HumanBackendError
from chatarena.config import ArenaConfig
from chatarena.environments import ENV_REGISTRY, TimeStep
from chatarena.database import log_arena, log_messages, SupabaseDB, supabase_available
from chatarena.message import Message
css = """#col-container {max-width: 90%; margin-left: auto; margin-right: auto; display: flex; flex-direction: column;}
#header {text-align: center;}
#col-chatbox {flex: 1; max-height: min(750px, 100%); display: flex;}
#chatbox {height: min(750px, 100%); max-height: 750px; display:flex;}
#label {font-size: 2em; padding: 0.5em; margin: 0;}
.message {font-size: 1.2em;}
.wrap {min-width: min(640px, 100vh)}
.message-wrap {max-height: min(700px, 100vh);}
"""
DEBUG = False
DEFAULT_BACKEND = "openai-chat"
DEFAULT_ENV = "conversation"
MAX_NUM_PLAYERS = 6
DEFAULT_NUM_PLAYERS = 2
def load_examples():
example_configs = {}
# Load json config files from examples folder
example_files = glob("examples/*.json")
for example_file in example_files:
with open(example_file, 'r') as f:
example = json.load(f)
example_configs[example["name"]] = example
return example_configs
EXAMPLE_REGISTRY = load_examples()
DB = SupabaseDB() if supabase_available else None
def get_moderator_components(visible=True):
name = "Moderator"
with gr.Row():
with gr.Column():
role_desc = gr.Textbox(label="Moderator role", lines=1, visible=visible, interactive=True,
placeholder=f"Enter the role description for {name}")
terminal_condition = gr.Textbox(show_label=False, lines=1, visible=visible, interactive=True,
placeholder="Enter the end criteria for the conversation")
with gr.Column():
backend_type = gr.Dropdown(show_label=False, visible=visible, interactive=True,
choices=list(BACKEND_REGISTRY.keys()), value=DEFAULT_BACKEND)
with gr.Accordion(f"{name} Parameters", open=False, visible=visible) as accordion:
temperature = gr.Slider(minimum=0, maximum=2.0, step=0.1, interactive=True, visible=visible,
label=f"temperature", value=0.7)
max_tokens = gr.Slider(minimum=10, maximum=500, step=10, interactive=True, visible=visible,
label=f"max tokens", value=200)
return [role_desc, terminal_condition, backend_type, accordion, temperature, max_tokens]
def get_player_components(name, visible):
with gr.Row():
with gr.Column():
role_desc = gr.Textbox(label=name, lines=3, interactive=True, visible=visible,
placeholder=f"Enter the role description for {name}")
with gr.Column():
backend_type = gr.Dropdown(show_label=False, choices=list(BACKEND_REGISTRY.keys()),
interactive=True, visible=visible, value=DEFAULT_BACKEND)
with gr.Accordion(f"{name} Parameters", open=False, visible=visible) as accordion:
temperature = gr.Slider(minimum=0, maximum=2.0, step=0.1, interactive=True, visible=visible,
label=f"temperature", value=0.7)
max_tokens = gr.Slider(minimum=10, maximum=500, step=10, interactive=True, visible=visible,
label=f"max tokens", value=200)
return [role_desc, backend_type, accordion, temperature, max_tokens]
def get_empty_state():
return gr.State({"arena": None})
with gr.Blocks(css=css) as demo:
state = get_empty_state()
all_components = []
with gr.Column(elem_id="col-container"):
gr.Markdown("""# 🏟 ChatArena️
Prompting multiple AI agents to play games in a language-driven environment.
**[Project Homepage](https://github.com/chatarena/chatarena)**
### Due to the high volume of requests, our OpenAI API Token exceeded the billing limit. We are approaching OpenAI to get the research access at the moment. We encourage users to run the demo locally following [this instruction](https://github.com/chatarena/chatarena#launch-the-demo-locally).""", elem_id="header")
with gr.Row():
env_selector = gr.Dropdown(choices=list(ENV_REGISTRY.keys()), value=DEFAULT_ENV, interactive=True,
label="Environment Type", show_label=True)
example_selector = gr.Dropdown(choices=list(EXAMPLE_REGISTRY.keys()), interactive=True,
label="Select Example", show_label=True)
# Environment configuration
env_desc_textbox = gr.Textbox(show_label=True, lines=2, visible=True, label="Environment Description",
placeholder="Enter a description of a scenario or the game rules.")
all_components += [env_selector, example_selector, env_desc_textbox]
with gr.Row():
with gr.Column(elem_id="col-chatbox"):
with gr.Tab("All"):
chatbot = gr.Chatbot(elem_id="chatbox", visible=True, show_label=False)
player_chatbots = []
for i in range(MAX_NUM_PLAYERS):
player_name = f"Player {i + 1}"
with gr.Tab(player_name, visible=(i < DEFAULT_NUM_PLAYERS)):
player_chatbot = gr.Chatbot(elem_id=f"chatbox-{i}", visible=i < DEFAULT_NUM_PLAYERS,
label=player_name, show_label=False)
player_chatbots.append(player_chatbot)
all_components += [chatbot, *player_chatbots]
with gr.Column(elem_id="col-config"): # Player Configuration
# gr.Markdown("Player Configuration")
parallel_checkbox = gr.Checkbox(label="Parallel Actions", value=False, visible=True)
with gr.Accordion("Moderator", open=False, visible=True):
moderator_components = get_moderator_components(True)
all_components += [parallel_checkbox, *moderator_components]
all_players_components, players_idx2comp = [], {}
with gr.Blocks():
num_player_slider = gr.Slider(2, MAX_NUM_PLAYERS, value=DEFAULT_NUM_PLAYERS, step=1,
label="Number of players:")
for i in range(MAX_NUM_PLAYERS):
player_name = f"Player {i + 1}"
with gr.Tab(player_name, visible=(i < DEFAULT_NUM_PLAYERS)) as tab:
player_comps = get_player_components(player_name, visible=(i < DEFAULT_NUM_PLAYERS))
players_idx2comp[i] = player_comps + [tab]
all_players_components += player_comps + [tab]
all_components += [num_player_slider] + all_players_components
def variable_players(k):
k = int(k)
update_dict = {}
for i in range(MAX_NUM_PLAYERS):
if i < k:
for comp in players_idx2comp[i]:
update_dict[comp] = gr.update(visible=True)
update_dict[player_chatbots[i]] = gr.update(visible=True)
else:
for comp in players_idx2comp[i]:
update_dict[comp] = gr.update(visible=False)
update_dict[player_chatbots[i]] = gr.update(visible=False)
return update_dict
num_player_slider.change(variable_players, num_player_slider, all_players_components + player_chatbots)
human_input_textbox = gr.Textbox(show_label=True, label="Human Input", lines=1, visible=True,
interactive=True, placeholder="Enter your input here")
with gr.Row():
btn_step = gr.Button("Start")
btn_restart = gr.Button("Clear")
gr.HTML(
"""
By clicking the "Start" button above, you consent to the collection and use of your input data for research purposes.
""") all_components += [human_input_textbox, btn_step, btn_restart] def _convert_to_chatbot_output(all_messages, display_recv=False): chatbot_output = [] for i, message in enumerate(all_messages): agent_name, msg, recv = message.agent_name, message.content, str(message.visible_to) new_msg = re.sub(r'\n+', '