1 points par GN⁺ 2024-11-19 | 1 commentaires | Partager sur WhatsApp
  • Fast GraphRAG est un framework GraphRAG simplifié pour des workflows de recherche pilotés par agents interprétables et de haute précision, qui met l’accent sur l’ajout d’un RAG avancé à un pipeline de recherche sans construire directement des workflows d’agents complexes
  • Il rend les graphes de connaissances explorables par des humains, permet de les interroger, de les visualiser et de les mettre à jour, et génère et affine automatiquement les graphes selon les exigences du domaine et de l’ontologie
  • Pour répondre aux requêtes, il utilise une exploration de graphe fondée sur le personalized PageRank afin de trouver les informations pertinentes, et le README renvoie au papier HippoRAG pour une vue d’ensemble de cette approche
  • Dans l’exemple de coût basé sur The Wizard of Oz, fast-graphrag est indiqué à 0,08 $, contre 0,48 $ pour graphrag, et il est affirmé que cette réduction des coûts par 6 s’améliore encore à mesure que la taille des données et le nombre d’insertions augmentent
  • Il fonctionne avec Python 3.10.1 ou supérieur, prend en charge l’installation depuis les sources et via PyPI, puis permet d’insérer des documents et d’effectuer des requêtes après configuration de la clé API OpenAI, tout en conservant automatiquement les connaissances dans le même répertoire de travail

Le framework de recherche proposé par Fast GraphRAG

  • Fast GraphRAG est un framework GraphRAG visant une connaissance interprétable et débogable
  • Le graphe présente les connaissances sous une forme que l’humain peut explorer, et prend en charge les opérations suivantes
    • requête
    • visualisation
    • mise à jour
  • Il cherche à offrir des fonctionnalités RAG avancées tout en réduisant la charge liée à la construction et à la conception directes de workflows d’agents

Principales fonctionnalités

  • Conçu pour pouvoir être exécuté rapidement et à faible coût à grande échelle, avec une orientation vers la réduction des besoins en ressources lourdes et des coûts
  • Prend en charge les données dynamiques, et génère puis affine automatiquement les graphes en fonction des exigences du domaine et de l’ontologie
  • Prend en charge les mises à jour incrémentales lorsque les données changent, ce qui permet des mises à jour en temps réel
  • Fournit une exploration intelligente qui améliore la précision et la fiabilité en exploitant une exploration de graphe fondée sur PageRank
  • L’ensemble adopte une approche asynchrone et vise des workflows robustes et prévisibles grâce à une prise en charge complète du typage

Exemple de coût

  • Dans l’exemple utilisant The Wizard of Oz, le coût de fast-graphrag est indiqué à 0,08 $, contre 0,48 $ pour graphrag
  • Le README présente cela comme une réduction des coûts par 6 et indique que l’effet d’économie s’améliore encore lorsque la taille des données et le nombre d’insertions augmentent

Installation et déroulement d’exécution

  • La méthode d’installation recommandée se divise entre l’installation depuis les sources pour les performances et l’installation via PyPI pour la stabilité
    • Installation depuis les sources : cloner le dépôt puis exécuter poetry install
    • Installation via PyPI : pip install fast-graphrag
  • L’exemple de démarrage rapide commence par définir la variable d’environnement OPENAI_API_KEY
  • Après avoir téléchargé le texte de A Christmas Carol, on initialise GraphRAG dans le code Python
  • L’exemple d’initialisation comprend les valeurs suivantes
    • working_dir="./book_example"
    • un domain qui analyse les personnages de l’histoire, leurs interactions, les lieux et les relations
    • une liste d’exemples de requêtes
    • les types d’entités ["Character", "Animal", "Place", "Object", "Activity", "Event"]
  • Le document est inséré avec grag.insert(f.read()), puis le résultat d’une requête est affiché avec grag.query("Who is Scrooge?").response
  • Si l’on réinitialise dans le même répertoire de travail, les connaissances sont automatiquement conservées
  • Pour contrôler le nombre de tâches LLM traitées en parallèle, notamment avec des modèles locaux, il est possible de définir en option une variable d’environnement comme CONCURRENT_TASK_LIMIT=8

