Faire du RAG sur des métadonnées documentaires : pourquoi ça ne va pas être si simple

Faire du RAG sur des métadonnées bibliographiques afin d'interagir en langage naturel et en mode conversationnel avec des collections documentaires via une interface de type chatbot est évidemment très tentant et semble la voie naturelle de l’application de l’IA générative sur des gisements documentaires, mais se heurte en réalité à un écueil de taille.

On rappelle en effet que l’objectif fondateur et fondamental des LLMs est de répondre à l’enjeu principal du NLP consistant à faire en sorte que les machines puissent comprendre et traiter le langage naturel, en développant pour cela des algorithmes capables de prendre du texte brut en entrée et d’en produire une représentation sémantique en sortie.

Par nature ces modèles sont dédiés et calibrés pour la compréhension du langage naturel dans toutes ses complexités, tandis que par nature également, nos métadonnées bibliographiques, quel qu’en soit le format ou la modélisation sous-jacente, ne constituent pas des ensembles textuels développés puisque notre objectif commun de traitement documentaire consiste justement à les normaliser et les structurer dans des formats professionnels afin de pouvoir les manipuler dans des systèmes de gestion de base de données et les échanger via des protocoles informatiques. La richesse de nos métadonnées proviennent ainsi de leur forte structuration normative, de leur adossement à des référentiels communs faisant autorité, de leur alignement et de leur découvrabilité par le biais de PIDs, mais du point de vue d’un LLM actionné dans une application de RAG, une notice Marc ou des triplets RDF en tant que source de connaissance externe constituent des arctefacts bien trop contextuellement et informativement “pauvres” pour être exploités.

On remarquera d'ailleurs que la plupart des exemples et tutos de chatbot de RAG dans des environnements documentaires s'appuient sur l'ajout et l'encodage de full-text de publications comme source de données externes dans le but d'interagir avec le contenu des publications, mais ne portent pas sur les métadonnées descriptives des publications pour disposer de l'équivalent d'un moteur de recherche documentaire. Même le futur NDE d'Exlibris annoncé comme la nouvelle version de Primo boosté à l'IA et au RAG permettra en fait de converser avec du texte intégral de publications, mais pas de requêter leurs métadonnées en langage naturel.


"Our approach to incorporating generative AI-powered discovery in Primo, based on full-text ProQuest content, into the research and learning process offers convenience to our future users" Source : https://exlibrisgroup.com/blog/artificial-intelligence-blog-series-prioritizing-conversational-discovery-at-ex-libris/


Donc que fait-on ? Et bien on revient par exemple à nos bons vieux graphes de données...

RAG et Knowledge graph

La recherche vectorielle, toute performante qu'elle soit sur des données textuelles non structurées, n'étant pas calibrée pour travailler sur des données structurées moins riches en informations contextuelles, une approche intéressante (surtout pour nous bibliothécaires !) consiste à combiner les représentations numériques vectorielles obtenues grâce aux modèles d'embeddings avec une modélisation des données en réseau afin de bénéficier du meilleur des deux systèmes : d’une part la capacité des graphes à capturer des relations complexes entre entités et à représenter des informations hétérogènes de manière interconnectée, et d’autre part le support de la base de données vectorielle qui conserve la compréhension sémantique des données. Il s'agit donc d'approfondir la description textuelle des entités en l'associant avec une représentation en réseau de ses propriétés et relations, afin "d'aider" le LLM dans sa compréhension terminologique du dataset, la beauté du dispositif tenant de plus au fait que LLMs peuvent en partie automatiser le processus de création de graphes de connaissances en identifiant les entités, comprenant leurs relations et suggérant la meilleure structure de graphe.

Développement du chatbot

On se base sur :

  • ce dataset de publications issues de HAL pour augmenter la base de connaissance du LLM avec ce nouveau contexte (cf ce précédent billet et cette doc pour les explications sur la méthode de constitution du jeu de données) ;
  • le framework LlamaIndex ;
  • la base de données NoSQL orientée graphe Neo4j pour stocker les noeuds et relations modélisés à partir du dataset.

Installation et import des librairies

! pip install -U datasets llama-index neo4j llama-index-embeddings-nomic install llama-index-llms-groq llama-index-graph-stores-neo4j

import pandas as pd
from datasets import load_dataset
from llama_index.core import SimpleDirectoryReader, KnowledgeGraphIndex, StorageContext, load_index_from_storage
from llama_index.graph_stores.neo4j import Neo4jGraphStore
from llama_index.embeddings.nomic import NomicEmbedding
from llama_index.llms.groq import Groq
from llama_index.core import Settings
import nest_asyncio

Pour se mettre en situation de notices bibliographiques standards et pour éprouver l'apport de la modélisation en graphe de connaissances sur des données peu verbeuses, on supprime l'abstract des métadonnées.

Chargement des données

# download data
hal_data = load_dataset("Geraldine/hal_univcotedazur_shs_articles_2013-2023", data_files="hal_data.csv")
df = pd.DataFrame(hal_data["train"])

# remove textual columns
df = df.drop(columns=["abstract_s","combined"])

# save
df.to_csv("hal_data.csv", index=False, encoding="utf-8")

# load data
reader = SimpleDirectoryReader(input_files=["hal_data.csv"])
documents = reader.load_data()

Modèle d'embeddings & LLM

