AI Engineering Academy · Lección

Observabilidad independiente del modelo con Langfuse

Integre Langfuse como alternativa de código abierto compatible con cualquier proveedor de LLM, capture spans personalizados para la recuperación y las llamadas a herramientas, y configure paneles de seguimiento de costes.

Lección 3 de 413 pasos

Observabilidad independiente del modelo con Langfuse es una lección gratuita de AI Engineering Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Engineering Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Engineering Academy incluye 4 lecciones en total.

Langfuse: observabilidad de LLM de código abierto

Langfuse es una plataforma de observabilidad de código abierto para aplicaciones de LLM que funciona con cualquier proveedor de modelos: OpenAI, Anthropic, Mistral, modelos locales mediante Ollama o su propio modelo ajustado. A diferencia de LangSmith, que le vincula a LangChain, Langfuse se integra con cualquier código de Python mediante un SDK sencillo. Puede alojar Langfuse usted mismo de forma gratuita o utilizar la nube gestionada en cloud.langfuse.com.

# pip install langfuse
from langfuse import Langfuse

langfuse = Langfuse(
    public_key='pk-lf-...',
    secret_key='sk-lf-...',
    host='https://cloud.langfuse.com'  # or your self-hosted URL
)

print('Langfuse connected:', langfuse.auth_check())

Trazas, spans y generaciones

Langfuse utiliza un modelo de datos jerárquico con tres niveles. Una traza representa una solicitud de usuario completa, de extremo a extremo. Dentro de una traza, los spans representan pasos de procesamiento individuales (recuperación, preprocesamiento y llamadas a herramientas). Las generaciones son un tipo especial de span específico para las llamadas a LLM: capturan el modelo, los tokens del prompt, los tokens de finalización y el coste de forma estructurada, lo que permite crear paneles de costes y métricas de calidad.

from langfuse import Langfuse

langfuse = Langfuse()

# Create a trace for one user request
trace = langfuse.trace(
    name='rag-query',
    user_id='user_123',
    session_id='session_abc',
    tags=['production', 'rag']
)

# Add a retrieval span
retrieval_span = trace.span(
    name='vector-retrieval',
    input={'query': 'What is RAG?'}
)
chunks = vector_db.search('What is RAG?')
retrieval_span.end(output={'chunks': [c['text'][:100] for c in chunks]})

# Add an LLM generation
generation = trace.generation(
    name='answer-generation',
    model='gpt-4o',
    model_parameters={'temperature': 0.0},
    input=[{'role': 'user', 'content': 'Context: ...\nQuestion: What is RAG?'}]
)
response = openai_client.chat.completions.create(model='gpt-4o', messages=[...])
generation.end(
    output=response.choices[0].message.content,
    usage={'input': response.usage.prompt_tokens, 'output': response.usage.completion_tokens}
)

El patrón de integración mediante decoradores

Langfuse proporciona decoradores de funciones que envuelven automáticamente sus funciones con spans de trazas. El decorador @observe() captura las entradas y salidas, los tiempos y cualquier excepción. Es la forma más limpia de instrumentar código existente sin reestructurarlo.

from langfuse.decorators import observe, langfuse_context

# @observe wraps the function as a span automatically
@observe()
def retrieve_chunks(query: str) -> list[dict]:
    return vector_db.search(query, top_k=5)

@observe()
def generate_answer(query: str, context: str) -> str:
    response = openai_client.chat.completions.create(
        model='gpt-4o',
        messages=[
            {'role': 'system', 'content': 'Answer using the context.'},
            {'role': 'user', 'content': f'Context: {context}\nQuestion: {query}'}
        ]
    )
    # Attach LLM usage data to the current span
    langfuse_context.update_current_observation(
        usage={'input': response.usage.prompt_tokens, 'output': response.usage.completion_tokens},
        model='gpt-4o'
    )
    return response.choices[0].message.content

