O que é LLM para engenheiros?
LLM para engenheiros (LLMs for engineers) é um fundamento de engenharia de IA para quem trabalha com LLMs. O modelo como uma função probabilística: o que entra, o que sai e o que ele não garante.
O Rafael escreveu uma função pequena. Ela manda a descrição de um produto para o modelo e pede a categoria.
No teste, voltou Eletrônicos dez vezes seguidas. Perfeito.
Em produção, no mesmo produto, voltou Eletrônico, no singular. Depois eletrônicos, minúsculo, com ponto final. E uma vez, Eletrônicos e Informática.
O código que comparava a resposta com a lista de categorias do marketplace quebrou. E alguns produtos novos nunca chegaram à vitrine.
O modelo não tinha defeito nenhum. O Rafael tratou a chamada ao modelo como uma função comum, que sempre devolve a mesma saída para a mesma entrada. Ela não é. Nesta aula, você vai conhecer as quatro propriedades que explicam o que aconteceu, e que quase todo padrão deste catálogo existe para controlar.
Para um engenheiro, este é o jeito mais útil de pensar num modelo de linguagem. É uma função probabilística de texto para texto.
Ela recebe uma sequência de tokens, que são pedacinhos de texto. E devolve a continuação mais provável, um token de cada vez.
Duas palavras dessa frase pesam muito. Probabilística, porque tem um sorteio lá dentro. E continuação, porque o modelo não está consultando nada. Está completando texto.
Vamos acompanhar uma chamada. Tudo o que o modelo sabe sobre a sua tarefa está na entrada. O prompt de sistema, a conversa, os documentos e as ferramentas que você oferece.
O modelo calcula uma probabilidade para cada próximo token possível.
Aí um token é escolhido a partir dessas probabilidades, com um pouco de sorteio.
Esse token é colado no texto, e o ciclo roda de novo.
Ele para quando o modelo emite um token de fim, ou quando bate no limite de saída que você definiu.
Desse desenho saem quatro propriedades. E cada uma muda o jeito de escrever o código em volta do modelo.
Primeira: ela não é determinística. A mesma entrada pode gerar saídas diferentes, porque o passo três é um sorteio. Uma diferença pequena num token do começo muda tudo depois. Foi isso que pegou o Rafael. Eletrônicos e Eletrônico estão a um token de distância.
Então o seu código precisa aceitar variação, ou eliminá-la na fronteira. É para isso que existe a saída estruturada.
Segunda: ela não tem memória. Toda chamada começa do zero. Se o modelo parece lembrar da conversa, é porque o seu código mandou o histórico inteiro de novo.
Pense na terceira mensagem de um chat. O cliente pergunta: e o frete do mais barato para Boston? Se o seu código manda só essa última mensagem, o modelo não faz ideia do que é o mais barato. Memória é trabalho seu. E cada turno guardado é pago de novo, a cada chamada.
Terceira: ela não sabe o que não está na entrada. O modelo aprendeu muita coisa no treino. Mas não conhece o seu banco de dados, a sua política de troca, nem o que mudou ontem. Ou você coloca essa informação na entrada, ou ele escreve algo plausível.
E plausível não é verdadeiro. Em 2023, advogados em Nova York entregaram uma petição citando decisões que um chatbot simplesmente inventou. O juiz puniu os advogados. O modelo não tinha jurisprudência na entrada, então completou o texto com casos que pareciam reais. É o problema que a busca, o RAG, resolve.
Quarta: ela não garante nada. O modelo não tem contrato. Pode ignorar uma instrução, errar uma conta ou inventar um campo. Toda garantia de verdade vem do código em volta.
Em 2024, o chatbot de uma companhia aérea falou para um cliente de luto sobre uma regra de reembolso que não era a política real. Um tribunal canadense mandou a empresa pagar. E rejeitou a ideia de que o chatbot respondia pelas próprias palavras. Para o cliente, o que o bot diz é o que a empresa disse.
Uma pergunta para você. O seu chatbot responde bem a primeira pergunta do cliente. Na segunda, e quanto é o frete dele, ele responde: de qual produto você está falando? Qual é a causa mais provável?
O seu código está mandando só a mensagem atual, sem os turnos anteriores. O modelo não guarda nada entre chamadas, então a palavra dele não aponta para nada.
Não é a janela de contexto cheia. Duas mensagens curtas nem chegam perto. E também não é a temperatura. O sorteio muda o jeito de falar, não apaga uma conversa.
Na prática, uma chamada tem quatro partes que você controla. O modelo. O erro comum é usar o maior para tudo e pagar caro.
O prompt de sistema, com as instruções fixas. O erro ali é transformá-lo num depósito de regras.
As mensagens. Aqui, as pessoas mandam histórico demais, ou de menos.
E o limite de saída. Curto demais, e a resposta é cortada no meio da frase.
A resposta também diz por que a geração parou, num campo chamado stop reason. End turn quer dizer que o modelo terminou. Max tokens quer dizer que o seu limite cortou. Um resumo que para no meio da frase, com um formato que nunca fecha, é quase sempre o segundo caso. Então confira esse campo antes de tentar ler qualquer coisa.
Na página tem um experimento de cinco minutos. Você faz a mesma pergunta cinco vezes com um prompt aberto, e cinco vezes com uma lista fechada de categorias.
Repare em três coisas. Se as cinco respostas são iguais. Se a forma muda, como maiúscula, plural ou ponto final. E se até a lista fechada gera uma resposta inválida.
Mesmo que tudo passe hoje, a última linha é o que importa. A conferência com a sua lista mora no código. E é ela que protege o resto do sistema quando o modelo sai do roteiro.
Então fica a regra prática. Deixe o modelo fazer o que só ele faz bem. Entender texto, escrever, decidir em casos ambíguos.
E deixe o código fazer todo o resto. Contas, comparar datas, consultar tabela, regras de negócio.
Pense numa calculadora de frete. O modelo lê a mensagem do cliente e tira o peso e o CEP. Depois, uma função de dez linhas consulta a tabela da transportadora e faz a conta. Exata, barata, e nunca tem um dia ruim.
O erro comum é o contrário. Colar a tabela de preços no prompt e pedir para o modelo fazer a conta. Funciona quase sempre, e falha de vez em quando, em silêncio. Quando o modelo faz esse tipo de trabalho, você tem um smell chamado LLM doing deterministic work.
Agora pense de novo no Rafael, e em tudo que escreve num sistema de verdade. Digamos que o modelo lê uma nota fiscal e o seu código grava o total direto no sistema contábil. Onde deve morar a garantia de que o valor faz sentido?
Não no prompt. Escrever nunca erre o total, mesmo em maiúsculas, aumenta o acerto, mas nunca vira garantia. E nem num modelo maior. Ele erra menos, e continua sem prometer nada.
Ela mora no código. O total precisa ser um número positivo e bater com a soma dos itens menos o desconto. Se não bater, a nota vai para uma fila de revisão, em vez de cair errada na contabilidade.
Então, a ideia para levar. Uma chamada ao modelo não é uma função com contrato. Ela varia, esquece, só sabe o que você entrega e não promete nada. É o seu código que transforma quase sempre em sempre tratado.
Na próxima aula, vamos olhar a unidade em que tudo é medido, o token, e a janela de contexto, o espaço onde tudo isso precisa caber. Até lá.
LLMs for engineers
LLM para engenheiros (LLMs for engineers) é um fundamento de engenharia de IA para quem trabalha com LLMs. O modelo como uma função probabilística: o que entra, o que sai e o que ele não garante.
O Rafael escreveu uma função que manda a descrição de um produto para o modelo e pede a categoria. Nos testes, deu “Eletrônicos” dez vezes seguidas. Em produção, no mesmo produto, apareceu “Eletrônico”, “eletrônicos.” e uma vez “Eletrônicos e Informática”. O código que comparava a resposta com a lista de categorias do marketplace quebrou, e parte dos produtos novos ficou sem vitrine.
Nada estava “errado” com o modelo. O Rafael tratou uma chamada de LLM como uma função comum, que devolve sempre a mesma saída para a mesma entrada. Ela não é.
Para um engenheiro, a forma mais útil de pensar num LLM é esta: uma função probabilística de texto para texto. Ela recebe uma sequência de tokens (pedaços de texto) e devolve a continuação mais provável, um token por vez.
flowchart LR
IN(["1. Entrada: system + mensagens"]):::io --> M(["2. Modelo"]):::llm
M --> D{"3. Próximo token?"}
D -->|"amostra"| T["4. Acrescenta o token"]:::tool
T --> M
D -->|"fim"| OUT(["5. Saída"]):::io
Desse desenho saem quatro propriedades. Cada uma muda como você escreve o código em volta do modelo.
A mesma entrada pode gerar saídas diferentes, porque o passo 3 sorteia. Uma diferença pequena num token do começo muda tudo que vem depois. Foi o que aconteceu com o Rafael: “Eletrônicos” e “Eletrônico” estão a um token de distância.
A consequência prática: o seu código precisa aceitar variação ou eliminá-la na fronteira. É por isso que Saída Estruturada existe.
Cada chamada começa do zero. Se o modelo “lembra” da conversa, é porque o seu código mandou o histórico de novo na entrada. Na terceira mensagem de um chat, a chamada real é esta:
{
"system": "Você é o assistente da Loja X.",
"messages": [
{ "role": "user", "content": "Vocês têm fone bluetooth?" },
{ "role": "assistant", "content": "Temos três modelos, de R$ 99 a R$ 349." },
{ "role": "user", "content": "E o frete do mais barato para Recife?" }
]
}
Se o seu código mandar só a última mensagem, o modelo não sabe o que é “o mais barato”. Memória é responsabilidade sua, e cada turno guardado é pago de novo em toda chamada.
O modelo aprendeu muita coisa no treino, mas não conhece o seu banco de dados, a política de troca da sua loja ou o que mudou ontem. Ou você coloca essa informação na entrada, ou ele escreve uma resposta plausível.
Plausível não é verdadeiro. Em 2023, no caso Mata v. Avianca, advogados em Nova York entregaram ao tribunal uma petição com decisões judiciais inventadas pelo ChatGPT e foram punidos pelo juiz. O modelo não tinha uma base de jurisprudência na entrada; ele completou o texto com casos que pareciam reais. Esse é o problema que RAG resolve.
O modelo não tem contrato. Ele pode ignorar uma instrução, errar uma conta ou inventar um campo. Toda garantia de verdade vem do código em volta: validação de schema, regras de negócio, aprovação humana.
Em 2024, no caso Moffatt v. Air Canada, o chatbot da companhia explicou a um cliente uma regra de reembolso para viagens por luto que não era a política real. O tribunal canadense mandou a empresa pagar a diferença e recusou o argumento de que o chatbot respondia por si mesmo. Para quem responde, o que o bot diz é o que a empresa disse.
Uma chamada de API tem quatro partes que você controla:
| Parte | O que é | Erro comum |
|---|---|---|
| Modelo | Qual LLM vai rodar | Usar o maior para tudo e pagar caro |
| System prompt | Instruções fixas da tarefa | Virar depósito de regras (Prompt Inchado) |
| Mensagens | A conversa e os dados do momento | Mandar histórico demais, ou de menos |
| Limite de saída | Quantos tokens a resposta pode ter (max_tokens) |
Limite curto que corta a resposta no meio |
A resposta da API também diz por que a geração parou, no campo stop_reason. end_turn quer dizer que o modelo terminou. max_tokens quer dizer que o limite cortou a resposta. Um JSON cortado no meio quase sempre é o segundo caso, e o seu código deve checar esse campo antes de tentar ler a saída.
Rode a mesma pergunta cinco vezes com um prompt aberto e cinco com uma lista fechada, e veja quantas respostas o seu código aceitaria. Precisa do SDK (pip install anthropic) e da variável ANTHROPIC_API_KEY.
import anthropic
client = anthropic.Anthropic()
CATEGORIES = {"Eletrônicos", "Casa", "Moda", "Esporte"}
def ask(prompt: str) -> str:
reply = client.messages.create(
model="claude-haiku-4-5",
max_tokens=50,
messages=[{"role": "user", "content": prompt}],
)
return next(b.text for b in reply.content if b.type == "text").strip()
open_prompt = "Em qual categoria fica um fone bluetooth? Responda com uma palavra."
closed_prompt = (
"Classifique o produto 'fone bluetooth' em exatamente uma destas categorias: "
+ ", ".join(sorted(CATEGORIES))
+ ". Responda só com o nome da categoria, sem pontuação."
)
for name, prompt in [("aberto", open_prompt), ("fechado", closed_prompt)]:
print(f"--- prompt {name}")
for i in range(5):
answer = ask(prompt)
print(i, repr(answer), "válida" if answer in CATEGORIES else "INVÁLIDA")
Repare em três coisas. Se as cinco respostas de cada bloco são idênticas. Se a forma muda (maiúscula, plural, ponto final), o que repr deixa visível. E se mesmo a lista fechada gera alguma resposta inválida.
Mesmo que todas passem hoje, a última linha do laço é o ponto: a validação contra CATEGORIES fica no código, e é ela que protege o resto do sistema quando o modelo sair da linha.
Quase todo padrão deste catálogo existe para lidar com uma dessas quatro propriedades:
| Propriedade | O que ela pede | Onde ler |
|---|---|---|
| Saída variável | Formato fixo e medição repetida | Saída Estruturada, O que é um eval |
| Sem memória | Estado gerenciado pelo código | Contexto Podre, Compactação de Contexto |
| Sem conhecimento do seu mundo | Dados certos na entrada | RAG, Uso de Ferramentas |
| Sem garantia | Validação e portões fora do modelo | Humano no Circuito, Guardrails de Entrada |
A regra prática: deixe o modelo fazer o que só ele faz bem (entender texto, escrever, decidir em casos ambíguos) e deixe o código fazer todo o resto. Conta, comparação de datas, consulta a tabela e regra de negócio cabem melhor em código. Quando o modelo faz esse trabalho, você tem o smell LLM Fazendo Conta.
Responda as 6 perguntas para concluir a aula. Só assistir não conclui: a checagem é o que conta para a trilha e para o certificado.
LLM para engenheiros (LLMs for engineers) é um fundamento de engenharia de IA para quem trabalha com LLMs. O modelo como uma função probabilística: o que entra, o que sai e o que ele não garante.