En Julio de 2026, Anthropic introdujo una nueva técnica de interpretabilidad, las J-lens, para identificar en un LLM lo que en neurociencias se llama el espacio de trabajo (workspace), el conjunto de representaciones internas disponibles para comunicación, razonamiento y modulación. Serían los pensamientos accesibles frente al procesamiento inconsciente.
Consideramos el vector de la corriente residual (residual stream) h en una capa intermedia L y en una posición de token dada. Si realizamos una pequeña perturbación en esa capa, esta se propagará hacia adelante afectando a la capa final del modelo. Mediante una aproximación lineal de primer orden (la derivada multivariable), este cambio se define por la matriz Jacobiana:
La media/esperanza se calcula con respecto a la posición de origen t, a todas las posiciones posteriores t’ dentro del contexto y a un corpus de mil prompts muestreados a partir de una distribución similar a la de preentrenamiento.
Esta matriz de dimensiones (d x d), d la dimensión interna del modelo, mapea cómo se trasladan geométricamente las activaciones de la capa intermedia a la capa final del transformer.
Para saber cómo afecta este cambio a un token específico w del vocabulario V, multiplicamos la matriz Jacobiana por el vector de des-incorporación (unembedding) de ese token. El gradiente del logit de ese token con respecto a la activación intermedia es:
A las filas de esta matriz de dimensiones (voc size x d) nos referimos como los vectores J-lens de la capa L. Cada vector J-lens es una dirección en el espacio del residual stream asociada a un único token del vocabulario del modelo
Aplicar la lente a un vector activación equivale a reemplazar todas las capas subsiguientes por la matriz de lente correspondiente, seguidas de las operaciones habituales de unembedding (aplicando también típicamente, una normalización).
Ordenando los tokens de vocabulario y viendo los top tokens nos da una idea de las palabras que la capa intermedia hace al modelo “pensar” o “decir”. Por ejemplo, pueden estar activos con score alto los conceptos “Francia” y “París”.
Es importante destacar que al proyectar tu vector de activaciones sobre la Jacobiana y la matriz de unembedding, obtienes que tokens están más activos pero no obtienes conceptos multi-token. Si una palabra como “fotosíntesis” se rompe en ["foto", "sín", "tesis"], sus vectores individuales están ligados a la fotografía o a la universidad en el vocabulario general. El Jacobiano por sí solo no te genera un vector unificado para la “fotosíntesis”, sino que tienes que deducirlo tú viendo los fragmentos activos. Por eso, en su artículo, Anthropic, tiene un apartado en su Apéndice con posibles soluciones para extender el J-Space a conceptos multi-token. A.9Extending the Jacobian lens to multi-token concepts
Vamos a ver un ejemplo usando la librería jlens de Anthropic que trae J-lens precalculadas para algunos modelos. Para poder descargar y ejecutar el modelo usamos una GPU RTX pro 4500.
Tomamos un modelo y un tokenizador estándar ya cargados desde Hugging Face (transformers) y los adaptamos a la interfaz interna de la librería jlens. Esto permite que la librería pueda identificar la arquitectura del modelo, extraer sus activaciones internas (del residual stream) y aplicar el vocabulario correcto para decodificar los estados intermedios. También descargamos y cargamos la J-lens precalculada para Qwen3-8B.
import torch
import transformers
import jlens
from huggingface_hub import hf_hub_download
# 1. Cargar el modelo base y el tokenizer desde Hugging Face
model_name = "Qwen/Qwen3-8B"
hf_model = transformers.AutoModelForCausalLM.from_pretrained(
model_name,
dtype=torch.bfloat16
).to("cuda") # o "mps" en Apple Silicon
tokenizer = transformers.AutoTokenizer.from_pretrained(model_name)
# 2. Envolver el modelo para que jlens pueda interceptar las activaciones
model = jlens.from_hf(hf_model, tokenizer)
# 3. Descargar y cargar la lente jacobiana preajustada para Qwen3-8B
lens_path = hf_hub_download(
"dormantx/jacobian-lens-qwen3-8b",
"qwen3_8b_lens.pt"
)
lens = jlens.JacobianLens.load(lens_path)
Ahora definimos el prompt, las capas sobre las que evaluar las proyecciones, aplicamos las J-lens, el logit directo (aplica la matriz de unembedding directamente a la capa) y mostramos el token de vocabulario con mayor score.
# 4. Definir el prompt y las capas de interés
prompt = "Fact: The currency used in the country shaped like a boot is"
layers_to_check = [16, 20, 24, 32, 34] # Capas intermedias donde se espera la diferencia
# 5. Aplicar la J-lens (con transporte jacobiano)
jl_logits, _, _ = lens.apply(
model,
prompt,
positions=[-1], # Última posición del prompt
layers=layers_to_check,
use_jacobian=True,
)
# 6. Aplicar el logit-lens directo (sin Jacobiano, como baseline)
ll_logits, _, _ = lens.apply(
model,
prompt,
positions=[-1],
layers=layers_to_check,
use_jacobian=False,
)
# 7. Mostrar la comparación capa por capa
print("Capa | J-lens (top-1) | Logit-lens directo (top-1)")
print("-----------------------------------------------------")
for layer in layers_to_check:
top_jl_token_id = jl_logits[layer][0].argmax()
top_ll_token_id = ll_logits[layer][0].argmax()
top_jl_word = tokenizer.decode([top_jl_token_id])
top_ll_word = tokenizer.decode([top_ll_token_id])
print(f"L{layer:<3} | {top_jl_word!r:<16} | {top_ll_word!r}")
Vemos el resultado.
Capa | J-lens (top-1) | Logit-lens directo (top-1)
-----------------------------------------------------
L16 | '”?' | '文化传媒'
L20 | ' famous' | '/is'
L24 | ' Italy' | ' Italy'
L32 | '欧元' | ' euro'
L34 | ' Euro' | ' the'
Vemos una capa (L16) donde el logit-lens directo es ruido puro (‘文化传媒’) mientras la J-lens no cruza el idioma. En las capas medias (L20–L24) la J-lens produce contenido semántico. El detalle multilingüe del L32 (chino vs. inglés) ilustra cómo el modelo representa conceptos bilingües y cómo cada método los “verbaliza” de forma distinta. En la capa alta (L34) el logit-lens retrocede a gramática (‘ the’) mientras la J-lens ya tiene la respuesta (‘ Euro’).

Deja una respuesta
Lo siento, debes estar conectado para publicar un comentario.