Observabilidad de LLM en 2026: Trazas, Evals y Seguimiento de Costos para Agentes AI

La guía definitiva de observabilidad para aplicaciones de LLM y agentes en 2026 -- trazas distribuidas con traces, spans y generaciones, las convenciones semánticas GenAI de OpenTelemetry, instrumentación de agentes con el SDK de Langfuse, seguimiento de tokens, costo y latencia, evaluación con LLM-as-judge, detección de drift y regresiones, gestión de prompts, y dashboards y alertas en producción. Cubre Langfuse, LangSmith, Arize Phoenix y Helicone.

LangfuseLangSmithArize PhoenixOpenTelemetryOpenInferenceTracingLLM-as-JudgeEvalsCost TrackingToken UsageDrift DetectionPrompt ManagementPythonTypeScript

1. ¿Qué es la Observabilidad de LLM?

La observabilidad de LLM es la práctica de instrumentar, capturar y analizar lo que ocurre dentro de una aplicación de LLM o de agentes para poder depurarla, controlar su costo y demostrar su calidad. Una sola petición de un usuario a un agente moderno puede ramificarse en docenas de pasos: construcción del prompt, recuperación, múltiples llamadas al modelo, ejecución de herramientas, reintentos y post-procesamiento. El monitoreo tradicional de aplicaciones registra la petición HTTP y un código de estado; la observabilidad de LLM registra el árbol de ejecución completo y no determinista -- cada prompt, cada completion, cada conteo de tokens, cada latencia, y un score de calidad para la respuesta final.

La disciplina se apoya en tres pilares. Las trazas reconstruyen el árbol causal de una ejecución para que veas exactamente qué prompt produjo qué salida y dónde se gastó tiempo y dinero. Las métricas agregan costo, latencia, uso de tokens y tasas de error a través de miles de peticiones. La evaluación adjunta scores de calidad -- de LLM-as-judge, aserciones de código o revisión humana -- a las trazas para que puedas medir si el sistema realmente está mejorando o empeorando. Juntos convierten una llamada al modelo de caja negra en un sistema depurable y medible.

El ecosistema de 2026 se ha consolidado alrededor de un conjunto pequeño de herramientas -- Langfuse (open-source, MIT), LangSmith (la plataforma gestionada de LangChain) y Arize Phoenix (open-source, OpenInference) -- más un estándar que madura rápido, las convenciones semánticas GenAI de OpenTelemetry, que permiten a cualquier backend de trazas ingerir telemetría de LLM. Esta composabilidad significa que la observabilidad es una capa transversal que se ubica junto a tu framework de agentes en vez de estar atada a él: instrumentas una vez y puedes enviar las mismas trazas a múltiples backends.

2. Por Qué los LLM Rompen el Monitoreo Tradicional

Las herramientas APM clásicas asumen código determinista: la misma entrada produce la misma salida, la latencia es estable y un código de estado 200 significa éxito. Las aplicaciones de LLM violan cada una de esas suposiciones. El mismo prompt puede devolver respuestas distintas en cada llamada, la latencia oscila con la longitud de la salida y la carga del modelo, y una petición puede devolver HTTP 200 mientras el contenido es una alucinación, un rechazo o un JSON malformado. Un dashboard en verde no te dice nada sobre si el modelo realmente está haciendo su trabajo.

Tres propiedades hacen que los sistemas de LLM sean únicamente difíciles de observar. El no determinismo significa que no puedes reproducir un bug reproduciendo una entrada -- necesitas el prompt, modelo, parámetros y completion exactos capturados. El costo es por token y sin límite: un loop de agente descontrolado o una ventana de contexto inflada pueden multiplicar el gasto por 10x sin cambiar el código, así que los conteos de tokens y el costo deben ser telemetría de primera clase, no una idea de último momento. La calidad es subjetiva y sufre drift: un prompt que funcionaba el mes pasado puede degradarse en silencio cuando un proveedor actualiza un modelo detrás de la misma cadena de versión, y no hay excepción que atrapar -- solo un declive lento en la calidad de las respuestas que solo puedes medir si estás puntuando las salidas.

