Memoria latente persistente para agentes LLM de múltiples saltos: cómo un documento de transferencia 6G cierra el arranque en frío del agente

Un recorrido divertido pero real por ILCP para agentes: un compresor β-VAE, un transporte estilo Xn, un proyector MLP cerrado y la irrazonablemente conveniente comprensión de que ya había resuelto exactamente este problema para las transferencias de 6G. El V1 del lado del agente es el cableado; Los recibos de esta publicación son recibos del papel 6G, debidamente etiquetados, porque la escritura honesta es el objetivo de esta serie.

– la piedra angular – de la serie “Inferencia agente de grado de producción”. Cada parte eliminó un tipo de trabajo redundante de un proceso de LLM agente. La parte 1 eliminó el llenado previo redundante (no lea el mismo documento dos veces). La parte 2 eliminó la espera redundante (no haga cola con cincuenta agentes en una sola fila). La parte 3 eliminó los viajes de ida y vuelta de CPU redundantes (no rebote cada recuperación de la GPU). La parte 4 (esta publicación y la última) elimina las reconstrucciones de contexto redundantes: el agente equivalente a deshacerse de su estado oculto cada vez que la conversación pasa a un nuevo especialista.

Conclusiones clave

El problema: en una canalización de agentes de múltiples saltos, cada vez que el control cambia del agente A al agente B, el receptor descarta el estado oculto de A y reconstruye el contexto a partir de una cadena de aviso. Esto es estructuralmente el mismo “arranque en frío posterior a la transferencia” que sufre un equipo de usuario (UE) cuando se mueve entre dos estaciones base (de origen a destino), donde la estación base de destino reinicializa el estado recurrente por usuario desde cero.

La solución: comprimir el estado recurrente del remitente en una pequeña carga útil latente, transportarlo a lo largo de la transferencia y dejar que el receptor lo use como un prefijo de aviso suave en lugar de volver a completar todo desde el texto. La misma lección de “calcular una vez, desplegar el estado compartido” que la serie ha estado repitiendo desde la Parte 1, se aplica a través de saltos de razonamiento en lugar de dentro de un proceso.

Los recibos "inusuales": el método subyacente es la Persistencia Inductiva del Contexto Latente (ILCP), un artículo revisado por pares del que fui coautor recientemente, aceptado en AI4NextG @ ICML 2026. En la prueba de conducción 4G/5G de Viena, ILCP elimina por completo los traspasos de ping-pong (0,0 % frente a 6,5 % de referencia sin transferencia, 22,6 % de referencia de transformador), recupera la precisión posterior a la entrega a +5,1 pp de promedio / +13,3 pp de pico, y se ejecuta de extremo a extremo a 7,7 ms p99 por decisión de entrega en la misma GTX 1080 que el resto de esta serie.

La parte honesta: esos números son números de transferencia de radio 6G, no números de agentes LLM. El V1 del lado del agente en esta publicación (ilcp-for-agents) es el cableado (un compresor β-VAE, un transporte en proceso, un proyector MLP cerrado y un arnés Qwen2.5-7B) y sus puntos de referencia del lado del agente son explícitamente trabajos futuros. Me niego a lavar los recibos de RAN como recibos de LLM incluso cuando la tentación es alta.

El truco: el hilo conductor de las telecomunicaciones que atravesó las Partes 1 a 3 a modo de analogía es, en la Parte 4, mi investigación publicada que resuelve el mismo problema en dos industrias diferentes. La serie cierra el círculo.

TL;DR: Los agentes LLM de múltiples saltos actualmente transfieren el contexto como una cadena. El Agente A termina de razonar, lo resume en un mensaje de texto y el Agente B lee esa cadena desde cero: el caché KV del receptor, el patrón de atención y cualquier cálculo parcial que el Agente A haya creado se descartan. Esta es la versión agente del arranque en frío posterior al traspaso que sufren las estaciones base 5G/6G cuando un UE (dispositivo móvil) se mueve entre dos estaciones base: la estación base objetivo reinicializa el estado recurrente por UE y tiene que reconstruirlo desde cero. Resolvimos ese problema con un método llamado Persistencia de contexto latente inductivo (ILCP): un β-VAE comprime un estado GRU de 128 atenuaciones en una carga útil latente de 128 bytes, la transporta a través de la interfaz estándar 3GPP Xn y luego un MLP cerrado lo proyecta en el espacio de estado de la estación base de destino en el momento de la entrega. En la prueba de manejo 4G/5G de Viena, ILCP elimina los traspasos de ping-pong (0,0% frente a 6,5% de referencia sin transferencia), recupera la precisión de la siguiente celda posterior al traspaso en un promedio de +5,1 pp / pico de +13,3 pp en la ventana de 50 a 250 ms posterior al traspaso y se ejecuta a 7,7 ms p99 por decisión en una sola GTX 1080. Esta parte asigna exactamente el mismo protocolo a Transferencias de agentes de LLM: ilcp-for-agents aprende a comprimir un resumen oculto agrupado, transportarlo a lo largo de la transferencia y proyectarlo nuevamente en un prefijo de aviso suave del lado del receptor. V1 es el cableado (PyTorch, Qwen2.5-7B-Instruct, β-VAE, MLP cerrado, transporte en proceso, métrica de coincidencia exacta de juguetes). La contribución aquí es la transferencia arquitectónica, no los números.

Repositorio de Github: https://github.com/AnubhabBanerjee/ILCP-for-Agents

(Confesión rápida antes de comenzar: llegué a toda esta serie con experiencia en ingeniería de RAN 5G/6G. Los ángulos de telecomunicaciones en las Partes 1, 2 y 3 fueron las analogías. Esta parte deja de ser una analogía. El mecanismo que estoy asignando a los agentes de LLM es el mismo mecanismo, escrito por los mismos coautores, que cierra el arranque en frío posterior al traspaso en las redes de acceso de radio 6G. Ese es el punto culminante de la serie. Hay una sección completa en el lado a lado (sección 7), pero también es la razón por la que esta publicación existe en la forma que tiene).

Modelo mental de arquitectura: mantén esto abierto mientras lees.

Contexto del Agente A → grupo medio enmascarado → codificador β-VAE → z (32 tenue latente) → TransportPayload en proceso → decodificador β-VAE + MLP cerrado → tokens de memoria K → torch.cat en la pregunta del Agente B incrustada → decodificación codiciosa

Todo lo que aparece a continuación es solo un comentario sobre una parte de esa línea.

Comprimir, transportar y proyectar.

1. Una confesión: resolví este problema antes de saber que lo tenía

En la Parte 3, hicimos todo lo posible para mantener nuestros tensores exactamente donde pertenecen: en el silicio. Al escribir un kernel CUDA personalizado para la recuperación Top-K, eliminamos los viajes de ida y vuelta de CPU redundantes que arrastran hacia abajo el RAG agente. La filosofía era absoluta: una vez que la GPU calcula un estado rico y de alta dimensión, no lo mueves y ciertamente no lo destruyes. Y, sin embargo, en el momento en que ese recuperador altamente optimizado termina su trabajo y pasa el testigo al siguiente especialista en su proceso, los marcos estándar lo obligan a hacer exactamente eso. Protegemos nuestro estado tensor con nuestras vidas dentro de un solo nodo, solo para tirarlo voluntariamente a la basura en el momento en que cruzamos un salto de razonamiento.

