milvus-logo
LFAI
Home
  • Integraciones

Integrar Milvus con DSPy

Open In Colab GitHub Repository

Qué es DSPy

DSPy, introducido por el Stanford NLP Group, es un marco programático innovador diseñado para optimizar las indicaciones y los pesos dentro de los modelos lingüísticos, especialmente valioso en escenarios en los que se integran grandes modelos lingüísticos (LLM) en múltiples etapas de un proceso. A diferencia de las técnicas convencionales de ingeniería de avisos, que dependen de la elaboración y los ajustes manuales, DSPy adopta un enfoque basado en el aprendizaje. Mediante la asimilación de ejemplos de preguntas-respuestas, DSPy genera mensajes optimizados de forma dinámica, adaptados a tareas específicas. Esta metodología innovadora permite reensamblar sin problemas cadenas enteras, eliminando la necesidad de realizar continuos ajustes manuales de las instrucciones. La sintaxis pitónica de DSPy ofrece varios módulos componibles y declarativos, simplificando la instrucción de los LLM.

Ventajas del uso de DSPy

  • Enfoque de programación: DSPy proporciona un enfoque de programación sistemático para el desarrollo de canalizaciones LM mediante la abstracción de canalizaciones como gráficos de transformación de texto en lugar de limitarse a indicar los LLM. Sus módulos declarativos permiten el diseño estructurado y la optimización, sustituyendo el método de ensayo y error de las plantillas tradicionales.
  • Mejora del rendimiento: DSPy demuestra una mejora significativa del rendimiento con respecto a los métodos existentes. A través de estudios de casos, supera a los avisos estándar y a las demostraciones creadas por expertos, mostrando su versatilidad y eficacia incluso cuando se compila en modelos LM más pequeños.
  • Abstracción modularizada: DSPy abstrae eficazmente los aspectos intrincados del desarrollo de canalizaciones LM, como la descomposición, el ajuste fino y la selección de modelos. Con DSPy, un programa conciso puede traducirse perfectamente en instrucciones para varios modelos, como GPT-4, Llama2-13b o T5-base, agilizando el desarrollo y mejorando el rendimiento.

Módulos

Existen numerosos componentes que contribuyen a construir un canal LLM. A continuación, describiremos algunos componentes clave para proporcionar una comprensión de alto nivel del funcionamiento de DSPy.

DSPy Modules Módulos DSPy

Firma: Las firmas en DSPy sirven como especificaciones declarativas, delineando el comportamiento de entrada/salida de los módulos, guiando el modelo de lenguaje en la ejecución de tareas. Módulo: Los módulos DSPy sirven como componentes fundamentales para los programas que aprovechan los modelos de lenguaje (LM). Abstraen diversas técnicas de instrucción, como la cadena de pensamiento o ReAct, y son adaptables para manejar cualquier firma DSPy. Con parámetros aprendibles y la capacidad de procesar entradas y producir salidas, estos módulos pueden combinarse para formar programas más amplios, inspirándose en los módulos NN de PyTorch pero adaptados a las aplicaciones LM. Optimizador: Los optimizadores en DSPy ajustan los parámetros de los programas DSPy, como las indicaciones y los pesos LLM, para maximizar las métricas especificadas como la precisión, mejorando la eficiencia del programa.

Por qué Milvus en DSPy

DSPy es un potente marco de programación que potencia las aplicaciones RAG. Estas aplicaciones necesitan recuperar información útil para mejorar la calidad de las respuestas, lo que requiere una base de datos vectorial. Milvus es una conocida base de datos vectorial de código abierto para mejorar el rendimiento y la escalabilidad. Con MilvusRM, un módulo recuperador en DSPy, la integración de Milvus se realiza sin problemas. Ahora, los desarrolladores pueden definir y optimizar fácilmente programas RAG utilizando DSPy, aprovechando las potentes capacidades de búsqueda vectorial de Milvus. Esta colaboración hace que las aplicaciones RAG sean más eficientes y escalables, combinando las capacidades de programación de DSPy con las funciones de búsqueda de Milvus.

Ejemplos

Ahora, vamos a recorrer un ejemplo rápido para demostrar cómo aprovechar Milvus en DSPy para optimizar una aplicación RAG.

Requisitos previos

Antes de construir la aplicación RAG, instale DSPy y PyMilvus.

$ pip install "dspy-ai[milvus]"
$ pip install -U pymilvus
Si estás usando Google Colab, para habilitar las dependencias recién instaladas, puede que necesites **reiniciar el runtime** (Haz click en el menú "Runtime" en la parte superior de la pantalla, y selecciona "Restart session" del menú desplegable).

Cargar el conjunto de datos

En este ejemplo, utilizamos HotPotQA, una colección de pares de preguntas-respuestas complejas, como nuestro conjunto de datos de entrenamiento. Podemos cargarlos a través de la clase HotPotQA.

from dspy.datasets import HotPotQA

# Load the dataset.
dataset = HotPotQA(
    train_seed=1, train_size=20, eval_seed=2023, dev_size=50, test_size=0
)

# Tell DSPy that the 'question' field is the input. Any other fields are labels and/or metadata.
trainset = [x.with_inputs("question") for x in dataset.train]
devset = [x.with_inputs("question") for x in dataset.dev]

Ingesta de datos en la base de datos vectorial Milvus

Introduzca la información contextual en la colección Milvus para la recuperación de vectores. Esta colección debe tener un campo embedding y un campo text. En este caso utilizamos el modelo text-embedding-3-small de OpenAI como función de incrustación de consultas por defecto.

import requests
import os

os.environ["OPENAI_API_KEY"] = "<YOUR_OPENAI_API_KEY>"
MILVUS_URI = "example.db"
MILVUS_TOKEN = ""