Por eso la observabilidad de LLM agrega un modelo de datos dedicado encima de las trazas ordinarias: una generación (una sola llamada al modelo con su prompt, completion, uso de tokens y costo), una traza (la petición completa), scores (señales de calidad adjuntas a cualquier span), y sesiones y usuarios (para agrupar conversaciones multi-turno). El resto de esta guía muestra cómo capturar esos datos con SDKs reales, estandarizarlos con OpenTelemetry, evaluarlos y alertar sobre ellos en producción.

3. Conceptos Core: Traces, Spans, Generaciones, Scores

Todas las herramientas de observabilidad comparten el mismo modelo de datos subyacente, tomado de las trazas distribuidas y especializado para LLM. Domina estas cuatro primitivas y podrás leer cualquier vista de trazas de Langfuse, LangSmith o Phoenix. Se mapean limpiamente a OpenTelemetry: una traza es un trace, un span es un span, una generación es un span con atributos específicos de LLM, y un score es un atributo o evento adjunto a un span.

ROOT

Traza (Trace)

El registro de nivel superior de una petición a través de tu aplicación -- un turno de chat, una llamada API o una ejecución de agente. Una traza tiene una entrada, una salida, una latencia total, un costo agregado y metadata (usuario, sesión, tags, entorno). Es la unidad que filtras, buscas y compartes. Todo lo demás se anida dentro de ella. En Langfuse una traza también lleva un trace_id estable que puedes adjuntar a tus propios logs para saltar de un evento de negocio directo a la ejecución.

STEP

Span (Observación)

Un span es cualquier unidad de trabajo anidada dentro de una traza: un paso de recuperación, una llamada a herramienta, una función de parsing o un sub-agente completo. Los spans forman un árbol mediante relaciones padre-hijo y cada uno registra su propio tiempo de inicio/fin, entrada, salida y estado. Así es como localizas un bug -- profundizas desde la traza lenta o fallida hasta el span exacto que lo causó, viendo la entrada que lo rompió.

LLM

Generación

Una generación es un span especializado para una sola llamada al modelo. Más allá del tiempo captura el nombre del modelo, los parámetros (temperature, max tokens, herramientas), los mensajes del prompt completos, el completion y el uso de tokens (entrada, salida, cacheados, razonamiento). A partir de los conteos de tokens y una tabla de precios la plataforma deriva el costo automáticamente. Las generaciones son donde ocurre la depuración de prompt-engineering: ves el prompt renderizado exacto, no tu plantilla.

QUALITY

Scores

Un score es una señal de calidad adjunta a una traza o span: un valor numérico, un booleano pasa/falla o una etiqueta categórica, con un comentario opcional. Los scores provienen de evaluadores LLM-as-judge, verificaciones de código deterministas (JSON válido, contiene cita), retroalimentación explícita del usuario (pulgar arriba/abajo) o anotación humana. Los scores son lo que hace medible la calidad en el tiempo y son la base para evals, quality gates de regresión y alertas de drift.

# pip install langfuse   (v3 Python SDK, OpenTelemetry-based)
from langfuse import get_client, observe

langfuse = get_client()  # reads LANGFUSE_PUBLIC_KEY / SECRET_KEY / HOST from env

@observe()                      # this function becomes the root trace
def answer_question(question: str) -> str:
    docs = retrieve(question)   # a nested span (see @observe below)
    completion = call_llm(question, docs)
    # attach a quality score to the current trace
    langfuse.score_current_trace(name="has_citation",
                                 value=1 if "[" in completion else 0)
    return completion

@observe()                      # nested span, auto-parented via OTEL context
def retrieve(question: str) -> list[str]:
    return vector_store.search(question, k=4)

@observe(as_type="generation")  # mark as an LLM generation
def call_llm(question: str, docs: list[str]) -> str:
    prompt = build_prompt(question, docs)
    resp = openai.chat.completions.create(
        model="gpt-5.1", messages=prompt, temperature=0.2)
    # record model + token usage so cost is computed automatically
    langfuse.update_current_generation(
        model="gpt-5.1",
        usage_details={"input": resp.usage.prompt_tokens,
                       "output": resp.usage.completion_tokens})
    return resp.choices[0].message.content

4. Instrumentación con el SDK de Langfuse

