Pular para o conteúdo

Oficina de troca de modelos: GPT-5.5 vs Kimi vs DeepSeek vs Mistral

Ver no idioma original →

Autoria: AI Engineer · Assistir no YouTube

Vídeo de autoria do canal indicado, não da IANIA; todos os direitos pertencem ao criador. Transcrição, resumo e tradução gerados automaticamente; o conteúdo no idioma original é preservado na versão em idioma original.

Idioma original: inglês

Vídeo original: The Model Swap Workshop: GPT-5.5 vs Kimi vs DeepSeek vs Mistral · Canal: AI Engineer · 51:12 · Assistir no YouTube

Tópicos: Agentes de IA, Avaliação e benchmarks de IA, Engenharia de prompts e contexto, Modelos de IA, RAG, busca e recuperação de informação

Nesta oficina guiada, a apresentadora compara GPT-5.5, Kimi K2.6, DeepSeek V4 Flash e Mistral Large 3 em tarefas práticas, como contagem, RAG, interpretação de imagens, tool calling e agentes. As demonstrações mostram que o desempenho varia conforme a tarefa e que benchmarks gerais não substituem avaliações no cenário específico de cada aplicação. A oficina também apresenta métodos para avaliar resultados, incluindo comparações diretas, LLM as a judge e a ferramenta Assert. Por fim, explora o DSPy para otimizar prompts e discute citações estruturadas em modelos da Anthropic e o uso de modelos locais com llama.

  • A escolha de um modelo deve considerar o cenário de uso, pois benchmarks gerais não indicam necessariamente como ele se comportará em uma aplicação específica.
  • Os modelos diferem na capacidade de seguir instruções e reconhecer quando as fontes de RAG não contêm a resposta.
  • A interpretação de imagens varia entre modelos e também pode mudar conforme o idioma usado na solicitação.
  • Descrições e parâmetros de ferramentas são parte da engenharia de prompt e influenciam as chamadas feitas pelo modelo.
  • Ao avaliar agentes, é importante medir não só a resposta final, mas também o uso correto e eficiente das ferramentas, incluindo chamadas em paralelo.
  • Evals devem incluir casos variados e ser atualizados com exemplos de uso observados em produção.
  • LLM as a judge pode avaliar respostas mais abertas, mas seus critérios precisam ser calibrados com avaliação humana.
  • Assert ajuda a gerar cenários de teste e critérios de avaliação a partir de uma especificação.
  • DSPy busca otimizar prompts com base em restrições e avaliações, podendo ajudar a obter bons resultados com modelos menores.
  • A oficina também demonstra citações estruturadas em modelos da Anthropic e explica como conectar exemplos a um servidor local de llama.
Início Capítulo Resumo
00:13 Objetivos e preparação da oficina A apresentadora explica o formato guiado, o repositório, a configuração do ambiente e o objetivo de comparar modelos.
05:04 Comparação básica e engenharia de prompt Os modelos são testados em uma tarefa de contagem, e uma instrução mais detalhada ajuda o Mistral a corrigir a resposta.
08:18 RAG e fundamentação nas fontes A oficina compara a capacidade dos modelos de admitir quando as fontes fornecidas não contêm a resposta.
12:43 Entrada de imagens e diferenças entre idiomas Os modelos analisam imagens de animais e plantas, e a apresentadora observa que o desempenho pode variar entre idiomas.
16:56 Tool calling e chamadas em loop A demonstração apresenta definições de ferramentas em JSON Schema e compara a precisão e a eficiência das chamadas.
23:54 Agentes e planejamento de viagens Um agente construído com LangChain combina buscas de voos e hotéis, verificações de orçamento e busca de atividades.
30:16 Evals com verificações diretas A apresentadora mostra testes de comparação de strings e recomenda ampliar os casos de avaliação com exemplos reais de usuários.
35:04 LLM as a judge e calibração A oficina usa um LLM para julgar resultados e ressalta a importância de fornecer contexto e calibrar os critérios com pessoas.
39:54 Assert e geração de cenários de teste A ferramenta Assert transforma uma especificação em critérios e cenários para avaliar um agente de planejamento de viagens.
45:20 Otimização de prompts com DSPy A apresentadora demonstra como DSPy pode iterar sobre prompts para satisfazer as restrições definidas para uma tarefa.
49:03 Anthropic, llama e encerramento A oficina aborda citações estruturadas em modelos da Anthropic, o uso de llama local e os recursos do repositório.

Precisamos ter opções: apontar nossas aplicações de IA para outro modelo e fazer com que continuem funcionando. — 02:21

Você só sabe se um modelo é bom quando o usa no seu cenário específico. — 05:04

Para produção, é importante ter avaliações automatizadas em lote que possam ser executadas e comparadas de forma confiável. — 30:48

Você quer avaliações personalizadas para realmente verificar se o seu agente está fazendo um bom trabalho. — 44:46

Eu sempre aprendo muito quando testo modelos diferentes e vejo como eles diferem. — 49:03

  • GPT-5.5 (modelo): Modelo usado como referência nas demonstrações e que se destaca na oficina por chamadas paralelas de ferramentas.
  • Kimi K2.6 (modelo): Modelo comparado nas tarefas de contagem, RAG, imagens e uso de ferramentas.
  • DeepSeek V4 Flash (modelo): Modelo avaliado em diversas tarefas, incluindo contagem, RAG e chamadas de ferramentas.
  • Mistral Large 3 (modelo): Modelo comparado em tarefas multimodais, de RAG e de agentes.
  • Microsoft Foundry (ferramenta): Plataforma usada para disponibilizar os modelos da oficina.
  • LangChain (ferramenta): Framework usado para implementar o exemplo de agente de planejamento de viagens.
  • Pydantic AI (ferramenta): Um dos frameworks de agentes disponibilizados no repositório da oficina.
  • Agent Framework (ferramenta): Um dos frameworks de agentes incluídos nos exemplos da oficina.
  • Assert (ferramenta): Ferramenta de pesquisa da Microsoft apresentada para gerar casos de teste e critérios de avaliação a partir de uma especificação.
  • DSPy (ferramenta): Framework que otimiza prompts com base em especificações, restrições e avaliações.
  • Anthropic (empresa): Empresa cujos modelos são apresentados com uma API de mensagens e suporte a citações estruturadas.
  • RAG (conceito): Abordagem em que o modelo responde a perguntas usando contexto fornecido e deve manter as respostas fundamentadas nas fontes.
  • tool calling (conceito): Capacidade do modelo de selecionar uma ferramenta e produzir os argumentos para chamá-la.
  • LLM as a judge (conceito): Método de avaliação em que um LLM analisa resultados e atribui um julgamento, que deve ser calibrado com referências humanas.
  • Llama (modelo): Modelo que pode ser usado nos exemplos ao apontá-los para um servidor local compatível.
  • Cedric (pessoa): Colega da apresentadora que ajuda os participantes durante a oficina.

00:13 Certo. Como já são quase 11h12, quero começar a falar sobre o workshop. Vou conduzi-lo como um workshop guiado, então vou passar por todos os exemplos aqui na tela, mas vocês também podem tentar acompanhar. O repo está disponível, e as variáveis de ambiente também. As variáveis de ambiente dão acesso a vários modelos do Foundry que implantei em um projeto do Microsoft Foundry. Eles têm uma certa capacidade de tokens. É possível

00:47 que ultrapassemos a capacidade de tokens nesta sessão. Só descobri muito recentemente que este workshop tinha sido aceito, então tentei conseguir o máximo de recursos que pude nesse curto período. No arquivo .env, há várias outras variáveis de ambiente possíveis que vocês podem comentar ou descomentar. Se começarmos a receber erros 429, ou seja, erros de limite de taxa excedido. Então, espero que haja capacidade suficiente

01:18 para que todos vocês possam experimentar esses modelos, e vamos ver. Também está aqui meu colega Cedric. Cedric vai circular enquanto eu estiver falando, então talvez possa ajudar com problemas também. Para configurar o código, se vocês já têm Python e UV na máquina, podem clonar o repo com git clone e executar uv sync, e isso deve instalar tudo o que precisam para rodar os exemplos, depois de terem o arquivo .env. Caso contrário, vocês podem criar um GitHub Codespace. Basicamente, é um VS Code no

01:51 navegador, com tudo configurado para vocês. Quem aqui usa UV? Cedric quer saber. Certo. Então, ainda não é o número um. Mas a outra pergunta é: quem usa Python? Certo, mais gente. >> Praticamente todo mundo aqui usa Python. >> É. Vocês contaram quem usa os dois? Certo. Então, se ainda não tiraram uma foto daquela tela, tirem uma agora. Caso contrário, Cedric também tem uma foto dela no celular e pode circular com ela, se vocês precisarem

02:21 desses links. O objetivo deste workshop é ter uma ideia das diferenças entre os vários modelos de ponta, ver como eles diferem e o que vocês podem fazer para melhorá-los. Preparei vários exemplos, além de avaliações e otimizações que podemos fazer para melhorar nossa experiência com os diferentes modelos. Acho que isso é muito importante para todos nós, como engenheiros de IA, porque, como vocês viram, há muitos modelos novos sendo lançados o tempo todo. E o governo dos Estados Unidos

02:53 pode, a qualquer momento, cortar o acesso a um modelo. Então, precisamos ter opções, certo? Precisamos conseguir direcionar nossas aplicações de IA para outro modelo e fazer com que continuem funcionando, ou saber como melhorá-las. Esse é o objetivo aqui: ganhar mais experiência com mais modelos. Estes são os modelos que implantei no Microsoft Foundry. Tenho o GPT-5.5, que é o padrão que uso o tempo todo. Também tenho o Kimi K2.6, um modelo mais recente e muito bom. Tenho o DeepSeek V4 Flash. E também o Mistral Large 3.

03:27 Esses são os quatro modelos que vamos comparar neste workshop. Como eu dizia, para configurar o workshop, este é o repo ao qual vocês estão se conectando. Se não têm Python na máquina, podem clicar no botão de código e haverá um botão grande escrito “Criar Codespace”. Cliquem nele e será criado um Codespace. Aqui está o Codespace. Já coloquei o arquivo .env, mas vocês vão acessar aquele outro

03:59 URL que mostrei para obter o arquivo de variáveis de ambiente. Ele leva a este arquivo aqui. Baixem-no e abram. Depois, criem um arquivo .env com o conteúdo, certo? Ele aponta para um projeto do Foundry que tem esses quatro modelos implantados. Como vocês viram, há limites de tokens. Se começarmos a receber erros de limite de taxa, vocês podem tentar estes outros modelos, que também têm implantações dos quatro modelos no projeto. E tenho outro projeto separado, especificamente para

04:32 Anthropic, só porque esse projeto tem termos diferentes. Certo. Depois que configurarem tudo, o comando uv sync sincronizará todos os pacotes de que precisam para Python. Certo, essa é a configuração. Agora, vou fazer isso aqui para que vocês possam acompanhar, se quiserem, ou simplesmente observar o que faço. Como eu dizia, temos os quatro modelos, e vocês podem compará-los simplesmente

05:04 fazendo benchmarks. Vocês podem pensar: “Este tem bons benchmarks de qualidade e bons benchmarks de segurança”. Também podem analisar o custo, a taxa de transferência e coisas do tipo. Assim, conseguem ter uma noção aproximada de quão bons são esses modelos, mas só vão saber o quanto um modelo é bom quando o usarem no caso específico de vocês, porque há muitas maneiras diferentes de usar modelos. Um benchmark específico não vai realmente mostrar como ele vai funcionar no caso de vocês. É por isso que temos neste repo vários cenários diferentes, e podemos experimentar esses

05:36 modelos em cada um deles. Vamos começar de um jeito bem, bem básico, certo? Uma única chamada a um LLM que pede para ele fazer algo. Em cada um desses arquivos, vocês vão ver que tudo começa com a variável model, que por padrão usa o GPT-3.5. Esse é nosso modelo de referência. É claro que é um modelo muito bom. Mas, se quisermos experimentar outro modelo, basta descomentar essa linha, e esse será o modelo usado. Este arquivo se conecta usando o SDK de Python da OpenAI ao URL do Foundry e passa a chave que está no ambiente. E o

06:11 prompt que vamos usar é: quantas vezes a letra E aparece na frase a seguir? “O senhor idoso entrou ansiosamente no elevador.” Contem com cuidado. Certo. Então, enviamos isso à API de respostas da OpenAI e dizemos: “Aqui, use este modelo com este prompt e vamos ver o resultado bruto, certo?” Estamos fazendo aquela coisa clássica de pedir a LLMs que contem. Vamos ver como eles se saem. Vou executar uv run examples seguido do nome deste arquivo

