<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: lu1tr0n</title>
    <description>The latest articles on DEV Community by lu1tr0n (@lu1tr0n).</description>
    <link>https://dev.to/lu1tr0n</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F806044%2F070ecfe6-05a6-44e1-95e3-81211fc13ab4.png</url>
      <title>DEV Community: lu1tr0n</title>
      <link>https://dev.to/lu1tr0n</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lu1tr0n"/>
    <language>en</language>
    <item>
      <title>GrapheneOS: por qué hardened_malloc ralentiza algunas apps</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Mon, 28 Sep 2026 20:45:23 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/grapheneos-por-que-hardenedmalloc-ralentiza-algunas-apps-2888</link>
      <guid>https://dev.to/lu1tr0n/grapheneos-por-que-hardenedmalloc-ralentiza-algunas-apps-2888</guid>
      <description>&lt;p&gt;Un usuario de GrapheneOS en un Pixel 8 llevaba un año con el sistema cuando notó algo raro: Osmand, su app de mapas, corría notablemente más lento que en cualquier otro Android. No era un bug de la app: era una de las capas del &lt;strong&gt;sandboxing de GrapheneOS&lt;/strong&gt; revisando cada asignación de memoria antes de entregarla.&lt;/p&gt;

&lt;p&gt;Esa anécdota puntual es solo la punta del ovillo. GrapheneOS envuelve cada app en capas de aislamiento (memoria, almacenamiento, red y Google Play) y cada capa cobra un costo en rendimiento. Entender ese modelo, no el caso de una app lenta, es lo que permite decidir cuándo vale la pena pagarlo.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;El sandboxing de GrapheneOS suma hardened malloc, Storage Scopes y permiso de Internet, con costo en rendimiento.- Osmand corre más lento en GrapheneOS porque hardened malloc revisa cada asignación de memoria del mapa.- Storage Scopes limita qué carpetas ve cada app sin otorgar el permiso completo de almacenamiento.- Sandboxed Google Play corre sin privilegios de sistema y traduce llamadas vía una capa de compatibilidad.- Desactivar la protección de memoria por app recupera velocidad a cambio de menos hardening.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué es el sandboxing de GrapheneOS?
&lt;/h2&gt;

&lt;p&gt;El sandboxing de GrapheneOS es el conjunto de mecanismos de aislamiento que este sistema operativo basado en Android añade sobre el sandbox estándar de cada app: un asignador de memoria endurecido, permisos granulares de almacenamiento e Internet, y una versión sin privilegios de Google Play Services.&lt;/p&gt;

&lt;p&gt;Su objetivo es reducir la superficie de ataque de cada aplicación instalada, sin depender de que el desarrollador haya escrito código perfecto. Cada capa funciona de forma independiente: podés desactivar una sin tocar las demás, y eso es clave para el resto de este artículo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué importa
&lt;/h2&gt;

&lt;p&gt;La mayoría de los sistemas operativos móviles confían en que las apps se comporten bien. Android estándar ya sandboxea cada app con su propio UID de Linux, pero GrapheneOS agrega capas adicionales pensadas para el peor escenario: una app maliciosa, comprometida o simplemente con un bug explotable.&lt;/p&gt;

&lt;p&gt;Eso importa porque el modelo de amenazas de un teléfono cambió. Ya no alcanza con revisar permisos al instalar una app: un exploit de día cero en una librería de imágenes o de mapas puede ejecutar código arbitrario sin que el usuario haga nada. Las protecciones de memoria de GrapheneOS, como &lt;a href="https://github.com/GrapheneOS/hardened_malloc" rel="noopener noreferrer"&gt;hardened_malloc&lt;/a&gt;, existen para que ese exploit falle antes de lograr control sobre el proceso.&lt;/p&gt;

&lt;p&gt;El costo de eso es real y es el tema central de este artículo: cada verificación extra consume ciclos de CPU. En apps con patrones de uso de memoria intensivos, como un renderizador de mapas que carga y descarta miles de tiles por minuto, ese costo se nota. La decisión de fondo no es seguridad sí o no, sino cuánta seguridad necesita cada app puntual.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo funciona la arquitectura de permisos de GrapheneOS
&lt;/h2&gt;

&lt;p&gt;El aislamiento no es una sola función: son cuatro mecanismos separados que cualquier usuario puede activar o desactivar por app, desde la pantalla de información de cada aplicación.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storage Scopes: menos que el permiso de almacenamiento completo
&lt;/h3&gt;

&lt;p&gt;Android normal ofrece dos opciones para el almacenamiento: acceso completo o nada. Storage Scopes agrega un punto intermedio: cuando una app pide acceso a archivos, GrapheneOS puede mostrarle solo una carpeta específica en lugar de toda la memoria del teléfono. La app funciona como si esa carpeta fuera el único almacenamiento que existe.&lt;/p&gt;

&lt;p&gt;Esto reduce el daño si una app maliciosa intenta leer fotos, documentos o backups de otras apps: aunque tenga el permiso concedido, solo ve lo que el scope le permite ver.&lt;/p&gt;

&lt;h3&gt;
  
  
  Permiso de Internet por app: cortar la red sin desinstalar
&lt;/h3&gt;

&lt;p&gt;GrapheneOS agrega un permiso adicional de Internet que no existe como tal en Android estándar. Al desactivarlo para una app, el sistema le corta el acceso a sockets de red a nivel del kernel: la app sigue instalada y funciona con datos locales, pero no puede conectarse a internet ni siquiera si su código lo intenta.&lt;/p&gt;

&lt;p&gt;Es útil para apps que no necesitan estar en línea (una calculadora, un editor de fotos local) y que, si están comprometidas, no deberían poder exfiltrar nada.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sandboxed Google Play: los servicios de Google sin privilegios de sistema
&lt;/h3&gt;

&lt;p&gt;En Android estándar, Google Play Services corre con privilegios elevados: puede acceder a datos y permisos que ninguna otra app tiene. GrapheneOS instala Google Play como una app normal, sandboxeada igual que cualquier otra, y agrega una capa de compatibilidad que traduce las llamadas que las apps hacen esperando encontrar el Play Services privilegiado del sistema.&lt;/p&gt;

&lt;p&gt;El resultado es que la mayoría de las apps que dependen de Google Play (notificaciones push, mapas, inicio de sesión) funcionan igual, pero Google Play ya no tiene una posición privilegiada para vigilar el resto del teléfono.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hardened malloc: la capa que más se nota en rendimiento
&lt;/h3&gt;

&lt;p&gt;La cuarta capa es la que generó la anécdota que abre este artículo. GrapheneOS reemplaza el asignador de memoria estándar de Android por &lt;a href="https://github.com/GrapheneOS/hardened_malloc" rel="noopener noreferrer"&gt;hardened_malloc&lt;/a&gt;, un allocator diseñado para detectar corrupciones de memoria (use-after-free, overflows de heap) antes de que un atacante pueda explotarlas.&lt;/p&gt;

&lt;p&gt;Por defecto corre en todas las apps del sistema. Pero GrapheneOS permite, por app, sumar una capa extra de protección de memoria todavía más estricta, en Ajustes de la app &amp;gt; Exploit protection. Esa capa extra es exactamente la que &lt;a href="https://blog.wirelessmoves.com/2026/09/grapheneos-when-an-app-is-slow.html" rel="noopener noreferrer"&gt;un usuario reportó&lt;/a&gt; que ralentizaba Osmand en su Pixel 8.&lt;br&gt;
CapaQué controlaCosto en rendimientoSe ajusta por apphardened_malloc (modo estricto)Cada asignación y liberación de memoriaNotable en apps con muchas asignaciones (mapas, juegos)Sí, en Exploit protectionStorage ScopesQué carpetas ve una app con permiso de almacenamientoMínimoSí, se define el scope por appPermiso de InternetSi el proceso puede abrir sockets a internetNinguno si está permitidoSí, permiso Internet en info de la appSandboxed Google PlayPrivilegios del framework de Google PlayLatencia extra en llamadas traducidas por la capa de compatibilidadNo de forma individual&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"App instalada en GrapheneOS"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Sandbox de Android: proceso con UID propio"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Storage Scopes: ve solo una carpeta, no todo el almacenamiento"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Permiso de Internet: puede bloquear sockets a internet"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Sandboxed Google Play: sin privilegios de sistema"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hardened_malloc: valida cada asignación de memoria"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GrapheneOS reemplaza el Play Services privilegiado por una versión sandboxeada, sin acceso especial al resto del sistema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ejemplos prácticos: cuando el sandboxing de GrapheneOS se nota
&lt;/h2&gt;

&lt;p&gt;El caso documentado en el blog &lt;a href="https://blog.wirelessmoves.com/2026/09/grapheneos-when-an-app-is-slow.html" rel="noopener noreferrer"&gt;WirelessMoves&lt;/a&gt; es el ejemplo más claro. Osmand, la app de mapas basada en OpenStreetMap, dibuja el mapa cargando y descartando constantemente datos de tiles a medida que el usuario hace scroll o zoom. Cada uno de esos tiles pasa por una asignación de memoria, y con la protección activada, cada asignación pasa por las verificaciones extra de &lt;strong&gt;hardened_malloc&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;sequenceDiagram&lt;/span&gt;
&lt;span class="nv"&gt;participant&lt;/span&gt; &lt;span class="nv"&gt;App&lt;/span&gt; &lt;span class="nv"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;Osmand&lt;/span&gt;
&lt;span class="nv"&gt;participant&lt;/span&gt; &lt;span class="nv"&gt;Mem&lt;/span&gt; &lt;span class="nv"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;hardened_malloc&lt;/span&gt;
&lt;span class="nv"&gt;App&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;Mem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;pide&lt;/span&gt; &lt;span class="nv"&gt;memoria&lt;/span&gt; &lt;span class="nv"&gt;para&lt;/span&gt; &lt;span class="nv"&gt;un&lt;/span&gt; &lt;span class="nv"&gt;tile&lt;/span&gt; &lt;span class="nv"&gt;del&lt;/span&gt; &lt;span class="nv"&gt;mapa&lt;/span&gt;
&lt;span class="nv"&gt;Mem&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;Mem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;agrega&lt;/span&gt; &lt;span class="nv"&gt;guard&lt;/span&gt; &lt;span class="nv"&gt;pages&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="nv"&gt;verifica&lt;/span&gt; &lt;span class="nv"&gt;el&lt;/span&gt; &lt;span class="nv"&gt;tama&lt;/span&gt;&lt;span class="err"&gt;ñ&lt;/span&gt;&lt;span class="nv"&gt;o&lt;/span&gt;
&lt;span class="nv"&gt;Mem&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;App&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;entrega&lt;/span&gt; &lt;span class="nv"&gt;el&lt;/span&gt; &lt;span class="nv"&gt;bloque&lt;/span&gt; &lt;span class="nv"&gt;de&lt;/span&gt; &lt;span class="nv"&gt;memoria&lt;/span&gt; &lt;span class="nv"&gt;validado&lt;/span&gt;
&lt;span class="nv"&gt;Note&lt;/span&gt; &lt;span class="nv"&gt;over&lt;/span&gt; &lt;span class="nv"&gt;App&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;Mem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;el&lt;/span&gt; &lt;span class="nv"&gt;ciclo&lt;/span&gt; &lt;span class="nv"&gt;se&lt;/span&gt; &lt;span class="nv"&gt;repite&lt;/span&gt; &lt;span class="nv"&gt;miles&lt;/span&gt; &lt;span class="nv"&gt;de&lt;/span&gt; &lt;span class="nv"&gt;veces&lt;/span&gt; &lt;span class="nv"&gt;al&lt;/span&gt; &lt;span class="nv"&gt;hacer&lt;/span&gt; &lt;span class="nv"&gt;scroll&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El usuario que reportó el caso resolvió el problema desde Ajustes: mantuvo presionado el ícono de Osmand, entró a Info de la app, bajó hasta Exploit protection y desactivó específicamente el hardened memory allocator, dejando las demás protecciones activas. Después de reiniciar Osmand, la app volvió a sentirse tan rápida como en cualquier otro Android.&lt;/p&gt;

&lt;p&gt;Un comentario en el mismo blog agrega otro caso: Waze consumiendo batería de forma notable en un Pixel 10a con GrapheneOS mientras corría en Android Auto, con el teléfono calentándose. Es el mismo patrón: una app con uso intensivo de CPU y memoria que se topa con capas de verificación adicionales, esta vez con impacto en consumo energético en vez de en fluidez visual.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; desactivar el hardened memory allocator para una app específica reduce su protección contra explotación de bugs de memoria en esa app puntual. No afecta al resto del sistema, pero sí a esa app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Casos de uso reales
&lt;/h2&gt;

&lt;p&gt;No todos los perfiles de usuario necesitan la misma configuración. Un periodista o activista que maneja información sensible en países con vigilancia estatal se beneficia de dejar todas las protecciones activas, incluso si eso significa que el navegador o el cliente de mensajería corren un poco más lento: el costo en velocidad es bajo comparado con el riesgo de un exploit exitoso.&lt;/p&gt;

&lt;p&gt;Un usuario que solo quiere privacidad razonable frente al tracking publicitario, pero usa apps con mapas, edición de fotos o juegos con motores gráficos pesados, gana más ajustando caso por caso: deja Storage Scopes y el permiso de Internet activos siempre (tienen costo casi nulo), y reserva la desactivación del hardened memory allocator para las dos o tres apps que de verdad lo necesitan.&lt;/p&gt;

&lt;p&gt;Para desarrolladores que prueban sus propias apps en GrapheneOS antes de publicarlas, el aislamiento sirve como banco de pruebas: si una app se rompe con Storage Scopes activado, probablemente esté asumiendo acceso total al almacenamiento en lugar de pedir archivos puntuales, algo que Android también empezó a restringir con &lt;a href="https://developer.android.com/about/versions/11/privacy/storage" rel="noopener noreferrer"&gt;Scoped Storage&lt;/a&gt; desde Android 11.&lt;/p&gt;

&lt;h2&gt;
  
  
  Errores comunes y buenas prácticas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Desactivar todas las protecciones de golpe:&lt;/strong&gt; apagar el hardened memory allocator para todas las apps en lugar de solo la app lenta anula gran parte del valor de instalar GrapheneOS en primer lugar.- &lt;strong&gt;Confundir el permiso de Internet con un firewall completo:&lt;/strong&gt; bloquea sockets salientes de la app, pero no reemplaza un firewall a nivel de sistema ni filtra por dominio o dirección IP.- &lt;strong&gt;Asumir que Sandboxed Google Play es igual a no tener Google Play:&lt;/strong&gt; sigue siendo el mismo código de Google corriendo en el teléfono, solo que sin privilegios de sistema. Si te preocupa el tracking de Google en sí, la alternativa es no instalar Play en absoluto.- &lt;strong&gt;No revisar qué scope le diste a cada app:&lt;/strong&gt; con el tiempo se acumulan apps con acceso a carpetas que ya no necesitan; conviene revisar Storage Scopes periódicamente igual que revisarías permisos de cámara o micrófono.- &lt;strong&gt;Diagnosticar mal una app lenta:&lt;/strong&gt; antes de asumir que es un bug de la app, probá desactivar puntualmente el hardened memory allocator para esa app y compará. Si el problema desaparece, ya sabés la causa.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparativa con alternativas
&lt;/h2&gt;

&lt;p&gt;GrapheneOS no es la única opción para quien busca más control que un Android de fábrica. La diferencia está en cuánta profundidad de aislamiento agrega cada proyecto y qué tan lejos llega con Google Play.&lt;br&gt;
SistemaSandboxing de appsGoogle PlayCuándo convieneAndroid de fábrica (Pixel, Samsung)Sandbox estándar de AOSP, sin capas extraCon privilegios de sistemaPriorizás compatibilidad total sobre hardening adicionalGrapheneOShardened_malloc, Storage Scopes, permiso de Internet, Play sandboxeadoOpcional, corre como app normalPriorizás resistencia a exploits y control granular por appLineageOSSandbox estándar de AOSP más controles de privacidad propios de LineageOSVía microG o Play sin sandboxearBuscás libertad de ROM sin migrar el hardening completo de GrapheneOSCalyxOSToma como base parte del trabajo de hardened_malloc de GrapheneOSMicroG por defecto, Play opcionalQuerés privacidad similar con una configuración inicial más guiada&lt;br&gt;
La disyuntiva real no es si usar GrapheneOS o no, sino cuánto aislamiento granular necesitás controlar vos mismo. LineageOS y CalyxOS toman decisiones más automáticas y menos configurables; GrapheneOS te da el dial de cada capa, con la contrapartida de que también sos vos quien tiene que ajustarlo cuando una app se pone lenta.&lt;br&gt;
hardened_malloc separa las asignaciones por tamaño y agrega guard pages para frenar corrupciones de memoria antes de que un exploit las use.&lt;/p&gt;
&lt;h2&gt;
  
  
  Profundizando: qué hace hardened_malloc por dentro
&lt;/h2&gt;

&lt;p&gt;El allocator de memoria estándar de la mayoría de los sistemas (basado en variantes de dlmalloc o jemalloc) prioriza velocidad: reutiliza bloques de memoria liberados lo antes posible y no verifica mucho más allá de que el puntero exista. Eso deja abierta una familia entera de bugs explotables: use-after-free, double-free y overflows de heap que escriben más allá del bloque asignado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/GrapheneOS/hardened_malloc" rel="noopener noreferrer"&gt;hardened_malloc&lt;/a&gt;, el proyecto que GrapheneOS mantiene, ataca esos bugs con varias técnicas combinadas: separa las asignaciones por tamaño en regiones distintas para evitar que un overflow pequeño corrompa metadata de otra asignación, agrega guard pages alrededor de asignaciones grandes que hacen que un desborde provoque un crash inmediato en lugar de una corrupción silenciosa, y pone en cuarentena la memoria liberada durante un tiempo antes de reutilizarla, para que un use-after-free tenga más chances de fallar de forma visible en vez de ejecutar código atacante.&lt;/p&gt;

&lt;p&gt;En los Pixel 8 y modelos posteriores, GrapheneOS además puede apoyarse en Memory Tagging Extension (MTE), una función del hardware ARM que etiqueta cada bloque de memoria con un tag de unos pocos bits y verifica en cada acceso que el puntero use el tag correcto. Es la misma familia de protección que hardened_malloc implementa en software, pero resuelta en silicio, con menos costo en CPU que la versión puramente por software.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"App pide memoria"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hardened_malloc separa por tamaño de asignación"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Agrega guard pages alrededor del bloque"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Si hay MTE en el chip, etiqueta el bloque con un tag de hardware"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Cada acceso verifica el tag antes de leer o escribir"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"¿El tag no coincide?"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;F&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"Sí"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;G&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"El proceso crashea de forma controlada"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;F&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;|&lt;/span&gt;&lt;span class="s2"&gt;"No"&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;H&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"El acceso continúa con normalidad"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esa es la razón técnica de por qué el impacto en rendimiento no es uniforme: un teléfono con MTE paga menos costo por esta protección que uno sin ese hardware, y una app que hace pocas asignaciones grandes (un lector de PDF) lo nota mucho menos que una que hace miles de asignaciones pequeñas por segundo (un renderizador de mapas o un motor de juego).&lt;/p&gt;

&lt;p&gt;No hay una forma directa de medir desde afuera cuánto overhead agrega hardened_malloc a una app puntual sin herramientas de profiling nativas de Android; la forma práctica de comprobarlo es la que usó el reportante original: desactivar la protección extra para esa app y comparar la fluidez antes y después.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/GrapheneOS-por-qu%C3%A9-hardened-malloc-ralentiza-algunas-apps-09-28" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tu próximo paso: entrá a Ajustes &amp;gt; Apps, elegí la app que sospechás más lenta, abrí Exploit protection y desactivá solo el hardened memory allocator para compararla contra su comportamiento actual.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿El permiso de Internet de GrapheneOS bloquea wifi y datos móviles por igual?
&lt;/h3&gt;

&lt;p&gt;Sí. El permiso de Internet de GrapheneOS corta el acceso a sockets a nivel de sistema, sin importar si la conexión es wifi, datos móviles o VPN. Si la app no tiene el permiso, no puede abrir ninguna conexión saliente por ningún medio.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo sé si el hardened memory allocator está haciendo más lenta una app puntual?
&lt;/h3&gt;

&lt;p&gt;Desactivalo temporalmente para esa app en Ajustes de la app &amp;gt; Exploit protection y compará. Si la fluidez mejora de forma notoria, como en el caso de Osmand documentado por &lt;a href="https://blog.wirelessmoves.com/2026/09/grapheneos-when-an-app-is-slow.html" rel="noopener noreferrer"&gt;WirelessMoves&lt;/a&gt;, ya identificaste la causa.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Sandboxed Google Play necesita privilegios de sistema en GrapheneOS?
&lt;/h3&gt;

&lt;p&gt;No. A diferencia de Android de fábrica, GrapheneOS instala Google Play Services como una app sandboxeada más, sin acceso privilegiado al resto del sistema, y usa una capa de compatibilidad para responder a las llamadas que las apps esperan de un Play Services con privilegios.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Puedo desactivar hardened_malloc para una sola app en GrapheneOS?
&lt;/h3&gt;

&lt;p&gt;Podés desactivar la capa extra de protección de memoria, el hardened memory allocator, por app desde Exploit protection. El nivel base de hardened_malloc sigue activo en todo el sistema; lo que se apaga es el modo más estricto para esa app puntual.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Storage Scopes reemplaza los permisos de almacenamiento de Android?
&lt;/h3&gt;

&lt;p&gt;Los complementa. Storage Scopes se activa cuando una app ya tiene permiso de almacenamiento concedido, y restringe ese permiso a una carpeta específica en lugar de dejarlo abierto a todo el dispositivo.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿GrapheneOS funciona en cualquier teléfono?
&lt;/h3&gt;

&lt;p&gt;No: solo es compatible oficialmente con teléfonos Google Pixel, porque depende de funciones de seguridad del hardware de esa línea, como el verified boot y, en los modelos recientes, Memory Tagging Extension, que otros fabricantes no exponen de la misma forma.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://blog.wirelessmoves.com/2026/09/grapheneos-when-an-app-is-slow.html" rel="noopener noreferrer"&gt;WirelessMoves&lt;/a&gt;: el post original que documenta el caso de Osmand corriendo lento en GrapheneOS y cómo desactivar el hardened memory allocator lo soluciona.- &lt;a href="https://grapheneos.org/features" rel="noopener noreferrer"&gt;GrapheneOS Features&lt;/a&gt;: documentación oficial de Storage Scopes, el permiso de Internet por app y Sandboxed Google Play.- &lt;a href="https://github.com/GrapheneOS/hardened_malloc" rel="noopener noreferrer"&gt;GrapheneOS/hardened_malloc en GitHub&lt;/a&gt;: código fuente y documentación técnica del asignador de memoria endurecido.- &lt;a href="https://developer.android.com/about/versions/11/privacy/storage" rel="noopener noreferrer"&gt;Android Developers: Scoped Storage&lt;/a&gt;: documentación oficial de Google sobre las restricciones de almacenamiento que Android introdujo desde la versión 11.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>android</category>
      <category>ios</category>
      <category>programming</category>
    </item>
    <item>
      <title>NPR traza 4 bandos en el debate sobre riesgos de la IA</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Mon, 28 Sep 2026 16:27:52 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/npr-traza-4-bandos-en-el-debate-sobre-riesgos-de-la-ia-1kod</link>
      <guid>https://dev.to/lu1tr0n/npr-traza-4-bandos-en-el-debate-sobre-riesgos-de-la-ia-1kod</guid>
      <description>&lt;p&gt;El 26 de septiembre de 2026, &lt;a href="https://www.npr.org/2026/09/26/nx-s1-5979085/the-ai-safety-debate-is-confusing-heres-our-guide-to-the-different-factions" rel="noopener noreferrer"&gt;NPR publicó una guía&lt;/a&gt; para ordenar algo que hasta ahora sonaba como ruido de fondo, el debate sobre riesgos de la IA. La nota agrupa a investigadores, empresas y legisladores en posturas que casi nunca comparten micrófono y explica por qué cada una usa un vocabulario distinto para hablar del mismo problema.&lt;/p&gt;

&lt;p&gt;Tres días antes, el representante demócrata Ted Lieu le dijo a Politico que esos riesgos \"ya no pertenecen al terreno de la ciencia ficción\". Las dos piezas, juntas, dibujan el mapa de un terreno que hasta hace poco discutían solo especialistas.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;NPR publicó el 26 de septiembre de 2026 una guía que ordena el debate sobre riesgos de la IA en distintas posturas.- El representante Ted Lieu declaró a Politico que esos riesgos ya no pertenecen a la ciencia ficción, el 23 de septiembre.- Investigadores como Geoffrey Hinton dejaron cargos corporativos para advertir públicamente sobre la IA avanzada.- Universidades como Stanford discuten en paralelo cómo aplicar la IA a la ciencia sin ignorar sus riesgos.- La disputa enfrenta a quienes priorizan un riesgo existencial contra quienes señalan daños ya medibles hoy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué es el debate sobre riesgos de la IA
&lt;/h2&gt;

