DSPy : arrête de bricoler tes prompts, programme tes LLM

De quoi avez-vous besoin

Version de Python

3.x

Packages

  • {"nom":"dspy","version":"3.3.1"}

Difficulté

Intermédiaire

Un prompt, c'est du verre. Tu passes une heure à peaufiner une phrase pour GPT-4o, et le jour où tu changes de modèle ou de version, tout casse. Tu recommences. Ce petit manège, DSPy — un framework signé Stanford — a décidé d'y mettre fin.

L'idée tient en une phrase : arrête d'écrire des prompts, écris des programmes. Tu décris ce que tu veux (les entrées, les sorties), tu fournis quelques exemples et une façon de noter la qualité, et DSPy fabrique puis améliore les instructions à ta place. Tu changes de modèle ? Tu recompiles au lieu de réécrire.

1. Installe DSPy

Un seul paquet, rien d'autre. DSPy est en pur Python et se glisse dans n'importe quel projet.

bash
pip install dspy

# ou, plus rapide et sans venv :
uv add dspy

2. Branche un modèle

DSPy parle à presque tous les LLM via une interface unique : OpenAI, Anthropic, Mistral, ou un modèle local servi par Ollama. Tu ne changes qu'une ligne.

python
import dspy

lm = dspy.LM("openai/gpt-4o-mini", api_key="sk-...")
dspy.configure(lm=lm)

Pour du 100 % local, remplace la première ligne par dspy.LM("ollama_chat/llama3.1") après avoir lancé Ollama. Le reste du code ne bouge pas.

3. Décris la tâche avec une signature

Une signature, c'est la fiche de poste de ton modèle : quelles entrées, quelles sorties, et une consigne en une phrase. Pas de prompt géant à copier-coller.

python
class Verdict(dspy.Signature):
    """Classe un commentaire en positif, négatif ou neutre."""
    commentaire: str = dspy.InputField()
    sentiment: str = dspy.OutputField(desc="positif, négatif ou neutre")

4. Appelle-le comme une fonction

ChainOfThought demande au modèle de raisonner avant de répondre. Résultat : une sortie propre et un raisonnement visible, que tu peux déboguer.

python
juger = dspy.ChainOfThought(Verdict)

resultat = juger(commentaire="Écran mort au bout de trois jours.")
print(resultat.sentiment)   # négatif
print(resultat.reasoning)   # le raisonnement, lisible et corrigeable

5. Laisse DSPy optimiser tes prompts

Le vrai super-pouvoir arrive ici. Tu donnes une poignée d'exemples annotés et une métrique de réussite, puis BootstrapFewShot fabrique et teste des dizaines de variantes de ton prompt jusqu'à trouver la meilleure.

python
exemples = [
    dspy.Example(commentaire="Une tuerie, je le rachèterais.", sentiment="positif").with_inputs("commentaire"),
    dspy.Example(commentaire="Livré en retard, déjà en panne.", sentiment="négatif").with_inputs("commentaire"),
    dspy.Example(commentaire="Correct, sans plus.", sentiment="neutre").with_inputs("commentaire"),
]

def est_juste(exemple, pred, trace=None):
    return pred.sentiment.strip().lower() == exemple.sentiment
python
from dspy.teleprompt import BootstrapFewShot

optimiseur = BootstrapFewShot(metric=est_juste)
juger_ameliore = optimiseur.compile(juger, trainset=exemples)

print(juger_ameliore(commentaire="Le service client répond en deux minutes.").sentiment)

Pourquoi ça change tout

Quand ton prompt vit dans une chaîne de caractères, il est figé. Quand il vit dans une signature, il devient une variable : DSPy peut le mesurer, le comparer, le réoptimiser. C'est la différence entre bricoler et faire de l'ingénierie.

Tu n'as plus besoin d'être un poète du prompt. Décris la tâche, donne des exemples, note les résultats, et laisse la machine faire ce qu'elle sait faire : essayer, comparer, recommencer. Ton code, lui, reste propre et portable d'un modèle à l'autre. La prochaine fois qu'un prompt te résiste, ne le réécris pas. Programme-le.