|
|
--- |
|
|
title: Wordle |
|
|
emoji: ๐ฎ |
|
|
colorFrom: yellow |
|
|
colorTo: indigo |
|
|
sdk: docker |
|
|
pinned: false |
|
|
app_port: 8000 |
|
|
base_path: /web |
|
|
tags: |
|
|
- openenv |
|
|
--- |
|
|
|
|
|
# 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 project root |
|
|
docker build -t textarena-env:latest -f server/Dockerfile . |
|
|
``` |
|
|
|
|
|
## 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/meta-pytorch/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 |
|
|
``` |
|
|
|