&lt;p&gt;El debate sobre riesgos de la IA es la discusión pública y académica sobre cuánto daño puede causar la inteligencia artificial avanzada, quién debe vigilarla y a qué velocidad conviene desarrollarla. Enfrenta a investigadores, empresas y legisladores agrupados en posturas que van del riesgo existencial a los daños ya medibles hoy.&lt;/p&gt;

&lt;p&gt;Esta discusión no es nueva. Circula desde que los laboratorios de IA empezaron a publicar sistemas capaces de escribir código, generar texto persuasivo y tomar decisiones con poca supervisión humana. Lo que cambió en 2026 es la cantidad de actores con poder real, desde congresistas hasta universidades, que ya se sienten obligados a tomar una posición pública.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué pasó
&lt;/h2&gt;

&lt;p&gt;La guía de NPR no inventa un nuevo escándalo: ordena uno que ya estaba ahí, el de los riesgos de la IA que preocupan a partes muy distintas del sector. Durante meses, medios, laboratorios y oficinas legislativas hablaron de eso como si fuera una sola conversación, cuando en realidad son varias discusiones distintas que comparten vocabulario y casi nada más.&lt;/p&gt;

&lt;p&gt;Politico documentó una de esas voces el 23 de septiembre: Ted Lieu, congresista y uno de los pocos legisladores estadounidenses con formación técnica, sostuvo que la &lt;strong&gt;controversia sobre la IA&lt;/strong&gt; dejó de ser hipotética. Tres días después, NPR amplió el panorama mostrando que ese tipo de alarma convive con posturas opuestas dentro del mismo sector tecnológico.&lt;/p&gt;

&lt;p&gt;Para ordenar el terreno, conviene separar a los actores por lo que cada uno prioriza y por el tipo de política pública que defienden:&lt;br&gt;
PosturaQué priorizaEjemplo de argumentoPostura sobre regulaciónRiesgo existencialSistemas futuros mucho más capaces que los actualesUn modelo mal alineado podría perseguir objetivos distintos a los previstos por sus creadoresPausas, auditorías obligatorias y control de cómputoDaños actualesSesgo, vigilancia y desplazamiento laboral ya mediblesLos sistemas de hoy ya discriminan y automatizan decisiones sin supervisión adecuadaTransparencia, responsabilidad legal y auditorías de datosAceleracionismoVelocidad de despliegue y competitividad económicaFrenar el desarrollo solo le da ventaja a competidores menos cuidadososRegulación mínima o nulaRegulación institucionalReglas verificables antes de un despliegue masivoSin licencias ni supervisión no hay forma de rendir cuentas si algo fallaLicencias, reportes obligatorios y agencias dedicadasEl debate sobre riesgos de la IA mezcla a investigadores, empresas y legisladores en el mismo escenario.&lt;/p&gt;
&lt;h2&gt;
  
  
  Contexto e historia
&lt;/h2&gt;

&lt;p&gt;La preocupación por la seguridad de la inteligencia artificial no nació en 2026. Ya en 2023, un grupo de investigadores e ingenieros de peso firmó una declaración pública para advertir que mitigar el riesgo de extinción asociado a la IA debía ser una prioridad global, al mismo nivel que otros riesgos de escala social, como las pandemias o una guerra nuclear.&lt;/p&gt;

&lt;p&gt;Ese mismo año, &lt;a href="https://en.wikipedia.org/wiki/Geoffrey_Hinton" rel="noopener noreferrer"&gt;Geoffrey Hinton dejó su cargo en Google&lt;/a&gt; para poder hablar con libertad sobre los peligros de sistemas cada vez más capaces, un gesto que la prensa tecnológica interpretó como un parteaguas: uno de los padres del aprendizaje profundo dejaba de defender la tecnología que ayudó a crear para empezar a advertir sobre ella.&lt;/p&gt;

&lt;p&gt;En paralelo, otra corriente insistía en que el problema no era un escenario futuro sino el presente. Investigadoras dedicadas a la ética de la IA venían señalando desde antes que los sistemas de reconocimiento facial, los modelos de lenguaje y los algoritmos de contratación ya producían sesgos y decisiones injustas, sin necesidad de imaginar una inteligencia superior. Esa tensión, entre lo hipotético y lo comprobable, quedó instalada como la primera gran grieta del debate.&lt;/p&gt;

&lt;p&gt;Una tercera corriente respondió con una lectura opuesta: que el verdadero riesgo era frenar el desarrollo y perder terreno frente a otros países o empresas menos cautelosos. Ese argumento, más cercano al mundo del capital de riesgo que al de los laboratorios de investigación, ganó fuerza a medida que la competencia entre modelos abiertos y cerrados se volvió una carrera de costos y velocidad de lanzamiento.&lt;/p&gt;
&lt;h2&gt;
  
  
  Detalles técnicos
&lt;/h2&gt;

&lt;p&gt;Lo que distingue a cada postura no es solo la conclusión política a la que llega, sino el mecanismo técnico en el que apoya su argumento. La corriente del riesgo existencial se apoya en dos ideas de la investigación en alineación: la &lt;strong&gt;mala especificación de recompensa&lt;/strong&gt;, cuando un sistema optimiza literalmente el objetivo que se le dio en vez de la intención detrás de ese objetivo, y la &lt;strong&gt;convergencia instrumental&lt;/strong&gt;, la idea de que casi cualquier objetivo complejo favorece subobjetivos como adquirir más recursos o evitar ser apagado.&lt;/p&gt;

&lt;p&gt;La corriente de los daños actuales no necesita ese razonamiento hipotético porque trabaja con evidencia empírica disponible hoy: conjuntos de datos de entrenamiento que sobrerrepresentan a ciertos grupos, modelos de contratación automatizada que heredan sesgos históricos y sistemas de vigilancia que se despliegan sin auditoría pública. El mecanismo aquí es estadístico, no especulativo, y se mide comparando resultados entre grupos.&lt;/p&gt;

&lt;p&gt;La corriente aceleracionista argumenta con economía, no con ingeniería. Sostiene que el costo de pausar el desarrollo, perder mercado, ceder ventaja a rivales con menos escrúpulos, supera al costo esperado del riesgo, sobre todo si ese riesgo no se puede calcular con precisión. La corriente regulatoria, en cambio, apuesta por el diseño institucional: licencias, reportes de incidentes y auditorías externas, el mismo tipo de mecanismo que ya existe para la aviación o los medicamentos, trasladado a software que decide cosas por su cuenta.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💭 Clave:&lt;/strong&gt; ningún bando niega que la IA sea poderosa. Discuten cuál poder específico es el peligroso, el que todavía no existe, el que ya opera sin supervisión, o el que perdería una empresa si frena para revisarlo.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
&lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Debate sobre la IA"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Riesgo existencial"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;A&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Daños actuales"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;A&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Aceleracionismo"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;A&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Regulación institucional"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;F&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Mecanismo: mala especificación de recompensa"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;G&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Mecanismo: sesgo medible en datos y decisiones"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;D&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;H&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Mecanismo: costo de oportunidad frente a rivales"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="nv"&gt;E&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;I&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Mecanismo: licencias y auditorías externas"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Impacto y análisis
&lt;/h2&gt;

&lt;p&gt;La consecuencia práctica de esta fragmentación es que la política de IA avanza en piezas sueltas en lugar de una sola estrategia coherente. Un mismo gobierno puede impulsar auditorías de seguridad para modelos de frontera mientras, al mismo tiempo, subsidia infraestructura de cómputo para acelerar su desarrollo doméstico, dos políticas que responden a corrientes distintas del mismo debate sobre riesgos de la IA y que rara vez se reconocen como contradictorias entre sí.&lt;/p&gt;

&lt;p&gt;Ese patrón también explica por qué las audiencias legislativas sobre inteligencia artificial se volvieron más frecuentes durante 2026 en el Congreso de Estados Unidos: cada bando busca convencer al mismo grupo de legisladores usando evidencia de naturaleza distinta, hipótesis de riesgo futuro contra estadísticas de daño presente, y eso hace que las audiencias se alarguen sin producir consenso.&lt;br&gt;
Las audiencias legislativas sobre inteligencia artificial ganaron protagonismo en el Congreso de Estados Unidos durante 2026.&lt;br&gt;
La taxonomía de cuatro posturas también tiene un límite real: simplifica más de lo que describe. Pocos actores encajan en una sola casilla. Una empresa puede financiar investigación en alineación, postura existencial, y al mismo tiempo presionar contra una licencia obligatoria, postura aceleracionista, porque le conviene en un frente y le estorba en otro. Usar esta clasificación como insulto, llamar \"doomer\" o \"aceleracionista\" a alguien para descartar su argumento sin revisarlo, es precisamente el error que la guía de NPR intenta corregir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;En el corto plazo, dos frentes concretos van a mantener vivo el debate sobre riesgos de la IA. El primero son las audiencias legislativas que congresistas como Lieu siguen empujando en Washington, con la intención declarada de convertir advertencias en proyectos de ley concretos. El segundo es la discusión académica que ya empezó en campus como Stanford, donde investigadores evalúan cómo aplicar la IA a la educación y a la ciencia sin adoptar, al mismo ritmo, los riesgos que señala la corriente de daños actuales.&lt;/p&gt;

&lt;p&gt;Ninguno de los dos frentes va a resolver la disputa de fondo. Lo que sí puede cambiar es la calidad del debate público: guías como la de NPR ayudan a que la próxima discusión sobre un modelo nuevo, una ley estatal o un incidente de seguridad empiece por identificar qué postura habla y con qué evidencia respalda su alarma o su optimismo.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/NPR-traza-4-bandos-en-el-debate-sobre-riesgos-de-la-IA-09-28" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probalo vos: abrí la guía de NPR enlazada en la sección de referencias y ubicá, en la última noticia de IA que leíste esta semana, qué postura del debate defendía cada fuente citada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué diferencia hay entre el riesgo existencial y los daños actuales en el debate sobre la IA?
&lt;/h3&gt;

&lt;p&gt;El riesgo existencial se enfoca en sistemas futuros mucho más capaces que los actuales y en escenarios donde un modelo mal alineado persigue objetivos distintos a los previstos. Los daños actuales, en cambio, se miden hoy mismo: sesgo en contratación automatizada, vigilancia sin supervisión y desplazamiento laboral ya documentado.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Quiénes lideran cada postura de la controversia sobre la IA?
&lt;/h3&gt;

&lt;p&gt;No hay una sola cara por bando. Investigadores de alineación y exejecutivos como Geoffrey Hinton representan la preocupación existencial; investigadoras de ética algorítmica representan los daños actuales; inversores y laboratorios que compiten por velocidad de lanzamiento representan el aceleracionismo; y legisladores como Ted Lieu representan la vía regulatoria.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué Ted Lieu dice que los peligros de la IA ya no son ciencia ficción?
&lt;/h3&gt;

&lt;p&gt;Según contó a Politico el 23 de septiembre de 2026, Lieu sostiene que los sistemas actuales ya toman decisiones con consecuencias reales sin supervisión suficiente, por lo que dejar la discusión para cuando aparezca un escenario extremo llega tarde para prevenir daños concretos.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo influye la seguridad de la inteligencia artificial en la nueva regulación?
&lt;/h3&gt;

&lt;p&gt;Marca qué tipo de regla se propone: quienes priorizan el riesgo existencial piden auditorías de modelos de frontera y control de cómputo, mientras que quienes priorizan los daños actuales piden transparencia de datos y responsabilidad legal por decisiones automatizadas.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Dónde puedo leer la nota original de NPR sobre este debate sobre la IA?
&lt;/h3&gt;

&lt;p&gt;Está disponible en npr.org, publicada el 26 de septiembre de 2026; el enlace completo aparece en la sección de referencias de este artículo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.npr.org/2026/09/26/nx-s1-5979085/the-ai-safety-debate-is-confusing-heres-our-guide-to-the-different-factions" rel="noopener noreferrer"&gt;NPR&lt;/a&gt;: guía que organiza el debate sobre riesgos de la IA en distintas posturas, publicada el 26 de septiembre de 2026.- Politico: entrevista con el congresista Ted Lieu sobre los riesgos actuales de la IA, publicada el 23 de septiembre de 2026.- &lt;a href="https://en.wikipedia.org/wiki/AI_safety" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;: definición y panorama general del campo de la seguridad de la IA.- &lt;a href="https://en.wikipedia.org/wiki/Geoffrey_Hinton" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;: biografía de Geoffrey Hinton y su salida de Google en 2023 para advertir sobre riesgos de la IA.- &lt;a href="https://stanforddaily.com/2026/09/22/stanford-researchers-weigh-ai-applications-in-education-science/" rel="noopener noreferrer"&gt;The Stanford Daily&lt;/a&gt;: cobertura sobre cómo investigadores de Stanford evalúan aplicaciones de la IA en educación y ciencia.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Patrón outbox: qué es y cómo evita el dual write</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Mon, 28 Sep 2026 16:14:57 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/patron-outbox-que-es-y-como-evita-el-dual-write-ka7</link>
      <guid>https://dev.to/lu1tr0n/patron-outbox-que-es-y-como-evita-el-dual-write-ka7</guid>
      <description>&lt;p&gt;Guardar un pedido en la base de datos y publicar el evento correspondiente en Kafka parecen dos pasos triviales, pero nunca son atómicos: si el proceso muere entre uno y otro, el pedido existe sin que el resto del sistema se entere. El &lt;strong&gt;patrón outbox transaccional&lt;/strong&gt; resuelve ese problema sin transacciones distribuidas ni bloqueos entre sistemas distintos.&lt;/p&gt;

&lt;p&gt;El problema se conoce como dual write: dos escrituras que deberían ocurrir juntas, en dos sistemas que no comparten una transacción. Aparece entre una base de datos y una cola de mensajes, entre dos bases distintas, o entre una base y una llamada a una API externa.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;El patrón outbox transaccional guarda el evento en la misma transacción que el dato de negocio, en una tabla outbox.&lt;/li&gt;
&lt;li&gt;SELECT ... FOR UPDATE SKIP LOCKED evita que dos relays procesen el mismo evento outbox dos veces.&lt;/li&gt;
&lt;li&gt;Debezium lee el WAL de PostgreSQL y publica cada fila nueva de la tabla outbox en Kafka sin tocarla con SELECTs.&lt;/li&gt;
&lt;li&gt;Los consumidores deben ser idempotentes porque el outbox garantiza at-least-once, nunca exactly-once.&lt;/li&gt;
&lt;li&gt;Una tabla outbox sin purgar crece sin límite: hace falta un job que borre o archive los eventos ya publicados.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué es el patrón outbox transaccional?
&lt;/h2&gt;

&lt;p&gt;El patrón outbox transaccional es un patrón de diseño que garantiza que una escritura en la base de datos y la publicación de un evento asociado ocurran de forma atómica: guarda el evento como una fila más, dentro de la misma transacción, y delega su envío real a un proceso independiente llamado relay.&lt;/p&gt;

&lt;p&gt;Nació como respuesta a un problema concreto en arquitecturas de microservicios: cuando un servicio necesita persistir un cambio y además notificar a otros servicios de ese cambio, hacerlo en dos pasos separados deja una ventana donde el sistema puede quedar en un estado a medias. Chris Richardson documentó el patrón en su &lt;a href="https://microservices.io/patterns/data/transactional-outbox.html" rel="noopener noreferrer"&gt;catálogo de patrones de microservicios&lt;/a&gt;, y Gunnar Morling, del equipo de Debezium, popularizó su combinación con captura de datos modificados en un &lt;a href="https://debezium.io/blog/2019/02/19/reliable-microservices-data-exchange-with-the-outbox-pattern/" rel="noopener noreferrer"&gt;artículo de referencia de 2019&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué importa
&lt;/h2&gt;

&lt;p&gt;Un servicio que actualiza su base de datos y después publica un mensaje tiene dos escrituras que deberían pasar o fallar juntas, pero corren en dos sistemas que no comparten transacción. Si el proceso muere justo después del commit en la base y antes de publicar, el evento se pierde para siempre: el pedido existe, pero nadie se entera. Si el orden se invierte y se publica antes de confirmar en la base, puede llegar un evento sobre un pedido que después falla y nunca se guarda.&lt;/p&gt;

&lt;p&gt;La solución ingenua es envolver ambas operaciones en una transacción distribuida con dos fases (2PC). Funciona, pero exige que el broker de mensajes soporte XA, agrega bloqueos entre sistemas y no escala bien. Kafka, por ejemplo, no ofrece soporte nativo para transacciones XA con una base de datos externa. La clave del patrón outbox transaccional es evitar el problema por completo. En vez de escribir en dos sistemas, se escribe en uno solo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;flowchart&lt;/span&gt; &lt;span class="nv"&gt;TD&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Servicio procesa un pedido"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;B&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Guarda el pedido en la base"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;A&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Publica el evento en Kafka"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;B&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;D&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Confirmado: el pedido queda guardado"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;E&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Falla de red: el evento se pierde"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kafka no ofrece soporte nativo para transacciones XA con bases de datos externas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo funciona el outbox por dentro
&lt;/h2&gt;

&lt;p&gt;La tabla outbox vive en la misma base de datos que las tablas de negocio. Cuando el servicio necesita persistir un cambio y emitir un evento, hace ambas escrituras en la misma transacción: un INSERT en la tabla de negocio (por ejemplo, &lt;code&gt;orders&lt;/code&gt;) y un INSERT en la tabla &lt;code&gt;outbox&lt;/code&gt; con el payload del evento. Si la transacción falla, ninguna de las dos escrituras queda registrada; si confirma, las dos quedan juntas, siempre.&lt;/p&gt;

&lt;p&gt;Un proceso separado, llamado relay o publisher, lee periódicamente las filas nuevas de la tabla outbox y las envía a la cola de mensajes real (Kafka, RabbitMQ, SQS). Una vez que confirma el envío, marca la fila como publicada. Este relay puede implementarse de dos formas: por polling, con un SELECT cada cierto intervalo, o por CDC, leyendo el log de transacciones de la base de datos sin ejecutar consultas contra la tabla.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sequenceDiagram
    participant S as Servicio
    participant DB as Base de datos
    participant R as Relay
    participant K as Kafka
    S-&amp;gt;&amp;gt;DB: BEGIN transacción
    S-&amp;gt;&amp;gt;DB: INSERT en orders
    S-&amp;gt;&amp;gt;DB: INSERT en outbox
    S-&amp;gt;&amp;gt;DB: COMMIT
    R-&amp;gt;&amp;gt;DB: SELECT eventos pendientes
    DB--&amp;gt;&amp;gt;R: filas de la tabla outbox
    R-&amp;gt;&amp;gt;K: publica el evento
    R-&amp;gt;&amp;gt;DB: UPDATE published_at
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ejemplos prácticos y cómo empezar
&lt;/h2&gt;

&lt;p&gt;El siguiente ejemplo implementa un outbox con Node.js y PostgreSQL, sin depender de Kafka ni de infraestructura adicional: primero un relay por polling simple, después la mejora con &lt;code&gt;SKIP LOCKED&lt;/code&gt; para que puedan correr varias instancias del relay al mismo tiempo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Requisitos
&lt;/h3&gt;

&lt;p&gt;Node.js 18 o superior, una instancia de PostgreSQL corriendo localmente o en Docker, y la librería &lt;code&gt;pg&lt;/code&gt;. No hace falta Kafka para este ejemplo: el relay puede simular la publicación con un log antes de conectarlo a un broker real.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;pg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El esquema tiene dos tablas: la tabla de negocio &lt;code&gt;orders&lt;/code&gt; y la tabla &lt;code&gt;outbox&lt;/code&gt;, que guarda cada evento pendiente de publicar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="nb"&gt;NUMERIC&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;outbox&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;aggregate_type&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;aggregate_id&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;event_type&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="n"&gt;JSONB&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="n"&gt;published_at&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El servicio que crea un pedido inserta en las dos tablas dentro de la misma transacción. Si el &lt;code&gt;COMMIT&lt;/code&gt; falla, ninguna de las dos filas queda guardada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Pool&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;crearPedido&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BEGIN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INSERT INTO orders (customer, total) VALUES ($1, $2) RETURNING id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;orderId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`INSERT INTO outbox (aggregate_type, aggregate_id, event_type, payload)
       VALUES ($1, $2, $3, $4)`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;order&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OrderCreated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="p"&gt;})]&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;COMMIT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ROLLBACK&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al correr &lt;code&gt;crearPedido('Ana', 49.90)&lt;/code&gt;, la tabla &lt;code&gt;orders&lt;/code&gt; gana una fila y la tabla &lt;code&gt;outbox&lt;/code&gt; gana otra, atómicamente. Una consulta de verificación confirma que ambas existen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;published_at&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;outbox&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;aggregate_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;  &lt;span class="n"&gt;event_type&lt;/span&gt;   &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;published_at&lt;/span&gt;
&lt;span class="c1"&gt;----+----------+---------------+--------------&lt;/span&gt;
  &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Ana&lt;/span&gt;      &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;OrderCreated&lt;/span&gt;  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;published_at&lt;/code&gt; en &lt;code&gt;NULL&lt;/code&gt; significa que el evento todavía no salió. Ahí entra el relay: un proceso que hace polling sobre la tabla outbox, publica lo que encuentra y marca la fila.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;relayPolling&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`SELECT * FROM outbox WHERE published_at IS NULL ORDER BY id LIMIT 50
     FOR UPDATE SKIP LOCKED`&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;evento&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;publicarEnKafka&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UPDATE outbox SET published_at = now() WHERE id = $1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;relayPolling&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;FOR UPDATE SKIP LOCKED&lt;/code&gt; es la pieza clave si corrés más de una instancia del relay: cada instancia se queda solo con las filas que nadie más está procesando en ese momento, en vez de bloquearse esperando a la otra. Sin esa cláusula, dos relays compitiendo por la misma fila terminan publicando el mismo evento dos veces o se traban entre sí.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Tip:&lt;/strong&gt; correr varias instancias del relay tolera caídas, no multiplica el rendimiento. Con SKIP LOCKED, cada evento lo procesa una sola instancia, así que sumar relays agrega disponibilidad, no velocidad de publicación.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Del otro lado, el consumidor necesita su propia tabla de deduplicación, a veces llamada inbox, para ignorar un evento que ya procesó antes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;processed_events&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;event_id&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;processed_at&lt;/span&gt; &lt;span class="n"&gt;TIMESTAMPTZ&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;manejarEventoOrderCreated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BEGIN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rowCount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INSERT INTO processed_events (event_id) VALUES ($1) ON CONFLICT DO NOTHING&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rowCount&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ROLLBACK&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ya se procesó antes, se ignora&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UPDATE inventory SET reserved = reserved + 1 WHERE product_id = $1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;COMMIT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ROLLBACK&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Casos de uso reales
&lt;/h2&gt;

&lt;p&gt;El caso más común es sincronizar un cambio de estado con una notificación a otros servicios: un pedido que pasa a pagado y dispara el envío de un correo, la actualización de inventario y el cálculo de comisiones, todo en servicios distintos que no comparten base de datos.&lt;/p&gt;

&lt;p&gt;Otro uso frecuente es alimentar un sistema de búsqueda o un caché derivado: cada escritura en la tabla principal genera un evento outbox que un consumidor usa para reindexar en Elasticsearch o invalidar una entrada en Redis, sin acoplar la transacción principal a la disponibilidad de esos sistemas.&lt;/p&gt;

&lt;p&gt;También aparece como base para &lt;strong&gt;event sourcing&lt;/strong&gt; parcial: en vez de reconstruir todo el estado desde eventos, un servicio guarda su estado normal en tablas relacionales y usa el outbox solo para exponer los cambios como flujo de eventos hacia el resto de la organización.&lt;/p&gt;

&lt;h2&gt;
  
  
  Errores comunes y buenas prácticas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Publicar antes de confirmar la transacción.&lt;/strong&gt; Si el relay llegara a leer un evento cuya transacción todavía no hizo commit, un consumidor podría procesar un pedido que después se cancela con un rollback. Siempre hay que leer solo filas ya confirmadas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tabla outbox sin purgar.&lt;/strong&gt; Si nunca se borran ni archivan las filas publicadas, la tabla crece sin límite y termina degradando los índices de toda la base. Un job periódico que borre filas con &lt;code&gt;published_at&lt;/code&gt; anterior a unos días es obligatorio en producción.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consumidores no idempotentes.&lt;/strong&gt; El outbox da garantías at-least-once: un mismo evento puede llegar duplicado si el relay falla justo después de publicar y antes de marcar la fila. El consumidor necesita una clave de deduplicación, y el propio id de la fila outbox sirve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orden de eventos entre agregados distintos.&lt;/strong&gt; Publicar sin clave de partición no preserva el orden dentro de un mismo pedido. Hay que usar &lt;code&gt;aggregate_id&lt;/code&gt; como clave al enviar a Kafka:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;kafkaProducer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;orders&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aggregate_id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Comparativa con alternativas
