milvus-logo
LFAI
Home
  • Integrações
    • Orquestração

Integrar Milvus com DSPy

Open In Colab

O que é DSPy

O DSPy, introduzido pelo Stanford NLP Group, é uma estrutura programática inovadora concebida para otimizar os prompts e os pesos nos modelos de linguagem, particularmente valiosa em cenários em que os modelos de linguagem de grande dimensão (LLMs) são integrados em várias fases de um pipeline. Ao contrário das técnicas convencionais de engenharia de prompts que dependem da elaboração e dos ajustes manuais, o DSPy adopta uma abordagem baseada na aprendizagem. Ao assimilar exemplos de perguntas e respostas, o DSPy gera prompts optimizados de forma dinâmica, adaptados a tarefas específicas. Essa metodologia inovadora permite a remontagem perfeita de pipelines inteiros, eliminando a necessidade de ajustes manuais contínuos de prompts. A sintaxe Pythonic do DSPy oferece vários módulos compostáveis e declarativos, simplificando a instrução de LLMs.

Benefícios da utilização de DSPy

  • Abordagem de programação: O DSPy fornece uma abordagem de programação sistemática para o desenvolvimento de pipelines de linhas de produção, abstraindo pipelines como gráficos de transformação de texto em vez de apenas solicitar os LLMs. Os seus módulos declarativos permitem o design estruturado e a otimização, substituindo o método de tentativa e erro dos modelos tradicionais de comandos.
  • Melhoria do desempenho: O DSPy demonstra ganhos significativos de desempenho em relação aos métodos existentes. Através de estudos de caso, ele supera o desempenho do prompting padrão e das demonstrações criadas por especialistas, demonstrando sua versatilidade e eficácia mesmo quando compilado em modelos LM menores.
  • Abstração modularizada: O DSPy abstrai efetivamente os aspectos intrincados do desenvolvimento do pipeline linear, tais como decomposição, ajuste fino e seleção de modelos. Com o DSPy, um programa conciso pode ser facilmente traduzido em instruções para vários modelos, como GPT-4, Llama2-13b ou T5-base, simplificando o desenvolvimento e melhorando o desempenho.

Módulos

Existem inúmeros componentes que contribuem para a construção de um pipeline LLM. Aqui, descreveremos alguns componentes-chave para fornecer uma compreensão de alto nível de como o DSPy opera.

DSPy Modules Módulos DSPy

Assinatura: As assinaturas em DSPy servem como especificações declarativas, delineando o comportamento de entrada/saída dos módulos, orientando o modelo de linguagem na execução de tarefas. Módulo: Os módulos DSPy servem como componentes fundamentais para programas que utilizam modelos de linguagem (LMs). Abstraem várias técnicas de estímulo, como a cadeia de pensamento ou o ReAct, e são adaptáveis para lidar com qualquer assinatura DSPy. Com parâmetros que podem ser aprendidos e a capacidade de processar entradas e produzir saídas, esses módulos podem ser combinados para formar programas maiores, inspirando-se nos módulos NN do PyTorch, mas adaptados para aplicações LM. Otimizador: Os optimizadores em DSPy afinam os parâmetros dos programas DSPy, tais como prompts e pesos LLM, para maximizar as métricas especificadas como a precisão, melhorando a eficiência do programa.

Porquê Milvus em DSPy

DSPy é uma poderosa estrutura de programação que impulsiona as aplicações RAG. Estas aplicações necessitam de obter informação útil para melhorar a qualidade das respostas, o que requer uma base de dados vetorial. O Milvus é uma conhecida base de dados vetorial de código aberto para melhorar o desempenho e a escalabilidade. Com o MilvusRM, um módulo retriever em DSPy, a integração do Milvus torna-se perfeita. Agora, os programadores podem facilmente definir e otimizar programas RAG utilizando o DSPy, tirando partido das fortes capacidades de pesquisa vetorial do Milvus. Esta colaboração torna as aplicações RAG mais eficientes e escaláveis, combinando as capacidades de programação do DSPy com as funcionalidades de pesquisa do Milvus.

Exemplos

Agora, vamos analisar um exemplo rápido para demonstrar como aproveitar o Milvus no DSPy para otimizar um aplicativo RAG.

Pré-requisitos

Antes de criar o aplicativo RAG, instale o DSPy e o PyMilvus.

$ pip install "dspy-ai[milvus]"
$ pip install -U pymilvus
Se estiver usando o Google Colab, para habilitar as dependências recém-instaladas, talvez seja necessário **reiniciar o tempo de execução** (clique no menu "Tempo de execução" na parte superior da tela e selecione "Reiniciar sessão" no menu suspenso).

Carregar o conjunto de dados

Neste exemplo, utilizamos o HotPotQA, uma coleção de pares complexos de perguntas e respostas, como o nosso conjunto de dados de treino. Podemos carregá-los através da classe 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]

Ingerir dados na base de dados vetorial Milvus

Ingerir a informação de contexto na coleção Milvus para recuperação de vectores. Esta coleção deve ter um campo embedding e um campo text. Neste caso, utilizamos o modelo text-embedding-3-small da OpenAI como função de incorporação de consulta predefinida.

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.

Agora, é necessário definir o 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)

Construir assinaturas

Agora que carregámos os dados, vamos começar a definir as assinaturas para as subtarefas do nosso pipeline. Podemos identificar o nosso simples input question e output answer, mas como estamos a construir uma pipeline RAG, vamos obter informação contextual do Milvus. Assim, vamos definir a nossa assinatura 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")

Incluímos descrições curtas para os campos context e answer para definir diretrizes mais claras sobre o que o modelo irá receber e gerar.

Construir o pipeline

Agora, vamos definir o pipeline 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
        )

Executando o pipeline e obtendo os resultados

Agora, criámos este pipeline RAG. Vamos experimentá-lo e obter resultados.

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

Podemos avaliar os resultados quantitativos no conjunto de dados.

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)

Otimização do pipeline

Depois de definir esse programa, a próxima etapa é a compilação. Esse processo atualiza os parâmetros em cada módulo para melhorar o desempenho. O processo de compilação depende de três fatores críticos:

  • Conjunto de treinamento: Utilizaremos os 20 exemplos de perguntas e respostas do nosso conjunto de dados de treinamento para esta demonstração.
  • Métrica de validação: Estabeleceremos uma métrica validate_context_and_answer simples. Esta métrica verifica a exatidão da resposta prevista e garante que o contexto recuperado inclui a resposta.
  • Optimizador específico (Teleprompter): O compilador do DSPy incorpora vários teleprompters concebidos para otimizar os seus programas de forma eficaz.
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)

A pontuação Ragas aumentou do seu valor anterior de 50,0 para 52,0, indicando uma melhoria na qualidade da resposta.

Resumo

O DSPy marca um salto nas interações do modelo de linguagem por meio de sua interface programável, que facilita a otimização algorítmica e automatizada dos prompts e pesos do modelo. Ao utilizar o DSPy para a implementação do RAG, a adaptabilidade a diferentes modelos de linguagem ou conjuntos de dados torna-se muito fácil, reduzindo drasticamente a necessidade de intervenções manuais entediantes.

Traduzido porDeepLogo

Try Managed Milvus for Free

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

Get Started
Feedback

Esta página foi útil?