Ga naar hoofdinhoud

Een knowledge graph gebruiken om een RAG-applicatie te bouwen

Leer hoe je knowledge graphs implementeert voor RAG-applicaties met deze stapsgewijze tutorial en verrijk AI-antwoorden met gestructureerde kennis.
· 15 min lezen

Verken met AI

Heb je je ooit afgevraagd hoe digitale assistenten zoals Alexa of Google Assistant zulke nauwkeurige antwoorden geven op je vragen?

De magie hierachter heet Retrieval-Augmented Generation (RAG), een combinatie van informatie-opvraging en taalgeneratie. Een belangrijke spil hierin is een knowledge graph, die deze assistenten helpt toegang te krijgen tot een enorme hoeveelheid gestructureerde informatie om hun antwoorden te verbeteren.

In deze tutorial duiken we in knowledge graphs en hoe je die kunt gebruiken om RAG-applicaties te bouwen voor nauwkeurigere en relevantere antwoorden.

We beginnen met de basis van knowledge graphs en hun rol in RAG. We vergelijken ze met vector databases en leren wanneer je beter de een of de ander gebruikt. Daarna gaan we praktisch aan de slag: we maken een knowledge graph uit tekstdata, slaan die op in een database en gebruiken hem om relevante info te vinden voor gebruikersvragen. Ook kijken we hoe je deze aanpak kunt uitbreiden naar verschillende soorten data en bestandsformaten, niet alleen platte tekst.

Wil je meer leren over RAG? Lees dan dit artikel over retrieval augmented generation.

Wat is een knowledge graph?

Knowledge graphs representeren informatie in een gestructureerd, onderling verbonden formaat. Ze bestaan uit entiteiten (nodes) en relaties (edges) tussen die entiteiten. Entiteiten kunnen echte objecten, concepten of ideeën voorstellen, terwijl relaties beschrijven hoe die entiteiten verbonden zijn.

Het idee achter knowledge graphs is om na te bootsen hoe mensen de wereld begrijpen en erover redeneren. We slaan informatie niet op in geïsoleerde silo’s; we leggen verbanden tussen verschillende stukjes informatie en vormen zo een rijk, onderling verbonden web van kennis.

Knowledge graphs helpen ons te zien hoe entiteiten verbonden zijn door de relaties tussen verschillende entiteiten duidelijk te tonen. Door deze verbanden te verkennen, kunnen we nieuwe informatie vinden en conclusies trekken die lastig zijn op basis van losse stukjes informatie.

Laten we een voorbeeld bekijken.

Figuur 1: In deze visuele weergave zijn de nodes cirkels en worden de relaties weergegeven als gelabelde pijlen die de nodes verbinden.

Deze knowledge graph legt de arbeidsrelaties vast tussen de personen Sarah en Michael en het bedrijf prismaticAI. In ons voorbeeld hebben we drie nodes:

  • Node 1
    • Type: Persoon
    • Naam: Sarah
  • Node 2
    • Type: Persoon
    • Naam: Michael
  • Node 3
    • Type: Bedrijf
    • Naam: prismaticAI

Kortom, we hebben twee persoon-nodes (Sarah en Michael) en één bedrijfsnode (prismaticAI). Laten we nu kijken naar de relaties (edges) tussen deze nodes:

  • Relatie 1: Sarah --[werkt voor]--> prismaticAI
    • Deze relatie geeft aan dat Sarah, voorgesteld door node 1, een "werkt voor"-relatie heeft met prismaticAI, voorgesteld door node 3. Met andere woorden: Sarah is een werknemer van prismaticAI.
  • Relatie 2: Michael --[werkt voor]--> prismaticAI
    • Net als bij de eerste relatie laat deze zien dat Michael, voorgesteld door node 2, ook een "werkt voor"-relatie heeft met prismaticAI (node 3). Michael is dus ook een werknemer van prismaticAI.

Query’s uitvoeren en traverseren in knowledge graphs

Een van de krachtige aspecten van knowledge graphs is dat je relaties tussen entiteiten kunt bevragen en traverseren om relevante informatie te vinden of nieuwe kennis af te leiden. Laten we bekijken hoe dat werkt met ons voorbeeld.

Eerst bepalen we welke informatie we willen ophalen uit de knowledge graph. Bijvoorbeeld:

Query 1: Waar werkt Sarah?