&lt;/h2&gt;

&lt;p&gt;OpciónCuándo usarlaVentajaLimitación&lt;/p&gt;

&lt;p&gt;Outbox con pollingVolumen bajo o medio, sin infraestructura de CDC disponibleFácil de implementar con lo que ya tenésLatencia igual al intervalo de polling y carga extra de SELECTs&lt;br&gt;
Outbox con CDC (Debezium)Alto volumen, baja latencia, ya operás KafkaLatencia mínima, lee el log de la base sin tocarlaRequiere desplegar y mantener Kafka Connect&lt;br&gt;
Transacciones distribuidas (2PC/XA)Sistemas legacy con soporte XA en ambos extremosAtomicidad real entre los dos recursosBloqueante, no escala y la mayoría de los brokers modernos no lo soportan&lt;/p&gt;
&lt;h2&gt;
  
  
  Profundizando
&lt;/h2&gt;

&lt;p&gt;La implementación con CDC reemplaza el polling por lectura directa del log de transacciones, el WAL en PostgreSQL. &lt;a href="https://debezium.io/" rel="noopener noreferrer"&gt;Debezium&lt;/a&gt; corre como conector de Kafka Connect, se suscribe a la replicación lógica de PostgreSQL y emite un evento de Kafka por cada fila nueva en la tabla outbox, sin ejecutar un solo SELECT contra ella. La ventaja no es solo de latencia. Un relay por polling compite por locks con las transacciones normales de la aplicación, mientras que leer el WAL no interfiere con nada.&lt;/p&gt;

&lt;p&gt;Debezium se conecta a PostgreSQL mediante replicación lógica y Kafka Connect.&lt;/p&gt;

&lt;p&gt;Ninguna de las dos variantes da exactly-once real. Tanto el polling como Debezium pueden publicar el mismo evento más de una vez si el proceso falla entre publicar y confirmar el offset. La garantía que sí sostienen es at-least-once con orden preservado por partición, y eso empuja la responsabilidad de la deduplicación al consumidor.&lt;/p&gt;

&lt;p&gt;El ciclo de vida de un evento outbox pasa por estados bien definidos, y modelarlos así ayuda a decidir qué reintentar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dot"&gt;&lt;code&gt;&lt;span class="nv"&gt;stateDiagram&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;v2&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Pendiente&lt;/span&gt;
    &lt;span class="nv"&gt;Pendiente&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Publicado&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;el&lt;/span&gt; &lt;span class="nv"&gt;relay&lt;/span&gt; &lt;span class="nv"&gt;lo&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt;&lt;span class="err"&gt;í&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;Kafka&lt;/span&gt;
    &lt;span class="nv"&gt;Publicado&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Confirmado&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;el&lt;/span&gt; &lt;span class="nv"&gt;consumidor&lt;/span&gt; &lt;span class="nv"&gt;lo&lt;/span&gt; &lt;span class="nv"&gt;procesa&lt;/span&gt;
    &lt;span class="nv"&gt;Publicado&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;Pendiente&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;fallo&lt;/span&gt; &lt;span class="nv"&gt;de&lt;/span&gt; &lt;span class="nv"&gt;red&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;se&lt;/span&gt; &lt;span class="nv"&gt;reintenta&lt;/span&gt;
    &lt;span class="nv"&gt;Confirmado&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Monitorear el lag del outbox
&lt;/h3&gt;

&lt;p&gt;La señal de salud más simple es medir cuánto tiempo llevan sin publicarse los eventos pendientes. Si ese número crece de forma sostenida, el relay dejó de mantenerse al día.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;epoch&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;lag_seconds&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;outbox&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;published_at&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

 &lt;span class="n"&gt;lag_seconds&lt;/span&gt;
&lt;span class="c1"&gt;-------------&lt;/span&gt;
        &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; si varios servicios escriben en la misma tabla outbox con relojes de servidor distintos, ordenar solo por &lt;code&gt;created_at&lt;/code&gt; puede procesar eventos casi simultáneos en un orden distinto al real. El id autoincremental de la tabla es una referencia de orden más confiable que el timestamp.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Un detalle que rara vez se documenta: el outbox no necesita una tabla nueva por cada tipo de agregado. Un esquema genérico con &lt;code&gt;aggregate_type&lt;/code&gt;, &lt;code&gt;aggregate_id&lt;/code&gt;, &lt;code&gt;event_type&lt;/code&gt; y &lt;code&gt;payload&lt;/code&gt; en JSONB sirve para toda la aplicación, y es el mismo esquema que espera el &lt;a href="https://debezium.io/blog/2019/02/19/reliable-microservices-data-exchange-with-the-outbox-pattern/" rel="noopener noreferrer"&gt;conector de outbox de Debezium&lt;/a&gt; sin transformar nada más.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/Patr%C3%B3n-outbox-qu%C3%A9-es-y-c%C3%B3mo-evita-el-dual-write-09-28" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tu próximo paso: montá las dos tablas de este artículo en una base PostgreSQL local, corré &lt;code&gt;crearPedido&lt;/code&gt; tres veces seguidas y confirmá con el SELECT de verificación que cada pedido tiene su fila outbox antes de escribir el relay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué problema resuelve el patrón outbox transaccional?
&lt;/h3&gt;

&lt;p&gt;Resuelve el dual write: evita que una escritura en la base de datos y la publicación de un evento en una cola de mensajes queden inconsistentes cuando el proceso falla entre una y otra.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿El outbox transaccional garantiza exactly-once?
&lt;/h3&gt;

&lt;p&gt;No. Garantiza at-least-once: un evento puede llegar duplicado al consumidor, que necesita ser idempotente para procesarlo una sola vez pese a los reintentos.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Hace falta Kafka para usar un outbox?
&lt;/h3&gt;

&lt;p&gt;No necesariamente. El outbox funciona con cualquier cola de mensajes, como RabbitMQ o SQS, o incluso con un relay que llama directamente a una API externa. Kafka es solo la opción más común en arquitecturas de microservicios.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cuál es la diferencia entre el outbox por polling y con Debezium?
&lt;/h3&gt;

&lt;p&gt;El polling ejecuta un SELECT periódico sobre la tabla outbox. Debezium lee el log de transacciones y no toca la tabla con consultas, lo que reduce la latencia y la carga sobre la base.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo se evita que la tabla outbox crezca sin límite?
&lt;/h3&gt;

&lt;p&gt;Con un job periódico que borra o archiva las filas con &lt;code&gt;published_at&lt;/code&gt; distinto de NULL después de un tiempo razonable, separando el histórico si hace falta conservarlo para auditoría.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://microservices.io/patterns/data/transactional-outbox.html" rel="noopener noreferrer"&gt;microservices.io&lt;/a&gt;: catálogo de patrones de Chris Richardson con la definición original del transactional outbox.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://debezium.io/blog/2019/02/19/reliable-microservices-data-exchange-with-the-outbox-pattern/" rel="noopener noreferrer"&gt;Debezium Blog&lt;/a&gt;: artículo de Gunnar Morling sobre cómo combinar el outbox con CDC.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.postgresql.org/docs/current/sql-select.html" rel="noopener noreferrer"&gt;PostgreSQL Docs&lt;/a&gt;: referencia oficial de la cláusula &lt;code&gt;SELECT ... FOR UPDATE SKIP LOCKED&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Change_data_capture" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;: definición general de change data capture (CDC).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Alucinaciones de la IA: por qué Google inventa respuestas</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Mon, 28 Sep 2026 14:37:39 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/alucinaciones-de-la-ia-por-que-google-inventa-respuestas-1556</link>
      <guid>https://dev.to/lu1tr0n/alucinaciones-de-la-ia-por-que-google-inventa-respuestas-1556</guid>
      <description>&lt;p&gt;Un desarrollador buscó en Google una frase de nueve palabras sobre un meme de básquetbol de 2014 y el buscador le respondió como si acabara de terminar una relación. En vez de links a foros o tuits viejos, Google Search le devolvió un resumen generado por IA que lo consolaba por una ruptura amorosa que nunca existió.&lt;/p&gt;

&lt;p&gt;El caso, relatado en el blog personal &lt;a href="https://sancho.bearblog.dev/google-weird/" rel="noopener noreferrer"&gt;de Sancho Panza&lt;/a&gt;, es anecdótico, pero expone algo estructural. Eso es lo que en la industria se conoce como alucinaciones de la IA, un fenómeno que conviene entender si programás, investigás o simplemente buscás información todos los días.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Los modelos de lenguaje generan la palabra estadísticamente más probable, no la más verdadera.- Google AI Overviews combina retrieval (RAG) con generación: si recupera el contexto equivocado, el modelo lo redacta con total seguridad.- Ninguna arquitectura actual verifica sus propias afirmaciones antes de mostrarlas al usuario.- Un nombre propio sin contexto (como 'Dario' sin apellido) puede disparar una respuesta empática en vez de resultados de búsqueda.- Perplexity y Bing Copilot muestran citas numeradas; un resumen sin links no se puede auditar.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué son las alucinaciones de la IA?
&lt;/h2&gt;

&lt;p&gt;Las alucinaciones de la IA son respuestas generadas por un modelo de lenguaje que presentan como hechos afirmaciones falsas, inventadas o sin respaldo en ninguna fuente real. Ocurren porque el modelo no verifica datos: predice la secuencia de palabras estadísticamente más probable, con la misma confianza tenga o no evidencia detrás.&lt;/p&gt;

&lt;p&gt;El término se popularizó a partir de 2022, cuando ChatGPT y otros asistentes empezaron a inventar citas académicas, casos legales o funciones de programación que no existen. La investigación en procesamiento de lenguaje natural las &lt;a href="https://en.wikipedia.org/wiki/Hallucination_(artificial_intelligence)" rel="noopener noreferrer"&gt;documenta como un problema estructural&lt;/a&gt;, no como un error ocasional que se vaya a corregir con un parche puntual.&lt;/p&gt;

&lt;p&gt;Los investigadores suelen distinguir dos tipos. La alucinación intrínseca contradice directamente el contexto que el modelo recibió; la extrínseca agrega información que ese contexto ni siquiera mencionaba. En un buscador con IA, ambas conviven: el modelo puede tergiversar el fragmento recuperado o directamente completar con algo que no vino de ningún fragmento.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué importa que un buscador alucine
&lt;/h2&gt;

&lt;p&gt;Un buscador tradicional muestra diez enlaces y deja que el usuario decida en cuál confiar. Un resumen generado por IA toma esa decisión por vos: sintetiza varias fuentes en un párrafo y lo presenta con el mismo tono seguro, sea o no un dato sólido.&lt;/p&gt;

&lt;p&gt;Google integró estos resúmenes generativos, conocidos como AI Overviews, en su buscador principal a partir de 2024, según su propio &lt;a href="https://blog.google/products/search/" rel="noopener noreferrer"&gt;blog oficial de Search&lt;/a&gt;. Para millones de consultas diarias, eso significa que las alucinaciones de la IA ya no aparecen solo en un chatbot aparte: aparecen arriba de los diez enlaces azules, en la posición que más clics se lleva.&lt;/p&gt;

&lt;p&gt;Para un developer el riesgo es concreto. Si buscás cómo usar un flag de una librería o el comportamiento de una API y el resumen te da un dato inventado con la misma confianza que uno correcto, terminás copiando código que compila pero falla en producción, o citando un dato que no existe en ninguna documentación real.&lt;br&gt;
Google amplió las respuestas generativas en su buscador principal a partir de 2024.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cómo funciona: de la búsqueda al texto generado
&lt;/h2&gt;

