Phase 05 - Lesson 17

Chatbots — De basados en reglas a neuronales a agentes de LLM

ELIZA respondía con coincidencia de patrones. DialogFlow mapeaba intenciones. GPT respondía a partir de los pesos. Claude ejecuta herramientas y verifica. Cada era resolvió la peor falla de la anterior.

Tipo: Aprender Lenguajes: Python Requisitos previos: Fase 5 · 13 (Question Answering), Fase 5 · 14 (Information Retrieval) Tiempo: ~75 minutos

El problema

Un usuario dice "Quiero cambiar mi vuelo." El sistema tiene que averiguar qué quiere, qué información falta, cómo obtenerla y cómo completar la acción. Luego el usuario dice "espera, ¿y si lo cancelo en su lugar?" y el sistema tiene que recordar el contexto, cambiar de tarea y preservar el estado.

La conversación es difícil para un sistema de ML. La entrada es abierta. La salida tiene que ser coherente a lo largo de muchos turnos. El sistema puede necesitar actuar sobre el mundo (cambiar un vuelo, cobrar una tarjeta). Cada paso equivocado es visible para el usuario.

Las arquitecturas de chatbot han pasado por cuatro paradigmas, cada uno introducido porque el anterior fallaba de forma demasiado visible. Esta lección los recorre en orden. El panorama de producción de 2026 es un híbrido de los dos últimos.

El concepto

Evolución de los chatbots: basado en reglas → recuperación → neuronal → agente

Basado en reglas (ELIZA, AIML, DialogFlow). Patrones escritos a mano coinciden con la entrada del usuario y producen respuestas. Los clasificadores de intención enrutan a flujos predefinidos. Las máquinas de estado de llenado de slots recopilan la información requerida. Funcionan de manera brillante dentro del alcance estrecho para el que fueron diseñadas. Fallan de inmediato fuera de él. Todavía se usan en dominios críticos de seguridad (autenticación bancaria, reserva de vuelos) donde la alucinación no se tolera.

Basado en recuperación. Un sistema al estilo de FAQ. Codifica cada par de (enunciado, respuesta). En tiempo de ejecución, codifica el mensaje del usuario y recupera la respuesta almacenada más cercana. Piensa en la clásica función de "artículos similares" de Zendesk. Maneja paráfrasis mejor que las reglas. Sin generación, así que sin alucinación.

Neuronal (seq2seq). Codificador-decodificador entrenado con registros de conversación. Genera respuestas desde cero. Fluido, pero propenso a salidas genéricas ("No sé") y deriva factual. Nunca se mantiene de forma confiable en el tema. La razón por la que Google, Facebook y Microsoft tuvieron chatbots decepcionantes en 2016-2019.

Agentes de LLM. Un modelo de lenguaje envuelto en un bucle que planifica, llama herramientas y verifica resultados. No es un chatbot con un prompt largo. Es un bucle de agente: planificar → llamar herramienta → observar resultado → decidir el siguiente paso. El anclaje que prioriza la recuperación (RAG) evita que alucine. Las llamadas a herramientas le permiten hacer cosas de verdad. Esta es la arquitectura de 2026.

Los cuatro paradigmas no son reemplazos secuenciales. Un chatbot de producción de 2026 enruta a través de los cuatro: basado en reglas para autenticación y acciones destructivas, recuperación para FAQ, generación neuronal para fraseo natural, agente de LLM para consultas ambiguas y abiertas.

Constrúyelo

Paso 1: coincidencia de patrones basada en reglas

import re


class RulePattern:
    def __init__(self, pattern, response_template):
        self.regex = re.compile(pattern, re.IGNORECASE)
        self.template = response_template


PATTERNS = [
    RulePattern(r"my name is (\w+)", "Nice to meet you, {0}."),
    RulePattern(r"i (need|want) (.+)", "Why do you {0} {1}?"),
    RulePattern(r"i feel (.+)", "Why do you feel {0}?"),
    RulePattern(r"(.*)", "Tell me more about that."),
]


def rule_based_respond(user_input):
    for pattern in PATTERNS:
        m = pattern.regex.match(user_input.strip())
        if m:
            return pattern.template.format(*m.groups())
    return "I don't understand."

ELIZA en 20 líneas. El truco del reflejo ("I feel sad" → "Why do you feel sad") es la demostración canónica del psicoterapeuta de Weizenbaum 1966. Sigue siendo instructivo.

Paso 2: basado en recuperación (FAQ)

Este fragmento ilustrativo requiere pip install sentence-transformers (que arrastra torch). El code/main.py ejecutable de esta lección usa, en su lugar, una similitud de Jaccard de la biblioteca estándar, de modo que la lección se ejecuta sin dependencias externas.

from sentence_transformers import SentenceTransformer
import numpy as np


FAQ = [
    ("how do i reset my password", "Go to Settings > Security > Reset Password."),
    ("how do i cancel my order", "Go to Orders, find the order, click Cancel."),
    ("what is your return policy", "30-day returns on unused items, original packaging."),
]


