<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alberto Luiz Souza</title>
    <description>The latest articles on DEV Community by Alberto Luiz Souza (@asouza).</description>
    <link>https://dev.to/asouza</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1308158%2F8fd06aa0-b887-40fd-a791-b03dafdaa0ec.jpeg</url>
      <title>DEV Community: Alberto Luiz Souza</title>
      <link>https://dev.to/asouza</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/asouza"/>
    <language>en</language>
    <item>
      <title>Detecção de anomalias: do sensor ao dashboard</title>
      <dc:creator>Alberto Luiz Souza</dc:creator>
      <pubDate>Mon, 30 Mar 2026 01:11:49 +0000</pubDate>
      <link>https://dev.to/asouza/deteccao-de-anomalias-do-sensor-ao-dashboard-294h</link>
      <guid>https://dev.to/asouza/deteccao-de-anomalias-do-sensor-ao-dashboard-294h</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Este texto foi inicialmente concebido pela IA Generativa em função da transcrição de um vídeo do canal de Daniel Romero (a pessoa que lidera nossa especialização em Engenharia de IA). Se preferir acompanhar por vídeo, é só dar o play.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/6MECPST996I"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Detecção de anomalias é uma técnica de Machine Learning usada para encontrar padrões em dados que não estão de acordo com o comportamento esperado. Empresas de cartão de crédito e fintechs usam esse tipo de abordagem no combate a fraudes, mas a aplicação vai muito além do mundo financeiro. Neste post, vamos construir um sistema completo de detecção de anomalias para monitorar vibração em maquinário industrial, passando por coleta de dados com sensor, treinamento de modelo e inferência em tempo real.&lt;/p&gt;

&lt;p&gt;A inspiração vem de empresas reais que fornecem sistemas de monitoramento preditivo para indústria, usando sensores que coletam dados de vibração e modelos de Machine Learning que analisam esses dados para prever problemas antes que eles aconteçam.&lt;/p&gt;

&lt;h2&gt;
  
  
  O plano geral do projeto
&lt;/h2&gt;

&lt;p&gt;O projeto percorre toda a cadeia de um sistema de detecção de anomalias:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Montar um protótipo com sensor acelerômetro conectado a um microcontrolador ESP32&lt;/li&gt;
&lt;li&gt;Coletar dados de vibração de um ar-condicionado em operação normal e com anomalia simulada&lt;/li&gt;
&lt;li&gt;Analisar os dados coletados e extrair features relevantes&lt;/li&gt;
&lt;li&gt;Treinar um modelo de Machine Learning para classificar operação normal versus anomalia&lt;/li&gt;
&lt;li&gt;Criar uma API para inferência em tempo real&lt;/li&gt;
&lt;li&gt;Construir um dashboard para monitorar o estado do sistema&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Coleta de dados com acelerômetro e ESP32
&lt;/h2&gt;

&lt;p&gt;Para coletar dados de vibração, o projeto usa um acelerômetro de 3 eixos (MPU6050) conectado a um ESP32 via protocolo I2C.&lt;/p&gt;

&lt;h3&gt;
  
  
  Como funciona um acelerômetro
&lt;/h3&gt;

&lt;p&gt;Um acelerômetro detecta aceleração linear ao longo de um eixo. O sensor utilizado é uma IMU (unidade de medição inercial), que combina acelerômetros, giroscópios e magnetômetros em um chip microscópico, usando tecnologia MEMS (sistemas microeletromecânicos).&lt;/p&gt;

&lt;p&gt;Internamente, o sensor possui uma massa sísmica em forma de H com extremidades sensoriais. Essa massa fica presa ao substrato nas extremidades, permitindo um movimento de vai e vem. Durante a movimentação, os dedos sensoriais se aproximam dos eletrodos, gerando detecção capacitiva. A mudança na capacitância entre os eletrodos fixos e a massa sísmica é usada para determinar a aceleração. Em termos práticos, o sensor detecta tanto forças estáticas como a gravidade quanto forças dinâmicas como vibrações.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuração do microcontrolador
&lt;/h3&gt;

&lt;p&gt;O ESP32 conecta-se ao Wi-Fi e envia os dados do acelerômetro para uma API Python via requisições HTTP POST. O fluxo funciona assim:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O ESP32 faz uma requisição GET para verificar se o servidor está pronto&lt;/li&gt;
&lt;li&gt;Se recebe resposta positiva, coleta 200 amostras por segundo (uma amostra a cada 5 milissegundos)&lt;/li&gt;
&lt;li&gt;Os valores X, Y e Z da aceleração são organizados em JSON e enviados via POST&lt;/li&gt;
&lt;li&gt;O servidor Python recebe os dados e salva em arquivos CSV&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Na configuração do sensor, o range do acelerômetro fica em mais ou menos 4G (podendo medir até 16G) e a largura de banda do filtro em 260 Hz. O range define o tamanho da força que o sensor pode medir, enquanto a largura de banda determina o quão rápido ele consegue registrar mudanças de movimento. A combinação dos dois funciona quase como um ajuste de sensibilidade.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduzindo a anomalia
&lt;/h3&gt;

&lt;p&gt;Para simular uma falha mecânica, um imã é fixado no cilindro metálico que faz o ar circular no ar-condicionado. Isso causa uma descalibragem proposital, fazendo o cilindro trepidar. Os dados são coletados em diferentes condições: operação normal em várias velocidades e operação com a anomalia inserida.&lt;/p&gt;

&lt;h2&gt;
  
  
  Análise exploratória dos dados
&lt;/h2&gt;

&lt;p&gt;Com os dados coletados, a análise revela diferenças claras entre operação normal e anomalia.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dados brutos
&lt;/h3&gt;

&lt;p&gt;Na operação normal, o eixo Z mantém um nível constante em torno de 10g, enquanto os eixos X e Y ficam próximos de zero com linhas suaves. Na operação com anomalia, aparecem oscilações mais intensas em todos os eixos, com um padrão mais irregular.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features estatísticas
&lt;/h3&gt;

&lt;p&gt;Três características se destacam na separação entre normal e anomalia:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Média&lt;/strong&gt;: mostra o valor central das medições ao longo do tempo. Há uma separação clara, indicando que o nível médio de vibração durante anomalias é consistentemente diferente&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variância&lt;/strong&gt;: mede como os dados se dispersam em relação à média. As anomalias apresentam valores muito maiores, indicando vibrações mais intensas e irregulares&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Curtose&lt;/strong&gt;: indica o quanto os dados se concentram em torno da média. Valores mais altos sugerem picos de vibração mais intensos e frequentes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cada feature fornece uma perspectiva diferente. A média entrega uma visão geral de vibração, a variância revela a intensidade das oscilações e a curtose indica a presença de eventos extremos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transformada rápida de Fourier (FFT)
&lt;/h3&gt;

&lt;p&gt;A FFT decompõe um sinal em suas frequências constituintes. Diferentes problemas mecânicos geram padrões de vibração em frequências específicas. Um rolamento com defeito pode gerar vibrações em uma frequência, enquanto um desbalanceamento pode gerar outra.&lt;/p&gt;

&lt;p&gt;Nos dados coletados, a operação normal mostra um perfil de frequência suave e com baixa magnitude. A anomalia mostra picos em certas frequências, especialmente no eixo Z, onde a magnitude chega a 16 vezes o valor normal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treinamento do modelo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Preparação dos dados
&lt;/h3&gt;

&lt;p&gt;O processo de preparação inclui:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Carregar os CSVs de cada tipo de operação (normal e anomalia)&lt;/li&gt;
&lt;li&gt;Remover o DC (valor médio do sinal) para centralizar os dados em torno de zero, eliminando viés constante e efeitos da gravidade&lt;/li&gt;
&lt;li&gt;Adicionar ruído aleatório para aumentar a robustez durante o treino&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Extração de features
&lt;/h3&gt;

&lt;p&gt;Para cada eixo, cinco features são extraídas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Desvio padrão&lt;/strong&gt;: variabilidade do sinal&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Curtose&lt;/strong&gt;: formato da distribuição&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amplitude máxima absoluta&lt;/strong&gt;: maior valor registrado&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RMS (média quadrática)&lt;/strong&gt;: medida de energia do sinal&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Range&lt;/strong&gt;: diferença entre valores máximos e mínimos&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Distância de Mahalanobis e threshold
&lt;/h3&gt;

&lt;p&gt;O algoritmo escolhido usa a distância de Mahalanobis para calcular o quão distante um ponto está da distribuição normal dos dados. Essa distância produz uma medida de quão estranho é um ponto em relação ao comportamento esperado.&lt;/p&gt;

&lt;p&gt;Uma função complementar encontra o melhor limiar (threshold) para separar normal de anomalia usando validação cruzada. A abordagem é conservadora: falsos positivos são penalizados 5 vezes mais que falsos negativos, priorizando evitar alarmes falsos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resultados do modelo
&lt;/h3&gt;

&lt;p&gt;A distribuição das distâncias de Mahalanobis mostra:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Casos normais concentrados entre 2 e 6, com pico próximo a 3,5&lt;/li&gt;
&lt;li&gt;Anomalias concentradas entre 8,5 e 14, com pico em torno de 10&lt;/li&gt;
&lt;li&gt;Threshold definido em 5,71&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Na matriz de confusão, o modelo acertou 86 de 100 predições: 47 verdadeiros normais, 39 verdadeiras anomalias, 3 falsos positivos e 11 falsos negativos. O modelo tende a ser mais conservador, preferindo classificar como normal os casos duvidosos.&lt;/p&gt;

&lt;p&gt;No relatório de classificação:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Normal&lt;/strong&gt;: precisão de 81%, recall de 94%, F1 de 87%&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anomalia&lt;/strong&gt;: precisão de 93%, recall de 78%, F1 de 85%&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Acurácia geral&lt;/strong&gt;: 86%&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AUC Score&lt;/strong&gt;: 0,87&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Inferência em tempo real
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Atualização do sensor
&lt;/h3&gt;

&lt;p&gt;Para a fase de inferência, o software do ESP32 é atualizado. A coleta passa para 100 amostras, organizadas como uma matriz 2D que corresponde ao formato de input esperado pelo modelo. Os dados são enviados para uma API de detecção de anomalias.&lt;/p&gt;

&lt;h3&gt;
  
  
  API com FastAPI
&lt;/h3&gt;

&lt;p&gt;A API recebe os dados do acelerômetro, carrega o modelo treinado (contendo média, covariância e threshold) e executa o pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pré-processamento dos novos dados e remoção do DC&lt;/li&gt;
&lt;li&gt;Cálculo das features estatísticas por eixo&lt;/li&gt;
&lt;li&gt;Cálculo da distância de Mahalanobis para a nova amostra&lt;/li&gt;
&lt;li&gt;Cálculo de confiança considerando histórico recente&lt;/li&gt;
&lt;li&gt;Classificação como normal ou anomalia&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Vale destacar que a distância de Mahalanobis aparece tanto no treino quanto na inferência, mas com propósitos diferentes. No treino, ela é usada para definir o threshold com dados rotulados. Na inferência, é calculada para cada nova amostra e comparada com o threshold já definido. No treino se calibra o sistema; na inferência se usa essa calibração para classificar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dashboard de monitoramento
&lt;/h3&gt;

&lt;p&gt;Uma aplicação em React exibe o status da classificação em tempo real, com três métricas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Confidence&lt;/strong&gt;: confiança do modelo na classificação atual&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distância de Mahalanobis&lt;/strong&gt;: calculada para os dados recebidos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Threshold&lt;/strong&gt;: limite constante que define quando algo é considerado anomalia&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O gráfico mostra a evolução temporal dessas métricas, permitindo acompanhar o comportamento do sistema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Possibilidades de evolução
&lt;/h2&gt;

&lt;p&gt;O projeto demonstra um fluxo completo, mas várias evoluções são possíveis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Treinar uma rede neural com mais dados para maior sofisticação&lt;/li&gt;
&lt;li&gt;Mapear peças internas do equipamento para identificar a origem da anomalia&lt;/li&gt;
&lt;li&gt;Combinar dados do acelerômetro com giroscópio para aumentar a precisão&lt;/li&gt;
&lt;li&gt;Projetar hardware dedicado com PCB customizada&lt;/li&gt;
&lt;li&gt;Separar os componentes da API de forma mais organizada&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Um projeto assim não garante uma vaga de trabalho, mas funciona como treino e pode chamar a atenção em meio a milhares de candidaturas. O diferencial está em cobrir toda a cadeia do problema: desde o entendimento do hardware e coleta de dados, passando pela análise exploratória e treinamento do modelo, até a inferência em tempo real com dashboard de monitoramento.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dev + Eficiente
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Desenvolva software de alta qualidade e domine Engenharia de IA com o Dev + Eficiente.&lt;/strong&gt; Cursos práticos, acesso vitalício, comunidade ativa e acesso a vagas remotas exclusivas em diversas empresas de tecnologia. Sua jornada para se tornar um dev mais eficiente pode começar agora.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>iot</category>
      <category>machinelearning</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Skills para agentes de código fazem diferença?</title>
      <dc:creator>Alberto Luiz Souza</dc:creator>
      <pubDate>Sun, 22 Mar 2026 23:41:08 +0000</pubDate>
      <link>https://dev.to/asouza/skills-para-agentes-de-codigo-fazem-diferenca-1med</link>
      <guid>https://dev.to/asouza/skills-para-agentes-de-codigo-fazem-diferenca-1med</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Este texto foi inicialmente concebido pela IA Generativa em função da transcrição de um vídeo do canal Dev Mais Eficiente. Se preferir acompanhar por vídeo, é só dar o play.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Rz5bQqzBUww"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Existe uma discussão recorrente sobre o quanto configurar skills (no Claude Code), rules (no Cursor) ou arquivos semelhantes realmente melhora o resultado dos agentes de código. Para tentar responder isso com dados, um estudo chamado SkillBench montou um benchmark com 84 tarefas de domínios variados e testou múltiplos modelos em três cenários: sem skill nenhuma, com skills geradas pelo próprio agente e com skills escritas com participação humana.&lt;/p&gt;

&lt;p&gt;Neste post, vamos analisar os principais achados do estudo, incluindo dados do apêndice sobre taxa de falha dos modelos que costumam passar despercebidos nas discussões.&lt;/p&gt;

&lt;h2&gt;
  
  
  O achado principal: skills escritas por humanos fazem diferença
&lt;/h2&gt;

&lt;p&gt;O gráfico central do estudo compara a taxa de resolução de tarefas em três condições: sem skill, com skill auto-gerada pelo agente e com skill escrita em conjunto com um ser humano que domina o assunto.&lt;/p&gt;

&lt;p&gt;O resultado mais relevante: skills escritas com participação humana consistentemente melhoram a taxa de resolução em relação às outras duas condições. Os modelos testados incluem Haiku 4.5, Sonnet 4.5, Opus 4.5, Gemini 3 Pro, GPT 5.2, Opus 4.6 e Gemini 3 Flash, e o padrão se repete em praticamente todos.&lt;/p&gt;

&lt;p&gt;Já as skills geradas pelo próprio agente tiveram efeito quase nulo comparadas a trabalhar sem skill nenhuma. Em alguns casos, como GPT 5.2 e Sonnet 4.5, o agente sem skill teve resultado levemente melhor do que com skill auto-gerada.&lt;/p&gt;

&lt;p&gt;Isso reforça algo que segue sendo verdade: o nível de expertise de quem direciona o agente continua fazendo diferença significativa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como o estudo foi montado
&lt;/h2&gt;

&lt;p&gt;O repositório do SkillBench contém 84 tarefas de naturezas diversas. Cada tarefa tem a instrução para o agente, metadados, timeout, testes automatizados para verificar o output e uma proposta de solução determinística.&lt;/p&gt;

&lt;p&gt;A execução funcionava assim: subia uma imagem Docker com o agente instalado (Claude Code, Codex, Gemini CLI), configurava com ou sem skill, apontava para a pasta com as instruções e deixava o agente trabalhar. Depois verificava o resultado contra os testes.&lt;/p&gt;

&lt;h2&gt;
  
  
  A variação por domínio e o que ela revela
&lt;/h2&gt;

&lt;p&gt;O estudo traz uma tabela com a taxa de resolução por domínio. Alguns números:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Saúde&lt;/strong&gt;: 86% com skill, 34% sem skill&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engenharia de software&lt;/strong&gt;: 38,9% com skill, 34,4% sem skill&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A diferença entre esses dois domínios é reveladora, mas precisa de contexto. Primeiro, o volume de tarefas era diferente: saúde tinha poucas tarefas, engenharia de software tinha mais de vinte. Segundo, e talvez mais importante, os modelos são muito mais bem treinados para engenharia de software do que para domínios como saúde.&lt;/p&gt;

&lt;p&gt;Isso leva a uma conclusão prática: quanto menos treinado o modelo é para um domínio específico, maior o gap que o conhecimento humano precisa preencher. Em domínios onde o modelo já tem bastante conhecimento nos dados de treino, a diferença que uma skill faz tende a ser menor.&lt;/p&gt;

&lt;h2&gt;
  
  
  O esforço de setup pode não compensar
&lt;/h2&gt;

&lt;p&gt;Existe uma tendência a montar setups elaborados para trabalhar com agentes de código: engenharia de contexto detalhada, troca de modelos por tipo de tarefa, controle granular de consumo de tokens. O estudo sugere que, pelo menos para tarefas mais padronizadas, esse esforço pode gerar diferença marginal.&lt;/p&gt;

&lt;p&gt;Se a tarefa é de conhecimento relativamente público e o modelo já é bem treinado naquele domínio, a diferença entre um setup sofisticado e um prompt direto pode ser pequena. Isso não significa que skills são inúteis, mas que vale avaliar se o esforço de configuração está gerando retorno proporcional.&lt;/p&gt;

&lt;p&gt;Para práticas de engenharia de software que são bastante padronizadas (separação de controllers e casos de uso, cálculos comuns, estilo funcional com imutabilidade), o modelo provavelmente já consegue operar bem sem instruções adicionais. A skill faz mais diferença quando o domínio é específico e não tão bem representado nos dados de treino.&lt;/p&gt;

&lt;h2&gt;
  
  
  A taxa de falha que ninguém comenta
&lt;/h2&gt;

&lt;p&gt;O apêndice do estudo traz uma tabela com as tentativas e taxas de falha de cada modelo. Alguns números:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Opus 4.6&lt;/strong&gt;: 1.245 tentativas, 67,1% de falha&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini 3 Pro&lt;/strong&gt;: 61% de falha&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Haiku e Sonnet&lt;/strong&gt;: acima de 80% de falha&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esses números consideram todas as condições (com skill auto-gerada, com skill humana, sem skill). A maioria das tentativas falhou, mesmo em tarefas que envolvem conhecimento de domínio público.&lt;/p&gt;

&lt;p&gt;Isso tem uma implicação direta para o fluxo de trabalho do dia a dia. Se a taxa de falha é essa em tarefas padronizadas, imagine dentro do contexto de negócio específico da sua empresa, com domínio que não é público e conexões que o modelo não tem como inferir. A taxa de falha provavelmente seria ainda maior.&lt;/p&gt;