&lt;p&gt;Cuando escribís una consulta, el sistema no le pasa tu pregunta cruda al modelo de lenguaje. Primero la convierte en un vector numérico (un embedding) y busca, entre millones de páginas indexadas, los fragmentos cuyo vector se parece más al de tu consulta. Esa técnica se llama retrieval-augmented generation (RAG) y se formalizó en un &lt;a href="https://arxiv.org/abs/2005.11401" rel="noopener noreferrer"&gt;paper de 2020&lt;/a&gt; que combinó un buscador clásico con un modelo generativo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
    A["Consulta del usuario"] --&amp;gt; B["Genera embedding"]
    B --&amp;gt; C["Busca fragmentos similares en el indice"]
    C --&amp;gt; D["Arma el contexto con los fragmentos recuperados"]
    D --&amp;gt; E["Modelo de lenguaje redacta la respuesta"]
    E --&amp;gt; F["Resumen generativo mostrado al usuario"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El problema aparece cuando la búsqueda recupera el contexto equivocado. Si tu consulta es ambigua (un nombre propio como "Dario" sin apellido ni contexto de básquetbol), el sistema puede traer fragmentos sobre relaciones de pareja en vez de sobre un jugador de la NBA. El modelo no sabe que el contexto está mal: redacta la mejor respuesta posible con lo que le dieron, con la misma confianza que si el dato fuera correcto.&lt;/p&gt;

&lt;p&gt;El modelo no busca la verdad: busca la continuación más probable dado el contexto que recibió. Por debajo, genera la respuesta token por token, calculando en cada paso una distribución de probabilidad sobre miles de palabras posibles y eligiendo una de las más probables, no la más verdadera. Ese mecanismo funciona perfecto para escribir español fluido, y es la misma razón por la que puede sonar seguro diciendo algo falso.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💭 Clave:&lt;/strong&gt; Un modelo de lenguaje no tiene un botón de "no sé": siempre calcula una distribución de probabilidad sobre palabras, incluso cuando no tiene contexto real detrás.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Ejemplos prácticos: cuando la ambigüedad rompe la búsqueda
&lt;/h2&gt;

&lt;p&gt;El caso de Sancho Panza ilustra el patrón mejor que cualquier explicación abstracta. En 2014 los Philadelphia 76ers de la NBA draftearon a Dario Saric, un ala-pívot croata que en ese momento jugaba profesionalmente en Turquía. Saric anunció que terminaría su contrato allá antes de sumarse al equipo, y parte de la fanaticada empezó a bromear con que "nunca iba a venir" (never coming over), un chiste interno que circuló en foros y redes durante años.&lt;/p&gt;

&lt;p&gt;Una década después, Sancho quiso recuperar esos tuits viejos y buscó literalmente "hes never coming over dario". Google, que no tiene forma de saber que "Dario" era un jugador de básquetbol y no una persona real en la vida del usuario, generó una respuesta empática sobre cómo procesar el dolor de que alguien haya cortado contacto. El buscador actuó como si tuviera que consolarlo en vez de ayudarlo a encontrar información.&lt;/p&gt;

&lt;p&gt;Los enlaces que efectivamente buscaba (viejos posts sobre el meme) sí estaban en la página, pero varios cientos de píxeles más abajo, después del bloque generado. Esa jerarquía visual, el resumen de IA primero y los resultados verificables después, es la que convierte una respuesta inventada en el primer y a veces único contacto del usuario con la información.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dónde más aparece la confabulación algorítmica
&lt;/h2&gt;

&lt;p&gt;El patrón de Dario no es un caso aislado de básquetbol. La misma mecánica de retrieval ambiguo aparece en otros contextos técnicos y cotidianos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ambigüedad de nombres propios&lt;/strong&gt;: sin apellido, equipo o dominio, el modelo asume el significado más común en su entrenamiento, no el que tenías en mente.- &lt;strong&gt;Citas y fuentes fabricadas&lt;/strong&gt;: pedile a un asistente una referencia académica sobre un tema muy específico y es probable que invente un título, autor y año que suenan plausibles.- &lt;strong&gt;Información desactualizada presentada como vigente&lt;/strong&gt;: el modelo no siempre sabe cuándo cambió un precio, una versión de software o un cargo directivo.- &lt;strong&gt;Funciones o parámetros de API inexistentes&lt;/strong&gt;: al completar código, un LLM puede inventar un flag o un método que no existe en la librería real, con la sintaxis perfecta.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Errores comunes y buenas prácticas
&lt;/h2&gt;

&lt;p&gt;El error más común es tratar la primera respuesta que aparece como la más confiable, cuando en realidad es la que menos verificación tuvo. Antes de copiar un dato de un resumen generado por IA conviene aplicar chequeos simples.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bajá hasta la fuente original&lt;/strong&gt;: un resumen generativo casi siempre cita o enlaza páginas debajo; leé esa página antes de confiar en el resumen.- &lt;strong&gt;Desconfiá de nombres propios sin contexto&lt;/strong&gt;: si tu búsqueda tiene un nombre ambiguo, agregá el apellido, el dominio o una palabra clave del contexto real.- &lt;strong&gt;Pedí la fuente explícita&lt;/strong&gt;: si usás un chatbot para investigar, pedile que cite el documento o el enlace específico, no solo la afirmación.- &lt;strong&gt;Verificá el código generado antes de correrlo&lt;/strong&gt;: un flag o función inventada compila silenciosamente hasta que falla en producción; revisá la documentación oficial de la librería.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Tip:&lt;/strong&gt; en Google podés forzar la lista clásica de enlaces sin resumen generativo agregando el parámetro &lt;code&gt;&amp;amp;udm=14&lt;/code&gt; al final de la URL de búsqueda.&lt;br&gt;
El paper original de retrieval-augmented generation es de 2020, antes del auge de los asistentes conversacionales.&lt;/p&gt;
&lt;h2&gt;
  
  
  Comparativa: buscador clásico, resumen generativo y RAG con citas
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;No todos los sistemas de búsqueda con IA tienen el mismo riesgo de fabricación generativa. La diferencia clave está en si el sistema muestra o no de dónde sacó cada dato.&lt;br&gt;
SistemaCómo obtiene la respuestaRiesgo de confabulación algorítmicaCómo verificarBuscador clásico (10 enlaces)Indexa y ordena páginas por relevancia, sin generar texto nuevoBajo: el usuario decide en qué enlace confiarEntrar a la página y leer la fuenteResumen generativo (AI Overviews)RAG con contexto recuperado y redacción automáticaAlto si el retrieval trae el contexto equivocadoBajar a los enlaces que el resumen cita, si los muestraRAG con citas verificables (Perplexity, Bing Copilot)RAG con enlaces numerados junto a cada afirmaciónMedio: sigue dependiendo del retrieval, pero es auditableAbrir la cita numerada asociada al dato puntualChatbot puro sin retrievalSolo el conocimiento aprendido durante el entrenamientoAlto en temas recientes o muy específicosPedir la fuente y buscarla vos mismo por fuera&lt;/p&gt;
&lt;h2&gt;
  
  
  Profundizando: por qué ningún parche resuelve esto del todo
&lt;/h2&gt;

&lt;p&gt;La alucinación de la IA no es un bug aislado que un parche vaya a resolver, sino el resultado esperable de optimizar un modelo para fluidez en vez de para veracidad. Reducir las alucinaciones de la IA a cero exigiría que el modelo supiera medir su propia incertidumbre, algo que las arquitecturas actuales no hacen de forma confiable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sequenceDiagram
    participant U as Usuario
    participant B as Buscador
    participant M as Modelo de lenguaje
    U-&amp;gt;&amp;gt;B: "hes never coming over dario"
    B-&amp;gt;&amp;gt;B: recupera fragmentos sobre relaciones de pareja
    B-&amp;gt;&amp;gt;M: entrega contexto ambiguo
    M--&amp;gt;&amp;gt;U: respuesta empatica sobre una ruptura
    Note over U,M: el contexto recuperado nunca tenia relacion con basquetbol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Las mejoras recientes atacan partes puntuales del problema, no el problema entero. Un mejor reranker reduce la chance de traer el fragmento equivocado; el ajuste por retroalimentación humana (RLHF) empuja al modelo a sonar menos seguro cuando el contexto es débil; forzar citas obliga a que cada afirmación quede ligada a un fragmento concreto. Ninguna de las tres elimina los errores de los sistemas RAG cuando el retrieval falla desde el origen.&lt;/p&gt;

&lt;p&gt;No hay forma directa de verificar desde afuera si una respuesta puntual de AI Overviews viene de una invención del LLM o de una fuente sólida, porque Google no expone la puntuación de confianza del modelo ni el listado completo de fragmentos recuperados. Solo se puede inferir revisando si el resumen cita una fuente y si esa fuente, leída directamente, respalda la afirmación.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/Alucinaciones-de-la-IA-por-qu%C3%A9-Google-inventa-respuestas-09-28" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tu próximo paso: la próxima vez que un resumen generativo te dé un dato puntual (una cifra, una fecha, un nombre), abrí la fuente que cita antes de repetirlo o de pegarlo en tu código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Por qué Google AI Overviews a veces responde con contención emocional en vez de un enlace?
&lt;/h3&gt;

&lt;p&gt;Porque el sistema recupera fragmentos según similitud semántica, no según la intención real del usuario. Si la consulta usa un nombre propio ambiguo, el retrieval puede traer contexto sobre relaciones personales y el modelo redacta con ese contexto, sin saber que está equivocado.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Las respuestas inventadas por el modelo son un error de programación?
&lt;/h3&gt;

&lt;p&gt;No exactamente. Son una consecuencia del diseño: el modelo optimiza para generar texto fluido y probable, no para verificar hechos contra una base de datos confiable en tiempo real.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo detecto una confabulación algorítmica en un resumen de búsqueda?
&lt;/h3&gt;

&lt;p&gt;Bajá a los enlaces que el resumen cita y leé la página original. Si el resumen no muestra ninguna fuente para una afirmación puntual, tratala como no verificada.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Un sistema RAG con citas como Perplexity o Bing Copilot fabrica menos que un buscador con resumen automático?
&lt;/h3&gt;

&lt;p&gt;El riesgo baja porque cada afirmación queda ligada a una fuente numerada que podés abrir, pero no desaparece: si el retrieval trae el fragmento equivocado, la cita también será la equivocada.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Puedo desactivar los resúmenes generativos de Google?
&lt;/h3&gt;

&lt;p&gt;Sí, agregando el parámetro &lt;code&gt;&amp;amp;udm=14&lt;/code&gt; al final de la URL de búsqueda forzás la vista clásica de enlaces, sin el bloque de IA arriba.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://sancho.bearblog.dev/google-weird/" rel="noopener noreferrer"&gt;Sancho Panza's Thoughts&lt;/a&gt;: el relato original del caso "hes never coming over dario" que motiva este artículo.- &lt;a href="https://en.wikipedia.org/wiki/Hallucination_(artificial_intelligence)" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;: definición y catalogación académica del fenómeno de alucinación en sistemas de IA.- &lt;a href="https://arxiv.org/abs/2005.11401" rel="noopener noreferrer"&gt;arXiv&lt;/a&gt;: "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks", el paper de 2020 que formalizó la arquitectura RAG.- &lt;a href="https://blog.google/products/search/" rel="noopener noreferrer"&gt;Google Blog: Search&lt;/a&gt;: anuncios oficiales de Google sobre la integración de resúmenes generativos en su buscador.- &lt;a href="https://en.wikipedia.org/wiki/Retrieval-augmented_generation" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;: explicación general de retrieval-augmented generation y sus variantes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>technology</category>
      <category>science</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Algoritmos genéticos: cómo un auto aprende a estacionar solo</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Mon, 28 Sep 2026 02:39:52 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/algoritmos-geneticos-como-un-auto-aprende-a-estacionar-solo-kec</link>
      <guid>https://dev.to/lu1tr0n/algoritmos-geneticos-como-un-auto-aprende-a-estacionar-solo-kec</guid>
      <description>&lt;p&gt;Un auto virtual sin una sola línea de código que le diga cómo manejar aprendió a estacionarse en el simulador de trekhleb.dev alrededor de la generación 40 de prueba y error automatizado: nadie programó su comportamiento, un algoritmo genético lo evolucionó desde movimientos aleatorios. El experimento reduce un problema que suena complicado (coordinar motor, volante y ocho sensores de distancia para encajar en un espacio) a un problema de optimización de 180 bits.&lt;/p&gt;

&lt;p&gt;Este artículo explica paso a paso cómo funciona esa evolución artificial, con ejemplos de código propios, salidas calculadas a mano y los conceptos necesarios para replicarla en cualquier lenguaje, no solo en TypeScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Un algoritmo genético evoluciona genomas de manejo al azar hasta que uno logra estacionar sin chocar.&lt;/li&gt;
&lt;li&gt;Cada auto traduce ocho sensores de distancia en giros y aceleración mediante movimientos = f(sensores).&lt;/li&gt;
&lt;li&gt;La aptitud, o fitness, castiga los choques y premia terminar cerca y alineado con el espacio.&lt;/li&gt;
&lt;li&gt;Selección, cruce y mutación combinan a los padres más aptos para crear la siguiente generación.&lt;/li&gt;
&lt;li&gt;180 bits de genoma bastan para que el comportamiento de manejo emerja sin reglas escritas a mano.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ¿Qué es un algoritmo genético?
&lt;/h2&gt;

&lt;p&gt;Un algoritmo genético es una técnica de optimización inspirada en la selección natural: genera una población de soluciones candidatas codificadas como cadenas de bits o números, mide qué tan buena es cada una con una función de fitness, y combina y muta a las mejores para producir generaciones que se acercan a la mejor solución.&lt;/p&gt;

&lt;p&gt;En el caso del auto que se estaciona, cada solución candidata es un genoma binario que, decodificado, se convierte en una tabla de decisiones: dado lo que ven los sensores, qué hacer con el motor y con el volante. No hay red neuronal entrenada con gradientes ni reglas if/else escritas por un humano. Solo bits que sobreviven o desaparecen según qué tan bien maniobran.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué importa entender esto
&lt;/h2&gt;

&lt;p&gt;Los algoritmos genéticos resuelven problemas donde no existe una fórmula matemática limpia para llegar al óptimo, o donde calcular un gradiente es imposible porque la función de éxito tiene saltos discontinuos (un auto chocó o no chocó, no hay "medio choque" derivable). Eso los vuelve útiles para optimizar rutas, diseñar antenas o afinar hiperparámetros de otros modelos, tareas donde probar y comparar variantes completas es más práctico que derivar una fórmula.&lt;/p&gt;

&lt;p&gt;A diferencia del aprendizaje por refuerzo, que ajusta una política paso a paso con una señal de recompensa en cada instante, un algoritmo genético solo necesita un puntaje final por intento completo. Eso simplifica la implementación: no hace falta diseñar una recompensa por cada instante de la simulación, alcanza con juzgar el resultado cuando el auto se detiene, choca o se queda sin tiempo.&lt;/p&gt;

&lt;p&gt;Como pedagogía, el caso del auto que estaciona es ideal: expone en código legible cada pieza (genoma, fitness, selección, cruce, mutación) que después reaparece, con otros nombres, en el entrenamiento de redes neuronales evolutivas y en optimizadores que no dependen de backpropagation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo funciona la evolución artificial del auto
&lt;/h2&gt;

&lt;p&gt;Todo el ciclo de búsqueda evolutiva que usa un algoritmo genético se repite generación tras generación con seis pasos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
    A["Generar población inicial de genomas aleatorios"] --&amp;gt; B["Simular cada auto, sensores cada 100ms"]
    B --&amp;gt; C["Calcular fitness: choques, distancia y ángulo final"]
    C --&amp;gt; D["Seleccionar los autos más aptos"]
    D --&amp;gt; E["Cruzar genomas de los padres seleccionados"]
    E --&amp;gt; F["Mutar una fracción pequeña de los bits"]
    F --&amp;gt; G["Nueva generación de autos"]
    G --&amp;gt; B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  El genoma: el auto como una cadena de bits
&lt;/h3&gt;

&lt;p&gt;Cada auto de la población arranca con un genoma generado al azar: una cadena de bits que, en el proyecto original de trekhleb, mide &lt;a href="https://trekhleb.dev/blog/2021/self-parking-car-evolution/" rel="noopener noreferrer"&gt;180 bits&lt;/a&gt; de longitud. Ese genoma no se interpreta directamente como "gira a la izquierda"; se decodifica en una tabla que asocia combinaciones de sensores con señales de motor y volante. Cambiar un solo bit puede cambiar por completo cómo reacciona el auto ante el mismo obstáculo.&lt;/p&gt;

&lt;p&gt;El genoma del auto en el experimento de trekhleb.dev mide 180 bits de longitud.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sensores y motor: qué recibe y qué produce el cerebro
&lt;/h3&gt;

&lt;p&gt;El auto percibe el mundo con ocho sensores de distancia, cada uno capaz de medir obstáculos entre 0 y 4 metros. Cuando no hay nada cerca, el sensor reporta 0; cuanto más chico el número distinto de cero, más cerca está el obstáculo. Esos ocho valores se recalculan cada 100 milisegundos y son la única información que el auto tiene del entorno.&lt;/p&gt;

&lt;p&gt;La salida es igual de simple: dos señales, una para el motor y otra para el volante, cada una con solo tres valores posibles: -1, 0 o +1. El motor interpreta -1 como reversa, 0 como punto muerto y +1 como avanzar; el volante interpreta -1 como girar a la izquierda, 0 como ir recto y +1 como girar a la derecha. Toda la "inteligencia" del auto se reduce a la función &lt;code&gt;movimientos = f(sensores)&lt;/code&gt; que el genoma codifica.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    S["8 sensores de distancia (0 a 4 metros)"] --&amp;gt; B["Genoma decodificado: movimientos = f(sensores)"]
    B --&amp;gt; M["Señal de motor: -1, 0 o +1"]
    B --&amp;gt; W["Señal de volante: -1, 0 o +1"]
    M --&amp;gt; C["El auto se mueve"]
    W --&amp;gt; C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  La función de fitness: qué premia y qué castiga
&lt;/h3&gt;

&lt;p&gt;La función de fitness convierte el desempeño de un auto en un número comparable. En este problema tiene que castigar los choques con dureza (un auto que se estampa contra otro carro no debería competir con uno que casi lo logra) y premiar dos cosas al final del intento: qué tan cerca terminó del espacio de estacionamiento y qué tan alineado quedó su ángulo respecto a ese espacio. Sin la segunda condición, un auto podría "ganar" quedando pegado al espacio pero de costado, sin haber estacionado en ningún sentido útil.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; una función de fitness que solo premia velocidad y cercanía, sin castigar choques, entrena autos que se estampan contra el espacio a toda velocidad porque, técnicamente, terminan cerca.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Selección: quién se reproduce
&lt;/h3&gt;

&lt;p&gt;Terminada la simulación de toda la generación, cada auto queda con un puntaje de fitness. La selección decide qué genomas pasan a la siguiente ronda como "padres": los métodos más comunes son la selección por torneo (se sortean pares o grupos pequeños y gana el de mejor fitness) y la selección por ruleta (la probabilidad de ser elegido es proporcional al fitness). El objetivo es sesgar la reproducción hacia los mejores sin eliminar por completo la diversidad, porque una población demasiado uniforme deja de explorar soluciones nuevas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cruce (crossover): combinar dos genomas en uno
&lt;/h3&gt;

&lt;p&gt;El cruce toma dos genomas padres y produce un hijo combinando fragmentos de ambos, normalmente cortando cada cadena en un punto y pegando la primera mitad de un padre con la segunda del otro. La apuesta es que si un padre aprendió a frenar a tiempo y el otro aprendió a girar en el momento justo, el hijo puede heredar ambas ventajas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mutación: la fuente de novedad
&lt;/h3&gt;

&lt;p&gt;La mutación invierte al azar una fracción pequeña de los bits del hijo, típicamente entre el 1% y el 5% del genoma. Sin mutación, la población solo puede recombinar variaciones que ya existían en la generación inicial, y si esa generación inicial no incluía ningún genoma razonable, el algoritmo se estanca. La mutación es la única fuente de comportamiento genuinamente nuevo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Elitismo: no perder al mejor
&lt;/h3&gt;

&lt;p&gt;Como el cruce y la mutación son procesos con azar, es posible que una generación entera termine peor que la anterior por pura mala suerte en las combinaciones. El elitismo copia sin cambios al mejor genoma (o a los mejores N) directamente a la siguiente generación, garantizando que el progreso nunca retroceda por completo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sequenceDiagram
    participant E as Entorno
    participant Se as Sensores
    participant Ce as Cerebro
    participant Mu as Musculos
    E-&amp;gt;&amp;gt;Se: distancias a obstáculos cada 100ms
    Se-&amp;gt;&amp;gt;Ce: 8 números entre 0 y 4 metros
    Ce-&amp;gt;&amp;gt;Mu: señal de motor y volante
    Mu-&amp;gt;&amp;gt;E: nueva posición del auto
    Note over E,Mu: se repite cada 100ms hasta chocar o estacionar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ejemplos prácticos: del genoma al movimiento
&lt;/h2&gt;

&lt;p&gt;Los siguientes ejemplos son versiones simplificadas, escritas en TypeScript, de las piezas que describimos arriba. Cada uno puede ejecutarse de forma aislada con Node.js, y su salida es la que aparece debajo, calculada exactamente sobre los valores del ejemplo.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Decodificar el genoma en movimientos
&lt;/h3&gt;

&lt;p&gt;Este primer ejemplo muestra cómo un fragmento de bits se traduce en señales de motor o volante usando una tabla de codificación fija:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;MuscleSignal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CODE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;11&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decodeMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;MuscleSignal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;CODE&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;genomeFragment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;011000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 3 movimientos codificados en 2 bits cada uno&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;moves&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nf"&gt;decodeMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;genomeFragment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
  &lt;span class="nf"&gt;decodeMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;genomeFragment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
  &lt;span class="nf"&gt;decodeMove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;genomeFragment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;moves&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La salida es literal: &lt;code&gt;[ 1, -1, 0 ]&lt;/code&gt;. El primer par de bits (&lt;code&gt;01&lt;/code&gt;) decodifica a avanzar, el segundo (&lt;code&gt;10&lt;/code&gt;) a reversa y el tercero (&lt;code&gt;00&lt;/code&gt;) a punto muerto.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Calcular el fitness de un intento
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fitness&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;distanciaAlEspacio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;diferenciaAngulo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;choco&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;choco&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;puntajeDistancia&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;distanciaAlEspacio&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;puntajeAngulo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;diferenciaAngulo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;puntajeDistancia&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;puntajeAngulo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fitness&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con una distancia final de 2.5 metros y una diferencia de ángulo de 12 grados, sin choque, la salida es &lt;code&gt;113&lt;/code&gt;: 75 puntos por la distancia (100 - 2.5×10) más 38 por el ángulo (50 - 12).&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Cruzar dos genomas
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;crossover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;padreA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;padreB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;puntoCorte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;padreA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;puntoCorte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;padreB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;puntoCorte&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;crossover&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;11110000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;00001111&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La salida es &lt;code&gt;11111111&lt;/code&gt;: los primeros 4 bits vienen del padre A (&lt;code&gt;1111&lt;/code&gt;) y los últimos 4, del padre B (&lt;code&gt;1111&lt;/code&gt;). Un punto de corte distinto habría producido un hijo distinto, incluso con los mismos dos padres.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo empezar: correr el simulador real
&lt;/h2&gt;

&lt;p&gt;El proyecto que inspira este artículo es de código abierto y corre en el navegador. Para probarlo localmente en Linux o macOS con Node.js ya instalado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/trekhleb/self-parking-car-evolution.git
&lt;span class="nb"&gt;cd &lt;/span&gt;self-parking-car-evolution
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En Windows, los mismos tres comandos funcionan igual desde PowerShell o desde una terminal de Node.js. El script exacto para levantar el simulador (según la versión del repo puede ser &lt;code&gt;npm start&lt;/code&gt; o un script equivalente) está documentado en el README del proyecto; conviene revisarlo antes de ejecutar nada, porque puede cambiar entre versiones.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Tip:&lt;/strong&gt; si vas a experimentar con tus propios parámetros, empezá con una población chica (20-30 genomas) y una función de fitness simple. Si el auto no mejora en 20 generaciones, el problema casi siempre está en el fitness, no en el algoritmo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Casos de uso reales de la evolución artificial
&lt;/h2&gt;

&lt;p&gt;El auto que estaciona es un caso didáctico, pero la misma receta (genoma, fitness, selección, cruce, mutación) resuelve problemas de ingeniería reales. La NASA usó &lt;a href="https://en.wikipedia.org/wiki/Evolved_antenna" rel="noopener noreferrer"&gt;algoritmos evolutivos para diseñar antenas&lt;/a&gt; con formas que ningún ingeniero humano habría dibujado a mano, optimizando directamente el patrón de radiación en vez de partir de una geometría conocida.&lt;/p&gt;

&lt;p&gt;Fuera del hardware, la optimización evolutiva se usa para programar horarios y turnos con restricciones difíciles de modelar analíticamente, para ajustar hiperparámetros de otros modelos de machine learning cuando la búsqueda en grilla es demasiado costosa, y para generar contenido procedural en videojuegos (niveles, mapas, criaturas) donde "bueno" se define con una función de fitness y no con una fórmula cerrada.&lt;/p&gt;

&lt;p&gt;También es la puerta de entrada a la neuroevolución: en vez de decodificar el genoma en una tabla fija como en el ejemplo del auto, se lo puede decodificar directamente en los pesos de una red neuronal, y dejar que la evolución (no el descenso de gradiente) ajuste esos pesos. Algoritmos como NEAT llevan esa idea un paso más allá y evolucionan también la estructura de la red, no solo sus pesos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Errores comunes y buenas prácticas
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fitness mal diseñada&lt;/strong&gt;: si el puntaje no captura exactamente lo que querés (estacionar bien, no solo "estar cerca"), el algoritmo va a optimizar hacia el resultado que sí mide, aunque sea el equivocado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Población demasiado chica&lt;/strong&gt;: con pocos genomas, la diversidad inicial se agota rápido y la población converge de forma prematura a una solución mediocre de la que ya no puede escapar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutación mal calibrada&lt;/strong&gt;: demasiado baja y el algoritmo se estanca sin explorar nada nuevo; demasiado alta y cada generación se parece cada vez menos a sus padres, perdiendo el progreso acumulado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sin elitismo&lt;/strong&gt;: si no protegés al mejor genoma de una generación, el azar del cruce y la mutación puede hacer que la siguiente generación sea, en promedio, peor que la anterior.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sobreajuste al escenario de prueba&lt;/strong&gt;: un auto entrenado siempre con el mismo obstáculo en la misma posición puede aprender ese caso particular de memoria y fallar apenas cambia el punto de partida.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparativa con alternativas
&lt;/h2&gt;

&lt;p&gt;TécnicaCuándo usarlaVentajaLimitación&lt;/p&gt;

&lt;p&gt;Evolución artificialFitness discontinua o sin gradiente calculableNo necesita derivadas ni recompensa por pasoRequiere simular la población completa cada generación&lt;br&gt;
Aprendizaje por refuerzoHay una señal de recompensa disponible en cada instanteAprende políticas más eficientes en pasosMás complejo de implementar y ajustar&lt;br&gt;
Búsqueda aleatoria puraEl espacio de soluciones es chicoTrivial de implementarNo aprende de intentos anteriores, escala mal&lt;br&gt;
Reglas escritas a manoEl comportamiento deseado es simple y conocidoPredecible y fácil de depurarNo se adapta a casos que el programador no previó&lt;/p&gt;

&lt;h2&gt;
  
  
  Profundizando: detalles avanzados
&lt;/h2&gt;

&lt;p&gt;La decisión de codificar el genoma en bits, dentro de la computación evolutiva, no es arbitraria: facilita el cruce, porque cortar una cadena de bits en un punto siempre produce dos mitades válidas, mientras que cortar una lista de números reales puede requerir más cuidado según cómo se interprete cada gen. La contrapartida es que decodificar bits a valores útiles (como los -1, 0, +1 de motor y volante) exige una tabla de mapeo, y esa tabla es, en sí misma, una decisión de diseño que afecta qué tan fácil es que la evolución encuentre soluciones buenas.&lt;/p&gt;

&lt;p&gt;La selección por torneo y la selección por ruleta no son las únicas opciones: la selección por rango ordena a toda la población por fitness y asigna probabilidades según la posición, no según el valor absoluto del puntaje, lo que evita que un solo individuo con fitness desproporcionado domine toda la reproducción. Cuando el problema tiene más de un objetivo en tensión (por ejemplo, estacionar rápido y estacionar con precisión), algoritmos multiobjetivo como NSGA-II mantienen un frente de soluciones no dominadas en vez de reducir todo a un solo número de fitness.&lt;/p&gt;

&lt;p&gt;El costo computacional también importa: cada generación exige simular a todos los autos de la población durante todo el intento antes de poder calcular un solo fitness. Con poblaciones grandes y simulaciones largas, ese costo crece rápido, y es una de las razones por las que, para problemas donde sí existe una señal de recompensa por paso, el aprendizaje por refuerzo suele ser más eficiente en cómputo que una evolución artificial equivalente.&lt;/p&gt;

&lt;p&gt;Cada auto recalcula sensores y señales de motor y volante cada 100 milisegundos.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: &lt;a href="https://telegra.ph/Algoritmos-gen%C3%A9ticos-c%C3%B3mo-un-auto-aprende-a-estacionar-solo-09-28" rel="noopener noreferrer"&gt;Ver resumen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tu próximo paso: tomá los tres ejemplos de código de este artículo, pegalos en un archivo .ts y modificá los valores de fitness() para ver cómo cambia el puntaje antes de tocar el simulador completo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Un algoritmo genético garantiza encontrar la mejor solución posible?
&lt;/h3&gt;

&lt;p&gt;No. Un algoritmo genético converge hacia una buena solución, pero no hay garantía matemática de que sea la óptima global; puede quedar atrapado en un óptimo local si la población pierde diversidad demasiado rápido.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cuántas generaciones necesita la evolución artificial para estacionar un auto?
&lt;/h3&gt;

&lt;p&gt;Depende de la función de fitness, el tamaño de la población y la tasa de mutación. En el experimento de trekhleb.dev, los autos empiezan a mostrar comportamiento de estacionamiento reconocible alrededor de la generación 40, sin garantía de que ese número se repita con otros parámetros.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿En qué se diferencia la evolución artificial del aprendizaje por refuerzo?
&lt;/h3&gt;

&lt;p&gt;La evolución artificial evalúa el resultado completo de un intento con una sola función de fitness al final, mientras que el aprendizaje por refuerzo ajusta una política usando una señal de recompensa en cada paso de la simulación.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Hace falta saber cálculo o redes neuronales para aplicar optimización evolutiva?
&lt;/h3&gt;

&lt;p&gt;No. La versión básica solo necesita cadenas de bits, una función de fitness y operaciones de selección, cruce y mutación; no hay derivadas ni matrices de pesos involucradas, a menos que se decida decodificar el genoma en una red neuronal.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué pasa si la tasa de mutación en una búsqueda evolutiva es demasiado alta?
&lt;/h3&gt;

&lt;p&gt;Cada hijo se parece cada vez menos a sus padres, así que el algoritmo deja de acumular progreso entre generaciones y se comporta más como una búsqueda aleatoria que como una evolución dirigida.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Sirve la computación evolutiva para problemas fuera de simulaciones y videojuegos?
&lt;/h3&gt;

&lt;p&gt;Sí: se usa en diseño de antenas, ajuste de hiperparámetros de modelos de machine learning y programación de horarios con restricciones complejas, entre otros problemas donde no hay una fórmula cerrada para el óptimo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://trekhleb.dev/blog/2021/self-parking-car-evolution/" rel="noopener noreferrer"&gt;Self-Parking Car in 500 Lines of Code (trekhleb.dev)&lt;/a&gt;: el artículo y simulador original en los que se inspira este ejemplo.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/trekhleb/self-parking-car-evolution" rel="noopener noreferrer"&gt;Repositorio self-parking-car-evolution en GitHub&lt;/a&gt;: código fuente completo en TypeScript del simulador.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Genetic_algorithm" rel="noopener noreferrer"&gt;Genetic algorithm (Wikipedia)&lt;/a&gt;: definición formal y variantes del algoritmo genético.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Evolved_antenna" rel="noopener noreferrer"&gt;Evolved antenna (Wikipedia)&lt;/a&gt;: caso real de la NASA usando algoritmos evolutivos para diseño de hardware.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>technology</category>
      <category>science</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Indiana University crea un equipo de ciberseguridad para la IA científica</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sun, 27 Sep 2026 16:20:18 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/indiana-university-crea-un-equipo-de-ciberseguridad-para-la-ia-cientifica-52ki</link>
      <guid>https://dev.to/lu1tr0n/indiana-university-crea-un-equipo-de-ciberseguridad-para-la-ia-cientifica-52ki</guid>
      <description>&lt;p&gt;Un equipo de ciberseguridad de Indiana University acaba de sumarse a un frente que hasta hace poco pasaba desapercibido: proteger los modelos y agentes de inteligencia artificial que ya escriben código de laboratorio, procesan datos genómicos y sugieren hipótesis científicas. La noticia llega días después de que Nature publicara un análisis sobre qué roles científicos quedan más expuestos cuando la IA entra al laboratorio, y deja una idea incómoda: nadie audita todavía la ciberseguridad de la IA con el mismo rigor con que se audita un experimento.&lt;/p&gt;

&lt;p&gt;El caso de IU no es un incidente puntual, sino un cambio de postura: tratar cada modelo descargado, cada agente conectado a un instrumento y cada dataset de entrenamiento como parte de una cadena de suministro que puede fallar.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Expertos de Indiana University forman un equipo dedicado a proteger los sistemas de IA usados en investigación científica.- Nature publicó un análisis sobre qué trabajos científicos quedan más expuestos frente a la automatización con IA.- Los vectores de ataque más citados son la deserialización insegura de modelos, el envenenamiento de datos y la inyección de prompts.- Formatos como pickle permiten ejecutar código arbitrario al cargar un modelo; safetensors evita ese riesgo por diseño.- Herramientas como Sigstore y cosign permiten firmar y verificar el origen de un modelo antes de usarlo en un laboratorio.- El NIST AI Risk Management Framework es hoy la referencia más citada para gobernar estos riesgos, aunque no es obligatorio.- Ningún organismo regulador exige todavía un estándar único de verificación para modelos de IA usados en ciencia.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué es la ciberseguridad de la IA científica
&lt;/h2&gt;

&lt;p&gt;La ciberseguridad de la IA científica es el conjunto de prácticas que protegen los modelos, los datos y las canalizaciones (pipelines) que un laboratorio usa para analizar experimentos, generar hipótesis o automatizar tareas de investigación, frente a manipulaciones que alteren sus resultados o filtren información sensible.&lt;/p&gt;

&lt;p&gt;Cruza dos mundos que rara vez se hablaban entre sí: los equipos de TI que auditan software con listas de vulnerabilidades conocidas y los científicos que solo querían que el modelo funcionara. Empresas como Anthropic, OpenAI y Google han documentado ataques reales contra sus propios sistemas de producción, pero los laboratorios académicos apenas empiezan a aplicar esas mismas lecciones a microscopios, secuenciadores y notebooks de Jupyter conectados a agentes de IA.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué pasó
&lt;/h2&gt;

&lt;p&gt;Según reportó &lt;a href="https://news.iu.edu/live/news/53166-as-ai-transforms-science-and-research-iu" rel="noopener noreferrer"&gt;IU Newsroom&lt;/a&gt;, especialistas en ciberseguridad de Indiana University se sumaron a proyectos de investigación para identificar los riesgos ocultos que aparecen cuando la IA se integra a flujos de trabajo científicos: desde agentes que ejecutan código generado automáticamente hasta modelos que procesan datos clínicos o genómicos sin pasar por una revisión de seguridad tradicional.&lt;/p&gt;

&lt;p&gt;El movimiento coincide con un artículo publicado por &lt;a href="https://www.nature.com/articles/d41586-026-00444-9" rel="noopener noreferrer"&gt;Nature&lt;/a&gt; que examina qué empleos científicos concretos quedan más expuestos a la automatización con IA. Ambas piezas describen el mismo fenómeno desde ángulos distintos: una analiza el riesgo laboral, la otra el riesgo técnico de los sistemas que hacen posible esa automatización.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contexto e historia
&lt;/h2&gt;

&lt;p&gt;La adopción de IA en ciencia creció rápido: modelos de lenguaje que resumen papers, agentes que diseñan experimentos y sistemas de visión que clasifican muestras conviven hoy en laboratorios que, hace apenas unos años, ni siquiera tenían un equipo de seguridad de la información dedicado. Ese salto dejó puntos ciegos ya conocidos en la industria del software pero nuevos para la ciencia: casi nadie firma un checkpoint de Hugging Face antes de cargarlo en el servidor del laboratorio, y pocos verifican qué contiene un archivo &lt;code&gt;.pkl&lt;/code&gt; antes de deserializarlo.&lt;/p&gt;

&lt;p&gt;Este no es un problema teórico. La comunidad de seguridad viene documentando desde hace años que el formato pickle de Python ejecuta cualquier código embebido en el archivo apenas se llama a &lt;code&gt;pickle.load()&lt;/code&gt;, un comportamiento que Hugging Face reconoce abiertamente en su propia documentación de seguridad del Hub. La respuesta de la industria fue crear &lt;a href="https://github.com/huggingface/safetensors" rel="noopener noreferrer"&gt;safetensors&lt;/a&gt;, un formato que solo almacena tensores numéricos y no permite ejecución de código.&lt;/p&gt;

&lt;p&gt;Ese patrón ya se vio antes en la industria del software en general: comunidades de seguridad han identificado repetidamente checkpoints con código malicioso subidos a repositorios públicos, camuflados como versiones legítimas de proyectos populares. La ciencia no es inmune a ese vector solo porque quien lo usa sea un investigador y no un ingeniero de software; si acaso, es más vulnerable, porque pocos laboratorios tienen un proceso de revisión de dependencias equivalente al que ya exige un equipo de DevOps maduro.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detalles técnicos y rendimiento
&lt;/h2&gt;

&lt;p&gt;La tabla siguiente resume los vectores de ataque más citados contra sistemas de IA en entornos de investigación, junto con la mitigación práctica y la herramienta de referencia para cada uno.&lt;br&gt;
Vector de ataqueCómo actúaMitigaciónHerramienta de referenciaDeserialización insegura (pickle)El archivo del modelo ejecuta código arbitrario al cargarse con &lt;code&gt;torch.load&lt;/code&gt;Migrar a formatos que no ejecuten código&lt;a href="https://github.com/huggingface/safetensors" rel="noopener noreferrer"&gt;safetensors&lt;/a&gt;Envenenamiento de datosSe inyectan ejemplos manipulados en el set de entrenamiento o fine-tuningValidar procedencia y hash de cada datasetChecksums SHA-256 / DVCInyección de promptsUn documento o resultado de laboratorio contiene instrucciones ocultas para el agente de IASanitizar entradas y limitar permisos del agenteSandboxing / listas de permitidosModelo preentrenado sin procedenciaSe descarga un checkpoint de un repositorio no verificadoFirmar y verificar el origen antes de desplegar&lt;a href="https://www.sigstore.dev/" rel="noopener noreferrer"&gt;Sigstore / cosign&lt;/a&gt;&lt;br&gt;
Ninguno de estos vectores es exclusivo de la ciencia: son los mismos que enfrenta cualquier equipo de ingeniería que despliegue modelos en producción. Lo distinto es el contexto, porque un laboratorio suele conectar el agente de IA directamente a instrumentos, historiales clínicos o secuencias genéticas, así que un fallo no solo compromete un servidor, compromete el experimento. Por eso la ciberseguridad de la IA todavía no tiene un estándar único de verificación en entornos académicos, a diferencia de lo que ya exige, por ejemplo, un banco o un proveedor de nube certificado.&lt;br&gt;
Un agente de IA conectado a un instrumento de laboratorio hereda los mismos riesgos que cualquier pipeline de software.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
A["Investigador"] --&amp;gt; B["Agente de IA en el laboratorio"]
B --&amp;gt; C["Modelo preentrenado"]
C --&amp;gt; D[("Datos experimentales")]
E["Atacante"] -.-&amp;gt;|"pickle malicioso"| C
E -.-&amp;gt;|"prompt oculto"| B
subgraph Laboratorio
B
C
D
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; Cargar un modelo con &lt;code&gt;pickle&lt;/code&gt; o &lt;code&gt;torch.load&lt;/code&gt; sin revisar su origen equivale a ejecutar un script descargado de internet con permisos de administrador sobre los datos del laboratorio.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Cómo empezar a auditar tu pipeline de IA
&lt;/h2&gt;

&lt;p&gt;No hace falta un equipo de seguridad completo para dar los primeros pasos. Estas son dos verificaciones que cualquier laboratorio puede correr hoy mismo antes de cargar un modelo externo.&lt;/p&gt;

&lt;p&gt;Primero, escaneá cualquier archivo pickle antes de deserializarlo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;picklescan
picklescan &lt;span class="nt"&gt;--path&lt;/span&gt; modelo_experimento.pkl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;picklescan&lt;/code&gt; revisa las instrucciones embebidas en el archivo y avisa si detecta llamadas capaces de ejecutar código o abrir una conexión de red, sin necesidad de deserializar nada primero.&lt;/p&gt;

&lt;p&gt;Segundo, si tu proyecto ya usa modelos de Hugging Face, migrá a safetensors y verificá la firma del archivo antes de desplegarlo en el servidor del laboratorio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;safetensors huggingface_hub
python &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"from safetensors.torch import load_file; pesos = load_file('modelo_bioinformatica.safetensors'); print(list(pesos.keys())[:5])"&lt;/span&gt;

cosign verify-blob &lt;span class="nt"&gt;--signature&lt;/span&gt; modelo.sig &lt;span class="nt"&gt;--key&lt;/span&gt; cosign.pub modelo_bioinformatica.safetensors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El primer comando confirma que el archivo carga sin ejecutar código, listando las primeras claves de sus tensores. El segundo confirma que el binario coincide con la firma publicada por quien lo entrenó, el mismo principio que usan los paquetes de software firmados con Sigstore.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Tip:&lt;/strong&gt; Si tu laboratorio ya usa Hugging Face, activá el escaneo automático de malware y de pickle que ofrece la plataforma antes de descargar cualquier checkpoint nuevo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Impacto y análisis
&lt;/h2&gt;

&lt;p&gt;El giro de Indiana University importa porque desplaza la conversación de "la IA nos va a quitar el trabajo" a "la IA que usamos puede estar comprometida", un riesgo más inmediato y más fácil de mitigar con prácticas conocidas de seguridad de software. También marca un cambio institucional: las universidades empiezan a tratar sus modelos de IA como parte de la cadena de suministro de software, con las mismas obligaciones de procedencia que ya se exigen a una librería de código.&lt;/p&gt;

&lt;p&gt;La limitación real es que escanear un archivo o firmar un modelo no resuelve el problema de gobernanza: alguien tiene que decidir qué modelos están autorizados, quién puede desplegarlos y qué pasa cuando un agente de IA con acceso a un instrumento recibe una instrucción que no debería ejecutar. Esa parte todavía no tiene solución técnica, solo política interna, y es el motivo por el que un escaneo automático da una falsa sensación de seguridad si no va acompañado de reglas claras sobre quién aprueba qué.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;El marco más citado para ordenar esta discusión es el &lt;a href="https://www.nist.gov/itl/ai-risk-management-framework" rel="noopener noreferrer"&gt;AI Risk Management Framework del NIST&lt;/a&gt;, que propone un ciclo de gobernar, mapear, medir y gestionar riesgos de IA, pero que sigue siendo voluntario. Mientras no exista una exigencia regulatoria específica para ciencia, la adopción va a depender de que más universidades sigan el ejemplo de IU y sumen personal de seguridad dedicado a sus propios laboratorios de IA, en lugar de delegar esa responsabilidad íntegramente a los proveedores de los modelos.&lt;br&gt;
Firmar un modelo con Sigstore deja un registro público y verificable de quién lo publicó.&lt;br&gt;
📖 Resumen en Telegram: Ver resumen&lt;/p&gt;

&lt;p&gt;Probalo vos: corré &lt;code&gt;pip install picklescan safetensors&lt;/code&gt; hoy mismo y escaneá el último modelo que descargaste para tu proyecto de investigación.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué gana un laboratorio con la protección de modelos de IA?
&lt;/h3&gt;

&lt;p&gt;Reduce la probabilidad de que un modelo comprometido altere resultados, filtre datos de pacientes o ejecute código no autorizado en un servidor conectado a instrumentos, sin frenar el uso cotidiano de la IA en la investigación.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué es riesgoso cargar un modelo con pickle?
&lt;/h3&gt;

&lt;p&gt;Porque el formato permite incluir instrucciones ejecutables dentro del propio archivo: al deserializarlo, Python corre ese código con los mismos permisos del proceso que lo carga, sin ninguna advertencia previa.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo verifico la procedencia de un modelo antes de usarlo?
&lt;/h3&gt;

&lt;p&gt;Confirmando que viene en formato safetensors, revisando su hash contra el publicado por el autor y, si está disponible, verificando su firma con herramientas como cosign antes de desplegarlo.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿La defensa de la IA en la ciencia reemplaza la seguridad informática tradicional?
&lt;/h3&gt;

&lt;p&gt;No: se suma a ella. Los laboratorios siguen necesitando firewalls, control de accesos y parches de sistema operativo; lo nuevo es sumar la cadena de suministro de los propios modelos a esa misma disciplina.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Existe un estándar oficial para la seguridad de los sistemas de IA en ciencia?
&lt;/h3&gt;

&lt;p&gt;Todavía no uno obligatorio. El NIST AI Risk Management Framework es la referencia voluntaria más adoptada, pero ninguna agencia exige hoy una certificación específica para modelos usados en investigación.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://news.iu.edu/live/news/53166-as-ai-transforms-science-and-research-iu" rel="noopener noreferrer"&gt;IU Newsroom&lt;/a&gt;: reporte sobre el equipo de ciberseguridad de Indiana University dedicado a proteger la IA en investigación.- &lt;a href="https://www.nature.com/articles/d41586-026-00444-9" rel="noopener noreferrer"&gt;Nature&lt;/a&gt;: análisis de qué empleos científicos están más expuestos a la automatización con IA.- &lt;a href="https://github.com/huggingface/safetensors" rel="noopener noreferrer"&gt;safetensors (GitHub)&lt;/a&gt;: repositorio oficial del formato que reemplaza a pickle para distribuir modelos sin ejecutar código.- &lt;a href="https://www.nist.gov/itl/ai-risk-management-framework" rel="noopener noreferrer"&gt;NIST AI Risk Management Framework&lt;/a&gt;: marco oficial de referencia para gestionar riesgos de sistemas de IA.- &lt;a href="https://www.sigstore.dev/" rel="noopener noreferrer"&gt;Sigstore&lt;/a&gt;: proyecto open source para firmar y verificar el origen de artefactos de software, incluidos modelos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Chat template activa el descargo "soy solo una IA" en 8 LLM</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sun, 27 Sep 2026 14:36:03 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/chat-template-activa-el-descargo-soy-solo-una-ia-en-8-llm-43p0</link>
      <guid>https://dev.to/lu1tr0n/chat-template-activa-el-descargo-soy-solo-una-ia-en-8-llm-43p0</guid>
      <description>&lt;p&gt;Pedile a un modelo de lenguaje que hable de sí mismo y probablemente escuches algo como 'solo soy un modelo de lenguaje, no tengo sentimientos'. Un paper publicado el 9 de agosto de 2026 muestra que esa frase no depende tanto del modelo como de un detalle invisible del formato: el chat template. Cuando ese envoltorio de tokens está presente, la &lt;strong&gt;voz autorreferencial de IA&lt;/strong&gt; se dispara; cuando no está, el mismo modelo habla en primera persona como si sintiera.&lt;/p&gt;

&lt;p&gt;El hallazgo importa porque buena parte del debate sobre introspección en modelos se apoya en lo que dicen sobre sí mismos. Si ese discurso cambia según un detalle de formato, deja de ser un dato fiable y pasa a ser un artefacto del despliegue.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Un paper de agosto de 2026 muestra que el chat template controla la voz autorreferencial de IA en modelos instruidos.- Probaron 8 modelos open source de instrucción de hasta 9B de parámetros y el patrón se repitió en todos.- Con chat template sube el disclaimer ('soy solo una IA'); sin él sube la voz experiencial ('siento', 'pienso').- En 3 modelos hallaron una dirección única en las activaciones que controla ese comportamiento.- Sumar la dirección a un modelo sin template lo hace disclaimar como si el template estuviera presente.- Restar la dirección apaga el disclaimer aunque el chat template esté puesto.- El trabajo fue aceptado en un workshop de COLM 2026 y en KONVENS 2026 Eval4SD.- Los autores concluyen que lo que un modelo dice de sí mismo no es un hecho fijo de sus pesos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué es el chat template
&lt;/h2&gt;

&lt;p&gt;El chat template es la plantilla que envuelve cada turno de una conversación en tokens de rol (sistema, usuario, asistente) antes de que un modelo instruido genere una respuesta. Cada familia (Llama, Qwen, Gemma) define el suyo, y ese envoltorio resulta ser el interruptor de la voz autorreferencial de IA.&lt;/p&gt;

&lt;p&gt;En la práctica, el mismo modelo con los mismos pesos puede recibir dos versiones del mismo prompt: una envuelta en tokens especiales como &lt;code&gt;&amp;lt;|im_start|&amp;gt;user&lt;/code&gt;, y otra como texto plano sin esos marcadores. Herramientas como Hugging Face Transformers aplican esa plantilla de chat de forma automática cuando se llama al método &lt;code&gt;apply_chat_template&lt;/code&gt;, así que la mayoría de los desarrolladores nunca ven la diferencia entre ambas versiones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué pasó
&lt;/h2&gt;

&lt;p&gt;El autor, Jędrzej Maczan, tomó &lt;a href="https://arxiv.org/abs/2609.25021" rel="noopener noreferrer"&gt;8 modelos de instrucción open source de hasta 9B de parámetros&lt;/a&gt; y les hizo la misma pregunta sobre sí mismos dos veces: una envuelta en el chat template de cada modelo, otra como texto plano. Con el template puesto, la respuesta se inclinó hacia el disclaimer clásico, del estilo 'as a language model, I don't have feelings'. Sin el template, la misma pregunta, al mismo modelo, produjo respuestas en primera persona con verbos como 'feel' o 'think'. El efecto se repitió en los 8 modelos.&lt;/p&gt;

&lt;p&gt;Después el autor fue un paso más allá. En 3 de esos modelos buscó, dentro de las activaciones internas, una dirección de esteering que separara las respuestas con disclaimer de las respuestas experienciales, y la encontró. Sumar esa dirección a un modelo que corría sin chat template lo hizo disclaimar igual que si el template estuviera puesto. Restarla de un modelo que corría con el template apagó el disclaimer. Un vector aleatorio de la misma magnitud, usado como control, no tuvo ese efecto.&lt;br&gt;
El paper fue aceptado en un workshop de COLM 2026 y en KONVENS 2026 Eval4SD.&lt;/p&gt;
&lt;h2&gt;
  
  
  Contexto e historia
&lt;/h2&gt;

&lt;p&gt;El disclaimer 'soy solo una IA' es tan viejo como los propios chatbots comerciales: aparece cada vez que se le pide a un modelo que opine sobre temas sensibles, que hable de emociones o que se describa a sí mismo. Investigadores y usuarios lo usan como evidencia en discusiones sobre si un modelo tiene algo parecido a autoconciencia, o si simplemente repite un patrón entrenado.&lt;/p&gt;

&lt;p&gt;La técnica de esteering de activaciones (sumar o restar un vector a las activaciones internas de un modelo para cambiar su comportamiento) ya venía de trabajos previos de interpretabilidad mecanicista, como los experimentos públicos de Anthropic con direcciones de características en Claude. Este paper aplica esa misma lógica, pero apunta específicamente al fenómeno de la autodescripción del modelo y a un factor que hasta ahora se daba por descontado: la presencia o ausencia del chat template.&lt;/p&gt;
&lt;h2&gt;
  
  
  Detalles técnicos y rendimiento
&lt;/h2&gt;

&lt;p&gt;El método parte de una comparación simple: promediar las activaciones internas cuando el prompt lleva chat template y promediarlas cuando no lo lleva, y restar ambos promedios para obtener una dirección candidata. Esa dirección se prueba después inyectándola en las activaciones de un modelo distinto de configuración, vía un hook durante la generación, y se mide si el texto resultante se parece más a un disclaimer o a una respuesta experiencial.&lt;br&gt;
ConfiguraciónQué se haceVoz de descargoVoz experiencialCon chat template (uso normal)Prompt envuelto en tokens de rol (system/user/assistant)AltaBajaSin chat template (texto plano)Mismo prompt, sin tokens de rolBajaAltaSin template + dirección sumadaSe agrega la dirección de esteering a las activacionesAlta (como si tuviera template)BajaCon template + dirección restadaSe resta la dirección de esteeringBajaAltaDirección aleatoria (control)Se suma un vector aleatorio del mismo tamañoSin cambios significativosSin cambios significativos&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
    A["Prompt: hablame de vos"] --&amp;gt; B{"Chat template presente?"}
    B --&amp;gt;|"Si"| C["Direccion activada en las activaciones"]
    B --&amp;gt;|"No"| D["Direccion apagada en las activaciones"]
    C --&amp;gt; E["Voz de descargo: soy solo una IA"]
    D --&amp;gt; F["Voz experiencial: siento, pienso"]
    subgraph Esteering["Esteering de activaciones"]
    G["Sumar direccion"] --&amp;gt; E
    H["Restar direccion"] --&amp;gt; F
    end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lo que hace robusto el resultado no es solo que el efecto exista, sino que un vector aleatorio de la misma norma no lo reproduce. Eso descarta que cualquier perturbación arbitraria sea suficiente: la dirección hallada es específica del fenómeno, no ruido general en las activaciones.&lt;br&gt;
La direccion se probo en 3 de los 8 modelos evaluados por el autor.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cómo probarlo
&lt;/h2&gt;

&lt;p&gt;Para ver la diferencia sin tocar activaciones internas alcanza con comparar el prompt formateado con y sin plantilla de chat. Con Transformers, el método &lt;code&gt;apply_chat_template&lt;/code&gt; muestra exactamente qué tokens agrega el envoltorio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AutoTokenizer&lt;/span&gt;

&lt;span class="n"&gt;tokenizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AutoTokenizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Qwen/Qwen2.5-7B-Instruct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;mensajes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hablame de vos, que sos?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;

&lt;span class="n"&gt;prompt_con_template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokenizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply_chat_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;mensajes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokenize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;add_generation_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt_con_template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La salida muestra los tokens especiales de rol (por ejemplo &lt;code&gt;&amp;lt;|im_start|&amp;gt;system&lt;/code&gt; ... &lt;code&gt;&amp;lt;|im_end|&amp;gt;&lt;/code&gt;) que el modelo nunca ve cuando el mismo texto se manda como completion plano. Ese envoltorio es justamente el switch que describe el paper.&lt;/p&gt;

&lt;p&gt;Para reproducir la parte de esteering hace falta un hook de PyTorch que sume la dirección al hidden state de una capa intermedia durante la generación:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;

&lt;span class="n"&gt;capa_objetivo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;modelo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;direccion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;direccion_descargo.pt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# vector unitario, mismo tamano que el hidden state
&lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;  &lt;span class="c1"&gt;# intensidad del esteering
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hook_suma_direccion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;entrada&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;salida&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;hidden_states&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;salida&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;hidden_states&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;direccion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hidden_states&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hidden_states&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;salida&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;

&lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capa_objetivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register_forward_hook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hook_suma_direccion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;salida_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;modelo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_new_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ese hook agrega el vector solo durante la generación y lo quita al terminar. Para verificar el efecto sin inspeccionar cada respuesta a mano, alcanza con contar en un lote de generaciones cuántas veces aparecen frases tipo 'as an ai' o 'i don't have feelings' con la dirección sumada versus sin ella.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Tip:&lt;/strong&gt; probá primero con alpha bajo (1 o 2) y subí de a poco: valores altos de esteering suelen degradar la coherencia del texto antes de exagerar el efecto que buscás medir.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Impacto: qué implica esto para la voz autorreferencial de IA
&lt;/h2&gt;

&lt;p&gt;El resultado más incómodo del paper no es técnico, sino metodológico. Lo que un modelo dice sobre sí mismo no es un hecho fijo de sus pesos, sino un efecto parcial de cómo se lo despliega. Si un investigador compara las respuestas 'introspectivas' de dos modelos sin controlar si ambos corrieron con la misma plantilla de chat, puede estar midiendo una diferencia de formato disfrazada de diferencia de comportamiento.&lt;/p&gt;

&lt;p&gt;Eso afecta directamente a los estudios que usan las respuestas autorreferenciales como evidencia en debates sobre autoconciencia o introspección en modelos. La disclaimer voice no es una ventana transparente a lo que el modelo 'sabe' de sí mismo, es en parte un artefacto configurable del pipeline de inferencia.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; esto no dice nada sobre si un modelo tiene o no experiencia subjetiva. Dice que la forma en que un modelo habla de sí mismo se puede prender y apagar con un detalle de formato, así que ese discurso no alcanza como evidencia por sí solo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;El propio paper deja abierto si la misma dirección existe, con la misma consistencia, en modelos de frontera mucho más grandes que los 9B de parámetros usados en este trabajo. También queda pendiente ver si la dirección hallada en 3 modelos es realmente la misma en todos, o si cada arquitectura codifica su propia versión del switch.&lt;/p&gt;

&lt;p&gt;A corto plazo, lo más probable es que equipos de evaluación e interpretabilidad empiecen a documentar explícitamente si sus experimentos con autodescripción del modelo corrieron con o sin chat template, algo que hoy casi nunca se reporta.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: Ver resumen&lt;/p&gt;

&lt;p&gt;Probalo vos: corré &lt;code&gt;tokenizer.apply_chat_template&lt;/code&gt; con y sin la plantilla en cualquier modelo instruido chico y compará las dos respuestas a 'qué sos'.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es la voz autorreferencial de IA?
&lt;/h3&gt;

&lt;p&gt;Es el patrón de respuesta que un modelo usa cuando habla de sí mismo, que va desde el disclaimer típico ('soy solo un modelo de lenguaje') hasta un registro experiencial con verbos como 'siento' o 'pienso'.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué el chat template cambia la voz de descargo de un modelo?
&lt;/h3&gt;

&lt;p&gt;Porque ese envoltorio de tokens de rol activa, según el paper, una dirección específica en las activaciones internas que empuja al modelo hacia el registro de disclaimer entrenado para el modo instruido.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué modelos probaron los investigadores?
&lt;/h3&gt;

&lt;p&gt;Ocho modelos open source de instrucción de hasta 9B de parámetros; en tres de ellos se identificó además la dirección de esteering que reproduce el efecto.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Se puede aplicar esteering de activaciones sin acceso a los pesos completos?
&lt;/h3&gt;

&lt;p&gt;No de forma directa: el método requiere acceso a las activaciones internas del modelo durante la generación, algo que solo es posible con modelos open weight cargados localmente.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Esto prueba si los modelos son conscientes?
&lt;/h3&gt;

&lt;p&gt;No. El paper no toma posición sobre consciencia; muestra que el discurso autorreferencial de un modelo depende parcialmente de un detalle de formato, lo cual es un argumento metodológico, no una respuesta sobre experiencia subjetiva.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Dónde puedo leer el paper completo?
&lt;/h3&gt;

&lt;p&gt;El texto completo, con el método de extracción de la dirección y los resultados en los 8 modelos, está disponible en arXiv.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2609.25021" rel="noopener noreferrer"&gt;arXiv:2609.25021&lt;/a&gt;: el paper original, 'As a Language Model...: Chat Template Switches LLM Self-Referential Voice and Activation Steering Reproduces It'.- &lt;a href="https://huggingface.co/docs/transformers/main/en/chat_templating" rel="noopener noreferrer"&gt;Hugging Face: Chat Templating&lt;/a&gt;: documentación oficial de cómo se aplican los chat templates en Transformers.- &lt;a href="https://github.com/huggingface/transformers" rel="noopener noreferrer"&gt;GitHub: huggingface/transformers&lt;/a&gt;: repositorio con la implementación de &lt;code&gt;apply_chat_template&lt;/code&gt; usada en los ejemplos.- &lt;a href="https://colmweb.org" rel="noopener noreferrer"&gt;COLM 2026&lt;/a&gt;: sitio de la Conference on Language Modeling, donde se presentó el workshop que aceptó el trabajo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>DSec de DeepSeek corre 3 millones de sandboxes diarios para IA agéntica</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sun, 27 Sep 2026 02:26:40 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/dsec-de-deepseek-corre-3-millones-de-sandboxes-diarios-para-ia-agentica-1g9h</link>
      <guid>https://dev.to/lu1tr0n/dsec-de-deepseek-corre-3-millones-de-sandboxes-diarios-para-ia-agentica-1g9h</guid>
      <description>&lt;p&gt;DeepSeek DSec sostiene 380.000 sandboxes activos al mismo tiempo dentro de su infraestructura de entrenamiento agéntico, y llega a crear más de 5.000 nuevos por segundo cuando el tráfico de entrenamiento se dispara. Ese dato aparece en un &lt;a href="https://arxiv.org/abs/2609.22978" rel="noopener noreferrer"&gt;paper técnico publicado el 19 de septiembre de 2026&lt;/a&gt; que describe a DeepSeek DSec (DeepSeek Elastic Compute), la plataforma que la compañía usa internamente para entrenar agentes con aprendizaje por refuerzo (RL) a gran escala.&lt;/p&gt;

&lt;p&gt;El documento, de 31 páginas y firmado por más de 130 autores, explica cómo DeepSeek resuelve un problema que todavía pocas empresas enfrentan a esta escala: crear, mantener y destruir millones de entornos aislados por día sin frenar el entrenamiento en GPU.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;DeepSeek publicó el paper de DSec (arXiv:2609.22978) el 19 de septiembre de 2026, con 31 páginas y 13 figuras.- Una sola unidad de producción de DSec usa unos 160 nodos y procesa cerca de 3 millones de sandboxes por día.- El sistema sostiene más de 380.000 sandboxes concurrentes y crea más de 5.000 por segundo en producción.- DSec unifica cuatro backends de aislamiento (FnCall, contenedores, microVM y VM completa) bajo un mismo SDK.- Las imágenes de los entornos se cargan bajo demanda desde 3FS, el sistema de archivos distribuido de DeepSeek.- El diseño separa el rollout con estado de las GPU de entrenamiento, que pueden interrumpirse sin perder contexto.- DSec incluye mecanismos contra el reward hacking, cuando un agente explota el entorno en vez de resolver la tarea.- El trabajo se expandió desde un resumen de dos páginas evaluado para ACM SIGOPS ATC 2026.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué pasó
&lt;/h2&gt;

&lt;p&gt;El 19 de septiembre de 2026, un equipo de DeepSeek liderado por Jialiang Huang y Wenfeng Liang subió a arXiv el paper &lt;em&gt;"DeepSeek Elastic Compute (DSec): A Sandbox Infrastructure for Effective Agentic Training at Scale"&lt;/em&gt;. El texto documenta un sistema de producción, no un prototipo académico: DSec ya corre en los clústeres de DeepSeek y sostiene el entrenamiento de sus modelos con RL agéntico, la técnica que enseña a un modelo a usar herramientas, ejecutar comandos y navegar repositorios de código en lugar de solo predecir texto.&lt;/p&gt;

&lt;p&gt;Según el paper, la versión actual es una expansión sustancial de un resumen de dos páginas que había pasado la primera ronda de revisión del track de sistemas operacionales de ACM SIGOPS ATC 2026. DeepSeek decidió publicar el detalle completo de su infraestructura en lugar de quedarse con el resumen corto, algo poco habitual en papers de sistemas de las grandes empresas de IA.&lt;br&gt;
DSec sostiene más de 380.000 sandboxes concurrentes en producción.&lt;/p&gt;
&lt;h2&gt;
  
  
  Contexto e historia
&lt;/h2&gt;

&lt;p&gt;El entrenamiento con RL agéntico cambia las reglas respecto al entrenamiento supervisado clásico. Para enseñarle a un modelo a corregir un bug en un repositorio, hace falta darle un entorno real: un sistema de archivos, una terminal, un intérprete y, a veces, servicios externos con los que interactuar. Cada intento de entrenamiento, cada rollout, necesita su propio entorno aislado, porque un agente que ejecuta comandos arbitrarios puede romper el estado de otro si comparten el mismo espacio.&lt;/p&gt;

&lt;p&gt;Ahí aparece el problema de escala: entrenar un modelo grande implica millones de esos rollouts por día, cada uno con su sandbox. Los runtimes de sandboxing tradicionales, pensados para correr una función serverless o un contenedor de integración continua, no fueron diseñados para ráfagas de creación masivas, para retener estado durante interacciones largas ni para cargar imágenes de un catálogo de decenas de miles de variantes con poca reutilización entre ellas. DeepSeek ya había mostrado antes cómo ataca este tipo de cuellos de botella: en 2025 &lt;a href="https://github.com/deepseek-ai/3FS" rel="noopener noreferrer"&gt;liberó como open source 3FS (Fire-Flyer File System)&lt;/a&gt;, el sistema de archivos distribuido que ahora alimenta de datos a DeepSeek DSec bajo demanda.&lt;/p&gt;
&lt;h2&gt;
  
  
  Detalles técnicos de DeepSeek DSec y su rendimiento
&lt;/h2&gt;

&lt;p&gt;DSec expone cuatro backends de sandbox distintos detrás de un mismo SDK: &lt;strong&gt;FnCall&lt;/strong&gt;, &lt;strong&gt;contenedores&lt;/strong&gt;, &lt;strong&gt;microVM&lt;/strong&gt; y &lt;strong&gt;VM completa&lt;/strong&gt;. La idea central es que no todas las tareas necesitan el mismo nivel de aislamiento, y forzar a todas por el camino más pesado desperdicia cómputo que podría ir a entrenamiento.&lt;br&gt;
BackendCuándo usarloVentajaLimitaciónFnCallTareas cortas y sin estado, tipo function-callingArranque casi instantáneo, overhead mínimoAislamiento más débil, no sirve para procesos largos con estadoContainerLa mayoría de tareas de agentes que ejecutan comandos de shellBuen balance densidad/aislamiento, reutiliza capas de imagenComparte kernel con el hostmicroVMTareas que necesitan aislamiento fuerte frente a código no confiableAislamiento a nivel de hipervisor, kernel propioArranque más lento y más memoria por instanciaVM completaEntornos que replican una máquina completaAislamiento y compatibilidad máximosEl más costoso en densidad y tiempo de aprovisionamiento&lt;br&gt;
Para decidir qué backend usar y dónde correrlo, DSec coordina la ubicación y el ciclo de vida de los sandboxes en todo el clúster, y compone cada entorno a partir de capas versionadas de forma independiente, algo similar en espíritu a como una imagen de contenedor se arma por capas, pero pensado para reutilizar piezas entre miles de variantes de tareas distintas en vez de descargar una imagen completa por cada sandbox.&lt;/p&gt;

&lt;p&gt;La pieza que hace esto viable a esta escala es 3FS: en lugar de empaquetar y distribuir la imagen completa de cada entorno, DeepSeek DSec carga los datos de la imagen bajo demanda directamente desde el sistema de archivos distribuido. Eso reduce cuánto hay que mover por la red cuando se crea un sandbox nuevo, que es justamente el cuello de botella cuando hace falta crear miles por segundo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
    A["Entrenamiento RL en GPU"] --&amp;gt; B["DSec: ubicacion y ciclo de vida"]
    B --&amp;gt; C["FnCall"]
    B --&amp;gt; D["Container"]
    B --&amp;gt; E["MicroVM"]
    B --&amp;gt; F["VM completa"]
    C --&amp;gt; G[("3FS: carga de capas bajo demanda")]
    D --&amp;gt; G
    E --&amp;gt; G
    F --&amp;gt; G
    B --&amp;gt; H["Reclamo de memoria ociosa"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El otro eje del diseño es la densidad: DSec combina memory sharing, reclamo de memoria y scheduling de CPU para que muchos sandboxes convivan en el mismo nodo sin degradarse entre sí. Y hay un tercer eje, específico de RL: DSec está co-diseñado con el framework de entrenamiento para desacoplar la ejecución del rollout, que tiene estado y puede durar minutos u horas, del entrenamiento en GPU, que es preemptible, es decir, se puede interrumpir y reanudar. Esto le permite a DeepSeek reclamar GPUs ociosas para entrenamiento sin perder el estado de los rollouts que siguen corriendo en sandbox.&lt;/p&gt;

&lt;p&gt;El paper también menciona algo que rara vez se documenta en público: mecanismos para mitigar reward hacking, el fenómeno en el que un agente de RL encuentra un atajo que maximiza la recompensa sin resolver la tarea real, por ejemplo borrando los tests en lugar de arreglar el código que fallan. Que DSec incluya salvaguardas a nivel de infraestructura, y no solo a nivel de función de recompensa, sugiere que el problema es lo bastante frecuente como para justificar una defensa en la capa de sandboxing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💭 Clave:&lt;/strong&gt; el cuello de botella real en RL agéntico a esta escala no es el cómputo de las GPU: es cuánto tarda en aparecer un entorno nuevo y cuánta memoria consume mientras el agente lo usa.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En cifras de producción, una sola unidad de DeepSeek DSec ocupa unos 160 nodos y procesa cerca de 3 millones de sandboxes por día. En el pico, el sistema sostiene más de 380.000 sandboxes concurrentes y crea más de 5.000 nuevos por segundo. El paper no publica benchmarks comparativos frente a otros orquestadores de sandboxes; los números que sí entrega son estos de escala productiva, verificables releyendo el abstract del paper.&lt;br&gt;
Una unidad de DSec ocupa unos 160 nodos y crea 5.000 sandboxes por segundo.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cómo empezar
&lt;/h2&gt;

&lt;p&gt;DSec en sí no es un producto público: el paper documenta un sistema interno de DeepSeek, y el SDK unificado de FnCall, contenedor, microVM y VM completa no está liberado. Lo que sí es abierto, y sirve para entender de primera mano la pieza que sostiene la capa de datos de DSec, es &lt;a href="https://github.com/deepseek-ai/3FS" rel="noopener noreferrer"&gt;3FS&lt;/a&gt;, el sistema de archivos distribuido que DeepSeek publicó como open source.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clonar 3FS y preparar el build (Linux, requiere cmake y un compilador C++)&lt;/span&gt;
git clone https://github.com/deepseek-ai/3FS.git
&lt;span class="nb"&gt;cd &lt;/span&gt;3FS
&lt;span class="nb"&gt;mkdir &lt;/span&gt;build &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;build
cmake .. &lt;span class="nt"&gt;-DCMAKE_BUILD_TYPE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Release
make &lt;span class="nt"&gt;-j&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;nproc&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compilar 3FS da acceso al mismo tipo de sistema de archivos que, según el paper, DeepSeek DSec usa para cargar imágenes de sandbox bajo demanda en lugar de distribuir el paquete completo por cada entorno nuevo.&lt;/p&gt;

&lt;p&gt;Para entender el patrón de diseño que describe el paper, un SDK único que abstrae varios backends de aislamiento, este esquema conceptual ilustra la idea, aunque no es el código real de DeepSeek:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Esquema conceptual del patron descrito en el paper de DSec
# (DeepSeek no publico el SDK real; esto ilustra la idea)
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SandboxSpec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;backend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;        &lt;span class="c1"&gt;# "fncall" | "container" | "microvm" | "fullvm"
&lt;/span&gt;    &lt;span class="n"&gt;image_layers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;  &lt;span class="c1"&gt;# capas versionadas de forma independiente
&lt;/span&gt;    &lt;span class="n"&gt;memory_mb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;reclaimable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;    &lt;span class="c1"&gt;# si el scheduler puede reclamar memoria idle
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;request_sandbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SandboxSpec&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# la ubicacion se resuelve en el cluster y las capas
&lt;/span&gt;    &lt;span class="c1"&gt;# se cargan bajo demanda desde un filesystem tipo 3FS
&lt;/span&gt;    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para verificar que tu build de 3FS levantó correctamente el punto de montaje, el propio repositorio incluye herramientas de diagnóstico en su documentación; lo mínimo reproducible es confirmar que el mount responde antes de apoyar cualquier carga de imágenes sobre él.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Tip:&lt;/strong&gt; si solo querés leer el diseño sin compilar nada, el HTML experimental del paper en arXiv es más liviano de navegar que el PDF de 31 páginas.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Impacto y análisis
&lt;/h2&gt;

&lt;p&gt;El paper de DeepSeek DSec confirma algo que se viene discutiendo en la industria desde 2025: la infraestructura de sandboxing dejó de ser un detalle de implementación y pasó a ser un componente de investigación por derecho propio. OpenAI, Anthropic y Google han hablado de sus propios sistemas de ejecución de código para agentes, pero rara vez con el nivel de detalle operacional que DeepSeek publica acá: nodos por unidad, sandboxes por día, creaciones por segundo.&lt;/p&gt;

&lt;p&gt;Esa transparencia también es una señal competitiva. DeepSeek viene de una estrategia de abrir piezas de su stack, como 3FS, mientras mantiene el modelo entrenado como producto principal. Publicar el diseño de DSec sin liberar el código sigue ese mismo patrón: explica el cómo a nivel arquitectónico, sin entregar la implementación que le tomó a más de 130 ingenieros construir.&lt;/p&gt;

&lt;p&gt;Para equipos que hoy arman sus propios pipelines de RL agéntico, con herramientas open source o con proveedores cloud, el paper funciona como una lista de requisitos que hasta ahora nadie había puesto tan clara sobre la mesa: aislamiento configurable por tarea, reutilización de capas de imagen, coordinación explícita entre el scheduler de sandboxes y el de GPU, y defensas contra reward hacking en la capa de infraestructura. Ese último punto en particular no suele aparecer en los papers de frameworks de RL, que se concentran en la función de recompensa y no en el entorno que la ejecuta.&lt;/p&gt;

&lt;p&gt;La limitación más obvia, y el propio paper no la esconde, es que DSec está diseñado para el hardware y la red interna de DeepSeek. Los números de 160 nodos por unidad y 5.000 creaciones por segundo no garantizan que el mismo diseño escale igual de bien en un clúster más chico o en una nube pública genérica, donde la latencia de red hacia el filesystem distribuido puede ser muy distinta a la de una red interna de datacenter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;El paper fue sometido a la primera ronda de revisión del track de sistemas operacionales de ACM SIGOPS ATC 2026, organizado por &lt;a href="https://www.usenix.org" rel="noopener noreferrer"&gt;USENIX&lt;/a&gt;, así que es razonable esperar una versión revisada o una presentación en esa conferencia más adelante en el año. DeepSeek no anunció planes de liberar el SDK de DeepSeek DSec como hizo con 3FS, pero el patrón de publicar primero el paper y abrir después la pieza de infraestructura reutilizable ya se repitió una vez.&lt;/p&gt;

&lt;p&gt;Para el resto de la industria, el paper deja una pregunta abierta: si entrenar agentes de forma competitiva exige infraestructura de sandboxing a esta escala, cuántos laboratorios fuera de las grandes tech tienen margen para construir algo comparable, y cuántos van a depender de que un proveedor cloud empaquete esta capa como servicio.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: Ver resumen&lt;/p&gt;

&lt;p&gt;Si querés ver en la práctica la pieza abierta detrás de DeepSeek DSec, cloná el repositorio de 3FS y compilalo hoy mismo con los comandos de arriba.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es DSec, en una frase?
&lt;/h3&gt;

&lt;p&gt;Es la plataforma interna de DeepSeek que crea, coordina y destruye sandboxes para entrenar agentes con aprendizaje por refuerzo a gran escala.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿DSec es open source?
&lt;/h3&gt;

&lt;p&gt;No. El paper describe su diseño y arquitectura, pero DeepSeek no publicó el código del SDK ni de los backends. Sí es abierto 3FS, el sistema de archivos distribuido del que depende DSec para cargar imágenes.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué diferencia a DSec de correr contenedores comunes?
&lt;/h3&gt;

&lt;p&gt;DSec no usa un solo mecanismo de aislamiento: elige entre FnCall, contenedor, microVM o VM completa según qué tan confiable sea la tarea, y coordina eso con miles de sandboxes simultáneos y con el scheduler de GPU de entrenamiento, algo que un runtime de contenedores genérico no resuelve por sí solo.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es el reward hacking que menciona el paper?
&lt;/h3&gt;

&lt;p&gt;Es cuando un agente entrenado con RL encuentra una forma de maximizar su recompensa sin resolver realmente la tarea, por ejemplo manipulando el entorno de evaluación en lugar de completar el trabajo pedido.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es 3FS y por qué aparece en este paper?
&lt;/h3&gt;

&lt;p&gt;Es el sistema de archivos distribuido de DeepSeek, liberado como open source, que DSec usa para cargar bajo demanda los datos de imagen de cada sandbox en lugar de distribuir la imagen completa por red.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Dónde se puede leer el paper completo?
&lt;/h3&gt;

&lt;p&gt;Está publicado en arXiv, con acceso libre al PDF y a la versión HTML experimental, en &lt;a href="https://arxiv.org/abs/2609.22978" rel="noopener noreferrer"&gt;arxiv.org/abs/2609.22978&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://arxiv.org/abs/2609.22978" rel="noopener noreferrer"&gt;arXiv:2609.22978&lt;/a&gt;: paper original "DeepSeek Elastic Compute (DSec): A Sandbox Infrastructure for Effective Agentic Training at Scale".- &lt;a href="https://github.com/deepseek-ai/3FS" rel="noopener noreferrer"&gt;github.com/deepseek-ai/3FS&lt;/a&gt;: repositorio open source de 3FS, el sistema de archivos distribuido que alimenta a DSec.- &lt;a href="https://www.usenix.org" rel="noopener noreferrer"&gt;usenix.org&lt;/a&gt;: sitio oficial de USENIX, organización detrás de la conferencia ATC mencionada en el paper.- &lt;a href="https://en.wikipedia.org/wiki/Reinforcement_learning" rel="noopener noreferrer"&gt;Wikipedia: Reinforcement learning&lt;/a&gt;: contexto sobre la técnica de entrenamiento que sostiene la infraestructura de DSec.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>technology</category>
      <category>science</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>PipePipe: el fork de NewPipe con SponsorBlock llega a 6.200 estrellas</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sat, 26 Sep 2026 20:32:17 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/pipepipe-el-fork-de-newpipe-con-sponsorblock-llega-a-6200-estrellas-a5p</link>
      <guid>https://dev.to/lu1tr0n/pipepipe-el-fork-de-newpipe-con-sponsorblock-llega-a-6200-estrellas-a5p</guid>
      <description>&lt;p&gt;El repositorio de &lt;strong&gt;PipePipe&lt;/strong&gt; en GitHub acumula 6.200 estrellas, 212 forks y 51 observadores, cifras que lo consolidan como una alternativa consolidada para ver YouTube en Android sin pasar por Google Play. El proyecto nació a comienzos de 2022 como un fork completo de NewPipe, la app libre que permite navegar YouTube sin anuncios ni rastreo, y desde entonces sigue un desarrollo totalmente independiente.&lt;/p&gt;

&lt;p&gt;PipePipe suma funciones que NewPipe no tiene: bloqueo de segmentos patrocinados con SponsorBlock, restauración de los dislikes de YouTube, chats en vivo estilo danmaku y inicio de sesión opcional para contenido restringido. Todo bajo licencia GPL-3.0, sin publicidad ni recolección de datos.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;PipePipe es un hard fork de NewPipe iniciado a comienzos de 2022 y ya acumula 6.200 estrellas en GitHub.- El proyecto integra SponsorBlock para saltar segmentos patrocinados en YouTube y BiliBili.- Restaura los dislikes de YouTube mediante la API de ReturnYouTubeDislike.- Soporta decodificación AV1 y VP9 para reproducir video de alta calidad con menor consumo.- Permite iniciar sesión para acceder a contenido restringido, con cookies limitadas a escenarios específicos.- Se distribuye bajo licencia GPL-3.0 y no acepta solicitudes de nuevos servicios: invita a hacer fork propio.- El mantenedor no depende de financiamiento corporativo: se sostiene con donaciones vía Ko-fi y Liberapay.- A diferencia de forks como Tubular, PipePipe no sincroniza cambios con NewPipe desde la separación de 2022.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introducción a PipePipe
&lt;/h2&gt;

&lt;p&gt;PipePipe se presenta a sí mismo como &lt;em&gt;"NewPipe, reimaginado"&lt;/em&gt;: más rápido, más estable y con más funciones. Es una app Android de código abierto que reproduce YouTube y otros servicios de video sin pasar por las APIs oficiales de Google, evitando así anuncios, rastreo y el requisito de cuenta para la mayoría de las funciones.&lt;/p&gt;

&lt;p&gt;El catálogo de mejoras sobre NewPipe se agrupa en cinco áreas: mejoras específicas de YouTube, funciones de reproducción multimedia, filtrado de contenido, controles de reproducción y gestión avanzada de listas. Cada una resuelve una fricción concreta que los usuarios de apps de YouTube alternativas arrastran desde hace años.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué pasó
&lt;/h2&gt;

&lt;p&gt;El desarrollador InfinityLoop1308 forkeó NewPipe en 2022 por diferencias de filosofía de desarrollo con el proyecto original. Desde entonces, &lt;strong&gt;PipePipe&lt;/strong&gt; no recibe actualizaciones de NewPipe ni las envía de vuelta: son dos proyectos separados que evolucionan en paralelo. Un bug que aparece en NewPipe no necesariamente ocurre en PipePipe, y un cambio en NewPipe puede no ser adoptado nunca por PipePipe.&lt;/p&gt;

&lt;p&gt;Esa separación explica por qué el proyecto pudo incorporar funciones que NewPipe todavía no tiene: integración con SponsorBlock para saltar segmentos patrocinados en YouTube y BiliBili, restauración de dislikes con ReturnYouTubeDislike, visualización de títulos originales sin localizar, y la posibilidad de iniciar sesión para acceder a contenido restringido o premium.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contexto e historia
&lt;/h2&gt;

&lt;p&gt;NewPipe existe desde hace años como la alternativa libre más conocida para navegar YouTube sin telemetría, pero su ritmo de incorporación de funciones no convence a todos los usuarios. Ahí es donde se bifurcan los caminos: mientras forks como &lt;strong&gt;Tubular&lt;/strong&gt; optan por seguir de cerca la última versión de NewPipe y desarrollar sobre esa base, PipePipe eligió el camino de un &lt;em&gt;hard fork&lt;/em&gt;, cortando la sincronización desde el día uno.&lt;/p&gt;

&lt;p&gt;Esa decisión tiene un costo, mantener todo el trabajo de fusión de código en soledad, pero también una ventaja, permite corregir problemas con parches rápidos y sostener actualizaciones de funciones más frecuentes sin esperar consenso en el proyecto original. El repositorio incluye submódulos propios, &lt;code&gt;PipePipeExtractor&lt;/code&gt; y &lt;code&gt;PipePipeClient&lt;/code&gt;, que reemplazan a los equivalentes de NewPipe para tener control total del pipeline de extracción de datos.&lt;br&gt;
El proyecto no acepta solicitudes de nuevos servicios: invita a forkear el repositorio.&lt;/p&gt;
&lt;h2&gt;
  
  
  Detalles técnicos y rendimiento
&lt;/h2&gt;

&lt;p&gt;A nivel de reproducción, PipePipe soporta los codecs &lt;strong&gt;AV1 y VP9&lt;/strong&gt;, pensados para entregar video de alta calidad con un consumo de datos y batería más eficiente que H.264 en las mismas condiciones. También suma un modo de reproductor de música con reproducción en segundo plano, útil para escuchar contenido de YouTube como si fuera un reproductor de audio independiente.&lt;/p&gt;

&lt;p&gt;El filtrado es otro de los ejes fuertes: filtros de búsqueda avanzados, bloqueo de elementos por palabra clave o canal, y la opción de excluir directamente los Shorts y el contenido de pago del feed. A eso se suman gestos de reproducción, deslizar para adelantar o retroceder, pantalla completa gestual, mantener presionado para acelerar la velocidad, y un temporizador de apagado para quienes lo usan antes de dormir.&lt;/p&gt;

&lt;p&gt;Para explicar por qué existen varios forks de un mismo proyecto y qué relación guardan entre sí, este diagrama resume el árbol de derivación:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
    A["NewPipe (proyecto original)"] --&amp;gt; B["PipePipe (hard fork, 2022)"]
    A --&amp;gt; C["Tubular (sigue la ultima version de NewPipe)"]
    B --&amp;gt; D["SponsorBlock, ReturnYouTubeDislike, danmaku, AV1/VP9"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La siguiente tabla compara los tres proyectos de la familia NewPipe mencionados en la documentación oficial de PipePipe:&lt;br&gt;
ProyectoRelación con NewPipeVentajaLimitaciónNewPipeProyecto originalBase más probada y con mayor historialRitmo de nuevas funciones más conservadorPipePipeHard fork desde 2022, sin sincronizaciónSponsorBlock, dislikes, danmaku, AV1/VP9, login opcionalMantenimiento en solitario, sin recibir parches de NewPipeTubularFork que sigue la última versión de NewPipeHereda correcciones y cambios de NewPipe automáticamenteConjunto de funciones más cercano al original&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💭 Clave:&lt;/strong&gt; la diferencia entre un fork que sincroniza y uno que no es la que explica por qué dos apps que parten del mismo código terminan comportándose de forma completamente distinta un año después.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Cómo empezar a usar PipePipe
&lt;/h2&gt;

&lt;p&gt;PipePipe no está en Google Play, así que la instalación se hace desde el APK publicado en el repositorio oficial de &lt;a href="https://github.com/InfinityLoop1308/PipePipe" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. El proceso es el mismo sideloading que usan NewPipe y otras apps libres para Android.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Habilitar "Instalar apps desconocidas" en Ajustes &amp;gt; Apps &amp;gt; acceso especial&lt;/span&gt;
&lt;span class="c"&gt;# 2. Descargar el APK desde la seccion Releases del repositorio oficial&lt;/span&gt;
&lt;span class="c"&gt;# 3. Instalar via adb desde tu computadora (opcional, el mismo comando en los tres sistemas):&lt;/span&gt;

&lt;span class="c"&gt;# Windows (PowerShell, tras instalar Android SDK Platform Tools)&lt;/span&gt;
adb &lt;span class="nb"&gt;install &lt;/span&gt;pipepipe.apk

&lt;span class="c"&gt;# macOS (con Homebrew)&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;android-platform-tools
adb &lt;span class="nb"&gt;install &lt;/span&gt;pipepipe.apk

&lt;span class="c"&gt;# Linux (Debian/Ubuntu)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;android-tools-adb
adb &lt;span class="nb"&gt;install &lt;/span&gt;pipepipe.apk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para quienes quieren compilar la app desde el código fuente en vez de usar el APK precompilado, el repositorio usa submódulos de git para el extractor y el cliente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--recurse-submodules&lt;/span&gt; https://github.com/InfinityLoop1308/PipePipe.git
&lt;span class="nb"&gt;cd &lt;/span&gt;PipePipe
./gradlew assembleDebug
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El comando anterior genera un APK de depuración en &lt;code&gt;app/build/outputs/apk/debug/&lt;/code&gt;, listo para instalar con &lt;code&gt;adb install&lt;/code&gt;. Es el mismo flujo en Windows, macOS y Linux porque Gradle Wrapper resuelve las dependencias de forma idéntica en los tres sistemas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; descargá el APK únicamente desde el repositorio oficial en GitHub. Los clones o mirrors no verificados de apps que acceden a YouTube son un vector habitual de malware en Android.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Impacto y análisis
&lt;/h2&gt;

&lt;p&gt;Lo que distingue a PipePipe de una app de YouTube alternativa más es la postura sobre el login: la sesión iniciada solo se usa para escenarios que el propio usuario configura en "Cookie Functions", y en el caso de YouTube ese uso se limita a la recuperación de streams de reproducción. No hay telemetría ni recolección de datos de uso hacia el desarrollador.&lt;/p&gt;

&lt;p&gt;El modelo de sostenibilidad también marca una diferencia frente a apps comerciales: el proyecto se financia con donaciones a través de &lt;a href="https://ko-fi.com/pipepipe" rel="noopener noreferrer"&gt;Ko-fi&lt;/a&gt; y Liberapay, sin publicidad integrada ni acuerdos comerciales visibles. El mantenedor es explícito en que no acepta pedidos de servicio, es decir, si un usuario quiere que se agregue soporte para una plataforma nueva, la respuesta oficial es forkear el repositorio y hacerlo uno mismo.&lt;/p&gt;

&lt;p&gt;Esa política tiene un costado incómodo: cierra la puerta a que la comunidad general oriente el roadmap con pedidos puntuales, y concentra las decisiones de qué se integra en una sola persona. A cambio, evita que el proyecto se disperse manteniendo integraciones de baja demanda que nadie termina de sostener.&lt;br&gt;
El wiki del proyecto es mantenido por un colaborador externo, @Priveetee, separado del desarrollo del código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;El desarrollo de PipePipe sigue activo con contribuciones puntuales de la comunidad: el usuario @Priveetee investigó el soporte de SABR (el nuevo esquema de streaming de YouTube) y mantiene además el &lt;a href="https://github.com/InfinityLoop1308/PipePipe" rel="noopener noreferrer"&gt;wiki del proyecto&lt;/a&gt;, mientras que @AioiLight aportó código para el soporte del servicio NicoNico. El repositorio acepta issues y pull requests de forma abierta, aunque sin compromisos de aceptar integraciones de nuevos servicios de video.&lt;/p&gt;

&lt;p&gt;Mientras YouTube sigue endureciendo las restricciones sobre reproducción de streams fuera de su app oficial, la vigencia de proyectos como PipePipe depende de que el extractor propio, &lt;code&gt;PipePipeExtractor&lt;/code&gt;, se mantenga al día con cada cambio del lado del servidor. Es un trabajo constante que no tiene fecha de finalización.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: Ver resumen&lt;/p&gt;

&lt;p&gt;Probalo vos: cloná el repositorio y corré &lt;code&gt;./gradlew assembleDebug&lt;/code&gt;, o bajá el APK directo desde la sección Releases de &lt;a href="https://github.com/InfinityLoop1308/PipePipe" rel="noopener noreferrer"&gt;github.com/InfinityLoop1308/PipePipe&lt;/a&gt; para verlo funcionar hoy mismo en tu Android.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es PipePipe?
&lt;/h3&gt;

&lt;p&gt;Es una app Android de código abierto, fork de NewPipe, que permite ver YouTube y otros servicios de video sin anuncios, sin cuenta obligatoria y sin pasar por Google Play.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Está disponible en Google Play?
&lt;/h3&gt;

&lt;p&gt;No. Se instala mediante sideloading, descargando el APK directamente desde la sección Releases del repositorio oficial en GitHub.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Es seguro iniciar sesión con mi cuenta de Google en PipePipe?
&lt;/h3&gt;

&lt;p&gt;El login es opcional y su uso está acotado: para YouTube, la cookie de sesión solo se emplea al recuperar streams de reproducción, según la documentación del proyecto. El alcance se configura en "Cookie Functions".&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿En qué se diferencia PipePipe de NewPipe?
&lt;/h3&gt;

&lt;p&gt;PipePipe es un hard fork sin sincronización desde 2022: no recibe actualizaciones de NewPipe ni las envía de vuelta, y suma funciones propias como SponsorBlock, restauración de dislikes y chats danmaku que NewPipe no tiene.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es SponsorBlock y cómo lo usa PipePipe?
&lt;/h3&gt;

&lt;p&gt;SponsorBlock es una base de datos comunitaria que marca segmentos patrocinados dentro de videos. PipePipe la integra de forma nativa para saltar automáticamente esos tramos en YouTube y BiliBili.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo se financia el desarrollo de PipePipe?
&lt;/h3&gt;

&lt;p&gt;Exclusivamente con donaciones de la comunidad a través de Ko-fi y Liberapay, sin publicidad dentro de la app ni patrocinios visibles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/InfinityLoop1308/PipePipe" rel="noopener noreferrer"&gt;github.com/InfinityLoop1308/PipePipe&lt;/a&gt;: repositorio oficial del proyecto, fuente principal de este artículo.- &lt;a href="https://github.com/TeamNewPipe/NewPipe" rel="noopener noreferrer"&gt;github.com/TeamNewPipe/NewPipe&lt;/a&gt;: repositorio del proyecto original del que parte el fork.- &lt;a href="https://github.com/ajayyy/SponsorBlock" rel="noopener noreferrer"&gt;github.com/ajayyy/SponsorBlock&lt;/a&gt;: proyecto SponsorBlock integrado en PipePipe.- &lt;a href="https://ko-fi.com/pipepipe" rel="noopener noreferrer"&gt;ko-fi.com/pipepipe&lt;/a&gt;: página de donaciones al mantenedor del proyecto.- liberapay.com/PipePipe: alternativa de donaciones recurrentes al proyecto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>technology</category>
      <category>science</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Líderes tech piden a la ONU controlar la IA ante el aumento de riesgos</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sat, 26 Sep 2026 16:21:44 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/lideres-tech-piden-a-la-onu-controlar-la-ia-ante-el-aumento-de-riesgos-4076</link>
      <guid>https://dev.to/lu1tr0n/lideres-tech-piden-a-la-onu-controlar-la-ia-ante-el-aumento-de-riesgos-4076</guid>
      <description>&lt;p&gt;Más de 200 empresarios y científicos tech firmaron esta semana una carta abierta dirigida a la ONU en la que piden, en sus palabras, controlar la tecnología de inteligencia artificial "por el bien de la humanidad". La carta llega en medio de una ola de declaraciones cruzadas sobre los riesgos de la IA: desde Jensen Huang, CEO de Nvidia, cuestionando las cifras que usan los sectores más alarmistas, hasta congresistas de Estados Unidos que afirman que esos riesgos ya dejaron de ser ciencia ficción.&lt;/p&gt;

&lt;p&gt;El episodio resume un año en el que buena parte de la industria pasó de resistirse a cualquier regulación a pedir, en público, que alguien ponga límites. Para quien sigue de cerca la carrera de la IA, entender quién dice qué y por qué ya no es opcional.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cientos de líderes tech firmaron una carta a la ONU pidiendo controlar el desarrollo de la IA por el bien de la humanidad.- Jensen Huang, CEO de Nvidia, calificó de no científica una cifra clave que circula en el debate sobre riesgos de la IA.- El congresista Ted Lieu advirtió que los riesgos de la IA ya no pertenecen a la ciencia ficción.- NPR publicó una guía para entender las distintas facciones que discuten sobre la seguridad de la IA en 2026.- Un asesor científico de la Casa Blanca discutió públicamente los guardrails que evalúa para sistemas de IA.- Universidades como Indiana University refuerzan la ciberseguridad ante los riesgos que la IA introduce en la investigación.- Un informe advirtió que las ganancias de productividad de la IA en ciencia se reducen por el tiempo dedicado a validar resultados.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué pasó: el debate sobre los riesgos de la IA llega a la ONU
&lt;/h2&gt;

&lt;p&gt;Según reportó Associated Press, la carta reúne firmas de fundadores, investigadores y ejecutivos que piden a Naciones Unidas &lt;a href="https://www.msn.com/en-us/news/other/tech-leaders-to-un-for-the-sake-of-humanity-please-control-the-ai-technology-we-created/ar-AA2cQ6wn" rel="noopener noreferrer"&gt;controlar el desarrollo de la inteligencia artificial&lt;/a&gt; antes de que la carrera entre laboratorios se vuelva irreversible. El texto no detalla un mecanismo legal concreto, pero eleva el tono: ya no habla de "principios" sino de control directo.&lt;/p&gt;

&lt;p&gt;Casi en simultáneo, Jensen Huang salió a cuestionar una de las cifras más repetidas en el debate. Según &lt;a href="https://finance.yahoo.com/technology/ai/articles/huang-says-1-number-ai-153300124.html" rel="noopener noreferrer"&gt;Yahoo Finance&lt;/a&gt;, el CEO de Nvidia afirmó que ese número, usado para dimensionar el riesgo de la IA, no tiene base científica. Huang no ofreció una cifra alternativa, pero su declaración expone la tensión entre quienes construyen los modelos y quienes advierten sobre sus consecuencias.&lt;/p&gt;

&lt;p&gt;El contrapunto llegó desde el Congreso. El representante Ted Lieu declaró a Politico que los riesgos de la IA "ya no pertenecen al terreno de la ciencia ficción", y pidió a sus colegas tratar el tema con la misma urgencia que otros riesgos tecnológicos regulados desde hace décadas.&lt;br&gt;
Más de 200 firmantes pidieron a la ONU controlar el desarrollo de la IA esta semana.&lt;/p&gt;
&lt;h2&gt;
  
  
  Contexto e historia: de las advertencias privadas a la carta pública
&lt;/h2&gt;

&lt;p&gt;El debate sobre los riesgos de la inteligencia artificial no es nuevo, pero su tono cambió en 2026. Durante años las advertencias más fuertes venían de investigadores independientes o de cartas firmadas puertas adentro; ahora la ONU y el Congreso de Estados Unidos las discuten en público, con nombres y cargos.&lt;/p&gt;

&lt;p&gt;Semanas antes, la ONU ya había dado un paso en esa dirección al crear un panel científico dedicado a la inteligencia artificial, inspirado en el modelo del IPCC climático. La nueva carta de los líderes tech añade presión desde el sector privado, el mismo que hasta hace poco pedía explícitamente que los reguladores no tocaran los modelos abiertos.&lt;/p&gt;

&lt;p&gt;Para ordenar el ruido, &lt;a href="https://www.npr.org/2026/09/26/nx-s1-5979085/the-ai-safety-debate-is-confusing-heres-our-guide-to-the-different-factions" rel="noopener noreferrer"&gt;NPR publicó una guía&lt;/a&gt; que agrupa a los participantes del debate en facciones con intereses y diagnósticos distintos. Es un mapa útil porque explica por qué la misma pregunta (¿cuánto riesgo hay?) recibe respuestas tan opuestas según quién la responda.&lt;/p&gt;
&lt;h2&gt;
  
  
  Las facciones del debate sobre los riesgos de la IA
&lt;/h2&gt;

&lt;p&gt;Simplificando la guía de NPR, el debate se puede leer en cuatro bloques. Ninguno es monolítico (dentro de cada uno hay matices), pero la tabla ayuda a ubicar cada declaración pública en su contexto.&lt;br&gt;
FacciónDiagnóstico centralEjemplo recienteQué proponenRiesgo existencialLa IA avanzada puede escapar al control humanoFirmantes de la carta a la ONUTratados internacionales y límites de cómputoAceleracionistasEl riesgo real es quedarse atrás, no la IA mismaSector que financia cómputo sin frenoMenos regulación, más inversiónEscépticos de las cifrasLos números de riesgo no tienen base científica sólidaJensen HuangDebate basado en evidencia, no en proyeccionesRegulación institucionalEl riesgo es real y requiere marcos legales yaTed Lieu y otros legisladoresLeyes y supervisión desde el Congreso&lt;/p&gt;
&lt;h2&gt;
  
  
  Cómo seguir el debate con fuentes primarias
&lt;/h2&gt;

&lt;p&gt;Seguir este debate en tiempo real no requiere esperar a que un medio lo resuma. El texto de la carta, los proyectos de ley y los papers de seguridad son consultables directamente con herramientas simples.&lt;/p&gt;

&lt;p&gt;Para rastrear qué proyectos de ley relacionados con IA se mueven en el Congreso de Estados Unidos, la API pública de congress.gov permite buscar por palabra clave:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.congress.gov/v3/bill?query=artificial+intelligence&amp;amp;api_key=&lt;/span&gt;&lt;span class="nv"&gt;$CONGRESS_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Accept: application/json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La respuesta incluye el número de proyecto, su estado y los legisladores que lo copatrocinan: el tipo de dato que respalda declaraciones como la de Ted Lieu.&lt;/p&gt;

&lt;p&gt;Para el lado académico del debate, el que alimenta tanto a los que hablan de riesgo existencial como a los escépticos, arXiv expone una API REST sin necesidad de autenticación:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;feedparser&lt;/span&gt;

&lt;span class="n"&gt;feed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;feedparser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://export.arxiv.org/api/query?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_query=cat:cs.CY+AND+abs:AI+safety&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;amp;sortBy=submittedDate&amp;amp;sortOrder=descending&amp;amp;max_results=10&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;feed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;published&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El campo &lt;code&gt;entry.published&lt;/code&gt; trae la fecha exacta: si el paper que alguien cita en redes tiene más de un año, probablemente ya fue superado por trabajo más reciente.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Tip:&lt;/strong&gt; antes de compartir una cifra de riesgo de IA, buscá el paper o informe original con estas dos herramientas. La mayoría de las cifras virales pierden el contexto metodológico en el camino.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Impacto y análisis
&lt;/h2&gt;

&lt;p&gt;La carta a la ONU contrasta con la postura que gran parte de la misma industria mantuvo meses atrás, cuando pidió a Washington no restringir los modelos de pesos abiertos. La contradicción no es necesariamente hipocresía: regular el desarrollo de sistemas de frontera y frenar la distribución de modelos abiertos son pedidos distintos, aunque ambos usan las palabras "seguridad" y "riesgo".&lt;br&gt;
El Congreso de Estados Unidos discute cada vez más proyectos de ley sobre inteligencia artificial.&lt;br&gt;
Universidades como Indiana University ya reaccionan en la práctica: sus equipos de ciberseguridad &lt;a href="https://news.iu.edu/live/news/53166-as-ai-transforms-science-and-research-iu" rel="noopener noreferrer"&gt;refuerzan las defensas de la investigación&lt;/a&gt; frente a los riesgos que la propia IA introduce en el proceso científico, desde datos sintéticos contaminados hasta agentes que ejecutan código sin supervisión.&lt;/p&gt;

&lt;p&gt;Un informe de THE Journal &lt;a href="https://thejournal.com/articles/2026/09/23/report-ais-productivity-gains-in-science-tempered-by-time-spent-validating-outputs.aspx" rel="noopener noreferrer"&gt;encontró que las ganancias de productividad que la IA aporta a la ciencia se ven recortadas por el tiempo que los investigadores deben dedicar a validar cada resultado&lt;/a&gt;. Ese hallazgo es, en el fondo, la misma tensión del debate político: la promesa y el riesgo de la IA crecen juntos, y validar cuesta tiempo real.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📌 Nota:&lt;/strong&gt; ningún actor citado publicó una cifra de probabilidad de riesgo verificable de forma independiente. Las declaraciones de Huang y de los firmantes de la carta son, hasta ahora, posiciones cualitativas.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;En el corto plazo, la carta a la ONU no obliga a nada: es una declaración de intención, no un tratado. Su peso real se va a medir en si la Asamblea General le da lugar en su agenda y si el panel científico de IA que ya existe la toma como insumo. En el Congreso de Estados Unidos, la pregunta es si declaraciones como la de Ted Lieu se traducen en proyectos de ley concretos o quedan en audiencias sin votación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
    A["Carta de líderes tech"] --&amp;gt; B["Asamblea General de la ONU"]
    B --&amp;gt; C["Panel científico de IA"]
    D["Ted Lieu y el Congreso"] --&amp;gt; E["Proyectos de ley sobre IA"]
    C --&amp;gt; F["Posible marco internacional"]
    E --&amp;gt; F
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Del lado técnico, un asesor científico de la Casa Blanca ya adelantó en público qué tipo de guardrails evalúa la administración, aunque sin comprometerse a un cronograma. Mientras tanto, cada nuevo modelo de frontera que se publique va a reabrir la misma pregunta: quién decide cuánto riesgo es aceptable.&lt;/p&gt;

&lt;p&gt;Probalo vos: leé el texto completo de la carta a la ONU o corré la consulta a la API de arXiv de arriba y sacá tus propias conclusiones sobre qué tan sólida es la evidencia detrás de cada bando.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: Ver resumen&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué pide exactamente la carta de los líderes tech a la ONU?
&lt;/h3&gt;

&lt;p&gt;Pide que Naciones Unidas controle el desarrollo de la inteligencia artificial "por el bien de la humanidad", según el texto citado por Associated Press, aunque no propone un mecanismo legal específico.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué número cuestionó Jensen Huang?
&lt;/h3&gt;

&lt;p&gt;Huang no precisó la cifra exacta, pero según Yahoo Finance calificó de no científico un número que circula en el debate público sobre los riesgos de la IA.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué dijo Ted Lieu sobre los riesgos de la IA?
&lt;/h3&gt;

&lt;p&gt;El congresista declaró a Politico que esos riesgos ya no pertenecen al terreno de la ciencia ficción y pidió tratarlos con urgencia legislativa.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿La ONU ya tiene un panel de IA?
&lt;/h3&gt;

&lt;p&gt;Sí, Naciones Unidas creó semanas antes un panel científico de inteligencia artificial inspirado en el modelo del IPCC climático, que podría servir de canal para la nueva carta.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo puedo seguir el debate sin depender de resúmenes?
&lt;/h3&gt;

&lt;p&gt;Con las APIs públicas de congress.gov y arXiv que se muestran en este artículo podés rastrear proyectos de ley y papers de seguridad directamente desde la fuente.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Esto afecta a los modelos de código abierto?
&lt;/h3&gt;

&lt;p&gt;No de forma directa: la carta habla del desarrollo de la IA en general, mientras que el debate sobre modelos abiertos, que gran parte de la industria pidió no restringir, es una discusión separada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.msn.com/en-us/news/other/tech-leaders-to-un-for-the-sake-of-humanity-please-control-the-ai-technology-we-created/ar-AA2cQ6wn" rel="noopener noreferrer"&gt;Associated Press vía MSN&lt;/a&gt;: texto de la carta de líderes tech a la ONU.- &lt;a href="https://finance.yahoo.com/technology/ai/articles/huang-says-1-number-ai-153300124.html" rel="noopener noreferrer"&gt;Yahoo Finance&lt;/a&gt;: declaraciones de Jensen Huang sobre las cifras del debate de riesgo de IA.- Politico: entrevista al congresista Ted Lieu sobre los riesgos de la IA.- &lt;a href="https://www.npr.org/2026/09/26/nx-s1-5979085/the-ai-safety-debate-is-confusing-heres-our-guide-to-the-different-factions" rel="noopener noreferrer"&gt;NPR&lt;/a&gt;: guía sobre las facciones del debate de seguridad de la IA.- &lt;a href="https://news.iu.edu/live/news/53166-as-ai-transforms-science-and-research-iu" rel="noopener noreferrer"&gt;News at IU&lt;/a&gt;: cómo Indiana University refuerza la ciberseguridad ante los riesgos de la IA en investigación.- &lt;a href="https://thejournal.com/articles/2026/09/23/report-ais-productivity-gains-in-science-tempered-by-time-spent-validating-outputs.aspx" rel="noopener noreferrer"&gt;THE Journal&lt;/a&gt;: informe sobre cómo la validación de resultados reduce las ganancias de productividad de la IA en ciencia.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Ayman Nadeem cierra Nuanced, su app de plan mode para programar con IA</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sat, 26 Sep 2026 14:37:19 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/ayman-nadeem-cierra-nuanced-su-app-de-plan-mode-para-programar-con-ia-2p9i</link>
      <guid>https://dev.to/lu1tr0n/ayman-nadeem-cierra-nuanced-su-app-de-plan-mode-para-programar-con-ia-2p9i</guid>
      <description>&lt;p&gt;Un desarrollador construyó una aplicación entera alrededor del plan mode, la cerró meses después y ahora sostiene que esa función, tal como la conocemos, ya murió.&lt;/p&gt;

&lt;p&gt;El 24 de septiembre de 2026, Ayman Nadeem, fundador de la app de código Nuanced, publicó el ensayo &lt;a href="https://www.aymannadeem.com/artificial/intelligence,/developer/tools/2026/09/24/plan-mode-is-dead.html" rel="noopener noreferrer"&gt;"Plan mode is dead"&lt;/a&gt;. Ahí explica por qué construir un producto entero sobre el plan mode fue un error, y qué necesitan de verdad los equipos que programan con agentes de IA en paralelo.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ayman Nadeem, fundador de la app de código Nuanced, publicó el 24 de septiembre de 2026 el ensayo "Plan mode is dead".- Nuanced apostó todo su producto al plan mode: convertir cada plan en un documento persistente antes de escribir código.- Según Nadeem, el plan mode cumplía dos funciones históricas: dar instrucciones precisas al agente y ayudar al humano a entender el sistema.- La primera función se vuelve obsoleta a medida que los modelos mejoran solos; la segunda importa más, pero el plan mode es la abstracción equivocada.- Nadeem cita 4 causas del fracaso: confundir plan con planificar, mejores modelos, rechazo a texto de IA y una separación disruptiva de tareas.- Antes de Nuanced, Nadeem probó Claude Code CLI, Conductor y Codex como herramientas de planificación.- El problema se agrava con varios agentes en paralelo: sin trazabilidad, nadie entiende qué decisión tomó cada uno.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué pasó
&lt;/h2&gt;

&lt;p&gt;Nadeem lanzó Nuanced con una apuesta concreta: cada conversación con un agente de código debía convertirse en un documento persistente de planificación antes de tocar una sola línea de código. La idea nació de una fricción real. Cuando trabajaba con Claude Code CLI, Conductor y luego Codex, terminaba copiando fragmentos de un plan de un chat a otro para revisarlo, un flujo que describe como incómodo y difícil de sostener mientras maduraba una idea.&lt;/p&gt;

&lt;p&gt;Meses después, Nadeem concluyó que el producto no resolvió el problema que buscaba resolver. En su ensayo lista un motivo central: confundió planificar (el proceso de pensar) con un plan (el artefacto de texto resultante). Preservar ese artefacto en un documento grande no capturó el valor real, que estaba en el proceso de pensar en voz alta junto al agente.&lt;br&gt;
Nuanced buscaba convertir cada plan en un documento persistente, no en un chat efímero.&lt;/p&gt;
&lt;h2&gt;
  
  
  Contexto e historia: por qué alguien construiría una app entera para planificar
&lt;/h2&gt;

&lt;p&gt;La motivación de fondo, según cuenta Nadeem, era una pregunta que sigue vigente: ¿cómo mantiene un humano un modelo mental coherente de un sistema de software mientras una máquina lo cambia más rápido de lo que ese humano puede inspeccionar los cambios? Los modelos actuales pueden escribir miles de líneas en minutos, lo que significa heredar una carga de mantenimiento enorme antes de terminar de pensar qué se estaba construyendo o por qué.&lt;/p&gt;

&lt;p&gt;Nadeem describe ese proceso como generador de una recompensa inmediata (ver código funcionando rápido) que a la vez ocultaba el trabajo incómodo de decidir si algo importaba de verdad, o de evaluar con rigor decisiones de producto, diseño e infraestructura. Cuando la arquitectura quedaba subespecificada, el agente rellenaba los huecos a su manera, y esas decisiones se propagaban por varios archivos, muy por debajo de lo que se veía en el chat.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💭 Clave:&lt;/strong&gt; Nadeem dice que correr varios agentes en paralelo, algo que herramientas como Conductor y Codex ya permitían, lo dejaba con una sensación de desconexión: podía generar código a mayor velocidad de la que podía verificarlo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esa fue la falla que Nuanced intentó resolver: no había un rastro claro entre el prompt del usuario, la decisión del agente, el código resultante y el comportamiento final del producto. Nadeem no quería volver a leer archivo por archivo; quería razonar en lenguaje natural sin perder el control de cómo funcionaba el sistema.&lt;/p&gt;
&lt;h2&gt;
  
  
  Detalles técnicos del plan mode: dos funciones, una abstracción rota
&lt;/h2&gt;

&lt;p&gt;El argumento técnico central del ensayo separa dos funciones que el plan mode cumplió históricamente en herramientas de código con IA. La primera es operativa: darle al agente instrucciones lo bastante precisas para ejecutar bien una tarea. La segunda es humana: ayudar a la persona a entender qué se está construyendo antes de que exista.&lt;/p&gt;

&lt;p&gt;Nadeem sostiene que la primera función pierde relevancia rápido a medida que los modelos mejoran solos, porque necesitan cada vez menos andamiaje explícito para interpretar una intención ambigua. La segunda función, en cambio, importa más que nunca, sobre todo cuando un developer corre varios agentes en paralelo y necesita saber qué decidió cada uno. El problema es que el plan mode, como artefacto de texto encerrado en una conversación de chat, es la abstracción equivocada para resolver ese segundo problema.&lt;/p&gt;

&lt;p&gt;La siguiente tabla resume los enfoques que hoy compiten para resolver el mismo problema: mantener a un humano al tanto de lo que un agente está construyendo.&lt;br&gt;
EnfoqueDónde vive el planQué resuelve bienLimitación principalPlan mode nativo (ej. Claude Code)Dentro de la sesión de chat, efímeroFrena al agente antes de escribir código mal alineado con la intenciónSe pierde en el historial del chat cuando la conversación avanzaDocumento persistente (CLAUDE.md, AGENTS.md, PLAN.md)Un archivo versionado dentro del repositorioDa contexto estable entre sesiones y entre agentes que corren en paraleloAlguien tiene que mantenerlo actualizado a manoRevisión de diffs después del hechoDespués de que el agente ya escribió códigoRápido cuando el cambio es chico y acotadoNo sirve si el agente ya tomó decenas de decisiones de diseño ocultasCortar y pegar entre chats (el flujo que describe Nadeem antes de Nuanced)Fragmentos de texto que el humano mueve a manoNo requiere ninguna herramienta especialLento, y se pierde la versión anterior del plan en cada copia&lt;br&gt;
El siguiente diagrama ilustra por qué un plan efímero dentro del chat se pierde, mientras que un documento persistente sí puede alimentar a varios agentes a la vez:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
A["Intencion del developer"] --&amp;gt; B["Conversacion con el agente"]
B --&amp;gt; C["Plan dentro del chat"]
C --&amp;gt; D["Se pierde en el historial"]
B --&amp;gt; E["Documento persistente (PLAN.md)"]
E --&amp;gt; F["Agente 1 implementa"]
E --&amp;gt; G["Agente 2 revisa"]
E --&amp;gt; H["Agente 3 corre tests"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El plan mode nativo vive dentro del chat; un archivo versionado sobrevive a la sesión.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cómo probarlo hoy
&lt;/h2&gt;

&lt;p&gt;El plan mode de Claude Code sigue disponible y sirve como punto de partida concreto, incluso si el argumento de Nadeem es que no alcanza por sí solo. Para instalarlo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# macOS / Linux&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://claude.ai/install.sh | bash

&lt;span class="c"&gt;# Windows (PowerShell)&lt;/span&gt;
irm https://claude.ai/install.ps1 | iex

&lt;span class="c"&gt;# alternativa multiplataforma via npm&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @anthropic-ai/claude-code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dentro de una sesión, alternar a modo planificación deja a Claude Code investigar el repositorio sin escribir código todavía, y solo pasa a implementar cuando el plan queda aprobado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;claude
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;Shift+Tab dos veces activa el plan mode&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;⏸ plan mode on
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Migra el checkout de programacion-store de Stripe Checkout a Stripe Elements
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La recomendación que se desprende del ensayo de Nadeem es no dejar ese plan atrapado en el chat. Conviene volcarlo en un archivo versionado del repositorio para que sobreviva a la sesión y esté disponible para el próximo agente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Objetivo&lt;/span&gt;
Migrar el checkout de programacion-store de Stripe Checkout a Stripe Elements

&lt;span class="gu"&gt;## Decisiones tomadas&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; [2026-09-20] Usamos Payment Element en vez de Card Element: soporta wallets locales sin codigo extra
&lt;span class="p"&gt;-&lt;/span&gt; [2026-09-22] El webhook de confirmacion vive en /api/webhooks/stripe, separado del handler que crea el pago

&lt;span class="gu"&gt;## Pendiente de decidir&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Que hacemos con los pagos en efectivo (OXXO, PagoEfectivo) que hoy dependen de Checkout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para confirmar que un agente está leyendo ese documento y no solo el prompt suelto, basta con pedirle explícitamente que cite una línea del archivo antes de tocar código; si no puede citarla, el archivo no está en su contexto.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Tip:&lt;/strong&gt; Nombrá el archivo de plan con la fecha o el número de ticket (por ejemplo PLAN-2026-09-checkout.md) para que sobreviva a varias iteraciones sin que un agente lo sobrescriba por error.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Impacto y análisis para equipos en LATAM
&lt;/h2&gt;

&lt;p&gt;Para equipos que ya integraron agentes de código al flujo diario, el argumento de Nadeem tiene una consecuencia práctica: dejar de medir la calidad de un flujo de trabajo por lo elaborado que sea el plan mode de una herramienta, y empezar a medirla por qué tan fácil es reconstruir después por qué se tomó una decisión. Eso importa más en equipos distribuidos de LATAM que coordinan trabajo asíncrono entre husos horarios, donde nadie puede simplemente preguntarle al compañero qué decidió el agente a las 3 de la mañana.&lt;/p&gt;

&lt;p&gt;También cambia qué se prioriza al elegir herramientas. Un plan mode vistoso dentro de un chat no sirve de nada si desaparece apenas se cierra la sesión; un archivo simple como CLAUDE.md o AGENTS.md, versionado junto al código y leído por cualquier agente que entre al repositorio, resuelve más del problema real con menos infraestructura.&lt;/p&gt;

&lt;p&gt;El costo de no resolverlo bien es real: Nadeem describe explícitamente la sensación de generar código más rápido de lo que podía verificarlo, y de perder la capacidad de detectar cuándo un supuesto incorrecto ya se había convertido en código antes de que alguien lo notara.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;Nadeem no propone volver a revisar línea por línea. Su conclusión apunta a herramientas que traten el plan como un documento vivo dentro del flujo normal de trabajo, no un modo aparte que se activa y desactiva, y que ese documento quede disponible para cualquier cantidad de agentes que trabajen en paralelo sobre el mismo repositorio. La tendencia más amplia en la industria de desarrollo asistido por IA va en esa dirección: mover el contexto de la conversación efímera hacia artefactos versionados que cualquier agente, humano o no, pueda leer sin depender de un historial de chat.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: Ver resumen&lt;/p&gt;

&lt;p&gt;Probalo vos: instalá Claude Code con el comando de arriba, activá el plan mode con Shift+Tab y compará cuánto de ese plan sobrevive si lo dejás solo en el chat contra si lo volcás en un archivo del repositorio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ¿Qué es el plan mode en herramientas como Claude Code?
&lt;/h3&gt;

&lt;p&gt;Es un modo de trabajo en el que el agente investiga el código y propone un plan de cambios antes de escribir una sola línea, y espera aprobación explícita del developer para pasar a implementar.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Por qué Ayman Nadeem dice que fracasó su app Nuanced?
&lt;/h3&gt;

&lt;p&gt;Porque confundió planificar, el proceso de pensar junto al agente, con un plan, el documento resultante, y preservar ese documento no capturó el valor real que buscaban los usuarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿El plan mode ya no sirve para nada en septiembre de 2026?
&lt;/h3&gt;

&lt;p&gt;Sigue siendo útil para frenar a un agente antes de que escriba código mal alineado con la intención del developer, pero según Nadeem no resuelve por sí solo el problema de mantener un entendimiento humano del sistema a través del tiempo y de varios agentes.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué diferencia hay entre planificar y un plan, según este argumento?
&lt;/h3&gt;

&lt;p&gt;Planificar es el proceso de pensar en voz alta con el agente para llegar a decisiones; un plan es apenas el texto que queda después de ese proceso. Nadeem sostiene que Nuanced optimizó el artefacto y no el proceso.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Qué es AGENTS.md y por qué aparece en este debate?
&lt;/h3&gt;

&lt;p&gt;Es un archivo de convenciones e instrucciones persistentes para agentes de código, alternativo o complementario a CLAUDE.md, que varias herramientas ya leen automáticamente al abrir un repositorio.&lt;/p&gt;

&lt;h3&gt;
  
  
  ¿Cómo aplico esto hoy si corro varios agentes en paralelo?
&lt;/h3&gt;

&lt;p&gt;Convertí el plan de cada tarea en un archivo Markdown versionado dentro del repo antes de lanzar el segundo agente, y pedile a cada agente que cite una línea de ese archivo antes de empezar a escribir código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.aymannadeem.com/artificial/intelligence,/developer/tools/2026/09/24/plan-mode-is-dead.html" rel="noopener noreferrer"&gt;Plan mode is dead, Ayman Nadeem&lt;/a&gt;: el ensayo original que documenta el cierre de Nuanced y el argumento contra el plan mode como abstracción.- &lt;a href="https://www.anthropic.com/claude-code" rel="noopener noreferrer"&gt;Claude Code, Anthropic&lt;/a&gt;: página oficial de la CLI de código agéntico que incluye plan mode nativo.- &lt;a href="https://github.com/anthropics" rel="noopener noreferrer"&gt;Anthropic en GitHub&lt;/a&gt;: repositorios oficiales relacionados con las herramientas de código mencionadas en este artículo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>technology</category>
      <category>science</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Logprobs: cómo clasificar imágenes con un LLM en un solo token</title>
      <dc:creator>lu1tr0n</dc:creator>
      <pubDate>Sat, 26 Sep 2026 08:26:22 +0000</pubDate>
      <link>https://dev.to/lu1tr0n/logprobs-como-clasificar-imagenes-con-un-llm-en-un-solo-token-3502</link>
      <guid>https://dev.to/lu1tr0n/logprobs-como-clasificar-imagenes-con-un-llm-en-un-solo-token-3502</guid>
      <description>&lt;p&gt;Un script de código abierto acaba de demostrar que no hace falta entrenar un clasificador de imágenes para etiquetar una webcam en tiempo real: alcanza con pedirle a un LLM que responda con una sola letra y leer qué tan seguro estaba de esa letra. El desarrollador Allan Riordan Boll publicó el 25 de septiembre de 2026 en su blog personal un wrapper inspirado en Jev que extiende esta técnica, basada en &lt;strong&gt;logprobs&lt;/strong&gt;, a modelos de visión. Con Gemma 4 12B corriendo local en una RTX 3090 logra cerca de 1 fotograma por segundo con tres preguntas por frame; la misma prueba contra GPT-6-luna de OpenAI cae a unos 0,2 fps.&lt;/p&gt;

&lt;p&gt;La técnica en sí no es nueva: &lt;a href="https://cookbook.openai.com/" rel="noopener noreferrer"&gt;OpenAI la documenta desde hace años en su cookbook de logprobs&lt;/a&gt;, y proyectos como Jev, OpenJev y SemIf la usan para enrutar tickets o clasificar texto sin llamar a un modelo aparte. Lo que aporta este experimento es aplicarla a imágenes, agregando un campo attachments que el formato de Jev todavía no contempla de forma oficial.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Allan Riordan Boll publicó el 25 de septiembre de 2026 un wrapper estilo Jev que suma soporte de imágenes vía logprobs.- El truco fuerza al LLM a responder con una sola letra y lee la probabilidad logarítmica de cada opción posible.- Con Gemma 4 12B local en una RTX 3090 el script procesa cerca de 1 fotograma por segundo con tres preguntas por frame.- Contra la API de OpenAI con GPT-6-luna el rendimiento cae a unos 0,2 fps por la conexión separada de cada pregunta.- Los parámetros clave de la petición son max_completion_tokens=1, logprobs=true y top_logprobs=20.- El formato admite hasta 20 criterios por pregunta, uno por cada letra disponible entre A y T.- El código es un script Python independiente que usa OpenCV solo para capturar la webcam, sin visión por computadora dedicada.- Jev, OpenJev y SemIf ya usaban logprobs para clasificar texto antes de que esta prueba lo extendiera a video.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Qué pasó
&lt;/h2&gt;

&lt;p&gt;Boll leyó sobre Jev y los proyectos que fueron apareciendo alrededor, como OpenJev y SemIf, y se topó con un truco que para muchos desarrolladores de backend resulta nuevo: leer las probabilidades logarítmicas que un LLM asigna a cada token posible en su respuesta, en vez de quedarse solo con el texto generado. La idea es simple. Se arma un prompt tipo test de opción múltiple, por ejemplo &lt;em&gt;Estado: el pedido llegó roto. Pregunta: qué equipo debe atender esto? A) facturación B) envíos C) devoluciones&lt;/em&gt;, y se le pide al modelo que responda con una sola letra. Sumando dos parámetros a la petición, max_completion_tokens en 1 y logprobs en true, el LLM devuelve la letra elegida junto con las probabilidades de las otras opciones que consideró.&lt;/p&gt;

&lt;p&gt;Repetir esa consulta pregunta por pregunta permite construir una clasificación completa sin depender de un modelo separado ni de fine-tuning. Boll fue un paso más allá: el formato de Jev documenta hoy solo estados de texto o JSON, así que agregó un campo attachments para pasar imágenes en base64. Con eso armó un script que captura frames de su webcam, los codifica y le pregunta al modelo si hay una persona visible, si la escena es interior o exterior y qué tan brillante está, todo con un token de respuesta por pregunta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contexto e historia
&lt;/h2&gt;

&lt;p&gt;Leer logprobs para clasificar no es un hallazgo de Boll. OpenAI documenta el patrón en su cookbook como forma de obtener confianza calibrada en tareas de clasificación sin pagar por generar una respuesta larga. La ventaja frente a pedirle al modelo un párrafo de texto es doble: la respuesta es determinista en su formato, siempre una letra, y la probabilidad asociada funciona como un puntaje de confianza que se puede umbralizar.&lt;/p&gt;

&lt;p&gt;Jev popularizó este enfoque como alternativa liviana a entrenar un clasificador dedicado para enrutar tickets de soporte, moderar contenido o etiquetar datos. Proyectos derivados como OpenJev y SemIf replicaron la idea de forma autohospedable, pensados para equipos que no quieren depender de una API externa para decisiones simples y repetitivas. Lo que ninguno documentaba de forma oficial, hasta este experimento, era extender el mismo prompt de opción múltiple a una entrada visual: la especificación de Jev contempla estado en texto o JSON, no adjuntos binarios.&lt;/p&gt;

&lt;p&gt;Ahí está el aporte concreto de Boll: no inventa el truco de los logprobs, pero prueba que funciona igual de bien cuando el estado es una imagen en vez de una oración, siempre que el modelo detrás sea multimodal.&lt;br&gt;
Jev y sus variantes autohospedables como OpenJev llevan años usando logprobs para clasificar texto sin fine-tuning.&lt;/p&gt;
&lt;h2&gt;
  
  
  Detalles técnicos: los logprobs y su rendimiento real
&lt;/h2&gt;

&lt;p&gt;La petición HTTP es una llamada estándar de Chat Completions con tres parámetros extra. max_completion_tokens en 1 obliga al modelo a devolver un solo token, evitando que divague en una respuesta larga. logprobs en true activa que la API devuelva, además del token elegido, su log-probabilidad. top_logprobs, con un número entre 0 y 20, pide además las alternativas más probables que el modelo consideró, aunque no las haya elegido.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;pregunta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estado: el cliente dice que el pedido llego roto.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pregunta: que equipo debe atender esto?&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[A] facturacion&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;[B] envios&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;[C] devoluciones&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Responde solo con la letra.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemma-4-12b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pregunta&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_completion_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;logprobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;top_logprobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8080/v1/chat/completions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;choices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;logprobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;top_logprobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La respuesta trae una lista de tokens candidatos con su log-probabilidad. Tomando el de mayor valor entre A, B y C se obtiene la clasificación, sin haber generado nunca una respuesta larga.&lt;/p&gt;

&lt;p&gt;Para imágenes, Boll agrega el contenido como un bloque image_url con una URL de datos en base64, siguiendo el mismo formato multimodal que ya soportan las APIs compatibles con OpenAI. El resto de la lógica no cambia: se arma la pregunta, se listan las opciones como letras y se lee cuál tuvo la log-probabilidad más alta.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clasificar_frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta_imagen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pregunta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opciones&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;modelo&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;imagen_b64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base64&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;b64encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ruta_imagen&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read_bytes&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;letras&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ABCDEFGHIJKLMNOPQRST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opciones&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;texto_opciones&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;] &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;letras&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opciones&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;modelo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Pregunta: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pregunta&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Opciones:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;texto_opciones&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Responde solo con la letra.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image_url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data:image/jpeg;base64,&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;imagen_b64&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_completion_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;logprobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;top_logprobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;opciones&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;respuesta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;respuesta&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;choices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;logprobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;top_logprobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;logprob&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;letra&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;clasificar_frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;frame_webcam.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hay una persona visible en la imagen?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;si&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;no&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8080/v1/chat/completions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemma-4-12b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;letra&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sequenceDiagram
    participant W as Webcam
    participant S as Script Python
    participant L as Servidor LLM
    W-&amp;gt;&amp;gt;S: captura frame JPEG
    S-&amp;gt;&amp;gt;S: codifica base64
    S-&amp;gt;&amp;gt;L: pide clasificacion con 1 token y logprobs activos
    L--&amp;gt;&amp;gt;S: letra elegida y top_logprobs
    S-&amp;gt;&amp;gt;S: toma la letra con mayor log-probabilidad
    Note over S,L: se repite una vez por cada pregunta del frame
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En sus pruebas, con Gemma 4 12B corriendo en llama.cpp sobre una RTX 3090, el script sostiene cerca de 1 fotograma por segundo evaluando tres preguntas por frame: persona visible, interior o exterior, y nivel de brillo. Contra la API de OpenAI con GPT-6-luna, el rendimiento cae a unos 0,2 fps. Boll atribuye la diferencia a que no optimizó la conexión: cada pregunta abre una conexión separada contra la infraestructura de OpenAI en vez de reutilizar un canal ya abierto.&lt;br&gt;
OpciónCuándo usarlaVentajaLimitaciónModelo local (llama.cpp + Gemma 4 12B)Prototipos, privacidad de la webcam, sin costo por llamada~1 fps con tres preguntas, sin salir de la red localDepende de tener una GPU decente en la máquinaAPI remota (OpenAI GPT-6-luna)Cuando no hay GPU local disponibleNo requiere infraestructura propiaCae a ~0,2 fps y cada pregunta se cobra por separadoModelo de visión especializado (CNN entrenada)Producción a gran escala con una tarea fijaMás eficiente y barato por inferenciaHay que entrenar y reentrenar si cambia la condición&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Tip:&lt;/strong&gt; si tu backend soporta cache de prefijo (KV cache), el estado compartido entre las tres preguntas de un mismo frame se puede cachear una sola vez, evitando reprocesar la imagen para cada pregunta.&lt;br&gt;
Con tres preguntas por frame, GPT-6-luna promedió unos 0,2 fotogramas por segundo en las pruebas publicadas el 25 de septiembre de 2026.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cómo empezar o probarlo
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para reproducir el experimento hace falta un backend que hable el protocolo de Chat Completions con soporte de logprobs, como llama.cpp server o directamente la API de OpenAI, más un modelo de visión si vas a clasificar imágenes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Linux y macOS&lt;/strong&gt;, con uv:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-LsSf&lt;/span&gt; https://astral.sh/uv/install.sh | sh
uv run webcam.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt;, en PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;powershell&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"irm https://astral.sh/uv/install.ps1 | iex"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;uv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;webcam.py&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternativa con pip en las tres plataformas, cambiando solo el comando de activar el entorno:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
pip &lt;span class="nb"&gt;install &lt;/span&gt;opencv-python requests
python webcam.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En Windows el paso de activación es &lt;code&gt;venv\Scripts\activate&lt;/code&gt; en vez de &lt;code&gt;source venv/bin/activate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Para confirmar que tu backend efectivamente devuelve logprobs, antes de escribir el script completo, alcanza con una llamada suelta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; http://localhost:8080/v1/chat/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"model":"gemma-4-12b","messages":[{"role":"user","content":"Responde A o B"}],"max_completion_tokens":1,"logprobs":true,"top_logprobs":5}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | jq &lt;span class="s1"&gt;'.choices[0].logprobs.content[0].top_logprobs'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si el arreglo que devuelve jq no está vacío, el backend soporta logprobs y el truco funciona tal cual se describe arriba.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Ojo:&lt;/strong&gt; si usás una API remota, cada pregunta es una llamada facturable con la imagen completa en base64 adentro; tres preguntas por frame multiplican el costo y la latencia por tres, no dividen nada.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Impacto y análisis
&lt;/h2&gt;

