Blog
AI/Voice
25 janvier 202610 min

Memoire IA : historique de conversation et tokens

Points cles a retenir : Donner de la memoire a une IA conversationnelle repose sur trois mecanismes : une sliding window avec priorites (system prompt + derniers echanges toujours inclus), un budget tokens controle pour maitriser les couts (une conversation de 10 echanges coute 5x plus), et un systeme de fallback entre modeles LLM pour garantir la disponibilite. C'est la difference entre un outil et un veritable assistant.

La premiere version de l'IA dans TAMSIV etait amnesiaque. "Ajoute du pain a ma liste de courses" fonctionnait parfaitement. Mais enchainer avec "Mets-la pour demain" echouait lamentablement — l'IA ne savait pas de quelle tache on parlait. Chaque echange repartait de zero.

Ce probleme est fondamental dans toute application IA conversationnelle. Les LLM n'ont aucune memoire native. A chaque requete, il faut renvoyer l'ensemble du contexte. Et ca change tout — en termes d'UX, de cout, et d'architecture.

Voici comment j'ai donne de la memoire a l'IA de TAMSIV.

Pile de carnets et journaux avec des marque-pages et post-it, symbolisant la memoire et l'historique de conversation
La memoire de l'IA, c'est comme un carnet : il faut choisir quoi garder et quoi oublier.

Pourquoi les LLM n'ont-ils pas de memoire ?

C'est contre-intuitif quand on utilise ChatGPT ou Claude, mais ces modeles n'ont aucune persistance entre les requetes. Chaque appel API est independant. La "memoire" que tu percois dans une conversation ChatGPT, c'est l'application qui renvoie l'historique complet a chaque message.

Concretement, quand tu envoies ton 5e message dans une conversation, l'API recoit :

  1. Le system prompt (les instructions de comportement)
  2. Le message 1 + la reponse 1
  3. Le message 2 + la reponse 2
  4. Le message 3 + la reponse 3
  5. Le message 4 + la reponse 4
  6. Ton message 5

A chaque echange supplementaire, le payload grossit. Et avec lui, deux problemes : la fenetre de contexte (limite technique du modele) et le cout en tokens (chaque token est facture).

C'est ce que la documentation d'OpenAI appelle la gestion de l'etat de conversation.

Comment fonctionne la sliding window de TAMSIV ?

La solution classique est la sliding window : on ne garde que les N derniers echanges. Mais une fenetre glissante brute est trop simpliste pour une app comme TAMSIV, ou l'IA doit comprendre des references a des actions passees.

J'ai implemente une sliding window avec priorites :

  • Priorite maximale : le system prompt (toujours inclus, jamais tronque)
  • Priorite haute : les 2 derniers echanges (le contexte immediat)
  • Priorite haute : les function calls et leurs resultats (les actions effectuees — creation de tache, modification de memo, etc.)
  • Priorite moyenne : les echanges precedents (3 a N-2)
  • Priorite basse : les echanges anciens, resumes ou supprimes selon le budget tokens

Pourquoi les function calls sont-ils prioritaires ? Parce que dans TAMSIV, quand l'utilisateur dit "Modifie la priorite de la tache qu'on vient de creer", l'IA doit savoir quelle tache a ete creee. Cette information est dans le function_result d'un echange precedent. Sans elle, l'IA ne peut pas resoudre le pronom "la".

Comment gerer le budget tokens sans exploser les couts ?

C'est le nerf de la guerre. Une conversation de 10 echanges peut couter 5 fois plus qu'un echange isole, parce que le payload cumulatif est renvoye a chaque fois.

Exemple concret avec un modele a 0.001$ / 1000 tokens :

  • Echange 1 : ~500 tokens (system prompt + message) = 0.0005$
  • Echange 5 : ~2500 tokens (historique 1-4 + message 5) = 0.0025$
  • Echange 10 : ~5000 tokens (historique 1-9 + message 10) = 0.005$
  • Total conversation 10 echanges : ~25 000 tokens cumules = 0.025$

