Every command, every script, every file. The reference chapter to come back to later — and the summary of everything that was measured.
The lab scripts, the course server, the dependency list and the installation instructions are in the course's public repository: github.com/Rafhael-Oliveira-IA/conceitos-gpt. If you do not use git, you can download everything as a .zip file. The models are not in the repository, because they add up to 13.2 GB: the tools/download_models.py script downloads all seven straight from Hugging Face.
# open PowerShell in the repository root and run, in order: .venv\Scripts\python.exe lab\01_tokenizer.py .venv\Scripts\python.exe lab\02_embeddings.py .venv\Scripts\python.exe lab\03_attention.py .venv\Scripts\python.exe lab\04_multihead_mask.py .venv\Scripts\python.exe lab\05_block.py .venv\Scripts\python.exe lab\06_scale.py .venv\Scripts\python.exe lab\07_decoding.py .venv\Scripts\python.exe lab\08_perplexity.py .venv\Scripts\python.exe lab\09_detector.py .venv\Scripts\python.exe lab\10_original_code.py # lab 11 needs the server. In ANOTHER terminal: .venv\Scripts\python.exe server\app.py # and then: .venv\Scripts\python.exe lab\11_api.py
Labs 06 and 08 load gpt2-xl (6 GB of RAM, ~3 min). If you are in a hurry or short on memory, append rapido:
.venv\Scripts\python.exe lab\06_scale.py rapido
| No. | Chapter | Script | The main experiment |
|---|---|---|---|
| 01 | Tokenization and BPE | 01_tokenizer.py | the cost of Portuguese; three incompatible tokenizers |
| 02 | Embeddings | 02_embeddings.py | neighbors of " Brazil"; wpe learned order on its own |
| 03 | Attention | 03_attention.py | softmax saturation without √ |
| 04 | Multi-head and mask | 04_multihead_mask.py | the proof of causality — difference exactly 0.00 |
| 05 | The Transformer block | 05_block.py | Pre-LN vs Post-LN; the logit lens |
| 06 | Architecture and scale | 06_scale.py | the exact parameter formula; in-context learning |
| 07 | Decoding | 07_decoding.py | top-p nucleus from 1 to 5,548 tokens; 80% repetition in greedy |
| 08 | Perplexity | 08_perplexity.py | monotonic scaling; noise is easier than shuffled text |
| 09 | GPT-1 → GPT-2 | 06 and 08 | PPL 46 → 21.7 at the same size |
| 10 | RoBERTa and MLM | 04, section 3 | the encoder changes everything when you touch the end |
| 11 | Encoder vs decoder | 04, section 3 | the same proof, read from both sides |
| 12 | The detector | 09_detector.py | modern LLM passes as human at 99.9% |
| 13 | Original code | 10_original_code.py | the first 25 BPE merges; JS = Python |
| 14 | Serving models | 11_api.py | the generate→detect cycle; the semantic-search failure |
GPT-2\ ├── .venv\ Python 3.14 + torch 2.14 (CPU) + transformers 5 ├── models\hf\ the 7 models, 13.2 GB in safetensors ├── repos\ │ ├── gpt-2\ original TensorFlow code (for READING) │ ├── GPT-3-Encoder\ JS tokenizer + vocab.bpe + encoder.json │ └── gpt-3\ 175B samples and corpus statistics ├── lab\ │ ├── common.py shared module — loads and configures everything │ └── 01..11_*.py the experiments ├── server\app.py API compatible with TGI and TEI ├── tools\ │ ├── style.css typography of the chapters │ ├── generate_pdfs.py HTML -> PDF (headless Chrome + page numbering) │ ├── download_models.py model download │ └── verify.py smoke test of the 7 models ├── src\conceitos_gpt-1-gpt-2\ HTML source of the 16 chapters (eng\ = English) ├── src\conceitos_antevisao\ the theory of the ELLM (Antivision experiment) ├── pdfs\gpt-1-gpt-2\ << the finished chapters; pdfs\antevisao\ those of the project └── out\ experiment outputs
# check that the 7 models load .venv\Scripts\python.exe tools\verify.py # regenerate all PDFs after editing an HTML .venv\Scripts\python.exe tools\generate_pdfs.py # regenerate just one .venv\Scripts\python.exe tools\generate_pdfs.py 07
All scripts use short aliases, defined in lab/common.py:
| Alias | Hugging Face repository | RAM |
|---|---|---|
gpt1 | openai-community/openai-gpt | 0.4 GB |
gpt2 | openai-community/gpt2 | 0.5 GB |
gpt2-medium | openai-community/gpt2-medium | 1.3 GB |
gpt2-large | openai-community/gpt2-large | 2.9 GB |
gpt2-xl | openai-community/gpt2-xl | 5.8 GB |
det-base | openai-community/roberta-base-openai-detector | 0.5 GB |
det-large | openai-community/roberta-large-openai-detector | 1.4 GB |
# to write your own experiments import common tok, mod = common.carregar_gerador("gpt2-medium") tok, mod, rot = comum.carregar_detector("det-base") tok, mod = comum.carregar_base("gpt2", atencoes=True)
common.py points the cache to models\hf, turns on offline mode (nothing goes to the network), forces UTF-8 on the Windows console, disables gradients and fixes the missing labels of det-large.
| Measurement | Result | Lab |
|---|---|---|
| Cost of Portuguese vs English (tokens/word) | 1.86 vs 1.14 — 1.63× | 01 |
Neighbors of " Brazil" in wte | Argentina, Portugal, Chile, Bolivia | 02 |
| Softmax entropy without √ | 0.022 (saturated) vs 1.17 | 03 |
| Causality: effect of the future on the past | 0.00e+00 in GPT-2; ~3e−01 in RoBERTa | 04 |
| Gradient at the 1st of 40 layers | Pre-LN 1.5 million times larger | 05 |
| KV cache gain | 42.2 vs 25.0 tokens/s | 04 |
| Parameter-count formula | 0.0% error across the 5 models | 06 |
In-context learning: P(" Paris") in gpt2 | 0.032 → 0.385 with 3 examples | 06 |
| Top-p nucleus ( | from 1 to 5,548 tokens | 07 |
| 4-gram repetition, greedy | 80% (0% in the other strategies) | 07 |
| Perplexity GPT-1 → GPT-2 XL | 46.07 → 21.70 → 16.04 → 14.30 → 12.93 | 08 |
| PPL: noise vs shuffled text | 469 vs 3,874 (noise is easier) | 08 |
| Detector against GPT-2 | P(human) = 0.0002 — works | 09 |
| Detector against a 2026 LLM | P(human) = 0.9993 — total failure | 09 |
| Detector on formal human text | regulation: 0.034 — false positive | 09 |
| OpenAI's JS tokenizer vs Python | identical IDs | 10 |
| Semantic search with the detector | similarities all at +0.99 — useless | 11 |
| Symptom | Cause and fix |
|---|---|
UnicodeEncodeError with \u0120 | console in cp1252. Always run through the scripts in lab\ — common.py already forces UTF-8. If you write your own, import comum on the first line. |
| Running out of memory in lab 06 | use rapido mode, which skips the XL. |
ConnectionRefused in lab 11 | the server is not up. Open another terminal and run server\app.py. |
Warning "pooler.dense.weight UNEXPECTED" | harmless. It is a leftover from RoBERTa's pre-training; the classification head reads the <s> directly (chapter 12). |
Warning "attn.bias UNEXPECTED" in GPT-1 | harmless. It is the causal mask, which transformers recreates instead of loading from the weights. |
| Model trying to download something | common.py sets HF_HUB_OFFLINE=1. If something tries to reach the network, it is a model outside the catalog. |
You are done. Four natural paths, in order of effort:
roberta-base, a labeled dataset of your own, and repeat the process from chapter 12. It is the most profitable practical skill in this course.transformers, you have truly understood. Andrej Karpathy's nanoGPT is a good reference for this step — and now you can read all of it.qwen3:4b and qwen3:8b installed. Run the same perplexity and decoding tests on them and see what seven years changed — and what did not (the architecture is still the same).BAAI/bge-small-en, intfloat/e5-small) and redo section 4 — this time working.One line separates the two families. masked_fill(futuro, -inf). Everything else — the training objective, the output format, being able to cache or not, generating or understanding — is a consequence.
Measure distributions, not anecdotes. gpt2-large "got a question wrong" and seemed worse than medium. Perplexity, over real text, showed scale behaving regularly. A sample of size 1 is not evidence.
A model only knows what it has seen. The detector works very well on GPT-2 text and fails on 2026 text — and, worse, confident in both cases. Outside the training distribution, a model's confidence means nothing.
The primary sources for the concepts in this chapter. The numbers in the text were measured in the lab; the ideas come from here.
Technical terms here carry their machine-learning meaning. The course glossary shows that meaning next to the others the same words have in IT.
End of the course. The scripts are still there — change the prompts, break things, measure again.
That is how every number in these chapters came to be.