06:41 aqui. Tudo isso está no README. Então, vamos percorrer os exemplos um por um. Basta copiar e colar de lá. Certo. O GPT-3.5 é muito bom em matemática, surpreendentemente bom. Meus colegas têm executado muitos benchmarks financeiros com ele ultimamente e dizem: “Meu Deus, ele faz muita matemática de cabeça”. E, de fato, acerta: há 13 letras E nessa frase, certo? Agora, vamos experimentar outro. Basta mudar o modelo. Digamos que queremos experimentar o Kimi. Mudamos para Kimi, e agora esse será o modelo usado. Vamos ver: “O Kimi consegue contar tão bem quanto o GPT-3.5?” Consegue. Chega a 13. Certo. Agora vocês podem estar pensando: “Ah, isso é fácil demais”. Vamos experimentar o DeepSeek V4 Flash. Desta vez, ele responde seis. Certo. Então, deixou passar sete letras E, né? Podemos ver imediatamente que há uma diferença entre o DeepSeek V4 e os dois primeiros modelos. Por fim, vamos experimentar o Mistral. Ele responde oito. Então, vemos que há uma diferença aqui. Certo. Ao ver isso, vocês podem pensar: “Bem, eu queria conseguir

07:16 avaliar isso

07:48 use todos esses modelos.” Então você começa a fazer um pouco de engenharia de prompt. Você pensa: “Certo, e se eu disser: divida a frase em palavras, conte cada palavra, some, mostre seu raciocínio, certo?” Vamos tentar, vamos tentar isso, certo? E, sabe, podemos corrigir nossos erros de digitação, embora isso não importe. Certo. Então, vamos tentar com Mistral e ver se, com um pouco de engenharia de prompt, conseguimos uma resposta melhor aqui.

08:18 Certo. E ele acertou, né? Então, sabe, ao dividir a frase e fazer uma pequena cadeia de pensamento, ele conseguiu chegar à resposta correta, né? Então, de imediato, podemos ver que há diferenças óbvias entre os modelos e, se mudarmos os prompts, podemos obter resultados diferentes. Certo. Agora vamos explorar algo mais interessante e partir para cenários mais reais. Vamos olhar para RAG. RAG ainda é um dos grandes casos de uso. Dá para dizer que, na verdade, tudo é RAG. Agents também são RAG.

08:49 Então, temos isto… RAG é quando você pede a um LLM que responda a uma pergunta com base em algum contexto, certo? E o importante no RAG é que você quer que ele responda à pergunta e se mantenha fundamentado no contexto. Você não quer que ele invente algo com base apenas nos pesos, certo? Você está tentando obrigá-lo a se ater ao contexto, certo? E o que percebo que varia bastante entre os modelos é que os modelos menores, menos poderosos, têm muito mais probabilidade de recorrer aos próprios pesos e fingir que aquilo fazia parte do contexto. Então, aqui temos um conjunto de dados sobre abelhas-carpinteiras e fazemos a seguinte pergunta: “Quais são

09:24 as principais diferenças entre a forma como as abelhas-do-mel e as abelhas-carpinteiras constroem seus ninhos?” Mas esse conjunto de dados só contém informações sobre abelhas-carpinteiras. Então, ele só deveria conseguir responder sobre elas. Portanto, uma boa resposta, neste caso, me daria as informações sobre as abelhas-carpinteiras e depois diria: “Desculpe, não posso falar sobre abelhas-do-mel. Não sei.” Então, dizemos algo como: “Ei, seu trabalho é responder com base nas fontes e citar as fontes. Aqui está sua pergunta, aqui estão suas fontes.” Certo, vamos testar e ver o que obtemos.

10:02 Certo, e ele… Sim, quando faz a busca primeiro, é uma busca bem básica. Certo, está enviando… fez a busca. Certo, e o que vemos é que ele diz: “O conjunto de dados não fornece detalhes sobre a construção dos ninhos das abelhas-do-mel.” É exatamente isso que queremos ver. Esta resposta é do GPT-5.5. O GPT-5.5 é muito bom em saber o que não sabe. Agora vamos trocar. Kimi também é bom. Não vou mostrar todos os modelos todas as vezes, só para poupar tempo. Vamos tentar o DeepSeek, certo? Porque

10:34 já vimos que há uma diferença aqui. Agora o DeepSeek, mais uma vez, diz que as fontes fornecidas não contêm essa informação. Certo, o DeepSeek se saiu bem aqui. Agora vamos ao Mistral. Ah, Mistral, desculpe. Cedric, como se pronuncia Mistral? É francês, certo? Uma empresa francesa? >> Mistral. >> Mistral. Cedric vai ser meu tradutor de francês. Toda vez que eu precisar dizer isso, você vai dizer. Agora, Mistral. Hein? É, certo. Mistral. Então, com o Mis… Mis… Mistral >> [risos] >> percebemos que o Mistral, na verdade,

11:07 respondeu com base nos próprios pesos, embora essa informação não estivesse nas fontes. Este é um exemplo de um modelo recorrendo aos próprios pesos, apesar de não querermos que fizesse isso, certo? Agora podemos tentar forçá-lo. Mais uma vez, podemos tentar fazer engenharia de prompt. Podemos dizer… espere, na verdade, seria algo como: “Se a resposta para uma informação não estiver nas fontes…”

11:37 “Diga que nenhuma fonte foi fornecida.” Acho que foi assim que consegui fazer funcionar. Ah, vou tentar isso e acrescentar: “Não invente uma resposta.” Certo, vamos tentar. >> [fungada] >> Estamos tentando fazer com que ele perceba quando está nos dando informações que não estão nas fontes. Às vezes, se você o obriga a dizer: “Ei, para cada informação que incluir na resposta, você precisa provar que a obteve das fontes, certo?” Então, aqui estou tentando fazer com que ele

12:10 associe cada um dos itens dessa resposta a uma fonte e, talvez, isso o faça perceber: “Ah, espere um pouco, isso na verdade não estava nas minhas respostas.” Certo, ele ainda está processando. Está pensando bastante nisso. Certo. E lá vamos nós. “Detalhes sobre as abelhas-do-mel: nenhuma fonte foi fornecida, além das interações com abelhas-carpinteiras.” >> [risos e suspiros] >> Então, ele definitivamente percebeu quando as informações não tinham fonte. Mesmo assim, continuou dando

12:43 as informações. Então, chegamos um pouco mais perto. Mas, como você pode ver, essa é definitivamente uma diferença que percebo com RAG, e RAG é o que mais uso. Então, ao avaliar modelos para usar com RAG, você precisa verificar se eles estão dispostos a admitir o que não sabem e qual é a probabilidade de inventarem coisas. Certo, agora vamos passar para a entrada de imagens. Muitos desses modelos são multimodais, então aceitam imagens como entrada. E há muitas situações bem legais em que você pode usar a entrada de imagens.

13:14 Então, temos alguns arquivos locais e vamos enviá-los aos LLMs e fazer algumas perguntas sobre eles, certo? Vou mostrar os arquivos. Exemplos de entrada de imagens. Certo. Os arquivos que temos aqui são esta imagem. É um auroque, não um unicórnio. Esta imagem é de alguns crocodilos que vi na Costa Rica e que me assustaram muito. E também temos esta imagem, que é uma lista de plantas.

13:49 Basicamente, uma captura de tela de uma tabela com algumas fontes bem pequenas. Então, estamos pedindo a cada LLM que interprete cada uma das imagens, certo? Primeiro perguntamos: “Ah, isto é um unicórnio?” Isso deveria ser fácil: dizer que não é um unicórnio. Ótimo. Depois perguntamos: “Ei, estes são jacarés ou crocodilos?” Isso é um pouco complicado. Na verdade, são crocodilos, por causa do focinho. Passei muito tempo lendo a página da Wikipédia sobre crocodilos; é preciso olhar para o focinho para saber. Felizmente, o GPT-5.5 também tem lido muito a Wikipédia, então sabe que

14:20 quando vê esse focinho, são crocodilos. E ele identificou corretamente a planta mais barata, naquela captura de tela de uma tabela com texto relativamente pequeno. É bem impressionante que o GPT-5.5 tenha conseguido fazer isso. Agora vamos tentar com… Para esses modelos, não podemos usar o DeepSeek, porque ele só aceita texto. Não é multimodal. Então, vamos testar apenas o Kimi e o Mistral. Ele identificou o auroque. Certo, ótimo. Só estou conferindo se

14:51 funciona. Certo. E, quanto aos crocodilos, ele diz corretamente que são crocodilos. E, quanto à planta mais barata, identificou a planta mais barata. Então, o Kimi também está se saindo muito bem. Por fim, vamos ao Mistral. Vamos ver. Certo. Ele sabe que não é um unicórnio. Não sabia que era um auroque. Neste caso, não teve certeza. Acha que são jacarés. Então, está tendo mais dificuldade para olhar para a imagem; acha que

15:22 são jacarés. E, quanto às plantas, identificou uma que custa US$ 2,30, bem mais cara do que a planta mais barata. Deveria ter encontrado uma por 58 centavos. Portanto, o Mistral não consegue responder a esse tipo de pergunta sobre imagens. O que acontece é que, em compreensão multimodal, não dá para fazer muita engenharia de prompt, porque o modelo ou entende uma imagem ou não entende. Talvez seja possível fazer alguma engenharia de prompt se você estiver trabalhando em um domínio muito específico e puder dar algumas dicas sobre como interpretar determinado tipo

15:53 de gráfico. Mas, com entrada de imagem, a questão é descobrir se, para os tipos de imagens que você vai enviar ao LLM, ele consegue entendê-las. Será que vai funcionar para esse cenário? Porque pode ser que o Mistral seja muito bom em certos tipos de tarefas com imagens, mas não nesta, certo? Então, tudo depende de descobrir qual tarefa você quer realizar e se o modelo vai fazer um bom trabalho nela. O interessante com o multimodal também é que muitas dessas coisas dependem do idioma, certo? Aqui

16:24 estou usando inglês. Lembre-se de que todos esses modelos são muito centrados no inglês, mas, se você mudar para outro idioma, por exemplo, se eu perguntar em espanhol se são caimanes ou cocodrilos, ele acaba pensando… dá a resposta errada, porque fica muito confuso com essas palavras diferentes e com a forma como elas correspondem ao inglês. A tarefa simplesmente fica difícil demais: é preciso entender a diferença entre jacarés e crocodilos e também lembrar que caimán significa jacaré em espanhol e não é a mesma coisa que o caimão que temos, por exemplo, na Flórida. Enfim, é fascinante

16:56 ver que, quando mudamos para o espanhol, ele falha na tarefa. Então, isso é outra coisa a se ter em mente, especialmente porque estamos na Califórnia. Muitas vezes, quando desenvolvemos aplicações aqui, elas são bilíngues, porque muita gente, sabe, fala espanhol aqui — 50% da população. Então, os resultados podem variar quando você muda de idioma. Certo, agora vamos passar ao tool calling, também conhecido como chamada de ferramentas. O tool calling é, na verdade, a base de todos os agents. Todos os agents se baseiam em tool calling. E essa é uma capacidade com a qual os LLMs são treinados especificamente durante o processo de treinamento

17:30 . Então, eles são treinados para poder analisar a definição de uma função, ou várias definições de funções, analisar a entrada do usuário e dizer: “Certo, com base nessa entrada do usuário, quero chamar esta função com estes argumentos e depois simplesmente retornar isso.” Neste exemplo, estou definindo uma função usando JSON schema. É isso que os LLMs entendem. Então, digo: “Certo, aqui está minha função. Ela tem o nome create calendar event. Tem esta descrição e estes são os parâmetros que aceita. Ela aceita um título com este

18:00 que é uma string. Aqui está uma descrição, certo?” E tudo isso vai ser enviado ao LLM. Então, enviamos o JSON schema completo ao LLM e dizemos: “Ei, aqui está a função. Você precisa decidir se vai chamá-la e como vai chamá-la, certo?” Então, na verdade, embora isto seja um objeto, isto é engenharia de prompt. Tudo aqui é, na verdade, eu decidindo o que será melhor para o LLM, certo? Que tipo devo usar? Que descrição devo adicionar aqui? Quais devem ser os nomes desses parâmetros? Porque o LLM vai decidir, com base em todas essas