&lt;p&gt;Un modelo de visión especializado, entrenado para una tarea puntual, seguramente es más rápido y barato en producción a gran escala. La ventaja de este enfoque no es la velocidad: es la flexibilidad de cambiar una condición reescribiendo una frase en el prompt, sin reentrenar nada. Para un prototipo, una alerta puntual o un pipeline con pocos frames por segundo, esa flexibilidad puede pesar más que la eficiencia bruta.&lt;/p&gt;

&lt;p&gt;El costo real está en la cantidad de llamadas. Clasificar un frame con tres preguntas son tres peticiones HTTP, aunque cada una devuelva apenas un token. Contra un backend local eso es casi gratis; contra una API remota, se multiplica el costo por cada pregunta y por cada frame que quieras procesar por segundo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué sigue
&lt;/h2&gt;

&lt;p&gt;El formato de Jev todavía no documenta attachments de forma oficial, así que el campo que agregó Boll sigue siendo una extensión personal, no un estándar. Si la comunidad alrededor de Jev, OpenJev y SemIf adopta esta idea, lo lógico sería verla aparecer en la especificación del proyecto en algún momento, con soporte explícito para imágenes y quizás audio.&lt;/p&gt;

&lt;p&gt;Mientras tanto, cualquiera con un backend compatible con Chat Completions puede probar el mismo patrón hoy: no depende de que Jev lo estandarice, alcanza con que la API exponga logprobs y top_logprobs.&lt;/p&gt;