Om deze vraag te beantwoorden, zoeken we het juiste startpunt in de knowledge graph. In dit geval beginnen we bij de node die Sarah voorstelt.

Vanaf dat startpunt (Sarah’s node) volgen we de uitgaande edge met het label "werkt voor". Deze edge verbindt Sarah’s node met de node die prismaticAI voorstelt. Door deze relatie te traverseren, concluderen we dat Sarah bij prismaticAI werkt.

Antwoord 1: Sarah werkt bij prismaticAI.

Nog een query:

Query 2: Wie werken er bij prismaticAI?

Dit keer beginnen we bij de node die prismaticAI voorstelt.

Vanaf de prismaticAI-node volgen we de "werkt voor"-edges terug. Zo komen we uit bij de nodes die de mensen voorstellen die bij prismaticAI werken. Door de "werkt voor"-relaties in omgekeerde richting te traverseren, zien we dat zowel Sarah als Michael bij prismaticAI werken.

Antwoord 2: Sarah en Michael werken bij prismaticAI.

Nog één voorbeeld!

Query 3: Werkt Michael bij hetzelfde bedrijf als Sarah?

We kunnen beginnen bij de node van Sarah of die van Michael. Laten we bij Sarah beginnen.

We volgen de "werkt voor"-relatie naar de prismaticAI-node.

Daarna controleren we of Michael ook een "werkt voor"-relatie heeft naar dezelfde prismaticAI-node. Omdat zowel Sarah als Michael een "werkt voor"-relatie met de prismaticAI-node hebben, kunnen we concluderen dat ze voor hetzelfde bedrijf werken.

Antwoord 3: Ja, Michael werkt bij hetzelfde bedrijf als Sarah (prismaticAI).

Door de relaties in de knowledge graph te traverseren, kunnen we specifieke stukjes informatie ophalen en de verbanden tussen entiteiten begrijpen. Knowledge graphs kunnen veel complexer worden, met talloze nodes en relaties, waardoor complexe, reële kennis gestructureerd en onderling verbonden kan worden weergegeven.

Voordelen van knowledge graphs in RAG-applicaties

RAG-applicaties combineren informatie-opvraging en natuurlijke taalgeneratie om relevante en samenhangende antwoorden te geven op vragen of prompts. Knowledge graphs bieden hierbij diverse voordelen en zijn daardoor bijzonder geschikt. Dit zijn de belangrijkste pluspunten:

Gestructureerde kennisrepresentatie

Zoals we zagen, representeren knowledge graphs informatie gestructureerd, met entiteiten (nodes) en hun relaties (edges). Deze gestructureerde weergave maakt het makkelijker om relevante informatie op te halen voor een bepaalde vraag of taak, vergeleken met ongestructureerde tekstdata.

In ons voorbeeld kunnen we eenvoudig achterhalen wie er bij prismaticAI werken door de "werkt voor"-relaties te volgen.

Contextueel begrip

Knowledge graphs leggen relaties tussen entiteiten vast, wat een dieper begrip van de context mogelijk maakt. Dat contextuele begrip is cruciaal om samenhangende en relevante antwoorden te genereren in RAG-applicaties.

Terug naar ons voorbeeld: inzicht in de "werkt voor"-relatie tussen Sarah, Michael en prismaticAI stelt een RAG-applicatie in staat om contextueel relevantere antwoorden te geven over hun dienstverband.

Inferentieel redeneren

Door relaties in een knowledge graph te traverseren, kunnen RAG-applicaties inferenties maken en nieuwe kennis afleiden die niet expliciet is vermeld. Deze mogelijkheid tot redeneren verbetert de kwaliteit en volledigheid van de gegenereerde antwoorden.

Door de relaties te traverseren kan een RAG-applicatie bijvoorbeeld afleiden dat Sarah en Michael bij hetzelfde bedrijf werken, ook al staat dat niet direct vermeld.

Kennisintegratie

Knowledge graphs kunnen informatie uit meerdere bronnen integreren, waardoor RAG-applicaties gebruikmaken van diverse en complementaire kennisbanken. Deze integratie leidt vaak tot vollediger en beter onderbouwde antwoorden.

We zouden in ons voorbeeld extra informatie kunnen toevoegen over bedrijven, medewerkers en hun rollen uit verschillende bronnen, voor een vollediger beeld bij het genereren van antwoorden.

Uitlegbaarheid en transparantie

