Avancerad RAG: LongRAG, Self-RAG och GraphRAG förklarat

LongRAG, Self-RAG, GraphRAG - Nästa generations tekniker

Sidinnehåll

Retrieval-Augmented Generation (RAG) har utvecklats långt bortom enkel vektorsimilitetssökning. LongRAG, Self-RAG och GraphRAG representerar den senaste utvecklingen inom dessa möjligheter.

Moderna RAG-system måste hantera enorma dokument, förstå komplexa entitetsrelationer och mycket mer.

a-pirate-captain Det här trevliga bilden är genererad av AI-modellen Flux 1 dev.

Utvecklingen bortom grundläggande RAG

Traditionella RAG-system följer ett enkelt mönster: dela upp dokument i bitar, kodning av dem till vektorer, hämta liknande bitar via kosinuslikhet och mata dem till en LLM. Även om det är effektivt för många användningsområden, har denna metod svårt med tre kritiska scenarier:

  1. Långväga beroenden: Viktig kontext kan sträcka sig över tusentals token över flera bitar
  2. Hämtningssäkerhet: Systemet har inget sätt att bedöma om hämtat innehåll verkligen är relevant
  3. Komplexitetsrelationer: Vektorsimilitet kan inte fånga invecklade samband mellan entiteter

Avancerade RAG-varianter hanterar dessa begränsningar med specialiserade arkitekturer anpassade för specifika utmaningar.

LongRAG: Erövringen av utökad kontext

Arkitekturoversikt

LongRAG omdefinierar grundläggande strategin för uppdelning genom att utnyttja LLMs med utökade kontextfönster (32K, 100K eller till och med 1M token). Istället för att dela upp dokument i små 512-token-bitar använder LongRAG ett hierarkiskt tillvägagångssätt:

Dokumentnivåskodning: Hela dokumentet (eller mycket stora avsnitt) bearbetas som en enda enhet. En dokumentnivåskodning fångar den övergripande semantiska betydelsen, samtidigt som hela texten bevaras för efterföljande bearbetning.

Minimal fragmentering: När uppdelning är nödvändig använder LongRAG mycket större bitar (4K-8K token) med betydande överlappning (20-30%). Detta bevarar berättelsens flöde och minskar kontextfragmentering.

Kontextsammanställning: Vid hämtningstid returnerar LongRAG hela dokument eller stora sammanhängande avsnitt istället för spridda fragment. LLM:n får kontinuerlig kontext som bevarar strukturella och semantiska samband.

Implementeringsstrategi

Här är en konceptuell implementering med Python och moderna kodningsmodeller:

from typing import List, Dict
import numpy as np

class LongRAGRetriever:
    def __init__(self, model, chunk_size=8000, overlap=1600):
        self.model = model
        self.chunk_size = chunk_size
        self.overlap = overlap
        self.doc_embeddings = []
        self.documents = []

    def create_long_chunks(self, text: str) -> List[str]:
        """Skapa överlappande stora bitar"""
        chunks = []
        start = 0
        while start < len(text):
            end = start + self.chunk_size
            chunk = text[start:end]
            chunks.append(chunk)
            start += (self.chunk_size - self.overlap)
        return chunks

    def index_document(self, doc: str, metadata: Dict):
        """Indexera dokument med hierarkisk kodning"""
        # Kodning av hela dokumentet
        doc_embedding = self.model.embed(doc)

        # Skapa stora bitar med överlappning
        chunks = self.create_long_chunks(doc)
        chunk_embeddings = [self.model.embed(c) for c in chunks]

        self.doc_embeddings.append({
            'doc_id': len(self.documents),
            'doc_embedding': doc_embedding,
            'chunk_embeddings': chunk_embeddings,
            'chunks': chunks,
            'full_text': doc,
            'metadata': metadata
        })
        self.documents.append(doc)

    def retrieve(self, query: str, top_k: int = 3) -> List[Dict]:
        """Hämta relevant långformigt innehåll"""
        query_embedding = self.model.embed(query)

        # Poängsättning på dokumentnivå först
        doc_scores = [
            np.dot(query_embedding, doc['doc_embedding'])
            for doc in self.doc_embeddings
        ]

        # Hämta toppdokument
        top_doc_indices = np.argsort(doc_scores)[-top_k:][::-1]

        results = []
        for idx in top_doc_indices:
            doc_data = self.doc_embeddings[idx]

            # För varje dokument, hitta bästa bitar
            chunk_scores = [
                np.dot(query_embedding, emb)
                for emb in doc_data['chunk_embeddings']
            ]
            best_chunk_idx = np.argmax(chunk_scores)

            # Returnera utökad kontext runt bästa bit
            context_chunks = self._get_extended_context(
                doc_data['chunks'],
                best_chunk_idx
            )

            results.append({
                'text': ''.join(context_chunks),
                'score': doc_scores[idx],
                'metadata': doc_data['metadata']
            })

        return results

    def _get_extended_context(self, chunks: List[str],
                             center_idx: int) -> List[str]:
        """Hämta utökad kontext runt relevant bit"""
        start = max(0, center_idx - 1)
        end = min(len(chunks), center_idx + 2)
        return chunks[start:end]

