Generative AI and LLMs

How Large Language Models Work

Lesson 2 of 10

A large language model does one thing: given some text, it predicts what comes next. Everything it appears to do, from answering questions to writing code, comes from doing that very well, over and over.

Step 1: text becomes tokens

A tokeniser splits text into tokens and replaces each with a number. Tokens are pieces of words. Common words are a single token, and rare words are split into several.

vocabulary = ["un", "believ", "able", "happi", "ness", "the", "cat", " "]

def tokenise(text):
    tokens = []
    while text:
        match = max((v for v in vocabulary if text.startswith(v)), key=len, default=None)
        if match is None:
            match = text[0]          # unknown character becomes its own token
        tokens.append(match)
        text = text[len(match):]
    return tokens

for word in ["unbelievable", "unhappiness", "the cat"]:
    tokens = tokenise(word)
    print(word, "->", tokens, "->", [vocabulary.index(t) if t in vocabulary else -1 for t in tokens])

Real tokenisers have vocabularies of tens of thousands of pieces, learned from data with algorithms such as byte-pair encoding. The principle is the same: any text can be written as a sequence of known pieces.

Step 2: tokens become vectors

Each token number is looked up in a table of embeddings, which gives a vector of several hundred or several thousand numbers. Information about each token’s position in the text is added.

Step 3: the transformer layers

The vectors pass through a stack of transformer layers. In each layer, attention lets every token draw information from the tokens before it, and a feed-forward network processes the result. After many layers, the vector at the last position encodes what the model needs to predict the next token.

Step 4: a probability for every token

The final vector is turned into a score for every token in the vocabulary, and the scores are turned into probabilities.

Step 5: choose a token and repeat

One token is chosen, added to the text, and the whole process runs again. This is called autoregressive generation.

import numpy as np

rng = np.random.default_rng(0)

# a toy "model": for each word, the probability of the next word
next_word = {
    "the":  {"cat": 0.5, "dog": 0.3, "sun": 0.2},
    "cat":  {"sat": 0.6, "ran": 0.4},
    "dog":  {"ran": 0.7, "sat": 0.3},
    "sun":  {"rose": 1.0},
    "sat":  {"down": 1.0},
    "ran":  {"away": 1.0},
}

def generate(start, steps=3):
    words = [start]
    for _ in range(steps):
        options = next_word.get(words[-1])
        if not options:
            break
        words.append(rng.choice(list(options), p=list(options.values())))
    return " ".join(words)

for _ in range(4):
    print(generate("the"))

Run it several times. The outputs differ because a token is sampled, not simply picked. A real model does the same with a vocabulary of tens of thousands of tokens and probabilities calculated from the entire preceding text.

Sampling settings

  • Temperature flattens or sharpens the probabilities. Low values give focused, repeatable output. High values give more varied output.
  • Top-p restricts the choice to the most likely tokens whose probabilities add up to p.
  • Maximum tokens limits the length of the output.
  • Stop sequences end generation when a given piece of text appears.

How a model is trained

Pretraining. The model reads an enormous amount of text and is trained to predict the next token. No labels are needed, because the text supplies its own answers. To predict well, the model has to pick up grammar, facts, styles and patterns of reasoning. This stage needs very large amounts of computing power.

Fine-tuning for conversation. The pretrained model is trained further on examples of instructions and good responses, so that it behaves as an assistant.

Alignment with human preferences. People, or models trained on human ratings, score outputs, and the model is adjusted towards responses that are helpful, accurate and safe.

What follows from this

Fact about the mechanism Consequence
It predicts likely text It can produce fluent text that is false
It sees only the context window It knows nothing you did not put there, beyond its training
It works on tokens It can miscount letters and mishandle long numbers
It samples Output varies from run to run
It was trained up to a cut-off date It lacks recent information
Generation is one token at a time Giving it room to reason before answering helps

Parameters and context size

Two numbers describe a model. The parameter count is the number of learned weights. The context window is the number of tokens it can take in at once. A larger context window lets you supply more material, at higher cost and with slower responses.

Practice

Change the probabilities in the toy model so that “the” is followed by “cat” 95% of the time. Generate ten sentences and count how many start with “the cat”.