XoneLM-1.0-Paper / sft_example.py
cloverxion's picture
Upload sft_example.py
17b4b9a verified
Raw
History Blame Contribute Delete
5.22 kB
import time
from typing import Dict, List
import torch
from torch.utils.data import DataLoader, Dataset
from modeling_xonelm import XoneLM, HardwareContext
from luminav import LuminaV
from tokenizer import (
build_xonelm_tokenizer,
MultiTurnConversationFormatter,
SpecialTokenConfig,
)
class SafeSFTCollator:
def __init__(self, max_seq_len: int = 512, pad_token_id: int = 0):
self.max_seq_len = max_seq_len
self.pad_token_id = pad_token_id
def __call__(self, samples: List[Dict[str, List[int]]]) -> Dict[str, torch.Tensor]:
batch_inputs = []
batch_labels = []
for item in samples:
inp = item["input_ids"][: self.max_seq_len]
lbl = item["labels"][: self.max_seq_len]
pad_len = self.max_seq_len - len(inp)
batch_inputs.append(
torch.tensor(inp + [self.pad_token_id] * pad_len, dtype=torch.long)
)
batch_labels.append(
torch.tensor(lbl + [-100] * pad_len, dtype=torch.long)
)
return {
"input_ids": torch.stack(batch_inputs),
"labels": torch.stack(batch_labels),
}
class ConversationDataset(Dataset):
def __init__(self, data: List[Dict[str, List[int]]]):
self.data = data
def __len__(self) -> int:
return len(self.data)
def __getitem__(self, idx: int) -> Dict[str, List[int]]:
return self.data[idx]
def run_sft_demo():
device = HardwareContext.get_optimal_device()
autocast_dtype = HardwareContext.get_optimal_autocast_dtype(device)
print("Compute Device :", device)
print("Autocast Dtype :", autocast_dtype)
tokenizer = build_xonelm_tokenizer()
vocab_size = len(tokenizer)
token_cfg = SpecialTokenConfig(
pad_token_id=0,
bos_token_id=1,
eos_token_id=2,
unk_token_id=3,
eod_token_id=4,
)
formatter = MultiTurnConversationFormatter(tokenizer, token_cfg)
sample_dialogues = [
[
{"role": "system", "content": "You are a precise reasoning assistant."},
{"role": "user", "content": "Lily found a wooden box. What did she open?"},
{"role": "assistant", "content": "She opened the wooden box to see what was inside."},
],
[
{"role": "system", "content": "You are a polite companion."},
{"role": "user", "content": "Hello! How can we optimize memory bandwidth?"},
{"role": "assistant", "content": "We can compress Key-Value caches using low-rank latent projections."},
],
[
{"role": "system", "content": "You are a creative writer."},
{"role": "user", "content": "Tell me a story about a kitten in the garden."},
{"role": "assistant", "content": "Once upon a time, a tiny kitten chased a butterfly across the grass."},
],
]
formatted_samples = [formatter.format_conversation(dialogue) for dialogue in sample_dialogues]
dataset = ConversationDataset(formatted_samples)
collator = SafeSFTCollator(max_seq_len=256, pad_token_id=token_cfg.pad_token_id)
loader = DataLoader(dataset, batch_size=2, shuffle=True, collate_fn=collator)
model = XoneLM(
vocab_size=vocab_size,
dim=512,
num_layers=12,
num_heads=8,
kv_latent_dim=64,
hub_size=512,
num_specialized_hubs=12,
num_terminals=32,
slots_per_terminal=16,
).to(device)
optimizer = LuminaV(
model.parameters(),
lr=2e-4,
betas=(0.9, 0.999),
eps=1e-8,
weight_decay=1e-3,
tau=0.8,
buffer=2,
cautious=True,
execution="auto",
)
use_scaler = (device.type == "cuda" and autocast_dtype == torch.float16)
scaler = torch.amp.GradScaler("cuda", enabled=True) if use_scaler else None
model.train()
optimizer.zero_grad()
start_time = time.time()
for epoch in range(2):
for step, batch in enumerate(loader):
x = batch["input_ids"].to(device, non_blocking=True)
y = batch["labels"].to(device, non_blocking=True)
with HardwareContext.get_autocast_context(device):
output = model(x, labels=y, is_sft=True)
loss = output.loss
if scaler is not None:
scaler.scale(loss).backward()
scaler.unscale_(optimizer)
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
scaler.step(optimizer)
scaler.update()
else:
loss.backward()
torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)
optimizer.step()
optimizer.zero_grad()
print(f"Epoch [{epoch+1}/2] | Step [{step+1}/{len(loader)}] | SFT Loss: {loss.item():.4f}")
elapsed = time.time() - start_time
print(f"[+] SFT Training Demo completed successfully in {elapsed:.2f}s!")
if __name__ == "__main__":
run_sft_demo()