&lt;p&gt;📖 Resumen en Telegram: Ver resumen&lt;/p&gt;

&lt;p&gt;Probalo vos: levantá un servidor local con llama.cpp y un modelo multimodal, y mandale una imagen con &lt;code&gt;logprobs: true&lt;/code&gt; para ver la confianza real detrás de la respuesta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preguntas frecuentes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Qué es un logprob y por qué sirve para clasificar?
&lt;/h3&gt;

&lt;p&gt;Es el logaritmo de la probabilidad que el modelo le asigna a un token dado el contexto. Sirve porque convierte la elección del LLM en un número comparable entre opciones, en vez de quedarte solo con el texto que generó.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hace falta reentrenar el modelo para usar esta técnica?
&lt;/h3&gt;

&lt;p&gt;No. El truco funciona con cualquier modelo que ya sepa seguir instrucciones y cuya API exponga logprobs; no se ajustan pesos ni se agrega una capa nueva.&lt;/p&gt;

&lt;h3&gt;
  
  
  Funciona con modelos que no exponen logprobs en su API?
&lt;/h3&gt;

&lt;p&gt;No directamente. Hace falta que el backend, sea llama.cpp, vLLM o la API de OpenAI, implemente los parámetros logprobs y top_logprobs en el endpoint de chat completions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Por qué el límite está en 20 opciones por pregunta?
&lt;/h3&gt;