&lt;p&gt;Na prática, isso significa que o ciclo de gerar, revisar, direcionar e gerar novamente continua sendo o fluxo normal. Quanto mais aberta e ambígua a tarefa, maior a chance do modelo produzir algo diferente do esperado. A participação humana no direcionamento segue sendo importante para reduzir esse ciclo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analogia com VMs e otimização prematura
&lt;/h2&gt;

&lt;p&gt;Uma maneira útil de pensar sobre isso é a analogia com máquinas virtuais. A JVM, por exemplo, faz otimizações sofisticadas em runtime. Na maioria dos casos, tentar micro-otimizar manualmente sem dados concretos pode até atrapalhar o trabalho da VM.&lt;/p&gt;

&lt;p&gt;Com agentes de código pode estar acontecendo algo parecido. Em algum momento, tentar ajustar finamente o comportamento do agente com muitas regras e configurações pode ser contra-produtivo. Para a maioria das tarefas, apostar no comportamento padrão do modelo e iterar a partir do resultado pode ser mais eficiente do que montar um setup elaborado antes de começar.&lt;/p&gt;

&lt;p&gt;Quando você tem dados concretos de que um ajuste específico faz diferença no seu contexto, aí sim vale configurar. Mas sem essa evidência, o default tende a funcionar razoavelmente bem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;O SkillBench traz dados úteis para calibrar expectativas. Skills escritas com participação de quem domina o assunto fazem diferença mensurável. Skills auto-geradas pelo agente praticamente não ajudam. A taxa de falha dos modelos ainda é alta mesmo em tarefas padronizadas, o que reforça que o direcionamento humano continua sendo parte essencial do fluxo.&lt;/p&gt;

&lt;p&gt;Para quem trabalha com agentes de código no dia a dia, o ponto prático é: invista seu tempo no que você sabe sobre o problema, não na engenharia de contexto genérica. O conhecimento de domínio que você traz para a skill é o que faz a diferença, não a sofisticação do setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dev + Eficiente
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Desenvolva software de alta qualidade e domine Engenharia de IA com o Dev + Eficiente.&lt;/strong&gt; Cursos práticos, acesso vitalício, comunidade ativa e acesso a vagas remotas exclusivas em diversas empresas de tecnologia. Sua jornada para se tornar um dev mais eficiente pode começar agora.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>coding</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Estudo da Anthropic sobre IA e aprendizagem: o modo de uso importa mais do que a ferramenta</title>
      <dc:creator>Alberto Luiz Souza</dc:creator>
      <pubDate>Mon, 16 Mar 2026 12:14:54 +0000</pubDate>
      <link>https://dev.to/asouza/estudo-da-anthropic-sobre-ia-e-aprendizagem-o-modo-de-uso-importa-mais-do-que-a-ferramenta-14ib</link>
      <guid>https://dev.to/asouza/estudo-da-anthropic-sobre-ia-e-aprendizagem-o-modo-de-uso-importa-mais-do-que-a-ferramenta-14ib</guid>
      <description>&lt;p&gt;Este texto foi inicialmente concebido pelo Agente Marketing Dev + Eficiente em função da transcrição de um vídeo do canal Dev Eficiente. Se preferir acompanhar por vídeo, é só dar o play.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/JeBve1kvpRU"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;A Anthropic publicou um estudo chamado "How AI Impacts Skill Formation". O experimento colocou pessoas para implementar funcionalidades usando uma biblioteca Python, dividindo-as em dois grupos: um com acesso a assistentes baseados em LLM e outro sem. Depois, aplicaram um quiz sobre os conhecimentos adquiridos durante a tarefa. O grupo que não usou IA tirou notas melhores.&lt;/p&gt;

&lt;p&gt;O resultado gerou bastante repercussão -- posts no LinkedIn dizendo que IA "emburrece" e alertas sobre o futuro da profissão. Mas quando olhamos os dados com mais cuidado, a história é mais nuançada do que o título sugere.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que o estudo de fato mostra
&lt;/h2&gt;

&lt;p&gt;O experimento usou uma biblioteca Python chamada Trio, que permite operações assíncronas com composição de tarefas. Os participantes tinham 35 minutos para completar a implementação.&lt;/p&gt;

&lt;p&gt;Dois resultados chamam atenção:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sobre produtividade:&lt;/strong&gt; a diferença de tempo entre quem usou IA e quem não usou não foi tão expressiva quanto se poderia imaginar. A pessoa mais rápida com IA completou em aproximadamente 18 minutos, enquanto a mais rápida sem IA demorou cerca de 21. Para essa tarefa específica, o ganho de produtividade não foi marcante.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sobre aprendizado:&lt;/strong&gt; aqui a diferença foi significativa. A pior nota de quem não usou IA foi melhor do que a melhor nota de quem usou. Quem não teve a opção de delegar precisou ler a documentação, entender os conceitos e resolver os problemas por conta própria -- e esse esforço se refletiu no quiz.&lt;/p&gt;

&lt;h2&gt;
  
  
  Os padrões de uso que explicam a diferença
&lt;/h2&gt;

&lt;p&gt;O estudo identificou diferentes padrões de interação com a IA, e nem todos levaram ao mesmo resultado:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delegação total:&lt;/strong&gt; a pessoa simplesmente pediu para a IA resolver e colou o resultado. Completou rápido (cerca de 19 minutos), mas ficou com média de 39% no quiz. É o padrão mais intuitivo quando o objetivo é apenas terminar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delegação do debugging:&lt;/strong&gt; quando apareceu um bug, a pessoa delegou a resolução completa para a IA. Esse foi o pior cenário -- demorou mais para terminar e ainda resultou em notas baixas. A oportunidade de entender o que deu errado, e se prevenir na próxima vez, se perdeu.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Geração seguida de compreensão:&lt;/strong&gt; a pessoa usou a IA para gerar o código, mas depois leu e tentou entender o que foi produzido. Esse grupo demorou um pouco mais, mas tirou notas na casa dos 60% -- não tão boas quanto quem não usou IA, mas com um trade-off possivelmente aceitável entre velocidade e aprendizado.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que isso significa na prática
&lt;/h2&gt;

&lt;p&gt;O estudo é honesto sobre suas limitações. As tarefas do experimento são isoladas e curtas, bem diferentes de tarefas reais de desenvolvimento, onde existe contexto acumulado, interação com outras equipes, análise de código existente e decisões arquiteturais.&lt;/p&gt;

&lt;p&gt;Um exemplo prático: ao precisar salvar currículos em um bucket da Cloudflare usando o R2, é perfeitamente razoável pedir para um agente gerar o código de integração. Se alguém perguntar depois como a API do R2 funciona em detalhe, a resposta honesta pode ser "não sei de cabeça". Isso não diz nada sobre a capacidade da pessoa como engenheira -- é um componente pontual, mapeado, que pode ser consultado quando necessário.&lt;/p&gt;

&lt;p&gt;Agora, o estudo evidencia algo que vale a atenção: quando a prioridade é só terminar, o impulso natural é parar de refletir. E falta de reflexão afeta o entendimento, a capacidade de pensar em alternativas e de se preparar para problemas futuros.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sensação de produtividade versus produtividade real
&lt;/h2&gt;

&lt;p&gt;Escrever mais código não significa produzir mais valor. Se alguém fala mil palavras por minuto e outra pessoa fala trezentas, isso não diz nada sobre a qualidade do que foi dito.&lt;/p&gt;

&lt;p&gt;Com ferramentas de IA, é fácil colocar mais tarefas no pipeline simplesmente porque agora é possível gerar mais código. Mas o número de tarefas entregues que de fato geram valor pode não ter mudado.&lt;/p&gt;

&lt;p&gt;Existem cenários onde o ganho de produtividade é óbvio e não faz sentido questionar: quando a pessoa não sabia fazer aquilo antes. Se alguém que nunca escreveu Swift consegue entregar uma funcionalidade com ajuda de IA, é claro que ficou "mais produtiva" -- antes não fazia nada.&lt;/p&gt;

&lt;p&gt;O cenário que ainda carece de evidências mais robustas é quando a pessoa já sabe fazer o trabalho, delega para a IA e depois confere o resultado. Estudos mais longitudinais seriam necessários para entender o impacto real nessa situação.&lt;/p&gt;

&lt;h2&gt;
  
  
  O papel de quem usa o agente
&lt;/h2&gt;

&lt;p&gt;Enquanto não existirem agentes operando sem humanos no loop, a responsabilidade pelo resultado é de quem abre o PR. Se o agente entregou algo, você aprovou, e depois não consegue explicar o que aquele código faz, o problema é seu.&lt;/p&gt;

&lt;p&gt;Usar ferramentas de IA para estudar e trabalhar faz sentido -- é uma tecnologia que fornece feedback como se houvesse alguém acompanhando o que você está fazendo. Mas o modo de uso importa. Gerar e entender é diferente de gerar e ignorar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;O estudo da Anthropic não traz uma revelação surpreendente: menos reflexão leva a menos entendimento. Mas quantifica isso de forma controlada e identifica padrões de uso que podem orientar como cada pessoa decide interagir com ferramentas de IA no dia a dia.&lt;/p&gt;

&lt;p&gt;A decisão prática é sobre quando vale abrir mão de entendimento profundo (componentes pontuais, integrações que não são o core do sistema) e quando vale investir o tempo de compreender o que foi gerado (lógica de negócio, componentes críticos, áreas onde um bug futuro pode puxar seu pé).&lt;/p&gt;

&lt;h2&gt;
  
  
  Dev + Eficiente
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Desenvolva software de alta qualidade e domine Engenharia de IA com o Dev + Eficiente.&lt;/strong&gt; Cursos práticos, acesso vitalício, comunidade ativa e acesso a vagas remotas exclusivas em diversas empresas de tecnologia. Sua jornada para se tornar um dev mais eficiente pode começar agora.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>learning</category>
      <category>programming</category>
    </item>
    <item>
      <title>Como o RAG está sendo usado na indústria de software: o que dizem 26 estudos</title>
      <dc:creator>Alberto Luiz Souza</dc:creator>
      <pubDate>Mon, 09 Mar 2026 11:49:23 +0000</pubDate>
      <link>https://dev.to/asouza/como-o-rag-esta-sendo-usado-na-industria-de-software-o-que-dizem-26-estudos-1ee3</link>
      <guid>https://dev.to/asouza/como-o-rag-esta-sendo-usado-na-industria-de-software-o-que-dizem-26-estudos-1ee3</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Este texto foi gerado pelo Agente Marketing Dev + Eficiente a partir de um relatório técnico de revisão sistemática sobre RAG na Engenharia de Software, conduzido com análise assistida por IA. O conteúdo abaixo sintetiza as principais evidências encontradas na literatura e em relatos industriais.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;RAG (Retrieval-Augmented Generation) combina mecanismos de recuperação de informação com modelos generativos. Na prática, o sistema consulta bases de conhecimento externas -- documentação técnica, logs operacionais, código-fonte, histórico de incidentes -- antes de produzir uma resposta. O modelo passa a fundamentar suas saídas em evidências recuperadas, reduzindo alucinações e aumentando a precisão.&lt;/p&gt;

&lt;p&gt;Uma revisão sistemática recente analisou 26 estudos (entre 2021 e 2025) para entender como o RAG está sendo aplicado na indústria de software. Os resultados mostram que a tecnologia já ultrapassou o estágio experimental e está presente em ambientes de produção em diversos setores.&lt;/p&gt;

&lt;h2&gt;
  
  
  Onde o RAG está sendo usado
&lt;/h2&gt;

&lt;p&gt;A distribuição por indústria revela três padrões:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Estudos transversais dominam.&lt;/strong&gt; A maior parte dos trabalhos (7 estudos) discute arquiteturas, técnicas e desafios de forma independente do domínio. Isso indica que a comunidade está consolidando padrões de engenharia de RAG que podem ser aplicados em diferentes contextos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cloud/DevOps e empresas de tecnologia concentram as aplicações mais maduras.&lt;/strong&gt; Computação em nuvem e tecnologia da internet aparecem com 2 estudos cada, com foco em observabilidade, detecção de anomalias em logs e revisão automática de código. São cenários onde documentação operacional, logs e conhecimento histórico estão naturalmente dispersos -- exatamente o tipo de problema que o RAG resolve.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Segurança e testes estão crescendo.&lt;/strong&gt; A necessidade de rastreabilidade, redução de alucinação e reutilização de conhecimento histórico torna o RAG atrativo para detecção de vulnerabilidades e automação de artefatos de teste.&lt;/p&gt;

&lt;p&gt;Além desses, o RAG aparece em setores como automotiva, telecomunicações, construção naval, energia e PMEs, demonstrando versatilidade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Em quais etapas do desenvolvimento
&lt;/h2&gt;

&lt;p&gt;A etapa de desenvolvimento e testes concentra a maior parte das evidências (14 dos 26 estudos). Dentro dela, o RAG é usado para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complemento de código em repositórios fechados&lt;/strong&gt;, como no caso do WeChat, onde o modelo recebe contexto do repositório interno antes de sugerir complementos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revisão automática de código&lt;/strong&gt;, fornecendo contexto de chamadas entre arquivos para gerar comentários mais relevantes e reduzir sugestões inválidas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Geração de testes&lt;/strong&gt;, incluindo scripts de teste de integração na indústria automotiva e automação de casos de teste em sistemas ERP com orquestração multiagente&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operacionalização do RAG em produção&lt;/strong&gt;, incluindo governança, trade-offs de latência versus qualidade e avaliação contínua&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fora de desenvolvimento e testes, o RAG aparece em resolução de incidentes (redução de MTTR com troubleshooting baseado em evidências), CI/CD (diagnóstico de falhas em pipelines) e cibersegurança (detecção de vulnerabilidades ancorada em bases como CWE/MITRE).&lt;/p&gt;

&lt;h2&gt;
  
  
  Quais LLMs estão sendo usadas
&lt;/h2&gt;

&lt;p&gt;A escolha do modelo depende do contexto:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Família GPT&lt;/strong&gt; aparece com maior frequência, por maturidade de ecossistema e capacidade de seguir instruções ancoradas em evidências. É a escolha predominante em sistemas de gestão do conhecimento e diagnóstico de incidentes em tempo real.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Família LLaMA&lt;/strong&gt; se destaca quando a prioridade é implantação on-premises, custo e governança. O caso da Ericsson é ilustrativo: um chatbot RAG para CI/CD usando Llama2-chat, onde até o custo de trocar de LLM por diferenças de estilo de prompt foi avaliado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Família Qwen&lt;/strong&gt; aparece associada a operações de nuvem, equilibrando capacidade e custo. Também é usada em indústria tradicional (construção naval), indicando que modelos open-weight entram como escolha por viabilidade.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Modelos especializados em código&lt;/strong&gt; (CodeLlama, DeepSeek-Coder, Yi-Coder, Codestral) competem com modelos gerais quando o domínio é programação. Vários estudos comparam múltiplos modelos para equilibrar custo e desempenho.&lt;/p&gt;

&lt;h2&gt;
  
  
  Embeddings: o que a indústria está escolhendo
&lt;/h2&gt;

&lt;p&gt;A família BGE (BAAI) foi a mais recorrente. Aparece em cenários que exigem alta precisão de recuperação, frequentemente combinada com rerankers para refinar os resultados antes de enviar ao LLM.&lt;/p&gt;

&lt;p&gt;Sentence-Transformers (all-MiniLM-L6-v2, all-distilroberta-v1) aparecem como opção pragmática para implantação rápida e pipelines leves.&lt;/p&gt;

&lt;p&gt;Embeddings da OpenAI (text-embedding-3-large) são usados quando o pipeline já está acoplado ao ecossistema OpenAI.&lt;/p&gt;

&lt;p&gt;Para código, embeddings especializados como CodeBERT e UniXcoder tendem a superar embeddings genéricos em tarefas de similaridade de código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arquiteturas que estão emergindo
&lt;/h2&gt;

&lt;p&gt;Além do pipeline RAG clássico (ingestão, chunking, vetorização, recuperação, geração), a revisão identificou padrões arquiteturais mais sofisticados:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RAG híbrido (lexical + semântico).&lt;/strong&gt; A combinação de BM25 com recuperação semântica aparece consistentemente como a configuração mais efetiva. Reciprocal Rank Fusion (RRF) é uma técnica recorrente para fundir os sinais.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recuperação em dois estágios (Retrieve + Rerank).&lt;/strong&gt; Primeiro recupera um conjunto maior com alta revocação, depois aplica um reranker (tipicamente cross-encoder) para alta precisão. Esse padrão aparece em múltiplos estudos industriais.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RAG guiado por intenção.&lt;/strong&gt; Classificação da consulta do usuário, extração de metadados e reescrita de query antes da recuperação. Resolve o problema de consultas incompletas ou ambíguas em ambientes operacionais.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RAG com grafos e Agentic RAG.&lt;/strong&gt; Para tarefas com dependências estruturais (chamadas entre arquivos, rastreabilidade), a combinação de banco vetorial com banco em grafo e orquestração multiagente. Alguns estudos já incorporam aprendizado por reforço para melhoria contínua baseada em feedback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RAG com base de conhecimento dinâmica.&lt;/strong&gt; A base de conhecimento evolui via active learning: logs com baixa incerteza são incorporados automaticamente, casos incertos vão para rotulagem humana. Adequado para cenários onde os dados mudam rapidamente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;As evidências indicam que o RAG já é uma tecnologia em uso industrial, não apenas experimental. Seu principal valor está em permitir que LLMs utilizem conhecimento corporativo -- documentação, código, histórico de incidentes -- fundamentando respostas em evidências concretas.&lt;/p&gt;

&lt;p&gt;A eficácia depende menos do modelo de linguagem escolhido e mais da qualidade do pipeline de recuperação: estratégia de chunking, escolha de embeddings, mecanismos de reranking e integração com os fluxos de trabalho existentes. Quem está implementando RAG em produção precisa tratar o pipeline de recuperação com o mesmo rigor que trata qualquer outro componente crítico do sistema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Artigo completo
&lt;/h2&gt;

&lt;p&gt;O artigo completo pode ser lido &lt;a href="https://docs.google.com/document/d/1QA8NvQJpYMoErQqfAeRz8xqUm5earc2n/edit?usp=drive_link&amp;amp;ouid=101139135933113985213&amp;amp;rtpof=true&amp;amp;sd=true" rel="noopener noreferrer"&gt;aqui&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Especialização em Engenharia de IA
&lt;/h2&gt;

&lt;p&gt;Na Especialização em Engenharia de IA, uma parceria com a Dev + Eficiente, abordamos RAG na prática: desde a construção do pipeline de recuperação até estratégias de avaliação e operacionalização em produção. O curso inclui Vector Search, Busca Híbrida, Agentes, Tools e muito mais, sempre com aulas 100% práticas.&lt;/p&gt;

&lt;p&gt;Faça sua inscrição em &lt;a href="https://deveficiente.com/especializacao-engenharia-ia" rel="noopener noreferrer"&gt;https://deveficiente.com/especializacao-engenharia-ia&lt;/a&gt; .&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>rag</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>CDD: como tornar a avaliação de complexidade de código mensurável</title>
      <dc:creator>Alberto Luiz Souza</dc:creator>
      <pubDate>Tue, 03 Mar 2026 12:43:47 +0000</pubDate>
      <link>https://dev.to/asouza/cdd-como-tornar-a-avaliacao-de-complexidade-de-codigo-mensuravel-1gj8</link>
      <guid>https://dev.to/asouza/cdd-como-tornar-a-avaliacao-de-complexidade-de-codigo-mensuravel-1gj8</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Este texto foi inicialmente concebido por um Agente Dev + Eficiente especializado nos conteúdos da Jornada e foi revisado por Alberto&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Uma classe que começa com 40 linhas e termina o ano com 400. Acontece em praticamente todo projeto. O problema não é a classe ter crescido. É que ninguém percebeu quando ela começou a ficar difícil de entender.&lt;/p&gt;

