Illustration for the post Comment ingérer des pages web pour le RAG avec LangChain ?

Deux techniques pour ingérer des pages web pour le RAG : BeautifulSoup vs Docling

Par Eric Burel - Formateur chez LBKE

Publié le

Les IA génératives hallucinent, un article de recherche vient même de prouver que c’est inévitable.

Mais on peut tout de même réduire ce risque grâce à l’architecture RAG ou “génération augmentée par une recherche”.

L’idée est simple : au lieu de laisser le LLM répondre directement à une question, on récupère d’abord une documentation en ligne ou dans une base de données. Le LLM donne ensuite de meilleures réponses.

Par exemple, on peut générer des programmes LangChain toujours corrects en fournissant au LLM les bonnes pages de documentation.

Dans un article précédent, nous avons décrit les 5 étapes pour construire un RAG.

Dans cet article, on se concentre en particulier sur l’ingestion des pages web.

Technique n°1 : extraction web de base avec BeautifulSoup

Le WebBaseLoader de LangChain offre une approche simple pour l’extraction de données web.

Il utilise BeautifulSoup, une librairie Python pour analyser les documents HTML.

On peut configurer le loader pour extraire des éléments spécifiques de la page.

from langchain_community.document_loaders import WebBaseLoader
import bs4

loader = WebBaseLoader(
    "https://python.langchain.com/docs/tutorials/llm_chain/",
	# On ne récupère que le tag <article>
    bs_kwargs={"parse_only": bs4.SoupStrainer("article")}
)
# On obtient des documents LangChain à partir de la page web
docs = loader.load()

Le code ci-dessus cible uniquement l’élément <article>, ignorant les menus de navigation et les pieds de page.

La documentation WebBaseLoader explique toutes les options de configuration pour cibler des éléments HTML spécifiques.

Pourquoi le HTML ne suffit pas ?

Malheureusement, cette approche produit souvent des résultats sous-optimaux. Le HTML a tendance à être assez bruité, il peut contenir des restes de scripts JavaScript, des classes CSS… Un problème que j’ai rencontré en essayant de contextualiser les réponses de GitHub Copilot avec la documentation de Next.js.

Rappelez-vous : les documents difficiles à lire pour les humains seront tout aussi difficiles à traiter pour les LLM.

Technique n°2 : extraction améliorée avec Docling

Docling fournit une meilleure extraction de contenu en convertissant les pages web en format Markdown.

Markdown est un format simple, lisible par l’humain et par la machine. Il préserve la structure de la page, mais sans la complexité HTML.

from langchain_docling.loader import ExportType, DoclingLoader

loader = DoclingLoader(
    "https://python.langchain.com/docs/tutorials/llm_chain/", 
    export_type=ExportType.MARKDOWN
)
# On obtient le même contenu, mais en markdown!
docs = loader.load()

La documentation de Docling détaille les capacités d’ingestion de ce loader.

Optimiser les résultats en combinant HTML + Markdown

Vous pouvez améliorer la qualité du contenu en combinant différents outils en plusieurs étapes.

Par exemple, utilisez BeautifulSoup pour le traitement HTML initial, puis appliquez des outils comme turndown ou markdownify pour la conversion HTML vers Markdown.

Il existe d’autres loaders LangChain pour les usages plus avancés, par exemple :

L’étape d’après : découper les documents

Il nous reste un dernier problème à régler : les pages web sont souvent trop longues.

Fournir directement un long contenu ne fonctionne pas. Les LLM récents peuvent gérer de très longs contextes, mais leurs réponses perdent en fait en qualité. Ils n’ont pas une très grande capacité de concentration !

Les longs documents web nécessitent un découpage en morceaux (“chunks”) plus petits, tout en gardant les informations liées ensemble.

Le chunking peut rapidement devenir complexe. Dans le cas d’une page web ingérée en Markdown, on peut utiliser le MarkdownHeaderTextSplitter, qui va s’appuyer sur les niveaux de titre pour découper le texte.

from langchain_text_splitters import MarkdownHeaderTextSplitter

# Splitter fondé sur les en-têtes markdown :
splitter = MarkdownHeaderTextSplitter([
    ("#", "title 1"), 
    ("##", "title 2"), 
    ("###", "title 3")
])

docs = splitter.split_text(markdown_content)

Les stratégies avancées incluent :

Le chunking est considéré comme l’une des meilleures pratiques pour la recherche vectorielle d’après la documentation de Milvus.

Conclusion : plusieurs techniques aident à ingérer des pages web pour le RAG

BeautifulSoup fonctionne bien pour l’analyse HTML avancée. Mais Docling permet de procéder directement à une conversion Markdown, très pratique pour une ingestion rapide quand la page est bien structurée.

Bien sûr, on peut aussi combiner ces deux outils, ou encore adopter des techniques plus élaborées pour ingérer des sites web.

Ce travail préalable garantit ensuite des réponses de qualité et une forte réduction des hallucinations. Le RAG fait partie du context engineering, c’est-à-dire l’art de fournir le bon contexte au LLM pour obtenir les bons résultats.

Pour les développeurs LLM, maîtriser le RAG est fondamental. Le RAG avec LangChain est l’objet du premier jour de notre formation à LangChain/LangGraph.

Vous avez apprécié cette ressource ?

Découvrez toutes nos formations Next.js, Astro.js et LangChain en présentiel ou en distanciel

Voir toutes les ressources

À propos de l'auteur

Photo d'Eric Burel

Eric Burel est ingénieur diplômé de l'ENSIMAG. Il est co-fondateur de LBKE et formateur web et IA.

Il partage régulièrement ses connaissances à travers des articles publiés sur Smashing Magazine et sur son blog. Vous le croiserez sûrement au détour d'un meetup sur Montpellier !

En savoir plus sur Eric Burel

Partager sur Bluesky Partager sur X
Flux RSS