Phase 10 - Lesson 01

Tokenizers: BPE, WordPiece, SentencePiece

This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.

Su LLM no lee inglés. Lee enteros. El tokenizador decide si esos enteros llevan significado o lo desperdician.

Tipo: Build Lenguajes: Python Prerrequisitos: Fase 05 (NLP Foundations) Tiempo: ~90 minutos

Objetivos de Aprendizaje

  • Implementar los algoritmos de tokenización BPE, WordPiece y Unigram desde cero y comparar sus estrategias de fusión
  • Explicar cómo el tamaño del vocabulario afecta la eficiencia del modelo: si es demasiado pequeño crea secuencias largas, si es demasiado grande desperdicia parámetros de embedding
  • Analizar los artefactos de tokenización en diferentes idiomas y código, identificando dónde fallan los tokenizadores específicos
  • Usar las bibliotecas tiktoken y sentencepiece para tokenizar texto e inspeccionar los IDs de token resultantes

El Problema

Su LLM no lee inglés. No lee ningún idioma. Lee números.

La brecha entre "Hello, world!" y [15496, 11, 995, 0] es el tokenizador. Cada palabra, cada espacio, cada signo de puntuación debe convertirse en un entero antes de que un modelo pueda procesarlo. Esta conversión no es neutra. Introduce suposiciones en el modelo que no se pueden deshacer más tarde.

Si se equivoca en esto, su modelo desperdiciará capacidad codificando palabras comunes con múltiples tokens. "unfortunately" se convierte en cuatro tokens en lugar de uno. Su ventana de contexto de 128K acaba de reducirse en un 75% para textos cargados de palabras de muchas sílabas. Si lo hace bien, la misma ventana de contexto contendrá el doble de significado. La diferencia entre "este modelo maneja bien el código" y "este modelo se ahoga con Python" a menudo se reduce a cómo se entrenó el tokenizador.

Cada llamada a la API que realiza a GPT-4 o Claude se cobra por token. Cada token que genera su modelo cuesta cómputo. Cuantos menos tokens se requieran para representar una salida, más rápida será la inferencia de extremo a extremo. La tokenización no es preprocesamiento. Es arquitectura.

El Concepto

Tres Enfoques Que Fallaron (y Uno Que Ganó)

Hay tres formas obvias de convertir texto en números. Dos de ellas no funcionan a escala.

La tokenización a nivel de palabra divide el texto en espacios y puntuación. "The cat sat" se convierte en ["The", "cat", "sat"]. Simple. Pero ¿qué pasa con "tokenization"? ¿O "GPT-4o"? ¿O una palabra compuesta en alemán como "Geschwindigkeitsbegrenzung"? El nivel de palabra requiere un vocabulario masivo para cubrir cada palabra en cada idioma. Si se le pasa una palabra, obtendrá el temido token [UNK], la forma en que el modelo dice "no tengo idea de qué es esto". Solo el inglés tiene más de un millón de formas de palabras. Agregue código, URLs, notación científica y otros 100 idiomas, y necesitará un vocabulario infinito.

La tokenización a nivel de caracteres va en la dirección opuesta. "hello" se convierte en ["h", "e", "l", "l", "o"]. El vocabulario es minúsculo (unas pocas cientos de caracteres). Nunca hay tokens desconocidos. Pero las secuencias se vuelven extremadamente largas. Una oración que tendría 10 tokens a nivel de palabra se convierte en 50 tokens a nivel de caracteres. El modelo debe aprender que "t", "h", "e" juntos significan "the", consumiendo capacidad de atención en algo que un humano aprende a los tres años de edad.

La tokenización de subpalabras encuentra el punto ideal. Las palabras comunes permanecen enteras: "the" es un solo token. Las palabras raras se descomponen en piezas significativas: "unhappiness" se convierte en ["un", "happi", "ness"]. El vocabulario se mantiene manejable (de 30K a 128K tokens). Las secuencias siguen siendo cortas. Los tokens desconocidos prácticamente desaparecen porque cualquier palabra se puede construir a partir de piezas de subpalabras.

Cada LLM moderno utiliza tokenización de subpalabras. GPT-2, GPT-4, BERT, Llama 3, Claude, todos ellos. La pregunta es qué algoritmo usar.