encoder = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
faq_questions = [q for q, _ in FAQ]
faq_embeddings = encoder.encode(faq_questions, normalize_embeddings=True)


def faq_respond(user_input, threshold=0.5):
    q_emb = encoder.encode([user_input], normalize_embeddings=True)[0]
    sims = faq_embeddings @ q_emb
    best = int(np.argmax(sims))
    if sims[best] < threshold:
        return None
    return FAQ[best][1]

El rechazo basado en umbral es la decisión de diseño clave. Si la mejor coincidencia no está lo bastante cerca, devuelve None y deja que el sistema escale.

Paso 3: generación neuronal (baseline)

Usa un pequeño codificador-decodificador ajustado por instrucción (FLAN-T5) o un modelo conversacional fine-tuned. Inutilizable en producción por sí solo en 2026 (contradicción, deriva fuera de tema, sinsentidos factuales), pero se usa dentro de sistemas híbridos para el fraseo natural. Los modelos solo-decodificador al estilo DialoGPT necesitan separadores de turno explícitos y manejo de EOS para producir respuestas coherentes; un pipeline text2text de FLAN-T5 funciona de inmediato para un ejemplo didáctico.

from transformers import pipeline

chatbot = pipeline("text2text-generation", model="google/flan-t5-small")

response = chatbot("Respond politely to: Hi there!", max_new_tokens=40)
print(response[0]["generated_text"])

Paso 4: bucle del agente de LLM

La forma de producción de 2026:

def agent_loop(user_message, tools, llm, max_steps=5):
    history = [{"role": "user", "content": user_message}]
    for _ in range(max_steps):
        response = llm(history, tools=tools)
        tool_call = response.get("tool_call")
        if tool_call:
            tool_name = tool_call.get("name")
            args = tool_call.get("arguments")
            if not isinstance(tool_name, str) or tool_name not in tools:
                history.append({"role": "assistant", "tool_call": tool_call})
                history.append({"role": "tool", "name": str(tool_name), "content": f"error: unknown tool {tool_name!r}"})
                continue
            if not isinstance(args, dict):
                history.append({"role": "assistant", "tool_call": tool_call})
                history.append({"role": "tool", "name": tool_name, "content": f"error: arguments must be a dict, got {type(args).__name__}"})
                continue
            result = tools[tool_name](**args)
            history.append({"role": "assistant", "tool_call": tool_call})
            history.append({"role": "tool", "name": tool_name, "content": result})
        else:
            return response["content"]
    return "I could not complete the task in the step budget."

Tres cosas que nombrar. Las herramientas son funciones invocables que el LLM puede llamar. El bucle termina cuando el LLM devuelve una respuesta final en lugar de una llamada a herramienta. El presupuesto de pasos evita bucles infinitos en tareas ambiguas.

La producción real añade: anclaje que prioriza la recuperación (inyectar documentos relevantes antes de cada llamada al LLM), guardrails (rechazar acciones destructivas sin confirmación), observabilidad (registrar cada paso) y evaluaciones (comprobaciones automatizadas de que el comportamiento del agente se mantiene dentro de la especificación).

Paso 5: enrutamiento híbrido

def hybrid_chat(user_input):
    if is_destructive_action(user_input):
        return structured_flow(user_input)

    faq_answer = faq_respond(user_input, threshold=0.6)
    if faq_answer:
        return faq_answer

    return agent_loop(user_input, tools, llm)


def is_destructive_action(text):
    danger_words = ["delete", "cancel", "charge", "refund", "transfer"]
    return any(w in text.lower() for w in danger_words)

El patrón: reglas deterministas para cualquier cosa destructiva, recuperación para FAQs preparadas, agentes de LLM para todo lo demás. Esto es lo que se lleva a producción en los sistemas de atención al cliente de 2026.

Úsalo

El stack de 2026:

Caso de uso Arquitectura
Reserva, pago, autenticación Máquinas de estado basadas en reglas + llenado de slots
FAQs de atención al cliente Recuperación sobre respuestas curadas
Chat de ayuda abierto Agente de LLM con RAG + llamadas a herramientas
Herramientas internas / asistentes de IDE Agente de LLM con llamadas a herramientas (buscar, leer, escribir)
Chatbots de compañía / personaje LLM ajustado con prompt de sistema de persona, recuperación sobre el conocimiento

Usa siempre enrutamiento híbrido en producción. Ninguna arquitectura por sí sola maneja bien cada solicitud. La propia capa de enrutamiento suele ser un pequeño clasificador de intención.

