Zurück zur Startseite

Nachrichtenverlauf in Python Ollama LLM Chat

Der Artikel beschreibt die Implementierung des Nachrichtenverlaufs in einem Konsolen-LLM-Chat in Python mit Ollama und LiteLLM. conversation_history mit Kürzung wird hinzugefügt, vollständige Nachrichtenstruktur. Code und Dialogbeispiele mit Kontext werden bereitgestellt.

Kontext im lokalen LLM-Chat: Code und Beispiele
Advertisement 728x90

Nachrichtenverlauf und Kontext in einem lokalen LLM-Chat mit Python implementieren

Der auf LiteLLM und Ollama basierende Konsolen-Chat aus dem vorherigen Teil verarbeitet Anfragen unabhängig voneinander. Das Modell kann vorherige Nachrichten nicht sehen, was den Dialog unterbricht: Verweise auf frühere Antworten werden ignoriert. Die Lösung besteht darin, den Nachrichtenverlauf in einer Python-Liste zu speichern und ihn mit jeder neuen Anfrage zu übergeben.

Dadurch wird eine Abfolge von Aufrufen zu einem zusammenhängenden Gespräch. Das Modell erhält den vollständigen Kontext: die Systemanweisung, frühere Nutzer/Assistent-Paare und die aktuelle Eingabe.

Nachrichtenstruktur für Kontext

Das Nachrichtenformat ist standardmäßig für OpenAI-kompatible APIs:

Google AdInline article slot
  • system: eine dauerhafte Anweisung, separat hinzugefügt
  • user: die Anfrage des Nutzers
  • assistant: die Antwort des Modells

Der Verlauf enthält nur Nutzer/Assistent-Paare. Beim Senden:

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

Die Reihenfolge ist entscheidend: System legt das Verhalten fest, Verlauf liefert Kontext, neue Nutzereingabe ist die aktuelle Anfrage.

Aktualisierter main.py-Code

Vollständiges Skript mit Verlauf und Kontextkürzung:

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 = "Du bist ein hilfreicher Assistent. Antworte präzise und auf den Punkt."

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"\nGenerierungszeit: {duration:.2f} Sek")
        return response.choices[0].message.content
    except Exception as e:
        print(f"\nAnfragefehler: {e}")
        return None


def main() -> None:
    print("Lokaler KI-Assistent mit Gedächtnis gestartet.")
    print("Gib eine Frage ein oder 'exit' zum Beenden.\n")

    conversation_history = []

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

        if user_input.lower() in ("exit", "quit"):
            print("Auf Wiedersehen!")
            break

        if not user_input:
            print("Bitte gib eine Frage ein.")
            continue

        print("\nModell denkt nach...")
        answer = send_request_to_llm(user_input, conversation_history)

        if answer is not None:
            print(f"\nKI: {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("\nAntwort konnte nicht abgerufen werden. Prüfe, ob Ollama läuft.\n")


if __name__ == "__main__":
    main()

Wichtige Logikänderungen

  • conversation_history: Liste in main() speichert Nachrichtenpaare
  • send_request_to_llm: akzeptiert Verlauf, erweitert via *
  • Paare speichern: nach einer Antwort werden Nutzer und Assistent hinzugefügt
  • trim_history: kürzt auf MAX_HISTORY_MESSAGES (6 Einträge — 3 Dialoge)

| Komponente | Vor Update | Nach Update |

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

| messages | system + user | system + history + user |

Google AdInline article slot

| Speicher | Keiner | Liste im RAM |

| Größe | Unbegrenzt | Bis zu 6 Nachrichten |

Kürzung verhindert Kontextüberlauf: alte Nachrichten erhöhen Tokens und verlangsamen Inferenz.

Kontext testen

Dialog mit abhängigen Anfragen:

  • Du: Nenne drei Python-Webentwicklungs-Frameworks
  • KI: Django, Flask, FastAPI
  • Du: Erzähl mir mehr über das zweite
  • KI: Flask ist ein leichtgewichtiges Microframework...

Das Modell bezieht sich korrekt auf "das zweite", indem es die vorherige Antwort sieht.

Grenzen der aktuellen Implementierung

  • Verlauf im RAM: geht beim Neustart verloren
  • Feste Grenze: 6 Nachrichten (konfigurierbar)
  • Keine Persistenz: erfordert Redis/Datenbank für Produktion

Für einen Telegram-Bot oder Web-App bleibt die Logik gleich: Verlauf in Nutzersitzung.

Was wichtig ist

  • Nachrichtenformat: system separat, Verlauf nur Nutzer/Assistent
  • Verlaufskürzung: [-limit:] bewahrt aktuelle Paare
  • Trennung der Verantwortlichkeiten: LLM-Anfragen in send_request_to_llm, Zustand in main()
  • Timeouts: request_timeout=120 für lange Kontexte
  • Protokollierung: Generierungszeit für Performance-Debugging

— Editorial Team

Advertisement 728x90

Weiterlesen