Pular para o conteúdo
mnzes

O que é DSPy?

PorDiógenes MenezesAprendendo IA em público

13 min de leitura

DSPy é um framework Python que troca prompt escrito à mão por código declarativo. Você declara quais campos entram e quais saem de cada chamada, escolhe um módulo e fornece uma métrica com alguns casos de exemplo. Um compilador gera o texto do prompt para maximizar essa métrica. O trabalho de escrever a instrução sai da sua mão e vira saída de um processo medido.

A frase que resume o projeto, e que o paper de 2023 usa, é que pipelines de modelo costumam ser implementados com templates de prompt fixos descobertos por tentativa e erro, e que dá para tratá-los como programas em vez disso1. A mecânica exata dessa geração é o assunto de como o DSPy compila prompts; aqui o objetivo é entender o modelo de programação.

Vale começar pelo que decide se a ferramenta serve para você. Automatizar a otimização só faz sentido com métrica e conjunto de casos na mão, e isso vale igual para DSPy e para alternativas como o TextGrad. Quem chega ao framework esperando que ele produza um prompt bom a partir de nada está pedindo a coisa errada à ferramenta certa. O paper original é explícito quanto a isso.

A signature

o que você declarapergunta -> respostao que o compilador montainstrução em texto+ formato dos campos+ exemplos escolhidosuma string sóna chamada da APIcompilarrenderizar
Figura 1Você declara os campos de entrada e saída. Quem escolhe as palavras da instrução, o formato dos campos e os exemplos é o compilador, contra a sua métrica.

A unidade básica do DSPy é a signature: a declaração de quais campos entram e quais saem de uma chamada. Na forma mais curta ela cabe numa string, como pergunta -> resposta. Na forma completa você escreve uma classe com campos de entrada e de saída, cada um com uma descrição de uma linha, e uma docstring dizendo o que a chamada faz.

A diferença entre isso e um prompt é o que está ausente. A signature não contém instrução em linguagem natural sobre como responder, não define o formato da saída em prosa e não traz exemplos. Ela declara o contrato de dados e para por aí.

Quem preenche o resto é o compilador. Ele monta a instrução em texto, decide como os campos são apresentados e escolhe quais exemplos entram, e faz isso com base na métrica que você forneceu. O resultado dessa montagem é uma string comum, que segue para a API do modelo exatamente como qualquer outro prompt. Não há mágica no meio: o que muda é quem escreveu a string.

O ganho prático aparece na manutenção. Quando você acrescenta um campo de saída, não precisa reescrever um parágrafo e torcer para o modelo respeitar. Você acrescenta o campo à declaração e recompila.

Os módulos

a mesmasignaturePredictdevolve só a saídaChainOfThoughtacrescenta os passosReActpensa, chama ferramenta,responde
Figura 2Trocar o módulo muda a estratégia de raciocínio sem tocar na declaração. É a mesma signature em Predict, ChainOfThought e ReAct.

Uma signature sozinha não faz nada. Ela é executada por um módulo, que define a estratégia usada para ir da entrada à saída. Os três módulos que cobrem a maior parte dos casos:

Predict faz a chamada direta. Entra a entrada, sai a saída declarada, sem etapa intermediária.

ChainOfThought acrescenta um campo de raciocínio antes da resposta, aplicando a técnica que Wei e colegas descreveram em 2022, quando mostraram que gerar passos intermediários melhora o desempenho em tarefas de aritmética, senso comum e raciocínio simbólico em modelos suficientemente grandes2. No DSPy isso é uma troca de uma palavra no código.

ReAct intercala raciocínio e chamada de ferramenta, seguindo o padrão proposto por Yao e colegas em 2022, em que o modelo alterna entre gerar um pensamento e executar uma ação que traz informação nova do ambiente3.

A propriedade que importa é a composição. Módulos são classes Python comuns, e um programa DSPy é um módulo que chama outros módulos, com laço, condicional e tudo que Python oferece. Um pipeline de recuperação com duas rodadas de busca e uma síntese final é código normal, e o compilador enxerga a árvore inteira quando vai otimizar.

Trocar Predict por ChainOfThought é uma linha, e essa é a demonstração mais direta do argumento do projeto: a estratégia de raciocínio vira parâmetro em vez de reescrita de texto.