Knowledge graphs bieden een transparante weergave van de kennis die is gebruikt om antwoorden te genereren. Die transparantie is cruciaal om de redenering achter de output te kunnen uitleggen, wat belangrijk is in veel toepassingen, zoals vraag-antwoord-systemen.

De uitleg bij antwoord 3 in ons voorbeeld zou kunnen zijn: Ja, Michael werkt bij hetzelfde bedrijf als Sarah. Ik kwam tot deze conclusie door te constateren dat Sarah bij prismaticAI werkt en vervolgens te verifiëren dat Michael ook een 'werkt voor'-relatie met prismaticAI heeft. Omdat ze beiden deze relatie met dezelfde bedrijfsentiteit hebben, kan ik afleiden dat ze bij hetzelfde bedrijf werken.

Deze transparantie in het redeneerproces helpt gebruikers en ontwikkelaars te begrijpen hoe de RAG-applicatie tot haar antwoord komt, in plaats van het als een black box te zien. Het vergroot ook het vertrouwen in het systeem, omdat het besluitvormingsproces helder is en kan worden gecontroleerd aan de hand van de knowledge graph.

Als er inconsistenties of ontbrekende informatie in de knowledge graph zitten, kan de uitleg bovendien helpen die te identificeren en op te lossen, wat leidt tot nauwkeurigere en completere antwoorden.

Met knowledge graphs kunnen RAG-applicaties accuratere, helderdere en beter te begrijpen antwoorden geven. Dat maakt ze nuttig voor uiteenlopende taken in natural language processing.

Knowledge graphs versus vector databases

Bij het bouwen van RAG-applicaties kom je vaak twee benaderingen tegen: knowledge graphs en vector databases. Beide worden gebruikt om informatie te representeren en op te halen, maar ze verschillen in hun onderliggende datastructuren en in hoe ze met informatie omgaan.

Dit zijn de belangrijkste verschillen tussen deze twee benaderingen:

Kenmerk

Knowledge graphs

Vector databases

Datarepresentatie

Entiteiten (nodes) en relaties (edges) tussen entiteiten, die samen een graafstructuur vormen.

Hoogdimensionale vectoren, elk een stukje informatie representerend (bijv. document, zin).

Ophaalmechanismen

Traverseren van de graafstructuur en het volgen van relaties tussen entiteiten. Maakt inferentie en afleiding van nieuwe kennis mogelijk.

Vectorsimilariteit op basis van een similariteitsmaat (bijv. cosinus-similariteit). Geeft de meest vergelijkbare vectoren en bijbehorende informatie terug.

Interpretatie

Voor mensen interpreteerbare representatie van kennis. Graafstructuur en gelabelde relaties maken verbindingen tussen entiteiten duidelijk.

Minder goed interpreteerbaar voor mensen door hoogdimensionale numerieke representaties. Moeilijk om relaties of de redenering achter opgehaalde informatie direct te begrijpen.

Kennisintegratie

Faciliteert integratie door entiteiten en relaties in één uniforme graafstructuur te representeren. Naadloze integratie als entiteiten en relaties goed zijn gemapt.

Lastiger. Vereist technieken zoals vector space alignment of ensemblemethoden om informatie te combineren. Zorgen voor vectorcompatibiliteit is niet triviaal.

Inferentieel redeneren

Maakt inferentieel redeneren mogelijk door de graaf te traverseren en relaties tussen entiteiten te benutten. Ontdekt impliciete verbanden en leidt nieuwe inzichten af.

Beperkter. Vertrouwt op vectorsimilariteit en kan impliciete relaties of inferenties missen. Kan soortgelijke informatie vinden, maar geen complexe relaties uit knowledge graphs achterhalen.

Zowel knowledge graphs als vector databases hebben hun sterke punten en use-cases; de keuze hangt af van de eisen van je applicatie. Knowledge graphs blinken uit in het representeren van en redeneren over gestructureerde kennis, terwijl vector databases geschikt zijn voor taken die sterk leunen op semantische similariteit en informatieopvraging op basis van vectorrepresentaties.

Meer weten over vector databases? Lees deze introductie tot vector databases voor machine learning. Bekijk ook de vijf populairste vector databases.

Hoe implementeer je knowledge graphs voor RAG-applicaties

In deze sectie laten we zien hoe je een knowledge graph implementeert om het taalgeneratieproces voor een RAG-applicatie te versterken. 