Användningsområden och prestanda

LongRAG utmärker sig i scenarier där kontext är viktig:

  • Analys av juridiska dokument: Kontrakt och juridiska handlingar har ofta beroenden som sträcker sig över flera sidor
  • Hämtning av forskningsartiklar: Förståelse av metodik kräver sammanhängande avsnitt, inte isolerade stycken
  • Kodrepositorier: Funktioner och klasser måste förstås inom sin modulkontxt

Prestandegenskaper:

  • Latens: Högre på grund av bearbetning av stora bitar (2-5 gånger långsammare än standard RAG)
  • Noggrannhet: 15-25% förbättring på långformiga fråga-svar-bänkar
  • Minne: Kräver 3-4 gånger mer minne för kontextfönster

Self-RAG: Reflekterande hämtning

Grundläggande principer

Self-RAG introducerar en metakognitiv nivå till RAG-system. Istället för att blindt hämtning och generering, reflekterar systemet aktivt över sina egna processer genom specialreflektionstoken:

Hämtningstoken: Bestämmer om hämtning är nödvändig för en given fråga Relevanstoken: Bedömer om hämtade dokument är relevanta Stödtoken: Kontrollerar om det genererade svaret stöds av det hämtade innehållet Kritiktoken: Bedömer den övergripande kvaliteten på det genererade svaret

Arkitekturkomponenter

Self-RAG-arkitekturen består av tre sammanvävda faser:

class SelfRAGSystem:
    def __init__(self, retriever, generator, critic):
        self.retriever = retriever
        self.generator = generator
        self.critic = critic

    def generate_with_reflection(self, query: str,
                                 max_iterations: int = 3):
        """Generera svar med självreflektion"""

        # Fas 1: Besluta om hämtning behövs
        retrieve_decision = self.critic.should_retrieve(query)

        if not retrieve_decision:
            # Direkt generering utan hämtning
            return self.generator.generate(query)

        # Fas 2: Hämta och bedöma relevans
        retrieved_docs = self.retriever.retrieve(query)
        relevant_docs = []

        for doc in retrieved_docs:
            relevance_score = self.critic.assess_relevance(
                query, doc
            )
            if relevance_score > 0.7:  # Tröskelvärde
                relevant_docs.append(doc)

        if not relevant_docs:
            # Fallback till generering utan hämtning
            return self.generator.generate(query)

        # Fas 3: Generera och verifiera stöd
        best_answer = None
        best_score = -1

        for _ in range(max_iterations):
            # Generera kandidatsvar
            answer = self.generator.generate(
                query, context=relevant_docs
            )

            # Bedöma stöd och kvalitet
            support_score = self.critic.check_support(
                answer, relevant_docs
            )
            quality_score = self.critic.assess_quality(answer)

            total_score = 0.6 * support_score + 0.4 * quality_score

            if total_score > best_score:
                best_score = total_score
                best_answer = answer

            # Tidig avslutning om hög kvalitet uppnås
            if total_score > 0.9:
                break

        return {
            'answer': best_answer,
            'confidence': best_score,
            'sources': relevant_docs,
            'reflections': {
                'retrieved': retrieve_decision,
                'relevance': len(relevant_docs),
                'support': support_score
            }
        }

Träning av reflektionmekanismer

