Hallo zusammen, hier ist Sarah von agnthq.com. Die letzten Wochen waren verrückt, nicht wahr? Jedes Mal, wenn ich blinzele, verspricht ein neuer KI-Agent, mein Leben, meinen Arbeitsablauf oder zumindest meine Kaffee-Bestellung zu verändern. Und ehrlich gesagt, viele von ihnen tun einfach nicht was sie versprechen… Sie sind entweder zu komplex, zu nischenspezifisch oder halten einfach nicht, was sie versprechen.
Aber von Zeit zu Zeit taucht etwas wirklich Interessantes auf. Etwas, das mich wirklich zum Nachdenken bringt: „Okay, das könnte wirklich nützlich sein.“ Heute möchte ich über eines dieser Dinge sprechen. Nicht über ein ganz neues Gadget, sondern über eine Plattform, die sich kontinuierlich weiterentwickelt hat und, meiner Meinung nach, einen idealen Punkt für den praktischen Alltag erreicht hat: das neue Agenst-Framework von LangChain mit seiner verbesserten strukturierten Ausgabe und seinen Aufruffähigkeiten für Tools.
Jetzt, bevor ihr seufzt und denkt: „Oh toll, noch ein Artikel über LangChain,“ lasst mich erklären. Ich experimentiere praktisch seit dem ersten Tag mit LangChain. Ich erinnere mich an die Anfänge, als ich LLMs und Tools zusammenstellte und mich wie ein digitaler Frankenstein fühlte. Es war mächtig, das steht fest, aber oft auch ungeschickt, schwierig zu debuggen, und man hatte das Gefühl, Code in Python 2 im Jahr 2024 zu schreiben. Die Ausgaben konnten… kreativ sein, um es milde auszudrücken, und zuverlässig zu bekommen, dass ein Agent das tat, was man wollte, insbesondere bei mehreren Schritten, fühlte sich mehr wie ein Gebet als Programmierung an.
Die letzten Updates, insbesondere wie die Agenten mit den Tools interagieren und eine strukturierte Ausgabe erzeugen, haben mir wirklich die Augen geöffnet. Wir sind von einem „experimentellen Spielplatz“ zu etwas „wirklich Nützlichem für meine Freelance-Arbeit“ übergegangen. Und das ist ein großer Schritt.
Meine Frustration mit Unzuverlässigen Agenten (und wie das hilft)
Lasst mich ein Bild malen. Vor ein paar Monaten versuchte ich, einen einfachen Agenten für eine Freundin zu bauen, die ein kleines E-Commerce-Geschäft betreibt. Ihr Problem: Die Kunden stellen oft sehr ähnliche Fragen zu Produkten, Versand und Rückgaben, und sie verbrachte viel zu viel Zeit damit, Antworten zu kopieren und einzufügen. Meine Idee war ein Agent, der:
- Die Produktdetails (Preis, Verfügbarkeit) aus einer fiktiven Datenbank abruft.
- Die Versandgebiete und -zeiten überprüft.
- Eine höfliche und präzise Antwort formuliert.
Sieht einfach aus, oder? Nicht wirklich. Meine ersten Versuche mit LangChain waren ein echtes Chaos. Der Agent hätte manchmal zufällige Produkt-IDs erfunden, vergaß, das Versand-Tool aufzurufen, oder gab einfach einen gesprächigen Text statt einer prägnanten Antwort aus. Es war ein Albtraum, konstant ein spezifisches Format zu bekommen, wie ein JSON-Objekt, das die Antwort und die verwendeten Tools enthält. Ich verbrachte Stunden damit, es mit ausgefeilten Eingabeaufforderungen zu überzeugen, nur damit es bei einem bestimmten Fall scheiterte.
Hier glänzt das neue Agenten-Framework. LangChain hat wirklich die Art und Weise verbessert, wie die Agenten entscheiden, welche Tools sie verwenden, und vor allem, wie sie ihre Ergebnisse zurückmelden. Es geht nicht mehr darum, zu hoffen, dass das LLM „die Lösung findet“, sondern ihm einen klaren und strukturierten Weg aufzuzeigen.
Die Hauptidee: Bessere Toolaufrufe und strukturierte Ausgaben
Die größte Verbesserung, meiner Meinung nach, kommt aus einer Kombination von Dingen:
- Verbesserte Tool-Definition: Die Tools werden jetzt mit Pydantic-Schemas definiert, was dem LLM viel klarer macht, welche Eingaben es erwartet.
- Funktionsaufruf-APIs (z. B. OpenAI): LangChain nutzt dies unter der Haube, um die Auswahl der Tools viel zuverlässiger zu machen. Das LLM „rät“ nicht mehr, welches Tool es verwenden soll; es wird explizit auf die verfügbaren Funktionen und deren Parameter hingewiesen.
- Parser für strukturierte Ausgaben: Das ist der heilige Gral für mich. Schluss mit dem Versuch, eine Antwort aus einem unstrukturierten Text-Blob mittels Regex herauszuziehen. Wir können jetzt genau festlegen, welche Struktur wir von der finalen Antwort des Agenten erwarten.
Schauen wir uns ein einfaches Beispiel an, um dies zu verdeutlichen. Stellen wir uns vor, wir haben ein Tool, um den aktuellen Lagerbestand eines Produkts zu überprüfen.
Beispiel: Ein einfaches Lagerbestands-Tool
Zuerst definieren wir unser Tool, indem wir ein Pydantic-Modell für dessen Eingabe verwenden:
from langchain_core.tools import tool
from pydantic import BaseModel, Field
class ProductStockInput(BaseModel):
product_id: str = Field(description="Die eindeutige ID für das Produkt.")
@tool("get_product_stock", args_schema=ProductStockInput)
def get_product_stock(product_id: str) -> dict:
"""
Sucht den aktuellen Lagerbestand für eine gegebene Produkt-ID.
Gibt ein Dictionary mit product_id und stock_level zurück.
"""
# Dies würde in der Regel eine Datenbank abfragen
stock_data = {
"P101": 50,
"P102": 0, # Ausverkauft
"P103": 15
}
stock_level = stock_data.get(product_id, -1) # -1 für nicht gefunden
if stock_level == -1:
return {"product_id": product_id, "stock_level": "Produkt nicht gefunden"}
return {"product_id": product_id, "stock_level": stock_level}
tools = [get_product_stock]
Bemerkenswert ist das `args_schema` hier. Es ist entscheidend. Das weist das LLM genau darauf hin, welche Argumente `get_product_stock` erwartet und welche Typen sie haben. Keine Mehrdeutigkeit mehr.
Den Agenten mit strukturierter Ausgabe aufbauen
Jetzt bauen wir einen Agenten, der dieses Tool verwendet und vor allem seine finale Antwort strukturiert bereitstellt. Für meine E-Commerce-Freundin wollte ich, dass der Agent die Kundenanfrage, die Antwort des Agenten und alle verwendeten Tools ausgibt, alles in einem hübschen JSON-Format.
from langchain_openai import ChatOpenAI
from langchain import hub
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_core.messages import BaseMessage
from typing import List, Union, Dict, Any
# Definieren des strukturierten Ausgabeformats für die finale Antwort des Agenten
class AgentResponse(BaseModel):
original_query: str = Field(description="Die ursprüngliche Anfrage des Kunden.")
agent_answer: str = Field(description="Die vom Agenten formulierte Antwort auf die Anfrage.")
tools_used: List[str] = Field(description="Eine Liste der Namen der Tools, die der Agent verwendet hat.")
metadata: Dict[str, Any] = Field(description="Alle Metadaten oder zusätzlichen Informationen von den Tools.")
# Laden des Basis-Prompts für den OpenAI-Tools-Agenten
prompt = hub.pull("hwchase17/openai-tools-agent")
llm = ChatOpenAI(model="gpt-4-0125-preview", temperature=0) # Verwendung eines aktuellen GPT-4 für Zuverlässigkeit
# Erstellen des Agenten
agent = create_openai_tools_agent(llm, tools, prompt)
# Erstellen des Agenten-Ausführers
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# Jetzt definieren wir, wie der Agent mit using with_structured_output antworten soll
# Hier geschieht die Magie für eine zuverlässige strukturierte Ausgabe!
structured_agent_executor = agent_executor.with_structured_output(AgentResponse)
# Lassen Sie uns das testen!
query1 = "Wie ist der aktuelle Lagerbestand für das Produkt P101?"
response1 = structured_agent_executor.invoke({"input": query1})
print("\n--- Antwort 1 ---")
print(response1.json(indent=2))
query2 = "Ist das Produkt P102 verfügbar?"
response2 = structured_agent_executor.invoke({"input": query2})
print("\n--- Antwort 2 ---")
print(response2.json(indent=2))
query3 = "Was ist die Hauptstadt von Frankreich?" # Der Agent sollte unser Tool dafür nicht verwenden
response3 = structured_agent_executor.invoke({"input": query3})
print("\n--- Antwort 3 ---")
print(response3.json(indent=2))
Wenn Sie dies ausführen, werden Sie in der detaillierten Ausgabe sehen, wie das LLM zuerst den Bedarf an `get_product_stock` identifiziert, es mit der richtigen `product_id` aufruft und dann das Ergebnis nutzt, um seine `agent_answer` zu formulieren. Noch wichtiger ist, dass die *endgültige Ausgabe* ein `AgentResponse`-Objekt ist, nicht nur ein String. Das ist unglaublich leistungsfähig für die Nachbearbeitung, Protokollierung oder sogar nur zur Anzeige konsistenter Informationen für einen Benutzer.
Was ich an `with_structured_output` liebe
Diese Methode `with_structured_output` stellt einen signifikanten Wandel dar. Das bedeutet, dass ich die Antworten des Agenten zuverlässig in andere Teile meiner Anwendung integrieren kann. Ich muss keine fragile Parsing-Logik mehr schreiben. Wenn der Agent in irgendeiner Weise abweicht, fängt Pydantic dies oft ein und gibt mir einen klaren Fehler, anstatt stillschweigend zu scheitern oder Müll zurückzugeben.
Für meine E-Commerce-Freundin bedeutet das, dass ihr Kundenservice-Portal nun die Antwort des Agenten mit Vertrauen anzeigen kann, in dem Wissen, dass sie im richtigen Format vorliegt. Wir können sogar die Felder `tools_used` und `metadata` speichern, um zu verstehen, wie oft der Agent spezifische Tools einsetzt oder ob es häufige Fragen gibt, auf die er nicht antworten kann.
Über einfache Tools hinaus: Mehrstufiges Denken mit Zuverlässigkeit
Der wahre Test für einen Agenten ist oft das mehrstufige Denken. Lassen Sie uns ein weiteres Werkzeug hinzufügen: eines, um die geschätzten Versandzeiten basierend auf einer Produkt-ID und einer Versandzone zu erhalten.
from langchain_core.tools import tool
from pydantic import BaseModel, Field
# ... (ProductStockInput und get_product_stock bleiben gleich) ...
class ShippingInfoInput(BaseModel):
product_id: str = Field(description="Die eindeutige Kennung des Produkts.")
destination_zone: str = Field(description="Die Versandzone (z. B. 'Zone A', 'Zone B').")
@tool("get_shipping_info", args_schema=ShippingInfoInput)
def get_shipping_info(product_id: str, destination_zone: str) -> dict:
"""
Liefert die geschätzten Versandzeiten für ein Produkt in eine spezifische Zone.
Gibt ein Dictionary mit product_id, zone und estimated_days zurück.
"""
# Fiktive Daten für den Versand
shipping_times = {
("P101", "Zone A"): "3-5 Werktage",
("P101", "Zone B"): "5-7 Werktage",
("P103", "Zone A"): "2-4 Werktage",
("P103", "Zone B"): "4-6 Werktage",
}
key = (product_id, destination_zone)
estimated_days = shipping_times.get(key, "Variabel, bitte den Support kontaktieren")
return {"product_id": product_id, "destination_zone": destination_zone, "estimated_days": estimated_days}
tools_multi = [get_product_stock, get_shipping_info]
# Einen Agenten und einen Executor mit den neuen Werkzeugen erstellen
agent_multi = create_openai_tools_agent(llm, tools_multi, prompt)
agent_executor_multi = AgentExecutor(agent=agent_multi, tools=tools_multi, verbose=True)
structured_agent_executor_multi = agent_executor_multi.with_structured_output(AgentResponse)
# Eine mehrstufige Anfrage testen
multi_step_query = "Wie ist der Bestand für P101 und wie lange dauert der Versand nach Zone A?"
response_multi = structured_agent_executor_multi.invoke({"input": multi_step_query})
print("\n--- Mehrstufige Antwort ---")
print(response_multi.json(indent=2))
Sie werden in der detaillierten Ausgabe feststellen, dass der Agent jetzt intelligent `get_product_stock` zuerst aufruft, dann `get_shipping_info`, und die Informationen in eine konsistente Antwort kombiniert, während er die Struktur `AgentResponse` einhält. Das ist ein enormer Fortschritt im Vergleich zu den Zeiten, in denen Sie diese Werkzeugaufrufe explizit aneinanderreihen oder hoffen mussten, dass das LLM die richtige Reihenfolge ableiten könnte.
Meine Erkenntnisse & Warum das jetzt wichtig ist
Also, warum mache ich jetzt so ein Aufhebens darum? Weil es darauf hindeutet, dass LangChain-Agenten, insbesondere in Kombination mit `create_openai_tools_agent` und `with_structured_output`, endlich ein Reifegrad erreicht haben, der sie tatsächlich für Entwickler nützlich macht, die konkrete Anwendungen erstellen. Schluss mit den endlosen Prompt-Engineering-Versuchen, um eine JSON-Ausgabe zu erzwingen, Schluss mit fragilem Regex-Parsen und deutlich weniger von diesen „halluzinierten Werkzeugaufrufen“.
Praktische Tipps für Sie:
- Überdenken Sie die LangChain-Agenten: Wenn Sie vor einem Jahr versucht haben, LangChain-Agenten zu verwenden und frustriert waren, ist jetzt der richtige Zeitpunkt, ihnen eine zweite Chance zu geben. Die Verbesserungen bei den Werkzeugaufrufen und der strukturierten Ausgabe sind erheblich.
- Definieren Sie die Werkzeuge mit Pydantic: Definieren Sie Ihre Werkzeugeingaben immer mithilfe von Pydantic-Modellen mit klaren Beschreibungen. Das gibt dem LLM die beste Chance zu verstehen, wann und wie es Ihre Werkzeuge verwenden soll.
- Nutzen Sie `with_structured_output`: Das ist Ihr bester Verbündeter für eine zuverlässige Agentenintegration. Definieren Sie ein Pydantic-Modell für die endgültige Ausgabe Ihres Agenten und verwenden Sie `agent_executor.with_structured_output(YourOutputModel)`. Das wird Ihnen viele Stunden Debugging und Parsing ersparen.
- Beginnen Sie einfach, und erweitern Sie dann: Versuchen Sie nicht, sofort einen Super-Agenten zu bauen. Beginnen Sie mit ein oder zwei einfachen Werkzeugen und einer klaren Ausgabestruktur. Sobald dies zuverlässig funktioniert, fügen Sie schrittweise mehr Komplexität hinzu.
- Verwenden Sie detaillierte Werkzeugbeschreibungen: Das Feld `description` in Ihrem `@tool`-Dekorator ist das, was das LLM liest, um zu entscheiden, ob es ein Werkzeug verwenden soll. Seien Sie klar, prägnant und erklären Sie, was das Werkzeug *macht* und was es *zurückgibt*.
- Verwenden Sie den OpenAI-Funktionsaufruf: Obwohl sich dieser Artikel auf LangChain konzentriert, kommt die zugrunde liegende Zuverlässigkeit oft von LLMs wie den GPT-Modellen von OpenAI, die über starke Funktionsaufruf-Fähigkeiten verfügen. Stellen Sie sicher, dass Sie Modelle verwenden, die dies unterstützen, um bessere Ergebnisse zu erzielen.
Ich bin überzeugt, dass diese Fortschritte die Erstellung intelligenter Agenten viel zugänglicher und vor allem zuverlässiger machen. Für jeden, der KI-gesteuerte Funktionen entwickelt, sei es ein Kundenservice-Bot, ein Datenanalyse-Assistent oder einfach das Automatisieren von lästigen Aufgaben, ist die Fähigkeit, vorhersehbar mit einem Agenten zu interagieren und strukturierte Daten zu erhalten, ein bedeutender Wandel. Dies hat Agenten von einer beeindruckenden Demo zu einem echten nützlichen Werkzeug im Arsenal der Entwickler gemacht.
Das war’s für heute. Probieren Sie es aus und lassen Sie mich wissen, was Sie aufbauen! Teilen Sie Ihre Gedanken und Erfahrungen in den Kommentaren unten. Viel Spaß beim Erstellen von Agenten!
🕒 Published: