Salta el contingut

1.2 Arquitectura Transformer i LLM Fundacionals

El paper que ho va canviar tot

"Attention Is All You Need" — Vaswani et al., Google Brain, 2017.


🏗️ L'Arquitectura Transformer

Paral·lelisme Total

Tots els tokens es processen simultàniament. Aprofita al màxim les GPUs modernes.

👀

Self-Attention

Cada token pot "mirar" directament qualsevol altre token. Capta dependències globals.

📐

Positional Encoding

Informació de posició explícita per cada token, ja que no hi ha recurrència.


🔬 Self-Attention: La Intuïció

La pregunta clau: "Quan proceso la paraula X, quines altres paraules del context necessito mirar?"

import numpy as np
import math

def scaled_dot_product_attention(Q, K, V):
    """
    Q (Query)  — "Què estic buscant?"       [seq_len, d_k]
    K (Key)    — "Quin contingut ofereixo?" [seq_len, d_k]
    V (Value)  — "Quina informació dono?"   [seq_len, d_v]
    """
    d_k = Q.shape[-1]

    # Similitud entre cada parell de tokens
    scores = np.matmul(Q, K.T) / math.sqrt(d_k)   # [seq, seq]

    # Convertir a distribució de probabilitat
    exp_s = np.exp(scores - scores.max(axis=-1, keepdims=True))
    attention = exp_s / exp_s.sum(axis=-1, keepdims=True)   # [seq, seq]

    # Suma ponderada de valors
    return np.matmul(attention, V), attention                # [seq, d_v]

Exemple Visual: "El gat seu al coixí"

         El    gat   seu    al   coixí
El     [0.50, 0.30, 0.05, 0.05, 0.10]  → "El" posa atenció en "gat"
gat    [0.10, 0.60, 0.15, 0.05, 0.10]  → "gat" auto-atenció alta
seu    [0.05, 0.40, 0.30, 0.10, 0.15]  → "seu" mira "gat" (qui seu?)
al     [0.10, 0.05, 0.10, 0.60, 0.15]  → preposició: auto-atenció
coixí  [0.05, 0.10, 0.15, 0.20, 0.50]  → objecte: auto-atenció

Multi-Head Attention: en lloc d'un sol mecanisme, el Transformer en té 8 o 16 en paral·lel. Cada cap aprèn aspectes diferents: sintaxi, semàntica, co-referència, temporalitat...


🧬 Genealogia dels LLM Moderns

graph TD
    A["Transformer (2017, Google)"] --> B["BERT (2018, Google)<br/>Encoder-only"]
    A --> C["GPT-1 (2018, OpenAI)<br/>Decoder-only"]
    C --> F["GPT-2 (2019)"] --> G["GPT-3 175B (2020)"]
    G --> H["InstructGPT + RLHF"] --> I["ChatGPT (Nov 2022)"]
    I --> J["GPT-4 (2023)"] --> K["GPT-4o (2024)"]
    K --> K2["o1 / o3 (2024-2025)<br/>Raonament extès"]
    K2 --> K3["GPT-4.5 / o4-mini (2025)"]

    A --> O["LLaMA 1 (2023, Meta)"] --> P["LLaMA 2"] --> Q["LLaMA 3.1 (2024)"]
    Q --> Q2["LLaMA 3.3 / 4 (2025)"]

    A --> R["Claude 1 (2023)"] --> S["Claude 2 / 2.1"]
    S --> S2["Claude 3: Haiku · Sonnet · Opus (2024)"]
    S2 --> T["Claude 3.5 Sonnet / Haiku (2024)"]
    T --> T2["Claude 4: Sonnet 4.6 · Opus 4.6 (2025)"]
    T2 --> T3["Claude Haiku 4.5 (2025)"]

    A --> U["Mistral 7B (2023)"] --> V["Mixtral 8x7B (MoE)"]
    V --> V2["Mistral Large / Codestral (2024-2025)"]

🔀 Encoder-only, Decoder-only i Encoder-Decoder

El diagrama anterior menciona aquests termes. Aquí els expliquem.

El Transformer original tenia dues meitats: un encoder (llegeix i entén) i un decoder (genera la sortida). Els models moderns n'han triat una o les dues, depenent de la tasca:

Encoder-only (models de comprensió)

L'encoder processa tota la seqüència en ambdues direccions (cada token "veu" els tokens anteriors i posteriors). Ideal per entendre el significat global d'un text.

Text: "El [MASK] menja el peix"
       ←←←← tots els tokens es veuen entre ells ←←←←
       →→→→ en ambdues direccions simultàniament →→→→

Sortida: representació vectorial de cada token (no genera text)

Usat per: classificació de text, anàlisi de sentiment, detecció d'entitats, cerca semàntica (embeddings).

Exemples: BERT, RoBERTa, DistilBERT.


Decoder-only (models generatius)

El decoder processa els tokens d'esquerra a dreta (autoregressive): cada token només "veu" els anteriors, mai els futurs. Perfecte per generar text de forma natural.

