Accéder au contenu principal

Introduction au prompt engineering avec LangChain

Découvrez la puissance du prompt engineering dans LangChain, une technique essentielle pour obtenir des réponses précises et pertinentes des modèles d’IA.
· 11 min lire

Explorez l'IA

LangChain est un framework open source conçu pour créer facilement des applications à l’aide de modèles de langage comme GPT, LLaMA, Mistral, etc.

L’une des fonctionnalités les plus puissantes de LangChain est sa prise en charge avancée du prompt engineering. Le prompt engineering désigne la conception et l’optimisation de requêtes (prompts) afin d’obtenir des réponses aussi précises et pertinentes que possible d’un modèle de langage.

Dans cet article, nous verrons les bases des prompts, comment LangChain les utilise, les modèles de prompts, la mémoire, les agents et les chaînes. Pour chacun de ces concepts clés, nous examinerons plusieurs exemples de code en Python afin qu’à la fin de ce tutoriel vous soyez à l’aise pour créer vos propres applications avec le framework LangChain en Python.

Curieux de voir comment LangChain et GPT peuvent servir à créer un agent IA simple ? Découvrez notre Code-Along Prompt Engineering avec GPT & LangChain :

Qu’est-ce que le prompt engineering ?

Image par l’auteur

Nous avons publié un guide complet sur le prompt engineering. Pour rappel, il s’agit de formuler des entrées textuelles capables de communiquer efficacement avec des modèles d’IA générative. Ces prompts, rédigés en langage naturel, précisent la tâche que nous souhaitons confier à l’IA.

Ils peuvent prendre des formes variées, allant de questions simples (par exemple demander l’explication d’un théorème) à des requêtes créatives, comme écrire un poème sur un thème précis.

En prompt engineering, l’essentiel n’est pas seulement ce que vous demandez, mais comment vous le demandez. Cela peut inclure le choix des bons mots, la définition d’un ton ou d’un style, l’ajout de contexte, ou même l’attribution d’un rôle à l’IA, comme lui demander de répondre en tant que locuteur natif d’une certaine langue.

Dans certains cas, les prompts peuvent aussi inclure des exemples pour guider le modèle. Cette technique, appelée few-shot learning, est particulièrement efficace pour les tâches complexes.

Avec les modèles qui génèrent des images ou de l’audio, les prompts décrivent généralement en détail le rendu souhaité : sujet, style, composition, ambiance, etc. L’art du prompt engineering consiste à ajuster ces éléments pour orienter l’IA vers le résultat recherché.

Les bases des prompts

Image par l’auteur

Les prompts sont les entrées fournies aux grands modèles de langage (LLM) pour obtenir la réponse souhaitée. Des prompts bien conçus sont essentiels pour tirer des sorties utiles des LLM. Le but du prompt engineering est de construire soigneusement des prompts qui produisent des réponses exactes, pertinentes et utiles.

Un bon prompt contient généralement quatre éléments :

  1. Instructions : indiquer au modèle quoi faire, comment utiliser les informations fournies, comment traiter la requête et comment structurer la sortie.
  2. Exemple d’entrée : fournir des entrées d’exemple pour montrer au modèle ce qui est attendu.
  3. Exemple de sortie : donner les sorties correspondantes.
  4. Requête : l’entrée réelle que vous voulez que le modèle traite.

À l’exception de la requête, tout le reste est optionnel mais peut fortement impacter la qualité de la réponse, en particulier les instructions qui guident le LLM sur la tâche et le format attendu.

Les exemples montrent le format de sortie souhaité pour un exemple d’entrée donné.

La requête est la question ou la demande adressée au LLM.

Construire des prompts efficaces consiste à combiner avec discernement ces éléments selon le problème à résoudre.

Les prompts dans LangChain

LangChain propose différentes classes et fonctions pour aider à construire et manipuler des prompts, ce qui facilite la gestion de tâches complexes avec des modèles de langage.

LangChain offre un support de premier plan pour le prompt engineering grâce à l’objet PromptTemplate.

Les modèles de prompts servent de guides structurés pour formuler des requêtes destinées aux modèles de langage.

Ces modèles incluent généralement des directives, une sélection d’exemples d’entrée (few-shot) et des questions et contextes adaptés à des tâches spécifiques.

