Créer avec l’IA

Comment créer un robot conversationnel qui répond à partir de vos propres documents?

· Par Robert Scales · 4 min de lecture

Réponse courte

Vous découpez vos documents en courts passages, vous transformez chaque passage en plongement et, pour chaque question, vous récupérez les quelques passages les plus proches par le sens; vous les collez ensuite dans le prompt en demandant au modèle de répondre uniquement à partir d’eux. Cette méthode s’appelle la génération augmentée par récupération, et elle permet à un modèle comme gpt-3.5-turbo de répondre sur des textes sur lesquels il n’a jamais été entraîné.

Un modèle de langage ne sait que ce qui se trouvait dans ses données d’entraînement. Les textes d’entraînement de gpt-3.5-turbo et de GPT-4 s’arrêtent pour l’essentiel en septembre 2021. Le modèle n’a jamais vu votre guide de l’employé, vos manuels de produits ni les notes de réunion du mois dernier. Vous pourriez essayer de les lui apprendre par ajustement fin, mais le livre de recettes (cookbook) d’OpenAI déconseille d’utiliser l’ajustement fin pour ajouter des connaissances : il sert mieux à enseigner un style ou une tâche qu’à faire retenir des faits de façon fiable.

L’approche qui fonctionne est plus simple. Au moment de la question, trouvez les passages pertinents de vos documents et placez-les devant le modèle, comme si vous laissiez un élève passer un examen à livre ouvert. Un article de 2020 de Patrick Lewis et de ses collègues a donné un nom à cette idée : la génération augmentée par récupération (retrieval-augmented generation, ou RAG). « Récupération » veut dire aller chercher l’information; « génération » veut dire rédiger la réponse.

Les quatre étapes

1. Découper. Divisez chaque document en courtes sections qui ont du sens à elles seules, comme un titre et ses paragraphes, quelques centaines de mots tout au plus. Le modèle ne peut lire qu’une quantité limitée de texte à la fois : environ 4 096 jetons (à peu près cinq pages) pour gpt-3.5-turbo et 8 192 pour GPT-4. Un jeton est un mot ou un morceau de mot.

2. Vectoriser. Envoyez chaque passage au point d’accès des plongements d’OpenAI, par exemple au modèle text-embedding-ada-002. Un plongement (embedding) est une longue liste de nombres qui capte le sens : deux passages sur la même idée obtiennent des nombres semblables même s’ils emploient des mots différents. Conservez le texte de chaque passage, son plongement et sa provenance (nom de fichier et page). Pour quelques milliers de passages, un tableau semblable à une feuille de calcul suffit; pour des millions, utilisez une base de données vectorielle, un système de stockage conçu pour ce type de recherche.

3. Récupérer. Quand une question arrive, transformez-la de la même façon et comparez-la à chaque passage conservé. La comparaison donne un score appelé similarité cosinus : plus il est proche de 1, plus le sens est proche. Gardez les trois à cinq meilleurs passages.

4. Répondre. Construisez un prompt qui contient les passages récupérés, leurs sources et la question, et envoyez-le au modèle de clavardage avec des consignes strictes.

Les étapes 1 et 2 se font une seule fois par document. Les étapes 3 et 4 se font à chaque question.

Un exemple concret en Python

Voici une version minimale qui utilise la bibliothèque Python openai et un petit guide de l’employé déjà découpé en passages. C’est une esquisse pour montrer le déroulement, pas du code prêt pour la production.

import openai, numpy as np

chunks = [
    {"text": "Les employés ont droit à 15 jours de vacances par année...", "source": "handbook.pdf, p. 4"},
    {"text": "Les notes de frais doivent être remises dans les 30 jours...", "source": "handbook.pdf, p. 9"},
    # ... le reste de vos passages
]

def embed(text):
    r = openai.Embedding.create(model="text-embedding-ada-002", input=text)
    return np.array(r["data"][0]["embedding"])

for c in chunks:                      # étape 2, exécutée une seule fois
    c["vec"] = embed(c["text"])

def answer(question, k=3):
    q = embed(question)                # étape 3
    best = sorted(chunks, key=lambda c: -np.dot(q, c["vec"]))[:k]
    context = "\n\n".join(f"[{c['source']}]\n{c['text']}" for c in best)
    messages = [
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": f"Contexte :\n{context}\n\nQuestion : {question}"},
    ]
    r = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=messages, temperature=0)
    return r["choices"][0]["message"]["content"]

