Prompt Engineering et APIs
Maîtrisez les techniques avancées de prompting (CoT, few-shot, JSON mode) et construisez des applications avec les APIs LLM et le function calling.
Au-delà du Prompt Basique
Dans le cours précédent, vous avez vu les bases du prompting. Ici, nous passons aux techniques qui font la différence entre un amateur et un professionnel.
Chain-of-Thought (CoT)
Le problème
Les LLMs se trompent souvent sur les problèmes qui nécessitent un raisonnement en plusieurs étapes.
Prompt : "Si j''ai 3 paniers de 7 pommes et que j''en mange 4, combien m''en reste-t-il ?"
GPT-4 (sans CoT) : "17" ✓ (parfois correct, parfois non)
La solution : forcer le raisonnement étape par étape
Prompt : "Si j''ai 3 paniers de 7 pommes et que j''en mange 4,
combien m''en reste-t-il ?
Réfléchis étape par étape."
Réponse :
1. 3 paniers × 7 pommes = 21 pommes au total
2. J''en mange 4
3. 21 - 4 = 17 pommes restantes
Pourquoi ça marche ? En forçant le modèle à "montrer son travail", chaque étape intermédiaire enrichit le contexte pour l''étape suivante. Le modèle a plus d''informations pour chaque calcul.
Variantes de CoT
| Technique | Prompt | Quand l''utiliser |
|---|---|---|
| Zero-shot CoT | "Réfléchis étape par étape" | Questions simples |
| Few-shot CoT | Donner des exemples avec le raisonnement | Problèmes complexes |
| Self-consistency | Générer N réponses et voter | Maximiser la précision |
Few-shot CoT en pratique
messages = [
{"role": "system", "content": "Tu es un assistant logique. Raisonne toujours étape par étape."},
{"role": "user", "content": "Marie a 2 fois plus de billes que Jean. Jean a 3 billes de plus que Paul. Paul a 5 billes. Combien Marie a-t-elle de billes ?"},
{"role": "assistant", "content": """Raisonnons étape par étape :
1. Paul a 5 billes
2. Jean a 3 billes de plus que Paul → 5 + 3 = 8 billes
3. Marie a 2 fois plus que Jean → 8 × 2 = 16 billes
Marie a 16 billes."""},
{"role": "user", "content": "Un train part à 14h de Paris à 300 km/h. Un autre part à 15h de Lyon (450 km) à 250 km/h vers Paris. À quelle heure se croisent-ils ?"}
]
Structured Outputs : Forcer le Format
Le problème
Quand on construit une application, on a besoin de réponses structurées (JSON, listes, tableaux) et pas de texte libre.
JSON Mode
La plupart des APIs proposent un mode JSON qui force le modèle à répondre en JSON valide.
from openai import OpenAI
client = OpenAI(base_url="https://openrouter.ai/api/v1", api_key="sk-or-...")
response = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[
{"role": "system", "content": "Tu extrais des informations de CV en JSON."},
{"role": "user", "content": """Extrais les infos de ce CV :
Jean Dupont, 5 ans d''expérience en Python et React.
Diplômé de l''INSA Lyon en 2019. Parle français et anglais.
Retourne un JSON avec : name, experience_years, skills (array), school, languages (array)"""}
],
response_format={"type": "json_object"},
temperature=0
)
import json
data = json.loads(response.choices[0].message.content)
print(json.dumps(data, indent=2, ensure_ascii=False))
Résultat attendu :
{
"name": "Jean Dupont",
"experience_years": 5,
"skills": ["Python", "React"],
"school": "INSA Lyon",
"languages": ["français", "anglais"]
}
Schéma strict avec Pydantic
Pour des applications production, validez les réponses avec Pydantic :
from pydantic import BaseModel
from typing import List
class CVInfo(BaseModel):
name: str
experience_years: int
skills: List[str]
school: str
languages: List[str]
# Valider la réponse du LLM
cv = CVInfo(**data)
print(f"Candidat : {cv.name}, {cv.experience_years} ans d''exp.")
print(f"Compétences : {', '.join(cv.skills)}")
Même en JSON mode, le modèle peut inventer des champs ou omettre des valeurs. Validez toujours avec un schéma.
Function Calling (Tool Use)
Le concept
Le function calling permet au LLM d''appeler des fonctions de votre code. Au lieu de répondre directement, le modèle retourne un appel de fonction structuré que votre application exécute.
Implémentation
import json
# Définir les fonctions disponibles
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Obtenir la météo actuelle pour une ville",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "Nom de la ville"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Unité de température"
}
},
"required": ["city"]
}
}
},
{
"type": "function",
"function": {
"name": "search_web",
"description": "Chercher des informations sur le web",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "La requête de recherche"
}
},
"required": ["query"]
}
}
}
]
# Envoyer au LLM
response = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[
{"role": "user", "content": "Quel temps fait-il à Toulouse ?"}
],
tools=tools,
tool_choice="auto" # Le modèle décide s''il appelle une fonction
)
# Le modèle retourne un appel de fonction
message = response.choices[0].message
if message.tool_calls:
call = message.tool_calls[0]
print(f"Fonction : {call.function.name}")
print(f"Arguments : {call.function.arguments}")
# → Fonction : get_weather
# → Arguments : {"city": "Toulouse", "unit": "celsius"}
Le flux complet
def get_weather(city, unit="celsius"):
"""Simule un appel API météo."""
# En production, appelez une vraie API
return {"temp": 18, "condition": "ensoleillé", "city": city}
# 1. Premier appel : le LLM décide d''appeler get_weather
response = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "Météo à Toulouse ?"}],
tools=tools,
)
# 2. Exécuter la fonction
call = response.choices[0].message.tool_calls[0]
args = json.loads(call.function.arguments)
result = get_weather(**args)
# 3. Renvoyer le résultat au LLM pour qu''il formule la réponse
messages = [
{"role": "user", "content": "Météo à Toulouse ?"},
response.choices[0].message, # Le message avec l''appel de fonction
{
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result)
}
]
final = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=messages,
)
print(final.choices[0].message.content)
# → "Il fait 18°C et ensoleillé à Toulouse."
Le function calling est la base des agents IA. Un agent est un LLM qui peut appeler des outils (recherche web, exécution de code, accès base de données) en boucle jusqu''à résoudre un problème.
Techniques Avancées
System Prompt Engineering
Un bon system prompt est précis, structuré et contient des contraintes explicites.
system_prompt = """Tu es un assistant expert en droit du travail français.
RÈGLES :
- Réponds UNIQUEMENT aux questions de droit du travail français
- Cite les articles de loi pertinents (Code du travail)
- Si tu n''es pas sûr, dis-le explicitement
- Format : commence par un résumé en 1 phrase, puis développe
- Langue : français, registre professionnel
INTERDICTIONS :
- Ne donne jamais de conseil juridique définitif
- Ne réponds pas aux questions hors sujet
- Ajoute toujours : "Consultez un avocat pour votre situation spécifique."
"""
Multi-turn Conversations
Les LLMs sont stateless : ils n''ont pas de mémoire. C''est à vous de renvoyer l''historique complet.
conversation = [
{"role": "system", "content": "Tu es un tuteur Python patient et pédagogue."},
]
def chat(user_message):
conversation.append({"role": "user", "content": user_message})
response = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=conversation,
temperature=0.5
)
assistant_message = response.choices[0].message.content
conversation.append({"role": "assistant", "content": assistant_message})
return assistant_message
# Utilisation
print(chat("C''est quoi une liste en Python ?"))
print(chat("Comment en ajouter un élément ?")) # Se souvient du contexte
print(chat("Et pour en supprimer ?")) # Historique complet envoyé
Attention au coût : Chaque message de l''historique est recompté à chaque appel. Une conversation de 50 messages coûte beaucoup plus qu''une seule question. Pensez à résumer ou tronquer l''historique quand il devient trop long.
Prompt Chaining
Décomposer une tâche complexe en plusieurs appels LLM successifs.
# Étape 1 : Extraire les données
extract_response = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": f"Extrais les noms et dates de ce texte en JSON :\n{texte}"}],
response_format={"type": "json_object"},
temperature=0
)
data = json.loads(extract_response.choices[0].message.content)
# Étape 2 : Analyser avec les données extraites
analysis_response = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": f"Analyse ces événements et identifie les tendances :\n{json.dumps(data)}"}],
temperature=0.3
)
print(analysis_response.choices[0].message.content)
Exercice : Construire un Assistant Spécialisé
Créez un assistant qui extrait des informations de fiches produit et les structure en JSON.
import json
from openai import OpenAI
client = OpenAI(base_url="https://openrouter.ai/api/v1", api_key="sk-or-...")
system = """Tu es un expert en extraction de données produit.
Pour chaque fiche produit, retourne un JSON avec :
- name (string)
- price (number, en euros)
- category (string)
- features (array de strings)
- rating (number, sur 5)
- in_stock (boolean)
Si une information est absente, utilise null."""
fiches = [
"iPhone 15 Pro - 1229€ - Smartphone Apple. Puce A17 Pro, 256Go, titane. Note 4.7/5. En stock.",
"Casque Sony WH-1000XM5 - Réduction de bruit active, 30h autonomie, Bluetooth 5.2. 349€. Rupture de stock. 4.8/5.",
"Samsung Galaxy Tab S9 - Tablette 11 pouces, 128Go, S Pen inclus. Prix : 799€."
]
for fiche in fiches:
response = client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[
{"role": "system", "content": system},
{"role": "user", "content": fiche}
],
response_format={"type": "json_object"},
temperature=0
)
data = json.loads(response.choices[0].message.content)
print(json.dumps(data, indent=2, ensure_ascii=False))
print("---")
Résultat : Un pipeline d''extraction automatique qui transforme du texte libre en données structurées exploitables par votre application.
Pour Aller Plus Loin
- Exercice bonus : ajoutez du function calling à l''assistant pour qu''il puisse rechercher un produit dans une base de données
- Explorez le Cookbook OpenAI pour des patterns avancés
- Prochain cours : fine-tuning et exécution de modèles en local avec Ollama
Specialiste IA — Master Intelligence Artificielle
Diplome d'un Master en Intelligence Artificielle, je travaille au quotidien sur des projets IA en entreprise. J'ai cree IwanttolearnAI pour rendre l'apprentissage de l'IA accessible a tous, gratuitement.
Continuer a apprendre
Gérer le Context Window et la Mémoire des LLMs
Comprenez les limites de mémoire des LLMs, le phénomène lost-in-the-middle, et maîtrisez les stratégies pour gérer efficacement de longs contextes en production.
Faire Tourner un LLM en Local avec Ollama
Installez et utilisez des LLMs directement sur votre machine avec Ollama : confidentialité totale, coût zéro, et intégration Python en quelques lignes.
Tokenisation : Comment l'IA Lit le Texte
Découvrez comment les LLMs décomposent le texte en tokens, pourquoi le français coûte plus cher que l'anglais, et comment maîtriser vos coûts d'API avec tiktoken.