<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Large Language Model &#8211; Smals Research</title>
	<atom:link href="https://www.smalsresearch.be/tag/large-language-model/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.smalsresearch.be</link>
	<description></description>
	<lastBuildDate>Tue, 21 Apr 2026 10:41:55 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.smalsresearch.be/wp-content/uploads/2026/01/cropped-cropped-Smals_Research-32x32.png</url>
	<title>Large Language Model &#8211; Smals Research</title>
	<link>https://www.smalsresearch.be</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Ingestion van ongestructureerde data: hoe maak je automatisch een graph op basis van tekst?</title>
		<link>https://www.smalsresearch.be/ingestion-van-ongestructureerde-data-graph/</link>
		
		<dc:creator><![CDATA[Pierre Leleux]]></dc:creator>
		<pubDate>Mon, 06 Oct 2025 09:00:00 +0000</pubDate>
				<category><![CDATA[[NL]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[data ingestion]]></category>
		<category><![CDATA[Knowledge Graph]]></category>
		<category><![CDATA[Large Language Model]]></category>
		<category><![CDATA[methodology]]></category>
		<category><![CDATA[Natural Language Processing]]></category>
		<guid isPermaLink="false">/?p=24036</guid>

					<description><![CDATA[Dit artikel gaat in op de manieren waarop een graph kan worden verkregen op basis van tekstuele data, de verschillende soorten graphs die kunnen worden geëxtraheerd en de tools die vaak worden gebruikt.]]></description>
										<content:encoded><![CDATA[
<p><a href="/ingestion-donnees-non-structurees-vers-graphe/"><em>Version en Français</em></a></p>
<p>Graphs, en meer bepaald knowledge graphs, maken het mogelijk om <a href="/graphtechnologieen-toepassingen-en-tools-2/">informatie op een gestructureerde manier weer te geven</a>. Zo krijgt een persoon een visuele samenvatting van de inhoud van een of meerdere documenten en kan een machine deze structuur gebruiken om bijvoorbeeld de inhoud ervan te analyseren (met behulp van <a href="/graphtechnologieen-toepassingen-en-tools/">graphalgoritmen</a>) en/of redeneringen te maken op basis van de graph (bijvoorbeeld in het kader van <a href="/graphrag-naar-een-knowledge-graph-augmented-generatie/">een graphRAG-toepassing</a> of om impliciete informatie te ontdekken (af te leiden)).</p>
<p>Dit artikel gaat in op de manieren waarop een graph kan worden verkregen op basis van tekstuele data, de verschillende soorten graphs die kunnen worden geëxtraheerd en de tools die vaak worden gebruikt, afhankelijk van het type extractie dat men wil uitvoeren.</p>
<p>Aangezien grote taalmodellen (LLM&#8217;s) bijzonder geschikt zijn voor tekstverwerking, zal dit artikel zich voornamelijk richten op de presentatie van LLM-gebaseerde benaderingen en vervolgens kort ingaan op verschillende alternatieve benaderingen.</p>



<h2 class="wp-block-heading">Knowledge graphs: een kort overzicht</h2>



<p>Een graph is een structuur die bestaat uit een reeks nodes en bogen (die paren van nodes met elkaar verbinden). Een knowledge graph voegt een extra semantische laag toe aan een klassieke graph, waarbij elke node een concept vertegenwoordigt (entiteit, persoon, enz.) en elke boog een relatie tussen twee concepten vertegenwoordigt (“werkt voor”, “is bevriend met”, enz.). Het is dus een weergave van kennis in de vorm van een reeks onderling verbonden entiteiten. Meer details over de verschillende soorten graphs en de bijbehorende tools vindt u <a href="/graphtechnologieen-toepassingen-en-tools/">hier</a>.</p>



<h2 class="wp-block-heading">Voorbereiding van het documentcorpus</h2>



<p>Voor de eenvoud gaan we ervan uit dat de tekstdocumenten die worden gebruikt om de graph op te bouwen, correct zijn opgeschoond. Dit artikel is namelijk niet bedoeld om de voorbewerking van tekstdocumenten (scrapen van webpagina&#8217;s, extraheren van tekst uit pdf-bestanden, enz.) te bespreken, aangezien deze voorbewerking op zich al een uitgebreid onderwerp is dat ongetwijfeld een apart artikel verdient.</p>



<h3 class="wp-block-heading">Fragmentatie van de tekst in “chunks”</h3>



<p>Een belangrijke stap in de voorbereiding van tekstdata voordat entiteiten en relaties worden geëxtraheerd, is het opsplitsen van de tekst in fragmenten (meestal ‘chunks’ genoemd). We hebben het concept van chunking al meerdere keren besproken in <a href="/databeheer-voor-generatieve-ai-toepassingen-kernbegrippen/">vorige blogposts</a>. Wanneer een document te lang is (meer dan enkele paragrafen), is het raadzaam om het op te splitsen in chunks (tekstfragmenten van redelijke omvang) die één voor één door de LLM worden verwerkt. Deze procedure maakt het mogelijk om de hoeveelheid informatie in elke chunk te beperken, zodat deze niet te veel entiteiten en relaties bevat die moeten worden geëxtraheerd. Deze opsplitsing in chunks kan op verschillende manieren gebeuren, hetzij op basis van het aantal woorden in de chunk, hetzij op basis van een vooraf gedefinieerd scheidingsteken (bijvoorbeeld een regeleinde dat het einde van de paragraaf aangeeft).</p>



<h2 class="wp-block-heading">De informatie weergeven of de structuur weergeven</h2>



<p>Laten we beginnen met de twee belangrijkste soorten graphs die kunnen worden geconstrueerd op basis van een reeks tekstdocumenten.</p>
<p>De eerste is een graph die de structuur van het document weergeeft (<em>document structure graph</em>), en niet de informatie die in de tekst staat. Bijvoorbeeld door de chunks te koppelen aan het document waaruit ze zijn gehaald en de volgorde waarin ze in het document voorkomen:</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2025/09/Document_structure_graph.png"><img fetchpriority="high" decoding="async" width="939" height="527" src="/wp-content/uploads/2025/09/Document_structure_graph.png" alt="" class="wp-image-23750" srcset="https://www.smalsresearch.be/wp-content/uploads/2025/09/Document_structure_graph.png 939w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Document_structure_graph-300x168.png 300w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Document_structure_graph-768x431.png 768w" sizes="(max-width: 939px) 100vw, 939px" /></a><figcaption class="wp-element-caption">Figuur 1: Graph die de structuur van een eenvoudig document weergeeft</figcaption></figure>



<p>Dit type graph kan ook worden verrijkt door relaties toe te voegen tussen semantisch vergelijkbare chunks of, indien van toepassing, door de hiërarchische organisatie van het document weer te geven in secties, subsecties, enz. Dit gebeurt via nodes die de secties/subsecties vertegenwoordigen en relaties van het type “HAS_SECTION”, “HAS_SUBSECTION”, evenals relaties die de volgorde van de secties/subsecties aangeven. Zodra de graph is opgebouwd, kan deze bijvoorbeeld worden gebruikt in RAG-toepassingen voor indexeringsdoeleinden om context te bieden aan de gebruikte chunks (zie <a href="/graphrag-naar-een-knowledge-graph-augmented-generatie/">onze blogpost over graphRAG</a>).</p>
<p>Het tweede type graph bestaat uit het opnemen van de informatie in de documenten in de vorm van nodes en relaties:</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2025/09/Domain_graph.png"><img decoding="async" width="877" height="179" src="/wp-content/uploads/2025/09/Domain_graph.png" alt="" class="wp-image-23751" srcset="https://www.smalsresearch.be/wp-content/uploads/2025/09/Domain_graph.png 877w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Domain_graph-300x61.png 300w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Domain_graph-768x157.png 768w" sizes="(max-width: 877px) 100vw, 877px" /></a><figcaption class="wp-element-caption">Figuur 2: Voorbeeld van informatie-extractie</figcaption></figure>



<p>In het kader van deze blogpost zullen we ons concentreren op dit tweede type graph. Merk op dat beide benaderingen elkaar niet uitsluiten. Als men voor het tweede type graph kiest, is het trouwens vaak nuttig om ook de documentstructuur weer te geven. Zo kan men indien nodig teruggaan naar de bron van de informatie in de graph.</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2025/09/Graph_combined.png"><img decoding="async" width="896" height="674" src="/wp-content/uploads/2025/09/Graph_combined.png" alt="" class="wp-image-23754" srcset="https://www.smalsresearch.be/wp-content/uploads/2025/09/Graph_combined.png 896w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Graph_combined-300x226.png 300w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Graph_combined-768x578.png 768w" sizes="(max-width: 896px) 100vw, 896px" /></a><figcaption class="wp-element-caption">Figuur 3: Extractie van structuur en informatie</figcaption></figure>



<h2 class="wp-block-heading">Opbouw van een knowledge graph met behulp van een LLM</h2>



<p>Eerst zullen we de algemene procedure voor het aanmaken van een knowledge graph op basis van tekstdocumenten via LLM voorstellen, alvorens te bekijken hoe deze aan de eigen behoeften kan worden aangepast.</p>
<p>LLM&#8217;s ontvangen standaard tekst als input (prompt) en sturen tekst terug als output in reactie op de prompt. Afhankelijk van de instructies bieden LLM&#8217;s echter de mogelijkheid om <strong><em>gestructureerde outputs</em></strong> te genereren, zoals JSON-bestanden. Vaak wordt deze functionaliteit gebruikt als basis voor het extraheren van kennis naar een graph, omdat deze gestructureerde output systematisch kan worden verwerkt.</p>
<p>Een script (bv. Python) haalt de chunks op en stuurt ze een voor een naar de LLM door een gestructureerd antwoord op te leggen (bv. <a href="https://python.langchain.com/docs/how_to/structured_output/">LangChain met de methode <em>llm.with_structured_output()</em></a>), met instructies over de taak, het type informatie dat in de tekst moet worden gedetecteerd en de structuur van het verwachte antwoord in de output. De gestructureerde output (meestal in JSON) wordt vervolgens eenvoudigweg ontleed in Python om de door de LLM gedetecteerde informatie (nodes/relaties) op te halen, die vervolgens rechtstreeks aan de graph kan worden toegevoegd (via een databasedriver).</p>
<p>Interessant is dat LLM&#8217;s een grote verscheidenheid aan antwoorden kunnen geven en dat het gebruik van gestructureerde output niet altijd nodig is. In sommige gevallen is het nog steeds het eenvoudigst om de LLM te vragen zijn extracties te leveren in de vorm van queries (bijvoorbeeld queries die de gedetecteerde nodes/relaties direct toevoegen), die als zodanig kunnen worden uitgevoerd, of in de vorm van RDF triples.</p>
<p>Na de algemene procedure, kijken we nu meer in detail naar de verschillende manieren om de informatie in de chunks binnen een graph te extraheren en weer te geven, te beginnen met de eenvoudigste benadering (thema-extractie) tot de meest complete (extractie van entiteiten en relaties).</p>



<h3 class="wp-block-heading">Thematische extractie</h3>



<p>In deze eerste benadering richten we ons op het opsporen en extraheren van de thema&#8217;s die in het document aan bod komen. We bouwen dus een thematische weergave van de verschillende documenten in het corpus om een structuur te verkrijgen van het type:</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2025/09/Theme_extraction.png"><img loading="lazy" decoding="async" width="872" height="178" src="/wp-content/uploads/2025/09/Theme_extraction.png" alt="" class="wp-image-23756" srcset="https://www.smalsresearch.be/wp-content/uploads/2025/09/Theme_extraction.png 872w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Theme_extraction-300x61.png 300w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Theme_extraction-768x157.png 768w" sizes="auto, (max-width: 872px) 100vw, 872px" /></a><figcaption class="wp-element-caption">Figuur 4: Ontologieschema van een thematische extractie</figcaption></figure>



<p>De graph heeft dus een lichte structuur en wordt gebruikt voor referentiedoeleinden, om gemakkelijk en snel documenten te identificeren die betrekking hebben op een (of meerdere) bepaald(e) onderwerp(en) van belang. Met dit type graph kunnen ook gelijkenissen tussen documenten (of tussen chunks) worden vastgesteld op basis van de gemeenschappelijke onderwerpen, of kan eenvoudigweg een schematische weergave worden gegeven van hun corpus van documenten en de thema&#8217;s die daarin aan bod komen.</p>
<p>Dit kan op een niet-gestuurde manier (de LLM vrij laten bepalen welke thema&#8217;s in de chunk aan bod komen) of op een gestuurde manier gebeuren (de LLM kiest een of meer thema&#8217;s uit een vooraf gedefinieerde lijst met thema&#8217;s die in de instructies van de prompt wordt gegeven).</p>



<h3 class="wp-block-heading">Extractie van <em>named entities</em></h3>



<p>De extractie (of herkenning) van <em>named entities</em> (<em>named-entity recognition</em>, vaak afgekort tot NER) is een bekend domein van natuurlijke taalverwerking (<em>natural language processing</em> (NLP)) dat bestaat uit het detecteren en categoriseren van entiteiten (personen, organisaties, plaatsen, enz.) die in een tekst worden genoemd. Het doel is dus vergelijkbaar met dat van thematische extractie: een graph maken door tekstfragmenten te koppelen aan de entiteiten die erin worden genoemd. We krijgen dus een graph met het volgende standaard schema:</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2025/09/Entity_extraction.png"><img loading="lazy" decoding="async" width="877" height="176" src="/wp-content/uploads/2025/09/Entity_extraction.png" alt="" class="wp-image-23752" srcset="https://www.smalsresearch.be/wp-content/uploads/2025/09/Entity_extraction.png 877w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Entity_extraction-300x60.png 300w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Entity_extraction-768x154.png 768w" sizes="auto, (max-width: 877px) 100vw, 877px" /></a><figcaption class="wp-element-caption">Figuur 5: Ontologieschema van een extractie van <em>named entities</em></figcaption></figure>



<p>Met dit type graph kunnen ook gelijkenissen tussen documenten (of tussen chunks) worden vastgesteld op basis van de entiteiten die ze gemeenschappelijk hebben. Het is interessant om op te merken dat deze extractie vergelijkbaar is met een volledige extractie (inclusief entiteiten en relaties, zie onderstaande paragraaf), behalve dat hier alleen de entiteiten worden geëxtraheerd en niet de relaties die ze met elkaar verbinden. Dit is een lichtere en gemakkelijker te implementeren oplossing wanneer een volledige extractie niet nodig is.</p>
<p>Dit soort extractie kan gemakkelijk worden uitgevoerd met behulp van een LLM met gestructureerde outputs. Met het <code>pydantic</code>-pakket kunnen op maat gemaakte templates worden gemaakt voor de verwachte outputstructuur. Bijvoorbeeld:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#000000;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>from pydantic import BaseModel, Field
from typing import List
class Entity(BaseModel):
    category: str = Field(description="The category of the entity.")
    name: str = Field(description="The name of the entity.")
class Extraction(BaseModel):
    entityList: List&#91;Entity&#93; = Field(description="The list of extracted entities.")
structured_llm = llm.with_structured_output(Extraction)
extracted=structured_llm.invoke(myPrompt)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #AF00DB">from</span><span style="color: #000000"> pydantic </span><span style="color: #AF00DB">import</span><span style="color: #000000"> BaseModel, Field</span></span>
<span class="line"><span style="color: #AF00DB">from</span><span style="color: #000000"> typing </span><span style="color: #AF00DB">import</span><span style="color: #000000"> List</span></span>
<span class="line"><span style="color: #0000FF">class</span><span style="color: #000000"> </span><span style="color: #267F99">Entity</span><span style="color: #000000">(</span><span style="color: #267F99">BaseModel</span><span style="color: #000000">):</span></span>
<span class="line"><span style="color: #000000">    category: </span><span style="color: #267F99">str</span><span style="color: #000000"> = Field(</span><span style="color: #001080">description</span><span style="color: #000000">=</span><span style="color: #A31515">&quot;The category of the entity.&quot;</span><span style="color: #000000">)</span></span>
<span class="line"><span style="color: #000000">    name: </span><span style="color: #267F99">str</span><span style="color: #000000"> = Field(</span><span style="color: #001080">description</span><span style="color: #000000">=</span><span style="color: #A31515">&quot;The name of the entity.&quot;</span><span style="color: #000000">)</span></span>
<span class="line"><span style="color: #0000FF">class</span><span style="color: #000000"> </span><span style="color: #267F99">Extraction</span><span style="color: #000000">(</span><span style="color: #267F99">BaseModel</span><span style="color: #000000">):</span></span>
<span class="line"><span style="color: #000000">    entityList: List&#91;Entity&#93; = Field(</span><span style="color: #001080">description</span><span style="color: #000000">=</span><span style="color: #A31515">&quot;The list of extracted entities.&quot;</span><span style="color: #000000">)</span></span>
<span class="line"><span style="color: #000000">structured_llm = llm.with_structured_output(Extraction)</span></span>
<span class="line"><span style="color: #000000">extracted=structured_llm.invoke(myPrompt)</span></span></code></pre></div>



<p> </p>
<p>In dit eenvoudige voorbeeld wordt de LLM gevraagd om een gestructureerde output van het type “Extraction” terug te geven, met als attribuut “entityList”, een lijst van “Entity”-objecten “ die net daarvoor zijn gedefinieerd.</p>
<p>Het is interessant om op te merken dat dit type template kan worden uitgebreid wanneer we extra informatie willen extraheren of het type gedetecteerde entiteiten willen beperken. Als we bijvoorbeeld alleen entiteiten van het type “persoon” en “onderneming” willen detecteren, kan de template worden aangepast door de klassen “ Persoon” en “Onderneming&#8221; aan te maken, waarin de attributen worden opgesomd die voor elke instantie van deze entiteiten moeten worden geëxtraheerd, en door het veld ”entityList“ te vervangen door twee velden “personList” en ”enterpriseList&#8221; in het uiteindelijke object dat moet worden teruggegeven.</p>
<p>Het voordeel van het gebruik van de methode <code>with_structured_output</code> is dat LangChain automatisch controleert of de output van de LLM overeenkomt met de template.</p>



<h3 class="wp-block-heading">Extractie van entiteiten en relaties</h3>



<p>Het doel hier is het bouwen van een graph die de kennis in het document of de documenten weergeeft in de vorm van onderling verbonden entiteiten (nodes) en relaties. Dit is de meest uitgebreide (en meest ingewikkelde) taak die we in detail zullen bekijken.</p>
<p>Laten we het volgende stukje tekst nemen om te illustreren wat voor soort extractie we hier willen uitvoeren:</p>
<p><em>“The San Fransisco-based 9th U.S. Circuit Court of Appeals rejected the legal challenge by the Federal Trade Commission to Microsoft’s $69</em><em> </em><em>billion acquisition of Activision Blizzard, the developer of </em><em>“</em><em>Call of Duty.</em><em>”</em><em> A three</em><em>‑</em><em>judge panel unanimously upheld a lower court</em><em>’</em><em>s decision denying a preliminary injunction, finding that the FTC had not demonstrated a likelihood of success in proving the merger would harm competition. The acquisition, completed in late</em><em> </em><em>2023 following UK regulatory approval, is the largest ever in the video gaming industry.”<br /></em>(Source: adapted from <a href="https://www.reuters.com/legal/microsoft-wins-ftc-appeal-challenging-69-bln-activision-blizzard-deal-2025-05-07/">Reuters, 2025</a>).</p>
<p>Zodra de informatie is geëxtraheerd, is dit een voorbeeld van een graph die op basis van deze tekst kan worden gemaakt:</p>



<figure class="wp-block-image aligncenter size-large"><a href="/wp-content/uploads/2025/09/Full_Extracted_KG.png"><img loading="lazy" decoding="async" width="1024" height="537" src="/wp-content/uploads/2025/09/Full_Extracted_KG-1024x537.png" alt="" class="wp-image-23761" srcset="https://www.smalsresearch.be/wp-content/uploads/2025/09/Full_Extracted_KG-1024x537.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Full_Extracted_KG-300x157.png 300w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Full_Extracted_KG-768x402.png 768w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Full_Extracted_KG.png 1330w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Figuur 6: Voorbeeld van extractie uit een tekst</figcaption></figure>



<p>Dit type extractie kan op veel verschillende manieren worden uitgevoerd. Het volgende deel is speciaal gewijd aan de verschillende benaderingen om een volledige extractie uit te voeren, en aan de voor- en nadelen daarvan.</p>



<h2 class="wp-block-heading">Welke benaderingen zijn er voor het extraheren van entiteiten en relaties?</h2>



<h3 class="wp-block-heading">Handmatige extractie versus speciale tools</h3>



<p>Een dergelijke graph kan manueel worden opgebouwd volgens de techniek die in het vorige deel werd voorgesteld (een prompt met instructies en de chunk naar de LLM sturen, de gestructureerde output ophalen en ontleden, en vervolgens de graph bijwerken via queries), ofwel biedt LangChain een tool aan om deze verschillende taken te automatiseren via de <a href="https://python.langchain.com/api_reference/experimental/graph_transformers/langchain_experimental.graph_transformers.llm.LLMGraphTransformer.html">LLM Graph Transformer</a>.</p>
<p>Deze tool vereenvoudigt de procedure door de instructies aan de LLM, het opstellen van de template en de verwerking van de gestructureerde output voor zijn rekening te nemen. De tool biedt verschillende instelmogelijkheden, zoals de mogelijkheid om de soorten nodes die gedetecteerd moeten worden te beperken (bv. alleen nodes van het type “Person”, “Company” en “Location”), de soorten relaties te beperken of de instructieprompt aan te passen.</p>
<p>Bovendien geeft een <code>LLMGraphTransformer</code>-instantie een lijst terug met objecten van het type <code>GraphDocument</code>, die de gedetecteerde nodes en relaties bevat en die direct kan worden gebruikt door verschillende LangChain-drivers naar graph-gerichte databases (zoals Memgraph, TigerGraph, Neo4j, enz.), om de geëxtraheerde entiteiten en relaties direct in de graph te importeren.</p>
<p>Hieronder volgt een voorbeeld van het extraheren van data uit een lijst met chunks met behulp van de <code>LLMGraphTransformer</code>-tool, gevolgd door het importeren van de entiteiten en relaties naar Neo4j:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#000000;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>doc_transformer=LLMGraphTransformer(llm=llm)
graph_docs=doc_transformer.convert_to_graph_documents(listOfChunks)

from langchain_neo4j import Neo4jGraph
graph=Neo4jGraph(
    url='XXXXX',
    username='YYYYY',
    password='ZZZZZ'
)
graph.add_graph_documents(graph_docs)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #000000">doc_transformer=LLMGraphTransformer(</span><span style="color: #001080">llm</span><span style="color: #000000">=llm)</span></span>
<span class="line"><span style="color: #000000">graph_docs=doc_transformer.convert_to_graph_documents(listOfChunks)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #AF00DB">from</span><span style="color: #000000"> langchain_neo4j </span><span style="color: #AF00DB">import</span><span style="color: #000000"> Neo4jGraph</span></span>
<span class="line"><span style="color: #000000">graph=Neo4jGraph(</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">url</span><span style="color: #000000">=</span><span style="color: #A31515">&#39;XXXXX&#39;</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">username</span><span style="color: #000000">=</span><span style="color: #A31515">&#39;YYYYY&#39;</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">password</span><span style="color: #000000">=</span><span style="color: #A31515">&#39;ZZZZZ&#39;</span></span>
<span class="line"><span style="color: #000000">)</span></span>
<span class="line"><span style="color: #000000">graph.add_graph_documents(graph_docs)</span></span></code></pre></div>



<p><br />Er bestaat ook een gratis alternatief voor Neo4j, waarvoor geen programmering nodig is: de <a href="https://llm-graph-builder.neo4jlabs.com/">Neo4j LLM Knowledge Graph Builder</a>. Deze online tool neemt alle stappen voor zijn rekening, van de voorbewerking van documenten (pdf, webpagina) tot de opbouw van de resulterende knowledge graphs, en biedt tal van personaliseringsopties (het beperken van de te detecteren entiteit- en/of relatietypes, enz.). Zie <a href="https://neo4j.com/labs/genai-ecosystem/llm-graph-builder/">hier</a> voor meer details.</p>



<h3 class="wp-block-heading">Vrije extractie versus begeleide extractie</h3>



<p>Merk op dat als er met deze tools geen beperkingen (op de soorten entiteiten en relaties die moeten worden geëxtraheerd) worden gedefinieerd, ze in alle vrijheid alle informatie zullen extraheren die ze kunnen vinden. Dit soort “blinde” extractie kan eventueel worden gebruikt voor kleine documenten, of in gevallen waarin men van tevoren niet weet wat voor soort structuur men kan extraheren, maar het is over het algemeen beter om van tevoren de gewenste ontologie voor de graph vast te leggen.</p>
<p>Vrije extractie is namelijk vaak een probleem om verschillende redenen:</p>
<p><strong>Explosie van entiteitstypen en relaties </strong></p>
<p>Naarmate de omvang of het aantal documenten toeneemt, bestaat het risico dat er al snel een zeer groot aantal verschillende soorten entiteiten en relaties in de graph terechtkomen, waardoor deze moeilijk te gebruiken kan worden (bijvoorbeeld voor RAG-toepassingen).</p>
<p><strong>Inconsistentie van types</strong></p>
<p>Bij gebrek aan een ontologie die een duidelijke nomenclatuur biedt, bestaat het risico van inconsistentie in de gedetecteerde types (een bedrijf kan bijvoorbeeld worden gelabeld als “Enterprise”, een ander als “Company” en een derde als “Organization”). In de praktijk kunnen dit soort problemen achteraf worden opgelost door alle soorten nodes op te sommen en semantisch verwante soorten te groeperen.</p>
<p><strong>Problemen met reïficatie</strong></p>
<p>Per definitie verbindt een relatie in een graph een node met een ander node. Er kan een probleem ontstaan wanneer een entiteit moet worden gekoppeld aan informatie die in de vorm van een relatie is gemodelleerd. Om het probleem te illustreren, nemen we als voorbeeld de overname van Activision Blizzard door Microsoft. Stel dat een eerste stuk tekst alleen deze overname vermeldt zonder verdere details, dan wordt deze hoogstwaarschijnlijk opgeslagen in de vorm:</p>
<p><code>(Microsoft)-[ACQUIRES]-&gt;(Activision Blizzard)</code></p>
<p>Stel dat de volgende chunk de informatie “<em>The FTC challenged the acquisition&#8230;</em>” vermeldt, dan hebben we een probleem omdat het niet meer mogelijk is om</p>
<p><code>(FTC)-[CHALLENGES]-&gt;(Acquisition)</code></p>
<p>te modelleren, aangezien de overname eerder werd gemodelleerd in de vorm van een relatie en niet als een node waarnaar door een relatie kan worden verwezen.</p>
<p>In dit geval kan de relatie bijvoorbeeld worden verwijderd en vervolgens worden vervangen door een node, zodat ernaar kan worden verwezen:</p>
<p><code>(Microsoft)-[INITIATES]-&gt;(Acquisition)-[TARGETS]-&gt;(Activision Blizzard)</code></p>
<p>Dit proces, dat <strong>reïficatie</strong> wordt genoemd, verloopt niet automatisch en vereist een extra verrijkingsstap om mogelijke verwijzingen naar informatie die in de vorm van relaties is gemodelleerd, op te sporen en indien nodig te reïficeren.</p>



<h2 class="wp-block-heading">Enkele alternatieven voor LLM&#8217;s</h2>



<p>Nu we een reeks benaderingen hebben bekeken die specifiek op LLM&#8217;s zijn gebaseerd, worden in dit gedeelte enkele alternatieve tools voorgesteld die zijn gebaseerd op klassieke NLP-methoden.</p>
<p>Voor wie alleen <em>named entities</em> wil extraheren, is <a href="/named-entity-recognition-une-application-du-nlp-utile/">hier een blogpost over dit onderwerp</a> te vinden, evenals een <a href="/pii-filtering/">voorbeeld van de toepassing van NER bij PII-filtering</a>.  Er zijn tal van vooraf getrainde NER-modellen beschikbaar op platforms zoals <a href="https://huggingface.co/models">Hugging Face</a>.</p>
<p>Het extraheren van entiteiten en relaties kan doorgaans op twee verschillende manieren gebeuren:</p>



<ul class="wp-block-list">
<li><strong>Extractie in twee afzonderlijke stappen</strong>: eerst wordt een NER gebruikt voor het detecteren en categoriseren van entiteiten, gevolgd door een extractie van relaties op basis van de tekst en de gedetecteerde entiteiten, om de relaties tussen deze entiteiten te bepalen. Enkele voorbeelden van tools voor het extraheren van relaties zijn <a href="https://github.com/thunlp/OpenNRE">openNRE</a>, <a href="https://github.com/alimirzaei/spacy-relation-extraction">spacy-relation-extraction</a> en <a href="https://github.com/jackboyla/GLiREL">GliREL</a>.</li>



<li><strong>End-to-end-extractie</strong>: tools die entiteiten en relaties in één stap extraheren, zoals <a href="https://nlp.stanford.edu/software/openie.html">OpenIE</a>, <a href="https://github.com/SapienzaNLP/relik">Relik</a>, <a href="https://github.com/Babelscape/rebel">REBEL</a> of <a href="https://www.diffbot.com/products/natural-language/">Diffbot</a> (commerciële oplossing).</li>
</ul>



<h2 class="wp-block-heading">Nagaan of de gedetecteerde gegevens conform zijn</h2>



<p>De grote kracht van LLM&#8217;s voor dit soort extractietaken is hun begrip van natuurlijke taal, waardoor de extractie kan worden gepersonaliseerd door de instructieprompt aan te passen. Als er bijvoorbeeld geen outputtemplate bestaat voor het gestructureerde antwoord (waar de LLM moeite mee kan hebben als de template te ingewikkeld wordt), is het mogelijk om ontologieconforme nodes en relaties te verkrijgen door de ontologie rechtstreeks in de instructieprompt te beschrijven, maar het is belangrijk om alert te blijven voor extracties. Er is namelijk geen garantie dat de LLM geen fouten maakt en geen niet-conforme relatie/entiteit als output teruggeeft.</p>
<p>In het algemeen geldt dat wanneer een LLM (of een andere tool) wordt gebruikt om automatisch informatie uit een tekst te extraheren naar een knowledge graph, het nuttig is om te controleren of datgene dat is geëxtraheerd wel degelijk in overeenstemming is met de ontologie en trouw is aan de informatie in de bron.</p>
<ol>
<li>Controleren of de extractie voldoet aan de ontologie</li>
</ol>
<p><a href="/shacl-logische-en-vormcontroles-met-kg-technologieen/">In een vorige blogpost</a> hebben we al vermeld dat het mogelijk is om de structuur en inhoud van een knowledge graph te valideren met behulp van de SHACL-standaard. Dit is een taal die de verschillende beperkingen bevat die van toepassing zijn op een knowledge graph. Het is mogelijk om ofwel een definitieve validatie van de graph uit te voeren, om te controleren of de inhoud daadwerkelijk voldoet aan de in SHACL geformuleerde beperkingen (en de data die deze beperkingen overtreden op te sommen), ofwel deze validaties transactioneel uit te voeren bij elke nieuwe toevoeging van informatie, om elke nieuwe onrechtmatige toevoeging te weigeren. Hoewel SHACL oorspronkelijk bedoeld was voor graphs in RDF, kunnen sommige databases toch SHACL-beperkingen interpreteren en de graph valideren, zoals <a href="https://neo4j.com/labs/neosemantics/">Neo4j met het <em>neosemantics</em> package (n10s)</a>.</p>
<ol start="2">
<li>Nagaan of de extractie correct is</li>
</ol>
<p>Het risico van automatische extractie is dat informatie die in de graph wordt ingevoerd feitelijk onjuist is ten opzichte van de oorspronkelijke tekst, wat in het bijzonder problematisch kan zijn als deze graph wordt gebruikt als potentiële informatiebron (bijvoorbeeld voor een graphRAG-toepassing). Er kunnen verschillende benaderingen worden gevolgd. De eenvoudigste is een menselijke controle van de geëxtraheerde informatie, maar dit kan moeilijk of zelfs onhaalbaar worden wanneer de documenten te lang/talrijk worden. De andere aanpak bestaat erin een tweede LLM te gebruiken om te controleren wat uit elk fragment is geëxtraheerd. Zoals we <a href="/praktische-ervaringen-met-automatische-rag-evaluatie/">in de post over de evaluatie van LLM&#8217;s</a> hebben vermeld, is het voor LLM&#8217;s gemakkelijker om achteraf fouten op te sporen dan ze te vermijden.</p>



<h2 class="wp-block-heading">Conclusie</h2>



<p>Deze technologieën zijn weliswaar krachtig, maar nooit perfect. Behalve vrije (blinde) extractie, die kan resulteren in een moeilijk bruikbare graph, vormt het opstellen van een knowledge graph op basis van tekst een taak die veel werk vereist. En dit zowel vooraf (voorbewerking van teksten, opstellen van een ontologie voor de graph op basis van de inhoud van de tekst), als achteraf (validatie van de structuur van de graph ten opzichte van de ontologie en controle van de juistheid en betrouwbaarheid van de inhoud).</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p><em>Dit is een ingezonden bijdrage van Pierre Leleux, data scientist et network data analyst bij Smals Research. Dit artikel werd geschreven in eigen naam en neemt geen standpunt in namens Smals.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Ingestion de données non-structurées&#160;: comment créer un graphe automatiquement à partir de texte&#160;?</title>
		<link>https://www.smalsresearch.be/ingestion-donnees-non-structurees-vers-graphe/</link>
		
		<dc:creator><![CDATA[Pierre Leleux]]></dc:creator>
		<pubDate>Thu, 11 Sep 2025 09:00:00 +0000</pubDate>
				<category><![CDATA[[FR]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[data ingestion]]></category>
		<category><![CDATA[Knowledge Graph]]></category>
		<category><![CDATA[Large Language Model]]></category>
		<category><![CDATA[methodology]]></category>
		<category><![CDATA[Natural Language Processing]]></category>
		<guid isPermaLink="false">/?p=23748</guid>

					<description><![CDATA[Cet article s’intéresse aux façons dont une représentation graphe peut être obtenue à partir de données textuelles, les différents types de graphe qui peuvent être extraits, et les outils fréquemment utilisés.]]></description>
										<content:encoded><![CDATA[
<p><em><a href="/ingestion-van-ongestructureerde-data-graph/">Nederlandstalige versie</a></em></p>
<p>Les graphes, et plus particulièrement les graphes de connaissances, permettent de <a href="/graphes_applications_et_outils_2/">représenter l’information de manière structurée</a>. Cela permet, pour un humain, d’avoir une représentation (synthèse visuelle) du contenu d’un ou de plusieurs documents et, pour une machine, d’exploiter cette structure afin, par exemple, d’en analyser le contenu (via l’utilisation <a href="/graphes_applications_et_outils/">d’algorithmes de graphe</a>) et/ou de raisonner sur le graphe (par exemple dans le cadre d’une <a href="/graphrag-vers-une-generation-augmentee-par-les-graphes-de-connaissances/">application de graphRAG</a> ou pour découvrir (inférer) de l’information implicite).</p>
<p>Cet article s’intéresse aux façons dont une représentation graphe peut être obtenue à partir de données textuelles, les différents types de graphe qui peuvent être extraits, et les outils fréquemment utilisés suivant le type d’extraction que l’on souhaite effectuer.</p>
<p>Il est à noter que, puisque les grands modèles de langage (LLM) sont particulièrement adaptés pour le traitement de texte, cet article se concentrera principalement sur la présentation d’approches basées sur les LLM et discutera rapidement, dans un second temps, de différentes approches alternatives.</p>



<h2 class="wp-block-heading">Les graphes de connaissances&nbsp;: un rappel rapide</h2>



<p>Un graphe est une structure composée d’un ensemble de nœuds et d’arcs (qui lient des paires de nœuds). Un graphe de connaissances ajoute une couche sémantique supplémentaire à un graphe classique, où chaque nœud représente un concept (entité, personne, etc.) et chaque arc représente une relation entre deux concepts (« travaille pour », « est ami avec », etc.). Il s’agit donc d’une représentation de la connaissance sous forme d’un ensemble d’entités interconnectées. Plus de détails sur les différentes formes de graphes et les outils associés peuvent être trouvés <a href="/graphes_applications_et_outils/">ici</a>.</p>



<h2 class="wp-block-heading">Préparation du corpus de documents</h2>



<p>Il est à noter que, pour des raisons de simplicité, nous faisons l’hypothèse que les documents de texte utilisés pour construire le graphe ont été correctement nettoyés. En effet, cet article n’a pas pour but de discuter de l’aspect relatif au prétraitement des documents de texte (scrapping de pages web, extraction de texte à partir de fichiers pdf, etc.), car ce prétraitement est déjà, en tant que tel, un vaste sujet méritant sans doute un article dédié.</p>



<h3 class="wp-block-heading">Fragmentation du texte en « chunks »</h3>



<p>Une étape importante de la préparation des données de texte avant d’en extraire les entités et relations est la division du texte en fragments (généralement appelés « chunks »). Nous avons déjà mentionné le concept de chunking à plusieurs reprises dans <a href="/ingestion-de-donnees-pour-les-applications-d-ia-generative/">de précédents articles</a>. Si un document est trop long (plus de quelques paragraphes…) il convient de le séparer en chunks (fragments de texte de taille raisonnable) qui seront traités un à un par le LLM. Cette procédure permet de limiter la quantité d’information présente dans chaque chunk, pour éviter que celui-ci ne contienne une quantité trop importante d’entités et de relations à extraire. Cette séparation en chunks peut se faire de différentes manières, soit sur la base du nombre de mots dans le chunk, soit sur la base d’un séparateur prédéfini (par exemple&nbsp;: un passage à la ligne qui indiquerait la fin du paragraphe).</p>



<h2 class="wp-block-heading">Représenter l’information ou représenter la structure</h2>



<p>Commençons par regarder les deux principaux types de graphe qui peuvent être construits à partir d’un ensemble de documents textuels.</p>
<p>Le premier est un graphe qui va présenter la structure du document (<em>document structure graph</em>), et non pas l’information qui est contenue dans le texte. Par exemple, en reliant les chunks au document d’où ils sont tirés ainsi que l’ordre d’apparition de ceux-ci dans le document&nbsp;:</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2025/09/Document_structure_graph.png"><img loading="lazy" decoding="async" width="939" height="527" src="/wp-content/uploads/2025/09/Document_structure_graph.png" alt="" class="wp-image-23750" srcset="https://www.smalsresearch.be/wp-content/uploads/2025/09/Document_structure_graph.png 939w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Document_structure_graph-300x168.png 300w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Document_structure_graph-768x431.png 768w" sizes="auto, (max-width: 939px) 100vw, 939px" /></a><figcaption class="wp-element-caption">Figure 1&nbsp;: Graphe représentant la structure d’un document simple</figcaption></figure>



<p>Ce type de graphe peut aussi être enrichi en ajoutant des relations entre chunks sémantiquement similaires ou, le cas échéant, en représentant l’organisation hiérarchique du document en sections, sous-sections, etc. Cela se fait via des nœuds représentant les sections/sous-sections et des relations de type « HAS_SECTION », « HAS_SUBSECTION », ainsi que des relations indiquant l’ordre des sections/sous-sections. Une fois le graphe construit, il peut par exemple être utilisé dans des applications de RAG à des fins d’indexation pour fournir du contexte aux chunks utilisés (voir <a href="/graphrag-vers-une-generation-augmentee-par-les-graphes-de-connaissances/">notre article sur le graphRAG</a>).</p>
<p>Le second type de graphe consiste à capturer l’information contenue dans les documents sous la forme de nœuds et de relations :</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2025/09/Domain_graph.png"><img loading="lazy" decoding="async" width="877" height="179" src="/wp-content/uploads/2025/09/Domain_graph.png" alt="" class="wp-image-23751" srcset="https://www.smalsresearch.be/wp-content/uploads/2025/09/Domain_graph.png 877w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Domain_graph-300x61.png 300w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Domain_graph-768x157.png 768w" sizes="auto, (max-width: 877px) 100vw, 877px" /></a><figcaption class="wp-element-caption">Figure 2&nbsp;: Exemple d&#8217;extraction d&#8217;informations</figcaption></figure>



<p>Dans le cadre de cet article, nous nous concentrerons sur ce second type de graphe. Il est à noter que les deux approches ne sont pas mutuellement exclusives. D’ailleurs, il est souvent utile, si l&#8217;on souhaite opter pour le deuxième type de graphe, de représenter également la structure des documents. Cela permet, si nécessaire, de pouvoir remonter à la source des informations présentes dans le graphe.</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2025/09/Graph_combined.png"><img loading="lazy" decoding="async" width="896" height="674" src="/wp-content/uploads/2025/09/Graph_combined.png" alt="" class="wp-image-23754" srcset="https://www.smalsresearch.be/wp-content/uploads/2025/09/Graph_combined.png 896w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Graph_combined-300x226.png 300w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Graph_combined-768x578.png 768w" sizes="auto, (max-width: 896px) 100vw, 896px" /></a><figcaption class="wp-element-caption">Figure 3&nbsp;: Extraction de structure et d&#8217;informations</figcaption></figure>



<h2 class="wp-block-heading">Construction d’un graphe de connaissances à l’aide d’un LLM</h2>



<p>Dans un premier temps, nous allons présenter la procédure générale à suivre pour la création d’un graphe de connaissances à partir de documents textuels via LLM, avant de voir comment l’adapter suivant ses besoins.</p>
<p>Les LLMs, par défaut, reçoivent en entrée du texte (prompt) et renvoient en sortie du texte généré en réponse au prompt. Cependant, suivant les instructions, les LLM offrent la possibilité de générer des <strong><em>outputs structurés</em></strong> tels que des fichiers JSON. C’est souvent sur la base de cette fonctionnalité que se base l’extraction de connaissances vers un graphe, car cet output structuré pourra être traité de façon systématique.</p>
<p>Un script (par ex. python) va récupérer les chunks et les envoyer un à un au LLM en imposant une réponse structurée (par ex. <a href="https://python.langchain.com/docs/how_to/structured_output/">langchain avec la méthode llm.with_structured_output()</a>), avec des instructions concernant la tâche, le genre d’information à détecter dans le texte, et la structure de la réponse attendue en sortie. L’output structuré (typiquement en JSON) est ensuite simplement décomposé en python afin de récupérer les informations (nœuds/relations) détectées par le LLM, qui peuvent ensuite être directement ajoutées au graphe (via un database driver).</p>
<p>Il est intéressant de noter que les LLM peuvent fournir une grande diversité de réponses, et l’utilisation d’une sortie structurée n’est pas forcément toujours nécessaire. Dans certains cas, le plus simple est encore de demander au LLM de fournir ses extractions sous la forme de requêtes (par exemple, de requêtes qui ajoutent directement les nœuds/relations détectées), qui peuvent être exécutées telles quelles, ou sous forme de triplets RDF.</p>
<p>Maintenant que nous avons vu la procédure générale, nous allons regarder plus en détail les différentes façons d’extraire et de représenter l’information contenue dans les chunks au sein d’un graphe, en commençant par l’approche la plus simple (extraction de thèmes) jusqu’à la plus complète (extraction d’entités et de relations).</p>



<h3 class="wp-block-heading">Extraction thématique</h3>



<p>Dans cette première approche, on va s’intéresser à la détection et l’extraction des thèmes abordés dans le document. On y construit donc une représentation thématique des différents documents du corpus de sorte à obtenir une structure de type&nbsp;:</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2025/09/Theme_extraction.png"><img loading="lazy" decoding="async" width="872" height="178" src="/wp-content/uploads/2025/09/Theme_extraction.png" alt="" class="wp-image-23756" srcset="https://www.smalsresearch.be/wp-content/uploads/2025/09/Theme_extraction.png 872w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Theme_extraction-300x61.png 300w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Theme_extraction-768x157.png 768w" sizes="auto, (max-width: 872px) 100vw, 872px" /></a><figcaption class="wp-element-caption">Figure 4&nbsp;: Schéma d’ontologie d’une extraction de thèmes</figcaption></figure>



<p>Le graphe a donc une structure légère et est utilisé à des fins de référencement, afin d&#8217;identifier facilement et rapidement les documents traitant d&#8217;un (ou plusieurs) sujet(s) d&#8217;intérêt donné(s). Ce type de graphe permet aussi d’établir des similarités entre documents (ou entre chunks) sur la base des sujets qu’ils ont en commun, ou simplement d’avoir une représentation schématique du corpus de documents et des thèmes qui y sont abordés.</p>
<p>Cela peut se faire soit de façon non-dirigée (laisser le LLM déterminer librement de la liste des thèmes abordés dans le chunk), soit dirigée (le LLM choisit un ou plusieurs thèmes parmi une liste prédéfinie de thèmes fournie dans les instructions du prompt).</p>



<h3 class="wp-block-heading">Extraction d’entités nommées</h3>



<p>L’extraction (ou reconnaissance) d’entités nommées (<em>named-entity recognition</em>, souvent abrégé en NER) est un domaine bien connu du traitement du langage naturel (<em>natural language processing</em> (NLP)) qui consiste à détecter et catégoriser les entités (personne, organisation, lieu, etc.) qui sont nommées dans un texte. L’objectif va donc être similaire à celui de l’extraction thématique&nbsp;: créer un graphe en liant les chunks de texte aux entités qui y sont mentionnées. Nous obtenons donc un graphe avec le schéma-type suivant&nbsp;:</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2025/09/Entity_extraction.png"><img loading="lazy" decoding="async" width="877" height="176" src="/wp-content/uploads/2025/09/Entity_extraction.png" alt="" class="wp-image-23752" srcset="https://www.smalsresearch.be/wp-content/uploads/2025/09/Entity_extraction.png 877w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Entity_extraction-300x60.png 300w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Entity_extraction-768x154.png 768w" sizes="auto, (max-width: 877px) 100vw, 877px" /></a><figcaption class="wp-element-caption">Figure 5&nbsp;: Schéma d’ontologie d’une extraction d’entités nommées</figcaption></figure>



<p>Ce type de graphe permet aussi d’établir des similarités entre documents (ou entre chunks) sur la base des entités qu’ils ont en commun. Il est intéressant de noter que cette extraction est similaire à une extraction complète (incluant entités et relations, voir section ci-dessous), si ce n’est qu’ici seules les entités sont extraites, et pas les relations qui les interconnectent. Il s’agit d’une solution plus légère et facile à mettre en place, lorsqu’une extraction complète n’est pas nécessaire.</p>
<p>Ce genre d’extraction peut se faire facilement par l’utilisation de LLM avec outputs structurés. Le package <code>pydantic</code> permet de créer des templates sur mesure pour la structure attendue en sortie. Par exemple&nbsp;:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#000000;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>from pydantic import BaseModel, Field
from typing import List
class Entity(BaseModel):
    category: str = Field(description="The category of the entity.")
    name: str = Field(description="The name of the entity.")
class Extraction(BaseModel):
    entityList: List&#91;Entity&#93; = Field(description="The list of extracted entities.")
structured_llm = llm.with_structured_output(Extraction)
extracted=structured_llm.invoke(myPrompt)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #AF00DB">from</span><span style="color: #000000"> pydantic </span><span style="color: #AF00DB">import</span><span style="color: #000000"> BaseModel, Field</span></span>
<span class="line"><span style="color: #AF00DB">from</span><span style="color: #000000"> typing </span><span style="color: #AF00DB">import</span><span style="color: #000000"> List</span></span>
<span class="line"><span style="color: #0000FF">class</span><span style="color: #000000"> </span><span style="color: #267F99">Entity</span><span style="color: #000000">(</span><span style="color: #267F99">BaseModel</span><span style="color: #000000">):</span></span>
<span class="line"><span style="color: #000000">    category: </span><span style="color: #267F99">str</span><span style="color: #000000"> = Field(</span><span style="color: #001080">description</span><span style="color: #000000">=</span><span style="color: #A31515">&quot;The category of the entity.&quot;</span><span style="color: #000000">)</span></span>
<span class="line"><span style="color: #000000">    name: </span><span style="color: #267F99">str</span><span style="color: #000000"> = Field(</span><span style="color: #001080">description</span><span style="color: #000000">=</span><span style="color: #A31515">&quot;The name of the entity.&quot;</span><span style="color: #000000">)</span></span>
<span class="line"><span style="color: #0000FF">class</span><span style="color: #000000"> </span><span style="color: #267F99">Extraction</span><span style="color: #000000">(</span><span style="color: #267F99">BaseModel</span><span style="color: #000000">):</span></span>
<span class="line"><span style="color: #000000">    entityList: List&#91;Entity&#93; = Field(</span><span style="color: #001080">description</span><span style="color: #000000">=</span><span style="color: #A31515">&quot;The list of extracted entities.&quot;</span><span style="color: #000000">)</span></span>
<span class="line"><span style="color: #000000">structured_llm = llm.with_structured_output(Extraction)</span></span>
<span class="line"><span style="color: #000000">extracted=structured_llm.invoke(myPrompt)</span></span></code></pre></div>



<p><br />Dans cet exemple simple, on demande au LLM de retourner une sortie structurée de type « Extraction », avec comme attribut « entityList » qui est une liste d’objets « Entity » définis juste avant.</p>
<p>Il est intéressant de noter que ce type de template peut être enrichi si l’on souhaite extraire des informations supplémentaires ou contraindre le type d’entités détectées. Par exemple, si l’on souhaite uniquement détecter des entités de type « personne » et « entreprise », le template peut être modifié en créant des classes « Personne » et « Entreprise », dans lesquelles on listera les attributs que l’on souhaite extraire pour chaque instance de ces entités, et en remplaçant le champs « entityList » par deux champs « personList » et « enterpriseList » dans l’objet final à retourner.</p>
<p>L’avantage d’utiliser la méthode <code>with_structured_output</code> est que langchain vérifiera automatiquement que la sortie du LLM est bien conforme au template.</p>



<h3 class="wp-block-heading">Extraction d’entités et de relations</h3>



<p>L’objectif ici est la construction d’un graphe qui va représenter la connaissance contenue au sein du ou des documents sous la forme d’entités (nœuds) interconnectées (relations). Il s’agit de la tâche la plus complète (et la plus compliquée), sur laquelle nous allons nous pencher le plus en détail.</p>
<p>Prenons le chunk de texte suivant, afin d’illustrer le genre d’extraction que nous souhaitons réaliser ici :</p>
<p><em>“The San Fransisco-based 9th U.S. Circuit Court of Appeals rejected the legal challenge by the Federal Trade Commission to Microsoft’s $69</em><em> </em><em>billion acquisition of Activision Blizzard, the developer of </em><em>“</em><em>Call of Duty.</em><em>”</em><em> A three</em><em>‑</em><em>judge panel unanimously upheld a lower court</em><em>’</em><em>s decision denying a preliminary injunction, finding that the FTC had not demonstrated a likelihood of success in proving the merger would harm competition. The acquisition, completed in late</em><em> </em><em>2023 following UK regulatory approval, is the largest ever in the video gaming industry.”<br /></em>(Source: adapted from <a href="https://www.reuters.com/legal/microsoft-wins-ftc-appeal-challenging-69-bln-activision-blizzard-deal-2025-05-07/">Reuters, 2025</a>).</p>
<p>Une fois l’information extraite, voici un exemple de graphe qu’il est possible de construire depuis ce texte :</p>



<figure class="wp-block-image aligncenter size-large"><a href="/wp-content/uploads/2025/09/Full_Extracted_KG.png"><img loading="lazy" decoding="async" width="1024" height="537" src="/wp-content/uploads/2025/09/Full_Extracted_KG-1024x537.png" alt="" class="wp-image-23761" srcset="https://www.smalsresearch.be/wp-content/uploads/2025/09/Full_Extracted_KG-1024x537.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Full_Extracted_KG-300x157.png 300w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Full_Extracted_KG-768x402.png 768w, https://www.smalsresearch.be/wp-content/uploads/2025/09/Full_Extracted_KG.png 1330w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Figure 6&nbsp;: Exemple d’extraction depuis un texte</figcaption></figure>



<p>Ce type d’extraction peut se faire de nombreuses façons différentes. La prochaine section sera spécialement dédiée aux différentes approches qui peuvent être adoptées pour réaliser une extraction complète, leurs avantages et inconvénients.</p>



<h2 class="wp-block-heading">Quelles approches pour réaliser une extraction d’entités et de relations&nbsp;?</h2>



<h3 class="wp-block-heading">Extraction manuelle VS outils dédiés</h3>



<p>La construction d’un graphe de ce type peut se faire de manière manuelle en suivant la technique présentée dans la section précédente (envoyer un prompt incluant les instructions et le chunk au LLM, récupérer et décomposer l’output structuré renvoyé en sortie, puis mettre à jour le graphe via requêtes), ou alors langchain propose un outil permettant d’automatiser ces différentes tâches via le <a href="https://python.langchain.com/api_reference/experimental/graph_transformers/langchain_experimental.graph_transformers.llm.LLMGraphTransformer.html">LLM Graph Transformer</a>.</p>
<p>Cet outil permet de simplifier la procédure, en prenant en charge les instructions au LLM, la construction du template et le traitement de la sortie structurée. Il offre plusieurs possibilités de personnalisation, comme la possibilité de restreindre les types de nœud que l’on souhaite détecter (par ex. uniquement des nœuds de type « Person », « Company » et « Location »), de restreindre les types de relation, ou encore de personnaliser le prompt d’instructions.</p>
<p>De plus, une instance <code>LLMGraphTransformer</code> renvoie en sortie liste d’objets de type <code>GraphDocument</code>, contenant les nœuds et relations détectés, qui est exploitable directement par plusieurs drivers langchain vers des bases de données orientées graphe (telles que Memgraph, TigerGraph, Neo4j, etc.), afin de réaliser directement l’importation des entités et relations extraites vers le graphe.</p>
<p>Ci-dessous, un exemple illustratif de l’extraction des données depuis une liste de chunks via l’outil <code>LLMGraphTransformer</code>, suivie de l’importation des entités et relations vers Neo4j&nbsp;:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#000000;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>doc_transformer=LLMGraphTransformer(llm=llm)
graph_docs=doc_transformer.convert_to_graph_documents(listOfChunks)

from langchain_neo4j import Neo4jGraph
graph=Neo4jGraph(
    url='XXXXX',
    username='YYYYY',
    password='ZZZZZ'
)
graph.add_graph_documents(graph_docs)</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki light-plus" style="background-color: #FFFFFF" tabindex="0"><code><span class="line"><span style="color: #000000">doc_transformer=LLMGraphTransformer(</span><span style="color: #001080">llm</span><span style="color: #000000">=llm)</span></span>
<span class="line"><span style="color: #000000">graph_docs=doc_transformer.convert_to_graph_documents(listOfChunks)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #AF00DB">from</span><span style="color: #000000"> langchain_neo4j </span><span style="color: #AF00DB">import</span><span style="color: #000000"> Neo4jGraph</span></span>
<span class="line"><span style="color: #000000">graph=Neo4jGraph(</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">url</span><span style="color: #000000">=</span><span style="color: #A31515">&#39;XXXXX&#39;</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">username</span><span style="color: #000000">=</span><span style="color: #A31515">&#39;YYYYY&#39;</span><span style="color: #000000">,</span></span>
<span class="line"><span style="color: #000000">    </span><span style="color: #001080">password</span><span style="color: #000000">=</span><span style="color: #A31515">&#39;ZZZZZ&#39;</span></span>
<span class="line"><span style="color: #000000">)</span></span>
<span class="line"><span style="color: #000000">graph.add_graph_documents(graph_docs)</span></span></code></pre></div>



<p><br />Il existe aussi une alternative gratuite pour Neo4j, qui ne requiert aucune programmation, le <a href="https://llm-graph-builder.neo4jlabs.com/">Neo4j LLM Knowledge Graph Builder</a>. Cet outil en ligne prend toutes les étapes en charge, en allant du prétraitement des documents (pdf, page web) jusqu’à la construction du graphe de connaissances résultant, et offre de multiples options de personnalisation (contraindre les types d’entité et/ou de relation à détecter, etc.). Voir <a href="https://neo4j.com/labs/genai-ecosystem/llm-graph-builder/">ici</a> pour plus de détails.</p>



<h3 class="wp-block-heading">Extraction libre VS extraction supervisée</h3>



<p>Il est à noter que si aucune contrainte (sur les types d’entité et de relation à extraire) n’est définie avec ces outils, ils vont librement extraire toutes les informations qu’ils peuvent trouver. Ce genre d’extraction « à l’aveugle » peut éventuellement être utilisée pour des petits documents, ou dans des cas où l’on ne sait pas à l’avance le genre de structure que l’on peut extraire, mais il est généralement préférable d’établir à l’avance l’ontologie que l’on souhaite adopter pour le graphe.</p>
<p>Une extraction libre est en effet souvent problématique pour plusieurs raisons :</p>
<p><strong>Explosion des types d’entité et de relation </strong></p>
<p>Lorsque la taille ou le nombre de documents augmente, l&#8217;on risque rapidement de se retrouver avec un très grand nombre de types différents d’entités et de relations au sein du graphe, ce qui peut le rendre difficile à exploiter (par ex. pour des applications de RAG).</p>
<p><strong>Incohérence de types</strong></p>
<p>En l’absence d’une ontologie fournissant une nomenclature claire, il y a des risques d’incohérence dans les types détectés (par exemple, une entreprise pourra être labelisée comme « Enterprise », une autre comme « Company », et une troisième comme « Organization »). En pratique, ce genre de soucis peut potentiellement être réglé a posteriori en listant tous les types de nœud et en rassemblant les types sémantiquement proches.</p>
<p><strong>Soucis de réification</strong></p>
<p>Par définition, une relation dans un graphe relie un nœud à un autre nœud. Un souci peut émerger lorsqu’une entité doit se connecter à une information qui a été modélisée sous la forme d’une relation. Pour illustrer le problème, reprenons en guise d&#8217;exemple l’acquisition d’Activision Blizzard par Microsoft. Supposons qu&#8217;un premier chunk de texte mentionne simplement cette acquisition sans plus de détails, elle sera fort potentiellement enregistrée sous la forme&nbsp;:</p>
<p><code>(Microsoft)-[ACQUIRES]-&gt;(Activision Blizzard)</code></p>
<p>Si maintenant le chunk suivant mentionne l’information « <em>The FTC challenged the acquisition&#8230;</em> », nous avons un problème car il n’est plus possible de modéliser</p>
<p><code>(FTC)-[CHALLENGES]-&gt;(Acquisition)</code></p>
<p>puisque l’acquisition a été précédemment modélisée sous la forme d’une relation, et non d’un nœud pouvant être référencé par une relation.</p>
<p>Dans ce cas, la relation peut par exemple être supprimée puis remplacée par un nœud, afin de la rendre référençable :</p>
<p><code>(Microsoft)-[INITIATES]-&gt;(Acquisition)-[TARGETS]-&gt;(Activision Blizzard)</code></p>
<p>Ce processus, appelé <strong>réification</strong>, n’est pas automatique et demande l’ajout d’une étape d’enrichissement pour détecter de potentielles références à des informations modélisées sous forme de relations, et les réifier si nécessaire.</p>



<h2 class="wp-block-heading">Quelques alternatives aux LLM</h2>



<p>Maintenant que nous avons vu une série d’approches basées spécifiquement sur les LLM, cette section propose quelques outils alternatifs basés sur des méthodes de NLP classique.</p>
<p>Si l&#8217;objectif est uniquement de faire l’extraction d’entités nommées, vous pouvez trouver <a href="/named-entity-recognition-une-application-du-nlp-utile/">ici un article de blog dédié à ce sujet</a>, ainsi qu’un <a href="/pii-filtering-fr/">exemple d’application de NER en PII filtering</a>. Il existe de nombreux modèles de NER préentrainés disponibles sur des plateformes telles que <a href="https://huggingface.co/">Hugging Face</a>.</p>
<p>Concernant l’extraction d’entités et de relations, elle peut se faire typiquement de 2 façons distinctes&nbsp;:</p>



<ul class="wp-block-list">
<li><strong>L’extraction en 2 étapes séparées&nbsp;:</strong> l&#8217;on commence par l’utilisation d’un NER pour la détection et la catégorisation des entités, suivie d&#8217;une extraction de relations sur la base du texte et des entités détectées, afin de déterminer les relations entre ces dernières. Quelques exemples d’outils pour l’extraction de relations incluent <a href="https://github.com/thunlp/OpenNRE">openNRE</a>, <a href="https://github.com/alimirzaei/spacy-relation-extraction">spacy-relation-extraction</a> ou encore <a href="https://github.com/jackboyla/GLiREL">GliREL</a>.</li>



<li><strong>L’extraction conjointe (end-to-end) &nbsp;:</strong> il s’agit d’outils qui réalisent l’extraction d’entités et de relations en une seule étape, tels que <a href="https://nlp.stanford.edu/software/openie.html">OpenIE</a>, <a href="https://github.com/SapienzaNLP/relik">Relik</a>,&nbsp;<a href="https://github.com/Babelscape/rebel">REBEL</a> ou <a href="https://www.diffbot.com/products/natural-language/">Diffbot</a> (solution commerciale).</li>
</ul>



<h2 class="wp-block-heading">Vérifier la conformité de ce qui a été détecté</h2>



<p>La grande force des LLM pour ce genre de tâche d’extraction est leur compréhension du langage naturel, ce qui permet de personnaliser l’extraction en adaptant le prompt d’instructions. Par exemple, en l’absence de template de sortie pour la réponse structurée (que le LLM peut peiner à respecter si le template devient trop compliqué), il est possible d’obtenir des nœuds et relations conformes à l’ontologie en décrivant l’ontologie directement dans le prompt d’instructions, mais il est important de rester vigilant aux extractions. En effet, il n’y a aucune garantie que le LLM ne fasse pas d’erreur, et ne renvoie pas en sortie une relation/entité non-conforme.</p>
<p>De manière générale, lorsqu’un LLM (ou tout autre outil) est utilisé pour extraire de l’information de façon automatique depuis un texte vers un graphe de connaissances, il est utile de vérifier que ce qui a été extrait est bien conforme à l’ontologie et fidèle à l’information qui se trouve dans la source.</p>
<ol>
<li>Vérifier que l’extraction respecte l’ontologie</li>
</ol>
<p>Comme nous l’avons déjà mentionné dans un <a href="/shacl-logische-en-vormcontroles-met-kg-technologieen/">précédent article de blog</a>, il est possible de valider la structure et le contenu d’un graphe de connaissances à l’aide du standard SHACL. Il s’agit d’un langage qui va contenir les différentes contraintes qui s’appliquent sur un graphe de connaissances. Il est possible soit d’effectuer une validation finale du graphe, pour vérifier que le contenu respecte effectivement les contraintes énoncées en SHACL (et de lister les données qui violent ces contraintes), soit d’effectuer ces validations de façon transactionnelle à chaque nouvelle information qui est ajoutée, afin de refuser tout nouvel ajout illégal. Bien qu’initialement prévu pour des graphes en RDF, certaines bases de données peuvent tout de même interpréter des contraintes en SHACL et valider le graphe, comme <a href="https://neo4j.com/labs/neosemantics/">neo4j avec le package <em>neosemantics</em> (n10s)</a>.</p>
<ol start="2">
<li>Vérifier que l’extraction est correcte</li>
</ol>
<p>Le risque d’une extraction automatique est qu’une information introduite dans le graphe soit factuellement incorrecte vis-à-vis du texte d’origine, ce qui peut être particulièrement problématique si ce graphe est utilisé comme potentielle source d’information (par exemple pour une application de graphRAG). Plusieurs approches peuvent être suivies. La plus simple est une vérification humaine des informations extraites, mais cela peut devenir difficile, voire infaisable, lorsque les documents deviennent trop longs/nombreux. L’autre approche consiste à utiliser un second LLM afin de vérifier ce qui a été extrait de chaque chunk. Comme nous l’avons mentionné dans <a href="/experiences-pratiques-avec-levaluation-automatique-de-la-rag/">l’article d’évaluation de LLM</a>, il est plus facile, pour les LLM, de détecter les erreurs a posteriori que de les éviter.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>Ces technologies, bien que performantes, ne sont jamais parfaites. Sauf extraction libre (à l’aveugle), mais qui risque d’aboutir à la création d’un graphe difficilement exploitable, la construction d’un graphe de connaissances à partir de texte est une tâche qui demande du travail, tant en amont (prétraitement des textes, établissement d’une ontologie pour le graphe sur la base du contenu du texte) qu’en aval (validation de la structure du graphe vis-à-vis de l’ontologie et vérification de la véracité et la fiabilité de son contenu).</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p><em>Ce post est une contribution individuelle de Pierre Leleux, data scientist et network data analyst chez Smals Research. Cet article est écrit en son nom propre et n’impacte en rien le point de vue de Smals.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Unstructured &#8211; Outil d&#8217;ingestion de données</title>
		<link>https://www.smalsresearch.be/unstructured-outil-dingestion-de-donnees/</link>
		
		<dc:creator><![CDATA[Katy Fokou]]></dc:creator>
		<pubDate>Tue, 15 Oct 2024 09:50:09 +0000</pubDate>
				<category><![CDATA[[FR]]]></category>
		<category><![CDATA[Quick reviews]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[data ingestion]]></category>
		<category><![CDATA[Large Language Model]]></category>
		<guid isPermaLink="false">https://www.smalsresearch.be/unstructured-outil-dingestion-de-donnees/</guid>

					<description><![CDATA[Unstructured est un outil d&#8217;ingestion de documents pour le développement d&#8217;applications basées sur les grands modèles de langue (LLM) telles que les applications de type RAG. L&#8217;outil est disponible comme plateforme payante no-code, sous forme d&#8217;API payant ou comme package Python open-source. Unstructured is een documentinvoertool voor de ontwikkeling van applicaties gebaseerd op grote taalmodellen [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Unstructured est un outil d&#8217;ingestion de documents pour le développement d&#8217;applications basées sur les grands modèles de langue (LLM) telles que les applications de type RAG. L&#8217;outil est disponible comme plateforme payante no-code, sous forme d&#8217;API payant ou comme package Python open-source.</p>




<p>Unstructured is een documentinvoertool voor de ontwikkeling van applicaties gebaseerd op grote taalmodellen (LLM) zoals RAG-toepassingen. De tool is beschikbaar als een betalend no-code platform, als betalende API of als open-source Python library.</p>







            <div data-wp-interactive="core/file" class="wp-block-file">
                <object data-wp-bind--hidden="!state.hasPdfPreview" hidden class="wp-block-file__embed" data="https://www.smalsresearch.be/wp-content/uploads/2024/10/QR-Unstructured.pdf" type="application/pdf" style="width:100%;height:600px" aria-label="Embed of QR-Unstructured."></object>
                <a id="wp-block-file--media-43b8f09f-c864-4077-98fa-689ba447f515" href="https://www.smalsresearch.be/wp-content/uploads/2024/10/QR-Unstructured.pdf">QR-Unstructured</a><a href="https://www.smalsresearch.be/wp-content/uploads/2024/10/QR-Unstructured.pdf" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-43b8f09f-c864-4077-98fa-689ba447f515">Download</a>
                </div>
            ]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Open-source taalmodellen &#8211; Een serieus alternatief voor ChatGPT ?</title>
		<link>https://www.smalsresearch.be/open-source-taalmodellen-een-serieus-alternatief-voor-chatgpt/</link>
		
		<dc:creator><![CDATA[Katy Fokou]]></dc:creator>
		<pubDate>Wed, 07 Feb 2024 15:44:00 +0000</pubDate>
				<category><![CDATA[[NL]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[Large Language Model]]></category>
		<category><![CDATA[Open Source]]></category>
		<guid isPermaLink="false">/?p=19888</guid>

					<description><![CDATA[In dit artikel onderzoeken we open source large language models, waarbij we kijken naar hun implementatie op lokale machines, hun gebruiksgemak en de kwaliteit van hun resultaten in vergelijking met propriëtaire modellen. Daarna worden de verschillende manieren onderzocht om de prestaties van deze modellen op specifieke taken te verbeteren]]></description>
										<content:encoded><![CDATA[
<p><em><a href="/les-modeles-de-langue-open-source-une-alternative-a-chatgpt/" data-type="link" data-id="/les-modeles-de-langue-open-source-une-alternative-a-chatgpt/">Version en français</a></em></p>



<p>Sinds de lancering van de ChatGPT-chatbot hebben we verschillende mogelijkheden van generatieve AI onderzocht, in het bijzonder <em>large language models</em> (LLM&#8217;s). Dit omvat het gebruik van LLM&#8217;s voor <a href="/llms-pour-code/">het genereren van code</a> en de implementatie van <a href="/un-propre-systeme-de-questions-reponses-base-sur-des-modeles-de-langue/">question answering systemen</a>. Tot nu toe hebben we voornamelijk het meest populaire propriëtaire model gebruikt: OpenAI GPT3/4 (ChatGPT). Deze modellen zijn eenvoudig te gebruiken en hun mogelijkheden zijn indrukwekkend. Het gebrek aan transparantie en de gebruiksbeperkingen die inherent zijn aan propriëtaire modellen hebben de afgelopen maanden echter geleid tot de snelle ontwikkeling van opensource-alternatieven.</p>



<p>Het artikel behandelt twee hoofdonderwerpen. Ten eerste onderzoeken we open source <em>large language models</em>, waarbij we kijken naar hun implementatie op lokale machines, hun gebruiksgemak en de kwaliteit van hun resultaten in vergelijking met propriëtaire modellen. Daarna worden de verschillende manieren onderzocht om de prestaties van deze modellen op specifieke taken te verbeteren.</p>



<p>Voordelen van het gebruik van open source<em> large language models</em></p>



<ul class="wp-block-list">
<li><strong>Transparantie</strong>. Details over de trainingsgegevens, kenmerken en architectuur van propriëtaire modellen worden vaak geheim gehouden. Dit maakt het moeilijk om problemen met betrekking tot bias en verkeerde informatie in de trainingsgegevens te identificeren en op te lossen. Open source modellen bieden daarentegen meer transparantie, omdat alle informatie openbaar beschikbaar is. Dit maakt het gemakkelijker om problemen te identificeren en op te lossen.</li>



<li><strong>Vertrouwelijkheid</strong>. Vertrouwelijkheid is een belangrijke factor en de belangrijkste reden waarom we open source modellen onderzoeken. Gevoelige en vertrouwelijke gegevens kunnen lokaal worden behandeld met open source modellen, waardoor het risico op gegevensinbreuken en ongeoorloofd gebruik wordt vermeden. Dit risico is daarentegen groter bij het gebruik van propriëtaire modellen die in de cloud worden gehost. Open source modellen bieden daarom een veiligere oplossing voor het verwerken van vertrouwelijke gegevens, op voorwaarde dat je voldoende hardware hebt om ze te hosten.</li>



<li><strong>Kostprijs</strong>. Propriëtaire modellen zijn duur op grote schaal en hun beschikbaarheid kan niet altijd gegarandeerd worden. Open source modellen zijn daarentegen gratis, waardoor ze toegankelijker zijn. Het is echter belangrijk op te merken dat het inzetten van open source-modellen op lokale insfrastructuur extra kosten met zich meebrengt waarmee rekening moet worden gehouden.</li>



<li><strong>Aanpasbaarheid</strong>. Open source LLM&#8217;s zijn flexibeler en kunnen gemakkelijk worden aangepast aan de specifieke behoeften van een bepaald gebruiksdomein.</li>
</ul>



<p><strong>Overzicht van open source large language models</strong></p>



<p>Een van de eerste voorbeelden van open source large language models (LLM&#8217;s) is het <a href="https://bigscience.huggingface.co/blog/bloom">BLOOM-model</a>. Het doel van BLOOM is om LLM&#8217;s te democratiseren door een taalmodel aan te bieden dat equivalent is aan GPT-3, dat meertalig, transparant en toegankelijk is voor de onderzoeksgemeenschap. De implementatie van BLOOM blijft echter moeilijk omdat&nbsp; hiervoor zware infrastructuur nodig is.</p>



<p>Vervolgens werden andere, veel &#8216;lichtere&#8217; modellen ontwikkeld. Aangezien de situatie snel evolueert, is het onmogelijk om in dit artikel een volledige lijst of relevante beoordeling van al deze modellen op te stellen. Het <a href="https://huggingface.co/models">Hugging Face</a> platform is echter een goede referentie voor toegang tot deze modellen en de bijbehorende informatie. Bij de keuze van een model is het belangrijk om de trainingsvoorwaarden (dataset, inbegrepen moderatie, enz.), de gebruiksvoorwaarden (voor onderzoek of commerciële doeleinden) en de specifieke kenmerken (talen en toepassingsgebieden, oriëntatie op instructies of chat) te controleren. Hier zijn enkele van de populairste modellen:</p>



<ul class="wp-block-list">
<li><a href="https://ai.meta.com/llama/">Llama 2</a> is een reeks modellen van verschillende grootte (7b-70b) ontwikkeld door Meta en gereproduceerd in verschillende vormen: Alpaca (alleen voor onderzoeksdoeleinden) en Vicuna. Er is ook een specifieke versie van Llama 2 voor het <a href="https://ai.meta.com/blog/code-llama-large-language-model-coding/">genereren van code</a>.</li>



<li><a href="https://www.microsoft.com/en-us/research/blog/phi-2-the-surprising-power-of-small-language-models/">Phi-2</a> is een compact model (2.7b) van Microsoft voor experimenten en onderzoek.</li>



<li><a href="https://falconllm.tii.ae/falcon.html">Falcon</a> is een meertalig model dat onlangs de eerste plaats behaalde in Hugging Face&#8217;s open LLM ranglijst. Dit model is groter dan Llama 2 (40b-180b) en vereist daarom aanzienlijke middelen om te draaien.</li>



<li><a href="https://mistral.ai/product/">Mistral</a> is een klein (7b) maar zeer krachtig meertalig model. Het Franse bedrijf Mistral AI heeft onlangs een nieuw model uitgebracht, Mixtral 8X7B, dat GPT-3.5 kan evenaren. Dit bevestigt de trend in open source om kleinere, meer betaalbare modellen te ontwikkelen zonder aan prestaties in te boeten.</li>



<li>En <a href="https://www.mosaicml.com/mpt">MPT</a> tenslotte, ontwikkeld door Mozaic ML, is primair bedoeld voor commercieel gebruik.</li>
</ul>



<p><strong>Een LLM lokaal implementeren en gebruiken</strong></p>



<p>Een model lokaal uitvoeren kan complex zijn. Gelukkig zijn er tools waarmee je modellen kunt benaderen via een API.Dit zijn enkele van de meest populaire frameworks:</p>



<ul class="wp-block-list">
<li><a href="https://github.com/ggerganov/llama.cpp">Llama.ccp</a> is een inferentie-engine die speciaal is ontworpen om Llama 2-modellen en andere compatibele modellen (GGML-formaat) uit te voeren op beperkte hardwarebronnen. Llama.cpp is echter een command line tool en heeft geen gebruikersinterface.</li>



<li><a href="https://cheatsheet.md/llm-leaderboard/ollama.en">OLlama</a> is een eenvoudig te gebruiken service.&nbsp; De toepassing wordt gestart vanaf een command line in een Linux-terminal en de gebruiker kan dan interageren met het model.</li>



<li><a href="https://lmstudio.ai/">LMStudio</a> en <a href="/publications/document/?docid=270">GPT4All</a> zijn toepassingen met een gebruiksvriendelijke interface voor een gebruikerservaring à la ChatGPT.</li>



<li>We moeten ook het <a href="https://github.com/imartinez/privateGPT">PrivateGPT</a> project vermelden, dat handig is voor het gebruik van lokale modellen om gevoelige documenten in disconnected mode te ondervragen.</li>
</ul>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2024/02/qa_llama2_ft_nl.png"><img loading="lazy" decoding="async" width="703" height="208" data-id="19916" src="/wp-content/uploads/2024/02/qa_llama2_ft_nl.png" alt="" class="wp-image-19916" srcset="https://www.smalsresearch.be/wp-content/uploads/2024/02/qa_llama2_ft_nl.png 703w, https://www.smalsresearch.be/wp-content/uploads/2024/02/qa_llama2_ft_nl-300x89.png 300w" sizes="auto, (max-width: 703px) 100vw, 703px" /></a></figure>
</figure>



<p>Dankzij de hierboven beschreven tools kunnen open source modellen op dezelfde manier worden aangeroepen als OpenAI modellen vanuit Python bibliotheken zoals <a href="https://www.smalsresearch.be/wp-content/uploads/2023/12/QR-LangChain.pdf">LangChain</a>.</p>



<pre class="wp-block-code"><code>    from langchain.llms import OLlama
    from langchain.embeddings import OLlamaEmbeddings
    llm = OLlama(base_url='http://localhost:11434', 
                    model='Llama2_7b_fine-tuned',
                    temperature=0)
    embeddings = OLlamaEmbeddings(base_url='http://localhost:11434', 
                                model='Llama2_7b_fine-tuned')</code></pre>



<p><strong>LLM&#8217;s verfijnen <em>(finetuning)</em></strong></p>



<p>LLM&#8217;s zijn krachtig en zeer veelzijdig, maar ze zijn vaak niet erg nauwkeurig als ze worden gebruikt voor een specifieke taak of domein met zijn eigen taal en concepten.</p>



<p>Er zijn verschillende manieren om een groot taalmodel te verbeteren. De eerste en eenvoudigste is om de prompt aan te passen (<em>prompt engineering, few-shot learning</em>), maar dit is niet altijd voldoende. Een ander alternatief is finetuning, op voorwaarde dat je toegang hebt tot de modellen en hun parameters. Deze methode bestaat uit het trainen van de laatste lagen om een bestaand model voor een specifieke taak te verfijnen met behulp van een aangepaste gegevensset voor het domein/de taak in kwestie. Het voordeel van finetuning is dat je, door te beginnen met een bestaand model, veel minder gegevens (en middelen) nodig hebt voor de training:&nbsp; Dit is het principe van<em> transfer learning</em>.</p>



<p>We hebben een finetuning-experiment uitgevoerd op een open source LLM om de resultaten van een vraag-en-antwoordsysteem te verbeteren door het te trainen op gegevens die specifiek zijn voor de socialezekerheidssector. De voornaamste stappen van dit experiment zijn:</p>



<ul class="wp-block-list">
<li>Trainingsgegevens voorbereiden. De trainingsvoorbeelden bestaan uit een reeks vragen/antwoorden op het gebied van sociale zekerheid, waarbij de vragen gedeeltelijk zijn gegenereerd met het GPT-4-model. Deze fase is de moeilijkste en meest tijdrovende, omdat er veel gegevens moeten worden verzameld en opgeschoond.</li>



<li>Basismodel selecteren. We hebben verschillende open source modellen getest, maar gezien de computermiddelen&nbsp;die we tot onze beschikking hadden, bleek het Llama 2-7b model het meest effectief in termen van nauwkeurigheid en snelheid.</li>



<li>Het model verfijnen. De Python-bibliotheek &#8220;<a href="https://huggingface.co/docs/transformers/installation">transformers</a>&#8221; ontwikkeld door Hugging Face is een goed hulpmiddel voor het verfijnen van LLM&#8217;s, maar vereist een minimum aan vaardigheid om te gebruiken. Voor ons experiment hebben we ervoor gekozen om het <a href="https://h2o.ai/platform/ai-cloud/make/llm-studio/">H2O LLMstudio</a> platform te gebruiken. Dit is een &#8216;no-code&#8217; platform waar hyperparameters en training worden geconfigureerd via een gebruikersinterface.</li>



<li>Evaluatie van het verfijnde model. Op basis van ons finetuningexperiment konden we aantonen dat het mogelijk was om de prestaties van een &#8216;light&#8217; open source model te verbeteren op een zeer specifieke taak met zeer weinig gegevens (+28%). Deze prestaties waren echter lager dan die verkregen met het GPT-4 model.</li>
</ul>



<p>Tot slot kan modelaanpassing ook worden bereikt door instructiegebaseerde finetuning. Deze meer geavanceerde finetuningmethode is vergelijkbaar met de hierboven beschreven methode. In feite wordt het model geleerd om instructies op te volgen door expliciete instructies toe te voegen aan de trainingsgegevens. Dit maakt het mogelijk om het model op een veelzijdige manier te verfijnen, d.w.z. om het in staat te stellen om verschillende taken nauwkeurig uit te voeren.</p>



<p><strong>Conclusie</strong></p>



<p>Open source large language models bieden meer transparantie, vertrouwelijkheid en aanpasbaarheid dan propriëtaire modellen. Het feit dat ze gratis zijn is een bijkomend voordeel, maar de kosten voor inferentie en onderhoud mogen niet over het hoofd gezien worden. Deze voordelen maken ze een logisch en aantrekkelijk alternatief voor veel toepassingen. Er is echter nog werk aan de winkel om deze open source taalmodellen echt competitief te maken, vooral voor complexe taken zoals redeneren (<em>reasoning</em>). Desondanks evolueert de ontwikkeling van open source snel en wordt de prestatiekloof met betaalde modellen kleiner. Deze modellen zijn zeker nodig voor specifieke toepassingen waarbij lokaal met vertrouwelijke gegevens moet worden gewerkt. Het is mogelijk om finetuning te gebruiken om hun gebrek aan precisie in specifieke taken te compenseren, op voorwaarde dat de relevante gegevens beschikbaar zijn.</p>


]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Les modèles de langage open-source &#8211; Une alternative sérieuse à ChatGPT?</title>
		<link>https://www.smalsresearch.be/les-modeles-de-langue-open-source-une-alternative-a-chatgpt/</link>
		
		<dc:creator><![CDATA[Katy Fokou]]></dc:creator>
		<pubDate>Thu, 18 Jan 2024 13:24:39 +0000</pubDate>
				<category><![CDATA[[FR]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[Large Language Model]]></category>
		<category><![CDATA[Open Source]]></category>
		<guid isPermaLink="false">/?p=19808</guid>

					<description><![CDATA[L'article explorera les large language models open-source en abordant leur mise en œuvre sur des machines locales, leur facilité d'utilisation et leur qualité de résultats comparée aux modèles propriétaires. Ensuite, il examinera les différentes possibilités d'amélioration des performances de ces modèles sur des tâches spécifiques.]]></description>
										<content:encoded><![CDATA[
<p><em><a href="/open-source-taalmodellen-een-serieus-alternatief-voor-chatgpt/" data-type="link" data-id="/open-source-taalmodellen-een-serieus-alternatief-voor-chatgpt/">Nederlandstalige versie</a></em></p>



<p>Depuis le lancement du chatbot ChatGPT, nous avons exploré différentes possibilités de l&#8217;IA générative, en particulier les grands modèles de langage (<em>large language model</em> – LLM). Cela inclut l&#8217;utilisation des &nbsp;LLMs pour la <a href="/llms-pour-code/">génération de code</a> et la mise en œuvre de <a href="/un-propre-systeme-de-questions-reponses-base-sur-des-modeles-de-langue/">systèmes de réponse aux questions</a> (question answering). Jusqu&#8217;à présent, nous avons principalement utilisé le modèle propriétaire le plus populaire&nbsp;: OpenAI GPT3/4 (ChatGPT). Ces modèles sont faciles à utiliser et leurs capacités sont impressionnantes. Cependant, le manque de transparence et les restrictions d&#8217;utilisation inhérentes aux modèles propriétaires ont conduit, ces derniers mois, au développement rapide d&#8217;alternatives open-source.</p>



<p>L&#8217;article abordera deux sujets principaux. Tout d&#8217;abord, il explorera les <em>large language models</em> open-source en abordant leur mise en œuvre sur des machines locales, leur facilité d&#8217;utilisation et leur qualité de résultats comparée aux modèles propriétaires. Ensuite, il examinera les différentes possibilités d&#8217;amélioration des performances de ces modèles sur des tâches spécifiques.</p>



<h2 class="wp-block-heading">Avantages liés à l’utilisation des <em>large language models</em> open-source</h2>



<ul class="wp-block-list">
<li><strong>La transparence.</strong> Les détails sur les données d&#8217;entraînement, les caractéristiques et l&#8217;architecture des modèles propriétaires sont souvent gardés secrets. Cela rend difficile l&#8217;identification et la résolution des problèmes liés aux biais et aux fausses informations contenues dans les données d&#8217;entraînement. En revanche, les modèles open-source permettent une plus grande transparence, car toutes les informations sont accessibles au public. Cela facilite l&#8217;identification et la résolution des problèmes.</li>



<li><strong>Le confidentialité.</strong> La confidentialité est un facteur important et constitue la principale raison de notre démarche d’exploration des modèles open-source. Les données sensibles et confidentielles peuvent être traitées en local avec des modèles open-source, évitant ainsi le risque de violation de données et d&#8217;utilisation non autorisée. En revanche, l&#8217;utilisation de modèles propriétaires hébergés sur le cloud accroît ce risque. Les modèles open-source offrent donc une solution plus sûre pour le traitement des données confidentielles à condition de disposer du hardware suffisant pour les héberger.</li>



<li><strong>Le coût.</strong> Les modèles propriétaires ont un coût important à grande échelle et leur disponibilité ne peut pas toujours être garantie. Les modèles open-source, par contre sont gratuits, ce qui les rend plus accessibles. Cependant, il est important de noter que le déploiement des modèles open-source sur des infrastructures locales entraîne des coûts supplémentaires qui doivent être pris en compte.</li>



<li><strong>L&#8217;adaptabilité.</strong> Les LLM open-source ont une plus grande flexibilité et peuvent être facilement adaptés pour répondre aux besoins spécifiques d&#8217;un domaine d&#8217;utilisation particulier.</li>
</ul>



<h2 class="wp-block-heading"><strong>Un tour des <em>large language models</em> open-source</strong></h2>



<p>L&#8217;un des premiers exemples de grands modèles de langage (LLM) open-source à avoir vu le jour est le modèle <a href="https://bigscience.huggingface.co/blog/bloom">BLOOM</a>. Son objectif est de démocratiser les LLM en proposant un modèle de langage équivalent à GPT-3, cependant multilingue, transparent et accessible à la communauté de recherche. Cependant, la mise en œuvre de BLOOM reste difficile car elle nécessite des infrastructures lourdes.</p>



<p>Par la suite, d&#8217;autres modèles beaucoup plus &#8220;légers&#8221; ont été développés. Il est impossible d&#8217;établir une liste complète ou une évaluation pertinente de tous ces modèles dans cet article car la situation évolue rapidement. Cependant, la plateforme <a href="https://huggingface.co/models">Hugging Face</a> est une bonne référence pour accéder à ces modèles et aux informations qui y sont associées. Lors du choix d&#8217;un modèle, il est important de vérifier les conditions d&#8217;entraînement (ensemble de données, modération incluse, etc.), les conditions d&#8217;utilisation (à des fins de recherche ou commerciales) ainsi que ses spécificités (langues et domaines d&#8217;application, orientation vers les instructions ou le chat). Voici quelques-uns des modèles les plus populaires&nbsp;:</p>



<ul class="wp-block-list">
<li><a href="https://ai.meta.com/llama/">Llama 2</a> est une suite de modèles de différentes tailles (7b-70b<sup data-fn="3bd6646d-2be3-4e53-8462-5ee233f3f333" class="fn"><a href="#3bd6646d-2be3-4e53-8462-5ee233f3f333" id="3bd6646d-2be3-4e53-8462-5ee233f3f333-link">1</a></sup>) développée par Meta et reproduite sous différentes formes&nbsp;: Alpaca (à des fins de recherche uniquement) et Vicuna. Il existe également une version spécifique de Llama 2 pour la <a href="https://ai.meta.com/blog/code-llama-large-language-model-coding/">génération de code</a>.</li>



<li><a href="https://www.microsoft.com/en-us/research/blog/phi-2-the-surprising-power-of-small-language-models/">Phi-2</a> est un modèle compact (2.7b) par Microsoft pour l&#8217;expérimentation et la recherche.</li>



<li><a href="https://falconllm.tii.ae/falcon.html">Falcon</a> est un modèle multilingue qui a récemment occupé la première place dans le classement open LLM établi par Hugging Face. Ce modèle est plus grand que Llama 2 (40b-180b) et nécessite donc des ressources importantes pour fonctionner.</li>



<li><a href="https://mistral.ai/product/">Mistral</a> est un modèle multilingue de &#8220;petite&#8221; taille (7b) mais très performant. La société française Mistral AI a récemment publié un nouveau modèle, Mixtral 8X7B, qui peut rivaliser avec GPT-3.5. Cela confirme la tendance dans le domaine de l&#8217;open-source à développer des modèles plus petits et plus abordables sans sacrifier les performances.</li>



<li>Et enfin <a href="https://www.mosaicml.com/mpt">MPT</a> développé par Mozaic ML est principalement destiné à une utilisation commerciale.</li>
</ul>



<p><a id="_msocom_1"></a></p>



<h2 class="wp-block-heading">Déploiement et utilisation d’un LLM en local</h2>



<p>Faire tourner un modèle en local peut être complexe. Heureusement, il existe pour cela des outils qui permettent d’accéder aux modèles via un API. Parmi les plus populaires, on retrouve les frameworks suivants&nbsp;:</p>



<ul class="wp-block-list">
<li><a href="https://github.com/ggerganov/llama.cpp">Llama.ccp</a> est un moteur d’inférence spécialement conçu pour faire tourner les modèles Llama 2 et autres modèles compatibles (format GGML) sur des ressources hardware limitées. Cependant, Llama.cpp est un outil qui s’exécute en ligne de commande et ne dispose pas d’interface utilisateur.</li>



<li><a href="https://cheatsheet.md/llm-leaderboard/ollama.en">OLlama</a> est un service facile d’utilisation.&nbsp; L’application est lancée en une ligne de commande dans un terminal Linux et l’utilisateur peut ensuite dialoguer avec le modèle.</li>



<li><a href="https://lmstudio.ai/">LMStudio</a> et <a href="/publications/document/?docid=270">GPT4All </a>sont des applications ayant une interface conviviale pour une expérience utilisateur «&nbsp;à la ChatGPT&nbsp;».</li>



<li>Notons aussi le projet <a href="https://github.com/imartinez/privateGPT">PrivateGPT</a>, utile pour l’utilisation des modèles en local pour interroger des documents sensibles en mode déconnecté.</li>
</ul>



<figure class="wp-block-image size-full is-resized"><a href="/wp-content/uploads/2024/01/qa_llama2_ft.png"><img loading="lazy" decoding="async" width="719" height="193" src="/wp-content/uploads/2024/01/qa_llama2_ft.png" alt="" class="wp-image-19871" style="width:816px;height:auto" srcset="https://www.smalsresearch.be/wp-content/uploads/2024/01/qa_llama2_ft.png 719w, https://www.smalsresearch.be/wp-content/uploads/2024/01/qa_llama2_ft-300x81.png 300w" sizes="auto, (max-width: 719px) 100vw, 719px" /></a><figcaption class="wp-element-caption">Exemple d&#8217;utilisation du modèle raffiné dans un système de question/réponse. </figcaption></figure>



<p>Grâce aux outils décrits ci-dessus, les modèles open-source peuvent être appelés de la même manière que les modèles OpenAI à partir de bibliothèques Python telles que <a href="https://www.smalsresearch.be/wp-content/uploads/2023/12/QR-LangChain.pdf">LangChain</a>.</p>



<pre class="wp-block-code"><code>    from langchain.llms import OLlama
    from langchain.embeddings import OLlamaEmbeddings
    llm = OLlama(base_url='http://localhost:11434', 
                    model='Llama2_7b_fine-tuned',
                    temperature=0)
    embeddings = OLlamaEmbeddings(base_url='http://localhost:11434', 
                                model='Llama2_7b_fine-tuned')
</code></pre>



<h2 class="wp-block-heading"><strong>Amélioration des LLM (<em>fine-tuning</em>)</strong></h2>



<p>Les LLM sont puissants et très polyvalents mais souvent peu précis lorsqu&#8217;ils sont utilisés pour une tâche ou un domaine spécifique ayant son propre langage et ses propres concepts.</p>



<p>Il y a plusieurs façons d’améliorer un grand modèle de langage. La première et la plus simple consiste à adapter le prompt (<em>prompt engineering</em>, <em>few-shot learning</em>) mais cela n’est pas toujours suffisant. Une autre alternative est le réglage fin ou fine-tuning à condition d’avoir accès aux modèles et ses paramètres. Cette méthode consiste à entraîner les dernières couches pour raffiner un modèle existant sur une tâche spécifique en utilisant un set de données personnalisé pour le domaine/la tâche visée. L’avantage du fine-tuning est qu’en partant d’un modèle existant, l&#8217;entraînement nécessite beaucoup moins de données (et de ressources): &nbsp;c’est le principe du <em>transfer learning</em>.</p>



<p>Nous avons réalisé une expérience de fine-tuning d’un LLM open-source pour l’amélioration de résultats d’un système de question-réponses en l’entrainant sur des données propres au domaine de la sécurité sociale. Les principales étapes de notre expérience sont les suivantes&nbsp;:</p>



<ul class="wp-block-list">
<li>Préparation des données de training. Les exemples d’entraînement consistent en une série de question/réponses sur le domaine de la sécurité sociale, les questions étant partiellement générées avec le modèle GPT-4. Cette étape est la plus difficile et la plus chronophage car elle requiert beaucoup de travail de collecte et de nettoyage de données.</li>



<li>Sélection du modèle de base. Nous avons testé plusieurs modèles open-source mais étant donné les ressources computationnelles dont nous disposons le modèle Llama 2-7b s’est avéré le plus efficace en termes de précision/rapidité.</li>



<li>Réglage fin du modèle. La bibliothèque Python «&nbsp;<a href="https://huggingface.co/docs/transformers/installation">transformers&nbsp;</a>» développée par Hugging Face est un bon outil pour le réglage des LLM mais cela demande un minimum de compétence pour son utilisation. Nous avons choisi pour notre expérience d’utiliser la plateforme <a href="https://h2o.ai/platform/ai-cloud/make/llm-studio/">H2O LLMstudio</a>. Cet outil est une plateforme «&nbsp;no-code&nbsp;» où la configuration des hyperparamètres et l’entraînement s&#8217;effectuent à l’aide d’une interface utilisateur.</li>



<li>Évaluation du modèle raffiné. Nous avons pu démontrer, à partir de notre expérience de fine-tuning, qu’il était possible avec peu de données d’améliorer les performances d’un modèle open-source «&nbsp;light&nbsp;» sur une tâche bien spécifique (+ 28%). Néanmoins, ces performances étaient en-dessous de celles obtenues avec le modèle GPT-4.</li>
</ul>



<p>Enfin, l’adaptation du modèle peut également se faire par réglage fin basé sur des instructions. Cette méthode plus avancée de <em>fine-tuning</em> est similaire à celle décrite précédemment. En effet, on apprend au modèle à suivre des instructions en ajoutant des instructions explicites en tant qu&#8217;entrée dans les données d&#8217;entraînement. Ceci permet de raffiner le modèle de manière polyvalente c&#8217;est-à-dire de le rendre capable d&#8217;effectuer différentes tâches avec précision.</p>



<h2 class="wp-block-heading"><strong>Conclusion</strong></h2>



<p>Les grands modèles de langage open-source offrent une transparence, une confidentialité et une adaptabilité supérieures par rapport aux modèles propriétaires. Leur gratuité constitue un avantage supplémentaire, mais il ne faut pas négliger les coûts d’inférence et de maintenance. Ces avantages en font une alternative logique et attrayante pour de nombreuses applications. Cependant, il reste du travail à faire pour rendre ces modèles de langage open-source véritablement compétitifs, notamment pour des tâches complexes telles que le raisonnement (<em>reasoning</em>). Néanmoins, le développement open-source évolue rapidement et l’écart de performance avec les modèles payants se réduit. Ces modèles sont certainement nécessaires pour des utilisations spécifiques qui nécessitent de travailler localement sur des données confidentielles. Il est possible de recourir à un réglage fin pour pallier leur manque de précision dans des tâches spécifiques, à condition de disposer de données pertinentes.</p>


<ol class="wp-block-footnotes"><li id="3bd6646d-2be3-4e53-8462-5ee233f3f333">Les chiffres 7b et 70b font références au nombre de paramètres du modèle. Ex: 7b = 7 milliards de paramètres. En comparaison, le modèle GPT3 a 175 milliards de paramètres.  <a href="#3bd6646d-2be3-4e53-8462-5ee233f3f333-link" aria-label="Jump to footnote reference 1"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/21a9.png" alt="↩" class="wp-smiley" style="height: 1em; max-height: 1em;" />︎</a></li></ol>

]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>H2O LLMstudio &#8211; Une interface no-code pour le réglage fin des grands modèles de langage</title>
		<link>https://www.smalsresearch.be/h2o-llmstudio-une-interface-no-code-pour-le-reglage-fin-des-grands-modeles-de-langage/</link>
		
		<dc:creator><![CDATA[Katy Fokou]]></dc:creator>
		<pubDate>Tue, 09 Jan 2024 08:10:59 +0000</pubDate>
				<category><![CDATA[[FR]]]></category>
		<category><![CDATA[Quick reviews]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[Large Language Model]]></category>
		<guid isPermaLink="false">https://www.smalsresearch.be/h2o-llmstudio-une-interface-no-code-pour-le-reglage-fin-des-grands-modeles-de-langage/</guid>

					<description><![CDATA[H2O LLMStudio est une plateforme open-source dédiée au réglage fin des grands modèles de langage (LLM), l’objectif étant de rendre ces modèles plus performants pour certaines tâches. H2O LLMStudio permet l’optimisation de modèles tels que Llama2 sans écrire une ligne de code à condition de disposer de ressources computationnelles suffisantes. H2O LLMStudio is een open-source [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>H2O LLMStudio est une plateforme open-source dédiée au réglage fin des grands modèles de langage (LLM), l’objectif étant de rendre ces modèles plus performants pour certaines tâches. H2O LLMStudio permet l’optimisation de modèles tels que Llama2 sans écrire une ligne de code à condition de disposer de ressources computationnelles suffisantes.</p>




<p>H2O LLMStudio is een open-source platform dat zich toelegt op het fine-tunen van grote taalmodellen (LLM), met als doel deze modellen beter te laten presteren voor bepaalde taken. H2O LLMStudio maakt de optimalisatie van modellen zoals Llama2 mogelijk zonder een regel code te schrijven, op voorwaarde dat er voldoende rekenkracht beschikbaar is.</p>







            <div data-wp-interactive="core/file" class="wp-block-file">
                <object data-wp-bind--hidden="!state.hasPdfPreview" hidden class="wp-block-file__embed" data="https://www.smalsresearch.be/wp-content/uploads/2024/01/QR-h2o-llmstudio_v3.pdf" type="application/pdf" style="width:100%;height:600px" aria-label="Embed of QR-h2o-llmstudio_v3."></object>
                <a id="wp-block-file--media-580e6578-7db3-4f04-a715-3ac0cdeddbc2" href="https://www.smalsresearch.be/wp-content/uploads/2024/01/QR-h2o-llmstudio_v3.pdf">QR-h2o-llmstudio_v3</a><a href="https://www.smalsresearch.be/wp-content/uploads/2024/01/QR-h2o-llmstudio_v3.pdf" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-580e6578-7db3-4f04-a715-3ac0cdeddbc2">Download</a>
                </div>
            ]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
