Erstellung von Human-in-the-Loop-Agenten mit LangGraph und Elasticsearch

Erfahren Sie, wie Sie mit LangGraph und Elasticsearch Human-in-the-Loop-Agenten erstellen, die Menschen in den Entscheidungsprozess einbeziehen, um kontextuelle Lücken zu schließen und Tool-Aufrufe vor ihrer Ausführung zu überprüfen.

Agent Builder ist ab sofort als technische Vorschau verfügbar. Starten Sie mit einer Elastic Cloud-Testversion und lesen Sie die Dokumentation zum Agent Builder hier.

In diesem Artikel werden wir untersuchen, wie LangGraph und Elasticsearch kombiniert werden können, um eine Human-in-the-Loop (HITL)-Anwendung zu erstellen. Dieser Ansatz ermöglicht es KI-Systemen, Nutzer direkt in den Entscheidungsprozess einzubeziehen, wodurch Interaktionen zuverlässiger und kontextsensitiver werden. Wir werden ein praktisches Beispiel mit einem kontextgesteuerten Szenario implementieren, um zu demonstrieren, wie LangGraph-Workflows mit Elasticsearch integriert werden können, um Daten abzurufen, Benutzereingaben zu verarbeiten und verfeinerte Ergebnisse zu liefern.

Voraussetzungen

  • NodeJS Version 18 oder neuer
  • OpenAI-API-Schlüssel
  • Elasticsearch 8.x+ Deployment

Warum LangGraph für Produktions-HITL-Systeme verwenden

In einem früheren Artikel haben wir LangGraph und seine Vorteile für den Aufbau eines RAG-Systems mit LLMs sowie bedingten Kanten vorgestellt, um automatisch Entscheidungen zu treffen und Ergebnisse anzuzeigen. Manchmal möchten wir nicht, dass das System komplett autonom agiert, sondern dass die Nutzer innerhalb der Ausführungsschleife Optionen auswählen und Entscheidungen treffen. Dieses Konzept heißt Human in the Loop.

Human-in-the-loop oder in der Schleife

Dabei handelt es sich um ein KI-Konzept, das es einer realen Person ermöglicht, mit KI-Systemen zu interagieren, um mehr Kontext zu liefern, Reaktionen zu bewerten, Reaktionen zu bearbeiten, nach weiteren Informationen zu fragen usw. Dies ist in Szenarien mit niedriger Fehlertoleranz wie Compliance, Entscheidungsfindung oder Inhaltsgenerierung sehr nützlich und trägt zur Verbesserung der Zuverlässigkeit der LLM-Outputs bei.

Ein häufiges Beispiel ist, wenn Ihr Programmierassistent Sie um die Erlaubnis bittet, einen bestimmten Befehl am Terminal auszuführen, oder Ihnen den Schritt-für-Schritt-Denkprozess zeigt, den Sie genehmigen müssen, bevor Sie mit dem Programmieren beginnen.

Elasticsearch + LangGraph: Wie sie interagieren

LangChain ermöglicht uns die Verwendung von Elasticsearch als Vektorspeicher und die Durchführung von Abfragen innerhalb von LangGraph-Anwendungen, was nützlich ist, um Volltext- oder semantische Suchen auszuführen, während LangGraph verwendet wird, um den spezifischen Workflow, die Tools und die Interaktionen zu definieren. HITL wird außerdem als zusätzliche Interaktionsebene mit dem Nutzer hinzugefügt.

Praktische Umsetzung: Human-in-the-loop

Stellen wir uns einen Fall vor, in dem ein Anwalt eine Frage zu einem Fall hat, den er kürzlich übernommen hat. Ohne die richtigen Hilfsmittel müsste er juristische Artikel und Präzedenzfälle manuell suchen, sie vollständig lesen und dann interpretieren, wie sie auf seine Situation anwendbar sind. Mit LangGraph und Elasticsearch können wir jedoch ein System aufbauen, das eine Datenbank von Rechtspräzedenzfällen durchsucht und eine Fallanalyse erstellt, die die spezifischen Details und den Kontext des Anwalts einbezieht.

Der Workflow beginnt, wenn der Anwalt eine Rechtsfrage einreicht. Das System führt eine Vektorsuche in Elasticsearch durch, ruft die relevantesten Präzedenzfälle ab und präsentiert sie dem Anwalt zur Auswahl in natürlicher Sprache. Nach der Auswahl erstellt der LLM einen Analyseentwurf und prüft, ob die Informationen vollständig sind. An dieser Stelle kann der Workflow zwei Pfaden folgen: Wenn alles klar ist, wird direkt eine endgültige Analyse generiert; wenn nicht, pausiert er, um eine Klärung vom Anwalt anzufordern. Sobald der fehlende Kontext bereitgestellt wird, schließt das System die Analyse ab und gibt sie unter Berücksichtigung der Klärungen zurück.

