Aller au contenu

Utiliser des documents

Vous trouverez dans le même dossier que ce fichier un fichier reglement_interieur.pdf. Ce document contient le règlement intérieur du lycée Rouvière (Toulon). Pour info, je n'ai strictement rien à voir avec ce lycée (je n'y ai jamais mis les pieds), c'est juste que j'ai pu télécharger ce document sur Internet.

Imaginez que votre but est de construire un chatbot capable de répondre aux questions en rapport avec le règlement intérieur de ce lycée. Pour que ce chatbot soit capable de vous apporter des réponses pertinentes, il faudrait que ce pdf ait été utilisé pour entraîner le modèle, ce qui est peu probable... Nous pouvons quand même essayer :

from dotenv import load_dotenv
from openai import OpenAI
from IPython.display import Markdown, display
import os
load_dotenv()
API_KEY = os.getenv('GOOGLE_API_KEY')
llm = OpenAI(api_key=API_KEY, base_url="https://generativelanguage.googleapis.com/v1beta/openai/")
prompt_system = """Tu dois répondre aux questions portant sur le règlement intérieur de lycée Rouvière de Toulon.
Tu ne dois aborder aucun autre sujet. Si tu ne trouves pas la réponse à la question posée, tu ne dois pas inventer une réponse,
tu dois simplement dire 'Désolé, je n'ai pas la réponse à cette question'.  
"""
msg_prompt_sys = [{'role' : 'system', 'content' : prompt_system}]
msg_user = [{'role' : 'user', 'content' : 'Quel est le rôle de l\'association Sébastien Carpentier au lycée Rouvière ?'}]
msg = msg_prompt_sys + msg_user
response = llm.chat.completions.create(model = 'gemini-2.0-flash', messages = msg)
answer = response.choices[0].message.content
display(Markdown(answer))
[Out]
Désolé, je n'ai pas la réponse à cette question.
Comme prévu, le modèle ne connaît pas la réponse à cette question.

Heureusement, une solution existe : intégrer le pdf au prompt afin que le LLM puisse avoir accès aux informations contenues dans ce fichier. Reprennons le code de zéro :

from dotenv import load_dotenv
from openai import OpenAI
from IPython.display import Markdown, display
from pypdf import PdfReader
import os
load_dotenv()
API_KEY = os.getenv('GOOGLE_API_KEY')
Nous avons importé la bibliothèque pypdf qui va nous permettre de lire le fichier pdf. Commençons par extraire les informations de ce pdf :

reader = PdfReader("./reglement_interieur.pdf")
reglement = ""
for page in reader.pages:
    text = page.extract_text()
    if text:
        reglement += text
L'instance reader de la classe PdfReader nous permet de parcourir le fichier reglement_interieur.pdf page par page (utilisation de la boucle for). Si l'élément extrait d'une page contient du texte, ce texte est concaténé avec le contenu de la variable reglement. A la fin de la boucle la variable reglement contient l'ensemble du règlement intérieur. Comme vous pouvez le vérifier :

print(reglement[:500]) #on affiche unquement les 500 premiers caractères
[Out]
     - 1 - 

    SOMMAIRE DU REGLEMENT INTERIEUR 

    I / CONNAITRE SES DEVOIRS 
    1- Le devoir de respecter les personnes - la laïcité 
    2- Le devoir de respecter les biens individuels et collectifs 
    3- Les devoirs scolaires 

    II / CONNAITRE SES DROITS 
    1- La liberté d’expression 
    2- Le droit de publication et d’affichage 
    3- Le droit de réunion et d’association- la M.D.L., l’association Carpentier et l’A.S. 
    4- Le droit à l’orientation 
    5- Le droit à l’éducation à la santé, à la citoyenneté et à l’enviro
Nous allons maintenant modifier notre prompt afin d'ajouter le contenu de la variable reglement:

prompt_system_2 = f"Tu dois répondre aux questions portant sur le règlement intérieur de lycée Rouvière de Toulon.\
Tu ne dois aborder aucun autre sujet. Si tu ne trouves pas la réponse à la question posée, tu ne dois pas inventer une réponse,\
tu dois simplement dire 'Désolé, je n'ai pas la réponse à cette question'. \
Pour t'aider à répondre aux questions, tu peux consulter le règlement intérieur du lycée Rouvière : \n {reglement}\n"
msg_prompt_sys_2 = [{'role' : 'system', 'content' : prompt_system_2}]
Nous avons cette fois-ci utilisé une f string afin de pouvoir intégrer le contenu de la variable reglement dans la chaîne de caractères.