Módulo próprio segue a mesma forma de qualquer biblioteca de rede neural em Python: você herda da classe base, instancia os submódulos no construtor e escreve o passo em um método. A analogia é deliberada e ajuda a prever o comportamento. Assim como em uma rede, o compilador percorre a árvore de submódulos para descobrir o que é otimizável, e um submódulo já compilado pode ser congelado para não ser mexido de novo quando você otimizar o programa que o contém.

Um programa mínimo

Uma triagem de ticket de suporte, que classifica e extrai o produto citado, cabe em poucas linhas:

import dspy

class Triagem(dspy.Signature):
    """Classifica um ticket de suporte e extrai o produto citado."""
    ticket: str = dspy.InputField(desc="texto enviado pelo cliente")
    categoria: str = dspy.OutputField(desc="cobranca, bug, duvida ou outro")
    produto: str = dspy.OutputField(desc="nome do produto, ou vazio")

triagem = dspy.ChainOfThought(Triagem)
print(triagem(ticket="A fatura de junho veio dobrada no plano Pro").categoria)

O que não está ali é o ponto. Não há instrução dizendo “você é um assistente de suporte”, não há descrição em prosa do formato de saída e não há exemplo. A docstring vira a instrução inicial, e o compilador pode substituí-la por outra que meça melhor.

Trocar ChainOfThought por Predict remove o campo de raciocínio e barateia a chamada. Acrescentar um quarto campo de saída é uma linha. Nos dois casos, o prompt que chega ao modelo é remontado sozinho, e é aí que a economia de manutenção aparece: a mudança é local, e não uma reescrita de parágrafo com efeito colateral em outro lugar do texto.

Quem escreve o quê

Você escreveO DSPy geraa signature(entrada -> saída)o texto da instruçãoos módulos ea composiçãoos exemplos escolhidosa métrica eo conjuntoo formato dos campos
Figura 3A divisão de trabalho é o conceito inteiro: você fica com a estrutura e o critério, o framework fica com a redação. Errar o critério anula o resto.

Do seu lado ficam três coisas. A signature, que é o contrato de dados. Os módulos e a forma como eles se compõem, que é a estrutura do programa. E a métrica com o conjunto de casos, que é o critério.

Do lado do framework ficam outras três. O texto da instrução, os exemplos selecionados a partir do seu conjunto e o formato em que os campos são apresentados ao modelo.

Repare em qual das duas colunas concentra o risco. Nenhuma otimização conserta uma métrica que mede a coisa errada, e nenhuma seleção de exemplo conserta uma decomposição ruim da tarefa. O framework é muito bom dentro do espaço que você delimitou, e completamente cego para o espaço que você não delimitou.

De onde veio

O DSPy não apareceu do nada. O antecessor direto é o DSP, de 2022, do mesmo grupo: um framework para compor modelo de linguagem e modelo de recuperação em pipelines que passam texto entre os dois, em vez do arranjo simples de recuperar e ler. O trabalho reportava ganhos relativos de 37% a 120% sobre o modelo puro, de 8% a 39% sobre o pipeline padrão de recuperar e ler, e de 80% a 290% sobre um pipeline contemporâneo de autoperguntas4.

O DSPy, em 2023, generalizou a ideia e acrescentou a peça que faltava: o compilador. Os módulos passaram a ser parametrizados, no sentido de que podem aprender criando e coletando demonstrações, e o compilador otimiza qualquer pipeline para maximizar uma métrica dada1.

Os números do paper valem com o escopo junto. Programas compilados superaram few-shot padrão em geralmente mais de 25% com GPT-3.5 e mais de 65% com llama2-13b-chat, e superaram pipelines com demonstrações escritas por especialistas em faixas de 5% a 46% e 16% a 40%. Os autores também relatam que programas compilados para modelos abertos e relativamente pequenos ficaram competitivos com abordagens que dependiam de cadeias de prompt escritas por especialistas para o GPT-3.51. São dois estudos de caso, com aqueles modelos, naquelas tarefas.

O trabalho seguinte, de 2024, refinou o compilador para programas de vários módulos, separando a proposta de instrução da seleção de demonstração e navegando a atribuição de crédito entre módulos sem rótulos intermediários5. É de lá que vem o otimizador que a biblioteca recomenda por padrão desde então. Uma pegadinha de vocabulário sobrevive dessa época: o paper de 2023 chama esses componentes de teleprompters, a documentação passou a chamá-los de optimizers, e o caminho de importação dspy.teleprompt continuou existindo. É o mesmo objeto.

