Accueil / Articles / Notes pratiques : Grouper les données parents-enfants et indexation hiérarchique dans RAG : A

Notes pratiques : Grouper les données parents-enfants et indexation hiérarchique dans RAG : A

Guide opérationnel des notes pratiques : Grouper les données en paires parent-enfant et indexation hiérarchique dans RAG : A : contrats, vérifications et emplacements de code prêts à l’emploi pour les équipes utilisant ce modèle.

2451 mots

Ce guide reconstitue le processus allant des matières premières à un système fonctionnel pour : Parent–Child Chunking and Hierarchical Indexing in RAG: A Practical Guide to Better Retrieval. L’accent est mis sur des étapes opérationnelles, des vérifications explicites et du code que vous pouvez intégrer directement dans un dépôt sans devoir deviner l’intention derrière les actions. Pour l’étape d’aperçu, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans avoir à deviner l’état caché. Documentez conjointement le parcours normal et les scénarios de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’une mise en forme ultérieure.

Pourquoi le chunking est en réalité la partie la plus difficile de RAG

Lorsque vous travaillez sur la question de savoir pourquoi le chunking constitue en réalité une étape, notez d’abord les exigences : entrées requises, signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Préférez des unités petites et testables à des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Évaluez le taux de rappel sur un ensemble de questions fixe avant d’ajuster les prompts. Un changement fréquent des prompts ne résout que rarement un système de récupération insuffisant.

Un exemple typique d’échec

Lors de l’étape consacrée à un exemple typique d’échec, notez d’abord les conditions prévues : les entrées requises, le signal de succès, ainsi que ce qui se produit en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux éléments générés, définez des vérifications de succès, et refusez toute exécution partielle silencieuse. Évaluez le taux de rappel sur un ensemble de questions fixe avant d’ajuster les prompts. Un simple changement de prompt ne résout que rarement un système de récupération insuffisant.

from sentence_transformers import SentenceTransformer
import numpy as np

model = SentenceTransformer("all-MiniLM-L6-v2")

