
Proyecto PINSAPIA: El Adivino de la Siguiente Palabra (Línea Lamarr)
📌 Ficha Técnica y Metadatos
- Slug:
pinsapia-linea-lamarr-adivino-siguiente-palabra-montesteam - Extract: Explora cómo generan texto los modelos de lenguaje en «El adivino de la siguiente palabra», una aplicación interactiva del Proyecto PINSAPIA (Línea Lamarr) desarrollada en el IES Monterroso dentro de los marcos MonteSTEAM y AIDARAC. Mediante peticiones autorregresivas (
max_tokens=1ylogprobs) sobre FastAPI en el puerto 8084, el alumnado visualiza paso a paso el ranking de probabilidad de las palabras candidatas, comprendiendo en directo el origen real de la temperatura, la creatividad y las alucinaciones en los LLM. - Palabras clave:
aidarac,montesteam,ies monterroso,proyecto pinsapia,linea lamarr,hedy lamarr,logprobs,generacion autorregresiva,fastapi,ia en el aula,pensamiento computacional,alfabetizacion de ia,recursos steam,top-5 tokens
1. Hedy Lamarr y la visión paso a paso de los modelos de lenguaje
Hedy Lamarr (1914–2000) no solo fue una estrella legendaria de Hollywood, sino también una inventora autodidacta excepcional. Durante la Segunda Guerra Mundial, junto al compositor George Antheil, patentó un sistema de comunicación secreta por salto de frecuencia inspirado en los rollos de las pianolas. Su idea revolucionaria consistió en descomponer una señal continua en múltiples fragmentos probabilísticos e impredecibles que cambiaban de canal constantemente, sentando las bases del Wi-Fi, el Bluetooth y la telefonía móvil moderna.
Su importancia en el contexto de la Inteligencia Artificial
En el “termómetro de la creatividad”, el alumnado comprueba que variar la temperatura de una IA modifica drásticamente el resultado de un texto. En esta actividad abrimos la caja negra para ver exactamente por qué ocurre esto.
Un Gran Modelo de Lenguaje (LLM) no piensa la frase entera antes de escribirla. No tiene un plan argumental completo por delante. Al igual que los saltos de frecuencia de Hedy Lamarr, la IA avanza de forma discreta y autorregresiva: en cada instante evalúa todo su vocabulario, calcula una lista de palabras candidatas con sus respectivas probabilidades estadístico-matemáticas y elige una.
Traer a Hedy Lamarr al aula permite desmitificar la idea de que la IA “piensa” o “siente” como un ser humano, demostrando que su aparente fluidez es el resultado de elegir paso a paso lo que estadísticamente “suena mejor a continuación”.
2. Guía de Instalación y Código Fuente (app_lamarr.py)
Requisitos previos e instalación de dependencias
Abre la terminal de tu sistema e instala los paquetes de Python necesarios:
Bash
pip install fastapi "uvicorn[standard]" httpx pydantic
Código Completo del Servidor (app_lamarr.py)
Guarda el siguiente código en un archivo llamado app_lamarr.py:
Python
import time
import math
import re
from typing import List, Dict, Any, Optional
from fastapi import FastAPI, HTTPException
from fastapi.responses import HTMLResponse
from pydantic import BaseModel
import httpx
app = FastAPI(
title="Proyecto PINSAPIA - Línea Lamarr: El Adivino de la Siguiente Palabra",
description="Explorador de predicción autorregresiva de tokens y probabilidades logprobs en tiempo real."
)
LM_STUDIO_API_URL = "http://localhost:1234/v1/chat/completions"
MODEL_NAME = "local-model" # Nombre genérico para LM Studio
# -----------------------------------------------------------------------------
# 1. EJEMPLOS PRECONFIGURADOS
# -----------------------------------------------------------------------------
PREDEFINED_PROMPTS = [
{
"id": "mercado",
"label": "1. 🛒 Cotidiano",
"text": "Ayer fui al",
"desc": "Completa un destino común en la rutina diaria."
},
{
"id": "receta",
"label": "2. 🍳 Gastronomía",
"text": "El secreto de la receta es",
"desc": "Busca un ingrediente o cualidad culinaria."
},
{
"id": "quijote",
"label": "3. 📖 Literatura",
"text": "En un lugar de la",
"desc": "Clásico inicio literario para probar memoria de patrones."
},
{
"id": "futuro",
"label": "4. 🤖 Tecnología",
"text": "El futuro de la inteligencia artificial es",
"desc": "Explora sesgos sobre visiones de futuro."
},
{
"id": "cuento",
"label": "5. 🌲 Cuento",
"text": "Había una vez un perro que vivía en",
"desc": "Inicio narrativo para construcciones creativas."
}
]
# -----------------------------------------------------------------------------
# 2. GENERADOR DE CANDIDATAS HEURÍSTICAS (FALLBACK DE CONTINGENCIA)
# -----------------------------------------------------------------------------
def generate_fallback_candidates(prompt_text: str) -> List[Dict[str, Any]]:
"""
Genera candidatas contextuales verosímiles en caso de que LM Studio
no esté activo o no tenga activado el parámetro logprobs.
"""
text_lower = prompt_text.strip().lower()
if text_lower.endswith("ayer fui al") or text_lower.endswith("fui al"):
raw = [("mercado", 34.5), ("parque", 22.1), ("cine", 17.8), ("médico", 13.2), ("colegio", 12.4)]
elif "receta" in text_lower:
raw = [("amor", 31.0), ("tiempo", 24.5), ("fuego", 18.2), ("sabor", 15.1), ("orden", 11.2)]
elif "lugar de la" in text_lower:
raw = [("Mancha", 82.0), ("ciudad", 8.5), ("costa", 4.2), ("tierra", 3.1), ("casa", 2.2)]
elif "inteligencia artificial" in text_lower:
raw = [("prometedor", 29.4), ("incierto", 24.1), ("fascinante", 20.3), ("humano", 14.8), ("clave", 11.4)]
else:
words = re.findall(r'\w+', text_lower)
last_word = words[-1] if words else "inicio"
seed = sum(ord(c) for c in last_word)
candidates = ["grande", "nuevo", "sol", "mundo", "camino", "mismo", "primer", "tiempo", "lugar", "siguiente"]
start_idx = seed % 5
selected = candidates[start_idx:start_idx+5]
probs = [38.0, 24.0, 16.0, 12.0, 10.0]
raw = list(zip(selected, probs))
return [
{"token": word, "probability": prob, "logprob": math.log(prob / 100.0)}
for word, prob in raw
]
# -----------------------------------------------------------------------------
# 3. ENDPOINT API: OBTENER TOP-5 SIGUIENTE TOKEN
# -----------------------------------------------------------------------------
class PredictRequest(BaseModel):
prompt: str
@app.post("/api/predict_next")
async def predict_next_token(req: PredictRequest):
prompt_text = req.prompt.strip()
if not prompt_text:
raise HTTPException(status_code=400, detail="El texto acumulado no puede estar vacío.")
start_time = time.perf_counter()
used_fallback = False
candidates: List[Dict[str, Any]] = []
payload = {
"model": MODEL_NAME,
"messages": [
{"role": "user", "content": f"Continúa la frase de forma natural. Frase: {prompt_text}"}
],
"max_tokens": 1,
"temperature": 1.0,
"logprobs": True,
"top_logprobs": 5
}
try:
async with httpx.AsyncClient() as client:
res = await client.post(LM_STUDIO_API_URL, json=payload, timeout=4.0)
if res.status_code == 200:
data = res.json()
choice = data["choices"][0]
if "logprobs" in choice and choice["logprobs"] and "content" in choice["logprobs"]:
top_list = choice["logprobs"]["content"][0]["top_logprobs"]
raw_probs = []
for item in top_list:
lp = item.get("logprob", -5.0)
prob_raw = math.exp(lp)
token_str = item.get("token", "").replace("Ġ", " ").replace(" ", " ")
raw_probs.append((token_str, prob_raw, lp))
total_prob = sum(p[1] for p in raw_probs) or 1.0
for tok, p_raw, lp in raw_probs:
norm_p = round((p_raw / total_prob) * 100, 2)
candidates.append({
"token": tok.strip(),
"probability": norm_p,
"logprob": round(lp, 3)
})
except Exception:
pass
if not candidates:
candidates = generate_fallback_candidates(prompt_text)
used_fallback = True
candidates = sorted(candidates, key=lambda x: x["probability"], reverse=True)
elapsed_ms = round((time.perf_counter() - start_time) * 1000, 2)
return {
"prompt": prompt_text,
"candidates": candidates,
"used_fallback": used_fallback,
"latency_ms": elapsed_ms
}
# -----------------------------------------------------------------------------
# 4. INTERFAZ WEB HTML
# -----------------------------------------------------------------------------
@app.get("/", response_class=HTMLResponse)
async def home():
return f"""
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Proyecto PINSAPIA - Línea Lamarr</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap');
body {{ font-family: 'Inter', sans-serif; background-color: #f1f5f9; }}
.pinsapia-topbar {{ background-color: #080d1a; }}
.pinsapia-header-card {{ background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%); }}
.btn-pinsapia {{ background-color: #0284c7; transition: all 0.2s ease; }}
.btn-pinsapia:hover {{ background-color: #0369a1; transform: translateY(-1px); }}
</style>
</head>
<body class="min-h-screen text-slate-800 flex flex-col">
<header class="pinsapia-topbar text-white px-4 py-2.5 flex flex-wrap justify-between items-center text-xs sm:text-sm shadow-md border-b border-slate-800">
<div class="flex items-center space-x-2 font-bold tracking-wide">
<span class="bg-cyan-500 text-black px-2 py-0.5 rounded font-extrabold text-sm uppercase tracking-wider">PINSAPIA</span>
<span class="text-white text-sm font-semibold tracking-wider">PROYECTO LAMARR</span>
<span class="bg-orange-600 text-white text-[10px] px-1.5 py-0.5 rounded font-mono font-bold ml-1">PUERTO :8084</span>
</div>
<div class="flex items-center space-x-2 mt-1 sm:mt-0">
<span class="bg-sky-600/30 text-sky-300 border border-sky-500/40 text-[11px] px-2.5 py-0.5 rounded-full font-medium">
IES MONTERROSO — LÍNEA LAMARR
</span>
</div>
</header>
<main class="max-w-6xl w-full mx-auto p-3 sm:p-6 space-y-6 flex-grow">
<div class="pinsapia-header-card rounded-xl p-5 text-white shadow-lg border border-slate-700/50 flex justify-between items-center">
<div>
<p class="text-cyan-400 font-bold text-xs uppercase tracking-widest mb-1">
Generación Autorregresiva y Distribución de Probabilidades
</p>
<h1 class="text-xl sm:text-2xl font-extrabold tracking-tight">
El Adivino de la Siguiente Palabra (Logprobs Top-5)
</h1>
</div>
<div class="text-3xl sm:text-4xl text-cyan-400 pl-4">
<i class="fa-solid fa-wand-magic-sparkles"></i>
</div>
</div>
<section class="bg-white rounded-xl shadow-sm border border-slate-200 p-5 space-y-4">
<div class="flex items-center space-x-2 font-bold text-slate-800 text-sm sm:text-base border-b border-slate-100 pb-2">
<span class="text-rose-500"><i class="fa-solid fa-thumbtack"></i></span>
<h2>1. INTRODUCE O SELECCIONA EL INICIO DE LA FRASE</h2>
</div>
<div class="bg-slate-50 border border-slate-200 rounded-lg p-3.5 space-y-3">
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-1">
<label class="text-xs font-bold text-slate-700 uppercase tracking-wider">
Ejemplos preconfigurados para clase:
</label>
<span class="text-[11px] text-slate-500">Haz clic en un ejemplo para cargarlo en el cuadro de texto</span>
</div>
<div class="flex flex-wrap gap-2" id="predefinedContainer"></div>
</div>
<div class="space-y-2">
<div class="flex justify-between items-center">
<label for="promptInput" class="block text-xs font-semibold text-slate-600">
Texto acumulado para la predicción:
</label>
<button onclick="reiniciarTexto()" class="text-xs text-rose-600 hover:text-rose-800 font-bold flex items-center gap-1">
<i class="fa-solid fa-rotate-left"></i> Reiniciar
</button>
</div>
<textarea id="promptInput" rows="3" class="w-full p-3 border border-slate-300 rounded-lg text-sm sm:text-base font-semibold text-slate-800 outline-none focus:ring-2 focus:ring-sky-500 transition shadow-inner" placeholder="Escribe el inicio de una frase aquí..."></textarea>
</div>
<button id="btnPredict" onclick="obtenerPrediccion()" class="w-full btn-pinsapia text-white font-bold py-3 px-4 rounded-lg shadow flex items-center justify-center space-x-2 text-sm sm:text-base">
<span>🔍</span>
<span>CALCULAR TOP-5 PALABRAS MÁS PROBABLES (MAX_TOKENS = 1)</span>
</button>
</section>
<section class="bg-slate-900 text-slate-200 rounded-xl shadow-md p-5 border border-slate-700 space-y-4">
<div class="flex items-center space-x-2 text-cyan-400 font-bold text-sm sm:text-base border-b border-slate-800 pb-2">
<i class="fa-solid fa-circle-info"></i>
<h2>¿QUÉ HACE EL BOTÓN Y CÓMO FUNCIONAN LOS ALGORITMOS AUTORREGRESIVOS?</h2>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-xs leading-relaxed">
<div class="bg-slate-800/80 p-3.5 rounded-lg border border-slate-700 space-y-2">
<div class="flex items-center space-x-2 text-amber-400 font-bold">
<i class="fa-solid fa-cubes"></i>
<span class="uppercase">1. Generación Token a Token (Sin Plan Previo)</span>
</div>
<p class="text-slate-300">
<strong>¿Qué hace?:</strong> Envía el texto acumulado solicitando únicamente <code>max_tokens: 1</code> junto a la lista de probabilidades (<code>logprobs</code>).
</p>
<ul class="list-disc pl-4 space-y-1 text-slate-300">
<li>El modelo no "sabe" cómo terminará la frase cuando empieza a escribirla.</li>
<li>En cada paso evalúa todo su vocabulario y asigna un porcentaje de probabilidad a cada opción.</li>
</ul>
</div>
<div class="bg-slate-800/80 p-3.5 rounded-lg border border-slate-700 space-y-2">
<div class="flex items-center space-x-2 text-sky-400 font-bold">
<i class="fa-solid fa-brain"></i>
<span class="uppercase">2. ¿Por qué el modelo "alucina" o se contradice?</span>
</div>
<p class="text-slate-300">
<strong>¿Qué hace?:</strong> Demuestra que la IA elige verosimilitud probabilística en lugar de verdad factual.
</p>
<ul class="list-disc pl-4 space-y-1 text-slate-300">
<li>Si eliges la opción más probable, la frase será "conservadora" (temperatura baja).</li>
<li>Si eliges opciones del final del ranking, la frase se volverá "arriesgada" o incoherente (temperatura alta).</li>
</ul>
</div>
</div>
</section>
<section id="sectionResults" class="bg-white rounded-xl shadow-sm border border-slate-200 p-5 space-y-4 hidden">
<div class="flex items-center justify-between border-b border-slate-100 pb-2">
<div class="flex items-center space-x-2 font-bold text-slate-800 text-sm sm:text-base">
<span class="text-emerald-600"><i class="fa-solid fa-list-ol"></i></span>
<h2>2. CANDIDATAS PREDICHAS PARA CONTINUAR LA FRASE</h2>
</div>
<span id="badgeMetrics" class="text-[11px] font-mono bg-slate-100 border border-slate-200 text-slate-600 px-2 py-0.5 rounded"></span>
</div>
<p class="text-xs text-slate-600 font-medium">
Haz clic en el botón <strong class="text-sky-700">"➕ Añadir"</strong> de cualquiera de las 5 palabras para agregarla al texto y volver a calcular el siguiente paso:
</p>
<div id="candidatesContainer" class="space-y-3"></div>
</section>
<section class="bg-white rounded-xl shadow-sm border border-slate-200 p-5 space-y-3">
<div class="flex items-center space-x-2 text-slate-800 font-bold text-sm border-b border-slate-100 pb-2">
<span class="text-sky-600"><i class="fa-solid fa-lightbulb"></i></span>
<h2>CIERRE Y REFLEXIÓN EN GRUPO (LÍNEA LAMARR)</h2>
</div>
<div class="text-xs text-slate-600 space-y-2 leading-relaxed">
<p>
<strong>Hedy Lamarr</strong> demostró que la transmisión de información requiere sincronización precisa entre emisor y receptor a través de saltos continuos de frecuencia. Del mismo modo, los modelos de lenguaje funcionan mediante "saltos probabilísticos" palabra a palabra.
</p>
<ul class="list-disc pl-5 space-y-1 text-slate-700">
<li><strong>Pregunta clave:</strong> Si en cada paso el modelo solo mira <em>"qué palabra suena bien ahora"</em>, ¿cómo es posible que pueda escribir una historia coherente de principio a fin?</li>
<li>¿Qué ocurre con la coherencia cuando elegimos deliberadamente las opciones con menor probabilidad del ranking?</li>
</ul>
</div>
</section>
</main>
<script>
const predefinedPrompts = {PREDEFINED_PROMPTS};
function initPredefined() {{
const container = document.getElementById('predefinedContainer');
container.innerHTML = predefinedPrompts.map(p => `
<button onclick="cargarEjemplo('${{p.id}}')" class="px-2.5 py-1 text-xs bg-slate-100 hover:bg-sky-100 text-slate-700 hover:text-sky-800 border border-slate-200 rounded font-medium transition text-left">
${{p.label}}: <span class="font-bold">"${{p.text}}..."</span>
</button>
`).join('');
}}
function cargarEjemplo(id) {{
const item = predefinedPrompts.find(x => x.id === id);
if (item) {{
document.getElementById('promptInput').value = item.text;
ocultarResultados();
}}
}}
function reiniciarTexto() {{
document.getElementById('promptInput').value = "";
ocultarResultados();
}}
function ocultarResultados() {{
document.getElementById('sectionResults').classList.add('hidden');
}}
async function obtenerPrediccion() {{
const promptText = document.getElementById('promptInput').value.trim();
if (!promptText) {{
alert("Por favor escribe o selecciona una frase de inicio.");
return;
}}
const btn = document.getElementById('btnPredict');
btn.disabled = true;
btn.innerHTML = '<span>⏳</span><span>Consultando probabilidades logprobs...</span>';
try {{
const res = await fetch('/api/predict_next', {{
method: 'POST',
headers: {{ 'Content-Type': 'application/json' }},
body: JSON.stringify({{ prompt: promptText }})
}});
const data = await res.json();
document.getElementById('sectionResults').classList.remove('hidden');
const mode = data.used_fallback ? " [Modo Fallback Heurístico]" : " [LM Studio Logprobs]";
document.getElementById('badgeMetrics').innerText = `Tiempo: ${{data.latency_ms}} ms${{mode}}`;
const container = document.getElementById('candidatesContainer');
container.innerHTML = data.candidates.map((c, idx) => {{
const isTop1 = idx === 0;
const isLast = idx === data.candidates.length - 1;
const barBg = isTop1 ? "bg-emerald-500" : (isLast ? "bg-amber-500" : "bg-sky-500");
const badgeText = isTop1 ? `<span class="bg-emerald-100 text-emerald-800 text-[10px] font-extrabold px-2 py-0.5 rounded">MÁS PROBABLE (CONSERVADORA)</span>` : (isLast ? `<span class="bg-amber-100 text-amber-800 text-[10px] font-extrabold px-2 py-0.5 rounded">MÁS ARRIESGADA</span>` : "");
const safeToken = c.token.replace(/'/g, "\\'");
return `
<div class="p-3.5 bg-slate-50 border border-slate-200 rounded-lg space-y-2 hover:border-sky-300 transition">
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2">
<div class="flex items-center space-x-2">
<span class="text-base font-extrabold text-slate-800">"${{c.token}}"</span>
${{badgeText}}
</div>
<div class="flex items-center space-x-3">
<span class="font-mono text-sky-700 text-sm font-extrabold">${{c.probability}}% Probabilidad</span>
<button onclick="seleccionarPalabra('${{safeToken}}')" class="btn-pinsapia text-white text-xs font-bold px-3 py-1.5 rounded shadow flex items-center gap-1">
<i class="fa-solid fa-plus"></i> Añadir
</button>
</div>
</div>
<div class="w-full bg-slate-200 rounded-full h-2.5 overflow-hidden">
<div class="${{barBg}} h-2.5 rounded-full transition-all duration-500" style="width: ${{Math.max(3, c.probability)}}%"></div>
</div>
</div>
`;
}}).join('');
document.getElementById('sectionResults').scrollIntoView({{ behavior: 'smooth' }});
}} catch (e) {{
alert("Error obteniendo predicción: " + e);
}} finally {{
btn.disabled = false;
btn.innerHTML = '<span>🔍</span><span>CALCULAR TOP-5 PALABRAS MÁS PROBABLES (MAX_TOKENS = 1)</span>';
}}
}}
function seleccionarPalabra(palabra) {{
const input = document.getElementById('promptInput');
let actual = input.value.trim();
input.value = actual + " " + palabra;
obtenerPrediccion();
}}
window.onload = function() {{
initPredefined();
document.getElementById('promptInput').value = "Ayer fui al";
}};
</script>
</body>
</html>
"""
# -----------------------------------------------------------------------------
# 5. EJECUCIÓN DEL SERVIDOR UVICORN (PUERTO 8084)
# -----------------------------------------------------------------------------
if __name__ == "__main__":
import uvicorn
uvicorn.run("app_lamarr:app", host="0.0.0.0", port=8084, reload=True)
Cómo ejecutar la aplicación con Uvicorn en el puerto 8084
Abre tu consola de comandos en la carpeta donde guardaste app_lamarr.py y lanza el servidor con:
Bash
uvicorn app_lamarr:app --host 0.0.0.0 --port 8084 --reload
O bien ejecutando directamente con Python:
Bash
python app_lamarr.py
Accede desde tu navegador en http://localhost:8084 (o desde los equipos de la red escolar usando la IP local del servidor).
3. Detalle Técnico e Ingeniería del Prompt
Cuando se pide una respuesta completa a un servidor como LM Studio, la API hace este ciclo de forma automática y repetida hasta terminar. Aquí interrumpimos la cadena pidiendo expresamente:
max_tokens: 1: Fuerza al modelo a detenerse tras generar un solo token.logprobs: Trueytop_logprobs: 5: Solicita las probabilidades de las 5 palabras o tokens candidatas más probables en esa posición específica.
Matiz técnico sobre Tokens vs. Palabras
Lo que el modelo predice no son siempre palabras completas, sino tokens (fragmentos de palabra o sílabas). Para mantener la fluidez en el aula, la app limpia los marcadores de espacio (como Ġ o ) de forma transparente. Si ocasionalmente aparece un fragmento a mitad de palabra, basta con explicar al alumnado que los modelos leen en “subpalabras” para optimizar su memoria.
4. Guía Didáctica para el Alumnado: ¿Cómo se juega?
[Paso 1: Escribir Inicio] ──> [Paso 2: Calcular Top-5] ──> [Paso 3: Elegir Candidata] ──> [Paso 4: Repetir]
"Ayer fui al..." Ver porcentajes Añadir a la frase Construir historia
Dinámica paso a paso para el aula
- Paso 1 (Inicio de frase): Escriben un detonante como
"Ayer fui al..."o"El secreto de la receta es..."(o eligen uno de los botones preconfigurados). - Paso 2 (Consultar candidatas): Pulsan “CALCULAR TOP-5 PALABRAS MÁS PROBABLES”. La app muestra el ranking de las 5 alternativas con sus barras de porcentaje (por ejemplo: “mercado” 34%, “parque” 21%, “cine” 18%, “médico” 12%, “colegio” 9%).
- Paso 3 (Seleccionar y ampliar): Hacen clic en “➕ Añadir” en una de las 5 opciones. La palabra se suma al texto acumulado y la app recalcula automáticamente las siguientes 5 opciones sobre la frase ya alargada.
- Paso 4 (Trabajo en equipo):
- Equipo Conservador (Temperatura Baja): Elige siempre la palabra #1 (la más probable).
- Equipo Arriesgado (Temperatura Alta): Elige deliberadamente las palabras del final de la lista (#4 o #5).


5. Preguntas de Cierre y Debate en Grupo
Al finalizar la construcción de 2 o 3 frases completas por equipo, leed ambos textos en voz alta y plantead las siguientes preguntas de reflexión:
- Comprensión global: Si en cada paso el modelo solo mira “qué palabra suena bien ahora”, ¿cómo es posible que logre redactar una historia con cierta coherencia?
- Origen de las alucinaciones: ¿Por qué un modelo se contradice a mitad de una respuesta larga o inventa datos falsos con total convicción? (Respuesta: porque en cada paso elige lo más verosímil estadísticamente, no lo verdadero).
- Pérdida de coherencia: ¿Qué ocurrió cuando el equipo arriesgado eligió siempre las opciones con menor porcentaje del ranking?




