Reference code openai/gpt-2 @ 9b63575, huggingface/transformers @ 71c6f69, configuration openai-community/gpt2 @ 607a30d · checkpoint tensors not independently counted · How to read

GPT-2 model overview

  1. UTF-8 text passes through byte-level BPE, which is configured by fixed vocabulary and merge assets.
  2. Token IDs cross the preprocessing boundary and select rows from the learned token embedding table WTE.
  3. The token sequence shape determines absolute position IDs, independently of token values, which select rows from WPE on a lower positional branch.
  4. Token and position embeddings are added, then training-only embedding dropout produces x zero. Evaluation leaves the sum unchanged.
  5. Exactly 12 transformer blocks transform x zero into x_12.
  6. Final LayerNorm acts across the 768-dimensional feature axis with epsilon equal to 10 to the minus 5.
  7. The transpose view of the shared WTE matrix projects the final states to logits without adding parameters.

Vocabulary and merge ranks

×

no parametersself.encoder, self.bpe_ranks

A fixed vocabulary of 50,257 entries and an ordered list of BPE merge ranks.

Explanation

encoder.json maps token strings to integer IDs. vocab.bpe lists the merges in order, and a merge’s rank is its position in that list (encoder.py 49, 113); BPE applies the lowest-ranked pair first.

Codeencoder.py 44–49, 108–117
encoder.py 44–49
        self.encoder = encoder
        self.decoder = {v:k for k,v in self.encoder.items()}
        self.errors = errors # how to handle errors in decoding
        self.byte_encoder = bytes_to_unicode()
        self.byte_decoder = {v:k for k, v in self.byte_encoder.items()}
        self.bpe_ranks = dict(zip(bpe_merges, range(len(bpe_merges))))
encoder.py 108–117
def get_encoder(model_name, models_dir):
    with open(os.path.join(models_dir, model_name, 'encoder.json'), 'r') as f:
        encoder = json.load(f)
    with open(os.path.join(models_dir, model_name, 'vocab.bpe'), 'r', encoding="utf-8") as f:
        bpe_data = f.read()
    bpe_merges = [tuple(merge_str.split()) for merge_str in bpe_data.split('\n')[1:-1]]
    return Encoder(
        encoder=encoder,
        bpe_merges=bpe_merges,
    )
Sources1

Contextual evidence

The released encoder loads encoder.json and the ordered BPE merge ranks.

openai · openai/gpt-2 / src/encoder.py
Pinned revision 9b63575ef427 ↗ · lines 44–117

Read code excerpt
        self.encoder = encoder
        self.decoder = {v:k for k,v in self.encoder.items()}
        self.errors = errors # how to handle errors in decoding
        self.byte_encoder = bytes_to_unicode()
        self.byte_decoder = {v:k for k, v in self.byte_encoder.items()}
        self.bpe_ranks = dict(zip(bpe_merges, range(len(bpe_merges))))

… lines 50–107 omitted …

def get_encoder(model_name, models_dir):
    with open(os.path.join(models_dir, model_name, 'encoder.json'), 'r') as f:
        encoder = json.load(f)
    with open(os.path.join(models_dir, model_name, 'vocab.bpe'), 'r', encoding="utf-8") as f:
        bpe_data = f.read()
    bpe_merges = [tuple(merge_str.split()) for merge_str in bpe_data.split('\n')[1:-1]]
    return Encoder(
        encoder=encoder,
        bpe_merges=bpe_merges,
    )