&lt;p&gt;Não existe um ponto de ruptura claro -- ela vai acumulando responsabilidades, condicionais e dependências até que qualquer alteração começa a pesar muito mais do que deveria. E aí você tem um time inteiro olhando para o mesmo arquivo e cada pessoa avaliando a dificuldade de um jeito diferente.&lt;/p&gt;

&lt;p&gt;A maioria das práticas que tentam resolver isso são baseadas em princípios qualitativos. "Responsabilidade única", "código limpo", "baixo acoplamento". Importantes, mas difíceis de aplicar de forma consistente entre pessoas diferentes de um mesmo time. O que é "responsabilidade única" para uma pessoa pode não ser para outra.&lt;/p&gt;

&lt;p&gt;O Cognitive Driven Development (CDD) parte de uma premissa diferente: é possível tornar a avaliação de complexidade de código algo mensurável e compartilhado. &lt;/p&gt;

&lt;p&gt;Para não causar confusão: não estamos falando de sustituição de práticas e sim de trazer uma prática que pode facilitar o uso das outras. &lt;/p&gt;

&lt;h2&gt;
  
  
  O fundamento: carga cognitiva aplicada a código
&lt;/h2&gt;

&lt;p&gt;A teoria da carga cognitiva vem da psicologia educacional. A ideia central é que seres humanos possuem um limite restrito de capacidade de absorção de informação em um determinado intervalo de tempo. Uma referência clássica é o trabalho de Miller (1956), que estabelece que uma pessoa consegue manter aproximadamente 7 itens simultâneos na mente.&lt;/p&gt;

&lt;p&gt;O insight do CDD é tratar código como material de consumo cognitivo -- assim como um slide, uma apostila ou um vídeo. Se existe um limite para o que uma pessoa consegue processar, então faz sentido que unidades de código também respeitem esse limite.&lt;/p&gt;

&lt;p&gt;A partir daí, o CDD sugere que a complexidade de uma unidade de código (um arquivo, por exemplo) tenha um limite definido. Passou deste limite? A complexidade está maior do que queremos, precisamos ajustar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como funciona na prática
&lt;/h2&gt;

&lt;p&gt;O processo é direto. A equipe decide quais elementos de código ela julga que mais pesam na mente das pessoas. Não existe resposta certa -- isso varia de time para time e de projeto para projeto.&lt;/p&gt;

&lt;p&gt;Por exemplo, em um projeto com Java, a equipe pode definir (apenas um exemplo) os seguintes elementos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Condicionais&lt;/li&gt;
&lt;li&gt;Acoplamentos com classes do projeto&lt;/li&gt;
&lt;li&gt;Funções como argumento&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cada elemento desse, dentro do CDD, é chamado de Intrinsic Complex Point (ICP). Num projeto usando Clojure, os elementos vão mudar. Num projeto usando Python, podem mudar de novo. A teoria é agnóstica de linguagem -- o que muda é quais construções da linguagem a equipe considera relevantes para o entendimento.&lt;/p&gt;

&lt;p&gt;Pode-se definir que cada elemento contabiliza um ponto e, a partir disso, já fica bem mais fácil avaliar a complexidade. Supondo que o limite é 10, basta contar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que isso funciona melhor do que princípios qualitativos
&lt;/h2&gt;

&lt;p&gt;Três ganhos práticos:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Uniformidade de avaliação.&lt;/strong&gt; Quando todo mundo conta os mesmos elementos e usa o mesmo limite, a discussão sobre complexidade sai do campo não determinístico e vai para o campo determinístico. Pessoas com níveis de experiência diferentes passam a analisar complexidade sob a mesma ótica.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automação.&lt;/strong&gt; Algo que se resume a contar elementos e comparar com um limite é completamente entendível por um programa. Isso pode entrar no CI, num linter, ou até ser delegado a um LLM (aceitando as variações nas respostas). Não depende de julgamento humano subjetivo no momento da verificação.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adaptabilidade.&lt;/strong&gt; Nada é fixo. A equipe, depois de iterar, pode querer trocar os ICPs, aumentar o limite, reduzir. A métrica evolui junto com o contexto do time. Se os acoplamentos com classes do projeto pararam de ser um problema porque todo mundo já domina, a equipe pode remover esse item e adicionar outro que passe a ser mais relevante.&lt;/p&gt;

&lt;h2&gt;
  
  
  O experimento
&lt;/h2&gt;

&lt;p&gt;Já há alguns anos, foi feito um experimento com mais de 20 pessoas, comparando refatoração convencional com refatoração guiada pelo CDD. O grupo que usou a métrica chegou a resultados mais uniformes e com complexidade menor -- independente do nível de experiência de quem refatorou.&lt;/p&gt;

&lt;p&gt;O ponto mais interessante: pessoas menos experientes entregaram código menos complexo do que pessoas mais experientes que refatoraram sem a métrica. Quando existe um limite claro e uma forma objetiva de medir, a experiência deixa de ser o único fator determinante para a qualidade do resultado. Métodos bons fazem diferença para diminuir diferenças de experiência. &lt;/p&gt;

&lt;h2&gt;
  
  
  O que muda no dia a dia
&lt;/h2&gt;

&lt;p&gt;Na prática, adotar o CDD significa que o code review ganha um critério a mais -- e um critério que não depende de quem está revisando. Se o arquivo passou do limite, precisa ser dividido. Se não passou, está dentro do aceitável.&lt;/p&gt;

&lt;p&gt;Isso não substitui a análise qualitativa. Você ainda vai discutir naming, coesão, decisões de design. Mas a questão "esse arquivo está complexo demais?" deixa de ser uma discussão sem fim.&lt;/p&gt;

&lt;p&gt;Para projetos novos, a sugestão é começar com um limite mais restritivo e ajustar conforme a equipe ganha experiência com a métrica. Para projetos existentes, o caminho é contabilizar primeiro e aplicar o limite apenas para código novo -- sem sair refatorando tudo de uma vez.&lt;/p&gt;

&lt;h2&gt;
  
  
  CDD dentro da Jornada Dev + Eficiente
&lt;/h2&gt;

&lt;p&gt;CDD é um dos mais de 20 cursos da Jornada Dev + Eficiente. E não é um curso isolado: o controle de complexidade de código se conecta diretamente com os cursos de design de código, engenharia de requisitos e DDD. A complexidade do código que você escreve é consequência de como você refinou o requisito, modelou o domínio e organizou as responsabilidades.&lt;/p&gt;

&lt;p&gt;A Jornada cobre de controle de complexidade de código até operação de sistemas em produção. Acesso vitalício, todas as perguntas respondidas pelos instrutores e comunidade no Discord.&lt;/p&gt;

&lt;p&gt;Acesse &lt;a href="https://deveficiente.com/oferta-10-por-cento" rel="noopener noreferrer"&gt;https://deveficiente.com/oferta-10-por-cento&lt;/a&gt; para conhecer tudo que oferecemos.&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>programming</category>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>O que acontece dentro do pipeline da sua aplicação LLM?</title>
      <dc:creator>Alberto Luiz Souza</dc:creator>
      <pubDate>Mon, 23 Feb 2026 00:07:42 +0000</pubDate>
      <link>https://dev.to/asouza/o-que-acontece-dentro-do-pipeline-da-sua-aplicacao-llm-12k4</link>
      <guid>https://dev.to/asouza/o-que-acontece-dentro-do-pipeline-da-sua-aplicacao-llm-12k4</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Este texto foi inicialmente concebido pela IA Generativa em função da transcrição de um vídeo do canal de Daniel Romero (a pessoa que lidera nossa Especialização em Engenharia de IA). Se preferir acompanhar por vídeo, é só dar o play.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/k6cTB2ltvTg"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Quando colocamos uma aplicação LLM em produção, entender o que está acontecendo internamente deixa de ser opcional. Qual prompt foi montado? Quantos tokens foram consumidos? Onde exatamente uma chamada falhou? LangSmith é uma plataforma de observabilidade do ecossistema LangChain projetada para responder essas perguntas em todos os estágios do ciclo de vida de uma aplicação LLM, da prototipagem à produção.&lt;/p&gt;

&lt;p&gt;Um ponto relevante: apesar de fazer parte do ecossistema LangChain, o LangSmith funciona de maneira independente. Isso significa que você pode monitorar chains e agentes desenvolvidos com qualquer framework, incluindo DSPy, LlamaIndex, CrewAI, LangGraph e outros.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuração inicial
&lt;/h2&gt;

&lt;p&gt;Para começar a utilizar o LangSmith, o processo é direto. Você cria uma conta em smith.langchain.com e, uma vez logado, tem acesso às principais seções da plataforma:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Projetos&lt;/strong&gt;: coleções de rastreamento organizadas por aplicação&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Annotations&lt;/strong&gt;: para anotar e revisar execuções&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Playground&lt;/strong&gt;: ambiente para testes rápidos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Datasets&lt;/strong&gt;: conjuntos de dados para avaliação de qualidade&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hub&lt;/strong&gt;: funciona como um repositório compartilhado de prompts, ferramentas e chains, similar ao Docker Hub&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A configuração no código também é simples. Você gera uma chave de API nas configurações da plataforma e define algumas variáveis de ambiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LANGCHAIN_TRACING_V2=true
LANGCHAIN_ENDPOINT=https://api.smith.langchain.com
LANGCHAIN_PROJECT=default
LANGSMITH_API_KEY=sua-chave-aqui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com essas variáveis configuradas, toda a telemetria da sua aplicação é enviada automaticamente para o LangSmith. Se você já utiliza o LangChain, não precisa instalar nenhuma biblioteca adicional. O suporte ao LangSmith já vem embutido no pacote.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo 1: Monitorando uma chain do LangChain
&lt;/h2&gt;

&lt;p&gt;No primeiro exemplo, temos uma chain simples que simula o comportamento de um RAG. Um system prompt orienta o assistente a responder com base apenas no contexto fornecido, e a pergunta do usuário recebe esse contexto como parâmetro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatOpenAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.prompts&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatPromptTemplate&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain_core.output_parsers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;StrOutputParser&lt;/span&gt;

&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ChatPromptTemplate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_messages&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Você é um assistente útil. Responda a solicitação do usuário com base apenas no contexto fornecido.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{question}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;Contexto: {context}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatOpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;StrOutputParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Resuma o texto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;context&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;texto&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ao executar essa chain, o LangSmith captura automaticamente todo o fluxo. No painel da plataforma, podemos ver:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RunnableSequence&lt;/strong&gt;: um resumo completo da execução, com todo o input enviado ao LLM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ChatOpenAI&lt;/strong&gt;: detalhes do modelo utilizado, parâmetros como temperatura (0.7 por padrão, quando não configurada explicitamente), provider e nome do modelo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metadata&lt;/strong&gt;: versão do LangChain, sistema operacional de origem, versão do Python e outros dados de contexto&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Na lateral, o LangSmith exibe informações operacionais importantes: timestamp, latência da chamada, quantidade de tokens consumidos e um cálculo estimado de custo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rastreamento por etapas
&lt;/h3&gt;

&lt;p&gt;Um dos recursos mais úteis é a visualização passo a passo de cada etapa da execução. Você consegue acompanhar desde a montagem do prompt com o ChatPromptTemplate, passando pelo envio para a OpenAI, até o retorno formatado pelo StrOutputParser. Cada etapa aparece separada, o que facilita a identificação de gargalos ou comportamentos inesperados.&lt;/p&gt;

&lt;h3&gt;
  
  
  Captura de erros
&lt;/h3&gt;

&lt;p&gt;Para demonstrar a captura de erros, basta trocar o modelo para um que não existe, como "gpt-5". O LangSmith registra o erro e permite investigar exatamente em qual etapa a execução falhou. Nesse caso, o ChatPromptTemplate foi montado corretamente, mas a chamada para a OpenAI retornou um erro informando que o modelo não foi encontrado. A mensagem aparece de forma clara e direta no painel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo 2: Monitorando aplicações sem LangChain
&lt;/h2&gt;

&lt;p&gt;E se a sua aplicação LLM não utiliza o LangChain? O LangSmith também funciona nesse cenário, com algumas configurações adicionais.&lt;/p&gt;

&lt;p&gt;No segundo exemplo, temos uma aplicação que usa diretamente o client da OpenAI, com uma função Retriever que simula a recuperação de contexto de um banco vetorial. Para habilitar o rastreamento, são necessários dois passos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Passo 1: Wrapper do client OpenAI
&lt;/h3&gt;

&lt;p&gt;O LangSmith oferece um wrapper para o client da OpenAI que habilita a coleta de métricas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langsmith.wrappers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;wrap_openai&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wrap_openai&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com essa configuração, o LangSmith passa a rastrear as chamadas ao ChatOpenAI. Porém, como não há as abstrações do LangChain, o rastreamento mostra apenas a chamada ao LLM como um bloco único.&lt;/p&gt;

&lt;h3&gt;
  
  
  Passo 2: Rastreamento granular com @traceable
&lt;/h3&gt;

&lt;p&gt;Para obter mais detalhes sobre o pipeline completo, o LangSmith fornece o decorator @traceable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langsmith&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;traceable&lt;/span&gt;

&lt;span class="nd"&gt;@traceable&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retriever&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Simula recuperação de contexto
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LangSmith serve para observabilidade&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="nd"&gt;@traceable&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;retriever&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o-mini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Responda com base no contexto: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com o @traceable aplicado nas funções, o LangSmith passa a rastrear cada etapa individualmente. No painel, a execução aparece hierarquicamente: a função RAG contém a chamada ao Retriever e, dentro dela, a chamada ao ChatOpenAI. A progressão fica visível: primeiro apenas o ChatOpenAI, depois a função RAG com o ChatOpenAI dentro, e por fim a cadeia completa com Retriever e ChatOpenAI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoramento e métricas
&lt;/h2&gt;

&lt;p&gt;Em projetos com maior volume de execuções, a seção Monitor do LangSmith oferece gráficos com métricas operacionais:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contagem de erros&lt;/li&gt;
&lt;li&gt;Quantidade de chamadas ao LLM&lt;/li&gt;
&lt;li&gt;Taxa de sucesso nas chamadas&lt;/li&gt;
&lt;li&gt;Métricas de latência (p50, p95)&lt;/li&gt;
&lt;li&gt;Tokens por segundo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essas métricas ajudam a acompanhar a saúde da aplicação em produção e identificar degradações de performance ao longo do tempo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avaliação de qualidade com datasets
&lt;/h2&gt;

&lt;p&gt;Além do monitoramento em tempo real, o LangSmith oferece recursos para avaliar a qualidade das respostas geradas pela sua aplicação. O fluxo funciona assim:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Você cria um dataset com pares de perguntas e respostas esperadas&lt;/li&gt;
&lt;li&gt;Carrega o dataset na plataforma&lt;/li&gt;
&lt;li&gt;Executa a avaliação contra diferentes versões da aplicação ou diferentes modelos&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No exemplo apresentado, uma comparação entre GPT-4o Mini e GPT-3.5 Turbo mostra diferenças de verbosidade, consumo de tokens, latência e custo. É possível definir um baseline e comparar o desempenho de cada modelo contra ele. Na prática, isso permite implementar testes A/B entre versões da aplicação ou entre modelos diferentes, com dados concretos para embasar a decisão.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;LangSmith resolve um problema prático de quem desenvolve aplicações LLM: saber o que está acontecendo dentro do pipeline. A configuração é simples, funciona com ou sem LangChain, e oferece desde rastreamento básico de chamadas até avaliação comparativa de modelos. Para quem está colocando aplicações LLM em produção, ter esse nível de visibilidade sobre o comportamento do sistema pode ser a diferença entre resolver um problema em minutos ou passar horas investigando logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Especialização em Engenharia de IA
&lt;/h2&gt;

&lt;p&gt;Conheça a Especialização em Engenharia de IA Dev + Eficiente. O curso aborda RAG, Vector Search, Busca Híbrida, Agentes, Tools e muito mais, sempre com aulas 100% práticas e com exemplos reais.&lt;/p&gt;

&lt;p&gt;Acesse &lt;a href="https://deveficiente.com/especializacao-engenharia-ia" rel="noopener noreferrer"&gt;https://deveficiente.com/especializacao-engenharia-ia&lt;/a&gt; .&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>monitoring</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Como expor sua API REST para um agente de código sem criar servidor MCP</title>
      <dc:creator>Alberto Luiz Souza</dc:creator>
      <pubDate>Mon, 16 Feb 2026 11:48:37 +0000</pubDate>
      <link>https://dev.to/asouza/como-expor-sua-api-rest-para-um-agente-de-codigo-sem-criar-servidor-mcp-1jd</link>
      <guid>https://dev.to/asouza/como-expor-sua-api-rest-para-um-agente-de-codigo-sem-criar-servidor-mcp-1jd</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Este texto foi inicialmente concebido pela IA Generativa em função da transcrição de um vídeo do Dev Eficiente. Se preferir acompanhar por vídeo, é só dar o play.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/bkHrzb7rC4E"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Servidores MCP se tornaram a maneira padronizada de expor APIs e funcionalidades para agentes de código como Claude Code, Cursor, Codex e outros. Mas existe uma discussão relevante no mercado sobre a complexidade que eles trazem. No fundo, em muitos casos, você está criando um wrapper da sua API que já existe para expor ela para o agente. E se existisse uma alternativa mais leve, que não exigisse criar um servidor novo em cima de algo que já funciona?&lt;/p&gt;

&lt;p&gt;Neste post, mostro como usei a funcionalidade de Agent Skills do Claude Code para expor uma API REST existente para o agente, sem alterar nenhum código da API e sem construir um servidor MCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  O contexto: MCP, complexidade e alternativas
&lt;/h2&gt;

&lt;p&gt;Na Dev + Eficiente temos essa discussão internamente. Daniel Romero tem uma visão crítica de que o MCP nasceu inchado, trazendo complexidade desnecessária em cenários onde você já tem uma API funcionando. Do outro lado, existe o argumento de que o MCP é a maneira padrão de expor coisas para agentes, o que facilita a integração do ponto de vista de quem consome.&lt;/p&gt;

&lt;p&gt;Existem alternativas mais leves surgindo, como o UTCP (Universal Tool Calling Protocol). Mas o caminho que explorei aqui foi diferente: usar a funcionalidade de Skills do Claude Code como ponte entre o agente e a API REST existente.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que são Agent Skills
&lt;/h2&gt;

&lt;p&gt;Agent Skills é uma funcionalidade do Claude Code que permite carregar instruções e scripts localmente. A própria Anthropic posiciona as Skills como algo mais local, que direciona o agente e pode inclusive orientar o consumo de serviços expostos via MCP ou qualquer outra fonte.&lt;/p&gt;