def cosine_similarity(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

query = "What is a risk of caching?"
chunk_a = "Caching improves system performance significantly."
chunk_b = "However, improper cache invalidation can lead to stale data issues."

query_embedding = model.encode(query)
score_a = cosine_similarity(query_embedding, model.encode(chunk_a))
score_b = cosine_similarity(query_embedding, model.encode(chunk_b))

print(f"Chunk A similarity: {score_a:.4f}  - '{chunk_a}'")
print(f"Chunk B similarity: {score_b:.4f}  - '{chunk_b}'")
Chunk A similarity: 0.5891  — 'Caching improves system performance significantly.'
Chunk B similarity: 0.5103  — 'However, improper cache invalidation can lead to stale data issues.'

Chunking parent-enfant

Lors de la phase d’agrégation en éléments parent/enfant, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût en tokens ou requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le système passe de l’environnement de démonstration à des environnements partagés. Mesurez le taux de rappel sur un ensemble fixe de questions avant d’ajuster les prompts. Changer fréquemment les prompts ne résout que rarement un système de récupération insuffisant. Lors de la phase d’agrégation en éléments parent/enfant, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’intégrité des modifications ultérieures du code. Documentez à la fois le parcours optimal et les procédures de récupération. Les tentatives de réexécution, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’améliorations apportées ultérieurement.

Comment cela fonctionne en pratique

La méthode « Comment ça marche en phase » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemple réussi, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’erreur doit pointer vers une seule responsabilité plutôt que vers un processus embrouillé. Séparez la politique de segmentation de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité changent.

def build_parent_child_index(document_section, parent_text, child_splitter, embedding_model):
    child_chunks = child_splitter(parent_text)
    records = []
    for child_text in child_chunks:
        records.append({
            "text": child_text,
            "embedding": embedding_model.encode(child_text),
            "parent_text": parent_text  # full parent stored directly on every child
        })
    return records


parent_text = """Indexing improves query speed by reducing scan time across large tables.
Caching reduces repeated computation but may introduce staleness if not invalidated properly.
Query optimization involves rewriting SQL queries to use more efficient execution plans."""

child_texts = [
    "Indexing improves query speed by reducing scan time across large tables.",
    "Caching reduces repeated computation but may introduce staleness if not invalidated properly.",
    "Query optimization involves rewriting SQL queries to use more efficient execution plans.",
]

records = [
    {"text": t, "parent_text": parent_text} for t in child_texts
]

for r in records:
    print(f"Child: {r['text'][:50]}...")
    print(f"  → linked to parent ({len(r['parent_text'])} chars)\n")

L’idée clé : récupérer petit, étendre grand

L’idée clé est que l’étape de récupération fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript parfait, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès et refusez toute complétion partielle silencieuse. Séparez la politique de segmentation de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité évoluent.

def parent_child_retrieve(query, child_records, embedding_model, top_k=3):
    query_embedding = embedding_model.encode(query)
    scored = [
        (np.dot(query_embedding, r["embedding"]) /
         (np.linalg.norm(query_embedding) * np.linalg.norm(r["embedding"])), r)
        for r in child_records
    ]
    scored.sort(key=lambda x: x[0], reverse=True)
    top_children = scored[:top_k]

    # Expand each matched child to its parent - but deduplicate first
    seen_parents = set()
    expanded_context = []

    for score, record in top_children:
        parent = record["parent_text"]
        if parent not in seen_parents:
            expanded_context.append(parent)
            seen_parents.add(parent)

     return expanded_context

for r in records:
    r["embedding"] = model.encode(r["text"])

context = parent_child_retrieve("What is a risk of caching?", records, model, top_k=2)
print("Context sent to the LLM:\n")

for c in context:
    print(c)

Pourquoi cela fonctionne si bien

Cette méthode fonctionne particulièrement bien lorsque l’étape en question est considérée comme une surface mesurable. Capturez un exemple idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de la démonstration aux environnements partagés. Séparez la politique de segmentation de la politique de récupération : modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité évoluent. Cette méthode fonctionne particulièrement bien lorsque l’étape en question est considérée comme une surface mesurable. Capturez un exemple idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez ensemble le parcours optimal et le parcours de récupération. Les tentatives de réessai, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure.

Indexation hiérarchique : aller encore plus loin

Pour mettre en place l’indexation hiérarchique, il convient de définir les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu, sans avoir à deviner l’état caché. Préférer des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Citer les passages qui fondent réellement la réponse. Sans citations, les opérateurs ne peuvent pas distinguer une hallucination d’un manque d’indexation.

Document: "Cloud Architecture Guide"
  Section: Networking
    Subsection: Load Balancing
      Chunk: Round-robin method
      Chunk: Least connections method
    Subsection: CDN usage
  Section: Security
    Subsection: IAM policies
    Subsection: Encryption

Pourquoi la hiérarchie est importante

Pour l’étape où la hiérarchie des raisons est importante, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des vérifications de succès et refusez les terminaisons partielles silencieuses. Citez les passages qui ont réellement servi de base à la réponse. Sans citations, les opérateurs ne peuvent pas distinguer une hallucination d’un manque dans l’indexation.

Récupération hiérarchique en pratique

Pour l’étape de récupération hiérarchique en action, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce du coût évite les factures inattendues lorsque le processus passe d’un environnement de démonstration à des environnements partagés. Citez les passages qui ont réellement servi de base à la réponse. Sans citations, les opérateurs ne peuvent pas distinguer une hallucination d’un manque d’indexation. Pour l’étape de récupération hiérarchique en action, définissez les entrées, le responsable de l’étape et les critères d’arrêt avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez ensemble le parcours optimal et les procédures de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non traités font partie du produit, et non pas…

Polissage final.

Indexation parent-enfant vs indexation hiérarchique

Lors de l’étape comparant l’indexation parent-enfant et l’indexation hiérarchique, notez d’abord les exigences : entrées requises, signal de succès et conséquences en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Préférez des unités petites et testables plutôt que des scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité et non un processus embrouillé. Évaluez le taux de rappel sur un ensemble de questions fixe avant d’ajuster les prompts. Un changement fréquent des prompts ne résout que rarement un système de récupération insuffisant.

Pattern d’implémentation (pipeline RAG en situation réelle)

Lorsque vous travaillez sur l’étape RAG du modèle d’implémentation dans le monde réel, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès et refusez les terminaisons partielles silencieuses. Mesurez le taux de rappel sur un ensemble fixe de questions avant d’ajuster les prompts. Changer fréquemment les prompts ne résout que rarement un système de récupération insuffisant.

Erreurs courantes dans les systèmes réels

Lorsque vous travaillez sur les erreurs fréquentes en environnement réel, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de la démonstration aux environnements partagés. Mesurez le taux de rappel sur un ensemble fixe de questions avant d’ajuster les prompts. Changer fréquemment les prompts ne résout que rarement un système de récupération insuffisant. Lorsque vous travaillez sur les erreurs fréquentes en environnement réel, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Documentez à la fois le parcours optimal et les procédures de récupération. Les tentatives de réessai, les contrôles humains et la gestion des messages non traités font partie intégrante du produit, et non d’une mise en forme ultérieure.

Où cela fait la plus grande différence

C’est pourquoi cette approche fonctionne le mieux lorsque l’ensemble est considéré comme une surface mesurable. Capturez un exemple réussi, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’erreur doit indiquer une seule responsabilité plutôt qu’un processus embrouillé. Séparez la politique de segmentation de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité changent.

Le tableau d’ensemble

La phase d’analyse globale fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un exemple réussi exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des critères de succès et refusez toute mise en œuvre partielle silencieuse. Séparez la politique de segmentation des données de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité évoluent.

Dernière pensée

La phase « Réflexion finale » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de la démonstration aux environnements partagés. Séparez la politique de segmentation de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité évoluent. La phase « Réflexion finale » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Documentez ensemble le parcours réussi et le parcours de récupération. Les tentatives de réessai, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure.

Liste de contrôle opérationnelle

La phase de liste de contrôle opérationnel fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre.

Gardez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système.

Séparez la politique de segmentation des données de la politique de récupération. Modifier l’une ne doit pas obliger à réécrire l’autre lorsque les métriques de qualité changent.

Évaluez séparément les réponses en une seule interaction et les trajectoires nécessitant plusieurs interactions. L’agrégation des scores de conversation masque les échecs liés aux boucles infinies du système.

Rédigez un petit manuel opérationnel : comment rotationner les clés, comment vider la file d’attente, comment effectuer une réversion de la dernière ingestion.

Considérez cette phase comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définites des critères de succès et refusez toute complétion partielle silencieuse.

Au préalable de promouvoir la pile logicielle, figez les versions, conservez une transcription exemplaire pour le chemin critique, et confirmez les étapes de rollback. Les environnements partagés nécessitent des limites de débit, des vérifications d’attribution, ainsi qu’un responsable clair pour la rotation des secrets. Préférez une fiabilité sans faille à des démonstrations brillantes mais ponctuelles.

Note de batch pour de861b3bd2cb : gardez les clés du fournisseur hors du répertoire, fixez un plafond pour les tokens par session, et stockez les transcriptions à côté des fichiers de configuration d’évaluation afin que les remplacements ultérieurs de modèles restent comparables.

Pour la note de renforcement de sécurité relative à l’étape 0, définissez les entrées, le responsable de l’étape et les critères d’achèvement avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu, sans avoir à deviner l’état caché. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définissez des vérifications de succès, et refusez toute exécution partielle silencieuse.

Détail de renforcement 0/954 : mesurez le temps d’exécution, la classe d’erreur et la consommation de tokens pour cette note, puis décidez si vous souhaitez conserver le changement en vous basant sur un ensemble de questions prédéfini plutôt que sur des observations anecdotiques.

Lors de la première étape de la note de renforcement, écrivez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’honnêteté des modifications de code ultérieures. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système.

Détail de renforcement 1/954 : mesurez le temps d’exécution, la classe d’erreur et la consommation de tokens pour cette note, puis décidez si vous souhaitez conserver le changement en vous basant sur un ensemble de questions prédéfini plutôt que sur des observations anecdotiques.

La deuxième étape de la note de renforcement fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement exemplaire, un cas d’échec et la note de réversion avant d’élargir le périmètre. Préférez des unités petites et testables à des scripts complexes. Lorsqu’une étape échoue, l’échec doit pointer vers une seule responsabilité plutôt que vers un processus embrouillé.

Détail de renforcement 2/954 : mesurez le temps d’exécution, la classe d’erreur et l’utilisation des tokens pour cette note, puis décidez si vous souhaitez conserver la modification en vous basant sur un ensemble de questions prédéfini plutôt que sur des anecdotes.