Self-RAG kräver träning av kritikerkomponenten för att göra tillförlitliga bedömningar. Detta innebär vanligtvis:

  1. Superviserad finjustering på dataset med relevansbedömningar
  2. Förstärkningsinlärning med belöningar för korrekta förutsägelser
  3. Kontrastinlärning för att skilja mellan stödda och icke-stödda påståenden

Reflektionstoken kan implementeras som:

  • Specialtoken i vokabulären (som [RETRIEVE], [RELEVANT])
  • Separata klassificeringshuvuden på modellen
  • Externa kritikermodeller (ensemble-tillvägagångssätt)

Produktionsöverväganden

När Self-RAG implementeras i produktionssystem:

Latensavvägningar: Varje reflektionsteg lägger till 20-40% inferensöverhead. Balansera noggrannhet med svarstidskrav.

Konfidensgränser: Justera reflektionströsklar baserat på ditt användningsområde. Juridiska eller medicinska applikationer kräver högre konfidens än allmänna chattbotar.

Övervakning: Följ reflektionsbeslut för att identifiera mönster. Om hämtning sällan behövs kan du dra nytta av en enklare arkitektur.

GraphRAG: Knowledge Graph-Enhanced Retrieval

Konceptuell grund

GraphRAG omvandlar hämtningsproblemet från vektorsimilitet till graftraversering. Istället för att hitta semantiskt liknande textsegment identifierar GraphRAG relevanta delgrafer av sammanhängande entiteter och relationer.

Entitetsextraktion: Identifiera namngivna entiteter, begrepp och deras typer Relationskartläggning: Extrahera relationer mellan entiteter (temporala, kausala, hierarkiska) Grafkonstruktion: Bygg en kunskapsgraf med entiteter som noder och relationer som kanter Delgrafhämtning: Ge en fråga, hitta relevanta sammanhängande delgrafer

Grafkonstruktionspipeline

Att bygga en kunskapsgraf från ostrukturerad text innebär flera steg:

class GraphRAGBuilder:
    def __init__(self, entity_extractor, relation_extractor):
        self.entity_extractor = entity_extractor
        self.relation_extractor = relation_extractor
        self.graph = NetworkGraph()

    def build_graph(self, documents: List[str]):
        """Bygg kunskapsgraf från dokument"""
        for doc in documents:
            # Extrahera entiteter
            entities = self.entity_extractor.extract(doc)

            # Lägg till entiteter som noder
            for entity in entities:
                self.graph.add_node(
                    entity['text'],
                    entity_type=entity['type'],
                    context=entity['surrounding_text']
                )

            # Extrahera relationer
            relations = self.relation_extractor.extract(
                doc, entities
            )

            # Lägg till relationer som kanter
            for rel in relations:
                self.graph.add_edge(
                    rel['source'],
                    rel['target'],
                    relation_type=rel['type'],
                    confidence=rel['score'],
                    evidence=rel['text_span']
                )

    def enrich_graph(self):
        """Lägg till härledda relationer och metadata"""
        # Beräkna nodviktighet (PageRank, etc.)
        self.graph.compute_centrality()

        # Identifiera samhällen/kluster
        self.graph.detect_communities()

        # Lägg till tidsordning om tidsstämplar finns
        self.graph.add_temporal_edges()

Frågebehandling med grafer

GraphRAG-frågor innebär multi-hop-resonemang över kunskapsgrafen:

class GraphRAGRetriever:
    def __init__(self, graph, embedder):
        self.graph = graph
        self.embedder = embedder

    def retrieve_subgraph(self, query: str,
                         max_hops: int = 2,
                         max_nodes: int = 50):
        """Hämta relevant delgraf för fråga"""

        # Identifiera fröentiteter i frågan
        query_entities = self.entity_extractor.extract(query)

        # Hitta matchande noder i grafen
        seed_nodes = []
        for entity in query_entities:
            matches = self.graph.find_similar_nodes(
                entity['text'],
                similarity_threshold=0.85
            )
            seed_nodes.extend(matches)

        # Expandera delgraf via traversering
        subgraph = self.graph.create_subgraph()
        visited = set()

        for seed in seed_nodes:
            self._expand_from_node(
                seed,
                subgraph,
                visited,
                current_hop=0,
                max_hops=max_hops
            )

        # Rangordna noder efter relevans
        ranked_nodes = self._rank_subgraph_nodes(
            subgraph, query
        )

        # Extrahera och formatera kontext
        context = self._format_graph_context(
            ranked_nodes[:max_nodes],
            subgraph
        )

        return context

    def _expand_from_node(self, node, subgraph, visited,
                         current_hop, max_hops):
        """Expandera delgraf rekursivt"""
        if current_hop >= max_hops or node in visited:
            return

        visited.add(node)
        subgraph.add_node(node)

        # Hämta grannar
        neighbors = self.graph.get_neighbors(node)

        for neighbor, edge_data in neighbors:
            # Lägg till kant till delgrafen
            subgraph.add_edge(node, neighbor, edge_data)

            # Expandera rekursivt
            self._expand_from_node(
                neighbor,
                subgraph,
                visited,
                current_hop + 1,
                max_hops
            )

    def _format_graph_context(self, nodes, subgraph):
        """Konvertera delgraf till textuell kontext"""
        context_parts = []

        for node in nodes:
            # Lägg till nodkontext
            context_parts.append(f"Entitet: {node.text}")
            context_parts.append(f"Typ: {node.entity_type}")

            # Lägg till relationsinformation
            edges = subgraph.get_edges(node)
            for edge in edges:
                context_parts.append(
                    f"- {edge.relation_type} -> {edge.target.text}"
                )

        return "\n".join(context_parts)

Microsofts GraphRAG-implementering

Microsofts GraphRAG tar ett unikt tillvägagångssätt genom att generera samhällssammanfattningar:

  1. Bygg initial graf från dokument med LLM-baserad entitets-/relationsextraktion
  2. Detektera samhällen med Leiden-algoritm eller liknande
  3. Generera sammanfattningar för varje samhälle med LLMs
  4. Hierarkisk struktur: Bygg flera nivåer av samhällsabstraktioner
  5. Frågetid: Hämta relevanta samhällen och traversera till specifika entiteter

Detta tillvägagångssätt är särskilt effektivt för:

  • Exploratoriska frågor (“Vilka är de huvudsakliga temana i detta korpus?”)
  • Multi-hop-resonemang (“Hur är A kopplat till C genom B?”)
  • Temporala analyser (“Hur har denna entitets relationer utvecklats?”)

Jämförande analys

När man ska använda varje variant

Använd LongRAG när:

  • Dokument har stark intern sammanhållning
  • Kontextfönster för din LLM stöder stora indata (32K+)
  • Svar på frågor kräver förståelse av långväga beroenden
  • Du arbetar med strukturerade dokument (rapporter, artiklar, böcker)

Använd Self-RAG när:

  • Noggrannhet och tillförlitlighet är kritiska
  • Du behöver förklarliga hämtningsbeslut
  • Falska positiva resultat från irrelevant hämtning är kostsamma
  • Frågekomplexiteten varierar mycket (vissa behöver hämtning, andra inte)

Använd GraphRAG när:

  • Ditt område har rika entitetsrelationer
  • Frågor involverar multi-hop-resonemang
  • Temporala eller hierarkiska relationer är viktiga
  • Du behöver förstå kopplingar mellan entiteter

Prestandametriskt jämförelse

Metrik Standard RAG LongRAG Self-RAG GraphRAG
Indexeringstid 1x 0.8x 1.1x 3-5x
Frågelatens 1x 2-3x 1.4x 1.5-2x
Minneanvändning 1x 3-4x 1.2x 2-3x
Noggrannhet (QA) baslinje +15-25% +20-30% +25-40%*
Tolkbarhet Låg Medel Hög Hög

*GraphRAG-förbättringar är starkt domänberoende

Hybridtillvägagångssätt

De mest kraftfulla produktionssystemen kombinerar ofta flera tekniker:

LongRAG + GraphRAG: Använd grafrstruktur för att identifiera relevanta dokumentkluster, sedan hämta hela dokument istället för fragment

Self-RAG + GraphRAG: Tillämpa reflektionmekanismer på graftraverseringsbeslut (vilka vägar att följa, när man ska stoppa expansion)

Tretrappspipeline: Använd GraphRAG för initial entitetsbaserad hämtning → Self-RAG för relevansfiltrering → LongRAG för kontextsammanställning

Implementeringsöverväganden