Permítanme dramatizar el traspaso de agentes de la forma en que lo hacen hoy en día todos los oleoductos de múltiples saltos.

Usted: "Agente A, lea este informe de 50 páginas, cree un resumen y entrégueselo al Agente B para que lo verifique".

Agente A: "Claro. Cargando el modelo. Leyendo el informe. Reuniendo el contexto. Llamando la atención sobre el párrafo 47. Formando mis opiniones. ✅"

La GPU funciona durante 30 segundos.

Agente A: "Listo. Aquí hay un resumen de 200 tokens del que estoy muy orgulloso".

Tú: "Genial. Reenvío al Agente B".

Agente A: "Espera, ¿cómo estás reenviando exactamente?"

Tú: "…¿como una cadena? ¿En el mensaje?"

Agente A: "Correcto. Entonces le estás enviando al Agente B mi hilo final. No mi estado oculto. Ni mi atención calculada en las 50 páginas que acabo de leer. Ni el hecho de que el párrafo 47 fue inusualmente cargado. Ni la confianza calibrada que construí. Sólo el hilo".

Tú: “Así es como funciona, sí”.

Agente A: "Genial. Genial, genial, genial. Diviértete, B. 👋"

Agente B: "Hola, soy una hermosa recién nacida apátrida. Cargando modelo. Leyendo la cadena del Agente A desde cero. Construyendo contexto. Agrupando. Formando opiniones. ✅"

La GPU pasa otros 30 segundos haciendo esencialmente el mismo trabajo que el Agente A acaba de terminar.

Tú: "… ¿hay alguna manera de omitir la segunda preparación del contexto y el cálculo de la atención?"

Agente B: "¿Qué segunda lectura?"

Así es como se ve realmente debajo de la tapa cada “enjambre de agentes múltiples” que he visto. Cada transferencia es una garganta en forma de cuerda por la que el estado interno del remitente no puede atravesar. El receptor obtiene el texto de salida y reconstruye el contexto a partir del texto, que es lo más caro que suele hacer un transformador, y lo que esta serie ha dedicado tres partes a tratar de convencerlo de que deje de hacerlo en una ejecución del canal.

Lo curioso es que he escrito sobre este problema antes, pero no para agentes de LLM.

En 2026, mi coautor y yo publicamos un artículo titulado “Persistencia del contexto latente inductivo: cierre del arranque en frío posterior al traspaso en redes de acceso de radio 6G”. La configuración es un teléfono móvil (también llamado equipo de usuario o UE) que se mueve entre estaciones base 5G/6G (también llamadas gNB). En cada traspaso, el gNB de destino descarta el estado recurrente por UE mantenido en el gNB de origen y reinicializa el estado oculto por UE en el gNB de destino. Luego, el modelo de predicción del lado objetivo tiene que reconstruir ese estado a partir de las pocas mediciones de radio posteriores al traspaso que acaba de recibir, mientras el UE ya se está moviendo. El periódico llama a esto el arranque en frío posterior a la entrega. ¿Suena alguna campana?

Ahora lea este párrafo de las contribuciones del artículo, ligeramente simplificado: "Tratamos el estado recurrente por usuario como un contexto de red portátil. Para abordar el problema práctico de que el mensaje estándar entre celdas tiene un presupuesto de tamaño pequeño, mostramos que una actualización diferencial de 128 bytes es suficiente para preservar la calidad predictiva de un estado GRU de 128 dimensiones a través del límite de transferencia. Nuestro protocolo ILCP propuesto comprime el estado oculto con un codificador automático variacional β, lo transporta en el interfaz estándar 3GPP Xn y la proyecta en el espacio de estado del gNB objetivo en el momento de la transferencia a través de un MLP controlado y aprendido”.

Si cambia "gNB de origen" por "agente A", "gNB de destino" por "agente B" y "mediciones de radio" por "tokens de la siguiente subtarea", tendrá la arquitectura de la que trata toda esta publicación. Mismo artículo, mismo autor, solo que el dominio de la aplicación es diferente.

La contribución de esta publicación no es el método; el método ya está en el artículo. La contribución de esta publicación es el mapeo: tomar ILCP y conectarlo para agentes LLM de múltiples saltos, de extremo a extremo, en un pequeño repositorio de PyTorch que ya vio. Los recibos que está a punto de ver en la sección 5 son recibos en papel, en unidades de entrega 6G, debidamente etiquetados.

2. ¿Por qué existe el arranque en frío del agente? (un curso intensivo de un minuto)

Omita esta sección si ya conectó una canalización agente de múltiples saltos en el pasado. Para todos los demás, aquí está la versión corta.

Un agente de múltiples saltos no es un modelo que responde a una pregunta. Se trata de varios modelos especializados que se turnan en un trabajo. Un enrutador decide la intención, un planificador descompone la tarea, un recuperador obtiene el contexto fundamentado, un razonador hace el pensamiento real, un verificador de seguridad huele el resultado y un finalizador escribe la respuesta. Cada uno de ellos es su propio avance, a menudo su propio modelo, a veces su propio proceso.

Entre dos de esos pases hacia adelante, controle las manos. Y aquí está el sucio secreto que la mayoría de los marcos de agentes cubren con diagramas amigables: en cada transferencia, el receptor recibe un mensaje de texto. Ni un estado oculto, ni un caché KV, ni siquiera un vector: texto. La clasificación de intención del enrutador se convierte en una cadena de token. El plan de tareas del planificador se convierte en un blob JSON. Los fragmentos seleccionados por el recuperador se convierten en una ventana contextual concatenada. La cadena de pensamiento del razonador se convierte en un bloque de “pensamiento:”. Cada traspaso es un tokenizador de ida y vuelta.

Eso suena bien hasta que cuentas. Una canalización agente estándar con cuatro saltos en un contexto compartido largo tokenizará y recargará el mismo material fuente cuatro veces. Tres de esas lecturas no aportan nada. El enrutador ya lo sabía, el planificador ya lo sabía, el razonador ya lo sabía. La cuarta lectura lo hace para beneficio del verificador de seguridad, y el verificador de seguridad lo hará nuevamente para el finalizador.

Si eso suena como el problema SwarmKV de la Parte 1, lo es, pero girado 90 grados. La parte 1 trataba sobre N agentes que leían el mismo documento dentro de una ejecución del canal. Esta parte trata sobre N agentes que leen el contexto acumulado de cada uno a través de saltos de razonamiento separados. Forma diferente, mismo impuesto subyacente: el receptor está desechando un costoso estado calculado y reconstruyéndolo desde cero a partir de una cadena rápida. Ese es el arranque en frío posterior a la entrega, disfrazado de Python.

3. La bombilla de “simplemente envía una luz latente a través del traspaso” (y por qué es más difícil de lo que parece)

El discurso es simple:

