Capacitação Microsoft AI — Aula 2: LLMs e engenharia de prompts

Segundo artigo da série que acompanha as aulas da Capacitação Microsoft AI 2026. Na aula 1 chegamos ao modelo com a montagem mínima; nesta aula a montagem é exatamente a mesma — o que muda é o que colocamos no contexto.

O que a aula cobriu

Como um modelo grande de linguagem funciona por dentro — tokens, probabilidade, janela de contexto — e o que isso significa para quem escreve o prompt. Depois, três técnicas na prática, todas sobre os mesmos três chamados de suporte, para que a comparação seja honesta: chat com histórico no cliente, few-shot e saída estruturada.

Três ideias para levar

1. Quem guarda o histórico: o serviço ou o cliente?

Na aula 1 o programa guardava só um ConversationId e o serviço lembrava a conversa. Aqui fazemos o oposto: uma List<ChatMessage> que cresce a cada turno e é enviada inteira. Mesmo IChatClient, mesmo endpoint, mesma identidade. A escolha não é de tecnologia, é de arquitetura: histórico no cliente dá controle total sobre o que entra no contexto (e sobre o custo em tokens); histórico no serviço simplifica o código e facilita retomar conversas.

2. Few-shot não é um recurso da API, é uma conversa fictícia

Em vez de descrever o formato de resposta que você quer, você mostra: monta uma conversa em que o assistente “já respondeu” daquele jeito e entrega como se tivesse acontecido. O modelo continua o padrão. Na demo, zero-shot devolve markdown livre; few-shot devolve Acesso | Alta | ... em uma linha.

List<ChatMessage> exemplos =
[
    new(ChatRole.System, "Você classifica chamados de suporte. Responda SEMPRE em uma única linha, no formato: Categoria | Urgência | Resumo."),
    new(ChatRole.User, "O sistema fechou sozinho quando cliquei em salvar."),
    new(ChatRole.Assistant, "Erro | Alta | Aplicação encerra ao salvar."),
    // ... mais dois pares
];

List<ChatMessage> mensagens = [.. exemplos, new ChatMessage(ChatRole.User, chamado)];
var resposta = await chatClient.GetResponseAsync(mensagens);

3. Saída estruturada: um record em vez de texto solto

Quando a resposta vai alimentar código — e não uma pessoa — pedir “com jeitinho” não basta. GetResponseAsync<T>() gera um JSON Schema a partir do seu record, envia junto com o prompt e desserializa a resposta. O modelo fica obrigado pelo serviço a produzir JSON válido naquele formato.

record TriagemChamado(string Categoria, string Urgencia, string Resumo, bool RequerAtencaoImediata);

var resposta = await chatClient.GetResponseAsync<TriagemChamado>(mensagens);
TriagemChamado triagem = resposta.Result;

Antes de rodar

  • Tudo o que valia na aula 1: .NET 10, Azure CLI com az login, papel Foundry User, FOUNDRY_ENDPOINT (do projeto) e FOUNDRY_MODEL (nome do deployment).
  • Os pacotes são os mesmos e nas mesmas versões. Microsoft.Extensions.AI e Microsoft.Extensions.AI.OpenAI ficam em 10.4.1 — é a única versão compatível com o OpenAI 2.9.1 que os pacotes Azure exigem. Subir sem --version compila e quebra em runtime.
  • O <NoWarn>OPENAI001</NoWarn> no .csproj não é opcional: AsIChatClient() ainda é experimental e o SDK promove o aviso a erro.

Se você está na trilha Python

As três demos existem em Python: histórico numa lista de mensagens, few-shot do mesmo jeito, e saída estruturada com Pydantic no lugar do record. Mesmo AIProjectClient e mesmo endpoint da aula 1.

Próximo passo

Rode a demo 2 duas vezes com o mesmo chamado — uma zero-shot, outra few-shot — e compare as respostas. Depois troque um dos exemplos do few-shot e veja como o modelo segue o novo padrão. Na aula 3 entramos no Microsoft Foundry de verdade: recurso, projeto, deploy de modelos e o SDK com resposta em streaming.

Dúvidas ou algo que não funcionou? Deixe nos comentários ou abra uma issue no repositório.

Comentários

Deixe um comentário