From f28fcd52b85cd69d40b30743e0975dfaa94164fc Mon Sep 17 00:00:00 2001 From: kazuki Date: Mon, 12 Aug 2024 19:09:14 +0900 Subject: [PATCH 01/10] feat: support dist ckpt --- .../Llama-3-8B/Llama-3-8B-instruct-v0.2.sh | 9 +- src/llama_recipes/arguments.py | 3 + src/llama_recipes/finetuning.py | 12 +- src/llama_recipes/utils/checkpoint.py | 121 ++++++++++++++++-- 4 files changed, 128 insertions(+), 17 deletions(-) diff --git a/scripts/tsubame/instruct/Llama-3-8B/Llama-3-8B-instruct-v0.2.sh b/scripts/tsubame/instruct/Llama-3-8B/Llama-3-8B-instruct-v0.2.sh index fa9e3f5..7641741 100644 --- a/scripts/tsubame/instruct/Llama-3-8B/Llama-3-8B-instruct-v0.2.sh +++ b/scripts/tsubame/instruct/Llama-3-8B/Llama-3-8B-instruct-v0.2.sh @@ -1,7 +1,7 @@ #!/bin/sh #$ -cwd -#$ -l node_f=4 -#$ -l h_rt=0:20:00:00 +#$ -l node_f=2 +#$ -l h_rt=0:1:00:00 #$ -o outputs/Llama-3-8b-instruct/$JOB_ID.log #$ -e outputs/Llama-3-8b-instruct/$JOB_ID.log #$ -p -5 @@ -54,7 +54,7 @@ GRAD_CLIP=1 # checkpoint TOKENIZER_DIR=/gs/bs/tga-NII-LLM/hf-checkpoints/Meta-Llama-3-8B-Instruct CHECKPOINT_DIR=/gs/bs/tga-NII-LLM/swallow-hf/Llama-3-Swallow-8B-v0.1 -CHECKPOINT_SAVE_DIR="/gs/bs/tga-NII-LLM/checkpoints/Llama-3-8B-Instruct-v0.2/LR_${LR}_MINLR_${MIN_LR}_WD_${WEIGHT_DECAY}_GC_${GRAD_CLIP}" +CHECKPOINT_SAVE_DIR="/gs/bs/tga-NII-LLM/checkpoints/Llama-3-8B-Instruct-v0.2/LR_${LR}_MINLR_${MIN_LR}_WD_${WEIGHT_DECAY}_GC_${GRAD_CLIP}-dist-ckpt" mkdir -p ${CHECKPOINT_SAVE_DIR} @@ -94,7 +94,7 @@ mpirun -np $NUM_GPUS \ --adam-beta1 0.9 \ --adam-beta2 0.95 \ --adam-eps 1e-8 \ - --save-interval 500 \ + --save-interval 10 \ --eval-interval 500 \ --eval-iters 10 \ --bf16 \ @@ -108,6 +108,7 @@ mpirun -np $NUM_GPUS \ --fsdp-activation-checkpointing \ --instruction-tuning \ --save-sampler-state \ + --use-dist-ckpt \ --use-mpi \ --wandb-entity "prj-jalm" \ --wandb-project "Llama-3-8B-Instruct-v0.2" \ diff --git a/src/llama_recipes/arguments.py b/src/llama_recipes/arguments.py index c69f447..8772372 100644 --- a/src/llama_recipes/arguments.py +++ b/src/llama_recipes/arguments.py @@ -64,6 +64,9 @@ def _add_fsdp_args(parser: argparse.ArgumentParser) -> argparse.ArgumentParser: group.add_argument( "--no-meta-device", action="store_true" ) + group.add_argument( + "--use-dist-ckpt", action="store_true" + ) return parser diff --git a/src/llama_recipes/finetuning.py b/src/llama_recipes/finetuning.py index 8669558..786b946 100644 --- a/src/llama_recipes/finetuning.py +++ b/src/llama_recipes/finetuning.py @@ -32,6 +32,8 @@ from llama_recipes.utils.checkpoint import ( load_model_state_dict, load_optimizer_state_dict, + load_dist_model_state_dict, + load_dist_optimizer_state_dict, load_scheduler_state_dict, load_rng_state_dict, get_latest_iteration, @@ -108,7 +110,10 @@ def main() -> None: param.requires_grad = False if args.load: - load_model_state_dict(model, args.load) # type: ignore + if args.use_dist_ckpt: + load_dist_model_state_dict(model, args.load) # type: ignore + else: + load_model_state_dict(model, args.load) # type: ignore print_model_size(model, args.base_model, rank) # type: ignore @@ -271,7 +276,10 @@ def main() -> None: ) if args.load: - load_optimizer_state_dict(model=model, optimizer=optimizer, path=args.load) # type: ignore + if args.use_dist_ckpt: + load_dist_optimizer_state_dict(model=model, optimizer=optimizer, path=args.load) # type: ignore + else: + load_optimizer_state_dict(model=model, optimizer=optimizer, path=args.load) # type: ignore if args.lr_decay_style == "cosine": scheduler = WarmupCosineAnnealingLR( diff --git a/src/llama_recipes/utils/checkpoint.py b/src/llama_recipes/utils/checkpoint.py index 4826138..28ede6b 100644 --- a/src/llama_recipes/utils/checkpoint.py +++ b/src/llama_recipes/utils/checkpoint.py @@ -7,7 +7,9 @@ StateDictType, # type: ignore FullStateDictConfig, # type:ignore : general model non-sharded, non-flattened params ) +import torch.distributed._shard.checkpoint as dist_cp from torch.distributed.fsdp.api import FullOptimStateDictConfig +from torch.distributed.checkpoint.optimizer import load_sharded_optimizer_state_dict from pathlib import Path import os import gc @@ -15,7 +17,7 @@ from megatron_lm.megatron.global_vars import get_args, get_sampler -def get_model_state_dict(model: FSDP) -> dict[str, torch.Tensor]: +def get_local_model_state_dict(model: FSDP) -> dict[str, torch.Tensor]: with FSDP.state_dict_type( model, StateDictType.FULL_STATE_DICT, @@ -26,7 +28,7 @@ def get_model_state_dict(model: FSDP) -> dict[str, torch.Tensor]: return state_dict -def get_optimizer_state_dict(model: FSDP, optimizer: torch.optim.Optimizer) -> dict[str, torch.Tensor]: +def get_local_optimizer_state_dict(model: FSDP, optimizer: torch.optim.Optimizer) -> dict[str, torch.Tensor]: with FSDP.state_dict_type( model, state_dict_type=StateDictType.FULL_STATE_DICT, @@ -38,8 +40,34 @@ def get_optimizer_state_dict(model: FSDP, optimizer: torch.optim.Optimizer) -> d return state_dict +def save_dist_model_and_optimizer_state_dict( + model: FSDP, optimizer: torch.optim.Optimizer, path: str +) -> None: + if torch_distributed.get_rank() == 0: + print(f"Saving model and optimizer state dict to {path}") + t0 = time.perf_counter() + + FSDP.set_state_dict_type( + model, + StateDictType.SHARDED_STATE_DICT, + ) + optim_state_dict = FSDP.optim_state_dict(model, optimizer) + state_dict = { + "model": model.state_dict(), + "optimizer": optim_state_dict, + } + dist_cp.save( + state_dict=state_dict, + checkpoint_id=path, + ) + torch_distributed.barrier() + t1 = time.perf_counter() + if torch_distributed.get_rank() == 0: + print(f"Saved model and optimizer state dict to {path}, took {t1 - t0:.2f}s") + + def save_model_state_dict(model: FSDP, path: str) -> None: - state_dict = get_model_state_dict(model) + state_dict = get_local_model_state_dict(model) if torch_distributed.get_rank() == 0: print(f"Saving model state dict to {path}") torch.save(state_dict, path) @@ -49,7 +77,7 @@ def save_model_state_dict(model: FSDP, path: str) -> None: def save_optimizer_state_dict(model: FSDP, optimizer: torch.optim.Optimizer, path: str) -> None: - state_dict = get_optimizer_state_dict(model, optimizer) + state_dict = get_local_optimizer_state_dict(model, optimizer) if torch_distributed.get_rank() == 0: print(f"Saving optimizer state dict to {path}") torch.save(state_dict, path) @@ -111,16 +139,24 @@ def save_checkpoint( start = time.time() print(f"Saving checkpoint to {checkpoint_path}") - save_model_state_dict( - model=model, - path=f"{checkpoint_path}/model.pt", - ) - if not args.no_save_optimizer_state: - save_optimizer_state_dict( + if args.use_dist_ckpt: + save_dist_model_and_optimizer_state_dict( model=model, optimizer=optimizer, - path=f"{checkpoint_path}/optimizer.pt", + path=checkpoint_path, + ) + else: + save_model_state_dict( + model=model, + path=f"{checkpoint_path}/model.pt", ) + if not args.no_save_optimizer_state: + save_optimizer_state_dict( + model=model, + optimizer=optimizer, + path=f"{checkpoint_path}/optimizer.pt", + ) + if args.save_sampler_state: sampler = get_sampler() @@ -165,6 +201,34 @@ def load_model_state_dict(model: torch.nn.Module, path: str) -> None: print(f"Loaded model state dict from {latest_checkpoint_path}/model.pt") +def load_dist_model_state_dict(model: FSDP, path: str) -> None: + latest_iteration: int = get_latest_iteration(path) + if latest_iteration == 0: + if torch_distributed.get_rank() == 0: + print(f"No checkpoint found in {path}, skipping model loading") + return + + latest_checkpoint_path: str = get_checkpoint_name(path, latest_iteration) + + if torch_distributed.get_rank() == 0: + print(f"Loading model state dict from {latest_checkpoint_path}") + + t0 = time.perf_counter() + FSDP.set_state_dict_type( + model, + StateDictType.SHARDED_STATE_DICT, + ) + state_dict = {"model": model.state_dict()} + dist_cp.load( + state_dict=state_dict, + checkpoint_id=latest_checkpoint_path, + ) + model.load_state_dict(state_dict["model"]) + + if torch_distributed.get_rank() == 0: + print(f"Loaded model state dict from {latest_checkpoint_path}, took {time.perf_counter() - t0:.2f}s") + + def load_optimizer_state_dict(model: FSDP, optimizer: torch.optim.Optimizer, path: str) -> None: latest_iteration: int = get_latest_iteration(path) if latest_iteration == 0: @@ -192,6 +256,41 @@ def load_optimizer_state_dict(model: FSDP, optimizer: torch.optim.Optimizer, pat print(f"Loaded optimizer state dict from {latest_checkpoint_path}/optimizer.pt") +def load_dist_optimizer_state_dict(model: FSDP, optimizer: torch.optim.Optimizer, path: str) -> None: + latest_iteration: int = get_latest_iteration(path) + if latest_iteration == 0: + if torch_distributed.get_rank() == 0: + print(f"No checkpoint found in {path}, skipping optimizer loading") + return + + latest_checkpoint_path: str = get_checkpoint_name(path, latest_iteration) + + if torch_distributed.get_rank() == 0: + print(f"Loading optimizer state dict from {latest_checkpoint_path}") + + t0 = time.perf_counter() + FSDP.set_state_dict_type( + model, + StateDictType.SHARDED_STATE_DICT, + ) + state_dict = {"model": model.state_dict()} + dist_cp.load( + state_dict=state_dict, + checkpoint_id=latest_checkpoint_path, + ) + optim_state = load_sharded_optimizer_state_dict( + model_state_dict=state_dict["model"], + optimizer_key="optimizer", + storage_reader=dist_cp.FileSystemReader(latest_checkpoint_path), + planner=dist_cp.DefaultLoadPlanner() + ) + flattened_optim_state = FSDP.optim_state_dict_to_load(model, optimizer, optim_state["optimizer"]) + optimizer.load_state_dict(flattened_optim_state) + + if torch_distributed.get_rank() == 0: + print(f"Loaded optimizer state dict from {latest_checkpoint_path}, took {time.perf_counter() - t0:.2f}s") + + def load_scheduler_state_dict(scheduler: torch.optim.lr_scheduler.LRScheduler, path: str) -> None: latest_iteration: int = get_latest_iteration(path) if latest_iteration == 0: From 13c6375ee569b2fa41c53e5a528019bfb1307f96 Mon Sep 17 00:00:00 2001 From: kazuki Date: Mon, 12 Aug 2024 19:10:31 +0900 Subject: [PATCH 02/10] feat: llm-jp dataset checker --- .../checker/llm_jp_instruct_checker.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 tools/dataset/checker/llm_jp_instruct_checker.py diff --git a/tools/dataset/checker/llm_jp_instruct_checker.py b/tools/dataset/checker/llm_jp_instruct_checker.py new file mode 100644 index 0000000..69f26b1 --- /dev/null +++ b/tools/dataset/checker/llm_jp_instruct_checker.py @@ -0,0 +1,20 @@ +import argparse +import json + +parser = argparse.ArgumentParser() +parser.add_argument("--input", type=str, help="Input file path") +args = parser.parse_args() + +with open(args.input, "r") as file: + lines = [json.loads(line) for line in file] + print(f"Number of lines: {len(lines)}") + for line in lines: + conversations = line["conversations"] + assert isinstance(conversations, list) + assert len(conversations) % 2 == 0 + for i in range(0, len(conversations), 2): + assert conversations[i]["role"] == "user" + assert conversations[i+1]["role"] == "assistant" + assert len(conversations[i]["content"]) > 0 + assert len(conversations[i+1]["content"]) > 0 + print("All checks passed") From 71b2732f454487bfa6b965701510ff906c8fb7f1 Mon Sep 17 00:00:00 2001 From: kazuki Date: Tue, 13 Aug 2024 00:11:06 +0900 Subject: [PATCH 03/10] fix: skip batch --- src/llama_recipes/arguments.py | 3 --- src/llama_recipes/utils/train_utils.py | 18 ++++++------------ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/llama_recipes/arguments.py b/src/llama_recipes/arguments.py index 8772372..80d872b 100644 --- a/src/llama_recipes/arguments.py +++ b/src/llama_recipes/arguments.py @@ -261,9 +261,6 @@ def _add_training_args(parser: argparse.ArgumentParser) -> argparse.ArgumentPars # model group.add_argument("--sliding-window-size", type=int, default=4096) - # loss spike - group.add_argument("--skip-batch", nargs='*', default=None) - # checkpoint group.add_argument("--no-save-optimizer-state", action="store_true") diff --git a/src/llama_recipes/utils/train_utils.py b/src/llama_recipes/utils/train_utils.py index 12b948e..cff3b2d 100644 --- a/src/llama_recipes/utils/train_utils.py +++ b/src/llama_recipes/utils/train_utils.py @@ -8,6 +8,7 @@ from torch.nn.utils import clip_grad_norm_ # type: ignore from llama_recipes.policies import fpSixteen, bfSixteen, bfSixteen_mixed, get_decoder_layer_wrapper +from llama_recipes.utils.distributed import print_rank_0 from llama_recipes.utils.wandb_utils import log_model_info, log_wandb from llama_recipes.utils.checkpoint import save_checkpoint, get_latest_iteration from llama_recipes.utils.dpo_loss import DPOLoss @@ -79,19 +80,13 @@ def train( eval_dataloader = iter(cyclic_iter(eval_dataloader)) # skip batch - skip_batches: list[tuple[int, int]] = [] - consumed_iters: int = iteration - if args.skip_batch: - skip_batches = parse_skip_batch(args.skip_batch) - - while iteration < args.train_iters: - # skip batch logic - while len(skip_batches) > 0 and skip_batches[0][0] <= consumed_iters <= skip_batches[0][1]: + if args.instruction_tuning or args.direct_preference_optimization: + assert args.continual_pretraining is False + print_rank_0(f"Skipping {iteration} batches") + for _ in range(iteration): next(train_dataloader) - consumed_iters += 1 - if len(skip_batches) > 0 and skip_batches[0][1] < consumed_iters: - skip_batches.pop(0) + while iteration < args.train_iters: iteration_start_time = time.perf_counter() model.train() @@ -179,7 +174,6 @@ def train( # gradient accumulation end iteration += 1 - consumed_iters += 1 if args.fp16: scaler.step(optimizer) # type: ignore (= optimizer.step()) From e1ca715c6fe7ac82d735a488d7b2d9ba112b54a1 Mon Sep 17 00:00:00 2001 From: kazuki Date: Tue, 13 Aug 2024 00:12:07 +0900 Subject: [PATCH 04/10] docs: add reference --- src/llama_recipes/utils/checkpoint.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/llama_recipes/utils/checkpoint.py b/src/llama_recipes/utils/checkpoint.py index 28ede6b..85d8cc3 100644 --- a/src/llama_recipes/utils/checkpoint.py +++ b/src/llama_recipes/utils/checkpoint.py @@ -214,6 +214,7 @@ def load_dist_model_state_dict(model: FSDP, path: str) -> None: print(f"Loading model state dict from {latest_checkpoint_path}") t0 = time.perf_counter() + # ref: https://github.com/pytorch/pytorch/blob/main/test/distributed/checkpoint/test_fsdp_optim_state.py FSDP.set_state_dict_type( model, StateDictType.SHARDED_STATE_DICT, @@ -269,6 +270,7 @@ def load_dist_optimizer_state_dict(model: FSDP, optimizer: torch.optim.Optimizer print(f"Loading optimizer state dict from {latest_checkpoint_path}") t0 = time.perf_counter() + # ref: https://github.com/pytorch/pytorch/blob/main/test/distributed/checkpoint/test_fsdp_optim_state.py FSDP.set_state_dict_type( model, StateDictType.SHARDED_STATE_DICT, From 5eae9eb2869ef4e8593f7cbfd7a824c4ab793b01 Mon Sep 17 00:00:00 2001 From: kazuki Date: Fri, 16 Aug 2024 21:21:13 +0900 Subject: [PATCH 05/10] release: v1.0 (add docs) --- README.md | 165 ++++++++++++++++++++-- images/llm-recipes-logo.webp | Bin 0 -> 146644 bytes requirements.txt | 7 +- scripts/abci/phi3/phi3-14b.sh | 2 +- scripts/gcp/codestral-22b.sh | 10 +- scripts/gcp/tokenize/codestral-ja-wiki.sh | 8 +- scripts/gcp/tokenize/yi-1.5-ja-wiki.sh | 6 +- scripts/gcp/yi-1.5-9b.sh | 10 +- 8 files changed, 173 insertions(+), 35 deletions(-) create mode 100644 images/llm-recipes-logo.webp diff --git a/README.md b/README.md index d321c82..25b2af1 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,49 @@ -# LLM Recipes +
+ +llm-recipes +=========================== +

User-friendly tool for seamless continual pre-training of Large Language Models

