Skip to content

Commit f1c0478

Browse files
Merge pull request #2386 from AI-Hypercomputer:hengtaoguo-sft-validation
PiperOrigin-RevId: 816926925
2 parents 1a33004 + 08830db commit f1c0478

3 files changed

Lines changed: 159 additions & 1 deletion

File tree

src/MaxText/examples/sft_llama3_demo.ipynb

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,11 +284,56 @@
284284
" print(\"EXECUTING ACTUAL TRAINING\")\n",
285285
" print(\"=\"*60)\n",
286286
"\n",
287-
" sft_train(config)\n",
287+
" trainer, mesh = sft_train(config)\n",
288288
"\n",
289289
"print(\"Training complete!\")\n",
290290
"print(\"Model saved at: \", BASE_OUTPUT_DIRECTORY)"
291291
]
292+
},
293+
{
294+
"cell_type": "markdown",
295+
"metadata": {},
296+
"source": [
297+
"## Decoding\n",
298+
"\n",
299+
"We could reuse the trainer.model to try a decode command after the SFT."
300+
]
301+
},
302+
{
303+
"cell_type": "code",
304+
"execution_count": null,
305+
"metadata": {},
306+
"outputs": [],
307+
"source": [
308+
"# Decode by using the trained model\n",
309+
"if MAXTEXT_AVAILABLE:\n",
310+
" from MaxText.vllm_decode import decode\n",
311+
"\n",
312+
" decode_config_argv = [\n",
313+
" \"\", \n",
314+
" f\"{MAXTEXT_REPO_ROOT}/configs/sft.yml\", # Decode config\n",
315+
" \"model_name=llama3.1-8b\",\n",
316+
" \"per_device_batch_size=1\",\n",
317+
" \"max_target_length=128\",\n",
318+
" \"max_prefill_predict_length=64\",\n",
319+
" \"weight_dtype=bfloat16\",\n",
320+
" \"dtype=bfloat16\",\n",
321+
" f\"hf_access_token={HF_TOKEN}\",\n",
322+
" \"base_output_directory=/tmp/maxtext_output\",\n",
323+
" \"run_name=sft_llama3_decode\",\n",
324+
" \"tokenizer_path=meta-llama/Llama-3.1-8B-Instruct\",\n",
325+
" \"prompt=Suggest some famous landmarks in London.\",\n",
326+
" \"use_chat_template=true\",\n",
327+
" \"decode_sampling_temperature=0.0\",\n",
328+
" \"decode_sampling_nucleus_p=1.0\",\n",
329+
" \"decode_sampling_top_k=0.0\",\n",
330+
" ]\n",
331+
" \n",
332+
" # Initialize configuration using MaxText's pyconfig\n",
333+
" decode_config = pyconfig.initialize(decode_config_argv)\n",
334+
" os.environ[\"SKIP_JAX_PRECOMPILE\"] = \"1\"\n",
335+
" decode(decode_config, trainer.model, mesh)"
336+
]
292337
}
293338
],
294339
"metadata": {

src/MaxText/sft/sft_trainer.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ def train(mt_config, goodput_recorder=None):
162162
with mesh, nn_partitioning.axis_rules(mt_config.logical_axis_rules):
163163
trainer.train(data_hooks.train_data_iterator, data_hooks.eval_data_iterator)
164164

165+
return trainer, mesh
166+
165167

166168
def main(argv: Sequence[str]) -> None:
167169
"""Main function to run SFT training.

src/MaxText/vllm_decode.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Copyright 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+
An example script to perform decoding using vLLM with a MaxText model.
16+
17+
Example command:
18+
python3 -m MaxText.vllm_decode MaxText/configs/sft.yml \
19+
model_name=llama3.1-8b tokenizer_path=meta-llama/Llama-3.1-8B-Instruct \
20+
tokenizer_type=huggingface hf_access_token=<your_hf_token> \
21+
load_parameters_path=<your_checkpoint_path> \
22+
per_device_batch_size=1 run_name=vllm_decode_test \
23+
use_chat_template=True prompt="Suggest some famous landmarks in London." \
24+
decode_sampling_temperature=0.0 decode_sampling_nucleus_p=1.0 decode_sampling_top_k=0.0
25+
"""
26+
27+
import os
28+
from typing import Any, Sequence
29+
30+
from absl import app
31+
import jax
32+
import transformers
33+
34+
from MaxText import model_creation_utils
35+
from MaxText import pyconfig
36+
from MaxText.common_types import Config
37+
from MaxText.integration.tunix.tunix_adapter import TunixMaxTextAdapter
38+
from tunix.rl.rollout import base_rollout
39+
from tunix.rl.rollout.vllm_rollout import VllmRollout
40+
41+
os.environ["SKIP_JAX_PRECOMPILE"] = "1"
42+
43+
44+
def decode(
45+
config: Config,
46+
model: Any,
47+
mesh: jax.sharding.Mesh,
48+
) -> None:
49+
"""Decode using vLLM with a MaxText model."""
50+
# Wrap the model for Tunix
51+
tunix_model = TunixMaxTextAdapter(base_model=model)
52+
53+
# Load the tokenizer and format the prompt
54+
model_tokenizer = transformers.AutoTokenizer.from_pretrained(config.tokenizer_path, token=config.hf_access_token)
55+
model_tokenizer.bos_token = None
56+
57+
# Format the prompt using chat template if specified
58+
prompts = [config.prompt]
59+
if config.use_chat_template:
60+
messages = [
61+
{"role": "user", "content": config.prompt},
62+
]
63+
formatted_prompt_string = model_tokenizer.apply_chat_template(
64+
messages,
65+
tokenize=False, # Set to False to get the string
66+
add_generation_prompt=True,
67+
add_special_tokens=False, # Prevent adding special tokens
68+
)
69+
print("Formatted prompt string:", formatted_prompt_string)
70+
prompts = [formatted_prompt_string]
71+
72+
# Create vLLM rollout for inference
73+
rollout_config = base_rollout.RolloutConfig(
74+
max_tokens_to_generate=config.max_target_length - config.max_prefill_predict_length,
75+
max_prompt_length=config.max_prefill_predict_length,
76+
temperature=config.decode_sampling_temperature,
77+
top_p=config.decode_sampling_nucleus_p,
78+
top_k=config.decode_sampling_top_k,
79+
)
80+
vllm_rollout = VllmRollout(
81+
model=tunix_model,
82+
tokenizer=model_tokenizer,
83+
cache_config_or_size=config.max_target_length, # Max sequence length
84+
mesh=mesh,
85+
model_version=config.tokenizer_path,
86+
hbm_utilization=0.8,
87+
init_with_random_weights=True, # Use random weights
88+
tpu_backend_type="jax",
89+
)
90+
91+
# Generate text
92+
output = vllm_rollout.generate(prompts, rollout_config)
93+
print("Generated text:")
94+
print(output.text[0])
95+
96+
97+
def main(argv: Sequence[str]) -> None:
98+
jax.config.update("jax_default_prng_impl", "unsafe_rbg")
99+
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "0"
100+
if "xla_tpu_spmd_rng_bit_generator_unsafe" not in os.environ.get("LIBTPU_INIT_ARGS", ""):
101+
os.environ["LIBTPU_INIT_ARGS"] = (
102+
os.environ.get("LIBTPU_INIT_ARGS", "") + " --xla_tpu_spmd_rng_bit_generator_unsafe=true"
103+
)
104+
105+
config = pyconfig.initialize(argv)
106+
maxtext_model, mesh = model_creation_utils.create_nnx_model(config)
107+
decode(config, model=maxtext_model, mesh=mesh)
108+
109+
110+
if __name__ == "__main__":
111+
app.run(main)

0 commit comments

Comments
 (0)