Tech

Otimize LLM com DSPy: um guia passo a passo para construir, otimizar e avaliar sistemas de IA

À medida que as capacidades dos grandes modelos de linguagem (LLMs) continuam a expandir-se, o desenvolvimento de sistemas robustos de IA que aproveitem o seu potencial tornou-se cada vez mais complexo. As abordagens convencionais geralmente envolvem técnicas complexas de solicitação, geração de dados para ajuste fino e orientação handbook para garantir a adesão às restrições específicas do domínio. No entanto, este processo pode ser tedioso, sujeito a erros e fortemente dependente da intervenção humana.

Entre no DSPy, uma estrutura revolucionária projetada para agilizar o desenvolvimento de sistemas de IA alimentados por LLMs. O DSPy introduz uma abordagem sistemática para otimizar prompts e pesos de LM, permitindo que os desenvolvedores criem aplicativos sofisticados com o mínimo de esforço handbook.

Neste guia abrangente, exploraremos os princípios básicos do DSPy, sua arquitetura modular e a variedade de recursos poderosos que ele oferece. Também mergulharemos em exemplos práticos, demonstrando como o DSPy pode transformar a maneira como você desenvolve sistemas de IA com LLMs.

O que é DSPy e por que você precisa dele?

DSPy é uma estrutura que separa o fluxo do seu programa (modules) dos parâmetros (prompts e pesos do LM) de cada etapa. Essa separação permite a otimização sistemática de prompts e pesos de LM, permitindo construir sistemas de IA complexos com maior confiabilidade, previsibilidade e adesão a restrições específicas de domínio.

Tradicionalmente, o desenvolvimento de sistemas de IA com LLMs envolvia um processo trabalhoso de dividir o problema em etapas, elaborando instruções complexas para cada etapa, gerando exemplos sintéticos para ajuste fino e orientando manualmente os LMs para aderir a restrições específicas. Essa abordagem não period apenas demorada, mas também propensa a erros, pois mesmo pequenas alterações no pipeline, no LM ou nos dados poderiam exigir um extenso retrabalho de prompts e etapas de ajuste fino.

O DSPy aborda esses desafios introduzindo um novo paradigma: otimizadores. Esses algoritmos orientados por LM podem ajustar os prompts e os pesos de suas chamadas LM, de acordo com uma métrica que você deseja maximizar. Ao automatizar o processo de otimização, o DSPy capacita os desenvolvedores a construir sistemas robustos de IA com intervenção handbook mínima, aumentando a confiabilidade e a previsibilidade dos resultados do LM.

Arquitetura Modular do DSPy

No coração do DSPy está uma arquitetura modular que facilita a composição de sistemas complexos de IA. A estrutura fornece um conjunto de módulos integrados que abstraem várias técnicas de immediate, como dspy.ChainOfThought e dspy.ReAct. Esses módulos podem ser combinados e compostos em programas maiores, permitindo que os desenvolvedores construam pipelines complexos adaptados às suas necessidades específicas.

Cada módulo encapsula parâmetros que podem ser aprendidos, incluindo instruções, exemplos de poucas tentativas e pesos LM. Quando um módulo é invocado, os otimizadores do DSPy podem ajustar esses parâmetros para maximizar a métrica desejada, garantindo que as saídas do LM cumpram as restrições e requisitos especificados.

Otimizando com DSPy

DSPy apresenta uma gama de otimizadores poderosos projetados para aprimorar o desempenho e a confiabilidade de seus sistemas de IA. Esses otimizadores aproveitam algoritmos orientados por LM para ajustar os prompts e pesos de suas chamadas LM, maximizando a métrica especificada e ao mesmo tempo aderindo às restrições específicas do domínio.

Alguns dos principais otimizadores disponíveis no DSPy incluem:

  1. BootstrapFewShot: este otimizador estende a assinatura gerando e incluindo automaticamente exemplos otimizados no immediate enviado ao modelo, implementando aprendizado rápido.
  2. BootstrapFewShotWithRandomSearch: Aplica-se BootstrapFewShot diversas vezes com busca aleatória nas demonstrações geradas, selecionando o melhor programa em detrimento da otimização.
  3. MIPRO: Gera instruções e exemplos rápidos em cada etapa, com a geração de instruções ciente de dados e de demonstração. Ele usa otimização bayesiana para pesquisar com eficácia o espaço de instruções de geração e demonstrações em seus módulos.
  4. BootstrapFinetune: destila um programa DSPy baseado em immediate em atualizações de peso para LMs menores, permitindo ajustar o(s) LLM(s) subjacente(s) para maior eficiência.

