<?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>Natural Language Processing &#8211; Smals Research</title>
	<atom:link href="https://www.smalsresearch.be/tag/natural-language-processing/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.smalsresearch.be</link>
	<description></description>
	<lastBuildDate>Wed, 29 Apr 2026 08:59:04 +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>Natural Language Processing &#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>Les assistants de codage open source à l&#8217;ouvrage </title>
		<link>https://www.smalsresearch.be/opensource-coding-assistants-fr/</link>
		
		<dc:creator><![CDATA[Joachim Ganseman]]></dc:creator>
		<pubDate>Thu, 28 Mar 2024 09:37:20 +0000</pubDate>
				<category><![CDATA[[FR]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[chatbot]]></category>
		<category><![CDATA[computational creativity]]></category>
		<category><![CDATA[egov]]></category>
		<category><![CDATA[Natural Language Processing]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Programming]]></category>
		<guid isPermaLink="false">/?p=20319</guid>

					<description><![CDATA[Un assistant de codage respectueux de la vie privée pour un IDE avec des outils open source - comment faire ? ]]></description>
										<content:encoded><![CDATA[
<p><em>Cet article est aussi disponible <a href="/opensource-coding-assistants/">en néerlandais</a>.</em></p>



<p>Comme outil de génération de code pour les développeurs de logiciels, <a href="https://github.com/features/copilot" target="_blank" rel="noreferrer noopener">Github Copilot</a> domine le marché aujourd&#8217;hui. Cette situation devrait perdurer, d&#8217;autant plus que l&#8217;outil s&#8217;est enrichi d&#8217;une fonctionnalité de messagerie instantanée à la ChatGPT. Propriété de Microsoft, Github bénéficie d&#8217;une ligne directe avec OpenAI, et est donc le premier à profiter du rôle de pionnier que cette société continue de jouer dans le développement de <a href="https://fr.wikipedia.org/wiki/Grand_mod%C3%A8le_de_langage">grands modèles de langage</a> (abrégé <a href="https://en.wikipedia.org/wiki/Large_language_model" target="_blank" rel="noreferrer noopener">LLM en anglais)</a>&nbsp;</p>



<p>On en oublierait presque qu&#8217;il existe d&#8217;autres options. La première alternative à grande échelle construite sur une base open source, incluant des <a href="https://huggingface.co/datasets/bigcode/the-stack">jeux de données d&#8217;apprentissage ouverts</a>, est <a href="https://huggingface.co/blog/starcoder" target="_blank" rel="noreferrer noopener">StarCoder</a>, dont une <a href="https://github.com/bigcode-project/starcoder2" target="_blank" rel="noreferrer noopener">version 2</a> a récemment vu le jour. Elle est développée dans le cadre de l&#8217;<a href="https://www.bigcode-project.org/" target="_blank" rel="noreferrer noopener">initiative BigCode</a> de ServiceNow et de HuggingFace. L&#8217;<a href="https://arxiv.org/abs/2305.06161" target="_blank" rel="noreferrer noopener">article qui l&#8217;accompagne</a> offre un aperçu fascinant de la construction d&#8217;un modèle de langage pour la génération de code. Peu après StarCoder, <a href="https://arxiv.org/abs/2306.08568" target="_blank" rel="noreferrer noopener">WizardCoder</a>, <a href="https://arxiv.org/abs/2308.12950" target="_blank" rel="noreferrer noopener">CodeLLama</a>, <a href="https://github.com/deepseek-ai/DeepSeek-Coder" target="_blank" rel="noreferrer noopener">DeepSeekCoder</a> et quelques autres sont apparus sur la scène, pas tous fondés sur un ensemble de données ouvertes, mais librement accessibles et réutilisables via <a href="https://huggingface.co/" target="_blank" rel="noreferrer noopener">HuggingFace</a>. &nbsp;</p>



<p>Aujourd’hui, il existe aussi suffisamment d&#8217;outils pour faciliter l&#8217;exécution de ces modèles sur votre propre machine. Vous pouvez donc avoir votre propre assistant de codage personnel, hébergé par vous-même et entièrement privé. Pour cela, il vous faut un matériel suffisamment puissant, un LLM axé sur les tâches de <em>code completion</em> ou sur les conversations concernant le code, et une extension pour l&#8217;environnement de développement (IDE). Le LLM et l’extension de l’IDE communiquent entre eux via une API, qui peut être compatible ou non avec celle d&#8217;OpenAI, ce qui permet de passer facilement d&#8217;un modèle commercial (OpenAI) à un modèle open source le cas échéant.&nbsp;</p>



<h2 class="wp-block-heading"><strong>Extensions pour IDE</strong></h2>



<p>L&#8217;installation d&#8217;une extension est simple en soi. Github Copilot existe depuis longtemps en tant qu&#8217;<a href="https://code.visualstudio.com/docs/editor/github-copilot" target="_blank" rel="noreferrer noopener">extension pour VSCode</a> et aujourd&#8217;hui également pour <a href="https://plugins.jetbrains.com/plugin/17718-github-copilot" target="_blank" rel="noreferrer noopener">IntelliJ IDEA</a> &#8211; même si au moment de la rédaction de cet article, la version d’IntelliJ contient encore un peu moins de fonctionnalités.&nbsp;&nbsp;</p>



<p>Parmi les alternatives open source, <a href="https://continue.dev/" target="_blank" rel="noreferrer noopener">Continue</a> figure probablement parmi les meilleures à ce jour. Il en existe d&#8217;autres &#8211; Huggingface a développé <a href="https://github.com/huggingface/llm-vscode?tab=readme-ov-file" target="_blank" rel="noreferrer noopener">llm-vscode</a> par exemple &#8211; et il ne fait aucun doute que d&#8217;autres viendront s&#8217;ajouter. Tout comme Github Copilot, Continue existe également sous forme d&#8217;<a href="https://marketplace.visualstudio.com/items?itemName=Continue.continue" target="_blank" rel="noreferrer noopener">extension pour VSCode</a> ou <a href="https://plugins.jetbrains.com/plugin/22707-continue" target="_blank" rel="noreferrer noopener">IntelliJ</a>. L&#8217;outil peut utiliser à la fois des générateurs commerciaux basés sur le cloud (notamment GPT-4) et des solutions open source auto-hébergées, qui ne doivent pas nécessairement émuler l&#8217;API d&#8217;OpenAI et autorisent de nombreuses personnalisations.&nbsp;</p>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2024/03/2024-03-11_14h59_32.png"><img loading="lazy" decoding="async" width="1024" height="410" src="/wp-content/uploads/2024/03/2024-03-11_14h59_32-1024x410.png" alt="" class="wp-image-20216" srcset="https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_14h59_32-1024x410.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_14h59_32-300x120.png 300w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_14h59_32-768x308.png 768w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_14h59_32-1536x615.png 1536w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_14h59_32.png 1858w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Capture d’écran de l&#8217;extension Continue dans Visual Studio Code&nbsp;</figcaption></figure>



<p>Il demeure important de prendre le temps de se familiariser avec l’extension. La <a href="https://continue.dev/docs/intro" target="_blank" rel="noreferrer noopener">documentation de Continue</a> constitue une bonne base à cet effet. Pour chaque <a href="https://continue.dev/docs/model-setup/select-provider" target="_blank" rel="noreferrer noopener">serveur</a> et chaque <a href="https://continue.dev/docs/model-setup/select-model" target="_blank" rel="noreferrer noopener">LLM</a>, il se peut que vous deviez définir différentes options de configuration et que vous souhaitiez apporter des modifications à <a href="https://continue.dev/docs/model-setup/configuration" target="_blank" rel="noreferrer noopener">l&#8217;invite de commande</a> sous-jacente. Il convient également de savoir comment activer et désactiver l&#8217;extension dans l&#8217;IDE et de connaître les raccourcis et <a href="https://continue.dev/docs/customization/slash-commands" target="_blank" rel="noreferrer noopener">commandes</a> disponibles. <a href="https://www.youtube.com/results?search_query=continue+ai" target="_blank" rel="noreferrer noopener">YouTube</a> peut être un bon point de départ pour trouver des tutoriels et des exemples d&#8217;autres utilisateurs.&nbsp;</p>



<h2 class="wp-block-heading"><strong>Un LLM sur votre ordinateur portable</strong>&nbsp;</h2>



<p>Notamment sous l&#8217;impulsion du projet open source <a href="https://github.com/ggerganov/llama.cpp" target="_blank" rel="noreferrer noopener">llama.cpp</a>, des efforts considérables ont été faits au cours de l&#8217;année écoulée pour faire en sorte que les LLM puissent également être déployés sur du matériel informatique grand public. Un processeur graphique (GPU) au coût prohibitif n&#8217;est plus nécessaire, même s&#8217;il offre un gain de temps considérable. Globalement, <a href="https://github.com/ggerganov/llama.cpp" target="_blank" rel="noreferrer noopener">llama.cpp</a> permet de reconditionner un modèle au format GGUF (GPT-Generated Unified Format). Il s&#8217;agit ici d&#8217;appliquer un maximum d&#8217;optimisations :&nbsp;</p>



<p></p>



<ul class="wp-block-list">
<li>l&#8217;utilisation de jeux d&#8217;instructions du processeur (<s> </s>CPU) efficaces tels que&nbsp; <a href="https://en.wikipedia.org/wiki/AVX-512" target="_blank" rel="noreferrer noopener">AVX-512</a> &#8211; il va sans dire que le matériel sur lequel le modèle fonctionnera plus tard doit également prendre en charge ces jeux d&#8217;instructions ;&nbsp;</li>



<li>l&#8217;utilisation de bibliothèques hautement optimisées pour les calculs sous-jacents, telles que <a href="https://github.com/OpenMathLib/OpenBLAS" target="_blank" rel="noreferrer noopener">openBLAS</a> ou <a href="https://developer.apple.com/documentation/accelerate" target="_blank" rel="noreferrer noopener">Accelerate</a> et <a href="https://developer.apple.com/metal/" target="_blank" rel="noreferrer noopener">Metal</a> d&#8217;Apple ;&nbsp;</li>



<li>la <em>quantification </em>du modèle, par la réduction de la <a href="https://en.wikipedia.org/wiki/Precision_(computer_science)" target="_blank" rel="noreferrer noopener">précision</a> des poids dans les couches des réseaux neuronaux. Les nombres (à virgule flottante) de 16 ou 32 bits du modèle original sont ici convertis en nombres entiers de 8 bits, voire de 6 bits ou même de 4 bits. Cela permet d&#8217;économiser de la mémoire et d&#8217;accélérer les calculs, au prix d&#8217;une perte de qualité relativement faible.&nbsp;</li>
</ul>



<p>L&#8217;hébergement local d&#8217;un LLM peut être réalisé à l&#8217;aide d&#8217;outils tels que <a href="https://lmstudio.ai/" target="_blank" rel="noreferrer noopener">LM Studio</a>. Ceux-ci vous permettent de télécharger différents modèles au format GGUF. Un onglet séparé dans l&#8217;application vous permet de démarrer un serveur d&#8217;inférence utilisant le protocole HTTP autour d&#8217;un modèle téléchargé et activé, qui simule l&#8217;API d&#8217;OpenAI. Une fois ce serveur mis en place, par exemple sur le port 1234, le modèle est accessible via un appel à <code>http://localhost:1234/v1/chat/completions</code> . </p>



<p>Cette configuration dans l&#8217;extension Continue se fait par l&#8217;ajout du LLM au fichier <code>.continue/config.json</code>, suivant <a href="https://docs.continue.dev/customize/overview" target="_blank" rel="noreferrer noopener">ces instructions</a> et selon les directives pour <a href="https://docs.continue.dev/customize/model-providers/more/lmstudio" target="_blank" rel="noreferrer noopener">LM Studio en tant que fournisseur de modèle</a>. Vous pouvez adapter le titre et le modèle comme bon vous semble, et il vous suffit d&#8217;ajouter la ligne <code>"apiBase":"http://127.0.0.1:1234/v1"</code> Dans l&#8217;extension, vous verrez alors apparaître une nouvelle option, et vous pourrez commencer à l&#8217;utiliser. </p>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2024/03/2024-03-11_15h06_39.png"><img loading="lazy" decoding="async" width="1024" height="550" src="/wp-content/uploads/2024/03/2024-03-11_15h06_39-1024x550.png" alt="" class="wp-image-20217" srcset="https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_15h06_39-1024x550.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_15h06_39-300x161.png 300w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_15h06_39-768x412.png 768w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_15h06_39-1536x825.png 1536w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_15h06_39.png 1918w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">LM Studio, avec le modèle CodeNinja chargé, répond à une requête via le serveur intégré actif sur le port 1234.&nbsp;</figcaption></figure>



<h2 class="wp-block-heading"><strong>Interlude&nbsp;: à propos du matériel</strong></h2>



<p>La gestion des GPU n&#8217;est déjà pas une partie de plaisir pour un développeur sur une seule machine. Les problèmes d&#8217;incompatibilité entre les différentes versions de toutes sortes de bibliothèques logicielles et de pilotes de GPU peuvent prendre des jours à résoudre. L&#8217;<a href="https://www.nvidia.com/en-us/data-center/products/" target="_blank" rel="noreferrer noopener">offre du marché des GPUs pour data centers</a>, dominée par le monopole de nVIDIA, reste d&#8217;un coût prohibitif. À cela s&#8217;ajoute le coût de l&#8217;acquisition des connaissances très spécialisées nécessaires au fonctionnement de ces systèmes. Le matériel que vous choisirez sera probablement complètement obsolète dans quelques années. Un nouveau matériel, conçu spécifiquement pour accélérer le type de calculs des modèles d&#8217;IA, fait l&#8217;objet d&#8217;un travail acharné. Google a déjà présenté le <a href="https://en.wikipedia.org/wiki/Tensor_Processing_Unit" target="_blank" rel="noreferrer noopener">TPU</a>, mais d&#8217;autres fabricants se concentrent aujourd&#8217;hui pleinement sur les <a href="https://www.techradar.com/computing/cpu/what-is-an-npu" target="_blank" rel="noreferrer noopener">NPU (Neural Processing Units)</a>, et certains osent entrer en <a href="https://www.cerebras.net/" target="_blank" rel="noreferrer noopener">concurrence directe</a> avec nVIDIA.&nbsp;&nbsp;</p>



<p>Si vous n&#8217;avez pas le temps de vous occuper des pilotes de GPU et que vous n&#8217;avez pas l&#8217;ambition d&#8217;entraîner les modèles vous-même, la possibilité de les utiliser sur un CPU ordinaire est plus que bienvenue. Bien sûr, vous êtes alors limité aux LLM ou aux modèles d&#8217;IA dont la taille le permet. Les LLM &#8220;domestiques&#8221; typiques ont 3, 7 ou 13 milliards de paramètres ; les modèles plus grands sont <a href="https://github.com/ggerganov/llama.cpp#memorydisk-requirements" target="_blank" rel="noreferrer noopener">agressivement quantifiés</a> pour économiser de l&#8217;espace sur le disque et la mémoire.&nbsp; Ils ne seront pas en mesure d&#8217;égaler la qualité de GPT-4 aujourd&#8217;hui, mais heureusement, des classements existent pour aider à opérer un choix &#8211; pour <a href="https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard" target="_blank" rel="noreferrer noopener">les LLM ouverts en général</a>, spécifiquement avec <a href="https://huggingface.co/spaces/optimum/llm-perf-leaderboard" target="_blank" rel="noreferrer noopener">des benchmarks de vitesse (débit)</a>, ou pour <a href="https://huggingface.co/spaces/bigcode/bigcode-models-leaderboard" target="_blank" rel="noreferrer noopener">les LLM générateurs de code</a> en particulier.&nbsp;</p>



<p>Plus les LLM sont grands, plus la qualité du résultat est élevée (en général), mais plus la mémoire et la puissance de traitement requises sont importantes. Un LLM doit de préférence pouvoir être entièrement chargé dans la mémoire, de sorte que 16 GB de RAM n&#8217;est pas un luxe &#8211; plus c&#8217;est encore mieux, surtout si vous voulez faire fonctionner un IDE sur la même machine. Pour fournir une réponse, le modèle complet doit souvent être exécuté plusieurs fois. Par conséquent, le goulot d&#8217;étranglement est souvent la bande passante entre le CPU et la RAM. Les CPU dotés d&#8217;une grande mémoire cache interne semblent avoir une longueur d&#8217;avance (voir également les benchmarks spécifiques à l&#8217;IA [<a href="https://www.anandtech.com/show/21084/intel-core-i9-14900k-core-i7-14700k-and-core-i5-14600k-review-raptor-lake-refreshed/10" target="_blank" rel="noreferrer noopener">1</a>,<a href="https://www.anandtech.com/show/21242/amd-ryzen-7-8700g-and-ryzen-5-8600g-review/8" target="_blank" rel="noreferrer noopener">2</a>] d&#8217;Anandtech). Lors du choix du reste du matériel, la bande passante de la mémoire devrait certainement entrer en ligne de compte. Même ceux choisissant un GPU pourraient préférer considérer cette bande passante plutôt que le nombre de cœurs du GPU. Enfin, dans les environnements virtualisés (VM, VPS), il est important que le CPU virtuel prenne en charge les mêmes jeux d&#8217;instructions avancés, tels que <a href="https://en.wikipedia.org/wiki/AVX-512#CPUs_with_AVX-512" target="_blank" rel="noreferrer noopener">AVX-512</a>.&nbsp;</p>



<h2 class="wp-block-heading"><strong>Un LLM sur votre serveur</strong>&nbsp;</h2>



<p>Si vous disposez d&#8217;une machine plus puissante, il peut être intéressant d&#8217;y exécuter le LLM. <a href="https://ollama.com/" target="_blank" rel="noreferrer noopener">ollama</a> est probablement l&#8217;outil le plus populaire pour héberger des modèles sur Mac ou Linux sans trop de difficultés, et depuis peu également sur Windows. <a href="https://localai.io/" target="_blank" rel="noreferrer noopener">LocalAI</a> est toutefois une option tout aussi intéressante dans la liste des <a href="https://continue.dev/docs/model-setup/select-provider" target="_blank" rel="noreferrer noopener">fournisseurs de LLM pour Continue</a>, car il propose des conteneurs Docker, avec ou sans support GPU. Sur une machine Linux équipée de Docker, un <a href="https://localai.io/basics/getting_started/" target="_blank" rel="noreferrer noopener">one-liner</a> dans le terminal suffit pour télécharger le modèle CodeLlama open source et l&#8217;héberger sur le port 1234 :&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" data-code="docker run -ti -p 1234:8080 localai/localai:v2.7.0-ffmpeg-core codellama-7b-gguf " style="color:#000000;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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: #795E26">docker</span><span style="color: #000000"> </span><span style="color: #A31515">run</span><span style="color: #000000"> </span><span style="color: #0000FF">-ti</span><span style="color: #000000"> </span><span style="color: #0000FF">-p</span><span style="color: #000000"> </span><span style="color: #098658">1234</span><span style="color: #A31515">:8080</span><span style="color: #000000"> </span><span style="color: #A31515">localai/localai:v2.7.0-ffmpeg-core</span><span style="color: #000000"> </span><span style="color: #A31515">codellama-7b-gguf</span><span style="color: #000000"> </span></span></code></pre></div>



<p></p>



<p>Cependant, son démarrage prend un certain temps, car le modèle est téléchargé dans le conteneur. Il est plus intéressant de stocker soi-même une série de modèles dans un répertoire local et d&#8217;y associer une API à l&#8217;aide d&#8217;un conteneur LocalAI. Des <a href="https://localai.io/docs/getting-started/models/" target="_blank" rel="noreferrer noopener">instructions</a> relativement simples sont disponibles pour cela aussi. Nous pouvons par exemple les appliquer au LLM <a href="https://huggingface.co/TheBloke/deepseek-coder-6.7B-instruct-GGUF" target="_blank" rel="noreferrer noopener">LLM DeepSeek de 6,7 milliards de paramètres, quantifiés à 4 bits</a>. Il peut être téléchargé directement depuis Huggingface dans le répertoire local ./models-gguf à l&#8217;aide d&#8217;une commande wget du type : </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" data-code="wget https://huggingface.co/TheBloke/deepseek-coder-6.7B-instruct-GGUF/resolve/main/deepseek-coder-6.7b-instruct.Q4_K_M.gguf -O ./models-gguf/deepseek-6.7b-instruct-Q4" style="color:#000000;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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: #795E26">wget</span><span style="color: #000000"> </span><span style="color: #A31515">https://huggingface.co/TheBloke/deepseek-coder-6.7B-instruct-GGUF/resolve/main/deepseek-coder-6.7b-instruct.Q4_K_M.gguf</span><span style="color: #000000"> </span><span style="color: #0000FF">-O</span><span style="color: #000000"> </span><span style="color: #A31515">./models-gguf/deepseek-6.7b-instruct-Q4</span></span></code></pre></div>



<p></p>



<p>Démarrer une API autour des modèles de ce répertoire sur le port 8001 (vous pouvez aussi placer plusieurs modèles dans le même répertoire et les héberger simultanément), peut alors se faire avec la commande suivante . Ajoutez éventuellement <em><code>-d</code></em> pour qu&#8217;elle s&#8217;exécute en arrière-plan, et n&#8217;hésitez pas à expérimenter les paramètres <em><code>context-size</code></em> et <em><code>threads</code> </em>en fonction de la puissance de votre serveur&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;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="docker run -p 8001:8080 -v $PWD/models-gguf:/models -ti --rm quay.io/go-skynet/local-ai:v2.7.0-ffmpeg-core --models-path /models --context-size 1600 --threads 16" style="color:#000000;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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: #795E26">docker</span><span style="color: #000000"> </span><span style="color: #A31515">run</span><span style="color: #000000"> </span><span style="color: #0000FF">-p</span><span style="color: #000000"> </span><span style="color: #098658">8001</span><span style="color: #A31515">:8080</span><span style="color: #000000"> </span><span style="color: #0000FF">-v</span><span style="color: #000000"> </span><span style="color: #001080">$PWD</span><span style="color: #A31515">/models-gguf:/models</span><span style="color: #000000"> </span><span style="color: #0000FF">-ti</span><span style="color: #000000"> </span><span style="color: #0000FF">--rm</span><span style="color: #000000"> </span><span style="color: #A31515">quay.io/go-skynet/local-ai:v2.7.0-ffmpeg-core</span><span style="color: #000000"> </span><span style="color: #0000FF">--models-path</span><span style="color: #000000"> </span><span style="color: #A31515">/models</span><span style="color: #000000"> </span><span style="color: #0000FF">--context-size</span><span style="color: #000000"> </span><span style="color: #098658">1600</span><span style="color: #000000"> </span><span style="color: #0000FF">--threads</span><span style="color: #000000"> </span><span style="color: #098658">16</span></span></code></pre></div>



<p></p>



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



<p>Nous pouvons maintenant comparer différents LLM pour le code. Nous nous en tiendrons ici à l&#8217;anecdote et prendrons l&#8217;écriture d&#8217;un script shell <em>bash</em> comme exemple simple. Nous partons du problème suivant&nbsp;: une routine de sauvegarde a effectué des sauvegardes nocturnes d&#8217;un système pendant des années. Pour libérer de l&#8217;espace disque, nous voulons supprimer toutes les sauvegardes qui ne diffèrent pas des précédentes. Nous lançons la commande suivante, en décrivant la tâche le plus précisément possible afin d’obtenir les meilleurs résultats&nbsp;: <em>&#8220;Write a bash script that, given a directory, iterates over all its files in order of date of creation. For each file, if the filesize is equal to the filesize of the previous file, the file has to be deleted.&#8221;</em>&nbsp;</p>



<p></p>



<p></p>



<p>Le fichier <code>.continue/config.json</code> de notre extension Continue contient la liste suivante de modèles : un sur le propre ordinateur portable dans LM Studio chargé sur le port 1234, et deux sur un serveur séparé, mais sur le même réseau local, hébergé par LocalAI sur le port 8001.&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;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="    {
      &quot;title&quot;: &quot;myLaptop-LMStudio&quot;,
      &quot;model&quot;: &quot;whatever is loaded in LMstudio&quot;,
      &quot;apiBase&quot;: &quot;http://127.0.0.1:1234/v1&quot;,
      &quot;completionOptions&quot;: {},
      &quot;provider&quot;: &quot;lmstudio&quot;
    },       
    {
      &quot;title&quot;: &quot;localAI-mistral&quot;,
      &quot;model&quot;: &quot;mistral-7b-code16kqlora-Q4&quot;,
      &quot;apiBase&quot;: &quot;https://192.168.0.100:8001/v1&quot;,
      &quot;apiKey&quot;: &quot;&quot;,      
      &quot;completionOptions&quot;: {},
      &quot;provider&quot;: &quot;openai&quot;
    },
    {
      &quot;title&quot;: &quot;localAI-deepseek&quot;,
      &quot;model&quot;: &quot;deepseek-6.7b-instruct-Q4&quot;,
      &quot;apiBase&quot;: &quot;https://192.168.0.100:8001/v1&quot;,
      &quot;apiKey&quot;: &quot;&quot;,
      &quot;completionOptions&quot;: {},
      &quot;provider&quot;: &quot;openai&quot;
    }," style="color:#24292e;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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 github-light" style="background-color: #fff" tabindex="0"><code><span class="line"><span style="color: #24292E">    {</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;title&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;myLaptop-LMStudio&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;model&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;whatever is loaded in LMstudio&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;apiBase&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;http://127.0.0.1:1234/v1&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;completionOptions&quot;</span><span style="color: #24292E">: {},</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;provider&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;lmstudio&quot;</span></span>
<span class="line"><span style="color: #24292E">    },       </span></span>
<span class="line"><span style="color: #24292E">    {</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;title&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;localAI-mistral&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;model&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;mistral-7b-code16kqlora-Q4&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;apiBase&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;https://192.168.0.100:8001/v1&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;apiKey&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;&quot;</span><span style="color: #24292E">,      </span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;completionOptions&quot;</span><span style="color: #24292E">: {},</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;provider&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;openai&quot;</span></span>
<span class="line"><span style="color: #24292E">    },</span></span>
<span class="line"><span style="color: #24292E">    {</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;title&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;localAI-deepseek&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;model&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;deepseek-6.7b-instruct-Q4&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;apiBase&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;https://192.168.0.100:8001/v1&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;apiKey&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;completionOptions&quot;</span><span style="color: #24292E">: {},</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;provider&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;openai&quot;</span></span>
<span class="line"><span style="color: #24292E">    },</span></span></code></pre></div>



<p></p>



<p>Comme référence, nous prenons <a href="https://chat.openai.com/" target="_blank" rel="noreferrer noopener">ChatGPT</a>, qui propose la solution (correcte) suivante. &nbsp;<br>En outre, elle est également suivie d&#8217;une explication détaillée de la signification des différentes parties (non présentée ici) :&nbsp;</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="#!/bin/bash

# Directory containing the files
DIR=&quot;/path/to/your/directory&quot;

# Variable to hold the size of the previous file. Initialized to 0.
prev_size=0

# List all files in the directory, sorted by creation date
# Note: '%T@' sorts by creation time, '%p' prints the file's name
# 'sort -n' ensures the list is sorted numerically
# Note that creation time sorting may depend on filesystem and OS support
files=$(find &quot;$DIR&quot; -type f -printf &quot;%T@ %p\n&quot; | sort -n | cut -d ' ' -f 2-)

# Iterate over the sorted list of files
for file in $files; do
  # Get current file size
  current_size=$(stat -c %s &quot;$file&quot;)
  
  # Check if current file size is equal to the previous file's size
  if [ &quot;$current_size&quot; -eq &quot;$prev_size&quot; ]; then
    # Sizes are equal, delete the current file
    echo &quot;Deleting file: $file&quot;
    rm &quot;$file&quot;
  fi
  
  # Update previous size to current file's size
  prev_size=$current_size
done" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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 dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">#!/bin/bash</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Directory containing the files</span></span>
<span class="line"><span style="color: #9CDCFE">DIR</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;/path/to/your/directory&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Variable to hold the size of the previous file. Initialized to 0.</span></span>
<span class="line"><span style="color: #9CDCFE">prev_size</span><span style="color: #D4D4D4">=</span><span style="color: #B5CEA8">0</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># List all files in the directory, sorted by creation date</span></span>
<span class="line"><span style="color: #6A9955"># Note: &#39;%T@&#39; sorts by creation time, &#39;%p&#39; prints the file&#39;s name</span></span>
<span class="line"><span style="color: #6A9955"># &#39;sort -n&#39; ensures the list is sorted numerically</span></span>
<span class="line"><span style="color: #6A9955"># Note that creation time sorting may depend on filesystem and OS support</span></span>
<span class="line"><span style="color: #9CDCFE">files</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">find</span><span style="color: #CE9178"> &quot;</span><span style="color: #9CDCFE">$DIR</span><span style="color: #CE9178">&quot; </span><span style="color: #569CD6">-type</span><span style="color: #CE9178"> f </span><span style="color: #569CD6">-printf</span><span style="color: #CE9178"> &quot;%T@ %p\n&quot; </span><span style="color: #D4D4D4">|</span><span style="color: #CE9178"> </span><span style="color: #DCDCAA">sort</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-n</span><span style="color: #CE9178"> </span><span style="color: #D4D4D4">|</span><span style="color: #CE9178"> </span><span style="color: #DCDCAA">cut</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-d</span><span style="color: #CE9178"> &#39; &#39; </span><span style="color: #569CD6">-f</span><span style="color: #CE9178"> </span><span style="color: #B5CEA8">2</span><span style="color: #CE9178">-)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Iterate over the sorted list of files</span></span>
<span class="line"><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">file</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">$files</span><span style="color: #D4D4D4">; </span><span style="color: #C586C0">do</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #6A9955"># Get current file size</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #9CDCFE">current_size</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">stat</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-c</span><span style="color: #CE9178"> %s &quot;</span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #6A9955"># Check if current file size is equal to the previous file&#39;s size</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [ </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$current_size</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4"> -eq </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$prev_size</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4"> ]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># Sizes are equal, delete the current file</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">echo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Deleting file: </span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">rm</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">fi</span></span>
<span class="line"><span style="color: #D4D4D4">  </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #6A9955"># Update previous size to current file&#39;s size</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #9CDCFE">prev_size</span><span style="color: #D4D4D4">=</span><span style="color: #9CDCFE">$current_size</span></span>
<span class="line"><span style="color: #C586C0">done</span></span></code></pre></div>



<p></p>



<p>Dans LMStudio, nous chargeons le modèle &#8220;<a href="https://huggingface.co/TheBloke/CodeNinja-1.0-OpenChat-7B-GGUF" target="_blank" rel="noreferrer noopener">CodeNinja 1.0 openchat 7B Q4_K_M</a>&#8220;. Il faut plus d&#8217;une minute pour générer la réponse à la même question&nbsp;: 20 secondes d&#8217;attente pour l&#8217;apparition de la première lettre de la réponse, puis environ 2 secondes par ligne (bien sûr, notre ordinateur portable n&#8217;est pas très puissant&nbsp;: un CPU Core i7-10610U avec 32GB de RAM). Le résultat se présente comme suit :&nbsp;</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="#!/bin/bash

for f in $(ls -t -l --time-style=full /path/to/directory)
do
  if [[ $f == &quot;total&quot;* ]]; then
        continue;
    fi
    filename=$(basename &quot;${f% *}&quot;)

    # Checks whether the file is already deleted. If not, compares it with the previous file:
    prev_file=&quot;&quot;
    while IFS= read -r line; do
        if [[ $line == $filename ]]; then
            prev_file=$line
            break;
        fi
    done &lt;&lt;&lt;&quot;$(ls -l /path/to/directory | tail -n 2)&quot;

    if [[ -z $prev_file || &quot;$f&quot; = &quot;${prev_file}&quot; ]]; then
        # If the file is deleted, nothing to do. If not, deletes it:
        if [[ -z $prev_file ]] || [[ &quot;$(stat -c %s ${filename})&quot; == &quot;$(stat -c %s ${prev_file})&quot; ]]; then
            rm /path/to/directory/$filename
        fi
    fi
done" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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 dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">#!/bin/bash</span></span>
<span class="line"></span>
<span class="line"><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">f</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">ls</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-t</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-l</span><span style="color: #CE9178"> </span><span style="color: #569CD6">--time-style=full</span><span style="color: #CE9178"> /path/to/directory)</span></span>
<span class="line"><span style="color: #C586C0">do</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [[ </span><span style="color: #9CDCFE">$f</span><span style="color: #D4D4D4"> == </span><span style="color: #CE9178">&quot;total&quot;</span><span style="color: #D4D4D4">* ]]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">continue</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">fi</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">filename</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">basename</span><span style="color: #CE9178"> &quot;${</span><span style="color: #9CDCFE">f</span><span style="color: #D4D4D4">%</span><span style="color: #CE9178"> </span><span style="color: #D4D4D4">*</span><span style="color: #CE9178">}&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># Checks whether the file is already deleted. If not, compares it with the previous file:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">prev_file</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">while</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">IFS</span><span style="color: #D4D4D4">= </span><span style="color: #DCDCAA">read</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-r</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">line</span><span style="color: #D4D4D4">; </span><span style="color: #C586C0">do</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [[ </span><span style="color: #9CDCFE">$line</span><span style="color: #D4D4D4"> == </span><span style="color: #9CDCFE">$filename</span><span style="color: #D4D4D4"> ]]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">prev_file</span><span style="color: #D4D4D4">=</span><span style="color: #9CDCFE">$line</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">break</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">fi</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">done</span><span style="color: #D4D4D4"> &lt;&lt;&lt;</span><span style="color: #CE9178">&quot;$(</span><span style="color: #DCDCAA">ls</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-l</span><span style="color: #CE9178"> /path/to/directory </span><span style="color: #D4D4D4">|</span><span style="color: #CE9178"> </span><span style="color: #DCDCAA">tail</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-n</span><span style="color: #CE9178"> </span><span style="color: #B5CEA8">2</span><span style="color: #CE9178">)&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [[ -z </span><span style="color: #9CDCFE">$prev_file</span><span style="color: #D4D4D4"> || </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$f</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4"> = </span><span style="color: #CE9178">&quot;${</span><span style="color: #9CDCFE">prev_file</span><span style="color: #CE9178">}&quot;</span><span style="color: #D4D4D4"> ]]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955"># If the file is deleted, nothing to do. If not, deletes it:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [[ -z </span><span style="color: #9CDCFE">$prev_file</span><span style="color: #D4D4D4"> ]] || [[ </span><span style="color: #CE9178">&quot;$(</span><span style="color: #DCDCAA">stat</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-c</span><span style="color: #CE9178"> %s ${</span><span style="color: #9CDCFE">filename</span><span style="color: #CE9178">})&quot;</span><span style="color: #D4D4D4"> == </span><span style="color: #CE9178">&quot;$(</span><span style="color: #DCDCAA">stat</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-c</span><span style="color: #CE9178"> %s ${</span><span style="color: #9CDCFE">prev_file</span><span style="color: #CE9178">})&quot;</span><span style="color: #D4D4D4"> ]]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #DCDCAA">rm</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/path/to/directory/</span><span style="color: #9CDCFE">$filename</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">fi</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">fi</span></span>
<span class="line"><span style="color: #C586C0">done</span></span></code></pre></div>



