Zpět na domů

Historie zpráv v LLM-chatu Python Ollama

Článek popisuje implementaci historie zpráv v konzolovém LLM-chatu na Pythonu s Ollama a LiteLLM. Přidává se conversation_history s ořezáním, úplná struktura messages. Uvádí se kód a příklady dialogů s kontextem.

Kontext v lokálním LLM-chatu: kód a příklady
Advertisement 728x90

Implementace kontextu a historie zpráv v lokálním LLM chatu na Pythonu

Konzolový chat založený na LiteLLM a Ollama z předchozí části zpracovává dotazy nezávisle. Model nevidí předchozí repliky, což narušuje dialog: odkazy na minulé odpovědi jsou ignorovány. Řešením je ukládání historie zpráv v Python seznamu a její předávání s každým novým dotazem.

Tím se posloupnost volání mění v souvislou konverzaci. Model získává plný kontext: systémovou instrukci, předchozí páry uživatel/asistent a aktuální vstup.

Struktura zpráv pro kontext

Formát zpráv je standardní pro OpenAI kompatibilní API:

Google AdInline article slot
  • system: trvalá instrukce, přidává se zvlášť
  • user: dotaz uživatele
  • assistant: odpověď modelu

Historie obsahuje pouze user/assistant. Při odeslání:

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

Pořadí je klíčové: system nastavuje chování, historie poskytuje kontext, nový user je aktuální dotaz.

Aktualizovaný kód main.py

Úplný skript s historií a ořezáváním kontextu:

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 = "Jsi užitečný asistent. Odpovídej stručně a k věci."

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"\nDoba generování: {duration:.2f} sek")
        return response.choices[0].message.content
    except Exception as e:
        print(f"\nChyba při dotazu: {e}")
        return None


def main() -> None:
    print("Lokální AI asistent s pamětí spuštěn.")
    print("Zadejte dotaz nebo 'konec' pro ukončení.\n")

    conversation_history = []

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

        if user_input.lower() in ("konec", "exit", "quit"):
            print("Na shledanou!")
            break

        if not user_input:
            print("Zadejte dotaz.")
            continue

        print("\nModel přemýšlí...")
        answer = send_request_to_llm(user_input, conversation_history)

        if answer is not None:
            print(f"\nAI: {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("\nOdpověď se nepodařilo získat. Zkontrolujte, zda je Ollama spuštěna.\n")


if __name__ == "__main__":
    main()

Klíčové změny v logice

  • conversation_history: seznam v main() ukládá páry zpráv
  • send_request_to_llm: přijímá history, rozbalí přes *
  • Ukládání párů: po odpovědi se přidají user a assistant
  • trim_history: ořízne na MAX_HISTORY_MESSAGES (6 zpráv — 3 dialogy)

| Komponenta | Před aktualizací | Po aktualizaci |

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

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

Google AdInline article slot

| Paměť | Chybí | Seznam v RAM |

| Velikost | Neomezená | Až 6 zpráv |

Ořezávání zabraňuje přetečení kontextu: staré zprávy zvyšují tokeny a zpomalují inference.

Testování kontextu

Dialog se závislými dotazy:

  • Vy: Jmenuj tři frameworky pro webový vývoj v Pythonu
  • AI: Django, Flask, FastAPI
  • Vy: Řekni mi o druhém podrobněji
  • AI: Flask — lehký microframework...

Model odkazuje na „druhý“ správně, protože vidí předchozí odpověď.

Omezení současné implementace

  • Historie v RAM: ztrácí se po restartu
  • Pevný limit: 6 zpráv (lze upravit)
  • Žádná perzistence: pro produkci je potřeba Redis/Databáze

Pro Telegram bota nebo webovou aplikaci logika zůstává: history v uživatelské relaci.

Co je důležité

  • Formát zpráv: system zvlášť, history pouze user/assistant
  • Ořezávání historie: [-limit:] zachová poslední páry
  • Rozdělení odpovědnosti: LLM dotazy v send_request_to_llm, stav v main()
  • Časové limity: request_timeout=120 pro dlouhé kontexty
  • Logování: doba generování pro ladění výkonu

— Editorial Team

Advertisement 728x90

Číst dál