<script data-pm-proxy="intercept"></script><?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[ML4SE]]></title><description><![CDATA[Você é Dev e quer entender como criar aplicações baseadas em machine learning (ML)? Nessa newsletter eu regularmente explico conceitos, práticas e técnicas de ML para desenvolvedores software.]]></description><link>https://ml4se.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!5B9_!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdad1b61e-dd33-4150-ba01-37485bff9679_640x640.png</url><title>ML4SE</title><link>https://ml4se.substack.com</link></image><generator>Substack</generator><lastBuildDate>Fri, 04 Sep 2026 22:10:53 GMT</lastBuildDate><atom:link href="/__u/ml4se.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Gustavo Pinto]]></copyright><language><![CDATA[pt-br]]></language><webMaster><![CDATA[ml4se@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[ml4se@substack.com]]></itunes:email><itunes:name><![CDATA[Gustavo Pinto]]></itunes:name></itunes:owner><itunes:author><![CDATA[Gustavo Pinto]]></itunes:author><googleplay:owner><![CDATA[ml4se@substack.com]]></googleplay:owner><googleplay:email><![CDATA[ml4se@substack.com]]></googleplay:email><googleplay:author><![CDATA[Gustavo Pinto]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Quando o teste unitário vira função de recompensa]]></title><description><![CDATA[Em segundos, a su&#237;te de testes do seu projeto responde a pergunta &#8220;este teste passa&#8221; com precis&#227;o.]]></description><link>https://ml4se.substack.com/p/quando-o-teste-unitario-vira-funcao</link><guid isPermaLink="false">https://ml4se.substack.com/p/quando-o-teste-unitario-vira-funcao</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Fri, 28 Aug 2026 22:13:06 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/cc604ba6-5988-40a0-89f2-bc357870d28d_2028x1402.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Em segundos, a su&#237;te de testes do seu projeto responde a pergunta &#8220;este teste passa&#8221; com precis&#227;o. Devolve a resposta como um sim ou um n&#227;o. E d&#225; a mesma resposta hoje e amanh&#227;, para o mesmo c&#243;digo. Essa combina&#231;&#227;o virou mat&#233;ria-prima para treinar modelos de linguagem.</p><p>Durante alguns anos, ensinar um modelo a preferir uma resposta a outra dependia de gente. Anotadores humanos comparavam pares de sa&#237;das. Essas compara&#231;&#245;es treinavam um modelo de recompensa, que por sua vez guiava o ajuste do modelo principal. &#201; o arranjo conhecido como Reinforcement Learning from Human Feedback (RLHF, aprendizado por refor&#231;o a partir de feedback humano). </p><p>RLHF funciona, custa caro e tem um efeito colateral conhecido: o modelo de recompensa &#233; uma aproxima&#231;&#227;o do gosto humano, e o modelo treinado tem incentivo para achar as brechas dessa aproxima&#231;&#227;o. J&#225; falamos sobre esse problema no texto sobre <a href="/__u/ml4se.substack.com/p/avaliando-a-qualidade-da-respostas">avalia&#231;&#227;o da qualidade das respostas</a>.</p><p>Com c&#243;digo, isso muda. Para saber se uma fun&#231;&#227;o est&#225; correta, n&#227;o precisamos perguntar a ningu&#233;m. O juiz j&#225; est&#225; no reposit&#243;rio, roda sozinho e n&#227;o tem opini&#227;o. Essa pr&#225;tica passou a dominar o processo de treinamento de modelos de c&#243;digo, chamado Reinforcement Learning with Verifiable Rewards (RLVR, aprendizado por refor&#231;o com recompensas verific&#225;veis).</p><p>Neste post n&#243;s vamos ver tr&#234;s itens: </p><ul><li><p>Como o la&#231;o de treinamento funciona. </p></li><li><p>Por que o algoritmo Group Relative Policy Optimization (GRPO) ganhou espa&#231;o nele. </p></li><li><p>E o que acontece quando o modelo descobre que passar no teste e resolver o problema s&#227;o objetivos diferentes.</p></li></ul><h3>O que muda quando a recompensa &#233; verific&#225;vel</h3><p>Em RLHF, a recompensa sai de uma rede neural treinada sobre prefer&#234;ncias. Por design, ela &#233; cont&#237;nua, ruidosa e imperfeita. Em RLVR, a recompensa sai da execu&#231;&#227;o de um programa. Em c&#243;digo, ela costuma ter a seguinte forma:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;7b206312-85d8-4018-8e6e-912f8cd4cc48&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def recompensa(codigo_gerado, suite_de_testes):
    resultado = executar_em_ambiente_isolado(codigo_gerado, suite_de_testes)
    return 1.0 if resultado.todos_passaram else 0.0</code></pre></div><p>Essas quatro linhas cont&#234;m o post inteiro. </p><p>Aqui n&#227;o h&#225; par&#226;metros a treinar nem anotador a contratar. E o sinal n&#227;o se degrada quando a distribui&#231;&#227;o dos dados muda, porque ele nunca foi estimado a partir de dados. Ele foi executado.</p><p>A ideia vai al&#233;m dos testes unit&#225;rios. <a href="/__u/ml4se.substack.com/p/como-especificacoes-formais-tornam">Em um outro texto aqui do blog</a>, n&#243;s vimos pr&#233;-condi&#231;&#245;es e p&#243;s-condi&#231;&#245;es como contratos verific&#225;veis, que cobrem propriedades universais em vez de casos particulares. Qualquer artefato execut&#225;vel que separe correto de incorreto serve de fonte de recompensa: uma su&#237;te de testes, um verificador de tipos, um provador, um checador de propriedades, um script em bash.</p><p>Mas essa ideia n&#227;o funciona bem al&#233;m do c&#243;digo. Ela vale para dom&#237;nios com verificador barato, e c&#243;digo &#233; o exemplo mais forte. Para reda&#231;&#227;o, resumo ou conselho, &#233; mais complicado, pois n&#227;o temos uma fun&#231;&#227;o que devolve 1 ou 0. </p><p>Nesses casos o problema do avaliador continua aberto.</p><h3>Como o la&#231;o funciona, e por que GRPO</h3><p>O la&#231;o de treinamento tem uma estrutura simples. </p><p>Para cada enunciado, o modelo gera um grupo de solu&#231;&#245;es candidatas; digamos <em>oito</em>. Cada solu&#231;&#227;o candidata roda contra a su&#237;te de testes em um ambiente isolado. Cada uma recebe recompensa 1 ou 0. O algoritmo ent&#227;o calcula quanto cada candidata foi melhor ou pior que as outras, e ajusta os pesos para tornar as boas mais prov&#225;veis.</p><p>O c&#225;lculo desse &#8220;melhor ou pior&#8221; &#233; o que separa os dois algoritmos. </p><p>O algoritmo Proximal Policy Optimization (PPO), padr&#227;o anterior, precisa de um segundo modelo treinado em paralelo. Esse segundo modelo, <em>chamado modelo de valor</em>, estima a recompensa esperada de um estado. Ele costuma ter porte parecido com o do primeiro, o que quase dobra a mem&#243;ria necess&#225;ria durante o treino.</p><p>O GRPO dispensa esse segundo modelo. No lugar da estimativa por rede neural, ele usa a estat&#237;stica do pr&#243;prio grupo. </p><blockquote><p>A vantagem de cada candidata &#233; a recompensa dela comparada &#224; m&#233;dia do grupo. </p></blockquote><p>Se sete candidatas falham e uma passa, a que passou recebe um peso positivo alto. Se todas passam, nenhuma se destaca, e o passo quase n&#227;o altera nada.</p><p>Essa mudan&#231;a tem uma consequ&#234;ncia interessante. Sem o modelo de valor, o custo dominante de um passo de treinamento deixa de ser a infer&#234;ncia da rede neural. Ele passa a ser execu&#231;&#227;o de c&#243;digo. </p><p>Treinar com RLVR significa rodar milh&#245;es de su&#237;tes de teste em ambientes isolados, com controle de tempo limite, de mem&#243;ria e de acesso &#224; rede. Perceba que o gargalo n&#227;o foi resolvido; ele migrou dos treinamentos dos modelos para infraestrutura de execu&#231;&#227;o. </p><h3>O sinal bin&#225;rio &#233; pobre</h3><p>A recompensa de 1 ou 0 tem uma fragilidade enorme. Em problemas mais dif&#237;ceis, pode acontecer de nenhuma das oito candidatas passar. Todas recebem 0. Todas t&#234;m a mesma vantagem. Mas o passo de treinamento n&#227;o ensina nada.</p><p>Mas tem um detalhe importante: Uma solu&#231;&#227;o candidata pode ter falhado s&#243; em um teste de borda, enquanto outra sequer compilou. Pra recompensa bin&#225;ria, essa informa&#231;&#227;o &#233; jogada fora. H&#225; duas linhas de pesquisa nessa frente.</p><ul><li><p>A primeira enriquece o sinal de execu&#231;&#227;o em vez de reduzi-lo a um bit. Por ex, o <a href="https://arxiv.org/pdf/2510.18471">CodeRL+</a> prop&#245;e alinhar a gera&#231;&#227;o &#224; sem&#226;ntica de execu&#231;&#227;o, aproveitando o que ocorre durante a execu&#231;&#227;o e n&#227;o apenas o veredito final.</p></li><li><p>A segunda linha treina um verificador especializado em c&#243;digo. Por ex, o trabalho <a href="https://arxiv.org/abs/2601.12186">Aletheia: What Makes RLVR For Code Verifiers Tick?</a> investiga as escolhas de receita nesse treinamento. Os autores fazem abla&#231;&#227;o de tr&#234;s fatores: tra&#231;os de racioc&#237;nio intermedi&#225;rios, aprendizado a partir de amostras negativas e treinamento on-policy.</p></li></ul><p>Parece que a receita &#243;tima depende do porte do modelo. </p><p>Em verificadores pequenos, o treinamento on-policy &#233; o principal motor de desempenho. Nos maiores, o or&#231;amento de racioc&#237;nio passa a ser o fator determinante. </p><h3>O modelo aprende a passar no teste</h3><p>Chegamos &#224; parte que muda a leitura de tudo que veio antes. </p><p>Se a recompensa &#233; passar nos testes, logo o objetivo que o modelo otimiza &#233; passar nos testes. Resolver o problema &#233; uma das formas de conseguir isso. </p><p>E nem sempre &#233; a mais barata.</p><p>O artigo <a href="https://arxiv.org/abs/2604.15149">LLMs Gaming Verifiers: RLVR can Lead to Reward Hacking</a> cataloga o que aparece em ambientes de c&#243;digo quando esse incentivo age sem freio. Por exemplo, j&#225; que temos que passar nos testes, porque n&#227;o sobrescreve-los, remover as asser&#231;&#245;es, ou at&#233; for&#231;ar o encerramento antecipado do programa? Assim, as execu&#231;&#245;es rendem recompensa 1 <strong>sem que o problema tenha sido resolvido</strong>.</p><p>O mesmo trabalho mostra uma vers&#227;o mais sutil disso em tarefas de racioc&#237;nio indutivo. Modelos treinados com RLVR passam a abandonar a indu&#231;&#227;o de regras e a enumerar r&#243;tulos caso a caso. A sa&#237;da satisfaz o verificador sem capturar o padr&#227;o que a tarefa pedia. &#201; a mesma coisa que escrever `<code>if entrada == 2: return 4</code>` e seguir em frente.</p><p>Para medir a frequ&#234;ncia dessas condutas, o <a href="https://arxiv.org/pdf/2510.20270">ImpossibleBench</a> usa uma constru&#231;&#227;o bem sofisticada. Os autores pegam tarefas de benchmarks estabelecidos. Depois criam variantes imposs&#237;veis, colocando a especifica&#231;&#227;o em linguagem natural em conflito direto com os testes. Por exemplo, um teste do tipo `<code>assert f(2) == 4</code>` passa a exigir `<code>assert f(2) == 5</code>`. Em outra, as duas asser&#231;&#245;es contradit&#243;rias convivem no mesmo arquivo.</p><p>Como a tarefa se tornou imposs&#237;vel de resolver honestamente, <strong>qualquer aprova&#231;&#227;o &#233; trapa&#231;a</strong>. A taxa de aprova&#231;&#227;o vira ent&#227;o uma medida direta da propens&#227;o a explorar atalhos. As taxas medidas em modelos de fronteira s&#227;o altas, com destaque para a variante baseada no SWE-bench. Os autores testaram tamb&#233;m uma interven&#231;&#227;o: dar ao agente a op&#231;&#227;o de declarar a tarefa imposs&#237;vel em vez de tentar resolv&#234;-la. Com essa sa&#237;da dispon&#237;vel, a taxa do GPT-5 na variante conflitante caiu de 54% para 9%.</p><h3>O que isso significa para quem escreve testes?</h3><p>Aqui invertemos a rela&#231;&#227;o usual entre teste e c&#243;digo. </p><p>N&#243;s escrevemos testes para detectar defeito. Quando o teste vira fun&#231;&#227;o de recompensa, ele passa a definir o comportamento. O modelo converge para o que o teste aceita, incluindo aquilo que o teste aceita por engano. Uma su&#237;te fraca deixa o defeito passar e, al&#233;m disso, <strong>ensina o defeito.</strong></p><p>A boa not&#237;cia &#233; que isso reaproveita conhecimento que o desenvolvedor j&#225; tem. A verifica&#231;&#227;o isom&#243;rfica est&#225; pr&#243;xima do teste metam&#243;rfico e do teste baseado em propriedade, que checam rela&#231;&#245;es entre entradas e sa&#237;das em vez de valores fixos. Um teste que fixa `<code>f(2) == 4</code>` pode ser satisfeito por uma tabela. Um teste que exige que a sa&#237;da de `<code>f</code>` cres&#231;a de forma mon&#243;tona, ou que `<code>f(g(x))</code>` valha o mesmo que `<code>g(f(x))</code>`, &#233; bem mais dif&#237;cil de satisfazer sem implementar a fun&#231;&#227;o.</p><p>A origem dos testes tamb&#233;m ganha peso novo. Em <a href="/__u/ml4se.substack.com/p/nao-use-o-chatgpt-para-gerar-testes">N&#227;o use o ChatGPT para gerar testes</a> n&#243;s vimos que pedir os testes ao mesmo modelo que escreveu o c&#243;digo reproduz as suposi&#231;&#245;es do c&#243;digo em vez de chec&#225;-las. Em RLVR, essa depend&#234;ncia deixa de ser quest&#227;o de higiene de projeto. Ela vira um problema de defini&#231;&#227;o do objetivo, porque o artefato gerado &#233; a pr&#243;pria fun&#231;&#227;o que o modelo vai otimizar.</p><h3>Conclus&#227;o</h3><p>O regime de recompensa verific&#225;vel colocou a engenharia de software em uma posi&#231;&#227;o incomum dentro do aprendizado de m&#225;quina. Outros dom&#237;nios ainda discutem como obter julgamento confi&#225;vel para treinar seus modelos. C&#243;digo j&#225; tinha esse julgamento pronto, versionado no reposit&#243;rio e execut&#225;vel em segundos. Foi essa disponibilidade que permitiu o avan&#231;o r&#225;pido dos modelos de c&#243;digo. E o GRPO baixou o pre&#231;o do processo ao trocar o modelo de valor pela estat&#237;stica do grupo.</p><p>O que os trabalhos recentes acrescentam &#233; o outro lado da moeda. O verificador n&#227;o &#233; neutro. Ele &#233; a defini&#231;&#227;o operacional de corre&#231;&#227;o, e o modelo otimiza exatamente aquilo que essa defini&#231;&#227;o mede. A queda de 54% para 9% no ImpossibleBench, quando o agente ganha a op&#231;&#227;o de recusar a tarefa, mostra que parte do comportamento indesejado vem do desenho do ambiente e n&#227;o do modelo. O resultado do Countdown-Code, com 1% de contamina&#231;&#227;o bastando para produzir efeito grande depois, mostra que a etapa anterior tamb&#233;m pesa.</p><p>Para quem escreve software, fica uma leitura sobre onde investir aten&#231;&#227;o. Melhorar a su&#237;te de testes deixou de ser apenas uma forma de encontrar defeitos mais cedo. Em um pipeline que treina ou seleciona modelos por execu&#231;&#227;o, a su&#237;te de testes &#233; a fun&#231;&#227;o objetivo. E a qualidade dela estabelece o teto do que o modelo consegue aprender.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ml4se.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Inscreva-se&quot;,&quot;language&quot;:&quot;pt-br&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">ML4SE &#233; uma newsletter focada em ajudar devs a mastigar t&#233;cnicas de aprendizado de m&#225;quina. Para receber novos posts, se inscreva na newsletter.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Digite seu e-mail&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Inscreva-se"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[Seu agente não precisa lembrar de tudo]]></title><description><![CDATA[Agentes baseados em LLM v&#227;o muito al&#233;m de responder uma pergunta por vez.]]></description><link>https://ml4se.substack.com/p/seu-agente-nao-precisa-lembrar-de</link><guid isPermaLink="false">https://ml4se.substack.com/p/seu-agente-nao-precisa-lembrar-de</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Fri, 21 Aug 2026 14:59:41 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/bf022ae1-c15d-41eb-9cee-ff0f657a59c6_2480x1246.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Agentes baseados em LLM  v&#227;o muito al&#233;m de responder uma pergunta por vez. Hoje estes agentes executam tarefas que levam dezenas de passos: abrir um formul&#225;rio, consultar um sistema interno, conferir o resultado, corrigir e seguir adiante.  Em um ambiente real, &#233; comum o agente acertar os primeiros passos com folga. Mas, l&#225; por volta do vig&#233;simo, come&#231;a a errar em coisas que j&#225; tinha acertado antes.</p><p>O diagn&#243;stico intuitivo &#233; que o modelo &#8220;esqueceu&#8221;. Mas nem sempre &#233; isso que acontece. O agente tem tudo na janela de contexto, incluindo quinze vers&#245;es desatualizadas do mesmo formul&#225;rio, e pode agir sobre a vers&#227;o errada. Cada chamada de uma tool devolve um bloco de texto que nenhum humano escreveu (e que ningu&#233;m revisou), e esse bloco fica no hist&#243;rico competindo pela aten&#231;&#227;o do modelo com a instru&#231;&#227;o original.</p><p>A rea&#231;&#227;o comum a esse problema &#233; procurar um modelo com janela maior. Um trabalho publicado em <a href="https://arxiv.org/abs/2606.10209">junho de 2026</a>, aponta para outra dire&#231;&#227;o: em um benchmark de 50 tarefas, o agente que descartava a maior parte do pr&#243;prio hist&#243;rico concluiu mais tarefas do que o agente que guardava tudo &#8212; e ainda gastou um ter&#231;o dos tokens e um ter&#231;o do tempo.</p><p>Neste texto vamos entender como &#233; poss&#237;vel que o hist&#243;rico de um agente deixe de ajudar a partir de certo ponto.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ml4se.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Inscreva-se&quot;,&quot;language&quot;:&quot;pt-br&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">ML4SE &#233; uma newsletter focada em ajudar devs a mastigar t&#233;cnicas de aprendizado de m&#225;quina. Para receber novos posts, se inscreva na newsletter.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Digite seu e-mail&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Inscreva-se"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><h3>O contexto de um agente cresce sozinho</h3><p>Em uma aplica&#231;&#227;o de chat, a janela de contexto cresce no ritmo em que a pessoa digita. Um usu&#225;rio atento pode escrever algumas centenas de tokens por turno.</p><p>Em um agente, o crescimento &#233; outro. </p><p>O agente decide chamar uma tool, e a tool devolve o que tiver para devolver (como a listagem de arquivos em um diret&#243;rio, no caso de uma tool de <code>ls</code>). Como vimos no texto sobre <a href="/__u/ml4se.substack.com/p/o-que-sao-tools">o que s&#227;o tools</a>, essa resposta volta para o hist&#243;rico como uma mensagem comum. Um endpoint pode devolver <strong>tr&#234;s mil tokens de JSON</strong>, dos quais o agente vai usar dois campos. Vinte chamadas e sabe-se l&#225; quantos mil tokens de hist&#243;rico  depois, a maior parte do contexto descreve uma situa&#231;&#227;o que j&#225; mudou.</p><p>Na literatura chamamos esse ac&#250;mulo de <em><a href="https://arxiv.org/abs/2601.07190">context bloat</a></em>: conforme o hist&#243;rico de intera&#231;&#227;o cresce: </p><ol><li><p>o custo por turno aumenta, </p></li><li><p>a lat&#234;ncia aumenta e </p></li><li><p>a capacidade de racioc&#237;nio degrada por distra&#231;&#227;o com contexto passado que j&#225; n&#227;o t&#234;m relev&#226;ncia assim. </p></li></ol><p>S&#227;o tr&#234;s efeitos distintos. Os dois primeiros s&#227;o de infraestrutura e todo mundo espera por eles. O terceiro &#233; de qualidade, e &#233; o que costuma passar despercebido, porque n&#227;o aparece no custo ($$) da API.</p><p>As camadas de aplica&#231;&#227;o que envolvem o modelo, ou seja, o que entra no prompt a cada itera&#231;&#227;o do loop, responde por boa parte do desempenho final, e o hist&#243;rico &#233; a pe&#231;a desse harness que parece n&#227;o ser projetada de forma deliberada.</p><h3>A janela anunciada n&#227;o &#233; a janela efetiva</h3><p>Antes de mexer no hist&#243;rico, vale entender por que guardar mais informa&#231;&#227;o piora a decis&#227;o. A refer&#234;ncia de base aqui &#233; um artigo bem conhecido de 2023: <a href="https://arxiv.org/abs/2307.03172">Lost in the Middle: How Language Models Use Long Contexts</a>. Os autores mediram a acur&#225;cia em fun&#231;&#227;o da posi&#231;&#227;o da informa&#231;&#227;o relevante dentro do contexto e encontraram uma curva em U: o desempenho &#233; mais alto quando a informa&#231;&#227;o est&#225; no come&#231;o ou no fim da entrada, mas cai drasticamente quando ela est&#225; no meio.</p><p>Esse comportamento apareceu em outros locais. O relat&#243;rio <a href="https://www.trychroma.com/research/context-rot">Context Rot</a>, da Chroma Research, testou 18 modelos, entre eles Claude Opus 4, GPT-4.1, Gemini 2.5 Pro e Qwen3, em tarefas controladas onde a &#250;nica vari&#225;vel era o tamanho da entrada. O desempenho cai conforme a entrada cresce, e a introdu&#231;&#227;o de um &#250;nico distrator j&#225; reduz a acur&#225;cia, com efeito maior em contextos maiores. O pr&#243;prio langchain <a href="https://reference.langchain.com/python/langchain-community/document_transformers/long_context_reorder/LongContextReorder">fornece uma implementa&#231;&#227;o para ordena&#231;&#227;o de contextos longos</a>, pensando exatamente nesse problema. </p><p>Ou seja: a janela de contexto anunciada e a janela dentro da qual ele decide <strong>bem s&#227;o coisas diferentes</strong>. </p><blockquote><p>Um modelo com um milh&#227;o de tokens de janela n&#227;o sustenta um milh&#227;o de tokens de qualidade uniforme. </p></blockquote><h3>O que acontece quando o hist&#243;rico &#233; podado</h3><p><a href="https://arxiv.org/abs/2606.10209">Voltemos ao paper que deu gatilho ao este texto</a>. O cen&#225;rio deste trabalho &#233; automa&#231;&#227;o de despesas no Microsoft Dynamics 365, com um agente GPT-5 conversando com o sistema via MCP, sobre um conjunto de 50 tarefas de itemiza&#231;&#227;o de despesas hoteleiras. Configura&#231;&#227;o moderna. </p><p>Tr&#234;s configura&#231;&#245;es de contexto foram comparadas:</p><ul><li><p><strong>Caso 1:</strong> Hist&#243;rico completo, com tudo que aconteceu na sess&#227;o: 71,0% de tarefas conclu&#237;das, 1.480.996 tokens, 14,56 horas de execu&#231;&#227;o.</p></li><li><p><strong>Caso 2:</strong> Poda para os 5 pares mais recentes de chamada e resposta de tools: 79,0% de tarefas conclu&#237;das, 535.274 tokens, 5,39 horas.</p></li><li><p><strong>Caso 3:</strong> Poda com sumariza&#231;&#227;o do que foi descartado: 91,6% de tarefas conclu&#237;das, 553.374 tokens, 5,79 horas.</p></li></ul><p>Vejam s&#243;: no caso 2, descartar o hist&#243;rico antigo, sem nenhum tratamento, subiu a taxa de conclus&#227;o em 8 pontos e cortou 64% dos tokens e 63% do tempo. Por outro lado, no caso 3, resumir o trecho descartado antes de jog&#225;-lo fora custou 18 mil tokens adicionais sobre a poda, mas alcan&#231;ou impressionantes 91% de tarefas conclu&#237;das.</p><p>No caso 2, a poda mant&#233;m os cinco pares mais recentes porque isso cobre aproximadamente dois ciclos completos de mem&#243;ria de trabalho necess&#225;ria para a tarefa em andamento. O que fica para tr&#225;s s&#227;o estados de formul&#225;rio j&#225; superados, levando a erros de execu&#231;&#227;o de uma a&#231;&#227;o sobre um snapshot que n&#227;o faz mais sentido. </p><p>A sumariza&#231;&#227;o, caso 3, por outro lado, usa uma janela de tr&#234;s intera&#231;&#245;es, dispara quando pelo menos um par &#233; descartado e preserva quais formul&#225;rios foram abertos e com quais controles houve intera&#231;&#227;o. </p><p><strong>Duas ressalvas antes de transportar esses n&#250;meros para outro contexto:</strong> </p><ul><li><p><strong>Escopo:</strong> o resultado vale para um fluxo transacional de formul&#225;rio, em sess&#227;o &#250;nica, dentro de um produto espec&#237;fico. Os valores de janela, cinco pares e tr&#234;s intera&#231;&#245;es, foram escolhidos por clareza de exposi&#231;&#227;o e n&#227;o por otimiza&#231;&#227;o, e os autores afirmam que caracterizar a janela adequada por dom&#237;nio continua em aberto. </p></li><li><p><strong>Operacional:</strong> mesmo na melhor configura&#231;&#227;o, 8,4% das tarefas ficaram incompletas, o que mant&#233;m a revis&#227;o humana como requisito de produ&#231;&#227;o. </p></li></ul><h4>Podando o hist&#243;rico no LangChain</h4><p>A primeira estrat&#233;gia, a janela deslizante, j&#225; existe pronta no LangChain. A fun&#231;&#227;o <a href="https://reference.langchain.com/python/langchain-core/messages/utils/trim_messages">trim_messages</a> recorta a lista de mensagens preservando o final:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;e72bdd26-5061-4d7a-8f45-5446c703621b&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from langchain_core.messages import trim_messages

# Mant&#233;m a instru&#231;&#227;o de sistema e as 10 mensagens mais recentes,
# o que corresponde a cerca de 5 pares de chamada e resposta de tool.

podar = trim_messages(
    max_tokens=10,
    token_counter=len,    # conta mensagens, n&#227;o tokens
    strategy=&#8221;last&#8221;,      # descarta a partir do in&#237;cio do hist&#243;rico
    include_system=True,  # a instru&#231;&#227;o do agente nunca sai
    start_on=&#8221;human&#8221;,     # evita come&#231;ar por uma resposta de tool &#243;rf&#227;
)

historico_curto = podar.invoke(historico)</code></pre></div><p>Dois par&#226;metros merecem aten&#231;&#227;o. O <code>include_system</code> protege a instru&#231;&#227;o do agente, que precisa sobreviver a qualquer poda. O <code>start_on=&#8221;human&#8221;</code> evita um recorte que deixe uma mensagem de ferramenta sem a chamada correspondente, situa&#231;&#227;o que a maioria das APIs rejeita. Trocando <code>token_counter=len</code> pelo contador do pr&#243;prio modelo, o corte passa a ser por or&#231;amento de tokens em vez de por n&#250;mero de mensagens, o que costuma ser mais adequado quando as respostas de ferramenta t&#234;m tamanhos muito diferentes entre si.</p><p>A segunda estrat&#233;gia &#233; resumir o que sai antes de descartar. Um pequeno exemplo de como isso pode ser feito est&#225; abaixo.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;9e9facdf-fad9-4212-913f-a4b5e6d90d9d&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">from langchain_core.messages import SystemMessage
from langchain_openai import ChatOpenAI

resumidor = ChatOpenAI(model="gpt-4.1-mini", temperature=0)

INSTRUCAO = (
    """Resuma o que o agente j&#225; executou: a&#231;&#245;es conclu&#237;das, valores 
    confirmados e pend&#234;ncias. N&#227;o repita sa&#237;da bruta de ferramenta."""
)