Mientras el Agente A todavía esté vivo, agrupe su contexto de trabajo en un único vector de resumen de tamaño fijo sAs_AsA​. Comprima sAs_AsA​ con un β-VAE en un pequeño zzz latente de, digamos, 32 flotadores. Eso es 128 bytes en fp32. Mano zzz a través del límite como lo único que cruza el salto. En el Agente B, decodifica zzz y proyéctalo a través de un MLP cerrado en K vectores de memoria en el propio espacio de incrustación de B. Concatene esos K vectores frente a las incorporaciones del token de pregunta y deje que B decodifique con avidez. B nunca relee el contexto de A como texto.

Eso es "calcular una vez, entregar el estado comprimido": la misma lección que las Partes 1 a 3, aplicada a través de saltos en lugar de dentro de una canalización. La única razón por la que se necesita más de un script PyTorch de 30 líneas es que tres problemas aburridos rompen inmediatamente el enfoque ingenuo.

Problema A: ¿Qué lleva usted realmente durante el traspaso?

La respuesta más clara es "todo el caché KV". El Agente A lo construyó; simplemente entrégueselo al Agente B. Sin embargo, el hecho es que el caché KV es un objeto por contexto que depende del modelo, el tokenizador, la cuantificación, la configuración de RoPE, la implementación de atención, el recuento de capas, el recuento de cabezas, la relación GQA, el n_ctx y el hash GGUF/safetensors exacto. Entregue un caché KV de un proceso que ejecuta el modelo X a un proceso que ejecuta el modelo Y y habrá enviado un blob binario que el receptor no puede interpretar. El elemento de la hoja de ruta de KV en disco en las limitaciones de V1 de SwarmKV existe precisamente para hacer explícitas esas invariantes; Hasta entonces, cada idea de “compartir el caché KV entre agentes” tiene que negociar un vocabulario de siete campos coincidentes antes de que los bytes signifiquen algo.

El ILCP V1 toma la decisión aburrida a propósito: no llevar el caché KV, llevar un resumen aprendido de lo que el caché KV intentaba representar. Un único vector de estado oculto agrupado es frágil en versión de modelo, pero no catastróficamente: es solo (tamaño_oculto) flotantes, y si el Agente A y el Agente B comparten el mismo modelo base, no queda ambiguo lo que significan esos flotantes. Desde src/agents/qwen_encoder.py:

@staticmethod def masked_mean_pool(last_hidden: torch.Tensor, atención_mask: torch.Tensor) -> torch.Tensor: """ Agrupación V1 aprobada: vectores de token de capa final promedio con relleno enmascarado a masa cero. Dividir por el recuento de tokens sin procesar (sin normalización L2) preserva las señales de magnitud sobre la confianza y la saturación que un grupo de norma unitaria borraría antes del cuello de botella de VAE. """ if last_hidden.dim() != 3: aumentar ValueError("last_hidden debe ser (batch, seq, dim).") if attention_mask.dim() != 2: aumentar ValueError("attention_mask debe ser (batch, seq).") máscara = atención_mask.unsqueeze(-1).to(dtype=last_hidden.dtype, dispositivo = último_hidden.dispositivo) sumado = (último_hidden * máscara). suma (dim = 1) longitudes = máscara. suma (dim = 1). abrazadera (min = 1.0) retorno sumado / longitudes

Preferimos la media enmascarada a los estados ocultos de la capa final. El comentario es honesto sobre la elección del diseño: no normalizamos L2 al salir, porque la magnitud transmite una señal útil sobre la confianza y la saturación que un conjunto de normas unitarias borraría. El cuello de botella β-VAE aguas abajo es lo que decide qué conservar y qué descartar, no la capa de acumulación.

Problema B: ¿Qué tan pequeña puede llegar a ser la carga útil y seguir siendo útil?

Un vector oculto agrupado de un modelo 7B es (4096,) flotantes: dieciséis kilobytes. Esto está bien para demostraciones de juguetes en proceso, pero en el momento en que el transporte se convierte en un mensaje de red real, dieciséis kilobytes por transferencia no son gratuitos. Todo el argumento del artículo de radio es que una actualización diferencial de 128 bytes es suficiente para preservar la calidad predictiva de un estado GRU de 128 dimensiones, porque el estado GRU vive en una variedad de baja dimensión relevante para la tarea y un β-VAE puede encontrar esa variedad durante el entrenamiento conjunto con la pérdida posterior.

La V1 del lado del agente ofrece la misma opción arquitectónica. Desde src/compressor/beta_vae.py:

class BetaVAE(nn.Module): """ β-VAE completamente conectado que opera en estados ocultos de LM agrupados. Por qué completamente conectado en lugar de convoluciones: la entrada ya es un único vector por muestra (grupo medio enmascarado a lo largo del tiempo), por lo que las capas conv agregarían una sobrecarga de parámetros sin explotar la localidad espacial como lo haría un kernel CUDA en las grillas. """ def __init__( self, input_dim: int, latent_dim: int, oculto_dim: int, beta: flotante = 1.0,) -> Ninguno:

Los dos cabezales del codificador devuelven μ y logvar por separado, porque vincularlos restringiría la curvatura; el truco de la reparametrización mantiene el muestreo diferenciable; la divergencia KL de forma cerrada es la expectativa analítica estándar bajo un codificador gaussiano diagonal. Nada de esto es un trabajo nuevo de VAE, Higgins et al. (2017) y Kipf & Welling (2016) hicieron el trabajo pesado hace una década, y los comentarios en el código son explícitos y ninguno de ellos pretende serlo. La contribución es a lo que se adjunta el VAE, no el VAE en sí.

Hay una pequeña ayuda en el mismo archivo que existe únicamente para informes honestos:

def latent_payload_bytes(latent_dim: int, dtype: torch.dtype) -> int: """ Informa el tamaño de la carga útil transferible en bytes para los recibos README (no se supone una carga útil de telecomunicaciones de 128 bytes). El tamaño del elemento sigue la alineación del elemento torch.dtype; este es el análogo en cable para el transporte en proceso. """ # torch.finfo / element_size proporciona el ancho de bytes para los tipos d flotantes utilizados en los tensores z. si no, dtype.is_floating_point: aumente ValueError("latent_payload_bytes espera un dtype flotante para z.") width = torch.tensor([], dtype=dtype).element_size() devuelve int(latent_dim) * int(ancho)

La cadena de documentación dice "no se supone una carga útil de telecomunicaciones de 128 bytes". El código del lado del agente se niega a asumir el número de 128 bytes del papel 6G: calcula la carga útil del lado del agente a partir de la atenuación y el tipo latentes reales en la ejecución que ejecutó, por lo que el recibo README del lado del agente dirá su propia verdad. Ese único ayudante es la política completa de “no lavar números RAN como números LLM”, en siete líneas.

Problema C: ¿Cómo utiliza realmente el receptor lo latente?

Aquí es donde el documento de radio y el mapeo de LLM divergen un poco, porque el receptor no tiene la misma forma de objeto en los dos dominios. En el artículo de radio, el receptor es una estación base objetivo que ejecuta su propio transformador gráfico heterogéneo GRU +, y el bloque de proyección devuelve el latente decodificado al espacio de estado recurrente del objetivo. En el lado del agente V1, el receptor es un decodificador de instrucciones Qwen2.5-7B congelado, y el bloque de proyección tiene que colocar el latente decodificado en algo que el decodificador pueda atender.