Um detalhe que costuma surpreender quem chega pelo prompt: o mesmo compilador também otimiza pesos. A biblioteca traz otimizadores que geram dados de fine-tuning a partir das próprias execuções do programa, e um trabalho de 2024 do mesmo grupo mostra que alternar entre otimizar peso e otimizar prompt supera fazer só uma das duas coisas, por até 60% e 6% em média, respectivamente, nos modelos e tarefas testados6. É por isso que a documentação fala em prompts e pesos, e não só em prompts.

DSPy não é LangChain

A comparação aparece sempre e os dois resolvem problemas diferentes.

LangChain e frameworks parecidos são de orquestração: eles ajudam a encadear chamadas, conectar ferramentas, gerenciar memória e falar com provedores diferentes por uma interface só. O texto do prompt continua sendo escrito por você, normalmente em um template com variáveis.

DSPy também compõe chamadas, mas a razão de existir dele é outra: gerar o texto do prompt a partir de uma métrica. Se você tirar o compilador, sobra um framework de orquestração com uma abstração a mais e menos integrações.

Na prática as duas coisas convivem, e a pergunta útil não é qual escolher, é onde está o seu problema. Se ele é conectar sistema, autenticar e lidar com falha de rede, o compilador não ajuda. Se ele é que ninguém sabe qual das quatro versões do prompt é melhor, orquestração não ajuda.

Onde falha

Sem conjunto, não faz nada de útil. É o limite que anula todos os outros. O compilador consome métrica e casos; sem eles você fica com uma camada de abstração e nenhum ganho de qualidade.

O prompt gerado é opaco. Ele existe, dá para imprimir e ler, e costuma ser longo e estranho. Alterar uma regra de negócio seis meses depois significa mexer na signature e recompilar, não editar uma frase. Times acostumados a corrigir prompt em produção em cinco minutos sentem essa troca.

A abstração vaza no formato. Quando a saída precisa de um formato muito específico, imposto por um contrato externo, o campo declarado nem sempre produz exatamente o que você quer, e você acaba escrevendo instrução em prosa dentro da descrição do campo. Isso funciona e desfaz parte do argumento.

A compilação envelhece com o modelo. O artefato é ajustado ao modelo e à versão medidos. Trocar o modelo pede recompilar, e quem não tiver o conjunto guardado e o pipeline reprodutível vai descobrir isso no pior momento.

A superfície da API se move. DSPy é um projeto ativo, e nomes de otimizador e assinaturas de método mudaram entre versões desde 2023. Fixe a versão e leia a documentação da versão que você fixou, porque tutorial de dois anos atrás frequentemente não roda.

Quando não vale

Três situações em que a resposta honesta é não usar.

Uma chamada só, com prompt curto e saída simples. O espaço de busca é pequeno demais para justificar a montagem, e três variações medidas à mão chegam ao mesmo lugar em uma tarde.

Prompt que muda toda semana por decisão de produto. Se a instrução acompanha uma regra de negócio em movimento, o ciclo de recompilar e revalidar vira gargalo, e a legibilidade que você perdeu passa a custar caro toda semana.

Time sem quem mantenha Python. A ferramenta é código. Em um time onde o prompt é editado por quem escreve o produto e não por quem escreve o backend, a adoção transfere a propriedade do prompt para a engenharia, e essa é uma decisão organizacional antes de ser técnica.

Como começar

  1. Escolha uma tarefa com saída verificável. Classificação, extração de campo, resposta com valor exato. É onde a métrica sai de graça.
  2. Junte 30 casos reais do seu log. Com a resposta esperada. Guarde 20% de fora, sem olhar.
  3. Escreva a signature primeiro. Campos e descrições curtas, sem instrução em prosa.
  4. Rode com Predict, sem compilar. Esse número é a linha de base.
  5. Compile e compare no mesmo conjunto. Se a diferença for menor que o ruído, a resposta é que a sua tarefa não precisava disso.
  6. Confirme no holdout. Só depois considere trocar o módulo ou aumentar o número de candidatos.

Quanto custa

Ordem de grandeza. Uma compilação típica avalia dezenas de candidatos contra o seu conjunto, então o custo é aproximadamente o tamanho do conjunto multiplicado pelo número de candidatos, multiplicado pelo custo de uma chamada. Um conjunto de 100 casos com 30 candidatos fica na casa de milhões de tokens de entrada, o que nos preços praticados em julho de 2026 dá dezenas de dólares por sessão.

