Skip to content

Commit fa273e9

Browse files
committed
disaggregated llama3.1-70b w pathways
1 parent 903a097 commit fa273e9

15 files changed

Lines changed: 2273 additions & 14 deletions

docker_build_dependency_image.sh

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,21 @@
2727
# works with any custom wheels.
2828
# bash docker_build_dependency_image.sh MODE=custom_wheels
2929

30+
# bash docker_build_dependency_image.sh MODE=grpo
31+
3032
# Enable "exit immediately if any command fails" option
3133
set -e
3234

35+
# Check for docker permissions
36+
if ! docker info > /dev/null 2>&1; then
37+
echo "ERROR: Permission denied while trying to connect to the Docker daemon." >&2
38+
echo "You can fix this by:" >&2
39+
echo "1. Running this script with sudo: 'sudo bash $0 $@'" >&2
40+
echo "2. Adding your user to the 'docker' group: 'sudo usermod -aG docker \${USER}' (requires a new login session)." >&2
41+
echo "3. Running `newgrp docker` in your current terminal." >&2
42+
exit 1
43+
fi
44+
3345
export LOCAL_IMAGE_NAME=maxtext_base_image
3446
echo "Building to $LOCAL_IMAGE_NAME"
3547

@@ -40,9 +52,10 @@ echo "Starting to build your docker image. This will take a few minutes but the
4052

4153
# Set environment variables
4254
for ARGUMENT in "$@"; do
43-
IFS='=' read -r KEY VALUE <<< "$ARGUMENT"
55+
IFS='=' read -r RAW_KEY VALUE <<< "$ARGUMENT"
56+
KEY=$(echo "$RAW_KEY" | tr '[:lower:]' '[:upper:]')
4457
export "$KEY"="$VALUE"
45-
echo "$KEY"="$VALUE"
58+
echo "$KEY=$VALUE"
4659
done
4760

4861

@@ -54,11 +67,18 @@ fi
5467
if [[ -z ${MODE} ]]; then
5568
export MODE=stable
5669
echo "Default MODE=${MODE}"
70+
export CUSTOM_JAX=0
71+
export INSTALL_GRPO=0
5772
elif [[ ${MODE} == "custom_wheels" ]] ; then
5873
export MODE=nightly
5974
export CUSTOM_JAX=1
75+
export INSTALL_GRPO=0
76+
elif [[ ${MODE} == "grpo" || ${MODE} == "grpo-experimental" ]] ; then
77+
export INSTALL_GRPO=1
78+
export CUSTOM_JAX=0
6079
else
6180
export CUSTOM_JAX=0
81+
export INSTALL_GRPO=0
6282
fi
6383

6484
if [[ -z ${DEVICE} ]]; then
@@ -104,6 +124,9 @@ if [[ -z ${LIBTPU_GCS_PATH+x} ]] ; then
104124
elif [[ ${MANTARAY} == "true" ]]; then
105125
echo "Building with benchmark-db"
106126
docker build --network host --build-arg MODE=${MODE} --build-arg JAX_VERSION=$JAX_VERSION --build-arg LIBTPU_GCS_PATH=$LIBTPU_GCS_PATH --build-arg DEVICE=$DEVICE -f ./maxtext_db_dependencies.Dockerfile -t ${LOCAL_IMAGE_NAME} .
127+
elif [[ ${INSTALL_GRPO} -eq 1 && ${DEVICE} == "tpu" ]]; then
128+
echo "Installing MaxText stable mode dependencies for GRPO"
129+
docker build --network host --build-arg MODE=stable --build-arg JAX_VERSION=$JAX_VERSION --build-arg LIBTPU_GCS_PATH=$LIBTPU_GCS_PATH --build-arg DEVICE=$DEVICE -f ./maxtext_dependencies.Dockerfile -t ${LOCAL_IMAGE_NAME} .
107130
else
108131
docker build --network host --build-arg MODE=${MODE} --build-arg JAX_VERSION=$JAX_VERSION --build-arg LIBTPU_GCS_PATH=$LIBTPU_GCS_PATH --build-arg DEVICE=$DEVICE -f ./maxtext_dependencies.Dockerfile -t ${LOCAL_IMAGE_NAME} .
109132
fi
@@ -113,6 +136,32 @@ else
113136
docker build --network host --build-arg CUSTOM_LIBTPU=true -f ./maxtext_libtpu_path.Dockerfile -t ${LOCAL_IMAGE_NAME} .
114137
fi
115138