Langfuse es la plataforma de observabilidad de LLM open-source (MIT) más adoptada, y su SDK de Python v3 está construido directamente sobre OpenTelemetry -- así que instrumentar tu código también produce spans OTEL estándar. Hay tres formas de instrumentar, y puedes mezclarlas libremente en la misma aplicación. Elige la más ligera que capture lo que necesitas, luego baja a los niveles inferiores para los spans que más importan.

Tres estilos de instrumentación, de menos a más código:

EASIEST

Decoradores (@observe)

El camino más rápido: anota cualquier función con @observe() y se convierte en un span; la más externa se convierte en la traza. El anidamiento es automático vía propagación de contexto de OpenTelemetry, así que obtienes un árbol correcto sin pasar IDs de un lado a otro. Agrega as_type="generation" para llamadas al modelo. Funciona en código síncrono y asíncrono. Ideal para tu propia lógica de negocio y funciones de pegamento.

DROP-IN

Integraciones y auto-instrumentación

Usa el cliente OpenAI envuelto (from langfuse.openai import openai) o el CallbackHandler de LangChain para capturar llamadas al modelo, prompts y uso de tokens con cero código manual. Como el SDK es OTEL-nativo, cualquier instrumentación de OpenTelemetry u OpenInference (Anthropic, LlamaIndex, el Vercel AI SDK) también fluye hacia Langfuse. Ideal para llamadas de frameworks y proveedores que no quieres envolver a mano.

CONTROL

Context managers de bajo nivel

Para máximo control usa los context managers langfuse.start_as_current_span() / start_as_current_generation() para crear spans explícitamente, fijar entradas/salidas, uso y metadata, y enlazar scores. Esto es a lo que recurres dentro de rutas calientes, lógica de reintento personalizada o handlers de streaming donde necesitas registrar el time-to-first-token por separado de la latencia total.

import os
os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-..."
os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-..."
os.environ["LANGFUSE_HOST"]       = "https://cloud.langfuse.com"  # or your self-hosted URL

# 1) Drop-in: the wrapped client traces every call automatically
from langfuse.openai import openai
resp = openai.chat.completions.create(
    model="gpt-5.1",
    messages=[{"role": "user", "content": "Summarize this ticket."}],
)

# 2) Low-level: explicit span with manual usage + a score
from langfuse import get_client
langfuse = get_client()
with langfuse.start_as_current_generation(
        name="classify", model="claude-sonnet-4-5") as gen:
    out = call_model(...)
    gen.update(output=out,
               usage_details={"input": 812, "output": 47})
    gen.score(name="valid_label", value=1)

langfuse.flush()  # ensure spans are exported before the process exits

5. Convenciones Semánticas GenAI de OpenTelemetry

Las convenciones semánticas GenAI de OpenTelemetry son el estándar emergente y neutral de proveedor para la telemetría de LLM. Definen un conjunto común de nombres de span y claves de atributos para que una llamada al modelo instrumentada una vez pueda ser entendida por cualquier backend compatible -- Langfuse, Phoenix, Grafana, Datadog, Honeycomb -- sin mapeo personalizado. A 2026 las convenciones permanecen en estado de Desarrollo en general, pero los spans de cliente (llamada al modelo) se estabilizaron a inicios de 2026 y los spans de agente/herramienta, aunque aún experimentales, han sido estables en la práctica durante el año. Actívate a los atributos más nuevos con la variable de entorno OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental.

La convención se organiza alrededor de un vocabulario pequeño de atributos y tipos de span:

ATTRS

Atributos gen_ai.*

Las claves centrales son gen_ai.system (el proveedor, p. ej. openai, anthropic), gen_ai.operation.name (chat, embeddings), gen_ai.request.model y gen_ai.response.model, parámetros de la petición como gen_ai.request.temperature y max_tokens, y los contadores de uso tan importantes gen_ai.usage.input_tokens y gen_ai.usage.output_tokens. Estandarizar estas claves es lo que permite a un solo dashboard agregar el costo a través de cada proveedor.

SPANS

Tipos de span

Las convenciones nombran tres niveles de span: spans de inference para una sola llamada al modelo (nombrados chat {model}), spans de execute_tool para llamadas a herramientas/funciones, y spans de invoke_agent para un paso de agente. Anidar estos correctamente reproduce el árbol de razonamiento del agente, de modo que un lector puede seguir qué llamada al modelo decidió llamar a qué herramienta con qué argumentos.

