Noticias
Modelos
Productos
keyboard_arrow_down
Lector
Lea las URL y busque en la web para obtener una base más sólida para su LLM.
Incrustaciones
Integraciones multilingües y multimodales de clase mundial.
reclasificador
Recuperador neuronal de clase mundial para maximizar la relevancia de la búsqueda.
Búsqueda profunda
Busca, lee y razona hasta encontrar la mejor respuesta.
Más
keyboard_arrow_down
Clasificador
Clasificación de cero disparos y pocos disparos para imágenes y texto.
Segmentador
Corta el texto largo en fragmentos y haz tokenización.

Documentación de la API
Generación automática de código para su IDE o LLM de Copilot
open_in_new


Compañía
keyboard_arrow_down
Sobre nosotros
Contactar con ventas
Programa de prácticas
Únete a nosotros
open_in_new
Descargar logotipo
open_in_new
Términos y condiciones


Acceso
login
Lo que me gusta de DSPy
Lo que creo que DSPy puede mejorar
Obstáculos Comunes para Principiantes en DSPy
star
Presentado
Blog de tecnología
marzo 30, 2024

DSPy: No es un prompt engineering común

¡Atención! La gente del Área de la Bahía ya abandonó AVP y ahora habla de DSPy. ¿Podría DSPy convertirse en el nuevo framework de referencia para la ingeniería de prompts después de LangChain y LlamaIndex?
Screenshot of a Tetris-like game with "Score: 40" and "Press Start 2P" text on display.
Han Xiao
Han Xiao • 13 minutos de lectura
[Diapositivas] DSPy: No es tu típica ingeniería de prompts
Una presentación realizada por Han el 15 de abril de 2024 en Mountain View.
DSPy Not Your Average Prompt Engineering (1).pdf
7 MB
download-circle

Recientemente he estado investigando DSPy, un framework de vanguardia desarrollado por el grupo de NLP de Stanford dirigido a optimizar algorítmicamente los prompts de modelos de lenguaje (LM). Durante los últimos tres días, he recopilado algunas impresiones iniciales y perspectivas valiosas sobre DSPy. Ten en cuenta que mis observaciones no pretenden reemplazar la documentación oficial de DSPy. De hecho, recomiendo encarecidamente leer su documentación y README al menos una vez antes de sumergirse en esta publicación. Mi discusión aquí refleja un entendimiento preliminar de DSPy, habiendo pasado algunos días explorando sus capacidades. Hay varias funciones avanzadas, como DSPy Assertions, Typed Predictor y el ajuste de pesos de LM, que aún no he explorado a fondo.

GitHub - stanfordnlp/dspy: DSPy: The framework for programming—not prompting—foundation models
DSPy: The framework for programming—not prompting—foundation models - stanfordnlp/dspy
GitHubstanfordnlp

A pesar de mi experiencia con Jina AI, que se centra principalmente en la base de búsqueda, mi interés en DSPy no fue impulsado directamente por su potencial en la Generación Aumentada por Recuperación (RAG). En cambio, me intrigó la posibilidad de aprovechar DSPy para el ajuste automático de prompts para abordar algunas tareas de generación.

Si eres nuevo en DSPy y buscas un punto de entrada accesible, o si estás familiarizado con el framework pero encuentras que la documentación oficial es confusa o abrumadora, este artículo está destinado a ti. También opto por _no_ adherirme estrictamente al estilo de DSPy, que puede parecer desalentador para los principiantes. Dicho esto, profundicemos.

tagLo que me gusta de DSPy

tagDSPy cerrando el ciclo de la ingeniería de prompts

Lo que más me emociona de DSPy es su enfoque para cerrar el ciclo del proceso de ingeniería de prompts, transformando lo que a menudo es un proceso _manual_, _artesanal_ en un flujo de trabajo de aprendizaje automático _estructurado_, _bien definido_: es decir, preparar conjuntos de datos, definir el modelo, entrenar, evaluar y probar. En mi opinión, este es el aspecto más revolucionario de DSPy.