L’objectif de LangChain est de concevoir des modèles compatibles avec différents modèles de langage, afin de faciliter leur réutilisation d’un modèle à l’autre.

En bref, vous pouvez utiliser la classe PromptTemplate pour créer un modèle de prompt textuel.

from langchain.prompts import PromptTemplate


prompt_template = PromptTemplate.from_template(
    "Tell me a {adjective} joke about {content}."
)
prompt_template.format(adjective="sad", content="data scientists")

Sortie :

>>> 'Tell me a sad joke about data scientists.'

Il n’est pas nécessaire d’avoir une variable. Vous pouvez créer un prompt avec cette classe même sans aucune variable.

from langchain.prompts import PromptTemplate
prompt_template = PromptTemplate.from_template("Tell me a joke")
prompt_template.format()

Sortie :

>>> 'Tell me a joke'

Et si vous développez une application de chat où il faut sauvegarder puis renvoyer l’historique des messages au LLM à chaque nouveau message utilisateur ? Le faire manuellement prend du temps.

Pour les modèles de chat pris en charge, vous pouvez utiliser ChatPromptTemplate :

from langchain.prompts import ChatPromptTemplate


chat_template = ChatPromptTemplate.from_messages(
    [
        ("system", "You are a helpful AI bot. Your name is {name}."),
        ("human", "Hello, how are you doing?"),
        ("ai", "I'm doing well, thanks!"),
        ("human", "{user_input}"),
    ]
)


messages = chat_template.format_messages(name="Bob", user_input="What is your name?")


print(messages)

Sortie :

>>> [SystemMessage(content='You are a helpful AI bot. Your name is Bob.'),

>>> HumanMessage(content='Hello, how are you doing?'),

>>> AIMessage(content="I'm doing well, thanks!"),

>>> HumanMessage(content='What is your name?')]

Vous vous demandez peut-être pourquoi utiliser des PromptTemplates plutôt que de passer directement une chaîne de caractères au LLM ? Voici de bonnes raisons d’utiliser les PromptTemplate de LangChain :

  • Les modèles de prompts sont réutilisables : vous créez un prompt une fois et vous l’utilisez dans de multiples contextes, par exemple pour résumer différents articles sans réécrire le prompt à chaque fois.
  • Ils séparent la mise en forme des prompts de l’appel au modèle, ce qui rend le code plus modulaire et permet de mettre à jour indépendamment le modèle ou le modèle de prompt.
  • Les modèles améliorent la lisibilité du code en encapsulant une logique complexe dans un format plus simple avec des variables nommées claires.
  • La maintenance est facilitée : toute modification de la logique du prompt se fait en un point central au lieu de devoir modifier chaque prompt individuellement.

La mémoire dans LangChain

Dans les applications de type chat avec modèles de langage, il est important que le système se souvienne des échanges passés.

Comme dans une conversation normale, le système doit pouvoir revenir sur ce qui a été dit auparavant.

Au plus simple, cela signifie garder quelques messages précédents. Un système plus avancé retiendra davantage de détails, comme des faits sur différents sujets et leurs liens.

Cette capacité à se souvenir des échanges s’appelle la « mémoire ». LangChain facilite l’ajout de mémoire à ces systèmes de chat.

Une mémoire dans LangChain remplit deux fonctions principales :

  1. Avant d’envoyer la requête au LLM, le système lit sa mémoire pour enrichir le prompt initial reçu de l’utilisateur.
  2. Une fois la réponse renvoyée par le LLM, elle est écrite en mémoire pour les interactions futures, avant d’être renvoyée à l’utilisateur.

Mémoire dans LangChain (source de l’image)

Pour utiliser la fonctionnalité Memory dans LangChain, vous pouvez recourir à la classe ConversationBufferMemory.

from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(return_messages=True)
memory.chat_memory.add_user_message("hi!")
memory.chat_memory.add_ai_message("what's up?")
memory.chat_memory.add_user_message("how are you doing?")
memory.chat_memory.add_ai_message("I am fine, thank you and you?")


# to check the variables history
memory.load_memory_variables({})

Sortie :