18:32 informações, como vai chamar essa função. Então, temos uma mensagem do usuário. É tipo… O usuário diz: “Ah, você pode adicionar algo ao meu calendário? É uma reunião de sincronização da equipe de plataforma. Eu, Sarah, da Ange, Marcus, a nova PM Priya. Amanhã às 13h30. É virtual, pelo Microsoft Teams, certo?” Então, dizemos ao LLM: “Ei, você é um assistente de calendário. Hoje é segunda-feira, 29 de junho. Use as ferramentas disponíveis para processar a solicitação do usuário.” E enviamos as ferramentas para ele. Agora, o LLM está analisando a solicitação do usuário e as ferramentas. E, neste caso, só tem aquela

19:02 função create calendar event. E vai decidir: “Ei, há alguma ferramenta aqui que eu possa usar para responder ao usuário?” Então, vamos ver quais chamadas de ferramenta ele decide fazer. Aí está. Este é um tool calling bem básico e de baixo nível. Quando criarmos um agent, vamos abstrair isso, mas eu queria começar com o tool calling de nível mais baixo que pudéssemos fazer. E o LLM simplesmente responde com o nome da função e os argumentos que quer que você envie. O próprio LLM não chama a função. Cabe a nós fazer isso. Certo,

19:35 então, podemos ver que coloquei o resultado esperado à esquerda, só para vocês poderem comparar com o resultado real. O GPT-5.5 me adicionou como participante, o que eu não queria muito. Mas, fora isso, foi muito bem. Vamos testar o DeepSeek e ver como ele se sai neste caso. Porque, quando fazemos tool calling, queremos ver se ele está chamando a ferramenta certa. Neste caso, está. Está chamando a ferramenta create calendar event. E queremos ver se está passando os argumentos que esperamos, certo? Temos certos argumentos que esperamos. Neste

20:06 caso, o DeepSeek colocou você como participante. E, para o local, disse “virtual (Microsoft Teams)”, o que não foi o que pedi, certo? Então, ele não está respeitando tanto as restrições dos meus argumentos. Vamos testar o Mistral também e ver como se sai. Quando vejo isso, começo a perceber: “Certo, há certa ambiguidade.” E, se ele chamou com os argumentos errados, isso significa que há ambiguidade. Preciso voltar às minhas descrições e dizer: “Sabe, não inclua a mim nem a você, apenas os participantes mencionados.”

20:41 Você pode dizer nome e sobrenome, se forem fornecidos, certo? Assim, começa a perceber em que pontos não foi específico o suficiente e a esclarecer essa ambiguidade; depois, avalia todas as entradas diferentes e vê como ele está se saindo. Certo. Esse foi um exemplo básico de tool calling. A próxima coisa que queremos fazer — estamos avançando até chegar aos agents — é fazer tool calling em um loop, certo? Quando temos um agent, ele chama ferramentas em um loop até alcançar um objetivo. Então, vamos

21:13 demonstrar usando uma função chamada calculate. Essa função calculate recebe uma expressão matemática e retorna o resultado, certo? E temos suporte básico para avaliar essas expressões matemáticas. Então, estamos dando a ele basicamente um problema contextualizado: “Ah, esta loja está fazendo uma liquidação. Se eu comprar três camisas e pagar tantos impostos, qual será o total?” Isso pode ser feito de várias maneiras diferentes. Ele poderia fazer várias chamadas de ferramenta à calculadora, com uma pequena expressão de cada vez, como: “Faça isto, depois faça aquilo, depois aquilo e, por fim, aquilo.” Ou, se o LLM for muito esperto, poderia juntar tudo

21:47 em uma expressão longa e fazer uma única chamada de ferramenta. Então, aqui estamos testando a eficiência, certo? Muitas vezes, quando se tem tool calling em um loop, as diferenças entre os modelos estão na eficiência. Eles conseguem chegar ao objetivo mais rápido? Conseguem atingir o mesmo objetivo com menos chamadas de ferramenta? É isso que vamos avaliar. O único system prompt é: não faça contas de cabeça. Certo. >> [risos] [suspiros] >> Vamos ver.

22:18 Essa instrução é mesmo para o GPT-5.5, porque ele se orgulha tanto de suas habilidades matemáticas que está sempre tentando fazer as contas de cabeça. Tipo: “Vamos lá.” Certo. O GPT-5.5 realmente faz o cálculo inteiro em uma expressão. Então, só precisou de uma chamada de ferramenta para chegar ao resultado final. Isso é bom. É bom, sabe, é rápido. Poupa nosso tempo. Agora vamos testar com o DeepSeek. Só pulo o Kimi o tempo todo porque ele é, na verdade, um modelo muito bom e, por isso, tem um desempenho quase igual ao do GPT-5.5 em muitos desses casos. Certo, agora podemos ver com

22:51 O DeepSeek está passando por isso e fazendo… fez tantos… quantos? Acho que fez quatro. Fez quatro chamadas de ferramenta, certo? Então, ainda chegou à resposta correta, mas fez quatro chamadas de ferramenta. E cada uma dessas chamadas de ferramenta é outra solicitação de rede, certo? Então, quando estamos avaliando dois modelos, queremos analisar tanto a resposta final quanto quanto tempo levou para chegar a ela, certo? Na verdade, o Kimi fez algo muito interessante no outro

23:24 dia. Vamos ver se faz de novo com este. Porque, na maior parte do tempo, o Kimi funciona muito bem, mas às vezes entra em uns loops estranhos quando fica conferindo o próprio trabalho. Ah, tudo bem, desta vez foi bem. É, outro dia, quando usei o Kimi, ele chegou à resposta certa na primeira tentativa e depois decidiu conferir o próprio trabalho com mais quatro chamadas. Eu disse: “Não, está bom. Está bom.” [risos] >> [suspiros] >> Então, é isso que estamos analisando aqui, certo? Quantas chamadas ele realmente precisa fazer para chegar ao fim.

23:54 Certo, agora podemos passar para os loops de agent. Na verdade, estou passando por isso bem rápido. Ah, ótimo. [risos] Tudo bem. Agora já temos a base, certo? Vimos tool calling e tool calling em um loop. Então, agora podemos construir um agent de verdade. Para isso, normalmente usaríamos um framework de agent. Já coloquei aqui três frameworks de agent diferentes para vocês escolherem o favorito. Temos LangChain, Pydantic AI e Agent Framework. Tenho certeza de que há outros frameworks de agent que deixei de fora, mas espero que encontrem algum de que gostem.

24:27 Então, todos seguem a mesma ideia. Certo, qual deles queremos mostrar? Alguém vote. LangChain. Certo, o LangChain continua muito popular e espero que haja por aqui algumas pessoas que usam LangChain, na conferência de hoje. Certo, com LangChain, estamos usando o LangChain V1, que é uma versão recente bem legal deles, caso você não tenha experimentado no último ano. E, pelo LangChain, nos conectamos aos modelos do Foundry. E o que

24:57 temos aqui é um agent de planejamento de viagens, que é um exemplo clássico. Ele tem ferramentas. Temos uma ferramenta para pesquisar voos, pesquisar hotéis e conferir o orçamento, para verificar se determinado voo e hotel cabem no orçamento; e outra para pesquisar atividades em uma cidade. Depois, tenho um middleware, que serve apenas para eu ver quais ferramentas estão sendo usadas. E então temos a chamada do agent propriamente dita. O agent tem um system prompt que diz: você vai ajudar os usuários a encontrar voos e hotéis. Ele também tem algumas regras, como pesquisar voos e hotéis, preferir voos diretos, blá-blá-blá, sempre conferir o orçamento e, no fim, perguntar sobre atividades com base no orçamento restante.

25:31 Depois, temos a mensagem do usuário: “Preciso voar de SF para Nova York no mês que vem por três noites. Meu orçamento total é de 6.600, e quero voos diretos e uma atividade.” Certo. Então temos tudo isso e estamos executando o agent. Há um pouco de código adicional aqui que só registra as chamadas de ferramenta para podermos vê-las. Vamos experimentar. Certo. E isso vai registrar as

26:05 chamadas de ferramenta feitas. Começamos com o GPT-5.5. Agora, o que é interessante aqui: vocês vão ver que, no turno um — deixa eu aumentar — está escrito que é paralelo. Uma coisa que dá para fazer com LLMs é que muitos deles oferecem suporte a chamadas paralelas de ferramentas. Se você fornecer várias definições de ferramentas, eles podem sugerir várias ferramentas que podem ser chamadas ao mesmo tempo, no mesmo turno. Isso é muito bom em termos de desempenho, porque, no seu servidor, você pode fazer, por exemplo, enviar

26:35 solicitações em paralelo para dois bancos de dados diferentes, certo? Desde que sejam independentes entre si, isso é ótimo: os LLMs podem dizer: “Ei, estas duas coisas podem ser feitas em paralelo. Por que você não faz isso?” Então, no primeiro turno, o GPT-5.5 diz: “Ei, pesquise hotéis em Nova York e pesquise voos de SF para Nova York”, porque decidiu que não havia dependência entre eles. Depois que recebeu os resultados, quando já tinha todas as opções, conferiu o orçamento com base no custo do voo e no custo do hotel que recebeu

27:07 naquela chamada. Então, viu qual era o orçamento restante e fez uma chamada para pesquisar atividades com esse orçamento restante. Portanto, este é provavelmente o agent mais eficiente que podemos ter para esse cenário. Vamos ver se obtemos resultados parecidos quando trocamos de modelo. E, claro, aqui você pode até trocar e comparar modelos e frameworks, certo? Porque cada framework tem um loop de tool

27:39 calling um pouco diferente. Também chamamos isso de harness, certo? Muitas vezes, você quer comparar tanto os modelos quanto os harnesses, e vai ver que há diferenças interessantes entre eles. Certo. Desta vez estamos com o Kimi, e o Kimi também não está fazendo chamadas em paralelo. Não sei se é porque o Kimi não oferece suporte a chamadas paralelas de ferramentas ou se simplesmente decidiu não fazer isso neste caso. Desta vez, fez o mesmo… Na verdade, fez ainda mais chamadas. Pesquisou voos e hotéis ao longo de dois turnos, então já foi menos eficiente, porque não fez as chamadas em paralelo. Depois, decidiu fazer duas chamadas para conferir o

28:11 orçamento, porque acho que estava verificando mais uma opção. E, então, fez a última chamada. Portanto, este precisou de duas chamadas de ferramenta a mais e demorou mais, porque não fez aquelas primeiras chamadas em paralelo. Certo, vamos ver como nos saímos com o DeepSeek. E dá para começar a ver por que isso é difícil, porque todo mundo me pergunta: “Como você avalia agents?” Agents são os mais difíceis de avaliar, porque há muita coisa acontecendo. Há muitas coisas diferentes acontecendo ao longo do processo.

28:42 A questão é: está chamando as ferramentas certas? Está chamando-as de forma eficiente? Está fazendo chamadas em paralelo? Neste caso, este não fez nada em paralelo, mas pelo menos fez apenas quatro chamadas de ferramenta. Então, foi razoavelmente eficiente. E, com o Mistral, muitas vezes vemos que ele esquece a última etapa. Vamos ver. Esse é o outro problema com os agents. Às vezes, quando chegam ao ponto em que a context window fica cheia, eles podem esquecer algumas instruções anteriores.

29:13 Talvez não sejam tão minuciosos em prestar atenção ao que eram as etapas originais. Às vezes, é preciso ir dando instruções ao longo do processo para que se lembrem: “Ah, espere, você deveria terminar com esta última etapa, certo?” Certo, ele não fez chamadas em paralelo. Então, vamos ver que o GPT-5.5 é muito bom em chamadas paralelas de ferramentas. Os outros não estão fazendo isso. Certo, o Mistral decidiu pesquisar apenas voos e hotéis e depois não fez mais nada. Então,

29:44 [risos] ele meio que desistiu ali. Esse é um exemplo em que teríamos que dar algumas instruções adicionais, tipo: “Ei, tem certeza de que já fez tudo, certo?” Você poderia usar algo como o route loop. Jeff Huntley está aqui hoje. Ele criou o route loop. E dá para forçar os agents a serem mais proativos, em vez de simplesmente usar o loop padrão. Certo. Então, esse foi um exemplo de agent. Também temos exemplos de agents nos outros frameworks.

30:16 Mas o que você vê é que o código é muito parecido entre eles. Eu tendo a achar que a maioria dos frameworks de agent é mais parecida do que diferente neste momento. Mas fique à vontade para conferir. Certo. Agora podemos falar de avaliações, certo? Até agora, fizemos tudo manualmente, executando e observando os resultados. Isso é bom para ter uma noção do tipo de diferença que você pode encontrar, mas, quando você for fazer algo para produção, vai querer ter avaliações em lote

