mirror of
https://github.com/NVIDIA/Model-Optimizer.git
synced 2026-10-02 03:14:52 +08:00
- [x] Product Rename: TensorRT Model Optimizer to Model Optimizer (OMNIML-3033) - [x] Mention in Latest News section with date on the date of merging this PR (12/08) Signed-off-by: Keval Morabia <28916987+kevalmorabia97@users.noreply.github.com>
16 KiB
16 KiB
In [ ]:
!git clone https://huggingface.co/datasets/nvidia/Daring-Anteater /tmp/Daring-AnteaterIn [ ]:
import transformers
import modelopt.torch.opt as mto
import modelopt.torch.speculative as mtsp
from modelopt.torch.speculative.config import EAGLE3_DEFAULT_CFG
mto.enable_huggingface_checkpointing()
# Load original HF model
base_model = "meta-llama/Llama-3.2-1B"
model = transformers.AutoModelForCausalLM.from_pretrained(
base_model, torch_dtype="auto", device_map="cuda"
)
# Read Default Config for EAGLE3
config = EAGLE3_DEFAULT_CFG["config"]
# Hidden size and vocab size must match base model
config["eagle_architecture_config"].update(
{
"hidden_size": model.config.hidden_size,
"vocab_size": model.config.vocab_size,
"draft_vocab_size": model.config.vocab_size,
"max_position_embeddings": model.config.max_position_embeddings,
}
)
# Convert Model for eagle speculative decoding
mtsp.convert(model, [("eagle", config)])
# Prepare Tokenizer
tokenizer = transformers.AutoTokenizer.from_pretrained(base_model, model_max_length=1024)
tokenizer.pad_token_id = tokenizer.eos_token_id
if tokenizer.chat_template is None:
tokenizer.chat_template = (
"{%- for message in messages %}"
"{{- '<|im_start|>' + message['role'] + '\n' + message['content'] + '<|im_end|>' + '\n' }}"
"{%- endfor %}"
)In [ ]:
import json
from dataclasses import dataclass, field
from eagle_utils import DataCollatorWithPadding, LazySupervisedDataset
from transformers import Trainer
with open("/tmp/Daring-Anteater/train.jsonl") as f:
data_json = [json.loads(line) for line in f]
train_dataset = LazySupervisedDataset(data_json[: int(len(data_json) * 0.95)], tokenizer=tokenizer)
eval_dataset = LazySupervisedDataset(data_json[int(len(data_json) * 0.95) :], tokenizer=tokenizer)
@dataclass
class TrainingArguments(transformers.TrainingArguments):
dataloader_drop_last: bool = field(default=True)
bf16: bool = field(default=True)
training_args = TrainingArguments(
output_dir="/tmp/eagle_bf16",
num_train_epochs=4,
per_device_train_batch_size=1,
per_device_eval_batch_size=1,
)
trainer = Trainer(
model=model,
tokenizer=tokenizer,
args=training_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
data_collator=DataCollatorWithPadding(),
)
trainer._move_model_to_device(model, trainer.args.device)
# Make sure label_smoother is None
assert trainer.label_smoother is None, "label_smoother is not supported in speculative decoding!"
trainer.train()
trainer.save_state()
trainer.save_model(training_args.output_dir)
tokenizer.save_pretrained(training_args.output_dir)In [ ]:
from modelopt.torch.export import export_hf_checkpoint
model.eval()
export_hf_checkpoint(
model,
export_dir="/tmp/hf_ckpt",
)In [ ]:
trtllm_serve_script = f"""trtllm-serve {base_model} \\
--host 0.0.0.0 \\
--port 8000 \\
--backend pytorch \\
--max_batch_size 32 \\
--max_num_tokens 8192 \\
--max_seq_len 8192 \\
--extra_llm_api_options /tmp/extra-llm-api-config.yml
"""
extra_llm_api_config = """enable_attention_dp: false
disable_overlap_scheduler: true
enable_autotuner: false
cuda_graph_config:
max_batch_size: 1
speculative_config:
decoding_type: Eagle
max_draft_len: 3
speculative_model_dir: /tmp/hf_ckpt
kv_cache_config:
enable_block_reuse: false
"""
# Dump the two scripts into /tmp
with open("/tmp/trtllm_serve.sh", "w") as f:
f.write(trtllm_serve_script)
with open("/tmp/extra-llm-api-config.yml", "w") as f:
f.write(extra_llm_api_config)In [ ]:
import subprocess
import threading
# Generate a unique container name so we can stop/remove it later
container_name = "trtllm_serve_spec"
docker_cmd = [
"docker",
"run",
"--rm",
"--net",
"host",
"--shm-size=2g",
"--ulimit",
"memlock=-1",
"--ulimit",
"stack=67108864",
"--gpus",
"all",
"-v",
"/tmp:/tmp",
"--name",
container_name,
"nvcr.io/nvidia/tensorrt-llm/release:1.1.0rc2",
"bash",
"-c",
"bash /tmp/trtllm_serve.sh",
]
# print docker outputs
proc = subprocess.Popen(
docker_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1
)
def stream_output(pipe):
for line in iter(pipe.readline, ""):
print(line, end="")
# Use thread to print outputs
thread = threading.Thread(target=stream_output, args=(proc.stdout,))
thread.daemon = True
thread.start()
print(
f"Starting trtllm-serve in Docker (PID: {proc.pid}, container name: {container_name}) in the background:"
)In [ ]:
import json
import requests
payload = {
"model": base_model,
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Tell me about speculative decoding."},
],
"max_tokens": 512,
"temperature": 0,
"chat_template": tokenizer.chat_template,
}
headers = {"Content-Type": "application/json", "Accept": "application/json"}
response = requests.post(
"http://localhost:8000/v1/chat/completions", headers=headers, data=json.dumps(payload)
)
output = response.json()
print(output)In [ ]:
!docker rm -f trtllm_serve_specIn [ ]:
# SGLang server launch command shell script
sglang_serve_script = f"""python3 -m sglang.launch_server \\
--model {base_model} \\
--host 0.0.0.0 \\
--port 30000 \\
--speculative-algorithm EAGLE3 \\
--speculative-eagle-topk 8 \\
--speculative-draft-model-path /tmp/hf_ckpt \\
--speculative-num-draft-tokens 3 \\
--speculative-num-steps 3 \\
--mem-fraction 0.6 \\
--cuda-graph-max-bs 2 \\
--dtype float16
"""
with open("/tmp/sglang_serve.sh", "w") as f:
f.write(sglang_serve_script)In [ ]:
import os
import subprocess
import threading
container_name = "sglang_serve_spec"
home_dir = os.path.expanduser("~")
hf_cache_dir = os.path.join(home_dir, ".cache", "huggingface")
# Ensure the Hugging Face cache directory exists. This directory should exist as ~/.cache/huggingface, when the model files for meta-llama/Llama-3.2-1B were downloaded earlier.
os.makedirs(hf_cache_dir, exist_ok=True)
docker_cmd = [
"docker",
"run",
"--rm",
"--net",
"host",
"--shm-size=32g",
"--gpus",
"all",
"-v",
f"{hf_cache_dir}:/root/.cache/huggingface",
"-v",
"/tmp:/tmp",
"--ipc=host",
"--name",
container_name,
"lmsysorg/sglang:latest",
"bash",
"-c",
"bash /tmp/sglang_serve.sh",
]
# Launch the Docker container
proc = subprocess.Popen(
docker_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1
)
# Stream the process output
def stream_output(pipe):
for line in iter(pipe.readline, ""):
print(line, end="")
# Use a thread to stream the output in without blocking the notebook
thread = threading.Thread(target=stream_output, args=(proc.stdout,))
thread.daemon = True
thread.start()
print(
f"Starting SGLang server in Docker (PID: {proc.pid}, container name: {container_name}) in the background:"
)In [ ]:
import json
import requests
payload = {
"model": base_model,
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Tell me about speculative decoding."},
],
"max_tokens": 512,
"temperature": 0,
}
headers = {"Content-Type": "application/json", "Accept": "application/json"}
# Send request to the SGLang server
response = requests.post(
"http://localhost:30000/v1/chat/completions", headers=headers, data=json.dumps(payload)
)
output = response.json()
print(output)In [ ]:
!docker rm -f sglang_serve_spec