Lo más limpio que puede atender un decodificador congelado es su propio espacio de incrustación de tokens. Entonces, el proyector eleva los vectores de memoria latentes a K que viven en el mismo espacio vectorial que las incrustaciones de tokens reales, y el receptor los concatena frente a la pregunta. Desde src/projector/gated_mlp.py:

class GatedLatentToMemoryProjector(nn.Module): """ Asigne z ∈ R^{latent_dim} a la memoria ∈ R^{K × model_hidden}. La puerta utiliza una no linealidad SiLU (ReLU suave) para que los gradientes no mueran en preactivaciones negativas como lo harían con una puerta sigmoidea simple que se satura en la inicialización. """

El maletero es un MLP pequeño; la cabeza de la puerta y la cabeza de valor se separaron; la puerta es sigmoidea, el valor se deja sin procesar y un producto por elementos elimina las direcciones latentes espurias antes de la remodelación final en (lote, K, modelo_hidden). Dos caminos, un producto, una remodelación. El comentario sobre la aplicación de la puerta en fp32 incluso cuando el LM se ejecuta en bf16 es una nota a pie de página de la era Pascal: la GTX 1080 utilizada como referencia canónica para esta serie no tiene una ALU bf16 de velocidad completa, por lo que la puerta en fp32 es simplemente cortés con el hardware.

La concatenación exacta ocurre dentro del arnés. Desde src/agents/harness.py:

prefijo = antorcha.cat([memory_tokens.unsqueeze(0), q_embeds], dim=1)

Ese es todo el acto. Las fichas de memoria van al frente; A continuación se incorporan tokens de preguntas. El receptor decodifica a partir de este prefijo usando inputs_embeds en lugar de input_ids, y el resto del ciclo de generación es una decodificación codiciosa estándar que reutiliza las entradas de caché KV de la misma manera que lo haría cualquier decodificador de producción después del primer paso amplio hacia adelante.

Estos tres problemas (qué llevar, qué tan pequeño hacerlo, cómo inyectarlo en el otro lado) son la sustancia completa de "enviar un mensaje latente a través del traspaso". La sección 4 explica cómo las piezas se pegan de un extremo a otro.

4. La tubería de comprimir → transportar → proyecto (la parte realmente interesante)

Todo el proceso del lado del agente consta de seis pasos, y el cableado se encuentra en cuatro archivos. Imagínelo como un tubo horizontal.

Paso 0: Construir compresor + proyector + transporte en el inicio del motor (load_ilcp_modules) Paso 1: Codificar el contexto del Agente A en un resumen agrupado s_A (QwenContextEncoder.pooled_embedding_for_text) Paso 2: Comprimir s_A a una z latente a través del codificador β-VAE media μ (BetaVAE.encode) Paso 3: Empaquetar z en una carga de transporte (CPU preparada bytes) (InProcessTransport.pack) Paso 4: Desempaquetar en el receptor y proyectar tokens de memoria z a K (InProcessTransport.unpack + GatedLatentToMemoryProjector) Paso 5: Concatar la memoria delante de las incrustaciones de preguntas y decodificar con avidez (greedy_generate_from_memory_prefix)

Recorramos cada uno con el código real. Los fragmentos son deliberadamente breves; los archivos completos son pequeños y vale la pena examinarlos.

Paso 1: contexto del agente A del grupo

Este es el paso aburrido que hace posible el resto del proceso. El Agente A lee su contexto de trabajo con la misma instrucción Qwen2.5-7B que ejecutará el Agente B, pero en lugar de decodificar los tokens, le pedimos al modelo que nos proporcione los estados ocultos de la capa final y los agrupe en un solo vector. Desde src/agents/qwen_encoder.py:

@torch.inference_mode() def encode_contexts( self, texts: list[str], max_length: int = 512, ) -> tuple[torch.Tensor, torch.Tensor]: """ Devuelve incrustaciones agrupadas (por lotes, ocultas) y las máscaras de atención utilizadas para auditar formas. torch.inference_mode() deshabilita completamente la contabilidad del contador de versiones frente a no_grad para una sobrecarga ligeramente menor al barrer miles de contextos para la construcción de conjuntos de datos de compresores en una GPU económica """ lote = self.tokenizer( texts, padding=True, truncation=True, max_length=max_length, return_tensors="pt", ) lote = {k: v.to(self.device) for k, v in batch.items()} salidas = self.lm(**batch, output_hidden_states=True, use_cache=False) last_hidden = salidas.hidden_states[-1] agrupado = self.masked_mean_pool(last_hidden, lote["attention_mask"]) retorno agrupado, lote["attention_mask"]

Un pase hacia adelante con output_hidden_states=True, los estados ocultos de la última capa, el grupo medio enmascarado de la sección 3, fuera. El tensor agrupado es (lote, tamaño_oculto), que para Qwen2.5-7B es (1, 4096) por muestra. Ese es el vector s_A del que habla la sección 4 del artículo; a excepción de un teléfono que se mueve entre torres de telefonía celular, el mismo vector es construido por un GRU de 128 atenuaciones a través de mediciones de radio. Diferentes sensores, misma función.

Paso 2: comprimir a una z latente

Desde src/agents/harness.py:

@torch.inference_mode() def ilcp_memory_from_context(self, contexto: str, dispositivo: torch.device) -> torch.Tensor: """ Comprimir → transporte → canalización del proyecto que devuelve el tensor de memoria del receptor (K, D) en el `dispositivo`. El uso del codificador VAE significa μ (no una muestra estocástica) estabiliza la latencia de múltiples pruebas y las comparaciones de calidad de la misma manera que un sistema implementado congelaría la estocasticidad después de la calibración """ s_a = self.encode_sender_summary(context).to(device) mu, _logvar = self.vae.encode(s_a.unsqueeze(0)) z = mu.squeeze(0) payload = self.transport.pack(z) z_b = self.transport.unpack(payload, dispositivo=dispositivo) mem =. self.projector(z_b.unsqueeze(0)).squeeze(0) devolver memoria

Ese es todo el salto de compresión → transporte → proyecto. La cadena de documentación hace explícita una elección de producción silenciosa pero importante: utilizamos la media del codificador μ en la inferencia, no una muestra estocástica reparametrizada. El periódico radiofónico hace lo mismo en el despliegue; la estocasticidad sólo es útil durante el entrenamiento. Congelarlo después de la calibración es lo que hace cada sistema de cuello de botella VAE enviado, y el comentario así lo dice.

Dentro de β-VAE, codificar devuelve media y logvar; Eliminamos logvar porque no estamos muestreando aquí. Desde src/compressor/beta_vae.py:

def encode(self, x: torch.Tensor) -> tuple[torch.Tensor, torch.Tensor]: """ Asigna un lote de incrustaciones resumidas a parámetros gaussianos diagonales. Devolver logvar en lugar de std evita un sqrt durante el entrenamiento y mejora la estabilidad numérica cuando las variaciones se vuelven pequeñas (evita explosiones de división en forma cerrada de KL). """ # Aplana las dimensiones intermedias opcionales para que el codificador siempre vea (batch, entrada_dim). h = self._encoder_body(x) mu = self._enc_mu(h) logvar = self._enc_logvar(h) devolver mu, logvar