Exemples et options de configuration

  • Le dossier examples fournit des tutoriels sur les cas d’usage courants de la bibliothèque
  • custom_llm.py est un exemple simple montrant comment configurer différemment un modèle de langage compatible avec l’API OpenAI et les embedders
  • checkpointing.ipynb traite de l’usage des checkpoints afin d’éviter des corruptions de données irréversibles
  • query_parameters.ipynb couvre divers paramètres de requête et montre comment inclure des références aux informations utilisées dans les réponses avec with_references=True

Philosophie de conception et méthode d’exploration

  • L’objectif est d’augmenter le nombre d’applications GenAI réussies, et pour cela l’équipe explique construire des outils de mémoire et de données permettant aux applications LLM d’exploiter des pipelines de recherche spécialisés sans avoir à configurer et maintenir des workflows d’agents complexes
  • Fast GraphRAG explore le graphe avec l’algorithme de personalized PageRank afin de trouver les informations les plus pertinentes pour répondre à la requête en cours
  • Pour un aperçu des raisons du fonctionnement de cette approche, le papier HippoRAG est donné en référence

Open source et service managé

  • Le dépôt est proposé sous licence MIT ; davantage de détails sont disponibles dans LICENSE.txt
  • Un service managé est proposé comme moyen de démarrer rapidement et de manière fiable
  • Ce service managé inclut 100 requêtes gratuites chaque premier mois, puis une facturation à l’usage
  • Pour en savoir plus sur le service managé, il est possible de réserver une démo ou de consulter la documentation
  • Les informations de contribution se trouvent dans CONTRIBUTING.md, et les questions peuvent être posées sur Discord