We behandelen de volgende stappen:

  • Tekstdata laden en preprocessen.
  • Een taalmodel initialiseren en een knowledge graph extraheren.
  • De knowledge graph opslaan in een database voor persistentie en query’s.
  • Relevante kennis uit de graaf ophalen op basis van gebruikersvragen.
  • Antwoorden genereren door de opgehaalde kennis te combineren met het taalmodel.

Aan het einde van deze sectie begrijp je hoe je knowledge graphs in RAG-applicaties implementeert, zodat je intelligentere en contextbewuste taalmodellen kunt bouwen.

Vereisten

Zorg ervoor dat je het volgende hebt geïnstalleerd voordat je begint:

  • Python 3.7 of hoger
  • LangChain-bibliotheek (pip install langchain)
  • LlamaIndex-bibliotheek (pip install llama-index)
  • Neo4j-database (of een andere compatibele graafdatabase)

Stap 1: Tekstdata laden en preprocessen

De eerste stap is het laden en preprocessen van de tekstdata waaruit we de knowledge graph gaan extraheren. In dit voorbeeld gebruiken we een tekstfragment over een technologiebedrijf genaamd prismaticAI, zijn medewerkers en hun rollen.

from langchain.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter

# Load text data
text = """Sarah is an employee at prismaticAI, a leading technology company based in Westside Valley. She has been working there for the past three years as a software engineer.
Michael is also an employee at prismaticAI, where he works as a data scientist. He joined the company two years ago after completing his graduate studies.
prismaticAI is a well-known technology company that specializes in developing cutting-edge software solutions and artificial intelligence applications. The company has a diverse workforce of talented individuals from various backgrounds.
Both Sarah and Michael are highly skilled professionals who contribute significantly to prismaticAI's success. They work closely with their respective teams to develop innovative products and services that meet the evolving needs of the company's clients."""

loader = TextLoader(text)
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=200, chunk_overlap=20)
texts = text_splitter.split_documents(documents)

We importeren eerst de benodigde klassen uit LangChain: TextLoader en CharacterTextSplitter. TextLoader laadt de tekstdata, terwijl CharacterTextSplitter de tekst in kleinere stukken hakt voor efficiëntere verwerking.

Vervolgens definiëren we de tekstdata als een multi-line stringvariabele text.

Daarna gebruiken we TextLoader om de tekstdata rechtstreeks uit de variabele te laden. De methode loader.load() retourneert een lijst van Document-objecten, elk met een chunk van de tekst.

Om de tekst in kleinere, beter hanteerbare stukken te splitsen, maken we een instantie van CharacterTextSplitter met een chunk_size van 200 tekens en een chunk_overlap van 20 tekens. De parameter chunk_overlap zorgt voor wat overlap tussen aangrenzende stukken, wat kan helpen om context te behouden tijdens het extraheren van kennis.

Tot slot gebruiken we de methode split_documents van CharacterTextSplitter om de Document-objecten in kleinere stukken te splitsen. Die worden opgeslagen in de variabele texts als een lijst van Document-objecten.

Door de tekstdata op deze manier te preprocessen, maken we hem klaar voor de volgende stap, waarin we een taalmodel initialiseren en gebruiken om een knowledge graph uit de tekstchunks te extraheren.

Stap 2: Taalmodel initialiseren en knowledge graph extraheren

Na het laden en preprocessen van de tekstdata initialiseren we een taalmodel en gebruiken dat om een knowledge graph uit de tekstchunks te halen. In dit voorbeeld gebruiken we het OpenAI-taalmodel via LangChain.

from langchain.llms import OpenAI
from langchain.transformers import LLMGraphTransformer
import getpass
import os

# Load environment variable for OpenAI API key
os.environ["OPENAI_API_KEY"] = getpass.getpass()

# Initialize LLM
llm = OpenAI(temperature=0)

# Extract Knowledge Graph
llm_transformer = LLMGraphTransformer(llm=llm)
graph_documents = llm_transformer.convert_to_graph_documents(texts)

Eerst importeren we de benodigde klassen uit LangChain: OpenAI en LLMGraphTransformer. OpenAI is een wrapper voor het OpenAI-taalmodel, dat we gebruiken om de knowledge graph te extraheren. LLMGraphTransformer helpt om tekstdata om te zetten naar een knowledge graph-representatie.

Daarna laden we de OpenAI API-sleutel vanuit een omgevingsvariabele. Dit is een best practice om gevoelige gegevens niet hard te coderen in je code.