Nachfolgend ein von LangGraph erstellter Graph, der zeigt, wie die App am Ende der Entwicklung aussehen wird. Jeder Node repräsentiert ein Tool oder eine Funktionalität:

Datensatz

Hier ist der Datensatz, der für dieses Beispiel verwendet wird. Dieser Datensatz enthält eine Sammlung von Präzedenzfällen, die jeweils einen Fall mit Verzögerungen bei der Leistungserbringung, die Begründung des Gerichts und das Endergebnis beschreiben.

Einrichtung der Ingestion und des Indexes

Die Indexeinrichtung und die Logik zur Daten-Ingestion sind in der Datei dataIngestion.ts definiert, in der wir Funktionen deklarieren, die die Indexerstellung übernehmen. Dieses Setup ist kompatibel mit der LangChain Vektorspeicher-Schnittstelle für Elasticsearch.

Hinweis: Die Mapping-Konfiguration ist ebenfalls in der dataIngestion.ts Datei enthalten.

Pakete installieren und Umgebungsvariablen einrichten

Lassen Sie uns ein Node.js-Projekt mit den Standardeinstellungen initialisieren:

  • @elastic/Elasticsearch: Elasticsearch-Client für Node.js. Wird verwendet, um Verbindungen herzustellen, Indizes zu erstellen und Abfragen auszuführen.
  • @langchain/community: Bietet Integrationen für von der Community unterstützte Tools, einschließlich des ElasticVectorSearch-Stores.
  • @langchain/core: Kernbausteine von LangChain, wie Ketten, Prompts und Hilfsmittel.
  • @langchain/langgraph: Fügt graphbasierte Orchestrierung hinzu, die Workflows mit Knoten, Kanten und Zustandsverwaltung ermöglicht.
  • @langchain/openai: Bietet Zugriff auf OpenAI-Modelle (LLMs und Einbettungen) über LangChain.
  • dotenv: Lädt Umgebungsvariablen aus einer.env Datei in process.env.
  • tsx: Ist ein nützliches Tool zum Ausführen von TypeScript-Code.

Führen Sie folgenden Befehl in der Konsole aus, um alle zu installieren:

Erstellen Sie eine .env Datei, um die Umgebungsvariablen einzurichten:

Wir werden TypeScript zum Schreiben des Codes verwenden, da es eine Ebene der Typsicherheit und eine bessere Entwicklererfahrung bietet. Erstellen Sie eine TypeScript-Datei mit dem Namen main.ts und fügen Sie den Code des nächsten Abschnitts ein.

Pakete importieren

In der Datei main.ts importieren wir zunächst die benötigten Module und initialisieren die Umgebungsvariablenkonfiguration. Dazu gehören die Kernkomponenten von LangGraph, die OpenAI-Modellintegrationen und der Elasticsearch-Client.

Wir importieren außerdem Folgendes aus der dataIngestion.ts-Datei :

  • ingestData: eine Funktion, die den Index erstellt und die Daten aufnimmt.
  • Dokument und Dokumentmetadaten: Schnittstellen, die die Dokumentstruktur des Datensatzes definieren.

Elasticsearch Vector Store Client, Embeddings Client und OpenAI-Client

Dieser Code initialisiert den Vektorspeicher, den Embeddings-Client und einen OpenAI-Client.

Das Workflow-Statusschema der Anwendung hilft bei der Kommunikation zwischen den Nodes:

Im Zustandsobjekt geben wir durch die Nodes die Nutzeranfrage, die daraus extrahierten Konzepte, die abgerufenen Rechtspräzedenzfälle und etwaige Mehrdeutigkeiten durch. Der Zustand verfolgt auch den vom Nutzer ausgewählten Präzedenzfall, die während des Prozesses erstellte Entwurfsanalyse und die endgültige Analyse, sobald alle Klärungen abgeschlossen sind.

Knoten

searchPrecedents: Dieser Node führt eine Ähnlichkeitssuche im Elasticsearch-Vektorspeicher basierend auf dem Eingang des Nutzers durch. Er ruft bis zu 5 übereinstimmende Dokumente ab und druckt sie aus, damit der Nutzer sie einsehen kann.

