Yeda AI Tips · #154

English

Registra un hash del arreglo de mensajes antes de cada llamada

Tu agente de IA no es tonto. Tu código está editando su memoria a sus espaldas. El modelo responde perfecto en un playground limpio y luego se descarrila apenas pasa por tu app. Antes de reportar un bug contra el modelo, mira lo único que tú controlas: el arreglo de mensajes (messages array) que envías en cada llamada.

Por qué el modelo está bien pero tu agente no

Las APIs de chat son sin estado (stateless). El proveedor no guarda memoria de tu conversación — tú eres dueño del historial completo y reenvías toda la lista de mensajes en cada request (Anthropic y OpenAI funcionan así). Ese diseño es limpio, pero significa que cada capa entre tu usuario y el modelo tiene la oportunidad de tocar el arreglo primero: un resumidor que recorta turnos viejos, un retriever que inyecta contexto, un middleware que reordena mensajes de sistema, un reintento que descarta el último turno. El modelo solo ve el arreglo que le entregas. Si ese arreglo está silenciosamente mal, la respuesta del modelo está silenciosamente mal — y parece que el modelo alucinó.

La auditoría de una línea: haz un hash del historial

No puedes revisar a ojo un arreglo de 40 mensajes en cada llamada. Así que no lo hagas. Calcula un hash estable de los mensajes justo antes de enviarlos, y regístralo:

import hashlib, json

def messages_fingerprint(messages):
    blob = json.dumps(messages, sort_keys=True, ensure_ascii=False)
    return hashlib.sha256(blob.encode("utf-8")).hexdigest()[:12]

fp = messages_fingerprint(messages)
logger.info("llm.call turns=%d fp=%s", len(messages), fp)
response = client.chat.completions.create(model=MODEL, messages=messages)

Ahora la regla es trivial de verificar: el hash solo debería cambiar cuando se agrega un turno nuevo. Si el fingerprint cambia entre dos llamadas pero no se agregó ningún turno de usuario o de asistente, alguna capa reescribió el historial. sort_keys=True hace que la serialización sea independiente del orden, así que el orden de las claves nunca dispara una falsa alarma — un hash distinto significa que el contenido o la forma del arreglo realmente cambió.

Leer la señal

Lo que vesLo que significa
El hash cambia, turns subió en 1Normal — se agregó un turno nuevo.
El hash cambia, turns sin cambiosUna capa editó un turno existente en su lugar.
El hash cambia, turns bajóAlgo descartó o truncó el historial.
El hash del mensaje de sistema difiere entre llamadasSe rompió el prompt caching — cada llamada es un cache miss.
Mismo fingerprint, respuesta incorrectaAhora puedes confiar en el arreglo — investiga el modelo o los parámetros.

Esa última fila es la verdadera ganancia: el fingerprint te deja descartar la plomería. Una vez que el hash es estable y correcto, te ganaste el derecho de culpar al modelo.

Trucos avanzados

messages[0] (o el campo system). Un prefijo de sistema idéntico byte a byte es la clave del prompt caching; si ese hash se mueve — un timestamp interpolado, un request ID, un nombre de usuario — estás pagando el precio de input completo en cada llamada y probablemente no lo sabes.

turnos pero hashes distintos, registra un diff compacto del arreglo (o los hashes por mensaje) para ver cuál turno fue mutado, no solo que algo lo fue.

el arreglo en el límite, y verifica que el fingerprint solo avance cuando agregas. Esto atrapa una regresión que corrompe el contexto en CI en lugar de en producción.

de la llamada de red — idealmente en el wrapper del cliente. Cualquier cosa registrada antes de un middleware no puede ver lo que ese middleware hizo.

Recursos

Yeda AI Tips — un tip de IA al día te libera del trabajo tedioso.