Pour une app avec des milliers d'utilisateurs, ces centimes s'additionnent vite. J'ai mis en place trois garde-fous :

  1. Limite de 20 echanges par conversation : au-dela, on recommande de demarrer une nouvelle conversation. Ca evite les conversations-monstres a 100 echanges.
  2. Compteur de tokens estime : avant chaque appel, le backend estime le nombre de tokens du payload complet. Si ca depasse le budget, les echanges les plus anciens sont tronques.
  3. Choix du modele selon la complexite : un message simple ("Ajoute du pain") utilise un modele leger. Une demande complexe ("Reorganise mes taches de la semaine par priorite") utilise un modele plus puissant.
Sablier transparent rempli de sable dore et de particules numeriques, symbolisant le budget tokens
Le budget tokens, c'est comme un sablier : chaque grain compte, et il faut decider quoi garder.

Comment fonctionne le fallback entre modeles LLM ?

En production, la fiabilite est non-negociable. Si le modele principal (configure via OPENROUTER_MODEL) renvoie une erreur 429 (rate limit) ou 503 (service unavailable), l'utilisateur ne doit rien remarquer.

Le backend de TAMSIV implemente un fallback automatique :

  1. Appel au modele principal via OpenRouter
  2. Si erreur 429/503 → retry avec OPENROUTER_FALLBACK_MODEL
  3. L'AlertService envoie un email a l'admin pour signaler le fallback
  4. L'utilisateur recoit sa reponse normalement — aucune degradation perceptible

En production, TAMSIV fait 2 a 3 fallbacks par semaine. C'est minime, mais ca arrive. Sans ce mecanisme, l'utilisateur verrait un message d'erreur generique — et probablement quitterait l'app.

Le choix d'OpenRouter comme proxy LLM (plutot qu'appeler directement l'API OpenAI ou Anthropic) est strategique : il permet de changer de modele sans modifier le code. Si un nouveau modele sort, il suffit de changer une variable d'environnement. Le pipeline vocal complet reste identique.

Quel impact la memoire a-t-elle sur l'experience utilisateur ?

La difference est spectaculaire. Avant l'historique de conversation, chaque echange etait independant. Apres, l'IA devient un veritable assistant :

  • "Modifie la priorite de la tache qu'on vient de creer" → l'IA sait quelle tache, et la modifie
  • "Finalement, mets ca a vendredi" → l'IA comprend que "ca" fait reference au dernier evenement cree
  • "Ajoute aussi un memo la-dessus" → l'IA reprend le sujet de la conversation pour creer le memo
  • "Non, j'ai dit demain, pas apres-demain" → l'IA corrige en comprenant la reference temporelle

C'est la difference entre un formulaire vocal (repete tout a chaque fois) et un assistant qui ecoute et se souvient. C'est ce qui rend le Dictaphone de TAMSIV utilisable au quotidien.

Comment le system prompt influence-t-il la qualite des reponses ?

Le system prompt est le document le plus important de l'application. C'est lui qui definit le comportement de l'IA : ton, format de reponse, function tools disponibles, contraintes.

