CommitLLM: cómo verificar una inferencia de un LLM
Las APIs de LLM te piden que confíes en que el proveedor corrió el modelo y la configuración que anuncia. CommitLLM agrega recibos criptográficos y auditorías sin el costo de un prover de conocimiento cero.
Sobre la imagen Veintisiete antenas registran cada una la misma señal, y el conjunto solo confía en aquello en lo que coinciden. CommitLLM le pide a un proveedor de LLM el mismo tipo de registro verificable de forma cruzada. El radiotelescopio Very Large Array en las Llanuras de San Agustín, Nuevo México, 2002. Imagen: Jesse Allen, NASA Earth Observatory, dominio público.
Traducción automática del original en inglés, todavía sin revisar. Leer el original.
Mandás un prompt a una API de un LLM. El proveedor dice que corrió Llama 70B. Tal vez lo hizo. Tal vez sirvió un modelo más chico para ahorrar plata, cambió la cuantización, modificó la configuración de decodificación o retocó la respuesta después de generarla. Hoy en general no tenés forma de saberlo. Recibís texto, una factura y una promesa.
Para un uso casual, una promesa muchas veces alcanza. Para compras empresariales, sistemas regulados, evaluación de benchmarks o flujos de agentes que toman decisiones con consecuencias, no alcanza. Si importa qué modelo está detrás de la respuesta, “confiá en nosotros” no es una interfaz satisfactoria.
Hoy tenés dos opciones poco satisfactorias. El fingerprinting estadístico te puede dar evidencia, pero no una verificación exacta por respuesta. Las pruebas de conocimiento cero (zero-knowledge proofs) te pueden dar garantías mucho más fuertes, pero el costo del prover todavía es demasiado alto para servir en producción. O tenés señales débiles, o pruebas fuertes que no podés pagar.
Construimos CommitLLM para ocupar ese hueco. El proveedor mantiene el camino normal de servicio en GPU. Sin circuito de prueba. Sin generación de una prueba por respuesta. El modelo responde normalmente, devuelve un recibo compacto y solo abre datos internos de la traza si el cliente pide una auditoría.
#Cómo funciona una respuesta auditada
A alto nivel, el protocolo es simple:
- El proveedor se compromete con la superficie de despliegue: pesos del modelo, cuantización, tokenizer, chat template, política de decodificación y post-procesamiento.
- El cliente manda un prompt y recibe tanto la salida del modelo como un recibo que vincula esa respuesta al despliegue comprometido.
- La mayoría de las veces, eso alcanza. El camino normal sigue siendo rápido.
- Si la respuesta importa, el cliente desafía tokens y estados internos específicos.
- El proveedor abre los datos de la traza pedidos, y el verificador los chequea en CPU contra el modelo y la configuración comprometidos.
La idea no es probar cada inferencia de antemano. La idea es que hacer trampa sea riesgoso y barato de detectar, sin obligar al proveedor a operar una granja de pruebas criptográficas.
#Por qué es lo suficientemente barato como para importar
La observación práctica es que los transformers pasan la mayor parte del tiempo haciendo multiplicaciones de matrices. Si podés chequear esas multiplicaciones de forma barata, el resto se vuelve manejable.
El truco que hace que esto funcione es viejo. Freivalds lo publicó en 1977. Te da una forma de testear si una multiplicación de matrices se hizo correctamente sin recalcularla entera.
Supongamos que el proveedor dice que calculó z = W @ x para alguna matriz de pesos pública W. Recalcular W @ x directamente es caro. Pero si el verificador tiene un vector aleatorio secreto r y precalculó v = r^T @ W, entonces chequear si v . x == r^T . z cuesta solo un producto escalar. Si el proveedor usó los pesos equivocados o produjo una salida equivocada, el chequeo falla con probabilidad abrumadora.
Eso cubre la capa externa cara del transformer: W_q, W_k, W_v, W_o, W_gate, W_up, W_down y LM_head. Las operaciones restantes, RMSNorm, RoPE, SiLU y los puentes de cuantización, son lo suficientemente chicas como para reproducirlas exactamente.
#Qué vincula el recibo
El recibo no vincula solamente que “corrió algún modelo”. Vincula toda la superficie que cambia lo que sale:
- Identidad del modelo: una raíz de Merkle sobre el checkpoint
- Esquema y configuración de cuantización
- Tokenizer, chat template, preprocesamiento
- Política de decodificación: temperature, top-k, top-p, penalizaciones, condiciones de corte
- Post-procesamiento de la salida
Si cambia cualquiera de estas cosas, cambia el recibo. El proveedor se compromete antes de saber qué tokens y qué capas va a desafiar el verificador.
#Dónde las garantías son exactas y dónde no
Somos honestos sobre lo que el protocolo puede y no puede hacer.
Exacto. Matmuls de la capa externa (Freivalds), puentes de cuantización, lookup de embeddings, la cola del token final a partir de un estado de frontera capturado, vinculación del LM head, logits, reproducción de la decodificación, reproducción de la política de salida. Verificación algebraica o recálculo canónico. Si está mal, el chequeo falla.
Aproximado. El interior de la atención. La atención nativa en FP16/BF16 no es reproducible bit a bit entre GPUs. Restringimos la atención desde ambos lados (Q/K/V verificados en la capa externa a la entrada, salida post-atención comprometida a la salida), pero no pretendemos que sea exacta.
Estadístico. La procedencia del prefijo/KV en el modo de auditoría de rutina. La vinculación del compromiso es exacta, pero las posiciones no abiertas quedan cubiertas por muestreo de desafíos. La auditoría profunda lleva esto a exacto.
Fail-closed. Todo lo que el verificador no sabe cómo reproducir se rechaza. Sin fallbacks silenciosos de mejor esfuerzo.
#Números
El prototipo agrega aproximadamente un 12-14% de overhead durante la generación. Ese es el primer número importante, porque significa que el camino normal de servicio sigue pareciendo un servicio normal. No estás reemplazando la inferencia por un sistema de pruebas. Le estás agregando auditabilidad.
Para Llama 70B, la auditoría de rutina cuesta alrededor de 1,3 ms por token desafiado, mientras que una auditoría completa de un solo token cuesta alrededor de 10 ms. La verificación corre en CPU. No hace falta una GPU del lado del cliente. Ese es el segundo número importante: el verificador puede ser liviano aunque el modelo no lo sea.
En el camino de reproducción corregido para Qwen2.5-7B-W8A8 y Llama-3.1-8B-W8A8, la diferencia en la atención más allá de 1k tokens ya es estrecha: L_inf de 8 y 9 en el peor caso, con más del 99,8% de los elementos dentro de un mismo bucket de cuantización. Dicho en simple: la única parte que no decimos que sea exacta ya está confinada a un corredor estrecho.
#Por qué no ZK
Las pruebas ZK te dan un objeto de prueba transferible que cualquiera puede verificar. Esa es una propiedad más fuerte que la que ofrece CommitLLM. El costo es que el overhead del prover ZK todavía es órdenes de magnitud demasiado alto para servir LLMs en producción.
CommitLLM hace una apuesta distinta: auditoría interactiva, clave del verificador en manos del cliente, overhead chico en el camino normal. Una transcripción de auditoría completamente revelada puede ser rechequeada por terceros, pero el recibo en sí no es una prueba sucinta. Para empresas, despliegues regulados y cómputo descentralizado, el modelo interactivo alcanza y la economía funciona hoy.
#Trabajo pendiente
Necesitamos más familias de modelos además de Qwen y Llama, un análisis más ajustado de la libertad adversarial después del corredor de atención, una procedencia de KV más fuerte y una formalización en Lean de las propiedades centrales del protocolo.
La infraestructura de LLMs hizo una paz extraña con la imposibilidad de verificar. Un proveedor pone el nombre de un modelo en un dashboard y el cliente lo acepta porque no hay una alternativa práctica. No creo que ese equilibrio dure. Si la procedencia del modelo importa, la interfaz no debería ser un logo y una promesa. Debería ser un recibo y la posibilidad de auditarlo.
El paper, el código y el roadmap son públicos.
Escrito con un LLM, como todo lo de este sitio. Las ideas y los errores son míos. Cómo escribo (en inglés).