LangSmith
Monitoring & Debugging mit LangSmith
Inhaltsverzeichnis
- Kurzüberblick: Warum LangSmith?
- Setup: API-Key und Umgebung
- Das kleinstmögliche funktionierende Beispiel
- Traces verstehen: Die Grundstruktur
- Praktisches Beispiel: Agent mit Tools tracken
- Datasets: Systematisches Testen
- Feedback: Qualität messen
- Integration in LangGraph-Workflows
- Best Practices
- Vergleich: LangSmith vs. Alternatives
- Häufige Fragen (FAQ)
- Abgrenzung zu verwandten Dokumenten
Kurzüberblick: Warum LangSmith?
LangChain und LangGraph ermöglichen den Bau komplexer KI-Anwendungen. Doch bei der Entwicklung stellen sich schnell Fragen:
- Warum hat die Chain eine bestimmte Antwort produziert?
- Welche Retrieval-Schritte wurden in welcher Reihenfolge ausgeführt?
- Wo ist der Fehler in einer 10-Schritte-RAG-Pipeline?
- Wie gut funktioniert das System mit echten Nutzerfragen?
LangSmith beantwortet diese Fragen durch:
- Vollständiges Tracing aller LLM-Calls, Tool-Aufrufe und Chain-Schritte
- Visuelle Darstellung komplexer Workflows
- Dataset-Management für systematische Evaluierung
- Performance-Monitoring in Produktion
- Feedback-Collection von Nutzern
Kernprinzip: Jede Ausführung wird automatisch protokolliert und kann nachvollzogen werden – ohne zusätzlichen Code im Workflow selbst.
LangSmith im Entwicklungs-Workflow
flowchart TB
DEV[Development<br/>LangChain/LangGraph Code]
RUN[Code Execution<br/>Chain/RAG/Tool Runs]
LANGSMITH[LangSmith Platform<br/>Automatic Tracing]
UI[LangSmith Web UI<br/>Visualization & Analysis]
DEBUG[Debug & Optimize<br/>Based on Insights]
DEV --> RUN
RUN -->|Automatic| LANGSMITH
LANGSMITH --> UI
UI --> DEBUG
DEBUG -.Improve Code.-> DEV
subgraph "No Code Changes Needed"
RUN
LANGSMITH
end
style LANGSMITH fill:#d5e8d4
style UI fill:#dae8fc
Setup: API-Key und Umgebung
LangSmith-Account erstellen
- Kostenlosen Account anlegen: eu.smith.langchain.com
- API-Key generieren: Settings → API Keys → Create API Key (im EU-Workspace)
- Optional: Organisation und Projekte anlegen
[!WARNING] EU-Endpoint verwenden
Für diesen Kurs immer den EU-Endpoint verwenden:https://eu.api.smith.langchain.com. Account und API-Key müssen ebenfalls im EU-Workspace erstellt werden, sonst erscheinen Traces nicht im erwarteten Projekt. APAC-Account (Asia-Pacific):https://ap.api.smith.langchain.com(seit SDK 0.8.x).
API-Keys in Google Colab Secrets hinterlegen
Schritt 1: Secrets in Colab einrichten
- In Google Colab: Schlüssel-Symbol 🔑 in der linken Seitenleiste
- Neue Secrets hinzufügen:
OPENAI_API_KEY: Eigener OpenAI-KeyLANGSMITH_API_KEY: LangSmith-Key (beginnt mitlsv2_pt_...)- Optional:
HF_TOKENfür Hugging Face
Schritt 2: Umgebung einrichten (Standard-Setup)
[!WARNING] Reihenfolge-Regel: Env-Vars vor Imports
LangSmith-Env-Vars müssen gesetzt sein, bevorlangchain,langsmithodergenai_libimportiert werden. Der Tracer liest die Env-Vars beim ersten Import — späteres Setzen wird ignoriert. Env-Vars ganz oben in der Setup-Cell, vor allen Imports setzen.
#@title 🔧 Umgebung einrichten{ display-mode: "form" }
!uv pip install --system -q git+https://github.com/ralf-42/GenAI.git#subdirectory=04_modul
import os
# ✅ LangSmith Env-Vars ZUERST – vor allen Imports!
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_PROJECT"] = "M02-LangSmith-Setup" # Konvention: "M##-Thema"
os.environ["LANGSMITH_ENDPOINT"] = "https://eu.api.smith.langchain.com"
# Erst danach: genai_lib und weitere Imports
from genai_lib.utilities import check_environment, get_ipinfo, setup_api_keys, mprint
setup_api_keys(['OPENAI_API_KEY', 'LANGSMITH_API_KEY'], create_globals=False)
print()
check_environment()
print()
get_ipinfo()
Wichtig:
- Env-Vars stehen vor dem
genai_lib-Import – das ist Pflicht laut Best Practices - Projektname-Konvention:
"M##-Thema"(z.B."M05-Structured-Output") – Traces sind sofort dem Modul zuzuordnen create_globals=Falseverhindert globale Variablen (Best Practice)- Ab jetzt werden alle LangChain/LangGraph-Operationen automatisch getrackt
Das kleinstmögliche funktionierende Beispiel
Der schnellste Weg zum Verständnis: Ein einfacher LLM-Call mit automatischem Tracing.
from langchain.chat_models import init_chat_model
# Normaler LLM-Setup (wie gewohnt)
llm = init_chat_model("openai:gpt-5.4-nano")
# Einfacher Call - wird automatisch getrackt!
response = llm.invoke("Erkläre LangSmith in einem Satz.")
print(response.content)
Was passiert im Hintergrund:
- LangSmith empfängt automatisch alle Daten (Input, Output, Latenz, Token)
- Ein “Trace” wird erstellt und in der Web-UI angezeigt
- Kein zusätzlicher Code nötig – funktioniert “out of the box”
Nächster Schritt: LangSmith-Dashboard öffnen und den Trace inspizieren
- URL: eu.smith.langchain.com/projects
- Projekt auswählen:
"M02-LangSmith-Setup" - Ersten Trace anklicken → vollständige Details sehen
Traces verstehen: Die Grundstruktur
LangSmith organisiert alle Daten in einer klaren Hierarchie:
flowchart TB
PROJECT["Project<br>Container für alle Traces<br>z.B. 'M08-RAG-Chain'"]
THREAD["Thread<br>Gesprächs-Sequenz<br>session_id / conversation_id"]
TRACE["Trace<br>Eine vollständige Anfrage<br>z.B. RAG-Ausführung"]
RUN["Run<br>Einzelne Operation<br>llm · chain · tool · ..."]
TAGS["Tags<br>Filterbare Labels"]
META["Metadata<br>Key-Value-Paare"]
FEEDBACK["Feedback<br>Score 0.0 – 1.0"]
PROJECT --> THREAD
THREAD --> TRACE
TRACE --> RUN
RUN -.-> TAGS
RUN -.-> META
RUN -.-> FEEDBACK
style PROJECT fill:#e1f5ff
style THREAD fill:#fff3cd
style TRACE fill:#dae8fc
style RUN fill:#d5e8d4
style TAGS fill:#f5f5f5
style META fill:#f5f5f5
style FEEDBACK fill:#f5f5f5
| Konzept | Bedeutung |
|---|---|
| Project | Container für alle zusammengehörigen Traces (z.B. ein Kursmodul) |
| Thread | Sequenz mehrerer Traces für ein Gespräch — verknüpft via session_id |
| Trace | Vollständige Aufzeichnung einer einzelnen Anfrage |
| Run | Einzelner Schritt innerhalb eines Trace (llm, chain, tool …) |
| Tags | Labels zur Filterung und Kategorisierung von Runs |
| Metadata | Zusätzliche Key-Value-Daten pro Run (z.B. User-ID, Version) |
| Feedback | Bewertung eines Runs — manuell oder automatisch (Score 0.0–1.0) |
Run-Typen
LangSmith kennt 7 Run-Typen (Werte immer lowercase):
| Run-Typ | Bedeutung | Typisches Beispiel |
|---|---|---|
llm | Direkte LLM-Aufrufe (Chat, Completion) | llm.invoke() |
chain | Verkettungen, Workflows, Agenten-Schritte | prompt | llm | parser, LangGraph-Nodes |
tool | Tool-/Funktionsaufrufe | @tool Decorator |
retriever | Dokumentenabruf aus Vektordatenbanken | vectorstore.as_retriever() |
embedding | Embedding-Berechnungen | embeddings.embed_query() |
prompt | Prompt-Template-Verarbeitung | ChatPromptTemplate.format_messages() |
parser | Output-Parser | StrOutputParser() |
Wichtige Hinweise:
chainist der häufigste Typ — er deckt alles ab, was kein direkter LLM-Call, kein Tool etc. ist. RAG-Pipelines und LCEL-Chains erscheinen typischerweise alschain.- Default-Fallback: Unbekannte oder falsch geschriebene
run_type-Werte (z.B."LLM"statt"llm") fallen automatisch auf"chain"zurück. - Kosten-Tracking (ab 2026): LangSmith bietet eine einheitliche Kostenübersicht über den gesamten Workflow — nicht nur für
llm-Runs. Custom Cost Metadata kann für beliebige Run-Typen übergeben werden.
Beispiel: Chain mit mehreren Runs
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
# LCEL-Chain (aus LangChain-Anleitung bekannt)
prompt = ChatPromptTemplate.from_template("Erkläre {topic} für Einsteiger.")
chain = prompt | llm | StrOutputParser()
result = chain.invoke({"topic": "Vektordatenbanken"})
Im LangSmith-Trace sichtbar:
graph TB
CHAIN[Chain Run - Gesamt<br/>Latenz: 1.5s]
PROMPT[Prompt Run<br/>Template-Formatierung<br/>0.1s]
LLM[LLM Run - GPT-4o-mini<br/>Input: 'Erkläre Vektordatenbanken...'<br/>Output: 'Vektordatenbanken speichern...'<br/>Tokens: 245 in=12, out=233<br/>Latenz: 1.2s]
PARSER[Parser Run<br/>String-Extraktion<br/>0.2s]
CHAIN --> PROMPT
CHAIN --> LLM
CHAIN --> PARSER
style CHAIN fill:#e1f5ff
style PROMPT fill:#ffe6cc
style LLM fill:#d5e8d4
style PARSER fill:#dae8fc
ASCII-Darstellung:
Chain Run (Gesamt)
├─ Prompt Run (Template-Formatierung)
├─ LLM Run (GPT-4o-mini Call)
│ ├─ Input: "Erkläre Vektordatenbanken für Einsteiger."
│ ├─ Output: "Vektordatenbanken speichern..."
│ ├─ Tokens: 245 (Input: 12, Output: 233)
│ └─ Latenz: 1.2s
└─ Parser Run (String-Extraktion)
Threads: Gespräche über mehrere Traces hinweg
Ein Thread verknüpft mehrere Traces zu einer Gesprächs-Sequenz — z.B. alle Nachrichten einer Chat-Session. Die Verknüpfung erfolgt über session_id oder conversation_id in den Metadaten.
# Thread-ID in den Metadaten setzen
config = {
"configurable": {"thread_id": "session-42"},
"metadata": {"session_id": "session-42"}, # → LangSmith gruppiert Traces als Thread
}
response = agent.invoke(
{"messages": [{"role": "user", "content": "Hallo!"}]},
config=config,
)
Im LangSmith-Dashboard: Threads-Ansicht zeigt den vollständigen Gesprächsverlauf über alle Traces hinweg — ideal für Debugging von Multi-Turn-Gesprächen.
Praktisches Beispiel: Agent mit Tools tracken
Tools und Agents profitieren besonders von LangSmith, da ihre Entscheidungswege oft komplex sind.
from langchain_core.tools import tool
from langchain.agents import create_agent
# Tool definieren (wie in LangChain-Anleitung)
@tool
def multiply(a: int, b: int) -> int:
"""Multipliziert zwei Zahlen."""
return a * b
@tool
def add(a: int, b: int) -> int:
"""Addiert zwei Zahlen."""
return a + b
# Agent erstellen
tools = [multiply, add]
agent = create_agent(
model=llm,
tools=tools,
system_prompt="Du bist ein Rechen-Agent. Nutze Tools für Berechnungen.",
)
# Agent ausführen - komplexe Frage
response = agent.invoke({
"messages": [{"role": "user", "content": "Berechne (5 * 8) + 3"}]
})
Im LangSmith-Trace wird sichtbar:
sequenceDiagram
autonumber
participant User
participant Agent
participant LLM
participant multiply as Tool: multiply
participant add as Tool: add
participant LangSmith
User->>Agent: "Berechne (5 * 8) + 3"
Agent->>LangSmith: Trace Start
Agent->>LLM: Process request with tools
LLM->>LLM: Decide: Need multiply(5, 8)
LLM-->>Agent: Tool call: multiply(5, 8)
Agent->>multiply: Execute multiply(5, 8)
multiply-->>Agent: Result: 40
Agent->>LangSmith: Log: Tool Run (multiply)
Agent->>LLM: Tool result: 40
LLM->>LLM: Decide: Need add(40, 3)
LLM-->>Agent: Tool call: add(40, 3)
Agent->>add: Execute add(40, 3)
add-->>Agent: Result: 43
Agent->>LangSmith: Log: Tool Run (add)
Agent->>LLM: Tool result: 43
LLM-->>Agent: Final answer
Agent-->>User: "Das Ergebnis ist 43"
Agent->>LangSmith: Trace Complete
Note over LangSmith: Every step logged:<br/>Inputs, Outputs,<br/>Latency, Tokens
Wichtig: Jeder Schritt ist einzeln inspizierbar – Input, Output, Latenz, Fehler.
Datasets: Systematisches Testen
Datasets ermöglichen wiederholbare Tests mit definierten Inputs und erwarteten Outputs.
Dataset erstellen (UI oder Code)
Variante A: Über UI
- LangSmith → Datasets → Create Dataset
- Beispiele hinzufügen (Input/Output-Paare)
Variante B: Programmatisch
from langsmith import Client
client = Client(api_url=os.environ["LANGSMITH_ENDPOINT"])
# Dataset mit Beispielen
examples = [
{"inputs": {"question": "Was ist 5 * 8?"}, "outputs": {"answer": "40"}},
{"inputs": {"question": "Addiere 10 und 15"}, "outputs": {"answer": "25"}},
{"inputs": {"question": "Was ist die Hauptstadt von Frankreich?"}, "outputs": {"answer": "Paris"}},
]
dataset_name = "Rechen-Agent-Tests"
dataset = client.create_dataset(dataset_name=dataset_name)
client.create_examples(
inputs=[e["inputs"] for e in examples],
outputs=[e["outputs"] for e in examples],
dataset_id=dataset.id,
)
Agent gegen Dataset evaluieren
from langsmith.evaluation import evaluate
def predict(inputs: dict) -> dict:
"""Wrapper für Agent-Aufruf"""
response = agent.invoke({
"messages": [{"role": "user", "content": inputs["question"]}]
})
# Antwort aus letzter Message extrahieren
return {"answer": response["messages"][-1].content}
# Evaluierung starten
results = evaluate(
predict,
data=dataset_name,
experiment_prefix="Agent-v1",
)
Ergebnis:
- Jeder Test-Case wird einzeln ausgeführt
- Traces für alle Runs werden automatisch gespeichert
- Vergleich über UI: Welche Fragen wurden korrekt beantwortet?
Feedback: Qualität messen
Feedback ermöglicht es, die Qualität von Antworten zu bewerten – manuell oder automatisch.
Manuelles Feedback (UI)
In der LangSmith-UI kann jeder Run bewertet werden:
- Daumen hoch/runter
- Sterne (1-5)
- Freitext-Kommentar
Programmatisches Feedback
Run-IDs über @traceable mit run_tree-Injection ermitteln – der moderne Weg (kein response["__run"].id mehr, da veraltet und unzuverlässig):
from langsmith import traceable, Client
client = Client(api_url=os.environ["LANGSMITH_ENDPOINT"])
@traceable(run_type="chain", name="AgentRun")
def agent_ausfuehren(frage: str, run_tree=None) -> str:
"""Agent-Ausführung – run_tree wird automatisch injiziert."""
response = agent.invoke({
"messages": [{"role": "user", "content": frage}]
})
return response["messages"][-1].content
# Agent ausführen
antwort = agent_ausfuehren("Was ist 5 * 8?")
# Run-ID über letzten Run im Projekt ermitteln
runs = list(client.list_runs(
project_name=os.environ["LANGSMITH_PROJECT"], limit=1
))
if runs:
client.create_feedback(
run_id=runs[0].id,
key="user_satisfaction",
score=1.0, # 0.0 = schlecht, 1.0 = gut
comment="Antwort war präzise und korrekt.",
)
Automatische Evaluierung mit LLM-as-Judge
LangChainStringEvaluator ist deprecated. Modernes Pattern: function-based Evaluators — einfache Python-Funktionen mit Signatur (run, example) -> dict:
from langsmith.evaluation import evaluate
from langsmith import traceable
# Einfacher Evaluator: exakter Vergleich
def korrektheit_evaluator(run, example) -> dict:
predicted = run.outputs.get("answer", "").strip().lower()
expected = example.outputs.get("answer", "").strip().lower()
return {"key": "correctness", "score": 1.0 if predicted == expected else 0.0}
# LLM-as-Judge Evaluator
@traceable
def llm_judge(run, example) -> dict:
predicted = run.outputs.get("answer", "")
expected = example.outputs.get("answer", "")
prompt = (
f"Bewerte die Antwort auf einer Skala von 0 bis 1.<br>"
f"Erwartete Antwort: {expected}<br>"
f"Tatsächliche Antwort: {predicted}<br>"
f"Antworte nur mit einer Zahl zwischen 0 und 1."
)
try:
score = float(llm.invoke(prompt).content.strip())
except ValueError:
score = 0.0
return {"key": "quality", "score": score}
# Evaluierung ausführen
results = evaluate(
predict,
data=dataset_name,
evaluators=[korrektheit_evaluator, llm_judge],
experiment_prefix="Agent-v1-auto-eval",
)
Vorteile:
- Skalierbar: 100+ Beispiele automatisch testen
- Konsistent: Gleiche Bewertungskriterien
- Nachvollziehbar: LLM-Begründungen werden gespeichert
Integration in LangGraph-Workflows
LangSmith trackt auch komplexe LangGraph-State-Machines automatisch.
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver
from typing import TypedDict, Annotated
from langgraph.graph.message import add_messages
class ChatState(TypedDict):
messages: Annotated[list, add_messages]
def agent_node(state: ChatState):
response = llm.invoke(state["messages"])
return {"messages": [response]}
# Graph bauen
graph = StateGraph(ChatState)
graph.add_node("agent", agent_node)
graph.add_edge(START, "agent")
graph.add_edge("agent", END)
# Mit Checkpointer kompilieren
checkpointer = MemorySaver()
compiled_graph = graph.compile(checkpointer=checkpointer)
# Ausführen - wird automatisch getrackt!
config = {"configurable": {"thread_id": "demo-session"}}
result = compiled_graph.invoke(
{"messages": [{"role": "user", "content": "Hallo!"}]},
config=config,
)
Im LangSmith-Trace:
- Vollständiger Graph-Ablauf sichtbar
- Jeden Node-Durchlauf einzeln inspizierbar
- State-Änderungen nachvollziehbar
- Checkpointing-Events protokolliert
Best Practices
Projekt-Organisation
Konvention: Modulname direkt in der Setup-Cell setzen
# ✅ Modulname in der Setup-Cell – vor allen Imports!
os.environ["LANGSMITH_PROJECT"] = "M05-Structured-Output"
Wichtig: LANGSMITH_PROJECT wird beim ersten Trace via lru_cache eingefroren. Spätere os.environ-Änderungen haben keinen Effekt. Daher den Modulnamen einmal korrekt in der Setup-Cell setzen – dann funktioniert es zuverlässig.
Standard-Setup im Notebook-Header
#@title 🔧 Umgebung einrichten{ display-mode: "form" }
!uv pip install --system -q git+https://github.com/ralf-42/GenAI.git#subdirectory=04_modul
import os
# ✅ LangSmith Env-Vars ZUERST – vor allen Imports!
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_PROJECT"] = "M05-Structured-Output" # Modulname anpassen
os.environ["LANGSMITH_ENDPOINT"] = "https://eu.api.smith.langchain.com"
# Erst danach: genai_lib und weitere Imports
from genai_lib.utilities import setup_api_keys, check_environment, get_ipinfo
setup_api_keys(['OPENAI_API_KEY', 'LANGSMITH_API_KEY'], create_globals=False)
check_environment()
get_ipinfo()
Modulspezifischer Abschnitt im Notebook (nach dem Setup):
# LangSmith: Aktives Projekt für diesen Abschnitt
import os
print(f"📊 LangSmith-Projekt: {os.environ['LANGSMITH_PROJECT']}")
# invoke() direkt – Projekt bereits korrekt in Setup-Cell gesetzt
run_cfg = {"run_name": "M05_Kap6_StructuredTrace", "tags": ["M05", "structured-output"]}
result = llm.with_structured_output(MyModel).with_config(**run_cfg).invoke("...")
Konventionen:
| Kontext | Projektname |
|---|---|
| Notebook | "M##-Thema" z.B. "M05-Structured-Output" |
| Produktion | "chatbot-production" |
| Experiment | "rag-experiment-2026-03" |
💡 Edge Case: Falls ein Projekt-Wechsel nach Notebook-Start nötig ist (z.B. kein Kernel-Neustart möglich), kann
ls.tracing_context(project_name=...)als Workaround verwendet werden.
Tags für bessere Organisation
from langsmith import traceable
@traceable(
run_type="chain",
tags=["rag", "produktiv", "version-2.0"],
)
def my_rag_chain(question: str):
# RAG-Logik hier
pass
Fehler debuggen
flowchart LR
FAIL[Chain fails<br/>Wrong answer]
OPEN[Open LangSmith UI<br/>Find failed run]
INSPECT[Inspect Trace<br/>Identify issue]
FIX[Fix Code<br/>Prompt or<br/>Retrieval config]
RETEST[Re-run Chain<br/>New trace created]
COMPARE[Compare in UI<br/>Before vs After]
SUCCESS{Fixed?}
FAIL --> OPEN
OPEN --> INSPECT
INSPECT --> FIX
FIX --> RETEST
RETEST --> COMPARE
COMPARE --> SUCCESS
SUCCESS -->|No| INSPECT
SUCCESS -->|Yes| END([Done])
style FAIL fill:#f8cecc
style SUCCESS fill:#d5e8d4
style COMPARE fill:#dae8fc
Typischer Workflow:
- Chain liefert falsche Antwort
- LangSmith öffnen → Run finden
- Trace inspizieren: An welcher Stelle ging es schief?
- Prompt oder Retrieval-Konfiguration anpassen
- Erneut testen → Vergleichen im UI
Vorteil: Direkter Vorher/Nachher-Vergleich im LangSmith-UI.
Performance-Monitoring
# Metadaten hinzufügen für Filterung
from langsmith import traceable
@traceable(metadata={"user_id": "student_42", "environment": "colab"})
def process_query(query: str):
return chain.invoke({"question": query})
Nutzen:
- Langsame Runs identifizieren (Latenz > 5s)
- Token-Verbrauch pro Student analysieren
- Fehlerraten nach Umgebung filtern
Einzelne Chains und Runs benennen mit .with_config()
Automatisches Tracing erfasst alle Runs – aber ohne explizite Namen sind sie im Dashboard schwer zu unterscheiden. .with_config() gibt einzelnen Chains, LLM-Aufrufen und Structured-Output-Chains einen eindeutigen Namen und Tags.
Prinzip: Config-Parameter vorab in einer separaten Variable festlegen
# Config-Parameter in einer eigenen Variable definieren
run_cfg = {
"run_name": "M07_Kap3_LCEL_Grundchain", # Konvention: M##_Kap##_Typ
"tags": ["M07", "lcel", "chain"], # Filterbar im LangSmith-Dashboard
}
chain = (
ChatPromptTemplate.from_template("Erkläre {topic} für Einsteiger.")
| llm
| StrOutputParser()
).with_config(**run_cfg)
result = chain.invoke({"topic": "Vektordatenbanken"})
Auf LLM-Aufrufe anwenden
run_cfg = {
"run_name": "M03_Kap1_LLM_Basis",
"tags": ["M03", "llm"],
}
named_llm = llm.with_config(**run_cfg)
response = named_llm.invoke("Was ist ein Sprachmodell?")
Auf with_structured_output() anwenden
from pydantic import BaseModel, Field
class Person(BaseModel):
name: str = Field(description="Vollständiger Name")
alter: int = Field(description="Alter in Jahren")
run_cfg = {
"run_name": "M05_Kap3_PersonExtraktion",
"tags": ["M05", "structured-output"],
}
structured_llm = llm.with_structured_output(Person).with_config(**run_cfg)
ergebnis = structured_llm.invoke("Emma Müller ist 34 Jahre alt.")
Regeln für run_cfg:
| Parameter | Konvention | Beispiel |
|---|---|---|
run_name | "M##_Kap##_Typ" (Modul, Kapitel, Kurzname) | "M05_Kap3_PersonExtraktion" |
tags | Liste: ["M##", "typ", ...] | ["M05", "structured-output"] |
⚠️ Regel:
.with_config()gehört in den Abschnitt, der Tracing erklärt – nicht pauschal auf jede Chain im Notebook. In Lehr-Notebooks einmalig pro Kapitel demonstrieren.
Tool-Tests ohne Tracing: .func()
Beim Testen einzelner @tool-Funktionen entsteht mit .invoke() immer ein Trace. Für isolierte Unit-Tests die Python-Funktion direkt über .func() aufrufen – komplett am Runnable-Framework vorbei.
from langchain_core.tools import tool
@tool
def celsius_nach_fahrenheit(temperatur: float) -> float:
"""Rechnet Celsius in Fahrenheit um."""
return round(temperatur * 9 / 5 + 32, 2)
# ✅ Kein Trace – direkte Python-Funktion
ergebnis = celsius_nach_fahrenheit.func(temperatur=37.0)
print(ergebnis) # 98.6
# ⚠️ Mit Trace – geht durch das Runnable-Framework
ergebnis = celsius_nach_fahrenheit.invoke({"temperatur": 37.0})
Wann .func() einsetzen:
- ✅ Isolierte Unit-Tests von Tool-Funktionen (Kapitel vor der LangSmith-Demo)
- ✅ Wenn Tracing-Unterdrückung via Context Manager nicht zuverlässig funktioniert
- ❌ Nicht verwenden, wenn das Runnable-Verhalten (Schema-Validierung, Callbacks) getestet werden soll
💡 Didaktischer Mehrwert: Der Kontrast
.func()vs..invoke()macht sichtbar, was das Runnable-Framework zusätzlich leistet – ideal für Lehr-Notebooks.
Trace-Patterns erkennen
Traces sind mehr als ein Debug-Log — sie machen systematische Verhaltensmuster sichtbar. Die folgenden Patterns treten immer wieder auf, quer durch alle Chain- und RAG-Typen:
| Pattern | Erkennungszeichen im Trace | Ursache / Gegenmittel |
|---|---|---|
| Over-Retrieval | Retriever läuft bei Fragen, die kein Dokument benötigen (z.B. reine Wissensfragen) | RAG-Routing zu pauschal → Conditional-Routing vor Retriever einbauen |
| Retry-Loop | Gleicher LLM-Call mit identischen Inputs wiederholt, jeweils error | Fehlende Fehlerbehandlung in der Chain → Error-Handling ergänzen |
| Token-Akkumulation | LLM-Input wächst mit jedem Schritt stark an | Kein Context-Management → Sliding-Window oder Summarization |
| Missing Tool Use | Agent antwortet direkt ohne Tools, obwohl passende Tools verfügbar | Tool-Beschreibung unklar → Tool-Docstring verbessern |
| Langsamer Retriever | retriever-Run dominiert die Gesamtlatenz | Zu viele k Dokumente oder langsamer Vectorstore → k reduzieren |
| Leere Retrieval-Ergebnisse | retriever-Run liefert 0 Dokumente | Query-Formulierung passt nicht zu Chunk-Stil → Query-Rewriting oder MMR |
Reales Beispiel — Over-Retrieval in einer RAG-Chain:
User: "Was ist LangSmith?"
→ Retriever: retrieve_documents(query="LangSmith") ← unnötig bei Wissensfrage
→ Tool: 0 relevante Dokumente gefunden
→ LLM: antwortet aus Modell-Wissen ← hätte direkt funktioniert
Ohne LangSmith-Trace wäre der Grund für die erhöhte Latenz nicht erkennbar gewesen. Gegenmittel: Routing-Schritt vor dem Retriever — nur bei dokumentenspezifischen Fragen retrieven.
Programmatische Pattern-Analyse mit show_trace():
from genai_lib.utilities import show_trace
# Letzte 3 Runs anzeigen
show_trace("M08-RAG-Chain", limit=3)
# Mit Step-Analyse des letzten Runs (zeigt alle Retrieval-Schritte)
show_trace("M08-RAG-Chain", show_steps=True)
show_steps=True listet alle Child-Runs (Typ, Name, Status, Dauer) — ideal um Over-Retrieval und leere Retrieval-Ergebnisse direkt im Notebook sichtbar zu machen.
Problembereiche systematisch finden (Quick Workflow)
Wenn eine Chain “irgendwie schlecht” wirkt, hilft eine feste Reihenfolge statt Ad-hoc-Debugging:
- Failed/Slow/Expensive Runs filtern (Projekt + Tags + Zeitraum)
- Top-Pattern clustern (z.B. Over-Retrieval, Token-Akkumulation, leere Ergebnisse — siehe 9.7)
- Einen Fix pro Pattern umsetzen (Prompt, Retrieval-Konfiguration, Routing)
- Vorher/Nachher vergleichen (gleiche Testfragen oder Dataset-Evals)
Im Kurs reichen Schritte 1–4 vollständig aus. Alerts und Production-Monitoring (p95-Latenz, Kostenbudgets, automatische Schwellwerte) sind für Production-Deployments relevant.
Web-UI Filter: Traces gezielt finden
Die LangSmith-Oberfläche unter eu.smith.langchain.com bietet leistungsstarke Filter — besonders nützlich, wenn das Projekt viele Runs enthält.
Nützlichste Filter-Kombinationen für den Kurs:
| Szenario | Filter | Wert |
|---|---|---|
| Nur Fehler anzeigen | Status | Error |
| Langsame Runs finden | Latency | > 10s |
| Viele Child-Runs | Child Runs | > 5 |
| Spezifische Chain | Name | contains "rag" |
| Experiment A vs. B | Tags | experiment-A / experiment-B |
| Zeitraum eingrenzen | Start Time | Last 1 hour / Last 24 hours |
Drei Kern-Views für den Kurs:
1. Debugging: Status = Error + Project = M##-...
2. Latenz: Latency > 5s + Child Runs > 3
3. Experiment: Tag "experiment-A" vs. Tag "experiment-B" (Compare-View)
Weitere Web-UI-Tipps:
- Playground direkt aus Trace: Trace öffnen → “Open in Playground” — Prompt live editieren, Modell wechseln, sofort testen
- Compare-Ansicht: Zwei Runs auswählen → “Compare” — zeigt Input/Output/Latenz/Tokens nebeneinander; ideal für Vorher/Nachher nach einem Fix
- Trace-Baum navigieren: Linke Seitenleiste zeigt verschachtelte Child-Runs; Klick auf einen Child-Run öffnet Input/Output/Latenz direkt
- Export: Run-Tabelle (gefiltert) → “Export” → CSV (nur Tabellen-Spalten); einzelne Traces → JSON (natives Format, nicht änderbar). Für vollständige Daten:
client.list_runs()+pandas.DataFrame.to_csv()
💡 Tipp: LangSmith-UI im zweiten Browser-Tab öffnen — so sind Traces direkt während der Entwicklung sichtbar, ohne den Notebook-Tab zu wechseln.
Vergleich: LangSmith vs. Alternatives
| Aspekt | LangSmith | Print/Logs | LangGraph Debug |
|---|---|---|---|
| Setup | 3 Zeilen Code | Immer verfügbar | Graph-spezifisch |
| Visualisierung | Interaktive UI | Terminal-Output | Stream-Modus |
| Historie | Persistent | Verloren nach Neustart | Session-basiert |
| Datasets | Integriert | Manuell verwalten | Nicht verfügbar |
| Team-Kollaboration | URL-Sharing | Screenshots | Nicht verfügbar |
| Produktion | Monitoring | Nicht skalierbar | Nur Development |
Fazit für den Kurs:
- Woche 1: LangSmith parallel zu Print-Debugging einführen
- Woche 2: LangSmith als primäres Debug-Tool etablieren
- Ab Woche 3: LangSmith für RAG-Evaluation und Chain-Optimierung nutzen
Häufige Fragen (FAQ)
“Werden alle Daten an LangSmith gesendet?”
Ja, standardmäßig:
- Alle Inputs und Outputs
- Metadaten (Latenz, Tokens, etc.)
- Fehler und Stack-Traces
Kontrolle:
- Sensitive Daten vorher filtern/anonymisieren
- Selective Tracing mit
@traceable(enabled=False) - Self-Hosted LangSmith für vollständige Kontrolle
“Kostet LangSmith extra?”
Free Tier: Kostenloser Einstieg verfügbar (ausreichend für erstes Ausprobieren) Paid Tiers: Verschiedene Pläne für Production-Nutzung
“Wie lange werden Traces gespeichert?”
Traces werden maximal 400 Tage aufbewahrt. Danach werden sie automatisch gelöscht.
Längerfristige Speicherung: Wichtige Runs als Dataset exportieren — Datasets unterliegen keiner automatischen Löschfrist.
# Run dauerhaft in ein Dataset überführen
client.create_example_from_run(run_id=run_id, dataset_name="wichtige-runs")
“Wie deaktiviere ich Tracing?”
# Temporär deaktivieren
os.environ["LANGSMITH_TRACING"] = "false"
# Für einzelne Funktionen
from langsmith import traceable
@traceable(enabled=False)
def nicht_getrackt():
pass
“Kann ich LangSmith ohne LangChain nutzen?”
Ja, mit dem @traceable Decorator:
from langsmith import traceable
@traceable
def custom_function(input_data):
# Beliebiger Python-Code
return result
“Was passiert, wenn ich den API-Key vergesse?”
# Setup prüft automatisch, ob Keys vorhanden sind
setup_api_keys(['OPENAI_API_KEY', 'LANGSMITH_API_KEY'], create_globals=False)
# Falls Key fehlt: Klare Fehlermeldung mit Hinweis auf Colab Secrets
Best Practice: Alle benötigten Keys zu Beginn im Setup-Block definieren.
💡 Tipp: LangSmith-UI immer im zweiten Browser-Tab öffnen – so können Traces direkt während der Entwicklung inspiziert werden!
🔑 Wichtig: Alle API-Keys werden sicher in Google Colab Secrets hinterlegt und niemals im Code sichtbar!
Abgrenzung zu verwandten Dokumenten
| Dokument | Frage |
|---|---|
| LangSmith Best Practices | Welche Tracing- und Evaluationsmuster gelten in produktionsnahen Projekten? |
| Evaluation & Observability | Welche Qualitätsfragen werden mit Traces und Testsets beantwortet? |
Version: 1.0
Stand: Mai 2026
Kurs: Generative KI mit LangChain 1.1+