graph TD
    A["Texto: 'unhappiness'"] --> B{"Estrategia de Tokenización"}
    B -->|A nivel de palabra| C["['unhappiness']\n1 token si está en vocab\n[UNK] si no"]
    B -->|A nivel de caracteres| D["['u','n','h','a','p','p','i','n','e','s','s']\n11 tokens"]
    B -->|BPE de subpalabras| E["['un','happi','ness']\n3 tokens"]

    style C fill:#ff6b6b,color:#fff
    style D fill:#ffa500,color:#fff
    style E fill:#51cf66,color:#fff

BPE: Byte Pair Encoding

BPE es un algoritmo de compresión codicioso (greedy) adaptado para la tokenización. La idea es lo suficientemente simple como para caber en una tarjeta de notas.

Comience con caracteres individuales. Cuente cada par adyacente en el corpus de entrenamiento. Fusione el par más frecuente en un nuevo token. Repita hasta alcanzar el tamaño de vocabulario deseado.

Aquí está BPE ejecutándose en un corpus diminuto con las palabras "lower", "lowest" y "newest":

Corpus (with word frequencies):
  "lower"  x5
  "lowest" x2
  "newest" x6

Step 0 -- Start with characters:
  l o w e r       (x5)
  l o w e s t     (x2)
  n e w e s t     (x6)

Step 1 -- Count adjacent pairs:
  (e,s): 8    (s,t): 8    (l,o): 7    (o,w): 7
  (w,e): 13   (e,r): 5    (n,e): 6    ...

Step 2 -- Merge most frequent pair (w,e) -> "we":
  l o we r        (x5)
  l o we s t      (x2)
  n e we s t      (x6)

Step 3 -- Recount and merge (e,s) -> "es":
  l o we r        (x5)
  l o we s t      (x2)    <- 'es' only forms from 'e'+'s', not 'we'+'s'
  n e we s t      (x6)    <- wait, the 'e' before 'we' and 's' after 'we'

Actually tracking this precisely:
  After "we" merge, remaining pairs:
  (l,o): 7   (o,we): 7   (we,r): 5   (we,s): 8
  (s,t): 8   (n,e): 6    (e,we): 6

Step 3 -- Merge (we,s) -> "wes" or (s,t) -> "st" (tied at 8, pick first):
  Merge (we,s) -> "wes":
  l o we r        (x5)
  l o wes t       (x2)
  n e wes t       (x6)

Step 4 -- Merge (wes,t) -> "west":
  l o we r        (x5)
  l o west        (x2)
  n e west        (x6)

...continue until target vocab size reached.

La tabla de fusiones (merge table) es el tokenizador. Para codificar texto nuevo, aplique las fusiones en el orden en que se aprendieron. El corpus de entrenamiento determina qué fusiones existen, y esa elección define permanentemente lo que ve el modelo.

graph LR
    subgraph Training["Bucle de Entrenamiento BPE"]
        direction TB
        T1["Inicio: vocabulario de caracteres"] --> T2["Contar todos los pares adyacentes"]
        T2 --> T3["Fusionar el par más frecuente"]
        T3 --> T4["Agregar token fusionado al vocabulario"]
        T4 --> T5{"¿Alcanzó el tamaño\nde vocabulario objetivo?"}
        T5 -->|No| T2
        T5 -->|Sí| T6["Listo: guardar tabla de fusiones"]
    end

Byte-Level BPE (GPT-2, GPT-3, GPT-4)

El BPE estándar funciona con caracteres Unicode. El BPE a nivel de bytes (Byte-level BPE) opera sobre bytes crudos (0-255). Esto proporciona un vocabulario base de exactamente 256, maneja cualquier idioma o codificación y nunca produce un token desconocido.

GPT-2 introdujo este enfoque. El vocabulario base cubre cada byte posible. Las fusiones de BPE se construyen sobre eso. La biblioteca tiktoken de OpenAI implementa BPE a nivel de bytes con los siguientes tamaños de vocabulario:

  • GPT-2: 50.257 tokens
  • GPT-3.5/GPT-4: ~100.256 tokens (codificación cl100k_base)
  • GPT-4o: 200.019 tokens (codificación o200k_base)

WordPiece (BERT)

WordPiece parece similar a BPE pero elige las fusiones de manera diferente. En lugar de la frecuencia bruta, maximiza la verosimilitud de los datos de entrenamiento:

BPE merge criterion:      count(A, B)
WordPiece merge criterion: count(AB) / (count(A) * count(B))