&lt;p&gt;A estrutura é simples. Dentro da pasta &lt;code&gt;.claude/skills/&lt;/code&gt;, você cria uma pasta com a sua skill contendo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Um arquivo &lt;code&gt;skill.md&lt;/code&gt; com nome, descrição e documentação dos endpoints&lt;/li&gt;
&lt;li&gt;Scripts que o agente pode executar para consumir a API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se você já criou uma tool para integrar com um agente, vai reconhecer a semelhança: a skill tem um nome e uma descrição que o LLM carrega no contexto. Quando você faz um pedido, o agente verifica se existe uma skill que pode ajudar a resolver e, se houver, carrega e executa.&lt;/p&gt;

&lt;h2&gt;
  
  
  O experimento: Contrate um Dev Eficiente
&lt;/h2&gt;

&lt;p&gt;Para testar essa abordagem, usei a plataforma Contrate um Dev Eficiente, que conecta o mercado com as pessoas que estudam conosco. O objetivo era expor o módulo de analytics da plataforma para o Claude Code sem mexer em nada no código existente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Estrutura do arquivo de skill
&lt;/h3&gt;

&lt;p&gt;O arquivo &lt;code&gt;skill.md&lt;/code&gt; segue um formato sugerido pela Anthropic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Nome: analytics-contrate-dev-eficiente
Descrição: Fornece acesso aos endpoints de analytics...

Autenticação:
&lt;span class="p"&gt;-&lt;/span&gt; Token deve ser configurado
&lt;span class="p"&gt;-&lt;/span&gt; Header de autenticação: Bearer {token}

Endpoints disponíveis:
&lt;span class="p"&gt;-&lt;/span&gt; /api/analytics - Análise geral (parâmetros: período)
&lt;span class="p"&gt;-&lt;/span&gt; /api/analytics/empresas - Contatos de empresas
&lt;span class="p"&gt;-&lt;/span&gt; /api/analytics/candidatos - Candidatos com currículo
&lt;span class="p"&gt;-&lt;/span&gt; /api/analytics/ranking - Rankings de vagas e empresas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Além da documentação dos endpoints, o arquivo referencia um bash script que o agente pode executar para consumir a API.&lt;/p&gt;

&lt;h3&gt;
  
  
  O bash script
&lt;/h3&gt;

&lt;p&gt;O script foi gerado pelo próprio Claude Code. Subi o agente no projeto do Contrate um Dev Eficiente, passei o link da documentação de Agent Skills da Anthropic, pedi para ele ler os endpoints do módulo de analytics e gerar tanto o arquivo de skill quanto o script de consumo autenticado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# Verifica token, faz a requisição autenticada e retorna o resultado&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O LLM carrega a skill, vê que existe um script referenciado, executa o script passando os parâmetros necessários (que estão documentados no arquivo de skill), recebe a resposta da API e trabalha em cima disso.&lt;/p&gt;

&lt;h2&gt;
  
  
  Na prática: como funcionou
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Consultas simples
&lt;/h3&gt;

&lt;p&gt;Ao pedir "quero listar as empresas cadastradas", o Claude Code identificou a skill de analytics, carregou, verificou o token de autenticação e executou a consulta. Quando passei um token expirado por engano, ele recebeu 403, tentou outro endpoint, recebeu 403 novamente e me pediu um novo token. Com o token correto, retornou os dados reais da plataforma.&lt;/p&gt;

&lt;h3&gt;
  
  
  Análise composta
&lt;/h3&gt;

&lt;p&gt;Ao pedir "quero uma análise geral", o agente decidiu por conta própria passar o parâmetro de período como seis meses. Consultou o endpoint, recebeu os dados e construiu uma análise com funil de conversão: empresas cadastradas, empresas com vagas, vagas com candidaturas, taxas de conversão e insights sobre a atividade da plataforma.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cruzamento entre endpoints
&lt;/h3&gt;

&lt;p&gt;Essa foi a parte mais interessante. Ao pedir "quero saber os nomes de pessoas que têm currículo e o perfil tech delas", o agente precisou combinar informações de endpoints diferentes. Primeiro consultou o endpoint que retorna currículos com perfil tech, depois identificou que não tinha os nomes, foi buscar no endpoint de candidatos com currículo e cruzou os dados.&lt;/p&gt;

&lt;h2&gt;
  
  
  A conexão com o nível 3 de maturidade REST
&lt;/h2&gt;

&lt;p&gt;Esse comportamento lembrou o modelo de maturidade REST de Richardson. No nível 3, o conceito de HATEOAS (Hypermedia as the Engine of Application State) propõe que o protocolo seja autodocumentado, com links que guiam o cliente sobre o que fazer em seguida.&lt;/p&gt;

&lt;p&gt;Na prática, poucos clientes HTTP implementam isso de verdade. Os clientes que construímos nas empresas são determinísticos: fazem chamadas pré-definidas, não seguem links dinamicamente. O navegador é o que mais se aproxima desse nível, por respeitar a semântica dos status codes e executar código que o servidor envia.&lt;/p&gt;

&lt;p&gt;Mas quando um LLM consome uma API documentada via skill, algo parecido acontece. Ele consulta um endpoint, percebe que a informação que precisa não está ali, identifica outro endpoint que pode complementar e faz a segunda chamada. Não é exatamente HATEOAS, mas é uma forma de navegação dinâmica entre endpoints que até então era muito difícil de implementar em clientes tradicionais.&lt;/p&gt;

&lt;p&gt;Uma pesquisa que fiz usando Deep Research do Claude encontrou um texto da Nord KPIs citando um arquiteto da Microsoft que argumenta que HATEOAS "chegou muito antes do que era possível, mas talvez agora seja mais possível". Concordo com essa visão.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vantagens dessa abordagem
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nenhuma alteração no código existente&lt;/strong&gt;: a API continua funcionando como antes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sem servidor novo para manter&lt;/strong&gt;: não é mais uma coisa para cuidar&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Localidade&lt;/strong&gt;: a skill é local, você expõe só o que quer, da partezinha que precisa&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibilidade&lt;/strong&gt;: você pode editar o arquivo de skill para o seu contexto, limitar endpoints, adicionar instruções específicas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replicável para qualquer API REST&lt;/strong&gt;: qualquer endpoint HTTP autenticado pode ser exposto dessa maneira&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Aplicações possíveis
&lt;/h2&gt;

&lt;p&gt;A mesma lógica se aplica a outros cenários. Se você tem um serviço de logs, métricas ou observabilidade com API HTTP, pode gerar um arquivo de skill e acessar tudo via terminal com um agente no momento de troubleshooting. Se quer consumir a API pública do GitHub sem instalar o servidor MCP do GitHub, pode criar uma skill que documente os endpoints que você precisa e um script de acesso autenticado.&lt;/p&gt;

&lt;p&gt;O repositório público de skills do Claude Code no GitHub já tem exemplos homologados pela Anthropic, como manipulação de PDF com scripts em Python, branding e outros. Servem como referência para construir as suas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Agent Skills do Claude Code oferecem uma alternativa pragmática para expor APIs REST para agentes de código. Não é uma substituição do MCP -- são coisas diferentes, para contextos diferentes. O MCP continua sendo o padrão para integração ampla e distribuída. Mas quando o que você precisa é algo local, leve, sem adicionar mais uma camada de infraestrutura sobre algo que já funciona, as Skills resolvem bem.&lt;/p&gt;

&lt;p&gt;O ponto central é: se você tem uma API REST funcionando, não precisa necessariamente criar um servidor MCP por cima dela. Um arquivo Markdown descrevendo os endpoints e um script de acesso podem ser suficientes para que o agente faça o trabalho.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dev + Eficiente
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Desenvolva software de alta qualidade e domine Engenharia de IA com o Dev + Eficiente.&lt;/strong&gt; Cursos práticos, acesso vitalício, comunidade ativa e acesso a vagas remotas exclusivas em diversas empresas de tecnologia. Sua jornada para se tornar um dev mais eficiente pode começar agora.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>api</category>
      <category>mcp</category>
    </item>
    <item>
      <title>Evidence Briefing – Monólito vs Microsserviços</title>
      <dc:creator>Alberto Luiz Souza</dc:creator>
      <pubDate>Mon, 09 Feb 2026 09:35:17 +0000</pubDate>
      <link>https://dev.to/asouza/evidence-briefing-monolito-vs-microsservicos-41k3</link>
      <guid>https://dev.to/asouza/evidence-briefing-monolito-vs-microsservicos-41k3</guid>
      <description>&lt;h2&gt;
  
  
  Monólito ou microsserviços: por onde começar?
&lt;/h2&gt;

&lt;p&gt;Decidir a arquitetura inicial de um sistema de software é uma das escolhas mais consequentes — e mais debatidas — no desenvolvimento de produtos digitais. Monólitos prometem simplicidade e velocidade; microsserviços prometem escala e autonomia. Mas em que contexto cada caminho faz mais sentido? Para ir além de opiniões e modismos, conduzimos uma revisão rápida de 23 estudos acadêmicos e aplicados, sintetizando evidências sobre vantagens, desvantagens e critérios de decisão de cada abordagem. O que encontramos reforça uma ideia central: não existe arquitetura universalmente superior — existe a arquitetura mais adequada ao problema, à equipe e ao momento do produto. Neste post, compartilhamos os principais achados e os trade-offs que toda equipe deveria considerar antes de tomar essa decisão.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1.Contexto&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A consolidação da Internet como principal meio de oferta de serviços digitais impulsionou o desenvolvimento de &lt;strong&gt;sistemas distribuídos&lt;/strong&gt;, capazes de atender grandes volumes de usuários, operar continuamente e evoluir de forma incremental. Nesse contexto, a arquitetura de software passou a exercer papel central na sustentação de atributos como escalabilidade, confiabilidade, desempenho e capacidade de evolução, tornando as decisões arquiteturais elementos estruturantes no ciclo de vida dos sistemas (BASS; CLEMENTS; KAZMAN, 2013).&lt;/p&gt;

&lt;p&gt;A decisão entre iniciar um sistema como &lt;strong&gt;monólito&lt;/strong&gt; ou como &lt;strong&gt;microsserviços&lt;/strong&gt; constitui uma das escolhas arquiteturais mais críticas no desenvolvimento de software, podendo influenciar atributos não funcionais relevantes, como escalabilidade, confiabilidade e custo de manutenção ao longo do tempo. Arquiteturas monolíticas são tradicionalmente associadas à simplicidade estrutural e à centralização do controle, enquanto arquiteturas de microsserviços propõem a decomposição do sistema em serviços pequenos e implantáveis de forma independente, frequentemente alinhados a capacidades de negócio (LEWIS; FOWLER, 2014; DRAGONI et al., 2017).&lt;/p&gt;

&lt;p&gt;Embora o debate sobre microsserviços tenha se intensificado tanto na indústria quanto na academia, estudos apontam que os resultados associados a esse estilo arquitetural variam significativamente conforme o contexto de aplicação. Aspectos como tamanho do sistema, organização das equipes, práticas de desenvolvimento e requisitos não funcionais influenciam de forma decisiva a adequação de cada abordagem arquitetural (DI FRANCESCO; LAGO; MALAVOLTA, 2019). Ainda assim, observa-se uma &lt;strong&gt;lacuna de entendimento prático e acadêmico sobre como iniciar sistemas de software&lt;/strong&gt;, especialmente nos estágios iniciais, quando decisões arquiteturais precisam ser tomadas diante de incertezas quanto à evolução futura do produto e da organização.&lt;/p&gt;

&lt;p&gt;Essa lacuna se manifesta na dificuldade de estabelecer critérios claros para a escolha da arquitetura inicial, bem como na ausência de consensos consolidados na literatura sobre quais fatores devem ser priorizados nesse momento. Como resultado, arquiteturas monolíticas e de microsserviços são frequentemente discutidas de forma comparativa, mas sem diretrizes suficientemente explícitas sobre &lt;strong&gt;em quais contextos cada alternativa tende a ser mais adequada&lt;/strong&gt; (DI FRANCESCO et al., 2018; TAIBI; LENARDUZZI; PAHL, 2017).&lt;/p&gt;

&lt;p&gt;Diante desse contexto, este trabalho tem como objetivo analisar e sintetizar evidências existentes sobre arquiteturas monolíticas e de microsserviços, buscando responder às seguintes questões:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quais são as vantagens e desvantagens de optar por uma arquitetura monolítica e por uma arquitetura de microsserviços?
&lt;/li&gt;
&lt;li&gt;Quais requisitos não funcionais influenciam decisões relacionadas às arquiteturas monolítica e de microsserviços?
&lt;/li&gt;
&lt;li&gt;Em quais contextos é mais adequado selecionar uma arquitetura monolítica ou uma arquitetura de microsserviços?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;2. Método&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Para a realização desta pesquisa foi utilizado a metodologia de Revisão Rápida. Uma &lt;strong&gt;revisão rápida&lt;/strong&gt; é uma forma &lt;strong&gt;estruturada e transparente&lt;/strong&gt; de reunir e resumir evidências sobre uma pergunta específica para apoiar decisões (CARTAXO et al. 2018). Isso quer dizer que, em vez de depender só de opinião ou experiências isoladas, a equipe segue um &lt;strong&gt;processo organizado&lt;/strong&gt; para identificar o que já foi estudado na literatura acadêmica e transformar esses achados em &lt;strong&gt;insights acionáveis&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2.1 Condução da pesquisa&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Inicialmente, foi realizada uma &lt;strong&gt;busca manual&lt;/strong&gt; no Google Scholar para gerar conhecimento da área para os pesquisadores e aperfeiçoar as questões de pesquisa. Nesta etapa o objeto era entender as pesquisas da área e sair com background suficiente para gerar uma boa string de busca.  Essa etapa resultou na seleção de &lt;strong&gt;3 estudos&lt;/strong&gt;, os quais compuseram o chamado &lt;strong&gt;Golden Set&lt;/strong&gt;. Esses trabalhos foram utilizados como base de referência para validar a estratégia de busca automatizada, garantindo que os principais estudos do domínio fossem recuperados.&lt;/p&gt;

&lt;p&gt;Em seguida, foi conduzida uma &lt;strong&gt;busca automatizada&lt;/strong&gt; no IEEE, utilizando uma string de busca definida a partir dos termos-chave identificados no Golden Set. Essa busca retornou um total de &lt;strong&gt;61 estudos&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Na etapa seguinte, foi realizada a &lt;strong&gt;leitura dos resumos&lt;/strong&gt; dos artigos encontrados, com aplicação dos critérios de inclusão e exclusão definidos no protocolo da revisão. Como resultado dessa triagem inicial, &lt;strong&gt;13 estudos&lt;/strong&gt; foram considerados aptos para a próxima fase.&lt;/p&gt;

&lt;p&gt;Em seguida, esses estudos passaram por uma &lt;strong&gt;leitura completa&lt;/strong&gt;, permitindo uma avaliação ao objetivo da pesquisa. Ao final dessa etapa, &lt;strong&gt;6 estudos&lt;/strong&gt; atenderam os critérios estabelecidos e foram selecionados a partir da busca automatizada.&lt;/p&gt;

&lt;p&gt;Por fim, foi realizada uma &lt;strong&gt;busca manual&lt;/strong&gt; no Google Scholar por artigos que citaram os 6 estudos da etapa anterior, na qual foram selecionados &lt;strong&gt;14 estudos&lt;/strong&gt; adicionais considerados relevantes para o escopo da pesquisa. Essa etapa teve como objetivo complementar a busca automatizada, garantindo a inclusão de trabalhos potencialmente relevantes que não foram recuperados pelas strings de busca definidas ou pela base selecionada. Totalizando &lt;strong&gt;23 estudos&lt;/strong&gt; identificados. Para mais informações sobre o processo, como string de busca, críterios de inclusão e exclusão, analisar o &lt;a href="https://docs.google.com/document/d/1-E6j6y-SPG6QKRFvmCEdD0sGN7orSCyQg4OSVZssjbI/edit?usp=drive_link" rel="noopener noreferrer"&gt;relatório de evidências.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3 Resultados&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A análise dos estudos selecionados permitiu identificar um conjunto de achados relacionados à adoção da arquitetura monolítica, organizados segundo três dimensões principais: organizacional, arquitetural e relacionada às pessoas. Os resultados foram extraídos de estudos aplicados e revisões, conforme indicado nos identificadores associados a cada aspecto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.1 Monolito&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.1.1 Dimensão Organizacional&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;No que se refere à dimensão organizacional, os estudos indicaram que a arquitetura monolítica apresentou vantagens em contextos caracterizados por equipes menores e projetos de pequeno porte (GRAVANIS; KAKARONTZAS; GEROGIANNIS, 2022; VELEPUCHA; FLORES, 2023). Esses cenários foram associados a uma maior simplicidade de coordenação e menor sobrecarga organizacional, favorecendo a adoção do monolito em fases iniciais de desenvolvimento. Por outro lado, os resultados também evidenciaram que mudanças estruturais em sistemas monolíticos estiveram associadas a custos elevados, especialmente à medida que o sistema evoluiu e se tornou mais complexo (VELEPUCHA; FLORES, 2023). Esses custos foram relacionados à necessidade de modificações amplas no código e à dependência entre componentes, dificultando a adaptação organizacional ao longo do tempo.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.1.2 Dimensão Arquitetural&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Na dimensão arquitetural, os achados revelaram tanto vantagens quanto desvantagens associadas à arquitetura monolítica. Entre as vantagens, destacaram-se o desenvolvimento inicial mais simples, a centralização do código-fonte e a maior facilidade para atividades de depuração (VELEPUCHA; FLORES, 2023; MENARD, 2020; BAŠKARADA; NGUYEN; KORONIOS, 2020; CHATURVEDI et al., 2024 ). Os estudos também indicaram que os testes de construção simples, como testes de unidade, foram mais facilmente implementados nesse tipo de arquitetura, em comparação com arquiteturas distribuídas (MENARD, 2020; CHATURVEDI et al., 2024; VELEPUCHA; FLORES, 2021).&lt;/p&gt;

&lt;p&gt;Entretanto, os resultados apontaram um conjunto consistente de desvantagens. A complexidade do sistema foi reportada como um problema recorrente, especialmente em aplicações de médio e grande porte (GRAVANIS; KAKARONTZAS; GEROGIANNIS, 2022; VELEPUCHA; FLORES, 2023; VELEPUCHA; FLORES, 2021). Questões relacionadas à escalabilidade foram frequentemente associadas à estrutura monolítica, limitando a capacidade de evolução independente dos componentes (GRAVANIS; KAKARONTZAS; GEROGIANNIS, 2022; MENARD, 2020; BAŠKARADA; NGUYEN; KORONIOS, 2020; SEEDAT; ABBAS; AHMAD, 2023). Além disso, os estudos relataram dificuldades relacionadas à manutenibilidade, alto acoplamento entre módulos e limitações na tolerância a falhas, uma vez que falhas em partes específicas do sistema puderam comprometer o funcionamento da aplicação como um todo (GRAVANIS; KAKARONTZAS; GEROGIANNIS, 2022; SEEDAT; ABBAS; AHMAD, 2023; VELEPUCHA; FLORES, 2021; CHATURVEDI et al., 2024). Outro achado relevante foi a dificuldade na realização de testes end-to-end, atribuída à dependência entre os componentes e à necessidade de execução integrada do sistema (VELEPUCHA; FLORES, 2023; BAŠKARADA; NGUYEN; KORONIOS, 2020; SEEDAT; ABBAS; AHMAD, 2023).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.1.3 Dimensão Relacionada às Pessoas&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;No que diz respeito à dimensão relacionada às pessoas, o estudo  indica que  a adoção e manutenção de sistemas monolíticos estiveram associadas a desenvolvimento com conhecimento técnico da arquitetura, tornando a necessidade um profissional não tão especializado (MENARD, 2020).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.2 Microserviços&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.2.1 Dimensão Organizacional&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Na dimensão organizacional, a entrega mais rápida de software foi reportada como uma vantagem em dois estudos, indicando que arquiteturas de microsserviços estiveram associadas à redução do tempo de entrega em determinados contextos (MENARD, 2020; KÖNÖNEN, 2018). Em contraste, a percepção de que essa arquitetura não representou uma resposta para todos os problemas organizacionais foi identificada em um estudo (MENARD, 2020), assim como a constatação de que sua adoção foi ineficaz para software de pequeno porte, também reportada em um estudo (MENARD, 2020).&lt;/p&gt;