@observe(name='rag-pipeline')  # top-level trace
def rag_pipeline(query: str) -> str:
    chunks = retrieve_chunks(query)  # becomes a nested span
    context = '\n'.join([c['text'] for c in chunks])
    return generate_answer(query, context)  # becomes another nested span

Integración con cualquier proveedor de LLM

A diferencia de la integración profunda de LangSmith con LangChain, Langfuse funciona con cualquier proveedor de LLM mediante el mismo enfoque basado en decoradores. Tanto si llama a la API de Anthropic como si utiliza un modelo local de Ollama, un endpoint de inferencia de Hugging Face o un modelo personalizado que haya ajustado, Langfuse registra la traza de la llamada de la misma manera. Esta neutralidad respecto al proveedor es esencial cuando ejecuta varios modelos en la misma aplicación.

from langfuse.decorators import observe, langfuse_context
import anthropic
from openai import OpenAI

anthropic_client = anthropic.Anthropic()
openai_client = OpenAI()

@observe()
def call_claude(prompt: str) -> str:
    response = anthropic_client.messages.create(
        model='claude-3-5-sonnet-20241022',
        max_tokens=1024,
        messages=[{'role': 'user', 'content': prompt}]
    )
    langfuse_context.update_current_observation(
        model='claude-3-5-sonnet-20241022',
        usage={'input': response.usage.input_tokens, 'output': response.usage.output_tokens}
    )
    return response.content[0].text

@observe()
def call_gpt4(prompt: str) -> str:
    response = openai_client.chat.completions.create(
        model='gpt-4o',
        messages=[{'role': 'user', 'content': prompt}]
    )
    langfuse_context.update_current_observation(model='gpt-4o',
        usage={'input': response.usage.prompt_tokens, 'output': response.usage.completion_tokens})
    return response.choices[0].message.content

Paneles de seguimiento de costes

Langfuse calcula automáticamente el coste a partir del nombre del modelo y del recuento de tokens mediante una tabla de precios integrada que incluye OpenAI, Anthropic, Mistral y docenas de proveedores más. El panel de costes muestra: el gasto total por periodo de tiempo, el coste desglosado por modelo, el coste desglosado por funcionalidad o usuario (mediante etiquetas y metadatos), y las tendencias de gasto diarias y semanales. Esta visibilidad evita sorpresas en la factura y ayuda a identificar solicitudes atípicas especialmente costosas.

# Cost data is automatically computed - no manual config
# Langfuse knows: gpt-4o input = $0.005/1K tokens, output = $0.015/1K tokens

# Add metadata to enable cost breakdown by feature
@observe(name='rag-query')
def handle_rag_query(query: str, feature: str, user_id: str) -> str:
    langfuse_context.update_current_trace(
        user_id=user_id,
        tags=[feature, 'rag'],
        metadata={'feature': feature, 'query_length': len(query)}
    )
    return rag_pipeline(query)

# In Langfuse dashboard you can now filter costs by:
# - feature: 'document_qa', 'chat', 'summarization'
# - user_id: to see which users are your most expensive
# - model: to compare gpt-4o vs gpt-4o-mini costs
# - date range: to see daily/weekly/monthly trends

Añadir puntuaciones de los comentarios de los usuarios

Langfuse permite adjuntar comentarios de los usuarios a las trazas posteriormente. Cuando un usuario pulsa el pulgar hacia arriba o hacia abajo en una respuesta, puede registrarlo como una puntuación en la traza correspondiente. Esto vincula las señales reales de satisfacción del usuario con el contexto completo de la traza, lo que permite analizar qué diferencia a las respuestas con una valoración alta de las que tienen una valoración baja.

from langfuse.decorators import observe, langfuse_context

@observe()
def generate_response(query: str) -> dict:
    answer = rag_pipeline(query)
    # Get the current trace ID to link feedback later
    trace_id = langfuse_context.get_current_trace_id()
    return {'answer': answer, 'trace_id': trace_id}

