¿Se encuentra en una situación en la que tiene muchas ideas sobre cómo mejorar su producto, pero no tiene tiempo para probarlas todas? Apuesto que sí.
¿Qué pasaría si te dijera que ya no tienes que hacerlo todo tú solo, puedes delegarlo en la IA? Puede ejecutar docenas (o incluso cientos) de experimentos por usted, descartar ideas que no funcionan e iterar sobre aquellas que realmente mueven la aguja.
Suena increíble. Y esa es exactamente la idea detrás de la investigación automática, donde un LLM opera en un bucle, experimentando continuamente, midiendo el impacto e iterando a partir de ahí. El enfoque parecía convincente y muchos de mis colegas ya han visto sus beneficios. Entonces decidí probarlo yo mismo.
Para ello, elegí una tarea analítica práctica: optimización del presupuesto de marketing con muchas restricciones. Veamos si un bucle autónomo puede alcanzar los mismos resultados que nosotros.
Fondo
Comencemos con algunos antecedentes para establecer el contexto. La autoinvestigación fue desarrollada por Andrej Karpathy. Como escribió en su repositorio:
Un día, la investigación de vanguardia en IA solía ser realizada por computadoras de carne entre comer, dormir, divertirse y sincronizarse de vez en cuando usando la interconexión de ondas de sonido en el ritual de la "reunión grupal". Esa era ya pasó. La investigación ahora es enteramente dominio de enjambres autónomos de agentes de IA que corren a través de megaestructuras de clústeres de cómputo en los cielos. Los agentes afirman que ahora estamos en la generación 10.205 del código base; en cualquier caso, nadie podría decir si eso es correcto o incorrecto, ya que el "código" es ahora un binario automodificable que ha crecido más allá de la comprensión humana. Este repositorio es la historia de cómo empezó todo. -@karpathy, marzo de 2026.
La idea detrás de la investigación automática es permitir que un LLM funcione por sí solo en un entorno donde pueda realizar experimentos continuamente. Cambia el código, entrena el modelo, evalúa si el rendimiento mejora y luego mantiene o descarta cada cambio antes de repetir el ciclo. Con el tiempo, regresa y (con suerte) encuentra un modelo mejor que el que tenía al principio. Con este enfoque, Andrej pudo mejorar significativamente el nanochat.
La implementación original se centró en optimizar un modelo de ML. Sin embargo, se puede aplicar un enfoque similar a cualquier tarea con un objetivo claro (desde reducir el tiempo de carga del sitio web hasta minimizar los errores al realizar scraping con Playwright). Más tarde, Shopify abrió una extensión de la investigación automática original, pi-autoresearch. Se basa en pi, un arnés mínimo de codificación de terminal de código abierto.
Sigue un ciclo similar a la investigación automática original, con algunos pasos clave:
Defina la métrica que desea mejorar, junto con las restricciones. Mida la línea de base. Prueba de hipótesis: en cada iteración, el agente propone una idea, la escribe y la prueba. Hay tres resultados posibles: no funciona (descartar), empeora la métrica (descartar) o mejora el objetivo (conservarlo e iterar desde allí). Repita: el ciclo continúa hasta que lo detiene, las mejoras se estabilizan o alcanza un límite de iteración predefinido.
Entonces, la idea central es definir un objetivo claro y dejar que el agente pruebe ideas audaces y aprenda de ellas. Este enfoque puede descubrir mejoras potenciales en sus KPI al probar ideas que su equipo simplemente nunca tuvo tiempo de explorar. Definitivamente suena interesante, así que probémoslo.
Tarea
Me gustaría probar este enfoque en una tarea analítica, ya que en las tareas analíticas del día a día a menudo tenemos objetivos claros y necesitamos iterar varias veces para llegar a una solución óptima. Entonces, revisé todas las publicaciones que he escrito para Towards Data Science a lo largo de los años y encontré una tarea relacionada con la optimización de campañas de marketing, que analizamos en el artículo "Optimizaciones lineales en análisis de productos".
La tarea es bastante común. Imagine que trabaja como analista de marketing y necesita planificar actividades de marketing para el próximo mes. Su objetivo es maximizar los ingresos dentro de un presupuesto de marketing limitado (30 millones de dólares).
Tiene un conjunto de posibles campañas de marketing, junto con proyecciones para cada una de ellas. Para cada campaña, sabemos lo siguiente:
país y canal de marketing, gastos de marketing: inversión requerida para esta actividad, ingresos: ingresos esperados de los clientes adquiridos durante los próximos 12 meses (nuestra métrica objetivo).
También tenemos información adicional, como la cantidad de usuarios adquiridos y la cantidad de contactos de atención al cliente. Los usaremos para repetir la tarea inicial y hacerla progresivamente más desafiante agregando restricciones adicionales.
Es útil darle al agente un enfoque básico para que tenga algo desde donde empezar. Entonces, armémoslo. Una solución sencilla para esta optimización es centrarse en los segmentos de mayor rendimiento por ingresos por dólar gastado. Podemos ordenar todas las campañas por esta métrica y seleccionar las que se ajusten al presupuesto. Por supuesto, este enfoque es bastante ingenuo y definitivamente puede mejorarse, pero proporciona un buen punto de partida.
importar pandas como pd df = pd.read_csv('marketing_campaign_estimations.csv', sep='t') # — Línea de base: codicioso por ingresos por dólar — df['revenue_per_spend'] = df.revenue / df.marketing_spending df = df.sort_values('revenue_per_spend', ascendente=False) df['spend_cumulative'] = df.marketing_spending.cumsum() seleccionado_df = df[df.spend_cumulative <= 30_000_000] gasto_total = seleccionado_df.marketing_spending.sum() ingresos_millones = seleccionado_df.revenue.sum() / 1_000_000 afirmar gasto_total <= 30_000_000, f"Presupuesto violado: {total_spend}" print(f"METRIC ingresos_millones={revenue_millions:.4f}") print(f"Segmentos={len(selected_df)} gasto={total_spend/1e6:.2f}M")
Puse este código en optimise.py en el repositorio.
Si analizamos la línea de base, vemos que los ingresos resultantes son 107,9 millones de dólares, mientras que el gasto total es 29,2 millones.
python3 optimise.py # METRIC ingresos_millones = 107,9158 # Segmentos = 48 gastos = 29,23 millones
Configurando
Antes de pasar al experimento real, primero debemos instalar pi_autoresearch. Comenzamos configurando pi siguiendo las instrucciones de pi.dev. Afortunadamente, se puede instalar con un solo comando, lo que le brinda un arnés de codificación pi en funcionamiento localmente que ya puede usar para ayudar con las tareas de codificación.
npm install -g @mariozechner/pi-coding-agent # instalar pi pi # iniciar pi /login # seleccionar proveedor y especificar APIKey
Sin embargo, como se mencionó anteriormente, nuestro objetivo es probar la extensión pi-autoresearch además de pi, así que instalémosla también.
instalación de pi https://github.com/davebcn87/pi-autoresearch
También quería implementar algunas barreras de seguridad, así que creé un archivo autoresearch.config.json en la raíz de mi repositorio para definir el número máximo de iteraciones. Esto ayuda a limitar la cantidad de iteraciones que puede ejecutar el agente y, a su vez, mantiene los costos de los tokens bajo control durante los experimentos. También puede establecer un límite de gasto por clave API con su proveedor de LLM para un control aún más estricto.
{ "maxIteraciones": 30 }
Puede encontrar todos los detalles sobre la configuración en los documentos.
Eso es todo. La configuración está hecha y estamos listos para comenzar el experimento.
experimentos
Finalmente, es hora de comenzar a utilizar el enfoque de investigación automática para determinar qué campañas de marketing debemos ejecutar. Estoy bastante seguro de que nuestro enfoque inicial no es óptimo, así que veamos si la investigación automática puede mejorarlo. Que comience el viaje.
Comencé la investigación automática llamando a la habilidad.
/habilidad:autoresearch-create
Después de eso, la investigación automática intenta inferir el objetivo de optimización y, si falla, solicita detalles adicionales.
En mi caso, simplemente inspeccionó el código que implementamos en optimise.py y creó un archivo autoresearch.md que resume la tarea. Esto es lo que obtuvimos (un resumen bastante sólido, considerando que solo vio nuestra función de optimización de referencia). Podemos ver que definió claramente las métricas y restricciones. También me gustó que resaltara explícitamente que no se permite cambiar los datos de entrada. Esa es una buena barandilla.
# Investigación automática: maximizar los ingresos de la campaña de marketing por debajo del presupuesto ## Objetivo Mejorar `optimise.py` para que seleccione un conjunto de segmentos de campaña con **ingresos totales máximos** respetando al mismo tiempo el presupuesto de marketing fijo de **30.000.000**. La implementación actual es una heurística codiciosa: clasifica por ingresos por gasto, toma un prefijo acumulativo y se detiene una vez que el siguiente elemento excede el presupuesto. Eso significa que puede dejar el presupuesto sin utilizar y nunca considerar elementos rentables más baratos más adelante en la lista ordenada. La carga de trabajo es pequeña (62 filas), por lo que probablemente sean prácticas estrategias de optimización combinatoria de mayor calidad. Deberíamos favorecer la lógica de selección exacta o casi exacta sobre las heurísticas frágiles cuando el tiempo de ejecución se mantiene rápido. ## Métricas – **Primaria**: `revenue_millions` (millones, cuanto más alto, mejor) – ingresos totales seleccionados divididos por 1.000.000 – **Secundaria**: – `spend_millions` – gasto total seleccionado dividido por 1.000.000 – `budget_slack_millions` – presupuesto no utilizado en millones – `segment_count` – número de segmentos seleccionados ## Cómo ejecutar `./autoresearch.sh`: ejecuta una verificación previa rápida de sintaxis, luego `optimise.py`, que debe emitir líneas `METRIC name=number`. ## Archivos en el alcance – `optimise.py` – lógica de selección de campaña y resultados de métricas – `autoresearch.sh` – evaluación comparativa y comprobaciones previas – `autoresearch.md` – memoria de sesión/hallazgos – `autoresearch.ideas.md` – trabajo pendiente de ideas prometedoras postergadas ## Fuera de los límites – `marketing_campaign_estimations.csv` – datos de entrada; no editar – Historial de Git/estructura de ramas fuera del flujo de trabajo de investigación automática ## Restricciones – Debe mantener el gasto `<= 30_000_000` – Debe mantener el script ejecutable con `python3 optimise.py` – Sin cambios en el conjunto de datos – Mantenga la solución simple y explicable a menos que la complejidad adicional genere ingresos sustancialmente mejores – El tiempo de ejecución debe seguir siendo lo suficientemente rápido para muchas iteraciones de investigación automática ## Qué se ha probado – El código base se ordena por `revenue / marketing_spending`, calcula el gasto acumulado y mantiene solo el prefijo ordenado bajo el presupuesto.
Después de definir la tarea, inmediatamente inició el ciclo. Puede funcionar durante algún tiempo, pero aún conserva la visibilidad. Puede ver tanto su razonamiento como algunas estadísticas clave en el widget (como la iteración actual, el mejor valor objetivo y la mejora con respecto a la línea de base), lo cual es bastante útil.
A medida que itera, también escribe un archivo autoresearch.jsonl con detalles completos de cada experimento y la métrica objetivo resultante. Este registro es muy útil tanto para revisar lo que se ha probado como para que el propio modelo realice un seguimiento de qué hipótesis ya ha probado.
En mi caso, a pesar del límite configurado de 30 iteraciones, decidió detenerse después de solo 5. El agente exploró varias estrategias diferentes: optimización exacta de la mochila, poda del espacio de búsqueda y un enfoque de programación dinámica de frontera de Pareto. Repasemos los detalles:
Iteración 1: reprodujo nuestro enfoque de referencia. La estrategia codiciosa de prefijos (ingresos/gastos) alcanzó los 107,9 millones, pero se detuvo antes de tiempo cuando los elementos no encajaban, perdiendo mejores combinaciones posteriores. No hay ningún avance aquí, sólo una verificación de cordura de la línea de base. Iteración 2: solucionador de mochila exacto. El agente cambió a un enfoque de sucursal y consolidación (0/1 mochila) y alcanzó 110,16 millones de ingresos (+2,25 millones de aumento), lo que supone una clara mejora. Una gran ganancia ya en la segunda iteración. Iteración 3: Poda de dominancia. Esta iteración intentó reducir el espacio de búsqueda eliminando segmentos dominados por pares (es decir, segmentos con peores gastos e ingresos que otros). Si bien es intuitiva, esta suposición no se cumple en la configuración de mochila 0/1: es posible que ya se haya seleccionado un segmento "dominante", mientras que uno "dominado" aún puede ser útil en combinación con otros. Como resultado, este enfoque fracasó y se redujo a 95,9 millones de ingresos, por lo que fue descartado. Un buen ejemplo de prueba y error. Lo probamos, no funcionó e inmediatamente seguimos adelante. Iteración 4: Frontera de programación dinámica. El agente cambió a un enfoque de programación dinámica de frontera de Pareto, pero logró el mismo resultado que en la iteración 2. Desde la perspectiva del analista, esto sigue siendo útil. Confirma que probablemente hemos alcanzado el nivel óptimo. Iteración 5: Contabilidad de números enteros. Esta iteración convirtió todos los valores monetarios de flotadores a centavos enteros para mejorar la estabilidad numérica y la reproducibilidad, pero nuevamente produjo el mismo valor final. Tiene sentido que el agente se detuviera ahí.
Entonces, al final, la solución óptima ya se encontró en la segunda iteración y coincide con la solución que encontramos en mi artículo sobre programación lineal. El agente aún probó algunas otras ideas, pero siguió terminando con el mismo resultado y finalmente se detuvo (en lugar de quemar aún más fichas).
Ahora podemos finalizar la investigación ejecutando el comando /skill:autoresearch-finalize, que confirma y envía todo a GitHub. Como resultado, creó una nueva rama con un PR, guardando tanto los cambios en el código optimise.py como los archivos de razonamiento intermedios. De esta manera, podemos rastrear fácilmente lo que sucedió durante todo el proceso.
El agente resolvió fácilmente nuestra tarea inicial. A continuación, intentemos hacerlo más realista agregando restricciones adicionales del equipo de Operaciones. Supongamos que nos damos cuenta de que también debemos asegurarnos de que no haya más de 5.000 tickets de atención al cliente incrementales (para que el equipo de operaciones pueda manejar la carga) y que la tasa general de contacto con el cliente se mantenga por debajo del 4,2 %, ya que esta es una de nuestras comprobaciones del estado del sistema. Esto hace que el problema sea más desafiante, ya que agrega restricciones adicionales y obliga al agente a revisar el espacio de la solución y buscar un nuevo óptimo.
Para comenzar, simplemente reinicié el proceso /skill:autoresearch-create, proporcionando restricciones adicionales.
/skill:autoresearch-create Tengo restricciones adicionales para nuestros contactos de CS para garantizar que nuestro equipo de Operaciones pueda manejar la demanda de manera saludable: – La cantidad de contactos de CS adicionales ≤ 5K – Tasa de contacto (contactos/usuarios de CS) ≤ 0,042
Esta vez, continuó exactamente donde lo dejamos. Ya tenía el contexto completo de la ejecución anterior, incluido todo lo que habíamos hecho hasta ahora. Como resultado de la actualización de la tarea, el agente revisó el archivo autoresearch.md para incluir las nuevas restricciones.
## Restricciones – Debe mantener el gasto `<= 30_000_000` – Debe mantener contactos CS adicionales `<= 5_000` – Debe mantener la tasa de contacto `<= 0.042` – Debe mantener el script ejecutable con `python3 optimise.py` – Sin cambios en el conjunto de datos – Mantenga la solución simple y explicable a menos que una complejidad adicional genere ingresos sustancialmente mejores – El tiempo de ejecución debe seguir siendo lo suficientemente rápido para muchas iteraciones de investigación automática
Ejecutó 8 iteraciones adicionales y convergió a la siguiente solución (nuevamente coincidiendo con lo que habíamos visto anteriormente):
Ingresos: 109,87 millones de dólares, Presupuesto gastado: 29,9981 millones de dólares (menos de 30 millones de dólares), Contactos de atención al cliente: 3218 (menos de 5 000), Tasa de contacto: 0,038 (menos de 0,042).
Después de introducir las nuevas restricciones, el agente reformuló el problema y cambió a un solucionador MILP exacto. Rápidamente encontró la solución óptima, alcanzando 109,87 millones de ingresos y cumpliendo con todas las limitaciones. La mayoría de las iteraciones posteriores realmente no cambiaron el resultado, simplemente limpiaron las cosas: eliminaron la lógica alternativa, redujeron las dependencias y mejoraron el tiempo de ejecución. Entonces, una vez que el problema estuvo bien definido, el agente dejó de “buscar” y comenzó a “ingeniería”. Lo que es aún más interesante es que sabía cuándo dejar de optimizar y no llegó hasta el límite de 30 iteraciones.
Finalmente, le pedí al agente que finalizara la investigación. Esta vez, por alguna razón, /skill:autoresearch-finalize no impulsó todos los cambios, por lo que tuve que pedirle manualmente a pi que creara dos RP: uno con cambios de código limpios y otro con el razonamiento y los archivos de respaldo. Puede consultar las relaciones públicas si desea ver más detalles sobre lo que intentó el agente.
Eso es todo por los experimentos. Obtuvimos resultados sorprendentes y pudimos ver las capacidades de la investigación automática. Entonces, es hora de concluir.
Resumen
Ese fue un experimento realmente interesante. El agente pudo alcanzar la misma solución óptima que encontramos anteriormente, completamente por sí solo. Si bien no impulsó el resultado más allá (lo cual no es sorprendente dado lo bien estudiados que están los problemas como la mochila), fue impresionante ver cómo un LLM puede explorar soluciones de manera iterativa y converger hacia un resultado sólido sin guía manual.
Creo que este enfoque tiene un gran potencial en múltiples dominios (desde entrenar modelos de ML y resolver tareas analíticas hasta problemas más complejos de ingeniería, como optimizar el rendimiento del sistema o los tiempos de carga). En muchos equipos, simplemente no tenemos tiempo para probar todas las ideas posibles o descartamos algunas de ellas demasiado pronto. Un bucle autónomo como este puede probar sistemáticamente diferentes enfoques y validarlos con métricas reales.
Al mismo tiempo, esto definitivamente no es una solución milagrosa. Habrá casos en los que el agente encuentre soluciones “óptimas” que no sean viables en la práctica, por ejemplo, mejorar la velocidad de carga del sitio web a costa de perjudicar la experiencia del usuario. Ahí es donde la supervisión humana se vuelve crítica: no sólo para validar los resultados, sino para garantizar que la solución tenga sentido de manera integral.
Por lo que he visto, este enfoque funciona mejor cuando tienes un objetivo claro, restricciones bien definidas y algo medible para optimizar. Es mucho más difícil aplicarlo a problemas más ambiguos, como hacer que un producto sea más fácil de usar, donde el éxito está menos claramente definido.
En general, definitivamente recomendaría probar pi-autoresearch o herramientas similares para sus propios problemas. Es una forma poderosa de probar ideas que normalmente no tendría tiempo de explorar y ver qué funciona realmente en la práctica. Y hay algo casi mágico en que tu producto mejore mientras duermes.
Descargo de responsabilidad: trabajo en Shopify, pero esta publicación es independiente de mi trabajo allí y refleja mis puntos de vista personales.