Embeddingsmodeller

Olika RAG-varianter har olika embeddingskrav:

LongRAG: Behöver embeddings som fungerar bra både på dokumentnivå och chunknivå. Överväg modeller tränade med kontrastivt lärande på långa sekvenser.

Self-RAG: Dra nytta av embeddings som fångar semantiska nyanser för finmaskig relevansbedömning.

GraphRAG: Kräver entitetsmedvetna embeddings. Modeller finjusterade på entitetslänkning uppvisar bättre prestanda.

Valet av embeddingsmodell påverkar prestanda betydligt. När man arbetar med lokala modeller ger verktyg som Ollama ett enkelt sätt att experimentera med olika embeddingsmodeller innan man går över till produktionsdistribution.

Chunkningsstrategier omprövade

Traditionell fast storleksbaserad chunkning räcker inte för avancerad RAG:

Semantisk chunkning: Bryt vid naturliga gränser (stycken, avsnitt, ämnesförskjutningar) Rekursiv chunkning: Skapa hierarkiska chunkar med förälder-barn-relationer Glidande fönster: Använd överlappande chunkar för att bevara kontext vid gränser Strukturmedveten: Respektera dokumentstruktur (markdown-rubriker, XML-taggar, kodblock)

För Python-baserade implementeringar erbjuder bibliotek som LangChain och LlamaIndex inbyggt stöd för dessa chunkningsstrategier.

Reranking-integration

Reranking förbättrar hämtningskvaliteten avsevärt för alla RAG-varianter. Efter initial hämtning ombedömer en specialiserad rerankingmodell resultaten baserat på interaktionsfunktioner mellan fråga och dokument. Detta ger en betydande noggrannhetsförbättring (10-20%) med minimal påverkan på latens när det integreras på ett genomtänkt sätt.

Skalning till produktion

Indexeringspipeline:

  • Använd distribuerad bearbetning (Ray, Dask) för stora dokumentkorpus
  • Implementera inkrementell indexering för realtidsuppdateringar
  • Lagra embeddings i optimerade vektordatabaser (Pinecone, Weaviate, Qdrant)

Frågeoptimering:

  • Cacha frekventa frågor och deras resultat
  • Implementera frågerutning (olika RAG-varianter för olika frågetyper)
  • Använd approximativ närmaste granne-sökning för sublinjär skalning

Övervakning:

  • Följ hämtningsrelevanspoäng
  • Övervaka reflektionsbeslut i Self-RAG
  • Mät graftraverseringsvägar och djup
  • Logga konfidenspoäng och användaråterkoppling

Verkliga tillämpningar

Söktjänst för teknisk dokumentation

En stor molnleverantör implementerade GraphRAG för sin dokumentation:

  • Entiteter: API-ändpunkter, parametrar, felkoder, tjänsternamn
  • Relationer: Beroenden, versionskompatibilitet, migreringsvägar
  • Resultat: 35% minskning av supportärenden, 45% snabbare lösningstid

Juridisk upptäckt

Ett juridiskt teknikföretag kombinerade Self-RAG med LongRAG:

  • Self-RAG filtrerar bort irrelevanta dokument tidigt
  • LongRAG bevarar kontext i behållna dokument
  • Advokater granskar 60% färre falska positiva resultat
  • Kritisk kontextbevaring förbättrades från 71% till 94%

Forskningslitteraturöversikt

Akademisk söktjänst som använder hybridtillvägagångssätt:

  • GraphRAG identifierar citationsnätverk och forskarsamhällen
  • LongRAG hämtar hela avsnitt som bevarar metodkontext
  • 40% förbättring i upptäckt av relevanta artiklar
  • Minskat tid för litteraturöversikt från veckor till dagar

Avancerade ämnen

Multi-Modal RAG

Förlängning av dessa varianter för att hantera bilder, tabeller och kod:

  • Visuell grundning: Länka textentiteter till bilder i dokument
  • Tabellförståelse: Parsa strukturerade data till grafformat
  • Kodanalys: Bygg beroendegrafer från kodbaser

Adaptiv RAG

Dynamisk val av RAG-strategi baserat på frågeegenskaper:

  • Klassificering av frågekomplexitet
  • Detektor för dokumenttyp
  • Kostnads-nytto-optimering för strategival