BPE pregunta: "¿Qué par aparece con más frecuencia?" WordPiece pregunta: "¿Qué par aparece junto con más frecuencia de lo esperado por azar?" Esta sutil diferencia produce vocabularios diferentes. WordPiece favorece las fusiones donde la coocurrencia es sorprendente, no solo frecuente.

WordPiece también utiliza un prefijo "##" para subpalabras de continuación:

"unhappiness" -> ["un", "##happi", "##ness"]
"embedding"   -> ["em", "##bed", "##ding"]

El prefijo "##" indica que esta pieza continúa un token anterior. BERT utiliza WordPiece con un vocabulario de 30.522 tokens. Cada variante de BERT (DistilBERT, el tokenizador de RoBERTa es en realidad BPE, pero BERT en sí es WordPiece).

SentencePiece (Llama, T5)

SentencePiece trata la entrada como una secuencia bruta de caracteres Unicode, incluyendo los espacios en blanco. Sin etapa de pretokenización. Sin reglas específicas de idioma sobre los límites de las palabras. Esto lo hace genuinamente agnóstico al idioma: funciona en chino, japonés, tailandés y otros idiomas donde los espacios no separan las palabras.

SentencePiece admite dos algoritmos:

  • Modo BPE: la misma lógica de fusión que el BPE estándar, aplicada a secuencias de caracteres crudos
  • Modo Unigram: comienza con un vocabulario grande y elimina iterativamente los tokens que menos afectan la verosimilitud general. Lo opuesto a BPE: poda en lugar de fusión.

Llama 2 utiliza SentencePiece BPE con un vocabulario de 32.000 tokens. T5 utiliza SentencePiece Unigram con 32.000 tokens. Nota: Llama 3 cambió a un tokenizador BPE a nivel de bytes basado en tiktoken con 128.256 tokens.

Vocabulary Size Tradeoffs

Esta es una decisión de ingeniería real con consecuencias mensurables.

graph LR
    subgraph Small["Vocabulario Pequeño (32K)\nej: BERT, T5"]
        S1["Más tokens por texto"]
        S2["Secuencias más largas"]
        S3["Matriz de embedding más pequeña"]
        S4["Mejor manejo de palabras raras"]
    end
    subgraph Large["Vocabulario Grande (128K+)\nej: Llama 3, GPT-4o"]
        L1["Menos tokens por texto"]
        L2["Secuencias más cortas"]
        L3["Matriz de embedding más grande"]
        L4["Inferencia más rápida"]
    end

Números concretos. Para un vocabulario de 128K con embeddings de 4.096 dimensiones, la matriz de embedding por sí sola tiene 128.000 x 4.096 = 524 millones de parámetros. Para un vocabulario de 32K, tiene 131 millones de parámetros. Esa es una diferencia de 400M de parámetros solo por la elección del tokenizador.

Pero los vocabularios más grandes comprimen el texto de manera más agresiva. El mismo párrafo en inglés que requiere 100 tokens con un vocabulario de 32K podría requerir 70 tokens con un vocabulario de 128K. Eso significa un 30% menos de pasadas hacia adelante (forward passes) durante la generación. Para un modelo que atiende millones de solicitudes, esto representa una reducción directa en el costo de cómputo.

La tendencia está clara: los tamaños de vocabulario están creciendo. GPT-2 usaba 50.257. GPT-4 usa ~100K. Llama 3 usa 128K. GPT-4o usa 200K.

Modelo Tamaño del Vocabulario Tipo de Tokenizador Promedio de Tokens por Palabra en Inglés
BERT 30.522 WordPiece ~1,4
GPT-2 50.257 BPE a nivel de bytes ~1,3
Llama 2 32.000 SentencePiece BPE ~1,4
GPT-4 ~100.256 BPE a nivel de bytes ~1,2
Llama 3 128.256 BPE a nivel de bytes (tiktoken) ~1,1
GPT-4o 200.019 BPE a nivel de bytes ~1,0

El Impuesto Multilingüe

Los tokenizadores entrenados principalmente en inglés son brutales con otros idiomas. El texto en coreano en el tokenizador de GPT-2 promedia de 2 a 3 tokens por palabra. En chino puede ser peor. Esto significa que un usuario coreano tiene efectivamente una ventana de contexto que es la mitad del tamaño de la de un usuario de habla inglesa, pagando el mismo precio por menos densidad de información.

Es por eso que Llama 3 cuadruplicó su vocabulario de 32K a 128K. Más tokens dedicados a escrituras no inglesas significan una compresión más justa entre idiomas.

