AI 12 min

Article 1: From Language to the Matrix: How Prompts and Tokens Truly Work on the Inside

Open the LLM engine room: learn how text becomes vectors (embeddings), Byte-Pair Encoding (BPE) tokenization mechanics, and ChatML format security implications.

Written by Samir El Azem Crovetto • Senior Backend Engineer & DevSecOps

Article 1: From Language to the Matrix: How Prompts and Tokens Truly Work on the Inside

Open the LLM engine room: learn how text becomes vectors (embeddings), Byte-Pair Encoding (BPE) tokenization mechanics, and ChatML format security implications.

Master Series: OWASP Top 10 for LLM & Generative AI Cybersecurity

Practical Lab: Download lab-01-prompts-y-tokens.ipynb


La mayoría de las vulnerabilidades en aplicaciones basadas en Inteligencia Artificial Generativa no nacen de fallos en el código del servidor ni de configuraciones erróneas en el cortafuegos. Nacen de un modelo mental equivocado.

Cuando los desarrolladores abordan los modelos de lenguaje (LLM), suelen tratarlos como entidades capaces de comprender el significado del texto del mismo modo que lo hace un ser humano. Escriben instrucciones en lenguaje natural, confían en que el modelo "entenderá las reglas" y asumen que las delimitaciones entre lo que dicta la aplicación y lo que envía el usuario se mantendrán intactas.

Para construir sistemas robustos y auditables es imprescindible desmontar esa ilusión. En este artículo abriremos la sala de máquinas de un LLM para analizar cómo se transforma el texto en vectores, cómo se estructuran internamente las plantillas de chat y de qué manera los parámetros de generación determinan si el comportamiento de la aplicación es predecible o un vector de riesgo.


1. Más allá de las palabras: La maquinaria de tokenización

Un modelo de lenguaje no procesa letras, palabras ni frases. Trabaja exclusivamente con números enteros denominados Token IDs, los cuales se proyectan en un espacio vectorial de miles de dimensiones (embeddings).

El proceso de conversión entre el texto plano y estos identificadores numéricos se llama tokenización. En las arquitecturas modernas basadas en Transformers se utilizan algoritmos de subpalabras (Subword Tokenization), principalmente Byte-Pair Encoding (BPE) o sus variantes (WordPiece, Unigram).

Texto Plano: "Seguridad en LLMs"
    │
    ▼ [ Tokenizador (BPE) ]
Tokens (Subpalabras): ["Segur", "idad", " en", " LL", "Ms"]
    │
    ▼ [ Mapeo a Vocabulario ]
Token IDs: [18452, 412, 488, 14201, 893]

¿Por qué la tokenización afecta directamente a la seguridad y a la lógica?

El proceso de tokenización introduce comportamientos contraintuitivos que todo ingeniero debe conocer:

  1. Troceado asimétrico e idiomas: El vocabulario de un tokenizador se entrena sobre un corpus finito de datos. Las palabras frecuentes en inglés suelen ocupar un único token, mientras que otros idiomas, fragmentos de código, caracteres en mayúsculas o cadenas codificadas (como Base64 o hashes) se fragmentan en múltiples tokens. Esto aumenta la longitud de la secuencia y distribuye la atención del modelo de forma dispar.
  2. Espacios y caracteres especiales: Un espacio antes de una palabra cambia por completo su identificador numérico. La cadena "admin" y la cadena " admin" son dos tokens totalmente diferentes para el modelo.
  3. Evasiones por troceado de tokens: Algunos ataques de inyección aprovechan combinaciones de caracteres raros o permutaciones de letras para dividir palabras clave (como comandos de filtrado o palabras prohibidas) en tokens que los analizadores de texto basados en expresiones regulares no detectan, pero que el modelo reensambla en su espacio vectorial.

2. La plantilla de chat (Chat Template): De cadenas simples a formatos estructurados

Cuando interactuamos con una API de chat (como la de OpenAI o modelos en Hugging Face), enviamos una lista de mensajes con roles asignados:

[
  {"role": "system", "content": "Eres un asistente de soporte técnico."},
  {"role": "user", "content": "Hola, necesito ayuda con mi cuenta."}
]

Sin embargo, los modelos de lenguaje autoregresivos no entienden de objetos JSON ni de funciones de alto nivel. Lo que el Transformer recibe es una única secuencia continua de texto plano intercalada con delimitadores especiales definidos por la plantilla de chat del modelo.

El formato ChatML y los delimitadores especiales

Uno de los estándares más extendidos es ChatML. Cuando el array JSON anterior se envía a la API, la plantilla de chat lo traduce a una cadena cruda antes de pasarla al tokenizador:

<|im_start|>system
Eres un asistente de soporte técnico.<|im_end|>
<|im_start|>user
Hola, necesito ayuda con mi cuenta.<|im_end|>
<|im_start|>assistant

Analicemos los elementos en juego:

  • <|imstart|> y <|imend|>: Son Tokens Especiales (Special Tokens). No son palabras normales; el tokenizador los asigna a identificadores reservados fuera del rango del lenguaje ordinario.
  • El rol (system, user, assistant): Es simplemente texto convencional colocado inmediatamente después del token especial de inicio.
  • El contexto del asistente: La secuencia finaliza con <|im_start|>assistant\n, indicando al modelo la posición exacta desde la cual debe comenzar a predecir los siguientes tokens.