Codificador β-VAE estándar. Las dos cabezas separadas para μ y logvar existen porque unirlas restringiría la curvatura de la geometría latente, que el comentario presenta en una oración para que el siguiente lector no tenga que preguntarse.

Paso 3: empaquetar en un TransportPayload

La frontera del transporte es deliberadamente explícita. Aunque el Agente A y el Agente B comparten el mismo proceso de Python en V1, la transferencia se incluye en un paso de serialización/deserializar para que las versiones futuras puedan intercambiarse en una red real (gRPC, buffers de anillo de memoria compartida, un protocolo de conexión) sin reescribir los sitios de llamada. Desde src/transport/in_process.py:

@dataclass(frozen=True) class TransportPayload: """ Contenedor inmutable para el tensor latente más metadatos mínimos para los registros de auditoría. Congelar la clase de datos evita una mutación accidental en el lugar que desincronizaría recibos de tamaño de bytes entre el agente emisor y receptor en arneses multiproceso. """ latent: torch.Tensor dtype_name: str latent_dim: int def byte_length(self) -> int: """ Calcula la longitud exacta de bytes serializados para tablas README (torch.save usa pickle; nosotros usamos bytes sin formato). Los bytes contiguos sin procesar reflejan la historia de la "carga útil sobre Xn" de manera más honesta que el decapado de tensores completos. """ return int(self.latent.numel() * self.latent.element_size())

byte_length() es el análogo del lado del agente de la "carga útil de 128 B sobre Xn" del documento de radio. Calcula el recuento de bytes transferibles real a partir del tensor real, sin suposiciones en la hoja de especificaciones. El documento de radio dice 128 bytes porque la SOLICITUD DE ENTREGA 3GPP Xn tiene un presupuesto estricto de tamaño de IE opcional. El lado del agente aún no tiene esa restricción, pero está cableado para medir cualquier tamaño en el que aterrice, de modo que cuando obtenga un transporte de red real, el recibo será honesto.

El paso del paquete en sí es pequeño y deliberado:

def pack(self, z: torch.Tensor) -> TransportPayload: """ Separar de autograd, mover al dispositivo de preparación y registrar dtype para fidelidad de ida y vuelta. La separación rompe el gráfico a propósito: el transporte es un límite de transferencia donde se detienen los gradientes del remitente. """ z_staged = z.detach().to(self.device).contiguous() return TransportPayload( latent=z_staged, dtype_name=str(z_staged.dtype), latent_dim=int(z_staged.shape[-1]), )

detach() rompe el gráfico de autogrado a propósito. El límite de transferencia es un límite lógico, no sólo un movimiento de memoria. Los gradientes del remitente se detienen en esta línea; el receptor construye su propio gráfico a partir del latente desempaquetado si así lo desea. El artículo sobre radio impone el mismo límite en la interfaz Xn, por la misma razón: las estaciones base de origen y de destino son procesos diferentes en máquinas diferentes, y un gráfico de autogrado entre procesos es una mala idea independientemente de la industria.

Paso 4: Desempaquetar y proyectar en K tokens de memoria

def unpack(self, carga útil: TransportPayload, dispositivo: torch.device | str) -> torch.Tensor: """ Materializa z en el dispositivo receptor antes de que el proyector lo incorpore a la memoria. clone() evita el alias si el mismo objeto de carga útil se reutiliza accidentalmente entre dos agentes. """ return payload.latent.clone().to(device, non_blocking=True)

El receptor materializa z en su propio dispositivo, clona a la defensiva para que dos receptores que lean el mismo objeto de carga útil no puedan pisotearse entre sí y luego se lo entrega al MLP cerrado. El avance del MLP cerrado, desde src/projector/gated_mlp.py:

def forward(self, z: torch.Tensor) -> torch.Tensor: """ Forma de retorno (lote, K, D) adecuada para torch.cat a lo largo de la dimensión de secuencia con incrustaciones de tokens. La aplicación de la puerta en float32 incluso cuando el LM se ejecuta en bf16 puede reducir el ruido numérico en GPU de consumo que carecen de ALU bf16 de velocidad completa (nota de hardware de la era Pascal para líneas base GTX 1080). """ # Asegúrese de que z tenga rango 2 por lo que las rutas matmul por lotes permanecen vectorizadas en núcleos tensoriales anchos cuando estén disponibles. if z.dim() != 2: rise ValueError("GatedLatentToMemoryProjector espera forma de z (batch, latent_dim).") h = self._trunk(z) gate = torch.sigmoid(self._gate_head(h)) value = self._value_head(h) # El producto Elementwise suprime direcciones espurias antes de transformarlas en tokens de memoria. mem_flat = puerta * valor de retorno mem_flat.view(z.size(0), self.num_memory_tokens, self.model_hidden)

Tronco → cabeza de compuerta y cabeza de valor dividida → producto por elementos → remodelar a (lote, K, D). La salida D es el tamaño oculto del LM, por lo que cada uno de los K tokens de memoria ya vive en el espacio de incrustación del modelo y se puede concatenar junto con incrustaciones de tokens reales sin una capa separada de coincidencia de espacio.

Paso 5: Concat frente a la pregunta y decodificación codiciosa

Ahora el receptor realmente responde. Desde src/agents/harness.py:

@torch.inference_mode() def greedy_generate_from_memory_prefix( lm: nn.Module, tokenizer, embed_layer: nn.Module, Memory_tokens: torch.Tensor, question_prompt: str, max_new_tokens: int, dispositivo: torch.device,) -> str: """ Decodificación codiciosa a partir de indicaciones suaves concatenadas + token de pregunta incrustaciones El bucle alterna entre un prefijo ancho hacia adelante (primer paso) y pasos delgados de un solo token que reutilizan las entradas de caché KV de la misma manera que lo haría un decodificador de producción después de que llega un marco de transferencia """ q_batch = tokenizer(question_prompt, return_tensors="pt", truncation=True, max_length=512) q_ids = q_batch["input_ids"].to(device) q_embeds =. embed_layer(q_ids) prefijo = torch.cat([memory_tokens.unsqueeze(0), q_embeds], dim=1) atención_mask = torch.ones(prefix.shape[:2], dispositivo=dispositivo, dtype=torch.long) pasado = Ninguno embed_step = prefijo generado: lista[int] =[]para _ en rango(max_new_tokens): out = lm( inputs_embeds=embed_step, atención_mask=attention_mask, pasado_key_values=pasado, use_cache=True, return_dict=True, ) pasado = out.past_key_values logits = out.logits[:, -1, :] next_id = int(logits.argmax(dim=-1).item()) generate.append(next_id) next_emb = embed_layer(torch.tensor([[next_id]], dispositivo=dispositivo, dtype=torch.long)) embed_step = next_emb add = torch.ones((1, 1), dispositivo=dispositivo, dtype=torch.long) atención_mask = torch.cat([attention_mask, agregar], dim=1) devolver tokenizer.decode(generado, skip_special_tokens=True)

Un prefijo amplio hacia adelante sobre [memory_tokens, question_embeds], luego una decodificación codiciosa estándar de un token a la vez reutilizando valores_clave_pasados. El receptor nunca tokeniza el contexto original del Agente A. No es necesario. La información que habría surgido de la lectura de ese contexto ya está presente en las fichas de memoria K, proyectadas directamente en el espacio de incrustación del receptor.