Ao aproveitar esses otimizadores, os desenvolvedores podem otimizar sistematicamente seus sistemas de IA, garantindo resultados de alta qualidade e, ao mesmo tempo, aderindo às restrições e requisitos específicos do domínio.

Introdução ao DSPy

Para ilustrar o poder do DSPy, vamos examinar um exemplo prático de construção de um sistema de geração aumentada de recuperação (RAG) para resposta a perguntas.

Etapa 1: Configurando o modelo de linguagem e o modelo de recuperação

A primeira etapa envolve a configuração do modelo de linguagem (LM) e do modelo de recuperação (RM) no DSPy.

Para instalar o DSPy, execute:

pip set up dspy-ai

O DSPy oferece suporte a várias APIs LM e RM, bem como hospedagem de modelos locais, facilitando a integração de seus modelos preferidos.

import dspy
# Configure the LM and RM
turbo = dspy.OpenAI(mannequin='gpt-3.5-turbo')
colbertv2_wiki17_abstracts = dspy.ColBERTv2(url='http://20.102.90.50:2017/wiki17_abstracts')
dspy.settings.configure(lm=turbo, rm=colbertv2_wiki17_abstracts)

Etapa 2: Carregando o conjunto de dados

A seguir, carregaremos o conjunto de dados HotPotQA, que contém uma coleção de pares complexos de perguntas e respostas, normalmente respondidos em vários saltos.

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)
# Specify the 'query' discipline because the enter
trainset = (x.with_inputs('query') for x in dataset.practice)
devset = (x.with_inputs('query') for x in dataset.dev)

Etapa 3: Construindo Assinaturas

DSPy usa assinaturas para definir o comportamento dos módulos. Neste exemplo, definiremos uma assinatura para a tarefa de geração de resposta, especificando os campos de entrada (contexto e pergunta) e o campo de saída (resposta).

class GenerateAnswer(dspy.Signature):
"""Reply questions with brief factoid solutions."""
context = dspy.InputField(desc="could comprise related details")
query = dspy.InputField()
reply = dspy.OutputField(desc="usually between 1 and 5 phrases")

Etapa 4: Construindo o Pipeline

Construiremos nosso pipeline RAG como um módulo DSPy, que consiste em um método de inicialização (__init__) para declarar os submódulos (dspy.Retrieve e dspy.ChainOfThought) e um método ahead (ahead) para descrever o fluxo de controle de resposta a questão usando esses módulos.

class RAG(dspy.Module):
    def __init__(self, num_passages=3):
    tremendous().__init__()
        self.retrieve = dspy.Retrieve(okay=num_passages)
        self.generate_answer = dspy.ChainOfThought(GenerateAnswer)
    def ahead(self, query):
        context = self.retrieve(query).passages
        prediction = self.generate_answer(context=context, query=query)
        return dspy.Prediction(context=context, reply=prediction.reply)

Etapa 5: Otimizando o Pipeline

Com o pipeline definido, agora podemos otimizá-lo usando os otimizadores do DSPy. Neste exemplo, usaremos o otimizador BootstrapFewShot, que gera e seleciona prompts efetivos para nossos módulos com base em um conjunto de treinamento e uma métrica para validação.

from dspy.teleprompt import BootstrapFewShot
# Validation metric
def validate_context_and_answer(instance, pred, hint=None):
answer_EM = dspy.consider.answer_exact_match(instance, pred)
answer_PM = dspy.consider.answer_passage_match(instance, pred)
return answer_EM and answer_PM
# Arrange the optimizer
teleprompter = BootstrapFewShot(metric=validate_context_and_answer)
# Compile this system
compiled_rag = teleprompter.compile(RAG(), trainset=trainset)

Etapa 6: avaliando o pipeline

Depois de compilar o programa, é essencial avaliar seu desempenho em um conjunto de desenvolvimento para garantir que atenda à precisão e confiabilidade desejadas.

