Lección 21 · 5 min · Gratis

Chatbot con historial de conversación

Copyright (c) Meta Platforms, Inc. y afiliados. Este software puede ser usado y distribuido según los términos del Acuerdo de Licencia de la Comunidad Llama.

Open In Colab

Este tutorial te muestra cómo construir un chatbot con historial de conversación. Usando Llama 4, crearemos un agente conversacional que toma una URL, comprende su contenido y te permite tener una conversación interactiva con él, manteniendo el historial de conversación.

Componente Elección Por qué
Modelo Llama-4-Maverick-17B-128E-Instruct-FP8 Un potente modelo Mixture-of-Experts (MoE) ideal para seguir instrucciones complejas. Llama 4 Maverick ofrece un rendimiento superior y una ventana de contexto masiva (hasta 1M de tokens).
Patrón Aprendizaje en contexto + memoria de ventana deslizante Pasaremos todo el contenido de la página web directamente al contexto del modelo. La gran ventana de contexto de Llama 4 hace que este enfoque simple sea viable incluso para páginas muy grandes, a menudo eliminando la necesidad de un sistema RAG complejo.
Infraestructura La API de Llama oficial de Meta Proporciona acceso sin servidor y listo para producción a los modelos Llama 4 usando el SDK llama_api_client.

Nota sobre los proveedores de inferencia: Este tutorial usa la API de Llama con fines de demostración. Sin embargo, puedes ejecutar modelos Llama 4 con cualquier proveedor de inferencia de tu preferencia. Ejemplos comunes incluyen Amazon Bedrock y Together AI. La lógica central de este tutorial puede adaptarse a cualquiera de estos proveedores.

Lo que aprenderás

  • Los fundamentos de la finalización de chat: Cómo estructurar conversaciones usando los roles de sistema, usuario y asistente.
  • Cómo gestionar el historial de conversación: Implementar una ventana deslizante para mantener el contexto en conversaciones largas sin exceder los límites de tokens.
  • Ingeniería de prompt práctica: Cómo guiar al modelo para que responda preguntas basándose solo en el texto proporcionado.
  • Cómo realizar metatareas: Aprovechar el modelo para resumir el historial de conversación.

Instalar dependencias

Necesitarás algunas librerías para este proyecto: requests para descargar páginas web, readability-lxml para extraer el contenido principal, markdownify para convertir HTML a Markdown limpio, tiktoken para un conteo preciso de tokens, y el llama-api-client oficial.

!uv pip install --quiet requests beautifulsoup4 readability-lxml markdownify tiktoken llama-api-client

Importaciones y configuración del cliente de la API de Llama

En este tutorial, usaremos la API de Llama como proveedor de inferencia. Por lo tanto, primero necesitarías obtener una clave de API de Llama si aún no tienes una. Luego, establece la clave de API de Llama como una variable de entorno, como LLAMA_API_KEY, como se muestra en el ejemplo.

Recuerda, puedes adaptar esta sección para usar tu proveedor de inferencia preferido.

import os, sys, re, html, textwrap
import requests
from typing import List, Dict
from bs4 import BeautifulSoup
import tiktoken
from readability import Document
from markdownify import markdownify
from llama_api_client import LlamaAPIClient
# --- Llama client ---
API_KEY = os.getenv("LLAMA_API_KEY")
if not API_KEY:
    sys.exit("❌  Please set the LLAMA_API_KEY environment variable.")

client = LlamaAPIClient(api_key=API_KEY)

Obtener y limpiar una página web

Para obtener respuestas de alta calidad del modelo, primero debes proporcionarle datos de alta calidad. El HTML sin procesar contiene mucho "ruido" (como barras de navegación, anuncios y scripts) que pueden distraer al modelo. La siguiente función implementa un proceso de tres pasos para transformar una página web desordenada en Markdown limpio y estructurado que es ideal para el LLM.

  1. Extraer contenido principal: Usa la librería readability para extraer el cuerpo principal del artículo, descartando el contenido repetitivo común como encabezados, pies de página y barras laterales.
  2. Limpieza final: Usa BeautifulSoup para eliminar cualquier etiqueta <script> o <style> restante.
  3. Convertir a Markdown: Convierte el HTML limpio a Markdown usando markdownify. Esto es mejor que el texto plano porque conserva una estructura semántica importante, como encabezados, listas y enlaces, lo que ayuda al modelo a comprender mejor la jerarquía y el significado del contenido.
