Percée de décomposition de requête : DecomposeRAG gère les questions complexes 50% mieux
Les chercheurs d'UC Berkeley introduisent DecomposeRAG, un framework de décomposition de requête automatisé qui améliore significativement les réponses aux questions multi-sauts.
Aperçu de la recherche
Le laboratoire NLP d'UC Berkeley a publié DecomposeRAG, un framework qui décompose automatiquement les requêtes complexes en sous-requêtes plus simples, atteignant des résultats state-of-the-art sur les benchmarks de QA multi-sauts.
Le problème
Les questions complexes nécessitent un raisonnement multi-sauts :
Exemple : "Quelle est la population de la capitale du pays où se trouve la Tour Eiffel ?"
Nécessite :
- Où se trouve la Tour Eiffel ? → France
- Quelle est la capitale de la France ? → Paris
- Quelle est la population de Paris ? → 2,1 millions
Le RAG traditionnel récupère du contexte pour la question complète, manquant souvent les étapes intermédiaires.
Approche DecomposeRAG
Décomposition automatique
Utilise GPT-4 pour décomposer les requêtes en sous-questions :
DEVELOPERpythondef decompose_query(complex_query): prompt = f"""Break this question into simple sub-questions that must be answered in order. Question: {complex_query} Sub-questions (in order): 1.""" response = gpt4.generate(prompt) sub_questions = parse_questions(response) return sub_questions
Récupération séquentielle
Répondre aux sous-questions dans l'ordre, en utilisant les réponses précédentes comme contexte :
DEVELOPERpythondef sequential_rag(sub_questions): context = "" for i, sub_q in enumerate(sub_questions): # Retrieve for this sub-question docs = retrieve(sub_q + " " + context, k=5) # Generate answer answer = llm.generate( query=sub_q, context=docs, previous_answers=context ) # Add to cumulative context context += f"\nQ{i+1}: {sub_q}\nA{i+1}: {answer}\n" return answer # Answer to final sub-question
Validation des réponses
Valide chaque réponse intermédiaire avant de continuer :
DEVELOPERpythondef validate_answer(question, answer, retrieved_docs): prompt = f"""Is this answer supported by the documents? Question: {question} Answer: {answer} Documents: {retrieved_docs} Supported? (yes/no):""" validation = llm.generate(prompt) return "yes" in validation.lower()
Si la validation échoue, réessayer avec plus de contexte ou une stratégie de récupération alternative.
Résultats de benchmark
Testé sur quatre datasets de QA multi-sauts :
| Dataset | RAG Baseline | DecomposeRAG | Amélioration |
|---|---|---|---|
| HotpotQA | 45.3% | 68.7% | +51.7% |
| 2WikiMultihopQA | 38.2% | 57.9% | +51.6% |
| MuSiQue | 32.1% | 49.8% | +55.1% |
| IIRC | 41.7% | 62.3% | +49.4% |
Amélioration moyenne : +52%
Comparaison avec d'autres méthodes
| Méthode | F1 moy | Coût (relatif) |
|---|---|---|
| RAG Standard | 39.3% | 1x |
| Chain-of-Thought | 43.8% | 2x |
| ReACT | 48.2% | 3x |
| DecomposeRAG | 59.7% | 2.5x |
DecomposeRAG atteint la meilleure précision à un coût modéré.
Insights clés
Quand la décomposition aide
L'efficacité varie selon la complexité de la requête :
| Sauts | Baseline | DecomposeRAG | Gain |
|---|---|---|---|
| 1 (simple) | 68.2% | 69.1% | +1.3% |
| 2 (moyen) | 51.3% | 67.4% | +31.4% |
| 3 (complexe) | 28.7% | 52.3% | +82.2% |
| 4+ (très complexe) | 15.2% | 38.9% | +156.3% |
Constat : Plus de sauts = gains plus importants de la décomposition.
Qualité de la décomposition
Analyse de la qualité des décompositions générées par LLM :
- Décomposition correcte : 87.3%
- Étapes manquantes : 8.2%
- Ordre incorrect : 3.1%
- Logique circulaire : 1.4%
Même des décompositions imparfaites améliorent les résultats.
Analyse d'erreurs
Où DecomposeRAG échoue-t-il ?
- Erreurs de décomposition (23%) : Mauvaises sous-questions
- Échecs de récupération (34%) : Impossible de trouver des docs pertinents pour la sous-question
- Erreurs de réponse (28%) : Mauvaise réponse intermédiaire qui se propage
- Échecs d'intégration (15%) : Impossible de combiner les sous-réponses
Le plus courant : La récupération échoue toujours pour les sous-questions.
Implémentation
Version basique
DEVELOPERpythonclass DecomposeRAG: def __init__(self, retriever, llm): self.retriever = retriever self.llm = llm async def query(self, complex_question): # Step 1: Decompose sub_questions = await self.decompose(complex_question) # Step 2: Sequential RAG context = "" for sub_q in sub_questions: # Retrieve docs = await self.retriever.retrieve( sub_q + " " + context, k=5 ) # Generate answer = await self.llm.generate( query=sub_q, context=docs, previous=context ) context += f"\n{sub_q} -> {answer}" # Return final answer return answer async def decompose(self, query): # Use LLM to decompose return await self.llm.decompose(query)
Avancé : Avec validation
DEVELOPERpythonclass ValidatedDecomposeRAG(DecomposeRAG): async def query(self, complex_question, max_retries=2): sub_questions = await self.decompose(complex_question) context = "" for sub_q in sub_questions: for attempt in range(max_retries): docs = await self.retriever.retrieve(sub_q + " " + context) answer = await self.llm.generate(sub_q, docs, context) # Validate if await self.validate(sub_q, answer, docs): context += f"\n{sub_q} -> {answer}" break elif attempt == max_retries - 1: # Failed validation, use best-effort answer context += f"\n{sub_q} -> {answer} (unverified)" return answer
Optimisations
Sous-requêtes parallèles
Quand les sous-questions sont indépendantes :
DEVELOPERpython# Identify independent sub-questions dependencies = analyze_dependencies(sub_questions) # Group independent questions independent_groups = group_by_dependencies(sub_questions, dependencies) # Process groups in parallel for group in independent_groups: # Parallel retrieval for group results = await asyncio.gather(*[ self.retrieve_and_answer(q, context) for q in group ]) # Add all to context for q, answer in zip(group, results): context += f"\n{q} -> {answer}"
Cache des résultats intermédiaires
DEVELOPERpythonclass CachedDecomposeRAG(DecomposeRAG): def __init__(self, retriever, llm): super().__init__(retriever, llm) self.cache = {} async def retrieve_and_answer(self, sub_q, context): cache_key = hash(sub_q + context) if cache_key in self.cache: return self.cache[cache_key] result = await super().retrieve_and_answer(sub_q, context) self.cache[cache_key] = result return result
Considérations pratiques
Latence
DecomposeRAG est 2-3x plus lent :
- Requête 2-sauts : +2-3 secondes
- Requête 3-sauts : +4-6 secondes
- Requête 4-sauts : +6-10 secondes
Atténuation :
- Sous-requêtes parallèles quand possible
- Cache des décompositions courantes
- Utiliser des LLMs plus rapides pour les étapes intermédiaires
Coût
Plus d'appels LLM = coût plus élevé :
- Décomposition : 1 appel LLM
- Chaque sous-question : 1 appel LLM
- Validation (optionnelle) : 1 appel par sous-question
Exemple :
- 3 sous-questions + validation = 7 appels LLM
- vs. 1 appel pour RAG standard
Multiplicateur de coût : 2-5x selon la complexité
Quand utiliser
Utiliser DecomposeRAG quand :
- Les questions sont complexes (multi-sauts)
- La précision est plus importante que la vitesse
- Le budget permet des coûts plus élevés
Utiliser RAG standard quand :
- Recherches simples
- Vitesse critique
- Sensible au coût
Directions futures
Améliorations prévues :
- Meilleure décomposition : Affiner des modèles plus petits
- Stratégie adaptive : Détecter automatiquement quand décomposer
- Raffinement itératif : Réessayer les sous-questions échouées
- Multimodal : Décomposer à travers modalités
Ressources
- Article : "DecomposeRAG: Automatic Query Decomposition for Multi-Hop Question Answering"
- Code : github.com/berkeley-nlp/decomposerag
- Démo : decomposerag.demo.berkeley.edu
Conclusion
DecomposeRAG démontre qu'une décomposition explicite des requêtes améliore significativement les réponses aux questions multi-sauts. Bien que plus coûteux et plus lent que le RAG standard, les gains de précision justifient le surcoût pour les requêtes complexes où l'exactitude est critique.
Tags
Articles connexes
Microsoft Research introduit GraphRAG : combinaison des graphes de connaissances avec le RAG
Microsoft Research dévoile GraphRAG, une nouvelle approche qui combine le RAG avec les graphes de connaissances pour améliorer la compréhension contextuelle
Évaluation automatique du RAG : nouveau framework atteint 95% de corrélation avec les jugements humains
Google Research introduit AutoRAGEval, un framework d'évaluation automatisé qui évalue fiablement la qualité du RAG sans annotation humaine.
Nouvelle recherche : le re-ranking par cross-encoder améliore la précision du RAG de 40%
L'étude du MIT démontre que la récupération en deux étapes avec re-ranking par cross-encoder surpasse significativement la recherche vectorielle en une seule étape sur plusieurs benchmarks.