>>> {'history': [HumanMessage(content='hi!'),

>>> AIMessage(content="what's up?"),

>>> HumanMessage(content='how are you doing?'),

>>> AIMessage(content='I am fine, thank you and you?')]}

La méthode renvoie un dictionnaire où la clé par défaut est history. Cette clé pointe vers une liste de messages, émis soit par un humain (HumanMessage), soit par le LLM (AIMessage).

Les chaînes (Chains) dans LangChain

Pour des tâches simples, un seul LLM (Large Language Model) suffit. Pour des tâches plus complexes, il faut généralement enchaîner plusieurs étapes et/ou modèles.

La méthode historique pour utiliser des Chains dans LangChain passe par l’interface Chain.

La méthode plus récente et recommandée est le LangChain Expression Language (LCEL). Bien que LCEL soit à privilégier pour les nouveaux projets, l’approche Chain reste utile et prise en charge.

from langchain.llms import OpenAI
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser


model = ChatOpenAI(openai_api_key = “...”)


prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "You're a expert data scientist and machine learning engineer who offer its expertise and responds to the point and accurately.",
        ),
        ("human", "{question}"),
    ]
)
runnable = prompt | model | StrOutputParser()


for chunk in runnable.stream({"question": "How is machine learning different than deep learning?"}):
    print(chunk, end="", flush=True)

Sortie :

>>> Machine learning and deep learning are subfields of artificial intelligence (AI) that involve training models to make predictions or decisions based on data. While there is an overlap between the two, they ……..

La façon dont runnable est créé n’est pas standard en Python : l’opérateur | est un « pipe ». Prompt | model | StrOutputParser() signifie que le Prompt est transmis au model, puis sa sortie est transmise à StrOutputParser(). Chaque étape de la chaîne transforme les données.

Vous souhaitez découvrir d’autres cas d’usage et applications à créer avec LangChain ? Consultez notre tutoriel cas d’usage pour l’ingénierie et les applications data.

Les agents LangChain

Le concept fondamental des agents consiste à utiliser un modèle de langage pour sélectionner une série d’actions.

Contrairement aux chaînes, où la séquence d’actions est prédéfinie dans le code, les agents s’appuient sur un modèle de langage comme moteur de décision pour identifier les actions appropriées et leur ordre.

Trois notions clés structurent les Agents dans LangChain :

  1. Outils : description des outils disponibles pour le LLM
  2. Entrée utilisateur : l’objectif général de la tâche
  3. Étapes intermédiaires : toute paire (action, sortie d’outil) déjà exécutée pour atteindre l’objectif utilisateur

Les outils représentent des fonctionnalités qu’un agent peut activer. Deux aspects sont cruciaux dans leur conception :

  • Garantir que l’agent dispose des bons outils.
  • Définir les outils de manière à maximiser leur utilité pour l’agent.

Pour nombre d’activités courantes, un agent a besoin d’un ensemble d’outils interconnectés. Pour cela, LangChain introduit la notion de toolkits. LangChain offre un large éventail de toolkits pour démarrer.

Pour en savoir plus sur les Agents, consultez ce guide officiel LangChain.

Crédits : certains exemples de cet article sont issus de la documentation officielle LangChain.

Conclusion

En proposant une approche structurée de la conception des prompts, LangChain simplifie l’interaction avec différents modèles de langage tout en maximisant l’efficacité et la pertinence des résultats. Des fonctionnalités comme PromptTemplate et Memory illustrent une intégration réfléchie de flexibilité et de précision en prompt engineering, adaptée à un large éventail de tâches, des requêtes simples aux conversations complexes.

Les fonctionnalités avancées des Chains et des Agents étendent encore le potentiel des applications construites avec LangChain en quelques lignes de code, quel que soit le LLM sous-jacent — et les options sont nombreuses.

Qu’il s’agisse de tâches simples ou d’applications plus élaborées, l’approche de LangChain pour le prompt engineering est simple, claire et facile à adopter.

Envie d’aller plus loin ? Découvrez la partie 1 de Comment construire des applications LLM avec LangChain sur DataCamp.

Moez Ali

Auteur

Moez Ali

Scientifique de données, fondateur et créateur de PyCaret

Sujets

Contenus associés

blog

Comprendre les TPU et les GPU dans l'IA : Un guide complet