Modos de falla que aún llegan a producción

  • Fabricación confiada. El agente de LLM afirma haber completado una acción que no completó. Mitigación: verificar resultados, registrar llamadas a herramientas, nunca dejar que el LLM afirme haber hecho algo sin un retorno de herramienta exitoso.

  • Inyección de prompt. El usuario inserta texto que sobrescribe el prompt de sistema. Clasificada como LLM01 en el OWASP Top 10 for LLM Applications 2025. Dos sabores: inyección directa (pegada en el chat) e inyección indirecta (oculta en documentos, correos o salidas de herramientas que el agente lee).

    Las tasas de ataque varían según el escenario. Las tasas de éxito medidas van de ~0,5-8,5% entre modelos de frontera en benchmarks generales de uso de herramientas y de programación. Configuraciones específicas de alto riesgo (ataques adaptativos contra agentes de programación de IA, orquestación vulnerable) han alcanzado ~84%. Los CVEs de producción incluyen EchoLeak (CVE-2025-32711, CVSS 9.3) — una falla de exfiltración de datos zero-click en Microsoft 365 Copilot activada por un correo controlado por el atacante.

    Mitigaciones: tratar la entrada del usuario como no confiable a lo largo de todo el bucle; sanitizar antes de las llamadas a herramientas; aislar las salidas de herramientas del prompt principal; usar el patrón Plan-Verify-Execute (PVE) en el que el agente planifica primero, luego verifica cada acción contra ese plan antes de ejecutar (esto evita que los resultados de herramientas inyecten nuevas acciones no planificadas); exigir confirmación del usuario para acciones destructivas; aplicar privilegio mínimo a los alcances de las herramientas.

    Ninguna cantidad de ingeniería de prompts elimina por completo este riesgo. Se requieren capas externas de defensa en tiempo de ejecución (LLM Guard, validación por allowlist, detección de anomalías semánticas).

  • Desviación de alcance. El agente se sale de la tarea porque una llamada a herramienta devolvió información tangencialmente relacionada. Mitigación: contratos de herramienta estrechos; mantener el prompt de sistema enfocado; añadir evaluaciones para la tasa de desviación de tarea.

  • Bucles infinitos. El agente sigue llamando a la misma herramienta. Mitigación: presupuesto de pasos, deduplicación de llamadas a herramientas, juez LLM sobre "¿estamos progresando?".

  • Agotamiento de la ventana de contexto. Las conversaciones largas empujan los turnos más antiguos fuera del contexto. Mitigación: resumir los turnos antiguos, recuperar turnos pasados relevantes por similitud, o usar un modelo de contexto largo.

Entrégalo

Guarda como outputs/skill-chatbot-architect.md:

---
name: chatbot-architect
description: Design a chatbot stack for a given use case.
version: 1.0.0
phase: 5
lesson: 17
tags: [nlp, agents, chatbot]
---

Given a product context (user need, compliance constraints, available tools, data volume), output:

1. Architecture. Rule-based, retrieval, neural, LLM agent, or hybrid (specify which paths go where).
2. LLM choice if applicable. Name the model family (Claude, GPT-4, Llama-3.1, Mixtral). Match to tool-use quality and cost.
3. Grounding strategy. RAG sources, retrieval method (see lesson 14), tool contracts.
4. Evaluation plan. Task success rate, tool-call correctness, off-task rate, hallucination rate on held-out dialogs.

Refuse to recommend a pure-LLM agent for any destructive action (payments, account deletion, data modification) without a structured confirmation flow. Refuse to skip the prompt-injection audit if the agent has write access to anything.

Ejercicios

  1. Fácil. Implementa el respond basado en reglas de arriba con 10 patrones para un bot de pedidos de una cafetería. Prueba casos límite: pedidos duplicados, modificaciones, cancelación, intención poco clara.
  2. Medio. Construye un híbrido de FAQ + fallback de LLM. 50 entradas de FAQ preparadas para un producto SaaS, fallback de LLM con recuperación sobre el sitio de documentación. Mide la tasa de rechazo y la exactitud en 100 preguntas reales de soporte.
  3. Difícil. Implementa el bucle del agente de arriba con tres herramientas (buscar, leer-datos-de-usuario, enviar-correo). Ejecuta una evaluación con 50 escenarios de prueba, incluidos intentos de inyección de prompt. Reporta la tasa de desviación de tarea, la tasa de tareas fallidas y cualquier éxito de inyección.

Términos clave

Término Lo que la gente dice Lo que realmente significa
Intención Lo que el usuario quiere Etiqueta categórica (book_flight, reset_password). Se enruta a un handler.
Slot Una pieza de información Parámetro que el bot necesita (fecha, destino). El llenado de slots es la secuencia de preguntas.
RAG Recuperación más generación Recuperar documentos relevantes, luego anclar la respuesta del LLM.
Llamada a herramienta Invocación de función El LLM emite una llamada estructurada con nombre + args. El runtime ejecuta, devuelve el resultado.
Bucle del agente Planificar, actuar, verificar Controlador que ejecuta llamadas al LLM intercaladas con llamadas a herramientas hasta que la tarea termina.
Inyección de prompt El usuario ataca el prompt Entrada maliciosa que intenta sobrescribir el prompt de sistema.

Lectura adicional

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).