Entrada:  "El gat"
Token 3:  "El gat" → prediu "menja"    (veu token 1, 2)
Token 4:  "El gat menja" → prediu "el" (veu token 1, 2, 3)
Token 5:  "El gat menja el" → prediu "peix"
...

Cada pas genera un nou token, i s'afegeix a l'entrada per generar el següent. Per això aquests models són bons escrivint, però no "veuen" el que ve després.

Usat per: generació de text, xat, escriptura de codi, agents.

Exemples: GPT-4, Claude, Llama, Mistral, Gemini.


Encoder-Decoder (models de transformació)

Combinen les dues meitats: l'encoder llegeix i entén el text d'entrada, i el decoder en genera un de nou. Útil quan la sortida és una transformació de l'entrada.

Entrada (encoder): "The cat eats fish"  ← entén la frase sencera
Sortida (decoder): "El gat menja el peix"  ← genera token a token

Usat per: traducció automàtica, resum de textos, resposta a preguntes amb context.

Exemples: T5, BART, mT5.


Resum visual

Encoder-only Decoder-only Encoder-Decoder
Direcció de l'atenció Bidireccional Esquerra → dreta Bidirec. + Esq.→dreta
Genera text? No
Millor per a... Entendre / classificar Generar / xatejar Traduir / resumir
Exemples BERT, RoBERTa GPT, Claude, Llama T5, BART
Usat en agents? Com a eina d'embedding Sí (el LLM central) Ocasionalment

Per què els agents usen decoder-only?

Els agents necessiten generar text (raonament, respostes, crides a eines). Els models decoder-only com GPT-4 o Claude ho fan de forma natural. Els models encoder-only com BERT s'usen com a eines auxiliars (p.ex., per convertir documents en vectors per al sistema RAG).


🔄 Les Tres Fases d'Entrenament

Fase 1: Pre-training

# Objectiu: predir el token següent (Causal LM)
# "El gat menja el" → [peix, menjar, gos, gat...]
# Dataset: CommonCrawl + Wikipedia + llibres + GitHub ≈ bilions de tokens
# Cost GPT-3: ~4.6M$ | GPT-4 estimat: ~100M$

for batch in dataset:   # ~300 bilions de tokens (GPT-3)
    logits = model(batch.input_tokens)
    loss = cross_entropy(logits, batch.next_tokens)
    loss.backward()
    optimizer.step()

Fase 2: Supervised Fine-Tuning (SFT)

# Dataset: ~13,000 parells (instrucció, resposta ideal) escrits per humans
dataset_sft = [
    {"instruccio": "Escriu un poema sobre la tardor",
     "resposta":   "Les fulles cauen lentament, silencioses..."},
    # ...
]
# El model aprèn a SEGUIR INSTRUCCIONS

Fase 3: RLHF

1. Model genera 3-4 respostes per cada pregunta
2. Humans les ordenen per qualitat: A > B > C
3. Reward Model aprèn a predir preferències humanes
4. PPO optimitza el model per maximitzar el reward
→ Resultat: respostes útils, segures i honestes

📊 Propietaris vs Open-Source

Criteri Propietari (GPT-4o, Claude) Open-Source (Llama, Mistral)
Rendiment Superior en tasques complexes Competitiu a 70B+ paràmetres
Cost Per token: $0.002–$0.06/1K Infraestructura pròpia / Ollama gratuït
Privacitat Dades surten al núvol Execució local, dades privades
Customització Fine-tuning limitat via API Fine-tuning complet amb les teves dades
En aquest curs gpt-4o-mini (pràctiques), gpt-4o (final) Llama 3.1 via Ollama (opció alternativa)

Usar Llama 3.1 localment (Ollama)

# Instal·lar Ollama — https://ollama.ai
curl -fsSL https://ollama.ai/install.sh | sh

# Descarregar Llama 3.1 8B (~5 GB)
ollama pull llama3.1:8b
ollama serve        # Servidor local: http://localhost:11434
# LangChain amb Ollama — mateixa interfície que OpenAI!
from langchain_ollama import ChatOllama

llm = ChatOllama(model="llama3.1:8b", temperature=0)
print(llm.invoke("Explica en 2 frases qué és un LLM.").content)

✅ Activitats

Exercici 1.2.1 — Cost d'un LLM

Usa la calculadora de preus d'OpenAI per estimar el cost de: 1. Processar 1,000 pàgines PDF (~500 tokens/pàgina) amb gpt-4o-mini 2. Generar 10,000 respostes curtes (~200 tokens) amb gpt-4o 3. Comparar amb el cost de Llama 3.1 local (considera ~0.20€/hora de CPU)

Exercici 1.2.2 — Tokenització

Usa el Tokenizer d'OpenAI: 1. Quants tokens té la frase "El gat seu al coixí" en català vs anglès? 2. Per qué el català sol consumir més tokens per paraula que l'anglès? 3. Quin impacte té això en el cost d'una aplicació multilingüe?


📚 Referències