1 commentaires

 
GN⁺ 2024-11-19
Commentaires sur Hacker News
  • En plus de PageRank, il existe plusieurs mesures de centralité intéressantes qui peuvent influencer le RAG sur des données structurées
    Parmi elles, la Triangle Centrality calcule la centralité en comptant les triangles autour d’un nœud, sur l’idée que les triangles renforcent fortement la fermeture des relations, tandis que les connexions ouvertes retirent du poids au centre et diluent ainsi la centralité
    https://arxiv.org/abs/2105.00110
    L’article affirme qu’elle est plus efficace que d’autres centralités comme PageRank, mais dans une étude utilisant GraphBLAS, sur plusieurs graphes creux allant jusqu’à 1,8 milliard d’arêtes, la TC était plus lente que notre implémentation creuse de PageRank
    Cela dit, plus le graphe grossit, plus la TC semble bien passer à l’échelle, et elle pourrait être plus efficace à l’échelle du billion d’arêtes
    https://fossies.org/linux/SuiteSparse/GraphBLAS/Doc/The_Grap...

    • Ici, on est sur des millions de nœuds/arêtes, donc l’efficacité n’est pas un enjeu majeur
      De toute façon, le goulot d’étranglement sera la partie que le LLM doit parser pour générer la réponse
      PageRank n’est qu’une première étape, mais j’aimerais bien tester aussi des alternatives plus précises
      Ici, on utilise un PageRank personnalisé, avec un poids initial attribué à un ensemble précis de nœuds ; je me demande si la Triangle Centrality prend aussi cela en charge
      On regarde également les poids d’arêtes, donc j’aimerais savoir si c’est possible aussi
    • Je me demande si vous avez essayé Authority Rank comme alternative à PageRank
      https://link.springer.com/content/pdf/10.1007/978-3-030-6097...
  • J’ai pas mal travaillé dans ce domaine, et j’en ai tiré quelques enseignements

    1. Si on peut faire un peu de travail avec un LLM au moment de l’ingestion, une recherche lexicale fondée sur BM25 suffit souvent à produire des résultats très pertinents
    2. Les embeddings ne fonctionnent bien que lorsque la taille de la requête est grosso modo du même ordre que celle de ce qu’on stocke dans le magasin d’embeddings
    3. Faire générer au LLM une réponse hypothétique à partir de la requête, puis utiliser cette réponse hypothétique pour la recherche par embeddings, fonctionne très bien
      En combinant ces trois éléments, on a construit une étape similaire de décomposition/extraction des connaissances, à laquelle on a ajouté un méta-prompteur pour générer pratiquement automatiquement les types de domaine/d’entité
      Les LLM ont, de manière générale, du mal à trouver le bon niveau de granularité pour des connaissances décomposées
      Une astuce consiste à demander au LLM de produire une mind map mermaid.js afin de découper l’entrée en arbre hiérarchique, puis de dire à la fin à quel niveau se trouve la bonne racine pour un nœud de connaissance
      On génère ensuite les questions auxquelles les connaissances de ce nœud permettent de répondre, puis on indexe ce texte de questions et on en fait aussi des embeddings
      Faire correspondre directement la requête utilisateur à ces questions avec du BM25 pur donne déjà de bons résultats, et l’approche hybride est encore meilleure, sans que l’écart soit énorme
      Si on n’utilise pas de LLM au moment de la requête, on peut aussi descendre hiérarchiquement depuis la racine vers des nœuds plus profonds en utilisant la similarité d’embedding comme fonction de coût de parcours
    • J’avais obtenu de bons résultats en expérimentant auparavant avec une structure en arbre similaire
      Au final, on a décidé de passer au graphe comme généralisation de l’arbre
      L’idée clé, selon moi, est d’utiliser la similarité d’embedding pour “parcourir” le graphe, et on l’intègre activement dans FastGraphRAG aussi, en pondérant les arêtes selon la requête
      C’est intéressant de voir plusieurs solutions converger vers une architecture semblable
    • J’aimerais bien que vous expliquiez davantage ce que vous entendez par “faire un peu de travail avec un LLM au moment de l’ingestion” et quel en est l’objectif
      L’idée de générer une réponse hypothétique à partir de la requête puis de faire la recherche d’embeddings avec cette réponse est intéressante, et j’aimerais l’ajouter à ma liste d’expériences
    • C’est encourageant d’entendre que le fait de créer une réponse hypothétique à partir de la requête puis de l’utiliser dans le flux RAG fonctionne réellement bien
      Je me demande maintenant si cela marcherait encore mieux en générant la réponse hypothétique avec un LLM finement ajusté sur le corpus
    • Je me demande si le texte injecté dans l’index BM25 est découpé en chunks
      J’aimerais aussi savoir si, au moment de générer la réponse hypothétique, vous promptiez des réponses adaptées à la “taille de chunk”
  • Utiliser PageRank pour améliorer la centralité semble une bonne idée, mais cela ne résout toujours pas le défaut probablement insoluble du RAG, à savoir pourquoi le RAG a fondamentalement du mal à fonctionner
    Si toutes les bases RAG affichent des performances inférieures aux attentes, c’est parce que le RAG ne parvient pas fondamentalement à retrouver les relations entre les mots nécessaires pour trouver l’information que cherche l’utilisateur
    Cela peut sembler étrange, car on pourrait penser que le mécanisme d’“attention” est justement censé bien faire ce genre de choses, mais en pratique ce n’est pas suffisant
    Par exemple, imaginons qu’un texte dise qu’une personne nommée ‘Sharon’ a assisté à plusieurs conférences de physicochimie, mais sans préciser sa profession
    Si l’on cherche “Quelle est la profession de Sharon ?”, la plupart des approches RAG auront probablement du mal à relier ‘profession’, la participation à des conférences et le type de conférence pour en déduire ‘chimiste’
    Ce type d’erreur se retrouve dans de nombreuses catégories d’information lorsqu’on récupère de l’information avec du RAG
    Au final, des solutions comme celle-ci donnent l’impression de réinventer, avec davantage d’étapes, d’autres méthodes de requête comme SQL ou PageRank, et à ce stade la vectorisation n’a plus beaucoup de sens

    • J’aurais tendance à dire que cette inférence relève du rôle du LLM
      Le composant RAG n’a qu’à retrouver, dans un grand jeu de données, l’article concernant Sharon et à transmettre l’ensemble au LLM comme contexte
    • Au contraire, ce type d’exemple est précisément au cœur de cette approche
      Si vous regardez l’article HippoRAG cité dans le billet d’origine, l’exemple de motivation est presque identique, et l’évaluation vise globalement ce type de questions-réponses multi-sauts
    • Avec un graphe de connaissances, cela ne semble pas impossible
      Il suffit de récupérer l’entité Sharon, puis de recevoir comme contexte supplémentaire les nœuds et arêtes proches de Sharon
      Ensuite, c’est le rôle du LLM, et si la profession ne figure pas dans le contexte fourni, il doit indiquer que “dans le contexte fourni, il est impossible de trouver la profession de Sharon”
  • J’ai trouvé ça intéressant, donc je me suis inscrit et j’ai téléversé quelques documents PDF sur le tableau de bord
    Mon cas d’usage consiste à analyser des documents de conformité liés à la fabrication dans une startup IA, mais pour que cela nous soit utile, il faut comprendre jusqu’à quelle échelle cela fonctionne et quel est le modèle de coût
    Nous avons environ 300 000 PDF par client, et nous nous attendons à ce qu’environ 10 % du corpus documentaire change chaque mois
    Tout système de GraphRAG doit pouvoir traiter des documents à grande échelle, et même si S3 peut servir de mécanisme d’ingestion, nous avons besoin de connaître le coût et le temps de traitement avant que le système soit de nouveau disponible au point suivant

    1. chargement initial
    2. mises à jour régulières — par exemple, comment le système supprime les données
    • Je pense pouvoir vous aider
      J’aimerais en discuter plus en détail, donc n’hésitez pas à me contacter à antonio [at] circlemind.co
  • Intéressant, mais je me demande quelle taille doit avoir un corpus de textes spécialisé par domaine pour produire un graphe de connaissances utile
    Aider applique depuis longtemps PageRank au graphe d’appels des dépôts de code
    Tout code non trivial contient beaucoup de structure de graphe pour alimenter PageRank, et cela fonctionne très bien pour trouver le contexte le plus pertinent dans un projet par rapport à la tâche en cours
    https://aider.chat/docs/repomap.html#optimizing-the-map

    • J’ai essayé avec des textes allant de courtes nouvelles jusqu’à des documents entiers de plusieurs millions de tokens, et dans les deux cas cela semble produire des graphes intéressants
      J’aimerais beaucoup avoir des retours quand davantage de personnes commenceront à l’utiliser
    • J’utilise bien Aider, mais je n’ai jamais réussi à générer correctement une repo map, que la base de code soit en Python, JS ou TS
      Je me demande si vous prévoyez de permettre de forcer la génération d’une repo map et de l’inspecter
  • Super
    Je me demande comment le graphe est stocké et interrogé
    Je connais bien les bases de données orientées graphe, mais ça ne semble pas être une dépendance
    Je me demande aussi si vous avez essayé le modèle sciphi triplex pour l’extraction
    Quand j’ai fait de l’extraction auparavant, les résultats n’étaient pas cohérents si j’extrayais plusieurs fois de suite le même chunk

    • Le graphe est actuellement stocké avec python-igraph
      La base de code est conçue pour pouvoir intégrer facilement n’importe quelle base de données graphe avec un léger wrapper, et nous prévoyons de prendre en charge prochainement des solutions comme neo4j
      Nous n’avons pas encore essayé triplex, car gpt4o-mini est pour l’instant suffisamment rapide et précis
      Nous utilisons aussi gpt4o-mini non seulement pour l’extraction des entités et des relations, mais aussi pour la génération de descriptions et la résolution des conflits
      Avec du fine-tuning, les résultats seraient certainement encore meilleurs
      L’interrogation du graphe consiste à trouver un ensemble initial de nœuds pertinents pour une requête donnée, puis à exécuter un PageRank personnalisé à partir de ces nœuds pour trouver d’autres passages pertinents
      Pour l’instant, nous choisissons les nœuds initiaux par recherche sémantique à la fois sur la requête complète et sur les entités extraites de la requête, mais nous avons aussi prévu quelques ajouts intéressants à cette approche
  • Bonne idée
    Personnellement, je pense que pour le RAG, la voie à suivre est la recherche d’information traditionnelle
    La recherche vectorielle est bien, mais elle est lente et coûteuse, et les gens ont tendance à l’utiliser comme de la poudre magique
    Elle fonctionne bien sur les données non structurées, mais n’est pas forcément aussi adaptée aux données structurées
    À moins d’un réglage très poussé, la recherche vectorielle n’est pas non plus tellement meilleure qu’une requête traditionnelle bien optimisée
    J’ai déjà vu en pratique des gens transformer des données structurées en données non structurées pour ensuite faire de la recherche vectorielle ou du prompt engineering, et globalement cela donne l’impression de prendre le problème à l’envers
    Ça peut fonctionner dans une certaine mesure, mais il y a probablement des façons plus intelligentes d’obtenir le même résultat
    L’essence même de Graph RAG est d’exploiter la structure des données
    Que ce soit avec des jointures SQL ou des requêtes de base de données graphe n’a pas vraiment d’importance
    Il y aurait aussi de la valeur à apprendre au LLM comment interroger ces systèmes, ou à l’interfacer avec des API de recherche/requête existantes
    Un mauvais classement peut être compensé par une fenêtre de contexte plus grande, et en récupérant plus de centaines de résultats avec plusieurs requêtes
    Ce type de passage à l’échelle sera bien plus rapide et moins coûteux que la recherche vectorielle

  • Ça a l’air bien, mais j’ai déjà été échaudé par d’autres couches d’abstraction comme LangChain, donc je crains une simplification excessive
    Je me demande comment vous comptez éviter de répéter les mêmes erreurs

  • Je me demande s’il existe des scores de métriques d’évaluation pour la recherche et la génération
    Par exemple sur des jeux de données comme KILT ou NQ
    Les jeux de données de benchmark ne font pas tout, mais montrer des scores corrects ainsi que des temps d’inférence aiderait beaucoup à convaincre les auteurs de frameworks ou à orienter le choix des ingénieurs
    En tant qu’ingénieur freelance en traitement automatique du langage, j’ai déjà construit beaucoup de pipelines RAG, et je compte essayer celui-ci moi-même

  • Je construis actuellement un chatbot de questions-réponses et j’ai du mal à gérer le scénario suivant
    Quand l’utilisateur demande « qu’est-ce que tu voulais dire dans la phrase précédente que tu viens de dire ? », je me demande comment ce framework peut récupérer le bon petit sous-ensemble de connaissances brutes et l’intégrer au LLM pour produire une réponse pertinente
    Il m’a été difficile de résoudre ce problème sans dépendre de frameworks externes
    https://www.reddit.com/r/LocalLLaMA/comments/1gtzdid/d_optim...
    J’aimerais savoir comment ce framework résout ce problème et comment il peut simplifier le processus

    • Après de nombreuses expériences, la seule chose qui a vraiment bien fonctionné dans une application de type chat a été de transmettre les 4 ou 5 derniers messages, puis si possible l’historique complet de la conversation, avant de demander au LLM de résumer la question dans le contexte de l’échange
      Sans cela, il échouait souvent quand l’utilisateur posait des questions comme « peux-tu détailler le point 2 ? » ou « donne un exemple détaillé de ce qui précède »
      L’implémentation actuelle maintient trois index, fournit la requête et les messages précédents, puis demande au LLM de les décomposer en
      requête complète, question optimisée pour BM25, mots-clés, question optimisée pour la recherche sémantique
      Ensuite, on exécute le RAG et un reranking, puis on transmet les N meilleurs passages avec la requête complète à un second appel au LLM
    • Si l’utilisateur pose ce genre de question, l’agent ne doit pas appeler le RAG et doit répondre uniquement à partir de l’historique de la conversation
      Il faut se concentrer sur l’étape d’orchestration
      Vous pouvez regarder du côté des agents ReAct, et le construire avec LangGraph ou Bedrock Agents
    • Je me demande si vous avez essayé de laisser le LLM décider, via l’usage d’outils ou des requêtes directes, s’il doit utiliser une recherche de connaissances ou non