A modo de comparación, la línea de base fría con la que mide V1 es el flujo de agente estándar: el receptor obtiene el contexto completo más la pregunta como input_ids y las respuestas del texto:

def _format_agent_prompt(context: str, question: str) -> str: """ Cree la cadena de inicio en frío que obliga al receptor LM a volver a leer todo el contexto del Agente A. Mantener el estilo del delimitador de instrucciones estable en todas las ramas aísla el efecto ILCP de la deriva del mensaje. """ return ( "Usted es el Agente B. Lea el contexto con atención, luego responda la pregunta con un lapso corto.nn" f"Contexto:n{context}nnPregunta: {pregunta}nnRespuesta:" )

Camino frío: lea el pasaje completo, complete todo el precompletado, responda. Ruta ILCP: obtener un latente, proyectarlo, decodificarlo a partir del prefijo. Misma tarea, dos contratos, uno de ellos hace la segunda lectura y otro no. Ese es el V1.

5. Los recibos (del periódico de telecomunicaciones, NO de agentes de LLM)

Esta es la sección donde cada parte anterior de esta serie incluye una tabla de referencia. La Parte 4 es la parte en la que tengo que ser honesto acerca de qué recibos realmente puedo presentarles.

Nota rápida sobre la metodología antes de que alguien busque las rocas: cada número en esta sección proviene de “Persistencia del contexto latente inductivo: cierre del arranque en frío posterior al traspaso en redes de acceso de radio 6G” (Banerjee & Awan, Nokia Munich, aceptado en AI4NextG @ ICML 2026; preimpresión arXiv:2605.00593v2, junio de 2026). El documento evalúa ILCP en la prueba de manejo 4G/5G de Viena, una traza de radio urbana de múltiples celdas y niveles con una densa superposición de celdas, 31 eventos de traspaso en la división de prueba retenida, mediciones por paso a 100 Hz, con intervalos de confianza del 95 % de arranque de 1000 en cada valor informado. El hardware de inferencia es una NVIDIA GTX 1080 (8 GB), Intel i7-8700K, 16 GB de RAM, que es, convenientemente, la misma GPU de referencia canónica que las otras partes de esta serie.

MétodoAcc@t=0 (%)HOF (%)Ping-pong (%)OvrZK-HGT (valor inicial sin transferencia)87,1 (74–97)12,9 (3–26)6,5 (0–16)75,6GAT-Temporal22,6 (10–39)77,4 (61–90)61,3 (45–77)19,3Transformador-Temporal77,4 (61–90)22,6 (10–39)22,6 (10–39)66,9LSTM12,9 (0–26)87,1 (74–97)83,9 (71–94)6,33GPP A3/A5 (regla)100,0 (100–100)0,0 (0–0)3,2 (0–10)72,4ILCP (nuestro)83,9 (71–94)16,1 (3–32)0,0 (0–0)74,1

Estas son métricas de traspaso de 6G, en unidades de traspaso de 6G, en una traza de traspaso de 6G. Acc@t=0 es "¿el modelo eligió la siguiente celda de servicio correcta en el momento de la entrega?" HOF es la fracción de eventos de traspaso en los que la siguiente celda prevista es incorrecta. Ping-pong es la fracción de traspasos invertidos dentro de una ventana corta: operativamente el modo de falla más doloroso, porque cada traspaso invertido es una señalización del plano de control desperdiciada en una red que ya tiene mil otras cosas que hacer. La línea base ZK-HGT (Zero-Knowledge HGT) es la arquitectura por lo demás idéntica sin ILCP (la misma columna vertebral de gráfico heterogéneo, el mismo GRU, el mismo puntuador candidato) pero con el estado recurrente por usuario reiniciado en cada entrega. ZK-HGT es la ablación limpia que aísla el efecto de la persistencia del estado de transferencia cruzada; ILCP es ZK-HGT más un latente transferido.

La fila más importante desde el punto de vista operativo es la tasa de ping-pong del 0,0% para ILCP frente al 6,5% para ZK-HGT y el 22,6% para la línea de base de Transformer. En despliegues futuros densos con células pequeñas superpuestas, los ping-pong son exactamente lo que destruye la calidad del servicio de movilidad. La sección 5.1 del documento señala que la regla A3/A5 alcanza una precisión del 100% en el rastro limpio solo porque las etiquetas de entrega en el rastro fueron generadas por una regla similar a A3/A5, por lo que la comparación es una verificación de cordura, no una victoria real. Lea el artículo para conocer una discusión detallada de por qué la fila A3/A5 imperturbable debe tratarse como un artefacto de fuga de etiquetas y no como un número a perseguir.

6. "Está bien, pero ¿en qué se diferencia esto del almacenamiento en caché de prefijos/RadixAttention/memoria RAG?"

Pregunta razonable, y vale la pena responderla directamente, porque el mundo de inferencia-infra tiene muchas primitivas superpuestas y un lector de HPC preguntará esto en el primer comentario.

Almacenamiento en caché de prefijos vLLM/cachés de sesiones TGI. Excelente si su prefijo compartido tiene un ámbito de solicitud o de sesión. Almacenan en caché el estado de KV dentro de un tiempo de ejecución de servicio para que una solicitud de seguimiento de la misma sesión no vuelva a completar el mismo prefijo. No sobreviven a un traspaso en el que el Agente B es un modelo diferente, un proceso diferente, una máquina diferente o incluso simplemente un contexto_llama diferente: el blob KV está vinculado al contexto local. ILCP-para-agentes es explícitamente portátil entre procesos por construcción, porque el objeto transportado es un resumen aprendido en un espacio latente portátil, no un blob KV en el diseño de memoria privada del motor. SwarmKV (Parte 1 de esta serie). Primo más cercano en el trabajo del mismo autor, con una diferencia fundamental: SwarmKV envía el mismo caché KV a N ramas que comparten un documento dentro de una ejecución de canalización. ILCP-para-agentes va en la otra dirección: persiste el estado a lo largo de los saltos donde el trabajo del Agente B es diferente del del Agente A. SwarmKV es "calcular una vez, desplegarse en abanico dentro de una ejecución". ILCP para agentes es "comprimir una vez, transferir entre saltos". Juntos cubren ambos ejes del problema del recómputo redundante. SGLang RadixAtención. Uso compartido de prefijos en forma de árbol dentro de un tiempo de ejecución de servicio: excelente para muchas solicitudes con prefijos compartidos, nuevamente con alcance en el tiempo de ejecución. No está diseñado para entregar un resumen portátil y tolerante a la versión del modelo a un proceso diferente que ejecuta un agente especializado diferente. Memoria de generación aumentada de recuperación (RAG). Almacena fragmentos de texto en una base de datos vectorial y los recupera en el momento de la consulta. Es útil, pero la unidad de transferencia es el texto, lo que significa que el receptor todavía tiene que tokenizar y precompletar. ILCP transfiere una información latente aprendida que el receptor consume a través de inputs_embeds, omitiendo por completo el tokenizador y el llenado previo del lado del texto del contenido persistente.

