Spring AI et Elasticsearch comme base de données vectorielle

Construire une application d'IA complète en utilisant Spring AI et Elasticsearch.

Elasticsearch dispose d'intégrations natives avec les outils et fournisseurs d'IA générative leaders du secteur. Consultez nos webinars sur le dépassement des bases de RAG ou sur la création d'applications prêtes à l'emploi avec la Base vectorielle Elastic.

Pour élaborer les meilleures solutions de recherche pour votre cas d'utilisation, commencez un essai gratuit d'Elastic Cloud ou essayez Elastic sur votre machine locale dès maintenant.

Spring AI est maintenant disponible, avec sa première version stable 1.0 prête à être téléchargée sur Maven Central. Utilisons-le immédiatement pour construire une application d'IA complète, en utilisant votre LLM favori et notre base de données vectorielle préférée. Ou plongez directement dans le référentiel avec l'application finale.

Qu'est-ce que l'IA de printemps ?

Spring AI 1.0, une solution complète pour l'ingénierie de l'IA en Java, est maintenant disponible après une période de développement significative influencée par les progrès rapides dans le domaine de l'IA. Cette version comprend de nombreuses nouvelles fonctionnalités essentielles pour les ingénieurs en IA.

Java et Spring sont les mieux placés pour profiter de la vague de l'IA. Des tonnes d'entreprises utilisent Spring Boot, ce qui facilite grandement l'intégration de l'IA dans ce qu'elles font déjà. Vous pouvez relier votre logique d'entreprise et vos données à ces modèles d'IA sans trop de difficultés.

Spring AI prend en charge différents modèles et technologies d'IA, tels que :

  • Modèles d'images: générer des images à partir de textes.
  • Modèles de transcription: prendre des sources audio et les convertir en texte.
  • Modèles d'intégration : convertissent des données arbitraires en vecteurs, qui sont des types de données optimisés pour la recherche de similarités sémantiques.
  • Modèles de chat : ces devraient vous être familiers ! Vous avez sans doute déjà eu une brève conversation avec l'un d'entre eux.

