AI Prompt Engineering · Leçon

Réécriture des requêtes et HyDE

Améliorer le rappel de la récupération.

Leçon 4 sur 413 étapes

Réécriture des requêtes et HyDE est une leçon AI Prompt Engineering gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage AI Prompt Engineering, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours AI Prompt Engineering comprend 4 leçons au total.

La requête est le maillon faible

La qualité de la récupération est limitée par la requête. Les requêtes brutes des utilisateurs sont souvent courtes, ambiguës, pleines de pronoms ou formulées différemment des documents. La transformation de requête remodèle la requête avant la récupération afin d’améliorer le rappel et la précision.

C’est l’une des améliorations les moins coûteuses et les plus efficaces par rapport à un RAG naïf : corrigez la requête et toutes les étapes en aval en bénéficieront.

def transform_query(raw, history):
    # Resolve references, expand, decompose, or hypothesize
    # BEFORE embedding and retrieving.
    return rewrite(raw, history)

Réécriture de requête

Il s’agit de la transformation la plus simple : un LLM réécrit la requête de l’utilisateur sous une forme plus claire, autonome et adaptée à la récupération. Il corrige les fautes de frappe, développe les abréviations et supprime le bruit conversationnel.

C’est particulièrement important dans une conversation à plusieurs tours, lorsque le dernier message est incompréhensible sans contexte (Et le deuxième ?).

def rewrite_query(raw):
    prompt = (
        'Rewrite the user question into a clear, standalone search '
        'query optimized for document retrieval. Keep key entities.\n'
        'Question: ' + raw
    )
    return llm(prompt, temperature=0).strip()

Condensation conversationnelle

Dans un RAG conversationnel, condensez le dialogue et le nouveau tour en une seule question autonome. Sans cette étape, les pronoms et les ellipses rendent la représentation vectorielle dépourvue de sens et la récupération s’effondre.

Transmettez les tours précédents afin que le réécrivain puisse convertir « cela », « celui-là » et « le précédent » en entités explicites que le moteur de récupération pourra retrouver.

def condense(history, follow_up):
    prompt = (
        'Given the conversation, rewrite the follow-up as a standalone '
        'question with all references resolved.\nConversation:\n' +
        render(history) + '\nFollow-up: ' + follow_up
    )
    return llm(prompt, temperature=0).strip()

Expansion de requête

L’expansion génère des synonymes, des termes associés ou des formulations différentes afin d’élargir la couverture lexicale et sémantique. Elle lutte contre le décalage de vocabulaire : le document dit « invalider », tandis que l’utilisateur dit « révoquer ».

Développez la requête pour la récupération, puis récupérez avec l’union des résultats ; n’affichez pas la forme développée à l’utilisateur. Méfiez-vous de l’expansion excessive, qui peut faire remonter des résultats hors sujet.

def expand(query, n=3):
    prompt = (
        'List ' + str(n) + ' alternative phrasings of this query using '
        'synonyms and domain terms, one per line.\n' + query
    )
    variants = parse_lines(llm(prompt, temperature=0.5))
    return [query] + variants

Récupération multi-requêtes

Générez plusieurs reformulations différentes, récupérez des résultats pour chacune, puis fusionnez les listes de résultats (fusion des rangs réciproques). Des formulations différentes font apparaître des segments pertinents différents ; la fusion combine leurs points forts et stabilise le rappel.

Cette méthode échange des appels de récupération supplémentaires contre une meilleure robustesse face à une formulation défaillante unique.

def multi_query(raw, n=4):
    queries = expand(raw, n)
    rankings = [dense_retrieve(q, 30) for q in queries]
    fused = rrf(*rankings)
    return dedup(fused)

Décomposition de requête

Les questions complexes à plusieurs étapes nécessitent une décomposition en sous-questions, chacune étant récupérée séparément avant d’être combinée. Demander quel CEO de l’entreprise ayant acquis X est plus âgé que... ne peut pas être résolu par une seule récupération.

Décomposez la question, récupérez les résultats pour chaque sous-question et laissez le générateur combiner les éléments de preuve rassemblés.

def decompose_and_retrieve(question):
    subs = parse_lines(llm(
        'Break this into independent sub-questions, one per line.\n' +
        question, temperature=0))
    evidence = {s: rerank(s, dense_retrieve(s, 30))[:3] for s in subs}
    return evidence  # generator synthesizes the final answer

HyDE : l’idée centrale

HyDE (représentations vectorielles de documents hypothétiques, Gao et al., 2022) inverse le problème. Au lieu de représenter vectoriellement la courte requête, il demande au LLM de générer un document-réponse hypothétique, puis représente celui-ci vectoriellement et l’utilise pour la récupération.

Le document hypothétique emploie le même registre que les documents réels. Sa représentation vectorielle est donc plus proche de celles des véritables réponses, ce qui corrige le décalage entre la requête et le document.

def hyde(query):
    hypo = llm(
        'Write a short passage that would answer this question, as if '
        'from a reference document.\nQuestion: ' + query,
        temperature=0.3)
    return dense_retrieve_by_vector(embed(hypo), k=30)  # embed the answer

Pourquoi HyDE améliore le rappel

