Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 123 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 🛒 WebShop

[![Python version](https://img.shields.io/badge/python-3.8%2B-blue)](https://www.python.org/downloads/release/python-3813/)
[![Python version](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/downloads/)
[![License](https://img.shields.io/badge/License-Princeton-orange)](https://copyright.princeton.edu/policy)
[![PyPI version](https://badge.fury.io/py/webshop.svg)](https://badge.fury.io/py/webshop)
![Pytest workflow](https://github.com/princeton-nlp/webshop/actions/workflows/pytest.yml/badge.svg)
Expand Down Expand Up @@ -39,72 +39,157 @@ WebShop is a simulated e-commerce website environment with 1.18 million real-wor
**Hugging Face Demo**: Devise your own natural language query for a product and ask for an agent trained with WebShop to find it on Amazon or eBay, deployed as a 🤗 Hugging Face space [here](https://huggingface.co/spaces/webshop/amazon_shop)!

## 🚀 Setup
Our code is implemented in Python. To setup, do the following:
1. Install [Python 3.8.13](https://www.python.org/downloads/release/python-3813/)
2. Install [Java](https://www.java.com/en/download/)
3. Download the source code:
This project uses modern Python tooling with [uv](https://github.com/astral-sh/uv) for fast, reliable dependency management.

### Prerequisites
1. **Python 3.12+**: [Download here](https://www.python.org/downloads/)
2. **Java**: [Download here](https://www.java.com/en/download/) (required for search engine)
3. **(Optional) uv package manager**: Will be auto-installed by `make setup`, or [install manually](https://github.com/astral-sh/uv#installation)

### Quick Start
1. Clone the repository:
```sh
git clone https://github.com/princeton-nlp/webshop.git webshop
cd webshop
```

2. Run the automated setup:
```sh
> git clone https://github.com/princeton-nlp/webshop.git webshop
make setup
```
4. Create a virtual environment using [Anaconda](https://anaconda.org/anaconda/python) and activate it
This command will:
* Install [uv](https://github.com/astral-sh/uv) if not already installed (10-100x faster than pip)
* Create a virtual environment (`.venv`) and install all dependencies from `pyproject.toml`
* Download and install the spaCy `en_core_web_sm` language model

3. Download data and build search indexes:
```sh
> conda create -n webshop python=3.8.13
> conda activate webshop
# Option A: Download small dataset (1,000 products) - faster for testing
make setup-data-small

# Option B: Download full dataset (all products)
make setup-data-all

# Build search engine indexes (required after downloading data)
make setup-search-engine
```
5. Install requirements into the `webshop` virtual environment via the `setup.sh` script

4. (Optional) Download human trajectories:
```sh
make setup-human-trajs
```

### Available Make Targets
The project uses a `Makefile` for common tasks:

**Setup Commands:**
- `make setup` - Complete initial setup (uv, dependencies, spacy model)
- `make setup-data-small` - Download 1,000 product dataset
- `make setup-data-all` - Download full product dataset
- `make setup-search-engine` - Build search engine indexes
- `make setup-human-trajs` - Download human demonstration trajectories
- `make download-spacy-model-lg` - Download larger spaCy model (en_core_web_lg)

**Run Commands:**
- `make run-dev` - Start Flask webapp in development mode
- `make run-prod` - Start Flask webapp in production mode
- `make run-web-agent-site` - Run web agent with browser (requires ChromeDriver)
- `make run-web-agent-text` - Run web agent text environment

**Utility Commands:**
- `make clean` - Clean up temporary files
- `make check-uv` - Verify uv is installed
- `make check-search-engine` - Verify search engine indexes are built

### Modern Python Tooling
This project has been modernized to use:
- **[uv](https://github.com/astral-sh/uv)**: Ultra-fast Python package manager (10-100x faster than pip)
- **pyproject.toml**: Modern Python project configuration (replaces requirements.txt)
- **Gymnasium**: Updated OpenAI Gym API with proper typing and modern standards
- **Python 3.12+**: Latest Python features and performance improvements

All dependencies are managed in `pyproject.toml`. To manually sync dependencies:
```sh
uv sync
```

To run Python commands in the virtual environment:
```sh
> ./setup.sh [-d small|all]
uv run python your_script.py
```
The setup script performs several actions in the following order:
* Installs Python dependencies listed in `requirements.txt`
* Downloads product and instruction data for populating WebShop
* Downloads `spaCy en_core_web_lg` model
* Construct search engine index from product, instruction data
* Downloads 50 randomly chosen trajectories generated by MTurk workers
The `-d` flag argument allows you to specify whether you would like to pull the entire product + instruction data set (`-d all`) or a subset of 1000 random products (`-d small`).

6. By default the WebShop only loads 1,000 products for a faster environment preview. To load all products, change `web_agent_site/utils.py`:
### Loading All Products
By default, the WebShop only loads 1,000 products for faster environment preview. To load all products, change `web_agent_site/utils.py`:
```python
# DEFAULT_ATTR_PATH = join(BASE_DIR, '../data/items_ins_v2_1000.json')
# DEFAULT_FILE_PATH = join(BASE_DIR, '../data/items_shuffle_1000.json')
DEFAULT_ATTR_PATH = join(BASE_DIR, '../data/items_ins_v2.json')
DEFAULT_FILE_PATH = join(BASE_DIR, '../data/items_shuffle.json')
```

7. (Optional) Download ResNet image feature files [here](https://drive.google.com/drive/folders/1jglJDqNV2ryrlZzrS0yOEk-aRAcLAhNw?usp=sharing) and put into `data/` for running models that require image features.

8. (Optional) Human demonstration data and be downloaded [here](https://drive.google.com/file/d/1GWC8UlUzfT9PRTRxgYOwuKSJp4hyV1dp/view?usp=sharing).
### Optional Downloads
- **Image Features**: Download ResNet image feature files [here](https://drive.google.com/drive/folders/1jglJDqNV2ryrlZzrS0yOEk-aRAcLAhNw?usp=sharing) and put into `data/` for running models that require image features.
- **Human Demonstrations**: Download human demonstration data [here](https://drive.google.com/file/d/1GWC8UlUzfT9PRTRxgYOwuKSJp4hyV1dp/view?usp=sharing).

## 🛠️ Usage
The WebShop environment can be rendered in two modes - `html` and `simple` - each of which offer a different observation space. The `simple` mode strips away the extraneous meta-data that the `html` mode includes to make model training and evaluation easier.

### Webpage Environment (`html` mode)
Launch the `WebShop` webpage:
```sh
> ./run_dev.sh
make run-dev
```
The site should then be viewable in the browser. Go to http://localhost:3000/ABC, where you should land on the search home page with a random instruction.
The site will be viewable in your browser at http://localhost:3000/. Navigate to http://localhost:3000/ABC to land on the search home page with a random instruction.

Navigating the website will automatically generate a corresponding trajectory file in the `user_session_logs/mturk` folder. Each file corresponds to a single instruction/web session, and each step of the file corresponds to a single action (i.e. `search[...]`, `click[...]`).

The current WebShop build comes with two flags:
* `--log`: Include this flag to create a trajectory `.jsonl` log file of actions on WebShop
* `--attrs`: Include this flag to display an `Attributes` tab on the `item_page` of WebShop
The `run-dev` command includes:
* `--log`: Creates trajectory `.jsonl` log files of actions on WebShop
* `--attrs`: Displays an `Attributes` tab on the `item_page` of WebShop

For production mode (logging only, no attributes):
```sh
make run-prod
```

### Text Environment (`simple` mode)
The `simple` mode of the WebShop environment is packaged and readily available as an OpenAI environment. The OpenAI gym definitions of the text environment can be found in the `web_agent_site/envs` folder.
The `simple` mode of the WebShop environment is packaged and readily available as a Gymnasium environment. The environment definitions can be found in the `web_agent_site/envs` folder.

To start using the gym and building agents that interact with the WebShop environment, include the following statements in your Python file:
To start using the environment and building agents that interact with WebShop, include the following statements in your Python file:
```python
import gym
import gymnasium as gym
from web_agent_site.envs import WebAgentTextEnv

env = gym.make('WebAgentTextEnv-v0', observation_mode='text', num_products=...)
observation, info = env.reset()

# Your agent logic here
action = your_policy(observation)
observation, reward, terminated, truncated, info = env.step(action)
```
Now, you can write your own agent that interacts with the environment via the standard OpenAI gym [interface](https://www.gymlibrary.ml/content/api/).
Now, you can write your own agent that interacts with the environment via the standard Gymnasium [interface](https://gymnasium.farama.org/).

**Note**: This project uses [Gymnasium](https://gymnasium.farama.org/) (the maintained fork of OpenAI Gym). The API follows the Gymnasium v1.0+ standard with 5-value returns from `step()`: `(observation, reward, terminated, truncated, info)`.

### Running Example Agents
Examples of a `RandomPolicy` agent interacting with the WebShop environment in both `html` and `simple` modes can be found in the `run_envs` folder. To run these examples locally:

Examples of a `RandomPolicy` agent interacting with the WebShop environment in both `html` and `simple` mode can be found in the `run_envs` folder. To run these examples locally, run the `run_web_agent_text_env.sh` or `run_web_agent_site_env.sh` script:
**Text Environment:**
```sh
> ./run_web_agent_text_env.sh
make run-web-agent-text
# or
uv run python run_envs/run_web_agent_text_env.py
```

**Site Environment (with browser):**
```sh
make run-web-agent-site
# or
uv run python run_envs/run_web_agent_site_env.py
```

Output example:
```
Products loaded.
Keys Cleaned.
Attributes Loaded.
Expand All @@ -115,7 +200,11 @@ Available actions: {'has_search_bar': True, 'clickables': ['search']}
Taking action "search[shoes]" -> Reward = 0.0
...
```
In order to run the `run_web_agent_site_env.sh` script, you must download a version of [ChromeDriver](https://chromedriver.chromium.org/downloads) compatible with your Chrome browser version. Once you have downloaded and unzipped the executable, rename it `chromedriver` and place it in the `webshop/envs` folder.

**ChromeDriver Setup:**
The site environment requires ChromeDriver. See `web_agent_site/envs/README.md` for installation instructions:
- **Recommended**: Install system-wide (`sudo apt-get install chromium-chromedriver` on Ubuntu/Debian)
- **Alternative**: Download from [ChromeDriver](https://chromedriver.chromium.org/downloads) and place in `web_agent_site/envs/chromedriver`

### Baseline Models
To run baseline models (rule, IL, RL, IL+RL) from the paper, please refer to the `README.md` in the [baseline_models](https://github.com/princeton-nlp/webshop/tree/master/baseline_models) folder.
Expand Down
105 changes: 105 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
.PHONY: setup install-uv sync-deps install-spacy-model update-spacy-model check-uv check-search-engine run-dev run-prod run-web-agent-site run-web-agent-text setup-data-small setup-data-all setup-human-trajs download-spacy-model-lg setup-search-engine clean

setup: install-uv sync-deps install-spacy-model
@echo "✓ Complete setup finished!"

check-uv:
@which uv > /dev/null 2>&1 || (echo "UV is not installed. Run 'make install-uv' first."; exit 1)
@echo "✓ UV is installed"

check-search-engine:
@if [ ! -d "search_engine/indexes" ] || [ -z "$$(ls -A search_engine/indexes 2>/dev/null | grep -v README)" ]; then \
echo "⚠️ Search engine indexes not found!"; \
echo ""; \
echo "Before running the application, you need to:"; \
echo " 1. Download data: make setup-data-small (or setup-data-all)"; \
echo " 2. Build indexes: make setup-search-engine"; \
echo ""; \
exit 1; \
fi
@echo "✓ Search engine indexes found"

install-uv:
@echo "Checking for UV installation..."
@if command -v uv > /dev/null 2>&1; then \
echo "✓ UV is already installed: $$(uv --version)"; \
else \
echo "Installing UV..."; \
curl -LsSf https://astral.sh/uv/install.sh | sh; \
echo "✓ UV installed successfully!"; \
echo "Note: You may need to restart your shell or run: source ~/.bashrc (or ~/.zshrc)"; \
fi

sync-deps: check-uv
@echo "Syncing dependencies with UV..."
@uv sync
@echo "✓ Dependencies synced successfully!"

install-spacy-model: check-uv
@echo "Installing spaCy language model (en_core_web_sm)..."
@uv pip install https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl
@echo "✓ Model installed successfully!"
@uv run python -c "import spacy; nlp = spacy.load('en_core_web_sm'); print('✓ Model verification passed!')"

update-spacy-model: check-uv
@echo "Updating spaCy language model to latest version..."
@uv pip install --upgrade https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl
@echo "✓ Model updated successfully!"
@uv run python -c "import spacy; nlp = spacy.load('en_core_web_sm'); print('✓ Model verification passed!')"

run-dev: check-search-engine
@echo "Starting Flask app in development mode..."
@FLASK_ENV=development uv run python -m web_agent_site.app --log --attrs

run-prod: check-search-engine
@echo "Starting Flask app in production mode..."
@uv run python -m web_agent_site.app --log

run-web-agent-site: check-search-engine
@echo "Starting web agent site environment..."
@uv run python run_envs/run_web_agent_site_env.py

run-web-agent-text: check-search-engine
@echo "Starting web agent text environment..."
@uv run python run_envs/run_web_agent_text_env.py

setup-data-small: check-uv
@echo "Downloading small dataset (1000 items)..."
@mkdir -p data
@cd data && uv run gdown https://drive.google.com/uc?id=1EgHdxQ_YxqIQlvvq5iKlCrkEKR6-j0Ib
@cd data && uv run gdown https://drive.google.com/uc?id=1IduG0xl544V_A_jv3tHXC0kyFi7PnyBu
@cd data && uv run gdown https://drive.google.com/uc?id=14Kb5SPBk_jfdLZ_CDBNitW98QLDlKR5O
@echo "✓ Small dataset downloaded successfully!"

setup-data-all: check-uv
@echo "Downloading full dataset..."
@mkdir -p data
@cd data && uv run gdown https://drive.google.com/uc?id=1A2whVgOO0euk5O13n2iYDM0bQRkkRduB
@cd data && uv run gdown https://drive.google.com/uc?id=1s2j6NgHljiZzQNL3veZaAiyW_qDEgBNi
@cd data && uv run gdown https://drive.google.com/uc?id=14Kb5SPBk_jfdLZ_CDBNitW98QLDlKR5O
@echo "✓ Full dataset downloaded successfully!"

setup-human-trajs: check-uv
@echo "Downloading human trajectories..."
@mkdir -p user_session_logs
@cd user_session_logs && uv run python -c "import gdown; gdown.download_folder('https://drive.google.com/drive/u/1/folders/16H7LZe2otq4qGnKw_Ic1dkt-o3U9Zsto', quiet=True, remaining_ok=True)"
@echo "✓ Human trajectories downloaded successfully!"

download-spacy-model-lg: check-uv
@echo "Downloading spaCy large model (en_core_web_lg)..."
@uv run python -m spacy download en_core_web_lg
@echo "✓ spaCy large model installed successfully!"

setup-search-engine: check-uv
@echo "Setting up search engine..."
@cd search_engine && mkdir -p resources resources_100 resources_1k resources_100k
@cd search_engine && uv run python convert_product_file_format.py
@cd search_engine && mkdir -p indexes
@cd search_engine && ./run_indexing.sh
@echo "✓ Search engine setup complete!"

clean:
@echo "Cleaning up temporary files..."
@rm -rf .temp_model
@rm -f en_core_web_sm-*.whl
@echo "✓ Cleanup complete!"
71 changes: 71 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
[project]
name = "webshop-ai"
version = "0.1.0"
description = "WebShop AI application"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"beautifulsoup4>=4.14.2",
"cleantext>=1.1.4",
"flask>=3.0.3",
"gdown>=5.0.0",
"gradio>=4.0.0",
"gymnasium>=1.0.0",
"litellm>=1.0.0",
"lxml>=6.0.2",
"numpy>=1.24.0",
"openai>=1.0.0",
"pandas>=2.0.0",
"pyserini>=0.22.0",
"pyyaml>=6.0.0",
"rank-bm25>=0.2.2",
"requests>=2.31.0",
"rich>=14.1.0",
"scikit-learn>=1.3.2",
"selenium>=4.27.1",
"spacy>=3.7.5",
"thefuzz>=0.22.1",
"torch>=2.5.1",
"tqdm>=4.66.0",
]

[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"black>=23.0.0",
"ruff>=0.1.0",
"mypy>=1.0.0",
"requests-mock>=1.11.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["web_agent_site"]

[dependency-groups]
dev = [
"pytest>=7.0.0",
"black>=23.0.0",
"ruff>=0.1.0",
"mypy>=1.0.0",
"requests-mock>=1.11.0",
]

[tool.black]
line-length = 88
target-version = ['py312']

[tool.ruff]
target-version = "py312"
line-length = 88
select = ["E", "F", "W", "C90", "I", "N", "UP", "YTT", "S", "BLE", "FBT", "B", "A", "COM", "C4", "DTZ", "T10", "DJ", "EM", "EXE", "FA", "ISC", "ICN", "G", "INP", "PIE", "T20", "PYI", "PT", "Q", "RSE", "RET", "SLF", "SLOT", "SIM", "TID", "TCH", "INT", "ARG", "PTH", "TD", "FIX", "ERA", "PD", "PGH", "PL", "TRY", "FLY", "NPY", "AIR", "PERF", "FURB", "LOG", "RUF"]
ignore = ["S101", "PLR0913", "PLR0912", "PLR0915"]

[tool.mypy]
python_version = "3.12"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true
Loading