Preparing Text for LLM Training
Preparing text is a necessary step before large language model training.
Why Raw Text Cannot Go Straight into Training
A large language model learns from large amounts of text, but text in its original written form is not yet ready for training. Preparing text for large language model training is a required step before the model can learn from it. Training does not simply consume text as it was originally written.
Text preparation means transforming text so that a language model can use it during training. This article focuses on one part of that preparation: tokenization, the process of splitting text into smaller units called tokens. Those tokens are the units the rest of the process works with, so the way text is split affects everything that follows.
As you read, keep one question in mind: when a sentence is split into tokens, what does the result look like, and how does the splitting decision change it? A tokenizer makes that decision for every piece of text it receives.
What do you think happens?
Before the model can learn from a story, which form must the text take?
Reveal answer
The text must be prepared, including tokenization, so that the training code can use it.
The source states that preparing text is a required step before training, so the model does not learn directly from the text in its raw form.
Word and Subword Tokens
The source describes tokenization as splitting text into two kinds of token: word tokens, which are whole words, and subword tokens, which are pieces smaller than a word. A word-level split can keep a word as one token, while a subword split can produce several smaller tokens for the same word.
Why The Verdict Is a Practical Example
The text used throughout this part is 'The Verdict', a short story by Edith Wharton that was already used in chapter 2. It is a small text. Because the story is in the public domain, there is no question about usage rights. Because it is small, the code runs on a standard laptop in a matter of minutes, even without a high-end GPU.
Size is the trade-off. A dataset this small cannot train a model that produces useful text on its own. The purpose here is education, so the code runs in minutes instead of weeks. Later in the workflow, pretrained weights from OpenAI are loaded into the model, which is how the small text is made useful in practice.
Dataset choice is therefore a matter of goal and constraints. A small public domain text answers the questions of licensing and speed, which matters when the aim is to learn the mechanics. A larger corpus is the route toward more extensive training, at a much higher computational cost.
To see how far the small example is from production work, consider the 7 billion parameter Llama 2 model, which the source describes as a relatively popular openly available LLM. Training it required 184,320 GPU hours on A100 GPUs and processed 2 trillion tokens. The Verdict exists so that a learner can practice the same workflow shape at a scale a laptop can handle.
Loading the Story and Counting Two Units
The first code step reads the whole story into a single string. The file is opened in read mode with UTF-8 encoding, and file.read() returns its full contents. Once the text is in memory, it can be measured in two different units.
open(..., "r", encoding="utf-8")opens the file in read mode with UTF-8 encodingfile.read()returns the full contents as one stringlen(text_data)counts characters in that string
The number of characters comes from len(text_data). The number of tokens comes from passing the same text through the tokenizer and measuring the result. The two counts answer different questions. The character count describes the raw text, while the token count describes how the model will actually read it.
The source notes that 5,145 tokens may look too small to train an LLM, and that is accepted because the aim is quick educational runs. The token count is the number to watch when judging what the model actually receives.
What do you think happens?
If you want to know how many units the model actually reads, which count should you use?
Reveal answer
The token count from the tokenizer
The character count describes the raw text, while the token count describes how the model reads it.
Splitting Into Training and Validation
Next the text is divided into a training part and a validation part. The validation part is used for model evaluation during training, so it must be kept separate from the training part. The split is set by a train_ratio of 0.90, which means 90 percent of the characters go to training and the remaining 10 percent go to validation. The split index computed from train_ratio divides the text into these two parts, and the two parts are never mixed.
Computing a split index from train_ratio
A text has 1,000 characters and train_ratio is 0.90. Find the split index and the two subsets. This short text is a generated illustration, not the source's story.
- 1Measure the text
len(text_data)gives the number of characters, here 1,000. - 2Multiply by the ratio
0.90 times 1,000 gives 900. This value marks where the training part ends.
- 3Slice the training subset
Characters from position 0 up to but not including position 900 form the training subset. That is 900 characters.
- 4Slice the validation subset
Characters from position 900 to the end form the validation subset. That is the remaining 100 characters, about a tenth of the text.
The split index is 900, the training subset holds the first 90 percent, and the validation subset holds the last 10 percent with no overlap.
Common mistake Letting the validation text overlap the training text
Why it failsThe validation part is used to evaluate the model during training, so shared text would make the evaluation unreliable.
Do this insteadSlice the text at one split index so that the two subsets never share positions.
Common mistake Reading train_ratio as the validation share instead of the training share
From Subsets to Chunks, Shuffles, and Batches
A split subset is still plain text, and the model needs fixed-size tensors. The source describes the preparation as a chain of operations. The subset is tokenized, the token sequence is divided into chunks of a user-specified length, the chunks are shuffled, and the shuffled chunks are organized into batches. The batch size sets how many chunks are processed together.
The loaders are built with the create_dataloader_v1 function from chapter 2. Both calls use the same batch size, max_length, and stride. The settings that differ are drop_last and shuffle, and those differences encode the training-versus-validation distinction. The code also fixes a random seed so the shuffling is repeatable.
batch_size=2 is the number of chunks processed together, chosen because the dataset is smallmax_length=256 sets the length of each chunkdrop_last=True on training discards an incomplete final batch so every training batch is fulldrop_last=False on validation keeps every validation chunk- shuffle=True on training varies example order, shuffle=False on validation keeps a fixed order
Set drop_last and shuffle to match each loader's role. Training benefits from full batches and varied order, while validation should keep every chunk and a fixed order so evaluation stays consistent.
The source uses a batch size of 2 because the dataset is small. It notes that training LLMs with batch sizes of 1,024 or larger is not uncommon in practice. The batch size is therefore a resource choice that scales with the work being done.
Checking the Batch Shapes
The source suggests an optional check. Iterate through each loader and print the shape of every input and target tensor. Each loader yields a pair, an input x and a target y, so the loop unpacks two values per batch.
The printed pattern matches the source: the training loader yields nine batches, each with two samples of 256 tokens, and the validation loader yields one batch of two input examples.- for x, y in loader unpacks the input and the target for each batch
- x.shape and y.shape show the tensor dimensions to check
Based on the printed output, the training loader yields nine batches, each with two samples of 256 tokens. That means each training input batch has shape 2 by 256. The validation loader yields one batch of two input examples. This matches what the split and the batch settings predict, since only about a tenth of the text goes to validation.
Suppose the training loader yields nine batches of two samples each, with 256 tokens per sample. How many token positions does one training input batch hold, and why does the validation loader yield far fewer batches?
Hints
- One input batch holds two samples, and each sample has 256 tokens.
- The validation subset is only about a tenth of the text, so it produces fewer chunks.
Mistakes in Text Preparation
Common mistake Treating the character count as the number of units the model reads
What it looks likeReporting len(text_data) as the model's input size.Why it failsThe character count describes the raw text, while the token count describes how the model actually reads it.
Do this insteadMeasure the tokens produced by the tokenizer when you need the model-facing count.
Common mistake Assuming one word always becomes one token
What it looks likeExpecting unhappiness to be a single token under every split.
Why it failsA subword split can produce several smaller tokens for the same word.
Do this insteadCheck how the tokenizer splits the word before counting.
Common mistake Shuffling the validation loader
Why it failsThe source keeps a fixed order for validation so evaluation stays consistent.
Do this insteadSet shuffle to False on the validation loader.
Common mistake Dropping the last incomplete batch from validation
Why it failsThe source sets
drop_lastto False on validation so no validation chunk is silently discarded.Do this insteadKeep drop_last as False for the validation loader.
Preparation Steps at a Glance
- 1Read the whole story into one string with UTF-8 encoding
- 2Count characters with
len(text_data)and tokens with the tokenizer - 3Split at a split index computed from
train_ratio, keeping training and validation apart - 4Tokenize each subset, divide the tokens into chunks, shuffle the chunks, and group them into batches
- 5Check the printed batch shapes for each loader
Key Takeaways
- Raw text must be prepared before LLM training, and tokenization, which splits text into tokens, is the part of that preparation covered here.
- Word tokens keep a word whole, while subword tokens can split one word into several smaller tokens; byte pair encoding is a more advanced tokenizing method.
- Characters and tokens are different counts, and the token count describes what the model reads.
- A
train_ratioof 0.90 sets a split index so that 90 percent of characters go to training and 10 percent to validation, and the two subsets are never mixed. - Subsets are chunked, shuffled, and batched by data loaders, and printed shapes such as 2 by 256 confirm that the loaders were built correctly.