139+
if [[ ${INSTALL_GRPO} -eq 1 ]] ; then
140+
if [[ ${DEVICE} != "tpu" ]] ; then
141+
echo "Error: MODE=grpo is only supported for DEVICE=tpu"
142+
exit 1
143+
fi
144+
145+
# # To install tpu_commons from a local path, we copy it into the build context, excluding __pycache__.
146+
# # This assumes vllm, tunix, tpu_commons is a sibling directory to the current one (maxtext).
147+
# rsync -a --exclude='__pycache__' ../tpu_commons .
148+
# # To install vllm from a local path, we copy it into the build context, excluding __pycache__.
149+
# # This assumes vllm is a sibling directory to the current one (maxtext).
150+
# rsync -a --exclude='__pycache__' ../vllm .
151+
152+
# rsync -a --exclude='__pycache__' ../tunix .
153+
154+
# # The cleanup is set to run even if the build fails to remove the copied directory.
155+
# trap "rm -rf ./tpu_commons ./vllm ./tunix" EXIT INT TERM
156+
157+
docker build \
158+
--network host \
159+
--build-arg BASEIMAGE=${LOCAL_IMAGE_NAME} \
160+
--build-arg MODE=${MODE} \
161+
-f ./maxtext_grpo_dependencies.Dockerfile \
162+
-t ${LOCAL_IMAGE_NAME} .
163+
fi
164+
116165
if [[ ${CUSTOM_JAX} -eq 1 ]] ; then
117166
echo "Installing custom jax and jaxlib"
118167
docker build --network host -f ./maxtext_custom_wheels.Dockerfile -t ${LOCAL_IMAGE_NAME} .

docker_upload_runner.sh

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ export PROJECT=$(gcloud config get-value project)
3030

3131
# Set environment variables
3232
for ARGUMENT in "$@"; do
33-
IFS='=' read -r KEY VALUE <<< "$ARGUMENT"
33+
IFS='=' read -r RAW_KEY VALUE <<< "$ARGUMENT"
34+
KEY=$(echo "$RAW_KEY" | tr '[:lower:]' '[:upper:]')
3435
export "$KEY"="$VALUE"
35-
echo "$KEY"="$VALUE"
36+
echo "$KEY=$VALUE"
3637
done
3738

3839
export LOCAL_IMAGE_NAME_RUNNER=${LOCAL_IMAGE_NAME}__runner
@@ -44,9 +45,36 @@ if [[ ! -v CLOUD_IMAGE_NAME ]]; then
4445
exit 1
4546
fi
4647

48+
# Check for dangling symbolic links (target does not exist).
49+
DANGLING_LINKS=$(find -L . -type l)
50+
if [ -n "$DANGLING_LINKS" ]; then
51+
echo "ERROR: Found dangling symbolic links in the build context:"
52+
echo "$DANGLING_LINKS"
53+
echo "These can cause 'failed to compute cache key' errors during 'docker build'."
54+
echo "Please remove or fix them before building the Docker image."
55+
exit 1
56+
fi
57+
58+
# Check for absolute symbolic links, which Docker can't follow outside the build context.
59+
ABSOLUTE_LINKS=$(find . -type l -lname '/*')
60+
if [ -n "$ABSOLUTE_LINKS" ]; then
61+
echo "ERROR: Found symbolic links with absolute paths in the build context:"
62+
echo "$ABSOLUTE_LINKS"
63+
echo "Docker cannot follow absolute paths outside of the build context, which can cause 'failed to compute cache key' errors."
64+
echo "Please remove these links or convert them to relative paths before building the Docker image."
65+
exit 1
66+
fi
67+
4768
# Download other test assets from GCS into "${MAXTEXT_PKG_DIR:-${MAXTEXT_REPO_ROOT:-$PWD}/src/MaxText}"/test_assets
48-
if ! gcloud storage cp gs://maxtext-test-assets/* "${MAXTEXT_TEST_ASSETS_ROOT:-${MAXTEXT_REPO_ROOT:-$PWD}/test_assets}"; then
49-
echo "WARNING: Failed to download test assets from GCS. These files are only used for end-to-end tests; you may not have access to the bucket."
69+
# if ! gcloud storage cp gs://maxtext-test-assets/* "${MAXTEXT_TEST_ASSETS_ROOT:-${MAXTEXT_REPO_ROOT:-$PWD}/test_assets}"; then
70+
# echo "WARNING: Failed to download test assets from GCS. These files are only used for end-to-end tests; you may not have access to the bucket."
71+
# fi
72+
73+
# Check if the base image exists locally
74+
if ! docker image inspect "${LOCAL_IMAGE_NAME}" &> /dev/null; then
75+
echo "ERROR: Base image '${LOCAL_IMAGE_NAME}' not found locally."
76+
echo "Please build it first by running 'bash docker_build_dependency_image.sh'."
77+
exit 1
5078
fi
5179