Viajando por el Área de la Bahía y hablando con muchos fundadores de startups centrados en la evaluación de LLM, me he encontrado con frecuentes discusiones sobre métricas, alucinaciones, observabilidad y cumplimiento. Sin embargo, estas conversaciones a menudo no progresan hacia los pasos críticos siguientes: Con todas estas métricas en la mano, ¿qué hacemos después? ¿Puede considerarse un enfoque estratégico ajustar la redacción en nuestros prompts, con la esperanza de que ciertas palabras mágicas (por ejemplo, "mi abuela se está muriendo") puedan mejorar nuestras métricas? Esta pregunta ha quedado sin respuesta por parte de muchas startups de evaluación de LLM, y era una que yo tampoco podía abordar, hasta que descubrí DSPy. DSPy introduce un método claro y programático para optimizar prompts basado en métricas específicas, o incluso para optimizar todo el pipeline de LLM, incluyendo tanto los prompts como los pesos del LLM.

Harrison, el CEO de LangChain, y Logan, el ex Jefe de Relaciones con Desarrolladores de OpenAI, han declarado en el podcast Unsupervised Learning que 2024 será un año crucial para la evaluación de LLM. Es por esta razón que creo que DSPy merece más atención de la que está recibiendo actualmente, ya que DSPy proporciona la pieza crucial que faltaba en el rompecabezas.

tagDSPy separando la lógica de la representación textual

Otro aspecto de DSPy que me impresiona es que formula la ingeniería de prompts en un módulo reproducible y agnóstico del LLM. Para lograrlo, extrae la lógica del prompt, creando una clara separación de responsabilidades entre la _lógica_ y la _representación textual_, como se ilustra a continuación.

Flowchart depicting sentiment analysis process with steps such as Prompt, Logic, and Textual Representation on a black backgr
En DSPy, el Prompt consiste en la lógica intrínseca (es decir, dspy.Module,) y su representación textual. La lógica es inmutable, reproducible, comprobable y agnóstica del LLM. La representación textual es solo la consecuencia de la lógica.

El concepto de DSPy de la lógica como la "causa" inmutable, comprobable y agnóstica del LLM, con la representación textual simplemente como su "consecuencia", puede parecer desconcertante al principio. Esto es especialmente cierto a la luz de la creencia generalizada de que "el futuro de los lenguajes de programación es el lenguaje natural". Abrazando la idea de que "la ingeniería de prompts es el futuro", uno podría experimentar un momento de confusión al encontrarse con la filosofía de diseño de DSPy. Contrario a la expectativa de simplificación, DSPy introduce una serie de módulos y sintaxis de firmas, ¡aparentemente regresando el prompting en lenguaje natural a la complejidad de la programación en C!

Pero ¿por qué adoptar este enfoque? Mi entendimiento es que en el corazón de la programación de prompts se encuentra la lógica central, con la comunicación sirviendo como un amplificador, potencialmente mejorando o disminuyendo su efectividad. La directiva "Hacer clasificación de sentimientos" representa la lógica central, mientras que una frase como "Sigue estas demostraciones o te despediré" es una forma de comunicarlo. Análogamente a las interacciones de la vida real, las dificultades para lograr las cosas a menudo no provienen de una lógica defectuosa sino de comunicaciones problemáticas. Esto explica por qué muchos, particularmente los no nativos, encuentran desafiante la ingeniería de prompts. He observado a ingenieros de software altamente competentes en mi empresa luchar con la ingeniería de prompts, no debido a una falta de lógica, sino porque no "hablan el lenguaje". Al separar la lógica del prompt, DSPy permite la programación determinista de la lógica a través de dspy.Module, permitiendo a los desarrolladores centrarse en la lógica de la misma manera que lo harían en la ingeniería tradicional, independientemente del LLM utilizado.

Entonces, si los desarrolladores se centran en la lógica, ¿quién gestiona la representación textual? DSPy asume este rol, utilizando tus datos y métricas de evaluación para refinar la representación textual—todo, desde determinar el enfoque narrativo hasta optimizar las pistas y elegir buenas demostraciones. Sorprendentemente, DSPy incluso puede usar métricas de evaluación para ajustar los pesos del LLM!

Flowchart illustrating a language model with branches for training data, logic, textual representation, and final results.

