DSPy: Substituindo Engenharia de Prompt Frágil por Pipelines de LLM Compilados
Sempre me deparo com o mesmo obstáculo ao pensar em pipelines de IA para finanças: você pode construir algo que funciona perfeitamente nos seus casos de teste e, depois, vê-lo desmoronar silenciosamente quando um fornecedor altera o formato de uma fatura ou surge um novo tipo de transação. A fragilidade está quase sempre nos prompts — strings criadas manualmente que ninguém quer tocar. O DSPy, introduzido por Khattab et al. em Stanford e publicado no ICLR 2024, propõe uma maneira fundamentalmente diferente de construir pipelines de LLM que merece atenção cuidadosa de qualquer pessoa que tente automatizar o trabalho contábil.
O artigo
DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines (Khattab, Singhvi, Maheshwari et al., ICLR 2024) reformula a construção de pipelines de LLM como um problema de programação, em vez de um problema de engenharia de prompt. A observação central é que as aplicações modernas de LLM são tipicamente construídas como coleções de strings de prompt codificadas de forma rígida — o que os autores chamam de "modelos de prompt" — unidas pelo fluxo de controle do Python. Quando o modelo muda, ou a distribuição das tarefas se altera, alguém precisa reescrever essas strings manualmente.
O DSPy substitui os modelos de prompt por duas abstrações: assinaturas e módulos. Uma assinatura é uma especificação tipada e declarativa do que uma chamada de LM deve fazer, escrita de forma compacta como pergunta -> resposta ou com descrições de campos explícitas em uma classe Python. Um módulo envolve uma assinatura com uma estratégia de raciocínio — ChainOfThought, ReAct, ProgramOfThought, MultiChainComparison, e assim por diante. A adição crítica é um compilador (o artigo o chama de teleprompter) que recebe um programa DSPy, um pequeno conjunto de dados rotulados e uma métrica de validação, e então gera automaticamente demonstrações de poucas tentativas (few-shot), seleciona entre elas e produz prompts que são otimizados para aquela métrica. O compilador não precisa de rótulos em cada etapa intermediária — ele pode realizar o bootstrapping de demonstrações executando um programa professor em entradas não rotuladas e filtrando rastros que resultam em saídas finais corretas.
Ideias principais
- Assinaturas desacoplam a intenção da implementação. Escrever
pergunta, contexto -> respostaé suficiente para o DSPy saber como construir, invocar e otimizar a chamada de LM subjacente. O desenvolvedor nunca escreve uma string de prompt. - A compilação é um bootstrapping orientado por métricas. O otimizador
BootstrapFewShotexecuta o programa em entradas de treinamento, coleta rastros de entrada-saída onde o pipeline é bem-sucedido e os utiliza como demonstrações — sem necessidade de anotação humana nas etapas intermediárias de raciocínio. - O compilador viabiliza modelos pequenos. No GSM8K (problemas matemáticos de palavras), o Llama2-13b padrão atinge 9,4% com prompts zero-shot. Após a compilação do DSPy com módulos de reflexão e ensemble, ele chega a 46,9%. O T5-Large (770 milhões de parâmetros), um modelo que a maioria das pessoas descartou para raciocínio complexo, atinge 39,3% de correspondência exata de resposta no HotPotQA usando apenas 200 exemplos rotulados.
- Prompts de especialistas não são o teto. No GSM8K, o GPT-3.5 com prompts few-shot padrão atinge 25,2%. O chain-of-thought elaborado por especialistas eleva isso para cerca de 72–73%. O pipeline compilado de reflexão e ensemble do DSPy o leva a 81,6% — sem qualquer humano escrevendo prompts.
- Programas são composicionais. Um pipeline de QA de recuperação de múltiplos saltos no DSPy tem cerca de 12 linhas de Python. O equivalente no LangChain, observam os autores, contém 50 strings que excedem 1000 caracteres de conteúdo de prompt artesanal.
- Três estágios de compilação. O otimizador opera como: geração de candidatos (rastros de bootstrapping), otimização de parâmetros (busca aleatória ou Optuna sobre hiperparâmetros) e otimização de ordem superior (ensembles, fluxo de controle dinâmico).
O que se sustenta — e o que não
Os resultados empíricos são reais e substanciais. Ir de 9,4% para 46,9% no GSM8K com Llama2-13b, usando apenas um punhado de exemplos de treinamento rotulados, não é incremental — é o tipo de lacuna que torna modelos pequenos e baratos viáveis para tarefas que anteriormente exigiam o GPT-4. A arquitetura também é genuinamente elegante: assinaturas são fáceis de ler, módulos são composicionais e a abstração não parece apresentar falhas para as tarefas demonstradas.
As limitações são reais, embora o artigo não as discuta em uma seção dedicada. A mais importante: o compilador é apenas tão bom quanto a sua métrica. Se a sua métrica de validação for imprecisa ou desalinhada com a qualidade real da tarefa — o que é extremamente comum na prática — o otimizador encontrará maneiras inteligentes de maximizá-la enquanto falha naquilo que você realmente se importa. Em um domínio estruturado como a contabilidade, você pode definir uma métrica como "o lançamento contábil fecha", mas um lançamento equilibrado ainda pode ter códigos de conta completamente errados. Os autores sabem que esse problema existe, mas deixam isso como responsabilidade do desenvolvedor.
Uma segunda limitação: a compilação ainda requer alguns dados rotulados. O artigo afirma que você pode usar apenas 10 exemplos com BootstrapFewShot e que apenas os valores de entrada são necessários (não os rótulos intermediários). Isso é verdade no melhor dos casos, mas na prática, a confiabilidade do bootstrapping degrada quando o programa inicial não consegue resolver nenhum exemplo de treinamento. Se o seu pipeline de agente financeiro tiver uma precisão basal próxima de zero — como é comum quando você está construindo algo novo — a compilação pode não sair do lugar.
Terceiro, e mais sutil: o DSPy otimiza prompts e demonstrações, mas não otimiza a estrutura do programa em si. Se você conectou os módulos de uma forma que é fundamentalmente errada para a tarefa, o compilador não o ajudará. O design do programa ainda cabe ao desenvolvedor.
Por que isso importa para a IA financeira
O problema da fragilidade do prompt é talvez o maior obstáculo prático para implantar agentes de IA financeira em produção. Um pipeline que categoriza transações combinando descrições com códigos de conta irá degradar sempre que os dados do fornecedor mudarem de formato, sempre que uma nova categoria de gastos aparecer ou sempre que o plano de contas for atualizado. Com o DSPy, você define a tarefa de forma abstrata (transaction_description, chart_of_accounts -> account_code, confidence) e deixa o compilador descobrir as demonstrações ideais cada vez que a distribuição mudar.
Para o Beancount especificamente, vejo um pipeline estruturado em três módulos DSPy encadeados: um que extrai dados de transação estruturados de exportações bancárias brutas, um que procura a conta mais compatível no plano de contas existente do ledger e um que valida o lançamento contábil resultante contra restrições de partidas dobradas. Cada módulo recebe sua própria assinatura; o programa inteiro é compilado contra uma métrica que verifica tanto a correção contábil quanto a conformidade do formato. O problema da qualidade da métrica é mais crítico aqui — você precisa de uma métrica que detecte códigos de conta errados, não apenas lançamentos desequilibrados — mas esse é um problema de engenharia solucionável.
A implicação mais profunda: o DSPy desloca o trabalho de "escrever prompts melhores" para "escrever métricas melhores e coletar pequenos conjuntos de dados rotulados". Essa é uma prática de engenharia muito mais sustentável para um sistema financeiro de produção que precisa evoluir à medida que regulamentações, estruturas de planos de contas e formatos de transação mudam ao longo do tempo.
O que ler a seguir
- OPRO: Large Language Models as Optimizers (Yang et al., arXiv:2309.03409) — A abordagem do Google DeepMind para otimização de prompt via refinamento iterativo gerado por LM; um contraponto útil à abordagem de bootstrapping do DSPy.
- TextGrad: Automatic "Differentiation" via Text (Yuksekgonul et al., arXiv:2406.07496) — molda a otimização como retropropagação através de feedback de texto em vez de bootstrapping orientado por métricas; mostra resultados fortes em tarefas de codificação e científicas onde a abordagem do DSPy é mais fraca.
- DSPy Assertions: Computational Constraints for Self-Refining Language Model Pipelines (Singhvi et al., arXiv:2312.13382) — adiciona restrições rígidas e flexíveis aos programas DSPy, permitindo que os pipelines se autocorrijam quando as saídas violam regras de domínio; diretamente relevante para impor invariantes contábeis.
