Conversation multi-tours
L'API CloudZIR est sans état : elle ne garde aucune mémoire entre deux requêtes. Pour tenir une conversation, c'est vous qui renvoyez l'historique à chaque appel.
Le principe#
Chaque appel contient la liste complète des messages échangés jusqu'ici. Le modèle lit cette liste et produit le message suivant :
Tour 1 → [system, user₁] → assistant₁
Tour 2 → [system, user₁, assistant₁, user₂] → assistant₂
Tour 3 → [system, user₁, assistant₁, user₂, ...] → assistant₃
Exemple complet#
from openai import OpenAI
client = OpenAI(api_key="zir_ai_...", base_url="https://api.cloudzir.com/v1")
messages = [{"role": "system", "content": "Tu es un assistant concis, en français."}]
def demander(texte: str) -> str:
messages.append({"role": "user", "content": texte})
reponse = client.chat.completions.create(model="mina-low", messages=messages)
contenu = reponse.choices[0].message.content
# ÉTAPE CLÉ : on remet la réponse dans l'historique
messages.append({"role": "assistant", "content": contenu})
return contenu
print(demander("Quelle est la capitale de l'Algérie ?"))
print(demander("Et sa population ?")) # « sa » = celle d'Alger : le contexte est conservéimport OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.CLOUDZIR_API_KEY,
baseURL: "https://api.cloudzir.com/v1",
});
const messages = [
{ role: "system", content: "Tu es un assistant concis, en français." },
];
async function demander(texte) {
messages.push({ role: "user", content: texte });
const r = await client.chat.completions.create({ model: "mina-low", messages });
const contenu = r.choices[0].message.content;
messages.push({ role: "assistant", content: contenu });
return contenu;
}
console.log(await demander("Quelle est la capitale de l'Algérie ?"));
console.log(await demander("Et sa population ?"));curl https://api.cloudzir.com/v1/chat/completions \
-H "Authorization: Bearer $CLOUDZIR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "mina-low",
"messages": [
{"role": "system", "content": "Tu es un assistant concis, en français."},
{"role": "user", "content": "Quelle est la capitale de l Algérie ?"},
{"role": "assistant", "content": "Alger."},
{"role": "user", "content": "Et sa population ?"}
]
}'Ne pas réinsérer la réponse de l'assistant dans messages. Le modèle perd
alors le fil et se répète : chaque tour lui paraît être le premier.
Les rôles#
| Rôle | Usage |
|---|---|
system | Instructions permanentes : ton, langue, périmètre, règles. Placé en premier. |
user | Ce que dit l'utilisateur final. |
assistant | Ce que le modèle a répondu (à renvoyer tel quel). |
tool | Le résultat d'un outil que vous avez exécuté (appels d'outils). |
developer est accepté comme synonyme de system.
Maîtriser la longueur (et le coût)#
L'historique est refacturé à chaque tour. Trois stratégies, du plus simple au plus fin :
1. Fenêtre glissante#
MAX_TOURS = 12
def tronquer(messages: list[dict]) -> list[dict]:
"""Garde le message système + les N derniers messages."""
systeme = [m for m in messages[:1] if m["role"] == "system"]
reste = messages[len(systeme):]
return systeme + reste[-MAX_TOURS * 2:]
2. Résumé des anciens tours#
def compacter(client, messages: list[dict]) -> list[dict]:
"""Remplace les vieux échanges par un résumé - moins cher que de tout garder."""
systeme, anciens, recents = messages[:1], messages[1:-8], messages[-8:]
if len(anciens) < 6:
return messages
resume = client.chat.completions.create(
model="mina-flash", # le résumé n'a pas besoin du gros modèle
messages=[
{"role": "system", "content": "Résume ces échanges en 5 points factuels."},
{"role": "user", "content": str(anciens)},
],
max_tokens=300,
).choices[0].message.content
return systeme + [{"role": "system", "content": f"Résumé des échanges précédents : {resume}"}] + recents
3. Vérifier avant d'envoyer#
Si le contexte estimé dépasse la fenêtre du modèle, l'API répond 400 avec un
message explicite. Anticipez avec l'estimation « caractères ÷ 4 » décrite dans
Jeton et utilisation, et choisissez un modèle à plus
grande fenêtre si besoin (mina-full monte à 256 000 jetons ; voir
Modèles et prix).
Persister une conversation#
Stockez la liste messages dans votre base (une ligne par message, avec
l'identifiant de conversation) et rechargez-la au tour suivant. Ne stockez jamais la clé API
côté navigateur : l'appel doit partir de votre serveur.
CloudZIR n'utilise pas le contenu de vos prompts pour entraîner des modèles. Pour les appels
synchrones de conversation, les routes de l'API transmettent les messages et images au moteur
sans les enregistrer dans la base de l'API; les métadonnées d'usage nécessaires à la facturation
et au support sont enregistrées. Les fichiers déposés via
l'API Fichiers sont stockés séparément et supprimés par
DELETE /v1/files/{file_id}; aucune expiration automatique ne leur est appliquée. Voir aussi Mise en cache du contexte
et la FAQ.