CONTENT

Eventos y captura de contenido

El contenido de prompts y completions es verboso y sensible, así que las convenciones lo llevan como eventos de span estructurados (o, en revisiones más nuevas, como los atributos gen_ai.input.messages / gen_ai.output.messages) que puedes desactivar por PII. Esta separación te permite mantener siempre activos los atributos de métrica baratos (modelo, tokens, latencia) mientras condicionas la captura costosa del payload completo detrás de una política de muestreo o redacción.

# Emit GenAI-convention spans with the vanilla OpenTelemetry SDK.
# Any OTEL backend (incl. Langfuse's /otel endpoint) can ingest these.
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(
    OTLPSpanExporter(endpoint="https://cloud.langfuse.com/api/public/otel/v1/traces")))
trace.set_tracer_provider(provider)
tracer = trace.get_tracer("my-app")

with tracer.start_as_current_span("chat gpt-5.1") as span:
    span.set_attribute("gen_ai.system", "openai")
    span.set_attribute("gen_ai.operation.name", "chat")
    span.set_attribute("gen_ai.request.model", "gpt-5.1")
    resp = call_openai(...)
    span.set_attribute("gen_ai.usage.input_tokens", resp.usage.prompt_tokens)
    span.set_attribute("gen_ai.usage.output_tokens", resp.usage.completion_tokens)

6. Instrumentar Agentes y Flujos Multi-Paso

Los agentes son lo más difícil de observar porque una sola petición explota en un árbol de profundidad variable de pasos de razonamiento, llamadas a herramientas y sub-agentes. La meta es una traza cuya forma refleje el flujo de control real del agente, para que una ejecución lenta o una respuesta errónea puedan rastrearse hasta el paso exacto que la causó. Tres técnicas cubren la mayoría de stacks de agentes, y se apoyan sobre los estilos de SDK de la sección 4.

TREE

Spans anidados para pasos y herramientas

Envuelve el loop del agente en un span raíz y cada iteración -- llamada al modelo, ejecución de herramienta, sub-agente -- en un span hijo. Registra el nombre de la herramienta, los argumentos y el resultado en los spans execute_tool y el razonamiento en el span del modelo. El árbol resultante te permite responder las dos preguntas que importan para los agentes: por qué eligió esa herramienta y cuál paso quemó los tokens o el tiempo.

AUTO

Auto-instrumentación de frameworks

La mayoría de frameworks de agentes emiten telemetría que puedes capturar sin cablear a mano. LangGraph y LangChain fluyen a través del CallbackHandler de Langfuse; CrewAI, el OpenAI Agents SDK y LlamaIndex están cubiertos por instrumentadores OpenInference/OTEL; el Claude Agent SDK expone sus propios hooks. Activa el instrumentador una vez y cada paso del agente se convierte en un span.

LINK

Sesiones, usuarios y metadata

Los agentes multi-turno necesitan trazas agrupadas en sesiones y etiquetadas con un id de usuario para que puedas reproducir una conversación completa y calcular el costo por usuario. Adjunta el entorno, la versión de release e identificadores de negocio como metadata. Así también los agentes distribuidos se mantienen coherentes: propaga el contexto de la traza a través de los límites de servicio y proceso para que un sub-agente en otra máquina se anide bajo la misma traza.

# LangGraph / LangChain agent -> Langfuse with zero manual spans
from langfuse.langchain import CallbackHandler
handler = CallbackHandler()

result = agent.invoke(
    {"messages": [("user", "Book the cheapest flight to Bogota")]},
    config={
        "callbacks": [handler],
        # group turns + attribute cost per user
        "metadata": {
            "langfuse_session_id": "conv-2291",
            "langfuse_user_id": "u_4417",
            "langfuse_tags": ["prod", "travel-agent"],
        },
    },
)

# Manual nesting for a custom loop (OTEL context auto-parents children)
from langfuse import get_client
langfuse = get_client()
with langfuse.start_as_current_span(name="agent-run", input=user_msg) as root:
    for step in range(max_steps):
        with langfuse.start_as_current_span(name=f"tool:{tool.name}",
                                            input=args) as tool_span:
            tool_span.update(output=tool.run(args))

7. Seguimiento de Costo, Latencia y Tokens