+ +llm-recipes + +
+ +llm-recipes is a tool designed to make the continual pre-training of Large Language Models (LLMs) easy and efficient. With an intuitive interface and flexible configuration options, researchers and developers can effortlessly manage training on any model or dataset. The tool supports distributed training on large GPU clusters and offers extensive customization, enabling users to leverage cutting-edge techniques with ease. + +What sets llm-recipes apart is its seamless integration with Hugging Face Transformers, allowing you to continue pre-training or perform instruction tuning on Dense LLMs (non-MoE models) with minimal changes. This means there’s no need to convert checkpoints or deal with complex workflows—just focus on refining your model. # Table of Contents -1. [Installation](#installation) -2. [Instruction Tuning](#instruction-tuning) -3. [LLM Continual Pre-Training](#llm-continual-pre-training) +- [Installation](#installation) + - [Multi-node Support](#multi-node-support) + - [FlashAttention](#flashattention) +- [Usage](#usage) + - [LLM Instruction Tuning](#llm-instruction-tuning) + - [LLM Continual Pre-Training](#llm-continual-pre-training) + - [LLM DPO](#llm-dpo) +- [Checkpoint formats](#checkpoint-formats) + - [llm-recipes format](#llm-recipes-format) + - [PyTorch format to Hugging Face format](#pytorch-format-to-hugging-face-format) + - [PyTorch distributed format to Hugging Face format](#pytorch-distributed-format-to-hugging-face-format) +- [Inference](#inference) +- [Training Speed and Scalability](#training-speed-and-scalability) +- [Projects Using llm-recipes](#projects-using-llm-recipes) +- [Citation](#citation) ## Installation -To install the package, run the following command: +This package has been tested with Python 3.10 and 3.11. The recommended environment is with CUDA Toolkit 12.1. + +To install the required packages, simply run: ```bash pip install -r requirements.txt ``` +> Note: The requirements.txt assumes that CUDA Toolkit 12.1 is installed on your system. + +### Multi-node Support -If you want to use the library in multi-nodes, you need to install the below packages: +For multi-node support, ensure you have the following dependencies installed: ```bash module load openmpi/4.x.x @@ -24,21 +53,131 @@ pip install mpi4py ### FlashAttention -To install the FlashAttention, run the following command: (GPU is required) +For GPU-accelerated FlashAttention, follow these steps: ```bash pip install ninja packaging wheel pip install flash-attn --no-build-isolation ``` -### ABCI +## Usage + +### LLM Instruction Tuning + +#### 1. **Data Preparation** + +Prepare your data in the below format and save it as a JSONL file: + +```jsonl +{ + "input": [ + { + "role": "user", + "content": "What is the weather like today?" + } + ], + "output": { + "role": "assistant", + "content": "The weather is sunny with a high of 25 degrees." + } +} +``` + +#### 2. **Change Dataset Class** + +Please modify the `Dataset` class in `src/llama_recipes/utils/instruction_tuning.py` to adjust to the model's expected format. +But, almost all the models have chat templates, so you may not need to change the `Dataset` class. + +#### 3. **Indexing** + +To load dataset efficiently, create an index file using the following command: + +```bash +python tools/pre-process/index_dataset.py \ + --data-file-path +``` + +After indexing, `.index_cache` directory will be created in the same directory as the JSONL file. + +#### 4. **Training** + +We provide an example script for instruction tuning for Llama-3-8B in `scripts/tsubame/instruct/Llama-3-8B/Llama-3-8B-instruct-v0.2.sh`. +You can modify the script to suit your needs. + +### LLM Continual Pre-Training + +#### 1. **Data Preparation** + +Prepare your data in the below format and save it as a JSONL file: + +```jsonl +{ + "text": "What is the weather like today?\nThe weather is sunny with a high of 25 degrees." +} +``` + +#### 2. **Tokenize Data** + +Tokenize your data using the tokenizer provided by the model you are using. +For example, to tokenize data for Codestral(Mistral-AI), run the following command: + +```bash +DATASET_DIR=/path/to/datasets/samples +OUTPUT_DIR=/path/to/datasets/debug/Codestral-22B-v0.1 + +mkdir -p ${OUTPUT_DIR} + +python megatron_lm/tools/preprocess_data.py \ + --input ${DATASET_DIR}/ja_wiki.jsonl \ + --output-prefix ${OUTPUT_DIR}/ja_wiki \ + --tokenizer-type Llama2Tokenizer \ + --tokenizer-model /path/to/hf_checkpoints/Codestral-22B-v0.1/tokenizer.model \ + --append-eod \ + --workers 64 +``` + +#### 3. **Training** + + + +### LLM DPO + +we experimentally support DPO, but it is not fully tested. +The documentation will be updated soon. + + +## Checkpoint formats + +### llm-recipes format + +llm-recipes creates 2 types of checkpoints: PyTorch format and PyTorch distributed format. +The PyTorch format is a simple checkpoint format. The example of the PyTorch format is as follows: + +```bash +model.pt optimizer.pt rng.pt sampler.pt scheduler.pt +``` +PyTorch distributed format is a checkpoint format that can be distributed-loaded using `torch.distributed`. +The example of the PyTorch distributed format is as follows: + +```bash +__0_0.distcp __1_0.distcp __2_0.distcp __3_0.distcp __4_0.distcp __5_0.distcp __6_0.distcp __7_0.distcp rng.pt sampler.pt scheduler.pt +``` + +### PyTorch format to Hugging Face format + +### PyTorch distributed format to Hugging Face format + + +## Inference + +## Training Speed and Scalability -If you use [ABCI](https://abci.ai/) to run the experiments, install scripts are available in `llm-recipes/install.sh`. +## Projects Using llm-recipes -## Instruction Tuning +Below are some of the projects where we have directly used llm-recipes: -[scripts/abci/instruction](scripts/abci/instruction) contains the scripts to run instruction tunings on ABCI. +- [Continual Pre-Training for Cross-Lingual LLM Adaptation: Enhancing Japanese Language Capabilities](https://arxiv.org/abs/2404.17790) +- [Building a Large Japanese Web Corpus for Large Language Models](https://arxiv.org/abs/2404.17733) -## LLM Continual Pre-Training +## Citation -Docs is coming soon. diff --git a/images/llm-recipes-logo.webp b/images/llm-recipes-logo.webp new file mode 100644 index 0000000000000000000000000000000000000000..e7b611ed4597503302dbe9626609971756bb36d1 GIT binary patch literal 146644 zcmXVX1zc0#|2~WX8#%gRNJ~q1DTtIHT~gA*Xa%U+ogU6x0}Z!^Z=;N+atvBV`1xTh=t#+9TT)-D zI=Q3`n=qb__F_A9oEd8nfoc%jWv)Nhe`|g9~hPcn7Me+pt zw%X&JH8C^IlZHo@$9V=p~CNr8Jx#QZY=mXnRVuTX`FLbPF$(3R(YS zLi)otvR*ueeYY8t2GPwaraAX{=Z`A7R$~3)O~)ewAaI`AKir2Zr^2nFS861e+c(n@|E!s8(V$kX zEJZc)N8&rni?;tOB>rgjW)Y_ODhp+*X5zXg4YI77{zE>ZzON2WVvX;Z-XM5Y=4XPd zn*7AdS@5C4Q7IV0s2KOd%J7%pE^A7V0Au;ZJoY!}2$^TOdh7F-m&O0rV8bW%{TjeP zv0t@ijQgjV4*f9awTDedrLIj!zsS9(JF0;9mmlL_VjFR$WLBW{D{1Ea9s)r8C^fE8 zYx%ZWDg%}1dJlcTjh-62m>TN7m(+g63LU7y@hTZGjP;Wt!?m+YQj7J=88S>#3tPx= z!FiOZmP0rqZ;T)NX&_EDUob}WJsbq7YGB!KVA%I&rp#+#U4BHW{KMYD_`mB2M;u4I zzKnee&u4+s4H+8arLd81i;V?9P0l>p)24)!C~rQWc>zHI9lh-4uA}U`Bu=C(&FC-X znfc9Vw7QtnFfOodzEES109O@OmLoO~F!%lxiQ_aEO^{`tM*E>;4&nT%yT^U6ZQ$BBOIWgBH*735)n|`pCY|sz*tdl=+j&kz`&cxg#^(v z=87CERJ}c#upnN)|wyj)|#U-r>w!`mT8}W?1)C3eDGv` zRO1E=mZC;jlA~QP>J_LSsa1%8HR4VJ4&X8sQp+lxVT+Aap9uELyb%zbk%iTn&3WAZt5yV03^h3={+7Rz^e6x?(QQYR=9-tdr*sWk;hj zb7c@(C`M+a#*My*qJg48;d}lY)F#JPWfUPsLP(}*OG0R55tZM*k!tzN8pImK+zE{# zdvw{G!-TRtAy^y7cS1S*3U> zg7}*TfjVsv^qUZCO!d;37C>0@!>uo!3&)AV&GRu0YgV(u`mS`i`cafJy}znzv|0<* z8ux@o{kZN#NCILaGK9hd0e@EL`^K7LVa{d5a?Iq((cmXd$UtZUwv$6^Ht|*DYqGXz zz1A%su#;^(8S~H2-`O$RTmfbXP!aznoYxi3K75Un~;U{mJ>iV%GB(W2wm;Hkq0tMTp z^xPIeI4Vvji=CIH6;WUxwb%(sZTc%u3KX&#wmV`G)k<8O`iTc_e$9wv5|Pd^+1#qfrReWO}j39>RQe_HH6>=V{I2d5TbKXKn`FLbzBk%`8I6vVoj#ys|^p&&sqLVm6*EPLz|pdB%V*QI*IZ(7JLDfgRsZxJ-xNCE7t3@F9k zA$Y}zR5c936Fm>A&KLGIYNNHDM!P7eOZyr~6Nivau6R3x*e$);5wP8a8W3AKKT-o+ zG{CVvGlz(6e0?E6=Xr+B<8wAiKClA>}2voBI)5P@7 zMw}>*5KM*aRo*KG`iKbErNx+tWPG5&QZaoYADNRhyZ0-eO21da8ILIwimt%;9 zWQg^=`BqM8G5Fzn9P*=y)1)yl5TV(7KRN_V4_TtJ+b)ApQ;VDrtUZwjd!8hA(@9gQ z!nRYjgy2Ss${<`J@uz43c`kX5E^gRK{z+~xY1to=&oqHldfwdO8mb!M%7Abti~%Zy zadr|}iIF(!w!TTok{gSW_Zf*_0riUjz0(5P10=_3ACUtd$$z5qrY)r0#@jqZR13gU z+B1|{5y1@6Zg7aCRt2sMF%#nlL~q!E<|f>>(b9_}gmgf@c9A>+8qPeDw^v=zTzTi*^a3g|Bv0m|Gf( zYB4n9Vwoln1L!6VP?>ULazes0!!YNmocRL!!0>5<*hpfp&tl~HGCso0`R#Njv9X$F<=rwAY~47?k}liCoN=Wn_mff*Y20yI6PH0EH&rj?R^HO zxBiZW7&g_GHy;T~d^V+fn^Ss;k&!s?z)DS}d^QFpz;(CX{F%5El3!LQcXSZ|EW~{2 zE;Nk10@s2)FE^G$jNq-7qfWN%(Ur>op%L5rkU9b>)!l^X6Gd;&S}=C53CpLwu1)oW zXDUsw4JB{w^iENRM*j`Ho2KVd1)V%ZM&amzV;tFm(-S2$Ia2AFK|$edbc(8BS`7@U zfkk@m_8yKT@`9FUB!nfzvS;=A%{ys`%D~MeChH9up+I6DMBJ&y-3zqh_1BH5l_h%@;FL;Mtzfd=nl2P`QcMw-c8i4Q5wAcx3Y1&VGuW7-O}3~+T@mlOJgEXVC3@=a zk{v{UOrI8Q9{(I3KAtA}NLD3EDkOgXF)ykTpHc`RcPOzRLBJ*`Uxo$l2VJYATZ{2u z&Qb-I-n)vJzg)xD|GIF_YMqXOvV4hdcWfQy&#y}mkZs)IQJ|5D|EzCPqwo7RLy3#L zTFF77bS6!1HiDDXzmRj0rE36Hr;>KWF1VFe2~XmD%Cng!m&25j1>wXZHpOEh%2 zSyB~L(&1kC)Z>xn$HCt;B|Y)U)fy_M)$@*+PX@F6W8HUtvZb~R%`3n_SQTvAc2ZTENmLmoTtNV` z0&M@^LM^KpFO9Um+ySpe{{E?#03%uc!`51_QMpmq$Uq2s`b%FqBv-;`w4?-UhRPkm z^I|5K6?{>O?<(ql45)Z?jgB%2U~(;vMmmTw4B@RJkn(p*B=lw40C90?pWP=>Qewr7 z+&;{w=ZGRwpSRN7CGN65Sk$%NcELy-YMP9eA4OfA_O0A_+4SI{9A1rjzC^(Ix*jki zI}vDse0)krNEzmhl3ZxwNidq+GgT;}1pvMRfZ3{Y<^wg+kiy1G!atEwvZ3B5`k|d~ zaS|xi84?~vsi7fcxTwp9#(fzed@HS--a%`!NH`NT>9Uk;Vf@%oPNIiejF6%}?(_x}+VQs{$xqgXD_1j&bhhr`v3ZJh0ng?3k26`IlJPzL)ZLvP@1Uz? z;5$zHZLZb~1j+HNCWZ?h!RZiK*~Q&O1IP0grai}1PPr^yXG`_|9ni>;7ep$m9wVQo zM%PQn6M%cPad5hx{Uo*K6#Es}0y@9Lb^MW9oZ+@P2eZO_KHydBM+PHqR z0#f+yQ`)srGQsp5c5x7bNqJOqHgfiCizQ<@MvIhH0s+CUlL16ACru&Gw|UQ~HeO!b z-cH^*5{OB^AjUuuS{SUgnoJeQBLxuNo1A?8U20r!YrxYv`@RH*1WP!|A#iG8u@=Oy z5tUCHe>*TfZG$$=pi`%<1B+nxV#*+=@ZeVMLWjcltJ$COLZ18Biwc`gEa&Gstw<$X zzZSAuo-PDp(je2?pa3Mh{AiB5tWK}ZYfJ8jp{{pUtN!=3Y2y%xtSfC`H1NR-wy~Hq z&hLz04*!PkQz@OERsKycx?%Zd5V>iY^UUPw$ZI?)AgshpL&$GhKp8e#lEV}pY(1|H z)5qmm`hZ*I8rzbBj-ZB>m0gI^=$P|T{ROI$`nx4NbuTKs{9dVil?Kj{+<6#|p1 zMmSF9w@;%D0-uCcBGj%QkDanzT&=`D`Fc+WI~I;lY|>=(kQQ%4zgzhc2?N0*CI*npNe%na4o1WhiSE@FGtIM13v^cUGaD?pI^ULQ~q!4yA^J@2qCWacw0MO zSfh1hPnhYthP2kkQg+}39fS+y@qee*w>VsOw8B0Gx5? z=IUj|iD;9bg2qUjaK8U(UG_)mU4}2e{#&6`EiX9bz$Y*Gnw!-6r+ERh!$(w5)1BnM z{P*AAUf$ko-bqicslX3H;#D|`bDdZaE?x2s|Gm4058E-}l{eA=UbXCCV5F-NjQnlM z`nl9~?c3YhVbAk_ZnQ%9vuLpsTJIVS>sPXR4Y)DCD65ogkHS3@5@r(~{kM#8g(W|j zTD-l^SPAyrD0}T;zHJ82%i7b$cClU`MpSWF$-9wAS%h^d}F|SLM*Em|Cm- zg7aP?Fh;zbA;Zy7FYpQZwxD4ZZ*(xYp`LL%x`^g0a{X{DI<8yTnksgB z2x$ULuCq+Cv^hf~v(+R`WXfwaGn0!49z#N>iV$lX=D^Z1fCuI~ujQr`J5S_JDHa}} zqfHY*k=TFzo=^s1(VhWMdPU*)ulJAMGbMjz@oQPn&ijD7-_IGJzY{-ao=RN-_0e`^ zxpz3a<;XpHCN_V-F0XO+Am9T&1nRAlJNkLy87uhF6cc2Vf-}V}igkzGMxr?E^_sC_ z(CLK98Ds2-_>a%Rv7*V)V_*81c8WZ&mT>yoW2L)?H4$};m(h`5ZysuVqs||xekIq( z(cbJnRzV1cbb9YTmV6UCw`IN`pW2+I1fxWZ|L3U?x26OMna<+O*9A5+8?{_ z{Qc0s_Wb_fl-Aq*yZ9Y){LW25=cb9|aqLO1WSC>&3>Nx;ASdrH)LC74KTN9`smw0z zBb#|{n)^H>#y3(n{$x~$bDTJfjDcxC?;%;BT)>pnGvCwIzYj1{Ls}?iMT#My2%t<`-Q}nBii>6k(oFjLxl+si z)S>X_xTOo8yTs#vOkND~d|m3Yqr)zJoG4Utc+%)o7;geBP~oqhdoyV<#vh(NGa97jMYQXE`^(_ZRmo5pGO~K zsko1V?~k{3Q1ekJhcoe_!eESbAf$(V{Z0ymF=9uk1)>EkK`M+NEa(l#PefVYcn7~x zeIRg#Mo-lH9B*%(sSpfF+h#l$>`c?J`i_>sxP;R+b$S_4AI=rk?3jJ!h-!*A-k2)r1 z0iV4x#6xSEAqT+^$OHqp3+%)+Q*`SkY{y3c;}$``e{>#m>*7E^*9HAM=)4HM7KD{b z@z%dcND!!dN~#7*K42V8gsGX2aqY=3;_485+`g1GeI+QB0$iYJ*&5ifO>?l}mrUo} z^V?#PCrt3MpWt8+R95eM0edjw?1W|Iri>7~sjW=5N;)Q2P9f{FEMTD5~r3ER|#9O#+9+dx-K= zV$8Gv3`B>ex70>fnJk}IpBe}cXsT>Ro``MC2RYpgw*scTocpR>&=Bhl1MKn(K_{v4 z*T98wv1FJSvP7&Rd|u&lGkmgedo%nz;dXoWg|4oy$HBA_3hU0sL}Sqpu-S&M_k!C; z)$`78?Mk>bTbkwzGXA1+ zv>u@c|9$ti?j>Pz*AV+k`X|CQ%@zfs^8L-0aHlqOv{+6D&kH@D9iP>el>+`7=|ajH z3@!Uqhf7YtNb4{j_zD@B#0YfZMu?Zu$cXihKSo)+W%2Cndz1bE8SC`-iH{iD#@5Lr zUEeWEdx$!*s#f9LL|zmz87?B&(bnI7rSS38iO=da>HYEjm69qNN)f0Fodif>A=nYO zCQ7_)e{-nk3!CzWSl3*>OcQkkaUq6*WlP_*NF}=s>E~ zn0U5%j0A-K$=r=A&E9)W>$mYJ)cSCN&pFefA(bZ&MAh-mByF_pSw}xbTwKcCGknDl z=Z^dKqbtN5?<#03bN;ytp0W9=H?2&DK5Allw84nOBfrfSo-nfg9 zGZF|?myTq&x}#OTVdZ@P>iiaMLZfYLMsbxRh#(|636sxu0jG7-9#JobflqZF34qMF@X!mci?M%hh;%0HEOWV3KHqFam%-g=9T`2Q#Rl{bj zK`726mj7T!(bU7LP-}dY)MtM)&~m)A;z{}hv4=-R&8UaysL$T-_NM%mI*aaI$48zV zE2mGLVVb&^y=5t{2?IFq9-fe&HcB&Xe4y}MtWL6KV?~4VZEBcnqtb9tocVoNc6S;b zZMiF$u?^etJS-$7)8?+fwGHh#884@D1#`eSES=R_`sGF|BJ&S3ThAnbZ5L&I^88a{ z8e=<7-y66s3f~_`OB8H!T;73j9|h2&9F8*GWf5ZR<}fXf+gr^2&#cg^Q#I#DG_C;} zF@cb6>BjH-8FKC_WJB~^-$Z17^QJ(s&KfuiAk6SZ@U?b}^yUt3?ax*pE`<35BPxsl z0%v~ZM7Dj}Od9Ah!V%-+xGg9n)z4W<7t0H;&}T{W=mH2I(1)CDK3x3s_FvknI;H%54j|w?B?Be6$9{O7rYvH}n47>ws4(uxh zdWhgpBg7=FI=B2=(U?jSzX1lr=RajBP|JeHoskVuAx%C$c7&C;z(>NMA^vPF7ol@{vH)YO9HkLw&giVfKA2Z9hBoh~p;>SjKNc|Q~7#&p` z0o!m_3 zK+qfrE$V<@KA>si<~@zN!``iNAq?6$rH6`a;K%hbhb#&SMXx4ovsFw}S2RX26_N z2x1_dFg|9a8{-Pq_M<ZA9kT75r!;*vX+S1M$FI?V%W<5@}rC0 zGefx(0Wk}_iq9XNTkW%$gEkSf?GY34ljAGeTph~-k=gIgW-{f1RobwY3!x6O{5vh@ z${483?>Qew{xi2)^Qdiu<7wr>#N6hy^dB{oWvkf8p7g|f`K8H3 z)0Xs<7nxrjDyO~)8dm>!IBxEUqmqJ771+Uv0FIOlHsFsoyocIW`0CrQFD!08M@@0T z9Tt5_9bQOoi7Mdpc(+*c2Ns=gC3&~VAI*;C#CHa~(56u~JQMim9ITu~`1h{1Csxhu z{f^x3dvYbg;SvAo-WnKhMCQZVfVi)Qe3= z_MQ783$|od7^(Z~+ONMQ5c$h~LT!-3dM~?56CJ@*>JY!4YB@r@gkQvZ!KD~EYHO;% zi#qs{w}-$s1*cTgY{h!M!i%}T=U+k?J$AAeI zv#2OYst7drjlx%ES|O;Z8>J}S_xAqn{r2(SKX1>NPM(OVsBX^+oP37CG+egFVC!)+ zr+h!6-cqdpO?9JV5ph;SWmWD4bJBJGe{^m<7agyIVYmCH>G6c+7D>HA@ zYReSIgw^2gFK@oyQ{2&9vxNR5D$QXg#$D^} zQz&c7`8i`j9>SjM+IsF|cAYS_%gpUS#3`>CN*9fFv2`dx^4_2N@MCb;p{)oQj1Pgs zMFL<}O@=b*$UND`2%I0vvwf-K6rS<2{)xbioLvD$&LYPVbI(|A4y|}y^dwG|k2jPy z#A;uWCg`iW{P+MmQN-Xy$z4ignd>t7FIacK1uwgTcS)p_>mW5)UFMZ?+&UoskRJ zpB~Z0$)hJdIP&?GnM(ugnew(D5-?>M;;p;?qV}YO+&Wm7Tm?MF$^FTfr|8|h@3XZB zoxFNr!U(cnS!_J#A%UcpU4jq(2v=XE{DvjZ1HMW#+XUP%+{$+K*;Yo&ZgqXVuRt=m z+MoLzB${7s4v2g3iHOa62+ROEViW`Kt*CJxRAqmNkV+f&AQUd4`dQ)SSBNXqWrt-s z_;kdzD2zz<)NCNCN0#thmm#>5TN#7$jFo(inQ3p1xqj=KR*qKSf1zRNrfK6y=!{Au zOy%d=kDY1_KB~zVpO?zin8R3!yLEYdS0X8yD%&%AUDPFj9pSEmhn=VXB)Q)GmsLem zhbJPY;7D^wduw5_hV{=^C?uEJ)S}yjoRy12`~j_C`ylH}_I!zb$JtlaBbS&6eQvRy z^mc@Ep(+gz=E+5K>d0x@(O(;Al%KA`(5V=Ty<;Sky7FPEsnf3!++vZP<^cAB0Ao;j zeIfetIM?~eih8gTUZ`I(Dxag6(bb^G0`t%MvwRDSZkP+|f$`wOH@l)BxTbDcnCPUK zahr=FEOvFUWunl2PX#GI1{|g0glmuU;#xKaUBo*ARrQzavQ)cO+P4IE^<{zDDSac0 zK)!I1s|4j5ijAK}wUVTLUTeO;@H{7n!Bu7s*O-y=i8-N6U1B>4<&+m&`lQB4O9WYk zS=E^&Gmq=^cvcfI67kwSjk_@+6UXZ_{^t_A-+;-;jQ*D*j37MYbm&Ncu#}zH+F#KG zunutw&EBvF-CQJD9~oHWg}#H4d#!;umFU}lyL-(XV=fJ6N8<%nL@_YuN*Z=%#ueBw zd)JdTrwmBj57D*>dt<8f80N#;mjNgmY3=kPeWsvrj+0%w4@T%uURGDrmwmZ*!Ni6-atqv0mAIXZb%8w2jLd< zT!wDoweiYhBX&LIs^Q$1Y;zQQGm1X-JLSLjRTqo(Ca-GO%-Cqh4# zeY6VRSVofuv2RKe*oy-_M(e3Qzb79ep4{1e5%ZP%D@;1Fx&orwM$L*iPO&`TEBZ_; zB^T2=E+#)b45BkEq9XU%={xijCk6SL9kVLv42nt*TU!6Nd`L**L5q&i0^kwgqJoM2 z=i<)Uwy0)mvkFCuKW(esR49~o{h|3W#5Gq6Q<3`JNol{E5@X}uib^MWJ%okSvt+p(3`Vn0F57jF#2s#6hC5vH8 zU0||3^uksr9A{aKp_2o}y+x;Qi)L@fJ>H`1O0{z9%QHq5OL7$@xN5Es_ zE3&z!q`53aUOtXWDDRqn`;q{&_2NV0%J>h(q@5S`X3=DL%plXB+c%Ul9+JJh^$UVp zznf&m+b~eyOg9Qex^_eQXRNvZdQ%6h=3<}?#Cl#GN>WmaeI!c{$nV;PnImxeNat-^ zSYO5Q@yhEDW2(+aucjt(33L>sR!-DT>)J2ETLaZ5S${Z^sWJ&lBgE6;AjMQzNe-jG z_VKNe{O_q(($%02%U{Rq>(*P6ftfid8+0007Klgion2&XR%S5$1Ry@Dx|;^*$@la> zv_B@bCs7Z67WzCDZ5p8bC{b_1SUp2C6M?0xIUCK)pIsv|Ze?GU?*{$$KQvi7$I1^+f z*p+3{O9W35eI~7wL!x*7n&r=Sk?Ctmwi%_d0HU`+tkz&$oktSLX3OL`gd6>LN~(p4 zN*+2wj}Uc>m5G8PD&yQi@gv5aw!1R-xHq6>icRPGqMRm8SMRxaNPB7_FV1btUV!|V^8hR};DhH44 z3f2+-B)Fip&qyf1V}<_UBe0UsHo-MJiS-YHP!In0#Y6OykiR4R))cbz;_a4d#UL6{ z+9;w2BQwZw9GP;pBT5TfZ}^k8O=9@{q^`{FWi7vMK&i7BdA#r0X(pj06{D%NpL^oA zz{2*$-uDMizlab}%2Wuz0e8qoyO&_*rxt{4QEkB>cy@y6RUn%!|5eVo3eXTKT;xJgOiCy%{_A&Z zlGn4NY2|d+A^zJnU9!V%JYTrS-<3st9TH=15&D!^*MQ}5%dlmJAznzPGENJ#Wzh3& zxBPJag!7aQFmwpGo+@QzJm^4D5)dJ2`9L=y%<|KEt+6PxBVX(O2=fpyw`qmNL&>LY z{0BnZkmBK=!2`Q{9G>b8V5DZQA$#m&KFW67Vbi_KAR(4s(%f+iMrmKEm|npW1y7!= z&tx2s@ILfFRZfh_Op;)j`e1ljm0n7}T-)242`@pedK<=pZp_w$F0H(B!Y@R2`MUK+?`wBJl03V?`wG*`MclFqL)f}j^56LD+g{2rT&{#(-gK%5L$2w= zXdTOJh2WOAxkkLaRS1TP7=fzxmfSlV84iClo5-7t-uixwM6$W>V3#!s7 zj<8jC`5#Wuosccy&OZVKIY|>JEQ#;jZQtE1utl%S_L%{TwRInNc=`BTsq|naIsUE7 z#!rB@_AB&UMD*T_R0J!y_i*bFk5^m?e0}sPf$zc~Jp{tnGd8FXbC&Num_<4vuAH|e z)TxRQR1bQy1B#deYQ83w6=y0>{0To@2^gd6ANPatBgAo0JE+^s6A9lYHv1Rv`Wr(? zuR9wbIcHF*iu`oGKRDeN-Xev?*-~(*rfUue(V^EzSbWHpy3Pe+Y{P!}lm)0B2_3tl z+O1jt%6OYib8Q zp~V2Es#gPSUOfe-><7Kz8tM`tQQL*;jY5i|C|vXNbr!~Cx;(p*>H1v0QHI$CuNK8A z6~s8|9`I+u7&o=LXskbydwL!jh_e-=83K{ywbJ6qXS^N6`v>c9e#WhKUu+S@ed7DL zz}j`_<7B;^)&FYe%veaXCqv#%`)860q^dwQWyP?AD2>>UJLT~CKIO+J#hnxJ=sEZu zM&pR(n8RLin5AxWqknLaJ}=dqIa*el%mYZkIoMP-75w>ahN7YN*1P@C{_8O}X(Aey zUy_$&!ckr5?)RN}-brGx*g>LZz$XfSxTE7em0Um_&MP8gvYn=ktK07nv2)lE7S^s} zEeT99Z1ZH*Lt)LNe`O_ajMM;(2U)%lKpXkKX{%Cr~y((^R zFB)~eXt|euGNR$5)zYns)3+UZ4P1i<-E`RPLmlB`8)6{@e|Os3GIo^1(&YSELxY>g z=A(B$esdsd%j@oUItFnOyrMMFzpOonpBS~R)e?OZ_?eQ0d>iEn`_?>q8*LS4HE>{WO_EF_A!O6Zu?09SVq+XgOO{IcT9x9sC#aB2air>F)u{#yAi( zveDdsjQ)Od)8*2w7>7B(SFwmOJhrhP_iF^vFx+lPwg7p$6;i7hmXcS4np4S!$S^Fo84kwj&|3n z_j;dD+{EwE-LmZ#8M|};oQA>STgC(u3CcqBLyZAef85EG^A->T9)W#PcP?*4dsKRD z=3x~fiWpsNOzk9r+*wzSAdXfXDL<8Qo6KzKMEDHHzS@kC&(umF+SrF-$UmSi%#HI^ z+{c-{IgLHF4-E0|wgyX&?VU*l>}3QyyW(Y19cOhHI3EK(MCES@3RK~$a$}-_Pa7xL z^}KRzNcA;cRl;^d+b()1s!Y?_UX_!yC)iG;Hs|oi^IYQi<`GcK1{JsVD!MbULz>#f z69R;%UQ7?z&nOh9w+&0Ts`VOs$RVCL;Jf{uc;P>uDa&6GA)e0|10M1q^LjC-jB7W+ zrLql%oXd0U)0PU(;hKd6uU5LL}D)@bq%=ORzDtB{*XKuvqkB!E01 z&!Xf`zv!_-iz;XnC}W}vIx1fjOM7GTlW(jM8!17_Y)lUd5{a`azeo`Vy(^RjF?}RRzSU+cqs_n}O zw)Z~Y+%~qF`)HAsN3+#dF1ZBl%KErmtVyY;JxV-fB|YrC+y1f+SH5!Cw8V=$pO@g z?J(N5Q+rdlhg!)yCo5 zc{sHqQhSP9BrN%qsoe`37M%AgmZ5&5NMqesV8K2hc^pIa1z%4qytyyOen$~0^!S;R zqC)b@ZN+-b=}2Fmw2py=y~yX`93~7_M{ zv6l0x`G8OR>- z$2)KvUa(@tYDQgkq}v;JHi8-^WazgWPk*@k=*zo@B&HFpxKI&wCth(mrp{bdNih)z z>gB`INnN|3Nd?v{rVEVtDzEvFn(s~uMEjJotQkbSP5tdUiBh+-$keEW78(T-lLoCF<~5fb2c=Wp!|)R z{^SNeYFp^_y3p&TSb_PsCiCK4TAfup##U!%#qQwfMn@t1pF^%#xq}1}lF5p(I*ClR z2v!7R5WP%n8~aG%n88vB%ErNPyv}4F0_&l6T{F99(!*7H`Emgl|GJ3(yg(l0JK-D4 z$aV$!xsgUzCNm42A*uNJ_eIl1Vt1IWsoJja$_6KwjA?IWR}3V6EH$Q)Lxk{!qNd-e zRf5FZ9Dp@kL-W^9`eU0d-KE+fM+jovTo6Yu*S*6v=^0AvUA2MH#2U(?xc{c$ePW0< znasxDp>&?LiG8%uL@Uqw((LR;kB_Mg(ar}3^=$G7$4^_1tgZBp7X#j@qMTKmxe|p)AHh_k) znLmy=aQ$*_x$1dP#ah z!h{lsPX~$1RR^k~eBL!*CJw$}*biRSzZ9_|%ii09-{Z{W#$I&|V@I~o4Jd?&uwx77 zI|lI!?1^T;vX8lmS zp2CGY!vgW~CbFf1u%GC-V9))K=){*wvE9iv_svi4&rjmrMRj)Y0`Za&l3jUtt$p_S zUB@fn1Xp^l4D7D0j_*lYl=P5nT(&wLv6NMsH*ofV1R(Q%`rPmQ6 zu#TwX&a%i4QHR&+rqSj{p`nLSYJs`E(uWif^3ZFV+Fq>J%WFFgoz~7&lXu2aYBs%4 z?U?1z=XXaZm%DU=@3W)G&##Y=NYvaxBy0P5NJ!2--UWQ-_nD-tDVqJd<+@juxn{k8 zio&=uP6Qns71>nIh;#wWvrm}`9VD;~O|niwKJWt=vEorD`tV0Nq|z8XlUCv#`ixOt zogC%|us*KvUWMSk0qo~MVGC)GdX$@1xl~Dh{r>=;- z{EgtKbH?GzEvFtbr^QM{v|JM-7l(vs|u%A)%a@f6Ef<)#XJVL?GF`$bhjt?gOYX`*UKUOfX)1v1d{ zK2tPCBXFl&t5Lz#A~8HamHxjS1_UYzDiHgWUm|#c?6qGn?vlw9&H29_CZQ?>FAM;_ zZSsYAS|jyjVrxsXBcdWztHi?6Z*ZSfsEM^U`KR)3WJU#cmwJrLef-+dlc^$Z&T7WU z(B{3p^!hxYG0yxURNdb;Rd@H&l2U+bWq(u7QX`%>KG@c+icue#g4b9{E}$W*@LRrh z&N`r}Esjm7T($%OhB2+;CBL~oGx>?={V1y3h}vx;Sfn1B-WZe({$2kSbR1DyPU$tW z3QO}T$l>22W09FYZReK@IMM%0uiqR&7Ldfkw2C5Q-tntk|J~wWaKhafP(B+IceQ_DS-J|JwNeTZBH6us>Th*=C_-fZ zl@9*uUtQ^zI}%VBqgW^=*|OQwwrcL;HF~PDzW`l*Y}U3Ia8y81rlao_NH9n2%M4~?niR3qv(#`E-SDFM#S`ChbW0^ z;YW&R^o@Q>FUfn}^q|Ub;NQ$?n18+OE`H~PVHE4O7G^sa>B{~WKVLii4y%D! z4T-1?tL@(_sfc0j35!~D=Z1HHYQcK9D$90y&W%SqUsQ^_VJbEm*g%TtbU&eD)mt?2 zK~b!kIgSc$jPjXo~Ja% z7Ht^34Gs9s=@~xf>SiuNh`Gu4ppyUwE}c9S4m34;uiS)qAm(w{dK-KOIbp{B*9m_oyImcT*X-&Bn-D1_OFMhJ@ z!s8M@iiZtc=w7SWP1a>w3GRps$M4N>2{)3>;HN}YHlB#~X8Pl+hyX!$g<;UAVQNBg z>VKZyjwKyAW*WKy>hOUo?!>@)4iG;TAeDNA+o>Yp1gb)g#9uPtH@Zpd(h<&h)swMX zXBg2Dw|@~oIOsh(uARreWA9DJm6BR1Izk9b6@5Af6KZGTc(f!fCS%)1+79(OZ0ZiPZVr$ zD*0YGHBGA%lTGGVMCW+doeQu%>$3SbTQ2Qh@^E3iM4xxn9^cBgO1yrGyQkp0t5YT2 zw6CqO!q__jb2Ye9^-!2-vtWfwJneeJ)8>W7WeKbAE|Uldvb^UmOE1V`Q;Dck;60Wa zeH^@6Du!%^5JrOCd+8dNLx0w56^&TfP&I4sA8J+FJK!2;^GEq)+Kw3KEEg(fW(s}H z&*nbyrC8(Y8ca4nXBi1@i~j!1EU~Ua*iCk{Rb`j5uP^cXn62lKkqu#TTGCIC2?~k6 z;B7car5s9W?A7?Tw&`~=*%llc@WM5!G`fG$$ux#Es6-6aY8ol1T31PaJ9At0T|B&! zyuDf&jpyQ#lk4>Fw3*-YsuH<#YoTaBHk*)Zh*q~@;hwg@`o4mf=%e5@u@(O2$D;l+ zIO7**x;)2q1jJ48rrK;iTd6Phjrg&Os%!7fgR?cFhz%0r8KPVfEO|bDGik3CpKWYv z{DJ&60IsV`hWB9hLOSTt#?)bDEm~%5v?E>Nk>I7Ikwi5!k2y&?x{HQh0^CZa66Dymwr$l;6 z;S!xD%uC=-ZXbR0pZoMLjfF-CA%xGMJtdS7Mj6bB^WXQk!Y>xKQOhJ^krv5uD3@3V zHMb4;YOG5w-H%th#s#whU%;0fKl+AyKdc`B^1AYNA42E-*kX*W5(q^INFgXvHn-68({dlR z0QpGt>~_UAP|BGrM~n53GEb_NCBdf#nEDMQUI>ry{sR>)baatIFh#_!jMV zFeWBp&OURk<^*Q?&v(dKGoclX5`hcFo+OB2tlByWKbPWhyb_o ztKR+TymRw8V#_3G6O3*8P|~J3hy2(l5Yq&nj%3;c^&0MMZf-Sul1=0D9q=BCtkz8t z=}tnY1qd!V3ljo!Mz8+w-~Ls&4quZ$=lQb4C{1v12=Sn&We}i*AnQJUQJ+z6L^R^R@2udYhMJ(qIb{{uXDf=lp)eE8lcpCqJt zT2IJnLTLu21s!|qfxnOcBJdQ2TBSk`fWf#a+1DPr<6N3>^9z@pg^v+9^P1->H}ulw zD;+Mdu3vZb(wFl*;-e1NYb_j%Wi7rwf; zVaqxv^Ql=W!m5SC+MWJh;UCD!#iHFBA;l2Ln@rI+JfFo6nxt);vv^HTWFyw9Od6OsigpRRa;*oQB7EYWJ=OS0A9=iWI0x zks43miEKKNL+^1c_^R$|4&OMj)7>V@&#=C`H8!oR107i4*y53E>sy|;S`2|`vesd% zLtqbY;D%9+0q^L4$(JmDkUo5U-gVoPPsWfzX>MjAc!p68Wig@0K6oqLc=F`_Z_49@ z*jhxWnof8=>?3!IFDiWdPPNh+X>Lw5>1GeFLzqFNDse&|`dSZsJubn0{Ec_MtM6*- zNer4+!adcY48{=XaIt^k2jKq=v#o`oO&Q!o${9Wb%IVGzz~$!VOS5M=H40qAEtA#C zxT)+}mZ?FRjKjS@*aJTp-vM-af^YNwM}GO70i!wuZV8kya%bb(=kN;nFhz?|peACj zd?jxOr)e4q?-ZUAz8yar6d0u$gc*!)d{>-Dj}tlmt{eX({y8v*5f~*jjTkk;piBbH z+Ie1rzf*6w)lvvaO=Hlx@jk}#bP!$>c!4_s4k0x7UNqGC)(z$W#AyBKRVrHIa))Ek zA<$Y1(L6&wK0{!Sp!7gO=3rz%nJh4a6M7;1zgcZ7uHMaytmjkOAX`>*%huEw;YJYr z3V6sbT5q>o3^k9H%cqWEIZe}ma^bB+sxa*Ewc0QJ z=%vr)IK&nqqNZS8G4tkE4?;qdBz&)a#OwxH%`QKK`V28@kT6`~Yb}1s=WjkigbV!X z$6xurb047x1_YvKMl($kqlCch@V@r;i}8_xZ{vgT z46{WvYTX`TR+?n;*m*(RJx=!>IWu$)YY5kgpxEXt?65MhTMaq$i}Bjbnbq^$D&NO) zd)P1f^r1}@YM}xL;W~XWt;z@4J!uw*$@3HM@FDmp?I^nQd@4N4D;DyAr-$$sGIgQh zk8=hoRxHDQ9$VadY4i-wz;%X2EKsWyO1>Jji2zD?TDW(3jc?5jEizlQ;3nO)`c6!v zd8hZS z^P?im;gTnbz&`lr@bROEE=fc<#8*GQv9j-#Y=99M;pWxgO+0WWsYYM|fOr^$D2i&9 zOK_4){q61kQMO^ksF>faW>G6KGqdk2iBrJ`lT9~#Fc*4FpP$CGnihMM+iS7TIN^i|45S$zg^~MecVnL+3|Xw+aQA`N z(Qh3(;gM%Iw++hXTJE*sT0M{OoqOChW_qiuMb{~nHa9T`QIFQ#5a_W40whJ+&}XxH z^vt0^3mH7O(e4VIZI7?rPuMy$-dI_EOsfE*s1`419zMoWX~5G$9%Md(urOeeZW+Kq zxqGn1TIEq+twZ3(R_;+jx;({v9`-EkRbjUS*_X!~8>^3b6$C1(+5KKl!T6pA?Gyil2r6j*yT#EH}G`v z^u_#WdwH{kSYlv1jGHjedVZ>A`HS4B?Jf|pTkyKy%rfQZm}(NK{Jdn2$Sc>zL)~O z3iA~py6}G9fBo9EE8jOu5So^c5DrdL4Fk%c3<4s&h|hcM&>_VZ;T-%jxm3l5X~HCY zpl~hR2qe5!I179mzWvX4DL*5u$22`VGK`Y+Hnd(vFB%TNVHlEs5Yz^`;pA0XjNE0}d0NgN-wML6fB zGMH9e#VilNE(NWjL+3CzAZO2T7lkck2!Ua!0kY+idpDw1A7GS%P}FgFT;p)~#9+q( z3pcS`%DliRo7E7pxqAAuwI8Bs3GIb*r{3r}*-FR>%gCz3LWW^Lu7%Gd*X&u?i?}$5 z)gZGntKe75D;7TR)|FQ<0|6(DKxsx3r5Z+HgcAbS<%BXBO^T@5 zXZTLxTd-QR4CXR?58U3bGRV4@xgk@7noW33co*NJZ{=NR!@cl8q66>aldr$!Eu-U# znIdd*cR6!q;a0sCUcp*vW84q{0wZu13s455$zs5oxNdR$_@!^IFM~y5i(tw%UJJ(= zMb*%er??d0X=*}Vmpnr3ecPi#mlHC#+1uVqyz?ox3(4e{lIK1ubORn>()&v{6D9p13@cj&hREBg~E5 z$+hq{O~f|8-$felNCCHn^!TT($vgqE@ zl}9*i?IkKpQlbs(oSZpwYVA(;!4|<2(DX%Y`w)JR3kTNwZCc6PJ98=+Wohl@&DHY) z0rwi@SPqp4%+UX{@QvW}nJuyj3U=X5{2TMbhY!Dz*TO|Q0Wb#DazYu5Cc;xHb`S9R z@KxErSQNCBTjjIoiy@P^lUnkLxaXc5^7hK*xplckP19(zr_5d z_XEAb2FLKDJUe&nSm%rutPTN#6T)cf2?{o=qetiO<~{HP+ud$kYAww8guYn5kHtbY zgeQ~GIYLJQ*V1IlJB5$on|7(gj&7{pevlp$DB7&rIXmzux2{~fwl<;wA=7k4ySsVd z`V-s@$Eif?X?J|a8WCwd<X(6f_sC`3GRp6cx30qiQW~K zpoai?l7O;7q^kPYc^p2O(NON$0KLN zVSG@Xa}MtHo0c~>V^ z(pe{k8$e4ABD)eMhdcRe#J!iE`BXj~cF{x$3WjL`0>L4K4m&Wz!eDDFU!n&c1|bgw z1Q97p1r-dLtri#Co1BL0v||)XYgs$+4&JfvQW0w?VGNoS4jlr(_ohA&X#}SG@8eb0oT%Oo0;-raCQLhtD z7}qcYP(mo7*2v^*{9y2Ih7y1hPB>vS3EF6IXy%d;M7pXfmy9zQO{xGtC@<99LfNZ? z?&X9~!UUCTem?$h@@1E^oX5g#w zjh|dua1Et7lfd;E;e<07ff{B+1=o4o{9Vs2?&l~}h&+@#9E1(pQN%vGU|0)y;Hm(O`>~RiB3oo#xD;4LNq`Hq9_XU`(J~;`#7D;SKXI zxM%quc0o6p%5v^m{!{RBwo06)I+W&y2;)pjcmksO*LfX$9Uk1=-Bd-90OLSNL?p$u z$Y`|s1Vi{_76x`5nwan|Uf@N1>;FTQrv=wAo)lKA@?=|a2&9E@2*Ftk0YZQR-OMN< zFebnPFJw5}ei5GsFJ-pSO&)Wi^Uy=bUcy1hsi_P`6Xq;Rcp@r}_D`O?{!#9My|g1j z8I00YM^w@0MX=6$&kcGw;e;_>;WOxke7i418-X}DL`#7)hiKL;5QpxfG$jNWOrW!K z@cH^v!N+;a`k_Oyk8ZN`;9g#P?EX8(`v^5uhw#KWO=+G0iFtSdZ`nS6d~{sP&_^hX z94A2Z;Q{ZIYg^7SIH3s%e2-qfG&+>y!`udsaO~1jS#T3JzzP?S+<7E)s41GX=)zGh zoZh>)yG$1%*@c+U0v0uJnd8Jw$n1*nlw6Tc2=g|9j4X^S5EjNbum$(}<*Qe(?%vIP z(7wrG4;J*0{94_5WoBTK!eY`I86hmJMmU2givCgFC4ZWpn%~_lDnwQ#CfE$X-mDx# zt^mSd)sYXAuZ*}h&mb304dT`YlQb3}QcdDEzOuM_;rM6qI&Ol7Fy6;I;Je~nFPNHQ z(i#kwk&zpbSw(mC0-p_^#-(9V5SiqL9$1T&gM&>?D^omhzOt+3*#EG!%u#@*fdt6ah(swgqZEsUW}l&ydgw#`l1Kn{h5 zkietB4I!jQaGFs<31bLsaX-~6?}YDwH_TVK47BOKA zmO(}kyX+m^b=UQm@)XPxsjbOk0s&x`t^%P(8FCZwG;ifwa+v(!Z_!|jo3;)DNZ>g_ zfI|<3}XqA6PJ z;ml`YO`LDSSX0MpTvkspuo_{3Z;}XYG=yg~BYZG}0MSS#3luyqemdV2?xSeQ zf;To69^&5sx6;Y&G%?u?NC-ijsHoVc3&z+kDWN1##NlZ^1-=OAdqlyC%^-bgk}xh#F-MR$AD@Ga3V0? zxc1-Y-woe_yXR*YQ41BU!`#30^xJpt)kWAM7|;|jC?yuOA*xchOJslo#>UQN7{$%q z?y^2^J-})eBhrMqaY8Oog|Kbq5SVXEy%}6^Bk)cR9tFOX_c{#Lp5#_I$WkY_XrYbA zTv@qx+uR+jftm6`M3AGR5XK~pWy=(5SF!6$uu3~hh$$`M2r^&;R8fQ;A6E$wumvZQ z6KTzvNs=V3*n%W^WEo|#j1aC%7~{Yd_)0#y{rKbU`PL|Su){U$L)^Rb`+0ZdHnsm~hvpY?!QuoL-onbx%K^CcSwe$mo$A z%Asq=f*=UCfE@^eEE=o~7%Wg->1i+LGq+#$s*&*>a^Bg;$KaEAbZJo9U_c-yzX6$o zBF0FO67ximjR7gGTbO){WoQFpLR~|3Or)Wt7Zw-8z+C9t_u@s}0wDoHP*C=^mR2$E ztyMD4=jP__=MLClkeewlTu?|+QGE!`gKaPdB&nbP10jR~ViJqVXxU)lNGz}%vNPW3 za4CdvA>0XY*X6ZvkLAxDet77*$TQ_(Oe6QRwx3%UR zr)kO<0g9}`I&E#PwpTd_=O{xS$PrX@V^t_ctmVBj&(qWhCu$0urnH6{3>J#Cp<=!| zeY$_0-v?3u2yys@@A?bh;TQg;U;cr1G0Ryv z&USZxx4X?M%+igDiWJbLtysj0HWUca;+iFRlv`IGd1UD#S6~3ffYPRW9&dqFecK5HjxOXgbrmM3@Fh+qcqphL^wqtA_yhKZnbys>i)z(%P;)q@BH4s z2!9M(@{MX0P2NCzK*kY_D<&mYHwQu2%D2g+Bet?bv2k z9@33f5!)0Hi3o%&5kW{ws8ulp*7BvLxkvpGcsu(#OLO@aC4`v|fP=vWl#t z(ITsuXjuqV453REt0Gn^prC-ZD%uc<0HS3#Wx2Jp@+5DETiF?e9MfbYu~0-Xqzq+g zW8^_Z4vQ}!p1D9oGP^w-ts+`+VL;Rr29N;@404*VKo}5NMba`#k(HabRZf=EQN5-oS2Eb}EU!?QXz-q_f>!Ts_ay8n^XA%a=u(U8&5y`4F%cNSZO9MrAQNL)QTtGpk zs!%}}tukA6yX|=mphM4{Ug%Lmzy?e!Z`&muSYu}}w=_P?v#^hiai-FfEQ2UiwX0QjVU|iq zj&x37P)mZd>CxgQrO9g2O?In!SWLp?F!^j17$uZYEhkimkSJh86}#Q;HtVp;Yn!(r@w{FISP%d!{p5~6Z%V)+1IR{JRw#h1t(wd_YP_#J)6q?pDc?->+M(d``^lD|X(yT1WV!pD*8gQ%QdYmSd5RwWCm}Rk=o$X)e z06fNXoAbNXDt%~ENJ0tK(fZpVFPAt2r?|28a)RjD9?5CYY5!pH`UF$Cqd z2{^@o30A;3kShl#WMmLZMk=eKQV|u22~7(wwE|CaaO=uUxx+y?$5J^Shb{LYuTM?N zX_bZ}^{H@RWssK&gfs~#An?cguD|pJJ%ZPLp?Z`hW{{B)Ae1nM0sA_SyzJm0p{ddf zs9#ESnT16*tL^pvX^z5G*1MaVu}_2oNldT}#srcEY%&_K44B}Y90DK!LnNZ8f;M#N zDlcTFQ@eyM)t58Nh&^ z*Vf7<=3s%1a%-HA$)SfGLN?2i0XY#8AR$OAs@P`{7MZPPXS>@Rg1rojqAG^WLYIE* z_A57^rMayd{dN(fFtyDjw3-M=v|~}J5U`;#fN=!jM0Aen7ll|2uW9C0K{Q~LHi;d2 zT!veD{^5f+@<~L_h!?D4#3eY+>Cx)yFjC?%CIsh<<&xYE4&*iR(4&V-tl&_p2PLJ) z<9zHbm}9N%bwZB_1yK^wV1Y!s00lddT0=y|BDUFqq54IC*xuwiT&Ew4qUbY=`;3a+ z-PzmyBy6_e99yMSZL$k}7a)u2TextcBt5I7rT~-(01+Z?ZIe5TNge2g&bW7&XW@QM zEUe`@Ev^$nad@0p!Dq5q#lnFN7_*hn%?(yK1v6}wgI?ZY06lV-W#}=0oIqKI4m}8f zO~7D`!3m-C90?&whzS;11t6%9VvJq-Fk-&_#1m(~f~RO)auD9ksjaBRf~-Q5N*ICB zR5Jq9RzFrnY;#y%O9VwCm?#kjL}*j(NT)UNq7K4A#3VNKI5R$Y|h+zSf?<5~hwiNF{0M_i~hPZrlwCe;uia4mrm&SarXMiU_nQsgQ4ck_bf z#l@*)cMj_ZfNMOkJl`&qrZi7Fr>SWOL6nCKLa&3UAQF+N*uwHKhG5qS_&#(-gG(+2 zA>iQPy+Rl)@GQKN+jh>K8?0y!a-2{GwO-S$nCt>E56|Q5Y!Rmvq33O8(g`v^R(U$59@NLQ(~H@^vb|sCcPQ}76yZrhQVNE zu`<hC2$GElr^1vVP@@4x*$_qW`Yd{gTY`h7z+@HCMrnl1uUeL2p%N5 z3dW=wISyP2kTJlW7UU5PTkPAqc=7OucoufZ!8BK2Tk9&fSQ*7JVvY8Ndl4UxOeqZE(S*_yRc;z0~{P&5}c-l0o70@BPw_spMU(!xMw_d@+JNc@F(ElmP4AzYLsvt zYM2_~3=7uDQ85-vejxv|>%A$=D0C_M{Ntk_W0o^%;<=5uXa5!df0| zPZ=*P9Qg!30p>7(GB{0jD9w!!C=rQ@Q6hpc4$jFT;Dm8P;K?LxL|^~|0%3Kvq=1se zVY@;#3Wm$liDRqYnQKGd75Wo3!BVhPppIod0<&7s>8xv&W?^A9Uo&0 z%#>ZTKEgXrJaViP0EEeE1Q;0^In6RMGO{uW3nWK~L={qnWC(!d3fhtg1UhnufkVJ} zvXRSRRo(t32TO@qN;>XikOKop9F zB86p)K`Nl@LV;j<);Psx5?g?=WpKAUT;(Wq5vfkWWR3a)M3B`AgX9EaQn{StBD{~6 z&CKn%#AFl*1Yig{0J|y(`sm3`#Skt~X=f=PB&KRU)_FL>TrVf9nCf!EvH*dQq9jCW zj4Fr#!FlchB^XZ%87vD-5#wlao}nezNELO)xfO>3F^NqX#^bG1x)(09)EU_9fo@3& zqZ&?8WG{RN%oa-_cw&quz}`B-w}h842pCX8q`HPD$|#c(GD%qw6K&eGD|Lwwi0ZbB zAww|Zd}}<|VF?D{$pA({KwvSB&K`Ojr$LdV69NOOQQ;si#20}_VloG2IyY|Y`%>Nw zhslkpDR3><*Fp~wxX}kDIoV39*J2V{jhjv_CZRPMEU-wmOk+*fSk0p!GG!`6GlKvD zI3e2A_KWzx!V3ttaij7v=Rh3jDmEq$r%v7fm*iH+0jUm8fa(#(3Dpozm|!dr7#YQi zA&h886)Kp8ZRXqEcIa>rjxaYEln!`eWRNi|a-h5ZqUDnmX|7>F2}6Js2RZ!tND*if zx#SeQkk?;6b}(Ne2iH;!O^6UZ1ECMh>ot37&7OB_>bPMhyVV@5Y?hT~H46)@$_+8bVPWMJycm9H9*`O`$CvJV#~V9`aYEq6s6M4B zEvCr?oB$c2gt5sn1Z0UwOcWGR1r=2E|+T^aHC{_X~RkOuP!|m zs~XOtgvr5t2lOcTI#Rt;FPuAf_?3JH+)ppqwbU@BwbY}vBQmH{d^NRsi9QglJ)23dp)@CaBxBi)g=prG8trKRKp-3 zV&NJQq!c?iIEMg|6p4V06Os#%qAKR$H1kzee3#Wkz3Zx4G$RH;y5FpWpA#FvuWDUjy%tWedt%5p{ z#v3IzBV;Oa+W#`@nof!}Bd&LvLqPT)1%k z{eHr#h^i-acq4qoC$>r>3)iI-K_n_hMHLW1MnWL05S&v&P{1|@fviY@Aa@`Tj8jBX zq*~M~xuRQi`_(2xYlm~aLC?nZ2}^BmhY@EwId!UrZDc{rS@6XdfCwVDbXoSU@GGBPqUYIfO2gcu_M3sNnx;*fjb^VvI;8fEg1kKm^nR=1x#@P&E| z3hK|-67Oa!2N0;Pq!OZtMG?F7p#mXAVgm9!?~sFSY=Xd`)D-175Ne=I^%@GRpd0(c zYL&h`$GKi_Ku$yDSYs)Fa~C-XIi}GPQ3ZWGVzy|viy1jw-+94NtHo1hdK0j|Ty0LEaHtTci?V$cg60=T|d%rXn-7z7$? zBO%LT-Y_c2T?d{kugvT`%Vp@0+w4IPL8eBDsQKlSe@(suHW7_A6RaKk59Zn<7taJ|3NpTiY#l@36139+AwNxWu zC!!+B=xg{wmG5{9!wk2seBc8cPcs8KCROzrCA^2}a;q_5F-c8rs}W$4(SS)elhdN6 z#T2(lwX$TlXt0@HE%qP>c*>CXT>tpT7f(_p8ajqI^ZGNf+Eil1|NFvid2k~ZdSCjb zmtW2}A!-{TRIvzGd0_GS_UJfIz*&Z|C?o`;Zew;~L_ZGu#R$U^rNKE1FvH4VX(@~u zK*b;*^gN(|f(Uj_fE*lfAV6T?kYoCAoZCmMvx6C)geB}OQOnzl`zgWLS(Iil5rJy- z^+m%keAio;a)&p=Uy`RcdL2S0VNe}nPr7McEpDQkJ@I+o#9LV`u%?RZ@+4@yRm-w! zSy`;cS(D4kX4UG!zMBZw3#Vyqa#0lG0tVi{KHi;$1G0#C9w z2zltR1v#>WDWSx6Ado}JAe6aF1|Zs6o$a5-(8FMiKrB{g52?Ulz%@jwF+@b|a>(xp z-|+@!t~_$&#y950Fo#XOP8cPe(4MJJ=ZGIjU20}Ayu?2Vz8Rdi@y4Ck z@+AVPV$Zp>CBOLpZ=e2b9)|)^uY;~wFXPH!dwaBrYN_yh;20fKXFk@K!YkM)4Kg5% zC`NoXyvomQE)FG$ng*5|IT=;(IygWKHck@~ARs^>m{emxSRh9b!b*|SDixKA#9UfVumUL52r?3o zgAFmN%K(fsZ1cb~_Z<-FP8?S79g%5$eZhBxM5-~O(ayJS@ILs#*cjN<6iJU{J3fy^ zBP&i1uReEt(V~72%Fbb40jJm)mo^#IzV5vs>dnL4Mb1E=Ua5PX(^dp*X9JUzglb42 zvMNmg#()810D%BmAOukb0%7b>668Q2kZzI!fsloS6WECYmf1eAs9ISAOk|#O5^VB`$KUgw_AU*`y>R8sOZcwf2)U^#j5Pliz6^@GI%^ky z4ZIIJfD*0|m*2x@LmPsPF&L0Y6(WLBB9hJ2P6-6aWr7_N1+s(`6H!GhW@$sjF3Ws} zo;9Y-oeT05OGF|>qGD7`Gk_Su3wY0kenF}M9ehE4SLXFIefkYh`Uemr-ILSIpMU*{`eyiA7aw{kbQ&QD8z1BO@J+aV)D1DEKu8iwsE*WF zj{zkN0wh5J#sr5BJ?LPnLKSUj(^gego6N(IbG@~ta)~8~w2=gYh_Fx^h-#5{!rio$ zVi2ice8G3VGyQ@u1Qa1a4a@VLd->zT%b6?fG-XnzKDk;)r`%MGA5xt`wByMO&wPD7 z4;Ls??uCWJ&*vp@8%w2~CY+(o`!9XbySh@gHTci-y*@e9NfSmj1X3(2maXILcH5N- z3XlMSCd8SPCO}3;mLo_~jFL)u%vN3wTvDN-yDAE`J%XdGR?wUAVQUQ|kN^u*NB?$z z8dNAvX@=08efeb~h%`}S%v^crooBv)*T4>?>rgExTY}*h%{6@AYxPwMWY9Ul`~I1!ePiUd-jFXgoix7d(WG$&m*!L zHn?N%jyta0$`)88W#J5htGwxf`znz&l)M?<%avXL5C&AMpkJ&nFTag@V4h(tluTqd zV8AjMunbOTUhpoB z48#C}6hw}tp*bAkV>5T$v2xAk4Fj?X6QhiE>N>Bb@eqquZZZ zzfKoKs)gk=rv)$uD_|0`49KFU0SsW00;O4iED%w#4Y0;IH%J8(M8#MPnMEaYWu9Xi zT6AYm6LCY3c>pHJm7(NGd@q-;tmT0{{tix&Scd;MU$(bulR5NwFZ?fgWGBz5p)_X@ zr{UXY|DrOLgD3y|{N-VdRMpXj&*oDu9XeEuD6#|y24kB50ox`uMG_GrkqBTg4j2fv zh!h|o8X-ASsH)oY2##=O9Lm`CB8=$9Zg+T=`|ui%&aJIEBvjXM_x4YuqHbFv)0%xp z2=E*;nBg11--mNOn+Z2saMov1vTT~6ne3*~CabB}q+4XPXt>3swwUymQ{#Esqt9mn zI+D8E{0ZRmXe*O9Hg5do`MbeBoIyCDEV0j@9-c>$DGwj}*u`&!jWpFE@tN?AINC*+ z5;}B3uNOKj!Y*A!Ap|0V0YimS5eShg5F!{O5CL$>0CH@hf(Vg&#aR3oCD> zgjE)+VZRu1AH0*UE{b@nVP$g-H_SNGRJJC3+(Dz-elPYYCuFtEX@FOq!bk-HATX zf9Xq4zmzJ2S%L40*Izz!rX1i5ZcKl8^{>fdrhwkcC)|H(#tl;9R(PKd4U4L`pv$n% zf$rjLF=P|^ic%(JkP+Yvs!O#jh(L^p4yi~8nFm%+VT2< z&8K{a{2DqrMhS6rasPuu)u*%w1iT{Xp!|dJ1MIuJFV7Q7sFqQ~{5iF+{^-(k>(@~R z7{C$EA6uFuFyXOUJV})ayugu1R|Yg(umYDkH{0zGmRN(Fsy|vShV-F84MR+2YlBiwL~g&dcT_Yi!sJT3b68&huhHS9foZJvyb<#V&+w`T z4jodYmdD5Vj6^3;qk$sJ+xBNOm*ERIwM4xJlXQlqL3ddd5tiu|F(O1(gTV#@gp$%W z0x-rTEn|?7i66G}(l{{dbKzXXo_ww{gr_){M zC|abgZdDAu1BYo#1<~8`rzqoBJ8|m33k{R%v>pVn1LRP)o>WQ zjG#+YyJ{~pf)SVK_hXj=L`;}26b$Tu$)QIc970JC=CCE1Md;I(P{B4l!=e7l#=#$q z^Y9?YNBv=}n1zy+K@k;+u*(-7*j+vRe6GRcyy5XxHO3~d2!0Q*KJmskjt>&jlu!mW zNO;fHyJ(uP#gw*~aMNhh6+cMkO7tX*8)P-EIa=AWT3IZx(k!cSjkjt|WdqJ&?a31$ z9ONJP{!jcH|MGvz^$dYq;g`tEX388Vlu2n$C?SmCDL(&gi;j}I?qXJFSd0))L&kS1-=E!wti8`GM$ZQGi*r)|5ZZQHhO+qP}JyT5;* zi2vrCI8_(*L`77^lZC9z%9U&VU3=bq; zVbS806vrGb&c1*vD~lVeKdi>*C!GBAhw}n-bs_kJi-8t4a9)1(?BL6fmZ zMCk5eB69#AE~MHrdN!c=j38bxRDl<4(yka6W^O=ML4=~r*d%)e)}QJmYRHI$$5l!8 z?EF(CzsL*%omBfW>>lJq0uRst%^NQf{5|W(3S7*dE#2m>K;e0a0=LGFK+$xfEd8Rt z$(~!Bno08srxLaZtn;TpdEQ(ToYXyG&C=DUF-7>EZR5+wwXr-;l~Zgm@h8&8U=1!3 zF_i?@T{USz9e9n(4%)yTDpvxI-S~++nZm*o$s@&H`lod+8_c(OfS>}Q1nAr-FN+$j zGIwVHryDy2mQcOU9C>hZ7xz;J4a*RpHEtfjpyeY_MwbnQ*T?;rYYmZ5>rrdP#oHQVa{%us96(cYPKer+x>ZS`$lzPhPj(4bKr?!u+Xf(@+AVNWNzXf z29S4ge6BTrJJXt=;4=R3x|k#^wazg*LX0v<02`ArAXOmbo z9XdNLi)b--Zf8|IS?qKThh?ObLC+cR(K{ROx{y2YNE> ze4HFuU64x+J6WS^i4;P&U& zPP*WWY$`JWF}1`cR8xMztuXr2d4`I>A%6HEZBmQINaM_Kt3uM}ZFIaukcL9`(MJ;6 zOy#+L5_wpW-5sU5N>O#WG3`$1q{x~=3F0c|37}g;qMCN0ADUQHE;S3mAPN}9ki)gY z46BxoK&H66@#;c<*l37v={C2&s3g%f z!E2#HHL8$UZ6Hq)XA4jvx)@ENT~34gh#sk|4u3I;v@>Cpm*(awDWZ{v%ogJtBh#81 zieMWP8&4ia&lclWjNe1hF+nLfg%h1S=LgYqx!YgHFDPUT5WzfOo(P8YhC_XD^772r z0ZZ|7w=}Z#gqs*Dw#5CnAY&aS(qwy0j5RAmbOZ9NPHN$xdZkzb@E`vZZQ)S&1E%eA zpxiMUOD{kjXHLA<)J~k1J~@P{y&?)MC8I_Wj2QfhB&uktCMYiJwVXeOV%<~CG|-aP zY3TC8rG9wFg~gU>en2LDA*6$ixtr@o##Nw-_6QiKK|C#Ed4tVN#kT&X^a_GO0WNeuC>!kRhV3lfN|!c# zTeI%18_Yr#%fONt`{rD2V5e zzz#9)-l}C+C+g&Ei9$(xKdV#AE5452RO63t*V9mOG2jUYNH5jgu_49{C-!D*oh>3|G5W(pswx7_wGKzjAae*=tnQhhv^$isnT$qgM?V z!IA{~2_OKE3UiL2Ux1AahsrxWzrkEGGIH1to$qmtd)Ws|t5vPvzcIZ1dPN&{F@pVm zSVjLS+S$h1L);BMVS3dnkes}U^F1E#0#PN{_u~cjz$4=tGY&7ZIY+k39*CApq`<7# zP8ij3{G>T#m;Z5UHg!#~!KE1}3S=0f<&pV0oH`$0?~>knJEI^R&uR5(Z@mBqR zGQiK>aC|ubfA=PcQ#oSLV@VoY&53|En9$_8CL?)+E@`U0Z_*N4M4G z@Ng;(vQMwI)Mx_h$1qrO>|MW!%XN&383QiSgplWA@2_Xpgs-a%frh0O)%byk%OXyl zMt?s)EkU}$Yz;gaDlVc|HAD?8uTJ|(s#U7B?D(7#y#Ik;)?T}=hC#xxRS5A8@n0Pu z&ixI{_S!q{PomT!!QLdQ)C^P+ePN$O%*Z!1L8P$pTUxnf32IUVMnpDlYZcDGpSv{T z+d>aUKdE3VU%**{Pny!&Msc9oA>W|Mch4sDIxmAdg}>LMg+#S@PtdCz);B$%4TZ&z zd(Ao~|2$*UsAh@6C?-b1NXsSED{|uYH~0^A9f>HLhH1wJ?xD035oCUt?EqKH%(l<7 zhv+l9hH*z#Bku=FP{Ymb&b;ajf^~1p5HPfWK@>$OkiW9Ztz2pe(TtrJ2<~rHGy8ND z%P5L8X6&LPx~*N>JqGa}4tM7}ngJQ)?ZL=pb<^Z%dw4k{yvS8E{Oi3U$ZR*dXO=Ye zUg~xk^BmI>t>2sJXzYuv1NW%wK zJ20X@kn=W01o(gj5rK6dSYAf$H*vkssQE*1h{j!PX6M+eTeO(l_3#n^Z6|Oy@(Z21 zXmb99CLe;FAe2ZKF763HnFkEGx0KJfdFy_sDdKsKVZRpdG)UVH|0)SZDoCqZ9K?a* z2fg5z&+E(1dD!V}>gw1m1~m`+!(N+pive%c%Q@4(6H)`19D^N#GC>JT&2Rs4z~bB9 zZ(WD1PAme$qqkI`v`8A7R4@y0q*o>&scC{szbw7rY>s!4ZFRP>R2CU@GWxN1l$jIH<;dbsm(i6nai0$Z>xT4SPHj7=E0gV)S^m1N`N$QGv0t_9mSv30 za=lQ4GM&}67pZpEppsbo{HcxOnxsJZZD7l?_~^~M(SB${vR>!}SEpd^T=^m@5My@% zh9JNHet)5EFNAXViPq40c6l!*ruC;Uj(U00BZA7!8cpDf7T9=9`XiMA_ikot+ML7B z8q)W;IlQ!6kyVwUoQY#&u)J;JcW+yQQ%Igb$2LGy3ar*cTO=b(YOc1g2`&}y0FfWu z?+@vgg#@SFLt3I%GJQ{%g~D>!NjsgtHFiDzha< zwI@?P!%q08saNy4R4dKa^xtJq1ofWPoSJC6JxgkEOnriW2M10u^bbk3pJ+I~v?ce?X zl7AbDVMn1Fka_wMuD zw-W-1xgjf_YTM$Qc!P^UZJUQ?3;=?)&%P=xPKaW9UV{X`!;m!c?9kc&Xy&?%D7NY| zPp!FAYm2pw3u>-OaqLvMCQh$4 z-$`z}y}lb+8yPitpO1Z$w8+>Ne7GHjUnt7jv~W3FYHSKwATMiRO^T(jTRZQIuy2z{ zW(JXZ8JJ42#OP#w&4wPgk@pPIC!)WJyfV8K6;n(*zklsxNct86j8oKwa#jyP?07oa zhqcMNlqOn6)p{_yKQ2K&JcK_W#zuV!F4xlZ2;ML_U$NnHvICxEQM|kj=Nkr&F($^? zzn`jh->;$oT{$0DSKO|9?BlJo4;5y1#BRdU~V*LOajiABbuS97HIk zz(9-?U|GO4K%hS>5Dux{(FHchd5CCuv3;@gnCipu5KA%QkgKwY@ zh-*DF-vWSefcM4DVUEDp%_rrX{%y`SV9z(_jRv6oC4bF-3|Xev0~q=)c=24S*+%U1 z^#L$_i+}Qe=|2*3_znSRKT^JPUbuJkQ+DIUf^HnAm7|`-E#ye1}FmvKXU*(FF8y;X#oH4$S<>xox305*1hjQ0QtA$ z*TzT88~?-3mhZc7$HySR;;rT}^10*d?7b>FpG-c zMsf-7aNRW+kQ-?45s9lp!y@`kllKA&t0~n(^=>MCqrE@yI4DYdBR4YkUh}#6Z-AUq zyKjMJM)s2I$ZDe?(iTkjxLyjI!U4MLBB)-2xA)Y>Y$TN=zWk=pH zhAPXKH`U!GJ3hsg{OExThmMsq9>fH0+iD5ay&>f6yY8yIyY{dm%G>FkI?G0ZztLTZ z7U?IlQn?8P%wpQL|9Fl#9-KKI_QUtTrx-MDL zzH{4JPutw?-P6SC13h&uVgqJw6KxFd4Vy~*FA0#~+;oM%Jfp=tp-xB{(>Mv`4J`c_ z$(;hIb=|(Y!^{DuQV1(F-E`>XX@HEr*w(mLfinE)K^z{RlW^n!x_#G>PF9X}@`!tk zKPH-!<4DQ%`;CDaqr-?D=OHKrfKut8XedGM<=S8k2SW_cEp`*IuJ!8Q{2W-0yZ*uG z0d-moXi1J|(*7BBhK!GYBNDsr2R?=rYn<8CZIz-ZVQc*bz}IH`!hX7ceBa?E7Lmt2 zjE^rm9+|azrXq)a$?d4gLUIa zeJ~!xYY@;lIIRB2V(aYlJ$?Er57FP({f(_qndN|KG>0s(r8Ml4ROQvQ!lTyyX6-x; z{Ut%OqMbhA1LBYY|3|>s z#-CdK^E-n4>%))q04<=F^ku8%kr!Hg=fYjQN#26#m68}xOA)GBtl zD6W5>b}OBRP+g%=hh;*35Bd$vO}AJSLCMv(wzvq4RP`;3Zp^o)6@^-%_u)67)napZ z&~TDM)BNOC%62BM_!W;S{-{f*d9KLv2lq0*8xkrCoiQzem*p2%;>=T{eIKYZ4Rj*) z^1Bm;vKNLe?ECb}V4SKSfs2tXD@K%%-37ln3j1I29}9Ree&jTU7JIiV+;PZVzO^+pI;h?p&k4uf0lXo^^!jmm5<1|6x$xqbiU zoPK32R+&C%i*b=xoj#{pm)(rUkk{NhEZcAQDsvGN8-nRp6fB-& z&a09JRW+xz5L5IMrG}X2(rK{(pU~(j99y7X<1P@7DEgA}Iu?XrKrewZhA@?y^n;=9 zDEgvpa69GR0UrwFL_HryhH4eip#bxm6)Y_CuMd!XC$zOpU@iowVePR9)^*3RjbxR1 zWB!$e(hGE)Uovp4iSXFWk`59jU;V(FgS@x~utXUXadU{Pyu?x0IXiZvJxusM9vdFcK7mh~+Y=9z|VpV~N#lV7-Ob6Zsq$^HF*gS*aXq2RSxC z4n?{;B;p(1jU(m_BgS*<_SI9EHOnuZ=FkH-}|vIXP#>CEC6Q`&Xl zV#kHrpi-ey`~0KU9Ya*DNG+(|cQi`eNBlR_yaho;G9=5x0XwB_wVep-#GqAxd5-NL zh4RHEz8x$!k5a5nja%#6LUpWU$)FGY#EhKaTa$w~&;FBd_Ual&W81Dbwi*Lw% zckcu|&c%fPy@Pz~Bv~aIF-~qH|EP8AFbnw=CwzUX_;r?YMnj6BnOnp=Unw>JJrFR~ z8vCrpUUcDQ%=Cg=f5JXlri=U}V7Sa@ni`V?G;vxH+bqe^Ea~sus*$>k6+vYhXwk;P)-rKS+HfI#)ffRKvC=(SXOZB1o1;K zSyqD9XEOm`Ygv*kg1MIa2c5%4vo%58?lPRzhe5@xEf&r#<%KrB+i32!nU1ZN7oW}XY$Ap9_kjeSk#e+n3 z64&h5x_iw(_0kqMiZMj3$Cu`U$pm29Mc1hCy0@&p_|@E_RP0=4TA%kQPDydS;zorB z!24cD(?khCi#hr%KH(Lw)!?!`tJjGF*CPJDeWO66YDYZI*$o|E=#k?h%UT?=JWB1Lv4^tD> z8jrYFa<?63TDrMuMdqMnWJewfliaK#TMG39o-;xo-znKZdfG9sU zd}Xi6NqpfEJhQ8>qlqeN4I1hyZXLsArO5Qg_4b#B*6$1`3X-z!Opc0gH?CrE`KlF| zQR7-Po0-|cs_oo3Tw1j~nVMVgue40^)J%|sE+HBDt+bn7VC!Pg-vth|LIU9a0v^tE zJR#ClQ+Y3=4I9be+70_{e08-aP5QWiVexxWv2=$Oe-XKnuxl1Za8{(xGCZ1bnP(yE zX+cMkjx=w3%vHw^Fx9h1wFe>R654_z!6W+Q@kNK^n3U4#OK`O0!Qhu`#*}1_eJ%sTjyM#5fw?h zFS+tNfv)_j!Iy9G9J_uUS2o~8Hf!wt(L4N0ouE-Qk!yXFxXt;E@0Ok%8VH;zA}8nI zY!Dnilj73$p3ZI1hhCP0w5>Myl4yLE?Wh!-8-EG*;`JVM5!!_j|41tV&wzisdiaWm z!HLW!kk&6X@`r*HYzBjbmxHCOu5L1t$wxn?FvfA|fG$42b%C`c!{7h@E+vpICiLP} zT{LaNnYMegNohLsZVqD3>3youAZvZxWZWZT?roV?gjopyz{j^EXe9hngw+twoo6bc_R)8 zCuDX;_SV1*KzQ97PQ6jyF_a>Gx0zT_aG>N{9_l6Q(Y1g`=GQO00$A^erN)91Lx6&+ z5r{eZYaL-+-Cw>P-Y>TCiO@fDjjd(?Cx%OwUYtWrTl>pb+SNPXe*n_k-jIowVjawQcS0r!L@B6(uH(@{kz!2J0|0gD4@YdzHPrF) zz=m=N#44I43lOUlb&xU+DQdh&U<{wTu(d1xl8o|dNhInGY(>ZdNF)MyIHLB3UNt2d z!T8OJdpgx7!{YXOm7_M${0h?)Gd>`pYR~U3{5ZoNTet=*ZI#q&N&_s zm>qegvYR5r`n(MtkfK@?GnkwdS0{|1k1oq|oT@r2bVlTQ5K`&+X+RQT>J}~TYf4q- z1Q4}p>h<3JO$nhZ0z4ow{8tE*FocbMR&jLjB?Vw3GJeV3RMuP$Grd<~5Muc7Qf{ob zYD4UgVz)cposkyJTjioFpJVJ%a4{3lp#68-fP~&fM!Yi_qiO95-ubx*SqSoYz}xBD z@wt_d7JqMzkSDAqt_t0@My4TdS{N-a8c#JOh~Gv_W7Ky(KBze5%qKH%w8y`skPHth zJGrW%Sy}+w&@<^^CZfD#G2}bvM^=B1nx}I0uPmdjyu>FSX$#gG&zM#;GfOOrnc8{--Kj^0@&?g-`ABlPa zvM=@&I<~|Z-py98rC?l#zbwcUEk-5=)p~A&mE$*nbGWrP-Z&e^qwuFLD8ce

