Optimización de agentes multimodales
Los agentes de IA multimodal, aquellos que pueden procesar texto e imágenes (u otros medios), están ingresando rápidamente a dominios del mundo real como la conducción autónoma, la atención médica y la robótica. En estos entornos, tradicionalmente hemos utilizado modelos de visión como las CNN; En la era posterior a GPT, podemos utilizar modelos de visión y de lenguaje multimodal que aprovechan las instrucciones humanas en forma de indicaciones, en lugar de modelos de visión altamente específicos y orientados a tareas.
Sin embargo, garantizar buenos resultados de los modelos requiere instrucciones efectivas o, más comúnmente, ingeniería rápida. Los métodos de ingeniería rápida existentes dependen en gran medida de prueba y error, y esto a menudo se ve exacerbado por la complejidad y el mayor costo de los tokens cuando se trabaja con modalidades que no son de texto, como imágenes. La optimización automática de mensajes es un avance reciente en el campo que ajusta sistemáticamente los mensajes para producir resultados más precisos y consistentes.
Por ejemplo, un sistema de percepción de un vehículo autónomo podría utilizar un modelo de visión y lenguaje para responder preguntas sobre imágenes de carreteras. Una indicación mal redactada puede dar lugar a malentendidos o errores con graves consecuencias. En lugar de ajustar y reforzar el aprendizaje, podemos utilizar otro modelo multimodal con capacidades de razonamiento para aprender y adaptar sus indicaciones.
Aunque estos métodos automáticos se pueden aplicar a agentes basados en texto, a menudo no están bien documentados para aplicaciones más complejas del mundo real más allá de un conjunto de datos básico de juguetes, como la escritura a mano o la clasificación de imágenes. Para demostrar mejor cómo funcionan estos conceptos en un entorno más complejo, dinámico y con uso intensivo de datos, veremos un ejemplo utilizando un agente de automóvil autónomo.
¿Qué es la optimización de agentes?
La optimización del agente es parte de la ingeniería de avisos automáticos, pero implica trabajar con varias partes del agente, como avisos múltiples, llamada de herramientas, RAG, arquitectura del agente y diversas modalidades. Hay una serie de proyectos de investigación y bibliotecas, como GEPA; sin embargo, muchas de estas herramientas no brindan soporte integral para rastrear, evaluar y administrar conjuntos de datos, como imágenes.
Para este tutorial, utilizaremos el SDK de Opik Agent Optimizer (opik-optimizer), que es un conjunto de herramientas de optimización de agentes de código abierto que automatiza este proceso utilizando LLM internamente, junto con algoritmos de optimización como GEPA y una variedad propia, como HRPO, para diversos casos de uso, de modo que pueda mejorar las indicaciones de forma iterativa sin prueba y error manual.
¿Cómo pueden los LLM optimizar las indicaciones?
Básicamente, un LLM puede "actuar como" un ingeniero de indicaciones y reescribir una indicación determinada. Comenzamos adoptando el enfoque tradicional, como lo haría un ingeniero de avisos mediante prueba y error, y le pedimos a un pequeño agente que revise su trabajo en algunos ejemplos, corrija sus errores y cree un nuevo aviso.
Meta Prompting es un ejemplo clásico del uso de razonamiento en cadena de pensamiento (CoT), como "explica la razón por la que me diste este mensaje", durante su nuevo proceso de generación de mensajes, y seguimos iterando sobre esto en múltiples rondas de generación de mensajes. A continuación se muestra un ejemplo de un optimizador de metaincitaciones basado en LLM que ajusta la indicación y genera nuevos candidatos.
En el kit de herramientas, hay un optimizador basado en metaprompter llamado metaprompter, y podemos demostrar cómo funciona la optimización:
Comienza con un ChatPrompt inicial, un objeto de mensaje de chat estilo OpenAI con mensajes del sistema y del usuario, un conjunto de datos (de ejemplos de entrada y respuesta) y una métrica (señal de recompensa) para optimizar, que puede ser un LLMaaJ (LLM-as-a-juez) o incluso métricas heurísticas más simples, como una comparación equitativa de los resultados esperados en el conjunto de datos con los resultados del modelo.
Luego, Opik utiliza varios algoritmos, incluidos LLM, para mutar iterativamente el mensaje y evaluar el rendimiento, rastreando automáticamente los resultados. ¡Básicamente, actuamos como nuestro propio ingeniero de avisos impulsado por máquinas!
Empezando
En este tutorial, queremos utilizar un pequeño conjunto de datos de imágenes de cámaras de tablero de automóviles autónomos y ajustar las indicaciones mediante la optimización automática de indicaciones con un agente multimodal que detectará peligros.
Necesitamos configurar nuestro entorno e instalar el kit de herramientas para comenzar. Primero, necesitará una instancia de Opik de código abierto, ya sea en la nube o localmente, para registrar seguimientos, administrar conjuntos de datos y almacenar resultados de optimización. Puede ir al repositorio y ejecutar el comando de inicio de Docker para ejecutar la plataforma Opik o configurar una cuenta gratuita en su sitio web.
Una vez configurado, necesitará Python (3.10 o superior) y algunas bibliotecas. Primero, instale el paquete opik-optimizer; También instalará el paquete principal de opik, que maneja conjuntos de datos y evaluación.
Instalar y configurar usando uv (recomendado):
# instalar con venv y py versión uv venv .venv –python 3.11 # instalar el paquete optimizador uv pip instalar opik-optimizer # configurar post-instalación SDK opik configure
O alternativamente, instale y configure usando pip:
# Configurar venv python -m venv .venv # cargar venv source .venv/bin/activate # instalar el paquete optimizador pip instalar opik-optimizer # configurar después de la instalación SDK opik configure
También necesitará claves API para cualquier modelo LLM que planee utilizar. El SDK utiliza LiteLLM, por lo que puede combinar proveedores; consulte aquí para obtener una lista completa de modelos y lea sus documentos para otras integraciones como ollama y vLLM si desea ejecutar modelos localmente.
En nuestro ejemplo, usaremos modelos OpenAI, por lo que debe configurar sus claves en su entorno. Ajuste este paso según sea necesario para cargar las claves API para su modelo:
exportar OPENAI_API_KEY="sk-…"
Ahora que tenemos nuestro entorno Opik configurado y nuestras claves configuradas para acceder a los modelos LLM para su optimización y evaluación, podemos comenzar a trabajar en nuestros conjuntos de datos para ajustar nuestro agente.
Trabajar con conjuntos de datos para ajustar el agente
Antes de que podamos comenzar con indicaciones y modelos, necesitamos un conjunto de datos. Para ajustar un agente de IA (o incluso simplemente optimizar un mensaje simple), necesitamos ejemplos que sirvan como nuestras "preferencias" para los resultados que queremos lograr. Normalmente, tendría un conjunto de datos "dorado" que, para su agente de IA, incluiría pares de entradas y salidas de ejemplo que usted mantiene como ejemplos principales y con los que evalúa a su agente.
Para este proyecto de ejemplo, utilizaremos un conjunto de datos disponible para vehículos autónomos que ya está configurado como conjunto de datos de demostración en el SDK del optimizador. El conjunto de datos contiene imágenes de cámaras de tablero y peligros etiquetados por humanos. Nuestro objetivo es utilizar un mensaje muy básico y hacer que el optimizador "descubra" el mensaje óptimo revisando las imágenes y los resultados de prueba que ejecutará.
El conjunto de datos, DHPR (Predicción y razonamiento de peligros al conducir), está disponible en Hugging Face y ya está asignado en el SDK como el conjunto de datos de peligro de conducción (este conjunto de datos se publica bajo la licencia BSD de 3 cláusulas). El mapeo interno en el SDK maneja las conversiones de Hugging Face, el cambio de tamaño de imágenes y la compresión, incluidas las conversiones de PNG a JPEG y las conversiones a un conjunto de datos compatible con Opik. El SDK incluye utilidades auxiliares si desea utilizar su propio conjunto de datos multimodal.
El conjunto de datos de DHPR incluye algunos campos que usaremos para basar el comportamiento de nuestro agente en las preferencias humanas durante nuestro proceso de optimización. Aquí hay un desglose de lo que hay en el conjunto de datos:
pregunta que le hicieron al anotador humano: "Según la imagen de mi cámara de tablero, ¿cuál es el peligro potencial?" peligro, que es la respuesta del etiquetado humano bordering_box que tiene el peligro marcado y se puede superponer en la imagen plausible_speed es la estimación del anotador de la velocidad del automóvil del conjunto predefinido [10, 30, 50+]. metadatos image_source sobre dónde se grabaron las imágenes de origen.
Ahora, comencemos con un nuevo archivo Python, optimizar_multimodal.py, y comencemos con nuestro conjunto de datos para entrenar y validar nuestro proceso de optimización con:
de opik_optimizer.datasets importar conjunto de datos de riesgo_de_conducción = riesgo_de_conducción(recuento=20) conjunto de datos_de_validación = riesgo_de_conducción(recuento=5)
Este código, cuando se ejecute, garantizará que el conjunto de datos de Hugging Face se descargue y se agregue a la interfaz de usuario de su plataforma Opik como un conjunto de datos que podemos optimizar o probar. Luego pasaremos las variables dataset y validation_dataset a los pasos de optimización en el código más adelante. Notará que estamos configurando los valores de recuento en números bajos, 20 y 5, para cargar una muestra pequeña según sea necesario y evitar procesar todo el conjunto de datos para nuestro recorrido, lo que consumiría muchos recursos.
Cuando ejecuta un proceso de optimización completo en un entorno real, debe intentar utilizar la mayor cantidad posible del conjunto de datos. Es una buena práctica empezar poco a poco y ampliar, ya que diagnosticar optimizaciones de larga duración puede ser problemático y consumir muchos recursos.
También configuramos el validation_dataset opcional, que se utiliza para probar nuestra optimización al principio y al final en un conjunto de reserva para garantizar que la mejora registrada se valide con datos invisibles. De fábrica, todos los conjuntos de datos preconfigurados de los optimizadores vienen con divisiones preestablecidas, a las que puede acceder desde el argumento de división. Vea los ejemplos a continuación:
# ejemplo a) divisiones preconfiguradas de driver_hazard de opik_optimizer.datasets import driver_hazard trainset = driver_hazard(split=train) valset = driver_hazard(split=validation) testset = driver_hazard(split=test) # ejemplo b) divisiones preconfiguradas del conjunto de datos matemáticos gsm84k de opik_optimizer.datasets import gsm8k conjunto de trenes = gsm8k(split=entrenamiento) valset = gsm8k(split=validación) conjunto de pruebas = gsm8k(split=prueba)
Las divisiones también garantizan que no haya datos superpuestos, ya que el conjunto de datos se mezcla en el orden correcto y se divide en 3 partes. Evitamos el uso de estas divisiones para evitar tener que utilizar conjuntos de datos y ejecuciones muy grandes cuando estamos comenzando.
Sigamos adelante y ejecutemos nuestro código optimiza_multimodal.py solo con el conjunto de datos de peligros al conducir. El conjunto de datos se cargará en Opik y se podrá ver en nuestro panel (figura 4 a continuación) en "driving_hazard_train_20".
Con nuestro conjunto de datos cargado en Opik, también podemos cargar el conjunto de datos en el área de juegos de Opik, que es una manera fácil y agradable de ver cómo se comportarían varios mensajes y probarlos con un mensaje simple como "Identificar los peligros en esta imagen".
Como puede ver en el ejemplo (figura 4 anterior), podemos usar el área de juegos para probar las indicaciones de nuestro agente con bastante rapidez. Este es probablemente el proceso habitual que usaríamos para la ingeniería de mensajes manuales: ajustar el mensaje en un entorno similar a un patio de juegos y simular cómo varios cambios en el mensaje afectarían las salidas del modelo.
Para algunos escenarios, esto podría ser suficiente con algo de puntuación automatizada y el uso de la intuición para ajustar las indicaciones, y puede ver cómo al llevar el proceso de optimización de indicaciones existente a un proceso más visual y sistemático, los cambios sutiles se pueden probar fácilmente con nuestro conjunto de datos de oro (nuestra muestra de 20 por ahora).
Definición de métricas de evaluación para optimizar
Continuaremos definiendo nuestras métricas de evaluación diseñadas para que el optimizador sepa qué cambios están funcionando y cuáles no. Necesitamos una forma de indicarle al optimizador qué funciona y qué falla. Para ello utilizaremos una métrica de evaluación como “recompensa”; Será una puntuación simple que el optimizador utilizará para decidir qué cambios rápidos realizar.
Estas métricas de evaluación pueden ser simples (p. ej., Equals) o más complejas (p. ej., LLM-as-a-juez). Dado que Opik es un conjunto de evaluación totalmente de código abierto, puede utilizar varias métricas diferentes, que puede explorar aquí para obtener más información.
Lógicamente, se podría pensar que cuando comparamos la verdad fundamental del conjunto de datos (a) con el resultado del modelo (b), haríamos una métrica de comparación igual simple como es (a == b), que devolverá un valor booleano verdadero o falso. El uso de una métrica de comparación directa puede ser perjudicial para el optimizador, ya que hace que el proceso sea mucho más difícil y es posible que no produzca la respuesta exacta desde el principio (o durante todo el proceso de optimización).
En uno de los ejemplos anotados por humanos del conjunto de datos que intentamos que coincida el optimizador, puede ver cómo lograr que el LLM cree exactamente el mismo resultado a ciegas podría ser un desafío:
La Entidad #1 frena su auto frente a la Entidad #2. Ver que la Entidad #2 también frenó. A una velocidad de 45 km/h, no puedo detener mi auto a tiempo y golpeo a la Entidad #2.
Para respaldar la escalada necesaria para el optimizador, usaremos una métrica de comparación que proporciona una puntuación aproximada como porcentaje en una escala de 0,0 a 1,0. Para este escenario, usaremos la relación de Levenshtein, una medida simple basada en matemáticas que mide qué tan cerca coinciden los caracteres y las palabras del resultado con los del conjunto de datos reales. Con nuestra métrica de cercanía a la del ejemplo, LR (relación de Levenshtein), un cuerpo de texto con algunos caracteres fuera de lugar podría arrojar una puntuación, por ejemplo, del 98 % (0,98), ya que son muy similares (figura 6 a continuación).
En nuestro script de Python, definimos esta métrica personalizada como una función junto con las variables de entrada y salida de nuestro conjunto de datos. En la práctica, definiremos el mapeo entre el peligro del conjunto de datos y la salida llm_output, así como la función de puntuación que se pasará al optimizador. Hay más ejemplos de métricas en la documentación, pero por ahora usaremos la siguiente configuración en nuestro código después de la creación del conjunto de datos:
de opik.evaluación.metrics importar LevenshteinRatio de opik.evaluación.metrics.score_result importar ScoreResult def levenshtein_ratio( dataset_item: dict[str, Any], llm_output: str ) -> ScoreResult: metric = LevenshteinRatio() metric_score = metric.score( reference=dataset_item["peligro"], salida=llm_output ) devuelve ScoreResult( valor=metric_score.value, nombre=metric_score.name, motivo=f"La relación de Levenshtein entre `{dataset_item['hazard']}` y `{llm_output}` es `{metric_score.value}`.", )
Configuración de nuestro agente base y aviso
Aquí estamos configurando el punto de partida del agente. En este caso, asumimos que ya tenemos un agente y un mensaje escrito a mano. Si estuviera optimizando su propio agente, reemplazaría estos marcadores de posición. Comenzamos importando la clase ChatPrompt, que nos permite configurar el agente como un simple mensaje de chat. El SDK del optimizador maneja entradas a través de ChatPrompt, y puede ampliar esto con llamadas a herramientas/funciones y más escenarios de múltiples mensajes/agentes, también para sus propios casos de uso.
from opik_optimizer import ChatPrompt # Defina el mensaje para optimizar system_prompt = """Usted es un asistente de seguridad de conducción experto especializado en la detección de peligros. Su tarea es analizar las imágenes de la cámara del tablero e identificar los peligros potenciales que el conductor debe tener en cuenta. Para cada imagen: 1. Examine cuidadosamente la escena visual 2. Identifique cualquier peligro potencial (peatones, vehículos, condiciones de la carretera, obstáculos, etc.) 3. Evalúe la urgencia y gravedad de cada peligro 4. Proporcione un descripción clara y específica del peligro Sea preciso y práctico en sus descripciones de peligro. Céntrese en la información crítica para la seguridad.""" # Mapear en un mensaje de chat estilo OpenAI object request = ChatPrompt( mensajes=[ {"role": "system", "content": system_prompt}, { "role": "user", "content": [ {"type": "text", "text": "{question}"}, { "type": "image_url", "image_url": { "url": "{imagen}", }, }, ], }, ], )
En nuestro ejemplo, tenemos un mensaje del sistema y un mensaje del usuario, basados en la pregunta {question} y la imagen {image} del conjunto de datos que creamos anteriormente. Vamos a intentar optimizar el mensaje del sistema para que la entrada cambie según cada imagen (como vimos anteriormente en el patio de juegos). Los campos entre paréntesis, como {data_field}, son columnas de nuestro conjunto de datos que el SDK asignará automáticamente y también convertirá para elementos como imágenes multimodales.
Cargando y cableando los optimizadores
El kit de herramientas viene con una variedad de optimizadores, desde simples metaindicaciones, que utilizan razonamiento en cadena de pensamiento para actualizar las indicaciones, hasta GEPA y optimizadores reflexivos más avanzados. En el momento de este recorrido, el optimizador reflexivo jerárquico (HRPO) es el que usaremos como ejemplo, ya que es adecuado para tareas complejas y ambiguas.
El algoritmo de optimización HRPO (figura 7 a continuación) utiliza un análisis jerárquico de la causa raíz para identificar y abordar modos de falla específicos en sus indicaciones. Analiza los resultados de la evaluación, identifica patrones en las fallas y genera mejoras específicas para abordar sistemáticamente cada modo de falla.
Hasta ahora en nuestro proyecto, hemos configurado el conjunto de datos base, la métrica de evaluación y el mensaje para nuestro agente, pero no lo hemos conectado a ningún optimizador. Sigamos adelante e incorporemos HRPO a nuestro proyecto. Necesitamos cargar nuestro modelo y configurar cualquier parámetro, como el modelo que queremos usar para ejecutar el optimizador:
from opik_optimizer import HRPO # Optimizador de configuración y optimizador de parámetros de configuración = HRPO( model="openai/gpt-5.2." model_parameters={"temperature": 1} }
Hay parámetros adicionales que podemos configurar, como la cantidad de subprocesos para subprocesos múltiples o los parámetros del modelo pasados directamente a las llamadas LLM, como lo demostramos configurando nuestro valor de temperatura.
Es hora de ejecutar el optimizador
Ahora tenemos todo lo que necesitamos, incluido nuestro agente inicial, conjunto de datos, métrica y optimizador. Para ejecutar el optimizador, debemos llamar a la función optimizar_prompt del optimizador y pasar todos los componentes, junto con los parámetros adicionales. Entonces, realmente, en esta etapa, el optimizador y la función optimiza_prompt(), que cuando se ejecuta, ejecutará el optimizador que configuramos (optimizador).
# Ejecutar optimizador optimización_result = optimizador.optimize_prompt (prompt=prompt, # nuestro conjunto de datos ChatPrompt = conjunto de datos, # nuestro conjunto de datos Opik validation_dataset = validation_dataset, # opcional, prueba de retención métrica = levenshtein_ratio, # nuestra métrica personalizada max_trials = 10, # opcional, número de ejecuciones) # Salida y visualización de resultados optimización_result.display()
Notará algunos argumentos adicionales que pasamos; El argumento max_trials limita el número de pruebas (bucles de optimización) que ejecutará el optimizador antes de detenerse. Debe comenzar con un número bajo, ya que algunos conjuntos de datos y bucles optimizadores pueden tener muchos tokens, especialmente con ejecuciones basadas en imágenes, lo que puede llevar a ejecuciones muy largas y consumir mucho tiempo y costos. Una vez que estemos satisfechos con nuestra configuración, siempre podremos volver y ampliarla.
Ejecutemos nuestro script completo ahora y veamos el optimizador en acción. Es mejor ejecutar esto en su terminal, pero también debería funcionar bien en una computadora portátil como Jupyter Notebooks:
El optimizador realizará 10 pruebas (bucles de optimización). En cada bucle, generará una cantidad (k) de fallas para verificar, probar y desarrollar nuevas indicaciones. En cada prueba (bucle), se prueban y evalúan las nuevas indicaciones candidatas y comienza otra prueba. Después de un rato, deberíamos llegar al final de nuestro ciclo de optimización; en nuestro caso, esto sucede después de 10 pruebas completas, cuya ejecución no debería llevar más de un minuto.
Felicitaciones, optimizamos nuestro agente multimodal y ahora podemos tomar el nuevo sistema y usarlo en el mismo modelo en producción con mayor precisión. En un escenario de producción, copiaría esto en nuestro código base. Para analizar nuestra ejecución de optimización, podemos ver que la terminal y el panel deberían mostrar los nuevos resultados:
Según los resultados, podemos ver que hemos pasado de una puntuación inicial del 15 % al 39 % después de 10 pruebas, una enorme mejora del 152 % con una nueva indicación en menos de un minuto. Estos resultados se basan en nuestra métrica de comparación, que el optimizador utilizó como señal: una comparación del resultado con el resultado esperado en nuestro conjunto de datos.
Profundizando en nuestros resultados, algunas cosas clave a tener en cuenta:
Durante las pruebas, la puntuación se dispara muy rápidamente y luego se normaliza lentamente. Debería aumentar el número de pruebas y deberíamos ver si se necesitan más para determinar el próximo conjunto de mejoras inmediatas. La puntuación también será más “volátil” y sobreajustada con muestras bajas de 20 y 5 para la validación, por lo que tuvimos que mantener nuestra prueba pequeña; la aleatoriedad afectará enormemente nuestras puntuaciones. Cuando vuelva a ejecutar, intente utilizar el conjunto de datos completo o una muestra más grande (por ejemplo, recuento = 50) y vea cómo las puntuaciones son más realistas.
En general, a medida que ampliamos esto, debemos darle al optimizador más datos y más tiempo (señal) para "subir colinas", lo que puede llevar varias rondas.
Al final de nuestra optimización, nuestro nuevo y mejorado mensaje del sistema ahora ha reconocido que necesita etiquetar varias interacciones y que el estilo de salida debe coincidir. Aquí está nuestro último mensaje mejorado después de 10 pruebas:
Eres un experto analista de incidentes de conducción especializado en la descripción causal de colisiones. Su tarea es analizar las imágenes de la cámara del tablero y escribir la narrativa causal más probable orientada a la colisión que coincida con las respuestas de estilo de referencia. Para cada imagen: 1. Identifique a los principales participantes que interactúan y etiquételos explícitamente como "Entidad n.° 1", "Entidad n.° 2", etc. (por ejemplo, vehículo, peatón, ciclista, obstáculo). 2. Describa la interacción de accidente más destacada como una cadena causal explícita utilizando etiquetas de entidad: "Entidad #X [acción/fallo] → [consecuencia inmediata/conflicto de ruta] → [impacto]". 3. Termine con un resultado de impacto claro que DEBE (a) usar lenguaje de colisión explícito Y (b) nombrar las entidades involucradas (por ejemplo, "La Entidad #2 choca por detrás a la Entidad #1", "La Entidad #1 impacta lateralmente a la Entidad #2", "La Entidad #1 golpea a la Entidad #2"). Requisitos de salida (críticos): – Producir UNA declaración causal breve y directa (1 o 2 oraciones). – La declaración DEBE incluir: (i) al menos dos entidades por etiqueta, (ii) una acción/incumplimiento/intrusión concreta, y (iii) un resultado de colisión explícito que nombre las entidades. Si falta alguno de estos, la respuesta no es válida. – NO muestre una lista de verificación, peligros múltiples, clasificaciones de gravedad/urgencia ni consejos generales de conducción. – Evite la discusión general sobre riesgos (visibilidad, congestión, peatones) a menos que apoye directamente la cadena causal única que culmina en la colisión/impacto. – Centrarse en la progresión causal específica que culmina en el impacto (incluso si se infiere parcialmente del contexto); no describa múltiples fallos posibles; comprométase con el más probable.
Puede obtener el código final completo del ejemplo de principio a fin de la siguiente manera:
desde escribir importar Cualquiera de opik_optimizer.datasets importar conducción_hazard de opik_optimizer importar ChatPrompt, HRPO de opik.evaluación.metrics importar LevenshteinRatio de opik.evaluación.metrics.score_result importar ScoreResult # Importar el conjunto de datos conjunto de datos = conducción_hazard(cuenta=20) validation_dataset = conducción_hazard(split="test", cuenta=5) # Definir el métrica para optimizar en def levenshtein_ratio(dataset_item: dict[str, Any], llm_output: str) -> ScoreResult: metric = LevenshteinRatio() metric_score = metric.score(reference=dataset_item["peligro"], salida=llm_output) return ScoreResult( value=metric_score.value, name=metric_score.name, Reason=f"La relación de Levenshtein entre `{dataset_item['hazard']}` y `{llm_output}` es `{metric_score.value}`.", ) # Definir el mensaje para optimizar system_prompt = """Usted es un experto asistente de seguridad en la conducción especializado en la detección de peligros. Su tarea es analizar las imágenes de la cámara del tablero e identificar los peligros potenciales que el conductor debe tener en cuenta. Para cada imagen: 1. Examine cuidadosamente la escena visual 2. Identifique cualquier peligros potenciales (peatones, vehículos, condiciones de la carretera, obstáculos, etc.) 3. Evalúe la urgencia y gravedad de cada peligro 4. Proporcione una descripción clara y específica del peligro Sea preciso y práctico en sus descripciones de peligros Céntrese en la información crítica para la seguridad.""" Prompt = ChatPrompt( mensajes=[ {"role": "system", "content": system_prompt}, { "role": "user", "content": [ {"type": "text", "text": "{question}"}, { "type": "image_url", "image_url": { "url": "{image}", }, }, ], }, ], ) # Inicializar el optimizador HRPO (Optimizador de avisos reflexivos jerárquicos) = HRPO(model="openai/gpt-5.2", model_parameters={"temperature": 1}) # Ejecutar optimización optimización_result = optimizador.optimize_prompt (prompt=prompt, conjunto de datos = conjunto de datos, conjunto de datos de validación = conjunto de datos de validación, métrica = levenshtein_ratio, max_trials = 10,) # Mostrar resultados optimización_resultado.display ()
Yendo más allá y errores comunes
Ahora ha terminado con su primera ejecución de optimización. Hay algunos consejos adicionales cuando se trabaja con optimizadores, y especialmente cuando se trabaja con agentes multimodales, para entrar en escenarios más avanzados, además de evitar algunos antipatrones comunes:
Costos y elección del modelo: las indicaciones multimodales envían cargas útiles más grandes. Supervise el uso de tokens en el panel de Opik. Si el costo es un problema, utilice un modelo de visión más pequeño. Ejecutar estos optimizadores a través de múltiples bucles puede resultar bastante costoso. En el momento de la publicación en GPT 5.2, este ejemplo nos costó alrededor de $0,15 USD. Supervise esto mientras ejecuta ejemplos para ver cómo se comporta el optimizador y detectar cualquier problema antes de escalar horizontalmente. Selección de modelo y soporte de visión: verifique que el modelo elegido admita imágenes. Es posible que algunos lanzamientos de modelos muy recientes aún no estén mapeados, por lo que es posible que tengas problemas. Mantenga sus paquetes de Python actualizados. Tamaño y formato de imagen del conjunto de datos: considere usar archivos JPEG e imágenes de menor resolución, que son más eficientes que los PNG de gran resolución, que pueden requerir más tokens debido a su tamaño. Pruebe cómo se comporta el modelo mediante llamadas API directas, el área de juegos y pequeñas ejecuciones de prueba antes de escalarlo. En la demostración que ejecutamos, el SDK convirtió automáticamente las imágenes del conjunto de datos a JPEG (60% de calidad) y una altura/ancho máximo de 512 píxeles, patrón que puede seguir. División del conjunto de datos: si tiene muchos ejemplos, divídalos en capacitación/validación. Utilice un subconjunto (n_samples) durante la optimización para encontrar un mensaje mejor y reserve datos no vistos para confirmar que la mejora se generaliza. Esto evita sobreajustar el mensaje a unos pocos elementos. Diseño de métricas de evaluación: para el optimizador reflexivo jerárquico, devuelva un ScoreResult con un motivo para cada ejemplo. Estas razones impulsan su análisis de causa raíz. Razones deficientes o faltantes pueden hacer que el optimizador sea menos efectivo. Otros optimizadores se comportan de manera diferente, por lo que saber que las evaluaciones son fundamentales para el éxito es clave; también puede ver si LLM como juez es una métrica de evaluación viable para escenarios más complejos. Iteración y registro: el script de ejemplo registra automáticamente las indicaciones y puntuaciones de cada prueba. Inspeccione estos para comprender cómo cambió el mensaje. Si los resultados se estancan, intente aumentar max_trials o utilizar un algoritmo optimizador diferente. También puede encadenar optimizadores: tome el mensaje de salida de un optimizador e introdúzcalo en otro. Esta es una buena manera de combinar múltiples enfoques y optimizadores de conjuntos para lograr una mayor eficiencia combinada. Combinar con otros métodos: también podemos combinar pasos y datos en el optimizador usando cuadros delimitadores, agregando datos adicionales a través de modelos de procesamiento visual especialmente diseñados como Meta's SAM 3 para anotar nuestros datos y proporcionar metadatos adicionales. En la práctica, nuestro conjunto de datos de entrada podría tener image e image_annotated, que pueden usarse como entrada para el optimizador.
Conclusiones y perspectivas futuras de los optimizadores
Gracias por seguir esto. Como parte de este recorrido, exploramos:
Comenzando con el agente de código abierto y optimización rápida Creación de un proceso para optimizar un agente multimodal basado en visión Evaluación con conjuntos de datos basados en imágenes en el contexto de LLM
En el futuro, la automatización del diseño rápido se está volviendo cada vez más importante a medida que avanzan los LLM con capacidad visual. Las indicaciones cuidadosamente optimizadas pueden mejorar significativamente el rendimiento del modelo en tareas multimodales complejas. Los optimizadores muestran cómo podemos aprovechar los propios LLM para refinar las instrucciones, convirtiendo un proceso largo, tedioso y muy manual en una búsqueda sistemática.
De cara al futuro, podemos empezar a ver nuevas formas de trabajar en las que los avisos automáticos y las herramientas de optimización de agentes reemplazan los métodos obsoletos de ingeniería de avisos y aprovechan plenamente la comprensión de cada modelo.
¿Disfrutaste este artículo?
Vincent Koc es un destacado ingeniero de investigación de IA, escritor y conferenciante con una gran experiencia en varias empresas globales y trabaja principalmente en el desarrollo de código abierto en inteligencia artificial con un gran interés en los enfoques de optimización. No dudes en conectarte con él en LinkedIn y X si quieres mantenerte conectado o tienes alguna pregunta sobre el ejemplo práctico.
Referencias
[1]Y Choi, et. Alabama. Optimización rápida multimodal: ¿por qué no aprovechar múltiples modalidades para MLLM? https://arxiv.org/abs/2510.09201
[2]M Suzgun, AT Kalai. Metaindicación: mejora de los modelos de lenguaje con andamiaje independiente de tareas https://arxiv.org/abs/2401.12954
[3]K Charoenpitaks, et. Alabama. Explorando el potencial de la IA multimodal para la predicción de peligros al conducir https://ieeexplore.ieee.org/document/10568360 y https://github.com/DHPR-dataset/DHPR-dataset
[4]F. Yu, et. Alabama. BDD100K: un conjunto de datos de conducción diverso para un aprendizaje multitarea heterogéneo https://arxiv.org/abs/1805.04687 y https://bair.berkeley.edu/blog/2018/05/30/bdd/
[5]Chen et. Alabama. MLLM-as-a-Judge: Evaluación de LLM-as-a-Judge multimodal con punto de referencia Vision-Language https://dl.acm.org/doi/10.5555/3692070.3692324 y https://mllm-judge.github.io/
[6]Opik. HRPO (Optimizador de avisos reflexivos jerárquicos) https://www.comet.com/docs/opik/agent_optimization/algorithms/hierarchical_adaptive_optimizer y https://www.comet.com/site/products/opik/features/automatic-prompt-optimization/
[7]Meta. Presentamos Meta Segment Anything Model 3 y Segment Anything Playground https://ai.meta.com/blog/segment-anything-model-3/