Spring AI und Elasticsearch als Ihre Vektordatenbank

Entwicklung einer kompletten KI-Anwendung mit Spring AI und Elasticsearch.

Elasticsearch verfügt über native Integrationen mit den branchenführenden Gen-AI-Tools und -Anbietern. Sehen Sie sich unsere Webinare zu den Themen „RAG-Grundlagen“ oder zum „Erstellen produktionsreifer Apps“ mit der Elastic-Vektordatenbank an.

Um die besten Suchlösungen für Ihren Anwendungsfall zu entwickeln, starten Sie jetzt eine kostenlose Cloud-Testversion oder testen Sie Elastic auf Ihrem lokalen Rechner.

Spring AI ist jetzt allgemein verfügbar, die erste stabile Version 1.0 steht auf Maven Central zum Download bereit. Lass es uns gleich nutzen, um eine vollständige KI-Anwendung zu erstellen, mit deinem bevorzugten LLM und unserer bevorzugten Vektordatenbank. Oder stürzen Sie sich direkt in das Repository mit der fertigen Anwendung.

Was ist Spring AI?

Spring AI 1.0, 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.

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.

Spring AI bietet Unterstützung für verschiedene KI-Modelle und -Technologien, wie zum Beispiel:

  • Bildmodelle: Generieren von Bildern anhand von Textvorgaben.
  • Transkriptionsmodelle: Sie nehmen Audioquellen und wandeln sie in Text um.
  • Einbettungsmodelle: Beliebige Daten werden in Vektoren umgewandelt, die für die semantische Ähnlichkeitssuche optimiert sind.
  • Chat-Modelle: diese Sollte bekannt sein! Sie haben zweifellos schon einmal ein kurzes Gespräch mit einem geführt.

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.

Spring AI-Lösungen für KI-Herausforderungen

Lassen Sie uns einige dieser Probleme und ihre Lösungen in Spring AI durchgehen.