Le system prompt de TAMSIV inclut :

  • Le persona : "Tu es l'assistant vocal de TAMSIV, une application de gestion de taches et memos."
  • Les function tools : les 7 fonctions que l'IA peut appeler (create_task, update_task, create_memo, update_memo, create_calendar_event, ask_clarification, end_conversation)
  • Les contraintes : reponses courtes (l'utilisateur ecoute via TTS), pas de markdown, pas de listes longues
  • Le contexte utilisateur : la langue preferee, le fuseau horaire, le plan (Free/Pro/Team)

Un system prompt bien concu reduit drastiquement les hallucinations et les reponses hors-sujet. C'est un investissement qui se repercute sur chaque conversation.

Comment gerer les conversations multimodales (voix + texte) ?

Dans TAMSIV, l'utilisateur parle mais l'IA repond en voix (via OpenAI TTS) ET en texte (affiche a l'ecran). L'historique stocke les deux formes :

  • Cote utilisateur : le texte transcrit par le STT (pas l'audio brut — trop lourd en tokens)
  • Cote IA : le texte de la reponse (envoye au TTS et affiche)

Le pipeline complet est : Audio → STT → Texte → LLM (avec historique) → Texte → TTS → Audio. L'historique ne vit que dans la couche texte, ce qui simplifie enormement l'architecture.

Filet de securite attrapant des orbes lumineux qui tombent, symbolisant le systeme de fallback
Le fallback entre modeles LLM : un filet de securite invisible pour l'utilisateur.

Quelles alternatives a la sliding window existent ?

La sliding window n'est pas la seule approche. D'autres strategies existent :

  • Summarization : resumer les anciens echanges en un paragraphe condense. Avantage : compression maximale. Inconvenient : perte de details, et un appel LLM supplementaire pour le resume.
  • RAG (Retrieval Augmented Generation) : stocker l'historique dans une base vectorielle et ne recuperer que les echanges pertinents par similarite semantique. Puissant mais lourd a implementer.
  • Memory explicite : stocker des "faits" extraits des conversations (preferences utilisateur, taches recurrentes) dans une base structuree. C'est ce que fait ChatGPT avec sa feature "Memory".

Pour TAMSIV, la sliding window avec priorites est le meilleur compromis : simple a implementer, efficace en tokens, et suffisante pour des conversations de 5 a 15 echanges. Si les conversations devenaient beaucoup plus longues, j'envisagerais le RAG.

Comment implementer un historique de conversation dans ton propre projet ?

Si tu construis une app avec un LLM, voici les etapes :

  1. Stocke l'historique cote serveur : ne fais jamais confiance au client pour maintenir l'etat de la conversation. Le backend est la source de verite.
  2. Implemente une sliding window : commence simple (garder les N derniers echanges), puis ajoute des priorites si necessaire.
  3. Budgetise les tokens : compte les tokens avant chaque appel. Tronque intelligemment si le budget est depasse.
  4. Ajoute un fallback : au minimum, un modele de secours en cas d'erreur du modele principal.
  5. Mesure les couts : logue chaque appel avec le nombre de tokens utilises. Ca permet d'optimiser le systeme sur la duree.

L'admin dashboard de TAMSIV affiche les metriques de conversation en temps reel : nombre moyen d'echanges, cout moyen par conversation, taux de fallback. Ces donnees sont essentielles pour optimiser les couts en production.

FAQ

Combien d'echanges un utilisateur moyen fait-il par conversation ?

Dans TAMSIV, la moyenne est de 3 a 5 echanges. L'utilisateur type dit "Ajoute une tache pour demain : rappeler le dentiste", confirme la preview, et enchaine avec une modification ("Mets-la en priorite haute"). Les conversations longues (10+ echanges) representent moins de 10% du volume.

Le cout de l'historique de conversation est-il significatif ?

Oui, c'est le poste de depense principal du pipeline IA. Chaque echange supplementaire augmente le cout cumule. Pour TAMSIV, le cout moyen par conversation est d'environ 0.01 a 0.03 EUR avec le modele principal. Le fallback model est generalement moins cher, ce qui compense partiellement les surcoutes.

Faut-il stocker l'historique en base de donnees ?

Pour TAMSIV, l'historique vit en memoire (cote backend) pendant la session WebSocket. Il n'est pas persiste en base — quand la connexion se ferme, l'historique est perdu. C'est un choix delibere : les conversations sont courtes et transitoires. Si tu as besoin de reprendre des conversations plus tard, il faudra persister en base.

OpenRouter vs appeler directement les APIs des fournisseurs LLM ?

OpenRouter agit comme un proxy qui unifie l'acces a des dizaines de modeles (OpenAI, Anthropic, Google, etc.) via une seule API. L'avantage : changer de modele sans modifier le code. L'inconvenient : une couche supplementaire (latence marginale). Pour une app comme TAMSIV qui a besoin de flexibilite et de fallback, c'est un choix evident.

La memoire de conversation fonctionne-t-elle avec le mode Realtime ?

TAMSIV a trois modes WebSocket. En mode LiveWebSocket (le mode par defaut), l'historique est gere manuellement comme decrit dans cet article. En mode Realtime (OpenAI Realtime API), l'historique est gere nativement par l'API — c'est un protocole bidirectionnel avec etat. Le mode legacy fonctionne en batch sans persistance.