Para mí, las contribuciones clave de DSPy—cerrar el ciclo de entrenamiento y evaluación en la ingeniería de prompts y separar la lógica de la representación textual—subrayan su potencial significativo para los sistemas LLM/Agent. ¡Una visión ambiciosa sin duda, pero definitivamente necesaria!

tagLo que creo que DSPy puede mejorar

Primero, DSPy presenta una curva de aprendizaje pronunciada para los principiantes debido a sus modismos. Términos como signature, module, program, teleprompter, optimization, y compile pueden ser abrumadores. Incluso para aquellos competentes en ingeniería de prompts, navegar por estos conceptos dentro de DSPy puede ser un laberinto desafiante.

Esta complejidad refleja mi experiencia con Jina 1.0, donde introdujimos una serie de conceptos como chunk, document, driver, executor, pea, pod, querylang y flow (¡incluso diseñamos adorables stickers para ayudar a los usuarios a recordarlos!).

La mayoría de estos conceptos iniciales fueron eliminados en posteriores refactorizaciones de Jina. Hoy, solo Executor, Document y Flow han sobrevivido a "la gran purga". Agregamos un nuevo concepto, Deployment, en Jina 3.0; así que eso equilibra las cosas. 🤷

Este problema no es exclusivo de DSPy o Jina; recordemos la multitud de conceptos y abstracciones introducidos por TensorFlow entre las versiones 0.x y 1.x. Creo que este problema surge a menudo en las primeras etapas de los frameworks de software, donde hay un impulso por reflejar las notaciones académicas directamente en el código para garantizar la máxima precisión y reproducibilidad. Sin embargo, no todos los usuarios valoran tales abstracciones granulares, con preferencias que varían desde el deseo de líneas simples hasta demandas de mayor flexibilidad. Discutí extensamente este tema de la abstracción en frameworks de software en una publicación de blog de 2020, que los lectores interesados podrían encontrar útil.

Layer of Abstraction When Building "Tensorflow" for Search · Han Xiao Tech Blog - Neural Search & AI Engineering
Since Feb. 2020, I started a new venture called Jina AI. Our mission is to build an open-source neural search ecosystem for businesses and developers, ... · Han Xiao
logo

En segundo lugar, la documentación de DSPy a veces carece de consistencia. Términos como module y program, teleprompter y optimizer, o optimize y compile (a veces referidos como training o bootstrapping) se usan indistintamente, aumentando la confusión. En consecuencia, pasé mis primeras horas con DSPy tratando de descifrar exactamente qué optimiza y qué implica el proceso de bootstrapping.

A pesar de estos obstáculos, a medida que profundizas en DSPy y revisas la documentación, probablemente experimentarás momentos de claridad donde todo comienza a tener sentido, revelando las conexiones entre su terminología única y las construcciones familiares vistas en frameworks como PyTorch. Sin embargo, DSPy sin duda tiene margen de mejora en futuras versiones, particularmente en hacer el framework más accesible para ingenieros de prompts sin experiencia en PyTorch.

tagObstáculos Comunes para Principiantes en DSPy

En las siguientes secciones, he compilado una lista de preguntas que inicialmente obstaculizaron mi progreso con DSPy. Mi objetivo es compartir estas ideas con la esperanza de que puedan aclarar desafíos similares para otros estudiantes.

tag¿Qué son teleprompter, optimization y compile? ¿Qué se optimiza exactamente en DSPy?

En DSPy, "Teleprompters" es el optimizador (y parece que @lateinteraction está actualizando la documentación y el código para aclarar esto). La función compile actúa en el corazón de este optimizador, similar a llamar optimizer.optimize(). Piensa en ello como el equivalente al entrenamiento en DSPy. Este proceso compile() busca ajustar:

  • las demostraciones de few-shot,
  • las instrucciones,
  • los pesos del LLM

Sin embargo, la mayoría de los tutoriales básicos de DSPy no profundizan en el ajuste de pesos e instrucciones, lo que lleva a la siguiente pregunta.

tag¿De qué se trata el bootstrap en DSPy?