Build It

Paso 1: Tokenizador a Nivel de Caracteres

Comience en la base. Un tokenizador a nivel de caracteres mapea cada carácter a su punto de código Unicode (code point). No requiere entrenamiento. Sin tokens desconocidos. Solo un mapeo directo.

class CharTokenizer:
    def encode(self, text):
        return [ord(c) for c in text]

    def decode(self, tokens):
        return "".join(chr(t) for t in tokens)

"hello" se convierte en [104, 101, 108, 108, 111]. Cada carácter es su propio token. Esta es la línea base sobre la cual mejoramos.

Paso 2: Tokenizador BPE desde Cero

La implementación real. Entrenamos en bytes crudos (como GPT-2), contamos pares, fusionamos el más frecuente y registramos cada fusión en orden. La tabla de fusiones es el tokenizador.

from collections import Counter

class BPETokenizer:
    def __init__(self):
        self.merges = {}
        self.vocab = {}

    def _get_pairs(self, tokens):
        pairs = Counter()
        for i in range(len(tokens) - 1):
            pairs[(tokens[i], tokens[i + 1])] += 1
        return pairs

    def _merge_pair(self, tokens, pair, new_token):
        merged = []
        i = 0
        while i < len(tokens):
            if i < len(tokens) - 1 and tokens[i] == pair[0] and tokens[i + 1] == pair[1]:
                merged.append(new_token)
                i += 2
            else:
                merged.append(tokens[i])
                i += 1
        return merged

    def train(self, text, num_merges):
        tokens = list(text.encode("utf-8"))
        self.vocab = {i: bytes([i]) for i in range(256)}

        for i in range(num_merges):
            pairs = self._get_pairs(tokens)
            if not pairs:
                break
            best_pair = max(pairs, key=pairs.get)
            new_token = 256 + i
            tokens = self._merge_pair(tokens, best_pair, new_token)
            self.merges[best_pair] = new_token
            self.vocab[new_token] = self.vocab[best_pair[0]] + self.vocab[best_pair[1]]

        return self

    def encode(self, text):
        tokens = list(text.encode("utf-8"))
        for pair, new_token in self.merges.items():
            tokens = self._merge_pair(tokens, pair, new_token)
        return tokens

    def decode(self, tokens):
        byte_sequence = b"".join(self.vocab[t] for t in tokens)
        return byte_sequence.decode("utf-8", errors="replace")

El bucle de entrenamiento es el núcleo de BPE: contar pares, fusionar el ganador, repetir. Cada fusión reduce el recuento total de tokens. Después de num_merges rondas, el vocabulario crece de 256 (bytes base) a 256 + num_merges.

La codificación aplica las fusiones en el orden exacto en que se aprendieron. Esto importa. Si la fusión 1 creó "th" y la fusión 5 creó "the", la codificación debe aplicar la fusión 1 primero para que se pueda formar "the" a partir de "th" + "e" en la fusión 5.

La decodificación es lo inverso: buscar cada ID de token en el vocabulario, concatenar los bytes y decodificar a UTF-8.

Paso 3: Prueba de Ida y Vuelta (Roundtrip) de Codificación y Decodificación

corpus = (
    "The cat sat on the mat. The cat ate the rat. "
    "The dog sat on the log. The dog ate the frog. "
    "Natural language processing is the study of how computers "
    "understand and generate human language. "
    "Tokenization is the first step in any NLP pipeline."
)

tokenizer = BPETokenizer()
tokenizer.train(corpus, num_merges=40)

test_sentences = [
    "The cat sat on the mat.",
    "Natural language processing",
    "tokenization pipeline",
    "unhappiness",
]

for sentence in test_sentences:
    encoded = tokenizer.encode(sentence)
    decoded = tokenizer.decode(encoded)
    raw_bytes = len(sentence.encode("utf-8"))
    ratio = len(encoded) / raw_bytes
    print(f"'{sentence}'")
    print(f"  Tokens: {len(encoded)} (from {raw_bytes} bytes) -- ratio: {ratio:.2f}")
    print(f"  Roundtrip: {'PASS' if decoded == sentence else 'FAIL'}")

La relación de compresión (compression ratio) le indica qué tan efectivo es el tokenizador. Una relación de 0,50 significa que el tokenizador comprimió el texto a la mitad de tokens en comparación con los bytes crudos. Cuanto menor sea, mejor. En el corpus de entrenamiento, la relación será buena. En texto fuera de distribución (out-of-distribution) como "unhappiness" (que no aparece en el corpus), la relación será peor: el tokenizador recurre a la codificación a nivel de caracteres para los patrones no vistos.