Les modèles de dialogue en ligne sont ceux qui semblent le plus faire parler d'eux dans le domaine de l'IA, et à juste titre, ils sont géniaux ! Ils peuvent vous aider à corriger un document ou à écrire un poème. (Ne leur demandez pas de raconter une blague... pour l'instant). Ils sont géniaux, mais ils ont quelques problèmes.

Des solutions d'IA de printemps pour relever les défis de l'IA

Examinons quelques-uns de ces problèmes et leurs solutions dans Spring AI.

ProblèmeSolution
CohérenceLes modèles de chat sont ouverts d'esprit et enclins à la distraction.Vous pouvez les doter d'un système d'incitation pour régir leur forme et leur structure générales
MémoireLes modèles d'IA n'ont pas de mémoire et ne peuvent donc pas établir de corrélation entre les messages d'un utilisateur donné et ceux d'un autre utilisateur.Vous pouvez leur donner un système de mémoire pour stocker les parties pertinentes de la conversation
L'isolementLes modèles d'IA vivent dans de petits bacs à sable isolés, mais ils peuvent faire des choses vraiment étonnantes si vous leur donnez accès à des outils - des fonctions qu'ils peuvent invoquer lorsqu'ils le jugent nécessaireSpring AI prend en charge l'appel d'outils, ce qui vous permet d'indiquer au modèle d'IA les outils présents dans son environnement, qu'il peut ensuite vous demander d'invoquer. Cette interaction à plusieurs tours est gérée de manière transparente pour vous
Données privéesLes modèles d'IA sont intelligents, mais ils ne sont pas omniscients ! Ils ne savent pas ce que contiennent vos bases de données propriétaires - et nous pensons que vous ne voudriez pas qu'ils le sachent !Vous devez informer leurs réponses en remplissant les invites, c'est-à-dire en utilisant le puissant opérateur de concaténation de chaînes pour insérer du texte dans la demande avant que le modèle n'examine la question posée. Des informations de base, si vous voulez. Comment décidez-vous de ce qui doit être envoyé et de ce qui ne doit pas l'être ? Utilisez un magasin de vecteurs pour sélectionner uniquement les données pertinentes et les envoyer ensuite. C'est ce que l'on appelle la génération augmentée par récupération (RAG).
HallucinationLes modèles de chat de l'IA aiment discuter ! Et parfois, ils le font avec tant d'assurance qu'ils peuvent inventer des chosesVous devez recourir à l'évaluation - en utilisant un modèle pour valider les résultats d'un autre - pour confirmer des résultats raisonnables.

Bien entendu, aucune application d'IA n'est isolée. Aujourd'hui, les systèmes et services d'IA modernes fonctionnent mieux lorsqu'ils sont intégrés à d'autres systèmes et services. Model Context Protocol (MCP) permet de connecter vos applications d'intelligence artificielle à d'autres services basés sur MCP, quel que soit le langage dans lequel elles sont écrites. Vous pouvez assembler tous ces éléments dans des flux de travail agentiques qui mènent à un objectif plus large.

Le plus beau ? Vous pouvez faire tout cela en vous appuyant sur les idiomes et abstractions familiers auxquels tout développeur Spring Boot est habitué : des dépendances de départ pratiques pour pratiquement tout sont disponibles sur Spring Initializr.

Spring AI fournit des autoconfigurations Spring Boot pratiques qui vous donnent la configuration conventionnelle sur la configuration que vous connaissez et attendez. Spring AI prend en charge l'observabilité avec l'Actuator de Spring Boot et le projet Micrometer. Il est également compatible avec GraalVM et les threads virtuels, ce qui vous permet de créer des applications d'IA super rapides et efficaces qui évoluent.

Pourquoi Elasticsearch ?

Elasticsearch est un moteur de recherche plein texte, vous le savez probablement. Alors pourquoi l'utiliser pour ce projet ? C'est aussi un magasin de vecteurs ! Il s'agit d'un excellent outil, dans lequel les données sont placées à côté du texte intégral. Autres avantages notables :

  • Très facile à mettre en place
  • Opensource
  • Évolutivité horizontale
  • La plupart des données libres de votre organisation se trouvent probablement déjà dans un cluster Elasticsearch.
  • Fonctionnalité de moteur de recherche complète
  • Entièrement intégré à Spring AI!

Si l'on tient compte de tous ces éléments, Elasticsearch remplit toutes les conditions d'un excellent magasin de vecteurs, alors configurons-le et commençons à construire notre application !

Prise en main d'Elasticsearch

Nous allons avoir besoin d'Elasticsearch et de Kibana, la console d'interface utilisateur que vous utiliserez pour interagir avec les données hébergées dans la base de données.

Vous pouvez tout essayer sur votre machine locale grâce aux images Docker et à la page d'accueil d'Elastic.co. Allez-y, faites défiler vers le bas pour trouver la commande curl, exécutez-la et envoyez-la directement dans votre shell :

Il suffit de tirer et de configurer des images Docker pour Elasticsearch et Kibana, et après quelques minutes, elles seront opérationnelles sur votre machine locale, avec les informations d'identification de connexion.

Vous avez également deux urls différentes que vous pouvez utiliser pour interagir avec votre instance Elasticsearch. Suivez les instructions et dirigez votre navigateur vers http://localhost:5601.

Notez également le nom d'utilisateur elastic et le mot de passe affichés sur la console : vous en aurez besoin pour vous connecter (dans l'exemple ci-dessus, il s'agit respectivement de elastic et w1GB15uQ).

L'intégration de l'application

Allez sur la page Spring Initializr et générez un nouveau projet Spring AI avec les dépendances suivantes :

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

Veillez à choisir la dernière et la meilleure version de Java (idéalement Java 24 - au moment de la rédaction de ce document - ou une version plus récente) et l'outil de construction de votre choix. Nous utilisons Apache Maven dans cet exemple.

Cliquez sur Generate, puis décompressez le projet et importez-le dans l'IDE de votre choix. (Nous utilisons IntelliJ IDEA.)

Commençons par le commencement : spécifions les détails de la connexion pour votre application Spring Boot. Sur application.properties,, écrivez ce qui suit :

Nous allons également utiliser la capacité de stockage vectoriel de Spring AI pour initialiser tout ce qui est nécessaire du côté d'Elasticsearch en termes de structures de données, donc spécifier :

Nous allons utiliser OpenAI dans cette démo, en particulier le modèle d'intégration et le modèle de conversation (n'hésitez pas à utiliser le service que vous préférez, tant que Spring AI le prend en charge).