Intuición de una sola línea: el almacenamiento en caché de prefijos es un truco en tiempo de ejecución para el mensaje repetido de un usuario; RAG es una base de datos de texto que el modelo aún debe leer cada vez; SwarmKV es un despliegue de KV dentro de la ejecución; ILCP es la primitiva arquitectura de salto cruzado que no lo son todas, extraída de un artículo sobre 6G revisado por pares porque esa industria lo necesitaba antes. Problemas diferentes, primitivos complementarios, frecuentemente implementables conjuntamente en el mismo edificio.

7. Giro de la trama: esto no es un giro de la trama (el presentador de telecomunicaciones, lo dijo claramente)

Esta es la sección donde, en las Partes 1 a 3, confesé que el trabajo de la GPU era en secreto un problema de telecomunicaciones disfrazado. En la Parte 4 ya no es una confesión: la base del código es el disfraz que se quita del papel.

Para lectores sin experiencia en 3GPP, aquí está el anillo decodificador de un párrafo. En una red móvil 5G o 6G, un teléfono (el UE, equipo de usuario) recibe servicio de una estación base (gNB) a la vez. Cuando el teléfono se mueve, finalmente se entrega a un nuevo gNB. Para realizar bien esa transferencia, la red debe predecir qué gNB debe ser atendido por el teléfono a continuación. Los enfoques aprendidos modernos hacen esa predicción con una red neuronal gráfica (GNN) sobre la topología local y un módulo recurrente (normalmente un GRU) sobre las mediciones de radio recientes del teléfono. El estado oculto en evolución del teléfono: "¿está caminando? ¿está en un tranvía? ¿está a punto de perder su línea de visión?". contexto: vive en ese GRU. En el momento de la entrega, ese estado de GRU se descarta y el gNB objetivo tiene que reinicializar el estado recurrente por UE y reconstruirlo a partir de las pocas mediciones que acaba de recibir. El periódico llama a esto el arranque en frío posterior a la entrega. ILCP es el protocolo que lo soluciona: comprime el estado de GRU del lado de origen con un β-VAE, transporta el estado latente a través de la interfaz estándar 3GPP Xn (el bus de mensajes entre estaciones base) y lo proyecta nuevamente en el espacio de estado del gNB de destino en el momento de la entrega a través de un MLP controlado aprendido. Todo encaja en una actualización diferencial de 128 bytes respaldada por el mensaje de SOLICITUD DE ENTREGA existente.

Lea ese párrafo y la arquitectura de las secciones 3 y 4 de esta publicación uno al lado del otro. Dígame con seriedad que estos son problemas diferentes.

Transferencia de 6G NR (en el gNB) ILCP para agentes (en el LLM) Historial de medición y movilidad de UE en el contexto de trabajo del gNBA de origen (resumen oculto agrupado) Estado recurrente de GRU de 128 atenuaciones h_u en el vector oculto agrupado de gNB4096 atenuado s_A en el remitente El compresor β-VAE codifica h_u en un compresor β-VAE latente de 32 atenuaciones s_A a una carga útil FP32 de 128 bytes latente a través de 3GPP Xn SOLICITUD DE ENTREGA Transporte Bytes de carga útil a través de transporte en proceso (independiente del protocolo de red en V1) El MLP cerrado por gNB de destino proyecta el estado latente en el espacio de estado de destino El MLP cerrado proyecta z en K tokens de memoria en el espacio de incrustación de LM Combinado a través de h_new = LayerNorm(decoded_h + γ ⊙ MLP([decoded_h, x_new]))Combinado a través de torch.cat([memory_tokens, q_embeds]) alimentando inputs_embedsReduce la brecha de inicio en frío posterior a HO (papel: pico +13,3 pp, promedio +5,1 pp)Reduce el inicio en frío de transferencia (la medición del lado del agente es una hoja de ruta, aún no enviada)Elimina los traspasos de ping-pong en la prueba división (artículo: 0,0 % frente a 6,5 %) Debería reducir los bucles de corrección de seguimiento “el agente B no entiende lo que A quiso decir” (la medición del lado del agente es la hoja de ruta)

La columna de la izquierda está publicada, revisada por pares, medida en la prueba de manejo 4G/5G de Viena y aceptada en el taller AI4NextG en ICML 2026. La columna de la derecha es el cableado V1 en ilcp-for-agents más un "todavía" honesto junto a cada afirmación de medición. Ese mapeo es la única razón por la que existe esta publicación.

8. Advertencias honestas (porque los comentarios van llegando)

Si vino aquí para encontrar el problema de este proyecto, felicidades por llegar hasta aquí. Para ayudarle, desde la sección LIMITACIONES del archivo README y los comentarios del código en línea:

No hay recibos numéricos del lado del agente en V1. Esta es la mayor advertencia y merece estar en la cima. El ilcp-for-agents V1 del lado del agente incluye cableado y un toy data/toy_handoff.json con cinco ejemplos evaluados bajo una estricta métrica de coincidencia exacta. No hay una campaña de referencia de tres pruebas del lado del agente, ni una tabla de latencia p99, ni un barrido de bytes por carga útil, ni un estudio de calidad frente a un conjunto de datos de control de calidad real. Cada afirmación numérica en esta publicación proviene del documento 6G, etiquetado en consecuencia, y los números del lado del agente están explícitamente en la hoja de ruta. No estoy blanqueando recibos de RAN como recibos de LLM. Si vino aquí esperando "el punto de referencia del agente V1", aún no existe, y pretender lo contrario traicionaría toda la tesis de los recibos honestos de esta serie. Estado con pérdidas. V1 mueve un resumen oculto agrupado, no activaciones completas ni un tensor KV. El cuello de botella de β-VAE es intencionado, pero es un cuello de botella. Existe un riesgo real de que se omitan detalles importantes para la tarea del receptor, y la forma correcta de descubrir qué se está omitiendo es ejecutar las pruebas comparativas del lado del agente que la V1 aún no ha enviado. El archivo README lo dice claramente. Métrica de juguete. La coincidencia exacta con cinco ejemplos escritos a mano es una verificación de cableado, no una afirmación de control de calidad de dominio abierto. Capta "el modelo produjo una cuerda" y "el mazo de cables conectó el prefijo correctamente". No capta "es buena la respuesta". Reemplazar el JSON de juguete con una tarea real pendiente es el punto número 1 de la hoja de ruta. Transporte en proceso en V1. El límite de transporte es lógicamente explícito (TransportPayload es un paso deliberado de empaquetar/desempaquetar), pero el cable V1 es torch.Tensor.detach().to('cpu'), no una llamada de red real. Un gRPC real o un búfer de anillo de memoria compartida es la hoja de ruta, detrás de la misma interfaz estable para que los sitios de llamadas no cambien. Pascal + bits y bytes. El archivo README es explícito en cuanto a que la carga de NF4 de 4 bits a través de bitsandbytes puede no estar disponible o ser inestable en algunas pilas Pascal sm_61. La opción alternativa es torch_dtype=torch.float16 en GPU o torch.float32 en CPU, o configure ILCP_MODEL_ID en un modelo de instrucción más pequeño. Se debe revelar cualquier ruta que realmente se haya ejecutado en su ejecución de recibos; el README coloca esa divulgación en el archivo narrativo de recibos, no en la métrica publicada. Receptor congelado. V1 trata el receptor LM como congelado y adapta solo el proyector. Esa es la apuesta más barata posible y es el punto de partida correcto, pero un mapeo más capaz podría permitir una ligera adaptación del lado del receptor. El artículo de radio hace lo análogo a la adaptación del lado del receptor a través de la combinación cerrada h_new = LayerNorm(decoded_h + γ ⊙ MLP([decoded_h, x_new])), donde x_new es el contexto recién observado del gNB objetivo. Esa ecuación es la forma exacta que probablemente debería adoptar una adaptación del receptor del lado LLM, y está en la hoja de ruta. La agrupación de remitentes es un resumen de un solo vector. El grupo medio enmascarado sobre los estados ocultos de la capa final es el grupo V1 aprobado. No es la única opción (existen agrupaciones de último token, resúmenes agrupados de atención o un pequeño agrupador aprendido) y la V1 no afirma explícitamente que la media enmascarada sea óptima. Afirma que es reproducible y fácil de auditar. La sección 3 del artículo de radio hace la elección análoga de “resumen único de tamaño fijo por transferencia” por la misma razón: es el contrato más simple que se puede medir.