Vervolgens initialiseren we een instantie van het OpenAI-taalmodel met een temperatuur van 0. De temperatuur bepaalt de mate van willekeur in de output; lagere waarden geven deterministischere antwoorden.

Na het initialiseren van het taalmodel maken we een instantie van LLMGraphTransformer en geven het geïnitialiseerde llm-object door. De klasse LLMGraphTransformer zet de tekstchunks (texts) om in een knowledge graph-representatie.

Tot slot roepen we de methode convert_to_graph_documents van LLMGraphTransformer aan met de lijst texts. Deze methode gebruikt het taalmodel om de tekstchunks te analyseren en relevante entiteiten, relaties en andere gestructureerde informatie te extraheren, die vervolgens als knowledge graph worden weergegeven. De resulterende knowledge graph wordt opgeslagen in de variabele graph_documents.

We hebben nu een taalmodel geïnitialiseerd en gebruikt om een knowledge graph uit de tekstdata te halen. In de volgende stap slaan we de knowledge graph op in een database voor persistentie en query’s.

Stap 3: Knowledge graph opslaan in een database

Nadat we de knowledge graph uit de tekstdata hebben geëxtraheerd, is het belangrijk om deze persistent en doorzoekbaar op te slaan. In deze tutorial gebruiken we Neo4j om de knowledge graph op te slaan. 

from langchain.graph_stores import Neo4jGraphStore

# Store Knowledge Graph in Neo4j
graph_store = Neo4jGraphStore(url="neo4j://your_neo4j_url", username="your_username", password="your_password")
graph_store.write_graph(graph_documents)

We importeren eerst de klasse Neo4jGraphStore uit LangChain. Deze klasse biedt een handige interface om met een Neo4j-database te werken en knowledge graphs op te slaan.

Vervolgens maken we een instantie van Neo4jGraphStore door de benodigde verbindingsgegevens op te geven: de Neo4j-database-URL, gebruikersnaam en wachtwoord. Vervang "your_neo4j_url", "your_username" en "your_password" door de juiste waarden voor jouw Neo4j-instantie.

Tot slot roepen we de methode write_graph aan op de graph_store-instantie en geven we de lijst graph_documents door die we in de vorige stap hebben verkregen. Deze methode serialiseert de knowledge graph en schrijft die naar de Neo4j-database.

Door de knowledge graph in Neo4j op te slaan, zorgen we ervoor dat hij persistent is en eenvoudig kan worden bevraagd en opgehaald wanneer nodig. De graafstructuur van Neo4j maakt efficiënte representatie en traversering mogelijk van de complexe relaties en entiteiten in de knowledge graph.

In de volgende stap zetten we de componenten klaar om kennis uit de graaf op te halen en antwoorden te genereren met de opgehaalde context.

Belangrijk: hoewel we in deze tutorial Neo4j gebruiken als graafdatabase, ondersteunt LangChain ook andere graafdatabases, zoals Amazon Neptune en TinkerPop-compatibele databases zoals Gremlin Server. Je kunt Neo4jGraphStore vervangen door de juiste implementatie voor jouw database.

Stap 4: Kennis ophalen voor RAG

Nu we de knowledge graph in een database hebben opgeslagen, kunnen we de componenten inrichten om relevante kennis op te halen uit de graaf op basis van gebruikersvragen en om antwoorden te genereren met de opgehaalde context. Dit is de kernfunctionaliteit van een RAG-applicatie.

from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.retrievers import KnowledgeGraphRAGRetriever
from llama_index.core.response_synthesis import ResponseSynthesizer

# Retrieve Knowledge for RAG
graph_rag_retriever = KnowledgeGraphRAGRetriever(storage_context=graph_store.storage_context, verbose=True)
query_engine = RetrieverQueryEngine.from_args(graph_rag_retriever)

Eerst importeren we de benodigde klassen uit LlamaIndex: RetrieverQueryEngine, KnowledgeGraphRAGRetriever en ResponseSynthesizer.

RetrieverQueryEngine is een query-engine die een retriever gebruikt om relevante context op te halen uit een gegevensbron (in ons geval de knowledge graph) en daarna een antwoord te synthetiseren met die context.

KnowledgeGraphRAGRetriever is een gespecialiseerde retriever die relevante informatie uit een knowledge graph in een database kan ophalen.

ResponseSynthesizer genereert het uiteindelijke antwoord door de opgehaalde context te combineren met een taalmodel.