Como el gasto en LLM se mide por token y crece sin ningún cambio de código, la telemetría de costo y latencia tiene que estar integrada desde el primer día, no atornillada después de la primera factura sorpresa. Una vez que cada generación registra su modelo y uso de tokens, la plataforma deriva el costo, y puedes segmentarlo por usuario, feature, versión de prompt o entorno para encontrar exactamente a dónde van el dinero y los milisegundos.

Cuatro señales a capturar en cada generación:

TOKENS

Uso de tokens

Registra los tokens de entrada, salida, cacheados y (para modelos de razonamiento) de razonamiento por separado. Los SDKs de los proveedores los devuelven en el objeto de uso de la respuesta; la auto-instrumentación los captura por ti. Los tokens de entrada cacheados se facturan a una fracción del precio completo, así que rastrearlos por separado es lo que hace que tus números de costo realmente coincidan con la factura.

COST

Costo desde un modelo de precios

El costo es derivado, no medido: la plataforma mapea (modelo, tipo de token) a un precio por token y multiplica. Langfuse incluye una tabla de precios mantenida y te permite definir modelos y precios personalizados para despliegues self-hosted o fine-tuned. Como el costo se calcula a partir de la cadena de modelo registrada, mantener esa cadena precisa es todo el juego.

LATENCY

Latencia y time-to-first-token

La duración total del span no basta para UIs de streaming. Captura el time-to-first-token (TTFT) por separado del tiempo total de generación, ya que el TTFT es lo que los usuarios perciben como capacidad de respuesta. Rastrea los tokens de salida por segundo para detectar un proveedor degradado, y observa la latencia p95/p99, no el promedio -- la latencia de cola es donde los flujos de agentes se quedan sin tiempo.

SLICE

Agregación y atribución

La recompensa es el agrupamiento: costo por usuario para encontrar a tus grandes consumidores, costo por feature para justificar un cambio de modelo, costo por versión de prompt para atrapar una regresión que duplicó el tamaño del contexto. Los dashboards agregan esto desde las generaciones crudas, y las APIs de métricas los exportan a Grafana o a un data warehouse para reportes de grado financiero.

8. Evals y LLM-as-Judge

Las trazas te dicen qué pasó; la evaluación te dice si fue bueno. Los evals corren en dos modos. Los evals offline corren antes de desplegar: ensamblas un dataset de entradas (y a menudo salidas esperadas), corres tu app sobre cada ítem como un experimento, puntúas los resultados y comparas contra la versión anterior -- un quality gate para CI/CD. Los evals online corren continuamente sobre trazas de producción en vivo, muestreando tráfico real y puntuándolo para que atrapes regresiones en el momento en que llegan a los usuarios. Toda plataforma madura (Langfuse, LangSmith, Phoenix) soporta ambos.

Los scores provienen de tres tipos de evaluador. El código determinista verifica las cosas baratas y objetivas -- JSON válido, contiene una cita, coincidencia exacta, latencia bajo presupuesto. El LLM-as-judge usa un modelo fuerte con una rúbrica para puntuar las cosas subjetivas -- fidelidad al contexto recuperado, relevancia, tono, utilidad -- y devuelve un score más una justificación escrita que puedes auditar. La anotación humana es la verdad de referencia contra la que calibras al juez y la reservas para los casos ambiguos. Combina las tres: usa código donde puedas, el juez donde debas y humanos para mantener honesto al juez.

El LLM-as-judge es poderoso pero tiene modos de falla conocidos que debes diseñar para evitar: sesgo de posición (favorecer la primera respuesta mostrada), sesgo de verbosidad (favorecer respuestas más largas) y auto-preferencia (un modelo calificando más alto a su propia familia). Mitígalos usando un modelo distinto y fuerte como juez, dándole una rúbrica concreta con ejemplos few-shot, pidiéndole una justificación antes del score y verificando periódicamente la concordancia juez-vs-humano. Trata al juez mismo como un sistema que evalúas, no como un oráculo en el que confías ciegamente.

# Offline experiment: run a dataset, score each item with an LLM judge (Langfuse)
from langfuse import get_client
langfuse = get_client()
dataset = langfuse.get_dataset("qa-regression-v3")

