chatPDF clone sans base vectorielle

Cet exemple est plus facile à comprendre

Installer les module Python suivants

pip install PyPDF2
pip install openai
pip install tiktoken
#!/usr/bin/env python3
"""
ChatPDF Simple - Version corrigée pour OpenAI v1.0+
Permet d'extraire le texte d'un PDF et de poser des questions dessus
Sans base vectorielle
"""

import PyPDF2
from openai import OpenAI
import os
import argparse
import sys
from typing import List, Optional
import tiktoken
import re


class ChatPDF:
    def __init__(self, api_key: Optional[str] = None):
        """
        Initialise ChatPDF avec la clé API OpenAI
        """
        self.api_key = 'sk-proj-BBXFnLZzRMt8EZp4LStJXyfzc_6knvyK'
        if not self.api_key:
            raise ValueError("Clé API OpenAI requise. Définissez OPENAI_API_KEY ou passez api_key")

        self.client = OpenAI(api_key=self.api_key)
        self.pdf_content = ""
        self.pdf_path = ""
        self.encoding = tiktoken.get_encoding("cl100k_base")

    def extract_text_from_pdf(self, pdf_path: str) -> str:
        """
        Extrait tout le texte d'un fichier PDF
        """
        try:
            with open(pdf_path, 'rb') as file:
                pdf_reader = PyPDF2.PdfReader(file)
                text = ""

                print(f"Extraction du texte de {len(pdf_reader.pages)} pages...")

                for page_num, page in enumerate(pdf_reader.pages):
                    try:
                        page_text = page.extract_text()
                        text += f"\n--- Page {page_num + 1} ---\n{page_text}\n"
                    except Exception as e:
                        print(f"Erreur lors de l'extraction de la page {page_num + 1}: {e}")
                        continue

                self.pdf_content = text
                self.pdf_path = pdf_path
                print(f"Extraction terminée. {len(text)} caractères extraits.")
                return text

        except FileNotFoundError:
            raise FileNotFoundError(f"Fichier PDF non trouvé: {pdf_path}")
        except Exception as e:
            raise Exception(f"Erreur lors de la lecture du PDF: {e}")

    def chunk_text(self, text: str, max_tokens: int = 3000) -> List[str]:
        """
        Divise le texte en chunks pour respecter les limites de tokens
        """
        sentences = re.split(r'[.!?]+', text)
        chunks = []
        current_chunk = ""

        for sentence in sentences:
            sentence = sentence.strip()
            if not sentence:
                continue

            test_chunk = current_chunk + " " + sentence if current_chunk else sentence

            if len(self.encoding.encode(test_chunk)) <= max_tokens:
                current_chunk = test_chunk
            else:
                if current_chunk:
                    chunks.append(current_chunk)
                current_chunk = sentence

        if current_chunk:
            chunks.append(current_chunk)

        return chunks

    def ask_question(self, question: str, model: str = "gpt-3.5-turbo") -> str:
        """
        Pose une question sur le contenu du PDF
        """
        if not self.pdf_content:
            return "Aucun PDF chargé. Veuillez d'abord extraire le contenu d'un PDF."

        # Préparer le contexte
        chunks = self.chunk_text(self.pdf_content, max_tokens=3000)

        # Si le document est court, utiliser tout le contenu
        if len(chunks) == 1:
            context = chunks[0]
        else:
            # Pour des documents longs, prendre les premiers chunks
            context = " ".join(chunks[:2])  # Utiliser les 2 premiers chunks
        print(('======'))
        print(context)
        print(('======'))

        prompt = f"""
Vous êtes un assistant qui répond aux questions basées sur le contenu d'un document PDF.

Contenu du document:
{context}

Question: {question}

Instructions:
- Répondez uniquement basé sur le contenu fourni
- Si l'information n'est pas dans le document, dites-le clairement
- Citez des passages spécifiques quand c'est pertinent
- Soyez précis et concis

Réponse:"""

        try:
            response = self.client.chat.completions.create(
                model=model,
                messages=[
                    {"role": "system", "content": "Vous êtes un assistant spécialisé dans l'analyse de documents PDF."},
                    {"role": "user", "content": prompt}
                ],
                max_tokens=500,
                temperature=0.1
            )

            return response.choices[0].message.content.strip()

        except Exception as e:
            return f"Erreur lors de la génération de la réponse: {e}"

    def summarize_pdf(self) -> str:
        """
        Génère un résumé du PDF
        """
        if not self.pdf_content:
            return "Aucun PDF chargé."

        chunks = self.chunk_text(self.pdf_content, max_tokens=3000)
        context = " ".join(chunks[:3])  # Utiliser les 3 premiers chunks

        prompt = f"""
Veuillez créer un résumé concis du document suivant:

{context}

Le résumé doit:
- Capturer les points clés et idées principales
- Être structuré et facile à lire
- Faire environ 200-300 mots maximum

Résumé:"""

        try:
            response = self.client.chat.completions.create(
                model="gpt-3.5-turbo",
                messages=[
                    {"role": "system", "content": "Vous créez des résumés clairs et concis de documents."},
                    {"role": "user", "content": prompt}
                ],
                max_tokens=400,
                temperature=0.2
            )

            return response.choices[0].message.content.strip()

        except Exception as e:
            return f"Erreur lors de la génération du résumé: {e}"


def main():
    parser = argparse.ArgumentParser(description="ChatPDF Simple - Analyseur de PDF avec IA")
    parser.add_argument("pdf_path", help="Chemin vers le fichier PDF")
    parser.add_argument("--api-key", help="Clé API OpenAI (ou utilisez la variable d'environnement OPENAI_API_KEY)")
    parser.add_argument("--model", default="gpt-3.5-turbo", help="Modèle OpenAI à utiliser")

    args = parser.parse_args()

    try:
        # Initialiser ChatPDF
        chat_pdf = ChatPDF(api_key=args.api_key)

        # Extraire le texte du PDF
        print(f"Chargement du PDF: {args.pdf_path}")
        chat_pdf.extract_text_from_pdf(args.pdf_path)

        # Générer un résumé automatique
        print("\n=== RÉSUMÉ AUTOMATIQUE ===")
        summary = chat_pdf.summarize_pdf()
        print(summary)

        # Mode interactif pour les questions
        print("\n=== MODE QUESTIONS-RÉPONSES ===")
        print("Posez vos questions sur le document (tapez 'quit' pour quitter):")

        while True:
            try:
                question = input("\n❓ Votre question: ").strip()

                if question.lower() in ['quit', 'exit', 'q']:
                    break

                if not question:
                    continue

                print("🤔 Recherche de la réponse...")
                answer = chat_pdf.ask_question(question, model=args.model)
                print(f"\n💡 Réponse:\n{answer}")

            except KeyboardInterrupt:
                break
            except Exception as e:
                print(f"Erreur: {e}")

        print("\nAu revoir!")

    except Exception as e:
        print(f"Erreur: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()

# Exemple d'utilisation en tant que module
"""
from chatpdf_simple import ChatPDF

# Initialiser
chat = ChatPDF(api_key="votre_clé_api")

# Charger un PDF
chat.extract_text_from_pdf("document.pdf")

# Poser des questions
response = chat.ask_question("Quels sont les points principaux de ce document?")
print(response)

# Générer un résumé
summary = chat.summarize_pdf()
print(summary)
"""

Usage

Macos
python3 main.py  document.pdf
Windows
python main.py document.pdf
Retour en haut