Rappel : le \n permet de passer à la ligne

Vous pouvez vérifier que le prompt système intégre bien le règlement intérieur :

print(prompt_system_2[:500]) #on affiche unquement les 500 premiers caractères
[Out]
    Tu dois répondre aux questions portant sur le règlement intérieur de lycée Rouvière de Toulon.Tu ne dois aborder aucun autre sujet. Si tu ne trouves pas la réponse à la question posée, tu ne dois pas inventer une réponse,tu dois simplement dire 'Désolé, je n'ai pas la réponse à cette question'. Pour t'aider à répondre aux questions, tu peux consulter le règlement intérieur du lycée Rouvière : 
      - 1 - 

    SOMMAIRE DU REGLEMENT INTERIEUR 

    I / CONNAITRE SES DEVOIRS 
    1- Le devoir de respecter les 
Nous pouvons maintenant reposer notre question :

msg_user_2 = [{'role' : 'user', 'content' : 'Quel est le rôle de l\'association Sébastien Carpentier au lycée Rouvière ?'}]
msg_2 = msg_prompt_sys_2 + msg_user_2
response_2 = llm.chat.completions.create(model = 'gemini-2.0-flash', messages = msg_2)
answer_2 = response_2.choices[0].message.content
display(Markdown(answer_2))
[Out]
L’Association Sébastien Carpentier aide, en particulier, les étudiants en difficulté financière.
Comme vous pouvez le constater, le modèle est maintenant capable de répondre.

Exercice : - vous pouvez modifier la question - vous pouvez intégrer votre propre pdf (n'oubliez pas de modifier le prompt système)

ATTENTION

Ce système d'intégration d'un document dans le prompt fonctionne car le pdf n'est pas trop long. En effet, un modèle peut accepter en entrée un certain nombre de tokens (on appelle cette entrée la fenêtre de contexte). La taille de la fenêtre de contexte est donc limitée, si vous dépassez cette limite, l'API du modèle vous renverra une erreur.

Les modèles ont des fenêtres de contexte de plus en plus grande. Celle du modèle que nous utilisons ici est d'environ un million de tokens, ce qui représente plusieurs romans !

Après, il ne faut pas perdre de vue que les tokens peuvent être payants, si vous vous amusez à passer des livres entiers dans le prompt, le coût pourrait devenir important. Et même si vous utilisez une API "gratuite" (comme nous), il ne faut jamais perdre de vue que ces requêtes ont un coût environnemental important, donc attention de ne pas faire n'importe quoi !

Il existe un moyen d'utiliser des documents de taille importante sans pour autant passer l'entièreté du document dans le prompt : c'est la méthode RAG que nous étudierons plus tard.

Ce chapitre est terminé. Dans le prochain chapitre nous mettrons en place une interface graphique afin de rendre l'échange avec le modèle plus convivial.

Code complet :

from dotenv import load_dotenv
from openai import OpenAI
from IPython.display import Markdown, display
from pypdf import PdfReader
import os
load_dotenv()
API_KEY = os.getenv('GOOGLE_API_KEY')

llm = OpenAI(api_key=API_KEY, base_url="https://generativelanguage.googleapis.com/v1beta/openai/")

reader = PdfReader("./reglement_interieur.pdf")
reglement = ""
for page in reader.pages:
    text = page.extract_text()
    if text:
        reglement += text

prompt_system_2 = f"Tu dois répondre aux questions portant sur le règlement intérieur de lycée Rouvière de Toulon.\
Tu ne dois aborder aucun autre sujet. Si tu ne trouves pas la réponse à la question posée, tu ne dois pas inventer une réponse,\
tu dois simplement dire 'Désolé, je n'ai pas la réponse à cette question'. \
Pour t'aider à répondre aux questions, tu peux consulter le règlement intérieur du lycée Rouvière : \n {reglement}\n"
msg_prompt_sys_2 = [{'role' : 'system', 'content' : prompt_system_2}]

msg_user_2 = [{'role' : 'user', 'content' : 'Quel est le rôle de l\'association Sébastien Carpentier au lycée Rouvière ?'}]
msg_2 = msg_prompt_sys_2 + msg_user_2
response_2 = llm.chat.completions.create(model = 'gemini-2.0-flash', messages = msg_2)
answer_2 = response_2.choices[0].message.content
display(Markdown(answer_2))