10.1 Introducción
En el tema anterior estudiamos las limitaciones generales de los modelos. Una de sus manifestaciones más conocidas es la alucinación: el sistema genera información que parece coherente dentro de la respuesta, pero no corresponde con la realidad disponible.
En programación, una alucinación puede ser un método inexistente, una opción de configuración inventada, una explicación falsa sobre el proyecto o la afirmación de que una prueba fue ejecutada cuando no existe evidencia de esa ejecución.
El problema no siempre se presenta como un error evidente. Con frecuencia, el código utiliza nombres razonables, respeta la sintaxis y resuelve el caso más simple. Esa apariencia puede llevarnos a incorporarlo sin comprobar lo que hace en situaciones reales.
10.2 Qué llamamos alucinación
Una alucinación ocurre cuando el modelo completa una respuesta con información no respaldada por el contexto, la documentación, el proyecto o una observación verificable. No implica intención de engañar: es una consecuencia posible del mecanismo de generación.
La IA intenta producir una continuación útil y consistente. Cuando la información es insuficiente, puede reconocer la incertidumbre, pedir contexto o construir una respuesta probable. El último comportamiento resulta peligroso si presenta la inferencia como un hecho.
Conviene distinguir tres situaciones:
- Error: existe información suficiente, pero la respuesta llega a una conclusión equivocada.
- Supuesto: el modelo completa un dato ausente para poder avanzar.
- Alucinación: presenta como real un elemento que no está respaldado o no existe.
En la práctica pueden aparecer juntas. Una dependencia inventada puede conducir a una implementación errónea construida sobre supuestos no declarados.
10.3 Por qué una alucinación resulta convincente
Los modelos aprendieron patrones presentes en grandes cantidades de texto y código. Por eso pueden crear nombres que siguen las convenciones de una biblioteca, aunque esa función específica nunca haya existido.
Una respuesta falsa puede parecer auténtica porque incluye:
- Nombres técnicos compatibles con el dominio.
- Parámetros semejantes a los utilizados por funciones reales.
- Comentarios que explican una intención razonable.
- Una estructura habitual para el lenguaje.
- Un ejemplo de uso coherente con la función inventada.
- Una explicación segura y sin señales explícitas de duda.
Las personas también completamos información cuando algo “suena bien”. La combinación entre una salida fluida y una revisión rápida favorece el error de aceptar por familiaridad.
10.4 Formas habituales de alucinación técnica
| Forma | Ejemplo | Cómo comprobarla |
|---|---|---|
| API inexistente | Invocar un método con nombre creíble que la biblioteca no ofrece. | Consultar documentación y ejecutar un ejemplo mínimo. |
| Paquete inventado | Recomendar una dependencia que no existe o no pertenece al autor indicado. | Buscarla en el registro oficial y revisar su procedencia. |
| Opción falsa | Agregar una propiedad de configuración que el programa ignora. | Comparar con el esquema o documentación de la versión usada. |
| Archivo supuesto | Afirmar que una función está definida en un archivo no inspeccionado. | Buscar el símbolo y abrir la ruta real. |
| Comportamiento inventado | Decir que una función valida datos cuando solo los transforma. | Leer la implementación y probar entradas representativas. |
| Ejecución no realizada | Asegurar que “todas las pruebas pasan” sin haber ejecutado el comando. | Solicitar o producir el registro real de la ejecución. |
La comprobación debe dirigirse al origen apropiado: el repositorio para el código propio, la documentación oficial para una API y la ejecución para el comportamiento.
10.5 Funciones y dependencias que no existen
Una biblioteca suele mantener una familia de nombres y conceptos. El modelo puede combinar esos patrones y generar una llamada perfectamente plausible.
const resultado = await cliente.buscarUsuarios({
texto: "Ana",
ignorarMayusculas: true,
coincidenciaAproximada: true
});
El fragmento es legible, pero no sabemos si buscarUsuarios existe, si acepta un objeto ni si reconoce esas opciones. Copiarlo obliga a responder varias preguntas:
- ¿Qué biblioteca y versión proporcionan
cliente? - ¿El método aparece en la documentación oficial?
- ¿Los parámetros tienen esos nombres y tipos?
- ¿Qué devuelve cuando no encuentra resultados?
- ¿La operación puede fallar y cómo informa el error?
Instalar un paquete desconocido solo porque fue sugerido agrega además un riesgo de seguridad. El nombre debe verificarse en el registro oficial, junto con su autoría, mantenimiento y necesidad real.
10.6 Código válido no significa código correcto
La sintaxis determina si el lenguaje puede interpretar una secuencia. La corrección depende de lo que el programa debería hacer. Entre ambos extremos existen varios niveles.
| Estado | Qué demuestra | Qué todavía no demuestra |
|---|---|---|
| Se puede interpretar | La sintaxis básica es válida. | Que las funciones utilizadas existan al ejecutar. |
| Se ejecuta | El flujo probado no produjo una excepción. | Que el resultado sea el esperado. |
| Pasa una prueba | Un caso coincide con una expectativa. | Que cubra límites y errores relevantes. |
| Cumple requisitos | Resuelve los casos definidos. | Que sea seguro, eficiente y mantenible. |
| Funciona en producción | Opera en un entorno real observado. | Que nunca fallará ante nuevas condiciones. |
10.7 Errores lógicos detrás de una buena apariencia
Observemos una función generada para aplicar un descuento del 10 % a compras de $100 o más:
function calcularTotal(total) {
if (total > 100) {
return total * 0.9;
}
return total;
}
El código es breve, válido y devuelve el resultado esperado para una compra de $150. Sin embargo, utiliza > en lugar de >=, por lo que no aplica el descuento exactamente en $100.
También quedan preguntas que la función no responde:
- ¿Qué ocurre con valores negativos?
- ¿Debe aceptar texto numérico?
- ¿Cómo se redondea el resultado?
- ¿La moneda admite decimales?
- ¿El porcentaje es fijo o configurable?
Una prueba del caso normal puede ocultar tanto el error del límite como los requisitos ausentes.
10.8 Casos felices y condiciones no consideradas
Los ejemplos generados suelen concentrarse en el camino ideal: datos presentes, red disponible, permisos correctos y respuesta exitosa. Las aplicaciones reales también reciben entradas vacías, operaciones repetidas y fallas parciales.
Para ampliar la revisión conviene considerar:
- Caso normal: la entrada más frecuente produce el resultado esperado.
- Límites: valores mínimos, máximos y exactamente iguales al umbral.
- Datos inválidos: tipos incorrectos, campos vacíos y formatos inesperados.
- Ausencia: recursos que no existen o respuestas sin resultados.
- Repetición: doble clic, reintento de una solicitud o evento duplicado.
- Concurrencia: dos personas modifican el mismo dato.
- Falla externa: demora, desconexión o error de un servicio.
No todos los proyectos necesitan la misma cobertura. Los casos se eligen según probabilidad, impacto y costo de recuperación.
10.9 Supuestos inventados sobre el proyecto
Una respuesta puede utilizar nombres reales del repositorio y aun así atribuirles relaciones falsas. Si la IA solo inspeccionó un controlador, podría afirmar que determinada tabla contiene un campo o que otra función realiza una validación.
Algunas expresiones requieren evidencia antes de aceptarlas:
- “El proyecto ya utiliza esta biblioteca”.
- “La autenticación se realiza en este archivo”.
- “Esta función solo se llama desde una pantalla”.
- “La base de datos garantiza que el valor sea único”.
- “No hay pruebas relacionadas con este comportamiento”.
Una búsqueda de archivos, referencias y configuración puede confirmar o refutar estas afirmaciones. Cuando la herramienta dispone de acceso, es preferible pedirle que investigue antes de inferir.
10.10 Explicaciones y evidencias fabricadas
La alucinación no se limita al código. También puede aparecer en el informe que acompaña una modificación. El sistema podría describir cambios no realizados, citar una prueba inexistente o interpretar de manera incorrecta la salida de un comando.
Una afirmación verificable debe estar vinculada con una evidencia:
| Afirmación | Evidencia adecuada |
|---|---|
| “La función fue modificada”. | Diferencia del archivo o contenido actual. |
| “Las pruebas pasan”. | Comando ejecutado, salida y código de finalización. |
| “La API admite esta opción”. | Documentación oficial de la versión utilizada. |
| “No existen otros usos”. | Búsqueda en el alcance completo del proyecto. |
| “El error quedó resuelto”. | Reproducción anterior y nueva ejecución exitosa. |
La evidencia no necesita ser extensa, pero sí debe corresponder directamente con la afirmación.
10.11 Código aparentemente seguro
Una solución puede validar algunos campos, utilizar nombres como sanitizar o autorizar y transmitir una falsa sensación de seguridad. El nombre de una función no prueba que implemente la protección necesaria.
Los errores de seguridad suelen depender del contexto:
- Validar en el navegador, pero confiar en datos sin validar en el servidor.
- Comprobar que una persona inició sesión, pero no que puede acceder al recurso solicitado.
- Ocultar un botón sin impedir la operación mediante la API.
- Cifrar una comunicación, pero exponer el secreto en registros.
- Escapar datos para HTML y reutilizarlos en una consulta con otras reglas.
En funciones relacionadas con identidad, permisos, pagos o datos sensibles, la revisión especializada y las pruebas de seguridad son indispensables.
10.12 Leer el código con preguntas concretas
Una lectura general puede quedarse en el estilo. Las preguntas obligan a conectar cada parte con su comportamiento:
- ¿Qué entrada recibe y quién puede controlarla?
- ¿Qué condiciones modifican el camino de ejecución?
- ¿Qué valores devuelve en éxito, ausencia y error?
- ¿Qué estado modifica y qué ocurre si la operación se repite?
- ¿Qué funciones externas invoca y qué contrato tienen?
- ¿Qué requisito demuestra cada bloque?
- ¿Qué supuesto no está representado en una validación o prueba?
Explicar el código con palabras propias es una buena comprobación. Si no podemos anticipar qué hará ante una entrada, todavía no estamos en condiciones de aprobarlo.
10.13 Una escalera de verificación
Las comprobaciones pueden ordenarse desde las más rápidas hasta las que reproducen con mayor fidelidad el uso real.
- Inspección: leer diferencias, nombres, dependencias y flujo.
- Análisis automático: aplicar formateador, analizador estático y comprobación de tipos.
- Prueba mínima: ejecutar la función o ejemplo que confirma que la API existe.
- Pruebas automatizadas: comprobar casos normales, límites y errores.
- Integración: verificar la interacción con archivos, base de datos o servicios.
- Prueba manual: recorrer el flujo desde la perspectiva de una persona usuaria.
- Observación: medir comportamiento en un entorno representativo.
No todos los cambios requieren llegar al último nivel. La profundidad debe corresponder al riesgo y al alcance de la modificación.
10.14 Instrucciones que reducen el riesgo
Ninguna frase elimina las alucinaciones, pero algunas instrucciones favorecen respuestas más verificables:
- “No supongas nombres de archivos: buscá primero dónde se implementa la función”.
- “Indicá qué información falta antes de elegir una biblioteca”.
- “Utilizá solamente las dependencias ya instaladas”.
- “Separá hechos observados de inferencias”.
- “Citá la documentación oficial correspondiente a esta versión”.
- “Mostrá el comando y el resultado de las pruebas ejecutadas”.
- “Enumerá casos que todavía no fueron comprobados”.
Pedir incertidumbre explícita es útil, pero no suficiente. Un modelo también puede mostrarse seguro sobre una respuesta falsa o expresar dudas sobre una correcta. La verificación debe ocurrir fuera de la redacción.
10.15 Flujo para aceptar código generado
Antes de incorporar una propuesta podemos aplicar un proceso breve y repetible:
- Relacionar el cambio con un requisito concreto.
- Revisar todos los archivos modificados y las dependencias nuevas.
- Confirmar en fuentes confiables las API desconocidas.
- Identificar supuestos y casos no cubiertos.
- Ejecutar las validaciones automáticas del proyecto.
- Agregar pruebas para el caso normal, los límites y los errores relevantes.
- Probar manualmente el comportamiento visible.
- Aceptar solo lo que podamos explicar y mantener.
Si una comprobación falla, no conviene pedir correcciones indefinidas sin revisar la causa. Debemos aportar el error real, reducir el caso y comprobar cada nueva hipótesis.
10.16 Actividad de comprensión
Retomá la función calcularTotal de la sección 10.7 y prepará una revisión como si hubiera sido propuesta por una IA para una tienda real.
- Escribí una especificación precisa del descuento.
- Identificá el error que aparece exactamente en el límite.
- Definí qué debería ocurrir con cero, valores negativos, decimales y entradas no numéricas.
- Prepará una tabla con entradas y resultados esperados.
- Corregí la función y explicá cada decisión tomada.
- Indicá qué pruebas demuestran el comportamiento y qué aspectos aún dependerían del sistema completo.
Como segunda parte, elegí una biblioteca que conozcas y buscá en un ejemplo generado una función, opción o comportamiento que necesite confirmación. Verificalo mediante documentación oficial y un ejemplo mínimo.