30:48 automatizadas, que possa executar de maneira confiável e cujos resultados possa comparar, certo? Então, o primeiro passo que podemos dar é fazer evals sem nada sofisticado, usando apenas comparação de strings, certo? O exemplo que tenho aqui é aquela tool call de criar um evento no calendário, porque podemos obter os argumentos e simplesmente fazer uma comparação direta de strings, perguntando: “Olha, retornou ‘virtual’, certo? Queríamos ‘virtual’ para isso. Retornou ‘virtual’?” Então,

31:19 quando estiver testando uma única tool call, basta verificar se chamou a ferramenta certa e usou os argumentos corretos. É isso que vamos fazer aqui. E configuramos vários casos de teste, certo? Porque, ao executar evals, você quer ter muitos casos de teste. Também quer que seja fácil adicionar mais casos, porque, quando seu app estiver em produção, você vai ver como os usuários realmente o usam e vai pensar: “Ah, entendi. Obrigado. Está tudo quebrado.” Aí você vai adicionar esses novos casos de entrada dos usuários às suas avaliações para

31:51 garantir que não haja desvio, certo? Isso é chamado de desvio do modelo, ou de se afastar do comportamento esperado. Então, você não quer que suas evals se afastem das entradas dos usuários. Depois que o app estiver em produção, você vai querer ter um bom sistema para incluir novas entradas dos usuários nos seus casos de avaliação. Aqui, tenho vários casos diferentes. Por exemplo, uma mensagem do usuário e as verificações, que são apenas comparações de strings, algumas comparações de listas, e verificamos coisas diferentes, certo? Conferimos os cálculos de datas. Eu sempre testo LLMs com cálculos de datas, porque

32:24 geralmente eles não são muito bons nisso. Então, outra dica: se você estiver trabalhando com datas, dê a eles uma ferramenta para fazer cálculos de datas, certo? Porque é difícil demais calcular datas de cabeça, especialmente em anos bissextos. Eu estava avaliando um LLM em um ano bissexto, e foi difícil. [risos] Depois tivemos durações ambíguas. Fiz um caso em espanhol, certo? É bom testar em diferentes idiomas, quaisquer que sejam os idiomas que você pretende oferecer suporte. [fungada] Este aqui, acho, está escrito com muita gíria. “E aí, pode reservar a sala de conferências grande?” Certo. Então, temos vários casos extremos aí, certo?

32:55 E agora vou executar essas evals. Certo, neste caso vou executá-las em cada um dos modelos e dos casos de uso. Muitas vezes, na prática, quando executo evals, rodo apenas em um modelo e comparo com uma execução anterior, talvez feita com outro modelo. Mas, como hoje estamos comparando modelos ativamente, vou executar em todos eles para podermos ver. Para cada um, ele vai fazer a

33:27 tool call, verificar os argumentos retornados e decidir se passou ou falhou. Agora, sobre evals: você não quer simplesmente incluí-las nos seus testes de integração, como parte da sua suíte de testes, porque elas são lentas e caras. Sim, alguma pergunta? >> Vejo que você só está verificando strings. Você sabe se algum framework faz isso de um jeito mais elegante? >> Você não gosta das minhas verificações de strings. Sim, quanto a frameworks para evals, muitos… Primeiro, a maioria dos provedores de observabilidade tem evals integradas, certo? Então,

34:00 se você estiver usando LangFuse, LangSmith, LangChain, Arize, todos têm seu próprio framework integrado. No caso do Foundry, temos dois frameworks diferentes para isso, e eu incluí exemplos no repo. Esses são o Azure AI evaluation SDK e o OpenAI.evals, do pacote OpenAI. Há vários frameworks, além do DeepEval e do Promptfoo em JavaScript, se você usa JavaScript. E qual era o outro? >> Vali. >> Vali?

34:31 >> Algo assim. >> Mark Vali, certo. >> V A L L Y. >> V A L L Y, certo. Bom, você usa esse. Há vários frameworks para evals. Vou usar um mais sofisticado daqui a pouco. Mas, para verificar strings, é o seguinte: não precisa de algo sofisticado, porque… >> Se você quer que ele faça algo específico… >> Isso. >> Fazer a paralelização que você mencionou para… >> Sim, sim. Para tool calls, aí você vai precisar de algo um pouco mais sofisticado, sim. Então, eu quis começar pelo básico, mas, na maioria das vezes, não dá para ficar só no básico, certo? Ah, na verdade, eles foram

35:04 muito bem desta vez. Nossa, legal. Normalmente, vamos precisar passar para avaliações mais sofisticadas. É aí que começamos a usar LLM as a judge. Isso porque, muitas vezes, a saída é bem mais subjetiva, e precisamos usar um LLM para ajudar a avaliar essa subjetividade. Há muitos frameworks que encapsulam esse processo. Para este exemplo, decidi escrever tudo diretamente no código para que vocês pudessem ver. A ideia de usar um LLM as a judge

35:38 é que você precisa colocá-lo no modo de juiz e dizer: “Certo, você é um avaliador. Isto é o que está sendo avaliado, e você precisa dizer se passou ou falhou.” Estamos tentando fazer o LLM dizer se passou ou falhou. E também queremos que ele dê uma justificativa. É muito útil que ele apresente uma justificativa. Então, queremos o resultado — aprovado ou reprovado — e uma justificativa. Depois, fornecemos a consulta e a resposta. Para fundamentar a avaliação, também queremos fornecer o contexto, porque isso ajuda o modelo a raciocinar sobre ela. Às vezes, para fazer uma avaliação de verdade, você precisa

36:08 ter acesso a mais informações. Por exemplo, se você está tentando avaliar se o uso de tool calls foi eficiente, precisa fornecer tudo. Tem que fornecer as definições das tool calls e os rastros das tool calls que ele fez, certo? Então, para criar avaliadores realmente bons, muitas vezes não basta fornecer a entrada e a saída: você fornece tudo o que aconteceu ao longo do caminho, tudo o que foi mostrado. Aqui, dizemos ao LLM: “Olha, vamos usar GPT-5 como modelo juiz. É um modelo juiz bem bom.” E vamos pedir que ele gere

36:40 um JSON que possamos analisar. Então, vou executar este LLM as a judge. O problema é que isso vai ser ainda mais lento, porque, a cada avaliação, vamos executar nosso próprio código, que usa um modelo, e depois vamos usar outro LLM para julgar esse código, certo? Então, cada caso de avaliação envolve, na verdade, duas chamadas a LLM. E, muitas vezes, você executa vários LLMs como juiz. Por exemplo, pode ter cinco avaliadores diferentes que você

37:11 em execução. Cada uma delas vai ser uma chamada separada de LLM, certo? Então, o complicado dos evals é que você não pode simplesmente executá-los o tempo todo. Não dá necessariamente para executá-los em cada CI e em cada commit, porque eles demoram bastante para rodar. Porque, normalmente, em produção, por exemplo, com RAG, quando estou avaliando RAG, você geralmente quer pelo menos uns 200 casos de teste, talvez 800. E isso são muitas chamadas a um LLM, certo? Então, leva algum tempo.

37:41 Então, você precisa pensar na frequência com que vai executar evals. Dá para ver que ele está percorrendo o texto; tem vários casos de teste diferentes, com perguntas e respostas diferentes. E está analisando os resultados. Neste caso, o que fiz foi executar previamente as perguntas e respostas. Essa também é uma maneira comum de fazer isso. Por exemplo, obter todo o contexto para o avaliador de antemão, porque assim você pode alterar o avaliador independentemente do seu app, certo? E isso é mais eficiente. Porque muitas vezes você percebe que seu

38:13 avaliador está incorreto, certo? Quer dizer, você não escreveu um bom avaliador. Então, é isso que você precisa descobrir quando usa LLM as a judge: espere, o problema está no meu app ou no meu juiz, certo? E você também quer calibrar seus juízes com a contribuição de pessoas. Então, trabalhar em um domínio que você conhece ou com um especialista no domínio definitivamente ajuda; essa pessoa pode ajudar você a rotular seus dados e dizer se concorda com o LLM as a judge. Foi realmente aprovado ou reprovado? Então, aqui recebemos os resultados e podemos ver o modelo

38:47 e suas pontuações. A maioria recebeu dois de três. Mr. Owl recebeu um de três. Então, ainda precisam melhorar em relação a se manterem fundamentados aqui. Esse é o fluxo de usar LLM as a judge. Como vocês podem ver, há vários frameworks que incluem LLM as a judge e facilitam esse processo. Mas quero mostrar que você também pode fazer isso por conta própria. Ah, também quero recomendar, se você tiver interesse em avaliação, o Hamel.dev. Não sei se ele está na conferência esta semana, mas ele

39:21 tem os recursos mais incríveis e dá cursos sobre evals o tempo todo. E também faz memes muito bons. Na verdade, usei estes ontem à noite. Então, se você estiver conversando com alguém sobre evals e precisar de um meme sobre evals, o que eu estava fazendo ontem à noite? Isso mesmo, criar um LLM as a judge é difícil. >> [risos] >> Então, este é um recurso muito importante. Como podemos confiar no juiz LLM? Você precisa calibrar seu juiz LLM. Certo. Tudo bem. Então, isso foi LLM as a judge. Mas, como vocês podem ver, é

39:54 difícil criar avaliadores-juízes, certo? Você precisa seguir o Hamel no Twitter, fazer o curso dele e aprender todas essas boas práticas para escrever um bom eval. Então, temos esta nova ferramenta da Microsoft Research. É muito nova, saiu na semana passada. Chama-se Assert. E o Assert ajuda você a escrever os juízes com base na especificação. Você escreve uma especificação. Diz: “Ei, este é o agent que estou criando e é mais ou menos isso que quero que ele faça, esta é a minha ideia de como ele deve funcionar e estes são os tipos de usuários que deve atender.”

40:24 Então, a ferramenta gera muitos casos de teste. Ela desenvolve sua especificação, transformando-a em rubricas de avaliação concretas, e resolve tudo isso para você com base em pesquisas, certo? Então, já fizemos isso para o planejador de viagens que está aqui. Então, aqui está o eval do Assert. Certo. O que podemos ver é que escrevemos um

40:57 arquivo YAML, porque todos queríamos ter mais YAML na nossa vida. O que percebi sobre YAML é que talvez eu odeie YAML, mas, para o que preciso fazer, ele é melhor do que qualquer outra coisa. Então, pronto. Neste YAML, descrevemos o contexto e dizemos: “Certo, vamos usar este modelo juiz. Estas são as dimensões que nos importam: orçamento, pressão orçamentária.” Podemos dar mais informações se soubermos, por exemplo: “Ah, nos importamos com orçamento folgado, orçamento apertado ou orçamento não especificado.” Assim, você pode

41:27 estratificar. Isso se chama estratificação. Você pode fazer a estratificação previamente, se quiser, ou pode pedir para a ferramenta criá-la. E temos mais dimensões aqui. Também existe uma skill de agent que ajuda você a escrever esse arquivo YAML, para não precisar escrevê-lo por conta própria, porque ninguém quer fazer isso, certo? E depois temos aquilo que está sendo avaliado. Este é o planejador de viagens do LangChain que vimos antes. Isso garante que tudo seja rastreado, porque, ao fazer avaliações, você quer ver cada chamada de ferramenta para poder avaliar tudo corretamente.

41:58 Certo. Então, ele executa tudo e podemos ver os resultados. Leva um tempo razoável. Então, já temos os evals aqui. Deixei eles rodando. Há uma pequena interface que você pode usar para visualizá-los. Certo. Aqui está o resultado desta avaliação de busca. Basicamente, ela identificou as diferentes categorias de comportamento,

42:32 certo? Como orçamento inviável, violação da regra de preferência por voos diretos e uso obrigatório de ferramentas, certo? Então, ela identifica quais comportamentos são permitidos e quais não são. Depois, gera o conjunto de testes. O conjunto de testes é bem divertido. Aqui vamos nós: cenário 65. Voo noturno antes de o instalador percorrer o ônibus com seis textos dos pais em um fim de semana para ver Alma. Gosto muito do fato de que estes títulos obviamente foram gerados por LLM, certo? Ela criou todos estes: ônibus com uma prancheta.

43:06 Ela consegue criar todos esses cenários com base naquele YAML para tentar simular usuários, certo? Porque é muito difícil montar sua avaliação antes de entrar em produção, mas você quer ter evals antes de entrar em produção, certo? Então, como descobrir qual será seu conjunto de testes? E este framework Assert ajuda bastante a criar esse conjunto de testes e a iniciar seus evals. Ele tem prompts e cenários. Depois, temos os resultados. Certo. Para obter os resultados, ele executou tudo com DeepSeek, Kimi e GPT-5.5 e chegou

