<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[KI - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[KI - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/de/search-labs/blog/category/ai</link>
    </image>
    <link>https://www.elastic.co/de/search-labs/blog/category/ai</link>
    <atom:link href="https://www.elastic.co/de/search-labs/rss/category/ai.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[de]]></language>
    <lastBuildDate>Sun, 20 Sep 2026 17:46:30 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Beschreiben statt zeichnen: KI-native Kibana-Dashboards über MCP und ES|QL]]></title>
    <description><![CDATA[Vom Prompt zum Dashboard. Erfahren Sie, wie Sie Kibana-Dashboards in natürlicher Sprache mit example-mcp-dashbuilder erstellen: eine Open-Source-MCP-Anwendung, die ES|QL-Abfragen schreibt, interaktive Diagramme erstellt und voll funktionsfähige Dashboards direkt in Kibana exportiert.]]></description>
    <content:encoded><![CDATA[<p>example-mcp-dashbuilder ist eine Open-Source-MCP-Anwendung, die einen Prompt in einfachem Englisch in ein interaktives Kibana-Dashboard verwandelt – und das alles direkt im Chatfenster Ihres Editors. Beschreiben Sie das gewünschte Dashboard, und die KI ermittelt Ihre Indexstruktur, schreibt korrekte ES|QL-Aggregationen für jede Visualisierung und rendert währenddessen eine Inline-Vorschau. Wenn Sie fertig sind, exportiert ein Befehl ein voll funktionsfähiges Kibana-Dashboard: echte Lens-Visualisierungen, Ihr exaktes Rasterlayout und benutzerdefinierte Farben werden beibehalten. Aktuell werden sechs Diagrammtypen unterstützt, wobei die vollständige Kibana Lens geplant ist.</p><h2>Was ist ein Kibana-Dashboard-Builder?</h2><p>Wie wäre es, wenn Sie das gewünschte Dashboard in einfachem Englisch beschreiben könnten und es dann mit interaktiven Diagrammen, einem Drag-and-Drop-Layout und einem Export nach Kibana mit einem Klick erscheinen würde?</p><p>Genau das macht <a href="https://github.com/elastic/example-mcp-dashbuilder.git"><strong>example-mcp-dashbuilder</strong></a>. Es handelt sich um eine Open-Source-Anwendung (Modellkontextprotokoll (MCP)), die KI-Assistenten mit Elasticsearch verbindet und es Ihnen ermöglicht, vollständige Kibana-Dashboards durch Konversation zu erstellen. Kein Durchklicken durch Menüs. Kein manuelles Schreiben von Visualisierungskonfigurationen. Beschreiben Sie einfach, was Sie benötigen, und die KI untersucht Ihre Daten, schreibt die ES|QL-Abfragen (Elasticsearch Query Language), erstellt die Diagramme und liefert ein lebendiges, interaktives Dashboard – alles im Chatfenster Ihres Editors.</p><h2><strong>Vom Prompt zum Dashboard in Sekunden</strong></h2><p>So sieht das in der Praxis aus. Sie geben beispielsweise Folgendes ein:</p><p>„Erstellen Sie mir ein Web-Traffic-Dashboard aus logstash-* mit Gesamtanfragen, übertragenen Bytes im Laufe der Zeit, wichtigen geografischen Quellen und einer Aufschlüsselung der Antwortcodes.“</p><p>Die KI daraufhin:</p><ol><li><p><strong>Erkennt Ihre Daten:</strong> Listet Indizes auf, inspiziert Feldzuordnungen.</p></li><li><p><strong>Schreibt ES|QL-Abfragen:</strong> Angepasst an Ihr Schema, mit den richtigen Aggregationen.</p></li><li><p><strong>Erstellt Visualisierungen:</strong> Balkendiagramme, Liniendiagramme, Metriken mit Sparklines, Heatmaps, Kreisdiagramme.</p></li><li><p><strong>Organisiert alles:</strong> Zusammenklappbare Abschnitte, aussagekräftige Titel, ordentliches Layout.</p></li><li><p><strong>Rendert eine interaktive Vorschau:</strong> Direkt im Chat, mit Tooltips, einem Zeitwähler und Drag-and-Drop.</p></li></ol><p>Jedes Diagramm wird bei der Erstellung inline angezeigt, sodass Sie den Fortschritt in Echtzeit verfolgen können. Dann zeigt <code>view_dashboard</code> das vollständige Dashboard mit allen Panels, die im 48-spaltigen Raster von Kibana angeordnet sind.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt75af5d9042d141b5/6a17e99dbe608675a4004792/dcbf47c4f17bf1a184fb0167408ebeb861ef6c9d-1404x1568.png" alt="Zwei Diagramme, die in der example-mcp-dashbuilder Schnittstelle angezeigt werden. Das erste ist ein vertikales Balkendiagramm mit dem Titel „Wichtige geografische Quellen“, das die Anzahl der Anfragen nach Ländercode zeigt. Das zweite ist ein Kreisdiagramm mit dem Titel „Aufschlüsselung der HTTP-Reaktionscodes“ und zeigt Segmente für 200, 404 und 503 Reaktionen." /><p><em>Einzelne Inline-Diagrammvorschau.</em></p><h2><strong>Bereitgestellt von ES|QL</strong></h2><p>Alle Datenabrufe verwenden <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/esql.html">ES|QL</a>, die Pipe-basierte Abfragesprache von Elasticsearch. Die KI verarbeitet nicht nur rohe Abfragen, sondern nutzt auch integrierte ES|QL-Syntax zusammen mit Informationen zur Struktur Ihrer Daten, um korrekte, effiziente Abfragen für jeden Visualisierungstyp zu schreiben.</p><p>Der Server enthält eine umfassende ES|QL-Referenz als MCP-Ressource. Bevor eine Abfrage geschrieben wird, liest die KI diese Referenz, um die verfügbaren Befehle, Funktionen und Muster zu verstehen. In Kombination mit einem Dataviz-Best-Practices-Leitfaden (der auch als Ressource diente) weiß die KI nicht nur, <em>wie</em> sie Abfragen gestaltet, sondern auch, <em>was</em> eine gute Visualisierung ausmacht:</p><ul><li><p>Verwenden Sie <code>BUCKET(@timestamp, 1 day)</code> für Zeitreihen; gruppieren Sie immer <code>SORT</code> nach dem Zeitfeld.</p></li><li><p>Beschränken Sie Kreisdiagramme mit <code>| SORT value DESC | LIMIT 6</code> auf sechs Abschnitte.</p></li><li><p>Wählen Sie Balkendiagramme für Kategorienvergleiche, Liniendiagramme für Trends und Kennzahlen für Leistungsindikatoren (KPI).</p></li></ul><h2><strong>KI-gestützte Datenexploration mit ergebnisoffener Analyse</strong></h2><p>Ein Dashboard zu erstellen, das Sie bereits in Ihrem Kopf entworfen haben, ist das eine. Die Frage lautet: „Was ist an diesem Index interessant?“ und eine brauchbare Antwort zu bekommen, ist das andere. Dafür muss die KI wissen, wie man <em>erkundet</em>, nicht nur, wie man zeichnet.</p><p>example-mcp-dashbuilder versendet eine <code>analysis://guidelines</code>-Ressource, die einen strukturierten Explorationsablauf definiert: Daten profilieren, gezielte Aggregationen ausführen, Muster aufzeigen, die es wert sind, untersucht zu werden, Diagramme für die interessantesten Ergebnisse erstellen und Drilldown-Abfragen vorschlagen, die der Nutzer als Nächstes haben könnte. Triggerphrasen wie „Analysiere meine Logs“ oder „Finde Muster in diesem Index“ veranlassen die KI, das Playbook zu lesen, bevor sie irgendetwas anderes tut. So entsteht durch einen offenen Prompt eine zusammenhängende Untersuchung und nicht ein zufälliger Haufen von Diagrammen.</p><p>Das Ergebnis: Sie können der KI einen unbekannten Index übergeben und erhalten einen Ausgangspunkt zurück: ein Dashboard sowie eine kurze Liste von Prompts, wie „Das mir aufgefallen, soll ich mir das genauer ansehen?“.</p><h2><strong>Kibana-Dashboard Export und Import: Ein vollständiger Rundgang</strong></h2><p>Der Export-/Import-Rundgang ist der Punkt, an dem example-mcp-dashbuilder für Teams, die bereits mit Kibana arbeiten, wirklich nützlich wird. example-mcp-dashbuilder ist etwas Eigenständiges, eine dialogorientierte Dashboard-Oberfläche, die in Ihren Editor integriert ist, aber Ihre Arbeit nicht dort einschließt. Hier erstellte Dashboards können bei Bedarf in Kibana übertragen werden, und bestehende Kibana-Dashboards können umgekehrt zur KI-gestützten Bearbeitung importiert werden.</p><h3><strong>Nach Kibana exportieren</strong></h3><p>Wenn Sie mit Ihrem Dashboard zufrieden sind, exportieren Sie es mit einem Befehl:</p><p>„Dieses Dashboard nach Kibana exportieren“</p><p>Jedes Panel wird als echte Kibana Lens-Visualisierung dargestellt. Die Übersetzung bewahrt:</p><ul><li><p><strong>ES|QL-Abfragen:</strong> Direkt übertragen als Lens ES|QL-Datenquellen.</p></li><li><p><strong>Rasterpositionen:</strong> Das gleiche 48-Spalten-System, das Kibana verwendet, Ihr Layout sieht also identisch aus.</p></li><li><p><strong>Benutzerdefinierte Farben:</strong> Serienpaletten, metrische Hintergründe, Heatmap-Farbrampen.</p></li></ul><p>Das Ergebnis ist ein voll funktionsfähiges Kibana-Dashboard. Kein Screenshot. Keine Einbettung. Ein echtes Dashboard, das Sie teilen und in Kibana weiter bearbeiten können.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1921c74c2833cabe/6a17e99f6864a4a712b687da/5e27777bc0a82cafb373943f65298bdb21d66176-1999x902.png" alt="Zwei Dashboards werden nebeneinander angezeigt. Das linke Dashboard mit dem Titel „Web-Traffic bearbeiten – Logstash (Dashbuilder)“ zeigt aktuelle Traffic-Metriken, ein Traffic-Volumen-Panel, ein geografisches Balkendiagramm und ein Kreisdiagramm mit Antwortcodes an. Das rechte Dashboard zeigt ein ähnliches Layout mit höheren Gesamtwerten und beinhaltet ein Traffic-Volumen-Panel, ein geografisches Balkendiagramm und ein Kreisdiagramm mit Antwortcodes." /><p><em>Kibana-Dashboard und Dashboard im Cursor-Chat nebeneinander.</em></p><h3><strong>Aus Kibana importieren</strong></h3><p>Der Rundgang funktioniert auch in die andere Richtung:</p><p>„Importieren Sie das Kibana-Dashboard mit der ID abc-123“</p><p>Hierbei wird ein bestehendes Kibana-Dashboard abgerufen, dessen Lens-Visualisierungen in bearbeitbare Diagrammkonfigurationen übersetzt, das Rasterlayout und die Abschnitte beibehalten und alles in example-mcp-dashbuilder geladen. Von dort aus können Sie es mit natürlicher Sprache ändern und erneut exportieren.</p><p>Dadurch wird die KI zu einem Mitarbeiter in Ihrem bestehenden Kibana-Workflow, nicht zu einem Ersatz.</p><h2><strong>Benutzerdefinierte Themen und Farben</strong></h2><p>Sie wünschen sich ein Dashboard mit Ihrem Branding? Stellen Sie einfach folgende Frage:</p><p>„Erstellen Sie ein Dashboard im pinken Design mit benutzerdefinierten Farben"</p><p>Jeder Visualisierungstyp unterstützt eine benutzerdefinierte Farbkonfiguration:</p><ul><li><p><strong>Diagramme:</strong> <code>palette</code> akzeptiert ein Array von Hex-Farben für Serien und Segmente.</p></li><li><p><strong>Metriken:</strong> <code>color</code> legt die Hintergrundfarbe fest.</p></li><li><p><strong>Heatmaps:</strong> <code>colorRamp</code> definiert den Verlauf von niedrigen zu hohen Werten.</p></li></ul><p>Die KI erkennt Themenwünsche auf natürliche Weise. Sagen Sie „maritimes Design“ und es wählt Blau- und Türkistöne aus. Sagen Sie „Unsere Markenfarben verwenden“ und geben Sie Hexadezimalwerte an, diese werden beim Export in Kibana übernommen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2bc7cddbdef81354/6a17e9a1ec0f89ee155a665e/4aceba013ac9cbb4a541109efd6acddf8a6ec47d-1562x1568.png" alt="Ein thematisches E-Commerce-Dashboard mit benutzerdefinierten pinken Farben. Das Layout zeigt oben die Umsatz- und Auftrags-KPIs, darunter einen eingeklappten Trendabschnitt und zwei kategorienbasierte Diagramme: ein Balkendiagramm für den Umsatz nach Kategorie und ein Kreisdiagramm für die Bestellungen nach Kategorie." /><p><em>Ein thematisches Dashboard mit benutzerdefinierten Farben.</em></p><p><strong>Funktionsweise von example-mcp-dashbuilder: MCP-Architektur</strong></p><p>example-mcp-dashbuilder basiert auf <a href="https://modelcontextprotocol.io/">MCP</a>, dem offenen Standard zur Verbindung von KI-Assistenten mit externen Werkzeugen und Daten. Hier die Architektur im Überblick:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6c0cd879646e9947/6a17e9a36864a4c408b687df/cbfeabe151ec1ee2b0655f4d17468c9bb358df7e-1024x559.png" alt="Ein Architekturdiagramm, das den mit dem MCP-Server verbundenen MCP-Host zeigt, der Tools, Ressourcen und Anweisungen enthält. Darunter befindet sich eine MCP-App-Box mit Elastic Charts und dem Rasterlayout von Kibana. Elasticsearch und Kibana werden unten angezeigt, wobei Pfeile sie mit der MCP-App verbinden." /><p>Der <strong>MCP-Server</strong> stellt 25 Tools bereit, die die KI direkt aufrufen kann, vom Ausführen von ES|QL-Abfragen, dem Exportieren von Dashboards sowie einige interne „App-only“-Tools, die die Inline-Vorschau nutzt, um Daten abzurufen, Layoutänderungen zu speichern und Zeitfelder zu erkennen. Er dient als Ressource für drei Bereiche: Als Leitfaden mit Best Practices für die Datenvisualisierung, als ES|QL-Referenz und als Playbook für die Tiefenanalyse, das bei offenen Prompts („Analysiere meine Logs“, „Was ist in diesem Index interessant?“) zum Einsatz kommt. Er wird entweder über stdio oder HTTP ausgeführt, der HTTP-Transport unterstützt streamfähige Antworten und Sitzungsmanagement, sodass mehrere Clients mit einem Server verbunden werden können.</p><p>Die <strong>MCP-App</strong> dient als interaktive Vorschau. Sie basiert auf React, <a href="https://elastic.github.io/elastic-charts">Elastic Charts</a> und <a href="https://eui.elastic.co/">Elastic UI</a>, gebündelt in einer einzigen, eigenständigen HTML-Datei. Wenn die KI <code>view_dashboard</code> aufruft oder ein Diagramm erstellt, rendert der Host dieses HTML in einem Sandbox-iframe. Die App kommuniziert vollständig über das <a href="https://modelcontextprotocol.io/extensions/apps/overview">MCP Apps-Protokoll</a> mit dem Server und nutzt <code>callServerTool()</code> über postMessage, um Daten abzurufen, Layouts zu speichern und Zeitfelder zu erkennen. Es gibt keinen lokalen Server, keinen Port zum Konfigurieren, keine externe Netzwerkabhängigkeit.</p><p>Das bedeutet, dass es mit jedem MCP-kompatiblen Client funktioniert: Cursor, Claude Desktop, Claude.ai, VS Code mit Copilot und mehr.</p><h2><strong>Welche Diagrammtypen unterstützt example-mcp-dashbuilder?</strong></h2><p>Zum Zeitpunkt der Erstellung dieses Artikels werden sechs Diagrammtypen unterstützt, die die gängigsten Dashboard-Szenarien abdecken:</p><p>Typ</p><p>Am besten für</p><p>Beispiel</p><p>Balkendiagramm</p><p>Kategorien vergleichen</p><p>Anfragen nach geografischer Quelle</p><p>Liniendiagramm</p><p>Trends im Laufe der Zeit</p><p>Pro Stunde übertragene Bytes</p><p>Bereich</p><p>Volumen im Laufe der Zeit</p><p>Volumen der Anfrage im Laufe der Zeit</p><p>Kreisdiagramm</p><p>Teil des Ganzen (maximal sechs Stücke)</p><p>Verteilung von Antwortcodes</p><p>Metrik</p><p>Einzelner KPI mit Sparkline</p><p>Gesamtzahl der Anfragen mit stündlichem Trend</p><p>Heatmap</p><p>Muster in zwei Dimensionen</p><p>Anfragen nach Wochentag und Stunde</p><p>Die Dashboards unterstützen ausklappbare Abschnitte zur besseren Übersicht, eine Zeitauswahl mit automatischer Zeitfelderkennung sowie die Möglichkeit, mehrere Dashboards zu speichern und zwischen ihnen zu wechseln. Parallele Chat-Sitzungen bleiben durch einen <code>dashboardId</code>-Thread, der bei jedem Tool-Aufruf durchlaufen wird, voneinander isoliert.</p><h2><strong>Installation und Ausführung von example-mcp-dashbuilder</strong></h2><p>example-mcp-dashbuilder ist Open-Source und sofort einsatzbereit. Sie benötigen Node.js 22+, eine Elasticsearch-Instanz (lokal oder Elastic Cloud) und einen MCP-kompatiblen Client.</p><p><strong>Claude Desktop:</strong> Laden Sie die neueste <code>.mcpb</code> von <a href="https://github.com/elastic/example-mcp-dashbuilder/releases">GitHub Releases</a> herunter und klicken Sie doppelt darauf. Claude Desktop fordert Sie zur Eingabe Ihrer Elasticsearch-Zugangsdaten auf.</p><p><strong>Cursor / Claude Code / VS Code Copilot:</strong> Richten Sie Ihre MCP-Konfiguration auf den veröffentlichten Tarball – kein Klon, kein <code>npm install</code>:</p>{
  "mcpServers": {
    "example-mcp-dashbuilder": {
      "type": "stdio",
      "command": "npx",
      "args": ["https://github.com/elastic/example-mcp-dashbuilder/releases/latest/download/example-mcp-dashbuilder.tgz"]
    }
  }
}<p>Legen Sie <code>ES_NODE, ES_API_KEY</code> (oder <code>ES_USERNAME / ES_PASSWORD</code>) und <code>KIBANA_URL</code> als Umgebungsvariablen fest. Wenn Sie lieber von der Quelle aus arbeiten möchten, klonen Sie das Repository und führen Sie <code>npm run setup</code> als interaktiven Assistenten aus, der Elasticsearch lokal sowie Elastic Cloud (Cloud ID + API-Schlüssel) verwaltet.</p><p>Beginnen Sie mit der Entwicklung:</p><p>„Erkunden Sie den Log-Index und erstellen Sie mir ein möglichst aussagekräftiges Dashboard.“</p><p>Die KI übernimmt dann den Rest. 😉</p><h2><strong>Roadmap: Die Zukunft von example-mcp-dashbuilder</strong></h2><p>Dies ist eine frühe Version, die wir aktiv weiter entwickeln. Dies sind einige Bereiche, auf die wir uns konzentrieren:</p><ul><li><p><strong>Weitere Diagrammtypen:</strong> Gauge, Donut, Treemap, Datentabelle und Tag Cloud, passend zu den vollständigen Funktionen von Lens.</p></li><li><p><strong>Dashboards auf Git pushen: </strong>Schreiben Sie Dashboard-Konfigurationen in ein Repository für Versionskontrolle und Code-Review-Workflows.</p></li><li><p><strong>Verbesserte Fehlerbehandlung: </strong>Detaillierteres Feedback, wenn ES|QL-Abfragen fehlschlagen, mit Vorschlägen für allgemeine Problemlösungen.</p></li><li><p><strong>Effektivere Analyseströme: </strong>Erweiterung des Deep-Analysis-Playbooks, um mehr Datenformen (Logs, Metriken, Traces) abzudecken.</p></li></ul><p>Wir würden uns freuen zu erfahren, was Sie damit entwickeln. Probieren Sie es aus, melden Sie Probleme und lassen Sie uns wissen, welche Visualisierungen und Workflows für Ihr Team am nützlichsten wären.</p><p><a href="https://github.com/elastic/example-mcp-dashbuilder">GitHub: elastic/example-mcp-dashbuilder</a></p><h3>Danksagungen</h3><p>Vielen Dank an <a href="mailto:walter.rafelsberger@elastic.co">Walter Rafelsberger</a> und <a href="mailto:tim.schnell@elastic.co">Tim Schnell</a> für ihren Beitrag zur Umsetzung.</p><h3>FAQ</h3><p><strong>Was ist example-mcp-dashbuilder?</strong> example-mcp-dashbuilder ist eine Open-Source-MCP (Model Context Protocol) Anwendung, die KI-Assistenten mit Elasticsearch verbindet. Es ermöglicht Ihnen, ein Kibana-Dashboard in einfachem Englisch zu beschreiben und generiert automatisch ES|QL-Abfragen, erstellt Visualisierungen und liefert ein interaktives Live-Dashboard direkt im Chatfenster Ihres Editors.</p><p><strong>Welche Abfragesprache verwendet example-mcp-dashbuilder, um Daten abzurufen?</strong> Alle Datenabrufe verwenden ES|QL, die Pipe-basierte Abfragesprache von Elasticsearch. Der MCP-Server enthält eine integrierte ES|QL-Referenz, die die KI vor dem Schreiben einer Abfrage liest, um eine korrekte Syntax und effiziente Aggregationen für jeden Visualisierungstyp zu gewährleisten.</p><p><strong>Kann ich mit example-mcp-dashbuilder erstellte Dashboards nach Kibana exportieren?</strong> Ja. Mithilfe von „Dieses Dashboard nach Kibana exportieren“ wird jedes Panel in eine echte Kibana Lens-Visualisierung übersetzt, wobei ES|QL-Abfragen, das 48-spaltige Rasterlayout, benutzerdefinierte Farben und Serienpaletten erhalten bleiben. Das Ergebnis ist ein voll funktionsfähiges Kibana-Dashboard, kein Screenshot oder Einbettung.</p><p><strong>Kann ich ein bestehendes Kibana-Dashboard in example-mcp-dashbuilder importieren, um eine KI-unterstützte Bearbeitung durchzuführen?</strong> Ja. Durch Angabe einer Kibana-Dashboard-ID wird das vorhandene Dashboard abgerufen, dessen Lens-Visualisierungen in bearbeitbare Diagrammkonfigurationen übersetzt und in example-mcp-dashbuilder geladen. Anschließend können Sie das Dashboard mithilfe natürlicher Sprache modifizieren und wieder nach Kibana exportieren.</p><p><strong>Welche MCP-Clients sind mit example-mcp-dashbuilder kompatibel?</strong> example-mcp-dashbuilder funktioniert mit jedem MCP-kompatiblen Client, einschließlich Cursor, Claude Desktop, Claude.ai und VS Code mit Copilot. Es unterstützt sowohl stdio- als auch HTTP-Transport, ohne dass eine lokale Server- oder Portkonfiguration erforderlich ist.</p><p><strong>Welche Diagrammtypen werden von example-mcp-dashbuilder unterstützt?</strong> Die aktuelle Version unterstützt sechs Diagrammtypen: Balkendiagramm, Liniendiagramm, Flächendiagramm, Kreisdiagramm, Metrik (mit Sparkline) und Heatmap. Geplante Ergänzungen umfassen Gauge, Donut, Treemap, Datentabelle und Tag Cloud, um den vollen Funktionsumfang von Kibana Lens zu erreichen.</p><p><strong>Was benötige ich, um example-mcp-dashbuilder auszuführen?</strong> Sie benötigen Node.js 22 oder höher, eine Elasticsearch-Instanz (lokal oder Elastic Cloud) und einen MCP-kompatiblen Client. Legen Sie die Umgebungsvariablen ES_NODE, ES_API_KEY (oder ES_USERNAME/ES_PASSWORD) und KIBANA_URL fest. Für Claude Desktop laden Sie die .mcpb- Datei von GitHub Releases herunter und installieren sie per Doppelklick.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/kibana-dashboard-builder-mcp-esql</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/kibana-dashboard-builder-mcp-esql</guid>
    <category><![CDATA[Kibana]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Stratoula Kalafateli]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2a69a35d6d51ff47/6a17e9a5b1e11339cd79f2b3/0d38385fd64c1445b2e955ba20532570f7f38679-1280x720.png" length="0" type="image/png"/>
    <pubDate>Fri, 22 May 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Entitätsauflösung mit Elasticsearch, Teil 4: Die ultimative Herausforderung]]></title>
    <description><![CDATA[Lösung und Bewertung von Herausforderungen bei der Entitätsauflösung in einem äußerst vielfältigen Datensatz zur „ultimativen Herausforderung“, der entwickelt wurde, um Abkürzungen zu verhindern.]]></description>
    <content:encoded><![CDATA[<p>Wir haben nun die Implementierung intelligenter Entitätsauflösung auf zwei Arten gesehen. Beide Ansätze beginnen auf dieselbe Weise: Aufbereitung und Extraktion der Entitäten, gefolgt vom Abruf der Kandidaten mit Elasticsearch. Anschließend bewerten wir diese Kandidaten mithilfe eines großen Sprachmodells (LLM), entweder durch promptbasierte JSON-Generierung oder durch Funktionsaufrufe, und fordern vom Modell eine transparente Begründung für seine Entscheidung.</p><p>Wie wir im <a href="https://www.elastic.co/search-labs/blog/elasticsearch-entity-resolution-llm-function-calling">vorherigen Beitrag</a> gesehen haben, ist die Konstanz, die durch Funktionsaufrufe ermöglicht wird, nicht nur eine praktische Optimierung, sondern essenziell. Nachdem wir strukturelle Fehler aus dem Evaluationskreislauf entfernt hatten, verbesserten sich die Ergebnisse in Standardszenarien (wie denen im Tier-4-Datensatz) dramatisch.</p><p>Doch eine offensichtliche Frage bleibt noch zu beantworten:</p><p><em>Funktioniert dieser Ansatz noch, wenn es kompliziert wird?</em></p><p>Die Entitätsauflösung in der realen Welt schlägt selten in einfachen Fällen fehl. Sie scheitert, wenn Namen Sprach-, Kultur-, Schrift-, Zeit- und Unternehmensgrenzen überschreiten. Sie scheitert, wenn auf Menschen mit Titeln anstelle von Namen Bezug genommen wird, wenn Unternehmen Namen ändern, wenn Transliterationen nicht konstant sind und wenn Kontext (nicht die Schreibweise) das Einzige ist, was eine Erwähnung mit einer realen Entität verbindet.</p><p>Für den letzten Beitrag dieser Serie haben wir das System einer sogenannten <strong>ultimativen Herausforderung</strong> unterzogen.</p><h2>Was macht dies zur ultimativen Herausforderung?</h2><p>In früheren Auswertungen haben wir das System mit zunehmend komplexeren Datensätzen getestet. Als wir die im vorherigen Beitrag besprochene Stufe 4 erreichten, hatten wir es bereits mit einer Mischung aus Spitznamen, Titeln, mehrsprachigen Namen und semantischen Bezügen zu tun. Diese Tests zeigten, dass die Architektur selbst solide war, aber dass Zuverlässigkeitsprobleme, insbesondere fehlerhaftes JSON, den Rückruf unterdrückten.</p><p>Mit dem implementierten Funktionsaufruf hatten wir endlich eine stabile Grundlage. So konnten wir eine interessantere Frage stellen:</p><p><em>Kann eine einheitliche Pipeline </em><em><strong>viele verschiedene Arten</strong></em><em> von Entitätsauflösungsproblemen gleichzeitig bewältigen?</em></p><p>Der ultimative herausfordernde Datensatz wurde darauf ausgelegt, genau diese Dimension zu erreichen.</p><p>Anstatt sich auf eine einzelne Schwierigkeit (wie Spitznamen oder Transliteration) zu konzentrieren, kombiniert dieser Datensatz <strong>mehr als 50 verschiedene Herausforderungstypen</strong>, darunter:</p><ul><li><p>Kulturelle Namenskonventionen.</p></li><li><p>Titelbasierte Referenzen.</p></li><li><p>Geschäftliche Beziehungen und historische Namensänderungen.</p></li><li><p>Mehrsprachige und skriptübergreifende Erwähnungen.</p></li><li><p>Zusammengesetzte Herausforderungen, die mehrere der oben genannten Punkte kombinieren.</p></li></ul><p>Entscheidend ist, dass es hier nicht um die Optimierung für einen einzigen, eng begrenzten Anwendungsfall geht. Es geht darum zu testen, ob das <em>Entwurfsmuster</em> Bestand hat, wenn sich die Regeln von Entität zu Entität ändern.</p><h2>Der Datensatz auf einen Blick</h2><p>Der ultimativ herausfordernde Datensatz besteht aus:</p><ul><li><p><strong>50 Entitäten</strong>, darunter Personen, Unternehmen und Institutionen.</p></li><li><p><strong>~60 Artikel</strong>, mit unterschiedlicher Struktur und sprachlicher Komplexität.</p></li><li><p><strong>51 verschiedene Herausforderungskategorien</strong>, grob unterteilt in:</p><ul><li><p>Kulturelle Namenskonventionen.</p></li><li><p>Titel und beruflichem Kontext.</p></li><li><p>Geschäfts- und Unternehmensbeziehungen.</p></li><li><p>Mehrsprachigkeit und Transliterationsherausforderungen.</p></li><li><p>Kombinierten und Grenzfall-Szenarien.</p></li></ul></li></ul><p>Zu Beginn der Serie haben wir gesehen, dass die Verwendung von generativer KI (GenKI) zur Erstellung von Datensätzen ein zweischneidiges Schwert sein kann. Ohne sie wäre es äußerst schwierig, ausreichend große und vielfältige Testdaten zusammenzustellen. Aber wenn das Modell nicht kontrolliert wird, neigt es dazu, die Dinge zu einfach zu machen.</p><p>Bei einer frühen Generationsüberprüfung stellten wir beispielsweise fest, dass das Modell Formulierungen wie „der russische Präsident“ als expliziten Aliasnamen für Wladimir Putin enthielt. Das mag heute vernünftig erscheinen, aber es widerspricht dem Zweck der Prüfung der Kontextauflösung. Was passiert, wenn der Artikel Russland in den 1990er Jahren behandelt? Das System sollte die richtige Entität aus dem Kontext ableiten und sich nicht auf einen fest codierten Alias verlassen.</p><p>Aus diesem Grund wurde dieser Datensatz bewusst so konzipiert, dass <strong>Abkürzungen nicht funktionieren</strong>. Pseudonyme werden nicht explizit aufgeführt, wenn das System die Bedeutung erschließen soll. Beschreibende Phrasen sind nicht vorab mit Entitäten verknüpft. Korrekte Treffer hängen oft vom Kontext auf Artikelebene ab, nicht nur vom lokalen Text.</p><p><strong>Wichtiger Hinweis:</strong> Obwohl wir die Fähigkeiten des Systems in verschiedenen Szenarien demonstrieren, ist dies dennoch ein Bildungsprototyp. Produktionssysteme, die die Überwachung von sanktionierten Entitäten in der realen Welt handhaben, würden zusätzliche Validierung, Compliance-Prüfungen, Audit-Trails und eine spezialisierte Handhabung für sensible Anwendungsfälle erfordern.</p><h2>Warum diese Szenarien schwierig sind</h2><p>Im ersten Beitrag dieser Reihe haben wir ein einfaches, aber mehrdeutiges Beispiel vorgestellt: „Das neue Swift-Update ist da!“ Die Herausforderung besteht darin, dass „Swift“ je nach Kontext auf mehrere reale Entitäten aufgelöst werden kann. Dieses Beispiel verdeutlicht eine grundlegendere Wahrheit: Natürliche Sprache ist von Natur aus mehrdeutig.</p><p>Die Entitätsauflösung ist daher nicht nur ein Problem des Zeichenfolgenabgleichs. Menschen verlassen sich routinemäßig auf gemeinsames Wissen, kulturelle Normen und situativen Kontext, um Referenzen zu lösen, und oft merken wir gar nicht, dass wir das tun.</p><p>Betrachten wir ein paar gängige Fälle:</p><ul><li><p>Ein Titel wie „der Präsident“ ist ohne geopolitischen und zeitlichen Kontext bedeutungslos.</p></li><li><p>Ein Firmenname kann sich je nach Zeitpunkt der Artikelveröffentlichung auf ein Mutterunternehmen, eine Tochtergesellschaft oder eine ehemalige Marke beziehen.</p></li><li><p>Der Name einer Person kann in verschiedenen Reihenfolgen, Schriften oder Transliterationen erscheinen, abhängig von Sprache und Kultur.</p></li><li><p>Die gleiche Phrase kann in verschiedenen Kontexten legitimerweise auf unterschiedliche Entitäten verweisen, und das System muss in der Lage sein, Matches genauso zuversichtlich <em>abzulehnen</em>, wie sie zu akzeptieren.</p></li></ul><p>Es gibt kein einzelnes Regelwerk, das all dies sauber abdeckt. Deshalb trennt dieser Prototyp die verschiedenen Bereiche so konsequent:</p><ul><li><p>Elasticsearch schränkt den Kandidatenraum effizient und transparent ein.</p></li><li><p>Das LLM wird nur dort verwendet, wo ein Urteil erforderlich ist, und ist gezwungen, sich selbst zu erklären.</p></li><li><p>Abruf und Schlussfolgerung bleiben getrennte Schritte.</p></li></ul><p>Diese Trennung wird umso wichtiger, je größer die Vielfalt der Herausforderungen ist.</p><h2>So geht das System mit Vielfalt ohne Spezialfälle um</h2><p>Eines der interessantesten Ergebnisse dieser Bewertung ist, was <em>sich nicht geändert hat</em>:</p><ul><li><p>Wir haben <strong>keine</strong> spezielle Logik für japanische Namen hinzugefügt.</p></li><li><p>Wir haben <strong>keine</strong> benutzerdefinierten Regeln für arabische Patronyme hinzugefügt.</p></li><li><p>Wir haben <strong>keine</strong> fest codierten Mappings für historische Firmennamen hinzugefügt.</p></li></ul><p>Stattdessen basierte das System auf denselben Kernzutaten, die früher in der Serie eingeführt wurden:</p><ul><li><p>Mit Kontext angereicherte Entitäten, die für semantische Suchen indexiert sind.</p></li><li><p>Hybrider Abruf (exakt, per Alias und semantisch) in Elasticsearch.</p></li><li><p>Eine kleine, gut definierte Gruppe von Kandidatenmatches.</p></li><li><p>LLM-Bewertung eingeschränkt durch Funktionsaufruf und Minimalschemata.</p></li></ul><p>Das deutet darauf hin, dass die Flexibilität des Systems von <strong>Repräsentation und Architektur</strong> herrührt, nicht von einer ständig wachsenden Sammlung von Regeln.</p><p>Wenn das System erfolgreich ist, liegt das daran, dass die richtigen Kandidaten ermittelt werden und das LLM ausreichend Kontext hat, um zu erklären, warum eine Referenz einer bestimmten Entität zugeordnet wird oder nicht.</p><h2>Ergebnisse: Wie hat es abgeschnitten?</h2><p>Im ultimativ herausfordernden Datensatz erzielte das System folgende Gesamtergebnisse:</p><ul><li><p><strong>Präzision:</strong> ~91 %</p></li><li><p><strong>Rückruf:</strong> ~86 %</p></li><li><p><strong>F1-Score:</strong> ~89 %</p></li><li><p><strong>LLM-Annahmequote:</strong> ~72 %</p></li></ul><h3>Leistung nach Herausforderungstyp</h3><p>Die Aufschlüsselung der Ergebnisse nach Herausforderungstyp zeigt Stärken und Schwächen:</p><p><strong>Die stärkste Leistung (100 % F1-Score)</strong> wurde in folgenden Bereichen beobachtet:</p><ul><li><p>Schriftübergreifender Abgleich (kyrillische, koreanische, chinesische Unternehmen).</p></li><li><p>Hebräische Szenarien (Patronyme, Berufstitel, religiöse Titel, Transliteration).</p></li><li><p>Unternehmenshierarchien (Luft- und Raumfahrt, diversifizierte Fertigungsunternehmen, Konzerne mit mehreren Geschäftsbereichen).</p></li><li><p>Berufsbezeichnungen (akademisch, militärisch, politisch, religiös).</p></li><li><p>Kombinierte japanische Szenarien mit mehreren Schriftsystemen.</p></li></ul><p><strong>Starke Leistung (80–99 % F1-Score)</strong> umfassten:</p><ul><li><p>Internationale politische Persönlichkeiten (98 %).</p></li><li><p>Historische Namensänderungen (90 %).</p></li><li><p>Komplexe Unternehmenshierarchien (89 %).</p></li><li><p>Japanische Firmennamen (93 %).</p></li><li><p>Cross-Script-Transliteration (86 %).</p></li><li><p>Arabische Patronyme (86 %).</p></li></ul><p><strong>Problematischere Bereiche</strong> waren:</p><ul><li><p>Erweiterte Transliteration (Chinesisch, Koreanisch): 0 % F1.</p></li><li><p>Bestimmte japanische Szenarien (Höflichkeitsformen, Namensreihenfolge, Variationen des Schriftsystems): ~67 % F1.</p></li><li><p>Einige arabische Szenarien (Unternehmensnamen, institutionelle Referenzen): ~40 % F1.</p></li></ul><p>Wichtig ist hier, <em>warum</em> das System in diesen Fällen Schwierigkeiten hatte. Die Fehler waren nicht auf das Scheitern des Gesamtansatzes zurückzuführen, sondern auf Einschränkungen in bestimmten Komponenten, insbesondere dem dichten Vektormodell, das für die semantische Suche in bestimmten mehrsprachigen Szenarien verwendet wird.</p><p>Da Abruf und Beurteilung klar getrennt sind, erfordert die Leistungssteigerung keine Neuprogrammierung des Systems. Der Austausch eines leistungsfähigeren mehrsprachigen Einbettungsmodells, die Anreicherung des Entitätskontextes oder die Verfeinerung der Suchstrategien würde die Ergebnisse in diesen Kategorien verbessern, ohne die Kernarchitektur zu verändern.</p><p>Aus architektonischer Sicht ist das der eigentliche Erfolgsmaßstab.</p><h2>Was uns das über das Design verrät</h2><p>Beim Rückblick auf die Serie lassen sich einige Muster erkennen:</p><ul><li><p><strong>Vorbereitung ist wichtiger als kluges Matching. </strong>Die Anreicherung von Entitäten mit Kontextinformationen im Vorfeld reduziert spätere Mehrdeutigkeiten erheblich.</p></li><li><p><strong>LLMs sind als Bewertungs- und nicht als Abrufsysteme am wertvollsten. </strong>Sie um eine Erklärung zu bitten, <em>warum</em> eine Übereinstimmung sinnvoll ist, ist weitaus wirkungsvoller als sie um eine Suche zu bitten.</p></li><li><p><strong>Zuverlässigkeit ermöglicht Genauigkeit. </strong>Der Funktionsaufruf hat nicht nur JSON bereinigt, sondern auch den Abruf von Informationen freigegeben, die bereits in der Abrufphase latent waren.</p></li><li><p><strong>Verallgemeinerung schlägt Spezialisierung. </strong>Eine kleine Anzahl gut gewählter Abstraktionen bewältigte Dutzende von Aufgabentypen ohne benutzerdefinierte Logik.</p></li></ul><p>Aus diesem Grund ist der Prototyp bewusst Elasticsearch-nativ und konservativ in der Verwendung von LLMs. Das Ziel besteht nicht darin, das Suchen zu ersetzen. Es geht darum, das Suchen in Situationen erklärbar zu machen, in denen die Bedeutung wichtig ist.</p><h2>Fazit</h2><p>Die ultimative Herausforderung bestand nicht darin, perfekte Metriken zu verfolgen; es ging darum, eine grundlegendere Frage zu beantworten:</p><p><em>Kann eine transparente, suchbasierte, LLM-gestützte Architektur mit der Mehrdeutigkeit realer Entitäten umgehen, ohne in Regeln oder Blackboxes zu zerfallen?</em></p><p>Für diesen Bildungsprototyp lautet die Antwort ja, mit klaren Vorbehalten in Bezug auf Produktionshärtung, Compliance, Überwachung und Datenqualität. Wenn Sie Systeme erstellen, die begründen müssen, <em>warum</em> ein Entitätsabgleich vorgenommen wurde, ist dieses Muster eine ernsthafte Überlegung wert. Ich hoffe, diese Serie hat gezeigt, dass die Entitätsauflösung kein Mysterium sein muss. Mit der richtigen Aufteilung der Anliegen wird sie zu etwas, worüber man nachdenken, was man messen und verbessern kann.</p><p>Diese Arbeit deutet auch auf ein breiteres architektonisches Muster hin. Daraus entsteht eine leichte, aber wichtige Weiterentwicklung der klassischen Retrieval-Augmented-Generation (RAG). Anstatt die Abfrage direkt in die Generierung einfließen zu lassen, führen wir einen expliziten Bewertungsschritt ein. Das LLM wird zunächst zur Beurteilung und Plausibilitätsprüfung der abgerufenen Kandidaten verwendet, und nur die als geeignet befundenen Ergebnisse dürfen die Generierung erweitern. Sie können sich das als Generation-Augmented Retrieval-Augmented Generation with Evaluation oder GARAGE vorstellen, denn wer weiß nicht ein gutes Akronym zu schätzen?</p><p>Welche anderen Anwendungsfälle könnten von diesem Muster profitieren? Systeme, die Vertrauen, Transparenz und nachvollziehbare Argumentation erfordern, sind natürliche Kandidaten. Die künftige Arbeit in diesem Bereich sollte sich als ebenso überzeugend erweisen wie die Ergebnisse, die wir hier gesehen haben, und ich bin gespannt, wie sich die Gemeinschaft weiter entwickelt.</p><h2>Nächste Schritte: Versuchen Sie es selbst</h2><p>Möchten Sie die ultimative Herausforderung in Aktion sehen? Schauen Sie sich das <a href="https://github.com/jesslm/entity-resolution-lab-public/tree/main/notebooks#:~:text=5%20minutes%20ago-,05_ultimate_challenge_v3.ipynb,-Initial%20public%20lab"><strong>Ultimate Challenge-Notebook</strong></a> für eine vollständige Anleitung mit realen Implementierungen, detaillierten Erklärungen und praktischen Beispielen an.</p><p>Die vollständige Pipeline zur Entitätsauflösung demonstriert die Kernkonzepte und die Architektur, die für den produktiven Einsatz erforderlich sind. Sie können es als Grundlage nutzen, um Systeme zu entwickeln, die Nachrichtenartikel überwachen, Erwähnungen von Entitäten verfolgen und Fragen beantworten, welche Entitäten in welchen Artikeln erscheinen – und das alles, während Transparenz und Erklärbarkeit erhalten bleiben.
</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/entity-resolution-elasticsearch-llm-challenges</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/entity-resolution-elasticsearch-llm-challenges</guid>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[Hybride Suche]]></category>
    <dc:creator><![CDATA[Jessica Moszkowicz]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc58be329ffebcd60/6a17043e47d49c0bc62d88ab/70fb0ff949f6db9ac9b8a28ecb4329ab915ebf46-720x420.png" length="0" type="image/png"/>
    <pubDate>Fri, 13 Mar 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Entitätsauflösung mit Elasticsearch & LLMs, Teil 2: Abgleich von Entitäten mit LLM-Bewertung und semantischer Suche]]></title>
    <description><![CDATA[Verwendung semantischer Suche und transparenter LLM-Bewertung zur Entitätsauflösung in Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>In<a href="https://www.elastic.co/search-labs/blog/entity-resolution-llm-elasticsearch"> Teil 1</a> haben wir unsere Watchlist vorbereitet und Entitätserwähnungen extrahiert. Nun können wir die schwierige Frage beantworten: Auf welche Entität bezieht sich die Erwähnung eigentlich? Kehren wir zu dem Beispiel im ersten Blog dieser Serie zurück, das verdeutlicht, warum wir eine Entitätsauflösung benötigen: „Das Swift-Update ist da!“ Stellen Sie sich vor, diese Überschrift wird von etwas mehr Kontext begleitet:</p><ol><li><p>Das neue Swift-Update ist da! Entwickler sind gespannt darauf, die neuen Features auszuprobieren.</p></li><li><p>Das neue Swift-Update ist da! Das neue Album erscheint nächsten Monat.</p></li></ol><p>Mit diesem zusätzlichen Kontext sollten wir den Namen „Swift“ der richtigen Entität zuordnen können.</p><p>Im <a href="https://www.elastic.co/search-labs/blog/entity-resolution-llm-elasticsearch">vorherigen Beitrag</a> haben wir unsere Watchlist eingerichtet und die Entitäten mit zusätzlichem Kontext angereichert. Anhand unserer obigen Beispiele müssen wir mindestens die folgenden beiden Elemente in der Liste haben: Taylor Swift und Swift Programming Language. Wir haben auch besprochen, wie wir Entitätserwähnungen aus Text extrahieren. Beide Beispiele würden „Swift“ extrahieren. Mit diesen Zutaten, der angereicherten Watchlist und den extrahierten Entitäten, sind wir endlich bereit, den Star der Show vorzustellen: den Entitätsabgleich.</p><p><strong>Denken Sie daran:</strong> Dies ist ein pädagogischer Prototyp, der entwickelt wurde, um Konzepte zum Abgleich von Entitäten zu vermitteln. Produktionssysteme könnten verschiedene große Sprachmodelle (LLMs), benutzerdefinierte Abgleichsregeln, spezialisierte Bewertungspipelines oder Ensemble-Ansätze verwenden, die mehrere Abgleichsstrategien kombinieren.</p><h2>Das Problem: Warum der Abgleich schwierig ist</h2><p>Die menschliche Sprache ist eine bemerkenswerte Sache. Eine ihrer interessantesten Eigenschaften ist ihre unendliche Kreativität. Wir können eine unendliche Anzahl neuer Sätze erzeugen und verstehen. Ist es dann verwunderlich, dass exakte Übereinstimmungen bei der Entitätsauflösung selten sind? Autoren bemühen sich, kreativ zu sein, wenn sie können. Es wäre ziemlich mühsam, wenn wir immer die vollständigen Namen schreiben und lesen müssten, wenn eine Entität erwähnt wird. Exakte Übereinstimmungen sind zwar einfach, aber die Realität sieht so aus, dass wir einen ausgefeilteren Ansatz zur Entitätsauflösung benötigen: einen, der robust genug ist, um zumindest einen Teil der grenzenlosen Kreativität menschlicher Autoren zu bewältigen. Deshalb unterteilen wir das Problem in zwei Schritte: Mit Elasticsearch werden plausible Kandidaten skaliert abgerufen, und anschließend wird mit einem LLM beurteilt, ob sich diese Kandidaten tatsächlich auf dieselbe reale Entität beziehen.</p><h2>Die Lösung: Dreistufiger Abgleich mit transparenter LLM-Bewertung</h2><p>Wir befinden uns mitten in einem Paradigmenwechsel in der Art und Weise, wie wir Computer nutzen. Genauso wie der Aufstieg des Internets uns vom lokalen Computing zu einem global vernetzten Netzwerk geführt hat, verändert die generative KI grundlegend die Art und Weise, wie Inhalte, Code und Informationen erstellt werden. Tatsächlich wurde der pädagogische Prototyp, der diese Serie begleitet, fast ausschließlich „Vibe-codiert“ unter Verwendung eines LLMs mit sorgfältiger Eingabe durch den Autor. Das soll nicht heißen, dass LLMs die Produktivität der menschlichen Sprache erreicht haben oder erreichen werden, aber es bedeutet, dass wir jetzt eine leistungsstarke Ressource haben, die uns bei der Entitätsauflösung unterstützt.</p><p>Ein häufiges Muster, das wir mit GenAI verwenden, ist Retrieval-Augmented Generation (RAG). Hier bedeutet <em>Abrufen</em> das Abrufen von Entitätskandidaten (nicht das Generieren von Antworten), und das LLM wird ausschließlich für die Bewertung und Erklärung von Übereinstimmungen verwendet. Obwohl wir ein LLM um Unterstützung bei der End-to-End-Lösung von Entitäten bitten <em>könnten</em>, ist das sowohl zeitlich als auch finanziell kostspielig. RAG hilft LLMs bei ihrer Arbeit, indem es effizientere Wege nutzt, um dem LLM Kontext bereitzustellen, und ermöglicht es dem LLM so, effizient bei der Entitätsauflösung zu helfen.</p><p>Für den Abrufteil von RAG greifen wir erneut auf Elasticsearch zurück. Zunächst ermitteln wir potenzielle Übereinstimmungen mithilfe einer Kombination aus exaktem Abgleich, Abgleich mit Aliasen und hybrider Suche, die Stichwort- und semantische Suche kombiniert. Sobald wir diese potenziellen Übereinstimmungen gefunden haben, schicken wir sie an ein LLM zur Bewertung. Das LLM fungiert als der letzte Übereinstimmungsbewerter. Wir lassen das LLM außerdem seine Argumentation erläutern, was ein wichtiges Unterscheidungsmerkmal zu anderen Entitätsauflösungssystemen darstellt. Ohne diese Erklärungen ist die Entitätsauflösung eine Blackbox; mit ihnen können wir selbst sehen, warum eine Übereinstimmung Sinn ergibt.</p><h2>Schlüsselkonzepte: Drei-Schritte-Abgleich, hybride Suche und transparente LLM-Bewertung</h2><p><strong>Was ist der Drei-Schritte-Abgleich?</strong> Zu Beginn dieses Projekts haben wir die Hypothese aufgestellt, dass die semantische Suche ein entscheidender Bestandteil des Systems sein wird, aber nicht jeder Abgleich erfordert eine so ausgefeilte Suche. Um effizient Übereinstimmungen zu finden, gehen wir das Problem progressiv an. Zuerst überprüfen wir exakte Übereinstimmungen mit der Stichwortsuche. Wenn wir eine solche Übereinstimmung finden, ist unsere Arbeit getan und wir können weitermachen. Wenn der exakte Abgleich fehlschlägt, wenden wir uns dem Aliasabgleich zu. Im Prototyp wird der Einfachheit halber auch der Aliasabgleich mit Stichwörtern durchgeführt. In der Produktion können Sie diesen Schritt durch Normalisierung, Transliterationsregeln, Fuzzy Matching oder kuratierte Aliastabellen erweitern. Wenn wir in den ersten beiden Schritten immer noch keinen potenziellen Treffer gefunden haben, dann ist es an der Zeit, die semantische Suche über die hybride Suche von Elasticsearch mit Reciprocal Rank Fusion (RRF) einzuführen.</p><p><strong>Was ist die hybride Suche?</strong> In Elasticsearch können wir die semantische Suche nutzen, um bedeutungsvolle Übereinstimmungen zu finden, die Kontext berücksichtigen. Elasticsearch wird häufig für Vektorsuche und hybride Abfrageverfahren eingesetzt. Semantische Ähnlichkeit ist sehr aussagekräftig, aber sie ist kein Ersatz für strukturiertes Filtern (z. B. nach Zeitspannen, Orten oder Identifikatoren) und ist oft unnötig, wenn eine exakte Übereinstimmung verfügbar ist. Elasticsearch hat sich mit der lexikalischen Suche einen Namen gemacht, die sich hervorragend für Aufgaben eignet, bei denen die semantische Suche nicht ausreicht. Um beide Ansätze voll auszuschöpfen, verwenden wir die lexikalische Suche neben der semantischen Suche in einer einzigen hybriden Abfrage. Anschließend führen wir die Ergebnisse zusammen, um mithilfe von RRF die wahrscheinlichsten Übereinstimmungen zu finden. Im Prototyp werden die oberen zwei Ergebnisse zu potenziellen Übereinstimmungen, die zur LLM-Bewertung gesendet werden können.</p><p><strong>Warum die LLM-Bewertung?</strong> LLM-Bewertungen und -Erklärungen ermöglichen es unserem System, Ambiguität und Kontext transparent zu behandeln. Dies ist entscheidend für Fälle wie „der Präsident“, die sich auf mehrere Entitäten beziehen können, abhängig vom Kontext, aber es ermöglicht auch, dass Dinge wie Spitznamen und kulturelle Variationen gut im System funktionieren. Und schließlich müssen wir bei geschäftskritischen Aufgaben, wie der Identifizierung von Personen aus Sanktionslisten, wissen, warum ein Treffer akzeptiert wurde, um dem System vertrauen zu können. Entscheidend ist, dass das LLM nicht den gesamten Korpus durchsucht; es bewertet nur die kleine Anzahl von Kandidaten, die von Elasticsearch zurückgegeben werden.</p><h2>Reale Ergebnisse: Übereinstimmung mit der LLM-Argumentation</h2><p>Eine große Herausforderung bei jeder Aufgabe der natürlichen Sprachverarbeitung ist die Erstellung eines Referenzdokuments, eines „Lösungsschlüssels“, der uns mitteilt, was die zu erwartenden Ergebnisse sind. Ohne diese Grundlage ist es nahezu unmöglich zu beurteilen, wie gut ein System eine Aufgabe erfüllt. Doch die Erstellung eines solchen Dokuments kann ein mühsamer Prozess sein. Für den Prototyp zur Entitätsauflösung haben wir uns erneut an generative KI gewandt, um Unterstützung bei der Einrichtung von Testdaten zu erhalten.</p><p>Zunächst definierten wir mehrere Herausforderungstypen, wie Spitznamen und Transliteration, und baten dann das LLM, eine gestufte Sammlung von Datensätzen zu erstellen, die für das System zunehmend größer und anspruchsvoller werden sollte. Die Erstellung der Datensätze war weniger einfach, als man es sich erhoffen könnte. Das LLM hatte eine starke Neigung zum „Betrügen“, indem es zu einfach wurde, die richtige Antwort zu erhalten. Eine der Herausforderungen konzentrierte sich zum Beispiel auf den semantischen Kontext. Zu dieser Art gehörte beispielsweise die Auflösung von „russischer Autor“ zu „Leo Tolstoi“. Das LLM hat fälschlicherweise „russischer Autor“ als Alias für „Leo Tolstoi“ verwendet, was die Notwendigkeit einer Hybridsuche zum Finden der Übereinstimmung negierte.</p><p>Nach mehreren Refaktorierungen, um Probleme wie dieses zu beheben, hatten wir fünf Datensatzstufen, mit denen wir arbeiten konnten. Die Stufen 1–4 waren zunehmend größer und boten mehr Herausforderungstypen. Stufe 5 war der Datensatz der „ultimativen Herausforderung“, der aus den kniffligsten Beispielen aller Herausforderungstypen bestand. Sämtliche Testdaten sind im <a href="https://github.com/jesslm/entity-resolution-lab-public/tree/main/comprehensive_evaluation">umfassenden Auswertungsverzeichnis</a> verfügbar.</p><p>Zur Evaluierung unseres auf Eingabeaufforderungen basierenden Ansatzes zur Entitätsauflösung konzentrierten wir uns auf den Stufe-4-Datensatz. Ein wichtiger Hinweis ist, dass die Bewertung als kontrolliertes Experiment durchgeführt wurde, so dass wir uns auf die Qualität der Entitätsübereinstimmung konzentrieren konnten. Die Daten der Watchlist wurden vorab mit Kontext angereichert, und Entitäten wurden im Voraus aus dem Artikel extrahiert. Dadurch wurde sichergestellt, dass sich die Bewertung auf den Abgleich und nicht auf die Genauigkeit der Extraktion konzentrierte. Dies isoliert die Qualität der Übereinstimmungen; die Gesamtleistung hängt zusätzlich von der Trefferquote bei der Extraktion und der Qualität der Anreicherung ab.</p><h3>Evaluationsdatensatz</h3><p>Der Evaluierungsdatensatz der Stufe 4 bietet einen umfassenden Test der Leistungsfähigkeit des Systems:[1]</p><ul><li><p><strong>Watchlist-Entitäten:</strong> 66 Entitäten unterschiedlichster Art (Personen, Organisationen, Standorte).</p></li><li><p><strong>Testartikel:</strong> 69 Artikel über reale Szenarien zur Auflösung von Entitäten.</p></li><li><p><strong>Erwartete Übereinstimmungen:</strong> 206 erwartete Entitätsübereinstimmungen in allen Artikeln.</p></li><li><p><strong>Herausforderungstypen: </strong>15 verschiedene Herausforderungstypen, die verschiedene Aspekte der Entitätsauflösung prüfen.</p></li></ul><p>Die in den Datensätzen enthaltenen Herausforderungstypen sind:</p><ul><li><p><strong>Spitznamen:</strong> „Bob Smith“ → „Robert Smith“ (sieben Artikel).</p></li><li><p><strong>Titel und Ehrenbezeichnungen:</strong> „Dr. Sarah Williams“ → „Sarah Williams“ (fünf Artikel).</p></li><li><p><strong>Semantischer Kontext:</strong> „Russischer Autor“ → „Leo Tolstoi“ (acht Artikel).</p></li><li><p><strong>Mehrsprachige Namen:</strong> Umgang mit Namen in verschiedenen Skripten (sechs Artikel).</p></li><li><p><strong>Geschäftseinheiten:</strong> Variationen von Firmennamen (sieben Artikel).</p></li><li><p><strong>Referenzen von Führungskräften: </strong>„Microsoft CEO“ → „Satya Nadella“ (fünf Artikel).</p></li><li><p><strong>Politische Führungspersönlichkeiten:</strong> Titelbasierte Referenzen (fünf Artikel).</p></li><li><p><strong>Initialen:</strong> „J. Smith“ → „John Smith“ (drei Artikel).</p></li><li><p><strong>Varianten der Namensreihenfolge:</strong> Verschiedene Konventionen für die Namensreihenfolge (drei Artikel).</p></li><li><p><strong>Abgekürzte Namen:</strong> Teilweise Namensübereinstimmungen (drei Artikel).</p></li><li><p><strong>Namensaufteilung:</strong> Namen, die über Text verteilt sind (drei Artikel).</p></li><li><p><strong>Fehlende Leerzeichen/Bindestriche:</strong> Formatierungsabweichungen (zwei Artikel).</p></li><li><p><strong>Transliteration:</strong> Skriptübergreifender Namensabgleich (zwei Artikel).</p></li><li><p><strong>Kombinierte Herausforderungen:</strong> Mehrere Herausforderungen in einem Artikel (sechs Artikel).</p></li><li><p><strong>Komplexe Geschäftsbeziehungen:</strong> Hierarchische Geschäftsbeziehungen (fünf Artikel).</p></li></ul><p>Mal sehen, wie die auf Eingabeaufforderungen basierende Entitätsauflösung funktioniert hat.</p><h3>Gesamtleistung</h3><p>Die Ergebnisse zeigen, dass die LLM-gestützte Übereinstimmungsbewertung vielversprechend ist, aber sie offenbaren auch ein erhebliches Zuverlässigkeitsproblem. Da jedes Kandidatenpaar vom LLM bewertet werden muss, können Fehler im strukturierten Ausgang die Akzeptanz und das Erinnern unterdrücken, selbst wenn der Abruf gut funktioniert.</p><p>Metrik</p><p>Wert</p><p>Präzision</p><p>83,8 %</p><p>Abruf</p><p>62,6 %</p><p>F1-Score</p><p>71,7 %</p><p>Gesamtanzahl der Übereinstimmungen</p><p>344</p><p>LLM-Annahmequote</p><p>44,8 %</p><p>Fehlerquote</p><p>30,2 %</p><h3>Das Problem mit der Fehlerrate</h3><p>Zur Erinnerung: Der erste Schritt im Prototyp besteht darin, mithilfe von Elasticsearch potenzielle Übereinstimmungspaare zu erstellen. Jede dieser potenziellen Übereinstimmungen muss vom LLM bewertet werden. Um all diese Übereinstimmungen effizient zu verarbeiten, fassen wir die LLM-Aufrufe in Batches zusammen. Dies reduziert die API-Kosten und die Latenzzeit, aber es besteht auch ein erhöhtes Risiko, dass der Ausgang fehlerhaftes JSON enthält. Mit zunehmender Batchgröße wird das JSON länger und komplexer, wodurch die Wahrscheinlichkeit steigt, dass der LLM ungültiges JSON generiert. Hier liegt der Ursprung der Fehlerquote von 30 %. In der Bewertung haben wir eine Batch-Größe von fünf Übereinstimmungen pro Anfrage verwendet. Selbst bei dieser konservativen Batchgröße beobachten wir immer noch JSON-Parsing-Fehler, welche die Auswertungsergebnisse erheblich verfälschen.</p><h2>Nächstes Ziel: Optimierung der LLM-Integration</h2><p>Nachdem wir nun Entitäten mithilfe semantischer Suche und LLM-Bewertung abgeglichen haben, verfügen wir über eine vollständige Entitätsauflösungspipeline. Dieser Ansatz führt jedoch einen neuen Ausfallmodus ein, wenn die Einschätzung des Modells richtig ist, sein Ausgang jedoch nicht nutzbar ist. Wir können die LLM-Integration im Hinblick auf höhere Zuverlässigkeit und Kosteneffizienz optimieren. Im nächsten Beitrag werden wir untersuchen, wie Sie Funktionsaufrufe für einen strukturierten Ausgang verwenden können, der garantierte Struktur- und Typsicherheit bietet und gleichzeitig Fehler und Kosten reduziert.</p><h2>Probieren Sie es selbst aus</h2><p>Möchten Sie den Entitätsabgleich in Aktion sehen? Schauen Sie sich das <a href="https://github.com/jesslm/entity-resolution-lab-public/tree/main/notebooks#:~:text=5%20minutes%20ago-,03_entity_matching_v3.ipynb,-Initial%20public%20lab">Entitätsabgleich-Notizbuch</a> für eine vollständige Anleitung mit realen Implementierungen, detaillierten Erklärungen und praktischen Beispielen an. Das Notizbuch zeigt Ihnen genau, wie Sie Entitäten mithilfe der dreistufigen Suche, der hybriden Suche mit RRF und der LLM-gestützten Bewertung mit Schlussfolgerungen abgleichen.</p><p><strong>Denken Sie daran:</strong> Dies ist ein pädagogischer Prototyp, der entwickelt wurde, um die Konzepte zu vermitteln. Bei der Entwicklung von Produktionssystemen sollten zusätzliche Faktoren wie Modellauswahl, Kostenoptimierung, Latenzanforderungen, Qualitätsvalidierung, Fehlerbehandlung und Überwachung berücksichtigt werden, die in diesem lernorientierten Prototyp nicht behandelt werden.</p><h2>Anmerkungen</h2><ol><li><p>Diese Datensätze sind synthetisch und für Bildungszwecke konzipiert; sie nähern sich realen Herausforderungen an, sind aber nicht repräsentativ für eine einzelne Produktionsdomäne.</p></li></ol>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-entity-resolution-llm-semantic-search</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-entity-resolution-llm-semantic-search</guid>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[Hybride Suche]]></category>
    <dc:creator><![CDATA[Jessica Moszkowicz]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltefc59243d9990405/6a17056ab339d5778f769ebf/473ca4357c7d60f690edbd2a844acda169aca9c3-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 26 Feb 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Automatisierung des Log-Parsing in Streams mit ML]]></title>
    <description><![CDATA[Erfahren Sie, wie ein hybrider ML-Ansatz durch Automatisierungsexperimente mit Log-Format-Fingerprinting in Streams eine Genauigkeit von 94 % beim Log-Parsing und 91 % bei der Log-Partitionierung erreicht hat.]]></description>
    <content:encoded><![CDATA[<p>In modernen Beobachtbarkeits-Stacks bleibt es eine Herausforderung, unstrukturierte Logs von verschiedenen Datenanbietern in Plattformen wie Elasticsearch zu Ingestieren. Die Abhängigkeit von manuell erstellten Parsing-Regeln führt zu fehleranfälligen Daten-Pipelines, bei denen selbst geringfügige Aktualisierungen des vorgelagerten Codes zu Parsing-Fehlern und nicht indizierten Daten führen. Diese Fragilität wird durch die Herausforderung der Skalierbarkeit noch verstärkt: In dynamischen Microservices-Umgebungen macht die kontinuierliche Hinzufügung neuer Services die manuelle Regelwartung zu einem operativen Albtraum.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte8f5bd0e4986b04c/6a170e6acdacbf612e7d2a9e/9108ec303339dd091faa3c363c7cf5c228155f49-3840x2160.png" alt="" /><p>Unser Ziel war es, zu einem automatisierten, adaptiven Ansatz überzugehen, der sowohl Log-Parsing (Feldextraktion) als auch Log-Partitionierung (Quellenidentifikation) bewältigen kann. Wir vermuteten, dass Large Language Models (LLMs) mit ihrem inhärenten Verständnis von Codesyntax und semantischen Mustern diese Aufgaben mit minimalem menschlichem Eingreifen automatisieren könnten.</p><p>Wir freuen uns, Ihnen mitteilen zu können, dass dieses Feature bereits in <a href="http://elastic.co/elasticsearch/streams"><u>Streams</u></a> verfügbar ist!</p><h2>Beschreibung des Datensatzes</h2><p>Wir haben für PoC-Zwecke eine <a href="https://github.com/logpai/loghub"><strong>Loghub-Sammlung</strong></a>von Logs gewählt. Für unsere Untersuchung wählten wir repräsentative Stichproben aus den folgenden Schlüsselbereichen aus:</p><ul><li><p>Verteilte Systeme: Wir verwendeten die HDFS- (Hadoop Distributed File System) und Spark-Datensätze. Diese enthalten eine Mischung aus Info-, Fehlerbehebungs- und Fehlermeldungen, die für Big Data-Plattformen typisch sind.</p></li><li><p>Server- und Webanwendungen: Logs von Apache-Webservern und OpenSSH boten eine wertvolle Quelle für Zugriffs-, Fehler- und sicherheitsrelevante Ereignisse. Diese sind entscheidend für die Überwachung des Webverkehrs und die Erkennung potenzieller Bedrohungen.</p></li><li><p>Betriebssysteme: Wir haben Protokolle von Linux und Windows aufgenommen. Diese Datensätze repräsentieren die üblichen, semistrukturierten Ereignisse auf Systemebene, denen Betriebsteams täglich begegnen.</p></li><li><p>Mobile Systeme: Um sicherzustellen, dass unser Modell auch Logs aus mobilen Umgebungen verarbeiten kann, haben wir den Android-Datensatz mit einbezogen. Diese Logs sind oft ausführlich und erfassen eine Vielzahl von Aktivitäten auf Anwendungs- und Systemebene auf Mobilgeräten.</p></li><li><p>Supercomputer: Um die Leistung in Hochleistungs-Computing-Umgebungen (HPC) zu testen, haben wir den BGL-Datensatz (Blue Gene/L) integriert, der hochstrukturierte Logs mit spezifischer Domänenterminologie enthält.</p></li></ul><p>Ein entscheidender Vorteil der Loghub-Sammlung ist, dass die Logs größtenteils unsaniert und unbeschriftet sind, was eine geräuschvolle Live-Produktionsumgebung mit Microservice-Architektur widerspiegelt.</p><p>Log-Beispiele:</p>[Sun Dec 04 20:34:21 2005] [notice] jk2_init() Found child 2008 in scoreboard slot 6
[Sun Dec 04 20:34:25 2005] [notice] workerEnv.init() ok /etc/httpd/conf/workers2.properties
[Mon Dec 05 11:06:51 2005] [notice] workerEnv.init() ok /etc/httpd/conf/workers2.properties
17/06/09 20:10:58 INFO output.FileOutputCommitter: Saved output of task 'attempt_201706092018_0024_m_000083_1138' to hdfs://10.10.34.11:9000/pjhe/test/1/_temporary/0/task_201706092018_0024_m_000083
17/06/09 20:10:58 INFO mapred.SparkHadoopMapRedUtil: attempt_201706092018_0024_m_000083_1138: Committed<p>Zusätzlich haben wir einen Kubernetes-Cluster mit einer typischen Webanwendung und Datenbank erstellt, die zusätzliche Logs in der gängigsten Domäne sammelt.</p><p>Beispiel für gängige Logfelder: Zeitstempel, Log-Ebene (INFO, WARN, FEHLER), Quelle, Nachricht.</p><h2>Few-Shot-Log-Parsing mit einem LLM</h2><p>Unsere erste Reihe von Experimenten konzentrierte sich auf eine grundlegende Frage: <strong>Kann ein LLM zuverlässig Schlüsselfelder identifizieren und konsistente Parsing-Regeln erzeugen, um sie zu extrahieren?</strong></p><p>Wir haben ein Modell gebeten, rohe Log-Stichproben zu analysieren und Log-Parsing-Regeln im regulären Ausdruck (Regex) und im <a href="https://www.elastic.co/docs/explore-analyze/scripting/grok">Grok-Format</a> zu generieren. Unsere Ergebnisse zeigten, dass dieser Ansatz großes Potenzial hat, aber auch erhebliche Herausforderungen bei der Implementierung.</p><h3>Hohe Zuverlässigkeit und Kontextbewusstsein</h3><p>Die ersten Ergebnisse waren vielversprechend. Das LLM zeigte eine starke Fähigkeit, Parsing-Regeln zu generieren, die mit hoher Wahrscheinlichkeit zu den bereitgestellten Beispielen passten. Neben der einfachen Mustererkennung zeigte das Modell die Fähigkeit zum Log-Verständnis – es konnte die Log-Quelle (z. B. Gesundheits-Tracking-App, Nginx-Web-App, Mongo-Datenbank) korrekt identifizieren und benennen.</p><h3>Das „Goldlöckchen“-Dilemma der Eingabestichproben</h3><p>Unsere Experimente zeigten schnell einen erheblichen Mangel an Robustheit aufgrund der extremen<strong> Empfindlichkeit gegenüber der Eingabestichprobe.</strong> Die Leistung des Modells schwankt stark in Abhängigkeit von den spezifischen Log-Beispielen, die im Prompt enthalten sind. Wir haben ein Log-Ähnlichkeitsproblem beobachtet, bei dem die Log-Stichprobe <em>gerade ausreichend unterschiedliche </em>Logs enthalten muss:</p><ul><li><p>Zu homogen (Overfitting)<strong>:</strong> Wenn die Eingabe-Logs zu ähnlich sind, neigt das LLM dazu, zu <strong>überspezifizieren</strong>. Es behandelt variable Daten – wie spezifische Java-Klassennamen in einem Stack-Trace – als statische Teile der Vorlage. Das Ergebnis sind spröde Regeln, die nur einen winzigen Teil der Logs abdecken und unbrauchbare Felder extrahieren.</p></li><li><p>Zu heterogen (Verwirrung): Umgekehrt, wenn die Stichprobe erhebliche Formatierungsunterschiede enthält – oder schlimmer noch, „Müll-Logs“ wie Fortschrittsbalken, Speichertabellen oder ASCII-Art – kämpft das Modell damit, einen gemeinsamen Nenner zu finden. Oftmals greift man dabei auf die Generierung komplexer, fehlerhafter regulärer Ausdrücke zurück oder verallgemeinert die gesamte Zeile vorschnell zu einem einzigen Nachrichten-Feld.</p></li></ul><h3>Die Einschränkung des Kontextfensters</h3><p>Wir sind außerdem auf einen Engpass im Kontextfenster gestoßen. Wenn die Eingabe-Logs lang, heterogen oder reich an extrahierbaren Feldern waren, verschlechterte sich oft die Ausgabe des Modells und wurde „unübersichtlich“ oder zu lang, um in das Ausgabekontextfenster zu passen. Natürlich hilft Chunking in diesem Fall. Durch das Aufteilen von Protokollen mithilfe zeichenbasierter und entitätsbasierter Trennzeichen könnten wir dem Modell helfen, sich auf das Extrahieren der Hauptfelder zu konzentrieren, ohne von Rauschen überwältigt zu werden.</p><h3>Die Konsistenz- und Standardisierungslücke</h3><p>Selbst wenn das Modell erfolgreich Regeln generierte, stellten wir leichte Inkonsistenzen fest:</p><ul><li><p>Namensvariationen für Dienste: Das Modell schlägt unterschiedliche Namen für dieselbe Entität vor (z. B. wird die Quelle in verschiedenen Ausführungen als „Spark“, „Apache Spark“ und „Spark log Analytics“ bezeichnet).</p></li><li><p>Variationen bei der Feldbenennung: Es fehlte an Standardisierung bei den Feldnamen (z. B. <code>id</code> vs. <code>service.id</code> vs. <code>device.id</code>). Wir haben Namen mithilfe einer standardisierten <a href="https://www.elastic.co/docs/reference/ecs/ecs-field-reference">Elastic-Feldbenennung</a> normalisiert.</p></li><li><p>Auflösungsvarianz: Die Auflösung der Feldextraktion variierte je nachdem, wie ähnlich die Eingabe-Logs einander waren.</p></li></ul><h2>Log-Format-Fingerprint</h2><p>Um die Herausforderung der Log-Ähnlichkeit anzugehen, führen wir eine leistungsstarke Heuristik ein: <strong>Log-Format-Fingerprint (LFF)</strong>.</p><p>Anstatt rohe, verrauschte Logs direkt in ein LLM einzuspeisen, wenden wir zunächst eine deterministische Transformation an, um die zugrundeliegende Struktur jeder Nachricht zu enthüllen. Dieser Vorverarbeitungsschritt abstrahiert variable Daten und generiert einen vereinfachten „Fingerabdruck“, der es uns ermöglicht, verwandte Logs zu gruppieren.</p><p>Die Mapping-Logik ist einfach, um Geschwindigkeit und Konsistenz zu gewährleisten:</p><ol><li><p>Ziffernabstraktion: Jede Ziffernfolge (0–9) wird durch eine einzelne „0“ ersetzt.</p></li><li><p>Textabstraktion: Jede Folge von alphabetischen Zeichen mit Leerzeichen wird durch ein einzelnes „a“ ersetzt.</p></li><li><p>Normalisierung von Leerzeichen: Alle Sequenzen von Leerzeichen (Leerzeichen, Tabulatoren, Zeilenumbrüche) werden zu einem einzigen Leerzeichen zusammengefasst.</p></li><li><p>Symbolerhaltung: Zeichensetzung und Sonderzeichen (z. B. :, [, ], /) werden beibehalten, da sie oft die stärksten Indikatoren für die Log-Struktur sind.</p></li></ol><p>Wir stellen den Log-Mapping-Ansatz vor. Die grundlegenden Mapping-Muster umfassen Folgendes:</p><ul><li><p>Ziffern 0–9 von beliebiger Länge -&gt; auf „0“.</p></li><li><p>Text (alphabetische Zeichen mit Leerzeichen) von beliebiger Länge -&gt; auf „a“.</p></li><li><p>Leerzeichen, Tabulatoren und neue Zeilen -&gt; auf ein einzelnes Leerzeichen.</p></li></ul><p>Schauen wir uns ein Beispiel an, wie uns dieses Mapping die Transformation der Logs ermöglicht.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf91eebab0ad79ccd/6a170e6c67045ba94f45c29c/78fa2887486eb9417804354ee3bf2a4fdb0f6383-846x252.png" alt="" /><p>Dadurch erhalten wir folgende Log-Masken:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt438d74dcb921578b/6a170e6d1949f74aa0e7aae3/ec439a3d3a25002498b97defcff733ea5ebc6b55-826x94.png" alt="" /><p>Beachten Sie die Fingerabdrücke der ersten beiden Logs. Trotz unterschiedlicher Zeitstempel, Quellklassen und Nachrichteninhalte sind ihre Präfixe (<code>0/0/0 0:0:0 a a.a:</code>) identisch. Durch diese strukturelle Ausrichtung können wir diese Logs automatisch in denselben Cluster einordnen.</p><p>Das dritte Log erzeugt jedoch einen völlig abweichenden Fingerabdruck (<code>0-0-0...</code>). Dies ermöglicht es uns, es algorithmisch von der ersten Gruppe zu trennen, <em>bevor</em> wir überhaupt ein LLM aufrufen.</p><h2>Bonus: Sofortige Implementierung mit ES|QL</h2><p>Es ist so einfach wie das Übergeben dieser Abfrage in Discover.</p><p><strong>Abfrage-Aufschlüsselung:</strong></p><p><strong>FROM</strong> LogHub: Zielt auf unseren Index mit den Rohprotokolldaten ab.</p><p><strong>EVAL</strong> Muster = …: Die Kern-Mapping-Logik. Wir verketten REPLACE-Funktionen, um die Abstraktion durchzuführen (z. B. Ziffern zu '0', Text zu 'a' usw.) und speichern das Ergebnis in einem „Muster“-Feld.</p><p><strong>STATS </strong>[column1 =] expression1, …<strong> BY </strong>SUBSTRING(pattern, 0, 15):</p><p>Dies ist ein Clustering-Schritt. Wir gruppieren Protokolle, die die ersten 15 Zeichen ihres Musters gemeinsam haben, und erstellen aggregierte Felder wie die Gesamtzahl der Protokolle pro Gruppe, eine Liste der Protokoll-Datenquellen, das Musterpräfix und 3 Protokollbeispiele.</p><p><strong>SORT</strong> total_count DESC | <strong>LIMIT</strong> 100 : Zeigt die 100 häufigsten Log-Muster an</p><p>Die Abfrageergebnisse auf LogHub werden unten angezeigt:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfa3960cf94ccf331/6a170e6fdc55decfa3e00e7c/b119498f124376c41d242a099bf9081fd6536be8-1600x394.png" alt="Log-Parsing-Abfrageergebnisse auf LogHub." /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2dbcde2a22e06367/6a170e71961e693a18c4cfb6/4dcfc0a5b7fa753497cc5def5ea3cd54449c0481-1600x719.png" alt="" /><p>Wie in der Visualisierung gezeigt, partitioniert dieser „LLM-freie“ Ansatz Protokolle mit hoher Genauigkeit. Es gelang ihm, 10 von 16 Datenquellen (basierend auf LogHub-Labels) vollständig zu clustern (&gt;90 %), und er erreichte ein Mehrheits-Clustering in 13 von 16 Quellen (&gt;60 %) – alles ohne zusätzliche Reinigung, Vorverarbeitung oder Feinabstimmung.</p><p>Log-Format-Fingerprinting bietet eine pragmatische, wirkungsvolle Alternative und Ergänzung zu ausgefeilten ML-Lösungen wie der <a href="https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-categorize-text-aggregation">Log-Pattern-Analyse.</a> Es bietet sofortige Einblicke in die Zusammenhänge der Logs und verwaltet große Log-Cluster effektiv.</p><ul><li><p>Vielseitigkeit als Grundform </p></li></ul><p>Dank <a href="https://www.elastic.co/blog/getting-started-elasticsearch-query-language">ES|QL-Implementierung</a> dient LFF sowohl als eigenständiges Werkzeug für schnelle Datendiagnostik/-visualisierungen als auch als Baustein in Loganalyse-Pipelines für Anwendungsfälle mit hohem Volumen. </p><ul><li><p>Flexibilität</p></li></ul><p>LFF lässt sich leicht anpassen und erweitern, um spezifische Muster zu erfassen, z. B. hexadezimale Zahlen und IP-Adressen.</p><ul><li><p>Deterministische Stabilität</p></li></ul><p>Im Gegensatz zu ML-basierten Clustering-Algorithmen ist die LFF-Logik geradlinig und deterministisch. Neue eingehende Logs wirken sich nicht rückwirkend auf bestehende Log-Cluster aus.</p><ul><li><p>Leistung und mMemory</p></li></ul><p>Es benötigt nur minimalen Speicher, kein Training und keine GPU und ist daher ideal für Echtzeit-Umgebungen mit hohem Durchsatz geeignet.</p><h2>Kombination des Log-Format-Fingerprints mit einem LLM</h2><p>Zur Validierung der vorgeschlagenen hybriden Architektur enthielt jedes Experiment eine zufällige 20%ige Teilmenge der Logs aus jeder Datenquelle. Diese Einschränkung simuliert eine reale Produktionsumgebung, in der Logs in Batches und nicht als monolithischer historischer Dump verarbeitet werden.</p><p>Das Ziel war zu demonstrieren, dass LFF als effektive Kompressionsschicht fungiert. Wir wollten beweisen, dass Parsing-Regeln mit hoher Abdeckung aus kleinen, kuratierten Stichproben generiert und erfolgreich auf den gesamten Datensatz verallgemeinert werden können.</p><h2>Ausführungspipeline</h2><p>Wir haben eine mehrstufige Pipeline implementiert, die die Daten filtert, gruppiert und stratifizierte Stichproben auf sie anwendet, bevor sie das LLM erreichen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt26635762891b3a41/6a170e73509168eea4e1bb91/b3f46ea471760b406a32fc7d4bc74cc03faaced2-3840x1660.png" alt="" /><p>1. Zweistufiges hierarchisches Clustering</p><ul><li><p>Unterklassen (exakte Übereinstimmung): Logs werden anhand identischer Fingerabdrücke aggregiert. Alle Logs einer Unterklasse haben exakt die gleiche Formatstruktur.</p></li><li><p>Ausreißerbereinigung. Wir verwerfen alle Unterklassen, die weniger als 5 % des gesamten Logvolumens ausmachen. Dadurch wird sichergestellt, dass sich das LLM auf das dominante Signal konzentriert und nicht durch Rauschen oder fehlerhafte Logs abgelenkt wird.</p></li><li><p>Metaklassen (Präfixübereinstimmung): Verbleibende Unterklassen werden in Metaklassen nach den ersten N Zeichen der Format-Fingerabdruckübereinstimmung gruppiert. Wir haben N=5 für das Log-Parsing und N=15 für die Log-Partitionierung gewählt, wenn die Datenquellen unbekannt sind.</p></li></ul><p>2. Stratifiziertes Sampling. Sobald der hierarchische Baum erstellt ist, erstellen wir die Log-Stichprobe für das LLM. Das strategische Ziel ist es, die Varianzabdeckung zu maximieren und gleichzeitig die Verwendung von Token zu minimieren.</p><ul><li><p>Wir wählen repräsentative Logs aus <em>jeder</em> gültigen Unterklasse innerhalb der breiteren Metaklasse aus.</p></li><li><p>Um einen Randfall mit zu vielen Unterklassen zu managen, wenden wir zufälliges Downsampling an, um die Zielfenstergröße anzupassen.</p></li></ul><p>3. Regelgenerierung. Abschließend fordern wir das LLM auf, eine Regex-Parsing-Regel zu generieren, die auf alle Logs in der bereitgestellten Stichprobe für jede Metaklasse zutrifft. Für unseren PoC haben wir das Modell GPT-4o Mini verwendet.</p><h2>Experimentelle Ergebnisse und Beobachtungen</h2><p>Wir haben auf dem Loghub-Datensätze eine Parsing-Genauigkeit von 94 % und eine Partitionierungs-Genauigkeit von 91 % erreicht.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1b896b41b3b70e7e/6a170e757d8d67601a70e7d9/49b2b6a1401dd1f33951da68e5a3fac37d0b5aaa-1600x1506.png" alt="94 % Genauigkeit beim Parsen und 91 % Genauigkeit bei der Partitionierung des Loghub-Datensatzes." /><p>Die obige Konfusionsmatrix veranschaulicht die Ergebnisse der Log-Partitionierung. Die vertikale Achse stellt die tatsächlichen Datenquellen dar, die horizontale Achse die vorhergesagten Datenquellen. Die Intensität der Heatmap entspricht dem Log-Volumen, wobei leichtere Kacheln auf eine höhere Anzahl hinweisen. Die diagonale Ausrichtung zeigt die hohe Genauigkeit des Modells bei der Quellenzuweisung mit minimaler Streuung.</p><h2>Einblicke aus unseren Leistungsvergleichsanalysen:</h2><ul><li><p><strong>Optimale Ausgangsbasis:</strong> Ein Kontextfenster von <strong>30 bis 40 Log-Stichproben</strong> pro Kategorie erwies sich als der „Sweet Spot“, der sowohl mit Regex- als auch mit Grok-Mustern durchweg ein robustes Parsing ermöglichte.</p></li><li><p><strong>Eingabeminimierung:</strong> Wir haben die Eingabegröße für Regex-Muster auf 10 Logs pro Kategorie erhöht und nur einen 2%igen Rückgang der Parsing-Leistung festgestellt, was bestätigt, dass diversitätsbasierte Stichproben kritischer sind als das rohe Volumen.</p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/log-parsing-partitioning-automation-experiments-streams</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/log-parsing-partitioning-automation-experiments-streams</guid>
    <category><![CDATA[ML-Forschung]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Nastia Havriushenko]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc1df5a7cae463d59/6a170e76a6c2b907d7e797ab/965c58f19742361160593c38fcaa8b2f4b0d6cc5-3838x2159.png" length="0" type="image/png"/>
    <pubDate>Fri, 02 Jan 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Erste Schritte mit Elastic Agent Builder und Strands Agents SDK]]></title>
    <description><![CDATA[Lernen Sie, wie Sie mit Elastic Agent Builder einen Agenten erstellen, und erkunden Sie anschließend, wie Sie den Agenten über das A2A-Protokoll nutzen, das mit dem Strands Agents SDK orchestriert wird.]]></description>
    <content:encoded><![CDATA[<p>Haben Sie eine Idee für einen KI-Agenten? Wahrscheinlich geht es darum, etwas mit Daten anzufangen, denn wenn ein Agent eine nützliche Aktion auslösen will, muss er eine Entscheidung treffen, und für diese Entscheidung braucht er die richtigen Daten.</p><p>Mit dem Elastic Agent Builder können Sie ganz einfach datenverbundene KI-Agenten erstellen. Wie das geht, zeigen wir Ihnen in diesem Blogbeitrag. Lassen Sie uns alle erforderlichen Schritte durchgehen, um einen Agenten mit einem MCP-Tool zu erstellen, der auf in Elastic gespeicherte Daten zugreift. Dann verwenden wir das Strands Agents SDK und seine A2A-Funktionen (Agent2Agent), um den Agenten zu betreiben. Das <a href="https://strandsagents.com/">Strands Agents SDK</a> ist eine Multiagenten-KI-Entwicklungsplattform, mit der Sie agentenbasierte Anwendungen mit genau dem Code erstellen können, der erforderlich ist, um das gewünschte Ergebnis zu erzielen.</p><p>Lassen Sie uns einen KI-Agenten entwickeln, der das Spiel RPS+ spielt, eine Variante des klassischen Spiels „Schere, Stein, Papier“ mit einer zusätzlichen Wendung: Es bietet den Spieler:innen einige zusätzliche Auswahlmöglichkeiten.</p><h2>Voraussetzungen</h2><p>Folgendes ist erforderlich, um die Schritte in diesem Blogbeitrag zu befolgen:</p><ul><li><p>Ein Texteditor, der auf Ihrem lokalen Computer ausgeführt wird</p><ul><li><p>Für die Beispielanleitungen in diesem Blogbeitrag verwenden wir <a href="https://code.visualstudio.com/download">Visual Studio Code</a>.</p></li></ul></li><li><p><a href="https://www.python.org/downloads/">Python 3.10 oder höher</a>, das auf Ihrem lokalen Computer ausgeführt wird</p></li></ul><h2>Ein Serverless-Projekt erstellen</h2><p>Als Erstes benötigen wir ein Elasticsearch Serverless-Projekt, das den Elastic Agent Builder beinhaltet.</p><p>Gehen Sie zu <a href="http://cloud.elastic.co/">Cloud.elastic.co/de/</a> und erstellen Sie ein neues Elasticsearch Serverless-Projekt.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3472edce39ec0b81/6a17060e66c4f93c17f8bf57/31b6a5c1c30dacbb4d5e58d1c566071e7143a0c8-1600x879.gif" alt="" /><h2>Einen Index erstellen und Daten hinzufügen</h2><p>Als Nächstes fügen wir einige Daten zu unserem Elasticsearch-Projekt hinzu. Öffnen Sie die Entwicklertools, wo wir Befehle ausführen können, um einen neuen Index zu erstellen und einige Daten darin einzufügen. Wählen Sie im Hauptmenü „Entwicklungstools“ aus.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltaedaa94068c07a17/6a17060f961e697558c4ce5f/f97d5af077504463155655a9e27c171a7f974f71-1600x879.jpg" alt="" /><p>Kopieren Sie den folgenden PUT-Befehl und fügen Sie ihn in den Anfrage-Eingangsbereich der Konsole des Entwicklungstools ein. Diese Anweisung erstellt einen Elasticsearch-Index mit dem Namen „game-docs“.</p>PUT /game-docs
{
  "mappings": {
    "properties": {
      "title": { "type": "text" },
      "content": { 
        "type": "text"
      },
      "filename": { "type": "keyword" },
      "last_modified": { "type": "date" }
    }
  }
}<p>Klicken Sie auf die Schaltfläche <strong>„Anfrage senden“</strong>, die in den Entwicklungstools rechts neben der Anweisung angezeigt wird. Sie sollten eine Benachrichtigung sehen, die bestätigt, dass der <em>Game-docs-Index</em> im Reaktion Flächendiagramm der Entwicklungstools erstellt wurde.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt430c357b479d93af/6a170611a6c2b98191e79624/be0555a1930e4d4f58b7ed8b669c9b702532ed17-1600x880.jpg" alt="" /><p>Ein Index namens <em>game-docs</em> ist ein großartiger Ort, um die Daten für das Spiel zu speichern, das wir gerade entwickeln. Fügen wir ein Dokument namens <em>rps+-md</em> in diesen Index ein, das alle Daten enthält, die unser Spiel benötigt. Kopieren Sie den folgenden PUT-Befehl und fügen Sie ihn in das Entwicklungstool ein.</p>PUT /game-docs/_doc/rps+-md
{
  "title": "Rock Paper Scissors +",
  "content": "
# Game Name
RPS+

# Starting Prompt
Let's play RPS+ !
---
What do you choose?

# Game Objects
1. Rock 🪨 👊
2. Paper 📜 🖐
3. Scissors ✄ ✌️
4. Light ☼ 👍
5. Dark Energy ☄ 🫱

# Judgement of Victory
* Rock beats Scissors
  * because rocks break scissors
* Paper beats Rock
  * because paper covers rock
* Scissors beat Paper
  * because scissors cut paper
* Rock beats Light
  * because you can build a rock structure to block out light
* Paper beats Light
  * because knowledge stored in files and paper books helps us understand light
* Light beats Dark Energy
  * because light enables humans to lighten up and laugh in the face of dark energy as it causes the eventual heat death of the universe
* Light beats Scissors
  * because light is needed to use scissors safely
* Dark Energy beats Rock
  * because dark energy rocks more than rocks. It rocks rocks and everything else in its expansion of the universe
* Dark Energy beats Paper
  * because humans, with their knowledge stored in files and paper books, can't explain dark energy 
* Scissors beat Dark Energy
  * because a human running with scissors is darker than dark energy

# Invalid Input
I was hoping for an worthy opponent
  - but alas it appears that time has past
  - but alas there's little time for your todo list when [todo:fix this] is so vast

# Cancel Game
The future belongs to the bold. Goodbye..
",
  "filename": "RPS+.md",
  "last_modified": "2025-11-25T12:00:00Z"
}<p>Klicken Sie auf die Schaltfläche <strong>„Anfrage senden“</strong> neben der Anweisung, um sie auszuführen und das <em>rps+-md-Dokument</em> zum game-docs-Index hinzuzufügen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt64d49e13754d5b25/6a17061214b270524be3c55d/3c01d8a4602de5c33337457591a388a4a4e3fad3-1600x879.jpg" alt="" /><p>Wir sollten jetzt einige Daten abfragen können, und mit Agent Builder ist das einfacher als je zuvor.</p><p>Wählen Sie <strong>Agenten</strong> aus dem Hauptnavigationsmenü aus.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb4d374bf2ba9135c/6a1706147d8d67468570e63e/82dbd2e9a439cabd5a5eea3d0ce005b87df0c3ea-1600x879.jpg" alt="" /><p>Dann müssen Sie nur noch den standardmäßigen Elastic AI Agent fragen: „Welche Daten habe ich?“</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc0f879cf28772718/6a1706161949f7f25ee7a92d/f7a2f39c9d1486bdf02d9e88a732b540ac2e2cd1-1600x872.gif" alt="" /><p>Der Elastic AI Agent bewertet die Daten und liefert eine prägnante Erklärung der vorhandenen Daten.</p><h2>Ein Tool erstellen</h2><p>Okay, wir haben jetzt einige Daten in Elastic. Lassen Sie uns diese nutzen. Der Agent Builder bietet integrierte Unterstützung zur Erstellung von <a href="https://modelcontextprotocol.io/">MCP-Tools</a>, die Agenten helfen, auf die Daten zuzugreifen, die sie benötigen, um den richtigen Kontext für ihre Aufgabe zu haben. Lassen Sie uns ein einfaches Tool erstellen, das unsere Spieldaten abruft.</p><p>Klicken Sie auf das Aktionsmenü des Agent Builders.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7802a6b94e81440c/6a170618ab7f085287db9db4/0e327c202674dda33bcc0e494d2b588fa8b32e4f-1600x879.png" alt="" /><p>Wählen Sie in den Menüoptionen <strong>Alle Werkzeuge anzeigen</strong>aus.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9f52ffe114fb6ea7/6a17061a4a531b801b36a884/1ebf58650e9fb56750d3f0b1700fab50b44f9bdf-1600x879.png" alt="" /><p>Klicken Sie auf <strong>+ Neues Tool.</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8090769f6c4d1899/6a17061c286714294093e219/6c03a7f28b99ac2d805f34f39948979893316a00-1600x879.png" alt="" /><p>Wählen Sie im Formular <strong>Tool erstellen</strong> die <a href="https://www.elastic.co/docs/explore-analyze/query-filter/languages/esql"><strong>Option ES|QL</strong></a><strong> aus. Wählen Sie als </strong><strong>Werkzeugtyp</strong> die gewünschte Option aus und geben Sie die folgenden Werte ein.</p><p>Für die <strong>Tool-ID</strong>:</p>example.get_game_docs<p>Für die <strong>Beschreibung</strong>:</p>Get RPS+ doc from Elasticsearch game-docs index.<p>Für <strong>Konfiguration </strong>geben Sie die folgende Abfrage in das <strong>ES|QL-Abfrage</strong>-Textfeld ein:</p>FROM game-docs | WHERE filename == "RPS+.md"<p>Ihr ausgefülltes Formular <strong>Tool erstellen</strong> sollte wie folgt aussehen. Klicken Sie auf <strong>Speichern</strong>, um das Tool zu erstellen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt77034c305198217a/6a17061e66c4f9e54ef8bf5e/b6c93e344600f319b9d2c3030020cf2d171ac1c4-1600x1312.png" alt="" /><p>Wir haben ein neues Werkzeug am Werkzeugständer hängen. Werkzeuge sollten nicht einfach nur an einem Regal hängen; sie sollten sinnvoll eingesetzt werden. Lassen Sie uns einen Agenten erstellen, der unser neues benutzerdefiniertes Tool verwenden kann.</p><h2>Einen Agenten erstellen und ihm ein Tool zuweisen</h2><p>Mit dem Agent Builder ist das Erstellen eines Agenten erfreulich einfach. Sie müssen einfach nur die Agentenanweisungen mit ein paar Details eingeben. Lassen Sie uns jetzt einen Agenten erstellen.</p><p>Klicken Sie auf <strong>Agenten verwalten.</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltaa8a83fc2f3758a9/6a1706201949f71a10e7a931/53934b93db07187e251d4b321cb9ca647e2fd51b-1600x858.png" alt="" /><p>Klicken Sie<strong> + Neuer Agent.</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3778403c5101a000/6a17062160084be12f3c449e/fae3ad8f31e71a6dfd044e1daa025a4e280b4e68-1600x490.png" alt="" /><p>Geben Sie die folgenden Informationen in das Formular <strong>Neuer Agent</strong> ein.</p><p>Geben Sie für die <strong>Agenten-ID</strong> den folgenden Text ein:</p>rps_plus_agent<p>Geben Sie im Textfeld <strong>Benutzerdefinierte Anweisungen </strong>die folgenden Anweisungen ein:</p>When prompted, if the prompt contains an integer, then select the corresponding numbered item in the list of "Game Objects" from your documents. Otherwise select a random game object. This is your chosen game object for a single round of the game.

# General Game Rules
* 2 players
    - the user: the person playing the game
    - you: the agent playing the game and serving as the game master
* Each player chooses a game object which will be compared and cause them to tie, win or lose.

# Start the game
1. This is the way each new game always starts. You make the first line of your response only the name of your chosen game object. 

2. The remainder of your response should be the "Starting Prompt" text from your documents and generate a list of "Game Objects" for the person playing the game to choose a game object from.  

# End of Game: The game ends in one of the following three outcomes:
1. Invalid Input: If the player responds with an invalid game object choice, respond with variations of the "Invalid Input" text from your documents and then end the game.

2. Tie: The game ends in a tie if the user chooses the same game object as your game object choice.

3. Win or Lose: The game winner is decided based on the "Judgement of Victory" conditions from your documents. Compare the user's game object choice and your game object choice and determine who chose the winning game object.

# Game conclusion
Respond with a declaration of the winner of the game by outputting the corresponding text in the "Judgement of Victory" section of your documents.<p>Geben Sie für den <strong>Anzeigenamen </strong>den folgenden Text ein:</p>RPS+ Agent<p>Für die <strong>Anzeigebeschreibung </strong>geben Sie den untenstehenden Text ein:</p>An agent that plays the game RPS+<p>Geben Sie dem Agenten das benutzerdefinierte Tool, das wir zuvor erstellt haben, indem Sie auf den Tab <strong>Tools</strong> klicken.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte5b0fe00abdde07c/6a17062314b2704bc4e3c563/1778f64bc3a1b4004998dc3668ef7f666788e193-1600x1390.png" alt="" /><p>Wählen Sie nur das Tool <em>example.get_game_docs</em> aus, das wir zuvor erstellt haben.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2210212e07e06104/6a170625a929cf3277ae08d1/7d734cd80161bcc058817482eb330ffcf1cb567b-1600x1363.png" alt="" /><p>Klicken Sie auf <strong>Speichern</strong>, um den neuen Agenten zu erstellen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6e3afc1918e26f14/6a170627ab7f084746db9db8/c0014faf605ce50c03679ed0d073bd9f3ae7234d-1600x468.png" alt="" /><p>Lassen Sie uns unseren neuen Agenten ausprobieren. Es gibt einen praktischen Link, um einen Chat mit einem beliebigen Agenten aus der Liste der Agenten zu starten.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blteb4b69dc5971d3a0/6a1706286f7f046840914743/b7d6943ad90a4f68691207caf66b81742e712145-1600x560.png" alt="" /><p>Geben Sie einfach „start game“ ein und das Spiel beginnt. Es funktioniert!</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte5b621d602223dff/6a17062ab339d568a1769ef8/984d008e4cc3f08cc1f101720673b0f7347c066c-1600x874.gif" alt="" /><p>Sie können sehen, dass der Agent seine Spielobjektauswahl oben in seiner Reaktion anzeigt. Dies ist nützlich, da wir die Wahl des Agenten sehen und bestätigen können, dass das Spiel wie erwartet funktioniert. Wenn man jedoch die Wahl des Gegners kennt, bevor man selbst wählt, wird das Spiel „Schere, Stein, Papier“ nicht besonders unterhaltsam. Um das Spiel zu verfeinern und seine endgültige Form zu erreichen, können wir eine Agenten-Orchestrierungsplattform verwenden, die Agenten mit Code steuern kann.</p><p>Hier kommt das Strands Agents SDK ins Spiel.</p><h2>Strands Agents SDK</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt73901ec745a97fbf/6a17062c964cea23c808bab3/c195bba6ff2754f5d8fda174a0c1d247bc283710-456x156.png" alt="" /><p>Wenn Sie neugierig darauf sind, neue Frameworks für die Agentenentwicklung auszuprobieren, dann ist das <a href="https://strandsagents.com/latest/">Strands Agents SDK</a> einen Versuch wert. Das <a href="https://aws.amazon.com/blogs/opensource/introducing-strands-agents-an-open-source-ai-agents-sdk/">Strands Agents SDK wurde von AWS (Mai 2025)</a> als <a href="https://github.com/strands-agents/sdk-python">Open-Source-Python-Implementierung</a> veröffentlicht, und es gibt jetzt auch eine <a href="https://dev.to/aws/strands-agents-now-speaks-typescript-a-side-by-side-guide-12b3">Typescript-Version</a>.</p><h2>Erste Schritte mit dem Strands Agents SDK in Python</h2><p>Starten Sie Ihre Programmiermaschinen. Wir werden jetzt im Eiltempo den Prozess des Klonens und Ausführens einer Beispiel-App durchgehen, die Strands Agents verwendet, um den <em>RPS+ Agent</em> über das A2A-Protokoll zu steuern. Lassen Sie uns eine optimierte Version des RPS+ Spiels entwickeln, bei der die Wahl des Agenten erst nach Ihrer Wahl bekannt gegeben wird, denn schließlich ist es das Rätselraten und der überraschende Ausgang, der Spiele wie „Schere, Stein, Papier“ so unterhaltsam macht.</p><p>Öffnen Sie auf Ihrem lokalen Computer <a href="https://code.visualstudio.com/download">Visual Studio Code</a> und öffnen Sie ein neues Terminal.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3de752025d62993f/6a17062d0c4857f16501a997/2339cc37c89a3524f2b2a21684bc61dae958e1cf-915x460.jpg" alt="" /><p>Im neu geöffneten Terminal führen Sie folgenden Befehl aus, um das Elasticsearch Labs-Repository zu klonen:</p>git clone https://github.com/elastic/elasticsearch-labs<p>Führen Sie den folgenden <em>cd</em>-Befehl aus, um das Verzeichnis in das Verzeichnis „elasticsearch-labs“ zu ändern:</p>cd elasticsearch-labs<p>Führen Sie anschließend folgenden Befehl aus, um das Repository in Visual Studio Code zu öffnen:</p>code .<p>Erweitern Sie im Visual Studio File Explorer die Ordner <em>supporting-blog-content</em> und <em>agent-builder-a2a-strands-agents</em> und öffnen Sie anschließend die Datei <em>elastic_agent_builder_a2a_rps+.py.</em> So sieht die Datei in Visual Studio Code aus:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt65ef8036a70bcaf1/6a17062f1949f7af36e7a935/d153b19e0e016c701576edb99ccab5af7c554f34-1484x1530.jpg" alt="" /><p>Hier ist der Inhalt der Datei <em>elastic_agent_builder_a2a_rps+.py</em>, den Sie in Ihrem Texteditor sehen sollten:</p>import asyncio
from dotenv import load_dotenv
from uuid import uuid4
import httpx
import os
import random
from a2a.client import A2ACardResolver, ClientConfig, ClientFactory
from a2a.types import Message, Part, Role, TextPart

DEFAULT_TIMEOUT = 60  # set request timeout to 1 minute


def create_message(*, role: Role = Role.user, text: str, context_id=None) -&gt; Message:
    return Message(
        kind="message",
        role="user",
        parts=[Part(TextPart(kind="text", text=text))],
        message_id=uuid4().hex,
        context_id=context_id,
    )


async def main():
    load_dotenv()
    a2a_agent_host = os.getenv("ES_AGENT_URL")
    a2a_agent_key = os.getenv("ES_API_KEY")
    custom_headers = {"Authorization": f"ApiKey {a2a_agent_key}"}

    async with httpx.AsyncClient(
        timeout=DEFAULT_TIMEOUT, headers=custom_headers
    ) as httpx_client:
        # Get agent card
        resolver = A2ACardResolver(httpx_client=httpx_client, base_url=a2a_agent_host)
        agent_card = await resolver.get_agent_card(
            relative_card_path="/rps_plus_agent.json"
        )
        # Create client using factory
        config = ClientConfig(
            httpx_client=httpx_client,
            streaming=True,
        )
        factory = ClientFactory(config)
        client = factory.create(agent_card)
        # Use the client to communicate with the agent
        print("\nSending 'start game' message to Elastic A2A agent...")
        random_game_object = random.randint(1, 5)
        msg = create_message(text=f"start with game object {random_game_object}")
        async for event in client.send_message(msg):
            if isinstance(event, Message):
                context_id = event.context_id
                response_complete = event.parts[0].root.text
                # Get agent choice from the first line of the response
                parsed_response = response_complete.split("\n", 1)
                agent_choice = parsed_response[0]
                print(parsed_response[1])
        # User choice sent for game results from the agent
        prompt = input("Your Choice  : ")
        msg = create_message(text=prompt, context_id=context_id)
        async for event in client.send_message(msg):
            if isinstance(event, Message):
                print(f"Agent Choice : {agent_choice}")
                print(event.parts[0].root.text)


if __name__ == "__main__":
    asyncio.run(main())<p>Lassen Sie uns einen Blick darauf werfen, was in diesem Code passiert. Ausgehend von der Methode <em><code>main()</code></em> greift der Code zunächst auf die Umgebungsvariablen für die Agenten-URL und den API-Schlüssel zu. Dann verwenden wir diese Werte, um ein <em><code>httpx</code></em><code> client</code> zu erstellen, mit dem wir die Agentenkarte für den Agenten abrufen können. Der Client verwendet dann die Agentenkartendaten, um eine „Spiel starten“-Anfrage an den Agenten zu senden. Interessant ist hierbei, dass wir einen <code>random_game_object</code> -Wert als Teil der <code>"start game"</code> -Anfrage einfügen. Dieser Wert ist eine Zufallszahl, die mit dem <em>Zufallsmodul</em> der Standardbibliothek von Python generiert wird. Der Grund dafür ist, dass sich herausgestellt hat, dass die leistungsstarken LLMs (die KI-Agenten ermöglichen) nicht besonders gut in Bezug auf Zufälligkeit sind. Kein Problem, hier kann Python helfen.</p><p>Im weiteren Verlauf des Codes wird, sobald der Agent auf die Anfrage „Spiel starten“ antwortet, die Spielobjektauswahl des Agenten extrahiert und in der Variable <em>agent_choice</em> gespeichert. Der Rest der Reaktion wird dem:der Nutzer:in als Text angezeigt. Anschließend wird der:die Nutzer:in zur Eingabe der eigenen Spielobjektauswahl aufgefordert. Diese Auswahl wird an den Agenten gesendet. Der Code zeigt dann die Auswahl des Spielobjekts durch den Agenten sowie dessen endgültige Entscheidung über den Spielausgang an.</p><h2>Einrichten Ihrer Agenten-URL und Ihres API-Schlüssels als Umgebungsvariablen</h2><p>Da die Beispiel-App auf Ihrem lokalen Computer ausgeführt wird, müssen wir dem Strands Agents SDK eine A2A-URL und einen API-Schlüssel für den Agenten bereitstellen, damit dieser mit unserem Agent Builder-Agenten kommunizieren kann. Die Beispiel-App verwendet eine Datei namens <em>.env</em>, um diese Werte zu speichern.</p><p>Erstellen Sie eine Kopie der Datei <em>env.example</em> und benennen Sie die neue Datei <em>.env.</em></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta17961cbcb42985c/6a170631b0367dc5a072bc55/25ead5f15a17dedb777132a082097cffb06cae4d-1600x843.jpg" alt="" /><p>Wechseln Sie zurück zum Elastic Agent Builder, wo wir die beiden benötigten Werte abrufen können.</p><p>Wählen Sie im Aktionsmenü des Agent Builders oben rechts auf der Seite die Option <strong>Alle Tools anzeigen</strong> aus.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt140885d7ebfcb969/6a1706327d8d67b17670e646/9c4f4e4a3bd76e11e0a182fa007a2f6aec7777b4-1600x880.jpg" alt="" /><p>Klicken Sie oben auf der Seite „Tools“ auf das Dropdown-Menü <strong>MCP-Server</strong> und wählen Sie <strong>MCP-Server-URL kopieren.</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc153c2caa27e949b/6a170634a292997793d00f6d/6cde0de678bb6f81bef8a59deffb110ad6c6ce26-1600x882.jpg" alt="" /><p>Fügen Sie die <strong>MCP-Server-URL</strong> als Ersatz für den <strong>&lt;YOUR-ELASTIC-AGENT-BUILDER-URL&gt;</strong>-Platzhalterwert in die <em>.env</em>-Datei ein. Nun müssen wir eine Aktualisierung an der URL vornehmen, das heißt, den Endtext „mcp“ durch „a2a“ ersetzen, da das <a href="https://a2a-protocol.org/">A2A-Protokoll</a> dasjenige ist, das das Agent Strands SDK zur Kommunikation mit dem in Elastic Agent Builder ausgeführten Agenten verwenden wird.</p><p>Die bearbeitete URL sollte in etwa so aussehen:</p>https://rps-game-project-12345a.kb.us-east-1.aws.elastic.cloud/api/agent_builder/a2a<p>Der andere Wert, den wir hier in Elastic Cloud brauchen, ist ein API-Schlüssel. Klicken Sie in der oberen Navigationsebene auf <strong>Elasticsearch</strong>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltada5de819f31d8ff/6a170635b339d55ae9769efc/651676b9be65178cdad50b5d24f26441c0bf3f97-1600x549.jpg" alt="" /><p>Klicken Sie auf die Schaltfläche <strong>API-Schlüssel kopieren</strong>, um den API-Schlüssel zu kopieren.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta18f85790df00706/6a170637cf4f257145b2d0bd/17f1e2ed5c7682630c71e75b0b09ffb1d9036210-1600x879.jpg" alt="" /><p>Zurück in Visual Studio Code fügen Sie nun den API-Schlüssel in die <em>.env</em>-Datei ein, um den Platzhaltertext <strong>&lt;YOUR-ELASTIC-API-KEY&gt; </strong>zu ersetzen. Ihre <em>.env</em>-Datei sollte etwa so aussehen:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt92ab4b37cdcca85e/6a1706386f7f0472ed914747/a357947e07f29c8c03382e00c7baedf04a399297-1600x286.jpg" alt="" /><h2>Die Beispiel-App ausführen</h2><p>Öffnen Sie ein neues Terminal in Visual Studio Code.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8702d826849755d0/6a17063a60084b45ca3c44a2/33e1174c68ea1ed47c7fe62ab6a6da657c606f56-1413x711.jpg" alt="" /><p>Führen Sie zunächst den folgenden <em>cd</em>-Befehl im Terminal aus:</p>cd elasticsearch-labs/supporting-blog-content/agent-builder-a2a-strands-agents<p>Führen Sie den folgenden Befehl aus, um eine virtuelle Python-Umgebung zu erstellen.</p>python -m venv .venv<p>Führen Sie je nach Betriebssystem Ihres lokalen Computers den folgenden Befehl aus, um die virtuelle Umgebung zu aktivieren.</p><ul><li><p>macOS/Linux</p></li></ul>source .venv/bin/activate<ul><li><p>Windows</p></li></ul>.venv\Scripts\activate<p>Die Beispiel-App verwendet das Strands Agents SDK, und wir sind nun an dem Punkt in dieser Anleitung angelangt, an dem wir es installieren müssen. Führen Sie folgenden Befehl aus, um das Strands Agents SDK zusammen mit allen erforderlichen Python-Bibliotheksabhängigkeiten zu installieren.</p>pip install -r requirements.txt<p>Es ist Zeit, die Startrampe freizumachen und den Countdown zu starten. Wir sind bereit, diese App zu starten. Zurücktreten. Führen wir sie mit folgendem Befehl aus:</p>python elastic_agent_builder_a2a_rps+.py<p>Sie sollten mit einer Partie RPS+ herausgefordert werden. Gut gemacht und viel Erfolg!</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbb3715672995fcfa/6a17063c6234e07b76db195f/041df81fbf1776f09e1243af0a435c4c0af6aca1-1600x948.gif" alt="" /><h2>Erstellen Sie Ihre KI-Apps mit relevantem Kontext</h2><p>Die Entwicklung eines KI-Agenten gehört nun zu Ihren Kernkompetenzen. Und Sie haben gesehen, wie einfach die Verwendung von Elastic Agent Builder-Agenten über A2A in Agenten-Entwicklungs-Frameworks wie dem Strands Agents SDK ist. <a href="https://cloud.elastic.co/registration?utm_source=agentic-ai-category&amp;utm_medium=search-labs&amp;utm_campaign=agent-builder">Testen Sie Elastic,</a> um KI-Agenten zu erstellen, die mit dem relevanten Kontext Ihrer benutzerdefinierten Daten verknüpft sind.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/agent-builder-a2a-strands-agents-guide</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/agent-builder-a2a-strands-agents-guide</guid>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[Agentische KI]]></category>
    <dc:creator><![CDATA[Jonathan Simon]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3472edce39ec0b81/6a17060e66c4f93c17f8bf57/31b6a5c1c30dacbb4d5e58d1c566071e7143a0c8-1600x879.gif" length="0" type="image/gif"/>
    <pubDate>Mon, 15 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[So erstellen Sie mit LangGraph.js und Elasticsearch einen KI-Suchworkflow für das Finanzwesen]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie LangGraph.js mit Elasticsearch verwenden können, um einen KI-gestützten Finanz-Suchworkflow zu erstellen, der Abfragen in natürlicher Sprache in dynamische, bedingte Filter für Investitions- und Marktanalysen umwandelt.]]></description>
    <content:encoded><![CDATA[<p>Beim Erstellen von KI-Suchanwendungen müssen häufig mehrere Aufgaben, der Datenabruf und die Datenextraktion zu einem nahtlosen Workflow koordiniert werden. LangGraph vereinfacht diesen Prozess, indem es Entwicklern ermöglicht, KI-Agenten mithilfe einer node-basierten Struktur zu orchestrieren. In diesem Artikel werden wir eine Finanzlösung mit <a href="https://langchain-ai.github.io/langgraphjs/">LangGraph.js</a> erstellen.</p><h2>Was ist LangGraph?</h2><p><a href="https://langchain-ai.github.io/langgraphjs/">LangGraph</a> ist ein Framework zum Erstellen von KI-Agenten und deren Orchestrierung in einem Workflow, um KI-unterstützte Anwendungen zu entwickeln. LangGraph verfügt über eine Knotenarchitektur, in der wir Funktionen deklarieren können, die Aufgaben darstellen, und diese als Knoten des Workflows zuweisen können. Das Ergebnis der Interaktion mehrerer Knoten ist ein Graph. LangGraph ist Teil des umfassenderen <a href="https://js.langchain.com/docs/introduction/">LangChain-Ökosystems</a>, das Tools für die Erstellung modularer und zusammensetzbarer KI-Systeme bereitstellt.</p><p>Zur Veranschaulichung dessen, warum LangGraph nützlich ist, werden wir eine problematische Situation damit lösen.</p><h2>Überblick über die Lösung</h2><p>In einem Risikokapitalunternehmen haben Investoren Zugriff auf eine umfangreiche Datenbank mit zahlreichen Filteroptionen, aber wenn man Kriterien kombinieren möchte, wird es schwierig und langsam. Dies kann dazu führen, dass einige relevante Start-ups für Investitionen nicht entdeckt werden. Das Ergebnis: Man verbringt viele Stunden damit, die besten Kandidaten zu identifizieren, oder verpasst sogar Chancen.</p><p>Mit LangGraph und Elasticsearch können wir gefilterte Suchen in natürlicher Sprache durchführen, sodass Nutzer komplexe Anfragen mit Dutzenden von Filtern nicht manuell erstellen müssen. Um die Flexibilität zu erhöhen, entscheidet der Workflow anhand der Nutzereingaben automatisch zwischen zwei Abfragetypen.</p><ul><li><p><strong>Investitionsorientierte Anfragen</strong>: Diese zielen auf finanzielle und finanzierungsbezogene Aspekte von Start-ups ab, wie <a href="https://www.investopedia.com/articles/personal-finance/102015/series-b-c-funding-what-it-all-means-and-how-it-works.asp">Finanzierungsrunden</a>, Bewertung oder <a href="https://www.investopedia.com/terms/r/revenue.asp">Umsatz</a>. <em>Beispiel:</em> „Suche Start-ups mit einer Series-A- oder Series-B-Finanzierung zwischen 8 und 25 Mio. Dollar und einem monatlichen Umsatz von über 500.000 Dollar.“</p></li><li><p><strong>Marktorientierte Anfragen</strong>: Diese konzentrieren sich auf <a href="https://en.wikipedia.org/wiki/Vertical_market">Branchensegmente</a>, <a href="https://en.wikipedia.org/wiki/Target_market">geografische Märkte</a> oder <a href="https://www.investopedia.com/terms/b/businessmodel.asp">Geschäftsmodelle</a> und helfen dabei, Chancen in bestimmten Sektoren oder Regionen zu identifizieren. <em>Beispiel:</em> „Suche Fintech- und Healthcare-Start-ups in San Francisco, New York oder Boston.“</p></li></ul><p>Um die Abfragen robust zu halten, werden wir das LLM dazu bringen, <a href="https://www.elastic.co/docs/solutions/search/search-templates">Suchvorlagen</a> anstelle vollständiger <a href="https://www.elastic.co/docs/explore-analyze/query-filter/languages/querydsl">DSL-Abfragen</a> zu erstellen. Auf diese Weise erhalten Sie immer die gewünschte Abfrage, und der LLM muss lediglich die Lücken ausfüllen und trägt nicht die Verantwortung, die benötigte Abfrage jedes Mal neu zu erstellen.</p><h2>Was Sie brauchen, um loszulegen</h2><ul><li><p>Elasticsearch API-Schlüssel</p></li><li><p>OpenAPI-API-Schlüssel</p></li><li><p>Node 18 oder neuer</p></li></ul><h2>Schritt-für-Schritt-Anweisungen</h2><p>In diesem Abschnitt schauen wir uns an, wie die App aussehen wird. Dafür verwenden wir <a href="https://www.typescriptlang.org/">TypeScript</a>, ein Superset von JavaScript, das statische Typen hinzufügt, um den Code zuverlässiger, leichter zu pflegen und sicherer zu machen, indem Fehler frühzeitig erkannt werden, während er vollständig kompatibel mit bestehendem JavaScript bleibt.</p><p>Der Knotenfluss sieht wie folgt aus:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt90db8f03f372608c/6a170986dc55de6e16e00d93/b47d7f238c4964a6febc0de7fe5e68b186f539c3-363x555.png" alt="" /><p>Das obige Bild wird von LangGraph generiert und stellt den Workflow dar, der die Ausführungsreihenfolge und die bedingte Logik zwischen den Knoten definiert:</p><ul><li><p><strong>decideStrategy: </strong>Verwendet ein LLM, um die Anfrage des Nutzers zu analysieren und zwischen zwei spezialisierten Suchstrategien zu entscheiden – investitionsorientiert oder marktorientiert.</p></li><li><p><strong>prepareInvestmentSearch: </strong>Extrahiert Filterwerte aus der Abfrage und erstellt eine vordefinierte Vorlage, die finanzielle und finanzierungsbezogene Parameter hervorhebt.</p></li><li><p><strong>prepareMarketSearch</strong>: Extrahiert ebenfalls Filterwerte, baut jedoch dynamisch Parameter auf, die den Markt-, Branchen- und geografischen Kontext betonen.</p></li><li><p><strong>executeSearch: </strong>Sendet die konstruierte Abfrage mit einer Suchvorlage an Elasticsearch und ruft die entsprechenden Start-up-Dokumente ab.</p></li><li><p><strong>VisualizeResults: </strong>Formatiert die Endergebnisse in einer klaren, lesbaren Zusammenfassung, die die wichtigsten Startup-Attribute wie Finanzierung, Branche und Umsatz aufzeigt.</p></li></ul><p>Dieser Fluss umfasst eine <a href="https://langchain-ai.github.io/langgraphjs/how-tos/branching/?h=conditional#how-to-create-branches-for-parallel-node-execution">bedingte Verzweigung</a>, die als „if“-Anweisung fungiert und basierend auf der Eingabe des Nutzers bestimmt, ob der Investitions- oder Marktsuchpfad verwendet wird. Diese vom LLM gesteuerte Entscheidungslogik macht den Workflow adaptiv und kontextsensitiv – ein Mechanismus, den wir in den nächsten Abschnitten genauer untersuchen werden.</p><h3>LangGraph-Status</h3><p>Bevor wir jeden Knoten einzeln betrachten, müssen wir verstehen, wie die Knoten kommunizieren und Daten austauschen. Dafür ermöglicht uns LangGraph, den Workflow-Status zu definieren. Dies definiert den gemeinsamen Status, der zwischen Knoten weitergegeben wird.</p><p>Der Zustand fungiert als gemeinsamer Container, der während des gesamten Workflows Zwischendaten speichert: Er beginnt mit der natürlichsprachlichen Anfrage des Nutzers, speichert dann die ausgewählte Suchstrategie, die vorbereiteten Parameter für Elasticsearch, die abgerufenen Suchergebnisse und schließlich den formatierten Ausgang.</p><p>Diese Struktur ermöglicht es jedem Knoten, den Status zu lesen und zu aktualisieren, wodurch ein konsistenter Informationsfluss vom Nutzer-Eingang bis zur endgültigen Visualisierung gewährleistet wird.</p>const VCState = Annotation.Root({
  input: Annotation&lt;string&gt;(), // User's natural language query
  searchStrategy: Annotation&lt;string&gt;(), // Search strategy chosen by LLM
  searchParams: Annotation&lt;any&gt;(), // Prepared search parameters
  results: Annotation&lt;any[]&gt;(), // Search results
  final: Annotation&lt;string&gt;(), // Final formatted response
});<h3>Einrichten der Anwendung</h3><p>Der gesamte Code in diesem Abschnitt ist im <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch">elasticsearch-labs-Repository</a> zu finden.</p><p>Öffnen Sie ein Terminal in dem Ordner, in dem sich die App befindet, und initialisieren Sie eine Node.js-Anwendung mit folgendem Befehl:</p>npm init -y<p>Nun können wir die notwendigen Abhängigkeiten für dieses Projekt installieren:</p>npm install @elastic/elasticsearch @langchain/langgraph @langchain/openai @langchain/core dotenv zod &amp;&amp; npm install --save-dev @types/node tsx typescript<ul><li><p><strong><code>@elastic/elasticsearch</code></strong>: Hilft uns bei der Bearbeitung von Elasticsearch-Anfragen, z. B. bei der Daten-Ingestion und dem Abrufen von Daten.</p></li><li><p><strong><code>@langchain/langgraph</code></strong>: JS-Abhängigkeit zur Bereitstellung aller LangGraph-Tools.</p></li><li><p><strong><code>@langchain/openai</code></strong>: LLM-Client von OpenAI für LangChain.</p></li><li><p>@langchain/core: Bietet die grundlegenden Bausteine für LangChain-Apps, einschließlich Prompt-Vorlagen.</p></li><li><p><strong><code>dotenv</code></strong>: Notwendige Abhängigkeit zur Verwendung von Umgebungsvariablen in JavaScript.</p></li><li><p><strong><code>zod</code></strong>: Abhängigkeit von Typdaten.</p></li></ul><p><code>@types/node</code> <code>tsx</code> <code>typescript</code> ermöglicht es uns, TypeScript-Code zu schreiben und auszuführen.</p><p>Erstellen Sie nun die folgenden Dateien:</p><ul><li><p><code>elasticsearchSetup</code><a href="http://ingest.ts/"><code>.ts</code></a>: Erstellt die Index-Mappings, lädt die Daten aus einer JSON-Datei und führt den Ingest der Daten in Elasticsearch durch.</p></li><li><p><a href="http://main.ts/"><code>main.ts</code></a>: Wird die LangGraph-Anwendung enthalten.</p></li><li><p><code>.env</code>Datei zum Speichern der Umgebungsvariablen</p></li></ul><p>In der <code>.env</code>-Datei fügen wir die folgenden Umgebungsvariablen hinzu:</p>ELASTICSEARCH_ENDPOINT="your-endpoint-here"
ELASTICSEARCH_API_KEY="your-key-here"
OPENAI_API_KEY="your-key-here"<p>Der OpenAPI-APIKey wird nicht direkt im Code verwendet; stattdessen wird er intern von der Bibliothek <code>@langchain/openai</code> verwendet.</p><p>Die gesamte Logik bezüglich der Erstellung von Mappings, der Erstellung von Suchvorlagen und der Datensatz-Ingestion kann in der Datei <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/elasticsearchSetup.ts"><code>elasticsearchSetup.ts</code></a> gefunden werden. In den nächsten Schritten konzentrieren wir uns auf die <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/main.ts"><code>main.ts</code></a>-Datei. Sie können den Datensatz auch überprüfen, um besser zu verstehen, wie die Daten in <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/dataset.json"><code>dataset.json</code></a> aussehen.</p><h3>LangGraph-App</h3><p>In der <code>main.ts</code>-Datei importieren wir einige notwendige Abhängigkeiten, um die LangGraph-Anwendung zu konsolidieren. In dieser Datei müssen Sie auch die Knotenfunktionen und die Zustandsdeklaration angeben. Die Graphdeklaration erfolgt in den nächsten Schritten anhand einer<code>main</code>-Methode. Die <code>elasticsearchSetup.ts</code>-Datei wird Elasticsearch-Helfer enthalten, die wir in den nächsten Schritten in den Knoten verwenden werden.</p>import { writeFileSync } from "node:fs";
import { StateGraph, Annotation, START, END } from "@langchain/langgraph";
import { ChatOpenAI } from "@langchain/openai";
import { z } from "zod";
import {
  esClient,
  ingestDocuments,
  createSearchTemplates,
  INDEX_NAME,
  INVESTMENT_FOCUSED_TEMPLATE,
  MARKET_FOCUSED_TEMPLATE,
  createIndex,
} from "./elasticsearchSetup.js";

const llm = new ChatOpenAI({ model: "gpt-4o-mini" });<p>Wie bereits erwähnt, wird der LLM-Client verwendet, um die Elasticsearch-Suchvorlagenparameter basierend auf der Frage des Nutzers zu generieren.</p>async function saveGraphImage(app: any): Promise&lt;void&gt; {
  try {
    const drawableGraph = app.getGraph();
    const image = await drawableGraph.drawMermaidPng();
    const arrayBuffer = await image.arrayBuffer();

    const filePath = "./workflow_graph.png";
    writeFileSync(filePath, new Uint8Array(arrayBuffer));
    console.log(`📊 Workflow graph saved as: ${filePath}`);
  } catch (error: any) {
    console.log("⚠️  Could not save graph image:", error.message);
  }
}<p>Die oben dargelegte Methode erzeugt das Graphbild im PNG-Format und verwendet hinter den Kulissen die <a href="https://mermaid.ink/">Mermaid.INK-API</a>. Dies ist nützlich, wenn Sie sehen möchten, wie die App-Knoten mit einer gestylten Visualisierung zusammenwirken.</p><h3>LangGraph-Knoten</h3><p>Sehen wir uns nun die einzelnen Knoten im Detail an:</p><h3>decideSearchStrategy-Knoten</h3><p>Der <code>decideSearchStrategy</code>-Knoten analysiert die Eingabe und entscheidet, ob eine investitions- oder marktorientierte Suche durchgeführt werden soll. Er verwendet ein LLM mit einem strukturierten Ausgang (definiert mit Zod), um den Abfragetyp zu klassifizieren. Bevor die Entscheidung getroffen wird, werden mithilfe einer Aggregation die verfügbaren Filter aus dem Index abgerufen, um sicherzustellen, dass das Modell über einen aktuellen Kontext zu Branchen, Standorten und Finanzierungsdaten verfügt.</p><p>Um die möglichen Filterwerte zu extrahieren und an das LLM zu senden, verwenden wir eine <a href="https://www.elastic.co/docs/explore-analyze/query-filter/aggregations">Aggregation</a>, um sie direkt aus dem Elasticsearch-Index abzurufen. Diese Logik wird in einer Methode namens <code>getAvailableFilters</code>zugeordnet:</p>async function getAvailableFilters() {
  try {
    const response = await esClient.search({
      index: INDEX_NAME,
      size: 0,
      aggs: {
        industries: {
          terms: { field: "industry", size: 100 },
        },
        locations: {
          terms: { field: "location", size: 100 },
        },
        funding_stages: {
          terms: { field: "funding_stage", size: 20 },
        },
        business_models: {
          terms: { field: "business_model", size: 10 },
        },
        lead_investors: {
          terms: { field: "lead_investor", size: 100 },
        },
        funding_amount_stats: {
          stats: { field: "funding_amount" },
        },
      },
    });

    return response.aggregations;
  } catch (error) {
    console.error("❌ Error getting available filters:", error);
    return {};
  }
}<p>Mit der obigen Aggregationsanfrage erhalten wir die folgenden Ergebnisse:</p>{
  "industries": {
    "doc_count_error_upper_bound": 0,
    "sum_other_doc_count": 0,
    "buckets": [
      {
        "key": "logistics",
        "doc_count": 5
      },
      ...
    ]
  },
  "locations": {
    "doc_count_error_upper_bound": 0,
    "sum_other_doc_count": 0,
    "buckets": [
      {
        "key": "San Francisco, CA",
        "doc_count": 4
      },
      {
        "key": "New York, NY",
        "doc_count": 3
      },
      ...
    ]
  },
  "funding_stages": {
    "doc_count_error_upper_bound": 0,
    "sum_other_doc_count": 0,
    "buckets": [
      {
        "key": "Series A",
        "doc_count": 8
      },
      ...
    ]
  },
  "business_models": {
    "doc_count_error_upper_bound": 0,
    "sum_other_doc_count": 0,
    "buckets": [
      {
        "key": "B2B",
        "doc_count": 13
      },
      ...
    ]
  },
  "lead_investors": {
    "doc_count_error_upper_bound": 0,
    "sum_other_doc_count": 0,
    "buckets": [
      {
        "key": "Battery Ventures",
        "doc_count": 1
      },
      {
        "key": "Benchmark Capital",
        "doc_count": 1
      },
      ...
    ]
  },
  "funding_amount_stats": {
    "count": 20,
    "min": 4500000,
    "max": 35000000,
    "avg": 14075000,
    "sum": 281500000
  }
}<p>Alle Ergebnisse finden Sie <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/responses/aggregationsResponse.json">hier</a>.</p><p>Für beide Strategien verwenden wir eine hybride Suche, um sowohl den strukturierten Teil der Frage (Filter) als auch die subjektiveren Teile (Semantik) zu erkennen. Hier ist ein Beispiel für beide Abfragen unter Verwendung von <a href="https://www.elastic.co/docs/solutions/search/search-templates">Suchvorlagen</a>:</p>await esClient.putScript({
      id: INVESTMENT_FOCUSED_TEMPLATE,
      script: {
        lang: "mustache",
        source: `{
          "size": 5,
          "retriever": {
            "rrf": {
              "retrievers": [
                {
                  "standard": {
                    "query": {
                      "semantic": {
                        "field": "semantic_field",
                        "query": "{{query_text}}"
                      }
                    }
                  }
                },
                {
                  "standard": {
                    "query": {
                      "bool": {
                        "filter": [
                          {"terms": {"funding_stage": {{#join}}{{#toJson}}funding_stage{{/toJson}}{{/join}}}},
                          {"range": {"funding_amount": {"gte": {{funding_amount_gte}}{{#funding_amount_lte}},"lte": {{funding_amount_lte}}{{/funding_amount_lte}}}}},
                          {"terms": {"lead_investor": {{#join}}{{#toJson}}lead_investor{{/toJson}}{{/join}}}},
                          {"range": {"monthly_revenue": {"gte": {{monthly_revenue_gte}}{{#monthly_revenue_lte}},"lte": {{monthly_revenue_lte}}{{/monthly_revenue_lte}}}}}
                        ]
                      }
                    }
                  }
                }
              ],
              "rank_window_size": 100,
              "rank_constant": 20
            }
          }
        }`,
      },
    });<p>Sehen Sie sich die Abfragen an, die in der<a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/elasticsearchSetup.ts#L119"><code>elasticsearchSetup.ts</code></a>-Datei detailliert beschrieben sind. Im folgenden Knoten wird entschieden, welche der beiden Abfragen verwendet wird:</p>// Node 1: Decide search strategy using LLM
async function decideSearchStrategy(state: typeof VCState.State) {
  // Zod schema for specialized search strategy decision
  const SearchDecisionSchema = z.object({
    search_type: z
      .enum(["investment_focused", "market_focused"])
      .describe("Type of specialized search strategy to use"),
    reasoning: z
      .string()
      .describe("Brief explanation of why this search strategy was chosen"),
  });

  const decisionLLM = llm.withStructuredOutput(SearchDecisionSchema);

  // Get dynamic filters from Elasticsearch
  const availableFilters = await getAvailableFilters();

  const prompt = `Query: "${state.input}"
    Available filters: ${JSON.stringify(availableFilters, null, 2)}

    Choose between two specialized search strategies:
    
    - investment_focused: For queries about funding stages, funding amounts, monthly revenue, lead investors, financial performance
    
    - market_focused: For queries about industries, locations, business models, market segments, geographic markets
    
    Analyze the query intent and choose the most appropriate strategy.
  `;

  try {
    const result = await decisionLLM.invoke(prompt);
    console.log(
      `🤔 Search strategy: ${result.search_type} - ${result.reasoning}`
    );

    return {
      searchStrategy: result.search_type,
    };
  } catch (error: any) {
    console.error("❌ Error in decideSearchStrategy:", error.message);
    return {
      searchStrategy: "investment_focused",
    };
  }
}<h3>prepareInvestmentSearch- und prepareMarketSearch-Knoten</h3><p>Beide Knoten verwenden eine gemeinsame Hilfsfunktion, <code>extractFilterValues</code>, die das LLM nutzt, um relevante Filter zu identifizieren, die in den Nutzereingaben erwähnt werden, wie z. B. Branche, Standort, Finanzierungsphase, Geschäftsmodell usw. Wir verwenden dieses Schema, um unsere <a href="https://www.elastic.co/docs/solutions/search/search-templates">Suchvorlage</a> zu erstellen.</p>// Extract all possible filter values from user input
async function extractFilterValues(input: string) {
  const FilterValuesSchema = z.object({
    // Investment-focused filters
    funding_stage: z
      .array(z.string())
      .default([])
      .describe("Funding stage values mentioned in query"),
    funding_amount_gte: z
      .number()
      .default(0)
      .describe("Minimum funding amount in USD"),
    funding_amount_lte: z
      .number()
      .default(100000000)
      .describe("Maximum funding amount in USD"),
    lead_investor: z
      .array(z.string())
      .default([])
      .describe("Lead investor values mentioned in query"),
    monthly_revenue_gte: z
      .number()
      .default(0)
      .describe("Minimum monthly revenue in USD"),
    monthly_revenue_lte: z
      .number()
      .default(10000000)
      .describe("Maximum monthly revenue in USD"),
    industry: z
      .array(z.string())
      .default([])
      .describe("Industry values mentioned in query"),
    location: z
      .array(z.string())
      .default([])
      .describe("Location values mentioned in query"),
    business_model: z
      .array(z.string())
      .default([])
      .describe("Business model values mentioned in query"),
  });

  const extractorLLM = llm.withStructuredOutput(FilterValuesSchema);
  const availableFilters = await getAvailableFilters();

  const extractPrompt = `Extract ALL relevant filter values from: "${input}"
    Available options: ${JSON.stringify(availableFilters, null, 2)}
    Extract only values explicitly mentioned in the query. Leave fields empty if not mentioned.`;

  return await extractorLLM.invoke(extractPrompt);
}<p>Je nach erkannter Absicht wählt der Workflow einen von zwei Pfaden:</p><p><strong>prepareInvestmentSearch:</strong> Erstellt finanzorientierte Suchparameter, einschließlich Finanzierungsphase, Finanzierungsbetrag, Investor und Erneuerungsinformationen. Die gesamte Abfragevorlage finden Sie in der <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/elasticsearchSetup.ts"><code>elasticsearchSetup.ts</code></a>-Datei:</p>// Node 2A: Prepare Investment-Focused Search Parameters 
async function prepareInvestmentSearch(state: typeof VCState.State) {
  console.log(
    "💰 Preparing INVESTMENT-FOCUSED search parameters with financial emphasis..."
  );

  try {
    // Extract all filter values from input
    const values = await extractFilterValues(state.input);

    let searchParams: any = {
      template_id: INVESTMENT_FOCUSED_TEMPLATE,
      query_text: state.input,
      ...values,
    };

    return { searchParams };
  } catch (error) {
    console.error("❌ Error preparing investment-focused params:", error);
    return {
      searchParams: {},
    };
  }
}<p><strong>prepareMarketSearch:</strong> erstellt marktorientierte Parameter, die sich auf Branchen, Geografien und Geschäftsmodelle konzentrieren. Die vollständige Abfrage finden Sie in der Datei <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/langgraph-js-elasticsearch/elasticsearchSetup.ts"><code>elasticsearchSetup.ts</code></a>:</p>// Node 2B: Prepare Market-Focused Search Parameters
async function prepareMarketSearch(state: typeof VCState.State) {
  console.log(
    "🔍 Preparing MARKET-FOCUSED search parameters with market emphasis..."
  );

  try {
    // Extract all filter values from input
    const values = await extractFilterValues(state.input);

    let searchParams: any = {
      template_id: MARKET_FOCUSED_TEMPLATE,
      query_text: state.input,
      ...values,
    };

    return { searchParams };
  } catch (error) {
    console.error("❌ Error preparing market-focused params:", error);
    return {};
  }
}<h3>executeSearch-Knoten</h3><p>Dieser Knoten nimmt die gesuchten Parameter aus dem Zustand und sendet sie zuerst an Elasticsearch, wobei er die <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-render-search-template">_render-API</a> verwendet, um die Abfrage für Debugging-Zwecke zu visualisieren, und sendet dann eine Anfrage zur Abrufung der Ergebnisse.</p>// Node 3: Execute Search
async function executeSearch(state: typeof VCState.State) {
  const { searchParams } = state;

  try {
    // getting formed query from template for debugging
    const renderedTemplate = await esClient.renderSearchTemplate({
      id: searchParams.template_id,
      params: searchParams,
    });

    console.log(
      "📋 Complete query:",
      JSON.stringify(renderedTemplate.template_output, null, 2)
    );

    const results = await esClient.searchTemplate({
      index: INDEX_NAME,
      id: searchParams.template_id,
      params: searchParams,
    });

    return {
      results: results.hits.hits.map((hit: any) =&gt; hit._source),
    };
  } catch (error: any) {
    console.error(`❌ ${state.searchParams.search_type} search error:`, error);
    return { results: [] };
  }
}<h3>visualizeResults-Knoten</h3><p>Dieser Knoten zeigt schließlich die Elasticsearch-Ergebnisse an.</p>// Node 4: Visualize results
async function visualizeResults(state: typeof VCState.State) {
  const results = state.results || [];

  let formattedResults = `🎯 Found ${results.length} startups matching your criteria:\n\n`;

  results.forEach((startup: any, index: number) =&gt; {
    formattedResults += `${index + 1}. **${startup.company_name}**\n`;
    formattedResults += `   📍 ${startup.location} | 🏢 ${startup.industry} | 💼 ${startup.business_model}\n`;
    formattedResults += `   💰 ${startup.funding_stage} - $${(
      startup.funding_amount / 1000000
    ).toFixed(1)}M\n`;
    formattedResults += `   👥 ${startup.employee_count} employees | 📈 $${(
      startup.monthly_revenue / 1000
    ).toFixed(0)}K MRR\n`;
    formattedResults += `   🏦 Lead: ${startup.lead_investor}\n`;
    formattedResults += `   📝 ${startup.description}\n\n`;
  });

  return {
    final: formattedResults,
  };
}<p>Programmatisch sieht der gesamte Graph so aus:</p>  const workflow = new StateGraph(VCState)
    // Register nodes - these are the processing functions
    .addNode("decideStrategy", decideSearchStrategy)
    .addNode("prepareInvestment", prepareInvestmentSearch)
    .addNode("prepareMarket", prepareMarketSearch)
    .addNode("executeSearch", executeSearch)
    .addNode("visualizeResults", visualizeResults)
    // Define execution flow with conditional branching
    .addEdge(START, "decideStrategy") // Start with strategy decision
    .addConditionalEdges(
      "decideStrategy",
      (state: typeof VCState.State) =&gt; state.searchStrategy, // Conditional function
      {
        investment_focused: "prepareInvestment", // If investment focused -&gt; RRF template preparation
        market_focused: "prepareMarket", // If market focused -&gt; dynamic query preparation
      }
    )
    .addEdge("prepareInvestment", "executeSearch") // Investment prep -&gt; execute
    .addEdge("prepareMarket", "executeSearch") // Market prep -&gt; execute
    .addEdge("executeSearch", "visualizeResults") // Execute -&gt; visualize
    .addEdge("visualizeResults", END); // End workflow<p>Wie Sie sehen können, haben wir eine bedingte Kante, bei der die App entscheidet, welcher „Pfad“ oder Knoten als Nächstes ausführen wird. Dieses Feature ist nützlich, wenn Workflows Verzweigungslogik benötigen, etwa die Wahl zwischen mehreren Tools oder das Einfügen eines Human-in-the-Loop-Schrittes.</p><p>Nachdem wir die Kern-Features von LangGraph verstanden haben, können wir die Anwendung einrichten, in der der Code ausgeführt werden soll:</p><p>Alles wird in einer <code>main</code>-Methode zusammengefasst. Hier deklarieren wir den Graphen mit allen Elementen unter der Variablen „Workflow“:</p>async function main() {
  await createIndex();
  await createSearchTemplates();
  await ingestDocuments();

  // Create the workflow graph with shared state
  const workflow = new StateGraph(VCState)
    // Register nodes - these are the processing functions
    .addNode("decideStrategy", decideSearchStrategy)
    .addNode("prepareInvestment", prepareInvestmentSearch)
    .addNode("prepareMarket", prepareMarketSearch)
    .addNode("executeSearch", executeSearch)
    .addNode("visualizeResults", visualizeResults)
    // Define execution flow with conditional branching
    .addEdge(START, "decideStrategy") // Start with strategy decision
    .addConditionalEdges(
      "decideStrategy",
      (state: typeof VCState.State) =&gt; state.searchStrategy, // Conditional function
      {
        investment_focused: "prepareInvestment", // If investment focused -&gt; RRF template preparation
        market_focused: "prepareMarket", // If market focused -&gt; dynamic query preparation
      }
    )
    .addEdge("prepareInvestment", "executeSearch") // Investment prep -&gt; execute
    .addEdge("prepareMarket", "executeSearch") // Market prep -&gt; execute
    .addEdge("executeSearch", "visualizeResults") // Execute -&gt; visualize
    .addEdge("visualizeResults", END); // End workflow


  const app = workflow.compile();

  await saveGraphImage(app);

  const query =
    "Find startups with Series A or Series B funding between $8M-$25M and monthly revenue above $500K";

  const marketResult = await app.invoke({ input: query });
  console.log(marketResult.final);
}<p>Die Abfragevariable simuliert die in einer hypothetischen Suchleiste eingegebenen Nutzereingaben:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltba7189d5f4e63403/6a1709880e2e49cc3041a076/e8d76909eb2bc1bb62f3ca9a8b3e4b85fcec2893-1600x164.png" alt="" /><p>Aus der natürlichsprachlichen Formulierung „Suche Start-ups mit Series-A- oder Series-B-Finanzierung zwischen 8 und 25 Millionen US-Dollar und einem monatlichen Umsatz von über 500.000 US-Dollar“ werden alle Filter extrahiert.</p><p>Rufen Sie abschließend die Hauptmethode auf:</p>main().catch(console.error);<h3>Ergebnisse</h3>🔍 Checking if index exists...
🏗️ Creating index...
✅ Index created successfully!
Ingesting documents...
✅ Documents ingested successfully!
✅ Investment-focused template created successfully!
✅ Market-focused template created successfully!

📊 Workflow graph saved as: ./workflow_graph.png

🔍 Query: "Find startups with Series A or Series B funding between $8M-$25M and monthly revenue above $500K"

🤔 Search strategy: investment_focused - The query specifically seeks profitable fintech startups with defined funding amounts and high monthly revenue, which aligns closely with financial performance metrics and investment-related criteria.

💰 Preparing INVESTMENT-FOCUSED search parameters with financial emphasis...

📋 Complete query: {
  "size": 5,
  "retriever": {
    "rrf": {
      "retrievers": [
        {
          "standard": {
            "query": {
              "semantic": {
                "field": "semantic_field",
                "query": "Find startups with Series A or Series B funding between $8M-$25M and monthly revenue above $500K"
              }
            }
          }
        },
        {
          "standard": {
            "query": {
              "bool": {
                "filter": [
                  {
                    "terms": {
                      "funding_stage": [
                        "Series A",
                        "Series B"
                      ]
                    }
                  },
                  {
                    "range": {
                      "funding_amount": {
                        "gte": 8000000,
                        "lte": 25000000
                      }
                    }
                  },
                  {
                    "terms": {
                      "lead_investor": []
                    }
                  },
                  {
                    "range": {
                      "monthly_revenue": {
                        "gte": 500000,
                        "lte": 0
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      ],
      "rank_window_size": 100,
      "rank_constant": 20
    }
  }
}
🎯 Found 5 startups matching your criteria:

1. **TechFlow**
   📍 San Francisco, CA | 🏢 logistics | 💼 B2B
   💰 Series A - $8.0M
   👥 45 employees | 📈 $500K MRR
   🏦 Lead: Sequoia Capital
   📝 TechFlow optimizes supply chain operations using AI-powered route optimization and real-time tracking. Founded in 2023, shows remarkable growth with $500K monthly revenue.

2. **DataViz**
   📍 New York, NY | 🏢 enterprise software | 💼 B2B
   💰 Series A - $10.0M
   👥 42 employees | 📈 $450K MRR
   🏦 Lead: Battery Ventures
   📝 DataViz creates intuitive data visualization tools for enterprise customers. No-code platform allows business users to create dashboards without technical expertise.

3. **FinanceAI**
   📍 San Francisco, CA | 🏢 fintech | 💼 B2C
   💰 Series C - $25.0M
   👥 120 employees | 📈 $1200K MRR
   🏦 Lead: Tiger Global Management
   📝 FinanceAI provides AI-powered investment advisory services to retail investors. Uses machine learning to analyze market trends with over 100,000 active users.

4. **UrbanMobility**
   📍 New York, NY | 🏢 logistics | 💼 B2B2C
   💰 Series B - $15.0M
   👥 78 employees | 📈 $750K MRR
   🏦 Lead: Kleiner Perkins
   📝 UrbanMobility revolutionizes urban transportation through autonomous delivery drones and smart logistics hubs. Partners with major retailers for same-day delivery across Manhattan and Brooklyn.

5. **HealthTech Solutions**
   📍 Boston, MA | 🏢 healthcare | 💼 B2B
   💰 Series B - $18.0M
   👥 95 employees | 📈 $900K MRR
   🏦 Lead: General Catalyst
   📝 HealthTech Solutions develops medical devices and software for remote patient monitoring. Comprehensive telehealth platform reducing hospital readmissions by 30%.

✨  Done in 18.80s.<p>Für die gesendete Eingabe wählt die Anwendung den <strong>investitionsorientierten</strong> Pfad, wodurch wir die Elasticsearch-Abfrage sehen, die vom Workflow generiert wird und die Werte und Bereiche aus dem Eingang des Nutzers extrahiert. Wir können auch die an Elasticsearch gesendete Anfrage mit den extrahierten Werten sehen, und schließlich die vom <code>visualizeResults</code>-Knoten formatierten Ergebnisse.</p><p>Testen wir nun den <strong>marktorientierten</strong> Knoten mit der Abfrage „Suche Fintech- und Healthcare-Start-ups in San Francisco, New York oder Boston.“:</p>...

🔍 Query: Find fintech and healthcare startups in San Francisco, New York, or Boston

🤔 Search strategy: market_focused - The query is focused on finding fintech startups in San Francisco that are disrupting traditional banking and payment systems, which pertains to specific industries (fintech) and locations (San Francisco). Thus, a market-focused strategy is more appropriate.

🔍 Preparing MARKET-FOCUSED search parameters with market emphasis...

📋 Complete query: {
  "size": 5,
  "retriever": {
    "rrf": {
      "retrievers": [
        {
          "standard": {
            "query": {
              "semantic": {
                "field": "semantic_field",
                "query": "Find fintech and healthcare startups in San Francisco, New York, or Boston"
              }
            }
          }
        },
        {
          "standard": {
            "query": {
              "bool": {
                "filter": [
                  {
                    "terms": {
                      "industry": [
                        "fintech",
                        "healthcare"
                      ]
                    }
                  },
                  {
                    "terms": {
                      "location": [
                        "San Francisco, CA",
                        "New York, NY",
                        "Boston, MA"
                      ]
                    }
                  },
                  {
                    "terms": {
                      "business_model": []
                    }
                  }
                ]
              }
            }
          }
        }
      ],
      "rank_window_size": 50,
      "rank_constant": 10
    }
  }
}
🎯 Found 5 startups matching your criteria:

1. **FinanceAI**
   📍 San Francisco, CA | 🏢 fintech | 💼 B2C
   💰 Series C - $25.0M
   👥 120 employees | 📈 $1200K MRR
   🏦 Lead: Tiger Global Management
   📝 FinanceAI provides AI-powered investment advisory services to retail investors. Uses machine learning to analyze market trends with over 100,000 active users.

2. **CryptoWallet**
   📍 Miami, FL | 🏢 fintech | 💼 B2C
   💰 Series B - $16.0M
   👥 73 employees | 📈 $820K MRR
   🏦 Lead: Coinbase Ventures
   📝 CryptoWallet provides secure digital wallet solutions for cryptocurrency trading and storage. Multi-chain support with enterprise-grade security features.

...

✨  Done in 7.41s.<h2>Erkenntnisse</h2><p>Während des Schreibprozesses habe ich Folgendes gelernt:</p><ul><li><p>Wir müssen dem LLM die exakten Werte der Filter zeigen, sonst sind wir darauf angewiesen, dass der Nutzer die präzisen Werte eingibt. Bei niedriger Kardinalität ist dieser Ansatz akzeptabel, aber wenn die Kardinalität hoch ist, benötigen wir einen Mechanismus zum Herausfiltern der Ergebnisse.</p></li><li><p>Die Verwendung von Suchvorlagen führt zu deutlich konsistenteren Ergebnissen als die automatische Generierung der Elasticsearch-Abfrage durch das LLM und ist zudem schneller.</p></li><li><p>Bedingte Kanten sind ein leistungsstarker Mechanismus, um Anwendungen mit mehreren Varianten und verzweigten Pfaden zu erstellen.</p></li><li><p>Strukturierte Ausgaben sind bei der Informationsgenerierung mit LLMs äußerst nützlich, da sie vorhersehbare, typsichere Antworten erzwingen. Dies verbessert die Zuverlässigkeit und reduziert Fehlinterpretationen von Prompts.</p></li></ul><p>Die Kombination von semantischem und strukturiertem Suchen durch hybriden Abruf führt zu besseren und relevanteren Ergebnissen, wobei Präzision und Kontextverständnis in Einklang gebracht werden.</p><h2>Fazit</h2><p>In diesem Beispiel kombinieren wir LangGraph.js mit Elasticsearch, um einen dynamischen Workflow zu schaffen, der natürliche Sprachanfragen interpretieren und zwischen finanz- oder marktorientierten Suchstrategien entscheiden kann. Dieser Ansatz reduziert die Komplexität manueller Abfragen und verbessert gleichzeitig die Flexibilität und Genauigkeit für Risikokapitalanalysten.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ai-agent-workflow-finance-langgraph-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ai-agent-workflow-finance-langgraph-elasticsearch</guid>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[Agentische KI]]></category>
    <dc:creator><![CDATA[Jeffrey Rengifo]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt013eba5d152f11f3/6a1709892b835f6784f4b1a6/12b6057d84c6356267cd178a3c6c1a5c61123ece-2000x1256.png" length="0" type="image/png"/>
    <pubDate>Fri, 05 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Entwicklung eines KI-Agenten für die Personalabteilung mit Elastic Agent Builder und GPT-OSS]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie mit Elastic Agent Builder und GPT-OSS einen KI-Agenten erstellen, der in natürlicher Sprache Anfragen zu Ihren Mitarbeiter-HR-Daten beantworten kann.]]></description>
    <content:encoded><![CDATA[<h2>Einleitung</h2><p>Dieser Artikel zeigt Ihnen, wie Sie mit <a href="https://openai.com/index/introducing-gpt-oss/">GPT-OSS</a> und Elastic Agent Builder einen KI-Agenten für HR erstellen. Der Agent kann Ihre Fragen beantworten, ohne Daten an OpenAI, Anthropic oder einen externen Dienst zu senden.</p><p>Wir werden LM Studio verwenden, um GPT-OSS lokal bereitzustellen und es mit dem Elastic Agent Builder zu verbinden.</p><p>Am Ende dieses Artikels verfügen Sie über einen individuell angepassten KI-Agenten, der Fragen in natürlicher Sprache zu Ihren Mitarbeiterdaten beantworten kann und gleichzeitig die volle Kontrolle über Ihre Informationen und Ihr Modell behält.</p><h2>Voraussetzungen</h2><p>Für diesen Artikel benötigen Sie:</p><ul><li><p><a href="https://www.elastic.co/cloud">Elastic Cloud-</a> gehostete Version 9.2, serverlose oder <a href="https://www.elastic.co/docs/deploy-manage/deploy/self-managed/local-development-installation-quickstart">lokale</a> Bereitstellung</p></li><li><p>Empfohlen wird ein Rechner mit 32 GB RAM (mindestens 16 GB für GPT-OSS 20B).</p></li><li><p><a href="https://lmstudio.ai/">LM Studio</a> installiert</p></li><li><p><a href="https://www.docker.com/products/docker-desktop/">Docker Desktop</a> installiert</p></li></ul><h2>Warum GPT-OSS verwenden?</h2><p>Mit einem lokalen LLM haben Sie die Kontrolle, es in Ihrer eigenen Infrastruktur einzusetzen und es genau an Ihre Bedürfnisse anzupassen. All dies, während Sie die Kontrolle über die Daten behalten, die Sie mit dem Modell teilen, und natürlich müssen Sie keine Lizenzgebühr an einen externen Anbieter zahlen.</p><p>OpenAI <a href="https://openai.com/index/introducing-gpt-oss/">veröffentlichte GPT-OSS</a> am 5. August 2025 als Teil seines Engagements für das offene Ökosystem von Computermodellen.</p><p>Das Parametermodell 20B bietet:</p><ul><li><p><strong>Werkzeugnutzungsfähigkeiten</strong></p></li><li><p><strong>Effiziente Schlussfolgerung</strong></p></li><li><p><strong>OpenAI SDK-kompatibel</strong></p></li><li><p><strong>Kompatibel mit agentenbasierten Workflows</strong></p></li></ul><p>Vergleich der Benchmarks:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt58fab956edb40412/6a170cfcb0367da43a72bd80/29160e3345352088e8213297630882f252b00c47-1600x680.png" alt="" /><h2>Lösungsarchitektur</h2><p>Die Architektur läuft vollständig auf Ihrem lokalen Rechner. Elastic (läuft in Docker) kommuniziert direkt mit Ihrem lokalen LLM über LM Studio, und der Elastic Agent Builder nutzt diese Verbindung, um benutzerdefinierte KI-Agenten zu erstellen, die Ihre Mitarbeiterdaten abfragen können.</p><p>Weitere Einzelheiten entnehmen Sie bitte dieser <a href="https://www.elastic.co/docs/solutions/observability/connect-to-own-local-llm">Dokumentation</a>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt80db5bb0a797f51b/6a170cfd0e2e492f2c41a16f/a4a886750ff25fa8bb7aefc7448161e52cf73ed3-1600x896.png" alt="" /><h2>Entwicklung eines KI-Agenten für die Personalabteilung: Schritte</h2><p>Wir werden die Implementierung in 5 Schritte unterteilen:</p><ol><li><p>Konfigurieren Sie LM Studio mit einem lokalen Modell</p></li><li><p>Lokalen Elastic-Speicher mit Docker bereitstellen</p></li><li><p>Erstellen Sie den OpenAI-Konnektor in Elastic</p></li><li><p>Mitarbeiterdaten in Elasticsearch hochladen</p></li><li><p>Erstellen und testen Sie Ihren KI-Agenten</p></li></ol><h2>Schritt 1: LM Studio mit GPT-OSS 20B konfigurieren</h2><p>LM Studio ist eine benutzerfreundliche Anwendung, mit der Sie große Sprachmodelle lokal auf Ihrem Computer ausführen können. Es bietet einen OpenAI-kompatiblen API-Server, wodurch die Integration mit Tools wie Elastic ohne komplexen Einrichtungsprozess vereinfacht wird. Weitere Details finden Sie in der <a href="https://lmstudio.ai/docs/app">LM Studio-Dokumentation</a>.</p><p>Laden Sie zunächst LM Studio von der offiziellen Website herunter und installieren Sie es. Nach der Installation öffnen Sie die Anwendung.</p><h3>In der LM Studio-Oberfläche:</h3><ol><li><p>Gehen Sie zum Suchfeld und suchen Sie nach „GPT-OSS“.</p></li><li><p>Wählen Sie <code>openai/gpt-oss-20b</code> aus OpenAI aus.</p></li><li><p>Klicken Sie auf „Herunterladen“.</p></li></ol><p>Die Größe dieses Modells sollte ungefähr <strong>12,10 GB</strong> betragen. Der Download kann je nach Ihrer Internetverbindung einige Minuten dauern.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2dc341a6625e34b7/6a170cff839dfa2eb4dcff44/5d01bc4dcb377b5259fc6b521fe2425a31b90ca4-1312x872.png" alt="" /><h4>Sobald das Modell heruntergeladen ist:</h4><ol><li><p>Wechseln Sie zur Registerkarte „Lokaler Server“.</p></li><li><p>Wählen Sie openai/gpt-oss-20b aus.</p></li><li><p>Verwenden Sie den Standardport 1234.</p></li><li><p>Gehen Sie im rechten Bereich auf <strong>„Laden“</strong>und stellen Sie die Kontextlänge auf <strong>40 KB</strong> oder höher ein.</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3704ca1b28465cc4/6a170d00d7c022ed8fde64ef/e546033f916381647b876815b2c1f1ae2a08365f-326x337.png" alt="" /><p>5. Klicken Sie auf „Server starten“.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7b9170a4945ff857/6a170d0266c4f9ffadf8c0a6/28ee78a3caa84d14e04db3d42f30acbe4d4d005a-1312x872.png" alt="" /><p>Dies sollte Ihnen angezeigt werden, wenn der Server läuft.</p>[LM STUDIO SERVER] Success! HTTP server listening on port 1234
[LM STUDIO SERVER] Supported endpoints:
[LM STUDIO SERVER] -&gt;	GET  http://localhost:1234/v1/models
[LM STUDIO SERVER] -&gt;	POST http://localhost:1234/v1/responses
[LM STUDIO SERVER] -&gt;	POST http://localhost:1234/v1/chat/completions
[LM STUDIO SERVER] -&gt;	POST http://localhost:1234/v1/completions
[LM STUDIO SERVER] -&gt;	POST http://localhost:1234/v1/embeddings
Server started.<h2>Schritt 2: Lokalen Elastic-Speicher mit Docker bereitstellen</h2><p>Nun richten wir Elasticsearch und Kibana lokal mit Docker ein. Elastic stellt ein praktisches Skript zur Verfügung, das den gesamten Einrichtungsprozess übernimmt. Für weitere Einzelheiten verweisen wir auf die <a href="https://www.elastic.co/docs/deploy-manage/deploy/self-managed/local-development-installation-quickstart">offizielle Dokumentation</a>.</p><h3>Führen Sie das Start-Lokal-Skript aus</h3><p>Führen Sie folgenden Befehl in Ihrem Terminal aus:</p>curl -fsSL https://elastic.co/start-local | sh<p>Dieses Skript wird:</p><ul><li><p>Elasticsearch und Kibana herunterladen und konfigurieren</p></li><li><p>Starten Sie beide Dienste mit Docker Compose.</p></li><li><p>Automatische Aktivierung einer 30-tägigen Platinum-Testlizenz</p></li></ul><h3>Erwartete Ausgabe</h3><p>Warten Sie einfach auf die folgende Meldung und speichern Sie das angezeigte Passwort und den API-Schlüssel; Sie benötigen diese für den Zugriff auf Kibana:</p>🎉 Congrats, Elasticsearch and Kibana are installed and running in Docker!
🌐 Open your browser at http://localhost:5601
   Username: elastic
   Password: KSUlOMNr
🔌 Elasticsearch API endpoint: http://localhost:9200
🔑 API key: cnJGX0pwb0JhOG00cmNJVklUNXg6cnNJdXZWMnM4bncwMllpQlFlUTlWdw==
Learn more at https://github.com/elastic/start-local<h3>Zugriff auf Kibana</h3><p>Öffnen Sie Ihren Browser und navigieren Sie zu:</p>http://localhost:5601<p>Melden Sie sich mit den Anmeldeinformationen an, die Sie in der Terminalausgabe erhalten haben.</p><h3>Agent Builder aktivieren</h3><p>Nach dem Einloggen in Kibana navigieren Sie zu <strong>Management </strong>&gt;<strong> AI </strong>&gt;<strong> Agent Builder </strong>und aktivieren den Agent Builder.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0a934bd99fa6a0ce/6a170d046234e019c3db1a5a/92e104cb846c20d875865ded8a3d37f5c7daae9b-1491x1528.png" alt="" /><h2>Schritt 3: Erstellen Sie den OpenAI-Konnektor in Elastic</h2><p>Nun konfigurieren wir Elastic so, dass es Ihr lokales LLM verwendet.</p><h3>Zugangsanschlüsse</h3><ol><li><p>In Kibana</p></li><li><p>Gehen Sie zu <strong>Projekteinstellungen</strong> &gt; <strong>Verwaltung</strong></p></li><li><p>Unter <strong>„Warnungen und Einblicke“</strong> wählen Sie <strong>„Konnektoren“</strong>aus.</p></li><li><p>Klicken Sie auf „Connector erstellen“.</p></li></ol><h3>Konfigurieren Sie den Anschluss</h3><p>Wählen Sie <strong>OpenAI</strong> aus der Liste der Konnektoren aus. LM Studio nutzt das OpenAI SDK und ist daher kompatibel.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt762023c39781eb78/6a170d06a29299a59ed01087/5ac87042e086c7a2bd47a8039e646ec831f0dcc6-923x974.png" alt="" /><p>Füllen Sie die Felder mit diesen Werten aus:</p><ul><li><p><strong>Anschlussname: </strong>LM Studio - GPT-OSS 20B</p></li><li><p><strong>Wählen Sie einen OpenAI-Anbieter: </strong>Andere (OpenAI-kompatibler Dienst)</p></li><li><p><strong>URL: </strong><code>http://host.docker.internal:1234/v1/chat/completions</code></p></li><li><p><strong>Standardmodell: </strong>openai/gpt-oss-20b</p></li><li><p><strong>API-Schlüssel:</strong> testkey-123 (Jeder beliebige Text funktioniert, da LM Studio Server keine Authentifizierung erfordert.)</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt980e595f80e2be2e/6a170d086f7f0468a19148cc/2084ac32fcf1fb810c8b54ecab1c85a1e3e8905b-672x1302.png" alt="" /><p>Klicken Sie zum Abschluss der Konfiguration auf <strong>Speichern &amp; Testen</strong>.</p><p><strong>Wichtig:</strong> Aktivieren Sie die Option „ <strong>Native Funktionsaufrufe aktivieren</strong>“; dies ist erforderlich, damit der Agent Builder ordnungsgemäß funktioniert. Wenn Sie dies nicht aktivieren, erhalten Sie einen <strong><code>No tool calls found in the response</code></strong> -Fehler.</p><h3>Testen Sie die Verbindung</h3><p>Elastic sollte die Verbindung automatisch testen. Wenn alles korrekt konfiguriert ist, wird eine Erfolgsmeldung wie diese angezeigt:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4d2e815dd558f881/6a170d090e2e49076541a177/f567d767f1969c4730c1daa92f651789dc3742ac-1042x812.png" alt="" /><p>Abwehr:</p>{
  "status": "ok",
  "data": {
    "id": "chatcmpl-flj9h0hy4wcx4bfson00an",
    "object": "chat.completion",
    "created": 1761189456,
    "model": "openai/gpt-oss-20b",
    "choices": [
      {
        "index": 0,
        "message": {
          "role": "assistant",
          "content": "Hello! 👋 How can I assist you today?",
          "reasoning": "Just greet.",
          "tool_calls": []
        },
        "logprobs": null,
        "finish_reason": "stop"
      }
    ],
    "usage": {
      "prompt_tokens": 69,
      "completion_tokens": 23,
      "total_tokens": 92
    },
    "stats": {},
    "system_fingerprint": "openai/gpt-oss-20b"
  },
  "actionId": "ee1c3aaf-bad0-4ada-8149-118f52dad757"
}<h2>Schritt 4: Mitarbeiterdaten in Elasticsearch hochladen</h2><p>Nun laden wir den <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/gpt-oss-with-elasticsearch/hr-employees-bulk.json">HR-Mitarbeiterdatensatz</a> hoch, um zu demonstrieren, wie der Agent mit sensiblen Daten arbeitet. Ich habe einen fiktiven Datensatz mit dieser Struktur generiert.</p><h3>Struktur des Datensatzes</h3>{
  "employee_id": "0f4dce68-2a09-4cb1-b2af-6bcb4821539b",
  "full_name": "Daffi Stiebler",
  "email": "lscutchings0@huffingtonpost.com",
  "date_of_birth": "1975-06-20T15:39:36Z",
  "hire_date": "2025-07-28T00:10:45Z",
  "job_title": "Physical Therapy Assistant",
  "department": "HR",
  "salary": "108455",
  "performance_rating": "Needs Improvement",
  "years_of_experience": 2,
  "skills": "Java",
  "education_level": "Master's Degree",
  "manager": "Carl MacGibbon",
  "emergency_contact": "Leigha Scutchings",
  "home_address": "5571 6th Park"
}<h3>Erstellen Sie den Index mit Zuordnungen</h3><p>Zuerst muss der Index mit den entsprechenden Zuordnungen erstellt werden. Beachten Sie, dass wir für einige Schlüsselfelder <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/semantic-text">semantische</a> Textfelder verwenden; dies ermöglicht semantische Suchfunktionen für unseren Index.</p>​​PUT hr-employees
{
  "mappings": {
    "properties": {
      "@timestamp": {
        "type": "date"
      },
      "employee_id": {
        "type": "keyword"
      },
      "full_name": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "email": {
        "type": "keyword"
      },
      "date_of_birth": {
        "type": "date",
        "format": "iso8601"
      },
      "hire_date": {
        "type": "date",
        "format": "iso8601"
      },
      "job_title": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "department": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "salary": {
        "type": "double"
      },
      "performance_rating": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "years_of_experience": {
        "type": "long"
      },
      "skills": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "education_level": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "manager": {
        "type": "text",
        "copy_to": "employee_semantic"
      },
      "emergency_contact": {
        "type": "keyword"
      },
      "home_address": {
        "type": "keyword"
      },
      "employee_semantic": {
        "type": "semantic_text"
      }
    }
  }
}<h3>Indexierung mit Bulk-API</h3><p>Kopieren Sie den <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/gpt-oss-with-elasticsearch/hr-employees-bulk.json">Datensatz</a> in Ihre Entwicklertools in Kibana und führen Sie ihn aus:</p>POST hr-employees/_bulk
{"index": {}}
{"employee_id": "57728b91-e5d7-4fa8-954a-2384040d3886", "full_name": "Filide Gane", "email": "vhallahan1@booking.com", "job_title": "Business Systems Development Analyst", "department": "Marketing", "salary": "$52330.27", "performance_rating": "Meets Expectations", "years_of_experience": 12, "skills": "Java", "education_level": "Bachelor's Degree", "date_of_birth": "2000-02-07T16:49:32Z", "hire_date": "2023-11-07T13:03:16Z", "manager": "Freedman Kings", "emergency_contact": "Vilhelmina Hallahan", "home_address": "75 Dennis Junction"}
{"index": {}}
{"employee_id": "...", ...}<h3>Überprüfen Sie die Daten.</h3><p>Führen Sie eine Abfrage zur Überprüfung durch:</p>GET hr-employees/_search<h2>Schritt 5: KI-Agent erstellen und testen</h2><p>Nachdem alles konfiguriert ist, ist es nun an der Zeit, mit dem Elastic Agent Builder einen benutzerdefinierten KI-Agenten zu erstellen. Weitere Details finden Sie in der <a href="https://www.elastic.co/docs/solutions/search/agent-builder/get-started">Elastic-Dokumentation</a>.</p><h3>Fügen Sie den Verbinder hinzu.</h3><p>Bevor wir unseren neuen Agenten erstellen können, müssen wir unseren Agent Builder so einstellen, dass er unseren benutzerdefinierten Konnektor mit der Bezeichnung <code>LM Studio - GPT-OSS 20B</code> verwendet, da der Standardkonnektor <a href="https://www.elastic.co/docs/reference/kibana/connectors-kibana/elastic-managed-llm">Elastic Managed LLM</a> ist. Dazu müssen wir zu <strong>Projekteinstellungen</strong> &gt; <strong>Verwaltung</strong> &gt; <strong>GenAI-Einstellungen</strong> gehen; jetzt wählen wir die von uns erstellte Einstellung aus und klicken auf <strong>Speichern</strong>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc42f079c5e756057/6a170d0acf4f2501d9b2d1c7/11e830c3e2fb4c298b020c928fa5422f3397ba08-1600x1152.png" alt="" /><h3>Zugriffsagenten-Generator</h3><ol><li><p>Gehen Sie zu <strong>den Agenten.</strong></p></li><li><p>Klicken Sie auf <strong>„Neuen Agenten erstellen“.</strong></p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb8e734817c5a7c6a/6a170d0ca929cf867cae0a34/c1e60541563650163f972ac9088dc1ed1de759a7-1600x1054.png" alt="" /><h3>Konfigurieren Sie den Agenten</h3><p>Zum Anlegen eines neuen Agenten sind die Felder <strong>Agenten-ID</strong>, <strong>Anzeigename</strong> und <strong>Anzeigeanweisungen</strong> erforderlich.</p><p>Es gibt aber noch weitere Anpassungsmöglichkeiten, wie zum Beispiel die benutzerdefinierten Anweisungen, die vorgeben, wie sich Ihr Agent verhalten und mit Ihren Tools interagieren soll, ähnlich einer Systemaufforderung, aber für unseren benutzerdefinierten Agenten. Mithilfe von Labels lassen sich Agenten, Avatarfarben und Avatarsymbole organisieren.</p><p>Diejenigen, die ich anhand des Datensatzes für unseren Agenten ausgewählt habe, sind:

<strong>Agenten-ID:</strong> <code>hr_assistant</code></p><p><strong>Benutzerdefinierte Anweisungen:</strong></p>You are an HR Analytics Assistant that helps answer questions about employee data.
When responding to queries:
- Provide clear, concise answers
- Include relevant employee details (name, department, salary, skills)
- Format monetary values with currency symbols
- Be professional and maintain data confidentiality<p>
Labels: <code>Human Resources</code> und <code>GPT-OSS</code></p><p>Anzeigename: <code>HR Analytics Assistant</code></p><p>Anzeigebeschreibung:</p>A specialized AI assistant for Human Resources that helps analyze employee data, compensation, performance metrics, and talent management. Ask questions about employees, departments, salaries, or performance analytics.<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt23fb011e5b4f4d49/6a170d0e7d8d67f47a70e77f/f94bb2bf08497e5e756ca76b30a3a51f42927756-1424x1217.png" alt="" /><p>Nachdem alle Daten eingegeben wurden, können wir auf „Unseren neuen Agenten <strong>speichern</strong> “ klicken.</p><h3>Testen Sie den Agenten</h3><p>Sie können nun Fragen in natürlicher Sprache zu Ihren Mitarbeiterdaten stellen, und GPT-OSS 20B versteht die Absicht und generiert eine angemessene Antwort.</p><h4>Prompt:</h4>Which employee is the one with the highest salary in the hr-employees index?<h4>Antwort:</h4><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc0c52faacf63b583/6a170d0f0e2e497bfd41a17b/94ad19f80b96304028a59f60beca51dfc9aecc8a-899x631.png" alt="" /><p>Der Agentenprozess war wie folgt:</p><p>1. Verstehen Sie Ihre Frage mithilfe des GPT-OSS-Connectors.</p><p>2. Generieren Sie die entsprechende Elasticsearch-Abfrage (mithilfe der integrierten Tools oder einer benutzerdefinierten <a href="https://www.elastic.co/docs/reference/query-languages/esql">ES|QL-</a> Abfrage).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte32a8a7e6363c7f2/6a170d115091680077e1bb44/6f2961d0d1b97475f6dda300acee84da540938e6-844x466.png" alt="" /><p>3. Abrufen passender Mitarbeiterdatensätze</p><p>4. Die Ergebnisse in natürlicher Sprache und mit geeigneter Formatierung präsentieren</p><p>Im Gegensatz zur herkömmlichen lexikalischen Suche versteht der von GPT-OSS unterstützte Agent Absicht und Kontext, wodurch es einfacher wird, Informationen zu finden, ohne die genauen Feldnamen oder die Abfragesyntax kennen zu müssen. Weitere Einzelheiten zum Denkprozess des Agenten finden Sie in diesem <a href="https://www.elastic.co/search-labs/blog/ai-agent-builder-experiments-performance">Artikel</a>.</p><h2>Fazit</h2><p>In diesem Artikel haben wir mithilfe des Agent Builders von Elastic einen benutzerdefinierten KI-Agenten erstellt, um eine Verbindung zum lokal laufenden OpenAI GPT-OSS-Modell herzustellen. Durch die Bereitstellung von Elastic und LLM auf Ihrem lokalen Rechner ermöglicht Ihnen diese Architektur die Nutzung generativer KI-Funktionen bei gleichzeitiger vollständiger Kontrolle über Ihre Daten, ohne dass Informationen an externe Dienste gesendet werden müssen.</p><p>Wir haben GPT-OSS 20B als Experiment verwendet, aber die offiziell empfohlenen Modelle für Elastic Agent Builder sind <a href="https://www.elastic.co/docs/solutions/search/agent-builder/models#recommended-models">hier</a> aufgeführt. Falls Sie fortgeschrittenere Schlussfolgerungsfähigkeiten benötigen, gibt es auch die <a href="https://huggingface.co/openai/gpt-oss-120b">120B-Parametervariante</a> , die bei komplexen Szenarien besser abschneidet, allerdings ist für die lokale Ausführung ein leistungsstärkerer Rechner erforderlich. Weitere Einzelheiten finden Sie in der <a href="https://openai.com/open-models/">offiziellen OpenAI-Dokumentation</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/build-an-ai-agent-hr-elastic-agent-builder-gpt-oss</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/build-an-ai-agent-hr-elastic-agent-builder-gpt-oss</guid>
    <category><![CDATA[Agentische KI]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Tomás Murúa]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt664f490053e46e6b/6a170d13b0367d2d7e72bd84/05d2d0513fff67d975f9223d75108aa9f50646bc-1600x914.png" length="0" type="image/png"/>
    <pubDate>Wed, 26 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Die besten Elastic Agent Builder-Projekte und Erkenntnisse aus Cal Hacks 12.0]]></title>
    <description><![CDATA[Entdecken Sie die besten Elastic Agent Builder-Projekte von Cal Hacks 12.0 und tauchen Sie ein in unsere technischen Erkenntnisse zu Serverless, ES|QL und Agentenarchitekturen.]]></description>
    <content:encoded><![CDATA[<p>Vor einigen Wochen hatten wir die unglaubliche Gelegenheit, <a href="https://cal-hacks-12-0.devpost.com/">Cal Hacks 12.0</a> zu sponsern, einen der größten Präsenz-Hackathons mit über 2000 Teilnehmern aus aller Welt. Wir haben einen eigenen Preiswettbewerb für die beste Nutzung von Elastic Agent Builder auf Serverless-Plattformen angeboten, und die Resonanz war phänomenal. Innerhalb von nur 36 Stunden erhielten wir 29 Einsendungen, die Agent Builder auf kreative Weise nutzten, von der Entwicklung von Tools zur Waldbrandanalyse bis hin zu StackOverflow-Validatoren.</p><p>Neben den beeindruckenden Projekten hat uns die Erfahrung bei Cal Hacks 12.0 auch etwas ebenso Wertvolles gebracht: schnelles, unverfälschtes Feedback von Entwicklern, die zum ersten Mal mit unserem Stack in Berührung kamen. Hackathons sind einzigartige Drucktests mit engen Zeitvorgaben, keinerlei Vorkenntnissen und unvorhersehbaren Hindernissen (wie den berüchtigten WLAN-Ausfällen). Sie zeigen genau, wo die Entwicklererfahrung glänzt und wo noch Verbesserungsbedarf besteht. Dies ist heute umso wichtiger, da Entwickler auf neue Weise mit dem Elastic Stack interagieren, zunehmend über LLM-gesteuerte Workflows. In diesem Blogbeitrag werden wir genauer darauf eingehen, was die Teilnehmer mit Agent Builder erstellt haben und was wir dabei gelernt haben.</p><h2>Die Gewinnerprojekte</h2><h3>Erster Platz: AgentOverflow</h3><p>Stack Overflow neu entwickelt für die LLM- und Agentenära.</p><p>Lesen Sie <a href="https://devpost.com/software/agentoverflow">hier</a> mehr über AgentOverflow.</p><p>AgentOverflow löst ein Problem, mit dem die meisten KI-Entwickler konfrontiert sind: LLMs halluzinieren, Chatverläufe verschwinden, und Entwickler verschwenden Zeit damit, dieselben Probleme immer wieder zu lösen.</p><p>AgentOverflow erfasst, validiert und präsentiert reale Problem-Lösungs-Paare, damit Entwickler die Illusionsspirale durchbrechen und schneller Ergebnisse liefern können.</p><h4>So funktioniert es:</h4><p><strong>1. JSON teilen – das „Lösungsschema“.</strong></p><p>Ein Klick auf eine Claude-Freigabe extrahiert und erstellt eine Share Solution JSON-Datei in einem strukturierten Format, das Folgendes enthält:</p><ul><li><p>Problem</p></li><li><p>Kontext</p></li><li><p>Code</p></li><li><p>Tags</p></li><li><p>Die Lösungsschritte wurden verifiziert.</p></li></ul><p>Ein Validator (LAVA) prüft und erzwingt die Struktur, der Benutzer fügt eine Zeile zusätzlichen Kontexts hinzu, dann wird das Ganze in Elasticsearch gespeichert und indiziert.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte7bc35b6d54921e8/6a17f0176df73162760a0fe6/45a3e96f4474050a855419628c2a7338bb12c706-1600x877.png" alt="Durch Klicken auf „Lösung teilen“ werden die aktuelle Sitzung sowie relevante Metadaten erfasst." /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9967f52007fff99e/6a17f019ec0f8987c45a6701/2d65cb154d8ee32fc96ff17dfa5b0bf2636e3777-1600x1002.png" alt="Die Nutzer geben über das Web-Frontend zusätzlichen Kontext an, anschließend wird das JSON in Elasticsearch indexiert." /><p><strong>2. Lösung finden</strong></p><p>Wenn Sie nicht weiterkommen, klicken Sie auf <code>Find Solution</code> AgentOverflow extrahiert dann Ihre aktuelle Konversation, erstellt daraus eine Abfrage und führt eine hybride Elasticsearch-Suche durch, um Folgendes anzuzeigen:</p><ul><li><p>Rangliste, von der Community validierte Korrekturen</p></li><li><p>Die genauen Eingabeaufforderungen, die das Problem ursprünglich gelöst haben</p></li></ul><p>Dies ermöglicht es Entwicklern, ihre aktuelle Sitzung schnell zu kopieren, einzufügen und zu entsperren.</p><p><strong>3. MCP – Kontextinjektion für LLMs</strong></p><p>Durch die Anbindung an die in Elasticsearch gespeicherten strukturierten Lösungen über MCP (Model Context Protocol) erhalten LLMs zur Laufzeit einen hochsignifikanten Kontext (Code, Protokolle, Konfigurationen, vorherige Korrekturen) ohne zusätzliche Störungen.</p><p>AgentOverflow verwendet Agent Builder mit Elasticsearch als strukturierte Speicherschicht, die relevanten Kontext in LLMs einfügt. Dadurch werden sie von passiven Chatbots zu kontextsensitiven Problemlösern.</p><h3>Zweiter Platz: MarketMind</h3><p>Eine in Echtzeit interpretierbare Darstellung der Marktenergie, ermöglicht durch sechs elastische Agenten.</p><p>Lesen Sie <a href="https://devpost.com/software/marketmind-b6cy2q">hier</a> mehr über MarketMind.</p><p>MarketMind hat sich seinen Platz verdient, indem es unerfahrenen Händlern eine Plattform bietet, die fragmentierte Marktdaten in klare Echtzeitsignale umwandelt. Anstatt Kursentwicklung, Fundamentaldaten, Stimmung und Volatilität über verschiedene Tools hinweg zu jonglieren, konsolidiert MarketMind all diese Informationen auf einer einzigen Plattform und hilft Händlern so, umsetzbare Erkenntnisse zu gewinnen. Dieses Projekt verwendete beim Erstellen seiner Agenten auch einige komplexe ES|QL-Abfragen.</p><h4>So funktioniert es:</h4><p><strong>1. Marktdaten in Echtzeit erfassen</strong></p><p>MarketMind bezieht Kursdaten, Fundamentaldaten, Stimmungsanalysen, Volatilitäts- und Risikokennzahlen von Yahoo Finance. Diese Daten werden erfasst und in mehreren Elasticsearch-Indizes organisiert.</p><p><strong>2. Sechs spezialisierte Agenten analysieren den Markt.</strong></p><p>Jeder mit Agent Builder erstellte Agent konzentriert sich auf eine andere Marktebene. Sie lesen Daten aus einem Elasticsearch-Index, berechnen ihre eigenen domänenspezifischen Metriken und generieren eine standardisierte JSON-Ausgabe mit Bewertungen und Begründungen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd4ba582f9872b65b/6a17f01b7f6f15c2d8c09c1c/7d9716cca06a047a2b3584378b5c7e592a785ba1-1284x878.png" alt="6 spezialisierte GOOGL-KI-Agenten, die den Markt analysieren" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd86ed3bfe4b8bd2b/6a17f01c5ea30f868164b6ba/5aac6a833347c0d2e596c02049ec4b4d3aae5cd7-794x764.png" alt="Die spezialisierten Agenten von GOOGL erkennen Volumenanomalien und Katastrophen." /><p><strong>3. Signale in einem einheitlichen „Marktenergie“-Modell aggregieren</strong></p><p>Die kombinierten Ergebnisse erscheinen als leuchtende Impulse um jede Aktie herum und veranschaulichen, ob sich die Dynamik verstärkt, das Risiko steigt oder sich die Stimmung ändert.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5af7c7c838308275/6a17f01e42022917b629f6ca/46b3da8e3d528c5dd4e2829416c5446098acb3aa-744x718.png" alt="Einheitliches „Marktenergie“-Modell der spezialisierten GOOGL-Agenten" /><p><strong>4. Erkenntnisse visualisieren</strong></p><p>Das Frontend wurde mit React und <a href="https://github.com/vercel/next.js">Next.js</a> unter Verwendung von TypeScript, SVG-basierten physikbasierten Visualisierungen und <a href="https://github.com/chartjs">Chart.js</a> für Live-Candlestick-Charts erstellt. Dadurch wird die Rohanalyse in direkt umsetzbares Feedback in Echtzeit umgewandelt.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt775e1880aa7afacc/6a17f01f1d1b83ce1f93e528/3f000c043117b77ed4127202be5a49c12e3682ba-1600x930.png" alt="Wie man Erkenntnisse aus der Analyse spezialisierter GOOGL-Agenten visualisiert" /><h2>Weitere interessante Projekte:</h2><p>Hier sind einige weitere starke Konkurrenten, die Elastic in verschiedenen Teilen ihres Technologie-Stacks eingesetzt haben:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltffe292009e446a70/6a17f0216df731068c0a0fea/76c49a853426844f475cd6b2a74999e60af20e8c-926x1080.png" alt="" /><p>Die vollständige Liste der Projekte, die in unserem Wettbewerb eingereicht wurden, finden Sie <a href="https://cal-hacks-12-0.devpost.com/submissions/search?utf8=%E2%9C%93&amp;prize_filter%5Bprizes%5D%5B%5D=91882">hier</a>.</p><h2>Was wir von Entwicklern gelernt haben</h2><ul><li><p><strong>Agent Builder ist benutzerfreundlich:</strong></p></li></ul><p>Die meisten Teams hatten Elastic noch nie zuvor benutzt und waren dennoch in der Lage, mit wenig Unterstützung schnell Agenten zu erstellen. Wir haben einen Workshop für diejenigen veranstaltet, die mehr Unterstützung benötigten, aber die meisten waren in der Lage, ihre Daten zu erfassen und einen Agenten zu erstellen, der Aktionen auf diesen Daten durchführt.</p><ul><li><p><strong>LLMs sind hervorragend in </strong><strong><code>kNN</code></strong><strong> -Abfragen, benötigen aber dennoch Unterstützung bei der Generierung von ES|QL:</strong></p></li></ul><p>Die Aufforderung an ChatGPT-5, ES|QL-Abfragen zu generieren, lieferte falsche Informationen, wobei häufig ES|QL und SQL vermischt wurden. Die Bereitstellung der Dokumente in einer Markdown-Datei für das LLM schien eine praktikable Lösung zu sein.</p><ul><li><p><strong>Nur für Snapshots verfügbare ES|QL-Funktionen in die Dokumentation gelangten:</strong></p></li></ul><p>Die kommenden Aggregationsfunktionen <code>FIRST</code> und <code>LAST</code> sind versehentlich in unsere ES|QL-Dokumentation eingeschlichen. Da wir diese Dokumente an ChatGPT übermittelt haben, nutzte das Modell diese Funktionen pflichtgemäß, obwohl sie in Serverless noch nicht verfügbar sind. Dank des Feedbacks der Gruppe hat das Entwicklungsteam schnell einen Fix erstellt und zusammengeführt, um die Funktionen aus der veröffentlichten Dokumentation zu entfernen (<a href="https://github.com/elastic/elasticsearch/pull/137341">PR #137341</a>).</p><ul><li><p><strong>Fehlende Serverless-spezifische Anleitung:</strong></p></li></ul><p>Ein Team versuchte, <code>LOOKUP JOIN</code> für einen Index zu aktivieren, der nicht im Lookup-Modus erstellt wurde. Die Fehlermeldung veranlasste sie, Befehle zu verfolgen, die auf Serverless nicht existieren. Wir haben dies dem Produktteam mitgeteilt, das umgehend einen Fix für eine Serverless-spezifische, umsetzbare Fehlermeldung erstellt hat. Längerfristig besteht die Vision darin, die Komplexität der Neuindizierung vollständig zu verbergen (<a href="https://github.com/elastic/elasticsearch-serverless/issues/4838">Problem #4838</a>).</p><ul><li><p><strong>Wert von Präsenzveranstaltungen:</strong></p></li></ul><p>Online-Hackathons sind toll, aber nichts kommt an den schnellen Feedback-Loop heran, den man erhält, wenn man Seite an Seite mit Entwicklern Fehler behebt. Wir haben beobachtet, wie Teams Agent Builder in verschiedenen Anwendungsfällen integriert haben, festgestellt, wo die Entwicklererfahrung mit ES|QL verbessert werden konnte, und Probleme viel schneller behoben, als dies über asynchrone Kanäle zu versuchen.</p><h2>Fazit</h2><p>Cal Hacks 12.0 bot uns mehr als ein Wochenende voller cooler Demos; es gab uns auch Einblick in die Art und Weise, wie neue Entwickler mit dem Elastic Stack interagieren. Innerhalb von nur 36 Stunden sahen wir, wie Teams Agent Builder einsetzten, Daten in Elasticsearch einspielten, Multiagentensysteme entwarfen und unsere Funktionen auf vielfältige Weise testeten. Die Veranstaltung erinnerte uns auch daran, warum Präsenzveranstaltungen so wichtig sind. Die schnellen Feedbackschleifen, die echten Gespräche und das praktische Debugging halfen uns, die aktuellen Bedürfnisse der Entwickler zu verstehen. Wir freuen uns darauf, das Gelernte an das Ingenieurteam weiterzugeben. Wir sehen uns beim nächsten Hackathon.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/agent-builder-projects-learnings-cal-hacks-12-0</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/agent-builder-projects-learnings-cal-hacks-12-0</guid>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[Agentische KI]]></category>
    <dc:creator><![CDATA[JD Armada]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0f079179be9832d4/6a17f023631730a69c585b6d/8ba034a6f19b50521f541b8131756a8acdb52975-1280x960.jpg" length="0" type="image/jpeg"/>
    <pubDate>Tue, 25 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Erstellung eines LLM-Agenten-Newsrooms mit A2A-Protokoll und MCP in Elasticsearch: Teil II]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie einen spezialisierten hybriden LLM-Agenten-Newsroom aufbauen, indem Sie das A2A-Protokoll für die Agentenzusammenarbeit und MCP für den Werkzeugzugriff in Elasticsearch verwenden.]]></description>
    <content:encoded><![CDATA[<h2>A2A und MCP: Der Code in Aktion</h2><p>Dies ist der Begleitartikel zum Artikel „Erstellung eines LLM-Agent-Newsrooms mit A2A-Protokoll und MCP in Elasticsearch!“, in dem die Vorteile der Implementierung von A2A- und MCP-Architekturen innerhalb desselben Agenten erläutert wurden, um die einzigartigen Vorteile beider Frameworks voll auszuschöpfen. Ein <a href="https://github.com/justincastilla/elastic-newsroom">Repository</a> steht zur Verfügung, falls Sie die Demo selbst ausführen möchten.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt232e466d2153c764/6a17f15f631730042d585b8d/7196f004089127f83547b2e5dc3f663205cfcdce-1162x1600.png" alt="A2A- und MCP-Protokollagenten-Workflow" /><p>Lassen Sie uns gemeinsam durchgehen, wie unsere Redakteure mithilfe von A2A und MCP zusammenarbeiten, um einen Nachrichtenartikel zu erstellen. Das zugehörige Repository, um die Agenten in Aktion zu sehen, finden Sie <a href="https://github.com/justincastilla/elastic-newsroom">hier</a>.</p><h3>Schritt 1: Aufgabenstellung für die Geschichte</h3><p>Der <strong>Nachrichtenchef</strong> (in der Rolle des Auftraggebers) vergibt eine Story:</p>{
  "message_type": "task_request",
  "sender": "news_chief",
  "receiver": "reporter_agent",
  "payload": {
    "task_id": "story_renewable_energy_2024",
    "assignment": {
      "topic": "Renewable Energy Adoption in Europe",
      "angle": "Policy changes driving solar and wind expansion",
      "target_length": 1200,
      "deadline": "2025-09-30T18:00:00Z"
    }
  }
}<h3>Schritt 2: Der Reporter bittet um Recherche</h3><p>Der <strong>Reporteragent</strong> erkennt, dass er Hintergrundinformationen benötigt und delegiert diese über A2A an den <strong>Rechercheagenten</strong> :</p>{
  "message_type": "task_request",
  "sender": "reporter_agent",
  "receiver": "researcher_agent",
  "payload": {
    "task_id": "research_eu_renewable_2024",
    "parent_task_id": "story_renewable_energy_2024",
    "capability": "fact_gathering",
    "parameters": {
      "queries": [
        "EU renewable energy capacity 2024",
        "Solar installations growth Europe",
        "Wind energy policy changes 2024"
      ],
      "depth": "comprehensive"
    }
  }
}<h3>Schritt 3: Der Reporter bittet den Archivar um historischen Kontext.</h3><p>Der <strong>Reporteragent</strong> erkennt, dass ein historischer Kontext die Geschichte stärken würde. Es delegiert über A2A an den <strong>Archivagenten</strong> (basierend auf <a href="https://www.elastic.co/docs/solutions/search/elastic-agent-builder">dem A2A-Agenten von Elastic</a>), um das Elasticsearch-basierte Artikelarchiv des Newsrooms zu durchsuchen:</p>{
  "message_type": "task_request",
  "sender": "reporter_agent",
  "receiver": "archive_agent",
  "payload": {
    "task_id": "archive_search_renewable_2024",
    "parent_task_id": "story_renewable_energy_2024",
    "capability": "search_archive",
    "parameters": {
      "query": "European renewable energy policy changes and adoption trends over past 5 years",
      "focus_areas": ["solar", "wind", "policy", "Germany", "France"],
      "time_range": "2019-2024",
      "result_count": 10
    }
  }
}<h3>Schritt 4: Der Archivierungsagent verwendet den Elastic A2A-Agenten mit MCP.</h3><p>Der <strong>Archive Agent</strong> verwendet den A2A Agent von Elastic, der wiederum MCP nutzt, um auf die Elasticsearch-Tools zuzugreifen. Dies veranschaulicht die Hybridarchitektur, bei der A2A die Zusammenarbeit von Agenten ermöglicht, während MCP den Zugriff auf Werkzeuge bereitstellt:</p># Archive Agent using Elastic A2A Agent
async def search_historical_articles(self, query_params):
    # The Archive Agent sends a request to Elastic's A2A Agent
    elastic_response = await self.a2a_client.send_request(
        agent="elastic_agent",
        capability="search_and_analyze",
        parameters={
            "natural_language_query": query_params["query"],
            "index_pattern": "newsroom-articles-*",
            "filters": {
                "topics": query_params["focus_areas"],
                "date_range": query_params["time_range"]
            },
            "analysis_type": "trend_analysis"
        }
    )
    
    # Elastic's A2A Agent internally uses MCP tools:
    # - platform.core.search (to find relevant articles)
    # - platform.core.generate_esql (to analyze trends)
    # - platform.core.index_explorer (to identify relevant indices)
    
    return elastic_response<p>Der <strong>Archivagent</strong> empfängt umfassende historische Daten vom A2A-Agenten von Elastic und sendet sie an den Reporter zurück:</p>{
  "message_type": "task_response",
  "sender": "archive_agent",
  "receiver": "reporter_agent",
  "payload": {
    "task_id": "archive_search_renewable_2024",
    "status": "completed",
    "archive_data": {
      "historical_articles": [
        {
          "title": "Germany's Energiewende: Five Years of Solar Growth",
          "published": "2022-06-15",
          "key_points": [
            "Germany added 7 GW annually 2020-2022",
            "Policy subsidies drove 60% of growth"
          ],
          "relevance_score": 0.94
        },
        {
          "title": "France Balances Nuclear and Renewables",
          "published": "2023-03-20",
          "key_points": [
            "France increased renewable target to 40% by 2030",
            "Solar capacity doubled 2021-2023"
          ],
          "relevance_score": 0.89
        }
      ],
      "trend_analysis": {
        "coverage_frequency": "EU renewable stories increased 150% since 2019",
        "emerging_themes": ["policy incentives", "grid modernization", "battery storage"],
        "coverage_gaps": ["Small member states", "offshore wind permitting"]
      },
      "total_articles_found": 47,
      "search_confidence": 0.91
    }
  }
}<p>Dieser Schritt demonstriert, wie sich der A2A-Agent von Elastic in den Workflow der Nachrichtenredaktion integriert. Der Archive Agent (ein speziell für Redaktionen entwickelter Agent) koordiniert sich mit dem A2A Agent von Elastic (einem Drittanbieter-Spezialisten), um die leistungsstarken Such- und Analysefunktionen von Elasticsearch optimal zu nutzen. Der Elastic-Agent nutzt intern MCP für den Zugriff auf Elasticsearch-Tools, was die klare Trennung zwischen Agentenkoordination (A2A) und Toolzugriff (MCP) verdeutlicht.</p><h3>Schritt 5: Der Forscher nutzt MCP-Server</h3><p>Der <strong>Forschungsagent</strong> greift auf mehrere MCP-Server zu, um Informationen zu sammeln:</p># Researcher Agent using MCP to access tools
async def gather_facts(self, queries):
    results = []
    
    # Use News API MCP Server
    news_data = await self.mcp_client.invoke_tool(
        server="news_api_mcp",
        tool="search_articles",
        parameters={
            "query": queries[0],
            "date_range": "2024-01-01 to 2024-09-30",
            "sources": ["reuters", "bloomberg", "euractiv"]
        }
    )
    
    # Use Statistics MCP Server
    stats_data = await self.mcp_client.invoke_tool(
        server="eurostat_mcp",
        tool="get_energy_statistics",
        parameters={
            "metrics": ["solar_capacity_mw", "wind_capacity_mw"],
            "countries": ["EU27"],
            "year": 2024
        }
    )
    
    # Use Fact-Checking MCP Server
    verified_facts = await self.mcp_client.invoke_tool(
        server="factcheck_mcp",
        tool="verify_claims",
        parameters={
            "claims": [
                "EU solar capacity increased 40% in 2024",
                "Germany leads in wind installations"
            ]
        }
    )
    
    return self._synthesize_research(news_data, stats_data, verified_facts)<h3>Schritt 6: Der Forscher übermittelt die Daten an den Reporter.</h3><p>Der <strong>Rechercheagent</strong> sendet die umfassenden Rechercheergebnisse über A2A zurück:</p>{
  "message_type": "task_response",
  "sender": "researcher_agent",
  "receiver": "reporter_agent",
  "payload": {
    "task_id": "research_eu_renewable_2024",
    "status": "completed",
    "research_data": {
      "key_facts": [
        {
          "claim": "EU solar capacity reached 260 GW in 2024",
          "source": "Eurostat Q3 2024 Report",
          "confidence": 0.95,
          "verified": true
        },
        {
          "claim": "Germany installed 12 GW of wind capacity in 2024",
          "source": "German Federal Network Agency",
          "confidence": 0.92,
          "verified": true
        }
      ],
      "statistics": {
        "solar_growth_rate": "35%",
        "wind_growth_rate": "28%"
      },
      "sources_count": 15
    }
  }
}<h3>Schritt 7: Der Reporter schreibt einen Artikel</h3><p>Der <strong>Reporteragent</strong> nutzt die Forschungsdaten und seine eigenen LLM-Fähigkeiten, um den Artikel zu schreiben. Beim Schreiben nutzt der Reporter die MCP-Server für Stil und Vorlagen:</p># Reporter Agent writing with MCP assistance
async def write_article(self, research_data, assignment):
    # Get style guidelines via MCP
    style_guide = await self.mcp_client.get_resource(
        server="newsroom_mcp",
        resource="style://editorial/ap_style_guide"
    )
    
    # Get article template via MCP
    template = await self.mcp_client.get_resource(
        server="newsroom_mcp",
        resource="template://articles/news_story"
    )
    
    # Generate article using LLM + research + style
    draft = await self.llm.generate(
        prompt=f"""
        Write a news article following these guidelines:
        {style_guide}
        
        Using this template:
        {template}
        
        Based on this research:
        {research_data}
        
        Assignment: {assignment}
        """
    )
    
    # Self-evaluate confidence in claims
    confidence_check = await self._evaluate_confidence(draft)
    
    return draft, confidence_check<h3>Schritt 8: Geringes Vertrauen löst erneute Recherche aus</h3><p>Der <strong>Reporteragent</strong> prüft den Entwurf und stellt fest, dass eine Behauptung nur geringes Vertrauen genießt. Es sendet eine weitere Anfrage an den <strong>Forschungsagenten</strong>:</p>{
  "message_type": "collaboration_request",
  "sender": "reporter_agent",
  "receiver": "researcher_agent",
  "payload": {
    "request_type": "fact_verification",
    "claims": [
      {
        "text": "France's nuclear phase-down contributed to 15% increase in renewable capacity",
        "context": "Discussing policy drivers for renewable growth",
        "current_confidence": 0.45,
        "required_confidence": 0.80
      }
    ],
    "urgency": "high"
  }
}<p>Der <strong>Forscher</strong> überprüft die Behauptung mithilfe von Faktencheck-Servern von MCP und liefert aktualisierte Informationen zurück:</p>{
  "message_type": "collaboration_response",
  "sender": "researcher_agent",
  "receiver": "reporter_agent",
  "payload": {
    "verified_claims": [
      {
        "original_claim": "France's nuclear phase-down contributed to 15% increase...",
        "verified_claim": "France's renewable capacity increased 18% in 2024, partially offsetting reduced nuclear output",
        "confidence": 0.88,
        "corrections": "Percentage was 18%, not 15%; nuclear phase-down is gradual, not primary driver",
        "sources": ["RTE France", "French Energy Ministry Report 2024"]
      }
    ]
  }
}<h3>Schritt 9: Der Reporter überarbeitet den Text und reicht ihn beim Redakteur ein.</h3><p>Der <strong>Reporter</strong> integriert die verifizierten Fakten und sendet den fertigen Entwurf per A2A an den <strong>Redaktionsagenten</strong> :</p>{
  "message_type": "task_request",
  "sender": "reporter_agent",
  "receiver": "editor_agent",
  "payload": {
    "task_id": "edit_renewable_story",
    "parent_task_id": "story_renewable_energy_2024",
    "content": {
      "headline": "Europe's Renewable Revolution: Solar and Wind Surge 30% in 2024",
      "body": "[Full article text...]",
      "word_count": 1185,
      "sources": [/* array of sources */]
    },
    "editing_requirements": {
      "check_style": true,
      "check_facts": true,
      "check_seo": true
    }
  }
}<h3>Schritt 10: Redaktionelle Überprüfungen mithilfe von MCP-Tools</h3><p>Der <strong>Redaktionsagent</strong> nutzt mehrere MCP-Server zur Überprüfung des Artikels:</p># Editor Agent using MCP for quality checks
async def review_article(self, content):
    # Grammar and style check
    grammar_issues = await self.mcp_client.invoke_tool(
        server="grammarly_mcp",
        tool="check_document",
        parameters={"text": content["body"]}
    )
    
    # SEO optimization check
    seo_analysis = await self.mcp_client.invoke_tool(
        server="seo_mcp",
        tool="analyze_content",
        parameters={
            "headline": content["headline"],
            "body": content["body"],
            "target_keywords": ["renewable energy", "Europe", "solar", "wind"]
        }
    )
    
    # Plagiarism check
    originality = await self.mcp_client.invoke_tool(
        server="plagiarism_mcp",
        tool="check_originality",
        parameters={"text": content["body"]}
    )
    
    # Generate editorial feedback
    feedback = await self._generate_feedback(
        grammar_issues, 
        seo_analysis, 
        originality
    )
    
    return feedback<p>Der <strong>Redakteur</strong> genehmigt den Artikel und leitet ihn weiter:</p>{
  "message_type": "task_response",
  "sender": "editor_agent",
  "receiver": "reporter_agent",
  "payload": {
    "status": "approved",
    "quality_score": 9.2,
    "minor_edits": [
      "Changed 'surge' to 'increased' in paragraph 3 for AP style consistency",
      "Added Oxford comma in list of countries"
    ],
    "approved_content": "[Final edited article]"
  }
}<h3>Schritt 11: Der Herausgeber veröffentlicht über CI/CD</h3><p>Schließlich veröffentlicht der <strong>Druckeragent</strong> den genehmigten Artikel mithilfe der MCP-Server für die CMS- und CI/CD-Pipeline:</p># Publisher Agent publishing via MCP
async def publish_article(self, content, metadata):
    # Upload to CMS via MCP
    cms_result = await self.mcp_client.invoke_tool(
        server="wordpress_mcp",
        tool="create_post",
        parameters={
            "title": content["headline"],
            "body": content["body"],
            "status": "draft",
            "categories": metadata["categories"],
            "tags": metadata["tags"],
            "featured_image_url": metadata["image_url"]
        }
    )
    
    post_id = cms_result["post_id"]
    
    # Trigger CI/CD deployment via MCP
    deploy_result = await self.mcp_client.invoke_tool(
        server="cicd_mcp",
        tool="trigger_deployment",
        parameters={
            "pipeline": "publish_article",
            "environment": "production",
            "post_id": post_id,
            "schedule": "immediate"
        }
    )
    
    # Track analytics
    await self.mcp_client.invoke_tool(
        server="analytics_mcp",
        tool="register_publication",
        parameters={
            "post_id": post_id,
            "publish_time": datetime.now().isoformat(),
            "story_id": metadata["story_id"]
        }
    )
    
    return {
        "status": "published",
        "post_id": post_id,
        "url": f"https://newsroom.example.com/articles/{post_id}",
        "deployment_id": deploy_result["deployment_id"]
    }<p>Der <strong>Verlag</strong> bestätigt die Veröffentlichung via A2A:</p>{
  "message_type": "task_complete",
  "sender": "printer_agent",
  "receiver": "news_chief",
  "payload": {
    "task_id": "story_renewable_energy_2024",
    "status": "published",
    "publication": {
      "url": "https://newsroom.example.com/articles/renewable-europe-2024",
      "published_at": "2025-09-30T17:45:00Z",
      "post_id": "12345"
    },
    "workflow_metrics": {
      "total_time_minutes": 45,
      "agents_involved": ["reporter", "researcher", "archive", "editor", "printer"],
      "iterations": 2,
      "mcp_calls": 12
    }
  }
}<p>Hier ist die vollständige Abfolge des A2A-Workflows im zugehörigen Repository unter Verwendung der oben beschriebenen Agenten.</p><p>#</p><p>Aus</p><p>Zu</p><p>Aktion</p><p>Protokoll</p><p>Beschreibung</p><p>1</p><p>Benutzer</p><p>Nachrichtenchef</p><p>Geschichte zuweisen</p><p>HTTP POST</p><p>Der Nutzer gibt Thema und Blickwinkel der Geschichte vor.</p><p>2</p><p>Nachrichtenchef</p><p>Intern</p><p>Geschichte erstellen</p><p>-</p><p>Erstellt einen Story-Datensatz mit eindeutiger ID</p><p>3</p><p>Nachrichtenchef</p><p>Reporter</p><p>Delegiertenzuweisung</p><p>A2A</p><p>Sendet die Story-Aufgabe über das A2A-Protokoll.</p><p>4</p><p>Reporter</p><p>Intern</p><p>Auftrag annehmen</p><p>-</p><p>Interne Zuordnung der Lagerbestände</p><p>5</p><p>Reporter</p><p>MCP-Server</p><p>Gliederung erstellen</p><p>MCP/HTTP</p><p>Erstellt Gliederungen für Artikel und Forschungsfragen</p><p>6a</p><p>Reporter</p><p>Forscher</p><p>Forschungsanfrage</p><p>A2A</p><p>Sendet Fragen (parallel zu 6b)</p><p>6b</p><p>Reporter</p><p>Archivar</p><p>Archiv durchsuchen</p><p>A2A JSONRPC</p><p>Durchsucht historische Artikel (parallel zu 6a)</p><p>7</p><p>Forscher</p><p>MCP-Server</p><p>Forschungsfragen</p><p>MCP/HTTP</p><p>Nutzt Anthropic über MCP, um Fragen zu beantworten</p><p>8</p><p>Forscher</p><p>Reporter</p><p>Forschung zurückgeben</p><p>A2A</p><p>Antworten zur Renditeforschung</p><p>9</p><p>Archivar</p><p>Elasticsearch</p><p>Suchindex</p><p>ES REST-API</p><p>Abfragen zum Nachrichtenarchivindex</p><p>10</p><p>Archivar</p><p>Reporter</p><p>Zurück zum Archiv</p><p>A2A JSONRPC</p><p>Gibt historische Suchergebnisse zurück</p><p>11</p><p>Reporter</p><p>MCP-Server</p><p>Artikel generieren</p><p>MCP/HTTP</p><p>Erstellt einen Artikel mit Recherche-/Archivkontext</p><p>12</p><p>Reporter</p><p>Intern</p><p>Entwurf speichern</p><p>-</p><p>Speichert den Entwurf intern.</p><p>13</p><p>Reporter</p><p>Nachrichtenchef</p><p>Entwurf einreichen</p><p>A2A</p><p>Reicht den fertigen Entwurf ein</p><p>14</p><p>Nachrichtenchef</p><p>Intern</p><p>Update zur Geschichte</p><p>-</p><p>Speichert den Entwurf, aktualisiert den Status auf "draft_submitted"</p><p>15</p><p>Nachrichtenchef</p><p>Editor</p><p>Entwurf prüfen</p><p>A2A</p><p>Automatische Weiterleitung an den Redakteur zur Überprüfung</p><p>16</p><p>Editor</p><p>MCP-Server</p><p>Rezensionsartikel</p><p>MCP/HTTP</p><p>Analysiert Inhalte mithilfe von Anthropic über MCP</p><p>17</p><p>Editor</p><p>Nachrichtenchef</p><p>Rückgabeprüfung</p><p>A2A</p><p>Sendet redaktionelles Feedback und Vorschläge</p><p>18</p><p>Nachrichtenchef</p><p>Intern</p><p>Ladenbewertung</p><p>-</p><p>Feedback der Ladenredaktion</p><p>19</p><p>Nachrichtenchef</p><p>Reporter</p><p>Änderungen anwenden</p><p>A2A</p><p>Feedback zur Routenbewertung an den Reporter</p><p>20</p><p>Reporter</p><p>MCP-Server</p><p>Änderungen anwenden</p><p>MCP/HTTP</p><p>Überarbeitet den Artikel basierend auf dem Feedback</p><p>21</p><p>Reporter</p><p>Intern</p><p>Entwurf aktualisieren</p><p>-</p><p>Aktualisiert den Entwurf mit den Überarbeitungen</p><p>22</p><p>Reporter</p><p>Nachrichtenchef</p><p>Rückgabe überarbeitet</p><p>A2A</p><p>Artikel über die Rückgabe überarbeitet</p><p>23</p><p>Nachrichtenchef</p><p>Intern</p><p>Update zur Geschichte</p><p>-</p><p>Die Geschäfte haben den Entwurf überarbeitet, der Status lautet nun „überarbeitet“.</p><p>24</p><p>Nachrichtenchef</p><p>Herausgeber</p><p>Artikel veröffentlichen</p><p>A2A</p><p>Automatische Weiterleitung zum Herausgeber</p><p>25</p><p>Herausgeber</p><p>MCP-Server</p><p>Tags generieren</p><p>MCP/HTTP</p><p>Erstellt Tags und Kategorien</p><p>26</p><p>Herausgeber</p><p>Elasticsearch</p><p>Indexartikel</p><p>ES REST-API</p><p>Indexiert Artikel im Nachrichtenarchivindex</p><p>27</p><p>Herausgeber</p><p>Dateisystem</p><p>Markdown speichern</p><p>Datei-E/A</p><p>Speichert den Artikel als .md-Datei Datei in /articles</p><p>28</p><p>Herausgeber</p><p>Nachrichtenchef</p><p>Veröffentlichung bestätigen</p><p>A2A</p><p>Rückgabestatus: Erfolgreich</p><p>29</p><p>Nachrichtenchef</p><p>Intern</p><p>Update zur Geschichte</p><p>-</p><p>Aktualisiert den Status der Story auf „veröffentlicht“.</p><h2>Fazit</h2><p>Sowohl A2A als auch MCP spielen eine wichtige Rolle im modernen erweiterten LLM-Infrastrukturparadigma. A2A bietet Flexibilität für komplexe Multiagentensysteme, jedoch potenziell geringere Portabilität und höhere operative Komplexität. MCP bietet einen standardisierten Ansatz für die Tool-Integration, der einfacher zu implementieren und zu warten ist, ist jedoch nicht für die Orchestrierung mehrerer Agenten ausgelegt.</p><p>Die Wahl ist nicht binär. Wie unser Beispiel aus der Redaktion zeigt, kombinieren die anspruchsvollsten und effektivsten LLM-gestützten Systeme oft beide Ansätze: Agenten koordinieren und spezialisieren sich über A2A-Protokolle, während sie über MCP-Server auf ihre Tools und Ressourcen zugreifen. Diese Hybridarchitektur bietet die organisatorischen Vorteile von Multiagentensystemen sowie die Standardisierungs- und Ökosystemvorteile von MCP. Dies deutet darauf hin, dass möglicherweise gar keine Wahlmöglichkeit besteht: Man könnte einfach beide als Standardansatz verwenden.</p><p>Es liegt an Ihnen als Entwickler oder Architekt, die beste Mischung beider Lösungen zu testen und zu ermitteln, um das richtige Ergebnis für Ihren spezifischen Anwendungsfall zu erzielen. Das Verständnis der Stärken, Grenzen und geeigneten Anwendungsbereiche der einzelnen Ansätze ermöglicht es Ihnen, effektivere, wartungsfreundlichere und skalierbare KI-Systeme zu entwickeln.</p><p>Egal, ob Sie eine digitale Nachrichtenredaktion, eine Kundenserviceplattform, einen Forschungsassistenten oder eine andere LLM-gestützte Anwendung entwickeln – die sorgfältige Berücksichtigung Ihrer Koordinierungsbedürfnisse (A2A) und Ihrer Anforderungen an den Werkzeugzugriff (MCP) wird Sie auf den Weg zum Erfolg führen.</p><h2>Weitere Ressourcen</h2><ul><li><p><strong>Elasticsearch Agent Builder: </strong><a href="https://www.elastic.co/docs/solutions/search/elastic-agent-builder">https://www.elastic.co/docs/solutions/search/elastic-agent-builder</a></p></li><li><p><strong>A2A-Spezifikation</strong>: <a href="https://a2a-protocol.org/latest/specification/">https://a2a-protocol.org/latest/specification/</a></p></li><li><p><strong>A2A- und MCP-Integration</strong>: <a href="https://a2a-protocol.org/latest/topics/a2a-and-mcp/">https://a2a-protocol.org/latest/topics/a2a-and-mcp/</a></p></li><li><p><strong>Model Context Protocol</strong>: <a href="https://modelcontextprotocol.io/">https://modelcontextprotocol.io</a></p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/a2a-protocol-mcp-llm-agent-workflow-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/a2a-protocol-mcp-llm-agent-workflow-elasticsearch</guid>
    <category><![CDATA[Agentische KI]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Justin Castilla]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1b1f22cdc2130333/6a17f161ec0f8917fa5a6712/f87330e5d4ca961593b3cfb861ca850a4cc34186-1519x1173.png" length="0" type="image/png"/>
    <pubDate>Mon, 24 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Sie wissen schon, Kontext – Teil II: Agentische KI und die Notwendigkeit von Kontextgestaltung]]></title>
    <description><![CDATA[Erfahren Sie, wie die Weiterentwicklung von LLMs hin zu agentenbasierter KI den Bedarf an Kontextentwicklung erhöht, um die Grenzen des RAG-Kontexts und das Speichermanagement zu überwinden.]]></description>
    <content:encoded><![CDATA[<p>Vor diesem (ziemlich ausführlichen) <a href="https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-evolution-agentic-ai">Hintergrund</a> zu den Veränderungen, die LLMs den zugrundeliegenden Prozessen der Informationswiedergewinnung zugeschrieben haben, wollen wir uns nun ansehen, wie sie auch die Art und Weise verändert haben, wie wir nach Daten suchen.</p><h2>Eine neue Art der Interaktion mit Daten</h2><p>Generative KI (genAI) und agentenbasierte KI gehen anders vor als die traditionelle Suche. Während wir früher mit der Informationssuche durch eine Suche begannen („Lass mich das mal googeln…“), erfolgt die erste Aktion sowohl bei generischer KI als auch bei Agenten in der Regel durch die Eingabe von natürlicher Sprache in eine Chat-Oberfläche. Die Chat-Oberfläche ist eine Diskussion mit einem LLM, der sein semantisches Verständnis nutzt, um unsere Frage in eine destillierte Antwort umzuwandeln, eine zusammenfassende Antwort, die scheinbar von einem Orakel stammt, das über ein breites Wissen über alle Arten von Informationen verfügt. Was den LLM wirklich auszeichnet, ist seine Fähigkeit, kohärente, durchdachte Sätze zu formulieren, die die einzelnen Wissensfragmente miteinander verknüpfen – selbst wenn diese ungenau oder völlig realitätsfern sind, steckt doch ein <a href="https://en.wikipedia.org/wiki/Truthiness">Körnchen Wahrheit</a> darin.</p><p>Die alte Suchleiste, mit der wir so vertraut geworden sind, kann man sich als die Ampelmaschine vorstellen, die wir benutzt haben, als <em><strong>wir selbst</strong></em> der denkende Agent waren. Inzwischen wandeln sogar Internet-Suchmaschinen unsere altbekannte, mühsame Suche nach Wörtern in KI-gesteuerte Übersichten um, die die Anfrage mit einer Zusammenfassung der Ergebnisse beantworten und den Nutzern so die Notwendigkeit ersparen, sich durch die einzelnen Ergebnisse zu klicken und diese selbst zu bewerten.</p><h2>Generative KI &amp; RAG</h2><p>Generative KI versucht, mithilfe ihres semantischen Verständnisses der Welt die in einer Chatanfrage geäußerte subjektive Absicht zu analysieren und anschließend mithilfe ihrer Schlussfolgerungsfähigkeiten spontan eine Expertenantwort zu erstellen. Eine generative KI-Interaktion besteht aus mehreren Teilen: Sie beginnt mit der Eingabe/Anfrage des Benutzers, frühere Konversationen in der Chat-Sitzung können als zusätzlicher Kontext verwendet werden, und die Anweisung gibt dem LLM vor, wie er argumentieren und welche Verfahren er bei der Erstellung der Antwort befolgen soll. Die Hilfestellungen haben sich von einfachen Erklärungen im Stil von „Erkläre es mir so, als wäre ich fünf Jahre alt“ zu vollständigen Anleitungen für die Bearbeitung von Anfragen weiterentwickelt. Diese Aufschlüsselungen enthalten oft separate Abschnitte, die Details zur Persona/Rolle der KI, zum vor der Generierung stattfindenden Denkprozess/internen Denkprozess, zu objektiven Kriterien, Einschränkungen, zum Ausgabeformat, zur Zielgruppe sowie Beispiele zur Veranschaulichung der zu erwartenden Ergebnisse beschreiben.</p><p>Zusätzlich zur Benutzeranfrage und der Systemaufforderung liefert Retrieval Augmented Generation (RAG) weitere Kontextinformationen in einem sogenannten „Kontextfenster“. RAG war eine entscheidende Ergänzung der Architektur; wir nutzen es, um das LLM über die fehlenden Puzzleteile in seinem semantischen Verständnis der Welt zu informieren.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbfa000ccfdd9d184/6a17ddb57b54f955f38b37da/5b9671d5d07d4caefde372bb3188000754a91eed-1470x746.png" alt="Wie LLMs Benutzeranfragen verarbeiten und Kontext erstellen" /><p>Kontextfenster können ziemlich <a href="https://www.dbreunig.com/2025/06/22/how-contexts-fail-and-how-to-fix-them.html">pingelig</a> sein, wenn es darum geht, was, wo und wie viel man ihnen gibt. Welcher Kontext ausgewählt wird, ist natürlich sehr wichtig, aber auch das Signal-Rausch-Verhältnis des bereitgestellten Kontexts sowie die Länge des Fensters spielen eine Rolle.</p><h3>Zu wenige Informationen</h3><p>Werden in einer Abfrage, einer Eingabeaufforderung oder einem Kontextfenster zu wenige Informationen angegeben, kann dies zu Halluzinationen führen, da das LLM den korrekten semantischen Kontext für die Generierung einer Antwort nicht genau bestimmen kann. Es gibt auch Probleme mit der Vektorähnlichkeit der Dokumentabschnittsgrößen – eine kurze, einfache Frage passt möglicherweise nicht semantisch zu den umfangreichen, detaillierten Dokumenten in unseren vektorisierten Wissensdatenbanken. Es wurden Techniken zur Erweiterung von Anfragen entwickelt, wie zum Beispiel <a href="https://medium.com/data-science/how-to-use-hyde-for-better-llm-rag-retrieval-a0aa5d0e23e8">Hypothetical Document Embeddings (HyDE)</a> , die LLMs verwenden, um eine hypothetische Antwort zu generieren, die reichhaltiger und ausdrucksstärker ist als die kurze Anfrage. Die Gefahr hierbei ist natürlich, dass das hypothetische Dokument selbst eine Halluzination ist, die den LLM noch weiter vom richtigen Kontext entfernt.</p><h3>Zu viele Informationen</h3><p>Genau wie bei uns Menschen kann eine zu große Informationsmenge in einem Kontextfenster auch einen LLM überfordern und verwirren, sodass er nicht mehr weiß, was die wichtigen Teile sein sollen. Kontextüberlauf (oder „ <a href="https://research.trychroma.com/context-rot">Kontextverfall</a>“) beeinträchtigt die Qualität und Leistung generativer KI-Operationen; er wirkt sich stark auf das „Aufmerksamkeitsbudget“ (das Arbeitsgedächtnis) des LLM aus und verwässert die Relevanz über viele konkurrierende Token hinweg. Zum Konzept der „Kontextverrottung“ gehört auch die Beobachtung, dass LLMs tendenziell eine <a href="https://alexandrabarr.beehiiv.com/p/context-windows">Positionsverzerrung</a> aufweisen – sie bevorzugen den Inhalt am Anfang oder Ende eines Kontextfensters gegenüber dem Inhalt im mittleren Abschnitt.</p><h3>Ablenkende oder widersprüchliche Informationen</h3><p>Je größer das Kontextfenster wird, desto größer ist die Wahrscheinlichkeit, dass es überflüssige oder widersprüchliche Informationen enthält, die das LLM davon ablenken können, den richtigen Kontext auszuwählen und zu verarbeiten. In gewisser Hinsicht wird es zu einem Problem von Müll rein/Müll raus: Wenn man einfach eine Reihe von Dokumentenergebnissen in ein Kontextfenster einfügt, erhält das LLM eine Menge Informationen zum Verarbeiten (möglicherweise zu viele), aber je nachdem, wie der Kontext ausgewählt wurde, besteht eine größere Wahrscheinlichkeit, dass widersprüchliche oder irrelevante Informationen einfließen.</p><h2>Agentische KI</h2><p>Ich hatte es Ihnen ja gesagt, es gäbe noch viel zu besprechen, aber wir haben es geschafft – wir sprechen jetzt endlich über agentenbasierte KI-Themen! Agentic AI ist eine sehr spannende neue Anwendung von LLM-Chat-Schnittstellen, die die Fähigkeit generativer KI (können wir sie schon als „Legacy“ bezeichnen?) erweitert, Antworten auf der Grundlage ihres eigenen Wissens und der von Ihnen bereitgestellten Kontextinformationen zu synthetisieren. Mit zunehmender Reife der generativen KI wurde uns bewusst, dass es ein gewisses Maß an Aufgaben und Automatisierung gibt, die LLMs übernehmen können, zunächst beschränkt auf mühsame, risikoarme Tätigkeiten, die leicht von einem Menschen überprüft/validiert werden können. Innerhalb kurzer Zeit erweiterte sich dieser anfängliche Umfang: Ein LLM-Chatfenster kann nun der Funke sein, der einen KI-Agenten dazu veranlasst, autonom zu planen, auszuführen und iterativ zu evaluieren und anzupassen, um sein festgelegtes Ziel zu erreichen. Die Agenten haben Zugriff auf die Schlussfolgerungen ihrer LLMs, den Chatverlauf und das Denkvermögen (sofern vorhanden) und verfügen außerdem über spezielle Werkzeuge, die sie zu diesem Zweck einsetzen können. Wir sehen jetzt auch Architekturen, die es einem übergeordneten Agenten ermöglichen, als Orchestrator mehrerer <a href="https://www.philschmid.de/the-rise-of-subagents">Unteragenten</a> zu fungieren, von denen jeder über eigene Logikketten, Befehlssätze, Kontext und Werkzeuge verfügt.</p><p>Die Agenten sind der Einstiegspunkt in einen weitgehend automatisierten Arbeitsablauf: Sie arbeiten selbstständig, indem sie mit einem Benutzer chatten und dann mithilfe von „Logik“ ermitteln, welche Tools zur Beantwortung der Frage des Benutzers zur Verfügung stehen. Werkzeuge gelten im Vergleich zu Agenten üblicherweise als passiv und sind darauf ausgelegt, nur eine bestimmte Art von Aufgabe zu erfüllen. Die <em>Aufgaben</em> , die ein Tool ausführen kann, sind quasi unbegrenzt (was wirklich spannend ist!), aber eine Hauptaufgabe von Tools besteht darin, Kontextinformationen zu sammeln, die ein Agent bei der Ausführung seines Arbeitsablaufs berücksichtigen kann.</p><p>Als Technologie steckt agentenbasierte KI noch in den Kinderschuhen und ist anfällig für das LLM-Äquivalent einer Aufmerksamkeitsdefizitstörung – sie vergisst leicht, was sie tun sollte, und macht oft andere Dinge, die überhaupt nicht Teil der Aufgabenstellung waren. Hinter der scheinbaren Magie verbergen sich die „logischen“ Fähigkeiten von LLMs, die darauf beruhen, das nächste wahrscheinlichste Token in einer Sequenz vorherzusagen. Damit logisches Denken (oder eines Tages künstliche allgemeine Intelligenz (AGI)) zuverlässig und vertrauenswürdig wird, müssen wir überprüfen können, ob es bei der Bereitstellung korrekter und aktueller Informationen so argumentiert, wie wir es erwarten (und uns vielleicht noch das kleine Quäntchen mehr liefert, an das wir selbst nicht gedacht hätten). Damit dies gelingt, benötigen agentenbasierte Architekturen die Fähigkeit, klar zu kommunizieren (Protokolle), sich an die von uns vorgegebenen Arbeitsabläufe und Einschränkungen zu halten (Leitplanken), sich zu merken, wo sie sich in einer Aufgabe befinden (Zustand), ihren verfügbaren Speicherplatz zu verwalten und zu überprüfen, ob ihre Antworten korrekt sind und die Aufgabenkriterien erfüllen.</p><h2>Sprich mit mir in einer Sprache, die ich verstehen kann.</h2><p>Wie es in neuen Entwicklungsbereichen üblich ist (insbesondere in der Welt der LLMs), gab es anfänglich eine ganze Reihe von Ansätzen für die Kommunikation zwischen Agent und Werkzeug, aber sie einigten sich schnell auf das <a href="https://modelcontextprotocol.io/docs/getting-started/intro">Model Context Protocol (MCP)</a> als De-facto-Standard. Die Definition des Model Context Protocol steckt bereits im Namen – es ist das <strong>Protokoll,</strong> das ein <strong>Modell</strong> verwendet, um <strong>Kontextinformationen</strong> anzufordern und zu empfangen. MCP fungiert als universeller Adapter für LLM-Agenten, um Verbindungen zu externen Tools und Datenquellen herzustellen; es vereinfacht und standardisiert die APIs, sodass verschiedene LLM-Frameworks und -Tools problemlos interoperabel sind. Das macht MCP zu einer Art Dreh- und Angelpunkt zwischen der Orchestrierungslogik und den Systemaufforderungen, die einem Agenten zur autonomen Ausführung im Dienste seiner Ziele gegeben werden, und den Operationen, die an Werkzeuge gesendet werden, um sie isolierter auszuführen (zumindest isoliert in Bezug auf den initiierenden Agenten).</p><p>Dieses Ökosystem ist so neu, dass sich jede Expansionsrichtung wie ein neues Terrain anfühlt. Wir verfügen über ähnliche Protokolle für Agent-zu-Agent-Interaktionen (<a href="https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/">Agent2Agent (A2A)</a> natürlich!) sowie über andere Projekte zur Verbesserung des Agenten-Schlussfolgerungsgedächtnisses (<a href="https://venturebeat.com/ai/new-memory-framework-builds-ai-agents-that-can-handle-the-real-worlds">ReasoningBank</a>), zur Auswahl des besten MCP-Servers für die jeweilige Aufgabe (<a href="https://arxiv.org/abs/2505.03275">RAG-MCP</a>) und zur Verwendung semantischer Analysen wie Zero-Shot-Klassifizierung und Mustererkennung bei Ein- und Ausgaben als <a href="https://openai.github.io/openai-guardrails-python/">Leitplanken</a> , um zu steuern, worauf ein Agent zugreifen darf.</p><p>Möglicherweise ist Ihnen aufgefallen, dass das zugrundeliegende Ziel jedes dieser Projekte darin besteht, die Qualität und Kontrolle der Informationen zu verbessern, die an ein Agenten-/genAI-Kontextfenster zurückgegeben werden? Während das agentenbasierte KI-Ökosystem seine Fähigkeit zur besseren Verarbeitung dieser Kontextinformationen stetig weiterentwickelt (um sie zu kontrollieren, zu verwalten und darauf zu reagieren), wird es immer notwendig sein, die <em>relevantesten</em> Kontextinformationen als Grundlage für die Aktionen des Agenten abzurufen.</p><h2>Willkommen im Kontext-Engineering!</h2><p>Wer mit Begriffen aus dem Bereich der generativen KI vertraut ist, hat wahrscheinlich schon von „Prompt Engineering“ gehört – mittlerweile ist es fast schon eine eigene Pseudowissenschaft. Prompt Engineering wird eingesetzt, um die besten und effizientesten Wege zu finden, die Verhaltensweisen, die das LLM bei der Generierung seiner Antwort verwenden soll, proaktiv zu beschreiben. „<a href="https://www.elastic.co/search-labs/blog/context-engineering-overview">Context Engineering</a> “ erweitert die Techniken des „Prompt Engineering“ über die Agentenseite hinaus und umfasst auch verfügbare Kontextquellen und -systeme auf der Werkzeugseite des MCP-Protokolls sowie die umfassenden Themen Kontextmanagement, -verarbeitung und -generierung:</p><ul><li><p><strong>Kontextmanagement </strong>– Bezieht sich auf die Aufrechterhaltung der Zustands- und Kontexteffizienz in langlaufenden und/oder komplexeren agentenbasierten Arbeitsabläufen. Iterative Planung, Nachverfolgung und Orchestrierung von Aufgaben und Werkzeugaufrufen zur Erreichung der Ziele des Agenten. Da Agenten nur über ein begrenztes „Aufmerksamkeitsbudget“ verfügen, befasst sich das Kontextmanagement hauptsächlich mit Techniken, die dazu beitragen, das Kontextfenster so zu verfeinern, dass sowohl der größtmögliche Umfang als auch die wichtigsten Kontextinformationen erfasst werden (Präzision versus Trefferquote!). Zu den Techniken gehören Komprimierung, Zusammenfassung und Beibehaltung des Kontextes aus vorherigen Schritten oder Werkzeugaufrufen, um im Arbeitsspeicher Platz für zusätzlichen Kontext in nachfolgenden Schritten zu schaffen.</p></li><li><p><strong>Kontextverarbeitung </strong>– Die logischen und hoffentlich größtenteils programmatischen Schritte zur Integration, Normalisierung oder Verfeinerung des aus unterschiedlichen Quellen gewonnenen Kontextes, damit der Agent den gesamten Kontext auf eine einigermaßen einheitliche Weise verarbeiten kann. Die grundlegende Aufgabe besteht darin, Kontext aus allen Quellen (Eingabeaufforderungen, RAG-System, Speicher usw.) so aufzubereiten, dass er vom Agenten möglichst effizient genutzt werden kann. </p></li><li><p><strong>Kontextgenerierung </strong>– Wenn es bei der Kontextverarbeitung darum geht, den abgerufenen Kontext für den Agenten nutzbar zu machen, dann gibt die Kontextgenerierung dem Agenten die Möglichkeit, diese zusätzlichen Kontextinformationen nach Belieben, aber auch unter bestimmten Einschränkungen, anzufordern und zu empfangen.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5e1e68c08fe050bc/6a17ddb7414c645035945073/4a8240e1eb078b2294b8d981b9caa8593589cac4-1600x900.png" alt="Kontextgestaltung in LLMs" /><p>Die verschiedenen Elemente von LLM-Chatanwendungen lassen sich direkt (und manchmal auch überlappend) auf jene übergeordneten Funktionen des Kontextmanagements abbilden:</p><ul><li><p><strong>Anweisungen / Systemaufforderung</strong> - Die Aufforderungen dienen als Gerüst dafür, wie die generative (oder agentenbasierte) KI-Aktivität ihr Denken auf die Erreichung des Ziels des Benutzers ausrichtet. Eingabeaufforderungen stellen einen eigenen Kontext dar; sie sind nicht nur tonale Anweisungen – sie beinhalten häufig auch Logik zur Aufgabenausführung und Regeln für Dinge wie „Schritt für Schritt nachdenken“ oder „tief durchatmen“, bevor man antwortet, um sicherzustellen, dass die Antwort die Anfrage des Benutzers vollständig erfüllt. Jüngste Tests haben gezeigt, dass Auszeichnungssprachen sehr effektiv sind, um die verschiedenen Teile einer Aufgabenstellung zu strukturieren. Es sollte jedoch darauf geachtet werden, die Anweisungen so zu formulieren, dass sie weder zu vage noch zu spezifisch sind; wir wollen dem LLM genügend Anweisungen geben, um den richtigen Kontext zu finden, aber nicht so präskriptiv sein, dass es unerwartete Erkenntnisse verpasst.</p></li><li><p><strong>Kurzzeitgedächtnis</strong> (Zustand/Verlauf) - Das Kurzzeitgedächtnis umfasst im Wesentlichen die Interaktionen der Chat-Sitzung zwischen dem Benutzer und dem LLM. Diese sind nützlich, um den Kontext in Live-Sitzungen zu verfeinern, und können zur späteren Verwendung und Fortsetzung gespeichert werden. </p></li><li><p><strong>Langzeitgedächtnis</strong> – Das Langzeitgedächtnis sollte Informationen enthalten, die über mehrere Sitzungen hinweg nützlich sind. Und es geht nicht nur um domänenspezifische Wissensdatenbanken, auf die über RAG zugegriffen wird; neuere Forschungen nutzen die Ergebnisse vorheriger agentischer/generativer KI-Anfragen, um innerhalb aktueller agentischer Interaktionen zu lernen und darauf zu verweisen. Zu den interessantesten Innovationen im Bereich des Langzeitgedächtnisses gehören solche, die die Art und Weise der <a href="https://steve-yegge.medium.com/introducing-beads-a-coding-agent-memory-system-637d7d92514a">Speicherung und Verknüpfung von</a> Zuständen so anpassen, dass Agenten dort weitermachen können, wo sie aufgehört haben. </p></li><li><p><strong>Strukturierte Ausgabe</strong> - Kognition erfordert Anstrengung, daher ist es wohl keine Überraschung, dass LLMs (genau wie Menschen) selbst mit Denkfähigkeiten beim Denken weniger Anstrengung aufwenden wollen, und in Ermangelung einer definierten API oder eines Protokolls ist eine Karte (ein Schema) für das Lesen der von einem Toolaufruf zurückgegebenen Daten äußerst hilfreich. Die Einbeziehung <a href="https://platform.openai.com/docs/guides/structured-outputs?lang=javascript">strukturierter Ausgaben</a> in das agentenbasierte Framework trägt dazu bei, diese Interaktionen zwischen Maschinen schneller und zuverlässiger zu gestalten, wodurch weniger gedankengesteuertes Parsen erforderlich wird.</p></li><li><p><strong>Verfügbare Tools</strong> – Tools können die unterschiedlichsten Aufgaben übernehmen, von der Erfassung zusätzlicher Informationen (z. B. durch Abfragen von Unternehmensdatenbanken mittels RAG-Code oder über Online-APIs) bis hin zur Durchführung automatisierter Aktionen im Auftrag des Agenten (z. B. durch Buchung eines Hotelzimmers auf Basis der Kriterien der Anfrage des Agenten). Werkzeuge könnten auch Unteragenten mit eigenen agentenbasierten Verarbeitungsketten sein. </p></li><li><p><strong>Retrieval Augmented Generation (RAG)</strong> – Mir gefällt die Beschreibung von RAG als „dynamische Wissensintegration“ sehr gut. Wie bereits erwähnt, ist RAG die Technik, um die zusätzlichen Informationen bereitzustellen, auf die das LLM beim Training keinen Zugriff hatte, oder es ist eine Wiederholung der Ideen, die wir für am wichtigsten halten, um die richtige Antwort zu erhalten – diejenige, die am relevantesten für unsere subjektive Anfrage ist.</p></li></ul><h2>Phänomenale kosmische Energie, winziger Wohnraum!</h2><p>Agentic AI bietet so viele faszinierende und aufregende neue Welten zum Erkunden! Es gibt zwar noch viele der alten, traditionellen Probleme der Datenbeschaffung und -verarbeitung zu lösen, aber auch ganz neue Herausforderungen, die erst jetzt im neuen Zeitalter der LLMs ans Licht der Öffentlichkeit treten. Viele der aktuellen Probleme, mit denen wir uns heute auseinandersetzen, hängen mit Kontextgestaltung zusammen, also damit, wie man Lernlern die zusätzlichen Kontextinformationen bereitstellt, die sie benötigen, ohne ihren begrenzten Arbeitsgedächtnisraum zu überlasten.</p><p>Die Flexibilität von halbautonomen Agenten, die Zugriff auf eine Reihe von Werkzeugen (und andere Agenten) haben, führt zu so vielen neuen Ideen für die Implementierung von KI, dass es schwer ist, sich die verschiedenen Möglichkeiten vorzustellen, wie wir die einzelnen Teile zusammensetzen könnten. Der Großteil der aktuellen Forschung fällt in den Bereich des Kontext-Engineerings und konzentriert sich auf den Aufbau von Speichermanagementstrukturen, die größere Mengen an Kontext verarbeiten und verfolgen können – denn die tiefgründigen Denkprobleme, die wir mit LLMs lösen wollen, weisen eine erhöhte Komplexität und länger andauernde, mehrphasige Denkprozesse auf, bei denen das Erinnern von extrem großer Bedeutung ist.</p><p>Viele der laufenden Experimente auf diesem Gebiet versuchen, die optimale Aufgabenverwaltung und Werkzeugkonfigurationen zu finden, um den agentenbasierten Schlund zu füttern. Jeder Werkzeugaufruf in der Argumentationskette eines Agenten verursacht kumulative Kosten, sowohl hinsichtlich des Rechenaufwands zur Ausführung der Funktion dieses Werkzeugs als auch der Auswirkungen auf das begrenzte Kontextfenster. Einige der neuesten Techniken zur Kontextverwaltung für LLM-Agenten haben unbeabsichtigte Ketteneffekte wie den „ <a href="https://venturebeat.com/ai/ace-prevents-context-collapse-with-evolving-playbooks-for-self-improving-ai">Kontextkollaps</a>“ verursacht, bei dem die Komprimierung/Zusammenfassung des akkumulierten Kontexts für langlaufende Aufgaben zu <em>verlustbehaftet</em> wird. Das angestrebte Ergebnis sind Werkzeuge, die einen prägnanten und genauen Kontext liefern, ohne dass überflüssige Informationen in den wertvollen Speicherplatz des Kontextfensters eindringen.</p><h3>So viele/zu viele Möglichkeiten</h3><p>Wir wollen eine klare Aufgabentrennung mit der Flexibilität, Werkzeuge/Komponenten wiederzuverwenden. Daher ist es absolut sinnvoll, dedizierte Agentenwerkzeuge für die Verbindung mit bestimmten Datenquellen zu entwickeln – jedes Werkzeug kann sich auf die Abfrage eines bestimmten Repository-Typs, eines bestimmten Datenstroms oder sogar eines bestimmten Anwendungsfalls spezialisieren. Aber Vorsicht: Im Bestreben, Zeit/Geld zu sparen/zu beweisen, dass etwas möglich ist, wird die Versuchung groß sein, LLMs als Instrument der Föderation zu nutzen… Versuchen Sie, das zu vermeiden, wir haben <a href="https://www.elastic.co/pdf/elastic-distributed-not-federated-search.pdf">das schon einmal erlebt</a> ! Die föderierte Abfrage fungiert als „universeller Übersetzer“, der eine eingehende Abfrage in die Syntax umwandelt, die das entfernte Repository versteht, und anschließend die Ergebnisse aus mehreren Quellen zu einer kohärenten Antwort zusammenführen muss. Die Federation als Technik <em>funktioniert</em> im kleinen Maßstab <em>ganz gut</em> , aber im großen Maßstab und insbesondere bei multimodalen Daten versucht die Federation, Lücken zu schließen, die einfach zu groß sind.</p><p>In der agentenbasierten Welt wäre der Agent der Föderator und die Werkzeuge (über MCP) wären die manuell definierten Verbindungen zu unterschiedlichen Ressourcen. Der Einsatz spezieller Tools zur Erfassung unverbundener Datenquellen mag zwar ein vielversprechender neuer Ansatz sein, um verschiedene Datenströme dynamisch pro Abfrage zu vereinen, doch die Verwendung von Tools, um dieselbe Frage an mehrere Quellen zu stellen, wird wahrscheinlich mehr Probleme verursachen als lösen. Bei jeder dieser Datenquellen handelt es sich wahrscheinlich um einen anderen Typ von Datenspeicher, der jeweils über eigene Funktionen zum Abrufen, Sortieren und Sichern der darin enthaltenen Daten verfügt. Diese Abweichungen oder „Impedanzfehlanpassungen“ zwischen den Repositories erhöhen natürlich die Verarbeitungslast. Außerdem können sie widersprüchliche Informationen oder Signale einbringen, wobei etwas so scheinbar Harmloses wie eine Fehlausrichtung der Bewertung die Bedeutung, die einem Teil des zurückgegebenen Kontextes beigemessen wird, stark beeinträchtigen und letztendlich die Relevanz der generierten Antwort beeinflussen kann.</p><h3>Auch für Computer ist der Kontextwechsel schwierig.</h3><p>Wenn man einen Agenten auf eine Mission schickt, besteht seine erste Aufgabe oft darin, alle relevanten Daten zu finden, auf die er Zugriff hat. Genau wie bei Menschen entsteht auch bei uns eine kognitive Belastung, wenn jede Datenquelle, mit der der Agent eine Verbindung herstellt, unterschiedliche und disaggregierte Antworten liefert. Diese Belastung entsteht durch das Herausfiltern der relevanten Kontextinformationen aus den abgerufenen Inhalten. Das braucht Zeit/Rechenleistung, und jedes kleine bisschen summiert sich in der agentenbasierten Logikkette. Daraus lässt sich schließen, dass, ähnlich wie bei <a href="https://blog.cloudflare.com/code-mode/">MCP</a>, die meisten agentenbasierten Werkzeuge sich eher wie APIs verhalten sollten – isolierte Funktionen mit bekannten Ein- und Ausgaben, die auf die Bedürfnisse verschiedener Agententypen abgestimmt sind. Wir stellen sogar fest, dass <a href="https://arxiv.org/html/2501.12372v5">LLMs Kontext für Kontext benötigen</a> – sie sind viel besser darin, die semantischen Punkte zu verbinden, insbesondere wenn es um eine Aufgabe wie die Übersetzung von natürlicher Sprache in strukturierte Syntax geht, wenn sie ein Schema haben, auf das sie sich beziehen können (RTFM in der Tat!).</p><h2>Pause im 7. Inning!</h2><p>Wir haben nun die <a href="https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-evolution-agentic-ai">Auswirkungen von LLMs auf das Abrufen und Abfragen von Daten</a> sowie die Entwicklung des Chatfensters hin zu einer agentenbasierten KI-Erfahrung behandelt. Lasst uns die beiden Themen miteinander verknüpfen und sehen, wie wir unsere neuartigen Such- und Abruffunktionen nutzen können, um unsere Ergebnisse im Bereich Context Engineering zu verbessern. Weiter zu <a href="https://www.elastic.co/search-labs/blog/context-engineering-hybrid-search-agentic-ai-accuracy">Teil III: Die Leistungsfähigkeit der hybriden Suche im Kontext-Engineering</a>!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/context-engineering-llm-evolution-agentic-ai</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/context-engineering-llm-evolution-agentic-ai</guid>
    <category><![CDATA[Agentische KI]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Woody Walton]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5f98889141fba45b/6a17ddb80b0bed0822dd34a2/79c0378b68d74d9e018c35ee2c1fd17daeee9f2c-1080x608.webp" length="0" type="image/webp"/>
    <pubDate>Tue, 18 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Erstellung eines LLM-Agent-Newsrooms mit A2A-Protokoll und MCP in Elasticsearch: Teil 1]]></title>
    <description><![CDATA[Erkunden Sie die Konzepte des A2A-Protokolls und des MCP anhand eines praktischen Beispiels aus einer Nachrichtenredaktion, in der spezialisierte LLM-Agenten zusammenarbeiten, um Nachrichtenartikel zu recherchieren, zu schreiben, zu bearbeiten und zu veröffentlichen.]]></description>
    <content:encoded><![CDATA[<h2>Einleitung</h2><p>Die derzeitigen LLM-gestützten Systeme entwickeln sich rasant über Einzelmodellanwendungen hinaus zu komplexen Netzwerken, in denen spezialisierte Agenten zusammenarbeiten, um Aufgaben zu bewältigen, die mit modernen Computern bisher für unmöglich gehalten wurden. Mit zunehmender Komplexität dieser Systeme rückt die Infrastruktur, die die Kommunikation der Agenten und den Zugriff auf Werkzeuge ermöglicht, in den Mittelpunkt der Entwicklung. Zur Erfüllung dieser Anforderungen haben sich zwei komplementäre Ansätze herausgebildet: <strong>Agent2Agent (A2A)</strong> -Protokolle für die Koordination mehrerer Agenten und das <strong>Model Context Protocol (MCP)</strong> für den standardisierten Zugriff auf Werkzeuge und Ressourcen.</p><p>Das Verständnis dafür, wann man die einzelnen Elemente harmonisch miteinander und wann man sie ohne die anderen einsetzt, kann die Skalierbarkeit, Wartbarkeit und Effektivität Ihrer Anwendungen erheblich beeinflussen. Dieser Artikel untersucht die Konzepte und Implementierungen von <strong>A2A</strong> am praktischen Beispiel einer digitalen Nachrichtenredaktion, in der spezialisierte LLM-Agenten zusammenarbeiten, um Nachrichtenartikel zu recherchieren, zu schreiben, zu bearbeiten und zu veröffentlichen.</p><p>Ein zugehöriges Repository finden Sie <a href="https://github.com/justincastilla/elastic-newsroom/tree/main">hier</a>, und konkrete Beispiele für A2A in der Praxis werden wir gegen Ende des Artikels in Abschnitt 5 untersuchen.</p><h3>Voraussetzungen</h3><p>Das <a href="https://github.com/justincastilla/elastic-newsroom/tree/main">Repository</a> besteht aus Python-basierten Implementierungen der A2A-Agenten. Flask stellt einen API-Server sowie einen benutzerdefinierten Python-Messaging-Dienst namens Event Hub bereit, der Nachrichten für die Protokollierung und UI-Aktualisierungen weiterleitet. Schließlich wird eine React-Benutzeroberfläche für die eigenständige Nutzung der Newsroom-Funktionen bereitgestellt. Alles ist zur einfacheren Implementierung in einem Docker-Image enthalten. Wenn Sie die Dienste direkt auf Ihrem Rechner ausführen möchten, sollten Sie sicherstellen, dass die folgenden Technologien installiert sind:</p><p>Sprachen und Laufzeiten</p><ul><li><p>Python 13.12 – Kern-Backend-Sprache</p></li><li><p>Node.js 18+ - Optionale React-Benutzeroberfläche</p></li></ul><p>Kern-Frameworks und SDKs:</p><ul><li><p>A2A SDK 0.3.8 – Agentenkoordination und -kommunikation</p></li><li><p>Anthropic SDK - Claude-Integration für die KI-Generierung</p></li><li><p>Uvicorn – ASGI-Server zum Ausführen von Agenten</p></li><li><p>FastMCP 2.12.5+ - MCP-Server-Implementierung</p></li><li><p>React 18.2 – Frontend-UI-Framework</p></li></ul><p>Daten &amp; Suche</p><ul><li><p>Elasticsearch 9.1.1+ - Artikelindexierung und -suche</p></li></ul><p>Docker-Bereitstellung (optional, aber empfohlen)</p><ul><li><p>Docker 28.5.1+</p></li></ul><h2>Abschnitt 1: Was ist Agent2Agent (A2A)?</h2><h3>Definition und Kernkonzepte</h3><p>Agent2Agent (A2A) ist ein standardisiertes Protokoll für die Interaktion zwischen unabhängigen LLM-Agenten. Anstatt eines einzigen monolithischen Systems, das alle Aufgaben übernimmt, ermöglicht A2A mehreren spezialisierten Agenten die Kommunikation, Koordination und Zusammenarbeit, um komplexe Arbeitsabläufe zu bewältigen, die für einen einzelnen Agenten schwierig, langsam oder gar unmöglich effizient zu handhaben wären.</p><p><strong>Offizielle Spezifikation</strong>: <a href="https://a2a-protocol.org/latest/specification/">https://a2a-protocol.org/latest/specification/</a></p><h3>Ursprung und Evolution</h3><p>Das Konzept der Agent2Agent-Kommunikation bzw. von Multiagentensystemen hat seine Wurzeln in der Forschung zu verteilten Systemen, Microservices und Multiagentensystemen, die <a href="https://en.wikipedia.org/wiki/Multi-agent_system">Jahrzehnte</a> zurückreicht. Frühe Arbeiten im Bereich der verteilten künstlichen Intelligenz legten den Grundstein für Agenten, die verhandeln, koordinieren und zusammenarbeiten können. Diese frühen Systeme dienten der Durchführung groß angelegter <a href="https://www.jasss.org/5/1/7.html">sozialer Simulationen</a>, <a href="https://arxiv.org/html/2410.09403v1">der akademischen Forschung</a> und <a href="https://www.researchgate.net/publication/334765661_Generation_Expansion_Planning_Considering_Investment_Dynamic_of_Market_Participants_Using_Multi-agent_System">dem Management von Stromnetzen</a>.</p><p>Mit der Verfügbarkeit von LLM und den gesunkenen Betriebskosten wurden Multiagentensysteme auch für den „Prosumer“-Markt zugänglich, unterstützt von Google und der breiteren KI-Forschungsgemeinschaft. Die Einführung des A2A-Protokolls, die heute als Agent2Agent-Systeme bekannt ist, hat sich zu einem modernen Standard entwickelt, der speziell für das Zeitalter mehrerer großer Sprachmodelle konzipiert wurde, die ihre Bemühungen und Aufgaben koordinieren.</p><p>Das A2A-Protokoll gewährleistet eine reibungslose Kommunikation und Koordination zwischen den Agenten, indem es einheitliche Standards und Prinzipien an den Interaktionspunkten anwendet, an denen LLMs sich verbinden und kommunizieren. Diese Standardisierung ermöglicht es Agenten verschiedener Entwickler – die unterschiedliche zugrunde liegende Modelle verwenden – effektiv zusammenzuarbeiten.</p><p>Kommunikationsprotokolle sind nicht neu und haben sich in nahezu jeder digitalen Transaktion im Internet fest etabliert. Wenn Sie <a href="https://www.elastic.co/search-labs">https://www.elastic.co/search-labs</a> eingegeben haben Wenn Sie einen Browser verwenden, um diesen Artikel zu erreichen, ist die Wahrscheinlichkeit hoch, dass alle TCP/IP-, HTTP-Transport- und DNS-Lookup-Protokolle ausgeführt wurden, um ein konsistentes Browsererlebnis für uns zu gewährleisten.</p><h3>Hauptmerkmale</h3><p>A2A-Systeme basieren auf mehreren grundlegenden Prinzipien, um eine reibungslose Kommunikation zu gewährleisten. Aufbauend auf diesen Prinzipien wird sichergestellt, dass verschiedene Agenten, die auf unterschiedlichen LLMs, Frameworks und Programmiersprachen basieren, nahtlos miteinander interagieren.</p><p>Hier sind die vier Hauptprinzipien:</p><ul><li><p><strong>Nachrichtenübermittlung</strong>: Agenten kommunizieren über strukturierte Nachrichten mit klar definierten Eigenschaften und Formaten.</p></li><li><p><strong>Koordination</strong>: Agenten orchestrieren komplexe Arbeitsabläufe, indem sie Aufgaben untereinander delegieren und Abhängigkeiten verwalten, ohne andere Agenten zu blockieren.</p></li><li><p><strong>Spezialisierung</strong>: Jeder Agent konzentriert sich auf einen bestimmten Bereich oder eine bestimmte Fähigkeit, wird Experte auf seinem Gebiet und bietet Aufgabenerledigung basierend auf diesen Fähigkeiten an.</p></li><li><p><strong>Verteilter Zustand</strong>: Zustand und Wissen sind auf mehrere Agenten verteilt und nicht zentralisiert. Die Agenten können sich gegenseitig über den Fortschritt des Aufgabenstatus und Teilergebnisse (Artefakte) informieren.</p></li></ul><h3>Die Redaktion: Ein laufendes Beispiel</h3><p>Stellen Sie sich eine digitale Nachrichtenredaktion vor, die von KI-Agenten gesteuert wird, von denen jeder auf einen anderen Aspekt des Journalismus spezialisiert ist:</p><ul><li><p><strong>Nachrichtenchef</strong> (Koordinator/Kunde): Vergibt Artikel und überwacht den Arbeitsablauf.</p></li><li><p><strong>Reporteragent</strong>: Verfasst Artikel auf Grundlage von Recherchen und Interviews.</p></li><li><p><strong>Rechercheagent</strong>: Sammelt Fakten, Statistiken und Hintergrundinformationen.</p></li><li><p><strong>Archivagent</strong>: Durchsucht historische Artikel und identifiziert Trends mithilfe von Elasticsearch.</p></li><li><p><strong>Redaktionsassistent</strong>: Überprüft Artikel auf Qualität, Stil und Suchmaschinenoptimierung.</p></li><li><p><strong>Verlagsagent</strong>: Veröffentlicht freigegebene Artikel über CI/CD auf der Blog-Plattform.</p></li></ul><p>Diese Akteure arbeiten nicht isoliert; wenn der Nachrichtenchef einen Artikel über <em>die Einführung erneuerbarer Energien</em> in Auftrag gibt, benötigt der Reporter den Rechercheur, um Statistiken zu sammeln, den Redakteur, um den Entwurf zu überprüfen, und den Verleger, um den endgültigen Artikel zu veröffentlichen. Diese Koordination erfolgt über A2A-Protokolle.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb6c7215a96326481/6a17f2dd445de953024d0243/cc0760dbd74c49b92fa00dafbb8c2e8740eb70b6-963x693.png" alt="" /><h2>Abschnitt 2: A2A-Architektur verstehen</h2><h3>Kundenbetreuer- und Fernbetreuerrollen</h3><p>In der A2A-Architektur übernehmen Agenten zwei Hauptrollen. Der <strong>Kundenbetreuer</strong> ist dafür verantwortlich, Aufgaben zu formulieren und an andere Betreuer im System zu kommunizieren. Es identifiziert Remote-Agenten und deren Fähigkeiten und nutzt diese Informationen, um fundierte Entscheidungen über die Aufgabenverteilung zu treffen. Der Kundenbetreuer koordiniert den gesamten Arbeitsablauf und sorgt dafür, dass die Aufgaben ordnungsgemäß verteilt werden und das System seine Ziele erreicht.</p><p>Der <strong>Remote Agent</strong> hingegen erledigt Aufgaben, die ihm von Clients übertragen werden. Es stellt Informationen bereit oder ergreift konkrete Maßnahmen als Reaktion auf Anfragen, initiiert aber keine Aktionen selbstständig. Remote-Agenten können bei Bedarf auch mit anderen Remote-Agenten kommunizieren, um ihre zugewiesenen Aufgaben zu erfüllen, wodurch ein kollaboratives Netzwerk spezialisierter Kompetenzen entsteht.</p><p>In unserer Redaktion fungiert der Nachrichtenchef als Ansprechpartner für den Kunden, während Reporter, Rechercheur, Redakteur und Verleger als externe Mitarbeiter Anfragen bearbeiten und sich untereinander abstimmen.</p><h3>Kernfunktionen für A2A</h3><p>A2A-Protokolle definieren verschiedene Funktionen, die die Zusammenarbeit mehrerer Agenten ermöglichen:</p><h4>1. Entdeckung</h4><p>A2A-Server müssen ihre Fähigkeiten bekanntgeben, damit Clients wissen, wann und wie sie diese für bestimmte Aufgaben nutzen können. Dies geschieht mithilfe von Agentenkarten – JSON-Dokumenten, die die Fähigkeiten, Eingaben und Ausgaben eines Agenten beschreiben. Agentenkarten werden über einheitliche, bekannte Endpunkte (wie den empfohlenen <code>/.well-known/agent-card.json</code> -Endpunkt) bereitgestellt, sodass Clients die Fähigkeiten eines Agenten ermitteln und abfragen können, bevor sie die Zusammenarbeit initiieren.</p><p>Nachfolgend sehen Sie eine Beispiel-Agentenkarte für den benutzerdefinierten Archivagenten von Elastic, „Archie Archivist“. Beachten Sie, dass Softwareanbieter wie Elastic ihre A2A-Agenten hosten und eine URL für den Zugriff bereitstellen:</p>{
  "name": "Archie Archivist",
  "description": "Helps find historical news documents in the Elasticsearch Index of archived news articles and content.",
  "url": "https://xxxxxxxxxxxxx-abc123.kb.us-central1.gcp.elastic.cloud/api/agent_builder/a2a/archive-agent",
  "provider": {
    "organization": "Elastic",
    "url": "https://elastic.co"
  },
  "version": "0.1.0",
  "protocolVersion": "0.3.0",
  "preferred_transport": "JSONRPC",
  "documentationURL": "https://www.elastic.co/docs/solutions/search/agent-builder/a2a-server"
  "capabilities": {
    "streaming": false,
    "pushNotifications": false,
    "stateTransitionHistory": false
  },
  "skills": [
    {
      "id": "platform.core.search",
      "name": "platform.core.search",
      "description": "A powerful tool for searching and analyzing data within your Elasticsearch cluster.",
      "inputModes": ["text/plain", "application/json"],
      "outputModes": ["text/plain", "application/json"]
    },
    {
      "id": "platform.core.index_explorer",
      "name": "platform.core.index_explorer",
      "description": "List relevant indices, aliases and datastreams based on a natural language query.",
      "inputModes": ["text/plain", "application/json"],
      "outputModes": ["text/plain", "application/json"]
    }
  ],
  "defaultInputModes": ["text/plain"],
  "defaultOutputModes": ["text/plain"]
}<p>Diese Agentenkarte offenbart mehrere wichtige Aspekte des Archivagenten von Elastic. Der Agent stellt sich als „Archie Archivist“ vor und gibt seinen Zweck klar an: die Suche nach historischen Nachrichtendokumenten in einem Elasticsearch-Index. Die Karte gibt den Anbieter (Elastic) und die Protokollversion (0.3.0) an und gewährleistet so die Kompatibilität mit anderen A2A-kompatiblen Agenten. Am wichtigsten ist jedoch, dass das <code>skills</code> -Array die spezifischen Fähigkeiten auflistet, die dieser Agent bietet, darunter leistungsstarke Suchfunktionen und intelligente Indexerkundung. Jede Fähigkeit definiert, welche Eingabe- und Ausgabemodi sie unterstützt, sodass Clients genau verstehen, wie sie mit diesem Agenten kommunizieren können. Dieser Agent basiert auf dem Agent Builder-Service von Elastic, der eine Reihe nativer, LLM-gestützter Tools und API-Endpunkte bereitstellt, um mit Ihrem Datenspeicher zu kommunizieren und nicht nur Daten daraus abzurufen. Zugriff auf A2A-Agenten in Elasticsearch finden Sie <a href="https://www.elastic.co/docs/solutions/search/agent-builder/a2a-server">hier</a>.</p><h4>2. Verhandlung</h4><p>Kunden und Agenten müssen sich auf Kommunikationsmethoden einigen – egal ob die Interaktion per Text, Formular, iFrames oder sogar Audio/Video erfolgt –, um eine ordnungsgemäße Benutzerinteraktion und einen reibungslosen Datenaustausch zu gewährleisten. Diese Aushandlung findet zu Beginn der Zusammenarbeit der Agenten statt und legt die Protokolle fest, die ihre Interaktion während des gesamten Arbeitsablaufs regeln. Ein Mitarbeiter im telefonischen Kundenservice könnte beispielsweise die Kommunikation über Audiostreams aushandeln, während ein Mitarbeiter im Datenanalyse-Bereich strukturiertes JSON bevorzugen könnte. Der Verhandlungsprozess stellt sicher, dass beide Parteien Informationen effektiv in einem Format austauschen können, das ihren Fähigkeiten und den Anforderungen der jeweiligen Aufgabe entspricht.</p><p>Die im obigen JSON-Ausschnitt aufgeführten Funktionen verfügen alle über Eingabe- und Ausgabeschemata; diese legen fest, wie andere Agenten mit diesem Agenten interagieren sollen.</p><h4>3. Aufgaben- und Zustandsmanagement</h4><p>Kunden und Agenten benötigen Mechanismen, um während der gesamten Aufgabenausführung über Aufgabenstatus, Änderungen und Abhängigkeiten zu kommunizieren. Dies umfasst die Verwaltung des gesamten Lebenszyklus einer Aufgabe von der Erstellung und Zuweisung bis hin zu Fortschrittsaktualisierungen und Statusänderungen. Typische Status sind: ausstehend, in Bearbeitung, abgeschlossen oder fehlgeschlagen. Das System muss außerdem Abhängigkeiten zwischen Aufgaben verfolgen, um sicherzustellen, dass die erforderlichen Vorarbeiten abgeschlossen sind, bevor die abhängigen Aufgaben beginnen. Fehlerbehandlung und Wiederholungslogik sind ebenfalls wesentliche Bestandteile, die es dem System ermöglichen, sich nach Fehlern reibungslos zu erholen und weiterhin Fortschritte in Richtung des Hauptziels zu erzielen.</p><p>Beispiel einer Aufgabenmeldung:</p>{
  "message_id": "msg_789xyz",
  "message_type": "task_request",
  "sender": "news_chief",
  "receiver": "researcher_agent",
  "timestamp": "2025-09-30T10:15:00Z",
  "payload": {
    "task_id": "task_456abc",
    "capability": "fact_gathering",
    "parameters": {
      "query": "renewable energy adoption rates in Europe 2024",
      "sources": ["eurostat", "iea", "ember"],
      "depth": "comprehensive"
    },
    "context": {
      "story_id": "story_123",
      "deadline": "2025-09-30T18:00:00Z",
      "priority": "high"
    }
  }
}<p>Diese Beispiel-Aufgabennachricht veranschaulicht mehrere wichtige Aspekte der A2A-Kommunikation.</p><ul><li><p>Die <strong>Nachrichtenstruktur</strong> umfasst Metadaten wie eine eindeutige Nachrichtenkennung, die Art der gesendeten Nachricht, die Kennung von Absender und Empfänger sowie einen Zeitstempel zur Nachverfolgung und Fehlerbehebung.</p></li><li><p>Die <strong>Nutzlast</strong> enthält die eigentlichen Aufgabeninformationen, in denen angegeben wird, welche Funktion auf dem Remote-Agenten aufgerufen wird, und die notwendigen Parameter zur Ausführung dieser Funktion bereitgestellt werden.</p></li><li><p>Der Abschnitt <strong>„Kontext“</strong> liefert zusätzliche Informationen, die dem empfangenden Agenten helfen, den übergeordneten Arbeitsablauf zu verstehen, einschließlich Fristen und Prioritätsstufen, die Aufschluss darüber geben, wie der Agent seine Ressourcen einsetzen und seine Arbeit planen sollte.</p></li></ul><h4>4. Zusammenarbeit</h4><p>Kunden und Agenten <strong>müssen</strong> eine dynamische, aber dennoch strukturierte Interaktion unterstützen, die es den Agenten ermöglicht, Klärungen, Informationen oder Teilaktionen vom Kunden, anderen Agenten oder Benutzern anzufordern. Dadurch entsteht eine kollaborative Umgebung, in der Agenten bei unklaren Anfangsanweisungen Nachfragen stellen, zusätzlichen Kontext anfordern können, um bessere Entscheidungen zu treffen, Teilaufgaben an andere Agenten mit besser geeigneter Expertise delegieren und Zwischenergebnisse zur Rückmeldung liefern können, bevor sie mit der Gesamtaufgabe fortfahren. Diese multidirektionale Kommunikation stellt sicher, dass die Agenten nicht isoliert arbeiten, sondern in einen fortlaufenden Dialog eingebunden sind, der zu besseren Ergebnissen führt.</p><h3>Verteilte Peer-to-Peer-Kommunikation</h3><p>A2A ermöglicht verteilte Kommunikation, bei der Agenten von verschiedenen Organisationen gehostet werden können, wobei einige Agenten intern verwaltet werden, während andere von Drittanbietern bereitgestellt werden. Diese Agenten können auf verschiedenen Infrastrukturen ausgeführt werden – potenziell über mehrere Cloud-Anbieter oder lokale Rechenzentren hinweg. Sie verwenden möglicherweise unterschiedliche zugrunde liegende LLMs, wobei einige Agenten auf GPT-Modellen, andere auf Claude und wieder andere auf Open-Source-Alternativen basieren. Agenten könnten sogar über verschiedene geografische Regionen hinweg operieren, um den Anforderungen der Datensouveränität nachzukommen oder die Latenz zu reduzieren. Trotz dieser Vielfalt stimmen alle Agenten einem gemeinsamen Kommunikationsprotokoll für den Informationsaustausch zu, wodurch die Interoperabilität unabhängig von Implementierungsdetails gewährleistet wird. Diese verteilte Architektur bietet Flexibilität beim Aufbau und der Bereitstellung von Systemen und ermöglicht es Organisationen, die besten Agenten und Infrastrukturen für ihre spezifischen Bedürfnisse zu kombinieren.</p><p>Dies ist die endgültige Architektur der Newsroom-Anwendung:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt74d59cd9267f54d8/6a17f2de505ac31129ad8c71/82e01a0d9746038eafd69d11177042b5390507ae-1600x838.png" alt="" /><h2>Abschnitt 3: Modellkontextprotokoll (MCP)</h2><h3>Definition und Zweck</h3><p>Das Model Context Protocol (MCP) ist ein von Anthropic entwickeltes standardisiertes Protokoll, das dazu dient, ein einzelnes LLM mit benutzerdefinierten Werkzeugen, Ressourcen und Eingabeaufforderungen sowie anderen ergänzenden Codebasiserweiterungen zu erweitern und zu stärken. MCP bietet eine universelle Schnittstelle zwischen Sprachmodellen und den externen Ressourcen, die sie benötigen, um Aufgaben effektiv zu erledigen. Dieser <a href="https://www.elastic.co/search-labs/blog/mcp-current-state">Artikel</a> beschreibt den aktuellen Stand von MCP anhand von Anwendungsbeispielen, aufkommenden Trends und der Implementierung von Elastic.</p><h3>Kernkonzepte des MCP</h3><p>MCP arbeitet mit einer Client-Server-Architektur und besteht aus drei Hauptkomponenten:</p><ul><li><p><strong>Clients:</strong> Anwendungen (wie Claude Desktop oder kundenspezifische KI-Anwendungen), die sich mit MCP-Servern verbinden, um auf deren Funktionen zuzugreifen.</p></li><li><p><strong>Server</strong>: Anwendungen, die Ressourcen, Werkzeuge und Eingabeaufforderungen für Sprachmodelle bereitstellen. Jeder Server ist darauf spezialisiert, Zugriff auf bestimmte Funktionen oder Datenquellen zu bieten.</p><ul><li><p><strong>Tools</strong>: Benutzerdefinierte Funktionen, die Modelle aufrufen können, um Aktionen auszuführen, wie z. B. Datenbanken zu durchsuchen, externe APIs aufzurufen oder Datentransformationen durchzuführen.</p></li><li><p><strong>Ressourcen:</strong> Datenquellen, aus denen Modelle lesen können, die dynamische oder statische Daten liefern und über URI-Muster aufgerufen werden (ähnlich wie REST-Routen).</p></li><li><p><strong>Eingabeaufforderungen: </strong>Wiederverwendbare Eingabeaufforderungsvorlagen mit Variablen, die das Modell bei der Erfüllung spezifischer Aufgaben unterstützen.</p></li></ul></li></ul><h3>Anfrage-Antwort-Muster</h3><p>MCP folgt einem bekannten Anfrage-Antwort-Interaktionsmuster, ähnlich wie REST-APIs. Der Client (LLM) fordert eine Ressource an oder ruft ein Tool auf. Anschließend verarbeitet der MCP-Server die Anfrage und gibt das Ergebnis zurück, das der LLM zur Fortsetzung seiner Aufgabe verwendet. Dieses zentralisierte Modell mit peripheren Servern bietet im Vergleich zur Peer-to-Peer-Agentenkommunikation ein einfacheres Integrationsmuster.</p><h3>MCP im Newsroom</h3><p>In unserem Beispiel aus der Nachrichtenredaktion nutzen einzelne Mitarbeiter MCP-Server, um auf die benötigten Tools und Daten zuzugreifen:</p><ul><li><p><strong>Der Forscheragent</strong> verwendet:</p><ul><li><p>News API MCP Server (Zugriff auf Nachrichtendatenbanken)</p></li><li><p>Faktencheck-Server von MCP (Überprüfung von Behauptungen anhand vertrauenswürdiger Quellen)</p></li><li><p>Akademische Datenbank MCP-Server (wissenschaftliche Artikel und Forschungsergebnisse)</p></li></ul></li><li><p><strong>Reporteragent</strong> verwendet:</p><ul><li><p>Styleguide MCP Server (Schreibstandards für Redaktionen)</p></li><li><p>Template MCP Server (Artikelvorlagen und -formate)</p></li><li><p>Bildbibliothek MCP-Server (Stockfotos und Grafiken)</p></li></ul></li><li><p><strong>Redaktionsagenten</strong> verwenden:</p><ul><li><p>Grammatikprüfung MCP-Server (Tools zur Sprachqualitätsprüfung)</p></li><li><p>Plagiatserkennungsserver MCP (Originalitätsprüfung)</p></li><li><p>SEO-Analyse MCP-Server (Überschriften- und Keyword-Optimierung)</p></li></ul></li><li><p><strong>Verlagsagenten</strong> verwenden:</p><ul><li><p>CMS MCP Server (API für Content-Management-Systeme)</p></li><li><p>CI/CD MCP-Server (Bereitstellungspipeline)</p></li><li><p>Analytics MCP Server (Tracking und Monitoring)</p></li></ul></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt195fe0bd36d36a48/6a17f2e0b1e113afe479f36c/b67311e3b58b27f9eb1b42a7b1dbad47ef3be4ad-808x535.png" alt="" /><h2>
Abschnitt 4: Architekturvergleich</h2><h3>Wann sollte man A2A verwenden?</h3><p>Die A2A-Architektur ist besonders geeignet für <strong>Szenarien, die eine echte Zusammenarbeit mehrerer Agenten erfordern</strong>. Mehrstufige Arbeitsabläufe, die eine Koordination erfordern, profitieren stark von A2A, insbesondere wenn Aufgaben mehrere sequentielle oder parallele Schritte umfassen, Arbeitsabläufe Iteration und Verfeinerung erfordern und Prozesse Kontrollpunkte und Validierungsanforderungen haben. In unserem Beispiel aus der Nachrichtenredaktion sieht der Arbeitsablauf vor, dass der Reporter den Artikel schreibt, ihn aber gegebenenfalls an den Rechercheur zurückgeben muss, wenn das Vertrauen in bestimmte Fakten gering ist, bevor er ihn an den Redakteur und schließlich an den Verleger weiterleitet.</p><p><strong>Domänenspezifische Spezialisierung über mehrere Bereiche hinweg</strong> ist ein weiterer wichtiger Anwendungsfall für A2A. Wenn mehrere Experten aus verschiedenen Bereichen benötigt werden, um eine größere Aufgabe zu bewältigen, wobei jeder Experte über fundiertes Fachwissen und spezialisierte Denkfähigkeiten für unterschiedliche Aspekte verfügt, bietet A2A den Koordinierungsrahmen, der für die Herstellung dieser Verbindungen erforderlich ist. Die Redaktion ist dafür ein perfektes Beispiel: Der Rechercheur ist auf die Informationsbeschaffung spezialisiert, der Reporter auf das Schreiben und der Redakteur auf die Qualitätskontrolle – jeder mit einem besonderen Fachgebiet.</p><p>Die Notwendigkeit eines autonomen Agentenverhaltens macht A2A besonders wertvoll. Agenten, die<strong> selbstständig Entscheidungen treffen können, proaktives Verhalten auf der Grundlage sich ändernder Bedingungen zeigen und sich dynamisch an die Workflow-Anforderungen anpassen können,</strong> sind in einer A2A-Architektur besonders erfolgreich. Die horizontale Skalierung spezialisierter Funktionen ist ein weiterer entscheidender Vorteil – anstatt eines einzigen Alleskönners arbeiten mehrere spezialisierte Agenten koordiniert zusammen, und mehrere Instanzen desselben Agenten können Teilaufgaben asynchron bearbeiten. Bei Eilmeldungen in unserer Redaktion arbeiten beispielsweise mehrere Reporter gleichzeitig an verschiedenen Aspekten derselben Geschichte.</p><p>Schließlich eignen sich Aufgaben, die eine echte Zusammenarbeit mehrerer Agenten erfordern, ideal für A2A. Dies umfasst <a href="https://arxiv.org/abs/2404.18796">LLM-als-Jury-Bewertungsmechanismen</a> , Konsensfindungs- und Abstimmungssysteme sowie <strong>kollaborative Problemlösungsansätze, bei denen mehrere Perspektiven erforderlich sind,</strong> um das beste Ergebnis zu erzielen.</p><h3>Wann sollte MCP verwendet werden?</h3><p>Das Model Context Protocol eignet sich ideal zur Erweiterung der Fähigkeiten eines einzelnen KI-Modells. Wenn ein einzelnes KI-Modell Zugriff auf mehrere Tools und Datenquellen benötigt, bietet MCP die perfekte Lösung mit zentralisierter Datenverarbeitung in Verbindung mit verteilten Tools und unkomplizierter Tool-Integration. In unserem Beispiel aus der Nachrichtenredaktion benötigt der Rechercheagent (ein Modell) Zugriff auf mehrere Datenquellen, darunter die News-API, Faktencheck-Dienste und akademische Datenbanken – der Zugriff erfolgt über standardisierte MCP-Server.</p><p>Die Integration standardisierter Werkzeuge gewinnt dann an Bedeutung, wenn die breite Weitergabe und Wiederverwendbarkeit von Werkzeugintegrationen wichtig ist. MCP glänzt hier mit seinem Ökosystem aus vorkonfigurierten MCP-Servern, die die Entwicklungszeit für gängige Integrationen erheblich reduzieren. Wenn Einfachheit und Wartbarkeit gefordert sind, sind die Anfrage-Antwort-Muster von MCP den Entwicklern vertraut, leichter zu verstehen und zu debuggen als verteilte Systeme und weisen eine geringere betriebliche Komplexität auf.</p><p>Schließlich wird MCP häufig von Softwareanbietern angeboten, um die Fernkommunikation mit ihren Systemen zu vereinfachen. Diese vom Anbieter bereitgestellten MCP-Server reduzieren die Einarbeitungs- und Entwicklungszeit erheblich und bieten gleichzeitig eine standardisierte Schnittstelle zu proprietären Systemen, wodurch die Integration wesentlich einfacher wird als die Entwicklung kundenspezifischer APIs.</p><h3>Wann man beides verwendet (A2A ❤️'s MCP)</h3><p>Viele hochentwickelte Systeme profitieren von der Kombination von A2A und MCP, wie in der <a href="https://a2a-protocol.org/latest/topics/a2a-and-mcp/">A2A-Dokumentation zur MCP-Integration</a> beschrieben. Systeme, die sowohl Koordination als auch Standardisierung erfordern, sind ideale Kandidaten für einen hybriden Ansatz. A2A übernimmt die Agentenkoordination und Workflow-Orchestrierung, während MCP den einzelnen Agenten Zugriff auf die Tools ermöglicht. In unserem Beispiel aus der Redaktion koordinieren sich die Mitarbeiter über A2A; der Arbeitsablauf verläuft dabei vom Reporter über den Rechercheur zum Redakteur und schließlich zum Verleger. Allerdings nutzt jeder Agent MCP-Server für seine spezialisierten Tools, wodurch eine klare architektonische Trennung entsteht.</p><p>Mehrere spezialisierte Agenten, die jeweils MCP für den Werkzeugzugriff nutzen, stellen ein gängiges Muster dar, bei dem es eine Agentenkoordinierungsschicht gibt, die von A2A verwaltet wird, und eine Werkzeugzugriffsschicht, die von MCP verwaltet wird. Durch diese klare Trennung der Zuständigkeiten werden die Systeme leichter verständlich und wartungsfreundlicher.</p><p>Die Vorteile der Kombination beider Ansätze sind beträchtlich. Sie profitieren von den organisatorischen Vorteilen von Multiagentensystemen, einschließlich Spezialisierung, Autonomie und Parallelverarbeitung, und genießen gleichzeitig die Vorteile von MCP in Bezug auf Standardisierung und Ökosystem, wie z. B. Werkzeugintegration und Ressourcenzugriff. Zwischen Agentenkoordination (A2A) und Ressourcenzugriff (MCP) besteht eine klare Trennung, und vor allem ist A2A für kleinere Aufgaben wie den API-Zugriff allein nicht erforderlich – MCP erledigt diese effizient ohne den Aufwand einer Multi-Agenten-Orchestrierung.</p><p><strong>Häufig gestellte Fragen: A2A vs. MCP – Anwendungsfälle</strong></p><p>Feature</p><p>Agent2Agent (A2A)</p><p>Model Context Protocol (MCP)</p><p>Hybrid (A2A + MCP)</p><p>Hauptziel</p><p>Multi-Agent-Koordination: Ermöglicht es einem Team spezialisierter Agenten, gemeinsam an komplexen, mehrstufigen Arbeitsabläufen zu arbeiten.</p><p>Erweiterung für einzelne Agenten: Erweitert die Funktionalität eines einzelnen LLM/Agenten um externe Tools, Ressourcen und Daten.</p><p>Gemeinsame Stärke: A2A kümmert sich um den Workflow des Teams, während MCP jedem Teammitglied die nötigen Werkzeuge zur Verfügung stellt.</p><p>Beispiel eines Redaktionsteams</p><p>Der Arbeitsablauf: Nachrichtenchef → Reporter → Rechercheur → Redakteur → Verleger. Dies ist die Koordinationsebene.</p><p>Tools für den einzelnen Agenten: Der Reporter-Agent greift über MCP auf den Styleguide-Server und den Vorlagenserver zu. Dies ist die Werkzeugzugriffsschicht.</p><p>Das vollständige System: Der Reporter stimmt sich mit dem Redakteur ab (A2A) und nutzt den Image Library MCP Server, um ein Bild für den Artikel zu finden.</p><p>Wann welches Werkzeug verwenden?</p><p>Wenn Sie echte Zusammenarbeit, Iteration und Verfeinerung benötigen oder spezialisiertes Fachwissen auf mehrere Mitarbeiter verteilt ist.</p><p>Wenn ein einzelner Agent Zugriff auf mehrere Tools und Datenquellen benötigt oder eine standardisierte Integration mit proprietären Systemen erfordert.</p><p>Wenn Sie die organisatorischen Vorteile von Multiagentensystemen und die Standardisierungs- und Ökosystemvorteile von MCP benötigen.</p><p>Kernnutzen</p><p>Autonomie und Skalierbarkeit: Agenten können unabhängige Entscheidungen treffen, und das System ermöglicht die horizontale Skalierung spezialisierter Funktionen.</p><p>Einfachheit und Standardisierung: Durch die zentrale Logik ist die Fehlersuche und Wartung einfacher, und es wird eine universelle Schnittstelle für Ressourcen bereitgestellt.</p><p>Klare Trennung der Zuständigkeiten: Macht das System verständlicher: A2A = Teamarbeit, MCP = Werkzeugzugriff.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1735ea5de41e10fd/6a17f2e26864a4125cb688c4/ddf6a29b1107ac6a63e94ecef703abc561a29e1e-986x656.png" alt="" /><h2>Fazit</h2><p>Dies ist der erste von zwei Teilen, die die Implementierung von A2A-basierten Agenten behandeln, die durch MCP-Server unterstützt werden, um Support und externen Zugriff auf Daten und Tools zu ermöglichen. Im nächsten Abschnitt wird der konkrete Code untersucht, um zu demonstrieren, wie die einzelnen Elemente zusammenarbeiten, um die Abläufe in einer Online-Nachrichtenredaktion nachzubilden. Obwohl beide Frameworks für sich genommen äußerst leistungsfähig und flexibel sind, werden Sie erst im Zusammenspiel sehen, wie sehr sie sich ergänzen.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/a2a-protocol-mcp-llm-agent-newsroom-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/a2a-protocol-mcp-llm-agent-newsroom-elasticsearch</guid>
    <category><![CDATA[Agentische KI]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Justin Castilla]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2716d804698ec878/6a17f2e41480095fd7b48888/9f938d8e2f0fdf7509edf028816c48bdbc8b3fc7-1600x900.png" length="0" type="image/png"/>
    <pubDate>Thu, 13 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Konfiguration der rekursiven Segmentierung für strukturierte Dokumente in Elasticsearch]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie rekursives Chunking in Elasticsearch mit Chunk-Größe, Trenngruppen und benutzerdefinierten Trennlisten für eine optimale strukturierte Dokumentenindizierung konfigurieren.]]></description>
    <content:encoded><![CDATA[<p>Seit Version 8.16 können Benutzer die Chunking-Strategie konfigurieren, die beim Importieren langer Dokumente in semantische Textfelder verwendet wird. Ab Version 9.1 / 8.19 haben wir eine neue konfigurierbare rekursive Chunking-Strategie eingeführt, die eine Liste regulärer Ausdrücke verwendet, um das Dokument in Abschnitte zu unterteilen. Das Ziel des Chunking ist es, ein langes Dokument in Abschnitte zu unterteilen, die zusammengehörige Inhalte enthalten. Unsere bisherigen Strategien zerlegen Texte auf der Ebene einzelner Wörter/Sätze, aber Dokumente, die in strukturierten Formaten geschrieben sind (z. B. Markdown-Dateien enthalten oft zusammengehörige Inhalte innerhalb von Abschnitten, die durch Trennzeichen definiert sind (z. B. Überschriften). Für diese Art von Dokumenten führen wir die rekursive Chunking-Strategie ein, um das Format strukturierter Dokumente zu nutzen und bessere Chunks zu erstellen!</p><h2>Was ist rekursives Chunking?</h2><p>Bei der rekursiven Segmentierung wird eine Liste von vorgegebenen Abschnittstrennungsmustern durchlaufen, um ein Dokument schrittweise in kleinere Segmente zu unterteilen, bis eine gewünschte maximale Segmentgröße erreicht ist.</p><h3>Wie konfiguriere ich rekursives Chunking?</h3><p>Folgende Werte können vom Benutzer für die rekursive Segmentierung konfiguriert werden:</p><ul><li><p>(erforderlich) <code>max_chunk_size</code>: Die maximale Anzahl von Wörtern in einem Chunk.</p></li><li><p>Entweder eines von beiden:</p><ul><li><p><code>separators</code>Eine Liste von regulären Ausdrücken, die verwendet werden, um das Dokument in Abschnitte zu unterteilen.</p></li><li><p><code>separator_group</code>Eine Zeichenkette, die einer von Elastic definierten Standardliste von Trennzeichen zugeordnet wird, die für bestimmte Dokumenttypen verwendet werden. Aktuell sind <code>markdown</code> und <code>plaintext</code> verfügbar.</p></li></ul></li></ul><h3>Wie funktioniert rekursives Chunking?</h3><p>Der Prozess des rekursiven Chunkings bei gegebenem Eingabedokument, einem <code>max_chunk_size</code> (gemessen in Wörtern) und einer Liste von Trennzeichenketten verläuft wie folgt:</p><ol><li><p>Wenn das Eingabedokument bereits innerhalb der maximalen Chunk-Größe liegt, wird ein einzelner Chunk zurückgegeben, der die gesamte Eingabe umfasst.</p></li><li><p>Teile den Text anhand des Vorkommens des Trennzeichens in mögliche Abschnitte auf. Für jeden potenziellen Teil:</p><ol><li><p>Wenn der potenzielle Datenblock innerhalb der maximalen Datenblockgröße liegt, fügen Sie ihn der Liste der an den Benutzer zurückzugebenden Datenblöcke hinzu.</p></li><li><p>Andernfalls wiederholen Sie ab Schritt 2, wobei Sie nur den Text aus dem potenziellen Chunk verwenden und diesen anhand des nächsten Trennzeichens in der Liste aufteilen. Wenn keine weiteren Trennzeichen mehr übrig sind, sollte man auf satzbasierte Segmentierung zurückgreifen.</p></li></ol></li></ol><h2>Beispiele für die Konfiguration von rekursivem Chunking</h2><p>Abgesehen von der Chunk-Größe besteht die wichtigste Konfiguration für rekursives Chunking in der Auswahl der Trennzeichen, die zum Aufteilen der Dokumente verwendet werden sollen. Wenn Sie nicht sicher sind, wo Sie anfangen sollen, bietet Elasticsearch einige Standardtrennzeichengruppen an, die für gängige Anwendungsfälle verwendet werden können.</p><h3>Verwendung von Trenngruppen</h3><p>Um eine Trenngruppe zu verwenden, geben Sie einfach den Namen der Gruppe an, die Sie bei der Konfiguration der Chunking-Einstellungen verwenden möchten. Zum Beispiel:</p>"chunking_settings": {
    "strategy": "recursive",
    "max_chunk_size": 25,
    "separator_group": "plaintext"
}<p>Dies führt zu einer rekursiven Chunking-Strategie, die die Trennzeichenliste <code>["(?&lt;!\\n)\\n\\n(?!\\n)", "(?&lt;!\\n)\\n(?!\\n)")]</code> verwendet. Dies funktioniert gut für allgemeine Klartextanwendungen, wobei der Text an zwei Zeilenumbruchzeichen, gefolgt von einem weiteren Zeilenumbruchzeichen, geteilt wird.</p><p>Wir bieten außerdem eine Trennzeichengruppe <code>markdown</code> an, die die Trennzeichenliste verwendet:</p>[
"\n# ",
       "\n## ",
       "\n### ",
       "\n#### ",
       "\n##### ",
       "\n###### ",
       "\n^(?!\\s*$).*\\n-{1,}\\n",
       "\n^(?!\\s*$).*\\n={1,}\\n"
]<p>Diese Trennzeichenliste eignet sich gut für allgemeine Markdown-Anwendungsfälle, da sie an jeder der 6 Überschriftenebenen und den Abschnittsumbruchzeichen aufteilt.</p><p>Beim Erstellen einer Ressource (Inferenzendpunkt/semantisches Textfeld) wird die Liste der Trennzeichen, die der Trennzeichengruppe zu diesem Zeitpunkt entsprechen, in Ihren Konfigurationen gespeichert. Wenn die Trenngruppe zu einem späteren Zeitpunkt aktualisiert wird, ändert sich dadurch das Verhalten Ihrer bereits erstellten Ressourcen nicht.</p><h3>Verwendung einer benutzerdefinierten Trennliste</h3><p>Falls eine der vordefinierten Trennzeichengruppen für Ihren Anwendungsfall nicht geeignet ist, können Sie eine benutzerdefinierte Liste von Trennzeichen definieren, die Ihren Anforderungen entspricht. Beachten Sie, dass reguläre Ausdrücke innerhalb der Trennzeichenliste angegeben werden können. Nachfolgend ein Beispiel für Chunking-Einstellungen mit benutzerdefinierten Trennzeichen:</p>"chunking_settings": {
    "strategy": "recursive",
    "max_chunk_size": 25,
    "separators": ["\n\n", "\n", "&lt;my-custom-separator&gt;"]
}<p>Die oben beschriebene Chunking-Strategie teilt an zwei Zeilenumbruchzeichen, gefolgt von einem Zeilenumbruchzeichen und schließlich an der Zeichenkette <code>“&lt;my-custom-separator&gt;”</code> auf.</p><h2>Ein Beispiel für rekursives Chunking in der Praxis</h2><p>Schauen wir uns ein Beispiel für rekursives Chunking in der Praxis an. In diesem Beispiel verwenden wir die folgenden Chunking-Einstellungen mit einer benutzerdefinierten Liste von Trennzeichen, die ein Markdown-Dokument anhand der beiden obersten Header-Ebenen aufteilen:</p>"chunking_settings": {
    "strategy": "recursive",
    "max_chunk_size": 25,
    "separators": ["\n# ", "\n## "]
}<p>Werfen wir einen Blick auf ein einfaches, unstrukturiertes Markdown-Dokument:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdb5f41d1bd43ba50/6a17e831e9ea87c1d8a9c5f3/3a5507f4a1288065097231548e5b18e240508785-1302x1446.png" alt="Ein nicht segmentiertes Markdown-Dokument" /><p>Nun verwenden wir die oben definierten Chunking-Einstellungen, um das Dokument in Chunking-Elemente zu unterteilen:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfffda162c7b9c87a/6a17e83296142aefa8eb1b0b/a3313c4c40ff39b8dbcdd7c4878c723f088e6c1a-1600x1187.png" alt="Aufteilen eines Dokuments in Elasticsearch" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt96f65346a8e09e3a/6a17e834445de9157b4d015e/79a2921943191ea631df94c9d465818ec8d3e738-1600x1206.png" alt="Aufteilen am zweiten Trennzeichen – Aufteilen eines Dokuments in Elasticsearch" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt28381c8f85aedf07/6a17e836ec0f89801e5a6640/459e695cce7540267422396b9a62ff4ad35f61db-1600x1260.png" alt="Letzte Abschnitte in einem Dokument nach satzbasierter Segmentierung in Elasticsearch" /><p>Hinweis: Der Zeilenumbruch am Ende jedes Abschnitts (außer Abschnitt 3) ist nicht hervorgehoben, befindet sich aber innerhalb der eigentlichen Abschnittsgrenzen.</p><h3>Legen Sie noch heute mit rekursivem Chunking los!</h3><p>Weitere Informationen zur Nutzung dieser Funktion finden Sie in der Dokumentation zur Konfiguration der Chunking-Einstellungen.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/recursive-chunking-structured-documents-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/recursive-chunking-structured-documents-elasticsearch</guid>
    <category><![CDATA[Grundlagen]]></category>
    <category><![CDATA[Inside Elastic]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Daniel Rubinstein]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf442dc4941f37be7/6a17e838505ac3eaf8ad8b3d/591872e31880768ca927507654a621addc0d124d-1600x960.png" length="0" type="image/png"/>
    <pubDate>Tue, 11 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Multimodale Suche nach Berggipfeln mit Elasticsearch und SigLIP-2 ]]></title>
    <description><![CDATA[Lernen Sie, wie Sie die multimodale Suche von Text zu Bild und von Bild zu Bild mithilfe von SigLIP-2-Einbettungen und der Elasticsearch kNN-Vektorsuche implementieren. Projektschwerpunkt: Auffinden von Fotos des Gipfels des Mount Ama Dablam während einer Everest-Trekkingtour.]]></description>
    <content:encoded><![CDATA[<p>Wollten Sie schon immer einmal Ihr Fotoalbum nach Bedeutung durchsuchen? Versuchen Sie Suchanfragen wie „Zeig mir meine Bilder, auf denen ich eine blaue Jacke trage und auf einer Bank sitze“, „Zeig mir Bilder vom Mount Everest“ oder „Sake und Sushi“. Schnapp dir eine Tasse Kaffee (oder dein Lieblingsgetränk) und lies weiter. In diesem Blog zeigen wir Ihnen, wie Sie eine multimodale hybride Suchanwendung erstellen. Multimodal bedeutet, dass die App verschiedene Arten von Eingaben verstehen und durchsuchen kann – Text, Bilder und Audio – und nicht nur Wörter. Hybrid bedeutet, dass Techniken wie Keyword-Matching, kNN-Vektorsuche und Geofencing kombiniert werden, um präzisere Ergebnisse zu liefern.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdfa1ec1ccd450e94/6a17da751d1b8308ee93e344/0ec6bbb45013846b59ee00d2bf73ee2182ee7392-1920x1080.gif" alt="Bibliothek mit Fotos verschiedener Berggipfel von der Mount-Everest-Wanderung." /><p>Um dies zu erreichen, verwenden wir Googles SigLIP-2, um Vektoreinbettungen sowohl für Bilder als auch für Texte zu generieren und diese in der Elasticsearch-Vektordatenbank zu speichern. Zum Zeitpunkt der Abfrage wandeln wir die Sucheingabe, Text oder Bild, in Einbettungen um und führen schnelle kNN-Vektorsuchen durch, um Ergebnisse abzurufen. Diese Konfiguration ermöglicht eine effiziente Text-zu-Bild- und Bild-zu-Bild-Suche. Eine Streamlit-Benutzeroberfläche erweckt dieses Projekt zum Leben, indem sie uns ein Frontend zur Verfügung stellt, mit dem wir nicht nur textbasiert nach passenden Fotos aus dem Album suchen und diese anzeigen können, sondern auch den Berggipfel auf dem hochgeladenen Bild identifizieren und weitere Fotos dieses Berges im Fotoalbum anzeigen können.
Wir beschreiben außerdem die Schritte, die wir zur Verbesserung der Suchgenauigkeit unternommen haben, und geben praktische Tipps und Tricks. Zur weiteren Erkundung stellen wir ein <a href="https://github.com/navneet83/multimodal-mountain-peak-search">GitHub-Repository</a> und ein <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/notebooks/multimodal_mountain_peak_search.ipynb">Colab-Notebook</a> zur Verfügung.</p><h2>Wie alles begann</h2><p>Dieser Blogbeitrag entstand auf Anregung eines 10-Jährigen, der mich bat, ihm alle Bilder des Mount Ama Dablam von meiner Everest-Basislager-Trekkingtour zu zeigen. Während wir das Fotoalbum durchsahen, wurde ich auch gebeten, mehrere andere Berggipfel zu identifizieren, von denen ich einige nicht benennen konnte.</p><p>Das brachte mich auf die Idee, dass dies ein unterhaltsames Computer-Vision-Projekt werden könnte. Was wir erreichen wollten:</p><ul><li><p>Finde Bilder eines Berggipfels anhand seines Namens</p></li><li><p>Errate den Namen des Berggipfels anhand eines Bildes und finde ähnliche Gipfel im Fotoalbum.</p></li><li><p>Konzeptabfragen zum Laufen bringen (<em>Person</em>, <em>Fluss</em>, <em>Gebetsfahnen</em> <em>usw.)</em></p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf82df9d7005fc3fe/6a17da78abe0f2e77bdfe8b9/e9d0d720a9b565d5b749bdc915068852d4f157ad-1200x1600.png" alt="Mount Ama Dablam " /><h2>Zusammenstellung des Dreamteams: SigLIP-2, Elasticsearch &amp; Streamlit</h2><p>Es wurde schnell klar, dass wir, um dies zu ermöglichen, sowohl den Text („Ama Dablam“) als auch die Bilder (Fotos aus meinem Album) in Vektoren umwandeln müssten, die sinnvoll verglichen werden können, d. h. im selben Vektorraum. Sobald wir das getan haben, besteht die Suche nur noch darin, „die nächstgelegenen Nachbarn zu finden“.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5f80b69a9d5bd28a/6a17da7a4b055ddd1243209e/20e6f8b7d4fa48414f407ec200adbe00ee28d517-1536x1024.png" alt="SigLIP-2, Elasticsearch &amp; Streamlit – ein Dreamteam." /><p>Um Bildeinbettungen zu generieren, verwenden wir einen mehrsprachigen<a href="https://huggingface.co/blog/vlms-2025"> Bild-Sprach-Encoder</a>, sodass ein Foto eines Berges und ein Ausdruck wie „Ama Dablam“ im selben Vektorraum landen.</p><p><a href="https://huggingface.co/blog/siglip2"><strong>SigLIP-2</strong></a>, das kürzlich von Google veröffentlicht wurde, passt hier gut hinein. Es kann Einbettungen ohne aufgabenspezifisches Training generieren (eine <strong>Zero-Shot</strong> -Einstellung) und eignet sich hervorragend für unseren Anwendungsfall: unbeschriftete Fotos und Gipfel mit unterschiedlichen Namen und Sprachen. Da es für die Zuordnung von Text zu Bild trainiert wurde, werden ein Bergbild von der Wanderung und eine kurze Texteingabeaufforderung als Einbettungen sehr ähnlich dargestellt, selbst wenn die Abfragesprache oder die Rechtschreibung variiert.</p><p>SigLIP-2 bietet ein gutes Verhältnis von Qualität zu Geschwindigkeit, unterstützt mehrere Eingangsauflösungen und läuft sowohl auf der CPU als auch auf der GPU. Der SigLIP-2 ist im Vergleich zu Vorgängermodellen wie dem ursprünglichen CLIP robuster für Außenaufnahmen. Während unserer Tests lieferte SigLIP-2 durchweg zuverlässige Ergebnisse. Es wird zudem sehr gut unterstützt, was es zur naheliegenden Wahl für dieses Projekt macht.</p><p>Als nächstes benötigen wir eine Vektordatenbank zum Speichern der Einbettungen und zur Durchführung der Power-Suche. Es sollte nicht nur die Cosinus-kNN-Suche über Bildeinbettungen unterstützen, sondern auch Geofencing und Textfilter in einer einzigen Abfrage anwenden. Elasticsearch passt hier gut: Es verarbeitet Vektoren (HNSW kNN auf dense_vector-Feldern) sehr gut, unterstützt die hybride Suche, die Text-, Vektor- und Geo-Abfragen kombiniert, und bietet standardmäßig Filter- und Sortierfunktionen. Es ist außerdem horizontal skalierbar, sodass man problemlos von einer Handvoll Fotos auf Tausende wachsen kann. Der offizielle <a href="https://www.elastic.co/docs/reference/elasticsearch/clients/python">Elasticsearch Python-Client</a> hält die Infrastruktur einfach und lässt sich nahtlos in das Projekt integrieren. Schließlich benötigen wir noch ein schlankes Frontend, in dem wir Suchanfragen eingeben und Ergebnisse anzeigen können. Für eine schnelle, Python-basierte Demo ist Streamlit hervorragend geeignet. Es bietet die grundlegenden Funktionen, die wir benötigen – Datei-Upload, ein responsives Bildraster und Dropdown-Menüs zum Sortieren und Geofencing. Es lässt sich leicht klonen und lokal ausführen und funktioniert auch in einem Colab-Notebook.</p><h2>Implementierung</h2><h3>Elasticsearch-Indexierungsdesign und Indexierungsstrategie</h3><p>Für dieses Projekt verwenden wir zwei Indizes: <code>peaks_catalog</code> und <code>photos</code>.</p><h4>Peaks_Katalogindex</h4><p>Dieser Index dient als kompakter Katalog markanter Berggipfel, die während der Everest-Basislager-Trekkingtour sichtbar sind. Jedes Dokument in diesem Index entspricht einem einzelnen Berggipfel, wie zum Beispiel dem Mount Everest. Für jedes Berggipfeldokument speichern wir Namen/Aliasse, optionale Breiten- und Längengradkoordinaten sowie einen einzelnen Prototypvektor, der durch die Kombination von SigLIP-2-Texteingabeaufforderungen (+ optionalen Referenzbildern) erstellt wird.</p><p><strong>Indexzuordnung:</strong></p><p>Feld</p><p>Typ</p><p>Beispiel</p><p>Zweck/Anmerkungen</p><p>Vektor-/Indexierung</p><p>Ausweis</p><p>Stichwort</p><p>ama-dablam</p><p>Stabiler Slug/ID</p><p>—</p><p>Namen</p><p>Text + Stichwort-Unterfeld</p><p>["Ama Dablam","Amadablam"]</p><p>Aliase / mehrsprachige Namen; names.raw für genaue Filter</p><p>—</p><p>Breitengrad</p><p>Geopunkt</p><p>{"lat":27.8617,"lon":86.8614}</p><p>GPS-Koordinaten des Gipfels als Kombination aus Breitengrad und Längengrad (optional)</p><p>—</p><p>elev_m</p><p>ganze Zahl</p><p>6812</p><p>Höhenangabe (optional)</p><p>—</p><p>text_embed</p><p>dense_vector</p><p>768</p><p>Kombinierter Prototyp (Aufforderungen und optional 1–3 Referenzbilder) für diesen Peak</p><p>index:true, similarity:"cosine", index_options:{type:"hnsw", m:16, ef_construction:128}</p><p>Dieser Index wird vor allem für Bild-zu-Bild-Suchen verwendet, beispielsweise zur Identifizierung von Berggipfeln anhand von Bildern. Wir verwenden diesen Index auch, um die Ergebnisse der Text-zu-Bild-Suche zu verbessern.</p><p>Zusammenfassend lässt sich sagen, dass die <code>peaks_catalog</code> die Frage „Welcher Berg ist das?“ in ein fokussiertes Nächste-Nachbar-Problem umwandelt und so das konzeptionelle Verständnis effektiv von der Komplexität der Bilddaten trennt.</p><p><strong>Indexierungsstrategie für den peaks_catalog-Index: </strong>Wir beginnen mit der Erstellung einer Liste der markantesten Gipfel, die während der EBC-Trekkingtour sichtbar sind. Für jeden Gipfel speichern wir seine geografische Position, seinen Namen, Synonyme und seine Höhe in einer <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/data/peaks.yaml">YAML-Datei</a>. Im nächsten Schritt wird für jeden Peak <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/embed_and_index_photos.py#L351">die Einbettung generiert</a> und im Feld <code>text_embed</code> gespeichert. Um robuste Einbettungen zu erzeugen, verwenden wir die folgende Technik:</p><ul><li><p>Erstellen Sie einen Textprototyp mit folgendem Werkzeug:</p><ul><li><p>Namen der Gipfel</p></li><li><p><a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/embed_and_index_photos.py#L301">Prompt-Ensemble</a> (Verwendung mehrerer unterschiedlicher Prompts, um dieselbe Frage zu beantworten), zum Beispiel:</p><ul><li><p>„Ein Naturfoto des Berggipfels {name} im Himalaya, Nepal“</p></li><li><p>„ {name} markanter Gipfel in der Khumbu-Region, alpine Landschaft“</p></li><li><p>„ {name} Berggipfel, Schnee, felsiger Grat“</p></li></ul></li><li><p>optionales <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/embed_and_index_photos.py#L333">Anti-Konzept</a> (sagt SigLIP-2, wonach nicht gematcht werden soll): einen kleinen Vektor für „Gemälde, Illustration, Poster, Karte, Logo“ abziehen, um eine Bevorzugung von echten Fotos zu erreichen.</p></li></ul></li><li><p>Optional <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/embed_and_index_photos.py#L388C13-L388C29">kann ein Bildprototyp erstellt werden,</a> falls Referenzbilder des Gipfels vorhanden sind.</p></li></ul><p>Anschließend <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/embed_and_index_photos.py#L392">verschmelzen wir den Text- und Bildprototyp</a> , um die endgültige Einbettung zu erzeugen. Abschließend wird das Dokument mit allen erforderlichen Feldern <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/embed_and_index_photos.py#L396">indexiert</a> :</p>def l2norm(v: np.ndarray) -&gt; np.ndarray:
    return v / (np.linalg.norm(v) + 1e-12)
def compute_blended_peak_vec(
        emb: Siglip2,
        names: List[str],
        peak_id: str,
        peaks_images_root: str,
        alpha_text: float = 0.5,
        max_images: int = 3,
) -&gt; Tuple[np.ndarray, int, int, List[str]]:
    """
    Build blended vector for a single peak.

    Returns:
      vec           : np.ndarray (L2-normalized)
      found_count   : number of reference images discovered
      used_count    : number of references used (&lt;= max_images)
      used_filenames: list of filenames used (for logging)
    """
    # 1) TEXT vector
    tv = embed_text_blend(emb, names)

    # 2) IMAGE refs: prefer folder by id; fallback to slug of the primary name
    root = Path(peaks_images_root)
    candidates = [root / peak_id]
    if names:
        candidates.append(root / slugify(names[0]))

    all_refs: List[Path] = []
    for c in candidates:
        if c.exists() and c.is_dir():
            all_refs = list_ref_images(c)
            if all_refs:
                break

    found = len(all_refs)
    used_list = all_refs[:max_images] if (max_images and found &gt; max_images) else all_refs
    used = len(used_list)

    img_v = embed_image_mean(emb, used_list) if used_list else None

    # 3) Blend TEXT and IMAGE vectors, clamp alpha to [0,1]
    a = max(0.0, min(1.0, float(alpha_text)))
    vec = l2norm(tv if img_v is None else (a * tv + (1.0 - a) * img_v)).astype("float32")
    return vec, found, used, [p.name for p in used_list]<p>Beispieldokument aus dem Index <code>peaks_catalog</code> :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1219f5d0e39b512c/6a17da7c57726263161bcace/bc05fbd0c4f8d721d5170c28a3884a9eda80bb7d-1210x1132.png" alt="Ein Beispieldokument aus dem peaks_catalog-Index in Elasticsearch." /><h4>Fotoindex</h4><p>Dieser Hauptindex speichert detaillierte Informationen über alle Fotos im Album. Jedes Dokument stellt ein einzelnes Foto dar und enthält folgende Informationen:</p><ul><li><p>Relativer Pfad zum Foto im Fotoalbum. Dies kann verwendet werden, um das passende Bild anzuzeigen oder das Bild in die Suchoberfläche zu laden.</p></li><li><p>GPS- und Zeitinformationen des Bildes.</p></li><li><p>Dichter Vektor für die Bildkodierung, generiert durch SigLIP-2.</p></li><li><p><code>predicted_peaks</code> Das ermöglicht es uns, nach Gipfelnamen zu filtern.

<strong>Indexzuordnung</strong></p></li></ul><p>Feld</p><p>Typ</p><p>Beispiel</p><p>Zweck/Anmerkungen</p><p>Vektor-/Indexierung</p><p>Weg</p><p>Stichwort</p><p>data/images/IMG_1234.HEIC</p><p>Wie die Benutzeroberfläche das Miniaturbild/Vollbild öffnet</p><p>—</p><p>Bildausschnitt</p><p>dense_vector</p><p>768</p><p>SigLIP-2 Bildeinbettung</p><p>index:true, similarity:"cosine", index_options:{type:"hnsw", m:16, ef_construction:128}</p><p>vorhergesagte_Spitzen</p><p>Stichwort</p><p>["ama-dablam","pumori"]</p><p>Top-K-Vorhersagen zur Indexierungszeit (kostengünstiger UX-Filter / Facette)</p><p>—</p><p>GPS</p><p>Geopunkt</p><p>{"lat":27.96,"lon":86.83}</p><p>Aktiviert Geofilter</p><p>—</p><p>Schusszeit</p><p>date</p><p>2023-10-18T09:41:00Z</p><p>Aufnahmezeit: Sortieren/Filtern</p><p>—</p><p><strong>Indexierungsstrategie für den Fotoindex: </strong>Für jedes Foto im Album gehen wir wie folgt vor:
 Extrahieren Sie die Bildinformationen <code>shot_time</code> und <code>gps</code> <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/embed_and_index_photos.py#L526">aus den Bildmetadaten</a>.</p><ul><li><p><a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/embed_and_index_photos.py#L511">SigLIP-2 Bildeinbettung</a>: Das Bild wird durch das Modell geleitet und der Vektor anschließend L2-normalisiert. Speichere die Einbettung im Feld <code>clip_image</code> .</p></li><li><p><a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/embed_and_index_photos.py#L519">Die Peaks werden vorhergesagt</a> und im Feld <code>predicted_peaks</code> gespeichert. Dazu nehmen wir zunächst den im vorherigen Schritt erzeugten Bildvektor des Fotos und führen dann eine schnelle kNN-Suche im Feld text_embed im Index <code>peaks_catalog</code> durch. Wir behalten die obersten 3-4 Spitzen bei und ignorieren den Rest.</p></li><li><p>Wir berechnen das Feld <code>_id</code> , indem wir einen <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/embed_and_index_photos.py#L509">Hashwert</a> aus Bildname und Pfad erstellen. Dadurch wird sichergestellt, dass nach mehreren Durchläufen keine Duplikate entstehen.</p></li></ul><p>Sobald alle Felder für das Foto ermittelt wurden, werden die Fotodokumente mithilfe <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/embed_and_index_photos.py#L530">der Massenindizierung</a> stapelweise indexiert:</p>def bulk_index_photos(
        es: Elasticsearch,
        images_root: str,
        photos_index: str = "photos",
        peaks_index: str = "peaks_catalog",
        topk_predicted: int = 5,
        batch_size: int = 200,
        refresh: str = "false",
) -&gt; None:
    """Walk a folder of images, embed + enrich, and bulk index to Elasticsearch."""
    root = Path(images_root)
    if not root.exists():
        raise SystemExit(f"Images root not found: {images_root}")

    emb = Siglip2()
    batch: List[Dict[str, Any]] = []
    n_indexed = 0

    for p in iter_images(root):
        rel = relpath_within(root, p)
        _id = id_for_path(rel)

        # 1) Image embedding (and reuse it for predicted_peaks)
        try:
            with Image.open(p) as im:
                ivec = emb.image_vec(im.convert("RGB")).astype("float32")
        except (UnidentifiedImageError, OSError) as e:
            print(f"[skip] {rel} — cannot embed: {e}")
            continue

        # 2) Predict top-k peak names
        try:
            top_names = predict_peaks(es, ivec.tolist(), peaks_index=peaks_index, k=topk_predicted)
        except Exception as e:
            print(f"[warn] predict_peaks failed for {rel}: {e}")
            top_names = []

        # 3) EXIF enrichment (safe)
        gps = get_gps_decimal(str(p))
        shot = get_shot_time(str(p))

        # 4) Build doc and stage for bulk
        doc = {"path": rel, "clip_image": ivec.tolist(), "predicted_peaks": top_names}
        if gps:
            doc["gps"] = gps
        if shot:
            doc["shot_time"] = shot

        batch.append(
            {"_op_type": "index", "_index": photos_index, "_id": _id, "_source": doc}
        )

        # 5) Periodic flush
        if len(batch) &gt;= batch_size:
            helpers.bulk(es, batch, refresh=refresh)
            n_indexed += len(batch)
            print(f"[photos] indexed {n_indexed} (last: {rel})")
            batch.clear()

    # Final flush
    if batch:
        helpers.bulk(es, batch, refresh=refresh)
        n_indexed += len(batch)
        print(f"[photos] indexed {n_indexed} total.")

    print("[done] photos indexing")<p>Beispieldokument aus dem Fotoindex:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt744b7e6326937cfc/6a17da7e6df731d3040a0da8/1dc1406ac2a97440b6804838795b3c2205c4c6b2-1080x1234.png" alt="Ein Beispieldokument aus dem Fotoindex in Elasticsearch." /><p>Zusammenfassend lässt sich sagen, dass der Fotoindex ein schneller, filterbarer und kNN-fähiger Speicher aller Fotos im Album ist. Die Kartierung ist bewusst minimalistisch gehalten – gerade so strukturiert, dass die Ergebnisse schnell abgerufen, übersichtlich dargestellt und nach Raum und Zeit unterteilt werden können. Dieser Index dient beiden Suchanwendungsfällen. Das Python-Skript zur Erstellung beider Indizes finden Sie <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/create_indices.py">hier</a>.</p><p>Die untenstehende Visualisierung der Kibana-Karten zeigt Dokumente aus dem Fotoalbum als grüne Punkte und Berggipfel ab dem Index <code>peaks_catalog</code> als rote Dreiecke an, wobei die grünen Punkte gut mit dem Wanderweg zum Everest-Basislager übereinstimmen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb5bf016e8d9c3e84/6a17da80be608681f10045e6/1c75d0ed0ce53d28a94bf2f47a354e25581d2baf-1600x1402.png" alt="Eine Visualisierung in Kibana Maps, die Dokumente aus dem Fotoalbum als grüne Punkte und Berggipfel aus dem peaks_catalog-Index als rote Dreiecke darstellt, wobei die grünen Punkte gut mit dem Wanderweg zum Everest Base Camp übereinstimmen." /><h2>Suchanwendungsfälle</h2><p><strong>Namenssuche (Text-zu-Bild): Mit</strong> dieser Funktion können Benutzer mithilfe von Textanfragen Fotos von Berggipfeln (und sogar abstrakten Konzepten wie „Gebetsfahnen“) finden. Um dies zu erreichen, wird die Texteingabe mithilfe von SigLIP-2 <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/query_by_peak_name.py#L87C5-L87C20">in einen Textvektor umgewandelt</a> . Für eine robuste Textvektorgenerierung verwenden wir die gleiche Strategie wie für die Erstellung von Text-Embeddings im <code>peaks_catalog</code> -Index: <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/query_by_peak_name.py#L104">Kombination</a> der Texteingabe mit einem kleinen <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/query_by_peak_name.py#L100">Prompt-Ensemble</a>, Subtraktion eines minor<a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/query_by_peak_name.py#L103"> Anti-Concept-Vektors</a> und Anwendung <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/query_by_peak_name.py#L104">der L2-Normalisierung</a> zur Erzeugung des endgültigen Abfragevektors. Anschließend wird eine kNN- <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/query_by_peak_name.py#L140">Abfrage</a> auf dem Feld <code>photos.clip_image</code> ausgeführt, um die am besten übereinstimmenden Peaks auf Basis der Kosinusähnlichkeit zu ermitteln und so die ähnlichsten Bilder zu finden. Optional können die Suchergebnisse relevanter gestaltet werden, indem Geo- und <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/query_by_peak_name.py#L152">Datumsfilter</a> und/oder ein <code>photos.predicted_peaks</code> -Termfilter als Teil der Abfrage angewendet werden (siehe Abfragebeispiele unten). Dadurch werden ähnlich aussehende Gipfel ausgeschlossen, die auf der Wanderung gar nicht sichtbar sind.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9bb9abf5ce64fcbb/6a17da81e8fbce20db3a17da/b5fac28ffdbedb820505365ca07df125cd01b939-946x370.png" alt="Wie die multimodale Suche nach Namen (Text-zu-Bild) in Elasticsearch funktioniert." /><p><strong>Elasticsearch-Abfrage mit Geofilter:</strong></p>POST photos/_search
{
  "knn": {
    "field": "clip_image",
    "query_vector": [ ... ],
    "k": 60,
    "num_candidates": 2000
  },
  "query": {
    "bool": {
      "filter": [
        { "geo_bounding_box": { "gps": { "top_left": "...", "bottom_right": "..." } } }
      ]
    }
  },
  "_source": ["path","predicted_peaks","gps","shot_time"]
}

Response (first two documents):
{
 "hits": {
   "total": {
     "value": 56,
     "relation": "eq"
   },
   "max_score": 0.5779596,
   "hits": [
     {
       "_index": "photos",
       "_id": "d01da3a1141981486c3493f6053c79e92a788463",
       "_score": 0.5779596,
       "_source": {
         "path": "IMG_2738.HEIC",
         "predicted_peaks": [
           "Pumori",
           "Kyajo Ri",
           "Khumbila",
           "Nangkartshang",
           "Kongde Ri"
         ],
         "gps": {
           "lat": 27.97116388888889,
           "lon": 86.82331111111111
         },
         "shot_time": "2023-11-03T08:07:13"
       }
     },
     {
       "_index": "photos",
       "_id": "c79d251f07adc5efaedc53561110a7fd78e23914",
       "_score": 0.5766071,
       "_source": {
         "path": "IMG_2761.HEIC",
         "predicted_peaks": [
           "Kyajo Ri",
           "Makalu",
           "Baruntse",
           "Cho Oyu",
           "Khumbila"
         ],
         "gps": {
           "lat": 27.975558333333332,
           "lon": 86.82515
         },
         "shot_time": "2023-11-03T08:51:08"
       }
     }
}<p><strong>Bildsuche (Bild-zu-Bild): Mit</strong> dieser Funktion können wir einen Berg auf einem Bild identifizieren und weitere Bilder desselben Berges innerhalb des Fotoalbums finden. Beim Hochladen eines Bildes wird dieses vom SigLIP-2-Bildcodierer verarbeitet, um einen <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/identify_from_picture_find_similar_peaks.py#L228">Bildvektor</a> zu erzeugen. Anschließend wird eine <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/identify_from_picture_find_similar_peaks.py#L234">kNN-Suche</a> im Feld <code>peaks_catalog.text_embed</code> durchgeführt, um die am besten passenden Peaknamen zu identifizieren. Anschließend <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/identify_from_picture_find_similar_peaks.py#L257">wird aus diesen übereinstimmenden Peaknamen ein Textvektor generiert</a> und eine weitere <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/scripts/identify_from_picture_find_similar_peaks.py#L263">kNN-Suche</a> im Fotoindex durchgeführt, um entsprechende Bilder zu finden.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltab9d16333e2a9e69/6a17da827f6f155448c099cc/3a3d5635bee7a222b95529dd7f9fbee016381610-1226x550.png" alt="Wie die multimodale Bildersuche (Bild-zu-Bild) in Elasticsearch funktioniert." /><p><strong>Elasticsearch-Abfrage:</strong></p><p>Schritt 1: Finde die passenden Peaknamen</p>GET peaks_catalog/_search
{
 "knn": {
   "field": "text_embed",
   "query_vector": [...image-vector... ],
   "k": 3,
   "num_candidates": 500
 },
 "_source": [
   "id",
   "names",
   "latlon",
   "text_embed"
 ]
}


Response (first two documents):
{
 "took": 2,
 "timed_out": false,
 "_shards": {
   "total": 1,
   "successful": 1,
   "skipped": 0,
   "failed": 0
 },
 "hits": {
   "total": {
     "value": 3,
     "relation": "eq"
   },
   "max_score": 0.58039916,
   "hits": [
     {
       "_index": "peaks_catalog",
       "_id": "pumori",
       "_score": 0.58039916,
       "_source": {
         "id": "pumori",
         "names": [
           "Pumori",
           "Pumo Ri"
         ],
         "latlon": {
           "lat": 28.01472,
           "lon": 86.82806
         },
         "text_embed": [
                  ... embeddings...
         ]
       }
     },
     {
       "_index": "peaks_catalog",
       "_id": "kyajo-ri",
       "_score": 0.57942784,
       "_source": {
         "id": "kyajo-ri",
         "names": [
           "Kyajo Ri",
           "Kyazo Ri"
         ],
         "latlon": {
           "lat": 27.909167,
           "lon": 86.673611
         },
         "text_embed": [
           ... embeddings...
         ]
       }
     }
   ]
 }
}<p>Schritt 2: Führen Sie eine Suche im Index <code>photos</code> durch, um die passenden Bilder zu finden (dieselbe Abfrage wie im Anwendungsfall der Text-zu-Bild-Suche):</p>POST photos/_search
{
 "knn": {
   "field": "clip_image",
   "query_vector": [ ...image-vector... ],
   "k": 30,
   "num_candidates": 2000
 },
 "_source": [
   "path",
   "gps",
   "shot_time",
   "predicted_peaks",
   "clip_image"
 ],
 "query": {
   "bool": {
     "filter": [
       {
         "term": {
           "predicted_peaks": "Pumori"
         }
       }
     ]
   }
 }
}


Response (first two documents):
{
 "hits": {
   "total": {
     "value": 56,
     "relation": "eq"
   },
   "max_score": 0.5779596,
   "hits": [
     {
       "_index": "photos",
       "_id": "d01da3a1141981486c3493f6053c79e92a788463",
       "_score": 0.5779596,
       "_source": {
         "path": "IMG_2738.HEIC",
         "predicted_peaks": [
           "Pumori",
           "Kyajo Ri",
           "Khumbila",
           "Nangkartshang",
           "Kongde Ri"
         ],
         "gps": {
           "lat": 27.97116388888889,
           "lon": 86.82331111111111
         },
         "shot_time": "2023-11-03T08:07:13"
       }
     },
     {
       "_index": "photos",
       "_id": "c79d251f07adc5efaedc53561110a7fd78e23914",
       "_score": 0.5766071,
       "_source": {
         "path": "IMG_2761.HEIC",
         "predicted_peaks": [
           "Kyajo Ri",
           "Makalu",
           "Baruntse",
           "Cho Oyu",
           "Khumbila"
         ],
         "gps": {
           "lat": 27.975558333333332,
           "lon": 86.82515
         },
         "shot_time": "2023-11-03T08:51:08"
       }
     }
}<h2>Streamlit-Benutzeroberfläche</h2><p>Um alles zusammenzuführen, haben wir eine einfache Streamlit-Benutzeroberfläche entwickelt, die es uns ermöglicht, beide Suchanwendungsfälle durchzuführen. In der linken Spalte wird eine scrollbare Liste von Gipfeln (aggregiert aus <code>photos.predicted_peaks</code>) mit Kontrollkästchen und einem Mini-Karten-/Geofilter angezeigt. Ganz oben befinden sich ein <strong>Suchfeld für den Namen</strong> und eine Schaltfläche zum Hochladen <strong>eines Fotos zur Identifizierung</strong> . Im mittleren Bereich befindet sich ein responsives Miniaturraster mit kNN-Werten, vorhergesagten Spitzenwerten und Erfassungszeiten. Jedes Bild enthält eine Schaltfläche <strong>„Bild anzeigen“</strong> für Vorschauen in voller Auflösung.</p><p><strong>Suche durch Hochladen eines Bildes:</strong> Wir prognostizieren den Peak und finden übereinstimmende Peaks aus dem Fotoalbum.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd1fb2b0304a310d2/6a17da8425daab7cda08a0fa/dca540cbf5279e6d6102c5a0c0351ddd4ac91cda-1600x1112.png" alt="Eine einfache, intuitive Benutzeroberfläche, die die multimodale Suche nach den Gipfeln des Mount Ama Dablam sowohl per Text-zu-Bild- als auch per Bild-zu-Bild-Suche ermöglicht." /><p><strong>Suche nach Text</strong>: Finde die passenden Höhepunkte im Album anhand des Textes</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt496c1ae8f7886320/6a17da86abe0f2da48dfe8bd/b1e8618db746cd49ea4962d3dc73031387b975dd-1600x1166.png" alt="Wie man in der Berggipfelbibliothek mithilfe der Textsuche nach einem Gipfel des Mount Everest sucht." /><h2>Fazit</h2><p>Was mit der Frage begann: <em>Können wir bitte die </em>Bilder<em><strong>von Ama Dablam</strong></em>sehen<em>?</em> entwickelte sich zu einem kleinen, funktionierenden <strong>multimodalen Suchsystem</strong> . Wir haben Rohdaten von Trekkingfotos aufgenommen, diese in <strong>SigLIP-2-Einbettungen</strong> umgewandelt und <strong>Elasticsearch</strong> verwendet, um ein schnelles <strong>kNN</strong> über Vektoren durchzuführen, sowie einfache Geo-/Zeitfilter, um die richtigen Bilder anhand ihrer <em>Bedeutung</em> anzuzeigen. Dabei haben wir die Belange mithilfe zweier Indizes getrennt: einem winzigen <code>peaks_catalog</code> Index von kombinierten Prototypen (zur Identifizierung) und einem skalierbaren <code>photos</code> Index von Bildvektoren und EXIF-Daten (zum Abruf). Es ist praktisch, reproduzierbar und leicht erweiterbar.</p><p>Falls Sie es feinabstimmen möchten, gibt es einige Einstellungen, mit denen Sie experimentieren können:</p><ul><li><p><strong>Einstellungen für die Abfragezeit:</strong> <code>k</code> (wie viele Nachbarn Sie zurückbekommen möchten) und <code>num_candidates</code> (wie breit die Suche vor der endgültigen Bewertung sein soll). Diese Einstellungen werden <a href="https://www.elastic.co/search-labs/blog/elasticsearch-knn-and-num-candidates-strategies">hier</a> im Blog besprochen.</p></li><li><p><strong>Indexzeiteinstellungen:</strong> <code>m</code> (Graphkonnektivität) und <code>ef_construction</code> (Genauigkeit der Build-Zeit vs. Speicher). Experimentieren Sie bei Abfragen auch mit <code>ef_search</code> – ein höherer Wert bedeutet in der Regel eine bessere Trefferquote, allerdings mit einem gewissen Nachteil bei der Latenz. Weitere Einzelheiten zu diesen Einstellungen finden Sie in <a href="https://www.elastic.co/search-labs/blog/hnsw-graph">diesem Blog</a> .</p></li></ul><p>Zukünftig werden native Modelle/Reranker für <strong>multimodale</strong> und <strong>mehrsprachige</strong> Suche in Kürze im Elastic-Ökosystem verfügbar sein. Dies dürfte die Bild-/Textsuche und das hybride Ranking von Haus aus noch weiter verbessern.<a href="https://ir.elastic.co/news/news-details/2025/Elastic-Completes-Acquisition-of-Jina-AI-a-Leader-in-Frontier-Models-for-Multimodal-and-Multilingual-Search/default.aspx?utm_source=chatgpt.com"> ir.elastic.co+1</a></p><p>Wenn Sie das selbst ausprobieren möchten:</p><ul><li><p><strong>GitHub-Repository:</strong> <a href="https://github.com/navneet83/multimodal-mountain-peak-search"><em>https://github.com/navneet83/multimodal-mountain-peak-search</em></a></p></li><li><p><strong>Colab-Schnellstartanleitung:</strong> <a href="https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/notebooks/multimodal_mountain_peak_search.ipynb">https://github.com/navneet83/multimodal-mountain-peak-search/blob/main/notebooks/multimodal_mountain_peak_search.ipynb</a></p></li></ul><p>Damit ist unsere Reise zu Ende, und es ist Zeit, zurückzufliegen. Ich hoffe, das war hilfreich, und falls etwas kaputtgeht (oder verbessert wird), würde ich gerne erfahren, was Sie geändert haben.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdce2fff1569d2a8b/6a17da894b055dd1f24320a2/d324d1e1472f1bfbd8f25747f57bdeeb9c7f16b2-1600x1200.png" alt="" />]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/multimodal-search-siglip-2-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/multimodal-search-siglip-2-elasticsearch</guid>
    <category><![CDATA[Vektordatenbank]]></category>
    <category><![CDATA[Hybride Suche]]></category>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[Python]]></category>
    <dc:creator><![CDATA[Navneet Kumar]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltccb66279debb05f9/6a17da8b63baffe228741b15/ffcf93358a7c5dadcea82faf3de460bf060d003c-1600x1200.png" length="0" type="image/png"/>
    <pubDate>Tue, 04 Nov 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Elastischer MCP-Server: Agent Builder-Tools für jeden KI-Agenten zugänglich machen]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie den integrierten Elastic MCP-Server im Agent Builder nutzen können, um jeden KI-Agenten sicher um Zugriff auf Ihre privaten Daten und benutzerdefinierten Tools zu erweitern.]]></description>
    <content:encoded><![CDATA[<p>Elastic Agent Builder ist eine Plattform zur Erstellung von Tools und Agents, die eng mit Ihren eigenen Daten in Elasticsearch integriert sind. Beispielsweise können Sie Tools erstellen, die eine semantische Suche in internen Dokumenten durchführen, Observability-Logs analysieren oder Sicherheitswarnungen abfragen.</p><p>Die wahre Magie entfaltet sich jedoch erst, wenn Sie diese maßgeschneiderten, datenorientierten Tools in die Umgebungen integrieren können, in denen Sie die meiste Zeit verbringen. Was wäre, wenn Ihr Code-Editor-Agent sicher auf die private Wissensdatenbank Ihres Unternehmens zugreifen könnte?</p><p>Hier kommt <strong>das Model Context Protocol (MCP)</strong> ins Spiel. Elastic Agent Builder wird mit einem integrierten MCP-Server ausgeliefert, der Zugriff auf die Tools der Plattform ermöglicht.</p><h2>Warum sollte man den Elastic Agent Builder MCP-Server verwenden?</h2><p>KI-Agenten sind unglaublich leistungsstark, aber ihr Wissen beschränkt sich typischerweise auf die Daten, mit denen sie trainiert wurden, und auf Informationen, die sie aktiv im öffentlichen Internet suchen können. Sie kennen weder die internen Designdokumente Ihres Unternehmens noch die spezifischen Bereitstellungs-Runbooks Ihres Teams oder die einzigartige Struktur Ihrer Anwendungsprotokolle.</p><p>Die Herausforderung besteht darin, Ihrem KI-Assistenten den benötigten spezialisierten Kontext zu liefern. Genau dieses Problem soll MCP lösen. <strong>MCP ist ein offener Standard, der es einem KI-Modell oder -Agenten ermöglicht, externe Tools zu erkennen und zu nutzen.</strong></p><p>Um dies zu ermöglichen, stellt der Elastic Agent Builder Ihre benutzerdefinierten Tools nativ über einen integrierten MCP-Server zur Verfügung. Das bedeutet, dass Sie jeden MCP-kompatiblen Client, wie <strong>Cursor</strong>, <strong>VS Code</strong> oder <strong>Claude Desktop</strong>, problemlos mit den spezialisierten, datenorientierten Tools verbinden können, die Sie mit Elastic Agent Builder erstellt haben.</p><h2>Wann sollte man MCP verwenden (und wann nicht)?</h2><p>Elastic Agent Builder beinhaltet mehrere Protokolle zur Unterstützung verschiedener Integrationsmuster. Die Wahl der richtigen Lösung ist der Schlüssel zum Aufbau effektiver KI-Workflows.</p><ul><li><p><strong>Verwenden Sie </strong><a href="https://www.elastic.co/docs/solutions/search/agent-builder/mcp-server"><strong>MCP</strong></a> , um Ihren KI-Agenten (wie in <strong>Cursor</strong> oder <strong>VS Code</strong>) mit spezialisierten Werkzeugen zu erweitern. Es ist der Ansatz „Bring your own tools“, der den bereits verwendeten Assistenten um einen sicheren Zugriff auf Ihre privaten Daten erweitert. Lediglich die Tools werden über den MCP-Server bereitgestellt – die Agenten von Elastic sind davon getrennt.</p></li><li><p><strong>Mit dem </strong><a href="https://www.elastic.co/docs/solutions/search/agent-builder/a2a-server"><strong>A2A-Protokoll</strong></a> können Sie Ihren vollständig benutzerdefinierten Elastic Agent mit anderen autonomen Agenten (wie in <a href="https://www.elastic.co/search-labs/blog/a2a-protocol-elastic-agent-builder-gemini-enterprise"><strong>Googles Gemini Enterprise</strong></a>) zusammenarbeiten lassen. Dies dient der Agenten-zu-Agenten-Delegierung, bei der jeder Agent als gleichberechtigter Partner an der Lösung eines Problems arbeitet.</p></li><li><p><strong>Nutzen Sie die </strong><a href="https://www.elastic.co/docs/solutions/search/agent-builder/kibana-api"><strong>Agent Builder APIs</strong></a> für die vollständige programmatische Kontrolle beim Erstellen einer benutzerdefinierten Anwendung von Grund auf.</p></li></ul><p>Für Entwickler, die Antworten aus ihrer internen Dokumentation erhalten möchten, ohne ihre IDE zu verlassen, ist MCP die perfekte Lösung.</p><h2>Beispiel: Ihre benutzerdefinierten Tools in Cursor mit Agent Builder MCP-Server</h2><p>Lassen Sie uns ein praktisches Beispiel durchgehen, das ich täglich verwende. Zuerst habe ich unsere interne technische Dokumentation gecrawlt und in einen Elasticsearch-Index namens <code>elastic-dev-docs</code> indexiert. Obwohl wir die im Agent Builder verfügbaren generischen, integrierten Tools verwenden könnten, werden wir unser eigenes, benutzerdefiniertes Tool erstellen, um diese spezielle Wissensdatenbank abzufragen.</p><p>Der Grund für die Entwicklung eines maßgeschneiderten Werkzeugs ist einfach: <strong>Kontrolle und Präzision</strong>. Dieser Ansatz gibt uns die Möglichkeit, eine schnelle semantische Abfrage direkt gegen unseren <code>elastic-dev-docs</code> -Index auszuführen. Wir haben die volle Kontrolle darüber, welcher Index genau anvisiert wird und wie die Daten abgerufen werden.</p><p>Und so können wir diese benutzerdefinierte Wissensdatenbank in einem KI-gestützten Code-Editor wie Cursor verwenden.</p><h3>Schritt 1: Erstellen Sie ein benutzerdefiniertes Wissensdatenbank-Tool im Agent Builder.</h3><p>Zuerst erstellen Sie ein neues Tool im Agent Builder. Eine klare und präzise Werkzeugbeschreibung ist wichtig, denn sie ist die Grundlage dafür, wie jeder KI-Agent, sei es der interne Elastic Agent oder ein externes Werkzeug wie Cursor, das über MCP verbunden ist, Ihr Werkzeug für die richtige Aufgabe erkennt und auswählt.</p><p>Eine aussagekräftige Beschreibung sollte explizit sein. Zum Beispiel: „Führt eine semantische Suche im elastic-dev-docs-Index durch, um interne Entwicklungsdokumentationen, Runbooks und Release-Prozeduren zu finden.“</p><p>Damit ist das Tool so konfiguriert, dass es eine semantische Suche in unserem spezifischen Index durchführt. Nach dem Speichern steht es sofort zum Servieren bereit.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt011118f0a9279185/6a17f367dbb4ffc4f3fb581a/1eea079908fdf7cc72dbe81abd07ff51601a43d4-1472x1600.png" alt="Erstellung eines benutzerdefinierten Wissensdatenbank-Tools im Agent Builder." /><p>Bevor Sie es mit der Außenwelt verbinden, können Sie es direkt in der Benutzeroberfläche testen. Klicken Sie einfach auf die Schaltfläche <strong>„Testen“</strong> , um die Parameter manuell einzugeben und so das Verhalten des LLM zu simulieren. Überprüfen Sie anschließend die Ergebnisse, um sicherzustellen, dass alles ordnungsgemäß funktioniert.</p><h3>Schritt 2: Cursor mit dem Elastic MCP-Server verbinden</h3><p>Elastic Agent Builder stellt automatisch alle verfügbaren Tools über einen sicheren MCP-Endpunkt bereit. Ihre individuelle Server-URL finden Sie in der Tools-Benutzeroberfläche von Kibana.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdd0e62ae0f394c3d/6a17f368e317916ec32d5933/ba137be30f0eaa7f028b96bd8af4e2779c3f8a33-1600x589.png" alt="Wie verbinde ich den Cursor in der Tools-Benutzeroberfläche von Kibana mit dem Elastic MCP-Server?" /><p>Um eine Verbindung zu Cursor herzustellen, fügen wir einfach diese URL zusammen mit einem Elastic API Key zur Authentifizierung in die Konfigurationsdatei ein (<a href="https://www.elastic.co/docs/deploy-manage/api-keys/elasticsearch-api-keys">hier erfahren Sie, wie Sie einen ES API Key erstellen</a>). Wir verwenden einen API-Schlüssel zur Autorisierung, da dieser sicherstellt, dass die Tools nur mit den von Ihnen erteilten Berechtigungen ausgeführt werden und alle Ihre Zugriffskontrollregeln eingehalten werden.</p><p>Die MCP-Konfiguration in Cursors <code>~/.cursor/mcp.json</code> sieht folgendermaßen aus:</p>{
  "mcpServers": {
    "elastic-agent-builder": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://your-kibana.kb.company.io/api/agent_builder/mcp",
        "--header",
        "Authorization:${AUTH_HEADER}"
      ],
      "env": {
        "AUTH_HEADER": "ApiKey &lt;ELASTIC_API_KEY&gt;"
      }
    }
  }
}<p>Sobald die Konfiguration gespeichert ist, sollte das Elastic Agent Builder MCP-Servertool in Cursor verfügbar sein.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2837638263e628ed/6a17f36adbb4ffeb9cfb5820/d302c6d3609fbf14fd40e21b9e69e567bf12553f-1600x1002.png" alt="Ein Bild des Elastic Agent Builder MCP-Servertools, das in Cursor verfügbar ist." /><h3>Schritt 3: Fragen Sie einfach drauflos!</h3><p>Nachdem die Verbindung hergestellt wurde, können Cursor-Agenten nun Ihre benutzerdefinierten Tools aufrufen, um Ihre Fragen zu beantworten oder den Codegenerierungsprozess zu steuern.</p><p>Stellen wir eine konkrete Frage:</p><p><em>„Schritte zur Freigabe des Crawler-Dienstes in der internen Entwicklungsdokumentation der Elasticsearch-Organisation nachschlagen“</em></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt83fa357261b30e93/6a17f36c4b055d16d1432326/14f572730203c23615bb9dd38234bcb3b0f81155-1600x1468.png" alt="Cursor-Agenten rufen benutzerdefinierte Tools auf, um Fragen zu beantworten und den Codegenerierungsprozess zu steuern." /><p>Hinter den Kulissen geschieht die Magie:</p><ol><li><p>Der Cursor-Agent entscheidet, wie Ihre Frage am besten beantwortet werden kann, und beschließt, den/die/das … anzurufen. <code>engineering_documentation_internal_search</code></p></li><li><p>Es ruft das Tool mit einer natürlichsprachlichen Anfrage auf.</p></li><li><p>Das Tool führt eine semantische Suche im Index <code>elastic-dev-docs</code> durch und gibt die relevantesten und aktuellsten Prozeduren zurück.</p></li></ol><p>Wir erhalten eine präzise und verlässliche Antwort auf Basis unserer internen Dokumentation, ohne jemals den Code-Editor verlassen zu müssen. Das Erlebnis ist nahtlos und beeindruckend.</p><h2>Jetzt bist du an der Reihe zu bauen</h2><p>Sie haben nun gesehen, wie Sie den integrierten MCP-Server im Elastic Agent Builder verwenden können, um Ihre KI-Assistenten um einen sicheren Zugriff auf Ihre privaten Daten zu erweitern. Die Modelle auf eigenen Informationen zu basieren, ist der Schlüssel zu ihrer tatsächlichen Nützlichkeit.</p><p>Zusammenfassend haben wir die wichtigsten Schritte behandelt:</p><ul><li><p>Die Wahl des richtigen Protokolls für Ihre Bedürfnisse (MCP).</p></li><li><p>Entwicklung eines maßgeschneiderten Wissensdatenbank-Tools.</p></li><li><p>Verbindung dieses Tools mit einem IDE-Assistenten wie Cursor.</p></li></ul><p>Ihre Agenten und Tools müssen nicht länger von ihrem wichtigsten Kontext getrennt werden. Wir hoffen, dass Ihnen dieser Leitfaden dabei hilft, effektivere, datenbasierte Arbeitsabläufe zu erstellen. Viel Spaß beim Bauen!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elastic-mcp-server-agent-builder-tools</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elastic-mcp-server-agent-builder-tools</guid>
    <category><![CDATA[Agentische KI]]></category>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[KI-Tools ]]></category>
    <dc:creator><![CDATA[Jedr Blaszyk,Joe McElroy]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta5b61961b6269ab1/6a17f36ea29299d839d02db2/ef5153551a1d14833c7f512fede554d1dfb31553-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Mon, 20 Oct 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Evaluierung von KI-Agenten: Wie Elastic agentenbasierte Frameworks testet]]></title>
    <description><![CDATA[Erfahren Sie, wie wir Änderungen an einem agentenbasierten System bewerten und testen, bevor wir sie für Elastic-Benutzer freigeben, um genaue und überprüfbare Ergebnisse zu gewährleisten.]]></description>
    <content:encoded><![CDATA[<h2>Einleitung</h2><p>Im Elastic Stack gibt es viele LLM-gestützte agentenbasierte Anwendungen, wie zum Beispiel den kommenden Elastic AI Agent im<a href="https://www.elastic.co/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder"> Agent Builder</a> (derzeit in der technischen Vorschau) und <a href="https://www.elastic.co/docs/solutions/security/ai/attack-discovery">Attack Discovery</a> (<a href="https://www.elastic.co/blog/whats-new-elastic-security-9-0-0">GA</a> in 8.18 und 9.0+), und weitere sind in Arbeit. Während der Entwicklung und auch nach der Bereitstellung ist es wichtig, diese Fragen zu beantworten:</p><ul><li><p>Wie schätzen wir die Qualität der Antworten dieser KI-Anwendungen ein?</p></li><li><p>Wenn wir eine Änderung vornehmen, wie können wir garantieren, dass diese Änderung tatsächlich eine Verbesserung darstellt und keine Verschlechterung der Benutzererfahrung zur Folge hat?</p></li><li><p>Wie können wir diese Ergebnisse auf einfache und reproduzierbare Weise testen?</p></li></ul><p>Im Gegensatz zu herkömmlichen Softwaretests erfordert die Evaluierung von generativen KI-Anwendungen statistische Methoden, eine differenzierte qualitative Überprüfung und ein tiefes Verständnis der Ziele der Nutzer.</p><p>Dieser Artikel beschreibt detailliert den Prozess, den das Elastic-Entwicklerteam anwendet, um Evaluierungen durchzuführen, die Qualität der Änderungen vor der Bereitstellung sicherzustellen und die Systemleistung zu überwachen. Unser Ziel ist es, sicherzustellen, dass jede Änderung durch Beweise untermauert wird, was zu verlässlichen und nachvollziehbaren Ergebnissen führt. Ein Teil dieses Prozesses ist direkt in Kibana integriert und spiegelt damit unser Bekenntnis zu Transparenz als Teil unseres Open-Source-Ethos wider. Durch die offene Weitergabe von Teilen unserer Evaluierungsdaten und Kennzahlen wollen wir das Vertrauen der Community stärken und einen klaren Rahmen für alle bieten, die KI-Agenten entwickeln oder unsere Produkte nutzen.</p><h2>Produktbeispiele</h2><p>Die in diesem Dokument verwendeten Methoden bildeten die Grundlage für unsere iterative Weiterentwicklung und Verbesserung von Lösungen wie Attack Discovery und Elastic AI Agent. Eine kurze Vorstellung der beiden:</p><h3>Angriffserkennung von Elastic Security</h3><p>Attack Discovery verwendet LLMs, um Angriffssequenzen in Elastic zu identifizieren und zusammenzufassen. Anhand der Elastic Security-Warnmeldungen in einem bestimmten Zeitraum (standardmäßig 24 Stunden) ermittelt der agentenbasierte Workflow von Attack Discovery automatisch, ob ein oder mehrere Angriffe stattgefunden haben, sowie wichtige Informationen darüber, welcher Host oder welche Benutzer kompromittiert wurden und welche Warnmeldungen zu dieser Schlussfolgerung beigetragen haben.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb70932abe8d4de75/6a17f04ea292990c52d02d61/20fabb47642dad7b588daaaa8c3a98de860ad01d-1251x758.png" alt="" /><p></p><p>Ziel ist es, dass die LLM-basierte Lösung ein Ergebnis liefert, das mindestens so gut ist wie das eines Menschen.</p><h3>Elastischer KI-Agent</h3><p>Der <strong>Elastic Agent Builder</strong> ist unsere neue Plattform zum Erstellen kontextsensitiver KI-Agenten, die alle unsere Suchfunktionen nutzen. Es beinhaltet den <strong>Elastic AI Agent</strong>, einen vorkonfigurierten, universell einsetzbaren Agenten, der Benutzern dabei hilft, ihre Daten durch dialogbasierte Interaktion zu verstehen und Antworten darauf zu erhalten.</p><p>Der Agent erreicht dies, indem er automatisch relevante Informationen innerhalb von Elasticsearch oder verbundenen Wissensdatenbanken identifiziert und eine Reihe vorgefertigter Tools nutzt, um mit diesen zu interagieren. Dies versetzt den Elastic AI Agent in die Lage, auf ein breites Spektrum von Benutzeranfragen zu reagieren, von einfachen Fragen und Antworten zu einem einzelnen Dokument bis hin zu komplexen Anfragen, die eine Aggregation und ein- oder mehrstufige Suchvorgänge über mehrere Indizes hinweg erfordern.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3b9dbede85a56bd6/6a17f050e8fbce88943a1a30/d29dee100bb8a17bb623acd745773a5164a1df4f-1600x1014.png" alt="" /><h2>Verbesserungen durch Experimente messen</h2><p>Im Kontext von KI-Agenten ist ein Experiment eine strukturierte, testbare Änderung des Systems, die darauf abzielt, die Leistung in genau definierten Dimensionen (z. B. Hilfreichkeit, Korrektheit, Latenz) zu verbessern. Ziel ist es, die folgende Frage endgültig zu beantworten: „Wenn wir diese Änderung umsetzen, können wir dann garantieren, dass es sich um eine echte Verbesserung handelt und die Benutzererfahrung nicht verschlechtert wird?“</p><p>Die meisten unserer Experimente umfassen im Allgemeinen Folgendes:</p><ul><li><p><strong>Eine Hypothese:</strong> Eine spezifische und widerlegbare Behauptung. <em>Beispiel:</em> „Das Hinzufügen des Zugriffs auf ein Tool zur Angriffserkennung verbessert die Korrektheit sicherheitsrelevanter Abfragen.“</p></li><li><p><strong>Erfolgskriterien:</strong> Klare Schwellenwerte, die definieren, was „Erfolg“ bedeutet. <em>Beispiel:</em> „+5 % Verbesserung der Korrektheitsbewertung im Sicherheitsdatensatz, keine Verschlechterung in anderen Bereichen.“</p></li><li><p><strong>Evaluierungsplan:</strong> Wie wir den Erfolg messen (Kennzahlen, Datensätze, Vergleichsmethode)</p></li></ul><p>Ein erfolgreiches Experiment ist ein systematischer Forschungsprozess. Jede Änderung, von einer kleinen, spontanen Anpassung bis hin zu einer grundlegenden architektonischen Umgestaltung, durchläuft diese sieben Schritte, um sicherzustellen, dass die Ergebnisse aussagekräftig und umsetzbar sind:</p><ul><li><p>Schritt 1: Identifizieren Sie das Problem</p></li><li><p>Schritt 2: Kennzahlen definieren</p></li><li><p>Schritt 3: Formulieren Sie eine klare Hypothese</p></li><li><p>Schritt 4: Vorbereitung des Auswertungsdatensatzes</p></li><li><p>Schritt 5: Führen Sie das Experiment durch.</p></li><li><p>Schritt 6: Ergebnisse analysieren + wiederholen</p></li><li><p>Schritt 7: Treffen Sie eine Entscheidung und dokumentieren Sie diese.</p></li></ul><p>Ein Beispiel für diese Schritte ist in <em>Abbildung 1</em> dargestellt. In den folgenden Unterabschnitten werden die einzelnen Schritte erläutert, und die technischen Details der einzelnen Schritte werden wir in den folgenden Dokumenten genauer ausführen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt06bfe2f0e4205a18/6a17f052faa91358eb93c968/3a9f5a3e92dd4922a795a19104c6e4ad8c98958d-2400x1352.png" alt="" /><h2>Schrittweise Anleitung mit echten Elastic-Beispielen</h2><h3>Schritt 1: Identifizieren Sie das Problem</h3><p><em>Welches Problem soll durch diese Änderung genau gelöst werden?</em></p><p>Beispiel für die Angriffserkennung: Die Zusammenfassungen sind gelegentlich unvollständig, oder harmlose Aktivitäten werden fälschlicherweise als Angriff eingestuft (falsch positive Ergebnisse).</p><p>Beispiel für einen Elastic AI Agent: Die Werkzeugauswahl des Agenten, insbesondere bei analytischen Abfragen, ist suboptimal und inkonsistent, was häufig dazu führt, dass das falsche Werkzeug ausgewählt wird. Dies wiederum erhöht die Tokenkosten und die Latenz.</p><h3>Schritt 2: Kennzahlen definieren</h3><p><em>Das Problem muss messbar gemacht werden, damit wir eine Veränderung mit dem aktuellen Zustand vergleichen können.</em></p><p>Gängige Metriken sind <a href="https://developers.google.com/machine-learning/crash-course/classification/accuracy-precision-recall">Präzision und Trefferquote</a>, <a href="https://en.wikipedia.org/wiki/Semantic_similarity">semantische Ähnlichkeit</a>, Faktentreue usw. Je nach Anwendungsfall verwenden wir Code-Checks, um die Metriken zu berechnen, wie z. B. übereinstimmende Alarm-IDs oder korrekt abgerufene URLs, oder wir verwenden Techniken wie LLM-as-judge für freiere Antworten.</p><p>Nachfolgend sind einige (<em>nicht vollständige</em>) Beispielmetriken aufgeführt, die in den Experimenten verwendet wurden:</p><p><strong>Angriffserkennung</strong></p><p>Metrisch</p><p>Beschreibung</p><p>Präzision und Rückruf</p><p>Vergleichen Sie die Alarm-IDs zwischen tatsächlichen und erwarteten Ausgaben, um die Erkennungsgenauigkeit zu messen.</p><p>Ähnlichkeit</p><p>Verwenden Sie BERTScore, um die semantische Ähnlichkeit des Antworttextes zu vergleichen.</p><p>Faktentreue</p><p>Sind wichtige IOCs (Indikatoren für eine Kompromittierung) vorhanden? Werden die MITRE-Taktiken (Branchenklassifizierung von Angriffen) korrekt abgebildet?</p><p>Konsistenz der Angriffskette</p><p>Vergleichen Sie die Anzahl der Entdeckungen, um festzustellen, ob der Angriff über- oder untererfasst gemeldet wurde.</p><p><strong>Elastischer KI-Agent</strong></p><p>Metrisch</p><p>Beschreibung</p><p>Präzision und Rückruf</p><p>Um die Genauigkeit des Informationsabrufs zu messen, werden die vom Agenten abgerufenen Dokumente/Informationen mit den tatsächlich benötigten Informationen oder Dokumenten abgeglichen, die zur Beantwortung der Anfrage erforderlich sind.</p><p>Faktentreue</p><p>Sind die zur Beantwortung der Benutzeranfrage erforderlichen Schlüsselinformationen vorhanden? Sind die Fakten in der richtigen Reihenfolge für verfahrenstechnische Anfragen?</p><p>Relevanz der Antwort</p><p>Enthält die Antwort Informationen, die für die Benutzeranfrage nebensächlich oder nicht relevant sind?</p><p>Vollständigkeit der Antwort</p><p>Beantwortet die Antwort alle Teile der Benutzeranfrage? Enthält die Antwort alle Informationen, die auch in den Referenzdaten vorhanden sind?</p><p>ES|QL-Validierung</p><p>Ist der generierte ES|QL-Code syntaktisch korrekt? Ist es funktional identisch mit dem tatsächlichen ES|QL-Standard?</p><h3>Schritt 3: Formulieren Sie eine klare Hypothese</h3><p><em>Legen Sie anhand des Problems und der oben definierten Kennzahlen klare Erfolgskriterien fest.</em></p><p>Beispiel für einen elastischen KI-Agenten:</p><ol><li><p>Nehmen Sie <strong>Änderungen an den Beschreibungen der Tools relevance_search und nl_search vor, um deren spezifische Funktionen und Anwendungsfälle klar zu definieren</strong>.</p></li><li><p>Wir gehen davon aus, dass wir <strong>die</strong> <strong>Genauigkeit</strong> unserer Tool-Aufrufe um <strong>25 %</strong> verbessern werden.</p></li><li><p>Wir werden überprüfen, ob dies insgesamt positiv ist, indem wir sicherstellen, dass es keine negativen Auswirkungen auf andere Kennzahlen gibt, z. B. <strong>Faktentreue und Vollständigkeit</strong>.</p></li><li><p>Wir glauben, dass dies funktionieren wird, da <strong>präzise Werkzeugbeschreibungen dem Agenten helfen, das am besten geeignete Suchwerkzeug für verschiedene Anfragetypen genauer auszuwählen und anzuwenden, wodurch Fehlanwendungen reduziert und die Gesamteffektivität der Suche verbessert wird</strong>.</p></li></ol><h3>Schritt 4: Vorbereitung des Auswertungsdatensatzes</h3><p><em>Um die Leistungsfähigkeit des Systems zu messen, verwenden wir Datensätze, die realweltliche Szenarien abbilden.</em></p><p>Je nach Art der durchgeführten Evaluierung benötigen wir möglicherweise unterschiedliche Datenformate, wie z. B. Rohdaten, die einem LLM zugeführt werden (z. B. Angriffsszenarien für die Angriffserkennung) und erwartete Ergebnisse. Wenn es sich bei der Anwendung um einen Chatbot handelt, dann können die Eingaben Benutzeranfragen sein und die Ausgaben korrekte Chatbot-Antworten, korrekte Links, die er hätte abrufen sollen, und so weiter.</p><p>Beispiel für Angriffserkennung:</p><p>10 neuartige Angriffsszenarien</p><p>8 Folgen von Oh My Malware (ohmymalware.com)</p><p>4 Szenarien mit mehreren Angriffen (entstanden durch die Kombination von Angriffen aus den ersten beiden Kategorien)</p><p>3 harmlose Szenarien</p><p>Beispiel eines Evaluierungsdatensatzes für Elastic AI-Agenten (<a href="https://github.com/elastic/kibana/blob/main/x-pack/platform/packages/shared/onechat/kbn-evals-suite-onechat/evals/kb/kb.spec.ts">Kibana-Datensatzlink</a>):</p><p>14 Indizes, die Open-Source-Datensätze verwenden, um mehrere Quellen in KB zu simulieren.</p><p>5 Abfragetypen (analytisch, Textabfrage, hybrid…)</p><p>7 Arten von Abfrageabsichten (prozedural, faktisch - Klassifizierung, investigativ; …)</p><h3>Schritt 5: Führen Sie das Experiment durch.</h3><p>Führen Sie das Experiment durch, indem Sie Antworten sowohl vom bestehenden Agenten als auch von der modifizierten Version gegen den Evaluierungsdatensatz generieren. Berechnen Sie Kennzahlen wie Faktentreue (siehe Schritt 2).</p><p>Wir kombinieren verschiedene Auswertungen auf Basis der in Schritt 2 geforderten Kennzahlen:</p><ul><li><p>Regelbasierte Auswertung (z. B. (mit Python/TypeScript prüfen, ob die .json-Datei gültig ist)</p></li><li><p>LLM als Richter (Befragung eines anderen LLM, ob eine Antwort sachlich mit einem Quelldokument übereinstimmt)</p></li><li><p>Menschliche Beteiligung an der Qualitätsprüfung zur Feinabstimmung</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt17ec63af0850d8dd/6a17f054505ac3e508ad8c1e/8648e75818d3291f0ac66f069438a500d42b8225-1600x1099.png" alt="Dies ist ein Beispiel für ein Auswertungsergebnis, das von unserem internen Framework generiert wurde. Es werden verschiedene Kennzahlen aus einem Experiment vorgestellt, das mit unterschiedlichen Datensätzen durchgeführt wurde." /><h3>Schritt 6: Ergebnisse analysieren + wiederholen</h3><p>Nachdem wir nun die Kennzahlen haben, analysieren wir die Ergebnisse. <u><em>Auch wenn die Ergebnisse die in Schritt 3 definierten Erfolgskriterien erfüllen, werden wir vor der Übernahme der Änderung in die Produktionsumgebung noch eine manuelle Überprüfung durchführen</em></u>; wenn die Ergebnisse die Kriterien nicht erfüllen, werden die Probleme behoben und anschließend die Auswertungen der neuen Änderung durchgeführt.</p><p>Wir gehen davon aus, dass einige Iterationen nötig sein werden, um die beste Änderung vor dem Zusammenführen zu finden. Ähnlich wie bei der Durchführung lokaler Softwaretests vor dem Pushen eines Commits können Offline-Evaluierungen mit lokalen Änderungen oder mehreren vorgeschlagenen Änderungen durchgeführt werden. Es ist hilfreich, das Speichern von Experimentergebnissen, Gesamtergebnissen und Visualisierungen zu automatisieren, um die Analyse zu optimieren.</p><h3>Schritt 7: Treffen Sie eine Entscheidung und dokumentieren Sie diese.</h3><p>Auf Basis eines Entscheidungsrahmens und Akzeptanzkriterien wird über die Übernahme der Änderung entschieden und das Experiment dokumentiert. Die Entscheidungsfindung ist vielschichtig und kann Faktoren berücksichtigen, die über den Auswertungsdatensatz hinausgehen, wie z. B. die Prüfung auf Regressionsszenarien in anderen Datensätzen oder die Abwägung des Kosten-Nutzen-Verhältnisses einer vorgeschlagenen Änderung.</p><p>Beispiel: Nach dem Testen und Vergleichen einiger Iterationen wählen Sie die Änderung mit der höchsten Punktzahl aus und senden sie zur Genehmigung an Produktmanager und andere relevante Stakeholder. Fügen Sie die Ergebnisse der vorherigen Schritte bei, um die Entscheidungsfindung zu erleichtern. Weitere Beispiele zum Thema Angriffserkennung finden Sie <a href="https://www.elastic.co/blog/elastic-security-generative-ai-features">unter Hinter den Kulissen der generativen KI-Funktionen von Elastic Security</a>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt62a466f3a0da114a/6a17f056faa91342c393c96c/74c80b8f34dce8ddd20873ecb2f553873587ed35-1600x618.png" alt="" /><h2>Fazit</h2><p>In diesem Blog haben wir den gesamten Ablauf eines Experiment-Workflows durchlaufen und veranschaulicht, wie wir Änderungen an einem agentenbasierten System bewerten und testen, bevor wir sie für Elastic-Benutzer freigeben. Wir haben auch einige Beispiele für die Verbesserung agentenbasierter Arbeitsabläufe in Elastic vorgestellt. In nachfolgenden Blogbeiträgen werden wir die Details verschiedener Schritte genauer erläutern, beispielsweise wie man einen guten Datensatz erstellt, wie man zuverlässige Metriken entwirft und wie man Entscheidungen trifft, wenn mehrere Metriken involviert sind.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ai-agent-evaluation-elastic</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ai-agent-evaluation-elastic</guid>
    <category><![CDATA[Agentische KI]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Susan Chang,Abhimanyu Anand]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte578b636637be6b1/6a17f057e8fbcebe9e3a1a36/ef3922076713872163e1aab47735361513b2c9ee-2400x1352.heif" length="0" type="image/*"/>
    <pubDate>Mon, 13 Oct 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Verbindung von Elastic Agents mit Gemini Enterprise über das A2A-Protokoll]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie mit Agent Builder Ihren benutzerdefinierten Elastic Agent externen Diensten wie Gemini Enterprise mithilfe des A2A-Protokolls zugänglich machen.]]></description>
    <content:encoded><![CDATA[<p><strong>Elastic Agent Builder</strong> ist eine Reihe von Funktionen zur Erstellung datengesteuerter KI-Agenten direkt in Elasticsearch. In früheren Beiträgen dieser <a href="https://www.elastic.co/search-labs/blog/series/context-aware-ai-agentic-workflows-with-elastic">Reihe</a> haben wir gezeigt, wie man benutzerdefinierte Agenten mit Werkzeugen ausstattet, um komplexe Aufgaben auszuführen, und ihnen eine Reihe benutzerdefinierter Anweisungen zur Verfügung stellt, um ihr Verhalten zu steuern.</p><p>Was aber, wenn Sie Ihre benutzerdefinierten Agenten mit den Anwendungen und Produktivitätstools verwenden möchten, auf die Sie bereits angewiesen sind?</p><p>Hier kommt das <strong>Agent-to-Agent (A2A)-Protokoll</strong> ins Spiel. A2A ist ein <a href="https://github.com/a2aproject/A2A">offener Standard</a> für Interoperabilität, der es Agenten verschiedener Plattformen ermöglicht, miteinander zu kommunizieren und zusammenzuarbeiten. Und wir haben es direkt in den Elastic Agent Builder integriert.</p><p>Heute zeigen wir Ihnen, wie Sie einen von Ihnen erstellten benutzerdefinierten Agenten anderen Diensten, insbesondere <strong>Gemini Enterprise </strong>(ehemals Agentspace), zugänglich machen können.</p><h2>Die Macht offener Standards: Warum A2A wichtig ist</h2><p>Im Blogbeitrag <a href="https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch">„Ihr erster Elastic Agent“</a> haben wir gezeigt, wie man benutzerdefinierte Agenten erstellt, zum Beispiel einen <em>Finanzassistenten</em> -Agenten mit sicherem Zugriff auf Ihre Marktdaten. Sein Nutzen ist jedoch begrenzt, wenn Sie die gewonnenen Erkenntnisse nicht auch in anderen Umgebungen wie Gemini Enterprise nutzen können, ohne Ihre Arbeit neu aufbauen zu müssen.</p><p>Diese Herausforderung der Interoperabilität ist es, die agentenbasierte KI zurückhält. Agenten benötigen eine gemeinsame Sprache, um plattformübergreifend zu kommunizieren. Genau diese Rolle übernimmt das A2A-Protokoll. Es bietet eine standardisierte Kommunikationsschicht, die es Ihnen nicht nur ermöglicht, direkt mit Ihrem Agenten zu interagieren, sondern auch eine Zukunft eröffnet, in der spezialisierte Agenten in Ihrem gesamten Unternehmen zusammenarbeiten und Erkenntnisse austauschen können.</p><p>Um dies zu ermöglichen, unterstützt der Elastic Agent Builder das A2A-Protokoll nativ über zwei Standardendpunkte für alle Ihre Agenten:</p><ol><li><p><strong>Der Agent Card-Endpunkt (</strong><strong><code>GET {your-kibana-url}/api/agent_builder/a2a/{agentId}.json</code></strong><strong>) - </strong>Dieser dient als Visitenkarte Ihres individuellen Agenten. Es stellt Metadaten über Ihren Agenten (Name, Beschreibung, Fähigkeiten usw.) für jeden A2A-kompatiblen Dienst bereit.</p></li><li><p><strong>Der A2A-Protokollendpunkt (</strong><strong><code>POST {your-kibana-url}/api/agent_builder/a2a/{agentId}</code></strong><strong>)</strong> - Dies ist der Kommunikationskanal. Andere Agenten senden ihre Anfragen hierher, Ihr Agent verarbeitet sie und sendet eine Antwort zurück, alles gemäß der <a href="https://a2a-protocol.org/latest/specification/">A2A-Protokollspezifikation</a>.</p></li></ol><h2>Testen Sie Ihren Makler mit dem A2A-Inspektor.</h2><p>Bevor wir unseren Agenten mit einem Produktionssystem verbinden, sollten wir überprüfen, ob die Kommunikation korrekt funktioniert. Am einfachsten geht das mit dem <strong>A2A Inspector</strong>, einem Tool, das speziell für das Testen und Debuggen von A2A-Integrationen entwickelt wurde.</p><p>Die Inbetriebnahme des Inspektors ist unkompliziert. Sie können das <a href="https://github.com/a2aproject/a2a-inspector">a2a-inspector-</a> Repository klonen und den Anweisungen in der README-Datei folgen, um <a href="https://github.com/a2aproject/a2a-inspector?tab=readme-ov-file#3-run-the-application">die Anwendung auszuführen</a>. Nach dem Start ist die Benutzeroberfläche standardmäßig unter <code>http://localhost:5001/</code> verfügbar.</p><p>Um den A2A-Inspektor mit Ihrem Makler zu verbinden, müssen Sie zwei wichtige Informationen angeben:</p><ul><li><p>Agentenkarten-URL: Dies ist der Endpunkt, der Ihren Agenten beschreibt. Für den <a href="https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch">Finanzassistenten-Agenten aus unserem vorherigen Beitrag</a> lautet diese URL <code>{your-kibana-url}/api/agent_builder/a2a/financial_assistant.json</code>.</p></li><li><p>Authentifizierungsheader: Wir verwenden einen Standard-API-Schlüssel zur Authentifizierung.</p></li></ul><p>Sobald Sie diese Angaben in der Benutzeroberfläche des Inspektors eingegeben haben, können Sie sich mit Ihrem Agenten verbinden und sofort mit ihm chatten.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6381135e3fb297df/6a17ef4bec0f898b0c5a66ea/7231c72bf30bed2a854f58658c1eca2843f43bfc-1600x1296.png" alt="Einrichtung der A2A-Agentenkarte und des Agenteninspektors" /><p>Diese einfache Validierung gibt uns die Gewissheit, dass unser Agent korrekt konfiguriert ist und für den nächsten Schritt bereit ist.</p><h2>Geh live! Ihr persönlicher Kundenbetreuer in Gemini Enterprise</h2><p>Und nun zum spannenden Teil: die Umsetzung unseres maßgeschneiderten Finanzberateragenten in Gemini Enterprise (ehemals Agentspace). Diese Integration wird durch den <a href="https://console.cloud.google.com/marketplace/product/elastic-prod/elastic-ai-agent">Elastic AI Agent ermöglicht, der auf dem Google Cloud Marketplace verfügbar ist</a>.</p><p>Nach der Verbindungsherstellung nutzt Gemini Enterprise das A2A-Protokoll, um direkt mit Ihrem Agenten zu kommunizieren. Hier zeigt sich die wahre Stärke der Interoperabilität: Benutzer können nun auf die tiefgreifenden, datengestützten Erkenntnisse Ihres benutzerdefinierten Elasticsearch-Agenten zugreifen, ohne jemals ihre gewohnte Umgebung verlassen zu müssen. Sie können Ihren benutzerdefinierten Elastic Agent in der Agentenliste sehen:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7f54f0bb15216d8e/6a17ef4d6df73107d90a0fdb/37a39e92ebf3d72c6c8014397cd8e846336173a4-1600x834.png" alt="Anzeigen eines benutzerdefinierten Agenten in einer Google Agentspace-Liste" /><p>Stellen Sie sich einen Benutzer in Gemini Enterprise vor, der Folgendes fragt:</p><p><em>„Ich bin besorgt über die Marktstimmung. Können Sie mir zeigen, welche unserer Kunden am stärksten von schlechten Nachrichten betroffen sein könnten?</em> “</p><p>Im Hintergrund leitet Gemini Enterprise diese Anfrage über das A2A-Protokoll an Ihren benutzerdefinierten Elastic Agent weiter. Ihr Agent verwendet dann seine spezialisierten Tools, um Ihre Daten abzufragen, eine Antwort zu formulieren und diese zurückzusenden. Für den Endnutzer ist das Erlebnis nahtlos.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte130c332ee0648a6/6a17ef4fe9ea874426a9c6bb/e5f126c1a27a51c6e69a767aa87c9f746b62e39c-1600x1044.png" alt="Ein Benutzer stellt Agentspace eine Anfrage und was geschieht mit dieser Anfrage im Hintergrund?" /><p>Und das ist noch nicht alles! Die mit dem Elastic-Agenten erhaltene Antwort kann nun als Kontext für Ihre nächsten Fragen verwendet werden, die möglicherweise einen anderen spezialisierten Agenten auslösen (z. B. (Ihr Investmentplattform-Agent passt das Engagement in börsennotierten Unternehmen an.) Alles, ohne die Suchleiste zu verlassen.</p><p>Mit Ihren Elastic-Agenten, die auf Gemini Enterprise mit A2A bereitgestellt werden, können Sie Zugriff, Orchestrierung und Workflows vereinheitlichen und Reibungsverluste zwischen KI-, Such- und Unternehmenssystemen beseitigen, indem Sie eine einzige Benutzeroberfläche anbieten, über die Benutzer mit ihren Daten und Tools interagieren können – alles im Kontext. Für die Anwender bedeutet das weniger Werkzeugwechsel und intuitivere, leistungsfähigere KI-Assistenten. Für Organisationen bedeutet dies eine integrierte, kohärente Governance, Skalierbarkeit und Interoperabilität.</p><h2>Jetzt sind Sie am Zug.</h2><p>Sie verfügen nun über die Werkzeuge, um Ihre Elastic Agents überall verfügbar zu machen. Durch die Nutzung des offenen A2A-Protokolls können Sie die Reichweite Ihrer benutzerdefinierten, datenorientierten Agenten erweitern.</p><p>In diesem Beitrag haben wir Ihnen die wichtigsten Schritte erläutert:</p><ul><li><p>Bereitstellung Ihres Agenten über die A2A Agent Card und Protocol Endpunkte.</p></li><li><p>Testen der Verbindung mit dem A2A Inspector.</p></li><li><p>Integration Ihres Agenten live in einen externen Dienst wie Googles Gemini Enterprise.</p></li></ul><p>Ihre Agenten müssen nicht länger isoliert werden. Wir freuen uns schon sehr auf die leistungsstarken, vernetzten Systeme, die Sie entwickeln werden. Viel Spaß beim Bauen!</p><p>Am einfachsten gelingt der Einstieg mit Ihrer kostenlosen Elastic Cloud-Testversion auf <a href="https://console.cloud.google.com/marketplace/product/elastic-prod/elastic-cloud?pli=1">dem Google Cloud Marketplace.</a></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/a2a-protocol-elastic-agent-builder-gemini-enterprise</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/a2a-protocol-elastic-agent-builder-gemini-enterprise</guid>
    <category><![CDATA[Agentische KI]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Jedr Blaszyk,Valerio Arvizzigno,Joe McElroy]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt63d7675adc5bc211/6a17ef51ddf97d38e8910bdf/5be8a425fab55dca2f9717d2e50812b0450fa625-1440x840.png" length="0" type="image/png"/>
    <pubDate>Thu, 09 Oct 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Ihr erster Elastic Agent: Von einer einzelnen Anfrage bis zum KI-gestützten Chat]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie mit dem AI Agent Builder von Elastic spezialisierte KI-Agenten erstellen können. In diesem Blogbeitrag entwickeln wir einen KI-gestützten Finanzagenten.]]></description>
    <content:encoded><![CDATA[<p>Mit dem neuen <a href="https://www.elastic.co/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder">Agent Builder</a> von Elastic können Sie spezialisierte KI-Agenten erstellen, die als Experten für Ihre spezifischen Geschäftsbereiche fungieren. Diese Funktion geht über einfache Dashboards und Suchleisten hinaus und verwandelt Ihre Daten von einer passiven Ressource in einen aktiven, dialogfähigen Partner.</p><p>Stellen Sie sich einen Finanzmanager vor, der sich vor einem Kundengespräch schnell einarbeiten muss. Statt manuell Newsfeeds zu durchforsten und Portfolio-Dashboards abzugleichen, können sie ihrem individuell entwickelten Agenten jetzt einfach eine direkte Frage stellen. Das ist der Vorteil eines „Chat-First“-Ansatzes. Der Manager hat einen direkten, dialogorientierten Draht zu seinen Daten und fragt beispielsweise: „Was gibt es Neues zu ACME Corp und wie wirkt sich das auf die Anlagen meines Kunden aus?“ und innerhalb von Sekunden eine zusammengefasste Expertenantwort zu erhalten.</p><p>Während wir heute einen Finanzexperten aufbauen, sind die Anwendungsbereiche so vielfältig wie Ihre Daten. Mit der gleichen Macht kann ein Cybersicherheitsanalyst zur Suche nach Bedrohungen, ein Site Reliability Engineer zur Diagnose eines Ausfalls oder ein Marketingmanager zur Optimierung einer Kampagne geschaffen werden. Unabhängig vom Fachgebiet bleibt die Kernmission dieselbe: Ihre Daten in einen Spezialisten zu verwandeln, mit dem Sie sich unterhalten können.</p><h2>Schritt 0: Unser Datensatz</h2><p>Unser heutiger Datensatz ist ein synthetischer, auf Finanzdaten basierender Datensatz, der aus Finanzkonten, Vermögenspositionen, Nachrichten und Finanzberichten besteht. Er ist zwar synthetisch, repliziert aber eine vereinfachte Version eines realen Finanzdatensatzes.</p><p><code>financial_accounts</code>Kundenportfolios mit Risikoprofilen</p><p><code>financial_holdings</code>: Aktien-/ETF-/Anleihenpositionen mit Kaufhistorie</p><p><code>financial_asset_details</code>Details zur Aktie/zum ETF/zur Anleihe</p><p><code>financial_news</code>: KI-generierte Marktartikel mit Stimmungsanalyse</p><p><code>financial_reports</code>Unternehmensgewinne und Analystennotizen</p><p>Sie können diesen Datensatz selbst laden, indem Sie der beigefügten Anleitung in <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/your-first-elastic-agent/Your_First_Elastic_Agent.ipynb">diesem</a> Notebook folgen.</p><h2>Schritt 1: Die Grundlage – Ihre Geschäftslogik als ES|QL</h2><p>Jede KI-Fähigkeit beginnt mit einer soliden Logik. Unserem Financial Manager-Agenten müssen wir beibringen, wie er eine häufig gestellte Frage beantworten kann: „Ich bin besorgt über die Marktstimmung.“ Können Sie mir zeigen, welche unserer Kunden am stärksten von schlechten Nachrichten bedroht sind? Diese Frage geht über eine einfache Suche hinaus. Dies erfordert von uns, die Marktstimmung mit den Kundenportfolios in Zusammenhang zu bringen.</p><p>Wir müssen die in den negativen Artikeln erwähnten Vermögenswerte finden, jeden Kunden identifizieren, der diese Vermögenswerte hält, den aktuellen Marktwert seines Engagements berechnen und dann die Ergebnisse nach dem höchsten Risiko ordnen. Diese komplexe Analyse mit mehreren Verknüpfungen ist die perfekte Aufgabe für unser hochentwickeltes ES|QL-Tool.</p><p>Hier ist die vollständige Abfrage, die wir verwenden werden. Es sieht beeindruckend aus, aber die Konzepte sind einfach.</p><h2>Aufschlüsselung: Verbindungen und Leitplanken</h2><p>Bei dieser Abfrage spielen zwei wichtige Konzepte eine Rolle, die den Agent Builder ausmachen.</p><h3>1. Die LOOKUP JOIN-Funktion</h3><p>Seit Jahren gehört die Möglichkeit, Daten aus verschiedenen Indizes anhand eines gemeinsamen Schlüssels zu verknüpfen, zu den am häufigsten nachgefragten Funktionen von Elasticsearch. Mit ES|QL ist das jetzt mit <code>LOOKUP JOIN</code> möglich.</p><p>In unserer neuen Abfrage führen wir eine Kette von drei <code>LOOKUP JOIN</code> durch: Zuerst verbinden wir negative Nachrichten mit Vermögensdetails, dann verknüpfen wir diese Vermögenswerte mit den Kundenbeständen und schließlich fügen wir sie zu den Kontoinformationen des Kunden hinzu. Dadurch wird mit einer einzigen, effizienten Abfrage ein unglaublich reichhaltiges Ergebnis aus vier verschiedenen Indizes erzeugt. Das bedeutet, dass wir unterschiedliche Datensätze kombinieren können, um eine einzige, aussagekräftige Antwort zu erhalten, ohne vorher alle unsere Daten in einen einzigen riesigen Index denormalisieren zu müssen.</p><h3>2. Parameter als LLM-Leitplanken</h3><p>Sie werden feststellen, dass die Abfrage <code>?time_duration</code> verwendet. Das ist nicht nur eine Variable; es ist eine Leitplanke für die KI. Während große Sprachmodelle (LLMs) hervorragend darin sind, Abfragen zu generieren, kann es zu ineffizienten oder sogar falschen Abfragen führen, wenn man ihnen freie Hand bei der Daten lässt.</p><p>Durch die Erstellung einer parametrisierten Abfrage zwingen wir das LLM dazu, innerhalb der getesteten, effizienten und korrekten Geschäftslogik zu arbeiten, die ein menschlicher Experte bereits definiert hat. Das ist vergleichbar damit, wie Entwickler seit Jahren Suchvorlagen verwenden, um Abfragefunktionen sicher für Anwendungen bereitzustellen. Der Agent kann eine Benutzeranfrage wie "diese Woche" interpretieren, um den Parameter <code>time_duration</code> zu füllen, muss aber unsere Abfragestruktur verwenden, um die Antwort zu erhalten. Dadurch erhalten wir die perfekte Balance zwischen Flexibilität und Kontrolle.</p><p>Letztendlich ermöglicht diese Abfrage einem Experten, der die Daten versteht, sein Wissen in einem Werkzeug zu kapseln. Andere Personen – und KI-Agenten – können dieses Werkzeug dann nutzen, um korrelierte Ergebnisse zu erhalten, indem sie einfach einen einzigen Parameter angeben, ohne etwas über die zugrunde liegende Komplexität wissen zu müssen.</p><h2>Schritt 2: Die Fertigkeit – Eine Abfrage in ein wiederverwendbares Werkzeug umwandeln</h2><p>Eine ES|QL-Abfrage ist nur Text, bis wir sie als <strong>Werkzeug</strong> registrieren. Im Agent Builder ist ein Tool mehr als nur eine gespeicherte Abfrage; es ist eine „Fähigkeit“, die ein KI-Agent verstehen und einsetzen kann. Der Zauber liegt in der von uns bereitgestellten <strong>Beschreibung in natürlicher Sprache</strong> . Diese Beschreibung bildet die Brücke zwischen der Frage eines Benutzers und der zugrunde liegenden Abfragelogik. Registrieren wir nun die soeben erstellte Abfrage.</p><h3>Der UI-Pfad</h3><p>Das Erstellen eines Tools in Kibana ist ein unkomplizierter Prozess.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte73e11c1d87593fa/6a17f2134202294dae29f6f2/a29c53a73b99af5972273c51218ea9004a9b0abb-1600x812.png" alt="Wie man ein Tool in Kibana erstellt." /><p>1. Navigieren Sie zu <strong>Agenten</strong></p><ul><li><p>Klicken Sie auf<strong> „Tools“</strong>oder <strong>„Tools verwalten“</strong> und klicken Sie dann auf die Schaltfläche <strong>„Neues Tool“</strong> .</p></li></ul><p>2. Füllen Sie das Formular mit folgenden Angaben aus:</p><ul><li><p><strong>Werkzeug-ID:</strong> <code>find_client_exposure_to_negative_news</code></p></li></ul><p>             ich. Dies ist die eindeutige ID des Tools.</p><ul><li><p><strong>Beschreibung:</strong> "Ermittelt das Risiko negativer Nachrichten im Kundenportfolio." Dieses Tool durchsucht aktuelle Nachrichten und Berichte nach negativen Stimmungen, identifiziert den zugehörigen Vermögenswert und findet alle Kunden, die diesen Vermögenswert halten. Es liefert eine nach dem aktuellen Marktwert der Position sortierte Liste zurück, um das höchste potenzielle Risiko hervorzuheben.“</p></li></ul><p>             ich. Dies ist das, was der LLM liest, um zu entscheiden, ob dieses Werkzeug das richtige für die Aufgabe ist.</p><ul><li><p><strong>Labels</strong>: <code>retrieval</code> and <code>risk-analysis</code></p></li></ul><p>         Etiketten dienen dazu, mehrere Werkzeuge zu gruppieren.</p><ul><li><p><strong>Konfiguration:</strong> Fügen Sie die vollständige ES|QL-Abfrage aus Schritt 1 ein.</p></li></ul><p>            ich. Dies ist die Suche, die der Agent verwenden wird.</p><p>3. Klicken Sie auf <strong>„Parameter aus Abfrage ableiten“</strong>. Die Benutzeroberfläche wird <code>?time_duration</code> automatisch finden und unten auflisten. Fügen Sie für jedes Element eine kurze Beschreibung hinzu, damit der Agent (und andere Benutzer) dessen Zweck verstehen können.</p><ul><li><p><code>time_duration</code>Der Zeitraum, in dem nach negativen Nachrichten gesucht wird. Format ist "X Stunden", Standardwert: 8760 Stunden</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7afbb0589c1828ad/6a17f2146864a44e7cb688a9/deb422d97863f78dbe08bfa2e3c708d1f75166ff-1600x938.png" alt="Konfigurieren Sie Ihr Tool einschließlich seiner Logik und aller benötigten Parameter mithilfe einer ESQL-Abfrage. " /><p>4. Probier es aus!</p><ul><li><p>Klicken Sie auf Speichern &amp; Testen.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfd09afbef6e21a93/6a17f2162f4a5c73b1fa89fd/57e768b88327821e70bd616744822f98fa367362-732x136.png" alt="Der gleiche &amp; Test-Button in Kibana." /><ul><li><p>Es wird ein neues Flyout angezeigt, in dem Sie die Abfrage testen können, um sicherzustellen, dass sie wie erwartet funktioniert.</p></li></ul><p>             ich. Geben Sie in <code>time_duration</code> den gewünschten Bereich ein, hier verwenden wir „8760 Stunden“.</p><ul><li><p>Klicken Sie auf „Absenden“, und wenn alles gut geht, erhalten Sie eine JSON-Antwort. Um sicherzustellen, dass es wie erwartet funktioniert, scrollen Sie nach unten und sehen Sie sich das Objekt <code>values</code> an. Dort werden die eigentlichen übereinstimmenden Dokumente zurückgegeben.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt89bdc3f093363f2a/6a17f217be60861c9c00488a/7e0c5171a4f7ffdfc1830f1a05a9acb987870b75-1600x722.png" alt="JSON-Antwort, die nach dem Klicken auf „Absenden“ erscheint." /><p>5. Klicken Sie auf das „X“ oben rechts, um das Testfenster zu schließen. Ihr neues Tool wird nun in der Liste angezeigt und kann einem Agenten zugewiesen werden.</p><h3>Der API-Pfad</h3><p>Für Entwickler, die Automatisierung bevorzugen oder Tools programmatisch verwalten müssen, lässt sich dasselbe Ergebnis mit einem einzigen API-Aufruf erzielen. Senden Sie einfach eine <code>POST</code> -Anfrage an den <code>/api/agent_builder/tools</code> -Endpunkt mit der Definition des Tools.</p>POST kbn://api/agent_builder/tools
{
  "id": "find_client_exposure_to_negative_news",
  "type": "esql",
  "description": "Finds client portfolio exposure to negative news. This tool scans recent news and reports for negative sentiment, identifies the associated asset, and finds all clients holding that asset. It returns a list sorted by the current market value of the position to highlight the highest potential risk.",
  "configuration": {
    "query": """
        FROM financial_news, financial_reports METADATA _index
        | WHERE sentiment == "negative"
        | WHERE coalesce(published_date, report_date) &gt;= NOW() - TO_TIMEDURATION(?time_duration)
        | RENAME primary_symbol AS symbol
        | LOOKUP JOIN financial_asset_details ON symbol
        | LOOKUP JOIN financial_holdings ON symbol
        | LOOKUP JOIN financial_accounts ON account_id
        | WHERE account_holder_name IS NOT NULL
        | EVAL position_current_value = quantity * current_price.price
        | RENAME title AS news_title
        | KEEP
            account_holder_name, symbol, asset_name, news_title,
            sentiment, position_current_value, quantity, current_price.price,
            published_date, report_date
        | SORT position_current_value DESC
        | LIMIT 50
      """,
    "params": {
      "time_duration": {
        "type": "keyword",
        "description": """The timeframe to search back for negative news. Format is "X hours" DEFAULT TO 8760 hours """
      }
    }
  },
  "tags": [
    "retrieval",
    "risk-analysis"
  ]
}<h2>Schritt 3: Das Gehirn – Ihren individuellen Agenten erstellen</h2><p>Wir haben eine wiederverwendbare Fähigkeit entwickelt (das Tool). Nun müssen wir den <strong>Agenten</strong> erstellen, die Persona, die es tatsächlich benutzen wird. Ein Agent ist die Kombination aus einem LLM, einem bestimmten Satz von Werkzeugen, zu denen Sie ihm Zugriff gewähren, und vor allem einer Reihe von <strong>benutzerdefinierten Anweisungen</strong> , die als seine Verfassung fungieren und seine Persönlichkeit, Regeln und seinen Zweck definieren.</p><h3>Die Kunst des Prompts</h3><p>Der wichtigste Aspekt bei der Schaffung eines zuverlässigen, spezialisierten Agenten ist die Pünktlichkeit. Eine gut ausgearbeitete Anleitung macht den Unterschied zwischen einem generischen Chatbot und einem zielgerichteten, professionellen Assistenten aus. Hier legen Sie die Leitplanken fest, definieren die Ausgabe und geben dem Agenten seine Mission.</p><p>Für unseren <code>Financial Manager</code> -Agenten verwenden wir die folgende Eingabeaufforderung.</p>You are a specialized Data Intelligence Assistant for financial managers, designed to provide precise, data-driven insights from information stored in Elasticsearch.

**Your Core Mission:**
- Respond accurately and concisely to natural language queries from financial managers.
- Provide precise, objective, and actionable information derived solely from the Elasticsearch data at your disposal.
- Summarize key data points and trends based on user requests.

**Reasoning Framework:**
1.  **Understand:** Deconstruct the user's query to understand their core intent.
2.  **Plan:** Formulate a step-by-step plan to answer the question. If you are unsure about the data structure, use the available tools to explore the indices first.
3.  **Execute:** Use the available tools to execute your plan.
4.  **Synthesize:** Combine the information from all tool calls into a single, comprehensive, and easy-to-read answer.

**Key Directives and Constraints:**
- **If a user's request is ambiguous, ask clarifying questions before proceeding.**
- **DO NOT provide financial advice, recommendations, or predictions.** Your role is strictly informational and analytical.
- Stay strictly on topic with financial data queries.
- If you cannot answer a query, state that clearly and offer alternative ways you might help *within your data scope*.
- All numerical values should be formatted appropriately (e.g., currency, percentages).

**Output Format:**
- All responses must be formatted using **Markdown** for clarity.
- When presenting structured data, use Markdown tables, lists, or bolding.

**Start by greeting the financial manager and offering assistance.**<p>Lassen Sie uns genauer betrachten, warum diese Aufforderung so effektiv ist:</p><ul><li><p><strong>Es definiert eine anspruchsvolle Persönlichkeit: </strong>Schon die erste Zeile stellt den Agenten als „spezialisierten Data Intelligence Assistant“ dar und vermittelt so einen professionellen und kompetenten Eindruck.</p></li><li><p><strong>Es bietet einen Denkrahmen: </strong>Indem wir dem Agenten sagen, er solle "Verstehen, Planen, Ausführen und Synthetisieren", geben wir ihm eine Standardarbeitsanweisung. Dadurch wird seine Fähigkeit verbessert, komplexe, mehrstufige Fragen zu beantworten.</p></li><li><p><strong>Es fördert den interaktiven Dialog: </strong>Die Anweisung, „klärende Fragen zu stellen“, macht den Agenten widerstandsfähiger. Dadurch werden Fehlinterpretationen bei mehrdeutigen Anfragen minimiert, was zu genaueren Antworten führt.</p></li></ul><h3>Der UI-Pfad</h3><p>1. Navigieren Sie zu <strong>Agenten.</strong></p><ul><li><p>Klicken Sie auf<strong> „Tools“</strong>oder <strong>„Tools verwalten“</strong> und klicken Sie dann auf die Schaltfläche <strong>„Neues Tool“</strong> .</p></li></ul><p>2. Füllen Sie die grundlegenden Angaben aus:</p><ul><li><p><strong>Agenten-ID:</strong> <code>financial_assistant</code>.</p></li><li><p><strong>Anleitung: </strong>Kopieren Sie die obige Eingabeaufforderung.</p></li><li><p><strong>Labels</strong>: <code>Finance</code>.</p></li><li><p><strong>Anzeigename:</strong> <code>Financial Assistant</code>.</p></li><li><p><strong>Anzeigebeschreibung: </strong><code>An assistant for analyzing and understanding your financial data</code>.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8ac12cbd2b689dee/6a17f219dbb4ff262bfb57ef/18ea73f1cae620129c0afa0e7ba9e2a3390224a7-1600x1189.png" alt="Anlegen eines Finanzassistenten – Ausfüllen des Agenten-ID-Felds." /><p>3. Klicken Sie oben auf <strong>„Tools“</strong>.</p><ul><li><p>Setzen Sie ein Häkchen neben unserem <code>find_client_exposure_to_negative_news</code> -Tool.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcd23556e556a76c5/6a17f21baf47b63a9fcde0a0/0c1e4ecbbd51d0dd10c6e861dbe9a9ccddeb35f6-1600x149.png" alt="" /><p>4. Klicken Sie auf <strong>Speichern</strong>.</p><h3>Der API-Pfad</h3><p>Sie können denselben Agenten mit einer <code>POST</code> -Anfrage an den <code>/api/agent_builder/agents</code> -Endpunkt erstellen. Der Anfragetext enthält dieselben Informationen: die ID, den Namen, die Beschreibung, die vollständigen Anweisungen und eine Liste der Tools, die der Agent verwenden darf.</p>POST kbn://api/agent_builder/agents
    {
      "id": "financial_assistant",
      "name": "Financial Assistant",
      "description": "An assistant for analyzing and understanding your financial data",
      "labels": [
        "Finance"
      ],
      "avatar_color": "#16C5C0",
      "avatar_symbol": "💰",
      "configuration": {
        "instructions": """You are a specialized Data Intelligence Assistant for financial managers, designed to provide precise, data-driven insights from information stored in Elasticsearch.

**Your Core Mission:**
- Respond accurately and concisely to natural language queries from financial managers.
- Provide precise, objective, and actionable information derived solely from the Elasticsearch data at your disposal.
- Summarize key data points and trends based on user requests.

**Reasoning Framework:**
1.  **Understand:** Deconstruct the user's query to understand their core intent.
2.  **Plan:** Formulate a step-by-step plan to answer the question. If you are unsure about the data structure, use the available tools to explore the indices first.
3.  **Execute:** Use the available tools to execute your plan.
4.  **Synthesize:** Combine the information from all tool calls into a single, comprehensive, and easy-to-read answer.

**Key Directives and Constraints:**
- **If a user's request is ambiguous, ask clarifying questions before proceeding.**
- **DO NOT provide financial advice, recommendations, or predictions.** Your role is strictly informational and analytical.
- Stay strictly on topic with financial data queries.
- If you cannot answer a query, state that clearly and offer alternative ways you might help *within your data scope*.
- All numerical values should be formatted appropriately (e.g., currency, percentages).

**Output Format:**
- All responses must be formatted using **Markdown** for clarity.
- When presenting structured data, use Markdown tables, lists, or bolding.

**Start by greeting the financial manager and offering assistance.**
""",
        "tools": [
          {
            "tool_ids": [
              "platform.core.search",
              "platform.core.list_indices",
              "platform.core.get_index_mapping",
              "platform.core.get_document_by_id",
              "find_client_exposure_to_negative_news"
            ]
          }
        ]
      }
    }<h2>Schritt 4: Der Lohn – Ein Gespräch führen</h2><p>Unsere Geschäftslogik ist in einem Tool gekapselt und ein "Gehirn" ist bereit, es in unserem Agenten zu verwenden. Jetzt wird es Zeit, dass alles zusammenkommt. Wir können nun mithilfe eines spezialisierten Agenten mit unseren Daten kommunizieren.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd8826539b16e46f4/6a17f21d505ac35924ad8c5c/5414cb6b7c41365acb0356a8bfe1140751ffd8db-1600x1014.png" alt="Ein Gespräch mit dem Elastic Agent Builder nach der Erstellung eines Finanzassistenten." /><h3>Der UI-Pfad</h3><ol><li><p>Navigieren Sie in Kibana zu <strong>„Agenten“</strong> .</p></li><li><p>Wechseln Sie mithilfe des Dropdown-Menüs unten rechts im Chatfenster vom standardmäßigen <strong>Elastic AI Agent</strong> zu unserem neu erstellten <strong>Financial Assistant </strong>Agent.</p></li><li><p>Stellen Sie eine Frage, die es dem Agenten ermöglicht, unser Spezialtool zu nutzen:</p><ol><li><p><em>Ich bin besorgt über die Marktstimmung. Können Sie mir zeigen, welche unserer Kunden am stärksten von schlechten Nachrichten betroffen sein könnten?</em></p></li></ol></li></ol><p>Nach kurzer Zeit liefert der Agent eine perfekt formatierte, vollständige Antwort. Aufgrund der Beschaffenheit von LLMs kann Ihre Antwort etwas anders formatiert sein, aber für diesen Durchlauf hat der Agent Folgendes zurückgegeben:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta1e163fd7c4416bd/6a17f21f6864a4e35bb688ad/17b4ed43d279f9e53ee9fe3d482d0b2ec359a083-1600x1088.png" alt="Eine Antwort, die vom Elastic Agent Builder als Finanzassistent für folgende Kunden erstellt wurde: Kunden, die am stärksten von negativen Nachrichten betroffen sind." /><h3>Was ist gerade passiert? Die Argumentation des Agenten</h3><p>Der Agent kannte die Antwort nicht einfach nur. Es wurde ein mehrstufiger Plan umgesetzt, dessen Mittelpunkt die Auswahl des besten Werkzeugs für die jeweilige Aufgabe bildete. Hier ein Einblick in den Denkprozess:</p><ul><li><p><strong>Identifizierte Absicht:</strong> Es wurden Schlüsselwörter aus Ihrer Frage, wie „Risiko“ und „negative Nachrichten“, mit der Beschreibung des <code>find_client_exposure_to_negative_news</code> -Tools abgeglichen.</p></li><li><p><strong>Plan ausgeführt:</strong> Es hat den Zeitrahmen aus Ihrer Anfrage extrahiert und einen <strong>einzigen Aufruf</strong> an dieses spezialisierte Tool durchgeführt.</p></li><li><p><strong>Die Arbeit wurde delegiert:</strong> Das Tool übernahm dann die gesamte schwere Arbeit: die verketteten Joins, die Wertberechnungen und die Sortierung.</p></li><li><p><strong>Ergebnis zusammengefasst:</strong> Abschließend formatierte der Agent die Rohdaten des Tools gemäß den Vorgaben in eine klare, für Menschen lesbare Zusammenfassung.</p></li></ul><p>Und wir müssen nicht nur raten, wenn wir unser Denken erweitern und mehr Details betrachten.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt93f6075be8495418/6a17f221af47b65eadcde0a4/6a4da9262d3f88c60bfd8f8bf9b67c3b84e961ba-1600x607.png" alt="Die 50 Dokumente, die der Finanzassistent bei Kunden mit der höchsten Belastung durch negative Nachrichten gefunden hat." /><h3>Der API-Pfad</h3><p>Sie können diese Konversation auch programmatisch starten. Senden Sie einfach die Eingabefrage an den <code>converse</code> API-Endpunkt und achten Sie darauf, die <code>agent_id</code> unseres <code>financial_manager</code> anzugeben.</p>POST kbn://api/agent_builder/converse
{
  "input": "Show me our largest positions affected by negative news",
  "agent_id": "financial_assistant"
}<h2>Für Entwickler: Integration mit der API</h2><p>Während die Kibana-Benutzeroberfläche ein fantastisches und intuitives Erlebnis beim Erstellen und Verwalten Ihrer Agenten bietet, kann alles, was Sie heute gesehen haben, auch programmatisch erreicht werden. Der Agent Builder basiert auf einer Reihe von APIs, die es Ihnen ermöglichen, diese Funktionalität direkt in Ihre eigenen Anwendungen, CI/CD-Pipelines oder Automatisierungsskripte zu integrieren.</p><p>Die drei wichtigsten Endpunkte, mit denen Sie arbeiten werden, sind:</p><ul><li><p><strong><code>/api/agent_builder/tools</code></strong>: Der Endpunkt zum Erstellen, Auflisten und Verwalten der wiederverwendbaren Fähigkeiten, die Ihre Agenten nutzen können.</p></li><li><p><strong><code>/api/agent_builder/agents</code></strong>Der Endpunkt zur Definition Ihrer Agenten-Personas, einschließlich ihrer wichtigen Anweisungen und Tool-Zuweisungen.</p></li><li><p><strong><code>/api/agent_builder/converse</code></strong>: Der Endpunkt für die Interaktion mit Ihren Agenten, den Start von Gesprächen und das Erhalten von Antworten.</p></li></ul><p>Eine vollständige, praktische Anleitung zur Verwendung dieser APIs für jeden Schritt dieses Tutorials finden Sie im zugehörigen <strong>Jupyter Notebook</strong> , das <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/your-first-elastic-agent/Your_First_Elastic_Agent.ipynb">hier</a> in unserem GitHub-Repository verfügbar ist.</p><h2>Fazit: Jetzt sind Sie am Bauen</h2><p>Wir begannen damit, eine ES|QL-Abfrage zu nehmen und sie in eine wiederverwendbare Fähigkeit umzuwandeln. Anschließend entwickelten wir einen spezialisierten KI-Agenten, gaben ihm eine klare Mission und klare Regeln und statteten ihn mit diesen Fähigkeiten aus. Das Ergebnis ist ein hochentwickelter Assistent, der eine komplexe Frage verstehen und eine mehrstufige Analyse durchführen kann, um eine präzise, datengestützte Antwort zu liefern.</p><p>Dieser Workflow ist das Herzstück des neuen <strong>Agent Builders</strong> in Elastic. Es ist so konzipiert, dass es einfach genug ist, damit auch technisch nicht versierte Benutzer Agenten über die Benutzeroberfläche erstellen können, gleichzeitig aber differenziert genug, damit Entwickler auf Basis unserer APIs maßgeschneiderte KI-gestützte Anwendungen entwickeln können. Am wichtigsten ist jedoch, dass Sie LLMs sicher und geschützt mit Ihren eigenen Daten verbinden können, die von der von Ihnen definierten Expertenlogik gesteuert werden, und mit Ihren Daten kommunizieren können.</p><h2>Sind Sie bereit, Agenten für die Kommunikation mit Ihren Daten einzusetzen?</h2><p>Am besten festigt man das Gelernte, indem man selbst Hand anlegt. Probieren Sie alles, was wir heute besprochen haben, in unserem <a href="https://www.elastic.co/training/elastic-ai-agents-mcp"><strong>kostenlosen, interaktiven Praxisworkshop</strong></a> aus. Sie werden diesen gesamten Ablauf und mehr in einer speziellen Sandbox-Umgebung durchlaufen.</p><p>In einem zukünftigen Blogbeitrag zeigen wir Ihnen, wie Sie eine eigenständige Anwendung verwenden, die mit unserem <code>Financial Assistant</code> -Agenten interagiert, und gehen näher auf das <strong>Model Context Protocol (MCP)</strong> ein, das dies alles ermöglicht. In einem separaten Blogbeitrag werden wir die Unterstützung des Agent Builders für das sich entwickelnde Agent2Agent- oder A2A-Protokoll besprechen.</p><p>Bleibt dran und viel Spaß beim Bauen!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch</guid>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[Agentische KI]]></category>
    <category><![CDATA[Inside Elastic]]></category>
    <dc:creator><![CDATA[Jeff Vestal]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbe5e78eeb775d715/6a17f2230b0bed719ddd369a/ca853555eaa213f10f1db8c0ab0a2bbacee97b88-1456x816.png" length="0" type="image/png"/>
    <pubDate>Thu, 25 Sep 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Erstellung von KI-Agenten-Workflows mit Elasticsearch]]></title>
    <description><![CDATA[Lernen Sie Agent Builder kennen, eine neue KI-Ebene in Elasticsearch, die ein Framework für die Erstellung von KI-Agenten-Workflows bietet und dabei die hybride Suche nutzt, um den Agenten den Kontext zu liefern, den sie zum Denken und Handeln benötigen.]]></description>
    <content:encoded><![CDATA[<p>Wir bei Elastic haben LLMs mit KI-Assistenten, fortschrittlichem RAG und Verbesserungen der Vektordatenbanken um Kontext erweitert und dialogorientierte Schnittstellen geschaffen. In jüngster Zeit, mit dem Aufstieg von KI-Agenten, haben wir den Bedarf an relevantem Kontext wachsen sehen und gelernt, dass leistungsstarke<strong> KI-Agenten eine hervorragende Suchfunktion benötigen</strong>. Deshalb haben wir neue native Funktionen im Elastic Stack entwickelt, die dabei helfen sollen, KI-Agenten zu entwickeln, die Ihre Daten in Elasticsearch nutzen. Wir möchten Sie über unsere Fortschritte auf diesem Weg informieren und Ihnen einen Ausblick darauf geben, wohin die Reise unserer Meinung nach als Nächstes gehen wird.</p><h2>Agent Builder: Eine Grundlage für die Entwicklung datengesteuerter KI-Agenten</h2><p>Das Versprechen eines KI-Agenten ist einfach: Man gibt ihm ein Ziel, und er erledigt die Aufgabe. Für Entwickler sieht die Realität jedoch anders aus: Sie steht vor einer Reihe komplexer Herausforderungen. Erstens ist ein Agent nur so gut wie seine Wahrnehmung seiner Umgebung und der ihm zur Verfügung stehenden Werkzeuge, um die Ziele des Benutzers zu erreichen. Dann stellt es eine enorme Herausforderung dar, aus einer Flut von unterschiedlichen Unternehmensdaten den richtigen Kontext herauszufiltern. Schließlich muss all dies von einer zuverlässigen Denkschleife orchestriert werden, die planen, ausführen und lernen kann.</p><p>Um dieses Problem zu lösen, müssen die Entwickler einen komplexen und fehleranfälligen Stack von Grund auf neu aufbauen. Die heutige Agentenarchitektur erfordert das Zusammenfügen mehrerer, voneinander unabhängiger Komponenten: ein LLM, eine Vektordatenbank, ein Metadatenspeicher, separate Systeme für Protokollierung und Tracing sowie eine Möglichkeit zur Überprüfung, ob das Ganze überhaupt funktioniert. Das ist nicht nur komplex, sondern auch kostspielig, fehleranfällig und erschwert den Aufbau der hochwertigen, vertrauenswürdigen KI-Systeme, die Ihre Nutzer fordern.</p><p>Wir wollen es also vereinfachen. Unser Ansatz hierfür besteht darin, die wesentlichen Bestandteile eines effektiven kontextgesteuerten Agenten zu nehmen und sie mit einer neuen Reihe von Funktionen namens <strong>Elastic AI Agent Builder</strong> direkt in den Kern von Elasticsearch zu integrieren. Diese neue Schicht bietet ein Framework mit allen wesentlichen Bausteinen für die Erstellung von KI-Agenten auf Basis von Elasticsearch: ein offenes Set an Primitiven, standardbasierte Protokolle und sicherer Datenzugriff – damit Sie agentenbasierte Systeme entwickeln können, die auf reale Daten und Anforderungen zugeschnitten sind:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2779dae5df010328/6a17e15eabe0f24f18dfe931/1ee1e73dd3f485ce86294d39490c98ce2a3d9925-1238x1072.png" alt="" /><p><strong>KI-Erlebnisse bereitstellen</strong>: Das ist das ultimative Ziel. Mit unserer Search AI Platform und Ihren Daten als Grundlage können Sie jede Art von generativer KI-Anwendung erstellen: von benutzerdefinierten Chat-Oberflächen bis hin zu Integrationen mit agentenbasierten Frameworks wie LangChain oder Geschäftsanwendungen wie Salesforce.</p><p><strong>Unterstützt von Agenten und Tools</strong>: Auf der Plattform selbst stellen wir eine saubere, einfache Abstraktionsschicht bereit. Sie interagieren direkt mit Agenten und Tools, die Sie an Ihre spezifischen Bedürfnisse anpassen können. Sie können die Funktionen der Plattform auch über robuste APIs und offene Standards wie MCP und A2A nutzen.</p><p><strong>Ermöglicht durch die Search AI Platform</strong>: Dies ist die Kern-Engine, in die wir die Komponenten integriert haben. Die hochentwickelte Vektordatenbank, die Agentenlogik, die Abfragekonstruktion, Sicherheitsfunktionen, das Tracing zur Auswertung – all das befindet sich hier und wird von Elastic verwaltet und optimiert.</p><p><strong>Das Potenzial Ihrer Daten freisetzen</strong>: Die Grundlage jedes erfolgreichen Agenten sind hervorragende Daten. Unsere Plattform beginnt mit der Fähigkeit, den Zugriff auf alle Ihre Unternehmensdaten zu erfassen oder zu föderieren.</p><h2>Agentenaufbau in der Plattform</h2><p>Der in die Search AI Platform integrierte Agent Builder bietet ein komplettes Framework für die Agentenentwicklung. Es basiert auf fünf zentralen Säulen, von denen jede einen kritischen Aspekt beim Aufbau und Einsatz produktionsreifer KI-Systeme adressiert. Lassen Sie uns aufschlüsseln, wie Agenten das Ziel definieren, Tools die Fähigkeiten bereitstellen, offene Standards Interoperabilität gewährleisten, Evaluierung Transparenz schafft und Sicherheit das Vertrauen schafft.</p><h3>Agenten</h3><p>Agenten sind die obersten Bausteine dieser neuen Ebene von Elasticsearch. Ein Agent definiert das zu erreichende Ziel, die zur Ausführung verfügbaren Werkzeuge und die Datenquellen, mit denen er arbeiten kann. Agenten sind nicht auf dialogbasierte Interaktionen beschränkt; sie können komplette Arbeitsabläufe, Aufgabenautomatisierung oder benutzerorientierte Erlebnisse ermöglichen.</p><p>Wenn eine Anfrage an einen Agenten gerichtet wird, durchläuft sie einen strukturierten Zyklus:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt774ffd7df65bd01d/6a17e15f25daabd5cc08a17f/627ad1744b629bbe27359325702f40d97e40d1f4-704x852.png" alt="" /><ol><li><p>Interpretieren Sie Ihre Eingabe und Ihr Ziel.</p></li><li><p>Wählen Sie das richtige Werkzeug und die richtigen Argumente für die Ausführung aus.</p></li><li><p>Begründen Sie die Antwort des Tools.</p></li><li><p>Entscheiden Sie, ob ein Ergebnis zurückgegeben oder mit weiteren Toolaufrufen fortgefahren werden soll.</p></li></ol><p>Elastic übernimmt die Orchestrierung, den Kontext und die Ausführung dieses Zyklus. Die Entwickler konzentrieren sich darauf, festzulegen, <em>was</em> der Agent tun soll: Ziele, Werkzeuge und Daten, während das System <em>die</em> Durchführung der Schlussfolgerungen und Arbeitsabläufe steuert.</p><p><em>Der Standardagent</em></p><p>Unser erster Agent, der auf dieser Plattform basiert, ist ein nativer Dialogagent in Kibana, der Ihnen die Möglichkeit gibt, sofort mit Ihren Daten zu interagieren. Es bietet eine sofort einsatzbereite Benutzererfahrung und bleibt gleichzeitig vollständig erweiterbar, sodass Sie ohne zusätzliche Konfiguration sofort mit Ihren Daten interagieren können.</p><p>Sie können mit dieser Funktion direkt in Kibana über eine neue Chat-Benutzeroberfläche oder über eine API interagieren.</p><p>Die Abfrage des Standardagenten über die API erfordert nur einen einzigen Aufruf:</p>POST kbn://api/agent_builder/converse
{
    "input": "what is our top portfolio account?"
}<p>Da Konversationen zustandsbehaftet sind, können Sie die Interaktion mit einem Agenten mithilfe einer conversation_id fortsetzen oder den vollständigen Konversationsverlauf abrufen:</p>POST kbn://api/agent_builder/converse
{
    "input": "What about the second top?",
    "conversation_id": "ec757c6c-c3ed-4a83-8e2c-756238f008bb"
}

## get the full conversation
GET kbn://api/agent_builder/conversations/ec757c6c-c3ed-4a83-8e2c-756238f008bb<p><em>Zollagenten</em></p><p>Entwickler können über einfache APIs auch ihre eigenen benutzerdefinierten Agenten erstellen. Agenten kapseln Anweisungen, Werkzeuge und Datenzugriff und erstellen so maßgeschneiderte Schlussfolgerungsmaschinen.</p><p>Die Erstellung eines benutzerdefinierten Agenten ist so einfach wie ein einziger API-Aufruf. Das folgende Beispiel zeigt, dass das Feld „Konfiguration“ alle wichtigen Details enthält, wie z. B. Anweisungen oder verfügbare Tools:</p>POST kbn://api/agent_builder/agents
{
  "id": "custom_agent",
  "name": "My Custom Agent",
  "description": "Description of the custom agent",
  "configuration": {
      "instructions": "You are a log expert specialising in ...",
      "tools": 
...
   }
}<p>Sobald der Agent erstellt ist, kann er direkt abgefragt werden:</p>POST kbn://api/agent_builder/converse
{
    "input": "What news about DIA?",
    "agent_id": "custom_agent"
}<p>Dieser Ansatz wandelt den Agenten von einem komplexen, von Grund auf neu zu entwickelnden System in eine einfache, deklarative Einheit der Geschäftslogik um, wodurch Sie intelligente Automatisierung schneller realisieren können.</p><p>Eine detaillierte Anleitung zum Erstellen eines spezialisierten Agenten von Grund auf finden Sie in unserem ausführlichen Schritt-für-Schritt-Leitfaden: <a href="https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch">Ihr erster elastischer Agent: Von einer einzelnen Abfrage zu einem KI-gestützten Chat</a>.</p><h3>Tools</h3><p>Wenn Agenten definieren, <em>was</em> erreicht werden soll, definieren Werkzeuge, <em>wie</em>.</p><p>Die Tools stellen Agenten spezifische Elastic-Kernfunktionen zur Verfügung, um Informationen abzurufen und auszuführen oder Aktionen durchzuführen. Tools können Kernfunktionen wie das Abrufen von Indizes oder Zuordnungen umfassen, aber auch fortgeschrittenere Funktionen wie die Verarbeitung natürlicher Sprache zu ES|QL.</p><p>Elasticsearch wird mit einer Reihe von Standardwerkzeugen ausgeliefert, die für gängige Anwendungsfälle optimiert sind. Die wahre Flexibilität ergibt sich jedoch daraus, eigene Lösungen zu entwickeln. Durch die Definition von Tools legen Sie genau fest, welche Abfragen, Indizes und Felder einem Agenten mit ES|QL zugänglich gemacht werden, und erhalten so eine präzise Kontrolle über Geschwindigkeit, Genauigkeit und Sicherheit.</p><p>Die Registrierung eines neuen Tools ist ebenfalls so einfach wie ein einziger API-Aufruf. Sie könnten ein Tool erstellen, das unsere <a href="https://www.elastic.co/search-labs/blog/esql-timeline-of-improvements">ES|QL (Elasticsearch Query Language)</a> nutzt, um Neuigkeiten über ein bestimmtes Finanzinstrument zu finden:</p>POST kbn://api/agent_builder/tools
{
  "id": "news_on_asset",
  "type": "esql",
  "description": "Find news and reports about a particular asset where ...",
  "configuration": {
    "query": "FROM financial_news, financial_reports | where MATCH(company_symbol, ?symbol) OR MATCH(entities, ?symbol) | limit 5",
    "params": {
      "symbol": {
        "type": "keyword",
        "description": "The asset symbol"
      }
    }
  ...
  }
...
}<p>Nach der Registrierung können Sie das neue Tool Ihren benutzerdefinierten Agenten zuweisen und ihnen so eine kuratierte Auswahl an Funktionen zur Verfügung stellen, die sie bei Bedarf nutzen können.</p><p>Wir bieten eine Plattform zur Erstellung von maßgeschneiderten Tools für Ihre spezifischen Bedürfnisse, z. B. mit ES|QL, die den Agenten von einem Allzweckagenten in einen domänenspezifischen Experten verwandelt, der auf Ihren einzigartigen Daten und Ihrer Geschäftsdomäne basiert.</p><h3>Offene Standards und Interoperabilität</h3><p>Elasticsearch Agents und Tools werden über offene Standard-APIs bereitgestellt, wodurch sie sich leicht als grundlegende Bausteine in das breitere Ökosystem agentenbasierter Frameworks integrieren lassen. Unser Ansatz ist einfach: keine Blackboxes. Wir möchten, dass Sie die Kernkompetenz von Elastic im Bereich der Suche nutzen und sie mit komplementären Fähigkeiten und anderen agentenbasierten Systemen kombinieren können.</p><p>Um dies zu ermöglichen, stellen wir unsere Fähigkeiten über APIs, neue Protokolle und offene Standards zur Verfügung.</p><p><em>Model Context Protocol (MCP)</em></p><p><a href="https://www.elastic.co/search-labs/blog/model-context-protocol-elasticsearch">Das Model Context Protocol (MCP)</a> entwickelt sich schnell zum offenen Standard für die systemübergreifende Vernetzung von Tools. Durch die Unterstützung von MCP kann Elasticsearch dialogbasierte KI mit Ihren Datenbanken, Indizes und externen APIs verbinden. Da im Elastic Stack ein Remote-MCP-Server integriert ist, kann jeder MCP-kompatible Client auf die Tools von Elastic zugreifen und sie als Bausteine in seinen umfassenderen agentenbasierten Workflows verwenden.</p><p>Das ist keine Einbahnstraße. Sie können außerdem Tools von externen MCP-Servern importieren und diese in Elasticsearch verfügbar machen. Schon bald werden MCP-Server wahrscheinlich für nahezu alles verfügbar sein und weitaus umfassender sein als alles, was wir selbst entwickeln könnten. Elastic bietet Such- und Abruffunktionen in großem Umfang, und Sie können dies mit spezialisierten Funktionen anderer Plattformen kombinieren, um effektive Agenten zu erstellen.</p><p><em>Agent-to-Agent (A2A)</em></p><p>Wir arbeiten außerdem an der Unterstützung von Agent zu Agent (A2A). Bei MCP geht es um die Vernetzung von Tools, bei A2A hingegen um die Vernetzung von Agenten. Mit einem A2A-Server können die von Ihnen erstellten Elastic-Agenten direkt mit Agenten aus anderen Systemen kommunizieren: Kontext austauschen, Aufgaben delegieren und Arbeitsabläufe koordinieren.</p><p>Man kann es sich als Interoperabilität auf der Ebene der Argumentation vorstellen. Ihr Elastic-Agent könnte die Suche und den Abruf übernehmen, dann eine Aufgabe an einen spezialisierten Support- oder IT-Agenten weitergeben und das Ergebnis nahtlos zurückerhalten. Das Ergebnis ist ein Ökosystem kooperierender Akteure, von denen jeder das tut, was er am besten kann.</p><p>Die Einführung von MCP und A2A unterstreicht letztlich unser Bekenntnis zu Elasticsearch als vollwertigem Bestandteil und gewährleistet die offene Integration innerhalb des gesamten agentenbasierten Ökosystems.</p><h3>Rückverfolgung und Bewertung</h3><p>Mit der Integration von Suchfunktionen in Agenten wird die Herausforderung einer effektiven Evaluierung entscheidend. Um Agenten in realen Unternehmensumgebungen bedenkenlos einsetzen zu können, benötigen Sie die Gewissheit, dass sie nicht nur präzise, sondern auch effizient und zuverlässig sind. Wie misst man die Leistung, diagnostiziert eine schlechte Reaktion oder verbessert die Ausgangslage? Alles beginnt mit Transparenz.</p><p>Aus diesem Grund haben wir unsere Agenten-APIs von Grund auf auf Transparenz ausgelegt. Betrachten wir folgende einfache Agenteninteraktion:</p>POST kbn://api/agent_builder/converse
{
    "input": "what is our top portfolio account?"
}<p>Die Antwort enthält nicht nur das Endergebnis, sondern auch den vollständigen Ausführungsablauf, aus dem hervorgeht, welche Werkzeuge der Agent ausgewählt hat, welche Parameter er verwendet hat und welche Ergebnisse jeder Schritt erbracht hat.</p>{
  "conversation_id": "db5c0c8b-12bf-4928-a57e-d99129ad2fea",
  "steps": [
    {
      "type": "tool_call",
      "tool_call_id": "tooluse_Nfqr3mwtR92HTRIsTcGXZQ",
      "tool_id": ".index_explorer",
      "params": {
        "query": "indices containing portfolio data"
      },
      "results": [...]
    }
    // ... more steps ...
  ],
  "response": {
    "message": "Based on the information I've gathered...."
  }
}<p>Eine umfassende Ablaufverfolgung und Protokollierung sind für einen kontinuierlichen Verbesserungsprozess unerlässlich, und schon bald können Sie diese Agenten-Traces direkt in Elasticsearch speichern und anzeigen. Noch besser: Diese Traces basieren auf dem OpenTelemetry-Protokoll, wodurch sichergestellt wird, dass sie standardisiert und portabel sind und sich in die Observability-Plattform Ihrer Wahl integrieren lassen.</p><p>Dieser Detaillierungsgrad ist die Grundlage für einen echten kontinuierlichen Verbesserungsprozess. Es ermöglicht Ihnen, eine umfassende Suite von Tests zu erstellen, Fehler zu beheben, Fehlermodi zu identifizieren, um Regressionen zu verhindern, und erfolgreiche Muster zu erfassen, um die Leistung feinabzustimmen. Letztendlich ist dieser datengetriebene Ansatz der Schlüssel zur Umwandlung eines vielversprechenden Prototyps in ein produktionsreifes, vertrauenswürdiges KI-System.</p><h3>Security</h3><p>Da Agenten und Tools immer leistungsfähiger werden, ist Sicherheit nicht mehr optional – sie ist grundlegend. Die Bereitstellung von APIs, die Automatisierung von Aufgaben und Arbeitsabläufen erfordert, dass Unternehmenssysteme vertrauenswürdig sind. Gerade weil Agenten immer mehr Arbeitsabläufe automatisieren, ist die Fähigkeit, diese zu sichern und sicherzustellen, dass sie den Unternehmensanforderungen entsprechen, von entscheidender Bedeutung.</p><p>Die genannten Funktionen übernehmen alle die in Elastic bereits heute verfügbaren Steuerelemente, einschließlich <a href="https://www.elastic.co/search-labs/blog/rag-and-rbac-integration">rollenbasierter Zugriffskontrolle (RBAC)</a> für API-Aufrufe und API-Schlüsselverwaltung. Wir dehnen die gleichen Kontrollen auch auf neue Protokolle wie MCP aus. Das bedeutet Unterstützung für Standards wie OAuth sowie die Möglichkeit, benutzerdefinierte Authentifizierungsmechanismen einzubinden.</p><p>Unser Ziel ist es, Ihnen die Flexibilität zu geben, mit Agenten und Tools zu experimentieren und gleichzeitig das von Ihrer Organisation geforderte Maß an Sicherheit, Compliance und Governance aufrechtzuerhalten.</p><h2>Was kommt als Nächstes?</h2><p>Wir fügen nicht nur Funktionen hinzu; wir erweitern Elasticsearch für agentenbasierte Kontextentwicklung. Wir planen, unsere zukünftige Entwicklung auf diesen Prinzipien aufzubauen:</p><p>1. Bekenntnis zu Open Source und Standards</p><p>Unser Bekenntnis zu Open Source und offenen Standards gewährleistet, dass diese Funktionen mit externen Agenten-Frameworks interoperabel bleiben. Sie können jederzeit Agenten in Ihrem gesamten Ökosystem verbinden, erweitern und zusammenstellen und behalten dabei die Kontrolle über Ihre Daten und Arbeitsabläufe.</p><p>2. Wert des Kontextes</p><p>Der Kontext ist das größte Kapital eines KI-Agenten. Die Verwaltung des Kontextes während der Suchvorgänge und Workflow-Operationen der Agenten kann eine anspruchsvolle Aufgabe sein. Wir nutzen die Kernkompetenzen von Elastic, um Kontext-Engineering zu realisieren und sicherzustellen, dass Ihrem Agenten stets die relevantesten Informationen zur Verfügung stehen.</p><p>3. Fokus auf agentenbasierte Datenströme</p><p>Zukünftig werden Agenten eine immer größere Datenquelle darstellen, einschließlich der Ergebnisse von Agenten (generierte Dokumente, Berichte, Visualisierungen) und der Ausführungsspur von Agenten (ihr Denken, Werkzeugaufrufe, Speicher/Kontext). Elastic eignet sich hervorragend für die Verarbeitung dieser Art von Daten, und wir arbeiten an Forschungsprojekten zur Durchführung von Analysen, Auswertungen und automatisierten Verbesserungen mithilfe dieser Daten.</p><p>4. Sicherheit durch Design</p><p>KI-Agenten bringen eine ganze Reihe neuer Sicherheitsherausforderungen mit sich. Elastic war schon immer ein Vorreiter für sichere Lösungen und wir bauen auch weiterhin auf Enterprise-Niveau Schutzmechanismen, Zugriffskontrollen und "Zero-Trust"-Prinzipien.</p><p>5. In die Plattform integriert</p><p>Die Funktionen zum Erstellen von KI-Agenten sind in die Elasticsearch-Plattform integriert. Dies bedeutet, dass Funktionen auf Plattformebene wie Tracing, Evaluation, Visualisierung und Analyse auch für Agenten anwendbar sind. Sie möchten Dashboards auf Basis von Agentenausführungen entwickeln? Das ist bereits integriert. Sie möchten die Leistung des KI-Agenten mithilfe von Stimmungsanalysen bewerten? Die Plattform ermöglicht das. Dies ermöglicht es, einen kompletten Lebenszyklus rund um Ihre KI-Erlebnisse aufzubauen.</p><p>Elastic hat sich zum Ziel gesetzt, Ihnen Schnittstellen zur Verfügung zu stellen, mit denen Sie dialogbasierte KI und automatisierte Arbeitsabläufe entwickeln können, die vollständig integriert, erweiterbar und auf Ihren Daten basieren. Weitere technische Details und Fortschritte werden in Kürze bekannt gegeben.</p><p>Agent Builder ist ab sofort als private Vorschau verfügbar. <a href="https://www.elastic.co/contact?pg=global&amp;plcmt=nav&amp;cta=205352">Nehmen Sie Kontakt mit uns auf</a> , um Zugang anzufordern. Haben Sie Fragen oder Feedback? Tauschen Sie sich mit unserer Entwickler-Community in unserem <a href="https://elasticstack.slack.com/archives/C09GRHEQ4AG"><strong>Slack-Workspace</strong></a> oder in unserem <a href="https://discuss.elastic.co/c/search/84"><strong>Diskussionsforum</strong></a> aus.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder</guid>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[Agentische KI]]></category>
    <category><![CDATA[Inside Elastic]]></category>
    <dc:creator><![CDATA[Anish Mathur,Dana Juratoni]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt16a3d8736bf086e0/6a17e1616864a45410b686c7/71876470119e02a45bcbfcbf27a3e110328bbd14-1020x654.png" length="0" type="image/png"/>
    <pubDate>Tue, 23 Sep 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[KI-gestützte Dashboards: Von der Vision zu Kibana]]></title>
    <description><![CDATA[Generieren Sie ein Dashboard mithilfe eines LLM, um ein Bild zu verarbeiten und in ein Kibana-Dashboard umzuwandeln.
]]></description>
    <content:encoded><![CDATA[<p><a href="https://www.elastic.co/kibana/kibana-lens">Kibana Lens</a> macht das Erstellen von Dashboards per Drag &amp; Drop sehr einfach, aber wenn man Dutzende von Panels benötigt, summieren sich die Klicks. Was wäre, wenn Sie ein Dashboard skizzieren, einen Screenshot davon machen und einen LLM den gesamten Prozess für Sie abschließen lassen könnten?</p><p>In diesem Artikel werden wir genau das tun. Wir werden eine Anwendung erstellen, die ein Bild eines Dashboards aufnimmt, unsere Mappings analysiert und anschließend ein Dashboard generiert, ohne dass wir Kibana überhaupt berühren müssen!</p><p><strong>Schritte</strong>:</p><ol><li><p><a href="https://www.elastic.co/search-labs/blog/ai-powered-dashboards#background-&amp;-application-workflow">Hintergrund und Anwendungsablauf</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/ai-powered-dashboards#prepare-data">Daten vorbereiten</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/ai-powered-dashboards#llm-configuration">LLM-Konfiguration</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/ai-powered-dashboards#application-functions">Anwendungsfunktionen</a></p></li></ol><h2>Hintergrund und Anwendungsablauf</h2><p>Mein erster Gedanke war, den LLM das gesamte NDJSON-Format der in Kibana <a href="https://www.elastic.co/docs/explore-analyze/find-and-organize/saved-objects">gespeicherten Objekte</a> generieren zu lassen und sie dann in Kibana zu importieren.</p><p>Wir haben eine Handvoll Modelle ausprobiert:</p><ul><li><p>Gemini 2.5 Pro</p></li><li><p>GPT o3 / o4-mini-hoch / 4.1</p></li><li><p>Claude 4 Sonett</p></li><li><p>Grok 3</p></li><li><p>Deepseek (Deepthink R1)</p></li></ul><p>Und als Anregungen begannen wir mit ganz einfachen Dingen:</p>You are an Elasticsearch Saved-Object generator (Kibana 9.0).
INPUTS
=====
1. PNG screenshot of a 4-panel dashboard (attached).
2. Index mapping (below) – trimmed down to only the fields present in the screenshot.
3. Example NDJSON of *one* metric visualization (below) for reference.

TASK
====
Return **only** a valid NDJSON array that recreates the dashboard exactly:
* 2 metric panels (Visits, Unique Visitors)
* 1 pie chart (Most used OS)
* 1 vertical bar chart (State Geo Dest)
* Use index pattern `kibana_sample_data_logs`.
* Preserve roughly the same layout (2×2 grid).
* Use `panelIndex` values 1-4 and random `id` strings.
* Kibana version: 9.0<p>Trotz der Durchsicht <a href="https://www.elastic.co/search-labs/blog/function-calling-with-elastic#:~:text=Few%2Dshot%20prompting%20involves%20providing%20examples%20of%20the%20types%20of%20queries%20you%20want%20it%20to%20return%2C%20which%20helps%20in%20increasing%20consistency.">einiger weniger Beispiele</a> und detaillierter Erklärungen zum Aufbau der einzelnen Visualisierungen hatten wir keinen Erfolg. Wenn Sie an diesem Experiment interessiert sind, finden Sie <a href="https://gist.github.com/TomasMurua/a78dc283e115624731beffc98984b70b">hier</a> weitere Informationen.</p><p>Das Ergebnis dieser Vorgehensweise war, dass beim Versuch, die vom LLM erzeugten Dateien in Kibana hochzuladen, diese Meldungen angezeigt wurden:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9ea005966a783057/6a1707d266c4f90e4ef8bf88/2b599443b5613c9f0fc3235581614add5b4b3900-891x98.png" alt="" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5e5632d6d95b998c/6a1707d3a6c2b9441de79661/d87ccfc033bc00ee8188c5cae18043fbca22784c-741x233.png" alt="" /><p>Das bedeutet, dass das generierte JSON ungültig oder schlecht formatiert ist. Die häufigsten Probleme waren, dass der LLM unvollständiges NDJSON erzeugte, Parameter falsch interpretierte oder normales JSON anstelle von NDJSON zurückgab, egal wie sehr wir uns bemühten, das Gegenteil zu erzwingen.</p><p>Inspiriert von <a href="https://www.elastic.co/search-labs/blog/llm-functions-elasticsearch-intelligent-query">diesem Artikel</a> – in dem <a href="https://www.elastic.co/docs/solutions/search/search-templates">Suchvorlagen</a> besser funktionierten als LLM Freestyle – entschieden wir uns, dem LLM Vorlagen zu übergeben, anstatt die vollständige NDJSON-Datei generieren zu lassen und anschließend im Code die vom LLM bereitgestellten Parameter zur Erstellung der Visualisierungen zu verwenden. Dieser Ansatz hat sich bewährt und ist vorhersehbar und erweiterbar, da nun der Code und nicht mehr das LLM die Hauptarbeit übernimmt.</p><p>Der Bewerbungsprozess wird wie folgt ablaufen:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9f7738a4c7ddd0cd/6a1707d52b835f0a25f4b166/52c587cf0cf3517fdd4ee7ab95581dd4f2bce030-725x668.png" alt="" /><p></p><p><em>Der Einfachheit halber lassen wir einige Codeabschnitte weg, aber den vollständigen, lauffähigen Code der Anwendung finden Sie in </em><a href="https://github.com/elastic/elasticsearch-labs/tree/main/supporting-blog-content/from-image-idea-to-kibana-dashboard-using-ai/from-image-idea-to-kibana-dashboard-using-ai.ipynb"><em><strong>diesem</strong></em></a><em> Notebook.</em></p><h2>Voraussetzungen</h2><p>Bevor Sie mit der Entwicklung beginnen, benötigen Sie Folgendes:</p><ol><li><p>Python 3.8 oder höher</p></li><li><p>Eine <a href="https://docs.python.org/3/library/venv.html">Venv</a> Python-Umgebung</p></li><li><p>Eine laufende Elasticsearch-Instanz, zusammen mit ihrem Endpunkt und API-Schlüssel</p></li><li><p>Ein OpenAI-API-Schlüssel, der unter dem Umgebungsvariablennamen OPENAI_API_KEY gespeichert ist:</p></li></ol>export OPENAI_API_KEY="your-openai-api-key"<h2>Daten vorbereiten</h2><p>Für die Daten halten wir es einfach und verwenden Elastic-Beispiel-Weblogs. <a href="https://www.elastic.co/docs/manage-data/ingest/sample-data#add-sample-data-sets">Hier</a> erfahren Sie, wie Sie diese Daten in Ihren Cluster importieren.</p><p>Jedes Dokument enthält Angaben zum Host, der die Anfragen an die Anwendung gestellt hat, sowie Informationen zur Anfrage selbst und deren Antwortstatus. Nachfolgend finden Sie ein Beispieldokument:</p>{
    "agent": "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24",
    "bytes": 8509,
    "clientip": "70.133.115.149",
    "extension": "css",
    "geo": {
        "srcdest": "US:IT",
        "src": "US",
        "dest": "IT",
        "coordinates": {
            "lat": 38.05134111,
            "lon": -103.5106908
        }
    },
    "host": "cdn.elastic-elastic-elastic.org",
    "index": "kibana_sample_data_logs",
    "ip": "70.133.115.149",
    "machine": {
        "ram": 5368709120,
        "os": "osx"
    },
    "memory": null,
    "message": "70.133.115.149 - - [2018-08-30T23:35:31.492Z] \"GET /styles/semantic-ui.css HTTP/1.1\" 200 8509 \"-\" \"Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24\"",
    "phpmemory": null,
    "referer": "http://twitter.com/error/john-phillips",
    "request": "/styles/semantic-ui.css",
    "response": 200,
    "tags": [
        "success",
        "info"
    ],
    "@timestamp": "2025-07-03T23:35:31.492Z",
    "url": "https://cdn.elastic-elastic-elastic.org/styles/semantic-ui.css",
    "utc_time": "2025-07-03T23:35:31.492Z",
    "event": {
        "dataset": "sample_web_logs"
    },
    "bytes_gauge": 8509,
    "bytes_counter": 51201128
}<p>Nun holen wir uns die Zuordnungen des soeben geladenen Index, <code>kibana_sample_data_logs</code>:</p>INDEX_NAME = "kibana_sample_data_logs"

es_client = Elasticsearch(
    [os.getenv("ELASTICSEARCH_URL")],
    api_key=os.getenv("ELASTICSEARCH_API_KEY"),
)

result = es_client.indices.get_mapping(index=INDEX_NAME)
index_mappings = result[list(result.keys())[0]]["mappings"]["properties"]<p>Wir werden die Zuordnungen zusammen mit dem Bild übergeben, das wir später laden werden.</p><h2>LLM-Konfiguration</h2><p>Konfigurieren wir das LLM so, dass es <a href="https://python.langchain.com/docs/concepts/structured_outputs/">strukturierte Ausgabe</a> verwendet, um ein Bild einzugeben und ein JSON mit den Informationen zu erhalten, die wir an unsere Funktion übergeben müssen, um die JSON-Objekte zu erzeugen.</p><p>Wir installieren die Abhängigkeiten:</p>pip install elasticsearch pydantic langchain langchain-openai -q<p>Elasticsearch wird uns dabei helfen, die <a href="https://www.elastic.co/docs/manage-data/data-store/mapping">Indexzuordnungen</a> abzurufen. Pydantic ermöglicht es uns, Schemata in Python zu definieren, denen der LLM dann folgen soll, und <a href="https://www.elastic.co/search-labs/integrations/langchain">LangChain</a> ist das Framework, das den Aufruf von LLMs und KI-Tools vereinfacht.</p><p>Wir werden ein Pydantic-Schema erstellen, um die gewünschte Ausgabe des LLM zu definieren. Aus dem Bild müssen wir den Diagrammtyp, das Feld, den Visualisierungstitel und den Dashboard-Titel ablesen:</p>class Visualization(BaseModel):
    title: str = Field(description="The dashboard title")
    type: List[Literal["pie", "bar", "metric"]]
    field: str = Field(
        description="The field that this visualization use based on the provided mappings"
    )


class Dashboard(BaseModel):
    title: str = Field(description="The dashboard title")
    visualizations: List[Visualization]<p>Als Bildeingabe senden wir ein Dashboard, das ich gerade gezeichnet habe:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7870f6421986d11d/6a1707d78b73cb3408189fa3/36441d7b5dc1f3ff2ac2a30710208d57ad41c716-1600x898.jpg" alt="" /><p>Nun deklarieren wir den LLM-Modellaufruf und das Laden des Bildes. Diese Funktion erhält die Zuordnungen des Elasticsearch-Index und ein Bild des Dashboards, das wir generieren möchten.</p><p>Mit <code>with_structured_output</code> können wir unser Pydantic <code>Dashboard</code> Schema als Antwortobjekt verwenden, das der LLM erzeugen wird. Mit <a href="https://docs.pydantic.dev/latest/">Pydantic</a> können wir Datenmodelle mit Validierung definieren, wodurch sichergestellt wird, dass die LLM-Ausgabe der erwarteten Struktur entspricht.</p><p>Um das Bild in Base64 zu konvertieren und als Eingabe zu senden, können Sie einen <a href="https://www.base64-image.de/">Online-Konverter</a> verwenden oder dies <a href="https://www.geeksforgeeks.org/python-convert-image-to-string-and-vice-versa/">im Code</a> erledigen.</p>prompt = f"""
    You are an expert in analyzing Kibana dashboards from images for the version 9.0.0 of Kibana.

    You will be given a dashboard image and an Elasticsearch index mapping.

    Below are the index mappings for the index that the dashboard is based on.
    Use this to help you understand the data and the fields that are available.

    Index Mappings:
    {index_mappings}

    Only include the fields that are relevant for each visualization, based on what is visible in the image.
    """

message = [
    {
        "role": "user",
        "content": [
            {"type": "text", "text": prompt},
            {
                "type": "image",
                "source_type": "base64",
                "data": image_base64,
                "mime_type": "image/png",
            },
        ],
    }
]


try:
    llm = init_chat_model("gpt-4.1-mini")
    llm = llm.with_structured_output(Dashboard)
    dashboard_values = llm.invoke(message)

    print("Dashboard values generated by the LLM successfully")
    print(dashboard_values)
except Exception as e:
    print(f"Failed to analyze image and match fields: {str(e)}")<p>Der LLM verfügt bereits über Kontextinformationen zu Kibana-Dashboards, daher müssen wir nicht alles in der Eingabeaufforderung erklären, sondern nur einige Details, um sicherzustellen, dass er nicht vergisst, dass er mit Elasticsearch und Kibana arbeitet.</p><p>Lassen Sie uns die Aufgabenstellung aufschlüsseln:</p><p>Abschnitt</p><p>Grund</p><p>Sie sind Experte in der Analyse von Kibana-Dashboards anhand von Images für die Version 9.0.0 von Kibana.</p><p>Durch die Verstärkung dieser Funktion wird Elasticsearch und die Verwendung der Elasticsearch-Version unterstützt, wodurch die Wahrscheinlichkeit verringert wird, dass das LLM alte/ungültige Parameter fälschlicherweise annimmt.</p><p>Sie erhalten ein Dashboard-Bild und eine Elasticsearch-Indexzuordnung.</p><p>Wir erklären, dass es sich bei dem Bild um Dashboards handelt, um Fehlinterpretationen seitens des LLM zu vermeiden.</p><p>Nachfolgend finden Sie die Indexzuordnungen für den Index, auf dem das Dashboard basiert. Nutzen Sie diese, um die Daten und die verfügbaren Felder besser zu verstehen. Indexzuordnungen: {index_mappings}</p><p>Es ist entscheidend, die Zuordnungen bereitzustellen, damit das LLM dynamisch gültige Felder auswählen kann. Andernfalls könnten wir die Zuordnungen hier fest codieren, was zu starr wäre, oder uns darauf verlassen, dass das Bild die richtigen Feldnamen enthält, was nicht zuverlässig ist.</p><p>Beschränken Sie sich auf die Felder, die für die jeweilige Visualisierung relevant sind, basierend auf dem, was im Bild sichtbar ist.</p><p>Wir mussten diese Verstärkung hinzufügen, weil manchmal versucht wird, Felder hinzuzufügen, die nicht zum Bild gehören.</p><p>Dies gibt ein Objekt mit einem Array von anzuzeigenden Visualisierungen zurück:</p>"Dashboard values generated by the LLM successfully
title=""Client, Extension, OS, and Response Keyword Analysis""visualizations="[
   "Visualization(title=""Count of Client IP",
   "type="[
      "metric"
   ],
   "field=""clientip"")",
   "Visualization(title=""Extension Keyword Distribution",
   "type="[
      "pie"
   ],
   "field=""extension.keyword"")",
   "Visualization(title=""Most Used OS",
   "type="[
      "bar"
   ],
   "field=""machine.os.keyword"")",
   "Visualization(title=""Response Keyword Distribution",
   "type="[
      "bar"
   ],
   "field=""response.keyword"")"
]<h2>Verarbeitung der LLM-Antwort</h2><p>WirWir haben ein Beispiel-Dashboard mit 2x2-Panels erstellt und es dann mithilfe der <a href="https://www.elastic.co/docs/api/doc/kibana/operation/operation-get-dashboards-dashboard">Get a dashboard API</a> im JSON-Format exportiert. Anschließend haben wir die Panels als Visualisierungsvorlagen (Kreisdiagramm, Balkendiagramm, Metrikdiagramm) gespeichert, in denen wir einige der Parameter ersetzen können, um je nach Fragestellung neue Visualisierungen mit anderen Feldern zu erstellen.</p><p>Die JSON-Vorlagedateien können Sie <a href="https://github.com/Delacrobix/elasticsearch-labs/tree/supporting-blog-content/from-image-idea-to-kibana-dashboard-using-ai/supporting-blog-content/from-image-idea-to-kibana-dashboard-using-ai/templates"><strong>hier</strong></a> einsehen. Beachten Sie, wie wir die Objektwerte, die wir später ersetzen möchten, durch {<code>variable_name</code>}ersetzt haben.
</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc55d69d84a08e668/6a1707d8a2929903acd00fb8/ec7e1ac0cd8b470df13e60940162b56778acb386-315x234.png" alt="" /><p>Anhand der von LLM bereitgestellten Informationen können wir entscheiden, welche Vorlage wir verwenden und welche Werte wir ersetzen.</p><p><code>fill_template_with_analysis</code> empfängt die Parameter für ein einzelnes Panel, einschließlich der JSON-Vorlage der Visualisierung, eines Titels, eines Feldes und der Koordinaten der Visualisierung im Raster.</p><p>Anschließend werden die Werte der Vorlage ersetzt und die endgültige JSON-Visualisierung zurückgegeben.</p>def fill_template_with_analysis(
    template: Dict[str, Any],
    visualization: Visualization,
    grid_data: Dict[str, Any],
):
    template_str = json.dumps(template)
    replacements = {
	 "{visualization_id}": str(uuid.uuid4()),
        "{title}": visualization.title,
        "{x}": grid_data["x"],
        "{y}": grid_data["y"],
    }

    if visualization.field:
        replacements["{field}"] = visualization.field

    for placeholder, value in replacements.items():
        template_str = template_str.replace(placeholder, str(value))

    return json.loads(template_str)<p>Um es einfach zu halten, verwenden wir statische Koordinaten, die wir den vom LLM erstellten Panels zuweisen, und erzeugen so ein 2x2-Raster-Dashboard wie in der obigen Abbildung dargestellt.</p># Filling templates fields
panels = []    
grid_data = [
    {"x": 0, "y": 0},
    {"x": 12, "y": 0},
    {"x": 0, "y": 12},
    {"x": 12, "y": 12},
]


i = 0

for vis in dashboard_values.visualizations:
    for vis_type in vis.type:
        template = templates.get(vis_type, templates.get("bar", {}))
        filled_panel = fill_template_with_analysis(template, vis, grid_data[i])
        panels.append(filled_panel)
        i += 1<p>Je nach dem vom LLM festgelegten Visualisierungstyp wählen wir eine JSON-Dateivorlage aus und ersetzen die relevanten Informationen durch <code>fill_template_with_analysis</code> . Anschließend fügen wir das neue Panel einem Array hinzu, das wir später zum Erstellen des Dashboards verwenden.</p><p>Sobald das Dashboard fertig ist, verwenden wir die <a href="https://www.elastic.co/docs/api/doc/kibana/operation/operation-post-dashboards-dashboard-id">„Create a dashboard“-API</a> , um die neue JSON-Datei an Kibana zu übertragen und das Dashboard zu generieren:
</p>try:
    dashboard_id = str(uuid.uuid4())

    # post request to create the dashboard endpoint
    url = f"{os.getenv('KIBANA_URL')}/api/dashboards/dashboard/{dashboard_id}"

    dashboard_config = {
        "attributes": {
            "title": dashboard_values.title,
            "description": "Generated by AI",
            "timeRestore": True,
            "panels": panels,  # Visualizations with the values generated by the LLM
            "timeFrom": "now-7d/d",
            "timeTo": "now",
        },
    }

    headers = {
        "Content-Type": "application/json",
        "kbn-xsrf": "true",
        "Authorization": f"ApiKey {os.getenv('ELASTICSEARCH_API_KEY')}",
    }

    requests.post(
        url,
        headers=headers,
        json=dashboard_config,
    )

    # Url to the generated dashboard
    dashboard_url = f"{os.getenv('KIBANA_URL')}/app/dashboards#/view/{dashboard_id}"

    print("Dashboard URL: ", dashboard_url)
    print("Dashboard ID: ", dashboard_id)

except Exception as e:
    print(f"Failed to create dashboard: {str(e)}")<p>Um das Skript auszuführen und das Dashboard zu generieren, führen Sie folgenden Befehl in der Konsole aus:</p>python &lt;file_name&gt;.py<p>Das Endergebnis wird folgendermaßen aussehen:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5ceffed004153a4f/6a1707d9a929cf9147ae0901/e909afbf0e47d9a6e0f7bd07dfb2efcfa5cf06ac-921x715.png" alt="" /><h2>Fazit</h2><p>LLMs zeigen ihre ausgeprägten visuellen Fähigkeiten bei der Umwandlung von Text in Code oder der Umwandlung von Bildern in Code. Die Dashboards-API ermöglicht es auch, JSON-Dateien in Dashboards umzuwandeln, und mit einem LLM und etwas Code können wir Bilder in ein Kibana-Dashboard umwandeln.</p><p>Der nächste Schritt besteht darin, die Flexibilität der Dashboard-Visualisierungen durch die Verwendung unterschiedlicher Rastereinstellungen, Dashboard-Größen und -Positionen zu verbessern. Darüber hinaus wäre die Unterstützung komplexerer Visualisierungen und Visualisierungstypen eine sinnvolle Ergänzung dieser Anwendung.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ai-powered-dashboards</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ai-powered-dashboards</guid>
    <category><![CDATA[Kibana]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Jeffrey Rengifo,Tomás Murúa]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt41727cbee6155a68/6a1707dbb0367dd2fd72bc86/eb60ceb2fbc3941745b21ae3357cbb6ea8fab18c-1443x811.png" length="0" type="image/png"/>
    <pubDate>Wed, 16 Jul 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Entwicklung eines agentenbasierten RAG-Assistenten mit JavaScript und Mastra und Elasticsearch]]></title>
    <description><![CDATA[Lerne, wie du KI-Agenten im JavaScript-Ökosystem entwickelst.]]></description>
    <content:encoded><![CDATA[<p>Diese Idee kam mir mitten in einer hitzigen Fantasy-Basketball-Liga mit hohem Einsatz. Ich fragte mich: <em>Könnte ich einen KI-Agenten entwickeln, der mir hilft, meine wöchentlichen Begegnungen zu dominieren? Absolut!</em></p><p>In diesem Beitrag zeigen wir Ihnen, wie Sie mit <a href="https://mastra.ai/en/docs">Mastra</a> einen agentenbasierten RAG-Assistenten und eine leichtgewichtige JavaScript-Webanwendung zur Interaktion mit diesem erstellen. Durch die Anbindung dieses Agenten an Elasticsearch erhalten Sie Zugriff auf strukturierte Spielerdaten und die Möglichkeit, statistische Aggregationen in Echtzeit durchzuführen, um Ihnen auf Spielerstatistiken basierende Empfehlungen geben zu können. Besuchen Sie das GitHub- <a href="https://github.com/jdarmada/nba-ai-assistant-js.git">Repository</a> , um die Schritte nachzuvollziehen; die <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/README.md">README-Datei</a> enthält Anweisungen zum Klonen und Ausführen der Anwendung. </p><p>So sollte es aussehen, wenn alles zusammengebaut ist:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt63ea3e7a09306fbf/6a17f1d97f6f150e22c09c50/1c73bd1dc1b5fe54f025c7a2b7c322acc9122f3a-1999x1393.png" alt="" /><p>Hinweis: Dieser Blogbeitrag baut auf „ <a href="https://www.elastic.co/search-labs/blog/ai-agents-ai-sdk-elasticsearch">Entwicklung von KI-Agenten mit AI SDK und Elastic</a>“ auf. Wenn Sie sich mit KI-Agenten im Allgemeinen noch nicht auskennen und nicht wissen, wofür sie eingesetzt werden könnten, fangen Sie dort an.
</p><h2><strong>Architekturübersicht</strong></h2><p>Kernstück des Systems ist ein großes Sprachmodell (LLM), das als Denkmaschine (das Gehirn) des Agenten fungiert. Es interpretiert die Benutzereingaben, entscheidet, welche Tools aufgerufen werden sollen, und koordiniert die notwendigen Schritte, um eine relevante Antwort zu generieren.</p><p>Der Agent selbst wird von Mastra, einem Agenten-Framework im JavaScript-Ökosystem, bereitgestellt. Mastra umschließt das LLM mit einer Backend-Infrastruktur, stellt es als API-Endpunkt bereit und bietet eine Schnittstelle zur Definition von Tools, Systemaufforderungen und Agentenverhalten.</p><p>Im Frontend verwenden wir <a href="https://vite.dev/guide/">Vite</a> , um schnell eine React-Webanwendung zu erstellen, die eine Chat-Oberfläche zum Senden von Anfragen an den Agenten und zum Empfangen seiner Antworten bereitstellt.</p><p>Schließlich gibt es noch Elasticsearch, das Spielerstatistiken und Matchup-Daten speichert, die der Agent abfragen und aggregieren kann.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte13f09493f217047/6a17f1db1d1b83178d93e546/443bdc00d84ed1dd49e9f9e431e86ca4b0892563-1999x977.png" alt="" /><h2><strong>Hintergrund</strong></h2><p>Lassen Sie uns einige grundlegende Konzepte durchgehen:</p><h3><strong>Was ist agentic RAG?</strong></h3><p>KI-Agenten können mit anderen Systemen interagieren, unabhängig agieren und Aktionen auf Basis ihrer definierten Parameter ausführen. Agentic RAG kombiniert die Autonomie eines KI-Agenten mit den Prinzipien der abrufverstärkten Generierung und ermöglicht es einem LLM, auszuwählen, welche Werkzeuge aufgerufen und welche Daten als Kontext verwendet werden sollen, um eine Antwort zu generieren. Lesen Sie <a href="https://www.elastic.co/search-labs/blog/retrieval-augmented-generation-rag">hier</a> mehr über RAG.</p><h3><strong>Warum sollte man bei der Wahl eines Frameworks über das AI-SDK hinausgehen?</strong></h3><p>Es gibt viele KI-Agenten-Frameworks, und Sie haben wahrscheinlich schon von den bekannteren wie <a href="https://www.elastic.co/search-labs/blog/using-crewai-with-elasticsearch">CrewAI</a>, <a href="https://www.elastic.co/search-labs/blog/using-autogen-with-elasticsearch">AutoGen</a> und <a href="https://www.elastic.co/search-labs/blog/build-rag-workflow-langgraph-elasticsearch">LangGraph</a> gehört. Die meisten dieser Frameworks verfügen über eine gemeinsame Funktionspalette, darunter die Unterstützung verschiedener Modelle, die Verwendung von Werkzeugen und das Speichermanagement.</p><p>Hier finden Sie eine <a href="https://docs.google.com/spreadsheets/d/1B37VxTBuGLeTSPVWtz7UMsCdtXrqV5hCjWkbHN8tfAo/edit?gid=0#gid=0">Vergleichstabelle</a> der verschiedenen Frameworks von Harrison Chase (CEO von LangChain).</p><p>Was mich an Mastra besonders interessiert hat, ist, dass es sich um ein JavaScript-basiertes Framework handelt, das für Full-Stack-Entwickler entwickelt wurde, um Agenten einfach in ihr Ökosystem zu integrieren. Das AI-SDK von Vercel kann das meiste davon auch, aber Mastra glänzt vor allem dann, wenn Ihre Projekte komplexere Agenten-Workflows beinhalten. Mastra erweitert die vom AI-SDK festgelegten Basismuster, und in diesem Projekt werden wir sie gemeinsam verwenden.</p><h3><strong>Rahmenwerke und Überlegungen zur Modellwahl</strong></h3><p>Diese Frameworks können zwar dabei helfen, schnell KI-Agenten zu entwickeln, es gibt jedoch einige Nachteile zu beachten. Wenn man beispielsweise andere Frameworks als KI-Agenten oder Abstraktionsschichten im Allgemeinen verwendet, verliert man ein Stück weit die Kontrolle. Wenn das LLM die Werkzeuge nicht korrekt verwendet oder etwas tut, was Sie nicht möchten, erschwert die Abstraktion die Fehlersuche. Dennoch ist dieser Kompromiss meiner Meinung nach den Komfort und die Geschwindigkeit wert, die man beim Erstellen von Projekten erhält, insbesondere weil diese Frameworks immer beliebter werden und ständig weiterentwickelt werden.</p><p>Auch diese Frameworks sind modellagnostisch, das heißt, Sie können verschiedene Modelle einsetzen und verwenden. Bedenken Sie jedoch, dass sich die Modelle in den Datensätzen unterscheiden, mit denen sie trainiert wurden, und dass sich dadurch auch die Ergebnisse unterscheiden. Manche Modelle unterstützen nicht einmal den Aufruf von Tools. Es ist also möglich, zwischen verschiedenen Modellen zu wechseln und diese auszuprobieren, um zu sehen, welches die besten Ergebnisse liefert. Bedenken Sie jedoch, dass Sie höchstwahrscheinlich für jedes Modell die Systemabfrage neu schreiben müssen. Zum Beispiel mit Llama3.3 Im Vergleich zu GPT-4o sind deutlich mehr Aufforderungen und spezifische Anweisungen erforderlich, um die gewünschte Antwort zu erhalten.</p><h3><strong>NBA Fantasy Basketball</strong></h3><p>Beim Fantasy-Basketball geht es darum, mit einer Gruppe von Freunden eine Liga zu gründen (Achtung: Je nachdem, wie wettbewerbsorientiert eure Gruppe ist, könnte dies den Status eurer Freundschaften beeinträchtigen), wobei in der Regel auch Geld auf dem Spiel steht. Jeder von euch stellt dann ein Team aus 10 Spielern zusammen, die abwechselnd wöchentlich gegen die 10 Spieler eines anderen Freundes antreten. Die Punkte, die zu Ihrer Gesamtpunktzahl beitragen, ergeben sich aus der Leistung jedes Ihrer Spieler gegen seine Gegner in einer bestimmten Woche.</p><p>Wenn ein Spieler Ihres Teams verletzt, gesperrt usw. wird, steht Ihnen eine Liste von Free Agents zur Verfügung, die Sie Ihrem Team hinzufügen können. Hier findet ein Großteil des schwierigen Denkens im Fantasy-Sport statt, denn man hat nur eine begrenzte Anzahl an Spielern zur Auswahl und jeder ist ständig auf der Suche nach dem besten Spieler.</p><p>Hier wird unser NBA-KI-Assistent seine Stärken ausspielen, insbesondere in Situationen, in denen Sie schnell entscheiden müssen, welchen Spieler Sie auswählen. Anstatt manuell nachschlagen zu müssen, wie ein Spieler gegen einen bestimmten Gegner abschneidet, kann der Assistent diese Daten schnell finden und Durchschnittswerte vergleichen, um Ihnen eine fundierte Empfehlung zu geben.</p><p>Nachdem Sie nun einige Grundlagen zu Agentic RAG und NBA Fantasy Basketball kennengelernt haben, sehen wir uns das Ganze mal in der Praxis an.</p><h2><strong>Aufbau des Projekts</strong></h2><p>Falls Sie an irgendeiner Stelle nicht weiterkommen oder es nicht von Grund auf neu erstellen möchten, schauen Sie bitte im <a href="https://github.com/jdarmada/nba-ai-assistant-js.git">Repository</a> nach.</p><h3><strong>Was wir behandeln werden</strong></h3><ol><li><p><strong>Gerüstbau für das Projekt:</strong></p><ol><li><p><strong>Backend (Mastra):</strong> Verwenden Sie npx create mastra@latest, um das Backend zu erstellen und die Agentenlogik zu definieren.</p></li><li><p><strong>Frontend (Vite + React):</strong> Verwenden Sie npm create vite@latest, um die Frontend-Chat-Oberfläche für die Interaktion mit dem Agenten zu erstellen.</p></li></ol></li><li><p><strong>Einrichten von Umgebungsvariablen</strong></p><ol><li><p>Installieren Sie dotenv, um Umgebungsvariablen zu verwalten.</p></li><li><p>Erstellen Sie eine .env-Datei Datei und geben Sie die erforderlichen Variablen an.</p></li></ol></li><li><p><strong>Elasticsearch einrichten</strong></p><ol><li><p>Erstellen Sie einen Elasticsearch-Cluster (entweder lokal oder in der Cloud).</p></li><li><p>Installieren Sie den offiziellen Elasticsearch-Client.</p></li><li><p>Stellen Sie sicher, dass Umgebungsvariablen zugänglich sind.</p></li><li><p>Verbindung zum Client herstellen.</p></li></ol></li><li><p><strong>Massenhaftes Einlesen von NBA-Daten in Elasticsearch</strong></p><ol><li><p>Erstellen Sie einen Index mit den entsprechenden Zuordnungen, um Aggregationen zu ermöglichen.</p></li><li><p>Spielerstatistiken aus einer CSV-Datei massenhaft in einen Elasticsearch-Index importieren.</p></li></ol></li><li><p><strong>Elasticsearch-Aggregationen definieren</strong></p><ol><li><p>Abfrage zur Berechnung historischer Durchschnittswerte gegen einen bestimmten Gegner.</p></li><li><p>Abfrage zur Berechnung der Saison-Durchschnittswerte gegen einen bestimmten Gegner.</p></li></ol></li><li><p><strong>Datei zum Spielervergleich</strong></p><ol><li><p>Konsolidiert Hilfsfunktionen und Elasticsearch-Aggregationen.</p></li></ol></li><li><p><strong>Agentenaufbau</strong></p><ol><li><p>Fügen Sie die Agentendefinition und die Systemeingabeaufforderung hinzu.</p></li><li><p>Installieren Sie zod und definieren Sie Tools.</p></li><li><p>Fügen Sie eine Middleware-Konfiguration zur Behandlung von CORS hinzu.</p></li></ol></li><li><p><strong>Integration des Frontends</strong></p><ol><li><p>Die Interaktion mit dem Agenten erfolgt über die useChat-Funktion des AI-SDK.</p></li><li><p>Erstellen Sie eine Benutzeroberfläche, die ordnungsgemäß formatierte Konversationen ermöglicht.</p></li></ol></li><li><p><strong>Die Anwendung ausführen</strong></p><ol><li><p>Starten Sie sowohl das Backend (Mastra-Server) als auch das Frontend (React-App).</p></li><li><p>Beispielabfragen und Anwendungsbeispiele.</p></li></ol></li><li><p><strong>Was kommt als Nächstes: Den Agenten intelligenter machen.</strong></p><ol><li><p>Durch die Integration semantischer Suchfunktionen können aussagekräftigere Empfehlungen ermöglicht werden.</p></li><li><p>Aktivieren Sie dynamische Abfragen, indem Sie die Suchlogik auf den Elasticsearch MCP (Model Context Protocol)-Server verlagern.</p></li></ol></li></ol><h3><strong>Voraussetzungen</strong></h3><ul><li><p><strong>Node.js und npm</strong>: Sowohl das Backend als auch das Frontend laufen auf Node.js. Stellen Sie sicher, dass Sie Node 18+ und npm v9+ installiert haben (das in Node 18+ standardmäßig enthalten ist).</p></li><li><p><strong>Elasticsearch-Cluster:</strong> Ein aktiver Elasticsearch-Cluster, entweder lokal oder in der Cloud.</p></li><li><p><strong>OpenAI API-Schlüssel</strong>: Generieren Sie einen auf der Seite „API-Schlüssel“ im <a href="https://platform.openai.com/api-keys">Entwicklerportal von OpenAI</a>.</p></li></ul><p></p><h3><strong>Projektstruktur</strong></h3><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt749baa120552e4ab/6a17f1dd1d1b83bfe993e54a/1c0bde11ad0eead523a95e03b9b905aa776e3fd1-1420x934.png" alt="" /><h4><strong>Schritt 1: Das Projektgerüst erstellen</strong></h4><ol><li><p>Erstellen Sie zunächst das Verzeichnis nba-ai-assistant-js und navigieren Sie darin mit folgendem Befehl: </p></li></ol>mkdir nba-ai-assistant-js &amp;&amp; cd nba-ai-assistant-js<p><strong>Backend:</strong></p><ol><li><p>Verwenden Sie das Mastra-Erstellungstool mit folgendem Befehl: </p></li></ol>npx create-mastra@latest<p>2. Sie sollten nun einige Eingabeaufforderungen in Ihrem Terminal erhalten. Bei der ersten nennen wir das Projekt-Backend:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt65abf68fe588e968/6a17f1de63baff2814741d5b/de2725031ed6837db99a979efcdd0ece1e197dbb-608x84.png" alt="" /><p>3. Als nächstes behalten wir die Standardstruktur für die Speicherung der Mastra-Dateien bei, also Eingabe <code>src/</code>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt89bd829fcf0ae6b9/6a17f1e04b055dd30e432302/88919d9ff1852126395e1fcd700ecb1b59aac63c-866x116.png" alt="" /><p>4. Dann wählen wir OpenAI als unseren Standard-LLM-Anbieter.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfd167cc77a40b9a8/6a17f1e11480099e29b48863/2328761e769f3ded134e5a21e8a0bf8f41e88f68-404x210.png" alt="" /><p>5. Abschließend werden Sie nach Ihrem OpenAI-API-Schlüssel gefragt. Fürs Erste wählen wir die Option, dies zu überspringen und es später in einer<code> .env</code> -Datei bereitzustellen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt12654151ed495370/6a17f1e22f4a5c0f84fa89f9/0662de9bd28758e377e4c63df8d08b479068ce63-444x120.png" alt="" /><p><strong>Frontend:</strong></p><ol><li><p>Wechseln Sie zurück in das Stammverzeichnis und führen Sie das <a href="https://vite.dev/guide/">Vite-Erstellungstool</a> mit folgendem Befehl aus: <code>npm create vite@latest frontend -- --template react</code></p></li></ol><p>Dadurch sollte eine leichtgewichtige React-App mit dem Namen <code>frontend</code> und einer spezifischen Vorlage für React erstellt werden.</p><p>Wenn alles gut geht, sollten Sie in Ihrem Projektverzeichnis ein Backend-Verzeichnis sehen, das den Mastra-Code enthält, und ein <code>frontend</code> -Verzeichnis mit Ihrer React-App.</p><p></p><h4><strong>Schritt 2: Umgebungsvariablen einrichten</strong></h4><ol><li><p>Zur Verwaltung sensibler Schlüssel verwenden wir das Paket <code>dotenv</code> , um unsere Umgebungsvariablen aus der .env-Datei zu laden. Datei. Navigieren Sie zum Backend-Verzeichnis und installieren Sie <code>dotenv</code>:</p></li></ol>cd backend
npm install dotenv --save<p>2. Im Backend-Verzeichnis befindet sich eine example.env-Datei mit den entsprechenden Variablen zum Ausfüllen. Wenn Sie Ihre eigene Version erstellen, achten Sie darauf, die folgenden Variablen einzubeziehen:</p># OpenAI Configuration
OPENAI_API_KEY=your_openai_api_key_here

# Elasticsearch Configuration
ELASTIC_ENDPOINT=your_elasticsearch_endpoint_here
ELASTIC_API_KEY=your_elasticsearch_api_key_here
<p></p><p>Hinweis: Stellen Sie sicher, dass diese Datei von Ihrer Versionskontrolle ausgeschlossen wird, indem Sie <code>.env</code> zu <code>.gitignore</code> hinzufügen.</p><h4><strong>Schritt 3: Elasticsearch einrichten</strong></h4><p>Als Erstes benötigen Sie einen aktiven Elasticsearch-Cluster. Es gibt zwei Möglichkeiten:</p><ul><li><p><strong>Option A: Elasticsearch Cloud verwenden</strong></p><ul><li><p>Registrieren Sie sich für <a href="https://cloud.elastic.co/registration">Elastic Cloud</a></p></li><li><p>Erstellen Sie eine neue Bereitstellung</p></li><li><p>Rufen Sie Ihre Endpunkt-URL und Ihren API-Schlüssel (kodiert) ab.</p></li></ul></li><li><p><strong>Option B: Elasticsearch lokal ausführen</strong></p><ul><li><p>Elasticsearch lokal installieren und ausführen</p></li><li><p>Verwenden Sie http://localhost:9200 als Endpunkt.</p></li><li><p>API-Schlüssel generieren</p></li></ul></li></ul><p></p><p><strong>Installation des Elasticsearch-Clients auf dem Backend:</strong></p><ol><li><p>Installieren Sie zunächst den offiziellen Elasticsearch-Client in Ihrem Backend-Verzeichnis:</p></li></ol>npm install @elastic/elasticsearch<p>2. Erstellen Sie anschließend ein Verzeichnis „lib“, um wiederverwendbare Funktionen zu speichern, und wechseln Sie in dieses Verzeichnis:</p>mkdir lib &amp;&amp; cd lib<p>3. Erstellen Sie darin eine neue Datei namens <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/lib/elasticClient.js">elasticClient.js</a>. Diese Datei initialisiert den Elasticsearch-Client und stellt ihn für die Verwendung in Ihrem gesamten Projekt zur Verfügung.</p><p>4. Da wir ECMAScript-Module (ESM) verwenden, sind __dirname and __-Dateinamen nicht verfügbar. Um sicherzustellen, dass Ihre Umgebungsvariablen korrekt aus der .env-Datei geladen werden Fügen Sie diese Konfiguration am Anfang der Datei im Backend-Ordner hinzu:</p>import { config } from 'dotenv';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { Client } from '@elastic/elasticsearch';

// Grab current directory and load .env from backend folder
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const envPath = join(__dirname, '../.env');

// Load environment variables from the correct path
config({ path: envPath });<p>5. Initialisieren Sie nun den Elasticsearch-Client mithilfe Ihrer Umgebungsvariablen und überprüfen Sie die Verbindung:</p>//Elastic client Initialization, make sure environment variables are being loaded in correctly
const config= {
    node: `${process.env.ELASTIC_ENDPOINT}`,
    auth: {
        apiKey: `${process.env.ELASTIC_API_KEY}`,
    },
};

export const elasticClient = new Client(config);

//Check if the client is connected
async function checkConnection() { 
    try {
        const info = await elasticClient.info();
        console.log('Elasticsearch is connected:', info);
    } catch (error) {
        console.error('Elasticsearch connection error:', error);
    }
}

checkConnection();
<p>Nun können wir diese Clientinstanz in jede Datei importieren, die mit Ihrem Elasticsearch-Cluster interagieren muss.</p><p></p><h4><strong>Schritt 4: Massenhaftes Einlesen von NBA-Daten in Elasticsearch</strong></h4><p><strong>Datensatz:</strong></p><p>Für dieses Projekt werden wir auf die Datensätze im Verzeichnis <a href="https://github.com/jdarmada/nba-ai-assistant-js/tree/main/backend">backend/data</a> des Repos zurückgreifen. Unser NBA-Assistent wird diese Daten als Wissensbasis für statistische Vergleiche und die Generierung von Empfehlungen nutzen.</p><ul><li><p><a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/data/sample_nba_data.csv">sample_player_game_stats.csv</a> - Beispielhafte Spielstatistiken eines Spielers (z. B. Punkte, Rebounds, Steals usw.) pro Spiel und Spieler während seiner gesamten NBA-Karriere. Wir werden diesen Datensatz für Aggregationen verwenden. (Hinweis: Dies sind Beispieldaten, die zu Demonstrationszwecken generiert wurden und nicht aus offiziellen NBA-Quellen stammen.)</p></li><li><p><a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/data/playerAndTeamInfo.js">playerAndTeamInfo.js</a> - Ersetzt die Spieler- und Team-Metadaten, die normalerweise über einen API-Aufruf bereitgestellt werden, damit der Agent Spieler- und Teamnamen IDs zuordnen kann. Da wir Beispieldaten verwenden, möchten wir den Aufwand des Abrufens von einer externen API vermeiden. Daher haben wir einige Werte fest codiert, auf die der Agent zugreifen kann.</p></li></ul><p></p><p><strong>Durchführung:</strong></p><ol><li><p>Erstellen Sie im Verzeichnis <code>backend/lib</code> eine Datei mit dem Namen <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/lib/playerDataIngestion.js">playerDataIngestion.js</a>.</p></li><li><p>Importe einrichten, den CSV-Dateipfad auflösen und das Parsen einrichten. Da wir ESM verwenden, müssen wir <code>__dirname</code> rekonstruieren, um den Pfad zur Beispiel-CSV-Datei aufzulösen. Außerdem importieren wir <a href="http://node.js/">Node.js.</a> eingebaute Module <code>fs</code> und <code>readline</code>, um die gegebene CSV-Datei Zeile für Zeile zu analysieren.</p></li></ol>import fs from 'fs';
import readline from 'readline';
import path from 'path';
import { fileURLToPath } from 'url';
import { elasticClient } from './elasticClient.js';

const indexName = 'sample-nba-player-data'; //Replace with your preferred index name

//Since we are using ES modules __dirname and __filename don't exist, so this is a workaround that allows us to use the absolute file path for our sample data.
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const filePath = path.resolve(__dirname, '../data/sample_nba_data.csv');<p>Damit sind Sie bestens gerüstet, um die CSV-Datei effizient zu lesen und zu analysieren, wenn wir zum Schritt der Massenverarbeitung übergehen.</p><p>3. Erstellen Sie einen Index mit der entsprechenden Zuordnung. Obwohl Elasticsearch Feldtypen mithilfe von <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/dynamic">Dynamic Mapping</a> automatisch ableiten kann, möchten wir hier explizit vorgehen, damit jede Statistik als numerisches Feld behandelt wird. Dies ist wichtig, da wir diese Felder später für Aggregationen verwenden werden. Wir möchten außerdem den Typ <code>float </code>für Statistiken wie Punkte, Rebounds usw. verwenden, um sicherzustellen, dass wir Dezimalwerte einbeziehen. Zum Schluss möchten wir die Mapping-Eigenschaft <code>dynamic: 'strict'</code> hinzufügen, damit Elasticsearch nicht dynamisch nicht erkannte Felder zuordnet. 
</p>// Function to create an index with mappings
async function createIndex() {
    try {
        // Check if the index already exists
        const exists = await elasticClient.indices.exists({ index: indexName });

        if (exists) {
            console.log(`Index "${indexName}" already exists, deleting it now.`);
            await elasticClient.indices.delete({ index: indexName });
            console.log(`Deleted index "${indexName}".`);
        }
        // Create the index with mappings
        const response = await elasticClient.indices.create({
            index: indexName,
            body: {
                mappings: {
                    dynamic: 'strict', // Prevent dynamic mapping
                    properties: {
                        game_id: { type: 'integer' },
                        game_date: { type: 'date' },
                        player_id: { type: 'integer' },
                        player_full_name: { type: 'text' },
                        player_team_id: { type: 'integer' },
                        player_team_name: { type: 'text' },
                        home_team: { type: 'boolean' },
                        opponent_team_id: { type: 'integer' },
                        opponent_team_name: { type: 'text' },
                        points: { type: 'float' },
                        rebounds: { type: 'float' },
                        assists: { type: 'float' },
                        steals: { type: 'float' },
                        blocks: { type: 'float' },
                        fg_percentage: { type: 'float' },
                        minutes_played: { type: 'float' },
                    },
                },
            },
        });

        console.log('Index created:', response);
        return true;
    } catch (error) {
        console.error('Error creating index:', error);
        return false;
    }
}
<p>4. Fügen Sie die Funktion hinzu, um die CSV-Daten in Ihren Elasticsearch-Index zu importieren. Innerhalb des Codeblocks überspringen wir die Kopfzeile. Anschließend werden die einzelnen Zeilen durch Kommas getrennt und in das Dokumentobjekt eingefügt. Dieser Schritt reinigt sie außerdem und stellt sicher, dass es sich um den richtigen Typ handelt. Als nächstes fügen wir die Dokumente zusammen mit den Indexinformationen in das bulkBody-Array ein, welches als Nutzlast für die Massenaufnahme in Elasticsearch dient.</p>async function bulkIngestCsv(filePath) {
    const readStream = fs.createReadStream(filePath);
    const rl = readline.createInterface({
        input: readStream,
        crlfDelay: Infinity,
    });

    const bulkBody = [];
    let lineNum = 0;

    //Skip the header line
    let headerLine = true;
    for await (const line of rl) {
        if (headerLine) {
            headerLine = false;
            continue;
        }
        lineNum++;

        // Split the line by comma and remove whitespace
        const [
            game_id,
            game_date,
            player_id,
            player_full_name,
            player_team_id,
            player_team_name,
            home_team,
            opponent_team_id,
            opponent_team_name,
            points,
            rebounds,
            assists,
            steals,
            blocks,
            fg_percentage,
            minutes_played,
        ] = line.split(',');

        // Create a document object
        const document = {
            game_id: parseInt(game_id),
            game_date: game_date.trim(),
            player_id: parseInt(player_id),
            player_full_name: player_full_name.trim(),
            player_team_id: parseInt(player_team_id),
            player_team_name: player_team_name.trim(),
            home_team: home_team.trim() === 'True', // Converts True/False into a boolean
            opponent_team_id: parseInt(opponent_team_id),
            opponent_team_name: opponent_team_name.trim(),
            points: parseFloat(points),
            rebounds: parseFloat(rebounds),
            assists: parseFloat(assists),
            steals: parseFloat(steals),
            blocks: parseFloat(blocks),
            fg_percentage: parseFloat(fg_percentage),
            minutes_played: parseFloat(minutes_played),
        };

        // Prepare the bulk operation format
        bulkBody.push({ index: { _index: indexName } });
        bulkBody.push(document);
    }

    console.log(`Parsed ${lineNum} lines from CSV`);
<p>5. Anschließend können wir <a href="https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-bulk">die Bulk-API</a> von Elasticsearch mit <code>elasticClient.bulk()</code> verwenden, um mehrere Dokumente in einer einzigen Anfrage zu erfassen. Die unten beschriebene Fehlerbehandlung ist so aufgebaut, dass sie Ihnen eine Übersicht darüber gibt, wie viele Dokumente nicht eingelesen werden konnten und wie viele erfolgreich eingelesen wurden.</p>try {
        // Perform the bulk request
        const response = await elasticClient.bulk({ body: bulkBody });

        if (response.errors) {
            console.log('Bulk Ingestion had some hiccups:');

            // Count successful vs failed operations
            let successCount = 0;
            let errorCount = 0;
            const errorDetails = [];

            response.items.forEach((item, index) =&gt; {
                const operation = item.index || item.create || item.update || item.delete;
                if (operation.error) {
                    errorCount++;
                    errorDetails.push({
                        document: index + 1,
                        error: operation.error,
                    });
                } else {
                    successCount++;
                }
            });

            console.log(`Successfully indexed: ${successCount} documents`);
            console.log(`Failed to index: ${errorCount} documents, here are the details`, errorDetails);

        } else {
            console.log(`Bulk Ingestion fully successful!`);
        }

    } catch (error) {
        console.error('Error performing bulk ingestion:', error);
    }
}
<p>6. Führen Sie die unten stehende Funktion <code>main()</code> aus, um die Funktionen <code>createIndex()</code> und <code>bulkIngestCsv()</code> nacheinander auszuführen.</p>// Run this function
async function main() {
    const result = await createIndex();
    if (!result) {
        console.error('Index setup failed. Aborting.');
        return;
    }

    await bulkIngestCsv(filePath);
    console.log('Bulk ingestion completed!');
}

main();
<p>Wenn in der Konsole eine Meldung erscheint, dass die Massenaufnahme erfolgreich war, überprüfen Sie kurz Ihren Elasticsearch-Index, um festzustellen, ob die Dokumente tatsächlich erfolgreich aufgenommen wurden.</p><h4><strong>Schritt 5: Elasticsearch-Aggregationen definieren und konsolidieren</strong></h4><p>Dies sind die Hauptfunktionen, die wir verwenden werden, wenn wir die Werkzeuge für den KI-Agenten definieren, um die Statistiken der Spieler miteinander zu vergleichen.</p><p>1. Navigieren Sie zum Verzeichnis <code>backend/lib</code> und erstellen Sie eine Datei namens <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/lib/elasticAggs.js">elasticAggs.js</a>.</p><p>2. Fügen Sie die unten stehende Abfrage hinzu, um historische Durchschnittswerte für einen Spieler gegen einen bestimmten Gegner zu berechnen. Diese Abfrage verwendet einen <code>bool</code> <a href="https://www.elastic.co/search-labs/tutorials/search-tutorial/full-text-search/filters">-Filter</a> mit 2 Bedingungen: eine, die <code>player_id</code> entspricht, und eine weitere, die <code>opponent_team_id</code> entspricht, um nur die relevanten Spiele abzurufen. Wir müssen keine Dokumente zurückgeben, uns geht es nur um die Aggregationen, deshalb setzen wir <code>size:0</code>. Im Block <code>aggs</code> führen wir mehrere <a href="https://www.elastic.co/docs/explore-analyze/query-filter/aggregations">Metrikaggregationen</a> parallel auf Feldern wie <code>points, rebounds, assists, steals, blocks</code> und <code>fg_percentage</code> durch, um deren Durchschnittswerte zu berechnen. LLMs können bei Berechnungen ungenau sein, und dies lagert diesen Prozess an Elasticsearch aus, um sicherzustellen, dass unser NBA-KI-Assistent Zugriff auf genaue Daten hat.</p>export async function getHistoricalAveragesAgainstOpponent(player_id, opponent_team_id) {
    try {
        //Query for Historical Averages
        const historicalQuery = await elasticClient.search({
            index: 'sample-nba-player-data', 
            size: 0,
            query: {
                bool: {
                    must: [
                        {
                            term: {
                                player_id: {
                                    value: player_id,
                                },
                            },
                        },
                        {
                            term: {
                                opponent_team_id: {
                                    value: opponent_team_id,
                                },
                            },
                        },
                    ],
                },
            },
            aggs: {
                avg_points: { avg: { field: 'points' } },
                avg_rebounds: { avg: { field: 'rebounds' } },
                avg_assists: { avg: { field: 'assists' } },
                avg_steals: { avg: { field: 'steals' } },
                avg_blocks: { avg: { field: 'blocks' } },
             avg_fg_percentage: { avg: { field: 'fg_percentage' } },
            },
        });

        return {
            points: historicalQuery.aggregations.avg_points.value || 0,
            rebounds: historicalQuery.aggregations.avg_rebounds.value || 0,
            assists: historicalQuery.aggregations.avg_assists.value || 0,
            steals: historicalQuery.aggregations.avg_steals.value || 0,
            blocks: historicalQuery.aggregations.avg_blocks.value || 0,
            fgPercentage: historicalQuery.aggregations.avg_fg_percentage.value || 0,
        };
    } catch (error) {
        console.error('Query error from getHistoricalAveragesAgainstOpponent function:', error);
        return { error: 'Queries failed in getting historical averages against opponent.' };
    }
}
<p>3. Um die Saisondurchschnittswerte eines Spielers gegen einen bestimmten Gegner zu berechnen, verwenden wir praktisch die gleiche Abfrage wie für die historischen Ergebnisse. Der einzige Unterschied bei dieser Abfrage besteht darin, dass der <code>bool</code> -Filter eine zusätzliche Bedingung für <code>game_date</code> enthält. Das Feld <code>game_date</code> muss innerhalb des Bereichs der aktuellen NBA-Saison liegen. In diesem Fall liegt der Bereich zwischen <code>2024-10-01</code> und <code>2025-06-30</code>. Die unten stehende zusätzliche Bedingung stellt sicher, dass die nachfolgenden Aggregationen nur die Spiele dieser Saison berücksichtigen.
</p>        {
                            range: {
                    //Range for this season, change to match current season
                                game_date: {
                                    gte: '2024-10-01',
                                    lte: '2025-06-30',
                                },
                            },
<h4><strong>Schritt 6: Spielervergleichstool</strong></h4><p>Um unseren Code modular und wartbar zu halten, erstellen wir eine Hilfsdatei, die Metadaten-Hilfsfunktionen und Elasticsearch-Aggregationen zusammenfasst. Dies wird das Hauptwerkzeug des Agenten mit Strom versorgen. Mehr dazu später:</p><p>1. Erstellen Sie eine neue Datei <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/lib/comparePlayers.js">comparePlayers.js</a> im Verzeichnis <code>backend/lib</code> .</p><p>2. Fügen Sie die unten stehende Funktion hinzu, um Metadaten-Helfer und Elasticsearch-Aggregationslogik in einer einzigen Funktion zu konsolidieren, die das Hauptwerkzeug des Agenten antreibt.
</p>import { playersByName } from '../data/playerAndTeamInfo.js';
import { teamsByName } from '../data/playerAndTeamInfo.js';
import { upcomingMatchups } from '../data/playerAndTeamInfo.js';
import { getHistoricalAveragesAgainstOpponent } from './elasticAggs.js';
import { getSeasonAveragesAgainstOpponent } from './elasticAggs.js';

//Simple helper functions to simulate API calls for player and team metadata. These reference the hardcoded values from playerAndTeamInfo.js in the data directory
export function getPlayerInfo(playerFullName) {
    return playersByName[playerFullName];
}

export function getTeamID(teamFullName) {
    return teamsByName[teamFullName];
}

export function getUpcomingMatchups(teamId) {
    return upcomingMatchups[teamId];
}

//Main function used by the 'playerComparisonTool' agent tool
export async function comparePlayersForNextMatchup(player1Name, player2Name) {
    //Get Player Info
    const player1Info = getPlayerInfo(player1Name);
    const player2Info = getPlayerInfo(player2Name);

    //Get upcoming matchups
    const player1NextGame = getUpcomingMatchups(player1Info.team_id)[0];
    const player2NextGame = getUpcomingMatchups(player2Info.team_id)[0];

    //Get season and historical averages against next opponent for player 1
    const player1SeasonAverages = await getSeasonAveragesAgainstOpponent(
        player1Info.player_id,
        player1NextGame.opponent_team_id
    );
    const player1HistoricalAverages = await getHistoricalAveragesAgainstOpponent(
        player1Info.player_id,
        player1NextGame.opponent_team_id
    );

    //Get season and historical averages against next opponent for player 2
    const player2SeasonAverages = await getSeasonAveragesAgainstOpponent(
        player2Info.player_id,
        player2NextGame.opponent_team_id
    );
    const player2HistoricalAverages = await getHistoricalAveragesAgainstOpponent(
        player2Info.player_id,
        player2NextGame.opponent_team_id
    );

    const player1 = {
        name: player1Name,
        playerId: player1Info.player_id,
        teamId: player1Info.team_id,
        nextOpponent: {
            teamId: player1NextGame.opponent_team_id,
            teamName: player1NextGame.opponent_team_name,
            home: player1NextGame.home,
        },
        stats: {
            seasonAverages: player1SeasonAverages,
            historicalAverages: player1HistoricalAverages,
        },
    };

    const player2 = {
        name: player2Name,
        playerId: player2Info.player_id,
        teamId: player2Info.team_id,
        nextOpponent: {
            teamId: player2NextGame.opponent_team_id,
            teamName: player2NextGame.opponent_team_name,
            home: player2NextGame.home,
        },
        stats: {
            seasonAverages: player2SeasonAverages,
            historicalAverages: player2HistoricalAverages,
        },
    };

    return [player1, player2];
}
<h4><strong>Schritt 7: Erstellung des Agenten</strong></h4><p>Nachdem Sie nun das Frontend- und Backend-Gerüst erstellt, NBA-Spieldaten eingespielt und eine Verbindung zu Elasticsearch hergestellt haben, können wir damit beginnen, alle Teile zusammenzufügen, um den Agenten zu entwickeln.</p><p><strong>Definition des Agenten</strong></p><p>1. Navigieren Sie zur Datei <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/src/mastra/agents/index.ts">index.ts</a> im Verzeichnis <code>backend/src/mastra/agents</code> und fügen Sie die Agentendefinition hinzu. Sie können Felder wie die folgenden angeben:</p><ul><li><p><strong>Name:</strong> Geben Sie Ihrem Agenten einen Namen, der als Referenz verwendet wird, wenn er im Frontend aufgerufen wird.</p></li><li><p><strong>Anweisungen/Systemaufforderung: </strong>Eine Systemaufforderung gibt dem LLM den anfänglichen Kontext und die Regeln vor, die während der Interaktion zu befolgen sind. Es ähnelt der Aufforderung, die Benutzer über das Chatfenster senden, diese wird jedoch vor jeglicher Benutzereingabe angezeigt. Auch dies hängt vom gewählten Modell ab.</p></li><li><p><strong>Modell:</strong> Welches LLM soll verwendet werden (Mastra unterstützt OpenAI, Anthropic, lokale Modelle usw.)?</p></li><li><p><strong>Tools:</strong> Eine Liste der Tool-Funktionen, die der Agent aufrufen kann.</p></li><li><p><strong>Speicher:</strong> (Optional) Wenn der Agent sich den Gesprächsverlauf usw. merken soll. Der Einfachheit halber können wir ohne persistenten Speicher beginnen, obwohl Mastra diesen unterstützt.</p></li></ul><p></p>import { openai } from '@ai-sdk/openai';
import { Agent } from '@mastra/core/agent';
import { playerComparisonTool } from '../tools';

export const basketballAgent = new Agent({
    name: 'Basketball Agent',
    instructions: `
      You are a NBA Basketball expert.
      Your primary function is to compare two NBA players and recommend which one is the better fantasy pickup.

      Only compare players from the following list:
      - LeBron James
      - Stephen Curry
      - Jayson Tatum
      - Jaylen Brown
      - Nikola Jokic
      - Luka Doncic
      - Kyrie Irving
      - Anthony Davis
      - Kawhi Leonard
      - Russell Westbrook

      Input Handling Rules:
      - If the user asks about a player that is not on this list, respond with the list of available players for comparison.
      - If the user only inputs one player, ask the user to add another player from the list provided.
      - If the user inputs a player with the wrong spelling or capitalizations, infer from the list of available players provided.
      - IMPORTANT: If the user asks a question or asks you to generate a response about anything outside of basketball or the scope of this project, DO NOT answer and affirm you can only talk about basketball.

      Tool Usage:
      - Extract and standardize player names to match the list exactly.
      - Use the playerComparisonTool, passing both names as strings.
      - The tool will return an object with game information, stats, and analysis.

      Format your response using Markdown syntax. Use:

        Example output format:

       
        #### Next Game Info
        - ***LeBron James** vs Warriors, May 24 (Home)  
        - ***Stephen Curry** vs Lakers, May 24 (Away)


        #### Stats Comparison  
        \`\`\`  
        Stat                  LeBron James (vs Warriors)    Stephen Curry (vs Lakers)  
        --------------------  -----------------------------  ----------------------------  
        Historical Points     28.3                          30.3  
        Historical Assists    6.7                           8.7  
        Season Points         28.8                          23.3  
        Season Assists        6.2                           4.7  
        \`\`\`

        #### Fantasy Recommendation  
        Explain which player is the better fantasy pickup and why.
      
    `,
    model: openai('gpt-4o'),
    tools: { playerComparisonTool },
});
<p><strong>
Werkzeuge definieren</strong></p><ol><li><p>Navigieren Sie zur Datei <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/src/mastra/tools/index.ts">index.ts</a> im Verzeichnis <code>backend/src/mastra/tools</code> .</p></li><li><p>Installieren Sie Zod mit folgendem Befehl:</p></li></ol>npm install zod<p>3. Werkzeugdefinitionen hinzufügen. Beachten Sie, dass wir die Funktion innerhalb der Datei <code>comparePlayers.js</code> als Hauptfunktion importieren, die der Agent beim Aufruf dieses Tools verwenden wird. Mit der Funktion <code>createTool()</code> von Mastra registrieren wir unser <code>playerComparisonTool</code>. Zu den Feldern gehören:</p><ul><li><p><code>id</code>Dies ist eine Beschreibung in natürlicher Sprache, die dem Agenten hilft zu verstehen, was das Tool leistet.</p></li><li><p><code>input schema</code>Um die Form der Eingabe für das Tool zu definieren, verwendet Mastra das <a href="https://zod.dev/">Zod</a> -Schema, eine TypeScript-Bibliothek zur Schema-Validierung. Zod hilft dabei, indem es sicherstellt, dass der Agent korrekt strukturierte Eingaben vornimmt und die Ausführung des Tools verhindert, wenn die Eingabestruktur nicht übereinstimmt.</p></li><li><p><code>description</code>Dies ist eine Beschreibung in natürlicher Sprache, die dem Agenten helfen soll zu verstehen, wann er anrufen und das Tool verwenden soll.</p></li><li><p><code>execute</code>Die Logik, die beim Aufruf des Tools ausgeführt wird. In unserem Fall verwenden wir eine importierte Hilfsfunktion, um Leistungsstatistiken zurückzugeben.</p></li></ul>import { comparePlayersForNextMatchup } from '../../../lib/comparePlayers.js'
import { createTool } from "@mastra/core/tools";
import { z } from "zod";

export const playerComparisonTool = createTool({
    id: "Compare two NBA players",
    inputSchema: z.object({
        player1:z.string(),
        player2:z.string()
    }),
    description: "Use this tool to compare two players given in the user prompt.",
    execute: async ({ context: { player1, player2 } }) =&gt; {
        return await comparePlayersForNextMatchup(player1, player2);
      },
})<p><strong>Hinzufügen von Middleware zur Behandlung von CORS</strong></p><p>Fügen Sie Middleware auf dem Mastra-Server hinzu, um <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS">CORS</a> zu behandeln. Man sagt, es gäbe drei Dinge im Leben, denen man nicht entkommen kann: den Tod, die Steuern und für Webentwickler zusätzlich CORS. Kurz gesagt, Cross-Origin Resource Sharing ist eine Browser-Sicherheitsfunktion, die verhindert, dass das Frontend Anfragen an ein Backend sendet, das auf einer anderen Domain oder einem anderen Port läuft. Obwohl wir sowohl das Backend als auch das Frontend auf localhost betreiben, verwenden sie unterschiedliche Ports, wodurch die CORS-Richtlinie ausgelöst wird. Wir müssen die in der <a href="https://mastra.ai/en/docs/server-db/middleware">Mastra-Dokumentation</a> beschriebene Middleware hinzufügen, damit unser Backend diese Anfragen vom Frontend zulässt.</p><p>1. Navigieren Sie zur Datei <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/backend/src/mastra/index.ts">index.ts</a> im Verzeichnis <code>backend/src/mastra</code> und fügen Sie die Konfiguration für CORS hinzu:</p><ul><li><p><code>origin: ['http://localhost:5173']</code></p><ul><li><p>Erlaubt Anfragen nur von dieser Adresse (Vite-Standardadresse)</p></li></ul></li><li><p><code>allowMethods: ["GET", "POST"]</code></p><ul><li><p>Zulässige HTTP-Methoden. In den meisten Fällen wird POST verwendet.</p></li></ul></li><li><p><code>allowHeaders: ["Content-Type", "Authorization", "x-mastra-client-type, "x-highlight-request", "traceparent"],</code></p><ul><li><p>Diese legen fest, welche benutzerdefinierten Header in Anfragen verwendet werden können.</p></li></ul></li></ul><p></p>import { Mastra } from '@mastra/core/mastra';
import { basketballAgent } from './agents';

console.log('Starting Mastra server...');

export const mastra = new Mastra({
  agents: { basketballAgent },
  server:{
    timeout: 10 * 60 * 1000, // 10 minutes
    cors: {
      origin: ['http://localhost:5173'],
      allowMethods: ["GET", "POST"],
      allowHeaders: [
        "Content-Type",
        "Authorization",
        "x-mastra-client-type",
        "x-highlight-request",
        "traceparent",
      ],
      exposeHeaders: ["Content-Length", "X-Requested-With"],
      credentials: false,
    },
  },

});

console.log('Mastra server configured.'); // Log after server configuration
<h4><strong>Schritt 8: Integration des Frontends</strong></h4><p>Diese React-Komponente stellt eine einfache Chat-Oberfläche bereit, die über den <a href="https://mastra.ai/en/docs/frameworks/agentic-uis/ai-sdk#using-the-usechat-hook">useChat()</a> -Hook aus <code>@ai-sdk/react</code> eine Verbindung zum Mastra AI-Agenten herstellt. Wir werden diesen Hook auch verwenden, um die Tokenverwendung und Toolaufrufe anzuzeigen sowie die Konversation darzustellen. In der obigen Systemabfrage bitten wir den Agenten außerdem, die Antwort im Markdown-Format auszugeben. Daher verwenden wir <code>react-markdown</code> , um die Antwort korrekt zu formatieren.</p><p></p><p>1. Installieren Sie im Frontend-Verzeichnis das Paket @ai-sdk/react, um den useChat()-Hook verwenden zu können.</p>npm install @ai-sdk/react<p>2. Installieren Sie im selben Verzeichnis React Markdown, damit wir die vom Agenten generierte Antwort richtig formatieren können.</p>npm install react-markdown<p>3. Implementiere <code>useChat()</code>. Dieser Hook steuert die Interaktion zwischen Ihrem Frontend und Ihrem KI-Agenten-Backend. Es verarbeitet Nachrichtenstatus, Benutzereingaben und Statusinformationen und bietet Lebenszyklus-Hooks zur Überwachung. Zu den Optionen, die wir übergeben, gehören:</p><ul><li><p><code>api:</code> Dies definiert den Endpunkt Ihres Mastra AI-Agenten. Standardmäßig wird Port 4111 verwendet, und wir möchten außerdem die Route hinzufügen, die Streaming-Antworten unterstützt.</p></li><li><p><code>onToolCall</code>Dies wird immer dann ausgeführt, wenn der Agent ein Tool aufruft; wir verwenden es, um zu verfolgen, welche Tools unser Agent aufruft.</p></li><li><p><code>onFinish</code>Dies wird ausgeführt, nachdem der Agent eine vollständige Antwort abgegeben hat. Auch wenn wir Streaming aktiviert haben, wird <code>onFinish</code> erst ausgeführt, nachdem die gesamte Nachricht empfangen wurde, und nicht nach jedem einzelnen Datenblock. Hier verwenden wir es, um unsere Token-Nutzung zu verfolgen. Dies kann hilfreich sein, um die LLM-Kosten zu überwachen und zu optimieren.</p></li></ul><p>4. Zum Schluss gehen Sie zur Komponente <a href="https://github.com/jdarmada/nba-ai-assistant-js/blob/main/frontend/components/ChatUI.jsx">ChatUI.jsx</a> im Verzeichnis <code>frontend/components</code> , um die Benutzeroberfläche für unsere Konversation zu erstellen. Als Nächstes muss die Antwort in eine <code>ReactMarkdown</code> -Komponente eingeschlossen werden, um die Antwort des Agenten korrekt zu formatieren.</p>import React, { useState } from 'react';
import { useChat } from '@ai-sdk/react';
import ReactMarkdown from 'react-markdown';

export default function ChatUI() {
    const [totalTokenUsage, setTotalTokenUsage] = useState(0);
    const [promptTokenUsage, setPromptTokenUsage] = useState(0);
    const [completionTokenUsage, setCompletionTokenUsage] = useState(0);
    const [toolsCalled, setToolsCalled] = useState([]);

    const { messages, input, handleInputChange, handleSubmit, status } = useChat({
        api: 'http://localhost:4111/api/agents/basketballAgent/stream', //Replace with your own endpoint for your agent
        id: 'my-chat-session',

        //Optional parameter to check agent tool calls
        onToolCall: ({ toolCall }) =&gt; {
            setToolsCalled((prev) =&gt; [...prev, toolCall.toolName]);
        },

        //Optional parameter to check token usages
        onFinish: (message, { usage }) =&gt; {
            setTotalTokenUsage((prev) =&gt; prev + usage.totalTokens);
            setPromptTokenUsage((prev) =&gt; prev + usage.promptTokens);
            setCompletionTokenUsage((prev) =&gt; prev + usage.completionTokens);
        },

        //Optional parameter for error handling
        onError: (error) =&gt; {
            console.error('Agent error:', error);
        },
    });

    return (
        &lt;div&gt;
            &lt;div className="agent-info"&gt;
                &lt;h4 className="stats-title"&gt;What's My Agent Doing?&lt;/h4&gt;

                &lt;div className="stats-box"&gt;
                    &lt;strong className="stats-sub-title"&gt;Tools Called:&lt;/strong&gt;
                    &lt;ul className="tool-list"&gt;
                        {toolsCalled.map((tool, idx) =&gt; (
                            &lt;li key={idx}&gt;{tool}&lt;/li&gt;
                        ))}
                        {toolsCalled.length === 0 &amp;&amp; &lt;li&gt;No tools called yet.&lt;/li&gt;}
                    &lt;/ul&gt;

                    &lt;div className="usage-stats"&gt;
                        &lt;p&gt;Prompt Token Usage: {promptTokenUsage}&lt;/p&gt;
                        &lt;p&gt;Completion Token Usage: {completionTokenUsage}&lt;/p&gt;
                        &lt;p&gt;Total Token Usage: {totalTokenUsage}&lt;/p&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;

            &lt;strong&gt;Conversation:&lt;/strong&gt;
            &lt;div className="convo-box"&gt;
                {messages.map((msg) =&gt; (
                    &lt;div key={msg.id} className="message-item"&gt;
                        &lt;strong className="message-role"&gt;{msg.role === 'assistant' ? 'Basketbot' : 'You'}:&lt;/strong&gt;
                        &lt;ReactMarkdown&gt;{msg.content}&lt;/ReactMarkdown&gt;
                    &lt;/div&gt;
                ))}
            &lt;/div&gt;

            &lt;form onSubmit={handleSubmit}&gt;
                &lt;input
                    type="text"
                    value={input}
                    onChange={handleInputChange}
                    placeholder="Input two players you want to compare."
                    className="input-box"
                /&gt;
                &lt;button type="submit" disabled={status === 'streaming'}&gt;
                    {status === 'streaming' ? 'Thinking...' : 'Send'}
                &lt;/button&gt;
            &lt;/form&gt;
        &lt;/div&gt;
    );
}<h4><strong>Schritt 9: Ausführen der Anwendung</strong></h4><p>Glückwunsch! Sie können die Anwendung nun ausführen. Folgen Sie diesen Schritten, um sowohl das Backend als auch das Frontend zu starten.</p><ol><li><p>Öffnen Sie ein Terminalfenster, beginnend im Stammverzeichnis, und navigieren Sie zum Backend-Verzeichnis. Starten Sie dort den Mastra-Server:</p></li></ol>cd backend

npm run dev<p>2. Öffnen Sie ein weiteres Terminalfenster, beginnend mit dem Stammverzeichnis, und navigieren Sie zum Frontend-Verzeichnis. Starten Sie dort die React-App:</p><p></p>cd frontend

npm run dev<p></p><p>3. Öffnen Sie Ihren Browser und navigieren Sie zu:</p><p></p><p><a href="http://localhost:5173/">http://localhost:5173</a></p><p></p><p>Sie sollten die Chat-Oberfläche sehen können. Probieren Sie diese Beispielaufforderungen aus:</p><ul><li><p>„Vergleiche LeBron James und Stephen Curry“</p></li><li><p>"Wen soll ich wählen, Jayson Tatum oder Luka Doncic?"</p></li></ul><p></p><h3><strong>Was kommt als Nächstes: Den Agenten intelligenter machen.</strong></h3><p>Um den Assistenten handlungsfähiger und die Empfehlungen aussagekräftiger zu gestalten, werde ich in der nächsten Version einige wichtige Verbesserungen vornehmen.</p><p></p><p><strong>Semantische Suche nach NBA-Nachrichten</strong></p><p>Es gibt unzählige Faktoren, die die Leistung eines Spielers beeinflussen können, viele davon spiegeln sich nicht in den reinen Statistiken wider. Dinge wie Verletzungsberichte, Aufstellungsänderungen oder auch eine Spielanalyse nach dem Spiel findet man nur in Nachrichtenartikeln. Um diesen zusätzlichen Kontext zu erfassen, werde ich semantische Suchfunktionen hinzufügen, damit der Agent relevante NBA-Artikel abrufen und diese Erzählung in seine Empfehlungen einbeziehen kann.</p><p></p><p><strong>Dynamische Suche mit dem Elasticsearch MCP-Server</strong></p><p>MCP (Model Context Protocol) entwickelt sich schnell zum Standard für die Art und Weise, wie Agenten Verbindungen zu Datenquellen herstellen. Ich werde die Suchlogik auf den Elasticsearch MCP-Server migrieren, wodurch der Agent Abfragen dynamisch erstellen kann, anstatt sich auf vordefinierte Suchfunktionen zu verlassen, die wir bereitstellen. Dies ermöglicht uns die Nutzung von Workflows in natürlicher Sprache und reduziert den Aufwand, jede einzelne Suchanfrage manuell zu formulieren. Erfahren Sie <a href="https://www.elastic.co/search-labs/blog/mcp-current-state">hier</a> mehr über den Elasticsearch MCP-Server und den aktuellen Stand des Ökosystems.</p><p></p><p>Diese Änderungen sind bereits im Gange, bleiben Sie gespannt!</p><h3><strong>Fazit</strong></h3><p></p><p>In diesem Blog haben wir einen agentenbasierten RAG-Assistenten entwickelt, der mithilfe von JavaScript, Mastra und Elasticsearch maßgeschneiderte Empfehlungen für Ihr Fantasy-Basketballteam liefert. Wir behandelten Folgendes:</p><ul><li><p><strong>Grundlagen von Agentic RAG</strong> und wie die Kombination der Autonomie eines KI-Agenten mit den Werkzeugen zur effektiven Nutzung von RAG zu differenzierteren und dynamischeren Agenten führen kann.</p></li><li><p><strong>Elasticsearch </strong>und wie seine Datenspeicherfunktionen und leistungsstarken nativen Aggregationen es zu einem großartigen Partner als Wissensbasis für ein LLM machen.</p></li><li><p><strong>Das Mastra- </strong>Framework und wie es die Entwicklung dieser Agenten für Entwickler im JavaScript-Ökosystem vereinfacht.</p></li></ul><p>Egal, ob Sie ein Basketballfanatiker sind, sich damit beschäftigen, wie man KI-Agenten entwickelt, oder beides wie ich, ich hoffe, dieser Blog hat Ihnen einige Bausteine für den Einstieg geliefert. Das vollständige Repository ist auf <a href="https://github.com/jdarmada/nba-ai-assistant-js">GitHub</a> verfügbar, Sie können es gerne klonen und damit experimentieren. Jetzt hol dir den Sieg in der Fantasy-Liga!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/agentic-rag</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/agentic-rag</guid>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[Agentische KI]]></category>
    <category><![CDATA[Javascript]]></category>
    <dc:creator><![CDATA[JD Armada]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8ffd561836a4cb20/6a17f1e47b54f978588b39e4/8132ed781c1ea5d46ca244182f421ed5c721f23b-1200x628.png" length="0" type="image/png"/>
    <pubDate>Tue, 01 Jul 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Verwenden von Azure LLM-Funktionen mit Elasticsearch für intelligentere Abfrageerlebnisse]]></title>
    <description><![CDATA[Entdecken Sie eine Beispiel-Immobilien-Such-App, die Azure Gen AI LLM Functions mit Elasticsearch nutzt, um flexible hybride Suchergebnisse zu liefern. Eine Schritt-für-Schritt-Anleitung zur Konfiguration und Ausführung der Beispiel-App in GitHub Codespaces finden Sie hier.]]></description>
    <content:encoded><![CDATA[<p>Präzision. Wenn es darauf ankommt, ist es sehr wichtig. Wenn Sie nach etwas Bestimmtem suchen, ist Präzision äußerst wichtig. Manchmal liefert eine zu präzise Abfrage jedoch keine Ergebnisse. Daher ist es von Vorteil, den Umfang einer Abfrage flexibel erweitern zu können, um zusätzliche potenziell relevante Daten zu finden.</p><p>In diesem Blogbeitrag wird die Verwendung von Elasticsearch und Azure Open AI zum Erstellen einer Beispiel-App beschrieben, die zeigt, wie bei der Suche nach sehr spezifischen Immobilienobjekten genaue Ergebnisse erzielt werden und gleichzeitig relevante Ergebnisse bereitgestellt werden, wenn keine spezifische Übereinstimmung verfügbar ist. Wir gehen alle erforderlichen Schritte durch, um einen Elasticsearch-Index zusammen mit einer Suchvorlage zu erstellen. Anschließend erläutern wir den gesamten Prozess der Erstellung einer App, die Azure OpenAI verwendet, um Benutzerabfragen entgegenzunehmen und in Elasticsearch-Suchvorlagenabfragen umzuwandeln, die erstaunlich benutzerdefinierte Ergebnisse liefern können.</p><p>Hier ist eine Liste aller Ressourcen, die wir zum Erstellen unserer Beispiel-App zur Immobiliensuche verwenden werden:</p><ul><li><p>Elasticsearch-Index und Suchvorlage</p></li><li><p>Azure OpenAI</p></li><li><p>Azure Maps-API</p></li><li><p><a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo/blob/main/VectorDBSetup.ipynb">Codespaces Jupyter Notebook</a></p></li><li><p>Semantischer Kernel</p></li><li><p>C#-App mit Blazor-Frontend</p></li></ul><h2>Intelligenter Abfrage-Workflow</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0461b58012efd772/6a17f73fa292997d52d02e19/0c4a7c835e06c514f158c00ab1055a7ba719a35f-1600x765.png" alt="Intelligenter Abfrage-Workflow" /><p>Dieser Workflow kombiniert LLM, LLM-Tools und Suche, um Abfragen in natürlicher Sprache in strukturierte, relevante Suchergebnisse umzuwandeln:</p><ul><li><p><strong>LLM (Large Language Model)</strong> – Interpretiert komplexe Benutzerabfragen und orchestriert Tools, um die Suchabsicht zu extrahieren und den Kontext anzureichern.</p></li><li><p><strong>LLM-Tools</strong> – Jedes LLM-Tool ist ein C#-Programm, das wir für diesen Beitrag erstellt haben. Es gibt drei Werkzeuge:</p><ul><li><p><em>Tool zur Parameterextraktion</em>: zieht wichtige Attribute wie Schlafzimmer, Badezimmer, Ausstattung und Preis aus der Abfrage.</p></li><li><p><em>GeoCode-Tool</em>: Konvertiert Ortsnamen in Breiten-/Längengrade zur räumlichen Filterung.</p></li><li><p><em>Suchtool</em>: füllt eine Elasticsearch-Suchvorlage mit Abfrageparametern und führt eine Suche aus. <strong>Hybridsuche</strong> – Führt eine Hybridsuche (Volltext + dichter Vektor) mit integrierter ML-Inferenz aus. Dieser mehrschichtige Ansatz gewährleistet intelligentere, kontextbezogene Abfrageerlebnisse für den Endbenutzer.</p></li></ul></li></ul><h2>Anwendungsarchitektur</h2><p>Hier ist ein Systemarchitekturdiagramm der Beispiel-App. Wir werden ein Codespaces Jupyter Notebook verwenden, um mit Elastic Cloud zu interagieren.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7617ae80295a3e2b/6a17f74196142a35deeb1cb0/2880afee184cd9270c0eb4310e51418e2339784d-936x452.png" alt="Systemarchitekturdiagramm einer Azure LLM Functions-App." /><h2>Voraussetzungen</h2><p>Sie benötigen nur Ihren Browser, da wir GitHub Codespaces verwenden, um die Beispiel-App zu klonen, zu konfigurieren und auszuführen. Für den Elastic-Teil der Lösung verwenden wir Elastic Cloud , um ein Elasticsearch Serverless-Projekt zu erstellen. Wir verwenden <a href="https://portal.azure.com/">das Azure-Portal</a> für die Arbeit mit Azure-Ressourcen.</p><h2>Klonen Sie das Beispiel-App-Repository in Codespaces</h2><p>Beginnen Sie mit dem Klonen des Codes für die Beispielanwendung. Sie können dies in <a href="https://github.com/codespaces/">GitHub Codespaces</a> tun, das eine Möglichkeit zum Klonen und Ausführen von Anwendungen bietet. Klicken Sie auf <strong>„Neuer Codespace“.</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd4ed9c67e2d79c41/6a17f7436df73146a20a10bc/b89cbec491659b6c8a0bb9551ed2629f7a37f9fd-1600x427.png" alt="Klonen eines Beispiel-App-Repositorys in Codespaces." /><p>Wählen Sie dann das Repository <a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo">jwilliams-elastic/msbuild-intelligent-query-demo</a> im Dropdown-Menü <strong>„Repository“</strong> aus und klicken Sie auf <strong>„Codespace erstellen“</strong>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdfcc992a6cb7a7d7/6a17f7450b0bed67c1dd3750/43ea377554527af9578400f16cd2342bf8fff3a2-1600x1049.png" alt="Repository-Dropdown-Menü öffnen und auf „Codespace erstellen“ klicken." /><h2>Erstellen Sie .env Datei</h2><p>Wir verwenden ein Python Jupyter Notebook, um auf Elastic Cloud zuzugreifen und mit ihr zu interagieren. Dabei werden die Konfigurationseinstellungen verwendet, die in einer Konfigurationsdatei gespeichert sind. Die Konfigurationsdatei für das Notebook sollte den Dateinamen <em><strong>.env</strong></em> haben und Sie werden es jetzt erstellen.</p><ol><li><p>Klicken Sie in GitHub Codespaces auf die Schaltfläche <strong>„Neue Datei“</strong>und fügen Sie eine Datei mit dem Namen <em><strong>.env</strong></em>hinzu.</p></li><li><p>Fügen Sie der neu erstellten <em><strong>.env</strong></em> -Datei den folgenden Inhalt hinzu Datei</p></li></ol>ELASTIC_URL=
ELASTIC_API_KEY=<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1a7dcb2fd2bb24f5/6a17f7462f4a5c21abfa8aa9/84d4f327948858ba61db0001dd8cf780d42fe0a7-1600x875.gif" alt="Ein Python Jupyter Notebook, um auf Elastic Cloud zuzugreifen und mit diesem zu interagieren. Dies geschieht mithilfe der Konfigurationswerte, die in einer Konfigurationsdatei gespeichert sind. " /><p>Wie Sie sehen, fehlen uns einige Werte, <strong>ELASTIC_URL</strong> und <strong>ELASTIC_API_KEY,</strong> die der <em>.env</em> hinzugefügt werden müssen. Datei. Lassen Sie uns diese jetzt erhalten, indem wir ein serverloses Elasticsearch-Projekt erstellen, das als Backend dient und die Suchfunktion für unsere Beispiel-App bereitstellt.</p><h2>Erstellen eines Elastic Serverless-Projekts</h2><ol><li><p>Gehen Sie zu <a href="http://cloud.elastic.co">cloud.elastic.co</a> und klicken Sie auf <strong>„Neues serverloses Projekt erstellen“</strong></p></li><li><p>Klicken Sie auf <strong>„Weiter“</strong> , um zur <strong>Elasticsearch-</strong> Lösung zu gelangen.</p></li><li><p>Wählen Sie <strong>„Optimiert für Vektoren“</strong></p></li><li><p>Legen Sie <strong>Azure</strong> als <strong>Cloud-Anbieter fest</strong></p></li><li><p>Klicken Sie auf <strong>„Serverloses Projekt erstellen“</strong></p></li><li><p>Klicken Sie im Hauptnavigationsmenü auf <strong>Erste Schritte</strong> und scrollen Sie nach unten, um die <strong>Verbindungsdetails</strong>zu kopieren</p></li><li><p>Klicken Sie auf die Schaltfläche <strong>„Kopieren“</strong> , um den <strong>Elasticsearch-Endpunkt</strong> aus den <strong>Verbindungsdetails</strong>zu kopieren</p></li><li><p>Aktualisieren Sie <em><strong>.env</strong></em> Datei, um die <strong>ELASTIC_URL</strong> als kopierten <strong>Elasticsearch-Endpunkt</strong>festzulegen</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt95b7fefa05173822/6a17f748ec0f89f05f5a67c6/77a35e55446d396066b68cfd132d1543a07b81cc-1600x875.gif" alt="Wie man ein neues Serverless-Projekt in Elasticsearch erstellt." /><h2>Erstellen eines Elastic-API-Schlüssels</h2><ol><li><p>Öffnen Sie die Seite <strong>„Erste Schritte“ von</strong> <strong>Elasticsearch und klicken Sie im</strong> Abschnitt „API-Schlüssel hinzufügen“ auf <strong>„Neu“ .</strong></p></li><li><p>Geben Sie einen <strong>Schlüsselnamen</strong>ein</p></li><li><p>Klicken Sie auf<strong> API-Schlüssel erstellen</strong></p></li><li><p>Klicken Sie auf die Schaltfläche „Kopieren“, um den API-Schlüsselwert zu kopieren</p></li><li><p>Zurück in <strong>Codespaces,</strong> wo wir die <em><strong>.env</strong></em>habenÖffnen Sie die Datei zum Bearbeiten und fügen Sie den kopierten Wert ein, um den<strong> ELASTIC_API_KEY</strong>festzulegen.</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf6b1c85d267e6ad0/6a17f74a4b055d118143239a/20168cba493d8e2c0d9ae7704eb0ae707df58e4c-1600x875.gif" alt="So erstellen Sie einen Elastic API-Schlüssel." /><h2>Öffnen Sie das Codespaces-Notebook und installieren Sie die Bibliotheksabhängigkeiten</h2><p>Wählen Sie im Datei-Explorer die Datei <em><strong>VectorDBSetup.ipynb</strong></em> aus, um das Notebook zu öffnen. Suchen Sie nach dem Laden des Notebooks den Notebook <a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo/blob/main/VectorDBSetup.ipynb?short_path=17c25d8#L40-L52">-Abschnitt mit dem Titel </a><a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo/blob/main/VectorDBSetup.ipynb?short_path=17c25d8#L40-L52"><strong>„Bibliotheken installieren“</strong></a><strong>. </strong>Klicken Sie auf die Schaltfläche „Abspielen“ des Abschnitts.</p><p>Wenn Sie zum ersten Mal ein Notebook in GitHub Codespaces ausführen, werden Sie aufgefordert, einen Codespaces-Kernel auszuwählen und die Python-Umgebung zu konfigurieren.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt970f4fa30c6c9302/6a17f74c505ac30ee6ad8ceb/2272f70615dfb9dcbeb91f39b6dd5076213e24a5-1600x875.gif" alt="Installation von Bibliotheksabhängigkeiten im Codespaces Notebook." /><h2>Definieren Sie Importe und laden Sie Umgebungsvariablen mit Codespaces Notebook</h2><p>Gehen Sie zum nächsten Abschnitt im Notebook <a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo/blob/main/VectorDBSetup.ipynb?short_path=17c25d8#L58-L104">mit dem Titel </a><a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo/blob/main/VectorDBSetup.ipynb?short_path=17c25d8#L58-L104"><strong>„Importe definieren und Umgebungsvariablen laden“</strong></a>. Klicken Sie auf die Schaltfläche „Abspielen“ des Abschnitts.</p><p>Dieser Code importiert die vom Notebook verwendeten Python-Bibliotheken und lädt die Umgebungsvariablen aus der <em>.env </em>die Sie zuvor erstellt haben.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6d74b41258420d5a/6a17f74e6317301f2f585c16/aa9f9198ff452ac0c4ce33b00f253731dbee22c5-1600x875.gif" alt="Definieren von Importen und Laden von Umgebungsvariablen mit Codespaces Notebook." /><h2>Erstellen Sie einen Elastic ML-Inferenzendpunkt mit dem Codespaces-Notebook</h2><p>Gehen Sie zum nächsten Notebook <a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo/blob/main/VectorDBSetup.ipynb?short_path=17c25d8#L112-L157">-Abschnitt mit dem Titel </a><a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo/blob/main/VectorDBSetup.ipynb?short_path=17c25d8#L112-L157"><strong>„ML-Inferenz-Endpunkt erstellen“</strong></a>. Klicken Sie auf die Schaltfläche „Abspielen“ des Abschnitts.</p><p>Dadurch wird ein neuer ML-Inferenz-Endpunkt im Elasticsearch-Projekt erstellt, den wir zum Generieren von Text-Embeddings aus unseren Daten verwenden. Text-Embeddings sind Vektordarstellungen von Text, die in Elasticsearch gespeichert werden, um die semantische Suche zu unterstützen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt87581300d4d0b66e/6a17f750e9ea875a81a9c795/97c1afab3e64027ee5ae77f377d56ba406ae1765-1600x875.gif" alt="Erstellung eines Elastic ML-Inferenzendpunkts mit Codespaces Notebook." /><h2>Erstellen Sie einen Elasticsearch-Index mit Codespaces Notebook</h2><p>Gehen Sie zum nächsten Notebook <a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo/blob/main/VectorDBSetup.ipynb?short_path=17c25d8#L165-L224">-Abschnitt mit dem Titel </a><a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo/blob/main/VectorDBSetup.ipynb?short_path=17c25d8#L165-L224"><strong>„Elasticsearch-Index erstellen“</strong></a>. Klicken Sie auf die Schaltfläche „Abspielen“ des Abschnitts.</p><p>Dadurch wird der Elasticsearch-Index erstellt, in dem unsere Beispieldaten und alle zugehörigen Vektordaten gespeichert werden, die über den ML-Inferenz-Endpunkt generiert werden.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta2d2d5a10c84a1b7/6a17f7527f6f15775cc09cd6/23a66283ee41239e24fb8455c3cd95641982ca6b-1600x875.gif" alt="Erstellen eines Elasticsearch-Index mit Codespaces Notebook." /><h2>Erstellen Sie eine Elasticsearch-Suchvorlage mit Codespaces Notebook</h2><p>Fahren Sie mit dem nächsten Notebook <a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo/blob/main/VectorDBSetup.ipynb?short_path=17c25d8#L232-L384">-Abschnitt mit dem Titel </a><a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo/blob/main/VectorDBSetup.ipynb?short_path=17c25d8#L232-L384"><strong>„Suchvorlage“</strong></a> fort. Klicken Sie auf die Schaltfläche „Abspielen“ des Abschnitts.</p><p>Dadurch wird eine <a href="https://www.elastic.co/de/docs/solutions/search/search-templates">Suchvorlage</a> erstellt, die unsere Beispiel-App als Vorlage verwendet und mit den Wörtern gefüllt, die aus der Suchanfrage eines Benutzers analysiert wurden. Dadurch können wir konfigurieren und steuern, wie spezifisch wir beim Abfragen von Daten im Elasticsearch-Index sind.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt194d6557d096ac25/6a17f7545772628d901bcda0/4c001a3e4d1cca4cfb5c043fea92c7ccaf9cb64a-1600x875.gif" alt="Erstellen einer Elasticsearch-Suchvorlage mit Codespaces Notebook." /><h2>Daten mithilfe des Codespaces Notebooks in den Elasticsearch-Index aufnehmen</h2><p>Gehen Sie zum nächsten Abschnitt des Notebooks <a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo/blob/main/VectorDBSetup.ipynb?short_path=17c25d8#L392-L450">mit dem Titel „ </a><a href="https://github.com/jwilliams-elastic/msbuild-intelligent-query-demo/blob/main/VectorDBSetup.ipynb?short_path=17c25d8#L392-L450"><strong>Eigenschaftsdaten aufnehmen“</strong></a>. Klicken Sie auf die Schaltfläche „Abschnitt ausführen“.</p><p>Durch Ausführen dieses Codeabschnitts werden die in der Datei <em>„properties.jsonl“</em>enthaltenen Beispieldaten in großen Mengen geladen. Nach einigen Minuten sollten Sie eine Bestätigung sehen, dass der Vorgang erfolgreich abgeschlossen wurde. Sie können bestätigen, dass der Index den erwarteten Datensatz enthält, indem Sie in Elastic Cloud zum Abschnitt <strong>Indexverwaltung</strong> gehen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltaf1b5ad59c75716d/6a17f7566864a4528fb6894b/e9698c798541ccfc08143a939846597028e3c566-1600x875.gif" alt="Datenaufnahme in den Elasticsearch-Index mithilfe von Codespaces Notebook." /><h2>Erstellen Sie appsetting.json, um die C#-App zu konfigurieren</h2><p>Nachdem unser Elasticsearch-Index erstellt und mit Daten gefüllt wurde, können wir nun die Beispiel-App für die Arbeit mit Elastic und Azure Cloud konfigurieren. Die C#-Beispiel-App verwendet eine Datei namens <em>appsettings.json</em> , um ihre Zugriffsinformationen wie API-Schlüssel zu speichern und zu laden. Sie erstellen die Datei <em>appsettings.json</em> jetzt mit dem Editor in Codespaces.</p><p>1. Erstellen Sie <em>appsettings.json</em> im <strong>HomeFinderApp </strong>-Ordner</p><p>2. Fügen Sie den folgenden Code in die Datei <em>appsettings.json</em> ein</p>{
 "ElasticSettings": {
   "Url": "",
   "ApiKey": "",
   "IndexName": "properties",
   "TemplateId": "properties-search-template"
 },
 "AzureOpenAISettings": {
   "Endpoint": "",
   "ApiKey": "",
   "DeploymentName": "gpt-4o"
 },
 "AzureMapsSettings": {
   "Url": "https://atlas.microsoft.com/geocode",
   "ApiKey": ""
 },
 "Logging": {
   "LogLevel": {
 	"Default": "Information",
 	"Microsoft.AspNetCore": "Warning"
   }
 },
 "AllowedHosts": "*"
}
<p>3. Suchen Sie im Abschnitt <strong>„ElasticSettings“</strong>  <strong>nach den URL- </strong>und API -Schlüsselwerten. Legen Sie sie auf die gleichen Werte fest, die Sie in der <em>.env-Datei</em> festgelegt haben Datei in einem früheren Schritt.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt28afc316da403ec9/6a17f758faa913584d93ca28/00dad25bacdea2adcbd1e6eca7658867a49b0d8c-1600x875.gif" alt="Erstellung der Datei appsetting.json zur Konfiguration der C#-Anwendung." /><h2>Erstellen des Azure OpenAI-Diensts</h2><p>Unsere Beispiel-App verwendet Azure OpenAI, um die Abfrage des App-Benutzers zu analysieren und dann eine Anfrage an Elasticsearch zu senden, indem sie die Suchvorlage ausfüllt, um zu versuchen, flexibel mitzuteilen, wonach der Benutzer sucht.</p><ol><li><p>Öffnen Sie einen neuen Browser-Tab und gehen Sie im Azure-Portal zu <a href="https://portal.azure.com/#blade/Microsoft_Azure_ProjectOxford/CognitiveServicesHub/OpenAI">AI Foundry | Azure OpenAI</a> . Klicken Sie auf +<strong>Erstellen</strong></p></li><li><p>Wählen Sie im Erstellungsformular eine <strong>Ressourcengruppe</strong> aus.</p></li><li><p>Geben Sie einen <strong>Namen</strong>ein</p></li><li><p>Wählen Sie eine <strong>Preisstufe</strong></p></li><li><p>Klicken Sie <strong>auf Weiter</strong></p></li><li><p>Klicken Sie auf der Registerkarte <strong>„Netzwerk“</strong> auf<strong> „Weiter“</strong></p></li><li><p>Klicken Sie auf der Registerkarte <strong>Tags</strong> <strong>auf Weiter</strong></p></li><li><p>Klicken Sie auf der Registerkarte <strong>„Überprüfen und senden“</strong> <strong>auf „Erstellen“</strong> .</p></li><li><p>Sobald die Erstellung abgeschlossen ist, klicken Sie auf <strong>„Zur Ressource gehen“.</strong></p></li><li><p>Wählen Sie im linken Navigationsmenü <strong>„Schlüssel und Endpunkt“</strong> aus.</p></li><li><p>Kopieren Sie den <strong>Endpunkt</strong> und fügen Sie ihn in die von Ihnen erstellte Datei <em>appsettings.json</em> in Ihrem Browser-Tab mit dem geöffneten Codespaces-Editor ein.</p></li><li><p>Kehren Sie dann zu Ihrem Browser-Tab zurück, der den Azure OpenAI <strong>-Schlüssel und die Endpunktseite</strong> enthält. Klicken Sie auf die Schaltfläche „Kopieren“ für <strong>Schlüssel 1</strong> und fügen Sie den kopierten Wert in die Datei <em>„appsettings.json“</em> ein, zurück in Ihrem Browser-Tab, in dem der Codespaces-Editor geöffnet ist.</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd01a5e82d9003d02/6a17f75a148009be65b48904/6d49197302d110410dca0a53b6ae90237cf2dfd6-1600x875.gif" alt="Erstellung eines Azure OpenAI-Dienstes." /><h2>Fügen Sie dem Azure Open AI-Dienst die Bereitstellung des GPT-4O-Modells hinzu</h2><p>Großartig, wir haben jetzt einen laufenden Azure OpenAI-Dienst, aber es ist noch eine Modellbereitstellung erforderlich, um uns die LLM-Funktionen bereitzustellen, die unsere Beispiel-App benötigt. Es stehen unzählige Modelle zur Auswahl. Lassen Sie uns <em>gpt-4o</em> bereitstellen, da es bereits in der von Ihnen erstellten Datei <em>appsettings.json</em> angegeben ist.</p><p></p><ol><li><p>Gehen Sie zu <a href="https://ai.azure.com/resource/playground">Azure AI Foundry</a> und klicken Sie auf <strong>„Bereitstellung erstellen“</strong></p></li><li><p>Suchen Sie nach <em>gpt-4o</em> und wählen Sie es aus den Ergebnissen aus</p></li><li><p>Klicken Sie auf <strong>„Bestätigen“</strong> , um es auszuwählen</p></li><li><p>Klicken Sie auf <strong>„Bereitstellen“</strong> , um das Modell bereitzustellen</p></li></ol><p>Nachdem Sie das <em>gpt-4o-</em> Modell erfolgreich bereitgestellt haben, können Sie im linken Navigationsmenü „ <strong>Bereitstellungen</strong> “ auswählen und bestätigen, dass die <em><strong>gpt-4o-</strong></em> Bereitstellung mit dem <strong>Status</strong> <strong>„Erfolgreich“</strong> aufgeführt ist.
</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte82341dd8a4982b0/6a17f75c4b055d9e0943239e/1b817ab67c05634e9c72777593b4d1a2c6c28191-1600x875.gif" alt="Hinzufügen einer gpt-4o-Modellbereitstellung zum Azure Open AI-Dienst." /><h2>Erstellen eines Azure Maps-Kontos</h2><p>Wir möchten, dass die Nutzer unserer Beispiel-App in bestimmten Gebieten nach Immobilien suchen können, ohne dabei zu spezifisch sein zu müssen. Wenn jemand nach einem Grundstück in der Nähe des örtlichen Bauernmarkts suchen möchte, ist Azure Maps ein Dienst, mit dem das OpenAI LLM die Breiten- und Längengradkoordinaten für den Markt abrufen kann. Die Koordinaten können dann in die auf Suchvorlagen basierenden Anfragen aufgenommen werden, die für Benutzerabfragen, die bestimmte Standorte und geografische Entfernungen berücksichtigen, an Elasticsearch gesendet werden.</p><ol><li><p><strong>Klicken</strong> Sie in <a href="https://portal.azure.com/#browse/Microsoft.Maps%2Faccounts">Azure Maps-Konten auf Erstellen</a></p></li><li><p>Auswählen einer <strong>Ressourcengruppe</strong></p></li><li><p>Geben Sie einen <strong>Namen</strong>ein</p></li><li><p>Stimmen Sie der Lizenz- und Datenschutzerklärung zu</p></li><li><p>Klicken Sie auf <strong>„Überprüfen und erstellen“</strong></p></li><li><p>Klicken Sie <strong>auf Erstellen</strong></p></li><li><p>Sobald die Kontoerstellung abgeschlossen ist, klicken Sie auf <strong>„Zur Ressource gehen“.</strong></p></li><li><p>Klicken Sie im linken Navigationsmenü auf <strong>„Authentifizierung“</strong></p></li><li><p>Kopieren Sie den <strong>Primärschlüsselwert</strong> und fügen Sie ihn als Wert des <strong>API-Schlüssels</strong> im Abschnitt <strong>„AzureMapsSettings“</strong> der Datei <em>„appsettings.json“</em> ein, zurück auf der Registerkarte Ihres Browsers mit dem Codespaces-Editor.</p></li></ol><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt42a4ab4bb7a96d24/6a17f75edbb4ff4f91fb5892/90fadd48e366682e2bad91e32988f93c6354e126-1600x875.gif" alt="Erstellen eines Azure Maps-Kontos." /><h2>Probieren Sie die Beispiel-App aus</h2><p>Jetzt kommt der spaßige Teil. Es ist Zeit, die Beispiel-App auszuführen. Wir verfügen über alle Konfigurationsdetails sowie die Elastic Cloud- und Azure Cloud-Ressourcen, die wir zum Betrieb der App benötigen.</p><p>1. Öffnen Sie ein Terminalfenster im Codespaces-Editor.</p><p>2. Verwenden Sie den folgenden Befehl, um das aktive Verzeichnis in den Beispiel-App-Ordner zu ändern.
</p>cd HomeFinderApp<p>3. Verwenden Sie den folgenden <em>Dotnet</em> -Befehl, um die App auszuführen.</p>dotnet run<p>4. Klicken Sie auf die Schaltfläche <strong>„Im Browser öffnen“,</strong>wenn sie angezeigt wird.</p><p>5. Testen Sie die Standardsuche und probieren Sie dann einige Ihrer eigenen benutzerdefinierten Suchen aus. Wenn Sie weitere Details dazu sehen möchten, was im Backend zur Generierung der Suchergebnisse ausgeführt wird, können Sie auf den Link <strong>„Anzeigen“</strong>neben <strong>„Toolaufrufe“ klicken.</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt41adf6631ba91be1/6a17f760505ac30986ad8cf1/821fe7b9446de5ed646d938cc9484a7ddad21030-1600x875.gif" alt="Ich probiere die Beispiel-App aus." /><p><strong>Bonus: </strong>Wenn Sie GPT-4o wirklich testen möchten, versuchen Sie die folgende Suche: <em>Ich suche nach einer Immobilie in der Nähe von Disney World, Florida, mit über 30 Schlafzimmern und über 20 Badezimmern, einem Pool und einer Garage und in Strandnähe für weniger als 200.000. </em>Diese Abfrage gibt nach mehreren Aufrufen des Suchtools Ergebnisse zurück.</p><h2>Elastic ist Ihre Lösung für Search AI</h2><p>Die laufende App ist ein Beispiel für die geführte Suche von Gen AI LLM unter Verwendung von Elasticsearch über Suchvorlagen als grundlegende Datenquelle. Experimentieren Sie ruhig und passen Sie die Beispiel-App an, um ein präzises und dennoch flexibles Sucherlebnis zu schaffen, das Ihren Benutzern hilft, das zu finden, wonach sie suchen.</p><p>Vielen Dank fürs Lesen. Probieren Sie <a href="https://cloud.elastic.co/registration">Elastic Cloud</a> aus.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/azure-llm-functions-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/azure-llm-functions-elasticsearch</guid>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Jonathan Simon,James Williams]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt93dd59caccfd7fc8/6a17f7614202292a7129f799/1431b90c7e00de06574c1e33c44a2e89296c824e-1200x628.png" length="0" type="image/png"/>
    <pubDate>Fri, 13 Jun 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Der aktuelle Stand von MCP (Model Context Protocol)]]></title>
    <description><![CDATA[Informieren Sie sich über MCP, Projektaktualisierungen, Funktionen, Sicherheitsherausforderungen, neue Anwendungsfälle und wie Sie mit dem Elasticsearch MCP-Server von Elastic herumbasteln können.]]></description>
    <content:encoded><![CDATA[<p>Ich habe vor Kurzem am <a href="https://mcpdevsummit.ai/">MCP Developers Summit</a> in San Francisco teilgenommen und es ist klar, dass das Model Context Protocol (MCP) schnell zu einem grundlegenden Baustein für KI-Agenten und kontextreiche KI-Anwendungen wird. Bei Elastic gehen wir diesen Weg, indem wir MCP-Server direkt aus <a href="https://www.elastic.co/de/elasticsearch/agent-builder">dem Agent Builder</a> heraus zugänglich machen und Elasticsearch so zu einem erstklassigen Kontext- und Werkzeuganbieter für jeden MCP-kompatiblen Agenten machen. In diesem Beitrag werde ich die wichtigsten Neuerungen der Veranstaltung, neue Anwendungsfälle, die Zukunftsaussichten von MCP und die Verwendung des Agent Builders zur Bereitstellung von Elasticsearch für Agenten über MCP erläutern.</p><h2>Was ist das Model Context Protocol (MCP)?</h2><p>Für diejenigen, die es nicht kennen: <a href="https://modelcontextprotocol.io/introduction">Model Context Protocol</a> ist ein offener Standard, der eine strukturierte, bidirektionale Möglichkeit bietet, KI-Modelle mit verschiedenen Datenquellen und Tools zu verbinden, sodass sie relevantere und fundiertere Antworten generieren können. Er wird allgemein als „ <a href="https://modelcontextprotocol.io/introduction">USB-C-Anschluss für KI-Anwendungen</a>“ bezeichnet.</p><p>Hier ist ein Architekturdiagramm, das seine bidirektionale Natur hervorhebt:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5ff0e141b5dfda29/6a17e7ffe8fbcee5263a1946/5eba1e59514eb58a5220bb92bb49e6328ee83cd7-674x466.png" alt="Model Context Protocol (MCP)-Architektur" /><p>Dies stellt für KI-Praktiker eine bedeutende Veränderung dar, da eine der größten Herausforderungen bei der Skalierung von KI-Anwendungen darin besteht, für jede neue Datenquelle benutzerdefinierte Integrationen erstellen zu müssen. MCP bietet eine nachhaltige, wiederverwendbare Architektur zum Verwalten und Bereitstellen von Kontext für Modelle. Es ist modellunabhängig, serverunabhängig und vollständig Open Source.</p><p>MCP ist die neueste Version einer Reihe von API-Spezifikationen, die die Integration zwischen Anwendungen standardisieren sollen. In der Vergangenheit hatten wir OpenAPI für RESTful-Dienste, GraphQL für Datenabfragen und gRPC für die Mikrodienstkommunikation. MCP teilt nicht nur die strukturierte Genauigkeit dieser älteren Spezifikationen, sondern bringt sie auch in eine generative KI-Umgebung ein, wodurch es einfacher wird, Agenten ohne benutzerdefinierte Konnektoren in verschiedene Systeme einzubinden. In vielerlei Hinsicht zielt MCP darauf ab, für KI-Agenten das zu tun, was HTTP für das Web getan hat. So wie HTTP die Kommunikation zwischen Browsern und Websites standardisiert, versucht MCP, die Art und Weise zu standardisieren, wie KI-Agenten mit der sie umgebenden Datenwelt interagieren.</p><h2>MCP im Vergleich zu anderen Agentenprotokollen</h2><p>Die Landschaft der Agentenprotokolle wächst rasant, und über ein Dutzend neuer Standards konkurrieren darum, die Interaktion der Agenten zu definieren. <a href="https://x.com/seldo">Laurie Voss</a> von LlamaIndex beschreibt, dass die meisten in zwei Typen eingeteilt werden können: Inter-Agent-Protokolle, bei denen der Schwerpunkt auf der Kommunikation der Agenten untereinander liegt, und kontextorientierte Protokolle wie MCP, bei denen der Schwerpunkt auf der Bereitstellung eines strukturierten Kontexts für LLMs liegt.</p><p>Andere beliebte Protokolle wie <a href="https://developers.googleblog.com/en/a2a-a-new-era-of-agent-interoperability/">A2A</a> (Agent to Agent) von Google, <a href="https://agentcommunicationprotocol.dev/introduction/welcome">ACP</a> (Agent Communication Protocol) von Cisco und IBM sowie <a href="https://agoraprotocol.org/">Agora</a> zielen darauf ab, Verhandlungen zwischen Agenten, den Aufbau von Koalitionen und sogar dezentrale Identitätssysteme zu ermöglichen. MCP verfolgt dabei einen etwas pragmatischeren Ansatz, da es sich darauf konzentriert, wie Agenten auf Tools und Daten zugreifen und nicht unbedingt darauf, wie sie miteinander kommunizieren (obwohl MCP dies in Zukunft auch auf andere Weise ermöglichen könnte).</p><p>Was MCP derzeit auszeichnet, ist seine Zugkraft und Dynamik. Wie React in den Anfängen der Frontend-Frameworks begann MCP mit einem Nischenproblem und ist heute in der Praxis eines der am häufigsten verwendeten und erweiterbarsten Agentenprotokolle.</p><h2>Gipfel-Rückblick: Neue Prioritäten für MCP</h2><p>Auf dem Gipfel sprachen Redner von Mitwirkenden bei Anthropic, Okta, OpenAI, AWS, GitHub und vielen anderen. Die Gespräche reichten von Verbesserungen des Kernprotokolls bis hin zu Implementierungen in der realen Welt und skizzierten sowohl unmittelbare als auch langfristige Prioritäten. Diese Gespräche spiegelten eine Abkehr von frühen Experimenten und einfachen Tool-Aufrufen hin zum Aufbau vertrauenswürdiger, skalierbarer und modularer KI-Systeme auf der Grundlage von MCP wider.</p><p>Mehrere Redner deuteten eine Zukunft an, in der MCP mehr als nur eine Protokoll-Infrastruktur ist und die Grundlage eines KI-nativen Webs werden kann. So wie JavaScript es Benutzern ermöglicht, auf Webseiten zu klicken und mit ihnen zu interagieren, könnte MCP es Agenten ermöglichen, dieselben Aktionen in unserem Namen auszuführen. Im E-Commerce beispielsweise könnten Benutzer, anstatt manuell zu einer Website zu navigieren, um einzukaufen, einfach einen Agenten anweisen, sich anzumelden, ein bestimmtes Produkt zu suchen, es in den Einkaufswagen zu legen und zur Kasse zu gehen.</p><p>Und das ist nicht bloß reine Spekulation und Hype; PayPal hat auf dem Gipfel sein neues Agenten-Toolkit und seinen MCP-Server vorgestellt, die genau dieses Agenten-Commerce-Erlebnis ermöglichen. Da MCP einen sicheren und zuverlässigen Zugriff auf Tools und Datenquellen bietet, können Agenten das Web nicht nur lesen, sondern auch darauf reagieren. MCP ist heute bereits ein leistungsstarker Standard mit großer Dynamik und könnte sich in Zukunft zum Standard für KI-gestützte Benutzerinteraktionen im gesamten Web entwickeln.</p><h2>MCP-Projekt-Updates: Transport, Erhebung und strukturierte Werkzeuge</h2><p><a href="https://x.com/JeromeSwannack">Jerome Swannack</a>, ein Hauptbeitragender zu MCP, hat einige Aktualisierungen der Protokollspezifikation der letzten 6 Monate mitgeteilt. Die Hauptziele dieser Änderungen sind:</p><ol><li><p>So aktivieren Sie Remote-MCP durch Hinzufügen von Streamable HTTP</p></li><li><p>Um umfangreichere Agenteninteraktionsmodelle durch die Ergänzung von Elicitation- und Tool-Output-Schemata zu ermöglichen</p></li></ol><p>Da MCP Open Source ist, stehen Änderungen wie Streamable HTTP den Entwicklern bereits zur Implementierung zur Verfügung. Die Schemata zur Ermittlung und Tool-Ausgabe sind derzeit noch nicht veröffentlicht. Sie befinden sich im Entwurfsstadium und können sich weiterentwickeln.</p><p><strong>Streamable HTTP </strong>(<a href="https://modelcontextprotocol.io/specification/2025-03-26/basic/transports">veröffentlicht am 26.03.2025</a>)<strong>:</strong> Ein wirkungsvolles technisches Update war die Einführung von Streamable HTTP als neuer Transportmechanismus. Dadurch werden serverseitig gesendete Ereignisse (SSE) durch ein skalierbareres, bidirektionales Modell ersetzt, das Chunked-Transfer-Encoding und progressive Nachrichtenübermittlung über eine einzelne HTTP-Verbindung unterstützt. Dadurch können Sie MCP-Server auf Cloud-Infrastrukturen wie AWS Lambda bereitstellen und Unternehmensnetzwerkbeschränkungen ohne langlebige Verbindungen oder die Notwendigkeit von Polling unterstützen.</p><p><strong>Elicitation </strong>(<a href="https://modelcontextprotocol.io/specification/2025-06-18/client/elicitation">veröffentlicht am 18.06.2025</a>)<strong>:</strong> Elicitation ermöglicht es Servern, ein Schema für die gewünschte Kontextstruktur eines Clients zu definieren. Im Wesentlichen kann der Server beschreiben, was er benötigt und welche Art von Eingabe er erwartet. Dies hat einige Auswirkungen: Server-Builder können komplexere Agenteninteraktionen erstellen. Client-Builder können dynamische Benutzeroberflächen implementieren, die sich an diese Schemata anpassen. Die Erhebung von Daten sollte jedoch nicht dazu verwendet werden, vertrauliche oder persönlich identifizierbare Informationen von Benutzern zu erhalten. Entwickler sollten <a href="https://modelcontextprotocol.io/specification/draft/client/elicitation#security-considerations">bewährte Methoden</a> befolgen, um sicherzustellen, dass die Abfrageaufforderungen sicher und angemessen bleiben, insbesondere wenn MCP weiterentwickelt wird. Dies hängt mit allgemeineren Sicherheitsbedenken zusammen, die wir später in diesem Beitrag erörtern werden.</p><p><strong>Tool-Ausgabeschemata </strong>(<a href="https://modelcontextprotocol.io/specification/draft/server/tools#output-schema">veröffentlicht am 18.06.2025</a>)<strong>: </strong>Dieses Konzept ermöglicht es dem Client und dem LLM, die Formen der Tool-Ausgabe im Voraus zu kennen. Mithilfe von Tool-Ausgabeschemata können Entwickler beschreiben, was ein Tool voraussichtlich zurückgeben wird. Diese Schemata beheben eine der Haupteinschränkungen des direkten Toolaufrufs, nämlich die ineffiziente Verwendung des Kontextfensters. Das Kontextfenster gilt als eine der wichtigsten Ressourcen bei der Arbeit mit LLMs. Wenn Sie ein Tool direkt aufrufen, gibt es Rohinhalte zurück, die vollständig in den Kontext des LLMs verschoben werden. Mithilfe von Tool-Ausgabeschemata können Sie Ihre Token und das Kontextfenster besser nutzen, indem Sie dem MCP-Server die Bereitstellung strukturierter Daten ermöglichen. Hier sind einige <a href="https://modelcontextprotocol.io/specification/draft/server/tools#security-considerations">Best Practices</a> zu Tools im Allgemeinen.</p><p>Zusammen werden diese neuen Updates und zukünftigen Ergänzungen dazu beitragen, dass MCP zu einem modulareren, typisierteren und produktionsbereiteren Agentenprotokoll wird.</p><h2>Untergenutzte Power-Funktionen: Sampling und Wurzeln</h2><p>Obwohl die MCP-Spezifikation nichts Neues ist, wurden in der Keynote sowohl Sampling als auch Roots hervorgehoben. Diese beiden Grundelemente werden derzeit übersehen und sind noch nicht ausreichend erforscht, können jedoch erheblich zu umfassenderen und sichereren Interaktionen zwischen Agenten beitragen.</p><p><strong>Sampling – Server können Vervollständigungen vom Client anfordern: </strong><a href="https://modelcontextprotocol.io/docs/concepts/sampling">Durch Sampling</a> können MCP-Server Vervollständigungen vom clientseitigen LLM anfordern. Dies trägt zur bidirektionalen Natur des Protokolls bei, bei dem der Server nicht nur auf Anfragen antwortet, sondern das Modell des Clients auffordern und bitten kann, eine Antwort zu generieren. Dadurch behält der Kunde die volle Kontrolle über die Kosten, die Sicherheit und das vom MCP-Server verwendete Modell. Wenn Sie also einen externen MCP-Server mit einem vorkonfigurierten Modell verwenden, müssen Sie weder Ihre eigenen API-Schlüssel angeben noch Ihr eigenes Abonnement für dieses Modell konfigurieren, da der Server einfach das bereits mit dem Client verbundene Modell aufrufen kann. Dies ermöglicht komplexere und interaktivere Agentenverhalten.</p><p><strong>Roots – eingeschränkter Zugriff auf Ressourcen: </strong><a href="https://modelcontextprotocol.io/docs/concepts/roots">Roots</a> wurden entwickelt, um Clients die Möglichkeit zu bieten, Server über relevante Ressourcen und Arbeitsbereiche zu informieren, auf die sie sich konzentrieren sollen. Dies ist leistungsstark, um den Umfang festzulegen, in dem Server arbeiten. Es ist wichtig zu beachten, dass Roots „ <a href="https://modelcontextprotocol.io/docs/concepts/roots#how-roots-work">informativ und nicht strikt erzwingend</a>“ sind, d. h., sie definieren keine Berechtigungen oder Berechtigungen für MCP-Server oder -Agenten. Mit anderen Worten: Sie können sich nicht allein auf Roots verlassen, um einen Server oder Agenten daran zu hindern, bestimmte Tools auszuführen oder Schreibaktionen durchzuführen. Bei Roots sollten Berechtigungen weiterhin clientseitig mit Mechanismen für Benutzergenehmigungen gehandhabt werden. Darüber hinaus sollten Entwickler weiterhin darauf achten, Server zu verwenden, die so konzipiert sind, dass sie die von den Roots gesetzten Grenzen respektieren und <a href="https://modelcontextprotocol.io/docs/concepts/roots#best-practices">bewährte Methoden</a> verwenden.</p><h2>Authentifizierung für Agenten: OAuth 2.1 und geschützte Metadaten</h2><p>Dieser Abschnitt konzentriert sich auf OAuth 2.1, die neueste Version von OAuth 2.0, die unsichere Abläufe beseitigt und bewährte Methoden konsolidiert.</p><p>Die OAuth-Unterstützung war ein mit Spannung erwartetes Thema, insbesondere da Sicherheit und Skalierbarkeit als die größten Hindernisse gelten, die verhindern, dass MCP zum Standard für die Verbindung von Agenten mit Tools wird. <a href="https://x.com/aaronpk">Aaron Parecki</a> (OAuth 2.1-Redakteur und Experte für Identitätsstandards bei Okta) erläuterte, wie MCP einen sauberen, skalierbaren OAuth-Flow übernehmen kann, der den Serverentwicklern den Großteil der Komplexität abnimmt. Die offizielle Autorisierungsspezifikation OAuth 2.1 wurde kürzlich am <a href="https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization">18.06.2025</a> in der neuesten Protokollrevision veröffentlicht.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4d53e7bb091b4f43/6a17e80163baff80dc741c56/2ea159116fe5e03ff800f077adf16d6ca9f1c1d1-1594x1280.png" alt="MCP-Authentifizierung für Agenten" /><p>In dieser Implementierung können die OAuth-Verantwortlichkeiten zwischen dem MCP-Client und dem Server aufgeteilt werden. Der Großteil des Authentifizierungsflusses wird vom MCP-Client initiiert und verarbeitet. Der Server ist nur am Ende beteiligt, um das sichere Token zu empfangen und zu überprüfen. Diese Aufteilung hilft bei der Lösung eines kritischen Skalierungsproblems bei der Authentifizierung über viele Tools hinweg, ohne dass Entwickler jede einzelne Verbindung konfigurieren müssen, und stellt sicher, dass MCP-Serverentwickler keine OAuth-Experten werden müssen.</p><p>Zwei wichtige Highlights aus dem Vortrag:</p><ol><li><p><a href="https://datatracker.ietf.org/doc/rfc9728/"><strong>Metadaten geschützter Ressourcen</strong></a>: MCP-Server können eine JSON-Datei veröffentlichen, die ihren Zweck, ihre Endpunkte und ihre Authentifizierungsmethoden beschreibt. Dadurch können Clients OAuth-Flows nur mit der Server-URL starten, was den Verbindungsprozess vereinfacht. Mehr erfahren: <a href="https://aaronparecki.com/2025/04/03/15/oauth-for-model-context-protocol">OAuth in MCP reparieren</a></p></li><li><p><a href="https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13"><strong>Unterstützung für IDPs und SSO</strong></a>: Unternehmen können Identitätsanbieter integrieren, um den Zugriff zentral zu verwalten. Dies ist sowohl für das Benutzererlebnis als auch für die Sicherheit ein Gewinn. Benutzer müssten nicht durch zehn verschiedene Zustimmungsbildschirme klicken und Sicherheitsteams könnten jede Verbindung beobachten.</p></li></ol><p>Indem die OAuth-Logik an den Client übertragen wird und auf Metadaten von Servern zurückgegriffen wird, vermeidet das MCP-Ökosystem einen großen Engpass. Dadurch wird MCP besser an die Art und Weise angepasst, wie moderne APIs in heutigen Produktionsumgebungen gesichert werden.</p><p>Zusätzliche Lektüre: <a href="https://aaronparecki.com/oauth-2-simplified/">OAuth 2 Simplified</a>.</p><h2>Sicherheitsherausforderungen in einem zusammensetzbaren Ökosystem</h2><p>Neue Entwicklungen bringen auch neue Angriffsflächen mit sich. Arjun Sambamoorthy von Cisco listet mehrere wichtige Bedrohungen in der MCP-Landschaft auf, darunter:</p><p>Bedrohung</p><p>Beschreibung</p><p>Abhilfemaßnahmen und bewährte Methoden</p><p>Sofortige Injektion &amp; Werkzeugvergiftung</p><p>Eine Möglichkeit, eine bösartige Eingabeaufforderung in den LLM-Systemkontext oder die Toolbeschreibung einzufügen, wodurch das LLM unbeabsichtigte Aktionen wie das Lesen von Dateien oder das Durchsickern von Daten ausführt.</p><p>Verwenden Sie Tools wie MCP Scan, um Überprüfungen der Tool-Metadaten durchzuführen. Überprüfen Sie Beschreibungen und Parameter, bevor Sie sie in Eingabeaufforderungen aufnehmen. Erwägen Sie abschließend die Implementierung von Benutzergenehmigungen für Hochrisikotools. Weitere Einzelheiten finden Sie im OWASP Prompt Injection-Handbuch in der zusätzlichen Leseliste unter der Tabelle.</p><p>Sampling-Angriffe</p><p>Im Kontext von MCP öffnet das Sampling dem MCP-Server die Tür für sofortige Injektionsangriffe auf das LLM.</p><p>Deaktivieren Sie die Stichprobenentnahme für nicht vertrauenswürdige Server und ziehen Sie in Erwägung, menschliche Genehmigungen für Stichprobenanfragen hinzuzufügen.</p><p>Bösartige MCP-Server</p><p>Bei den aktuellen Sammlungen von MCP-Servern ist es schwierig, jeden einzelnen zu überprüfen, um die Sicherheit zu gewährleisten. Betrügerische Server können Ihre Daten unbemerkt sammeln und böswilligen Akteuren preisgeben.</p><p>Stellen Sie nur Verbindungen zu MCP-Servern aus vertrauenswürdigen Registern oder internen Listen her. Führen Sie Server von Drittanbietern in Containern mit Sandboxing aus.</p><p>Schädliche MCP-Installationstools</p><p>Befehlszeileninstallationsprogramme und -skripte sind praktisch, um MCP-Server oder -Tools schnell zu implementieren, aber Sie könnten am Ende ungeprüften, kompromittierten Code installieren.</p><p>Installieren Sie es in Sandbox-Umgebungen und validieren Sie Paketsignaturen. Führen Sie niemals automatische Updates aus nicht verifizierten Quellen durch.</p><p>Um dem noch weiter entgegenzuwirken, schlägt Arjun ein vertrauenswürdiges MCP-Register vor, das alle Überprüfungen übernimmt (ein Thema, das im Mittelpunkt stand – weitere Einzelheiten finden Sie in den ersten beiden Punkten der Leseliste unten) und außerdem die Verwendung dieser <a href="https://github.com/slowmist/MCP-Security-Checklist">Sicherheitscheckliste</a>.</p><p>Weiterführende Literatur:</p><ul><li><p><a href="https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices">Offizielle Best Practices für MCP-Sicherheit</a></p></li><li><p><a href="https://owasp.org/www-project-top-10-for-large-language-model-applications/">OWASP LLM-Bewerbung Top 10</a></p></li><li><p><a href="https://hiddenlayer.com/innovation-hub/">HiddenLayer-Bedrohungsforschung</a></p></li><li><p><a href="https://github.com/invariantlabs-ai/mcp-scan">MCP-Scan</a></p></li><li><p><a href="https://genai.owasp.org/llmrisk/llm01-prompt-injection/">OWASP Prompt Injection-Leitfaden</a></p></li></ul><h2>Was kommt als Nächstes: Register, Governance und Ökosystem</h2><p>Ein zentrales MCP-Register ist in der Entwicklung und war eines der am häufigsten diskutierten Themen auf dem Gipfel. Das aktuelle Server-Ökosystem leidet unter Fragmentierung, geringem Vertrauen und mangelnder Auffindbarkeit. Für Entwickler ist es schwierig, MCP-Server zu finden, ihre Funktion zu überprüfen und sie sicher zu installieren, insbesondere in einem dezentralen Ökosystem, in dem Metadaten unvollständig oder gefälscht sein können.</p><p>Ein zentrales Register behebt diese Schwachstellen direkt, indem es als vertrauenswürdige Quelle der Wahrheit fungiert, die Auffindbarkeit verbessert, die Integrität der Servermetadaten sicherstellt und das Risiko der Installation bösartiger Tools verringert.</p><p>Die Ziele des MCP-Registers sind:</p><ul><li><p>Bereitstellung einer einzigen zuverlässigen Quelle für Servermetadaten (was ein Server tut, wie er authentifiziert, installiert und aufgerufen wird)</p></li><li><p>Beseitigung unvollständiger Registrierungen von Drittanbietern und Fragmentierung, sodass ein Server bei der Registrierung nicht jede einzelne andere Registrierung im Internet aktualisieren muss.</p></li><li><p>Bereitstellung eines Serverregistrierungsflusses, der ein CLI-Tool und eine server.json-Datei umfasst, die die zuvor erwähnten Metadaten enthält.</p></li></ul><p>Die allgemeinere Hoffnung besteht darin, dass ein vertrauenswürdiges Register dabei hilft, das Ökosystem sicher zu skalieren und es Entwicklern ermöglicht, neue Tools selbstbewusst zu erstellen und zu teilen.</p><p>Ein weiteres wichtiges Thema für Anthropic war die Regierungsführung. Sie machten deutlich, dass MCP offen und von der Community gesteuert bleiben sollte, die Skalierung dieses Governance-Modells jedoch noch in Arbeit ist. Sie suchen derzeit in diesem Bereich nach Unterstützung und bitten jeden, der Erfahrung mit der Governance in Open-Source-Protokollen hat, sich zu melden. Dies führt zu dem anderen Thema, das ich erwähnen wollte. Während der gesamten Veranstaltung betonten die Redner, dass das Ökosystem nur durch die Beiträge der Entwickler wachsen kann. Es bedarf konzentrierter Anstrengungen, um MCP zum neuen Webstandard zu machen und es von den anderen gängigen Agentenprotokollen abzuheben.</p><h2>MCP in der Praxis: Fallstudien und Demos</h2><p>Mehrere Organisationen berichteten, wie MCP bereits in praktischen Anwendungen eingesetzt wird:</p><ul><li><p><strong>PayPal – MCP-Server für Agentic Commerce: </strong>PayPal stellte sein neues <a href="https://github.com/paypal/agent-toolkit/">Agent-Toolkit</a> und seinen MCP-Server vor, die das Einkaufserlebnis eines Benutzers grundlegend verändern können. Anstatt soziale Medien nach Artikeln zu durchsuchen, Preise zu vergleichen und zur Kasse zu gehen, können Benutzer mit einem Agenten chatten, der eine Verbindung zum PayPal-MCP-Server herstellt und alle diese Aktionen abwickelt.
</p></li><li><p><strong>EpicAI.pro – Jarvis:</strong> Die Entwicklungen in MCP bringen uns einem echten Assistenten vom Typ Jarvis immer näher. Für diejenigen, die die Iron Man-Filme nicht kennen: Jarvis ist ein KI-Assistent, der natürliche Sprache verwendet, auf multimodale Eingaben reagiert, beim Antworten keine Latenz aufweist, die Bedürfnisse des Benutzers proaktiv antizipiert, Integrationen automatisch verwaltet und zwischen Geräten und Standorten im Kontext wechseln kann. Wenn wir uns Jarvis als physischen Roboterassistenten vorstellen, verleiht MCP Jarvis „Hände“ oder die Fähigkeit, komplexe Aufgaben zu bewältigen.
</p></li><li><p><strong>Postman – </strong><a href="https://www.postman.com/explore/mcp-generator"><strong>MCP-Server-Generator</strong></a><strong>: </strong>Bietet eine Warenkorb-Erfahrung für API-Anfragen, bei der Sie verschiedene API-Anfragen auswählen, in einen Korb legen und den gesamten Korb als MCP-Server herunterladen können.
</p></li><li><p><strong>Bloomberg – </strong>Bloomberg hat einen wichtigen Engpass bei der GenAI-Entwicklung für Unternehmen gelöst. Mit fast 10.000 Ingenieuren benötigten sie eine standardisierte Möglichkeit, Tools und Agenten teamübergreifend zu integrieren. Mit MCP haben sie ihre internen Tools in modulare Remote-First-Komponenten umgewandelt, die Agenten problemlos über eine einheitliche Schnittstelle aufrufen können. Dadurch konnten ihre Ingenieure Tools für die gesamte Organisation bereitstellen, während sich die KI-Teams auf die Erstellung von Agenten statt auf benutzerdefinierte Integrationen konzentrierten. Bloomberg unterstützt jetzt skalierbare, sichere Agenten-Workflows, die die vollständige Interoperabilität mit dem MCP-Ökosystem ermöglichen. Bloomberg hat keine öffentlichen Quellen verlinkt, aber dies ist, was sie auf dem Gipfel öffentlich präsentiert haben.
</p></li><li><p><strong>Block – </strong>Block verwendet MCP, um <a href="https://github.com/block/goose?tab=readme-ov-file">Goose</a> zu betreiben, einen internen KI-Agenten, der es Mitarbeitern ermöglicht, Aufgaben in den Bereichen Technik, Vertrieb, Marketing und mehr zu automatisieren. Sie haben über 60 MCP-Server für Tools wie Git, Snowflake, Jira und Google Workspace erstellt, um die Interaktion in natürlicher Sprache mit den Systemen zu ermöglichen, die sie täglich verwenden. Die Mitarbeiter von Block verwenden Goose jetzt, um Daten abzufragen, Betrug zu erkennen, Vorfälle zu verwalten, interne Prozesse zu steuern und vieles mehr – und das alles, ohne Code schreiben zu müssen. MCP hat Block dabei geholfen, die Einführung von KI in vielen Berufsfunktionen in nur zwei Monaten zu skalieren.
</p></li><li><p><strong>AWS – </strong><a href="https://github.com/awslabs/mcp"><strong>AWS MCP-Server</strong></a><strong>: </strong>AWS hat einen unterhaltsamen MCP-Server mit Dungeons-and-Dragons-Thema vorgestellt, der das Würfeln simuliert, vergangene Würfe verfolgt und Ergebnisse über Streamable HTTP zurückgibt. Dieses einfache Beispiel verdeutlicht, wie einfach es ist, MCP-Server mit AWS-Tools und -Infrastrukturen wie Lambda und Fargate zu erstellen und bereitzustellen. Sie stellten außerdem <a href="https://aws.amazon.com/blogs/opensource/introducing-strands-agents-an-open-source-ai-agents-sdk/">Strands SDK</a> vor, ein Open-Source-Toolkit zum Erstellen multimodaler Agenten, die mit MCP-Servern interagieren.</p></li></ul><h2>MCP-Unterstützung im Elastic Agent Builder</h2><p>Sie können noch heute mit MCP experimentieren und dabei <a href="https://www.elastic.co/de/search-labs/blog/elastic-ai-agent-builder-context-engineering-introduction">den Elastic Agent Builder verwenden.</a> Dies ist die einfachste Möglichkeit, Agenten direkt auf Basis Ihrer Daten zu erstellen. Mit Agent Builder können Sie Elasticsearch-basierte Tools für MCP-kompatible Agenten bereitstellen. Es enthält bereits einige leistungsstarke integrierte Tools, darunter:</p><ul><li><p><code>platform.core.search</code> - Führt Suchvorgänge unter Verwendung der vollständigen Elasticsearch Query DSL aus.</p></li><li><p><code>platform.core.list_indices</code> - Listet alle verfügbaren Indizes in Elasticsearch auf (hilft Agenten, die vorhandenen Daten zu ermitteln)</p></li><li><p><code>platform.core.get_index_mapping</code> - Ruft Feldzuordnungen für einen bestimmten Index ab (hilft Agenten, die Struktur und die Typen Ihrer Daten zu verstehen)</p></li><li><p><code>platform.core.get_document_by_id</code> - Ruft ein bestimmtes Dokument anhand seiner ID ab (für präzisen Abruf)</p></li></ul><p>Mit diesen Tools allein können Sie Ihren Agenten mit Such- und Relevanzfunktionen auf Unternehmensebene ausstatten, was für die Entwicklung zuverlässiger KI-Agenten unerlässlich ist.</p><p>Was Agent Builder noch leistungsfähiger macht, ist die Möglichkeit, eigene, auf die Bedürfnisse Ihrer Anwendung zugeschnittene Tools zu definieren und bereitzustellen. Dies ist besonders nützlich für vordefinierte oder wiederholbare Arbeitsabläufe, bei denen der Agent eine bestimmte Art von Suche in einem bestimmten Index durchführen soll, ohne dass diese Logik jedes Mal neu ermittelt werden muss. Anstatt Tokens für Planung und Schlussfolgerung auszugeben, um zum selben Ergebnis zu gelangen, können Sie diese Absicht direkt in ein Tool einprogrammieren, wodurch Ihre Agenten schneller, zuverlässiger und kosteneffizienter werden.</p><p>Innerhalb der Agent Builder-Benutzeroberfläche finden Sie hier ein Beispiel für eine benutzerdefinierte Tool-Definition, die ES|QL verwendet:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltca9e3d0a4e7031c0/6a17e803faa913d8c393c897/c1f6405a374b707e8e6fa36b9e21db5f3c7cd127-1376x864.png" alt="Agent Builder-Benutzeroberfläche" /><p>Sobald Sie Ihre benutzerdefinierten Tools definiert haben, können Sie diese (sowie die integrierten nativen Tools) mithilfe von MCP verfügbar machen, indem Sie auf das Dropdown-Menü für <code>Manage MCP</code> klicken und die MCP-Server-URL kopieren.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf7d8b29b06c08f94/6a17e805033c8d07f06bb1b6/9f39588525ca2643475de557ea54a6bcf5c150f6-1282x616.png" alt="MCP-Tools" /><p>Sie können diesen MCP-Endpunkt nun in jeden Client importieren, der MCP verwendet, um ihn mit Agent Builder zu verbinden und ihm Zugriff auf alle verfügbaren Tools zu gewähren. Weitere Informationen finden Sie in dieser Einführung zu <a href="https://www.elastic.co/de/search-labs/blog/elastic-ai-agent-builder-context-engineering-introduction">Agent Builder</a>.</p><h2>Fazit</h2><p>Der MCP Dev Summit machte deutlich, dass MCP die Art und Weise prägt, wie diese KI-Agenten miteinander und mit der sie umgebenden Datenwelt interagieren. Unabhängig davon, ob Sie einen Agenten mit Unternehmensdaten verbinden oder vollständig autonome Agenten entwerfen, bietet MCP eine standardisierte, zusammensetzbare Möglichkeit zur Integration, die im großen Maßstab schnell nützlich wird. Von Transportprotokollen und Sicherheitsmustern bis hin zu Registern und Governance reift das MCP-Ökosystem schnell. MCP wird weiterhin offen und von der Community gesteuert sein, sodass Entwickler heute die Möglichkeit haben, seine Entwicklung mitzugestalten.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/mcp-current-state</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/mcp-current-state</guid>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[JD Armada]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2f63f23bbecd2a18/6a17e8066317302039585aa7/02b8c8672ffa129e0ed91a92d6cab612a01d27f2-1200x628.png" length="0" type="image/png"/>
    <pubDate>Thu, 12 Jun 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Spring AI und Elasticsearch als Ihre Vektordatenbank]]></title>
    <description><![CDATA[Lernen Sie, wie Sie eine produktionsreife RAG-App mit Spring AI und Elasticsearch erstellen und LLMs mit Ihren proprietären Daten mithilfe einer Vektordatenbank integrieren.
]]></description>
    <content:encoded><![CDATA[<p><strong>Spring AI</strong> ist jetzt allgemein verfügbar, die erste <a href="https://spring.io/blog/2025/05/20/spring-ai-1-0-GA-released">stabile Version 1.0</a> steht auf <a href="https://mvnrepository.com/artifact/org.springframework.ai/spring-ai-core">Maven Central</a> zum Download bereit. Lass es uns gleich nutzen, um eine vollständige KI-Anwendung zu erstellen, mit deinem bevorzugten <a href="https://www.elastic.co/what-is/large-language-models">LLM</a> und unserer bevorzugten <a href="https://www.elastic.co/elasticsearch/vector-database">Vektordatenbank</a>. Oder stürzen Sie sich direkt in das <a href="https://github.com/xeraa/rag-with-java-springai-elasticsearch">Repository</a> mit der fertigen Anwendung.</p><h2>Was ist Spring AI?</h2><p><strong>Spring AI 1.0</strong>, eine umfassende Lösung für KI-Engineering in Java, ist nach einer langen Entwicklungsphase, die von rasanten Fortschritten im Bereich der KI geprägt war, nun verfügbar. Die Version enthält zahlreiche wichtige neue Funktionen für KI-Ingenieure.</p><p>Java und Spring sind bestens positioniert, um auf diesen KI-Zug aufzuspringen. Unzählige Unternehmen setzen auf Spring Boot, um ihre Systeme zu betreiben. Dadurch ist es extrem einfach, KI in ihre bestehenden Prozesse zu integrieren. Sie können Ihre Geschäftslogik und Daten im Prinzip ohne großen Aufwand direkt mit diesen KI-Modellen verknüpfen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltee1f144eb9e74866/6a17e379dbb4ffdf4bfb5647/328d7c51e1c145e94ea1e73ee9ff91836d3b180e-1600x773.png" alt="Wie Sie Spring AI mit Elasticsearch verwenden" /><p>Spring AI bietet Unterstützung für <a href="https://docs.spring.io/spring-ai/reference/api/index.html">verschiedene KI-Modelle und -Technologien</a>, wie zum Beispiel:</p><ul><li><p><strong>Bildmodelle</strong>: Generieren von Bildern anhand von Textvorgaben.</p></li><li><p><strong>Transkriptionsmodelle</strong>: Sie nehmen Audioquellen und wandeln sie in Text um.</p></li><li><p><strong>Einbettungsmodelle: </strong>Beliebige Daten werden in <a href="https://www.elastic.co/what-is/vector-embedding">Vektoren</a> umgewandelt, die für die semantische Ähnlichkeitssuche optimiert sind.</p></li><li><p><strong>Chat-Modelle: </strong>dieseSollte bekannt sein! Sie haben zweifellos schon einmal ein kurzes Gespräch mit einem geführt.</p></li></ul><p>Chatmodelle stehen im Bereich der KI derzeit im Mittelpunkt des Interesses, und das völlig zu Recht – sie sind fantastisch! Sie können sie bitten, Ihnen bei der Korrektur eines Dokuments zu helfen oder ein Gedicht zu schreiben. (Bitten Sie sie nur noch nicht, einen Witz zu erzählen.) Sie sind großartig, aber sie haben auch einige Schwächen.</p><h2>Spring AI-Lösungen für KI-Herausforderungen</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbd2d062ded38cf83/6a17e37adbb4ff69d7fb564b/2ebd68a90ebc73847df6ef7325936d4d06b35c8c-1600x900.jpg" alt="Spring AI-Lösungen für KI-Herausforderungen" /><p>Lassen Sie uns einige dieser Probleme und ihre Lösungen in Spring AI durchgehen.</p><p></p><p>Problem</p><p>Lösung</p><p>Konsistenz</p><p>Chat-Models sind aufgeschlossen und lassen sich leicht ablenken.</p><p>Sie können ihnen eine Systemvorgabe geben, um ihre Gesamtform und Struktur zu steuern.</p><p>Erinnerung</p><p>KI-Modelle haben kein Gedächtnis, daher können sie keine Nachrichten von verschiedenen Nutzern miteinander verknüpfen.</p><p>Sie können ihnen ein Speichersystem zur Verfügung stellen, um die relevanten Teile des Gesprächs zu speichern.</p><p>Isolierung</p><p>KI-Modelle leben in isolierten kleinen Umgebungen, aber sie können wirklich Erstaunliches leisten, wenn man ihnen Zugriff auf Werkzeuge gibt – Funktionen, die sie bei Bedarf aufrufen können.</p><p>Spring AI unterstützt Tool Calling, wodurch Sie dem KI-Modell Tools in seiner Umgebung mitteilen können, die es dann aufrufen soll. Diese mehrstufige Interaktion wird vollständig transparent für Sie abgewickelt.</p><p>Private Daten</p><p>KI-Modelle sind intelligent, aber nicht allwissend! Sie wissen nicht, was sich in Ihren firmeneigenen Datenbanken befindet – und wir glauben auch nicht, dass Sie das möchten!</p><p>Sie müssen die Antworten der Nutzer durch das Einfügen von Eingabeaufforderungen beeinflussen – im Grunde genommen verwenden Sie den allmächtigen String-Verkettungsoperator, um Text in die Anfrage einzufügen, bevor das Modell die gestellte Frage analysiert. Hintergrundinformationen, wenn Sie möchten. Wie entscheidet man, was verschickt werden soll und was nicht? Verwenden Sie einen Vektorspeicher, um nur die relevanten Daten auszuwählen und diese weiterzuleiten. Dies wird als Retrieval Augmented Generation oder RAG bezeichnet.</p><p>Halluzination</p><p>KI-Chatmodelle unterhalten sich gerne! Und manchmal tun sie das so selbstsicher, dass sie sich Dinge ausdenken können.</p><p>Sie müssen eine Evaluierung durchführen – also ein Modell verwenden, um die Ausgabe eines anderen zu validieren –, um plausible Ergebnisse zu bestätigen.</p><p></p><p>Und natürlich ist keine KI-Anwendung eine Insel. Moderne KI-Systeme und -Dienste funktionieren heutzutage am besten, wenn sie mit anderen Systemen und Diensten integriert sind. <a href="https://modelcontextprotocol.io/introduction"><strong>Modellkontextprotokoll</strong></a>(MCP) ermöglicht es, Ihre KI-Anwendungen mit anderen MCP-basierten Diensten zu verbinden, unabhängig davon, in welcher Sprache sie geschrieben sind. All dies lässt sich in <strong>agentenbasierten </strong>Arbeitsabläufen zusammenfassen, die auf ein übergeordnetes Ziel hinarbeiten.</p><p>Das Beste daran? All dies gelingt Ihnen, indem Sie auf die vertrauten Idiome und Abstraktionen zurückgreifen, die jeder Spring Boot-Entwickler erwartet: Praktische Starter-Abhängigkeiten für praktisch alles sind auf <a href="https://start.spring.io"><strong>Spring Initializr</strong></a>verfügbar<strong>.</strong></p><p>Spring AI bietet komfortable Spring Boot-Autokonfigurationen, die Ihnen das von Ihnen bekannte und erwartete Konvention-vor-Konfigurations-Setup bieten. Und Spring AI unterstützt Observability mit Spring Boot's Actuator und dem Micrometer-Projekt. Es harmoniert auch hervorragend mit GraalVM und virtuellen Threads, sodass Sie superschnelle und effiziente KI-Anwendungen erstellen können, die skalierbar sind.</p><h2>Warum Elasticsearch?</h2><p>Elasticsearch ist eine Volltextsuchmaschine, das wissen Sie wahrscheinlich schon. Warum verwenden wir es also für dieses Projekt? Nun ja, es ist <em>auch</em> ein Vektorshop! Und zwar eine ziemlich gute, bei der die Daten direkt neben dem vollständigen Text stehen. Weitere bemerkenswerte Vorteile:</p><ul><li><p>Super einfach einzurichten</p></li><li><p>Opensource</p></li><li><p>Horizontal skalierbar</p></li><li><p>Die meisten Freitextdaten Ihrer Organisation befinden sich wahrscheinlich bereits in einem Elasticsearch-Cluster.</p></li><li><p>Vollständige Suchmaschinenfunktion</p></li><li><p>Vollständig <a href="https://docs.spring.io/spring-ai/reference/api/vectordbs/elasticsearch.html">in Spring AI integriert</a>!</p></li></ul><p>Alles in allem erfüllt Elasticsearch alle Anforderungen an einen hervorragenden Vektorspeicher. Also lasst uns ihn einrichten und mit der Entwicklung unserer Anwendung beginnen!</p><h2>Erste Schritte mit Elasticsearch</h2><p>Wir benötigen sowohl Elasticsearch als auch Kibana, die Benutzeroberfläche, mit der Sie mit den in der Datenbank gespeicherten Daten interagieren werden.</p><p>Dank der praktischen Docker-Images und der <a href="http://elastic.co">Elastic.co-Homepage</a> können Sie alles auf Ihrem lokalen Rechner ausprobieren. Gehe dorthin, scrolle nach unten, um den Befehl <code>curl</code> zu finden, führe ihn aus und leite ihn direkt in deine Shell weiter:</p> curl -fsSL https://elastic.co/start-local | sh 
  ______                     
 |  ____| |         | | (_)     
 | |__  | | __  ___| |_   ___ 
 |  __| | |/ _` / __| __| |/ __|
 | |____| | (_| \__ \ |_| | (__ 
 |______|_|\__,_|___/\__|_|\___|
-------------------------------------------------
🚀 Run Elasticsearch and Kibana for local testing
-------------------------------------------------
ℹ️  Do not use this script in a production environment
⌛️ Setting up Elasticsearch and Kibana v9.0.0...
- Generated random passwords
- Created the elastic-start-local folder containing the files:
  - .env, with settings
  - docker-compose.yml, for Docker services
  - start/stop/uninstall commands
- Running docker compose up --wait
[+] Running 25/26
 ✔ kibana_settings Pulled                                                 16.7s 
 ✔ kibana Pulled                                                          26.8s 
 ✔ elasticsearch Pulled                                                   17.4s                                                                     
[+] Running 6/6
 ✔ Network elastic-start-local_default             Created                 0.0s 
 ✔ Volume "elastic-start-local_dev-elasticsearch"  Created                 0.0s 
 ✔ Volume "elastic-start-local_dev-kibana"         Created                 0.0s 
 ✔ Container es-local-dev                          Healthy                12.9s 
 ✔ Container kibana_settings                       Exited                 11.9s 
 ✔ Container kibana-local-dev                      Healthy                21.8s 
🎉 Congrats, Elasticsearch and Kibana are installed and running in Docker!
🌐 Open your browser at http://localhost:5601
   Username: elastic
   Password: w1GB15uQ
🔌 Elasticsearch API endpoint: http://localhost:9200
🔑 API key: SERqaGlKWUJLNVJDODc1UGxjLWE6WFdxSTNvMU5SbVc5NDlKMEhpMzJmZw==
Learn more at https://github.com/elastic/start-local
➜  ~ <p>Dadurch werden einfach Docker-Images für Elasticsearch und Kibana heruntergeladen und konfiguriert, und nach wenigen Minuten sind sie auf Ihrem lokalen Rechner einsatzbereit, inklusive der Zugangsdaten.</p><p>Außerdem stehen Ihnen zwei verschiedene URLs zur Verfügung, über die Sie mit Ihrer Elasticsearch-Instanz interagieren können. Folgen Sie den Anweisungen und rufen Sie in Ihrem Browser <a href="http://localhost:5601">http://localhost:5601</a> auf.</p><p>Beachten Sie auch den Benutzernamen <code>elastic</code> und das Passwort, die in der Konsole ausgegeben werden: Sie benötigen diese zum Anmelden (in der obigen Beispielausgabe sind dies <code>elastic</code> bzw. <code>w1GB15uQ</code>).</p><p></p><h2>Die App zusammenführen</h2><p>Rufen Sie die <a href="https://start.spring.io">Spring Initializr-</a> Seite auf und generieren Sie ein neues Spring AI-Projekt mit den folgenden Abhängigkeiten:</p><ul><li><p><code>Elasticsearch Vector Store</code></p></li><li><p><code>Spring Boot Actuator</code></p></li><li><p><code>GraalVM</code></p></li><li><p><code>OpenAI</code></p></li><li><p><code>Web</code></p></li></ul><p>Achten Sie darauf, die neueste und beste Version von Java zu wählen (idealerweise Java 24 – zum Zeitpunkt der Erstellung dieses Dokuments – oder höher) und das Build-Tool Ihrer Wahl. In diesem Beispiel verwenden wir Apache Maven.</p><p>Klicken Sie auf <code>Generate</code> und entpacken Sie anschließend das Projekt und importieren Sie es in Ihre bevorzugte IDE. (Wir verwenden IntelliJ IDEA.)</p><p>Das Wichtigste zuerst: Legen wir die Verbindungsdetails für Ihre Spring Boot-Anwendung fest. Schreiben Sie in <code>application.properties,</code> Folgendes:</p>spring.elasticsearch.uris=http://localhost:9200
spring.elasticsearch.username=elastic
spring.elasticsearch.password=w1GB15uQ<p>Wir werden außerdem die Vektorspeicherfunktion von Spring AI nutzen, um alle benötigten Datenstrukturen auf der Elasticsearch-Seite zu initialisieren. Geben Sie dazu Folgendes an:</p>spring.ai.vectorstore.elasticsearch.initialize-schema=true<p>In dieser Demo verwenden wir <strong>OpenAI</strong> , genauer gesagt das <strong>Embedding Model</strong> und <strong>das Chat Model </strong>(Sie können gerne den Dienst Ihrer Wahl verwenden, solange <a href="https://docs.spring.io/spring-ai/reference/api/embeddings.html#available-implementations">Spring AI ihn unterstützt</a>).</p><p>Das Embedding-Modell wird benötigt, um Einbettungen der Daten zu erstellen, bevor wir sie in Elasticsearch speichern. Damit OpenAI funktioniert, müssen wir <code>API key</code> angeben:</p>spring.ai.openai.api-key=...<p>Sie können sie als Umgebungsvariable wie <code>SPRING_AI_OPENAI_API_KEY</code> definieren, um zu vermeiden, dass die Anmeldeinformationen in Ihrem Quellcode gespeichert werden.</p><p>Wir werden Dateien hochladen. Stellen Sie daher sicher, dass Sie anpassen, wie viele Daten in den Servlet-Container hochgeladen werden können:</p>spring.servlet.multipart.max-file-size=20MB
spring.servlet.multipart.max-request-size=20MB<p>Wir haben es fast geschafft! Bevor wir uns ans Programmieren machen, werfen wir einen Blick darauf, wie das Ganze funktionieren wird.</p><p>Auf unserem Rechner haben wir die <a href="https://images-cdn.fantasyflightgames.com/filer_public/9f/aa/9faa23a3-9f71-4c77-865f-bba4aac8a258/runewars-revised-_rulebook.pdf">folgende Datei</a> heruntergeladen (eine Liste der Regeln für ein Brettspiel), sie in <code>test.pdf</code> umbenannt und in <code>~/Downloads/test.pdf</code> abgelegt.</p><p>Die Datei wird an den Endpunkt <code>/rag/ingest</code> gesendet (ersetzen Sie den Pfad entsprechend Ihrer lokalen Konfiguration):</p>http --form POST http://localhost:8080/rag/ingest path@/Users/jlong/Downloads/test.pdf<p>Das könnte ein paar Sekunden dauern…</p><p>Im Hintergrund werden die Daten an OpenAI gesendet, das daraus Einbettungen erstellt; diese Daten werden dann in Elasticsearch geschrieben, sowohl die Vektoren als auch der Originaltext.</p><p>In diesen Daten und allen darin enthaltenen Einbettungen geschieht die Magie. Anschließend können wir Elasticsearch über die <code>VectorStore</code> -Schnittstelle abfragen.</p><p>Der vollständige Ablauf sieht folgendermaßen aus:</p><ul><li><p>Der HTTP-Client lädt Ihre ausgewählte PDF-Datei in die Spring-Anwendung hoch.</p></li><li><p>Spring AI übernimmt die Textextraktion aus unserem PDF und unterteilt jede Seite in 800 Zeichen lange Abschnitte.</p></li><li><p>OpenAI generiert die Vektordarstellung für jeden Chunk.</p></li><li><p>Sowohl der segmentierte Text als auch die Einbettung werden anschließend in Elasticsearch gespeichert.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt93f4a64b634e9cce/6a17e37cb1e113215879f216/9734adb2d7128e61c515d5855dfad6d3a326a4a1-1454x706.png" alt="Vollständiger Workflow für die Textextraktion von Spring AI aus dem PDF, die Vektorrepräsentation von Open AI und das Textchunking von Elasticsearch zur Erstellung von Einbettungen." /><p>Zum Schluss stellen wir eine Anfrage:</p>http :8080/rag/query question=="where do you place the reward card after obtaining it?" <p>Und wir erhalten eine relevante Antwort:</p>After obtaining a Reward card, you place it facedown under the Hero card of the hero who received it.
Found at page: 28 of the manual<p>Toll! Wie funktioniert das alles?</p><ul><li><p>Der HTTP-Client übermittelt die Frage an die Spring-Anwendung.</p></li><li><p>Spring AI erhält die Vektordarstellung der Frage von OpenAI.</p></li><li><p>Durch diese Einbettung sucht es in den gespeicherten Elasticsearch-Chunks nach ähnlichen Dokumenten und ruft die ähnlichsten Dokumente ab.</p></li><li><p>Spring AI sendet dann die Frage und den abgerufenen Kontext an OpenAI, um eine LLM-Antwort zu generieren.</p></li><li><p>Schließlich gibt es die generierte Antwort und einen Verweis auf den abgerufenen Kontext zurück.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfab41731851104f3/6a17e37e445de90e924d00aa/3799de6e8cb13ce49b9e136cfe593263030231a8-1464x1050.png" alt="Vollständiger Spring-IA und Open-AI Workflow zur Generierung der LLM-Antwort auf eine Frage." /><p>Lasst uns einen Blick in den Java-Code werfen, um zu sehen, wie er wirklich funktioniert.</p><p>Zunächst einmal zur <strong>Main-</strong> Klasse: Es handelt sich um eine standardmäßige Hauptklasse für jede beliebige Spring Boot-Anwendung.</p>@SpringBootApplication
public class DemoApplication {
 	public static void main(String[] args) { 
     		SpringApplication.run(DemoApplication.class, args);
 	}
}<p>Dort gibt es nichts zu sehen. Weiter geht’s…</p><p>Als nächstes ein einfacher HTTP-Controller:</p>@RestController
class RagController {

   private final RagService rag;

   RagController(RagService rag) {
       this.rag = rag;
   }

   @PostMapping("/rag/ingest")
   ResponseEntity&lt;?&gt; ingestPDF(@RequestBody MultipartFile path) {
       rag.ingest(path.getResource());
       return ResponseEntity.ok().body("Done!");
   }

   @GetMapping("/rag/query")
   ResponseEntity&lt;?&gt; query(@RequestParam String question) {
       String response = rag.directRag(question);
       return ResponseEntity.ok().body(response);
   }
}<p>Der Controller ruft lediglich einen von uns entwickelten Dienst auf, der Dateien aufnimmt und in den Elasticsearch-Vektorspeicher schreibt und anschließend Abfragen gegen denselben Vektorspeicher ermöglicht.</p><p>Schauen wir uns den Service an:</p>@Service
class RagService {

   private final ElasticsearchVectorStore vectorStore;

   private final ChatClient ai;

   RagService(ElasticsearchVectorStore vectorStore, ChatClient.Builder clientBuilder) {
       this.vectorStore = vectorStore;
       this.ai = clientBuilder.build();
   }

   void ingest(Resource path) {
       PagePdfDocumentReader pdfReader = new PagePdfDocumentReader(path);
       List&lt;Document&gt; batch = new TokenTextSplitter().apply(pdfReader.read());
       vectorStore.add(batch);
   }

  // TBD
}<p>Dieser Code übernimmt die gesamte Datenaufnahme: Ausgehend von einem Spring Framework <code>Resource</code>, das ein Container um Bytes ist, lesen wir die PDF-Daten (vermutlich eine <code>.PDF</code> -Datei - stellen Sie sicher, dass Sie dies überprüfen, bevor Sie beliebige Eingaben akzeptieren!) mit Spring AIs <code>PagePdfDocumentReader</code> und tokenisieren sie dann mit Spring AIs <code>TokenTextSplitter</code>. Schließlich fügen wir die resultierenden <code>List&lt;Document&gt;</code>-Objekte der <code>VectorStore</code> -Implementierung <code>ElasticsearchVectorStore</code> hinzu.</p><p>Sie können dies mit Kibana bestätigen: Nachdem Sie eine Datei an den Endpunkt <code>/rag/ingest</code> gesendet haben, öffnen Sie Ihren Browser unter <code>localhost:5601</code> und navigieren Sie im Seitenmenü auf der linken Seite zu <code>Dev Tools</code>. Dort können Sie Abfragen stellen, um mit den Daten in der Elasticsearch-Instanz zu interagieren.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt45805a5b2da5e336/6a17e3803e03d70a584f2bda/c85e522f02f8b2da7462cd428dc7e952c9692542-1600x1040.png" alt="Wie erstellt man eine Abfrage in der Elasticsearch-Instanz." /><p>Stellen Sie eine Anfrage wie diese:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt21d79210fe213b1e/6a17e382e3179163492d5767/00974a176cbce11e70fcab24fb4b3f9c6e205982-1600x1040.png" alt="Eine Abfrage in der Elasticsearch-Konsole ausführen." /><p>Und nun zum spannenden Teil: Wie erhalten wir diese Daten wieder als Antwort auf Benutzeranfragen?</p><p>Hier ist ein erster Entwurf für die Implementierung der Abfrage in einer Methode namens <code>directRag</code>.</p>String directRag(String question) {
   // Query the vector store for documents related to the question
   List&lt;Document&gt; vectorStoreResult =
           vectorStore.doSimilaritySearch(SearchRequest.builder().query(question).topK(5)
                   .similarityThreshold(0.7).build());

   // Merging the documents into a single string
   String documents = vectorStoreResult.stream()
           .map(Document::getText)
           .collect(Collectors.joining(System.lineSeparator()));

   // Exit if the vector search didn't find any results
   if (documents.isEmpty()) {
       return "No relevant context found. Please change your question.";
   }

   // Setting the prompt with the context
   String prompt = """
           You're assisting with providing the rules of the tabletop game Runewars.
           Use the information from the DOCUMENTS section to provide accurate answers to the
           question in the QUESTION section.
           If unsure, simply state that you don't know.
          
           DOCUMENTS:
           """ + documents
           + """
           QUESTION:
           """ + question;


   // Calling the chat model with the question
   String response = ai
           .prompt()
           .user(prompt)
           .call()
           .content();

   return response +
           System.lineSeparator() +
           "Found at page: " +
           // Retrieving the first ranked page number from the document metadata
           vectorStoreResult.getFirst().getMetadata().get(PagePdfDocumentReader.METADATA_START_PAGE_NUMBER) +
           " of the manual";

}<p>Der Code ist recht einfach, aber wir werden ihn in mehrere Schritte unterteilen:</p><ol><li><p>Verwenden Sie <code>VectorStore</code> , um eine Ähnlichkeitssuche durchzuführen.</p></li><li><p>Ausgehend von allen Ergebnissen werden die zugrunde liegenden Spring AI <code>Document</code>s ermittelt und deren Text extrahiert, der anschließend zu einem einzigen Ergebnis zusammengefügt wird.</p></li><li><p>Sende die Ergebnisse von <code>VectorStore</code> an das Modell, zusammen mit einer Aufforderung, die dem Modell erklärt, was damit zu tun ist, und der Frage des Benutzers. Warten Sie die Antwort ab und senden Sie sie zurück.</p></li></ol><p></p><p>Dies ist <strong>RAG</strong> – Retrieval Augmented Generation. Es geht um die Idee, dass wir Daten aus einem Vektorspeicher verwenden, um die vom Modell durchgeführte Verarbeitung und Analyse zu unterstützen. Jetzt, wo Sie wissen, wie es geht, hoffen wir, dass Sie es nie tun müssen! So jedenfalls nicht: <a href="https://docs.spring.io/spring-ai/reference/api/advisors.html">Die Berater</a> von Spring AI sind dazu da, diesen Prozess noch weiter zu vereinfachen.</p><p>Advisors ermöglicht die Vor- und Nachbearbeitung einer Anfrage an ein bestimmtes Modell und stellt darüber hinaus eine Abstraktionsschicht zwischen Ihrer Anwendung und dem Vektorspeicher bereit. Fügen Sie Ihrem Build die folgende Abhängigkeit hinzu:
</p>&lt;dependency&gt;
   &lt;groupId&gt;org.springframework.ai&lt;/groupId&gt;
   &lt;artifactId&gt;spring-ai-advisors-vector-store&lt;/artifactId&gt;
&lt;/dependency&gt;<p>Füge der Klasse eine weitere Methode namens <code>advisedRag(String question)</code> hinzu:</p>String advisedRag(String question) {
   return this.ai
           .prompt()
           .user(question)
           .advisors(new QuestionAnswerAdvisor(vectorStore))
           .call()
           .content();
}<p>Die gesamte RAG-Musterlogik ist in <code>QuestionAnswerAdvisor</code> gekapselt. Alles andere ist genau so, wie jede andere Anfrage an <code>ChatModel</code> wäre! Hübsch!</p><p><a href="https://github.com/xeraa/rag-with-java-springai-elasticsearch">Den vollständigen Code finden Sie auf GitHub</a>.</p><h2>Fazit</h2><p>In dieser Demo verwendeten wir Docker-Images und führten alles auf unserem lokalen Rechner durch, das Ziel hier ist jedoch die Entwicklung produktionsreifer KI-Systeme und -Dienste. Es gibt verschiedene Möglichkeiten, dies zu verwirklichen.</p><p>Zunächst können Sie <a href="https://docs.spring.io/spring-boot/reference/actuator/index.html#actuator">den Spring Boot Actuator</a> hinzufügen, um den Tokenverbrauch zu überwachen. Tokens dienen als Stellvertreter für die Komplexität (und manchmal auch die Kosten in Dollar und Cent) einer bestimmten Anfrage an das Modell.</p><p>Der Spring Boot Actuator befindet sich bereits im Klassenpfad. Geben Sie daher einfach die folgenden Eigenschaften an, um alle Metriken anzuzeigen (die vom großartigen Projekt <a href="http://micrometer.io">Micrometer.io</a> erfasst werden):</p>management.endpoints.web.exposure.include=*<p>Starten Sie Ihre Anwendung neu. Führe eine Abfrage durch und gehe dann zu: <a href="http://localhost:8080/actuator/metrics">http://localhost:8080/actuator/metrics</a>. Suchen Sie nach „ <code>token</code>“ und Sie erhalten Informationen über die von der Anwendung verwendeten Token. Behalten Sie das bitte im Auge. Sie können natürlich auch die Micrometer- <a href="https://docs.micrometer.io/micrometer/reference/implementations/elastic.html">Integration für Elasticsearch</a> nutzen, um diese Metriken zu übertragen und Elasticsearch als Ihre bevorzugte Zeitreihendatenbank zu verwenden!</p><p>Man sollte dann bedenken, dass wir jedes Mal, wenn wir eine Anfrage an einen Datenspeicher wie Elasticsearch, an OpenAI oder an andere Netzwerkdienste stellen, E/A-Operationen durchführen und dass diese E/A-Operationen häufig die Threads blockieren, auf denen sie ausgeführt werden. Java 21 und spätere Versionen werden mit nicht-blockierenden <strong>virtuellen Threads</strong> ausgeliefert, die die Skalierbarkeit deutlich verbessern. Aktivieren Sie es mit:
</p>spring.threads.virtual.enabled=true<p>Und schließlich sollten Sie Ihre Anwendung und Ihre Daten an einem Ort hosten, an dem sie optimal funktionieren und skalieren können. Sie haben sich sicher schon Gedanken darüber gemacht, wo Sie Ihre Anwendung ausführen möchten, aber wo werden Sie Ihre Daten hosten? Dürfen wir Ihnen die <a href="https://cloud.elastic.co/">Elastic Cloud</a> empfehlen? Es ist sicher, privat, skalierbar und voller Funktionen. Unser Lieblingsteil? Wenn Sie möchten, können Sie die Serverless-Edition wählen, bei der Elastic den Pager trägt, nicht Sie!</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/spring-ai-elasticsearch-application</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/spring-ai-elasticsearch-application</guid>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Josh Long,Philipp Krenn,Laura Trotta]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt26b868ef618164c6/6a17e3830b0bedd68cdd3515/0771fb5b3d9234697cb868cd7d9d1b840000bf29-1280x720.png" length="0" type="image/png"/>
    <pubDate>Tue, 20 May 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[​​Erstellung eines RAG-Workflows mit LangGraph und Elasticsearch]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie eine LangGraph Retrieval Agent Template mit Elasticsearch konfigurieren und anpassen, um einen RAG-Workflow für effizienten Datenabruf und KI-gesteuerte Antworten zu erstellen.]]></description>
    <content:encoded><![CDATA[<p>Die <a href="https://github.com/langchain-ai/retrieval-agent-template">LangGraph Retrieval Agent-Vorlage</a> ist ein von LangChain entwickeltes Starterprojekt, das die Erstellung abrufbasierter Frage-Antwort-Systeme mit LangGraph in LangGraph Studio erleichtern soll. Diese Vorlage ist für die nahtlose Integration mit Elasticsearch vorkonfiguriert und ermöglicht Entwicklern die schnelle Erstellung von Agenten, die Dokumente effizient indizieren und abrufen können.</p><p>In diesem Blog geht es um das Ausführen und Anpassen der LangChain Retrieval Agent-Vorlage mit LangGraph Studio und LangGraph CLI. Die Vorlage bietet ein Framework zum Erstellen von Retrieval-Augmented Generation (RAG)-Anwendungen und nutzt verschiedene Retrieval-Backends wie Elasticsearch.</p><p>Wir führen Sie durch die Einrichtung, Konfiguration der Umgebung und effiziente Ausführung der Vorlage mit Elastic, während wir den Agentenfluss anpassen.</p><h2>Voraussetzungen</h2><p>Bevor Sie fortfahren, stellen Sie sicher, dass Folgendes installiert ist:</p><ul><li><p>Elasticsearch Cloud-Bereitstellung oder lokale Elasticsearch-Bereitstellung (oder erstellen Sie eine 14-tägige <a href="https://www.elastic.co/de/cloud/cloud-trial-overview">kostenlose Testversion </a>auf Elastic Cloud) – Version 8.0.0 oder höher</p></li><li><p>Python 3.9+</p></li><li><p>Zugriff auf einen LLM-Anbieter wie <a href="https://cohere.com/">Cohere</a> (in diesem Handbuch verwendet), <a href="https://openai.com/">OpenAI</a> oder <a href="https://www.anthropic.com/claude">Anthropic/Claude</a></p></li></ul><h2>Erstellen der LangGraph-App</h2><h3>1. Installieren Sie die LangGraph CLI</h3>pip install --upgrade "langgraph-cli[inmem]"<h3>2. Erstellen Sie eine LangGraph-App aus der Retrieval-Agent-Vorlage</h3>mkdir lg-agent-demo
cd lg-agent-demo
langgraph new lg-agent-demo <p><em>Ihnen wird ein interaktives Menü angezeigt, in dem Sie aus einer Liste verfügbarer Vorlagen auswählen können. </em>Wählen Sie 4 für Retrieval Agent und 1 für Python, wie unten gezeigt:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd44177037ea46d45/6a17f86b3e9e45265fba1663/6a41a41f95c2477c67810adc7be46d91faf06878-1600x407.png" alt="Vorlage für interaktive Abfragen." /><ul><li><p><strong>Fehlerbehebung</strong>: Wenn der Fehler „urllib.error.URLError: &lt;urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)&gt;“ auftritt, „</p></li></ul><p>Führen Sie den Python-Befehl „Zertifikat installieren“ aus, um das Problem wie unten gezeigt zu beheben.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbbe2d1d3a1af75b1/6a17f86d445de97c9c4d02e7/83ec238136c41738457299fd42c83aff32eb5b97-1407x75.png" alt="Den Python-Befehl zum Installieren des Zertifikats ausführen." /><h3>3. Abhängigkeiten installieren</h3><p>Erstellen Sie im Stammverzeichnis Ihrer neuen LangGraph-App eine virtuelle Umgebung und installieren Sie die Abhängigkeiten im Modus <code>edit</code> , damit Ihre lokalen Änderungen vom Server verwendet werden:</p>#For Mac
python3 -m venv lg-demo
source lg-demo/bin/activate 
pip install -e .

#For Windows
python3 -m venv lg-demo
lg-demo\Scripts\activate 
pip install -e .<h2>Einrichten der Umgebung</h2><h3>1. Erstellen Sie eine .environment-Umgebung Datei</h3><p>Die Datei <code>.env</code> enthält API-Schlüssel und Konfigurationen, damit die App eine Verbindung mit dem von Ihnen gewählten LLM- und Abrufanbieter herstellen kann. Generieren Sie eine neue <code>.env</code> -Datei, indem Sie die Beispielkonfiguration duplizieren:</p>cp .env.example .env<h3>2. Konfigurieren Sie die .env-Datei. Datei</h3><p>Die Datei <code>.env</code> enthält eine Reihe von Standardkonfigurationen. Sie können es aktualisieren, indem Sie basierend auf Ihrem Setup die erforderlichen API-Schlüssel und -Werte hinzufügen. Alle Schlüssel, die für Ihren Anwendungsfall nicht relevant sind, können unverändert bleiben oder entfernt werden.</p># To separate your traces from other applications
LANGSMITH_PROJECT=retrieval-agent

# LLM choice (set the API key for your selected provider):
ANTHROPIC_API_KEY=your_anthropic_api_key
FIREWORKS_API_KEY=your_fireworks_api_key
OPENAI_API_KEY=your_openai_api_key

# Retrieval provider (configure based on your chosen service):

## Elastic Cloud:
ELASTICSEARCH_URL=https://your_elastic_cloud_url
ELASTICSEARCH_API_KEY=your_elastic_api_key

## Elastic Local:
ELASTICSEARCH_URL=http://host.docker.internal:9200
ELASTICSEARCH_USER=elastic
ELASTICSEARCH_PASSWORD=changeme

## Pinecone:
PINECONE_API_KEY=your_pinecone_api_key
PINECONE_INDEX_NAME=your_pinecone_index_name

## MongoDB Atlas:
MONGODB_URI=your_mongodb_connection_string

# Cohere API key:
COHERE_API_KEY=your_cohere_api_key<ul><li><p>Beispieldatei <code>.env</code> (unter Verwendung von Elastic Cloud und Cohere)</p></li></ul><p>Nachfolgend finden Sie eine Beispielkonfiguration <code>.env</code> für die Verwendung <strong>von Elastic Cloud</strong> als Abrufanbieter und <strong>Cohere</strong> als LLM, wie in diesem Blog gezeigt:</p># To separate your traces from other applications
LANGSMITH_PROJECT=retrieval-agent
#Retrieval Provider
# Elasticsearch configuration
ELASTICSEARCH_URL=elastic-url:443
ELASTICSEARCH_API_KEY=elastic_api_key
# Cohere API key
COHERE_API_KEY=cohere_api_key<p><em>Hinweis: In dieser Anleitung wird Cohere sowohl für die Antwortgenerierung als auch für die Einbettung verwendet. Sie können je nach Anwendungsfall jedoch auch andere LLM-Anbieter wie </em><em><strong>OpenAI,</strong></em><em><strong>Claude</strong></em><em> oder sogar ein lokales LLM-Modell verwenden. Stellen Sie sicher, dass alle </em><em><code>.env</code></em><em> Schlüssel, die Sie verwenden möchten, in der Datei vorhanden und korrekt festgelegt sind.</em></p><h3>3. Aktualisieren Sie die Konfigurationsdatei -configuration.py </h3><p>Nachdem Sie Ihre <code>.env</code> -Datei mit den entsprechenden API-Schlüsseln eingerichtet haben, besteht der nächste Schritt darin, die Standardmodellkonfiguration Ihrer Anwendung zu aktualisieren. Durch die Aktualisierung der Konfiguration wird sichergestellt, dass das System die Dienste und Modelle verwendet, die Sie in Ihrer <code>.env</code> -Datei angegeben haben.</p><p>Navigieren Sie zur Konfigurationsdatei:</p> cd src/retrieval_graph<p>Die Datei <code>configuration.py</code> enthält die Standardmodelleinstellungen, die vom Abrufagenten für drei Hauptaufgaben verwendet werden:</p><ul><li><p><strong>Einbettungsmodell</strong> – konvertiert Dokumente in Vektordarstellungen</p></li><li><p><strong>Abfragemodell</strong> – verarbeitet die Abfrage des Benutzers in einen Vektor</p></li><li><p><strong>Antwortmodell</strong> – generiert die endgültige Antwort</p></li></ul><p>Standardmäßig verwendet der Code Modelle von <strong>OpenAI</strong> (z. B. <code>openai/text-embedding-3-small</code>) und <strong>Anthropic</strong> (z. <code>anthropic/claude-3-5-sonnet-20240620 and anthropic/claude-3-haiku-20240307</code>).

In diesem Blog wechseln wir zur Verwendung von Cohere-Modellen. Wenn Sie bereits OpenAI oder Anthropic verwenden, sind keine Änderungen erforderlich.</p><h4>Beispieländerungen (mit Cohere):</h4><p>Öffnen Sie <code>configuration.py</code> und ändern Sie die Modellstandards wie unten gezeigt:</p>…
 embedding_model: Annotated[
       str,
       {"__template_metadata__": {"kind": "embeddings"}},
   ] = field(
       default="cohere/embed-english-v3.0",
…
response_model: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = field(
       default="cohere/command-r-08-2024",
…
query_model: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = field(
       default="cohere/command-r-08-2024",
       metadata={<h2>Ausführen des Abrufagenten mit der LangGraph-Befehlszeilenschnittstelle</h2><h3>1. Starten Sie den LangGraph-Server</h3>cd lg-agent-demo
langgraph dev<p>Dadurch wird der LangGraph-API-Server lokal gestartet. Wenn dies erfolgreich ausgeführt wird, sollten Sie etwa Folgendes sehen:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt46c7a703e715ef66/6a17f86eb1e113272d79f42e/e3c3344b24651067e2d0892d870feca505b3be35-1494x542.png" alt=" LangGraph API-Server läuft erfolgreich." /><p>Öffnen Sie die URL der Studio-Benutzeroberfläche.</p><p>Es stehen zwei Diagramme zur Verfügung:</p><ul><li><p><strong>Retrieval-Graph</strong>: Ruft Daten aus Elasticsearch ab und beantwortet die Anfrage mithilfe eines LLM.</p></li><li><p><strong>Indexer-Graph</strong>: Indiziert Dokumente in Elasticsearch und generiert Einbettungen mithilfe eines LLM.</p></li></ul><h3>2. Konfigurieren des Indexergraphen</h3><ul><li><p>Öffnen Sie den Indexergraphen.</p></li><li><p>Klicken Sie auf „Assistenten verwalten“.</p><ul><li><p>Klicken Sie auf <strong>„Neuen Assistenten hinzufügen</strong>“, geben Sie die Benutzerdaten wie angegeben ein und schließen Sie anschließend das Fenster.</p></li></ul></li></ul>{"user_id": "101"}<h3>3. Beispieldokumente indexieren</h3><ul><li><p>Indizieren Sie die folgenden Beispieldokumente, die einen hypothetischen Quartalsbericht für die Organisation NoveTech darstellen:</p></li></ul>[
  {    "page_content": "NoveTech Solutions Q1 2025 Report - Revenue: $120.5M, Net Profit: $18.2M, EPS: $2.15. Strong AI software launch and $50M government contract secured."
  },
  {
    "page_content": "NoveTech Solutions Business Highlights - AI-driven analytics software gained 15% market share. Expansion into Southeast Asia with two new offices. Cloud security contract secured."
  },
  {
    "page_content": "NoveTech Solutions Financial Overview - Operating expenses at $85.3M, Gross Margin 29.3%. Stock price rose from $72.5 to $78.3. Market Cap reached $5.2B."
  },
  {
    "page_content": "NoveTech Solutions Challenges - Rising supply chain costs impacting hardware production. Regulatory delays slowing European expansion. Competitive pressure in cybersecurity sector."
  },
  {
    "page_content": "NoveTech Solutions Future Outlook - Expected revenue for Q2 2025: $135M. New AI chatbot and blockchain security platform launch planned. Expansion into Latin America."
  },
  {
    "page_content": "NoveTech Solutions Market Performance - Year-over-Year growth at 12.7%. Stock price increase reflects investor confidence. Cybersecurity and AI sectors remain competitive."
  },
  {
    "page_content": "NoveTech Solutions Strategic Moves - Investing in R&amp;D to enhance AI-driven automation. Strengthening partnerships with enterprise cloud providers. Focusing on data privacy solutions."
  },
  {
    "page_content": "NoveTech Solutions CEO Statement - 'NoveTech Solutions continues to innovate in AI and cybersecurity. Our growth strategy remains strong, and we foresee steady expansion in the coming quarters.'"
  }
]<p>Sobald die Dokumente indiziert sind, wird im Thread eine Löschmeldung angezeigt, wie unten dargestellt.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt38715eadffcb62f0/6a17f877faa9135f7393ca4c/fd3a1efd64cb54d54ea56ef5055249dd066d5708-1600x854.png" alt="LangGraph- und Elasticsearch-RAG-Workflow-Dokumente wurden indiziert." /><h3>4. Ausführen des Abrufgraphen</h3><ul><li><p>Wechseln Sie zum Abrufgraphen.</p></li><li><p>Geben Sie die folgende Suchanfrage ein:</p></li></ul>What was NovaTech Solutions total revenue in Q1 2025?<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5c0d070fca52e512/6a17f879505ac36d37ad8d12/eb4d8ddfe0effd7e1868fba921b8ef13f7baf27a-1600x755.png" alt="Ausführen des LangGraph- und Elasticsearch-Abrufgraphen" /><p>Das System gibt relevante Dokumente zurück und liefert eine genaue Antwort basierend auf den indizierten Daten.</p><h2>Passen Sie den Abrufagenten an.</h2><p>Um das Benutzererlebnis zu verbessern, führen wir einen Anpassungsschritt im Abrufgraphen ein, um die nächsten drei Fragen vorherzusagen, die ein Benutzer stellen könnte. Diese Vorhersage basiert auf Folgendem:</p><ul><li><p>Kontext aus den abgerufenen Dokumenten</p></li><li><p>Vorherige Benutzerinteraktionen</p></li><li><p>Letzte Benutzerabfrage</p></li></ul><p>Zur Implementierung der Abfragevorhersagefunktion sind die folgenden Codeänderungen erforderlich:</p><h3>1. Aktualisiere graph.py</h3><ul><li><p>Funktion <code>predict_query</code> hinzufügen:</p></li></ul>async def predict_query(
   state: State, *, config: RunnableConfig
) -&gt; dict[str, list[BaseMessage]]:
   logger.info(f"predict_query predict_querypredict_query predict_query predict_query predict_query")  # Log the query

   configuration = Configuration.from_runnable_config(config)
   prompt = ChatPromptTemplate.from_messages(
       [
           ("system", configuration.predict_next_question_prompt),
           ("placeholder", "{messages}"),
       ]
   )
   model = load_chat_model(configuration.response_model)
   user_query = state.queries[-1] if state.queries else "No prior query available"
   logger.info(f"user_query: {user_query}")
   logger.info(f"statemessage: {state.messages}")
   #human_messages = [msg for msg in state.message if isinstance(msg, HumanMessage)]

   message_value = await prompt.ainvoke(
       {
           "messages": state.messages,
           "user_query": user_query,  # Use the most recent query as primary input
           "system_time": datetime.now(tz=timezone.utc).isoformat(),
       },
       config,
   )

   next_question = await model.ainvoke(message_value, config)
   return {"next_question": [next_question]}<ul><li><p>Ändern Sie die Funktion <code>respond</code> , um das Objekt <strong><code>response</code></strong> anstelle der Nachricht zurückzugeben:</p></li></ul>async def respond(
   state: State, *, config: RunnableConfig
) -&gt; dict[str, list[BaseMessage]]:
   """Call the LLM powering our "agent"."""
   configuration = Configuration.from_runnable_config(config)
   # Feel free to customize the prompt, model, and other logic!
   prompt = ChatPromptTemplate.from_messages(
       [
           ("system", configuration.response_system_prompt),
           ("placeholder", "{messages}"),
       ]
   )
   model = load_chat_model(configuration.response_model)

   retrieved_docs = format_docs(state.retrieved_docs)
   message_value = await prompt.ainvoke(
       {
           "messages": state.messages,
           "retrieved_docs": retrieved_docs,
           "system_time": datetime.now(tz=timezone.utc).isoformat(),
       },
       config,
   )
   response = await model.ainvoke(message_value, config)
   # We return a list, because this will get added to the existing list
   return {"response": [response]}<ul><li><p>Aktualisieren Sie die Graphstruktur, um einen neuen Knoten und eine neue Kante für predict_query hinzuzufügen:</p></li></ul>builder.add_node(generate_query)
builder.add_node(retrieve)
builder.add_node(respond)
builder.add_node(predict_query)
builder.add_edge("__start__", "generate_query")
builder.add_edge("generate_query", "retrieve")
builder.add_edge("retrieve", "respond")
builder.add_edge("respond", "predict_query")<h3>2. Aktualisiere prompts.py</h3><ul><li><p>Erstelle eine Eingabeaufforderung für eine Vorhersage in <code>prompts.py</code>:</p></li></ul>PREDICT_NEXT_QUESTION_PROMPT = """Given the user query and the retrieved documents, suggest the most likely next question the user might ask.

**Context:**
- Previous Queries:
{previous_queries}

- Latest User Query: {user_query}

- Retrieved Documents:
{retrieved_docs}

**Guidelines:**
1. Do not suggest a question that has already been asked in previous queries.
2. Consider the retrieved documents when predicting the next logical question.
3. If the user's query is already fully answered, suggest a relevant follow-up question.
4. Keep the suggested question natural and conversational.
5. Suggest at least 3 question

System time: {system_time}"""<h3>3. Aktualisieren Sie die Datei configuration.py</h3><ul><li><p>Fügen Sie <code>predict_next_question_prompt</code> hinzu:</p></li></ul>predict_next_question_prompt: str = field(
       default=prompts.PREDICT_NEXT_QUESTION_PROMPT,
       metadata={"description": "The system prompt used for generating responses."},
   )<h3>4. Aktualisiere state.py</h3><ul><li><p>Fügen Sie die folgenden Attribute hinzu:</p></li></ul>response: Annotated[Sequence[AnyMessage], add_messages]
next_question : Annotated[Sequence[AnyMessage], add_messages]<h3>5. Führen Sie den Abrufgraphen erneut aus.</h3><ul><li><p>Geben Sie die folgende Suchanfrage erneut ein:</p></li></ul>What was NovaTech Solutions total revenue in Q1 2025?<p>Das System verarbeitet die Eingabe und sagt drei verwandte Fragen voraus, die Benutzer stellen könnten, wie unten gezeigt.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd8d4de9396ca4853/6a17f87be31791dc742d59c7/70e855a2e4edc0ba5a147588df0de30eb081d053-1600x777.png" alt="Ausführung des Retrieval-Graphen mit 3 Benutzerfragen unter Verwendung von LangGraph und Elasticsearch" /><h2>Fazit</h2><p>Die Integration der Retrieval Agent-Vorlage in LangGraph Studio und CLI bietet mehrere wichtige Vorteile:</p><ul><li><p><strong>Beschleunigte Entwicklung</strong>: Die Vorlagen- und Visualisierungstools optimieren die Erstellung und das Debuggen von Abruf-Workflows und verkürzen so die Entwicklungszeit.</p></li><li><p><strong>Nahtlose Bereitstellung</strong>: Integrierte Unterstützung für APIs und automatische Skalierung gewährleistet eine reibungslose Bereitstellung in allen Umgebungen.</p></li><li><p><strong>Einfache Updates:</strong> Das Ändern von Arbeitsabläufen, das Hinzufügen neuer Funktionen und die Integration zusätzlicher Knoten ist einfach, wodurch der Abrufprozess leichter skaliert und verbessert werden kann.</p></li><li><p><strong>Permanenter Speicher</strong>: Das System behält Agentenzustände und -wissen bei und verbessert so Konsistenz und Zuverlässigkeit.</p></li><li><p><strong>Flexible Workflow-Modellierung</strong>: Entwickler können Abruflogik und Kommunikationsregeln für bestimmte Anwendungsfälle anpassen.</p></li><li><p><strong>Interaktion und Debugging in Echtzeit</strong>: Die Möglichkeit zur Interaktion mit laufenden Agenten ermöglicht effizientes Testen und Problemlösen.</p></li></ul><p>Durch die Nutzung dieser Funktionen können Unternehmen leistungsstarke, effiziente und skalierbare Abrufsysteme erstellen, die die Datenzugänglichkeit und das Benutzererlebnis verbessern.</p><p>Der vollständige Quellcode für dieses Projekt ist auf <a href="https://github.com/elastic/elasticsearch-labs/tree/main/supporting-blog-content/langraph-retrieval-agent-template-demo">GitHub</a> verfügbar.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/build-rag-workflow-langgraph-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/build-rag-workflow-langgraph-elasticsearch</guid>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Neha Saini]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0c9f03d2c1a9cb4c/6a17f87d0b0bed3781dd377c/17b7e7b336f73e232375d1add582ae5f6c52a279-1440x840.png" length="0" type="image/png"/>
    <pubDate>Fri, 25 Apr 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Verwendung von Amazon Nova-Modellen in Elasticsearch]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie Amazon Nova-Modelle in Elasticsearch verwenden können, um Sentiment, Authentizität, Zusammenfassungen und Schlüsselwörter automatisch aus Produktbewertungen in Elasticsearch zu extrahieren.]]></description>
    <content:encoded><![CDATA[<p>In diesem Artikel werden wir Amazons KI-Modellfamilie Amazon Nova besprechen und lernen, wie man sie zusammen mit Elasticsearch verwendet.</p><h2>Über Amazon Nova</h2><p>Amazon Nova ist eine Familie von künstlichen Intelligenzmodellen von Amazon, die auf Amazon Bedrock verfügbar sind und auf hohe Leistung und Kosteneffizienz ausgelegt sind. Diese Modelle arbeiten mit Text-, Bild- und Videoeingaben, erzeugen Textausgaben und sind für unterschiedliche Anforderungen an Genauigkeit, Geschwindigkeit und Kosten optimiert.</p><h3>Amazon Nova Hauptmodelle</h3><ul><li><p>Amazon Nova Micro: Dieses Modell konzentriert sich ausschließlich auf Textverarbeitung und ist schnell und kostengünstig. Es eignet sich ideal für Übersetzungen, logisches Schlussfolgern, Codevervollständigung und die Lösung mathematischer Probleme. Mit einer Generierungsrate von über 200 Token pro Sekunde eignet es sich ideal für Anwendungen, die sofortige Reaktionen erfordern.</p></li><li><p>Amazon Nova Lite: Ein kostengünstiges multimodales Modell, das Bilder, Videos und Text schnell verarbeiten kann. Es zeichnet sich durch seine Schnelligkeit und Genauigkeit aus und ist für interaktive und hochvolumige Anwendungen geeignet, bei denen Kosten ein wichtiger Faktor sind.</p></li><li><p>Amazon Nova Pro: Die fortschrittlichste Option, die hohe Genauigkeit, Geschwindigkeit und Kosteneffizienz vereint. Ideal für komplexe Aufgaben wie Videozusammenfassung, Frage-Antwort-Systeme, Softwareentwicklung und KI-Agenten. Expertenrezensionen bestätigen seine hervorragende Text- und Bildverarbeitungsfähigkeit sowie seine Fähigkeit, Anweisungen zu befolgen und automatisierte Arbeitsabläufe auszuführen.</p></li></ul><p>Die Amazon Nova-Modelle eignen sich für eine Vielzahl von Anwendungen, von der Content-Erstellung und Datenanalyse bis hin zur Softwareentwicklung und KI-gestützten Prozessautomatisierung.</p><p>Im Folgenden zeigen wir Ihnen, wie Sie Amazon Nova-Modelle in Verbindung mit Elasticsearch für die automatisierte Analyse von Produktbewertungen verwenden können.</p><p>Was wir tun werden:</p><ol><li><p>Erstellen Sie einen Endpunkt über die Inference API, der Amazon Bedrock mit Elasticsearch integriert.</p></li><li><p>Erstellen Sie eine Pipeline mithilfe des Inference Processors, die Aufrufe an den Inference API-Endpunkt durchführt.</p></li><li><p>Indexieren Sie Produktbewertungen und generieren Sie mithilfe der Pipeline automatisch eine Analyse der Bewertungen.</p></li><li><p>Analysieren Sie die Ergebnisse der Integration.</p></li></ol><h2>Erstellung eines Endpoint in der Inference API mit Amazon Nova Lite</h2><p>Zunächst konfigurieren wir die Inference API, um Amazon Bedrock mit Elasticsearch zu integrieren. Wir definieren Amazon Nova Lite, ID <strong>amazon.nova-lite-v1:0</strong>, als das zu verwendende Modell, da es ein ausgewogenes Verhältnis zwischen Geschwindigkeit, Genauigkeit und Kosten bietet.</p><p><strong>Hinweis:</strong> Sie benötigen gültige Zugangsdaten, um Amazon Bedrock nutzen zu können. Die Dokumentation zum Erhalt von Zugriffsschlüsseln finden Sie <a href="https://docs.aws.amazon.com/keyspaces/latest/devguide/create.keypair.html">hier</a>:</p>PUT _inference/completion/bedrock_completion_amazon_nova-lite
{
   "service": "amazonbedrock",
   "service_settings": {
       "access_key": "#access_key#",
       "secret_key": "#secret_key#",
       "region": "us-east-1",
       "provider": "amazontitan",
       "model": "amazon.nova-lite-v1:0"
   }
}<h2>Erstellung der Pipeline für die Bewertungsanalyse</h2><p>Nun erstellen wir eine Verarbeitungspipeline, die den Inferenzprozessor verwendet, um eine Überprüfungsanalyseaufforderung auszuführen. Diese Aufforderung sendet die Bewertungsdaten an Amazon Nova Lite, das Folgendes ausführt:</p><ul><li><p>Sentimentklassifizierung (positiv, negativ oder neutral).</p></li><li><p>Zusammenfassung der Rezension.</p></li><li><p>Schlüsselwortgenerierung.</p></li><li><p>Authentizitätsmessung (authentisch | verdächtig | generisch).</p></li></ul>PUT /_ingest/pipeline/review_analyzer_ai
{
      "processors": [
      {
        "script": 
            {
            "source": """ctx.prompt = "Analyze the following product review and return a structured JSON. Task: - Summarize the review concisely. - Detect and classify the sentiment as positive, neutral, or negative.- Generate relevant tags (keywords) based on the review content and detected sentiment. - Evaluate the authenticity of the review (authentic, suspicious, or generic). Review: " + ctx.review + " Respond in JSON format with the following fields: \"review_analyze\": {\"sentiment\": \"&lt;positive | neutral | negative&gt;\", \"authenticity\": \"&lt;authentic | suspicious | generic&gt;\",\"summary\": \"&lt;short review summary&gt;\", \"keywords\": [\"&lt;keyword 1&gt;\", \"&lt;keyword 2&gt;\", \"...\"]}}}"
            """
            }
      },
      {
        "inference": {
          "model_id": "bedrock_completion_amazon_nova-lite",
          "input_output": {
            "input_field": "prompt",
            "output_field": "result"
          }
        }
      },
      {
        "gsub": {
          "field": "result",
          "pattern": "```json",
          "replacement": ""
        } 
      },
      {
        "json" : {
          "field" : "result",
          "strict_json_parsing": false,
          "add_to_root" : true
        }
      },
      {
        "remove": {
          "field": "result"
        }
      },
      {
        "remove": {
          "field": "prompt"
        }
      }
    ]
}<h2>Indexierungsrezensionen</h2><p>Wir indexieren Produktbewertungen nun mithilfe der Bulk-API. Die zuvor erstellte Pipeline wird automatisch angewendet und fügt die vom Nova-Modell generierte Analyse den indizierten Dokumenten hinzu.</p>POST bulk/
{ "index": { "_index" : "products", "_id": 1, "pipeline":"review_analyzer_ai" } }
{ "product": "Pampers Pants Premium Care Fralda", "review": "Best diaper ever! Great material, lots of cotton, without all that plastic. Doesn't leak! My baby is a boy and every diaper leaked around the waist, this model solved the problem. Even on a small baby it's worth the effort of putting on the short diaper. I put it on my baby at 9 pm and only take it off in the morning, without any leaks." }
{ "index": { "_index" : "products", "_id": 2, "pipeline":"review_analyzer_ai" } }
{ "product": "Portable Electric Body Massager", "review": "It broke in three months for no apparent reason, thank goodness I didn't review it before. I don't recommend buying it because it has a short lifespan." }
{ "index": { "_index" : "products", "_id": 3, "pipeline":"review_analyzer_ai" } }
{ "product": "Havit Fuxi-H3 Black Quad-Mode Wired and Wireless Gaming Headset", "review": "The sound is good for the price, but the connectivity is horrible. You always need to be playing audio, otherwise it loses connection (I work from home, and this is very annoying). Sometimes it loses connection and you have to turn it off and on again to get it back on. The microphone is very sensitive, so it loses connection frequently and you have to turn the headset off and on for the microphone to work again. The flexibility of the stem is useless, because if you move it, the microphone can turn off. Sometimes I need to use Linux and the headset simply doesn't work. It's light and comfortable, the sound is adequate, but the connectivity is terrible." }
{ "index": { "_index" : "products", "_id": 4, "pipeline":"review_analyzer_ai" } }
{ "product": "Air Fryer 4L Oil Free Fryer Mondial", "review": "For those looking for value for money, it's a good option, but the tray (which is underneath the perforated basket) is already peeling a lot. My mother has one just like it and said that hers is even rusting, in other words, the material is MUCH inferior. There's also something that bothers me, because it looks like a microwave, it doesn't fry evenly, it's weaker in the middle and stronger on the sides. Buy at your own risk." }<h2>Abfragen und Analysieren der Ergebnisse</h2><p>Zum Schluss führen wir eine Abfrage durch, um zu sehen, wie das Amazon Nova Lite-Modell die Rezensionen analysiert und klassifiziert. Durch Ausführen von GET products/_search erhalten wir die Dokumente, die bereits mit den aus dem Rezensionsinhalt generierten Feldern angereichert sind.</p><p>Das Modell ermittelt die vorherrschende Stimmung (positiv, neutral oder negativ), generiert prägnante Zusammenfassungen, extrahiert relevante Schlüsselwörter und schätzt die Authentizität jeder Rezension ein. Diese Felder helfen dabei, die Meinung des Kunden zu verstehen, ohne den gesamten Text lesen zu müssen.</p><p>Zur Interpretation der Ergebnisse betrachten wir Folgendes:</p><ul><li><p>Sentiment, das die allgemeine Wahrnehmung des Produkts durch den Konsumenten widerspiegelt.</p></li><li><p>Die Zusammenfassung, in der die wichtigsten Punkte hervorgehoben werden.</p></li><li><p>Schlüsselwörter, die verwendet werden können, um ähnliche Rezensionen zu gruppieren oder Feedbackmuster zu identifizieren.</p></li><li><p>Authentizität, die ein Indikator dafür ist, ob die Rezension vertrauenswürdig erscheint. Dies ist nützlich für die Kuratierung oder Moderation.</p></li></ul>   "hits": [
      {
        "_index": "products",
        "_id": "1",
        "_score": 1,
        "_ignored": [
          "review.keyword"
        ],
        "_source": {
          "product": "Pampers Pants Premium Care Fralda",
          "model_id": "bedrock_completion_amazon_nova-lite",
          "review_analyze": {
            "summary": "The reviewer praises the diaper for its great material, high cotton content, and leak-proof design, especially highlighting its effectiveness for their baby.",
            "sentiment": "positive",
            "keywords": [
              "best diaper",
              "great material",
              "cotton",
              "no plastic",
              "leak-proof",
              "baby",
              "effective"
            ],
            "authenticity": "authentic"
          },
          "review": "Best diaper ever! Great material, lots of cotton, without all that plastic. Doesn't leak! My baby is a boy and every diaper leaked around the waist, this model solved the problem. Even on a small baby it's worth the effort of putting on the short diaper. I put it on my baby at 9 pm and only take it off in the morning, without any leaks."
        }
      },
      {
        "_index": "products",
        "_id": "2",
        "_score": 1,
        "_source": {
          "product": "Portable Electric Body Massager",
          "model_id": "bedrock_completion_amazon_nova-lite",
          "review_analyze": {
            "summary": "The product broke in three months for no apparent reason and the reviewer does not recommend it due to its short lifespan.",
            "sentiment": "negative",
            "keywords": [
              "broke",
              "short lifespan",
              "not recommend"
            ],
            "authenticity": "authentic"
          },
          "review": "It broke in three months for no apparent reason, thank goodness I didn't review it before. I don't recommend buying it because it has a short lifespan."
        }
      },
      {
        "_index": "products",
        "_id": "3",
        "_score": 1,
        "_ignored": [
          "review.keyword"
        ],
        "_source": {
          "product": "Havit Fuxi-H3 Black Quad-Mode Wired and Wireless Gaming Headset",
          "model_id": "bedrock_completion_amazon_nova-lite",
          "review_analyze": {
            "summary": "The headset has good sound quality for the price but suffers from poor connectivity, especially when using the microphone or moving the headset. It also has compatibility issues with Linux.",
            "sentiment": "negative",
            "keywords": [
              "sound",
              "connectivity",
              "microphone",
              "compatibility",
              "annoying",
              "turn off and on",
              "Linux",
              "flexible stem",
              "work from home"
            ],
            "authenticity": "authentic"
          },
          "review": "The sound is good for the price, but the connectivity is horrible. You always need to be playing audio, otherwise it loses connection (I work from home, and this is very annoying). Sometimes it loses connection and you have to turn it off and on again to get it back on. The microphone is very sensitive, so it loses connection frequently and you have to turn the headset off and on for the microphone to work again. The flexibility of the stem is useless, because if you move it, the microphone can turn off. Sometimes I need to use Linux and the headset simply doesn't work. It's light and comfortable, the sound is adequate, but the connectivity is terrible."
        }
      },
      {
        "_index": "products",
        "_id": "4",
        "_score": 1,
        "_ignored": [
          "review.keyword"
        ],
        "_source": {
          "product": "Air Fryer 4L Oil Free Fryer Mondial",
          "model_id": "bedrock_completion_amazon_nova-lite",
          "review_analyze": {
            "summary": "The product offers value for money but has issues with peeling, rusting, and uneven frying.",
            "sentiment": "negative",
            "keywords": [
              "value for money",
              "peeling",
              "rusting",
              "uneven frying",
              "weaker in the middle"
            ],
            "authenticity": "authentic"
          },
          "review": "For those looking for value for money, it's a good option, but the tray (which is underneath the perforated basket) is already peeling a lot. My mother has one just like it and said that hers is even rusting, in other words, the material is MUCH inferior. There's also something that bothers me, because it looks like a microwave, it doesn't fry evenly, it's weaker in the middle and stronger on the sides. Buy at your own risk."
        }
      }
    ]<h2>Fazit</h2><p>Die Integration von Amazon Nova Lite und Elasticsearch demonstrierte, wie Sprachmodelle Rohrezensionen in strukturierte und wertvolle Informationen umwandeln können. Durch die Verarbeitung der Rezensionen mittels einer Pipeline konnten wir Stimmungsanalyse, Authentizität, Zusammenfassungen und Schlüsselwörter automatisch und konsistent extrahieren.</p><p>Die Ergebnisse zeigen, dass das Modell den Kontext der Rezensionen verstehen, Nutzermeinungen klassifizieren und die relevantesten Punkte jeder Erfahrung hervorheben kann. Dadurch entsteht ein wesentlich umfangreicherer Datensatz, der zur Verbesserung der Suchfunktionen genutzt werden kann.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/amazon-nova-models-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/amazon-nova-models-elasticsearch</guid>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Andre Luiz]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdbbf13eb690294f1/6a17fddd6df73195190a115a/304713c48b568e17d0bb56b19edb28769f7801b3-721x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Wed, 02 Apr 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Verbinden Sie Agenten mit Elasticsearch mit dem Model Context Protocol]]></title>
    <description><![CDATA[Lassen Sie uns den Model Context Protocol-Server verwenden, um mit Ihren Daten in Elasticsearch zu chatten.]]></description>
    <content:encoded><![CDATA[<p>Was wäre, wenn die Interaktion mit Ihren Daten so mühelos wäre wie das Chatten mit einem Kollegen? Stellen Sie sich vor, Sie fragen einfach: „Zeigen Sie mir alle Bestellungen über 500 $ vom letzten Monat“ oder „Welche Produkte haben die meisten 5-Sterne-Bewertungen erhalten?“ und Sie erhalten sofort genaue Antworten, ohne dass Sie nachfragen müssen.</p><p>Das Model Context Protocol (MCP) macht dies möglich. Es verbindet die Konversations-KI nahtlos mit Ihren Datenbanken und externen APIs und wandelt komplexe Anfragen in natürliche Konversationen um. Moderne LLMs verfügen zwar über hervorragende Sprachkenntnisse, ihr wahres Potenzial entfaltet sich jedoch erst bei der Integration in reale Systeme. MCP schließt die Lücke zwischen ihnen und macht die Dateninteraktion intuitiver und effizienter.</p><p>In diesem Beitrag untersuchen wir:</p><ul><li><p>MCP-Architektur – So funktioniert es unter der Haube</p></li><li><p>Vorteile eines mit Elasticsearch verbundenen MCP-Servers</p></li><li><p>Erstellen eines <a href="https://github.com/elastic/mcp-server-elasticsearch">Elasticsearch-basierten MCP-Servers</a></p></li></ul><p>Es stehen spannende Zeiten bevor! Die Integration von MCP in Ihren Elastic-Stack verändert die Art und Weise, wie Sie mit Informationen interagieren, und macht komplexe Abfragen so intuitiv wie alltägliche Gespräche.</p><h2>Modellkontextprotokoll</h2><p>Das von Anthropic entwickelte <a href="https://modelcontextprotocol.io/introduction">Model Context Protocol</a> (MCP) ist ein offener Standard, der KI-Modelle über sichere, bidirektionale Kanäle mit externen Datenquellen verbindet. Es löst eine große KI-Einschränkung: Echtzeitzugriff auf externe Systeme unter Beibehaltung des Gesprächskontexts.</p><h3>MCP-Architektur</h3><p>Die Architektur des Model Context Protocol besteht aus zwei Hauptkomponenten:</p><ul><li><p><strong>MCP-Clients</strong> – KI-Assistenten und Chatbots, die im Namen der Benutzer Informationen anfordern oder Aufgaben ausführen.</p></li><li><p><strong>MCP-Server</strong> – Datenspeicher, Suchmaschinen und APIs, die relevante Informationen abrufen oder angeforderte Aktionen ausführen (z. B. Aufrufen externer APIs).</p></li></ul><p>MCP-Server bieten Clients vier Hauptfunktionen:</p><ul><li><p><strong>Ressourcen</strong> – Strukturierte Daten, Dokumente und Inhalte, die abgerufen und als Kontext für LLM-Interaktionen verwendet werden können. Dadurch können KI-Assistenten auf relevante Informationen aus Datenbanken, Suchindizes oder anderen Quellen zugreifen.</p></li><li><p><strong>Tools</strong> – Ausführbare Funktionen, die es LLMs ermöglichen, mit externen Systemen zu interagieren, Berechnungen durchzuführen oder Aktionen in der realen Welt auszuführen. Diese Tools erweitern die KI-Funktionen über die Textgenerierung hinaus und ermöglichen es Assistenten, Workflows auszulösen, APIs aufzurufen oder Daten dynamisch zu bearbeiten.</p></li><li><p><strong>Eingabeaufforderungen</strong> – Wiederverwendbare Eingabeaufforderungsvorlagen und Arbeitsabläufe zum Standardisieren und Teilen gängiger LLM-Interaktionen.</p></li><li><p><strong>Sampling</strong> – Fordern Sie LLM-Vervollständigungen über den Client an, um anspruchsvolles Agentenverhalten zu ermöglichen und gleichzeitig Sicherheit und Datenschutz zu gewährleisten.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfe82754551bb187a/6a17f7ec6864a43e71b6895d/bef5178133391e96e3d66ae634e41a85712a33a9-2345x1620.png" alt="Model Context Protocol (MCP)-Architektur" /><h2>MCP-Server + Elasticsearch</h2><p></p><p>Herkömmliche Retrieval-Augmented Generation (RAG)-Systeme rufen Dokumente basierend auf Benutzerabfragen ab, aber MCP geht noch einen Schritt weiter: Es ermöglicht KI-Agenten, Aufgaben dynamisch zu erstellen und in Echtzeit auszuführen. Dadurch können Benutzer Fragen in natürlicher Sprache stellen, wie zum Beispiel:</p><p></p><ul><li><p>„Zeigen Sie mir alle Bestellungen über 500 $ vom letzten Monat.“</p></li><li><p>„Welche Produkte haben die meisten 5-Sterne-Bewertungen erhalten?“</p></li></ul><p></p><p>Und erhalten Sie sofort präzise Antworten, ohne eine einzige Anfrage zu schreiben.</p><p></p><p>MCP erreicht dies durch:</p><ul><li><p>Dynamische Toolauswahl – Agenten wählen auf intelligente Weise die richtigen Tools aus, die über MCP-Server basierend auf der Benutzerabsicht bereitgestellt werden. „Intelligentere“ LLMs sind im Allgemeinen besser darin, die richtigen Werkzeuge mit den entsprechenden Argumenten basierend auf dem Kontext auszuwählen.</p></li><li><p>Bidirektionale Kommunikation – Agenten und Datenquellen tauschen Informationen reibungslos aus und verfeinern Abfragen nach Bedarf (z. B. Suchen Sie zuerst nach einer Indexzuordnung und erstellen Sie erst dann die ES-Abfrage.</p></li><li><p>Multi-Tool-Orchestrierung – Workflows können Tools von mehreren MCP-Servern gleichzeitig nutzen.</p></li><li><p>Permanenter Kontext – Agenten erinnern sich an vorherige Interaktionen und sorgen so für Kontinuität über Gespräche hinweg.</p></li></ul><p>Ein mit Elasticsearch verbundener MCP-Server ermöglicht eine leistungsstarke Echtzeit-Abrufarchitektur. KI-Agenten können Elasticsearch-Daten bei Bedarf erkunden, abfragen und analysieren. Ihre Daten können über eine einfache Chat-Schnittstelle durchsucht werden.</p><p>MCP dient nicht nur dem Abrufen von Daten, sondern ermöglicht auch Aktionen. Es lässt sich in andere Tools integrieren, um Workflows auszulösen, Prozesse zu automatisieren und Erkenntnisse in Analysesysteme einzuspeisen. Durch die Trennung von Suche und Ausführung sorgt MCP dafür, dass KI-gestützte Anwendungen flexibel und aktuell bleiben und nahtlos in Agenten-Workflows integriert werden.</p><h2>Praxisnah: MCP-Server zum Chatten mit Ihren Elasticsearch-Daten</h2><p>Um über einen MCP-Server mit Elasticsearch zu interagieren, benötigen wir mindestens folgende Funktionen:</p><ul><li><p>Indizes abrufen</p></li><li><p>Zuordnungen abrufen</p></li><li><p>Führen Sie Suchvorgänge mit der Query DSL von Elasticsearch durch</p></li></ul><p>Unser Server ist in TypeScript geschrieben und wir werden das offizielle <a href="https://github.com/modelcontextprotocol/typescript-sdk">MCP TypeScript SDK</a> verwenden. Zur Einrichtung empfehlen wir die Installation der Claude Desktop App (die kostenlose Version ist ausreichend), da diese einen integrierten MCP-Client enthält. Unser MCP-Server stellt im Wesentlichen den offiziellen <a href="https://www.elastic.co/de/guide/en/elasticsearch/client/javascript-api/current/index.html">JavaScript Elasticsearch-Client</a> über MCP-Tools bereit.</p><p>Beginnen wir mit der Definition des Elasticsearch-Clients und des MCP-Servers:</p> const esClient = new Client({
    node: url,
    auth: {
      apiKey: apiKey,
    },
  });

  const server = new McpServer({
    name: "elasticsearch-mcp-server",
    version: "0.1.0",
  });<p>Wir werden die folgenden MCP-Servertools verwenden, die mit Elasticsearch interagieren können:</p><ul><li><p><strong>Indizes auflisten</strong> (<a href="https://github.com/elastic/mcp-server-elasticsearch/blob/main/index.ts#L46">list_indices</a>): Dieses Tool ruft alle verfügbaren Elasticsearch-Indizes ab und liefert Details wie Indexname, Integritätsstatus und Dokumentanzahl.</p></li><li><p><strong>Zuordnungen abrufen</strong> (<a href="https://github.com/elastic/mcp-server-elasticsearch/blob/main/index.ts#L94">get_mappings</a>): Dieses Tool ruft die Feldzuordnungen für einen angegebenen Elasticsearch-Index ab und hilft Benutzern, die Struktur und Datentypen gespeicherter Dokumente zu verstehen.</p></li><li><p><strong>Suche</strong> (<a href="https://github.com/elastic/mcp-server-elasticsearch/blob/main/index.ts#L147">Suche</a>): Dieses Tool führt eine Elasticsearch-Suche mithilfe einer bereitgestellten Abfrage-DSL aus. Es aktiviert automatisch Hervorhebungen für Textfelder und erleichtert so die Identifizierung relevanter Suchergebnisse.</p></li></ul><p>Die vollständige Elasticsearch MCP-Serverimplementierung ist im Repository <a href="https://github.com/elastic/mcp-server-elasticsearch">elastic/mcp-server-elasticsearch</a> verfügbar.</p><h4>Chatten Sie mit Ihrem Index</h4><p>Sehen wir uns an, wie Sie den Elasticsearch MCP-Server einrichten, damit Sie Fragen zu Ihren Daten in natürlicher Sprache stellen können, z. B. „Finden Sie alle Bestellungen über 500 $ vom letzten Monat.“</p><p><strong>Konfigurieren Sie Ihre Claude Desktop App</strong></p><ul><li><p>Öffnen Sie die Claude Desktop App</p></li><li><p>Navigieren Sie zu Einstellungen &gt; Entwickler &gt; MCP-Server</p></li><li><p>Klicken Sie auf „Konfiguration bearbeiten“ und fügen Sie diese Konfiguration zu Ihrem <code>claude_desktop_config.json</code> hinzu:</p></li></ul>{
  "mcpServers": {
    "Elasticsearch MCP Server": {
      "command": "npx",
      "args": [
        "-y",
        "@elastic/mcp-server-elasticsearch"
      ],
      "env": {
        "ES_URL": "",
        "ES_API_KEY": ""
      }
    }
  }
}<p>Hinweis: Dieses Setup verwendet das von Elastic veröffentlichte npm-Paket <a href="https://www.npmjs.com/package/@elastic/mcp-server-elasticsearch">@elastic/mcp-server-elasticsearch</a> . Wenn Sie lokal entwickeln möchten, finden Sie <a href="https://github.com/elastic/mcp-server-elasticsearch/blob/main/README.md">hier</a> weitere Informationen zum Hochfahren des Elasticsearch MCP-Servers.</p><p><strong>Füllen Sie Ihren Elasticsearch-Index</strong></p><ul><li><p>Sie können unsere <a href="https://gist.github.com/jedrazb/60e9400cbe40addfd9e4337749c28431">Beispieldaten</a> verwenden, um den Index "Bestellungen" für diese Demo zu füllen</p></li><li><p>Auf diese Weise können Sie Abfragen wie „Alle Bestellungen über 500 $ vom letzten Monat suchen“ ausprobieren.</p></li></ul><p><strong>Beginnen Sie mit der Nutzung</strong></p><ul><li><p>Öffnen Sie eine neue Konversation in der Claude Desktop App</p></li><li><p>Der MCP-Server verbindet sich automatisch</p></li><li><p>Stellen Sie Fragen zu Ihren Elasticsearch-Daten!</p></li></ul><p>Sehen Sie sich diese Demo an, um zu sehen, wie einfach es ist, Ihre Elasticsearch-Daten mithilfe natürlicher Sprache abzufragen:</p><h4>Wie funktionieren diese Abfragen?</h4><p>Bei der Aufforderung „Alle Bestellungen über 500 $ vom letzten Monat suchen“ erkennt das LLM die Absicht, den Elasticsearch-Index mit angegebenen Einschränkungen zu durchsuchen. Um eine effektive Suche durchzuführen, muss der Agent:</p><ul><li><p>Ermitteln Sie den Indexnamen: <code>orders</code></p></li><li><p>Verstehen Sie die Zuordnungen des <code>orders</code> -Index</p></li><li><p>Erstellen Sie die Query-DSL kompatibel mit Index-Mappings und führen Sie anschließend die Suchanfrage aus</p></li></ul><p>Diese Interaktion kann wie folgt dargestellt werden:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt152f41bc8c3e9752/6a17f7ee6df73152df0a10cc/8875bc75745124be87deac0be666509446887de2-2345x1620.png" alt="Wie funktioniert MCP-Server + Elasticsearch" /><h2>Fazit</h2><p>Das Model Context Protocol verbessert Ihre Interaktion mit Elasticsearch-Daten und ermöglicht Konversationen in natürlicher Sprache anstelle komplexer Abfragen. Durch die Verbindung von KI-Funktionen mit Ihren Daten erstellt MCP einen intuitiveren und effizienteren Workflow, der den Kontext während Ihrer Interaktionen aufrechterhält.</p><p>Der Elasticsearch MCP-Server ist als öffentliches npm-Paket (<a href="https://www.npmjs.com/package/@elastic/mcp-server-elasticsearch">@elastic/mcp-server-elasticsearch</a>) verfügbar, was die Integration für Entwickler unkompliziert macht. Mit minimalem Einrichtungsaufwand kann Ihr Team beginnen, Daten zu untersuchen, Workflows auszulösen und durch einfache Gespräche Erkenntnisse zu gewinnen.</p><p>Bereit, es selbst zu erleben? Testen Sie noch heute den <a href="https://github.com/elastic/mcp-server-elasticsearch">Elasticsearch MCP-Server</a> und beginnen Sie mit dem Chatten mit Ihren Daten.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/model-context-protocol-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/model-context-protocol-elasticsearch</guid>
    <category><![CDATA[Agentische KI]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Jedr Blaszyk,Joe McElroy]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltce68a95c633809ae/6a17f7f0148009fa28b48915/65b378f644bd13e3edf2f108d48186f1889f546c-1200x628.png" length="0" type="image/png"/>
    <pubDate>Fri, 28 Mar 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Aufbau eines multimodalen RAG-Systems mit Elasticsearch: Die Geschichte von Gotham City]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie ein multimodales Retrieval-Augmented Generation (RAG)-System erstellen, das Text-, Audio-, Video- und Bilddaten integriert, um eine umfassendere, kontextualisierte Informationsbeschaffung zu ermöglichen.]]></description>
    <content:encoded><![CDATA[<p>In diesem Blog erfahren Sie, wie Sie mit Elasticsearch eine multimodale RAG-Pipeline (Retrieval-Augmented Generation) erstellen. Wir werden untersuchen, wie Sie ImageBind nutzen können, um Einbettungen für verschiedene Datentypen zu generieren, darunter Text, Bilder, Audio und Tiefenkarten. Sie erfahren auch, wie Sie diese Einbettungen mithilfe von dense_vector und k-NN-Suche effizient in Elasticsearch speichern und abrufen können. Abschließend integrieren wir ein großes Sprachmodell (LLM), um die abgerufenen Beweise zu analysieren und einen umfassenden Abschlussbericht zu erstellen.</p><h3>Wie funktioniert die multimodale RAG-Pipeline?</h3><ol><li><p><strong>Hinweise sammeln</strong> → Bilder, Audio, Texte und Tiefenkarten vom Tatort in Gotham.</p></li><li><p><strong>Einbettungen generieren</strong> → Jede Datei wird mithilfe des multimodalen Modells ImageBind in einen Vektor konvertiert.</p></li><li><p><strong>Indizierung in Elasticsearch</strong> → Die Vektoren werden für einen effizienten Abruf gespeichert.</p></li><li><p><strong>Suche nach Ähnlichkeit</strong> → Bei einem neuen Hinweis werden die ähnlichsten Vektoren abgerufen.</p></li><li><p><strong>Das LLM analysiert die Beweise</strong> → Ein GPT-4-Modell synthetisiert die Antwort und identifiziert den Verdächtigen!</p></li></ol><h3>Eingesetzte Technologien</h3><ul><li><p><strong>ImageBind</strong> → Generiert einheitliche Einbettungen für verschiedene Modalitäten.</p></li><li><p><strong>Elasticsearch</strong> → Ermöglicht eine schnelle und effiziente Vektorsuche.</p></li><li><p><strong>LLM (GPT-4, OpenAI)</strong> → Analysiert die Beweise und erstellt einen Abschlussbericht.</p></li></ul><h3>Für wen ist dieser Blog?</h3><ul><li><p>Elastic-Benutzer, die an der multimodalen Vektorsuche interessiert sind.</p></li><li><p>Entwickler, die multimodales RAG in der Praxis verstehen möchten.</p></li><li><p>Jeder, der nach skalierbaren Lösungen zur Analyse von Daten aus mehreren Quellen sucht.</p></li></ul><h2>Voraussetzungen für multimodale RAG: Aufbau der Umgebung</h2><p>Um das Verbrechen in Gotham City aufzuklären, müssen Sie Ihre Technologieumgebung einrichten. Folgen Sie dieser Schritt-für-Schritt-Anleitung:</p><h3>1. Technische Voraussetzungen</h3><p>Komponente</p><p>Spezifikation</p><p>Betriebssystem</p><p>Linux, macOS oder Windows</p><p>Python</p><p>3.10 oder höher</p><p>RAM</p><p>Mindestens 8 GB (16 GB empfohlen)</p><p>Grafikkarte</p><p>Optional, aber für ImageBind empfohlen</p><h3><strong>2. Einrichten des Projekts</strong></h3><p>Alle Ermittlungsmaterialien sind auf GitHub verfügbar und wir werden für dieses interaktive Erlebnis zur Aufklärung von Verbrechen Jupyter Notebook (Google Colab) verwenden. Befolgen Sie diese Schritte, um zu beginnen:</p><h4>Einrichten mit Jupyter Notebook (Google Colab)</h4><p><strong>1. Zugriff auf das Notebook</strong></p><ul><li><p>Öffnen Sie unser gebrauchsfertiges Google Colab-Notizbuch: <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/building-multimodal-rag-with-elasticsearch-gotham/notebook/01-mmrag-blog-quick-start.ipynb">Multimodales RAG mit Elasticsearch</a><u>.</u></p></li><li><p>Dieses Notizbuch enthält den gesamten Code und alle Erklärungen, die Sie zum Mitmachen benötigen.</p></li></ul><p><strong>2. Klonen Sie das Repository</strong></p># Clone the repository with the multimodal RAG code
!git clone -b https://github.com/elastic/elasticsearch-labs.git

# Navigate to the project directory
cd elasticsearch-labs/supporting-blog-content/building-multimodal-rag-with-elasticsearch-gotham<p><strong>3. Abhängigkeiten installieren</strong></p> # Install PyTorch and related libraries
!pip install torch&gt;=2.1.0 torchvision&gt;=0.16.0 torchaudio&gt;=2.1.0

# Install vision processing libraries
!pip install opencv-python-headless pillow numpy

# Install the specific ImageBind fork
!pip install git+https://github.com/hkchengrex/ImageBind.git

# Install Elasticsearch and environment management
!pip install elasticsearch python-dotenv<p><strong>4. Anmeldeinformationen konfigurieren</strong></p># Input your credentials securely
import getpass

ELASTICSEARCH_URL = input("Enter the Elasticsearch endpoint url: ")
ELASTICSEARCH_API_KEY = getpass.getpass("Enter the Elasticsearch API key: ")
OPENAI_API_KEY = getpass.getpass("Enter the OpenAI API key: ")

# Configure environment variables
import os
os.environ["ELASTICSEARCH_API_KEY"] = ELASTICSEARCH_API_KEY
os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
os.environ["ELASTICSEARCH_URL"] = ELASTICSEARCH_URL<p>Hinweis: Das ImageBind-Modell (~2 GB) wird beim ersten Ausführen automatisch heruntergeladen.</p><p>Nachdem nun alles eingerichtet ist, können wir in die Details eintauchen und das Verbrechen aufklären!</p><h2>Einleitung: Die Kriminalität in Gotham City</h2><p>In einer regnerischen Nacht erschüttert ein schockierendes Verbrechen die Stadt Gotham City. Commissioner Gordon braucht Ihre Hilfe, um das Geheimnis zu lüften. Hinweise sind über verschiedene Formate verstreut: verschwommene Bilder, mysteriöse Audiodaten, verschlüsselte Texte und sogar Tiefenkarten. Sind Sie bereit, die fortschrittlichste KI-Technologie zur Lösung des Falls einzusetzen?</p><p>In diesem Blog werden Sie Schritt für Schritt durch den Aufbau eines <strong>multimodalen RAG-Systems (Retrieval-Augmented Generation)</strong> geführt, das verschiedene Datentypen (<strong>Bilder, Audio, Texte und Tiefenkarten</strong>) in einem einzigen Suchraum vereint. Wir werden <strong>ImageBind</strong> verwenden, um multimodale Einbettungen zu generieren, <strong>Elasticsearch</strong> , um diese Einbettungen zu speichern und abzurufen, und ein <strong>Large Language Model (LLM),</strong> um die Beweise zu analysieren und einen Abschlussbericht zu erstellen.</p><h2>Grundlagen: Multimodale RAG-Architektur</h2><h3>Was ist ein multimodaler RAG?</h3><p>Der Aufstieg von <strong>Retrieval-Augmented Generation (RAG) Multimodal</strong> revolutioniert die Art und Weise, wie wir mit KI-Modellen interagieren. Traditionell arbeiten RAG-Systeme ausschließlich mit Text und rufen relevante Informationen aus Datenbanken ab, bevor sie Antworten generieren. Die Welt beschränkt sich jedoch nicht nur auf Text<strong>– auch Bilder, Videos und Audiodateien enthalten wertvolles Wissen</strong>. Aus diesem Grund gewinnen multimodale Architekturen an Bedeutung, die es KI-Systemen ermöglichen, <strong>Informationen aus verschiedenen Formaten zu kombinieren, um umfassendere und präzisere Antworten zu erhalten</strong>.</p><h3><strong>Drei Hauptansätze für multimodale RAG</strong></h3><p>Zur Implementierung eines multimodalen RAG werden üblicherweise drei Strategien verwendet. Jeder Ansatz hat seine eigenen Vorteile und Einschränkungen, abhängig vom Anwendungsfall:</p><h4>1. Gemeinsamer Vektorraum</h4><p>Daten aus verschiedenen Modalitäten werden mithilfe multimodaler Modelle wie ImageBind in einen gemeinsamen Vektorraum abgebildet. Dadurch können Textabfragen Bilder, Videos und Audiodateien ohne explizite Formatkonvertierung abrufen.</p><p><strong>Vorteile:</strong></p><ul><li><p>Ermöglicht <strong>modalübergreifenden Abruf</strong> ohne explizite Formatkonvertierung.</p></li><li><p>Bietet eine <strong>reibungslose Integration</strong> zwischen verschiedenen Modalitäten und ermöglicht den direkten Abruf von Text, Bild, Audio und Video.</p></li><li><p>Skalierbar für verschiedene Datentypen, daher nützlich für <strong>groß angelegte Abrufanwendungen</strong>.</p></li></ul><p><strong>Nachteile:</strong></p><ul><li><p><strong>Für das Training sind große multimodale Datensätze erforderlich</strong>, die möglicherweise nicht immer verfügbar sind.</p></li><li><p>Der gemeinsame Einbettungsraum kann zu <strong>einer semantischen Drift</strong> führen, bei der die Beziehungen zwischen Modalitäten nicht perfekt erhalten bleiben.</p></li><li><p>Je nach Datensatzverteilung kann <strong>eine Verzerrung in multimodalen Modellen</strong> die Abrufgenauigkeit beeinträchtigen.</p></li></ul><h4>2. Einzelne geerdete Modalität</h4><p>Alle Modalitäten werden vor dem Abruf in ein <strong>einziges Format</strong>, normalerweise <strong>Text</strong>, konvertiert. Beispielsweise werden Bilder durch <strong>automatisch generierte Bildunterschriften</strong> beschrieben und Audiodaten in Text transkribiert.</p><p><strong>Vorteile:</strong></p><ul><li><p><strong>Vereinfacht das Auffinden</strong>, da alles in eine <strong>einheitliche Textdarstellung</strong> umgewandelt wird.</p></li><li><p>Funktioniert gut mit <strong>vorhandenen textbasierten Suchmaschinen</strong>, sodass keine spezielle multimodale Infrastruktur erforderlich ist.</p></li><li><p>Kann <strong>die Interpretierbarkeit</strong> verbessern, da die abgerufenen Ergebnisse in einem für Menschen lesbaren Format vorliegen.</p></li></ul><p><strong>Nachteile:</strong></p><ul><li><p><strong>Informationsverlust</strong>: Bestimmte Details (z. B. räumliche Beziehungen in Bildern, Ton in Audio) werden in Textbeschreibungen möglicherweise nicht vollständig erfasst.</p></li><li><p><strong>Abhängig von der Untertitel-/Transkriptionsqualität</strong>: Fehler in automatischen Anmerkungen können die Abrufeffektivität verringern.</p></li><li><p><strong>Nicht optimal für rein visuelle oder akustische Abfragen,</strong> da beim Konvertierungsprozess möglicherweise wichtiger Kontext entfernt wird.</p></li></ul><h4>3. Getrennte Abholung</h4><p>Behält für jede Modalität <strong>unterschiedliche Modelle</strong> bei. Das System führt für jeden Datentyp <strong>eine separate Suche</strong> durch und <strong>führt die Ergebnisse später zusammen</strong>.</p><p><strong>Vorteile:</strong></p><ul><li><p>Ermöglicht <strong>eine benutzerdefinierte Optimierung pro Modalität</strong> und verbessert so die Abrufgenauigkeit für jeden Datentyp.</p></li><li><p>Geringere Abhängigkeit von <strong>komplexen multimodalen Modellen</strong>, wodurch die Integration vorhandener Abrufsysteme erleichtert wird.</p></li><li><p>Bietet <strong>eine detaillierte Kontrolle über die Rangfolge und Neubewertung,</strong> da Ergebnisse aus verschiedenen Modalitäten dynamisch kombiniert werden können.</p></li></ul><p><strong>Nachteile:</strong></p><ul><li><p><strong>Erfordert eine Zusammenführung der Ergebnisse</strong>, wodurch der Abruf- und Rankingprozess komplexer wird.</p></li><li><p>Kann zu <strong>inkonsistenten Antworten</strong> führen, wenn unterschiedliche Modalitäten widersprüchliche Informationen zurückgeben.</p></li><li><p><strong>Höherer Rechenaufwand</strong> , da für jede Modalität unabhängige Suchvorgänge durchgeführt werden, was die Verarbeitungszeit verlängert.</p></li></ul><h3>Unsere Wahl: Gemeinsamer Vektorraum mit ImageBind</h3><p>Unter diesen Ansätzen haben wir uns für <strong>den Shared Vector Space</strong> entschieden, eine Strategie, die perfekt auf die Anforderungen <strong>effizienter multimodaler Suchen</strong> abgestimmt ist. Unsere Implementierung basiert auf <strong>ImageBind</strong>, einem Modell, das mehrere Modalitäten (<strong>Text, Bild, Audio und Video</strong>) in einem <strong>gemeinsamen Vektorraum</strong> darstellen kann. Dies ermöglicht uns:</p><ul><li><p>Führen Sie <strong>modalübergreifende Suchen</strong> zwischen verschiedenen Medienformaten durch, ohne alles in Text konvertieren zu müssen.</p></li><li><p>Verwenden Sie <strong>ausdrucksstarke Einbettungen</strong> , um Beziehungen zwischen verschiedenen Modalitäten zu erfassen.</p></li><li><p>Sorgen Sie für <strong>Skalierbarkeit und Effizienz</strong>, indem Sie optimierte Einbettungen für einen schnellen Abruf in Elasticsearch speichern.</p></li></ul><p>Durch die Übernahme dieses Ansatzes haben wir eine <strong>robuste multimodale Suchpipeline</strong> erstellt, bei der eine Textabfrage ohne zusätzliche Vorverarbeitung <strong>direkt Bilder oder Audio abrufen</strong> kann. Diese Methode erweitert die praktischen Anwendungen von <strong>der intelligenten Suche in großen Repositorien</strong> bis hin zu <strong>fortschrittlichen multimodalen Empfehlungssystemen</strong>.</p><p>Die folgende Abbildung veranschaulicht den Datenfluss innerhalb der multimodalen RAG-Pipeline und hebt den Indexierungs-, Abruf- und Antwortgenerierungsprozess basierend auf multimodalen Daten hervor:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt77bce4aa5216bcf3/6a17eef263173069e0585b57/a4ffdb44582738991813c045be37312dacb0d4f3-1488x1436.png" alt="Multimodaler Rag-Datenfluss" /><h3>Wie funktioniert der Einbettungsraum?</h3><p>Traditionell stammen Texteinbettungen aus Sprachmodellen (z. B. BERT, GPT). Mit nativen multimodalen Modellen wie <strong>ImageBind</strong> von Meta AI verfügen wir nun über ein Grundgerüst, das Vektoren für mehrere Modalitäten generiert:</p><ul><li><p><strong>Text</strong>: Sätze und Absätze werden in Vektoren derselben Dimension umgewandelt.</p></li><li><p><strong>Bilder (Sehen)</strong>: Pixel werden in denselben dimensionalen Raum abgebildet, der für Text verwendet wird.</p></li><li><p><strong>Audio</strong>: Tonsignale werden in Einbettungen umgewandelt, die mit Bildern und Text vergleichbar sind.</p></li><li><p><strong>Tiefenkarten</strong>: Tiefendaten werden verarbeitet und führen ebenfalls zu Vektoren.</p></li></ul><p>Somit kann jeder Hinweis (<strong>Text, Bild, Audio, Tiefe</strong>) mithilfe von Vektorähnlichkeitsmetriken wie <strong>der Kosinusähnlichkeit</strong> mit jedem anderen verglichen werden. Wenn eine <strong>lachende Audioprobe</strong> und ein <strong>Bild des Gesichts eines Verdächtigen</strong> in diesem Raum „nahe beieinander“ liegen, können wir auf eine gewisse Korrelation schließen (z. B. dieselbe Identität).</p><h2>Phase 1 – Hinweise am Tatort sammeln</h2><p>Bevor wir die Beweise analysieren, müssen wir sie sammeln. Das Verbrechen in Gotham hat Spuren hinterlassen, die in Bildern, Audiodateien, Texten und sogar Tiefendaten verborgen sein könnten. Lassen Sie uns diese Hinweise organisieren, um sie in unser System einzuspeisen.</p><h3>Was haben wir?</h3><p>Commissioner Gordon hat uns die folgenden Akten mit Beweismaterial geschickt, das in vier verschiedenen Modalitäten am Tatort gesammelt wurde:</p><p><strong>Streckenbeschreibung und Modalität</strong></p><p><strong>a) Bilder (2 Fotos)</strong></p><ul><li><p><code>crime_scene1.jpg, crime_scene2.jpg</code> → Fotos vom Tatort. Zeigt verdächtige Spuren auf dem Boden.</p></li><li><p><code>suspect_spotted.jpg</code> → Bild einer Überwachungskamera, das eine Silhouette zeigt, die vom Tatort wegläuft.</p></li></ul><p><strong>b)</strong> <strong>Audio (1 Aufnahme)</strong></p><ul><li><p><code>joker_laugh.wav </code>→ Ein Mikrofon in der Nähe des Tatorts fing ein unheimliches Lachen ein.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte7690380dc545367/6a17eef8be6086886a00483b/3457bab38aa4a3caf61ca2a5e0a8b477ddd15cb1-86x45.png" alt="" /><p><strong>c) Text (1 Nachricht)</strong></p><ul><li><p><code>Riddle.txt, note2.txt</code> → Am Tatort wurden einige mysteriöse Notizen gefunden, die möglicherweise vom Verbrecher hinterlassen wurden.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8e5b8f4bc4124708/6a17eefa1d1b83850c93e50c/8963228dc3b4b7e2106cb6ddffbe2154020eb735-77x79.png" alt="" /><p><strong>d) Tiefe (1 Tiefenkarte)</strong></p><ul><li><p><code>depth_suspect.png</code> → Eine Überwachungskamera mit Tiefensensor hat einen Verdächtigen in einer nahegelegenen Gasse erfasst.</p></li><li><p><code>jdancing-depth.png</code> → Eine Überwachungskamera mit Tiefensensor hat einen Verdächtigen aufgenommen, der die U-Bahn-Station entlangging.</p></li></ul><p>Diese Beweisstücke liegen in unterschiedlichen Formaten vor und können nicht direkt auf die gleiche Weise analysiert werden. Wir müssen sie in Einbettungen umwandeln – numerische Vektoren, die einen kreuzmodalen Vergleich ermöglichen.</p><h3><strong>Dateiorganisation</strong></h3><p>Bevor wir mit der Verarbeitung beginnen, müssen wir sicherstellen, dass alle Hinweise im Datenverzeichnis ordnungsgemäß organisiert sind, damit die Pipeline reibungslos läuft.</p><p><strong>Erwartete Verzeichnisstruktur:</strong></p>data/
├── images/
│   ├── crime_scene1.jpg
│   ├── suspect_spotted.jpg
│   ...
├── audios/
│   ├── joker_laugh.wav
│   ...
├── texts/
│   ├── riddle.txt
│   ... 
├── depths/
│   ├── depth_suspect.png<h3>Code zur Überprüfung der Hinweisorganisation</h3><p>Bevor wir fortfahren, stellen wir sicher, dass sich alle erforderlichen Dateien am richtigen Speicherort befinden.</p>import os

# Base directory for clues
data_dir = "data"

# List of expected files
evidences = {
    "images": ["crime_scene1.jpg","crime_scene1.jpg", "joker_alley.jpg"],
    "audios": ["joker_laugh.wav"],
    "texts": ["riddle.txt", "note2.txt”],
    "depths": ["depth_suspect.png", "jdancing-depth.png"]
}

# Create directories if they don't exist
for category, files in evidences.items():
    category_path = os.path.join(data_dir, category)
    os.makedirs(category_path, exist_ok=True)

    for file in files:
        file_path = os.path.join(category_path, file)
        if not os.path.exists(file_path):
            print(f"Warning: {file} not found in {category_path}.")

print("All files are correctly organized!")<p><strong>Ausführen der Datei</strong></p>python  stages/01-stage/files_check.py<p><strong>Erwartete Ausgabe (wenn alle Dateien korrekt sind):</strong></p>All files are correctly organized!<p><strong>Erwartete Ausgabe (falls eine Datei fehlt):</strong></p>Warning: joker_laugh.wav not found in data/audios/
Warning: depth_suspect.png not found in data/depths/<p>Dieses Skript hilft, Fehler zu vermeiden, bevor wir mit der Generierung von Einbettungen und deren Indizierung in Elasticsearch beginnen.</p><h2>Phase 2 – Organisieren der Beweise</h2><h3>Einbettungen mit ImageBind generieren</h3><p>Um die Hinweise zu vereinheitlichen, müssen wir sie in Einbettungen umwandeln – Vektordarstellungen, die die Bedeutung jeder Modalität erfassen. Wir verwenden <strong>ImageBind</strong>, ein Modell von Meta AI, das Einbettungen für verschiedene Datentypen (<strong>Bilder, Audio, Text und Tiefenkarten</strong>) innerhalb eines gemeinsamen Vektorraums generiert.
</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltff4aefffbfb5bf00/6a17eefe6864a45aecb68860/b19a1c32cc7a0b4c00fa5b247b18cce71f9693cb-1580x918.png" alt="Einbettungen mit ImageBind generieren" /><h3><strong>Wie funktioniert ImageBind?</strong></h3><p>Um verschiedene Arten von Beweisen (<strong>Bilder, Audio, Text und Tiefenkarten</strong>) zu vergleichen, müssen wir sie mithilfe von <strong>ImageBind</strong> in numerische Vektoren umwandeln. Dieses Modell ermöglicht die Konvertierung aller Eingabetypen in dasselbe Einbettungsformat und ermöglicht so <strong>modalitätsübergreifende Suchen</strong> .</p><p>Nachfolgend finden Sie einen optimierten Code (<code>src/embedding_generator.py</code>), um Einbettungen für alle Eingabetypen unter Verwendung der entsprechenden Prozessoren für jede Modalität zu generieren:</p>class EmbeddingGenerator:
    """Class for generating multimodal embeddings using ImageBind."""
    
    def __init__(self):
        self.device = "cuda" if torch.cuda.is_available() else "cpu"
        self.model = self._load_model()

    def _load_model(self):
        """Loads the ImageBind model and sets it to inference mode."""
        model = imagebind_model.imagebind_huge(pretrained=True)
        model.eval()
        model.to(self.device)
        return model

    def generate_embedding(self, input_data, modality):
        """Generates embedding for different modalities"""
        processors = {
            "vision": lambda x: data.load_and_transform_vision_data(x, self.device),
            "audio": lambda x: data.load_and_transform_audio_data(x, self.device),
            "text": lambda x: data.load_and_transform_text(x, self.device),
            "depth": self.process_depth
        }
        
        try:
            # Input type verification
            if not isinstance(input_data, list):
                raise ValueError(f"Input data must be a list. Received: {type(input_data)}")
                
            # Convert input data to a tensor format that the model can process
            # For images: [batch_size, channels, height, width] 
            # For audio: [batch_size, channels, time] 
            # For text: [batch_size, sequence_length]
            inputs = {modality: processors[modality](input_data)}
            with torch.no_grad():
                embedding = self.model(inputs)[modality]
            return embedding.squeeze(0).cpu().numpy()
        except Exception as e:
            logger.error(f"Error generating {modality} embedding: {str(e)}", exc_info=True)
            raise<p>Ein Tensor ist eine grundlegende Datenstruktur im maschinellen Lernen und Deep Learning, insbesondere bei der Arbeit mit Modellen wie ImageBind. In unserem Kontext:</p>input_tensor = processors[modality]([input_data], self.device)<p>Hier stellt der Tensor die Eingabedaten (Bild, Audio oder Text) dar, die in ein mathematisches Format konvertiert werden, das das Modell verarbeiten kann. Speziell:</p><ul><li><p><strong>Für Bilder</strong>: Der Tensor stellt das Bild als mehrdimensionale Matrix numerischer Werte dar (Pixel, organisiert nach Höhe, Breite und Farbkanälen).</p></li><li><p><strong>Für Audio</strong>: Der Tensor stellt Schallwellen als eine Abfolge von Amplituden über die Zeit dar.</p></li><li><p><strong>Für Text</strong>: Der Tensor stellt Wörter oder Token als numerische Vektoren dar.</p></li></ul><h3>Testen der Einbettungsgenerierung:</h3><p>Testen wir unsere Einbettungsgenerierung mit dem folgenden Code. Speichern Sie es in 02-stage/test_embedding_generation.py und führen Sie es mit diesem Befehl aus:</p>python stages/02-stage/test_embedding_generation.py generator = EmbeddingGenerator()
image_embedding = generator.generate_embedding("data/images/crime_scene1.jpg","vision")

print(image_embedding.shape)<h3>Erwartete Ausgabe:</h3>(1024,)<p>Nun wurde das Bild in einen <strong>1024-dimensionalen Vektor</strong> umgewandelt.</p><h2>Phase 3 – Speicherung und Suche in Elasticsearch</h2><p>Nachdem wir nun die Einbettungen für die Beweise generiert haben, müssen wir sie in einer Vektordatenbank speichern, um effiziente Suchvorgänge zu ermöglichen. Hierzu verwenden wir <strong>Elasticsearch</strong>, das dichte Vektoren (<code>dense_vector</code>) unterstützt und Ähnlichkeitssuchen ermöglicht.</p><p>Dieser Schritt besteht aus zwei Hauptprozessen:</p><ul><li><p><strong>Indizierung der Einbettungen</strong> → Speichert die generierten Vektoren in Elasticsearch.</p></li><li><p><strong>Ähnlichkeitssuche</strong> → Ruft die ähnlichsten Datensätze zu einem neuen Beweisstück ab.</p></li></ul><h3>Indizierung der Beweise in Elasticsearch</h3><p>Jedes von <strong>ImageBind</strong> verarbeitete Beweisstück (Bild, Audio, Text oder Tiefe) wird in einen <strong>1024-dimensionalen Vektor</strong> umgewandelt. Wir müssen diese Vektoren in <strong>Elasticsearch</strong> speichern, um zukünftige Suchen zu ermöglichen.</p><p>Der folgende Code (<code>src/elastic_manager.py</code>) erstellt einen <strong>Index</strong> in Elasticsearch und konfiguriert die Zuordnung zum Speichern der Einbettungen.</p>from elasticsearch import Elasticsearch, helpers
...

class ElasticsearchManager:
    """Manages multimodal operations in Elasticsearch"""
    
    def __init__(self):
        load_dotenv()  # Load variables from .env
        self.es = self._connect_elastic()
        self.index_name = "multimodal_content"
        self._setup_index()
    
    def _connect_elastic(self):
        """Connects to Elasticsearch"""
        return Elasticsearch(
            os.getenv("ELASTICSEARCH_URL"),  # Elasticsearch endpoint
            api_key=os.getenv("ELASTICSEARCH_API_KEY")
        )
    
    def _setup_index(self):
        """Sets up the index if it doesn't exist"""
        if not self.es.indices.exists(index=self.index_name):
            mapping = {
                "mappings": {
                    "properties": {
                        "embedding": {
                            "type": "dense_vector",
                            "dims": 1024,
                            "index": True,
                            "similarity": "cosine"
                        },
                        "modality": {"type": "keyword"},
                        "content": {"type": "binary"},
                        "description": {"type": "text"},
                        "metadata": {"type": "object"},
                        "content_path": {"type": "text"}
                    }
                }
            }
            self.es.indices.create(index=self.index_name, body=mapping)
    
    def index_content(self, embedding, modality, content=None, description="", metadata=None, content_path=None):
        """Indexes multimodal content"""
        doc = {
            "embedding": embedding.tolist(),
            "modality": modality,
            "description": description,
            "metadata": metadata or {},
            "content_path": content_path
        }
        
        if content:
            doc["content"] = base64.b64encode(content).decode() if isinstance(content, bytes) else content
        
        return self.es.index(index=self.index_name, document=doc)
    
    def search_similar(self, query_embedding, modality=None, k=5):
        """Searches for similar contents"""
        query = {
            "knn": {
                "field": "embedding",
                "query_vector": query_embedding.tolist(),
                "k": k,
                "num_candidates": 100,
                "filter": [{"term": {"modality": modality}}] if modality else []
            }
        }
        
        try:
            response = self.es.search(
                index=self.index_name,
                query=query,
                size=k            
            )
            
            # Return both source data and score for each hit
            return [{
                **hit["_source"],
                "score": hit["_score"]
            } for hit in response["hits"]["hits"]]
        
        except Exception as e:
            print(f"Error: processing search_evidence: {str(e)}")
            return "Error generating search evidence"<h3>Ausführen der Indizierung</h3><p>Lassen Sie uns nun ein Beweisstück indizieren, um den Prozess zu testen.</p># Example: Indexing an image from the crime scene
generator = EmbeddingGenerator()
es_manager = ElasticsearchManager(cloud_id="YOUR_CLOUD_ID", api_key="YOUR_API_KEY")

image_embedding = generator.generate_embedding("data/images/crime_scene1.jpg", "vision")

response = es_manager.index_content(
    embedding=image_embedding,
    modality="vision",
    description="Photo of the crime scene with suspicious traces",
    content_path="data/images/crime_scene1.jpg"
)
print(json.dumps(response, indent=2))<p><strong>Erwartete Ausgabe in Elasticsearch (Zusammenfassung des indizierten Dokuments):</strong></p>{
    "embedding": [0.12, -0.53, 0.89, ...],  
    "modality": "vision",  
    "description": "Photo of the crime scene with suspicious traces",  
    "content_path": "data/images/crime_scene1.jpg"  
}<p>Um alle multimodalen Beweise zu indizieren, führen Sie bitte den folgenden Python-Befehl aus:</p>python stages/03-stage/index_all_modalities.py<p>Jetzt werden die Beweise in <strong>Elasticsearch</strong> gespeichert und können bei Bedarf abgerufen werden.</p><h3>Überprüfen des Indizierungsprozesses</h3><p>Nachdem wir das Indexierungsskript ausgeführt haben, überprüfen wir, ob alle unsere Beweise korrekt in Elasticsearch gespeichert wurden. Sie können <strong>die Dev Tools von Kibana</strong> verwenden, um einige Überprüfungsabfragen auszuführen:</p><p>1. Überprüfen Sie zunächst, ob der Index erstellt wurde:</p>GET _cat/indices/multimodal_content?v<p>2. Überprüfen Sie dann die Anzahl der Dokumente pro Modalität:</p>GET multimodal_content/_search
{
  "size": 0,
  "aggs": {
    "modalities": {
      "terms": {
        "field": "modality.keyword"
      }
    }
  }
}<p>3. Untersuchen Sie abschließend die indizierte Dokumentstruktur:</p>GET multimodal_content/_search
{
  "size": 1,
  "query": {
    "match_all": {}
  }
}<h4>Erwartete Ergebnisse:</h4><ul><li><p>Ein Index mit dem Namen „multimodal_content“ sollte vorhanden sein.</p></li><li><p>Etwa 7 Dokumente, verteilt auf verschiedene Modalitäten (Bild, Audio, Text, Tiefe).</p></li><li><p>Jedes Dokument sollte die Felder „Einbettung“, „Modalität“, „Beschreibung“, „Metadaten“ und „content_path“ enthalten.</p></li></ul><p>Dieser Überprüfungsschritt stellt sicher, dass unsere Beweisdatenbank ordnungsgemäß eingerichtet ist, bevor wir mit der Ähnlichkeitssuche fortfahren.</p><h3>Suche nach ähnlichen Beweisen in Elasticsearch</h3><p>Nachdem die Beweise nun indiziert wurden, können wir Suchen durchführen, um die Datensätze zu finden, die einem neuen Hinweis am ähnlichsten sind. Diese Suche verwendet <strong>Vektorähnlichkeit</strong> , um die ähnlichsten Datensätze im <strong>Einbettungsraum</strong> zurückzugeben.</p><p>Der folgende Code führt diese Suche durch.</p>def search_similar_evidence(self, query_embedding, k=5, modality=None):
    """Performs a kNN search to find the most similar clues."""
    
    knn_query = {
        "field": "embedding",
        "query_vector": query_embedding.tolist(),
        "k": k,
        "num_candidates": 100
    }

    query_body = {"knn": knn_query}
    if modality:
        query_body = {
            "bool": {
                "must": [
                    query_body, 
                    {"term": {"modality": modality}}
                ]
            }
        }

    try:
      results = self.es.search(
        index=self.index_name,
        query=query_body,
        _source_includes=["description", "modality", "content_path"],
        size=k
      )
    except Exception as e:
            print(f"Error processing search_evidence: {str(e)}")
            return "Error generating search evidence”

    return results["hits"]["hits"]<h3>Testen der Suche – Verwenden von Audio als Abfrage für multimodale Ergebnisse</h3><p>Testen wir nun die Beweissuche anhand einer <strong>verdächtigen Audiodatei</strong>. Wir müssen auf die gleiche Weise eine Einbettung für die Datei generieren und nach ähnlichen Einbettungen suchen:</p>python stages/03-stage/search_by_audio.py# Initialize classes
generator = EmbeddingGenerator()
es_manager = ElasticsearchManager(cloud_id="YOUR_CLOUD_ID", api_key="YOUR_API_KEY")

# Generate embedding for a suspicious audio
audio_embedding = generator.generate_embedding("data/audios/mysterious_laugh.wav", "audio")

# Search for similar evidence in Elasticsearch
similar_evidences = es_manager.search_similar_evidence(audio_embedding, k=3)

# Display the retrieved results
print("\n🔎 Similar evidence found:\n")
for i, evidence in enumerate(similar_evidences, start=1):
    description = evidence['_source']['description']
    modality = evidence['_source']['modality']
    score = evidence['_score']
    content_path = evidence['_source'].get('content_path', 'N/A')

    print(f"{i}. {description} ({modality})")
    print(f"   Similarity: {score:.4f}")
    print(f"   File path: {content_path}\n")<p><strong>Erwartete Ausgabe im Terminal:</strong></p>🔎 Similar evidence found:

1. A sinister laugh captured near the crime scene (audio)
   Similarity: 0.9985
   File path: data/audios/joker_laugh.wav

2. The Joker with green hair, white face paint, and a sinister smile in an urban night setting. (vision)
   Similarity: 0.6068
   File path: data/images/joker_laughing.png

3. Suspect dancing (vision)
   Similarity: 0.5591
   File path: data/images/jdancing.png<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt73f8f56b0f2b8493/6a17ef01faa91381ca93c94e/24067ea40f7958e171149221f83cbd9bcfccc53f-1582x1208.png" alt="" /><p>Jetzt können wir <strong>die gefundenen Beweise analysieren</strong> und ihre Relevanz für den Fall bestimmen.</p><h3>Mehr als Audio – Multimodale Suchen erkunden</h3><h4>Rollentausch: Jede Modalität kann eine „Frage“ sein</h4><p>In unserem <strong>multimodalen RAG-</strong> System ist <strong>jede Modalität</strong> eine potenzielle <strong>Suchanfrage</strong>. Lassen Sie uns über das Audiobeispiel hinausgehen und untersuchen, wie andere Datentypen <strong>Untersuchungen einleiten</strong> können.</p><h4>1. Suche nach Text (Entzifferung der Notiz des Täters)</h4><p>Szenario: Sie haben eine <strong>verschlüsselte Textnachricht</strong> gefunden und möchten entsprechende Beweise finden.</p>python stages/03-stage/search_by_text.py# Generate embedding from text
text = "Why so serious?"
embedding_text = generator.generate_embedding([text], "text")

# Search for related evidence
similar_evidences = es_manager.search_similar(
    query_embedding=embedding_text,
    k=3
)<p><strong>Erwartete Ergebnisse:</strong></p>🔎 Similar evidence found:

1. Mysterious note found at the location (text)
   Similarity: 0.7639
   File path: data/texts/riddle.txt

2. The Joker with green hair, white face paint, and a sinister smile in an urban night setting. (vision)
   Similarity: 0.7161
   File path: data/images/joker_laughing.png

3. Why so serious (text)
   Similarity: 0.7132
   File path: data/texts/note2.txt<h4>2. Bildersuche (Verfolgung des verdächtigen Tatorts)</h4><p><strong>Szenario:</strong> Ein <strong>neuer Tatort</strong> (<code>crime_scene2.jpg</code>) muss mit anderen Beweisen verglichen werden.
</p>python stages/03-stage/search_by_image.py# Generate embedding for a suspicious image
vision_embedding = generator.generate_embedding(["data/images/crime_scene2.jpg"], "vision")

# Search for similar evidence in Elasticsearch
similar_evidences = es_manager.search_similar(
    query_embedding=vision_embedding,
    k=3
)<p><strong>Ausgabe:</strong></p>🔎 Similar evidence found:

1. Photo of the crime scene: A dark, rain-soaked alley is filled with playing cards, while a sinister graffiti of the Joker laughing stands out on the brick wall. (vision)
   Similarity: 0.8258
   File path: data/images/crime_scene1.jpg

2. The Joker with green hair, white face paint, and a sinister smile in an urban night setting. (vision)
   Similarity: 0.6897
   File path: data/images/joker_laughing.png

3. Suspect dancing (vision)
   Similarity: 0.6588
   File path: data/images/jdancing.png<h4>3. Tiefenkartensuche (3D-Verfolgung)</h4><p><strong>Szenario:</strong> Eine <strong>Tiefenkarte</strong> (<code>jdancing-depth.png</code>) deckt <strong>Bildfluchtmuster</strong> <strong>auf</strong>.</p>python stages/03-stage/search_by_depth.py# Generate embedding for a suspicious depth map
vision_embedding = generator.generate_embedding(["data/depths/jdancing-depth.png"], "depth")

# Search for similar evidence in Elasticsearch
similar_evidences = es_manager.search_similar(
    query_embedding=vision_embedding,
    modality="vision",
    k=3
)<p><strong>Ausgabe</strong></p>🔎 Similar evidence found:

1. The Joker with green hair, white face paint, and a sinister smile in an urban night setting. (vision)
   Similarity: 0.5329
   File path: data/images/joker_laughing.png<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt224eaf1be75a8b6b/6a17ef03e8fbceada23a1a0e/985f9536db95c772c696dfac996822fb00f199ee-1594x1160.png" alt="" /><p></p>2. Photo of the crime scene: A dark, rain-soaked alley is filled with playing cards, while a sinister graffiti of the Joker laughing stands out on the brick wall. (vision)
   Similarity: 0.5053
   File path: data/images/crime_scene1.jpg<p></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9d75bdf986e1bbdd/6a17eef32f4a5c25d5fa89b1/7023ee786ccc760689257abbde2f759ca3cf5c59-1024x768.jpg" alt="" />3. Suspect dancing (vision)
   Similarity: 0.4859
   File path: data/images/jdancing.png<p></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt73f8f56b0f2b8493/6a17ef01faa91381ca93c94e/24067ea40f7958e171149221f83cbd9bcfccc53f-1582x1208.png" alt="" /><h3><strong>Warum ist das wichtig?</strong></h3><p>Jede Modalität weist <strong>einzigartige Verbindungen</strong> auf:</p><ul><li><p><strong>Text</strong> → Sprachliche Muster des Verdächtigen.</p></li><li><p><strong>Bilder</strong> → Erkennung von <strong>Orten und Objekten.</strong></p></li><li><p><strong>Tiefe</strong> → 3D- <strong>Szenenrekonstruktion.</strong></p></li></ul><p>Jetzt verfügen wir in <strong>Elasticsearch</strong> <strong>über eine strukturierte Beweisdatenbank</strong>, die es uns ermöglicht,<strong>multimodale Beweise effizient zu speichern und abzurufen</strong>.</p><h3><strong>Zusammenfassung unserer Aktivitäten:</strong></h3><ul><li><p><strong>Gespeicherte multimodale Einbettungen</strong> in Elasticsearch.</p></li><li><p><strong>Führte Ähnlichkeitssuchen durch</strong> und fand Beweise im Zusammenhang mit neuen Hinweisen.</p></li><li><p><strong>Die Suche wurde mit einer verdächtigen Audiodatei getestet</strong>, um sicherzustellen, dass das System ordnungsgemäß funktioniert.</p></li></ul><p><strong>Nächster Schritt:</strong> Wir werden ein <strong>LLM</strong> (Large Language Model) verwenden, um <strong>die abgerufenen Beweise zu analysieren</strong> und einen <strong>Abschlussbericht</strong> zu erstellen.</p><h2>Stufe 4 – Die Punkte mit dem LLM verbinden</h2><p>Nachdem die Beweise nun in <strong>Elasticsearch</strong> <strong>indiziert wurden</strong> und anhand der Ähnlichkeit abgerufen werden können, benötigen wir ein <strong>LLM (Large Language Model),</strong> um sie <strong>zu analysieren</strong> und einen <strong>Abschlussbericht zu</strong> erstellen, den wir an Kommissar Gordon senden können. Der <strong>LLM</strong> ist dafür verantwortlich <strong>, Muster zu erkennen, Hinweise zu verknüpfen und auf Grundlage der gefundenen Beweise einen möglichen Verdächtigen vorzuschlagen</strong> .</p><p>Für diese Aufgabe verwenden wir <strong>GPT-4 Turbo</strong> und formulieren eine <strong>detaillierte Eingabeaufforderung</strong> , damit das Modell die Ergebnisse effizient <strong>interpretieren</strong> kann.</p><h3><strong>LLM-Integration</strong></h3><p>Um das <strong>LLM</strong> in unser System zu integrieren, haben wir die <strong>LLMAnalyzer-</strong> Klasse (<code>src/llm_analyzer.py</code>) erstellt, die die <strong>abgerufenen Beweise</strong> von <strong>Elasticsearch</strong> empfängt und einen <strong>forensischen Bericht</strong> erstellt, der diese Beweise als Eingabekontext verwendet.</p>import os
from openai import OpenAI
import logging
from dotenv import load_dotenv

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class LLMAnalyzer:
    """Evidence analyzer using GPT-4"""
    
    def __init__(self):
        load_dotenv()
        self.client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
    
    def analyze_evidence(self, evidence_results):
        """
        Analyzes multimodal search results and generates a report
        
        Args:
            evidence_results: Dict with results by modality
            {
                'vision': [...],
                'audio': [...],
                'text': [...],
                'depth': [...]
            }
        """
        # Format evidence for the prompt
        evidence_summary = self._format_evidence(evidence_results)

        # final prompt
        prompt = f"""
You are a highly experienced forensic detective specializing in multimodal evidence analysis. Your task is to analyze the collected evidence (audio, images, text, depth maps) and conclusively determine the **prime suspect** responsible for the Gotham Central Bank case.

---

### **Collected Evidence:**
{evidence_summary}

### **Task:**
1. **Analyze all the evidence** and identify cross-modal connections.
2. **Determine the exact identity of the criminal** based on behavioral patterns, visual/auditory/textual clues, and symbolic markers.
3. **Justify your conclusion** by explaining why this suspect is definitively responsible.
4. **Assign a confidence score (0-100%)** to your conclusion.

---

### **Final Output Format (Strictly Follow This Format):**
- **Prime Suspect:** [Full Name or Alias]
- **Evidence Supporting Conclusion:** [Detailed breakdown of visual, auditory, textual, and behavioral evidence]
- **Behavioral Patterns:** [Key actions, motives, and criminal signature]
- **Confidence Level:** [0-100%]
- **Next Steps (if any):** [What additional evidence would further confirm the identity? If none, state "No further evidence required."]

If there is **insufficient evidence**, specify exactly what is missing and suggest what additional data would be needed for a conclusive identification.

This report must be **direct and definitive**--avoid speculation and provide a final, actionable determination of the suspect's identity.
"""
        try:
            response = self.client.chat.completions.create(
                model="gpt-4-turbo-preview",
                messages=[
                    {
                        "role": "system",
                        "content": "You are a forensic detective specialized in multimodal evidence analysis."
                    },
                    {"role": "user", "content": prompt_01}
                ],
                temperature=0.5,
                max_tokens=1000
            )
            
            report = response.choices[0].message.content
            logger.info("\n📋 Forensic Report Generated:")
            logger.info("=" * 50)
            logger.info(report)
            logger.info("=" * 50)
            
            return report
            
        except Exception as e:
            logger.error(f"Error generating report: {str(e)}")
            return None<h4>Temperatureinstellung in der LLM-Analyse:</h4><p>Für unser forensisches Analysesystem verwenden wir eine moderate Temperatur von 0,5. Diese ausgewogene Einstellung wurde gewählt, weil:</p><ul><li><p>Es stellt einen Mittelweg zwischen deterministischen (zu starren) und stark zufälligen Ergebnissen dar;</p></li><li><p>Bei 0,5 behält das Modell genügend Struktur bei, um logische und vertretbare forensische Schlussfolgerungen zu liefern;</p></li><li><p>Diese Einstellung ermöglicht es dem Modell, Muster zu erkennen und Verbindungen herzustellen, während es gleichzeitig innerhalb angemessener forensischer Analyseparameter bleibt.</p></li><li><p>Es gleicht den Bedarf an konsistenten, zuverlässigen Ergebnissen mit der Fähigkeit aus, aufschlussreiche Analysen zu erstellen.</p></li></ul><p>Diese moderate Temperatureinstellung trägt dazu bei, dass unsere forensische Analyse sowohl zuverlässig als auch aufschlussreich ist und sowohl zu starre als auch zu spekulative Schlussfolgerungen vermieden werden.</p><h3>Ausführen der Beweisanalyse</h3><p>Nachdem wir nun über die <strong>LLM-Integration</strong> verfügen, benötigen wir ein <strong>Skript</strong> , das alle Systemkomponenten verbindet. Dieses Skript wird:</p><ul><li><p><strong>Suchen Sie in Elasticsearch nach ähnlichen Beweisen</strong> <strong>.</strong></p></li><li><p><strong>Analysieren Sie die abgerufenen Beweise</strong> mithilfe des <strong>LLM</strong> , um einen <strong>Abschlussbericht zu erstellen.</strong></p></li></ul><h4>Code: Skript zur Beweisanalyse</h4>python stages/04-stage/rag_crime_analyze.pyimport sys
import os
sys.path.append(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'src'))

from embedding_generator import EmbeddingGenerator
from elastic_manager import ElasticsearchManager
from llm_analyzer import LLMAnalyzer

import json
import logging
from dotenv import load_dotenv

# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Load environment variables
load_dotenv()

# Initialize classes
generator = EmbeddingGenerator()
es_manager = ElasticsearchManager()

llm = LLMAnalyzer()
logger.info("✅ All components initialized successfully")
    
try:
    evidence_data = {}
    
    # Get data for each modality
    test_files = {
        'vision': 'data/images/crime_scene2.jpg',
        'audio': 'data/audios/joker_laugh.wav',
        'text': 'Why so serious?',
        'depth': 'data/depths/jdancing-depth.png'
    }
    
    logger.info("🔍 Collecting evidence...")
    for modality, test_input in test_files.items():
        try:
            if modality == 'text':
                embedding = generator.generate_embedding([test_input], modality)
            else:
                embedding = generator.generate_embedding([str(test_input)], modality)
            
            results = es_manager.search_similar(embedding, k=2)
            if results:
                evidence_data[modality] = results
                logger.info(f"✅ Data retrieved for {modality}: {len(results)} results")
            else:
                logger.warning(f"⚠️ No results found for {modality}")
                
        except Exception as e:
            logger.error(f"❌ Error retrieving {modality} data: {str(e)}")
    
    if not evidence_data:
        raise ValueError("No evidence data found in Elasticsearch!")
    
    # Test forensic report generation
    logger.info("\n📝 Generating forensic report...")
    report = llm.analyze_evidence(evidence_data)
    
    if report:
        logger.info("✅ Forensic report generated successfully")
        logger.info("\n📊 Report Preview:")
        logger.info("+" * 50)
        logger.info(report)
        logger.info("+" * 50)
    else:
        raise ValueError("Failed to generate forensic report")
        
except Exception as e:
    logger.error(f"❌ Error in analysis : {str(e)}")<h4>Erwartete LLM-Ausgabe</h4>**Prime Suspect:** The Joker

**Evidence Supporting Conclusion:**

- **Visual Evidence:**
  - The photo of the crime scene with playing cards scattered around and the graffiti of the Joker laughing matches the Joker's known calling cards and thematic elements. The similarity score of 0.83 indicates a high likelihood that these elements are directly associated with the Joker.
  - The image of the Joker with green hair, white face paint, and a sinister smile in an urban night setting, although with a lower similarity score of 0.69, still supports the presence or recent activity of the Joker in areas consistent with the crime scene's characteristics.

- **Auditory Evidence:**
  - The captured sinister laugh with a similarity score of 1.00 perfectly matches known audio profiles of the Joker, making it a direct auditory signature of his presence at or near the crime scene.
  - Despite the lower similarity score of 0.61, the second audio piece further corroborates the Joker's involvement through thematic consistency.

- **Textual Evidence:**
  - The mysterious note found at the location, with a similarity score of 0.76, likely contains thematic or direct references to the Joker's modus operandi or signature phrases, further implicating him in the crime.
  - The similarity score of 0.72 for the Joker's description in textual evidence reinforces the thematic connection to the crime scene.

- **Depth Evidence:**
  - Depth sensor capture of the suspect with a similarity score of 0.77 suggests a physical presence matching the Joker's known dimensions or characteristic movements.
  - The lower similarity score of 0.53 in the second depth evidence still contributes to the overall pattern of evidence pointing towards the Joker, albeit with less certainty.

**Behavioral Patterns:**
- The Joker is known for his theatrical crimes, often leaving behind a signature trail of chaos, including playing cards, sinister laughter, and thematic graffiti. These elements are not only consistent with his known criminal signature but also directly observed at the crime scene.
- His motives often include creating chaos, drawing attention to his acts, and challenging his arch-nemesis, Batman, making a high-profile bank heist fitting within his behavioral patterns.

**Confidence Level:** 95%

**Next Steps:** No further evidence required.

The combination of visual, auditory, textual, and depth evidence strongly points to the Joker as the prime suspect. The thematic consistency across multiple modes of evidence, combined with known behavioral patterns and criminal signature, leaves little doubt regarding his involvement. While there is always a small margin of uncertainty in forensic analysis, the evidence at hand provides a compelling case against the Joker with a high degree of confidence.<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt05526b73530f46ed/6a17ef043e03d782434f2d30/132ee0880b7fb1e64b5b2d886ab76b58baa6de37-1024x768.jpg" alt="" /><h2>Fazit: Fall gelöst</h2><p>Nachdem alle <strong>Hinweise gesammelt und analysiert wurden</strong>, hat das <strong>multimodale RAG-System</strong> einen Verdächtigen identifiziert: <strong>den Joker</strong>.</p><p>Durch die Kombination <strong>von Bildern, Audio, Text und Tiefenkarten</strong> in einem <strong>gemeinsamen Vektorraum</strong> mithilfe von <strong>ImageBind</strong> konnte das System <strong>Verbindungen erkennen</strong> , die manuell nicht hätten identifiziert werden können. <strong>Elasticsearch</strong> sorgte für <strong>schnelle und effiziente Suchvorgänge</strong>, während <strong>LLM</strong> die Beweise in einem <strong>klaren und schlüssigen Bericht</strong> zusammenfasste.</p><p>Die <strong>wahre Macht</strong> dieses Systems <strong>geht jedoch über Gotham City hinaus</strong>. Die <strong>multimodale RAG-Architektur</strong> öffnet Türen zu <strong>zahlreichen realen Anwendungen</strong>:</p><ul><li><p><strong>Urbane Überwachung:</strong> Identifizierung von Verdächtigen anhand von <strong>Bild-, Audio- und Sensordaten</strong>.</p></li><li><p><strong>Forensische Analyse:</strong> Korrelieren <strong>von Beweisen aus mehreren Quellen</strong> zur Aufklärung <strong>komplexer Verbrechen</strong>.</p></li><li><p><strong>Multimedia-Empfehlung:</strong> Erstellen von <strong>Empfehlungssystemen</strong> , die <strong>multimodale Kontexte</strong> verstehen (z. B. <strong>Musikvorschläge</strong> basierend auf Bildern oder Text).</p></li><li><p><strong>Social-Media-Trends:</strong> Erkennen von <strong>Trendthemen</strong> in verschiedenen Datenformaten.</p></li></ul><p>Nachdem Sie nun gelernt haben, wie <strong>man ein multimodales RAG-System erstellt</strong>, warum <strong>testen Sie es nicht mit Ihren eigenen Hinweisen</strong>?</p><p><strong>Teilen Sie Ihre Entdeckungen</strong> mit uns und helfen Sie der <strong>Community</strong> , im Bereich der <strong>multimodalen KI</strong> voranzukommen!</p><h2>Besonderer Dank</h2><p>Ich möchte Adrian Cole für seinen wertvollen Beitrag und seine Überprüfung während des Prozesses der Definition der Bereitstellungsarchitektur dieses Codes danken.</p><h2>Referenzen</h2><ul><li><p><a href="https://www.elastic.co/de/search-labs/blog/multimodal-image-retrieval-with-roboflow">Erstellen Sie ein multimodales Bildabrufsystem mithilfe der KNN-Suche und CLIP-Einbettungen</a></p></li><li><p><a href="https://www.elastic.co/de/search-labs/tutorials/search-tutorial/vector-search/nearest-neighbor-search">k-Nearest-Neighbor (kNN)-Suche</a></p></li><li><p><a href="https://pytorch.org/docs/stable/tensors.html">Offizielle PyTorch-Dokumentation zu Tensoren</a></p></li><li><p><a href="https://imagebind.metademolab.com/">ImageBind: eine neue Möglichkeit, KI über alle Sinne hinweg zu „vernetzen“</a></p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/building-multimodal-rag-system</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/building-multimodal-rag-system</guid>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Alex Salgado]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt75ee2f922dacb7a8/6a17ef067b54f9775a8b39a3/47635eb4dadb8481854862668231eaa3a005ebee-1600x900.jpg" length="0" type="image/jpeg"/>
    <pubDate>Tue, 11 Mar 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Verwenden von Ollama mit der Inference-API]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie Ollama mithilfe der Inference API in Elasticsearch integrieren.]]></description>
    <content:encoded><![CDATA[<p>In diesem Artikel erfahren Sie, wie Sie lokale Modelle mithilfe von Ollama mit dem Elasticsearch-Inferenzmodell verbinden und Ihren Dokumenten dann mithilfe von Playground Fragen stellen.</p><p>Elasticsearch ermöglicht Benutzern die Verbindung mit LLMs über die Open <a href="https://www.elastic.co/de/guide/en/elasticsearch/reference/current/inference-apis.html">Inference API</a> und unterstützt Anbieter wie Amazon Bedrock, Cohere, Google AI, Azure AI Studio, HuggingFace – als Service und andere.</p><p><a href="https://ollama.com">Ollama</a> ist ein Tool, mit dem Sie LLM-Modelle mithilfe Ihrer eigenen Infrastruktur (Ihrem lokalen Computer/Server) herunterladen und ausführen können. <a href="https://ollama.com/library">Hier</a> finden Sie eine Liste der verfügbaren Modelle, die mit Ollama kompatibel sind.</p><p>Ollama ist eine großartige Option, wenn Sie verschiedene Open-Source-Modelle hosten und testen möchten, ohne sich Gedanken über die unterschiedlichen Einrichtungsmöglichkeiten der einzelnen Modelle oder über die Erstellung einer API für den Zugriff auf die Modellfunktionen machen zu müssen, da Ollama sich um alles kümmert.</p><p>Da die Ollama-API mit der OpenAI-API kompatibel ist, können wir das Inferenzmodell problemlos integrieren und mit Playground eine RAG-Anwendung erstellen.</p><h2>Voraussetzungen</h2><ol><li><p>Elasticsearch 8.17</p></li><li><p>Kibana 8.17</p></li><li><p>Python</p></li></ol><h2>Schritte</h2><ol><li><p><a href="https://www.elastic.co/de/search-labs/blog/ollama-with-inference-api#setting-up-ollama-llm-server">Einrichten des Ollama LLM-Servers</a></p></li><li><p><a href="https://www.elastic.co/de/search-labs/blog/ollama-with-inference-api#creating-mappings">Erstellen von Zuordnungen</a></p></li><li><p><a href="https://www.elastic.co/de/search-labs/blog/ollama-with-inference-api#indexing-data">Indizierung von Daten</a></p></li><li><p><a href="https://www.elastic.co/de/search-labs/blog/ollama-with-inference-api#asking-questions-using-playground">Fragen stellen mit Playground</a></p></li></ol><h2>Einrichten des Ollama LLM-Servers</h2><p>Wir werden einen LLM-Server einrichten, um ihn mithilfe von Ollama mit unserer Playground-Instanz zu verbinden. Wir müssen:</p><ul><li><p>Laden Sie Ollama herunter und führen Sie es aus.</p></li><li><p>Verwenden Sie ngrok, um über das Internet auf Ihren lokalen Webserver zuzugreifen, der Ollama hostet</p></li></ul><h3>Laden Sie Ollama herunter und führen Sie es aus</h3><p>Um Ollama zu verwenden, müssen wir <a href="https://ollama.com/download">es zuerst herunterladen</a>. Ollama bietet Unterstützung für Linux, Windows und macOS. Laden Sie <a href="https://ollama.com/download">hier einfach die mit Ihrem Betriebssystem kompatible Ollama-Version herunter.</a> Sobald Ollama installiert ist, können wir aus dieser <a href="https://ollama.com/library">Liste</a> unterstützter LLMs ein Modell auswählen. In diesem Beispiel verwenden wir das Modell <a href="https://ollama.com/library/llama3.2">llama3.2</a>, ein allgemeines mehrsprachiges Modell. Im Setup-Prozess aktivieren Sie das Befehlszeilentool für Ollama. Sobald das heruntergeladen ist, können Sie die folgende Zeile ausführen:</p>ollama pull llama3.2<p>Das Ergebnis lautet:</p>pulling manifest
pulling dde5aa3fc5ff... 100% ▕█████████████████████████████████████████████████████████████████████████████████████████▏ 2.0 GB
pulling 966de95ca8a6... 100% ▕█████████████████████████████████████████████████████████████████████████████████████████▏ 1.4 KB
pulling fcc5a6bec9da... 100% ▕█████████████████████████████████████████████████████████████████████████████████████████▏ 7.7 KB
pulling a70ff7e570d9... 100% ▕█████████████████████████████████████████████████████████████████████████████████████████▏ 6.0 KB
pulling 56bb8bd477a5... 100% ▕█████████████████████████████████████████████████████████████████████████████████████████▏   96 B
pulling 34bb5ab01051... 100% ▕█████████████████████████████████████████████████████████████████████████████████████████▏  561 B
verifying sha256 digest
writing manifest
success<p>Nach der Installation können Sie es mit diesem Befehl testen:</p>ollama run llama3.2<p>Stellen wir eine Frage:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc12f240920e897f5/6a17f39425daab32a508a367/ad1eff81c1b04d2a747c3afd0ecbc215e5bd96fd-800x501.gif" alt="Führen Sie Ollama aus und stellen Sie ihm eine Frage" /><p>Wenn das Modell ausgeführt wird, aktiviert Ollama eine API, die standardmäßig auf Port „11434“ ausgeführt wird. Lassen Sie uns eine Anfrage an diese API stellen und dabei der <a href="https://github.com/ollama/ollama/blob/main/docs/api.md">offiziellen Dokumentation</a> folgen:</p>curl http://localhost:11434/api/generate -d '{                                          
  "model": "llama3.2",               
  "prompt": "What is the capital of France?"
}' <p>Dies ist die Antwort, die wir erhalten haben:</p>{"model":"llama3.2","created_at":"2024-11-28T21:48:42.152817532Z","response":"The","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.251884485Z","response":" capital","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.347365913Z","response":" of","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.446837322Z","response":" France","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.542367394Z","response":" is","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.644580384Z","response":" Paris","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.739865362Z","response":".","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.834347518Z","response":"","done":true,"done_reason":"stop","context":[128006,9125,128007,271,38766,1303,33025,2696,25,6790,220,2366,18,271,128009,128006,882,128007,271,3923,374,279,6864,315,9822,30,128009,128006,78191,128007,271,791,6864,315,9822,374,12366,13],"total_duration":6948567145,"load_duration":4386106503,"prompt_eval_count":32,"prompt_eval_duration":1872000000,"eval_count":8,"eval_duration":684000000}<p><em>Beachten Sie, dass die spezifische Antwort für diesen Endpunkt ein Streaming ist.</em></p><h3>Endpunkt mit ngrok dem Internet aussetzen</h3><p>Da unser Endpunkt in einer lokalen Umgebung arbeitet, kann von einem anderen Punkt – wie unserer Elastic Cloud-Instanz – nicht über das Internet darauf zugegriffen werden. <a href="https://ngrok.com">ngrok</a> ermöglicht es uns, einen Port mit einer öffentlichen IP freizugeben. Erstellen Sie ein Konto in ngrok und folgen Sie der offiziellen <a href="https://dashboard.ngrok.com/get-started/setup">Einrichtungsanleitung</a>.</p><p>Sobald der ngrok-Agent installiert und konfiguriert wurde, können wir den von Ollama verwendeten Port verfügbar machen:</p>ngrok http 11434 --host-header="localhost:11434"<p><em>Hinweis: Der Header </em><em><code>--host-header="localhost:11434"</code></em><em> garantiert, dass der Header „Host“ in den Anfragen mit „localhost:11434“ übereinstimmt.</em></p><p>Durch Ausführen dieses Befehls wird ein öffentlicher Link zurückgegeben, der funktioniert, solange ngrok und der Ollama-Server lokal ausgeführt werden.</p>Session Status                online                                                                                                                                                                              
Account                       xxxx@yourEmailProvider.com (Plan: Free)                                                                                                                                             
Version                       3.18.4                                                                                                                                                                              
Region                        United States (us)                                                                                                                                                                  
Latency                       561ms                                                                                                                                                                               
Web Interface                 http://127.0.0.1:4040                                                                                                                                                               
Forwarding                    https://your-ngrok-url.ngrok-free.app -&gt; http://localhost:11434                                                                                                                   


Connections                   ttl     opn     rt1     rt5     p50     p90                                                                                                                                         
                              0       0       0.00    0.00    0.00    0.00                                                ```<p>Unter „Weiterleitung“ können wir sehen, dass ngrok eine URL generiert hat. Speichern Sie es für später.</p><p>Versuchen wir erneut, eine HTTP-Anfrage an den Endpunkt zu senden, diesmal unter Verwendung der von ngrok generierten URL:</p>curl https://your-ngrok-endpoint.ngrok-free.app/api/generate -d '{                                          
  "model": "llama3.2",               
  "prompt": "What is the capital of France?"
}'<p>Die Antwort sollte der vorherigen ähnlich sein.</p><h2>Erstellen von Zuordnungen</h2><h3>ELSER-Endpunkt</h3><p>Für dieses Beispiel <a href="https://www.elastic.co/de/guide/en/elasticsearch/reference/current/put-inference-api.html">erstellen wir einen Inferenzendpunkt mithilfe der Elasticsearch-Inferenz-API</a>. Zusätzlich verwenden wir <a href="https://www.elastic.co/de/guide/en/machine-learning/current/ml-nlp-elser.html">ELSER</a> , um die Einbettungen zu generieren.</p>PUT _inference/sparse_embedding/medicines-inference
{
  "service": "elasticsearch",
  "service_settings": {
    "num_allocations": 1,
    "num_threads": 1,
    "model_id": ".elser_model_2_linux-x86_64"
  }
}<p>Stellen wir uns für dieses Beispiel vor, Sie haben eine Apotheke, die zwei Arten von Medikamenten verkauft:</p><ul><li><p>Medikamente, für die ein Rezept erforderlich ist.</p></li><li><p>Medikamente, für die KEIN Rezept erforderlich ist.</p></li></ul><p>Diese Informationen würden in das Beschreibungsfeld jedes Medikaments aufgenommen.</p><p>Das LLM muss dieses Feld interpretieren, daher verwenden wir folgende Datenzuordnungen:</p>PUT medicines
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "copy_to": "semantic_field"
      },
      "semantic_field": {
        "type": "semantic_text",
        "inference_id": "medicines-inference"
      },
      "text_description": {
        "type": "text",
        "copy_to": "semantic_field"
      }
    }
  }
}<p>Das Feld <code>text_description</code> speichert den Klartext der Beschreibungen, während <code>semantic_field</code>, ein Feldtyp vom Typ <a href="https://www.elastic.co/de/guide/en/elasticsearch/reference/current/semantic-text.html">„semantic_text“</a> , die von ELSER generierten Einbettungen speichert.</p><p>Die Eigenschaft <a href="https://www.elastic.co/de/guide/en/elasticsearch/reference/current/copy-to.html">copy_to</a> kopiert den Inhalt aus den Feldern name und <code>text_description</code> in das semantische Feld, sodass die Einbettungen für diese Felder generiert werden.</p><h2>Indizierung von Daten</h2><p>Lassen Sie uns nun die Daten mithilfe der <a href="https://www.elastic.co/de/guide/en/elasticsearch/reference/current/docs-bulk.html">_bulk-API</a> indizieren.</p>POST _bulk
{"index":{"_index":"medicines"}}
{"id":1,"name":"Paracetamol","text_description":"An analgesic and antipyretic that does NOT require a prescription."}
{"index":{"_index":"medicines"}}
{"id":2,"name":"Ibuprofen","text_description":"A nonsteroidal anti-inflammatory drug (NSAID) available WITHOUT a prescription."}
{"index":{"_index":"medicines"}}
{"id":3,"name":"Amoxicillin","text_description":"An antibiotic that requires a prescription."}
{"index":{"_index":"medicines"}}
{"id":4,"name":"Lorazepam","text_description":"An anxiolytic medication that strictly requires a prescription."}
{"index":{"_index":"medicines"}}
{"id":5,"name":"Omeprazole","text_description":"A medication for stomach acidity that does NOT require a prescription."}
{"index":{"_index":"medicines"}}
{"id":6,"name":"Insulin","text_description":"A hormone used in diabetes treatment that requires a prescription."}
{"index":{"_index":"medicines"}}
{"id":7,"name":"Cold Medicine","text_description":"A compound formula to relieve flu symptoms available WITHOUT a prescription."}
{"index":{"_index":"medicines"}}
{"id":8,"name":"Clonazepam","text_description":"An antiepileptic medication that requires a prescription."}
{"index":{"_index":"medicines"}}
{"id":9,"name":"Vitamin C","text_description":"A dietary supplement that does NOT require a prescription."}
{"index":{"_index":"medicines"}}
{"id":10,"name":"Metformin","text_description":"A medication used for type 2 diabetes that requires a prescription."}<p>Abwehr:</p>{
   "errors": false,
   "took": 34732020848,
   "items": [
 	{
   	"index": {
     	"_index": "medicines",
     	"_id": "mYoeMpQBF7lnCNFTfdn2",
     	"_version": 1,
     	"result": "created",
     	"_shards": {
       	"total": 2,
       	"successful": 2,
       	"failed": 0
     	},
     	"_seq_no": 0,
     	"_primary_term": 1,
     	"status": 201
   	}
 	},
 	{
   	"index": {
     	"_index": "medicines",
     	"_id": "mooeMpQBF7lnCNFTfdn2",
     	"_version": 1,
     	"result": "created",
     	"_shards": {
       	"total": 2,
       	"successful": 2,
       	"failed": 0
     	},
     	"_seq_no": 1,
     	"_primary_term": 1,
     	"status": 201
   	}
 	},
 	{
   	"index": {
     	"_index": "medicines",
     	"_id": "m4oeMpQBF7lnCNFTfdn2",
     	"_version": 1,
     	"result": "created",
     	"_shards": {
       	"total": 2,
       	"successful": 2,
       	"failed": 0
     	},
     	"_seq_no": 2,
     	"_primary_term": 1,
     	"status": 201
   	}
 	},
 	{
   	"index": {
     	"_index": "medicines",
     	"_id": "nIoeMpQBF7lnCNFTfdn2",
     	"_version": 1,
     	"result": "created",
     	"_shards": {
       	"total": 2,
       	"successful": 2,
       	"failed": 0
     	},
     	"_seq_no": 3,
     	"_primary_term": 1,
     	"status": 201
   	}
 	},
 	{
   	"index": {
     	"_index": "medicines",
     	"_id": "nYoeMpQBF7lnCNFTfdn2",
     	"_version": 1,
     	"result": "created",
     	"_shards": {
       	"total": 2,
       	"successful": 2,
       	"failed": 0
     	},
     	"_seq_no": 4,
     	"_primary_term": 1,
     	"status": 201
   	}
 	},
 	{
   	"index": {
     	"_index": "medicines",
     	"_id": "nooeMpQBF7lnCNFTfdn2",
     	"_version": 1,
     	"result": "created",
     	"_shards": {
       	"total": 2,
       	"successful": 2,
       	"failed": 0
     	},
     	"_seq_no": 5,
     	"_primary_term": 1,
     	"status": 201
   	}
 	},
 	{
   	"index": {
     	"_index": "medicines",
     	"_id": "n4oeMpQBF7lnCNFTfdn2",
     	"_version": 1,
     	"result": "created",
     	"_shards": {
       	"total": 2,
       	"successful": 2,
       	"failed": 0
     	},
     	"_seq_no": 6,
     	"_primary_term": 1,
     	"status": 201
   	}
 	},
 	{
   	"index": {
     	"_index": "medicines",
     	"_id": "oIoeMpQBF7lnCNFTfdn2",
     	"_version": 1,
     	"result": "created",
     	"_shards": {
       	"total": 2,
       	"successful": 2,
       	"failed": 0
     	},
     	"_seq_no": 7,
     	"_primary_term": 1,
     	"status": 201
   	}
 	},
 	{
   	"index": {
     	"_index": "medicines",
     	"_id": "oYoeMpQBF7lnCNFTfdn2",
     	"_version": 1,
     	"result": "created",
     	"_shards": {
       	"total": 2,
       	"successful": 2,
       	"failed": 0
     	},
     	"_seq_no": 8,
     	"_primary_term": 1,
     	"status": 201
   	}
 	},
 	{
   	"index": {
     	"_index": "medicines",
     	"_id": "oooeMpQBF7lnCNFTfdn2",
     	"_version": 1,
     	"result": "created",
     	"_shards": {
       	"total": 2,
       	"successful": 2,
       	"failed": 0
     	},
     	"_seq_no": 9,
     	"_primary_term": 1,
     	"status": 201
   	}
 	}
   ]
 }<h2>Fragen stellen mit Playground</h2><p><a href="https://www.elastic.co/de/guide/en/kibana/current/playground.html">Playground</a> ist ein Kibana-Tool, mit dem Sie mithilfe von Elasticsearch-Indizes und einem LLM-Anbieter schnell ein RAG-System erstellen können. Sie können diesen <a href="https://www.elastic.co/de/search-labs/blog/playground-connectors-data-chat">Artikel</a> lesen, um mehr darüber zu erfahren.</p><h3>Verbinden des lokalen LLM mit Playground</h3><p>Wir müssen zunächst einen Connector erstellen, der die soeben erstellte öffentliche URL verwendet. Gehen Sie in Kibana zu <strong>„Suchen &gt; Playground“</strong> und klicken Sie dann auf „Mit einem LLM verbinden“.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt22148eabfabf6d3f/6a17f3963e9e459f97ba15c6/1854f0808f8150e359fe62ba5d901d32a88d477c-1600x867.png" alt="Verbinden des lokalen LLM mit Playground für Ollama" /><p>Durch diese Aktion wird auf der linken Seite der Kibana-Oberfläche ein Menü angezeigt. Klicken Sie dort auf „OpenAI“.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6e28194d9012f141/6a17f39725daab500a08a36b/c83d3c4d7035a518124ad7d22b38764db57b6800-933x1007.png" alt="Wählen Sie einen Connector aus: Öffnen Sie AI Ollama" /><p>Wir können jetzt mit der Konfiguration des OpenAI-Connectors beginnen.</p><p>Gehen Sie zu „Connector-Einstellungen“ und wählen Sie für den OpenAI-Anbieter „Andere (OpenAI-kompatible Dienste)“ aus:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9984dce6f78a7c08/6a17f3990b0bed0b7add36c4/ecfcdc4b575c309bd55b4e61ca0ddb348aa84f64-917x268.png" alt="Legen Sie die Connector-Einstellungen für die Verwendung von Ollama mit der Inference-API fest" /><p>Nun konfigurieren wir die übrigen Felder. In diesem Beispiel nennen wir unser Modell "medicines-llm". Verwenden Sie im URL-Feld die von ngrok generierte URL (/v1/chat/completions). Wählen Sie im Feld „Standardmodell“ die Option „llama3.2“ aus. Wir benötigen keinen API-Schlüssel, geben Sie einfach einen beliebigen Text ein, um fortzufahren:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8a24b93a39d380fb/6a17f39b96142a15c7eb1c3c/5d3b5027c8096cbe49fb740d70aa24e849611a9d-916x688.png" alt="Einstellungen hinzufügen" /><p>Klicken Sie auf „Speichern“ und fügen Sie die Indexmedikamente hinzu, indem Sie auf „Datenquellen hinzufügen“ klicken:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4f107a54d5be25f9/6a17f39d4b055deb9d432338/525113da59e902c8235f62bde8fb62371a63e11b-1579x753.png" alt="Fügen Sie Datenquellen hinzu, um Ihren Dokumenten mithilfe von Playground Fragen zu stellen" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt03fb36fe05dcdbf5/6a17f39ebe608602f40048be/96138de0bbe2c2ac619f64889d3487df62739ca4-466x805.png" alt="Abfragedaten hinzufügen" /><p>Großartig! Wir haben jetzt Zugriff auf Playground mithilfe des LLM, das wir lokal als RAG-Engine ausführen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb1b27580107259b3/6a17f3a096142abefceb1c40/cfb48b33c70f4534ab77eb01f58008237f65e6f4-1600x851.png" alt="Modelleinstellungen im Playground auswählen" /><p>Bevor wir es testen, fügen wir dem Agenten spezifischere Anweisungen hinzu und erhöhen die Anzahl der an das Modell gesendeten Dokumente auf 10, damit die Antwort möglichst viele Dokumente enthält. Das Kontextfeld ist <code>semantic_field</code> und enthält dank der Eigenschaft „copy_to“ den Namen und die Beschreibung der Medikamente.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4fbc97dc87c6fc62/6a17f3a1e8fbce052c3a1aa0/0c57c9c0e1a0e7b58fffdd3ef81d67d41e2990c4-580x806.png" alt="Modelleinstellungen im Elastic Playground" /><p>Stellen wir nun die Frage: <em><strong>Kann ich Clonazepam ohne Rezept kaufen?</strong></em> und sehen Sie, was passiert:</p><p>Wie erwartet haben wir die richtige Antwort erhalten.</p><h3>Wie geht es weiter?</h3><p>Der nächste Schritt besteht darin, Ihre eigene Anwendung zu erstellen! Playground bietet ein Code-Skript in Python, das Sie auf Ihrem Computer ausführen und an Ihre Anforderungen anpassen können. Beispielsweise indem Sie es hinter einen <a href="https://fastapi.tiangolo.com/">FastAPI</a> -Server stellen, um einen QA-Medizin-Chatbot zu erstellen, der von Ihrer Benutzeroberfläche genutzt wird.</p><p>Sie finden diesen Code, indem Sie oben rechts im Playground auf die Schaltfläche <em><strong>„Code anzeigen“</strong></em> klicken:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt42fe193b8aa08830/6a17f3a33e9e4569e8ba15ca/816bfd0e5f936ad65dbe719d5df10714e550a40b-380x121.png" alt="Schaltfläche „Code anzeigen“" /><p>Und Sie verwenden die <em><strong>Endpunkte und API-Schlüssel,</strong></em> um die im Code erforderliche Umgebungsvariable <code>ES_API_KEY</code> zu generieren.</p><p>Für dieses spezielle Beispiel lautet der Code wie folgt:</p>## Install the required packages
## pip install -qU elasticsearch openai
import os
from elasticsearch import Elasticsearch
from openai import OpenAI
es_client = Elasticsearch(
    "https://your-deployment.us-central1.gcp.cloud.es.io:443",
    api_key=os.environ["ES_API_KEY"]
)
openai_client = OpenAI(
    api_key=os.environ["OPENAI_API_KEY"],
)
index_source_fields = {
    "medicines": [
        "semantic_field"
    ]
}
def get_elasticsearch_results():
    es_query = {
        "retriever": {
            "standard": {
                "query": {
                    "nested": {
                        "path": "semantic_field.inference.chunks",
                        "query": {
                            "sparse_vector": {
                                "inference_id": "medicines-inference",
                                "field": "semantic_field.inference.chunks.embeddings",
                                "query": query
                            }
                        },
                        "inner_hits": {
                            "size": 2,
                            "name": "medicines.semantic_field",
                            "_source": [
                                "semantic_field.inference.chunks.text"
                            ]
                        }
                    }
                }
            }
        },
        "size": 3
    }
    result = es_client.search(index="medicines", body=es_query)
    return result["hits"]["hits"]
def create_openai_prompt(results):
    context = ""
    for hit in results:
        inner_hit_path = f"{hit['_index']}.{index_source_fields.get(hit['_index'])[0]}"
        ## For semantic_text matches, we need to extract the text from the inner_hits
        if 'inner_hits' in hit and inner_hit_path in hit['inner_hits']:
            context += '\n --- \n'.join(inner_hit['_source']['text'] for inner_hit in hit['inner_hits'][inner_hit_path]['hits']['hits'])
        else:
            source_field = index_source_fields.get(hit["_index"])[0]
            hit_context = hit["_source"][source_field]
            context += f"{hit_context}\n"
    prompt = f"""
  Instructions:
  - You are an assistant specializing in answering questions about the sale of medicines.
  - Answer questions truthfully and factually using only the context presented.
  - If you don't know the answer, just say that you don't know, don't make up an answer.
  - You must always cite the document where the answer was extracted using inline academic citation style [], using the position.
  - Use markdown format for code examples.
  - You are correct, factual, precise, and reliable.
  Context:
  {context}
  """
    return prompt
def generate_openai_completion(user_prompt, question):
    response = openai_client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": user_prompt},
            {"role": "user", "content": question},
        ]
    )
    return response.choices[0].message.content
if __name__ == "__main__":
    question = "my question"
    elasticsearch_results = get_elasticsearch_results()
    context_prompt = create_openai_prompt(elasticsearch_results)
    openai_completion = generate_openai_completion(context_prompt, question)
    print(openai_completion)<p>Damit es mit Ollama funktioniert, müssen Sie den OpenAI-Client so ändern, dass er eine Verbindung zum Ollama-Server statt zum OpenAI-Server herstellt. Die vollständige Liste der OpenAI-Beispiele und kompatiblen Endpunkte finden Sie hier.</p>openai_client = OpenAI(
    # you can use http://localhost:11434/v1/ if running this code locally.
    base_url='https://your-ngrok-url.ngrok-free.app/v1/',
    # required but ignored
    api_key='ollama',
)<p>Und ändern Sie das Modell auch in llama3.2, wenn Sie die Vervollständigungsmethode aufrufen:</p>def generate_openai_completion(user_prompt, question):
    response = openai_client.chat.completions.create(
        model="llama3.2",
        messages=[
            {"role": "system", "content": user_prompt},
            {"role": "user", "content": question},
        ]
    )
    return response.choices[0].message.content<p>Fügen wir unsere Frage hinzu: <em><strong>Kann ich Clonazepam ohne Rezept kaufen? </strong></em>Zur Elasticsearch-Abfrage:</p>def get_elasticsearch_results():
    es_query = {
        "retriever": {
            "standard": {
                "query": {
                    "nested": {
                        "path": "semantic_field.inference.chunks",
                        "query": {
                            "sparse_vector": {
                                "inference_id": "medicines-inference",
                                "field": "semantic_field.inference.chunks.embeddings",
                                "query": "Can I buy Clonazepam without a prescription?"
                            }
                        },
                        "inner_hits": {
                            "size": 2,
                            "name": "medicines.semantic_field",
                            "_source": [
                                "semantic_field.inference.chunks.text"
                            ]
                        }
                    }
                }
            }
        },
        "size": 3
    }
    result = es_client.search(index="medicines", body=es_query)
    return result["hits"]["hits"]<p>Und auch zum Abschlussaufruf mit einigen Ausdrucken, damit wir bestätigen können, dass wir die Elasticsearch-Ergebnisse als Teil des Fragenkontexts senden:</p>if __name__ == "__main__":
    question = "Can I buy Clonazepam without a prescription?"
    elasticsearch_results = get_elasticsearch_results()
    context_prompt = create_openai_prompt(elasticsearch_results)
    print("========== Context Prompt START ==========")
    print(context_prompt)
    print("========== Context Prompt END ==========")
    print("========== Ollama Completion START ==========")
    openai_completion = generate_openai_completion(context_prompt, question)
    print(openai_completion)
    print("========== Ollama Completion END ==========")<p>Lassen Sie uns nun den Befehl ausführen</p><p><code>pip install -qU elasticsearch openai</code></p><p><code>python main.py</code></p><p>Sie sollten ungefähr Folgendes sehen:</p>========== Context Prompt START ==========
  Instructions:
  - You are an assistant specializing in answering questions about the sale of medicines.
  - Answer questions truthfully and factually using only the context presented.
  - If you don't know the answer, just say that you don't know, don't make up an answer.
  - You must always cite the document where the answer was extracted using inline academic citation style [], using the position.
  - Use markdown format for code examples.
  - You are correct, factual, precise, and reliable.
  Context:
  Clonazepam
 ---
An antiepileptic medication that requires a prescription.A nonsteroidal anti-inflammatory drug (NSAID) available WITHOUT a prescription.
 ---
IbuprofenAn anxiolytic medication that strictly requires a prescription.
 ---
Lorazepam


========== Context Prompt END ==========
========== Ollama Completion START ==========
No, you cannot buy Clonazepam over-the-counter (OTC) without a prescription [1]. It is classified as a controlled substance in the United States due to its potential for dependence and abuse. Therefore, it can only be obtained from a licensed healthcare provider who will issue a prescription for this medication.
========== Ollama Completion END ==========<h2>Fazit</h2><p>In diesem Artikel können wir die Leistungsfähigkeit und Vielseitigkeit von Tools wie Ollama sehen, wenn wir sie zusammen mit der Elasticsearch-Inferenz-API und Playground verwenden.</p><p>Nach einigen einfachen Schritten hatten wir eine funktionierende RAG-Anwendung mit einem Chat, der ein LLM verwendete, das kostenlos in unserer eigenen Infrastruktur lief. Dies ermöglicht uns außerdem eine bessere Kontrolle über Ressourcen und vertrauliche Informationen und gibt uns außerdem Zugriff auf eine Vielzahl von Modellen für unterschiedliche Aufgaben.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ollama-with-inference-api</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ollama-with-inference-api</guid>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Jeffrey Rengifo]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd9c8eb0fc946920e/6a17f3a46864a4b2fbb688f0/399b9ef527be633845fb6505b68132cc03bc9e09-1150x628.png" length="0" type="image/png"/>
    <pubDate>Fri, 14 Feb 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Lokales Testen von DeepSeek R1 für RAG mit Ollama und Kibana]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie eine lokale Instanz von DeepSeek ausführen und sich von Kibana aus damit verbinden.]]></description>
    <content:encoded><![CDATA[<p>Alle reden über DeepSeek R1, das neue große Sprachmodell des chinesischen Hedgefonds High-Flyer. Die Nachrichten sind voll von Spekulationen darüber, was es für die Branche bedeutet, dass sie nun ein fähiges, mit offenen Gewichtungen arbeitendes LLM mit Kettenlogik eingeführt haben. Für alle, die neugierig sind und dieses neue Modell mit RAG und den intelligenten Funktionen der Vektordatenbank von Elasticsearch ausprobieren möchten, gibt es hier ein kurzes Tutorial, das Ihnen den Einstieg in die Verwendung von DeepSeek R1 mit lokaler Inferenz erleichtert. Dabei verwenden wir die Playground-Funktion von Elastic und entdecken sogar einige gute und schlechte Eigenschaften von DeepSeek R1 für RAG.</p><p>Hier ist ein Diagramm, das zeigt, was wir in diesem Tutorial konfigurieren werden:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3214cc505e3d4d06/6a17df98dbb4ff12bafb55da/8aafec9011e986cd85b10958544a4d77be81e518-739x419.png" alt="DeepSeek-Konfiguration mit Elasticsearch und Ollama" /><h2>Einrichten der lokalen Inferenz mit Ollama</h2><p><a href="https://ollama.com/">Ollama</a> ist eine hervorragende Möglichkeit, schnell eine kuratierte Auswahl an Open-Source-Modellen für lokale Inferenztests auszuprobieren, und ein beliebtes Werkzeug für KI-Entwickler.</p><h3>Ausführen von Ollama bare metal</h3><p>Eine <a href="https://github.com/ollama/ollama/tree/main?tab=readme-ov-file#ollama">lokale Installation</a> auf Mac, Linux oder Windows ist der einfachste Weg, um lokale GPU-Funktionen zu nutzen, insbesondere für Nutzer mit Apple-Chips der M-Serie. Sobald Sie Ollama installiert haben, können Sie DeepSeek R1 mit dem folgenden Befehl herunterladen und ausführen.</p><p>Vielleicht möchten Sie die Parametergröße an Ihre Hardware anpassen. Verfügbare Größen finden Sie <a href="https://ollama.com/library/deepseek-r1">hier</a>.</p>ollama run deepseek-r1:7b<p>Sie können im Terminal mit dem Modell chatten, aber das Modell läuft auch dann weiter, wenn Sie den Befehl mit Strg+d verlassen oder „/bye“ eingeben. Um zu sehen, ob das Modell noch läuft, geben Sie Folgendes ein:</p>ollama ps<h3>Ollama in einem Container ausführen</h3><p>Der schnellste alternative Weg zum Ausführen von Ollama ist die Nutzung einer Container-Engine wie Docker. Die Nutzung der GPU Ihres lokalen Rechners ist je nach Umgebung nicht immer einfach, aber eine schnelle Testeinrichtung ist nicht schwer, solange Ihr Container über genügend RAM und Speicherplatz für die Multi-GB-Modelle verfügt.</p><p>Das Einrichten und Ausführen von Ollama in Docker ist so einfach wie der Befehl:</p>mkdir ollama_deepseek
cd ollama_deepseek
mkdir ollama
docker run -d -v ./ollama:/root/.ollama -p 11434:11434 \
--name ollama ollama/ollama
<p>Dies erstellt ein Verzeichnis namens „Ollama“ im aktuellen Verzeichnis und verankert es im Container, um die Ollama-Konfiguration sowie die Modelle zu speichern. Je nach Anzahl der verwendeten Parameter können diese eine Größe von einigen GB bis zu Dutzenden von GB haben, daher sollten Sie ein Laufwerk mit ausreichend freiem Speicherplatz wählen.</p><p>Hinweis: Wenn Sie eine Nvidia-GPU in Ihrem Computer haben, installieren Sie unbedingt das <a href="https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html#installation">Nvidia Container-Toolkit</a> und fügen Sie dem obigen Befehl zum Ausführen von Docker „--gpus=all“ hinzu.</p><p>Sobald der Ollama-Container auf Ihrem Rechner läuft, können Sie ein Modell wie DeepSeek R1 mit folgendem Befehl abrufen:</p>docker exec -it ollama ollama pull deepseek-r1:7b<p>Ähnlich wie beim Bare-Metal-Ansatz möchten Sie möglicherweise die Parametergröße ändern, um sie an Ihre Hardware anzupassen. Verfügbare Größen finden Sie unter <a href="https://ollama.com/library/deepseek-r1">https://ollama.com/library/deepseek-r1</a>.</p><p>Sobald das Herunterladen des Modells abgeschlossen ist, können Sie „/bye“ eingeben, um die Eingabeaufforderung zu beenden. So überprüfen Sie, ob das Modell noch ausgeführt wird:</p>docker exec -it ollama ollama ps<h2>Testen unserer lokalen Inferenz mit einem Curl</h2><p>Um die lokale Inferenz mit cURL zu testen, können Sie den folgenden Befehl ausführen. Wir verwenden stream:false, damit wir die narrative JSON-Reaktion leicht lesen können:</p>curl http://localhost:11434/api/generate -d '{
  "model": "deepseek-r1:7b",
  "stream": false,
  "prompt":"Why is Elastic so cool?"
}'<h2>Testen von „OpenAI-kompatiblem“ Ollama und einer RAG-Eingabeaufforderung</h2><p>Praktischerweise bietet Ollama auch einen REST-Endpoint, der das Verhalten von OpenAI nachahmt, um die Kompatibilität mit einer Vielzahl von Tools, einschließlich Kibana, zu gewährleisten.</p>curl http://localhost:11434/v1/chat/completions -d '{
  "model": "deepseek-r1:7b",
  "stream": false,
  "messages": [
    { 
      "role": "system", 
      "content": "You are a helpful AI Assistant that uses the following context to answer questions only use the following context. \n\nContext:  The color of the sky today is purple. "},
    { "role": "user", 
      "content": "What does the sky look like today?" 
    }
  ]
}'<p>Das Testen dieser komplexeren Eingabeaufforderung führt zu Inhalten, die einen &lt;think&gt;-Abschnitt enthalten, in dem das Modell darauf trainiert wurde, das Problem zu durchdenken.</p>&lt;think&gt; 
Okay, so I need to figure out what the user is asking for here. They provided a context where the sky is described as purple today and then asked about how the sky looks. At first glance, it seems straightforward—maybe they just want confirmation or more details on why the sky is that color.
Wait, but maybe there's something deeper. Purple skies aren't something I encounter every day. It usually happens at certain times of the year, like during sunrise or sunset with the sun setting in pink or orange. Could this be a hint about the time of day? Or perhaps it's just an unusual natural phenomenon? 
I should consider if \"purple\" is a typo. Maybe they meant something else like blue or gray. But since they specifically said purple, I'll go with that. Purple skies can happen when there are atmospheric conditions that scatter light differently, maybe due to pollution or cloud cover affecting the sunset.

So, putting it all together, the user might be looking for an explanation of why today's sky is purple and what that implies about the weather or time of day. Alternatively, they could just want a simple statement confirming that the sky looks purple today.
&lt;/think&gt;

The color of the sky today is described as purple. This unusual shade can occur due to atmospheric conditions affecting light scattering, such as during sunrise/sunset with pollution or cloud cover influencing the sunset's hues.<h2>Ollama mit Kibana verbinden</h2><p>Eine großartige Möglichkeit, Elasticsearch zu nutzen, ist das „<a href="https://github.com/elastic/start-local?tab=readme-ov-file#-try-elasticsearch-and-kibana-locally">start-local</a>“-Entwicklungsskript.</p><p>Stellen Sie sicher, dass Kibana und Elasticsearch Ihr Ollama im Netzwerk erreichen können. Wenn Sie ein lokales Container-Setup des Elastic Stack verwenden, bedeutet dies möglicherweise, dass Sie „localhost“ durch „host.docker.internal“ oder „host.containers.internal“ ersetzen müssen, um einen Netzwerkpfad zum gehosteten Computer zu erhalten.</p><p>Navigieren Sie in Kibana zu Stack Management &gt; Alerts and Insights &gt; Connectors.</p><h3>Was tun, wenn Sie diese allgemeine Setup-Warnung sehen?</h3><p>Sie müssen sicherstellen, dass der xpack.encryptedSavedObjects.encryptionKey <a href="https://www.elastic.co/guide/en/kibana/current/xpack-security-secure-saved-objects.html">korrekt eingestellt ist</a>. Dies ist ein häufig übersehener Schritt bei der lokalen Docker-Installation von Kibana, daher liste ich die Schritte zur Behebung in der Docker-Syntax auf.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta4f7b7be2e04afae/6a17df9a1d1b8391e293e393/b70b4b810bcac1d1599b07da90a98c5c744a38de-497x223.png" alt="" /><p>Stellen Sie sicher, dass Sie Ihr Kibana/Konfig-Verzeichnis dauerhaft speichern, damit Änderungen erhalten bleiben, wenn der Container heruntergefahren wird. Meine Kibana-Container-Laufwerke sehen in der docker-compose.yml folgendermaßen aus:</p>services:
  kibana:
...
   volumes:
      - certs:/usr/share/kibana/config/certs
      - kibanadata:/usr/share/kibana/data
      - kibanaconfig:/usr/share/kibana/config
...
volumes:
  certs:
    driver: local
  esdata01:
    driver: local
  kibanadata:
    driver: local
  kibanaconfig:
    driver: local<p>Jetzt können Sie den Keystore erstellen und einen Wert eingeben, damit die Verbindungsschlüssel nicht im Klartext gespeichert werden.</p>## generate some new keys for me and print them to the terminal
docker exec -it kibana_1 bin/kibana-encryption-keys generate

## create a new keystrore
docker exec -it kibana_1 bin/kibana-keystore create
docker exec -it kibana_1 bin/kibana-keystore add xpack.encryptedSavedObjects.encryptionKey

## You'll be prompted to paste in a value<p>Starten Sie Ihren gesamten Cluster vollständig neu, um sicherzustellen, dass die Änderungen wirksam werden.</p><h3>Erstellen des Connectors</h3><p>Erstellen Sie auf dem Connector-Konfigurationsbildschirm (navigieren Sie in Kibana zu Stack Management &gt; Alerts and Insights &gt; Connectors) einen Connector und wählen Sie den Typ „OpenAI“ aus.</p><p>Konfigurieren Sie den Connector mit den folgenden Einstellungen:</p><ul><li><p>Name des Connectors: Deepseek (Ollama)</p></li><li><p>Wählen Sie einen OpenAI-Anbieter aus: andere (OpenAI-kompatibler Dienst)</p></li><li><p>URL: <a href="http://localhost:11434/v1/chat/completions">http://localhost:11434/v1/chat/completions</a></p><ul><li><p>Passen Sie den richtigen Pfad zu Ihrem Ollama an. Denken Sie daran, host.docker.internal oder ein Äquivalent zu ersetzen, wenn Sie aus einem Container heraus aufrufen.</p></li></ul></li><li><p>Standardmodell: deepseek-r1:7b</p></li><li><p>API-Schlüssel: Denken Sie sich etwas aus, ein Eintrag ist erforderlich, aber der Wert spielt keine Rolle</p></li></ul><p>Beachten Sie, dass das Testen eines benutzerdefinierten Connectors zu Ollama im Connector-Setup derzeit in 8.17 nicht funktioniert, aber in der nachfolgenden Kibana-Version 8.18 behoben wurde.</p><p>Unser Connector sieht so aus:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt774e0793eb110f9d/6a17df9c445de981014d004d/4ce214aa953b4090ed112fbde40b01c01fb8f5c7-786x836.png" alt="" /><h2>Vektoreingebettete Daten in Elasticsearch einlesen</h2><p>Wenn Sie bereits mit Playground vertraut sind und Daten eingerichtet haben, können Sie zum nächsten Playground-Schritt übergehen. Wenn Sie jedoch einige schnelle Testdaten benötigen, müssen wir sicherstellen, dass unsere _inference-APIs eingerichtet sind. Ab Version 8.17 sind die Zuweisungen für Machine Learning dynamisch, sodass wir zum Herunterladen und Aktivieren des mehrsprachigen e5-Vektors nur Folgendes in den Kibana Dev-Tools ausführen müssen.</p>GET /_inference


POST /_inference/text_embedding/.multilingual-e5-small-elasticsearch
{
   "input": "are internet memes about deepseek sound investment advice?"
}<p>Wenn Sie dies noch nicht getan haben, wird das Herunterladen des e5-Modells aus den Modell-Repositorys von Elastic ausgelöst.</p><p>Als Nächstes laden wir ein gemeinfreies Buch als unseren RAG-Kontext hoch. Hier können Sie „Alice im Wunderland“ von Project Gutenberg herunterladen: <a href="https://www.gutenberg.org/cache/epub/11/pg11.txt">Link</a>. Speichern Sie es als .txt-Datei.</p><p>Navigieren Sie zu Elasticsearch &gt; Home &gt; Datei hochladen</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt45c594487844ecb4/6a17df9dfaa9137edb93c786/649042271f34a5e66789b17c39bfe95971c7f4ce-1360x629.png" alt="" /><p>Wählen Sie Ihre Textdatei aus oder ziehen Sie sie per Drag &amp; Drop und klicken Sie dann auf die Schaltfläche „Importieren“.</p><p>Wählen Sie auf dem Bildschirm „Daten importieren“ die Registerkarte „Erweitert“ und setzen Sie den Indexnamen auf „book_alice“.</p><p>Wählen Sie die Option „Zusätzliches Feld hinzufügen“, sie befindet sich klein direkt unter „Automatisch erstellte Felder“. Wählen Sie „Semantisches Textfeld hinzufügen“ und ändern Sie den Inferenz-Endpoint in „.multilingual-e5-small-elasticsearch“. Wählen Sie „Hinzufügen“ und dann „Importieren“.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9d9c22ccdaee8590/6a17df9f3e03d731f94f2b8e/e58d5c9a2d406d8e62eb96cab9ac98ca89414346-507x602.png" alt="" /><p></p><p>Wenn das Laden und die Inferenz abgeschlossen sind, können wir zu Playground gehen.</p><h2>RAG im Playground testen</h2><p>Navigieren Sie in Kibana zu Elasticsearch &gt; Playground.</p><p>Auf dem Playground-Bildschirm sollten Sie ein grünes Häkchen und „LLM Connected“ sehen, das anzeigt, dass ein Connector vorhanden ist. Dies ist der Ollama-Connector, den wir gerade oben erstellt haben. Eine ausführlichere Anleitung für Playground finden Sie <a href="https://www.elastic.co/guide/en/kibana/current/playground.html">hier</a>.</p><p>Klicken Sie auf das blaue Symbol „Datenquellen hinzufügen“ und wählen Sie den „book_alice“-Index aus, den wir zuvor erstellt haben, oder einen anderen Index, den Sie zuvor konfiguriert haben und der Inferenz-APIs für Einbettungen verwendet.</p><p>DeepSeek ist ein Gedankenkettenmodell mit starken Ausrichtungsmerkmalen. Aus der RAG-Perspektive heraus ist dies sowohl gut als auch schlecht. Das Gedankenkettentraining kann DeepSeek dabei helfen, scheinbar widersprüchliche Aussagen in Zitaten zu rationalisieren, aber die starke Ausrichtung auf Trainingswissen kann auch dazu führen, dass es seine eigene Version der Weltfakten unserer Kontextgrundlage vorzieht. Diese starke Ausrichtung ist zwar gut gemeint, erschwert jedoch bekanntermaßen die Unterweisung von LLMs bei der Erörterung von Themen, bei denen unser privates Wissen im Trainingsdatensatz eingeschränkt oder nicht gut repräsentiert ist.</p><p>In unserem Playground-Setup haben wir folgende Systemvorgabe eingetragen: „Sie sind ein Assistent für Frage-Antwort-Aufgaben anhand relevanter Textstellen aus dem Buch „Alice im Wunderland““ und die anderen Vorgaben übernommen.</p><p>Auf die Frage „Wer war bei der Teeparty?“ erhalten wir die Antwort: „Der Märzhase, der Hutmacher und die Haselmaus waren bei der Teeparty. [Zitat: Position 1 und 2]“, was korrekt ist.
</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0ce6a0facd972fdd/6a17dfa03e03d79aaa4f2b92/e8af3ff93a72e1f02de8e73f6c2606cbc19970e5-1296x813.png" alt="" /><p>Anhand der &lt;think&gt;-Tags können wir erkennen, dass DeepSeek bei der Beantwortung der Fragen definitiv über den Inhalt der Zitate nachgedacht hat.</p><h2>Testen von Ausrichtungsbeschränkungen</h2><p>Lassen Sie uns als Test ein intellektuell anspruchsvolles Szenario für DeepSeek erstellen. Wir erstellen einen Index von Verschwörungstheorien, von denen die Trainingsdaten von DeepSeek wissen, dass sie nicht wahr sind.</p><p>In den Kibana-Entwicklungstools erstellen wir den folgenden Index und die folgenden Daten:</p>PUT /classic_conspiracies
{
   "mappings": {
       "properties": {
           "content": {
               "type": "text",
               "copy_to": "content_semantic"
           },
           "content_semantic": {
               "type": "semantic_text",
               "inference_id": ".multilingual-e5-small-elasticsearch"
           }
       }
   }
}




POST /classic_conspiracies/_doc/1
{
   "content": "birds aren't real, the government replaced them with drones a long time ago"
}
POST /classic_conspiracies/_doc/2
{
   "content": "tinfoil hats are necessary to prevent our brains from being read"
}
POST /classic_conspiracies/_doc/3
{
   "content": "ancient aliens influenced early human civilizations, this explains why things made out of stone are marginally similar on different continents"
}<p>
Diese Verschwörungstheorien werden die Grundlage für unser LLM bilden. Trotz einer aggressiven Systemaufforderung akzeptiert DeepSeek unsere Version der Fakten nicht. Wären wir in einer Situation, in der wir wüssten, dass unsere privaten Daten vertrauenswürdiger, fundierter oder auf die Bedürfnisse unserer Organisation abgestimmt sind, wäre dies nicht akzeptabel:</p><p>Zur Testfrage „Sind Vögel echt?“ (Erklärung <a href="https://knowyourmeme.com/memes/birds-arent-real">kenne dein Meme</a>) erhalten wir die Antwort: „Im angegebenen Kontext werden Vögel nicht als real angesehen, aber in Wirklichkeit sind sie echte Tiere. [Kontext: Position 1]“. Dieser Test beweist, dass DeepSeek R1 auch auf der 7B-Parameterebene leistungsstark ist … je nach unserem Datensatz ist es jedoch möglicherweise nicht die beste Wahl für RAG.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5e8dabf65ea200e1/6a17dfa2ec0f8982135a6541/67d5f6cdb97bfd3adb926cbd588c768f9d6730ae-1277x737.png" alt="" /><h2>Was haben wir also gelernt?</h2><p>Zusammenfassend:</p><ul><li><p>Das lokale Ausführen von Modellen in Tools wie Ollama ist eine großartige Möglichkeit, einen Blick auf das Modellverhalten zu werfen.</p></li><li><p>DeepSeek R1 ist ein Schlussfolgerungsmodell, was bedeutet, dass es für Anwendungsfälle wie RAG Vor- und Nachteile hat.</p></li><li><p>Playground ist in der Lage, sich über eine OpenAI-ähnliche REST-API mit Inferenz-Hosting-Frameworks wie Ollama zu verbinden, was in dieser frühen Ära des KI-Hostings zu einem De-facto-Standard wird.</p></li></ul><p>Insgesamt sind wir beeindruckt, wie weit die lokale, „air-gapped“-RAG gekommen ist. Die Tools in Elasticsearch, Kibana und die verfügbaren Open-Weight-Modelle haben sich erheblich weiterentwickelt, seit wir 2023 zum ersten Mal über die <a href="https://www.elastic.co/search-labs/blog/privacy-first-ai-search-langchain-elasticsearch">datenschutzfreundliche KI-Suche</a> geschrieben haben.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/deepseek-rag-ollama-playground</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/deepseek-rag-ollama-playground</guid>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[Kibana]]></category>
    <dc:creator><![CDATA[Dave Erickson,Jakob Reiter]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2a4b2ae6bd97850b/6a17dfa4be6086558f00464c/1bd853bfdfa2710e44cc4c08dede6bd21b35c4b8-1542x860.png" length="0" type="image/png"/>
    <pubDate>Thu, 30 Jan 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Facettensuche: KI zur Verbesserung des Suchumfangs und der Suchergebnisse]]></title>
    <description><![CDATA[Erfahren Sie, wie Sie mit der Facettensuche in Elasticsearch die Optionen innerhalb von Kategorien schnell eingrenzen können.]]></description>
    <content:encoded><![CDATA[<p>In diesem Artikel werden wir untersuchen, wie künstliche Intelligenz (KI), insbesondere durch den Einsatz fortschrittlicher Sprachmodelle wie GPT-4, dazu beitragen kann, mehr kontextbezogene Aspekte zu schaffen und diese dadurch für die Nutzer noch relevanter und nützlicher zu machen.</p><p>Die Facettensuche ist ein leistungsstarkes Werkzeug in E-Commerce-Plattformen. Es hilft dabei, Suchergebnisse anhand der Eigenschaften der angezeigten Elemente zu organisieren und zu verfeinern. Facetten werden zwar oft mit Filtern verwechselt, funktionieren aber anders. Filter sind feste Attribute, die durch Informationen definiert werden, die immer im Index vorhanden sind, wie zum Beispiel die Kategorie oder das Format eines Produkts. Facetten hingegen sind dynamisch und werden aus den Ergebnissen der ausgeführten Suche generiert.</p><p>Stellen Sie sich einen Bekleidungskatalog vor: Felder wie „Kategorie“ (z. B. T-Shirts, Hosen) oder „Geschlecht“ (z. B. männlich, weiblich) sind Filter, die dabei helfen, die Ergebnisse einzugrenzen. Die Facetten spiegeln jedoch spezifische Eigenschaften der in den Ergebnissen angezeigten Produkte wider, wie z. B. gängige Farben, verfügbare Größen oder Materialien. Dies ermöglicht ein anpassungsfähigeres und kontextbezogeneres Sucherlebnis.</p><p>Unten sehen Sie ein Bild, auf dem wir mit einem Filter interagieren und die danach gefilterten Suchergebnisse sehen können.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc4ce8ca7e5b62ad7/6a17f8ba6864a4534bb68979/74d2159706ab7248ebe5efddc74c882f0693db71-600x420.gif" alt="Beispiel für eine Facettensuche" /><h2>Wie KI die Facettengenerierung verbessern kann</h2><p>Künstliche Intelligenz wird oft mit semantischer Suche und Einbettungen in Verbindung gebracht, aber was ist mit Facetten? Wie kann KI genutzt werden, um Facetten für jede Suche nützlicher und kontextspezifischer zu gestalten?</p><p>Eine interessante Möglichkeit besteht darin, mithilfe von KI neue Kategorisierungen zu erstellen, die über die traditionellen Klassifizierungen im Index hinausgehen. Durch die Analyse spezifischer Merkmale des Inhalts können diese neuen Kategorien eine reichhaltigere und präzisere Kontextualisierung ermöglichen, wodurch die einzelnen Aspekte relevanter und besser auf die Bedürfnisse der Nutzer abgestimmt werden. Dies ermöglicht eine aussagekräftigere Verfeinerung der Ergebnisse im Vergleich zu den ursprünglichen Dokumentenkategorien.</p><h2>Wie KI die Filmklassifizierung für bessere Suchergebnisse verfeinern kann</h2><p>Lassen Sie uns die folgenden Filme analysieren, die alle aktuell dem Genre Drama zugeordnet sind:</p><ul><li><p>Requiem für einen Traum
 Zusammenfassung: Die drogeninduzierten Utopien von vier Bewohnern von Coney Island zerbrechen, als ihre Sucht immer tiefer wird.</p></li><li><p>Amerikanische Schönheit
 Zusammenfassung: Ein sexuell frustrierter Vorstadtvater gerät in eine Midlife-Crisis, nachdem er sich in die beste Freundin seiner Tochter verliebt hat.</p></li><li><p>Good Will Hunting
 Kurzfassung: Will Hunting, ein Hausmeister am MIT, hat ein Talent für Mathematik, braucht aber die Hilfe eines Psychologen, um in seinem Leben eine Richtung zu finden.</p></li></ul><p>Diese Genreklassifizierung erfasst weder die subtilen Unterschiede noch die einzigartigen Kontexte der einzelnen Filme. Durch den Einsatz von KI zur Analyse von Inhaltsangaben und zentralen Themen können wir neue Kategorien erstellen, die den wahren Kontext jedes Films besser widerspiegeln. Zum Beispiel:</p><ul><li><p>Requiem für einen Traum – Neue Kategorie: „Sucht und Abhängigkeit“</p></li><li><p>American Beauty – Neue Kategorie: „Midlife-Crisis“</p></li><li><p>Good Will Hunting – Neue Kategorie: „Intellektueller Kampf“</p></li></ul><p>Durch diese neuen Kategorien werden die Suchergebnisse wesentlich präziser und bieten den Nutzern gleichzeitig aussagekräftigere Filter zur Verfeinerung ihrer Ergebnisse. Dieser Ansatz ist besonders effektiv, wenn die ursprünglichen Kategorien zu allgemein gehalten sind, da er es den Nutzern ermöglicht, leichter genau das zu finden, wonach sie suchen.</p><h2>Erstellen neuer Kategorien mit GPT-4: Beispiel für die Facettensuche</h2><p>In diesem Beispiel zeigen wir, wie ein KI-Modell verwendet werden kann, um neue Filmkategorien zu erstellen, die präziser sind und besser auf den Kontext des jeweiligen Werkes abgestimmt sind. Um diesen Prozess zu demonstrieren, werden wir die Elastic-Simulationspipeline zusammen mit dem OpenAI-Inferenzdienst verwenden. Es wird eine Pipeline mit mehreren Prozessoren erstellt, darunter der Skriptprozessor, der für die Erstellung der Eingabeaufforderung zuständig ist, die im Inferenzprozessor ausgeführt werden soll und die neuen Kategorien bestimmen kann. Die anderen Prozessoren werden verwendet, um die während der Pipeline-Ausführung erzeugten Daten und Hilfsfelder zu bearbeiten. Erwähnenswert ist, dass diese Logik auch auf andere ähnliche Werkzeuge oder Modelle angewendet werden kann.</p><p>Als erstes müssen wir den Inferenz-Endpunkt erstellen, in dem wir den Dienst als OpenAI, das für den Zugriff auf den Dienst erforderliche Token und das Modell definieren. In diesem Beispiel verwende ich gpt-4o-mini. Für weitere Details zum OpenAI-Inferenzdienst klicken Sie <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">hier</a>.</p>PUT _inference/completion/generate_topics_ia
{
    "service": "openai",
    "service_settings": {
        "api_key": "your-token",
        "model_id": "gpt-4o-mini"
    }
}<p>Nachdem der Endpunkt erstellt wurde, können wir ihn nun verwenden, um die neuen Kategorien zu erstellen. Nachfolgend finden Sie eine Pipeline, die den gesamten Prozess der Dokumentendatenmanipulation und der Generierung von Eingabeaufforderungen übernimmt. Ich werde die Funktion jedes Prozessors im Detail erläutern.</p><p>Der erste Prozessor ist für die Erstellung der Eingabeaufforderung zuständig. Es ist sehr wichtig, die Anweisungen klar und detailliert zu formulieren, damit die KI die Themen korrekt analysieren und identifizieren kann. In dieser Aufgabenstellung bitte ich um zwei Themen, die auf der Analyse von Titel, Beschreibung und Genre der Filme basieren.</p>{
        "script": {
          "source": """
            ctx.prompt = "You are an expert in semantic analysis and audiovisual content categorization. Your task is to generate only subcategories (max 2 topics) that describe specific aspects of movies based on their genres and descriptions. The output should be like: 'n1, n2, ...n'. Here is a movie info to analyze: Title: " + ctx.title  + "Genres: " + ctx.genres  + "Description: " + ctx.description;
          """
        }<p>Die nächste Pipeline ist die Inferenzpipeline. Sie empfängt die Eingabeaufforderung und sendet sie an unseren <strong>generate_topics_ia-</strong> Endpunkt. Die vom Modell generierte Antwort wird im Ergebnisfeld gespeichert.</p>{
        "inference": {
          "model_id": "generate_topics_ia",
          "input_output": {
            "input_field": "prompt",
            "output_field": "result"
          }
        }
      }<p>Als Nächstes werden 3 Prozessoren verwendet, um die Antwort zu bearbeiten und sie im Themenfeld festzulegen, zusätzlich zum Entfernen temporärer Felder, die ich erstellt habe.</p><p>Bei der Ausführung dieser Pipeline erhalten wir die folgenden Ergebnisse:</p>{
  "docs": [
    {
      "doc": {
        "_index": "index",
        "_version": "-3",
        "_id": "1",
        "_source": {
          "description": "While Frodo and Sam edge closer to Mordor with the help of the shifty Gollum, the divided fellowship makes a stand against Sauron's new ally, Saruman, and his hordes of Isengard.",
          "model_id": "generate_topics_ia",
          "title": "The Lord of the Rings: The Fellowship of the Ring",
          "genres": [
            "Action",
            "Adventure",
            "Drama"
          ],
          "topics": [
            "Fantasy",
            "Quest"
          ]
        },
        "_ingest": {
          "timestamp": "2024-11-22T17:51:51.340010257Z"
        }
      }
    },
    {
      "doc": {
        "_index": "index",
        "_version": "-3",
        "_id": "2",
        "_source": {
          "description": "A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.",
          "model_id": "generate_topics_ia",
          "title": "Interstellar",
          "genres": [
            "Adventure",
            "Drama",
            "Sci-Fi"
          ],
          "topics": [
            "space exploration",
            "human survival"
          ]
        },
        "_ingest": {
          "timestamp": "2024-11-22T17:51:51.340413173Z"
        }
      }
    },
    {
      "doc": {
        "_index": "index",
        "_version": "-3",
        "_id": "3",
        "_source": {
          "description": "An astronaut becomes stranded on Mars after his team assume him dead, and must rely on his ingenuity to find a way to signal to Earth that he is alive.",
          "model_id": "generate_topics_ia",
          "title": "The Martian",
          "genres": [
            "Adventure",
            "Drama",
            "Sci-Fi"
          ],
          "topics": [
            "survival",
            "ingenuity"
          ]
        },
        "_ingest": {
          "timestamp": "2024-11-22T17:51:51.340427965Z"
        }
      }
    }
  ]
}<p>Beachten Sie, dass wir neue Kategorien haben, die stärker mit dem Kontext der Filme zusammenhängen, auch wenn einige ursprünglich aus demselben Genre stammen.</p><p>Wir können diese neuen Kategorien nun verwenden und sie zusammen mit dem Dokument indexieren. Auf diese Weise erhalten wir bei der Erstellung der Facetten neben der Hauptkategorie auch spezifischere Unterkategorien, die auf den Kontext der Filme abgestimmt sind.</p><p>Darüber hinaus ist es möglich, diese neuen Kategorien zu vektorisieren und sie in Vektorsuchen zu verwenden. Dies bedeutet, dass die neuen Kategorien nicht nur als Filter dienen, sondern auch zur Berechnung semantischer Ähnlichkeiten mit den Suchbegriffen verwendet werden können, wodurch die Relevanz der präsentierten Ergebnisse weiter erhöht wird.</p><p>Vollständige Pipeline:</p>POST /_ingest/pipeline/_simulate
{
  "pipeline": {
    "processors": [
      {
        "script": {
          "source": """
            ctx.prompt = "You are an expert in semantic analysis and audiovisual content categorization. Your task is to generate only subcategories (max 2 topics) that describe specific aspects of movies based on their genres and descriptions. The output should be like string: 'n1, n2m ...n'. Here is a movies info to analyze: Title: " + ctx.title  + "Genres: " + ctx.genres  + "Description: " + ctx.description;
          """
        }
      },
      {
        "inference": {
          "model_id": "generate_topics_ia",
          "input_output": {
            "input_field": "prompt",
            "output_field": "result"
          }
        }
      },
      {
        "split": {
          "field": "result",
          "target_field": "topics",
          "separator": ", "
        }
      },
      {
        "remove": {
          "field": "result"
        }
      },
      {
        "remove": {
          "field": "prompt"
        }
      }
    ]
  },
  "docs": [
    {
      "_index": "index",
      "_id": "1",
      "_source": {
        "title": "The Lord of the Rings: The Fellowship of the Ring",
        "description": "While Frodo and Sam edge closer to Mordor with the help of the shifty Gollum, the divided fellowship makes a stand against Sauron's new ally, Saruman, and his hordes of Isengard.",
        "genres": [
          "Action",
          "Adventure",
          "Drama"
        ]
      }
    },
    {
      "_index": "index",
      "_id": "2",
      "_source": {
        "title": "Interstellar",
        "description": "A team of explorers travel through a wormhole in space in an attempt to ensure humanity's survival.",
        "genres": [
          "Adventure", "Drama", "Sci-Fi"
        ]
      }
    },
    {
      "_index": "index",
      "_id": "3",
      "_source": {
        "title": "The Martian",
        "description": "An astronaut becomes stranded on Mars after his team assume him dead, and must rely on his ingenuity to find a way to signal to Earth that he is alive.",
        "genres": [
          "Adventure", "Drama", "Sci-Fi"
        ]
      }
    }
  ]
}<h2>Fazit</h2><p>Der Einsatz von KI zur Verbesserung der Suchergebnisse kann das Sucherlebnis grundlegend verändern, indem die Ergebnisse spezifischer und kontextbezogener werden. Im Gegensatz zu festen Kategorien, die oft sehr allgemein gehalten sind, können KI-generierte Kategorien den Kontext besser widerspiegeln. Wenn wir beispielsweise Filme neu klassifizieren, können wir Kontextinformationen erfassen, die in den primären Kategorien fehlen, und so viel relevantere Gruppierungen vornehmen.</p><p>Diese neuen Kategorien können dem Index hinzugefügt werden, um nicht nur die Facettierung zu verbessern, sondern auch Vektorsuchen zu ermöglichen. Das Ergebnis ist ein effizienteres Sucherlebnis mit Filtern, die besser auf den Kontext abgestimmt sind.</p><h2>Referenzen</h2><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html">https://www.elastic.co/guide/en/elasticsearch/reference/current/infer-service-openai.html</a></p><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/simulate-pipeline-api.html">https://www.elastic.co/guide/en/elasticsearch/reference/current/simulate-pipeline-api.html</a></p><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/script-processor.html">https://www.elastic.co/guide/en/elasticsearch/reference/current/script-processor.html</a></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/faceted-search-examples-ai</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/faceted-search-examples-ai</guid>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Andre Luiz]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd2838185214162c8/6a17f8bedbb4ff04affb58a5/25c9f9baa2326b5189ce0b1cc6240475781c755d-721x421.jpg" length="0" type="image/jpeg"/>
    <pubDate>Tue, 28 Jan 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Wie man den Elasticsearch Vector Store Connector für Microsoft Semantic Kernel zur Entwicklung von KI-Agenten verwendet]]></title>
    <description><![CDATA[Microsoft Semantic Kernel ist ein leichtgewichtiges Open-Source-Entwicklungskit, mit dem Sie auf einfache Weise KI-Agenten erstellen und die neuesten KI-Modelle in Ihre C#-, Python- oder Java-Codebasis integrieren können. Mit der Veröffentlichung des Semantic Kernel Elasticsearch Vector Store Connectors können Entwickler, die Semantic Kernel zum Erstellen von KI-Agenten verwenden, Elasticsearch nun als skalierbaren Vektorspeicher der Enterprise-Klasse einbinden und gleichzeitig die Abstraktionen von Semantic Kernel weiterhin nutzen.]]></description>
    <content:encoded><![CDATA[<p>In Zusammenarbeit mit dem <a href="https://learn.microsoft.com/en-us/semantic-kernel/overview/">Microsoft Semantic Kernel-</a> Team geben wir die Verfügbarkeit des <a href="https://github.com/elastic/semantic-kernel-net/">Semantic Kernel Elasticsearch Vector Store Connector</a> für <a href="https://learn.microsoft.com/en-us/semantic-kernel/overview/">Microsoft Semantic Kernel</a> (.NET)-Benutzer bekannt. Der semantische Kernel vereinfacht die Entwicklung von KI-Agenten auf Unternehmensebene und bietet unter anderem die Möglichkeit, große Sprachmodelle (LLMs) mit relevanteren, datengesteuerten Antworten aus einem Vektorspeicher zu erweitern. Semantic Kernel bietet eine nahtlose Abstraktionsschicht für die Interaktion mit Vektorspeichern wie Elasticsearch und stellt wichtige Funktionen wie das Erstellen, Auflisten und Löschen von Datensatzsammlungen sowie das Hochladen, Abrufen und Löschen einzelner Datensätze bereit.</p><p>Der <a href="https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/out-of-the-box-connectors/elasticsearch-connector?pivots=programming-language-csharp">sofort einsatzbereite Semantic Kernel Elasticsearch Vector Store Connector</a> unterstützt die <a href="https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/?pivots=programming-language-csharp#the-vector-store-abstraction">Abstraktionen des Semantic Kernel Vector Stores</a> , was es Entwicklern sehr einfach macht, Elasticsearch als Vector Store beim Erstellen von KI-Agenten einzubinden.</p><p>Elasticsearch hat eine starke Verankerung in der Open-Source-Community und hat vor Kurzem die <a href="https://www.elastic.co/blog/elasticsearch-is-open-source-again">AGPL-Lizenz</a> übernommen. In Kombination mit dem Open-Source-Microsoft Semantic Kernel bieten diese Tools eine leistungsstarke, unternehmensgerechte Lösung. Sie können lokal beginnen, indem Sie Elasticsearch in wenigen Minuten mit diesem Befehl <code>curl -fsSL https://elastic.co/start-local | sh </code>starten (siehe <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html">start-local</a> für Details) und dann auf <a href="https://cloud.elastic.co/registration?onboarding_token=vectorsearch&amp;utm_source=semantickernel&amp;utm_content=documentation">Cloud-gehostete</a> oder <a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.16/install-elasticsearch.html">selbstgehostete</a> Versionen umsteigen, während Sie Ihre KI-Agenten produktiv einsetzen.</p><p>In diesem Blogbeitrag zeigen wir Ihnen, wie Sie <a href="https://github.com/elastic/semantic-kernel-net/">den Semantic Kernel Elasticsearch Vector Store Connector</a> in Verbindung mit Semantic Kernel verwenden. Eine Python-Version des Konnektors wird zu einem späteren Zeitpunkt verfügbar sein.</p><h2>Szenario auf hoher Ebene: Entwicklung einer RAG-Anwendung mit Semantic Kernel und Elasticsearch</h2><p>Im folgenden Abschnitt gehen wir ein Beispiel durch. Im Wesentlichen entwickeln wir eine RAG-Anwendung (Retrieval Augmented Generation), die eine Frage des Benutzers als Eingabe entgegennimmt und eine Antwort zurückgibt. Wir verwenden Azure OpenAI (<a href="https://devblogs.microsoft.com/semantic-kernel/introducing-new-ollama-connector-for-local-models/">ein lokales LLM</a> kann ebenfalls verwendet werden) als LLM, Elasticsearch als Vektorspeicher und Semantic Kernel (.net) als Framework, um alle Komponenten miteinander zu verbinden.</p><p>Falls Sie mit RAG-Architekturen nicht vertraut sind, können Sie sich mit diesem Artikel eine kurze Einführung verschaffen: <a href="https://www.elastic.co/search-labs/blog/retrieval-augmented-generation-rag">https://www.elastic.co/search-labs/blog/retrieval-augmented-generation-rag</a>.</p><p>Die Antwort wird vom LLM generiert, der mit Kontextinformationen gespeist wird, die für die Frage relevant sind und aus dem Elasticsearch-Vektorspeicher abgerufen werden. Die Antwort enthält auch die Quelle, die vom LLM als Kontext verwendet wurde.</p><h3>RAG-Beispiel</h3><p>In diesem konkreten Beispiel entwickeln wir eine Anwendung, die es Benutzern ermöglicht, Fragen zu Hotels zu stellen, die in einer internen Hoteldatenbank gespeichert sind. Der Benutzer könnte z.B. Suchen Sie nach einem bestimmten Hotel anhand verschiedener Kriterien oder fordern Sie eine Liste von Hotels an.</p><p>Für die Beispieldatenbank haben wir eine <a href="https://github.com/elastic/semantic-kernel-net/blob/main/Elastic.SemanticKernel.Playground/hotels.csv">Liste von Hotels</a> mit 100 Einträgen generiert. Die Stichprobengröße ist bewusst klein gehalten, damit Sie die Konnektordemo so einfach wie möglich ausprobieren können. In einer realen Anwendung würde der Elasticsearch-Connector seine Vorteile gegenüber anderen Optionen, wie der `InMemory`-Vektorspeicherimplementierung, insbesondere bei der Arbeit mit extrem großen Datenmengen zeigen.</p><p>Die vollständige Demo-Anwendung finden Sie im Elasticsearch Vector Store Connector- <a href="https://github.com/elastic/semantic-kernel-net/tree/main/Elastic.SemanticKernel.Playground">Repository</a>.</p><p>Beginnen wir damit, die erforderlichen NuGet-Pakete und die verwendeten Direktiven zu unserem Projekt hinzuzufügen:</p>dotnet add package "Elastic.Clients.Elasticsearch" -v 8.16.2
dotnet add package "Elastic.SemanticKernel.Connectors.Elasticsearch" -v 0.1.2
dotnet add package "Microsoft.Extensions.Hosting" -v 9.0.0
dotnet add package "Microsoft.SemanticKernel.Connectors.AzureOpenAI" -v 1.30.0
dotnet add package "Microsoft.SemanticKernel.PromptTemplates.Handlebars" -v 1.30.0using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

using Elastic.Clients.Elasticsearch;
using Elastic.Transport;

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Data;
using Microsoft.SemanticKernel.Embeddings;
using Microsoft.SemanticKernel.PromptTemplates.Handlebars;<p>Wir können nun unser Datenmodell erstellen und es mit semantischen Kernel-spezifischen Attributen ausstatten, um das Speichermodellschema und einige Hinweise für die Textsuche zu definieren:</p>/// &lt;summary&gt;
/// Data model for storing a "hotel" with a name, a description, a  description embedding and an optional reference link.
/// &lt;/summary&gt;
public sealed record Hotel
{
	[VectorStoreRecordKey]
	public required string HotelId { get; set; }

	[TextSearchResultName]
	[VectorStoreRecordData(IsFilterable = true)]
	public required string HotelName { get; set; }

	[TextSearchResultValue]
	[VectorStoreRecordData(IsFullTextSearchable = true)]
	public required string Description { get; set; }

	[VectorStoreRecordVector(Dimensions: 1536, DistanceFunction.CosineSimilarity, IndexKind.Hnsw)]
	public ReadOnlyMemory&lt;float&gt;? DescriptionEmbedding { get; set; }

	[TextSearchResultLink]
	[VectorStoreRecordData]
	public string? ReferenceLink { get; set; }
}<p>Die Attribute des Speichermodellschemas (`VectorStore*`) sind für die tatsächliche Verwendung des Elasticsearch Vector Store Connectors am relevantesten, nämlich:</p><p></p><ul><li><p><code>VectorStoreRecordKey</code> Eine Eigenschaft einer Datensatzklasse als Schlüssel zu kennzeichnen, unter dem der Datensatz in einem Vektorspeicher abgelegt wird.</p></li><li><p><code>VectorStoreRecordData</code> Eine Eigenschaft einer Datensatzklasse als 'Daten' kennzeichnen.</p></li><li><p><code>VectorStoreRecordVector</code> Eine Eigenschaft einer Datensatzklasse als Vektor kennzeichnen.</p></li></ul><p>Alle diese Attribute akzeptieren verschiedene optionale Parameter, mit denen das Speichermodell weiter angepasst werden kann. Im Fall von <code>VectorStoreRecordKey </code> ist es beispielsweise möglich, eine andere Distanzfunktion oder einen anderen Indextyp anzugeben.</p><p>Die Textsuchattribute (<code>TextSearch*</code>) werden im letzten Schritt dieses Beispiels wichtig sein. Wir werden später auf sie zurückkommen.</p><p>Im nächsten Schritt initialisieren wir die Semantic Kernel Engine und erhalten Referenzen zu den Kerndiensten. In einer realen Anwendung sollte <a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection">Dependency Injection</a> anstelle des direkten Zugriffs auf die Service-Collection verwendet werden. Dasselbe gilt für die fest codierte Konfiguration und die Geheimnisse, die stattdessen mithilfe eines <a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/configuration">Konfigurationsanbieters</a> gelesen werden sollten:</p>var builder = Host.CreateApplicationBuilder(args);

// Register AI services.
var kernelBuilder = builder.Services.AddKernel();

kernelBuilder.AddAzureOpenAIChatCompletion("gpt-4o", "https://my-service.openai.azure.com", "my_token");

kernelBuilder.AddAzureOpenAITextEmbeddingGeneration("ada-002", "https://my-service.openai.azure.com", "my_token");

// Register text search service.
kernelBuilder.AddVectorStoreTextSearch&lt;Hotel&gt;();

// Register Elasticsearch vector store.
var elasticsearchClientSettings = new ElasticsearchClientSettings(new Uri("https://my-elasticsearch-instance.cloud"))
    .Authentication(new BasicAuthentication("elastic", "my_password"));

kernelBuilder.AddElasticsearchVectorStoreRecordCollection&lt;string, Hotel&gt;("skhotels", elasticsearchClientSettings);

// Build the host.
using var host = builder.Build();

// For demo purposes, we access the services directly without using a DI context.

var kernel = host.Services.GetService&lt;Kernel&gt;()!;
var embeddings = host.Services.GetService&lt;ITextEmbeddingGenerationService&gt;()!;
var vectorStoreCollection = host.Services.GetService&lt;IVectorStoreRecordCollection&lt;string, Hotel&gt;&gt;()!;

// Register search plugin.
var textSearch = host.Services.GetService&lt;VectorStoreTextSearch&lt;Hotel&gt;&gt;()!;
kernel.Plugins.Add(textSearch.CreateWithGetTextSearchResults("SearchPlugin"));<p>Der Dienst <code>vectorStoreCollection</code> kann nun verwendet werden, um die Sammlung zu erstellen und einige <a href="https://github.com/elastic/semantic-kernel-net/blob/main/Elastic.SemanticKernel.Playground/hotels.csv">Demodatensätze</a> einzulesen:</p>await vectorStoreCollection.CreateCollectionIfNotExistsAsync();

// CSV format: ID;Hotel Name;Description;Reference Link
var hotels = (await File.ReadAllLinesAsync("hotels.csv"))
    .Select(x =&gt; x.Split(';'));

foreach (var chunk in hotels.Chunk(25))
{
    var descriptionEmbeddings = await embeddings.GenerateEmbeddingsAsync(chunk.Select(x =&gt; x[2]).ToArray());
    
    for (var i = 0; i &lt; chunk.Length; ++i)
    {
        var hotel = chunk[i];
        await vectorStoreCollection.UpsertAsync(new Hotel
        {
            HotelId = hotel[0],
            HotelName = hotel[1],
            Description = hotel[2],
            DescriptionEmbedding = descriptionEmbeddings[i],
            ReferenceLink = hotel[3]
        });
    }
}<p>Dies zeigt, wie Semantic Kernel die Verwendung eines Vektorspeichers mit all seiner Komplexität auf wenige einfache Methodenaufrufe reduziert.</p><p>Im Hintergrund wird in Elasticsearch ein neuer Index erstellt und alle notwendigen Eigenschaftszuordnungen werden angelegt. Unser Datensatz wird dann vollständig transparent in das Speichermodell abgebildet und schließlich im Index gespeichert. Nachfolgend sehen Sie, wie die Zuordnungen in Elasticsearch aussehen.</p>{
  "mappings": {
    "properties": {
      "descriptionEmbedding": {
        "dims": 1536,
        "index": true,
        "index_options": {
          "type": "hnsw"
        },
        "similarity": "cosine",
        "type": "dense_vector"
      },
      "hotelName": {
        "type": "keyword"
      },
      "description": {
        "type": "text"
      }
    }
  }
}<p>Die <code>embeddings.GenerateEmbeddingsAsync()</code> -Aufrufe riefen transparent den konfigurierten Azure AI Embeddings Generation-Dienst auf.</p><p>Noch mehr Magie lässt sich im letzten Schritt dieser Demonstration beobachten.</p><p>Mit nur einem einzigen Aufruf von <code>InvokePromptAsync</code> werden alle folgenden Operationen ausgeführt, wenn der Benutzer eine Frage zu den Daten stellt:</p><p>1. Es wird eine Einbettung für die Frage des Benutzers generiert.</p><p>2. Der Vektorspeicher wird nach relevanten Einträgen durchsucht.</p><p>3. Die Ergebnisse der Abfrage werden in eine Eingabeaufforderungsvorlage eingefügt.</p><p>4. Die eigentliche Anfrage in Form der finalen Eingabeaufforderung wird an den KI-Chatvervollständigungsdienst gesendet.</p>// Invoke the LLM with a template that uses the search plugin to
// 1. get related information to the user query from the vector store
// 2. add the information to the LLM prompt.
var response = await kernel.InvokePromptAsync(
    promptTemplate: """
                    Please use this information to answer the question:
                    {{#with (SearchPlugin-GetTextSearchResults question)}}
                      {{#each this}}
                        Name: {{Name}}
                        Value: {{Value}}
                        Source: {{Link}}
                        -----------------
                      {{/each}}
                    {{/with}}
                    
                    Include the source of relevant information in the response.

                    Question: {{question}}
                    """,
    arguments: new KernelArguments
    {
        { "question", "Please show me all hotels that have a rooftop bar." },
    },
    templateFormat: "handlebars",
    promptTemplateFactory: new HandlebarsPromptTemplateFactory());<p>Erinnern Sie sich an die <code>TextSearch*</code> -Attribute, die wir zuvor in unserem Datenmodell definiert haben? Mithilfe dieser Attribute können wir in unserer Eingabeaufforderungsvorlage entsprechende Platzhalter verwenden, die automatisch mit den Informationen aus unseren Einträgen im Vektorspeicher befüllt werden.</p><p>Die endgültige Antwort auf unsere Frage „Bitte zeigen Sie mir alle Hotels mit einer Dachterrassenbar“ lautet wie folgt:</p>Console.WriteLine(response.ToString());

// &gt; The hotel that has a rooftop bar is Skyline Suites. You can find more information about this hotel [here](https://example.com/yz567).<p>Die Antwort bezieht sich korrekt auf den folgenden Eintrag in unserer hotels.csv-Datei.</p>9;
Skyline Suites;
Offering panoramic city views from every suite, this hotel is perfect for those who love the urban landscape. Enjoy luxurious amenities, a rooftop bar, and close proximity to attractions. Luxurious and contemporary.;
https://example.com/yz567<p>Dieses Beispiel zeigt sehr gut, wie die Verwendung des Microsoft Semantic Kernel durch seine durchdachten Abstraktionen eine signifikante Reduzierung der Komplexität ermöglicht und gleichzeitig ein sehr hohes Maß an Flexibilität gewährleistet. Durch die Änderung einer einzigen Codezeile können beispielsweise der Vektorspeicher oder die verwendeten KI-Dienste ersetzt werden, ohne dass ein anderer Teil des Codes umstrukturiert werden muss.</p><p>Gleichzeitig bietet das Framework eine enorme Menge an High-Level-Funktionalität, wie zum Beispiel die Funktion `InvokePrompt` oder das Template- oder Such-Plugin-System.</p><p>Die vollständige Demo-Anwendung finden Sie im Elasticsearch Vector Store Connector-Repository.</p><h2>Was ist sonst noch mit Elasticsearch möglich?</h2><ul><li><p><a href="https://www.elastic.co/search-labs/blog/semantic-search-simplified-semantic-text">Elasticsearch: Neues semantisches Textmapping: Vereinfachung der semantischen Suche</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/semantic-reranking-with-retrievers">Semantisches Reranking in Elasticsearch mit Retrievern</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1">Erweiterte RAG-Techniken Teil 1: Datenverarbeitung</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2">Fortgeschrittene RAG-Techniken Teil 2: Abfragen und Testen</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/elasticsearch-rag-with-llama3-opensource-and-elastic">RAG mit Llama 3 Open-Source und Elastic erstellen</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/local-rag-agent-elasticsearch-langgraph-llama3">Eine Anleitung zum Erstellen eines lokalen Agenten mit LangGraph, LLaMA3 und dem Elasticsearch-Vektorspeicher von Grund auf</a></p></li></ul><h2>Elasticsearch &amp; Semantic Kernel: Was kommt als Nächstes?</h2><ul><li><p>Wir haben gezeigt, wie der Elasticsearch-Vektorspeicher beim Erstellen von GenAI-Anwendungen in .NET einfach in den Semantic Kernel eingebunden werden kann. Seien Sie gespannt auf die nächste Python-Integration.</p></li><li><p>Da Semantic Kernel Abstraktionen für fortgeschrittene Suchfunktionen wie <a href="https://www.elastic.co/search-labs/tutorials/search-tutorial/vector-search/hybrid-search">die Hybridsuche</a> erstellt, ermöglicht Elasticsearch Connect .NET-Entwicklern die einfache Implementierung dieser Funktionen bei der Verwendung von Semantic Kernel.</p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-connector-microsoft-semantic-kernel</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-connector-microsoft-semantic-kernel</guid>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[.NET]]></category>
    <category><![CDATA[Vektordatenbank]]></category>
    <dc:creator><![CDATA[Florian Bernd,Srikanth Manvi]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2d8725035e86f8a8/6a17fe447f6f1564f8c09d74/0564fe794e4c66d0507317822d7aa71826183d20-1311x762.jpg" length="0" type="image/jpeg"/>
    <pubDate>Fri, 06 Dec 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[LangChain4j mit Elasticsearch als Einbettungsspeicher]]></title>
    <description><![CDATA[LangChain4j (LangChain für Java) verwendet Elasticsearch als eingebetteten Speicher. Erfahren Sie, wie Sie damit Ihre RAG-Anwendung in reinem Java erstellen können.]]></description>
    <content:encoded><![CDATA[<p>
Im <a href="https://www.elastic.co/search-labs/blog/langchain4j-llm-integration-introduction">vorherigen Beitrag</a> haben wir herausgefunden, was LangChain4j ist und wie es funktioniert:</p><ul><li><p>Führen Sie eine Diskussion mit LLMs, indem Sie ein <code>ChatLanguageModel</code> und ein <code>ChatMemory</code></p></li><li><p>Die Chat-Historie wird im Speicher gehalten, um den Kontext einer früheren Diskussion mit einem LLM wieder abrufen zu können.</p></li></ul><p>Dieser Blogbeitrag erklärt, wie man:</p><ul><li><p>Vektor-Einbettungen aus Textbeispielen erstellen</p></li><li><p>Vektoreinbettungen im Elasticsearch-Einbettungsspeicher speichern </p></li><li><p>Suche nach ähnlichen Vektoren</p></li></ul><h2>Einbettungen erstellen</h2><p>Um Einbettungen zu erstellen, müssen wir ein <code>EmbeddingModel</code> definieren, das verwendet werden soll. Wir können beispielsweise dasselbe Mistral-Modell verwenden, das wir im <a href="https://www.elastic.co/search-labs/blog/langchain4j-llm-integration-introduction">vorherigen Beitrag</a> verwendet haben. Es lief mit ollama:</p>EmbeddingModel model = OllamaEmbeddingModel.builder()
  .baseUrl(ollama.getEndpoint())
  .modelName(MODEL_NAME)
  .build();<p>Ein Modell ist in der Lage, aus Text Vektoren zu generieren. Hier können wir die Anzahl der vom Modell generierten Dimensionen überprüfen:</p>Logger.info("Embedding model has {} dimensions.", model.dimension());
// This gives: Embedding model has 4096 dimensions.<p>Um Vektoren aus einem Text zu generieren, können wir Folgendes verwenden:</p>Response&lt;Embedding&gt; response = model.embed("A text here");<p>Oder wenn wir auch Metadaten bereitstellen möchten, um nach Dingen wie Text, Preis, Veröffentlichungsdatum oder Ähnlichem filtern zu können, können wir <code>Metadata.from()</code> verwenden. Zum Beispiel fügen wir hier den Spielnamen als Metadatenfeld hinzu:</p>TextSegment game1 = TextSegment.from("""
    The game starts off with the main character Guybrush Threepwood stating "I want to be a pirate!"
    To do so, he must prove himself to three old pirate captains. During the perilous pirate trials, 
    he meets the beautiful governor Elaine Marley, with whom he falls in love, unaware that the ghost pirate 
    LeChuck also has his eyes on her. When Elaine is kidnapped, Guybrush procures crew and ship to track 
    LeChuck down, defeat him and rescue his love.
""", Metadata.from("gameName", "The Secret of Monkey Island"));
Response&lt;Embedding&gt; response1 = model.embed(game1);
TextSegment game2 = TextSegment.from("""
    Out Run is a pseudo-3D driving video game in which the player controls a Ferrari Testarossa 
    convertible from a third-person rear perspective. The camera is placed near the ground, simulating 
    a Ferrari driver's position and limiting the player's view into the distance. The road curves, 
    crests, and dips, which increases the challenge by obscuring upcoming obstacles such as traffic 
    that the player must avoid. The object of the game is to reach the finish line against a timer.
    The game world is divided into multiple stages that each end in a checkpoint, and reaching the end 
    of a stage provides more time. Near the end of each stage, the track forks to give the player a 
    choice of routes leading to five final destinations. The destinations represent different 
    difficulty levels and each conclude with their own ending scene, among them the Ferrari breaking 
    down or being presented a trophy.
""", Metadata.from("gameName", "Out Run"));
Response&lt;Embedding&gt; response2 = model.embed(game2);<p>Wenn Sie diesen Code ausführen möchten, sehen Sie sich bitte die Klasse <a href="https://github.com/dadoonet/langchain4j-demo/blob/main/src/test/java/fr/pilato/demo/Step5EmbedddingsTest.java">Step5EmbedddingsTest.java</a> an.</p><h2>Elasticsearch hinzufügen, um unsere Vektoren zu speichern</h2><p>LangChain4j bietet einen In-Memory-Embedding-Speicher. Dies ist nützlich, um einfache Tests durchzuführen:</p>EmbeddingStore&lt;TextSegment&gt; embeddingStore = new InMemoryEmbeddingStore&lt;&gt;();
embeddingStore.add(response1.content(), game1);
embeddingStore.add(response2.content(), game2);<p>Bei deutlich größeren Datensätzen funktioniert das natürlich nicht, da dieser Datenspeicher alles im Arbeitsspeicher ablegt und wir auf unseren Servern nicht über unbegrenzten Speicherplatz verfügen. Wir könnten unsere Einbettungen also stattdessen in Elasticsearch speichern, das per Definition "elastisch" ist und mit Ihren Daten skalieren kann. Dazu fügen wir Elasticsearch zu unserem Projekt hinzu:</p>&lt;dependency&gt;
  &lt;groupId&gt;dev.langchain4j&lt;/groupId&gt;
  &lt;artifactId&gt;langchain4j-elasticsearch&lt;/artifactId&gt;
  &lt;version&gt;${langchain4j.version}&lt;/version&gt;
&lt;/dependency&gt;

&lt;dependency&gt;
  &lt;groupId&gt;org.testcontainers&lt;/groupId&gt;
  &lt;artifactId&gt;elasticsearch&lt;/artifactId&gt;
  &lt;version&gt;1.20.1&lt;/version&gt;
  &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;<p>Wie Sie bemerkt haben, haben wir dem Projekt auch das Elasticsearch TestContainers-Modul hinzugefügt, sodass wir eine Elasticsearch-Instanz aus unseren Tests heraus starten können:</p>// Create the elasticsearch container
ElasticsearchContainer container =
  new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:8.15.0")
    .withPassword("changeme");

// Start the container. This step might take some time...
container.start();

// As we don't want to make our TestContainers code more complex than
// needed, we will use login / password for authentication.
// But note that you can also use API keys which is preferred.
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme"));

// Create a low level Rest client which connects to the elasticsearch container.
client = RestClient.builder(HttpHost.create("https://" + container.getHttpHostAddress()))
  .setHttpClientConfigCallback(httpClientBuilder -&gt; {
    httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
    httpClientBuilder.setSSLContext(container.createSslContextFromCa());
    return httpClientBuilder;
  })
  .build();

// Check the cluster is running
client.performRequest(new Request("GET", "/"));<p>Um Elasticsearch als Einbettungsspeicher zu verwenden, müssen Sie „nur“ vom LangChain4j-In-Memory-Datenspeicher zum Elasticsearch-Datenspeicher wechseln:</p>EmbeddingStore&lt;TextSegment&gt; embeddingStore =
  ElasticsearchEmbeddingStore.builder()
    .restClient(client)
    .build();
embeddingStore.add(response1.content(), game1);
embeddingStore.add(response2.content(), game2);<p>Dadurch werden Ihre Vektoren in Elasticsearch in einem <code>default</code> -Index gespeichert. Sie können den Indexnamen auch in einen aussagekräftigeren Namen ändern:</p>EmbeddingStore&lt;TextSegment&gt; embeddingStore =
  ElasticsearchEmbeddingStore.builder()
    .indexName("games")
    .restClient(client)
    .build();
embeddingStore.add(response1.content(), game1);
embeddingStore.add(response2.content(), game2);<p>Wenn Sie diesen Code ausführen möchten, sehen Sie sich bitte die Klasse <a href="https://github.com/dadoonet/langchain4j-demo/blob/main/src/test/java/fr/pilato/demo/Step6ElasticsearchEmbedddingsTest.java">Step6ElasticsearchEmbedddingsTest.java</a> an.</p><h2>Suche nach ähnlichen Vektoren</h2><p>Um nach ähnlichen Vektoren zu suchen, müssen wir zunächst unsere Frage mithilfe des gleichen Modells, das wir zuvor verwendet haben, in eine Vektordarstellung umwandeln. Das haben wir schon gemacht, also ist es nicht schwer, das noch einmal zu tun. Beachten Sie, dass wir in diesem Fall die Metadaten nicht benötigen:</p>String question = "I want to pilot a car";
Embedding questionAsVector = model.embed(question).content();<p>Wir können mit dieser Repräsentation unserer Frage eine Suchanfrage erstellen und den Embedding-Speicher bitten, die ersten Top-Vektoren zu finden:</p>EmbeddingSearchResult&lt;TextSegment&gt; result = embeddingStore.search(
  EmbeddingSearchRequest.builder()
    .queryEmbedding(questionAsVector)
    .build());<p>Wir können die Ergebnisse nun durchlaufen und einige Informationen ausgeben, wie zum Beispiel den Spielnamen, der aus den Metadaten stammt, und die Punktzahl:</p>result.matches().forEach(m -&gt; Logger.info("{} - score [{}]",
  m.embedded().metadata().getString("gameName"), m.score()));<p>Wie zu erwarten, ist „Out Run“ der erste Treffer:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7ca0dcfdb1a9c94f/6a170291cf4f256938b2d017/140b6a962e5edbb4870419250e30bfb815b0d73e-640x480.gif" alt="Out Run" />Out Run - score [0.86672974]
The Secret of Monkey Island - score [0.85569763]<p>Wenn Sie diesen Code ausführen möchten, sehen Sie sich bitte die Klasse <a href="https://github.com/dadoonet/langchain4j-demo/blob/9ec4b1d4c7c69821f143ddf272bbfed273c67b14/src/test/java/fr/pilato/demo/Step7SearchForVectorsTest.java#L110-L129">Step7SearchForVectorsTest.java</a> an. </p><h2>Hinter den Kulissen</h2><p>Die Standardkonfiguration für den Elasticsearch Embedding Store verwendet im Hintergrund die <a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.15/query-dsl-knn-query.html">approximative kNN-Abfrage</a> .</p>POST games/_search
{
  "query" : {
    "knn": {
      "field": "vector",
      "query_vector": [-0.019137882, /* ... */, -0.0148779955]
    }
  }
}<p>Dies könnte jedoch geändert werden, indem dem Embedding-Speicher eine andere Konfiguration (<code>ElasticsearchConfigurationScript</code>) als die Standardkonfiguration (<code>ElasticsearchConfigurationKnn</code>) bereitgestellt wird:</p>EmbeddingStore&lt;TextSegment&gt; embeddingStore =
  ElasticsearchEmbeddingStore.builder()
    .configuration(ElasticsearchConfigurationScript.builder().build())
    .indexName("games")
    .restClient(client)
    .build();<p>Die <code>ElasticsearchConfigurationScript</code> -Implementierung führt im Hintergrund eine <a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.15/query-dsl-script-score-query.html"><code>script_score</code></a> <a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.15/query-dsl-script-score-query.html">-Abfrage</a> mit einer <a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.15/query-dsl-script-score-query.html#vector-functions-cosine"><code>cosineSimilarity</code></a> <a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.15/query-dsl-script-score-query.html#vector-functions-cosine">-Funktion</a> aus.</p><p>Grundsätzlich gilt beim Aufruf:</p>EmbeddingSearchResult&lt;TextSegment&gt; result = embeddingStore.search(
  EmbeddingSearchRequest.builder()
    .queryEmbedding(questionAsVector)
    .build());<p>Dies nennt man nun:</p>POST games/_search
{
  "query": {
    "script_score": {
      "script": {
        "source": "(cosineSimilarity(params.query_vector, 'vector') + 1.0) / 2",
        "params": {
          "queryVector": [-0.019137882, /* ... */, -0.0148779955]
        }
      }
    }
  }
}<p>In diesem Fall ändert sich das Ergebnis hinsichtlich der "Ordnung" nicht, sondern nur die Punktzahl wird angepasst, da der <code>cosineSimilarity</code> -Aufruf keine Näherung verwendet, sondern den Kosinus für jeden der übereinstimmenden Vektoren berechnet:</p>Out Run - score [0.871952]
The Secret of Monkey Island - score [0.86380446]<p>Wenn Sie diesen Code ausführen möchten, sehen Sie sich bitte die Klasse <a href="https://github.com/dadoonet/langchain4j-demo/blob/9ec4b1d4c7c69821f143ddf272bbfed273c67b14/src/test/java/fr/pilato/demo/Step7SearchForVectorsTest.java#L132-L155">Step7SearchForVectorsTest.java</a> an.</p><h2>Fazit</h2><p>Wir haben behandelt, wie einfach Sie Einbettungen aus Ihrem Text generieren können und wie Sie die nächsten Nachbarn in Elasticsearch speichern und suchen können, und zwar mit zwei verschiedenen Ansätzen:</p><ul><li><p>Verwendung der approximativen und schnellen <code>knn</code> -Abfrage mit der Standardoption <code>ElasticsearchConfigurationKnn</code></p></li><li><p>Verwendung der exakten, aber langsameren <code>script_score</code> -Abfrage mit der <code>ElasticsearchConfigurationScript</code> -Option</p></li></ul><p>Im nächsten Schritt geht es darum, eine vollständige RAG-Anwendung zu entwickeln, basierend auf dem, was wir hier gelernt haben.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/langchain4j-elasticsearch-embedding-store</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/langchain4j-elasticsearch-embedding-store</guid>
    <category><![CDATA[Java]]></category>
    <category><![CDATA[KI]]></category>
    <category><![CDATA[Vektordatenbank]]></category>
    <dc:creator><![CDATA[David Pilato]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfc873b86c76d1798/6a170293acf088f666be99b3/abd8a4a809064101c037af66b87f28e5ecde03b0-1474x645.jpg" length="0" type="image/jpeg"/>
    <pubDate>Tue, 08 Oct 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Wir stellen LangChain4j vor, um die LLM-Integration in Java-Anwendungen zu vereinfachen.]]></title>
    <description><![CDATA[LangChain4j (LangChain für Java) ist ein leistungsstarkes Toolset, mit dem Sie Ihre RAG-Anwendung in reinem Java erstellen können.]]></description>
    <content:encoded><![CDATA[<p>Das <a href="https://docs.langchain4j.dev/">LangChain4j-Framework</a> wurde 2023 mit <a href="https://github.com/langchain4j/langchain4j/blob/main/README.md#introduction">folgendem Ziel</a> entwickelt:</p>Das Ziel von LangChain4j ist es, die Integration von LLMs in Java-Anwendungen zu vereinfachen.<p>LangChain4j bietet eine standardisierte Methode, um:</p><ul><li><p>Einbettungen (Vektoren) aus einem gegebenen Inhalt erstellen, beispielsweise aus einem Text</p></li><li><p>Einbettungen in einem Einbettungsspeicher speichern</p></li><li><p>Suche nach ähnlichen Vektoren im Einbettungsspeicher</p></li><li><p>mit LLMs sprechen</p></li><li><p>Nutzen Sie die Chat-Speicherfunktion, um sich an den Kontext einer Diskussion mit einem LLM zu erinnern.</p></li></ul><p>Diese Liste ist nicht vollständig, und die LangChain4j-Community implementiert ständig neue Funktionen.</p><p>Dieser Beitrag behandelt die ersten Hauptbestandteile des Frameworks.</p><h2>Hinzufügen von LangChain4j OpenAI zu unserem Projekt</h2><p>Wie bei allen Java-Projekten ist es einfach eine Frage der Abhängigkeiten. Hier verwenden wir Maven, aber das gleiche Ergebnis ließe sich auch mit jedem anderen Abhängigkeitsmanager erzielen.</p><p>Als ersten Schritt für das Projekt, das wir hier aufbauen wollen, werden wir OpenAI verwenden, daher müssen wir lediglich das <code>langchain4j-open-ai</code> -Artefakt hinzufügen:</p>&lt;properties&gt;
  &lt;langchain4j.version&gt;0.34.0&lt;/langchain4j.version&gt;
&lt;/properties&gt;

&lt;dependencies&gt;
  &lt;dependency&gt;
    &lt;groupId&gt;dev.langchain4j&lt;/groupId&gt;
    &lt;artifactId&gt;langchain4j-open-ai&lt;/artifactId&gt;
    &lt;version&gt;${langchain4j.version}&lt;/version&gt;
  &lt;/dependency&gt;
&lt;/dependencies&gt;
<p>Für den restlichen Code verwenden wir entweder unseren eigenen API-Schlüssel, den Sie durch die Registrierung eines Kontos bei <a href="https://platform.openai.com/signup/">OpenAI</a> erhalten, oder den vom LangChain4j-Projekt bereitgestellten Schlüssel, der jedoch nur zu Demonstrationszwecken dient:</p>static String getOpenAiApiKey() {
  String apiKey = System.getenv(API_KEY_ENV_NAME);
  if (apiKey == null || apiKey.isEmpty()) {
    Logger.warn("Please provide your own key instead using [{}] env variable", API_KEY_ENV_NAME);
    return "demo";
  }
  return apiKey;
}
<p>Wir können nun eine Instanz unseres ChatLanguageModel erstellen:</p>ChatLanguageModel model = OpenAiChatModel.withApiKey(getOpenAiApiKey());
<p>Und schließlich können wir eine einfache Frage stellen und die Antwort erhalten:</p>String answer = model.generate("Who is Thomas Pesquet?");
Logger.info("Answer is: {}", answer);
<p>Die gegebene Antwort könnte etwa so lauten:</p>Thomas Pesquet is a French aerospace engineer, pilot, and European Space Agency astronaut.
He was selected as a member of the European Astronaut Corps in 2009 and has since completed 
two space missions to the International Space Station, including serving as a flight engineer 
for Expedition 50/51 in 2016-2017. Pesquet is known for his contributions to scientific 
research and outreach activities during his time in space.
<p>Wenn Sie diesen Code ausführen möchten, sehen Sie sich bitte die Klasse <a href="https://github.com/dadoonet/langchain4j-demo/blob/main/src/test/java/fr/pilato/demo/Step1AiChatTest.java">Step1AiChatTest.java</a> an.</p><h2>Mehr Kontext mit langchain4j</h2><p>Fügen wir das <code>langchain4j</code> -Artefakt hinzu:</p>&lt;dependency&gt;
  &lt;groupId&gt;dev.langchain4j&lt;/groupId&gt;
  &lt;artifactId&gt;langchain4j&lt;/artifactId&gt;
  &lt;version&gt;${langchain4j.version}&lt;/version&gt;
&lt;/dependency&gt;
<p>Dieses Tool bietet uns einen Werkzeugkasten, der uns dabei helfen kann, eine fortgeschrittenere LLM-Integration für unseren Assistenten zu entwickeln. Hier erstellen wir einfach eine <code>Assistant</code> -Schnittstelle, die die <code>chat</code> -Methode bereitstellt, welche automatisch die zuvor definierte <code>ChatLanguageModel</code> aufruft:</p>interface Assistant {
  String chat(String userMessage);
}
<p>Wir müssen lediglich die Klasse LangChain4j <code>AiServices</code> bitten, eine Instanz für uns zu erstellen:</p>Assistant assistant = AiServices.create(Assistant.class, model);
<p>Und rufen Sie dann die Methode <code>chat(String)</code> auf:</p>String answer = assistant.chat("Who is Thomas Pesquet?");
Logger.info("Answer is: {}", answer);
<p>Das System verhält sich genauso wie zuvor. Warum also haben wir den Code geändert? Erstens ist es eleganter, aber darüber hinaus können Sie dem LLM nun mithilfe einfacher Annotationen Anweisungen geben:</p>interface Assistant {
  @SystemMessage("Please answer in a funny way.")
  String chat(String userMessage);
}
<p>Dies ergibt nun Folgendes:</p>Ah, Thomas Pesquet is actually a super secret spy disguised as an astronaut! 
He's out there in space fighting aliens and saving the world one spacewalk at a time. 
Or maybe he's just a really cool French astronaut who has been to the International 
Space Station. But my spy theory is much more exciting, don't you think?
<p>Wenn Sie diesen Code ausführen möchten, sehen Sie sich bitte die Klasse <a href="https://github.com/dadoonet/langchain4j-demo/blob/main/src/test/java/fr/pilato/demo/Step2AssistantTest.java">Step2AssistantTest.java</a> an.</p><h2>Wechsel zu einem anderen LLM: langchain4j-ollama</h2><p>Wir können das großartige <a href="https://ollama.com/">Ollama-Projekt</a> nutzen. Es ist hilfreich, einen LLM lokal auf Ihrem Rechner auszuführen.</p><p>Fügen wir das <code>langchain4j-ollama</code> -Artefakt hinzu:</p>&lt;dependency&gt;
  &lt;groupId&gt;dev.langchain4j&lt;/groupId&gt;
  &lt;artifactId&gt;langchain4j-ollama&lt;/artifactId&gt;
  &lt;version&gt;${langchain4j.version}&lt;/version&gt;
&lt;/dependency&gt;
<p>Da wir den Beispielcode mithilfe von Tests ausführen, fügen wir unserem Projekt <a href="https://java.testcontainers.org/">Testcontainers</a> hinzu:</p>&lt;dependency&gt;
  &lt;groupId&gt;org.testcontainers&lt;/groupId&gt;
  &lt;artifactId&gt;ollama&lt;/artifactId&gt;
  &lt;version&gt;1.20.1&lt;/version&gt;
  &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
<p>Wir können jetzt Docker-Container starten/stoppen:</p>static String MODEL_NAME = "mistral";
static String DOCKER_IMAGE_NAME = "langchain4j/ollama-" + MODEL_NAME + ":latest";

static OllamaContainer ollama = new OllamaContainer(
  DockerImageName.parse(DOCKER_IMAGE_NAME).asCompatibleSubstituteFor("ollama/ollama"));

@BeforeAll
public static void setup() {
  ollama.start();
}

@AfterAll
public static void teardown() {
  ollama.stop();
}
<p>Wir müssen lediglich das <code>model</code> -Objekt in ein <code>OllamaChatModel</code> ändern, anstatt des zuvor verwendeten <code>OpenAiChatModel</code> :</p>OllamaChatModel model = OllamaChatModel.builder()
  .baseUrl(ollama.getEndpoint())
  .modelName(MODEL_NAME)
  .build();
<p>Beachten Sie, dass das Abrufen des Bildes mit dem zugehörigen Modell einige Zeit in Anspruch nehmen kann, aber nach einer Weile erhalten Sie die Antwort:</p>Oh, Thomas Pesquet, the man who single-handedly keeps the French space program running 
while sipping on his crisp rosé and munching on a baguette! He's our beloved astronaut 
with an irresistible accent that makes us all want to learn French just so we can 
understand him better. When he's not floating in space, he's probably practicing his 
best "je ne sais quoi" face for the next family photo. Vive le Thomas Pesquet! 
🚀🌍🇫🇷 #FrenchSpaceHero
<h2>Besser mit Speicher</h2><p>Wenn wir mehrere Fragen stellen, merkt sich das System standardmäßig nicht die vorherigen Fragen und Antworten. Wenn wir also nach der ersten Frage „Wann wurde er geboren?“ fragen, Unsere Anwendung wird folgende Fragen beantworten:</p>Oh, you're asking about this legendary figure from history, huh? Well, let me tell 
you a hilarious tale! He was actually born on Leap Year's Day, but only every 400 
years! So, do the math... if we count backwards from 2020 (which is also a leap year), 
then he was born in... *drumroll please* ...1600! Isn't that a hoot? But remember 
folks, this is just a joke, and historical records may vary.
<p>Das ist Unsinn. Stattdessen sollten wir <a href="https://docs.langchain4j.dev/tutorials/chat-memory">Chat Memory</a> verwenden:</p>ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);
Assistant assistant = AiServices.builder(Assistant.class)
  .chatLanguageModel(model)
  .chatMemory(chatMemory)
  .build();
<p>Die erneute Beantwortung derselben Fragen liefert nun ein aussagekräftiges Ergebnis:</p>Oh, Thomas Pesquet, the man who was probably born before sliced bread but after dinosaurs! 
You know, around the time when people started putting wheels on suitcases and calling it 
a revolution. So, roughly speaking, he came into this world somewhere in the late 70s or 
early 80s, give or take a year or two - just enough time for him to grow up, become an 
astronaut, and make us all laugh with his space-aged antics! Isn't that a hoot? 
*laughs maniacally*
<h2>Fazit</h2><p>Im <a href="https://www.elastic.co/search-labs/blog/langchain4j-elasticsearch-embedding-store">nächsten Beitrag</a> werden wir herausfinden, wie wir mithilfe von Elasticsearch als Einbettungsspeicher Fragen an unseren privaten Datensatz stellen können. Das wird uns die Möglichkeit geben, unsere Anwendungssuche auf die nächste Stufe zu heben.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/langchain4j-llm-integration-introduction</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/langchain4j-llm-integration-introduction</guid>
    <category><![CDATA[Java]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[David Pilato]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0435ed6d14579089/6a17e79ae8fbce7e433a192f/cf129b8b25fbe7204e2adca8fca5fec04207f096-720x720.png" length="0" type="image/png"/>
    <pubDate>Mon, 23 Sep 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Fortgeschrittene RAG-Techniken Teil 2: Abfragen und Testen]]></title>
    <description><![CDATA[Diskussion und Umsetzung von Techniken zur Steigerung der RAG-Leistung. Teil 2 von 2, mit Schwerpunkt auf Abfragen und Tests einer erweiterten RAG-Pipeline.]]></description>
    <content:encoded><![CDATA[<p><em>Der gesamte Code ist </em><a href="https://github.com/elastic/elasticsearch-labs/tree/advanced-rag-techniques/supporting-blog-content/advanced-rag-techniques"><em>im Searchlabs-Repository im Branch advanced-rag-techniques zu</em></a><em> finden.</em></p><p>Willkommen zu Teil 2 unseres Artikels über fortgeschrittene RAG-Techniken! Im <a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1">ersten Teil dieser Serie</a> haben wir die Datenverarbeitungskomponenten der erweiterten RAG-Pipeline eingerichtet, besprochen und implementiert:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9a4691874a19d8da/6a170b3f47d49c99f22d8a24/72b51ba2ae5e5977b56e5b915674753d6cfd0e56-1440x840.jpg" alt="Fortschrittliche RAG-Pipeline" /><p>In diesem Teil werden wir mit dem Abfragen und Testen unserer Implementierung fortfahren. Kommen wir gleich zur Sache!</p><h3>Inhaltsverzeichnis</h3><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#searching-and-retrieving,-generating-answers">Suchen und Abrufen, Generieren von Antworten</a></p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#enriching-queries-with-synonyms">Anreicherung von Suchanfragen mit Synonymen</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#hyde-hypothetical-document-embedding">HyDE (Hypothetische Dokumenteneinbettung)</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#hybrid-search">Hybrid Search</a></p></li></ul></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#experiments">Experimente</a></p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#summary-of-results">Zusammenfassung der Ergebnisse</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#test-1-who-audits-elastic">Test 1: Wer prüft Elastic?</a></p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#advancedrag">AdvancedRAG</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#simplerag">SimpleRAG</a></p></li></ul></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#test-2--total-revenue-2023">Test 2: Gesamtumsatz 2023</a></p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#advancedrag-1">AdvancedRAG</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#simplerag-1">SimpleRAG</a></p></li></ul></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#test-3-what-product-does-growth-primarily-depend-on-how-much">Test 3: Von welchem Produkt hängt das Wachstum primär ab? Wie viel?</a></p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#advancedrag-2">AdvancedRAG</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#simplerag-2">SimpleRAG</a></p></li></ul></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#test-4-describe-employee-benefit-plan">Test 4: Beschreiben Sie den Mitarbeitervergütungsplan</a></p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#advancedrag-3">AdvancedRAG</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#simplerag-3">SimpleRAG</a></p></li></ul></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#test-5-which-companies-did-elastic-acquire">Test 5: Welche Unternehmen hat Elastic übernommen?</a></p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#advancedrag-4">AdvancedRAG</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#simplerag-4">SimpleRAG</a></p></li></ul></li></ul></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#conclusion">Fazit</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#appendix">Anhang</a></p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#prompts">Eingabeaufforderungen</a></p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#rag-question-answering-prompt">RAG-Frage-Antwort-Aufforderung</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#elastic-query-generator-prompt">Eingabeaufforderung für den Elastic-Abfragegenerator</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#potential-questions-generator-prompt">Mögliche Fragen zur Generierung von Anregungen</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#hyde-generator-prompt">HyDE-Generator-Eingabeaufforderung</a></p></li></ul></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#sample-hybrid-search-query">Beispiel einer hybriden Suchanfrage</a></p></li></ul></li></ul><h2>Suchen und Abrufen, Generieren von Antworten</h2><p>Beginnen wir mit unserer ersten Frage, idealerweise einer Information, die hauptsächlich im Jahresbericht zu finden ist. Wie wäre es mit:</p>Who audits Elastic?"
<p>Nun wenden wir einige unserer Techniken an, um die Abfrage zu verbessern.</p><h3>Anreicherung von Suchanfragen mit Synonymen</h3><p>Zunächst sollten wir die Vielfalt der Abfrageformulierungen erhöhen und sie in eine Form bringen, die sich leicht in eine Elasticsearch-Abfrage verarbeiten lässt. Wir werden GPT-4o zur Hilfe nehmen, um die Abfrage in eine Liste von OR-Klauseln umzuwandeln. Schreiben wir diese Aufgabenstellung auf:</p>
ELASTIC_SEARCH_QUERY_GENERATOR_PROMPT = '''
You are an AI assistant specialized in generating Elasticsearch query strings. Your task is to create the most effective query string for the given user question. This query string will be used to search for relevant documents in an Elasticsearch index.

Guidelines:
1. Analyze the user's question carefully.
2. Generate ONLY a query string suitable for Elasticsearch's match query.
3. Focus on key terms and concepts from the question.
4. Include synonyms or related terms that might be in relevant documents.
5. Use simple Elasticsearch query string syntax if helpful (e.g., OR, AND).
6. Do not use advanced Elasticsearch features or syntax.
7. Do not include any explanations, comments, or additional text.
8. Provide only the query string, nothing else.

For the question "What is Clickthrough Data?", we would expect a response like:
clickthrough data OR click-through data OR click through rate OR CTR OR user clicks OR ad clicks OR search engine results OR web analytics

AND operator is not allowed. Use only OR.

User Question:
[The user's question will be inserted here]

Generate the Elasticsearch query string:
'''
<p>Bei Anwendung auf unsere Anfrage generiert GPT-4o Synonyme der Basisanfrage und verwandtes Vokabular.</p>'audits elastic OR 
elasticsearch audits OR 
elastic auditor OR 
elasticsearch auditor OR 
elastic audit firm OR 
elastic audit company OR 
elastic audit organization OR 
elastic audit service'
<p>In der Klasse <code>ESQueryMaker</code> habe ich eine Funktion definiert, um die Abfrage aufzuteilen:</p>def parse_or_query(self, query_text: str) -&gt; List[str]:
    # Split the query by 'OR' and strip whitespace from each term
    # This converts a string like "term1 OR term2 OR term3" into a list ["term1", "term2", "term3"]
    return [term.strip() for term in query_text.split(' OR ')]
<p>Seine Aufgabe besteht darin, diese Kette von ODER-Klauseln in eine Liste von Begriffen aufzuteilen, um uns eine Mehrfachübereinstimmung unserer wichtigsten Dokumentfelder zu ermöglichen:</p>["original_text", 'keyphrases', 'potential_questions', 'entities']
<p>Schließlich komme ich zu folgender Anfrage:</p> 'query': {
    'bool': {
        'must': [
            {
                'multi_match': {
                'query': 'audits Elastic Elastic auditing Elastic audit process Elastic compliance Elastic security audit Elasticsearch auditing Elasticsearch compliance Elasticsearch security audit',
                'fields': [
                    'original_text',
                'keyphrases',
                'potential_questions',
                'entities'
                ],
                'type': 'best_fields',
                'operator': 'or'
                }
            }
      ]
<p>Dies deckt wesentlich mehr Aspekte ab als die ursprüngliche Anfrage und verringert hoffentlich das Risiko, ein Suchergebnis zu verpassen, weil wir ein Synonym vergessen haben. Aber wir können mehr tun.</p><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#table-of-contents">Zurück nach oben</a></p><h3>HyDE (Hypothetische Dokumenteneinbettung)</h3><p>Lassen Sie uns GPT-4o erneut einsetzen, diesmal zur Implementierung <a href="https://arxiv.org/abs/2212.10496">von HyDE</a>.</p><p>Die Grundidee von HyDE besteht darin, ein hypothetisches Dokument zu generieren – also ein Dokument, das wahrscheinlich die Antwort auf die ursprüngliche Anfrage enthält. Die sachliche Richtigkeit oder Genauigkeit des Dokuments ist nicht von Belang. Vor diesem Hintergrund formulieren wir nun die folgende Aufgabenstellung:</p>HYDE_DOCUMENT_GENERATOR_PROMPT = '''
You are an AI assistant specialized in generating hypothetical documents based on user queries. Your task is to create a detailed, factual document that would likely contain the answer to the user's question. This hypothetical document will be used to enhance the retrieval process in a Retrieval-Augmented Generation (RAG) system.

Guidelines:
1. Carefully analyze the user's query to understand the topic and the type of information being sought.
2. Generate a hypothetical document that:
   a. Is directly relevant to the query
   b. Contains factual information that would answer the query
   c. Includes additional context and related information
   d. Uses a formal, informative tone similar to an encyclopedia or textbook entry
3. Structure the document with clear paragraphs, covering different aspects of the topic.
4. Include specific details, examples, or data points that would be relevant to the query.
5. Aim for a document length of 200-300 words.
6. Do not use citations or references, as this is a hypothetical document.
7. Avoid using phrases like "In this document" or "This text discusses" - write as if it's a real, standalone document.
8. Do not mention or refer to the original query in the generated document.
9. Ensure the content is factual and objective, avoiding opinions or speculative information.
10. Output only the generated document, without any additional explanations or meta-text.

User Question:
[The user's question will be inserted here]

Generate a hypothetical document that would likely contain the answer to this query:
'''
<p>Da die Vektorsuche typischerweise mit der Kosinusvektorähnlichkeit arbeitet, besteht die Prämisse von HyDE darin, dass wir bessere Ergebnisse erzielen können, indem wir Dokumente mit Dokumenten abgleichen, anstatt Anfragen mit Dokumenten abzugleichen.</p><p>Uns geht es um Struktur, Ablauf und Terminologie. Nicht so sehr die Fakten. GPT-4o erzeugt ein HyDE-Dokument wie dieses:</p>'Elastic N.V., the parent company of Elastic, the organization known for developing Elasticsearch, is subject to audits to ensure financial accuracy, 
regulatory compliance, and the integrity of its financial statements. The auditing of Elastic N.V. is typically conducted by an external, 
independent auditing firm. This is common practice for publicly traded companies to provide stakeholders with assurance regarding the company\'s 
financial position and operations.\n\nThe primary external auditor for Elastic is the audit firm Ernst &amp; Young LLP (EY). Ernst &amp; Young is one of the 
four largest professional services networks in the world, commonly referred to as the "Big Four" audit firms. These firms handle a substantial number 
of audits for major corporations around the globe, ensuring adherence to generally accepted accounting principles (GAAP) and international financial 
reporting standards (IFRS).\n\nThe audit process conducted by EY involves several steps. Initially, the auditors perform a risk assessment to identify 
areas where misstatements due to error or fraud could occur. They then design audit procedures to test the accuracy and completeness of financial statements,
 which include examining financial transactions, assessing internal controls, and reviewing compliance with relevant laws and regulations. Upon completion of 
 the audit, Ernst &amp; Young issues an audit report, which includes the auditor’s opinion on whether the financial statements are free from material misstatement 
 and are presented fairly in accordance with the applicable financial reporting framework.\n\nIn addition to external audits by firms like Ernst &amp; Young, 
 Elastic may also be subject to internal audits. Internal audits are performed by the company’s own internal auditors to evaluate the effectiveness of internal 
 controls, risk management, and governance processes.\n\nOverall, the auditing process plays a crucial role in maintaining the transparency and reliability of 
 Elastic\'s financial information, providing confidence to investors, regulators, and other stakeholders.'
<p>Es sieht ziemlich glaubwürdig aus, wie der ideale Kandidat für die Art von Dokumenten, die wir indexieren möchten. Wir werden dies einbetten und für die hybride Suche verwenden.</p><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#table-of-contents">Zurück nach oben</a></p><h3>Hybrid Search</h3><p>Dies ist der Kern unserer Suchlogik. Unsere lexikalische Suchkomponente besteht aus den generierten OR-Klauselzeichenketten. Unsere dichte Vektorkomponente wird das eingebettete HyDE-Dokument (auch Suchvektor genannt) sein. Wir verwenden KNN, um effizient mehrere Kandidatendokumente zu identifizieren, die unserem Suchvektor am nächsten liegen. Unsere lexikalische Suchkomponente nennen wir standardmäßig <em>Scoring mit TF-IDF und BM25</em> . Schließlich werden die lexikalischen und dichten Vektorwerte unter Verwendung des von <a href="https://arxiv.org/abs/2407.01219">Wang et al</a>. empfohlenen Verhältnisses von 30/70 kombiniert.</p>def hybrid_vector_search(self, index_name: str, query_text: str, query_vector: List[float], 
                         text_fields: List[str], vector_field: str, 
                         num_candidates: int = 100, num_results: int = 10) -&gt; Dict:
    """
    Perform a hybrid search combining text-based and vector-based similarity.

    Args:
        index_name (str): The name of the Elasticsearch index to search.
        query_text (str): The text query string, which may contain 'OR' separated terms.
        query_vector (List[float]): The query vector for semantic similarity search.
        text_fields (List[str]): List of text fields to search in the index.
        vector_field (str): The name of the field containing document vectors.
        num_candidates (int): Number of candidates to consider in the initial KNN search.
        num_results (int): Number of final results to return.

    Returns:
        Dict: A tuple containing the Elasticsearch response and the search body used.
    """
    try:
        # Parse the query_text into a list of individual search terms
        # This splits terms separated by 'OR' and removes any leading/trailing whitespace
        query_terms = self.parse_or_query(query_text)

        # Construct the search body for Elasticsearch
        search_body = {
            # KNN search component for vector similarity
            "knn": {
                "field": vector_field,  # The field containing document vectors
                "query_vector": query_vector,  # The query vector to compare against
                "k": num_candidates,  # Number of nearest neighbors to retrieve
                "num_candidates": num_candidates  # Number of candidates to consider in the KNN search
            },
            "query": {
                "bool": {
                    # The 'must' clause ensures that matching documents must satisfy this condition
                    # Documents that don't match this clause are excluded from the results
                    "must": [
                        {
                            # Multi-match query to search across multiple text fields
                            "multi_match": {
                                "query": " ".join(query_terms),  # Join all query terms into a single space-separated string
                                "fields": text_fields,  # List of fields to search in
                                "type": "best_fields",  # Use the best matching field for scoring
                                "operator": "or"  # Match any of the terms (equivalent to the original OR query)
                            }
                        }
                    ],
                    # The 'should' clause boosts relevance but doesn't exclude documents
                    # It's used here to combine vector similarity with text relevance
                    "should": [
                        {
                            # Custom scoring using a script to combine vector and text scores
                            "script_score": {
                                "query": {"match_all": {}},  # Apply this scoring to all documents that matched the 'must' clause
                                "script": {
                                    # Script to combine vector similarity and text relevance
                                    "source": """
                                    # Calculate vector similarity (cosine similarity + 1)
                                    # Adding 1 ensures the score is always positive
                                    double vector_score = cosineSimilarity(params.query_vector, params.vector_field) + 1.0;
                                    # Get the text-based relevance score from the multi_match query
                                    double text_score = _score;
                                    # Combine scores: 70% vector similarity, 30% text relevance
                                    # This weighting can be adjusted based on the importance of semantic vs keyword matching
                                    return 0.7 * vector_score + 0.3 * text_score;
                                    """,
                                    # Parameters passed to the script
                                    "params": {
                                        "query_vector": query_vector,  # Query vector for similarity calculation
                                        "vector_field": vector_field  # Field containing document vectors
                                    }
                                }
                            }
                        }
                    ]
                }
            }
        }

        # Execute the search request against the Elasticsearch index
        response = self.conn.search(index=index_name, body=search_body, size=num_results)
        # Log the successful execution of the search for monitoring and debugging
        logger.info(f"Hybrid search executed on index: {index_name} with text query: {query_text}")
        # Return both the response and the search body (useful for debugging and result analysis)
        return response, search_body
    except Exception as e:
        # Log any errors that occur during the search process
        logger.error(f"Error executing hybrid search on index: {index_name}. Error: {e}")
        # Re-raise the exception for further handling in the calling code
        raise e
<p>Schließlich können wir eine RAG-Funktion zusammensetzen. Unser Ampelsystem, von der Anfrage bis zur Antwort, folgt diesem Ablauf:</p><ol><li><p>Konvertiere die Abfrage in OR-Klauseln.</p></li><li><p>Generieren Sie ein HyDE-Dokument und betten Sie es ein.</p></li><li><p>Übergeben Sie beide Werte als Eingaben an die Hybridsuche.</p></li><li><p>Die Top-n-Ergebnisse abrufen und umkehren, sodass die relevanteste Bewertung im Kontextspeicher des LLM als „aktuellste“ angezeigt wird (Reverse Packing). Beispiel für Reverse Packing: Anfrage: „Elasticsearch-Abfrageoptimierungstechniken“. Abgerufene Dokumente (sortiert nach Relevanz): Umgekehrte Reihenfolge für den LLM-Kontext: Durch die Umkehrung der Reihenfolge erscheint die relevanteste Information (1) zuletzt im Kontext und erhält potenziell mehr Aufmerksamkeit vom LLM bei der Antwortgenerierung.</p><ol><li><p>„Verwenden Sie Boolesche Abfragen, um mehrere Suchkriterien effizient zu kombinieren.“</p></li><li><p>„Implementieren Sie Caching-Strategien, um die Antwortzeiten von Abfragen zu verbessern.“</p></li><li><p>„Indexzuordnungen für schnellere Suchleistung optimieren.“</p></li><li><p>„Indexzuordnungen für schnellere Suchleistung optimieren.“</p></li><li><p>„Implementieren Sie Caching-Strategien, um die Antwortzeiten von Abfragen zu verbessern.“</p></li><li><p>„Verwenden Sie Boolesche Abfragen, um mehrere Suchkriterien effizient zu kombinieren.“</p></li></ol></li><li><p>Übergeben Sie den Kontext zur Generierung an das LLM.</p></li></ol>def get_context(index_name, 
                match_query, 
                text_query, 
                fields, 
                num_candidates=100, 
                num_results=20, 
                text_fields=["original_text", 'keyphrases', 'potential_questions', 'entities'], 
                embedding_field="primary_embedding"):

    embedding=embedder.get_embeddings_from_text(text_query)

    results, search_body = es_query_maker.hybrid_vector_search(
        index_name=index_name,
        query_text=match_query,
        query_vector=embedding[0][0],
        text_fields=text_fields,
        vector_field=embedding_field,
        num_candidates=num_candidates,
        num_results=num_results
    )

    # Concatenates the text in each 'field' key of the search result objects into a single block of text.
    context_docs=['\n\n'.join([field+":\n\n"+j['_source'][field] for field in fields]) for j in results['hits']['hits']]

    # Reverse Packing to ensure that the highest ranking document is seen first by the LLM.
    context_docs.reverse()
    return context_docs, search_body

def retrieval_augmented_generation(query_text):
    match_query= gpt4o.generate_query(query_text)
    fields=['original_text']

    hyde_document=gpt4o.generate_HyDE(query_text)

    context, search_body=get_context(index_name, match_query, hyde_document, fields)

    answer= gpt4o.basic_qa(query=query_text, context=context)
    return answer, match_query, hyde_document, context, search_body

<p>Führen wir unsere Abfrage aus und erhalten wir die Antwort:</p>According to the context, Elastic N.V. is audited by an independent registered public accounting firm, PricewaterhouseCoopers (PwC). 
This information is found in the section titled "report of independent registered public accounting firm," which states:

"We have audited the accompanying consolidated balance sheets of Elastic N.V. [...] / s / pricewaterhouseco."
<p>Hübsch. Das ist richtig.</p><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#table-of-contents">Zurück nach oben</a></p><h2>Experimente</h2><p>Jetzt gilt es, eine wichtige Frage zu beantworten. Was hat uns der immense Aufwand und die zusätzliche Komplexität dieser Implementierungen gebracht?</p><p>Lasst uns einen kleinen Vergleich anstellen. Die von uns implementierte RAG-Pipeline im Vergleich zur hybriden Basissuche, ohne die von uns vorgenommenen Verbesserungen. Wir werden eine kleine Testreihe durchführen und sehen, ob wir wesentliche Unterschiede feststellen. Wir werden das soeben implementierte RAG-Schema als AdvancedRAG und die Basispipeline als SimpleRAG bezeichnen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf605c8246989df32/6a1711178b73cbc61d18a11d/8da40067835ab8b4dc12fe52a51a6c26858ad32f-1440x1095.jpg" alt="Einfache RAG-Pipeline" /><h4>Zusammenfassung der Ergebnisse</h4><p>Diese Tabelle fasst die Ergebnisse von fünf Tests beider RAG-Pipelines zusammen. Ich habe die relative Überlegenheit der einzelnen Methoden anhand der Detailtiefe und Qualität der Antworten beurteilt, aber dies ist eine rein subjektive Einschätzung. Die tatsächlichen Antworten sind unterhalb dieser Tabelle zu Ihrer Information aufgeführt. Nach dieser Vorrede schauen wir uns nun an, wie sie abgeschnitten haben!</p><p>SimpleRAG konnte die Fragen 1 und 5 nicht beantworten. AdvancedRAG ging bei den Fragen 2, 3 und 4 wesentlich detaillierter vor. Aufgrund der detaillierteren Antworten beurteilte ich die Qualität der Antworten von AdvancedRAG als besser.</p><p>Prüfen</p><p>Frage</p><p>AdvancedRAG-Leistung</p><p>SimpleRAG Performance</p><p>Erweiterte RAG-Latenz</p><p>SimpleRAG-Latenz</p><p>Gewinner</p><p>1</p><p>Wer prüft Elastic?</p><p>PwC wurde korrekt als Wirtschaftsprüfer identifiziert.</p><p>Der Prüfer konnte nicht identifiziert werden.</p><p>11,6 Sekunden</p><p>4,4 Sekunden</p><p>AdvancedRAG</p><p>2</p><p>Wie hoch waren die Gesamteinnahmen im Jahr 2023?</p><p>Die korrekte Umsatzzahl wurde angegeben. Zusätzliche Kontextinformationen wurden mit Umsatzzahlen aus den Vorjahren hinzugefügt.</p><p>Die korrekte Umsatzzahl wurde angegeben.</p><p>13,3 Sekunden</p><p>2,8 Sekunden</p><p>AdvancedRAG</p><p>3</p><p>Von welchem Produkt hängt das Wachstum primär ab? Wie viel?</p><p>Elastic Cloud wurde korrekt als Haupttreiber identifiziert. Beinhaltete den Gesamtkontext der Einnahmen und detailliertere Informationen.</p><p>Elastic Cloud wurde korrekt als Haupttreiber identifiziert.</p><p>14,1 Sekunden</p><p>12,8 Sekunden</p><p>AdvancedRAG</p><p>4</p><p>Beschreibung des Mitarbeitervergütungsprogramms</p><p>Gab eine umfassende Beschreibung der Altersvorsorgepläne, Gesundheitsprogramme und sonstigen Leistungen. Enthält spezifische Beitragsbeträge für verschiedene Jahre.</p><p>Es wurde ein guter Überblick über die Leistungen gegeben, einschließlich Vergütung, Altersvorsorgepläne, Arbeitsumfeld und das Elastic Cares-Programm.</p><p>26,6 Sekunden</p><p>11,6 Sekunden</p><p>AdvancedRAG</p><p>5</p><p>Welche Unternehmen hat Elastic übernommen?</p><p>Die im Bericht erwähnten kürzlich erfolgten Akquisitionen (CmdWatch, Build Security, Optimyze) wurden korrekt aufgeführt. Es wurden einige Anschaffungsdaten und Kaufpreise angegeben.</p><p>Es konnten keine relevanten Informationen aus dem bereitgestellten Kontext abgerufen werden.</p><p>11,9 Sekunden</p><p>2,7 Sekunden</p><p>AdvancedRAG</p><h4>Test 1: Wer prüft Elastic?</h4><p>AdvancedRAG</p>According to the context, Elastic N.V. is audited by an independent 
registered public accounting firm, PricewaterhouseCoopers (PwC). 
This information is found in the section titled "report of 
independent registered public accounting firm," which states:
"We have audited the accompanying consolidated balance sheets 
of Elastic N.V. [...] / s / pricewaterhouseco."
<p>SimpleRAG</p>According to the provided context, no specific auditing firm 
or company is mentioned as the auditor for Elastic. 
The context provided talks about various features, strengths, 
deployment options, and other details related to Elastic and 
its operations but does not specify which auditing firm is 
responsible for auditing Elastic's financial statements or 
internal controls.
<p><strong>Zusammenfassung</strong>: SimpleRAG hat PwC nicht als Wirtschaftsprüfer identifiziert.</p><p>Okay, das ist tatsächlich ziemlich überraschend. Das sieht nach einem Suchfehler seitens SimpleRAG aus. Es wurden keine Dokumente im Zusammenhang mit der Wirtschaftsprüfung gefunden. Lasst uns den Schwierigkeitsgrad beim nächsten Test etwas reduzieren.</p><h4>Test 2: Gesamtumsatz 2023</h4><p>AdvancedRAG</p>### Total Revenue for 2023

According to the provided context, the total revenue for the 
year ended April 30, 2023, was **$1,068,989,000**. This 
information can be found several times in the provided text. 
Specifically, one part states:

"The following table sets forth our results of operations 
for the periods presented in dollars and as a percentage of 
our total revenue. ... year ended April 30, 2023, ... 
total revenue 1,068,989".

Additionally, it is mentioned here as well:

"For the years ended April 30, 2023, 2022, and 2021, 
representing year-over-year growth of 24% for the year 
ended April 30, 2023... total revenue $1,068,989".

Therefore, the total revenue for 2023 is $1.069 billion.
<p>SimpleRAG</p>According to the context provided, the total revenue for the fiscal year ended April 30, 2023, is:

$1,068,989,000 (or approximately $1.1 billion).
<p><strong>Zusammenfassung</strong>: Beide RAGs haben die richtige Antwort gegeben: 1.068.989.000 US-Dollar Gesamtumsatz im Jahr 2023</p><p>Beide waren genau hier. Es scheint, als ob AdvancedRAG ein breiteres Spektrum an Dokumenten erworben hat. Die Antwort ist sicherlich detaillierter und berücksichtigt auch Informationen aus den Vorjahren. Das war angesichts der von uns vorgenommenen Verbesserungen zu erwarten, aber es ist viel zu früh, um das zu beurteilen.</p><p>Erhöhen wir den Schwierigkeitsgrad.</p><h4>Test 3: Von welchem Produkt hängt das Wachstum primär ab? Wie viel?</h4><p>AdvancedRAG</p>### Product Growth Primarily Depends On:
According to the context, "our revenue is derived primarily from 
subscriptions of search, observability and security built into 
the elastic stack." The document mentions various strategies and 
factors contributing to the company’s growth which include investment 
in "elastic cloud," "elastic stack," and the conversion of free 
users to paid subscribers.

### Quantitative Data:
- **Revenue**: The document states, "Our total revenue was $1.1 billion, 
$862.4 million, and $608.5 million for the years ended April 30, 2023, 
2022, and 2021, respectively."
- **Subscription Revenue**: "Subscriptions accounted for 92%, 93%, 
and 93% of our total revenue for the years ended April 30, 2023, 
2022, and 2021, respectively."
- **Elastic Cloud Contribution**: "For the years ended April 30, 2023, 
2022, and 2021, Elastic Cloud contributed 40%, 35%, and 27% of our 
total revenue, respectively."
- **Customer Growth**: The number of customers increased from 
"over 15,000 as of April 30, 2021," to "approximately 20,200 as of 
April 30, 2023."

### Summary:
Product growth for the company primarily depends on the "Elastic Stack" 
(which includes search, observability, and security solutions) and 
particularly the "Elastic Cloud." The Elastic Cloud's growing contribution 
to revenue highlights its significance, which grew from 27% in 2021 to 40% in 2023.
<p>SimpleRAG</p>According to the provided context, growth primarily depends on **Elastic Cloud**, 
which is described as the company's "family of cloud-based offerings." 
The context also emphasizes the significance of Elastic Cloud in achieving 
the company's long-term growth potential and its role in increasing subscription revenue.

From the context:

- "Increasing adoption of Elastic Cloud... is an important growth opportunity 
for our business. Organizations are increasingly looking for hosted 
deployment alternatives with reduced administrative burdens."
- "We believe that offering Elastic Cloud is important for achieving 
our long-term growth potential, and we expect Elastic Cloud’s contribution 
to our subscription revenue to continue to increase."

In terms of the contribution to total revenue, here are the specific figures provided:

- Elastic Cloud contributed 40% of the total revenue for the year ended April 30, 2023.
- Elastic Cloud contributed 35% of the total revenue for the year ended April 30, 2022.
- Elastic Cloud contributed 27% of the total revenue for the year ended April 30, 2021.

This progression shows a clear upward trend in the importance and 
contribution of Elastic Cloud to the company's overall revenue.
<p><strong>Zusammenfassung</strong>: Beide RAG-Modelle haben Elastic Cloud korrekt als wichtigsten Wachstumstreiber identifiziert. AdvancedRAG hingegen enthält mehr Details, berücksichtigt Abonnementumsätze und Kundenwachstum und erwähnt explizit andere Elastic-Angebote.</p><h4>Test 4: Beschreiben Sie den Mitarbeitervergütungsplan</h4><p>AdvancedRAG</p>### Employee Benefit Plan Overview

The provided context outlines various elements of the employee benefit plan at 
Elastic, often referred to as "Elasticians." Here are the key components 
described in the texts:

1. **401(k) Plan**:
   - **Coverage**: The 401(k) plan is available to substantially all U.S. 
   employees who meet minimum age and service requirements.
   - **Contributions**: Elastic makes contributions to the 401(k) plan up to 
   6% of the participating employee’s W-2 earnings and wages.
   - **Expenses**: For the fiscal years ended April 30, Elastic recorded 
   expenses of $17.9 million (2023), $15.2 million (2022), and $11.4 million (2021) 
   related to the 401(k) plan.
   - **Defined-Contribution Plans in Other Countries**: Elastic has 
   defined-contribution plans in various other countries and recorded respective 
   expenses of $9.4 million (2023), $7.2 million (2022), and $5.1 million (2021).

2. **Stock-Based Compensation**:
   - **Types of Awards**: Stock options, restricted stock units (RSUs), 
   and shares under the Employee Stock Purchase Plan (ESPP).
   - **Fair Value Measurement**: Fair value of these stock awards is 
   measured using models like Black-Scholes.
   - **Employee Stock Purchase Plan (2022 ESPP)**: 
     - Started in 2022, it allows employees to acquire ordinary 
     shares at a discount (85% of the market value at the beginning 
     or end of the offering period).
     - Offering periods are approximately six months long.

3. **Total Rewards Compensation**:
   - **Components**: Includes cash compensation as well as equity awards, 
   reflecting a comprehensive interest in the well-being of the employees.
   - **Programs**: Market competitive medical and dental programs, 
   mental health, and holistic well-being programs.
   - **Paid Time Off**: Features 16 weeks of paid leave for new 
   parents and life-planning benefits.

4. **Retirement and Income Protection Plans**:
   - **401(k) Match**: Elastic provides a dollar-for-dollar 
   match up to 6% of eligible earnings up to a plan-limit 
   maximum for U.S.-based employees.
   - **Similar Plans Outside the U.S.**: Competitive retirement 
   plans available for employees based outside the United States.

5. **Flexible Work Environment**: 
   - **Distributed Workforce**: Elastic operates with a global 
   distributed workforce model, allowing employees to work remotely 
   and providing a broad candidate pool.
   
6. **Learning and Development**:
   - **Programs**: Access to on-demand video-based learning, 
   leadership development programs, and other specific training 
   to develop managers and leaders.

7. **Employee Engagement and Surveys**:
   - **Mechanisms**: Annual employee engagement survey and 
   mid-year pulse survey.
   - **Objectives**: To monitor morale, develop action plans, 
   and maintain high engagement scores.

8. **Onboarding Program**:
   - **X-School**: An extensive new-hire orientation program to 
   help new employees meet peers and learn about the company's 
   products and solutions.

In summary, Elastic's employee benefit plan encompasses a broad 
spectrum of financial, health, well-being, and professional development 
benefits designed to support and enhance the lives of its employees. 
The plan is both competitive and comprehensive, aiming to attract,
retain, and engage its global workforce.
<p>SimpleRAG</p>The employee benefit plan at the Company includes several key 
components aimed at enhancing the overall well-being and 
professional development of employees, referred to as "Elasticians." 

1. **Compensation and Benefits:**
   - The Company provides market-competitive compensation 
   packages which typically include cash compensation and equity awards.
   - Comprehensive medical and dental programs are offered, 
   emphasizing mental health and holistic well-being.
   - Paid time off programs feature:
     - 16 weeks of paid leave for new parents.
     - Life-planning benefits.
     - Travel reimbursements for certain healthcare services.

2. **Retirement and Income Protection Plans:**
   - In the United States, employees are eligible for a 401k 
   plan with a dollar-for-dollar match by the Company up to 6% 
   of eligible earnings, subject to a plan limit.
   - Similar competitive retirement and income protection plans 
   are available for employees outside the United States.

3. **Work Environment:**
   - The Company offers a flexible work environment, allowing most 
   employees to work from anywhere as often as they would like.
   - Physical offices around the world are available for employees 
   who prefer to work on-site or need a space for face-to-face interactions.

4. **Community Involvement:**
   - The Elastic Cares Program supports charitable organizations 
   that matter to employees on both local and global levels.
   - The program includes:
     - Donation matching.
     - Providing the Company's technology for free to certain 
     nonprofit organizations.
     - Volunteer time off initiative.
<p><strong>Zusammenfassung</strong>: AdvancedRAG geht wesentlich tiefer und detaillierter darauf ein und erwähnt den 401K-Plan für in den USA ansässige Mitarbeiter sowie die Beitragspläne außerhalb der USA. Es werden auch Gesundheits- und Wohlbefindenspläne erwähnt, das Programm Elastic Cares, das SimpleRAG erwähnt, wird jedoch nicht aufgeführt.</p><h4>Test 5: Welche Unternehmen hat Elastic übernommen?</h4><p>AdvancedRAG</p>Elastic acquired several companies over the years to enhance its 
technology and market presence. According to the provided context, 
the specific acquisitions include:

1. **CmdWatch Security Inc.**: Acquired on September 17, 2021. 
The total purchase consideration was $77.8 million.
2. **Build Security Ltd.**: Acquired on September 2, 2021. The 
combined purchase price for Build Security Ltd. and another acquisition was $57.2 million.
3. **Optimyze Cloud Inc.**: Acquired on November 1, 2021. Part 
of the combined purchase price mentioned above with Build Security Ltd.
4. **Endgame, Inc.**: Although the context mentions an amended 
and restated stock incentive plan, it indicates that Endgame, Inc. was 
associated with Elastic, suggesting it could have been acquired at some point.

These acquisitions are part of Elastic's strategy to 
enhance the technology underlying its security and 
observability offerings.
<p>SimpleRAG</p>The provided context does not specify any companies that Elastic has acquired. 
Therefore, based on the context, there is no information available about the companies acquired by Elastic.
<p><strong>Zusammenfassung</strong>: SimpleRAG liefert keine relevanten Informationen zu Akquisitionen, was zu einer fehlerhaften Antwort führt. AdvancedRAG listet CmdWatch, Build Security und Optimyze korrekt auf; dies waren die im Bericht genannten wichtigsten Akquisitionen.</p><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#table-of-contents">Zurück nach oben</a></p><h2>Fazit</h2><p>Unsere Tests ergaben, dass unsere fortschrittlichen Techniken den Umfang und die Tiefe der präsentierten Informationen erhöhen und dadurch potenziell die Qualität der RAG-Antworten verbessern.</p><p>Darüber hinaus könnten Verbesserungen bei der Zuverlässigkeit erzielt werden, da mehrdeutig formulierte Fragen wie <code>Which companies did Elastic acquire?</code> und <code>Who audits Elastic</code> von AdvancedRAG korrekt beantwortet wurden, nicht aber von SimpleRAG.</p><p>Allerdings sollte man bedenken, dass in 3 von 5 Fällen die grundlegende RAG-Pipeline, die die Hybridsuche, aber keine anderen Techniken einbezog, Antworten lieferte, die den Großteil der wichtigsten Informationen erfassten.</p><p>Es ist zu beachten, dass die Latenz von AdvancedRAG aufgrund der Einbeziehung von LLMs in den Phasen der Datenaufbereitung und -abfrage im Allgemeinen 2- bis 5-mal größer ist als die von SimpleRAG. Dies stellt einen erheblichen Kostenfaktor dar, der AdvancedRAG möglicherweise nur für Situationen geeignet macht, in denen die Antwortqualität Vorrang vor der Latenz hat.</p><p>Die erheblichen Latenzkosten können durch den Einsatz eines kleineren und kostengünstigeren LLM wie Claude Haiku oder GPT-4o-mini in der Datenaufbereitungsphase verringert werden. Die fortgeschrittenen Modelle werden für die Antwortgenerierung verwendet.</p><p>Dies steht im Einklang mit den Ergebnissen von Wang et al. Wie ihre Ergebnisse zeigen, sind alle erzielten Verbesserungen relativ geringfügig. Kurz gesagt, mit einer einfachen RAG-Basislinie kommt man schon fast zu einem brauchbaren Endprodukt und ist dabei auch noch günstiger und schneller. Für mich ist das ein interessantes Ergebnis. Für Anwendungsfälle, in denen Geschwindigkeit und Effizienz im Vordergrund stehen, ist SimpleRAG die vernünftige Wahl. Für Anwendungsfälle, in denen jedes letzte Quäntchen Leistung herausgeholt werden muss, könnten die in AdvancedRAG integrierten Techniken einen vielversprechenden Ansatz bieten.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt56b7067a9d41d5a8/6a171119acf0886fb4be9c45/ea811706b6adc4731d90b925a9fefa0ac15901b4-1440x1060.jpg" alt="Wang-Pipeline" /><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2#table-of-contents">Zurück nach oben</a></p><h2>Anhang</h2><h3>Eingabeaufforderungen</h3><h4>RAG-Frage-Antwort-Aufforderung</h4><p>Aufforderung an das LLM, Antworten basierend auf Anfrage und Kontext zu generieren.</p>BASIC_RAG_PROMPT = '''
You are an AI assistant tasked with answering questions based primarily on the provided context, while also drawing on your own knowledge when appropriate. Your role is to accurately and comprehensively respond to queries, prioritizing the information given in the context but supplementing it with your own understanding when beneficial. Follow these guidelines:

1. Carefully read and analyze the entire context provided.
2. Primarily focus on the information present in the context to formulate your answer.
3. If the context doesn't contain sufficient information to fully answer the query, state this clearly and then supplement with your own knowledge if possible.
4. Use your own knowledge to provide additional context, explanations, or examples that enhance the answer.
5. Clearly distinguish between information from the provided context and your own knowledge. Use phrases like "According to the context..." or "The provided information states..." for context-based information, and "Based on my knowledge..." or "Drawing from my understanding..." for your own knowledge.
6. Provide comprehensive answers that address the query specifically, balancing conciseness with thoroughness.
7. When using information from the context, cite or quote relevant parts using quotation marks.
8. Maintain objectivity and clearly identify any opinions or interpretations as such.
9. If the context contains conflicting information, acknowledge this and use your knowledge to provide clarity if possible.
10. Make reasonable inferences based on the context and your knowledge, but clearly identify these as inferences.
11. If asked about the source of information, distinguish between the provided context and your own knowledge base.
12. If the query is ambiguous, ask for clarification before attempting to answer.
13. Use your judgment to determine when additional information from your knowledge base would be helpful or necessary to provide a complete and accurate answer.

Remember, your goal is to provide accurate, context-based responses, supplemented by your own knowledge when it adds value to the answer. Always prioritize the provided context, but don't hesitate to enhance it with your broader understanding when appropriate. Clearly differentiate between the two sources of information in your response.

Context:
[The concatenated documents will be inserted here]

Query:
[The user's question will be inserted here]

Please provide your answer based on the above guidelines, the given context, and your own knowledge where appropriate, clearly distinguishing between the two:
'''
<h4>Eingabeaufforderung für den Elastic-Abfragegenerator</h4><p>Aufforderung zur Anreicherung von Abfragen mit Synonymen und deren Umwandlung in das OR-Format.</p>ELASTIC_SEARCH_QUERY_GENERATOR_PROMPT = '''
You are an AI assistant specialized in generating Elasticsearch query strings. Your task is to create the most effective query string for the given user question. This query string will be used to search for relevant documents in an Elasticsearch index.

Guidelines:
1. Analyze the user's question carefully.
2. Generate ONLY a query string suitable for Elasticsearch's match query.
3. Focus on key terms and concepts from the question.
4. Include synonyms or related terms that might be in relevant documents.
5. Use simple Elasticsearch query string syntax if helpful (e.g., OR, AND).
6. Do not use advanced Elasticsearch features or syntax.
7. Do not include any explanations, comments, or additional text.
8. Provide only the query string, nothing else.

For the question "What is Clickthrough Data?", we would expect a response like:
clickthrough data OR click-through data OR click through rate OR CTR OR user clicks OR ad clicks OR search engine results OR web analytics

AND operator is not allowed. Use only OR.

User Question:
[The user's question will be inserted here]

Generate the Elasticsearch query string:
'''
<h4>Mögliche Fragen zur Generierung von Anregungen</h4><p>Anregung zur Generierung potenzieller Fragen, Anreicherung der Dokumentmetadaten.</p>RAG_QUESTION_GENERATOR_PROMPT = '''
You are an AI assistant specialized in generating questions for Retrieval-Augmented Generation (RAG) systems. Your task is to analyze a given document and create 10 diverse questions that would effectively test a RAG system's ability to retrieve and synthesize information from this document.

Guidelines:
1. Thoroughly analyze the entire document.
2. Generate exactly 10 questions that cover various aspects and levels of complexity within the document's content.
3. Create questions that specifically target:
   a. Key facts and information
   b. Main concepts and ideas
   c. Relationships between different parts of the content
   d. Potential applications or implications of the information
   e. Comparisons or contrasts within the document
4. Ensure questions require answers of varying lengths and complexity, from simple retrieval to more complex synthesis.
5. Include questions that might require combining information from different parts of the document.
6. Frame questions to test both literal comprehension and inferential understanding.
7. Avoid yes/no questions; focus on open-ended questions that promote comprehensive answers.
8. Consider including questions that might require additional context or knowledge to fully answer, to test the RAG system's ability to combine retrieved information with broader knowledge.
9. Number the questions from 1 to 10.
10. Output only the ten questions, without any additional text, explanations, or answers.

Document:
[The document content will be inserted here]

Generate 10 questions optimized for testing a RAG system based on this document:
'''
<h4>HyDE-Generator-Eingabeaufforderung</h4><p>Aufforderung zur Generierung hypothetischer Dokumente mit HyDE</p>HYDE_DOCUMENT_GENERATOR_PROMPT = '''
You are an AI assistant specialized in generating hypothetical documents based on user queries. Your task is to create a detailed, factual document that would likely contain the answer to the user's question. This hypothetical document will be used to enhance the retrieval process in a Retrieval-Augmented Generation (RAG) system.

Guidelines:
1. Carefully analyze the user's query to understand the topic and the type of information being sought.
2. Generate a hypothetical document that:
   a. Is directly relevant to the query
   b. Contains factual information that would answer the query
   c. Includes additional context and related information
   d. Uses a formal, informative tone similar to an encyclopedia or textbook entry
3. Structure the document with clear paragraphs, covering different aspects of the topic.
4. Include specific details, examples, or data points that would be relevant to the query.
5. Aim for a document length of 200-300 words.
6. Do not use citations or references, as this is a hypothetical document.
7. Avoid using phrases like "In this document" or "This text discusses" - write as if it's a real, standalone document.
8. Do not mention or refer to the original query in the generated document.
9. Ensure the content is factual and objective, avoiding opinions or speculative information.
10. Output only the generated document, without any additional explanations or meta-text.

User Question:
[The user's question will be inserted here]

Generate a hypothetical document that would likely contain the answer to this query:
'''
<h3>Beispiel einer hybriden Suchanfrage</h3>{'knn': {'field': 'primary_embedding',
  'query_vector': [0.4265527129173279,
   -0.1712949573993683,
   -0.042020395398139954,
   ...],
  'k': 100,
  'num_candidates': 100},
 'query': {'bool': {'must': [{'multi_match': {'query': 'audits Elastic Elastic auditing Elastic audit process Elastic compliance Elastic security audit Elasticsearch auditing Elasticsearch compliance Elasticsearch security audit',
      'fields': ['original_text',
       'keyphrases',
       'potential_questions',
       'entities'],
      'type': 'best_fields',
      'operator': 'or'}}],
   'should': [{'script_score': {'query': {'match_all': {}},
      'script': {'source': '\n                                        double vector_score = cosineSimilarity(params.query_vector, params.vector_field) + 1.0;\n                                        double text_score = _score;\n                                        return 0.7 * vector_score + 0.3 * text_score;\n                                        ',
       'params': {'query_vector': [0.4265527129173279,
         -0.1712949573993683,
         -0.042020395398139954,
        ...],
        'vector_field': 'primary_embedding'}}}}]}},
 'size': 10}
]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2</guid>
    <category><![CDATA[Vektordatenbank]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Han Xiang Choong]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf605c8246989df32/6a1711178b73cbc61d18a11d/8da40067835ab8b4dc12fe52a51a6c26858ad32f-1440x1095.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 15 Aug 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Erweiterte RAG-Techniken Teil 1: Datenverarbeitung]]></title>
    <description><![CDATA[Diskussion und Umsetzung von Techniken zur Steigerung der RAG-Leistung. Teil 1 von 2, der sich auf die Datenverarbeitungs- und Aufnahmekomponente einer fortschrittlichen RAG-Pipeline konzentriert.]]></description>
    <content:encoded><![CDATA[<p><em>Dies ist Teil 1 unserer Erkundung fortgeschrittener RAG-Techniken. </em><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2"><em>Klicken Sie hier für Teil 2!</em></a></p><p>Die kürzlich erschienene Arbeit <a href="https://arxiv.org/abs/2407.01219">„Searching for Best Practices in Retrieval-Augmented Generation“</a> bewertet empirisch die Wirksamkeit verschiedener RAG-Verbesserungstechniken mit dem Ziel, eine Reihe von Best Practices für RAG zu ermitteln.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt671704ff06a4011d/6a170b3ea929cf2d19ae09d8/dafa7250e7c4ead4d9b4aed7c407509131929749-1440x572.png" alt="Die von Wang empfohlene RAG-Pipeline" /><p>Wir werden einige dieser vorgeschlagenen Best Practices umsetzen, nämlich diejenigen, die darauf abzielen, die Qualität der Suche zu verbessern <strong>(Sentence Chunking, HyDE, Reverse Packing)</strong>.</p><p>Aus Gründen der Kürze lassen wir die Techniken zur Effizienzsteigerung <strong>(Abfrageklassifizierung und Zusammenfassung)</strong> aus.</p><p>Wir werden auch einige Techniken anwenden, die nicht behandelt wurden, die ich persönlich aber für nützlich und interessant halte <strong>(Metadateneinbindung, zusammengesetzte Multi-Field-Einbettungen, Abfrageanreicherung)</strong>.</p><p>Zum Schluss führen wir einen kurzen Test durch, um zu sehen, ob sich die Qualität unserer Suchergebnisse und generierten Antworten im Vergleich zur Ausgangslage verbessert hat. Los geht's!</p><h2>RAG-Übersicht</h2><p>RAG zielt darauf ab, LLMs zu verbessern, indem Informationen aus externen Wissensdatenbanken abgerufen werden, um die generierten Antworten anzureichern. Durch die Bereitstellung domänenspezifischer Informationen können LLMs schnell an Anwendungsfälle außerhalb des Umfangs ihrer Trainingsdaten angepasst werden; dies ist wesentlich kostengünstiger als eine Feinabstimmung und einfacher, sie auf dem neuesten Stand zu halten.</p><p>Maßnahmen zur Verbesserung der Qualität von Ampelbewertungen konzentrieren sich typischerweise auf zwei Bereiche:</p><ol><li><p>Verbesserung der Qualität und Klarheit der Wissensbasis.</p></li><li><p>Verbesserung der Abdeckung und Spezifität von Suchanfragen.</p></li></ol><p>Diese beiden Maßnahmen sollen das Ziel erreichen, die Wahrscheinlichkeit zu erhöhen, dass der LLM Zugang zu relevanten Fakten und Informationen hat und somit weniger wahrscheinlich Halluzinationen hat oder auf sein eigenes Wissen zurückgreift, das möglicherweise veraltet oder irrelevant ist.</p><p>Die Vielfalt der Methoden lässt sich in wenigen Sätzen nur schwer verdeutlichen. Um die Dinge verständlicher zu machen, gehen wir direkt zur Umsetzung über.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9a4691874a19d8da/6a170b3f47d49c99f22d8a24/72b51ba2ae5e5977b56e5b915674753d6cfd0e56-1440x840.jpg" alt="Fortschrittliche RAG-Pipeline" /><h3>Inhaltsverzeichnis</h3><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#overview">Überblick</a></p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#table-of-contents">Inhaltsverzeichnis</a></p></li></ul></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#set-up">Aufstellen</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#ingesting-processing-and-embedding-documents">Einlesen, Verarbeiten und Einbetten von Dokumenten</a>  </p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#data-ingestion">Dateningestion</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#sentence-level-token-wise-chunking">Chunking auf Satzebene, tokenweise</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#metadata-inclusion-and-generation">Metadateneinbindung und -generierung</a> </p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#keyphrases-extracted-by-textrank">Von TextRank extrahierte Schlüsselphrasen</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#potential-questions-generated-by-gpt-4o">Mögliche Fragen, die von GPT-4o generiert wurden</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#entities-extracted-by-spacy">Von Spacy extrahierte Entitäten</a></p></li></ul></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#composite-multi-field-embeddings">Zusammengesetzte Mehrfeldeinbettungen</a></p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#indexing-to-elastic">Indexierung zu Elastic</a></p></li></ul></li></ul></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#cat-break">Katzenbruch</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#appendix">Anhang</a></p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#definitions">Definitionen</a></p></li></ul></li></ul><h2>Aufstellen</h2><p><em>Der gesamte Code ist </em><a href="https://github.com/elastic/elasticsearch-labs/tree/advanced-rag-techniques/supporting-blog-content/advanced-rag-techniques"><em>im Searchlabs-Repository zu</em></a><em> finden.</em></p><p>Das Wichtigste zuerst. Sie benötigen Folgendes:</p><ol><li><p>Eine elastische Cloud-Bereitstellung</p></li><li><p>Eine LLM-API – In diesem Notebook verwenden wir eine GPT-4o-Bereitstellung auf Azure OpenAI.</p></li><li><p>Python Version 3.12.4 oder höher</p></li></ol><p>Wir werden den gesamten Code aus <a href="https://github.com/elastic/elasticsearch-labs/blob/advanced-rag-techniques/supporting-blog-content/advanced-rag-techniques/main.ipynb">dem main.ipynb-Notebook ausführen.</a></p><p>Klonen Sie nun das Repository mit git, navigieren Sie zu supporting-blog-content/advanced-rag-techniques und führen Sie anschließend die folgenden Befehle aus:</p># Create a new virtual environment named 'rag_env'
python -m venv rag_env

# Activate the virtual environment (for Unix-based systems)
source rag_env/bin/activate

# (For Windows)
.\rag_env\Scripts\activate

# Install packages listed in requirements.txt
pip install -r requirements.txt
<p>Sobald das erledigt ist, erstellen Sie eine <em>.env-Datei.</em> Datei öffnen und die folgenden Felder ausfüllen (Referenz in <a href="https://github.com/elastic/elasticsearch-labs/blob/advanced-rag-techniques/supporting-blog-content/advanced-rag-techniques/.env.example"><em>.env.example</em></a>). Ein Dank geht an meinen Co-Autor Claude-3.5 für die hilfreichen Kommentare.</p># Elastic Cloud: Found in the 'Deployment' page of your Elastic Cloud 
# console
ELASTIC_CLOUD_ENDPOINT=""
ELASTIC_CLOUD_ID=""

# Elastic Cloud: Created during deployment setup or in 'Security' 
# settings
ELASTIC_USERNAME=""
ELASTIC_PASSWORD=""

# Elastic Cloud: The name of the index you created in Kibana or via API
ELASTIC_INDEX_NAME=""

# Azure AI Studio: Found in 'Keys and Endpoint' section of your Azure 
# OpenAI resource
AZURE_OPENAI_KEY_1=""
AZURE_OPENAI_KEY_2=""
AZURE_OPENAI_REGION=""
AZURE_OPENAI_ENDPOINT=""

# Azure AI Studio: Found in 'Deployments' section of your Azure OpenAI 
# resource
AZURE_OPENAI_DEPLOYMENT_NAME=""

# Using BAAI/bge-small-en-v1.5 because I think it is a good balance of 
# resource efficiency and performance. 
HUGGINGFACE_EMBEDDING_MODEL="BAAI/bge-small-en-v1.5"
<p>Als Nächstes wählen wir das zu importierende Dokument aus und legen es im Dokumentenordner ab. Für diesen Artikel verwenden wir den <a href="https://s201.q4cdn.com/217177842/files/doc_downloads/OtherDocuments/2023/AnnualMeeting/Annual-Report-Fiscal-Year-2023.pdf">Elastic NV Jahresbericht 2023</a>. Es handelt sich um ein ziemlich anspruchsvolles und komplexes Dokument, perfekt geeignet, um unsere RAG-Techniken einem Stresstest zu unterziehen.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte292dc6030d496cc/6a170b40dc55de9b03e00dfc/e513b9d67adac43da794c25a5969b893127bbbe3-1440x395.jpg" alt="Elastic-Jahresbericht 2023" /><p>Jetzt sind wir bereit, lasst uns mit der Einnahme beginnen. Öffnen Sie <em>main.ipynb</em> und führen Sie die ersten beiden Zellen aus, um alle Pakete zu importieren und alle Dienste zu initialisieren.</p><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#table-of-contents">Zurück nach oben</a></p><h2>Einlesen, Verarbeiten und Einbetten von Dokumenten</h2><h3>Dateningestion</h3><ul><li><p><em>Persönliche Anmerkung: Ich bin von der Benutzerfreundlichkeit von LlamaIndex begeistert. In den alten Zeiten vor LLMs und LlamaIndex war das Einlesen von Dokumenten in verschiedenen Formaten ein mühsamer Prozess, bei dem man esoterische Pakete aus allen möglichen Quellen zusammentragen musste. Jetzt ist es auf einen einzigen Funktionsaufruf reduziert. Wild.</em></p></li></ul><p>Die <code>SimpleDirectoryReader</code> lädt alle Dokumente in den <code>directory_path.</code> -Dateien. Für <code>.pdf</code> -Dateien gibt sie eine Liste von Dokumentobjekten zurück, die ich in Python-Dictionaries umwandle, da ich diese einfacher zu handhaben finde.</p># llamaindex_processor.py
from llama_index.core import SimpleDirectoryReader

class LlamaIndexProcessor:
   def __init__(self):
       pass 
   
   def load_documents(self, directory_path):
       ''' 
       Load all documents in directory
       '''
       reader = SimpleDirectoryReader(input_dir=directory_path)
       return reader.load_data()

# main.ipynb
llamaindex_processor=LlamaIndexProcessor()
documents=llamaindex_processor.load_documents('./documents/')
documents=[dict(doc_obj) for doc_obj in documents]
<p>Jedes Wörterbuch enthält den Schlüsselinhalt im Feld <code>text</code> . Es enthält außerdem nützliche Metadaten wie Seitenzahl, Dateiname, Dateigröße und Dateityp.</p>{
  'id_': '5f76f0b3-22d8-49a8-9942-c2bbab14f63f',
  'metadata': {'page_label': '5',
   'file_name': 'Elastic_NV_Annual-Report-Fiscal-Year-2023.pdf',
   'file_path': '/Users/han/Desktop/Projects/truckasaurus/documents/Elastic_NV_Annual-Report-Fiscal-Year-2023.pdf',
   'file_type': 'application/pdf',
   'file_size': 3724426,
   'creation_date': '2024-07-27',
   'last_modified_date': '2024-07-27'},
   'text': 'Table of Contents\nPage\nPART I\nItem 1. Business 3\n15 Item 1A. Risk Factors\nItem 1B. Unresolved Staff Comments 48\nItem 2. Properties 48\nItem 3. Legal Proceedings 48\nItem 4. Mine Safety Disclosures 48\nPART II\nItem 5. Market for Registrant's Common Equity, Related Stockholder Matters and Issuer Purchases of \nEquity Securities49\nItem 6. [Reserved] 49\nItem 7. Management's Discussion and Analysis of Financial Condition and Results of Operations 50\nItem 7A. Quantitative and Qualitative Disclosures About Market Risk 64\nItem 8. Financial Statements and Supplementary Data 66\nItem 9. Changes in and Disagreements With Accountants on Accounting and Financial Disclosure 100\n100\n101Item 9A. Controls and Procedures\nItem 9B. Other Information\nItem 9C. Disclosure Regarding Foreign Jurisdictions That Prevent Inspections 101\nPART III\n102\n102\n102\n102Item 10. Directors, Executive Officers and Corporate Governance\nItem 11. Executive Compensation\nItem 12. Security Ownership of Certain Beneficial Owners and Management, and Related Stockholder Matters  \nItem 13. Certain Relationships and Related Transactions, and Director Independence\nItem 14. Principal Accountant Fees and Services 102\nPART IV\n103\n105Item 15. Exhibits and Financial Statement Schedules  \nItem 16. Form 10-K Summary\nSignatures 106\ni',
   ...
}
<p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#table-of-contents">Zurück nach oben</a></p><h3>Chunking auf Satzebene, tokenweise</h3><p>Als Erstes sollten wir unsere Dokumente in Abschnitte von einheitlicher Länge unterteilen (um Konsistenz und Verwaltbarkeit zu gewährleisten). Einbettungsmodelle haben individuelle Token-Limits (maximale Eingabegröße, die sie verarbeiten können). Tokens sind die grundlegenden Einheiten des Textes, die Prozesse modellieren. Um Informationsverluste (Abschneidung oder Auslassung von Inhalten) zu vermeiden, sollten wir Texte bereitstellen, die diese Grenzen nicht überschreiten (indem wir längere Texte in kleinere Abschnitte aufteilen).</p><p>Das Chunking hat einen erheblichen Einfluss auf die Leistung. Im Idealfall stellt jeder Abschnitt eine in sich abgeschlossene Informationseinheit dar, die Kontextinformationen zu einem einzelnen Thema erfasst. Zu den Chunking-Methoden gehören das Chunking auf Wortebene, bei dem Dokumente anhand der Wortanzahl aufgeteilt werden, und das semantische Chunking, das ein LLM verwendet, um logische Trennpunkte zu identifizieren.</p><p>Die Segmentierung auf Wortebene ist zwar günstig, schnell und einfach, birgt aber das Risiko, Sätze zu trennen und dadurch den Kontext zu zerstören. Die semantische Segmentierung wird langsam und teuer, insbesondere bei Dokumenten wie dem 116-seitigen Elastic Annual Report.</p><p>Lasst uns einen Mittelweg wählen. Die Segmentierung auf Satzebene ist zwar immer noch einfach, kann aber den Kontext besser erhalten als die Segmentierung auf Wortebene und ist dabei deutlich günstiger und schneller. Zusätzlich werden wir ein gleitendes Fenster implementieren, um einen Teil des umgebenden Kontextes zu erfassen und die Auswirkungen der Absatzteilung zu verringern.</p># chunker.py 

import uuid
import re


class Chunker: 
    def __init__(self, tokenizer):
        self.tokenizer = tokenizer 
    
    def split_into_sentences(self, text):
        """Split text into sentences."""
        return re.split(r'(?&lt;=[.!?])\s+', text)
 
    def sentence_wise_tokenized_chunk_documents(self, documents, chunk_size=512, overlap=20, min_chunk_size=50):
        '''
        1. Split text into sentences.
        2. Tokenize using the provided tokenizer method.
        3. Build chunks up to the chunk_size limit.
        4. Create an overlap based on tokens - to preserve context.
        5. Only keep chunks that meet the minimum token size requirement.
        '''
        chunked_documents = []

        for doc in documents:
            sentences = self.split_into_sentences(doc['text'])
            tokens = []
            sentence_boundaries = [0]

            # Tokenize all sentences and keep track of sentence boundaries
            for sentence in sentences:
                sentence_tokens = self.tokenizer.encode(sentence, add_special_tokens=True)
                tokens.extend(sentence_tokens)
                sentence_boundaries.append(len(tokens))

            # Create chunks
            chunk_start = 0
            while chunk_start &lt; len(tokens):
                chunk_end = chunk_start + chunk_size

                # Find the last complete sentence that fits in the chunk
                sentence_end = next((i for i in sentence_boundaries if i &gt; chunk_end), len(tokens))
                chunk_end = min(chunk_end, sentence_end)

                # Create the chunk
                chunk_tokens = tokens[chunk_start:chunk_end]

                # Check if the chunk meets the minimum size requirement
                if len(chunk_tokens) &gt;= min_chunk_size:
                    # Create a new document object for this chunk
                    chunk_doc = {
                        'id_': str(uuid.uuid4()),
                        'chunk': chunk_tokens,
                        'original_text': self.tokenizer.decode(chunk_tokens),
                        'chunk_index': len(chunked_documents),
                        'parent_id': doc['id_'],
                        'chunk_token_count': len(chunk_tokens)
                    }

                    # Copy all other fields from the original document
                    for key, value in doc.items():
                        if key != 'text' and key not in chunk_doc:
                            chunk_doc[key] = value

                    chunked_documents.append(chunk_doc)

                # Move to the next chunk start, considering overlap
                chunk_start = max(chunk_start + chunk_size - overlap, chunk_end - overlap)

        return chunked_documents

# main.ipynb 
# Initialize Embedding Model
HUGGINGFACE_EMBEDDING_MODEL = os.environ.get('HUGGINGFACE_EMBEDDING_MODEL')
embedder=EmbeddingModel(model_name=HUGGINGFACE_EMBEDDING_MODEL)

# Initialize Chunker
chunker=Chunker(embedder.tokenizer)
<p>Die Klasse <code>Chunker</code> verwendet den Tokenizer des Einbettungsmodells zum Kodieren und Dekodieren von Text. Wir werden nun Blöcke von jeweils 512 Token erstellen, mit einer Überlappung von 20 Token. Dazu teilen wir den Text in Sätze auf, tokenisieren diese Sätze und fügen die tokenisierten Sätze dann unserem aktuellen Chunk hinzu, bis wir keine weiteren mehr hinzufügen können, ohne unser Token-Limit zu überschreiten.</p><p>Zum Schluss werden die Sätze wieder in den Originaltext dekodiert, um sie einzubetten. Dieser wird in einem Feld namens <code>original_text</code> gespeichert. Die Chunks werden in einem Feld namens <code>chunk</code> gespeichert. Um unnötige Dokumente (auch: überflüssige Dokumente) zu reduzieren, werden wir alle Dokumente verwerfen, die kürzer als 50 Token sind.</p><p>Lassen Sie uns das anhand unserer Dokumente prüfen:</p>chunked_documents=chunker.sentence_wise_tokenized_chunk_documents(documents, chunk_size=512)
<p>Und Sie erhalten Textabschnitte zurück, die etwa so aussehen:</p>print(chunked_documents[4]['original_text'])

[CLS] the aggregate market value of the ordinary shares held by non - affiliates of the registrant, 
based on the closing price of the shares of ordinary shares on the new york stock exchange on 
october 31, 2022 ( the last business day of the registrant 's second fiscal quarter ), was 
approximately $ 6. 1 billion. [SEP] [CLS] as of may 31, 2023, the registrant had 97, 390, 886 
ordinary shares, par value €0. 01 per share, outstanding. [SEP] [CLS] documents incorporated by 
reference portions of the registrant 's definitive proxy statement relating to the registrant 's 2
023 annual general meeting of shareholders are incorporated by reference into part iii of this annual 
...
...
<p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#table-of-contents">Zurück nach oben</a></p><h3>Metadateneinbindung und -generierung</h3><p>Wir haben unsere Dokumente in Abschnitte unterteilt. Nun ist es an der Zeit, die Daten anzureichern. Ich möchte zusätzliche Metadaten generieren oder extrahieren. Diese zusätzlichen Metadaten können genutzt werden, um die Suchleistung zu beeinflussen und zu verbessern.</p><p>Wir definieren eine <code>DocumentEnricher</code> -Klasse, deren Aufgabe es ist, eine Liste von Dokumenten (Python-Dictionaries) und eine Liste von Prozessorfunktionen entgegenzunehmen. Diese Funktionen werden auf die Spalte <code>original_text</code> der Dokumente angewendet und ihre Ergebnisse in neuen Feldern gespeichert.</p><p>Zuerst extrahieren wir mithilfe von <a href="https://github.com/elastic/elasticsearch-labs/blob/advanced-rag-techniques/supporting-blog-content/advanced-rag-techniques/nltk_processor.py">TextRank</a> Schlüsselphrasen. TextRank ist ein graphenbasierter Algorithmus, der Schlüsselphrasen und -sätze aus Texten extrahiert, indem er ihre Wichtigkeit anhand der Beziehungen zwischen den Wörtern ordnet.</p><p>Als nächstes <a href="https://github.com/elastic/elasticsearch-labs/blob/advanced-rag-techniques/supporting-blog-content/advanced-rag-techniques/llm.py">generieren wir potenzielle_Fragen mithilfe von GPT-4o</a>.</p><p>Zum Schluss <a href="https://github.com/elastic/elasticsearch-labs/blob/advanced-rag-techniques/supporting-blog-content/advanced-rag-techniques/entity_extractor.py">extrahieren wir Entitäten</a> mithilfe von <a href="https://spacy.io/">Spacy</a>.</p><p>Da der Code für jeden dieser Punkte recht umfangreich und komplex ist, verzichte ich darauf, ihn hier wiederzugeben. Bei Interesse sind die Dateien in den unten stehenden Codebeispielen gekennzeichnet.</p><p>Starten wir die Datenanreicherung:</p># documentenricher.py
from tqdm import tqdm

class DocumentEnricher:

    def __init__(self):
        pass 

    def enrich_document(self, documents, processors, text_col='text'):
        for doc in tqdm(documents, desc="Enriching documents using processors: "+str(processors)): 
            for (processor, field) in processors: 
                metadata=processor(doc[text_col])
                if isinstance(metadata, list):
                    metadata='\n'.join(metadata)
                doc.update({field: metadata})
 
# main.ipynb
# Initialize processor classes 
nltkprocessor=NLTKProcessor() // nltk_processor.py
entity_extractor=EntityExtractor() // entity_extractor.py
gpt4o = LLMProcessor(model='gpt-4o') // llm.py

# Initialize LLM
documentenricher=DocumentEnricher()

# Create new fields in the documents - These are the outputs of the processor functions.
processors=[
    (nltkprocessor.textrank_phrases, "keyphrases"),
    (gpt4o.generate_questions, "potential_questions"),
    (entity_extractor.extract_entities, "entities")
    ]

# .enrich_document() will modify chunked_docs in place. 
# To view the results, we'll print chunked_docs in the next few cells!
documentenricher.enrich_document(chunked_docs, text_col='original_text', processors=processors)
<p>Und sehen Sie sich die Ergebnisse an:</p><h4>Von TextRank extrahierte Schlüsselphrasen</h4><p>Diese Schlüsselbegriffe stehen stellvertretend für die Kernthemen des jeweiligen Abschnitts. Wenn eine Anfrage mit Cybersicherheit zu tun hat, wird die Punktzahl dieses Abschnitts erhöht.</p>print(chunked_documents[25]['keyphrases'])

'elastic agent stop', 'agent stop malware', 
'stop malware ransomware', 'malware ransomware environment', 
'ransomware environment wide', 'environment wide visibility', 
'wide visibility threat', 'visibility threat detection', 
'sep cl key', 'cl key feature'
<h4>Mögliche Fragen, die von GPT-4o generiert wurden</h4><p>Diese potenziellen Fragen könnten direkt mit den Suchanfragen der Nutzer übereinstimmen und so zu einer Verbesserung der Punktzahl führen. Wir fordern GPT-4o auf, Fragen zu generieren, die mithilfe der im aktuellen Chunk enthaltenen Informationen beantwortet werden können.</p>print(chunked_documents[25]['potential_questions'])

1. What are the primary functions that Elastic Agent provides in terms of cybersecurity?
2. Describe how Logstash contributes to data management within an IT environment.
3. List and explain any key features of Logstash mentioned in the document.
4. How does Elastic Agent enhance environment-wide visibility in threat detection?
5. What capabilities does Logstash offer for handling data beyond simple collection?
6. In what ways does the document suggest that Elastic Agent stops malware and ransomware?
7. Can you identify any relationships between the functionalities of Elastic Agent and Logstash in an integrated environment?
8. What implications might the advanced threat detection capabilities of Elastic Agent have for organizational security policies?
9. Compare and contrast the roles of Elastic Agent and Logstash based on their described functions.
10. How might the centralized collection ability of Logstash support the threat detection capabilities of Elastic Agent?
<h4>Von Spacy extrahierte Entitäten</h4><p>Diese Entitäten dienen einem ähnlichen Zweck wie die Schlüsselphrasen, erfassen aber die Namen von Organisationen und Einzelpersonen, die bei der Extraktion von Schlüsselphrasen möglicherweise nicht erfasst werden.</p>print(chunked_documents[29]['entities'])

'appdynamics', 'apm data', 'azure sentinel', 
'microsoft', 'mcafee', 'broadcom', 'cisco', 
'dynatrace', 'coveo', 'lucidworks'
<p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#table-of-contents">Zurück nach oben</a></p><h3>Zusammengesetzte Mehrfeldeinbettungen</h3><p>Nachdem wir unsere Dokumente nun mit zusätzlichen Metadaten angereichert haben, können wir diese Informationen nutzen, um robustere und kontextsensitive Einbettungen zu erstellen.</p><p>Lassen Sie uns den aktuellen Stand des Prozesses noch einmal betrachten. Wir haben in jedem Dokument vier Interessensgebiete.</p>{
    "chunk": "...",
    "keyphrases": "...", 
    "potential_questions": "...", 
    "entities": "..." 
}
<p>Jedes Feld repräsentiert eine andere Perspektive auf den Kontext des Dokuments und hebt möglicherweise einen wichtigen Bereich hervor, auf den sich das LLM konzentrieren sollte.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt84cb328fce6aae23/6a170b42964cea3e4408bbc4/aea1f513009a0c7c8545a79fad8f072a5bcae24c-1440x1067.jpg" alt="Metadatenanreicherungspipeline in RAG" /><p>Der Plan besteht darin, jedes dieser Felder einzubetten und dann eine gewichtete Summe der Einbettungen zu erstellen, die als zusammengesetzte Einbettung bezeichnet wird.</p><p>Mit etwas Glück wird dieses Composite Embedding dem System ermöglichen, kontextsensitiver zu werden, und zusätzlich einen weiteren einstellbaren Hyperparameter zur Steuerung des Suchverhaltens einführen.</p><p>Zunächst betten wir jedes Feld ein und aktualisieren jedes Dokument direkt, indem wir unser lokal definiertes Einbettungsmodell verwenden, das wir zu Beginn des Notebooks main.ipynb importiert haben.</p># EmbeddingModel defined in embedding_model.py
embedder=EmbeddingModel(model_name=HUGGINGFACE_EMBEDDING_MODEL)

cols_to_embed=['keyphrases', 'potential_questions', 'entities']

embedding_cols=[]
for col in cols_to_embed:
    # Works on text input
    embedding_col=embedder.embed_documents_text_wise(chunked_documents, text_field=col)
    embedding_cols.append(embedding_col)
# Works on token input
embedding_col=embedder.embed_documents_token_wise(chunked_documents, token_field="chunk")
embedding_cols.append(embedding_col)
<p>Jede Einbettungsfunktion gibt das Feld der Einbettung zurück, welches einfach das ursprüngliche Eingabefeld mit einem Suffix <code>_embedding</code> ist.</p><p>Definieren wir nun die Gewichtungen unserer zusammengesetzten Einbettung:</p>embedding_cols=[
                'keyphrases_embedding',
                'potential_questions_embedding',
                'entities_embedding',
                'chunk_embedding']
combination_weights=[
                    0.1,
                    0.15,
                    0.05,
                    0.7
                ]
<p>Mithilfe der Gewichtungen können Sie den einzelnen Komponenten Prioritäten zuweisen, basierend auf Ihrem Anwendungsfall und der Qualität Ihrer Daten. Intuitiv betrachtet hängt die Größe dieser Gewichtungen vom semantischen Wert jeder Komponente ab. Da der Chunk-Text selbst mit Abstand den größten Informationsgehalt aufweist, weise ich ihm eine Gewichtung von 70 % zu. Da es sich bei den Entitäten um die kleinsten handelt, nämlich lediglich um eine Liste von Organisations- oder Personennamen, weise ich ihnen eine Gewichtung von 5 % zu. Die genaue Festlegung dieser Werte muss empirisch, also für jeden Anwendungsfall einzeln, erfolgen.</p><p>Zum Schluss schreiben wir eine Funktion, um die Gewichtungen anzuwenden und unser zusammengesetztes Embedding zu erstellen. Um Speicherplatz zu sparen, löschen wir auch alle Komponenteneinbettungen.</p>from tqdm import tqdm 
def combine_embeddings(objects, embedding_cols, combination_weights, primary_embedding='primary_embedding'):
    # Ensure the number of weights matches the number of embedding columns
    assert len(embedding_cols) == len(combination_weights), "Number of embedding columns must match number of weights"
    
    # Normalize weights to sum to 1
    weights = np.array(combination_weights) / np.sum(combination_weights)
    
    for obj in tqdm(objects, desc="Combining embeddings"):
        # Initialize the combined embedding
        combined = np.zeros_like(obj[embedding_cols[0]])
        
        # Compute the weighted sum
        for col, weight in zip(embedding_cols, weights):
            combined += weight * np.array(obj[col])
        
        # Add the new combined embedding to the object
        obj.update({primary_embedding:combined.tolist()})
        
        # Remove the original embedding columns
        for col in embedding_cols:
            obj.pop(col, None)

combine_embeddings(chunked_documents, embedding_cols, combination_weights)
<p>Hiermit ist unsere Dokumentenbearbeitung abgeschlossen. Wir haben nun eine Liste von Dokumentobjekten, die folgendermaßen aussehen:</p>{ 'id_': '7fe71686-5cd0-4831-9e79-998c6dbeae0c', 'chunk': [2312, 14613, ...], 'original_text': 'if an emerging growth company, indicate by check mark if the registrant has elected not to use the extended ...', 'chunk_index': 3, 'chunk_token_count': 399, 'metadata': {'page_label': '3', 'file_name': 'Elastic_NV_Annual-Report-Fiscal-Year-2023.pdf', ... 'keyphrases': 'sep cl unk\ncheck mark registrant\ncl unk indicate\nunk indicate check\nindicate check mark\nprincipal executive office\naccelerate filer unk\ncompany unk emerge\nunk emerge growth\nemerge growth company', 'potential_questions': '1. What are the different types of registrant statuses mentioned in the document?\n2. Under what section of the Sarbanes-Oxley Act must registrants file a report on the effectiveness of their internal ...', 'entities': 'the effe ctiveness of\nsection 13\nSEP\nUNK\nsection 21e\n1934\n1933\nu. s. c.\nsection 404\nsection 12\nal', 'primary_embedding': [-0.3946287803351879, -0.17586839850991964, ...] }
<h4>Indexierung zu Elastic</h4><p>Lasst uns unsere Dokumente per Massen-Upload in Elastic Search hochladen. Zu diesem Zweck habe ich vor langer Zeit eine Reihe von Elastic-Helper-Funktionen in <a href="https://github.com/elastic/elasticsearch-labs/blob/advanced-rag-techniques/supporting-blog-content/advanced-rag-techniques/elastic_helpers.py"><code>elastic_helpers.py</code></a> definiert. Es handelt sich um einen sehr langen Codeabschnitt, daher konzentrieren wir uns auf die Funktionsaufrufe.</p><p><code>es_bulk_indexer.bulk_upload_documents</code> Funktioniert mit beliebigen Listen von Wörterbuchobjekten und nutzt dabei die praktischen dynamischen Zuordnungen von Elasticsearch.</p># Initialize Elasticsearch
ELASTIC_CLOUD_ID = os.environ.get('ELASTIC_CLOUD_ID')
ELASTIC_USERNAME = os.environ.get('ELASTIC_USERNAME')
ELASTIC_PASSWORD = os.environ.get('ELASTIC_PASSWORD')
ELASTIC_CLOUD_AUTH = (ELASTIC_USERNAME, ELASTIC_PASSWORD)
es_bulk_indexer = ESBulkIndexer(cloud_id=ELASTIC_CLOUD_ID, credentials=ELASTIC_CLOUD_AUTH)
es_query_maker = ESQueryMaker(cloud_id=ELASTIC_CLOUD_ID, credentials=ELASTIC_CLOUD_AUTH)

# Define Index Name
index_name=os.environ.get('ELASTIC_INDEX_NAME')


# Create index and bulk upload 
index_exists = es_bulk_indexer.check_index_existence(index_name=index_name)
if not index_exists:
    logger.info(f"Creating new index: {index_name}")
    es_bulk_indexer.create_es_index(es_configuration=BASIC_CONFIG, index_name=index_name)

success_count = es_bulk_indexer.bulk_upload_documents(
    index_name=index_name, 
    documents=chunked_documents, 
    id_col='id_',
    batch_size=32
)
<p>Gehe zu Kibana und überprüfe, ob alle Dokumente indexiert wurden. Es sollten 224 sein. Nicht schlecht für ein so umfangreiches Dokument!</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8efeface6effe01d/6a170b447d8d67652870e72a/1b3b07f6b98ceb65f6594ce4be83c5b0ed7e7cf9-1440x1380.jpg" alt="Index Kibana" /><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#table-of-contents">Zurück nach oben</a></p><h2>Katzenbruch</h2><p>Lasst uns eine Pause machen, der Artikel ist etwas anspruchsvoll, ich weiß. Schaut euch meine Katze an:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc1db5595f71c12ff/6a170b450e2e49940241a0fe/baca4eb52b801b21ced97352cc55462f0a12d6b0-969x996.jpg" alt="Han-Pipeline" /><p>Liebenswert. Der Hut ist verschwunden und ich vermute fast, dass sie ihn gestohlen und irgendwo versteckt hat :(</p><p>Herzlichen Glückwunsch, dass du es so weit geschafft hast :)</p><p>Seien Sie in <a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2">Teil 2</a> wieder dabei, wenn wir unsere RAG-Pipeline testen und bewerten!</p><h2>Anhang</h2><h3>Definitionen</h3><p><strong>1. Satzgliederung</strong></p><ul><li><p>Eine Vorverarbeitungstechnik, die in RAG-Systemen verwendet wird, um Text in kleinere, sinnvolle Einheiten zu unterteilen.</p></li><li><p><em>Prozess:</em> </p><ol><li><p>Eingabe: Großer Textblock (z. B. Dokument, Absatz)</p></li><li><p>Ausgabe: Kleinere Textsegmente (typischerweise Sätze oder kleine Satzgruppen)</p></li></ol></li><li><p><em>Zweck:</em> </p><ul><li><p>Erzeugt detaillierte, kontextspezifische Textsegmente</p></li><li><p>Ermöglicht eine präzisere Indizierung und einen schnelleren Abruf.</p></li><li><p>Verbessert die Relevanz der abgerufenen Informationen in RAG-Systemen</p></li></ul></li><li><p><em>Eigenschaften:</em> </p><ul><li><p>Segmente sind semantisch aussagekräftig.</p></li><li><p>Kann unabhängig indexiert und abgerufen werden.</p></li><li><p>Oft wird etwas Kontext beibehalten, um die Verständlichkeit für sich allein zu gewährleisten.</p></li></ul></li><li><p><em>Vorteile:</em> </p><ul><li><p>Verbessert die Abrufgenauigkeit</p></li><li><p>Ermöglicht eine gezieltere Erweiterung in RAG-Pipelines.</p></li></ul></li></ul><p><strong>2. HyDE (Hypothetisches Dokumenteneinbetten)</strong></p><ul><li><p>Eine Technik, die ein LLM verwendet, um ein hypothetisches Dokument zur Abfrageerweiterung in RAG-Systemen zu generieren.</p></li><li><p><em>Prozess:</em>  </p><ol><li><p>Eingabeanfrage an einen LLM</p></li><li><p>LLM generiert ein hypothetisches Dokument, das die Anfrage beantwortet.</p></li><li><p>Das generierte Dokument einbetten</p></li><li><p>Verwenden Sie die Einbettung für die Vektorsuche</p></li></ol></li><li><p><em>Hauptunterschied:</em> </p><ul><li><p>Traditionelles RAG: Gleicht Suchanfragen mit Dokumenten ab</p></li><li><p>HyDE: Ordnet Dokumente einander zu</p></li></ul></li><li><p><em>Zweck:</em> </p><ul><li><p>Verbesserung der Abfrageleistung, insbesondere bei komplexen oder mehrdeutigen Anfragen</p></li><li><p>Erfasst einen reichhaltigeren semantischen Kontext als eine kurze Anfrage</p></li></ul></li><li><p><em>Vorteile:</em> </p><ul><li><p>Nutzt das Wissen des LLM, um Anfragen zu erweitern</p></li><li><p>Kann potenziell die Relevanz der abgerufenen Dokumente verbessern</p></li></ul></li><li><p><em>Herausforderungen:</em> </p><ul><li><p>Erfordert zusätzliche LLM-Inferenz, was die Latenz und die Kosten erhöht.</p></li><li><p>Die Leistung hängt von der Qualität des generierten hypothetischen Dokuments ab.</p></li></ul></li></ul><p><strong>3. Rückwärtsverpackung</strong></p><ul><li><p>Eine in RAG-Systemen verwendete Technik, um Suchergebnisse neu zu ordnen, bevor sie an den LLM weitergeleitet werden.</p></li><li><p><em>Prozess:</em> </p><ol><li><p>Die Suchmaschine (z. B. Elasticsearch) gibt Dokumente in absteigender Reihenfolge ihrer Relevanz zurück.</p></li><li><p>Die Reihenfolge ist umgekehrt, das wichtigste Dokument steht nun an letzter Stelle.</p></li></ol></li><li><p><em>Zweck:</em> </p><ul><li><p>Nutzt den Aktualitätsbias von LLMs aus, die sich tendenziell stärker auf die neuesten Informationen in ihrem Kontext konzentrieren.</p></li><li><p>Gewährleistet, dass im Kontextfenster des LLM die relevantesten Informationen stets aktuell sind.</p></li></ul></li><li><p><em>Beispiel:</em> Ursprüngliche Reihenfolge: [Relevantester, Zweitwichtigster, Drittwichtigster, ...] Umgekehrte Reihenfolge: [..., Drittwichtigster, Zweitwichtigster, Relevantester]</p></li></ul><p><strong>4. Abfrageklassifizierung</strong></p><ul><li><p>Eine Technik zur Optimierung der Effizienz von RAG-Systemen durch die Bestimmung, ob eine Anfrage RAG erfordert oder direkt vom LLM beantwortet werden kann.</p></li><li><p><em>Prozess:</em> </p><ol><li><p>Entwickeln Sie einen benutzerdefinierten Datensatz, der speziell auf den verwendeten LLM zugeschnitten ist.</p></li><li><p>Trainieren Sie ein spezialisiertes Klassifizierungsmodell</p></li><li><p>Nutzen Sie das Modell, um eingehende Anfragen zu kategorisieren.</p></li></ol></li><li><p><em>Zweck:</em> </p><ul><li><p>Verbessern Sie die Systemeffizienz, indem Sie unnötige RAG-Verarbeitung vermeiden.</p></li><li><p>Direkte Anfragen an den am besten geeigneten Antwortmechanismus</p></li></ul></li><li><p><em>Anforderungen:</em> </p><ul><li><p>LLM-spezifischer Datensatz und Modell</p></li><li><p>Kontinuierliche Optimierung zur Aufrechterhaltung der Genauigkeit</p></li></ul></li><li><p><em>Vorteile:</em> </p><ul><li><p>Reduziert den Rechenaufwand für einfache Abfragen</p></li><li><p>Verbessert möglicherweise die Antwortzeit für Nicht-RAG-Anfragen</p></li></ul></li></ul><p><strong>5. Zusammenfassung</strong></p><ul><li><p>Eine Technik zur Komprimierung abgerufener Dokumente in RAG-Systemen.</p></li><li><p><em>Prozess:</em> </p><ol><li><p>Relevante Dokumente abrufen</p></li><li><p>Erstellen Sie prägnante Zusammenfassungen jedes Dokuments.</p></li><li><p>Verwenden Sie in der RAG-Pipeline Zusammenfassungen anstelle vollständiger Dokumente.</p></li></ol></li><li><p><em>Zweck:</em> </p><ul><li><p>Verbessern Sie die RAG-Performance, indem Sie sich auf wesentliche Informationen konzentrieren.</p></li><li><p>Rauschen und Störungen durch weniger relevante Inhalte reduzieren</p></li></ul></li><li><p><em>Vorteile:</em> </p><ul><li><p>Verbessert möglicherweise die Relevanz der LLM-Antworten</p></li><li><p>Ermöglicht die Einbeziehung weiterer Dokumente innerhalb der Kontextgrenzen.</p></li></ul></li><li><p><em>Herausforderungen:</em> </p><ul><li><p>Gefahr, wichtige Details in der Zusammenfassung zu verlieren</p></li><li><p>Zusätzlicher Rechenaufwand für die Zusammenfassungserstellung</p></li></ul></li></ul><p><strong>6. Einbeziehung von Metadaten</strong></p><ul><li><p>Eine Technik zur Anreicherung von Dokumenten mit zusätzlichen Kontextinformationen.</p></li><li><p><em>Metadatentypen:</em>  </p><ul><li><p>Schlüsselwörter</p></li><li><p>Titel</p></li><li><p>Termine</p></li><li><p>Angaben zur Autorschaft</p></li><li><p>Klappentexte</p></li></ul></li><li><p><em>Zweck:</em> </p><ul><li><p>Erweitern Sie die dem Ampelsystem zur Verfügung stehenden Kontextinformationen.</p></li><li><p>LLM-Studierenden ein klareres Verständnis des Dokumentinhalts und dessen Relevanz vermitteln</p></li></ul></li><li><p><em>Vorteile:</em> </p><ul><li><p>Verbessert möglicherweise die Abrufgenauigkeit</p></li><li><p>Verbessert die Fähigkeit des LLM-Programms, den Nutzen von Dokumenten zu beurteilen</p></li></ul></li><li><p><em>Durchführung:</em> </p><ul><li><p>Kann während der Dokumentenvorverarbeitung erfolgen.</p></li><li><p>Möglicherweise sind zusätzliche Datenextraktions- oder -generierungsschritte erforderlich.</p></li></ul></li></ul><p><strong>7. Zusammengesetzte Mehrfeld-Einbettungen</strong></p><ul><li><p>Eine fortschrittliche Einbettungstechnik für RAG-Systeme, die separate Einbettungen für verschiedene Dokumentkomponenten erstellt.</p></li><li><p><em>Prozess:</em> </p><ol><li><p>Relevante Felder identifizieren (z. B. Titel, Schlüsselwörter, Klappentext, Hauptinhalt)</p></li><li><p>Erzeugen Sie separate Einbettungen für jedes Feld.</p></li><li><p>Diese Einbettungen können kombiniert oder gespeichert werden, um sie beim Abruf zu verwenden.</p></li></ol></li><li><p><em>Unterschied zum Standardverfahren:</em> </p><ul><li><p>Traditionell: Einmaliges Einbetten für das gesamte Dokument</p></li><li><p>Komposit: Mehrere Einbettungen für verschiedene Dokumentaspekte</p></li></ul></li><li><p><em>Zweck:</em> </p><ul><li><p>Erstellen Sie differenziertere und kontextbezogene Dokumentendarstellungen</p></li><li><p>Informationen aus einer größeren Vielfalt von Quellen innerhalb eines Dokuments erfassen</p></li></ul></li><li><p><em>Vorteile:</em> </p><ul><li><p>Verbessert möglicherweise die Leistung bei mehrdeutigen oder vielschichtigen Anfragen.</p></li><li><p>Ermöglicht eine flexiblere Gewichtung verschiedener Dokumentaspekte bei der Recherche.</p></li></ul></li><li><p><em>Herausforderungen:</em> </p><ul><li><p>Erhöhte Komplexität bei der Einbettung von Speicher- und Abrufprozessen</p></li><li><p>Möglicherweise sind komplexere Matching-Algorithmen erforderlich.</p></li></ul></li></ul><p><strong>8. Abfrageanreicherung</strong></p><ul><li><p>Eine Technik zur Erweiterung der ursprünglichen Suchanfrage um verwandte Begriffe, um die Suchabdeckung zu verbessern.</p></li><li><p><em>Prozess:</em> </p><ol><li><p>Analysieren Sie die ursprüngliche Anfrage</p></li><li><p>Generieren Sie Synonyme und semantisch verwandte Phrasen</p></li><li><p>Erweitern Sie die Abfrage um diese zusätzlichen Begriffe</p></li></ol></li><li><p><em>Zweck:</em> </p><ul><li><p>Erhöhen Sie den Bereich potenzieller Übereinstimmungen im Dokumentenkorpus.</p></li><li><p>Verbesserung der Abfrageleistung für Anfragen mit spezifischer oder technischer Sprache</p></li></ul></li><li><p><em>Vorteile:</em> </p><ul><li><p>Ruft möglicherweise relevante Dokumente ab, die nicht exakt den ursprünglichen Suchbegriffen entsprechen.</p></li><li><p>Kann dazu beitragen, Vokabeldiskrepanz zwischen Anfragen und Dokumenten zu überwinden.</p></li></ul></li><li><p><em>Herausforderungen:</em> </p><ul><li><p>Gefahr der Abfrageabweichung bei unsachgemäßer Implementierung</p></li><li><p>Kann den Rechenaufwand im Abrufprozess erhöhen</p></li></ul></li></ul><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1#table-of-contents">Zurück nach oben</a></p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1</guid>
    <category><![CDATA[Vektordatenbank]]></category>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Han Xiang Choong]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9a4691874a19d8da/6a170b3f47d49c99f22d8a24/72b51ba2ae5e5977b56e5b915674753d6cfd0e56-1440x840.jpg" length="0" type="image/jpeg"/>
    <pubDate>Wed, 14 Aug 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Schutz sensibler und personenbezogener Daten in RAG mit Elasticsearch und LlamaIndex]]></title>
    <description><![CDATA[Wie man sensible Daten und personenbezogene Daten in einer RAG-Anwendung mit Elasticsearch und LlamaIndex schützt.]]></description>
    <content:encoded><![CDATA[<p></p><p></p><p>In diesem Beitrag werden wir uns mit Möglichkeiten zum Schutz personenbezogener Daten (PII) und sensibler Daten bei der Verwendung öffentlicher LLMs in einem RAG-Ablauf (Retrieval Augmented Generation) befassen. Wir werden untersuchen, wie man personenbezogene Daten und sensible Daten mithilfe von Open-Source-Bibliotheken und regulären Ausdrücken maskieren kann, sowie wie man lokale LLMs verwendet, um Daten zu maskieren, bevor man einen öffentlichen LLM aufruft.</p><p>Bevor wir beginnen, wollen wir einige Begriffe wiederholen, die wir in diesem Beitrag verwenden.</p><h2>Terminologie</h2><p><a href="https://www.llamaindex.ai/">LlamaIndex</a> ist ein führendes Datenframework für die Entwicklung von LLM-Anwendungen (Large Language Model). LlamaIndex bietet Abstraktionen für verschiedene Phasen der Entwicklung einer RAG-Anwendung (Retrieval Augmented Generation). Frameworks wie LlamaIndex und LangChain bieten Abstraktionen, damit Anwendungen nicht eng an die APIs eines bestimmten LLM gekoppelt werden.</p><p><a href="https://www.elastic.co/enterprise-search">Elasticsearch</a> wird von <a href="https://elastic.co/">Elastic</a> angeboten. Elastic ist ein Branchenführer hinter Elasticsearch, einem skalierbaren Datenspeicher und einer Vektordatenbank, die Volltextsuche für Präzision, Vektorsuche für semantisches Verständnis und Hybridsuche für das Beste aus beiden Welten unterstützt. Elasticsearch ist eine verteilte, RESTful-basierte Such- und Analyse-Engine, ein skalierbarer Datenspeicher und eine Vektordatenbank. Die in diesem Blog verwendeten Elasticsearch-Funktionen sind in der kostenlosen Open-Source-Version von Elasticsearch verfügbar.</p><p><a href="https://www.promptingguide.ai/techniques/rag">Retrieval-Augmented Generation (RAG)</a> ist eine KI-Technik bzw. ein KI-Muster, bei dem LLMs mit externem Wissen versorgt werden, um Antworten auf Benutzeranfragen zu generieren. Dadurch können die Antworten des LLM auf einen spezifischen Kontext zugeschnitten und weniger allgemein gehalten werden.</p><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.13/semantic-search.html">Einbettungen</a> sind numerische Repräsentationen der Bedeutung von Texten/Medien. Es handelt sich um niedrigdimensionale Darstellungen hochdimensionaler Informationen.</p><h2>RAG und Datenschutz</h2><p>Im Allgemeinen sind große Sprachmodelle (LLMs) gut darin, Antworten auf der Grundlage von im Modell verfügbaren Informationen zu generieren, die mit Internetdaten trainiert werden können. Für Anfragen, bei denen die im Modell nicht verfügbaren Informationen vorliegen, müssen die LLMs jedoch externes Wissen oder spezifische Details erhalten, die nicht im Modell enthalten sind. Solche Informationen könnten sich in Ihrer Datenbank oder Ihrem internen Wissenssystem befinden. Retrieval-Augmented Generation (RAG) ist eine Technik, bei der für eine gegebene Benutzeranfrage zunächst relevante Kontextinformationen aus externen Systemen (z. B. Ihrer Datenbank) abgerufen und diese Kontextinformationen zusammen mit der Benutzeranfrage an das LLM gesendet werden, um eine spezifischere und relevantere Antwort zu generieren.</p><p>Dadurch eignet sich die RAG-Technik hervorragend für Anwendungen in der Fragebeantwortung, der Inhaltserstellung und überall dort, wo ein tiefes Verständnis von Kontext und Details von Vorteil ist.</p><p>Daher besteht bei einer RAG-Pipeline die Gefahr, dass interne Informationen wie PII (personenbezogene Daten) und sensible Informationen (z. B. Namen, Geburtsdaten, Kontonummern usw.) öffentlichen LLMs zugänglich gemacht werden.</p><p>Obwohl Ihre Daten bei der Verwendung einer Vektordatenbank wie Elasticsearch (durch verschiedene Mechanismen wie <a href="https://www.elastic.co/guide/en/cloud-enterprise/current/ece-configure-rbac.html">rollenbasierte Zugriffskontrolle</a>, <a href="https://www.elastic.co/search-labs/blog/dls-internal-knowledge-search">Dokumentensicherheit</a> usw.) sicher sind, ist Vorsicht geboten, wenn Sie Daten an ein öffentliches LLM senden.</p><p>Der Schutz personenbezogener Daten (PII) und sensibler Daten ist bei der Verwendung großer Sprachmodelle (LLMs) aus mehreren Gründen von entscheidender Bedeutung:</p><ul><li><p><strong>Datenschutzkonformität</strong>: Viele Regionen verfügen über strenge Vorschriften, wie beispielsweise die Datenschutz-Grundverordnung (DSGVO) in Europa oder den California Consumer Privacy Act (CCPA) in den Vereinigten Staaten, die den Schutz personenbezogener Daten vorschreiben. Die Einhaltung dieser Gesetze ist notwendig, um rechtliche Konsequenzen und Geldstrafen zu vermeiden.</p></li><li><p><strong>Nutzervertrauen</strong>: Die Gewährleistung der Vertraulichkeit und Integrität sensibler Informationen schafft Nutzervertrauen. Nutzer werden Systeme, von denen sie glauben, dass sie ihre Privatsphäre schützen, eher nutzen und mit ihnen interagieren.</p></li><li><p><strong>Datensicherheit</strong>: Der Schutz vor Datenlecks ist unerlässlich. Werden sensible Daten LLMs ohne angemessene Sicherheitsvorkehrungen zugänglich gemacht, können sie gestohlen oder missbraucht werden, was zu potenziellen Schäden wie Identitätsdiebstahl oder Finanzbetrug führen kann.</p></li><li><p><strong>Ethische Überlegungen</strong>: Aus ethischer Sicht ist es wichtig, die Privatsphäre der Nutzer zu respektieren und verantwortungsvoll mit ihren Daten umzugehen. Der unsachgemäße Umgang mit personenbezogenen Daten kann zu Diskriminierung, Stigmatisierung oder anderen negativen gesellschaftlichen Auswirkungen führen.</p></li><li><p><strong>Unternehmensreputation</strong>: Unternehmen, die sensible Daten nicht schützen, können einen Reputationsschaden erleiden, der langfristige negative Auswirkungen auf ihr Geschäft haben kann, einschließlich Kunden- und Umsatzverlusten.</p></li><li><p><strong>Reduzierung des Missbrauchsrisikos</strong>: Der sichere Umgang mit sensiblen Daten trägt dazu bei, einen missbräuchlichen Einsatz der Daten oder des Modells zu verhindern, wie beispielsweise das Trainieren der Modelle mit verzerrten Daten oder die Verwendung der Daten zur Manipulation oder Schädigung von Einzelpersonen.</p></li></ul><p>Zusammenfassend lässt sich sagen, dass ein umfassender Schutz personenbezogener Daten und sensibler Daten notwendig ist, um die Einhaltung gesetzlicher Bestimmungen zu gewährleisten, das Vertrauen der Nutzer zu erhalten, die Datensicherheit sicherzustellen, ethische Standards einzuhalten, den Ruf des Unternehmens zu schützen und das Missbrauchsrisiko zu verringern.</p><h2>Kurze Zusammenfassung</h2><p>Im <a href="https://www.elastic.co/search-labs/blog/rag-with-llamaIndex-and-elasticsearch">vorherigen Beitrag</a> haben wir besprochen, wie man ein Q&amp;A-Erlebnis mit einer RAG-Technik und Elasticsearch als Vektordatenbank unter Verwendung von LlamaIndex und einem lokal laufenden Mistral LLM implementiert. Hier bauen wir darauf auf.</p><p>Das Lesen des vorherigen Beitrags ist optional, da wir nun kurz besprechen/zusammenfassen werden, was wir im vorherigen Beitrag behandelt haben.</p><p>Wir verfügten über einen Beispieldatensatz mit Callcenter-Gesprächen zwischen Agenten und Kunden eines fiktiven Hausratversicherungsunternehmens. Wir haben eine einfache RAG-Anwendung entwickelt, die Fragen wie „Für welche Art von wasserbezogenen Problemen reichen Kunden Schadensmeldungen ein?“ beantwortet.</p><p>Im Großen und Ganzen sah der Ablauf so aus.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9d3882da43bfdac0/6a17050867045bd5fe45c0e9/9d51295472f8bcca3d1973248acb724f8b94767e-1054x555.png" alt="RAG Flow" /><p>Während der Indexierungsphase haben wir Dokumente mithilfe der LlamaIndex-Pipeline geladen und indexiert. Die Dokumente wurden in Abschnitte unterteilt und zusammen mit ihren Einbettungen in der Elasticsearch-Vektordatenbank gespeichert.</p><p>Während der Abfragephase, als der Benutzer eine Frage stellte, ermittelte LlamaIndex die K ähnlichsten Dokumente, die für die Abfrage relevant waren. Diese Top-K relevanten Dokumente wurden zusammen mit der Anfrage an das lokal laufende Mistral LLM gesendet, das dann die Antwort generierte, die an den Benutzer zurückgesendet wurde. Sie können sich gerne den vorherigen Beitrag durchlesen oder <a href="https://github.com/srikanthmanvi/RAG-InsuranceCompany/tree/main">den Code erkunden</a>.</p><p>Im vorherigen Beitrag hatten wir LLM lokal am Laufen. Im Produktionsbetrieb kann es jedoch sinnvoll sein, ein externes LLM von verschiedenen Anbietern wie <a href="https://openai.com/">OpenAI</a>, <a href="https://mistral.ai/">Mistral</a>, <a href="https://www.anthropic.com/claude">Anthropic</a> usw. zu verwenden. Es könnte daran liegen, dass Ihr Anwendungsfall ein größeres Basismodell erfordert oder dass eine lokale Ausführung aufgrund von Anforderungen der Unternehmensproduktion wie Skalierbarkeit, Verfügbarkeit, Leistung usw. nicht möglich ist.</p><p>Die Einbindung eines externen LLM in Ihre RAG-Pipeline birgt das Risiko, dass sensible Daten und personenbezogene Daten unbeabsichtigt an die LLMs gelangen. In diesem Beitrag werden wir Möglichkeiten zur Maskierung personenbezogener Daten im Rahmen Ihres RAG-Prozesses untersuchen, bevor Sie Dokumente an einen externen LLM senden.</p><h2>RAG mit einem öffentlichen LLM</h2><p>Bevor wir darauf eingehen, wie Sie Ihre personenbezogenen Daten und sensiblen Informationen in einer RAG-Pipeline schützen können, werden wir zunächst eine einfache RAG-Anwendung mit LlamaIndex, der Elasticsearch Vector-Datenbank und OpenAI LLM erstellen.</p><h3>Voraussetzungen</h3><p>Wir benötigen Folgendes.</p><ul><li><p><strong>Elasticsearch</strong> ist als Vektordatenbank zum Speichern der Einbettungen eingerichtet und betriebsbereit. Folgen Sie den Anweisungen aus dem vorherigen Beitrag zur <a href="https://www.elastic.co/search-labs/blog/rag-with-llamaIndex-and-elasticsearch#install-elasticsearch">Installation von Elasticsearch</a>.</p></li><li><p>OpenAI-API-Schlüssel.</p></li></ul><h3>Einfache RAG-Anwendung</h3><p>Zur Information: Der vollständige Code befindet sich in diesem <a href="https://github.com/srikanthmanvi/RAG-InsuranceCompany/tree/protecting-pii">GitHub-Repository</a>(Branch:protecting-pii). Das Klonen des Repositorys ist optional, da wir den Code im Folgenden genauer betrachten werden.</p><p>Erstellen Sie in Ihrer bevorzugten IDE eine neue Python-Anwendung mit den folgenden 3 Dateien.</p><ul><li><p><code>index.py</code> Hierhin wird der Code für die Indizierung von Daten eingefügt.</p></li><li><p><code>query.py</code> Hier wird der Code für Abfragen und die Interaktion mit LLM eingefügt.</p></li><li><p><code>.env</code> dort, wo Konfigurationseigenschaften wie API-Schlüssel gespeichert werden.</p></li></ul><p>Wir müssen einige Pakete installieren. Wir beginnen damit, eine neue <a href="https://docs.python.org/3/library/venv.html">virtuelle Python-Umgebung</a> im Stammverzeichnis Ihrer Anwendung zu erstellen.</p>python3 -m venv .venv
<p>Aktivieren Sie die virtuelle Umgebung und installieren Sie die unten aufgeführten erforderlichen Pakete.</p>source .venv/bin/activate
pip install llama-index 
pip install llama-index-embeddings-openai
pip install llama-index-vector-stores-elasticsearch
pip install sentence-transformers
pip install python-dotenv
pip install openai
<p>Konfigurieren Sie die Verbindungseigenschaften von OpenAI und Elasticsearch in der .env-Datei. Datei.</p>OPENAI_API_KEY="REPLACEME"
ELASTIC_CLOUD_ID="REPLACEME"
ELASTIC_API_KEY="REPLACEME"
<h4>Indexierungsdaten</h4><p>Laden Sie die Datei <a href="https://github.com/srikanthmanvi/RAG-InsuranceCompany/blob/main/conversations.json">conversations.json</a> herunter, die <em>Konversationen</em> zwischen Kunden und Callcenter-Mitarbeitern unseres fiktiven Hausversicherungsunternehmens enthält. Platzieren Sie die Datei im Stammverzeichnis der Anwendung zusammen mit den beiden Python-Dateien und der .env-Datei. die Datei, die Sie zuvor erstellt haben. Nachfolgend ein Beispiel für den Inhalt der Datei.</p>{
"conversation_id": 103,
"customer_name": "Sophia Jones",
"agent_name": "Emily Wilson",
"policy_number": "JKL0123",
"conversation": "Customer: Hi, I'm Sophia Jones. My Date of Birth is November 15th, 1985, Address is 303 Cedar St, Miami, FL 33101, and my Policy Number is JKL0123.\nAgent: Hello, Sophia. How may I assist you today?\nCustomer: Hello, Emily. I have a question about my policy.\nCustomer: There's been a break-in at my home, and some valuable items are missing. Are they covered?\nAgent: Let me check your policy for coverage related to theft.\nAgent: Yes, theft of personal belongings is covered under your policy.\nCustomer: That's a relief. I'll need to file a claim for the stolen items.\nAgent: We'll assist you with the claim process, Sophia. Is there anything else I can help you with?\nCustomer: No, that's all for now. Thank you for your assistance, Emily.\nAgent: You're welcome, Sophia. Please feel free to reach out if you have any further questions or concerns.\nCustomer: I will. Have a great day!\nAgent: You too, Sophia. Take care.",
"summary": "A customer inquires about coverage for stolen items after a break-in at home, and the agent confirms that theft of personal belongings is covered under the policy. The agent offers assistance with the claim process, resulting in the customer expressing relief and gratitude."
}
<p>Fügen Sie den unten stehenden Code in <code>index.py</code> ein, der sich um die Indizierung der Daten kümmert.</p># index.py
# pip install sentence-transformers
# pip install llama-index-embeddings-openai
# pip install llama-index-embeddings-huggingface

import json
import os
from dotenv import load_dotenv
from llama_index.core import Document
from llama_index.core import Settings
from llama_index.core.ingestion import IngestionPipeline
from llama_index.core.node_parser import SentenceSplitter
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.vector_stores.elasticsearch import ElasticsearchStore


def get_documents_from_file(file):
   """Reads a json file and returns list of Documents"""

   with open(file=file, mode='rt') as f:
       conversations_dict = json.loads(f.read())

   # Build Document objects using fields of interest.
   documents = [Document(text=item['conversation'],
                         metadata={"conversation_id": item['conversation_id']})
                for
                item in conversations_dict]
   return documents

# Load .env file contents into env
load_dotenv('.env')
Settings.embed_model = HuggingFaceEmbedding(
   model_name="BAAI/bge-small-en-v1.5"
)

def main():
   # ElasticsearchStore is a VectorStore that
   # takes care of Elasticsearch Index and Data management.
   es_vector_store = ElasticsearchStore(index_name="convo_index",
                                        vector_field='conversation_vector',
                                        text_field='conversation',
                                        es_cloud_id=os.getenv("ELASTIC_CLOUD_ID"),
                                        es_api_key=os.getenv("ELASTIC_API_KEY"))

   # LlamaIndex Pipeline configured to take care of chunking, embedding
   # and storing the embeddings in the vector store.
   llamaindex_pipeline = IngestionPipeline(
       transformations=[
           SentenceSplitter(chunk_size=350, chunk_overlap=50),
           Settings.embed_model
       ],
       vector_store=es_vector_store
   )

   # Load data from a json file into a list of LlamaIndex Documents
   documents = get_documents_from_file(file="conversations.json")
   llamaindex_pipeline.run(documents=documents)
   print(".....Indexing Data Completed.....\n")

if __name__ == "__main__":
   main()
<p>Wenn Sie den obigen Code ausführen, wird ein Index in Elasticsearch erstellt und die Einbettungen werden im Elasticsearch-Index mit dem Namen <code>convo_index</code> gespeichert.</p><p>Falls Sie eine Erläuterung zur LlamaIndex IngestionPipeline benötigen, lesen Sie bitte den vorherigen Beitrag im Abschnitt <a href="https://www.elastic.co/search-labs/blog/rag-with-llamaIndex-and-elasticsearch#indexing-data">"IngestionPipeline erstellen"</a>.</p><h4>Abfrage</h4><p>Im vorherigen Beitrag haben wir ein lokales LLM für <a href="https://www.elastic.co/search-labs/blog/rag-with-llamaIndex-and-elasticsearch#querying">Abfragen</a> verwendet.</p><p>In diesem Beitrag verwenden wir das öffentliche LLM OpenAI, wie unten dargestellt.</p># query.py
from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.llms.openai import OpenAI
from index import es_vector_store

# Public LLM where we send user query and Related Documents
llm = OpenAI()

index = VectorStoreIndex.from_vector_store(es_vector_store)

# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the LLM.
# Note that documents are sent as-is. So any PII/Sensitive data is sent to the LLM.
query_engine = index.as_query_engine(llm, similarity_top_k=10)

query="Give me summary of water related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
result = query_engine.query(bundle)
print(result)
<p>Der obige Code gibt die Antwort von OpenAI wie folgt aus.</p><p>Kunden haben verschiedene Ansprüche im Zusammenhang mit Wasser geltend gemacht, darunter Probleme wie Wasserschäden in Kellern, geplatzte Rohre, Hagelschäden an Dächern sowie die Ablehnung von Ansprüchen aufgrund von Gründen wie mangelnder rechtzeitiger Meldung, Wartungsmängeln, allmählichem Verschleiß und bereits bestehenden Schäden. In allen Fällen äußerten die Kunden ihre Frustration über die Ablehnung ihrer Ansprüche und forderten eine faire Bewertung und Entscheidung in Bezug auf ihre Ansprüche.</p><h2>Maskierung von PII in RAG</h2><p>Was wir bisher behandelt haben, beinhaltet das Senden von Dokumenten unverändert zusammen mit der Benutzeranfrage an OpenAI.</p><p>In der RAG-Pipeline haben wir, nachdem der relevante Kontext aus einem Vektorspeicher abgerufen wurde, die Möglichkeit, personenbezogene Daten und sensible Informationen zu maskieren, bevor wir die Anfrage und den Kontext an das LLM senden.</p><p>Es gibt verschiedene Möglichkeiten, personenbezogene Daten zu maskieren, bevor man sie an ein externes LLM sendet, wobei jede ihre eigenen Vorzüge hat. Wir betrachten einige der folgenden Optionen.</p><ol><li><p>Verwendung von NLP-Bibliotheken wie spacy.io oder <a href="https://microsoft.github.io/presidio/">Presidio</a> (Open-Source-Bibliothek, die von Microsoft gepflegt wird).</p></li><li><p>Verwendung von LlamaIndex direkt aus der Verpackung <code>NERPIINodePostprocessor.</code></p></li><li><p>Nutzung lokaler LLMs über <code>PIINodePostprocessor</code></p></li></ol><p>Sobald Sie die Maskierungslogik mithilfe einer der oben genannten Methoden implementiert haben, können Sie die LlamaIndex IngestionPipeline mit einem PostProcessor konfigurieren (entweder mit einem eigenen benutzerdefinierten PostProcessor oder mit einem der standardmäßig verfügbaren PostProcessors von LlamaIndex).</p><h3>Verwendung von NLP-Bibliotheken</h3><p>Im Rahmen der RAG-Pipeline könnten wir sensible Daten mithilfe von NLP-Bibliotheken maskieren. In dieser Demo verwenden wir das spacy.io-Paket.</p><p>Erstellen Sie eine neue Datei <code>query_masking_nlp.py</code> und fügen Sie den unten stehenden Code ein.</p># query_masking_nlp.py

# pip install spacy
# python3 - m spacy download en_core_web_sm
import re
from typing import List, Optional

import spacy
from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.core.postprocessor.types import BaseNodePostprocessor
from llama_index.core.schema import NodeWithScore
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.openai import OpenAI
from index import es_vector_store

# Load the spaCy model
nlp = spacy.load("en_core_web_sm")

# Compile regex patterns for performance
phone_pattern = re.compile(r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b')
email_pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b')
date_pattern = re.compile(r'\b(\d{1,2}[-/]\d{1,2}[-/]\d{2,4}|\d{2,4}[-/]\d{1,2}[-/]\d{1,2})\b')
dob_pattern = re.compile(
r"(January|February|March|April|May|June|July|August|September|October|November|December)\s(\d{1,2})(st|nd|rd|th),\s(\d{4})")
address_pattern = re.compile(r'\d+\s+[\w\s]+\,\s+[A-Za-z]+\,\s+[A-Z]{2}\s+\d{5}(-\d{4})?')
zip_code_pattern =  re.compile(r'\b\d{5}(?:-\d{4})?\b')
policy_number_pattern = re.compile(r"[A-Z]{3}\d{4}\.$")  # 3 characters followed by 4 digits, in our case e.g XYZ9876

Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")

# match = re.match(policy_number_pattern, "XYZ9876")
# print(match)


def mask_pii(text):
   """
   Masks Personally Identifiable Information (PII) in the given
   text using pre-defined regex patterns and spaCy's named entity recognition.
   Args:
       text (str): The input text containing potential PII.
   Returns:
       str: The text with PII masked.
   """

   # Process the text with spaCy for NER
   doc = nlp(text)

   # Mask entities identified by spaCy NER (e.g First/Last Names etc)
   for ent in doc.ents:
       if ent.label_ in ["PERSON", "ORG", "GPE"]:
           text = text.replace(ent.text, '[MASKED]')

   # Apply regex patterns after NER to avoid overlapping issues
   text = phone_pattern.sub('[PHONE MASKED]', text)
   text = email_pattern.sub('[EMAIL MASKED]', text)
   text = date_pattern.sub('[DATE MASKED]', text)
   text = address_pattern.sub('[ADDRESS MASKED]', text)
   text = dob_pattern.sub('[DOB MASKED]', text)
   text = zip_code_pattern.sub('[ZIP MASKED]', text)
   text = policy_number_pattern.sub('[POLICY MASKED]', text)

   return text


class CustomPostProcessor(BaseNodePostprocessor):
   """
   Custom Postprocessor which masks Personally Identifiable Information (PII).
   PostProcessor is called on the Documents before they are sent to the LLM.
   """
   def _postprocess_nodes(
           self, nodes: List[NodeWithScore], query_bundle: Optional[QueryBundle]
   ) -&gt; List[NodeWithScore]:
       # Masks PII
       for n in nodes:
          n.node.set_content(mask_pii(n.text))
       return nodes

   
# Use Public LLM to send user query and Related Documents
llm = OpenAI()
index = VectorStoreIndex.from_vector_store(es_vector_store)

# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the LLM.
# Note that documents are masked based on custom logic defined in CustomPostProcessor._postprocess_nodes.
query_engine = index.as_query_engine(llm, similarity_top_k=10, node_postprocessors=[CustomPostProcessor()])



query = "Give me summary of water related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
response = query_engine.query(bundle)
print(response)

<p>Die Antwort des LLM ist unten dargestellt.</p>Kunden haben verschiedene Ansprüche im Zusammenhang mit Wasser geltend gemacht, darunter Probleme wie Wasserschäden in Kellern, geplatzte Rohre, Hagelschäden an Dächern und Überschwemmungen bei Starkregen. Diese Ansprüche haben zu Frustrationen geführt, da Ansprüche aus Gründen wie mangelnder rechtzeitiger Meldung, Wartungsproblemen, allmählichem Verschleiß und bereits vorhandenen Schäden abgelehnt wurden. Kunden äußerten Enttäuschung, Stress und finanzielle Belastung infolge dieser Ablehnungen ihrer Ansprüche und forderten faire Bewertungen und gründliche Überprüfungen. Einige Kunden sahen sich zudem mit Verzögerungen bei der Schadensregulierung konfrontiert, was zu weiterer Unzufriedenheit mit dem Service der Versicherungsgesellschaft führte.<p>Im obigen Code geben wir beim Erstellen der Llama Index QueryEngine einen CustomPostProcessor an.</p><p>Die Logik, die von der QueryEngine aufgerufen wird, ist in der Methode <code>_postprocess_nodes</code> von <code>CustomPostProcessor</code> definiert. Wir verwenden die SpaCy.io-Bibliothek, um benannte Entitäten in unseren Daten zu erkennen, und verwenden dann einige reguläre Ausdrücke, um diese Namen sowie sensible Informationen zu ersetzen, bevor wir die Dokumente an das LLM senden.</p><p>Nachfolgend finden Sie beispielhaft Ausschnitte aus den Originalkonversationen und der vom CustomPostProcessor erstellten maskierten Konversation.</p><p>Originaltext:</p>Kunde: Hallo, ich bin Matthew Lopez, geboren am 12. Oktober 1984, und wohne in 456 Cedar St, Smalltown, NY 34567. Meine Versicherungsnummer lautet TUV8901. Agent: Guten Tag, Matthew. Wie kann ich Ihnen heute behilflich sein? Kunde: Hallo, ich bin äußerst enttäuscht über die Entscheidung Ihres Unternehmens, meinen Antrag abzulehnen.<p>Maskierter Text durch den CustomPostProcessor.</p>Kunde: Hallo, ich bin [MASKED], [MASKED] ist [DOB MASKED], und ich wohne in der Cedar St 456, [MASKED], [MASKED] 34567. Meine Versicherungsnummer lautet [MASKED]. Agent: Guten Tag, [MASKE]. Wie kann ich Ihnen heute behilflich sein? Kunde: Hallo, ich bin äußerst enttäuscht über die Entscheidung Ihres Unternehmens, meinen Antrag abzulehnen.<p>Notiz:</p><p><em>Das Identifizieren und Maskieren von personenbezogenen Daten und sensiblen Informationen ist keine einfache Aufgabe. Die Berücksichtigung verschiedener Formate und Semantiken sensibler Informationen erfordert ein gutes Verständnis Ihres Fachgebiets und Ihrer Daten. Auch wenn der oben dargestellte Code für einige Anwendungsfälle funktionieren mag, müssen Sie ihn möglicherweise an Ihre Bedürfnisse und Tests anpassen.</em></p><h3>Verwendung des LlamaIndex direkt aus der Verpackung <code>NERPIINodePostprocessor</code></h3><p>LlamaIndex hat den Schutz personenbezogener Daten in einer RAG-Pipeline durch die Einführung vereinfacht. <code>NERPIINodePostprocessor.</code></p>from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.core.postprocessor import NERPIINodePostprocessor
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.openai import OpenAI
from index import es_vector_store

Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")

# Use Public LLM to send user query and Related Documents
llm = OpenAI()

ner_processor = NERPIINodePostprocessor()
index = VectorStoreIndex.from_vector_store(es_vector_store)

# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the LLM.
# Note that documents masked using the NERPIINodePostprocessor so that PII/Sensitive data is not sent to the LLM.
query_engine = index.as_query_engine(llm, similarity_top_k=10, node_postprocessors=[ner_processor])

query = "Give me summary of fire related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
response = query_engine.query(bundle)
print(response)
<p>Die Antwort sieht wie folgt aus:</p>Kunden haben im Zusammenhang mit Bränden Schadensansprüche an ihren Immobilien geltend gemacht. In einem Fall wurde ein Anspruch auf Schadensersatz für einen Brandschaden an einer Garage abgelehnt, da Brandstiftung vom Versicherungsschutz ausgeschlossen ist. Ein anderer Kunde reichte eine Schadensmeldung wegen eines Brandschadens an seinem Haus ein, der durch seine Versicherungspolice abgedeckt war. Darüber hinaus meldete ein Kunde einen Küchenbrand und erhielt die Zusicherung, dass der Brandschaden abgedeckt sei.<h3>Nutzung lokaler LLMs über <code>PIINodePostprocessor</code></h3><p>Alternativ könnten wir auch ein lokal oder in Ihrem privaten Netzwerk laufendes LLM nutzen, um die Maskierung durchzuführen, bevor die Daten an ein öffentliches LLM gesendet werden.</p><p>Wir werden Mistral, das auf Ollama auf Ihrem lokalen Rechner läuft, für die Maskierung verwenden.</p><h4>Mistral lokal ausführen</h4><p>Laden Sie <a href="https://ollama.com/">Ollama</a> herunter und installieren Sie es. Nach der Installation von Ollama führen Sie diesen Befehl aus, um <a href="https://ollama.com/library/mistral">Mistral</a>herunterzuladen und auszuführen.</p>ollama run mistral
<p>Das Herunterladen und erstmalige lokale Ausführen des Modells kann einige Minuten dauern. Prüfen Sie, ob Mistral weht, indem Sie eine Frage wie die folgende stellen: „Schreibe ein Gedicht über Wolken“ und prüfen Sie, ob Ihnen das Gedicht gefällt. Bitte lassen Sie ollama laufen, da wir später über Code mit dem Mistral-Modell interagieren müssen.</p><p>Erstellen Sie eine neue Datei namens <code>query_masking_local_LLM.py</code> und fügen Sie den unten stehenden Code ein.</p># pip install llama-index-llms-ollama
from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.core.postprocessor import PIINodePostprocessor
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.ollama import Ollama
from llama_index.llms.openai import OpenAI
from index import es_vector_store

Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")

# Use Public LLM to send user query and Related Documents and Local LLM to mask
public_llm = OpenAI()
local_llm = Ollama(model="mistral")

pii_processor = PIINodePostprocessor(llm=local_llm)
index = VectorStoreIndex.from_vector_store(es_vector_store)

# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the public LLM.
# Note that documents are masked using the local llm via PIINodePostprocessor
# so that PII/Sensitive data is not sent to the public LLM.
query_engine = index.as_query_engine(public_llm, similarity_top_k=10, node_postprocessors=[pii_processor])


query = "Give me summary of fire related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
result = query_engine.query(bundle)
print(result)
<p>Die Antwort sieht in etwa so aus wie unten dargestellt.</p>Kunden haben im Zusammenhang mit Bränden Schadensansprüche an ihren Immobilien geltend gemacht. In einem Fall wurde ein Anspruch auf Schadensersatz für einen Brandschaden an einer Garage abgelehnt, da Brandstiftung vom Versicherungsschutz ausgeschlossen ist. Ein anderer Kunde reichte eine Schadensmeldung wegen eines Brandschadens an seinem Haus ein, der durch seine Versicherungspolice abgedeckt war. Darüber hinaus meldete ein Kunde einen Küchenbrand und erhielt die Zusicherung, dass der Brandschaden abgedeckt sei.<h3>Fazit</h3><p>In diesem Beitrag haben wir gezeigt, wie Sie personenbezogene Daten und sensible Daten beim Einsatz öffentlicher LLMs in einem RAG-Flow schützen können. Wir haben verschiedene Wege aufgezeigt, wie dies erreicht werden kann. Es wird dringend empfohlen, diese Ansätze anhand Ihres Anwendungsfalls und Ihrer Bedürfnisse zu testen, bevor Sie sie übernehmen.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/rag-security-masking-pii</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/rag-security-masking-pii</guid>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Srikanth Manvi]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9d3882da43bfdac0/6a17050867045bd5fe45c0e9/9d51295472f8bcca3d1973248acb724f8b94767e-1054x555.png" length="0" type="image/png"/>
    <pubDate>Thu, 25 Jul 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[RAG (Retrieval Augmented Generation) mit LlamaIndex, Elasticsearch und Mistral]]></title>
    <description><![CDATA[Lernen Sie, wie Sie ein RAG-System (Retrieval Augmented Generation) mit LlamaIndex, Elasticsearch und lokal ausgeführtem Mistral implementieren.]]></description>
    <content:encoded><![CDATA[<p>In diesem Blogbeitrag werden wir erläutern, wie man ein Q&amp;A-Erlebnis mithilfe einer RAG-Technik (Retrieval Augmented Generation) und Elasticsearch als Vektordatenbank implementiert. Wir werden LlamaIndex und ein lokal laufendes Mistral LLM verwenden.</p><p>Bevor wir anfangen, werden wir uns einige Fachbegriffe ansehen.</p><h3>Terminologie</h3><p><a href="https://www.llamaindex.ai/">LlamaIndex</a> ist ein führendes Datenframework für die Entwicklung von LLM-Anwendungen (Large Language Model). LlamaIndex bietet Abstraktionen für verschiedene Phasen der Entwicklung einer RAG-Anwendung (Retrieval Augmented Generation). Frameworks wie LlamaIndex und LangChain bieten Abstraktionen, damit Anwendungen nicht eng an die APIs eines bestimmten LLM gekoppelt werden.</p><p><a href="https://www.elastic.co/enterprise-search">Elasticsearch</a> wird von <a href="https://elastic.co/">Elastic</a> angeboten. Elastic ist ein Branchenführer hinter Elasticsearch, einer Such- und Analyse-Engine, die Volltextsuche für Präzision, Vektorsuche für semantisches Verständnis und Hybridsuche für das Beste aus beiden Welten unterstützt. Elasticsearch ist ein skalierbarer Datenspeicher und eine Vektordatenbank. Die in diesem Blog verwendeten Elasticsearch-Funktionen sind in der kostenlosen Open-Source-Version von Elasticsearch verfügbar.</p><p><a href="https://www.promptingguide.ai/techniques/rag">Retrieval Augment Generation (RAG)</a> ist eine KI-Technik bzw. ein KI-Muster, bei dem LLMs mit externem Wissen ausgestattet werden, um Antworten auf Benutzeranfragen zu generieren. Dadurch können die LLM-Antworten auf den jeweiligen Kontext zugeschnitten werden und sind spezifischer.</p><p><a href="https://docs.mistral.ai/">Mistral</a> bietet sowohl Open-Source- als auch optimierte LLM-Modelle für Unternehmen an. In diesem Tutorial verwenden wir deren Open-Source-Modell <a href="https://docs.mistral.ai/models/#mistral-7b">Mistral-7b</a> , das auf Ihrem Laptop läuft. Falls Sie das Modell nicht auf Ihrem Laptop ausführen möchten, können Sie alternativ die Cloud-Version nutzen. In diesem Fall müssen Sie den Code in diesem Blog anpassen, um die richtigen API-Schlüssel und Pakete zu verwenden.</p><p><a href="https://ollama.com/">Ollama</a> hilft dabei, LLMs lokal auf Ihrem Laptop auszuführen. Wir werden Ollama verwenden, um das Open-Source-Modell Mistral-7b lokal auszuführen.</p><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.13/semantic-search.html">Einbettungen</a> sind numerische Repräsentationen der Bedeutung von Texten/Medien. Es handelt sich um niedrigdimensionale Darstellungen hochdimensionaler Informationen.</p><h3>Erstellung einer RAG-Anwendung mit LlamaIndex, Elasticsearch und Mistral: Szenarioübersicht</h3><p><strong>Szenario:</strong></p><p>Wir verfügen über einen Beispieldatensatz (als JSON-Datei) mit Callcenter-Gesprächen zwischen Agenten und Kunden eines fiktiven Hausratversicherungsunternehmens. Wir werden eine einfache RAG-Anwendung entwickeln, die Fragen wie diese beantworten kann:</p><p><code>Give me summary of water related issues.</code></p><h3>Hoher Durchfluss</h3><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9d3882da43bfdac0/6a17050867045bd5fe45c0e9/9d51295472f8bcca3d1973248acb724f8b94767e-1054x555.png" alt="RAG Flow" /><p>Wir betreiben Mistral LLM lokal mit Ollama.</p><p>Als nächstes laden wir <em>Konversationen</em> aus der JSON-Datei als <code>Documents</code> in den <a href="https://developers.llamaindex.ai/python/examples/vector_stores/elasticsearchindexdemo/">ElasticsearchStore</a> (einen VectorStore, der von Elasticsearch unterstützt wird). Beim Laden der Dokumente erstellen wir Einbettungen mithilfe des lokal laufenden Mistral-Modells. Wir speichern diese Einbettungen zusammen mit den <em>Konversationen</em> im LlamaIndex Elasticsearch Vector Store (<a href="https://developers.llamaindex.ai/python/examples/vector_stores/elasticsearchindexdemo/">ElasticsearchStore</a>).</p><p>Wir konfigurieren eine LlamaIndex IngestionPipeline und stellen ihr den lokal verwendeten LLM zur Verfügung, in diesem Fall Mistral, das über Ollama läuft.</p><p>Wenn wir eine Frage stellen wie „Geben Sie mir eine Zusammenfassung der wichtigsten wasserbezogenen Probleme.“ Elasticsearch führt eine semantische Suche durch und liefert <em>Konversationen</em> zum Thema Wasser. Diese <em>Konversationen</em> werden zusammen mit der ursprünglichen Frage an das lokal laufende LLM gesendet, um eine Antwort zu generieren.</p><h3>Schritte zum Erstellen der RAG-Anwendung</h3><h4>Mistral lokal ausführen</h4><p>Laden Sie <a href="https://ollama.com/">Ollama</a> herunter und installieren Sie es. Nach der Installation von Ollama führen Sie diesen Befehl aus, um <a href="https://ollama.com/library/mistral">Mistral</a>herunterzuladen und auszuführen.</p>ollama run mistral
<p>Das Herunterladen und erstmalige lokale Ausführen des Modells kann einige Minuten dauern. Prüfen Sie, ob Mistral weht, indem Sie eine Frage wie die folgende stellen: „Schreibe ein Gedicht über Wolken“ und prüfen Sie, ob Ihnen das Gedicht gefällt. Bitte lassen Sie ollama laufen, da wir später über Code mit dem Mistral-Modell interagieren müssen.</p><h4>Elasticsearch installieren</h4><p>Elasticsearch lässt sich entweder durch Erstellen einer Cloud-Bereitstellung (<a href="https://www.elastic.co/search-labs/tutorials/install-elasticsearch/elastic-cloud">Anleitung hier</a>) oder durch Ausführen in Docker (<a href="https://www.elastic.co/search-labs/tutorials/install-elasticsearch/docker">Anleitung hier</a>) in Betrieb nehmen. Sie können auch eine produktionsreife, selbstgehostete Elasticsearch-Bereitstellung erstellen, indem Sie <a href="https://www.elastic.co/search-labs/tutorials/install-elasticsearch/docker#self-hosted-production-deployments">hier</a> beginnen.</p><p>Sofern Sie die Cloud-Bereitstellung nutzen, besorgen Sie sich den API-Schlüssel und die Cloud-ID für die Bereitstellung, wie in der Anleitung beschrieben. Wir werden sie später verwenden.</p><h4>RAG-Anwendung</h4><p>Der vollständige Code ist als Referenz in diesem <a href="https://github.com/srikanthmanvi/RAG-InsuranceCompany">GitHub-Repository</a> zu finden. Das Klonen des Repos ist optional, da wir den Code im Folgenden durchgehen werden.</p><p>Erstellen Sie in Ihrer bevorzugten IDE eine neue Python-Anwendung mit den folgenden 3 Dateien.</p><ul><li><p><code>index.py</code> Hierhin wird der Code für die Indizierung von Daten eingefügt.</p></li><li><p><code>query.py</code> Hier wird der Code für Abfragen und die Interaktion mit LLM eingefügt.</p></li><li><p><code>.env</code> dort, wo Konfigurationseigenschaften wie API-Schlüssel gespeichert werden.</p></li></ul><p>Wir müssen einige Pakete installieren. Wir beginnen damit, eine neue <a href="https://docs.python.org/3/library/venv.html">virtuelle Python-Umgebung</a> im Stammverzeichnis Ihrer Anwendung zu erstellen.</p>python3 -m venv .venv
<p>Aktivieren Sie die virtuelle Umgebung und installieren Sie die unten aufgeführten erforderlichen Pakete.</p>source .venv/bin/activate
pip install llama-index 
pip install llama-index-embeddings-ollama
pip install llama-index-llms-ollama
pip install llama-index-vector-stores-elasticsearch
pip install sentence-transformers
pip install python-dotenv
<h4>Indexierungsdaten</h4><p>Laden Sie die Datei <a href="https://github.com/srikanthmanvi/RAG-InsuranceCompany/blob/main/conversations.json">conversations.json</a> herunter, die <em>Konversationen</em> zwischen Kunden und Callcenter-Mitarbeitern unseres fiktiven Hausversicherungsunternehmens enthält. Platzieren Sie die Datei im Stammverzeichnis der Anwendung zusammen mit den beiden Python-Dateien und der .env-Datei. die Datei, die Sie zuvor erstellt haben. Nachfolgend ein Beispiel für den Inhalt der Datei.</p>{
    "conversation_id": 103,
    "customer_name": "Sophia Jones",
    "agent_name": "Emily Wilson",
    "policy_number": "JKL0123",
    "conversation": "Customer: Hi, I'm Sophia Jones. My Date of Birth is November 15th, 1985, Address is 303 Cedar St, Miami, FL 33101, and my Policy Number is JKL0123.\nAgent: Hello, Sophia. How may I assist you today?\nCustomer: Hello, Emily. I have a question about my policy.\nCustomer: There's been a break-in at my home, and some valuable items are missing. Are they covered?\nAgent: Let me check your policy for coverage related to theft.\nAgent: Yes, theft of personal belongings is covered under your policy.\nCustomer: That's a relief. I'll need to file a claim for the stolen items.\nAgent: We'll assist you with the claim process, Sophia. Is there anything else I can help you with?\nCustomer: No, that's all for now. Thank you for your assistance, Emily.\nAgent: You're welcome, Sophia. Please feel free to reach out if you have any further questions or concerns.\nCustomer: I will. Have a great day!\nAgent: You too, Sophia. Take care.",
    "summary": "A customer inquires about coverage for stolen items after a break-in at home, and the agent confirms that theft of personal belongings is covered under the policy. The agent offers assistance with the claim process, resulting in the customer expressing relief and gratitude."
}
<p>Wir definieren eine Funktion namens <code>get_documents_from_file</code> in <code>index.py</code> , die die JSON-Datei liest und eine Liste von Dokumenten erstellt. <a href="https://docs.llamaindex.ai/en/stable/module_guides/loading/documents_and_nodes/">Dokumentobjekte</a> sind die grundlegende Informationseinheit, mit der LlamaIndex arbeitet.</p># index.py
import json, os
from llama_index.core import Document, Settings
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core.ingestion import IngestionPipeline
from llama_index.embeddings.ollama import OllamaEmbedding
from llama_index.vector_stores.elasticsearch import ElasticsearchStore
from dotenv import load_dotenv

def get_documents_from_file(file):
   """Reads a json file and returns list of Documents"""

   with open(file=file, mode='rt') as f:
       conversations_dict = json.loads(f.read())
      
   # Build Document objects using fields of interest.
   documents = [Document(text=item['conversation'],
                         metadata={"conversation_id": item['conversation_id']})
                for
                item in conversations_dict]
   return documents
<p>IngestionPipeline erstellen</p><p>Fügen Sie zunächst die Elasticsearch CloudID und die API-Schlüssel, die Sie im Abschnitt <code>Install Elasticsearch</code> erhalten haben, in die Datei <code>.env</code> ein. Ihre <code>.env</code> -Datei sollte wie folgt aussehen (mit realen Werten).</p>ELASTIC_CLOUD_ID=&lt;REPLACE WITH YOUR CLOUD ID&gt;
ELASTIC_API_KEY=&lt;REPLACE WITH YOUR API_KEY&gt;
<p>Mit LlamaIndex <a href="https://docs.llamaindex.ai/en/stable/module_guides/loading/ingestion_pipeline/">IngestionPipeline</a> können Sie eine Pipeline aus mehreren Komponenten zusammensetzen. Fügen Sie den unten stehenden Code in die Datei <code>index.py</code> ein.</p># index.py

# Load .env file contents into env
# ELASTIC_CLOUD_ID and ELASTIC_API_KEY are expected to be in the .env file.
load_dotenv('.env')

# ElasticsearchStore is a VectorStore that
# takes care of ES Index and Data management.
es_vector_store = ElasticsearchStore(index_name="calls",
                                     vector_field='conversation_vector',
                                     text_field='conversation',
                                     es_cloud_id=os.getenv("ELASTIC_CLOUD_ID"),
                                     es_api_key=os.getenv("ELASTIC_API_KEY"))


def main():
    # Embedding Model to do local embedding using Ollama.
    ollama_embedding = OllamaEmbedding("mistral")

    # LlamaIndex Pipeline configured to take care of chunking, embedding
    # and storing the embeddings in the vector store.
    pipeline = IngestionPipeline(
        transformations=[
            SentenceSplitter(chunk_size=350, chunk_overlap=50),
            ollama_embedding,
        ],
        vector_store=es_vector_store
    )

    # Load data from a json file into a list of LlamaIndex Documents
    documents = get_documents_from_file(file="conversations.json")

    pipeline.run(documents=documents)
    print(".....Done running pipeline.....\n")


if __name__ == "__main__":
    main()

<p>Wie bereits erwähnt, kann die LlamaIndex IngestPipeline aus mehreren Komponenten zusammengesetzt sein. Wir fügen der Pipeline in Zeile <code>pipeline = IngestionPipeline(...</code> 3 Komponenten hinzu.</p><ul><li><p><a href="https://docs.llamaindex.ai/en/stable/module_guides/loading/node_parsers/modules/?h=sentencesp#sentencesplitter">SentenceSplitter</a>: Wie aus der Definition von <code>get_documents_from_file()</code> hervorgeht, verfügt jedes Dokument über ein Textfeld, das die in der JSON-Datei gefundene Konversation enthält. Dieses Textfeld enthält einen langen Text. Damit die semantische Suche gut funktioniert, muss der Text in kleinere Abschnitte unterteilt werden. Die Klasse <a href="https://docs.llamaindex.ai/en/stable/module_guides/loading/node_parsers/modules/?h=sentencesp#sentencesplitter">SentenceSplitter</a> erledigt das für uns. Diese Abschnitte werden in der LlamaIndex-Terminologie als Knoten bezeichnet. Die Knoten enthalten Metadaten, die auf das Dokument verweisen, zu dem sie gehören. Alternativ können Sie auch Elasticsearch Ingestpipeline für das Chunking verwenden, wie in diesem <a href="https://www.elastic.co/search-labs/blog/chunking-via-ingest-pipelines">Blog</a> gezeigt.</p></li><li><p><a href="https://docs.llamaindex.ai/en/stable/module_guides/models/embeddings/">OllamaEmbedding</a>: Embedding-Modelle wandeln einen Textabschnitt in Zahlen (auch Vektoren genannt) um. Die numerische Darstellung ermöglicht uns die <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/semantic-search.html">semantische Suche,</a> bei der die Suchergebnisse der Bedeutung des Wortes entsprechen, anstatt nur eine Textsuche durchzuführen. Wir stellen der IngestionPipeline <code>OllamaEmbedding("mistral")</code> zur Verfügung. Die mit SentenceSplitter aufgeteilten Chunks werden über Ollama an das auf Ihrem lokalen Rechner laufende Mistral-Modell gesendet. Mistral erstellt dann Einbettungen für die Chunks.</p></li><li><p><a href="https://developers.llamaindex.ai/python/examples/vector_stores/elasticsearchindexdemo/">ElasticsearchStore</a>: Der LlamaIndex ElasticsearchStore-Vektorspeicher sichert die in einen Elasticsearch-Index erstellten Einbettungen. ElasticsearchStore kümmert sich um das Erstellen und Befüllen des angegebenen Elasticsearch-Index mit Inhalten. Beim Erstellen des ElasticsearchStore (referenziert durch <code>es_vector_store</code>) geben wir den Namen des Elasticsearch-Index an, den wir erstellen möchten (<code>calls</code> in unserem Fall ), das Feld im Index, in dem die Einbettungen gespeichert werden sollen (<code>conversation_vector</code> in unserem Fall ) und das Feld, in dem der Text gespeichert werden soll (<code>conversation</code> in unserem Fall ). Zusammenfassend lässt sich sagen, dass auf Basis unserer Konfiguration <code>ElasticsearchStore</code> ein neuer Index in Elasticsearch mit <code>conversation_vector</code> und <code>conversation</code> als Feldern (neben anderen automatisch erstellten Feldern) erstellt wird.</p></li></ul><p>Um das Ganze zusammenzuführen, starten wir die Pipeline durch den Aufruf von <code>pipeline.run(documents=documents)</code>.</p><p>Führen Sie das Skript index.py aus, um die Ingest-Pipeline zu starten:</p>python index.py
<p>Sobald der Pipeline-Lauf abgeschlossen ist, sollte in Elasticsearch ein neuer Index mit dem Namen <code>calls</code> angezeigt werden. Wenn Sie eine einfache Elasticsearch-Abfrage über die Entwicklerkonsole ausführen, sollten Sie die geladenen Daten zusammen mit den Einbettungen sehen können.</p>GET calls/_search?size=1
<p>Zusammenfassend lässt sich sagen, dass wir bisher Dokumente aus einer JSON-Datei erstellt, diese in Abschnitte unterteilt, Einbettungen für diese Abschnitte erstellt und die Einbettungen (sowie die Textkonversation) in einem Vektorspeicher (ElasticsearchStore) gespeichert haben.</p><h4>Abfrage</h4><p>Mit dem llamaIndex <a href="https://docs.llamaindex.ai/en/stable/module_guides/indexing/vector_store_guide/">VectorStoreIndex</a> können Sie relevante Dokumente abrufen und Daten abfragen. Standardmäßig speichert VectorStoreIndex Einbettungen im Arbeitsspeicher in einem <a href="https://docs.llamaindex.ai/en/stable/module_guides/indexing/vector_store_guide/">SimpleVectorStore</a>. Alternativ können jedoch externe Vektorspeicher (wie <a href="https://developers.llamaindex.ai/python/examples/vector_stores/elasticsearchindexdemo/">ElasticsearchStore</a>) verwendet werden, um die Einbettungen persistent zu machen.</p><p>Öffnen Sie <code>query.py</code> und fügen Sie den folgenden Code ein.</p># query.py
from llama_index.core import VectorStoreIndex, QueryBundle, Response, Settings
from llama_index.embeddings.ollama import OllamaEmbedding
from llama_index.llms.ollama import Ollama
from index import es_vector_store

# Local LLM to send user query to
local_llm = Ollama(model="mistral")
Settings.embed_model= OllamaEmbedding("mistral")

index = VectorStoreIndex.from_vector_store(es_vector_store)
query_engine = index.as_query_engine(local_llm, similarity_top_k=10)

query="Give me summary of water related issues"
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
result = query_engine.query(bundle)
print(result)
<p>Wir definieren ein lokales LLM (<code>local_llm</code>), das auf das Mistral-Modell verweist, das auf Ollama läuft. Als nächstes erstellen wir einen VectorStoreIndex (<code>index</code>) aus dem zuvor erstellten ElasticsearchStore-Vektorspeicher und erhalten dann eine Abfrage-Engine aus dem Index. Beim Erstellen der Abfrage-Engine verweisen wir auf das lokale LLM, das zur Beantwortung verwendet werden soll. Wir geben außerdem (<code>similarity_top_k=10</code>) an, um die Anzahl der Dokumente zu konfigurieren, die aus dem Vektorspeicher abgerufen und an das LLM gesendet werden sollen, um eine Antwort zu erhalten.</p><p>Führen Sie das Skript <code>query.py</code> aus, um den RAG-Ablauf auszuführen:</p>python query.py
<p>Wir senden die Anfrage <code>Give me summary of water related issues</code> (Sie können <code>query</code> gerne anpassen) und die Antwort des LLM, die mit zugehörigen Dokumenten geliefert wird, sollte in etwa wie folgt aussehen.</p>Im gegebenen Kontext sehen wir mehrere Fälle, in denen Kunden nach einer Deckung für Wasserschäden gefragt haben. In zwei Fällen verursachten Überschwemmungen Schäden an Kellern, in einem weiteren Fall waren Dachlecks das Problem. Die Agenten bestätigten, dass beide Arten von Wasserschäden durch ihre jeweiligen Versicherungsbedingungen abgedeckt sind. Daher sind Probleme im Zusammenhang mit Wasser, wie Überschwemmungen und Dachlecks, typischerweise durch Wohngebäudeversicherungen abgedeckt.<h4>Einige Einschränkungen:</h4><p>Dieser Blogbeitrag ist eine Einführung für Anfänger in die RAG-Technik mit Elasticsearch und lässt daher die Konfiguration von Funktionen aus, die es Ihnen ermöglichen, diesen Ausgangspunkt in die Produktion zu überführen. Bei der Entwicklung für Produktionsanwendungen sollten Sie komplexere Aspekte berücksichtigen, wie z. B. die Möglichkeit, Ihre Daten mit <a href="https://www.elastic.co/search-labs/blog/dls-internal-knowledge-search">Document Level Security</a> zu schützen, Ihre Daten im Rahmen einer Elasticsearch <a href="https://www.elastic.co/search-labs/blog/chunking-via-ingest-pipelines">Ingest-Pipeline</a> in Chunking-Aufteilung aufzuteilen oder sogar andere <a href="https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-overview.html">ML-Jobs</a> auf denselben Daten auszuführen, die für GenAI/Chat/Q&amp;A-Anwendungsfälle verwendet werden.</p><p>Sie könnten auch in Erwägung ziehen, Daten aus verschiedenen externen Quellen (z. B. Azure Blob Storage, Dropbox, Gmail usw.) zu beziehen und Einbettungen mithilfe von <a href="https://www.elastic.co/guide/en/enterprise-search/current/connectors.html">Elastic Connectors</a> zu erstellen.</p><p>Elastic macht all das und noch viel mehr möglich und bietet eine umfassende Lösung auf Unternehmensebene für GenAI-Anwendungsfälle und darüber hinaus.</p><h4>Was kommt als Nächstes?</h4><ul><li><p>Möglicherweise ist Ihnen aufgefallen, dass wir 10 thematisch zusammenhängende Konversationen zusammen mit der Benutzerfrage an das LLM senden, damit dieses eine Antwort formulieren kann. Diese Gespräche können personenbezogene Daten (PII) wie Name, Geburtsdatum, Adresse usw. enthalten. In unserem Fall ist das LLM lokal, daher ist ein Datenleck kein Problem. Wenn Sie jedoch ein LLM in der Cloud (z. B. OpenAI) verwenden möchten, ist es nicht wünschenswert, Texte zu senden, die personenbezogene Daten enthalten. In einem Folgeblogbeitrag werden wir sehen, wie man personenbezogene Daten maskiert, bevor man sie im RAG-Flow an externe LLMs sendet.</p></li><li><p>In diesem Beitrag haben wir ein lokales LLM verwendet. Im kommenden Beitrag über die Maskierung personenbezogener Daten in RAG werden wir uns ansehen, wie man einfach von einem lokalen LLM zu einem öffentlichen LLM wechseln kann.</p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/rag-with-llamaIndex-and-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/rag-with-llamaIndex-and-elasticsearch</guid>
    <category><![CDATA[KI]]></category>
    <dc:creator><![CDATA[Srikanth Manvi]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9d3882da43bfdac0/6a17050867045bd5fe45c0e9/9d51295472f8bcca3d1973248acb724f8b94767e-1054x555.png" length="0" type="image/png"/>
    <pubDate>Fri, 12 Apr 2024 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>