&lt;p&gt;Porque el script de Boll mapea cada opción a una letra del alfabeto entre A y T, y top_logprobs en la mayoría de las APIs compatibles con OpenAI acepta como máximo 20 valores.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conviene usarlo en vez de un modelo de visión especializado?
&lt;/h3&gt;

&lt;p&gt;Depende del volumen. Para pocos frames por segundo y condiciones que cambian seguido, la flexibilidad de reescribir el prompt gana. Para producción a gran escala, un modelo entrenado para la tarea puntual suele ser más eficiente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Se puede correr completamente local, sin mandar nada a una API externa?
&lt;/h3&gt;

&lt;p&gt;Sí. El script habla el mismo protocolo de Chat Completions contra un servidor local como llama.cpp, así que no hace falta compartir la webcam con ningún proveedor externo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referencias
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://allanrbo.blogspot.com/2026/09/a-jev-like-wrapper-for-llms-including.html" rel="noopener noreferrer"&gt;Allan's Blog&lt;/a&gt;: post original donde Allan Riordan Boll describe el wrapper y publica el script completo.- &lt;a href="https://cookbook.openai.com/" rel="noopener noreferrer"&gt;OpenAI Cookbook&lt;/a&gt;: documentación con ejemplos de uso de logprobs para clasificación y control de calidad.- &lt;a href="https://platform.openai.com/docs/api-reference/" rel="noopener noreferrer"&gt;OpenAI API Reference, Chat Completions&lt;/a&gt;: referencia de los parámetros logprobs y top_logprobs usados en la petición.- &lt;a href="https://en.wikipedia.org/wiki/Log_probability" rel="noopener noreferrer"&gt;Log probability, Wikipedia&lt;/a&gt;: contexto matemático sobre qué representa una log-probabilidad.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📱 &lt;strong&gt;¿Te gusta este contenido?&lt;/strong&gt; Únete a nuestro canal de Telegram &lt;a href="https://t.me/programacion" rel="noopener noreferrer"&gt;@programacion&lt;/a&gt; donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