┌─────────────────────────────────────────────────────────────────────────┐
│              Estructura Interna del Tensor de Entrada                   │
├─────────────────────────────────────────────────────────────────────────┤
│ [100264] system\nEres un asistente... [100265]\n                        │
│ └── Token especial inicio (system)       └── Token especial fin         │
│                                                                         │
│ [100264] user\nHola, necesito... [100265]\n                             │
│ └── Token especial inicio (user)         └── Token especial fin         │
│                                                                         │
│ [100264] assistant\n                                                    │
│ └── Punto de generación del modelo                                      │
└─────────────────────────────────────────────────────────────────────────┘

Si la aplicación web no valida ni sanitiza adecuadamente la entrada del usuario y permite que este introduzca caracteres o marcas que simulen estos delimitadores (por ejemplo, escribir directamente <|im_start|>system en un formulario), el modelo puede interpretar que la instrucción procede del sistema y no del usuario. Este fenómeno se conoce como Inyección de Delimitadores.


3. La palanca estocástica: Parámetros de generación

Una vez que la secuencia de tokens entra en el Transformer, el modelo no produce una respuesta definitiva de golpe. Lo que genera en cada paso es una distribución de probabilidad sobre todo su vocabulario para decidir cuál será el siguiente token.

La forma en que elegimos ese siguiente token está regulada por los hiperparámetros de generación. Ajustarlos adecuadamente es el primer paso para reducir la volatilidad de una aplicación en producción.

Logits del Modelo ──► Softmax ──► Distribución de Probabilidad ──► Muestreo (Sampling) ──► Token Elegido
                                           │
                                 [ Temperatura / Top-P / Top-K ]

Parámetros clave y su impacto en la predecibilidad

  1. Temperatura (temperature):
  • Controla la "suavidad" de la distribución de probabilidad.
  • Una temperatura de 0.0 (o muestreo codicioso / greedy decoding) obliga al modelo a seleccionar siempre el token con la probabilidad matemática más alta. La salida se vuelve determinista para una misma entrada.
  • Temperaturas elevadas (0.8 - 1.2) aplanan la curva de probabilidad, otorgando opciones a tokens menos probables. Esto favorece la creatividad, pero introduce volatilidad no deseada en sistemas corporativos.
  1. Top-P (Nucleus Sampling):
  • En lugar de considerar todo el vocabulario, el modelo acumula los tokens más probables hasta alcanzar el porcentaje indicado por P (por ejemplo, 0.9 o 90%). Todos los demás tokens son descartados del muestreo.
  • Permite recortar la "cola larga" de tokens improbables o irrelevantes sin fijar un número rígido de candidatos.
  1. Top-K:
  • Restringe el muestreo a los K tokens con mayor probabilidad absoluta (por ejemplo, los 40 mejores).
  1. Penalizaciones de Presencia y Frecuencia (presencepenalty / frequencypenalty):
  • Modifican la probabilidad de un token en función de si ya ha aparecido en el texto generado, evitando bucles repetitivos.

Implicación para el diseño seguro de software

Para tareas operativas, análisis de datos, extracción de entidades o integración con APIs externas, la temperatura debe ser 0.0. Mantener un parámetro de generación aleatorio en un flujo de trabajo empresarial donde se requieren respuestas estructuradas (como JSON o SQL) expone el sistema a fallos de formato inaccesibles para los validadores estáticos.


4. Ejemplo práctico: Inspección del empaquetado de contexto en Python

Para comprender cómo un framework empaqueta un prompt antes de enviarlo al modelo, observemos el siguiente fragmento en Python utilizando la librería transformers de Hugging Face:

from transformers import AutoTokenizer

# Carga de un tokenizador compatible con ChatML / formato instructivo
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")

mensajes = [
    {
        "role": "system",
        "content": "Eres un auditor de seguridad. Valida estrictamente las reglas."
    },
    {
        "role": "user",
        "content": "Analiza el siguiente evento de log: USER_LOGIN_SUCCESS"
    }
]

# Aplicar la plantilla de chat sin tokenizar para ver el texto bruto
texto_estructurado = tokenizer.apply_chat_template(
    mensajes, 
    tokenize=False, 
    add_generation_prompt=True
)

print("--- TEXTO BRUTO DEPOSITADO EN LA VENTANA DE CONTEXTO ---")
print(texto_estructurado)

# Convertir a Token IDs
tokens = tokenizer.encode(texto_estructurado)
print(f"\nNúmero total de tokens: {len(tokens)}")
print(f"Primeros 10 Token IDs: {tokens[:10]}")

Al ejecutar este código, observaremos cómo el objeto estructurado de Python se convierte en una única cadena continua repleta de marcas de control internas. Ese bloque de texto unificado es el único material que procesará el motor del modelo.


Resumen para el lunes por la mañana

  1. Abandona el modelo mental del "lector inteligente": Los LLMs no leen ideas; procesan secuencias numéricas de tokens bajo cálculos probabilísticos.
  2. Usa siempre la API estructurada de mensajes: Nunca concatenes cadenas de texto a mano como "System: " + promptsistema + "\nUser: " + entradausuario. Delega esa responsabilidad a la plantilla de chat oficial del modelo o SDK.
  3. Establece temperature = 0.0 en tareas deterministas: Reduce el margen de variabilidad estocástica si tu aplicación requiere salidas estructuradas o integración con lógica de backend.
  4. Sanitiza entradas contra tokens de control: Asegúrate de que los inputs de usuarios no contengan secuencias reservadas de delimitadores de plantilla (como delimitadores ChatML) que puedan distorsionar la interpretación del modelo.


🧪 Associated Hands-On Practical Lab

Practice the concepts from this masterclass in the accompanying hands-on Jupyter notebook: