Los modelos de lenguaje grandes (LLM), los flujos de trabajo agénticos y los almacenes de vectores se han vuelto cada vez más poderosos y los marcos para optimizar el desarrollo de aplicaciones de IA han crecido en popularidad. DSPy es un kit de herramientas que proporciona módulos de propósito general que reemplazan la ingeniería rápida y la entrada directa de lenguaje natural con configuración mediante código Python.
Generalmente, trabajar con LLM o modelos fundacionales requiere una una cuidadosa ingeniería rápida, donde el usuario ajusta las instrucciones de texto para obtener los resultados correctos. Si bien este enfoque puede ser eficaz, requiere mucho tiempo y es propenso a errores, y crea cadenas de herramientas frágiles que deben actualizarse cuando se lanzan nuevas versiones de un modelo. Los marcos populares como LangChain encadenan los modelos de lenguaje para la creación de aplicaciones y LlamaIndex se enfoca en mejorar las capacidades de búsqueda dentro de los textos. Con esto, los desarrolladores aún necesitan experiencia en el ajuste de las instrucciones y tiempo para probar cada instrucción para obtener los resultados deseados. DSPy simplifica este proceso de ajuste de instrucciones con un enfoque programático para guiar y delimitar el comportamiento del modelo de lenguaje.
DSPy se centra en automatizar la optimización de la construcción de instrucciones. Para reemplazar el hackeo de instrucciones y los generadores de datos sintéticos únicos, DSPy proporciona optimizadores generales, que son algoritmos que actualizan los parámetros de su programa. Cada vez que modifique su código, datos, afirmaciones o métricas, puede compilar su programa nuevamente y DSPy realizará la optimización de instrucciones para crear nuevas instrucciones efectivas que se ajusten a sus cambios.
A veces, las personas imaginan que la optimización automática de las instrucciones significa crear un sistema en el que los LLM critiquen y mejoren las instrucciones generadas por los usuarios. Esta no es la forma más eficaz de utilizar los LLM. DSPy aprovecha el poder de la generación de ideas de los LLM para generar sus propias instrucciones. Luego, prueba esas variaciones utilizando un conjunto de métricas de evaluación para ver si resuelven mejor el problema. Si no se desempeñan numéricamente mejor en una métrica asignada por el usuario, entonces las instrucciones novedosas se desechan. Es similar a un algoritmo evolutivo en el que las instrucciones se evalúan para determinar su idoneidad y se mejoran iterativamente.
DSPy puede ser útil en varios tipos diferentes de flujos de trabajo y escenarios. Algunos de los más utilizados son la generación aumentada por recuperación, multihop question answering y el resumen de documentos.
Chain of thought (CoT) prompting simula procesos de razonamiento similares a los humanos al pedirle al modelo que descomponga tareas complejas en una secuencia de pasos lógicos hacia una resolución final. Estos pasos de razonamiento se introducen en la ventana de contexto del modelo, lo que le proporciona una mayor base en la tarea en cuestión y, a menudo, conduce a mejores respuestas incluso en escenarios complejos. DSPy ayuda haciendo que el modelo de lenguaje genere instrucciones y estrategias de cadena de pensamiento y probándolas con el modelo de lenguaje para generar las instrucciones de CoT más efectivas para el modelo dado.
Generación aumentada por recuperación
La generación aumentada por recuperación (RAG) es un enfoque que permite a los LLM aprovechar un gran corpus de conocimientos de fuentes y consultar su almacén de conocimientos para encontrar pasajes o contenidos relevantes y producir una respuesta bien refinada. La RAG garantiza que los LLM puedan utilizar dinámicamente el conocimiento en tiempo real, incluso si no se entrenaron originalmente en el tema, y dar respuestas correctas. Esta potencia adicional conduce a una mayor complejidad al configurar pipelines de RAG. DSPy ofrece un enfoque fluido para configurar pipelines de instrucciones y generar instrucciones efectivas (ajuste de instrucciones) o, en el caso de modelos más pequeños, ajustar las ponderaciones de los modelos.
Los pipelines de RAG se pueden optimizar con DSPy de dos maneras: mediante ejemplos etiquetados o ejemplos de bootstrap. Los ejemplos etiquetados son simplemente preexistentes, y los ejemplos etiquetados manualmente se utilizan para entrenar directamente el modelo de estudiante. Hace bootstrapping en el contexto de DSPy significa usar un modo de lenguaje en un paradigma de profesor y estudiante. El profesor genera nuevos ejemplos de entrenamiento basados en algunas instrucciones proporcionadas por el usuario. Estos ejemplos de bootstrapping se utilizan junto con los ejemplos etiquetados manualmente o en lugar de ellos para entrenar el módulo del estudiante hasta que proporcione las respuestas correctas. Las instrucciones que generan las respuestas correctas se actualizan iterativamente a lo largo del pipeline DSPy.
Muchas veces, una sola consulta de búsqueda no es suficiente para una tarea compleja de preguntas y respuestas. El popular conjunto de datos HotPot Question Answering consiste en preguntas que requieren múltiples análisis y recuperaciones de preguntas antes de que puedan responderse. Por ejemplo: "¿Bill Nelson voló como especialista en carga útil en un transbordador espacial lanzado por primera vez en qué año?" Esta respuesta requiere saber que Bill Nelson voló en el transbordador espacial Columbia y luego poder determinar que el Columbia voló por primera vez en 1981.
El enfoque estándar para este desafío en la literatura aumentada por recuperación es construir un sistema de búsqueda multihop. Estos sistemas leen los resultados recuperados y luego generan consultas adicionales para recopilar información adicional cuando sea necesario antes de llegar a una respuesta final. Con DSPy, puede crear el mismo sistema en unas cuantas líneas de código de una manera sólida que le permite actualizar los modelos y simplemente volver a ejecutar su pipeline.
El resumen condensa un texto más largo en una versión más corta sin dejar de conservar la información clave y las ideas principales. Es una habilidad poderosa para que un LLM funcione bien, con aplicaciones que van desde la creación de resúmenes de artículos hasta la generación de informes concisos a partir de documentos extensos.
Evaluar la calidad de los resúmenes producidos por los modelos de lenguaje presenta desafíos importantes. A diferencia de las tareas con respuestas claras correctas o incorrectas, la calidad del resumen suele ser subjetiva y depende del contexto. El modelo debe equilibrar la retención de información con la concisión, al tiempo que conserva el tono y la intención del texto original y garantiza la precisión de los hechos sin introducir errores. Adaptarse a diferentes tipos de material de origen y propósitos de resumen presenta un desafío adicional. DSPy le permite utilizar datos etiquetados para ajustar sus instrucciones de resumen para obtener las mejores respuestas posibles.
DSPy tiene su propio vocabulario y terminología; aprender algunos de esos términos clave ayudará a arrojar algo de luz sobre la arquitectura general.
Compilación: este proceso es la forma en que DSPy traduce un programa basado en Python en instrucciones que un modelo de lenguaje puede entender y ejecutar de manera eficiente.
Firma: se trata de una clase que define los tipos de entrada y salida de un módulo, lo que garantiza la compatibilidad entre diferentes módulos en un programa DSPy. Algunos ejemplos de firmas son tareas, como ingresar una pregunta y generar resultados del razonamiento y la respuesta o tomar un documento como entrada y generar resultados de un resumen.
Optimizador: este componente de DSPy ajusta el programa compilado para el modelo de lenguaje específico que está utilizando, por ejemplo, GPT3.5-Turbo o GPT-4.0 o Llama 3.1. Los optimizadores garantizan que maximice el rendimiento y la precisión de su programa. En versiones anteriores de DSPy, estos se llamaban teleprompters. Los programas DSPy consisten en múltiples llamadas a modelos de lenguaje que se apilan como módulos DSPy. Cada módulo DSPy tiene tres tipos de parámetros internos: los pesos del LM, las instrucciones que se supone que debe seguir y las demostraciones almacenadas del comportamiento de entrada/salida.
Cuando se le da una métrica, DSPy crea instrucciones optimizadas utilizando todos los pesos, instrucciones y comportamiento del modelo con algoritmos de optimización de varias etapas. Estos pueden combinar descenso de gradiente (para ponderaciones de modelos de lenguaje) y optimización discreta basada en modelos de lenguaje, es decir, para elaborar o actualizar instrucciones y para crear o validar demostraciones. Las demostraciones de DSPy son similares a los ejemplos de few-shot, pero son mucho más potentes. Se pueden crear desde cero, dado su programa, y su creación y selección se pueden optimizar de muchas maneras efectivas.
En muchos casos, la compilación conduce a mejores instrucciones que la escritura humana porque los optimizadores pueden probar más cosas, de manera mucho más sistemática, y ajustar las métricas directamente con respecto a un humano.
Pipeline: un pipeline es cómo DSPy se refiere a una secuencia de módulos conectados que trabajan juntos para lograr una tarea compleja. Por ejemplo, un pipeline podría resumir un artículo, traducirlo de un idioma de origen a un idioma de destino y luego generar preguntas sobre él en un idioma de destino.
Métricas: DSPy define varias métricas diferentes para medir el rendimiento de la salida. Por ejemplo, es posible que necesite que el resultado coincida exactamente con su etiqueta. En otros casos, una coincidencia parcial podría ser una buena opción para sus necesidades. Una métrica de uso común proporcionada por DSPy es Semantic F1. Esta métrica mide qué parte de la información de la etiqueta está contenida en la respuesta y qué tan pocos datos extraños que no están en la respuesta objetivo etiquetada están presentes en la respuesta. Si necesita una forma diferente de medir el rendimiento, también puede proporcionar sus propias métricas personalizadas.
Comenzar con DSPy es tan simple como llamar a pip install dspy-IA. No se requiere hardware especial, ya que la mayoría de los modelos se pueden usar en la nube a través de una API o ejecutarse localmente. Se puede ejecutar localmente o en entornos de notebooks alojados, como Google Colab o Watson Studio.
Un pipeline DSPy típico para la generación aumentada por recuperación consta de un modelo de lenguaje y un modelo de recuperación. Por ejemplo, para trabajar con OpenAI GPT-3.5 Turbo como el modelo de lenguaje y ColBERTV2 retriever como modelo de recuperación, configuraríamos DSPy así:
Las firmas son plantillas que le permiten configurar cómo se pueden estructurar los campos de entrada y salida para el modelo de lenguaje y el modelo de recuperación. Por ejemplo, este fragmento de código muestra la sintaxis para dar instrucciones al modelo de lenguaje con contexto y el modelo de recuperación con estructura:
Incluimos pequeñas descripciones para los campos de contexto y respuesta para definir pautas más sólidas sobre lo que el modelo recibirá y debería generar.
Una vez que haya definido sus firmas, puede ejecutar su programa y crear instrucciones óptimas para su tarea mediante el uso de un optimizador adecuado para su tarea. En DSPy, este proceso se denomina compilación. La compilación de un programa actualiza los parámetros almacenados en cada módulo. En la mayoría de los escenarios, esto consiste principalmente en recopilar y seleccionar buenas demostraciones para incluirlas en la instrucción.
La compilación requiere:
• Un conjunto de entrenamiento o ejemplos de bootstrap.
• Una métrica para la validación. En un escenario de RAG, esta sería una forma de medir qué tan precisa es la respuesta predicha y que el contexto recuperado contiene la respuesta.
• Un optimizador específico para generar instrucciones con las que realizar pruebas. Por ejemplo, el optimizador BootstrapFewShot podría usarse para generar instrucciones y luego probar esas instrucciones generadas.
Para compilar un programa DSPy, configure qué modelos desea usar y páselos al método de compilación del optimizador que ha seleccionado. Por ejemplo, un programa para una aplicación de RAG contendría un modelo de lenguaje y un modelo de recuperación. Luego, se pasarían al método de compilación y el optimizador usaría los datos recuperados para establecer el contexto para la generación del lenguaje.
A continuación, defina una métrica para evaluar tanto la recuperación como el modelo de lenguaje. Esa definición de métrica se daría a un optimizador, como BootstrapFewShot o LabeledFewShot, para que la use mientras evalúa las instrucciones generadas por el modelo de lenguaje. Finalmente, el optimizador compila un módulo personalizado que contiene el método de reenvío que ha definido con un conjunto de datos de entrenamiento.
Seleccionar qué optimizador usar generalmente requiere experimentación, pero hay pautas:
• Si tiene muy pocos ejemplos (alrededor de 10), puede comenzar con BootstrapFewShot para generar nuevos datos de entrenamiento.
• Si tiene más datos, por ejemplo, 50 ejemplos o más, pruebe BootstrapFewShotWithRandomSearch para generar nuevos datos de entrenamiento en partes aleatorias de sus datos de entrenamiento.
• Si necesita un programa muy eficiente, puede ajustar un pequeño LLM para su tarea con BootstrapFinetune.
Después de compilar su programa y comparar sus métricas, es posible que esté satisfecho con los resultados. También puede encontrar que no le gusta algo sobre el programa final o los resultados de acuerdo con las métricas elegidas. El desarrollo iterativo es clave. DSPy proporciona herramientas para hacerlo de forma incremental mediante la iteración de sus datos, la actualización de la estructura de su programa, y las métricas y el optimizador que ha elegido.
DSPy es de código abierto, por lo que puede inspeccionar el código y ver el progreso del desarrollo. Los documentos en el sitio de StanfordNLP en Github contienen la documentación y múltiples tutoriales paso a paso y demostraciones sobre cómo comenzar con DSPy.