Paso 4: Comparar con tiktoken

import tiktoken

enc = tiktoken.get_encoding("cl100k_base")

texts = [
    "The cat sat on the mat.",
    "unhappiness",
    "Hello, world!",
    "def fibonacci(n): return n if n < 2 else fibonacci(n-1) + fibonacci(n-2)",
    "Geschwindigkeitsbegrenzung",
]

for text in texts:
    our_tokens = tokenizer.encode(text)
    tiktoken_tokens = enc.encode(text)
    tiktoken_pieces = [enc.decode([t]) for t in tiktoken_tokens]
    print(f"'{text}'")
    print(f"  Our BPE:   {len(our_tokens)} tokens")
    print(f"  tiktoken:  {len(tiktoken_tokens)} tokens -> {tiktoken_pieces}")

tiktoken utiliza exactamente el mismo algoritmo pero entrenado en cientos de gigabytes de texto con 100.000 fusiones. El algoritmo es idéntico. La diferencia radica en los datos de entrenamiento y el número de fusiones. Su tokenizador entrenado en un párrafo con 40 fusiones no puede competir con las 100K fusiones de tiktoken en un corpus masivo. Pero el mecanismo es el mismo.

Paso 5: Análisis de Vocabulario

def analyze_vocabulary(tokenizer, test_texts):
    total_tokens = 0
    total_chars = 0
    token_usage = Counter()

    for text in test_texts:
        encoded = tokenizer.encode(text)
        total_tokens += len(encoded)
        total_chars += len(text)
        for t in encoded:
            token_usage[t] += 1

    print(f"Vocabulary size: {len(tokenizer.vocab)}")
    print(f"Total tokens across all texts: {total_tokens}")
    print(f"Total characters: {total_chars}")
    print(f"Avg tokens per character: {total_tokens / total_chars:.2f}")

    print(f"\nMost used tokens:")
    for token_id, count in token_usage.most_common(10):
        token_bytes = tokenizer.vocab[token_id]
        display = token_bytes.decode("utf-8", errors="replace")
        print(f"  Token {token_id:4d}: '{display}' (used {count} times)")

    unused = [t for t in tokenizer.vocab if t not in token_usage]
    print(f"\nUnused tokens: {len(unused)} out of {len(tokenizer.vocab)}")

Esto revela la distribución de Zipf en su vocabulario. Dominan unos pocos tokens (espacios, "the", "e"). La mayoría de los tokens rara vez se usan. Los tokenizadores de producción se optimizan para esta distribución: los patrones comunes obtienen IDs de token cortos y los patrones raros obtienen representaciones más largas.

Use It

Su BPE desde cero funciona. Ahora vea cómo son las herramientas de producción.

tiktoken (OpenAI)

import tiktoken

enc = tiktoken.get_encoding("cl100k_base")

text = "Tokenizers convert text to integers"
tokens = enc.encode(text)
print(f"Tokens: {tokens}")
print(f"Pieces: {[enc.decode([t]) for t in tokens]}")
print(f"Roundtrip: {enc.decode(tokens)}")

tiktoken está escrito en Rust con enlaces (bindings) para Python. Codifica millones de tokens por segundo. El mismo algoritmo BPE, con una implementación de fuerza industrial.

Hugging Face tokenizers

from tokenizers import Tokenizer
from tokenizers.models import BPE
from tokenizers.trainers import BpeTrainer
from tokenizers.pre_tokenizers import ByteLevel

tokenizer = Tokenizer(BPE())
tokenizer.pre_tokenizer = ByteLevel()

trainer = BpeTrainer(vocab_size=1000, special_tokens=["<pad>", "<eos>", "<unk>"])
tokenizer.train(["corpus.txt"], trainer)

output = tokenizer.encode("The cat sat on the mat.")
print(f"Tokens: {output.tokens}")
print(f"IDs: {output.ids}")

La biblioteca tokenizers de Hugging Face también se basa en Rust por debajo. Entrena BPE en corpora a escala de gigabytes en segundos. Esto es lo que se usa al entrenar su propio modelo.

Cargar el Tokenizador de Llama

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.1-8B")