Le modèle d'intégration est nécessaire pour créer des intégrations des données avant de les stocker dans Elasticsearch. Pour qu'OpenAI fonctionne, nous devons spécifier l'adresse API key:

Vous pouvez la définir comme une variable d'environnement telle que SPRING_AI_OPENAI_API_KEY pour éviter d'avoir à la stocker dans votre code source.

Nous allons télécharger des fichiers, donc assurez-vous de personnaliser la quantité de données pouvant être téléchargées vers le conteneur de servlet :

Nous y sommes presque ! Avant de nous plonger dans l'écriture du code, donnons un aperçu de la manière dont cela va fonctionner.

Sur notre machine, nous avons téléchargé le fichier suivant (une liste de règles pour un jeu de société), l'avons renommé en test.pdf et l'avons placé dans ~/Downloads/test.pdf.

Le fichier sera envoyé au point de terminaison /rag/ingest (remplacez le chemin d'accès en fonction de votre configuration locale) :

Cela peut prendre quelques secondes...

En coulisses, les données sont envoyées à OpenAI, qui crée des enchâssements de données ; ces données sont ensuite écrites dans Elasticsearch, à la fois les vecteurs et le texte d'origine.

C'est à partir de ces données, et de tous les enchâssements qu'elles contiennent, que la magie opère. Nous pouvons ensuite interroger Elasticsearch à l'aide de l'interface VectorStore.

Le flux complet se présente comme suit :

  • Le client HTTP télécharge le PDF de votre choix vers l'application Spring.
  • Spring AI se charge de l'extraction du texte de notre PDF et découpe chaque page en morceaux de 800 caractères.
  • OpenAI génère la représentation vectorielle pour chaque morceau.
  • Le texte fragmenté et l'intégration sont ensuite stockés dans Elasticsearch.

Enfin, nous émettrons une requête :

Et nous obtiendrons une réponse pertinente :

C'est bien ! Comment cela fonctionne-t-il ?

  • Le client HTTP soumet la question à l'application Spring.
  • Spring AI obtient la représentation vectorielle de la question auprès d'OpenAI.
  • Cette intégration permet de rechercher des documents similaires dans les morceaux Elasticsearch stockés et d'extraire les documents les plus similaires.
  • Spring AI envoie ensuite la question et le contexte récupéré à OpenAI pour générer une réponse LLM.
  • Enfin, il renvoie la réponse générée et une référence au contexte récupéré.

Plongeons dans le code Java pour voir comment cela fonctionne réellement.

Tout d'abord, la classe Main: il s'agit d'une classe principale standard pour n'importe quelle application Spring Boot.

Il n'y a rien à voir. Continuons...

Ensuite, un contrôleur HTTP de base :

Le contrôleur appelle simplement un service que nous avons construit pour gérer l'ingestion de fichiers et leur écriture dans la base de données vectorielles Elasticsearch, puis pour faciliter les requêtes sur cette même base de données vectorielles.

Examinons le service :

Ce code gère l'ensemble de l'ingestion : étant donné un Spring Framework Resource, qui est un conteneur d'octets, nous lisons les données PDF (présumées être un fichier .PDF - assurez-vous de le valider avant d'accepter des entrées arbitraires !) à l'aide de Spring AI PagePdfDocumentReader, puis nous les tokenisons à l'aide de Spring AI TokenTextSplitter, et enfin nous ajoutons les List<Document>s résultants à l'implémentation de VectorStore, ElasticsearchVectorStore.

Vous pouvez le confirmer en utilisant Kibana : après avoir envoyé un fichier au point de terminaison /rag/ingest, ouvrez votre navigateur sur localhost:5601 et, dans le menu latéral de gauche, naviguez vers Dev Tools. Vous pouvez y émettre des requêtes pour interagir avec les données de l'instance Elasticsearch.

Emettez une requête comme celle-ci :

Passons maintenant aux choses sérieuses : comment récupérer ces données en réponse à des requêtes d'utilisateurs ?