from dspy.consider import Consider
# Arrange the evaluator
consider = Consider(devset=devset, metric=validate_context_and_answer, num_threads=4, display_progress=True, display_table=0)
# Consider the compiled RAG program
evaluation_result = consider(compiled_rag)
print(f"Analysis Outcome: {evaluation_result}")

Etapa 7: inspecionando o histórico do modelo

Para uma compreensão mais profunda das interações do modelo, você pode revisar as gerações mais recentes inspecionando o histórico do modelo.

# Examine the mannequin's historical past
turbo.inspect_history(n=1)

Etapa 8: fazendo previsões

Com o pipeline otimizado e avaliado, agora você pode usá-lo para fazer previsões sobre novas questões.

# Instance query
query = "Which award did Gary Zukav's first e-book obtain?"
# Make a prediction utilizing the compiled RAG program
prediction = compiled_rag(query)
print(f"Query: {query}")
print(f"Reply: {prediction.reply}")
print(f"Retrieved Contexts: {prediction.context}")

Exemplo mínimo de trabalho com DSPy

Agora, vamos examinar outro exemplo mínimo de trabalho usando o conjunto de dados GSM8K e o modelo OpenAI GPT-3.5-turbo para simular tarefas de immediate no DSPy.

Configurar

Primeiro, certifique-se de que seu ambiente esteja configurado corretamente:

import dspy
from dspy.datasets.gsm8k import GSM8K, gsm8k_metric
# Arrange the LM
turbo = dspy.OpenAI(mannequin='gpt-3.5-turbo-instruct', max_tokens=250)
dspy.settings.configure(lm=turbo)
# Load math questions from the GSM8K dataset
gsm8k = GSM8K()
gsm8k_trainset, gsm8k_devset = gsm8k.practice(:10), gsm8k.dev(:10)
print(gsm8k_trainset)

O gsm8k_trainset e gsm8k_devset conjuntos de dados contêm uma lista de exemplos com cada exemplo tendo um campo de perguntas e respostas.

Defina o Módulo

A seguir, defina um programa personalizado utilizando o módulo ChainOfThought para raciocínio passo a passo:

class CoT(dspy.Module):
def __init__(self):
tremendous().__init__()
self.prog = dspy.ChainOfThought("query -> reply")
def ahead(self, query):
return self.prog(query=query)

Compilar e avaliar o modelo

Agora compile-o com o BootstrapFewShot teleprompter:

from dspy.teleprompt import BootstrapFewShot
# Arrange the optimizer
config = dict(max_bootstrapped_demos=4, max_labeled_demos=4)
# Optimize utilizing the gsm8k_metric
teleprompter = BootstrapFewShot(metric=gsm8k_metric, **config)
optimized_cot = teleprompter.compile(CoT(), trainset=gsm8k_trainset)
# Arrange the evaluator
from dspy.consider import Consider
consider = Consider(devset=gsm8k_devset, metric=gsm8k_metric, num_threads=4, display_progress=True, display_table=0)
consider(optimized_cot)
# Examine the mannequin's historical past
turbo.inspect_history(n=1)

Este exemplo demonstra como configurar seu ambiente, definir um módulo personalizado, compilar um modelo e avaliar rigorosamente seu desempenho usando o conjunto de dados fornecido e as configurações de teleprompter.

Gerenciamento de dados em DSPy

DSPy opera com conjuntos de treinamento, desenvolvimento e teste. Para cada exemplo nos seus dados, normalmente você tem três tipos de valores: entradas, rótulos intermediários e rótulos finais. Embora os rótulos intermediários ou finais sejam opcionais, é essencial ter alguns exemplos de entradas.

Criando objetos de exemplo

Objetos de exemplo em DSPy são semelhantes aos dicionários Python, mas vêm com utilitários úteis:

qa_pair = dspy.Instance(query="It is a query?", reply="That is a solution.")
print(qa_pair)
print(qa_pair.query)
print(qa_pair.reply)

Saída:

Instance({'query': 'It is a query?', 'reply': 'That is a solution.'}) (input_keys=None)
It is a query?
That is a solution.

Especificando chaves de entrada

No DSPy, os objetos de exemplo têm um método with_inputs() para marcar campos específicos como entradas:

