<?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[À l'intérieur d'Elastic - 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[À l'intérieur d'Elastic - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/fr/search-labs/blog/category/inside-elastic</link>
    </image>
    <link>https://www.elastic.co/fr/search-labs/blog/category/inside-elastic</link>
    <atom:link href="https://www.elastic.co/fr/search-labs/rss/category/inside-elastic.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[fr]]></language>
    <lastBuildDate>Mon, 28 Sep 2026 15:08:09 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Comment nous avons construit Elasticsearch simdvec pour faire de la recherche vectorielle l'une des plus rapides au monde]]></title>
    <description><![CDATA[Comment nous avons conçu Elasticsearch simdvec, la bibliothèque de noyaux SIMD optimisée manuellement qui alimente chaque requête de recherche vectorielle dans Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>Elasticsearch simdvec est le moteur de calcul de distance vectorielle dans Elasticsearch. Il fournit des noyaux AVX-512 et NEON ajustés manuellement pour chaque type de vecteur pris en charge par Elasticsearch. Son architecture de calcul par lots masque la latence mémoire grâce à un prefetching explicite sur x86 et un chargement entrelacé sur ARM, surpassant jusqu'à 4 fois les performances de bibliothèques comme FAISS et jvector lorsque le volume de données dépasse la capacité du cache du processeur. Dans cet article, nous expliquons les raisons de sa création, son fonctionnement interne et comment il contribue à faire de la recherche vectorielle d'Elasticsearch l'une des plus rapides au monde.</p><h2>Comment nous avons conçu Elasticsearch simdvec</h2><p>Chaque requête de recherche vectorielle dans Elasticsearch, qu'il s'agisse d'un balayage transversal <a href="https://arxiv.org/abs/1603.09320">Hierarchical Navigable Small World (HNSW)</a>, d'un balayage de fichier inversé (IVF) ou d'une passe de reclassement, se résume au même problème : calculer les distances entre les vecteurs, des millions de fois par requête. Elasticsearch prend en charge un large éventail de types de données et de stratégies de quantification, de float32 à int8, bfloat16, binaire et quantification binaire améliorée (BBQ). Chacune présente des compromis différents entre mémoire, débit et rappel. Derrière tout cela se cache un moteur unique : simdvec.</p><p>Nous avons conçu simdvec pour rendre chaque calcul de distance aussi rapide que le permet le matériel. Dans cet article, nous expliquons pourquoi nous l'avons conçu, ce qu'il contient et où il a le plus d'impact.</p><h3>Construit comme une voiture de course</h3><p>En tant que passionnés de Formule 1 (l'un d'entre nous a travaillé pour l'écurie Ferrari), nous constatons un parallèle évident. Une Formule 1 est conçue dans un seul but : réaliser le meilleur temps au tour. La puissance du moteur, l'aérodynamisme et la conception du châssis n'ont d'importance que dans la mesure où ils contribuent à cet objectif. Il en va de même pour une base vectorielle, où le débit d'indexation, la latence des requêtes et le rappel sont les facteurs déterminants de sa performance.</p><p>Bien que le résultat final soit ce qui compte, atteindre les plus hauts niveaux de performance nécessite que chaque composant contribue de façon optimale. Il ne doit pas être simplement <em>suffisant</em>, mais <em>le meilleur </em>de sa catégorie. Simdvec est conçu dans cet esprit, en se concentrant sur une partie critique du système : le moteur. C'est une bibliothèque de noyaux dédiée, optimisée pour le <a href="https://en.wikipedia.org/wiki/Single_instruction,_multiple_data">Single Instruction Multiple Data</a> (SIMD), qui fournit des fonctions de distance C++ natives optimisées et appelées depuis Java via l'interface de fonction étrangère (FFI) <a href="https://openjdk.org/projects/panama/">Panama</a>. Il prend en charge le scoring en lots, le prefetching des lignes de cache et tous les types et mises en page de vecteurs utilisés dans Elasticsearch.</p><p>C'est le moteur derrière chaque requête.</p><h3>Pourquoi nous avons créé le nôtre</h3><p>Nous avons commencé en 2023 avec l'API Panama Vector dans Apache Lucene. Elle fonctionnait bien pour les produits scalaires de nombres flottants 32 bits, mais les besoins d'Elasticsearch ont rapidement dépassé ses capacités. Elasticsearch prend en charge une large gamme de types de vecteurs quantifiés : int8, int4, bfloat16, mono-bit et BBQ asymétrique. Chacun possède des stratégies SIMD, des compositions de packs et des exigences d'accumulateur différents. Au-delà de la couverture des types, les méthodes de scoring d'Elasticsearch exigent un débit supérieur à celui d'une simple paire : HNSW doit évaluer plusieurs voisins du graphe en une seule passe, IVF nécessite un scoring en lots de milliers de candidats avec prefetching, et le scoring sur disque doit fonctionner directement sur la mémoire mappée en mémoire sans copie. Nous avons examiné les solutions disponibles, mais aucune ne couvrait l'ensemble des besoins.</p><p>Nous avons donc développé simdvec : des noyaux C++ natifs optimisés manuellement, appelés depuis Java via FFI, avec scoring par lots, prefetching et prise en charge de tous les types vectoriels utilisés par Elasticsearch. En étant propriétaires de la bibliothèque, nous maîtrisons l'intégralité de la pile. Lorsque nous ajoutons un nouveau type de quantification comme BBQ, il bénéficie d'un noyau SIMD optimisé intégré à l'ensemble du système. Nous n'attendons pas qu'une bibliothèque tierce le prenne en charge et nous ne faisons aucun compromis sur les performances, quel que soit le type. Chaque requête vectorielle dans Elasticsearch – HNSW, IVF, de reclassement ou hybride – s'exécute sur ce moteur, conçu autour des opérations et des types que nous utilisons réellement.</p><p>Simdvec possède des bibliothèques natives distinctes pour x86 et ARM, chacune comportant plusieurs niveaux d'architecture du jeu d'instructions (ISA) sélectionnés au démarrage. La surcharge des appels depuis Java via FFI est très faible, de l'ordre de quelques <a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md#ffm-downcall-overhead-measurements">nanosecondes</a>.</p><h3>Le panorama</h3><p>Nous ne sommes pas les seuls à développer des noyaux de distance vectorielle optimisés pour SIMD. L'écosystème est riche et nous souhaitions comprendre les performances de simdvec. Non pas pour classer les projets, mais pour contextualiser et situer le moteur d'Elasticsearch. Nous avons sélectionné trois projets comme points de référence, chacun représentant une approche différente :</p><ul><li><p><strong>jvector</strong> : une bibliothèque Java de recherche de plus proches voisins approximatifs (ANN) qui utilise l'API Panama Vector pour le calcul de distance vectorisé, avec une accélération C native optionnelle sur x86.</p></li><li><p><strong>FAISS</strong> : un framework de recherche vectorielle open source largement déployé, avec des noyaux AVX2/AVX-512 ajustés manuellement.</p></li><li><p><strong>NumKong</strong> (anciennement SimSIMD) : une suite complète de plus de 2 000 noyaux SIMD ajustés manuellement, couvrant les fonctions de distance, les opérations matricielles et le calcul géospatial.</p></li></ul><p>Chaque projet répond à un objectif différent et fait l'objet de compromis différents. Nous incluons des numéros de référence provenant d'eux pour donner du contexte à la performance de simdvec sur les opérations spécifiques dont Elasticsearch a besoin.</p><h3>Comment nous mesurons</h3><p>Les <a href="https://github.com/ChrisHegarty/jvector-kernel-benchmarks">benchmarks simdvec et jvector</a> sont écrits en Java avec JMH, le harnais de microbenchmark JVM standard, avec la surcharge FFI incluse. Pour les <a href="https://github.com/ldematte/simsimd-benchmarks">benchmarks NumKong</a> et <a href="https://github.com/ChrisHegarty/faiss-kernel-benchmarks">FAISS</a>, nous avons écrit de petits programmes C/C++ utilisant Google Benchmark, qui est le framework standard de microbenchmark C++. Ces deux frameworks mesurent les temps d'exécution en nanosecondes, après une phase de warmup et un étalonnage des itérations. Nous avons vérifié, grâce à des compteurs de performance matériels, que toutes les bibliothèques utilisent SIMD sur les deux plateformes. L'ensemble du code des benchmarks est disponible publiquement dans les référentiels GitHub associés (et, pour simdvec, dans le référentiel <a href="https://github.com/elastic/elasticsearch">elasticsearch</a>).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt90a7d66553be3c9d/6a1701d166c4f942caf8bea5/aee116772df161cf86b7668f575ac34c733a23c5-1580x238.png" alt="Tableau listant deux plateformes : x86 avec AMD EPYC Turin (Zen 5), AVX2 et AVX‑512, AWS c8a.4xlarge, et ARM avec Graviton 4 (Neoverse V2), NEON et SVE2, AWS c8g.4xlarge." /><p><strong>Logiciel :</strong> JDK 25.0.2, JMH 1.37, GCC 14, Google Benchmark (dernière version).</p><h2>Un vecteur à la fois</h2><p>L'opération fondamentale de la recherche vectorielle consiste à calculer la distance entre deux vecteurs. Chaque évaluation de voisinage HNSW, chaque score de candidat IVF, chaque comparaison de reclassement ramène à cette boucle interne.</p><p>Nous avons mesuré le débit d'une seule paire à 1 024 dimensions sur les deux plateformes, en commençant par le type float32, le type de référence et celui où l'écosystème est le plus compétitif. Nous avons comparé simdvec à FAISS et jvector ; nous avons exclu NumKong car il utilise des accumulateurs float64 pour float32, ce qui le rend 3,2 à 5,3 fois plus lent (selon la plateforme), privilégiant la précision numérique au débit. Pour une comparaison équitable, nous avons testé NumKong sur int8, où il utilise la même stratégie d'accumulateurs que simdvec.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte3bc2ecaf3ad2b61/6a1701d2ab7f08039ddb9d0f/352cfa0fc18f123140f746d843404f80127fb1b7-1500x675.png" alt="Graphique à barres horizontales intitulé &quot;float32 Dot Product – AMD Turin&quot; qui compare cinq implémentations : FAISS AVX‑512 à 23,2 ns/op, ES simdvec AVX‑512 à 28,3 ns/op, FAISS AVX2 à 36,4 ns/op, ES simdvec AVX2 à 38,9 ns/op et jvector à 43,9 ns/op." /><p>Sur x86, FAISS AVX-512 est le noyau à paire unique le plus rapide à 23 ns. Simdvec AVX-512 suit à 28 ns, un écart qui reflète la surcharge d'appel FFI. Les deux utilisent le FMA 512 bits avec déroulement par accumulateurs multiples. Au niveau AVX2, les deux sont beaucoup plus proches, 36 ns et 39 ns respectivement, tous deux limités par le registre de 256 bits et les largeurs de chargement en mémoire. jvector arrive à 44 ns grâce à l'API Java Panama Vector. Panama génère un bon code SIMD, mais les intrinsèques C++ optimisées manuellement conservent un avantage.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcbbbe442631a575d/6a1701d42b835f81bcf4b083/95e44d9767f21ec4bccaed835e3c99aa180431ee-1500x495.png" alt="Graphique à barres horizontales intitulé &quot;float32 Dot Product – Graviton 4 (ARM)&quot; montrant ES simdvec à 70,2 ns/op, jvector à 110,0 ns/op et FAISS à 155,6 ns/op." /><p>Sur ARM, simdvec affiche le meilleur temps d'exécution (70 ns), devançant largement jvector (110 ns) et FAISS (156 ns). Simdvec utilise des noyaux NEON optimisés manuellement pour aarch64. Jvector, quant à lui, ne possède aucun code ARM natif et repose sur Panama. FAISS s'appuie sur la vectorisation automatique du compilateur plutôt que sur des fonctions intrinsèques NEON explicites, ce qui explique l'écart plus important. Ceci illustre l'avantage pratique de posséder la bibliothèque de noyaux : lors du passage d'Elasticsearch à Graviton, nous avons intégré des noyaux NEON dédiés. Ni jvector ni FAISS n'ont accordé la même priorité au code natif ARM.</p><p>Mais Elasticsearch ne se limite pas aux nombres à virgule flottante 32 bits. La quantification d'<strong>Int8</strong> réduit la mémoire d'un facteur 4, la quantification bfloat16 d'un facteur 2 et la quantification BBQ d'un facteur 32. Chaque type nécessite sa propre stratégie SIMD, et simdvec fournit des noyaux natifs optimisés manuellement pour chacun d'entre eux.</p><p>Parmi les bibliothèques que nous avons comparées, seule NumKong possède des noyaux comparables pour int8. Nous avons mesuré le produit scalaire int8, la distance euclidienne au carré et le cosinus pour le format int8 sur 1 024 dimensions.</p><p><strong>Score Int8 pour une seule paire (1 024 dimensions, ns/vec op – plus bas est mieux)</strong></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3ac255d158e93504/6a1701d5a292997e48d00eb1/a0b852fd5f51d57bd2488886600472ee65ab64da-1594x378.png" alt="Tableau comparant les performances x86 et ARM pour le produit scalaire, la distance euclidienne au carré et les opérations cosinus, en listant les valeurs ES, NumKong et diff pour chaque opération sur les deux architectures." /><p>Sur les deux architectures, NumKong est aussi performant, voire plus rapide, pour les petites et moyennes dimensions, la différence étant principalement due à une surcharge d'appels réduite (appel direct en C contre FFI Java). Pour les grandes dimensions, simdvec rattrape son retard, grâce à une implémentation noyau plus efficace (qui utilise le déroulement en cascade) qui amortit le coût des appels : à mesure que la dimension augmente, <a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md#single-pair-i8-nsop-2">cet écart se réduit et finit par s'inverser</a>. Le point de bascule se situe entre 768 et 1 536 dimensions, selon la fonction et l'architecture.</p><p>Malgré la surcharge légèrement supérieure de l'interface FFI Java, simdvec rivalise avec les bibliothèques C/C++ fortement optimisées. Non seulement c'est la seule bibliothèque dotée de noyaux optimisés pour float32 <em>et</em> int8, mais elle est également en tête sur ARM et juste derrière FAISS sur x86 (pour float32), et très proche de NumKong sur les deux architectures (pour int8). Enfin, pour bfloat16, int4, binary et BBQ, bien qu'il existe des alternatives, simdvec se distingue par un SIMD ajusté manuellement et adapté à la structure des données de chaque type.</p><p>Cependant, un moteur de recherche en production n'évalue pas un vecteur à la fois ; il en évalue des milliers par requête. La question suivante est de savoir ce qui se passe à cette échelle.</p><h3>Des milliers à la fois</h3><p>Les performances sur une seule paire ne représentent qu'une partie du problème. En pratique, c'est le comportement des systèmes sous charge qui est important. Une simple requête HNSW peut évaluer des centaines de voisins dans le graphe. Une analyse IVF peut évaluer des milliers d'entrées de listes de publication. Une passe de reclassement peut évaluer des dizaines de milliers de candidats. Le débit sur une seule paire est important, mais ce qui compte davantage, c'est la rapidité avec laquelle il est possible d'évaluer de nombreux vecteurs et la façon dont les performances se dégradent lorsque l'ensemble de travail déborde des caches du processeur.</p><p>Simdvec propose un scoring par lots pour tous les types de données. Il ne s'agit pas simplement de boucles sur des noyaux de distance à une seule paire, mais de boucles internes dotées de plusieurs accumulateurs qui chargent le vecteur de requête une fois par pas de dimension et le partagent entre plusieurs vecteurs de documents, avec un prefetching explicite des lignes de cache pour le lot suivant. Ni jvector ni FAISS n'offrent d'équivalent (à l'heure actuelle). Jvector ne dispose pas d'API Bulk ; les appelants calculent donc le score d'une paire à la fois dans une boucle. FAISS expose <code>fvec_inner_products_ny</code>, qui, à l'heure actuelle, est implémenté comme une boucle sur sa fonction de distance à une seule paire, sans amortissement ni prefetching des requêtes.</p><p><strong>Float32.</strong> Pour mesurer l'impact au niveau du noyau, nous avons évalué une requête unique sur un nombre croissant de vecteurs de documents float32 de 1 024 dimensions, en utilisant des modèles d'accès aléatoire simulant des recherches de voisins dans un graphe dispersé de type HNSW. Les trois tailles d'ensemble de données (32, 625 et 32 500 vecteurs) ont été choisies de manière à ce que l'ensemble de travail dépasse respectivement les caches L1, L2 et L3.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2df64ec77a1921ae/6a1701d714b270393ae3c4de/1d90267be1c63ac82b8ba588617ebedb0be0d1b6-1334x558.png" alt="Deux graphiques à barres comparant les temps de scoring du produit scalaire Float32 en lots pour Elasticsearch simdvec, FAISS et jvector sur AMD Turin (x86, AVX-512) et Graviton 4 (ARM, NEON) sur trois tailles : 32 vecteurs, 625 vecteurs et 32 500 vecteurs." /><p>Lorsque les données tiennent dans le cache, simdvec est le plus rapide sur les deux plateformes, mais l'écart reste modeste, car l'arithmétique du noyau est prépondérante. La différence est flagrante lorsque la taille de l'ensemble de travail dépasse le cache L3. Sur x86, simdvec atteint 95 ns par vecteur, contre 165 ns pour FAISS et 412 ns pour jvector. Sur ARM, le constat est identique : simdvec se maintient à 162 ns, tandis que FAISS grimpe à 347 ns et jvector à 476 ns. Le prefetching et l'amortissement des requêtes dans simdvec masquent la latence mémoire, contrairement à une simple boucle sur des noyaux à paire unique. Cet avantage est encore plus manifeste précisément là où les véritables charges de travail de recherche s'exécutent, au cœur de la mémoire principale.</p><p><strong>Int8.</strong> Le même schéma s'applique aux types quantifiés. Nous avons mesuré le scoring par lots du produit scalaire int8 à 1 024 dimensions avec des tailles d'ensemble de données choisies pour dépasser les mêmes limites de cache L1, L2 et L3, en comparant le scoring par lots de simdvec au scoring de paires individuelles de NumKong dans une boucle.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcda85e10007188d0/6a1701d9cf4f25d722b2cff7/9ee97d98b40d13b19370b76b33e67ea66bfb3250-1580x338.png" alt=" Tableau intitulé &quot;x86 – Bulk scoring, int8 dot product (ns/op, lower is better)&quot; comparant ES simdvec et NumKong sur trois tailles de vecteurs – 128, 2 500 et 130 000 – avec les valeurs ns/op correspondantes et les ratios d'accélération." /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt972c311b7d08ba73/6a1701dadc55dec02ee00c87/601f50a03fa3e6263cbac9700281dfe3e511de60-1580x338.png" alt="Tableau intitulé &quot;ARM – Bulk scoring, int8 dot product (ns/op, lower is better)&quot; comparant ES simdvec et NumKong sur trois tailles de vecteurs – 128, 2 500 et 130 000 – avec les valeurs ns/op correspondantes et les ratios d'accélération" /><p>Sur x86, simdvec est de 1,2 à 1,9 fois plus rapide, grâce à la combinaison du prefetching explicite et du traitement par lots. Sur ARM, simdvec l'emporte également (de 1,7 à 1,9 fois plus rapide) quelle que soit la taille des ensembles de données. Cet avantage provient du traitement par lots de quatre vecteurs simultanément, offrant un parallélisme au niveau mémoire via un modèle d'accès entrelacé. Dans les deux cas, le résultat le plus frappant se situe au niveau des ensembles de données les plus volumineux, là où il est le plus significatif.</p><p>Les résultats concernant la distance au carré et le cosinus montrent un schéma similaire, avec des accélérations de 1,4 à 1,8 fois pour ARM, et de 1,3 à 3,0 fois pour x86 (détails <a href="https://github.com/ldematte/simsimd-benchmarks/blob/main/COMPARISON.md">ici</a>).</p><h3>Quand la mémoire est essentielle</h3><p>Les index vectoriels de production ne tiennent généralement pas dans le cache du processeur. Un index vectoriel de 10 millions d'éléments (int8) à 1 024 dimensions pèse 10 Go. Le scoring des candidats implique le traitement en continu des données depuis la DRAM, et c'est là que l'architecture de scoring par lots fait toute la différence.</p><p>Nous avons utilisé des compteurs de performances matérielles pour mesurer ce qui se passe à l'intérieur du processeur pendant le scoring par lots et avons constaté que masquer la latence de la mémoire nécessite deux stratégies fondamentalement différentes, une par architecture.</p><p><strong>Sur x86, le prefetching explicite élimine les défauts de cache. </strong>Le noyau principal traite les vecteurs séquentiellement, chaque vecteur étant entièrement calculé avant le suivant, tout en émettant des instructions de prefetching pour le lot suivant. Les données futures sont chargées dans le cache L1 avant que le processeur n'en ait besoin.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt368f29b5143d0f5a/6a1701dcc1e8a51780f8817b/a39548f8060c2a4a5154521a4047dd92d8cd77be-1580x309.png" alt="Tableau intitulé « x86 (AMD Turin) — Compteurs matériels par opération int8 » comparant les modes simple et groupé pour les pertes de cache L1, l'IPC et les pertes de dTLB, avec les facteurs d'amélioration correspondants." /><p>Sur ARM, la même approche séquentielle s'est avérée peu performante, même avec prefetching. En revanche, le <strong>noyau de traitement par lots entrelace les charges</strong> de quatre vecteurs à chaque position d'itération, offrant ainsi au moteur hors séquence quatre flux mémoire indépendants. Le processeur ne récupère pas les données plus rapidement, mais le temps d'attente est réduit en ayant toujours une autre opération à traiter pendant que les requêtes mémoire sont en cours de traitement. Une analyse détaillée est disponible dans <a href="https://github.com/elastic/elasticsearch/issues/145412">ce ticket GitHub</a>.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8751ac5b20b75508/6a1701deab7f08db83db9d13/832de3bc0d556a493b7bf3f250196018acfc1585-1580x238.png" alt="Tableau intitulé &quot;ARM (Graviton 4) – Hardware counters per int8 operation&quot; comparant les modes unique et groupé pour les défauts de cache L1 et les blocages du backend, avec les notes d'amélioration correspondantes" /><p>Les chiffres racontent deux histoires différentes :</p><ol><li><p>Sur x86, le prefetching réduit les défauts de cache de 139 000 à 19 000 et double le nombre d'instructions par cycle (IPC). L'avantage en termes de traitement par lots s'accroît avec la taille des données, passant de 1,2 fois pour le cache L2 à 2,8 fois pour les caches au-delà du cache L3, car le prefetching masque les allers-retours DRAM de plus en plus coûteux.</p></li><li><p>Sur ARM, le nombre d'échecs de cache reste pratiquement inchangé. Ce qui change, c'est le taux d'utilisation : les blocages du backend diminuent de 40 % car le modèle d'accès entrelacé assure l'alimentation continue du pipeline. Cet avantage reste constant, à 1,8 fois, quelle que soit la taille de l'ensemble de données, car le parallélisme au niveau de la mémoire s'applique que les données proviennent du cache ou de la DRAM.</p></li></ol><p>Deux architectures, deux stratégies, un résultat : à l'échelle de la production, simdvec maintient le pipeline du processeur occupé même lorsque les vecteurs sont dispersés dans la mémoire principale.</p><h2>Ce que cela signifie pour les utilisateurs d'Elasticsearch</h2><p>Ces capacités au niveau du noyau s'additionnent. Une simple requête de recherche vectorielle peut calculer des millions d'opérations de distance : parcours de graphe HNSW, scoring des candidats, reclassement. Sur des milliers de requêtes simultanées, chaque opération, même en nanosecondes, se traduit directement par une latence de requête et un débit de cluster optimaux. Que vous utilisiez float32, int8, bfloat16 ou BBQ, que votre index soit en mémoire ou sur disque, simdvec est le moteur sous-jacent, et chacune de ces opérations s'exécute sur ce même moteur, optimisé à la nanoseconde près.</p><p>L'essentiel à retenir est qu'à l'échelle de la production, les performances de la recherche vectorielle ne sont pas principalement déterminées par le débit SIMD brut. Elles dépendent surtout de la capacité du système à masquer efficacement la latence mémoire tout en maintenant la capacité de calcul sur des millions de petites opérations.</p><p>Les noyaux simdvec s'améliorent à quasiment chaque nouvelle version d'Elasticsearch. Dès l'apparition de nouveaux types de quantification et de plateformes matérielles, des noyaux optimisés sont intégrés. De plus, les types existants continuent de gagner en vitesse grâce à l'amélioration des implémentations déjà disponibles.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-vector-search-simdvec-engine</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-vector-search-simdvec-engine</guid>
    <category><![CDATA[Base vectorielle]]></category>
    <category><![CDATA[À l'intérieur d'Elastic]]></category>
    <dc:creator><![CDATA[Chris Hegarty,Lorenzo Dematte,Simon Cooper]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta18088409621369b/6a1701dfdc55de7297e00c8b/df9646091bafbbf0a6dfd212ff8a6bd1e8589708-1280x720.png" length="0" type="image/png"/>
    <pubDate>Thu, 23 Apr 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Annonce des autorisations en lecture seule pour les tableaux de bord Kibana]]></title>
    <description><![CDATA[Présentation des tableaux de bord en lecture seule dans Kibana, offrant aux créateurs de tableaux de bord des contrôles de partage détaillés pour garantir l'exactitude des résultats et les protéger contre les modifications indésirables.]]></description>
    <content:encoded><![CDATA[<p>Vous connaissez la situation. Vous passez une heure à créer le tableau de bord parfait pour suivre vos logs : chaque graphique, chaque filtre, chaque étiquette. Vous le partagez avec votre équipe. Quelques jours plus tard, vous l'ouvrez et quelque chose cloche. Un collègue a modifié une requête. Ou quelqu'un a changé la plage de dates. Ils pensaient sûrement bien faire. Vous voilà maintenant à éplucher les modifications et à remettre en question chaque chiffre. Ça vous dit quelque chose ?</p><p>C'est précisément pour cela que nous avons créé des <strong>tableaux de bord en lecture seule</strong>. C'est le niveau de contrôle que vous attendiez. Partagez vos tableaux de bord en toute confiance, sans craindre que la prochaine personne qui dispose d'un accès en modification ne les modifie ou ne les altère.</p><p>Remarque : les autorisations en lecture seule sont disponibles dans Elastic Cloud Serverless et à partir de la version 9.3 pour Elastic Cloud Hosted et Elastic autogéré.</p><h2>Quand l'option "tout le monde peut modifier" pose problème</h2><p>Dans Kibana, le <em>partage </em>est généralement synonyme d'autorisations au niveau de l'espace. Si quelqu'un peut créer des tableaux de bord dans un espace, il peut également modifier ou supprimer ceux des autres. C'est génial pour collaborer jusqu'à ce que ce ne soit plus le cas. Une modification accidentelle peut entraîner de mauvaises décisions, une perte de confiance et beaucoup de nettoyage.</p><p>Nous avons entendu les solutions de contournement : <strong>"On ajoute "lecture seule" dans le nom du tableau de bord et on espère que les gens le remarqueront."</strong> Ou encore : <strong>"On les étiquette et on croise les doigts."</strong> L'espoir n'est pas un modèle d'autorisations. Il vous fallait un moyen efficace de verrouiller un tableau de bord sans en interdire l'accès à tous.</p><h2>Ce qui ne va pas</h2><p>Deb et Kevin ont tous deux un accès en modification au tableau de bord de surveillance des logs dans l'espace Opérations. Kevin apporte quelques modifications aux graphiques. À son retour, Deb constate que les chiffres ne correspondent plus à ce qu'elle a présenté. Elle doit alors rechercher ce qui a été modifié (souvent de mémoire), le corriger et se demander combien de rapports erronés ont été diffusés.</p><h2>Tableaux de bord en lecture seule : droits d'accès et contrôle adaptés</h2><p>Les tableaux de bord en lecture seule résolvent ce problème en vous permettant de contrôler si d'autres utilisateurs peuvent les modifier. Lorsque vous partagez un tableau de bord, vous avez le choix entre : <strong>modifier</strong> (par défaut, comme aujourd'hui) ou <strong>afficher</strong>. En mode <strong>affichage</strong>, vous seul (et les administrateurs de Kibana) pouvez le modifier ou le supprimer. Tous les autres peuvent l'ouvrir, l'utiliser et lui faire confiance, mais ils ne peuvent pas le modifier.</p><h3>Ce que vous obtenez</h3><ul><li><p><strong>Intégrité du tableau de bord</strong> : en mode <strong>affichage</strong>, les autres utilisateurs disposant d'un accès en modification dans l'espace ne peuvent ni modifier ni supprimer le tableau de bord. S'ils tentent de le faire, un message leur indique qu'il est verrouillé. Vos graphiques et votre logique restent intacts.</p></li><li><p><strong>Vous gardez le contrôle</strong> : vous êtes le propriétaire. Vous pouvez toujours modifier, affiner et mettre à jour. Le partage en lecture seule ne vous empêche pas d'accéder au contenu ; il verrouille la version visible par tous les autres utilisateurs.</p></li><li><p><strong>Cycle de vie flexible</strong> : vous pouvez à tout moment repasser un tableau de bord en mode "modifiable". Et les administrateurs Kibana peuvent toujours gérer tous les tableaux de bord (par exemple, si le propriétaire quitte l'entreprise). Il n'y a pas d'impasse.</p></li></ul><p>Vous pouvez partager largement des tableaux de bord finalisés et stratégiques, en ayant l'assurance qu'ils resteront cohérents. Cette fonctionnalité est disponible dans <strong>tous les niveaux et offres Elastic</strong>, y compris Serverless.</p><h3>Qui peut faire quoi ?</h3><p>Référence rapide par rôle :</p><ul><li><p><strong>Propriétaire du tableau de bord</strong> : vous l'avez créé ; vous disposez d'un accès complet en modification.</p></li><li><p><strong>Administrateur Kibana</strong> : peut gérer tous les tableaux de bord.</p></li><li><p><strong>Utilisateur avec droit de modification dans l'espace</strong> : peut créer et modifier ses tableaux de bord ; ne peut ni modifier ni supprimer les tableaux de bord en mode lecture seule.</p></li><li><p><strong>Utilisateur avec droit d'affichage dans l'espace</strong> : peut uniquement consulter (et afficher) les tableaux de bord.</p></li></ul><p>Action</p><p>Propriétaire du tableau de bord</p><p>Administrateur Kibana</p><p>Utilisateur avec modification de l'espace</p><p>Utilisateur avec droit d'affichage dans l'espace</p><p>Afficher et consulter les tableaux de bord</p><p>✔</p><p>✔</p><p>✔</p><p>✔</p><p>Créer de nouveaux tableaux de bord</p><p>✔</p><p>✔</p><p>✔</p><p>✘</p><p>Modifier/supprimer les tableaux de bord modifiables</p><p>✔</p><p>✔</p><p>✔</p><p>✘</p><p>Modifier ou supprimer les tableaux de bord en lecture seule</p><p>✔</p><p>✔</p><p>✘</p><p>✘</p><h2>Comment activer le mode lecture seule</h2><p>Vous pouvez activer le mode lecture seule lors de l'enregistrement d'un nouveau tableau de bord ou ultérieurement depuis le menu Partager.</p><h3>Lors de l’enregistrement d’un nouveau tableau de bord</h3><ul><li><p>Créez votre tableau de bord, puis cliquez sur <strong>Enregistrer</strong>.</p></li><li><p>Dans la fenêtre modale "Enregistrer en tant que nouveau tableau de bord", recherchez <strong>Autorisations</strong>.</p></li><li><p>Passez de <strong>Peut modifier</strong> à <strong>Peut afficher</strong>.</p></li><li><p>Cliquez sur <strong>Save</strong> (Enregistrer). Et le tour est joué ! C'est en lecture seule pour tous les autres utilisateurs.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt120724e3b963289f/6a16f76354abb858cd133baf/42a71d1bb55f9d50bd079f53bf45a0e1999b27f7-1214x1306.png" alt=" Boîte de dialogue Kibana affichant les options d'enregistrement d'un tableau de bord, avec les autorisations de lecture seule sélectionnées." /><h2>Pour un tableau de bord que vous possédez déjà</h2><ul><li><p>Ouvrez le tableau de bord.</p></li><li><p>Ouvrez le menu <strong>Partager le tableau de bord</strong>.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8fa2f365687c2ca8/6a16f764a292990e4bd00e01/e8405938557c879b1d4c262b98cf5a7f66408c04-1246x264.png" alt="Barre d'outils du tableau de bord Kibana affichant les options permettant de quitter le mode édition, de partager, de modifier les paramètres, d'ajouter des panneaux et d'enregistrer, l'option Partager étant mise en avant." /><ul><li><p>Dans la fenêtre de partage, recherchez <strong>Autorisations</strong> et sélectionnez <strong>Affichage uniquement</strong>. La modification s'applique immédiatement ; les autres utilisateurs dans l'espace ne peuvent plus le modifier ni le supprimer.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt05e6051dbe4b8250/6a16f76667045b321445bf9d/849405bc32701f3ebe0def012d8ae3cf3813ea0a-996x750.png" alt="Panneau de partage Kibana affichant les autorisations du tableau de bord et l'option permettant de copier un lien en lecture seule." /><ul><li><p>Vous pouvez survoler l'action <strong>Partager</strong> avec la souris pour voir le type d'autorisations dont dispose un tableau de bord donné.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf8880996f84cdab3/6a16f7678b73cb3682189dfa/80541ddb1b1bc567b0aeff693944ea8b6871d6a7-1270x320.png" alt="Barre d'outils Kibana avec le bouton Partager mis en évidence et une infobulle indiquant que tous les utilisateurs de l'espace peuvent consulter le tableau de bord." /><h3>Voir quels tableaux de bord sont verrouillés</h3><p>Dans la liste principale des tableaux de bord, les tableaux de bord que vous ne pouvez ni modifier ni supprimer sont signalés par une case à cocher désactivée. Cela permet de repérer facilement les tableaux de bord en lecture seule.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9c5fae7fa018c89a/6a16f768b0367da1b172bacb/24b2eba08df86174db949c662e7886c5aea1b460-1999x876.png" alt="La liste des tableaux de bord Kibana, affichant plusieurs tableaux de bord, avec les créateurs, les horodatages, et un élément sélectionné." /><p>Sur le tableau de bord, vous constaterez également que l'action Modifier est désactivée et qu'une info-bulle apparaît, expliquant que le tableau de bord a été configuré en lecture seule.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt50ef3c91d5640c0c/6a16f76a60084b08fc3c434d/e0a2f9da6dc854e876fc6dc2a7c3ef8b313b52ef-1358x330.png" alt="Barre d'outils du tableau de bord Kibana affichant un bouton Modifier et une infobulle d'avertissement indiquant que l'utilisateur n'est pas autorisé à modifier le tableau de bord." /><h2>Faites l'essai</h2><p>Les tableaux de bord en lecture seule sont désormais disponibles. Créez un tableau de bord, passez-le en mode <strong>Affichage uniquement</strong> et partagez-le. Votre équipe dispose ainsi d'une source unique d'information fiable, et vous avez l'esprit tranquille. Fini les mentions "Ne pas modifier" dans le titre.</p><p>Nous aimerions savoir comment vous utilisez les tableaux de bord en lecture seule. Partagez vos commentaires sur notre <a href="https://discuss.elastic.co">forum communautaire</a>.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/kibana-dashboards-read-only-permissions</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/kibana-dashboards-read-only-permissions</guid>
    <category><![CDATA[À l'intérieur d'Elastic]]></category>
    <dc:creator><![CDATA[Teresa Alvarez Soler]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta4d7f707011ca90f/6a16f76b8b73cb3125189dfe/11e578bc317aea30d2e10ccc0334a532f6af2ef9-720x420.jpg" length="0" type="image/jpeg"/>
    <pubDate>Thu, 26 Mar 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Arrêt précoce adaptatif pour HNSW dans Elasticsearch]]></title>
    <description><![CDATA[Présentation d'une nouvelle stratégie adaptative d'arrêt précoce pour HNSW dans Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>Elasticsearch utilise l'algorithme <a href="https://www.elastic.co/search-labs/blog/hnsw-graph">Hierarchical Navigable Small World</a> (HNSW) pour effectuer une recherche vectorielle sur un graphe de proximité. HNSW est reconnu pour offrir un bon compromis entre la qualité des résultats des k plus proches voisins (kNN) et le coût associé.</p><p>Dans HNSW, la recherche s'effectue par expansion itérative des nodes candidats dans le graphe, en conservant un ensemble limité des voisins les plus proches découverts jusqu'à présent. Chaque expansion a un coût (opérations vectorielles, recherches aléatoires sur disque, etc.), et le bénéfice marginal de ce coût tend à diminuer à mesure que la recherche progresse.</p><p>Une façon d'optimiser le parcours du graphe HNSW est d'interrompre la recherche lorsque la probabilité marginale de trouver de nouveaux les plus proches n'augmente plus. C'est pourquoi, dans <a href="https://www.elastic.co/docs/reference/elasticsearch/index-settings/index-modules#index-dense-vector-hnsw-early-termination">Elasticsearch 9.2</a>, nous avons introduit un nouveau <a href="https://www.elastic.co/search-labs/blog/hnsw-knn-search-early-termination">mécanisme d'arrêt précoce</a>. Ce mécanisme interrompt la recherche lorsque la visite des nodes du graphe ne fournit pas suffisamment de nouveaux voisins les plus proches, de façon consécutive, pendant un nombre déterminé de fois.</p><p>Cet article explique comment nous avons amélioré le mécanisme mentionné d'arrêt précoce dans HNSW afin de mieux l'adapter à différents ensembles de données et distributions de données.</p><h2><strong>Arrêt précoce dans HNSW</strong></h2><p>Dans HNSW, la recherche se déroule en étendant itérativement les nodes candidats dans le graphe de proximité, en conservant un ensemble limité des voisins les plus proches découverts jusqu'à présent, jusqu'à avoir exploré l'ensemble du graphe ou répondu à certains critères d'arrêt précoce.</p><p>L'arrêt précoce n'est donc pas toujours une optimisation ; il <strong>fait partie intégrante de l'algorithme de recherche lui-même</strong>. Le moment où nous décidons d'interrompre la recherche détermine l'équilibre entre l'efficacité et le rappel. Dans Elasticsearch, il existe déjà plusieurs façons d'interrompre prématurément une requête sur HNSW :</p><ul><li><p>Un nombre maximal déterminé de nodes est exploré.</p></li><li><p>Un délai d'expiration déterminé est atteint.</p></li></ul><p>Bien que simples et prévisibles, ces règles sont largement <strong>indépendantes de ce qu'effectue réellement la recherche</strong>. De plus, elles servent principalement à garantir que la requête se termine dans un délai raisonnable pour l'utilisateur final.</p><p>Dans un <a href="https://www.elastic.co/search-labs/blog/hnsw-knn-search-early-termination">article de blog précédent</a>, nous avons introduit le concept de redondance dans HNSW. En bref, les calculs redondants se produisent lorsque HNSW continue d'évaluer de nouveaux nodes candidats qui ne permettent pas de trouver davantage de voisins les plus proches.</p><h2><strong>Patience : mesurer les progrès plutôt que les efforts</strong></h2><p>La notion de <em>patience</em> recadre l'arrêt précoce sur le <strong>progrès plutôt que sur l'effort</strong>.</p><p>Au lieu de demander :</p><p>"Combien d'étapes avons-nous franchies ?"</p><p>La nouvelle question devient :</p><p>« Quelle est la quantité de calcul que nous acceptons de gaspiller, jusqu'à ce que nous perdions espoir ? »</p><p>Lors d'une recherche HNSW, l'exploration précoce génère généralement des améliorations maximales de l'ensemble des k meilleurs candidats. Au cours des premières étapes de l'exploration du graphe HNSW, l'ensemble des voisins est mis à jour en continu à mesure que l'algorithme découvre des voisins de plus en plus proches du vecteur de requête. Avec le temps, ces améliorations deviennent plus rares à mesure que la recherche converge. L'<a href="https://cs.uwaterloo.ca/~jimmylin/publications/Teofili_Lin_ECIR2025.pdf">arrêt basé sur la patience</a> surveille ce schéma et interrompt la recherche lorsque les améliorations cessent de se produire pendant une période prolongée.</p><p>En pratique, lors de l'exploration du graphe HNSW, nous calculons également le taux de saturation de la file d'attente à chaque étape du parcours des nodes candidats. Ce taux mesure le pourcentage de voisins les plus proches restés inchangés lors de la visite du dernier node du graphe (ou l'inverse du nombre de nouveaux voisins introduits lors de la dernière itération). Si ce taux devient trop élevé pendant plusieurs itérations consécutives, l'exploration du graphe est interrompue.</p><p>D'un point de vue conceptuel, la patience considère la recherche HNSW comme un <strong>processus à rendements décroissants</strong>. Lorsque les rendements se stabilisent, continuer à explorer le graphe apporte peu d'avantages.</p><p>Ce recadrage est puissant car il lie directement l'arrêt aux <em>résultats observables</em> plutôt qu'à des limites fixes arbitraires.</p><p>L'avantage de cette technique d'arrêt précoce intelligent est que les explorations de graphes HNSW ont tendance à visiter un nombre plus restreint de nodes tout en conservant un rappel relatif quasi parfait.</p><p>Pour visualiser cela, nous pouvons tracer le nombre de rappels par node visité que nous avons obtenus avec l'arrêt précoce basé sur la patience (étiqueté <em><code>et=static</code></em>), par rapport au comportement par défaut du HNSW (étiqueté <em><code>et=no</code></em>) sur quelques ensembles de données, FinancialQA et Quora, ainsi que des modèles JinaV3 et E5-small.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfd0d692b9beb476a/6a170ef4dc55debf0be00e97/a9d07c5153ea64a2426c82487c36846030692bb9-1600x945.png" alt="Arrêt précoce adaptatif pour HNSW " /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt93509c251a1b641e/6a170ef6dc55dea2b3e00e9b/dac56125c4b16d1b596c9876b6ca9ac7b2dc87fa-1600x944.png" alt="Arrêt précoce adaptatif pour HNSW ES" /><h2><strong>Seuils statiques et dynamiques HNSW</strong></h2><p>Dans Elasticsearch, cela se traduit concrètement par l'utilisation de <strong>seuils statiques</strong>. Le premier seuil correspond au <strong>seuil de saturation</strong>, c'est-à-dire le niveau de saturation que nous considérons comme sous-optimal. Le second seuil correspond au nombre de nodes consécutifs du graphe pouvant être visités tout en maintenant une saturation de la file d'attente sous-optimale, soit le <strong>seuil de patience</strong>.</p><p>Lors de l'introduction de cette stratégie d'arrêt précoce dans Elasticsearch 9.2, nous avons opté pour des valeurs par défaut prudentes afin de maximiser le rappel tout en optimisant la latence et la consommation de mémoire. C'est pourquoi nous avons fixé le seuil de saturation à 100 % et le seuil de patience à 30 % (limité) de la valeur de <a href="https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-knn-query#knn-query-top-level-parameters:~:text=search%20request%20size.-,num_candidates,-(Optional%2C%20integer)%20The"><em><code>num_candidates</code></em></a> dans la requête KNN.</p><p>Dans de nombreux cas, ces paramètres ont donné de bons résultats. Cependant, deux requêtes demandant le même nombre de voisins peuvent avoir des comportements de convergence radicalement différents. Certaines requêtes rencontrent des voisinages locaux denses et saturent rapidement ; d'autres doivent parcourir de longs chemins épars avant de trouver des candidats compétitifs. Ces dernières se sont avérées les plus difficiles à gérer efficacement.</p><p>De ce fait, nous avons parfois constaté :</p><ul><li><p>Une surexploration pour les requêtes simples.</p></li><li><p>Un arrêt prématuré pour les requêtes complexes.</p></li></ul><p>Nous avons donc estimé que les valeurs de seuil déterminées codifiaient des hypothèses globales sur la convergence, alors que nous pouvions mieux adapter le HNSW à différentes dynamiques.</p><h2><strong>Rendre l'arrêt précoce de HNSW adaptatif</strong></h2><p>L'arrêt précoce adaptatif aborde ce problème sous un angle différent. Au lieu d'imposer des seuils d'arrêt prédéfinis, l'algorithme <strong>détermine le moment où il doit s'arrêter à partir de la dynamique de recherche elle-même.</strong></p><p>Ainsi, au lieu de comparer le taux de saturation de la file d'attente entre deux candidats consécutifs, nous avons décidé d'introduire à la fois un taux de découverte lissé instantané  (combien de nouveaux voisins ont été introduits pour une requête <em>q</em> lors de la dernière visite <em>i</em>), ainsi qu'une moyenne glissante  et un écart-type  d'un tel taux de découverte pendant la visite du graphe (en utilisant l'<a href="https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm">algorithme de Welford)</a>. Ces statistiques sur le taux de découverte sont calculées par requête, permettant ainsi de déterminer différents niveaux de patience pour chacune d'entre elles.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdbfb1e123f1b026d/6a170ef7cf4f25d9bab2d216/1958be7ca4425ade66eaf621ada3533173183598-694x118.png" alt="" /><p>Les seuils auparavant statiques deviennent adaptatifs aux statistiques du taux de découverte : le seuil de saturation devient la moyenne mobile plus l'écart type, tandis que nous faisons en sorte que la patience s'adapte et évolue inversement avec l'écart type.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7d4d91f464a9dc9d/6a170ef8d7c0223420de656a/f7ee4a55c24853b657df26052b275e8bd76cf0f9-654x156.png" alt="" /><p>Les règles de sortie précoce restent les mêmes ; la saturation survient lorsque le taux de découverte instantané est inférieur au seuil de saturation adaptatif. La visite du graphe s'arrête si la saturation persiste pendant un nombre d'explorations de candidats consécutives supérieur au seuil de patience adaptatif.</p><p>De cette façon, nous obtenons un comportement qui ne dépend pas du paramètre <em><code>num_candidates</code></em> dans la requête KNN (qui peut toujours être défini ou laissé par défaut, indépendamment d'une sortie anticipée) et qui s'adapte mieux à chaque requête et distribution vectorielle de manière dynamique.</p><p>Le rappel par node visité sur FinancialQA et Quora avec la stratégie adaptative (étiquetée <em><code>et=adaptive</code></em>) indique un rappel plus élevé par node visité, par rapport à la stratégie statique (<em><code>et=static</code></em>) et au comportement par défaut de HNSW (<em><code>et=no</code></em>).</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blteab7ba53ae14da0e/6a170ef9961e69e072c4cfd5/2a906997d9a25d74c7038bd9661bc97581e7258e-1600x938.png" alt=" stratégie adaptative et comportement par défaut de HNSW" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6fb9e672d3698200/6a170efb67045b7b2b45c2ab/3a114911e232c351dbb814cea20e8b0f1415a717-1600x925.png" alt="" /><p>L'arrêt précoce adaptatif est activé par défaut dans Elasticsearch 9.3 pour les champs vectoriels denses HNSW (et peut éventuellement être désactivé via le <a href="https://www.elastic.co/docs/reference/elasticsearch/index-settings/index-modules#index-dense-vector-hnsw-early-termination">même paramètre de niveau d'index</a>).</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/hnsw-elasticsearch-adaptive-early-termination</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/hnsw-elasticsearch-adaptive-early-termination</guid>
    <category><![CDATA[Base vectorielle]]></category>
    <category><![CDATA[À l'intérieur d'Elastic]]></category>
    <dc:creator><![CDATA[Tommaso Teofili]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt27b746cc1995e6b7/6a170efda29299de8ad010c6/e6d3186f609dd56dc5ffe33d70fa9e5cfa05b51f-1280x720.png" length="0" type="image/png"/>
    <pubDate>Mon, 02 Mar 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Améliorez les performances de recherche avec 'best_compression']]></title>
    <description><![CDATA[Bien que 'best_compression' soit généralement considéré comme une fonctionnalité d'économie d'espace de stockage pour les cas d'utilisation d'Elastic Observability et d'Elastic Security, ce blog démontre son efficacité en tant que levier d'optimisation des performances pour la recherche.]]></description>
    <content:encoded><![CDATA[<p></p><p>Lors de l'optimisation d'Elasticsearch pour des charges de travail à forte simultanéité, l'approche standard consiste à maximiser la RAM afin de conserver l'ensemble des documents de travail en mémoire et d'obtenir une faible latence de recherche. Par conséquent, <a href="https://www.elastic.co/docs/reference/elasticsearch/index-settings/index-modules"><code>best_compression</code></a> est rarement l'option choisie pour les charges de travail de recherche, car il est principalement perçu comme une mesure d'économie d'espace pour les cas d'utilisation d'Elastic Observability et d'Elastic Security où l'efficacité du stockage est prioritaire.</p><p>Dans ce blog, nous démontrons que lorsque la taille de l'ensemble de données dépasse nettement le cache de page du système d'exploitation, <code>best_compression</code> améliore les performances de recherche et l'efficacité des ressources en réduisant le goulot d'étranglement des E/S.</p><h2><strong>La configuration</strong></h2><p>Notre cas d'utilisation est une application de recherche à forte simultanéité qui s'exécute sur des <a href="https://www.elastic.co/docs/deploy-manage/deploy/elastic-cloud/ec-change-hardware-profile#ec-profiles-compute-optimized-arm">instances Elastic Cloud optimisées pour le processeur</a>.</p><ul><li><p>Volume de données : ~500 millions de documents</p></li><li><p>Infrastructure : 6 instances Elastic Cloud (Elasticsearch Service) (chaque instance : 1,76 To de stockage | 60 Go de RAM | 31,9 vCPU)</p></li><li><p>Rapport mémoire/stockage : la RAM peut recevoir environ 5 % du volume total de données</p></li></ul><h2><strong>Les symptômes : latence élevée</strong></h2><p>Nous avons constaté qu'aux alentours de 19:00, lorsque le nombre de requêtes augmentait fortement, la latence de recherche s'est considérablement dégradée. Comme le montrent les figures 1 et 2, lorsque le trafic atteignait un pic d'environ 400 requêtes par minute et par instance Elasticsearch, le temps de réponse moyen des requêtes chutait à plus de 60 ms.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf8ab7de934d6b410/6a170440c1e8a58db3f881c1/f9c6cc1882e7db24336c65c54bbc1d38dcdb7fa3-697x311.png" alt="Le nombre de requêtes par minute par instance Elasticsearch a atteint un pic" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt32de2bed0afbacd5/6a1704422b835fa5ddf4b0e2/bbb705ae2fcd14c81d335bf322346caf3bf33765-996x618.png" alt="Temps de réponse moyen pour les requêtes Elasticsearch" /><p>L'utilisation du processeur est restée relativement faible après le traitement initial des connexions, indiquant que le calcul n'était pas le facteur limitant.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta5b45d4a1ff48f54/6a17044447d49cd7252d88af/cec15a28d2d22e9adedd2951bb2334b3717890a1-1494x730.png" alt="Utilisation du processeur par Elasticsearch" /><p>Une forte corrélation est apparue entre le volume de requêtes et les défauts de page. À mesure que les requêtes augmentaient, nous avons observé une hausse proportionnelle des défauts de page, avec un pic aux alentours de 400k/minute. Cela indique que l'ensemble de données actif ne pouvait pas être contenu dans le cache de pages.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd0a3d0c610700bdb/6a17044560084b6f403c4459/511f2f10300a9d10ba3d7a82b9a8c8d567ac5636-1492x678.png" alt="Nombre de défauts de page et performances d'Elasticsearch" /><p>Parallèlement, l'utilisation du tas JVM semblait normale et saine. Cela a permis d'exclure les problèmes de récupération de mémoire et de confirmer que le goulot d'étranglement était lié aux entrées/sorties.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3f888a03ce78eb04/6a170448964cea401008ba59/336bbad638f866304358dba1d06ee987de0f23cf-1490x568.png" alt="Utilisation du tas dans Elasticsearch" /><h2><strong>Le diagnostic : I/O bound</strong></h2><p>Le système était limité par les E/S. <a href="https://www.elastic.co/blog/elasticsearch-caching-deep-dive-boosting-query-speed-one-cache-at-a-time">Elasticsearch s'appuie sur le cache de pages du système d'exploitation pour fournir les données d'index depuis la mémoire</a>. Lorsque l'index est trop volumineux pour le cache, les requêtes entraînent des lectures disque coûteuses. Bien que la solution classique consiste à effectuer un scaling horizontal (ajout de nœuds/RAM), nous souhaitions d'abord optimiser au maximum nos ressources existantes.</p><h2><strong>La solution</strong></h2><p>Par défaut, Elasticsearch utilise la compression <a href="https://en.wikipedia.org/wiki/LZ4_(compression_algorithm)">LZ4</a> pour ses segments d'index, qui offre un bon compromis entre vitesse et taille. Nous avons émis l'hypothèse que le passage à <code>best_compression</code> (qui utilise <a href="https://en.wikipedia.org/wiki/Zstd">zstd</a>) réduirait la taille des index. Une empreinte mémoire plus faible permet d'intégrer une plus grande partie de l'index dans le cache de pages, moyennant une augmentation négligeable de la charge CPU (pour la décompression) au profit d'une réduction des E/S disque.</p><p>Pour activer <code>best_compression</code>, nous avons réindexé les données avec le paramètre d'index <code>index.codec: best_compression</code>. Sinon, le même résultat pourrait être obtenu en fermant l'index, en réinitialisant le codec d'index à <code>best_compression</code>, puis en effectuant une fusion de segments.</p>POST my-index/_close
PUT my-index/_settings
{
    "codec": "best_compression"
}
  
POST my-index/_open  
POST my-index/_forcemerge?max_num_segments=1<h2><strong>Résultats</strong></h2><p>Les résultats ont confirmé notre hypothèse : l'amélioration de l'efficacité du stockage s'est directement traduite par une augmentation substantielle des performances de recherche sans augmentation concomitante de l'utilisation du processeur.</p><p>L'application de <code>best_compression</code> a réduit la taille de l'index d'environ 25 %. Bien qu'inférieure à la réduction observée dans les données de log répétitives, cette réduction de 25 % a effectivement augmenté la capacité de notre cache de pages dans les mêmes proportions.</p><p>Lors du test de charge suivant (à partir de 17:00), le trafic était encore plus élevé, avec un pic de 500 requêtes par minute et par nœud Elasticsearch.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta61ab3bd5ded5716/6a170449a6c2b9f711e795dd/fc1902f396cb2115c0013155ad07f6eb87389c60-660x309.png" alt="Test de charge dans Elaticserach" /><p>Malgré la charge plus élevée, l'utilisation du processeur était inférieure à celle de l'exécution précédente. L'utilisation élevée dans le test précédent était probablement due à la surcharge liée à la gestion excessive des défauts de page et à la gestion des E/S de disque.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9fd1a44b02a4f787/6a17044b2b835ff996f4b0e6/15699ef4c65b3f0a9f8a3e1bae8bb18f7b647025-819x352.png" alt="Amélioration des performances d'utilisation du processeur Elasticsearch avec best_compression" /><p>Surtout, le nombre de défauts de page diminue de manière significative. Même à un débit plus élevé, les erreurs se situent autour de &lt;200k par minute, contre &gt;300k dans le test de référence.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltef0c621d76767115/6a17044c2b835fe49ef4b0ea/f76ca967976d740af88a9359b66041701abb46fc-764x340.png" alt="Nombre de défauts de page et amélioration des performances Elasticsearch avec best_compression" /><p>Bien que les résultats concernant les défauts de page soient encore loin d'être optimaux, le temps de réponse aux requêtes a été réduit d'environ 50 %, se maintenant sous la barre des 30 ms même en cas de charge plus importante.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt6579b3d005d04101/6a17044e66c4f9179cf8bf13/750ec1c59b8eb5069aed4c066d856ecea82d5bca-620x311.png" alt="Amélioration des performances moyennes du temps de réponse aux requêtes dans Elasticsearch avec best_compression" /><p></p><h2><strong>Conclusion : best_compression pour la recherche</strong></h2><p>Pour les cas d'utilisation de recherche où le volume de données dépasse la mémoire physique disponible, <code>best_compression</code> est un levier puissant d'optimisation des performances.</p><p>La solution classique aux erreurs de cache consiste à scaler pour augmenter la RAM. Cependant, en réduisant l'empreinte de l'index, nous avons atteint le même objectif : maximiser le nombre de documents dans le cache de pages. Notre prochaine étape consistera à explorer l'<a href="https://www.elastic.co/blog/space-savings-a-lesser-known-benefit-of-index-sorting-in-elasticsearch"><strong>index trié</strong></a> afin d'optimiser davantage l'espace de stockage et d'améliorer encore les performances de nos ressources existantes.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/improve-elasticsearch-performance-best-compression</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/improve-elasticsearch-performance-best-compression</guid>
    <category><![CDATA[À l'intérieur d'Elastic]]></category>
    <dc:creator><![CDATA[Sherry Ger,Ryan Eno]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt4ff57fbb95c04412/6a17044fab7f081490db9d66/5141a8c2618337207d848ce16b258a86885955b2-1600x1034.jpg" length="0" type="image/jpeg"/>
    <pubDate>Fri, 23 Jan 2026 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Évaluer la pertinence des requêtes de recherche à l’aide de listes de jugement]]></title>
    <description><![CDATA[Découvrez comment créer des listes de jugement pour évaluer objectivement la pertinence des requêtes de recherche et améliorer des indicateurs de performance comme le rappel, dans le cadre de tests de recherche scalable avec Elasticsearch.]]></description>
    <content:encoded><![CDATA[<p>Les développeurs travaillant sur des moteurs de recherche rencontrent souvent le même problème : l’équipe métier n’est pas satisfaite d’un résultat de recherche, car les documents attendus en tête des résultats apparaissent en troisième ou quatrième position.</p><p>Mais en corrigeant ce cas précis, vous risquez de détériorer d’autres requêtes, faute de pouvoir tester chaque cas manuellement. Mais comment vérifier, vous ou votre équipe QA, si une modification d’une requête a un effet en cascade sur les autres ? Et surtout, comment s’assurer que les modifications apportées ont réellement amélioré une requête ?</p><h2>Vers une évaluation systématique</h2><p>C’est là que les listes de jugement prennent tout leur sens. Plutôt que de recourir à des tests manuels et subjectifs à chaque changement, vous pouvez définir un ensemble fixe de requêtes pertinentes pour votre cas d’usage, avec leurs résultats attendus.</p><p>Cet ensemble vous sert de référence. À chaque modification, vous l’utilisez pour déterminer si votre recherche s’est effectivement améliorée ou non.</p><p>Ce qui rend cette approche si précieuse :</p><ul><li><p><strong>Élimine l’incertitude</strong> : plus besoin de vous demander si vos changements impactent d’autres requêtes – les données vous le diront.</p></li><li><p><strong>Met fin aux tests manuels</strong> : une fois les ensembles de jugement enregistrés, le test devient automatique.</p></li><li><p><strong>Accompagne les changements</strong> : vous pouvez mettre en évidence des métriques claires qui confirment les bénéfices d’une modification.</p></li></ul><h2>Comment constituer votre liste de jugement</h2><p>L’une des façons les plus simples de commencer consiste à choisir une requête représentative et à sélectionner manuellement les documents pertinents. Deux approches sont possibles pour construire cette liste :</p><ul><li><p><strong>Jugements binaires :</strong> Chaque document associé à une requête reçoit une <strong>étiquette simple</strong> : <em>pertinent</em> (1) ou non pertinent (0).</p></li><li><p><strong>Jugements gradués :</strong> chaque document reçoit ici un score selon différents niveaux. Exemple : une échelle de 0 à 4, semblable à une <a href="https://en.wikipedia.org/wiki/Likert_scale">échelle de Likert</a>, où 0 signifie « pas du tout pertinent » et 4 « totalement pertinent », avec des nuances comme « pertinent », « plus ou moins pertinent », etc.</p></li></ul><p>Les jugements binaires sont adaptés lorsque l’intention de recherche est bien définie : ce document doit-il apparaître dans les résultats ou non ?</p><p>Les jugements gradués sont utiles lorsque la frontière est plus floue : certains résultats sont meilleurs que d’autres. On peut ainsi distinguer des résultats « très pertinents », « pertinents » ou « inutiles », et utiliser des métriques qui prennent en compte l’ordre des résultats ainsi que les retours des utilisateurs. Mais les échelles graduées présentent aussi des inconvénients : les évaluateurs peuvent interpréter différemment les niveaux de notation, ce qui nuit à la cohérence des jugements. De plus, comme les métriques graduées accordent plus de poids aux notes élevées, une légère variation (par exemple, noter 3 au lieu de 4) peut entraîner un changement bien plus important dans la métrique que ce que l’évaluateur avait anticipé. Cette part de subjectivité rend les jugements gradués plus bruyants et plus difficiles à gérer dans le temps.</p><h2>Dois-je classer les documents moi-même ?</h2><p>Pas forcément, car il existe plusieurs façons de créer votre liste de jugement, chacune avec ses avantages et ses inconvénients :</p><ul><li><p><strong>Jugements explicites :</strong> des experts métier examinent chaque couple requête/document et évaluent manuellement le niveau de pertinence. Cela garantit qualité et contrôle, mais c’est moins scalable.</p></li><li><p><strong>Jugements implicites :</strong> cette méthode déduit les documents pertinents à partir du comportement réel des utilisateurs : clics, taux de rebond, achats, etc. Elle permet de collecter automatiquement des données, mais celles-ci peuvent être biaisées. Par exemple, les utilisateurs ont tendance à cliquer plus souvent sur les premiers résultats, même s’ils ne sont pas pertinents.</p></li><li><p><strong>Jugements générés par l’IA :</strong> cette dernière option utilise des modèles (comme les LLM) pour évaluer automatiquement les requêtes et les documents – on parle souvent de<a href="https://en.wikipedia.org/wiki/LLM-as-a-Judge"> jurys LLM</a>. C’est rapide et facilement scalable, mais la qualité des données dépend du modèle utilisé et de la pertinence de ses données d’entraînement vis-à-vis de vos <a href="http://interests.as/">objectifs</a> métier. Comme pour les évaluations humaines, les jurys LLM peuvent introduire leurs propres biais ou incohérences. Il est donc essentiel de valider leurs résultats à l’aide d’un ensemble restreint de jugements de confiance. Les modèles LLM sont de nature probabiliste, il n’est donc pas rare de voir un modèle LLM attribuer des scores différents à un même résultat, même avec un paramètre de <a href="https://www.ibm.com/think/topics/llm-temperature">température</a> réglé sur 0.</p></li></ul><p>Voici quelques recommandations pour choisir la méthode la plus adaptée à la création de votre ensemble de jugement :</p><ul><li><p>Décidez des fonctionnalités critiques pour lesquelles seuls les utilisateurs peuvent vraiment juger (prix, marque, langue, style, détails du produit, etc.). Si ces éléments sont critiques, vous avez besoin de <strong>jugements explicites</strong> – au moins pour une partie de votre <em>liste de jugement</em>.</p></li><li><p>Utilisez des <strong>jugements implicites</strong> lorsque votre moteur de recherche génère déjà suffisamment de trafic pour que vous puissiez exploiter les clics, conversions et temps passés comme métriques de tendance. Il reste essentiel d’interpréter ces résultats avec prudence, en les comparant à des jugements explicites afin d’éviter tout biais (ex. : les utilisateurs ont tendance à cliquer sur les premiers résultats, même si des documents plus pertinents apparaissent plus bas).</p></li></ul><p>Pour y remédier, des techniques de réduction des biais de position permettent d’ajuster ou de repondérer les données de clics afin de mieux refléter l’intérêt réel des utilisateurs. Parmi les approches possibles :</p><ul><li><p><strong>Changement d’ordre des résultats</strong> : permet de modifier l’ordre des résultats de recherche pour un sous-ensemble d’utilisateurs afin d’évaluer l’effet de la position sur les clics.</p></li><li><p>Les <strong>modèles de clic</strong> incluent<a href="https://wiki.math.uwaterloo.ca/statwiki/index.php?title=a_Dynamic_Bayesian_Network_Click_Model_for_web_search_ranking"> : Dynamic Bayesian Network </a><a href="https://wiki.math.uwaterloo.ca/statwiki/index.php?title=a_Dynamic_Bayesian_Network_Click_Model_for_web_search_ranking"><strong>(DBN)</strong></a>, <a href="https://rsrikant.com/papers/kdd10.pdf">User Browsing Model</a> <a href="https://rsrikant.com/papers/kdd10.pdf"><strong>(UBM)</strong></a>, etc. Ces modèles statistiques estiment la probabilité qu’un clic reflète un véritable intérêt et non simplement une position dans la page, en prenant en compte des facteurs comme le défilement, la durée du clic, la séquence de navigation, et le retour aux résultats.</p></li></ul><h2>Exemple : application de notation de films</h2><h3>Produits requis</h3><p>Pour exécuter cet exemple, vous avez besoin d'un cluster Elasticsearch 8.x en cours d'exécution, <a href="https://www.elastic.co/downloads/elasticsearch">en local</a> ou sur <a href="https://www.elastic.co/cloud/cloud-trial-overview">Elastic Cloud Hosted</a> (hébergé ou sans serveur), ainsi que d'un accès à l'<a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis">API REST</a> ou à Kibana.</p><p>Imaginez une application dans laquelle les utilisateurs peuvent publier leurs avis sur des films et aussi rechercher des films à regarder. Comme ces textes sont rédigés par les utilisateurs eux-mêmes, ils peuvent contenir des fautes de frappe ou de nombreuses variations dans la façon de s’exprimer. Il est donc essentiel que le moteur de recherche puisse interpréter cette diversité et fournir des résultats utiles aux utilisateurs.</p><p>Afin de pouvoir tester différentes requêtes sans impacter le comportement global de la recherche, l’équipe métier de votre entreprise a créé l’ensemble de jugement binaire suivant, basé sur les recherches les plus fréquentes :</p><p>Requête</p><p>DocID</p><p>Texte</p><p>Performance de DiCaprio</p><p>doc1</p><p>La performance de DiCaprio dans The Revenant était époustouflante.</p><p>Performance de DiCaprio</p><p>doc2</p><p>Inception montre Leonardo DiCaprio dans l’un de ses rôles les plus emblématiques.</p><p>Performance de DiCaprio</p><p>doc3</p><p>Brad Pitt offre une performance solide dans ce thriller criminel.</p><p>Performance de DiCaprio</p><p>doc4</p><p>Une aventure riche en action avec des effets visuels impressionnants.</p><p>films tristes qui vous font pleurer</p><p>doc5</p><p>Une histoire bouleversante d’amour et de perte qui m’a fait pleurer pendant des heures.</p><p>films tristes qui vous font pleurer</p><p>doc6</p><p>Un des films les plus tristes jamais réalisés — apportez des mouchoirs !</p><p>films tristes qui vous font pleurer</p><p>doc7</p><p>Une comédie légère qui vous fera rire</p><p>films tristes qui vous font pleurer</p><p>doc8</p><p>Une épopée de science-fiction pleine d’action et de rebondissements.</p><p>Création de l'index :</p>PUT movies
{
  "mappings": {
    "properties": {
      "text": {
        "type": "text"
      }
    }
  }
}<p>Requête BULK :</p>POST /movies/_bulk
{ "index": { "_id": "doc1" } }
{ "text": "DiCaprio performance in The Revenant was breathtaking." }
{ "index": { "_id": "doc2" } }
{ "text": "Inception shows Leonardo DiCaprio in one of his most iconic roles." }
{ "index": { "_id": "doc3" } }
{ "text": "Brad Pitt delivers a solid performance in this crime thriller." }
{ "index": { "_id": "doc4" } }
{ "text": "An action-packed adventure with stunning visual effects." }
{ "index": { "_id": "doc5" } }
{ "text": "A heartbreaking story of love and loss that made me cry for hours." }
{ "index": { "_id": "doc6" } }
{ "text": "One of the saddest movies ever made -- bring tissues!" }
{ "index": { "_id": "doc7" } }
{ "text": "A lighthearted comedy that will make you laugh." }
{ "index": { "_id": "doc8" } }
{ "text": "A science-fiction epic full of action and excitement." }<p>Voici la requête Elasticsearch utilisée par l’application :</p>GET movies/_search
{
 "query": {
   "match": {
     "text": {
       "query": "DiCaprio performance",
       "minimum_should_match": "100%"
     }
   }
 }
}<h3>Du jugement aux métriques</h3><p>À elles seules, les listes de jugement fournissent peu d’informations : elles ne font qu’exprimer une attente vis-à-vis des résultats de nos requêtes. Elles révèlent tout leur intérêt lorsqu’elles servent à calculer des métriques objectives pour évaluer les performances de la recherche.</p><p>Aujourd’hui, la plupart des métriques les plus courantes incluent</p><ul><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#k-precision"><strong>Précision</strong></a><strong> : </strong>mesure la proportion de résultats réellement pertinents parmi tous les résultats de recherche.</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#k-recall"><strong>Rappel</strong></a><strong> : </strong>mesure la proportion de documents pertinents que le moteur de recherche a trouvés parmi tous les résultats.</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#_discounted_cumulative_gain_dcg"><strong>Gain Cumulé Actualisé (DCG)</strong></a><strong> : </strong>mesure la qualité du classement des résultats, en tenant compte du fait que les documents les plus pertinents devraient apparaître en haut de la liste.</p></li><li><p><a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval#_mean_reciprocal_rank"><strong>Rang réciproque moyen (MRR) :</strong></a> mesure la position du premier résultat pertinent. Plus un document est haut dans la liste, plus son score est élevé.</p></li></ul><p>En reprenant l’exemple de l’application de notation de films, nous allons calculer la métrique de rappel pour vérifier si des informations sont ignorées par nos requêtes.</p><p>Dans Elasticsearch, nous pouvons utiliser les <em>listes de jugement</em> pour calculer ces métriques via l’<a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/search-rank-eval">API Ranking Evaluation</a>. Cette API prend en entrée la liste de jugement, la requête et la métrique à évaluer, puis retourne une valeur qui correspond à une comparaison du résultat de la requête avec la liste de jugement.</p><p>Lançons la liste de jugement pour les deux requêtes dont nous disposons :</p>POST /movies/_rank_eval
{
 "requests": [
   {
     "id": "dicaprio-performance",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "DiCaprio performance",
             "minimum_should_match": "100%"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc1",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc2",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc3",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc4",
         "rating": 0
       }
     ]
   },
   {
     "id": "sad-movies",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "sad movies that make you cry",
             "minimum_should_match": "100%"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc5",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc6",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc7",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc8",
         "rating": 0
       }
     ]
   }
 ],
 "metric": {
   "recall": {
     "k": 10,
     "relevant_rating_threshold": 1
     }
 }
}<p>Nous allons utiliser deux requêtes avec rank_eval : une pour la requête sur DiCaprio et une autre pour les films tristes. Chaque requête est accompagnée de sa propre liste de jugement (notations). Il n’est pas nécessaire d’évaluer tous les documents : ceux qui ne figurent pas dans la liste de notation sont simplement considérés comme non jugés. Pour effectuer les calculs, la métrique de rappel ne prend en compte que l’« ensemble pertinent », c’est-à-dire les documents jugés pertinents dans l’évaluation.</p><p>Dans ce cas, la requête sur DiCaprio obtient un rappel de 1, tandis que celle sur les films tristes obtient 0. Autrement dit, nous avons récupéré tous les résultats pertinents pour la première requête, et aucun pour la seconde. Le rappel moyen est donc de 0,5.</p>{
 "metric_score": 0.5,
 "details": {
   "dicaprio-performance": {
     "metric_score": 1,
     "unrated_docs": [],
     "hits": [
       {
         "hit": {
           "_index": "movies",
           "_id": "doc1",
           "_score": 2.4826927
         },
         "rating": 1
       },
       {
         "hit": {
           "_index": "movies",
           "_id": "doc2",
           "_score": 2.0780432
         },
         "rating": 1
       }
     ],
     "metric_details": {
       "recall": {
         "relevant_docs_retrieved": 2,
         "relevant_docs": 2
       }
     }
   },
   "sad-movies": {
     "metric_score": 0,
     "unrated_docs": [],
     "hits": [],
     "metric_details": {
       "recall": {
         "relevant_docs_retrieved": 0,
         "relevant_docs": 2
       }
     }
   }
 },
 "failures": {}
}<p>Peut-être que nous sommes trop stricts avec le paramètre minimum_should_match : en exigeant que 100 % des mots de la requête soient présents dans les documents, nous risquons d’écarter des résultats pertinents. Supprimons le paramètre <strong>minimum_should_match</strong>, afin qu’un document soit considéré comme pertinent dès qu’un seul mot de la requête est présent.</p>POST /movies/_rank_eval
{
 "requests": [
   {
     "id": "dicaprio-performance",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "DiCaprio performance"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc1",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc2",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc3",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc4",
         "rating": 0
       }
     ]
   },
   {
     "id": "sad-movies",
     "request": {
       "query": {
         "match": {
           "text": {
             "query": "sad movies that make you cry"
           }
         }
       }
     },
     "ratings": [
       {
         "_index": "movies",
         "_id": "doc5",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc6",
         "rating": 1
       },
       {
         "_index": "movies",
         "_id": "doc7",
         "rating": 0
       },
       {
         "_index": "movies",
         "_id": "doc8",
         "rating": 0
       }
     ]
   }
 ],
 "metric": {
   "recall": {
     "k": 10,
     "relevant_rating_threshold": 1
     }
 }
}<p>Comme vous pouvez le constater, en supprimant le paramètre <strong>minimum_should_match</strong> dans l'une des deux requêtes, nous obtenons maintenant un rappel moyen de 1 dans les deux cas.</p>{
  "metric_score": 1,
  "details": {
    "dicaprio-performance": {
      "metric_score": 1,
      "unrated_docs": [],
      "hits": [
        {
          "hit": {
            "_index": "movies",
            "_id": "doc1",
            "_score": 2.0661702
          },
          "rating": 1
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc3",
            "_score": 0.732218
          },
          "rating": 0
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc2",
            "_score": 0.6271719
          },
          "rating": 1
        }
      ],
      "metric_details": {
        "recall": {
          "relevant_docs_retrieved": 2,
          "relevant_docs": 2
        }
      }
    },
    "sad-movies": {
      "metric_score": 1,
      "unrated_docs": [],
      "hits": [
        {
          "hit": {
            "_index": "movies",
            "_id": "doc7",
            "_score": 2.1307156
          },
          "rating": 0
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc5",
            "_score": 1.3160692
          },
          "rating": 1
        },
        {
          "hit": {
            "_index": "movies",
            "_id": "doc6",
            "_score": 1.190063
          },
          "rating": 1
        }
      ],
      "metric_details": {
        "recall": {
          "relevant_docs_retrieved": 2,
          "relevant_docs": 2
        }
      }
    }
  },
  "failures": {}
}<p>En résumé, supprimer la clause minimum_should_match : 100 % permet d’obtenir un rappel parfait pour les deux requêtes.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltaf4f08a8a2915180/6a170df61949f76cbfe7aaba/24d055da4348c63827ba7046fe8cafb6f47cadd8-546x628.png" alt="" /><p>Nous l'avons fait ! N'est-ce pas ?</p><p>Pas si vite !</p><p>En augmentant le rappel, on élargit la gamme des résultats possibles. Cependant, chaque ajustement implique un compromis. D’où l’importance de définir des cas de test complets, en utilisant plusieurs métriques pour évaluer les changements.</p><p>Les listes de jugement et les métriques vous évitent d’avancer à l’aveugle lorsque vous apportez des modifications, car vous disposez désormais de données pour les justifier. La validation n’est plus manuelle ni répétitive, et vous pouvez tester vos changements sur plusieurs cas d’usage, et non plus un seul. Les tests A/B vous permettent également de tester en conditions réelles la configuration qui convient le mieux à vos utilisateurs et à votre cas d’utilisation, bouclant ainsi la boucle entre métriques techniques et résultats concrets.</p><h2>Recommandations finales pour l’utilisation des listes de jugement</h2><p>Travailler avec des listes de jugement ne consiste pas seulement à mesurer : c’est aussi construire un cadre vous permettant d’itérer en toute confiance. Pour y parvenir, voici quelques recommandations :</p><ol><li><p><strong>Démarrez petit, mais démarrez</strong>. Il n’est pas nécessaire d’avoir 10 000 requêtes avec 50 listes de jugement chacune. Vous devez seulement identifier les 5 à 10 requêtes les plus critiques pour votre cas d’utilisation, et définir les documents que vous attendez en haut des résultats. Cela vous donne déjà une base de travail. En général, on commence par les principales requêtes et celles qui ne renvoient aucun résultat. Vous pouvez aussi tester en partant d’une métrique simple comme la précision, puis monter en complexité.</p></li><li><p><strong>Validez avec les utilisateurs.</strong> Complétez les résultats chiffrés par des tests A/B en production. De cette façon, vous saurez si les modifications prometteuses dans les métriques ont aussi un véritable impact.</p></li><li><p><strong>Gardez la liste vivante.</strong> Votre cas d’utilisation évoluera, tout comme vos requêtes critiques. Mettez régulièrement à jour votre liste de jugement pour refléter les nouveaux besoins.</p></li><li><p><strong>Intégrez-la à vos workflows.</strong> Intégrez les listes de jugement dans vos pipelines de développement. Assurez-vous que chaque modification de configuration, de synonymes ou d’analyse de texte soit automatiquement validée à partir de votre liste de référence.</p></li><li><p><strong>Connectez les savoir-faire techniques à la stratégie.</strong> Ne vous limitez pas à des métriques techniques comme la précision ou le rappel. Utilisez les résultats d’évaluation pour éclairer vos décisions métier.</p></li></ol>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/judgment-lists-search-query-relevance-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/judgment-lists-search-query-relevance-elasticsearch</guid>
    <category><![CDATA[Pertinence]]></category>
    <category><![CDATA[À l'intérieur d'Elastic]]></category>
    <dc:creator><![CDATA[Jhon Guzmán]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcadfd2fb1cc95b4c/6a170df7acf0887798be9bd0/25478d0ffb228afd5d65d82312998ec1c299c565-700x490.png" length="0" type="image/png"/>
    <pubDate>Thu, 11 Dec 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Configurer le découpage récursif pour les documents structurés dans Elasticsearch]]></title>
    <description><![CDATA[Apprenez à configurer le découpage récursif dans Elasticsearch avec la taille des morceaux, les groupes de séparateurs et les listes de séparateurs personnalisées pour une indexation optimale des documents structurés.]]></description>
    <content:encoded><![CDATA[<p>Depuis la version 8.16, les utilisateurs peuvent configurer la stratégie de découpage utilisée lors de l'ingestion de longs documents dans des champs de texte sémantique. Depuis la version 9.1 / 8.19, nous avons introduit une nouvelle stratégie de découpage récursif configurable qui utilise une liste d'expressions régulières pour découper le document. L'objectif du découpage en morceaux est de diviser un long document en sections qui encapsulent un contenu apparenté. Nos stratégies existantes permettent de diviser le texte selon une granularité de mots/phrases, mais les documents écrits dans des formats structurés (ex. Markdown) contiennent souvent des contenus connexes dans des sections définies par des chaînes de séparation (ex. ). Pour ces types de documents, nous introduisons la stratégie de découpage récursif afin d'exploiter le format des documents structurés pour créer de meilleurs morceaux !</p><h2>Qu'est-ce que le découpage récursif ?</h2><p>Le découpage récursif parcourt une liste de sections fournies en séparant les modèles afin de diviser progressivement un document en segments plus petits jusqu'à ce qu'ils atteignent une taille maximale souhaitée.</p><h3>Comment configurer le découpage récursif ?</h3><p>Les valeurs configurables fournies par l'utilisateur pour le découpage récursif sont les suivantes :</p><ul><li><p>(obligatoire) <code>max_chunk_size</code>: Le nombre maximum de mots dans un bloc.</p></li><li><p>L'un ou l'autre :</p><ul><li><p><code>separators</code>: Une liste de motifs de chaînes regex qui seront utilisés pour découper le document en morceaux.</p></li><li><p><code>separator_group</code>: Une chaîne qui correspondra à une liste par défaut de séparateurs définis par Elastic à utiliser pour des types de documents spécifiques. Actuellement, <code>markdown</code> et <code>plaintext</code> sont disponibles.</p></li></ul></li></ul><h3>Comment fonctionne le découpage récursif ?</h3><p>Le processus de découpage récursif d'un document d'entrée, d'un <code>max_chunk_size</code> (mesuré en mots) et d'une liste de chaînes de séparation est le suivant :</p><ol><li><p>Si le document d'entrée est déjà compris dans la taille maximale des morceaux, il renvoie un seul morceau couvrant l'ensemble du document d'entrée.</p></li><li><p>Découper le texte en morceaux potentiels sur la base des occurrences du séparateur. Pour chaque morceau potentiel :</p><ol><li><p>Si le morceau potentiel ne dépasse pas la taille maximale, il est ajouté à la liste des morceaux à renvoyer à l'utilisateur.</p></li><li><p>Sinon, répétez l'étape 2, en utilisant uniquement le texte du morceau potentiel et en le séparant à l'aide du séparateur suivant dans la liste. S'il n'y a plus de séparateurs à essayer, il faut se rabattre sur le découpage en phrases.</p></li></ol></li></ol><h2>Exemples de configuration du découpage récursif</h2><p>Outre la taille des morceaux, la principale configuration du découpage récursif consiste à sélectionner les séparateurs à utiliser pour diviser vos documents. Si vous ne savez pas par où commencer, Elasticsearch propose quelques groupes de séparateurs par défaut qui peuvent être utilisés pour des cas d'utilisation courants.</p><h3>Utilisation de groupes de séparation</h3><p>Pour utiliser un groupe séparateur, il suffit d'indiquer le nom du groupe que vous souhaitez utiliser lors de la configuration des paramètres de regroupement. Par exemple :</p>"chunking_settings": {
    "strategy": "recursive",
    "max_chunk_size": 25,
    "separator_group": "plaintext"
}<p>Vous obtiendrez ainsi une stratégie de découpage récursif qui utilise la liste de séparateurs <code>["(?&lt;!\\n)\\n\\n(?!\\n)", "(?&lt;!\\n)\\n(?!\\n)")]</code>. Cela fonctionne bien pour les applications génériques de texte brut, en séparant deux caractères de retour à la ligne, suivis d'un caractère de retour à la ligne.</p><p>Nous proposons également un groupe de séparateurs <code>markdown</code> qui utilisera la liste des séparateurs :</p>[
"\n# ",
       "\n## ",
       "\n### ",
       "\n#### ",
       "\n##### ",
       "\n###### ",
       "\n^(?!\\s*$).*\\n-{1,}\\n",
       "\n^(?!\\s*$).*\\n={1,}\\n"
]<p>Cette liste de séparateurs fonctionnera bien pour les cas d'utilisation généraux de markdown, en séparant chacun des 6 niveaux d'en-tête et les caractères de coupure de section.</p><p>Lors de la création d'une ressource (point d'inférence/champ textuel sémantique), la liste des séparateurs correspondant au groupe de séparateurs du moment sera stockée dans vos configurations. Si le groupe de séparateurs est mis à jour ultérieurement, cela ne modifiera pas le comportement des ressources déjà créées.</p><h3>Utilisation d'une liste de séparateurs personnalisée</h3><p>Si l'un des groupes de séparateurs prédéfinis ne convient pas à votre cas d'utilisation, vous pouvez définir une liste personnalisée de séparateurs répondant à vos besoins. Notez que des expressions régulières peuvent être fournies dans la liste des séparateurs. Voici un exemple de paramètres de regroupement configurés avec des séparateurs personnalisés :</p>"chunking_settings": {
    "strategy": "recursive",
    "max_chunk_size": 25,
    "separators": ["\n\n", "\n", "&lt;my-custom-separator&gt;"]
}<p>La stratégie de découpage en morceaux découpera 2 caractères de nouvelle ligne, suivis d'un caractère de nouvelle ligne, et enfin une chaîne de caractères <code>“&lt;my-custom-separator&gt;”</code>.</p><h2>Un exemple de découpage récursif en action</h2><p>Voyons un exemple de découpage récursif en action. Pour cet exemple, nous utiliserons les paramètres de découpage suivants avec une liste personnalisée de séparateurs qui découpent un document markdown en utilisant les deux premiers niveaux d'en-tête :</p>"chunking_settings": {
    "strategy": "recursive",
    "max_chunk_size": 25,
    "separators": ["\n# ", "\n## "]
}<p>Examinons un simple document Markdown non tronqué :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltdb5f41d1bd43ba50/6a17e831e9ea87c1d8a9c5f3/3a5507f4a1288065097231548e5b18e240508785-1302x1446.png" alt="Un document Markdown non tronqué" /><p>Utilisons maintenant les paramètres de découpage définis ci-dessus pour découper le document en morceaux :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfffda162c7b9c87a/6a17e83296142aefa8eb1b0b/a3313c4c40ff39b8dbcdd7c4878c723f088e6c1a-1600x1187.png" alt="Chunking d'un document dans Elasticsearch" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt96f65346a8e09e3a/6a17e834445de9157b4d015e/79a2921943191ea631df94c9d465818ec8d3e738-1600x1206.png" alt="Splitting on second separator- chunking a document in Elasticsearch" /><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt28381c8f85aedf07/6a17e836ec0f89801e5a6640/459e695cce7540267422396b9a62ff4ad35f61db-1600x1260.png" alt="Derniers morceaux d'un document après un découpage basé sur les phrases dans Elasticsearch" /><p>Remarque : la nouvelle ligne à la fin de chaque morceau (à l'exception du morceau 3) n'est pas mise en évidence, mais elle est incluse dans les limites du morceau.</p><h3>Commencez dès aujourd'hui à utiliser le découpage récursif !</h3><p>Pour plus d'informations sur l'utilisation de cette fonctionnalité, consultez la documentation sur la configuration des paramètres de regroupement.</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[Les bases]]></category>
    <category><![CDATA[À l'intérieur d'Elastic]]></category>
    <category><![CDATA[IA]]></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[Expériences d'amélioration des outils d'IA agentique pour Elasticsearch]]></title>
    <description><![CDATA[Découvrez comment nous avons amélioré les flux de travail des agents d'IA pour Elasticsearch par le biais d'expériences itératives en combinant les extracteurs linéaires, la recherche hybride et semantic_text pour une optimisation RAG évolutive.]]></description>
    <content:encoded><![CDATA[<p>Comme tout le monde ces jours-ci, ici à Elastic, nous nous lançons à fond dans le Chat, les agents et le RAG. Dans le département Search, nous avons récemment travaillé sur un Agent Builder et un Tool Registry, dans le but de rendre trivial le "chat" avec vos données dans Elasticsearch.</p><p>Lisez le <a href="https://www.elastic.co/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder">blog Building AI Agentic Workflows with Elasticsearch</a> pour en savoir plus sur la "vue d'ensemble" de cet effort, ou <a href="https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch">Your First Elastic Agent : From a Single Query to an AI-Powered Chat</a> pour une introduction plus pratique.</p><p>Dans ce blog, nous allons nous intéresser à l'une des premières choses qui se produisent lorsque vous commencez à discuter et vous présenter quelques-unes des améliorations récentes que nous avons apportées.</p><h2>Que se passe-t-il ici ?</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1331b1043612efe3/6a17f115505ac3dc41ad8c3c/25a24055a166d7d6ba81d80aa35cb97163662e23-1600x443.png" alt="" /><p>Lorsque vous discutez avec vos données Elasticsearch, notre agent IA par défaut suit ce flux standard :</p><ol><li><p>Inspecter l'invite.</p></li><li><p>Identifiez l'index susceptible de contenir les réponses à cette question.</p></li><li><p>Générer une requête pour cet index, sur la base de l'invite.</p></li><li><p>Effectuez une recherche dans cet index avec cette requête.</p></li><li><p>Synthétiser les résultats.</p></li><li><p>Les résultats peuvent-ils répondre à l'invitation ? Si oui, répondez. Si ce n'est pas le cas, répétez l'opération, mais essayez quelque chose de différent.</p></li></ol><p>Cela ne devrait pas sembler trop nouveau - il s'agit simplement de Retrieval Augmented Generation (RAG). Et comme on peut s'y attendre, la qualité de vos réponses dépend fortement de la pertinence de vos premiers résultats de recherche. En travaillant à l'amélioration de la qualité de nos réponses, nous avons donc accordé une attention toute particulière aux requêtes générées à l'étape 3 et exécutées à l'étape 4. Et nous avons remarqué une tendance intéressante.</p><p>Souvent, lorsque nos premières réponses étaient "mauvaises", ce n'était pas parce que nous avions lancé une mauvaise requête. C'est parce que <em>nous avions choisi le mauvais index</em> à interroger. Les étapes 3 et 4 ne nous posaient généralement pas de problème - c'était l'étape 2.</p><h2>Que faisions-nous ?</h2><p>Notre mise en œuvre initiale était simple. Nous avions construit un outil (appelé index_explorer) qui faisait effectivement un <code>_cat/indices</code> pour lister tous les indices disponibles, puis demandait au LLM d'identifier lequel de ces indices correspondait le mieux au message/à la question/à l'invitation de l'utilisateur. Vous pouvez voir cette <a href="https://github.com/elastic/kibana/blob/0cc78184957fcd12110dabae50353392ea937508/x-pack/platform/packages/shared/onechat/onechat-genai-utils/tools/index_explorer.ts#L98-L113">mise en œuvre originale ici.</a></p>You are an AI assistant for the Elasticsearch company.
based on a natural language query from the user, your task is to select up to ${limit} most relevant indices from a list of indices.

*The natural language query is:* ${nlQuery}

*List of indices:*
${indices.map((index) =&gt; `- ${index.index}`).join('\n')}

Based on those information, please return most relevant indices with your reasoning.
Remember, you should select at maximum ${limit} indices.<p>Dans quelle mesure cela a-t-il fonctionné ? Nous n'étions pas sûrs ! Nous avions des exemples clairs de <em>dysfonctionnements</em>, mais notre premier défi était de quantifier notre situation actuelle.</p><h2>Établir une base de référence</h2><h3>Cela commence par des données</h3><p>Nous avions besoin d'un ensemble de données en or pour mesurer l'efficacité d'un outil à sélectionner le bon indice à partir d'une demande de l'utilisateur et d'un ensemble préexistant d'indices. Comme nous ne disposions pas d'un tel ensemble de données, nous en avons créé un.</p><p>Reconnaissance : Il ne s'agit pas d'une "meilleure pratique", nous le savons. Mais parfois, il est préférable d'aller de l'avant plutôt que de faire du surplace. <a href="https://www.elastic.co/about/our-source-code#progress-perfection">Le progrès, la perfection SIMPLE</a>.</p><p>Nous avons généré des indices de semences pour plusieurs domaines différents à l'aide de <a href="https://gist.github.com/seanstory/a08db2e149897da656db3a1ca72e17ac">cette invite</a>. Ensuite, pour chaque domaine généré, nous avons généré quelques indices supplémentaires en utilisant<a href="https://gist.github.com/seanstory/a280a85d067e61bfeb5911bf2654e6e2"> cette invite</a> (l'objectif étant ici de semer la confusion pour le LLM avec des négatifs durs et des exemples difficiles à classer). Ensuite, nous avons édité manuellement chaque index généré et ses descriptions. Enfin, nous avons généré des requêtes de test à l'aide de <a href="https://gist.github.com/seanstory/44291b666c05a383136f6e36bb9106fa">cette invite</a>, ce qui nous a permis d'obtenir des échantillons de données tels que les suivants :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1bd9cd78154195e3/6a17f117dbb4fff7b5fb57d2/9d96d87e286eddbc012402b1ecccd57419a99253-1600x782.png" alt="" /><p>et des cas de test tels que :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltadf30a0aeafd56ef/6a17f1192f4a5c160ffa89eb/4c2e9ad941d98d7e66033bbc08c9b8060ec19097-1600x797.png" alt="" /><h3>Élaboration d'un harnais de test</h3><p>À partir de là, la procédure a été très simple. Script up a tool that could :</p><ol><li><p>Faire table rase du passé avec un cluster Elasticsearch cible.</p></li><li><p>Créer tous les indices définis dans le jeu de données cible.</p></li><li><p>Pour chaque scénario de test, exécutez l'outil i<code>ndex_explorer</code> (nous disposons d'une <a href="https://www.elastic.co/docs/api/doc/kibana/operation/operation-post-agent-builder-tools-execute">API pour l'exécution de l'outil</a>).</p></li><li><p>Comparez l'indice du résultat à l'indice attendu et saisissez le résultat.</p></li><li><p>Une fois tous les scénarios de test terminés, les résultats sont présentés sous forme de tableau.</p></li></ol><h3>L'enquête dit...</h3><p>Les premiers résultats ont été, sans surprise, médiocres.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt73367741359e258d/6a17f11a505ac39749ad8c40/9c10679bcd6291edfa2a9ba42e7dd922aa483f0b-1216x806.png" alt="" /><p>Dans l'ensemble, 77,14% ont identifié avec précision le bon indice. Et ce, dans le meilleur des cas, c'est-à-dire lorsque tous les indices ont des noms appropriés et sémantiquement significatifs. Quiconque a déjà fait un `PUT test2/_doc/foo {...}` sait que vos index n'ont pas toujours des noms significatifs.</p><p>Nous disposons donc d'une base de référence, qui montre qu'il y a beaucoup de place pour l'amélioration. Il était temps de faire de la science ! 🧪</p><h2>Expérimentation</h2><h3>Hypothèse 1 : Les cartographies aideront à</h3><p>L'objectif est ici d'identifier un index qui contiendra des données pertinentes pour le message original. La partie d'un index qui décrit le mieux les données qu'il contient est le <em>mappage de</em> l'index. Même sans saisir d'échantillons du contenu de l'index, le fait de savoir que l'index possède un champ prix de type double implique que les données représentent quelque chose à vendre. Un champ auteur de type texte implique des données linguistiques non structurées. L'association des deux pourrait impliquer que les données sont des livres, des histoires ou des poèmes. De nombreux indices sémantiques peuvent être déduits de la seule connaissance des propriétés d'un index. Dans une branche locale, j'ai donc ajusté notre `.index_explorer` pour envoyer les mappings complets d'un index (ainsi que son nom) au LLM afin qu'il prenne sa décision. </p><p>Le résultat (à partir des journaux Kibana) :</p>[2025-09-05T11:01:21.552-05:00][ERROR][plugins.onechat] Error: Error calling connector: event: error
data: {"error":{"code":"request_entity_too_large","message":"Received a content too large status code for request from inference entity id [.rainbow-sprinkles-elastic] status [413]","type":"error"}}


    at createInferenceProviderError (errors.ts:90:10)
    at convertUpstreamError (convert_upstream_error.ts:39:38)
    at handle_connector_response.ts:26:33
    at Observable.init [as _subscribe] (/Users/seanstory/Desktop/Dev/kibana/node_modules/rxjs/src/internal/observable/throwError.ts:123:68)...<p>Les premiers auteurs de l'outil l'avaient prévu. Si le mappage d'un index est une mine d'or d'informations, c'est aussi un bloc de JSON assez verbeux. Et dans un scénario réaliste où vous comparez de nombreux indices (notre ensemble de données d'évaluation en définit 20), ces blobs JSON s'accumulent. Nous voulons donc donner au LLM plus de contexte pour sa décision que de simples noms d'index pour toutes les options, mais pas autant que les mappings complets de chacune d'entre elles.</p><h3>Hypothèse 2 : des correspondances "aplaties" (listes de champs) en guise de compromis</h3><p>Nous sommes partis de l'hypothèse que les créateurs d'index utiliseront des noms d'index sémantiquement significatifs. Et si nous étendions cette hypothèse aux noms des champs ? Notre expérience précédente a échoué parce que le mappage de JSON comprend BEAUCOUP de métadonnées et d'éléments parasites.</p>     "description_text": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword"
            }
          },
          "copy_to": [
            "description_semantic"
          ]
        },<p>Le bloc ci-dessus, par exemple, compte 236 caractères et définit un seul champ dans une correspondance Elasticsearch. Alors que la chaîne "description_text" ne comporte que 16 caractères. Le nombre de caractères a été multiplié par près de 15, sans amélioration sémantique significative de la description de ce que ce champ implique à propos des données disponibles. Que se passerait-il si nous récupérions les correspondances pour tous les indices, mais qu'avant de les envoyer au LLM, nous les "aplatissions" en une simple liste de noms de champs ?</p><p>Nous avons essayé.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta5eda7a79493ee81/6a17f11c9da390327fe46590/112c2f447c11f154b5082725cd49b51d0a3c8a65-1214x804.png" alt="" /><p>C'est formidable ! Des améliorations dans tous les domaines. Mais pourrions-nous faire mieux ?</p><h3>Hypothèse 3 : Descriptions dans le mapping _meta</h3><p>Si le simple fait de nommer les champs sans contexte supplémentaire a provoqué un tel saut, on peut supposer que l'ajout d'un contexte substantiel serait encore plus efficace ! Il n'est pas nécessairement conventionnel que chaque index soit accompagné d'une description, mais il est possible d'ajouter des métadonnées de tout type au niveau de l'index à l'objet _meta de la cartographie. Nous avons repris les index générés et ajouté des descriptions pour chaque index de notre ensemble de données. Tant que les descriptions ne sont pas trop longues, elles devraient utiliser moins de tokens que la cartographie complète et fournir de bien meilleures indications sur les données incluses dans l'index. Notre expérience a validé cette hypothèse.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt61b85cf40e0e6357/6a17f11dfbc5f82809491bbe/32d2692ad4479d0e52d8ee723dcc5710a6ec90f3-1208x806.png" alt="" /><p>Une amélioration modeste, et nous sommes maintenant &gt;90% précis dans tous les domaines.</p><h3>Hypothèse 4 : La somme est plus grande que les parties</h3><p>Les noms de champs ont permis d'améliorer nos résultats. Les descriptions ont permis d'accroître nos résultats. L'utilisation des descriptions ET <em>des </em>noms de champs devrait donc permettre d'obtenir de meilleurs résultats, n'est-ce pas ?</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte6297c6aaf7db802/6a17f11e14d90c1bd779b6e6/114cbb408ff16b136251d2265416bd5270380fe5-1208x794.png" alt="" /><p>Les données ont répondu "non" (pas de changement par rapport à l'expérience précédente). La théorie principale était que, puisque les descriptions ont été générées à partir des champs/mappings de l'index, il n'y a pas assez d'informations différentes entre ces deux éléments de contexte pour ajouter quelque chose de "nouveau" lorsqu'on les combine. En outre, la charge utile que nous envoyons pour nos 20 indices de test devient assez importante. Le raisonnement que nous avons suivi jusqu'à présent n'est pas extensible. En fait, il y a de bonnes raisons de croire qu'aucune des expériences que nous avons menées jusqu'à présent ne fonctionnerait sur des clusters Elasticsearch où il y a des centaines ou des milliers d'indices à choisir. Toute approche qui augmente linéairement la taille du message envoyé au LLM à mesure que le nombre total d'indices augmente n'est probablement pas une stratégie généralisable.</p><p>Ce dont nous avons vraiment besoin, c'est d'une approche qui nous aide à réduire un grand nombre de candidats aux options les plus pertinentes...</p><p>Il s'agit d'un problème de recherche.</p><h3>Hypothèse 5 : Sélection par recherche sémantique</h3><p>Si le nom d'un index a une signification sémantique, il peut être stocké sous forme de vecteur et faire l'objet d'une recherche sémantique.</p><p>Si les noms des champs d'un index ont une signification sémantique, ils peuvent être stockés sous forme de vecteurs et faire l'objet d'une recherche sémantique.</p><p>Si un index possède une description ayant une signification sémantique, il peut lui aussi être stocké sous forme de vecteur et faire l'objet d'une recherche sémantique.</p><p>Aujourd'hui, les index Elasticsearch ne rendent aucune de ces informations consultables (peut-être devrions-nous le faire !), mais il était assez simple de<a href="https://github.com/elastic/connectors/pull/3638"> bricoler quelque chose</a> qui pouvait combler cette lacune. En utilisant le cadre de connecteur d'Elastic, j'ai construit un connecteur qui produirait un document pour chaque index dans un cluster. Les documents de sortie ressembleraient à quelque chose comme :</p> doc = {
                "_id": index_name,
                "index_name": index_name,
			"meta_description”: description,
"field_descriptions" = field_descriptions,
                "mapping": json.dumps(mapping),  
                "source_cluster": self.es_client.configured_host,
            }<p>J'ai envoyé ces documents vers un nouvel index où j'ai défini manuellement le mappage :</p>{
   "mappings": {
       "properties": {
           "semantic_content": {
               "type": "semantic_text"
           },
           "index_name": {
               "type": "text",
               "copy_to": "semantic_content"
           },
           "mapping": {
               "type": "keyword",
               "copy_to": "semantic_content"
           },
           "source_cluster": {
               "type": "keyword"
           },
           "meta_description": {
               "type": "text",
               "copy_to": "semantic_content"
           },
           "field_descriptions": {
               "type": "text",
               "copy_to": "semantic_content"
           }
       }
   }
}<p>Cela crée un champ unique semantic_content, dans lequel tous les autres champs ayant une signification sémantique sont regroupés et indexés. La recherche dans cet index devient triviale, avec simplement :</p>GET indexed-indices/_search
{
 "query": {
   "semantic": {
     "field": "semantic_content",
     "query": "$query"
   }
 }
}<p>L'outil <code>index_explorer</code> modifié est maintenant <em>beaucoup</em> plus rapide, car il n'a pas besoin de faire une demande à un LLM, mais peut demander un seul encastrement pour la requête donnée et effectuer une opération de recherche vectorielle efficace. En prenant le premier hit comme index sélectionné, nous avons obtenu les résultats suivants :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc27c302e6bef0b23/6a17f120577262d2f21bccdc/06ef5d78040d064d3444793f636d527d9e19a869-1214x800.png" alt="" /><p>Cette approche est évolutive. Cette approche est efficace. Mais cette approche est à peine meilleure que notre ligne de base. Ce n'est pas surprenant, car l'approche de la recherche est incroyablement naïve. Il n'y a aucune nuance. Aucune reconnaissance du fait que le nom et la description d'un index devraient avoir plus de poids qu'un nom de champ arbitraire que l'index contient. Pas de possibilité de pondérer les correspondances lexicales exactes par rapport aux correspondances synonymes. Cependant, la construction d'une requête très nuancée nécessiterait de supposer BEAUCOUP de choses sur les données disponibles. Jusqu'à présent, nous avons déjà fait des hypothèses importantes sur la signification sémantique des noms d'index et de champs, mais nous devrions aller plus loin et commencer à supposer la signification <em>qu</em> 'ils ont et la manière dont ils sont liés les uns aux autres. Sans cela, nous ne pouvons probablement pas identifier de manière fiable la meilleure correspondance comme premier résultat, mais nous pouvons plus probablement dire que la meilleure correspondance se trouve quelque part dans les N premiers résultats. Nous avons besoin de quelque chose qui puisse consommer des informations sémantiques dans le contexte dans lequel elles existent, en les comparant à celles d'une autre entité qui peut se représenter d'une manière sémantiquement distincte, et juger entre elles. Comme un LLM.</p><h3>Hypothèse 6 : Réduction du nombre de candidats</h3><p>Il y a eu bien d'autres expériences que je vais passer sous silence, mais la principale avancée a été d'abandonner le désir de choisir la meilleure correspondance uniquement à partir d'une recherche sémantique, et d'utiliser plutôt la recherche sémantique comme un filtre pour éliminer les indices non pertinents de la considération du LLM. Nous avons combiné la recherche linéaire, la recherche hybride avec RRF et <code>semantic_text</code> pour <a href="https://gist.github.com/seanstory/d704443120e20f6c844db10e30066860">notre recherche</a>, en limitant les résultats aux 5 premiers indices correspondants.</p><p>Ensuite, pour chaque correspondance, nous avons ajouté le nom de l'index, la description et les noms des champs à un message pour le LLM. Les résultats ont été fantastiques :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7ac4cb8f7153fdf9/6a17f121af47b66d1dcde082/8fcabd78f591f90d6bc7c0e087d31317e4eef791-1206x804.png" alt="" /><p>La plus grande précision de toutes les expériences réalisées à ce jour ! Et comme cette approche n'augmente pas la taille du message proportionnellement au nombre total d'indices, elle est beaucoup plus évolutive.</p><h2>Résultats</h2><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8d66130d9fae6bea/6a17f123ddf97d7527910c19/04d630797213dbb8bf567da41d1cdd5c7b4586c9-1600x521.png" alt="" /><p>Le premier résultat clair est que notre base de référence <em>peut être</em> améliorée. Cela semble évident rétrospectivement, mais avant le début de l'expérimentation, des discussions sérieuses ont eu lieu sur la question de savoir si nous devions abandonner complètement notre outil <code>index_explorer</code> et nous fier à la configuration explicite de l'utilisateur pour limiter l'espace de recherche. Bien que cela reste une option viable et valable, cette recherche montre qu'il existe des voies prometteuses vers l'automatisation de la sélection de l'indice lorsque les données de l'utilisateur ne sont pas disponibles.</p><p>Le résultat suivant a été que le simple fait d'ajouter des caractères de description au problème a un rendement décroissant. Avant cette recherche, nous nous demandions si nous devions investir dans l'extension de la capacité d'Elasticsearch à stocker des <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/mapping-field-meta">métadonnées au niveau des champs</a>. Aujourd'hui, ces valeurs <code>meta</code> sont plafonnées à 50 caractères, et l'on a supposé qu'il faudrait augmenter cette valeur pour pouvoir obtenir une compréhension sémantique de nos champs. Ce n'est manifestement pas le cas, et le LLM semble s'en sortir assez bien avec des noms de domaines. Nous pourrons approfondir cette question ultérieurement, mais elle ne nous semble plus urgente.</p><p>Inversement, cela a clairement démontré l'importance d'avoir des métadonnées d'index "consultables". Pour ces expériences, nous avons piraté un index des indices. Mais c'est quelque chose que nous pourrions étudier en l'intégrant directement dans Elasticsearch, en créant des API pour le gérer, ou au moins en établissant une convention à ce sujet. Nous allons évaluer nos options et en discuter en interne, alors restez à l'écoute.</p><p>Enfin, cet effort a confirmé l'intérêt de prendre le temps d'expérimenter et de prendre des décisions fondées sur des données. En fait, cela nous a aidés à réaffirmer que notre produit Agent Builder aura besoin de capacités d'évaluation robustes et intégrées au produit. Si nous devons créer un ensemble de tests uniquement pour un outil qui prélève des indices, nos clients auront absolument besoin de moyens pour évaluer qualitativement leurs outils personnalisés au fur et à mesure qu'ils procèdent à des ajustements itératifs.</p><p>Je suis impatient de voir ce que nous allons construire, et j'espère que vous l'êtes aussi !</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/ai-agent-builder-experiments-performance</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/ai-agent-builder-experiments-performance</guid>
    <category><![CDATA[IA agentique]]></category>
    <category><![CDATA[À l'intérieur d'Elastic]]></category>
    <category><![CDATA[Recherche hybride]]></category>
    <dc:creator><![CDATA[Sean Story]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt68d11a4c7fd11d4c/6a17f1257b54f9b6598b39d4/42903c869e034674b30bb36013345aaa97f6608b-1184x864.png" length="0" type="image/png"/>
    <pubDate>Mon, 06 Oct 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Votre premier agent Elastic : D'une simple requête à un chat alimenté par l'IA]]></title>
    <description><![CDATA[Apprenez à utiliser le constructeur d'agents d'IA d'Elastic pour créer des agents d'IA spécialisés. Dans ce blog, nous allons créer un agent d'IA financier.]]></description>
    <content:encoded><![CDATA[<p>Avec le nouvel <a href="https://www.elastic.co/search-labs/blog/ai-agentic-workflows-elastic-ai-agent-builder">Agent Builder</a> d'Elastic, vous pouvez créer des agents d'IA spécialisés qui agissent en tant qu'experts pour vos domaines d'activité spécifiques. Cette fonction vous permet d'aller au-delà des simples tableaux de bord et des barres de recherche, en transformant vos données d'une ressource passive en un partenaire actif et conversationnel.</p><p>Imaginez un gestionnaire financier qui doit se mettre à niveau avant une réunion avec un client. Au lieu de chercher manuellement dans les fils d'actualité et de croiser les tableaux de bord des portefeuilles, ils peuvent désormais simplement poser une question directe à leur agent personnalisé. C'est l'avantage d'une approche "chat-first". Le gestionnaire a un lien direct et conversationnel avec ses données, en posant des questions telles que : "Quelles sont les dernières nouvelles sur ACME Corp et comment cela affecte-t-il les avoirs de mon client ?" et obtenir une réponse synthétisée et experte en quelques secondes.</p><p>Si nous construisons aujourd'hui un expert financier, les applications sont aussi variées que vos données. Le même pouvoir peut créer un analyste en cybersécurité pour traquer les menaces, un ingénieur en fiabilité de site pour diagnostiquer une panne ou un responsable marketing pour optimiser une campagne. Quel que soit le domaine, la mission principale est la même : transformer vos données en un spécialiste avec lequel vous pouvez discuter.</p><h2>Étape 0 : Notre ensemble de données</h2><p>Notre jeu de données du jour est un jeu de données synthétique à dominante financière, composé de comptes, de positions d’actifs, d’actualités économiques et de rapports financiers. Bien qu’il soit artificiel, il reproduit une version simplifiée d’un véritable jeu de données financières.</p><p><code>financial_accounts</code>: Portefeuilles de clients avec profils de risque</p><p><code>financial_holdings</code>: Positions en actions/ETF/obligations avec historique des achats</p><p><code>financial_asset_details</code>: Détails sur l'action/ETF/obligation</p><p><code>financial_news</code>: Articles de marché générés par l'IA avec analyse des sentiments</p><p><code>financial_reports</code>: Résultats de l'entreprise et notes des analystes</p><p>Vous pouvez charger vous-même cet ensemble de données en suivant le cahier d'accompagnement situé <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/your-first-elastic-agent/Your_First_Elastic_Agent.ipynb">ici.</a></p><h2>Étape 1 : La base - Votre logique d'entreprise en tant qu'ES|QL</h2><p>Toute compétence en matière d'IA commence par un solide morceau de logique. Pour notre agent Financial Manager, nous devons lui apprendre à répondre à une question courante : "Je m'inquiète du sentiment du marché. Pouvez-vous me montrer lesquels de nos clients sont les plus exposés aux mauvaises nouvelles ?" Cette question va au-delà d'une simple recherche. Cela nous oblige à établir une corrélation entre le sentiment du marché et les portefeuilles des clients.</p><p>Nous devons trouver les actifs mentionnés dans les articles négatifs, identifier chaque client détenant ces actifs, calculer la valeur de marché actuelle de leur exposition, puis classer les résultats afin d'établir un ordre de priorité pour les risques les plus élevés. Cette analyse complexe et multi-joints est le travail parfait pour notre outil avancé ES|QL.</p><p>Voici la requête complète que nous utiliserons. Il est impressionnant, mais les concepts sont simples.</p><h2>En bref : jonctions et garde-corps</h2><p>Deux concepts importants sont en jeu dans cette requête et font de l'agent un bâtisseur.</p><h3>1. La jointure LOOKUP</h3><p>Depuis des années, l'une des fonctionnalités les plus demandées d'Elasticsearch est la possibilité de joindre des données provenant de différents index sur la base d'une clé commune. Avec ES|QL, c'est désormais possible avec <code>LOOKUP JOIN</code>.</p><p>Dans notre nouvelle requête, nous effectuons une chaîne de trois <code>LOOKUP JOIN</code>: d'abord en reliant les nouvelles négatives aux détails des actifs, ensuite en reliant ces actifs aux avoirs des clients, et enfin en les reliant aux informations sur le compte du client. Cela permet d'obtenir un résultat incroyablement riche à partir de quatre indices différents en une seule requête efficace. Cela signifie que nous pouvons combiner des ensembles de données disparates pour créer une réponse unique et perspicace sans avoir à dénormaliser toutes nos données en un index géant au préalable.</p><h3>2. Les paramètres comme garde-fous du LLM</h3><p>Vous remarquerez que la requête utilise <code>?time_duration</code>. Il ne s'agit pas seulement d'une variable, mais d'un garde-fou pour l'IA. Si les grands modèles de langage (LLM) sont excellents pour générer des requêtes, le fait de leur laisser le champ libre sur vos données peut conduire à des requêtes inefficaces, voire incorrectes.</p><p>En créant une requête paramétrée, nous obligeons le LLM à travailler dans le cadre de la logique commerciale testée, efficace et correcte qu'un expert humain a déjà définie. Il s'agit d'une méthode similaire à celle utilisée par les développeurs depuis des années pour exposer en toute sécurité les capacités de recherche aux applications. L'agent peut interpréter une demande de l'utilisateur comme "cette semaine" pour remplir le paramètre <code>time_duration</code>, mais il doit utiliser notre structure de requête pour obtenir la réponse. Cela nous permet d'obtenir un équilibre parfait entre flexibilité et contrôle.</p><p>En fin de compte, cette requête permet à un expert qui comprend les données d'encapsuler ses connaissances dans un outil. D'autres personnes - et des agents d'intelligence artificielle - peuvent alors utiliser cet outil pour obtenir des résultats corrélés en fournissant simplement un seul paramètre, sans avoir besoin de connaître la complexité sous-jacente.</p><h2>Étape 2 : Les compétences - Transformer une requête en un outil réutilisable</h2><p>Une requête ES|QL n'est que du texte jusqu'à ce que nous l'enregistrions en tant qu'<strong>outil</strong>. Dans l'Agent Builder, un outil est plus qu'une simple requête sauvegardée ; c'est une compétence "" qu'un agent IA peut comprendre et choisir d'utiliser. La magie réside dans la <strong>description en langage naturel</strong> que nous fournissons. Cette description est la passerelle qui relie la question de l'utilisateur à la logique d'interrogation sous-jacente. Enregistrons la requête que nous venons de construire.</p><h3>Le chemin de l'interface utilisateur</h3><p>La création d'un outil dans Kibana est un processus simple.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte73e11c1d87593fa/6a17f2134202294dae29f6f2/a29c53a73b99af5972273c51218ea9004a9b0abb-1600x812.png" alt="Comment créer un outil dans Kibana." /><p>1. Naviguer vers <strong>Agents</strong></p><ul><li><p>Cliquez sur<strong> Outils </strong>ou <strong>Gérer les outils</strong> et cliquez sur le bouton <strong>Nouvel outil.</strong></p></li></ul><p>2. Remplissez le formulaire avec les informations suivantes :</p><ul><li><p><strong>ID de l'outil :</strong> <code>find_client_exposure_to_negative_news</code></p></li></ul><p>             i. Il s'agit de l'identifiant unique de l'outil</p><ul><li><p><strong>Description :</strong> "Détermine l'exposition du portefeuille du client aux nouvelles négatives. Cet outil analyse les nouvelles et les rapports récents pour y déceler un sentiment négatif, identifie l'actif associé et trouve tous les clients qui détiennent cet actif. Il renvoie une liste triée en fonction de la valeur de marché actuelle du poste afin de mettre en évidence le risque potentiel le plus élevé."</p></li></ul><p>             i. C'est ce que le LLM lit pour décider si cet outil est le bon pour le poste.</p><ul><li><p><strong>Étiquettes</strong>: <code>retrieval</code> et <code>risk-analysis</code></p></li></ul><p>         Les étiquettes sont utilisées pour regrouper plusieurs outils</p><ul><li><p><strong>Configuration :</strong> Coller la requête ES|QL complète de l'étape 1</p></li></ul><p>            i. Voici la recherche que l'agent utilisera</p><p>3. Cliquez sur <strong>Inférer les paramètres de la requête</strong>. L'interface utilisateur trouvera automatiquement le site <code>?time_duration</code>, dont la liste figure ci-dessous. Ajoutez une description simple pour chacun d'entre eux afin d'aider l'agent (et les autres utilisateurs) à comprendre leur fonction.</p><ul><li><p><code>time_duration</code>: Le délai pour rechercher des nouvelles négatives. Le format est le suivant : "X heures" DEFAUT 8760 heures</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7afbb0589c1828ad/6a17f2146864a44e7cb688a9/deb422d97863f78dbe08bfa2e3c708d1f75166ff-1600x938.png" alt="Configurer votre outil, y compris sa logique et tous les paramètres nécessaires, à l'aide d'une requête ESQL. " /><p>4. Testez-le !</p><ul><li><p>Cliquez sur Save &amp; test.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfd09afbef6e21a93/6a17f2162f4a5c73b1fa89fd/57e768b88327821e70bd616744822f98fa367362-732x136.png" alt="Le même bouton de test &amp; dans Kibana." /><ul><li><p>Une nouvelle fenêtre s'ouvre, dans laquelle vous pouvez tester la requête pour vous assurer qu'elle fonctionne comme prévu.</p></li></ul><p>             i. Dans <code>time_duration</code>, entrez la plage souhaitée, ici nous utilisons "8760 heures"</p><ul><li><p>Cliquez sur "Submit" et si tout se passe bien, vous verrez une réponse JSON. Pour vous assurer qu'il fonctionne comme prévu, faites défiler la page vers le bas et regardez l'objet <code>values</code>. C'est là que les documents correspondants sont renvoyés.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt89bdc3f093363f2a/6a17f217be60861c9c00488a/7e0c5171a4f7ffdfc1830f1a05a9acb987870b75-1600x722.png" alt="Réponse JSON qui apparaît après avoir cliqué sur soumettre." /><p>5. Cliquez sur le "X" en haut à droite pour fermer la fenêtre de test. Votre nouvel outil apparaît alors dans la liste, prêt à être attribué à un agent.</p><h3>Le chemin de l'API</h3><p>Pour les développeurs qui préfèrent l'automatisation ou qui ont besoin de gérer des outils par programme, vous pouvez obtenir le même résultat avec un seul appel d'API. Il suffit d'envoyer une demande <code>POST</code> au point de terminaison <code>/api/agent_builder/tools</code> avec la définition de l'outil.</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>Étape 3 : Les cerveaux - Créer votre agent personnalisé</h2><p>Nous avons créé une compétence réutilisable (l'outil). Nous devons maintenant créer l'<strong>agent</strong>, la personne qui l'utilisera réellement. Un agent est la combinaison d'un MLD, d'un ensemble spécifique d'outils auxquels vous lui donnez accès et, surtout, d'un ensemble d'<strong>instructions personnalisées</strong> qui agissent comme sa constitution, définissant sa personnalité, ses règles et son objectif.</p><h3>L'art de la proposition</h3><p>L'élément le plus important pour créer un agent fiable et spécialisé est la rapidité. Un ensemble d'instructions bien conçues fait la différence entre un chatbot générique et un assistant professionnel ciblé. C'est là que vous fixez les garde-fous, définissez les résultats et donnez à l'agent sa mission.</p><p>Pour notre agent <code>Financial Manager</code>, nous utiliserons l'invite suivante.</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>Voyons pourquoi cette incitation est si efficace :</p><ul><li><p><strong>Elle définit une personnalité sophistiquée : </strong>La première ligne établit immédiatement que l'agent est un assistant spécialisé en intelligence des données ( "),", ce qui donne un ton professionnel et compétent.</p></li><li><p><strong>Il fournit un cadre de raisonnement : </strong>En disant à l'agent de "Comprendre, Planifier, Exécuter et Synthétiser," nous lui donnons une procédure opérationnelle standard. Cela améliore sa capacité à traiter des questions complexes et à plusieurs étapes.</p></li><li><p><strong>Il favorise le dialogue interactif : </strong>L'instruction de "poser des questions de clarification" rend l'agent plus robuste. Il minimisera les hypothèses erronées sur les demandes ambiguës, ce qui permettra d'obtenir des réponses plus précises.</p></li></ul><h3>Le chemin de l'interface utilisateur</h3><p>1. Naviguez vers <strong>Agents.</strong></p><ul><li><p>Cliquez sur<strong> Outils </strong>ou <strong>Gérer les outils</strong> et cliquez sur le bouton <strong>Nouvel outil.</strong></p></li></ul><p>2. Complétez les informations de base :</p><ul><li><p><strong>ID de l'agent :</strong> <code>financial_assistant</code>.</p></li><li><p><strong>Instructions : </strong>Copiez le message ci-dessus.</p></li><li><p><strong>Étiquettes</strong>: <code>Finance</code>.</p></li><li><p><strong>Nom d'affichage :</strong> <code>Financial Assistant</code>.</p></li><li><p><strong>Description de l'affichage : </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="Création d'un assistant financier - remplir le champ ID de l'agent." /><p>3. De retour en haut, cliquez sur <strong>Outils.</strong></p><ul><li><p>Cochez la case à côté de notre outil <code>find_client_exposure_to_negative_news</code>.</p></li></ul><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcd23556e556a76c5/6a17f21baf47b63a9fcde0a0/0c1e4ecbbd51d0dd10c6e861dbe9a9ccddeb35f6-1600x149.png" alt="" /><p>4. Cliquez sur <strong>Enregistrer</strong>.</p><h3>Le chemin de l'API</h3><p>Vous pouvez créer exactement le même agent à l'aide d'une requête <code>POST</code> vers le point de terminaison <code>/api/agent_builder/agents</code>. Le corps de la demande contient toutes les mêmes informations : l'identifiant, le nom, la description, l'ensemble des instructions et une liste des outils que l'agent est autorisé à utiliser.</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>Étape 4 : La récompense - Avoir une conversation</h2><p>Notre logique d'entreprise est encapsulée dans un outil et un cerveau "" est prêt à l'utiliser dans notre agent. Il est temps de voir tout cela se concrétiser. Nous pouvons maintenant commencer à discuter avec nos données à l'aide d'un agent spécialisé.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd8826539b16e46f4/6a17f21d505ac35924ad8c5c/5414cb6b7c41365acb0356a8bfe1140751ffd8db-1600x1014.png" alt="Conversation avec l'Elastic Agent Builder après la création d'un assistant financier." /><h3>Le chemin de l'interface utilisateur</h3><ol><li><p>Naviguez jusqu'à <strong>Agents </strong>dans Kibana.</p></li><li><p>En utilisant le menu déroulant en bas à droite de la fenêtre de chat, passez de l'<strong>agent Elastic AI</strong> par défaut à l'agent <strong>Financial Assistant </strong>que nous venons de créer.</p></li><li><p>Posez une question qui permettra à l'agent d'utiliser notre outil spécialisé :</p><ol><li><p><em>Je m'inquiète du sentiment du marché. Pouvez-vous m'indiquer quels sont nos clients les plus exposés aux mauvaises nouvelles ?</em></p></li></ol></li></ol><p>Après quelques instants, l'agent vous renvoie une réponse parfaitement formatée et complète. En raison de la nature des LLM, votre réponse peut être formatée légèrement différemment, mais pour cette exécution, l'agent a renvoyé :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blta1e163fd7c4416bd/6a17f21f6864a4e35bb688ad/17b4ed43d279f9e53ee9fe3d482d0b2ec359a083-1600x1088.png" alt="Une réponse créée par l'Elastic Agent Builder en tant qu'assistant financier pour : les clients les plus exposés aux nouvelles négatives." /><h3>Que s'est-il passé ? Le raisonnement de l'agent</h3><p>L'agent ne s'est pas contenté de "savoir" la réponse. Elle a exécuté un plan en plusieurs étapes centré sur la sélection du meilleur outil pour le travail. Voici un aperçu de son processus de réflexion :</p><ul><li><p><strong>L'intention a été identifiée :</strong> Il a fait correspondre des mots clés de votre question, comme "risk" et "negative news," à la description de l'outil <code>find_client_exposure_to_negative_news</code>.</p></li><li><p><strong>Exécution d'un plan :</strong> Il a extrait le délai de votre demande et a lancé un <strong>appel unique à</strong> cet outil spécialisé.</p></li><li><p><strong>Délégation du travail :</strong> L'outil a ensuite effectué toutes les opérations lourdes : les jointures enchaînées, les calculs de valeur et le tri.</p></li><li><p><strong>Synthèse du résultat :</strong> Enfin, l'agent a formaté les données brutes de l'outil en un résumé clair et lisible par l'homme, en suivant les règles de l'invite.</p></li></ul><p>Et nous ne sommes pas obligés de deviner, si nous élargissons notre réflexion et voyons plus de détails.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt93f6075be8495418/6a17f221af47b65eadcde0a4/6a4da9262d3f88c60bfd8f8bf9b67c3b84e961ba-1600x607.png" alt="Les 50 documents que l'assistant financier a trouvés auprès des clients les plus exposés aux nouvelles négatives." /><h3>Le chemin de l'API</h3><p>Vous pouvez entamer cette même conversation par le biais d'un programme. Il suffit d'envoyer la question d'entrée au point de terminaison de l'API <code>converse</code>, en veillant à spécifier le <code>agent_id</code> de notre <code>financial_manager</code>.</p>POST kbn://api/agent_builder/converse
{
  "input": "Show me our largest positions affected by negative news",
  "agent_id": "financial_assistant"
}<h2>Pour les développeurs : Intégrer l'API</h2><p>Si l'interface Kibana offre une expérience fantastique et intuitive pour la création et la gestion de vos agents, tout ce que vous avez vu aujourd'hui peut également être réalisé de manière programmatique. L'Agent Builder est construit sur un ensemble d'API, vous permettant d'intégrer cette fonctionnalité directement dans vos propres applications, pipelines CI/CD ou scripts d'automatisation.</p><p>Les trois principaux points d'aboutissement avec lesquels vous travaillerez sont les suivants :</p><ul><li><p><strong><code>/api/agent_builder/tools</code></strong>: Le point final pour créer, lister et gérer les compétences réutilisables que vos agents peuvent utiliser.</p></li><li><p><strong><code>/api/agent_builder/agents</code></strong>: Le point final pour la définition de vos personas d'agents, y compris leurs instructions très importantes et l'affectation des outils.</p></li><li><p><strong><code>/api/agent_builder/converse</code></strong>: Le point final pour interagir avec vos agents, entamer des conversations et obtenir des réponses.</p></li></ul><p>Pour une démonstration complète et pratique de l'utilisation de ces API pour réaliser chaque étape de ce tutoriel, consultez le <strong>bloc-notes Jupyter</strong> qui l'accompagne, disponible <a href="https://github.com/elastic/elasticsearch-labs/blob/main/supporting-blog-content/your-first-elastic-agent/Your_First_Elastic_Agent.ipynb">ici</a> dans notre dépôt GitHub.</p><h2>Conclusion : À vous de construire</h2><p>Nous avons commencé par prendre une requête ES|QL et la transformer en une compétence réutilisable. Nous avons ensuite créé un agent d'intelligence artificielle spécialisé, en lui donnant une mission et des règles claires, et nous l'avons doté de cette compétence. Il en résulte un assistant sophistiqué capable de comprendre une question complexe et d'exécuter une analyse en plusieurs étapes pour fournir une réponse précise et fondée sur des données.</p><p>Ce flux de travail est au cœur du nouvel <strong>Agent Builder d'</strong> Elastic. Il est conçu pour être suffisamment simple pour que les utilisateurs non techniques puissent créer des agents via l'interface utilisateur, mais suffisamment nuancé pour que les développeurs puissent créer des applications personnalisées basées sur l'IA à partir de nos API. Plus important encore, il vous permet de connecter en toute sécurité des LLM à vos propres données, régies par la logique experte que vous définissez, et de discuter avec vos données.</p><h2>Prêt à utiliser des agents pour dialoguer avec vos données ?</h2><p>La meilleure façon de consolider ce que vous avez appris est de vous salir les mains. Essayez tout ce que nous avons discuté aujourd'hui dans notre <a href="https://www.elastic.co/training/elastic-ai-agents-mcp"><strong>atelier pratique interactif et gratuit</strong></a>. Vous suivrez l'ensemble de ce processus et bien d'autres choses encore dans un environnement de type "bac à sable".</p><p>Dans un prochain blog, nous vous montrerons comment utiliser une application autonome qui interagit avec notre agent <code>Financial Assistant</code> et nous nous pencherons sur le <strong>protocole de contexte de modèle (MCP)</strong> qui rend tout cela possible. Dans un autre blog, nous parlerons de la prise en charge par Agent Builder du protocole Agent2Agent, ou A2A, en cours de développement.</p><p>Restez à l'écoute et bonne construction !</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[IA]]></category>
    <category><![CDATA[IA agentique]]></category>
    <category><![CDATA[À l'intérieur d'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[Construire des flux de travail d'IA agentique avec Elasticsearch]]></title>
    <description><![CDATA[Découvrez Agent Builder, une nouvelle couche d'IA dans Elasticsearch qui fournit un cadre pour construire des flux de travail d'IA agentique, en utilisant la recherche hybride pour fournir aux agents le contexte dont ils ont besoin pour raisonner et agir.]]></description>
    <content:encoded><![CDATA[<p>Chez Elastic, nous avons apporté du contexte aux LLM et aux interfaces conversationnelles avec des assistants IA, des RAG avancés et des améliorations de la base de données vectorielle. Récemment, avec l'essor des agents d'intelligence artificielle, nous avons constaté que le besoin d'un contexte pertinent augmentait, et nous avons appris que<strong> les agents d'intelligence artificielle</strong> à fort impact ont besoin d'une recherche de qualité. Nous avons donc créé de nouvelles capacités natives dans la pile Elastic, conçues pour aider à développer des agents d'IA qui exploitent vos données dans Elasticsearch. Nous aimerions vous faire part de nos progrès dans ce domaine et de la direction que nous envisageons pour l'avenir.</p><h2>Agent Builder : Une base pour la construction d'agents d'intelligence artificielle pilotés par les données</h2><p>La promesse d'un agent d'intelligence artificielle est simple : donnez-lui un objectif et il fera le travail. Mais pour les développeurs, la réalité est une série de défis complexes. Tout d'abord, la qualité d'un agent dépend de sa perception de l'environnement et des outils qui lui sont fournis pour atteindre les objectifs de l'utilisateur. Par ailleurs, fournir le bon contexte à partir d'une mer de données d'entreprise diverses constitue un défi de taille. Enfin, tout cela doit être orchestré par une boucle de raisonnement fiable capable de planifier, d'exécuter et d'apprendre.</p><p>Pour résoudre ce problème, les développeurs doivent construire une pile complexe et fragile à partir de zéro. L'architecture actuelle des agents vous oblige à assembler plusieurs éléments disparates : un LLM, une base de données vectorielle, un magasin de métadonnées, des systèmes distincts pour la journalisation et la traçabilité, et un moyen d'évaluer si tout cela fonctionne. Ce n'est pas seulement complexe, c'est aussi coûteux, source d'erreurs, et cela rend difficile l'élaboration des systèmes d'IA de haute qualité et dignes de confiance que vos utilisateurs exigent.</p><p>Nous voulons donc simplifier les choses. Pour ce faire, notre approche consiste à prendre les éléments essentiels d'un agent contextuel efficace et à les intégrer directement au cœur d'Elasticsearch grâce à un nouvel ensemble de fonctionnalités appelé <strong>Elastic AI Agent Builder</strong>. Cette nouvelle couche fournit un cadre avec tous les éléments essentiels pour créer des agents d'intelligence artificielle alimentés par Elasticsearch : un ensemble ouvert de primitives, des protocoles basés sur des normes et un accès sécurisé aux données - afin que vous puissiez construire des systèmes agentiques adaptés aux données et aux exigences du monde réel :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2779dae5df010328/6a17e15eabe0f24f18dfe931/1ee1e73dd3f485ce86294d39490c98ce2a3d9925-1238x1072.png" alt="" /><p><strong>Offrir des expériences d'IA</strong>: c'est l'objectif ultime. Avec notre Search AI Platform et vos données comme base, vous pouvez créer n'importe quel type d'application d'IA générative : des interfaces de chat personnalisées aux intégrations avec des frameworks agentiques comme LangChain ou des applications d'entreprise comme Salesforce.</p><p><strong>Exploité par des agents &amp; Tools</strong>: au-dessus de la plateforme, nous exposons une couche d'abstractions propre et simple. Vous interagissez directement avec les agents et les outils, que vous pouvez personnaliser pour répondre à vos besoins spécifiques. Vous pouvez également accéder aux capacités de la plateforme par le biais d'API robustes et de normes ouvertes telles que MCP et A2A.</p><p><strong>La Search AI Platform</strong>: il s'agit du moteur de base dans lequel nous avons intégré les composants. La base de données vectorielle avancée, la logique de l'agent, la construction des requêtes, les caractéristiques de sécurité, le traçage pour l'évaluation, tout cela vit ici, géré et optimisé par Elastic.</p><p><strong>Libérer la puissance de vos données</strong>: la base de tout grand agent est constituée de données de qualité. Notre plateforme commence par la capacité d'ingérer ou de fédérer l'accès à toutes les données de votre entreprise.</p><h2>Création d'agents dans la plate-forme</h2><p>Agent Builder, intégré à la Search AI Platform, fournit un cadre complet pour le développement d'agents. Il repose sur cinq piliers clés, chacun d'entre eux étant conçu pour traiter un aspect essentiel de la construction et du déploiement de systèmes d'IA de niveau de production. Voyons comment les agents définissent l'objectif, les outils fournissent les capacités, les normes ouvertes garantissent l'interopérabilité, l'évaluation assure la transparence et la sécurité assure la confiance.</p><h3>Agents</h3><p>Les agents sont le plus haut niveau de construction de cette nouvelle couche d'Elasticsearch. Un agent définit l'objectif à atteindre, l'ensemble des outils disponibles pour l'exécution et les sources de données sur lesquelles il peut agir. Les agents ne se limitent pas aux interactions conversationnelles ; ils peuvent alimenter des flux de travail complets, l'automatisation des tâches ou des expériences face à l'utilisateur.</p><p>Lorsqu'une demande est adressée à un agent, elle suit un cycle structuré :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt774ffd7df65bd01d/6a17e15f25daabd5cc08a17f/627ad1744b629bbe27359325702f40d97e40d1f4-704x852.png" alt="" /><ol><li><p>Interpréter votre contribution et votre objectif</p></li><li><p>Sélectionner l'outil et les arguments adéquats pour l'exécution</p></li><li><p>Raisonner sur la réponse de l'outil</p></li><li><p>Décider si l'on renvoie un résultat ou si l'on poursuit les invocations d'outils.</p></li></ol><p>Elastic se charge de l'orchestration, du contexte et de l'exécution de ce cycle. Les développeurs se concentrent sur la définition de <em>ce que</em> l'agent doit faire : objectifs, outils et données, tandis que le système gère la <em>manière dont</em> le raisonnement et les flux de travail sont exécutés.</p><p><em>L'agent par défaut</em></p><p>Notre premier agent construit sur cette plateforme est un agent conversationnel natif dans Kibana, vous donnant la possibilité d'interagir immédiatement avec vos données. Il offre une expérience prête à l'emploi tout en restant totalement extensible et permet de commencer à interagir avec vos données immédiatement, sans configuration supplémentaire.</p><p>Vous pouvez interagir avec cette expérience directement dans Kibana par le biais d'une nouvelle expérience utilisateur de chat ou par le biais de l'API.</p><p>L'interrogation de l'agent par défaut via l'API ne nécessite qu'un seul appel :</p>POST kbn://api/agent_builder/converse
{
    "input": "what is our top portfolio account?"
}<p>Comme les conversations ont un état, vous pouvez continuer à interagir avec un agent à l'aide d'un numéro d'identification de la conversation ou récupérer l'historique complet de la conversation :</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>Agents des douanes</em></p><p>Les développeurs peuvent également créer leurs propres agents personnalisés grâce à des API simples. Les agents encapsulent les instructions, les outils et l'accès aux données, créant ainsi des moteurs de raisonnement sur mesure.</p><p>La création d'un agent personnalisé est aussi simple qu'un simple appel à l'API. L'exemple ci-dessous montre un exemple, le champ "configuration" contient tous les détails clés, tels que les instructions ou les outils disponibles :</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>Une fois créé, l'agent peut être interrogé directement :</p>POST kbn://api/agent_builder/converse
{
    "input": "What news about DIA?",
    "agent_id": "custom_agent"
}<p>Cette approche transforme l'agent d'un système complexe à construire de toutes pièces en une unité simple et déclarative de logique d'entreprise, ce qui vous permet de mettre en place plus rapidement une automatisation intelligente.</p><p>Pour savoir comment créer un agent spécialisé à partir de zéro, consultez notre guide détaillé, étape par étape : <a href="https://www.elastic.co/search-labs/blog/ai-agent-builder-elasticsearch">Votre premier agent Elastic : D'une simple requête à un chat alimenté par l'IA</a>.</p><h3>Outils</h3><p>Si les agents définissent <em>ce qu'il</em> faut accomplir, les outils définissent <em>comment.</em></p><p>Les outils exposent les capacités spécifiques du noyau Elastic pour que les agents puissent exécuter et récupérer des informations ou effectuer une action. Les outils peuvent inclure des fonctionnalités de base telles que l'obtention d'index ou de mappages, ou des fonctionnalités plus avancées telles que le langage naturel pour ES|QL.</p><p>Elasticsearch est livré avec un ensemble d'outils par défaut optimisés pour les besoins courants. Mais la véritable flexibilité réside dans la création de votre propre système. En définissant les outils, vous décidez exactement quelles requêtes, quels index et quels champs sont exposés à un agent avec ES|QL, ce qui vous permet de contrôler précisément la vitesse, la précision et la sécurité.</p><p>L'enregistrement d'un nouvel outil est aussi simple qu'un simple appel à l'API. Vous pouvez créer un outil qui exploite notre <a href="https://www.elastic.co/search-labs/blog/esql-timeline-of-improvements">ES|QL (Elasticsearch Query Language)</a> pour trouver des informations sur un actif financier spécifique :</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>Une fois enregistré, vous pouvez attribuer le nouvel outil à vos agents personnalisés, en leur donnant un ensemble de capacités à raisonner et à invoquer chaque fois que cela est nécessaire.</p><p>Nous fournissons une plateforme pour créer des outils personnalisés pour vos besoins spécifiques, par exemple avec ES|QL qui transforme l'agent polyvalent en un expert spécifique à un domaine, fondé sur vos données uniques et votre domaine d'activité.</p><h3>Normes ouvertes et interopérabilité</h3><p>Les agents et outils Elasticsearch sont exposés via des API standard ouvertes, ce qui facilite leur intégration en tant que blocs fondamentaux dans l'écosystème plus large des cadres agentiques. Notre approche est simple : pas de boîte noire. Nous voulons que vous puissiez prendre la force principale d'Elastic en matière de recherche et l'associer à des capacités complémentaires et à d'autres systèmes agentiques.</p><p>Pour rendre cela possible, nous exposons nos capacités par le biais d'API, de protocoles émergents et de normes ouvertes.</p><p><em>Protocole de contexte de modèle (MCP)</em></p><p>Le <a href="https://www.elastic.co/search-labs/blog/model-context-protocol-elasticsearch">protocole MCP (Model Context Protocol)</a> est en passe de devenir la norme ouverte pour la connexion des outils entre les systèmes. En prenant en charge MCP, Elasticsearch peut connecter l'IA conversationnelle à vos bases de données, indices et API externes. Avec un serveur MCP distant intégré à la pile Elastic, tout client compatible MCP peut accéder aux outils d'Elastic et les utiliser comme éléments de construction dans vos flux de travail agentiques plus vastes.</p><p>Il ne s'agit pas d'une voie à sens unique. Vous pourrez également importer des outils à partir de serveurs MCP externes et les rendre disponibles dans Elasticsearch. Bientôt, les serveurs MCP seront probablement disponibles pour presque tout et seront bien plus complets que tout ce que nous pourrions créer nous-mêmes. Elastic fournit des fonctions de recherche et d'extraction à grande échelle, et vous pouvez les combiner avec des capacités spécialisées d'autres plateformes pour créer des agents efficaces.</p><p><em>Agent à agent (A2A)</em></p><p>Nous travaillons également sur la prise en charge des services d'agent à agent (A2A). Alors que le MCP concerne la connexion des outils, l'A2A concerne la connexion des agents. Avec un serveur A2A, les agents Elastic que vous créez pourront dialoguer directement avec des agents d'autres systèmes : partage de contexte, délégation de tâches et coordination de flux de travail.</p><p>Il s'agit d'une interopérabilité au niveau du raisonnement. Votre agent Elastic pourrait se charger de la recherche et de l'extraction, puis confier une tâche à un agent spécialisé dans l'assistance ou les technologies de l'information, et recevoir le résultat en retour de manière transparente. Il en résulte un écosystème d'agents coopérants, chacun faisant ce qu'il fait le mieux.</p><p>En fin de compte, l'adoption de MCP et d'A2A renforce notre engagement en faveur du rôle d'Elasticsearch en tant que citoyen de première classe, garantissant une intégration ouverte dans l'ensemble de l'écosystème agentique.</p><h3>Recherche et évaluation</h3><p>Au fur et à mesure que la recherche s'intègre aux agents, le défi d'une évaluation efficace devient crucial. Pour déployer en toute confiance des agents dans des environnements d'entreprise réels, vous devez avoir l'assurance qu'ils sont non seulement précis, mais aussi efficaces et fiables. Comment mesurer les performances, diagnostiquer une mauvaise réponse ou améliorer la situation de départ ? Tout commence par la visibilité.</p><p>C'est pourquoi nous avons conçu nos API pour la transparence dès le départ. Prenons l'exemple d'une simple interaction avec un agent :</p>POST kbn://api/agent_builder/converse
{
    "input": "what is our top portfolio account?"
}<p>La réponse comprend non seulement la réponse finale, mais aussi la trace complète de l'exécution, détaillant les outils sélectionnés par l'agent, les paramètres utilisés et les résultats de chaque étape.</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>Une traçabilité et une journalisation complètes sont essentielles pour une boucle d'amélioration continue, et bientôt, vous pourrez stocker et visualiser ces traces d'agents directement dans Elasticsearch. Mieux encore, ces traces sont construites sur le protocole OpenTelemetry, ce qui garantit qu'elles sont normalisées et portables pour l'intégration avec la plateforme d'observabilité de votre choix.</p><p>Ce niveau de détail est la base d'une véritable boucle d'amélioration continue. Il vous permet d'élaborer une suite complète de tests, de déboguer les échecs, d'identifier les modes de défaillance afin d'éviter les régressions et de capturer les modèles de réussite afin d'affiner les performances. En fin de compte, cette approche fondée sur les données est la clé de la transformation d'un prototype prometteur en un système d'IA fiable de qualité industrielle.</p><h3>Security</h3><p>Au fur et à mesure que les agents et les outils deviennent plus performants, la sécurité n'est plus facultative, elle est fondamentale. L'exposition des API, l'automatisation des tâches et des flux de travail exigent que les systèmes d'entreprise soient fiables. D'autant plus que les agents commencent à automatiser de plus en plus de flux de travail. Il est donc essentiel de pouvoir sécuriser ces flux et de s'assurer qu'ils répondent aux exigences de l'entreprise.</p><p>Les capacités ci-dessus héritent toutes des contrôles déjà disponibles dans Elastic aujourd'hui, y compris le <a href="https://www.elastic.co/search-labs/blog/rag-and-rbac-integration">contrôle d'accès basé sur les rôles (RBAC)</a> pour les appels d'API et la gestion des clés d'API. Nous étendons également les mêmes contrôles à de nouveaux protocoles tels que le MCP. Cela signifie la prise en charge de normes telles que OAuth, ainsi que la possibilité d'intégrer des mécanismes d'authentification personnalisés.</p><p>Notre objectif est de vous donner la flexibilité nécessaire pour expérimenter des agents et des outils, tout en maintenant le niveau de sécurité, de conformité et de gouvernance exigé par votre organisation.</p><h2>Ce qui vient ensuite</h2><p>Nous ne nous contentons pas d'ajouter des fonctionnalités, nous développons Elasticsearch pour l'ingénierie contextuelle agentique. Nous prévoyons de poursuivre notre développement sur la base de ces principes :</p><p>1. Engagement en faveur des normes Open Source &amp;</p><p>Notre engagement en faveur de l'open source et des normes ouvertes garantit que ces capacités restent interopérables avec les cadres agentiques externes. Vous serez toujours en mesure de connecter, d'étendre et de composer des agents à travers votre écosystème tout en gardant le contrôle de vos données et de vos flux de travail.</p><p>2. Valeur du contexte</p><p>Le contexte d'un agent d'intelligence artificielle est son plus grand atout. La gestion du contexte lorsque les agents effectuent des recherches et des opérations de flux de travail peut être une tâche difficile. Nous nous appuyons sur les points forts d'Elastic pour résoudre les problèmes d'ingénierie contextuelle, en veillant à ce que les informations les plus pertinentes soient toujours disponibles pour votre agent.</p><p>3. Focus sur les flux de données agentiques</p><p>À l'avenir, les agents constitueront une source de données de plus en plus importante, y compris les résultats des agents (documents générés, rapports, visualisations) et les traces d'exécution des agents (leur raisonnement, les appels d'outils, la mémoire/le contexte). Elastic est bien adapté au traitement de ce type de données, et nous travaillons sur la recherche concernant l'analyse, l'évaluation et l'amélioration automatisée de ces données.</p><p>4. Sécurité et sûreté dès la conception</p><p>Les agents d'intelligence artificielle posent de nouveaux défis en matière de sécurité et de sûreté. Elastic a toujours été un leader en matière de solutions sécurisées, et nous continuons à intégrer des garde-fous de niveau entreprise, des contrôles d'accès et les principes "zero-trust".</p><p>5. Intégré dans la plate-forme</p><p>Les capacités de création d'agents d'intelligence artificielle sont intégrées dans la plateforme Elasticsearch. Cela signifie que les capacités au niveau de la plateforme, telles que le traçage, l'évaluation, la visualisation et l'analyse, sont toutes applicables aux agents. Vous souhaitez développer des tableaux de bord basés sur les exécutions des agents - c'est intégré. Vous souhaitez évaluer les performances de l'agent d'IA à l'aide d'une analyse des sentiments - la plateforme le permet. Cela permet de construire un cycle de vie complet autour de vos expériences d'IA.</p><p>L'objectif d'Elastic est de vous donner les interfaces pour construire une IA conversationnelle et des flux de travail automatisés qui sont entièrement intégrés, extensibles et ancrés dans vos données. De plus amples détails techniques et des informations sur les progrès réalisés seront bientôt communiqués.</p><p>Agent Builder est disponible dès à présent en version privée. <a href="https://www.elastic.co/contact?pg=global&amp;plcmt=nav&amp;cta=205352">Connectez-vous avec nous</a> pour demander l'accès. Vous avez des questions ou des commentaires ? Connectez-vous avec notre communauté de développeurs dans notre <a href="https://elasticstack.slack.com/archives/C09GRHEQ4AG"><strong>espace de travail Slack</strong></a> ou sur notre <a href="https://discuss.elastic.co/c/search/84"><strong>forum de discussion.</strong></a></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[IA]]></category>
    <category><![CDATA[IA agentique]]></category>
    <category><![CDATA[À l'intérieur d'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[Filtrage de la recherche vectorielle : Garder la pertinence]]></title>
    <description><![CDATA[Il ne suffit pas d'effectuer une recherche vectorielle pour trouver les résultats les plus similaires à une requête. Le filtrage est souvent nécessaire pour réduire les résultats de la recherche. Cet article explique comment fonctionne le filtrage pour la recherche vectorielle dans Elasticsearch et Apache Lucene.]]></description>
    <content:encoded><![CDATA[<p>La recherche vectorielle ne suffit pas pour trouver des résultats pertinents. Il est très courant d'utiliser des critères de filtrage qui permettent de réduire les résultats de la recherche et d'éliminer les résultats non pertinents.</p><p>Comprendre le fonctionnement du filtrage dans la recherche vectorielle vous aidera à équilibrer les compromis entre performance et rappel, et à découvrir certaines des optimisations utilisées pour rendre la recherche vectorielle plus performante lorsque le filtrage est utilisé.</p><h2>Pourquoi le filtrage ?</h2><p>La recherche vectorielle a révolutionné la manière dont nous trouvons des informations pertinentes dans de grands ensembles de données, en nous permettant de découvrir des éléments sémantiquement similaires à une requête.</p><p>Toutefois, il ne suffit pas de trouver des articles similaires. Nous devons souvent réduire les résultats de la recherche en fonction de critères ou d'attributs spécifiques.</p><p>Imaginez que vous recherchiez un produit dans un magasin de commerce électronique. Une recherche purement vectorielle peut vous montrer des articles visuellement similaires, mais vous pouvez aussi vouloir filtrer par fourchette de prix, marque, disponibilité ou évaluations des clients. Sans filtrage, vous seriez confronté à un vaste éventail de produits similaires, ce qui rendrait difficile de trouver exactement ce que vous cherchez.</p><p>Le filtrage permet un contrôle précis des résultats de la recherche, garantissant que les éléments récupérés ne sont pas seulement alignés sur le plan sémantique, mais qu'ils répondent également à toutes les exigences nécessaires. L'expérience de recherche est ainsi beaucoup plus précise, efficace et conviviale.</p><p>C'est là qu'Elasticsearch et Apache Lucene excellent - l'utilisation d'un filtrage efficace sur différents types de données est l'une des principales différences avec les autres bases de données vectorielles.</p><h2>Filtrage pour la recherche vectorielle exacte</h2><p>Il existe deux manières principales d'effectuer des recherches de vecteurs exacts :</p><ul><li><p>Utilisation d'un type d'index <code>flat</code> pour votre champ dense_vector. Ainsi, les recherches sur <code>knn</code> utilisent la recherche exacte au lieu de la recherche approximative.</p></li><li><p>Utilisation d'une <a href="https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-script-score-query#vector-functions">requête script_score</a> qui utilise des fonctions vectorielles pour calculer le score. Ceci peut être utilisé avec n'importe quel type d'index.</p></li></ul><p>Lors de l'exécution d'une recherche vectorielle exacte, tous les vecteurs sont comparés à la requête. Dans ce cas, le filtrage améliore les performances, car seuls les vecteurs qui passent le filtre doivent être comparés.</p><p>Cela n'a pas d'incidence sur la qualité du résultat, car tous les vecteurs sont pris en compte de toute façon. Nous filtrons simplement à l'avance les résultats qui ne sont pas intéressants, afin de réduire le nombre d'opérations.</p><p>C'est très important, car il peut être plus performant d'exécuter une recherche exacte plutôt qu'une recherche approximative lorsque les filtres appliqués donnent un petit nombre de documents.</p><p>La règle de base est d'utiliser la recherche exacte lorsque moins de 10 000 documents passent le filtre. Les index <a href="https://www.elastic.co/search-labs/blog/better-binary-quantization-lucene-elasticsearch">BBQ</a> sont beaucoup plus rapides pour les comparaisons, il est donc logique d'utiliser la recherche exacte lorsque les index basés sont inférieurs à 100k. Consultez <a href="https://www.elastic.co/search-labs/blog/knn-exact-vs-approximate-search">cet article de blog</a> pour plus de détails.</p><p>Si vos filtres sont toujours très restrictifs, vous pouvez envisager une indexation axée sur la recherche exacte plutôt que sur la recherche approximative en utilisant un type d'index <code>flat</code> plutôt qu'un index basé sur HNSW. Pour plus de détails, voir <a href="https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/dense-vector#dense-vector-params">les propriétés de index_options</a>.</p><h2>Filtrage pour la recherche vectorielle approximative</h2><p>Lors de l'exécution d'une recherche vectorielle approximative, nous échangeons la précision des résultats contre la performance. Les structures de données de recherche vectorielle telles que HNSW recherchent efficacement les voisins les plus proches sur des millions de vecteurs. Ils se concentrent sur la récupération des vecteurs les plus similaires en effectuant le moins possible de comparaisons de vecteurs, qui sont coûteuses à calculer.</p><p>Cela signifie que les autres attributs de filtrage ne font pas partie des données vectorielles. Les différents types de données ont leurs propres structures d'indexation qui sont efficaces pour les trouver et les filtrer, comme les dictionnaires de termes, les listes d'écritures et les valeurs doc.</p><p>Étant donné que ces structures de données sont distinctes du mécanisme de recherche vectorielle, comment appliquer le filtrage à la recherche vectorielle ? Il existe deux options : appliquer les filtres après la recherche vectorielle (post-filtrage) ou avant la recherche vectorielle (préfiltrage).</p><p>Chacune de ces options présente des avantages et des inconvénients. Voyons cela de plus près !</p><h3>Post-filtrage</h3><p>Le post-filtrage applique des filtres après que la recherche vectorielle a été effectuée. Cela signifie que les filtres sont appliqués après que les k résultats vectoriels les plus similaires ont été trouvés.</p><p>Il est évident que nous pouvons potentiellement obtenir moins de k résultats après avoir appliqué les filtres aux résultats. Nous pourrions bien sûr obtenir plus de résultats à partir de la recherche vectorielle (valeur k plus élevée), mais nous ne serons pas sûrs d'obtenir k ou plus après avoir appliqué les filtres.</p><p>L'avantage du post-filtrage est qu'il ne modifie pas le comportement de la recherche vectorielle lors de l'exécution - la recherche vectorielle n'est pas consciente du filtrage. En revanche, il modifie le nombre final de résultats obtenus.</p><p>Voici un exemple de post-filtrage à l'aide de la <a href="https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-knn-query">requête knn</a>. Vérifier que la clause de filtrage est distincte de la requête knn :</p>{
  "query": {
    "bool": {
      "must": {
        "knn": {
          "field": "image-vector",
          "query_vector": [54, 10, -2],
          "k": 5,
          "num_candidates": 50
        }
      },
      "filter": {
        "term": {
          "file-type": "png"
        }
      }
    }
  }
}<p>Le post-filtrage est également disponible pour la recherche knn en utilisant le <a href="https://www.elastic.co/docs/reference/elasticsearch/rest-apis/filter-search-results#post-filter">post-filtre</a>:</p>{
  "knn": {
    "field": "image-vector",
    "query_vector": [54, 10, 2],
    "k": 5,
    "num_candidates": 50
  },
  "post_filter": {
    "term": {
      "file-type": "png"
    }
  }
}<p>Gardez à l'esprit que vous devez utiliser une section de post-filtrage explicite avec la recherche knn. Si vous n'utilisez pas de post-filtre, la recherche knn <a href="https://www.elastic.co/docs/solutions/search/vector/knn#_combine_approximate_knn_with_other_features">combinera les résultats des plus proches voisins</a> avec d'autres requêtes ou filtres au lieu d'effectuer un post-filtre.</p><h3>Préfiltrage</h3><p>L'application de filtres avant la recherche vectorielle permet d'abord d'extraire les documents qui satisfont aux filtres, puis de transmettre ces informations à la recherche vectorielle.</p><p>Lucene utilise les <a href="https://github.com/apache/lucene/blob/7a60d7ce92392181e137361336e5196bd486cdd9/lucene/core/src/java/org/apache/lucene/util/BitSet.java">BitSets</a> pour stocker efficacement les documents qui satisfont aux conditions du filtre. La recherche vectorielle parcourt ensuite le graphe HNSW en tenant compte des documents qui satisfont à la condition. Avant d'ajouter un candidat aux résultats, il vérifie qu'il est contenu dans le BitSet des documents valides.</p><p>Cependant, le candidat doit être exploré et comparé à la requête, même s'il ne s'agit pas d'un document valide. L'efficacité de HNSW repose sur la connexion entre les vecteurs du graphe : si nous cessons d'explorer un candidat, cela signifie que nous risquons d'ignorer également ses voisins.</p><p>Imaginez que vous conduisiez pour vous rendre à une station-service. Si vous écartez les routes qui ne comportent pas de station-service, il est peu probable que vous arriviez à destination. Les autres routes ne sont peut-être pas celles dont vous avez besoin, mais elles vous <em>relient à</em> votre destination. Idem pour les vecteurs sur un graphique HNSW !</p><p>Il s'ensuit que l'application d'un préfiltrage est moins performante que la non-application de filtres. Nous devons effectuer le travail sur <em>tous les</em> vecteurs que nous visitons dans notre recherche, et nous devons rejeter ceux qui ne correspondent pas au filtre. Nous travaillons davantage et prenons plus de temps pour obtenir nos meilleurs résultats.</p><p>Voici un exemple de préfiltrage dans le DSL de requête Elasticsearch. Vérifiez que la clause de filtrage fait désormais partie de la section knn :</p>{
  "knn": {
    "field": "image-vector",
    "query_vector": [54, 10, -2],
    "k": 5,
    "num_candidates": 50,
    "filter": {
      "term": {
        "file-type": "png"
      }
    }
  }
}<p>Le préfiltrage est disponible à la fois pour la <a href="https://www.elastic.co/docs/solutions/search/vector/knn#knn-search-filter-example">recherche knn</a> et la <a href="https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-knn-query#knn-query-filtering">requête knn</a>:</p>{
  "query": {
    "knn": {
      "field": "image-vector",
      "query_vector": [-5, 9, -12],
      "k": 5,
      "filter": {
        "term": {
          "file-type": "png"
        }
      }
    }
  }
}<h4>Optimisation du préfiltrage</h4><p>Il existe quelques optimisations que nous pouvons appliquer pour garantir la performance du préfiltrage.</p><p>Nous pouvons passer à la recherche exacte si le filtre est très restrictif. Lorsqu'il y a peu de vecteurs à comparer, il est plus rapide d'effectuer une recherche exacte sur les quelques documents qui satisfont le filtre.</p><p>Il s'agit d'une optimisation appliquée automatiquement dans <a href="https://github.com/apache/lucene/blob/eb876b618da5d04c1ad14b04a48321638318493a/lucene/core/src/java/org/apache/lucene/search/AbstractKnnVectorQuery.java#L218">Lucene</a> et Elasticsearch.</p><p>Une autre méthode d'optimisation consiste à ignorer les vecteurs qui ne satisfont pas au filtre. Au lieu de cela, cette méthode vérifie les voisins des vecteurs filtrés qui passent le filtre. Cette approche réduit effectivement le nombre de comparaisons puisque les vecteurs filtrés ne sont pas pris en compte, et continue d'explorer les vecteurs connectés au chemin actuel.</p><p>Cet algorithme est ACORN-1, et le processus est décrit en détail dans <a href="https://www.elastic.co/search-labs/blog/filtered-hnsw-knn-search">ce billet de blog.</a></p><h2>Filtrage à l'aide de la sécurité au niveau du document</h2><p><a href="https://www.elastic.co/docs/deploy-manage/users-roles/cluster-or-deployment-auth/controlling-access-at-document-field-level#document-level-security">Document Level Security (DLS)</a> est une fonctionnalité d'Elasticsearch qui spécifie les documents que les rôles d'utilisateurs peuvent récupérer.</p><p>La DLS est réalisée à l'aide de requêtes. Une requête peut être associée aux index pour un rôle, ce qui limite effectivement les documents qu'un utilisateur appartenant à ce rôle peut extraire des index.</p><p>L'interrogation sur le rôle est utilisée comme filtre pour <a href="https://github.com/elastic/elasticsearch/blob/c3a1cb34294e902a9f46d7e840ea09965019f456/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authz/accesscontrol/SecurityIndexReaderWrapper.java#L92">extraire les documents qui y correspondent</a> et qui sont mis en cache sous la forme d'un ensemble de bits. Ce BitSet est ensuite utilisé pour envelopper le lecteur Lucene sous-jacent, de sorte que seuls les documents renvoyés par la requête sont considérés comme <em>vivants, c'est-à-dire</em>qu'ils existent dans l'index et n'ont pas été supprimés.</p><p>Étant donné que les documents sont <a href="https://github.com/apache/lucene/blob/a211d30097a8e3264d3ef073a054bd31eb847231/lucene/core/src/java/org/apache/lucene/search/AbstractKnnVectorQuery.java#L196">extraits du lecteur</a> pour effectuer la requête knn, seuls les documents disponibles pour l'utilisateur seront pris en compte. S'il existe un préfiltre, les documents DLS <a href="https://github.com/apache/lucene/blob/a211d30097a8e3264d3ef073a054bd31eb847231/lucene/core/src/java/org/apache/lucene/search/AbstractKnnVectorQuery.java#L204">y seront ajoutés</a>.</p><p>Cela signifie que le filtrage DLS fonctionne comme un préfiltre pour la recherche vectorielle approximative, avec les mêmes implications en termes de performances et d'optimisations.</p><p>Le DLS avec recherche exacte présente les mêmes avantages que l'application de n'importe quel filtre - moins il y a de documents extraits du DLS, plus la recherche exacte est performante. Tenez également compte du nombre de documents renvoyés par le DLS - si les rôles du DLS sont très restrictifs, vous pouvez envisager d'utiliser la recherche exacte au lieu de la recherche approximative.</p><h2>Analyse comparative</h2><p>Chez Elasticsearch, nous voulons nous assurer que le filtrage de la recherche vectorielle est efficace. Nous disposons d'<a href="https://elasticsearch-benchmarks.elastic.co/#tracks/so_vector/nightly/default/90d">un benchmark spécifique pour le filtrage vectoriel</a> qui effectue des recherches vectorielles approximatives avec différents filtrages afin de s'assurer que la recherche vectorielle continue à récupérer des résultats pertinents aussi rapidement que possible.</p><p>Vérifiez les <a href="https://elasticsearch-benchmark-analytics.elastic.co/app/dashboards#/view/43b63e80-5ba2-11ed-aede-a742809feed4?_g=(refreshInterval:(pause:!t,value:60000),time:(from:'2025-05-28T01:27:58.456Z',to:'2025-06-30T13:53:26.430Z'))&amp;_a=()">améliorations apportées</a> lors de l'introduction d'ACORN-1. Pour les tests où seuls 2% des vecteurs passent le filtre, le temps de latence des requêtes est réduit à 55% de la durée initiale :</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt820cb0b715cf291c/6a17e227dbb4ff8d49fb5615/3eac3748a33376fc97d957364a5c1f5108d5c58b-1023x896.png" alt="" /><h2>Conclusion</h2><p>Le filtrage fait partie intégrante de la recherche. S'assurer que le filtrage est performant dans la recherche vectorielle, et comprendre les compromis et les optimisations, c'est ce qui fait l'efficacité et la précision d'une recherche.</p><p>Le filtrage a un impact sur les performances de la recherche vectorielle :</p><ul><li><p>La recherche exacte est plus rapide lorsque l'on utilise le filtrage. Vous pouvez envisager d'utiliser la recherche exacte au lieu de la recherche approximative si votre filtrage est suffisamment restrictif. Il s'agit d'une optimisation automatique dans Elasticsearch.</p></li><li><p>La recherche approximative est plus lente lorsque l'on utilise le préfiltrage. Le préfiltrage nous permet d'obtenir les k premiers résultats correspondant au filtre, au prix d'une recherche plus lente.</p></li><li><p>Le post-filtrage ne permet pas nécessairement de retrouver les k premiers résultats, car ils peuvent être filtrés par le filtre lorsqu'il est appliqué.</p></li></ul><p>Bon filtrage !</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/vector-search-filtering</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/vector-search-filtering</guid>
    <category><![CDATA[Base vectorielle]]></category>
    <category><![CDATA[Lucene]]></category>
    <category><![CDATA[À l'intérieur d'Elastic]]></category>
    <dc:creator><![CDATA[Carlos Delgado]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt39ede1736e0f1456/6a17e2282f4a5c5031fa8843/03b1dd4c7bda4fbabd8e374bc2e4f12d5be6ef5f-1600x1150.png" length="0" type="image/png"/>
    <pubDate>Wed, 03 Sep 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>