Advanced RAG: LongRAG, Self-RAG e GraphRAG Spiegati
LongRAG, Self-RAG, GraphRAG - Tecniche di ultima generazione
Generazione Rafforzata con Recupero (RAG) ha evoluto molto al di là della semplice ricerca per similarità vettoriale. LongRAG, Self-RAG e GraphRAG rappresentano l’avanguardia di queste capacità.
I sistemi RAG moderni devono gestire documenti di grandi dimensioni, comprendere relazioni complesse tra entità e molto altro.
Quest’immagine piacevole è generata da modello AI Flux 1 dev.
L’Evolvere Oltre il RAG Base
I sistemi RAG tradizionali seguono un modello semplice: frammentare i documenti, incapsularli in vettori, recuperare frammenti simili tramite similarità del coseno e alimentarli a un LLM. Sebbene efficaci per molti casi d’uso, questo approccio ha difficoltà in tre scenari critici:
- Dipendenze a lungo raggio: Il contesto importante potrebbe spaziare su migliaia di token distribuiti su diversi frammenti
- Confidenza nel recupero: Il sistema non ha modo di valutare se il contenuto recuperato è realmente rilevante
- Complessità delle relazioni: La similarità vettoriale non riesce a catturare connessioni intricate tra entità
Le varianti avanzate di RAG affrontano queste limitazioni con architetture specializzate mirate a specifici problemi.
LongRAG: Conquista un Contesto Esteso
Panoramica dell’Architettura
LongRAG ripensa fondamentalmente la strategia di frammentazione sfruttando LLM con finestre di contesto estese (32K, 100K o addirittura 1M token). Invece di suddividere i documenti in piccoli frammenti di 512 token, LongRAG utilizza un approccio gerarchico:
Embedding a Livello di Documento: L’intero documento (o sezioni molto grandi) viene elaborato come unità singola. Un embedding a livello di documento cattura il significato semantico complessivo, mantenendo il testo completo per l’elaborazione successiva.
Minima Frammentazione: Quando è necessario frammentare, LongRAG utilizza frammenti molto più grandi (4K-8K token) con un sovrapposizione significativa (20-30%). Questo preserva il flusso narrativo e riduce la frammentazione del contesto.
Assemblaggio del Contesto: Al momento del recupero, LongRAG restituisce documenti completi o sezioni coerenti piuttosto che frammenti sparsi. L’LLM riceve un contesto continuo che mantiene relazioni strutturali e semantiche.
Strategia di Implementazione
Ecco un’implementazione concettuale utilizzando Python e modelli di embedding moderni:
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]:
"""Crea frammenti sovrapposti di grandi dimensioni"""
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):
"""Indicizza il documento con embedding gerarchici"""
# Embed l'intero documento
doc_embedding = self.model.embed(doc)
# Crea grandi frammenti con sovrapposizione
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]:
"""Recupera contenuti a lungo formato rilevanti"""
query_embedding = self.model.embed(query)
# Valuta prima a livello di documento
doc_scores = [
np.dot(query_embedding, doc['doc_embedding'])
for doc in self.doc_embeddings
]
# Ottieni i documenti principali
top_doc_indices = np.argsort(doc_scores)[-top_k:][::-1]
results = []
for idx in top_doc_indices:
doc_data = self.doc_embeddings[idx]
# Per ogni documento, trova i migliori frammenti
chunk_scores = [
np.dot(query_embedding, emb)
for emb in doc_data['chunk_embeddings']
]
best_chunk_idx = np.argmax(chunk_scores)
# Restituisce il contesto esteso intorno al miglior frammento
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]:
"""Ottieni il contesto esteso intorno al frammento rilevante"""
start = max(0, center_idx - 1)
end = min(len(chunks), center_idx + 2)
return chunks[start:end]
Caso d’Uso e Prestazioni
LongRAG eccelle in scenari in cui il contesto è importante:
- Analisi di documenti legali: Contratti e brevi legali spesso hanno dipendenze che si estendono su dozzine di pagine
- Recupero di articoli di ricerca: Per comprendere la metodologia è necessario un contesto coerente, non paragrafi isolati
- Repository di codice: Funzioni e classi devono essere comprese all’interno del loro contesto modulare
Caratteristiche delle prestazioni:
- Latenza: Maggiore a causa del processamento di grandi frammenti (2-5 volte più lento del RAG standard)
- Precisione: Miglioramento del 15-25% nei benchmark per domande a lungo formato
- Memoria: Richiede 3-4 volte più memoria per le finestre di contesto
Self-RAG: Recupero Riflessivo
Principi Fondamentali
Self-RAG introduce un livello metacognitivo ai sistemi RAG. Invece di recuperare e generare in modo cieco, il sistema riflette attivamente sui propri processi attraverso speciali token di riflessione:
Token di Recupero: Decide se è necessario il recupero per una determinata domanda Token di Rilevanza: Valuta se i documenti recuperati sono effettivamente rilevanti Token di Supporto: Verifica se la risposta generata è supportata dal contenuto recuperato Token di Critica: Valuta la qualità complessiva della risposta generata
Componenti dell’Architettura
L’architettura Self-RAG è composta da tre fasi interconnesse:
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):
"""Genera risposta con auto-riflessione"""
# Fase 1: Decide se è necessario il recupero
retrieve_decision = self.critic.should_retrieve(query)
if not retrieve_decision:
# Generazione diretta senza recupero
return self.generator.generate(query)
# Fase 2: Recupera e valuta la rilevanza
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: # Threshold
relevant_docs.append(doc)
if not relevant_docs:
# Rientro alla generazione senza recupero
return self.generator.generate(query)
# Fase 3: Genera e verifica il supporto
best_answer = None
best_score = -1
for _ in range(max_iterations):
# Genera risposta candidata
answer = self.generator.generate(
query, context=relevant_docs
)
# Valuta supporto e qualità
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
# Arresto precoce se raggiunta alta qualità
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
}
}
Addestramento dei Meccanismi di Riflessione
Self-RAG richiede l’addestramento del componente critico per effettuare valutazioni affidabili. Questo tipicamente implica:
- Fine-tuning supervisionato su dataset annotati con giudizi di rilevanza
- Apprendimento per rinforzo con premi per previsioni accurate
- Apprendimento contrastivo per distinguere affermazioni supportate da quelle non supportate
I token di riflessione possono essere implementati come:
- Token speciali nel vocabolario (come
[RETRIEVE],[RELEVANT]) - Classificatori separati sul modello
- Modelli critici esterni (approccio ensemble)
Considerazioni per la Produzione
Quando si distribuisce Self-RAG in sistemi di produzione:
Scambi di Latenza: Ogni passo di riflessione aggiunge un sovraccarico del 20-40% nell’inferenza. Bilanciare la completezza con i requisiti di tempo di risposta.
Soglie di Confidenza: Regolare le soglie di riflessione in base al caso d’uso. Le applicazioni legali o mediche richiedono una maggiore confidenza rispetto ai chatbot generali.
Monitoraggio: Tracciare le decisioni di riflessione per identificare pattern. Se il recupero è raramente necessario, potresti trarre vantaggio da un’architettura più semplice.
GraphRAG: Recupero Rafforzato da Grafi di Conoscenza
Fondamenti Concettuali
GraphRAG trasforma il problema del recupero da similarità vettoriale a percorso su grafi. Invece di trovare frammenti di testo semanticamente simili, GraphRAG identifica sottografi rilevanti di entità e relazioni connesse.
Estrazione delle Entità: Identifica entità denominate, concetti e i loro tipi Mappatura delle Relazioni: Estrae relazioni tra entità (temporali, causali, gerarchiche) Costruzione del Grafo: Costruisce un grafo di conoscenza con entità come nodi e relazioni come archi Recupero del Sottografo: Dato un query, trova sottografi rilevanti connessi
Pipeline di Costruzione del Grafo
Costruire un grafo di conoscenza da testo non strutturato implica diversi stadi:
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]):
"""Costruisci grafo di conoscenza dai documenti"""
for doc in documents:
# Estrai entità
entities = self.entity_extractor.extract(doc)
# Aggiungi entità come nodi
for entity in entities:
self.graph.add_node(
entity['text'],
entity_type=entity['type'],
context=entity['surrounding_text']
)
# Estrai relazioni
relations = self.relation_extractor.extract(
doc, entities
)
# Aggiungi relazioni come archi
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):
"""Aggiungi relazioni derivate e metadati"""
# Calcola l'importanza dei nodi (PageRank, ecc.)
self.graph.compute_centrality()
# Identifica comunità/cluster
self.graph.detect_communities()
# Aggiungi ordinamento temporale se disponibili timestamp
self.graph.add_temporal_edges()
Elaborazione delle Query con Grafi
Le query GraphRAG implicano un ragionamento a salti multipli attraverso il grafo di conoscenza:
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):
"""Recupera sottografo rilevante per la query"""
# Identifica entità di base nella query
query_entities = self.entity_extractor.extract(query)
# Trova nodi corrispondenti nel grafo
seed_nodes = []
for entity in query_entities:
matches = self.graph.find_similar_nodes(
entity['text'],
similarity_threshold=0.85
)
seed_nodes.extend(matches)
# Espande il sottografo tramite percorso
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
)
# Classifica i nodi per rilevanza
ranked_nodes = self._rank_subgraph_nodes(
subgraph, query
)
# Estrae e formatta il contesto
context = self._format_graph_context(
ranked_nodes[:max_nodes],
subgraph
)
return context
def _expand_from_node(self, node, subgraph, visited,
current_hop, max_hops):
"""Espande ricorsivamente il sottografo"""
if current_hop >= max_hops or node in visited:
return
visited.add(node)
subgraph.add_node(node)
# Ottieni i vicini
neighbors = self.graph.get_neighbors(node)
for neighbor, edge_data in neighbors:
# Aggiungi l'arco al sottografo
subgraph.add_edge(node, neighbor, edge_data)
# Espandi ricorsivamente
self._expand_from_node(
neighbor,
subgraph,
visited,
current_hop + 1,
max_hops
)
def _format_graph_context(self, nodes, subgraph):
"""Converte il sottografo in contesto testuale"""
context_parts = []
for node in nodes:
# Aggiungi contesto del nodo
context_parts.append(f"Entità: {node.text}")
context_parts.append(f"Tipo: {node.entity_type}")
# Aggiungi informazioni sulle relazioni
edges = subgraph.get_edges(node)
for edge in edges:
context_parts.append(
f"- {edge.relation_type} -> {edge.target.text}"
)
return "\n".join(context_parts)
Implementazione GraphRAG di Microsoft
L’implementazione GraphRAG di Microsoft adotta un approccio unico generando sintesi di comunità:
- Costruisci il grafo iniziale dai documenti utilizzando l’estrazione di entità e relazioni basata su LLM
- Identifica le comunità utilizzando l’algoritmo Leiden o simili
- Genera sintesi per ogni comunità utilizzando LLM
- Struttura gerarchica: Costruisci diversi livelli di astrazione delle comunità
- Al momento della query: Recupera le comunità rilevanti e percorri fino a entità specifiche
Questo approccio è particolarmente efficace per:
- Query esplorative (“Quali sono i temi principali in questo corpus?”)
- Ragionamento a salti multipli (“Come è A connesso a C attraverso B?”)
- Analisi temporale (“Come sono evoluti i rapporti di questa entità?”)
Analisi Comparativa
Quando Utilizzare Ogni Variante
Utilizza LongRAG quando:
- I documenti hanno una forte coerenza interna
- Le finestre di contesto del tuo LLM supportano grandi input (32K+)
- Le risposte alle domande richiedono la comprensione di dipendenze a lungo raggio
- Stai lavorando con documenti strutturati (rapporti, articoli, libri)
Utilizza Self-RAG quando:
- La precisione e la fiducia sono critiche
- Hai bisogno di decisioni di recupero spiegabili
- I falsi positivi da recupero irrilevante sono costosi
- La complessità delle query varia ampiamente (qualcuna richiede recupero, altre no)
Utilizza GraphRAG quando:
- Il tuo dominio ha relazioni tra entità ricche
- Le query implicano ragionamento a salti multipli
- Le relazioni temporali o gerarchiche sono importanti
- Hai bisogno di comprendere le connessioni tra entità
Confronto delle Metriche di Prestazione
| Metrica | RAG Standard | LongRAG | Self-RAG | GraphRAG |
|---|---|---|---|---|
| Tempo di Indicizzazione | 1x | 0.8x | 1.1x | 3-5x |
| Latenza delle Query | 1x | 2-3x | 1.4x | 1.5-2x |
| Utilizzo della Memoria | 1x | 3-4x | 1.2x | 2-3x |
| Precisione (QA) | baseline | +15-25% | +20-30% | +25-40%* |
| Interpretabilità | Bassa | Media | Alta | Alta |
*Le migliorie di GraphRAG dipendono molto dal dominio
Approcci Ibridi
I sistemi di produzione più potenti spesso combinano diverse tecniche:
LongRAG + GraphRAG: Utilizza la struttura del grafo per identificare cluster di documenti rilevanti, quindi recupera documenti completi invece di frammenti
Self-RAG + GraphRAG: Applica i meccanismi di riflessione alle decisioni di percorso del grafo (quali percorsi seguire, quando fermarsi)
Pipeline a tre fasi: Utilizza GraphRAG per il recupero iniziale basato su entità → Self-RAG per il filtraggio della rilevanza → LongRAG per l’assemblaggio del contesto
Considerazioni sull’Implementazione
Modelli di Embedding
Diverse varianti di RAG hanno diversi requisiti di embedding:
LongRAG: Richiede embedding che funzionino bene sia a livello di documento che di frammento. Considera modelli addestrati con apprendimento contrastivo su lunghe sequenze.
Self-RAG: Beneficia di embedding che catturano sottili sfumature semantiche per l’analisi della rilevanza fine-grained.
GraphRAG: Richiede embedding consapevoli delle entità. I modelli sottoposti a fine-tuning su compiti di collegamento delle entità si comportano meglio.
La scelta del modello di embedding ha un impatto significativo sulle prestazioni. Quando si lavora con modelli locali, strumenti come Ollama offrono un modo semplice per sperimentare con diversi modelli di embedding prima di impegnarsi in un’implementazione di produzione.
Strategie di Frammentazione Revisitate
La frammentazione tradizionale a dimensione fissa non è sufficiente per RAG avanzato:
Frammentazione semantica: Suddividi ai confini naturali (paragrafi, sezioni, cambiamenti di argomento) Frammentazione ricorsiva: Crea frammenti gerarchici con relazioni padre-figlio Finestra scorrevole: Utilizza frammenti sovrapposti per preservare il contesto ai confini Struttura consapevole: Rispetta la struttura del documento (intestazioni markdown, tag XML, blocchi di codice)
Per le implementazioni in Python, le librerie come LangChain e LlamaIndex offrono un supporto integrato per queste strategie di frammentazione.
Integrazione di Reranking
Il reranking migliora drasticamente la qualità del recupero in tutte le varianti di RAG. Dopo il recupero iniziale, un modello specializzato ririscore i risultati in base a caratteristiche dell’interazione query-documento. Questo fornisce un significativo miglioramento della precisione (10-20%) con un impatto minimo sulla latenza quando integrato con cura.
Scalabilità alla Produzione
Pipeline di indicizzazione:
- Utilizza elaborazione distribuita (Ray, Dask) per grandi corpora di documenti
- Implementa indicizzazione incrementale per aggiornamenti in tempo reale
- Archivia gli embedding in database vettoriali ottimizzati (Pinecone, Weaviate, Qdrant)
Ottimizzazione delle query:
- Cachizza query frequenti e i loro risultati
- Implementa routing delle query (diverse varianti di RAG per diversi tipi di query)
- Utilizza ricerca approssimata del vicino più prossimo per una scalabilità sub-lineare
Monitoraggio:
- Traccia i punteggi di rilevanza del recupero
- Monitora le decisioni di riflessione in Self-RAG
- Misura i percorsi e le profondità di attraversamento dei grafi
- Registra i punteggi di confidenza e i feedback degli utenti
Applicazioni Real-World
Ricerca nella Documentazione Tecnica
Un importante provider di cloud ha implementato GraphRAG per la loro documentazione:
- Entità: Endpoint API, parametri, codici di errore, nomi dei servizi
- Relazioni: Dipendenze, compatibilità tra versioni, percorsi di migrazione
- Risultato: Riduzione del 35% delle ticket di supporto, tempo di risoluzione ridotto del 45%
Scoperta Legale
Un’azienda di tecnologia legale ha combinato Self-RAG con LongRAG:
- Self-RAG filtra i documenti irrilevanti in modo precoce
- LongRAG preserva il contesto nei documenti conservati
- Gli avvocati esaminano il 60% in meno di falsi positivi
- La conservazione del contesto critico è migliorata dal 71% al 94%
Rassegna della Letteratura Accademica
Motore di ricerca accademico con approccio ibrido:
- GraphRAG identifica reti di citazioni e comunità di ricerca
- LongRAG recupera sezioni complete mantenendo il contesto della metodologia
- Miglioramento del 40% nella scoperta di articoli rilevanti
- Riduzione del tempo per la revisione della letteratura da settimane a giorni
Argomenti Avanzati
RAG Multimodale
Estendere queste varianti per gestire immagini, tabelle e codice:
- Fondamento visivo: Collega entità di testo alle immagini nei documenti
- Comprensione delle tabelle: Parsa dati strutturati in formato grafico
- Analisi del codice: Costruisce grafi di dipendenze da codici
RAG Adattivo
Selezione dinamica della strategia RAG in base alle caratteristiche della query:
- Classificatore di complessità della query
- Rilevatore del tipo di documento
- Ottimizzatore del costo-beneficio per la selezione della strategia
RAG con Riservatezza
Implementazione di queste varianti con vincoli di riservatezza:
- Recupero federato tra silos di dati
- Riservatezza differenziale negli embedding
- Ricerca approssimata con crittografia
Getting Started
Quick Start with Python
Per coloro che desiderano implementare queste tecniche, iniziare con una solida base in Python è essenziale. L’ampio ecosistema di Python per l’apprendimento automatico lo rende la scelta naturale per lo sviluppo di sistemi RAG.
Ecco un punto di partenza semplice per sperimentare:
# Install dependencies
# pip install sentence-transformers faiss-cpu langchain
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np
# Basic setup for experimenting with long chunks
model = SentenceTransformer('all-MiniLM-L6-v2')
documents = [
# Your long-form documents here
]
# Create embeddings
embeddings = model.encode(documents)
# Build FAISS index
dimension = embeddings.shape[1]
index = faiss.IndexFlatL2(dimension)
index.add(embeddings.astype('float32'))
# Query
query = "Your question here"
query_embedding = model.encode([query])
distances, indices = index.search(
query_embedding.astype('float32'), k=3
)
Framework Selection
LangChain: Migliore per il prototipo rapido, integrazioni estese LlamaIndex: Ottimizzato per l’indicizzazione e il recupero dei documenti Haystack: Pronto per la produzione, forti astrazioni delle pipeline Custom: Quando si ha bisogno di un controllo completo e di ottimizzazione
Evaluation Framework
Implementare un’accurata valutazione prima del deployment in produzione:
Metriche di recupero:
- Precision@K, Recall@K, MRR (Mean Reciprocal Rank)
- NDCG (Normalized Discounted Cumulative Gain)
Metriche di generazione:
- ROUGE, BLEU per la similarità testuale
- BERTScore per la similarità semantica
- Valutazione umana per la valutazione della qualità
Metriche end-to-end:
- Tasso di successo del compito
- Punteggi di soddisfazione degli utenti
- Percentili di latenza (p50, p95, p99)
Conclusion
Il panorama dei sistemi RAG si è evoluto significativamente al di là della semplice ricerca di similarità vettoriale. LongRAG, Self-RAG e GraphRAG affrontano ciascuno specifiche limitazioni degli approcci tradizionali:
LongRAG risolve il problema della frammentazione del contesto adottando finestre di contesto estese e un minimo di suddivisione in frammenti. È la scelta ideale quando la coerenza dei documenti è importante e si dispongono delle risorse computazionali per gestire contesti di grandi dimensioni.
Self-RAG aggiunge una critica di sé stessa ai sistemi di recupero. Riflettendo sulle proprie decisioni, riduce i falsi positivi e migliora la fiducia — essenziale per le applicazioni ad alto rischio dove l’accuratezza è più importante della velocità.
GraphRAG sfrutta il potere della rappresentazione strutturata della conoscenza. Quando il dominio coinvolge relazioni complesse tra entità, il recupero basato su grafi può evidenziare connessioni che la similarità vettoriale non riesce a rilevare.
Il futuro dei sistemi RAG probabilmente prevede approcci ibridi che combinano le forze di queste varianti. Un sistema in produzione potrebbe utilizzare GraphRAG per identificare cluster di entità rilevanti, Self-RAG per filtrare e validare i recuperi, e LongRAG per assemblare contesti coerenti per l’LLM.
Mentre gli LLM continuano a migliorare e le finestre di contesto si espandono, vedremo emergere varianti RAG ancora più sofisticate. La chiave è comprendere i requisiti specifici del caso d’uso — struttura dei documenti, modelli di query, esigenze di accuratezza e vincoli computazionali — e selezionare la tecnica appropriata o la combinazione di esse.
L’ecosistema degli strumenti si sta maturando rapidamente, con framework come LangChain, LlamaIndex e Haystack che forniscono un supporto sempre più sofisticato per questi modelli avanzati. Combinati con potenti runtime locali degli LLM e modelli di embedding, è mai stato più facile sperimentare e deployare sistemi RAG di produzione.
Iniziare con le basi, misurare rigorosamente le prestazioni e evolvere l’architettura come richiesto dai requisiti. Le varianti avanzate di RAG trattate qui forniscono una mappa per questa evoluzione.
Useful links
- Python Cheatsheet
- Reranking with embedding models
- LLMs and Structured Output: Ollama, Qwen3 & Python or Go
- Cloud LLM Providers
- LLMs Comparison: Qwen3:30b vs GPT-OSS:20b
External References
- Microsoft GraphRAG: A Modular Graph-Based Retrieval-Augmented Generation System
- Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection
- LongRAG: Enhancing Retrieval-Augmented Generation with Long-context LLMs
- Retrieval-Augmented Generation for Large Language Models: A Survey
- FAISS: A Library for Efficient Similarity Search
- LangChain Documentation: Advanced RAG Techniques
- HuggingFace: Sentence Transformers for Embedding Models
- RAG Survey: A Comprehensive Analysis of Retrieval Augmented Generation