Präzedenzfallauswahl: Dieser Node ermöglicht es dem Nutzer, mithilfe natürlicher Sprache denjenigen Anwendungsfall auszuwählen, der durch die Proximity-Suche ermittelt wurde und am besten zur Frage passt. An diesem Punkt unterbricht die Anwendung den Workflow und wartet auf die Nutzereingabe.

selectPrecedent: Dieser Node sendet den Nutzerinput zusammen mit den abgerufenen Dokumenten zur Interpretation, sodass eines von ihnen ausgewählt werden kann. Das LLM erfüllt diese Aufgabe, indem es eine Zahl zurückgibt, die das Dokument repräsentiert, das es aus der natürlichen Spracheingabe des Nutzers ableitet.

createDraft: Dieser Node generiert die erste rechtliche Analyse basierend auf dem vom Nutzer gewählten Präzedenzfall. Er verwendet einen LLM, um zu beurteilen, inwieweit der gewählte Präzedenzfall auf die Frage des Anwalts anwendbar ist, und um festzustellen, ob dem System genügend Informationen vorliegen, um fortzufahren.

Wenn der Präzedenzfall direkt angewendet werden kann, erstellt der Node einen Analyseentwurf und nimmt den richtigen Pfad zum End-Node. Wenn das LLM Unklarheiten wie undefinierte Vertragsbedingungen, fehlende Zeitrahmendetails oder unklare Bedingungen erkennt, gibt es eine Markierung zurück, die darauf hinweist, dass eine Klärung erforderlich ist, zusammen mit einer Liste der spezifischen Informationen, die bereitgestellt werden müssen. In diesem Fall löst die Mehrdeutigkeit den linken Pfad des Graphen aus.

Die beiden möglichen Pfade des Graphen sehen folgendermaßen aus:

Der linke Pfad enthält einen zusätzlichen Node, der die Klarstellung übernimmt.

RequestClarification: Dieser Node löst den zweiten Human-in-the-Loop-Schritt aus, wenn das System feststellt, dass dem Analyseentwurf grundlegender Kontext fehlt. Der Workflow wird unterbrochen und der Nutzer wird aufgefordert, die fehlenden Vertragsdetails zu klären, die der vorherige Node entdeckt hat.

generateFinalAnalysis: Dieser Node erstellt die endgültige rechtliche Analyse, indem er den ausgewählten Präzedenzfall mit dem vom Nutzer bereitgestellten zusätzlichen Kontext kombiniert, falls nötig. Anhand der im vorherigen HITL-Schritt gesammelten Klarstellung fasst das LLM die Begründung des Präzedenzfalls, die vom Nutzer bereitgestellten Vertragsdetails und die Bedingungen zusammen, die bestimmen, ob ein Verstoß stattgefunden haben könnte.

Der Node liefert eine vollständige Analyse, die rechtliche Auslegung und praktische Empfehlungen integriert.

Graph erstellen:

Im Graph können wir sehen, dass die bedingte Kante die Bedingung für die Wahl des „finalen“ Pfades definiert. Wie gezeigt, hängt die Entscheidung nun davon ab, ob der Analyseentwurf Unklarheiten aufgedeckt hat, die einer weiteren Klärung bedürfen.

Zusammengefasst zur Ausführung:

Führen Sie das Skript aus:

Nachdem wir den gesamten Code zugewiesen haben, führen wir die Datei main.ts aus, indem wir den folgenden Befehl im Terminal eingeben:

Sobald das Skript ausgeführt wird, wird die Frage „Stellt ein Muster wiederholter Verzögerungen einen Verstoß dar, selbst wenn jede einzelne Verzögerung geringfügig ist?“ an Elasticsearch gesendet, um eine Proximity-Suche durchzuführen, und die aus dem Index abgerufenen Ergebnisse werden angezeigt. Die App erkennt, dass mehrere relevante Präzedenzfälle mit der Abfrage übereinstimmen, pausiert die Ausführung und bittet den Nutzer, bei der Klarstellung zu helfen, welcher rechtliche Präzedenzfall am relevantesten ist:

Das Interessante an dieser Anwendung ist, dass wir in natürlicher Sprache eine Option auswählen können, wobei das LLM den Input des Nutzers interpretiert, um die richtige Wahl zu ermitteln. Lassen Sie uns sehen, was passiert, wenn wir den Text eingeben: „Fall H“

