Buckets:
| # TextArena Environment | |
| An OpenEnv wrapper for [TextArena](https://github.com/textarena/textarena) game environments. Supports text-based games like Wordle, providing a standardized API for agent interaction. | |
| > [!NOTE] | |
| > Generic wrapper for any [TextArena](https://www.textarena.ai/docs/overview) game inside OpenEnv. This module exposes the TextArena `Env` interface through the standard HTTP server/client APIs used by other OpenEnv environments, enabling quick experimentation with the full suite of word, reasoning, and multi-agent games. | |
| ## Quick Start | |
| The simplest way to use the TextArena environment is through the `TextArenaEnv` class: | |
| ```python | |
| from textarena_env import TextArenaAction, TextArenaEnv | |
| try: | |
| # Create environment from Docker image | |
| env = TextArenaEnv.from_docker_image("textarena-env:latest") | |
| # Reset to start a new episode | |
| result = env.reset() | |
| print(f"Game prompt:\n{result.observation.prompt}") | |
| # Play a few turns (example: Wordle guesses) | |
| guesses = ["[crane]", "[slate]", "[audio]"] | |
| for guess in guesses: | |
| result = env.step(TextArenaAction(message=guess)) | |
| # Check messages for feedback | |
| for message in result.observation.messages: | |
| print(f"Response: {message.content}") | |
| print(f"Reward: {result.reward}") | |
| print(f"Done: {result.done}") | |
| if result.done: | |
| break | |
| finally: | |
| # Always clean up | |
| env.close() | |
| ``` | |
| That's it! The `TextArenaEnv.from_docker_image()` method handles: | |
| - Starting the Docker container | |
| - Waiting for the server to be ready | |
| - Connecting to the environment | |
| - Container cleanup when you call `close()` | |
| ## Building the Docker Image | |
| Before using the environment, you need to build the Docker image: | |
| ```bash | |
| # From the textarena_env directory | |
| cd envs/textarena_env | |
| docker build -t textarena-env:latest -f server/Dockerfile . | |
| ``` | |
| ## Testing the Gradio UI locally | |
| With the web interface enabled, the server serves a **Gradio UI** at `/web`. If your `openenv` supports `gradio_builder`, you get two tabs (see [Customizing the Web UI](https://huggingface.co/docs/openenv/guides/customizing-web-ui)): | |
| - **Playground** – default OpenEnv UI (Reset, Step, Get state, Quick Start, README). | |
| - **Custom** – Wordle-style HTML block (see `server/gradio_ui.py`; uses [Gradio 6 `gr.HTML`](https://gradio.app/docs/gradio/html) to render the block). | |
| **Option A – From the OpenEnv repo root (recommended for the Custom tab)** | |
| Use the core that includes the tabbed interface and custom builder: | |
| ```bash | |
| cd envs/textarena_env | |
| ENABLE_WEB_INTERFACE=true PYTHONPATH=../../src uv run uvicorn server.app:app --host 0.0.0.0 --port 8000 | |
| ``` | |
| **Option B – From the environment directory only** | |
| ```bash | |
| cd envs/textarena_env | |
| ENABLE_WEB_INTERFACE=true uv run server | |
| ``` | |
| Or: | |
| ```bash | |
| ENABLE_WEB_INTERFACE=true uv run uvicorn server.app:app --host 0.0.0.0 --port 8000 | |
| ``` | |
| Then open **http://localhost:8000/web**. Use the **Playground** tab to Reset and Step with guesses (e.g. `[crane]`, `[stone]`). If you ran with Option A, the **Custom** tab shows the Wordle-style demo block. | |
| ## Deploying to Hugging Face Spaces | |
| You can easily deploy your OpenEnv environment to Hugging Face Spaces using the `openenv push` command: | |
| ```bash | |
| # From the environment directory (where openenv.yaml is located) | |
| openenv push | |
| # Or specify options | |
| openenv push --namespace my-org --private | |
| ``` | |
| The `openenv push` command will: | |
| 1. Validate that the directory is an OpenEnv environment (checks for `openenv.yaml`) | |
| 2. Prepare a custom build for Hugging Face Docker space (enables web interface) | |
| 3. Upload to Hugging Face (ensuring you're logged in) | |
| ### Prerequisites | |
| - Authenticate with Hugging Face: The command will prompt for login if not already authenticated | |
| ### Options | |
| - `--directory`, `-d`: Directory containing the OpenEnv environment (defaults to current directory) | |
| - `--repo-id`, `-r`: Repository ID in format 'username/repo-name' (defaults to 'username/env-name' from openenv.yaml) | |
| - `--base-image`, `-b`: Base Docker image to use (overrides Dockerfile FROM) | |
| - `--private`: Deploy the space as private (default: public) | |
| ### Examples | |
| ```bash | |
| # Push to your personal namespace (defaults to username/env-name from openenv.yaml) | |
| openenv push | |
| # Push to a specific repository | |
| openenv push --repo-id my-org/my-env | |
| # Push with a custom base image | |
| openenv push --base-image ghcr.io/huggingface/openenv-base:latest | |
| # Push as a private space | |
| openenv push --private | |
| # Combine options | |
| openenv push --repo-id my-org/my-env --base-image custom-base:latest --private | |
| ``` | |
| After deployment, your space will be available at: | |
| `https://huggingface.co/spaces/<repo-id>` | |
| The deployed space includes: | |
| - **Web Interface** at `/web` - Interactive UI for exploring the environment | |
| - **API Documentation** at `/docs` - Full OpenAPI/Swagger interface | |
| - **Health Check** at `/health` - Container health monitoring | |
| ## Environment Details | |
| ### Action | |
| **TextArenaAction**: Contains a single field | |
| - `message` (str) - The message/action to send to the game | |
| ### Observation | |
| **TextArenaObservation**: Contains the game state and response | |
| - `prompt` (str) - Game instructions and context | |
| - `messages` (List[TextArenaMessage]) - Conversation history with the game | |
| - `current_player_id` (int) - ID of the current player | |
| - `legal_players` (List[int]) - List of valid player IDs | |
| - `info` (Dict) - Additional game metadata | |
| - `reward` (float) - Reward for the current step (inherited from Observation) | |
| - `done` (bool) - Whether the episode has ended (inherited from Observation) | |
| ### TextArenaMessage | |
| Each message in the conversation has: | |
| - `sender_id` (int) - ID of the message sender | |
| - `content` (str) - The message content | |
| - `category` (str) - Message type (e.g., "PROMPT", "MESSAGE") | |
| ### State | |
| **TextArenaState**: Server-side state snapshot | |
| - `episode_id` (str) - Unique identifier for the current episode | |
| - `step_count` (int) - Number of steps taken in the current episode | |
| - `env_id` (str) - The TextArena environment ID (e.g., "Wordle-v0") | |
| - `num_players` (int) - Number of players in the game | |
| - `max_turns` (Optional[int]) - Maximum turns allowed | |
| - `turn` (int) - Current turn number | |
| - `last_reward` (float) - Most recent reward | |
| - `last_info` (Dict) - Most recent info dictionary | |
| - `raw_state` (Dict) - Raw TextArena state snapshot | |
| ### Reward | |
| Rewards are determined by the underlying TextArena game. For example: | |
| - **Wordle-v0**: Positive reward for winning, includes reward signals for green/yellow letter matches | |
| ## Advanced Usage | |
| ### Connecting to an Existing Server | |
| If you already have a TextArena environment server running, you can connect directly: | |
| ```python | |
| from textarena_env import TextArenaEnv, TextArenaAction | |
| # Connect to existing server | |
| env = TextArenaEnv(base_url="<ENV_HTTP_URL_HERE>") | |
| # Use as normal | |
| result = env.reset() | |
| result = env.step(TextArenaAction(message="[crane]")) | |
| # Close connection (does NOT stop the server) | |
| env.close() | |
| ``` | |
| ### Environment Configuration | |
| The server supports configuration via environment variables: | |
| - `TEXTARENA_ENV_ID` - Game to load (default: "Wordle-v0") | |
| - `TEXTARENA_NUM_PLAYERS` - Number of players (default: 1) | |
| - `TEXTARENA_MAX_TURNS` - Maximum turns per episode | |
| - `TEXTARENA_DOWNLOAD_NLTK` - Download NLTK data (default: "1") | |
| - `TEXTARENA_KW_*` - Pass additional kwargs to TextArena (e.g., `TEXTARENA_KW_difficulty=hard`) | |
| ## Development & Testing | |
| ### Direct Environment Testing | |
| Test the environment logic directly without starting the HTTP server: | |
| ```python | |
| from textarena_env.server.environment import TextArenaEnvironment | |
| from textarena_env.models import TextArenaAction | |
| # Create environment directly | |
| env = TextArenaEnvironment(env_id="Wordle-v0", num_players=1) | |
| # Test reset | |
| obs = env.reset() | |
| print(f"Prompt: {obs.prompt}") | |
| # Test step | |
| obs = env.step(TextArenaAction(message="[crane]")) | |
| print(f"Done: {obs.done}, Reward: {obs.reward}") | |
| ``` | |
| ### Running Locally | |
| Run the server locally for development: | |
| ```bash | |
| # Install dependencies | |
| uv venv && source .venv/bin/activate | |
| uv pip install -e . | |
| # Start the server | |
| python -m uvicorn server.app:app --reload | |
| ``` | |
| Or using the CLI entry point: | |
| ```bash | |
| uv run --project . server --port 8000 | |
| ``` | |
| ## Project Structure | |
| ``` | |
| textarena_env/ | |
| ├── __init__.py # Module exports | |
| ├── README.md # This file | |
| ├── openenv.yaml # OpenEnv manifest | |
| ├── pyproject.toml # Project metadata and dependencies | |
| ├── uv.lock # Locked dependencies (generated) | |
| ├── client.py # TextArenaEnv client implementation | |
| ├── models.py # Action, Observation, and State models | |
| ├── rewards.py # Reward provider utilities | |
| └── server/ | |
| ├── __init__.py # Server module exports | |
| ├── environment.py # Core TextArenaEnvironment implementation | |
| ├── app.py # FastAPI application | |
| └── Dockerfile # Container image definition | |
| ``` | |
Xet Storage Details
- Size:
- 9.04 kB
- Xet hash:
- dbbbd4f13fc0abf27de7208350f389d163fdb8309d359bef92e09c95a632e559
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.