# Later, when user submits feedback:
def record_user_feedback(trace_id: str, score: int, comment: str):
    langfuse.score(
        trace_id=trace_id,
        name='user_satisfaction',  # score name
        value=score,               # 1 (thumbs up) or 0 (thumbs down)
        comment=comment,
        data_type='BOOLEAN'
    )

# Now in Langfuse: filter traces where user_satisfaction = 0
# to find the exact prompts and contexts that users rated negatively

Puntuaciones automatizadas con LLM-as-judge

Además de los comentarios de los usuarios, Langfuse admite la puntuación automatizada mediante evaluadores LLM-as-judge. Puede definir evaluadores que se ejecuten de forma asíncrona sobre trazas seleccionadas y las puntúen según criterios como la relevancia, la fidelidad, la toxicidad o la corrección del formato. Estas puntuaciones automatizadas aparecen en el mismo panel de puntuaciones que los comentarios humanos, lo que proporciona una supervisión continua de la calidad sin necesidad de anotación humana a gran escala.

from langfuse import Langfuse

langfuse = Langfuse()

def auto_score_traces():
    # Get recent unscored traces
    traces = langfuse.fetch_traces(tags=['production'], limit=50)
    
    for trace in traces.data:
        question = trace.input.get('query', '')
        answer = trace.output.get('answer', '') if trace.output else ''
        
        if not question or not answer:
            continue
        
        # LLM-as-judge scoring
        score = evaluate_relevance(question, answer)  # returns 0.0-1.0
        
        langfuse.score(
            trace_id=trace.id,
            name='auto_relevance',
            value=score,
            data_type='NUMERIC',
            comment='Automated relevance score from LLM judge'
        )

# Run this as a scheduled job every hour

Gestión de prompts en Langfuse

Langfuse incluye una función de gestión de prompts que almacena sus prompts en la nube de Langfuse y permite recuperarlos en tiempo de ejecución. Esto desacopla las versiones de los prompts de las implementaciones del código: puede actualizar un prompt en la interfaz de Langfuse y el cambio tendrá efecto de inmediato, sin implementar código. Langfuse también registra qué versión del prompt utilizó cada traza, por lo que puede comparar el rendimiento entre distintas versiones.

from langfuse import Langfuse

langfuse = Langfuse()

# Fetch the current production prompt by name
# The prompt lives in Langfuse UI, not in your code
prompt = langfuse.get_prompt('rag-system-prompt', version='production')

# Use it in your pipeline
messages = [
    {'role': 'system', 'content': prompt.compile(context_limit=4000)},
    {'role': 'user', 'content': query}
]

response = openai_client.chat.completions.create(model='gpt-4o', messages=messages)

# The trace is automatically linked to the prompt version
# In Langfuse you can filter: show me traces using prompt v3 vs v4
# and compare their quality scores

Alojamiento propio de Langfuse

Puede alojar Langfuse usted mismo con un único comando de Docker Compose, utilizando PostgreSQL para el almacenamiento. El alojamiento propio significa que los datos de sus trazas nunca salen de su infraestructura, algo esencial para aplicaciones que gestionan información de identificación personal, datos médicos o contenido propietario. La versión autoalojada ofrece las mismas funciones que la nube gestionada, pero requiere que usted administre la infraestructura (copias de seguridad, escalado y actualizaciones).

# Self-host Langfuse with Docker Compose
# docker-compose.yml (simplified)
# version: '3'
# services:
#   langfuse:
#     image: langfuse/langfuse:2
#     ports:
#       - '3000:3000'
#     environment:
#       - DATABASE_URL=postgresql://langfuse:password@postgres/langfuse
#       - NEXTAUTH_SECRET=your-random-secret
#       - SALT=your-random-salt
#   postgres:
#     image: postgres:15
#     environment:
#       - POSTGRES_DB=langfuse
#       - POSTGRES_PASSWORD=password

