
Proyecto IA Monterroso (XXIV): que PINSAPA busque en Internet (sin decir tonterías)
Esta entrada empezó como una broma a medias — “flipante… ya va a ser mucho pedirte que PINSAPA busque cositas en internet” — y se convirtió en la funcionalidad que más idas y vueltas ha tenido hasta ahora. Con razón: es la primera vez que PINSAPA trae contenido de fuera del centro y de fuera de su propio conocimiento, y eso cambia las reglas del juego en seguridad.
La preocupación real, dicha sin rodeos
En cuanto se planteó la idea, la respuesta no fue “qué bien”, fue una duda concreta y acertada: “me podría devolver cualquier cosa, y podría ser porno o lo que sea”. Tenía toda la razón. Un “safe search” nunca garantiza al 100% que no aparezca contenido inapropiado en un centro con menores — depende de adivinar qué es “seguro” en todo internet, y eso no es una base sólida.
Primer diseño (después descartado): SerpApi y una lista de 7 dominios
La primera solución fue restringir la búsqueda a un puñado de dominios de confianza elegidos a mano (Wikipedia, RAE, BOE, Junta de Andalucía, Wikcionario, Vikidia, Wikilibros) usando SerpApi como proveedor de búsqueda (plan gratuito: 250 búsquedas al mes). Se implementó, se probó con red simulada (25 comprobaciones, 0 fallos) y se subió a producción.
Pero al pedir que se probara de verdad, la respuesta fue clara: “no quiero serpapi… quiero que lo haga en wikipedia limpio y ya está”. Y no le faltaba razón — depender de una cuenta externa, con un plan gratuito que hay que vigilar, para algo que las propias wikis ya ofrecen gratis y sin registro, era más complejidad de la necesaria. Se deshizo todo: fuera SERPAPI_KEY, fuera la lista de dominios, fuera la dependencia de un proveedor de pago.
La versión que se quedó: MediaWiki, directo, sin proveedor
Wikipedia (y cualquier wiki hecha con el mismo software, MediaWiki) tiene su propia API de búsqueda pública, gratuita, sin necesidad de clave ni de registrarse — confirmado en la documentación oficial de MediaWiki, que solo recomienda (no exige) identificar la aplicación con una cabecera User-Agent descriptiva. Una preocupación menos que mantener, y encima más sencillo de verdad, no solo de explicar.
def _buscar_en_wiki(nombre_fuente, url_api, consulta, limite=2):
try:
respuesta = requests.get(
url_api,
params={
"action": "query", "format": "json", "formatversion": 2,
"generator": "search", "gsrsearch": consulta, "gsrlimit": limite,
"gsrnamespace": 0, "prop": "extracts", "exintro": 1,
"explaintext": 1, "exsentences": 3, "redirects": 1,
},
headers=_CABECERAS_BUSQUEDA,
timeout=_TIMEOUT_BUSQUEDA_SEGUNDOS,
)
respuesta.raise_for_status()
paginas = respuesta.json().get("query", {}).get("pages") or []
except (requests.exceptions.RequestException, ValueError):
return []
...
Se añadió una segunda fuente, Vikidia — la misma tecnología, pero pensada explícitamente para lectores de 8 a 13 años. La idea era usarla como primera opción para reducir justo el riesgo de que Wikipedia (enciclopedia general, no curada para menores) devuelva algo poco adecuado para la edad. La lista de fuentes es, literalmente, una lista de dos líneas — cambiar el orden es mover esas dos líneas, nada más:
_FUENTES_BUSQUEDA = [
("Wikipedia", "https://es.wikipedia.org/w/api.php"),
("Vikidia", "https://es.vikidia.org/w/api.php"),
]
(El orden final —Wikipedia primero, Vikidia de respaldo— es a petición expresa, para probarlo así. Aviso pendiente: con este orden, Vikidia casi no llega a activarse, porque Wikipedia por sí sola casi siempre llena el cupo de resultados antes de que le toque turno.)
El primer fallo real: Vikidia devolvió un artículo sobre YouTube
Al probar “busca en internet qué es un algoritmo”, Vikidia no dijo “no tengo eso” — devolvió un artículo sobre YouTube, sin relación ninguna con la pregunta. El motivo: Vikidia es una wiki pequeña sin un motor de búsqueda potente detrás (Wikipedia sí tiene uno, con Elasticsearch; Vikidia no), así que cuando no tiene el tema, a veces devuelve el artículo que más se le parece por pura casualidad.
Y el modelo, al recibir esa basura, no dijo “no he encontrado nada relevante” (como se le pedía) — simplemente la ignoró en silencio y respondió con su propio conocimiento general, afirmando igualmente que se “basaba en la información disponible en Internet”. Una frase falsa, dicha con total naturalidad.
La solución no fue pedirle al modelo que fuera más listo — ya se ha visto en esta serie que un modelo de 3B no sigue esas instrucciones de forma fiable. La solución fue no dejarle llegar la basura en primer lugar: un filtro de relevancia en Python, antes de aceptar cualquier resultado.
def _resultado_es_relevante(consulta, titulo, extracto):
significativas = _palabras_significativas(consulta) # sin "qué", "es", "un"...
if not significativas:
return True
texto_normalizado = _normalizar_texto_busqueda(f"{titulo} {extracto}")
return any(palabra in texto_normalizado for palabra in significativas)
Si ninguna palabra con peso de la pregunta aparece ni en el título ni en el resumen devuelto, se descarta — como si esa wiki no hubiera encontrado nada. Sin tildes ni mayúsculas de por medio, para no fallar por una simple tilde.
Un segundo fallo, más sutil, y el aviso que pedía esta entrada
Con el filtro puesto, la prueba se repitió y esta vez sí funcionó: Wikipedia devolvió el extracto real de “Algoritmo”, y el modelo lo citó explícitamente (“Según Wikipedia…”), varias veces. El problema de la basura irrelevante está resuelto.
Pero apareció algo distinto, y hay que decirlo con la misma claridad que lo anterior: la respuesta añadió que “Al-Khwarizmi… desarrolló métodos para resolver ecuaciones cúbicas”. Eso es falso, y no viene del extracto que se le mandó (que solo hablaba de la definición general de algoritmo, sin mencionar ecuaciones cúbicas). Al-Khwarizmi es conocido por el álgebra de ecuaciones lineales y cuadráticas — las ecuaciones cúbicas se resolvieron siglos después. El modelo se inventó ese dato por su cuenta, encima de una cita real y bien hecha.
Aviso honesto para quien use esta función: que PINSAPA cite bien una fuente real no significa que todo lo que diga a continuación sea cierto. Un modelo de 3 mil millones de parámetros corriendo en un portátil sin GPU tiende a añadir “cultura general” propia sin que se le pida, y esa cultura general puede estar equivocada. Esto no es un fallo del código de búsqueda — es un límite del modelo, y no hay instrucción de prompt que lo garantice al 100%. Cualquier dato relevante que PINSAPA dé a partir de una búsqueda merece comprobarse antes de darlo por bueno, sobre todo si es un detalle concreto (una fecha, un nombre, una cifra) que no estaba literalmente en la cita.
Cómo se comprobó
En capas, como siempre en este proyecto: primero una batería de detección de frases (17 casos, positivos y negativos, 0 fallos). Después, con la red simulada: fuente que llena el cupo sin molestar a la otra, fuente que falla y la otra responde igual, las dos fallando a la vez sin romper nada, JSON corrupto en una sin bloquear la otra, tope de fragmentos respetado — y, tras el hallazgo real, el caso exacto de “algoritmo devuelve YouTube” convertido en prueba permanente, para que no vuelva a pasar sin que salte una comprobación. 26 comprobaciones en total, 0 fallos, antes de cada subida a ROCKY.
Y, la parte que no se puede simular: las pruebas reales en ROCKY, con internet de verdad, que fueron las que sacaron a la luz los dos fallos de esta entrada — el filtro de relevancia no habría nacido sin la prueba real de “qué es un algoritmo”, y el aviso sobre las ecuaciones cúbicas tampoco.
Se añadió además un registro en la consola del servidor ([busqueda] activada para... o ...no hubo resultados en ninguna wiki) para poder ver, sin adivinar, qué le llega de verdad al modelo en cada pregunta — sin esto, distinguir “no encontró nada” de “encontró algo bueno y lo ignoró” habría sido imposible solo mirando la respuesta final.
Instalación
Ningún paso nuevo. Sin variable de entorno, sin cuenta que crear, sin clave que guardar — la API de MediaWiki es pública. Solo reiniciar la API para cargar el código.
Cómo comprobarlo
Pedir “busca en internet [algo]” y mirar la consola de ROCKY: debería aparecer [busqueda] activada para... con un resumen real citando Wikipedia o Vikidia, o el aviso de que ninguna wiki tenía nada. Y, sobre todo, leer la respuesta con el mismo ojo crítico que cualquier fuente de internet: si cita bien pero añade un dato muy concreto que no estaba en el extracto, conviene comprobarlo aparte.
Qué queda pendiente
El límite de las “invenciones encima de una cita real” no tiene arreglo fácil con este modelo — queda documentado, no resuelto. El orden Wikipedia-primero deja a Vikidia casi sin uso; si con el tiempo eso pesa más que la comodidad de probarlo así, basta con volver a intercambiar el orden de la lista. Y sigue sin haber una forma de que el alumnado elija explícitamente “quiero que mire primero en la wiki para niños” — hoy es una decisión fija para todos, no una preferencia.