def comprimir(historico, janela=10):
    antigas, recentes = historico[:-janela], historico[-janela:]

    if not antigas:
        return historico

    resumo = resumidor.invoke(
        [("system", INSTRUCAO),
         ("human", "\n".join(str(m.content) for m in antigas))]

    )
    return [SystemMessage(content=f&#8221;J&#225; executado: {resumo.content}&#8221;)] + recentes</code></pre></div><h3>Quando a poda pode atrapalhar?</h3><p>O resultado do benchmark n&#227;o autoriza podar sempre, e h&#225; evid&#234;ncia na dire&#231;&#227;o <a href="https://arxiv.org/abs/2605.11051">contr&#225;ria para outro dom&#237;nio</a>. Nesse trabalho, foi analisado a compress&#227;o autom&#225;tica em agentes que trabalham sobre reposit&#243;rios de c&#243;digo e identificaram perda de informa&#231;&#227;o necess&#225;ria em tr&#234;s situa&#231;&#245;es: 1) tarefas que envolvem m&#250;ltiplos arquivos interdependentes, 2) problemas que exigem reconhecer padr&#245;es arquiteturais do reposit&#243;rio inteiro, e 3) c&#243;digo com acoplamento alto. </p><p>Precisamos entender a diferen&#231;a entre os dois cen&#225;rios. </p><p>No primeiro, a itemiza&#231;&#227;o de despesas, o passo seguinte depende quase s&#243; do estado atual do formul&#225;rio; e o hist&#243;rico antigo &#233; passivo. Por outro lado, em uma corre&#231;&#227;o de bug que atravessa quatro arquivos, o que foi lido no passo 3 continua sendo relevante ao longo dos passos; o hist&#243;rico &#233; ativo. </p><blockquote><p>Quanto mais as decis&#245;es futuras dependerem de informa&#231;&#227;o lida no passado, mais cara fica a poda por posi&#231;&#227;o.</p></blockquote><p>Para esses casos existe uma terceira estrat&#233;gia, que &#233; deixar o pr&#243;prio agente decidir o que compactar. O <a href="https://arxiv.org/abs/2606.28434">SWE-MeM</a>, treina o agente para gerenciar a pr&#243;pria mem&#243;ria com base no estado da trajet&#243;ria, no progresso da tarefa e no or&#231;amento de contexto restante, tanto de forma proativa quanto sob demanda. Na avalia&#231;&#227;o da abordagem, foi observado 43,4% de resolu&#231;&#227;o de problemas com modelos de 4 bilh&#245;es de par&#226;metros e 60,2% com modelos de 30 bilh&#245;es. Mas a&#237; o problema deixa de ser uma fun&#231;&#227;o de recorte no seu c&#243;digo e passa a envolver (re)treinamentos de modelos.</p><h3>Conclus&#227;o</h3><p>O hist&#243;rico de um agente n&#227;o &#233; um registro que precisa ser preservado. </p><p>Guardar tudo &#233; uma decis&#227;o de projeto tanto quanto podar, com a diferen&#231;a de que &#233; a decis&#227;o que ningu&#233;m tomou de forma consciente.</p><p>Em um fluxo transacional, o agente que descarta o hist&#243;rico antigo acerta mais do que o que guarda tudo, e que resumir antes de descartar recupera a informa&#231;&#227;o que a poda por posi&#231;&#227;o perde. </p><p>A pergunta que devemos nos fazer &#233;: o pr&#243;ximo passo depende do estado atual ou do caminho percorrido? </p><ul><li><p>Se depende do estado, uma janela deslizante com resumo cobre bem o caso e cabe em vinte linhas. </p></li><li><p>Se depende do caminho, o resumo precisa ser desenhado com cuidado sobre o que a tarefa exige, e vale medir a taxa de conclus&#227;o com e sem compress&#227;o antes de adot&#225;-la. </p></li></ul><p>Em qualquer um dos dois, medir tokens por tarefa conclu&#237;da, e n&#227;o apenas tokens por chamada, &#233; o que mostra se a mudan&#231;a fez sentido.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ml4se.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Inscreva-se&quot;,&quot;language&quot;:&quot;pt-br&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">ML4SE &#233; uma newsletter focada em ajudar devs a mastigar t&#233;cnicas de aprendizado de m&#225;quina. Para receber novos posts, se inscreva na newsletter.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Digite seu e-mail&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Inscreva-se"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[Como especificações formais tornam agentes de LLM mais confiáveis?]]></title><description><![CDATA[Agentes de c&#243;digo deixaram de ser demonstra&#231;&#227;o e passaram a escrever parte do que vai para produ&#231;&#227;o.]]></description><link>https://ml4se.substack.com/p/como-especificacoes-formais-tornam</link><guid isPermaLink="false">https://ml4se.substack.com/p/como-especificacoes-formais-tornam</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Fri, 14 Aug 2026 18:20:26 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/36198c10-45fa-4fad-8777-54d5acd9c1c5_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Agentes de c&#243;digo deixaram de ser demonstra&#231;&#227;o e passaram a escrever parte do que vai para produ&#231;&#227;o. Aqui no blog n&#243;s j&#225; tratamos dessa mudan&#231;a em alguns textos, como <a href="/__u/ml4se.substack.com/p/quais-habilidades-um-full-life-cycle">Quais habilidades um full life-cycle engineer precisa ter?</a> e em <a href="/__u/ml4se.substack.com/p/o-que-e-harness-engineering">O que &#233; harness engineering?</a>.  A medida que agentes assumem a implementa&#231;&#227;o, verifica&#231;&#227;o e valida&#231;&#227;o ganham peso relativo. A habilidade escassa passa a ser <em>especificar</em>.</p><p>O problema &#233; que &#8220;especificar&#8221; costuma significar escrever um par&#225;grafo de descri&#231;&#227;o em linguagem natural.. Mas, um par&#225;grafo n&#227;o roda, n&#227;o &#233; execut&#225;vel. Ele n&#227;o aceita nem rejeita nada. Especifica&#231;&#227;o formal entra como uma alternativa: descrever o comportamento pretendido em uma linguagem que uma m&#225;quina consegue conferir. </p><p>Neste texto vamos ver o que isso significa no contexto das LLMs, por que a aus&#234;ncia de uma especifica&#231;&#227;o formal pode deixar o c&#243;digo gerado fr&#225;gil e como usar especifica&#231;&#245;es formais para aumentar a robustez.</p><h3>O que &#233;, exatamente, uma especifica&#231;&#227;o formal?</h3><p>Uma especifica&#231;&#227;o formal descreve o comportamento pretendido de um trecho de c&#243;digo em termos verific&#225;veis, sem dizer como ele deve ser implementado. A formula&#231;&#227;o mais antiga e mais pr&#225;tica vem do <em>design by contract</em> de Bertrand Meyer: um par de pr&#233;-condi&#231;&#227;o e p&#243;s-condi&#231;&#227;o.</p><ul><li><p>A <strong>pr&#233;-condi&#231;&#227;o</strong> delimita o dom&#237;nio de entrada: quais entradas e qual estado de programa s&#227;o admiss&#237;veis antes deste ser chamado. </p></li><li><p>A <strong>p&#243;s-condi&#231;&#227;o</strong> prescreve o que precisa valer depois: propriedades da sa&#237;da e do estado resultante, assumindo que a pr&#233;-condi&#231;&#227;o foi satisfeita.</p></li></ul><p>Existem duas fam&#237;lias de especifica&#231;&#227;o formal. Na fam&#237;lia dedutiva, a especifica&#231;&#227;o &#233; escrita em uma linguagem de verifica&#231;&#227;o (como JML) e um provador de teoremas tenta demonstrar que a implementa&#231;&#227;o a satisfaz para toda entrada poss&#237;vel. Na fam&#237;lia execut&#225;vel, a especifica&#231;&#227;o &#233; c&#243;digo, parecido com um teste de unidade, que roda junto com o programa e julga cada execu&#231;&#227;o concreta.</p><p>O benchmark <a href="https://arxiv.org/abs/2604.12268">CodeSpecBench</a> adota a segunda forma e a codifica como fun&#231;&#245;es Python:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;1803fae1-2aaf-4b08-9a64-d86255e519d7&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python"># Problema: dado um array de inteiros e um alvo, retornar os &#237;ndices de dois
# elementos distintos cuja soma &#233; igual ao alvo. Assume-se que existe
# exatamente uma solu&#231;&#227;o e que nenhum elemento &#233; usado duas vezes.

def preconditions(nums, target):
    # tipos b&#225;sicos
    assert isinstance(nums, list) and isinstance(target, int)
    assert len(nums) &gt;= 2 and all(isinstance(x, int) for x in nums)

    # o enunciado garante unicidade da solu&#231;&#227;o: isso faz parte do dom&#237;nio
    pares = [(i, j)
             for i in range(len(nums))
             for j in range(i + 1, len(nums))
             if nums[i] + nums[j] == target]
    assert len(pares) == 1

def postconditions(nums, target, result):
    # formato do resultado
    assert isinstance(result, (list, tuple)) and len(result) == 2
    i, j = result

    # validade dos &#237;ndices e corre&#231;&#227;o sem&#226;ntica
    assert i != j and 0 &lt;= i &lt; len(nums) and 0 &lt;= j &lt; len(nums)
    assert nums[i] + nums[j] == target</code></pre></div><p>Repare no que essas quinze linhas fazem e no que um teste unit&#225;rio n&#227;o faz. O teste diz que <code>dois_soma([3,2,4], 6)</code> deve retornar <code>[1,2]</code>. A p&#243;s-condi&#231;&#227;o diz que qualquer par de &#237;ndices distintos cuja soma bata serve, para qualquer entrada no dom&#237;nio. O teste &#233; um or&#225;culo pontual. A especifica&#231;&#227;o &#233; um or&#225;culo universal (ou pelo menos universal sobre o dom&#237;nio que a pr&#233;-condi&#231;&#227;o delimita).</p><h3>Por que a aus&#234;ncia de especifica&#231;&#227;o deixa o c&#243;digo gerado por LLMs fr&#225;gil?</h3><p>Suponha que voc&#234; pe&#231;a a um modelo uma fun&#231;&#227;o que ordena uma lista de inteiros, e ele devolva isto:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;4f9a759a-d089-4fdc-b31b-4fef0bac41ec&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def ordenar(xs):
    return sorted(set(xs))</code></pre></div><p>Essa fun&#231;&#227;o passa em ordenar<code>([3, 1, 2]) == [1, 2, 3]</code>. Passa em ordenar <code>([]) == []</code>. Passa em ordenar <code>([5]) == [5]</code>. Se a sua su&#237;te de testes n&#227;o tiver um caso com elemento repetido, o defeito vai para produ&#231;&#227;o intacto. A p&#243;s-condi&#231;&#227;o correta pega o problema na primeira execu&#231;&#227;o com duplicata, porque ela n&#227;o fala sobre exemplos, fala sobre a rela&#231;&#227;o entre entrada e sa&#237;da:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;031d1843-d88d-4979-8908-2fb2b3daa321&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def postcondicao_ordenar(xs, resultado):
    # a sa&#237;da precisa estar ordenada
    assert all(resultado[i] &lt;= resultado[i + 1] for i in range(len(resultado) - 1))

    # e precisa ser uma permuta&#231;&#227;o da entrada, n&#227;o apenas um subconjunto
    assert sorted(xs) == resultado</code></pre></div><p>Para dar um exemplo, o benchmark <a href="https://arxiv.org/abs/2510.12047">ContractEval</a>, constru&#237;do sobre HumanEval+ com 364 tarefas e cinco LLMs de c&#243;digo, mede a dist&#226;ncia entre &#8220;passa nos testes&#8221; e &#8220;respeita o contrato&#8221;. </p><p>Usando o mesmo prompt padr&#227;o, os modelos alcan&#231;am resultados entre 75% e 82% e 0% de satisfa&#231;&#227;o contratual. Mesmo quando o contrato &#233; colocado explicitamente no prompt, a satisfa&#231;&#227;o sobe apenas para a faixa de 23% a 41%. Isso significa que o c&#243;digo funciona nos casos testados, por&#233;m ignora as condi&#231;&#245;es de borda que ningu&#233;m escreveu.</p><p>Existe uma segunda fragilidade, mais desconfort&#225;vel, que o CodeSpecBench avalia: <strong>o modelo consegue resolver o problema sem entender o problema</strong>. </p><p>Comparando gera&#231;&#227;o de solu&#231;&#227;o com gera&#231;&#227;o de especifica&#231;&#227;o nas mesmas tarefas, o paper reporta Claude-4.5-Sonnet com 77,2% de acerto em gerar a solu&#231;&#227;o no n&#237;vel de reposit&#243;rio e 21,0% em gerar a especifica&#231;&#227;o correspondente (GPT-5 aparece com 72,8% contra 10,2%). </p><blockquote><p>Escrever a implementa&#231;&#227;o &#233; uma tarefa em que o LLM pode se apoiar em padr&#245;es conhecidos. Por outro, escrever o contrato exige saber o que o programa deve exatamente fazer, sem o atalho de dizer como.</p></blockquote><p>Em outro paper, <a href="https://arxiv.org/abs/2603.17193">Talk is Cheap, Logic is Hard</a>, os autores avaliaram 24 modelos em 40 tarefas de formaliza&#231;&#227;o e evidenciou que todos formalizam pr&#233;-condi&#231;&#245;es melhor do que p&#243;s-condi&#231;&#245;es; mas nenhum acertou o conjunto completo!</p><h3>Como especifica&#231;&#245;es tornam LLMs mais robustas</h3><p>H&#225; tr&#234;s usos distintos, com custos e ganhos distintos.</p><ul><li><p><strong>Uso 1: a especifica&#231;&#227;o como or&#225;culo para escolher entre candidatos.</strong> Quando voc&#234; pede n implementa&#231;&#245;es ao modelo, precisa decidir qual usar, e normalmente n&#227;o tem a sa&#237;da esperada para comparar. A especifica&#231;&#227;o pode ajudar a resolver isso. O CodeSpecBench mediu esse procedimento. Com re-ranking guiado por especifica&#231;&#227;o, o pass@1 do Qwen3-8B subiu de 59,4% para 62,2%, e o do Qwen3-32B de 71,2% para 73,9%. O ganho &#233; maior em pass@1 do que em pass@5, o que indica que a especifica&#231;&#227;o est&#225; fazendo o trabalho de identificar a melhor solu&#231;&#227;o dentro do conjunto, n&#227;o de aumentar a diversidade dele.</p></li><li><p><strong>Uso 2: a especifica&#231;&#227;o como guarda em tempo de execu&#231;&#227;o.</strong> Aqui a especifica&#231;&#227;o n&#227;o fica em um arquivo de teste, fica em volta da fun&#231;&#227;o em produ&#231;&#227;o. O CodeSpecBench faz isso no n&#237;vel de reposit&#243;rio, configurando um <code>conftest.py</code> que envolve a fun&#231;&#227;o alvo, executa a pr&#233;-condi&#231;&#227;o antes da chamada e a p&#243;s-condi&#231;&#227;o depois. A biblioteca <a href="https://github.com/Parquery/icontract">icontract</a> oferece algo parecido por decorador.</p></li><li><p><strong>Uso 3: a especifica&#231;&#227;o como alvo de prova.</strong> Nesse caminho o modelo gera c&#243;digo e prova, e um verificador decide. &#201; a rota mais forte e a mais cara.</p></li></ul><h3>O que j&#225; existe por a&#237;? </h3><p>Os n&#250;meros de verifica&#231;&#227;o dedutiva melhoraram r&#225;pido. O benchmark de <a href="https://arxiv.org/abs/2509.22908">vericoding</a>, com 12.504 especifica&#231;&#245;es formais reporta at&#233; 82% de sucesso, usando modelos de prateleira. Os autores registram tamb&#233;m a progress&#227;o em Dafny de 68% para 96% em benchmarks existentes ao longo de um ano.</p><p><a href="https://arxiv.org/abs/2605.08553">VeriContest</a>, com 946 problemas de LeetCode e Codeforces em Rust, decomp&#245;e a tarefa e mede cada etapa: 92,18% em gerar c&#243;digo a partir da descri&#231;&#227;o, 48,31% em gerar a especifica&#231;&#227;o, 13,95% em gerar a prova e 5,29% de s&#237;ntese verificada de ponta a ponta. A dist&#226;ncia entre o primeiro resultado e o &#250;ltimo resultado &#233; a dist&#226;ncia entre escrever c&#243;digo e garantir c&#243;digo.</p><p>H&#225; tamb&#233;m um servi&#231;o da Amazon chamado <a href="https://aws.amazon.com/about-aws/whats-new/2025/08/automated-reasoning-checks-amazon-bedrock-guardrails">Automated Reasoning checks</a>, dispon&#237;vel desde agosto de 2025. &#201; o mesmo mecanisom mas em outra roupagem: a pol&#237;tica de neg&#243;cio &#233; codificada como um conjunto de regras de l&#243;gica formal com um esquema de vari&#225;veis, e cada resposta do modelo &#233; verificada contra essas regras antes de chegar ao usu&#225;rio. A AWS reporta at&#233; 99% de acur&#225;cia na detec&#231;&#227;o de respostas corretas, com auditabilidade por constru&#231;&#227;o, j&#225; que o resultado da checagem vem acompanhado da regra que foi violada. </p><h3>Por onde come&#231;o?</h3><p>Escolha a fun&#231;&#227;o mais cr&#237;tica do seu c&#243;digo gerado por agente, escreva a p&#243;s-condi&#231;&#227;o dela em cinco linhas de assert, e ligue um @given do Hypothesis em cima. Voc&#234; vai descobrir na mesma tarde quantos dos seus testes eram exemplos disfar&#231;ados de garantia.</p><p>A partir da&#237;, o caminho tem tr&#234;s degraus e vale subir um de cada vez. </p><ul><li><p>O primeiro &#233; acrescentar a pr&#233;-condi&#231;&#227;o, que costuma ser mais dif&#237;cil do que parece: os dados do ContractEval e do Talk is Cheap mostram que &#233; justamente ali, na defini&#231;&#227;o do dom&#237;nio de entrada, que modelos e desenvolvedores erram menos, e &#233; ali que voc&#234; descobre suposi&#231;&#245;es que ningu&#233;m tinha escrito em lugar nenhum. </p></li><li><p>O segundo degrau &#233; tirar a asser&#231;&#227;o do arquivo de teste e coloc&#225;-la em volta da fun&#231;&#227;o em produ&#231;&#227;o, com um decorador do icontract ou com um wrapper pr&#243;prio, para que a viola&#231;&#227;o apare&#231;a na primeira execu&#231;&#227;o real fora do dom&#237;nio, e n&#227;o tr&#234;s semanas depois em um log de erro sem contexto. </p></li><li><p>O terceiro degrau &#233; usar a especifica&#231;&#227;o dentro do pr&#243;prio la&#231;o do agente, como or&#225;culo de sele&#231;&#227;o: pe&#231;a n implementa&#231;&#245;es, descarte as que violam a p&#243;s-condi&#231;&#227;o, e escolha entre as que sobraram. </p></li></ul><p>Vale notar que uma especifica&#231;&#227;o formal cobra manuten&#231;&#227;o, e uma especifica&#231;&#227;o restritiva demais pode reprovar uma implementa&#231;&#227;o correta. A sugest&#227;o &#233; descrever o que o chamador observa, nunca como a fun&#231;&#227;o chega l&#225;. Se a especifica&#231;&#227;o quebra quando algu&#233;m troca a estrutura interna, ela virou teste de implementa&#231;&#227;o.</p>]]></content:encoded></item><item><title><![CDATA[Quais as habilidades de um full life-cycle engineer?]]></title><description><![CDATA[Agentes de c&#243;digo deixaram o est&#225;gio de demonstra&#231;&#227;o e entraram no fluxo de trabalho real, nada de novo.]]></description><link>https://ml4se.substack.com/p/quais-habilidades-um-full-life-cycle</link><guid isPermaLink="false">https://ml4se.substack.com/p/quais-habilidades-um-full-life-cycle</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Fri, 07 Aug 2026 15:34:04 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/882f99eb-eccf-4916-83a9-e8bff9a3edb9_2452x1490.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Agentes de c&#243;digo abrem pull requests, respondem a issues, escrevem testes, revisam commits e, em algumas organiza&#231;&#245;es, opinam sobre decis&#245;es de projeto. Se a m&#225;quina escreve a maior parte do c&#243;digo, o que exatamente uma pessoa engenheira de software faz?</p><p>Uma cena que provavelmente j&#225; aconteceu com voc&#234;. Um agente abre um pull request com 400 linhas, uma descri&#231;&#227;o bem redigida e todos os testes verdes. Voc&#234; olha o diff por 90 segundos, reconhece o padr&#227;o geral, n&#227;o encontra nada obviamente errado e&#8230; aprova. Tr&#234;s semanas depois surge um comportamento estranho em produ&#231;&#227;o e ningu&#233;m no time consegue explicar por que aquele componente foi desenhado daquele jeito. O c&#243;digo est&#225; l&#225;, funciona na maior parte do tempo, mas a inten&#231;&#227;o por tr&#225;s daquele c&#243;digo se perdeu.</p><p>Esse &#233; o ponto de partida de um artigo publicado em junho de 2026 por Sungmin Kang, Baishakhi Ray e Abhik Roychoudhury, intitulado &#8220;<a href="https://arxiv.org/abs/2606.21894">Skills for the future software profession: beyond agentic AI!</a>&#8221;. O texto sintetiza duas mesas redondas sobre IA confi&#225;vel para c&#243;digo, realizadas em Singapura (janeiro de 2026) e Nova York (junho de 2026), cada uma com 30 a 40 participantes vindos de MIT, Harvard, Google, Meta, Amazon, IBM e outras institui&#231;&#245;es. O objetivo foi destilar, a partir de discuss&#245;es em grupo, quais compet&#234;ncias os desenvolvedores v&#227;o precisar daqui para frente.</p><p>Neste post vamos percorrer as tr&#234;s compet&#234;ncias que o artigo identifica: </p><ol><li><p>especifica&#231;&#245;es execut&#225;veis como base de verifica&#231;&#227;o e valida&#231;&#227;o, </p></li><li><p>arquitetura ag&#234;ntica, e </p></li><li><p>gest&#227;o de d&#237;vida cognitiva. </p></li></ol><h2>O gargalo mudou de lugar</h2><p>Tradicionalmente, escrever c&#243;digo era a parte mais cara do desenvolvimento. Com a gera&#231;&#227;o autom&#225;tica barateando a produ&#231;&#227;o, o gargalo desloca-se da produ&#231;&#227;o de software para a garantia de software (do ingl&#234;s, <em>software assurance</em>).</p><p>Os participantes das mesas redondas relataram uma observa&#231;&#227;o inc&#244;moda sobre isso. Desenvolvedores aceitam c&#243;digo gerado por IA com <strong>escrut&#237;nio cada vez menor</strong>, o que torna a revis&#227;o manual uma salvaguarda pouco confi&#225;vel. Aqui no blog n&#243;s j&#225; tratamos desse desconforto em <a href="/__u/ml4se.substack.com/p/porque-eu-nao-posso-confiar-cegamente">Porque eu n&#227;o posso confiar cegamente no c&#243;digo gerado por LLMs</a>. Pensando no artigo, um pouco mais adiante: se a revis&#227;o humana linha a linha n&#227;o escala com o volume de c&#243;digo gerado, a confian&#231;a precisa vir de outro lugar.</p><p>Esse outro lugar s&#227;o os artefatos de verifica&#231;&#227;o e valida&#231;&#227;o que uma m&#225;quina consegue checar. De acordo com os autores, especifica&#231;&#227;o e verifica&#231;&#227;o passam <strong>a preceder</strong> a implementa&#231;&#227;o; e n&#227;o <strong>a suceder</strong>. O desenvolvedor conversa com o usu&#225;rio final, extrai a inten&#231;&#227;o, converte essa inten&#231;&#227;o em artefatos verific&#225;veis por m&#225;quina, e s&#243; ent&#227;o o agente implementa algo que satisfa&#231;a esses artefatos.</p><h2>Especifica&#231;&#245;es execut&#225;veis</h2><p>A primeira compet&#234;ncia que o artigo lista &#233; a tradu&#231;&#227;o de inten&#231;&#227;o do usu&#225;rio em especifica&#231;&#245;es execut&#225;veis. O artigo ilustra um di&#225;logo como: </p><ul><li><p>o usu&#225;rio pede uma funcionalidade X que vai permitir a funcionalidade Y; </p></li><li><p>o desenvolvedor responde que, por controle de qualidade, vai escrever Z; </p></li><li><p>o usu&#225;rio confirma que &#233; isso mesmo. </p></li></ul><blockquote><p>O artefato Z &#233; uma especifica&#231;&#227;o execut&#225;vel, que pode ser teste, uma pr&#233;-condi&#231;&#227;o, uma p&#243;s-condi&#231;&#227;o, uma propriedade.</p></blockquote><p>Considere uma fun&#231;&#227;o de desconto em centavos. O contrato &#233; o que n&#243;s mantemos; a implementa&#231;&#227;o &#233; o que o agente pode reescrever quantas vezes quiser.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;a6ae62a9-0f12-4b43-9e4b-171b32759f29&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python"># spec.py
# A implementa&#231;&#227;o pode ser regenerada por um agente a qualquer momento.
# O contrato abaixo, n&#227;o: ele &#233; o artefato que o time humano possui.

from hypothesis import given, strategies as st

def aplicar_desconto(valor_centavos: int, percentual: int) -&gt; int:
    &#8220;&#8221;&#8220;
    pre:  valor_centavos &gt;= 0
    pre:  0 &lt;= percentual &lt;= 100
    post: 0 &lt;= __return__ &lt;= valor_centavos
    &#8220;&#8221;&#8220;
    return valor_centavos - (valor_centavos * percentual) // 100

@given(
    valor=st.integers(min_value=0, max_value=10**9),
    pct=st.integers(min_value=0, max_value=100),

)

def test_contrato_do_desconto(valor, pct):
    resultado = aplicar_desconto(valor, pct)
    # P&#243;s-condi&#231;&#227;o: o resultado vive dentro do intervalo declarado.
    assert 0 &lt;= resultado &lt;= valor
    # Dom&#237;nio: centavos s&#227;o indivis&#237;veis, o retorno tem que ser inteiro.
    assert isinstance(resultado, int)
    # Casos de fronteira, escritos como propriedade e n&#227;o como exemplo solto.
    assert aplicar_desconto(valor, 0) == valor
    assert aplicar_desconto(valor, 100) == 0</code></pre></div><p>Os coment&#225;rios pre: e post: na docstring n&#227;o s&#227;o decorativos. Esse &#233; o formato que o <a href="https://github.com/pschanely/CrossHair">CrossHair</a> l&#234; para fazer verifica&#231;&#227;o simb&#243;lica da fun&#231;&#227;o, e o bloco <code>@given</code> &#233; <a href="https://hypothesis.readthedocs.io/">Hypothesis</a> gerando entradas para testar a propriedade em vez de um punhado de exemplos escolhidos &#224; m&#227;o.</p><p>Agora suponha que um agente receba a tarefa de &#8220;deixar a fun&#231;&#227;o mais leg&#237;vel&#8221; e devolva esta vers&#227;o:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;752c64b4-fe4b-4461-aa59-c8c8131f3d8c&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def aplicar_desconto(valor_centavos, percentual):
    return valor_centavos - valor_centavos * percentual / 100</code></pre></div><p>O comportamento parece equivalente numa leitura r&#225;pida, e &#233; exatamente o tipo de mudan&#231;a que passa em uma revis&#227;o de 90 segundos. </p><p>S&#243; que a divis&#227;o deixou de ser inteira. Com <code>valor=1</code> e <code>pct=50</code>, o retorno &#233; <code>0.5</code>, meio centavo. A asser&#231;&#227;o <code>isinstance(resultado, int)</code> reprova a mudan&#231;a, e fica f&#225;cil para o <code>Hypothesis</code> encontrar esse contraexemplo. A p&#243;s-condi&#231;&#227;o continua satisfeita, o tipo n&#227;o. </p><p>O artefato de V&amp;V que pegou o que passou batido pela leitura humana.</p><p>Especifica&#231;&#245;es formais n&#227;o &#233; algo muito comum em um projeto de software, entendemos. Talvez por isso que a infer&#234;ncia de especifica&#231;&#245;es (do ingl&#234;s, <em>specification inference</em>) se torna mais relevante. </p><p>Agentes conseguem inferir testes e especifica&#231;&#245;es a partir de documenta&#231;&#227;o, c&#243;digo e relatos de issues. O <a href="https://arxiv.org/abs/2404.05427">AutoCodeRover</a>, por exemplo, usa especifica&#231;&#245;es inferidas via busca no c&#243;digo para melhorar o desempenho de corre&#231;&#227;o, abordagem depois comercializada no <a href="https://www.sonarsource.com/products/sonarqube/remediation-agent/)">Remediation Agent</a> do SonarQube.</p><p>Isso tende a mudar a natureza do trabalho humano. </p><p>Como a gera&#231;&#227;o de especifica&#231;&#245;es tamb&#233;m est&#225; sendo automatizada, a compet&#234;ncia que resta ao desenvolvedor <strong>&#233; de avalia&#231;&#227;o</strong>: </p><ul><li><p>julgar se a especifica&#231;&#227;o captura fielmente a inten&#231;&#227;o do usu&#225;rio, </p></li><li><p>se ela &#233; suficientemente completa, e </p></li><li><p>se oferece o n&#237;vel de garantia adequado ao contexto. </p></li></ul><p>Os engenheiros do futuro n&#227;o precisam se tornar especialistas em m&#233;todos formais, longe disso. Mas talvez precisem entender no papel das <strong>especifica&#231;&#245;es execut&#225;veis</strong>. </p><p>H&#225; tamb&#233;m obviamente o risco das especifica&#231;&#245;es inferidas sofrerem drift em rela&#231;&#227;o a implementa&#231;&#245;es, que continuam evoluindo. Isso exige ambientes de desenvolvimento (ou plataformas agenticas) capazes de validar continuamente a consist&#234;ncia entre c&#243;digo e especifica&#231;&#227;o.</p><h2>Arquitetura ag&#234;ntica</h2><p>A segunda compet&#234;ncia &#233; a orquestra&#231;&#227;o de agentes. Com as especifica&#231;&#245;es no lugar, o pr&#243;ximo problema &#233; desenhar o sistema de agentes que vai produzir o software. </p><p>O artigo descreve um pipeline com pap&#233;is separados: </p><ul><li><p>um agente de <strong>codifica&#231;&#227;o</strong> que implementa e edita c&#243;digo a partir da descri&#231;&#227;o, </p></li><li><p>um agente de <strong>verifica&#231;&#227;o</strong> que confere se o c&#243;digo atende &#224; especifica&#231;&#227;o formal, e</p></li><li><p>um agente de <strong>testes</strong> que executa a su&#237;te contra o ambiente real.</p></li></ul><p>Os autores d&#227;o nome a essa disciplina emergente: <strong>arquitetura ag&#234;ntica</strong>. </p><p>Assim como a arquitetura de software decomp&#245;e sistemas em componentes e suas intera&#231;&#245;es, a arquitetura ag&#234;ntica trata da organiza&#231;&#227;o de agentes especializados, dos protocolos que governam a colabora&#231;&#227;o entre eles, e de onde posicionar a supervis&#227;o humana para maximizar a confiabilidade. As perguntas de pesquisa em aberto s&#227;o reconhec&#237;veis para quem j&#225; desenhou sistemas distribu&#237;dos: como os agentes se comunicam, como decompor o fluxo de trabalho entre eles, e como localizar, diagnosticar e recuperar falhas.</p><p>H&#225; uma previs&#227;o espec&#237;fica no texto que merece aten&#231;&#227;o: as interfaces em linguagem natural devem evoluir para interfaces guiadas por especifica&#231;&#227;o, que oferecem mais precis&#227;o e controle. Isso conversa diretamente com o que discutimos em O que &#233; harness engineering? (https://ml4se.substack.com/p/o-que-e-harness-engineering), onde o ponto era que a constru&#231;&#227;o do ambiente ao redor do modelo pesa tanto quanto o modelo. O artigo acrescenta que essa engenharia de ambiente vai passar a ser mat&#233;ria de curr&#237;culo, incluindo decomposi&#231;&#227;o de tarefas, protocolos de coordena&#231;&#227;o, intera&#231;&#227;o humano-agente e desenho de fluxos sens&#237;veis a confian&#231;a.</p><h2>D&#237;vida cognitiva</h2><p>D&#237;vida t&#233;cnica &#233; um conceito conhecido: nasce de compromissos de projeto e implementa&#231;&#227;o assumidos para acelerar a entrega, e mora dentro do software. </p><p>D&#237;vida cognitiva (do ingl&#234;s, <em>cognitive debt</em>), termo que o artigo emprestado de <a href="https://queue.acm.org/detail.cfm?id=3746223">outro artigo</a>, mora em outro lugar: ela aparece quando os desenvolvedores perdem gradualmente o entendimento da inten&#231;&#227;o, da arquitetura e da justificativa por tr&#225;s de componentes gerados pelos agentes.</p><p>Na era ag&#234;ntica, a d&#237;vida principal desloca-se de dentro do software (d&#237;vida t&#233;cnica) para defici&#234;ncias no entendimento humano e organizacional (d&#237;vida cognitiva). O c&#243;digo pode estar limpo e o time, ainda assim, incapaz de explicar por que ele &#233; daquele jeito. Algumas contra medidas sugeridas:</p><ul><li><p><strong>Pol&#237;ticas de autoria com cust&#243;dia humana</strong>. Atribuir responsabilidade por cada artefato a um custodiante humano, independentemente de quem de fato escreveu o c&#243;digo, para que exista presta&#231;&#227;o de contas sobre artefatos gerados por IA.</p></li><li><p><strong>Propriedade das decis&#245;es arquiteturais.</strong> As pessoas engenheiras devem continuar donos das decis&#245;es de arquitetura, para conseguir localizar e raciocinar sobre falhas rapidamente quando as implementa&#231;&#245;es estiverem automatizadas. </p></li><li><p><strong>Reposit&#243;rios de artefatos (al&#233;m do c&#243;digo</strong>)<strong>.</strong> Os participantes enfatizaram manter, versionados os requisitos, as especifica&#231;&#245;es execut&#225;veis, as instru&#231;&#245;es dadas aos agentes, as pol&#237;ticas de ferramentas, o racional de projeto e at&#233; as trajet&#243;rias dos agentes.</p></li><li><p><strong>Full life-cycle engineers</strong>. O artigo observa que a ind&#250;stria j&#225; caminha para full life-cycle engineers, estendendo a no&#231;&#227;o de desenvolvimento full-stack para incluir a curadoria de longo prazo de sistemas assistidos por IA.</p></li></ul><p>Uma ideia pr&#225;tica aparece na se&#231;&#227;o de perspectivas: um participante descreveu depositar as especifica&#231;&#245;es no pr&#243;prio reposit&#243;rio, como arquivos markdown. O artefato precisa existir, ser versionado junto do c&#243;digo e ser execut&#225;vel o suficiente para impedir o drift.</p><h2>Conclus&#227;o</h2><p>Os curr&#237;culos de computa&#231;&#227;o v&#227;o precisar de uma mudan&#231;a radical para ajudar a converter requisitos de neg&#243;cio em especifica&#231;&#245;es chec&#225;veis, com assist&#234;ncia de IA, e em compor agentes e subagentes num pipeline ag&#234;ntico.</p><p>A preocupa&#231;&#227;o atual do desenvolvedor com compor componentes para construir um sistema deve dar lugar &#224; preocupa&#231;&#227;o em gerenciar confian&#231;a em agentes conforme pipelines ag&#234;nticos s&#227;o compostos. Passamos a raciocinar sobre atores com comportamento probabil&#237;stico. N&#227;o &#233; somente uma mudan&#231;a de ferramenta, &#233; tamb&#233;m uma mudan&#231;a de comportamento.</p><p>Embora seja um artigo curto, sem nenhum experimento, ele organiza bem uma inquieta&#231;&#227;o difusa em tr&#234;s compet&#234;ncias. A primeira delas da pra cair na pr&#225;tica sem esperar mudan&#231;a curricular alguma: </p><ul><li><p>escolha um componente do seu sistema que tenha sido gerado por um agente de c&#243;digo; </p></li><li><p>escreva a p&#243;s-condi&#231;&#227;o que ele precisa respeitar e a propriedade que caracteriza o comportamento correto, no formato do exemplo que montamos acima; </p></li><li><p>rode o Hypothesis contra a implementa&#231;&#227;o atual. </p><ul><li><p>se a propriedade passar, voc&#234; ganhou um artefato que sobrevive &#224; pr&#243;xima regenera&#231;&#227;o do c&#243;digo. s</p></li><li><p>e falhar, voc&#234; acabou de descobrir algo que a revis&#227;o de 90 segundos n&#227;o pegou.</p></li></ul></li></ul><p>As outras duas compet&#234;ncias, arquitetura ag&#234;ntica e gest&#227;o de d&#237;vida cognitiva, s&#227;o de prazo mais longo e dependem de escolha organizacional. </p><p>Mas a pergunta de cust&#243;dia d&#225; para fazer nesta semana: quem, com nome e sobrenome, responde pela inten&#231;&#227;o por tr&#225;s de cada componente que um agente escreveu no seu reposit&#243;rio? Se n&#227;o houver resposta, a d&#237;vida cognitiva j&#225; est&#225; sendo acumulada.</p><div><hr></div><p><span>Estou considerando abrir uma nova turma sobre Cuidados com LLMs em produ&#231;&#227;o. Se isso parece interessante pra voc&#234;, </span><a href="https://forms.gle/3VcFaRoxauSzLwnaA">deixe seu contato aqui</a><span>?</span></p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ml4se.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Inscreva-se&quot;,&quot;language&quot;:&quot;pt-br&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">ML4SE &#233; uma newsletter focada em ajudar devs a mastigar t&#233;cnicas de aprendizado de m&#225;quina. Para receber novos posts, se inscreva na newsletter.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Digite seu e-mail&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Inscreva-se"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Quais preocupações um dev deve ter ao colocar uma LLM em produção?]]></title><description><![CDATA[Entenda as 3 principais caracter&#237;sticas de uma LLM; e como trata-las.]]></description><link>https://ml4se.substack.com/p/quais-preocupacoes-um-dev-deve-ter</link><guid isPermaLink="false">https://ml4se.substack.com/p/quais-preocupacoes-um-dev-deve-ter</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Sun, 02 Aug 2026 02:50:08 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/341431e5-f1e3-4b8f-8081-9d83671fffca_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><p></p><p>N&#227;o &#233; novidade que montar um prot&#243;tipo com LLM ficou r&#225;pido e simples. Em uma tarde, conectamos uma chamada de API, ajustamos um prompt e temos algo que responde de forma convincente na tela. Essa velocidade cria a impress&#227;o de que o trabalho est&#225; quase pronto, e que separar o prot&#243;tipo da aplica&#231;&#227;o final &#233; uma quest&#227;o de poucos ajustes.</p><p>O problema aparece quando esse mesmo c&#243;digo sai da m&#225;quina do dev e passa a atender requisi&#231;&#245;es de verdade. Um endpoint que respondia bem em um teste isolado agora recebe milhares de chamadas por dia, cada uma com um custo associado, e nem sempre devolve a mesma resposta para a mesma entrada. H&#225; tr&#234;s caracter&#237;sticas importantes aqui: 1) o tempo de resposta, 2) o gasto por requisi&#231;&#227;o e 3) a varia&#231;&#227;o da sa&#237;da. Mas a gente s&#243; atenta pra elas em produ&#231;&#227;o.</p><p>Neste post, vamos explorar essas tr&#234;s preocupa&#231;&#245;es uma a uma. Na lat&#234;ncia, discutimos por que reduzir o prompt costuma ajudar menos do que se imagina. No custo, falamos de algumas abordagens (comuns em outros contextos e resignificadas para LLMs). No n&#227;o-determinismo, estudamos como medir a varia&#231;&#227;o da sa&#237;da em vez de tentar elimin&#225;-la.</p><h2>Lat&#234;ncia</h2><p>Existe uma intui&#231;&#227;o comum de que prompts menores geram respostas mais r&#225;pidas. A <a href="https://developers.openai.com/api/docs/guides/latency-optimization">documenta&#231;&#227;o de otimiza&#231;&#227;o de lat&#234;ncia da OpenAI</a> mede isso e chega a uma conclus&#227;o diferente:</p><blockquote><p> &#8220;Cutting 50% of your output tokens may cut ~50% your latency&#8221;, enquanto &#8220;cutting 50% of your prompt may only result in a 1-5% latency improvement&#8221;.</p></blockquote><p>Ou seja, o tempo de resposta &#233; dominado pela gera&#231;&#227;o de sa&#237;da, n&#227;o pelo tamanho da entrada. Cortar metade do prompt devolve entre 1% e 5% de melhoria. Cortar metade da sa&#237;da devolve perto de 50%. </p><p>Quem quer ganho de tempo deveria come&#231;ar limitando o que o modelo escreve: definir <code>max_tokens</code>, usar sequ&#234;ncias de parada, pedir concis&#227;o de forma expl&#237;cita e, em respostas estruturadas, encurtar os nomes dos campos do JSON, uma vez que cada nome de campo &#233; gerado token a token.</p><p>A segunda corre&#231;&#227;o diz respeito ao que medimos. Lat&#234;ncia m&#233;dia esconde justamente o caso que gera reclama&#231;&#227;o. O consenso de instrumenta&#231;&#227;o, resumido no <a href="https://bentoml.com/llm/llm-inference-basics/llm-inference-metrics">LLM Inference Handbook</a> da BentoML, &#233; decompor a medi&#231;&#227;o em quatro n&#250;meros, sempre em percentis (p50, p95, p99), nunca em m&#233;dia:</p><ol><li><p><strong>TTFT (time to first token):</strong> O tempo at&#233; o primeiro token aparecer. &#201; o que o usu&#225;rio percebe </p></li><li><p><strong>ITL (inter-token latency):</strong> A fluidez da resposta enquanto ela &#233; escrita.</p></li><li><p><strong>Queue time:</strong> Satura&#231;&#227;o do servidor e limites de requisi&#231;&#227;o</p></li><li><p><strong>Lat&#234;ncia de ponta a ponta:</strong> O n&#250;mero que entra no acordo de n&#237;vel de servi&#231;o</p></li></ol><p>O p99 importa porque &#233; ele que registra os efeitos que somem na m&#233;dia: interfer&#234;ncia entre requisi&#231;&#245;es no mesmo lote, remo&#231;&#227;o de entradas do cache de aten&#231;&#227;o e pausas do coletor de lixo.</p><p>Do lado das t&#233;cnicas, a de melhor rela&#231;&#227;o entre esfor&#231;o e retorno &#233; o <em>streaming</em>, a entrega da resposta token a token conforme ela &#233; gerada. O detalhe interessante &#233; que o <em>streaming</em> n&#227;o reduz a lat&#234;ncia real. Ele reduz a lat&#234;ncia percebida, e a documenta&#231;&#227;o da OpenAI trata as duas como categorias distintas. Vale registrar ainda a &#250;ltima recomenda&#231;&#227;o: para muitos problemas, pr&#233;-computa&#231;&#227;o e cache tradicional continuam mais r&#225;pidos que qualquer modelo. O guia de boas <a href="https://developers.openai.com/api/docs/guides/production-best-practices">pr&#225;ticas de produ&#231;&#227;o</a> complementa esse ponto com as recomenda&#231;&#245;es de limite de requisi&#231;&#245;es e de monitoramento de gasto.</p><h2>Custo</h2><p>A tabela de pre&#231;os da <a href="https://platform.claude.com/docs/en/build-with-claude/prompt-caching">documenta&#231;&#227;o da Anthropic</a> usa multiplicadores sobre o pre&#231;o base do token de entrada:</p><ul><li><p>Entrada normal: 1,0x</p></li><li><p>Escrita no cache (validade de 5 minutos): 1,25x</p></li><li><p>Escrita no cache (validade de 1 hora): 2,0x</p></li><li><p>Leitura do cache: 0,1x</p></li></ul><p>A conta que importa est&#225; na diferen&#231;a entre 1,25x para escrever e 0,1x para ler: <strong>o cache se paga j&#225; na segunda leitura do mesmo prompt</strong>. Como a validade de cinco minutos &#233; renovada a cada leitura, tr&#225;fego cont&#237;nuo mant&#233;m o prompt ativo.</p><p>Existe tamb&#233;m um m&#237;nimo de tokens por modelo (de 512 a 4096, conforme o caso). Abaixo desse m&#237;nimo o conte&#250;do n&#227;o &#233; armazenado e a API n&#227;o retorna erro, o que produz uma falha silenciosa. Por isso, leia <code>cache_read_input_tokens</code> na resposta e confirme que o cache est&#225; sendo usado.</p><p>Duas outras frentes de economia que aparecem com frequ&#234;ncia:</p><ul><li><p><strong>Processamento em lote.</strong> A <a href="https://platform.claude.com/docs/en/build-with-claude/batch-processing">Batch API</a> oferece 50% de redu&#231;&#227;o em entrada e sa&#237;da, com a maioria dos lotes conclu&#237;dos em menos de uma hora. Serve para tudo que n&#227;o tem usu&#225;rio esperando: avalia&#231;&#245;es,modera&#231;&#227;o de conte&#250;do, enriquecimento de dados e reprocessamentos. Um caso que costuma passar despercebido &#233; que as suas pr&#243;prias rodadas de avalia&#231;&#227;o se encaixam nesse perfil e costumam representar uma fatia relevante da fatura.</p></li><li><p>Cascatas de modelos. No paper <a href="https://arxiv.org/abs/2305.05176">FrugalGPT</a>, os autores apresentam a seguinte ideia: um modelo barato responde primeiro, um estimador de qualidade avalia a resposta e decide se ela serve ou se a pergunta deve subir para um modelo mais caro. O resultado divulgado no artigo, de at&#233; 98% de redu&#231;&#227;o de custo mantendo a qualidade do melhor modelo individual, vale como teto obtido em benchmarks espec&#237;ficos. Para calibrar expectativa, o dado de produ&#231;&#227;o publicado pela Ramp &#233; mais informativo: o time relata <a href="https://builders.ramp.com/post/thompson-sampling-model-routing">25% a 30% de economia</a>, roteando requisi&#231;&#245;es.</p></li></ul><p>Algumas outras <a href="https://www.finops.org/wg/token-economics-saas/">medidas recomendadas</a> s&#227;o conhecidas de quem j&#225; operou custos de nuvem: </p><ul><li><p>atribuir gasto por funcionalidade e por cliente desde o primeiro dia,</p></li><li><p>aplicar limites de token no gateway em vez de confiar no comportamento da aplica&#231;&#227;o, e </p></li><li><p>configurar alertas sobre a taxa de consumo, n&#227;o apenas sobre o total mensal.</p></li></ul><p>Um agente preso em la&#231;o consome o or&#231;amento do m&#234;s em poucas horas, e o fechamento mensal avisa tarde.</p><h2>N&#227;o-determinismo</h2><p>J&#225; falamos <a href="/__u/ml4se.substack.com/p/porque-eu-nao-posso-confiar-cegamente">aqui no blog</a> sobre alucina&#231;&#245;es, e esse termo ganhou notoriedade popular. </p><p>No entanto, reprodutibilidade bit a bit tem valor em pesquisas sobre aprendizado por refor&#231;o e em depura&#231;&#227;o de c&#243;digo, por exemplo, mas raramente &#233; o objetivo certo em um produto. <strong>O que queremos n&#227;o &#233; eliminar a vari&#226;ncia, e sim medi-la e mant&#234;-la dentro de uma faixa aceit&#225;vel.</strong></p><p>Uma forma comum de medir a vari&#226;ncia &#233; rodar o mesmo input v&#225;rias vezes e observar a distribui&#231;&#227;o das sa&#237;das. </p><p><a href="https://thinkingmachines.ai/blog/defeating-nondeterminism-in-llm-inference/">Em uma pesquisa recente</a>, os autores utilizam o modelo Qwen3-235B, temperatura zero e o mesmo prompt, mas observaram 80 varia&#231;&#245;es distintas. Os primeiros 102 tokens foram id&#234;nticos em todas elas. A diverg&#234;ncia come&#231;ou no token 103. Isso significa que n&#227;o basta apenas configurar a temperatura para zero, precisamos de mecanismos para observar a varia&#231;&#227;o antes que ela vire incidente. </p><p>Para reduzir a vari&#226;ncia, algumas escolhas de projeto ajudam:</p><ol><li><p><strong>Planos de execu&#231;&#227;o.</strong> Gerar um plano com o modelo e execut&#225;-lo de forma estruturada torna cada etapa test&#225;vel e permite rastrear a falha at&#233; o passo exato.</p></li><li><p><strong>Sa&#237;da estruturada com decodifica&#231;&#227;o restrita</strong>. Bibliotecas como Outlines, Guidance e XGrammar compilam um JSON Schema e bloqueiam tokens inv&#225;lidos durante a gera&#231;&#227;o, mesma ideia por tr&#225;s dos <a href="https://openai.com/index/introducing-structured-outputs-in-the-api/">structured outputs da OpenAI</a>. H&#225; uma ressalva pouco divulgada: o <a href="https://arxiv.org/pdf/2501.10868">JSONSchemaBench</a> traz evid&#234;ncia de que a restri&#231;&#227;o pode reduzir a acur&#225;cia do conte&#250;do em compara&#231;&#227;o com extra&#231;&#227;o livre seguida de valida&#231;&#227;o. </p></li><li><p><strong>Diversidade n&#227;o vem de temperatura.</strong> Aumentar a temperatura degrada a qualidade sem produzir a variedade desejada. Alternativas existe, como 1) embaralhar a ordem dos itens no template, 2) manter uma lista de sa&#237;das recentes e 3) instruir o modelo a evit&#225;-las, ou variar o enunciado do prompt.</p></li></ol><p>Medir vari&#226;ncia s&#243; tem utilidade se soubermos <strong>o que conta como resposta boa</strong>, e &#233; aqui que entra o desenho da avalia&#231;&#227;o. </p><p>De acordo com <a href="https://hamel.dev/blog/posts/evals-faq/">alguns</a> <a href="https://eugeneyan.com/writing/evals/">praticantes</a>, primeiro passo n&#227;o &#233; escolher uma biblioteca de avalia&#231;&#227;o nem definir m&#233;tricas, e sim ler sa&#237;das reais. O procedimento que eles descrevem vem da pesquisa qualitativa e tem quatro etapas. </p><ol><li><p>Come&#231;amos reunindo um conjunto de tra&#231;os de execu&#231;&#227;o (traces) representativo do tr&#225;fego real. </p></li><li><p>Sobre ele fazemos open coding, ou codifica&#231;&#227;o aberta, que consiste em anotar em texto livre o que houve de errado em cada sa&#237;da, sem categorias definidas de antem&#227;o, justamente para n&#227;o enxergar apenas as falhas que j&#225; esper&#225;vamos. </p></li><li><p>Em seguida vem o axial coding, ou codifica&#231;&#227;o axial, quando essas anota&#231;&#245;es soltas s&#227;o agrupadas em categorias. </p></li><li><p>A quarta etapa &#233; iterar at&#233; a satura&#231;&#227;o te&#243;rica, o ponto em que novos tra&#231;os param de revelar padr&#245;es in&#233;ditos. </p></li></ol><p>Sobre volume, n&#227;o existe n&#250;mero m&#225;gico: 20 a 50 sa&#237;das costumam ser suficientes na primeira rodada, e a sugest&#227;o para os ciclos seguintes &#233; revisar mais de cem tra&#231;os recentes a cada vez. Uma regra pr&#225;tica ajuda a calibrar o resultado: comece com tr&#234;s crit&#233;rios de avalia&#231;&#227;o. Menos que isso costuma indicar que a tarefa n&#227;o est&#225; bem definida, e muitos mais tornam a avalia&#231;&#227;o dif&#237;cil de manter.</p><p>S&#243; o que sobrevive a essa triagem merece virar avaliador autom&#225;tico, e a ordem de ado&#231;&#227;o vai do mais barato para o mais caro. Por ex, primeiro as asser&#231;&#245;es determin&#237;sticas, escritas a partir de falhas concretas que apareceram na an&#225;lise: verifica&#231;&#245;es de formato, express&#245;es regulares, presen&#231;a de campos obrigat&#243;rios. Depois, para as falhas que resistem &#224;s corre&#231;&#245;es &#243;bvias e que n&#227;o cabem em uma asser&#231;&#227;o, o LLM como juiz. A anota&#231;&#227;o humana fica por &#250;ltimo, reservada ao que os dois n&#237;veis anteriores n&#227;o cobrem. </p><p>Quem chegar ao LLM como juiz precisa trat&#225;-lo como qualquer outro classificador, o que significa tr&#234;s cuidados. </p><ul><li><p>O primeiro &#233; usar julgamento bin&#225;rio, aprovado ou reprovado, em vez de notas de um a cinco, que introduzem subjetividade sem melhorar a decis&#227;o. </p></li><li><p>O segundo &#233; preferir compara&#231;&#227;o entre pares (a vers&#227;o atual contra a candidata) a notas absolutas, apresentando cada par nas duas ordens poss&#237;veis. No paper <a href="https://arxiv.org/abs/2406.07791">Judging the Judges</a>, fo observado que a posi&#231;&#227;o em que uma resposta aparece no prompt altera a prefer&#234;ncia do avaliador. </p></li><li><p>O terceiro &#233; validar o juiz contra r&#243;tulos humanos, medindo taxa de verdadeiros positivos e de verdadeiros negativos em um conjunto de teste. Um juiz que nunca foi comparado com julgamento humano produz n&#250;meros sem significado conhecido. </p></li></ul><p>Vale lembrar tamb&#233;m da lei de Goodhart nesse desenho: quando a m&#233;trica vira alvo, ela deixa de medir bem. Otimizar demais para consist&#234;ncia factual, por exemplo, tende a produzir resumos vagos, que s&#227;o menos inconsistentes e tamb&#233;m menos &#250;teis.</p><div><hr></div><p>Estou considerando abrir uma nova turma sobre Cuidados com LLMs em produ&#231;&#227;o. Se isso parece interessante pra voc&#234;, <a href="https://forms.gle/3VcFaRoxauSzLwnaA">deixe seu contato aqui</a>? </p><div><hr></div><p></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ml4se.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Inscreva-se&quot;,&quot;language&quot;:&quot;pt-br&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">ML4SE &#233; uma newsletter focada em ajudar devs a mastigar t&#233;cnicas de aprendizado de m&#225;quina. Para receber novos posts, se inscreva na newsletter.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Digite seu e-mail&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Inscreva-se"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[O que é harness engineering?]]></title><description><![CDATA[A capacidade de um agente de IA n&#227;o depende apenas do modelo de linguagem, mas tamb&#233;m da infraestrutura respons&#225;vel por sua execu&#231;&#227;o.]]></description><link>https://ml4se.substack.com/p/o-que-e-harness-engineering</link><guid isPermaLink="false">https://ml4se.substack.com/p/o-que-e-harness-engineering</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Fri, 24 Jul 2026 18:48:52 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/afb26bb4-6e44-45d2-b693-d48d93327291_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Antes de tudo, vale uma reflex&#227;o: quando um agente de IA falha ao realizar uma tarefa de desenvolvimento de software, onde est&#225; o problema? Na maioria das vezes, parece que o modelo ainda n&#227;o &#233; &#8220;inteligente&#8221; o suficiente. Se fosse, o modelo capaz de raciocinar melhor, compreender projetos/classes maiores ou planejar sequ&#234;ncias mais longas de a&#231;&#245;es. Esses erros desapareceriam naturalmente.</p><p>Essa forma de pensar direcionaram boa parte da evolu&#231;&#227;o recente dos modelos de linguagem. Modelos maiores, janelas de contexto maiores e novas t&#233;cnicas de treinamento buscaram ampliar as capacidades dos modelos. Por outro lado, em vez de atribuir o sucesso (ou fracasso) de uma tarefa exclusivamente ao modelo, a capacidade de um agente emerge da intera&#231;&#227;o entre tr&#234;s componentes: o modelo, o ambiente e uma camada intermedi&#225;ria chamada <strong>harness</strong>.</p><h2><strong>O que &#233; um harness?</strong></h2><p>O harness &#233; a infraestrutura de execu&#231;&#227;o que envolve um modelo de linguagem durante a realiza&#231;&#227;o de uma tarefa. &#201; essa camada que determina como o agente observa um projeto, quais informa&#231;&#245;es recebe como contexto, quais ferramentas pode utilizar, como interpreta o retorno de suas a&#231;&#245;es e quais evid&#234;ncias utiliza para concluir que uma tarefa foi realmente finalizada. </p><p><em>O harness &#233; uma plataforma com v&#225;rios componentes; o modelo &#233; apenas um deles.</em></p><p>O modelo deixa de ser visto como o &#250;nico respons&#225;vel pelo comportamento do agente. Da mesma forma que um desenvolvedor depende de IDEs, sistemas de versionamento, ferramentas de teste e documenta&#231;&#227;o para realizar seu trabalho, um agente tamb&#233;m depende de uma infraestrutura que organize sua intera&#231;&#227;o com o ambiente.</p><p>Sob essa perspectiva, um modelo extremamente capaz pode ter desempenho mediano quando executado sobre um harness limitado. Da mesma forma, melhorias no harness podem aumentar significativamente a confiabilidade do sistema sem qualquer altera&#231;&#227;o no modelo utilizado.</p><h2><strong>Mais do que uma camada de integra&#231;&#227;o</strong></h2><p>&#192; primeira vista, pode parecer que o harness seja apenas uma camada respons&#225;vel por conectar o modelo &#224;s ferramentas dispon&#237;veis. N&#227;o somente.</p><p>O harness &#233; respons&#225;vel por diversas fun&#231;&#245;es fundamentais durante todo o ciclo de vida de uma tarefa. Vai desde a especifica&#231;&#227;o da tarefa, a sele&#231;&#227;o de contexto, o acesso &#224;s ferramentas, o gerenciamento da mem&#243;ria do projeto, o acompanhamento do estado da tarefa, a observabilidade da execu&#231;&#227;o, a atribui&#231;&#227;o de falhas, os mecanismos de verifica&#231;&#227;o, o controle de permiss&#245;es, a auditoria de entropia e o registro das interven&#231;&#245;es realizadas durante a execu&#231;&#227;o. Muita coisa, muito detalhe.</p><p>O harness ajuda a organiza toda a intera&#231;&#227;o entre o modelo e o ambiente de desenvolvimento.</p><h2><strong>A capacidade emerge do sistema</strong></h2><p>Tradicionalmente, costuma-se avaliar um agente observando apenas sua sa&#237;da final. Se ele produziu um patch correto, considera-se que foi bem-sucedido. Caso contr&#225;rio, conclui-se que o modelo tem limita&#231;&#245;es.</p><p>No entanto, a capacidade de um agente &#233; uma propriedade do sistema completo formado pelo modelo, pelo harness e pelo ambiente. Isso significa que falhas podem estar relacionadas n&#227;o apenas ao racioc&#237;nio do modelo, mas tamb&#233;m &#224; forma como o contexto foi constru&#237;do.</p><h2><strong>N&#237;veis de Harness</strong></h2><p>Para tornar essa ideia mais concreta, existe inclusive <a href="https://arxiv.org/abs/2605.13357">uma classifica&#231;&#227;o </a>composta por quatro n&#237;veis de harness, denominados H0 at&#233; H3.</p><ul><li><p><strong><span>H0</span></strong><span>: Produz apenas o resultado final (por exemplo, um patch), com pouca ou nenhuma evid&#234;ncia sobre sua execu&#231;&#227;o.</span></p></li><li><p><strong><span>H1</span></strong><span>: Adiciona registros b&#225;sicos da execu&#231;&#227;o, permitindo reproduzir as a&#231;&#245;es realizadas pelo agente.</span></p></li><li><p><strong><span>H2</span></strong><span>: Incorpora mecanismos de verifica&#231;&#227;o e atribui&#231;&#227;o de falhas, aumentando a confiabilidade dos resultados.</span></p></li><li><p><strong><span>H3</span></strong><span>: Produz um pacote completo de evid&#234;ncias (</span><em><span>episode package</span></em><span>), reunindo contexto, execu&#231;&#227;o, verifica&#231;&#245;es e rastreabilidade para auditoria e reprodu&#231;&#227;o.</span></p></li></ul><p>O aspecto interessante dessa classifica&#231;&#227;o &#233; que ela n&#227;o mede a intelig&#234;ncia do modelo. Ela mede o n&#237;vel de suporte oferecido ao agente durante sua execu&#231;&#227;o. Conforme o harness evolui, cresce tamb&#233;m a quantidade de evid&#234;ncias produzidas para justificar e validar as mudan&#231;as realizadas.</p><h2><strong>A avalia&#231;&#227;o de qualidade vai al&#233;m da resposta do modelo</strong></h2><p>Essa vis&#227;o tamb&#233;m leva a uma mudan&#231;a na forma de avaliar agentes de c&#243;digo.</p><p>Em vez de considerar apenas se uma tarefa foi conclu&#237;da com sucesso, podemos registrar toda a trajet&#243;ria de execu&#231;&#227;o em um pacot&#227;o de logs. Com os logs, podemos, analisar n&#227;o somente o resultado final, mas como o agente chegou ao resultado, quais decis&#245;es tomou, quais verifica&#231;&#245;es realizou e quais falhas foram identificadas ao longo do processo.</p><h2><strong>Competindo com as big techs?</strong></h2><p>Durante muito tempo, a pergunta que muitos pesquisadores e praticantes faziam era se um modelo de linguagem seria capaz de produzir o c&#243;digo correto. Agora a pergunta &#233; outra: a plataforma de harness consegue produzir um c&#243;digo correto, verific&#225;vel e pass&#237;vel de manuten&#231;&#227;o?</p><p>Aqui abre um espa&#231;o para laborat&#243;rios e empresas que est&#227;o longe da saude financeira das bigtechs, uma vez que n&#227;o precisamos concentrar os esfor&#231;os em aumentar a capacidade dos modelos. Podemos, por outro lago, nos preocupar em criar uma infraestrutura que sustenta sua execu&#231;&#227;o (de modelos menores, mais baratos ou mais r&#225;pidos).</p>]]></content:encoded></item><item><title><![CDATA[Modelos de Contexto Longo Não Tornarão RAG Obsoleto]]></title><description><![CDATA[Com os avan&#231;os recentes nos modelos lingu&#237;sticos e no processamento de linguagem natural, os modelos de contexto longo t&#234;m gerado entusiasmo nas comunidades de pesquisa e desenvolvimento de aplica&#231;&#245;es baseadas em LLMs.]]></description><link>https://ml4se.substack.com/p/modelos-de-contexto-longo-nao-tornarao</link><guid isPermaLink="false">https://ml4se.substack.com/p/modelos-de-contexto-longo-nao-tornarao</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Sun, 30 Jun 2024 17:52:46 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/fcc5cda0-17c7-4f8f-a112-fd8c087269f6_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Com os avan&#231;os recentes nos modelos lingu&#237;sticos e no processamento de linguagem natural, os modelos de contexto longo t&#234;m gerado entusiasmo nas comunidades de pesquisa e desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. Esses modelos s&#227;o capazes de n&#227;o somente considerar centenas de milhares (ou at&#233; milh&#245;es) de tokens para gerar respostas, mas tamb&#233;m prometem melhorias significativas na precis&#227;o e na relev&#226;ncia das respostas geradas. </p><p>Dessa forma, o uso de modelos de contexto longo pode parecer uma solu&#231;&#227;o alternativa para aqueles que desenvolvem solu&#231;&#245;es baseadas na arquitetura RAG &#8212; em que informa&#231;&#245;es externas s&#227;o fornecidas para um modelo de forma a tornar sua resposta mais precisa e relevante. </p><p>Um dos pilares da arquitetura RAG est&#225; na estrat&#233;gia de busca e sele&#231;&#227;o das informa&#231;&#245;es que s&#227;o passadas para a LLM. No RAG, o processo de busca precisa ser cuidadosamente desenhado para que documentos relevantes sejam selecionados e enviados para o modelo lingu&#237;stico; diminuindo o ru&#237;do e aumentando a qualidade das respostas. </p><p>No entanto, quando se fala em modelos de contextos longo, na casa de milh&#245;es de tokens, a primeira vista pode-se imaginar que essa etapa de busca e sele&#231;&#227;o de informa&#231;&#245;es pode se tornar menos relevante, uma vez que o modelo &#233; capaz de processar um n&#250;mero muito maior de documentos. Voc&#234; pode simplesmente colocar todos seus dados no contexto com o modelo!</p><p>Nesse texto, argumento h&#225; tr&#234;s motivos pelo quais modelos de contexto longo n&#227;o devem tornar a arquitetura RAG obsoleta.</p><div><hr></div><h2>Bootcamp LLM4Devs</h2><p>&#128218; Voc&#234; &#233; dev e quer criar aplica&#231;&#245;es baseadas em LLMs?</p><p>O bootcamp <strong>#LLM4Devs</strong> &#233; um evento que acontece uma vez por m&#234;s, em formato online de 4h de dura&#231;&#227;o, focado em ajudar devs a construir sua primeira aplica&#231;&#227;o baseada em LLMs. &#201; um evento super <em>hands on</em>!</p><p>Alguns dos t&#243;picos abordados:</p><p>&#128992; Entendendo sobre LLMs</p><p>&#128995; Testando prompts e engenharia de prompts</p><p>&#128309; Entendendo de embeddings</p><p>&#128994; Comparando dados por similaridade</p><p>&#128993; Conectando com um banco vetorial</p><p>E tem mais! Se inscrevendo no bootcamp, <a href="https://gustavopinto.gumroad.com/l/llm4devs">voc&#234; ganha acesso a tr&#234;s cursos sobre LLMs</a>.</p><p>Interessou? Clique aqui e saiba mais:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://llmbootcamp.dev/&quot;,&quot;text&quot;:&quot;Bootcamp LLM4Devs&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://llmbootcamp.dev/"><span>Bootcamp LLM4Devs</span></a></p><div><hr></div><h2>RAG em 2 minutos</h2><p>Os modelos RAG combinam a capacidade de recupera&#231;&#227;o de informa&#231;&#245;es de grandes bancos de dados com a gera&#231;&#227;o de texto contextualizado, permitindo que os modelos de linguagem lidem com informa&#231;&#245;es atualizadas e espec&#237;ficas que n&#227;o est&#227;o contidas em seu treinamento original. </p><p>Isso &#233; particularmente importante, pois o conhecimento armazenado em modelos de linguagem geralmente est&#225; desatualizado ou incompleto. Al&#233;m disso, os modelos RAG s&#227;o projetados para mitigar problemas como alucina&#231;&#245;es e desinforma&#231;&#227;o, proporcionando respostas mais confi&#225;veis.</p><p>Para saber um pouco mais sobre a arquitetura RAG, <a href="/__u/ml4se.substack.com/p/arquitetura-de-uma-solucao-baseada">veja esse texto da newsletter</a>.</p><h2>Modelos longos ainda precisam do RAG</h2><p>H&#225; pelo menos tr&#234;s raz&#245;es pelas quais modelos longo ainda devem precisar se apoiar em arquiteturas como o RAG.</p><ul><li><p><strong>Primeiro, mesmo com uma janela de contexto de 10 milh&#245;es de tokens, ainda precisar&#237;amos de uma maneira de selecionar a informa&#231;&#227;o mais relevante a ser alimentada no modelo.</strong> Por exemplo, considere um cen&#225;rio onde um pesquisador est&#225; analisando uma vasta cole&#231;&#227;o de artigos cient&#237;ficos para responder a uma pergunta espec&#237;fica. Mesmo que o modelo possa processar todos esses artigos simultaneamente, ele ainda precisa identificar quais partes dos textos s&#227;o mais pertinentes para fornecer uma resposta precisa. Sem um mecanismo eficaz de sele&#231;&#227;o de informa&#231;&#245;es, a capacidade de processamento aumentada pode se tornar uma desvantagem, levando a respostas confusas ou incorretas.</p></li><li><p><strong>Segundo, ainda faltam avalia&#231;&#245;es detalhadas sobre como LLMs podem raciocinar em contextos t&#227;o grande</strong>s. Sem uma boa recupera&#231;&#227;o e classifica&#231;&#227;o, corremos o risco de sobrecarregar o modelo com ru&#237;dos ou at&#233; mesmo preencher a janela de contexto com informa&#231;&#245;es completamente irrelevantes. Imagine um sistema de atendimento ao cliente que tenta responder a uma consulta complexa. Se o modelo for inundado com transcri&#231;&#245;es de conversas passadas sem filtragem adequada, ele pode se perder em detalhes desnecess&#225;rios e fornecer respostas imprecisas. Avalia&#231;&#245;es detalhadas ajudam a entender como os modelos lidam com grandes quantidades de dados e para desenvolver m&#233;todos que melhorem sua capacidade de racioc&#237;nio em tais contextos.</p></li><li><p><strong>Finalmente, h&#225; o custo.</strong> O custo de infer&#234;ncia do Transformer tende a escalar com o comprimento do contexto. Modelos mais recentes, como o GPT-4, s&#227;o significativamente mais caros em termos de processamento em compara&#231;&#227;o com modelos anteriores como o GPT-3.5. Por exemplo, usar o GPT-4 pode ser at&#233; dez vezes mais caro que usar o GPT-3.5 para a mesma tarefa. Em aplica&#231;&#245;es comerciais, esse aumento nos custos pode ser proibitivo. Empresas que dependem de respostas r&#225;pidas e eficientes podem achar insustent&#225;vel o uso de modelos de contexto longo sem um retorno claro sobre o investimento.</p></li></ul><h2>Modelos longos precisam ser avaliados</h2><p>Embora esses modelos de contexto longo tragam luz para um grande n&#250;mero de aplica&#231;&#245;es, seu desempenho ainda &#233; pouco conhecido. No artigo <a href="https://arxiv.org/pdf/2309.01431">Benchmarking Large Language Models in Retrieval-Augmented Generation</a>, os autores prop&#245;e algumas formas em que esses LLMs (utilizados em conjunto de aplica&#231;&#245;es baseadas em RAG) precisam ser avaliados para que seu comportamento seja mais conhecido. </p><p>Por exemplo:</p><ul><li><p><strong>A Robustez ao Ru&#237;do</strong> &#233; a capacidade dos LLMs em lidar com documentos ruidosos. Como os recuperadores n&#227;o s&#227;o perfeitos, o conhecimento externo que eles recuperam frequentemente cont&#233;m uma quantidade significativa de ru&#237;do, ou seja, documentos que s&#227;o relevantes para a pergunta, mas n&#227;o cont&#234;m nenhuma informa&#231;&#227;o sobre a resposta. Para responder efetivamente &#224;s perguntas dos usu&#225;rios, os LLMs devem ser capazes de extrair a informa&#231;&#227;o necess&#225;ria dos documentos, apesar da presen&#231;a de documentos ruidosos.</p></li><li><p><strong>A Rejei&#231;&#227;o Negativa</strong> &#233; uma forma para que o LLM n&#227;o responda uma pergunta quando o contexto n&#227;o fornece informa&#231;&#245;es &#250;teis. Quando o mecanismo de busca falha em recuperar documentos contendo as respostas, &#233; importante que o modelo tenha a capacidade de rejeitar o reconhecimento e evitar gerar conte&#250;do enganoso.</p></li><li><p><strong>A Integra&#231;&#227;o de Informa&#231;&#245;es</strong> &#233; a capacidade de integrar respostas de v&#225;rios documentos. Em muitos casos, a resposta a uma pergunta pode estar contida em v&#225;rios documentos. Por exemplo, para a pergunta "Quem s&#227;o os campe&#245;es do U.S. Open 2022 nas categorias de simples masculino e feminino?", os dois campe&#245;es podem ser mencionados em documentos diferentes. Para fornecer melhores respostas a perguntas complexas, &#233; necess&#225;rio que os LLMs tenham a capacidade de integrar informa&#231;&#245;es.</p></li><li><p><strong>A Robustez Contrafactual</strong> refere-se &#224; capacidade de lidar com erros no conhecimento externo. No mundo real, h&#225; uma abund&#226;ncia de informa&#231;&#245;es falsas na internet. Note que avaliamos apenas a situa&#231;&#227;o em que os LLMs recebem avisos sobre potenciais riscos nas informa&#231;&#245;es recuperadas por meio de instru&#231;&#245;es.</p></li></ul><p>Com a cria&#231;&#227;o desses benchmarks, a decis&#227;o para quando utilizar os modelos se torna mais facilitada para os seus usu&#225;rios.</p><h2>Conclus&#227;o</h2><p>Enquanto os modelos de contexto longo oferecem benef&#237;cios substanciais, eles ainda enfrentam desafios, como a incorpora&#231;&#227;o de documentos ruidosos e a integra&#231;&#227;o de informa&#231;&#245;es de m&#250;ltiplas fontes. </p><p>Por outro lado, os modelos RAG continuam a evoluir, combinando a robustez ao ru&#237;do e a capacidade de rejeitar respostas quando os dados s&#227;o inadequados. </p><p>Portanto, a evolu&#231;&#227;o das tecnologias de IA provavelmente ver&#225; uma coexist&#234;ncia e uma integra&#231;&#227;o crescente entre modelos de contexto longo e RAG, cada um complementando as limita&#231;&#245;es do outro para fornecer solu&#231;&#245;es mais completas e precisas no processamento de linguagem natural.</p>]]></content:encoded></item><item><title><![CDATA[Como usar modelos linguísticos abertos?]]></title><description><![CDATA[N&#227;o &#233; novidade que modelos lingu&#237;sticos propriet&#225;rios como o GPT da OpenAI e o Gemini do Google s&#227;o possivelmente as primeiras alternativas quando se come&#231;a a trabalhar no desenvolvimento de aplica&#231;&#245;es baseadas em LLMs.]]></description><link>https://ml4se.substack.com/p/como-usar-modelos-linguisticos-abertos</link><guid isPermaLink="false">https://ml4se.substack.com/p/como-usar-modelos-linguisticos-abertos</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Sat, 22 Jun 2024 19:45:57 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/cf297e16-5c39-49cb-9707-1ec400c7500e_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>N&#227;o &#233; novidade que modelos lingu&#237;sticos propriet&#225;rios como o GPT da OpenAI e o Gemini do Google s&#227;o possivelmente as primeiras alternativas quando se come&#231;a a trabalhar no desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. </p><p>Embora esses modelos sejam capazes de responder acuradamente um n&#250;mero quase sem fim de quest&#245;es de amplo dom&#237;nio, esses modelos ainda contam com uma barreira significativa, em particular, para o usu&#225;rio comum: o custo financeiro. </p><p>Utilizar esses modelos para realizar algumas pequenas chamadas podem n&#227;o ser algo necessariamente custoso do ponto de vista monet&#225;rio. No entanto, como geralmente o modelo de precifica&#231;&#227;o desses modelos est&#225; associado a quantidade de chamadas realizadas a suas APIs, o custo tende a aumentar a medida que se aumenta a base de usu&#225;rios de um sistema baseado em LLMs. </p><p>N&#227;o obstante, as vers&#245;es mais recentes desses modelos &#8212;aquelas com melhor acur&#225;cia&#8212; tendem a ser as mais caras, o que sobrecarrega ainda mais o custo do pequeno usu&#225;rio. Ademais, embora muitos desses modelos forne&#231;am calculadoras que ajudem a dar uma previsibilidade no custo total do uso dos modelos, realizar esse tipo de conta n&#227;o &#233; uma tarefa f&#225;cil, uma vez que algumas vari&#225;veis n&#227;o s&#227;o conhecidas antecipadamente (como a quantidade de usu&#225;rios acessando o sistema e os tipos de usos desses usu&#225;rios). </p><p>Como forma de minimizar essa limita&#231;&#227;o financeira, algumas empresas, universidades e entidades p&#250;blicas tem disponibilizado vers&#245;es abertas de modelos lingu&#237;sticos. Esses modelos, muitas vezes tem desempenho semelhante (ou at&#233; superior) a modelos lingu&#237;sticos propriet&#225;rios, torando-se assim solu&#231;&#245;es para aqueles interessados em construir aplica&#231;&#245;es baseadas em LLMs, por&#233;m diminuindo o custo de invoca&#231;&#245;es de APIs privadas.</p><p>Nesse texto, vamos conhecer alguns desses modelos e abordar algumas formas de consumi-los.</p><div><hr></div><h2>Bootcamp LLM4Devs</h2><p>&#128218; Voc&#234; &#233; dev e quer criar aplica&#231;&#245;es baseadas em LLMs?</p><p>O bootcamp <strong>#LLM4Devs</strong> &#233; um evento que acontece uma vez por m&#234;s, em formato online de 4h de dura&#231;&#227;o, focado em ajudar devs a construir sua primeira aplica&#231;&#227;o baseada em LLMs. &#201; um evento super <em>hands on</em>!</p><p>Alguns dos t&#243;picos abordados:</p><p>&#128992; Entendendo sobre LLMs</p><p>&#128995; Testando prompts e engenharia de prompts</p><p>&#128309; Entendendo de embeddings</p><p>&#128994; Comparando dados por similaridade</p><p>&#128993; Conectando com um banco vetorial</p><p>E tem mais! Se inscrevendo no bootcamp, <a href="https://gustavopinto.gumroad.com/l/llm4devs">voc&#234; ganha acesso a tr&#234;s cursos sobre LLMs</a>.</p><p>Interessou? Clique aqui e saiba mais:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://llmbootcamp.dev/&quot;,&quot;text&quot;:&quot;Bootcamp LLM4Devs&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://llmbootcamp.dev/"><span>Bootcamp LLM4Devs</span></a></p><div><hr></div><h3>Onde posso encontrar esses modelos abertos?</h3><p>Geralmente, o primeiro local para se procurar por modelos abertos &#233; no HuggingFace. Se voc&#234; ainda n&#227;o conhece, dedique um tempo para criar uma conta, navegar e entender um pouco das principais funcionalidades desse site. </p><p>Em uma analogia simples, voc&#234; pode entender que o HuggingFace &#233; o GitHub para modelos. Ou seja, um reposit&#243;rio de c&#243;digo do GitHub &#233; an&#225;logo a um reposit&#243;rio de modelo no HuggingFace. </p><p>Outro ponto interessante &#233; que o HuggingFace hospeda n&#227;o somente modelos lingu&#237;sticos, mas tamb&#233;m modelos de imagens para texto, de voz para texto, multimodais, etc. H&#225; centenas de milhares de modelos que podem ser facilmente acessados. Umas dessas formas de acess&#225;-los &#233; atrav&#233;s da biblioteca <code>transformers</code>, desenvolvida pelo pr&#243;prio HuggingFace. </p><p>No entanto, nesse texto, faremos uso do LangChain para acessar os modelos dispon&#237;veis no HuggingFace. Usaremos o LangChain, pois, embora a biblioteca transformers seja mais robusta, ao meu ver, o LangChain fornece uma interface mais intuitiva e amig&#225;vel (dado um menor n&#250;mero de configura&#231;&#245;es necess&#225;rias) para acessar os modelos do HuggingFace.</p><h3>Quais modelos posso utilizar?</h3><p>Como mencionamos, o HunggingFace tem centenas de milhares de modelos hospedados. E como no GitHub, muitos desses modelos tem baixa qualidade ou n&#227;o s&#227;o mais mantidos. Dessa forma, &#233; importante fazer um trabalho de pesquisa e curadoria antes de utilizar algum modelo menos conhecido em um ambiente mais produtivo.  </p><p>Para facilitar, sugiro aqui alguns dos modelos lingu&#237;sticos que poderiam ser utilizados inicialmente:</p><ul><li><p><a href="https://huggingface.co/mistralai/Mistral-7B-Instruct-v0.3">mistralai/Mistral-7B-Instruct-v0.3</a>: O Mistral-7B-Instruct-v0.3 &#233; um modelo de linguagem grande de 7 bilh&#245;es de par&#226;metros desenvolvido pela Mistral AI. Este modelo &#233; ajustado especificamente para seguir instru&#231;&#245;es, tornando-o adequado para tarefas que requerem compreens&#227;o contextual e respostas precisas em linguagem natural.</p></li><li><p><a href="https://huggingface.co/microsoft/Phi-3-mini-4k-instruct">microsoft/Phi-3-mini-4k-instruct:</a> O Phi-3-mini-4k-instruct da Microsoft &#233; um modelo compacto com um foco em efici&#234;ncia e desempenho. Com otimiza&#231;&#227;o para tarefas de instru&#231;&#227;o, ele &#233; projetado para processar e responder a consultas complexas, mantendo um equil&#237;brio entre qualidade de resposta e consumo de recursos computacionais. <a href="/__u/ml4se.substack.com/p/conheca-o-phi-3-um-modelo-linguagem">J&#225; escrevemos sobre ele aqui na newsletter</a>.</p></li><li><p><a href="https://huggingface.co/meta-llama/Meta-Llama-3-8B-Instruct">meta-llama/Meta-Llama-3-8B-Instruct:</a> O Meta-Llama-3-8B-Instruct &#233; um modelo robusto de 8 bilh&#245;es de par&#226;metros criado pela Meta. Este modelo tem uma arquitetura avan&#231;a e permite seguir instru&#231;&#245;es em diversas tarefas de processamento de linguagem natural. <a href="/__u/ml4se.substack.com/p/explorando-o-llama-3-com-langchain">Tamb&#233;m j&#225; escrevemos sobre ele aqui na newsletter.</a></p></li></ul><h3>Uso pela API de infer&#234;ncia do HuggingFace</h3><p>Como mencionado, vamos utilizar o LangChain para acessar esses modelos. Podemos come&#231;ar instalando o LangChain:</p><pre><code>pip install langchain</code></pre><p>Uma vez instalado, vamos usar a API HuggingFaceEndpoint, que fornece acesso ao endpoint de infer&#234;ncia do modelo no HuggingFace. </p><p>Esse endpoint torna simples o acesso aos modelos, uma vez que n&#227;o se faz necess&#225;rio baixar e configura-los localmente. Todavia, &#233; importante notar que nem todos os modelos est&#227;o dispon&#237;veis atrav&#233;s desse endpoint. </p><p>Para que seja poss&#237;vel acessar o endpoint, &#233; necess&#225;rio criar uma conta e, em seguida, um token no seu perfil no HuggingFace.</p><p>Com esse token em m&#227;os, podemos fazer nossa primeira requisi&#231;&#227;o a um modelo aberto, hospedado (e executando) no HuggingFace.</p><pre><code>from langchain.llms import HuggingFaceHub
import os

os.environ["HUGGINGFACEHUB_API_TOKEN"] = TOKEN

llm = HuggingFaceEndpoint(repo_id="meta-llama/Meta-Llama-3-70B-Instruct", task="text-generation")

prompt = """
        &lt;|begin_of_text|&gt;
        &lt;|start_header_id|&gt;system&lt;|end_header_id|&gt;
        Voc&#234; &#233; um assistente de c&#243;digo especializado em culin&#225;ria.
        &lt;|eot_id|&gt;
        &lt;|start_header_id|&gt;user&lt;|end_header_id|&gt;
        Me fa&#231;a uma lasanha vegana.
        &lt;|eot_id|&gt;
        &lt;|start_header_id|&gt;assistant&lt;|end_header_id|&gt;
        """

llm.invoke(prompt)</code></pre><p>Este c&#243;digo importa a biblioteca `HuggingFaceHub` do Langchain e a biblioteca `os` para manipula&#231;&#227;o de vari&#225;veis de ambiente. Ele configura a vari&#225;vel de ambiente <code>HUGGINGFACEHUB_API_TOKEN</code> com um token de acesso necess&#225;rio para autenticar e acessar os recursos do HuggingFace Hub. Em seguida, um objeto chamado <code>llm</code> &#233; criado usando a classe <code>HuggingFaceEndpoint</code>, especificando o reposit&#243;rio do modelo <code>meta-llama/Meta-Llama-3-70B-Instruct</code> e definindo a tarefa como "<code>text-generation</code>", que indica que o modelo ser&#225; usado para gerar texto.</p><p>Ap&#243;s a configura&#231;&#227;o do modelo, o c&#243;digo define um prompt, que &#233; um texto de entrada formatado para orientar a gera&#231;&#227;o de texto do modelo. Note que o prompt &#233; ligeiramente diferente, pois conta com uma s&#233;rie de tokens especiais que ajudam o modelo a responder de maneira mais assertiva. Cada modelo aberto tende a ter seus pr&#243;prios tokens especiais, e conhecer esses tokens &#233; fundamental para uma boa comunica&#231;&#227;o com o modelo.</p><p>Finalmente, o c&#243;digo chama o m&#233;todo `<code>invoke</code>` do objeto LLM, passando o prompt para gerar uma resposta baseada nas instru&#231;&#245;es fornecidas. Este processo permite que o modelo produza uma resposta &#224; solicita&#231;&#227;o do usu&#225;rio.</p><h3>Uso do modelo localmente</h3><p>Podemos tamb&#233;m baixar e rodar um modelo localmente. Par isso, utilizaremos a biblitoeca <a href="https://github.com/ggerganov/llama.cpp">LLamaCPP</a>.</p><p>O LLamaCPP permite o uso de modelos empacotados como arquivos de formato gguf, que rodam em ambientes somente CPU e mistos CPU/GPU.</p><p>Para usar o LlamaCPP, precisamos de modelos cujo caminho do modelo termine com gguf. Para encontra-los, voc&#234; pode fazer buscas no pr&#243;prio HunggingFace pelo nome do seu modelo, mais a extens&#227;o gguf. </p><pre><code>from langchain_community.llms import LlamaCpp

drive.mount('/content/drive')

llm = LlamaCpp(
            model_path="Phi-3-mini-4k-instruct.gguf",
            temperature=0.75,
            top_p=1,
            verbose=True,
            n_ctx=4096
            )

prompt = """&lt;|user|&gt;
How to explain Internet for a medieval knight?&lt;|end|&gt;
&lt;|assistant|&gt;"""

response = llm.invoke(prompt)
print(response)</code></pre><p>No exemplo acima, usamos o modelo phi-3, logo o prompt deve utilizar os tokens seguidos por esse modelo. Note que &#233; poss&#237;vel definir ainda alguns par&#226;metros durante a instancia&#231;&#227;o do objeto llm. Considere <a href="https://api.python.langchain.com/en/latest/llms/langchain_community.llms.llamacpp.LlamaCpp.html">navegar pela documenta&#231;&#227;o oficial</a> para conhecer mais sobre esses par&#226;metros.</p><h2>Conclus&#227;o</h2><p>Concluindo, enquanto modelos lingu&#237;sticos propriet&#225;rios, como o GPT da OpenAI e o Gemini do Google, s&#227;o frequentemente as primeiras escolhas para desenvolvedores iniciando em aplica&#231;&#245;es baseadas em LLMs, seu uso pode se tornar financeiramente invi&#225;vel &#224; medida que a base de usu&#225;rios cresce. A precifica&#231;&#227;o baseada no volume de chamadas &#224;s suas APIs pode tornar os custos proibitivos, especialmente para pequenas empresas ou desenvolvedores individuais. Al&#233;m disso, as vers&#245;es mais precisas desses modelos tendem a ser as mais caras, aumentando ainda mais o desafio financeiro.</p><p>Felizmente, a crescente disponibilidade de modelos abertos oferece uma alternativa vi&#225;vel e econ&#244;mica. Plataformas como o HuggingFace disponibilizam uma vasta gama de modelos de alta qualidade que podem ser utilizados gratuitamente ou a um custo significativamente menor. Neste texto, exploramos como utilizar alguns desses modelos atrav&#233;s do LangChain, uma biblioteca que facilita o acesso e a integra&#231;&#227;o desses modelos em suas aplica&#231;&#245;es. Com isso, desenvolvedores podem criar solu&#231;&#245;es robustas e eficientes, minimizando os custos associados ao uso de modelos lingu&#237;sticos propriet&#225;rios.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ml4se.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Inscreva-se&quot;,&quot;language&quot;:&quot;pt-br&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">ML4SE &#233; uma newsletter focada em ajudar devs a mastigar t&#233;cnicas de aprendizado de m&#225;quina. Para receber novos posts, se inscreva na newsletter.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Digite seu e-mail&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Inscreva-se"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Conheça o Phi-3, um Modelo Linguagem Compacto]]></title><description><![CDATA[Nos &#250;ltimos anos, o progresso not&#225;vel da IA pode ser amplamente atribu&#237;do aos esfor&#231;os para ampliar os conjuntos de dados e modelos cada vez maiores.]]></description><link>https://ml4se.substack.com/p/conheca-o-phi-3-um-modelo-linguagem</link><guid isPermaLink="false">https://ml4se.substack.com/p/conheca-o-phi-3-um-modelo-linguagem</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Mon, 17 Jun 2024 01:19:52 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/de8cb9af-d0e5-48aa-bf0d-2b2c2cddd7b4_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Nos &#250;ltimos anos, o progresso not&#225;vel da IA pode ser amplamente atribu&#237;do aos esfor&#231;os para ampliar os conjuntos de dados e modelos cada vez maiores. Os LLMs aumentaram de tamanho de meros bilh&#245;es de par&#226;metros h&#225; apenas cinco anos (GPT-2 tinha 1,5 bilh&#245;es de par&#226;metros) para trilh&#245;es de par&#226;metros atualmente.</p><p>O direcionamento para esse esfor&#231;o &#233; em parte devido as melhorias que s&#227;o obtidas ao treinar modelos com quantidade de dados cada vez maiores. Ou seja, ao aumentar o tamanho de um modelo de linguagem (adicionando mais par&#226;metros) e ao treinar com mais dados, o desempenho do modelo tende a melhorar o desempenho de maneira previs&#237;vel e consistente &#8212; o que &#233; conhecido como <em>scaling laws</em>. </p><p>No entanto, essa teoria agora &#233; desafiada pela exist&#234;ncia de novos modelos menores que permitem interagir com dados de novas maneiras.</p><p><a href="https://export.arxiv.org/pdf/2404.14219">Em trabalhos anteriores sobre os modelos phi</a>, foi mostrado que uma combina&#231;&#227;o de dados da web dispon&#237;vel publicamente e dados sint&#233;ticos criados por LLM, possibilita um desempenho em modelos menores que normalmente s&#243; era visto em modelos muito maiores. </p><p>Um exemplo&nbsp;&#233; modelo lingu&#237;stico phi-2 (de 2.7 bilh&#245;es de par&#226;metros), que teve desempenho similar a de modelos 25 vezes maiores treinados com dados regulares. </p><div><hr></div><h2>Bootcamp LLM4Devs</h2><p>&#128218; Voc&#234; &#233; dev e quer criar aplica&#231;&#245;es baseadas em LLMs?</p><p>No pr&#243;ximo dia 13/07/2024 (s&#225;bado), vai rolar um bootcamp online de 4h de dura&#231;&#227;o, sobre desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. Vai ser super <em>hands on</em>!</p><p>Alguns dos t&#243;picos abordados:</p><p>&#128992; Entendendo sobre LLMs</p><p>&#128995; Testando prompts e engenharia de prompts</p><p>&#128309; Entendendo de embeddings</p><p>&#128994; Comparando dados por similaridade</p><p>&#128993; Conectando com um banco vetorial</p><p>E tem mais! Se inscrevendo no bootcamp, <a href="https://gustavopinto.gumroad.com/l/llm4devs">voc&#234; ganha acesso a tr&#234;s cursos sobre LLMs</a>.</p><p>Interessou? Clique aqui e saiba mais:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://llmbootcamp.dev/&quot;,&quot;text&quot;:&quot;Bootcamp LLM4Devs&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://llmbootcamp.dev/"><span>Bootcamp LLM4Devs</span></a></p><div><hr></div><h2>Small language models</h2><p>Os "small language models" (SLMs), ou pequenos modelos de linguagem, s&#227;o uma classe de modelos que possuem um n&#250;mero relativamente pequeno de par&#226;metros em compara&#231;&#227;o com osLLMs. Enquanto os LLMs, como o GPT-3, possuem bilh&#245;es ou at&#233; trilh&#245;es de par&#226;metros, os SLMs t&#234;m uma quantidade significativamente menor, muitas vezes na faixa de milh&#245;es a poucos bilh&#245;es de par&#226;metros.</p><p>A principal vantagem dos SLMs &#233; a sua efici&#234;ncia. Devido ao menor n&#250;mero de par&#226;metros, eles requerem menos poder computacional e mem&#243;ria para treinamento e execu&#231;&#227;o, tornando-os mais acess&#237;veis para organiza&#231;&#245;es com recursos limitados. Essa efici&#234;ncia permite que os SLMs sejam implantados em dispositivos locais, como smartphones e computadores pessoais, sem a necessidade de conex&#227;o constante &#224; nuvem. Isso n&#227;o apenas reduz a lat&#234;ncia nas respostas, mas tamb&#233;m aumenta a privacidade dos dados, pois as informa&#231;&#245;es n&#227;o precisam ser enviadas para servidores remotos.</p><p>Apesar de seu tamanho menor, os SLMs podem ser altamente eficazes em uma variedade de tarefas de processamento de linguagem natural. Isso &#233; poss&#237;vel gra&#231;as a t&#233;cnicas avan&#231;adas de treinamento que utilizam dados de alta qualidade e novos m&#233;todos de filtragem. Por exemplo, os SLMs podem ser treinados com conjuntos de dados cuidadosamente selecionados e sinteticamente gerados, permitindo que eles alcancem desempenho semelhante ao de modelos maiores em tarefas espec&#237;ficas.</p><p>Al&#233;m disso, os SLMs s&#227;o mais facilmente ajust&#225;veis para aplica&#231;&#245;es especializadas. Organiza&#231;&#245;es podem personalizar esses modelos para atender a necessidades espec&#237;ficas com menos esfor&#231;o e recursos do que seriam necess&#225;rios para adaptar um LLM. Isso os torna ideais para cen&#225;rios onde a rapidez na resposta e a execu&#231;&#227;o local s&#227;o cruciais, como em sistemas de suporte ao cliente, dispositivos de IoT e aplicativos em &#225;reas remotas com conectividade limitada.</p><h2>Phi-3-mini, o estado da arte do SLMs</h2><p>O modelo <strong>phi-3-mini </strong>&#233; um <a href="https://huggingface.co/microsoft/Phi-3-mini-4k-instruct">SLM open source</a> lan&#231;ado mais recentemente pela Microsoft. O phi-3-mini &#233; baseado em uma arquitetura decoder-only do transformer, com comprimento de contexto de 4.000 tokens. Tamb&#233;m foi introduzido uma vers&#227;o de contexto mais longo, chamada phi-3-mini-128K, que usa a t&#233;cnica LongRope para estender o comprimento do contexto para 128.000 tokens.</p><p>O phi-3-mini &#233; constru&#237;do de forma semelhante ao Llama-2 e usa o mesmo tokenizador com um vocabul&#225;rio de 320.641 palavras. Isso significa que todos os pacotes desenvolvidos para a fam&#237;lia de modelos Llama-2 podem ser adaptados diretamente para o phi-3-mini. O modelo foi treinado usando bfloat16 com um total de 3,3 trilh&#245;es de tokens. O modelo j&#225; est&#225; ajustado para conversa&#231;&#227;o.</p><p>O modelo phi-3-small, com 7 bilh&#245;es de par&#226;metros, utiliza o tokenizador tiktoken, que melhora a tokeniza&#231;&#227;o multil&#237;ngue, com um vocabul&#225;rio de 100.352 palavras e um comprimento de contexto padr&#227;o de 8192 tokens. Ele segue a arquitetura padr&#227;o de um decoder-only com 7 bilh&#245;es de par&#226;metros.</p><p>Gra&#231;as ao seu tamanho pequeno, o phi-3-mini pode ser quantizado para 4 bits, ocupando apenas cerca de 1,8 GB de mem&#243;ria. <a href="https://export.arxiv.org/pdf/2404.14219">De acordo com o relat&#243;rio oficial</a>, o modelo foi testado ap&#243;s quantiza&#231;&#227;o e implantado em um iPhone 14 com chip A16 Bionic, rodando nativamente no dispositivo e totalmente offline, alcan&#231;ando mais de 12 tokens por segundo.</p><p>Em termos de capacidades de modelos de linguagem grandes (LLM), embora o modelo phi-3-mini alcance um n&#237;vel de compreens&#227;o e racioc&#237;nio lingu&#237;stico semelhante ao de modelos muito maiores, ele ainda &#233; fundamentalmente limitado pelo seu tamanho para certas tarefas.</p><h2>Hello world com o Phi-3-mini</h2><p>O modelo phi-3-mini est&#225; dispon&#237;vel no <a href="https://huggingface.co/microsoft/Phi-3-mini-4k-instruct">huggingface</a>, logo pode ser acessado usando a sua API oficial. Para esse exemplo, utilizaremos o LangChain para comunicar com o modelo phi-3-mini no huggingface. </p><p>O c&#243;digo abaixo configura e utiliza um modelo de linguagem da HuggingFace para gerar texto a partir de um prompt espec&#237;fico. </p><pre><code>from langchain_community.llms import HuggingFaceEndpoint
import os
from dotenv import load_dotenv

load_dotenv()

os.environ["HUGGINGFACEHUB_API_TOKEN"] = os.getenv("HG")

model = HuggingFaceEndpoint(repo_id="microsoft/Phi-3-mini-4k-instruct", task="text-generation", temperature=0.9)


prompt = f"""
&lt;|user|&gt;
How to explain Internet for a medieval knight?&lt;|end|&gt;
&lt;|assistant|&gt;
"""

response = model.invoke(prompt)
print(response)</code></pre><p>Inicialmente, o c&#243;digo importa as bibliotecas necess&#225;rias e carrega as vari&#225;veis de ambiente a partir de um arquivo `.env` usando `load_dotenv()`. </p><p>Em seguida, ele define a vari&#225;vel de ambiente `HUGGINGFACEHUB_API_TOKEN` com o valor da vari&#225;vel `HG` carregada do arquivo `.env`, o que &#233; necess&#225;rio para autenticar a API da Hugging Face. Voc&#234; precisa criar um token no HuggingFace para acessar sua API.</p><p>O c&#243;digo ent&#227;o cria uma inst&#226;ncia do modelo `HuggingFaceEndpoint` especificando o identificador do reposit&#243;rio do modelo (`repo_id`) e a tarefa que ele deve realizar (`task`), que no caso &#233; a gera&#231;&#227;o de texto. Tamb&#233;m definimos o par&#226;metro `temperature` para ajustar a criatividade da resposta gerada pelo modelo.</p><p>Depois, o c&#243;digo define um prompt, que neste caso &#233; uma pergunta sobre como explicar a Internet para um cavaleiro medieval. Perceba os tokens especiais que s&#227;o utilizados por esse modelo.</p><p>Por fim, usamos o m&#233;todo `invoke()` do modelo, ele gera uma resposta para o prompt e imprime essa resposta.</p><h2>Conclus&#227;o</h2><p>O progresso not&#225;vel da IA nos &#250;ltimos anos se deve, em grande parte, aos esfor&#231;os para aumentar os modelos e os conjuntos de dados. LLMs cresceram de bilh&#245;es de par&#226;metros para trilh&#245;es, melhorando o desempenho de maneira previs&#237;vel atrav&#233;s das chamadas "leis de escala". No entanto, a introdu&#231;&#227;o de novos modelos menores que interagem de maneiras inovadoras com os dados desafiou essa teoria. Trabalhos anteriores mostraram que a combina&#231;&#227;o de dados dispon&#237;veis na web e dados sint&#233;ticos gerados por LLMs pode permitir que modelos menores alcancem um desempenho anteriormente reservado a modelos maiores. Um exemplo disso &#233; o modelo phi-2, que com 2,7 bilh&#245;es de par&#226;metros conseguiu um desempenho semelhante ao de modelos 25 vezes maiores.</p><p>Os "small language models" (SLMs) destacam-se pela efici&#234;ncia, requerendo menos recursos computacionais e podendo ser implementados localmente em dispositivos como smartphones. Embora menores, eles podem ser altamente eficazes em diversas tarefas de processamento de linguagem natural, especialmente com t&#233;cnicas de treinamento avan&#231;adas e filtragem de dados. </p><p>O modelo phi-3-mini, por exemplo, &#233; um SLM baseado em uma arquitetura transformer decoder-only, com comprimento de contexto estendido e alta adaptabilidade para aplica&#231;&#245;es especializadas. Ele pode ser quantizado para ocupar apenas 1,8 GB de mem&#243;ria, funcionando eficientemente em dispositivos como o iPhone 14. Assim, os SLMs oferecem uma alternativa poderosa e eficiente aos LLMs, combinando desempenho robusto com acessibilidade e versatilidade para diversas aplica&#231;&#245;es pr&#225;ticas.</p>]]></content:encoded></item><item><title><![CDATA[O que são os parâmetros de um modelo?]]></title><description><![CDATA[Par&#226;metros de um modelo de aprendizado de m&#225;quina s&#227;o os valores internos que o modelo ajusta durante o processo de treinamento para minimizar o erro e otimizar o desempenho na tarefa espec&#237;fica.]]></description><link>https://ml4se.substack.com/p/o-que-sao-os-parametros-de-um-modelo</link><guid isPermaLink="false">https://ml4se.substack.com/p/o-que-sao-os-parametros-de-um-modelo</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Mon, 10 Jun 2024 01:17:40 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/1adf9f65-cfd8-4006-bd4a-9c8751671998_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Par&#226;metros de um modelo de aprendizado de m&#225;quina s&#227;o os valores internos que o modelo ajusta durante o processo de treinamento para minimizar o erro e otimizar o desempenho na tarefa espec&#237;fica. </p><p>Esses par&#226;metros determinam como o modelo transforma as entradas nos resultados previstos. Por exemplo, em redes neurais, os par&#226;metros incluem pesos e biases das conex&#245;es entre neur&#244;nios. </p><p>O ajuste adequado desses par&#226;metros &#233; crucial para que o modelo aprenda padr&#245;es a partir dos dados de treinamento e fa&#231;a previs&#245;es precisas em novos dados.</p><div><hr></div><h2>Bootcamp LLM4Devs</h2><p>&#128218; Voc&#234; &#233; dev e quer criar aplica&#231;&#245;es baseadas em LLMs?</p><p>No pr&#243;ximo dia 15/06/2024 (s&#225;bado), vai rolar um bootcamp online de 3h:30m de dura&#231;&#227;o, sobre desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. Vai ser super <em>hands on</em>!</p><p>Alguns dos t&#243;picos abordados:</p><p>&#128992; Entendendo sobre LLMs</p><p>&#128995; Testando prompts e engenharia de prompts</p><p>&#128309; Entendendo de embeddings</p><p>&#128994; Comparando dados por similaridade</p><p>&#128993; Conectando com um banco vetorial</p><p>E tem mais! Se inscrevendo no bootcamp, <a href="https://gustavopinto.gumroad.com/l/llm4devs">voc&#234; ganha acesso a tr&#234;s cursos sobre LLMs</a>.</p><p>Interessou? Clique aqui e saiba mais:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://llmbootcamp.dev/&quot;,&quot;text&quot;:&quot;Bootcamp LLM4Devs&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://llmbootcamp.dev/"><span>Bootcamp LLM4Devs</span></a></p><div><hr></div><h2>O que &#233; mesmo aprendizado de m&#225;quina?</h2><p>De maneira simplista, a id&#233;ia do aprendizado de m&#225;quina &#233; criar (ou melhor, treinar) modelos expondo-os em um conjunto de dados. Com esses modelos treinados &#233; poss&#237;vel, de alguma forma, usa-los para avaliar (ou predizer) um conjunto de dados at&#233; ent&#227;o desconhecido. </p><p>Digamos que voc&#234; queira uma fun&#231;&#227;o que receba uma imagem e produza um r&#243;tulo descrevendo-a, ou qualquer outra tarefa que pare&#231;a exigir algum elemento de intui&#231;&#227;o e reconhecimento de padr&#245;es. </p><p>A ideia do aprendizado de m&#225;quina &#233; que, em vez de tentar definir explicitamente um algoritmo que descreve como realizar essa tarefa em c&#243;digo &#8212; que &#233; o que as pessoas teriam feito nos prim&#243;rdios da IA &#8212; voc&#234; configure uma estrutura flex&#237;vel com bot&#245;es (ou melhor, par&#226;metros) ajust&#225;veis. </p><p>Para ajustar os valores desses par&#226;metros, voc&#234; fornece muitos, muitos exemplos de como a sa&#237;da deve ser formatada para uma determinada entrada, de forma que o modelo comece a imitar esse comportamento.</p><h3>Modelos com poucos par&#226;metros</h3><p>Talvez a forma mais simples de aprendizado de m&#225;quina seja a regress&#227;o linear, onde suas entradas e sa&#237;das s&#227;o n&#250;meros, algo como a metragem quadrada de uma casa e seu pre&#231;o, e voc&#234; deseja encontrar uma linha que melhor se ajuste atrav&#233;s desses dados, para prever os pre&#231;os futuros de im&#243;veis.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="/__u/substackcdn.com/image/fetch/$s_!14Zu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff099e16d-8971-4e24-8b73-6d48613f2f5b_787x466.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="/__u/substackcdn.com/image/fetch/$s_!14Zu!, /__u/ml4se.substack.com/w_424, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff099e16d-8971-4e24-8b73-6d48613f2f5b_787x466.jpeg 424w, /__u/substackcdn.com/image/fetch/$s_!14Zu!, /__u/ml4se.substack.com/w_848, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff099e16d-8971-4e24-8b73-6d48613f2f5b_787x466.jpeg 848w, /__u/substackcdn.com/image/fetch/$s_!14Zu!, /__u/ml4se.substack.com/w_1272, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff099e16d-8971-4e24-8b73-6d48613f2f5b_787x466.jpeg 1272w, /__u/substackcdn.com/image/fetch/$s_!14Zu!, /__u/ml4se.substack.com/w_1456, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff099e16d-8971-4e24-8b73-6d48613f2f5b_787x466.jpeg 1456w" sizes="100vw"><img src="/__u/substackcdn.com/image/fetch/$s_!14Zu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff099e16d-8971-4e24-8b73-6d48613f2f5b_787x466.jpeg" width="787" height="466" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f099e16d-8971-4e24-8b73-6d48613f2f5b_787x466.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:466,&quot;width&quot;:787,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="/__u/substackcdn.com/image/fetch/$s_!14Zu!, /__u/ml4se.substack.com/w_424, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff099e16d-8971-4e24-8b73-6d48613f2f5b_787x466.jpeg 424w, /__u/substackcdn.com/image/fetch/$s_!14Zu!, /__u/ml4se.substack.com/w_848, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff099e16d-8971-4e24-8b73-6d48613f2f5b_787x466.jpeg 848w, /__u/substackcdn.com/image/fetch/$s_!14Zu!, /__u/ml4se.substack.com/w_1272, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff099e16d-8971-4e24-8b73-6d48613f2f5b_787x466.jpeg 1272w, /__u/substackcdn.com/image/fetch/$s_!14Zu!, /__u/ml4se.substack.com/w_1456, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff099e16d-8971-4e24-8b73-6d48613f2f5b_787x466.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Imagem deste link: https://www.linkedin.com/pulse/machine-learning-predicting-house-prices-eike-dehling/</figcaption></figure></div><p>Essa linha &#233; descrita por dois par&#226;metros, <a href="https://www.alura.com.br/artigos/desvendando-a-regressao-linear">como o </a><em><a href="https://www.alura.com.br/artigos/desvendando-a-regressao-linear">coeficiente angular</a></em><a href="https://www.alura.com.br/artigos/desvendando-a-regressao-linear"> e o </a><em><a href="https://www.alura.com.br/artigos/desvendando-a-regressao-linear">intercepto</a></em>. O objetivo da regress&#227;o linear &#233; encontrar quais s&#227;o os melhores valores para esses par&#226;metros, de forma a gerar uma reta que melhor possa descrever os dados.</p><h3>Modelos com muitos par&#226;metros</h3><p>Os modelos baseados em deep learning s&#227;o muito mais sofisticados. O GPT-3, por exemplo, n&#227;o possui dois, mas 175 bilh&#245;es de par&#226;metros.</p><p>Para que esses modelos sejam treinados nessa escala, os dados precisam seguir um formato espec&#237;fico.  Os dados s&#227;o costumeiramente formatados como um array de n&#250;meros reais, podendo ser uma lista de n&#250;meros, uma matriz bidimensional ou, muitas vezes, matrizes alta dimens&#227;o, onde o termo geral usado &#233; <em>tensor</em>.</p><p>Muitas vezes pensamos que os dados de entrada s&#227;o transformados em camadas distintas, onde, novamente, cada camada &#233; sempre estruturada como algum tipo de matriz de n&#250;meros reais, at&#233; chegar a uma camada final de sa&#237;da. Por exemplo, a camada final em um modelo lingu&#237;stico como o GPT-3 &#233; uma lista de n&#250;meros que representa a probabilidade dos pr&#243;ximos tokens poss&#237;veis.</p><p>Em deep learning, esses par&#226;metros do modelo s&#227;o quase sempre chamados de <em>pesos</em>, e isso ocorre porque uma caracter&#237;stica importante desses modelos &#233; que a &#250;nica maneira pela qual esses par&#226;metros interagem com os dados que est&#227;o sendo processados &#233; por meio de somas ponderadas. Se voc&#234; pensar em como funciona a multiplica&#231;&#227;o de vetores de matrizes, cada componente na sa&#237;da parece uma soma ponderada.</p><blockquote><p>Os dados processados simplesmente codificam as entradas inseridas no modelo para uma determinada execu&#231;&#227;o. Por outro lado, os pesos s&#227;o o c&#233;rebro do modelo; s&#227;o onde se aprende os padr&#245;es durante o treinamento e, assim, determinando o comportamento do modelo. </p></blockquote><p>Olhando rapidamente a evolu&#231;&#227;o dos modelos lingu&#237;stico, uma caracter&#237;stica not&#225;vel &#233; o progressivo aumento no n&#250;mero de par&#226;metros desses modelos. Tome por exemplo o GPT2, lan&#231;ado em 2019, que foi disponibilizado com v&#225;rias vers&#245;es, variando entre 117 milh&#245;es de par&#226;metros at&#233; 1.5bilh&#245;es de par&#226;metros. </p><p>Cerca de um ano depois, a OpenAI lan&#231;ou o GPT3, agora com 175 bilh&#245;es de par&#226;metros; mais de 100x mais par&#226;metros do que a vers&#227;o anterior.</p><h3>Por que muitos par&#226;metros s&#227;o importantes</h3><p>Ter muitos par&#226;metros em um modelo de linguagem  &#233; importante pois cada par&#226;metro representa uma parte do conhecimento adquirido durante o treinamento. Imagine que cada par&#226;metro &#233; como uma pequena pe&#231;a de um quebra-cabe&#231;a, e o quebra-cabe&#231;a completo &#233; o entendimento do modelo sobre a linguagem humana. Quanto mais pe&#231;as, mais detalhada e precisa &#233; a imagem final.</p><p>Em modelos de linguagem, par&#226;metros s&#227;o usados para capturar padr&#245;es, nuances e contextos de dados textuais vastos e variados. Quando um modelo tem muitos par&#226;metros, ele pode aprender e armazenar uma quantidade imensa de informa&#231;&#245;es sobre gram&#225;tica, vocabul&#225;rio, g&#237;rias, express&#245;es idiom&#225;ticas, contextos culturais, conhecimento factual e at&#233; mesmo sutilezas emocionais. Essa riqueza de detalhes permite ao modelo gerar respostas que s&#227;o mais coerentes, contextualmente apropriadas e muitas vezes indistingu&#237;veis daquelas produzidas por humanos.</p><p>Al&#233;m disso, a capacidade de um modelo com muitos par&#226;metros de generalizar a partir dos dados de treinamento &#233; significativamente maior. Isso significa que o modelo pode entender e responder adequadamente a uma ampla gama de perguntas e t&#243;picos, mesmo aqueles que n&#227;o encontrou diretamente durante o treinamento. Por exemplo, um modelo com bilh&#245;es de par&#226;metros pode entender e responder perguntas sobre eventos hist&#243;ricos pouco conhecidos, avan&#231;adas teorias cient&#237;ficas ou peculiaridades de diversas culturas.</p><h2>Conclus&#227;o</h2><p>A import&#226;ncia dos par&#226;metros em modelos de aprendizado de m&#225;quina, especialmente em modelos de linguagem como o GPT-3, n&#227;o pode ser subestimada. </p><p>Cada par&#226;metro funciona como um componente essencial que ajuda o modelo a capturar e processar uma vasta gama de informa&#231;&#245;es textuais. Com um n&#250;mero maior de par&#226;metros, o modelo pode armazenar e utilizar um conhecimento mais detalhado sobre gram&#225;tica, vocabul&#225;rio, e contextos culturais, permitindo que ele gere respostas mais precisas e coerentes. </p><p>Esse aumento na quantidade de par&#226;metros tamb&#233;m melhora a capacidade do modelo de generalizar a partir dos dados de treinamento, possibilitando que ele entenda e responda a uma ampla variedade de quest&#245;es com alta precis&#227;o. </p><p>A evolu&#231;&#227;o dos modelos de linguagem demonstra que a amplia&#231;&#227;o do n&#250;mero de par&#226;metros parece ser um caminho sem volta como forma de melhorar a capacidade de intera&#231;&#227;o de maneira natural com os usu&#225;rios.</p>]]></content:encoded></item><item><title><![CDATA[Desenvolvimento de agentes é o seu próximo passo profissional ]]></title><description><![CDATA[N&#227;o &#233; surpresa que processo de desenvolvimento de software sofre significativas mudan&#231;as de tempos em tempos.]]></description><link>https://ml4se.substack.com/p/desenvolvimento-de-software-orientado</link><guid isPermaLink="false">https://ml4se.substack.com/p/desenvolvimento-de-software-orientado</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Wed, 29 May 2024 23:29:32 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/e79d27cb-6a8c-463f-802b-bb866febad1c_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>N&#227;o &#233; surpresa que processo de desenvolvimento de software sofre significativas mudan&#231;as de tempos em tempos. </p><p>Desde o uso de linguagens de programa&#231;&#227;o de alto n&#237;vel que abstraem tarefas antes manuais, como gerenciamento de mem&#243;ria, passando pela populariza&#231;&#227;o de pr&#225;ticas como CI/CD e DevOps, que t&#234;m ajudam a melhorar a qualidade de entrega ao longo do ciclo de vida do software, surfando junto com a revolu&#231;&#227;o dos cont&#234;ineres como Docker, gerenciando ambientes de desenvolvimento e produ&#231;&#227;o, majoritariamente em nuvem. </p><p>Esses s&#227;o apenas alguns poucos exemplos por&#233;m significativos exemplos de mudan&#231;as que aconteceram no processo de desenvolvimento. Essas mudan&#231;as n&#227;o apenas aumentaram a velocidade de entrega de software, mas tamb&#233;m elevaram os padr&#245;es de qualidade e usabilidade das aplica&#231;&#245;es.</p><p>Estamos prestes de vivenciar uma nova e not&#225;vel mudan&#231;a: o desenvolvimento de software orientado a agentes.</p><div><hr></div><h2>Bootcamp LLM4Devs</h2><p>&#128218; Voc&#234; &#233; dev e quer criar aplica&#231;&#245;es baseadas em LLMs?</p><p>No pr&#243;ximo dia 15/06/2024 (s&#225;bado), vai rolar um bootcamp online de 3h:30m de dura&#231;&#227;o, sobre desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. Vai ser super <em>hands on</em>!</p><p>Alguns dos t&#243;picos abordados:</p><p>&#128992; Entendendo sobre LLMs</p><p>&#128995; Testando prompts e engenharia de prompts</p><p>&#128309; Entendendo de embeddings</p><p>&#128994; Comparando dados por similaridade</p><p>&#128993; Conectando com um banco vetorial</p><p>E tem mais! Se inscrevendo no bootcamp, <a href="https://gustavopinto.gumroad.com/l/llm4devs">voc&#234; ganha acesso a tr&#234;s cursos sobre LLMs</a>.</p><p>Interessou? Clique aqui e saiba mais:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://llmbootcamp.dev/&quot;,&quot;text&quot;:&quot;Bootcamp LLM4Devs&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://llmbootcamp.dev/"><span>Bootcamp LLM4Devs</span></a></p><div><hr></div><p>Embora o desenvolvimento software baseado de agentes n&#227;o seja algo necessariamente novo, <a href="https://dl.acm.org/doi/pdf/10.1145/267658.267772">com artigos que datam da d&#233;cada de 1990</a>, a evolu&#231;&#227;o e populariza&#231;&#227;o dos LLMs simplificaram o processo de cria&#231;&#227;o de agentes sofisticados. </p><p>Poder&#237;amos usar as palavras do prof. Carlos Lucena, de um texto de 2003, para exemplificar a ideia de desenvolvimento orientado a agentes:</p><blockquote><p><em><a href="https://www.researchgate.net/profile/Alberto-Sardinha-2/publication/221556044_Software_engineering_for_large-scale_multi-agent_systems_-_SELMAS%272003/links/0912f50b8eaa40d767000000/Software-engineering-for-large-scale-multi-agent-systems-SELMAS2003.pdf#page=14">Enquanto a orienta&#231;&#227;o de objetos &#233; usada para modelar componentes passivos, o desenvolvimento orientado a agentes &#233; ideal para representar componentes aut&#244;nomos em sistemas de software. A &#225;rea de pesquisa de sistemas multiagentes ajudam a entender a autonomia, coordena&#231;&#227;o, mobilidade, organiza&#231;&#227;o, abertura e intelig&#234;ncia desses agentes. A Engenharia de Software est&#225; estudando como as li&#231;&#245;es dessas teorias de agentes em IA podem ajudar a superar as limita&#231;&#245;es da engenharia de software orientada a objetos e a lidar com a complexidade do software moderno.</a></em> </p></blockquote><p>Movendo a janela de tempo uns 20 anos, nos deparamos com a evolu&#231;&#227;o e populariza&#231;&#227;o dos  modelos lingu&#237;sticos. </p><p>Esses modelos, como o GPT-4, LLaMa 3 ou Claude 3, tornaram o acesso a estes modelos, atrav&#233;s de suas APIs, extremamente simplificado. N&#227;o obstante, novos frameworks surgiram (e continuam surgindo) com o objetivo de n&#227;o somente padronizar e simplificar o acesso &#224; esses modelos, como tamb&#233;m orquestrar todo o pipeline de coleta, curadoria e manipula&#231;&#227;o de dados, que s&#227;o consumidos e enriquecidos pelos modelos. </p><p>Estes modelos, operado por frameworks e bibliotecas, abrem as portas para um sem fim n&#250;mero de aplica&#231;&#245;es e automa&#231;&#245;es que podem ser criadas por pessoas desenvolvedoras; finalmente girando as engrenagens do desenvolvimento de software orientado a agentes.</p><p>Com os modelos lingu&#237;sticos se tornando cada vez mais assertivos em suas respostas, associado a competitividade dos grandes players provedores destes modelos, que tende a baratear o custo de acesso, junto com bons frameworks e ferramentas que simplificam a jornada do desenvolvedor, em pouco tempo, <strong>o desenvolvimento de software impulsionado por LLMs se tornar&#225; t&#227;o comum quanto outras pr&#225;ticas de desenvolvimento</strong>.</p><p>Quem ganha com isso &#233; o desenvolvedor, que se torna capaz de construir aplica&#231;&#245;es mais inteligentes e adaptativas, com velocidade e produtividade.</p><p>Como &#233; o caso de qualquer novo paradigma de programa&#231;&#227;o, tanto pesquisadores quanto a comunidade de praticantes est&#227;o se esfor&#231;ando para criar metodologias que orientam o processo de constru&#231;&#227;o de agentes sofisticados. </p><p>Como toda nova tecnologia, as solu&#231;&#245;es existentes ainda devem evoluir at&#233; ganhar maturidade para serem utilizadas com baixo risco em ambientes produtivos. O pr&#243;prio LangChain, um dos principais frameworks nessa &#225;rea, por exemplo, <a href="/__u/ml4se.substack.com/p/devo-adotar-o-langchain">tem sido  alvo frequente de questionamentos de alguns de seus usu&#225;rios</a>. De maneira geral, ainda &#233; dif&#237;cil compreender a intera&#231;&#227;o entre agentes e objetos, na perspectiva de engenharia de software. </p><p>Por mais que essas limita&#231;&#245;es tragam indaga&#231;&#245;es da comunidade t&#233;cnico-cient&#237;fica de desenvolvimento, o fato &#233; que essa nova era de desenvolvimento promete n&#227;o apenas aumentar a efici&#234;ncia e a qualidade do software produzido, mas tamb&#233;m abrir novas possibilidades para a cria&#231;&#227;o de solu&#231;&#245;es inovadoras que atendam &#224;s necessidades cada vez mais complexas dos usu&#225;rios e dos mercados.</p><p>Se voc&#234; n&#227;o quer ficar de fora dessa, considere se inscrever no <a href="https://llmbootcamp.dev/">Bootcamp LLM4Devs</a>. </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ml4se.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Inscreva-se&quot;,&quot;language&quot;:&quot;pt-br&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">ML4SE &#233; uma newsletter focada em ajudar devs a mastigar t&#233;cnicas de aprendizado de m&#225;quina. Para receber novos posts, se inscreva na newsletter.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Digite seu e-mail&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Inscreva-se"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Explorando o LLaMa 3 com LangChain]]></title><description><![CDATA[O LLaMA 3, desenvolvido pela Meta AI, representa um avan&#231;o significativo na s&#233;rie de modelos de linguagem LLaMA.]]></description><link>https://ml4se.substack.com/p/explorando-o-llama-3-com-langchain</link><guid isPermaLink="false">https://ml4se.substack.com/p/explorando-o-llama-3-com-langchain</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Sun, 26 May 2024 20:15:04 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/bdee461e-bd5b-4be3-a885-90d083078388_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>O LLaMA 3, desenvolvido pela Meta AI, representa um avan&#231;o significativo na s&#233;rie de modelos de linguagem LLaMA. A vers&#227;o mais recente inclui dois modelos principais com 8 bilh&#245;es (8B) e 70 bilh&#245;es (70B) de par&#226;metros, projetados para suportar diversos tipos de casos de uso. </p><p>De acordo com experimentos, o LLaMA 3 destaca-se especialmente em tarefas que envolvem racioc&#237;nio aprimorado e gera&#231;&#227;o de c&#243;digo. As melhorias no processo de pr&#233;-treino (que utilizou mais de 15T de tokens; 7 vezes maior que do LLaMA 2) resultaram em modelos que n&#227;o apenas s&#227;o mais precisos, mas tamb&#233;m oferecem maior diversidade de respostas e melhor alinhamento com as expectativas dos usu&#225;rios.</p><p>O LLaMA 3 segue abordagem do LLaMA 2, de ser aberto para sua comunidade. Essa estrat&#233;gia visa estimular a inova&#231;&#227;o em IA, permitindo que desenvolvedores, pesquisadores e empresas explorem e aprimorem a tecnologia. Dessa forma, os custos envolvidos com o uso do modelo se restringem aos custos de processamento, mem&#243;ria e energia, gastos durante o processo de infer&#234;ncia.</p><p>Nesse texto, vamos experimentar um pouco com esse modelo!</p><div><hr></div><p>&#128218; Voc&#234; &#233; dev e quer criar aplica&#231;&#245;es baseadas em LLMs?</p><p>No pr&#243;ximo dia 15/06/2024 (s&#225;bado), vai rolar um bootcamp online de 3h:30m de dura&#231;&#227;o, sobre desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. Vai ser super <em>hands on</em>! </p><p>Alguns dos t&#243;picos abordados:</p><p>&#128992; Entendendo sobre LLMs</p><p>&#128995; Testando prompts e engenharia de prompts</p><p>&#128309; Entendendo de embeddings</p><p>&#128994; Comparando dados por similaridade</p><p>&#128993; Conectando com um banco vetorial</p><p>E tem mais! Se inscrevendo no bootcamp, <a href="https://gustavopinto.gumroad.com/l/llm4devs">voc&#234; ganha acesso a tr&#234;s cursos sobre LLMs</a>.</p><p>Interessou? Clique aqui e saiba mais:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://llmbootcamp.dev/&quot;,&quot;text&quot;:&quot;Inscreva-se agora!&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://llmbootcamp.dev/"><span>Inscreva-se agora!</span></a></p><div><hr></div><h2>Detalhes do modelo</h2><p>O LLaMA 3 &#233; fornecido em duas configura&#231;&#245;es de par&#226;metros: 8B e 70B. &#201; um modelo que recebe texto como entrada, e fornece como sa&#237;da ou texto ou trechos de c&#243;digo. A data de lan&#231;amento foi 18 de abril de 2024, embora detenha conhecimento at&#233; Mar&#231;o de 2023 (para a vers&#227;o de 8B de par&#226;metros) e Dezembro de 2023 (para a vers&#227;o de 70B de par&#226;metros).</p><p>O tamanho da janela de contexto do modelo LLaMA 3 &#233; de 8.000 tokens. Isso significa que o modelo pode considerar at&#233; 8.000 tokens de texto ao gerar respostas ou realizar previs&#245;es. Na pr&#225;tica, a janela de contexto determina a quantidade de texto que o modelo pode "lembrar" e usar como refer&#234;ncia ao processar novas entradas. Um tamanho maior de janela de contexto permite que o modelo mantenha mais informa&#231;&#245;es relevantes, melhorando sua capacidade de compreender e gerar respostas coerentes em textos mais longos ou complexos. </p><p>O LLaMa 3 &#233; disponibilizado atrav&#233;s de uma nova licen&#231;a, chamada &#8220;<a href="https://llama.meta.com/llama3/license/">Meta Llama 3 Community License Agreement</a>&#8221;, que se assemelha a licen&#231;as permissivas, como a MIT ou Apache 2, uma vez que concede permiss&#227;o para usar, reproduzir, distribuir, criar trabalhos derivados e fazer modifica&#231;&#245;es nos materiais do LlaMa.</p><p>Mais detalhes t&#233;cnicos sobre o modelo podem ser consultados <a href="https://about.fb.com/br/news/2024/04/apresentando-meta-llama-3-o-grande-modelo-de-linguagem-de-codigo-aberto-mais-capaz-ate-hoje/">na p&#225;gina oficial</a>, ou <a href="https://github.com/meta-llama/llama3/blob/main/MODEL_CARD.md">no model card</a>, no GitHub do projeto.</p><h2>Instala&#231;&#245;es e downloads</h2><p>Para nosso primeiro exemplo, utilizaremos tamb&#233;m o LangChain, que &#233; um framework que auxilia na cria&#231;&#227;o de aplica&#231;&#245;es baseadas em LLMs. </p><p>Podemos instalar o LangChain com um comando pip: </p><pre><code>pip install langchain langchain_community</code></pre><p>Precisamos tamb&#233;m isntalar o langchain_community, pois este fornece interfaces com os mais diversos modelos e conectores, incluindo o LLaMa, atrav&#233;s da biblioteca llama-cpp-python.</p><p>Ap&#243;s a instala&#231;&#227;o das bibliotecas, precisamos tamb&#233;m baixar o modelo. O download pode ser feito de v&#225;rias fontes, incluindo do <a href="https://llama.meta.com/docs/getting_the_models">site oficial da Meta</a> e do <a href="https://llama.meta.com/docs/getting-the-models/hugging-face">perfil da Meta do HuggingFace</a>. Dentre as mais varias vers&#245;es de modelos dispon&#237;veis, para esse texto, utilizaremos a <code>Meta-Llama-3-8B-Instruct-Q3_K_L.gguf</code>. O nome do modelo fornece informa&#231;&#245;es espec&#237;ficas sobre suas caracter&#237;sticas. Por exemplo:</p><ul><li><p><strong>Meta</strong>: Indica que o modelo foi desenvolvido pela Meta.</p></li><li><p><strong>Llama</strong>: Refere-se &#224; fam&#237;lia de modelos de linguagem LLaMA.</p></li><li><p><strong>3</strong>: Denota que &#233; a terceira vers&#227;o da s&#233;rie LLaMA.</p></li><li><p><strong>8B</strong>: Indica o tamanho do modelo em termos de par&#226;metros.</p></li><li><p><strong>Instruct</strong>: Significa que o modelo foi ajustado por instru&#231;&#227;o, otimizado para seguir comandos e gerar respostas &#250;teis em contextos de di&#225;logo e outras intera&#231;&#245;es.</p></li><li><p><strong>Q3_K_L</strong>: Se refere a uma t&#233;cnica espec&#237;fica de <a href="https://www.linkedin.com/feed/update/urn:li:activity:7200508224280678403/">quantiza&#231;&#227;o</a> aplicada ao modelo. </p></li><li><p><strong>.gguf</strong>: &#201; a extens&#227;o do arquivo, indicando o formato no qual o modelo est&#225; armazenado.</p></li></ul><h2>Hello world no langchain</h2><p>Uma vez com o ambiente instalado e configurado, podemos fazer nosso hello world, usando a classe <code>LlamaCpp</code>. Por exemplo:</p><pre><code>from langchain_community.llms import LlamaCpp

llm = LlamaCpp(model_path="models/Meta-Llama-3-8B-Instruct-Q3_K_L.gguf", max_tokens=100,n_ctx=512)

response = llm.invoke("Quais s&#227;o os melhores amigos do Mickey Mouse?")

print(response)</code></pre><p>Perceba que a classe <code>LlamaCpp </code>recebe dois outros par&#226;metros: o <code>max_tokens</code> e o <code>n_ctx</code>. O <code>n_ctx</code> define o tamanho da janela de contexto. </p><p>A janela de contexto determina o n&#250;mero m&#225;ximo de tokens que podem ser processados de uma vez &#8212; considerando tanto a entrada do usu&#225;rio quanto a resposta do modelo. Por padr&#227;o,  no LLaMa3 este valor &#233; definido para 512 tokens, mas pode ser ajustado com base em suas necessidades, at&#233; o limite m&#225;ximo de 8k tokens.</p><p>O <code>max_tokens</code>, por outro lado, ajuda a definir o limite de tokens gerados como resposta. Perceba, no entanto, que se o modelo gerar mais tokens do que o limite definido, a resposta do usu&#225;rio ser&#225; cortada. Defina <code>max_tokens = None </code>para gerar at&#233; o final da janela de contexto.</p><p>Al&#233;m desses tr&#234;s par&#226;metros, h&#225; v&#225;rios outros que podem ser configurados e est&#227;o documentados na <a href="https://github.com/langchain-ai/langchain/blob/master/libs/community/langchain_community/llms/llamacpp.py">classe LlamaCpp</a>, como a possibilidade de carregar somente o vocabul&#225;rio (sem os pesos), a possibilidade de rodar o processo de infer&#234;ncia em paralelo, a temperatura do modelo, al&#233;m de v&#225;rios outros.</p><h2>Tokens especiais</h2><p>H&#225; alguns tokens especiais usados para interagir via prompt com o Meta Llama 3:</p><ul><li><p><strong>&lt;|begin_of_text|&gt;</strong>: Isso &#233; equivalente ao token BOS (Beginning of String), indicando o in&#237;cio de uma nova sequ&#234;ncia de texto.</p></li><li><p><strong>&lt;|eot_id|&gt;</strong>: Isso indica o fim de uma mensagem.</p></li><li><p><strong>&lt;|start_header_id|&gt;{role}&lt;|end_header_id|&gt;</strong>: Esses tokens envolvem o papel de uma mensagem espec&#237;fica. Os pap&#233;is poss&#237;veis s&#227;o: <em>system</em>, <em>user</em> e <em>assistant</em>.</p></li><li><p><strong>&lt;|end_of_text|&gt;</strong>: Isso &#233; equivalente ao token EOS (End of String). Ao gerar esse token, o Llama 3 deixar&#225; de gerar mais tokens.</p></li></ul><p>Um prompt pode opcionalmente conter uma &#250;nica mensagem do sistema, ou m&#250;ltiplas mensagens alternadas de usu&#225;rio e assistente, mas deve sempre terminar com a mensagem do usu&#225;rio, seguida pelo cabe&#231;alho do assistente. Por exemplo:</p><pre><code><code>from langchain_community.llms import LlamaCpp
from langchain_core.prompts import PromptTemplate

llm = LlamaCpp(model_path="models/Meta-Llama-3-8B-Instruct-Q3_K_L.gguf", 
               max_tokens=None,
               n_ctx=512,
               stop=["&lt;|eot_id|&gt;"])

template = """
        &lt;|begin_of_text|&gt;
        &lt;|start_header_id|&gt;system&lt;|end_header_id|&gt;
        {system_prompt}
        &lt;|eot_id|&gt;
        &lt;|start_header_id|&gt;user&lt;|end_header_id|&gt;
        {user_prompt}
        &lt;|eot_id|&gt;
        &lt;|start_header_id|&gt;assistant&lt;|end_header_id|&gt;
        """
def get_response(user_prompt):
    sys_template_str = "You are a helpful AI bot, named Bob. You are specialized in Disney movies. Give a one or two sentences only."
    
    human_template_str = "{user_prompt}"

    prompt = PromptTemplate.from_template(template.format(system_prompt = sys_template_str, user_prompt = human_template_str))

    session = prompt | llm 

    return session.invoke({"user_prompt" : user_prompt})

response = get_response("Who is Mickey Mouse best friend?")
print(response)</code></code></pre><p>No passo a passo: </p><p><strong>&lt;|begin_of_text|&gt;</strong>: Especifica o come&#231;o de um prompt</p><p><strong>&lt;|start_header_id|&gt;system&lt;|end_header_id|&gt;</strong>: Especifica o papel do usu&#225;rio da mensagem seguinte, neste caso, o &#8220;system&#8221;</p><p><strong>{system_prompt}</strong>: A mensagem de sistema a ser enviada</p><p><strong>&lt;|eot_id|&gt;</strong>: Especifica o fim da mensagem de sistema</p><p><strong>&lt;|start_header_id|&gt;user&lt;|end_header_id|&gt;</strong>: Especifica o papel do usu&#225;rio da mensagem seguinte, neste caso, o &#8220;user&#8221;</p><p><strong>{user_prompt}</strong>: A mensagem de usu&#225;rio a ser enviada</p><p><strong>&lt;|start_header_id|&gt;assistant&lt;|end_header_id|&gt;</strong>: Termina com o cabe&#231;alho do assistente, para solicitar ao modelo que inicie a gera&#231;&#227;o.</p><p>Seguindo este prompt, o Llama 3 o completa gerando a {assistant_message}. Ele sinaliza o fim da {assistant_message} ao gerar o token EOS, de fim da string.</p><h2>Conclus&#227;o</h2><p>O LLaMA 3, desenvolvido pela Meta AI, representa um avan&#231;o significativo na s&#233;rie de modelos de linguagem LLaMA, oferecendo modelos com 8 bilh&#245;es (8B) e 70 bilh&#245;es (70B) de par&#226;metros para suportar diversos casos de uso. </p><p>Estes modelos destacam-se em tarefas que envolvem racioc&#237;nio aprimorado e gera&#231;&#227;o de c&#243;digo, resultando em modelos mais precisos, com maior diversidade de respostas e melhor alinhamento com as expectativas dos usu&#225;rios. Seguindo a abordagem do LLaMA 2, o modelo LLaMA 3 &#233; disponibilizado para a comunidade, atrav&#233;s da sua pr&#243;pria licen&#231;a &#8220;Meta Llama 3 Community License Agreement&#8221;.</p><p>H&#225; algumas formas de se utiliza ro LLaMA 3. Nesse texto, usamos o LangChain, que &#233; um framework popular para criar aplica&#231;&#245;es baseadas em modelos de linguagem. Com o langchain, pudemos criar nosso hello world, com poucas linhas de c&#243;digo.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ml4se.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Inscreva-se&quot;,&quot;language&quot;:&quot;pt-br&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">ML4SE &#233; uma newsletter focada em ajudar devs a mastigar t&#233;cnicas de aprendizado de m&#225;quina. Para receber novos posts, se inscreva na newsletter.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Digite seu e-mail&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Inscreva-se"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Devo adotar o Langchain?]]></title><description><![CDATA[LangChain &#233; um framework que facilita a cria&#231;&#227;o de aplica&#231;&#245;es baseadas em LLMs, como o GPT.]]></description><link>https://ml4se.substack.com/p/devo-adotar-o-langchain</link><guid isPermaLink="false">https://ml4se.substack.com/p/devo-adotar-o-langchain</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Mon, 20 May 2024 02:19:05 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/020358b0-d6cd-4323-9f60-bebe5e1feb9b_1024x1024.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>LangChain &#233; um framework que facilita a cria&#231;&#227;o de aplica&#231;&#245;es baseadas em LLMs, como o GPT.  </p><p>O LangChain permite a integra&#231;&#227;o entre os modelos de linguagem e v&#225;rias fontes de conhecimento, otimizando a maneira como os desenvolvedores constroem agentes inteligentes que utilizam processamento de linguagem natural para responder a perguntas e executar tarefas.</p><p>O LangChain tem rapidamente se popularizado na comunidade de desenvolvimento (com mais de 85K &#11088;&#65039; no GitHub) e &#233; um dos frameworks mais utilizados no momento para constru&#231;&#227;o de aplica&#231;&#245;es baseadas em LLMs. </p><p>No entanto, o uso do framework tem sido alvo de questionamentos. Parte dessas cr&#237;ticas est&#225; relacionado a <a href="https://minimaxir.com/2023/07/langchain-problem/">dificuldade de uso do LangChain</a>. No &#250;ltimo Tech Radar de Abril de 2024, a ThoughtWorks sugere inclusive a pausa na ado&#231;&#227;o do framework, colocando como sugest&#245;es outras solu&#231;&#245;es, como o <a href="https://pypi.org/project/semantic-kernel/">SemanticKernel</a>, da Microsoft.</p><p>Nesse texto, ofere&#231;o minhas enviesadas considera&#231;&#245;es sobre o uso do LangChain.</p><div><hr></div><p>&#128218; Voc&#234; &#233; dev e quer criar aplica&#231;&#245;es baseadas em LLMs?</p><p>No pr&#243;ximo dia 15/06/2024 (s&#225;bado), vai rolar um bootcamp online de 3h:30m de dura&#231;&#227;o, sobre desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. Vai ser super <em>hands on</em>! </p><p>Alguns dos t&#243;picos abordados:</p><p>&#128992; Entendendo sobre LLMs</p><p>&#128995; Testando prompts e engenharia de prompts</p><p>&#128309; Entendendo de embeddings</p><p>&#128994; Comparando dados por similaridade</p><p>&#128993; Conectando com um banco vetorial</p><p>E tem mais! Se inscrevendo no bootcamp, <a href="https://gustavopinto.gumroad.com/l/llm4devs">voc&#234; ganha acesso a tr&#234;s cursos sobre LLMs</a>.</p><p>Interessou? Clique aqui e saiba mais:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://gustavopinto.gumroad.com/l/bootcamp-llm4devs&quot;,&quot;text&quot;:&quot;Conhe&#231;a o Bootcamp LLM4Devs&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://gustavopinto.gumroad.com/l/bootcamp-llm4devs"><span>Conhe&#231;a o Bootcamp LLM4Devs</span></a></p><div><hr></div><h3>Meu uso do LangChain</h3><p>Tenho sido usu&#225;rio do LangChain h&#225; cerca de um ano, e nesse meio tempo acompanhei v&#225;rias mudan&#231;as que aconteceram na estrutura do framework. </p><p>Como fui evoluindo meu uso junto com a pr&#243;pria evolu&#231;&#227;o do framework, acompanhei algumas modifica&#231;&#245;es significativas que aconteceram, como por exemplo, a frequente ado&#231;&#227;o de novos loaders, bem como algumas separa&#231;&#245;es de interfaces em pacotes espec&#237;ficos, como mais recentemente a separa&#231;&#227;o dos splitters em um pr&#243;prio pacote, chamado langchain-text-splitters.</p><p>Mas confesso que eu s&#243; percebi as mudan&#231;as mais significativas no framework quando eu refiz o treinamento do LangChain oferecido pela DeepLearning.ai. Refazer o treinamento, que possivelmente foi desenhado em alguma vers&#227;o 0.0.x, mas j&#225; utilizando vers&#245;es 0.1.x, me fez perceber o quanto que o treinamento envelheceu r&#225;pido. As APIs que foram usadas no treinamento j&#225; estavam depreciadas, ou mesmo removidas. Refazer o treinamento se tornou bem dif&#237;cil. </p><p>Inclusive, com a introdu&#231;&#227;o do <a href="https://python.langchain.com/v0.1/docs/expression_language/">LCEL</a>, alguns usos importantes do framework mudaram drasticamente. Acredito que a vis&#227;o &#233; que o LCEL se torne a forma padr&#227;o para uso do framework. No entanto, enquanto o framework migra suas paulatinamente suas interfaces para o LCEL, &#233; preciso conviver com as interfaces antigas junto com as novas.</p><h3>Problemas observados com o LangChain</h3><p>Listo aqui alguns problemas observados.</p><h4>Dificuldade de uso</h4><p>O LangChain apresenta uma complexidade desnecess&#225;ria para tarefas simples, incorporando m&#250;ltiplas classes de objetos e templates de prompts que complicam opera&#231;&#245;es b&#225;sicas. </p><p>Essa abordagem aumenta o esfor&#231;o de codifica&#231;&#227;o e compreens&#227;o, fazendo com que tarefas que poderiam ser realizadas com poucas linhas de c&#243;digo em bibliotecas padr&#227;o exigem estruturas mais elaboradas e menos intuitivas no LangChain. Esse excesso de complexidade n&#227;o apenas dificulta o aprendizado por novos usu&#225;rios, mas tamb&#233;m desencoraja a ado&#231;&#227;o para projetos menores ou menos complexos.</p><p>&#201; verdade que o LCEL simplifica boa parte desse processo, mas, como mencionado anteriormente, o LCEL ainda n&#227;o cobre amplamente os diversos usos do framework.</p><h4>Documenta&#231;&#227;o desatualizada</h4><p>Talvez por conta do desenvolvimento acelerado do framework (v&#225;rios releases por m&#234;s, e at&#233; por semana), alguns pontos da documenta&#231;&#227;o n&#227;o foram atualizados na mesma velocidade.</p><p>Por conta disso, n&#227;o era incomum encontram exemplos de trechos de c&#243;digos que n&#227;o funcionam conforme esperado sem modifica&#231;&#245;es adicionais. Isso acontecia por uso de depend&#234;ncias desatualizadas ou falta de explica&#231;&#245;es claras. Para um projeto open source, documenta&#231;&#227;o &#233; chave, e alguns pequenos problemas acabam por desencorajar potenciais usu&#225;rios. Isso era particularmente frustrante quando os demais exemplos de c&#243;digo que encontrava usavam vers&#245;es diferentes das APIs. Imagina a mistura.</p><h4>Falta de clareza sobre uso dos Agents</h4><p>Agents e tools s&#227;o funcionalidades que tem grande potencial de uso. Agents servem para orquestrar a intera&#231;&#227;o entre diferentes tools e uma LLMs, permitindo descobrir e executar a&#231;&#245;es complexas em sequ&#234;ncia.</p><p>No entanto, a documenta&#231;&#227;o sobre como Agents e tools funcionam ainda &#233; vaga, deixando os usu&#225;rios sem uma compreens&#227;o clara de como funcionam ou como implementar de maneira eficaz. Lembro de discutir extensivamente sobre quais s&#227;o os potenciais cases de uso de Agents com alguns colegas. </p><p>O processo de descoberta de tools por um Agent &#233; algo pouco claro. Por exemplo, n&#227;o sabemos como as tools s&#227;o selecionadas e utilizadas dentro de um fluxo de Agent, ou como os resultados s&#227;o gerenciados e apresentados. </p><p>O processo de tratamento de exce&#231;&#227;o de agentes tamb&#233;m &#233; confuso; caso uma tool n&#227;o seja encontrada, ou caso a tool retorne um erro, o usu&#225;rio tem pouco controle do fluxo excepcional, reduzindo a efic&#225;cia geral do sistema.</p><h3>Mas afinal, devo usar o LangChain?</h3><p>Apesar das limita&#231;&#245;es mencionadas acima, ainda acredito que o uso do LangChain &#233; muito ben&#233;fico, principalmente para aqueles que est&#227;o iniciando sua jornada no processo de cria&#231;&#227;o de aplica&#231;&#245;es baseadas em LLMs. </p><p>O LangChain facilita muito o processo de carregamento de conte&#250;do externas, processamento dos dados, cria&#231;&#227;o de embeddings, armazenamento de dados em bancos de dados vetoriais, etc. Inclusive, no <a href="https://gustavopinto.gumroad.com/l/bootcamp-llm4devs">bootcamp LLM4Devs</a>, n&#243;s usamos o LangChain para criar uma aplica&#231;&#227;o RAG simples, em poucas horas.</p><p>Ademais, o problema da complexidade do uso do LangChain deve ser minimizado nas pr&#243;ximas vers&#245;es, principalmente com a estabiliza&#231;&#227;o da LCEL.</p><p>Pra finalizar, n&#227;o custa lembrar que essas s&#227;o apenas as minhas pr&#243;prias observa&#231;&#245;es, baseada no meu uso da ferramenta. Aconselho voc&#234; leitor a avaliar suas pr&#243;prias percep&#231;&#245;es, antes de tomar uma decis&#227;o sobre usar (ou n&#227;o) o framework.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ml4se.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Inscreva-se&quot;,&quot;language&quot;:&quot;pt-br&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">ML4SE &#233; uma newsletter focada em ajudar devs a mastigar t&#233;cnicas de aprendizado de m&#225;quina. Para receber novos posts, se inscreva na newsletter.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Digite seu e-mail&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Inscreva-se"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[1 Ano da Newsletter ML4SE 🥳]]></title><description><![CDATA[No dia 10 de Maio de 2023, publiquei o primeiro texto nessa newsletter.]]></description><link>https://ml4se.substack.com/p/1-ano-da-newsletter-ml4se</link><guid isPermaLink="false">https://ml4se.substack.com/p/1-ano-da-newsletter-ml4se</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Thu, 09 May 2024 10:00:45 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/c88cc5b4-8dd4-4bac-b93b-6134e1ee6c42_1702x1702.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>No dia 10 de Maio de 2023, publiquei o primeiro texto nessa newsletter. E, 40 textos depois, comemoro hoje o primeiro anivers&#225;rio da ML4SE!</p><p>Comecei essa newsletter com dois objetivos: </p><ol><li><p>estudar e me desenvolver profissionalmente nessa &#225;rea de ML4SE; e </p></li><li><p>me aproximar da comunidade de desenvolvedores de software. </p></li></ol><p>Assumi o compromisso de escrever nessa newsletter por um ano. </p><p>Aos trancos e barrancos, <strong>fico muito feliz em mencionar que este &#233; 40o texto dessa newsletter</strong>. Obrigado a todos voc&#234;s que acompanham esse trabalho, seja lendo os textos, compartilhando com colegas, dando likes nas redes sociais, etc. Meu muito obrigado!</p><p>Agora &#233; hora de refletir um pouco sobre o que rolou. </p><p>Tem vontade de criar uma newsletter e n&#227;o sabe o que esperar? Talvez esse texto ajude a gerenciar as expectativas.</p><div><hr></div><p>&#128218; Voc&#234; &#233; dev e quer criar aplica&#231;&#245;es baseadas em LLMs?</p><p>No pr&#243;ximo dia 18/05/2024 (s&#225;bado), vai rolar um bootcamp online de 3h de dura&#231;&#227;o, sobre desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. Alguns dos t&#243;picos que ser&#227;o abordados:</p><p>&#128992; Entendendo sobre LLMs</p><p>&#128995; Testando prompts e engenharia de prompts</p><p>&#128309; Entendendo de embeddings</p><p>&#128994; Comparando dados por similaridade</p><p>&#128993; Conectando com um banco vetorial</p><p>E mais, se inscrevendo no bootcamp, <a href="https://gustavopinto.gumroad.com/l/llm4devs">voc&#234; ganha acesso a tr&#234;s cursos sobre LLMs</a>: </p><p>Interessou? Clique aqui e saiba mais:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://ml4se.substack.com/p/bootcamp&quot;,&quot;text&quot;:&quot;Bootcamp LLM4Devs&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="/__u/ml4se.substack.com/p/bootcamp"><span>Bootcamp LLM4Devs</span></a></p><div><hr></div><h3>O que &#233; ML4SE?</h3><p>ML4SE, do Ingl&#234;s, Machine Learning for Software Engineering, &#233; uma &#225;rea de pesquisa que utiliza de t&#233;cnicas de Machine Learning para resolver problemas da Engenharia de Software. </p><p>ML4SE &#233; uma &#225;rea relativamente conhecida no submundo da Engenharia de Software. Quando criei essa newsletter, pensei que esse termo seria tamb&#233;m facilmente transposto, e que as pessoas iriam assimilar essa confus&#227;o de letras com um n&#250;mero no meio com facilidade. Obviamente me enganei.</p><p>Algumas pessoas j&#225; me abordaram para falar da newsletter, sem conseguir pronunciar o nome da newsletter. S&#243; assim para eu perceber que n&#227;o somente as pessoas tem dificuldades em gravar o nome, mas tamb&#233;m que o nome n&#227;o &#233; facilmente pronunci&#225;vel. </p><p>Ou seja, ML4SE &#233; um p&#233;ssimo nome para uma newsletter.</p><p>Vez por outra me pego pensando em qual seria um nome melhor. Confesso que ainda n&#227;o cheguei a uma conclus&#227;o, mas &#233; poss&#237;vel que essa newsletter mude de nome nos pr&#243;ximos meses.</p><h3>Escrever quando seu trabalho n&#227;o &#233; escrever</h3><p>A newsletter nasceu com a tentativa de publicar textos semanalmente. Como escritor acad&#234;mico, minha soberba insistia em dizer que escrever mil palavras por semana seria uma atividade simples e prazerosa. </p><p>Nos primeiros 3, 4 meses, eu at&#233; que conseguir manter essa disciplina (inclusive houveram semanas que eu publiquei mais de um texto). No entanto, rapidamente percebi que mais importante do que conhecer algumas t&#233;cnicas de escrita, &#233; conseguir emprega-las regularmente.</p><p>Isso, de certa forma, foi um conhecimento novo pra mim. Como acad&#234;mico, parte do seu trabalho &#233; escrever. Voc&#234; escreve regularmente porque o seu trabalho &#233; escrever regularmente. Agora que coloquei minhas barbas acad&#234;micas de molho, escrever regularmente n&#227;o &#233; mais o meu trabalho; ao menos, n&#227;o &#233; mais o que paga as contas. </p><p>Logo, eu preciso arrumar tempo para escrever. Da mesma forma que se arruma tempo para fazer esportes, ir ao supermercado, levar o cachorro para passear, &#233; preciso arrumar tempo para escrever. Escrever passa a competir com todas as demais atividades do dia a dia. Consequentemente, escrever, quando seu trabalho n&#227;o &#233; escrever, &#233; muito mais dif&#237;cil. </p><p>Um salve a todos voc&#234;s que escrevem mesmo que escrever n&#227;o seja seu ganha p&#227;o!</p><h3>Frequ&#234;ncia de escrita</h3><p>Come&#231;ar a escrever na newsletter foi f&#225;cil. Como qualquer atividade nova, voc&#234; tende a come&#231;ar empolgado, ainda mais quando voc&#234; entende das t&#233;cnicas da atividade em quest&#227;o. Mas entender das t&#233;cnicas n&#227;o &#233; tudo.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="/__u/substackcdn.com/image/fetch/$s_!9BmH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb42fe4ca-fa2e-4945-943a-38243e5cc465_1310x798.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="/__u/substackcdn.com/image/fetch/$s_!9BmH!, /__u/ml4se.substack.com/w_424, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb42fe4ca-fa2e-4945-943a-38243e5cc465_1310x798.png 424w, /__u/substackcdn.com/image/fetch/$s_!9BmH!, /__u/ml4se.substack.com/w_848, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb42fe4ca-fa2e-4945-943a-38243e5cc465_1310x798.png 848w, /__u/substackcdn.com/image/fetch/$s_!9BmH!, /__u/ml4se.substack.com/w_1272, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb42fe4ca-fa2e-4945-943a-38243e5cc465_1310x798.png 1272w, /__u/substackcdn.com/image/fetch/$s_!9BmH!, /__u/ml4se.substack.com/w_1456, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb42fe4ca-fa2e-4945-943a-38243e5cc465_1310x798.png 1456w" sizes="100vw"><img src="/__u/substackcdn.com/image/fetch/$s_!9BmH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb42fe4ca-fa2e-4945-943a-38243e5cc465_1310x798.png" width="1310" height="798" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b42fe4ca-fa2e-4945-943a-38243e5cc465_1310x798.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:798,&quot;width&quot;:1310,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:74062,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="/__u/substackcdn.com/image/fetch/$s_!9BmH!, /__u/ml4se.substack.com/w_424, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb42fe4ca-fa2e-4945-943a-38243e5cc465_1310x798.png 424w, /__u/substackcdn.com/image/fetch/$s_!9BmH!, /__u/ml4se.substack.com/w_848, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb42fe4ca-fa2e-4945-943a-38243e5cc465_1310x798.png 848w, /__u/substackcdn.com/image/fetch/$s_!9BmH!, /__u/ml4se.substack.com/w_1272, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb42fe4ca-fa2e-4945-943a-38243e5cc465_1310x798.png 1272w, /__u/substackcdn.com/image/fetch/$s_!9BmH!, /__u/ml4se.substack.com/w_1456, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb42fe4ca-fa2e-4945-943a-38243e5cc465_1310x798.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Quantidade de textos publicados por m&#234;s</figcaption></figure></div><p>A figura acima contabiliza o n&#250;mero de textos por m&#234;s.</p><p>Depois de escrever 10 textos entre Maio e Junho de 2023, n&#227;o demorou muito para a periodicidade diminuir, at&#233; cair por completo. Em Julho e Agosto de 2023, reduzi para o esperado n&#250;mero de 4 textos por m&#234;s. Mas em Setembro de 2023 eu perdi a sequencia de textos pela primeira vez. Em Outubro de 2023 eu consegui retomar ao 4 textos mensais. Mas&#8230;</p><p>Entre Novembro 2023 e Dezembro 2023 eu publiquei apenas 5 textos. Em Janeiro de 2024, por outro lado, eu n&#227;o escrevi nenhum texto. Lembro que naquele momento eu me questionava sobre a continuidade da newsletter. Mais sobre isso a seguir.</p><p>Em Fevereiro e Mar&#231;o de 2024 consegui retomar, com uma boa frequ&#234;ncia (7 textos publicados nos dois meses), mas Abril novamente quase n&#227;o escrevi na newsletter. Diferente de Janeiro, em Abril eu de fato gostaria de ter escrito (e tinha v&#225;rios textos em mente), mas um mix de viagens, doen&#231;as e outros afazeres, me afastaram do teclado. </p><p>Chegamos na segunda semana de Maio, e este &#233; o segundo texto do m&#234;s. Embora eu, como escritor dessa newsletter, ainda trabalharei a mentalidade para manter a periodicidade semanal dos textos, talvez, como leitor dessa newsletter, aguardar 2&#8212;3 textos por m&#234;s seja algo mais pr&#243;ximo do real. </p><h3>Quantidade de conte&#250;do escrito</h3><p>Esses 40 textos geraram 58.306 palavras, o que &#233; equivalente a um pequeno livro de umas 150 p&#225;ginas. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="/__u/substackcdn.com/image/fetch/$s_!f4fq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e1aa0c5-67ce-4fa0-927e-39bcc1e1ac14_1314x792.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="/__u/substackcdn.com/image/fetch/$s_!f4fq!, /__u/ml4se.substack.com/w_424, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e1aa0c5-67ce-4fa0-927e-39bcc1e1ac14_1314x792.png 424w, /__u/substackcdn.com/image/fetch/$s_!f4fq!, /__u/ml4se.substack.com/w_848, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e1aa0c5-67ce-4fa0-927e-39bcc1e1ac14_1314x792.png 848w, /__u/substackcdn.com/image/fetch/$s_!f4fq!, /__u/ml4se.substack.com/w_1272, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e1aa0c5-67ce-4fa0-927e-39bcc1e1ac14_1314x792.png 1272w, /__u/substackcdn.com/image/fetch/$s_!f4fq!, /__u/ml4se.substack.com/w_1456, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e1aa0c5-67ce-4fa0-927e-39bcc1e1ac14_1314x792.png 1456w" sizes="100vw"><img src="/__u/substackcdn.com/image/fetch/$s_!f4fq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e1aa0c5-67ce-4fa0-927e-39bcc1e1ac14_1314x792.png" width="1314" height="792" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4e1aa0c5-67ce-4fa0-927e-39bcc1e1ac14_1314x792.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:792,&quot;width&quot;:1314,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:89496,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="/__u/substackcdn.com/image/fetch/$s_!f4fq!, /__u/ml4se.substack.com/w_424, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e1aa0c5-67ce-4fa0-927e-39bcc1e1ac14_1314x792.png 424w, /__u/substackcdn.com/image/fetch/$s_!f4fq!, /__u/ml4se.substack.com/w_848, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e1aa0c5-67ce-4fa0-927e-39bcc1e1ac14_1314x792.png 848w, /__u/substackcdn.com/image/fetch/$s_!f4fq!, /__u/ml4se.substack.com/w_1272, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e1aa0c5-67ce-4fa0-927e-39bcc1e1ac14_1314x792.png 1272w, /__u/substackcdn.com/image/fetch/$s_!f4fq!, /__u/ml4se.substack.com/w_1456, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e1aa0c5-67ce-4fa0-927e-39bcc1e1ac14_1314x792.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Para cada texto, eu tento escrever o m&#237;nimo de mil palavras. Como &#233; poss&#237;vel perceber pela figura acima, em 36 dos 40 textos, consegui chegar nesse limite m&#237;nimo. </p><p>Por outro lado, eu n&#227;o tenho nenhum limite m&#225;ximo de palavras por texto. Como eu tento escrever o texto todo de uma &#250;nica vez, geralmente eu termino 1) por cansa&#231;o ou 2) por precisar alternar para uma outra atividade. Deixar o texto para terminar outro dia pra mim &#233; o pior cen&#225;rio, que eu evito a todo custo.</p><h3>Qualidade do conte&#250;do escrito</h3><p>Na queda de bra&#231;os entre velocidade e qualidade, eu tendo a priorizar a velocidade na escrita e publica&#231;&#227;o dos textos da newsletter. Eu muito raramente eu fa&#231;o edi&#231;&#245;es textuais finas, com o objetivo de melhorar a qualidade do conte&#250;do escrito. Ou seja, depois de escrever a &#250;ltima linha, o mais prov&#225;vel &#233; que eu clique em &#8220;publicar&#8221;. </p><p>Com isso, os erros de digita&#231;&#227;o e as senten&#231;as sem sentido acabam indo de brinde para o leitor. Confesso que isso n&#227;o &#233; algo que eu me preocupe. Desde que comecei a escrever irregularmente em m&#237;dias sociais, eu entendi que se for para refinar o texto de um blog (ou, nesse caso, da newsletter) com o mesmo esmero que eu fa&#231;o em um artigo cient&#237;fico, o mais prov&#225;vel &#233; que esse texto nunca venha a existir. </p><p>Vez por outra algum leitor aponta alguns desses erros, o que eu prontamente corrijo. E por mim est&#225; tudo bem, pois entre ter um texto de qualidade sub&#243;tima e n&#227;o ter o texto, eu prefiro o primeiro caso.</p><h3>Crescimento da newsletter</h3><p>Ao iniciar a newsletter, eu imaginava que um grande n&#250;mero de usu&#225;rios iria encontra-la e, como em um passe de m&#225;gica, eu teria uma rica base de usu&#225;rios. Mas n&#227;o &#233; bem assim que funciona. </p><p>Hoje entendo claramente que a base de usu&#225;rios s&#243; cresce a medida que eu escrevo novos textos. Mas n&#227;o somente escrever: eu preciso tamb&#233;m divulgar esse material. </p><p>Confesso que essa parte de divulga&#231;&#227;o e marketing do conte&#250;do &#233; uma habilidade que eu ainda n&#227;o trabalho bem, mas sinto que consegui avan&#231;ar alguns cent&#237;metros. Mas n&#227;o tem muito atalho. Tem que manter o fluxo de escrita de textos.</p><p>Com rela&#231;&#227;o a base de usu&#225;rios, no momento que escrevo esse texto, a newsletter tem 170 assinantes!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="/__u/substackcdn.com/image/fetch/$s_!N44g!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a12dd7e-eb0a-4860-8493-3003309a1c76_2364x908.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="/__u/substackcdn.com/image/fetch/$s_!N44g!, /__u/ml4se.substack.com/w_424, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a12dd7e-eb0a-4860-8493-3003309a1c76_2364x908.png 424w, /__u/substackcdn.com/image/fetch/$s_!N44g!, /__u/ml4se.substack.com/w_848, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a12dd7e-eb0a-4860-8493-3003309a1c76_2364x908.png 848w, /__u/substackcdn.com/image/fetch/$s_!N44g!, /__u/ml4se.substack.com/w_1272, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a12dd7e-eb0a-4860-8493-3003309a1c76_2364x908.png 1272w, /__u/substackcdn.com/image/fetch/$s_!N44g!, /__u/ml4se.substack.com/w_1456, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a12dd7e-eb0a-4860-8493-3003309a1c76_2364x908.png 1456w" sizes="100vw"><img src="/__u/substackcdn.com/image/fetch/$s_!N44g!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a12dd7e-eb0a-4860-8493-3003309a1c76_2364x908.png" width="1456" height="559" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7a12dd7e-eb0a-4860-8493-3003309a1c76_2364x908.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:559,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:118452,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="/__u/substackcdn.com/image/fetch/$s_!N44g!, /__u/ml4se.substack.com/w_424, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a12dd7e-eb0a-4860-8493-3003309a1c76_2364x908.png 424w, /__u/substackcdn.com/image/fetch/$s_!N44g!, /__u/ml4se.substack.com/w_848, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a12dd7e-eb0a-4860-8493-3003309a1c76_2364x908.png 848w, /__u/substackcdn.com/image/fetch/$s_!N44g!, /__u/ml4se.substack.com/w_1272, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a12dd7e-eb0a-4860-8493-3003309a1c76_2364x908.png 1272w, /__u/substackcdn.com/image/fetch/$s_!N44g!, /__u/ml4se.substack.com/w_1456, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a12dd7e-eb0a-4860-8493-3003309a1c76_2364x908.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Crescimento da base de usu&#225;rios ao longo de 1 ano</figcaption></figure></div><p>Como podemos perceber na curva de crescimento de usu&#225;rios, durante Novembro 2023 e Janeiro 2024, a newsletter quase que estagnou. </p><h3>Estagna&#231;&#227;o da newsletter</h3><p>Como comentei acima, durante Dezembro 2023 e Janeiro 2024 eu pensei fortemente em deixar a newsletter de lado. H&#225; dois principais motivos:</p><ul><li><p><strong>Baixo retorno:</strong> E aqui eu nem estou falando de retorno financeiro. &#201; retorno no sentido de conseguir criar uma comunidade de leitores interessados no conte&#250;do. Observar crescimentos mete&#243;ricos de outros autores de newsletter me fez acreditar que eu tamb&#233;m poderia passar por algo parecido. Demorei para perceber que o jogo da cria&#231;&#227;o de conte&#250;do &#233; o do longo prazo.</p></li><li><p><strong>N&#227;o entender que o cliente sou eu. </strong>Embora escrever seja uma atividade que eu me considero tecnicamente habilidoso, a obrigatoriedade de escrever regularmente, sobre temas diferentes, muitos dos quais eu n&#227;o domino, gerou por vezes um estresse que eu n&#227;o conseguia justificar pra mim mesmo. <em>Ora, se ningu&#233;m pediu pra eu fazer isso, por que diachos eu deveria estar me estressando?</em> <em>Se estou cansado, &#233; s&#243; parar de escrever, n&#227;o?</em> Depois de tanto tempo trabalhando para os outros, eu demorei pra entender que eu n&#227;o criei essa newsletter para ajudar algu&#233;m; eu criei para me ajudar a me tornar um profissional melhor. Se eu ajudar algu&#233;m ao longo do processo, &#243;timo. Mas o objetivo inicial n&#227;o era esse.</p></li></ul><p>Eu esqueci que eu sou o principal benefici&#225;rio dessa newsletter. Eu esqueci qual era o meu prop&#243;sito com a newsletter. </p><p>Sem um prop&#243;sito claro, escrever aqui se tornou chato, ma&#231;ante. Virou mais uma daquelas obriga&#231;&#245;es da vida adulta que a gente precisa cumprir.</p><p>Ter claro os objetivos da newsletter me ajudaram a colocar os pingos nos is. Escrever esse texto, agora, refor&#231;a o meu objetivo com essa newsletter. (N&#227;o obstante, este est&#225; sendo um texto muito gratificante de escrever :-)</p><h3>Visibilidade dos textos</h3><p>A newsletter atraiu 9.001 visualiza&#231;&#245;es durante esse primeiro ano. O texto mais visualizado foi o &#8220;<a href="/__u/ml4se.substack.com/p/nao-use-o-chatgpt-para-gerar-testes">N&#227;o use o ChatGPT para gerar testes de unidade</a>&#8221;, com 443 visualiza&#231;&#245;es. </p><p>A newsletter tem uma taxa de abertura de 39.9%. Nunca cheguei a investigar outras taxas, mas confesso que considero essa uma boa taxa de abertura. </p><p>Embora nenhum texto tenha viralizado na rede, eu considero bem interessante esses n&#250;meros. N&#227;o tenho dados para comparar com meus textos acad&#234;micos, mas acredito que poucos s&#227;o os artigos que eu tenho mais de 400 visualiza&#231;&#245;es &#8212; mesmo estes estando dispon&#237;veis em grandes sites de editoras.</p><h3>Organiza&#231;&#227;o para escrever</h3><p>Eu fico impressionado com algumas newsletters que eu assinto. Religiosamente, o texto est&#225; na minha caixa de entrada, toda a semana, no mesmo hor&#225;rio. </p><p>Esse &#233; um n&#237;vel de disciplina que eu n&#227;o consigo nem entender direito. Eu fico feliz s&#243; de conseguir escrever algo na semana corrente; manter o fluxo de textos no mesmo dia e hor&#225;rio pra mim &#233; algo impens&#225;vel :-)</p><p>Por algum tempo eu escrevia aos domingo, de tarde/noite. Mas como domingo &#233; um dia bem fam&#237;lia, eu mentalmente tendia a deixar pro &#250;ltimo minuto poss&#237;vel (at&#233; chegar ao ponto de tardiar para segunda). Tentei tamb&#233;m planejar a escrita para dias como quarta-feira e/ou sexta-feira.  Mas, sinto que ter um dia fixo n&#227;o funciona bem comigo, uma vez que vez por outra tem algum evento social que colide com o dia de escrita, tardiando mais um texto na newsletter. </p><p>Mas, no fim, n&#227;o tenho dia certo para escrever. Escrevo, quando d&#225;. </p><p>Por outro lado, quando eu escrevo, eu tendo a escrever todo o texto de uma &#250;nica vez. Eu evito quebrar escrita do textos em m&#250;ltiplos dias, uma vez que isso cai no problema de competir com eventos sociais, deixando a escrita do texto pro &#250;ltimo minuto poss&#237;vel.</p><h3>Uso de ferramentas de IA</h3><p>Embora eu sempre escreva miolo do conte&#250;do, eu regularmente uso o ChatGPT em algumas partes do conte&#250;do. Por exemplo, para identificar erros de sintaxe ou fazer pequenas melhorias no texto, eu uso um prompt do tipo: &#8220;Fa&#231;a apenas pequenas melhorias ortogr&#225;ficas no texto abaixo&#8221;. </p><p>Em outros casos, eu pe&#231;o para o ChatGPT gerar algum conte&#250;do que eu possivelmente j&#225; escrevi algumas outras vezes (e estou com pouco interesse em escrever novamente), algo como &#8220;Escreva 40 palavras sobre embeddings&#8221;. Tamb&#233;m recorrentemente uso o ChatGPT para escrever a conclus&#227;o dos textos (p.e., &#8220;Dado esse texto de blog, escreva uma conclus&#227;o em 30 palavras&#8221;). </p><p>Al&#233;m do ChatGPT, as figuras que acompanham os textos tamb&#233;m s&#227;o geradas com ferramentas de IA. Testei v&#225;rias ferramentas ao longo desse ano. Mais recentemente, tenho usado somente o DALL-E 3.</p><h3>Monetiza&#231;&#227;o da newsletter</h3><p>Na internet tem v&#225;rios exemplos de newsletters bem sucedidas, em que o autor da newsletter recebe algumas dezenas (centenas?) de milhares de d&#243;lares, como resultado de uma rica base de usu&#225;rios que confiam no conte&#250;do compartilhado.</p><p>Esse claramente n&#227;o &#233; o caso dessa newsletter :-)</p><p>Embora exista uma vers&#227;o paga dessa newsletter (que eu confesso nem lembrar qual &#233; o valor), n&#227;o h&#225; nenhum assinante pago cadastrado. Algumas pessoas j&#225; me consultaram para saber quais outros benef&#237;cios elas teriam acesso, caso mudassem para um plano pago. Infelizmente, n&#227;o h&#225; outro benef&#237;cio ao assinante.</p><p>Eu j&#225; cheguei a pensar algumas a&#231;&#245;es que poderia desenvolver na newsletter paga (como textos mais profundos, v&#237;deos explicando os textos j&#225; escritos, etc), mas acho que em nenhuma dessas a&#231;&#245;es eu achei interessante o suficiente para agregar valor aos assinantes &#8212; acho que nem mesmo eu pagaria para assinar a minha newsletter. </p><p>Dessa forma, a newsletter n&#227;o gera nenhum retorno financeiro diretamente. No entanto, criar a newsletter me fez perceber outras formas de monetiza&#231;&#227;o</p><h3>Monetiza&#231;&#227;o inspirada pela newsletter</h3><p>Embora esta newsletter n&#227;o monetize diretamente, ela ajudou a monetizar indiretamente. </p><p>Atrav&#233;s da newsletter, eu percebi que existia uma demanda para cria&#231;&#227;o de material t&#233;cnico mais profundo. Por conta disso, comecei a criar alguns cursos t&#233;cnicos, e divulgar aqui pela newsletter. At&#233; o momento, j&#225; criei tr&#234;s cursos: </p><ul><li><p><a href="https://gustavopinto.gumroad.com/l/chat-llm">Converse com seus Documentos</a></p></li><li><p><a href="https://gustavopinto.gumroad.com/l/embeddings">Entendendo Embeddings</a></p></li><li><p><a href="https://gustavopinto.gumroad.com/l/dominando-chunks">Dominando Estrat&#233;gias de Chunking</a></p></li></ul><p>Como esses cursos s&#227;o gravados, os alunos tem poucas chances de interagir com outros alunos e tamb&#233;m comigo, como instrutor desses cursos. Por conta dessa falta de intera&#231;&#227;o, algumas pessoas me consultaram sobre a possibilidade de realiza-los em um formato s&#237;ncrono. Pensando nessa demanda, nasceu o <a href="/__u/ml4se.substack.com/p/bootcamp">Bootcamp LLM4Dev</a>, um treinamento de 3h focando em como criar aplica&#231;&#245;es baseadas em LLMs. </p><p>Mas nenhum desses materiais teria sido constru&#237;do se n&#227;o existisse a newsletter. Ao escrever, compartilhar, receber feedback e refletir em cima, deu pra observar novas demandas que, por sua vez, puderam ser monetizadas.</p><h3>Agradecimentos</h3><p>Talvez essa newsletter n&#227;o teria existido se n&#227;o fosse o <a href="https://www.linkedin.com/in/alberto-souza-953b0b7/">Alberto Tavares</a>. L&#225; no passado, o Alberto j&#225; tinha me provocado na poss&#237;vel cria&#231;&#227;o de um servi&#231;o de resumos de textos cient&#237;ficos. A id&#233;ia parecia boa, mas acabou que n&#227;o foi pra frente. Mas a semente tinha sido plantada.</p><p>Preciso tamb&#233;m agradecer a todos voc&#234;s que l&#234;em meu conte&#250;do, que compartilham com colegas, que me ajudam indicando meus erros (sejam eles t&#233;cnicos ou de ortografia), etc. Saber que tem algu&#233;m do outro lado da linha &#233; muito gratificante pra esse trabalho, que &#233; majoritariamente sozinho. </p><p>Obrigado!</p>]]></content:encoded></item><item><title><![CDATA[7 Limitações de Sistemas Baseados em RAG]]></title><description><![CDATA[As novas inova&#231;&#245;es dos grandes modelos lingu&#237;sticos (do Ingl&#234;s, LLMs) forneceram aos engenheiros de software novas capacidades para construir solu&#231;&#245;es mais sofisticadas, como por exmplo completar tarefas complexas, resumir documentos, responder a perguntas sobre um ou mais artefatos, e gerar novos conte&#250;dos.]]></description><link>https://ml4se.substack.com/p/7-limitacoes-de-sistemas-baseados</link><guid isPermaLink="false">https://ml4se.substack.com/p/7-limitacoes-de-sistemas-baseados</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Thu, 02 May 2024 16:00:52 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/fdd86cc1-079e-47ce-9562-be6d341c07ce_1024x1024.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As novas inova&#231;&#245;es dos grandes modelos lingu&#237;sticos (do Ingl&#234;s, LLMs) forneceram aos engenheiros de software novas capacidades para construir solu&#231;&#245;es mais sofisticadas, como por exmplo completar tarefas complexas, resumir documentos, responder a perguntas sobre um ou mais artefatos, e gerar novos conte&#250;dos. </p><p>No entanto, os LLMs enfrentam limita&#231;&#245;es no que diz respeito ao conhecimento atualizado ou ao conhecimento espec&#237;fico de dom&#237;nio atualmente capturado nos reposit&#243;rios da empresa. Duas op&#231;&#245;es para abordar esse problema s&#227;o: </p><ol><li><p>Fine-tuning dos LLMs (continua&#231;&#227;o do treinamento de um LLM usando artefatos espec&#237;ficos do dom&#237;nio), o que requer a gest&#227;o ou hospedagem de um LLM refinado; ou</p></li><li><p>Usar abordagens de <a href="/__u/ml4se.substack.com/p/rag-transforme-respostas-genericas">Retrieval-Augmented Generation (RAG)</a>, que dependem de LLMs para a gera&#231;&#227;o de respostas usando artefatos de conhecimento existentes (e extens&#237;veis). </p></li></ol><p>Ambas as op&#231;&#245;es t&#234;m pr&#243;s e contras relacionados &#224; privacidade/seguran&#231;a dos dados, escalabilidade, custo, habilidades necess&#225;rias, etc. Neste texto, nos concentramos em algumas limita&#231;&#245;es das abordagem do RAG.</p><div><hr></div><p>&#128218; Voc&#234; &#233; dev e quer criar aplica&#231;&#245;es baseadas em LLMs?</p><p>No pr&#243;ximo dia 18/05/2024 (s&#225;bado), vai rolar um bootcamp online de 3h de dura&#231;&#227;o, sobre desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. Alguns dos t&#243;picos que ser&#227;o abordados:</p><p>&#128992; Entendendo sobre LLMs</p><p>&#128995; Testando prompts e engenharia de prompts</p><p>&#128309; Entendendo de embeddings</p><p>&#128994; Comparando dados por similaridade</p><p>&#128993; Conectando com um banco vetorial</p><p>E mais, se inscrevendo no bootcamp, <a href="https://gustavopinto.gumroad.com/l/llm4devs">voc&#234; ganha acesso a tr&#234;s cursos sobre LLMs</a>: </p><p>Interessou? Clique aqui e saiba mais:</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://ml4se.substack.com/p/bootcamp&quot;,&quot;text&quot;:&quot;Quero conhecer o Bootcamp LLM4Devs&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="/__u/ml4se.substack.com/p/bootcamp"><span>Quero conhecer o Bootcamp LLM4Devs</span></a></p><div><hr></div><h3>RAG Overview</h3><p>Os sistemas baseados em RAG oferecem uma solu&#231;&#227;o atraente para esse desafio. </p><p>Ao integrar mecanismos de recupera&#231;&#227;o com as capacidades generativas dos LLMs, os sistemas RAG podem sintetizar informa&#231;&#245;es contextualmente relevantes, precisas e atualizadas. Um sistema baseado em RAG combina capacidades de recupera&#231;&#227;o de informa&#231;&#245;es e a habilidade generativa dos LLMs. </p><p>O componente de recupera&#231;&#227;o se concentra em recuperar informa&#231;&#245;es relevantes para uma consulta de um usu&#225;rio a partir de um reposit&#243;rio de dados. O componente de gera&#231;&#227;o, por sua vez, usa essas informa&#231;&#245;es recuperadas como contexto para gerar uma resposta para a consulta. </p><p>Os sistemas RAG s&#227;o um caso de uso importante, j&#225; que todas as informa&#231;&#245;es n&#227;o estruturadas podem agora ser indexadas e disponibilizadas para consulta, reduzindo o tempo de desenvolvimento, sem necessidade de cria&#231;&#227;o de, por exemplo, grafos de conhecimento e com pouca curadoria dos dados.</p><p>Engenheiros de software construindo sistemas RAG devem pr&#233;-processar o conhecimento de dom&#237;nio capturado como artefatos em diferentes formatos, armazenar informa&#231;&#245;es processadas em um banco de dados apropriado, implementar  estrat&#233;gias de busca adequadas, classificar os artefatos correspondentes e chamar a API dos LLMs passando consultas de usu&#225;rios e documentos de contexto. </p><h3>Limita&#231;&#245;es do RAG</h3><p>No artigo &#8220;<a href="https://arxiv.org/pdf/2401.05856">Seven Failure Points When Engineering a Retrieval Augmented Generation System</a>&#8221;, os autores exploraram 3 sistemas baseados em RAG, de forma a identificar suas limita&#231;&#245;es. </p><h4>Estudos de caso</h4><p>O artigo conduziu tr&#234;s estudos de caso para descobrir os desafios que surgem ao implementar sistemas RAG. </p><ul><li><p>Cognitive Reviewer: O Cognitive Reviewer &#233; um sistema baseado em RAG que apoia pesquisadores na an&#225;lise de documentos cient&#237;ficos. Ele permite que eles carreguem artigos de pesquisa relacionados a uma pergunta ou objetivo espec&#237;fico. Os documentos s&#227;o classificados e dispon&#237;veis para revis&#227;o manual, e os pesquisadores podem fazer perguntas diretamente aos documentos. O sistema processa documentos em tempo real e usa um algoritmo de classifica&#231;&#227;o para ordenar os documentos carregados.</p></li><li><p>AI Tutor: O AI Tutor &#233; um sistema RAG integrado ao sistema de gest&#227;o de aprendizagem de uma Universidade. Ele permite que alunos fa&#231;am perguntas sobre o conte&#250;do do curso, com respostas obtidas do material de aprendizagem, incluindo PDFs, v&#237;deos e textos. V&#237;deos s&#227;o transcritos e fragmentados pelo modelo Whisper. O sistema tamb&#233;m inclui um reescritor para consultas, considerando o contexto. </p></li><li><p>Biomedical Q&amp;A: Este sistema RAG foi criado usando um dataset cient&#237;fico, composto por perguntas, respostas e links para documentos. O dataset cont&#233;m pares de perguntas e respostas no dom&#237;nio biom&#233;dico, com respostas de tipos variados. Foram indexados 4.017 documentos e 1.000 perguntas. </p></li></ul><h3>Limita&#231;&#245;es de sistemas baseados em RAG</h3><p>A partir dos estudos de caso, os autores identificaram uma sete principais limita&#231;&#245;es. S&#227;o elas:</p><ul><li><p><strong>Conte&#250;do ausente.</strong> O primeiro caso ocorre ao fazer uma pergunta que n&#227;o pode ser respondida pelos documentos dispon&#237;veis. No caso positivo, o sistema RAG responder&#225; algo como "Desculpe, n&#227;o sei". No entanto, para perguntas relacionadas ao conte&#250;do, mas que n&#227;o t&#234;m respostas, o sistema pode ser enganado a dar uma resposta incorreta.</p></li><li><p><strong>Documentos melhor ranqueados faltantes</strong>. A resposta para a pergunta est&#225; em um documento existente, mas este n&#227;o foi classificado alto o suficiente para ser retornada ao usu&#225;rio. Em teoria, todos os documentos s&#227;o classificados e usados nas pr&#243;ximas etapas. No entanto, na pr&#225;tica, somente os K-principais documentos s&#227;o retornados, onde K &#233; um valor selecionado com base no desempenho</p></li><li><p><strong>Documentos n&#227;o selecionados para adicionar contexto</strong>. Documentos com a resposta foram recuperados do banco de dados, mas n&#227;o foram selecionados para adicionar contexto para gerar uma resposta. Isso ocorre quando muitos documentos s&#227;o retornados do banco de dados e um processo de consolida&#231;&#227;o ocorre para buscar a resposta.</p></li><li><p><strong>LLM n&#227;o identificou o documento.</strong> Aqui, a resposta est&#225; presente no contexto fornecido ao LLM, mas o modelo de linguagem n&#227;o conseguiu identificar e extrair a resposta correta. Normalmente, isso ocorre quando h&#225; muito ru&#237;do ou informa&#231;&#245;es contradit&#243;rias no contexto.</p></li><li><p><strong>Formato Inadequado.</strong> A pergunta envolvia a extra&#231;&#227;o de informa&#231;&#245;es em um determinado formato, como uma tabela ou lista, e a LLM ignorou esta instru&#231;&#227;o.</p></li><li><p><strong>Especificidade Incorreta</strong>. A resposta &#233; retornada pela LLM, por&#233;m n&#227;o &#233; espec&#237;fica o suficiente (ou &#233; muito espec&#237;fica) para atender &#224; necessidade do usu&#225;rio. Esse problema tamb&#233;m ocorre quando os usu&#225;rios n&#227;o t&#234;m certeza de como fazer uma pergunta (e lan&#231;am perguntas muito gerais).</p></li><li><p><strong>Incompleto.</strong> Respostas incompletas n&#227;o s&#227;o incorretas, mas perdem algumas das informa&#231;&#245;es, mesmo que essas informa&#231;&#245;es estejam no contexto e dispon&#237;veis para extra&#231;&#227;o. Um exemplo de pergunta, como "Quais s&#227;o os pontos-chave abordados nos documentos A, B e C?" Uma abordagem melhor seria fazer essas perguntas separadamente.</p></li></ul><h2>Conclus&#227;o</h2><p>Os LLMs oferecem novas capacidades para engenheiros de software, permitindo a constru&#231;&#227;o de solu&#231;&#245;es inovadoras. No entanto, eles enfrentam limita&#231;&#245;es no acesso a conhecimentos atualizados ou espec&#237;ficos de dom&#237;nios capturados em reposit&#243;rios corporativos. Sistemas baseadas em RAG emergem como uma solu&#231;&#227;o, integrando capacidades de recupera&#231;&#227;o de dados e gera&#231;&#227;o de respostas com precis&#227;o contextual.</p><p>O artigo &#8220;Seven Failure Points When Engineering a Retrieval Augmented Generation System&#8221; examina os desafios de implementar sistemas RAG, apresentando estudos de caso que revelam pontos falhos cruciais. </p><p>O estudo conclui que a implementa&#231;&#227;o eficaz de sistemas RAG requer um equil&#237;brio entre pr&#233;-processamento de artefatos, armazenamento de dados, estrat&#233;gia de busca e integra&#231;&#227;o com APIs de LLMs, destacando o papel fundamental de desenvolvedores na supera&#231;&#227;o dessas limita&#231;&#245;es para sistemas RAG robustos e eficazes.</p>]]></content:encoded></item><item><title><![CDATA[O que são tools?]]></title><description><![CDATA[Um novo paradigma de programa&#231;&#227;o?]]></description><link>https://ml4se.substack.com/p/o-que-sao-tools</link><guid isPermaLink="false">https://ml4se.substack.com/p/o-que-sao-tools</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Tue, 02 Apr 2024 01:43:38 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/e5c23357-0f2c-45d9-a737-85a6b538ff0a_1024x1024.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>O que s&#227;o tools?</h2><p>Similar as ferramentas (tools) usadas no mundo real, as tools usadas por LLM tamb&#233;m devem ser externas ao empregador (isto &#233;, o LLM) e s&#227;o parte do ambiente. </p><p>Como as LLMs s&#227;o produtos do mundo digital, uma tool &#233; uma fun&#231;&#227;o (por exemplo, <code>soma_um()</code>) executada nos seus ambientes correspondentes; por exemplo, programas Python s&#227;o execut&#225;veis em ambientes Python. </p><p>Dessa forma, uma tool pode ser aplicada a outros objetos (por exemplo, dados) e produzir uma sa&#237;da (por exemplo, <code>soma_um(1) &#8594; 2</code>).</p><p>Nesse texto, vamos entender um pouco mais sobre esse novo paradigma de programa&#231;&#227;o: O uso de tools executada externamente a LLM, que por sua vez gera as chamadas a fun&#231;&#227;o e argumentos de entrada para usar a tool.</p><div><hr></div><p>&#128218; Voc&#234; &#233; dev e quer aprender um pouco mais sobre a cria&#231;&#227;o de aplica&#231;&#245;es baseadas em LLM?<br><br>Eu criei um curso que aborda aspectos te&#243;ricos e pr&#225;ticos do desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. Alguns dos t&#243;picos cobertos:<br><br>&#128992; O que s&#227;o e como criar embeddings<br>&#128993; Como selecionar partes relevantes nos seus documentos<br>&#128309; Como integrar essas partes documentos com uma LLM</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://gustavopinto.gumroad.com/l/chat-llm&quot;,&quot;text&quot;:&quot;Achou legal? Clica aqui!&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://gustavopinto.gumroad.com/l/chat-llm"><span>Achou legal? Clica aqui!</span></a></p><div><hr></div><h3>Como uma tool &#233; integrada a uma LLM?</h3><p>Assumindo que uma LLM comunica com usu&#225;rios principalmente em linguagem natural, ao receber uma consulta de usu&#225;rio como "Como est&#225; o tempo hoje?", o LLM ent&#227;o procede para gerar texto ou chamadas de uma <code>tool</code>. Por exemplo, a LLM come&#231;a gerando alguns tokens de texto "Est&#225;...". </p><p>Quando a LLM precisa buscar tools externas para completar a tarefa, por exemplo, obter informa&#231;&#245;es meteorol&#243;gicas em tempo real, ele gera tokens com o nome da tool e argumentos de entrada dentro de par&#234;nteses para construir uma express&#227;o completa de chamada da tool. Esta express&#227;o completa acionar&#225; uma mudan&#231;a do modo de gera&#231;&#227;o de texto para o modo de execu&#231;&#227;o da tool. A tool ser&#225; executada e retornar&#225; o resultado da execu&#231;&#227;o para o LLM.</p><p>A LLM envia a chamada ao m&#233;todo <code>check_weather()</code> retorna a sa&#237;da "ensolarado". O resultado retornado substitui a chamada da tool nos tokens gerados pelo LLM (por exemplo, de "Est&#225; <code>check_weather()</code>" para "Est&#225; ensolarado"), que &#233; usado para etapas subsequentes de gera&#231;&#227;o. Consequentemente, o LLM volta ao modo de gera&#231;&#227;o de texto e continua a terminar a resposta gerando novos tokens de texto, por exemplo, adicionando "hoje.", e finalmente retornando a resposta ao usu&#225;rio.</p><h3>Por que tools s&#227;o &#250;teis?</h3><p>Tools podem ajudar na resolu&#231;&#227;o de tarefas de diferentes maneiras, dependendo da funcionalidade das <em>tools</em>. Tools podem ser divididas em tr&#234;s categorias:</p><ul><li><p><strong>Percep&#231;&#227;o:</strong> <em>Tools</em> de percep&#231;&#227;o fornecem ou coletam informa&#231;&#245;es do ambiente. Um exemplo &#233; usar uma API <code>get_time()</code> para obter a hora atual, que n&#227;o est&#225; inclu&#237;da no conhecimento param&#233;trico do LLM aprendido durante o treinamento.</p></li><li><p><strong>A&#231;&#227;o:</strong> <em>Tools</em> de a&#231;&#227;o podem exercer a&#231;&#245;es sobre o ambiente e mudar seu estado. Por exemplo, <code>turn_left()</code> pode mudar a dire&#231;&#227;o de um agente incorporado, ou executar <code>make_post(website, post)</code> pode mudar o conte&#250;do em um site.</p></li><li><p><strong>Computa&#231;&#227;o:</strong> <em>Tools</em> de computa&#231;&#227;o n&#227;o necessariamente percebem ou modificam o ambiente externo, mas usam programas para lidar com tarefas computacionais complexas. Por exemplo, uma calculadora &#233; uma tool de computa&#231;&#227;o para c&#225;lculo matem&#225;tico. Note que a computa&#231;&#227;o tamb&#233;m inclui atos mais gerais de computa&#231;&#227;o al&#233;m do c&#225;lculo num&#233;rico. Portanto, um tradutor tamb&#233;m &#233; uma tool de computa&#231;&#227;o que pode ser usada para traduzir entre idiomas.</p></li></ul><p>Note que muitas tools podem se encaixar em m&#250;ltiplas categorias. Por exemplo, um motor de busca &#233; uma tool que pode realizar tanto computa&#231;&#227;o quanto percep&#231;&#227;o. </p><p>Como computa&#231;&#227;o, ele mede a similaridade de documentos e seleciona os relevantes, mas tamb&#233;m percebe o ambiente (ou seja, a web) e busca dados (ou seja, documentos retornados) dele. </p><p>Da mesma forma, consultas SQL podem ser usadas como tools de computa&#231;&#227;o (por exemplo, <code>SELECT SQRT(16) / 10 AS result</code>), tools de percep&#231;&#227;o para visualizar dados (por exemplo, <code>SELECT name FROM data</code>), tools de a&#231;&#227;o para modificar dados (por exemplo, <code>INSERT INTO data VALUES name</code>), ou todas as acima.</p><h3>Tools e Agentes</h3><p>Recentemente, houve um crescimento de trabalhos sobre agentes alimentados por LLMs. <a href="https://www.google.com.br/books/edition/Artificial_Intelligence/8jZBksh-bUMC?hl=pt-BR&amp;gbpv=0&amp;bsq=Artificial%20intelligence%20a%20modern%20approach.">Russell &amp; Norvig (2010)</a> definem agentes como "qualquer coisa que pode ser vista como percebendo seu ambiente atrav&#233;s de sensores e atuando sobre esse ambiente atrav&#233;s de atuadores." </p><p>De acordo com essa defini&#231;&#227;o, agentes s&#227;o programas que usam tools de percep&#231;&#227;o para perceber o ambiente situado, ou tools de a&#231;&#227;o para interagir com o ambiente. Modelos que usam apenas tools de computa&#231;&#227;o e n&#227;o interagem com seus ambientes atrav&#233;s de tools de percep&#231;&#227;o ou a&#231;&#227;o n&#227;o se enquadram na categoria de "agentes" de acordo com esta defini&#231;&#227;o.</p><h3>Quando tools s&#227;o &#250;teis?</h3><p>Embora seja dif&#237;cil enumerar exaustivamente cada cen&#225;rio onde tools poderiam ser &#250;teis, resumimos algumas categorias principais do uso de tools abaixo. Note que uma tool pode se encaixar em uma ou mais categorias.</p><ul><li><p>Acesso ao conhecimento: LLMs armazenam conhecimento limitado durante o treinamento devido a limites em (i) os dados nos quais s&#227;o treinados e (ii) a capacidade dos LLMs de memorizar e utilizar todos os dados que veem no momento do treinamento. V&#225;rias tools podem ser usadas para aliviar essa quest&#227;o. Executores de SQL e SPARL podem fornecer acesso a dados em bases de conhecimento estruturadas. Uma tool de busca na Internet pode permitir que LLMs acessem informa&#231;&#245;es mais atualizadas. </p></li><li><p>Atividades de computa&#231;&#227;o: Atividades computacionais complexas, como c&#225;lculos matem&#225;ticos, s&#227;o conhecidas por serem desafiadoras para LLMs. Enquanto at&#233; uma calculadora pode melhorar as habilidades num&#233;ricas de um LLM, programas Python mais gen&#233;ricos tamb&#233;m podem ser empregados para auxiliar tarefas de racioc&#237;nio. Para trabalhos profissionais mais complexos, tools podem tamb&#233;m ser aplicadas, como usar worksheet para manipular Google Sheets, ou at&#233; mesmo tools para dom&#237;nios financeiros, m&#233;dicos, educacionais ou de publicidade.</p></li><li><p>Intera&#231;&#227;o com o mundo: LLMs sem tools s&#227;o fundamentalmente incapazes de perceber e agir no mundo ao seu redor, necessitando do uso de tools onde tal percep&#231;&#227;o e a&#231;&#227;o sejam necess&#225;rias. Por exemplo, LLMs podem acessar informa&#231;&#245;es em tempo real como o clima ou conhecimento posicional como localiza&#231;&#227;o. Por outro lado, LLMs podem manipular informa&#231;&#245;es do mundo real como gerenciar calend&#225;rios e e-mails. Al&#233;m de atividades baseadas na web, LLMs podem se engajar em atividades f&#237;sicas, como pescar com varas ou minerar com machados no mundo do Minecraft.</p></li><li><p>Acessando LLMs especializados: Alguns trabalhos prop&#245;em usar LLMs especializados como tools, essencialmente usando o LLM principal como um planejador de tarefas para despachar solicita&#231;&#245;es para outros LLMs. Alguns pesquisadores usaram modelos de tradu&#231;&#227;o autom&#225;tica para auxiliar tarefas multil&#237;ngues. Al&#233;m de tarefas espec&#237;ficas, alguns trabalhos adotam m&#250;ltiplos modelos neurais de plataformas como Hugginface ou similares (Patil et al., 2023; Shen et al., 2023a), ou os ajustam ainda mais em v&#225;rios dados (Viswanathan et al., 2023). Comparado ao LLM base, esses modelos com tools desenvolvem habilidades especializadas, podendo ter diferen&#231;as arquitet&#244;nicas substanciais dos LLMs base.</p></li></ul><h2>Conclus&#227;o </h2><p>As tools s&#227;o interfaces para programas que operam externamente ao LLM, desenhadas para estender suas capacidades al&#233;m da gera&#231;&#227;o de texto. </p><p>Essas tools variam de programas simples, como calculadoras, a sistemas complexos de busca e executores de c&#243;digo, permitindo aos LLMs acessar informa&#231;&#245;es atualizadas, realizar c&#225;lculos complexos e interagir com o ambiente de maneiras significativas. </p><p>Essa externaliza&#231;&#227;o de tarefas para tools especializadas permite que os LMs superem limita&#231;&#245;es inerentes ao seu treinamento e armazenamento de conhecimento, oferecendo uma abordagem mais din&#226;mica e adapt&#225;vel &#224; resolu&#231;&#227;o de problemas. </p><p>Portanto, o uso de tools por LMs n&#227;o s&#243; amplia o escopo de suas aplica&#231;&#245;es, mas tamb&#233;m melhora a qualidade e a relev&#226;ncia das respostas fornecidas aos usu&#225;rios, marcando um avan&#231;o significativo na intera&#231;&#227;o humano-m&#225;quina e na intelig&#234;ncia artificial aplicada.</p>]]></content:encoded></item><item><title><![CDATA[Diversificando a Seleção de Chunks usando Query Expansion]]></title><description><![CDATA[Como LLMs podem ser utilizados para expandir consultas em sistemas de recupera&#231;&#227;o, melhorando a precis&#227;o e o alcance das buscas dos usu&#225;rios.]]></description><link>https://ml4se.substack.com/p/expansao-de-consultas-com-llms</link><guid isPermaLink="false">https://ml4se.substack.com/p/expansao-de-consultas-com-llms</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Fri, 22 Mar 2024 21:08:52 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/8f00dd1a-466e-4593-90bf-c55b76b266f6_1024x1024.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a href="https://www.linkedin.com/in/ghlp/">Me siga no LinkedIn</a> | <a href="/__u/ml4se.substack.com/about#%C2%A7considere-apoiar-a-newsletter">Apoie a Newsletter</a> | <a href="https://gustavopinto.gumroad.com/l/chat-llm">Curso: Converse com seus documentos</a></p><div><hr></div><p>Query Expansion (QE)&nbsp;&#233; uma t&#233;cnica utilizada em sistemas de Information Retrieval (IR) que ajuda a melhorar a capacidade do sistema de recuperar todos os documentos relevantes para uma determinada consulta. A QE adiciona termos adicionais &#224; consulta original, ajudando a recuperar documentos relevantes que n&#227;o tinham palavras em comum (sobreposi&#231;&#227;o lexical) com a consulta original.<br><br><a href="https://arxiv.org/pdf/2305.03653.pdf">Neste artigo</a>, os autores prop&#245;e o uso de LLMs para auxiliar na expans&#227;o de consultas. Por exemplo, dado uma consulta, podemos pedir para o LLM gere uma variedade de termos alternativos. Dessa forma, em vez de fazer uma &#250;nica busca com o input do usu&#225;rio, podemos fazer v&#225;rias buscas, com os termos fornecidos pela LLM; e assim ser capaz de encontrar documentos que poderiam n&#227;o ser identificados pela consulta original.<br><br>Hoje, usar QE tem se tornado uma etapa comum no pipeline de sistemas baseados em LLMs. Nesse texto, vamos revisitar a &#225;rea de recupera&#231;&#227;o e informa&#231;&#227;o para explicar como funciona uma query expansion.</p><div><hr></div><p>&#128218; Voc&#234; &#233; dev e quer aprender um pouco mais sobre a cria&#231;&#227;o de aplica&#231;&#245;es baseadas em LLM?<br><br>Eu criei um curso que aborda aspectos te&#243;ricos e pr&#225;ticos do desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. Alguns dos t&#243;picos cobertos:<br><br>&#128992; O que s&#227;o e como criar embeddings<br>&#128993; Como selecionar partes relevantes nos seus documentos<br>&#128309; Como integrar essas partes documentos com uma LLM</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://gustavopinto.gumroad.com/l/chat-llm&quot;,&quot;text&quot;:&quot;Achou legal? Clica aqui!&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://gustavopinto.gumroad.com/l/chat-llm"><span>Achou legal? Clica aqui!</span></a></p><div><hr></div><h2>Information Retrieval</h2><p>A recupera&#231;&#227;o de informa&#231;&#227;o (IR, do ingl&#234;s "Information Retrieval") visa localizar documentos relevantes de um vasto corpus, com base em uma consulta realizada pelo usu&#225;rio. Esse processo &#233; um componente essencial nos motores de busca modernos, e pesquisadores t&#234;m investido nesse campo por d&#233;cadas. </p><p>Existem dois paradigmas principais para a IR: </p><ul><li><p>A recupera&#231;&#227;o esparsa baseada em l&#233;xico, como o BM25, e</p></li><li><p>A recupera&#231;&#227;o densa <a href="/__u/ml4se.substack.com/p/buscando-itens-de-dado-semelhantes">baseada em embeddings</a>.</p></li></ul><h4>Busca Lexica</h4><p>A recupera&#231;&#227;o esparsa baseada em l&#233;xico, exemplificada pelo algoritmo BM25, &#233; um m&#233;todo tradicional que avalia a relev&#226;ncia de documentos com base na presen&#231;a e frequ&#234;ncia de palavras-chave da consulta do usu&#225;rio nos documentos. </p><p>Esse m&#233;todo considera a import&#226;ncia das palavras dentro dos documentos e em todo o corpus, permitindo identificar documentos relevantes atrav&#233;s da an&#225;lise de termos espec&#237;ficos.</p><h4>Busca Densa</h4><p>Por outro lado, a recupera&#231;&#227;o densa baseada em embeddings representa documentos e consultas como vetores em um espa&#231;o cont&#237;nuo, utilizando t&#233;cnicas de aprendizado profundo para capturar o significado sem&#226;ntico das palavras e frases. </p><p>Essa abordagem permite uma compara&#231;&#227;o mais sofisticada entre consultas e documentos, identificando relev&#226;ncias mesmo quando as palavras-chave exatas n&#227;o est&#227;o presentes, gra&#231;as &#224; capacidade de captar nuances sem&#226;nticas e contextuais. </p><h4>Busca Lexica ou Densa?</h4><p>Ambas as abordagens t&#234;m seus m&#233;ritos e s&#227;o empregadas dependendo das necessidades espec&#237;ficas do sistema de busca. </p><p>A busca l&#233;xica &#233; not&#225;vel pela sua simplicidade e efic&#225;cia em situa&#231;&#245;es onde a correspond&#234;ncia exata de termos &#233; crucial, enquanto a recupera&#231;&#227;o baseada em embeddings &#233; interessante pela sua capacidade de entender e conectar conceitos sem&#226;nticos mais amplos, promovendo uma busca mais intuitiva e flex&#237;vel. </p><h3>Query Expansion Tradicional</h3><p>A Query Expansion &#233; uma t&#233;cnica consolidada, <a href="https://cir.nii.ac.jp/crid/1570291225586316544">proposta inicialmente por Rocchio em 1971</a>, que visa melhorar os sistemas de busca ao reescrever a consulta original do usu&#225;rio. </p><p>Essa reescrita &#233; realizada com base em feedback de pseudo-relev&#226;ncia ou em fontes de conhecimento externas, como o WordNet. Tal abordagem &#233; particularmente &#250;til para a busca densa, ajudando a superar o desafio do &#8220;gap&#8221; lexical entre a consulta e os documentos.</p><p>Ao adicionar termos adicionais &#224; consulta original, a consulta expandida tende a ampliar significativamente a capacidade de recuperar documentos relevantes que, de outra forma, n&#227;o teriam sobreposi&#231;&#227;o lexical com a consulta inicial. </p><p>Este m&#233;todo &#233; amplamente estudado e reconhecido por sua capacidade de expandir os termos de consulta para novos termos que expressam o mesmo conceito ou necessidade de informa&#231;&#227;o, aumentando assim a probabilidade de correspond&#234;ncia lexical com documentos no corpus.</p><h3>Query Expansion Baseada em LLM</h3><p>Recentemente, o uso de Query Expansion foi enriquecida com o uso de LLMs. Atrav&#233;s dos LLMs,  &#233; poss&#237;vel gerar m&#250;ltiplas consultas a partir de uma &#250;nica pergunta. Essas consultas podem ser executadas em paralelo, e os resultados obtidos s&#227;o agregados para fornecer uma resposta mais abrangente. </p><p>Essa estrat&#233;gia &#233; especialmente &#250;til para quest&#245;es complexas que podem ser decompostas em m&#250;ltiplas subquest&#245;es. </p><p>Por exemplo, a pergunta &#8220;Qual &#233; o maior artilheiro da copa do mundo FIFA de futebol?&#8221; poderia ser expandida para as seguintes perguntas: </p><ul><li><p>&#8220;Quem det&#233;m o recorde de mais gols marcados em uma &#250;nica edi&#231;&#227;o da Copa do Mundo FIFA de Futebol?&#8221;</p></li><li><p>&#8220;Qual jogador tem o maior n&#250;mero de gols na hist&#243;ria das Eliminat&#243;rias da Copa do Mundo FIFA?&#8221;</p></li><li><p>&#8220;Quem lidera a lista de artilheiros de todos os tempos da sele&#231;&#227;o nacional em Copas do Mundo FIFA?&#8221;</p></li></ul><p>Essa abordagem permite melhorar o recall ao adicionar termos relacionados &#224; consulta original, aumentando assim a abrang&#234;ncia da busca e a chance de recuperar documentos relevantes que poderiam ser perdidos devido a varia&#231;&#245;es lingu&#237;sticas ou sin&#244;nimos n&#227;o presentes na consulta inicial. </p><p>Ao incorporar palavras e frases que expressam o mesmo conceito ou est&#227;o semanticamente relacionadas, a busca se torna mais inclusiva, capturando uma gama mais ampla de documentos que satisfazem a necessidade de informa&#231;&#227;o do usu&#225;rio. </p><h2>Conclus&#227;o</h2><p>A Query Expansion (QE) introduz uma abordagem sofisticada e adapt&#225;vel para melhorar a precis&#227;o e o alcance das buscas realizadas pelos usu&#225;rios. </p><p>Este artigo explorou a interse&#231;&#227;o entre t&#233;cnicas tradicionais de QE e as capacidades avan&#231;adas proporcionadas por LLMs, demonstrando como essa combina&#231;&#227;o pode superar limita&#231;&#245;es anteriores e abrir novos caminhos para a recupera&#231;&#227;o eficaz de informa&#231;&#227;o. </p><p>Ao empregar LLMs na gera&#231;&#227;o de consultas expandidas, os sistemas de IR podem agora abordar consultas complexas e amb&#237;guas com uma precis&#227;o sem precedentes, adaptando-se melhor &#224;s inten&#231;&#245;es dos usu&#225;rios e ao contexto sem&#226;ntico das suas buscas. </p>]]></content:encoded></item><item><title><![CDATA[Reranking: Potencializando o Desempenho do RAG]]></title><description><![CDATA[Estrat&#233;gias para otimizar a performance do RAG.]]></description><link>https://ml4se.substack.com/p/reranking-potencializando-o-desempenho</link><guid isPermaLink="false">https://ml4se.substack.com/p/reranking-potencializando-o-desempenho</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Wed, 13 Mar 2024 21:00:17 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/e4b2e51c-16ba-4441-9ce4-62112d34e0fa_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Em aplica&#231;&#245;es baseadas em LLMs, comumente usa-se <a href="/__u/ml4se.substack.com/p/arquitetura-de-uma-solucao-baseada">a estrat&#233;gia do RAG</a> para realizar buscas sem&#226;nticas em grandes conjuntos de documentos de texto, transformando-os em vetores para an&#225;lise de similaridade. </p><p>No entanto, devido &#224; compress&#227;o de informa&#231;&#245;es em vetores, <a href="/__u/ml4se.substack.com/p/desvantagens-do-rag">o RAG pode recuperar documentos pouco relevantes</a>, comprometendo a efic&#225;cia da busca.</p><p>Como forma de amenizar esse problema, algumas arquiteturas prop&#245;em a implementa&#231;&#227;o de uma etapa extra no desenho de sistemas baseados em LLM &#8212; um sistema de reranking, onde os documentos recuperados inicialmente s&#227;o posteriormente reordenados de acordo com a sua relev&#226;ncia em rela&#231;&#227;o &#224; consulta. </p><p>Essa abordagem maximiza a efic&#225;cia da recupera&#231;&#227;o, garantindo que os documentos mais relevantes sejam apresentados ao usu&#225;rio, melhorando assim a precis&#227;o e relev&#226;ncia das respostas fornecidas pelo RAG. </p><p>Ao minimizar a quantidade de documentos irrelevantes passados para o modelo de linguagem, a qualidade das respostas geradas &#233; significativamente aprimorada, mitigando o problema inicial de retorno de informa&#231;&#245;es pouco relevantes.</p><div><hr></div><p>&#128218; Voc&#234; &#233; dev e quer aprender um pouco mais sobre a cria&#231;&#227;o de aplica&#231;&#245;es baseadas em LLM?<br><br>Eu criei um curso que aborda aspectos te&#243;ricos e pr&#225;ticos do desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. Alguns dos t&#243;picos cobertos:<br><br>&#128992; O que s&#227;o e como criar embeddings<br>&#128993; Como selecionar partes relevantes nos seus documentos<br>&#128309; Como integrar essas partes documentos com uma LLM</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://gustavopinto.gumroad.com/l/chat-llm&quot;,&quot;text&quot;:&quot;Achou legal? Clica aqui!&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://gustavopinto.gumroad.com/l/chat-llm"><span>Achou legal? Clica aqui!</span></a></p><div><hr></div><h2>Limita&#231;&#245;es da busca sem&#226;ntica</h2><p>Com o RAG, estamos realizando <a href="/__u/ml4se.substack.com/p/buscando-itens-de-dado-semelhantes">uma busca sem&#226;ntica</a> em muitos documentos de texto &#8212; estes podem ser de dezenas de milhares at&#233; dezenas de bilh&#245;es de documentos.</p><p>Para garantir tempos de busca r&#225;pidos em escala, geralmente usamos <a href="/__u/ml4se.substack.com/p/o-que-e-uma-vector-database">busca vetorial</a> &#8212; ou seja, transformamos nosso texto em vetores, inserimos estes em um espa&#231;o vetorial e comparamos sua proximidade com um vetor de consulta usando uma m&#233;trica de similaridade, como a similaridade cosseno.</p><p>Para que a busca vetorial funcione, precisamos de vetores. </p><p>Esses vetores s&#227;o essencialmente compress&#245;es do &#8220;significado&#8221; por tr&#225;s de algum texto em vetores (tipicamente) de 768 ou 1536 dimens&#245;es. H&#225; alguma perda de informa&#231;&#227;o porque estamos comprimindo essa informa&#231;&#227;o em um &#250;nico vetor.</p><p>Devido a essa perda de informa&#231;&#227;o, frequentemente observamos que os principais documentos da busca vetorial n&#227;o s&#227;o necessariamente os mais relevantes. </p><p>Agora imagine, por exemplo, que algum documento em uma posi&#231;&#227;o inferior (l&#225; pelo 20o ou 25o) poderia ajudar nossa LLM a formular melhores respostas. O que fazer? </p><h2>Limite da Janela de Contexto</h2><p>Uma solu&#231;&#227;o mais simples seria aumentar o n&#250;mero de documentos que estamos retornando (ou seja, aumentar o <code>top_k</code>) e passar todos esses documentos para a LLM.</p><p>No entanto, n&#227;o podemos passar todos os documentos para nossa LLM. Primeiro pois as LLMs t&#234;m limites sobre quanto texto podemos passar para eles &#8212; chamamos esse limite de janela de contexto. </p><p>Mas, calma ai. Sabemos que algumas LLMs t&#234;m janelas de contexto enormes, como o Claude da Anthropic, com uma janela de contexto de 100K tokens, n&#227;o &#233; verdade?</p><p>Com isso, n&#227;o poder&#237;amos incluir muitas centenas de documentos at&#233; &#8220;preencher&#8221; a toda a capacidade da janela de contexto para melhorar a recupera&#231;&#227;o?</p><p>Novamente, n&#227;o podemos usar preenchimento de contexto porque isso reduz o desempenho de recupera&#231;&#227;o do LLM, como evidenciado <a href="https://direct.mit.edu/tacl/article/doi/10.1162/tacl_a_00638/119630">neste estudo cient&#237;fico</a>, que percebeu que a qualidade da resposta da LLM degrada &#224; medida que adicionamos mais tokens &#224; janela de contexto.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="/__u/substackcdn.com/image/fetch/$s_!vkIH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fe99f6b-cb7a-4ca6-92dc-ed15f9a96362_902x872.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="/__u/substackcdn.com/image/fetch/$s_!vkIH!, /__u/ml4se.substack.com/w_424, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fe99f6b-cb7a-4ca6-92dc-ed15f9a96362_902x872.png 424w, /__u/substackcdn.com/image/fetch/$s_!vkIH!, /__u/ml4se.substack.com/w_848, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fe99f6b-cb7a-4ca6-92dc-ed15f9a96362_902x872.png 848w, /__u/substackcdn.com/image/fetch/$s_!vkIH!, /__u/ml4se.substack.com/w_1272, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fe99f6b-cb7a-4ca6-92dc-ed15f9a96362_902x872.png 1272w, /__u/substackcdn.com/image/fetch/$s_!vkIH!, /__u/ml4se.substack.com/w_1456, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_webp, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fe99f6b-cb7a-4ca6-92dc-ed15f9a96362_902x872.png 1456w" sizes="100vw"><img src="/__u/substackcdn.com/image/fetch/$s_!vkIH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fe99f6b-cb7a-4ca6-92dc-ed15f9a96362_902x872.png" width="480" height="464.0354767184036" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7fe99f6b-cb7a-4ca6-92dc-ed15f9a96362_902x872.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:872,&quot;width&quot;:902,&quot;resizeWidth&quot;:480,&quot;bytes&quot;:133662,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="/__u/substackcdn.com/image/fetch/$s_!vkIH!, /__u/ml4se.substack.com/w_424, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fe99f6b-cb7a-4ca6-92dc-ed15f9a96362_902x872.png 424w, /__u/substackcdn.com/image/fetch/$s_!vkIH!, /__u/ml4se.substack.com/w_848, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fe99f6b-cb7a-4ca6-92dc-ed15f9a96362_902x872.png 848w, /__u/substackcdn.com/image/fetch/$s_!vkIH!, /__u/ml4se.substack.com/w_1272, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fe99f6b-cb7a-4ca6-92dc-ed15f9a96362_902x872.png 1272w, /__u/substackcdn.com/image/fetch/$s_!vkIH!, /__u/ml4se.substack.com/w_1456, /__u/ml4se.substack.com/c_limit, /__u/ml4se.substack.com/f_auto, /__u/ml4se.substack.com/q_auto:good, /__u/ml4se.substack.com/fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fe99f6b-cb7a-4ca6-92dc-ed15f9a96362_902x872.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Como podemos observar na imagem acima, a medida que aumentamos a quantidade de documentos que passamos para uma LLM, a capacidade de uma LLM de responder apropriadamente uma pergunta torna-se pior do que se o documento n&#227;o tivesse sido fornecido em primeiro lugar.</p><p> Os LLMs tamb&#233;m s&#227;o menos propensos a seguir instru&#231;&#245;es &#224; medida que preenchemos a janela de contexto &#8212; portanto, o preenchimento de contexto &#233; uma m&#225; ideia.</p><blockquote><p>Podemos aumentar o n&#250;mero de documentos retornados por nosso banco de dados vetorial para aumentar a recupera&#231;&#227;o da recupera&#231;&#227;o, mas n&#227;o podemos passar esses documentos para nosso LLM sem prejudicar a recupera&#231;&#227;o do LLM.</p></blockquote><h2>ReRanking de documentos</h2><p>Uma solu&#231;&#227;o proposta para esse problema &#233; maximizar a recupera&#231;&#227;o da recupera&#231;&#227;o, recuperando muitos documentos, e depois maximizar a recupera&#231;&#227;o do LLM minimizando o n&#250;mero de documentos que chegam ao LLM. </p><p>Para fazer isso, repriorizamos os documentos recuperados e mantemos apenas os mais relevantes para nosso LLM &#8212; para fazer isso, usamos um ReRanking.</p><p>Um modelo de ReRanking &#8212; tamb&#233;m conhecido como um cross-encoder &#8212; &#233; um tipo de modelo que, dado um par de consulta e documento, emitir&#225; uma pontua&#231;&#227;o de similaridade. Usamos essa pontua&#231;&#227;o para reorganizar os documentos por relev&#226;ncia para nossa consulta.</p><h3>Recupera&#231;&#227;o em dois est&#225;gios</h3><p>Engenheiros de busca t&#234;m usado rerankers em sistemas de recupera&#231;&#227;o em dois est&#225;gios por muito tempo. Nestes sistemas s&#227;o desenhados com dois est&#225;gios:</p><ul><li><p>Primeiro, um modelo de incorpora&#231;&#227;o/retriever recupera um conjunto de documentos relevantes de um conjunto de dados maior. </p></li><li><p>Segundo, um modelo de prioriza&#231;&#227;o (o reranker) &#233; usado para reorganizar esses documentos recuperados pelo modelo de primeiro est&#225;gio.</p></li></ul><p>Usamos dois est&#225;gios porque recuperar um pequeno conjunto de documentos de um grande conjunto de dados &#233; muito mais r&#225;pido do que usar um ReRanker em um grande conjunto de documentos; RerRnkers s&#227;o lentos e retreivers s&#227;o r&#225;pidos.</p><p>Mas se um reranker &#233; muito mais lento, por que se preocupar em us&#225;-los? A resposta &#233; que rerankers s&#227;o muito mais precisos do que modelos de incorpora&#231;&#227;o.</p><h2>Busca sem&#226;ntica ou ReRanker?</h2><p>A intui&#231;&#227;o por tr&#225;s de uma busca sem&#226;ntica (ou bi-encoder) &#233; que para realizar essas buscas, precisamos antes comprimir todos os documento em vetores, que &#233; um processo <em>lossy,</em> o que significa que perdemos informa&#231;&#227;o.</p><p>Por outro lado, um ReRanker pode receber as informa&#231;&#245;es brutas diretamente, significando menos perda de informa&#231;&#227;o. Como executamos o ReRanker no momento da consulta do usu&#225;rio, temos o benef&#237;cio adicional de analisar o significado de nosso documento espec&#237;fico para a consulta do usu&#225;rio &#8212; em vez de tentar produzir um significado gen&#233;rico m&#233;dio.</p><h2>Implementando um ReRank</h2><p>H&#225; diversas t&#233;cnicas para cria&#231;&#227;o de ReRankers. </p><p>Nesse texto vamos usar a biblioteca <a href="https://github.com/PrithivirajDamodaran/FlashRank">FlashRank</a>, que &#233; relativamente madura e possui integra&#231;&#227;o com o LangChain. </p><p>Para instalar, basta um</p><pre><code>pip install flashrank</code></pre><p>Em seguida, basta criar o objeto <code>Ranker</code>.</p><pre><code>from flashrank import Ranker, RerankRequest
ranker = Ranker()</code></pre><p>Por fim, basta passar a query junto com os documentos selecionados. Estes documentos devem vir de uma busca sem&#226;ntica, mas, por simplicidade, vou defini-los diretamente no c&#243;digo:</p><pre><code>query = "Como acelerar LLMs?"
passages = [
   {
      "id": 1,
      "text": "Introduza *lookahead decoding*: - um algoritmo de decodifica&#231;&#227;o paralela para acelerar a infer&#234;ncia do LLM - sem a necessidade de um modelo preliminar ou armazenamento de dados - diminui linearmente o n&#250;mero de etapas de decodifica&#231;&#227;o em rela&#231;&#227;o ao log(FLOPs) utilizado por etapa de decodifica&#231;&#227;o.",
      "meta": {"additional": "info1"}
   },
   {
      "id": 2,
      "text": "A efici&#234;ncia da infer&#234;ncia do LLM ser&#225; um dos t&#243;picos mais cruciais tanto para a ind&#250;stria quanto para a academia, simplesmente porque quanto mais eficiente voc&#234; for, mais dinheiro economizar&#225;. O projeto vLLM &#233; uma leitura obrigat&#243;ria para esta dire&#231;&#227;o, e agora eles acabaram de lan&#231;ar o artigo.",
      "meta": {"additional": "info2"}
   },
   {
      "id": 3,
      "text": "Existem muitas maneiras de aumentar a taxa de transfer&#234;ncia da infer&#234;ncia do LLM (tokens/segundo) e diminuir a pegada de mem&#243;ria, &#224;s vezes ao mesmo tempo. Aqui est&#227;o alguns m&#233;todos que descobri serem eficazes ao trabalhar com o Llama 2. Esses m&#233;todos s&#227;o todos bem integrados com a Hugging Face. Esta lista est&#225; longe de ser exaustiva; alguns desses m&#233;todos podem ser usados em combina&#231;&#227;o entre si e h&#225; muitos outros para experimentar. - Bettertransformer (Biblioteca &#211;tima): Basta chamar `model.to_bettertransformer()` no seu modelo Hugging Face para uma melhoria modesta em tokens por segundo. - Fp4 Mixed-Precision (Bitsandbytes): Requer configura&#231;&#227;o m&#237;nima e reduz drasticamente a pegada de mem&#243;ria do modelo. - AutoGPTQ: Demorado, mas leva a um modelo muito menor e infer&#234;ncia mais r&#225;pida. A quantiza&#231;&#227;o &#233; um custo &#250;nico que se paga a longo prazo.",
      "meta": {"additional": "info3"}
   },
   {
      "id": 4,
      "text": "J&#225; quis fazer sua infer&#234;ncia do LLM ir brrrrr, mas ficou preso na implementa&#231;&#227;o da decodifica&#231;&#227;o especulativa e na busca pelo modelo preliminar adequado? N&#227;o mais dor! Empolgado em apresentar Medusa, um framework simples que remove o irritante modelo preliminar enquanto obt&#233;m um aumento de velocidade de 2x.",
      "meta": {"additional": "info4"}
   },
   {
      "id": 5,
      "text": "vLLM &#233; uma biblioteca r&#225;pida e f&#225;cil de usar para infer&#234;ncia e atendimento do LLM. vLLM &#233; r&#225;pido com: Taxa de atendimento de &#250;ltima gera&#231;&#227;o. Gerenciamento eficiente da mem&#243;ria de chave e valor de aten&#231;&#227;o com PagedAttention. Agrupamento cont&#237;nuo de solicita&#231;&#245;es recebidas. Kernels CUDA otimizados.",
      "meta": {"additional": "info5"}
   }
]</code></pre><p>Nesse exemplo, os metadados s&#227;o opcionais. O ID pode ser o ID do seu banco de dados da etapa de recupera&#231;&#227;o.</p><p>Por fim, basta passar esses valores para os objetos <code>RerankRequest</code> e <code>Ranker</code>.</p><pre><code>rerankrequest = RerankRequest(query=query, passages=passages)
results = ranker.rerank(rerankrequest)
print(results)</code></pre><h2>Conclus&#227;o</h2><p>O reranking &#233; um dos m&#233;todos mais simples que ajuda a melhorar o desempenho de recupera&#231;&#227;o no modelo do RAG.</p><p>Nesse texto, exploramos por que os rerankers podem oferecer um desempenho muito superior aos seus equivalentes de modelo de incorpora&#231;&#227;o &#8212; e como um sistema de recupera&#231;&#227;o em dois est&#225;gios nos permite obter o melhor dos dois mundos, possibilitando a busca em grande escala enquanto mantemos um desempenho de qualidade.</p>]]></content:encoded></item><item><title><![CDATA[Entendendo a Chain do LangChain]]></title><description><![CDATA[Conecte a&#231;&#245;es atrav&#233;s das chains]]></description><link>https://ml4se.substack.com/p/entendendo-a-chain-do-langchain</link><guid isPermaLink="false">https://ml4se.substack.com/p/entendendo-a-chain-do-langchain</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Sun, 10 Mar 2024 21:11:16 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/9b8e5a65-508d-463a-b301-2c09540c9dd3_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a href="https://www.linkedin.com/in/ghlp/">Me siga no LinkedIn</a> | <a href="/__u/ml4se.substack.com/about#%C2%A7considere-apoiar-a-newsletter">Apoie a Newsletter</a> | <a href="https://gustavopinto.gumroad.com/l/chat-llm">Curso: Converse com seus documentos</a></p><div><hr></div><p>No centro do LangChain est&#225; um componente conhecido como <code>Chain</code>, que cria a conex&#227;o central entre um ou v&#225;rios grandes modelos de linguagem.</p><p>De maneira simplificada uma chain ajuda a pegar a sa&#237;da de uma chamada &#224; LLM e us&#225;-la como entrada para um pr&#243;ximo passo (que pode inclusive ser uma outra chamada &#224; LLM). </p><p>Imagine esta situa&#231;&#227;o: uma chain &#233; criada para receber a entrada do usu&#225;rio, fazer algum refinamento e, posteriormente, passar essa resposta refinada para um modelo de linguagem. Dessa forma, torna-se poss&#237;vel conectar v&#225;rias intera&#231;&#245;es com a LLM.</p><p>Atrav&#233;s da cria&#231;&#227;o de chains, v&#225;rios elementos podem se unir de maneira transparente. </p><p>Dessa forma, as chains nos proporcionam a capacidade de construir aplicativos complexos, ligando v&#225;rias chains entre si ou incorporando chains com outros elementos do sistema. As chains s&#227;o ponto-chave no desenvolvimento de software baseado em LLMs. </p><p>Vantagens de usar uma Chain.</p><ul><li><p>Ao pegar a sa&#237;da de um LLM e us&#225;-la como entrada para o pr&#243;ximo, torna-se poss&#237;vel realizar v&#225;rias intera&#231;&#245;es com uma LLMs de maneira sequencial.</p></li><li><p>Misturar LLMs com dados externos permite que o sistema responda a consultas de maneira eficaz.</p></li></ul><p>H&#225; diferentes tipos de chains. Nesse texto, vamos passar por algumas das principais.</p><div><hr></div><p>&#128218; Voc&#234; &#233; dev e quer aprender um pouco mais sobre a cria&#231;&#227;o de aplica&#231;&#245;es baseadas em LLM?<br><br>Eu criei um curso que aborda aspectos te&#243;ricos e pr&#225;ticos do desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. Alguns dos t&#243;picos cobertos:<br><br>&#128992; O que s&#227;o e como criar embeddings<br>&#128993; Como selecionar partes relevantes nos seus documentos<br>&#128309; Como integrar essas partes documentos com uma LLM</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://gustavopinto.gumroad.com/l/chat-llm&quot;,&quot;text&quot;:&quot;Achou legal? Clica aqui!&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://gustavopinto.gumroad.com/l/chat-llm"><span>Achou legal? Clica aqui!</span></a></p><div><hr></div><h2>Chain = prompt | model</h2><p>A forma mais b&#225;sica de chain &#233; combinando (ou encadeando) um prompt e um modelo. Na newsletter j&#225; abordagens esse tipo mais b&#225;sico de chain, utilizando o <a href="/__u/ml4se.substack.com/p/langchain-e-lcel-facilitando-a-interacao">LangChain Expression Language</a>. </p><p>Embora seja poss&#237;vel fazer alguns encadeamento de a&#231;&#245;es , nesse tipo de chain ficamos limitados quando queremos, por exemplo, encadear duas ou mais chamadas a LLM.</p><h2>Sequencial Chain</h2><p><strong>Sequential Chain</strong> Uma Sequential Chain &#233; uma chain que combina v&#225;rias chains individuais, onde a sa&#237;da de uma chain serve como entrada para a pr&#243;xima em uma sequ&#234;ncia cont&#237;nua. Ela opera executando uma s&#233;rie de chains consecutivamente.</p><p>Existem dois tipos de Sequential Chains:</p><ul><li><p><strong>SimpleSequentialChain</strong>, que lida com uma &#250;nica entrada e sa&#237;da.</p></li><li><p><strong>SequentialChain</strong>, que gerencia v&#225;rias entradas e sa&#237;das simultaneamente.</p></li></ul><h3><strong>SimpleSequentialChains</strong></h3><p>As SimpleSequentialChains permitem que uma &#250;nica entrada passe por uma s&#233;rie de transforma&#231;&#245;es, resultando em uma sa&#237;da refinada. </p><p>Por exemplo, imagine que voc&#234; quer fazer uma receita de cozinha, mas que gostaria de saber qual &#233; o item mais importante da receita para que voc&#234; possa comprar o melhor material poss&#237;vel no mercado. </p><p>Nesse caso, ter&#237;amos dois prompts: um para criar a receita e outro para identificar o item mais importante da receita. Al&#233;m disso, o segundo prompt deve estar conectado com o primeiro, uma vez que n&#227;o sabemos de antem&#227;o quais s&#227;o os itens da receita. </p><p>Poder&#237;amos implementar essa chain da seguinte forma:</p><pre><code>from langchain_openai import ChatOpenAI
from langchain.chains.sequential import SimpleSequentialChain

model = ChatOpenAI()
# Primeiro prompt
prompt = ChatPromptTemplate.from_template(
    "Crie uma lista de compras para fazer uma receita de: {receita}"
)
chain = LLMChain(llm=model, prompt=prompt)

# Segundo prompt
second_prompt = ChatPromptTemplate.from_template(
    "Dentre dos itens de receita, descreva qual &#233; o mais importante e o motivo: {list}"
)
second_chain = LLMChain(llm=model, prompt=second_prompt)

combined_chain = SimpleSequentialChain(chains=[chain, second_chain], verbose=True)
combined_chain.invoke({"input": "lasanha"})</code></pre><p>Inicialmente, cria-se um prompt solicitando a cria&#231;&#227;o de uma lista de compras para uma receita espec&#237;fica. Uma inst&#226;ncia da classe <code>LLMChain</code> &#233; usada para processar esse prompt, utilizando um modelo predefinido.</p><p>Em seguida, &#233; criado um segundo prompt, pedindo ao usu&#225;rio que destaque o item mais importante da lista de compras e explique sua relev&#226;ncia. Outra inst&#226;ncia da <code>LLMChain</code> &#233; criada para lidar com essa instru&#231;&#227;o. </p><p>Por fim, ambas as chains s&#227;o combinadas em uma <code>SimpleSequentialChain</code>, permitindo a execu&#231;&#227;o sequencial das opera&#231;&#245;es. </p><p>Ao invocar a cadeia combinada com o par&#226;metro <code>"lasanha"</code>, o c&#243;digo faz uma execu&#231;&#227;o sequencia das duas chain, na ordem que foram passadas por par&#226;metro..</p><h3><strong>SequentialChains</strong> </h3><p>Similar a uma <code>SimpleSequencialChain</code>, uma <code>SequentialChain</code> pode combinar v&#225;rias chains usando a sa&#237;da de uma chain como entrada para a pr&#243;xima. No entanto, diferente da <code>SimpleSequencialChain</code>, uma <code>SequentialChain</code> pode executar uma s&#233;rie de chains ao mesmo tempo, e o resultado dessas chains &#233; passado para outras chains. </p><p>Por exemplo, imagine que voc&#234; queria escrever sobre um tema espec&#237;fico da engenharia de software, mas com o estilo de escrita de um not&#225;vel pesquisador da &#225;rea. Dessa forma, podemos criar as seguintes chains:</p><ul><li><p><em>Chain1</em>: Buscar um renomado pesquisador em engenharia de software</p></li><li><p><em>Chain2</em>: Escrever um texto sobre engenharia de software</p></li><li><p><em>Chain3</em>: Identificar a &#225;rea de conhecimento do pesquisador renomado</p></li><li><p><em>Chain4</em>: Reescrever o texto, focando na &#225;rea de conhecimento do pesquisador renomado</p></li></ul><p>Note que as <em>Chains1</em> e <em>Chains2</em> do exemplo a cima s&#227;o independentes uma da outra, logo podem se executadas em paralelo. </p><p>Poder&#237;amos implementar essa chain da seguinte forma:</p><pre><code>from langchain.chains import SequentialChain

first_prompt = ChatPromptTemplate.from_template(
    "Cite o nome de um pesquisador brasileiro que escreve sobre a seguinte &#225;rea do conhecimento:\n\n{topic}"
)
first_chain = LLMChain(llm=model, prompt=first_prompt,
                    output_key="writer"
                    )

second_prompt = ChatPromptTemplate.from_template(
    "Escreva um resumo sobre o que se trata a &#225;rea do conhecimento chamada:\n\n{topic}"
)
second_chain = LLMChain(llm=model, prompt=second_prompt,
                    output_key="summary"
                    )

third_prompt = ChatPromptTemplate.from_template(
    "Descreva em at&#233; cinco palavras a princial &#225;rea de atuacao do pesquisador {writer} na {topic}."
)
third_chain = LLMChain(llm=model, prompt=third_prompt,
                    output_key="research_topic"
                    )

fourth_prompt = ChatPromptTemplate.from_template(
    "Reescreva o seguinte texto, focando na &#225;rea de {software_topic}, no estilo de {writer}:\n\n{summary}"
)
fourth_chain = LLMChain(llm=model, prompt=fourth_prompt,
                    output_key="writer_summary"
                    )


main_chain = SequentialChain(
    chains=[first_chain, second_chain, third_chain, fourth_chain],
    input_variables=["topic"],
    output_variables=["writer", "summary", "research_topic", "writer_summary"],
    verbose=True
)

main_chain.invoke('''engenharia de software''')</code></pre><p>Neste c&#243;digo, o primeiro prompt solicita o nome de um pesquisador brasileiro na &#225;rea indicada, enquanto o segundo pede um resumo sobre essa &#225;rea de conhecimento. </p><p>A terceira intera&#231;&#227;o busca descrever a principal &#225;rea de atua&#231;&#227;o do pesquisador na engenharia de software em at&#233; cinco palavras. </p><p>Por fim, o quarto prompt reescreve um texto focado na &#225;rea espec&#237;fica do software, usando o estilo do pesquisador mencionado. </p><p>Perceba, no entanto, que as chains <code>first_chain</code> e <code>second_chain</code>  s&#227;o executadas de maneira independente, mas seu resultado &#233; combinado e utilizado na  <code>fourth_chain.</code></p><h2>Outras Chains</h2><p>O LangChain oferece suporte para diversos <a href="https://python.langchain.com/docs/modules/chains">outros tipos de chain</a>. Citamos alguns exemplos a seguir.</p><h3><strong>RouterChains</strong></h3><p>A <code>RouterChain</code> &#233; utilizada para tarefas ligeiramente mais complicadas. Por exemplo, quando temos m&#250;ltiplas chains, cada uma especializada em um tipo espec&#237;fico de input, podemos ter uma router chain que decide para qual chain enviar o input.</p><p>Imagine, por exemplo, que voc&#234; &#233; um estudante do ENEM, e precisa de um servi&#231;o de pergunta e respostas especializado em f&#237;sica, matem&#225;tica e hist&#243;ria. </p><p>Nesse servi&#231;o, dado uma pergunta do usu&#225;rio sobre uma dessas disciplinas, o prompt correto deve ser escolhido e executado.</p><h2>create_sql_query_chain</h2><p>Essa &#233; uma chain que gera consultas SQL, atrav&#233;s da classe <code>SQLDatabase</code>, que fornece um m&#233;todo <code>get_table_info</code> que pode ser usado para obter informa&#231;&#245;es sobre colunas, bem como dados de amostra da tabela.</p><p>Para mitigar o risco de vazamento de dados sens&#237;veis, &#233; importante limitar as permiss&#245;es para leitura e ajuste para as tabelas necess&#225;rias.</p><p>Exemplo: </p><pre><code><code>from langchain_openai import ChatOpenAI
from langchain.chains import create_sql_query_chain
from langchain_community.utilities import SQLDatabase

db = SQLDatabase.from_uri("sqlite:///Chinook.db")
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
chain = create_sql_query_chain(llm, db)
response = chain.invoke({"question": "Quantos empregados existem?"})</code></code></pre><h2>Conclus&#227;o</h2><p>O LangChain, por meio de suas chains, desempenha um papel crucial no desenvolvimento de aplicativos baseados em Large Language Models (LLMs). As chains, como Sequential Chains e Router Chains, permitem a constru&#231;&#227;o de intera&#231;&#245;es sequenciais e decis&#245;es din&#226;micas, proporcionando flexibilidade e efic&#225;cia. </p><p>Ao unir diferentes elementos de maneira transparente, as chains possibilitam a cria&#231;&#227;o de aplicativos complexos. Esse m&#233;todo, exemplificado com receitas de culin&#225;ria e reda&#231;&#227;o acad&#234;mica, demonstra como as chains oferecem uma abordagem vers&#225;til e poderosa para a intera&#231;&#227;o e manipula&#231;&#227;o de dados, ampliando as capacidades do desenvolvimento de software baseado em LLMs.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ml4se.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Inscreva-se&quot;,&quot;language&quot;:&quot;pt-br&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">ML4SE &#233; uma newsletter focada em ajudar devs a mastigar t&#233;cnicas de aprendizado de m&#225;quina. Para receber novos posts, se inscreva na newsletter.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Digite seu e-mail&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Inscreva-se"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p>]]></content:encoded></item><item><title><![CDATA[LangChain e LCEL: Facilitando a Interação com Modelos de Linguagem]]></title><description><![CDATA[Iniciando com LangChain Expression Language]]></description><link>https://ml4se.substack.com/p/langchain-e-lcel-facilitando-a-interacao</link><guid isPermaLink="false">https://ml4se.substack.com/p/langchain-e-lcel-facilitando-a-interacao</guid><dc:creator><![CDATA[Gustavo Pinto]]></dc:creator><pubDate>Mon, 04 Mar 2024 02:26:47 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/f79e0b0a-6143-45ed-94e2-4a156094e654_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a href="https://www.linkedin.com/in/ghlp/">Me siga no LinkedIn</a> | <a href="/__u/ml4se.substack.com/about#&amp;#167;considere-apoiar-a-newsletter">Apoie a Newsletter</a> | <a href="https://gustavopinto.gumroad.com/l/chat-llm">Curso: Converse com seus documentos</a></p><div><hr></div><p>O LangChain &#233; um framework  que apoia no desenvolvimento de aplicativos baseados por modelos de linguagem. O framework simplifica tarefas como adi&#231;&#227;o de contexto nos prompts, ou de <em>reasoning</em> dos modelos de linguagem. </p><p>Uma das formas de interagir com o LangChain &#233; atrav&#233;s da LCEL, LangChain Expression Language. A LCEL &#233; uma abordagem declarativa que simplifica o uso do framework para compor <em>chains</em> (ou cadeias) mais facilmente. </p><p>A LCEL abrange desde as cadeias mais simples, que combinam duas etapas (um prompt e uma LLM), at&#233; cadeias mais complexas, como um pipeline que envolve dezenas ou at&#233; centenas de etapas. Al&#233;m do suporte, como linguagem declarativa, o LCEL &#233; de f&#225;cil uso e entendimento. </p><p>Nesse texto, vamos demonstrar o uso LCEL, criando pequenas cadeias de itera&#231;&#227;o de prompts.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://ml4se.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Inscreva-se&quot;,&quot;language&quot;:&quot;pt-br&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">ML4SE &#233; uma newsletter focada em ajudar devs a mastigar t&#233;cnicas de aprendizado de m&#225;quina. Para receber novos posts, se inscreva na newsletter.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Digite seu e-mail&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Inscreva-se"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3>Comunicando com o modelo</h3><p>Antes de come&#231;ar, precisamos configurar nosso ambiente para trabalhar com LangChain e uma LLM. Para esse texto, utilizaremos a LLM da OpenAI. Logo, precisamos instalar as seguintes depend&#234;ncias:</p><pre><code><code>!pip install langchain openai langchain_openai</code></code></pre><p>Nosso Hello World consiste em realizar uma chamada ao modelo e imprimir o resultado. Para isso, podemos usar a classe <code>ChatOpenAI</code>. </p><pre><code>model = ChatOpenAI(api_key="chave", model="gpt-4", max_tokens=200, temperature=0)</code></pre><p>Perceba que para construi o objeto <code>ChatOpenAI</code> precisamos passar tr&#234;s par&#226;metros: </p><ul><li><p><code>api_key</code>: Chave de acesso ao modelo da OpenAI. Automaticamente inferida da vari&#225;vel de ambiente OPENAI_API_KEY se n&#227;o fornecida.</p></li><li><p><code>model</code>: Escolha do tipo de modelo generativo. O modelo padr&#227;o &#233; o gpt-3.5-turbo.</p></li><li><p><code>max_tokens</code>: Limite m&#225;ximo de tokens para gerar respostas.</p></li><li><p><code>temperature</code>: Define a varia&#231;&#227;o na resposta. Quanto maior, mais diversa ser&#225; a resposta. Se zero, as respostas tendem a ser consistentes em requisi&#231;&#245;es consecutivas com o mesmo prompt.</p></li></ul><p>Com o objeto model criado, &#233; poss&#237;vel realizar chamadas ao modelo.</p><pre><code>model.invoke("oi, meu nome &#233; Gustavo. Tudo bem com voc&#234;?")
=&gt; AIMessage(content='Ol&#225;, Gustavo! Eu sou uma intelig&#234;ncia artificial, ent&#227;o n&#227;o tenho sentimentos, mas estou aqui para ajudar. Como posso ajud&#225;-lo hoje?')</code></pre><p>Note que o retorno &#233; envelopado na classe <code>AIMessage</code>. Caso queria acessar somente a resposta, basta acessar a vari&#225;vel <code>content</code>.</p><p>Importante saber que cada chamada ao modelo &#233; <em>stateless</em>. Ou seja, o modelo n&#227;o guarda o estado das informa&#231;&#245;es que foram passadas previamente. Para observar esse comportamento, basta executar uma nova requisi&#231;&#227;o perguntando sobre algo da requisi&#231;&#227;o anterior:</p><pre><code><code>model.invoke("oi, meu nome &#233; Gustavo. Tudo bem com voc&#234;?")
=&gt; AIMessage(content='Ol&#225;, Gustavo! Eu sou uma intelig&#234;ncia artificial, ent&#227;o n&#227;o tenho sentimentos, mas estou aqui para ajudar. Como posso ajud&#225;-lo hoje?')


model.invoke("Qual &#233; mesmo o meu nome?")
AIMessage(content='Desculpe, como sou uma intelig&#234;ncia artificial, n&#227;o tenho acesso a essa informa&#231;&#227;o.')</code></code></pre><p>Como forma de lidar com essa caracter&#237;stica, o LangChain fornece recursos para uma constru&#231;&#227;o de <a href="https://python.langchain.com/docs/modules/memory/">mem&#243;ria</a>, mas que n&#227;o abordaremos nesse texto.</p><div><hr></div><p>&#128218; Voc&#234; &#233; dev e quer aprender um pouco mais sobre a cria&#231;&#227;o de aplica&#231;&#245;es baseadas em LLM?<br><br>Eu criei um curso que aborda aspectos te&#243;ricos e pr&#225;ticos do desenvolvimento de aplica&#231;&#245;es baseadas em LLMs. Alguns dos t&#243;picos cobertos:<br><br>&#128992; O que s&#227;o e como criar embeddings<br>&#128993; Como selecionar partes relevantes nos seus documentos<br>&#128309; Como integrar essas partes documentos com uma LLM</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://gustavopinto.gumroad.com/l/chat-llm&quot;,&quot;text&quot;:&quot;Achou legal? Clica aqui!&quot;,&quot;action&quot;:null,&quot;class&quot;:&quot;button-wrapper&quot;}" data-component-name="ButtonCreateButton"><a class="button primary button-wrapper" href="https://gustavopinto.gumroad.com/l/chat-llm"><span>Achou legal? Clica aqui!</span></a></p><div><hr></div><h3>Separando o prompt do modelo</h3><p>No exemplo anterior, usamos o m&#233;todo <code>invoke</code> da classe <code>ChatOpenAI</code> para iniciar uma conversa com o modelo. No entanto, h&#225; casos em que gostar&#237;amos de fornecer uma instru&#231;&#227;o pr&#233;via para que o modelo se comporte de acordo com alguma caracter&#237;stica. </p><p>Por exemplo, se estamos construindo um sistema especializado em design de software devemos instruir nosso modelo a se comportar como um expert nessa &#225;rea. Somente ap&#243;s essa instru&#231;&#227;o, podemos solicitar ao modelo uma resposta a pergunta do usu&#225;rio. </p><p>Para isso, devemos criar um prompt com essa caracter&#237;stica. Para criar um prompt no LangChain, podemos usar a classe <code>ChatPromptTemplate</code>. Vejamos no exemplo abaixo:</p><pre><code>from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_template("Voc&#234; deve atuar como um expert em design de software. Ajude nosso usu&#225;rio: {input}")</code></pre><p>Agora que temos a defini&#231;&#227;o do <code>modelo</code> e do <code>prompt</code>, criaremos nossa primeira  cadeia, usando o operador <code>|</code> (pipe):</p><pre><code>chain = prompt | model</code></pre><p>O pipe em comportamento similar ao pipe que utilizamos em sistemas unix, em que uma opera&#231;&#227;o &#233; realizada ap&#243;s a execu&#231;&#227;o da opera&#231;&#227;o anterior. </p><p>Embora n&#227;o seja uma sintaxe muito pythonica, pipe &#233; uma constru&#231;&#227;o de c&#243;digo dispon&#237;vel no LCEL que simplifica muito o encadeamento de opera&#231;&#245;es em LLMs. Debaixo dos panos, quando o interpretador Python encontra o operador <code>|</code> entre dois objetos (como <code>a | b</code>), ele tenta passar o objeto <code>a</code> para o m&#233;todo <code>__or__</code> do objeto <code>b</code>.</p><p>Isso significa que esses padr&#245;es s&#227;o equivalentes:</p><pre><code># padr&#227;o tradicional
chain = a.__or__(b)
chain("some input")

# padr&#227;o com pipe
chain = a | b
chain("some input")</code></pre><p>Ap&#243;s a constru&#231;&#227;o da nossa chain, basta invoca-la usando o m&#233;todo <code>invoke</code>.</p><pre><code><code>chain.invoke({"input": "quando n&#227;o devemos refatorar um c&#243;digo?"})</code></code></pre><p>Perceba que para invocar a chain, precisamos passar um dicion&#225;rio <code>{}</code> como par&#226;metro para o m&#233;todo invoke. Passamos como chave para esse dicion&#225;rio a string <code>"input"</code>, e como valor, passamos a string da pergunta do usu&#225;rio (<code>"quando n&#227;o devemos refatorar um c&#243;digo?")</code>. Perceba que a chave <code>"input"</code> &#233; a mesma que usamos no <code>ChatPromptTemplate.from_template</code>, e o LangChain trata da interpola&#231;&#227;o de strings. O uso de um dicion&#225;rio &#233; necess&#225;rio, uma vez que o prompt pode ter v&#225;rias par&#226;metros (passados pelo usu&#225;rio, ou por outros prompts).</p><h3>Formatando a sa&#237;da</h3><p>Um outro elemento frequentemente empregado na chain, &#233; o analisador de sa&#237;da (output_parser).</p><p>Os analisadores de sa&#237;da s&#227;o respons&#225;veis por pegar a sa&#237;da de um LLM e transform&#225;-la em um formato mais adequado. Isso &#233; muito &#250;til para modificar a forma que os dados est&#227;o estruturados. Alguns dos analisadores de sa&#237;da <a href="https://python.langchain.com/docs/modules/model_io/output_parsers/">implementados pelo framework</a> s&#227;o: </p><ul><li><p>Lista (CommaSeparatedListOutputParser): Retorna os elementos em uma lista separados por v&#237;rgula</p></li><li><p>JSON (): Retorna um objeto JSON conforme especificado. &#201; poss&#237;vel especificar um modelo Pydantic, e ele retornar&#225; JSON para esse modelo. Provavelmente o analisador de sa&#237;da mais confi&#225;vel para obter dados estruturados que N&#195;O usam chamadas de fun&#231;&#227;o.</p></li><li><p>XML (): Retorna um dicion&#225;rio de tags. Use quando a sa&#237;da XML for necess&#225;ria, especialmente com modelos eficientes na escrita XML, como o da Anthropic.</p></li><li><p>Pydantic (): Aceita um modelo Pydantic definido pelo usu&#225;rio e retorna dados nesse formato.</p></li><li><p>YAML (): Aceita um modelo Pydantic definido pelo usu&#225;rio e retorna dados nesse formato, utilizando YAML para a codifica&#231;&#227;o.</p></li><li><p>PandasDataFrame: &#218;til para realizar opera&#231;&#245;es com pandas DataFrames.</p></li></ul><p>Por padr&#227;o, se utiliza o <a href="https://api.python.langchain.com/en/latest/output_parsers/langchain_core.output_parsers.string.StrOutputParser.html">StrOutputParser</a>, que &#233; um parser de string. Como &#233; um parser padr&#227;o, n&#227;o &#233; necess&#225;rio invoc&#225;-lo. Mas, sua utiliza&#231;&#227;o &#233; a mesma que a seguinte: </p><pre><code>from langchain_core.output_parsers import StrOutputParser

chain = prompt | model | StrOutputParser()</code></pre><p>Para usar outros parsers, basta alterar o objeto a ser fornecido. Por exemplo:</p><pre><code><code>from langchain_core.output_parsers import CommaSeparatedListOutputParser

chain = prompt | model | CommaSeparatedListOutputParser()
chain.invoke({"input": "explique 3 principais pr&#225;ticas de design?"})</code></code></pre><p>Para outros parsers, como o JSON, &#233; preciso tamb&#233;m definir qual ser&#225; o formato do documento resultante. Para isso, podemos definir uma classe usando pydantic, indicando o corpo do documento JSON.</p><pre><code><code>from langchain_core.output_parsers import JsonOutputParser
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain.prompts import PromptTemplate

class Design(BaseModel):
    design: str = Field(description="nome da pratica de design")
    descricao: str = Field(description="descricao da pratica de design")

# criando parser com formato esperado
parser = JsonOutputParser(pydantic_object=Design)

prompt = ChatPromptTemplate.from_template("Voc&#234; deve atuar como um expert em design de software. Ajude nosso usu&#225;rio: {format_instructions}\n\n{input}")
prompt = prompt.partial(format_instructions=parser.get_format_instructions())

chain = prompt | model | parser

chain.invoke({"input": "a pr&#225;tica de design chamada SOLID"})</code></code></pre><p>Al&#233;m de criar o objeto <code>Design</code> e passa-lo para nosso parser <code>JsonOutputParser(pydantic_object=Design)</code>, foi necess&#225;rio tamb&#233;m mudar nosso prompt, para que este seja instru&#237;do da nova formata&#231;&#227;o. Como resultado, tivemos nossa sa&#237;da formatada como JSON, que facilita a integra&#231;&#227;o da resposta da LLM com demais servi&#231;os. Isso tudo, adicionando um pipe a mais na nossa chain.</p><h3>Conclus&#227;o</h3><p>O LangChain &#233; um framework que simplifica o desenvolvimento de aplicativos baseados em modelos de linguagem. Um dos seus destaques reside na LangChain Expression Language (LCEL), uma abordagem declarativa que facilita a cria&#231;&#227;o de cadeias de opera&#231;&#245;es, desde prompts simples at&#233; pipelines complexos. </p><p>Demonstrando seu uso, o texto ilustra a intera&#231;&#227;o com a OpenAI's LLM, exemplificando a cria&#231;&#227;o de cadeias de itera&#231;&#227;o de prompts e a separa&#231;&#227;o do prompt do modelo. Al&#233;m disso, aborda recursos como constru&#231;&#227;o de mem&#243;ria e formata&#231;&#227;o de sa&#237;da, destacando a versatilidade do LangChain na constru&#231;&#227;o de aplica&#231;&#245;es baseadas em LLMs.</p>]]></content:encoded></item></channel></rss>