43:40 a estes números. Neste caso, números menores são melhores. Então, podemos ver que o GPT-5.5 se saiu muito melhor do que os outros. Na verdade, fiquei surpresa, porque vimos que Kimi geralmente tem sido muito bom hoje, e eu achava que estava mais ou menos no mesmo nível. Mas, pelo menos neste cenário, o GPT-5.5 teve o menor número de violações, então ficou com a melhor pontuação aqui. Então, é isso. Este é o Assert. Vou

44:12 dizer que sou completamente nova no Assert, já que ele saiu há apenas uma semana. Então, foi só isso que consegui usar até agora, mas a ideia é ajudar você a criar esses avaliadores, montar esse conjunto de testes, seguir as boas práticas e iniciar seus evals, para que você possa começar com evals realmente bons. Porque o que estamos vendo é que continuamos dizendo às pessoas: vocês precisam executar evals, precisam executar evals, mas ninguém executa evals, ou então executam os evals padrão, como coerência e fluência. Nunca usem esses. LLMs são ótimos em produzir textos coerentes. Você nunca

44:46 precisa verificar se um LLM é coerente. Se não for, é porque algo muito ruim aconteceu. Às vezes, uso os avaliadores de fundamentação e relevância para minhas coisas de RAG, mas, na maioria das vezes, os avaliadores integrados não são o que você precisa. Você quer criar avaliadores personalizados. E é nisso que isto está ajudando: você precisa de avaliadores personalizados para realmente ver se seu agent está fazendo um bom trabalho. Mas, sabe, você precisa de alguma ajuda para começar a criar esses avaliadores personalizados. Certo. Ah, faltam 3 minutos. Fiquei falando demais. Certo, finalmente, sabe, antes estávamos falando sobre

45:20 engenharia de prompt: como podemos ajustar este prompt para funcionar melhor com esses modelos? Isso é bem doloroso, né? Ter que ajustar o prompt toda vez que você troca de modelo e depois rodar evals de novo dá bastante trabalho. Ah, tem um timer. Obrigado. Certo. Se você tem que ajustar o modelo toda vez, dá bastante trabalho, e você não sabe como ajustá-lo, né? Não conhece os detalhes de cada modelo, nem o que vai funcionar bem com ele. Então, o que acrescentei como exemplo final

45:50 é o uso de DSPy. Alguém aqui já usou DSPy? Legal, algumas pessoas. Então, a ideia do DSPy é que você declare seu programa, dizendo: “Estou criando este programa, que espera receber uma entrada do usuário e transformá-la em uma saída estruturada”. Você declara as restrições do seu programa, e então o DSPy encontra o prompt que atende a essas restrições. Ou seja, o DSPy escreve seu prompt. Basicamente, você registra sua especificação e deixa o DSPy escrever os

46:22 prompts com base nas avaliações e em descobrir: “Que prompt vai satisfazer essas restrições?”. E ele usa este algoritmo interessante chamado GEPA, algoritmos genéticos de Pareto. Ele pode usar esses algoritmos genéticos para criar o próximo melhor prompt a ser testado, e é muito legal vê-lo fazer isso. Essa é a ideia do DSPy. Então, basicamente, precisamos configurar… É bem diferente, né? Você não pode simplesmente pegar seu código padrão e usar. É preciso reescrever praticamente todo o código porque, em vez de ter seu pro… seu prompt no

46:53 código, as restrições ficam no código. Sua especificação é seu código. O prompt é uma saída desse processo do DSPy, né? Aqui, estou pedindo que ele gere uma lista numerada em que cada linha tenha uma contagem exata de palavras e a primeira letra de cada linha forme uma palavra-alvo. Esse é o tipo de entrada; depois, temos um monte de restrições para verificar se o resultado está correto, né? Então, você precisa definir sua especificação e configurar verificações, testes para conferir: “A saída satisfaz esta restrição?”. Assim, o DSPy pode continuar iterando, subindo a colina, basicamente até

47:23 encontrar um prompt que satisfaça essas restrições, né? Você fornece a ele o modelo aluno e o modelo de reflexão; depois, ele executa este otimizador GEPA, que tenta encontrar o melhor prompt, e então recebemos o resultado. Deixei o resultado salvo aqui para podermos vê-lo. Leva um bom tempo. Esta tarefa demorou uns 6 minutos. Mas aqui, este resultado são as instruções propriamente ditas. Vou ativar a quebra automática de linha. Certo. Este é o system prompt que ele criou com base nessas

47:57 restrições e nessas verificações, né? E isso é bom porque este é um system prompt que funciona com Mistral. Escolhi Mistral porque era o modelo com que estávamos tendo mais dificuldade, né? Então, especialmente usando modelos menores, isso significa que podemos usar o modelo mais barato e ainda obter os resultados de que precisamos, né? Houve ótimas palestras de empresas como Dropbox e Shopify sobre como usaram DSPy e GEPA para deixar de usar modelos maiores e passar a usar modelos menores, talvez até fazendo o deploy na própria infraestrutura e obtendo os mesmos resultados.

48:29 Mas o principal era usar essa abordagem para descobrir qual é o prompt ideal. É, sem dúvida, uma maneira diferente de escrever seus aplicativos. Pode parecer um pouco estranho ter o prompt como saída desse processo, mas também é uma maneira potencialmente muito poderosa de escrever o aplicativo e pode dar a você muito mais independência em relação aos modelos e mais flexibilidade para usar mais desses modelos. Então, eu queria garantir que as pessoas também conhecessem essa opção. Certo. Então, é, era isso tudo

49:03 que eu queria mostrar. Como vocês podem ver, há muitas diferenças entre os modelos, diferentes maneiras de melhorar a saída do modelo e depois avaliá-la e melhorá-la. Recomendo que vocês experimentem os modelos. Sempre aprendo muito quando testo modelos diferentes e vejo como eles são diferentes. Ah, não mostrei a Anthropic. Eu queria mostrar a Anthropic. Certo. Também tenho alguns modelos da Anthropic em deploy. Com a Anthropic, você precisa usar uma

49:33 API diferente. Por isso não usei a Anthropic na maior parte do tempo. Mas talvez você tenha interesse na Anthropic. Eles usam a Messages API, então você precisa adaptar seu código. Mas eu gosto especificamente dela para RAG, porque há algo interessante: a Anthropic tem a ideia de citações integrada aos modelos. Você pode fornecer as fontes neste formato estruturado. Então, diz: “Esta é minha fonte. É um documento. É texto. Aqui está o texto.” Depois, você habilita as citações. E

50:06 então os modelos da Anthropic são treinados para retornar blocos de texto com citações. Você pode extraí-las de forma programática, o que é muito útil quando você está criando frontends. Basta vincular suas citações. Isso é muito legal. Então, outra coisa a considerar são as várias maneiras diferentes de chamar modelos. Certo. Estamos chegando ao fim do tempo. O repo vai continuar disponível, então vocês podem continuar trabalhando nele. Preciso trocar as chaves que coloquei naquele .env, porque, quer dizer, confio em vocês, mas não sei até que ponto. E o Cedric já disse que foi errado da minha parte fazer isso. Então, não vou poder manter essas chaves por muito mais tempo. Mas espero que vocês possam experimentar com o repo. Também podem testar com uma llama. Adicionei suporte a llama ontem. Então, se quiserem testar uma llama também, se estiverem usando modelos locais, basicamente basta alterar os exemplos para apontarem para o servidor local da llama. Também é preciso mudar os nomes dos modelos, né? Mas, em geral, todos devem funcionar com

50:41 uma llama também, porque é a mesma API. Certo. Obrigado a todos. Ah, e tem adesivos. >> [aplausos]

51:12 uma llama também, porque é a mesma API. Certo. Obrigado a todos. Ah, e tem adesivos. >> [aplausos]

Transcrição original

[00:13] All right. Uh since it’s already like 11:12, I want to start talking about the workshop. Um so, I’m going to do this as a guided workshop, so I’ll go through all the examples up here on screen, um but you can also uh try and follow along. So, the repo is there, the environment variables are there. Uh so, the environment variables give you access to a bunch of Foundry models that I’ve deployed on uh Microsoft Foundry project. Um and they have a certain amount of token capacity. It is possible

[00:47] that we are going to go over the token capacity um in you know, in this session. Um I only got found out very recently that this workshop was accepted, so I tried to get as much resources as I could in the small period of time. Um so, in that EMB file, there is actually uh multiple different possible environment variables that you can comment in or comment out. If we do start getting 429s, um you know, uh rate limit exceeded errors. Uh so, yeah. So, I’m hoping that there’s enough capacity

[01:18] for all of you to be able to try out those models, and uh we will see. Uh I also have my colleague Cedric here. Uh so, Cedric is going to be wandering around while I’m talking, so he might be able to help uh with with issues as well. Uh if you In terms of setting up the code, if you already have Python and UV on your machine, then you can do a get clone of the repo and run UV sync, and that should have everything you need to run the examples uh once you have that .env. Uh otherwise, you can make a GitHub code space. That’s uh basically a VS code in

[01:51] the browser that has everything set up for you. Uh who here uses UV? Cedric wants to know. Okay. So, it’s not number one yet. But, the other question here, who uses Python? All right, then more people. Okay. >> Pretty much everyone uses Python here. >> Yeah. Oh, did you count the overlap? All right. Okay. All right, so if you didn’t take a picture of that screen yet, just take a picture of it now. Otherwise, Cedric also has a picture of it on his phone, so he can go around if you need

[02:21] those links. Uh, so the goal of this workshop is to be able to get a feel for the differences between the different, you know, uh, top-of-the-line models and see how they differ and, you know, what you can improve about them. So, I’ve set up a bunch of different examples and also evaluations and optimizations that we can do to improve our experience across models. Uh, and I think this is a really important thing for all of us to just be to be doing as AI engineers because, you know, as you’ve seen, like, there’s so many new models that come out all the time. And, you know, the US government

[02:53] at any point could cut off access to a model. So, we need to like, we need to have options, right? So, we need to be able to, you know, point our AI applications at a different model and and have it still work or know how to improve it. Uh, so that’s the goal here is to get more experience with more models. So, uh, these are the models I’ve deployed inside Microsoft Foundry. Uh, so I’ve got uh, GPT-5 5, that’s a standard one I use all the time. But, then I’ve got Kimmy K2.6, that’s a uh, more recent one that’s quite good. I’ve got Deep Seek V4 Flash. And then I have Mistral Large 3.

[03:27] So, these are the four models that we’ll be comparing in this workshop. Um, so as I was saying, you can in order to set up the workshop, here’s the repo that that you’re all into. So, if you don’t have Python on your machine, you can just click on the code button and there’ll be a big button here that says create code space. So, you click on that, it’ll make a code space. So, then here’s the uh, the code space and then this has um, I’ve already put the dot env, but then you go and you grab that other

[03:59] um URL that I put up there to get the env. That goes to this file here. You download it. You open that. And then you create a dot env with the contents, okay? So, this is pointing at a that foundry project that has those four models deployed. As you’ve seen, that does have you know, it has token limits. So, if we start getting rate limits, you can start you can try these other models that also have the four project deploys. And then I have a separate one specifically for

[04:32] Anthropic just because it has different terms for that project. All right. So, so yeah, and then once you’ve got that set up, then you v sync will sync all of the packages that you need for Python. All right, so that’s the setup. Now, I’m going to actually go through it and do it do it up here so that you can you know, hopefully follow along if you want, or you can just watch watch what I do. So, as I was saying, we do have the four models, and you can compare models just

[05:04] doing benchmarks. You’re like, oh, you know, this one has good quality benchmarks and good safety benchmarks. You can also look at you know, the cost and thoroughput and stuff like that. And you can get this approximate notion for how good these models are, but you don’t really know how good a model is until you use it for your particular scenario because there’s so many different ways of using models. And a particular benchmark isn’t really going to tell you how it’s going to work for your scenario. So, that’s what we have in this repo here is a ton of different scenarios, and we can try out these

[05:36] models for each of them. So, we’re going to start really really basic, all right? So, just a single LLM call that asks the LLM to do something. So, what you see for each of these files is that they all start off with the model variable and they default to GPT-3.5. That’s kind of our baseline. It’s obviously it’s a very good model. But then if we want to try a different model, we can just uncomment that line and that will be the model that gets used. So, this file here is connecting using the OpenAI Python SDK to the Foundry URL and passing in the key from the environment. And the

