
Large language models (LLM) zoals ChatGPT zijn in staat om bijna alle vragen te beantwoorden. Dit komt omdat ze getraind zijn op een grote hoeveelheid informatie. Maar wat nou als je een LLM vragen wilt laten beantwoorden over documenten waarop het LLM niet getraind is, zoals bedrijfsdocumenten? Dat kan door gebruik te maken van retrieval augmented generation (RAG) voor LLMs.
Wat is retrieval augmented generation?
De kern van retrieval augmented generation (RAG) is dat een prompt verrijkt wordt met informatie uit relevante documenten. RAG bestaat uit de volgende drie stappen:
- Retrieval: op basis van het gebruikersprompt achterhalen welke documenten relevant zijn
- Augmentation: relevante documenten toevoegen aan het prompt zodat het LLM deze kan gebruiken om het prompt te beantwoorden
- Generation: het genereren van antwoorden door het LLM op basis van het prompt met de toegevoegde documenten.
De relevante documenten worden uit een database gehaald. Het toevoegen van documenten aan deze database heet ingestion.
Het onderstaande overzicht geeft dit schematisch weer:
De ingestion en retrieval stap zijn de kern van een RAG-applicatie. Beide stappen zijn gebaseerd op het principe van embeddings.
Embeddings
Een embedding is een vectorrepresentatie (een lijst van getallen) van een stuk tekst dat wordt gegenereerd door een embeddingmodel. De betekenis van een tekst wordt zo op een wiskundige manier opgeslagen.
Het maken van embeddings gebeurt met een embedding model. De ChatGPT API heeft hiervoor embeddingmodellen beschikbaar.
Bij een RAG-applicatie wordt zowel het gebruikersprompt als de beschibkare documenten omgezet in embeddings. Met een wiskundige formule kan vervolgens worden bepaald in welke mate een prompt overeenkomt met de beschikbare documenten.
Ingestion
Met ingestion worden documenten, inclusief de embeddings, in een database opgeslagen. Dit gebeurt op de volgende manier:
- Indien nodig wordt een document voorbewerkt, bijv. middels OCR (optical character recognition), zodat het document kan worden omgezet naar tekst. Dit is vooral nuttig bij (gescande) pdf's. Ook andere bestanden, zoals Excel of HTML, kunnen worden voorbewerkt afhankelijk van de inhoud.
- Het document wordt gesplitst in chunks. Elke chunk kan bijvoorbeeld een zin van een document voorstellen.
- Van elke chunk wordt een embedding gemaakt. De chunk en embedding worden opgeslagen in een vectordatabase.
Er wordt gebruik gemaakt van een vectordatabase omdat dit de mogelijkheid biedt om heel snel grote hoeveelheden embeddings van chunks te vergeleken met de embedding van een prompt. Deze snelheid is belangrijk omdat een document doorgaans veel chunks heeft.
Retrieval
Retrieval betekent dat op basis van een prompt (bijvoorbeeld: "Wat is de datum van oprichting van Rag B.V.?") documenten worden gezocht die relevant zijn om de vraag te kunnen beantwoorden.
In de retrieval stap wordt gezocht welke chunks het meest overeenkomen met deze prompt. Dit wordt similarity search genoemd. Vectordatabases bieden de mogelijkheid om middels één retrievalquery de top n meest vergelijkbare chunks te achterhalen. Er zijn meerdere wiskundige manieren om dit te doen, de meest voorkomende opties zijn cosine similarity en euclidean distance.
Het gebruikte embeddingmodel moet gelijk zijn in de ingestion en retrieval stap, anders kunnen deze niet worden vergeleken.
De meest overeenkomende chunks kunnen worden vervolgens worden toegevoegd aan het gebruikersprompt. Er kunnen niet oneindig veel chunks worden toegevoegd aan het prompt, de grootte van het context window (de maximale grootte van een prompt) is per definitie beperkt.
De hoeveelheid toegevoegde informatie moet ook worden beperkt om andere redenen. Een LLM zal in staat zijn betere antwoorden te geven wanneer de toegevoegde informatie daadwerkelijk relevant is. Daarnaast geeft een LLM sneller antwoord bij kleinere prompts.
Optimalisatie
Het kan bewerkelijk zijn om een RAG-applicatie optimaal te configureren, aangezien er veel vrijheid zit in de implementatie.
Zo moeten er keuzes worden gemaakt over de volgende punten:
Voorbewerken: de gewenste voorbewerking hangt af van het type document (pdf, HTML, Excel, etc.) en de inhoud die erin staat. Het uitlezen van deze documenten kan op verschillende manieren. Met name wanneer er veel tabellen of afbeeldingen aanwezig zijn moet de beste aanpak per document bepaald worden.
Chunken: het opsplitsen van documenten kan op oneindig veel manieren. De grootte van een chunk moet slim gekozen worden. Kleine chunks zijn preciezer, maar kunnen relevante context missen. Grote chunks hebben meer context maar zijn weer minder precies. Daarnaast kan er worden gechunkt met of zonder overlap, kunnen stopwoorden wel of niet verwijderd worden, etc.
De hoeveelheid relevante embeddings: bij een similarity search wordt een retrieval query uitgevoerd die de top n meest relevante chunks teruggeeft. Wanneer een te grote hoevelheid (irrelevante) chunks wordt toegevoegd aan een prompt, zal een LLM langzamer worden en minder nauwkeurige antwoorden geven.
De augmentation stap: de simpelste manier om een prompt te verrijken is door de gevonden chunks direct aan het prompt terug te geven. Je kan er echter ook voor kiezen om de documenten die bij een chunk horen als geheel toe te voegen aan een prompt. Dit zorgt ervoor dat een LLM meer informatie heeft, maar ook dit kan ten koste gaan van zowel snelheid als nauwkeurigheid. Dit werkt daarom vooral goed bij kleinere documenten van enkele pagina's of minder.
Prompt engineering. Door middel van prompts kan een LLM worden geïnstrueerd om beter antwoorden te geven. Dit kan bijvoorbeeld door een LLM te vragen een prompt om te zetten naar een 'query' die beter geschikt is voor embeddings. Voorbeeld: "Wanneer is precies de laatste James Bond film uitgekomen?" wordt dan door het LLM omgezet naar "james bond meest recente film". (Stop)woorden als "wanneer", "precies" en interpunctie worden dan achterwege gelaten, waardoor de retrieval query mogelijk relevantere resultaten teruggeeft.
Type LLM: Je kunt hierbij kiezen voor een cloud-gebaseerde LLM, zoals GPT-4 via de OpenAI API, maar ook voor een lokaal draaiend taalmodel. Deze local LLMs werken volledig op je eigen server of laptop, en bieden voordelen zoals meer controle, lagere kosten en betere privacy. Tools als Ollama of LM Studio maken het mogelijk om krachtige modellen zoals Mistral of LLaMA lokaal te gebruiken.
Libraries
Zelf een RAG-applicatie ontwikkelen is mogelijk dankzij een veelvoud aan libraries die hiervoor beschikbaar zijn in Python. De meest bekende zijn Langchain en LlamaIndex.
Voor vectordatabases zijn ook een veelvoud aan opties beschikbaar. Een veelgebruikte open source optie is Postgres i.c.m. de extensie Pgvector. Andere open source opties met kleine onderlinge verschillen zijn:
Al deze opties zijn populair en hebben goede ondersteuning in verschillende frameworks.
Samenvatting
Retrieval Augmented Generation (RAG) stelt LLM's zoals ChatGPT in staat om vragen te beantwoorden over documenten buiten hun trainingsdata. Door relevante documenten op te halen, ze toe te voegen aan het prompt en antwoorden te genereren, kan RAG nauwkeurige, contextspecifieke antwoorden leveren. De juiste keuzes in het voorbewerken, chunking en retrieval-optimalisatie zijn cruciaal voor het succes van een RAG-applicatie. Wanneer dit goed gebeurt, is het een krachtige oplossingen om (bedrijfs)documentatie effectief te doorgronden.
Wil je AI expert worden?
Tijdens onze AI Opleiding leer je het hele AI spectrum kennen; van klassieke machine learning modellen tot generative AI met o.a. ChatGPT. Je leert programmeren in Python zodat je op uiteenlopende vlakken aan de slag kunt met AI. Of ben je op zoek naar een globale niet-technische introductie in AI? Bekijk dan onze AI cursus voor niet-techneuten eens. Bekijk ook eens onze AI consultancy diensten

Terry is full-stack AI-ontwikkelaar en data scientist. Hij geeft gestudeerd aan de TU Delft. In zijn carrière richt hij zich al 10+ jaar op het optimaal waarde halen uit data door toepassing van machine learning en AI.