05 - Auto-prompt optimization — DSPy e além

TL;DR

Auto-prompt optimization transforma prompt de “string artesanal” em “programa compilado”: você declara o que quer (Signatures de input/output em DSPy), declara a métrica de sucesso (eval function), o compilador otimiza a versão final do prompt contra exemplos. DSPy (Stanford, Khattab et al., 2023) é o framework de referência em 2026: Signatures, Modules, Compilers (BootstrapFewShot, MIPRO, COPRO). Vizinhos: APE (Zhou et al., 2023) gera candidatos via LLM-meta-prompter, OPRO (Yang et al., 2023) trata LLM como otimizador iterativo, promptbreeder (Fernando et al., 2023) usa evolução. Quando auto-prompt vence: pipeline com várias chamadas LM, eval claro, iteração repetida. Quando manual vence: one-shot alto-risco, edge-case que exige judgment, ausência de eval confiável. Estado 2026: real e crescente em produção, mas longe de “default” — muito uso ainda é experimental ou em pipeline acadêmico.

Por que existe

Prompt engineering manual é caro (tempo do humano), inconsistente (cada engenheiro com seu estilo) e mal escala (10 prompts × 5 modelos × 3 versões = matriz que explode). Auto-prompt parte da premissa: se você consegue definir uma métrica de sucesso, dá pra otimizar o prompt em vez de artesanar.

Analogias úteis (com cautela):

  • Compilador de software: você escreve em linguagem de alto nível (Signature), compilador gera código de baixo nível (prompt) otimizado pra a target.
  • AutoML: em vez de tunar hiperparâmetros à mão, você define busca + métrica + dataset, e algoritmo encontra a melhor combinação.

Diferença pro caso de prompt: a “linguagem de alto nível” ainda inclui muita ambiguidade (descrição em PT/EN), e o “compilador” ainda depende de muitos shots da LM. Não é compilação clássica — é otimização orientada por exemplos e eval function.

DSPy — Signatures, Modules, Compilers

DSPy (Khattab et al., 2023) é o framework de referência em 2026. Três abstrações centrais:

Signature — o “tipo” do prompt

Declaração de input/output do passo LM, sem dizer como prompted:

import dspy
 
class SummarizeArticle(dspy.Signature):
    """Resuma um artigo em 3 bullets factuais."""
    article: str = dspy.InputField(desc="texto do artigo")
    summary: list[str] = dspy.OutputField(desc="exatamente 3 bullets factuais")

Signature é spec, não prompt. O prompt vai ser gerado/otimizado depois.

Module — a chamada LM com a signature

Module instancia a Signature numa chamada concreta:

class Summarizer(dspy.Module):
    def __init__(self):
        super().__init__()
        self.generate = dspy.ChainOfThought(SummarizeArticle)
 
    def forward(self, article: str):
        return self.generate(article=article)
 
summarizer = Summarizer()
result = summarizer(article="...")
# result.summary = ["bullet 1", "bullet 2", "bullet 3"]

O dspy.ChainOfThought é um padrão de module que adiciona reasoning antes do output. Outros: dspy.Predict (direto), dspy.ReAct (com tool use).

Compiler — otimiza o prompt contra exemplos + eval function

# 1. Dataset com exemplos rotulados (ou só inputs, dependendo do compiler)
trainset = [
    dspy.Example(article="...", summary=["...", "...", "..."]).with_inputs("article"),
    # ... mais exemplos
]
 
# 2. Eval function — diz quão boa é uma resposta
def evaluate_summary(example, pred, trace=None) -> bool:
    # Pred é o output do module; example é o ground truth
    if len(pred.summary) != 3:
        return False
    # Critério qualquer: cobertura, faithfulness, factualidade...
    return judge_with_llm(article=example.article, summary=pred.summary)
 
# 3. Compila — testa few-shot variations, escolhe a melhor
from dspy.teleprompt import BootstrapFewShot
 
teleprompter = BootstrapFewShot(metric=evaluate_summary, max_bootstrapped_demos=4)
compiled_summarizer = teleprompter.compile(summarizer, trainset=trainset)
 
# 4. Usa compiled como qualquer module — agora com few-shot otimizado
result = compiled_summarizer(article="...")

O BootstrapFewShot é o compiler mais simples: roda o module sem few-shot no trainset, mantém os casos que passam no eval, usa eles como few-shot. Outros compilers mais sofisticados:

  • MIPRO / MIPROv2 — otimiza instruções e few-shot demos via busca bayesiana sobre o espaço de prompts; um dos mais usados em 2026
  • COPRO — otimiza só a instrução (texto do system) via meta-prompter
  • BootstrapFinetune — combina prompt otimizado com fine-tune

Diferença prática:

CompilerOtimizaCusto de compilaçãoQuando
BootstrapFewShotApenas few-shot demosBaixoStart; dataset pequeno
MIPRO/MIPROv2Instruções + few-shotMédio-altoQuando vale investir mais; melhor performance
COPROApenas instruçãoMédioQuando dataset não tem ground truth pra few-shot

Vizinhos do DSPy

APE — Automatic Prompt Engineer

Zhou et al., 2023 — APE usa um LLM-meta-prompter pra gerar candidatos de prompt a partir de input/output examples, depois ranqueia os candidatos por eval. Mais simples conceitualmente que DSPy: gera prompt → testa → escolhe melhor.

Pesquisa fundadora; em 2026 a maior parte da implementação prática migrou pra DSPy ou framework similar com primitives mais expressivas.

OPRO — LLMs as Optimizers

