Files
paddlepaddle--paddlenlp/slm/examples/code_generation/codegen/run_clm.py
T
wehub-resource-sync 2aaeece67c
Pipelines-Test / Pipelines-Test (push) Waiting to run
Codestyle Check / Lint (push) Has been cancelled
Codestyle Check / Check bypass (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:37:14 +08:00

163 lines
5.9 KiB
Python

# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import math
from dataclasses import dataclass, field
from functools import partial
from itertools import chain
from typing import Optional
import paddle
import paddle.nn as nn
from datasets import load_dataset
from paddlenlp.data import DataCollatorWithPadding
from paddlenlp.trainer import PdArgumentParser, Trainer, TrainingArguments, set_seed
from paddlenlp.transformers import CodeGenForCausalLM, CodeGenTokenizer
from paddlenlp.utils.log import logger
@dataclass
class ModelArguments:
model_name_or_path: Optional[str] = field(
default="Salesforce/codegen-350M-mono",
metadata={"help": ("Path to pre-trained model.")},
)
overwrite_cache: Optional[bool] = field(
default=False,
metadata={"help": ("Whether to overwrite cache for dataset.")},
)
@dataclass
class DataArguments:
train_file: Optional[str] = field(
default=None,
metadata={"help": "The input training data file."},
)
validation_file: Optional[str] = field(
default=None,
metadata={"help": "The input validation data file."},
)
block_size: Optional[int] = field(
default=None,
metadata={"help": ("The training dataset will be truncated in block of this size for training. ")},
)
def compute_metrics(eval_preds):
labels = paddle.to_tensor(eval_preds.label_ids, dtype="int64")
logits = paddle.to_tensor(eval_preds.predictions)
loss_fct = nn.CrossEntropyLoss()
eval_loss = loss_fct(logits[:, :-1, :], labels[:, 1:])
perplexity = math.exp(eval_loss)
return {"perplexity": perplexity}
def convert_example(examples, tokenizer):
"""convert examples into necessary features"""
# Convert raw text to feature
tokenized_examples = tokenizer(
examples["code"], return_attention_mask=True, return_position_ids=False, return_token_type_ids=False
)
return tokenized_examples
def group_texts(examples, block_size):
concatenated_examples = {k: list(chain(*examples[k])) for k in examples.keys()}
total_length = len(concatenated_examples[list(examples.keys())[0]])
if total_length >= block_size:
total_length = (total_length // block_size) * block_size
result = {
k: [t[i : i + block_size] for i in range(0, total_length, block_size)]
for k, t in concatenated_examples.items()
}
result["labels"] = result["input_ids"].copy()
return result
def process_ds(dataset, tokenizer, overwrite_cache, block_size):
trans_func = partial(convert_example, tokenizer=tokenizer)
dataset = dataset.map(
trans_func, batched=True, remove_columns=dataset.column_names, load_from_cache_file=overwrite_cache
)
trans_func = partial(group_texts, block_size=block_size)
dataset = dataset.map(trans_func, batched=True, load_from_cache_file=overwrite_cache)
return dataset
def do_train():
parser = PdArgumentParser((ModelArguments, DataArguments, TrainingArguments))
model_args, data_args, training_args = parser.parse_args_into_dataclasses()
paddle.set_device(training_args.device)
if paddle.distributed.get_world_size() > 1:
paddle.distributed.init_parallel_env()
set_seed(training_args.seed)
model = CodeGenForCausalLM.from_pretrained(model_args.model_name_or_path)
tokenizer = CodeGenTokenizer.from_pretrained(model_args.model_name_or_path)
train_set = load_dataset("json", data_files=data_args.train_file, split="train")
dev_set = load_dataset("json", data_files=data_args.validation_file, split="train")
if data_args.block_size is None:
block_size = tokenizer.model_max_length
if block_size > 1024:
logger.warning(
f"The tokenizer picked seems to have a very large `model_max_length` ({tokenizer.model_max_length}). "
"Picking 1024 instead. You can change that default value by passing --block_size xxx."
)
block_size = 1024
else:
if data_args.block_size > tokenizer.model_max_length:
logger.warning(
f"The block_size passed ({data_args.block_size}) is larger than the maximum length for the model"
f"({tokenizer.model_max_length}). Using block_size={tokenizer.model_max_length}."
)
block_size = min(data_args.block_size, tokenizer.model_max_length)
train_set = process_ds(train_set, tokenizer, model_args.overwrite_cache, block_size)
dev_set = process_ds(dev_set, tokenizer, model_args.overwrite_cache, block_size)
batchify_fn = DataCollatorWithPadding(tokenizer, return_attention_mask=True)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_set if training_args.do_train else None,
eval_dataset=dev_set if training_args.do_eval else None,
tokenizer=tokenizer,
data_collator=batchify_fn,
compute_metrics=compute_metrics,
)
if training_args.do_train:
train_results = trainer.train(resume_from_checkpoint=training_args.resume_from_checkpoint)
metrics = train_results.metrics
trainer.save_model()
trainer.log_metrics("train", metrics)
trainer.save_metrics("train", metrics)
trainer.save_state()
if training_args.do_eval:
eval_metrics = trainer.evaluate()
trainer.log_metrics("eval", eval_metrics)
if __name__ == "__main__":
do_train()