
Isto faz parte de uma série contínua: veja o primeiro e o segundo posts.
Uma monstruosidade hedionda. Todo engenheiro experiente já viu uma: código tão vasto, de alto risco e difícil de entender que ninguém ousa tocá-lo. Não há testes unitários, cada mudança é motivo para um pequeno ataque cardíaco. Os únicos que se aventuram perto dele são os veteranos - aqueles que estavam por perto quando o monstro foi construído e só chegam perto quando não há alternativa. É obsoleto, não modularizado e as dependências estão desatualizadas. O componente é perigoso demais para ser alterado seriamente.
Lembro-me da primeira monstruosidade que encontrei. Uma função de 5.000 linhas que era central para as operações de um negócio que valia centenas de milhões de dólares; quase ninguém tinha confiança para tocá-la. Quando ela quebrou, equipes inteiras foram acordadas no meio da noite. Todo o desenvolvimento na empresa foi desacelerado por causa de uma dependência desse componente-chave. Milhões de dólares foram gastos tentando gerenciar o monstro.
O que tudo isso tem a ver com os prompts do LLM? Eles também podem se tornar monstruosidades! Tão assustadores de mudar, que ninguém os toca. Ou, inversamente, as equipes tentam consertá-los e causam uma avalanche de incidentes.
Os clientes não querem pagar por software que funciona corretamente apenas às terças e quintas-feiras; eles exigem confiabilidade constante e um fluxo de novos recursos. Ao construir sistemas de alta confiabilidade de longo prazo, é essencial permitir que o aplicativo evolua, mantendo as luzes constantemente acesas. Isso se aplica a aplicativos alimentados por Gen AI tanto quanto a softwares tradicionais.
Então, como você obtém um aplicativo saudável alimentado por IA e não uma monstruosidade? Há mais de uma dúzia de abordagens, todas abordadas nesta série. Todas elas começam com um princípio: em vez de um prompt gigantesco, você quer vários prompts menores focados, cada um com o objetivo de resolver um único problema.
Modularização é a prática de dividir um sistema complexo em componentes menores, autocontidos e reutilizáveis. Na engenharia de software tradicional, isso significa escrever funções, classes e serviços que lidam com uma tarefa específica. No contexto da engenharia de prompts para LLMs, modularização significa dividir um prompt grande e monolítico em prompts menores e focados — cada um projetado para executar uma tarefa única e bem definida.
A modularização permite que você introduza mudanças com segurança no seu sistema ao longo do tempo. Sua importância cresce quando:
Todas essas dimensões precisam ser entendidas ao planejar o sistema.
Mas como especificamente a modularização ajuda a manter o sistema? Os principais benefícios são descritos abaixo.
O desempenho do prompt LLM é inerentemente instável. Sua natureza é tal que qualquer mudança pode afetar a saída de maneiras imprevisíveis. Você pode gerenciar esse risco dividindo grandes prompts em componentes, onde uma mudança pode afetar apenas o desempenho de uma parte do sistema. Mesmo se um prompt estiver quebrado, o resto do sistema operará como antes da mudança.
Mas e se os prompts operarem como uma cadeia? Quebrar um componente ainda não quebraria a cadeia? Sim, quebraria, mas o dano ainda é reduzido neste cenário. Uma saída errônea em uma cadeia de prompts pode fornecer aos prompts downstream entradas defeituosas, mas cada componente ainda operaria como antes da mudança no conjunto de entradas válidas. Compare isso com a alteração de um prompt gigante - a mudança pode (e vai!) afetar cada bit de lógica codificado naquele prompt. Você não quebrou um aspecto do sistema - você potencialmente quebrou cada parte dele.
(Operar cadeias de prompts com segurança é um capítulo futuro da série. Você precisa planejar vários tipos de falhas e ter planos de contingência. Mas isso está além do escopo aqui)
Qualquer um que tenha escrito testes unitários sabe que uma função simples que faz uma única coisa é BEM mais fácil de testar do que uma função complexa que tenta fazer muitas coisas diferentes. O mesmo se aplica a prompts - um prompt pequeno e focado pode ser testado muito mais completamente, tanto manualmente quanto de forma totalmente automatizada.
Um amplo conjunto de evidências mostra que prompts mais curtos tendem a ter melhor desempenho do que os mais longos: 1 , 2 , 3 .
Pesquisas sobre os efeitos da multitarefa no desempenho do prompt são mais mistas: 4 , 5 . Um prompt perfeitamente otimizado pode, sob as circunstâncias certas, realizar multitarefas. Na prática, porém, é muito mais fácil otimizar prompts focados, onde você pode rastrear o desempenho ao longo de uma única dimensão principal. Você deve almejar prompts mais focados sempre que possível.
Explicar as complexidades de um super prompt com 3 mil palavras para um novo membro da equipe é uma jornada. E não importa o quanto você explique, os únicos que têm uma noção dessa fera serão os autores contribuintes.
Um sistema de prompts, com cada parte relativamente simples, pode ser integrado muito mais rápido; os engenheiros começarão a ser produtivos mais cedo.
Ao usar diferentes modelos em diferentes partes do sistema, você pode obter economias significativas de custo e latência sem afetar a qualidade da resposta.
Por exemplo, um prompt que determina o idioma de entrada não precisa ser particularmente inteligente - ele não requer seu modelo mais recente e caro. Por outro lado, o prompt que gera a resposta com base na documentação pode se beneficiar de uma cadeia de raciocínio de pensamento incorporada em modelos de ponta.
A maioria dos aplicativos baseados em software exige a adição segura de recursos por longos períodos de tempo. Há, no entanto, uma exceção. Os aplicativos de protótipo não devem ser mantidos por muito tempo; eles não receberão novos recursos e não são feitos para alta confiabilidade. Portanto, não perca tempo com modularização ao construir protótipos. Na verdade, a maioria dos padrões desta série não se aplica a aplicativos de protótipo. Ao construir um protótipo - vá rápido, verifique as incógnitas críticas e então jogue o código fora.
Outra consideração é saber quando parar de modularizar. Há sobrecarga para gerenciar prompts extras e se os benefícios de uma modularização adicional forem baixos, você deve parar de dividir o sistema ainda mais.
Se modularizar prompts fosse trivial - todo mundo estaria fazendo isso. Para gerenciar muitos prompts em um sistema, você precisa investir em infraestrutura - sem ela, você terá caos. Aqui estão os requisitos mínimos para a infraestrutura de prompt do LLM:
Capacidade de adicionar prompts rapidamente e sem dor de forma padronizada. Particularmente importante quando os prompts são carregados de fora da base de código. Veja Princípio II: Carregue Prompts com Segurança (Se Você Realmente Precisar) .
Capacidade de implantar prompts de forma automatizada.
Capacidade de registrar e monitorar entradas/saídas de prompts individuais.
Capacidade de adicionar testes automatizados que abrangem prompts.
Uma maneira de rastrear facilmente os gastos de token/$ em vários prompts.
Vamos ver como a construção de um sistema alimentado por Gen AI funciona na prática com e sem modularização.
Você está construindo um aplicativo de suporte técnico e está determinado a implementá-lo com um único prompt. Na versão mais simples, você pode imaginar um prompt monolítico que gera respostas enquanto carrega documentação relevante por meio do RAG .
Parece legal e fácil, certo? Mas conforme você adiciona recursos, surgem problemas com essa arquitetura:
Você quer responder a mensagens em uma lista fixa de idiomas, mas não lidar com outros. Para conseguir isso, você adiciona instruções de prompt para responder somente em certos idiomas e fazer com que o LLM retorne o campo “idioma” para fins de relatórios.
Você quer que todas as conversas sejam classificadas. Adicione um campo “label” à saída do prompt.
Quando o usuário estiver insatisfeito - encaminhe o caso para o suporte humano. Adicione a variável de saída “escalate_to_human” junto com as instruções no prompt.
Precisa de uma tradução de todas as mensagens enviadas para auditoria interna. Retorne o campo “translated” com uma mensagem em inglês.
Precisa de proteção para garantir que o aplicativo nunca pergunte aos usuários sobre sua localização e em quem eles votaram na última eleição. Adicione instruções rápidas e teste manualmente.
Precisa de um resumo para cada conversa? Adicione o campo “summary” a cada saída.
Talvez você esteja começando a ver o problema - este prompt agora tem seis saídas. Testá-lo será um pesadelo. Você adiciona suporte para outro idioma e, de repente, seu aplicativo começa a retornar o resumo em espanhol em vez de inglês. Por quê? Quem sabe, as saídas do LLM são instáveis, então alterar o prompt tem resultados imprevisíveis.
Parabéns - você criou um monstro! Com o tempo, ele crescerá e causará ainda mais dor.
Tanto o Prompt Chain quanto um prompt de classificação totalmente separado são usados. O prompt grande original é modularizado tanto quanto possível.
Um prompt detecta o idioma, um fornece a tradução, um determina se o usuário está chateado e escala para humanos, o prompt de resposta gera a resposta, o guardrail verifica a conformidade da resposta. As saídas de um prompt são encadeadas para serem entradas do próximo; o código tradicional pode operar entre esses prompts para, por exemplo, verificar a elegibilidade do idioma, sem envolver LLMs.
Uma alteração ainda pode interromper um determinado prompt, mas os riscos são bastante reduzidos porque:
Você obtém todos os benefícios da Gen AI, mas os riscos são muito reduzidos. Além disso, você pode usar modelos mais baratos para alguns componentes para economizar dinheiro.
A modularização permite isolar erros, melhorar a manutenibilidade e construir um sistema mais confiável. Mesmo aplicativos de tamanho moderado terão dezenas, se não centenas, de prompts de componentes. Divida os prompts até que cada um execute uma única tarefa e até que os benefícios da modularização adicional sejam superados pela complexidade operacional adicional. A modularização de seus prompts é uma necessidade se seus aplicativos orientados por IA devem permanecer confiáveis e continuar a adicionar recursos a longo prazo. Já existem muitos sistemas "monstros" por aí - tome cuidado para não criar novos!
Se você gostou desta série, inscreva-se para receber mais postagens.