&lt;p&gt;Problemas relacionados ao gerenciamento dos serviços foram reportados em dois estudos (KRUG; CHANIN; SALES, 2024; CHATURVEDI et al., 2024), evidenciando desafios associados à coordenação, monitoramento e operação de múltiplos serviços. Além disso, a falta de autonomia para deploys foi identificada em um estudo (KRUG; CHANIN; SALES, 2024), indicando limitações organizacionais em contextos específicos. Por outro lado, a autonomia de equipes foi apontada como uma vantagem em três estudos (MENARD, 2020, KÖNÖNEN, 2018; CHATURVEDI et al., 2024), sugerindo que a descentralização promovida pelos microsserviços favoreceu a independência das equipes de desenvolvimento em determinados cenários.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.2.2 Dimensão Arquitetural&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;No âmbito arquitetural, a escalabilidade foi o aspecto mais frequentemente reportado, sendo identificada como vantagem em dezesseis estudos (KALSKE; MÄKITALO; MIKKONEN, 2017; GRAVANIS; KAKARONTZAS; GEROGIANNIS, 2022; NOGUEIRA et al., 2024; VELEPUCHA; FLORES, 2023; AUER et al., 2021; HMUE; PHYU; PAING, 2024; MENARD, 2020; KÖNÖNEN, 2018; HONCHARUK, 2025; BAŠKARADA; NGUYEN; KORONIOS, 2020; CHATURVEDI et al., 2024; SEEDAT; ABBAS; AHMAD, 2023; VELEPUCHA; FLORES, 2021), o que indica forte recorrência desse tema na literatura analisada. A diversidade de stacks para programar foi mencionada como vantagem em um estudo (BAŠKARADA; NGUYEN; KORONIOS, 2020), assim como a redução de código redundante, também reportada em um estudo (KÖNÖNEN, 2018). A flexibilidade na construção dos módulos foi identificada como vantagem em um estudo (KALSKE; MÄKITALO; MIKKONEN, 2017), associando a arquitetura de microsserviços à possibilidade de evolução independente dos componentes.&lt;/p&gt;

&lt;p&gt;Por outro lado, a ambiguidade na definição e compreensão dos microsserviços foi reportada como desvantagem em um estudo(MENARD, 2020), indicando dificuldades conceituais ou de escopo. Questões relacionadas à tolerância a falhas foram identificadas como vantagem em quatro estudos (KÖNÖNEN, 2018; CHATURVEDI et al., 2024; SEEDAT; ABBAS; AHMAD, 2023; VELEPUCHA; FLORES, 2021), sugerindo que a arquitetura favoreceu o isolamento de falhas em determinados contextos. Em contrapartida, dificuldades relacionadas à realização de testes foram reportadas em três estudos (KÖNÖNEN, 2018; KRUG; CHANIN; SALES, 2024; AUER et al., 2021), indicando que a testabilidade representou um desafio recorrente em ambientes baseados em microsserviços.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3.2.3 Dimensão Relacionada às Pessoas&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;No que se refere à dimensão relacionada às pessoas, a falta de conhecimento técnico da equipe foi identificada como desvantagem em três estudos (MENARD, 2020; KÖNÖNEN, 2018; KRUG; CHANIN; SALES, 2024), indicando que a adoção de microsserviços esteve associada à necessidade de competências técnicas mais avançadas, tanto no desenvolvimento quanto na operação dos sistemas.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3.3 Requisitos Não Funcionais em Arquiteturas de Microsserviços&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A análise dos estudos selecionados permitiu identificar um conjunto de requisitos não funcionais associados à adoção de arquiteturas baseadas em microsserviços. Esses requisitos foram extraídos de estudos aplicados e revisões, sendo classificados de acordo com sua recorrência na literatura analisada.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;escalabilidade&lt;/strong&gt; foi o requisito não funcional mais frequentemente reportado, estando presente em &lt;strong&gt;16 estudos&lt;/strong&gt; (KALSKE; MÄKITALO; MIKKONEN, 2017; GRAVANIS; KAKARONTZAS; GEROGIANNIS, 2022; NOGUEIRA et al., 2024; VELEPUCHA; FLORES, 2023; AUER et al., 2021; HMUE; PHYU; PAING, 2024; MENARD, 2020; KÖNÖNEN, 2018; HONCHARUK, 2025; BAŠKARADA; NGUYEN; KORONIOS, 2020; CHATURVEDI et al., 2024; SEEDAT; ABBAS; AHMAD, 2023; VELEPUCHA; FLORES, 2021), o que indica forte consenso na literatura quanto à capacidade dessa arquitetura de suportar crescimento e variações de carga por meio da decomposição e escalonamento independente dos serviços. A &lt;strong&gt;orquestração&lt;/strong&gt; foi identificada em &lt;strong&gt;dois estudos&lt;/strong&gt; (HMUE; PHYU; PAING, 2024; BAŠKARADA; NGUYEN; KORONIOS, 2020), refletindo a necessidade de mecanismos específicos para coordenação e gerenciamento dos serviços distribuídos.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;disponibilidade&lt;/strong&gt; foi reportada em &lt;strong&gt;um estudo&lt;/strong&gt; (VELEPUCHA; FLORES, 2023), enquanto a &lt;strong&gt;tolerância a falhas&lt;/strong&gt; foi identificada em &lt;strong&gt;quatro estudos&lt;/strong&gt; (KÖNÖNEN, 2018; CHATURVEDI et al., 2024; SEEDAT; ABBAS; AHMAD, 2023; VELEPUCHA; FLORES, 2021 ), indicando que o isolamento de serviços contribuiu para a resiliência do sistema em determinados contextos. O &lt;strong&gt;reuso&lt;/strong&gt; foi associado aos microsserviços em &lt;strong&gt;cinco estudos&lt;/strong&gt; (NOGUEIRA et al., 2024; VELEPUCHA; FLORES, 2023; CARVALHO et al., 2019; HONCHARUK, 2025; GOUIGOUX; TAMZALIT, 2017), sugerindo que a modularização favoreceu a reutilização de componentes e funcionalidades. A &lt;strong&gt;segurança distribuída&lt;/strong&gt; foi mencionada em &lt;strong&gt;dois estudos&lt;/strong&gt; (HMUE; PHYU; PAING, 2024; VELEPUCHA; FLORES, 2021), evidenciando preocupações relacionadas à proteção de dados, autenticação e autorização em ambientes distribuídos.&lt;/p&gt;

&lt;p&gt;O requisito de &lt;strong&gt;performance&lt;/strong&gt; foi reportado em &lt;strong&gt;sete estudos&lt;/strong&gt; (KALSKE; MÄKITALO; MIKKONEN, 2017; GRAVANIS; KAKARONTZAS; GEROGIANNIS, 2022; CARVALHO et al., 2019; BAŠKARADA; NGUYEN; KORONIOS, 2020; VELEPUCHA; FLORES, 2021; GOUIGOUX; TAMZALIT, 2017; BERRY et al., 2024), indicando que o impacto no desempenho foi um aspecto recorrente nas avaliações de microsserviços, tanto em termos de benefícios quanto de desafios decorrentes da comunicação entre serviços.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;refatoração&lt;/strong&gt; foi reportada em &lt;strong&gt;dois estudos&lt;/strong&gt; (KALSKE; MÄKITALO; MIKKONEN, 2017; GRAVANIS; KAKARONTZAS; GEROGIANNIS, 2022), sugerindo a necessidade de reestruturação do código durante a adoção ou evolução da arquitetura. O &lt;strong&gt;deploy contínuo (CI/CD)&lt;/strong&gt; foi identificado em &lt;strong&gt;sete estudos&lt;/strong&gt; (GRAVANIS; KAKARONTZAS; GEROGIANNIS, 2022; NOGUEIRA et al., 2024; VELEPUCHA; FLORES, 2023; AUER et al., 2021; HONCHARUK, 2025; BAŠKARADA; NGUYEN; KORONIOS, 2020; CHATURVEDI et al., 2024; GOUIGOUX; TAMZALIT, 2017), indicando forte associação entre microsserviços e práticas de automação de entrega. A &lt;strong&gt;manutenibilidade&lt;/strong&gt; foi reportada em &lt;strong&gt;cinco estudos&lt;/strong&gt; (NOGUEIRA et al., 2024; AUER et al., 2021; CHATURVEDI et al., 2024; SEEDAT; ABBAS; AHMAD, 2023; FRITZSCH et al., 2019), refletindo benefícios e desafios relacionados à evolução do sistema ao longo do tempo.&lt;/p&gt;

&lt;p&gt;Aspectos relacionados às &lt;strong&gt;pessoas e à agilidade&lt;/strong&gt; foram identificados em &lt;strong&gt;nove estudos (&lt;/strong&gt;GRAVANIS; KAKARONTZAS; GEROGIANNIS, 2022; NOGUEIRA et al., 2024; AUER et al., 2021; MENARD, 2020; KÖNÖNEN, 2018; HONCHARUK, 2025; CHATURVEDI et al., 2024; SEEDAT; ABBAS; AHMAD, 2023; VELEPUCHA; FLORES, 2021), indicando que a arquitetura de microsserviços está frequentemente associada a mudanças organizacionais, maior autonomia de equipes e necessidade de adaptação de processos. Por fim, &lt;strong&gt;testes&lt;/strong&gt; foram reportados em &lt;strong&gt;quatro estudos&lt;/strong&gt; (VELEPUCHA; FLORES, 2023; HMUE; PHYU; PAING, 2024; BAŠKARADA; NGUYEN; KORONIOS, 2020; SEEDAT; ABBAS; AHMAD, 2023), evidenciando desafios específicos na validação de sistemas distribuídos, especialmente no que se refere a testes de integração e ponta a ponta.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3.4 Síntese dos Critérios para Seleção entre Arquitetura Monolítica e Microsserviços&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A análise dos estudos selecionados permitiu sintetizar um conjunto de critérios decisórios associados à escolha entre arquitetura monolítica e arquitetura de microsserviços, considerando o tipo de problema a ser resolvido, o contexto organizacional e o estágio de maturidade da empresa. Os resultados indicaram que a decisão arquitetural esteve diretamente relacionada às características do negócio, da equipe e dos objetivos do sistema.&lt;/p&gt;

&lt;p&gt;No caso da &lt;strong&gt;arquitetura monolítica&lt;/strong&gt;, os estudos indicaram que sua adoção esteve associada a cenários nos quais o objetivo principal foi a &lt;strong&gt;validação de ideias&lt;/strong&gt;, o &lt;strong&gt;desenvolvimento de projetos pequenos&lt;/strong&gt; e a &lt;strong&gt;redução do tempo de entrada no mercado&lt;/strong&gt;. Esses contextos foram caracterizados por &lt;strong&gt;equipes menores&lt;/strong&gt;, &lt;strong&gt;estrutura técnica mais simples&lt;/strong&gt; e &lt;strong&gt;custos iniciais reduzidos&lt;/strong&gt;. A literatura analisada apontou que tais características tornaram a arquitetura monolítica particularmente adequada para &lt;strong&gt;startups&lt;/strong&gt; e organizações em estágio inicial, especialmente quando houve necessidade de construção rápida de &lt;strong&gt;produtos mínimos viáveis (MVPs)&lt;/strong&gt; com baixo investimento inicial.&lt;/p&gt;

&lt;p&gt;Em contraste, a &lt;strong&gt;arquitetura de microsserviços&lt;/strong&gt; foi associada a contextos nos quais requisitos como &lt;strong&gt;segurança&lt;/strong&gt;, &lt;strong&gt;testes contínuos&lt;/strong&gt;, &lt;strong&gt;crescimento do negócio&lt;/strong&gt;, &lt;strong&gt;resiliência&lt;/strong&gt;, &lt;strong&gt;observabilidade&lt;/strong&gt; e &lt;strong&gt;escalabilidade organizacional e técnica&lt;/strong&gt; foram mais relevantes. Os estudos indicaram que essa arquitetura foi mais frequentemente adotada por &lt;strong&gt;empresas consolidadas&lt;/strong&gt;, caracterizadas por operações em larga escala, múltiplos domínios de negócio e disponibilidade de investimento para sustentar a complexidade arquitetural. Nesses cenários, a adoção de microsserviços esteve associada a &lt;strong&gt;custos mais elevados&lt;/strong&gt;, tanto em termos técnicos quanto organizacionais, compensados pela capacidade de evolução independente dos serviços.&lt;/p&gt;

&lt;p&gt;Os resultados também indicaram que, independentemente da arquitetura adotada, a decisão impactou a &lt;strong&gt;organização como um todo&lt;/strong&gt;, exigindo alinhamento entre estrutura organizacional, processos de desenvolvimento e capacidades técnicas. A literatura destacou que a arquitetura selecionada demandou &lt;strong&gt;dinâmicas organizacionais específicas&lt;/strong&gt; para que seus benefícios fossem efetivamente alcançados, incluindo adequações na forma de trabalho das equipes, nos processos de entrega e na governança técnica.&lt;/p&gt;

&lt;p&gt;De modo geral, a síntese dos estudos analisados indicou que a escolha entre arquitetura monolítica e microsserviços não esteve associada exclusivamente a critérios técnicos, mas resultou de uma combinação de fatores organizacionais, estratégicos e humanos, os quais influenciaram diretamente a sustentabilidade da arquitetura ao longo do tempo.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Discussão&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Os resultados deste briefing reforçam que a escolha entre &lt;strong&gt;monólito&lt;/strong&gt; e &lt;strong&gt;microsserviços&lt;/strong&gt; é, sobretudo, &lt;strong&gt;dependente de contexto&lt;/strong&gt; e do “momento” do produto. No conjunto analisado (23 estudos), o &lt;strong&gt;monólito&lt;/strong&gt; aparece mais associado a cenários de &lt;strong&gt;menor complexidade organizacional e técnica&lt;/strong&gt;, com &lt;strong&gt;equipes menores&lt;/strong&gt; e &lt;strong&gt;projetos pequenos&lt;/strong&gt;, destacando benefícios como &lt;strong&gt;simplicidade de desenvolvimento&lt;/strong&gt;, &lt;strong&gt;centralização do código&lt;/strong&gt;, &lt;strong&gt;facilidade de depuração&lt;/strong&gt; e &lt;strong&gt;testes mais simples&lt;/strong&gt; quando comparados a cenários distribuídos.&lt;/p&gt;

&lt;p&gt;Ao mesmo tempo, a literatura indica que, à medida que o sistema cresce, tendem a emergir limitações ligadas a &lt;strong&gt;complexidade&lt;/strong&gt;, &lt;strong&gt;acoplamento&lt;/strong&gt;, &lt;strong&gt;manutenaibilidade&lt;/strong&gt; e &lt;strong&gt;escalabilidade&lt;/strong&gt;, além do custo de mudanças que podem exigir reconstrução/redeploy de toda a aplicação.&lt;/p&gt;

&lt;p&gt;Já os &lt;strong&gt;microsserviços&lt;/strong&gt; são descritos principalmente como resposta a demandas de &lt;strong&gt;escalabilidade&lt;/strong&gt; e &lt;strong&gt;evolução independente&lt;/strong&gt; (desenvolver, implantar e escalar serviços separadamente), com benefícios adicionais frequentemente citados como &lt;strong&gt;isolamento de falhas&lt;/strong&gt; e &lt;strong&gt;flexibilidade evolutiva&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Contudo, essa arquitetura introduz um custo de coordenação e operação: surgem desafios como &lt;strong&gt;definir e delimitar serviços&lt;/strong&gt; (onde “cortar”), &lt;strong&gt;testes mais difíceis&lt;/strong&gt;, &lt;strong&gt;gerência/observabilidade&lt;/strong&gt; e maior dependência de &lt;strong&gt;expertise técnica&lt;/strong&gt; para lidar com a complexidade distribuída.&lt;/p&gt;

&lt;p&gt;Do ponto de vista de requisitos não funcionais e critérios de decisão, há uma diferença importante: para microsserviços, a síntese destaca concentração em &lt;strong&gt;escalabilidade&lt;/strong&gt; e em capacidades organizacionais ligadas a entrega (agilidade, CI/CD e governança de deploy), enquanto no monólito aparecem com mais ênfase &lt;strong&gt;testes&lt;/strong&gt;, &lt;strong&gt;arquitetura simples&lt;/strong&gt;, &lt;strong&gt;time-to-market&lt;/strong&gt;, &lt;strong&gt;custo&lt;/strong&gt;, &lt;strong&gt;deploy fácil&lt;/strong&gt; e &lt;strong&gt;depuração&lt;/strong&gt; como critérios recorrentes.&lt;/p&gt;

&lt;p&gt;Esse contraste sugere que “iniciar” com microsserviços tende a fazer mais sentido quando o problema já nasce com demandas claras de escala/resiliência e trabalho paralelo entre equipes, enquanto o monólito tende a favorecer fases de maior incerteza, validação (MVP) e foco em velocidade/custo.&lt;/p&gt;

&lt;p&gt;Por fim, há um alerta metodológico relevante: a evidência utilizada é &lt;strong&gt;heterogênea&lt;/strong&gt; e o relatório-base &lt;strong&gt;não inclui avaliação detalhada de qualidade metodológica por artigo&lt;/strong&gt;; portanto, este briefing deve ser usado como &lt;strong&gt;apoio à decisão&lt;/strong&gt;, não como regra universal.&lt;/p&gt;

&lt;p&gt;Além disso, a própria revisão foi conduzida como &lt;strong&gt;revisão rápida&lt;/strong&gt;, isto é, um processo estruturado e transparente para sintetizar evidências visando apoiar decisões, o que reforça a necessidade de interpretar os achados com pragmatismo e cautela. Vale salientar também que devido a escolha desse método, é possível que existam outros artigos que não foram capturados na busca. Para minimizar o impacto, foi realizado uma busca manual nas citações. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. Conclusão&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Com base na síntese dos 23 estudos, a decisão entre monólito e microsserviços deve ser orientada por &lt;strong&gt;(i) tipo de problema, (ii) requisitos não funcionais, (iii) contexto organizacional e (iv) Capacidade técnica da equipe&lt;/strong&gt;, evitando adoção por “moda” e priorizando a capacidade real de operação e entrega.&lt;/p&gt;