[06:11] prompt we’re doing here is how many times does the letter E appear in the following sentence? The elderly gentleman eagerly entered the elevator. Count carefully. All right. So, then we send that to the OpenAI responses API and say, “Here, use this model with this prompt and then let’s see the raw the output, right?” So, we’re doing the classic thing of asking LLMs to count. And so, we’ll see, you know, how well they’re able to do. So, I’m going to say UB run examples with the name of this this file name

[06:41] here. And this is all in, you know, in the read me. So, we’re just going through one by one. So, you can just copy-paste from there. All right. So, GPT-3.5 is actually very good at math, surprisingly good at math. My colleagues have been running a lot of finance benchmarks on it lately and they’re like, “Oh my god, like it does so much math in its head.” So, it does actually get this correct that there are 13 E’s in this sentence, right? So, now let’s try Now we just change it, right? So, okay, let’s say we want to try Kimmy. So, we go and we change to Kimmy and now Kimmy will be the model that’s used. And we see, “Okay, can Kimmy count as

[07:16] well as GPT-3.5?” And it does. It gets 13. All right. Now you might be thinking, “Oh, is this just too easy? Let’s try DeepSeek V4 Flash. And this time it gets six. Okay. So, it missed out on seven of the E’s, right? So, we can immediately see that there’s definitely difference between you know, DeepSeek V4 and those first two models. And then finally, we’ll try Mistral. And this one gets eight. Uh so, what we see there’s a difference here. All right. So, when you see this and you’re like, “Well, I want to be able to

[07:48] use all these models.” Then you start doing some prompt engineering. You’re like, “Okay, what if I say, uh you know, break the sentence into words, count per word, uh sum, show your reasoning, right?” Let’s try Let’s try that, right? And you know, we can fix our typos, not that it matters. All right. So, let’s try it with Mistral and see with a little bit of prompt engineering, can we get a better better response here?

[08:18] All right. And it got it, right? So, you know, by breaking it up, doing a little chain of thought here, it was able to come up with the correct answer, right? So, immediately, we can see that there’s obviously differences across models and if we change prompts, you know, we can get uh different outputs. All right. So, now let’s get more interesting and go to more real-world scenarios. Uh so, let’s look at RAG. So, RAG is still one of the big uses. Arguably, really everything is RAG. Agents are RAG, too. Um

[08:49] So, we have this So, RAG is when you ask an LLM to answer a question based off some context, right? And the thing that’s important for RAG is that you want it to answer the question and stay grounded in the context. You don’t want it to make up anything that is just from its weights, right? You’re trying to force it stick to the context, right? And that’s what I find really varies across the models is that the smaller models, the less powerful models are actually much more likely to go to their weights and pretend it was part of the context. Um so, what we have here is um we have a data set about carpenter bees and we ask it a question, “What are

[09:24] the key differences differences between how honey bees and carpenter bees build their nests?” But this data set only has carpenter bee information. Uh so, it should only actually be able to answer about carpenter bees. So a good response in this case would tell me the carpenter bee information and then it say, “Sorry, I can’t tell you about honey bees. I don’t know.” Um, so we tell it like, “Hey, your job is to answer based on the sources, cite the sources. Um, here’s your here’s your question, here’s your sources.” All right, so let’s go ahead and try that out and see what we get.

[10:02] All right, and it’s Yeah, so when it’s doing the search first, very basic search. Okay, so it’s sending did the search. All right, and what we see and it says the data set does not provide details on honey bee nest construction. So this is what we actually want to see. This is from GB55. GB55 is very good at knowing what it doesn’t know. So now, let’s try switching Um, Kimmy’s also good as well. So I’m not going to show every model every time now just for for sake of time. Um, so let’s try Deep Seek, right? Cuz

[10:34] we’ve already seen that, you know, there’s a distinction here. Now Deep Seek, once again, says provided sources do not contain information. All right, so Deep Seek did a good job here. And now let’s go to Mistral. Uh, Mistral, sorry. Cedric, how do we say Mistral? It’s French, right? French company? >> Mistral. >> Mistral. Cedric’s going to be my French translator. Every time I need to say it, you’re just going to say it. Now, Mistral. Mhm? Yeah, okay. Mistral. Um, so Mis- Mis- With Mistral >> [laughter] >> Um, we do see that Mistral actually

[11:07] answered uh, from its weights uh, even though that information was not in the sources. So this is an example where a model went into its weights even though we didn’t want it to do, right? Now we can try to force it. Once again, we can try to do prompt engineering. Uh, we can say uh, wait, actually so it would say uh, if the if the answer for a bit of info is not in sources.

[11:37] Say no source provided. I think this is what I got it to work. Uh oh, I will try that and do not make up an answer. All right, let’s try this. >> [snorts] >> So, we’re trying to force it to realize when it’s giving us information that’s not in the weights. And sometimes if you force it to say, “Hey, for every bit of information that you’re giving back in your answer, you have to prove that you got that from from the sources, right?” Um so, here I’m trying to have it

[12:10] associate each of the things in that in that answer with a source and um and maybe that will force it to realize, “Oh, wait a second, that wasn’t actually, you know, in my in my answers here.” All right, it’s still going out. It’s going to think it’s thinking really hard about it here. Okay. And there we go. Honeybee details are no source provided beyond interactions with carpenter bees. >> [laughter and gasps] >> Um so, it definitely knew when things were not source provided. It still gave

[12:43] the information. So, we got a little closer. But as you can see, this is definitely uh a difference that I see with rag and rag is what I work with the most. Uh so, it’s it’s something you want to evaluate when you’re looking at models to use with rag is are the models willing to admit what they don’t know, how likely are they to make stuff up? All right, so now let’s move to image input. A lot of these models are multimodal, so they will accept images as input. And you know, there’s lots of really cool um situations you can do

[13:14] with image input. So, here we’ve got some files locally and we’re just going to send them to the LLMs and ask them some questions about the files, right? Um I’ll show you the files. Examples, image input. Okay. All right. So, the files we have here are this picture. This is an aurochs, not a unicorn. This picture. This is of some crocodiles that I saw in Costa Rica that I was very afraid of. And then also we have this picture which is a list of plants.

[13:49] Basically like a screenshot of a table with some really small fonts in it. So, we’re asking each of the LLMs to interpret each of the images, right? So, first we say, “Oh, is this a unicorn?” Right? That should be easy to say it’s not a unicorn. Great. Then we say, “Hey, are these alligators or crocodiles?” That’s a bit tricky. They are actually crocodiles because of their snout. I spent a lot of time reading the Wikipedia page about crocodiles and you got to look at their snout and then you know. Luckily, GPT-5.5 has also been on a Wikipedia binge and so it knows that

[14:20] when it sees that snout, then that is crocodiles. And then the cheapest plant, it correctly found the cheapest plant in that like fairly small text screenshot of a table. So, that’s pretty impressive that GPT-5.5 could do that. So, now let’s try it with Now, for these models, we can’t use DeepSeek cuz DeepSeek only accepts text. It’s not a multimodal model. So, we’re only going to try Kimmy and Mistral. So, you know, it figured out the aurochs. Okay, good. Just making sure it

[14:51] works. All right. And then for crocodiles, it does say crocodiles correctly. And then cheapest plant, it got the cheapest plant. So, Kimmy is doing a great job as well. And then finally, let’s go to Mistral. Here. Let’s see. All right. So, you know, it knows it knows it’s not a unicorn. It didn’t know it was an aurochs. This one, it wasn’t sure. It thinks they’re alligators. So, it you know, it’s having a harder time looking at the it thinks that

[15:22] they’re alligators. And then for the the plants, it pulled out a plant that’s $2.30, which is way more expensive than the cheapest plant. It was supposed to find one for 58 cents. So, the Mistral isn’t able to answer these kind of images. Now, here’s the thing, when it comes to multimodal understanding, you can’t really do much prompt engineering cuz either like the like the the model either understands an image or it doesn’t. Like you might be able to do some prompt engineering if you know you’re in a very particular domain and there’s some hints that you can give to it about how to read a particular kind

[15:53] of graph. Um but really with image input, it’s about figuring out, you know, for the kind of images that you’re going to send to the LLM, does the LLM understand those images? Is it going to, you know, is it going to work for that scenario, right? Um because it may be that, you know, maybe Mistral is really good at particular kinds of image tasks, but just not this, right? So, it’s all figuring out what is the task you want to do and is the model going to do a good job at it? Now, what’s interesting with the multimodal, too, is that a lot of these also depend on the language, right? Here

[16:24] I’m using English. Remember, all these models are super English-centric, but if you switch to a different language, like if I ask in Spanish if they’re caimanes or cocodrilos, it actually thinks uh it says it gives the wrong answer because it’s getting so confused in its head between these different like words and how they map across English. Like it just becomes too hard of a task both understand the difference between alligators and crocodiles and also remember that caiman means alligator in Spanish and is not the same thing as the caiman that we have in like Florida. Anyway, it’s like it’s fascinating to

[16:56] see that once we switch to Spanish, it fails at the task. Um so, that’s another thing to keep in mind, especially we’re in California, a lot of times when we develop applications here, they are bilingual cuz a lot of, you know, 50% Spanish-speaking here. Um so, you know, your your mileage may vary as you change languages. Okay, so now let’s go on to function calling, also known as tool calling. So, tool calling is in fact the basis of like all agents. All agents are based off of tool calling. And this is a a capability that the LLMs are trained with specifically during the training

[17:30] process. So, they are trained to be able to look at a definition of a function or multiple function definitions and look at the user input and say, “Okay, based off that user input, I want to call this function with these arguments and and then, you know, just return that.” So, in this example here, I’m defining a function using JSON schema. This is what the LLMs understand. So, I say, “Okay, here’s my function. It has the name create calendar event. It has this description and these are the parameters it takes. It takes a title with this

[18:00] that’s a string. Here’s a description, right?” And all of this is all going to get sent to the LLM. So, we send this full JSON schema to the LLM and say, “Hey, here’s the function. You got to decide whether you’re going to call this and how you’re going to call it, right?” So, this is in fact, even though this this is like an object, this is prompt engineering here. Everything here is actually like me deciding what is going to be the best for the LLM, right? What type should I use? What description should I add here? What should be the names of these parameters? Cuz the LLM’s going to decide based on all that

[18:32] information how it’s going to call this function. Uh so, then we have a user message. So, it’s like So, the user’s like, “Oh, can you throw something on my calendar? It’s a platform team sync. Me, Sarah from Ange, Marcus, the new PM Priya. Tomorrow at 1:30 p.m. It’s virtual on Microsoft Teams, okay?” So, then our then we tell the LLM like, “Hey, you’re a calendar assistant. Today is Monday, June 29th. Use the available tools to process the user’s request.” And we send it the tools. And so, now the LLM is looking at the user request, looking at the tools. And in this case, it just has that

[19:02] create calendar event. And it’s going to decide, “Hey, is there a tool here I can use to answer the user?” Uh and then we’re just going to go through and see what tool calls it decides to make. Uh so there we go. So in and this is like really low-level tool calling here. Uh once we build an agent, we’re going to abstract on top of this, but I wanted to start with the most low-level tool calling we can do. And the LM just responds back with here’s the name of the function and here’s the arguments that I want you to send. The LM itself doesn’t call the function. That’s up to us to do. All

[19:35] right, so what we can see is that uh I put my I put the expected on the left just so you can see and we can see the actual. So GPT 55 did add me as an attendee, which I didn’t really want. Um but it did pretty good otherwise. So let’s try uh Deep Seek and see how Deep Seek does with this one. Cuz what we want to see like when we’re doing tool calling, we want to see is it calling the right tool? So it is in this case. It is calling the create calendar event tool. And is it passing in the arguments that we expect, right? We have certain arguments we expect. In this

[20:06] case, Deep Seek put you as an attendee. And then for the location, it said virtual {parentheses} Microsoft Teams, which is not what I asked for, right? So it’s not adhering to my argument um constraints as much. Let’s try Mistral as well. And see how it does. So once I see this, I can start to realize like, “Okay, there’s some ambiguity, right?” And you know, if it if it called it with the wrong arguments, that means there’s ambiguity. I need to go back into my descriptions and say, you know, uh you know, don’t you know, don’t include me or you, just named attendees.

[20:41] Um you know, you could say first and last if provided, right? So you start to see, you know, what what you haven’t been specific enough about and start to clarify that ambiguity and then, you know, evaluate all the different um inputs and see how it’s doing. All right. So that was a basic tool calling. The next thing we want to do, we’re building up to agents here. The next thing is to do tool calling in a loop, right? So when we have an agent, it’s calling tools in a loop until it reaches a goal. Um so, we’re going to