Une question et sa réponse sont formulées différemment ; une question et une réponse fausse mais plausible sont formulées de manière similaire à la véritable réponse. HyDE exploite l’a priori génératif du LLM pour combler cet écart, même si le contenu hypothétique comporte des erreurs factuelles.

L’exactitude du document hypothétique importe peu : celui-ci doit seulement avoir le vocabulaire et la structure adéquats pour se situer près des vrais documents dans l’espace des représentations vectorielles.

# Robustness: average several hypothetical docs to reduce variance
def hyde_avg(query, n=3):
    vecs = [embed(llm(HYDE_PROMPT + query, temperature=0.5))
            for _ in range(n)]
    centroid = sum(vecs) / n
    return dense_retrieve_by_vector(centroid, 30)

Compromis et modes d’échec de HyDE

HyDE ajoute une génération par LLM avant la récupération, ce qui augmente la latence et les coûts, et peut halluciner un contenu hypothétique qui s’écarte du sujet. Cela nuit au rappel pour les requêtes de niche ou hors distribution, sur lesquelles le modèle ne dispose d’aucune connaissance.

Atténuez ce risque en combinant la récupération par vecteur HyDE avec la récupération à partir de la requête brute au moyen d’une fusion, afin qu’un mauvais contenu hypothétique ne puisse pas faire chuter complètement le rappel.

def hyde_hybrid(query):
    a = dense_retrieve_by_vector(embed(hyde_doc(query)), 30)
    b = dense_retrieve(query, 30)          # raw-query fallback
    return dedup(rrf(a, b))                 # robust to bad hypotheticals

Choisir et combiner les techniques

Ces transformations sont complémentaires. Utilisez la condensation pour les conversations, l’expansion et les requêtes multiples pour combler les lacunes de vocabulaire, la décomposition pour les questions à plusieurs étapes et HyDE en cas de décalage de registre entre la question et le document. De nombreuses architectures de production enchaînent la condensation, puis HyDE, puis la fusion avec la requête brute, avant le réordonnancement.

Chaque transformation supplémentaire coûte un appel à un LLM ; activez-les donc selon le type de requête plutôt que de les exécuter systématiquement toutes.

def route_transform(query, history, qtype):
    q = condense(history, query) if history else query
    if qtype == 'multi_hop': return decompose_and_retrieve(q)
    if qtype == 'mismatch':  return hyde_hybrid(q)
    if qtype == 'vocab_gap': return multi_query(q)
    return dense_retrieve(q, 30)

Évaluer les transformations

Mesurez chaque transformation en fonction de son gain en rappel@k de la récupération et en exactitude de la réponse finale par rapport à la requête brute, sur un ensemble exempt de fuites. Suivez la latence ajoutée et le coût des LLM afin de ne conserver que les transformations qui sont rentables.

Attention : une transformation qui améliore le rappel tout en ajoutant des éléments distrayants peut réduire l'exactitude de la réponse, sauf si elle est associée à un réordonnancement et à une compression.

def eval_transform(name, fn, eval_set):
    return {
        'recall@10': recall_at_k(eval_set, retriever=fn, k=10),
        'answer_acc': answer_accuracy(eval_set, retriever=fn),
        'extra_latency_ms': transform_latency(fn),
    }

Vérification rapide

Réfléchissez aux raisons pour lesquelles HyDE fonctionne malgré des hypothèses imparfaites.

Récapitulatif

Points essentiels :

  • La récupération est limitée par la requête ; la transformer constitue une mise à niveau RAG peu coûteuse et à fort effet de levier.
  • La réécriture et la condensation rendent les requêtes de conversation autonomes ; l'expansion et les requêtes multiples comblent les lacunes de vocabulaire.
  • La décomposition traite les questions à sauts multiples en récupérant des résultats pour chaque sous-question.
  • HyDE intègre une réponse hypothétique pour combler le décalage de registre entre la question et le document ; l'exactitude de l'hypothèse n'est pas requise.
  • Combinez les transformations selon le type de requête, fusionnez-les avec la requête brute pour plus de robustesse, puis évaluez le rappel, l'exactitude de la réponse, la latence et le coût.
Gratuit pour commencer

Apprends AI Prompt Engineering avec un tuteur IA — gratuit

Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.

Cours
53
Leçons
199

Questions Fréquemment Posées

La leçon « Réécriture des requêtes et HyDE » est-elle gratuite ?

Oui — le texte complet de « Réécriture des requêtes et HyDE » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours AI Prompt Engineering, passe à CoddyKit PRO. Le cours AI Prompt Engineering comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Réécriture des requêtes et HyDE » ?

Améliorer le rappel de la récupération. Tu pratiques AI Prompt Engineering avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer AI Prompt Engineering ?

Aucune expérience préalable n'est requise. AI Prompt Engineering sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.

Combien de temps prend la leçon « Réécriture des requêtes et HyDE » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon AI Prompt Engineering ?

Oui. Chaque leçon AI Prompt Engineering inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Au-delà du RAG naïf
  2. Réordonner les fragments récupérés
  3. Compression du contexte
  4. Réécriture des requêtes et HyDE
← Retour à AI Prompt Engineering