ProblemLösung
KonsistenzChat-Models sind aufgeschlossen und lassen sich leicht ablenken.Sie können ihnen eine Systemvorgabe geben, um ihre Gesamtform und Struktur zu steuern.
ErinnerungKI-Modelle haben kein Gedächtnis, daher können sie keine Nachrichten von verschiedenen Nutzern miteinander verknüpfen.Sie können ihnen ein Speichersystem zur Verfügung stellen, um die relevanten Teile des Gesprächs zu speichern.
IsolierungKI-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.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.
Private DatenKI-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!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.
HalluzinationKI-Chatmodelle unterhalten sich gerne! Und manchmal tun sie das so selbstsicher, dass sie sich Dinge ausdenken können.Sie müssen eine Evaluierung durchführen – also ein Modell verwenden, um die Ausgabe eines anderen zu validieren –, um plausible Ergebnisse zu bestätigen.

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. Modellkontextprotokoll (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 agentenbasierten Arbeitsabläufen zusammenfassen, die auf ein übergeordnetes Ziel hinarbeiten.

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 Spring Initializrverfügbar.

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.

Warum Elasticsearch?

Elasticsearch ist eine Volltextsuchmaschine, das wissen Sie wahrscheinlich schon. Warum verwenden wir es also für dieses Projekt? Nun ja, es ist auch ein Vektorshop! Und zwar eine ziemlich gute, bei der die Daten direkt neben dem vollständigen Text stehen. Weitere bemerkenswerte Vorteile:

  • Super einfach einzurichten
  • Opensource
  • Horizontal skalierbar
  • Die meisten Freitextdaten Ihrer Organisation befinden sich wahrscheinlich bereits in einem Elasticsearch-Cluster.
  • Vollständige Suchmaschinenfunktion
  • Vollständig in Spring AI integriert!

Alles in allem erfüllt Elasticsearch alle Anforderungen an einen hervorragenden Vektorspeicher. Also lasst uns ihn einrichten und mit der Entwicklung unserer Anwendung beginnen!

Erste Schritte mit Elasticsearch

Wir benötigen sowohl Elasticsearch als auch Kibana, die Benutzeroberfläche, mit der Sie mit den in der Datenbank gespeicherten Daten interagieren werden.

Dank der praktischen Docker-Images und der Elastic.co-Homepage können Sie alles auf Ihrem lokalen Rechner ausprobieren. Gehe dorthin, scrolle nach unten, um den Befehl curl zu finden, führe ihn aus und leite ihn direkt in deine Shell weiter:

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.

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 http://localhost:5601 auf.

Beachten Sie auch den Benutzernamen elastic und das Passwort, die in der Konsole ausgegeben werden: Sie benötigen diese zum Anmelden (in der obigen Beispielausgabe sind dies elastic bzw. w1GB15uQ).

Die App zusammenführen

Rufen Sie die Spring Initializr- Seite auf und generieren Sie ein neues Spring AI-Projekt mit den folgenden Abhängigkeiten:

  • Elasticsearch Vector Store
  • Spring Boot Actuator
  • GraalVM
  • OpenAI
  • Web

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.

Klicken Sie auf Generate und entpacken Sie anschließend das Projekt und importieren Sie es in Ihre bevorzugte IDE. (Wir verwenden IntelliJ IDEA.)

Das Wichtigste zuerst: Legen wir die Verbindungsdetails für Ihre Spring Boot-Anwendung fest. Schreiben Sie in application.properties, Folgendes:

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:

In dieser Demo verwenden wir OpenAI , genauer gesagt das Embedding Model und das Chat Model (Sie können gerne den Dienst Ihrer Wahl verwenden, solange Spring AI ihn unterstützt).

Das Embedding-Modell wird benötigt, um Einbettungen der Daten zu erstellen, bevor wir sie in Elasticsearch speichern. Damit OpenAI funktioniert, müssen wir API key angeben:

Sie können sie als Umgebungsvariable wie SPRING_AI_OPENAI_API_KEY definieren, um zu vermeiden, dass die Anmeldeinformationen in Ihrem Quellcode gespeichert werden.

Wir werden Dateien hochladen. Stellen Sie daher sicher, dass Sie anpassen, wie viele Daten in den Servlet-Container hochgeladen werden können:

Wir haben es fast geschafft! Bevor wir uns ans Programmieren machen, werfen wir einen Blick darauf, wie das Ganze funktionieren wird.

Auf unserem Rechner haben wir die folgende Datei heruntergeladen (eine Liste der Regeln für ein Brettspiel), sie in test.pdf umbenannt und in ~/Downloads/test.pdf abgelegt.

Die Datei wird an den Endpunkt /rag/ingest gesendet (ersetzen Sie den Pfad entsprechend Ihrer lokalen Konfiguration):

Das könnte ein paar Sekunden dauern…

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.

In diesen Daten und allen darin enthaltenen Einbettungen geschieht die Magie. Anschließend können wir Elasticsearch über die VectorStore -Schnittstelle abfragen.

Der vollständige Ablauf sieht folgendermaßen aus:

  • Der HTTP-Client lädt Ihre ausgewählte PDF-Datei in die Spring-Anwendung hoch.
  • Spring AI übernimmt die Textextraktion aus unserem PDF und unterteilt jede Seite in 800 Zeichen lange Abschnitte.
  • OpenAI generiert die Vektordarstellung für jeden Chunk.
  • Sowohl der segmentierte Text als auch die Einbettung werden anschließend in Elasticsearch gespeichert.

Zum Schluss stellen wir eine Anfrage:

Und wir erhalten eine relevante Antwort:

Toll! Wie funktioniert das alles?

  • Der HTTP-Client übermittelt die Frage an die Spring-Anwendung.
  • Spring AI erhält die Vektordarstellung der Frage von OpenAI.
  • Durch diese Einbettung sucht es in den gespeicherten Elasticsearch-Chunks nach ähnlichen Dokumenten und ruft die ähnlichsten Dokumente ab.
  • Spring AI sendet dann die Frage und den abgerufenen Kontext an OpenAI, um eine LLM-Antwort zu generieren.
  • Schließlich gibt es die generierte Antwort und einen Verweis auf den abgerufenen Kontext zurück.

Lasst uns einen Blick in den Java-Code werfen, um zu sehen, wie er wirklich funktioniert.

Zunächst einmal zur Main- Klasse: Es handelt sich um eine standardmäßige Hauptklasse für jede beliebige Spring Boot-Anwendung.

Dort gibt es nichts zu sehen. Weiter geht’s…

Als nächstes ein einfacher HTTP-Controller:

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.

Schauen wir uns den Service an:

Dieser Code übernimmt die gesamte Datenaufnahme: Ausgehend von einem Spring Framework Resource, das ein Container um Bytes ist, lesen wir die PDF-Daten (vermutlich eine .PDF -Datei - stellen Sie sicher, dass Sie dies überprüfen, bevor Sie beliebige Eingaben akzeptieren!) mit Spring AIs PagePdfDocumentReader und tokenisieren sie dann mit Spring AIs TokenTextSplitter. Schließlich fügen wir die resultierenden List<Document>-Objekte der VectorStore -Implementierung ElasticsearchVectorStore hinzu.

Sie können dies mit Kibana bestätigen: Nachdem Sie eine Datei an den Endpunkt /rag/ingest gesendet haben, öffnen Sie Ihren Browser unter localhost:5601 und navigieren Sie im Seitenmenü auf der linken Seite zu Dev Tools. Dort können Sie Abfragen stellen, um mit den Daten in der Elasticsearch-Instanz zu interagieren.

Stellen Sie eine Anfrage wie diese:

Und nun zum spannenden Teil: Wie erhalten wir diese Daten wieder als Antwort auf Benutzeranfragen?

Hier ist ein erster Entwurf für die Implementierung der Abfrage in einer Methode namens directRag.

Der Code ist recht einfach, aber wir werden ihn in mehrere Schritte unterteilen:

  1. Verwenden Sie VectorStore , um eine Ähnlichkeitssuche durchzuführen.
  2. Ausgehend von allen Ergebnissen werden die zugrunde liegenden Spring AI Documents ermittelt und deren Text extrahiert, der anschließend zu einem einzigen Ergebnis zusammengefügt wird.
  3. Sende die Ergebnisse von VectorStore 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.

Dies ist RAG – 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: Die Berater von Spring AI sind dazu da, diesen Prozess noch weiter zu vereinfachen.

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:

Füge der Klasse eine weitere Methode namens advisedRag(String question) hinzu:

Die gesamte RAG-Musterlogik ist in QuestionAnswerAdvisor gekapselt. Alles andere ist genau so, wie jede andere Anfrage an ChatModel wäre! Hübsch!

Den vollständigen Code finden Sie auf GitHub.

Fazit

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.

Zunächst können Sie den Spring Boot Actuator 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.

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 Micrometer.io erfasst werden):

Starten Sie Ihre Anwendung neu. Führe eine Abfrage durch und gehe dann zu: http://localhost:8080/actuator/metrics. Suchen Sie nach „ token“ 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- Integration für Elasticsearch nutzen, um diese Metriken zu übertragen und Elasticsearch als Ihre bevorzugte Zeitreihendatenbank zu verwenden!

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 virtuellen Threads ausgeliefert, die die Skalierbarkeit deutlich verbessern. Aktivieren Sie es mit:

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 Elastic Cloud 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!

Zugehörige Inhalte

Sind Sie bereit, hochmoderne Sucherlebnisse zu schaffen?

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

Probieren Sie es selbst aus