Bootstrap se refiere a la creación de demostraciones autogeneradas para el aprendizaje few-shot en contexto, una parte crucial del proceso compile() (es decir, optimización/entrenamiento como mencioné arriba). Estas demostraciones few-shot se generan a partir de datos etiquetados proporcionados por el usuario; y una demostración a menudo consiste en entrada, salida, razonamiento (por ejemplo, en Cadenas de Pensamiento), y entradas y salidas intermedias (para prompts de múltiples etapas). Por supuesto, las demostraciones few-shot de calidad son clave para la excelencia de la salida. Para ello, DSPy permite funciones métricas definidas por el usuario para asegurar que solo se elijan las demostraciones que cumplan ciertos criterios, lo que lleva a la siguiente pregunta.

tag¿Qué es la función métrica de DSPy?

Después de la experiencia práctica con DSPy, he llegado a creer que la función métrica necesita mucho más énfasis que lo que proporciona la documentación actual. La función métrica en DSPy juega un papel crucial tanto en las fases de evaluación como de entrenamiento, actuando también como función de "pérdida", gracias a su naturaleza implícita (controlada por trace=None):

def keywords_match_jaccard_metric(example, pred, trace=None):  
    # Jaccard similarity between example keywords and predicted keywords  
    A = set(normalize_text(example.keywords).split())  
    B = set(normalize_text(pred.keywords).split())  
    j = len(A & B) / len(A | B)
    if trace is not None:
        # act as a "loss" function
        return j  
    return j > 0.8  # act as evaluation

Este enfoque difiere significativamente del aprendizaje automático tradicional, donde la función de pérdida suele ser continua y diferenciable (por ejemplo, hinge/MSE), mientras que la métrica de evaluación puede ser completamente diferente y discreta (por ejemplo, NDCG). En DSPy, las funciones de evaluación y pérdida están unificadas en la función métrica, que puede ser discreta y la mayoría de las veces devuelve un valor booleano. ¡La función métrica también puede integrar un LLM! En el ejemplo siguiente, implementé una coincidencia aproximada usando LLM para determinar si el valor predicho y la respuesta estándar son similares en magnitud, por ejemplo, "1 millón de dólares" y "$1M" devolverían verdadero.

class Assess(dspy.Signature):  
    """Assess the if the prediction is in the same magnitude to the gold answer."""  
  
    gold_answer = dspy.InputField(desc='number, could be in natural language')  
    prediction = dspy.InputField(desc='number, could be in natural language')  
    assessment = dspy.OutputField(desc='yes or no, focus on the number magnitude, not the unit or exact value or wording')  
  
def same_magnitude_correct(example, pred, trace=None):  
    return dspy.Predict(Assess)(gold_answer=example.answer, prediction=pred.answer).assessment.lower() == 'yes'

Por poderosa que sea, la función métrica influye significativamente en la experiencia del usuario de DSPy, determinando no solo la evaluación final de calidad sino también afectando los resultados de la optimización. Una función métrica bien diseñada puede llevar a prompts optimizados, mientras que una mal elaborada puede hacer que la optimización falle. Al abordar un nuevo problema con DSPy, podrías encontrarte dedicando tanto tiempo a diseñar la lógica (es decir, DSPy.Module) como a la función métrica. Este doble enfoque en lógica y métricas puede ser intimidante para los principiantes.

tag"Bootstrapped 0 full traces after 20 examples in round 0" ¿qué significa esto?

Este mensaje que aparece silenciosamente durante compile() merece tu máxima atención, ya que esencialmente significa que la optimización/compilación falló, y el prompt que obtienes no es mejor que un simple few-shot. ¿Qué salió mal? He resumido algunos consejos para ayudarte a depurar tu programa DSPy cuando encuentres este mensaje:

Tu Función Métrica es Incorrecta

¿Está la función your_metric, usada en BootstrapFewShot(metric=your_metric), correctamente implementada? Realiza algunas pruebas unitarias. ¿Tu your_metric devuelve alguna vez True, o siempre devuelve False? Ten en cuenta que devolver True es crucial porque es el criterio para que DSPy considere el ejemplo bootstrapped como un "éxito". Si devuelves cada evaluación como True, ¡entonces cada ejemplo es considerado un "éxito" en el bootstrapping! Esto no es ideal, por supuesto, pero es cómo puedes ajustar la rigurosidad de la función métrica para cambiar el resultado "Bootstrapped 0 full traces". Ten en cuenta que aunque DSPy documenta que las métricas también pueden devolver valores escalares, después de revisar el código subyacente, no lo recomendaría para principiantes.

