Conversation state et gestion de session
Conversation state et gestion de session
La Responses API introduit une gestion de session native qui simplifie considérablement le maintien du contexte entre les échanges. Fini le besoin de renvoyer tout l’historique à chaque requête.
Le chaînage avec previous_response_id
La fonctionnalité la plus importante de la Responses API est le chaînage automatique des réponses :
from openai import OpenAI
client = OpenAI()
# Premier échange
r1 = client.responses.create(
model="gpt-5.3",
instructions="Vous êtes un professeur de mathématiques patient.",
input="Je voudrais apprendre les fractions."
)
print(f"R1 : {r1.output_text}")
# Deuxième échange — le contexte est conservé automatiquement
r2 = client.responses.create(
model="gpt-5.3",
input="Pouvez-vous me donner un exemple concret ?",
previous_response_id=r1.id
)
print(f"R2 : {r2.output_text}")
# Troisième échange — toute la conversation est accessible
r3 = client.responses.create(
model="gpt-5.3",
input="Et comment les additionner ?",
previous_response_id=r2.id
)
print(f"R3 : {r3.output_text}")
# Le modèle sait qu'on parle de fractions depuis le début
Comparaison avec l’ancien modèle
Avant (Chat Completions) — gestion manuelle
# ANCIEN — vous deviez tout gérer vous-même
historique = [
{"role": "system", "content": "Vous êtes un professeur de maths."},
{"role": "user", "content": "Je voudrais apprendre les fractions."},
{"role": "assistant", "content": "Bien sûr ! Les fractions..."},
{"role": "user", "content": "Un exemple concret ?"},
{"role": "assistant", "content": "Prenons une pizza..."},
{"role": "user", "content": "Comment les additionner ?"},
]
# Tout renvoyé à chaque appel = coûts croissants
Maintenant (Responses API) — gestion automatique
# NOUVEAU — un seul ID suffit
r = client.responses.create(
model="gpt-5.3",
input="Comment les additionner ?",
previous_response_id="resp_precedent_id"
)
# Le serveur gère l'historique pour vous
Gestion de sessions multiples
Pour gérer plusieurs conversations en parallèle (multi-utilisateurs) :
class SessionManager:
"""Gestionnaire de sessions de conversation."""
def __init__(self):
self.sessions: dict[str, str] = {} # user_id -> last_response_id
def envoyer_message(self, user_id: str, message: str,
instructions: str = "") -> str:
"""Envoie un message dans la session de l'utilisateur."""
kwargs = {
"model": "gpt-5.3",
"input": message,
}
# Ajouter les instructions si fournies
if instructions:
kwargs["instructions"] = instructions
# Chaîner avec la réponse précédente si elle existe
if user_id in self.sessions:
kwargs["previous_response_id"] = self.sessions[user_id]
response = client.responses.create(**kwargs)
# Sauvegarder l'ID pour le prochain tour
self.sessions[user_id] = response.id
return response.output_text
def nouvelle_session(self, user_id: str):
"""Démarre une nouvelle conversation pour l'utilisateur."""
if user_id in self.sessions:
del self.sessions[user_id]
# Utilisation
manager = SessionManager()
# Utilisateur Alice
print(manager.envoyer_message("alice", "Bonjour, parlez-moi de Python."))
print(manager.envoyer_message("alice", "Quels sont ses avantages ?"))
# Utilisateur Bob (conversation indépendante)
print(manager.envoyer_message("bob", "Bonjour, parlez-moi de Rust."))
# Alice continue sa conversation sur Python
print(manager.envoyer_message("alice", "Comment débuter ?"))
Gestion de l’historique avec input structuré
Vous pouvez aussi gérer l’historique manuellement quand vous avez besoin de plus de contrôle :
def conversation_manuelle():
"""Conversation avec gestion manuelle de l'historique."""
historique = []
while True:
user_input = input("Vous : ")
if user_input.lower() == "quit":
break
historique.append({"role": "user", "content": user_input})
response = client.responses.create(
model="gpt-5.3",
instructions="Vous êtes un assistant concis.",
input=historique
)
assistant_msg = response.output_text
historique.append({"role": "assistant", "content": assistant_msg})
print(f"Assistant : {assistant_msg}")
print(f" (Tokens cumulés : {response.usage.input_tokens})")
# conversation_manuelle()
Stratégies de persistance
Sauvegarde des sessions en base de données
import json
from datetime import datetime
class PersistentSessionManager:
"""Sessions persistantes avec sauvegarde."""
def __init__(self, db_path: str = "sessions.json"):
self.db_path = db_path
self.sessions = self._charger()
def _charger(self) -> dict:
try:
with open(self.db_path, "r") as f:
return json.load(f)
except FileNotFoundError:
return {}
def _sauvegarder(self):
with open(self.db_path, "w") as f:
json.dump(self.sessions, f, indent=2)
def envoyer(self, session_id: str, message: str) -> str:
kwargs = {"model": "gpt-5.3", "input": message}
if session_id in self.sessions:
kwargs["previous_response_id"] = self.sessions[session_id]["last_id"]
response = client.responses.create(**kwargs)
self.sessions[session_id] = {
"last_id": response.id,
"updated_at": datetime.now().isoformat(),
"total_tokens": response.usage.total_tokens
}
self._sauvegarder()
return response.output_text
Expiration des sessions
from datetime import datetime, timedelta
def nettoyer_sessions(sessions: dict, max_age_heures: int = 24) -> dict:
"""Supprime les sessions expirées."""
maintenant = datetime.now()
actives = {}
for sid, data in sessions.items():
updated = datetime.fromisoformat(data["updated_at"])
if maintenant - updated < timedelta(hours=max_age_heures):
actives[sid] = data
supprimees = len(sessions) - len(actives)
if supprimees > 0:
print(f"{supprimees} session(s) expirée(s) supprimée(s)")
return actives
Bonnes pratiques
- Utilisez
previous_response_idpour les conversations simples : c’est le plus efficace - Passez à l’input structuré quand vous avez besoin de modifier l’historique
- Implémentez un nettoyage des sessions inactives
- Surveillez les tokens cumulés pour éviter les surprises de facturation
- Stockez les
response.idde manière fiable (base de données, pas mémoire)
Points clés à retenir
previous_response_idchaîne les réponses automatiquement sans renvoyer l’historique- Chaque réponse a un
idunique utilisable pour le chaînage - Gérez des sessions multiples avec un dictionnaire
user_id -> response_id - L’input structuré (liste de messages) offre plus de contrôle sur l’historique
- Implémentez la persistance et l’expiration des sessions en production