Ingeniería de Inducción Cómo engañar a la IA para resolver tus problemas

Engañando a la IA para resolver problemas

7 trucos de solicitud, LangChain y código de ejemplo en Python

Este es el cuarto artículo de una serie sobre el uso de modelos de lenguaje grandes (LLMs) en la práctica. Aquí, discutiré la ingeniería de solicitudes (PE) y cómo utilizarla para construir aplicaciones habilitadas para LLM. Comienzo revisando las técnicas clave de PE y luego paso a través del código de ejemplo en Python de cómo usar LangChain para construir una aplicación basada en LLM.

Foto de Jason Leung en Unsplash

Cuando se escucha por primera vez sobre la ingeniería de solicitudes, muchas personas técnicas (incluyéndome a mí) tienden a burlarse de la idea. Podríamos pensar: “¿Ingeniería de solicitudes? Bah, eso es aburrido. Muéstreme cómo construir un LLM desde cero”.

Sin embargo, después de profundizar más en el tema, aconsejaría a los desarrolladores que no descarten automáticamente la ingeniería de solicitudes. Iría aún más lejos y diría que la ingeniería de solicitudes puede lograr el 80% del valor de la mayoría de los casos de uso de LLM con un esfuerzo (relativamente) muy bajo.

El objetivo de este artículo es transmitir este punto a través de una revisión práctica de la ingeniería de solicitudes y ejemplos ilustrativos. Si bien seguramente hay lagunas en lo que la ingeniería de solicitudes puede hacer, abre la puerta para descubrir soluciones simples e ingeniosas a nuestros problemas.

¿Qué es la ingeniería de solicitudes?

En el primer artículo de esta serie, definí la ingeniería de solicitudes como cualquier uso de un LLM tal como viene (es decir, sin entrenar ningún parámetro del modelo interno). Sin embargo, se puede decir mucho más al respecto.

  1. La ingeniería de solicitudes es “el medio por el cual los LLM se programan con solicitudes”. [1]
  2. La ingeniería de solicitudes es “un arte empírico de componer y formatear la solicitud para maximizar el rendimiento de un modelo en una tarea deseada”. [2]
  3. “los modelos de lenguaje… quieren completar documentos, por lo que puedes engañarlos para que realicen tareas simplemente organizando documentos falsos”. [3]

La primera definición transmite la innovación clave que proviene de los LLM, que es que ahora se pueden programar computadoras usando inglés simple. El segundo punto enmarca la ingeniería de solicitudes como un esfuerzo en gran medida empírico, donde los profesionales, los experimentadores y los constructores son los principales exploradores de esta nueva forma de programación.

El tercer punto (de Andrej Karpathy) nos recuerda que los LLM no están explícitamente entrenados para hacer casi cualquier cosa que les pidamos. Por lo tanto, en cierto sentido, estamos “engañando” a estos modelos de lenguaje para resolver problemas. Siento que esto captura la esencia de la ingeniería de solicitudes, que depende menos de tus habilidades técnicas y más de tu creatividad.

2 Niveles de Ingeniería de Solicitudes

Existen dos formas distintas de hacer ingeniería de solicitudes, a las que llamé “la forma fácil” y “la forma menos fácil” en el primer artículo de esta serie.

La Forma Fácil

Esta es la forma en que la mayoría del mundo hace ingeniería de solicitudes, a través de ChatGPT (o algo similar). Es una forma intuitiva, sin código y gratuita de interactuar con un LLM.

Aunque este enfoque es excelente para algo rápido y simple, como resumir una página de texto, reescribir un correo electrónico, ayudarte a generar ideas para una fiesta de cumpleaños, etc., tiene sus desventajas. Una gran desventaja es que no es fácil integrar este enfoque en un proceso automatizado más grande o en un sistema de software. Para hacer esto, necesitamos ir un paso más allá.

La Forma Menos Fácil

Esto resuelve muchas de las desventajas de la “forma fácil” al interactuar con LLMs programáticamente, es decir, utilizando Python. Tuvimos una idea de cómo hacer esto en los dos artículos anteriores de esta serie, donde exploramos la API de Python de OpenAI y la biblioteca Hugging Face Transformers.

Aunque esto requiere más conocimientos técnicos, aquí es donde radica el verdadero poder de la ingeniería de solicitudes, porque permite a los desarrolladores integrar módulos basados en LLM en sistemas de software más grandes.

Un buen ejemplo (quizás irónico) de esto es ChatGPT. El núcleo de este producto consiste en dar indicaciones a un modelo pre-entrenado (es decir, GPT-3.5-turbo) para que actúe como un chatbot y luego envolverlo en una interfaz web fácil de usar.

Por supuesto, desarrollar GPT-3.5-turbo es la parte difícil, pero eso no es algo de lo que debamos preocuparnos aquí. Con todos los LLM pre-entrenados que tenemos a nuestro alcance, casi cualquier persona con habilidades básicas de programación puede crear una poderosa aplicación de IA como ChatGPT sin necesidad de ser un investigador de IA o un doctorado en aprendizaje automático.

Creando aplicaciones de IA con Ingeniería de Indicaciones

La forma menos sencilla desbloquea un nuevo paradigma de programación y desarrollo de software. Los desarrolladores ya no están obligados a definir cada aspecto lógico de sus sistemas de software. Ahora tienen la opción de transferir una parte no trivial a los LLM. Veamos un ejemplo concreto de cómo podría ser esto.

Supongamos que quieres crear un corrector automático para una clase de historia de secundaria. Sin embargo, el problema es que todas las preguntas tienen respuestas escritas, por lo que a menudo puede haber múltiples versiones de una respuesta correcta. Por ejemplo, las siguientes respuestas a “¿Quién fue el 35º presidente de los Estados Unidos de América?” podrían ser correctas.

  • John F. Kennedy
  • JFK
  • Jack Kennedy (un apodo común)
  • John Fitzgerald Kennedy (probablemente intentando obtener crédito extra)
  • John F. Kenedy (apellido mal escrito)

En el paradigma de programación tradicional, era responsabilidad del desarrollador encontrar la manera de tener en cuenta todas estas variaciones. Para hacer esto, podrían listar todas las respuestas correctas posibles y usar un algoritmo de coincidencia exacta de cadenas o incluso usar coincidencia difusa para ayudar con las palabras mal escritas.

Sin embargo, con este nuevo paradigma habilitado por LLM, el problema puede resolverse mediante una simple ingeniería de indicaciones. Por ejemplo, podríamos usar la siguiente indicación para evaluar las respuestas de los estudiantes.

Eres un profesor de historia de secundaria corrigiendo tareas. \Basado en la pregunta de la tarea indicada por "P:" y la respuesta correcta \indicada por "R:", tu tarea es determinar si la respuesta del estudiante es \correcta. La calificación es binaria; por lo tanto, las respuestas de los estudiantes pueden ser correctas o incorrectas. Los errores ortográficos simples están bien. P: {pregunta}R: {respuesta_correcta} Respuesta del estudiante: {respuesta_del_estudiante}

Podemos pensar en esta indicación como una función, donde dados una pregunta, una respuesta_correcta y una respuesta_del_estudiante, genera la calificación del estudiante. Esto luego se puede integrar en una pieza de software más grande que implemente el corrector automático.

En términos de ahorro de tiempo, me llevó unos 2 minutos escribir esta indicación, mientras que si intentara desarrollar un algoritmo para hacer lo mismo, me tomaría horas (si no días) y probablemente tendría un peor rendimiento. Entonces el ahorro de tiempo para tareas como esta es de 100-1000 veces.

Por supuesto, hay muchas tareas en las que los LLM no brindan ningún beneficio sustancial y otros métodos existentes son mucho más adecuados (por ejemplo, predecir el clima de mañana). De ninguna manera los LLM son la solución para todos los problemas, pero sí crean un nuevo conjunto de soluciones para tareas que requieren procesar el lenguaje natural de manera efectiva, algo que históricamente ha sido difícil para las computadoras.

7 Trucos para la Ingeniería de Indicaciones

Aunque el ejemplo de indicación anterior puede parecer una forma natural y obvia de enmarcar la tarea de calificación automática, empleó deliberadamente heurísticas específicas de ingeniería de indicaciones (o “trucos”, como los llamaré). Estos (y otros) trucos han surgido como formas confiables de mejorar la calidad de las respuestas de los LLM.

Aunque hay muchos consejos y trucos para escribir buenas indicaciones, aquí limito la discusión a aquellos que parecen ser los más fundamentales (en mi opinión) basados en algunas referencias [1,3-5]. Para un análisis más profundo, recomiendo al lector que explore las fuentes citadas aquí.

Truco 1: Sé Descriptivo (Más es Mejor)

Una característica distintiva de los LLM es que se entrenan con corpora de texto masivos. Esto les proporciona un vasto conocimiento del mundo y la capacidad de realizar una enorme variedad de tareas. Sin embargo, esta impresionante generalidad puede dificultar el rendimiento en una tarea específica si no se proporciona el contexto adecuado.

Por ejemplo, comparemos dos indicaciones para generar un mensaje de cumpleaños para mi papá.

Sin Truco

Escríbeme un mensaje de cumpleaños para mi papá.

Con Truco

Escríbeme un mensaje de cumpleaños para mi papá que no exceda los 200 caracteres. Este es un cumpleaños importante porque cumple 50 años. Para celebrar, reservé un viaje de chicos a Cancún. Asegúrate de incluir un poco de humor pícaro, eso le encanta.

Truco 2: Dar Ejemplos

El siguiente truco es darle al LLM ejemplos de respuestas para mejorar su rendimiento en una tarea específica. El término técnico para esto es aprendizaje de pocas muestras, y se ha demostrado que mejora significativamente el rendimiento del LLM [6].

Veamos un ejemplo específico. Digamos que queremos escribir un subtítulo para un artículo de Towards Data Science. Podemos usar ejemplos existentes para ayudar a guiar la completación del LLM.

Sin Truco

Dado el título de un artículo de blog de Towards Data Science, escribe un subtítulo para él.Título: Ingeniería de Indicaciones: Cómo engañar a la IA para resolver tus problemasSubtítulo:

Con Truco

Dado el título de un artículo de blog de Towards Data Science, escribe un subtítulo para él.Título: Una Introducción Práctica a los LLMsSubtítulo: 3 niveles de uso de LLMs en la prácticaTítulo: Descifrando el OpenAI (Python) APISubtítulo: Una introducción completa para principiantes con código de ejemploTítulo: Ingeniería de Indicaciones: Cómo engañar a la IA para resolver tus problemasSubtítulo:

Truco 3: Usar Texto Estructurado

Asegurarse de que las indicaciones sigan una estructura organizada no solo las hace más fáciles de leer y escribir, sino que también tiende a ayudar al modelo a generar completaciones adecuadas. Empleamos esta técnica en el ejemplo para el Truco 2, donde etiquetamos explícitamente el título y el subtítulo de cada ejemplo.

Sin embargo, hay innumerables formas en las que podemos darle estructura a nuestras indicaciones. Aquí tienes algunos ejemplos: usar MAYÚSCULAS para enfatizar, usar delimitadores como “` para resaltar un cuerpo de texto, usar lenguajes de marcado como Markdown o HTML para formatear texto, usar JSON para organizar información, etc. Ahora, veamos esto en acción.

Sin Truco

Escríbeme una receta de galletas con chispas de chocolate.

Con Truco

Crea una receta bien organizada para galletas con chispas de chocolate. Utiliza los siguientes elementos de formato:**Título**: Galletas Clásicas con Chispas de Chocolate**Ingredientes**: Enumera los ingredientes con medidas precisas y formato adecuado.**Instrucciones**: Proporciona instrucciones paso a paso en formato numerado, detallando el proceso de horneado.**Consejos**: Incluye una sección separada con consejos útiles de horneado y posibles variaciones.

Truco 4: Cadena de Pensamiento

Este truco fue propuesto por Wei et al. [7]. La idea básica es guiar a un LLM a pensar “paso a paso”. Esto ayuda a descomponer problemas complejos en subproblemas manejables, lo cual le da al LLM “tiempo para pensar” [3,5]. Zhang et al. demostraron que esto puede ser tan sencillo como incluir el texto “Pensemos paso a paso” en la indicación [8].

Esta noción se puede aplicar a cualquier proceso similar a una receta. Por ejemplo, si quiero crear una publicación en LinkedIn basada en mi último blog de VoAGI, puedo guiar al LLM para que siga el proceso paso a paso que sigo yo.

Sin Truco

Escríbeme una publicación en LinkedIn basada en el siguiente blog de VoAGI.Blog de VoAGI: {Texto del blog de VoAGI}

Con Truco

Escríbeme una publicación en LinkedIn basada en el proceso paso a paso y el blog de VoAGI que se muestra a continuación.Paso 1: Idear un gancho de una línea relevante para el blog.Paso 2: Extraer 3 puntos clave del artículo.Paso 3: Comprimir cada punto a menos de 50 caracteres.Paso 4: Combinar el gancho, los puntos clave comprimidos del Paso 3 y una llamada a la acción para generar el resultado final.Blog de VoAGI: {Texto del blog de VoAGI}

Truco 5: Personas de Chatbot

Una técnica algo sorprendente que tiende a mejorar el rendimiento del LLM es hacer que adopte una determinada persona, por ejemplo, “eres un experto”. Esto es útil porque es posible que no sepas la mejor manera de describir tu problema al LLM, pero puedes saber quién podría ayudarte a resolver ese problema [1]. Así es como podría verse esto en la práctica.

Sin truco

Hazme un itinerario de viaje para un fin de semana en la ciudad de Nueva York.

Con truco

Actúa como un nativo de Nueva York y taxista que sabe todo sobre la ciudad. \Por favor, hazme un itinerario de viaje para un fin de semana en la ciudad de Nueva York basado en \tu experiencia. No olvides incluir tu encantador acento neoyorquino en tu \respuesta.

Truco 6: Enfoque Invertido

Puede ser difícil darle la mejor indicación a un LLM cuando no sabemos lo que sabe o cómo piensa. Ahí es donde puede ser útil el “enfoque invertido”. Consiste en darle indicaciones al LLM para que te haga preguntas hasta que tenga una comprensión suficiente (es decir, contexto) del problema que estás tratando de resolver.

Sin truco

¿Cuál es una idea para una aplicación basada en LLM?

Con truco

Quiero que me hagas preguntas para ayudarme a pensar en una idea de aplicación basada en LLM. Hazme una pregunta a la vez para mantener la conversación fluida.

Truco 7: Reflexionar, Revisar y Perfeccionar

Este último truco incita al modelo a reflexionar sobre sus respuestas anteriores para mejorarlas. Algunos casos de uso comunes son hacer que el modelo evalúe críticamente su propio trabajo preguntándole si “completó la tarea” o pidiéndole que “explique el razonamiento y las suposiciones” detrás de una respuesta [1, 3].

Además, puedes pedirle al LLM que perfeccione no solo sus respuestas sino también tus indicaciones. Esta es una forma sencilla de reescribir automáticamente las indicaciones para que sean más fáciles de “entender” para el modelo.

Con truco

Revisa tu respuesta anterior, identifica áreas de mejora y ofrece una versión \mejorada. Luego, explica tu razonamiento sobre cómo mejoraste la respuesta.

Código de ejemplo: Calificador automático con LangChain

Ahora que hemos revisado varias heurísticas de indicación, veamos cómo podemos aplicarlas a un caso de uso específico. Para hacer esto, volveremos al ejemplo del calificador automático que vimos antes.

Eres un profesor de historia de secundaria que califica las tareas. \Basándote en la pregunta de la tarea indicada por "P:" y la respuesta correcta \indicada por "R:", tu tarea es determinar si la respuesta del estudiante es \correcta. La calificación es binaria; por lo tanto, las respuestas de los estudiantes pueden ser correctas o incorrectas. Los errores ortográficos simples están permitidos. P: {pregunta}R: {respuesta_correcta} Respuesta del estudiante: {respuesta_estudiante}

A simple vista, algunos de los trucos mencionados anteriormente deberían ser evidentes, es decir, Truco 6: persona del chatbot, Truco 3: uso de texto estructurado y Truco 1: ser descriptivo. Esto es lo que suele ser una buena indicación en la práctica, es decir, combinar múltiples técnicas en una sola indicación.

Aunque podríamos copiar y pegar esta plantilla de indicación en ChatGPT y reemplazar los campos de pregunta, respuesta_correcta y respuesta_estudiante, este no es un método escalable para implementar el calificador automático. En cambio, lo que queremos es integrar esta indicación en un sistema de software más grande para poder construir una aplicación fácil de usar que pueda ser utilizada por una persona.

LangChain

Una forma de hacer esto es mediante LangChain, que es una biblioteca de Python que ayuda a simplificar la construcción de aplicaciones sobre modelos de lenguaje grandes. Lo hace proporcionando una variedad de abstracciones útiles para usar LLMs de forma programática.

La clase central que hace esto se llama chain (de ahí el nombre de la biblioteca). Esto abstrae el proceso de generar una indicación, enviarla a un LLM y analizar la salida para que se pueda llamar e integrar fácilmente en un script más grande.

Vamos a ver cómo usar LangChain para nuestro caso de uso de calificación automática. El código de ejemplo está disponible en el repositorio de GitHub para este artículo.

Importaciones

Comenzamos importando los módulos de biblioteca necesarios.

from langchain.chat_models import ChatOpenAIfrom langchain.prompts import PromptTemplatefrom langchain.chains import LLMChainfrom langchain.schema import BaseOutputParser

Aquí usaremos gpt-3.5-turbo, que requiere una clave secreta para la API de OpenAI. Si no tienes una, proporcioné una guía paso a paso sobre cómo obtener una en un artículo anterior de esta serie. Me gusta almacenar la clave secreta en un archivo Python separado (sk.py) e importarla con la siguiente línea de código.

from sk import my_sk #importar clave secreta desde otro archivo python

Nuestra primera cadena

Para definir nuestra cadena, necesitamos dos elementos principales: el LLM y el prompt. Comenzamos creando un objeto para el LLM.

# definir objeto LLMchat_model = ChatOpenAI(openai_api_key=my_sk, temperature=0)

LangChain tiene una clase específica para los modelos de chat de OpenAI (y muchos otros). Paso mi clave de API secreta y establezco la temperatura en 0. El modelo predeterminado aquí es gpt-3.5-turbo, pero también puedes usar gpt-4 usando el argumento de entrada “model_name”. Puedes personalizar aún más el modelo de chat configurando otros argumentos de entrada.

A continuación, definimos nuestra plantilla de prompt. Este objeto nos permite generar prompts dinámicamente a través de cadenas de entrada que actualizan automáticamente una plantilla base. Así es como se ve.

# definir plantilla de promptprompt_template_text = """Eres un profesor de historia de secundaria corrigiendo tareas. \Basado en la pregunta de la tarea indicada por "**Q:**" y la respuesta correcta indicada por "**A:**", tu tarea es determinar si la respuesta del estudiante es correcta. \La calificación es binaria; por lo tanto, las respuestas de los estudiantes pueden ser correctas o incorrectas. \Los errores ortográficos simples están bien.**Q:** {question}**A:** {correct_answer}**Respuesta del estudiante:** {student_answer}"""prompt = PromptTemplate(input_variables=["question", "correct_answer", "student_answer"], \                  template = prompt_template_text)

Con nuestro LLM y prompt, ahora podemos definir nuestra cadena.

# definir cadenachain = LLMChain(llm=chat_model, prompt=prompt)

A continuación, podemos pasar inputs a la cadena y obtener una calificación en una sola línea de código.

# definir inputsquestion = "¿Quién fue el 35º presidente de los Estados Unidos de América?"correct_answer = "John F. Kennedy"student_answer =  "FDR"# ejecutar cadenachain.run({'question':question, 'correct_answer':correct_answer, \    'student_answer':student_answer})# salida: La respuesta del estudiante es incorrecta. 

Aunque esta cadena puede realizar la tarea de calificación de manera efectiva, sus salidas pueden no ser adecuadas para un proceso automatizado. Por ejemplo, en el bloque de código anterior, el LLM indicó correctamente que la respuesta del estudiante “FDR” era incorrecta, pero sería mejor si el LLM nos diera una salida en un formato estándar que se pudiera utilizar en el procesamiento posterior.

Analizador de salida

Aquí es donde son útiles los analizadores de salida. Estas son funciones que podemos integrar en una cadena para convertir las salidas del LLM a un formato estándar. Veamos cómo podemos crear un analizador de salida que convierta la respuesta del LLM en una salida booleana (es decir, Verdadero o Falso).

# definir analizador de salidaclass GradeOutputParser(BaseOutputParser):    """Determina si la calificación fue correcta o incorrecta"""    def parse(self, text: str):        """Analiza la salida de una llamada al LLM."""        return "incorrecta" not in text.lower()

Aquí creamos un analizador de salida simple que verifica si la palabra “incorrecta” está en la salida del LLM. Si no está, devolvemos True, lo que indica que la respuesta del estudiante es correcta. De lo contrario, devolvemos False, lo que indica que la respuesta del estudiante es incorrecta.

Luego podemos incorporar este analizador de salida en nuestra cadena para analizar el texto sin problemas cuando ejecutemos la cadena.

# actualizar cadenachain = LLMChain(    llm=chat_model,    prompt=prompt,    output_parser=GradeOutputParser())

Finalmente, podemos ejecutar la cadena para una lista completa de respuestas de los estudiantes e imprimir los resultados.

# ejecutar la cadena en un bucle forstudent_answer_list = ["John F. Kennedy", "JFK", "FDR", "John F. Kenedy", \                  "John Kennedy", "Jack Kennedy", "Jacquelin Kennedy", "Robert F. Kenedy"]for student_answer in student_answer_list:    print(student_answer + " - " + str(chain.run({'question':question, 'correct_answer':correct_answer, 'student_answer':student_answer})))    print('\n')# Salida:# John F. Kennedy - True# JFK - True# FDR - False# John F. Kenedy - True# John Kennedy - True# Jack Kennedy - True# Jacqueline Kennedy - False# Robert F. Kenedy - False

YouTube-Blog/LLMs/langchain-example en main · ShawhinT/YouTube-Blog

Códigos para complementar videos de YouTube y publicaciones de blog en VoAGI. – YouTube-Blog/LLMs/langchain-example en main ·…

github.com

Limitaciones

La Ingeniería de Prompts es más que pedirle ayuda a ChatGPT para escribir un correo electrónico o aprender sobre la Computación Cuántica. Es un nuevo paradigma de programación que cambia cómo los desarrolladores pueden construir aplicaciones.

Aunque esta es una innovación poderosa, tiene sus limitaciones. Por un lado, las estrategias de promoción óptimas dependen del LLM. Por ejemplo, al promover a GPT-3 a “pensar paso a paso”, se obtuvieron mejoras significativas en tareas simples de razonamiento matemático [8]. Sin embargo, para la última versión de ChatGPT, la misma estrategia no parece ser útil (ya piensa paso a paso).

Otra limitación de la Ingeniería de Prompts es que requiere modelos de lenguaje de propósito general a gran escala, como ChatGPT, que implican costos computacionales y financieros significativos. Esto puede ser excesivo para muchos casos de uso que están más estrechamente definidos, como la coincidencia de cadenas, el análisis de sentimientos o la sumarización de texto.

Podemos superar estas limitaciones a través del ajuste fino de modelos de lenguaje pre-entrenados. Aquí es donde tomamos un modelo de lenguaje existente y lo ajustamos para un caso de uso particular. En el próximo artículo de esta serie, exploraremos técnicas populares de ajuste fino complementadas con ejemplos de código en Python.

👉 Más sobre LLMs: Introducción | OpenAI API | Hugging Face Transformers

Recursos

Conecta: Mi sitio web | Reserva una llamada | Pregúntame cualquier cosa

Redes sociales: YouTube 🎥 | LinkedIn | Twitter

Apoyo: Invítame un café ☕️

The Data Entrepreneurs

Una comunidad para emprendedores en el espacio de datos. 👉 ¡Únete a Discord!

VoAGI.com

[1] arXiv:2302.11382 [cs.SE]

[2] arXiv:2106.09685 [cs.CL]

[3] Estado de GPT por Andrej Karpathy en Microsoft Build 2023

[4] arXiv:2206.07682 [cs.CL]

[5] ChatGPT Prompt Engineering para Desarrolladores por deeplearning.ai

[6] arXiv:2005.14165 [cs.CL]

[7] arXiv:2201.11903 [cs.CL]

[8] arXiv:2210.03493 [cs.CL]