Retour à l'accueil

Historique des messages dans le chat Python Ollama LLM

L'article décrit l'implémentation de l'historique des messages dans un chat LLM console en Python avec Ollama et LiteLLM. conversation_history avec élagage est ajouté, structure complète des messages. Code et exemples de dialogues avec contexte sont fournis.

Contexte dans le chat LLM local : code et exemples
Advertisement 728x90

Implémentation de l'historique des messages et du contexte dans un chat LLM local avec Python

Le chat en console basé sur LiteLLM et Ollama de la partie précédente traite les requêtes indépendamment. Le modèle ne peut pas voir les messages précédents, ce qui rompt le dialogue : les références aux réponses passées sont ignorées. La solution consiste à stocker l'historique des messages dans une liste Python et à le transmettre avec chaque nouvelle requête.

Cela transforme une séquence d'appels en une conversation cohérente. Le modèle reçoit le contexte complet : l'instruction système, les paires utilisateur/assistant précédentes et l'entrée actuelle.

Structure des messages pour le contexte

Le format des messages est standard pour les API compatibles OpenAI :

Google AdInline article slot
  • system : une instruction persistante, ajoutée séparément
  • user : la requête de l'utilisateur
  • assistant : la réponse du modèle

L'historique contient uniquement les paires utilisateur/assistant. Lors de l'envoi :

[
    {"role": "system", "content": SYSTEM_PROMPT},
    *conversation_history,
    {"role": "user", "content": user_message}
]

L'ordre est critique : le système définit le comportement, l'historique fournit le contexte, le nouvel utilisateur est la requête actuelle.

Code mis à jour de main.py

Script complet avec historique et écrêtage du contexte :

Google AdInline article slot
# -*- coding: utf-8 -*-
import time
from typing import Optional
from litellm import completion

MODEL = "ollama_chat/qwen2.5:3b"
API_BASE = "http://localhost:11434"
SYSTEM_PROMPT = "Vous êtes un assistant utile. Répondez de manière concise et précise."

MAX_HISTORY_MESSAGES = 6


def trim_history(history: list, limit: int) -> list:
    if len(history) <= limit:
        return history
    return history[-limit:]


def send_request_to_llm(user_message: str, history: list) -> Optional[str]:
    messages = [
        {"role": "system", "content": SYSTEM_PROMPT},
        *history,
        {"role": "user", "content": user_message},
    ]
    try:
        start_time = time.time()
        response = completion(
            model=MODEL,
            messages=messages,
            api_base=API_BASE,
            request_timeout=120,
        )
        duration = time.time() - start_time
        print(f"\nTemps de génération : {duration:.2f} sec")
        return response.choices[0].message.content
    except Exception as e:
        print(f"\nErreur de requête : {e}")
        return None


def main() -> None:
    print("Assistant IA local avec mémoire démarré.")
    print("Entrez une question ou 'exit' pour quitter.\n")

    conversation_history = []

    while True:
        user_input = input("Vous : ").strip()

        if user_input.lower() in ("exit", "quit"):
            print("Au revoir !")
            break

        if not user_input:
            print("Veuillez entrer une question.")
            continue

        print("\nModèle en réflexion...")
        answer = send_request_to_llm(user_input, conversation_history)

        if answer is not None:
            print(f"\nIA : {answer}\n")
            conversation_history.append({"role": "user",      "content": user_input})
            conversation_history.append({"role": "assistant", "content": answer})
            conversation_history = trim_history(conversation_history, MAX_HISTORY_MESSAGES)
        else:
            print("\nÉchec de la réponse. Vérifiez si Ollama est en cours d'exécution.\n")


if __name__ == "__main__":
    main()

Changements logiques clés

  • conversation_history : liste dans main() stocke les paires de messages
  • send_request_to_llm : accepte l'historique, l'étend via *
  • Sauvegarde des paires : après une réponse, utilisateur et assistant sont ajoutés
  • trim_history : écrête à MAX_HISTORY_MESSAGES (6 éléments — 3 dialogues)

| Composant | Avant mise à jour | Après mise à jour |

|-----------|-------------------|-------------------|

| messages | système + utilisateur | système + historique + utilisateur |

Google AdInline article slot

| Mémoire | Aucune | Liste en RAM |

| Taille | Illimitée | Jusqu'à 6 messages |

L'écrêtage empêche le débordement de contexte : les anciens messages augmentent les tokens et ralentissent l'inférence.

Test du contexte

Dialogue avec requêtes dépendantes :

  • Vous : Nommez trois frameworks de développement web Python
  • IA : Django, Flask, FastAPI
  • Vous : Dites-m'en plus sur le deuxième
  • IA : Flask est un microframework léger...

Le modèle référence correctement "le deuxième" en voyant la réponse précédente.

Limites de l'implémentation actuelle

  • Historique en RAM : perdu au redémarrage
  • Limite fixe : 6 messages (configurable)
  • Aucune persistance : nécessite Redis/BDD pour la production

Pour un bot Telegram ou une application web, la logique reste : historique dans la session utilisateur.

Ce qui est important

  • Format des messages : système séparément, historique uniquement utilisateur/assistant
  • Écrêtage de l'historique : [-limit:] préserve les paires récentes
  • Séparation des responsabilités : requêtes LLM dans send_request_to_llm, état dans main()
  • Timeouts : request_timeout=120 pour les longs contextes
  • Journalisation : temps de génération pour le débogage des performances

— Editorial Team

Advertisement 728x90

Lire ensuite