def faithfulness_judge(query, answer, context) -> float:
    verdict = openai.chat.completions.create(
        model="gpt-5.1", temperature=0,
        messages=[{"role": "system",
                   "content": "Score 0-1 how fully the ANSWER is supported "
                              "by CONTEXT. Give a one-line reason, then the number."},
                  {"role": "user",
                   "content": f"Q:{query}\nCONTEXT:{context}\nANSWER:{answer}"}])
    return parse_score(verdict.choices[0].message.content)

for item in dataset.items:
    with item.run(run_name="prompt-v12") as root:   # links trace to the dataset run
        out = my_app(item.input)
        root.score(name="faithfulness",
                   value=faithfulness_judge(item.input, out, out_context))
# Compare run "prompt-v12" vs "prompt-v11" in the UI to catch regressions.

9. Comparación de Herramientas

El panorama de observabilidad se ha consolidado en 2026 alrededor de unas pocas herramientas con distintas concesiones en licenciamiento, modelo de instrumentación y profundidad de evals. Así se comparan las opciones principales:

Dimension Langfuse LangSmith Arize Phoenix Helicone MLflow Tracing
License / hosting MIT open source; self-host or cloud Proprietary; managed cloud + self-host enterprise Elastic License 2.0; self-host or Arize cloud Open source; cloud + self-host (maintenance mode) Apache 2.0; self-host or managed
Instrumentation SDK (@observe), integrations, OTEL-native LangChain callbacks, SDK, OTEL ingest OpenInference/OTEL auto-instrumentors Proxy/gateway (swap base URL) + async Autolog + OTEL-compatible tracing
Evals & LLM-judge Built-in judge, datasets, experiments Deep: datasets, evaluators, experiments 50+ research-backed metrics, judge Basic scoring / feedback GenAI eval + scorers
Prompt management Versioned prompts + playground Prompt Hub + playground Prompt playground / versioning Prompt tracking Prompt registry
Cost tracking Maintained price table + custom models Per-run token & cost Token & cost per span Strong (its original focus) Token usage; cost via config
OTEL / standards Native OTEL + GenAI conventions OTEL ingest supported Owns OpenInference conventions OTEL export available OTEL-compatible
Best for Self-hosted, full-stack OSS + prompt mgmt LangChain/LangGraph-native teams Notebook & eval-heavy, drift analysis Quick gateway-level cost/log visibility Teams already on the MLflow platform

Estas herramientas son cada vez más interoperables porque convergen en el mismo formato de cable OpenTelemetry/OpenInference -- puedes instrumentar una vez y distribuir las trazas a más de un backend. Elige por tu restricción principal: Langfuse para un stack self-hosted permisivo (MIT) con trazas, evals y gestión de prompts en un solo lugar; LangSmith si tu equipo vive en LangGraph/LangChain y quiere la integración nativa más profunda; Arize Phoenix para flujos pesados en evals y drift, guiados por notebooks; Helicone para la visibilidad de costo y logs más rápida a nivel de gateway (ahora en modo de mantenimiento tras su adquisición de 2026, así que pesa el soporte a largo plazo); y MLflow Tracing si ya corres la plataforma MLflow. Elijas la que elijas, instrumentar hacia las convenciones GenAI te mantiene portable.

10. Dashboards, Alertas y Detección de Drift

La instrumentación y los evals son entradas; la recompensa operativa son dashboards que muestran la salud de un vistazo, alertas que te avisan antes de que los usuarios se quejen, y detección de drift que atrapa la lenta degradación de calidad única de los LLM. Estos cierran el ciclo desde las trazas crudas de vuelta a la acción.

DASHBOARDS

Dashboards de producción

Rastrea las señales vitales en una sola pantalla: volumen de peticiones, tasa de error, latencia p50/p95/p99 y TTFT, costo total y por usuario, throughput de tokens, y scores de eval promedio en el tiempo -- segmentados por modelo, versión de prompt y entorno. Langfuse y Phoenix incluyen dashboards integrados; para un panel único, exporta métricas vía la API OTEL/metrics hacia Grafana junto al resto de tu infraestructura.

ALERTING

Alertas y SLOs