print(qa_pair.with_inputs("query"))
print(qa_pair.with_inputs("query", "reply"))

Os valores podem ser acessados ​​usando o operador ponto, e métodos como inputs() e rótulos() retornam novos objetos de exemplo contendo apenas chaves de entrada ou não, respectivamente.

Otimizadores em DSPy

Um otimizador DSPy ajusta os parâmetros de um programa DSPy (isto é, prompts e/ou pesos LM) para maximizar métricas especificadas. O DSPy oferece vários otimizadores integrados, cada um empregando estratégias diferentes.

Otimizadores disponíveis

  • BootstrapFewShot: gera exemplos rápidos usando pontos de dados de entrada e saída rotulados fornecidos.
  • BootstrapFewShotWithRandomSearch: aplica BootstrapFewShot várias vezes com pesquisa aleatória nas demonstrações geradas.
  • EU COPRO: Gera e refina novas instruções para cada etapa, otimizando-as com subida coordenada.
  • MIPRO: otimiza instruções e exemplos rápidos usando a otimização bayesiana.

Escolhendo um otimizador

Se você não souber por onde começar, use BootstrapFewShotWithRandomSearch:

Para poucos dados (10 exemplos), use BootstrapFewShot.
Para um pouco mais de dados (50 exemplos), use BootstrapFewShotWithRandomSearch.
Para conjuntos de dados maiores (mais de 300 exemplos), use MIPRO.

Veja como usar BootstrapFewShotWithRandomSearch:

from dspy.teleprompt import BootstrapFewShotWithRandomSearch
config = dict(max_bootstrapped_demos=4, max_labeled_demos=4, num_candidate_programs=10, num_threads=4)
teleprompter = BootstrapFewShotWithRandomSearch(metric=YOUR_METRIC_HERE, **config)
optimized_program = teleprompter.compile(YOUR_PROGRAM_HERE, trainset=YOUR_TRAINSET_HERE)

Salvando e carregando programas otimizados

Depois de executar um programa através de um otimizador, salve-o para uso futuro:

otimizado_program.save(SEU_SAVE_PATH)

Carregue um programa salvo:

loaded_program = YOUR_PROGRAM_CLASS()
loaded_program.load(path=YOUR_SAVE_PATH)

Recursos avançados: Asserções DSPy

As asserções DSPy automatizam a aplicação de restrições computacionais em LMs, aumentando a confiabilidade, previsibilidade e correção das saídas de LM.

Usando Asserções

Definir funções de validação e declarar asserções após a respectiva geração do modelo. Por exemplo:

dspy.Recommend(
len(question) <= 100,
"Question needs to be brief and fewer than 100 characters",
)
dspy.Recommend(
validate_query_distinction_local(prev_queries, question),
"Question needs to be distinct from: " + "; ".be a part of(f"{i+1}) {q}" for i, q in enumerate(prev_queries)),
)

Transformando Programas com Asserções

from dspy.primitives.assertions import assert_transform_module, backtrack_handler
baleen_with_assertions = assert_transform_module(SimplifiedBaleenAssertions(), backtrack_handler)

Alternativamente, ative as asserções diretamente no programa:

baleen_with_assertions = SimplifiedBaleenAssertions().activate_assertions()

Otimizações baseadas em asserções

As asserções DSPy funcionam com otimizações DSPy, especialmente com BootstrapFewShotWithRandomSearch, incluindo configurações como:

  • Compilação com Asserções
  • Compilação + Inferência com Asserções

Conclusão

DSPy oferece uma abordagem poderosa e sistemática para otimizar modelos de linguagem e seus prompts. Seguindo as etapas descritas nestes exemplos, você pode construir, otimizar e avaliar sistemas complexos de IA com facilidade. O design modular e os otimizadores avançados do DSPy permitem a integração eficiente e eficaz de vários modelos de linguagem, tornando-o uma ferramenta valiosa para qualquer pessoa que trabalhe na área de PNL e IA.

Esteja você construindo um sistema simples de resposta a perguntas ou um pipeline mais complexo, o DSPy fornece a flexibilidade e a robustez necessárias para alcançar alto desempenho e confiabilidade.

Unite AI Mobile Newsletter 1

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button