Cas d'usage 1: Fichier PDF

Implémentation de RAG sur un fichier PDF court ou long

Implémentation de RAG sur un Fichier PDF

Les documents PDF sont l'un des formats les plus courants pour le partage d'informations structurées. Dans ce cas d'usage, nous allons explorer comment implémenter la technique Naive RAG sur un fichier PDF, en distinguant deux scénarios : les PDF courts (moins de 3 pages) et les PDF longs (plus de 50 pages).

Comparaison des Approches pour PDF Courts et Longs

La stratégie de traitement diffère significativement selon la longueur du document PDF :

Traitement RAG sur un fichier PDF PDF COURT (< 3 pages) PDF LONG (> 50 pages) +------------------+ +------------------+ | Fichier PDF | | Fichier PDF | | (< 3 pages) | | (> 50 pages) | +------------------+ +------------------+ | | v v +------------------+ +------------------+ | Extraction | | Extraction | | de texte | | de texte | +------------------+ +------------------+ | | v v +------------------+ +------------------+ | Traitement | | Segmentation | | du document | | en sections | | entier | +------------------+ +------------------+ | | v | +------------------+ | | Chunking | | | (500-1000 tokens)| | +------------------+ | | v v +------------------+ +------------------+ | Vectorisation | | Vectorisation | | du document | | des chunks | +------------------+ +------------------+ | | v v +------------------+ +------------------+ | Stockage dans | | Stockage dans | | base vectorielle | | base vectorielle | +------------------+ +------------------+ | | v v +------------------+ +------------------+ | Requête | | Requête | | utilisateur | | utilisateur | +------------------+ +------------------+ | | v v +------------------+ +------------------+ | Récupération | | Récupération | | du document | | des chunks | | pertinent | | pertinents | +------------------+ +------------------+ | | v v +------------------+ +------------------+ | Génération | | Génération | | de réponse | | de réponse | +------------------+ +------------------+ Avantages PDF court: Avantages PDF long: - Traitement simple - Réponses plus précises - Contexte complet - Utilisation efficace du - Implémentation rapide contexte pertinent - Gestion de grands volumes

Implémentation pour PDF Court (< 3 pages)

Pour les PDF courts, l'approche est simplifiée car nous pouvons traiter le document entier comme une seule unité.

Étape 1: Installation des dépendances

pip install langchain pypdf openai chromadb

Étape 2: Extraction du texte du PDF

import os
from langchain.document_loaders import PyPDFLoader

# Charger le PDF
loader = PyPDFLoader("chemin/vers/document_court.pdf")
documents = loader.load()

# Pour un PDF court, nous pouvons simplement concaténer tout le texte
text_content = " ".join([doc.page_content for doc in documents])

Étape 3: Création de l'embedding et stockage

from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma

# Initialiser le modèle d'embedding
embeddings = OpenAIEmbeddings()

# Pour un document court, nous pouvons créer un seul document
from langchain.schema import Document
doc = Document(page_content=text_content, metadata={"source": "document_court.pdf"})

# Créer la base vectorielle
vectorstore = Chroma.from_documents([doc], embeddings)

Étape 4: Configuration du modèle de langage

from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA

# Initialiser le modèle de langage
llm = ChatOpenAI(model_name="gpt-3.5-turbo")

# Créer la chaîne de traitement RAG
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",  # "stuff" est adapté pour les documents courts
    retriever=vectorstore.as_retriever()
)

Étape 5: Interrogation du système

# Poser une question
query = "Quel est le sujet principal de ce document?"
response = qa_chain.run(query)
print(response)

Implémentation pour PDF Long (> 50 pages)

Pour les PDF longs, nous devons adopter une approche de chunking pour diviser le document en segments gérables.

Étape 1: Installation des dépendances

pip install langchain pypdf openai chromadb tiktoken

Étape 2: Extraction et segmentation du texte

import os
from langchain.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter

# Charger le PDF
loader = PyPDFLoader("chemin/vers/document_long.pdf")
documents = loader.load()

# Diviser le texte en chunks
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200,
    length_function=len
)
chunks = text_splitter.split_documents(documents)

Étape 3: Création des embeddings et stockage

from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma

# Initialiser le modèle d'embedding
embeddings = OpenAIEmbeddings()

# Créer la base vectorielle avec tous les chunks
vectorstore = Chroma.from_documents(chunks, embeddings)