&lt;p&gt;Em estágios iniciais e contextos com &lt;strong&gt;equipes menores&lt;/strong&gt;, alta incerteza e prioridade em &lt;strong&gt;simplicidade, velocidade e custo&lt;/strong&gt;, o &lt;strong&gt;monólito&lt;/strong&gt; tende a ser uma alternativa mais adequada, com ganhos em desenvolvimento, testes e depuração, ainda que possa exigir revisão arquitetural conforme o sistema cresce.&lt;/p&gt;

&lt;p&gt;Quando o sistema já enfrenta (ou claramente enfrentará) demandas fortes de &lt;strong&gt;escalabilidade/resiliência&lt;/strong&gt;, necessidade de &lt;strong&gt;deploy independente&lt;/strong&gt; e &lt;strong&gt;trabalho paralelo entre equipes&lt;/strong&gt;, os &lt;strong&gt;microsserviços&lt;/strong&gt; tendem a ser mais adequados, desde que a organização consiga sustentar a complexidade adicional (delimitação de serviços, testes distribuídos e operação/observabilidade).&lt;/p&gt;

&lt;p&gt;Por se tratar de uma revisão rápida e por a evidência ser heterogênea, recomenda-se usar este briefing como &lt;strong&gt;base para uma decisão consciente&lt;/strong&gt;, complementando com análise do contexto local (produto, equipe e operação) e registrando explicitamente os trade-offs assumidos&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Apêndice A – Estudos analisados (títulos e IDs)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Lista do relatório-base:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ID1 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Challenges+When+Moving+from+Monolith+to+Microservice+Architecture&amp;amp;btnG=" rel="noopener noreferrer"&gt;Challenges When Moving from Monolith to Microservice Architecture (Aplicado)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID2 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=You+don%E2%80%99t+need+a+Microservices+Architecture+%28yet%29&amp;amp;btnG=" rel="noopener noreferrer"&gt;You don’t need a Microservices Architecture (yet) (Revisões)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID3 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Insights+on+Microservice+Architecture+Through+the+Eyes+of+Industry+Practitioners&amp;amp;btnG=" rel="noopener noreferrer"&gt;Insights on Microservice Architecture Through the Eyes of Industry Practitioners (Aplicado)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID4 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=A+Survey+on+Microservices+Architecture%3A+Principles%2C+Patterns+and+Migration+Challenges&amp;amp;btnG=" rel="noopener noreferrer"&gt;A Survey on Microservices Architecture: Principles, Patterns and Migration Challenges (Revisões)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID5 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=From+monolithic+systems+to+Microservices%3A+An+assessment+framework+%28Aplicado%29&amp;amp;btnG=" rel="noopener noreferrer"&gt;From monolithic systems to Microservices: An assessment framework (Aplicado)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID6 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Analysis+of+the+Criteria+Adopted+in+Industry+to+Extract+Microservices+%28Aplicado%29&amp;amp;btnG=" rel="noopener noreferrer"&gt;Analysis of the Criteria Adopted in Industry to Extract Microservices (Aplicado)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID7 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Microservices+vs+Monolith%3A+A+Comparative+Analysis+and+Problem-Solving+Approach+in+Web+Development+Area+%28Aplicado%29&amp;amp;btnG=" rel="noopener noreferrer"&gt;Microservices vs Monolith: A Comparative Analysis and Problem-Solving Approach in Web Development Area (Aplicado)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID8 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Monolithic+vs.+Microservice+Architecture%3A+A+Performance+and+Scalability+Evaluation+%28Aplicado%29&amp;amp;btnG=" rel="noopener noreferrer"&gt;Monolithic vs. Microservice Architecture: A Performance and Scalability Evaluation (Aplicado)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID9 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=The+Monolith+Strikes+Back%3A+Why+Istio+Migrated+From+Microservices+to+a+Monolithic+Architecture+%28Aplicado%29&amp;amp;btnG=" rel="noopener noreferrer"&gt;The Monolith Strikes Back: Why Istio Migrated From Microservices to a Monolithic Architecture (Aplicado)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID10 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Decision+criteria+between+microservice+and+monolithic+architecture+%28Revis%C3%B5es%29&amp;amp;btnG=" rel="noopener noreferrer"&gt;Decision criteria between microservice and monolithic architecture (Revisões)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID11 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Microservices%3A+Considerations+before+implementation&amp;amp;btnG=" rel="noopener noreferrer"&gt;Microservices: Considerations before implementation (Revisões)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID12 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Do+You+Really+Need+Microservices+Architecture%3F&amp;amp;btnG=" rel="noopener noreferrer"&gt;Do You Really Need Microservices Architecture? (Aplicado)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID13 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Exploring+the+Pros+and+Cons+of+Monolithic+Applications+versus+Microservices&amp;amp;btnG=" rel="noopener noreferrer"&gt;Exploring the Pros and Cons of Monolithic Applications versus Microservices (Aplicado)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID14 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Architecting+Microservices%3A+Practical+Opportunities+and+Challenges&amp;amp;btnG=" rel="noopener noreferrer"&gt;Architecting Microservices: Practical Opportunities and Challenges (Aplicado)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID15 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Promises+and+challenges+of+microservices%3A+an+exploratory+study&amp;amp;btnG=" rel="noopener noreferrer"&gt;Promises and challenges of microservices: an exploratory study  (Aplicado)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID16 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Migrating+Towards+Microservice+Architectures%3A+An+Industrial+Survey&amp;amp;btnG=" rel="noopener noreferrer"&gt;Migrating Towards Microservice Architectures: An Industrial Survey (Aplicado)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID17 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=From+Monolith+to+Microservices+%3A+A+Systematic+Literature+Survey&amp;amp;btnG=" rel="noopener noreferrer"&gt;From Monolith to Microservices : A Systematic Literature Survey (Revisões)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID18 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Systematic+Mapping+of+Monolithic+Applications+to+Microservices+Architecture&amp;amp;btnG=" rel="noopener noreferrer"&gt;Systematic Mapping of Monolithic Applications to Microservices&lt;/a&gt;
&lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Systematic+Mapping+of+Monolithic+Applications+to+Microservices+Architecture&amp;amp;btnG=" rel="noopener noreferrer"&gt;Architecture (Revisões)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ID19 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Monolits+to+microservices+-+Migration+Problems+and+Challenges%3A+A+SMS&amp;amp;btnG=" rel="noopener noreferrer"&gt;Monolits to microservices - Migration Problems and&lt;/a&gt;
&lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Monolits+to+microservices+-+Migration+Problems+and+Challenges%3A+A+SMS&amp;amp;btnG=" rel="noopener noreferrer"&gt;Challenges: A SMS (Revisões)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ID20 – &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Microservices+Migration+in+Industry%3A+Intentions%2C+Strategies%2C+and+Challenges&amp;amp;btnG=" rel="noopener noreferrer"&gt;Microservices Migration in Industry: Intentions, Strategies, and Challenges (Aplicado)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ID21 - &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=From+Monolith+to+Microservices%3A+Lessons+Learned+on+an+Industrial+Migration+to+a+Web+Oriented+Architecture&amp;amp;btnG=" rel="noopener noreferrer"&gt;From Monolith to Microservices: Lessons Learned on an Industrial Migration to a Web Oriented Architecture (Aplicado)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ID22 - &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Is+it+Worth+Migrating+a+Monolith+to+Microservices%3F+An+Experience+Report+on+Performance%2C+Availability+and+Energy+Usage&amp;amp;btnG=" rel="noopener noreferrer"&gt;Is it Worth Migrating a Monolith to Microservices? An Experience Report on Performance, Availability and Energy Usage (Aplicado)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ID23 - &lt;a href="https://scholar.google.com/scholar?hl=pt-BR&amp;amp;as_sdt=0%2C5&amp;amp;q=Architecture+Migration+From+Monolithic+to+Microservices%3A+Developing+Readiness+Criteria+%28Aplicado%29&amp;amp;btnG=" rel="noopener noreferrer"&gt;Architecture Migration From Monolithic to Microservices: Developing Readiness Criteria (Aplicado)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Referências&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;BASS, Len; CLEMENTS, Paul; KAZMAN, Rick. &lt;em&gt;Software Architecture in Practice&lt;/em&gt;. 3. ed. Boston: Addison-Wesley, 2013.&lt;/p&gt;

&lt;p&gt;DI FRANCESCO, Paolo; LAGO, Patricia; MALAVOLTA, Ivano. Architecting with microservices: A systematic mapping study. &lt;em&gt;Journal of Systems and Software&lt;/em&gt;, v. 150, p. 77–97, 2019.&lt;/p&gt;

&lt;p&gt;DI FRANCESCO, Paolo et al. Migrating towards microservices: An industrial survey. In: &lt;em&gt;Proceedings of the IEEE International Conference on Software Architecture (ICSA)&lt;/em&gt;. 2018.&lt;/p&gt;

&lt;p&gt;DRAGONI, Nicola et al. Microservices: Yesterday, today, and tomorrow. In: &lt;em&gt;Present and Ulterior Software Engineering&lt;/em&gt;. Cham: Springer, 2017. p. 195–216.&lt;/p&gt;

&lt;p&gt;LEWIS, James; FOWLER, Martin. &lt;em&gt;Microservices&lt;/em&gt;. 2014. Disponível em: &lt;a href="https://martinfowler.com/articles/microservices.html?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;https://martinfowler.com/articles/microservices.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;TAIBI, Davide; LENARDUZZI, Valentina; PAHL, Claus. Processes, motivations, and issues for migrating to microservices architectures: An empirical investigation. &lt;em&gt;IEEE Cloud Computing&lt;/em&gt;, v. 4, n. 5, p. 22–32, 2017.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cartaxo, B.; Pinto, G.; Soares, S.&lt;/strong&gt; The Role of Rapid Reviews in Supporting Decision-Making in Software Engineering Practice. In: Proceedings of the 22nd International Conference on Evaluation and Assessment in Software Engineering (EASE’18). 2018. p. 24–34. DOI: 10.1145/3210459.3210462. &lt;/p&gt;

&lt;p&gt;GRAVANIS, Dimitrios; KAKARONTZAS, George; GEROGIANNIS, Vassilis. &lt;em&gt;You don’t need a Microservices Architecture (yet): Monoliths may do the trick.&lt;/em&gt; In: Proceedings of the 2021 European Symposium on Software Engineering (ESSE ’21). New York, NY, EUA: ACM, 2022. p. 39–44. DOI: 10.1145/3501774.3501780.&lt;/p&gt;

&lt;p&gt;VELEPUCHA, Victor; FLORES, Pamela. &lt;em&gt;A survey on microservices architecture: Principles, patterns and migration challenges.&lt;/em&gt; IEEE Access, v. 11, p. 88339–88358, 2023.&lt;/p&gt;

&lt;p&gt;VELEPUCHA, Victor; FLORES, Pamela. &lt;em&gt;Monoliths to microservices: Migration problems and challenges: A SMS.&lt;/em&gt; In: 2021 Second International Conference on Information Systems and Software Technologies (ICI2ST). IEEE, 2021.&lt;/p&gt;

&lt;p&gt;MENARD, Niklas. &lt;em&gt;Decision criteria between microservice and monolithic architecture.&lt;/em&gt; 2020.&lt;/p&gt;

&lt;p&gt;BAŠKARADA, Saša; NGUYEN, Vivian; KORONIOS, Andy. &lt;em&gt;Microservices architecture: opportunities and practical challenges.&lt;/em&gt; Journal of Computer Information Systems, 2020.&lt;/p&gt;

&lt;p&gt;CHATURVEDI, Mayank et al. &lt;em&gt;From monolith to microservices: A systematic literature review.&lt;/em&gt; In: 2024 IEEE 3rd International Conference on Data, Decision and Systems (ICDDS). IEEE, 2024. p. 1–6.&lt;/p&gt;

&lt;p&gt;KALSKE, Miika; MÄKITALO, Niko; MIKKONEN, Tommi. &lt;em&gt;Challenges when moving from monolith to microservice architecture.&lt;/em&gt; Cham: Springer International Publishing, 2017. p. 32–47.&lt;/p&gt;

&lt;p&gt;NOGUEIRA, Vinicius L. et al. &lt;em&gt;Insights on microservice architecture through the eyes of industry practitioners.&lt;/em&gt; In: 2024 IEEE International Conference on Software Maintenance and Evolution (ICSME). IEEE, 2024. p. 765–777.&lt;/p&gt;

&lt;p&gt;AUER, Florian et al. &lt;em&gt;From monolithic systems to microservices: An assessment framework.&lt;/em&gt; Information and Software Technology, v. 137, p. 106600, 2021.&lt;/p&gt;

&lt;p&gt;CARVALHO, Luiz et al. &lt;em&gt;Analysis of the criteria adopted in industry to extract microservices.&lt;/em&gt; In: 2019 IEEE/ACM CESI &amp;amp; SER&amp;amp;IP. IEEE, 2019. p. 22–29.&lt;/p&gt;

&lt;p&gt;HMUE, Khant; PHYU, Myat Pwint; PAING, Aye Myat Myat. &lt;em&gt;Microservices vs monolith: A comparative analysis and problem-solving approach in web development area.&lt;/em&gt; In: 2024 IEEE ICAIT. IEEE, 2024. p. 1–5.&lt;/p&gt;

&lt;p&gt;BLINOWSKI, Grzegorz; OJDOWSKA, Anna; PRZYBYŁEK, Adam. &lt;em&gt;Monolithic vs. microservice architecture: A performance and scalability evaluation.&lt;/em&gt; IEEE Access, v. 10, p. 20357–20374, 2022.&lt;/p&gt;

&lt;p&gt;MENDONÇA, Nabor C. et al. &lt;em&gt;The monolith strikes back: Why Istio migrated from microservices to a monolithic architecture.&lt;/em&gt; IEEE Software, v. 38, n. 5, p. 17–22, 2021.&lt;/p&gt;

&lt;p&gt;KÖNÖNEN, Heini. &lt;em&gt;Microservices: Considerations before implementation.&lt;/em&gt; 2018.&lt;/p&gt;

&lt;p&gt;HONCHARUK, Vitalii. &lt;em&gt;Do you really need microservices architecture?&lt;/em&gt; 2025.&lt;/p&gt;

&lt;p&gt;KRUG, Daniel dos Santos; CHANIN, Rafael; SALES, Afonso. &lt;em&gt;Exploring the pros and cons of monolithic applications versus microservices.&lt;/em&gt; In: ICEIS 2024 – Volume 2. 2024.&lt;/p&gt;

&lt;p&gt;WANG, Yingying; KADIYALA, Harshavardhan; RUBIN, Julia. &lt;em&gt;Promises and challenges of microservices: An exploratory study.&lt;/em&gt; Empirical Software Engineering, v. 26, n. 4, p. 63, 2021.&lt;/p&gt;

&lt;p&gt;DI FRANCESCO, Paolo; LAGO, Patricia; MALAVOLTA, Ivano. &lt;em&gt;Migrating towards microservice architectures: An industrial survey.&lt;/em&gt; In: 2018 IEEE ICSA. IEEE, 2018. p. 29–2909.&lt;/p&gt;

&lt;p&gt;SEEDAT, Momil; ABBAS, Qaisar; AHMAD, Nadeem. &lt;em&gt;Systematic mapping of monolithic applications to microservices architecture.&lt;/em&gt; arXiv:2309.03796, 2023.&lt;/p&gt;

&lt;p&gt;FRITZSCH, Jonas et al. &lt;em&gt;Microservices migration in industry: Intentions, strategies, and challenges.&lt;/em&gt; In: 2019 IEEE ICSME. IEEE, 2019. p. 481–490.&lt;/p&gt;

&lt;p&gt;GOUIGOUX, Jean-Philippe; TAMZALIT, Dalila. &lt;em&gt;From monolith to microservices: Lessons learned on an industrial migration to a web oriented architecture.&lt;/em&gt; In: 2017 IEEE ICSAW. IEEE, 2017. p. 62–65.&lt;/p&gt;

&lt;p&gt;BERRY, Vincent et al. &lt;em&gt;Is it worth migrating a monolith to microservices? An experience report on performance, availability and energy usage.&lt;/em&gt; In: 2024 IEEE ICWS. IEEE, 2024. p. 944–954.&lt;/p&gt;

&lt;p&gt;HABIB, Pamungkas Imam et al. &lt;em&gt;Architecture migration from monolithic to microservices: Developing readiness criteria.&lt;/em&gt; IEEE Access, v. 12, p. 194630–194645, 2024.&lt;/p&gt;

&lt;p&gt;CHATURVEDI, Mayank et al. From Monolith to Microservices: A Systematic Literature Survey. In: 2024 IEEE 3rd International Conference on Data, Decision and Systems (ICDDS). IEEE, 2024. p. 1-6.&lt;/p&gt;

&lt;p&gt;BAŠKARADA, Saša; NGUYEN, Vivian; KORONIOS, Andy. Architecting microservices: Practical opportunities and challenges. Journal of Computer Information Systems, 2020.&lt;/p&gt;

&lt;p&gt;GOUIGOUX, Jean-Philippe; TAMZALIT, Dalila. From monolith to microservices: Lessons learned on an industrial migration to a web oriented architecture. In: 2017 IEEE international conference on software architecture workshops (ICSAW). IEEE, 2017. p. 62-65.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>softwareengineering</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>O que 70 especificações me ensinaram sobre agentes de código</title>
      <dc:creator>Alberto Luiz Souza</dc:creator>
      <pubDate>Mon, 12 Jan 2026 10:55:51 +0000</pubDate>
      <link>https://dev.to/asouza/o-que-70-especificacoes-me-ensinaram-sobre-agentes-de-codigo-4c50</link>
      <guid>https://dev.to/asouza/o-que-70-especificacoes-me-ensinaram-sobre-agentes-de-codigo-4c50</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Este texto foi inicialmente concebido pela IA Generativa em função da transcrição de um vídeo do Dev Eficiente. Se preferir acompanhar por vídeo, é só dar o play.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/cenPrHKGIRQ"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Depois de escrever quase 70 especificações para construir um projeto de ponta a ponta, quero compartilhar o que aprendi sobre Spec Driven Development. Esse tema tem ganhado tração por conta da capacidade de descrever o que você quer em linguagem natural e deixar um agente de código gerar o necessário para você.&lt;/p&gt;

&lt;p&gt;O projeto em questão foi a plataforma Contrato Dev Eficiente, que conecta nossa comunidade de pessoas que estudam conosco com empresas que precisam de profissionais com vontade de aprender. Não foi um experimento pontual - foram muitas especificações, tanto para backend quanto para frontend, e o resultado está no ar sendo usado.&lt;/p&gt;

&lt;h2&gt;
  
  
  O contexto atual do Spec Driven Development
&lt;/h2&gt;

&lt;p&gt;Recentemente, saiu um post no blog de Martin Fowler escrito por Birgitta Bockler, Distinguished Engineer e AI Assisted Delivery Expert na ThoughtWorks. Ela testou três ferramentas: Kiro (da Amazon), SpecKit e Tessel. O texto discute diferentes abordagens.&lt;/p&gt;

&lt;p&gt;Eu olhei o Kiro quando a Amazon lançou e uma pessoa da comunidade Dev Eficiente me indicou o SpecKit. Confesso que quando olhei, não me interessou no sentido de ser o caminho mais promissor para mim. A maioria dessas ferramentas trabalha com a ideia de você escrever a feature inteira e deixar que a especificação seja fonte para quebra de tarefas, para que o LLM planeje as tarefas necessárias.&lt;/p&gt;