Define SLOs y alerta sobre incumplimientos: costo por hora por encima de un presupuesto (guarda contra loops descontrolados), tasa de error o timeout por encima de un umbral, regresión de latencia p95, o un score de eval online cayendo por debajo de un piso. Enruta las alertas a Slack/PagerDuty. La alerta más valiosa específica de LLM es una alerta de calidad -- una caída sostenida en los scores del juez -- porque nada más te dirá que el modelo empeoró.

DRIFT

Detección de drift

Los sistemas de LLM se degradan en silencio cuando las distribuciones de entrada cambian o un proveedor actualiza un modelo detrás de una cadena de versión estable. Detéctalo monitoreando el drift en el espacio de embeddings de entradas y salidas, rastreando las tendencias de scores de eval, y comparando las distribuciones de producción con tu dataset de referencia. Phoenix se especializa en el análisis de drift de embeddings; una métrica de drift creciente es tu alerta temprana para reevaluar y reajustar antes de que los usuarios lo noten.

CI/CD

Quality gates de regresión en CI

Conecta los evals offline a tu pipeline para que un cambio de prompt o modelo no pueda mergear si baja los scores en el dataset dorado. Corre el experimento del dataset en cada PR, falla el build cuando el score agregado cae más allá de una tolerancia, y publica el diff de los casos que empezaron a fallar. Esto convierte ¿rompí algo con mi ajuste de prompt? de un chequeo intuitivo a un quality gate automatizado.

# Regression gate: fail CI when a prompt change lowers the eval score
import statistics, sys
from langfuse import get_client

langfuse = get_client()
dataset = langfuse.get_dataset("qa-regression-v3")

scores = []
for item in dataset.items:
    with item.run(run_name=f"ci-{GIT_SHA}") as root:
        out = my_app(item.input)
        s = faithfulness_judge(item.input, out, out_context)
        root.score(name="faithfulness", value=s)
        scores.append(s)

mean = statistics.mean(scores)
BASELINE, TOLERANCE = 0.86, 0.03
if mean < BASELINE - TOLERANCE:
    print(f"FAIL: faithfulness {mean:.3f} < {BASELINE - TOLERANCE:.3f}")
    sys.exit(1)      # blocks the merge
print(f"OK: faithfulness {mean:.3f}")

11. Gestión y Versionado de Prompts

Los prompts son el código fuente de una app de LLM, pero con demasiada frecuencia están hardcodeados y se editan en producción sin rastro. La gestión de prompts los lleva a un registro versionado que vive junto a tus datos de observabilidad. Autoras y etiquetas prompts (por ejemplo production vs staging), los obtienes en runtime por nombre y etiqueta, y -- crucialmente -- cada traza registra qué versión de prompt la produjo. Ese vínculo es lo que hace accionable el resto de la observabilidad: cuando los scores de eval caen o el costo se dispara, puedes ver exactamente qué versión de prompt es responsable y revertir una etiqueta sin desplegar código.

En Langfuse el cliente cachea los prompts obtenidos y los refresca en segundo plano, así que el overhead en runtime es insignificante y tu app sigue sirviendo el último prompt conocido como bueno incluso si la API está brevemente no disponible. Combinado con los experimentos de dataset de la sección 8, el versionado de prompts te da un flujo completo de gestión de cambios: edita un prompt en el playground, córrelo contra el dataset dorado offline, compara los scores con la versión de producción actual, promueve la etiqueta si gana, y observa los scores de eval online confirmar la mejora en producción -- todo sin un redespliegue. Este es el ciclo que separa a los equipos que iteran sobre prompts de forma segura de los que rompen producción con un cambio de redacción "rápido".

from langfuse import get_client
langfuse = get_client()

# Fetch the version currently labelled "production" (cached + auto-refreshed)
prompt = langfuse.get_prompt("support-classifier", label="production")

# Compile the template with variables
compiled = prompt.compile(ticket=ticket_text, categories=categories)

# Link the generation to this exact prompt version so the trace shows it
with langfuse.start_as_current_generation(
        name="classify",
        model="gpt-5.1",
        prompt=prompt,          # associates trace <-> prompt version
) as gen:
    resp = openai.chat.completions.create(
        model="gpt-5.1", messages=compiled)
    gen.update(output=resp.choices[0].message.content)
# In the UI: filter traces by prompt version, compare cost/latency/scores across versions.

Guías Relacionadas