# After docker-compose up, point your SDK to:
langfuse = Langfuse(
    public_key='pk-lf-your-key',
    secret_key='sk-lf-your-key',
    host='http://localhost:3000'  # your self-hosted instance
)

Langfuse frente a LangSmith: cuándo elegir cada uno

Elija LangSmith cuando utilice LangChain de forma intensiva, quiera tracing automático sin configuración, necesite una integración profunda con las evaluaciones de LangChain y se sienta cómodo con la dependencia del proveedor. Elija Langfuse cuando utilice varios proveedores de LLM, necesite alojarlo usted mismo para cumplir los requisitos de privacidad de los datos, quiera transparencia de código abierto o desarrolle con frameworks distintos de LangChain. Ambos están preparados para producción y ofrecen niveles gratuitos generosos.

Integración de OpenTelemetry para LLM

Para los equipos que ya utilizan OpenTelemetry para el tracing distribuido, Langfuse admite la ingesta mediante OTLP (OpenTelemetry Protocol). Puede enviar datos de trazas de LLM desde sus exportadores de OTel existentes directamente a Langfuse sin cambiar su instrumentación. Esto permite crear una pila de observabilidad unificada en la que las trazas de LLM, los spans de consultas a bases de datos y las trazas de solicitudes HTTP conviven en el mismo sistema con identificadores de correlación coherentes.

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace.export import BatchSpanProcessor

# Configure OTel to send to Langfuse OTLP endpoint
exporter = OTLPSpanExporter(
    endpoint='https://cloud.langfuse.com/api/public/otel/v1/traces',
    headers={
        'Authorization': 'Basic ' + base64.b64encode(b'pk-lf-xxx:sk-lf-xxx').decode()
    }
)

provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(exporter))
trace.set_tracer_provider(provider)

# Now create spans as usual - they appear in Langfuse automatically
tracer = trace.get_tracer('my-llm-app')
with tracer.start_as_current_span('rag-query') as span:
    span.set_attribute('llm.model', 'gpt-4o')
    span.set_attribute('llm.prompt_tokens', 500)
    result = rag_pipeline(query)

Comprobación rápida

Compruebe sus conocimientos sobre Langfuse para la observabilidad independiente del modelo en esta lección.

Resumen de la lección

En esta lección ha aprendido lo siguiente: Langfuse proporciona observabilidad de LLM de código abierto e independiente del modelo mediante un modelo de datos jerárquico de trazas, spans y generaciones; el decorador @observe() instrumenta código existente con cambios mínimos; y el seguimiento de costes, las puntuaciones de los comentarios de los usuarios y la puntuación automatizada mediante LLM-as-judge convierten Langfuse en una plataforma completa de supervisión de la calidad. A continuación, configuraremos alertas sobre la latencia, el coste y la degradación de la calidad.

Gratis para empezar

Aprende Python con un tutor de IA — gratis

Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.

Cursos
30
Lecciones
120

Preguntas frecuentes

¿La lección «Observabilidad independiente del modelo con Langfuse» es gratis?

Sí — el texto completo de «Observabilidad independiente del modelo con Langfuse» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Engineering Academy, actualiza a CoddyKit PRO. El curso de AI Engineering Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Observabilidad independiente del modelo con Langfuse»?

Integre Langfuse como alternativa de código abierto compatible con cualquier proveedor de LLM, capture spans personalizados para la recuperación y las llamadas a herramientas, y configure paneles de… Practicas AI Engineering Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar AI Engineering Academy?

No se requiere experiencia previa. AI Engineering Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «Observabilidad independiente del modelo con Langfuse»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de AI Engineering Academy?

Sí. Cada lección de AI Engineering Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Por qué las aplicaciones con LLM son difíciles de depurar
  2. Trazas con LangSmith
  3. Observabilidad independiente del modelo con Langfuse
  4. Alertas sobre latencia, costes y degradación de la calidad
← Volver a AI Engineering Academy