Vervolgens maken we een instantie van KnowledgeGraphRAGRetriever door de storage_context van onze graph_store-instantie door te geven. Deze storage_context bevat de informatie om verbinding te maken met en query’s uit te voeren op de Neo4j-database waarin we de knowledge graph hebben opgeslagen. We zetten ook verbose=True aan voor gedetailleerde logging tijdens het ophalen.

Daarna initialiseren we een RetrieverQueryEngine via de methode from_args en geven onze instantie graph_rag_retriever door. Deze query-engine handelt het hele proces af: relevante context uit de knowledge graph ophalen en op basis daarvan een antwoord genereren.

Met deze componenten klaar kunnen we de knowledge graph bevragen en antwoorden genereren met de opgehaalde context. In de volgende stap zie je hoe dat in de praktijk werkt.

Stap 5: De knowledge graph bevragen en een antwoord genereren

Tot slot kunnen we de knowledge graph bevragen en antwoorden genereren met de opgehaalde context.

def query_and_synthesize(query):
    retrieved_context = query_engine.query(query)
    response = response_synthesizer.synthesize(query, retrieved_context)
    print(f"Query: {query}")
    print(f"Answer: {response}\n")

# Initialize the ResponseSynthesizer instance
response_synthesizer = ResponseSynthesizer(llm)

# Query 1
query_and_synthesize("Where does Sarah work?")

# Query 2
query_and_synthesize("Who works for prismaticAI?")

# Query 3
query_and_synthesize("Does Michael work for the same company as Sarah?")

In dit voorbeeld definiëren we drie verschillende vragen over de medewerkers en het bedrijf uit de tekstdata. Voor elke vraag gebruiken we de query_engine om de relevante context uit de knowledge graph op te halen, maken we een instantie van ResponseSynthesizer en roepen we de methode synthesize aan met de vraag en de opgehaalde context.

De ResponseSynthesizer gebruikt het taalmodel en de opgehaalde context om een definitief antwoord te genereren, dat vervolgens in de console wordt afgedrukt, overeenkomstig met de antwoorden in het eerste deel van dit artikel.

Knowledge graphs in praktijksituaties

Hoewel de tutorial laat zien hoe je een knowledge graph gebruikt voor RAG met relatief eenvoudige tekst, gaan praktijksituaties vaak over complexere en diversere datasets. Bovendien kan de input in allerlei bestandsformaten komen, niet alleen platte tekst. In deze sectie bekijken we hoe je de RAG-applicatie op basis van een knowledge graph kunt uitbreiden om met zulke scenario’s om te gaan.

Omgaan met grote en diverse datasets

Naarmate de omvang en complexiteit van de inputdata toenemen, kan het extraheren van een knowledge graph uitdagender worden. Enkele strategieën:

  • Gedistribueerde constructie van de knowledge graph: Voor zeer grote datasets kun je het bouwproces paralleliseren en over meerdere machines of een cluster verdelen. Door de dataset te partitioneren en parallel knowledge graphs te extraheren, kun je deze later samenvoegen tot één uniforme graaf.
  • Incrementele updates van de knowledge graph: In plaats van de hele graaf telkens opnieuw op te bouwen wanneer er nieuwe data binnenkomt, kun je incrementeel updaten. Je voegt nieuwe informatie toe en behoudt de bestaande kennis en relaties.
  • Domeinspecifieke extractie: Voor datasets die meerdere domeinen of onderwerpen beslaan, kan het zinvol zijn domeinspecifieke extractiepijplijnen te ontwikkelen. Die sluit je aan op de terminologie, entiteiten en relaties van elk domein, wat de nauwkeurigheid en volledigheid verbetert.
  • Fusie en integratie van knowledge graphs: Als je met data uit meerdere bronnen werkt, moeten de geëxtraheerde grafen mogelijk worden gefuseerd of geïntegreerd tot één representatie. Daarbij horen technieken zoals entiteitenresolutie, relatie-alignering en conflictoplossing om consistentie te waarborgen en redundantie te vermijden.

Omgaan met verschillende bestandstypen