Das Modell nimmt die Erläuterungen des Nutzers auf und integriert sie in den Workflow, um mit der endgültigen Analyse fortzufahren, sobald genügend Kontext vorhanden ist. In diesem Schritt nutzt das System auch die zuvor festgestellte Unklarheit: Die Entwurfsanalyse hat fehlende Vertragsdetails hervorgehoben, die die rechtliche Auslegung maßgeblich beeinflussen könnten. Diese „fehlenden Informationen“ dienen dem Modell als Leitfaden, um festzustellen, welche Klarstellungen unerlässlich sind, um Unsicherheiten zu beseitigen, bevor eine verlässliche endgültige Meinung abgegeben werden kann.

Der Nutzer muss bei dem nächsten Input die gewünschten Erläuterungen angeben. Versuchen wir es mit „Vertrag erfordert 'pünktliche Lieferung' ohne Zeitpläne. 8 Verzögerungen von 2-4 Tagen über 6 Monate. 50.000 $ Verluste durch 3 verpasste Kundenfristen. Verkäufer benachrichtigt, aber das Muster hält an.“

Dieser Ausgang zeigt die letzte Phase des Workflows, in der das Modell den ausgewählte Präzedenzfall (Fall H) und die Klärungen des Anwalts integriert, um eine vollständige rechtliche Analyse zu generieren. Das System erklärt, warum das Muster der Verzögerungen wahrscheinlich einen Verstoß darstellt, skizziert die Faktoren, die diese Interpretation stützen, und gibt praktische Empfehlungen. Insgesamt zeigt der Output, wie die HITL-Klärungen Mehrdeutigkeiten auflösen und es dem Modell ermöglichen, eine fundierte, kontextspezifische rechtliche Stellungnahme zu erstellen.

Andere reale Szenarien

Diese Art von Anwendung, die Elasticsearch, LangGraph und Human-in-the-Loop verwendet, kann in anderen Apps nützlich sein wie:

  • Bei der Überprüfung von Tool-Aufrufen vor ihrer Ausführung, zum Beispiel im Finanzhandel, genehmigt ein Mensch Kauf-/Verkaufsaufträge, bevor sie erteilt werden.
  • Fügen Sie bei Bedarf zusätzliche Parameter an, zum Beispiel bei der Triage des Kundensupports, bei der ein menschlicher Mitarbeiter die richtige Problemkategorie auswählt, wenn die KI mehrere mögliche Interpretationen des Problems des Kunden findet.

Und es gibt viele Anwendungsfälle, die es noch zu entdecken gilt, in denen Human-in-the-Loop ein entscheidender Faktor sein wird.

Fazit

Mit LangGraph und Elasticsearch können wir Agenten erstellen, die eigene Entscheidungen treffen und als lineare Workflows agieren oder Bedingungen erfüllen, die sie dazu veranlassen, den einen oder anderen Pfad zu wählen. Mit Human-in-the-Loop können die Agenten den tatsächlichen Nutzer in den Entscheidungsprozess einbeziehen, um kontextuelle Lücken zu füllen und Bestätigungen für Systeme anzufordern, bei denen Fehlertoleranz entscheidend ist.

Einer der Vorteile dieses Ansatzes ist, dass man einen großen Datensatz mithilfe der Elasticsearch-Funktionen filtern und dann mit einem LLM ein einzelnes Dokument als Nutzerauswahl erhalten kann. Dieser letzte Schritt wäre mit Elasticsearch allein viel komplizierter, da es viele Möglichkeiten gibt, wie ein Mensch ein Ergebnis in natürlicher Sprache interpretieren kann.

Mit diesem Ansatz bleibt das System schnell und Token-effizient, da wir dem LLM nur das senden, was für die endgültige Entscheidung benötigt wird, und nicht die gesamten Datensätze. Gleichzeitig wird die Absicht des Nutzers sehr genau erkannt und so lange iteriert, bis die gewünschte Option ausgewählt ist.

Zugehörige Inhalte

Sind Sie bereit, hochmoderne Sucherlebnisse zu schaffen?

Eine ausreichend fortgeschrittene Suche kann nicht durch die Bemühungen einer einzelnen Person erreicht werden. Elasticsearch wird von Datenwissenschaftlern, ML-Ops-Experten, Ingenieuren und vielen anderen unterstützt, die genauso leidenschaftlich an der Suche interessiert sind wie Sie. Lasst uns in Kontakt treten und zusammenarbeiten, um das magische Sucherlebnis zu schaffen, das Ihnen die gewünschten Ergebnisse liefert.

Probieren Sie es selbst aus