Étape 4: Configuration du modèle de langage

from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA

# Initialiser le modèle de langage
llm = ChatOpenAI(model_name="gpt-3.5-turbo")

# Créer la chaîne de traitement RAG
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="map_reduce",  # "map_reduce" est adapté pour les documents longs
    retriever=vectorstore.as_retriever(search_kwargs={"k": 5})  # Récupérer les 5 chunks les plus pertinents
)

Étape 5: Interrogation du système

# Poser une question
query = "Résumez les principales conclusions du chapitre 3."
response = qa_chain.run(query)
print(response)

Implémentation dans n8n

Voici comment implémenter un workflow RAG pour PDF dans n8n :

Workflow pour PDF Court

  1. HTTP Request Node : Pour déclencher le workflow via une API
  2. Read Binary File Node : Pour lire le fichier PDF
  3. Code Node : Pour extraire le texte du PDF avec PyPDF
    const { PythonShell } = require('python-shell');
    const fs = require('fs');
    
    // Écrire le PDF dans un fichier temporaire
    const pdfBuffer = $input.item.binary.data;
    fs.writeFileSync('/tmp/temp.pdf', Buffer.from(pdfBuffer, 'base64'));
    
    // Script Python pour extraire le texte
    const pythonScript = `
    import pypdf
    reader = pypdf.PdfReader('/tmp/temp.pdf')
    text = ""
    for page in reader.pages:
        text += page.extract_text()
    print(text)
    `;
    
    // Exécuter le script Python
    return new Promise((resolve, reject) => {
      PythonShell.runString(pythonScript, null, (err, results) => {
        if (err) reject(err);
        else resolve([{json: {text: results[0]}}]);
      });
    });
  4. OpenAI Node : Pour créer l'embedding du document
  5. Function Node : Pour stocker l'embedding dans une base de données
  6. OpenAI Node : Pour générer une réponse basée sur la requête et le document
  7. Respond to Webhook Node : Pour renvoyer la réponse

Workflow pour PDF Long

  1. HTTP Request Node : Pour déclencher le workflow via une API
  2. Read Binary File Node : Pour lire le fichier PDF
  3. Code Node : Pour extraire et segmenter le texte du PDF
    const { PythonShell } = require('python-shell');
    const fs = require('fs');
    
    // Écrire le PDF dans un fichier temporaire
    const pdfBuffer = $input.item.binary.data;
    fs.writeFileSync('/tmp/temp.pdf', Buffer.from(pdfBuffer, 'base64'));
    
    // Script Python pour extraire et segmenter le texte
    const pythonScript = `
    import pypdf
    import json
    
    reader = pypdf.PdfReader('/tmp/temp.pdf')
    chunks = []
    
    # Extraire le texte page par page
    for i, page in enumerate(reader.pages):
        text = page.extract_text()
        
        # Diviser en paragraphes
        paragraphs = text.split('\\n\\n')
        
        # Créer des chunks de taille raisonnable
        current_chunk = ""
        for para in paragraphs:
            if len(current_chunk) + len(para) < 1000:
                current_chunk += para + " "
            else:
                chunks.append({"text": current_chunk, "page": i+1})
                current_chunk = para + " "
        
        if current_chunk:
            chunks.append({"text": current_chunk, "page": i+1})
    
    print(json.dumps(chunks))
    `;
    
    // Exécuter le script Python
    return new Promise((resolve, reject) => {
      PythonShell.runString(pythonScript, null, (err, results) => {
        if (err) reject(err);
        else {
          const chunks = JSON.parse(results[0]);
          return resolve([{json: {chunks}}]);
        }
      });
    });
  4. Split In Batches Node : Pour traiter les chunks par lots
  5. OpenAI Node : Pour créer les embeddings de chaque chunk
  6. Function Node : Pour stocker les embeddings dans une base de données
  7. HTTP Request Node : Pour recevoir la requête de l'utilisateur
  8. OpenAI Node : Pour créer l'embedding de la requête
  9. Function Node : Pour rechercher les chunks les plus similaires
  10. OpenAI Node : Pour générer une réponse basée sur la requête et les chunks pertinents
  11. Respond to Webhook Node : Pour renvoyer la réponse

Considérations Pratiques

Choix entre les approches

Le choix entre l'approche pour PDF court ou long dépend principalement de :

Optimisations possibles