text = "Tokenizers are the unsung heroes of LLMs"
tokens = tokenizer.encode(text)
print(f"Token IDs: {tokens}")
print(f"Tokens: {tokenizer.convert_ids_to_tokens(tokens)}")
print(f"Vocab size: {tokenizer.vocab_size}")

multilingual = ["Hello world", "Hola mundo", "Bonjour le monde"]
for text in multilingual:
    ids = tokenizer.encode(text)
    print(f"'{text}' -> {len(ids)} tokens")

El vocabulario de 128K de Llama 3 comprime los textos que no están en inglés significativamente mejor que el vocabulario de 50K de GPT-2. Puede verificarlo usted mismo: codifique la misma oración en varios idiomas y cuente los tokens.

Ship It

Esta lección produce outputs/prompt-tokenizer-analyzer.md, un prompt reutilizable que analiza la eficiencia de la tokenización para cualquier combinación de texto y modelo. Aliméntelo con una muestra de texto y le dirá qué tokenizador de modelo lo maneja mejor.

Ejercicios

  1. Modifique el tokenizador BPE para imprimir el vocabulario en cada paso de fusión. Observe cómo "t" + "h" se convierte en "th", luego "th" + "e" se convierte en "the". Siga la pista de cómo se ensamblan las palabras comunes en inglés pieza por pieza.

  2. Agregue tokens especiales (<pad>, <eos>, <unk>) al tokenizador BPE. Asígneles los IDs 0, 1, 2 y desplace todos los demás tokens en consecuencia. Implemente un paso de pretokenización que divida en espacios en blanco antes de ejecutar BPE.

  3. Implemente el criterio de fusión de WordPiece (relación de verosimilitul en lugar de frecuencia). Entrene tanto BPE como WordPiece en el mismo corpus con el mismo número de fusiones. Compare los vocabularios resultantes: ¿cuál produce subpalabras lingüísticamente más significativas?

  4. Construya un benchmark de eficiencia de tokenizadores multilingües. Tome 10 oraciones en inglés, español, chino, coreano y árabe. Tokenice cada una con tiktoken (cl100k_base) y mida el promedio de tokens por carácter. Cuantifique el "impuesto multilingüe" para cada idioma.

  5. Entrene su tokenizador BPE en un corpus más grande (descargue un artículo de Wikipedia). Ajuste el número de fusiones para lograr una relación de compresión dentro del 10% de tiktoken en ese mismo texto. Esto le obligará a comprender la relación entre el tamaño del corpus, el recuento de fusiones y la calidad de la compresión.

Términos clave

Término Lo que dice la gente Lo que realmente significa
Token "Una palabra" Una unidad en el vocabulario del modelo; puede ser un carácter, una subpalabra, una palabra o un bloque de varias palabras
BPE "Algo de compresión" Codificación por pares de bytes (Byte Pair Encoding): fusiona iterativamente el par de tokens adyacentes más frecuente hasta alcanzar el tamaño de vocabulario objetivo
WordPiece "El tokenizador de BERT" Similar a BPE, pero las fusiones maximizan la relación de verosimilitud count(AB)/(count(A)*count(B)) en lugar de la frecuencia bruta
SentencePiece "Una biblioteca de tokenizadores" Un tokenizador agnóstico al idioma que opera sobre Unicode crudo sin pretokenización, admitiendo los algoritmos BPE y Unigram
Tamaño del vocabulario "Cuántas palabras conoce" El número total de tokens únicos: GPT-2 tiene 50.257, BERT tiene 30.522, Llama 3 tiene 128.256
Fertilidad "No es un término de tokenización" Promedio de tokens por palabra: mide la eficiencia del tokenizador en distintos idiomas (1,0 es perfecto, 3,0 significa que el modelo trabaja tres veces más de lo necesario)
BPE a nivel de bytes "El tokenizador de GPT" BPE que opera sobre bytes crudos (0-255) en lugar de caracteres Unicode, garantizando que no haya tokens desconocidos para ninguna entrada
Tabla de fusiones "El archivo del tokenizador" Lista ordenada de fusiones de pares aprendidas durante el entrenamiento; esto ES el tokenizador, y el orden importa
Pretokenización "División en espacios" Reglas aplicadas antes de la tokenización de subpalabras: división por espacios en blanco, separación de dígitos, manejo de puntuación
Relación de compresión "Qué tan eficiente es el tokenizador" Tokens producidos divididos por los bytes de entrada; un valor menor significa mejor compresión e inferencia más rápida

Lectura Adicional

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).