Volver al inicio

Historial de mensajes en chat Python Ollama LLM

El artículo describe la implementación del historial de mensajes en un chat LLM de consola en Python con Ollama y LiteLLM. Se añade conversation_history con recorte, estructura completa de mensajes. Se proporcionan código y ejemplos de diálogos con contexto.

Contexto en chat LLM local: código y ejemplos
Advertisement 728x90

Implementación de Historial de Mensajes y Contexto en un Chat Local con LLM en Python

El chat por consola basado en LiteLLM y Ollama de la parte anterior procesa las solicitudes de forma independiente. El modelo no puede ver los mensajes anteriores, lo que rompe el diálogo: las referencias a respuestas pasadas se ignoran. La solución es almacenar el historial de mensajes en una lista de Python y pasarlo con cada nueva solicitud.

Esto convierte una secuencia de llamadas en una conversación coherente. El modelo recibe el contexto completo: la instrucción del sistema, los pares usuario/asistente anteriores y la entrada actual.

Estructura de Mensajes para el Contexto

El formato de mensaje es estándar para las API compatibles con OpenAI:

Google AdInline article slot
  • system: una instrucción persistente, añadida por separado
  • user: la consulta del usuario
  • assistant: la respuesta del modelo

El historial contiene solo pares usuario/asistente. Al enviar:

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

El orden es crítico: el sistema establece el comportamiento, el historial proporciona contexto y el nuevo usuario es la consulta actual.

Código Actualizado de main.py

Script completo con historial y recorte de contexto:

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 = "Eres un asistente útil. Responde de forma concisa y al grano."

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"\nTiempo de generación: {duration:.2f} seg")
        return response.choices[0].message.content
    except Exception as e:
        print(f"\nError en la solicitud: {e}")
        return None


def main() -> None:
    print("Asistente de IA local con memoria iniciado.")
    print("Introduce una pregunta o 'exit' para salir.\n")

    conversation_history = []

    while True:
        user_input = input("Tú: ").strip()

        if user_input.lower() in ("exit", "quit"):
            print("¡Hasta luego!")
            break

        if not user_input:
            print("Por favor, introduce una pregunta.")
            continue

        print("\nEl modelo está pensando...")
        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("\nNo se pudo obtener una respuesta. Verifica si Ollama está en ejecución.\n")


if __name__ == "__main__":
    main()

Cambios Lógicos Clave

  • conversation_history: lista en main() que almacena pares de mensajes
  • send_request_to_llm: acepta historial, se expande mediante *
  • Guardar pares: después de una respuesta, se añaden usuario y asistente
  • trim_history: recorta a MAX_HISTORY_MESSAGES (6 elementos — 3 diálogos)

| Componente | Antes de la Actualización | Después de la Actualización |

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

| mensajes | sistema + usuario | sistema + historial + usuario |

Google AdInline article slot

| Memoria | Ninguna | Lista en RAM |

| Tamaño | Ilimitado | Hasta 6 mensajes |

El recorte evita el desbordamiento de contexto: los mensajes antiguos aumentan los tokens y ralentizan la inferencia.

Prueba del Contexto

Diálogo con consultas dependientes:

  • Tú: Nombra tres frameworks de desarrollo web en Python
  • IA: Django, Flask, FastAPI
  • Tú: Cuéntame más sobre el segundo
  • IA: Flask es un microframework ligero...

El modelo referencia correctamente "el segundo" al ver la respuesta anterior.

Limitaciones de la Implementación Actual

  • Historial en RAM: se pierde al reiniciar
  • Límite fijo: 6 mensajes (configurable)
  • Sin persistencia: requiere Redis/BD para producción

Para un bot de Telegram o una aplicación web, la lógica permanece: historial en la sesión del usuario.

Lo Importante

  • Formato de mensaje: sistema por separado, historial solo usuario/asistente
  • Recorte de historial: [-limit:] preserva los pares recientes
  • Separación de responsabilidades: solicitudes LLM en send_request_to_llm, estado en main()
  • Tiempos de espera: request_timeout=120 para contextos largos
  • Registro: tiempo de generación para depuración de rendimiento

— Editorial Team

Advertisement 728x90

Leer después