In de praktijk kan data in allerlei formaten komen, zoals PDF’s, Word-documenten, spreadsheets of zelfs gestructureerde data zoals JSON of XML. Om met die bestandstypen om te gaan, kun je het volgende doen:

  • Bestandsconversie: Er zijn veel libraries en tools om verschillende bestandsformaten naar platte tekst om te zetten. Zo kun je libraries zoals pdfplumber of tika gebruiken om tekst uit PDF’s te halen, of python-docx voor Word-documenten.
  • Aangepaste file loaders: LangChain biedt een DocumentLoader-interface om aangepaste loaders voor specifieke bestandstypen te maken. Je kunt je eigen loader implementeren door DocumentLoader te subklassen en de methode load te overschrijven voor het gewenste formaat.
  • Gestructureerde data verwerken: Voor formaten zoals JSON of XML kun je libraries als pandas of lxml gebruiken om de relevante informatie te parsen en te extraheren voordat je deze aan de extractiepijplijn van de knowledge graph doorgeeft.
  • Multimodale knowledge graph-extractie: Soms bevat de input multimodale data, met zowel tekst als bijvoorbeeld afbeeldingen of video’s. In zulke gevallen kun je technieken voor multimodale extractie verkennen, waarbij je tekstuele extractie combineert met computervisie of andere modality-specifieke methoden.

Met deze strategieën kun je de RAG-applicatie op basis van een knowledge graph uitbreiden naar complexere en diversere datasets en een breder scala aan bestandstypen. 

Belangrijk om te onthouden: naarmate de complexiteit van de input toeneemt, vraagt het extraheren van een knowledge graph vaker om domeinspecifieke afstemming en verfijning voor accurate en betrouwbare resultaten.

Uitdagingen

Het opzetten van knowledge graphs voor RAG in de echte wereld kan complex zijn en kent verschillende uitdagingen. Dit zijn enkele belangrijke punten:

Constructie van de knowledge graph

Het bouwen van een hoogwaardige knowledge graph is complex en tijdrovend en vereist aanzienlijke domeinkennis en inspanning. Entiteiten, relaties en feiten uit diverse databronnen extraheren en integreren in één coherente graaf is uitdagend, zeker bij grote en diverse datasets. Het vereist begrip van het domein, het identificeren van relevante informatie en het zo structureren dat relaties en semantiek accuraat worden vastgelegd.

Dataintegratie en interoperabiliteit

RAG-applicaties moeten vaak data integreren uit meerdere heterogene bronnen, elk met eigen structuur, formaat en semantiek. Consistentie waarborgen, conflicten oplossen en entiteiten en relaties mappen over bronnen heen is niet triviaal. Het vraagt om zorgvuldige opschoning, transformatie en mapping zodat de knowledge graph de informatie uit de verschillende bronnen correct weergeeft.

Onderhoud en evolutie van de knowledge graph

Knowledge graphs zijn niet statisch. Ze moeten continu worden bijgewerkt en onderhouden zodra nieuwe informatie beschikbaar komt of bestaande informatie verandert. De graaf up-to-date en consistent houden met veranderende databronnen kan veel middelen vergen. Dit omvat het monitoren van wijzigingen, het identificeren van relevante updates en het doorvoeren daarvan in de graaf met behoud van integriteit en consistentie.

Schaalbaarheid en performance

Als de knowledge graph in omvang en complexiteit groeit, wordt efficiënte opslag, retrieval en bevraging steeds uitdagender. Schaalbaarheids- en prestatieproblemen kunnen optreden, zeker bij grootschalige RAG-applicaties met hoge queryvolumes. Optimalisatie van opslag, indexering en queryverwerking is dan cruciaal om acceptabele prestaties te behouden.

Querycomplexiteit en redeneren

Hoewel knowledge graphs uitblinken in het representeren van complexe relaties en multi-hop-redeneren, kan het formuleren en uitvoeren van complexe query’s die daarvan gebruikmaken lastig zijn. Efficiënte query- en redeneeralgoritmen ontwikkelen is een actief onderzoeksgebied. Inzicht in de querytaal en redeneercapaciteiten van het systeem is belangrijk om het volledige potentieel te benutten.

Gebrek aan standaardisatie

Er ontbreken breed geaccepteerde standaarden voor het representeren en bevragen van knowledge graphs, wat kan leiden tot interoperabiliteitsproblemen en vendor lock-in. Verschillende systemen gebruiken verschillende datamodellen, querytalen en API’s, waardoor overstappen of integreren lastiger wordt. Het adopteren of ontwikkelen van standaarden kan interoperabiliteit bevorderen en vendor lock-in verminderen.

Uitlegbaarheid en transparantie