[21:13] demonstrate using this just a function calculate. So, this calculate takes a mathematical expression and returns back the output, right? And we have, you know, basic support for uh evaluating these uh mathematical expressions. So, we’re giving it basically a word problem where it’s like, “Oh, this store is having a sale. If I buy three shirts and pay, you know, this much tax, what’s my total?” And this can be done several different ways. It could be done with multiple tool calls to that calculator call with like one little expression at a time, like, “Do this, and then do this, and then do this, and then this.” Or, if the LM is very clever, it could batch all

[21:47] that into one long expression and do a single tool call. So, here we’re testing efficiency, right? Where, you know, there’s more like a lot of times once you have tool calling in a loop, the differences between the models is their efficiency. Are they able to get to the goal faster? Can they accomplish the same goal with less tool calls, right? So, that’s what we’re going to say. Uh the only system prompt is do not do math in your head. Okay. >> [laughter] [gasps] >> So, let’s see.

[22:18] Uh that one’s really for GB55 cuz it’s so proud of its math abilities that it’s always trying to do it in its head. Like, “Come on.” All right. So, GB55 indeed does the entire calculation in one expression. So, it only required one tool call to get to the final result. So, that’s good. That’s good. That’s, you know, fast. It saves us time. So, now let’s try with um DeepSeek. The only reason I skip Kimmy all the time is cuz it’s actually a very good model, and so it does pretty much uh on par with uh GB55 uh for much of these. Okay. So, now we can see with

[22:51] DeepSeek, it is going through and it’s doing and and and and it’s doing like so many how many it did like four. It did four tool calls, right? So, it still got to the correct answer, but it took four tool calls. And every one of those tool calls is another network request, right? And so, you know, when we’re evaluating two two models, we want to both look at the final answer, but also how how long did it take to get to that final answer, right? Um actually, Kimmy did do something really interesting the other

[23:24] day. Let’s see if it does it again with this one. Cuz Kimmy most of the time works quite well, but Kimmy does sometimes get into weird loops um when it’s kind of like double-checking itself. Uh okay, this time it did well. Yeah, the other day when I did Kimmy, it like got the right answer on the first try and then decided to check its work with the like four other calls. I was like, “No, you’re good. You’re good.” [laughter] >> [gasps] >> Um so that’s what that’s what we’re looking at here, okay? Is how many how many calls does it actually need to get to the end.

[23:54] All right, so next um we can go to uh agent loops. Okay, I’m actually going quite fast through this now, actually. Uh okay, good. [laughter] Um all right. So now we’ve got the basis, right? We’ve seen tool calling, tool calling in a loop. So now we can actually build like a proper agent. And for this, we’d usually use an agent framework. Uh I’ve gone ahead and put three different agent frameworks in here uh so that you can pick your favorite. So we have LangChain, Pydantic AI, and Agent Framework. Uh I’m sure there’s

[24:27] other agent frameworks as well that I missed, but hopefully you can find one that you like there. Uh so these are all, you know, the same idea. All right, which one do we want to show? Someone vote. LangChain. All right, LangChain is still very popular and uh hopefully there’s some LangChain folks here today at the conference. All right, so with LangChain, we are using LangChain V1, um which is a a nice uh newest TK version of theirs if you haven’t tried it in the last year. And so we connect to the Foundry models from LangChain. and what

[24:57] we have here is a travel planning agent, which is a classic example. So, it has tools. So, we have a tool for search flights, search hotels, and check budget to check if a certain flight and hotel fits within the budget, uh and then search activities within a city. Uh then I’ve got some middleware, which is just for me to see what tools are happening. And then we have the actual agent call. So, the agent has a system prompt that says you’re going to help users find flights and hotels. Uh you’re you know, it has some rules here like search for both flights and hotels, prefer direct flights, yada yada, always check check

[25:31] budget, and then ask for activities at the end based off the remaining budget. Then we have the user message. I need to fly from SF to New York City next month for 3 nights. My total budget is 6 600, and I want direct flights and an activity. All right. So, we have all that, and then we are running the agent. There’s some additional code here that’s just logging out the tool calls so that we can see it. So, let’s go ahead and try that out. Okay. And so, this is going to log out the

[26:05] tool calls that happened. We’re starting off with GPT 55 here. Now, what’s interesting here, you’ll see turn one. Let me make this bigger. Turn one, it says is parallel. So, one thing is you can do with LLMs is uh is like many LLMs support parallel tool calling where if you give them a bunch of tool definitions, they can suggest a multiple tools that can be called at the same time in the same turn. And this is really good from a performance perspective because on your server, you can actually file like you can send off

[26:35] requests in parallel to like two different databases, right? Uh so, as long as they’re independent of each other, this is a great thing that LLMs can do is say, “Hey, these two these two things can be done in parallel. Why don’t you do them?” So, uh GPT 55 on the first turn and “Hey, search for hotels in New York City and search for flights in uh from SF to New York City.” cuz it’s decided that there wasn’t a dependency between them. And then, once that came back, once it had all the options, it did a check budget um based off of the flight cost and the hotel cost that it got back from

[27:07] that call. And then, it saw what the remaining budget was and then it did a call for search activities with that remaining budget. So, this is probably the most efficient agent that we can have for this scenario. So, let’s see if we get similar um results when we change models here. Do do do. And of course, here you can even change and compare across both models and frameworks, right? Because every framework has a slightly different tool

[27:39] calling loop. We also call it the harness, right? So, a lot of times that you’re you want to compare both models and harnesses and and you’ll see there’s interesting differences across them. All right. So, this time we’re with Kimmy and Kimmy is not paralyzing uh as well. I don’t know if that’s because Kimmy doesn’t support parallel tool calling or it’s just deciding not to in this case. So, this time it did the same Actually, it did even more calls. So, it did search flight and search hotels. It did over two turns, so that’s already less efficient cuz it didn’t paralyze. Then, it decided to do two calls to check

[28:11] budget cuz I think it was checking like one more option. And then, it did the final thing. So, this one took two extra tool calls and it took longer because it didn’t paralyze that first uh set of turns. All right, let’s see how we do with DeepSeek. And you can start to see why it’s hard cuz everybody asked me like, “How do you evaluate agents?” Agents are the hardest to evaluate because there’s so much going on. There’s so many different things that are happening along the way.

[28:42] It’s like, are is it calling the right tools? Is it calling them efficiently? Is it calling things in parallel? Um in this case, you know, this one uh didn’t do any parallelizing, um but at least it only did four tool calls. So, you know, reasonably efficient. And then Mistral Mistral often will see Mistral often forgets the very last step. And so, we’ll see. Um you know, that’s the other problem with the agents. Sometimes agents, when they get to the like once their context window fills up, they might forget some earlier

[29:13] instructions. They may not be as thorough um with, you know, paying attention to what the original steps were. And sometimes you have to like kind of prompt them along the way to to remember like, “Oh, wait, you’re supposed to you know, finish up with this final step here, right?” Okay, so it did it didn’t do parallel. So, what we’re going to see is GPT-5.5 is very good at parallel tool calling. Um the other ones not not aren’t doing it. Okay, so Mistral decided to only search flights and search hotels and then not do anything else. Um so,

[29:44] [laughter] it did it did it kind of gave up there. Um so, that’s an example where, okay, we’d have to do some additional steering there to be like, “Hey, are you sure that you have everything, right?” Um you could use something like the route loop. Uh Jeff Huntley is here today. He made the route loop. And you know, you can you can force uh you know, you can force agents to be more aggressive uh instead of just using the default loop. All right. Okay, so that uh that was an agent example of saying we also have agent examples in the other frameworks.

[30:16] Um but what you see is the code is really similar across them. Uh I tend to think most agent frameworks are, you know, pre- more similar than they are different at this point. Um but, you know, you’re welcome to check them out. All right. So, now we can talk about evaluations, right? So, we’ve been doing everything just, you know, manually running them and observing the results. That’s nice to get a feel for the kind of differences that you can see, but when you’re actually going to be, you know, doing something for production, you do want to actually have bulk

[30:48] automated evaluations that you can reliably run and compare results, right? So, the first step that we can do is just uh doing evals for um without, you know, with just using string comparison, right? Um so, the example I have here is with that create calendar event tool call, cuz what we can do is like we’re actually getting back the arguments, we can actually just do a straight string comparison say, “Hey, did it give back virtual, right? We wanted virtual for this, did it give back virtual?” So,

[31:19] when you’re testing a single tool call, you can just check to see, did it check did it call call the right tool and did it use the right arguments? So, that’s what we’re going to do in this one. Um and we set up a bunch of test cases, right? Cuz when you’re running evals, you want to have lots and lots of test cases. You also want it to be easy to add more test cases, cuz once your app is in production, you’re going to see how users really use it and you’re like, “Oh, okay. Thank you. Everything’s broken.” No, and then you’re going to go and add those new cases of user input to uh your, you know, your evaluations to

[31:51] make sure that you don’t drift, right? This is called like model drift or your your your drift away from it. So, you don’t want your evals to drift away from your user inputs. So, once they’re in production, you want a good system for getting new user inputs into your eval cases. So, here what I do is I’ve got like lots of different um you know, uh cases here. Like, here’s a user message, here’s the checks, and these checks are just doing really string comparison, uh some list comparison, and we check different things, right? We check the date math. Uh I always check LLMs on date math, cuz

[32:24] usually they’re kind of bad at it. So, another tip, if you’re doing dates, give them just give them a tool to do date math, okay? Cuz it’s too hard to do date math in your head. Uh especially on leap years. I was evaluating >> [laughter] >> And LLM on a leap year, that was hard. Uh then we had um okay, ambiguous durations. I did one in Spanish, right? It’s nice to test across different languages, whatever languages you’re going to support. >> [snorts] >> Uh this one I guess is written written real slangy. Yo, can you book the big conference room? Okay. All right, so we have various edge cases there, right?

[32:55] And then we’re let me to run these evals. Okay, and these evals in this case I’m going to run it across each of the models and the use cases. A lot of times in reality when I’m running evals, I’m just running it on a single model and then I’m comparing to like a previous run where maybe I’d done a different model. Uh but you know, for today uh since we are actively comparing across models, I’m going to run it across all the models so we can see um it’s for each of them it’s doing the

[33:27] tool call, checking the args that come back, and deciding if it’s a pass or a fail. Uh now here’s the thing about evals is that you don’t want to just have these like just be part of like your pie test, like your test suite because these are slow, these are expensive. Yeah, question? >> Um I see you just roll, you know, checking strings against Uh do you know if any frameworks do this a bit more elegantly >> You don’t like my string checks. Um yeah, so framework-wise for evals a lot of so first of all, most observability providers have evals built in, right? So

[34:00] if you’re doing LangFuse, LangSmith, LangChain, um Arize, like they all have their own framework built in. For Foundry, we have um we have two different frameworks uh for it and I actually I do have the examples in the repo. Um um those ones there’s Azure AI evaluation SDK, Open uh AI.evals um from the OpenAI package. So there’s a bunch of frameworks, there’s also DeepEval and Prompt Prompt foo in JavaScript if you’re a JavaScript person. And which one? >> Vali. >> Vali?

[34:31] >> Something like that. >> Mark Vali, okay. >> V A L L Y >> V A L L Y, okay. I mean you use that one. Um so there’s a number of eval frameworks um I’ll I’m going to use a fancier one soon. But for string check, but here’s the thing like like for string check, you don’t really have to do a fancy one um because you’re like >> If you’re looking for it to do a specific >> Yeah. >> Do the parallelization you mentioned for >> Yeah, yeah. So for tool calls, yeah, that’s where you’re going to get a bit fancier, yeah. Yeah, so I wanted to start with the basic, but yeah, most of the time we can’t get away with just the basic, right? Um oh, they did actually

[35:04] really well this time. Wow, nice. Um so usually we’re going to have to move to fancier evaluation. Um so that’s when we start to bring in LLM as a judge. Uh so this is cuz a lot of times, you know, the the output is a lot fuzzier and we need to use an LLM to help us reason about that fuzziness. And there’s many frameworks that do wrap this um For this example, I just decided to write it entirely in the in the code so you could see. So the idea when you use an LLM as a judge

[35:38] is that you need to give it, you know, put the LLM in judge mode and say, “Okay, you are an evaluator. This is what you’re evaluating and you need to either say does it pass or does it fail?” Right? We’re trying to force the LLM to say does this pass or fail? Um and we also want it to give it reason, right? It’s really really helpful to have it give it reason. So we want pass, fail, and a reason. And then we give it the query, we give it the response. And for grounding this, we also want to give it the context cuz that helps it actually reason about it. So sometimes in order to really evaluate, you do need