On choisit le modèle d'embeddings nomic-embed-text-v1.5 et mixtral comme LLM.

NOMIC_API_KEY = "..."
nest_asyncio.apply()

embed_model = NomicEmbedding(
    api_key=NOMIC_API_KEY,
    dimensionality=768,
    model_name="nomic-embed-text-v1.5",
)
GROQ_API_KEY = "..."
llm = Groq(model="mixtral-8x7b-32768", api_key=GROQ_API_KEY)

Settings.llm = llm
Settings.embed_model = embed_model
Settings.chunk_size = 512

Graph store

Pour l'intégration de Neo4j comme base de données de persistance et d'interrogation des données, on choisit de créer une instance (gratuite) via Neo4j Aura, l'offre de service cloud de Neo4j. Voir cette documentation pour la création du compte et de la base de données sur la plateforme.

# infos de connexion
username = "neo4j"
password = "..."
url = "neo4j+s://xxxxxxxx.databases.neo4j.io:7687"

graph_store = Neo4jGraphStore(
    username=username,
    password=password,
    url=url,
)

storage_context = StorageContext.from_defaults(graph_store=graph_store)

Création de l'index

index = KnowledgeGraphIndex.from_documents(
    documents,
    storage_context=storage_context,
    include_embeddings=True,
    max_triplets_per_chunk=2,
    show_progress=True,
)

Le paramètre "include_embeddings=True" indique de persister à la fois les attributs textuels des noeuds et relations et les vecteurs des embeddings. On retrouve ce double index dans la liste des index de l'instance Neo4j

SHOW INDEXES

enter image description here

Sauvegarde de l'index

Cette étape n'est pas obligatoire dans le processus, mais très utile pour stocker l'index contenant les embeddings dans le système de fichiers locaux afin de pouvoir le recharger ultérieurement sans avoir à reconstruire tout le Graph store dans Neo4j.

# Persist
index.storage_context.persist("./index_storage")

# For reloading
storage_context = StorageContext.from_defaults(persist_dir="./index_storage")
index = load_index_from_storage(storage_context)

Au final, voici à quoi ressemble (en partie) le graphe dans le browser de Neo4j

enter image description here

Création du moteur d'interrogation

query_engine = index.as_query_engine(
    include_text=True,
    response_mode="tree_summarize",
    embedding_mode="hybrid",
    similarity_top_k=5,
)

Le paramètre "embedding_mode='hybrid'" actionne la recherche hybride qui utilise une combinaison de mots clés et de recherche vectorielle.

Requêtes

response = query_engine.query(
    "Is there many articles about climate change ? If you find some, give me the title, the author and the publication date of the three ones that seems the more accurate for you "
)
print(response)

Voir la réponse

Based on the information provided, there are indeed several articles that discuss climate change and its impacts. Here are three articles that seem particularly relevant:

1. "Territorial inertia versus adaptation to climate change. When local authorities discuss coastal management in a French Mediterranean region" by Samuel Robert, Axel Quercy, and Alexandra Schleyer-Lindenmann, published in 2023 in Global Environmental Change.
2. "Building types in France. Clustering building morphometrics using national spatial data" by Allessandro Araldi, David Emsellem, Giovanni Fusco, Andrea Tettamanzi, and Denis Overal, published in 2023 in Revue Internationale de Géomatique.
3. "Uncovering the structure of property ownership for a better understanding of the socio-spatial distribution of wealth" by Laure Casanova Enault, Martin Bocquet, and Guilhem Boulay, published in 2023 in Journal of Urban Affairs.

These articles discuss various aspects of climate change and its impacts on coastal management, building morphometrics, and property ownership.

response = query_engine.query(
    "How many works of Norbert Hillaire is there ? "
)
print(response)

Voir la réponse

There are two works of Norbert Hillaire. This conclusion is derived from the knowledge sequence that indicates Norbert Hillaire is the author of 'Hal-03625117' and 'Hal-03625395'.

Ce qui est factuellement incomplet puisqu'il y a 5 articles dont Norbert Hillaire est le co-auteur dans le jeu de données.

response = query_engine.query(
    "Can you count the number of publications associated with each publisher and tell Which publisher has the most publications?"
)
print(response)

Voir la réponse

After analyzing the given data, there are two publishers mentioned: Taylor & Francis (Routledge) and Elsevier.

Ce qui est partiellement faux car Elsevier est bien l'éditeur le plus représenté mais Taylor & Francis n'arrive qu'en 5ème position en nombre cumulé de publications.

Conclusion

Si l'on poursuit plus avant les questions/réponses avec le moteur d'interrogation, il apparaît nettement que les réponses pourraient être justes et pertinentes, mais qu'elles ne le sont que partiellement en raison de la structure du graphe en partie inadéquate et de la modélisation automatique en réseau par le LLM parfois impropre. Comme toujours avec les systèmes de RAG, derrière l'apparente facilité de mise en oeuvre permise par les outils et frameworks et une fois passé le côté "magique" de la chose, aboutir à une application stable et pertinente implique un développement complexe avec de nombreux réglages, tests et phases manuelles (comme ici par exemple où il faudrait en fait et entre autres ne pas déléguer au seul modèle l'extraction de données structurées en graphe depuis le dataset mais définir le schéma de données en amont afin d'aider le LLM à générer un KnowledgeGraph de meilleure qualité).


"> ');