# RAG-pipeline opzetten met lokale AI en eigen documenten Een RAG-pipeline opzetten met lokale AI laat je model antwoorden geven op basis van je eigen documenten. RAG staat voor Retrieval Augmented Generation: je vult de algemene kennis van het model aan met jouw specifieke informatie, volledig lokaal en privé. [[TOC]] ## Wat is RAG en waarom heb je het nodig? Een taalmodel kent veel algemene dingen, maar weet niets van jouw bedrijf, contracten of handleidingen. RAG lost dat op door bij elke vraag eerst de relevante stukken uit jouw documenten op te zoeken en die aan het model mee te geven. Het model antwoordt dan op basis van jouw informatie in plaats van te gokken. :::info title="RAG voorkomt verzinsels" Zonder RAG verzint een model soms antwoorden over onderwerpen die het niet kent. Met RAG baseert het zich op echte stukken uit jouw documenten, wat de betrouwbaarheid sterk verhoogt. ::: ## Hoe een RAG-pipeline werkt De pipeline bestaat uit twee fases. Eerst bereid je je documenten voor: je knipt ze in stukken en zet die om in vectoren met een embeddingmodel. Daarna, bij elke vraag, zoek je de stukken op die het beste bij de vraag passen en geef je die mee aan het taalmodel. De vier stappen op een rij: 1. **Documenten knippen.** Splits je documenten in behapbare stukken tekst. 2. **Embeddings maken.** Zet elk stuk om in een vector met een embeddingmodel. 3. **Opslaan in database.** Bewaar de vectoren in een vectordatabase. 4. **Zoeken en antwoorden.** Vind de relevante stukken en geef ze aan het model. De eerste drie stappen doe je één keer (of telkens als je documenten verandert). De vierde stap herhaalt zich bij elke vraag die je stelt. ## Wat je nodig hebt Voor een lokale RAG-pipeline heb je drie onderdelen nodig: Ollama met een taalmodel, een embeddingmodel zoals `nomic-embed-text`, en een vectordatabase. Voor een eenvoudige opzet werkt een lichte vectordatabase die lokaal draait prima. Veel mensen gebruiken een Python-framework dat deze onderdelen aan elkaar knoopt, zoals LangChain of LlamaIndex. :::howto title="RAG-pipeline opzetten" 1. Download een embeddingmodel met `ollama pull nomic-embed-text`. 2. Lees je documenten in en splits ze in stukken van bijvoorbeeld 500 woorden. 3. Maak voor elk stuk een embedding via het Ollama-embeddings-endpoint. 4. Sla de embeddings op in een lokale vectordatabase. 5. Maak bij elke vraag een embedding van de vraag en zoek de dichtstbijzijnde stukken. 6. Geef die stukken samen met de vraag aan je taalmodel via Ollama. ::: ## Embeddings maken met Ollama Ollama kan naast tekst genereren ook embeddings maken. Je roept daarvoor het `/api/embed`-endpoint aan met een `input`-veld: ```bash curl http://localhost:11434/api/embed -d '{ "model": "nomic-embed-text", "input": "De factuur moet binnen 14 dagen betaald worden" }' ``` Het antwoord is een lange lijst getallen, de vector, die de betekenis van de tekst vastlegt. Stukken met vergelijkbare betekenis krijgen vergelijkbare vectoren, waardoor je op betekenis kunt zoeken in plaats van op exacte woorden. Welk embeddingmodel je kiest, bepaalt mede de kwaliteit van je zoekresultaten. Een paar veelgebruikte lokale modellen: | Model | Grootte | Sterk punt | | --- | --- | --- | | `nomic-embed-text` | klein (ongeveer 300 MB) | snel en licht, prima startpunt | | `mxbai-embed-large` | middel (ongeveer 700 MB) | hogere kwaliteit, meer dimensies | | `bge-m3` | groter (ongeveer 1,2 GB) | sterk meertalig, geschikt voor Nederlands | :::tip title="Kies je tekststukken zorgvuldig" Te kleine stukken missen context, te grote stukken bevatten te veel ruis. Voor de meeste documenten werken stukken van 300 tot 800 woorden met een kleine overlap (bijvoorbeeld 50 woorden) goed. Die overlap voorkomt dat een zin precies op een knip uit elkaar valt. ::: ## De zoek- en antwoordfase Bij een vraag maak je eerst een embedding van de vraag zelf. Die vergelijk je met alle opgeslagen vectoren en je pakt de paar stukken die het dichtst in de buurt liggen. Die stukken plak je samen met de vraag in een prompt en stuur je naar het taalmodel. In je prompt vertel je het model expliciet dat het alleen op de meegegeven stukken mag antwoorden, anders gaat het alsnog gokken. :::warn title="RAG is zo goed als je documenten" Zijn je bronnen verouderd, onvolledig of tegenstrijdig, dan geeft het model verkeerde antwoorden met overtuiging. Houd je documentenverzameling actueel en controleer belangrijke antwoorden altijd bij de bron. ::: ## Volledig lokaal en privé Het mooie is dat de hele pipeline lokaal draait. Het embeddingmodel, de vectordatabase en het taalmodel staan allemaal op je eigen machine. Je gevoelige documenten verlaten je apparaat niet, wat RAG ideaal maakt voor [[lokale-ai-privacy-voordelen|vertrouwelijke informatie]]. :::faq ### Wat is het verschil tussen RAG en fine-tunen? RAG geeft documenten mee bij elke vraag zonder het model te wijzigen. Fine-tunen past het model zelf aan. RAG is flexibeler en makkelijker bij te werken, omdat je alleen je documenten hoeft te vervangen. ### Welk embeddingmodel kan ik lokaal gebruiken? nomic-embed-text is een populaire en lichte keuze die in Ollama beschikbaar is. Wil je betere resultaten of goede ondersteuning voor Nederlands, dan zijn mxbai-embed-large en bge-m3 sterke alternatieven. ### Heb ik een aparte vectordatabase nodig? Voor een serieuze opzet wel, maar voor een klein project kun je vectoren ook in het geheugen of een eenvoudig bestand houden. Een echte vectordatabase schaalt beter en zoekt sneller bij veel documenten. ### Kan ik PDF-bestanden gebruiken? Ja, maar je moet de tekst eerst uit de PDF halen. Veel frameworks doen dat automatisch voordat ze de tekst in stukken knippen. ### Moet ik mijn embeddings opnieuw maken als ik van model wissel? Ja. Vectoren van verschillende embeddingmodellen zijn niet onderling vergelijkbaar. Wissel je van model, dan moet je al je documenten opnieuw inlezen en opnieuw van embeddings voorzien. ::: Met een lokale RAG-pipeline bouw je een privé kennisassistent. Begin eventueel met de eenvoudige documentupload van [[open-webui-instellen|Open WebUI]] of verdiep je in [[ollama-api-koppelen|de Ollama API]].