Instructions to use KexuanShi/Megatron-LM with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- NeMo
How to use KexuanShi/Megatron-LM with NeMo:
# tag did not correspond to a valid NeMo domain.
- Notebooks
- Google Colab
- Kaggle
| # Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. | |
| """Tokenization utilities.""" | |
| import torch | |
| from megatron.core import parallel_state | |
| from megatron.core.inference.communication_utils import broadcast_int_list, broadcast_tensor | |
| def tokenize_prompts( | |
| tokenizer, prompts=None, tokens_to_generate=None, add_BOS=None, rank=0, data_parallel=False | |
| ): | |
| """Tokenize prompts and make them avaiable on all ranks. | |
| Args: | |
| data_parallel (bool): Broadcast tokens across a single data parallel model replica. | |
| """ | |
| # On all ranks set to None so we can pass them to functions | |
| sizes_list = None | |
| prompts_tokens_cuda_long_tensor = None | |
| prompts_length_cuda_long_tensor = None | |
| # On the specified rank, build the above. | |
| src_rank = torch.distributed.get_rank() | |
| if data_parallel: | |
| src_rank = parallel_state.get_data_parallel_src_rank() | |
| if src_rank == rank: | |
| assert prompts is not None | |
| assert tokens_to_generate is not None | |
| # Tensor of tokens padded and their unpadded length. | |
| prompts_tokens_cuda_long_tensor, prompts_length_cuda_long_tensor = ( | |
| _tokenize_prompts_and_batch(tokenizer, prompts, tokens_to_generate, add_BOS) | |
| ) | |
| # We need the sizes of these tensors for the boradcast | |
| sizes_list = [ | |
| prompts_tokens_cuda_long_tensor.size(0), # Batch size | |
| prompts_tokens_cuda_long_tensor.size(1), | |
| ] # Sequence lenght | |
| # First, broadcast the sizes. | |
| sizes_tensor = broadcast_int_list( | |
| 2, int_list=sizes_list, rank=rank, data_parallel=data_parallel | |
| ) | |
| # Now that we have the sizes, we can boradcast the tokens | |
| # and length tensors. | |
| sizes = sizes_tensor.tolist() | |
| prompts_tokens_cuda_long_tensor = broadcast_tensor( | |
| sizes, | |
| torch.int64, | |
| tensor=prompts_tokens_cuda_long_tensor, | |
| rank=rank, | |
| data_parallel=data_parallel, | |
| ) | |
| prompts_length_cuda_long_tensor = broadcast_tensor( | |
| sizes[0], | |
| torch.int64, | |
| tensor=prompts_length_cuda_long_tensor, | |
| rank=rank, | |
| data_parallel=data_parallel, | |
| ) | |
| return prompts_tokens_cuda_long_tensor, prompts_length_cuda_long_tensor | |
| def _tokenize_prompts_and_batch(tokenizer, prompts, tokens_to_generate, add_BOS): | |
| """Given a set of prompts and number of tokens to generate: | |
| - tokenize prompts | |
| - set the sequence length to be the max of length of prompts | |
| plus the number of tokens we would like to generate | |
| - pad all the sequences to this length so we can convert them | |
| into a 2D tensor. | |
| """ | |
| # Tokenize all the prompts. | |
| if hasattr(tokenizer, 'eod'): | |
| eod_token = tokenizer.eod | |
| elif hasattr(tokenizer, 'eos_id'): | |
| eod_token = tokenizer.eos_id | |
| else: | |
| raise AttributeError('No eod token found in Tokenizer') | |
| if add_BOS: | |
| prompts_tokens = [[eod_token] + tokenizer.tokenize(prompt) for prompt in prompts] | |
| else: | |
| prompts_tokens = [tokenizer.tokenize(prompt) for prompt in prompts] | |
| # Now we have a list of list of tokens which each list has a different | |
| # size. We want to extend this list to: | |
| # - incorporate the tokens that need to be generated | |
| # - make all the sequences equal length. | |
| # Get the prompts length. | |
| prompts_length = [len(prompt_tokens) for prompt_tokens in prompts_tokens] | |
| # Get the max prompts length. | |
| max_prompt_len = max(prompts_length) | |
| # Number of tokens in the each sample of the batch. | |
| samples_length = max_prompt_len + tokens_to_generate | |
| # Now update the list of list to be of the same size: samples_length. | |
| for prompt_tokens, prompt_length in zip(prompts_tokens, prompts_length): | |
| padding_size = samples_length - prompt_length | |
| prompt_tokens.extend([eod_token] * padding_size) | |
| # Now we are in a structured format, we can convert to tensors. | |
| prompts_tokens_tensor = torch.tensor(prompts_tokens, dtype=torch.long, device='cuda') | |
| prompts_length_tensor = torch.tensor(prompts_length, dtype=torch.long, device='cuda') | |
| return prompts_tokens_tensor, prompts_length_tensor | |