Le texte et les chiffres du guide sont inventés pour l’exemple. Le produit scalaire de deux plongements est le score de similarité de l’étape 3, et une temperature de 0 rend la formulation aussi prévisible que possible.

C’est dans le prompt système que vous fixez les règles :

Prompt
Tu réponds aux questions des employés en utilisant UNIQUEMENT les passages de contexte fournis dans le message de l’utilisateur.
Règles :
1. Si la réponse se trouve dans le contexte, réponds en quatre phrases au plus et cite la source entre crochets, par exemple [handbook.pdf, p. 4].
2. Si le contexte ne contient pas la réponse, réponds exactement : « Je ne sais pas d’après les documents dont je dispose. » N’utilise pas de connaissances extérieures et ne devine pas.
3. Si des passages se contredisent, dis-le et cite-les tous les deux.

À essayer : prenez un document que vous connaissez bien, comme les règlements d’un club ou le manuel d’un électroménager, découpez-le en dix à vingt passages selon les titres, et exécutez le code ci-dessus. Posez cinq questions auxquelles il répond et deux auxquelles il ne répond pas. Vérifiez que chaque réponse porte une citation exacte et que les deux questions hors sujet reçoivent la réponse « Je ne sais pas ».

Quand les réponses tournent mal

Le livre de recettes propose une bonne façon de déboguer. Quand une réponse est fausse, affichez d’abord les passages que le modèle a reçus. Si le bon passage manque, c’est l’étape de récupération qui a échoué : essayez des passages plus petits ou mieux étiquetés, ou récupérez-en davantage. Si le bon passage était là et que le modèle s’est quand même trompé, c’est l’étape de réponse qui a échoué : resserrez le prompt ou utilisez un modèle plus puissant comme GPT-4.

Attendez-vous à ce que ce montage brille pour les recherches directes (« Combien de jours de vacances ai-je? ») et peine avec les questions qui exigent de combiner plusieurs passages éparpillés (« Compare nos politiques de déplacement et de télétravail »).

Comment lui faire dire « Je ne sais pas »?

Donnez-lui une permission explicite, et une formule exacte. Les modèles sont entraînés à être serviables; sans consignes, ils ont donc tendance à combler les trous avec un texte plausible tiré de leurs connaissances générales. La règle 2 du prompt ci-dessus indique au modèle que « Je ne sais pas » est une bonne réponse, interdit les connaissances extérieures et fixe la formulation. L’exemple du livre de recettes d’OpenAI fait de même, avec la réponse de repli « I could not find an answer. »

Une formule fixe aide aussi votre code. Vous pouvez la détecter et réagir autrement, par exemple en proposant un lien vers une personne-ressource ou en consignant la question pour savoir quels documents manquent.

Testez-le ensuite délibérément. Gardez une courte liste de questions auxquelles vos documents ne répondent pas et lancez-les après chaque modification de votre prompt ou de votre découpage. Vérifiez aussi la récupération elle-même : si les meilleurs passages n’ont qu’un lien lointain avec la question, le modèle risque de les étirer pour en faire une réponse. Afficher la source citée avec chaque réponse permet aux utilisateurs de vérifier par eux-mêmes, et c’est la meilleure protection dont vous disposez.

Sources

  1. Question answering using embeddings-based search — OpenAI Cookbook on GitHub (commit of 2023-05-09), 9 mai 2023
  2. Introducing Text and Code Embeddings in the OpenAI API — OpenAI, 25 janvier 2022
  3. Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks — arXiv (Patrick Lewis and 11 co-authors), 22 mai 2020

Recevez gratuitement le Guide de l’intelligence artificielle

Abonnez-vous à l’infolettre hebdomadaire et recevez le guide gratuit : ce qui a changé en IA cette semaine, une leçon, un prompt à essayer. Désabonnement en un clic.

Ce que nous faisons de votre adresse

Retour en haut

Affichage

Vos choix sont enregistrés dans ce navigateur seulement. Aucune donnée n’est transmise.

Taille du texte
100 %
Couleurs
Lecture
Autres réglages
Déclaration d’accessibilité