Voici un premier aperçu de la mise en œuvre de la requête, dans une méthode appelée directRag.

Le code est assez simple, mais nous allons le décomposer en plusieurs étapes :

  1. Utilisez le site VectorStore pour effectuer une recherche de similitude.
  2. Étant donné tous les résultats, récupérer les Documents sous-jacents de Spring AI et extraire leur texte, en les concaténant tous en un seul résultat.
  3. Envoyer les résultats du site VectorStore au modèle, accompagnés d'une invite indiquant au modèle ce qu'il doit en faire et de la question de l'utilisateur. Attendez la réponse et renvoyez-la.

Il s'agit de la RAG (retrieval augmented generation). Il s'agit de l'idée que nous utilisons des données provenant d'un magasin de vecteurs pour informer le traitement et l'analyse effectués par le modèle. Maintenant que vous savez comment faire, espérons que vous n'aurez jamais à le faire ! En tout cas, pas de cette manière : Les conseillers de Spring AI sont là pour simplifier encore davantage ce processus.

Advisors vous permet de pré- et post-traiter une requête vers un modèle donné, en plus de fournir une couche d'abstraction entre votre application et le magasin de vecteurs. Ajoutez la dépendance suivante à votre construction :

Ajoutez une autre méthode appelée advisedRag(String question) à la classe :

Toute la logique du modèle RAG est encapsulée dans le site QuestionAnswerAdvisor. Pour le reste, tout se passe comme n'importe quelle demande adressée à ChatModel! C'est bien !

Vous pouvez obtenir le code complet sur GitHub.

Conclusion

Dans cette démo, nous avons utilisé des images Docker et tout fait sur notre machine locale, mais l'objectif ici est de construire des systèmes et des services d'IA dignes d'une production. Il y a plusieurs choses que vous pouvez faire pour que cela devienne une réalité.

Tout d'abord, vous pouvez ajouter Spring Boot Actuator pour surveiller la consommation de jetons. Les jetons sont une approximation du coût de la complexité (et parfois du coût en dollars) d'une demande donnée au modèle.

Vous avez déjà l'Actuator Spring Boot sur le classpath, il suffit donc de spécifier les propriétés suivantes pour afficher toutes les métriques (capturées par le magnifique projet Micrometer.io ) :

Redémarrez votre application. Effectuez une recherche, puis rendez-vous sur : http://localhost:8080/actuator/metrics. Recherchez "token" et vous verrez des informations sur les jetons utilisés par l'application. Veillez à garder un œil sur ce point. Vous pouvez bien sûr utiliser l' intégration de Micrometer pour Elasticsearch pour pousser ces métriques et faire en sorte qu'Elasticsearch agisse comme votre base de données de séries temporelles de choix, aussi !

Il faut alors considérer que chaque fois que nous faisons une requête à un entrepôt de données comme Elasticsearch, ou à OpenAI, ou à d'autres services réseau, nous faisons de l'IO et - souvent - cette IO bloque les threads sur lesquels elle s'exécute. Java 21 et les versions ultérieures intègrent des threads virtuels non bloquants qui améliorent considérablement l'évolutivité. L'activer avec :

Enfin, vous voudrez héberger votre application et vos données dans un endroit où elles pourront prospérer et évoluer. Nous sommes certains que vous avez déjà réfléchi à l'endroit où vous allez exécuter votre application, mais où allez-vous héberger vos données ? Pouvons-nous vous recommander l'Elastic Cloud? Il est sécurisé, privé, évolutif et doté de nombreuses fonctionnalités. Ce que nous préférons ? Si vous le souhaitez, vous pouvez obtenir l'édition Serverless dans laquelle Elastic porte le pager, pas vous !

Pour aller plus loin

Prêt à créer des expériences de recherche d'exception ?

Une recherche suffisamment avancée ne se fait pas avec les efforts d'une seule personne. Elasticsearch est alimenté par des data scientists, des ML ops, des ingénieurs et bien d'autres qui sont tout aussi passionnés par la recherche que vous. Mettons-nous en relation et travaillons ensemble pour construire l'expérience de recherche magique qui vous permettra d'obtenir les résultats que vous souhaitez.

Jugez-en par vous-même