AI Engineering Academy · Lektion

Langfuse für modellunabhängige Observability

Integrieren Sie Langfuse als Open-Source-Alternative, die mit jedem LLM-Anbieter funktioniert, erfassen Sie benutzerdefinierte Spans für Retrieval und Tool-Aufrufe und richten Sie Dashboards zur Kostenüberwachung ein.

Lektion 3 von 413 Schritte

Langfuse für modellunabhängige Observability ist eine kostenlose AI Engineering Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des AI Engineering Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der AI Engineering Academy-Kurs umfasst insgesamt 4 Lektionen.

Langfuse: Open-Source-Observability für LLMs

Langfuse ist eine Open-Source-Observability-Plattform für LLM-Anwendungen, die mit jedem Modellanbieter funktioniert: OpenAI, Anthropic, Mistral, lokalen Modellen über Ollama oder Ihrem eigenen feinabgestimmten Modell. Im Gegensatz zu LangSmith, das Sie an LangChain bindet, lässt sich Langfuse über ein einfaches SDK in beliebigen Python-Code integrieren. Sie können Langfuse kostenlos selbst hosten oder die verwaltete Cloud unter cloud.langfuse.com verwenden.

# 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())

Traces, Spans und Generations

Langfuse verwendet ein hierarchisches Datenmodell mit drei Ebenen. Ein Trace steht für eine vollständige Benutzeranfrage von Anfang bis Ende. Innerhalb eines Traces stellen Spans einzelne Verarbeitungsschritte dar (Abruf, Vorverarbeitung, Tool-Aufrufe). Generations sind ein spezieller Spantyp für LLM-Aufrufe: Sie erfassen Modell, Prompt-Tokens, Completion-Tokens und Kosten in strukturierter Form und ermöglichen dadurch Kosten-Dashboards und Qualitätsmetriken.

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}
)

Das Integrationsmuster mit Decorators

Langfuse stellt Funktions-Decorators bereit, die Ihre Funktionen automatisch mit Trace-Spans umhüllen. Der Decorator @observe() erfasst Eingaben und Ausgaben, Zeitmessungen sowie alle Ausnahmen. Dies ist die sauberste Möglichkeit, bestehenden Code zu instrumentieren, ohne ihn strukturell ändern zu müssen.

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

Integration mit beliebigen LLM-Anbietern

Im Gegensatz zur tiefen Integration von LangSmith in LangChain funktioniert Langfuse mit jedem LLM-Anbieter und verwendet dabei denselben auf Decorators basierenden Ansatz. Unabhängig davon, ob Sie die API von Anthropic, ein lokales Ollama-Modell, einen Hugging-Face-Inferenzendpunkt oder ein eigenes feinabgestimmtes Modell aufrufen: Langfuse erfasst den Aufruf auf dieselbe Weise. Diese Anbieterneutralität ist entscheidend, wenn Sie mehrere Modelle in derselben Anwendung ausführen.

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

Dashboards zur Kostenverfolgung

Langfuse berechnet die Kosten automatisch anhand des Modellnamens und der Tokenanzahl mithilfe einer integrierten Preistabelle, die OpenAI, Anthropic, Mistral und Dutzende weitere Anbieter abdeckt. Das Kosten-Dashboard zeigt: die Gesamtausgaben nach Zeitraum, die nach Modell aufgeschlüsselten Kosten, die nach Funktion oder Benutzer aufgeschlüsselten Kosten (mithilfe von Tags und Metadaten) sowie tägliche und wöchentliche Ausgabentrends. Diese Transparenz verhindert böse Überraschungen bei der Abrechnung und hilft, teure Ausreißeranfragen zu erkennen.

# 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

Benutzerfeedback-Bewertungen hinzufügen

Mit Langfuse können Sie Traces nachträglich Benutzerfeedback zuordnen. Wenn ein Benutzer bei einer Antwort auf „Daumen hoch“ oder „Daumen runter“ klickt, können Sie dies als Bewertung für den entsprechenden Trace erfassen. Dadurch werden echte Signale zur Benutzerzufriedenheit mit dem vollständigen Kontext des Traces verknüpft. So können Sie analysieren, wodurch sich besonders gut bewertete von schlecht bewerteten Antworten unterscheiden.

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

Automatisierte Bewertungen mit LLM-as-Judge

Neben Benutzerfeedback unterstützt Langfuse automatisierte Bewertungen mithilfe von LLM-as-Judge-Evaluatoren. Sie können Evaluatoren definieren, die asynchron auf Stichproben von Traces ausgeführt werden und diese anhand von Kriterien wie Relevanz, Faktentreue, Toxizität oder Formatkorrektheit bewerten. Diese automatisierten Bewertungen werden im selben Bewertungs-Dashboard wie menschliches Feedback dargestellt und ermöglichen so eine kontinuierliche Qualitätsüberwachung ohne eine umfangreiche manuelle Annotation.

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