Todo lo que figura en esta lista está en la hoja de ruta. Nada de esto cambia el reclamo arquitectónico. El objetivo de ponerlo por escrito es que no debería tener que buscarlo, y en el momento en que una publicación de blog de referencia oculta sus advertencias, es el momento en que sus números dejan de ser confiables. (La Parte 1 decía exactamente esto en su propia sección de advertencias honestas. La Parte 4 hereda la política palabra por palabra).

9. El techo V1 y el final de la serie

Esta es la parte final. No existe una Parte 5 a la que aplazar los problemas difíciles. Entonces, en lugar de apuntar hacia adelante, esta sección apunta hacia atrás a lo largo de toda la serie y pregunta qué enviamos realmente.

La tesis era sencilla y la forma de cuatro partes se mantenía:

Parte 1: Precarga redundante. SwarmKV: ejecute prefill una vez, distribuya el caché KV a muchas ramas que comparten el mismo documento. La solución fue "calcular una vez, copiar los bytes". Ahorró un 48,69 % de extremo a extremo y un 98,09 % de la latencia de activación de la segunda rama en la GTX 1080 canónica. Parte 2: espera redundante. Kube-TimeSlice-Profiler: cuando muchos agentes comparten una GPU a través del time-slicing de Kubernetes CUDA, la mediana miente y el p99 dice la verdad. La solución no fue "nunca compartir" (compartir es la forma en que un enjambre de agentes proporciona su silicio) sino "medir la cola y dejar de confiar en la fase de cápsula". La misma GPU canónica, el mismo modelo clase Qwen, una pequeña herramienta honesta que convierte “la GPU se siente lenta” en un factor de degradación con tres decimales. Parte 3: viajes de ida y vuelta de CPU redundantes. CUDA-TopK-Retrieval: el salto de recuperación RAG agente quiere permanecer en la GPU. La solución fue un kernel CUDA de 343 líneas que mantiene similitud + Top-K en el dispositivo, hasta 8,57 veces más rápido de extremo a extremo en la misma GPU canónica en los valores K que realmente importan, con el techo K=100 documentado honestamente. Parte 4: Reconstrucciones de contexto redundante. ILCP para agentes: las transferencias de agentes actualmente se eliminan y se reconstruyen el contexto. La solución es un protocolo de compresión → transporte → proyecto extraído, casi línea por línea, de un documento de transferencia 6G revisado por pares. V1 envía el cableado; Las mediciones del lado del agente son un trabajo futuro explícito. Lo transferible es la arquitectura, no los números de radio.

Cuatro partes, cuatro tipos de trabajo redundante, una lección subyacente: negarse a volver a calcular supera a cualquier algoritmo inteligente. Embalaje de contenedores, atención de paginación, decodificación especulativa, enrutamiento MoE, mezcla de profundidades, todo realmente impresionante. Ninguno de ellos te ahorra nada comparado con simplemente no hacer el mismo trabajo dos veces. La mayoría de los sistemas modernos trabajan duro. Los bien diseñados trabajan menos.

Y una lección más, que no aprecié hasta que me senté a escribir la Parte 4: las buenas ideas de infraestructura migran entre industrias antes de migrar entre equipos. Transmisión celular, combinación suave HARQ, división de tiempo OFDMA, libros de códigos de haces MIMO, transferencia de estado posterior a la transferencia: los cuatro cuellos de botella que abordó esta serie fueron aquellos con los que la red de acceso de radio se topó primero, a veces veinte años antes de que la multitud de LLM tuviera un nombre para ellos. La parte 1 fue transmitida por SIB con un disfraz de transformador. La parte 2 fue TDMA en un ConfigMap de Kubernetes. La parte 3 fue la selección de haces del lado UE a través de un kernel CUDA. La parte 4 fue la persistencia del estado del lado Xn a través de PyTorch. Década diferente, pila de protocolos diferente, misma forma de problema.

Esa era la serie. No pretendo que sea una ingeniería terminada: cada parte tiene una V2 que vale la pena escribir, cada repositorio tiene una hoja de ruta más larga que su README, pero la tesis de cuatro partes está en la página y la misma GTX 1080 canónica está en los recibos al final de cada publicación. Ingeniería de sistemas orientada a la producción, validada en una GPU económica. Ese fue siempre el punto.

10. envolver

Si construye una infraestructura LLM agente para ganarse la vida: observe cómo su canalización de múltiples saltos se transfiere entre agentes especializados. Si el salto es una concatenación de cadenas seguida de una tokenización y recarga previa en el receptor, usted está pagando el impuesto de arranque en frío. La solución no requiere nuevos trucos con transformadores; requiere aceptar que la unidad correcta de transferencia entre agentes es un resumen aprendido, no una cadena de mensajes.

Si construye sistemas de telecomunicaciones para ganarse la vida: el documento de entrega de 6G debajo de la Parte 4 es el único recibo revisado por pares en todo este proyecto, y se encuentra debajo de las cuatro partes como un recordatorio honesto de que el mundo de la radio ha estado resolviendo estos problemas de arquitectura durante veinte años, mientras que el mundo LLM todavía estaba discutiendo sobre plantillas rápidas. Ven aquí. La computación es excelente, los plazos son más suaves que los suyos y el problema del arranque en frío resulta familiar.

Si es un principiante que ha estado leyendo esta serie y llegó hasta la Parte 4: felicitaciones, ahora comprende más por qué la inferencia de IA agente es más difícil que el 80% de las personas que la construyen para ganarse la vida. También comprende por qué “el cuello de botella de este mes es X” rara vez es un problema nuevo; casi siempre es un problema antiguo convertido en un vocabulario nuevo. Ve a buscar el viejo problema, porque probablemente alguien ya lo resolvió para que tú no tengas que hacerlo.

Descargo de responsabilidad: las ilustraciones de este artículo se generaron utilizando IA (Claude Opus 4.8). Son ilustrativos, no fotográficos, y cualquier etiqueta visible dentro de las imágenes está estilizada en lugar de autorizada; consulte el cuerpo del artículo y el código mismo para obtener nombres precisos de funciones, valores métricos y detalles de arquitectura.