from pymilvus import MilvusClient, DataType, Collection
from dspy.retrieve.milvus_rm import openai_embedding_function

client = MilvusClient(uri=MILVUS_URI, token=MILVUS_TOKEN)

if "dspy_example" not in client.list_collections():
    client.create_collection(
        collection_name="dspy_example",
        overwrite=True,
        dimension=1536,
        primary_field_name="id",
        vector_field_name="embedding",
        id_type="int",
        metric_type="IP",
        max_length=65535,
        enable_dynamic=True,
    )
text = requests.get(
    "https://raw.githubusercontent.com/wxywb/dspy_dataset_sample/master/sample_data.txt"
).text

for idx, passage in enumerate(text.split("\n")):
    if len(passage) == 0:
        continue
    client.insert(
        collection_name="dspy_example",
        data=[
            {
                "id": idx,
                "embedding": openai_embedding_function(passage)[0],
                "text": passage,
            }
        ],
    )

Definir MilvusRM.

Ahora tiene que definir el MilvusRM.

from dspy.retrieve.milvus_rm import MilvusRM
import dspy

retriever_model = MilvusRM(
    collection_name="dspy_example",
    uri=MILVUS_URI,
    token=MILVUS_TOKEN,  # ignore this if no token is required for Milvus connection
    embedding_function=openai_embedding_function,
)
turbo = dspy.OpenAI(model="gpt-3.5-turbo")
dspy.settings.configure(lm=turbo)

Creación de firmas

Ahora que hemos cargado los datos, empecemos a definir las firmas para las subtareas de nuestro pipeline. Podemos identificar nuestra simple entrada question y salida answer, pero dado que estamos construyendo un pipeline RAG, recuperaremos información contextual de Milvus. Así que definamos nuestra firma como context, question --> answer.

class GenerateAnswer(dspy.Signature):
    """Answer questions with short factoid answers."""

    context = dspy.InputField(desc="may contain relevant facts")
    question = dspy.InputField()
    answer = dspy.OutputField(desc="often between 1 and 5 words")

Incluimos breves descripciones de los campos context y answer para definir directrices más claras sobre lo que el modelo recibirá y deberá generar.

Construcción de la canalización

Ahora vamos a definir el proceso RAG.

class RAG(dspy.Module):
    def __init__(self, rm):
        super().__init__()
        self.retrieve = rm

        # This signature indicates the task imposed on the COT module.
        self.generate_answer = dspy.ChainOfThought(GenerateAnswer)

    def forward(self, question):
        # Use milvus_rm to retrieve context for the question.
        context = self.retrieve(question).passages
        # COT module takes "context, query" and output "answer".
        prediction = self.generate_answer(context=context, question=question)
        return dspy.Prediction(
            context=[item.long_text for item in context], answer=prediction.answer
        )

Ejecutar el proceso y obtener los resultados

Ahora, hemos construido esta canalización RAG. Probémosla y obtengamos resultados.

rag = RAG(retriever_model)
print(rag("who write At My Window").answer)
Townes Van Zandt

Podemos evaluar los resultados cuantitativos en el conjunto de datos.

from dspy.evaluate.evaluate import Evaluate
from dspy.datasets import HotPotQA

evaluate_on_hotpotqa = Evaluate(
    devset=devset, num_threads=1, display_progress=False, display_table=5
)

metric = dspy.evaluate.answer_exact_match
score = evaluate_on_hotpotqa(rag, metric=metric)
print("rag:", score)

Optimización del programa

Después de definir este programa, el siguiente paso es la compilación. Este proceso actualiza los parámetros dentro de cada módulo para mejorar el rendimiento. El proceso de compilación depende de tres factores críticos:

  • Conjunto de entrenamiento: Utilizaremos los 20 ejemplos de pregunta-respuesta de nuestro conjunto de datos de entrenamiento para esta demostración.
  • Métrica de validación: Estableceremos una métrica sencilla validate_context_and_answer. Esta métrica verifica la precisión de la respuesta predicha y garantiza que el contexto recuperado incluye la respuesta.
  • Optimizador específico (Teleprompter): El compilador de DSPy incorpora múltiples teleprompters diseñados para optimizar sus programas de forma efectiva.
from dspy.teleprompt import BootstrapFewShot

# Validation logic: check that the predicted answer is correct.# Also check that the retrieved context does contain that answer.


def validate_context_and_answer(example, pred, trace=None):
    answer_EM = dspy.evaluate.answer_exact_match(example, pred)
    answer_PM = dspy.evaluate.answer_passage_match(example, pred)
    return answer_EM and answer_PM


# Set up a basic teleprompter, which will compile our RAG program.
teleprompter = BootstrapFewShot(metric=validate_context_and_answer)

# Compile!
compiled_rag = teleprompter.compile(rag, trainset=trainset)

# Now compiled_rag is optimized and ready to answer your new question!
# Now, let’s evaluate the compiled RAG program.
score = evaluate_on_hotpotqa(compiled_rag, metric=metric)
print(score)
print("compile_rag:", score)

La puntuación de Ragas ha aumentado de su valor anterior de 50,0 a 52,0, lo que indica una mejora en la calidad de la respuesta.

Resumen

DSPy marca un salto en las interacciones de los modelos lingüísticos gracias a su interfaz programable, que facilita la optimización algorítmica y automatizada de los teleprompters y pesos de los modelos. Al aprovechar DSPy para la implementación de la GAR, la adaptabilidad a diferentes modelos lingüísticos o conjuntos de datos se convierte en un juego de niños, reduciendo drásticamente la necesidad de tediosas intervenciones manuales.

Traducido porDeepL

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started
Feedback

¿Fue útil esta página?