Integritetsskyddande RAG

Implementering av dessa varianter med integritetskrav:

  • Federerad hämtning över datasilos
  • Differentiell integritet i inbäddningar
  • Krypterad likhetsökning

Att börja med

Snabbstart med Python

För dem som vill implementera dessa tekniker är det viktigt att börja med en solid Python-plattform. Pythons rika ekosystem för maskininlärning gör det till det naturliga valet för RAG-utveckling.

Här är en enkel startpunkt för experiment:

# Installera beroenden
# pip install sentence-transformers faiss-cpu langchain

from sentence_transformers import SentenceTransformer
import faiss
import numpy as np

# Grundläggande inställning för experiment med långa segment
model = SentenceTransformer('all-MiniLM-L6-v2')

documents = [
    # Dina långformade dokument här
]

# Skapa inbäddningar
embeddings = model.encode(documents)

# Bygg FAISS-index
dimension = embeddings.shape[1]
index = faiss.IndexFlatL2(dimension)
index.add(embeddings.astype('float32'))

# Fråga
query = "Din fråga här"
query_embedding = model.encode([query])
distances, indices = index.search(
    query_embedding.astype('float32'), k=3
)

Ramverkval

LangChain: Bäst för snabb prototypning, omfattande integrationer LlamaIndex: Optimerad för dokumentindexering och hämtning Haystack: Produktionsklar, starka pipeline-abstraktioner Anpassad: När du behöver full kontroll och optimering

Utvärderingsramverk

Implementera noggrann utvärdering innan produktionsdistribution:

Hämtningsmått:

  • Precision@K, Recall@K, MRR (Mean Reciprocal Rank)
  • NDCG (Normalized Discounted Cumulative Gain)

Genereringsmått:

  • ROUGE, BLEU för textlikhet
  • BERTScore för semantisk likhet
  • Mänsklig utvärdering för kvalitetsbedömning

Slut-till-slut-mått:

  • Uppgiftslyckandesats
  • Användarnöjdhetspoäng
  • Latenspercentiler (p50, p95, p99)

Slutsats

Landskapet för RAG-system har mognat betydligt bortom grundläggande vektorsimilaritetsökning. LongRAG, Self-RAG och GraphRAG löser var och en specifika begränsningar hos traditionella metoder:

LongRAG löser problemet med kontextfragmentering genom att omfatta utökade kontextfönster och minimal segmentering. Det är det självklara valet när dokumentkoherens är viktig och du har de beräkningsresurser som krävs för att hantera stora kontexter.

Self-RAG lägger till kritisk självmedvetenhet i hämtningssystem. Genom att reflektera över sina egna beslut minskar det falska positiva resultat och förbättrar tillförlitligheten - avgörande för högriskapplikationer där noggrannhet är viktigare än hastighet.

GraphRAG låser upp kraften i strukturerad kunskapsrepresentation. När ditt domän involverar komplexa relationer mellan entiteter kan grafbaserad hämtning framhäva samband som vektorsimilaritet helt missar.

Framtiden för RAG innebär troligen hybrida tillvägagångssätt som kombinerar styrkorna hos dessa varianter. Ett produktionssystem kan använda GraphRAG för att identifiera relevanta entitetskluster, Self-RAG för att filtrera och validera hämtningar, och LongRAG för att sammanställa sammanhängande kontext för LLM.

När LLMs fortsätter att förbättras och kontextfönster expanderar, kommer vi att se ännu mer sofistikerade RAG-varianter framträda. Nyckeln är att förstå dina specifika krav för användningsfall - dokumentstruktur, frågemönster, noggrannhetskrav och beräkningsbegränsningar - och välja den lämpliga tekniken eller kombinationen av dessa.

Verktygsmiljön mognar snabbt, med ramverk som LangChain, LlamaIndex och Haystack som erbjuder alltmer sofistikerat stöd för dessa avancerade mönster. Kombinerat med kraftfulla lokala LLM-runtime och inbäddningsmodeller har det aldrig varit enklare att experimentera med och distribuera produktionsklara RAG-system.

Börja med grunderna, mäta prestanda noggrant och utveckla din arkitektur efter behov. De avancerade RAG-varianter som täcks här ger en vägledning för denna utveckling.

Användbara länkar

Externa referenser