Yang et al., 2023 — OPRO trata o LLM como otimizador iterativo: o meta-prompt mostra “aqui estão prompts já tentados e seus scores, sugira o próximo”. O modelo aprende a partir do histórico do próprio experimento.

Forte em domínios onde o gradient de “o que melhora” é capturável em natural language. Menos usado em produção (custo de iteração + dependência do meta-modelo).

Promptbreeder

Fernando et al., 2023 — usa evolução genética sobre população de prompts: mutações (LLM reescreve um prompt), seleção (eval ranqueia), próximo geração. Pesquisa interessante, adoção em produção tímida.

Quando auto-prompt vence

Cenários onde o trabalho de configurar auto-prompt paga:

CenárioPor quê
Pipeline com várias chamadas LMOtimizar 5 prompts à mão = 5x o esforço; DSPy otimiza tudo junto contra eval end-to-end
Eval function clara e barataBootstrapFewShot precisa rodar eval várias vezes; eval caro = compilação cara
Otimização repetida (modelo novo)Mudou de Sonnet pra Opus? Recompila em vez de re-engenheirar 5 prompts à mão
Dataset com ground truth disponívelGround truth viabiliza few-shot selection automática
Tolerância pra prompt “feio”Compiler pode gerar prompts longos e estranhos; aceitar isso é parte do contrato

Quando manual vence

Cenários onde artesanato vence:

CenárioPor quê
One-shot alto-riscoInvestir em DSPy pra um prompt = overkill
Edge case que exige judgmentCompiler otimiza pro caso médio; edge precisa tuning explícito
Eval function frágil ou ausenteSem eval, compiler não sabe pra onde otimizar
Restrições de schema rígidasCompiler pode adicionar “ruído” no prompt que quebra schema em casos não cobertos pelo eval
Prompt safety-criticalCada token do prompt importa; compiler escolher por você é arriscado
Iteração rápida com produto/PMAuto-compila é assíncrono; conversa rápida é manual

Quando combinar — auto + manual

Em produção real, raramente é puro auto ou puro manual. Pattern recomendado:

1. Humano escreve Signature + base prompt + eval function (parte criativa, alto-nível)
2. DSPy compila few-shot e instruções contra eval (parte chata, alto-volume)
3. Humano revisa o prompt compilado, descarta partes problemáticas, ajusta
4. Recompila com a versão revisada como base
5. Promove se eval em produção confirma

A humano define o espaço (Signature, métrica), o compilador busca dentro do espaço.

Eval function — o ponto mais crítico do setup

Auto-prompt é só tão bom quanto sua eval function. Se eval mede a coisa errada, compiler vai gerar o prompt errado. Princípios:

  • Eval rápido — vai rodar centenas de vezes durante compilação; segundos importam
  • Eval estável — variância baixa entre runs
  • Eval cobre o objetivo final — não otimize só sintaxe; cubra semântica e edge cases
  • Eval bate com métrica de prod — eval que diverge de métrica de prod = ganha eval, perde prod

Quando ground truth não existe, LLM-as-judge (04 - LLM-as-judge — quando e como) viabiliza eval automatizado pra DSPy. Cuidado: judge enviesado vira prompt enviesado.

Estado 2026

Realidade honesta:

  • DSPy é estável e amplamente conhecido em comunidade de IA, com adoção crescente em pipeline acadêmico e em algumas equipes de produção. Não é “tooling de produção default” como um framework web maduro.
  • Ferramentas competidoras / complementares estão surgindo (TextGrad, frameworks proprietários de labs); o espaço ainda está se consolidando.
  • Auto-prompt em produção costuma cobrir partes do pipeline (e.g., compilar few-shot pra uma signature crítica) em vez de todo o sistema.
  • Tradeoff conhecido — prompts gerados por compiler costumam ser mais longos e menos legíveis que prompts artesanais. Tolerar isso é parte do custo.

A escolha “DSPy ou não” em 2026 é típica de adoção de tecnologia em transição: time pequeno em produto early, manual basta; time que vai recompilar contra modelos novos a cada trimestre, vale aprender DSPy mesmo com overhead inicial.

Anti-padrões

  • DSPy sem eval function — compiler precisa de métrica; sem ela, gera lixo otimizado
  • Eval function que mede a coisa errada — compiler diverge da métrica de produção
  • Acoplar DSPy ao código sem fallback pra prompt artesanal — quando compilação quebra ou modelo muda, sem fallback você fica parado
  • Compilar uma vez e esquecer — modelo muda, distribuição muda, recompila periodicamente
  • DSPy como prata bala em problema mal definido — se o objetivo é difícil de medir, DSPy não resolve, agrava
  • Confiar 100% no prompt compilado em prod safety-critical — humano deve auditar antes de promover
  • Ignorar custo de compilação — MIPRO com dataset grande + modelo caro = compilação cara

Fontes

  • Khattab, Singhvi, Maheshwari et al.DSPy: Compiling Declarative Language Model Calls into Self-Improving Pipelines (arxiv:2310.03714). Paper original.
  • DSPydocumentação oficial e repositório.
  • Khattab et al.In-Context Learning for Extreme Multi-Label Classification (arxiv:2401.12178). Uso de DSPy em problema concreto.
  • Zhou et al.Large Language Models Are Human-Level Prompt Engineers (APE, arxiv:2211.01910).
  • Yang et al.Large Language Models as Optimizers (OPRO, arxiv:2309.03409).
  • Fernando et al.Promptbreeder: Self-Referential Self-Improvement Via Prompt Evolution (arxiv:2309.16797).
  • Opsahl-Ong et al.Optimizing Instructions and Demonstrations for Multi-Stage Language Model Programs (MIPROv2, arxiv:2406.11695).

Veja também