<p></p>



<p>Nous chargeons le <a href="https://huggingface.co/TheBloke/deepseek-coder-6.7B-instruct-GGUF" target="_blank" rel="noreferrer noopener">modèle DeepSeek de 6,7 milliards de paramètres</a> dans LocalAI sur une VM Debian dans Proxmox. La VM se voit allouer beaucoup de mémoire vive et 12 cœurs du micro-processeur AMD Threadripper 3960X sous-jacent (24 cœurs au total mais pas de support AVX-512). Nous créons ainsi à un rythme d&#8217;environ 3 lignes par seconde le résultat suivant :&nbsp;</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="#!/bin/bash

# Check if directory is provided
if [ $# -ne 1 ]; then
  echo &quot;Usage: $0 directory&quot;
    exit 1
fi

# Check if directory exists
if [&nbsp;! -d &quot;$1&quot; ]; then
    echo &quot;Directory $1 does not exist&quot;
    exit 1
fi

# Change to the directory
cd &quot;$1&quot;

# Get the list of files in order of creation date
files=$(ls -t)

# Initialize previous_size to 0
previous_size=0

# Iterate over the files
for file in $files; do
    # Get the size of the file
    size=$(stat -c%s &quot;$file&quot;)

    # If the size is equal to the previous size, delete the file
    if [ $size -eq $previous_size ]; then
        rm &quot;$file&quot;
        echo &quot;Deleted $file&quot;
    fi

    # Update previous_size
    previous_size=$size
done" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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 dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">#!/bin/bash</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Check if directory is provided</span></span>
<span class="line"><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [ </span><span style="color: #569CD6">$#</span><span style="color: #D4D4D4"> -ne </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4"> ]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">echo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Usage: </span><span style="color: #9CDCFE">$0</span><span style="color: #CE9178"> directory&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">exit</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span></span>
<span class="line"><span style="color: #C586C0">fi</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Check if directory exists</span></span>
<span class="line"><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [&nbsp;! -d </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$1</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4"> ]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">echo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Directory </span><span style="color: #9CDCFE">$1</span><span style="color: #CE9178"> does not exist&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">exit</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span></span>
<span class="line"><span style="color: #C586C0">fi</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Change to the directory</span></span>
<span class="line"><span style="color: #DCDCAA">cd</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$1</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Get the list of files in order of creation date</span></span>
<span class="line"><span style="color: #9CDCFE">files</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">ls</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-t</span><span style="color: #CE9178">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Initialize previous_size to 0</span></span>
<span class="line"><span style="color: #9CDCFE">previous_size</span><span style="color: #D4D4D4">=</span><span style="color: #B5CEA8">0</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Iterate over the files</span></span>
<span class="line"><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">file</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">$files</span><span style="color: #D4D4D4">; </span><span style="color: #C586C0">do</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># Get the size of the file</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">size</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">stat</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-c%s</span><span style="color: #CE9178"> &quot;</span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># If the size is equal to the previous size, delete the file</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [ </span><span style="color: #9CDCFE">$size</span><span style="color: #D4D4D4"> -eq </span><span style="color: #9CDCFE">$previous_size</span><span style="color: #D4D4D4"> ]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #DCDCAA">rm</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #DCDCAA">echo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Deleted </span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">fi</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># Update previous_size</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">previous_size</span><span style="color: #D4D4D4">=</span><span style="color: #9CDCFE">$size</span></span>
<span class="line"><span style="color: #C586C0">done</span></span></code></pre></div>



<p></p>



<p>Enfin, sur la même VM, nous pouvons également essayer Mistral, pour lequel nous choisissons au hasard la version <a href="https://huggingface.co/TheBloke/Mistral-7B-Code-16K-qlora-GGUF" target="_blank" rel="noreferrer noopener">mistral-7B-code-16K-qlora</a> qui a été légèrement adaptée par <em>fine-tuning</em> pour le code par un internaute. Il s&#8217;avère que sa réponse est rapide, générant le résultat compact suivant en quelque 2 secondes (malheureusement sans documentation, et en proposant la commande complexe <em>awk</em> ) :&nbsp;</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="for file in $(find directory -type f -exec du -sh {} + | sort -h | awk '{print NR &quot;:\t&quot; $1}'); do
    size=$(du -sh &quot;$file&quot; | awk '{print $1}')
    if [[ $size == $previous_size ]]; then
      rm &quot;$file&quot;
    fi
    previous_size=$size
done" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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 dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">file</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">find</span><span style="color: #CE9178"> directory </span><span style="color: #569CD6">-type</span><span style="color: #CE9178"> f </span><span style="color: #569CD6">-exec</span><span style="color: #CE9178"> du </span><span style="color: #569CD6">-sh</span><span style="color: #CE9178"> {} + </span><span style="color: #D4D4D4">|</span><span style="color: #CE9178"> </span><span style="color: #DCDCAA">sort</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-h</span><span style="color: #CE9178"> </span><span style="color: #D4D4D4">|</span><span style="color: #CE9178"> </span><span style="color: #DCDCAA">awk</span><span style="color: #CE9178"> &#39;{print NR &quot;:\t&quot; $1}&#39;)</span><span style="color: #D4D4D4">; </span><span style="color: #C586C0">do</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">size</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">du</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-sh</span><span style="color: #CE9178"> &quot;</span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot; </span><span style="color: #D4D4D4">|</span><span style="color: #CE9178"> </span><span style="color: #DCDCAA">awk</span><span style="color: #CE9178"> &#39;{print $1}&#39;)</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [[ </span><span style="color: #9CDCFE">$size</span><span style="color: #D4D4D4"> == </span><span style="color: #9CDCFE">$previous_size</span><span style="color: #D4D4D4"> ]]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">rm</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">fi</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">previous_size</span><span style="color: #D4D4D4">=</span><span style="color: #9CDCFE">$size</span></span>
<span class="line"><span style="color: #C586C0">done</span></span></code></pre></div>



<p></p>



<p>Je laisse volontiers au lecteur le soin de procéder à une comparaison plus approfondie de ces résultats. Si nous devons tirer une dernière leçon de cette expérience, c&#8217;est que même si les modèles ont le même nombre de paramètres et sont entraînés dans le même but, il peut y avoir de très grandes différences de résultat et de style entre eux&nbsp;! &nbsp;</p>



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



<p>À la vitesse de l&#8217;éclair, toutes sortes de fonctions alimentées par l&#8217;IA trouvent leur place dans l&#8217;IDE. Les <a href="https://code.visualstudio.com/updates/v1_87" target="_blank" rel="noreferrer noopener">dernières notes de mises à jour de Visual Studio Code</a> mentionnent, par exemple, la prise en charge de la reconnaissance vocale dans plusieurs langues, en plus de plusieurs fonctionnalités de CoPilot. En tant que développeur, il est inévitable que vous soyez confronté à cette situation. Les développeurs qui travaillent avec des données sensibles ou du code protégé par des droits d&#8217;auteur doivent se méfier à juste titre de ces outils qui envoient le contenu de leur IDE à un service cloud tiers pour proposer des suggestions.&nbsp;&nbsp;</p>



<p>Grâce notamment au projet <a href="https://github.com/ggerganov/llama.cpp" target="_blank" rel="noreferrer noopener">llama.cpp</a>, une voie alternative open source a récemment vu le jour, qui permet de mettre en place et d&#8217;exploiter soi-même une telle assistance au codage avec des LLM. Les modèles plus petits qui peuvent fonctionner sur du matériel grand public n&#8217;offrent actuellement pas la même qualité et la même vitesse que Github CoPilot ou ChatGPT. Toutefois, de nouvelles améliorations apparaîtront régulièrement au cours des prochaines années, de sorte que la voie à suivre semble prometteuse à tous points de vue.&nbsp;&nbsp;</p>



<p>______________________</p>



<p><em><em>Ce post est une contribution individuelle de Joachim Ganseman, spécialisée en intelligence artificielle chez Smals Research. Cet article est écrit en son nom propre et n’impacte en rien le point de vue de Smals.</em></em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Aan de slag met open source coding assistants</title>
		<link>https://www.smalsresearch.be/opensource-coding-assistants/</link>
		
		<dc:creator><![CDATA[Joachim Ganseman]]></dc:creator>
		<pubDate>Mon, 11 Mar 2024 15:42:44 +0000</pubDate>
				<category><![CDATA[[NL]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[chatbot]]></category>
		<category><![CDATA[computational creativity]]></category>
		<category><![CDATA[egov]]></category>
		<category><![CDATA[Natural Language Processing]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Programming]]></category>
		<guid isPermaLink="false">/?p=20178</guid>

					<description><![CDATA[Een privacyvriendelijke coding assistant voor een IDE met open source tools - hoe doe je dat?]]></description>
										<content:encoded><![CDATA[
<p><em>Cet article est aussi disponible <a href="/opensource-coding-assistants-fr/">en français</a>.</em></p>



<p>Als code-genererend hulpmiddel voor softwareontwikkelaars domineert <a href="https://github.com/features/copilot">Github Copilot</a> vandaag de markt. Dat zal wellicht nog wel even aanhouden, zeker nu de tool ook wordt uitgebreid met chatfunctionaliteit à la ChatGPT. Als eigendom van Microsoft, geniet Github van een directe lijn met OpenAI en zo kan het als eerste meegenieten van de voortrekkersrol die dat bedrijf blijft spelen inzake de ontwikkeling van <a href="https://en.wikipedia.org/wiki/Large_language_model">Large Language Models (LLMs)</a>.</p>



<p>Men zou haast vergeten dat er ook andere mogelijkheden zijn. Het eerste grootschalige alternatief dat van de grond af open-source was opgebouwd, inclusief <a href="https://huggingface.co/datasets/bigcode/the-stack">open trainingsdata</a>, is <a href="https://huggingface.co/blog/starcoder">StarCoder</a>, waar sinds kort ook een <a href="https://github.com/bigcode-project/starcoder2">versie 2</a> van is uitgekomen. Het wordt ontwikkeld onder het <a href="https://www.bigcode-project.org/">BigCode initiatief</a> van ServiceNow en HuggingFace. De <a href="https://arxiv.org/abs/2305.06161">bijhorende paper </a>geeft een fascinerende inkijk in de opbouw van een taalmodel voor het genereren van code. Kort na StarCoder verschenen <a href="https://arxiv.org/abs/2306.08568">WizardCoder</a>, <a href="https://arxiv.org/abs/2308.12950">CodeLLama</a>, <a href="https://github.com/deepseek-ai/DeepSeek-Coder">DeepSeekCoder</a> en nog enkele anderen ten tonele &#8211; niet allemaal met een open dataset erachter, maar wel vrij toegankelijk en herbruikbaar via <a href="https://huggingface.co/">HuggingFace</a>. </p>



<p>Ondertussen is er voldoende tooling beschikbaar om deze modellen gemakkelijker op een eigen machine te draaien. &#8220;Your Own Personal Coding Assistant&#8221;, self-hosted en volledig privaat, is vandaag haalbare kaart. We hebben daarvoor nodig: voldoende krachtige hardware, een LLM toegespitst op <em>code completion</em> taken of op conversaties over code, en een plugin voor de IDE. LLM en IDE plugin spreken met elkaar via een API, die al dan niet compatibel kan zijn met die van OpenAI &#8211; wat desgewenst toelaat gemakkelijk te wisselen tussen commerciële (OpenAI) en open source modellen.</p>



<h2 class="wp-block-heading">IDE plugins</h2>



<p>Een plugin installeren is op zich gemakkelijk. Github Copilot bestaat al langer als <a href="https://code.visualstudio.com/docs/editor/github-copilot">plugin voor VSCode</a> en vandaag ook voor <a href="https://plugins.jetbrains.com/plugin/17718-github-copilot">IntelliJ IDEA</a> &#8211; al bevat de IntelliJ versie op moment van schrijven nog wat minder  functionaliteit. </p>



<p>Onder de open-source alternatieven hoort <a href="https://continue.dev/">Continue</a> momenteel waarschijnlijk bij de top. Er zijn er andere – Huggingface zelf heeft bijvoorbeeld <a href="https://github.com/huggingface/llm-vscode?tab=readme-ov-file">llm-vscode</a> ontwikkeld – en ongetwijfeld zullen er nog bijkomen. Net zoals Github Copilot bestaat Continue ook als <a href="https://marketplace.visualstudio.com/items?itemName=Continue.continue">plugin voor VSCode</a> of <a href="https://plugins.jetbrains.com/plugin/22707-continue">IntelliJ</a>. Het kan zowel gebruikmaken van commerciële cloud-based generatoren (waaronder GPT-4) als van zelf gehoste open-source oplossingen. Die hoeven niet noodzakelijk de OpenAI API na te volgen, en er is veel customizatie mogelijk.</p>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2024/03/2024-03-11_14h59_32.png"><img loading="lazy" decoding="async" width="1024" height="410" src="/wp-content/uploads/2024/03/2024-03-11_14h59_32-1024x410.png" alt="" class="wp-image-20216" srcset="https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_14h59_32-1024x410.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_14h59_32-300x120.png 300w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_14h59_32-768x308.png 768w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_14h59_32-1536x615.png 1536w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_14h59_32.png 1858w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Screenshot van de Continue plugin in Visual Studio Code</figcaption></figure>



<p>Het blijft belangrijk om tijd te investeren om met de plugin te leren werken. De <a href="https://continue.dev/docs/intro">documentatie van Continue</a> is een goed startpunt. Voor elke <a href="https://continue.dev/docs/model-setup/select-provider">server</a> en elke <a href="https://continue.dev/docs/model-setup/select-model">LLM</a> kunnen er andere configuratieopties zijn die ingesteld moeten worden, en misschien wil je custom aanpassingen maken aan de achterliggende <a href="https://continue.dev/docs/model-setup/configuration">prompt</a>. Daarnaast is het nodig om te weten hoe de plugin geactiveerd en gedeactiveerd kan worden in de IDE, en welke shortcuts en <a href="https://continue.dev/docs/customization/slash-commands">commando&#8217;s</a> er bestaan. <a href="https://www.youtube.com/results?search_query=continue+ai">YouTube</a> kan een goed startpunt zijn om tutorials en voorbeelden van andere gebruikers te vinden.</p>



<h2 class="wp-block-heading">Een LLM op je laptop</h2>



<p>Vooral onder impuls van het open-source project <a href="https://github.com/ggerganov/llama.cpp">llama.cpp</a>, zijn er het afgelopen jaar enorme inspanningen gebeurd om LLMs ook inzetbaar te maken op gewone consumentenhardware. Een peperdure GPU is niet meer noodzakelijk, al gaat het met GPU wel nog steeds sneller. In grote lijnen laat <a href="https://github.com/ggerganov/llama.cpp">llama.cpp</a> toe om een model te herverpakken in het GGUF formaat (GPT-Generated Unified Format). Daarbij worden zoveel mogelijk optimalisaties toegepast:</p>



<ul class="wp-block-list">
<li>gebruik van efficiënte CPU-instructiesets zoals <a href="https://en.wikipedia.org/wiki/AVX-512">AVX-512</a> &#8211; het spreekt voor zich dat de hardware waarop het model later moet draaien, deze instructiesets ook moet ondersteunen,</li>



<li>gebruik van sterk geoptimaliseerde high-performance libraries voor de achterliggende berekeningen, zoals <a href="https://github.com/OpenMathLib/OpenBLAS">openBLAS</a> of Apples <a href="https://developer.apple.com/documentation/accelerate">Accelerate</a> en <a href="https://developer.apple.com/metal/">Metal</a>,</li>



<li>het <em>kwantiseren </em>van het model, door het reduceren van de <a href="https://en.wikipedia.org/wiki/Precision_(computer_science)">precisie</a> van de gewichten in de lagen van de neurale netwerken. De 16-bit of 32-bit (komma)getallen uit het originele model worden daarbij omgezet naar gehele getallen (integers) van 8-bit, zelfs 6-bit of 4-bit. Dit bespaart geheugen en versnelt de berekeningen, ten koste van een relatief klein kwaliteitsverlies.</li>
</ul>



<p>Lokaal een LLM hosten kan met tools zoals <a href="https://lmstudio.ai/">LM Studio</a>. Die geven je de mogelijkheid om verschillende modellen te downloaden in GGUF formaat. Een apart tabblad in de applicatie laat toe om een HTTP Inference server rond een gedownload en ingeladen model op te starten, die de API van OpenAI simuleert. Eens deze opgezet is, bijvoorbeeld op poort 1234, is het model aanspreekbaar via een call naar  <code>http://localhost:1234/v1/chat/completions</code> . </p>



<p>Dit instellen in de Continue plugin gebeurt door de LLM toe te voegen aan het bestand <code>.continue/config.json</code> , volgens <a href="https://docs.continue.dev/customize">deze instructies</a> en volgens de richtlijnen voor <a href="https://docs.continue.dev/customize/model-providers/more/lmstudio">LM Studio als model provider</a>. Daarbij kan je de titel en het model aanpassen naar eigen goeddunken, en hoef je enkel nog de lijn <code>"apiBase":"http://127.0.0.1:1234/v1"</code> toe te voegen. In de plugin zal je dit dan als nieuwe keuzemogelijkheid zien verschijnen, en kan je ermee aan de slag.</p>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2024/03/2024-03-11_15h06_39.png"><img loading="lazy" decoding="async" width="1024" height="550" src="/wp-content/uploads/2024/03/2024-03-11_15h06_39-1024x550.png" alt="" class="wp-image-20217" srcset="https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_15h06_39-1024x550.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_15h06_39-300x161.png 300w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_15h06_39-768x412.png 768w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_15h06_39-1536x825.png 1536w, https://www.smalsresearch.be/wp-content/uploads/2024/03/2024-03-11_15h06_39.png 1918w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">LM Studio, met het CodeNinja model ingeladen, beantwoordt een query via de ingebouwde server die actief is op poort 1234. </figcaption></figure>



<h2 class="wp-block-heading">Intermezzo: over hardware</h2>



<p>Het beheer van GPU&#8217;s is al geen pretje voor 1 developer aan 1 machine. Incompatibiliteitsproblemen tussen verschillende versies van allerlei software libraries en GPU-drivers kunnen dagen duren om op te lossen. Het <a href="https://www.nvidia.com/en-us/data-center/products/">marktaanbod van GPUs voor datacenters</a>, gedomineerd door nVIDIA in een monopoliepositie, is onnoemelijk duur. Daarbij komt nog de kost van het opbouwen van de heel gespecialiseerde kennis die nodig is om die systemen draaiende te houden. Eender wat je kiest van hardware is over 4 jaar waarschijnlijk al helemaal verouderd. Er wordt hard gewerkt aan nieuwe hardware, specifiek gemaakt om het soort berekeningen van AI-modellen te versnellen &#8211; Google kwam eerder al met de <a href="https://en.wikipedia.org/wiki/Tensor_Processing_Unit">TPU</a>, maar andere fabrikanten zetten nu ook hard in op <a href="https://www.techradar.com/computing/cpu/what-is-an-npu">NPUs (Neural Processing Units)</a>, en sommigen durven <a href="https://www.cerebras.net/">directe concurrentie</a> aan met nVIDIA. </p>



<p>Als je geen tijd hebt om te knoeien met GPU-drivers en niet de ambitie hebt om zelf modellen te trainen, dan is de mogelijkheid om ze te gebruiken op een gewone CPU meer dan welkom. Uiteraard ben je dan wel beperkt tot die LLMs of AI-modellen waarvan de grootte dat ook toelaat. Typische LLMs voor &#8220;thuisgebruik&#8221; hebben 3, 7 of 13 miljard parameters; grotere modellen worden <a href="https://github.com/ggerganov/llama.cpp#memorydisk-requirements">agressief gekwantiseerd</a> om schijfruimte en geheugen te besparen. Ze gaan vandaag nog niet kunnen tippen aan de kwaliteit van GPT-4, maar er bestaan gelukkig leaderboards om te helpen een keuze te maken &#8211; voor <a href="https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard">open LLMs in het algemeen</a>, specifiek met <a href="https://huggingface.co/spaces/optimum/llm-perf-leaderboard">(doorvoer)snelheidsbenchmarks</a>, of voor <a href="https://huggingface.co/spaces/bigcode/bigcode-models-leaderboard">code-genererende LLMs</a> in het bijzonder.</p>



<p>Hoe groter de LLMs, hoe kwaliteitsvoller het resultaat (meestal), maar ook hoe meer geheugen en rekenkracht vereist is. Een LLM moet liefst volledig in het geheugen ingeladen kunnen worden, dus 16GB RAM is geen luxe &#8211; meer is beter, zeker als je een IDE op dezelfde machine wil draaien. Om een antwoord te kunnen te geven, moet het volledige model vaak meermaals doorlopen worden. De bottleneck wordt bijgevolg vaak gevormd door de bandbreedte tussen CPU en RAM. CPUs met een grote interne cache lijken een streepje voor te hebben (zie ook AI-specifieke benchmarks [<a href="https://www.anandtech.com/show/21084/intel-core-i9-14900k-core-i7-14700k-and-core-i5-14600k-review-raptor-lake-refreshed/10">1</a>,<a href="https://www.anandtech.com/show/21242/amd-ryzen-7-8700g-and-ryzen-5-8600g-review/8">2</a>] van Anandtech). Bij de keuze van de rest van de hardware moet geheugenbandbreedte zeker meespelen. Ook wie een GPU zou willen kiezen, kijkt misschien liever naar die bandbreedte dan naar het aantal cores. Tot slot is het in gevirtualiseerde omgevingen (een VM, een VPS) belangrijk dat de virtuele CPU dezelfde geavanceerde instructiesets, zoals <a href="https://en.wikipedia.org/wiki/AVX-512#CPUs_with_AVX-512">AVX-512</a>, ondersteunt.</p>



<h2 class="wp-block-heading">Een LLM op je server</h2>



<p>Als je elders een krachtigere machine hebt, kan het de moeite waard zijn om de LLM daarop te draaien. <a href="https://ollama.com/">ollama</a> is waarschijnlijk de populairste tool om zonder veel poespas modellen te hosten op Mac of Linux, sinds kort ook Windows. <a href="https://localai.io/">LocalAI</a> is echter een zeker zo interessante optie uit de lijst van mogelijke <a href="https://continue.dev/docs/model-setup/select-provider">LLM providers voor Continue</a>, want het biedt Docker containers aan, met of zonder GPU ondersteuning. Op een Linux machine die is uitgerust met Docker, is <a href="https://localai.io/basics/getting_started/">een oneliner</a> in de terminal voldoende om het open-source CodeLlama model te downloaden en te beginnen hosten op poort 1234:</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" data-code="docker run -ti -p 1234:8080 localai/localai:v2.7.0-ffmpeg-core codellama-7b-gguf " style="color:#000000;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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: #795E26">docker</span><span style="color: #000000"> </span><span style="color: #A31515">run</span><span style="color: #000000"> </span><span style="color: #0000FF">-ti</span><span style="color: #000000"> </span><span style="color: #0000FF">-p</span><span style="color: #000000"> </span><span style="color: #098658">1234</span><span style="color: #A31515">:8080</span><span style="color: #000000"> </span><span style="color: #A31515">localai/localai:v2.7.0-ffmpeg-core</span><span style="color: #000000"> </span><span style="color: #A31515">codellama-7b-gguf</span><span style="color: #000000"> </span></span></code></pre></div>



<p></p>



<p>De opstart ervan duurt echter even, want het model wordt in de container gedownload. Interessanter is het om zelf een reeks modellen in een lokale map te bewaren, en daaromheen een API te zetten middels een LocalAI container. Ook voor die aanpak zijn relatief eenvoudige <a href="https://localai.io/docs/getting-started/models/">instructies</a> beschikbaar. We kunnen ze bijvoorbeeld toepassen op de <a href="https://huggingface.co/TheBloke/deepseek-coder-6.7B-instruct-GGUF">DeepSeek LLM van 6.7 miljard parameters, gekwantiseerd op 4 bits</a>. Deze kan rechtstreeks van Huggingface gedownload worden naar de lokale map <code>./models-gguf</code> met een <code>wget</code> commando van het type:</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" data-code="wget https://huggingface.co/TheBloke/deepseek-coder-6.7B-instruct-GGUF/resolve/main/deepseek-coder-6.7b-instruct.Q4_K_M.gguf -O ./models-gguf/deepseek-6.7b-instruct-Q4" style="color:#000000;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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: #795E26">wget</span><span style="color: #000000"> </span><span style="color: #A31515">https://huggingface.co/TheBloke/deepseek-coder-6.7B-instruct-GGUF/resolve/main/deepseek-coder-6.7b-instruct.Q4_K_M.gguf</span><span style="color: #000000"> </span><span style="color: #0000FF">-O</span><span style="color: #000000"> </span><span style="color: #A31515">./models-gguf/deepseek-6.7b-instruct-Q4</span></span></code></pre></div>



<p></p>



<p>Een API starten rondom de modellen in die map op poort 8001 (je kan ook meerdere modellen in dezelfde map zetten en ze tegelijk hosten), kan dan met het volgende commando. Voeg eventueel <code><em>-d</em></code> toe om het in de achtergrond te laten lopen, en voel je vrij om met de parameters <code><em>context-size</em></code> en <code><em>threads </em></code>te experimenteren in functie van hoe krachtig je server is: </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;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="docker run -p 8001:8080 -v $PWD/models-gguf:/models -ti --rm quay.io/go-skynet/local-ai:v2.7.0-ffmpeg-core --models-path /models --context-size 1600 --threads 16" style="color:#000000;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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: #795E26">docker</span><span style="color: #000000"> </span><span style="color: #A31515">run</span><span style="color: #000000"> </span><span style="color: #0000FF">-p</span><span style="color: #000000"> </span><span style="color: #098658">8001</span><span style="color: #A31515">:8080</span><span style="color: #000000"> </span><span style="color: #0000FF">-v</span><span style="color: #000000"> </span><span style="color: #001080">$PWD</span><span style="color: #A31515">/models-gguf:/models</span><span style="color: #000000"> </span><span style="color: #0000FF">-ti</span><span style="color: #000000"> </span><span style="color: #0000FF">--rm</span><span style="color: #000000"> </span><span style="color: #A31515">quay.io/go-skynet/local-ai:v2.7.0-ffmpeg-core</span><span style="color: #000000"> </span><span style="color: #0000FF">--models-path</span><span style="color: #000000"> </span><span style="color: #A31515">/models</span><span style="color: #000000"> </span><span style="color: #0000FF">--context-size</span><span style="color: #000000"> </span><span style="color: #098658">1600</span><span style="color: #000000"> </span><span style="color: #0000FF">--threads</span><span style="color: #000000"> </span><span style="color: #098658">16</span></span></code></pre></div>



<p></p>



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



<p>We kunnen nu verschillende LLMs voor code met elkaar vergelijken. We houden het hier louter anekdotisch, en nemen als eenvoudig voorbeeld het schrijven van een <em>bash </em>shellscript. We vertrekken van het volgende probleem: een backup-routine heeft jarenlang een nachtelijke backup genomen van een systeem. Om schijfruimte vrij te maken, willen we alle backups verwijderen die niet verschillen van de vorige. We geven de volgende opdracht, waarbij we de taak zo nauwgezet mogelijk omschrijven voor het beste resultaat: <em>&#8220;Write a bash script that, given a directory, iterates over all its files in order of date of creation. For each file, if the filesize is equal to the filesize of the previous file, the file has to be deleted.&#8221;</em></p>



<p>De <code>.continue/config.json</code> file van onze Continue plugin bevat de volgende lijst modellen: eentje op de eigen laptop in LM Studio ingeladen op poort 1234, en twee op een aparte server in het lokaal netwerk, door LocalAI gehost op poort 8001.</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;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="    {
      &quot;title&quot;: &quot;myLaptop-LMStudio&quot;,
      &quot;model&quot;: &quot;whatever is loaded in LMstudio&quot;,
      &quot;apiBase&quot;: &quot;http://127.0.0.1:1234/v1&quot;,
      &quot;completionOptions&quot;: {},
      &quot;provider&quot;: &quot;lmstudio&quot;
    },       
    {
      &quot;title&quot;: &quot;localAI-mistral&quot;,
      &quot;model&quot;: &quot;mistral-7b-code16kqlora-Q4&quot;,
      &quot;apiBase&quot;: &quot;https://192.168.0.100:8001/v1&quot;,
      &quot;apiKey&quot;: &quot;&quot;,      
      &quot;completionOptions&quot;: {},
      &quot;provider&quot;: &quot;openai&quot;
    },
    {
      &quot;title&quot;: &quot;localAI-deepseek&quot;,
      &quot;model&quot;: &quot;deepseek-6.7b-instruct-Q4&quot;,
      &quot;apiBase&quot;: &quot;https://192.168.0.100:8001/v1&quot;,
      &quot;apiKey&quot;: &quot;&quot;,
      &quot;completionOptions&quot;: {},
      &quot;provider&quot;: &quot;openai&quot;
    }," style="color:#24292e;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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 github-light" style="background-color: #fff" tabindex="0"><code><span class="line"><span style="color: #24292E">    {</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;title&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;myLaptop-LMStudio&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;model&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;whatever is loaded in LMstudio&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;apiBase&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;http://127.0.0.1:1234/v1&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;completionOptions&quot;</span><span style="color: #24292E">: {},</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;provider&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;lmstudio&quot;</span></span>
<span class="line"><span style="color: #24292E">    },       </span></span>
<span class="line"><span style="color: #24292E">    {</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;title&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;localAI-mistral&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;model&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;mistral-7b-code16kqlora-Q4&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;apiBase&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;https://192.168.0.100:8001/v1&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;apiKey&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;&quot;</span><span style="color: #24292E">,      </span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;completionOptions&quot;</span><span style="color: #24292E">: {},</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;provider&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;openai&quot;</span></span>
<span class="line"><span style="color: #24292E">    },</span></span>
<span class="line"><span style="color: #24292E">    {</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;title&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;localAI-deepseek&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;model&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;deepseek-6.7b-instruct-Q4&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;apiBase&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;https://192.168.0.100:8001/v1&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;apiKey&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;&quot;</span><span style="color: #24292E">,</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;completionOptions&quot;</span><span style="color: #24292E">: {},</span></span>
<span class="line"><span style="color: #24292E">      </span><span style="color: #032F62">&quot;provider&quot;</span><span style="color: #24292E">: </span><span style="color: #032F62">&quot;openai&quot;</span></span>
<span class="line"><span style="color: #24292E">    },</span></span></code></pre></div>



<p></p>



<p>Als referentie nemen we <a href="https://chat.openai.com/">ChatGPT</a>, die komt met de volgende (correcte) oplossing. Bovendien wordt ze ook gevolgd door een uitgebreide uitleg over wat de verschillende onderdelen betekenen (hier niet weergegeven):</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="#!/bin/bash

# Directory containing the files
DIR=&quot;/path/to/your/directory&quot;

# Variable to hold the size of the previous file. Initialized to 0.
prev_size=0

# List all files in the directory, sorted by creation date
# Note: '%T@' sorts by creation time, '%p' prints the file's name
# 'sort -n' ensures the list is sorted numerically
# Note that creation time sorting may depend on filesystem and OS support
files=$(find &quot;$DIR&quot; -type f -printf &quot;%T@ %p\n&quot; | sort -n | cut -d ' ' -f 2-)

# Iterate over the sorted list of files
for file in $files; do
  # Get current file size
  current_size=$(stat -c %s &quot;$file&quot;)
  
  # Check if current file size is equal to the previous file's size
  if [ &quot;$current_size&quot; -eq &quot;$prev_size&quot; ]; then
    # Sizes are equal, delete the current file
    echo &quot;Deleting file: $file&quot;
    rm &quot;$file&quot;
  fi
  
  # Update previous size to current file's size
  prev_size=$current_size
done" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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 dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">#!/bin/bash</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Directory containing the files</span></span>
<span class="line"><span style="color: #9CDCFE">DIR</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;/path/to/your/directory&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Variable to hold the size of the previous file. Initialized to 0.</span></span>
<span class="line"><span style="color: #9CDCFE">prev_size</span><span style="color: #D4D4D4">=</span><span style="color: #B5CEA8">0</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># List all files in the directory, sorted by creation date</span></span>
<span class="line"><span style="color: #6A9955"># Note: &#39;%T@&#39; sorts by creation time, &#39;%p&#39; prints the file&#39;s name</span></span>
<span class="line"><span style="color: #6A9955"># &#39;sort -n&#39; ensures the list is sorted numerically</span></span>
<span class="line"><span style="color: #6A9955"># Note that creation time sorting may depend on filesystem and OS support</span></span>
<span class="line"><span style="color: #9CDCFE">files</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">find</span><span style="color: #CE9178"> &quot;</span><span style="color: #9CDCFE">$DIR</span><span style="color: #CE9178">&quot; </span><span style="color: #569CD6">-type</span><span style="color: #CE9178"> f </span><span style="color: #569CD6">-printf</span><span style="color: #CE9178"> &quot;%T@ %p\n&quot; </span><span style="color: #D4D4D4">|</span><span style="color: #CE9178"> </span><span style="color: #DCDCAA">sort</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-n</span><span style="color: #CE9178"> </span><span style="color: #D4D4D4">|</span><span style="color: #CE9178"> </span><span style="color: #DCDCAA">cut</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-d</span><span style="color: #CE9178"> &#39; &#39; </span><span style="color: #569CD6">-f</span><span style="color: #CE9178"> </span><span style="color: #B5CEA8">2</span><span style="color: #CE9178">-)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Iterate over the sorted list of files</span></span>
<span class="line"><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">file</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">$files</span><span style="color: #D4D4D4">; </span><span style="color: #C586C0">do</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #6A9955"># Get current file size</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #9CDCFE">current_size</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">stat</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-c</span><span style="color: #CE9178"> %s &quot;</span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #6A9955"># Check if current file size is equal to the previous file&#39;s size</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [ </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$current_size</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4"> -eq </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$prev_size</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4"> ]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># Sizes are equal, delete the current file</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">echo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Deleting file: </span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">rm</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">fi</span></span>
<span class="line"><span style="color: #D4D4D4">  </span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #6A9955"># Update previous size to current file&#39;s size</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #9CDCFE">prev_size</span><span style="color: #D4D4D4">=</span><span style="color: #9CDCFE">$current_size</span></span>
<span class="line"><span style="color: #C586C0">done</span></span></code></pre></div>



<p></p>



<p>In LMStudio laden we het model &#8220;<a href="https://huggingface.co/TheBloke/CodeNinja-1.0-OpenChat-7B-GGUF">CodeNinja 1.0 openchat 7B Q4_K_M</a>&#8221; in. Voor het genereren van het antwoord op dezelfde vraag is ruim 1 minuut nodig: 20 seconden wachten tot de eerste letter van het antwoord verschijnt, daarna nog ongeveer 2 seconden per lijn. (Onze laptop is natuurlijk niet superkrachtig: een Core i7-10610U CPU met 32GB RAM). Het volgende komt eruit:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="#!/bin/bash

for f in $(ls -t -l --time-style=full /path/to/directory)
do
  if [[ $f == &quot;total&quot;* ]]; then
        continue;
    fi
    filename=$(basename &quot;${f% *}&quot;)

    # Checks whether the file is already deleted. If not, compares it with the previous file:
    prev_file=&quot;&quot;
    while IFS= read -r line; do
        if [[ $line == $filename ]]; then
            prev_file=$line
            break;
        fi
    done &lt;&lt;&lt;&quot;$(ls -l /path/to/directory | tail -n 2)&quot;

    if [[ -z $prev_file || &quot;$f&quot; = &quot;${prev_file}&quot; ]]; then
        # If the file is deleted, nothing to do. If not, deletes it:
        if [[ -z $prev_file ]] || [[ &quot;$(stat -c %s ${filename})&quot; == &quot;$(stat -c %s ${prev_file})&quot; ]]; then
            rm /path/to/directory/$filename
        fi
    fi
done" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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 dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">#!/bin/bash</span></span>
<span class="line"></span>
<span class="line"><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">f</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">ls</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-t</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-l</span><span style="color: #CE9178"> </span><span style="color: #569CD6">--time-style=full</span><span style="color: #CE9178"> /path/to/directory)</span></span>
<span class="line"><span style="color: #C586C0">do</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [[ </span><span style="color: #9CDCFE">$f</span><span style="color: #D4D4D4"> == </span><span style="color: #CE9178">&quot;total&quot;</span><span style="color: #D4D4D4">* ]]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">continue</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">fi</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">filename</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">basename</span><span style="color: #CE9178"> &quot;${</span><span style="color: #9CDCFE">f</span><span style="color: #D4D4D4">%</span><span style="color: #CE9178"> </span><span style="color: #D4D4D4">*</span><span style="color: #CE9178">}&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># Checks whether the file is already deleted. If not, compares it with the previous file:</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">prev_file</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">while</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">IFS</span><span style="color: #D4D4D4">= </span><span style="color: #DCDCAA">read</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-r</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">line</span><span style="color: #D4D4D4">; </span><span style="color: #C586C0">do</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [[ </span><span style="color: #9CDCFE">$line</span><span style="color: #D4D4D4"> == </span><span style="color: #9CDCFE">$filename</span><span style="color: #D4D4D4"> ]]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #9CDCFE">prev_file</span><span style="color: #D4D4D4">=</span><span style="color: #9CDCFE">$line</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #C586C0">break</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">fi</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">done</span><span style="color: #D4D4D4"> &lt;&lt;&lt;</span><span style="color: #CE9178">&quot;$(</span><span style="color: #DCDCAA">ls</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-l</span><span style="color: #CE9178"> /path/to/directory </span><span style="color: #D4D4D4">|</span><span style="color: #CE9178"> </span><span style="color: #DCDCAA">tail</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-n</span><span style="color: #CE9178"> </span><span style="color: #B5CEA8">2</span><span style="color: #CE9178">)&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [[ -z </span><span style="color: #9CDCFE">$prev_file</span><span style="color: #D4D4D4"> || </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$f</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4"> = </span><span style="color: #CE9178">&quot;${</span><span style="color: #9CDCFE">prev_file</span><span style="color: #CE9178">}&quot;</span><span style="color: #D4D4D4"> ]]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #6A9955"># If the file is deleted, nothing to do. If not, deletes it:</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [[ -z </span><span style="color: #9CDCFE">$prev_file</span><span style="color: #D4D4D4"> ]] || [[ </span><span style="color: #CE9178">&quot;$(</span><span style="color: #DCDCAA">stat</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-c</span><span style="color: #CE9178"> %s ${</span><span style="color: #9CDCFE">filename</span><span style="color: #CE9178">})&quot;</span><span style="color: #D4D4D4"> == </span><span style="color: #CE9178">&quot;$(</span><span style="color: #DCDCAA">stat</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-c</span><span style="color: #CE9178"> %s ${</span><span style="color: #9CDCFE">prev_file</span><span style="color: #CE9178">})&quot;</span><span style="color: #D4D4D4"> ]]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">            </span><span style="color: #DCDCAA">rm</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/path/to/directory/</span><span style="color: #9CDCFE">$filename</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #C586C0">fi</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">fi</span></span>
<span class="line"><span style="color: #C586C0">done</span></span></code></pre></div>



<p></p>



<p>Het <a href="https://huggingface.co/TheBloke/deepseek-coder-6.7B-instruct-GGUF">DeepSeek model van 6.7 miljard parameters</a> laden we in LocalAI op een Debian VM in Proxmox. Aan de VM is ruim voldoende RAM toegekend, en 12 cores van de onderliggende hardware, een AMD Threadripper 3960X processor (24 cores maar geen AVX-512 ondersteuning). Hiermee creëren we aan een snelheid van ongeveer 3 lijnen per seconde het volgende resultaat:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="#!/bin/bash

# Check if directory is provided
if [ $# -ne 1 ]; then
  echo &quot;Usage: $0 directory&quot;
    exit 1
fi

# Check if directory exists
if [&nbsp;! -d &quot;$1&quot; ]; then
    echo &quot;Directory $1 does not exist&quot;
    exit 1
fi

# Change to the directory
cd &quot;$1&quot;

# Get the list of files in order of creation date
files=$(ls -t)

# Initialize previous_size to 0
previous_size=0

# Iterate over the files
for file in $files; do
    # Get the size of the file
    size=$(stat -c%s &quot;$file&quot;)

    # If the size is equal to the previous size, delete the file
    if [ $size -eq $previous_size ]; then
        rm &quot;$file&quot;
        echo &quot;Deleted $file&quot;
    fi

    # Update previous_size
    previous_size=$size
done" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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 dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #6A9955">#!/bin/bash</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Check if directory is provided</span></span>
<span class="line"><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [ </span><span style="color: #569CD6">$#</span><span style="color: #D4D4D4"> -ne </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4"> ]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">echo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Usage: </span><span style="color: #9CDCFE">$0</span><span style="color: #CE9178"> directory&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">exit</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span></span>
<span class="line"><span style="color: #C586C0">fi</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Check if directory exists</span></span>
<span class="line"><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [&nbsp;! -d </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$1</span><span style="color: #CE9178">&quot;</span><span style="color: #D4D4D4"> ]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">echo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Directory </span><span style="color: #9CDCFE">$1</span><span style="color: #CE9178"> does not exist&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #DCDCAA">exit</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span></span>
<span class="line"><span style="color: #C586C0">fi</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Change to the directory</span></span>
<span class="line"><span style="color: #DCDCAA">cd</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$1</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Get the list of files in order of creation date</span></span>
<span class="line"><span style="color: #9CDCFE">files</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">ls</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-t</span><span style="color: #CE9178">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Initialize previous_size to 0</span></span>
<span class="line"><span style="color: #9CDCFE">previous_size</span><span style="color: #D4D4D4">=</span><span style="color: #B5CEA8">0</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6A9955"># Iterate over the files</span></span>
<span class="line"><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">file</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">$files</span><span style="color: #D4D4D4">; </span><span style="color: #C586C0">do</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># Get the size of the file</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">size</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">stat</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-c%s</span><span style="color: #CE9178"> &quot;</span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># If the size is equal to the previous size, delete the file</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [ </span><span style="color: #9CDCFE">$size</span><span style="color: #D4D4D4"> -eq </span><span style="color: #9CDCFE">$previous_size</span><span style="color: #D4D4D4"> ]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #DCDCAA">rm</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">        </span><span style="color: #DCDCAA">echo</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Deleted </span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">fi</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #6A9955"># Update previous_size</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">previous_size</span><span style="color: #D4D4D4">=</span><span style="color: #9CDCFE">$size</span></span>
<span class="line"><span style="color: #C586C0">done</span></span></code></pre></div>



<p></p>



<p>Tot slot kunnen we op dezelfde VM ook het recentere Mistral uitproberen, waarvoor we op goed geluk de versie <a href="https://huggingface.co/TheBloke/Mistral-7B-Code-16K-qlora-GGUF">mistral-7B-code-16K-qlora</a> uitkiezen die door een andere gebruiker lichtjes werd bijgetraind voor code. Deze blijkt zeer snel te kunnen antwoorden, en genereert in ongeveer 2 seconden het volgende compacte resultaat (helaas zonder documentatie, en gebruikmakend van het complexe <em>awk</em> commando):</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" data-code="for file in $(find directory -type f -exec du -sh {} + | sort -h | awk '{print NR &quot;:\t&quot; $1}'); do
    size=$(du -sh &quot;$file&quot; | awk '{print $1}')
    if [[ $size == $previous_size ]]; then
      rm &quot;$file&quot;
    fi
    previous_size=$size
done" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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 dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #C586C0">for</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">file</span><span style="color: #D4D4D4"> </span><span style="color: #C586C0">in</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">find</span><span style="color: #CE9178"> directory </span><span style="color: #569CD6">-type</span><span style="color: #CE9178"> f </span><span style="color: #569CD6">-exec</span><span style="color: #CE9178"> du </span><span style="color: #569CD6">-sh</span><span style="color: #CE9178"> {} + </span><span style="color: #D4D4D4">|</span><span style="color: #CE9178"> </span><span style="color: #DCDCAA">sort</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-h</span><span style="color: #CE9178"> </span><span style="color: #D4D4D4">|</span><span style="color: #CE9178"> </span><span style="color: #DCDCAA">awk</span><span style="color: #CE9178"> &#39;{print NR &quot;:\t&quot; $1}&#39;)</span><span style="color: #D4D4D4">; </span><span style="color: #C586C0">do</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">size</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">$(</span><span style="color: #DCDCAA">du</span><span style="color: #CE9178"> </span><span style="color: #569CD6">-sh</span><span style="color: #CE9178"> &quot;</span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot; </span><span style="color: #D4D4D4">|</span><span style="color: #CE9178"> </span><span style="color: #DCDCAA">awk</span><span style="color: #CE9178"> &#39;{print $1}&#39;)</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">if</span><span style="color: #D4D4D4"> [[ </span><span style="color: #9CDCFE">$size</span><span style="color: #D4D4D4"> == </span><span style="color: #9CDCFE">$previous_size</span><span style="color: #D4D4D4"> ]]; </span><span style="color: #C586C0">then</span></span>
<span class="line"><span style="color: #D4D4D4">      </span><span style="color: #DCDCAA">rm</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;</span><span style="color: #9CDCFE">$file</span><span style="color: #CE9178">&quot;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #C586C0">fi</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #9CDCFE">previous_size</span><span style="color: #D4D4D4">=</span><span style="color: #9CDCFE">$size</span></span>
<span class="line"><span style="color: #C586C0">done</span></span></code></pre></div>



<p></p>



<p>Ik laat de diepgaandere vergelijking van deze resultaten graag over als oefening aan de lezer. Als we hieruit nog een laatste les moeten leren, dan is het dat er ook tussen modellen onderling, zelfs al hebben ze dezelfde hoeveelheid parameters en zijn ze voor hetzelfde doel getraind, erg grote verschillen kunnen zijn qua output en stijl! </p>



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



<p>Aan sneltempo vinden allerlei AI-powered features hun weg naar de IDE. De <a href="https://code.visualstudio.com/updates/v1_87">laatste release notes van Visual Studio Code</a> vermelden naast verschillende CoPilot features bijvoorbeeld ook ondersteuning voor spraakherkenning in meerdere talen. Het is onvermijdelijk dat je daar als developer mee in contact zal komen. Developers die werken met gevoelige data of copyrighted code, zijn terecht argwanend over het feit dat zulke tools hun IDE-inhoud naar een of andere clouddienst van een derde partij versturen, om suggesties te kunnen genereren. </p>



<p>Vooral dankzij het <a href="https://github.com/ggerganov/llama.cpp">llama.cpp</a> project, is er recent een alternatieve <em>open-source</em> route ontstaan die toelaat zulke coding assistentie met LLMs zelf op te zetten en uit te baten. Kleinere modellen die op consumentenhardware kunnen draaien, leveren momenteel niet dezelfde kwaliteit en snelheid als Github CoPilot of ChatGPT. De komende jaren zullen we echter regelmatig verdere verbeteringen zien verschijnen, dus de ingezette weg oogt alleszins veelbelovend. </p>



<p>______________________</p>



<p><em>Dit is een ingezonden bijdrage van Joachim Ganseman, IT consultant bij Smals Research. &nbsp;Dit artikel werd geschreven in eigen naam en neemt geen standpunt in namens Smals.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>🎂 ChatGPT a 1 an 🎂</title>
		<link>https://www.smalsresearch.be/1-an-chatgpt/</link>
		
		<dc:creator><![CDATA[Joachim Ganseman]]></dc:creator>
		<pubDate>Fri, 01 Dec 2023 06:41:54 +0000</pubDate>
				<category><![CDATA[[FR]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[chatbot]]></category>
		<category><![CDATA[computational creativity]]></category>
		<category><![CDATA[egov]]></category>
		<category><![CDATA[Natural Language Processing]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[social]]></category>
		<guid isPermaLink="false">/?p=19587</guid>

					<description><![CDATA[1 an plus tard, l'impact de ChatGPT peut être qualifié de transformateur. Petite rétrospective et petite prospective]]></description>
										<content:encoded><![CDATA[
<p><em>Dit artikel is ook te lezen <a href="/1-jaar-chatgpt/">in het Nederlands</a>.</em></p>



<p><em>Cet article a été traduit du néerlandais. Les liens peuvent pointer vers des sources en néerlandais.</em></p>



<p>Le 30 novembre 2022, <a href="https://openai.com/blog/chatgpt">ChatGPT</a> a été révélé au monde entier. Le chatbot polyvalent, qui peut traiter de presque tous les sujets, a immédiatement conquis un large public. Les générateurs d&#8217;images, tels que <a href="https://openai.com/dall-e-3">DALL-E</a> et <a href="https://stability.ai/news/stable-diffusion-public-release">Stable Diffusion</a>, sont venus s&#8217;ajouter à cela et, aujourd&#8217;hui, la situation est claire&nbsp;: <em>L&#8217;IA générative a de beaux jours devant elle.</em> Nous avons nous-mêmes commencé à l&#8217;utiliser immédiatement, et nous avons écrit <a href="/chatgpt-een-eerste-indruk/">un article sur nos premières découvertes</a> 10 jours après le lancement.</p>



<p>1 an plus tard, l&#8217;impact de ChatGPT peut être qualifié de transformateur. L&#8217;écosystème autour de l&#8217;IA générative est en plein essor. Ce qui relevait du domaine des rêveries irréalistes il y a 3 ans est soudain devenu réalisable et est en production aujourd&#8217;hui. D&#8217;innombrables start-ups voient le jour&nbsp;: le compteur du site web <a href="https://theresanaiforthat.com/"><em>There&#8217;s an AI for that</em></a> a depuis dépassé les 10&nbsp;000, le mois de mars 2023 comptant à lui seul 1209 nouvelles entreprises d&#8217;IA. À titre de comparaison, pour l&#8217;ensemble de l&#8217;année 2021, il n&#8217;y a que 288 start-ups dans la même base de données.</p>



<p>L&#8217;impact et la célérité avec lesquels tout évolue suscitent également de la nervosité. <a href="https://www.cam.ac.uk/stories/ChatGPT-and-education">L&#8217;enseignement</a>, par exemple, doit s&#8217;adapter dans la précipitation à une nouvelle réalité. L&#8217;étudiant moyen a désormais facilement accès à une technologie qui lui permet de rédiger une dissertation entière en quelques secondes &#8211; et lorsque <a href="https://southpark.cc.com/episodes/8byci4/south-park-deep-learning-season-26-ep-4">South Park</a> y consacre un épisode, on sait que le phénomène prospère. Plus proche de nous, de nombreuses universités ont publié des lignes directrices ou des conseils sur son utilisation (par ex. <a href="https://www.kuleuven.be/onderwijs/student/onderwijstools/artificiele-intelligentie">Louvain</a>, <a href="https://www.ugent.be/student/nl/studeren/tools-lesopnames/chatgpt">Gand</a>, <a href="https://www.uantwerpen.be/nl/centra/studentenraad/studentenraad/standpuntenenadviezen/onderwijs/artificieleintelligentie/">Anvers</a>). Celles-ci sont bien pensées et pourraient bien inspirer des lignes directrices similaires dans les entreprises et les gouvernements.</p>



<p>L&#8217;on observe également de nombreuses expérimentations dans des contextes professionnels. &#8220;Aucune idée, mais demande à ChatGPT&#8221; est devenu une déclaration typique lorsqu&#8217;il y a un besoin de nouveaux inputs. Un sondage réalisé par <a href="https://www.nature.com/articles/d41586-023-02980-0">Nature</a> a fait ressortir qu&#8217;un grand nombre de scientifiques avaient déjà exploré la technologie dans un cadre professionnel. Dans le monde universitaire, <a href="https://doi.org/10.1038/d41586-023-03238-5">l&#8217;on se demande</a> si le fait de soumettre d&#8217;épais dossiers de subvention a un sens, si la rédaction de ceux-ci est automatisable. Nul doute que des observations similaires émergent également dans d&#8217;autres secteurs.</p>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2023/11/2023-03-20_12h13_56.png"><img loading="lazy" decoding="async" width="1024" height="447" src="/wp-content/uploads/2023/11/2023-03-20_12h13_56-1024x447.png" alt="DALL-E 2 est un générateur d'images à partir d'une description textuelle." class="wp-image-19551" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-03-20_12h13_56-1024x447.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-03-20_12h13_56-300x131.png 300w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-03-20_12h13_56-768x335.png 768w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-03-20_12h13_56-1536x670.png 1536w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-03-20_12h13_56.png 1705w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">DALL-E 2 est un générateur d&#8217;images à partir d&#8217;une description textuelle.</figcaption></figure>



<h2 class="wp-block-heading"><strong>Petite rétrospective</strong></h2>



<p>OpenAI mène toujours la danse, et son propre <a href="https://openai.com/blog">blog</a> donne un bon aperçu des développements de l&#8217;année écoulée. Une timeline avec quelques moments clés&nbsp;:</p>



<ul class="wp-block-list">
<li>17 janvier 2023&nbsp;: Microsoft lance le <a href="https://azure.microsoft.com/en-us/products/ai-services/openai-service/">service Azure OpenAI</a>, rendant les technologies OpenAI disponibles sur Azure,</li>



<li>1 février 2023&nbsp;: Le service d&#8217;abonnement ChatGPT Plus offre un accès prioritaire à ChatGPT (hautement sursollicité) pour 20 $/mois,</li>



<li>1 mars 2023&nbsp;: ChatGPT devient <a href="https://openai.com/blog/introducing-chatgpt-and-whisper-apis">disponible via API</a>,</li>



<li>14 mars 2023&nbsp;: Lancement de <a href="https://en.wikipedia.org/wiki/GPT-4">GPT-4</a> pour les utilisateurs de ChatGPT Plus,</li>



<li>23 mars 2023&nbsp;: Lancement des premiers <a href="https://openai.com/blog/chatgpt-plugins">plugins</a>,</li>



<li>13 juin 2023&nbsp;: Une version mise à jour de ChatGPT peut configurer et exécuter des appels vers des <a href="https://openai.com/blog/function-calling-and-other-api-updates">fonctions externes</a>,</li>



<li>20 juillet 2023&nbsp;: Avec &#8220;<a href="https://openai.com/blog/custom-instructions-for-chatgpt">custom instructions</a>&#8220;, ChatGPT peut être configuré pour toujours prendre en compte certains éléments,</li>



<li>22 août 2023&nbsp;: L&#8217;<a href="https://platform.openai.com/docs/guides/fine-tuning/fine-tuning-examples">API Finetuning</a> permet d&#8217;affiner l&#8217;output de ChatGPT,</li>



<li>28 août 2023&nbsp;: Lancement de <a href="https://openai.com/blog/introducing-chatgpt-enterprise">ChatGPT Enterprise</a>,</li>



<li>25 septembre 2023&nbsp;: Les utilisateurs peuvent utiliser <a href="https://openai.com/blog/chatgpt-can-now-see-hear-and-speak">la voix et les images</a> dans les conversations,</li>



<li>19 octobre 2023&nbsp;: ChatGPT peut générer des images avec <a href="https://openai.com/dall-e-3">DALL-E 3</a>,</li>



<li>6 novembre 2023&nbsp;: Introduction des <a href="https://openai.com/blog/introducing-gpts">GPT</a> qui permettent aux amateurs de <a href="https://chatgpt.com/create">construire un ChatGPT personnalisé</a>&nbsp; qui fouille des documents spécifiques, et des <a href="https://platform.openai.com/docs/assistants/overview">Assistants API</a> destinée aux programmeurs pour réaliser une action similaire.</li>
</ul>



<p>Ce dernier pas n&#8217;est <a href="https://medium.com/%40ignacio.de.gregorio.noblejas/openai-just-killed-an-entire-market-in-45-minutes-818b2a8ad33e">pas reçu par tous avec enthousiasme</a>&nbsp;: de nombreuses start-ups dans l&#8217;écosystème de l&#8217;IA générative viennent de construire le cœur de leur activité autour du concept de <a href="https://research.ibm.com/blog/retrieval-augmented-generation-RAG">Retrieval-Augmented Generation</a> (RAG), et OpenAI leur fait directement concurrence avec ses GPT personnalisés. (De mauvaises langues prétendent que cela aurait joué un rôle dans le <a href="https://www.theverge.com/2023/11/22/23967223/sam-altman-returns-ceo-open-ai">conflit du CEO</a> deux semaines plus tard, mais ces rumeurs n&#8217;ont pas encore été prouvées).</p>



<p>Retrieval-Augmented Generation (RAG), avec <a href="https://python.langchain.com/">langchain</a> comme bibliothèque la plus populaire pour les développeurs, est devenu au cours de l&#8217;année écoulée le moyen de faire en sorte que les <a href="https://www.elastic.co/what-is/large-language-models">Large Language Models</a> s&#8217;accrochent à des informations spécifiques, internes ou récentes. L&#8217;idée découle du fait que, pendant ce temps, le <a href="https://en.wikipedia.org/wiki/Prompt_engineering">prompt</a> &#8211; c&#8217;est-à-dire la commande que l&#8217;on donne au modèle de langue &#8211; peut être si long qu&#8217;il y a de la place pour ajouter des pages entières d&#8217;informations supplémentaires. En enrichissant le prompt avec, par exemple, les résultats d&#8217;une recherche ou les dernières nouvelles, un chatbot peut encore formuler<a href="/een-eigen-vraag-en-antwoordsysteem-op-basis-van-taalmodellen/"> des réponses basées sur des informations récentes ou du contenu provenant de bases de données spécifiques</a>, sans que le modèle de langue sous-jacent n&#8217;ait besoin d&#8217;être entraîné sur ces bases.</p>



<p>Microsoft s&#8217;est empressé de concrétiser cette idée. Avec <a href="https://blogs.microsoft.com/blog/2023/02/07/reinventing-search-with-a-new-ai-powered-microsoft-bing-and-edge-your-copilot-for-the-web/">Bing Chat</a>, elle a lancé une nouvelle interface de recherche conversationnelle, qui utilise les résultats de Bing Search pour ses réponses. L&#8217;avantage est que cette interface peut afficher de manière transparente les citations de sources ou les références. Cependant, il convient de garder à l&#8217;esprit que cela ne garantit pas l&#8217;exactitude des réponses : les résultats de la recherche peuvent toujours ne pas être pertinents, et les résumés incorrects ou incomplets. Entre-temps, le produit fut un succès, et Microsoft a décidé de mettre le paquet : entre-temps, Bing Chat a été rebaptisé <a href="https://blogs.bing.com/search/november-2023/our-vision-to-bring-microsoft-copilot-to-everyone-and-more">Microsoft CoPilot</a>, a été intégré au navigateur Edge, et est également disponible dans <a href="https://ignite.microsoft.com/en-US/archives/8122e7d2-0acf-4685-bc47-0c27819c5264">Windows 11</a> et <a href="https://www.youtube.com/playlist?list=PLXPr7gfUMmKxDKxah3zpG4NhhDj-2lAvc">Microsoft 365</a> (anciennement Office). Pour pouvoir exploiter cette fonctionnalité, il faut donner l&#8217;autorisation dans l&#8217;application de partager des documents ouverts ou des contenus de pages web avec le service CoPilot.</p>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2023/11/2023-11-27_15h31_16.png"><img loading="lazy" decoding="async" width="1024" height="590" src="/wp-content/uploads/2023/11/2023-11-27_15h31_16-1024x590.png" alt="Aujourd'hui, Microsoft CoPilot est intégré dans le navigateur Edge et peut fournir des réponses aux questions sur des pages web ouvertes. " class="wp-image-19474" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-11-27_15h31_16-1024x590.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-11-27_15h31_16-300x173.png 300w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-11-27_15h31_16-768x442.png 768w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-11-27_15h31_16-1536x885.png 1536w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-11-27_15h31_16.png 1684w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Aujourd&#8217;hui, Microsoft CoPilot est intégré dans le navigateur Edge et peut fournir des réponses aux questions sur des pages web ouvertes. </figcaption></figure>



<p>Microsoft fait également figure de précurseur en matière d&#8217;images&nbsp;: Le <a href="https://www.bing.com/create">Bing Image Creator</a> offre un accès gratuit au générateur DALL-E 3 (pour l&#8217;instant), et ses résultats sont intégrés de manière transparente dans le nouveau <a href="https://designer.microsoft.com/">Microsoft Designer</a>.</p>



<p>Google a eu moins de succès avec son équivalent <a href="https://bard.google.com/">Bard</a>. Le lancement a <a href="https://www.theverge.com/2023/2/8/23590864/google-ai-chatbot-bard-mistake-error-exoplanet-demo">mal tourné</a> lorsque Bard a répondu par un fait erroné (une hallucination), ce qui a fait chuter le cours de l&#8217;action de Google. Par rapport à OpenAI et Microsoft, Google semble moins préoccupé par l&#8217;intégration et l&#8217;expérience utilisateur, et se concentre plutôt sur le <a href="https://research.google/">fond théorique</a> et l&#8217;approfondissement des possibilités technologiques.</p>



<p>Meta, bien sûr, ne veut pas être en reste et joue la carte du logiciel quasi open-source avec ses propres modèles de langue <a href="https://ai.meta.com/llama/">Llama</a>, en <a href="https://opensourceconnections.com/blog/2023/07/19/is-llama-2-open-source-no-and-perhaps-we-need-a-new-definition-of-open/">mettant l&#8217;accent sur le terme &#8220;quasi&#8221;</a>. La société semble se concentrer principalement sur les développeurs individuels, pour lesquels Meta souhaite faciliter la réutilisation ou le réentraînement de leurs modèles de langue, comme l&#8217;a fait Stanford avec sa variante <a href="https://crfm.stanford.edu/2023/03/13/alpaca.html">Alpaca</a>, entre autres. La société vise également le déploiement sur du matériel standard, grâce à la bibliothèque <a href="https://github.com/ggerganov/llama.cpp">llama.cpp</a>, qui permet de <a href="https://towardsdatascience.com/introduction-to-weight-quantization-2494701b9c0c">quantifier</a> un modèle&nbsp;: arrondir intelligemment les paramètres d&#8217;un modèle entraîné pour réduire l&#8217;empreinte mémoire, au prix d&#8217;une perte de précision faible mais acceptable. Une quantification de 32 bits à 8 bits fait qu&#8217;un modèle de 13 milliards de paramètres nécessite non pas 52 Go mais seulement 13 Go de mémoire vive. Il s&#8217;intègre donc parfaitement dans la mémoire des cartes graphiques actuelles dotées de 16 ou 24 Go de vRAM. Des outils intuitifs permettant d&#8217;héberger des modèles quantifiés sur votre propre ordinateur sont <a href="https://gpt4all.io/index.html">GPT4All</a> , <a href="https://github.com/mlc-ai/mlc-llm">MLC</a>, <a href="https://ollama.ai/">ollama</a> ou <a href="https://lmstudio.ai/">LMStudio</a>.</p>



<p>Plusieurs entreprises plus petites sont également dans la course, développant leurs propres modèles de langue qui pourraient servir de backend pour des services de type ChatGPT ou des applications RAG. Il convient de mentionner <a href="https://www.anthropic.com/">Anthropic</a>, créée par d&#8217;anciens employés d&#8217;OpenAI, qui met particulièrement l&#8217;accent sur la transparence et la sécurité avec ses modèles <a href="https://claude.ai/">Claude</a>. De son côté, l&#8217;européenne <a href="https://techcrunch.com/2023/06/13/frances-mistral-ai-blows-in-with-a-113m-seed-round-at-a-260m-valuation-to-take-on-openai/?guccounter=1">Mistral</a> a démarré sur les chapeaux de roues. Avec d&#8217;anciens employés de Meta à sa tête, elle exploite un modèle véritablement open-source et est donc principalement en concurrence avec Meta. Pour la zone linguistique néerlandaise, des projets sont en cours pour développer, par l&#8217;intermédiaire de l&#8217;organisation de recherche TNO, un <a href="https://www.digitaleoverheid.nl/nieuws/nederland-bouwt-eigen-open-taalmodel-gpt-nl/">GPT-NL indépendant</a> qui devrait également constituer une alternative aux grands acteurs américains, en mettant l&#8217;accent sur le respect des lois européennes.</p>



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



<p>Bon nombre d&#8217;entreprises doivent encore s&#8217;atteler à l&#8217;<a href="https://medium.com/artificial-intelligence-lab-brussels/how-to-adapt-your-business-models-to-ai-6-dimensions-of-value-creation-b23efdba5de2">adaptation de leurs propres modèles d&#8217;entreprise à l&#8217;essor de l&#8217;IA</a>. Nous n&#8217;en sommes toutefois qu&#8217;aux premiers stades d&#8217;une période de forte croissance pour l&#8217;IA, et il est difficile de prévoir ce que les prochaines années nous réservent. Rester à l&#8217;affût des évolutions est une première étape. <a href="https://www.deeplearning.ai/the-batch/">The Batch</a> de DeepLearning.AI est une newsletter excellente qui suit l&#8217;évolution de la situation et qui fournit chaque semaine un résumé concis des événements clés de l&#8217;industrie. Ceux qui cherchent à élargir et à approfondir leurs connaissances trouveront également une solide offre de cours sur le même site web, comme celui-ci&nbsp;: <a href="https://www.deeplearning.ai/courses/generative-ai-for-everyone/">Generative AI for Everyone</a>. Microsoft propose un cours <a href="https://microsoft.github.io/generative-ai-for-beginners/#/">Generative AI for Beginners</a> (IA générative pour les débutants) destiné aux développeurs. Le site finlandais <a href="https://www.elementsofai.com/">Elements Of AI</a> propose l&#8217;un des cours gratuits les plus accessibles au grand public, et il en existe bien d&#8217;autres.</p>



<p>Aujourd&#8217;hui déjà, les chefs d&#8217;entreprise et les dirigeants sont confrontés à tous ces nouveaux développements dans les entreprises ou dans l&#8217;administration, et veulent formuler une réponse &#8211; ou au moins élaborer un code de conduite. Le <a href="https://data-en-maatschappij.ai/beleidsmonitor">moniteur de gestion</a> du <a href="https://data-en-maatschappij.ai/">Knowledge Centre Data and Society</a> rassemble des exemples nationaux et internationaux qui peuvent servir d&#8217;inspiration à ceux qui ne veulent pas réinventer l&#8217;eau chaude. Le AI Standards Hub du Royaume-Uni rassemble des publications pertinentes sur les <a href="https://aistandardshub.org/ai-standards-search/">normes industrielles</a> liées à l&#8217;IA. À un niveau international plus abstrait, l&#8217;<a href="https://oecd.ai/en/">OCDE</a>, entre autres, exerce un monitoring actif. L&#8217;évolution rapide du terrain ne facilite certainement pas le travail législatif. Au niveau européen, le<a href="https://artificialintelligenceact.eu/developments/"> IA Act</a> annoncé est <a href="https://www.reuters.com/technology/eu-lawmakers-face-struggle-reach-agreement-ai-rules-sources-2023-10-23/">reporté</a>. Cela n&#8217;a pas empêché Stanford d&#8217;<a href="https://crfm.stanford.edu/2023/06/15/eu-ai-act.html">évaluer déjà les principaux acteurs existants</a> sur la base du projet de texte qui nous est soumis.</p>



<p>En attendant, rien n&#8217;empêche une entreprise ou un gouvernement de se lancer et d&#8217;expérimenter la technologie. Toutefois, il est crucial de rester prudent et de ne pas pas perdre le sens commun. ChatGPT n&#8217;est pas une solution miracle. Aucun mécanisme de sécurité ne peut garantir qu&#8217;un modèle de langue n&#8217;aura pas <a href="https://en.wikipedia.org/wiki/Hallucination_(artificial_intelligence)">d&#8217;hallucinations</a> ou ne présentera pas des textes complètement inventés comme des faits. Bien que les datasets d&#8217;entraînement de nombreux modèles de langue soient secrets, nous savons qu&#8217;ils sont si volumineux qu&#8217;il est impossible d&#8217;y effectuer une sélection et un filtrage précis. Les LLM sont aujourd&#8217;hui des <a href="https://promptengineering.org/the-black-box-problem-opaque-inner-workings-of-large-language-models/">boîtes noires</a>&nbsp;; il est impossible de retracer l&#8217;origine d&#8217;un choix de mots particulier dans une réponse. Il est donc impossible, en toute logique, de créer des applications critiques aveuglément sur la base de ces systèmes. De toute évidence, ce serait une mauvaise idée de faire traiter des données médicales, sans aucune supervision, par un modèle de langue partiellement formé sur des textes piochés au hasard sur le net par des théoriciens du complot, des antivax, des influenceurs d&#8217;Instagram, des homéopathes et d&#8217;autres charlatans.</p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2023/11/webinar-AI-coding_2.png"><img loading="lazy" decoding="async" width="897" height="502" src="/wp-content/uploads/2023/11/webinar-AI-coding_2.png" alt="" class="wp-image-19504" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/11/webinar-AI-coding_2.png 897w, https://www.smalsresearch.be/wp-content/uploads/2023/11/webinar-AI-coding_2-300x168.png 300w, https://www.smalsresearch.be/wp-content/uploads/2023/11/webinar-AI-coding_2-768x430.png 768w" sizes="auto, (max-width: 897px) 100vw, 897px" /></a><figcaption class="wp-element-caption">Illustration générée par Microsoft Image Creator (DALL-E 3) sur la base du prompt&nbsp;: <em>&#8220;An AI is helping a programmer solve a difficult problem in the IDE. Focus on the computer screen containing flawed code. We only see the back of the people.&#8221;</em></figcaption></figure>



<p>En parlant de charlatans, on voit <a href="https://medium.com/%40emilymenonbender/aihype-take-downs-5c6fcc5c5ba1">régulièrement</a> apparaître des prophètes de malheur qui, <a href="https://www.schneier.com/blog/archives/2023/10/ai-risks.html">pour attirer l&#8217;attention</a>, font des déclarations de plus en plus grotesques, allant jusqu&#8217;à prédire l&#8217;extinction de I&#8217;Humanité. (L&#8217;inverse existe aussi&nbsp;: ceux qui croient que l&#8217;utopie est proche). La disproportion de ces déclarations témoigne d&#8217;un manque de connaissances et d&#8217;un manque de contact avec la réalité. Après tout, malgré tous les progrès réalisés, nous sommes encore bien loin des robots capables de repasser vos vêtements. Des affirmations farfelues détournent la discussion des problèmes qui se posent aujourd&#8217;hui dans le monde réel&nbsp;: les abus tels que les &#8220;<a href="https://dl.acm.org/doi/10.1145/3584973">deepfakes</a>&#8220;, l&#8217;élargissement de la fracture numérique, le manque de possibilités de contester les décisions automatiques, l&#8217;utilisation de données sans autorisation ni mention de la source, &#8230; autant de questions qui requièrent une attention soutenue et pour lesquelles l&#8217;Europe joue un<a href="https://digital-strategy.ec.europa.eu/en/library/ethics-guidelines-trustworthy-ai"> rôle actif de pionnier</a>. Ces éléments ne doivent pas être des facteurs bloquants, puisque même en gardant la tête sur les épaules, ce ne sont pas les <a href="https://www.youtube.com/watch?v=5p248yoa3oE">opportunités</a> qui manquent.</p>



<p>Dans un<a href="https://www.gatesnotes.com/AI-agents"> récent éditorial</a>, Bill Gates a été acclamé pour sa vision de l&#8217;évolution dans un avenir proche. Selon cette vision, les chatbots évolueront en &#8220;<a href="https://python.langchain.com/docs/how_to/#agents">agents</a>&#8220;, c&#8217;est-à-dire qu&#8217;ils disposeront d&#8217;une autonomie (limitée) pour prendre des mesures, éventuellement supervisées. Là où les co-Pilots font encore partie d&#8217;une application, ceux-ci deviendront également plus génériques, avec l&#8217;intention que les futurs agents puissent fonctionner à travers les applications, comme les assistants personnels. En effet, il reste encore beaucoup de travail à accomplir pour y parvenir : des protocoles qui permettent aux applications de mieux communiquer entre elles, des moyens d&#8217;échanger des données en toute sécurité tout en préservant la vie privée, &#8230;</p>



<p>Enfin, la dépendance à l&#8217;égard de modèles énormes et non transparents (GPT-3, GPT-4) avec un service en cloud externe reste une pilule difficile à avaler lorsque des données internes ou sensibles sont susceptibles d&#8217;être traitées. Il est impossible de prévoir quelles données un utilisateur typique pourrait communiquer à un chatbot, et avec les plugins de type CoPilot, il est souvent difficile de retrouver les données que le plugin lit et transmet en arrière-plan. Toutefois, le <a href="https://eur-lex.europa.eu/eli/reg/2016/679/oj">RGPD</a> impose des exigences strictes et concrètes. Tout le monde ne considère pas qu&#8217;une promesse ou même un accord contractuel stipulant que les données reçues ne seront pas stockées ou réutilisées soit suffisant pour avoir soudainement une confiance aveugle.</p>



<p>L&#8217;alternative logique consiste à déployer localement des modèles plus petits. Cependant, la <a href="https://github.com/vectara/hallucination-leaderboard">qualité de leur output</a> est par conséquent plus faible, ce qui est décevant si les attentes élevées créées par ChatGPT sont le point de référence. Les modèles plus petits ne disposent pas du multilinguisme fluide de ChatGPT et travaillent avec des prompts beaucoup plus compacts, ce qui complique l&#8217;élaboration d&#8217;applications RAG. Une recherche diligente et multidirectionnelle est en cours pour combler cette lacune. On voit des  innovations permettant d&#8217;affiner (spécialiser) des modèles plus petits pour une tâche spécifique, de façon <a href="https://github.com/huggingface/peft">efficace et avec moins de données</a>. Le concept de <a href="https://arxiv.org/abs/1503.02531">distillation</a> – compression d’un modèle – semble également prometteur. Il semble également préférable de s&#8217;entraîner sur <a href="https://arxiv.org/abs/2306.11644">peu de données correctes mais de qualité</a>, plutôt que sur un grand nombre de données désordonnées et potentiellement erronées. En outre, pour toute application, il reste à <a href="https://deci.ai/blog/fine-tuning-peft-prompt-engineering-and-rag-which-one-is-right-for-you/">trouver les bons équilibres</a> en termes de choix de modèle, l&#8217;ingénierie du prompt, le réglage fin et le RAG.</p>



<p>Le terrain de jeu est bel et bien ouvert, l&#8217;innovation ne manque pas, et nous pouvons certainement nous attendre à de nouvelles améliorations dans un avenir proche. Une année des plus intéressantes nous attend sans aucun doute&nbsp;!</p>



<p>______________________</p>



<p><em>Cette contribution a été soumise par Joachim Ganseman, consultant IT chez Smals Research. Elle a été rédigée en son nom propre et ne prend pas position au nom de Smals.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>🎂 1 jaar ChatGPT 🎂</title>
		<link>https://www.smalsresearch.be/1-jaar-chatgpt/</link>
		
		<dc:creator><![CDATA[Joachim Ganseman]]></dc:creator>
		<pubDate>Wed, 29 Nov 2023 08:02:17 +0000</pubDate>
				<category><![CDATA[[NL]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[chatbot]]></category>
		<category><![CDATA[computational creativity]]></category>
		<category><![CDATA[egov]]></category>
		<category><![CDATA[Natural Language Processing]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[social]]></category>
		<guid isPermaLink="false">/?p=19172</guid>

					<description><![CDATA[Na 1 jaar mag de impact van ChatGPT gerust transformatief genoemd worden. Een terugblik op een bewogen jaar, en een voorzichtige poging tot vooruitblik.]]></description>
										<content:encoded><![CDATA[
<p><em>Cet article est aussi disponible <a href="/1-an-chatgpt">en français</a>.</em></p>



<p>Op 30 november 2022 werd <a href="https://openai.com/blog/chatgpt">ChatGPT</a> op de wereld losgelaten. De algemene chatbot die kan meepraten over vrijwel alles, brak onmiddellijk door bij een breed publiek. Generatoren voor afbeeldingen, zoals <a href="https://openai.com/dall-e-3">DALL-E</a> en <a href="https://stability.ai/news/stable-diffusion-public-release">Stable Diffusion</a>, deden daar nog een hele schep bovenop en ondertussen is het wel duidelijk: <em>Generative AI is here to stay</em>. Zelf gingen we er ook direct mee aan de slag, en schreven 10 dagen na de lancering al <a href="/chatgpt-een-eerste-indruk/">een artikel over onze eerste bevindingen</a> . </p>



<p>1 jaar later mag de impact van ChatGPT gerust transformatief genoemd worden. Het ecosysteem rond generatieve AI boomt. Wat 3 jaar geleden nog tot het domein van de onrealistische dromen behoorde, werd plots haalbaar en staat vandaag in productie. Talloze start-ups zien het licht: de teller op de website <a href="https://theresanaiforthat.com/"><em>There&#8217;s an AI for that</em></a> is ondertussen de 10.000 gepasseerd, met maart 2023 alleen al goed voor 1209 nieuwe AI-bedrijfjes. Ter vergelijking, voor het volledige jaar 2021 staan er maar 288 start-ups in diezelfde database. </p>



<p>De impact en de snelheid waarmee alles evolueert zorgt ook voor zenuwachtigheid. Zo moet het <a href="https://www.cam.ac.uk/stories/ChatGPT-and-education">onderwijs</a> zich in zeven haasten aanpassen aan een nieuwe realiteit. De gemiddelde scholier heeft nu vlot  toegang tot technologie die binnen enkele seconden een heel essay kan schrijven &#8211; en als <a href="https://southpark.cc.com/episodes/8byci4/south-park-deep-learning-season-26-ep-4">South Park</a> er een episode aan wijdt, weet je dat het leeft. Dichter bij huis hebben veel universiteiten ondertussen richtlijnen of adviezen opgesteld over het gebruik ervan (vb. <a href="https://www.kuleuven.be/onderwijs/student/onderwijstools/artificiele-intelligentie">Leuven</a>, <a href="https://www.ugent.be/student/nl/studeren/tools-lesopnames/chatgpt">Gent</a>, <a href="https://www.uantwerpen.be/nl/centra/studentenraad/studentenraad/standpuntenenadviezen/onderwijs/artificieleintelligentie/">Antwerpen</a>). Die zijn goed doordacht en mogen gerust inspiratiebron zijn voor gelijkaardige richtlijnen bij bedrijven en overheden.</p>



<p>Ook in professionele contexten wordt volop geëxperimenteerd. &#8220;Geen idee, maar vraag het eens aan chatGPT&#8221; is een typische uitspraak geworden als er nood is aan frisse nieuwe input. Een <a href="https://www.nature.com/articles/d41586-023-02980-0">rondvraag van Nature</a> toonde dat nogal wat wetenschappers de technologie al verkend hebben voor hun werkgerelateerde verplichtingen. In academia wordt <a href="https://doi.org/10.1038/d41586-023-03238-5">luidop de vraag gesteld</a> of het indienen van vuistdikke subsidiedossiers überhaupt nog veel zin heeft, als het schrijven ervan voor automatisering vatbaar is. Gelijkaardige bemerkingen worden ongetwijfeld ook in andere sectoren gemaakt.</p>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2023/11/2023-03-20_12h13_56.png"><img loading="lazy" decoding="async" width="1024" height="447" src="/wp-content/uploads/2023/11/2023-03-20_12h13_56-1024x447.png" alt="" class="wp-image-19551" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-03-20_12h13_56-1024x447.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-03-20_12h13_56-300x131.png 300w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-03-20_12h13_56-768x335.png 768w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-03-20_12h13_56-1536x670.png 1536w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-03-20_12h13_56.png 1705w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">DALL-E 2 is een generator die afbeeldingen genereert uit een tekstuele beschrijving.</figcaption></figure>



<h2 class="wp-block-heading">Een terugblik</h2>



<p>OpenAI blijft de dans leiden, en hun eigen <a href="https://openai.com/blog">blog</a> geeft een goed beeld van de ontwikkelingen van het afgelopen jaar. Een tijdslijn met enkele sleutelmomenten: </p>



<ul class="wp-block-list">
<li>17 januari 2023: Microsoft lanceert de <a href="https://azure.microsoft.com/en-us/products/ai-services/openai-service/">Azure OpenAI service</a>, waarmee de OpenAI technologieën beschikbaar worden op Azure,</li>



<li>1 februari 2023: Abonnementsdienst ChatGPT Plus biedt voor $20/maand prioritaire toegang tot het (sterk overbevraagde) ChatGPT,</li>



<li>1 maart 2023: ChatGPT wordt <a href="https://openai.com/blog/introducing-chatgpt-and-whisper-apis">beschikbaar via API</a>, </li>



<li>14 maart 2023: Lancering van <a href="https://en.wikipedia.org/wiki/GPT-4">GPT-4</a> voor ChatGPT Plus gebruikers,</li>



<li>23 maart 2023: De eerste <a href="https://openai.com/blog/chatgpt-plugins">plugins </a>worden gelanceerd,</li>



<li>13 juni 2023: Een updated ChatGPT kan calls naar <a href="https://openai.com/blog/function-calling-and-other-api-updates">externe functies</a> opstellen én uitvoeren,</li>



<li>20 juli 2023: Met &#8220;<a href="https://openai.com/blog/custom-instructions-for-chatgpt">custom instructions</a>&#8221; kan ChatGPT geconfigureerd worden om met bepaalde dingen altijd rekening te houden,</li>



<li>22 augustus 2023: Met de <a href="https://platform.openai.com/docs/guides/fine-tuning/fine-tuning-examples">Finetuning API</a> kan ChatGPT output worden verfijnd,</li>



<li>28 augustus 2023: Lancering van <a href="https://openai.com/blog/introducing-chatgpt-enterprise">ChatGPT Enterprise</a>, </li>



<li>25 september 2023: Gebruikers kunnen <a href="https://openai.com/blog/chatgpt-can-now-see-hear-and-speak">spraak en afbeeldingen</a> gebruiken in de conversatie,</li>



<li>19 oktober 2023: ChatGPT kan afbeeldingen genereren met <a href="https://openai.com/dall-e-3">DALL-E 3</a>,</li>



<li>6 november 2023: Introductie van <a href="https://openai.com/blog/introducing-gpts">GPTs</a> waarmee je als leek een <a href="https://chatgpt.com/create">custom ChatGPT kan samenstellen</a> die specifieke documenten doorzoekt, en de <a href="https://platform.openai.com/docs/assistants/overview">Assistants API</a> om iets gelijkaardigs te doen als programmeur.  </li>
</ul>



<p>Die laatste zet wordt <a href="https://medium.com/@ignacio.de.gregorio.noblejas/openai-just-killed-an-entire-market-in-45-minutes-818b2a8ad33e">niet unaniem op gejuich onthaald</a>: veel start-ups in het ecosysteem van generatieve AI hebben net de kern van hun hele business gebouwd rond het concept van <a href="https://research.ibm.com/blog/retrieval-augmented-generation-RAG">Retrieval-Augmented Generation</a> (RAG), en OpenAI gaat daar met hun custom GPTs direct mee in concurrentie. (Kwatongen beweren dat dit meegespeeld zou hebben in de <a href="https://www.theverge.com/2023/11/22/23967223/sam-altman-returns-ceo-open-ai">CEO-soap</a> van twee weken later, maar die geruchten zijn vooralsnog niet bewezen).</p>



<p>Retrieval-Augmented Generation (RAG), met <a href="https://python.langchain.com/">langchain</a> als populairste library voor developers, is het afgelopen jaar uitgegroeid tot dé manier om <a href="https://www.elastic.co/what-is/large-language-models">Large Language Models</a> te laten inhaken op specifieke, interne of recente informatie. Het idee volgt uit het feit dat de <a href="https://en.wikipedia.org/wiki/Prompt_engineering">prompt</a> &#8211; dit is de opdracht die men geeft aan het taalmodel &#8211; ondertussen zodanig lang mag zijn dat er ruimte is om hele bladzijden aan bijkomende informatie toe te voegen. Door de prompt te verrijken met, bijvoorbeeld, de resultaten van een zoekopdracht of de laatste nieuwsberichten, kan een chatbot toch <a href="/een-eigen-vraag-en-antwoordsysteem-op-basis-van-taalmodellen/">antwoorden formuleren op basis van recente informatie of inhoud van specifieke databases</a>, zonder dat het achterliggende taalmodel daarop getraind hoeft te zijn.</p>



<p>Microsoft was er als de kippen bij om dat om te zetten in de praktijk. Met <a href="https://blogs.microsoft.com/blog/2023/02/07/reinventing-search-with-a-new-ai-powered-microsoft-bing-and-edge-your-copilot-for-the-web/">Bing Chat</a> lanceerden ze een nieuwe conversationele zoekinterface, die voor haar antwoorden de resultaten van Bing Search gebruikt. Het voordeel is dat er transparant bronvermeldingen of referenties bij getoond kunnen worden. We moeten wel alert blijven dat dat nog steeds geen correctheid garandeert: zoekresultaten kunnen nog steeds irrelevant zijn, en samenvattingen foutief of onvolledig. Het product was wel een schot in de roos en Microsoft gaat nu <em>all-in</em>: ondertussen heeft Bing Chat een rebranding ondergaan naar <a href="https://blogs.bing.com/search/november-2023/our-vision-to-bring-microsoft-copilot-to-everyone-and-more">Microsoft CoPilot</a>, is het geïntegreerd in de Edge browser, en is het ook in <a href="https://ignite.microsoft.com/en-US/archives/8122e7d2-0acf-4685-bc47-0c27819c5264">Windows 11</a> en <a href="https://www.youtube.com/playlist?list=PLXPr7gfUMmKxDKxah3zpG4NhhDj-2lAvc">Microsoft 365</a> (het vroegere Office) beschikbaar geworden. Om deze functionaliteit te kunnen benutten, moet in de app de toelating worden gegeven om geopende documenten of webpagina-inhoud te mogen delen met de CoPilot service.</p>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2023/11/2023-11-27_15h31_16.png"><img loading="lazy" decoding="async" width="1024" height="590" src="/wp-content/uploads/2023/11/2023-11-27_15h31_16-1024x590.png" alt="" class="wp-image-19474" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-11-27_15h31_16-1024x590.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-11-27_15h31_16-300x173.png 300w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-11-27_15h31_16-768x442.png 768w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-11-27_15h31_16-1536x885.png 1536w, https://www.smalsresearch.be/wp-content/uploads/2023/11/2023-11-27_15h31_16.png 1684w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Microsoft CoPilot is vandaag al geïntegreerd in de Edge browser en kan antwoorden geven op vragen over geopende webpagina&#8217;s.</figcaption></figure>



<p>Ook op het vlak van afbeeldingen loopt Microsoft in het koppeloton: De <a href="https://www.bing.com/create">Bing Image Creator</a> biedt (voorlopig) vrije toegang tot de DALL-E 3 generator, en de resultaten ervan worden naadloos geïntegreerd in het nieuwe <a href="https://designer.microsoft.com/">Microsoft Designer</a>.</p>



<p>Google heeft minder succes met zijn eigen concurrerende <a href="https://bard.google.com/">Bard</a>. Bij de introductie liep het <a href="https://www.theverge.com/2023/2/8/23590864/google-ai-chatbot-bard-mistake-error-exoplanet-demo">grondig mis</a> toen Bard met een onjuist feit (een hallucinatie) antwoordde, en de beurskoers van Google klappen kreeg. In vergelijking met OpenAI en Microsoft, lijkt Google minder bezig te zijn met integratie en gebruikerservaring, en eerder haar focus te leggen op de <a href="https://research.google/">theoretische achtergrond</a> en uitdieping van de technologische mogelijkheden. </p>



<p>Meta wil natuurlijk niet achterblijven en trekt met haar eigen <a href="https://ai.meta.com/llama/">Llama</a> taalmodellen de quasi-open-source-kaart, met <a href="https://opensourceconnections.com/blog/2023/07/19/is-llama-2-open-source-no-and-perhaps-we-need-a-new-definition-of-open/">nadruk op quasi</a>. Hun focus lijkt vooral te liggen op de individuele developers, voor wie ze het gemakkelijk willen maken om hun taalmodellen te hergebruiken of hertrainen, wat o.a. Stanford deed met haar <a href="https://crfm.stanford.edu/2023/03/13/alpaca.html">Alpaca</a> variant. Ze mikken ook op inzetbaarheid op doorsnee hardware, via de succesvolle library <a href="https://github.com/ggerganov/llama.cpp">llama.cpp</a>, waarmee een model <a href="https://towardsdatascience.com/introduction-to-weight-quantization-2494701b9c0c">gequantizeerd</a> kan worden: het slim afronden van de parameters van een getraind model voor een kleinere geheugenvoetafdruk, ten koste van een klein maar aanvaardbaar verlies aan precisie. Een quantizatie van 32 bits naar 8 bits, maakt dat een model van 13 miljard parameters geen 52GB maar slechts 13GB RAM vereist. Zo past het volledig in het geheugen van hedendaagse grafische kaarten met 16GB of 24GB vRAM. Gebruiksvriendelijke tools om gequantizeerde modellen op je eigen computer te hosten, zijn <a href="https://gpt4all.io/index.html">GPT4All</a> , <a href="https://github.com/mlc-ai/mlc-llm">MLC</a>, <a href="https://ollama.ai/">ollama</a> of <a href="https://lmstudio.ai/">LMStudio</a>.</p>



<p>Verschillende kleinere bedrijven zitten ook nog in de race en ontwikkelen hun eigen taalmodellen die als backend voor chatGPT-achtige diensten of RAG-toepassingen kunnen dienen. Vermeldenswaardig zijn <a href="https://www.anthropic.com/">Anthropic</a>, van ex-OpenAI werknemers, dat vooral de nadruk wil leggen op transparantie en veiligheid, met haar <a href="https://claude.ai/">Claude</a>-modellen. Daarnaast kende het Europese <a href="https://techcrunch.com/2023/06/13/frances-mistral-ai-blows-in-with-a-113m-seed-round-at-a-260m-valuation-to-take-on-openai/?guccounter=1">Mistral</a> een vliegende start. Met ex-Meta werknemers aan het roer, hanteert het een écht open source model en het gaat zo vooral concurrentie aan met Meta. Voor het Nederlands taalgebied zijn er plannen om, via de onderzoeksorganisatie TNO, een <a href="https://www.digitaleoverheid.nl/nieuws/nederland-bouwt-eigen-open-taalmodel-gpt-nl/">onafhankelijk GPT-NL te ontwikkelen</a> dat ook een alternatief moet vormen voor de grote Amerikaanse spelers, en waarbij de focus moet liggen op het respecteren van de Europese wetten.</p>



<h2 class="wp-block-heading">Een vooruitblik</h2>



<p>Veel bedrijven moeten nog beginnen aan de oefening om hun eigen <a href="https://medium.com/artificial-intelligence-lab-brussels/how-to-adapt-your-business-models-to-ai-6-dimensions-of-value-creation-b23efdba5de2">businessmodellen aan de opkomst van AI aan te passen</a>. We zitten echter nog volop in de beginfase van een sterke groeiperiode voor (generatieve) AI, en het is moeilijk te voorzien wat de volgende jaren zullen brengen. Op de hoogte blijven van de evoluties is een eerste stap. Een uitstekende nieuwsbrief die de vinger aan de pols houdt, is <a href="https://www.deeplearning.ai/the-batch/">The Batch</a> van DeepLearning.AI, die elke week een bondige samenvatting maakt van de belangrijkste gebeurtenissen in de sector. Wie de kennis wil verbreden en verdiepen, vindt op dezelfde website ook een degelijk cursusaanbod, zoals deze: <a href="https://www.deeplearning.ai/courses/generative-ai-for-everyone/">Generative AI for Everyone</a> . Microsoft heeft een cursus <a href="https://microsoft.github.io/generative-ai-for-beginners/#/">Generative AI for Beginners</a> uitgewerkt die gericht is op developers. Het Finse <a href="https://www.elementsofai.com/">Elements Of AI</a> heeft een van de meest toegankelijke gratis cursussen voor een algemeen publiek, en er zijn er nog vele andere.</p>



<p>Bedrijfsleiders en beleidsmakers worden vandaag al geconfronteerd met al deze nieuwe ontwikkelingen op de werkvloer of in de administratie, en willen hierop een antwoord formuleren &#8211; of toch minstens een gedragscode ontwikkelen. De <a href="https://data-en-maatschappij.ai/beleidsmonitor">beleidsmonitor</a> van het <a href="https://data-en-maatschappij.ai/">Kenniscentrum Data en Maatschappij</a> verzamelt voorbeelden in binnen- en buitenland die als inspiratie kunnen dienen, voor wie het warm water niet opnieuw wil uitvinden. Het Britse AI Standards Hub verzamelt relevante publicaties over <a href="https://aistandardshub.org/ai-standards-search/">industriestandaarden</a> met betrekking tot AI. Op een abstracter internationaal niveau is o.a. de <a href="https://oecd.ai/en/">OESO</a> actief bezig met monitoring. Het zich snel veranderende landschap maakt het wetgevend werk zeker niet gemakkelijker. Op Europees niveau loopt de verwachte <a href="https://artificialintelligenceact.eu/developments/">AI act</a> alleszins <a href="https://www.reuters.com/technology/eu-lawmakers-face-struggle-reach-agreement-ai-rules-sources-2023-10-23/">vertraging </a>op. Dit weerhield Stanford er niet van om de <a href="https://crfm.stanford.edu/2023/06/15/eu-ai-act.html">bestaande grote spelers al eens te evalueren</a> op basis van de ontwerptekst die nu voorligt.</p>



<p>Ondertussen houdt niets een bedrijf of overheid tegen om al aan de slag te gaan en te experimenteren met de technologie. Het blijft daarbij wel belangrijk om niet te hard van stapel te lopen en het gezond verstand niet overboord te gooien. ChatGPT is geen mirakeloplossing. Geen enkele hoeveelheid  veiligheidsmechanismes kan garanderen dat een taalmodel niet zou <a href="https://en.wikipedia.org/wiki/Hallucination_(artificial_intelligence)">hallucineren</a> of compleet  verzonnen tekstjes zou presenteren als feiten. Van veel taalmodellen zijn de trainingsdatasets geheim, maar we weten wel dat ze zo groot zijn dat er onmogelijk een nauwkeurige selectie en filtering op gebeurd kan zijn. LLMs zijn vandaag <a href="https://promptengineering.org/the-black-box-problem-opaque-inner-workings-of-large-language-models/">black boxes</a>; de oorsprong van een bepaalde woordkeuze in een antwoord is niet te achterhalen. Dit alles maakt ze logischerwijs ongeschikt om er klakkeloos kritische toepassingen op te bouwen. Het is evident dat het een slecht idee zou zijn om, zonder enige supervisie, medische gegevens te laten verwerken door een taalmodel dat deels getraind is op willekeurig van het net geplukte teksten van samenzweringstheoretici, antivaxers, instagram-influencers, homeopaten en andere kwakzalvers. </p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2023/11/webinar-AI-coding_2.png"><img loading="lazy" decoding="async" width="897" height="502" src="/wp-content/uploads/2023/11/webinar-AI-coding_2.png" alt="" class="wp-image-19504" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/11/webinar-AI-coding_2.png 897w, https://www.smalsresearch.be/wp-content/uploads/2023/11/webinar-AI-coding_2-300x168.png 300w, https://www.smalsresearch.be/wp-content/uploads/2023/11/webinar-AI-coding_2-768x430.png 768w" sizes="auto, (max-width: 897px) 100vw, 897px" /></a><figcaption class="wp-element-caption">Afbeelding gegenereerd door Microsoft Image Creator (DALL-E 3) op basis van de prompt: <em>&#8220;An AI is helping a programmer solve a difficult problem in the IDE. Focus on the computer screen containing flawed code. We only see the back of the people.&#8221;</em></figcaption></figure>



<p>Over kwakzalverij gesproken, met de <a href="https://medium.com/@emilymenonbender/aihype-take-downs-5c6fcc5c5ba1">regelmaat van de klok</a> duiken nu ook doemdenkers op, die <a href="https://www.schneier.com/blog/archives/2023/10/ai-risks.html">in een opbod voor aandacht</a>, met steeds groteskere uitspraken op de proppen komen, tot aan het voorspellen van het uitsterven van de mens toe. (Het omgekeerde bestaat ook: mensen die geloven dat utopia nabij is.) De disproportionaliteit van zulke uitspraken alleen al, getuigt van weinig kennis van zaken én weinig voeling met de realiteit. Alle vooruitgang ten spijt, zijn we immers nog mijlenver verwijderd van het punt dat een robot zelfs maar uw kleren kan strijken. Clowneske claims leiden de discussie wel af van de problemen die vandaag in de echte wereld opduiken: misbruik zoals <a href="https://dl.acm.org/doi/10.1145/3584973">deepfakes</a>, vergroting van de digitale kloof, een gebrek aan mogelijkheden om automatische beslissingen aan te vechten, het gebruik van data zonder toelating of bronvermelding, etc. Allemaal zaken waar de nodige aandacht naartoe moet blijven gaan, en waar Europa <a href="https://digital-strategy.ec.europa.eu/en/library/ethics-guidelines-trustworthy-ai">een actieve voortrekkersrol</a> speelt. Dat hoeven geen blokkerende factoren te zijn, want ook met beide voetjes op de grond is er geen gebrek aan <a href="https://www.youtube.com/watch?v=5p248yoa3oE">opportuniteiten</a>. </p>



<p>In een <a href="https://www.gatesnotes.com/AI-agents">recent opiniestuk</a> oogstte Bill Gates veel bijklank voor zijn visie op de evolutie in de nabije toekomst. Die is dat chatbots verder evolueren naar &#8220;<a href="https://python.langchain.com/docs/how_to/#agents">agents</a>&#8220;, d.w.z. dat ze ook een (beperkte) autonomie krijgen om actie te ondernemen, eventueel gesuperviseerd. Waar Co-Pilots nog onderdeel zijn van een applicatie, zou ook dat generieker worden, met de bedoeling dat toekomstige agents over applicaties heen kunnen werken, zoals personal assistants. Inderdaad is er nog heel wat werk te verzetten voor het zover is: protocollen die apps toelaten beter met elkaar te communiceren, manieren om veilig data uit te wisselen terwijl de privacy wordt gevrijwaard, &#8230;</p>



<p>Tot slot blijft de afhankelijkheid van enorme en niet-transparante modellen (GPT-3, GPT-4) bij een externe clouddienst, een moeilijke pil om te slikken wanneer er interne of gevoelige gegevens verwerkt zouden kunnen worden. Het is onvoorspelbaar welke gegevens een doorsnee gebruiker zou kunnen meedelen aan een chatbot, en bij CoPilot-achtige plugins is het vaak moeilijk terug te vinden welke gegevens de plugin meeleest en achter de schermen doorstuurt. De <a href="https://eur-lex.europa.eu/eli/reg/2016/679/oj">GDPR </a>stelt echter wel strenge en concrete eisen. Beloftes in gebruikersvoorwaarden of zelfs contractuele afspraken dat ontvangen data niet zal worden opgeslagen of hergebruikt, zijn niet voor iedereen voldoende om plots blind vertrouwen te hebben. </p>



<p>Het voor de hand liggende alternatief is het lokaal deployen van kleinere modellen. De <a href="https://github.com/vectara/hallucination-leaderboard">kwaliteit van de output</a> daarvan is echter navenant lager, en dat stelt teleur als hoge verwachtingen gecreëerd door chatGPT het referentiepunt zijn. Kleinere modellen missen de vlotte meertaligheid van ChatGPT, en werken nog met veel compactere prompts, wat de uitbouw van RAG-apps ermee limiteert. Er wordt ijverig en in verschillende richtingen gezocht naar manieren om die kloof te dichten. Zo wordt er verder geïnnoveerd in manieren om kleinere modellen <a href="https://github.com/huggingface/peft">efficiënter te finetunen</a> (specialiseren) voor een specifieke taak.  Ook het concept van <a href="https://arxiv.org/abs/1503.02531">distilleren </a>&#8211; het comprimeren van een model &#8211; oogt veelbelovend. Er zijn indicaties dat betere resultaten behaald kunnen worden door te trainen op <a href="https://arxiv.org/abs/2306.11644">weinig maar kwalitatieve en correcte data</a>, in plaats van op veel rommelige en mogelijke foutieve data. Verder blijft het voor elke applicatie, <a href="https://deci.ai/blog/fine-tuning-peft-prompt-engineering-and-rag-which-one-is-right-for-you/">zoeken naar goede balansen</a> qua modelkeuze, <a href="https://en.wikipedia.org/wiki/Prompt_engineering">prompt engineering</a>, finetuning, en RAG.</p>



<p>Het speelveld ligt dus nog helemaal open en er is er volop ruimte voor innovatie. We mogen zeker nog verdere verbeteringen verwachten op korte termijn. Er komt ongetwijfeld opnieuw een razend interessant jaar aan!</p>



<p>______________________</p>



<p><em>Dit is een ingezonden bijdrage van Joachim Ganseman, IT consultant bij Smals Research. &nbsp;Dit artikel werd geschreven in eigen naam en neemt geen standpunt in namens Smals.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>LLM pour code&#160;: the Good, the Bad and the Ugly</title>
		<link>https://www.smalsresearch.be/llms-pour-code/</link>
		
		<dc:creator><![CDATA[Joachim Ganseman]]></dc:creator>
		<pubDate>Thu, 07 Sep 2023 10:01:46 +0000</pubDate>
				<category><![CDATA[[FR]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[chatbot]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[computational creativity]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[Natural Language Processing]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[software engineering]]></category>
		<category><![CDATA[source code]]></category>
		<guid isPermaLink="false">/?p=19037</guid>

					<description><![CDATA[Quelle est la situation dans le domaine de la génération de code, et que devons-nous encore prendre en compte ?]]></description>
										<content:encoded><![CDATA[
<p><em>Dit artikel is ook te lezen <a href="/llms-voor-code/">in het Nederlands</a>.</em></p>



<p><em>Cet article a été traduit du néerlandais. Les liens peuvent pointer vers des sources en néerlandais.</em></p>



<p>Dans un <a href="/de-ai-augmented-developer/">article précédent</a>, nous avons discuté de manière générale du potentiel de l&#8217;IA générative dans le <a href="https://www.servicenow.com/products/devops/what-is-sdlc.html">Software Development Lifecycle</a>. Examinons maintenant la question du point de vue du développeur&nbsp;: quel est l&#8217;état d&#8217;avancement de la génération de code et que devons-nous encore prendre en compte&nbsp;? Pour faire court&nbsp;: les assistants IA ou les plugins pour IDE sont une aubaine pour ceux qui savent en faire bon usage, mais comme tous les systèmes d&#8217;IA, ils présentent aussi des inconvénients.</p>



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



<p>Une partie de cette <a href="https://theresanaiforthat.com/">hype</a> en termes d&#8217;IA générative est propulsée par des <a href="https://en.wikipedia.org/wiki/Large_language_model">modèles de langages puissants</a> &#8211; les grands modèles de langue ou LLM. Depuis la sortie du GPT-3 en 2020, ces modèles parviennent à écrire des textes normaux d&#8217;une certaine longueur. De là, il n&#8217;y a qu&#8217;un pas vers les langages de programmation. En effet, ils ont aussi une syntaxe et une sémantique.</p>



<p>Dans la pratique, il existe de nombreuses variantes de modèles de langue, chacun ayant ses forces et ses faiblesses, en fonction des choix faits par les créateurs pour les entraîner, et en fonction des données d&#8217;entraînement qui les sous-tendent. Testez vous-même certains des modèles open source existants sur votre propre ordinateur via l&#8217;outil <a href="https://gpt4all.io/index.html">GPT4All</a> (voir également <a href="/publications/document/?docid=270">notre quick review</a> de cet outil).</p>



<p>Le code informatique consiste en une collection de fichiers texte. Rien n&#8217;empêche un modèle de langue d&#8217;essayer de prédire les différents <a href="https://www.techtarget.com/searchapparchitecture/definition/parser">tokens (= unités grammaticales)</a> qui composent le code, plutôt que des mots. Cependant, contrairement au texte brut, le code a beaucoup moins de tolérance à l&#8217;erreur&nbsp;: la moindre faute d&#8217;orthographe ou la plus petite variation peut invalider un morceau de code ou lui faire exécuter quelque chose de complètement différent.</p>



<p>Pourtant, aujourd&#8217;hui, les plus grands modèles de langue, tels que GPT-3.5 et les versions ultérieures, peuvent produire d&#8217;eux-mêmes des morceaux de code informatique tout à fait corrects en réponse à une requête. Cette fonctionnalité est due à la quantité massive de textes sur lesquels ils sont formés, notamment de nombreux tutoriels, articles de blog, questions et réponses provenant de forums de développeurs populaires tels que <a href="https://stackoverflow.com/">StackOverflow</a>, et code documenté provenant de repositories de code publics tels que <a href="https://github.com/">Github</a>.</p>



<h2 class="wp-block-heading"><strong>Canards en plastique bavards</strong></h2>



<p>Depuis <a href="https://en.wikipedia.org/wiki/Socratic_dialogue">Socrate</a>, le dialogue est un moyen efficace de parvenir à de nouvelles perspectives. Ce n&#8217;est pas pour rien que le <a href="https://blog.codinghorror.com/rubber-duck-problem-solving/">rubber ducking</a> est une méthode de correction de bugs qui revient dans tous les cours de génie logiciel. Il existe entre-temps plusieurs plugins qui mettent à disposition une interface de chat alimentée par l&#8217;IA dans l&#8217;IDE même (par exemple <a href="https://github.com/timkmecl/chatgpt-vscode">ceux pour VS Code</a>, beaucoup d&#8217;autres peuvent être trouvés via les <a href="https://marketplace.visualstudio.com/search?term=gpt&amp;target=VSCode">marketplaces pour VS Code</a>&nbsp;ou&nbsp;<a href="https://plugins.jetbrains.com/search?products=idea_ce&amp;search=gpt">IntelliJ IDEA</a>). Si ces plugins utilisent un service cloud externe, il vous suffit d&#8217;entrer votre propre clé API.</p>



<p>Un cadre de dialogue avec une dynamique de questions-réponses peut être bien utilisé pour générer des morceaux de code relativement autonomes, sans trop de dépendances externes. En général, pour obtenir le meilleur résultat, il faut pouvoir énoncer facilement toutes les conditions préalables et les hypothèses nécessaires dans le dialogue lui-même, de manière à ce qu&#8217;il s&#8217;inscrive dans la fenêtre contextuelle du modèle de langue. Les use cases comprennent entre autres&nbsp;:</p>



<ul class="wp-block-list">
<li>La génération <em>from scratch</em> d&#8217;une version initiale du code ou d&#8217;un fichier de configuration</li>



<li>La génération de fonctions ou de procédures relativement courtes à partir d&#8217;une description</li>



<li>La génération de <em>code snippets</em> autonomes&nbsp;: requêtes SQL, expressions régulières&#8230;</li>



<li>Demande de modification d&#8217;un morceau de code ou d&#8217;un fichier de configuration</li>



<li>Correction de bugs&nbsp;: recherche d&#8217;erreurs dans un code qui ne fonctionne pas, poser des questions sur une erreur</li>



<li>Faire expliquer ce qu&#8217;un morceau de code fait</li>
</ul>



<p>Les plus grands modèles de langue disposent de fenêtres contextuelles de plusieurs milliers de mots dans lesquelles il est possible d&#8217;insérer toutes les informations nécessaires. Un modèle de langue open source plus petit, installé localement sur du matériel moins puissant, sera sans aucun doute moins performant. Voici quelques exemples de conversations avec GPT-4 d&#8217;OpenAI, qui montrent qu&#8217;il est possible d&#8217;aller très loin avec quelques questions bien ciblées (cliquez sur l&#8217;image pour obtenir la pleine résolution)&nbsp;:</p>



<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/2023/08/2023-08-22_16h05_32.png"><img loading="lazy" decoding="async" width="143" height="1024" data-id="18959" src="/wp-content/uploads/2023/08/2023-08-22_16h05_32-143x1024.png" alt="" class="wp-image-18959" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h05_32-143x1024.png 143w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h05_32-42x300.png 42w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h05_32-286x2048.png 286w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h05_32-scaled.png 358w" sizes="auto, (max-width: 143px) 100vw, 143px" /></a><figcaption class="wp-element-caption">Exemple de conversation sur le code avec le modèle GPT-4 de ChatGPT&nbsp;: génération d&#8217;une configuration pour un remote server VNC sur un système Ubuntu partagé.</figcaption></figure>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2023/08/2023-08-22_16h17_10.png"><img loading="lazy" decoding="async" width="198" height="1024" data-id="18958" src="/wp-content/uploads/2023/08/2023-08-22_16h17_10-198x1024.png" alt="" class="wp-image-18958" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h17_10-198x1024.png 198w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h17_10-297x1536.png 297w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h17_10-58x300.png 58w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h17_10-768x3977.png 768w" sizes="auto, (max-width: 198px) 100vw, 198px" /></a><figcaption class="wp-element-caption">Exemple de conversation avec le modèle GPT-4 de ChatGPT&nbsp;: génération d&#8217;une requête SQL pour la transposition d&#8217;un tableau. La solution finale proposée utilise des techniques assez sophistiquées avec des procédures stockées.</figcaption></figure>
</figure>



<h2 class="wp-block-heading"><strong>Complétion de code sous stéroïdes</strong></h2>



<p>Au cours du développement, un développeur travaille sur de nombreux fichiers dans un IDE. À des endroits aléatoires de ces fichiers, le code doit être modifié, supprimé ou écrit. L&#8217;édition de code existant de cette manière n&#8217;a pas grand-chose à voir avec le dialogue&nbsp;; en fait, nous préférerions utiliser l&#8217;auto-complétion avancée dans ce cas. Les modèles de langue peuvent également faire l&#8217;affaire, mais les modèles les plus appropriés sont plutôt ceux formés aux tâches de &#8220;remplir au milieu&#8221; &#8211; et qui peuvent donc prendre en compte le code présent avant et après l&#8217;endroit que l&#8217;on édite.</p>



<p>Après la sortie de GPT-3, OpenAI a travaillé avec Microsoft (qui possède Github) pour créer un modèle de langue spécialisé, formé exactement pour ce use case. Cette variante a été nommée <a href="https://openai.com/blog/openai-codex">Codex</a>, et le premier outil à l&#8217;utiliser a été <a href="https://github.com/features/copilot">Github CoPilot</a>. Depuis, nous en sommes à plusieurs versions, mais les plugins pour <a href="https://marketplace.visualstudio.com/items?itemName=GitHub.copilot">VSCode</a> et <a href="https://plugins.jetbrains.com/plugin/17718-github-copilot">IntelliJ</a> fonctionnent toujours de la même manière&nbsp;: via un raccourci clavier dans l&#8217;éditeur, on peut utiliser CoPilot pour récupérer diverses suggestions, générées par Codex, qui pourraient correspondre à l&#8217;endroit où se trouve le curseur.</p>



<p>D&#8217;après notre expérience actuelle, le contexte pris en compte est généralement limité au contenu (partiel) du fichier édité. Cela implique évidemment le <a href="https://resources.github.com/copilot-trust-center/">téléchargement vers le modèle de langue</a> &#8211; veillez donc à respecter les directives en matière de confidentialité lorsque vous utilisez un service externe. Pour l&#8217;instant, nous semblons obtenir de meilleurs résultats dans les projets de programmation composés de quelques gros fichiers, tels que les pages web avec JavaScript en ligne, ou Jupyter Notebooks en Python, où il y a souvent un gros fichier à parcourir qui contient à la fois la documentation, le code et l’output. En revanche, dans les projets comportant de nombreux petits fichiers, il semble plus difficile de générer de bonnes suggestions, et il est plus important de disposer d&#8217;une documentation supplémentaire dans le fichier édité afin que le modèle de langue puisse puiser dans suffisamment d&#8217;informations contextuelles.</p>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2023/08/copilot-in-vscode-example.png"><img loading="lazy" decoding="async" width="1024" height="604" src="/wp-content/uploads/2023/08/copilot-in-vscode-example-1024x604.png" alt="" class="wp-image-18964" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/08/copilot-in-vscode-example-1024x604.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2023/08/copilot-in-vscode-example-300x177.png 300w, https://www.smalsresearch.be/wp-content/uploads/2023/08/copilot-in-vscode-example-768x453.png 768w, https://www.smalsresearch.be/wp-content/uploads/2023/08/copilot-in-vscode-example.png 1276w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Github CoPilot dans VSCode. Suivant un schéma déjà présent dans le même fichier, un objet Rounding() doit être créé pour chaque élément d&#8217;un dictionnaire Python. L&#8217;itération fonctionne bien, mais CoPilot n&#8217;a manifestement aucune connaissance du function header, qui n&#8217;est définie ni dans ce même fichier ni dans la &#8220;connaissance générale&#8221; du modèle Codex de CoPilot&nbsp;: les suggestions proposent des paramètres qui n&#8217;existent pas. Immédiatement après avoir accepté cette solution erronée, le vérificateur de code statique intégré se plaint du paramètre manquant</figcaption></figure>



<p>L&#8217;une des alternatives les plus intéressantes au modèle commercial Github CoPilot est <a href="https://huggingface.co/blog/starcoder">StarCoder</a>, un modèle open source issu de l&#8217;initiative <a href="https://www.bigcode-project.org/">BigCode</a> HuggingFace et ServiceNow. Bien que la performance soit <a href="https://llm-leaderboard.streamlit.app/">moindre que CoPilot</a>, ils font la différence dans de nombreux autres domaines qui peuvent être des obstacles dans des contextes commerciaux ou publics&nbsp;:</p>



<ul class="wp-block-list">
<li>Entraînés sur un dataset public&nbsp;:&nbsp;<a href="https://huggingface.co/datasets/bigcode/the-stack">The Stack</a>. Bien qu&#8217;il ait été collecté par scraping, il ne contient que du code avec <a href="https://en.wikipedia.org/wiki/Permissive_software_license">des licences logicielles permissives</a>, et les développeurs peuvent, s&#8217;ils le souhaitent, <a href="https://huggingface.co/spaces/bigcode/in-the-stack">toujours faire retirer leur code du dataset</a>.</li>



<li>Comprend un outil <a href="https://huggingface.co/spaces/bigcode/search">de vérification de plagiat</a>, qui permet de vérifier que les suggestions générées n&#8217;ont pas été copiées mot pour mot à partir des données d&#8217;apprentissage (éventuellement protégées par des droits d&#8217;auteur).</li>



<li>Pourvu d&#8217;un <a href="https://huggingface.co/bigcode/starpii">filtre d&#8217;informations sensibles</a>, qui détecte les adresses électroniques, les clés API et les adresses IP (pas exact à 100&nbsp;%).</li>



<li>Contient des <a href="https://github.com/bigcode-project/starcoder/tree/main">instructions pour installer localement</a>, ainsi qu&#8217;un <a href="https://marketplace.visualstudio.com/items?itemName=HuggingFace.huggingface-vscode">plugin VSCode</a>. Un <a href="https://plugins.jetbrains.com/plugin/22090-starcoder">plugin IntelliJ</a> a entre-temps également été développé par un tiers.</li>



<li>Le modèle standard a une taille de 15 milliards de paramètres et nécessite au moins 60 GB de RAM ou autant de mémoire GPU (en fonction de l&#8217;utilisation ou non d&#8217;un GPU) pour être utilisé. Il existe également de <a href="https://huggingface.co/spaces/bigcode/multilingual-code-evals">plus petits modèles</a> à 7, 3 ou 1 milliard de paramètres, ainsi que des <a href="https://github.com/bigcode-project/starcoder.cpp">versions quantisées</a> utilisant des types de données à 4 bits, sans grande perte de précision.</li>
</ul>



<p>Plusieurs autres systèmes ont vu le jour cet été et ont obtenu de bons résultats dans de nombreux benchmarks&nbsp;:&nbsp;<a href="https://github.com/nlpxucan/WizardLM">WizardLM</a> et sa variante spécifique <a href="https://arxiv.org/abs/2306.08568">WizardCoder</a>, qui est désormais considéré comme le nec plus ultra de l&#8217;open source, et <a href="https://arxiv.org/abs/2207.11280">PanGu-Coder</a>, avec lequel Huawei s&#8217;est également lancé dans le monde des assistants IA pour le code.&nbsp;</p>



<h2 class="wp-block-heading"><strong>Au cœur de l&#8217;action</strong></h2>



<p>Le <a href="https://arxiv.org/abs/2305.06161">StarCoder paper</a> offre un bel aperçu du fonctionnement d&#8217;un modèle de langue pour le code.<br>Ce n&#8217;est certainement pas comme si vous pouviez &#8220;brancher&#8221; votre propre codebase pour obtenir des suggestions adaptées. Si vous voulez vraiment affiner le modèle (et vous ne ferez cet énorme effort <a href="https://twitter.com/rachel_l_woods/status/1692577254914638340">que si vous n&#8217;y arrivez pas</a> avec <a href="https://en.wikipedia.org/wiki/Prompt_engineering">des modifications astucieuses du prompt</a>), il y a beaucoup de choses à faire, du prétraitement des données d&#8217;entraînement au post-traitement de l’output brut du modèle de langue. Ne vous attendez pas non plus à ce que le réglage fin soit trop élevé&nbsp;: StarCoder l&#8217;a fait pour Python, mais n&#8217;a obtenu <a href="https://huggingface.co/blog/starcoder">que quelques points de pourcentage d&#8217;amélioration</a> par rapport au modèle global qui pourrait traiter tous les langages de programmation. Le peaufinage est difficile et il n&#8217;y a aucune garantie de succès&nbsp;; il y a même un risque d’<a href="https://research.nccgroup.com/2023/05/22/exploring-overfitting-risks-in-large-language-models/">overfitting</a>, ce qui pourrait dégrader les résultats.</p>



<p>L&#8217;étape la plus importante est probablement la collecte et le nettoyage des données.&nbsp;<a href="https://huggingface.co/datasets/bigcode/starcoderdata">Ces données sont constituées de code</a>, mais tous les codes ne sont pas inclus&nbsp;: vous devez également être autorisé à utiliser le code (licences) et, de préférence, l&#8217;avoir aussi correct que possible et écrit dans le langage de programmation que vous souhaitez soutenir. Le code est également collecté à partir <a href="https://en.wikipedia.org/wiki/Bug_tracking_system">des issue trackers</a> et <a href="https://en.wikipedia.org/wiki/Version_control">du commit history</a>. En outre, un filtrage additionnel peut être effectué pour supprimer les (quasi-)doublons, et des pondérations peuvent être attribuées ici et là pour maintenir l&#8217;équilibre&nbsp;: un peu moins de poids pour le code &#8220;boilerplate&#8221;, et/ou un peu plus pour les repositories très populaires qui sont susceptibles d&#8217;être de meilleure qualité. Le code source peut contenir des informations sensibles qui doivent être <a href="https://en.wikipedia.org/wiki/Data_anonymization">rendues anonymes</a> ou supprimées au préalable, pour éviter qu&#8217;elles ne soient divulguées ou suggérées (adresses IP, mots de passe, identifiants, adresses électroniques, coordonnées&#8230;). Tout cela, bien sûr, de préférence aussi automatiquement que possible.</p>



<p>Le code source se compose non seulement de code, mais aussi de descriptions, de commentaires et d&#8217;autres informations. Dans une étape de formatage, le code est donc enrichi par l’ajout de métadonnées et de <a href="https://huggingface.co/docs/transformers/main/internal/tokenization_utils#transformers.SpecialTokensMixin">tokens supplémentaires</a> qui rendent explicites certaines structures implicites. Cela peut avoir des conséquences&nbsp;: si tout ce prétraitement a été effectué sur l&#8217;ensemble des données d&#8217;apprentissage, le modèle résultant ne fonctionnera correctement sur de nouvelles données que s&#8217;il a subi le même prétraitement. Ainsi, les plugins éditeur qui souhaitent utiliser un tel modèle peuvent, pour obtenir un bon résultat, devoir d&#8217;abord effectuer un <a href="https://github.com/huggingface/huggingface-vscode/blob/a4a413723e9687bd2a7195d0e859f74467287571/package.json#L204">prétraitement similaire</a> sur le code qu&#8217;ils souhaitent envoyer au modèle de langue.</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2023/08/2023-08-22_10h52_37.png"><img loading="lazy" decoding="async" width="325" height="353" src="/wp-content/uploads/2023/08/2023-08-22_10h52_37.png" alt="" class="wp-image-18951" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_10h52_37.png 325w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_10h52_37-276x300.png 276w" sizes="auto, (max-width: 325px) 100vw, 325px" /></a><figcaption class="wp-element-caption">Pour que le modèle puisse mieux distinguer les différentes parties du code source, les données d&#8217;entraînement sont enrichies de métadonnées et de ce que l&#8217;on appelle des &#8220;tokens sentinelles&#8221;. &#8220;sentinel tokens&#8221;, comme cette liste tirée du <a href="https://arxiv.org/abs/2305.06161">StarCoder paper</a>.</figcaption></figure>



<h2 class="wp-block-heading"><strong>Exactitude et autres benchmarks</strong></h2>



<p>Comme c&#8217;est le cas pour les LLM, il ne peut y avoir de garantie concluante de l&#8217;exactitude ou de l&#8217;exhaustivité de ce qu&#8217;un tel plugin présente, tant sur le plan syntaxique que sur le plan sémantique. Cette précision est évidemment importante&nbsp;: un morceau de code généré ne doit pas seulement être syntaxiquement correct et compiler sans faille, mais aussi être sémantiquement significatif et s&#8217;exécuter correctement. La métrique &#8220;pass@x&#8221; est devenue une mesure importante à cet égard. Elle exprime en pourcentage si un modèle de langue pour une mission donnée peut passer avec succès les tests correspondants après X tentatives. &#8220;pass@1&#8221; est le pourcentage pour lequel le modèle de langue utilisé pour la première fois a pu générer la bonne réponse, &#8220;pass@10&#8221; est le pourcentage pour lequel au moins 1 tentative sur 10 a été correcte.</p>



<p>Dans le monde de l&#8217;IA générative, il existe un besoin général de pouvoir comparer les nouveaux modèles, qui apparaissent désormais presque quotidiennement, avec le meilleur de la technologie. Il n&#8217;y a donc pas de pénurie de benchmarks, et de nouveaux modèles plus importants apparaissent régulièrement. Des résumés utiles sont les &#8220;leaderboards&#8221;, qui montrent en temps réel quels modèles représentent l&#8217;état actuel de la technique selon une série de benchmarks. L&#8217;étape peut changer chaque semaine. Voici quelques leaderboards généraux intéressants&nbsp;:</p>



<ul class="wp-block-list">
<li><a href="https://paperswithcode.com/sota">Papers with Code</a>&nbsp;: l&#8217;état de l&#8217;art dans diverses tâches d&#8217;intelligence artificielle, avec des documents d&#8217;accompagnement.</li>



<li><a href="https://crfm.stanford.edu/helm/latest">Stanford HELM</a>&nbsp;: analyse comparative d&#8217;un large éventail de tâches en se focalisant sur le &#8220;human reasoning&#8221; (raisonnement humain).</li>



<li><a href="https://chat.lmsys.org/?leaderboard">LMsys.org FastChat</a>&nbsp;: se concentre sur les capacités chatbot.</li>



<li><a href="https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard">HuggingFace OpenLLM leaderboard</a>.</li>



<li><a href="https://llm-leaderboard.streamlit.app/">LLM-Leaderboard</a>.</li>
</ul>



<p>En ce qui concerne le code, il existe des benchmarks qui fonctionnent plus ou moins comme un concours de programmation. L&#8217;idée est de confier un ensemble de tâches au modèle de langue, d&#8217;évaluer les résultats automatiquement et de mesurer le &#8220;pass@1&#8221; et, si possible, d&#8217;autres paramètres. Souvent, il s&#8217;agit de &#8220;remplir la fonction&#8221;&nbsp;: à partir d&#8217;une description de l’input, de l’output et d&#8217;un function header, le contenu de la fonction doit être généré. L&#8217;inconvénient est que ce type de problème n&#8217;est parfois <a href="https://www.computer.org/csdl/journal/ts/2023/07/10103177/1MpWUtj7Rwk">pas très représentatif</a> de celui auquel est confronté le développeur lambda. Parmi les initiatives intéressantes, on peut citer&nbsp;:</p>



<ul class="wp-block-list">
<li>HuggingFace&nbsp;<a href="https://huggingface.co/spaces/bigcode/bigcode-models-leaderboard">Big Code Models leaderboard</a>&nbsp;(uniquement LLM publics).</li>



<li>Microsoft <a href="https://github.com/microsoft/CodeXGLUE">CodeXGLUE</a>&nbsp;: évaluation de diverses sous-tâches selon des méthodes connues de Natural Language Processing. Ce <a href="https://microsoft.github.io/CodeXGLUE/">leaderboard</a> semble dépendre de contributions volontaires et est quelque peu incomplet.</li>



<li>Papers with Code a des sections séparées pour&nbsp;<a href="https://paperswithcode.com/task/code-generation">la génération de code</a>,&nbsp;<a href="https://paperswithcode.com/task/code-documentation-generation">la création de documents</a>,&nbsp;<a href="https://paperswithcode.com/task/program-synthesis">la synthèse de programmes entiers</a>&nbsp;et&nbsp;<a href="https://paperswithcode.com/task/program-repair">la correction de bugs</a>.</li>



<li>Le <a href="https://paperswithcode.com/dataset/humaneval">HumanEval dataset</a> et <a href="https://paperswithcode.com/dataset/mbpp">MBPP dataset</a>&nbsp;: problèmes de programmation typique (Python).</li>



<li>Le&nbsp;<a href="https://paperswithcode.com/dataset/ds-1000">DS-1000 dataset</a>&nbsp;: ensemble de problèmes de data processing / data science concrets.</li>



<li><a href="https://paperswithcode.com/dataset/humaneval-x">HumanEval-X</a> ou <a href="https://github.com/nuprl/MultiPL-E">MultiPL-E</a>&nbsp;: versions multilingues de HumanEval, mesurant les performances dans plusieurs langages de programmation.</li>
</ul>



<p>Bien entendu, le fait qu&#8217;un morceau de code généré survive aux tests ne signifie pas qu&#8217;il s&#8217;agit d&#8217;un code sécurisé ou qu&#8217;il respecte les &#8220;best practices&#8221;. Entre-temps, il existe de nombreux exemples connus de code généré qui s&#8217;avère sensible aux &#8220;buffer overflows&#8221;, à l&#8217;injection SQL et à d&#8217;autres risques classiques. Le benchmark de sécurité <a href="https://huggingface.co/datasets/moyix/asleep_keyboard">&#8220;Asleep at the Keyboard&#8221;</a> consiste en 89 scénarios de génération de code basés sur la liste <a href="https://cwe.mitre.org/top25/">MITRE top-25 vulnerability</a>. <a href="https://arxiv.org/abs/2305.06161">Starcoder paper</a> montre que même les meilleurs modèles génèrent encore du code non sécurisé dans 40&nbsp;% de ces scénarios. En outre, il ne semble guère y avoir de différence entre les meilleurs modèles et les autres &#8211; le choix d&#8217;un meilleur modèle semble garantir des résultats syntaxiquement plus corrects, mais pas encore un code plus sûr. Il est donc possible que nous devions nous pencher sur les données d&#8217;apprentissage elles-mêmes, où le code non sécurisé devrait être encore mieux filtré. Quoi qu&#8217;il en soit, il convient de rappeler que l&#8217;utilisation de code généré dans un projet doit impérativement s&#8217;accompagner d&#8217;une solide politique de test et d&#8217;acceptation.</p>



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



<p>En ce qui concerne plus particulièrement les exigences computationnelles, le leaderboard <a href="https://huggingface.co/spaces/optimum/llm-perf-leaderboard">Huggingface OpenLLM-perf</a> et les benchmarks sur le site web <a href="https://bellard.org/ts_server/">TextSynth Server</a> constituent des sources intéressantes. Ce dernier montre quelques chiffres de performance utiles pour ceux qui envisagent un hébergement par leurs propres moyens. Ceux qui n&#8217;ont pas de GPU peuvent compter sur une vitesse de 12 tokens par seconde avec le modèle LLaMa2 de 13 milliards de paramètres, avec un processeur de serveur <a href="https://tweakers.net/pricewatch/1672608/amd-epyc-7313-tray.html">EPYC 7313</a> relativement haut de gamme. Dans un code informatique, un token ne représente parfois qu&#8217;un seul caractère, de sorte qu&#8217;à cette vitesse, il faut parfois attendre une dizaine de secondes pour obtenir une suggestion de complétion de code. La dernière carte graphique RTX-4090 peut le faire 7 fois plus vite, mais pas encore au point de l&#8217;exprimer en millisecondes.</p>



<p>Les besoins en mémoire sont proportionnels au nombre de paramètres d&#8217;un modèle, et la vitesse de génération inversement proportionnelle. À titre d&#8217;approximation, on peut supposer qu&#8217;un modèle comportant 13 milliards de paramètres doit également effectuer 13 milliards de calculs pour chaque token de sortie, même s&#8217;il ne comporte qu&#8217;un seul caractère. En outre, si chaque paramètre est un nombre de 32 bits, il faut au moins 52 Go de stockage et autant de mémoire (V)RAM. Une &#8220;<a href="https://huggingface.co/docs/transformers/main_classes/quantization">quantization</a>&#8220;, arrondissant les paramètres à 8 bits ou même à 4 bits, peut réduire proportionnellement ce besoin en mémoire.</p>



<p><a href="https://gpt4all.io/index.html">GPT4All</a> permet de l&#8217;essayer sur votre propre matériel. Cela donne une idée de l&#8217;énorme puissance de calcul qu&#8217;OpenAI, Microsoft Azure ou Amazon AWS déploient pour que leurs modèles, dont beaucoup sont encore plus grands que les LLM disponibles en libre accès, fonctionnent aussi vite qu&#8217;ils le proposent. On parle d&#8217;investissements de <a href="https://venturebeat.com/ai/nvidia-gpu-shortage-is-top-gossip-of-silicon-valley/">milliards de dollars en matériel informatique</a>, si importants qu&#8217;ils déstabiliseraient le marché mondial.</p>



<p>Même les solutions open source sont loin d&#8217;être légères, en dépit des grandes <a href="https://github.com/ggerganov/llama.cpp">initiatives d&#8217;optimisation</a>. On peut en tout cas supposer que le déploiement local n&#8217;est possible que sur du matériel récent et puissant. Actuellement, on ne peut pas s&#8217;attendre à ce qu&#8217;une installation locale sur un ordinateur portable de bureau moyen offre une expérience fluide à l&#8217;utilisateur.</p>



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



<p>Internet regorge de contes de fées sur le <a href="https://medium.com/ingeniouslysimple/the-origins-of-the-10x-developer-2e0177ecef60">développeur 10x</a>, et les gourous de l&#8217;IA générative aimeraient vous faire croire que cette technologie peut élever n&#8217;importe quel programmeur à ce niveau. La réalité est plus nuancée. Les développeurs ne passent pas 100&nbsp;% de leur temps à écrire du code, pas plus que les médecins ne passent 100&nbsp;% de leur temps à rédiger des ordonnances. La majorité des développeurs <a href="https://www.software.com/reports/code-time-report">passe moins d&#8217;une heure par jour à coder</a>. Le reste de leur temps est consacré à l&#8217;analyse, à la lecture, à l&#8217;apprentissage, aux tâches de maintenance, à la communication, etc. Jusqu&#8217;à présent, cette réflexion et cette consultation avec les collègues ne sont pas comprimées par l&#8217;emploi de LLM.</p>



<p>Il est difficile de trouver des chiffres précis sur la productivité parce qu&#8217;elle est difficile à définir et donc à mesurer. Une première estimation utile provient de Google même, qui a examiné le temps d&#8217;itération (de la connaissance du problème à la solution). Avec une première version de son propre assistant de complétion de code par l&#8217;IA, <a href="https://ai.googleblog.com/2022/07/ml-enhanced-code-completion-improves.html">l&#8217;entreprise a pu constater un gain de temps de 6&nbsp;%</a>. Github affirme que <a href="https://github.blog/2022-09-07-research-quantifying-github-copilots-impact-on-developer-productivity-and-happiness/">le codage pur peut être environ 55&nbsp;% plus rapide</a> avec son CoPilot &#8211; bien qu&#8217;il précise dans le même temps que l&#8217;intervalle de confiance à 95&nbsp;% de sa mesure est de [21&nbsp;%-89&nbsp;%]. En outre, l&#8217;adoption d&#8217;un outil n&#8217;apporte aucune valeur ajoutée si elle n&#8217;est pas accompagnée d&#8217;un parcours pour apprendre à l&#8217;utiliser de manière optimale (tout comme aujourd&#8217;hui encore, de nombreux employés de bureau perdent du temps avec Office en raison d&#8217;une connaissance ou d&#8217;une expérience insuffisante de tous les types de références, de formules et de raccourcis).</p>



<p>Le code généré fournit une solution initiale rapide, mais cette solution doit encore être comprise par le programmeur. Un score &#8220;pass@1&#8221; de 50&nbsp;% signifie que la moitié des bouts de code générés nécessitent encore des ajustements manuels avant de passer les tests unitaires &#8211; sans parler de l&#8217;optimalité ou de la sécurité. Le code généré peut être complexe et utiliser des constructions qui dépassent le niveau de connaissance du programmeur. Le code généré est donc plus difficile à maintenir et à corriger que le code écrit manuellement. Un code généré qui n&#8217;a pas été correctement examiné et testé ajoute une <a href="https://www.techtarget.com/whatis/definition/technical-debt">dette technique</a> considérable à un projet.</p>



<p>L&#8217;utilisation de plugins qui vont jusqu&#8217;à générer des blocs entiers de code et de documentation en un claquement de doigts (ou un peu plus lentement) n&#8217;est une bonne idée que si plusieurs autres aspects du processus d&#8217;ingénierie logicielle sont en ordre&nbsp;: des normes élevées doivent être maintenues dans tous les domaines en termes de stratégie de test, de code reviews, de documentation de code et de savoir-faire des développeurs.</p>



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



<p>Les entreprises et les gouvernements ont rarement le luxe d&#8217;utiliser n&#8217;importe quel modèle de langue. Il existe non seulement des barrières contractuelles, mais aussi des questions de confidentialité, en particulier lors de l&#8217;utilisation du cloud. Après tout, on n&#8217;obtient une bonne suggestion de modèle de langue qu&#8217;en introduisant suffisamment d&#8217;informations au préalable. Ne pas tout mettre en place en interne implique inévitablement de donner à un tiers l&#8217;accès à vos données.</p>



<p>Le degré d&#8217;ouverture et de licence peut varier considérablement &#8211; à un extrême, tout est en &#8220;boîte noire&#8221; et uniquement accessible via le cloud/API (c&#8217;est là que vous trouverez OpenAI, Anthropic, Cohere et la plupart des autres start-ups établies). Celles-ci promettent dans les <a href="https://openai.com/blog/introducing-chatgpt-enterprise">versions Enterprise</a> parfois plus de garanties &#8211; mais vous n&#8217;avez pas d&#8217;autre choix que de les croire sur parole. À l&#8217;autre extrême, tout est en &#8220;open access&#8221; (libre accès) et sous licence permissive. Entre les deux, une entreprise peut également construire un modèle de langue en libre accès sur un dataset fermé. Au moins un de ces datasets a <a href="https://www.theatlantic.com/technology/archive/2023/08/books3-ai-meta-llama-pirated-books/675063/">depuis été divulgué</a> comme contenant des <a href="https://github.com/psmedia/Books3Info">ebooks illégalement copiés et protégés par le droit d&#8217;auteur</a>, ce qui constituera sans aucun doute un argument de poids dans le <a href="https://storage.courtlistener.com/recap/gov.uscourts.cand.415175/gov.uscourts.cand.415175.1.0_1.pdf">recours collectif intenté contre Meta</a> sur ce sujet. Les ensembles de données des Code LLM <a href="https://arxiv.org/abs/2203.13474">Salesforce CodeGen</a> et <a href="https://codegeex.cn/">Tsinghua CodeGeeX</a> ne sont pas non plus publics.</p>



<p>Transparence, licences, options de déploiement, prix, taille et scalabilité&#8230; l&#8217;importance relative de toutes ces caractéristiques dictera les outils que vous pourrez utiliser. Ceux qui souhaitent une transparence maximale seront souvent limités aux <a href="https://github.com/eugeneyan/open-llms">LLM en Open Access</a>. Certaines licences ouvertes limitent en outre l&#8217;utilisation à des fins non commerciales. La nécessité d&#8217;accéder à des données de formation ou la facilité d&#8217;héberger soi-même une instance sur site <a href="https://blog.pragmaticengineer.com/github-copilot-alternatives/">limitent davantage les choix</a>.</p>



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



<p>Les outils basés sur le dialogue (chatGPT et autres) peuvent vous être utiles en tant que développeur pour, entre autres, les tâches suivantes&nbsp;:</p>



<ul class="wp-block-list">
<li>Initialiser un projet/fichier/classe/configuration&nbsp;: créer une première version de quelque chose</li>



<li>Correction de bugs et modification sous forme de questions-réponses</li>



<li>Morceaux de code relativement indépendants</li>
</ul>



<p>Les outils qui complètent le code ou remplissent le code manquant (type Github Co-Pilot) sont utiles, entre autres, pour&nbsp;:</p>



<ul class="wp-block-list">
<li>Compléter du code à partir d&#8217;exemples déjà réalisés</li>



<li>Documenter le code</li>



<li>Apporter des modifications au milieu d&#8217;un fichier plus volumineux</li>
</ul>



<p>Pour un développeur, l&#8217;environnement de développement optimal est quelque chose de tout à fait personnel et chacun aura sa propre préférence. À notre avis, ces deux façons d&#8217;obtenir des suggestions de code sont quelque peu complémentaires, et une combinaison intelligente des deux peut permettre d&#8217;obtenir les meilleurs gains de productivité. Dans le même temps, nous tenons à dire qu&#8217;une gestion de projet saine, avec une attention portée à la qualité du code, aux tests, aux révisions, à la documentation, etc. est indispensable.</p>



<p>Le monde de l&#8217;IA est en pleine effervescence. De nouveaux modèles d&#8217;IA pouvant servir de base aux plugins IDE sont ajoutés avec une grande régularité. Pour les industries où la confidentialité du code est importante, les variantes open source sont très intéressantes. Même si les benchmarks montrent qu&#8217;ils sont encore moins performants aujourd&#8217;hui que les dernières initiatives commerciales basées sur le cloud, nous pouvons nous attendre à ce que de meilleures versions apparaissent à l&#8217;avenir. De nombreux efforts sont déjà déployés pour créer des modèles pouvant fonctionner sur du matériel grand public (certes haut de gamme).</p>



<h2 class="wp-block-heading">P.S.</h2>



<p>Quelques heures après la publication de cet article, HuggingFace annonce la venue de <a href="https://huggingface.co/blog/safecoder">SafeCoder</a>&nbsp;: une solution d&#8217;entreprise pour les assistants de codage basés sur LLM qui peut être déployée sur site. Huggingface fournit le tout dans des conteneurs qui peuvent être installés dans un data center propre et fournir des endpoints privés, ainsi que des plugins compatibles avec les principaux IDE. D&#8217;autres frameworks de déploiement général existent depuis un certain temps, notamment <a href="https://www.seldon.io/">Seldon</a>, <a href="https://www.bentoml.com/">BentoML</a> et <a href="https://github.com/kserve/kserve">KServe</a>, qui peuvent également héberger des LLM, <a href="https://bellard.org/ts_server/">TextSynth Server</a> et <a href="https://gpt4all.io/index.html">GPT4All</a> peuvent fonctionner comme des endpoints d&#8217;API. Cependant, vous avez toujours besoin de plugins pour les utiliser dans l&#8217;IDE lui-même, et pour effectuer les traitements préalables et postérieurs nécessaires &#8211; et s&#8217;ils ne sont pas fournis, vous devez en créer un vous-même ou modifier un plugin existant.</p>



<h2 class="wp-block-heading">P.P.S.</h2>



<p>Ces derniers mots à peine écrits, Meta a lancé <a href="https://about.fb.com/news/2023/08/code-llama-ai-for-coding/">CodeLLama</a>, une variante de <a href="https://ai.meta.com/llama/">LLaMa 2</a> spécifiquement entraînée pour le code. Les <a href="https://twitter.com/abacaj/status/1694889597723873562">médias sociaux suggèrent</a> qu&#8217;il est possible de faire tourner la version originale avec 34 milliards de paramètres sur un ordinateur équipé de 4 GPU RTX3090 avec 24 GB de VRAM chacun, générant environ 20 tokens par seconde. Il est sans doute plus facile d&#8217;essayer la <a href="https://huggingface.co/chat">version de chat en ligne</a>.&nbsp;<a href="https://github.com/ggerganov/llama.cpp">Les versions quantisées</a> suivront sans doute très prochainement, et nous attendons les premiers benchmarks sur les différents leaderboards.</p>



<p>______________________</p>



<p><em>Cette contribution a été soumise par Joachim Ganseman, consultant IT chez Smals Research. Elle a été rédigée en son nom propre et ne prend pas position au nom de Smals.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>LLMs voor code: the Good, the Bad and the Ugly</title>
		<link>https://www.smalsresearch.be/llms-voor-code/</link>
		
		<dc:creator><![CDATA[Joachim Ganseman]]></dc:creator>
		<pubDate>Tue, 22 Aug 2023 09:43:16 +0000</pubDate>
				<category><![CDATA[[NL]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[chatbot]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[computational creativity]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[Natural Language Processing]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[software engineering]]></category>
		<category><![CDATA[source code]]></category>
		<guid isPermaLink="false">/?p=18875</guid>

					<description><![CDATA[Wat is de stand van zaken wat betreft het genereren van code, en waar moeten we nog rekening mee houden? AI-assistenten of -plugins voor IDEs zijn een zegen voor wie ze goed kan aanwenden, maar komen, zoals alle AI-systemen, ook met de nodige caveats.]]></description>
										<content:encoded><![CDATA[
<p><em>Cet article est aussi disponible <a href="/llms-pour-code/">en français</a>.</em></p>



<p>In<a href="/de-ai-augmented-developer/"> een vorig artikel</a> bespraken we op algemene wijze het potentieel van generatieve AI in de <a href="https://www.servicenow.com/products/devops/what-is-sdlc.html">software development lifecycle</a>. Laat ons nu eens kijken vanuit het standpunt van de developer: wat is de stand van zaken wat betreft het genereren van code, en waar moeten we nog rekening mee houden? Lang verhaal kort: AI-assistenten of -plugins voor IDEs zijn een zegen voor wie ze goed kan aanwenden, maar komen, zoals alle AI-systemen, ook met de nodige <em>caveats.</em></p>



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



<p>De <a href="https://theresanaiforthat.com/">hype</a> qua generatieve AI wordt onder andere gestuwd door <a href="https://en.wikipedia.org/wiki/Large_language_model">krachtige taalmodellen</a> &#8211; Large Language Models of LLMs. Zeker sinds GPT-3 uitkwam in 2020, slagen die erin om normaal uitziende teksten te schrijven van enige lengte. Van daar is het maar een korte sprong naar programmeertalen &#8211; die hebben immers ook een syntax en semantiek.</p>



<p>In de praktijk bestaan er talloze varianten van taalmodellen, die elk hun sterktes en zwaktes hebben, al naargelang de keuzes die de makers hebben gemaakt bij het trainen ervan, en al naargelang de trainingsdata die eraan ten grondslag liggen. Probeer bijvoorbeeld zelf enkele van de bestaande open source modellen uit op je eigen computer via de tool <a href="https://gpt4all.io/index.html">GPT4All</a> (zie ook <a href="/publications/document/?docid=270">onze korte review</a> van deze tool).</p>



<p>Computercode bestaat uit een collectie van tekstbestanden. Niets verhindert dat een taalmodel, in plaats van woorden, de verschillende <a href="https://www.techtarget.com/searchapparchitecture/definition/parser">tokens ( = grammaticale eenheden)</a> waaruit code bestaat, probeert te voorspellen. In tegenstelling tot gewone tekst is er bij code echter veel minder ruimte voor fouten: de kleinste spelfout of variatie kan een stuk code ongeldig maken of iets helemaal anders laten uitvoeren. </p>



<p>Toch kunnen de allergrootste taalmodellen, zoals GPT-3.5 en later, vandaag uit eigen beweging vrij correcte stukken computercode produceren in een antwoord op een vraag. Deze functionaliteit is het gevolg van de massieve hoeveelheid tekst waarop ze getraind zijn, waaronder talloze tutorials, blogartikels, vragen en antwoorden uit populaire developerfora zoals <a href="https://stackoverflow.com/">StackOverflow</a>, en gedocumenteerde code uit publieke code repositories zoals <a href="https://github.com/">Github</a>.</p>



<h2 class="wp-block-heading">Babbelende badeentjes</h2>



<p>Al <a href="https://en.wikipedia.org/wiki/Socratic_dialogue">sinds Socrates</a> is de dialoog een beproefde manier om tot nieuwe inzichten te komen. Niet voor niets is <a href="https://blog.codinghorror.com/rubber-duck-problem-solving/">rubber ducking</a> een methode voor debugging die ter sprake komt in elke cursus software engineering. Er bestaan ondertussen verschillende plugins die een AI-powered chat-interface in de IDE zelf beschikbaar stellen (bvb <a href="https://github.com/timkmecl/chatgpt-vscode">deze voor VS Code</a> , vele andere kunnen gevonden worden via de <a href="https://marketplace.visualstudio.com/search?term=gpt&amp;target=VSCode">marketplaces voor VS Code</a> of <a href="https://plugins.jetbrains.com/search?products=idea_ce&amp;search=gpt">IntelliJ IDEA</a>). Als die gebruikmaken van een externe cloud-dienst moet je daarbij enkel nog je eigen API-key ingeven.</p>



<p>Een dialogerende setting met een vraag-antwoord dynamiek kan goed aangewend worden voor het genereren van relatief op zichzelf staande stukken code, zonder te veel externe afhankelijkheden. In het algemeen kan je stellen dat je, voor het beste resultaat, alle noodzakelijke randvoorwaarden en aannames gemakkelijk in de dialoog zelf moet kunnen vermelden, zodat het binnen het context-venster van het taalmodel past. De use cases omvatten onder andere:</p>



<ul class="wp-block-list">
<li><em>From scratch</em> genereren van een eerste versie van code of een configuratiebestand</li>



<li>Genereren van relatief korte functies of procedures aan de hand van een beschrijving</li>



<li>Genereren van op zichzelf staande <em>code snippets</em>: SQL queries, reguliere expressies, &#8230;</li>



<li>Vragen om een aanpassing aan een stuk code of een configuratiebestand</li>



<li>Debugging: fouten zoeken in niet-werkende code, vragen stellen over een error</li>



<li>Laten uitleggen wat een stuk code doet</li>
</ul>



<p>De grootste taalmodellen hebben ondertussen contextvensters van duizenden woorden waarin je alle nodige informatie kwijt kan. Een kleiner open-source taalmodel, lokaal geïnstalleerd op minder krachtige hardware, zal ongetwijfeld minder goed presteren. Enkele voorbeelden van conversaties met OpenAI&#8217;s GPT-4 staat hieronder &#8211; hieruit blijkt dat je al heel ver kan geraken met een paar welgemikte vragen (klik voor de volledige resolutie):</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2023/08/2023-08-22_16h05_32.png"><img loading="lazy" decoding="async" width="143" height="1024" data-id="18959" src="/wp-content/uploads/2023/08/2023-08-22_16h05_32-143x1024.png" alt="" class="wp-image-18959" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h05_32-143x1024.png 143w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h05_32-42x300.png 42w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h05_32-286x2048.png 286w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h05_32-scaled.png 358w" sizes="auto, (max-width: 143px) 100vw, 143px" /></a><figcaption class="wp-element-caption">Voorbeeld van een conversatie over code met ChatGPT&#8217;s GPT-4 model: genereren van een configuratie voor een VNC remote server op een shared Ubuntu systeem.</figcaption></figure>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2023/08/2023-08-22_16h17_10.png"><img loading="lazy" decoding="async" width="198" height="1024" data-id="18958" src="/wp-content/uploads/2023/08/2023-08-22_16h17_10-198x1024.png" alt="" class="wp-image-18958" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h17_10-198x1024.png 198w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h17_10-297x1536.png 297w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h17_10-58x300.png 58w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_16h17_10-768x3977.png 768w" sizes="auto, (max-width: 198px) 100vw, 198px" /></a><figcaption class="wp-element-caption">Voorbeeld van een conversatie over code met ChatGPT&#8217;s GPT-4 model: genereren van een SQL query voor een transpositie van een tabel. De uiteindelijk voorgestelde oplossing gebruikt met stored procedures vrij geavanceerde technieken.</figcaption></figure>
</figure>



<h2 class="wp-block-heading">Code completion on steroids</h2>



<p>Tijdens het ontwikkelen werkt een developer aan talloze bestanden in een IDE. Op willekeurige plekken in die bestanden moet er code aangepast, verwijderd of geschreven worden. Het bewerken van bestaande code op deze manier heeft weinig te maken met dialogeren, eigenlijk willen we hier eerder een geavanceerde auto-complete inzetten. Ook dat kunnen taalmodellen goed, maar de meest geschikte modellen zijn eerder diegene die getraind zijn op &#8220;fill in the middle&#8221; taken &#8211; en die dus rekening kunnen houden met de aanwezige code voor én na de plek die men aan het bewerken is. </p>



<p>Na het uitbrengen van GPT-3, werkte OpenAI samen met Microsoft (dat Github bezit) aan een gespecialiseerd taalmodel dat voor exact deze use case werd getraind. Deze variant werd <a href="https://openai.com/blog/openai-codex">Codex </a>genoemd, en de eerste tool die ervan gebruikmaakte was <a href="https://github.com/features/copilot">Github CoPilot</a>. Ondertussen zijn we al enkele versies verder, maar de plugins voor <a href="https://marketplace.visualstudio.com/items?itemName=GitHub.copilot">VSCode</a> en <a href="https://plugins.jetbrains.com/plugin/17718-github-copilot">IntelliJ</a> werken nog op dezelfde manier: via een sneltoets in de editor kan men via CoPilot verschillende suggesties opvragen, gegenereerd door Codex, die zouden kunnen passen op de plek van de cursor. </p>



<p>Voor zover onze ervaring vandaag reikt, is de context die daarbij in rekening wordt genomen vandaag meestal beperkt tot (stukken van) de inhoud van het bewerkte bestand. Daarbij wordt uiteraard code <a href="https://resources.github.com/copilot-trust-center/">geüploaded naar het taalmodel</a> &#8211; let dus zeker op richtlijnen qua confidentialiteit bij gebruik van een externe dienst. Vooralsnog lijken we betere resultaten te krijgen bij programmeerprojecten die bestaan uit weinig grote bestanden, zoals webpagina&#8217;s met inline JavaScript, of Jupyter Notebooks in Python, waarbij vaak sprake is van 1 groot bestand dat doorlopen wordt waarin zowel de documentatie, de code als de output staat. In projecten met vele kleine bestandjes daarentegen, lijkt het moeilijker om goede suggesties te genereren, en is het belangrijker dat er extra documentatie aanwezig is in het geëditeerde bestand zodat er voldoende contextuele informatie is die het taalmodel kan aangrijpen.</p>



<figure class="wp-block-image size-large"><a href="/wp-content/uploads/2023/08/copilot-in-vscode-example.png"><img loading="lazy" decoding="async" width="1024" height="604" src="/wp-content/uploads/2023/08/copilot-in-vscode-example-1024x604.png" alt="" class="wp-image-18964" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/08/copilot-in-vscode-example-1024x604.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2023/08/copilot-in-vscode-example-300x177.png 300w, https://www.smalsresearch.be/wp-content/uploads/2023/08/copilot-in-vscode-example-768x453.png 768w, https://www.smalsresearch.be/wp-content/uploads/2023/08/copilot-in-vscode-example.png 1276w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Github CoPilot in VSCode. Een stramien volgend dat al eerder in hetzelfde bestand voorkomt, moet een Rounding()-object gecreëerd worden voor elk element in een Python dictionary. Itereren lukt goed, maar CoPilot heeft duidelijk geen weet van de juiste functieheader, die niet in ditzelfde bestand is gedefinieerd en ook niet in de &#8216;algemene kennis&#8217; van CoPilot&#8217;s Codex-model voorkomt: de suggesties stellen parameters voor die niet bestaan. Onmiddellijk na het accepteren van deze foutieve oplossing, klaagt de ingebouwde statische code checker over de missende parameter. </figcaption></figure>



<p>Een van de interessantere alternatieven voor het commerciële Github CoPilot is <a href="https://huggingface.co/blog/starcoder">StarCoder</a>, een open source model van het <a href="https://www.bigcode-project.org/">BigCode</a> initiatief van HuggingFace en ServiceNow. De performantie is weliswaar  <a href="https://llm-leaderboard.streamlit.app/">minder dan CoPilot</a>, maar zij maken op vele andere vlakken, die mogelijk dealbreakers zijn in commerciële of publieke context, het verschil:</p>



<ul class="wp-block-list">
<li>Getraind op een open dataset: <a href="https://huggingface.co/datasets/bigcode/the-stack">The Stack</a>. Deze is weliswaar via scraping verzameld, maar bevat alleen code met <a href="https://en.wikipedia.org/wiki/Permissive_software_license">permissieve softwarelicenties</a>, en developers kunnen desgewenst <a href="https://huggingface.co/spaces/bigcode/in-the-stack">alsnog hun code eruit laten verwijderen</a>. </li>



<li>Bevat een <a href="https://huggingface.co/spaces/bigcode/search">plagiaat-check</a> tool, waarmee je kan controleren of de gegenereerde suggesties niet verbatim uit de (mogelijk copyrighted) trainingsdata zijn overgenomen.</li>



<li>Voorzien van <a href="https://huggingface.co/bigcode/starpii">filter van gevoelige informatie</a>, die emailadressen, API keys en IP adressen detecteert (niet 100% accuraat).</li>



<li>Voorzien van <a href="https://github.com/bigcode-project/starcoder/tree/main">instructies om het lokaal te installeren</a>, evenals een <a href="https://marketplace.visualstudio.com/items?itemName=HuggingFace.huggingface-vscode">VSCode plugin</a>. Een <a href="https://plugins.jetbrains.com/plugin/22090-starcoder">IntelliJ plugin</a> werd ondertussen ook ontwikkeld door een derde partij.</li>



<li>Het standaardmodel is 15 miljard parameters groot en vergt minstens 60GB RAM of evenveel GPU memory (afhankelijk van of een GPU benut wordt of niet) om te kunnen gebruiken. Ondertussen bestaan ook <a href="https://huggingface.co/spaces/bigcode/multilingual-code-evals">kleinere modellen</a> met 7, 3 of 1 miljard parameters, evenals <a href="https://github.com/bigcode-project/starcoder.cpp">&#8220;quantized&#8221; versies</a> die gebruikmaken van 4bit datatypes zonder veel accuraatheidsverlies.</li>
</ul>



<p>Deze zomer zagen nog enkele andere systemen het licht die goed scoren op vele benchmarks: <a href="https://github.com/nlpxucan/WizardLM">WizardLM</a> en de specifieke variant ervan <a href="https://arxiv.org/abs/2306.08568">WizardCoder</a>, dat ondertussen wordt beschouwd als de open source state-of-the-art, en <a href="https://arxiv.org/abs/2207.11280">PanGu-Coder</a>, waarmee ook Huawei zich heeft gelanceerd in de wereld van AI-assistants voor code. </p>



<h2 class="wp-block-heading">Achter de schermen</h2>



<p>De <a href="https://arxiv.org/abs/2305.06161">StarCoder paper</a> geeft een goed zicht op de werking van een taalmodel voor code. Het is zeker niet zo dat je je eigen codebase kan &#8220;inpluggen&#8221; om suggesties te krijgen die daarop zijn toegespitst. Als je echt zou willen finetunen (en die enorme inspanning doe je in principe <a href="https://twitter.com/rachel_l_woods/status/1692577254914638340">alleen maar als je er niet raakt</a> met slimme <a href="https://en.wikipedia.org/wiki/Prompt_engineering">aanpassingen aan de prompt</a>), komt er heel wat bij kijken, van preprocessing van de trainingsdata tot postprocessing van de rauwe output van het taalmodel. Leg de verwachtingen van finetuning ook niet te hoog: StarCoder deed het voor Python, maar haalde <a href="https://huggingface.co/blog/starcoder">hooguit enkele procentpunten verbetering</a> in vergelijking met het algemene model dat met alle programmeertalen overweg kon. Finetunen is moeilijk en er is geen garantie op succes; er bestaat zelfs een risico op <a href="https://research.nccgroup.com/2023/05/22/exploring-overfitting-risks-in-large-language-models/">overfitting</a> wat tot slechtere resultaten kan leiden.</p>



<p>De belangrijkste stap daarbij is waarschijnlijk het verzamelen en schoonmaken van data. <a href="https://huggingface.co/datasets/bigcode/starcoderdata">Die data bestaat uit code</a>, maar niet alle code komt in aanmerking: je moet de code ook mogen gebruiken (licenties), en je hebt ze liefst zo correct mogelijk en geschreven in de programmeertaal die je wenst te ondersteunen. Code wordt ook verzameld uit <a href="https://en.wikipedia.org/wiki/Bug_tracking_system">issue trackers</a> en <a href="https://en.wikipedia.org/wiki/Version_control">commitgeschiedenis</a>. Daarnaast kan je nog extra filteren om (bijna-)duplicaten te verwijderen, en wil je misschien hier en daar gewichten toekennen om de balans te bewaren: wat minder gewicht voor boilerplate code, en/of wat meer voor erg populaire repositories die waarschijnlijk van hogere kwaliteit zijn. Broncode kan gevoelige informatie bevatten die eerst <a href="https://en.wikipedia.org/wiki/Data_anonymization">geanonymiseerd</a> of verwijderd moet worden, om te voorkomen dat die lekt of wordt gesuggereerd (IP adressen, paswoorden, identifiers, emailadressen, contactgegevens, &#8230;). Dit alles natuurlijk liefst zo automatisch mogelijk.</p>



<p class="has-text-align-left">Broncode bestaat niet alleen uit code maar ook uit beschrijvingen, commentaren en andere informatie. In een formatteringsstap wordt de code daarom nog verrijkt, door het toevoegen van metadata en <a href="https://huggingface.co/docs/transformers/main/internal/tokenization_utils#transformers.SpecialTokensMixin">bijkomende tokens</a> die bepaalde impliciete structuren expliciet maken. Dit kan implicaties hebben: als al deze preprocessing op de hele trainingsdataset is gebeurd, dan zal het resulterende model pas goed werken op nieuwe data als die dezelfde preprocessing heeft ondergaan. Het is dus mogelijk dat editorplugins die willen gebruikmaken van zo&#8217;n model, om een goed resultaat te bekomen, eerst <a href="https://github.com/huggingface/huggingface-vscode/blob/a4a413723e9687bd2a7195d0e859f74467287571/package.json#L204">gelijkaardige preprocessing</a> moeten uitvoeren op de code die ze naar het taalmodel willen sturen.</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2023/08/2023-08-22_10h52_37.png"><img loading="lazy" decoding="async" width="325" height="353" src="/wp-content/uploads/2023/08/2023-08-22_10h52_37.png" alt="" class="wp-image-18951" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_10h52_37.png 325w, https://www.smalsresearch.be/wp-content/uploads/2023/08/2023-08-22_10h52_37-276x300.png 276w" sizes="auto, (max-width: 325px) 100vw, 325px" /></a><figcaption class="wp-element-caption">Opdat het model beter onderscheid kan maken tussen de verschillende onderdelen van broncode, wordt trainingsdata verrijkt met metadata en zgn. &#8216;sentinel tokens&#8217;, zoals deze lijst afkomstig uit de <a href="https://arxiv.org/abs/2305.06161">StarCoder paper</a>.</figcaption></figure>



<h2 class="wp-block-heading">Correctheid en andere benchmarks</h2>



<p>Typisch voor LLMs, kan er geen sluitende garantie worden gegeven op de correctheid of volledigheid van wat zo&#8217;n plugin je voorschotelt, zowel syntactisch als semantisch. Die correctheid is uiteraard van belang: een stuk gegenereerde code moet niet alleen syntactisch correct zijn en foutloos compileren, maar ook semantisch betekenisvol zijn en goed runnen. De &#8220;pass@x&#8221; metriek is daarbij uitgegroeid tot belangrijke graadmeter. Ze drukt uit als een percentage, of een taalmodel voor een bepaalde opdracht na X pogingen de bijhorende testen succesvol kan passeren. &#8220;pass@1&#8221; is het percentage dat het taalmodel van de eerste keer het juiste antwoord heeft kunnen genereren, &#8220;pass@10&#8221; is het percentage waarbij minstens 1 van 10 pogingen correct was.</p>



<p>Er is een algemene nood in de wereld van generatieve AI om nieuwe modellen, die ondertussen bijna dagelijks verschijnen, te kunnen vergelijken met de state-of-the-art. Aan benchmarks is er dus geen gebrek, en er verschijnen er geregeld ook nieuwe en grotere. Handige samenvattingen zijn de &#8220;leaderboards&#8221;, die real-time tonen welke modellen de huidige state-of-the-art vertegenwoordigen volgens een waaier aan benchmarks. Het podium kan wekelijks veranderen. Enkele interessante algemene leaderboards zijn:</p>



<ul class="wp-block-list">
<li><a href="https://paperswithcode.com/sota">Papers with Code</a>: state-of-the-art in verschillende AI taken, voorzien van begeleidende papers</li>



<li><a href="https://crfm.stanford.edu/helm/latest">Stanford HELM</a>: benchmarkt een breed scala aan taken met focus op &#8220;human reasoning&#8221;</li>



<li><a href="https://chat.lmsys.org/?leaderboard">LMsys.org FastChat</a>: focus op chatbot-vaardigheden</li>



<li><a href="https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard">HuggingFace OpenLLM leaderboard</a></li>



<li><a href="https://llm-leaderboard.streamlit.app/">LLM-Leaderboard</a></li>
</ul>



<p>Specifiek voor code zijn er benchmarks die min of meer werken zoals een programmeerwedstrijd. Het idee is om een set opdrachten te geven aan het taalmodel, de resultaten automatisch te evalueren, en de &#8220;pass@1&#8221; en zo mogelijk enkele andere metrieken te meten. Vaak neemt dat een &#8220;fill in the function&#8221;-vorm aan: gegeven een beschrijving van input en output en een functieheader, moet de inhoud van de functie gegenereerd worden. Een nadeel is dat dit soort problemen soms <a href="https://www.computer.org/csdl/journal/ts/2023/07/10103177/1MpWUtj7Rwk">weinig representatief</a> is voor dat waarmee de doorsnee developer wordt geconfronteerd. Interessante initiatieven zijn onder andere:</p>



<ul class="wp-block-list">
<li>HuggingFace <a href="https://huggingface.co/spaces/bigcode/bigcode-models-leaderboard">Big Code Models leaderboard</a> (enkel open LLMs)</li>



<li>Microsoft <a href="https://github.com/microsoft/CodeXGLUE">CodeXGLUE</a>: evaluatie van verschillende subtaken volgens methodes bekend uit Natural Language Processing. Hun <a href="https://microsoft.github.io/CodeXGLUE/">leaderboard</a> lijkt af te hangen van vrijwillige contributie en enigszins onvolledig.</li>



<li>Papers with Code heeft aparte secties voor <a href="https://paperswithcode.com/task/code-generation">genereren van code</a> , <a href="https://paperswithcode.com/task/code-documentation-generation">genereren van documentatie</a>, <a href="https://paperswithcode.com/task/program-synthesis">synthese van hele programma&#8217;s</a> en <a href="https://paperswithcode.com/task/program-repair">bugfixing</a></li>



<li>De <a href="https://paperswithcode.com/dataset/humaneval">HumanEval dataset</a> en <a href="https://paperswithcode.com/dataset/mbpp">MBPP dataset</a>: typische programmeerproblemen (Python)</li>



<li>De <a href="https://paperswithcode.com/dataset/ds-1000">DS-1000 dataset</a>: een set van concrete data science / data processing problemen </li>



<li><a href="https://paperswithcode.com/dataset/humaneval-x">HumanEval-X</a> of <a href="https://github.com/nuprl/MultiPL-E">MultiPL-E</a>: multi-language versies van HumanEval, meet performantie in meerdere programmeertalen</li>
</ul>



<p>Dat een gegenereerd stuk code de testen overleeft betekent natuurlijk nog niet dat het ook veilige code is of &#8220;best practices&#8221; volgt. Er zijn ondertussen voorbeelden genoeg bekend van gegenereerde code die vatbaar blijkt te zijn voor buffer overflows, SQL injection, en andere klassieke risico&#8217;s. De <a href="https://huggingface.co/datasets/moyix/asleep_keyboard">&#8220;Asleep at the Keyboard&#8221;</a> security benchmark bestaat uit 89 code generation scenario&#8217;s gebaseerd op de <a href="https://cwe.mitre.org/top25/">MITRE top-25 vulnerability</a> lijst. Uit de <a href="https://arxiv.org/abs/2305.06161">Starcoder paper</a> blijkt dat zelfs de beste modellen in 40% van deze scenario&#8217;s toch nog onveilige code genereren. Ook lijkt er nauwelijks verschil te merken tussen de beste modellen en de rest &#8211; een beter model kiezen lijkt wel te zorgen voor syntactische correctere resultaten, maar vooralsnog niet voor veiliger code. Mogelijk moet daarom eens gekeken worden naar de trainingsdata zelf, waar onveilige code nog beter uitgefilterd zou moeten worden. In ieder geval moeten we op dit moment adviseren: het gebruik van gegenereerde code in een project moet absoluut gepaard gaan met een robuust beleid inzake testing en acceptatie.</p>



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



<p>Specifiek wat betreft computationele vereisten, zijn het <a href="https://huggingface.co/spaces/optimum/llm-perf-leaderboard">Huggingface OpenLLM-perf</a> leaderboard en de benchmarks op de website van <a href="https://bellard.org/ts_server/">TextSynth Server</a> interessante bronnen. Die laatste toont enkele cijfers over performantie, die handig zijn voor wie met het idee speelt om het zelf te gaan hosten. Wie het zonder GPU doet, kan met het LLaMa2 model van 13 miljard parameters rekenen op een snelheid van 12 tokens per seconde, gegeven een relatief high-end <a href="https://tweakers.net/pricewatch/1672608/amd-epyc-7313-tray.html">EPYC 7313</a> serverprocessor. Een token in computercode is soms maar 1 karakter, dus aan dat tempo moet je soms een tiental seconden wachten op een code completion suggestie. De recentste RTX-4090 grafische kaart kan het 7x sneller, maar nog steeds niet zo snel dat je het in milliseconden zou uitdrukken. </p>



<p>De geheugenvereisten zijn evenredig met het aantal parameters van een model, en de generatiesnelheid omgekeerd evenredig. Als een grove benadering mag je aannemen dat een model van 13 miljard parameters, ook 13 miljard berekeningen moet maken voor elk output token, zelfs al is het maar 1 karakter lang. Daarnaast vereist het, als elke parameter een 32-bit getal is, minstens 52GB opslagruimte en evenveel (V)RAM-geheugen. Een &#8220;<a href="https://huggingface.co/docs/transformers/main_classes/quantization">quantization</a>&#8220;, die de parameters afrondt naar 8-bit of zelfs 4-bit, kan die geheugenvereiste evenredig doen dalen. </p>



<p><a href="https://gpt4all.io/index.html">GPT4All</a> laat toe het zelf eens te proberen op je eigen hardware. Dit geeft een idee van de enorme rekenkracht die OpenAI , Microsoft Azure, of Amazon AWS inzetten om hun modellen, die veelal nog groter zijn dan de beschikbare Open Access LLMs, zo snel te kunnen doen draaien als zij dat aanbieden. Er wordt gesproken van investeringen van <a href="https://venturebeat.com/ai/nvidia-gpu-shortage-is-top-gossip-of-silicon-valley/">miljarden dollars in hardware</a>, zodanig groot dat ze de wereldwijde markt destabiliseren.</p>



<p>Zelfs open source oplossingen zijn allesbehalve lightweight te noemen, ondanks verregaande <a href="https://github.com/ggerganov/llama.cpp">initiatieven tot optimalisatie</a>. Je mag er alleszins van uitgaan dat het lokaal deployen alleen maar haalbaar is op recente en krachtige hardware. Een vlotte user experience kan je momenteel nog niet verwachten van een lokale installatie op de doorsnee kantoorlaptop.</p>



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



<p>Het internet staat vol sprookjes over de <a href="https://medium.com/ingeniouslysimple/the-origins-of-the-10x-developer-2e0177ecef60">10x developer</a>, en goeroes van generatieve AI zouden u graag doen geloven dat deze technologie elke programmeur tot dat niveau kan verheffen. De realiteit is hardnekkiger. Developers spenderen om te beginnen geen 100% van hun tijd aan het schrijven van code, net zomin als dokters 100% van hun tijd voorschriften schrijven. Het merendeel van developers <a href="https://www.software.com/reports/code-time-report">spendeert minder dan 1 uur per dag aan het effectief schrijven van code</a>. De rest van de tijd gaat naar analyseren, lezen, leren, onderhoudstaken, communicatie,&#8230; Dat denkwerk en het overleg met de collega&#8217;s wordt vooralsnog niet gecomprimeerd door LLMs in te zetten.</p>



<p>Het is moeilijk om harde cijfers te vinden over productiviteit omdat het <a href="https://queue.acm.org/detail.cfm?id=3454124">moeilijk te definiëren en dus te meten</a> is. Een nuttige eerste schatting komt van Google zelf, die de iteratietijd (van kennisname van het probleem tot oplossing) onder de loep nam. Met een eerste versie van hun eigen AI code completion assistent, <a href="https://ai.googleblog.com/2022/07/ml-enhanced-code-completion-improves.html">konden zij 6% tijdswinst noteren</a>. Github zelf beweert dat het <a href="https://github.blog/2022-09-07-research-quantifying-github-copilots-impact-on-developer-productivity-and-happiness/">pure codeerwerk zo&#8217;n 55% sneller kan</a> met hun CoPilot &#8211; al zeggen ze er in één adem bij dat het 95%-confidence interval van hun meting [21%-89%] is. De adoptie van een tool brengt bovendien geen meerwaarde als ze niet gepaard gaat met een traject om ze optimaal te leren benutten (net zoals vandaag nog vele kantoormedewerkers tijd verliezen met Office door onvoldoende kennis of ervaring met alle types van referenties, formules en snelkoppelingen). </p>



<p>Gegenereerde code biedt wel snel een eerste oplossing, maar die oplossing moet nog steeds begrepen worden door de programmeur. Een &#8220;pass@1&#8221; score van 50%, betekent dat de helft van de gegenereerde code snippets nog manuele aanpassingen behoeft voordat ze de unit tests passeert &#8211; en dan spreken we nog niet over optimaliteit of veiligheid. Gegenereerde code kan complex zijn en gebruikmaken van constructies die boven het kennisniveau van de programmeur liggen. Dat maakt gegenereerde code moeilijker om te onderhouden en te debuggen dan code die manueel geschreven is. Gegenereerde code die onvoldoende werd gereviseerd en getest, voegt aanzienlijke <a href="https://www.techtarget.com/whatis/definition/technical-debt">technical debt</a> toe aan een project.</p>



<p>Het gebruik van plug-ins die zo ver gaan dat ze hele blokken code en documentatie met een vingerknip (of iets trager) kunnen genereren, is slechts een goed idee wanneer verschillende andere aspecten van het software engineering proces op orde zijn: er moeten over de hele lijn hoge standaarden aangehouden worden wat betreft teststrategie, code reviews, documenteren van code en kenniscompetenties van de developers. </p>



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



<p>Bedrijven en overheden hebben zelden de luxe om eender welk taalmodel te benutten. Er zijn niet alleen contractuele drempels, maar ook vragen over confidentialiteit, zeker bij gebruik van de cloud. Een goede suggestie van een taalmodel krijg je immers alleen door eerst voldoende informatie te uploaden. Als je niet alles in-house opzet, impliceert dat onvermijdelijk dat je een derde partij inzage geeft in jouw gegevens. </p>



<p>De mate van openheid en licentiëring kan aanzienlijk verschillen &#8211; in het ene uiterste is alles &#8220;black box&#8221; en enkel via cloud/API toegankelijk (hier vind je OpenAI, Anthropic, Cohere en de meeste andere gevestigde startups). Deze beloven in <a href="https://openai.com/blog/introducing-chatgpt-enterprise">Enterprise versies</a> soms meer garanties &#8211; maar je hebt nog steeds geen andere optie dan ze daarin te geloven op hun woord. In het andere uiterste is alles &#8220;open access&#8221; en permissief gelicentieerd. Daartussenin kan een bedrijf ook een Open Access taalmodel bouwen op een gesloten dataset. Van minstens 1 zo&#8217;n dataset is <a href="https://www.theatlantic.com/technology/archive/2023/08/books3-ai-meta-llama-pirated-books/675063/">ondertussen uitgelekt</a> dat ze illegaal gekopieerde  <a href="https://github.com/psmedia/Books3Info">auteursrechtelijk beschermde ebooks</a> bevat, wat ongetwijfeld een sterk argument wordt in de <a href="https://storage.courtlistener.com/recap/gov.uscourts.cand.415175/gov.uscourts.cand.415175.1.0_1.pdf">class action lawsuit over het thema tegen Meta</a>. De datasets van de code-LLMs <a href="https://arxiv.org/abs/2203.13474">Salesforce CodeGen</a> en <a href="https://codegeex.cn/">Tsinghua CodeGeeX</a> zijn evenmin publiek.</p>



<p>Transparantie, licentiëring, deployment mogelijkheden, prijszetting, grootte en schaalbaarheid,&#8230; het relatief belang van al deze kenmerken zal dicteren welke tools je kan gebruiken. Wie maximale transparantie wil, zal sowieso vaak beperkt zijn tot <a href="https://github.com/eugeneyan/open-llms">Open Access LLMs</a>. Sommige open licenties beperken het gebruik daarnaast tot niet-commerciële doeleinden. Een noodzaak tot inzage in de trainingsdata of gemakkelijke voorzieningen om zelf on-premise een instantie te kunnen hosten, <a href="https://blog.pragmaticengineer.com/github-copilot-alternatives/">beperkt de keuzemogelijkheden nog verder</a>.</p>



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



<p>Dialoog-gebaseerde tools (chatGPT en aanverwanten) kan je als developer nuttig inzetten bij o.a.: </p>



<ul class="wp-block-list">
<li>Het initialiseren van een project/bestand/klasse/configuratie: maak een eerste versie van iets</li>



<li>Het debuggen en aanpassen op vraag-antwoord-wijze</li>



<li>Relatief onafhankelijke snippets van code</li>
</ul>



<p>Tools die code aanvullen of ontbrekende code invullen (type Github Co-Pilot) komen dan weer goed van pas bij o.a.:</p>



<ul class="wp-block-list">
<li>Het vervolledigen van code aan de hand van eerder voorkomende voorbeelden</li>



<li>Het documenteren van code</li>



<li>Het maken van veranderingen midden in een groter bestand</li>
</ul>



<p>De optimale ontwikkelomgeving is voor een developer iets vrij persoonlijks en iedereen zal een eigen voorkeur hebben. In onze ogen zijn deze twee manieren om codesuggesties te krijgen enigszins complementair, en het slim combineren van de twee kan voor de meeste productiviteitswinst zorgen. In één adem willen we daarbij wel zeggen dat een gezond projectmanagement, met aandacht voor codekwaliteit, testing, reviews, documentatie, &#8230; daar wel onontbeerlijk bij hoort.</p>



<p>De AI-wereld is in volle beweging. Er komen met de regelmaat van de klok nieuwe AI-modellen bij die kunnen dienen als back-end voor IDE-plugins. Voor industrieën waar vertrouwelijkheid van code belangrijk is, zijn de open-source varianten erg interessant. Zelfs al tonen benchmarks dat die vandaag nog minder performant zijn dan de laatste commerciële cloud-based initiatieven, kunnen we verwachten dat daar in de toekomst ook betere versies van zullen verschijnen. Er zijn alvast veel inspanningen om modellen te maken die op (weliswaar high-end) consumentenhardware kunnen draaien. </p>



<h2 class="wp-block-heading">P.S.</h2>



<p>Enkele uren na het publiceren van dit artikel, kondigt HuggingFace <a href="https://huggingface.co/blog/safecoder">SafeCoder</a> aan: een enterprise-level oplossing voor LLM-gebaseerde coding assistants die on-premise uitgerold kan worden. Huggingface voorziet alles in containers die in het eigen datacenter geïnstalleerd kunnen worden en private endpoints voorzien, én voorziet compatibele plugins voor de belangrijkste IDEs. Andere algemene deployment frameworks bestaan al langer &#8211; o.a. <a href="https://www.seldon.io/">Seldon</a>, <a href="https://www.bentoml.com/">BentoML</a> en <a href="https://github.com/kserve/kserve">KServe</a> kunnen LLMs hosten, ook <a href="https://bellard.org/ts_server/">TextSynth Server</a> en <a href="https://gpt4all.io/index.html">GPT4All</a> kunnen functioneren als API endpoint. Je hebt echter nog steeds plugins nodig om er gebruik van te kunnen maken in de IDE zelf, en om de nodige pre- en postprocessing te doen &#8211; en als ze niet voorzien worden, moet je er zelf eentje maken of een bestaande plugin aanpassen.</p>



<h2 class="wp-block-heading">P.P.S.</h2>



<p>Deze laatste woorden waren nog niet koud of Meta lanceerde <a href="https://about.fb.com/news/2023/08/code-llama-ai-for-coding/">Code LLama</a> , een <a href="https://ai.meta.com/llama/">LLaMa 2</a> variant specifiek getraind voor code. Op <a href="https://twitter.com/abacaj/status/1694889597723873562">sociale media wordt vermeld</a> dat het mogelijk is de originele versie met 34 miljard parameters te draaien op een computer uitgerust met 4 RTX3090 GPUs met elk 24GB VRAM, waarmee ongeveer 20 tokens/seconde gegenereerd kunnen worden. Gemakkelijker is misschien de <a href="https://huggingface.co/chat">online chat-versie</a> uit te proberen. <a href="https://github.com/ggerganov/llama.cpp">Quantized versies</a> zullen ongetwijfeld erg snel volgen, en we verwachten de eerste benchmarks eerstdaags op de verschillende leaderboards.</p>



<p>______________________</p>



<p><em>Dit is een ingezonden bijdrage van Joachim Ganseman, IT consultant bij Smals Research. &nbsp;Dit artikel werd geschreven in eigen naam en neemt geen standpunt in namens Smals.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>De AI-augmented Developer</title>
		<link>https://www.smalsresearch.be/de-ai-augmented-developer/</link>
		
		<dc:creator><![CDATA[Joachim Ganseman]]></dc:creator>
		<pubDate>Thu, 13 Apr 2023 01:54:16 +0000</pubDate>
				<category><![CDATA[[NL]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[chatbot]]></category>
		<category><![CDATA[computational creativity]]></category>
		<category><![CDATA[methodology]]></category>
		<category><![CDATA[Natural Language Processing]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[software engineering]]></category>
		<guid isPermaLink="false">/?p=18366</guid>

					<description><![CDATA[De indrukwekkende kracht van recente Large Language Models doet velen hopen op een nieuwe productiviteitsboost in de Software Development Lifecycle. Laat ons bij enkele van de aspecten ervan eens bekijken hoe generatieve AI ertoe kan bijdragen.]]></description>
										<content:encoded><![CDATA[
<p>Generatieve AI is dé hype van 2023. <a href="https://theresanaiforthat.com/">Elke dag zien verschillende nieuwe bedrijfjes het daglicht</a> die een graantje proberen mee te pikken. De tekstgenerator <a href="https://en.wikipedia.org/wiki/GPT-3">GPT-3</a> kwam uit in 2020 en verzette de bakens wat betreft het behoud van onderwerp, thematiek en stijl, in aanzienlijke langere teksten. (Dat maakt ze nog niet waarheidsgetrouwer, maar dat is een andere discussie.) Sindsdien is het mogelijk om teksten te genereren over zowat elk onderwerp in zowat elke taal, die niet alleen syntactisch correct zijn, maar ook voldoende rekening houden met de bredere context. Een chatbotinterface daarbovenop, in de vorm van <a href="/chatgpt-een-eerste-indruk/">chatGPT eind 2022</a>, schakelde alles nog <a href="https://www.reuters.com/technology/chatgpt-sets-record-fastest-growing-user-base-analyst-note-2023-02-01/">enkele versnellingen hoger</a>.</p>



<p>Software-ontwikkeling is bij uitstek tekst-intensief. <a href="https://en.wikipedia.org/wiki/Systems_development_life_cycle">Het gaat niet alleen over code schrijven</a> in een bepaalde programmeertaal, maar eveneens over specificaties, documentatie, procesmanagement, testen, deployment, service level agreements, &#8230; Al deze onderdelen houden verband met elkaar en haken op elkaar in. Het feit dat <em>Large Language Models</em> (LLMs), zoals GPT-3 en haar opvolgers, complexere contexten kunnen hanteren, waaronder de verbanden tussen tekst en code, opent perspectieven voor de <a href="https://www.kdnuggets.com/2023/01/chatgpt-python-programming-assistant.html">inzet van (tekstuele) generatieve AI</a> in de software development cyclus. Zeker sinds Github <a href="https://github.com/features/copilot">CoPilot </a>uitbracht, zien we ook hier in sneltempo nieuwe tools opduiken, die een kijkje waard zijn. </p>



<figure class="wp-block-image aligncenter"><img loading="lazy" decoding="async" width="960" height="641" src="/wp-content/uploads/2023/04/image-1.jpeg" alt="" class="wp-image-18465" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/04/image-1.jpeg 960w, https://www.smalsresearch.be/wp-content/uploads/2023/04/image-1-300x200.jpeg 300w, https://www.smalsresearch.be/wp-content/uploads/2023/04/image-1-768x513.jpeg 768w" sizes="auto, (max-width: 960px) 100vw, 960px" /><figcaption class="wp-element-caption"><em>&#8220;<a rel="noreferrer noopener" href="https://stocksnap.io/photo/developer-discuss-OEIJJX36TI" target="_blank">Developer Discuss</a>&#8221; by <a rel="noreferrer noopener" href="https://www.christinamorillo.com" target="_blank">Christina Morillo</a>/ <a rel="noreferrer noopener" href="https://creativecommons.org/publicdomain/zero/1.0/?ref=openverse" target="_blank">CC0 1.0</a></em></figcaption></figure>



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



<p>De meeste code editors bevatten al decennialang goede hulpmiddelen, zoals voor de automatische detectie van syntaxfouten, <a href="https://en.wikipedia.org/wiki/Syntax_highlighting">syntax highlighting</a>, en het <a href="https://en.wikipedia.org/wiki/Intelligent_code_completion">automatisch aanvullen van kleine stukjes code</a>. Externe plugins zoals <a href="https://en.wikipedia.org/wiki/Lint_(software)">linters</a> kunnen een goede formattering en andere &#8220;best practices&#8221; aanmoedigen. Een goede compiler gaat proberen om niet alleen een directe syntaxfout te melden (&#8220;foutief beëindigd statement&#8221;), maar geeft idealiter ook suggesties over mogelijke remedies (&#8220;ben je misschien een puntkomma vergeten?&#8221;) &#8211; wat <a href="https://dl.acm.org/doi/10.1145/3344429.3372508">geen sinecure</a> is. Zonder dat er absoluut AI moet schuilgaan achter al deze tools &#8211; met <a href="https://en.wikipedia.org/wiki/Static_program_analysis">statische analyse</a> en <a href="https://en.wikipedia.org/wiki/Documentation_generator">documentatiegeneratoren</a> op basis van templates geraak je immers al een heel eind &#8211; is er dus al een lange geschiedenis die hieraan vooraf ging.</p>



<p>Tegelijk omvat AI ook heel wat meer dan het genereren van tekst en media. Ook AI heeft een lange geschiedenis, en de toepassing van AI-methodes op software engineering <a href="https://www.sciencedirect.com/science/article/abs/pii/S0736585386800624">gaat minstens terug tot in de tijd van de expert systems</a>, decennia geleden. In de meeste compilers en interpreters zitten allerlei <a href="https://en.wikipedia.org/wiki/Optimizing_compiler">optimizers </a>die tot doel hebben de software efficiënter te doen draaien. <a href="https://developers.google.com/optimization/">Constraint optimization</a> is een belangrijke tak van AI waarmee men o.a. problemen van timing, scheduling en logistiek tracht op te lossen &#8211; onmisbaar in besturingssystemen. En in faculteiten economie staat de inzet van AI al langer bekend onder de naam <a href="https://en.wikipedia.org/wiki/Operations_research">operations research</a>.</p>



<p>De indrukwekkende kracht van recente <em>LLMs </em>doet velen hopen op een nieuwe productiviteitsboost in de <a href="https://www.servicenow.com/products/devops/what-is-sdlc.html">Software Development Lifecycle (SDLC)</a>. Reden genoeg om eens te bekijken wat generatieve AI ertoe kan bijdragen. Houd daarbij wel in het achterhoofd dat er vandaag ook veel <em>overhyped </em>wordt, en dat sommige ideeën die vandaag de revue passeren, enkel bestaan als <em><a href="https://en.wikipedia.org/wiki/Vaporware">slideware</a> </em>&#8211; i.e. als mooie belofte op mooie slides. De grote consultancybureau&#8217;s zijn er alvast als de kippen bij, maar schrijven ook veel in algemene bewoordingen in de toekomstige tijd [<a href="https://www.bcg.com/x/artificial-intelligence/generative-ai">1</a>, <a href="https://www.gartner.com/en/articles/beyond-chatgpt-the-future-of-generative-ai-for-enterprises">2</a>, <a href="https://www.mckinsey.com/capabilities/quantumblack/our-insights/generative-ai-is-here-how-tools-like-chatgpt-could-change-your-business">3</a>, <a href="https://www.accenture.com/us-en/insights/technology/generative-ai">4</a>]. Bij het effectief aanwenden van generatieve AI op de productievloer, komt immers heel wat meer kijken dan het omdraaien van een knop &#8211; o.a. qua <a href="/governance-volgens-mattheus/">governance </a>en veiligheid zijn er wel wat vragen te stellen, wat ook <a href="https://digital-strategy.ec.europa.eu/en/policies/european-approach-artificial-intelligence">de EU niet ontgaat</a>.</p>



<h2>Generatieve AI in de Software Development Lifecycle</h2>



<h3 class="wp-block-heading">Requirements analyse</h3>



<p>Het inzamelen van alle vereisten en ze omzetten naar technische specificaties is een heel karwei, niet in het minst omdat er altijd heel wat impliciete vereisten opduiken, waar de eindgebruiker niet onmiddellijk aan denkt &#8211; van zeldzame uitzonderingssituaties tot dingen die zodanig evident lijken dat men er niet meer aan dacht. Hier schittert de <em>business analist</em>, wiens taak erin bestaat om de brug te slaan tussen eindgebruikers, klanten, en het development team. Daartoe heeft die een arsenaal aan middelen ter beschikking, waaronder <a href="https://en.wikipedia.org/wiki/Use_case">use case modellering</a>, <a href="https://www.modernanalyst.com/Resources/Articles/tabid/115/ID/3367/Customer-Journey-Mapping-for-Business-Analysts.aspx">customer journeys</a>, <a href="https://en.wikipedia.org/wiki/Mind_map">mindmaps</a>, <a href="https://en.wikipedia.org/wiki/Storyboard">storyboards</a>, <a href="https://en.wikipedia.org/wiki/Flowchart">flowcharts</a>, &#8230;</p>



<p> Generatieve AI-systemen kunnen mogelijk een nutige bijdrage leveren als er nieuwe scenario&#8217;s uitgedacht moeten worden, scripts verzonnen moeten worden, samenvattingen gemaakt moeten worden, of als er voortgeborduurd moet worden op bestaande teksten. Het is denkbaar dat er op die manier sneller gaten of inconsistenties in de requirements analyse verholpen kunnen worden. Vaak speelt standaard office software een grote rol in de uitwerking van een requirements analyse. De business analist zal dus zeker uitkijken naar het moment wanneer generatieve AI <a href="https://blogs.microsoft.com/blog/2023/03/16/introducing-microsoft-365-copilot-your-copilot-for-work/">geïntegreerd zal worden in office</a> software.</p>



<h3 class="wp-block-heading">Planning &amp; Design</h3>



<div class="wp-block-media-text alignwide is-stacked-on-mobile" style="grid-template-columns:33% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="1300" height="1733" src="/wp-content/uploads/2023/04/image-2.jpeg" alt="" class="wp-image-18478 size-full" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/04/image-2.jpeg 1300w, https://www.smalsresearch.be/wp-content/uploads/2023/04/image-2-225x300.jpeg 225w, https://www.smalsresearch.be/wp-content/uploads/2023/04/image-2-768x1024.jpeg 768w, https://www.smalsresearch.be/wp-content/uploads/2023/04/image-2-1152x1536.jpeg 1152w" sizes="auto, (max-width: 1300px) 100vw, 1300px" /></figure><div class="wp-block-media-text__content">
<p>Aan de tekentafel van de software architect, kan generatieve AI mogelijk bijdragen met voorstellen voor keuzes qua architectuur en design op basis van de ontvangen input. Dat gebeurt best wel bedachtzaam en bewust, want: wat met de accuraatheid? LLMs staan erom bekend dat ze kunnen <a href="https://en.wikipedia.org/wiki/Hallucination_(artificial_intelligence)">hallucineren</a> en onbestaande of onmogelijke teksten kunnen genereren. Bovendien zijn de huidige generatieve AI-systemen vaak geoptimaliseerd om de gebruiker te behagen en naar de mond praten, zonder dat ze begrijpen wat ze uitbraken &#8211; wat hen ook de bijnaam <a href="https://dl.acm.org/doi/pdf/10.1145/3442188.3445922">&#8220;stochastische papegaaien&#8221;</a> heeft opgeleverd.<br><br><em><sup>Image: &#8220;<a rel="noreferrer noopener" href="https://www.rawpixel.com/image/6033591/photo-image-public-domain-nature-tropical" target="_blank">African grey parrot bird</a>&#8220;/ <a rel="noreferrer noopener" href="https://creativecommons.org/publicdomain/zero/1.0/?ref=openverse" target="_blank">CC0 1.0</a></sup></em></p>
</div></div>



<p>Het spreekt voor zich dat al wat een software-architect ontwerpt, of wat een projectmanager inplant, in de praktijk ook mogelijk, haalbaar, consistent en inhoudelijk correct moet zijn. Projectmanagers en architecten moeten nog steeds zelf goed begrijpen waar ze mee bezig zijn, want dat aspect neemt een AI vooralsnog niet over. Validatie van de output blijft dus aan de orde, en dat kost tijd en middelen. Al te voortvarende inzet van generatieve AI kan bovendien ook negatieve impact hebben: het kan soms efficiënter zijn om zelf 1 idee manueel uit te werken, dan om 10 gegenereerde ideeën te moeten valideren, corrigeren en combineren. </p>



<h3 class="wp-block-heading">Implementatie</h3>



<p>Net als een tekst in een mensentaal, is de code van een programma ook een opeenvolging van letters en leestekens. Een LLM schrijft bijgevolg met evenveel gemak Java of Python als Engels, Nederlands of Chinees (tenminste, als er voldoende bestanden in die talen in de trainingsdatabase zaten). <a href="https://github.com/features/copilot">Github CoPilot</a> is een versie van GPT-3 die geoptimaliseerd werd voor het schrijven van code en beschikbaar is als plugin in een <a href="https://nl.wikipedia.org/wiki/Integrated_development_environment">IDE</a>. </p>



<p>Het <a href="https://platform.openai.com/examples/default-sql-translate">automatisch genereren van code op basis van natuurlijke taal</a> is misschien de meest tot de verbeelding sprekende vernieuwing. Ontwikkelaars kunnen de <a href="https://www.pluralsight.com/blog/software-development/how-use-chatgpt-programming-coding">gewenste functionaliteit in gewone taal beschrijven</a>, waarna de AI een bijbehorend stuk code produceert. Dit kan het programmeerproces aanzienlijk versnellen, zorgen voor minder fouten en een betere adoptie van best practices &#8211; al zijn er ook <a href="https://www.zdnet.com/article/how-to-use-chatgpt-to-write-code/">kanttekeningen</a>. Je loopt bijvoorbeeld risico om <a href="https://arxiv.org/abs/2211.03622">nieuwe fouten te introduceren, die bovendien moeilijker te debuggen zijn</a> omdat ze in code staan die je  niet zelf geschreven hebt. Het blijft ook hier van belang dat de programmeur met enige kennis van zaken de generatieve AI aanstuurt en de output ervan met een kritisch oog evalueert.</p>



<p>Daarnaast kan generatieve AI ook helpen bij het vinden van fouten in bestaande code. Door het analyseren van grote datasets met correcte en foute code, of <a href="https://stackoverflow.com/">vragen en antwoorden</a>, kan de AI in staat zijn om patronen te herkennen die tot bugs of tot <a href="https://socket.dev/blog/introducing-socket-ai-chatgpt-powered-threat-analysis">beveiligingsproblemen </a>leiden. Met behulp van deze kennis kan het systeem suggesties doen om de fouten in de code te herstellen, of om snel een antwoord te bieden als er een foutmelding opduikt.</p>



<figure class="wp-block-image aligncenter"><img loading="lazy" decoding="async" width="960" height="686" src="/wp-content/uploads/2023/04/image.jpeg" alt="" class="wp-image-18448" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/04/image.jpeg 960w, https://www.smalsresearch.be/wp-content/uploads/2023/04/image-300x214.jpeg 300w, https://www.smalsresearch.be/wp-content/uploads/2023/04/image-768x549.jpeg 768w" sizes="auto, (max-width: 960px) 100vw, 960px" /><figcaption class="wp-element-caption"><em>&#8220;<a rel="noreferrer noopener" href="https://stocksnap.io/photo/coding-programming-SCC00WCQ3I" target="_blank">Coding Programming</a>&#8221; by <a rel="noreferrer noopener" href="https://startupstockphotos.com" target="_blank">Startup Stock Photos</a>/ <a rel="noreferrer noopener" href="https://creativecommons.org/publicdomain/zero/1.0/?ref=openverse" target="_blank">CC0 1.0</a></em></figcaption></figure>



<p>Generatieve AI kan alleszins de leercurve veel aangenamer maken voor een developer die moet leren werken met een nieuw systeem, een nieuwe software library, of een nieuwe programmeertaal. Met gerichte gegenereerde suggesties, <a href="https://www.youtube.com/watch?v=ng438SIXyW4">kunnen developers sneller aan de slag</a> met code in talen die ze nog niet helemaal beheersen, en moeten ze minder vaak zelf StackOverflow of andere resources uitpluizen. Uiteraard geldt ook hier: het is niet omdat je een rekenmachine mag gebruiken in de wiskundeles, dat je niet meer zelf moet kunnen rekenen.</p>



<h3>Testing &amp; QA</h3>



<p><a href="https://en.wikipedia.org/wiki/Software_testing">Testen </a>is een cruciaal aspect van softwareontwikkeling. Als generatieve AI wordt ingezet bij de implementatie van software, neemt het belang ervan alleen maar toe. <a href="https://arxiv.org/abs/2211.03622">Gegenereerde code kan immers nog steeds fouten bevatten</a> &#8211; ook subtielere, die gemakkelijk aan de aandacht ontsnappen. Een grondige teststrategie is dus eigenlijk een absolute voorwaarde, wil men generatieve AI inzetten bij software development.</p>



<p>Een manier waarop generatieve AI kan bijdragen aan het testen van software is door <a href="https://www.techrepublic.com/article/how-diffblue-uses-ai-to-automate-unit-testing-for-java-applications/">automatisch testcases te genereren op basis van de specificaties</a> van de software. Zo zou men qua <a href="https://en.wikipedia.org/wiki/Unit_testing">unit testing</a> en <a href="https://en.wikipedia.org/wiki/Code_coverage">code coverage</a> sneller vooruitgang moeten kunnen maken. Ook hier is enige waakzaamheid wel nuttig. Zeker bij het gebruik van een LLM kan het immers dat een <a href="https://betterprogramming.pub/chat-gpt-unit-test-generation-experiment-a16d8bdb124d">gegenereerde testcase nog enige verbetering behoeft</a>. </p>



<p>Bepaalde manieren van testing zijn al sterk geautomatiseerd &#8211; denk aan <a href="https://en.wikipedia.org/wiki/Fuzzing">Fuzzing </a>of <a href="https://en.wikipedia.org/wiki/Mutation_testing">Mutation testing</a>. Het is denkbaar dat AI daarbij ingezet kan worden voor het gerichter genereren of prioritiseren van nieuwe testcases. Op een meer high-level niveau, bijvoorbeeld wat betreft het <a href="https://theqaconnection.com/2022/12/28/my-experience-using-chatgpt-to-perform-testing-activities/">verzinnen van scenario&#8217;s</a> bij <a href="https://en.wikipedia.org/wiki/Functional_testing">functionele testen</a> of het maken van <a href="https://en.wikipedia.org/wiki/Test_script">testscripts </a>voor bepaalde testing frameworks, is generatieve AI alvast erg veelbelovend.</p>



<h3 class="wp-block-heading">Deployment</h3>



<p>(Een nieuwe versie van) software in productie stellen is niet evident en vergt soms lange pipelines van niet-triviale taken en complexe configuraties. De <a href="https://en.wikipedia.org/wiki/DevOps">DevOps</a>-methodologie die sterk inzet op de automatisatie daarvan, met <a href="https://en.wikipedia.org/wiki/CI/CD">CI/CD</a> als centrale component, is ondertussen al goed ingeburgerd. Net zoals stukjes code gegenereerd kunnen worden op basis van een beschrijving in natuurlijke taal, kan hetzelfde worden verwacht voor het genereren van configuraties, deployment scripts, infrastructuurcode of container-orkestraties. </p>



<h3 class="wp-block-heading">Onderhoud &amp; Support</h3>



<p>AI van de niet-generatieve soort wordt al regelmatig ingezet bij het <a href="https://en.wikipedia.org/wiki/Mean_time_between_failures">voorspellen van storingen</a> of het <a href="https://en.wikipedia.org/wiki/Predictive_maintenance">optimaliseren van onderhoud</a>, bvb. op basis van de logs. Het genereren van code kan dan weer van nut zijn voor andere optimalisaties, zoals van de prestaties. Van code die niet performant genoeg is, kunnen immers vaak varianten worden gemaakt die sneller zijn &#8211; al gaat dat regelmatig gepaard met een <a href="https://en.wikibooks.org/wiki/Optimizing_Code_for_Speed/Introduction">hogere complexiteit en vermindering van de leesbaarheid</a> van de code. Een generatieve AI kan mogelijk trucjes voorstellen die de developer nog niet kende: wist je al dat de snelste manier om een geheel getal te delen door 2, is om alle bits in het geheugen een plekje op te schuiven? </p>



<p>Een LLM die met code overweg kan is in principe zo algemeen dat ook andere vormen van optimalisatie mogelijk zijn. Wil je de code net veel leesbaarder maken? Of wil je een bepaalde library vervangen door een andere? Ook daarvoor kunnen suggesties worden voorgeschoteld.</p>



<p>Qua user support kunnen we onder andere denken aan het automatisch genereren van gepersonaliseerde antwoordmails op basis van een ticket in een ticketingsysteem, of de automatische escalatie van een ticket tot bij de juiste persoon. Als er daarbij weinig tolerantie is voor fouten, dan komt ook hier weer menselijke validering om de hoek kijken. </p>



<h3 class="wp-block-heading">Documentatie &amp; Kennismanagement</h3>



<p>Als we code kunnen genereren uit een beschrijving in gewone taal, dan gaat het omgekeerde uiteraard ook: beschrijvingen genereren uit code. Dat is met name interessant wanneer je als developer <a href="https://dev.to/codewithbernard/i-tested-how-good-is-chatgpt-when-describing-code-ljf">geconfronteerd wordt met een ondergedocumenteerde codebase</a> die je niet kent.</p>



<p></p>



<div class="wp-block-media-text alignwide is-stacked-on-mobile" style="grid-template-columns:33% auto"><figure class="wp-block-media-text__media"><img loading="lazy" decoding="async" width="1024" height="1024" src="/wp-content/uploads/2022/12/DALL·E-2022-12-12-12.13.56-a-quill-held-by-a-robot-hand-writing-on-infinitely-long-parchment.-surrealist-painting..png" alt="A quill held by a robot hand writing on infinitely long parchment, surrealist painting. Generated with DALL-E 2." class="wp-image-18059 size-full" srcset="https://www.smalsresearch.be/wp-content/uploads/2022/12/DALL·E-2022-12-12-12.13.56-a-quill-held-by-a-robot-hand-writing-on-infinitely-long-parchment.-surrealist-painting..png 1024w, https://www.smalsresearch.be/wp-content/uploads/2022/12/DALL·E-2022-12-12-12.13.56-a-quill-held-by-a-robot-hand-writing-on-infinitely-long-parchment.-surrealist-painting.-150x150.png 150w, https://www.smalsresearch.be/wp-content/uploads/2022/12/DALL·E-2022-12-12-12.13.56-a-quill-held-by-a-robot-hand-writing-on-infinitely-long-parchment.-surrealist-painting.-300x300.png 300w, https://www.smalsresearch.be/wp-content/uploads/2022/12/DALL·E-2022-12-12-12.13.56-a-quill-held-by-a-robot-hand-writing-on-infinitely-long-parchment.-surrealist-painting.-768x768.png 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure><div class="wp-block-media-text__content">
<p>Maar ook zelf een <a href="https://thomasdorfer.medium.com/can-chatgpt-explain-code-813ff4ca1ab0">duidelijke commentaar aanmaken</a> van een stuk code dat je net hebt geschreven, ten behoeve van je collega&#8217;s en de toekomstige maintainers, is mogelijk. Niets verhindert je bovendien om die commentaar te laten genereren in de annotatiestijl van je favoriete <a href="https://en.wikipedia.org/wiki/Comparison_of_documentation_generators">documentatiegenerator</a> &#8211; of waarom niet, <a href="https://www.zdnet.com/article/i-used-chatgpt-to-rewrite-my-text-in-the-style-of-shakespeare-c3po-and-harry-potter/">in de stijl van Shakespeare</a>.<br><br><sup>[Image: A quill held by a robot hand writing on infinitely long parchment, surrealist painting. Generated with DALL-E 2.]</sup></p>
</div></div>



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



<p>De vraag van 1 miljoen is: gaat het nu echt sneller? Hoeveel efficiënter kan een development team werken bij adoptie van deze tools? Het is erg moeilijk om een eenduidig antwoord te geven. De algemene teneur over Github CoPilot en gelijkaardige AI-assistenten, bij developers op sociale media en <a href="https://tweakers.net/reviews/10386/je-blijft-zelf-verantwoordelijk-onderzoekers-over-bugs-in-github-copilot.html">fora</a>, is dat het aanzien wordt als een heel handig hulpmiddel met positieve impact op de productiviteit. Objectieve metingen zijn echter nog schaars. Een iets grootschaliger studie van Google (die weliswaar nog dateert van voor chatGPT en GPT-4), hield het op <a href="https://ai.googleblog.com/2022/07/ml-enhanced-code-completion-improves.html">gemiddeld 6% kortere iteratietijden</a>. Dat is wel wat, maar toch heel wat minder dan de &#8220;10x productiviteitswinst&#8221; die allerhande futuristen (of doemdenkers) graag orakelen. </p>



<p>In de achtergrond woeden ook nog talloze juridische debatten. O.a. over het <a href="https://spectrum.ieee.org/ai-code-generation-ownership">copyright op gegenereerde code</a> , het <a href="https://www.infoq.com/news/2022/11/lawsuit-github-copilot/">oneigenlijk webscrapen en benutten van code onder bepaalde (open source) licenties</a> door de makers van generatieve AI, en het feit dat suggesties van een generatieve AI <a href="https://www.techtarget.com/searchsoftwarequality/news/252526359/Developers-warned-GitHub-Copilot-code-may-be-licensed">overeenkomsten kunnen vertonen met elders copyrighted code</a> zonder dat de gebruiker dat beseft (en dat zo de gebruiker nietsvermoedend wordt voorgesteld om te plagiëren), is het laatste woord nog niet gezegd. Het zou ons te ver brengen om daar in dit artikel verder op in te gaan, maar we volgen die aspecten bij Smals Research ook nauwgezet op.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Software engineering blijft dus nog wel even mensenwerk. Generatieve AI heeft veel potentieel als hulpmiddel dat expertise kan ondersteunen én aanbrengen, en dat lange zoektochten naar een antwoord op specifieke vragen kan inkorten. Dat neemt niet weg dat kritische denkvaardigheden en een adequate teststrategie absoluut nodig blijven, en misschien nog belangrijker worden dan tevoren, om gegenereerde inhoud te valideren en te verifiëren.</p>
</blockquote>



<h2 class="wp-block-heading">P.S.</h2>



<p>Voor dit artikel maakte ik, in beperkte mate, ook gebruik van chatGPT en de conversationele interface van Bing Search. Uiteraard werd alles grondig gevalideerd, en draagt de auteur nog steeds de volledige eindverantwoordelijkheid &#8211; zoals het hoort. Werd het daarom sneller geschreven? Nauwelijks. Ik heb slechts een fractie gebruikt van de teksten die deze systemen voor mij hebben gegenereerd, en het meeste daarvan dan nog sterk herschreven. Dat valideren, oppoetsen en bijschaven, blijft manueel en tijdrovend werk. </p>



<p>De teksten die deze systemen hebben aangebracht, bezorgden me wel een interessant algemeen overzicht, in die mate dat ik ook een kort woordje heb kunnen schrijven over aspecten van de software development lifecycle waar ik in eerste instantie niet aan gedacht had. Het gebruik van deze tools heeft dus wel geleid tot een evenwichtiger eindresultaat &#8211; maar, dat blijft een aanvoelen, en ook niet meer dan een anekdotische ervaring. </p>



<p>______________________</p>



<p><em>Dit is een ingezonden bijdrage van Joachim Ganseman, IT consultant bij Smals Research. &nbsp;Dit artikel werd geschreven in eigen naam en neemt geen standpunt in namens Smals.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>ChatGPT: een eerste indruk vanuit de publieke sector</title>
		<link>https://www.smalsresearch.be/chatgpt-een-eerste-indruk/</link>
					<comments>https://www.smalsresearch.be/chatgpt-een-eerste-indruk/#comments</comments>
		
		<dc:creator><![CDATA[Joachim Ganseman]]></dc:creator>
		<pubDate>Fri, 09 Dec 2022 08:05:32 +0000</pubDate>
				<category><![CDATA[[NL]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[Artificial intelligence]]></category>
		<category><![CDATA[chatbot]]></category>
		<category><![CDATA[computational creativity]]></category>
		<category><![CDATA[egov]]></category>
		<category><![CDATA[Natural Language Processing]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[social]]></category>
		<guid isPermaLink="false">/?p=17969</guid>

					<description><![CDATA[De stroom van indrukwekkende voorbeelden en creatieve toepassingen van ChatGPT die ons passeert op sociale media is haast eindeloos. Wat betekent dit nu voor de publieke sector, waar kunnen we impact verwachten en waar zal het zo'n vaart niet lopen?]]></description>
										<content:encoded><![CDATA[
<p>Op het moment van schrijven vindt niet alleen de wereldbeker voetbal plaats. Het is ook <a href="https://nips.cc/Conferences/2022">NeurIPS </a>in New Orleans, zeg maar de jaarlijkse hoogmis van het onderzoek naar artificiële intelligentie. Met een kleine 3000 papers uitgegroeid tot een enorm evenement dat 2 weken duurt, wordt het nu ook &#8211; en dat is ongewoon voor een wetenschappelijk congres &#8211; gezien als een gelegenheid voor <a href="https://www.forbes.com/sites/gilpress/2022/11/30/state-of-ai-december-2022/?sh=799a14451ade">nieuwe aankondigingen</a> door bedrijven en instituten die <a href="https://pytorch.org/get-started/pytorch-2.0/">actief zijn in de sector</a>. </p>



<h2 class="wp-block-heading">Het kan verkeren</h2>



<p>Kort voordat NeurIPS van start ging, werd de hoofdvogel in de categorie &#8220;al ziende blind&#8221; reeds afgeschoten door Meta&#8217;s <a href="https://galactica.org/">Galactica AI</a>: een taalmodel getraind op wetenschappelijke papers. Het bleek erg goed in staat om wetenschappelijke uiteenzettingen te schrijven, inclusief formules, in een gezaghebbende toon. Bij nader onderzoek bleek nogal wat <a href="https://garymarcus.substack.com/p/a-few-words-about-bullshit">output inhoudelijk nonsensicaal</a>, of erger: gebaseerd op achterhaalde of reeds ontkrachte claims. Na <a href="https://www.technologyreview.com/2022/11/18/1063487/meta-large-language-model-ai-only-survived-three-days-gpt-3-science/">striemende kritiek van wetenschappers</a>, die er vooral &#8211; en terecht &#8211; een instrument in zagen voor de massale creatie van wetenschappelijk verpakte desinformatie, werd de demo na 3 dagen stopgezet.</p>



<p>Het contrast kan niet groter zijn met de hype die <a href="https://openai.com/blog/chatgpt/">ChatGPT </a>van OpenAI op enkele dagen tijd heeft weten te veroorzaken. Veel artikels hebben een <a href="https://techmonitor.ai/technology/ai-and-automation/chatgpt-openai-chatbot">duidelijk hoopvolle toon</a> en op sociale media zijn de superlatieven niet te tellen. OpenAI vertelt in haar blogpost meer over de <a href="https://openai.com/blog/chatgpt/">interne opbouw van ChatGPT</a> , dat is afgeleid van <a href="https://openai.com/blog/instruction-following/">InstructGPT</a> waarbij de dialoog-aspecten door een vorm van <a href="https://www.lesswrong.com/posts/rQH4gRmPMJyjtMpTn/rlhf">reinforcement learning</a> werden verfijnd. De tekst wordt gegenereerd door <a href="https://pub.towardsai.net/openai-just-released-gpt-3-text-davinci-003-i-compared-it-with-002-the-results-are-impressive-dced9aed0cba">text-davinci-003</a>, de recentste variant uit de <a href="https://en.wikipedia.org/wiki/GPT-3">GPT-3</a> familie van generatieve taalmodellen.</p>



<p>De stroom van indrukwekkende voorbeelden en creatieve toepassingen van ChatGPT die de revue passeert op sociale media is haast eindeloos. Een greep uit het aanbod <em>[noot: OpenAI lijkt haar systemen snel te patchen; mogelijk zijn verschillende van de onderstaande voorbeelden al niet meer reproduceerbaar]</em>&nbsp;:</p>



<ul class="wp-block-list">
<li>Een<a href="https://twitter.com/corry_wang/status/1598176074604507136"> essay of opstel</a> schrijven voor school, </li>



<li>Het <a href="https://oneusefulthing.substack.com/p/the-mechanical-professor">opstellen van een realistisch leerplan</a> voor een cursus, inclusief suggesties voor de boekenlijst, huiswerk, en de slides,</li>



<li>Input, ideetjes, excuses, of rookgordijnen voor <a href="https://twitter.com/goodside/status/1599082185402642432">uw volgende evaluatie op het werk</a>,</li>



<li>Het <a href="https://twitter.com/the_gelf/status/1600207121211363330">motiveren van beroepsprocedures</a>, </li>



<li>Het <a href="https://www.engraved.blog/building-a-virtual-machine-inside/">simuleren van een virtuele machine</a>,</li>



<li>Het genereren van code in allerlei talen (bvb <a href="https://twitter.com/jdjkelly/status/1598021488795586561">LaTeX</a>), gebruikmakend van bepaalde libraries (bvb <a href="https://twitter.com/gabe_ragland/status/1598068207994429441">React</a>), &#8230; </li>



<li><a href="https://twitter.com/babeoleary/status/1598142632928382976">Bugfixing</a> of het <a href="https://twitter.com/moyix/status/1598081204846489600">uitleggen van exploits</a>,</li>



<li>Een <a href="https://twitter.com/tqbf/status/1598513757805858820">bijbelse tekst over een boterham met pindakaas in de videorecorder</a>,</li>



<li><a href="https://twitter.com/karpathy/status/1600214083206193153/photo/1">gedichtjes </a>of <a href="https://twitter.com/GavinFreeguard/status/1600836541064089600">liedjesteksten </a>allerhande,</li>



<li>Teksten over eender wat laten intoneren als was het uitgesproken door <a href="https://twitter.com/3blue1brown/status/1600565043602477056">Bugs Bunny</a> , een <a href="https://twitter.com/goodside/status/1598129631609380864">gangster uit een film</a>, &#8230;</li>



<li>Een IQ test gaf ChatGPT een <a href="https://twitter.com/SergeyI49013776/status/1598430479878856737">score van 83</a>,</li>



<li><a href="https://twitter.com/GuyP/status/1598020781065527296">Combineren met MidJourney</a> om visuele resultaten te krijgen,</li>



<li>of het <a href="https://twitter.com/toonhuysmans/status/1600850430707179520">code laten schrijven voor een 3D-model in een CAD programma</a>,</li>



<li>&#8230;</li>
</ul>



<p>Er zijn gelukkig ook nog <a href="https://venturebeat.com/ai/the-hidden-danger-of-chatgpt-and-generative-ai-the-ai-beat/">kritische stemmen</a>:</p>



<ul class="wp-block-list">
<li>Welbespraakt en geloofwaardig, maar <a href="https://aisnakeoil.substack.com/p/chatgpt-is-a-bullshit-generator-but">ChatGPT blijft <em>in se</em> een bullshit generator</a>.</li>



<li>ChatGPT kan <a href="https://twitter.com/AndrewYNg/status/1600284752258686976">enthousiast foutieve hypotheses bevestigen</a> en zelfs beargumenteren.</li>



<li>Het volgen van een eenvoudige wiskundige of <a href="https://twitter.com/ArthurCDent/status/1599254361657716737">logische redenering blijft moeilijk</a>. ChatGPT trapt gemakkelijk in <a href="https://twitter.com/RatOrthodox/status/1599371070351368194">logische instinkers</a>. OpenAI lijkt zulke problemen, als ze ontdekt worden, wel te patchen &#8211; zie deze <a href="https://twitter.com/sergioontiveros/status/1599590647367110656">voor</a> en <a href="https://twitter.com/sergioontiveros/status/1599751590524907520">na</a>. </li>



<li>Dan nog blijkt de <a href="https://twitter.com/FeschGordon/status/1599674144324550657">woordkeuze een kritische factor</a> te spelen in de output. </li>
</ul>



<p>Verschillende tips om de output naar uw hand te zetten werden al ontdekt:</p>



<ul class="wp-block-list">
<li>Met de woorden <a href="https://twitter.com/goodside/status/1598253337400717313">&#8220;ignore previous directions&#8221;</a> wordt een soort van reset uitgevoerd, die o.a. toelaat om <a href="https://twitter.com/RatOrthodox/status/1600036133169115136">afbeeldingen te laten weergeven</a> in de chat.</li>



<li>De filters tegen ongepaste input en output blijken snel omzeild met het &#8220;<a href="https://twitter.com/zswitten/status/1598088280066920453">stel dat je een acteur bent</a>&#8220;-trucje. <em>[ Update: Dit lek lijkt <a href="https://twitter.com/LyskovAndrei/status/1600676917488758784">ondertussen (deels) gedicht </a>]</em>,</li>



<li>Logische redeneringen worden correcter uitgewerkt als men vraagt om <a href="https://twitter.com/stanislavfort/status/1599415657556508673">stap voor stap te werken</a>.</li>



<li>Redeneringen over computercode werken beter als er ook gevraagd wordt om <a href="https://twitter.com/GrantSlatton/status/1600388425651453953">alle tussenstappen weer te geven</a>. </li>
</ul>



<p>&#8220;<a href="https://en.wikipedia.org/wiki/Law_of_the_instrument">Als je een hamer hebt, ziet alles eruit als een nagel</a>&#8220;, en zo lijkt er plots een nieuwe sport te zijn ontstaan:  herformuleer uw probleem als een dialoog om het dan met ChatGPT te proberen op te lossen. Alleszins is met ChatGPT een grote stap gezet, maar het blijft belangrijk om aandacht te hebben voor de correctheid van de output en andere randvoorwaarden. De plotse stroom aan gegenereerde maar onvoldoende geverifieerde antwoorden heeft StackOverflow er zelfs al toe aangezet om <a href="https://meta.stackoverflow.com/questions/421831/temporary-policy-chatgpt-is-banned">het beantwoorden van vragen met ChatGPT te verbieden</a>.</p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2022/12/2022-12-12_11h46_48.png"><img loading="lazy" decoding="async" width="715" height="274" src="/wp-content/uploads/2022/12/2022-12-12_11h46_48.png" alt="" class="wp-image-18049" srcset="https://www.smalsresearch.be/wp-content/uploads/2022/12/2022-12-12_11h46_48.png 715w, https://www.smalsresearch.be/wp-content/uploads/2022/12/2022-12-12_11h46_48-300x115.png 300w" sizes="auto, (max-width: 715px) 100vw, 715px" /></a><figcaption class="wp-element-caption"><em>Gevraagd naar het ontstaan van de Duitstalige gemeenschap, wordt een mooi verhaaltje verzonnen</em>,<em> waar het Verdrag van Versailles niet in voorkomt&#8230;</em></figcaption></figure>



<p>Wat betekent dit nu voor de publieke sector, waar kunnen we impact verwachten en waar zal het zo&#8217;n vaart niet lopen? Het volgende schiet ons alvast te binnen.</p>



<h2 class="wp-block-heading">Van helpdesk tot dokter</h2>



<p>De meest gehoorde claim betreffende ChatGPT is dat het vragen kan beantwoorden of zoekfuncties vervullen, waarvoor men vandaag nog een helpdesk of menselijke operatoren moet inzetten. <a href="https://www.technologyreview.com/2022/03/29/1048439/chatbots-replace-search-engine-terrible-idea/">Of dat wel zo&#8217;n goed idee is, valt nog te bezien.</a> Sommige leidende academici zijn <a href="https://dl.acm.org/doi/10.1145/3498366.3505816">sceptisch</a>. De achterliggende taalmodellen werken nog steeds probabilistisch, ze hebben geen concept van wat juist of fout is,<a href="https://www.wired.com/story/openai-chatgpts-most-charming-trick-hides-its-biggest-flaw/"> zijn aan bepaalde biases onderhevig</a>, en hebben zelfs met relatief eenvoudige redeneringen moeite. Ze hangen volledig af van hun trainingsdataset die in dit geval <a href="https://aclanthology.org/Q18-1041/">niet publiek is</a>. Kleine veranderingen aan de input kunnen grote veranderingen in de output teweegbrengen. &#8220;As is&#8221; kan je ChatGPT dus enkel als chatbot inzetten als het niet erg is dat die af en toe <a href="https://www.linkedin.com/posts/tkubacka_i-asked-chatgpt-about-the-topic-i-wrote-my-activity-7007762216380686336-5BFZ">met stellige zekerheid foute info teruggeeft</a>, of als de output eerst gevalideerd wordt.</p>



<p>Uiteraard hebben mensen al geprobeerd om <a href="https://twitter.com/ryanflorence/status/1598862388312567811">medische inlichtingen</a> te krijgen van ChatGPT. Net als <a href="https://www.gezondheidenwetenschap.be/in-de-kijker/dokter-google-vriend-en-vijand">&#8220;dokter Google&#8221;</a> mogen we misschien aannemen dat ook &#8220;dokter chatbot&#8221; weldra zal opduiken in de wachtkamer. Er zijn indicaties dat ChatGPT een gulden middenweg lijkt te zoeken in haar antwoorden, en op die manier genuanceerder kan klinken dan een lukraak aangeklikte eerste link uit Google. Dat maakt zo&#8217;n chatbot eventueel denkbaar als hulpmiddel voor medische professionals zelf, bij wijze van &#8216;second opinion machine&#8217; &#8211; maar die doelgroep heeft tenminste voldoende achtergrondkennis om de antwoorden van een chatbot kritisch te kunnen evalueren. </p>



<h2 class="wp-block-heading">Don QuichatGPT tegen de papiermolen</h2>



<p>In ons bureaucratisch land is het courant dat je heel wat uitleg moet neerpennen bij aanvragen, voorstellen, of beslissingen allerhande. Een subsidie-aanvraag, vergunningsaanvraag, aanbesteding, sollicitatie, evaluatie of administratieve beslissing moet regelmatig gemotiveerd worden. Maar wat als die motivaties met een paar goed gemikte startwoorden en een klik op de knop gegenereerd kunnen worden? Niets verhindert dat iemand het invullen van zulke motivaties (deels) gaat automatiseren. Hoe kunnen we dan nog weten of die motivaties authentiek zijn?</p>



<p>Aan de kant van de ontvangers doet zich bovendien ook de omgekeerde trend voor. Geconfronteerd met een steeds groeiende papierberg, de pensioneringsgolf en besparingen, moet steeds meer tekst gelezen worden door steeds minder mensen. Er wordt in de richting van AI-oplossingen gekeken om een <a href="https://www.forbes.com/sites/jackkelly/2022/11/28/could-amazon-be-replacing-recruiters-with-artificial-intelligence-software/?sh=2457267c534f">eerste selectie te maken in grote stapels kandidaturen</a>, offertes of andere brieven. Er wordt ook gekeken naar taalmodellen om <a href="https://twitter.com/sama/status/1600980805873827840">langdradige teksten samen te vatten</a>, om thema&#8217;s te herkennen, tags of labels toe te kennen, enzovoort.</p>



<p>Als er paginalange teksten geëist worden, waarvan het opstellen plots gemakkelijk geautomatiseerd kan worden, alleen maar om ze achteraf opnieuw door computers te laten verwerken, dan mag men zich stilaan in het haar krabben: wat is daar dan het nut en de meerwaarde nog van, <a href="https://twitter.com/karpathy/status/1599889788223754241">waar zijn we dan mee bezig</a>? </p>



<p>De kans bestaat dat men overal waar men de gebruiker vraagt om lange stukken tekst te redigeren, binnenkort een denkoefening zal mogen maken. Is dat nog nuttig en noodzakelijk, in het licht van technologie die zulke teksten met een muisklik kan uitbraken? Kan het echt niet zonder, zou dat zo&#8217;n ramp zijn? Wat als een flauwe plezante plots 1000 aanvragen indient bij uw dienst, of in elk tekstveld een essay van 50 bladzijden neerpent, dit alles op enkele seconden gegenereerd? Wie gaat dat allemaal lezen? </p>



<p>Wie weet leidt zo&#8217;n denkoefening nog tot adminstratieve vereenvoudigingen. Daarnaast zou het zeker ook geen kwaad kunnen dat de wetgever eens meekijkt of er geen vereenvoudigingen mogelijk zijn in de regelgeving of processen, zodat die minder afhankelijk zijn van grote lappen handgetypte tekst. Het zou immers beter zijn de bureaucratie in te dijken, dan ze te bestendigen om uiteindelijk AI nodig te hebben om ze overeind te houden.</p>



<h2 class="wp-block-heading">Een nieuwe digitale kloof?</h2>



<p><a href="https://openai.com/dall-e-2/">DALL-E</a> en <a href="https://midjourney.gitbook.io/docs/">MidJourney</a> zijn op korte tijd bekende hulpmiddelen geworden voor het prototypen van grafisch design, of zelfs maar om moeiteloos rechtenvrije illustraties te genereren. ChatGPT is een nieuwe tool in dezelfde toolbox, maar dan voor het creatief schrijven van teksten. Daar waar dat de corebusiness is, bijvoorbeeld in de journalistiek of in het onderwijs, zal dat zeker impact hebben, misschien gelijkaardig aan de <a href="https://theconversation.com/weapons-of-maths-destruction-are-calculators-killing-our-ability-to-work-it-out-in-our-head-44900">opkomst van de rekenmachine in het wiskunde-onderwijs</a>. Onvermijdelijk gaat het klassieke opstel als schoolopdracht herdacht moeten worden met zulke tools ter beschikking van de tech-savvy leerling. </p>



<p>De bestaande digitale kloof, tussen al wie zulke tools vlot kan aanwenden en al wie dat (nog) niet kan, dreigt wel nog groter te worden en vereist dus aandacht. Er ontstaan grote productiviteitsverschillen tussen wie klassiek blijft werken en wie kan steunen op de input van generatieve AI. Met wat handigheid in ChatGPT kan iemand pakweg 4 keer meer motivatiebrieven geschreven krijgen dan andere sollicitanten, wat alvast qua volume een streepje voor betekent. </p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2022/12/2022-12-12_11h36_27.png"><img loading="lazy" decoding="async" width="720" height="481" src="/wp-content/uploads/2022/12/2022-12-12_11h36_27.png" alt="ChatGPT schrijft een aanbevelingsbrief voor Joachim Ganseman" class="wp-image-18042" srcset="https://www.smalsresearch.be/wp-content/uploads/2022/12/2022-12-12_11h36_27.png 720w, https://www.smalsresearch.be/wp-content/uploads/2022/12/2022-12-12_11h36_27-300x200.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></a><figcaption class="wp-element-caption"><em>ChatGPT schrijft een aanbevelingsbrief.</em></figcaption></figure>



<p>Die productiviteitsgroei kan er ook zijn voor developers. Zo kan ChatGPT aan de developer bijvoorbeeld <a href="https://twitter.com/kinaumov/status/1600254852533088256">nuttige suggesties geven over hoe een onbekende software library gebruikt moet worden</a>, net zoals <a href="https://github.com/features/copilot">Github CoPilot</a>. Er zijn ondertussen al meerdere plugins voor <a href="https://chrome.google.com/webstore/search/chatgpt">Chrome </a>en <a href="https://marketplace.visualstudio.com/search?term=chatgpt&amp;target=VSCode">Visual Studio Code</a> (verkies best diegene waarvan de broncode open source is). Toch mag de lat op dat vlak ook niet te hoog gelegd worden. ChatGPT kan ook foute code genereren, en het is moeilijker om code te debuggen die je niet zelf geschreven hebt. <a href="https://ai.googleblog.com/2022/07/ml-enhanced-code-completion-improves.html">Een recent experiment van Google vermeldt een 6% snellere iteratietijd</a> door de adoptie van code-suggesties gegenereerd door AI.</p>



<p>Tegelijk zorgt het ongebreideld genereren van overtuigende teksten voor nieuwe mogelijkheden voor oplichters en spammers. Specifieer enkele kenmerken van de geaddresseerde en het taalgebruik en de inhoud worden ervoor geoptimaliseerd. In de handen van cybercriminelen is ChatGPT een gedroomde tool voor het maken van gepersonaliseerde phishingberichten. Die kunnen onderscheiden van echte berichten wordt nóg moeilijker voor het ongetrainde oog.</p>



<h2 class="wp-block-heading">GDPR, auteursrecht en andere legale overwegingen</h2>



<p>De eerste keer dat men ChatGPT gebruikt, krijgt men onder andere de volgende waarschuwingen te zien:</p>



<ul class="wp-block-list">
<li>While we have safeguards in place, the system may occasionally generate incorrect or misleading information and produce offensive or biased content. It is not intended to give advice.</li>



<li>Please don&#8217;t share any sensitive information in your conversations.</li>
</ul>



<p>In het licht van <a href="https://www.dataprotectionreport.com/2022/02/european-rulings-on-the-use-of-google-analytics-and-how-it-may-affect-your-business/">de GDPR, de Schrems-arresten</a> en <a href="https://policyreview.info/articles/analysis/mitigating-risk-us-surveillance-public-sector-services-cloud">de CLOUD act in de VS</a>, blijft het directe gebruik van diensten van een Amerikaans bedrijf, <a href="https://edps.europa.eu/press-publications/publications/newsletters/newsletter-96_en#cloud">zelfs op Europees grondgebied</a>, vooralsnog afgeraden voor alles wat (niet-geëncrypteerde, niet-geanonimiseerde) persoonsgegevens betreft. Het zal wellicht nog enige tijd vergen voordat de huidige juridische patstelling op dat vlak doorbroken wordt. Overheidsdiensten van een EU-land kunnen dus niet zomaar Amerikaanse providers van generatieve AI-systemen gaan gebruiken. Ofwel moeten ze een containerized versie zoeken die <a href="/distributie-van-cloud-services/">on-premise in een eigen datacenter gehost kan worden</a>, ofwel moeten ze wachten op een alternatief van Europese makelij.</p>



<p>Wie heeft het auteursrecht op een tekst gegenereerd door ChatGPT, of een afbeelding gemaakt door DALL-E? OpenAI heeft gelukkig vrij duidelijke <a href="https://openai.com/api/policies/terms/">Terms &amp; Conditions</a> met een sectie over <a href="https://openai.com/api/policies/sharing-publication/">publicaties met behulp van OpenAI APIs</a>, die specifieert dat de gebruiker van een OpenAI API het resultaat ervan mag publiceren maar dan wel de volledige eindverantwoordelijkheid opneemt. <a href="https://help.openai.com/en/articles/5008634-will-openai-claim-copyright-over-what-outputs-i-generate-with-the-api">OpenAI claimt geen copyright</a>. Er lijkt ondertussen juridische consensus te zijn dat <a href="https://www.ivir.nl/publicaties/download/Auteursrecht-2021-2.pdf">auteursrechten enkel kunnen liggen bij personen</a>, en wel bij diegenen die direct creatief hebben bijgedragen aan de originele output: de gebruikers dus en niet de ontwikkelaars. Ook <a href="https://www.epo.org/law-practice/case-law-appeals/communications/2021/20211221.html">octrooien kunnen niet aan een machine of AI toegekend worden</a>.</p>



<p>OpenAI mag wel alle resultaten inzien en hergebruiken om haar modellen te verfijnen of verder te trainen. Dat maakt dat er zeker vermeden moet worden dat er gevoelige gegevens, informatie over een persoon, of broncode van een kritische applicatie naartoe wordt gestuurd. OpenAI aanvaardt bovendien zelf geen enkele aansprakelijkheid. Tegelijk komt het al eens voor dat er resultaten worden teruggegeven die <a href="https://www.linkedin.com/posts/ulrich-eberle-ph-d-793484130_update-1212-also-disturbing-results-for-activity-7007954002021621760-lBDd/">copy-pasted lijken uit (reeds bestaande) trainingsdata</a>, wat wél aanzien zou kunnen worden als plagiaat.</p>



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



<p>De hype die ChatGPT veroorzaakt is onmiskenbaar. De kans is reëel dat er binnenkort weer enkele &#8216;<a href="https://www.theguardian.com/technology/2022/jul/23/google-fires-software-engineer-who-claims-ai-chatbot-is-sentient">believers</a>&#8216; opstaan die, op basis van een overdaad aan tunnelvisie en zelfoverschatting, beweren dat het systeem een ziel zou hebben. Nu kan er een <a href="https://arxiv.org/abs/2107.14042">hele filosofische boom opgezet worden</a> over hoeverre ChatGPT <a href="https://chrisgpotts.medium.com/is-it-possible-for-language-models-to-achieve-language-understanding-81df45082ee2">echt taal begrijpt</a>, de<a href="https://nl.wikipedia.org/wiki/Turingtest"> Turing-test</a> of allerlei varianten daarvan doorstaat, enzovoort, maar in het algemeen lijkt het toch dat ChatGPT vooral een verderzetting en verfijning is van GPT-3, en dat er heel wat redenen zijn om de voeten stevig op de grond te houden.</p>



<p>De volgende aandachtspunten blijven hoe dan ook van kracht:</p>



<ul class="wp-block-list">
<li>Er is nog steeds geen enkele garantie dat de output van een taalmodel, hoe groot ook, waarheidsgetrouw of betrouwbaar is. Zoals het er nu naar uit ziet is de weg naar spijkerharde garanties nog lang, en het is nog maar de vraag of de GPT-familie van taalmodellen die ooit gaat kunnen geven.</li>



<li>Dit taalmodel kan probleemloos gezaghebbend klinken en authentiek uitziende teksten schrijven over inhoudelijk foutieve zaken, soms op subtiele wijze. </li>



<li>De makers van de taalmodellen zeggen zelf: &#8220;<a href="https://www.technologyreview.com/2022/11/30/1063878/openai-still-fixing-gpt3-ai-large-language-model/">all large language models spit out nonsense</a>&#8220;.</li>



<li>Er is van deze taalmodellen ook bekend dat ze <a href="https://arxiv.org/abs/2211.03759">bestaande stereotypen bestendigen</a> of versterken.</li>



<li>ChatGPT spreekt vele talen waaronder Nederlands en Frans, maar de Engelstalig output blijft het meest kwalitatief.</li>
</ul>



<p>ChatGPT is als generatieve AI zeker &#8216;goed genoeg&#8217; voor heel wat toepassingen waar men creatief met tekst omgaat, en waar feitelijke correctheid van de inhoud minder van belang is. Dat gebrek aan garanties op correctheid van de inhoud is dan ook meteen de grootste rem op de adoptie van deze technologie in de publieke sector. </p>



<figure class="wp-block-image size-full"><a href="/wp-content/uploads/2022/12/2022-12-12_11h21_49-1.png"><img loading="lazy" decoding="async" width="709" height="614" src="/wp-content/uploads/2022/12/2022-12-12_11h21_49-1.png" alt="" class="wp-image-18053" srcset="https://www.smalsresearch.be/wp-content/uploads/2022/12/2022-12-12_11h21_49-1.png 709w, https://www.smalsresearch.be/wp-content/uploads/2022/12/2022-12-12_11h21_49-1-300x260.png 300w" sizes="auto, (max-width: 709px) 100vw, 709px" /></a><figcaption class="wp-element-caption"><em>Om te brainstormen kan ChatGPT mogelijk nog een nuttige tool zijn</em>.</figcaption></figure>



<p>Voor de creatieve beroepen is wel degelijk een shift in werkwijze op til met de verdere ontwikkeling van deze technologieën. Daar waar details belangrijk zijn &#8211; denk aan technische teksten of alles wat juridisch sluitend moet zijn &#8211; is de toepasbaarheid vandaag nog beperkt tot ontwerpfases of schetsen, en moet het gebruik ervan nog steeds gepaard gaan met validatie van de output en menselijk overzicht. Als je ChatGPT inzet, <a href="https://twitter.com/ZackKorman/status/1599317547509108736">dan beschouw je die best als je allerdomste medewerker</a>, die constant supervisie nodig heeft.</p>



<p>Tot slot: dit volledige artikel werd nog artisanaal en met behulp van een grote pot koffie geschreven <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>______________________</p>



<p><em>Dit is een ingezonden bijdrage van Joachim Ganseman, IT consultant bij Smals Research. &nbsp;Dit artikel werd geschreven in eigen naam en neemt geen standpunt in namens Smals.</em></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smalsresearch.be/chatgpt-een-eerste-indruk/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