O custo esquecido é o de produção. O prompt compilado quase sempre é maior que o escrito à mão, porque exemplos ajudam e o compilador vai colocá-los. Se ele dobra de tamanho e a sua aplicação faz um milhão de chamadas por mês, essa diferença supera o custo de todas as compilações juntas. Vale medir o tamanho do prompt vencedor antes de aceitar o ganho de exatidão.

Footnotes

  1. Khattab et al. (2023) descrevem o modelo de programação e o compilador, com programas compilados superando few-shot padrão em geralmente mais de 25% com GPT-3.5 e mais de 65% com llama2-13b-chat em dois estudos de caso. 2 3

  2. Wei et al. (2022) mostraram que gerar passos intermediários melhora o desempenho em aritmética, senso comum e raciocínio simbólico a partir de certa escala de modelo.

  3. Yao et al. (2022) propuseram intercalar geração de pensamento com ação no ambiente, que é o padrão implementado pelo módulo ReAct.

  4. Khattab et al. (2022) propuseram o DSP, antecessor direto, com ganhos relativos de 37% a 120% sobre o modelo puro em tarefas de perguntas e respostas de domínio aberto e multi-hop.

  5. Opsahl-Ong et al. (2024) separaram proposta de instrução de seleção de demonstração em programas de vários módulos, sem rótulos intermediários.

  6. Soylu et al. (2024) alternaram otimização de pesos e de prompts no mesmo pipeline, superando otimizar só pesos em até 60% e só prompts em até 6%, na média entre modelos e tarefas.

Perguntas frequentes

O que é DSPy?
Um framework, publicado em 2023 por um grupo de Stanford, que substitui prompt escrito à mão por código declarativo. Você declara quais campos entram e quais saem, escolhe um módulo e fornece uma métrica; um compilador gera o texto do prompt otimizado para essa métrica.
O que é uma signature no DSPy?
A declaração dos campos de entrada e de saída de uma chamada, com uma descrição curta de cada um. Ela diz o que a chamada faz e não como pedir. É a partir dela que o compilador monta a instrução, o formato dos campos e a seleção de exemplos.
DSPy é a mesma coisa que LangChain?
Não. LangChain orquestra chamadas e integrações, e você continua escrevendo o texto dos prompts. DSPy também compõe módulos, mas o objetivo dele é gerar esse texto a partir de uma métrica e de um conjunto de casos. Os dois resolvem problemas diferentes e coexistem.
Programar em vez de escrever prompt funciona mesmo?
Com métrica e conjunto, sim. No paper de 2023, programas compilados superaram few-shot padrão em geralmente mais de 25% com GPT-3.5 e mais de 65% com llama2-13b-chat. Sem métrica e sem conjunto o compilador não tem contra o que otimizar e você fica só com a abstração.
Preciso saber Python para usar DSPy?
Sim. DSPy é uma biblioteca Python e o programa é código: classes de signature, módulos compostos e uma função de métrica. Quem não escreve Python não usa a ferramenta, e essa é a barreira de entrada real, mais alta que a de escrever prompt no chat.
DSPy funciona com qualquer modelo?
Funciona com qualquer modelo que a biblioteca consiga chamar, e o resultado da compilação vale só para o modelo em que foi medido. Trocar de modelo pede recompilar, porque o prompt gerado é ajustado ao comportamento daquela versão específica.
Qual é o custo de adotar DSPy?
Dias de reescrita do pipeline, mais o custo em tokens de cada compilação, que multiplica o tamanho do conjunto pelo número de candidatos. O custo recorrente esquecido é que o prompt compilado costuma ser mais longo, e isso aparece na fatura de produção.

Referências

  1. Khattab, O. et al.. DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines (2023)arXiv:2310.03714
  2. Khattab, O. et al.. Demonstrate-Search-Predict: Composing retrieval and language models for knowledge-intensive NLP (2022)arXiv:2212.14024
  3. Opsahl-Ong, K. et al.. Optimizing Instructions and Demonstrations for Multi-Stage Language Model Programs (2024)arXiv:2406.11695
  4. Wei, J. et al.. Chain-of-Thought Prompting Elicits Reasoning in Large Language Models (2022)arXiv:2201.11903
  5. Yao, S. et al.. ReAct: Synergizing Reasoning and Acting in Language Models (2022)arXiv:2210.03629
  6. Soylu, D. et al.. Fine-Tuning and Prompt Optimization: Two Great Steps that Work Better Together (2024)arXiv:2407.10930