def fetch_page_text(url: str, timeout: int = 15) -> str:
    """Download a webpage and return plain text (scripts/styles removed)."""
    r = requests.get(url, timeout=timeout)
    r.raise_for_status
    html_raw = r.text

    # ---- 1. keep only the main article if possible -----------------------
    html_main = Document(html_raw).summary(html_partial=True)
    soup = BeautifulSoup(html_main, "html.parser")

    # ---- 2. drop noise ----------------------------------------------------
    for tag in soup(["script", "style", "noscript", "header", "footer", "nav", "aside"]):
        tag.decompose()

    # ---- 3. html to markdown ----------------------------------------------
    cleaned_html = str(soup)
    md_text = markdownify(cleaned_html, heading_style="ATX")      # ## Heading
    md_text = html.unescape(md_text)
    md_text = re.sub(r"\n{3,}", "\n\n", md_text).strip()

    return md_text
url = input("🔗  Paste a URL to chat about: ").strip()
raw_article = fetch_page_text(url)
print(f"✅  Retrieved {len(raw_article):,} characters.")
print(raw_article)
🔗  Paste a URL to chat about:  https://ai.meta.com/blog/llama-4-multimodal-intelligence/
✅  Retrieved 20,286 characters.
## Takeaways

* We’re sharing the first models in the Llama 4 herd, which will enable people to build more personalized multimodal experiences.
* Llama 4 Scout, a 17 billion active parameter model with 16 experts, is the best multimodal model in the world in its class and is more powerful than all previous generation Llama models, while fitting in a single NVIDIA H100 GPU. Additionally, Llama 4 Scout offers an industry-leading context window of 10M and delivers better results than Gemma 3, Gemini 2.0 Flash-Lite, and Mistral 3.1 across a broad range of widely reported benchmarks.
* Llama 4 Maverick, a 17 billion active parameter model with 128 experts, is the best multimodal model in its class, beating GPT-4o and Gemini 2.0 Flash across a broad range of widely reported benchmarks, while achieving comparable results to the new DeepSeek v3 on reasoning and coding—at less than half the active parameters. Llama 4 Maverick offers a best-in-class performance to cost ratio with an experimental chat version scoring ELO of 1417 on [LMArena](https://lmarena.ai/leaderboard).
* These models are our best yet thanks to distillation from Llama 4 Behemoth, a 288 billion active parameter model with 16 experts that is our most powerful yet and among the world’s smartest LLMs. Llama 4 Behemoth outperforms GPT-4.5, Claude Sonnet 3.7, and Gemini 2.0 Pro on several STEM benchmarks. Llama 4 Behemoth is still training, and we’re excited to share more details about it even while it’s still in flight.
* Download the Llama 4 Scout and Llama 4 Maverick models today on [llama.com](https://www.llama.com/llama-downloads/) and [Hugging Face](https://huggingface.co/meta-llama). Try Meta AI built with Llama 4 in WhatsApp, Messenger, Instagram Direct, and on the [web](https://meta.ai/).

As more people continue to use artificial intelligence to enhance their daily lives, it’s important that the leading models and systems are openly available so everyone can build the future of personalized experiences. Today, we’re excited to announce the most advanced suite of models that support the entire [Llama](https://www.llama.com/) ecosystem. We’re introducing Llama 4 Scout and Llama 4 Maverick, the first open-weight natively multimodal models with unprecedented context length support and our first built using a mixture-of-experts (MoE) architecture. We’re also previewing Llama 4 Behemoth, one of the smartest LLMs in the world and our most powerful yet to serve as a teacher for our new models.

These Llama 4 models mark the beginning of a new era for the Llama ecosystem. We designed two efficient models in the Llama 4 series, Llama 4 Scout, a 17 billion active parameter model with 16 experts, and Llama 4 Maverick, a 17 billion active parameter model with 128 experts. The former fits on a single H100 GPU (with Int4 quantization) while the latter fits on a single H100 host. We also trained a teacher model, Llama 4 Behemoth, that outperforms GPT-4.5, Claud
… (salida recortada)

Gestionar la ventana de contexto

Los modelos Llama tienen una ventana de contexto fija. La ventana de contexto es el número máximo de tokens que pueden considerar a la vez. Una ventaja clave de Llama 4 es el tamaño de esta ventana. Llama-4-Maverick-17B-128E-Instruct-FP8 admite hasta 1 millón de tokens, lo que te permite pasar libros enteros o documentos extensos como contexto.

Aunque Llama 4 ofrece una ventana de contexto muy grande de 1M de tokens, la mayoría de los proveedores de API admiten ventanas de tokens más pequeñas que esta. Como este tutorial usa la API de Llama, trabajaremos dentro de su ventana de tokens, que es de 128k. Debemos asegurarnos de que todo nuestro prompt, que incluye el mensaje del sistema, el contenido de la página web y el historial de conversación, quepa dentro de este límite.

Para evitar errores, truncaremos el contenido de la página web si es demasiado largo. Usaremos tiktoken para un conteo y truncamiento precisos de tokens. Reservaremos un HEADROOM de 16,384 tokens para acomodar un historial de chat de larga duración y la siguiente respuesta del modelo, y recortaremos el artículo para que quepa en el espacio restante. Ten en cuenta que, si bien tiktoken proporciona un conteo local preciso, el número exacto de tokens procesados por una API puede variar ligeramente; por lo tanto, usamos el símbolo '≈' para el conteo.

MAX_CTX = 128000 # A practical context window for Llama 4 Maverick
HEADROOM = 16384 # for turns + response
MAX_ARTICLE = MAX_CTX - HEADROOM

encoding = tiktoken.get_encoding("o200k_base")
def count_tokens(s: str) -> int:
    """Returns the number of tokens in a text string."""
    return len(encoding.encode(s))

def truncate(text: str, max_tokens: int = MAX_ARTICLE) -> str:
    """Truncates a text string to a maximum number of tokens."""
    if count_tokens(text) <= max_tokens:
        return text
    
    tokens = encoding.encode(text)
    truncated_tokens = tokens[:max_tokens]
    return encoding.decode(truncated_tokens, errors='ignore') + "\n\n[... truncated to fit context ...]"
    
article = truncate(raw_article)
print(f"Article now ≈ {count_tokens(article)} tokens.")
Article now ≈ 4216 tokens.

Chatbot con historial de conversación

A continuación, crearemos una clase PageChat para encapsular la lógica del chatbot y gestionar su estado. Usar una clase es una forma limpia de manejar el historial de conversación y la configuración del modelo.

El SYSTEM_PROMPT es un componente clave. Proporciona al modelo sus instrucciones principales, definiendo su personalidad y sus restricciones. Una buena práctica es ser muy específico. Aquí, le indicamos que responda preguntas solo a partir del texto de la página web proporcionado y que declare explícitamente cuando falte información. Esta es una técnica crítica para fundamentar el modelo y reducir la probabilidad de respuestas fabricadas (alucinaciones).

El método _messages ensambla la carga útil final enviada a la API. Observa el orden:

  1. El SYSTEM_PROMPT establece el comportamiento general.
  2. Un segundo mensaje del sistema inyecta el contenido article como contexto.
  3. Se incluyen las últimas k vueltas del historial de conversación, implementando una ventana deslizante para la memoria.
  4. Se añade el último user_msg.

Esta estructura asegura que el modelo tenga todo el contexto necesario para generar una respuesta relevante y precisa.

SYSTEM_PROMPT = (
    "You are PageChat, an AI that answers questions **only** from the supplied "
    "webpage text. If information is absent, say so. Be concise."
)

class PageChat:
    def __init__(self, article_text: str,
                 model: str = "Llama-4-Maverick-17B-128E-Instruct-FP8",
                 history_window: int = 128):
        self.article = article_text
        self.model  = model
        self.k      = history_window
        self.history: List[Dict[str, str]] = []

    def _messages(self, user_msg: str) -> List[Dict[str, str]]:
        msgs = [
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "system", "content": f"[WEBPAGE]\n\n{self.article}"},
            *self.history[-self.k*2:],
            {"role": "user", "content": user_msg},
        ]
        return msgs

    def chat(self, user_msg: str) -> str:
        resp = client.chat.completions.create(
            model=self.model,
            messages=self._messages(user_msg),
            temperature=0.1,  # Lower temperature for more factual, deterministic answers
        )
        assistant = resp.completion_message.content.text
        self.history.extend([
            {"role": "user", "content": user_msg},
            {"role": "assistant", "content": assistant},
        ])
        return assistant

Ejecutar el bucle de chat interactivo

Esta última parte del código inicia la sesión interactiva. Crea una instancia del bot PageChat y entra en un bucle, esperando tu entrada. Escribe "exit" o "quit" para finalizar la conversación.

bot = PageChat(article)
print("\n🤖  Ask me about the page!  Type 'exit' to quit.")
while True:
    try:
        user = input("\nYou: ").strip()
    except (EOFError, KeyboardInterrupt):
        break
    if user.lower() in {"exit", "quit"}:
        break
    if not user:
        continue
    answer = bot.chat(user)
    print(f"\nPageChat: {answer}")
🤖  Ask me about the page!  Type 'exit' to quit.
You:  Give me a 2 sentence summary
PageChat: Meta is releasing Llama 4 Scout and Llama 4 Maverick, two new multimodal AI models that offer state-of-the-art performance and are available for download on llama.com and Hugging Face. The models are part of the Llama 4 series, which also includes the larger Llama 4 Behemoth model that is still in training and has shown exceptional performance on various benchmarks.
You:  What is the difference between the Llama 4 Maverick and Llama 4 Scout models?
PageChat: Llama 4 Maverick and Llama 4 Scout are both 17 billion active parameter models, but they differ in the number of experts used in their mixture-of-experts (MoE) architecture: Llama 4 Maverick has 128 experts, while Llama 4 Scout has 16 experts. This difference affects their performance, with Llama 4 Maverick outperforming Llama 4 Scout and other models on various benchmarks, but also potentially requiring more resources.
You:  What is the max context length of the Llama 4 Scout model?
PageChat: The Llama 4 Scout model has a context window of 10 million tokens.
You:  What is the pricing of the Llama 4 Maverick model?
PageChat: The webpage does not mention the pricing of the Llama 4 Maverick model. It does mention that Llama 4 Maverick offers a "best-in-class performance to cost ratio", but the actual cost is not specified.
You:  When will the Behemoth model be released?
PageChat: The webpage does not provide a specific release date for the Llama 4 Behemoth model, stating only that it is "still training" and that more details will be shared "even while it's still in flight".
You:  exit

Consultas de ejemplo para probar:

  • "Dame un resumen de dos oraciones."
  • "¿Cuál es el precio?"
  • Seguimiento: "¿Cuáles son las 3 conclusiones principales?"

Extra: Resumir la conversación

Dado que estás almacenando el historial de conversación, puedes usar el modelo para realizar metatareas sobre él, como resumir el chat. Esto puede ser útil para el registro, el análisis o para proporcionar al usuario un resumen rápido de una interacción larga.

def summarize_conversation(bot: PageChat, max_tokens: int = 128) -> str:
    msgs = [
        {"role": "system", "content": "Summarize the chat in 3 concise bullets."},
        {"role": "user",   "content": "\n".join(m['content'] for m in bot.history)},
    ]
    resp = client.chat.completions.create(
        model=bot.model,
        messages=msgs,
        max_completion_tokens=max_tokens,
    )
    return resp.completion_message.content.text.strip()

print("\nChat so far:")
print(summarize_conversation(bot))
Chat so far:
Here is a 2-sentence summary:

Meta has released two new multimodal AI models, Llama 4 Scout and Llama 4 Maverick, which offer state-of-the-art performance and are available for download. The models are part of the Llama 4 series, which also includes the larger Llama 4 Behemoth model that is still in training and has no specified release date.

Próximos pasos y rutas de actualización

Este tutorial proporciona una base sólida, pero puedes extenderlo de varias maneras para una aplicación de nivel de producción.

Necesidad Dónde buscar
Páginas largas / múltiples documentos Para contenido más grande que la ventana de contexto, usa Generación Aumentada por Recuperación (RAG). Esto implica dividir documentos en fragmentos, almacenarlos en una base de datos vectorial y recuperar solo los fragmentos más relevantes para responder una pregunta. Consulta nuestro libro de cocina RAG de fragmentación contextual.
Memoria persistente Para sistemas de producción, podrías almacenar el historial de conversación en una base de datos.
Sensación en tiempo real Habilita stream=True para recibir la respuesta token por token, mejorando la latencia percibida. Consulta el ejemplo de streaming en la guía de Chat y conversación.
Datos y acciones en vivo Dale al chatbot acceso a datos en vivo o APIs externas usando Llamada a Herramientas. Consulta la guía completa de Llamada a Herramientas.
Lección del curso «Llama Cookbook (use cases)» de Meta, publicado con licencia MIT. Traducción y adaptación al español de IA con Clase. IA con Clase no está afiliado a Meta. Ver el original · Licencia
Esta lección es gratuita. El resto del curso se abre con la Membresía de IA con Clase, que incluye todos los cursos del catálogo. Ver precios