&lt;p&gt;O que funcionou para mim não foi bem do jeito que está descrito nesses textos.&lt;/p&gt;

&lt;h2&gt;
  
  
  A evolução das minhas especificações
&lt;/h2&gt;

&lt;h3&gt;
  
  
  O começo: linguagem natural detalhada
&lt;/h3&gt;

&lt;p&gt;Na minha primeira especificação, eu queria importar pessoas alunas da plataforma de cursos para o novo sistema. Era um código de importação e eu estava menos preocupado com design naquele momento.&lt;/p&gt;

&lt;p&gt;O template inicial tinha:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Objetivo&lt;/li&gt;
&lt;li&gt;Pacote/pasta onde o código deveria ser gerado&lt;/li&gt;
&lt;li&gt;Referências importantes (como links de documentação)&lt;/li&gt;
&lt;li&gt;Detalhes de implementação em linguagem natural&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eu dava detalhes bem granulares: "cria o controller que seja capaz de importar todos os membros que ainda não foram importados anteriormente", "quando fizer a primeira chamada, já verifica se existe o primeiro email", "a chamada deve ser feita pelo cliente X que deve vir do application properties e deve obrigatoriamente ser definida como variável de ambiente".&lt;/p&gt;

&lt;p&gt;O problema? Percebi que estava investindo muito tempo escrevendo parágrafos em linguagem natural explicando o que eu queria.&lt;/p&gt;

&lt;h3&gt;
  
  
  O problema do código gerado por LLMs
&lt;/h3&gt;

&lt;p&gt;A média do código que vem do LLM, para o tipo de design que eu queria construir, não era suficiente. Mesmo tendo um arquivo &lt;code&gt;CLAUDE.md&lt;/code&gt; com guidelines, as decisões de design vinham com características que me incomodavam:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Código pouco coeso&lt;/strong&gt;: O LLM é bom quando você quer generalização, mas quando você pensa em coesão e separação de responsabilidades, o código gerado geralmente não atende às expectativas.&lt;/p&gt;

&lt;p&gt;Eu ficava olhando e pensando: "não é por esse caminho que eu quero". E aí comecei a refatorar bastante código, o que me fez questionar se essa era a melhor abordagem.&lt;/p&gt;

&lt;h3&gt;
  
  
  A virada: contratos de código ao invés de linguagem natural
&lt;/h3&gt;

&lt;p&gt;A minha versão final das especificações é bem diferente. Ao invés de tentar descrever o código em linguagem natural, o que mais funcionou foi:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pensar nas classes e arquivos necessários&lt;/strong&gt; para fazer determinado fluxo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Investir tempo nos métodos públicos&lt;/strong&gt; - as assinaturas, os parâmetros, o retorno&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Não pensar na implementação&lt;/strong&gt;, apenas nos contratos&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Por exemplo, numa especificação recente eu tinha:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Referências:
- Classe RecuperaAnaliseArquivoCurriculo (já declarada com métodos e parâmetros)
- ArquivoCurriculoRepository (estrutura já definida)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eu declarava os métodos, os parâmetros, escrevia a classe que representava a resposta. Aí eu olhava e falava: "acho que o controller está bom, preciso desses parâmetros, com esses parâmetros eu consigo fazer o que quero fazer".&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemplo prático: sistema de agentes
&lt;/h3&gt;

&lt;p&gt;Numa especificação para criar agentes de análise, eu escrevi as classes antes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// No arquivo prepara.ts&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgenteAnalisadorDeFormacoes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgenteAnalisadorDeExperiencias&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgenteAnalisadorDeHabilidadesTecnicas&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AnalisadorAgregado&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// junta tudo&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgenteAnaliseCompleta&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// chama todos e retorna análise final&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A explicação de alto nível foi apenas: "a partir de um ID de arquivo de currículo, precisamos analisar o currículo, criando um feedback e uma sugestão de versão atualizada".&lt;/p&gt;

&lt;p&gt;As referências que eu quero que o agente use, e pronto.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que delego vs. o que eu defino
&lt;/h2&gt;

&lt;p&gt;A combinação que funcionou para mim foi:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delego para o agente:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Coisas que quero fazer e não sei direito como (detalhes de implementação de bibliotecas específicas)&lt;/li&gt;
&lt;li&gt;Coisas que simplesmente não ligo para o como&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por exemplo, numa especificação eu precisava:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Código que utilizasse o Cloudflare R2 (S3 compatível) - não sabia usar a biblioteca&lt;/li&gt;
&lt;li&gt;Storage genérico para ter versão local e remota para desenvolvimento&lt;/li&gt;
&lt;li&gt;Usar Apache Tika para extrair texto de currículos (doc, pdf, texto)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eu falei: "coda isso pra mim", porque não sabia os detalhes, mas sabia que precisava.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Eu defino:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As interfaces (assinaturas dos métodos)&lt;/li&gt;
&lt;li&gt;Como uma coisa se conecta com a outra&lt;/li&gt;
&lt;li&gt;O fluxo de alto nível&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Spec Driven Development no Frontend
&lt;/h2&gt;

&lt;p&gt;O mesmo padrão funcionou no frontend. Uma especificação para tela de candidaturas ficou assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Objetivo: Possibilitar que o contato de empresa logada visualize
os candidatos para uma determinada vaga.

Referências:
- A tela de listagem de candidaturas é essa: [componente]
- O endpoint que deve ser acessado é esse: [endpoint]
- Retorno do endpoint: [exemplo JSON]

Explicação de alto nível:
- Essa tela deve ser só para pessoa logada
- Os links de GitHub e LinkedIn apontam para endereços internos
  que retornam [formato X] - lidar com isso
- Fazer o link de visualizar candidaturas ir para essa nova tela
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eu entregava o endpoint, o retorno do endpoint, e pedia para codar a tela em função desse limite estabelecido.&lt;/p&gt;

&lt;h2&gt;
  
  
  A granularidade que funciona
&lt;/h2&gt;

&lt;p&gt;Esse é um tema importante citado no texto da ThoughtWorks. Minha observação não indica que pegar uma ideia de feature e investir tempo para o LLM planejar as tarefas seja o jeito mais eficiente.&lt;/p&gt;

&lt;p&gt;A granularidade que funciona para mim é a de &lt;strong&gt;Task&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Pensando nas nomenclaturas: se você tem Épico &amp;gt; História &amp;gt; Task (como no Jira), o que tem funcionado é pegar a Task e usar Spec Driven Development para ela. Não a feature inteira, não o épico - a task.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sobre ferramentas específicas
&lt;/h2&gt;

&lt;p&gt;Não usei nenhuma ferramenta dedicada a Spec Driven Development. Olhando as ferramentas, sinceramente não acho que precisa - mas não vou falar muito fortemente porque não usei a fundo. Os agentes de código que já existem (Claude Code, Codex, Gemini CLI) com um template minimamente razoável já fazem muito bem o trabalho.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parei de pedir testes de início
&lt;/h2&gt;

&lt;p&gt;Outra mudança: parei de pedir para escrever testes logo de cara. Prefiro primeiro ver o código gerado, e depois escrever os testes automatizados. Isso me deu mais controle sobre a qualidade final.&lt;/p&gt;

&lt;h2&gt;
  
  
  Além de código: documentação
&lt;/h2&gt;

&lt;p&gt;A mesma ideia funcionou para construir documentações. Spec Driven Development para gerar documentação significa: delinear o que preciso na documentação, como escrevo, meus padrões de escrita, o template - e deixar o agente gerar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;O padrão que funcionou para mim em Spec Driven Development foi:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pensar na tarefa&lt;/strong&gt; (não na feature inteira)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Definir os contratos de código&lt;/strong&gt; - classes, interfaces, assinaturas de métodos, parâmetros, retornos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escrever explicação de alto nível&lt;/strong&gt; - apenas o suficiente para contextualizar&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delegar detalhes de implementação&lt;/strong&gt; que não sei ou não me importo como são feitos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limitar a autonomia&lt;/strong&gt; do agente para o fluxo já delineado&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Não foi tentar fazer tudo em linguagem natural. Foi uma união entre estrutura de código que limita a autonomia e contexto em linguagem natural para o que precisa de explicação.&lt;/p&gt;

&lt;p&gt;É experiência de campo, de um projeto real que está no ar. Fiz muitas vezes - não foi uma nem duas - e esse é o setup que tem funcionado mais para mim quando penso em engenharia de contexto para agentes de código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dev + Eficiente
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Desenvolva software de alta qualidade e domine Engenharia de IA com o Dev + Eficiente.&lt;/strong&gt; Cursos práticos, acesso vitalício, comunidade ativa e acesso a vagas remotas exclusivas em diversas empresas de tecnologia. &lt;a href="https://deveficiente.com/" rel="noopener noreferrer"&gt;Sua jornada para se tornar um dev mais eficiente pode começar agora&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Semantic Cache: Como Otimizar Aplicações RAG com Cache Semântico</title>
      <dc:creator>Alberto Luiz Souza</dc:creator>
      <pubDate>Mon, 05 Jan 2026 10:00:15 +0000</pubDate>
      <link>https://dev.to/asouza/semantic-cache-como-otimizar-aplicacoes-rag-com-cache-semantico-4k84</link>
      <guid>https://dev.to/asouza/semantic-cache-como-otimizar-aplicacoes-rag-com-cache-semantico-4k84</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Este texto foi inicialmente concebido pela IA Generativa em função da transcrição de um vídeo do canal de Daniel Romero(a pessoa que lidera nossa especialização em Engenharia de IA). Se preferir acompanhar por vídeo, é só dar o play.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/BOInWQ2LJH0"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Ao trabalhar com aplicações baseadas em RAG (Retrieval-Augmented Generation), um dos desafios é lidar com o custo e a latência de processar perguntas repetidas. Cada vez que um usuário faz uma pergunta, todo o pipeline precisa ser executado novamente, mesmo que a resposta já tenha sido gerada anteriormente. Neste post, vamos explorar como o Semantic Cache pode resolver esse problema de forma elegante e eficiente.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é Cache?
&lt;/h2&gt;

&lt;p&gt;Um cache é uma memória de alta velocidade que armazena de forma eficiente os dados acessados com frequência. A ideia é simples: em vez de recalcular ou buscar uma informação toda vez que ela é solicitada, armazenamos o resultado para uso futuro.&lt;/p&gt;

&lt;h2&gt;
  
  
  O Pipeline RAG Tradicional
&lt;/h2&gt;

&lt;p&gt;Em um RAG tradicional, quando um usuário faz uma pergunta, o sistema executa várias etapas: faz o embedding da pergunta, pesquisa em um vector database (podendo realizar busca por palavra-chave, semântica ou híbrida), recupera os documentos relevantes, envia o contexto junto com o prompt e a pergunta original para o LLM, e finalmente retorna a resposta gerada ao usuário.&lt;/p&gt;

&lt;p&gt;Se o usuário fizer a mesma pergunta repetidamente, todo esse processo ocorre a cada requisição. Como você pode imaginar, isso é custoso tanto em termos de tempo quanto de dinheiro.&lt;/p&gt;

&lt;h2&gt;
  
  
  O Problema do Cache Tradicional
&lt;/h2&gt;

&lt;p&gt;Para evitar gerar a mesma resposta várias vezes para uma pergunta frequente, podemos armazenar as perguntas e suas respectivas respostas em um cache. Por exemplo, se o usuário perguntar "Qual é a capital do Brasil?" pela primeira vez, geramos a resposta seguindo o pipeline de RAG e salvamos no cache. Na próxima vez que a mesma pergunta for feita, recuperamos a resposta do cache.&lt;/p&gt;

&lt;p&gt;Esse tipo de cache é bastante comum e funciona com um mecanismo de chave-valor: a pergunta é a chave e a resposta é o valor. Porém, há um problema importante.&lt;/p&gt;

&lt;p&gt;Ao trabalhar com um cache do tipo key-value, pequenas variações na formulação de uma pergunta podem resultar em um valor de hash diferente. Por exemplo, "Qual é a capital do Brasil?" e "Você pode me dizer a capital do Brasil?" são essencialmente a mesma pergunta, mas sua formulação literal é diferente. Se usarmos uma abordagem simples para procurar a resposta no cache, provavelmente não vamos conseguir encontrar, porque a versão hash da pergunta é diferente.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Solução: Semantic Cache
&lt;/h2&gt;

&lt;p&gt;Para melhorar a precisão dos resultados da busca, podemos usar um cache semântico em vez de confiar em um mecanismo de combinação exata (Exact Match). Isso envolve armazenar as perguntas, respostas e seus embeddings em um mecanismo de chave-valor.&lt;/p&gt;

&lt;p&gt;Quando um usuário faz uma pergunta, podemos realizar uma busca semântica em todas as perguntas no cache para encontrar a mais semelhante. Se o score de similaridade entre a pergunta do usuário e a pergunta mais similar no cache estiver acima de um determinado limite, podemos assumir que a pergunta é essencialmente a mesma e fornecer a resposta correspondente.&lt;/p&gt;

&lt;p&gt;O cache tradicional opera com base em combinação exata: quando você procura uma chave, ele verifica se ela existe no cache. Já o cache semântico funciona de maneira diferente: ele pesquisa semanticamente, procurando o significado da chave em vez de uma combinação exata. Por exemplo, "Qual é a capital do Brasil?" versus "Me diga o nome da capital do Brasil" terão o mesmo resultado em um cache semântico, pois a formulação é diferente, mas o significado é o mesmo. Em contraste, um cache tradicional falharia para a segunda pergunta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vantagens e Considerações
&lt;/h2&gt;

&lt;p&gt;Se você estiver utilizando um LLM em um sistema de perguntas e respostas e tiver que fazer muitas chamadas para a API, essa operação vai custar caro. É aqui que uma solução de cache semântico se destaca, porque será extremamente eficiente e rápida, economizando tempo e dinheiro do projeto.&lt;/p&gt;

&lt;p&gt;Usar cache também é uma ótima maneira de otimizar o desempenho de chatbots, armazenando dados acessados com frequência. Uma abordagem interessante é criar patches ad-hoc para diálogos de chatbots, identificando perguntas feitas com frequência e preparando respostas pré-escritas. O chatbot pode recuperar rapidamente as respostas do cache e responder instantaneamente, sem acessar um LLM. Isso garante consistência nas respostas para perguntas como "Qual é o endereço da loja?".&lt;/p&gt;

&lt;p&gt;Por outro lado, usar cache pode não ser uma boa ideia se você quiser diferentes variações para a mesma consulta. No entanto, em um sistema de perguntas e respostas, a variação geralmente não importa.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementação Prática
&lt;/h2&gt;

&lt;p&gt;Em uma implementação prática, é possível utilizar o mesmo vector database tanto para armazenamento dos documentos quanto para o cache semântico. Por exemplo, utilizando Qdrant: o armazenamento vetorial com dados em cloud para busca semântica, e o cache com persistência em memória.&lt;/p&gt;

&lt;p&gt;Quando o usuário faz uma pergunta, é necessário fazer o embedding da pergunta. Essa parte deve ser feita independentemente de utilizar cache ou não, porque para fazer uma busca, tanto no vector database quanto no cache, são necessários embeddings. Lembrando que esse custo está bem reduzido se comparado com os LLMs.&lt;/p&gt;

&lt;p&gt;A função de cache verifica se a pergunta já foi respondida, buscando através de todos os embeddings e comparando com o embedding da pergunta. Se estiver no cache, retorna a resposta armazenada. É importante definir um limite adequado baseado na métrica utilizada. Por exemplo, com distância euclidiana, quanto menor o valor, melhor (mais próximo de zero significa maior similaridade). Se fosse similaridade do cosseno, números maiores significariam maior semelhança.&lt;/p&gt;

&lt;p&gt;Se a pergunta não existir no cache, o sistema passa pelo processo normal de RAG: busca semântica no vector database, encontra os chunks mais similares, envia como contexto junto com a consulta do usuário e o prompt para o LLM. Ao final, gera uma nova resposta e a salva no cache para uso futuro.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;O Semantic Cache é uma técnica poderosa para otimizar aplicações RAG, permitindo economia significativa de tempo e custos ao evitar processamentos redundantes. A chave está em entender que perguntas semanticamente equivalentes devem retornar a mesma resposta, mesmo quando formuladas de maneiras diferentes. &lt;/p&gt;

&lt;h2&gt;
  
  
  Dev+ Eficiente
&lt;/h2&gt;

&lt;p&gt;Este conteúdo é parte do ecossistema Dev+ Eficiente, mantido por Alberto junto com Maurício Aniche e Rafael Ponte, que inclui um canal e dois treinamentos. O primeiro é a Jornada Dev+ Eficiente, cujo foco é fazer com que você seja capaz de entregar software que de fato gera valor com o máximo de qualidade e eficiência. &lt;/p&gt;

&lt;p&gt;O segundo é a especialização em Engenharia de IA, uma parceria com Daniel Romero, cuja ideia é habilitar você para entregar software de excelência, integrando sistemas com LLMs. &lt;/p&gt;

&lt;p&gt;Conheça mais em &lt;a href="https://deveficiente.com/interesse-especializacao-engenharia-ia" rel="noopener noreferrer"&gt;https://deveficiente.com/interesse-especializacao-engenharia-ia&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>performance</category>
      <category>rag</category>
    </item>
    <item>
      <title>Como Criar um Chatbot com RAG do Zero: Guia Prático com OpenAI e Qdrant</title>
      <dc:creator>Alberto Luiz Souza</dc:creator>
      <pubDate>Mon, 29 Dec 2025 18:29:00 +0000</pubDate>
      <link>https://dev.to/asouza/como-criar-um-chatbot-com-rag-do-zero-guia-pratico-com-openai-e-qdrant-2fed</link>
      <guid>https://dev.to/asouza/como-criar-um-chatbot-com-rag-do-zero-guia-pratico-com-openai-e-qdrant-2fed</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Este texto foi inicialmente concebido pela IA Generativa em função da transcrição de um vídeo do canal de Daniel Romero(a pessoa que lidera nossa especialização em Engenharia de IA). Se preferir acompanhar por vídeo, é só dar o play.&lt;/p&gt;

&lt;p&gt;Um detalhe importante é que o vídeo exemplifica com LangChain e aqui nós preferimos deixar apenas com o suficiente. &lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/lAtA2nCTfF0"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Retrieval-Augmented Generation, ou simplesmente RAG, é uma técnica que tem revolucionado a forma como construímos aplicações de inteligência artificial. Neste post, vamos criar um chatbot do zero usando essa técnica — sem frameworks intermediários, direto nos SDKs. Ao final, você será capaz de criar um chatbot usando modelos GPT da OpenAI (ou alternativas como Groq) integrado a um banco de dados vetorial. Esse chatbot poderá responder perguntas relacionadas a qualquer documentação interna de uma empresa, por exemplo.&lt;/p&gt;

&lt;h2&gt;
  
  
  O Problema: Por Que LLMs Alucinam?
&lt;/h2&gt;

&lt;p&gt;Antes de colocar a mão na massa, vale entender por que precisamos do RAG em primeiro lugar.&lt;/p&gt;

&lt;p&gt;Aplicações mais simples fazem uma consulta direta em um LLM para obter respostas. Isso funciona bem para conhecimento geral ou informações que o modelo viu durante a fase de treino. O problema? Muitos LLMs simplesmente não viram informações suficientes sobre tópicos que gostaríamos de entender.&lt;/p&gt;

