Pular para o conteúdo
Categoria: Desenvolvendo com IA14 min de leitura

Prompt engineering para código: como pedir o que você precisa

Por Lucas Andrade ·

Aprenda técnicas de prompt para gerar código melhor: contexto, exemplos few-shot, restrições, chain-of-thought, anatomia de um bom prompt e iteração estruturada com o modelo.

Pedir código a um modelo de linguagem parece simples, mas a diferença entre uma resposta inútil e uma solução pronta para produção quase sempre está no prompt. O modelo não lê sua mente: ele responde ao que você escreveu, com todo o contexto e todas as ambiguidades que você deixou. Neste guia você vai aprender técnicas concretas de prompt engineering voltadas para geração de código — do básico de dar contexto até padrões avançados como few-shot e chain-of-thought — além de um modelo mental para montar prompts e os erros que sabotam os seus resultados.

Por que o prompt muda tudo

Modelos de linguagem grandes funcionam por probabilidade condicionada ao contexto: cada token que eles geram depende de tudo o que veio antes, incluindo o seu prompt. Quando você escreve "faça uma função de login", o modelo precisa adivinhar a linguagem, o framework, o formato de retorno e mil outros detalhes. Cada adivinhação é uma chance de errar.

A boa notícia é que esses modelos aprenderam a generalizar a partir de pouquíssimos exemplos no próprio prompt, sem precisar de retreinamento — capacidade descrita como aprendizado few-shot (Brown et al., 2020). Isso significa que você consegue "ensinar" o comportamento desejado ali na hora, só ajustando o texto. Dominar essa habilidade é o que separa quem briga com a IA de quem a usa como alavanca.

Há um corolário importante: o modelo não tem estado entre conversas e não "lembra" do seu projeto a menos que você diga. Tudo o que ele sabe sobre o seu caso está no que você fornece naquele momento. Prompt engineering, no fundo, é a engenharia de decidir o que entra nessa janela de contexto e como organizá-lo para maximizar a chance de uma resposta correta.

A anatomia de um bom prompt de código

Antes dos princípios isolados, vale ter um esqueleto mental. Um prompt de código robusto costuma ter quatro blocos, nesta ordem:

  1. Papel e objetivo — quem o modelo deve ser e o que você quer alcançar.
  2. Contexto técnico — linguagem, versões, framework, convenções.
  3. Tarefa específica — a função, o comportamento, os casos de borda.
  4. Formato e restrições — como você quer receber a resposta e o que evitar.
[Papel]      Você é um engenheiro Python sênior.
[Contexto]   Projeto em Python 3.12 com FastAPI 0.110 e Pydantic v2.
             Convenção: snake_case, erros via exceções.
[Tarefa]     Escreva um endpoint POST /usuarios que valida o corpo
             com um modelo Pydantic e persiste via repositório injetado.
             Trate e-mail duplicado retornando 409.
[Formato]    Retorne apenas o código do endpoint e o modelo, com type
             hints. Sem explicações fora do código.

Esse esqueleto não precisa ser preenchido sempre por inteiro, mas tê-lo na cabeça evita que você esqueça o bloco que mais causa erro: o contexto técnico.

Princípio 1: dê contexto explícito

O erro número um é assumir que o modelo conhece seu projeto. Sempre informe:

  • Linguagem e versão ("Python 3.12", "TypeScript com Node 20").
  • Framework ou biblioteca ("usando FastAPI", "com React e hooks").
  • Convenções do projeto ("seguimos snake_case", "erros via exceções, não códigos de retorno").
  • O objetivo de negócio por trás da função.

Compare os dois prompts:

Ruim:  faça uma função que busca usuários

Bom:   Em Python 3.12 com SQLAlchemy 2.0, escreva uma função
       buscar_usuarios_ativos(session) que retorna uma lista de
       objetos User com status='ativo', ordenados por data_cadastro
       decrescente. Use type hints e trate o caso de lista vazia.

O segundo prompt elimina dezenas de ambiguidades e quase sempre produz código aproveitável de primeira.

Princípio 2: defina restrições e formato de saída

Diga ao modelo o que você NÃO quer e como quer receber a resposta. Restrições reduzem o espaço de respostas possíveis e aumentam a precisão:

  • "Não use bibliotecas externas além da standard library."
  • "Retorne apenas o código, sem explicação."
  • "O código deve ser compatível com navegadores antigos (ES5)."
  • "Inclua docstrings e tratamento de erros."

Definir o formato é especialmente útil quando você vai integrar a saída a um fluxo automatizado. Se você quer só uma função, peça só a função. Se quer um arquivo completo com imports, peça isso explicitamente.