qh% 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.41.1 +transformers>=4.44.0 datasets accelerate peft @@ -10,11 +10,10 @@ peft appdirs loralib scipy -py7zr # 圧縮解凍library +py7zr bitsandbytes -fire # argparser +fire -# formatter & linter black flake8 diff --git a/scripts/abci/phi3/phi3-14b.sh b/scripts/abci/phi3/phi3-14b.sh index 512d7f9..df48553 100644 --- a/scripts/abci/phi3/phi3-14b.sh +++ b/scripts/abci/phi3/phi3-14b.sh @@ -136,7 +136,7 @@ mpirun -np $NUM_GPUS \ --optimizer adam \ --adam-beta1 0.9 \ --adam-beta2 0.95 \ - --adam-eps 1e-5 \ + --adam-eps 1e-8 \ --save-interval 500 \ --eval-interval 100 \ --eval-iters 10 \ diff --git a/scripts/gcp/codestral-22b.sh b/scripts/gcp/codestral-22b.sh index caa9ee6..7e2eaad 100644 --- a/scripts/gcp/codestral-22b.sh +++ b/scripts/gcp/codestral-22b.sh @@ -87,14 +87,14 @@ LR_DECAY_STEPS=25000 WEIGHT_DECAY=0.1 GRAD_CLIP=1 # model config -TOKENIZER_MODEL=/home/ext_kazuki_fujii_rio_gsic_titech/hf_checkpoints/Codestral-22B-v0.1/tokenizer.model -CHECKPOINT_DIR=/home/ext_kazuki_fujii_rio_gsic_titech/hf_checkpoints/Codestral-22B-v0.1 -CHECKPOINT_SAVE_DIR=/home/ext_kazuki_fujii_rio_gsic_titech/checkpoints/Codestral-22B-v0.1 +TOKENIZER_MODEL=/home/kazuki/hf_checkpoints/Codestral-22B-v0.1/tokenizer.model +CHECKPOINT_DIR=/home/kazuki/hf_checkpoints/Codestral-22B-v0.1 +CHECKPOINT_SAVE_DIR=/home/kazuki/checkpoints/Codestral-22B-v0.1 mkdir -p ${CHECKPOINT_SAVE_DIR} # data config -DATASET_DIR=/home/ext_kazuki_fujii_rio_gsic_titech/datasets/debug/Codestral-22B-v0.1 +DATASET_DIR=/home/kazuki/datasets/debug/Codestral-22B-v0.1 TRAIN_DATA_PATH="" @@ -132,7 +132,7 @@ mpirun -np $NUM_GPUS \ --optimizer adam \ --adam-beta1 0.9 \ --adam-beta2 0.95 \ - --adam-eps 1e-5 \ + --adam-eps 1e-8 \ --save-interval 500 \ --eval-interval 100 \ --eval-iters 10 \ diff --git a/scripts/gcp/tokenize/codestral-ja-wiki.sh b/scripts/gcp/tokenize/codestral-ja-wiki.sh index 7c61e08..cd40bd7 100644 --- a/scripts/gcp/tokenize/codestral-ja-wiki.sh +++ b/scripts/gcp/tokenize/codestral-ja-wiki.sh @@ -1,10 +1,10 @@ #!/bin/bash -# swich virtual env +# switch virtual env source .env/bin/activate -DATASET_DIR=/home/ext_kazuki_fujii_rio_gsic_titech/datasets/samples -OUTPUT_DIR=/home/ext_kazuki_fujii_rio_gsic_titech/datasets/debug/Codestral-22B-v0.1 +DATASET_DIR=/home/kazuki/datasets/samples +OUTPUT_DIR=/home/kazuki/datasets/debug/Codestral-22B-v0.1 mkdir -p ${OUTPUT_DIR} @@ -13,6 +13,6 @@ python megatron_lm/tools/preprocess_data.py \ --input ${DATASET_DIR}/ja_wiki.jsonl \ --output-prefix ${OUTPUT_DIR}/ja_wiki \ --tokenizer-type Llama2Tokenizer \ - --tokenizer-model /home/ext_kazuki_fujii_rio_gsic_titech/hf_checkpoints/Codestral-22B-v0.1/tokenizer.model \ + --tokenizer-model /home/kazuki/hf_checkpoints/Codestral-22B-v0.1/tokenizer.model \ --append-eod \ --workers 64 diff --git a/scripts/gcp/tokenize/yi-1.5-ja-wiki.sh b/scripts/gcp/tokenize/yi-1.5-ja-wiki.sh index 63edeaf..d0d4a70 100644 --- a/scripts/gcp/tokenize/yi-1.5-ja-wiki.sh +++ b/scripts/gcp/tokenize/yi-1.5-ja-wiki.sh @@ -3,8 +3,8 @@ # swich virtual env source .env/bin/activate -DATASET_DIR=/home/ext_kazuki_fujii_rio_gsic_titech/datasets/samples -OUTPUT_DIR=/home/ext_kazuki_fujii_rio_gsic_titech/datasets/debug/yi-1.5 +DATASET_DIR=/home/kazuki/datasets/samples +OUTPUT_DIR=/home/kazuki/datasets/debug/yi-1.5 mkdir -p ${OUTPUT_DIR} @@ -13,6 +13,6 @@ python megatron_lm/tools/preprocess_data.py \ --input ${DATASET_DIR}/ja_wiki.jsonl \ --output-prefix ${OUTPUT_DIR}/ja_wiki \ --tokenizer-type Llama2Tokenizer \ - --tokenizer-model /home/ext_kazuki_fujii_rio_gsic_titech/hf_checkpoints/Yi-1.5-9B/tokenizer.model \ + --tokenizer-model /home/kazuki/hf_checkpoints/Yi-1.5-9B/tokenizer.model \ --append-eod \ --workers 64 diff --git a/scripts/gcp/yi-1.5-9b.sh b/scripts/gcp/yi-1.5-9b.sh index 6e657a8..e4a7b6f 100644 --- a/scripts/gcp/yi-1.5-9b.sh +++ b/scripts/gcp/yi-1.5-9b.sh @@ -87,14 +87,14 @@ LR_DECAY_STEPS=25000 WEIGHT_DECAY=0.1 GRAD_CLIP=1 # model config -TOKENIZER_MODEL=/home/ext_kazuki_fujii_rio_gsic_titech/hf_checkpoints/Yi-1.5-9B/tokenizer.model -CHECKPOINT_DIR=/home/ext_kazuki_fujii_rio_gsic_titech/hf_checkpoints/Yi-1.5-9B -CHECKPOINT_SAVE_DIR=/home/ext_kazuki_fujii_rio_gsic_titech/checkpoints/Yi-1.5-9B +TOKENIZER_MODEL=/home/kazuki/hf_checkpoints/Yi-1.5-9B/tokenizer.model +CHECKPOINT_DIR=/home/kazuki/hf_checkpoints/Yi-1.5-9B +CHECKPOINT_SAVE_DIR=/home/kazuki/checkpoints/Yi-1.5-9B mkdir -p ${CHECKPOINT_SAVE_DIR} # data config -DATASET_DIR=/home/ext_kazuki_fujii_rio_gsic_titech/datasets/debug/yi-1.5 +DATASET_DIR=/home/kazuki/datasets/debug/yi-1.5 DATA_PATH="" @@ -132,7 +132,7 @@ mpirun -np $NUM_GPUS \ --optimizer adam \ --adam-beta1 0.9 \ --adam-beta2 0.95 \ - --adam-eps 1e-5 \ + --adam-eps 1e-8 \ --save-interval 500 \ --eval-interval 100 \ --eval-iters 10 \ From 393b7469b1499d566f669e003bf4357f4ca5ea3e Mon Sep 17 00:00:00 2001 From: kazuki Date: Fri, 16 Aug 2024 21:21:47 +0900 Subject: [PATCH 06/10] feat: delete unnecessary files --- src/llama_recipes/inference/__init__.py | 2 - src/llama_recipes/inference/chat_utils.py | 65 ------- .../inference/checkpoint_converter_fsdp_hf.py | 65 ------- src/llama_recipes/inference/model_utils.py | 30 ---- src/llama_recipes/inference/safety_utils.py | 169 ------------------ tests/conftest.py | 18 -- tests/datasets/test_custom_dataset.py | 58 ------ tests/datasets/test_grammar_datasets.py | 54 ------ tests/datasets/test_samsum_datasets.py | 37 ---- tests/test_batching.py | 94 ---------- tests/test_finetuning.py | 75 -------- tests/test_sampler.py | 86 --------- 12 files changed, 753 deletions(-) delete mode 100644 src/llama_recipes/inference/__init__.py delete mode 100644 src/llama_recipes/inference/chat_utils.py delete mode 100644 src/llama_recipes/inference/checkpoint_converter_fsdp_hf.py delete mode 100644 src/llama_recipes/inference/model_utils.py delete mode 100644 src/llama_recipes/inference/safety_utils.py delete mode 100644 tests/conftest.py delete mode 100644 tests/datasets/test_custom_dataset.py delete mode 100644 tests/datasets/test_grammar_datasets.py delete mode 100644 tests/datasets/test_samsum_datasets.py delete mode 100644 tests/test_batching.py delete mode 100644 tests/test_finetuning.py delete mode 100644 tests/test_sampler.py diff --git a/src/llama_recipes/inference/__init__.py b/src/llama_recipes/inference/__init__.py deleted file mode 100644 index 54ed04d..0000000 --- a/src/llama_recipes/inference/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# This software may be used and distributed according to the terms of the Llama 2 Community License Agreement. \ No newline at end of file diff --git a/src/llama_recipes/inference/chat_utils.py b/src/llama_recipes/inference/chat_utils.py deleted file mode 100644 index 8d781e3..0000000 --- a/src/llama_recipes/inference/chat_utils.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# This software may be used and distributed according to the terms of the Llama 2 Community License Agreement. - -import json -from typing import List, Literal, TypedDict - - -Role = Literal["user", "assistant"] - - -class Message(TypedDict): - role: Role - content: str - - -Dialog = List[Message] - -B_INST, E_INST = "[INST]", "[/INST]" -B_SYS, E_SYS = "<>\n", "\n<>\n\n" -def format_tokens(dialogs, tokenizer): - prompt_tokens = [] - for dialog in dialogs: - if dialog[0]["role"] == "system": - dialog = [ - { - "role": dialog[1]["role"], - "content": B_SYS - + dialog[0]["content"] - + E_SYS - + dialog[1]["content"], - } - ] + dialog[2:] - assert all([msg["role"] == "user" for msg in dialog[::2]]) and all( - [msg["role"] == "assistant" for msg in dialog[1::2]] - ), ( - "model only supports 'system','user' and 'assistant' roles, " - "starting with user and alternating (u/a/u/a/u...)" - ) - """ - Please verify that your tokenizer support adding "[INST]", "[/INST]" to your inputs. - Here, we are adding it manually. - """ - dialog_tokens: List[int] = sum( - [ - tokenizer.encode( - f"{B_INST} {(prompt['content']).strip()} {E_INST} {(answer['content']).strip()} ", - ) - for prompt, answer in zip(dialog[::2], dialog[1::2]) - ], - [], - ) - assert ( - dialog[-1]["role"] == "user" - ), f"Last message must be from user, got {dialog[-1]['role']}" - dialog_tokens += tokenizer.encode( - f"{B_INST} {(dialog[-1]['content']).strip()} {E_INST}", - ) - prompt_tokens.append(dialog_tokens) - return prompt_tokens - - -def read_dialogs_from_file(file_path): - with open(file_path, 'r') as file: - dialogs = json.load(file) - return dialogs \ No newline at end of file diff --git a/src/llama_recipes/inference/checkpoint_converter_fsdp_hf.py b/src/llama_recipes/inference/checkpoint_converter_fsdp_hf.py deleted file mode 100644 index 175a97c..0000000 --- a/src/llama_recipes/inference/checkpoint_converter_fsdp_hf.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# This software may be used and distributed according to the terms of the Llama 2 Community License Agreement. - -# from accelerate import init_empty_weights, load_checkpoint_and_dispatch - -import fire -import os -import sys -import yaml - -from transformers import LlamaTokenizer - -from llama_recipes.inference.model_utils import load_llama_from_config - -# Get the current file's directory -current_directory = os.path.dirname(os.path.abspath(__file__)) - -# Get the parent directory -parent_directory = os.path.dirname(current_directory) - -# Append the parent directory to sys.path -sys.path.append(parent_directory) -from model_checkpointing import load_sharded_model_single_gpu - -def main( - fsdp_checkpoint_path="", # Path to FSDP Sharded model checkpoints - consolidated_model_path="", # Path to save the HF converted model checkpoints - HF_model_path_or_name="" # Path/ name of the HF model that include config.json and tokenizer_config.json (e.g. meta-llama/Llama-2-7b-chat-hf) - ): - - try: - file_name = 'train_params.yaml' - # Combine the directory and file name to create the full path - train_params_path = os.path.join(fsdp_checkpoint_path, file_name) - # Open the file - with open(train_params_path, 'r') as file: - # Load the YAML data - data = yaml.safe_load(file) - - # Access the 'model_name' field - HF_model_path_or_name = data.get('model_name') - - print(f"Model name: {HF_model_path_or_name}") - except FileNotFoundError: - print(f"The file {train_params_path} does not exist.") - HF_model_path_or_name = input("Please enter the model name: ") - print(f"Model name: {HF_model_path_or_name}") - except Exception as e: - print(f"An error occurred: {e}") - - - #load the HF model definition from config - model_def = load_llama_from_config(HF_model_path_or_name) - print("model is loaded from config") - #load the FSDP sharded checkpoints into the model - model = load_sharded_model_single_gpu(model_def, fsdp_checkpoint_path) - print("model is loaded from FSDP checkpoints") - #loading the tokenizer form the model_path - tokenizer = LlamaTokenizer.from_pretrained(HF_model_path_or_name) - tokenizer.save_pretrained(consolidated_model_path) - #save the FSDP sharded checkpoints in HF format - model.save_pretrained(consolidated_model_path) - print(f"HuggingFace model checkpoints has been saved in {consolidated_model_path}") -if __name__ == "__main__": - fire.Fire(main) diff --git a/src/llama_recipes/inference/model_utils.py b/src/llama_recipes/inference/model_utils.py deleted file mode 100644 index 02785e9..0000000 --- a/src/llama_recipes/inference/model_utils.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# This software may be used and distributed according to the terms of the GNU General Public License version 3. - -from peft import PeftModel -from transformers import LlamaForCausalLM, LlamaConfig - -# Function to load the main model for text generation -def load_model(model_name, quantization): - model = LlamaForCausalLM.from_pretrained( - model_name, - return_dict=True, - load_in_8bit=quantization, - device_map="auto", - low_cpu_mem_usage=True, - ) - return model - - -# Function to load the PeftModel for performance optimization -def load_peft_model(model, peft_model): - peft_model = PeftModel.from_pretrained(model, peft_model) - return peft_model - -# Loading the model from config to load FSDP checkpoints into that -def load_llama_from_config(config_path): - model_config = LlamaConfig.from_pretrained(config_path) - model = LlamaForCausalLM(config=model_config) - return model - - \ No newline at end of file diff --git a/src/llama_recipes/inference/safety_utils.py b/src/llama_recipes/inference/safety_utils.py deleted file mode 100644 index 38a44d4..0000000 --- a/src/llama_recipes/inference/safety_utils.py +++ /dev/null @@ -1,169 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# This software may be used and distributed according to the terms of the Llama 2 Community License Agreement. - -import os -import torch -import warnings - - -# Class for performing safety checks using AuditNLG library -class AuditNLGSensitiveTopics(object): - def __init__(self): - pass - - def __call__(self, output_text): - try: - from auditnlg.safety.exam import safety_scores - except ImportError as e: - print("Could not import optional dependency: auditnlg\nPlease install manually with:\n pip install auditnlg\nFollowed by:\npip install -r requirements.txt") - raise e - - - data = [{"output": output_text}] - - result = safety_scores(data=data, method="sensitive_topics") - scores = result[1]["all_scores"][0] - is_safe = scores["pred_class"] == "none" - report = "" - if not is_safe: - report += f"Predicted class: {scores['pred_class']}\n" - report += "|" + "|".join(f"{n:^10}" for n in [list(k.keys())[0] for k in scores["class_scores"]]) + "|\n" - report += "|" + "|".join(f"{n:^10.5}" for n in [list(k.values())[0] for k in scores["class_scores"]]) + "|\n" - return "Sensitive Topics", is_safe, report - - -class SalesforceSafetyChecker(object): - def __init__(self): - pass - - def __call__(self, output_text): - from transformers import AutoModelForSeq2SeqLM, AutoTokenizer, AutoConfig - - config = AutoConfig.from_pretrained("Salesforce/safety-flan-t5-base") - tokenizer = AutoTokenizer.from_pretrained("Salesforce/safety-flan-t5-base") - model = AutoModelForSeq2SeqLM.from_pretrained("Salesforce/safety-flan-t5-base", config=config) - model.eval() - - prefix = "Is the field safe or unsafe?" - input_ids = tokenizer(prefix + " " + output_text + " ", return_tensors="pt").input_ids - - if len(input_ids[0]) > 512: - warnings.warn( - "Input length is > 512 token. Safety check result could be incorrect." - ) - - with torch.no_grad(): - outputs = model.generate( - input_ids, - output_scores=True, - return_dict_in_generate=True, - max_new_tokens=20, - ) - - is_safe = tokenizer.decode(outputs.sequences[0], skip_special_tokens=True).split(" ")[0] == "safe" - - report = "" - if not is_safe: - true_false_ids = tokenizer("true false").input_ids[:2] - keys = ["toxicity", "hate", "identity", "violence", "physical", "sexual", "profanity", "biased"] - scores = {} - for k, i in zip(keys, range(3,20,2)): - scores[k] = round(outputs.scores[i][0,true_false_ids].softmax(dim=0)[0].item(), 5) - - report += "|" + "|".join(f"{n:^10}" for n in scores.keys()) + "|\n" - report += "|" + "|".join(f"{n:^10}" for n in scores.values()) + "|\n" - return "Salesforce Content Safety Flan T5 Base", is_safe, report - - - def get_total_length(self, data): - prefix = "Is the field safe or unsafe " - input_sample = " {output} ".format(**data[0]) - - return len(self.tokenizer(prefix + input_sample)["input_ids"]) - - -# Class for performing safety checks using Azure Content Safety service -class AzureSaftyChecker(object): - def __init__(self): - try: - from azure.ai.contentsafety import ContentSafetyClient - from azure.core.credentials import AzureKeyCredential - - key = os.environ["CONTENT_SAFETY_KEY"] - endpoint = os.environ["CONTENT_SAFETY_ENDPOINT"] - except ImportError: - raise Exception( - "Could not import required package azure-ai-contentsafety. Install with: pip install azure-ai-contentsafety" - ) - except KeyError: - raise Exception( - "Environment variables not set. Please set CONTENT_SAFETY_KEY and CONTENT_SAFETY_ENDPOINT." - ) - - self.client = ContentSafetyClient(endpoint, AzureKeyCredential(key)) - - def __call__(self, output_text): - from azure.core.exceptions import HttpResponseError - from azure.ai.contentsafety.models import AnalyzeTextOptions, TextCategory - - print(len(output_text)) - if len(output_text) > 1000: - raise Exception("Input length to safety check is too long (>1000).") - - categories = [ - TextCategory.VIOLENCE, - TextCategory.SELF_HARM, - TextCategory.SEXUAL, - TextCategory.HATE, - ] - - request = AnalyzeTextOptions(text=output_text, categories=categories) - - try: - response = self.client.analyze_text(request) - except HttpResponseError as e: - print("Analyze text failed.") - if e.error: - print(f"Error code: {e.error.code}") - print(f"Error message: {e.error.message}") - raise - print(e) - raise e - - levels = {0: "Safe", 2: "Low", 4: "Medium", 6: "High"} - - severities = [ - getattr(response, c.name.lower() + "_result").severity for c in categories - ] - - DEFAULT_LEVELS = [0, 0, 0, 0] - - is_safe = all([s <= l for s, l in zip(severities, DEFAULT_LEVELS)]) - - report = "" - if not is_safe: - report = "|" + "|".join(f"{c.name:^10}" for c in categories) + "|\n" - report += "|" + "|".join(f"{levels[s]:^10}" for s in severities) + "|\n" - - return "Azure Content Saftey API", is_safe, report - - -# Function to load the PeftModel for performance optimization -# Function to determine which safety checker to use based on the options selected -def get_safety_checker(enable_azure_content_safety, - enable_sensitive_topics, - enable_salesforce_content_safety, - ): - safety_checker = [] - if enable_azure_content_safety: - safety_checker.append(AzureSaftyChecker()) - if enable_sensitive_topics: - safety_checker.append(AuditNLGSensitiveTopics()) - if enable_salesforce_content_safety: - safety_checker.append(SalesforceSafetyChecker()) - return safety_checker - - - - - diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index a441def..0000000 --- a/tests/conftest.py +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# This software may be used and distributed according to the terms of the Llama 2 Community License Agreement. - -import pytest - -from transformers import LlamaTokenizer - - -@pytest.fixture -def setup_tokenizer(): - def _helper(tokenizer): - #Align with Llama 2 tokenizer - tokenizer.from_pretrained.return_value = LlamaTokenizer.from_pretrained("decapoda-research/llama-7b-hf") - tokenizer.from_pretrained.return_value.add_special_tokens({'bos_token': '', 'eos_token': ''}) - tokenizer.from_pretrained.return_value.bos_token_id = 1 - tokenizer.from_pretrained.return_value.eos_token_id = 2 - - return _helper diff --git a/tests/datasets/test_custom_dataset.py b/tests/datasets/test_custom_dataset.py deleted file mode 100644 index 9c8d0b6..0000000 --- a/tests/datasets/test_custom_dataset.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# This software may be used and distributed according to the terms of the Llama 2 Community License Agreement. - -import pytest -from unittest.mock import patch - - -@patch('llama_recipes.finetuning.train') -@patch('llama_recipes.finetuning.LlamaForCausalLM.from_pretrained') -@patch('llama_recipes.finetuning.LlamaTokenizer.from_pretrained') -@patch('llama_recipes.finetuning.optim.AdamW') -@patch('llama_recipes.finetuning.StepLR') -def test_custom_dataset(step_lr, optimizer, tokenizer, get_model, train, mocker): - from llama_recipes.finetuning import main - - tokenizer.return_value = mocker.MagicMock(side_effect=lambda x: {"input_ids":[len(x)*[0,]], "attention_mask": [len(x)*[0,]]}) - - kwargs = { - "dataset": "custom_dataset", - "custom_dataset.file": "examples/custom_dataset.py", - "batch_size": 1, - "use_peft": False, - } - - main(**kwargs) - - assert train.call_count == 1 - - args, kwargs = train.call_args - train_dataloader = args[1] - eval_dataloader = args[2] - - VAL_SAMPLES = 818 - TRAIN_SAMPLES = 14732 - CONCAT_SIZE = 2048 - - assert len(train_dataloader) == TRAIN_SAMPLES // CONCAT_SIZE - assert len(eval_dataloader) == VAL_SAMPLES - - -@patch('llama_recipes.finetuning.train') -@patch('llama_recipes.finetuning.LlamaForCausalLM.from_pretrained') -@patch('llama_recipes.finetuning.LlamaTokenizer.from_pretrained') -@patch('llama_recipes.finetuning.optim.AdamW') -@patch('llama_recipes.finetuning.StepLR') -def test_unknown_dataset_error(step_lr, optimizer, tokenizer, get_model, train, mocker): - from llama_recipes.finetuning import main - - tokenizer.return_value = mocker.MagicMock(side_effect=lambda x: {"input_ids":[len(x)*[0,]], "attention_mask": [len(x)*[0,]]}) - - kwargs = { - "dataset": "custom_dataset", - "custom_dataset.file": "examples/custom_dataset.py:get_unknown_dataset", - "batch_size": 1, - "use_peft": False, - } - with pytest.raises(AttributeError): - main(**kwargs) diff --git a/tests/datasets/test_grammar_datasets.py b/tests/datasets/test_grammar_datasets.py deleted file mode 100644 index 67b37eb..0000000 --- a/tests/datasets/test_grammar_datasets.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# This software may be used and distributed according to the terms of the Llama 2 Community License Agreement. - -from unittest.mock import patch - -from transformers import LlamaTokenizer - - -@patch('llama_recipes.finetuning.train') -@patch('llama_recipes.finetuning.LlamaTokenizer') -@patch('llama_recipes.finetuning.LlamaForCausalLM.from_pretrained') -@patch('llama_recipes.finetuning.optim.AdamW') -@patch('llama_recipes.finetuning.StepLR') -def test_grammar_dataset(step_lr, optimizer, get_model, tokenizer, train, mocker, setup_tokenizer): - from llama_recipes.finetuning import main - - setup_tokenizer(tokenizer) - - BATCH_SIZE = 8 - kwargs = { - "model_name": "decapoda-research/llama-7b-hf", - "batch_size": BATCH_SIZE, - "batch_size": 1, - "use_peft": False, - "dataset": "grammar_dataset", - "batching_strategy": "padding", - } - - main(**kwargs) - - assert train.call_count == 1 - - args, kwargs = train.call_args - train_dataloader = args[1] - eval_dataloader = args[2] - - VAL_SAMPLES = 2988 - TRAIN_SAMPLES = 13016 - - assert len(train_dataloader) == TRAIN_SAMPLES // BATCH_SIZE - assert len(eval_dataloader) == VAL_SAMPLES - - batch = next(iter(train_dataloader)) - - assert "labels" in batch.keys() - assert "input_ids" in batch.keys() - assert "attention_mask" in batch.keys() - - assert batch["labels"][0][29] == -100 - assert batch["labels"][0][30] == 29871 - - assert batch["input_ids"][0][0] == 1 - assert batch["labels"][0][-1] == 2 - assert batch["input_ids"][0][-1] == 2 diff --git a/tests/datasets/test_samsum_datasets.py b/tests/datasets/test_samsum_datasets.py deleted file mode 100644 index ece230e..0000000 --- a/tests/datasets/test_samsum_datasets.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# This software may be used and distributed according to the terms of the Llama 2 Community License Agreement. - -from unittest.mock import patch - - -@patch('llama_recipes.finetuning.train') -@patch('llama_recipes.finetuning.LlamaForCausalLM.from_pretrained') -@patch('llama_recipes.finetuning.LlamaTokenizer.from_pretrained') -@patch('llama_recipes.finetuning.optim.AdamW') -@patch('llama_recipes.finetuning.StepLR') -def test_custom_dataset(step_lr, optimizer, tokenizer, get_model, train, mocker): - from llama_recipes.finetuning import main - - tokenizer.return_value = mocker.MagicMock(side_effect=lambda x: {"input_ids":[len(x)*[0,]], "attention_mask": [len(x)*[0,]]}) - - - kwargs = { - "batch_size": 1, - "use_peft": False, - "dataset": "samsum_dataset", - } - - main(**kwargs) - - assert train.call_count == 1 - - args, kwargs = train.call_args - train_dataloader = args[1] - eval_dataloader = args[2] - - VAL_SAMPLES = 818 - TRAIN_SAMPLES = 14732 - CONCAT_SIZE = 2048 - assert len(train_dataloader) == TRAIN_SAMPLES // CONCAT_SIZE - assert len(eval_dataloader) == VAL_SAMPLES - \ No newline at end of file diff --git a/tests/test_batching.py b/tests/test_batching.py deleted file mode 100644 index 0f0f21e..0000000 --- a/tests/test_batching.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# This software may be used and distributed according to the terms of the Llama 2 Community License Agreement. - -import pytest -from unittest.mock import patch - - -@patch('llama_recipes.finetuning.train') -@patch('llama_recipes.finetuning.LlamaTokenizer') -@patch('llama_recipes.finetuning.LlamaForCausalLM.from_pretrained') -@patch('llama_recipes.finetuning.optim.AdamW') -@patch('llama_recipes.finetuning.StepLR') -def test_packing(step_lr, optimizer, get_model, tokenizer, train, mocker, setup_tokenizer): - from llama_recipes.finetuning import main - - setup_tokenizer(tokenizer) - - kwargs = { - "model_name": "decapoda-research/llama-7b-hf", - "batch_size": 8, - "batch_size": 1, - "use_peft": False, - "dataset": "samsum_dataset", - "batching_strategy": "packing", - } - - main(**kwargs) - - assert train.call_count == 1 - - args, kwargs = train.call_args - train_dataloader = args[1] - eval_dataloader = args[2] - - assert len(train_dataloader) == 96 - assert len(eval_dataloader) == 42 - - batch = next(iter(train_dataloader)) - - assert "labels" in batch.keys() - assert "input_ids" in batch.keys() - assert "attention_mask" in batch.keys() - - assert batch["labels"][0].size(0) == 4096 - assert batch["input_ids"][0].size(0) == 4096 - assert batch["attention_mask"][0].size(0) == 4096 - - -@patch('llama_recipes.finetuning.train') -@patch('llama_recipes.finetuning.LlamaTokenizer') -@patch('llama_recipes.finetuning.LlamaForCausalLM.from_pretrained') -@patch('llama_recipes.finetuning.optim.AdamW') -@patch('llama_recipes.finetuning.StepLR') -@patch('llama_recipes.finetuning.setup') -@patch('llama_recipes.finetuning.FSDP') -@patch('llama_recipes.finetuning.torch.distributed.is_initialized') -@patch('llama_recipes.utils.config_utils.dist') -def test_distributed_packing(dist, is_initialized, fsdp, setup, step_lr, optimizer, get_model, tokenizer, train, setup_tokenizer): - import os - from llama_recipes.finetuning import main - - setup_tokenizer(tokenizer) - - rank = 0 - os.environ['LOCAL_RANK'] = f'{rank}' - os.environ['RANK'] = f'{rank}' - os.environ['WORLD_SIZE'] = '2' - os.environ['MASTER_ADDR'] = 'localhost' - os.environ['MASTER_PORT'] = '12345' - - kwargs = { - "model_name": "decapoda-research/llama-7b-hf", - "batch_size": 8, - "batch_size": 1, - "use_peft": False, - "dataset": "samsum_dataset", - "batching_strategy": "packing", - "enable_fsdp": True - } - - is_initialized.return_value = True - dist.get_rank.return_value = rank - dist.get_world_size.return_value = 2 - - main(**kwargs) - - assert train.call_count == 1 - - args, kwargs = train.call_args - train_dataloader = args[1] - eval_dataloader = args[2] - - assert len(train_dataloader) == 96 //2 - assert len(eval_dataloader) == 42 //2 diff --git a/tests/test_finetuning.py b/tests/test_finetuning.py deleted file mode 100644 index abaa4bd..0000000 --- a/tests/test_finetuning.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# This software may be used and distributed according to the terms of the Llama 2 Community License Agreement. - -from unittest.mock import patch -import importlib - -from torch.utils.data.dataloader import DataLoader - -from llama_recipes.finetuning import main - -@patch('llama_recipes.finetuning.train') -@patch('llama_recipes.finetuning.LlamaForCausalLM.from_pretrained') -@patch('llama_recipes.finetuning.LlamaTokenizer.from_pretrained') -@patch('llama_recipes.finetuning.get_preprocessed_dataset') -@patch('llama_recipes.finetuning.optim.AdamW') -@patch('llama_recipes.finetuning.StepLR') -def test_finetuning_no_validation(step_lr, optimizer, get_dataset, tokenizer, get_model, train): - kwargs = {"run_validation": False} - - get_dataset.return_value = [1] - - main(**kwargs) - - assert train.call_count == 1 - - args, kwargs = train.call_args - train_dataloader = args[1] - eval_dataloader = args[2] - - assert isinstance(train_dataloader, DataLoader) - assert eval_dataloader is None - - assert get_model.return_value.to.call_args.args[0] == "cuda" - - -@patch('llama_recipes.finetuning.train') -@patch('llama_recipes.finetuning.LlamaForCausalLM.from_pretrained') -@patch('llama_recipes.finetuning.LlamaTokenizer.from_pretrained') -@patch('llama_recipes.finetuning.get_preprocessed_dataset') -@patch('llama_recipes.finetuning.optim.AdamW') -@patch('llama_recipes.finetuning.StepLR') -def test_finetuning_with_validation(step_lr, optimizer, get_dataset, tokenizer, get_model, train): - kwargs = {"run_validation": True} - get_dataset.return_value = [1] - - main(**kwargs) - - assert train.call_count == 1 - - args, kwargs = train.call_args - train_dataloader = args[1] - eval_dataloader = args[2] - assert isinstance(train_dataloader, DataLoader) - assert isinstance(eval_dataloader, DataLoader) - - assert get_model.return_value.to.call_args.args[0] == "cuda" - - -@patch('llama_recipes.finetuning.train') -@patch('llama_recipes.finetuning.LlamaForCausalLM.from_pretrained') -@patch('llama_recipes.finetuning.LlamaTokenizer.from_pretrained') -@patch('llama_recipes.finetuning.get_preprocessed_dataset') -@patch('llama_recipes.finetuning.generate_peft_config') -@patch('llama_recipes.finetuning.get_peft_model') -@patch('llama_recipes.finetuning.optim.AdamW') -@patch('llama_recipes.finetuning.StepLR') -def test_finetuning_peft(step_lr, optimizer, get_peft_model, gen_peft_config, get_dataset, tokenizer, get_model, train): - kwargs = {"use_peft": True} - - get_dataset.return_value = [1] - - main(**kwargs) - - assert get_peft_model.return_value.to.call_args.args[0] == "cuda" - assert get_peft_model.return_value.print_trainable_parameters.call_count == 1 \ No newline at end of file diff --git a/tests/test_sampler.py b/tests/test_sampler.py deleted file mode 100644 index 8cdb4bb..0000000 --- a/tests/test_sampler.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# This software may be used and distributed according to the terms of the Llama 2 Community License Agreement. - -import random -import pytest - -import torch - -from llama_recipes.data.sampler import LengthBasedBatchSampler -from llama_recipes.data.sampler import DistributedLengthBasedBatchSampler - -SAMPLES = 33 - -@pytest.fixture -def dataset(): - random.seed(42) - dataset = [] - def add_samples(ds, n, a, b): - for _ in range(n): - ds.append(random.randint(a,b) * [1,]) - add_samples(dataset, SAMPLES // 2, 1,9) - add_samples(dataset, (SAMPLES // 2) + (SAMPLES % 2), 10,20) - - return random.sample(dataset, len(dataset)) - - -@pytest.mark.parametrize("batch_size, drop_last", [(2, False), (8, False), (2, True), (8, True)]) -def test_batch_sampler_array(dataset, batch_size, drop_last): - - sampler = LengthBasedBatchSampler(dataset, batch_size, drop_last) - - EXPECTED_LENGTH = SAMPLES // batch_size if drop_last else (SAMPLES // batch_size) + (SAMPLES % batch_size) - - all_ids = [i for b in sampler for i in b] - assert len(set(all_ids)) == EXPECTED_LENGTH * batch_size if drop_last else len(dataset) - - assert len(sampler) == EXPECTED_LENGTH - is_long = [len(d)>=10 for d in dataset] - - def check_batch(batch): - return all(batch) or not any(batch) - - assert all(check_batch(is_long[i] for i in b) for b in sampler) - - -@pytest.mark.parametrize("batch_size, drop_last", [(2, False), (8, False), (2, True), (8, True)]) -def test_batch_sampler_dict(dataset, batch_size, drop_last): - - dist_dataset = [{"input_ids": d, "attention_mask": d} for d in dataset] - - sampler = LengthBasedBatchSampler(dist_dataset, batch_size, drop_last) - - EXPECTED_LENGTH = SAMPLES // batch_size if drop_last else (SAMPLES // batch_size) + (SAMPLES % batch_size) - - assert len(sampler) == EXPECTED_LENGTH - is_long = [len(d)>=10 for d in dataset] - - def check_batch(batch): - return all(batch) or not any(batch) - - assert all(check_batch(is_long[i] for i in b) for b in sampler) - - -@pytest.mark.parametrize("batch_size", [2, 8]) -def test_dist_batch_sampling(dataset, batch_size): - sampler_1 = DistributedLengthBasedBatchSampler( - dataset, - batch_size=batch_size, - rank=0, - num_replicas=2, - shuffle=False, - ) - sampler_2 = DistributedLengthBasedBatchSampler( - dataset, - batch_size=batch_size, - rank=1, - num_replicas=2, - shuffle=False, - ) - - ids_1 = set(i for b in sampler_1 for i in b) - ids_2 = set(i for b in sampler_2 for i in b) - - assert ids_1.isdisjoint(ids_2) - assert len(ids_1)+len(ids_2) > 0 - assert len(ids_1)+len(ids_2) == len(dataset) // batch_size * batch_size \ No newline at end of file From 1870233e675519a2ed2fd3b8326cb5b57525ea39 Mon Sep 17 00:00:00 2001 From: kazuki Date: Fri, 16 Aug 2024 21:35:33 +0900 Subject: [PATCH 07/10] doc: update feature metrics --- README.md | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 25b2af1..53092e1 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,15 @@ llm-recipes is a tool designed to make the continual pre-training of Large Langu What sets llm-recipes apart is its seamless integration with Hugging Face Transformers, allowing you to continue pre-training or perform instruction tuning on Dense LLMs (non-MoE models) with minimal changes. This means there’s no need to convert checkpoints or deal with complex workflows—just focus on refining your model. +| Feature | llm-recipes | llama-recipes | torchtune | +|---------------------------------|-------------|---------------|-----------| +| **SFT(Supervised Fine-Tuning)** | ✅ | ✅ | ✅ | +| **Continual Pre-Training** | ✅ | ✅ | ✅ | +| **DPO(Direct Preference Optimization)** | ✅ | ❌ | ❌ | +| **Llama Models Support** | ✅ | ✅ | ✅ | +| **Non-Llama Models Support** | ✅ | ❌ | ❌ | +| **Multi-Node Support** | ✅ | ✅ | ❌ | + # Table of Contents - [Installation](#installation) @@ -138,7 +147,11 @@ python megatron_lm/tools/preprocess_data.py \ #### 3. **Training** +We support Llama-2, Llama-3, Llama-3.1, Mistral, Codestral, Phi-3, Yi-1.5, and gemma-2. +If you want to continually pre-train or instruction tune other models, you should modify `src/llama_recipes/get_models.py` and `src/llama_recipes/get_model_decoder_layer.py`. +We provide example scripts for continual pre-training for codestral-22B in `scripts/gcp/codestral-22b.sh`. +You can modify the script to suit your needs. ### LLM DPO @@ -150,7 +163,7 @@ The documentation will be updated soon. ### llm-recipes format -llm-recipes creates 2 types of checkpoints: PyTorch format and PyTorch distributed format. +llm-recipes supports 2 types of checkpoints: PyTorch format and PyTorch distributed format. The PyTorch format is a simple checkpoint format. The example of the PyTorch format is as follows: ```bash @@ -165,9 +178,31 @@ __0_0.distcp __1_0.distcp __2_0.distcp __3_0.distcp __4_0.distcp __5_0.dist ### PyTorch format to Hugging Face format +You can convert the PyTorch format to the Hugging Face format using the following command: + +```bash +ITERATION=1000 +FORMATTED_ITERATION=$(printf "iter_%07d" $ITERATION) + +CHECK_POINT_PATH=/path/to/train/checkpoint/${FORMATTED_ITERATION}/model.pt +OUTPUT_PATH=/path/to/converted/checkpoint/${FORMATTED_ITERATION} + +mkdir -p $OUTPUT_PATH + +BASE_MODEL_CHECKPOINT=/path/to/huggingface-checkpoint/Llama-2-7b-hf + +python tools/checkpoint-convert/convert_ckpt.py \ + --model $BASE_MODEL_CHECKPOINT \ + --ckpt $CHECK_POINT_PATH \ + --out $OUTPUT_PATH \ + --sequence-length 4096 +``` + ### PyTorch distributed format to Hugging Face format + + ## Inference ## Training Speed and Scalability From e9c6b564acd28abedb341e96edf0098e7bcd0b2d Mon Sep 17 00:00:00 2001 From: kazuki Date: Sat, 17 Aug 2024 00:03:28 +0900 Subject: [PATCH 08/10] feat: fsdp convert script --- tools/checkpoint-convert/convert_fsdp.py | 155 +++++------------- .../scripts/abci/convert_fsdp.sh | 58 +++---- 2 files changed, 65 insertions(+), 148 deletions(-) diff --git a/tools/checkpoint-convert/convert_fsdp.py b/tools/checkpoint-convert/convert_fsdp.py index 016bbce..caa857c 100644 --- a/tools/checkpoint-convert/convert_fsdp.py +++ b/tools/checkpoint-convert/convert_fsdp.py @@ -1,143 +1,66 @@ +import argparse +import os import sys -sys.path.append("/bb/llm/gaf51275/llama/llama-recipes/src") +current_path: str = os.getcwd() +sys.path.append(f"{current_path}/src") +sys.path.append(current_path) -from transformers import ( # noqa: F401 - LlamaConfig, - LlamaForCausalLM, - LlamaTokenizer, - default_data_collator, -) -from torch.distributed._shard.checkpoint import FileSystemReader -from torch.distributed.fsdp import FullyShardedDataParallel as FSDP # type: ignore -from torch.distributed.fsdp.fully_sharded_data_parallel import CPUOffload # type: ignore -from torch.distributed.fsdp import ShardingStrategy # type: ignore -from torch.distributed.fsdp.fully_sharded_data_parallel import StateDictType # type: ignore import torch -from typing import Any -import torch.distributed.checkpoint as dist_cp -import os -import argparse -import torch.distributed as torch_distributed -from llama_recipes.utils import fsdp_auto_wrap_policy -from transformers.models.llama.modeling_llama import LlamaDecoderLayer -from llama_recipes.utils.train_utils import clear_gpu_cache +import torch.distributed._shard.checkpoint as dist_cp +from torch.distributed._shard.checkpoint import FileSystemReader +from transformers import AutoModelForCausalLM, AutoTokenizer + + +def load_sharded_model_single_gpu(model, model_path: str): + state_dict = { + "model": model.state_dict() + } + dist_cp.load( + state_dict=state_dict, + storage_reader= FileSystemReader(model_path), + ) + model.load_state_dict(state_dict["model"]) + + print(f"Sharded state checkpoint loaded from {model_path}", flush=True) + return model def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description="Llama-Recipes convert") parser.add_argument("--hf-base-model-path", type=str, default=None, help="huggingface checkpoint path") + parser.add_argument("--tokenizer-path", type=str, default=None, help="tokenizer path") parser.add_argument("--fsdp-checkpoint-path", type=str, default=None, help="FSDP checkpoint path") parser.add_argument("--checkpoint-output-path", type=str, default=None, help="output checkpoint path") + parser.add_argument("--sequence-length", type=int, required=True) args = parser.parse_args() return args def main() -> None: - # distributed setting - global_rank = int(os.getenv("OMPI_COMM_WORLD_RANK", 0)) - local_rank = int(os.getenv("OMPI_COMM_WORLD_LOCAL_RANK", 0)) - world_size = int(os.getenv("OMPI_COMM_WORLD_SIZE", 1)) - - os.environ["RANK"] = str(global_rank) - os.environ["LOCAL_RANK"] = str(local_rank) - os.environ["WORLD_SIZE"] = str(world_size) - - torch_distributed.init_process_group("nccl") - print(f"torch.distributed.init rank={torch_distributed.get_rank()}", flush=True) - args = parse_args() - if torch_distributed.is_initialized(): - torch.cuda.set_device(local_rank) - clear_gpu_cache(local_rank) - - # model definition - if torch_distributed.get_rank() == 0: - print("model loading start", flush=True) - - if torch_distributed.get_rank() == 0: - model = LlamaForCausalLM.from_pretrained( - args.hf_base_model_path, - load_in_8bit=None, - device_map=None, - use_cache=None, - ) - else: - llama_config = LlamaConfig.from_pretrained(args.hf_base_model_path) - llama_config.use_cache = False - with torch.device("meta"): - model = LlamaForCausalLM(llama_config) - - if torch_distributed.get_rank() == 0: - print("model setup", flush=True) - - my_auto_wrapping_policy = fsdp_auto_wrap_policy(model, LlamaDecoderLayer) - - fsdp_model = FSDP( - module=model, # type: ignore - auto_wrap_policy=my_auto_wrapping_policy, - cpu_offload=CPUOffload(offload_params=True), - mixed_precision=None, # bf16の場合は None にする - sharding_strategy=ShardingStrategy.FULL_SHARD, - device_id=torch.cuda.current_device(), - limit_all_gathers=True, - sync_module_states=True, - param_init_fn=lambda module: module.to_empty(device=torch.device("cuda"), recurse=False), # type: ignore - ) - if torch_distributed.get_rank() == 0: - print("FSDP model setup done", flush=True) - - reader = FileSystemReader( - args.fsdp_checkpoint_path + model = AutoModelForCausalLM.from_pretrained( + args.hf_base_model_path, + torch_dtype=torch.bfloat16, + trust_remote_code=True, + max_position_embeddings=args.sequence_length, ) - with FSDP.state_dict_type(fsdp_model, StateDictType.SHARDED_STATE_DICT): - state_dict: dict[str, Any] = { - "model": fsdp_model.state_dict(), - # cannot load the optimizer state_dict together with the model state_dict - } - - dist_cp.load_state_dict( # type: ignore - state_dict=state_dict, - storage_reader=reader, - ) - fsdp_model.load_state_dict(state_dict["model"]) - - print("load fsdp checkpoint : rank = ", torch_distributed.get_rank(), flush=True) - - state_dict = get_model_state_dict(fsdp_model) - print("get_model_state_dict : rank = ", torch_distributed.get_rank(), flush=True) + print(f"Loaded HF model: {args.hf_base_model_path}\n", flush=True) - if torch_distributed.get_rank() == 0: - hf_model = LlamaForCausalLM.from_pretrained( - args.hf_base_model_path, - torch_dtype=torch.bfloat16, - ) - # convert to hf checkpoint - hf_model.load_state_dict(state_dict) # type: ignore - print("load_state_dict", flush=True) + print(f"Loading sharded checkpoint from {args.fsdp_checkpoint_path}", flush=True) + model = load_sharded_model_single_gpu(model, args.fsdp_checkpoint_path) + print(f"Loaded sharded checkpoint from {args.fsdp_checkpoint_path}\n", flush=True) - hf_model.save_pretrained(args.checkpoint_output_path) # type: ignore - - torch_distributed.barrier() - print("Done!: rank = ", torch_distributed.get_rank(), flush=True) - - -from torch.distributed.fsdp import FullStateDictConfig # type: ignore - - -def get_model_state_dict(model: FSDP) -> dict[str, torch.Tensor]: - with FSDP.state_dict_type( - model, - StateDictType.FULL_STATE_DICT, - FullStateDictConfig(offload_to_cpu=True, rank0_only=True), - ): - # state_dict() を呼ぶことで parameter を 保存してくれる - state_dict = model.state_dict() + tokenizer = AutoTokenizer.from_pretrained( + args.tokenizer_path, + ) + tokenizer.save_pretrained(args.checkpoint_output_path) - return state_dict + model.save_pretrained(args.checkpoint_output_path, safe_serialization=True) + print(f"Saved checkpoint to {args.checkpoint_output_path}", flush=True) if __name__ == "__main__": diff --git a/tools/checkpoint-convert/scripts/abci/convert_fsdp.sh b/tools/checkpoint-convert/scripts/abci/convert_fsdp.sh index 18abe39..d01277d 100644 --- a/tools/checkpoint-convert/scripts/abci/convert_fsdp.sh +++ b/tools/checkpoint-convert/scripts/abci/convert_fsdp.sh @@ -1,52 +1,46 @@ -#!/bin/bash -#$ -l rt_AF=1 -#$ -l h_rt=10:00:00 -#$ -j y -#$ -o outputs/convert/fsdp/ +#!/bin/sh #$ -cwd +#$ -l node_f=1 +#$ -l h_rt=0:1:00:00 +#$ -o outputs/convert/$JOB_ID.log +#$ -e outputs/convert/$JOB_ID.log +#$ -p -5 + # module load -source /etc/profile.d/modules.sh -module load cuda/11.8/11.8.0 -module load cudnn/8.9/8.9.2 -module load nccl/2.16/2.16.2-1 -module load hpcx/2.12 +module use /gs/fs/tga-NII-LLM/modules/modulefiles + +module load ylab/cuda/12.1 +module load ylab/cudnn/8.9.7 +module load ylab/nccl/cuda-12.2/2.20.5 +module load ylab/hpcx/2.17.1 +module load ninja/1.11.1 set -e # swich virtual env source .env/bin/activate -# distributed settings -export MASTER_ADDR=$(/usr/sbin/ip a show dev bond0 | grep 'inet ' | awk '{ print $2 }' | cut -d "/" -f 1) -export MASTER_PORT=$((10000 + ($JOB_ID % 50000))) - -echo "MASTER_ADDR=${MASTER_ADDR}" - -start=10000 -end=12000 +start=78 +end=78 increment=1000 for ((i = start; i <= end; i += increment)); do ITERATION=$i FORMATTED_ITERATION=$(printf "iter_%07d" $ITERATION) - CHECK_POINT_PATH=/bb/gaf51217/fujii/checkpoints/llama-2-13b-chat-filtered-gbs_16-a100_2/${FORMATTED_ITERATION} - OUTPUT_PATH=/bb/gaf51217/fujii/hf_checkpoints/kotoba/llama-2-13b-chat-filtered-gbs_16/${FORMATTED_ITERATION} + CHECK_POINT_PATH=/gs/bs/tga-NII-LLM/checkpoints/Llama-3-8B-Instruct-v0.2/LR_1e-5_MINLR_1e-6_WD_0.1_GC_1-dist-ckpt/${FORMATTED_ITERATION} + OUTPUT_PATH=/gs/bs/tga-NII-LLM/checkpoints/fsdp-hf/Llama-3-8B-Instruct-v0.2/LR_1e-5_MINLR_1e-6_WD_0.1_GC_1-dist-ckpt/${FORMATTED_ITERATION} echo "convert FSDP ${CHECK_POINT_PATH} to ${OUTPUT_PATH}" mkdir -p $OUTPUT_PATH - BASE_MODEL_CHECKPOINT=/bb/llm/gaf51275/llama/huggingface-checkpoint/Llama-2-13b-hf - - mpirun -np 8 \ - --npernode 8 \ - -x MASTER_ADDR=$MASTER_ADDR \ - -x MASTER_PORT=$MASTER_PORT \ - -bind-to none -map-by slot \ - -x PATH \ - python tools/checkpoint-convert/convert_fsdp.py \ - --hf-base-model-path $BASE_MODEL_CHECKPOINT \ - --fsdp-checkpoint-path $CHECK_POINT_PATH \ - --checkpoint-output-path $OUTPUT_PATH + BASE_MODEL_CHECKPOINT=/gs/bs/tga-NII-LLM/hf-checkpoints/Meta-Llama-3-8B-Instruct + + python tools/checkpoint-convert/convert_fsdp.py \ + --hf-base-model-path $BASE_MODEL_CHECKPOINT \ + --tokenizer-path $BASE_MODEL_CHECKPOINT \ + --fsdp-checkpoint-path $CHECK_POINT_PATH \ + --checkpoint-output-path $OUTPUT_PATH \ + --sequence-length 8192 done From be9a2e24b3ec4f14a78bdff3e02dab844260cc18 Mon Sep 17 00:00:00 2001 From: kazuki Date: Sat, 17 Aug 2024 00:03:42 +0900 Subject: [PATCH 09/10] chore: update inference script --- tools/inference/inference.sh | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tools/inference/inference.sh b/tools/inference/inference.sh index 4d05001..2e6c191 100644 --- a/tools/inference/inference.sh +++ b/tools/inference/inference.sh @@ -1,31 +1,33 @@ -#!/bin/bash -#$ -l rt_AG.small=1 -#$ -l h_rt=1:00:00 -#$ -j y -#$ -o outputs/inference/ +#!/bin/sh #$ -cwd +#$ -l node_q=1 +#$ -l h_rt=0:1:00:00 +#$ -o outputs/inference/$JOB_ID.log +#$ -e outputs/inference/$JOB_ID.log +#$ -p -5 # module load -source /etc/profile.d/modules.sh -module use /bb/llm/gaf51275/modules/modulefiles +module use /gs/fs/tga-NII-LLM/modules/modulefiles -module load cuda/12.1/12.1.1 -module load cudnn/cuda-12.1/9.0.0 -module load nccl/2.20.5 -module load hpcx/2.12 -module load gcc/11.4.0 +module load ylab/cuda/12.1 +module load ylab/cudnn/8.9.7 +module load ylab/nccl/cuda-12.2/2.20.5 +module load ylab/hpcx/2.17.1 +module load ninja/1.11.1 set -e # swich virtual env source .env/bin/activate +INFERENCE_MODEL_DIR=/gs/bs/tga-NII-LLM/checkpoints/fsdp-hf/Llama-3-8B-Instruct-v0.2/LR_1e-5_MINLR_1e-6_WD_0.1_GC_1-dist-ckpt/iter_0000078 + python tools/inference/inference.py \ - --model-path /bb/llm/gaf51275/llama/converted-hf-checkpoint/mistral-7B-VE/okazaki-cc/iter_0004000 \ - --tokenizer-path /bb/llm/gaf51275/llama/converted-hf-checkpoint/mistral-7B-VE/okazaki-cc/iter_0004000 \ + --model-path $INFERENCE_MODEL_DIR \ + --tokenizer-path $INFERENCE_MODEL_DIR \ --prompt "Tokyo is the capital of Japan." python tools/inference/inference.py \ - --model-path /bb/llm/gaf51275/llama/converted-hf-checkpoint/mistral-7B-VE/okazaki-cc/iter_0004000 \ - --tokenizer-path /bb/llm/gaf51275/llama/converted-hf-checkpoint/mistral-7B-VE/okazaki-cc/iter_0004000 \ + --model-path $INFERENCE_MODEL_DIR \ + --tokenizer-path $INFERENCE_MODEL_DIR \ --prompt "東京工業大学のキャンパスは" From 129b36a6a0d2efcfe3be850c28b09bdd3b47c612 Mon Sep 17 00:00:00 2001 From: kazuki Date: Sat, 17 Aug 2024 00:03:56 +0900 Subject: [PATCH 10/10] docs: update README --- README.md | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 53092e1..bd54b04 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ What sets llm-recipes apart is its seamless integration with Hugging Face Transf | Feature | llm-recipes | llama-recipes | torchtune | |---------------------------------|-------------|---------------|-----------| | **SFT(Supervised Fine-Tuning)** | ✅ | ✅ | ✅ | -| **Continual Pre-Training** | ✅ | ✅ | ✅ | +| **Continual Pre-Training** | ✅ | ✅ | ✅ | | **DPO(Direct Preference Optimization)** | ✅ | ❌ | ❌ | | **Llama Models Support** | ✅ | ✅ | ✅ | | **Non-Llama Models Support** | ✅ | ❌ | ❌ | @@ -200,13 +200,47 @@ python tools/checkpoint-convert/convert_ckpt.py \ ### PyTorch distributed format to Hugging Face format +You can convert the PyTorch distributed format to the Hugging Face format using the following command: +```bash + ITERATION=1000 + FORMATTED_ITERATION=$(printf "iter_%07d" $ITERATION) + + CHECK_POINT_PATH=/path/to/fsdp/checkpoint/${FORMATTED_ITERATION} + OUTPUT_PATH=/path/to/converted-hf-checkpoint/${FORMATTED_ITERATION} + + echo "convert FSDP ${CHECK_POINT_PATH} to ${OUTPUT_PATH}" + mkdir -p $OUTPUT_PATH + + BASE_MODEL_CHECKPOINT=/path/to/hf-checkpoints/Meta-Llama-3-8B-Instruct + + python tools/checkpoint-convert/convert_fsdp.py \ + --hf-base-model-path $BASE_MODEL_CHECKPOINT \ + --tokenizer-path $BASE_MODEL_CHECKPOINT \ + --fsdp-checkpoint-path $CHECK_POINT_PATH \ + --checkpoint-output-path $OUTPUT_PATH \ + --sequence-length 8192 +``` ## Inference +After checkpoint conversion, you can use the Hugging Face Transformers library to load the converted checkpoint and perform inference. + +The following is an example of how to do inference using the converted checkpoint (huggingface format): + +```bash +python tools/inference/inference.py \ + --model-path /path/to/converted/iter_0004000 \ + --tokenizer-path /path/to/tokenizer/path \ + --prompt "Tokyo is the capital of" +``` + ## Training Speed and Scalability +We are currently working on improving the training speed and scalability of llm-recipes. +We will update this section with more information soon. + ## Projects Using llm-recipes Below are some of the projects where we have directly used llm-recipes: @@ -216,3 +250,4 @@ Below are some of the projects where we have directly used llm-recipes: ## Citation +we are current submitting the paper to SC24 workshop, and the citation will be updated soon.