Tu Lógica (DSPy.Module) es Incorrecta

Si la función métrica es correcta, entonces necesitas verificar si tu lógica dspy.Module está correctamente implementada. Primero, verifica que la firma DSPy está correctamente asignada para cada paso. Las firmas en línea, como dspy.Predict('question->answer'), son fáciles de usar, pero por calidad, sugiero fuertemente implementar con firmas basadas en clases. Específicamente, agrega algunas docstrings descriptivas a la clase, completa los campos desc para InputField y OutputField—todo esto proporciona pistas al LM sobre cada campo. A continuación implementé dos DSPy.Module multi-etapa para resolver problemas de Fermi, uno con firma en línea, otro con firma basada en clases.

class FermiSolver(dspy.Module):
    def __init__(self):
        super().__init__()
        self.step1 = dspy.Predict('question -> initial_guess')
        self.step2 = dspy.Predict('question, initial_guess -> calculated_estimation')
        self.step3 = dspy.Predict('question, initial_guess, calculated_estimation -> variables_and_formulae')
        self.step4 = dspy.ReAct('question, initial_guess, calculated_estimation, variables_and_formulae -> gathering_data')
        self.step5 = dspy.Predict('question, initial_guess, calculated_estimation, variables_and_formulae, gathering_data -> answer')

    def forward(self, q):
        step1 = self.step1(question=q)
        step2 = self.step2(question=q, initial_guess=step1.initial_guess)
        step3 = self.step3(question=q, initial_guess=step1.initial_guess, calculated_estimation=step2.calculated_estimation)
        step4 = self.step4(question=q, initial_guess=step1.initial_guess, calculated_estimation=step2.calculated_estimation, variables_and_formulae=step3.variables_and_formulae)
        step5 = self.step5(question=q, initial_guess=step1.initial_guess, calculated_estimation=step2.calculated_estimation, variables_and_formulae=step3.variables_and_formulae, gathering_data=step4.gathering_data)
        return step5

Solucionador de problemas Fermi usando solo firma en línea