Um detalhe subestimado: pedir saída estruturada quando você vai processar a resposta por código. Se um agente vai consumir o resultado, peça JSON com um esquema definido e diga "responda apenas com o JSON, sem cercas de markdown". Quanto mais determinístico o formato, menos parsing frágil você escreve depois.

Princípio 3: forneça exemplos (few-shot)

A técnica few-shot consiste em mostrar ao modelo um ou mais exemplos do par entrada→saída desejado, antes de pedir o caso real. Isso ancora o estilo, o formato e as convenções. É uma das aplicações mais poderosas da capacidade de aprendizado em contexto descrita por Brown et al. (2020).

Aqui está como escrevemos validadores neste projeto:

# exemplo
def validar_email(valor: str) -> bool:
    """Retorna True se valor for um e-mail válido."""
    return bool(re.match(r"[^@]+@[^@]+\.[^@]+", valor))

Agora, no mesmo estilo, escreva validar_cpf(valor: str) -> bool.

Com o exemplo, o modelo replica a assinatura, a docstring e o padrão de retorno sem você precisar descrevê-los em palavras.

Quando usar zero-shot, one-shot ou few-shot

Nem todo prompt precisa de exemplos. Vale calibrar:

  • Zero-shot (sem exemplos): tarefas comuns e bem especificadas, como "escreva uma função que inverte uma string". Modelos atuais resolvem direto.
  • One-shot (um exemplo): quando o formato importa mais que a lógica. Um exemplo basta para fixar o estilo de saída.
  • Few-shot (vários exemplos): quando há uma convenção sutil que só fica clara vendo padrões repetidos — nomenclatura interna, formato de log, estrutura de testes do time.

Mais exemplos custam tokens e nem sempre ajudam. Use o mínimo que comunica o padrão.

Princípio 4: peça raciocínio passo a passo (chain-of-thought)

Para problemas que exigem várias etapas — algoritmos, lógica de negócio complexa, depuração — vale pedir ao modelo que raciocine antes de codar. Essa técnica, chamada chain-of-thought, melhora significativamente o desempenho em tarefas de raciocínio ao fazer o modelo explicitar os passos intermediários (Wei et al., 2022).

Na prática:

Preciso de uma função que detecte ciclos em um grafo dirigido.
Primeiro, explique a abordagem e os casos de borda.
Depois, escreva o código em Python.

Ao forçar a explicação antes da implementação, você reduz erros de lógica e ainda ganha uma documentação do raciocínio. Quem quiser entender o mecanismo por trás disso pode ler Chain-of-Thought: fazendo a IA pensar passo a passo.

Um cuidado: para tarefas triviais, pedir raciocínio só infla a resposta e gasta tokens. Reserve o chain-of-thought para problemas onde a lógica é o gargalo, não a digitação.

Princípio 5: itere com feedback preciso

Raramente o primeiro prompt entrega a versão final, e tudo bem. O segredo é iterar com precisão em vez de repetir "não funcionou":

  • Cole a mensagem de erro completa.
  • Diga o que mudou em relação ao esperado.
  • Aponte a linha ou o comportamento específico.
A função quebra quando a lista está vazia: retorna None
em vez de []. Corrija para retornar uma lista vazia e
adicione um teste para esse caso.

Feedback específico transforma o modelo num parceiro de depuração eficaz. Feedback vago só gera novas adivinhações.

Uma tática que economiza tempo: quando uma conversa acumula muitas idas e vindas, o contexto fica poluído com tentativas erradas. Em vez de continuar empurrando correções, recomece um prompt limpo já incorporando tudo o que você aprendeu. Conversas longas e bagunçadas degradam a qualidade tanto quanto prompts vagos.

Princípio 6: decomponha tarefas grandes

Não peça "construa um sistema de e-commerce" de uma vez. Modelos têm uma janela de contexto limitada e perdem qualidade quando o pedido é gigante. Quebre em partes:

  1. Modelo de dados.
  2. Camada de acesso ao banco.
  3. Endpoints da API.
  4. Validações.
  5. Testes.

Cada etapa vira um prompt focado, com a saída anterior servindo de contexto para a próxima. Essa decomposição também facilita a revisão humana, que continua indispensável.

Padrões de prompt que funcionam

