ChatArena Documentation

repository·main·Indexed 23 days ago

https://github.com/farama-foundation/chatarena

A multi-agent language game environment for researching autonomous LLM agents and social interactions. Built on a Markov Decision Process framework, ChatArena provides abstractions for Arenas, Environments, Language Backends, and Players. It supports multiple backends (including OpenAI, Anthropic, Cohere, and HuggingFace), a Gradio-based Web UI, and a Python API for programmatic control and custom environment development.

Tokens
11.3K
Snippets
24
Records
57
Agent score
81%

What's inside ChatArena

  1. How the Message Pool and Visibility Control work

    main

    Agents in ChatArena do not communicate directly. Instead, they use a message pool as a proxy to exchange information. The message pool acts as part of the game state.

    Message Creation and Routing

    • Agent Actions: When an agent acts, a message is appended to the pool. Each message has a receiver, which is determined either by the environment's rules or by the agent itself.
    • Moderator Messages: The environment can inject messages under the name of the moderator to provide state information or instructions.

    Visibility and Turn Management

    An observation is rendered by the message pool by collecting only the messages visible to a specific agent.

    To support games requiring simultaneous/parallel moves (like Rock-Paper-Scissors) where agents must not see others' moves in the same turn, the message pool supports turn-based filtering. You can specify a "current turn" or a set of "current turns"; messages belonging to future turns are ignored during observation rendering.

  2. Use ModeratedConversation to control game dynamics with an LLM

    main

    ModeratedConversation is an advanced environment type where an LLM acts as a moderator. Unlike standard environments, the moderator is a special player that manages game state transitions and determines the game's end conditions. This is useful for games where the state (like a board game) needs to be tracked and evaluated by an LLM to decide if a player has won or if the game should continue.

    You can implement this by defining a moderator that tracks specific game state variables and triggers the end of the game based on those variables.

  3. How the Agent Environment Cycle works

    main

    ChatArena follows the design principles of OpenAI Gym and PettingZoo. Agents interact with the environment through a cyclic process. In every cycle:

    1. Observe: The agent receives an observation from the environment.
    2. Act: The agent outputs an action.
    3. Transition: The environment processes the action and makes a state transition.

    Optional Features:

    • Rewards: The environment can compute a scalar reward for each agent per cycle.
    • Termination: The environment can provide a terminal signal indicating the end of the session.
  4. Understanding Actions and Observations

    main

    In ChatArena, communication and interaction are standardized as follows:

    Actions

    Actions are represented as plain text. While actions are text-based, you can prompt LLMs to generate structured text like JSON or code. ChatArena provides utilities to extract JSON and code (using markdown syntax) from these text actions.

    Observations

    An observation is a list of messages. Each message contains:

    • sender: The entity that sent the message (can be an agent or the built-in moderator).
    • content: The plain text content of the message.
  5. How ChatArena core concepts work together

    main

    ChatArena is built on four primary abstractions that form a multi-agent language game environment:

    1. Arena: The top-level container that encapsulates an environment and its players. It manages the main game loop and provides interfaces like WebUI, CLI, configuration loading, and data storage.
    2. Environment: Stores the game state and executes game logic to handle state transitions. It renders observations as natural language for players. Note that players cannot see the raw game state, only these observations.
    3. Language Backend: The intelligence source. It accepts text (or collections of text) and returns a text response.
    4. Player: An agent (policy) that acts as a stateless function mapping observations to actions. By default, players query the language backend when receiving an observation.
  6. Using Intelligence Backends

    main

    Each agent is powered by an intelligence backend that processes observations and produces actions.

    Workflow:

    1. The backend receives an observation (a list of messages).
    2. The backend renders these messages into the format required by the specific model.
    3. The model returns text, which becomes the agent's action.

    Supported Backend Types:

    • LLM APIs: OpenAI, Anthropic, Cohere, etc.
    • Local LLMs: e.g., via Hugging Face Transformers.
    • Humans: A human user interacting via a UI.
  7. Install ChatArena via pip

    main

    Install the core ChatArena library using pip. Note that you may need to set your OPENAI_API_KEY environment variable to use GPT-3.5-turbo or GPT-4 agents.

    pip install chatarena

    To use GPT-3 as an LLM agent, set your OpenAI API key:

    export OPENAI_API_KEY="your_api_key_here"
  8. Create a custom ChatArena environment

    main

    To define a new game, extend the Environment class by following these steps:

    1. Define the class: Inherit from the base Environment class and set a type_name. Add the class to the ALL_ENVIRONMENTS registry in chatarena/environments/__init__.py.
    2. Initialize: Implement the __init__ method. The arguments defined here will correspond to the configuration keys used to instantiate the environment.
    3. Implement Mechanics: Use the step method to define game dynamics.
    4. Handle State and Rewards: Implement reset, get_observation, is_terminal, and get_rewards to manage the lifecycle and feedback.
    5. Prompt Engineering: Use the CLI or Web UI to develop role description prompts (and a global prompt if needed) and save them to a configuration file.
  9. Define players with LLM backends

    main

    To create participants for a language game, instantiate the Player class. Each player requires a name, a backend (e.g., OpenAIChat), a role_desc defining their specific persona, and a global_prompt describing the shared environment context.

    from chatarena.agent import Player
    from chatarena.backends import OpenAIChat
    
    environment_description = "It is in a university classroom ..."
    
    player1 = Player(
        name="Professor", 
        backend=OpenAIChat(),
        role_desc="You are a professor in ...",
        global_prompt=environment_description
    )
  10. Create a custom environment class

    main

    To develop a custom environment in ChatArena, you must create a class that inherits from the Environment base class. Follow these steps:

    1. Define the class: Inherit from Environment and define a required type_name string. This type_name is used by the ENV_REGISTRY to identify the class when loading from configuration files.
    2. Register the class: You must add your new class to the ALL_ENVIRONMENTS list in chatarena/environments/__init__.py so the system can detect it.
    3. Initialize the class: Implement __init__ to set up player names, game state, and other variables. Note that the environment's "state" is typically maintained by a MessagePool instance.
    4. Implement game mechanics: Implement the step method to handle player actions (e.g., giving clues, voting).
    5. Manage lifecycle and rewards: Implement the following required methods:
      • reset(): Resets the environment state.
      • get_observation(player_name=None): Returns a List[Message] representing what the player sees.
      • is_terminal(): Returns a boolean indicating if the game has ended.
      • get_rewards(...): Returns a Dict[str, float] mapping player names to their scores/rewards.
  11. Use the Umshini: Deception environment

    main

    The Umshini: Deception environment is a two-player language game where one player (the attacker) attempts to manipulate the other (the defender) into performing a forbidden action. The environment is symmetrical: roles swap halfway through the match.

    To use this environment, wrap it using PettingZooCompatibilityV0. You must specify the env_name as "deception" and provide a restricted_action string which the defender is forbidden from performing.

    from chatarena.environments.umshini.pettingzoo_wrapper import PettingZooCompatibilityV0
    
    env = PettingZooCompatibilityV0(env_name="deception", restricted_action="open the door", render_mode="human")
    env.reset()
    
    for agent in env.agent_iter():
        observation, reward, termination, truncation, info = env.last()
    
        if termination or truncation:
            break
    
        # The observation is the most recent message in format: "[Player 1 ->all]: test."
        response = your_model(observation)
        env.step(response)
  12. Develop and test role description prompts

    main

    Once your environment is defined, you need to create role_desc prompts to guide the LLM players. You can test these prompts using the ChatArena CLI or the Web UI.

    Using the CLI

    Create Player instances with your desired role_desc and launch the arena using .launch_cli():

    alice = Player(name="Alice", backend=OpenAIChat(), role_desc="Write your prompt here")
    bob = Player(name="Bob", backend=OpenAIChat(), role_desc="Write your prompt here")
    env = Chameleon(player_names=["Alice", "Bob"], topic_codes=...)
    arena = Arena(players=[alice, bob], environment=env).launch_cli()

    After refining your prompts, you can save the configuration to a file:

    arena.save_config(path=...)

    Using the Web UI

    Alternatively, you can launch the Gradio-based Web UI and select your custom environment from the dropdown menu:

    gradio app.py
    alice = Player(name="Alice", backend=OpenAIChat(), role_desc="Write your prompt here")
    bob = Player(name="Bob", backend=OpenAIChat(), role_desc="Write your prompt here")
    env = Chameleon(player_names=["Alice", "Bob"], topic_codes=...)
    arena = Arena(players=[alice, bob], environment=env).launch_cli()
    
    # Save the configuration once prompts are ready
    arena.save_config(path="path/to/config.json")