kg-gen : extraire un graphe de connaissances d'un texte avec un LLM
[NeurIPS '25] Knowledge Graph Generation from Any Text
En bref
- De quoi s’agit-il ?
- La bibliothèque kg-gen transforme un texte brut ou un tableau de messages en entités, relations et clusters, en s'appuyant sur LiteLLM et DSPy. Son intérêt tient surtout au post-traitement des doublons, pas à l'appel au modèle.
- À qui s’adresse-t-il ?
- kg-gen convient à qui veut un graphe d'entités et de relations à partir de texte déjà propre, avec un modèle au choix via LiteLLM, et qui accepte de vérifier lui-même la licence et la qualité du clustering. À éviter si le texte source est bruité ou si le budget d'appels LLM est serré.
- Puis-je l’utiliser commercialement ?
- Pas sans autorisation. GitHub ne trouve aucun fichier de licence dans ce dépôt, et sans licence tous les droits sont réservés par défaut : vous pouvez lire le code, mais pas le réutiliser. Consultez le README ou demandez l’accord des auteurs avant de l’utiliser.
- Est-il encore maintenu ?
- Oui. Les derniers commits datent d’il y a 175 jours.
- En quel langage est-il écrit ?
- Principalement Python, d’après les statistiques de langage de GitHub.
Ces réponses reposent sur les données GitHub du projet (dernière synchronisation le 15 septembre 2026) et sur notre analyse. Elles ne constituent pas un avis juridique.
ANALYSE OPEN SOURCE APPROFONDIE
Le problème : un LLM répond en prose, pas en triplets
Un modèle de langage lit volontiers un paragraphe et en résume le sens. Ce qu'il ne fait pas nativement, c'est rendre une structure exploitable : une liste d'entités, une liste de types de relations, et les triplets qui les relient. Or c'est exactement ce qu'il faut pour alimenter un index de graphe, générer des données synthétiques d'entraînement, ou simplement cartographier les concepts d'un document. kg-gen se place sur ce créneau. Le README énumère quatre usages : aider un système RAG, produire des données synthétiques, structurer un texte quelconque, analyser les relations entre concepts. La cible est donc l'ingénieur qui a du texte et qui veut des triplets, sans écrire lui-même la couche de parsing et de dédoublonnage. Le projet est publié sous une licence que le matériel fourni ne précise pas, ce qui est en soi un point à trancher avant tout usage en production.
Deux appels distincts : l'extraction, puis la réconciliation
Le mécanisme visible dans le README tient en deux temps. Le premier est l'extraction : le texte est envoyé au modèle, qui renvoie des ensembles d'entités, d'arêtes et de relations. Le second, optionnel mais central, est la réconciliation. Avec chunk_size=5000 et cluster=True, le texte long est découpé en morceaux, chaque morceau produit son propre graphe, puis les entités et les relations sont regroupées. Le README montre le résultat sous forme de dictionnaires entity_clusters et edge_clusters : 'artificial intelligence' regroupe {'AI', 'artificial intelligence'}, 'machine learning' regroupe {'machine learning', 'ML'}, et côté arêtes 'is type of' absorbe 'is a type of' et 'is a kind of'. C'est là que se joue la qualité réelle du graphe. Un LLM qui traite deux morceaux de texte différents écrira tantôt 'neural nets', tantôt 'NN' pour la même chose. Sans cette étape, le graphe est un sac de variantes. La méthode kg.aggregate([graph4_a, graph4_b]) permet de fusionner des graphes produits séparément, et kg.cluster() de les réconcilier ensuite, éventuellement avec un context textuel. Le README indique aussi que la sortie structurée passe par DSPy, et que les appels modèles sont routés par LiteLLM.
Le modèle est un paramètre, pas une dépendance
kg-gen ne présuppose aucun fournisseur. Le constructeur prend une chaîne model au format LiteLLM, généralement {model_provider}/{model_name}. Le README cite openai/gpt-5, gemini/gemini-2.5-flash et ollama_chat/deepseek-r1:14b. Cette dernière entrée mérite l'attention : elle signifie qu'on peut faire tourner l'extraction sur une machine locale via Ollama, sans clé d'API, ce qui change la donne pour les textes confidentiels. Une clé peut être passée directement en argument api_key, ou laissée dans l'environnement. Le README mentionne également un paramètre base_url pour pointer vers une API compatible auto-hébergée, avec un exemple dans tests/test_custom_api_base.py. C'est un choix d'architecture qui a un coût : la qualité du graphe dépend entièrement du modèle choisi, et le projet ne fournit aucun garde-fou sur ce point. Un petit modèle local produira des relations plus pauvres et des variantes plus nombreuses à réconcilier. Le paramètre temperature par défaut est 0.0, ce qui est cohérent avec une tâche d'extraction où l'on veut de la reproductibilité plutôt que de la variété.
Mise en route : pip, un test, et deux formats d'entrée
L'installation tient en une commande : pip install kg-gen. Pour travailler depuis les sources, le README indique pip install -e '.[dev]' après clonage, puis python tests/test_basic.py depuis la racine du dépôt. Ce script sert de vérification et produit une visualisation dans tests/test_basic.html. C'est le point de contrôle le plus concret offert par la documentation : si ce fichier apparaît et contient un graphe lisible, la chaîne modèle est correcte. L'entrée accepte deux formes. Une chaîne simple, avec un paramètre context facultatif qui oriente l'extraction (le README donne context="Family relationships" sur une phrase de parenté). Ou une liste de dictionnaires avec role et content, ce qui permet de traiter une conversation et d'en extraire le graphe. Pour l'affichage, KGGen.visualize(graph, output_path, open_in_browser=True) génère un rendu HTML. Le serveur MCP s'installe avec la même distribution : pip install kg-gen puis kggen mcp, à brancher sur un client MCP comme Claude Desktop. Le dossier experiments/MINE contient les instructions du benchmark du même nom, et un jeu de données est publié sur Hugging Face sous belindamo/wiki_qa_kggen.
Ce que la documentation ne dit pas sur la qualité du clustering
Le point faible de l'approche est aussi son argument principal. Le clustering d'entités et d'arêtes repose sur le modèle, et le README ne décrit ni la méthode employée, ni les seuils, ni la façon de corriger un cluster erroné. Les noms de versions récentes du dépôt suggèrent d'ailleurs que le sujet bouge : une version est intitulée MINE-deduplication-scikitlearn-vs-faiss, ce qui indique une comparaison entre deux implémentations de dédoublonnage. Autrement dit, le mécanisme de réconciliation n'est pas figé. Conséquence pratique : sur un domaine où deux entités proches ne doivent surtout pas être fusionnées (deux personnes homonymes, deux versions d'un même produit), le clustering automatique peut créer des erreurs silencieuses. Le graphe reste syntaxiquement valide, les triplets sont bien formés, mais la sémantique est fausse. Le README ne présente aucune option pour inspecter ou verrouiller un cluster avant fusion. Sur un texte court et propre, ce risque est faible. Sur des milliers de morceaux, il devient le principal facteur d'erreur, bien avant la qualité du modèle.
Face à un pipeline RAG classique
L'alternative la plus directe n'est pas un autre outil de graphe, c'est l'absence de graphe. Un pipeline RAG standard découpe le texte en segments, calcule des embeddings, et retrouve les passages proches d'une question. La différence d'approche est nette. Le RAG par embeddings ne construit aucune structure explicite : il rapproche des vecteurs, et la relation entre deux passages reste implicite, noyée dans une distance. kg-gen produit des triplets nommés, du type ('France', 'has capital', 'Paris'), qui sont lisibles, filtrables et vérifiables un par un. En contrepartie, il faut un appel LLM par morceau de texte plus les appels de clustering, là où un index vectoriel se construit en une passe d'encodage. Le coût et la latence ne sont pas du même ordre. Pour une base documentaire volumineuse et stable, un index vectoriel reste plus économique. Pour un corpus où l'on veut interroger les relations entre concepts, ou générer des données d'entraînement structurées, le graphe apporte quelque chose que la similarité ne donne pas. Les deux peuvent coexister : le README cite justement l'aide au RAG comme premier cas d'usage.
Coût de maintenance et licence
Le dépôt est actif : le dernier push indiqué est le 24 mars 2026, et trois versions ont été publiées entre octobre et novembre 2025. Ces versions sont des jeux d'évaluation et des comparaisons d'implémentations, pas des correctifs d'API. Cela suggère un projet en phase d'expérimentation, où les choix internes peuvent encore changer. La dépendance à LiteLLM et à DSPy est le principal poste de maintenance : une rupture dans l'un de ces deux paquets se répercute directement sur kg-gen, et l'utilisateur n'a pas de contrôle dessus. La licence n'est pas identifiable dans le matériel fourni. C'est un point bloquant pour toute intégration dans un produit distribué : il faut consulter le fichier LICENSE du dépôt avant de vous engager, et vérifier au passage les conditions des modèles que vous appelez, qui sont distinctes de celles du code. Le README ne donne aucune indication sur ce sujet.
Conclusion éditoriale
kg-gen convient à qui veut un graphe d'entités et de relations à partir de texte déjà propre, avec un modèle au choix via LiteLLM, et qui accepte de vérifier lui-même la licence et la qualité du clustering. À éviter si le texte source est bruité ou si le budget d'appels LLM est serré. Avant de vous engager, lancez python tests/test_basic.py sur un échantillon de vos propres données et regardez les clusters produits.
Notes de la communauté