Hoewel knowledge graphs uitlegbare en transparante redenering mogelijk maken, is het niet altijd eenvoudig om het redeneerproces voor eindgebruikers begrijpelijk te maken, zeker bij complexe query’s of redeneerpaden. Gebruiksvriendelijke interfaces en toelichtingen die het proces en de aannames duidelijk communiceren zijn belangrijk voor vertrouwen en adoptie.

Domeinspecifieke uitdagingen

Afhankelijk van het domein en de toepassing kunnen er extra uitdagingen zijn, zoals omgaan met domeinspecifieke terminologie, ontologieën of dataformaten. In de medische sector bijvoorbeeld voegen complexe terminologie, coderingssystemen en privacyvraagstukken extra lagen complexiteit toe aan het opzetten en gebruiken van een knowledge graph.

Ondanks deze uitdagingen bieden knowledge graphs grote voordelen voor RAG-applicaties, vooral voor het representeren van gestructureerde kennis, het mogelijk maken van complex redeneren en het leveren van uitlegbare en transparante resultaten. Door deze uitdagingen aan te pakken met doordacht ontwerp, integratiestrategieën en efficiënte queryverwerking, kun je succesvol RAG-applicaties op basis van knowledge graphs implementeren.

Conclusie

In deze tutorial hebben we de kracht van knowledge graphs verkend om accuratere, informatievere en contextueel relevante antwoorden te creëren. We zijn begonnen met de basis van knowledge graphs en hun rol in RAG-applicaties. Daarna hebben we een hands-on voorbeeld doorlopen: een knowledge graph extraheren uit tekstdata, opslaan in een Neo4j-database en gebruiken om relevante context op te halen voor gebruikersvragen. Tot slot lieten we zien hoe je met die context antwoorden genereert op basis van de gestructureerde kennis in de graaf.

Wil je meer leren over AI en LLM’s? Bekijk dan deze vaardighedentraject van zes cursussen over AI Fundamentals.

Hopelijk vond je deze tutorial nuttig en leuk. Tot de volgende keer!

Happy coding!

FAQs

Kan ik Cypher gebruiken om de knowledge graph te bevragen?

Ja, je kunt Cypher gebruiken, de querytaal van Neo4j, om de knowledge graph direct te bevragen. Met Cypher kun je complexe query’s en bewerkingen op de graafdata uitvoeren. Hoewel we in de tutorial de libraries LangChain en LlamaIndex gebruiken om query’s af te handelen, kun je voor geavanceerdere of aangepaste query’s altijd terugvallen op Cypher.

Hoe kan ik de knowledge graph visualiseren?

Een knowledge graph visualiseren helpt je de relaties en entiteiten in je data beter te begrijpen. Tools zoals Neo4j Bloom, Gephi of zelfs maatwerkvisualisaties met D3.js kun je gebruiken om interactieve visualisaties van je knowledge graph te maken. Met deze tools kun je de graaf visueel verkennen, wat het makkelijker maakt om patronen en inzichten te vinden.

Kan ik deze knowledge graph integreren met andere AI-modellen?

Je kunt de knowledge graph integreren met verschillende AI-modellen, zoals aanbevelingssystemen, sentimentanalysemodellen of zelfs computervisiemodellen. Zo kun je de knowledge graph bijvoorbeeld gebruiken om context te bieden aan een aanbevelingssysteem of om het begrip van tekst in een sentimentanalysemodel te verbeteren. De flexibiliteit van knowledge graphs maakt ze een krachtig hulpmiddel om uiteenlopende AI-toepassingen te verrijken.

Dr Ana Rojo-Echeburúa

Auteur

Dr Ana Rojo-Echeburúa

Ana Rojo Echeburúa is een AI- en dataspecialist met een PhD in Toegepaste Wiskunde. Ze houdt ervan om data om te zetten in bruikbare inzichten en heeft ruime ervaring in het aansturen van technische teams. Ana werkt graag nauw samen met klanten om hun bedrijfsproblemen op te lossen en innovatieve AI-oplossingen te creëren. Ze staat bekend om haar probleemoplossend vermogen en heldere communicatie, en is gepassioneerd door AI, vooral generatieve AI. Ana zet zich in voor continue ontwikkeling en ethische AI, en voor het vereenvoudigen van complexe vraagstukken en het op een toegankelijke manier uitleggen van technologie.

Onderwerpen

Gerelateerd