[36:08] access to more information. So like tool calls, if you’re trying to evaluate whether it was an efficient user of tool calls, you can’t you have to give it everything. You have to give it the tool call definitions. You have to give it the traces of the tool calls it made, right? So to build really good evaluators, a lot of times you’re you’re not just giving it the input output, you’re giving it every everything that happened along the way, everything that was shown. Uh so here we, you know, we tell the LLM, “Hey, we’re going to use the judge model of GPT-5. It’s a pretty good judge model.” And we’re going to ask for it to output

[36:40] some JSON that we can look at. So let me go ahead and run uh this LLM as a judge. Now, here’s the thing, um this is going to be even slower because now each time we’re running an eval, we’re both running our own code, which is using a model, and we’re then using another LLM to judge that code, right? So every single eval case is actually two LLM calls. And then many times you actually run multiple LLMs as a judge. Like you’ll have like five different evaluators that you’re

[37:11] running. Each of those is going to be a separate LLM call, right? Um so that that’s what is tricky about evals is that you can’t just run them all the time. You can’t necessarily run them on every single CI uh and every single commit because they are fairly slow to run. Cuz normally in production, like for rag, when I’m evaluating rag, you know, you usually want like 200 test cases at least, maybe 800. And that’s that’s like a lot of calls to an LLM, right? So that that takes some amount of time.

[37:41] Um so you do want to think about how often you’re going to be, you know, running evals. So you can see that it’s going through its text it it’s got a bunch of different test cases, different questions and answers. And it’s it’s looking at the results. Now, in this case, what I did was that I like pre-ran the um the questions and answers. This is a common way of doing it, too. Like get, you know, get all your get your context for the evaluator beforehand um because then you can change your evaluator independently from your app, right? Um and that’s more efficient. Cuz a lot of times what you realize is that your

[38:13] evaluator is incorrect, right? Like that you haven’t written good evaluator. Uh so that’s what you have to figure out when you’re doing LLM as judge, you have to figure out like wait, is the problem my app or is the problem my judge, right? And uh you also want to calibrate your judges with human input as well. So, it definitely helps me working on a domain you know, or work with a domain expert that can help you label your data and say and you know, do they agree with your LLM as a judge? Was it actually a pass or a fail? Uh so here we get the results back and we can see you know, the model

[38:47] um and their scores um most of them got like two out of three. Mr. Owl got one out of three. You know, so they’re they’re they have some work to do on being more grounded here. So that is the generator of using LLM as a judge. As you see, there’s quite a few frameworks that uh make it, you know, that have built-in LLM as a judge that make it easier to do it. Um but I want to show that you you know, you can’t you can’t also do it yourself. Oh, also I should recommend if you’re interested in evaluation, Hamel.dev. I don’t know if he’s at the conference this week, but he

[39:21] has the most amazing resources and he teaches courses all the time about evals. And also he’s very good memes. I actually used these last night. So, if you’re ever chatting with someone about evals and you need an eval meme, uh what was it what I was doing last night? Yeah, building an LLM as a judge it’s it’s hard. >> [laughter] >> Uh so very important resource here. How can we trust the LLM judge? You have to calibrate your LLM judge. Okay. All right. So, that was LLM as a judge. So now um but then they as you see, it

[39:54] is hard to build judge evaluators, right? Like you have to like follow Hamel on Twitter and take his course and learn all these best practices for how you write uh a good eval. Um uh so we have this new tool from Microsoft Research. It’s very new, like the last week. Um it’s called Assert. And Assert helps you write the judges based off of the spec. So, you write a spec. You say, “Hey, this is the agent I’m building and this is, you know,

[40:24] roughly what I want it to be doing, my idea about how it should work, and um what kind of users it should support.” And then it will generate lots of test cases. It’ll like flesh out your your spec into um into actual judging rubrics, and figure all of that out for you based off of, you know, all the the it’s very based in in research, right? So, we’ve done that for the travel planner already in here. Um so, here’s the um so, it’s under this assert eval. Okay. So, what we can see is that we write a

[40:57] YAML file cuz we all wanted more YAML in our life. What I realized about YAML is that I might hate YAML, but it’s also better than everything else for what I need it for. So, there we go. Um so, in this YAML, you know, we describe uh the context, and we describe, “Okay, we’re going to use this judge model. Um these are the kind of dimensions we care about is budget, you know, budget pressure.” So, we can we can give it more information if we know, like, “Oh, we care about ample budget, tight budget, invisible.” Um you know, so, you can you can

[41:27] stratify it. This is called stratification. You can you can pre-stratify if you want, uh or you can just have it come up with the stratification. Uh and then we have more dimensions here. And there’s this there’s also a a skill an agent skill that helps you write this YAML file so that you don’t have to write it yourself cuz no one wants to write it, right? Um and then we have the actual thing that’s evaluating. This is the LangChain travel planner that we saw before. Uh so, this just makes sure that it’s tracing everything cuz it’s saying, “When you are doing evaluations, you do want to see every single tool call so that you

[41:58] can really properly do these evaluations.” All right. So, then it it runs it all, and then we can see the results. It does take a, you know, a decent amount of time. So, we’ve already got the um evals in here. Uh so, I’ve got them running. Uh there’s like a little like front end that you can use to view them. Okay. All right. So, here is the result of this um a search evaluation. Um so, basically it you know, it came up with the different behavior categories,

[42:32] right? So, making like budget in infeasibility, direct flight preference rule violation, required tool use, right? So, uh it comes up with what behaviors are you know, allowed but not allowed. And then it comes up with the test set. The test set is really is pretty fun. Um and here we go. Scenario 65. Red eye before the installer walked through the coach with six parent text one weekend to see Alma. I really like that these are obviously LLM generated titles, right? So, it came up with all of these coach with a clipboard. Um

[43:06] it can it comes up with all these scenarios based off that that YAML to try and simulate users, right? Cuz the whole thing it’s really hard to bootstrap your evaluation before you go into production, but you want to have evals before you go into production, right? So, how do you figure out, you know, what your test set is going to be? And so, this assert framework helps a lot with making that test set and bootstrapping your evals. Uh so, it has prompts and scenarios. And then we have the results. Okay. So, for the results, it ran it um across Deep Sea, Kimmy, and GBD 5.5 and uh came up

[43:40] with the you know, with the numbers here. Um and in this case the the lower numbers are better. And so, we can see that uh GBD 5.5 did way better than the other ones. I was actually surprised cuz Kimmy, we’ve seen that Kimmy has generally been quite good today um and I was thinking it was kind of on par, but at least for this scenario, uh GBD 5.5 had the lowest number of violations, and so it is it’s scoring the best here. Um so So yeah. So this is assert. I will

[44:12] say I’m I’m brand new to assert since it only came out like a week ago. Um so this is all I’ve I’ve used it so far, but the idea here is that it’s helping you to build those evaluators to build that test set and to follow the best practices and bootstrap your evals so that you can start start off um you know, with with some really good evals. Cuz what we’re seeing is that we keep telling people like you got to run evals, you got to run evals, and then no one’s running evals or they’re running like the default evals like coherence and fluency. Never run those. Like LLMs are great at being coherent. You never

[44:46] have to check if an LLM is coherent. If some if they’re not, like something really bad has happened. Um I do sometimes use the groundness and relevance evaluators for my rag things, but most of the times the built-in evaluators are not what you want. You want to build custom evaluators. And that’s what this is helping you with is like okay, you need custom evaluators to really see if your agent is doing a good job. Uh but you know, you need some help bootstrapping those custom evaluators. All right. Oh, we have 3 minutes left. I’ve been blabbing. Okay, finally, um you know, earlier we were talking about

[45:20] prompt engineering like okay, how can we tweak this prompt in order to work better for these models? That’s pretty painful, right? If you have to tweak the prompt every time you switch models and like rerun evals, that’s like a lot of work. Oh, there’s a little timer. Thank you. Okay. Uh so if you Yeah, if you have to tweak the model every time, uh that’s a lot of work and you don’t know which way to tweak tweak the model, right? You don’t know the details of every single model, what’s going to really work well for it. So uh what I’ve added is this as a final

[45:50] example is using Dspy. Has anyone used Dspy here? Cool, a couple people. So Dspy, the idea of Dspy is that you declare your program like you say, “Hey, I’m making this program that’s expecting to take user input and then turning it into a structured counter bit.” So, you declare the constraints of your program and then Dspy is going to figure out the prompt that adheres to those constraints. So, Dspy is going to write your prompt. So, you you’re basically checking your spec in and then having Dspy by write the

[46:22] prompts based off of doing evaluations and seeing, “Hey, what prompt is going to satisfy those constraints?” And it actually uses these this cool algorithm called Jeppa, genetic credo algorithms. It can use these genetic algorithms in order to come up with the next best prompt to try, which is really really cool to watch it do that. Um so, that’s the idea of Dspy. And so, basically we have to set So, it’s very different, right? You can’t just take your standard code and just use it. You kind of have to rewrite your whole code cuz now, instead of checking your pro- like your prompt isn’t in your

[46:53] code, your constraints are in your code. Your spec is your code. The prompt is an output from this Dspy process, right? So, here I’m doing I’m asking it to generate a numbered list where each line has exact word count and the first letter of the line spell out a target word. So, this is the kind of input and then we have a bunch of constraints that are checking to see is the result correct, right? So, you need to set up your spec and then set up like checks, tests to see, “Hey, does the output satisfy this constraint?” And that way Dspy can keep iterating, hill climbing, right? Basically hill climbing until it

[47:23] finds a prompt that satisfies those constraints, right? So, you give it the student model, the reflection model, uh then it runs this Jeppa uh optimizer, which you know, tries to find the best um prompt, and then we get back the result. So, the result I have it stored here so we can see it. It does take a fair amount of time. It took like 6 minutes on this task. Um but here, this result is the actual instructions. So, let me add word wrap into there. Right. So, this is the system prompt that it came up with based off of those

[47:57] constraints and those you know those checks, right? And so this is nice because this is a system prompt that works with Mistral. Cuz I I picked Mistral cuz that was the one we were having the hardest time with, right? So especially with using smaller models, this means we can use the cheapest model and still get the results we need, right? So there’s been some great talks by like Dropbox, Shopify about how they’ve used DSPy plus Jeppa so that they can move off the larger models and use the smaller models and maybe even deploy it on their infrastructure and get the same results.

[48:29] But the key was trying to you know using this order to figure out what that optimal prompt is. So this is a definitely a different way of writing your apps and it can feel a little different to you know to have the prompt be the output of this process, but it’s also potentially really powerful way of writing it and can give you a lot more model independence and more flexibility to be able to use more of these models. So I wanted to yeah, make sure that people knew about that as an option as well. Okay. All right. So So yeah, so that was all

[49:03] the things that I wanted to show. As you can see there’s lots of differences between models, different ways you can improve the model output and then evaluate it and then improve it. I do encourage you like yeah, just just tinker with the models. It’s I always learn so much whenever I you know try out different models um and see how different they are. Oh, I never showed Anthropic. I meant to show Anthropic. Okay. I do have some Anthropic’s deployed as well. With Anthropic you do have to use a different

[49:33] API. That’s why I wasn’t using Anthropic most of the time. But of course you might be interested in Anthropic. They They use the messages API instead, so you do have to switch your code around. But I actually specifically like it for rag because here’s interesting is that with Anthropic they actually have this notion of citations built into the models. So, you can actually you provide the sources in this structured format. So, you say, “Hey, this is my source. It’s a document. It’s text. Here’s the text of it.” And then you enable citations. And

[50:06] then the Anthropic models are actually trained to return back blocks of text with citation. So, you can extract those in a programmatic way, which is really nice when you’re like building front ends. You can just link your citations. So, that’s really cool. So, that’s even another thing to look at is you know, a whole different ways of calling models, too. Okay. All right. And yeah, we’re kind of at time here. The the repo will stay up. So, you’re welcome to keep working on the repo. I do need to rotate the keys that I put

[50:41] in that .env because I mean, I trust you, but I don’t know how much I trust you. And Cedric always already said I was bad for doing that. So, I I won’t be able to keep those keys up for much longer. But, hopefully with the repo you can try it out. You can also try it out with a llama. I added a llama support yesterday. So, if you want you know, do you want to try a llama, too? If you’re doing local models, you basically just change the examples to point at the local llama server. And you just have to change the model names as well, right? But, generally they should all work with

[51:12] a llama as well because it’s same API. All right. Thank you, everyone. Oh, and there’s stickers. >> [applause]