Prompt-Verwaltung in Langfuse

Langfuse bietet eine Funktion zur Prompt-Verwaltung, die Ihre Prompts in der Langfuse-Cloud speichert und zur Laufzeit abrufen lässt. Dadurch werden Prompt-Versionen von Code-Deployments entkoppelt: Sie können einen Prompt in der Langfuse-Benutzeroberfläche aktualisieren, und die Änderung wird sofort wirksam, ohne dass Sie neuen Code bereitstellen müssen. Langfuse erfasst außerdem, welche Prompt-Version für jeden Trace verwendet wurde, sodass Sie die Leistung verschiedener Prompt-Versionen vergleichen können.

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

Langfuse selbst hosten

Langfuse lässt sich mit einem einzigen Docker-Compose-Befehl selbst hosten und verwendet PostgreSQL zur Speicherung. Beim Selbsthosting verlassen Ihre Trace-Daten niemals Ihre Infrastruktur – das ist für Anwendungen mit personenbezogenen Daten, medizinischen Daten oder proprietären Inhalten unerlässlich. Die selbst gehostete Version bietet dieselben Funktionen wie die verwaltete Cloud, erfordert jedoch, dass Sie die Infrastruktur selbst verwalten (Backups, Skalierung und Upgrades).

# 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 oder LangSmith: Wann Sie welche Lösung wählen sollten

Wählen Sie LangSmith, wenn Sie intensiv mit LangChain arbeiten, ein automatisch aktiviertes Tracing ohne Konfiguration und eine tiefe Integration in LangChain-Evaluierungen wünschen und mit der Abhängigkeit von einem Anbieter einverstanden sind. Wählen Sie Langfuse, wenn Sie mehrere LLM-Anbieter verwenden, aus Gründen des Datenschutzes selbst hosten müssen, Transparenz durch Open Source wünschen oder mit anderen Frameworks als LangChain entwickeln. Beide Lösungen sind für den Produktionseinsatz geeignet und bieten großzügige kostenlose Kontingente.

OpenTelemetry-Integration für LLMs

Für Teams, die OpenTelemetry bereits für verteiltes Tracing verwenden, unterstützt Langfuse die Verarbeitung von OTLP (OpenTelemetry Protocol). Sie können LLM-Trace-Daten aus Ihren vorhandenen OTel-Exportern direkt an Langfuse senden, ohne Ihre Instrumentierung zu ändern. So entsteht ein einheitlicher Observability-Stack, in dem LLM-Traces, Spans von Datenbankabfragen und Traces von HTTP-Anfragen mit konsistenten Korrelations-IDs im selben System vorliegen.

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)

Kurze Überprüfung

Testen Sie in dieser Lektion Ihr Verständnis von Langfuse für modellagnostische Observability.

Zusammenfassung der Lektion

In dieser Lektion haben Sie gelernt: Langfuse bietet eine quelloffene, modellagnostische Observability-Lösung für LLMs auf Grundlage eines hierarchischen Datenmodells aus Traces, Spans und Generations; der Decorator @observe() instrumentiert bestehenden Code mit minimalen Änderungen; und Kostenverfolgung, Benutzerfeedback-Bewertungen und automatisierte LLM-as-Judge-Bewertungen machen Langfuse zu einer vollständigen Plattform für die Qualitätsüberwachung. Als Nächstes richten wir Benachrichtigungen für Latenz, Kosten und Qualitätsverschlechterungen ein.

Kostenlos starten

Lerne Python mit einem KI-Tutor — kostenlos

Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.

Kurse
30
Lektionen
120

Häufig gestellte Fragen

Ist die Lektion „Langfuse für modellunabhängige Observability“ kostenlos?

Ja — der vollständige Text von „Langfuse für modellunabhängige Observability“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des AI Engineering Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der AI Engineering Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Langfuse für modellunabhängige Observability“?

Integrieren Sie Langfuse als Open-Source-Alternative, die mit jedem LLM-Anbieter funktioniert, erfassen Sie benutzerdefinierte Spans für Retrieval und Tool-Aufrufe und richten Sie Dashboards zur Kost… Du übst AI Engineering Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um AI Engineering Academy zu starten?

Keine Vorkenntnisse erforderlich. AI Engineering Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.

Wie lange dauert die Lektion „Langfuse für modellunabhängige Observability“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser AI Engineering Academy-Lektion Code schreiben und ausführen?

Ja. Jede AI Engineering Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Warum sich LLM-Anwendungen schwer debuggen lassen
  2. Tracing mit LangSmith
  3. Langfuse für modellunabhängige Observability
  4. Alarme bei Latenz, Kosten und Qualitätsverlust
← Zurück zu AI Engineering Academy