Reúna estes "moldes" no seu repertório:

  • Persona: "Você é um engenheiro Go sênior obcecado por simplicidade." Ajusta o tom e as escolhas técnicas.
  • Restrição negativa: "Sem dependências externas." Evita soluções infladas.
  • Rubrica: "Otimize para legibilidade, depois para performance." Define prioridades de trade-off.
  • Auto-revisão: "Depois de escrever, revise seu próprio código e aponte um possível bug." Faz o modelo pegar erros sozinho.

Dois padrões avançados: testes primeiro e refatoração guiada

Além dos moldes básicos, dois padrões rendem muito em código de produção.

O primeiro é pedir os testes antes da implementação. Você descreve o comportamento, pede ao modelo que escreva os casos de teste e só depois implemente o código que os satisfaz. Isso força uma especificação concreta e revela ambiguidades cedo:

Escreva primeiro os testes (pytest) para uma função
parse_intervalo(texto) que aceita "1-5" e devolve [1,2,3,4,5],
cobrindo entrada inválida e intervalo invertido.
Depois implemente a função que passa em todos os testes.

O segundo é a refatoração guiada por restrição: cole o código atual e dê uma direção clara de melhoria, sem deixar o modelo "melhorar à vontade":

Refatore esta função para reduzir a complexidade ciclomática,
mantendo a assinatura pública e o comportamento idênticos.
Não introduza dependências novas. Explique cada mudança em uma linha.

Restringir o escopo da refatoração evita que o modelo reescreva tudo e introduza regressões silenciosas.

Erros comuns ao escrever prompts

Evite estas armadilhas frequentes:

  • Prompt vago demais: sem contexto, o modelo inventa premissas.
  • Prompt longo e bagunçado: instruções conflitantes confundem o modelo. Seja organizado.
  • Aceitar sem testar: prompt bom não dispensa execução e revisão.
  • Não fixar versões: o modelo pode gerar código para uma API que mudou.
  • Confiar em bibliotecas inventadas: modelos às vezes "alucinam" pacotes que não existem. Sempre confira imports desconhecidos antes de usar.
  • Misturar muitos pedidos num prompt só: quando você junta "escreva, documente, teste e otimize" numa frase, costuma receber as quatro coisas pela metade.

Prompt engineering para código não é mágica nem adivinhação: é comunicação técnica clara. Quanto melhor você descreve o problema, melhor é a resposta.

Estudo de caso: do prompt ruim ao prompt afiado

Acompanhe a evolução de um pedido real, para ver os princípios atuando juntos. Suponha que você precise de uma função que faça retry de uma chamada HTTP.

Versão 0 — ingênua:

faça uma função de retry

O modelo adivinha linguagem, biblioteca, número de tentativas, política de espera. Provavelmente entrega algo genérico que não encaixa no seu projeto.

Versão 1 — com contexto:

Em Python 3.12, escreva uma função que repete uma chamada HTTP
com a biblioteca httpx em caso de falha.

Melhor, mas ainda ambíguo: quantas tentativas? Espera fixa ou exponencial? Quais erros justificam retry?

Versão 2 — específica e restrita:

Em Python 3.12 com httpx (cliente síncrono), escreva
fetch_com_retry(url, tentativas=3). Faça backoff exponencial
(0.5s, 1s, 2s). Repita apenas em erros de conexão e em status 5xx;
não repita em 4xx. Use type hints, levante a última exceção se
todas as tentativas falharem. Retorne apenas a função.

Essa terceira versão elimina quase toda ambiguidade e quase sempre produz código que entra direto no projeto. Note que não ficou mais "bonita" — ficou mais precisa. É esse salto de precisão, não de tamanho, que define um bom prompt.

Controlando a aleatoriedade da resposta

Um aspecto frequentemente ignorado do prompt engineering é que parte da variação nas respostas não vem do seu texto, e sim da configuração de geração. Modelos têm um parâmetro de temperatura que controla o quanto a saída é "criativa" versus determinística.

Para código, a regra prática é simples: temperatura baixa. Você não quer criatividade na hora de gerar uma função de parsing — quer a resposta mais provável e consistente. Temperatura alta faz sentido para brainstorming de abordagens ("liste cinco maneiras diferentes de resolver isto"), mas para a implementação final, o determinismo é seu aliado, inclusive porque torna os resultados mais reproduzíveis quando você ajusta o prompt.

Da mesma forma, se a sua tarefa exige saída estruturada estrita (JSON conforme um esquema), prefira recursos de saída estruturada da API quando disponíveis, em vez de só pedir no texto. Eles reduzem a chance de o modelo "escorregar" para um formato livre.

Prompts dentro do editor