5280
docker build --build-arg BASEIMAGE=${LOCAL_IMAGE_NAME} -f ./maxtext_runner.Dockerfile -t ${LOCAL_IMAGE_NAME_RUNNER} .
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<!--
2+
Copyright 2024 Google LLC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
https://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
17+
# Try GRPO with Pathways!
18+
19+
This tutorial demonstrates step-by-step instructions for setting up the environment and then training the Llama3.1 70B-IT model on the GSM8K math reasoning benchmark using Group Relative Policy Optimization (GRPO). GRPO can enhance your model's problem-solving skills on mathematical word problems, coding problems, etc.
20+
21+
GRPO is an RL algorithm designed to enhance the reasoning abilities of LLMs. It is a variant of Proximal Policy Optimization (PPO) that reduces memory usage by eliminating the need for a separate value function model. GRPO works by generating multiple responses for a given prompt, evaluating these responses using a reward model, and then calculating a relative advantage based on the group's performance to update the policy.
22+
23+
We use Tunix as the library for GRPO.
24+
And we use vLLM as the library for efficient model inference and generation.
25+
26+
Furthermore, we use Pathways for [orchestration](https://cloud.google.com/ai-hypercomputer/docs/workloads/pathways-on-cloud/pathways-intro). Using Pathways, you can also run GRPO in a disaggregated mode where the trainer and the samplers are running on separate mesh. Try out the following recipe `v5p-64`. You can submit jobs to a Pathways enabled GKE cluster.
27+
28+
## Build and Upload MaxText Docker Image with Tunix, vLLM, tpu-commons dependencies
29+
Run the following bash script to create a docker image with all the dependencies of MaxText, Tunix, vLLM and tpu-commons installed.
30+
31+
In addition to MaxText dependencies,
32+
33+
1. It installs `pip install keyring keyrings.google-artifactregistry-auth` which enables pip to authenticate with Google Artifact Registry automatically.
34+
2. Next, it installs `vLLM` for Jax and TPUs from the artifact registry `https://us-python.pkg.dev/cloud-tpu-images/maxtext-rl/simple/`
35+
3. Then, it installs `tpu-commons` from the same artifact registry.
36+
37+
38+
`tpu_commons` is the TPU backend for vLLM. You will need both libraries to run vLLM on tpus.
39+
We use the scheduler code from vLLM, and the model runner code from `tpu_commons`
40+
41+
```
42+
bash docker_build_dependency_image.sh MODE=grpo
43+
```
44+
45+
You can also use `bash docker_build_dependency_image.sh MODE=grpo-experimental` to try out new features via experimental dependencies such as improved pathwaysutils resharding API
46+
47+
48+
49+
### Upload the dependency docker image along with MaxText code
50+
```
51+
bash docker_upload_runner.sh CLOUD_IMAGE_NAME=path/to/gcr.io
52+
```
53+
54+
### Submit your jobs
55+
56+
Please use a pathways enabled cluster, and you can submit the script `maxtext/src/MaxText/examples/grpo_llama3_1_70b_demo_pw.py` via XPK
57+
```
58+
xpk workload create-pathways --workload $WORKLOAD \
59+
--docker-image path/to/gcr.io:latest --cluster $TPU_CLUSTER \
60+
--tpu-type=$TPU_TYPE --num-slices=1 --zone=$ZONE \
61+
--project=$PROJECT_ID --priority=high \
62+
--command "HF_TOKEN=$HF_TOKEN TF_CPP_MIN_LOG_LEVEL=0 JAX_PLATFORMS=proxy JAX_BACKEND_TARGET=grpc://127.0.0.1:29000 ENABLE_PATHWAYS_PERSISTENCE='1' python src/MaxText/examples/grpo_llama3_1_70b_demo_pw.py"
63+
```
64+
65+
The overview of the demo script ~/maxtext/src/MaxText/examples/grpo_llama3_1_70b_demo_pw.py` is as follows:
66+
67+
1. We load a policy model and a reference model. Both are copies of `Llama3.1-70b-Instruct`.
68+
2. Evaluate the policy model's performance on GSM8K math reasoning benchmark.
69+
3. Train the policy model using GRPO with potentially different meshes for trainer and rollout dependending on the parameters `TRAINER_DEVICES_FRACTION` and `SAMPLER_DEVICES_FRACTION`. If we set both of these to `1.0`, the entire (same) mesh will be used for both trainer and rollout. If we set say `TRAINER_DEVICES_FRACTION=0.5` and `SAMPLER_DEVICES_FRACTION=0.5`, the first half of the devices will be used for trainer and the second half will be used for rollout
70+
4. Evaluate the policy model's performance on GSM8K math reasoning benchmark after the post-training with GRPO.

docs/tutorials/grpo.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ In this tutorial we use a single host TPUVM such as `v6e-8/v5p-8`. Let's get sta
3232
bash setup.sh
3333
```
3434

35-
### Activate your virtual environment
35+
### Activate your virtual environment (Skip if you have already done this for running `bash setup.sh` )
3636
```
3737
# Replace with your virtual environment name if not using this default name
3838
venv_name="maxtext_venv"
@@ -60,7 +60,7 @@ We use the scheduler code from vLLM, and the model runner code from `tpu_commons
6060

6161
Finally, run the script
6262

63-
`python ~/maxtext/MaxText/examples/grpo_llama3_demo.py`
63+
`python ~/maxtext/src/MaxText/examples/grpo_llama3_1_8b_demo.py`
6464

6565
The overview of the demo script is as follows:
6666

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Copyright 2023–2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
ARG BASEIMAGE
16+
FROM ${BASEIMAGE}
17+
ARG MODE
18+
19+
ENV MODE=$MODE
20+
21+
RUN echo "Installing GRPO dependencies (vLLM, tpu-common, tunix) with MODE=${MODE}"
22+
23+
24+
# Uninstall existing jax to avoid conflicts
25+
RUN pip uninstall -y jax jaxlib libtpu
26+
27+
RUN pip install aiohttp==3.12.15
28+
29+
# Install Python packages that enable pip to authenticate with Google Artifact Registry automatically.
30+
RUN pip install keyring keyrings.google-artifactregistry-auth
31+
32+
RUN pip install numba==0.61.2
33+
34+
# Install vLLM for Jax and TPUs from the artifact registry
35+
RUN VLLM_TARGET_DEVICE="tpu" pip install --no-cache-dir --pre \
36+
--index-url https://us-python.pkg.dev/cloud-tpu-images/maxtext-rl/simple/ \
37+
--extra-index-url https://pypi.org/simple/ \
38+
--extra-index-url https://us-python.pkg.dev/ml-oss-artifacts-published/jax/simple/ \
39+
--extra-index-url https://download.pytorch.org/whl/nightly/cpu \
40+
--find-links https://storage.googleapis.com/jax-releases/libtpu_releases.html \
41+
--find-links https://storage.googleapis.com/libtpu-wheels/index.html \
42+
--find-links https://storage.googleapis.com/libtpu-releases/index.html \
43+
--find-links https://storage.googleapis.com/jax-releases/jax_nightly_releases.html \
44+
--find-links https://storage.googleapis.com/jax-releases/jaxlib_nightly_releases.html \
45+
vllm==0.11.1rc1.dev292+g1b86bd8e1.tpu
46+
47+
# Install tpu-commons from the artifact registry
48+
RUN pip install --no-cache-dir --pre \
49+
--index-url https://us-python.pkg.dev/cloud-tpu-images/maxtext-rl/simple/ \
50+
--extra-index-url https://pypi.org/simple/ \
51+
--extra-index-url https://us-python.pkg.dev/ml-oss-artifacts-published/jax/simple/ \
52+
--find-links https://storage.googleapis.com/jax-releases/libtpu_releases.html \
53+
tpu-commons==0.1.2
54+
55+
RUN if [ "$MODE" = "grpo-experimental" ]; then \
56+
pip uninstall -y jax jaxlib libtpu && \
57+
pip install --pre -U jax jaxlib -i https://us-python.pkg.dev/ml-oss-artifacts-published/jax/simple/ && \
58+
pip install -U --pre libtpu -f https://storage.googleapis.com/jax-releases/libtpu_releases.html; \
59+
fi

maxtext_jax_ai_image.Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ RUN if [ "$DEVICE" = "tpu" ] && [ "$JAX_STABLE_STACK_BASEIMAGE" = "us-docker.pkg
4949

5050
# Install google-tunix for TPU devices, skip for GPU
5151
RUN if [ "$DEVICE" = "tpu" ]; then \
52-
python3 -m pip install 'google-tunix>=0.1.0'; \
52+
python3 -m pip install 'google-tunix>=0.1.2'; \
5353
# TODO: Once tunix stopped pinning jax 0.7.1, we should remove our 0.7.0 version pin (b/450286600)
5454
python3 -m pip install 'jax==0.7.0' 'jaxlib==0.7.0'; \
5555
fi

setup.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ if [[ "$MODE" == "stable" || ! -v MODE ]]; then
184184

185185
# TODO: Once tunix has support for GPUs, move it from here to requirements.txt
186186
echo "Installing google-tunix for stable TPU environment"
187-
python3 -m uv pip install 'google-tunix>=0.1.0'
187+
python3 -m uv pip install 'google-tunix>=0.1.2'
188188
echo "Installing stable jax, jaxlib for tpu"
189189
if [[ -n "$JAX_VERSION" ]]; then
190190
echo "Installing stable jax, jaxlib, libtpu version ${JAX_VERSION}"

0 commit comments

Comments
 (0)