La monitorización tradicional te dice que una petición tardó 4 segundos y devolvió HTTP 200. Para una aplicación con LLM, eso casi no sirve de nada. La respuesta podría ser errónea, el recuperador podría no haber encontrado nada relevante, el agente podría haber llamado once veces a la misma herramienta y la petición podría haber costado cuarenta céntimos. La observabilidad de LLM consiste en ver qué pasó por dentro: prompts, contexto recuperado, llamadas a herramientas, tokens, latencia por paso y, en última instancia, calidad. Esta guía muestra qué capturar, cómo estructurarlo con OpenTelemetry y cómo usarlo en el día a día.
Por qué las aplicaciones LLM necesitan otra observabilidad
Los sistemas con LLM tienen propiedades que el APM clásico no gestiona bien:
- No determinismo. La misma entrada puede producir salidas distintas; para depurar necesitas el prompt y la respuesta reales.
- Pipelines de varios pasos. Una respuesta RAG implica reescritura de la consulta, embedding, búsqueda, reranking y generación. Un agente puede dar decenas de pasos. Los fallos se esconden en medio.
- La calidad no es binaria. Una respuesta 200 con una respuesta alucinada es un fallo que ninguna tasa de errores muestra.
- El coste es por petición. El uso de tokens varía en órdenes de magnitud entre peticiones y es una métrica de primer nivel.
- Contenido sensible. Los prompts contienen datos de usuarios, documentos y a veces secretos; registrarlos requiere cuidado.
Qué capturar
Para cada llamada al LLM, como mínimo:
| Campo | Por qué |
|---|---|
| Modelo y proveedor, parámetros (temperatura, máximo de tokens) | Reproducir y comparar |
| Nombre y versión de la plantilla de prompt | Correlacionar la calidad con los cambios de prompt; consulta prompt engineering |
| Tokens de entrada y salida, tokens cacheados | Coste y eficiencia de la caché |
| Latencia: tiempo hasta el primer token, total | Experiencia de usuario |
| Motivo de fin (stop, length, tool use, refusal) | Seguimiento de truncamientos y rechazos |
| Llamadas a herramientas con argumentos y resultados | Depuración de agentes |
| IDs y puntuaciones de los documentos recuperados | Depuración de RAG |
| IDs de usuario/sesión/cliente (seudonimizados) | Agrupación, coste por cliente |
| Feedback y puntuaciones de evals añadidos después | Calidad a lo largo del tiempo |
Guarda el prompt y la respuesta completos donde la política lo permita, con límites de retención y control de acceso. Sin ellos, la mayor parte de la depuración es adivinar.
Estructúralo como trazas
La traza de una petición de usuario debe reflejar el pipeline. Para un chat RAG:
trace: POST /api/chat (2.9 s, $0.011)
├─ span: rewrite_query llm claude-… in 420 / out 35 tok 310 ms
├─ span: embed_query embedding 45 ms
├─ span: hybrid_search db top_k=50 80 ms
├─ span: rerank reranker 50 → 8 190 ms
└─ span: generate_answer llm in 6,200 (cached 4,800) / out 310 tok 2.2 s
attributes: prompt=support_answer@v14, finish_reason=stop
En un agente, cada iteración del bucle se convierte en un span con la decisión del modelo y spans hijos para las ejecuciones de herramientas. En sistemas multiagente, cada subagente es una traza hija del span del orquestador. Esta estructura permite responder preguntas como "¿qué paso se volvió más lento tras la versión de la semana pasada?" o "¿con qué frecuencia llama el agente dos veces seguidas a search_orders?".
Las convenciones semánticas GenAI de OpenTelemetry
OpenTelemetry tiene convenciones semánticas para IA generativa que estandarizan los nombres de spans y los atributos para llamadas a modelos, agentes y herramientas: atributos como gen_ai.request.model, gen_ai.usage.input_tokens, gen_ai.usage.output_tokens, gen_ai.response.finish_reasons y nombres de operación para chat, embeddings y ejecución de herramientas. Usarlas significa que la telemetría de tus LLM pasa por el mismo Collector y los mismos backends que el resto de tu configuración de OpenTelemetry, y que las herramientas que entienden las convenciones pueden mostrarla correctamente.
Un span manual en Python:
from opentelemetry import trace
tracer = trace.get_tracer("support-bot")
def generate_answer(messages, prompt_version: str):
with tracer.start_as_current_span("chat claude") as span:
span.set_attribute("gen_ai.operation.name", "chat")
span.set_attribute("gen_ai.request.model", MODEL)
span.set_attribute("app.prompt.version", prompt_version)
resp = client.messages.create(model=MODEL, max_tokens=800, messages=messages)
span.set_attribute("gen_ai.usage.input_tokens", resp.usage.input_tokens)
span.set_attribute("gen_ai.usage.output_tokens", resp.usage.output_tokens)
span.set_attribute("gen_ai.response.finish_reasons", [resp.stop_reason])
return resp
En la práctica, las librerías de autoinstrumentación (por ejemplo, OpenLLMetry y OpenInference) parchean los SDK y frameworks habituales y emiten estos spans por ti. Algunas convenciones siguen marcadas como experimentales; fija las versiones de las librerías y cuenta con que los nombres de los atributos evolucionen.
Herramientas
| Herramienta | Tipo | Notas |
|---|---|---|
| Langfuse | Open source, autoalojable + nube | Trazas, gestión de prompts, evals, seguimiento de costes; ingesta OpenTelemetry |
| Arize Phoenix | Open source | Trazas mediante OpenInference, evals, herramientas de datasets |
| LangSmith | SaaS (autoalojado en enterprise) | Integración profunda con LangChain/LangGraph |
| Tu APM actual (Grafana, Datadog, Honeycomb…) | Backend OTel | Bueno para latencia y coste; más débil para revisar a nivel de prompt |
Una configuración habitual: emite OpenTelemetry una vez, envía las métricas de infraestructura y los spans a tu backend actual y manda los spans GenAI (con contenido) a una herramienta específica de LLM para el análisis a nivel de prompt. Alojarla tú mismo importa cuando los prompts contienen datos personales o confidenciales; consulta privacidad en aplicaciones LLM.
Métricas y paneles
Construye un panel por funcionalidad con LLM que incluya:
- Volumen: peticiones, conversaciones, ejecuciones de agentes.
- Latencia: p50/p95 del tiempo hasta el primer token y total; latencia por paso en los pipelines.
- Coste: tokens y dinero por petición, usuario, cliente y funcionalidad; tasa de aciertos de caché. Úsalos para guiar la optimización de costes de LLM.
- Fiabilidad: errores del proveedor, límites de frecuencia (429), timeouts, reintentos, fallbacks; consulta fiabilidad de las APIs de LLM.
- Comportamiento: motivos de fin (tasa de truncamiento), tasa de rechazos, tasa de errores de herramientas, pasos por ejecución de agente.
- Calidad: tasa y puntuación del feedback de usuarios, puntuaciones de evals en línea, tasa de escalado a personas.
Alerta sobre lo que notan los usuarios o lo que cuesta dinero: latencia p95, tasa de errores, picos repentinos de coste por cliente y ejecuciones de agentes que superan el límite de pasos.
Conectar la observabilidad con la calidad
Las trazas valen mucho más cuando se conectan con la evaluación:
- Evals en línea. Ejecuta comprobaciones automáticas baratas sobre una muestra de trazas de producción —fundamentación, validez del formato, infracciones de políticas— y añade las puntuaciones a las trazas.
- Feedback. Asocia los pulgares arriba/abajo y los comentarios a la traza que produjo la respuesta.
- Datasets a partir de producción. Filtra las trazas con puntuaciones bajas o feedback negativo, revísalas y añade los casos representativos a tu conjunto de referencia.
- Comparación entre versiones. Etiqueta las trazas con la versión de la aplicación y del prompt; compara puntuaciones y costes antes y después de cada versión.
Este bucle —trazas de producción que alimentan los evals offline— es el núcleo del proceso descrito en cómo evaluar aplicaciones LLM.
Depurar con trazas: tres casos típicos
"El bot respondió con seguridad, pero mal." Abre la traza y revisa primero el span de recuperación. En la mayoría de los casos el documento correcto no estaba entre los fragmentos recuperados o quedó por debajo del corte. El arreglo está en el chunking, la búsqueda híbrida o el reranking, no en el prompt; consulta embeddings y chunking.
"Las respuestas van más lentas esta semana." Compara la latencia por span antes y después de la versión. Un culpable típico es un cambio de prompt que movió contenido dinámico al principio, rompiendo el prefijo de caché: los tokens cacheados caen a cero y el coste de entrada y el tiempo hasta el primer token se disparan.
"El agente a veces entra en bucle." Filtra las trazas de agentes con un número de pasos por encima del percentil 95 y léelas. Las llamadas idénticas repetidas a una herramienta suelen apuntar a un mensaje de error poco útil o a una salida de herramienta que no le dice al modelo que la tarea está completa; consulta diseño de herramientas para agentes.
Privacidad y seguridad de la telemetría
Los prompts y respuestas de tu stack de observabilidad son un almacén de datos con datos personales. Trátalos como tal:
- Anonimiza o seudonimiza la PII antes de exportar cuando sea posible (correos, teléfonos, identificadores fiscales); herramientas como Microsoft Presidio ayudan.
- Separa el contenido de los metadatos. Conserva los recuentos de tokens y la latencia durante mucho tiempo, y el contenido durante una ventana de retención corta.
- Restringe el acceso al contenido a las personas que lo necesitan para depurar.
- Nunca registres secretos. Elimina las claves de API y los tokens de los argumentos de las herramientas.
- Ten en cuenta la residencia de los datos al usar herramientas SaaS; los datos de la UE pueden necesitar alojamiento en la UE.
Un plan de despliegue
- Día 1: registra el modelo, los tokens, la latencia, el motivo de fin y la versión del prompt en cada llamada. Incluso una línea de log estructurada es un gran paso.
- Semana 1: añade trazas de OpenTelemetry con las convenciones GenAI a lo largo del pipeline y expórtalas a una herramienta de observabilidad de LLM.
- Semanas 2–3: paneles de coste, latencia, errores y comportamiento; alertas ante picos.
- Mes 2: captura de feedback, evals en línea sobre una muestra y revisión semanal de las trazas con puntuación baja.
Preguntas frecuentes
¿Deberíamos registrar los prompts completos en producción? Normalmente sí, con anonimización, retención corta y control de acceso. Sin el contenido, depurar problemas de calidad es casi imposible.
¿Las trazas añaden latencia? Es despreciable si las exportaciones son asíncronas y por lotes, como hace OpenTelemetry por defecto.
¿Cómo trazamos las respuestas en streaming? Abre el span al recibir la petición, registra el tiempo hasta el primer token como evento o atributo y ciérralo cuando termine el stream, incluido el uso de tokens del último fragmento.
¿Podemos usar nuestro Grafana o Datadog actual? Sí para métricas y latencia. Para leer prompts, comparar versiones y etiquetar trazas, las herramientas específicas de LLM son más productivas.
Fuentes
- OpenTelemetry. Semantic conventions for generative AI systems.
- Documentación de Langfuse.
- Arize Phoenix.
- Traceloop. OpenLLMetry.
- Microsoft. Presidio — data protection and de-identification SDK.
- Hamel Husain. Your AI product needs evals.