Boa parte do prompt engineering moderno acontece dentro do próprio editor, onde o modelo já tem acesso ao seu código. Ferramentas como o GitHub Copilot: guia completo para programar com IA usam comentários e código ao redor como contexto implícito, enquanto o Cursor: o editor de código com IA que está dominando 2026 permite conversas com referência direta a arquivos. Nesses ambientes, escrever um bom comentário descritivo antes de uma função é, na prática, escrever um prompt.

A grande vantagem do editor é que o contexto vem de graça: o modelo já enxerga os tipos, os imports e as funções vizinhas. Isso muda a técnica — em vez de descrever as convenções do projeto em palavras, você as deixa visíveis no arquivo aberto e mantém um comentário-âncora curto descrevendo a intenção. Ainda assim, os mesmos princípios valem: seja específico sobre o comportamento e os casos de borda, mesmo quando o framework já está implícito.

Quando você combina prompts bem construídos com um fluxo iterativo, chega perto de conseguir construir software apenas conversando — a base do Vibe coding: o que é e como construir apps só com prompts. A diferença é que, com prompt engineering sólido, você mantém o controle sobre a qualidade.

Um fluxo de trabalho completo, do zero ao código revisado

Reunindo tudo, um fluxo eficiente de gerar código com IA costuma seguir estes passos:

  1. Especifique antes de pedir. Escreva, mesmo que mentalmente, o que a função deve fazer, suas entradas, saídas e casos de borda. Prompt vago nasce de pensamento vago.
  2. Monte o prompt com a anatomia — papel, contexto técnico, tarefa, formato. Inclua versões e convenções.
  3. Peça testes ou raciocínio primeiro quando a lógica for o gargalo. Para tarefas simples, vá direto ao código.
  4. Execute e teste de imediato. Não acumule código não verificado. Rode, observe o comportamento real.
  5. Itere com feedback preciso — erro completo, comportamento esperado, linha afetada.
  6. Revise como em um code review. Confira imports, trate o caso de borda esquecido, verifique se não há biblioteca inventada.
  7. Capture o que funcionou. Se um molde de prompt rendeu, guarde-o para reutilizar.

Esse ciclo transforma a IA de "gerador imprevisível" em uma etapa controlada do seu processo de engenharia. O ganho de produtividade vem menos de cada prompt isolado e mais de ter um fluxo repetível em que você confia.

Perguntas frequentes

Preciso de prompts longos para ter respostas boas? Não. Precisa de prompts específicos. Um prompt curto e preciso ("em Go 1.22, escreva X com type Y, tratando o caso Z") supera um parágrafo genérico. Comprimento não é qualidade.

Vale a pena montar uma biblioteca de prompts? Sim. Os moldes que funcionam para o seu stack — formato de testes, estilo de erro, estrutura de endpoint — economizam tempo quando reutilizados. Trate-os como snippets versionados.

O modelo erra mesmo com um prompt perfeito? Sim, e por isso execução e revisão são inegociáveis. O prompt aumenta a probabilidade de acerto; não a garante. Trate toda saída como código de um colega que ainda precisa passar pelo seu code review.

Devo dizer ao modelo para "pensar passo a passo" sempre? Não. Isso ajuda em tarefas de raciocínio (algoritmos, lógica complexa, depuração) e atrapalha em tarefas triviais, onde só infla a resposta. Use com critério.

Conclusão

A qualidade do código gerado por IA é, em grande medida, um reflexo da qualidade do seu prompt. Dar contexto explícito, definir restrições, usar exemplos few-shot na dose certa, pedir raciocínio passo a passo quando a lógica é o gargalo e iterar com feedback preciso são técnicas que transformam o modelo de um gerador caótico em um colaborador confiável. Tenha na cabeça a anatomia de um bom prompt — papel, contexto, tarefa e formato — e construa um repertório de moldes para o seu stack. Trate o prompt como um artefato de engenharia: refine, versione mentalmente os que funcionam e revise sempre a saída. O modelo é poderoso, mas é você quem o direciona.

Referências

  • Brown, T., Mann, B., Ryder, N., Subbiah, M., Kaplan, J., et al. (2020). Language Models are Few-Shot Learners. NeurIPS.
  • Wei, J., Wang, X., Schuurmans, D., Bosma, M., Ichter, B., Xia, F., Chi, E., Le, Q., & Zhou, D. (2022). Chain-of-Thought Prompting Elicits Reasoning in Large Language Models. NeurIPS.

Leituras relacionadas

Nenhum comentário ainda

Seja o primeiro a comentar.

Deixe seu comentário

Entre com sua conta Canverly para comentar. Você pode usar a mesma conta em qualquer site da rede.

Entrar com Canverly