&lt;p&gt;Se você perguntar ao GPT-3.5 Turbo o que tem de tão especial no modelo Mistral 7B, provavelmente não vai receber uma boa resposta. O Mistral é um modelo de linguagem recente que não foi incluído nos dados de treino da maioria dos LLMs. Resultado: eles fornecem informações incorretas ou simplesmente inventam algo.&lt;/p&gt;

&lt;p&gt;Outro exemplo interessante: o Qdrant é um sistema de banco de dados que indexa e recupera dados vetoriais em alta dimensão. Porém, ao perguntar ao GPT-4 o que é Qdrant, ele pode dizer que não encontra informações sobre o termo e sugerir que você errou a digitação. Isso indica claramente que o modelo não tem ideia do que é Qdrant. O conhecimento de um LLM é limitado ao que foi aprendido durante o treinamento — ele não tem acesso ao mundo exterior.&lt;/p&gt;

&lt;p&gt;E sim, o termo técnico para esse comportamento é &lt;strong&gt;alucinação&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por Que Isso Acontece?
&lt;/h2&gt;

&lt;p&gt;LLMs alucinam porque dependem exclusivamente do conhecimento aprendido durante o processo de treino. O modelo não aprende explorando o mundo. Se algo não estiver em seus dados de treino, ele não vai saber — e mesmo que esteja, pode não ser preciso, levando a ambiguidades.&lt;/p&gt;

&lt;p&gt;O propósito de um LLM é comprimir as informações dos dados de treino em um modelo interno do mundo. Esse tipo de conhecimento é chamado de &lt;strong&gt;conhecimento paramétrico&lt;/strong&gt;, porque é armazenado nos parâmetros do modelo. E esses parâmetros são congelados após o treinamento, ou seja, o LLM não pode aprender coisas novas ou se adaptar a novas situações.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Solução: RAG
&lt;/h2&gt;

&lt;p&gt;É aqui que entra o RAG(Retrieval Augmented Generation) para apoiar na resolução desse problema. A ideia é adicionar um componente intermediário — que pode ser um Pipeline RAG, uma busca no Google, ou uma comunicação com uma fonte externa como um banco de dados SQL.&lt;/p&gt;

&lt;p&gt;Com o RAG, adicionamos um componente de memória externa que pode ser modificado e atualizado: uma espécie de memória de longo prazo. Isso permite que o sistema se adapte a novas situações, indo além do que o modelo aprendeu originalmente.&lt;/p&gt;

&lt;p&gt;No caso do RAG, é comum usar um banco de dados vetorial como memória externa. A vantagem? Podemos adicionar, excluir e gerenciar a memória e o conhecimento da aplicação. É quase como gerenciar ou atualizar informações no cérebro de uma pessoa — uma analogia um pouco distópica, mas que ilustra bem o conceito.&lt;/p&gt;

&lt;p&gt;Esse método é chamado de &lt;strong&gt;Source Knowledge&lt;/strong&gt;, diferente do conhecimento paramétrico, porque o conhecimento não é armazenado nos parâmetros do modelo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Construindo um Chatbot Básico
&lt;/h2&gt;

&lt;p&gt;Vamos à prática. Primeiro, instalamos os pacotes necessários:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;openai qdrant-client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para trabalhar com a API da OpenAI, o chatlog é representado como uma lista de dicionários. Cada dicionário contém uma &lt;code&gt;role&lt;/code&gt; (que pode ser &lt;code&gt;system&lt;/code&gt;, &lt;code&gt;user&lt;/code&gt; ou &lt;code&gt;assistant&lt;/code&gt;) e o &lt;code&gt;content&lt;/code&gt; com o texto correspondente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# usa a variável de ambiente OPENAI_API_KEY
&lt;/span&gt;
&lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Você é um assistente útil que responde a perguntas.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Olá, bot, como você está hoje?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estou bem, obrigado! Como posso ajudar?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Gostaria de entender o que é Machine Learning.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-3.5-turbo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para ver o texto da resposta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A resposta pode ser adicionada ao histórico para continuar a conversa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, se fizermos uma nova pergunta sobre "a diferença entre supervisionado e não supervisionado" — sem mencionar a palavra "aprendizado" — o modelo consegue manter o contexto e responder sobre "aprendizado supervisionado e não supervisionado". Isso mostra que o histórico de conversação está funcionando corretamente.&lt;/p&gt;

&lt;p&gt;Montar esse chatbot básico é relativamente fácil. Não tem nada complicado acontecendo aqui.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparando os Dados para o RAG
&lt;/h2&gt;

&lt;p&gt;Para adicionar conhecimento externo ao chatbot, precisamos de uma base de conhecimento. Neste exemplo, usamos um dataset do Hugging Face que contém o paper do Mistral 7B já dividido em chunks — ou seja, o texto do artigo já foi pré-processado e separado em pedaços menores, prontos para serem indexados.&lt;/p&gt;

&lt;p&gt;O dataset tem várias colunas (como &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;summary&lt;/code&gt;), mas para esse exemplo só precisamos de duas: &lt;code&gt;chunk&lt;/code&gt; (o pedaço de texto) e &lt;code&gt;source&lt;/code&gt; (a fonte de onde veio):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="c1"&gt;# Carrega o dataset e isola as colunas relevantes
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chunk&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;

&lt;span class="c1"&gt;# Cada registro contém o texto e sua origem
&lt;/span&gt;&lt;span class="n"&gt;chunks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chunk&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;sources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Gerando Embeddings
&lt;/h2&gt;

&lt;p&gt;Para indexar os chunks no banco de dados vetorial, precisamos transformá-los em vetores (embeddings). Usamos a API de embeddings da OpenAI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_embedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text-embedding-ada-002&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Integrando o Banco de Dados Vetorial
&lt;/h2&gt;

&lt;p&gt;Agora vamos adicionar tudo isso ao banco de dados vetorial. Usaremos o Qdrant diretamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;qdrant_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QdrantClient&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;qdrant_client.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VectorParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PointStruct&lt;/span&gt;

&lt;span class="c1"&gt;# Inicializa o cliente (em memória para este exemplo)
&lt;/span&gt;&lt;span class="n"&gt;qdrant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;QdrantClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;:memory:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Cria a coleção
&lt;/span&gt;&lt;span class="n"&gt;qdrant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chatbot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;vectors_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;VectorParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1536&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COSINE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora indexamos os chunks. Para cada chunk, geramos o embedding e inserimos no banco:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_embedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;PointStruct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;source&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;qdrant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chatbot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conectando a Base de Conhecimento ao LLM
&lt;/h2&gt;

&lt;p&gt;Estamos quase terminando. Falta conectar a base de conhecimento ao nosso LLM.&lt;/p&gt;

&lt;p&gt;Podemos testar a comunicação com o banco de dados vetorial executando uma consulta:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;O que tem de tão especial no Mistral 7B?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qdrant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chatbot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;query_vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;get_embedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso retorna os três chunks mais similares semanticamente à pergunta. Lembra que antes o LLM não conseguia responder essa pergunta? Agora é diferente — estamos obtendo chunks diretamente do artigo sobre o Mistral 7B.&lt;/p&gt;

&lt;p&gt;O resultado é útil, mas um pouco difícil de ler. Para resolver isso, deixamos o LLM processar essa informação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando o Prompt com RAG
&lt;/h2&gt;

&lt;p&gt;Configuramos uma função que recupera os itens mais relevantes do banco de dados vetorial e monta o prompt com contexto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;augmented_prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Recupera os chunks relevantes
&lt;/span&gt;    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qdrant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chatbot&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;query_vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;get_embedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Extrai o texto dos resultados
&lt;/span&gt;    &lt;span class="n"&gt;source_knowledge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="c1"&gt;# Monta o prompt com contexto
&lt;/span&gt;    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Use o contexto abaixo para responder a pergunta.

Contexto:
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;source_knowledge&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

Pergunta: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, no System Prompt, informamos ao LLM para utilizar o contexto para responder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;O que tem de tão especial no Mistral 7B?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Use o contexto abaixo para responder a pergunta.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;augmented_prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-3.5-turbo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E agora temos uma resposta baseada no conteúdo do paper: "Mistral 7B é um modelo de linguagem com 7 bilhões de parâmetros, projetado para oferecer desempenho superior e eficiência." Pelo menos ele não está dizendo que é um vinho!&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerações Sobre o RAG
&lt;/h2&gt;

&lt;p&gt;Implementar o RAG de forma ingênua — assumindo que toda consulta exige uma busca na base de conhecimento — nem sempre é necessário. Se um usuário cumprimentar o chatbot com "Oi, tudo bem? Como você está?", não faz sentido consultar uma base externa para responder.&lt;/p&gt;

&lt;p&gt;Além disso, o tempo de inferência pode ser lento dependendo do modelo e da API escolhida. Essa é uma desvantagem, mas os benefícios compensam:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Melhor desempenho de retrieval&lt;/li&gt;
&lt;li&gt;Maior precisão nas respostas&lt;/li&gt;
&lt;li&gt;Possibilidade de fornecer citações das fontes&lt;/li&gt;
&lt;li&gt;Mais rápido e eficiente que outras abordagens, como Agents&lt;/li&gt;
&lt;li&gt;Controle sobre o número de tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Alternativa com Groq para Inferência Rápida
&lt;/h2&gt;

&lt;p&gt;Pensando em aplicações reais, usar apenas a OpenAI pode trazer dois problemas: custo (que sobe rapidamente) e tempo de inferência (às vezes crítico).&lt;/p&gt;

&lt;p&gt;Uma alternativa com inferência muito mais rápida é o Groq, capaz de gerar cerca de 800 tokens por segundo. Para usá-lo, basta instalar o pacote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;groq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O SDK do Groq segue a mesma estrutura da OpenAI, então a migração é simples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;groq&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Groq&lt;/span&gt;

&lt;span class="n"&gt;groq_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Groq&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# usa a variável de ambiente GROQ_API_KEY
&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;groq_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama-3.1-70b-versatile&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A execução é muito mais rápida que o GPT. E como ambos os SDKs seguem a mesma interface, podemos reutilizar exatamente a mesma estrutura de mensagens e a função &lt;code&gt;augmented_prompt&lt;/code&gt; que criamos antes — basta trocar o cliente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Um pipeline RAG basicamente recupera informações, utiliza essas informações como contexto e gera respostas. Essa abordagem resolve o problema fundamental das alucinações em LLMs ao adicionar uma fonte de conhecimento externa que pode ser atualizada e gerenciada independentemente do modelo.&lt;/p&gt;

&lt;p&gt;Os pontos principais:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LLMs têm conhecimento limitado ao que foi aprendido durante o treinamento (conhecimento paramétrico)&lt;/li&gt;
&lt;li&gt;O RAG adiciona uma "memória de longo prazo" que pode ser modificada (Source Knowledge)&lt;/li&gt;
&lt;li&gt;Bancos de dados vetoriais são a escolha comum para armazenar esse conhecimento&lt;/li&gt;
&lt;li&gt;Os SDKs da OpenAI e Groq seguem interfaces similares, facilitando a troca entre provedores&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Especialização em Engenharia de IA
&lt;/h2&gt;

&lt;p&gt;Este conteúdo é um trecho de uma das aulas da Especialização em Engenharia de IA, uma parceria com a Dev Mais Eficiente. O curso aborda RAG, Vector Search, Busca Híbrida, Agents, Tools e muito mais, sempre com aulas 100% práticas e com exemplos reais.&lt;/p&gt;

&lt;p&gt;Faça sua inscrição em &lt;a href="https://deveficiente.com/especializacao-engenharia-ia" rel="noopener noreferrer"&gt;https://deveficiente.com/especializacao-engenharia-ia&lt;/a&gt; .&lt;/p&gt;

</description>
      <category>openai</category>
      <category>rag</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Como Implementar um Sistema RAG do Zero em Python</title>
      <dc:creator>Alberto Luiz Souza</dc:creator>
      <pubDate>Mon, 22 Dec 2025 18:15:40 +0000</pubDate>
      <link>https://dev.to/asouza/como-implementar-um-sistema-rag-do-zero-em-python-1ej7</link>
      <guid>https://dev.to/asouza/como-implementar-um-sistema-rag-do-zero-em-python-1ej7</guid>
      <description>&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Este texto foi inicialmente concebido pela IA Generativa em função da transcrição de um vídeo do canal de Daniel Romero(a pessoa que lidera nossa especialização em Engenharia de IA). Se preferir acompanhar por vídeo, é só dar o play.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/0aFpP3-wap0"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;RAG (Retrieval-Augmented Generation) é uma técnica que combina busca por similaridade com geração de texto por LLMs para criar respostas mais precisas e contextualizadas. Neste post, vamos implementar um sistema RAG simples do zero, usando apenas três bibliotecas: NumPy, Sentence Transformers e Grok.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que vamos construir
&lt;/h2&gt;

&lt;p&gt;Nosso sistema RAG terá três componentes principais: geração de embeddings para os documentos, busca por similaridade usando similaridade do cosseno e geração de resposta usando um LLM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuração inicial
&lt;/h2&gt;

&lt;p&gt;Para este exemplo, precisamos instalar apenas três bibliotecas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;numpy sentence-transformers grok
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos trabalhar com o básico, sem banco vetorial por enquanto. NumPy será usado para os cálculos, Sentence Transformers para os embeddings e Grok para o LLM.&lt;/p&gt;

&lt;p&gt;Começamos com os imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sentence_transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SentenceTransformer&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;grok&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Grok&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Carregando o modelo e gerando embeddings
&lt;/h2&gt;

&lt;p&gt;O modelo que vamos utilizar é o &lt;code&gt;all-MiniLM-L6-v2&lt;/code&gt;. Ele é pequeno, rápido e muito eficiente. Vale destacar que esse modelo funciona bem apenas para o idioma inglês, então para produção com conteúdo em português seria necessário trocar de modelo.&lt;/p&gt;

&lt;p&gt;Um detalhe importante: esses modelos de embeddings são treinados olhando para milhões de pares de textos. Alguns pares são positivos, como duas frases que querem dizer a mesma coisa, ou uma pergunta com a resposta certa. Outros pares são negativos, com duas frases sem relação nenhuma. O treino funciona basicamente dizendo para o modelo: "esses dois aqui têm que ficar perto, e esses outros aqui têm que ficar distantes". Depois de repetir isso milhares de vezes, o modelo aprende a transformar qualquer texto em um vetor de números que preserva o sentido.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SentenceTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;all-MiniLM-L6-v2&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Grok&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Seus documentos (fonte de conhecimento)
&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="c1"&gt;# Lista de documentos sobre machine learning
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Gerar embeddings de todos os documentos
&lt;/span&gt;&lt;span class="n"&gt;doc_embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com essa única linha, todos os documentos se transformam em vetores numéricos. No caso do &lt;code&gt;all-MiniLM-L6-v2&lt;/code&gt;, cada documento tem 384 dimensões do tipo float32. Como não temos um banco vetorial neste momento, esses vetores ficam guardados na memória.&lt;/p&gt;

&lt;h2&gt;
  
  
  Entendendo a similaridade do cosseno
&lt;/h2&gt;

&lt;p&gt;Uma das partes mais importantes é como medir a distância entre dois textos. Para resolver isso, implementamos a similaridade do cosseno.&lt;/p&gt;

&lt;p&gt;A fórmula da similaridade do cosseno é expressa como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;similarity(A, B) = cos(θ) = (A · B) / (||A|| × ||B||)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O numerador &lt;code&gt;A · B&lt;/code&gt; representa o produto escalar dos vetores A e B, calculado multiplicando cada elemento de A pelo elemento correspondente de B e somando todos esses produtos. No denominador, temos o produto das normas euclidianas dos dois vetores.&lt;/p&gt;

&lt;p&gt;Geometricamente, essa fórmula calcula o cosseno do ângulo θ entre os dois vetores no espaço n-dimensional. Quando θ é igual a zero graus, os vetores apontam na mesma direção e o cosseno vale 1, indicando máxima similaridade. Quando θ é igual a 90 graus, os vetores são perpendiculares e o cosseno vale zero, indicando nenhuma similaridade.&lt;/p&gt;

&lt;p&gt;Veja um exemplo prático:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;v2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Produto escalar
&lt;/span&gt;&lt;span class="n"&gt;dot_product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Resultado: 32
&lt;/span&gt;
&lt;span class="c1"&gt;# Magnitude (norma euclidiana)
&lt;/span&gt;&lt;span class="n"&gt;magnitude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Similaridade do cosseno
&lt;/span&gt;&lt;span class="n"&gt;similarity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dot_product&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;magnitude&lt;/span&gt;  &lt;span class="c1"&gt;# Resultado: 0.97 (97% de similaridade)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa etapa final mede o quanto os vetores v1 e v2 estão na mesma direção.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementando as funções do RAG
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Função de similaridade do cosseno
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cosine_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Função de recuperação de documentos
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Gera o embedding da query
&lt;/span&gt;    &lt;span class="n"&gt;query_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Calcula similaridade com todos os documentos
&lt;/span&gt;    &lt;span class="n"&gt;similarities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc_embedding&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc_embeddings&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;sim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cosine_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query_embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;doc_embedding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;similarities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sim&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Ordena pela similaridade (maior primeiro)
&lt;/span&gt;    &lt;span class="n"&gt;similarities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Retorna os top_k documentos mais relevantes
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;sim&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sim&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;similarities&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Função de geração de resposta
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_answer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retrieved_docs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Junta os documentos em um contexto único
&lt;/span&gt;    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;retrieved_docs&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama-3.1-8b-instant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Você é um especialista em machine learning. Use apenas o contexto fornecido para responder as perguntas.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Contexto fornecido:&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;Pergunta do usuário: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A temperatura zero garante que as respostas sejam mais determinísticas e focadas no contexto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Função principal RAG
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Recupera os documentos mais relevantes
&lt;/span&gt;    &lt;span class="n"&gt;retrieved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Gera a resposta com o LLM
&lt;/span&gt;    &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_answer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retrieved&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retrieved&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testando o sistema
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;rag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;O que é machine learning?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Mostra os documentos recuperados com suas similaridades
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;similarity&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;similarity&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;Em projetos mais complexos, temos ainda mais desafios. Teríamos um banco de dados vetorial, estratégia de extração de conteúdo, chunking, filtros, metadados e muito mais. Mas essa é a base, e agora você entende como o RAG funciona na prática.&lt;/p&gt;

&lt;h2&gt;
  
  
  Especialização em Engenharia de IA
&lt;/h2&gt;

&lt;p&gt;Este conteúdo é um trecho de uma das aulas da Especialização em Engenharia de IA, uma parceria com a Dev Mais Eficiente. O curso aborda RAG, Vector Search, Busca Híbrida, Agents, Tools e muito mais, sempre com aulas 100% práticas e com exemplos reais.&lt;/p&gt;

&lt;p&gt;Faça sua inscrição em &lt;a href="https://deveficiente.com/especializacao-engenharia-ia" rel="noopener noreferrer"&gt;https://deveficiente.com/especializacao-engenharia-ia&lt;/a&gt; .&lt;/p&gt;

</description>
      <category>rag</category>
      <category>python</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