class FermiStep1(dspy.Signature):
    question = dspy.InputField(desc='Fermi problems involve the use of estimation and reasoning')
    initial_guess = dspy.OutputField(desc='Have a guess – don't do any calculations yet')

class FermiStep2(FermiStep1):
    initial_guess = dspy.InputField(desc='Have a guess – don't do any calculations yet')
    calculated_estimation = dspy.OutputField(desc='List the information you'll need to solve the problem and make some estimations of the values')

class FermiStep3(FermiStep2):
    calculated_estimation = dspy.InputField(desc='List the information you'll need to solve the problem and make some estimations of the values')
    variables_and_formulae = dspy.OutputField(desc='Write a formula or procedure to solve your problem')

class FermiStep4(FermiStep3):
    variables_and_formulae = dspy.InputField(desc='Write a formula or procedure to solve your problem')
    gathering_data = dspy.OutputField(desc='Research, measure, collect data and use your formula. Find the smallest and greatest values possible')

class FermiStep5(FermiStep4):
    gathering_data = dspy.InputField(desc='Research, measure, collect data and use your formula. Find the smallest and greatest values possible')
    answer = dspy.OutputField(desc='the final answer, must be a numerical value')

class FermiSolver2(dspy.Module):
    def __init__(self):
        super().__init__()
        self.step1 = dspy.Predict(FermiStep1)
        self.step2 = dspy.Predict(FermiStep2)
        self.step3 = dspy.Predict(FermiStep3)
        self.step4 = dspy.Predict(FermiStep4)
        self.step5 = dspy.Predict(FermiStep5)

    def forward(self, q):
        step1 = self.step1(question=q)
        step2 = self.step2(question=q, initial_guess=step1.initial_guess)
        step3 = self.step3(question=q, initial_guess=step1.initial_guess, calculated_estimation=step2.calculated_estimation)
        step4 = self.step4(question=q, initial_guess=step1.initial_guess, calculated_estimation=step2.calculated_estimation, variables_and_formulae=step3.variables_and_formulae)
        step5 = self.step5(question=q, initial_guess=step1.initial_guess, calculated_estimation=step2.calculated_estimation, variables_and_formulae=step3.variables_and_formulae, gathering_data=step4.gathering_data)
        return step5

Solucionador de problemas Fermi usando firma basada en clases con descripción más completa de cada campo.

Además, revisa la parte def forward(self, ). Para Modules multi-etapa, asegúrate de que la salida (o todas las salidas como en FermiSolver) del último paso se alimenta como entrada al siguiente paso.

Tu Problema es Simplemente Demasiado Difícil

Si tanto la métrica como el módulo parecen correctos, entonces es posible que tu problema sea simplemente demasiado desafiante y la lógica que implementaste no sea suficiente para resolverlo. Por lo tanto, DSPy encuentra que es inviable hacer bootstrap de cualquier demo dada tu lógica y función métrica. En este punto, aquí hay algunas opciones que puedes considerar:

  • Usar un LM más potente. Por ejemplo, reemplazar gpt-35-turbo-instruct con gpt-4-turbo como el LM del estudiante, usar un LM más fuerte como profesor. Esto puede ser bastante efectivo. Después de todo, un modelo más fuerte significa mejor comprensión de los prompts.
  • Mejorar tu lógica. Agregar o reemplazar algunos pasos en tu dspy.Module con otros más complicados. Por ejemplo, reemplazar Predict por ChainOfThought ProgramOfThought, agregando el paso Retrieval.
  • Agregar más ejemplos de entrenamiento. Si 20 ejemplos no son suficientes, ¡apunta a 100! Entonces puedes esperar que un ejemplo pase la verificación métrica y sea seleccionado por BootstrapFewShot.
  • Reformular el problema. A menudo, un problema se vuelve irresoluble cuando la formulación es incorrecta. Pero si cambias el ángulo para mirarlo, las cosas podrían ser mucho más fáciles y obvias.

En la práctica, el proceso involucra una mezcla de prueba y error. Por ejemplo, abordé un problema particularmente desafiante: generar un icono SVG similar a los iconos de Google Material Design basado en dos o tres palabras clave. Mi estrategia inicial fue utilizar un simple DSPy.Module que usa dspy.ChainOfThought('keywords -> svg'), emparejado con una función métrica que evaluaba la similitud visual entre el SVG generado y el SVG de Material Design de referencia, similar a un algoritmo pHash. Comencé con 20 ejemplos de entrenamiento, pero después de la primera ronda, terminé con "Bootstrapped 0 full traces after 20 examples in round 0", indicando que la optimización había fallado. Al aumentar el conjunto de datos a 100 ejemplos, revisar mi módulo para incorporar múltiples etapas y ajustar el umbral de la función métrica, finalmente logré 2 demostraciones bootstrapped y conseguí obtener algunos prompts optimizados.

Categorías:
star
Presentado
Blog de tecnología
rss_feed
Oficinas
location_on
Sunnyvale, California
710 Lakeway Dr, Ste 200, Sunnyvale, CA 94085, EE. UU.
location_on
Berlín, Alemania (sede central)
Prinzessinnenstraße 19-20, 10969 Berlín, Alemania
location_on
Beijing, China
Piso 5, Edificio 6, No.48 Haidian West St. Pekín, China
location_on
Shenzhen, China
Piso 402, Edificio de Tecnología Fu'an, Shenzhen, China
Fundación de búsqueda
Lector
Incrustaciones
reclasificador
Búsqueda profunda
Clasificador
Segmentador
Documentación API
Obtener la clave API de Jina
Límite de velocidad
Estado de la API
Compañía
Sobre nosotros
Contactar con ventas
Sala de prensa
Programa de prácticas
Únete a nosotros
open_in_new
Descargar logotipo
open_in_new
Términos
Seguridad
Términos y condiciones
Privacidad
Administrar cookies
email
Jina AI © 2020-2025.