<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Benchmark on IBM UFCG</title><link>https://llm-pt-ibm.github.io/tags/benchmark/</link><description>Recent content in Benchmark on IBM UFCG</description><generator>Hugo -- gohugo.io</generator><language>pt</language><copyright>IBM &amp; UFCG - 2025</copyright><lastBuildDate>Fri, 28 Nov 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://llm-pt-ibm.github.io/tags/benchmark/index.xml" rel="self" type="application/rss+xml"/><item><title>Inferência de LLMs com Ollama na IBM Power9 Utilizando CPU</title><link>https://llm-pt-ibm.github.io/posts/ollama_cpu/</link><pubDate>Wed, 01 Apr 2026 00:00:00 +0000</pubDate><guid>https://llm-pt-ibm.github.io/posts/ollama_cpu/</guid><description>&lt;h2 id="contexto">Contexto&lt;/h2>&lt;p>Este post apresenta um guia prático para realizar inferência de grandes Modelos de Linguagem (LLMs) utilizando o &lt;a href="https://ollama.com/" rel="external">&lt;span class="link-personalizado">&lt;em>Ollama&lt;/em>&lt;/span>&lt;/a>, em um ambiente IBM POWER9. O Ollama é um &lt;em>framework&lt;/em> baseado no &lt;a href="https://github.com/ggml-org/llama.cpp.git" rel="external">&lt;span class="link-personalizado">&lt;em>llama.cpp&lt;/em>&lt;/span>&lt;/a>, projetado para simplificar a implementação e execução de tais modelos, oferecendo uma interface amigável e suporte para diversas tarefas.&lt;/p>&lt;figure>&lt;img src="https://llm-pt-ibm.github.io/images/funcionamento_ollama.png" alt="Figura 1"/>&lt;figcaption> &lt;p>Fluxo de uma requisição&lt;/p> &lt;/figcaption>&lt;/figure>&lt;p>Apesar do crescimento no uso de LLMs, a disponibilidade de materiais voltados para a arquitetura &lt;em>ppc64le&lt;/em> (IBM POWER9) ainda é bastante limitada. Em geral, os tutoriais disponíveis são antigos, pouco detalhados ou focados em arquiteturas mais comuns, como &lt;em>x86_64&lt;/em>, o que dificulta a reprodução do ambiente no contexto apresentado. Este é o primeiro de dois posts dessa série, que tem como objetivo realizar a inferência inteiramente via CPU, explorando a arquitetura &lt;em>ppc64le&lt;/em>, de maneira atualizada, prática e reproduzível. No próximo post, abordaremos a utilização de GPU para acelerar o processo.&lt;/p>&lt;h2 id="tldr">TL;DR&lt;/h2>&lt;ul>&lt;li>Este post apresenta detalhes sobre como configurar o ambiente para realizar inferências com a infraestrutura da IBM POWER9.&lt;/li>&lt;li>A execução é realizada via CPU utilizando o Ollama;&lt;/li>&lt;li>O principal desafio envolve a configuração correta do ambiente, especialmente dependências como &lt;em>Go&lt;/em>, &lt;em>GCC&lt;/em> e &lt;em>CMake&lt;/em>, além da compatibilidade com &lt;a href="https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux" rel="external">&lt;span class="link-personalizado">&lt;em>RHEL&lt;/em>&lt;/span>&lt;/a>&lt;/li>&lt;/ul>&lt;h2 id="ambiente-utilizado">Ambiente utilizado&lt;/h2>&lt;p>&lt;strong>Hardware&lt;/strong>:&lt;/p>&lt;ul>&lt;li>Arquitetura &lt;em>ppc64le&lt;/em>;&lt;/li>&lt;li>RAM: ~64GB;&lt;/li>&lt;li>Execução: Máquina Virtual (VM);&lt;/li>&lt;/ul>&lt;p>&lt;strong>Sistema Operacional:&lt;/strong> Alma Linux 8.10 (&lt;em>ppc64le&lt;/em>), binário compatível com &lt;em>Red Hat Enterprise Linux (RHEL)&lt;/em> 8.9/8.10.&lt;/p>&lt;h2 id="setup-inicial">&lt;em>Setup&lt;/em> inicial&lt;/h2>&lt;p>Para executar o Ollama na arquitetura POWER9, é necessário preparar o ambiente com as dependências adequadas.O primeiro passo é atualizar o sistema e instalar os utilitários básicos:&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo dnf update -y&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo dnf install -y wget git tar make gcc gcc-c++ cmake gcc-toolset-11&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Embora esse comando instale parte das dependências, é necessário garantir que as versões corretas estejam sendo utilizadas.&lt;/p>&lt;h3 id="configuração-do-go">Configuração do &lt;em>Go&lt;/em>&lt;/h3>&lt;p>O Ollama é desenvolvido em &lt;em>Go&lt;/em>, portanto é necessário garantir a versão adequada.&lt;/p>&lt;p>&lt;strong>Versão esperada:&lt;/strong> 1.25.7 linux/ppc64le&lt;/p>&lt;h4 id="caso-não-esteja-instalado">Caso não esteja instalado:&lt;/h4>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>wget https://go.dev/dl/go1.25.7.linux-ppc64le.tar.gz&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo tar -C /usr/local -xzf go1.25.7.linux-ppc64le.tar.gz&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>export PATH&lt;span style="color:#f92672">=&lt;/span>/usr/local/go/bin:$PATH&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Para adicionar ao &lt;em>PATH&lt;/em> permanentemente:&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>echo &lt;span style="color:#e6db74">&amp;#39;export PATH=/usr/local/go/bin:$PATH&amp;#39;&lt;/span> &amp;gt;&amp;gt; ~/.bashrc&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>source ~/.bashrc&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Verifique se a versão está correta: &lt;code>go version&lt;/code>&lt;/p>&lt;h3 id="configuração-do-cmake">Configuração do &lt;em>Cmake&lt;/em>&lt;/h3>&lt;p>Verifique se a versão está correta: &lt;code>cmake --version&lt;/code>&lt;/p>&lt;p>&lt;strong>Versão esperada:&lt;/strong> cmake 3.26.5&lt;/p>&lt;h4 id="caso-não-esteja-instalado-1">Caso não esteja instalado:&lt;/h4>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>wget https://github.com/Kitware/CMake/releases/download/v3.26.5/cmake-3.26.5.tar.gz&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>tar -xzf cmake-3.26.5.tar.gz&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cd cmake-3.26.5&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>./bootstrap&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>make -j&lt;span style="color:#66d9ef">$(&lt;/span>nproc&lt;span style="color:#66d9ef">)&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>sudo make install&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="configuração-do-gcc">Configuração do &lt;em>GCC&lt;/em>&lt;/h3>&lt;p>&lt;strong>Versão esperada:&lt;/strong> &lt;code>gcc 11.2.1&lt;/code>&lt;/p>&lt;p>&lt;strong>Importante:&lt;/strong> No AlmaLinux 8, o &lt;em>gcc-toolset&lt;/em> não é ativado automaticamente. É necessário habilitar a sessão manualmente:&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>scl enable gcc-toolset-11 bash&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Esse comando ativa o GCC apenas na sessão atual. Se abrir outro terminal, será necessário executar o comando novamente.&lt;/p>&lt;p>&lt;strong>Verifique a versão:&lt;/strong> &lt;code>gcc --version&lt;/code>&lt;/p>&lt;h4 id="caso-não-esteja-instalado-2">Caso não esteja instalado:&lt;/h4>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>sudo dnf install -y gcc-toolset-11&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>scl enable gcc-toolset-11 bash&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="clonando-o-ollama">Clonando o Ollama&lt;/h3>&lt;p>Com o ambiente configurado, podemos realizar o &lt;em>build&lt;/em> do Ollama. Aqui vamos clonar o repositório oficial do ollama e mudar a versão utilizada (importante para a compatibilidade com a POWER e para obter uma versão estável).&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>cd /root&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git clone https://github.com/ollama/ollama.git&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cd ollama&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#Alterar a versão: &lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>git checkout v0.9.4&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Para verificar, use: &lt;code>git status&lt;/code>&lt;/p>&lt;h2 id="build-do-ollama">&lt;em>Build&lt;/em> do Ollama&lt;/h2>&lt;p>Após ativar GCC na versão certa:&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>export CGO_ENABLED&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>go clean -cache -modcache -i -r&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>go build -o ollama .&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>O &lt;em>CGO&lt;/em> precisa estar habilitado porque o Ollama depende do llama.cpp, que utiliza código em C/C++ para otimizações de performance. Sem isso, o &lt;em>build&lt;/em> falha ou perde compatibilidade com a arquitetura.&lt;/p>&lt;p>Isso deve ocorrer sem nenhum erro e gerar o binário &lt;code>ollama&lt;/code> criado no diretório atual.&lt;/p>&lt;p>Para verificar: &lt;code>./ollama --version&lt;/code>&lt;/p>&lt;h2 id="realizando-a-inferência">Realizando a Inferência&lt;/h2>&lt;p>Com o &lt;em>Ollama&lt;/em> compilado, podemos iniciar o servidor:&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>./ollama serve&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Uma observação importante é que, como o ambiente está sendo executado em uma máquina virtual, não é possível manter o comando em execução no terminal principal e, simultaneamente, utilizar outro terminal na mesma sessão para realizar a inferência, sem alguma ferramenta auxiliar para gerenciar múltiplos terminais.O que faremos então é executar o servidor em segundo plano (&lt;em>background&lt;/em>), mas você pode optar por usar &lt;em>Tmux&lt;/em> ou &lt;em>Screen&lt;/em>, permitindo que o mesmo terminal continue disponível para a execução dos demais comandos (que veremos a seguir). Para isso, você pode rodar:&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>./ollama serve &amp;amp;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Para verificar se deu certo: &lt;code>ps aux | grep ollama&lt;/code>. Vai aparecer algo assim:&lt;/p>&lt;figure>&lt;img src="https://llm-pt-ibm.github.io/images/print_ollama_serve.png" alt="Figura 2"/>&lt;figcaption> &lt;p>Ollama executando&lt;/p> &lt;/figcaption>&lt;/figure>&lt;h2 id="baixar-o-modelo-de-teste-e-executar-a-inferência">Baixar o modelo de teste e executar a inferência&lt;/h2>&lt;p>Para validação, utilizamos o modelo &lt;em>TinyLlama&lt;/em>, por ser leve e adequado para execução em CPU. Para isso, em outro terminal, rode:&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>./ollama pull tinyllama&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Para executar a inferência:&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>./ollama run tinyllama &lt;span style="color:#e6db74">&amp;#34;O céu é azul?&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Se tudo tiver sido feito de maneira correta, você terá algo como:&lt;/p>&lt;figure>&lt;img src="https://llm-pt-ibm.github.io/images/ollama_run.png" alt="Figura 3"/>&lt;figcaption> &lt;p>Inferencia sendo executada&lt;/p> &lt;/figcaption>&lt;/figure>&lt;p>É importante destacar que o &lt;em>Ollama&lt;/em> trabalha, por padrão, com modelos disponibilizados em seu próprio repositório, que já estão convertidos e otimizados para execução, geralmente no formato compatível com o &lt;em>llama.cpp&lt;/em>. Esses modelos podem ser facilmente utilizados por meio do comando &lt;code>ollama pull&lt;/code>, como no caso do &lt;em>TinyLlama&lt;/em> utilizado neste exemplo. Embora seja possível utilizar modelos externos, isso exige etapas adicionais, como a conversão para formatos compatíveis (por exemplo, &lt;em>GGUF&lt;/em>) e a criação de um &lt;em>Modelfile&lt;/em>.&lt;/p>&lt;h2 id="considerações-finais">Considerações Finais&lt;/h2>&lt;p>Com os passos apresentados, foi possível configurar o ambiente para executar inferências de LLMs em uma máquina IBM POWER9 utilizando a CPU. Apesar de ser funcional, essa abordagem apresenta limitações no desempenho, especialmente para modelos maiores, devido a ausência de aceleração via GPU. Como próximo passo, pretendemos explorar a execução utilizando GPU, avaliando ganhos de desempenho e escalabilidade.&lt;/p>&lt;h2 id="próximos-passos">Próximos Passos&lt;/h2>&lt;ul>&lt;li>Testar versões mais recentes e a compatibilidade entre elas;&lt;/li>&lt;li>Realizar uma experimentação de &lt;em>benchmarks&lt;/em> para comparar o desempenho da Inferência em CPU em relação a inferência em GPU;&lt;/li>&lt;li>Segundo post dessa série, realizando inferência em GPU.&lt;/li>&lt;/ul></description></item><item><title>Virtualização em Power9: como estruturamos um ambiente isolado com KVM e Libvirt</title><link>https://llm-pt-ibm.github.io/posts/virtualization/</link><pubDate>Fri, 27 Mar 2026 00:00:00 +0000</pubDate><guid>https://llm-pt-ibm.github.io/posts/virtualization/</guid><description>&lt;h2 id="contexto">Contexto&lt;/h2>&lt;p>Diante da necessidade de estabelecer ambientes isolados e seguros para a instalação de bibliotecas, frameworks e ferramentas de uso geral, o encapsulamento de um ambiente surgiu como alternativa para resolução desse problema, fazendo-se presente através do KVM gerenciado por meio do virt-manager e do virsh.&lt;/p>&lt;p>A virtualização é amplamente utilizada em ambientes x86, com ferramentas e fluxos bem consolidados. No entanto, quando migramos para arquiteturas como o IBM Power9 (ppc64le), muitos desses processos deixam de ser diretos e exigem adaptações específicas. Abaixo, temos um diagrama que demonstra essa comunicação dividida em 4 camadas.&lt;/p>&lt;h2 id="fluxo-de-comunicação-entre-hardware-power9-e-máquinas-virtuais">Fluxo de comunicação entre Hardware (Power9) e Máquinas Virtuais&lt;/h2>&lt;p>O fluxo é organizado nas seguintes camadas:&lt;/p>&lt;!--&lt;div style="text-align: center;"> &lt;img src="https://llm-pt-ibm.github.io/images/kvm_virtualizacao.png" style="max-width: 90%;">&lt;/div> -->&lt;figure>&lt;img src="https://llm-pt-ibm.github.io/images/kvm_virtualizacao.png" alt="Figura 1: Diagrama que representa a arquitetura de virtualização em 4 camadas."/>&lt;figcaption> &lt;p>Figura 1: Diagrama que representa a arquitetura de virtualização em 4 camadas.&lt;/p> &lt;/figcaption>&lt;/figure>&lt;p>Neste trabalho, exploramos a construção de um ambiente virtualizado utilizando KVM e Libvirt em um servidor Power9, com foco em isolamento, reprodutibilidade e uso compartilhado entre membros de uma equipe.&lt;/p>&lt;h2 id="tldr">TL;DR&lt;/h2>&lt;ul>&lt;li>Implementamos um ambiente virtualizado no Power9 usando KVM + Libvirt.&lt;/li>&lt;li>Adaptamos fluxos comuns de virtualização para arquitetura ppc64le, resolvendo problemas de permissão, lock de escrita e provisionamento.&lt;/li>&lt;li>O ambiente permite isolamento seguro entre usuários e fácil gerenciamento de VMs.&lt;/li>&lt;li>Disponibilizamos imagens prontas com drivers NVIDIA/CUDA para uso imediato.&lt;/li>&lt;/ul>&lt;h2 id="ambiente-utilizado">Ambiente utilizado&lt;/h2>&lt;ul>&lt;li>&lt;strong>Arquitetura&lt;/strong>: Servidor IBM Power9 (Arquitetura ppc64le).&lt;/li>&lt;li>&lt;strong>Sistema Operacional (SO)&lt;/strong>: AlmaLinux 8.10 binário compatível com Red Hat Enterprise Linux (RHEL) 8.9/8.10.&lt;/li>&lt;li>&lt;strong>RAM&lt;/strong>: 512GB.&lt;/li>&lt;li>&lt;strong>Execução&lt;/strong>: Virtual Manager para gerenciamento de Máquinas Virtuais (VMs).&lt;/li>&lt;li>&lt;strong>Hypervisor&lt;/strong>: KVM (Kernel-based Virtual Machine) / QEMU.&lt;/li>&lt;li>&lt;strong>Gerenciamento&lt;/strong>: Libvirt (virsh, virt-install, virt-customize).&lt;/li>&lt;li>&lt;strong>Armazenamento&lt;/strong>: Discos virtuais no formato .qcow2.&lt;/li>&lt;li>&lt;strong>GPUs&lt;/strong>: 4x NVIDIA Tesla V100 SXM2 16GB (NVLink2).&lt;/li>&lt;/ul>&lt;h2 id="instalando-o-ambiente-de-virtualização-kvm--libvirt">Instalando o ambiente de virtualização (KVM + Libvirt)&lt;/h2>&lt;p>Antes de criar qualquer VM, é necessário instalar e configurar o KVM e o Libvirt no servidor Power9.&lt;/p>&lt;ol>&lt;li>&lt;strong>Instalação dos pacotes&lt;/strong>:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sudo dnf install -y qemu-kvm libvirt libvirt-client libvirt-daemon libvirt-daemon-kvm virt-install virt-viewer guestfs-tools \libguestfs-tools python3-libvirt&lt;/code>&lt;/pre>&lt;ol start="2">&lt;li>&lt;strong>Iniciando serviço&lt;/strong>:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sudo systemctl enable --now libvirtdsudo systemctl status libvirtd&lt;/code>&lt;/pre>&lt;ol start="3">&lt;li>&lt;strong>Adicionando o usuário ao grupo libvirt&lt;/strong>:Para que usuários não-root possam gerenciar VMs sem precisar de sudo em todo comando:&lt;/li>&lt;/ol>&lt;p>Execute o comando abaixo:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo usermod -aG libvirt $(whoami)&lt;/code>&lt;/pre>&lt;p>Faça logout e login novamente para aplicar a mudança.&lt;/p>&lt;ol start="4">&lt;li>&lt;strong>Verificando instalação&lt;/strong>:&lt;/li>&lt;/ol>&lt;p>Verifique a versão do &lt;code>virsh&lt;/code>:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virsh version&lt;/code>&lt;/pre>&lt;p>Valide o suporte à virtualização no processador:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virt-host-validate&lt;/code>&lt;/pre>&lt;h2 id="setup">Setup&lt;/h2>&lt;ol>&lt;li>&lt;strong>Preparação de ambiente&lt;/strong>:No KVM, a forma mais rápida de provisionar VMs é clonar uma imagem &amp;ldquo;semente&amp;rdquo; (.qcow2) e expandi-la, em vez de fazer uma instalação limpa via ISO. Portanto, para manter a organização, todos os discos virtuais ficarão em um diretório separado:&lt;/li>&lt;/ol>&lt;p>Baixe a imagem base do Alma Linux 8:&lt;/p>&lt;pre tabindex="0">&lt;code>cd /home/user/wget https://repo.almalinux.org/almalinux/8/cloud/ppc64le/images/AlmaLinux-8-GenericCloud-latest.ppc64le.qcow2 -O alma8_base.qcow2&lt;/code>&lt;/pre>&lt;ol start="2">&lt;li>&lt;strong>Gerenciamento do Hipervisor&lt;/strong>:A administração do hipervisor e das instâncias segue protocolos específicos para garantir a estabilidade do sistema. Comandos para o Administrador controlar o serviço no Power9:&lt;/li>&lt;/ol>&lt;p>Desative o sistema KVM:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo systemctl stop libvirtd&lt;/code>&lt;/pre>&lt;p>Reative o sistema KVM:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo systemctl start libvirtd&lt;/code>&lt;/pre>&lt;p>Habilite no boot:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo systemctl enable libvirtd&lt;/code>&lt;/pre>&lt;ol start="3">&lt;li>&lt;strong>Resolução de permissões&lt;/strong>:O usuário do sistema que executa o KVM (chamado qemu) precisa ter permissão para acessar os discos da VM. Se o diretório estiver dentro de uma home pessoal, o Linux bloqueará o acesso por padrão. Para permitir que o hipervisor acesse a pasta de discos sem expor seus arquivos pessoais, conceda permissão de execução (o+x) nos diretórios:&lt;/li>&lt;/ol>&lt;p>Permita que o qemu &amp;ldquo;atravesse&amp;rdquo; a home (apenas travessia, não leitura):&lt;/p>&lt;pre tabindex="0">&lt;code>chmod o+x /home/user&lt;/code>&lt;/pre>&lt;p>Permita que o qemu acesse a pasta de discos:&lt;/p>&lt;pre tabindex="0">&lt;code>chmod o+x /home/user/discos&lt;/code>&lt;/pre>&lt;ol start="4">&lt;li>&lt;strong>Configuração de rede virtual (Libvirt)&lt;/strong>:O Libvirt cria uma rede NAT padrão (default) que coloca as VMs na faixa 192.168.122.0/24. As VMs têm acesso à internet via NAT, mas não são acessíveis diretamente da rede externa sem configuração adicional.&lt;/li>&lt;/ol>&lt;p>Verifique o status da rede:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virsh net-list --all&lt;/code>&lt;/pre>&lt;p>Se estiver inativa, inicie e habilite no boot:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virsh net-start defaultsudo virsh net-autostart default&lt;/code>&lt;/pre>&lt;p>Se a rede não existir, defina e inicialize:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virsh net-define /usr/share/libvirt/networks/default.xmlsudo virsh net-start defaultsudo virsh net-autostart default&lt;/code>&lt;/pre>&lt;p>Se o XML não for encontrado, instale o pacote de configuração de rede:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo dnf install -y libvirt-daemon-config-network&lt;/code>&lt;/pre>&lt;ol start="5">&lt;li>&lt;strong>Criando novas VMs&lt;/strong>:&lt;/li>&lt;/ol>&lt;p>Clone a imagem base:&lt;/p>&lt;pre tabindex="0">&lt;code>cp /home/user/alma8_base.qcow2 /home/user/discos/nome_vm.qcow2&lt;/code>&lt;/pre>&lt;p>Expanda o disco (a expansão deve ser feita ANTES de criar a VM):&lt;/p>&lt;pre tabindex="0">&lt;code>qemu-img resize /home/user/discos/nome_vm.qcow2 +100G&lt;/code>&lt;/pre>&lt;p>Crie a VM:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virt-install \ --connect qemu:///system \ --name vm_nome \ --memory 131072 \ --vcpus 16 \ --cpu host \ --disk path=/home/user/discos/nome_vm.qcow2,format=qcow2 \ --import \ --os-variant almalinux8 \ --network network=default \ --graphics none \ --noautoconsole&lt;/code>&lt;/pre>&lt;ol start="6">&lt;li>&lt;strong>Customização após criar as VMs&lt;/strong>:Após criar a VM, é necessário definir a senha root, pois a imagem cloud vem sem senha por padrão. Utilizamos o virt-customize para isso. &lt;strong>Importante&lt;/strong>: A VM deve estar desligada para que o disco possa ser editado em segurança.&lt;/li>&lt;/ol>&lt;p>Desligue a VM:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virsh shutdown vm_nome&lt;/code>&lt;/pre>&lt;p>Aguarde o desligamento completo:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virsh list --all&lt;/code>&lt;/pre>&lt;p>Injete a senha no disco:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virt-customize -a /home/user/discos/nome_vm.qcow2 \ --root-password password:senha_desejada&lt;/code>&lt;/pre>&lt;p>Ligue a VM novamente:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virsh start vm_nome&lt;/code>&lt;/pre>&lt;ol start="7">&lt;li>&lt;strong>Acessando VMs&lt;/strong>:&lt;/li>&lt;/ol>&lt;p>&lt;strong>Via console serial&lt;/strong>&lt;/p>&lt;p>Conecte ao console da VM:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virsh console vm_nome&lt;/code>&lt;/pre>&lt;p>Para sair do console, use &lt;code>Ctrl + ]&lt;/code>.&lt;/p>&lt;p>&lt;strong>Via SSH&lt;/strong>&lt;/p>&lt;p>Descubra o IP da VM:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virsh domifaddr vm_nome&lt;/code>&lt;/pre>&lt;p>Acesse via SSH:&lt;/p>&lt;pre tabindex="0">&lt;code>ssh root@&amp;lt;ip_da_vm&amp;gt;&lt;/code>&lt;/pre>&lt;ol start="8">&lt;li>&lt;strong>Gerenciar e apagar VMs&lt;/strong>:Se você precisar destruir um ambiente para recriá-lo do zero, siga os 3 passos obrigatórios para limpar tudo:&lt;/li>&lt;/ol>&lt;p>Force o desligamento da VM:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virsh destroy nome_da_vm&lt;/code>&lt;/pre>&lt;p>Remova a definição da VM do Libvirt:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virsh undefine nome_da_vm&lt;/code>&lt;/pre>&lt;p>Apague o disco virtual para liberar espaço no Power9:&lt;/p>&lt;pre tabindex="0">&lt;code>rm -f /home/user/discos/nome_da_vm.qcow2&lt;/code>&lt;/pre>&lt;ol start="9">&lt;li>&lt;strong>Criar VM a partir de imagem existente (clonagem)&lt;/strong>:Para criar uma nova VM a partir de uma imagem já configurada, como as imagens prontas com drivers NVIDIA:&lt;/li>&lt;/ol>&lt;p>Opção A: clonar via &lt;code>qemu-img&lt;/code> (mantém a imagem original intacta):&lt;/p>&lt;pre tabindex="0">&lt;code>qemu-img create -f qcow2 -b imagem-base.qcow2 -F qcow2 nova-vm.qcow2&lt;/code>&lt;/pre>&lt;p>Opção B: clonar via &lt;code>virt-clone&lt;/code>:&lt;/p>&lt;pre tabindex="0">&lt;code>virt-clone \ --original vm-base \ --name vm-nova \ --file /home/user/discos/nova-vm.qcow2&lt;/code>&lt;/pre>&lt;p>Caso seja necessário, pode-se executar o passo de excluir a VM e recriá-la conforme a etapa 5.&lt;/p>&lt;h2 id="imagens-prontas-com-drivers-nvidia">Imagens prontas com drivers NVIDIA&lt;/h2>&lt;p>Para facilitar o uso das GPUs Tesla V100 presentes no servidor, disponibilizamos imagens .qcow2 pré-configuradas com os drivers NVIDIA, CUDA e cuDNN instalados. Isso elimina a necessidade de configurar o ambiente base a cada novo uso.&lt;/p>&lt;ol>&lt;li>&lt;p>&lt;strong>Imagens disponíveis&lt;/strong>:&lt;/p>&lt;table>&lt;thead>&lt;tr>&lt;th style="text-align:left">Imagem&lt;/th>&lt;th style="text-align:left">Conteúdo&lt;/th>&lt;/tr>&lt;/thead>&lt;tbody>&lt;tr>&lt;td style="text-align:left">AlmaLinux-8-Power9-NVIDIA-drivers.qcow2.xz&lt;/td>&lt;td style="text-align:left">AlmaLinux 8.10 + drivers NVIDIA 535 + CUDA 12.2 + cuDNN 9.0&lt;/td>&lt;/tr>&lt;/tbody>&lt;/table>&lt;/li>&lt;li>&lt;p>&lt;strong>Como usar imagens pré-configuradas&lt;/strong>:&lt;/p>&lt;/li>&lt;/ol>&lt;p>Baixe e descompacte a imagem:&lt;/p>&lt;pre tabindex="0">&lt;code>pip install --user gdowngdown --folder &amp;#34;https://drive.google.com/file/d/1coGmFTwLWdUP6AlOfwd-_VmN0eoNwFOT/view?usp=drive_link&amp;#34;xz -d AlmaLinux-8-Power9-NVIDIA-drivers.qcow2.xz&lt;/code>&lt;/pre>&lt;p>Mova para o diretório de discos e crie a VM a partir dela:&lt;/p>&lt;pre tabindex="0">&lt;code>cp AlmaLinux-8-Power9-NVIDIA-drivers.qcow2 /home/user/discos/minha-vm-gpu.qcow2&lt;/code>&lt;/pre>&lt;p>Crie a VM normalmente:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virt-install \ --connect qemu:///system \ --name vm_gpu \ --memory 131072 \ --vcpus 16 \ --cpu host \ --disk path=/home/user/discos/minha-vm-gpu.qcow2,format=qcow2 \ --import \ --os-variant almalinux8 \ --network network=default \ --graphics none \ --noautoconsole&lt;/code>&lt;/pre>&lt;p>Para que a VM tenha acesso às GPUs físicas, é necessário configurar o passthrough PCIe conforme descrito no próximo post desta série.&lt;/p>&lt;ol start="3">&lt;li>&lt;strong>Como gerar nova imagem a partir de VM configurada&lt;/strong>:Após instalar drivers ou qualquer software dentro de uma VM, você pode exportar o estado atual como nova imagem para reuso:&lt;/li>&lt;/ol>&lt;p>Desligue a VM:&lt;/p>&lt;pre tabindex="0">&lt;code>sudo virsh shutdown vm_nome&lt;/code>&lt;/pre>&lt;p>Converta e compacte a imagem (remove espaço não utilizado):&lt;/p>&lt;pre tabindex="0">&lt;code>qemu-img convert -O qcow2 -c \ /home/user/discos/vm_nome.qcow2 \ /home/user/discos/AlmaLinux-8-Power9-minha-imagem.qcow2&lt;/code>&lt;/pre>&lt;p>Comprima para distribuição:&lt;/p>&lt;pre tabindex="0">&lt;code>xz -T0 -v /home/user/discos/AlmaLinux-8-Power9-minha-imagem.qcow2&lt;/code>&lt;/pre>&lt;p>Saída esperada: &lt;code>AlmaLinux-8-Power9-minha-imagem.qcow2.xz&lt;/code>.&lt;/p>&lt;p>Verifique a integridade:&lt;/p>&lt;pre tabindex="0">&lt;code>qemu-img check AlmaLinux-8-Power9-minha-imagem.qcow2qemu-img info AlmaLinux-8-Power9-minha-imagem.qcow2&lt;/code>&lt;/pre></description></item><item><title>Avaliação de Modelos IBM Granite para Tarefas de Geração de Código no HumanEvalX</title><link>https://llm-pt-ibm.github.io/posts/post_humanevalx/</link><pubDate>Fri, 28 Nov 2025 00:00:00 +0000</pubDate><guid>https://llm-pt-ibm.github.io/posts/post_humanevalx/</guid><description>&lt;h2 id="contexto">Contexto&lt;/h2>&lt;p>O uso de modelos de linguagem para &lt;strong>geração e compreensão de código&lt;/strong> tem se tornado essencial em fluxos de desenvolvimento modernos.&lt;br>Como parte do esforço conjunto entre o &lt;strong>LSD/UFCG&lt;/strong> e a &lt;strong>IBM Brasil&lt;/strong>, investigamos a performance da família &lt;strong>IBM Granite 4&lt;/strong> no benchmark &lt;strong>HumanEvalX&lt;/strong>, que avalia capacidades de programação em &lt;em>cinco linguagens&lt;/em>: Python, Java, Go, C++, e JavaScript.&lt;/p>&lt;p>O objetivo foi responder perguntas centrais da equipe:&lt;/p>&lt;ul>&lt;li>&lt;em>Quão versáteis são os modelos Granite entre linguagens diferentes?&lt;/em>&lt;/li>&lt;li>&lt;em>Modelos menores entregam performance útil?&lt;/em>&lt;/li>&lt;li>&lt;em>Como os Granite se posicionam frente a modelos open-source como DeepSeek Coder e CodeLlama?&lt;/em>&lt;/li>&lt;/ul>&lt;hr>&lt;h2 id="metodologia--processo">Metodologia / Processo&lt;/h2>&lt;p>A avaliação foi conduzida utilizando o &lt;strong>OpenCompass&lt;/strong>, um framework moderno e extensível para benchmarking de LLMs em escala. Ele permitiu executar todos os experimentos de forma padronizada, reprodutível e com protocolos consistentes de inferência.&lt;/p>&lt;p>Como o OpenCompass não possui suporte nativo aos modelos hospedados na &lt;strong>IBM Cloud&lt;/strong>, foi necessário desenvolver um &lt;em>client&lt;/em> personalizado para integrar o framework à IBM Cloud Inference API. Esse &lt;em>client&lt;/em> permitiu que o processo de avaliação executasse requisições de forma transparente, tratasse autenticação, controlasse parâmetros de geração e retornasse as respostas no formato esperado pelo benchmark. Os experimentos também foram executados no &lt;strong>Google Colab&lt;/strong>, que serviu como ambiente prático de prototipação e execução dos modelos.&lt;/p>&lt;p>Utilizamos o benchmark HumanEvalX, uma extensão do HumanEval tradicional, cobrindo cinco linguagens com métricas consistentes de avaliação como, por exemplo ,&lt;strong>Pass@1&lt;/strong>.&lt;/p>&lt;p>Os modelos avaliados incluíram:&lt;/p>&lt;ul>&lt;li>Granite 4.0 Micro (3B)&lt;/li>&lt;li>Granite 4.0 (1B)&lt;/li>&lt;li>Granite 4.0 h-tiny (7B)&lt;/li>&lt;li>Granite 4.0 h-small (30B) — via IBM Cloud&lt;/li>&lt;li>granite 4.0 (350M)&lt;/li>&lt;li>granite code instruct 8B — via IBM Cloud&lt;/li>&lt;li>DeepSeek Coder (6.7B)&lt;/li>&lt;li>CodeLlama (7B)&lt;/li>&lt;/ul>&lt;p>A métrica utilizada foi &lt;strong>Pass@1&lt;/strong>, seguindo o protocolo do benchmark.&lt;/p>&lt;hr>&lt;h2 id="resultados-e-conclusões">Resultados e Conclusões&lt;/h2>&lt;figure>&lt;img src="https://llm-pt-ibm.github.io/images/heatmap_humanevalX.png" alt="Heatmap de desempenho"/>&lt;figcaption> &lt;p>Heatmap do desempenho dos modelos no HumanEvalX.&lt;/p> &lt;/figcaption>&lt;/figure>&lt;p>A avaliação revelou comportamentos importantes:&lt;/p>&lt;h3 id="1-o-granite-40-h-small-se-destacou-pela-versatilidade">&lt;strong>1. O granite-4.0-h-small se destacou pela versatilidade&lt;/strong>&lt;/h3>&lt;p>Ele superou 60% de Pass@1 em Java, C++ e JavaScript, além de manter mais de 50% em Python e Go. Esse desempenho consistente entre linguagens sugere que o modelo tem boa capacidade de generalização, mostrando-se promissor em cenários que envolvem diferentes ecossistemas de programação, embora análises adicionais em outros benchmarks sejam importantes para uma conclusão mais ampla.&lt;/p>&lt;h3 id="2-o-granite-micro-3b-apresentou-performance-acima-do-esperado">&lt;strong>2. O Granite Micro (3B) apresentou performance acima do esperado&lt;/strong>&lt;/h3>&lt;p>Apesar de ser um modelo pequeno, o Granite Micro (3B) surpreendeu ao alcançar 65.85% em JavaScript e 68.90% em Java, superando inclusive modelos maiores avaliados.Esse comportamento mostra que, mesmo com uma arquitetura compacta, ele consegue entregar resultados sólidos, tornando-se uma opção altamente eficiente para aplicações que exigem baixo custo computacional sem abrir mão de desempenho.&lt;/p>&lt;h3 id="3-a-progressão-de-tamanhos-350m--1b--3b--7b--30b-mostra-evolução-gradual-e-coerente">&lt;strong>3. A progressão de tamanhos (350M → 1B → 3B → 7B → 30B) mostra evolução gradual e coerente&lt;/strong>&lt;/h3>&lt;p>Os resultados mostram que, à medida que avançamos pelos diferentes tamanhos da linha Granite, há uma evolução coerente no desempenho. Os modelos menores entregam resultados estáveis dentro da sua categoria, enquanto os maiores ampliam progressivamente a capacidade de resolver tarefas mais complexas. Essa distribuição ajuda a entender melhor onde cada modelo se encaixa no espectro de uso.&lt;/p>&lt;h3 id="4-a-comparação-entre-provedores-ajuda-a-contextualizar-os-resultados">&lt;strong>4. A comparação entre provedores ajuda a contextualizar os resultados&lt;/strong>&lt;/h3>&lt;p>Ao lado dos modelos da IBM, também avaliamos modelos de outros provedores, como DeepSeek e Meta. Em algumas linguagens, as diferenças foram pequenas, mas em todas elas houve ao menos um modelo da família Granite que alcançou a melhor pontuação. Os modelos Granite 4 Micro (3B) e Granite 4 h-small (30B) foram os destaques com resultados que ficaram próximos, e em alguns casos acima, de modelos reconhecidos por serem especialistas em código.&lt;/p>&lt;hr>&lt;h2 id="próximos-passos">Próximos Passos&lt;/h2>&lt;ul>&lt;li>Executar os mesmos modelos da família Granite no LiveCodeBench, um benchmark mais amplo que vai além de &lt;strong>code-generation&lt;/strong>, avaliando também &lt;strong>code execution&lt;/strong> e &lt;strong>test-output&lt;/strong>.&lt;/li>&lt;li>Realizar um &lt;strong>fine-tuning de um modelo Granite 4.0 Micro (3B) utilizando o InstructLab&lt;/strong> e observar o impacto dessa adaptação no desempenho do modelo no &lt;strong>HumanEvalX&lt;/strong>, comparando antes e depois do ajuste.&lt;/li>&lt;/ul></description></item><item><title>Contaminação por dados de Benchmark em LLMs: Fundamentos, Causas e Estratégias de Detecção</title><link>https://llm-pt-ibm.github.io/posts/introducao_contaminacao/</link><pubDate>Mon, 21 Jul 2025 00:00:00 +0000</pubDate><guid>https://llm-pt-ibm.github.io/posts/introducao_contaminacao/</guid><description>&lt;h2 id="contexto">Contexto&lt;/h2>&lt;p>&lt;em>Benchmarks&lt;/em> são estruturas organizadas e padronizadas que podem ser utilizadas para avaliar o desempenho de grandes modelos de linguagem (LLMs). Compostos, em geral, por uma base de dados, um conjunto de tarefas e métricas de avaliação, esses recursos fornecem um ponto de referência comum para mensurar avanços, comparar arquiteturas e orientar decisões de desenvolvimento e implantação.&lt;/p>&lt;p>Apesar de seu uso recorrente, os resultados obtidos em &lt;em>benchmarks&lt;/em> podem ser influenciados por diversos fatores. Um dos fatores ocorre quando, de alguma forma, os dados de teste são previamente expostos ao modelo durante seu treinamento. Esse cenário caracteriza o fenômeno conhecido como &lt;strong>contaminação por dados de &lt;em>benchmark&lt;/em>&lt;/strong>, que pode ocorrer de forma acidental ou deliberada. A presença desse tipo de contaminação tende a comprometer a avaliação, pois o modelo pode memorizar parcial ou integralmente os exemplos avaliados em uma determinada tarefa, distorcendo seu desempenho real.&lt;/p>&lt;div style="text-align: center; display: table;"> &lt;img src="https://llm-pt-ibm.github.io/images/contaminacao_explicacao.png" alt="Explicação contaminação" style="max-width: 50%; box-shadow: none;"> &lt;p style="margin-top: 0.3em; font-size: 0.8em; font-style: italic; color: #000000eb">Contaminação por dados de benchmark&lt;/p>&lt;/div>&lt;p>Com o objetivo de introduzir e difundir esse tema, esta postagem apresenta os fundamentos conceituais da contaminação por dados de &lt;em>benchmark&lt;/em>, suas causas recorrentes e as metodologias atualmente utilizadas para sua detecção.&lt;/p>&lt;h2 id="tldr">TL;DR&lt;/h2>&lt;ul>&lt;li>Modelos são vulneráveis à contaminação quando os dados utilizados para testá-lo são previamente expostos durante o treinamento.&lt;/li>&lt;li>A contaminação pode ocorrer de forma acidental ou intencional e compromete a validade das avaliações.&lt;/li>&lt;li>Existem diferentes formas de contaminação, que variam pelo conteúdo exposto, momento da exposição e nível de abstração.&lt;/li>&lt;li>Métodos de detecção podem ser diretos (quando os dados de treinamento são acessíveis) ou indiretos (baseados em comportamento ou inferência).&lt;/li>&lt;li>Ferramentas como LLMSanitize, BenBench, ConStat e CDD-TED auxiliam na identificação sistemática de contaminações.&lt;/li>&lt;/ul>&lt;h2 id="impactos-da-contaminação">Impactos da contaminação&lt;/h2>&lt;p>A contaminação por dados de &lt;em>benchmarks&lt;/em> provoca distorções que afetam tanto o rigor científico das avaliações quanto a confiabilidade de aplicações baseadas em LLMs. Os principais impactos descritos abaixo, também são discutidos em estudos como &lt;a href="#ref1">[1]&lt;/a> &lt;a href="#ref5">[5]&lt;/a> &lt;a href="#ref7">[7]&lt;/a>.&lt;/p>&lt;div style="text-align: center; display: table; width: 100%;"> &lt;img src="https://llm-pt-ibm.github.io/images/icones_riscos_contaminacao.png" alt="Riscos da contaminação" style="max-width: 40%; box-shadow: none;"> &lt;p style="margin-top: 0.3em; font-size: 0.8em; font-style: italic; color: #000000eb">Riscos da contaminação por dados de benchmark&lt;/p>&lt;/div>&lt;ul>&lt;li>&lt;p>&lt;strong>Inflacionamento de métricas:&lt;/strong> A exposição prévia aos dados de avaliação pode elevar artificialmente o desempenho dos modelos, resultando em métricas superestimadas, como acurácia e calibragem. Isso dificulta a interpretação precisa de suas capacidades reais.&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;strong>Avaliação comprometida:&lt;/strong> Quando um &lt;em>benchmark&lt;/em> é aplicado a modelos que já tiveram acesso a seus dados, ele deixa de refletir a dificuldade real das tarefas, comprometendo sua função como instrumento de avaliação imparcial.&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;strong>Redução da generalização:&lt;/strong> A contaminação favorece a memorização de exemplos específicos em vez da aprendizagem de padrões gerais, o que reduz a capacidade do modelo de lidar com dados não vistos, especialmente em casos de contaminação por rótulo ou semântica.&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;strong>Riscos em aplicações sensíveis:&lt;/strong> Avaliações contaminadas podem levar à adoção de modelos em domínios críticos, como saúde, direito e finanças, com base em métricas distorcidas. Isso aumenta o risco de falhas operacionais e decisões inadequadas.&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;strong>Comparações enviesadas e desperdício de recursos:&lt;/strong> A contaminação prejudica a equidade entre modelos, especialmente quando apenas alguns foram expostos previamente aos dados de &lt;em>benchmark&lt;/em>. Isso compromete comparações, favorece modelos não auditáveis e pode levar à alocação ineficiente de recursos.&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;strong>Comprometimento da integridade científica:&lt;/strong> Avaliações baseadas em &lt;em>benchmarks&lt;/em> contaminados afetam a reprodutibilidade e podem resultar em conclusões inválidas, enfraquecendo a confiabilidade de estudos que utilizam esses resultados como base empírica.&lt;/p>&lt;/li>&lt;/ul>&lt;h2 id="causas-da-contaminação-por-dados-de-benchmark">Causas da contaminação por dados de &lt;em>benchmark&lt;/em>&lt;/h2>&lt;p>A contaminação por dados de &lt;em>benchmarks&lt;/em> em LLMs pode ocorrer de forma &lt;strong>acidental&lt;/strong> &lt;a href="#ref1">[1]&lt;/a> &lt;a href="#ref4">[4]&lt;/a> ou &lt;strong>intencional&lt;/strong> &lt;a href="#ref1">[1]&lt;/a> &lt;a href="#ref3">[3]&lt;/a>, com diferentes origens e consequências, dependendo principalmente da forma como os dados de treinamento são coletados, utilizados e reaproveitados nos ciclos de desenvolvimento dos modelos.&lt;/p>&lt;p>A contaminação &lt;strong>acidental&lt;/strong> é a mais comum e ocorre, na maioria dos casos, devido ao uso de &lt;strong>dados extraídos automaticamente da internet para pré-treinamento em larga escala&lt;/strong> &lt;a href="#ref1">[1]&lt;/a> &lt;a href="#ref4">[4]&lt;/a>. Esses corpora, por sua diversidade e volume, frequentemente incluem conteúdos associados a &lt;em>benchmarks&lt;/em>, como exemplos idênticos, trechos brutos ou textos semanticamente relacionados. Isso se deve ao fato de &lt;em>benchmarks&lt;/em> e dados de treinamento frequentemente compartilharem fontes públicas comuns, como Wikipedia, repositórios educacionais, artigos técnicos e redes sociais.&lt;/p>&lt;div style="text-align: center; display: table;"> &lt;img src="https://llm-pt-ibm.github.io/images/contaminacao_nao_intencional.png" alt="Contaminação não intencional" caption="" style="max-width: 80%; box-shadow: none;"> &lt;p style="margin-top: 0.3em; font-size: 0.8em; font-style: italic; color: #000000eb">Exemplo de fluxo de contaminação não intencional&lt;/p>&lt;/div>&lt;p>Embora mecanismos de filtragem possam ser implementados para evitar a inclusão de &lt;em>benchmarks&lt;/em> conhecidos, essa estratégia apresenta limitações &lt;a href="#ref4">[4]&lt;/a>. É difícil garantir a exclusão de todos os &lt;em>benchmarks&lt;/em> existentes, especialmente os lançados recentemente ou ainda não amplamente documentados. Além disso, a identificação de sobreposição semântica é complexa, o que torna a detecção de vazamentos indiretos ainda mais desafiadora.&lt;/p>&lt;p>Outro vetor de contaminação acidental está relacionado à &lt;strong>reutilização de interações com usuários&lt;/strong> para re-treinamento ou ajuste fino de modelos implantados em produção &lt;a href="#ref7">[7]&lt;/a>. Sistemas comerciais podem reaproveitar entradas fornecidas por usuários durante testes, avaliações públicas ou uso real. Quando essas interações reproduzem exemplos derivados de &lt;em>benchmarks&lt;/em>, há risco de contaminação retroativa, mesmo que não intencional, nos ciclos seguintes de treinamento.&lt;/p>&lt;p>Além disso, a contaminação pode se propagar por meio da &lt;strong>geração de conteúdo por LLMs&lt;/strong> &lt;a href="#ref1">[1]&lt;/a>. Modelos contaminados podem gerar textos que replicam padrões ou trechos presentes em &lt;em>benchmarks&lt;/em>, mesmo que de forma parafraseada ou reestruturada. Esses textos, quando reutilizados em novos &lt;em>benchmarks&lt;/em> ou conjuntos de treinamento, perpetuam e amplificam a contaminação original. Apesar de, nesses casos, os desenvolvedores poderem estar cientes da contaminação prévia, a natureza recursiva do processo faz com que a propagação ocorra de forma indireta e, muitas vezes, incontrolável. Por esse motivo, esse tipo de exposição também pode ser considerado um caso de contaminação acidental.&lt;/p>&lt;p>Por outro lado, a &lt;strong>contaminação intencional&lt;/strong> ocorre quando dados de &lt;em>benchmark&lt;/em> são deliberadamente incluídos no treinamento, com o objetivo de melhorar o desempenho do modelo em tarefas específicas &lt;a href="#ref1">[1]&lt;/a> &lt;a href="#ref3">[3]&lt;/a>. Essa prática pode ocorrer, por exemplo, ao incorporar conjuntos como MATH ou GSM8K com o propósito de otimizar a performance em raciocínio matemático &lt;a href="#ref6">[6]&lt;/a>. Embora esse uso possa ser justificável como dado supervisionado, sua posterior reutilização como &lt;em>benchmark&lt;/em> invalida a avaliação.&lt;/p>&lt;div style="text-align: center; display: table;"> &lt;img src="https://llm-pt-ibm.github.io/images/contaminacao_intencional.png" alt="Contaminação intencional" caption="" style="max-width: 80%; box-shadow: none;"> &lt;p style="margin-top: 0.3em; font-size: 0.8em; font-style: italic; color: #000000eb">Exemplo de fluxo de contaminação intencional&lt;/p>&lt;/div>&lt;p>É fundamental que, em casos como esse, haja &lt;strong>transparência na documentação dos modelos&lt;/strong>. &lt;em>benchmarks&lt;/em> utilizados como parte do treinamento não devem ser reaplicados como instrumentos de avaliação. Ainda assim, essa distinção nem sempre é respeitada, especialmente em modelos comerciais cuja documentação é limitada ou inexistente &lt;a href="#ref5">[5]&lt;/a>.&lt;/p>&lt;h2 id="categorias-e-níveis-de-contaminação">Categorias e níveis de contaminação&lt;/h2>&lt;p>A contaminação por dados de &lt;em>benchmark&lt;/em> pode assumir diferentes formas, variando conforme o tipo de conteúdo exposto, o grau de abstração da informação vazada e o estágio do treinamento em que a contaminação ocorre. Essas categorias não são mutuamente exclusivas e frequentemente se combinam, o que torna o fenômeno difícil de rastrear e mitigar.&lt;/p>&lt;p>Em muitos casos, a exposição ocorre devido a um &lt;strong>vazamento de entrada&lt;/strong>, que é quando apenas as entradas dos &lt;em>benchmarks&lt;/em> são expostas ao modelo &lt;a href="#ref4">[4]&lt;/a>, como perguntas, comandos ou &lt;em>prompts&lt;/em>. No entanto, há situações em que tanto as entradas quanto os rótulos ou respostas anotadas estão presentes no treinamento, e essa situação é conhecida como &lt;strong>vazamento de entrada-saída&lt;/strong> &lt;a href="#ref4">[4]&lt;/a>.&lt;/p>&lt;p>Outra forma comum de categorizar a contaminação é quando os modelos são expostos ao &lt;strong>texto bruto&lt;/strong> utilizado na construção de &lt;em>benchmarks&lt;/em> &lt;a href="#ref5">[5]&lt;/a>, como artigos da Wikipedia, decisões judiciais ou descrições técnicas. Complementarmente, há o caso que envolve a &lt;strong>contaminação por diretrizes de anotação&lt;/strong> &lt;a href="#ref5">[5]&lt;/a>, quando o modelo acessa instruções empregadas no processo de rotulagem dos dados. Esse tipo de vazamento pode induzir comportamentos compatíveis com os critérios esperados pelo &lt;em>benchmark&lt;/em>, mesmo sem exposição direta aos exemplos.&lt;/p>&lt;p>Além disso, a contaminação pode ocorrer em diferentes &lt;strong>níveis de abstração&lt;/strong>. No &lt;strong>nível semântico&lt;/strong>, o modelo é exposto a conteúdos conceitualmente semelhantes ou derivados dos &lt;em>benchmarks&lt;/em>, como reformulações, tópicos correlatos ou textos provenientes da mesma fonte &lt;a href="#ref1">[1]&lt;/a>. Essa forma de vazamento pode introduzir vieses temáticos e comprometer a capacidade de generalização do modelo, sendo difícil de detectar por não envolver cópia literal. No &lt;strong>nível informacional&lt;/strong>, o vazamento ocorre por meio de estruturas secundárias associadas ao &lt;em>benchmark&lt;/em>, como distribuições temporais, frequências de rótulos, metadados ou até análises externas sobre o conjunto de dados &lt;a href="#ref1">[1]&lt;/a>. Essas informações, mesmo sem conter o conteúdo principal, podem influenciar sutilmente o comportamento do modelo. No &lt;strong>nível de dados&lt;/strong>, ocorre a exposição literal de exemplos do conjunto de avaliação, mas sem os rótulos correspondentes, o que ainda assim permite que o modelo aprenda padrões específicos do &lt;em>benchmark&lt;/em> &lt;a href="#ref1">[1]&lt;/a>. Já no &lt;strong>nível de rótulos&lt;/strong>, o caso mais crítico, tanto os exemplos quanto os rótulos estão presentes no treinamento, o que favorece memorização direta, reduz a capacidade de generalização e compromete seriamente a validade da avaliação &lt;a href="#ref1">[1]&lt;/a>.&lt;/p>&lt;p>Por fim, a contaminação pode ocorrer em diferentes fases do ciclo de treinamento &lt;a href="#ref5">[5]&lt;/a>. Durante o &lt;strong>pré-treinamento&lt;/strong>, é comum que corpora amplos e não curados incluam trechos relacionados a &lt;em>benchmarks&lt;/em>, por compartilharem fontes comuns. No &lt;strong>ajuste fino supervisionado&lt;/strong>, conjuntos rotulados podem conter instâncias próximas ou idênticas às utilizadas posteriormente nos dados de teste do modelo. Já na &lt;strong>fase pós-implantação&lt;/strong>, dados derivados de interações com usuários ou gerados por outras LLMs também podem introduzir contaminação, especialmente quando reaproveitados para re-treinamento.&lt;/p>&lt;p>Essas diferentes manifestações evidenciam que a contaminação por dados de &lt;em>benchmarks&lt;/em> é um fenômeno multifacetado, que pode ser sutil ou direta, intencional ou não, com impactos relevantes para a validade das avaliações, a comparação entre modelos e a confiabilidade dos sistemas desenvolvidos.&lt;/p>&lt;h2 id="metodologias-de-detecção">Metodologias de detecção&lt;/h2>&lt;p>A identificação de contaminação em &lt;em>benchmarks&lt;/em> exige metodologias específicas, que variam conforme o nível de acesso ao modelo avaliado. Esse acesso costuma ser classificado em três categorias. Modelos &lt;strong>caixa branca&lt;/strong> permitem acesso completo aos pesos e aos dados de treinamento. Modelos &lt;strong>caixa cinza&lt;/strong> têm documentação limitada e expõem distribuições de probabilidade ou valores de log‑probabilidade, mas não os dados originais. Já modelos &lt;strong>caixa preta&lt;/strong> oferecem apenas as respostas finais, sem qualquer visibilidade sobre arquitetura ou treinamento.&lt;/p>&lt;div style="text-align: center; display: table;"> &lt;img src="https://llm-pt-ibm.github.io/images/tipos_de_modelos.png" alt="Tipos de Modelos" caption="" style="max-width: 70%; box-shadow: none;"> &lt;p style="margin-top: 0.3em; font-size: 0.8em; font-style: italic; color: #000000eb">Níveis de acesso a modelos&lt;/p>&lt;/div>&lt;p>Cada configuração impõe limitações próprias e condiciona as técnicas de detecção disponíveis. Metodologias de detecção direta, como busca por duplicação literal ou análise de similaridade semântica, requerem transparência total sobre os dados de treinamento e, portanto, aplicam‑se principalmente a modelos caixa branca &lt;a href="#ref1">[1]&lt;/a> &lt;a href="#ref3">[3]&lt;/a> &lt;a href="#ref4">[4]&lt;/a>. Já metodologias de detecção indireta, focadas em vazamentos comportamentais, manipulação de entrada, perturbações ou evidências temporais, podem ser empregadas inclusive em modelos caixa cinza ou caixa preta, pois não dependem de acesso direto aos dados utilizados no treinamento &lt;a href="#ref3">[3]&lt;/a> &lt;a href="#ref4">[4]&lt;/a>. A seguir, apresentam‑se as principais abordagens descritas na literatura, organizadas de acordo com a origem da evidência e o grau de inferência envolvido.&lt;/p>&lt;h3 id="metodologias-de-detecção-direta">Metodologias de detecção direta&lt;/h3>&lt;p>Algumas metodologias de detecção partem da premissa de que o conjunto de dados utilizado no treinamento do modelo é conhecido ou publicamente acessível. Nesses casos, é possível realizar comparações diretas entre os dados de teste (&lt;em>benchmarks&lt;/em>) e os dados efetivamente utilizados no treinamento, o que permite evidenciar contaminações com alto grau de precisão.&lt;/p>&lt;p>Modelos classificados como &lt;strong>caixa branca&lt;/strong>, como o &lt;a href="https://huggingface.co/TucanoBR" target="_blank" rel="noopener noreferrer">&lt;strong>Tucano&lt;/strong>&lt;/a>, disponibilizam não apenas a arquitetura e os pesos, mas também todo o processo de pré-processamento e os dados utilizados no treinamento, possibilitando esse tipo de verificação. Já para modelos &lt;strong>caixa cinza&lt;/strong>, mesmo entre os de código aberto como o &lt;a href="https://huggingface.co/meta-llama" target="_blank" rel="noopener noreferrer">&lt;strong>LLaMA&lt;/strong>&lt;/a> ou o &lt;a href="https://huggingface.co/mistralai" target="_blank" rel="noopener noreferrer">&lt;strong>Mistral&lt;/strong>&lt;/a>, a ausência dos dados de treinamento impossibilita a aplicação dessas estratégias.&lt;/p>&lt;p>Entre os métodos mais utilizados nesse cenário estão:&lt;/p>&lt;ul>&lt;li>&lt;p>&lt;strong>String matching&lt;/strong>: busca por duplicações exatas entre exemplos do &lt;em>benchmark&lt;/em> e entradas do conjunto de treinamento. Essa técnica utiliza substrings, n‑gramas ou trechos completos, sendo eficiente e de fácil implementação. Embora direta e objetiva, há limitação quanto à identificação de repetições literais, sem capturar variantes semânticas ou paráfrases &lt;a href="#ref4">[4]&lt;/a>.&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;strong>Similaridade via &lt;em>embeddings&lt;/em>&lt;/strong>: utiliza representações vetoriais de sentenças para medir a proximidade semântica entre exemplos do conjunto de treinamento e do &lt;em>benchmark&lt;/em>. Essa técnica permite identificar contaminações menos explícitas, como reformulações e variações estruturais, sendo especialmente útil em casos em que não há duplicações literais. No entanto, além de mais custosa, sua eficácia depende da escolha apropriada do modelo de &lt;em>embeddings&lt;/em> e da métrica de distância utilizada &lt;a href="#ref4">[4]&lt;/a>.&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;strong>Detecção de paráfrases&lt;/strong>: utiliza LLMs ou classificadores especializados para avaliar se exemplos do &lt;em>benchmark&lt;/em> são paráfrases de conteúdos previamente vistos. Essa abordagem é útil quando há suspeita de reformulações, mas exige supervisão humana ou limiares bem definidos para reduzir falsos positivos &lt;a href="#ref4">[4]&lt;/a>.&lt;/p>&lt;/li>&lt;/ul>&lt;p>Essas técnicas são consideradas &lt;strong>concretas e verificáveis&lt;/strong>, pois operam diretamente sobre os dados de treinamento e permitem mensurar de forma clara a sobreposição com os &lt;em>benchmarks&lt;/em>. No entanto, apresentam alto custo metodológico, já que requerem acesso completo aos dados de treinamento e demandam recursos computacionais significativos para análise em larga escala.&lt;/p>&lt;h3 id="metodologias-de-detecção-indireta">Metodologias de detecção indireta&lt;/h3>&lt;p>Em contextos em que os dados de treinamento não são públicos, como no caso de modelos proprietários (&lt;a href="https://chatgpt.com/" target="_blank" rel="noopener noreferrer">&lt;strong>GPT-4&lt;/strong>&lt;/a>, &lt;a href="https://claude.ai/" target="_blank" rel="noopener noreferrer">&lt;strong>Claude&lt;/strong>&lt;/a> ou &lt;a href="https://gemini.google.com/" target="_blank" rel="noopener noreferrer">&lt;strong>Gemini&lt;/strong>&lt;/a>), não é possível realizar comparações diretas com os &lt;em>benchmarks&lt;/em>. Nessas situações, a detecção de contaminação depende de evidências indiretas, geralmente obtidas por meio de inferência estatística, análise cronológica ou observação de comportamentos em tarefas específicas.&lt;/p>&lt;p>Essas abordagens são especialmente relevantes em modelos classificados como &lt;strong>caixa preta&lt;/strong> e &lt;strong>caixa cinza&lt;/strong>, nos quais não há acesso aos dados de treinamento. Ainda assim, também podem ser aplicadas a modelos &lt;strong>caixa branca&lt;/strong>, especialmente em análises comparativas, complementares ou em cenários de validação cruzada.&lt;/p>&lt;p>As principais estratégias empregadas nesse cenário incluem:&lt;/p>&lt;ul>&lt;li>&lt;p>&lt;strong>Análise cronológica&lt;/strong>: busca comparar o desempenho do modelo em &lt;em>benchmarks&lt;/em> publicados em momentos distintos. Uma melhora abrupta em &lt;em>benchmarks&lt;/em> liberados após a data de corte do treinamento pode sugerir exposição posterior ao conteúdo de teste &lt;a href="#ref4">[4]&lt;/a>.&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;strong>Análise comportamental&lt;/strong>: avalia se o modelo responde corretamente a variações nos exemplos do &lt;em>benchmark&lt;/em>, como &lt;em>prompts&lt;/em> truncados, reordenados ou parafraseados. Técnicas como o &lt;strong>TS-Guessing&lt;/strong> exploram esse princípio para detectar memorização implícita &lt;a href="#ref2">[2]&lt;/a> &lt;a href="#ref4">[4]&lt;/a>.&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;strong>Inferência por confiança&lt;/strong>: abrange métodos que estimam a presença de exemplos de treinamento com base no padrão de respostas do modelo. Técnicas como os &lt;strong>Membership Inference Attacks (MIA)&lt;/strong> e o &lt;strong>BenBench&lt;/strong> comparam o grau de confiança ou perplexidade do modelo em exemplos suspeitos em relação a exemplos sabidamente fora do treinamento. Uma concentração anormal de confiança ou variação de perplexidade em itens específicos pode indicar memorização &lt;a href="#ref4">[4]&lt;/a> &lt;a href="#ref6">[6]&lt;/a>.&lt;/p>&lt;/li>&lt;/ul>&lt;p>Essas metodologias são úteis para detectar contaminação em modelos sem transparência sobre seus dados de origem, mas envolvem maior grau de incerteza. Por dependerem de inferências comportamentais ou contextuais, os resultados exigem interpretação cuidadosa, especialmente quando utilizados de forma isolada. Ainda assim, úteis para a avaliação de modelos comerciais ou sem documentação disponível.&lt;/p>&lt;h3 id="ferramentas-auxiliares-na-detecção-de-contaminação">Ferramentas auxiliares na detecção de contaminação&lt;/h3>&lt;p>Com o aumento da preocupação em torno da contaminação por dados de &lt;em>benchmarks&lt;/em>, diversas ferramentas têm sido desenvolvidas para automatizar e padronizar estratégias de detecção. Essas ferramentas integram métodos complementares baseados em correspondência literal, similaridade semântica, comportamento do modelo e análises estatísticas, permitindo investigações mais robustas mesmo em contextos com acesso restrito aos dados ou aos parâmetros dos modelos.&lt;/p>&lt;p>O &lt;a href="https://github.com/ntunlp/LLMSanitize" target="_blank" rel="noopener noreferrer">&lt;strong>LLMSanitize&lt;/strong>&lt;/a> implementa diversas técnicas descritas em diferentes estudos, oferecendo métodos voltados a modelos &lt;strong>caixa branca&lt;/strong>, como &lt;em>string matching&lt;/em>, truncamento de entrada e avaliação semântica com LLMs, bem como estratégias para modelos &lt;strong>caixa cinza&lt;/strong> e &lt;strong>caixa preta&lt;/strong>, como o &lt;strong>TS-Guessing&lt;/strong> e o &lt;strong>Sharded Likelihood&lt;/strong>, metodologias baseadas em análise comportamental.&lt;/p>&lt;p>Algumas ferramentas são voltadas a metodologias específicas. O &lt;a href="https://github.com/GAIR-NLP/benbench" target="_blank" rel="noopener noreferrer">&lt;strong>BenBench&lt;/strong>&lt;/a>, por exemplo, busca sinais de memorização implícita por meio da análise de perplexidade, similaridade e acurácia em versões originais e parafraseadas de &lt;em>benchmarks&lt;/em>, sendo especialmente útil na avaliação de modelos &lt;strong>caixa preta&lt;/strong> ou &lt;strong>caixa cinza&lt;/strong>. O &lt;a href="https://github.com/eth-sri/ConStat" target="_blank" rel="noopener noreferrer">&lt;strong>ConStat&lt;/strong>&lt;/a> é voltado à comparação estatística entre o desempenho do modelo em dados suspeitos e em outros &lt;em>benchmarks&lt;/em> similares, visando detectar padrões de desempenho atípicos. Já o &lt;a href="https://github.com/YihongDong/CDD-TED4LLMs" target="_blank" rel="noopener noreferrer">&lt;strong>CDD-TED&lt;/strong>&lt;/a> propõe o uso de &lt;em>benchmarks&lt;/em> diagnósticos controlados para examinar discrepâncias na distribuição de confiança e entropia das respostas, oferecendo evidências indiretas de contaminação.&lt;/p>&lt;p>Essas ferramentas representam meios práticos e sistemáticos para detectar exposições em diferentes níveis.&lt;/p>&lt;h2 id="conclusão">Conclusão&lt;/h2>&lt;p>A contaminação por dados de &lt;em>benchmark&lt;/em> constitui um desafio relevante para a avaliação justa de modelos de linguagem. Como discutido ao longo do texto, esse fenômeno compromete a validade das métricas, dificulta comparações entre LLMs e pode levar à adoção de modelos com desempenho superestimado em aplicações reais.&lt;/p>&lt;p>Para mitigar a contaminação, diversas estratégias têm sido indicadas na literatura. Entre elas, destacam-se a reformulação de &lt;em>benchmarks&lt;/em> por meio de técnicas como &lt;em>paraphrasing&lt;/em> e &lt;em>back-translation&lt;/em>, a criação de conjuntos de teste dinâmicos, o uso de avaliações mediadas por modelos de linguagem mais robustos e a implementação de &lt;em>benchmarks&lt;/em> privados com acesso controlado. No entanto, essas soluções ainda enfrentam limitações práticas, especialmente em idiomas sub-representados, nos quais a variedade e a qualidade dos dados disponíveis são restritas.&lt;/p>&lt;p>Este artigo apresentou uma caracterização geral da contaminação por dados de &lt;em>benchmark&lt;/em>, abordando suas causas, impactos e principais metodologias de detecção. Como continuidade, serão conduzidos estudos empíricos com foco em idiomas sub-representados. Embora a maioria dos trabalhos existentes se concentre em idiomas amplamente representados nos dados globais, como o inglês e o chinês, há indícios de que o problema seja ainda mais crítico em línguas com menor presença nos repositórios de treinamento. A escassez de &lt;em>benchmarks&lt;/em> exclusivos e a ampla reutilização de fontes públicas aumentam a probabilidade de sobreposição entre dados de treinamento e teste nesse contexto.&lt;/p>&lt;p>Tomando o português brasileiro como exemplo de idioma sub-representado, os estudos futuros utilizarão modelos multilíngues e especializados no idioma, com o objetivo de estimar o grau de exposição a dados de avaliação e contribuir para práticas mais consistentes de validação e comparação entre modelos.&lt;/p>&lt;h2 id="referências">Referências&lt;/h2>&lt;p>&lt;a name="ref1">[1]&lt;/a> Cheng Xu, Shuhao Guan, Derek Greene, and M-Tahar Kechadi. 2024. &lt;em>Benchmark Data Contamination of Large Language Models: A Survey&lt;/em>. arXiv preprint arXiv:2406.04244.&lt;/p>&lt;p>&lt;a name="ref2">[2]&lt;/a> Chunyuan Deng, Yilun Zhao, Xiangru Tang, Mark Gerstein, and Arman Cohan. 2024. &lt;em>Investigating Data Contamination in Modern Benchmarks for Large Language Models&lt;/em>. In &lt;em>Proceedings of the 2024 Conference of the North American Chapter of the Association for Computational Linguistics: Human Language Technologies (Volume 1: Long Papers)&lt;/em>, pages 8706–8719, Mexico City, Mexico. Association for Computational Linguistics.&lt;/p>&lt;p>&lt;a name="ref3">[3]&lt;/a> Chunyuan Deng, Yilun Zhao, Yuzhao Heng, Yitong Li, Jiannan Cao, Xiangru Tang, and Arman Cohan. 2024. &lt;em>Unveiling the Spectrum of Data Contamination in Language Model: A Survey from Detection to Remediation&lt;/em>. In &lt;em>Findings of the Association for Computational Linguistics: ACL 2024&lt;/em>, pages 16078–16092, Bangkok, Thailand. Association for Computational Linguistics.&lt;/p>&lt;p>&lt;a name="ref4">[4]&lt;/a> Mathieu Ravaut, Bosheng Ding, Fangkai Jiao, Hailin Chen, Xingxuan Li, Ruochen Zhao, Chengwei Qin, Caiming Xiong, and Shafiq Joty. 2024. &lt;em>How much are LLMs contaminated? A Comprehensive Survey and the LLMSanitize Library&lt;/em>. arXiv preprint arXiv:2404.00699.&lt;/p>&lt;p>&lt;a name="ref5">[5]&lt;/a> Oscar Sainz, Jon Campos, Iker García-Ferrero, Julen Etxaniz, Oier Lopez de Lacalle, and Eneko Agirre. 2023. &lt;em>NLP Evaluation in Trouble: On the Need to Measure LLM Data Contamination for Each Benchmark&lt;/em>. In &lt;em>Findings of the Association for Computational Linguistics: EMNLP 2023&lt;/em>, pages 10776–10787, Singapore. Association for Computational Linguistics.&lt;/p>&lt;p>&lt;a name="ref6">[6]&lt;/a> Ruijie Xu, Zengzhi Wang, Run-Ze Fan, and Pengfei Liu. 2024. &lt;em>Benchmarking Benchmark Leakage in Large Language Models&lt;/em>. arXiv preprint arXiv:2404.18824.&lt;/p>&lt;p>&lt;a name="ref7">[7]&lt;/a> Simone Balloccu, Patrícia Schmidtová, Mateusz Lango, and Ondrej Dusek. 2024. &lt;em>Leak, Cheat, Repeat: Data Contamination and Evaluation Malpractices in Closed-Source LLMs&lt;/em>. In &lt;em>Proceedings of the 18th Conference of the European Chapter of the Association for Computational Linguistics (Volume 1: Long Papers)&lt;/em>, pages 67–93, St. Julian’s, Malta. Association for Computational Linguistics.&lt;/p></description></item><item><title>Computação@UFCG lidera contribuições do Brasil ao framework HELM-Stanford em parceria com a IBM</title><link>https://llm-pt-ibm.github.io/posts/contribuicao_helm/</link><pubDate>Wed, 09 Jul 2025 00:00:00 +0000</pubDate><guid>https://llm-pt-ibm.github.io/posts/contribuicao_helm/</guid><description>&lt;p>&lt;strong>Colaboração entre Ciência da Computação da UFCG e a IBM faz da universidade a maior contribuinte brasileira para o &lt;em>framework&lt;/em> de avaliação &lt;a href="https://github.com/stanford-crfm/helm" rel="external">&lt;span class="link-personalizado">HELM-Stanford&lt;/span>&lt;/a> em 2025.&lt;/strong>&lt;/p>&lt;p>O HELM-Stanford é um dos principais &lt;em>frameworks&lt;/em> globais para avaliar modelos de linguagem, medindo precisão, robustez e responsabilidade. Ser a maior contribuinte brasileira — por meio da parceria entre Computação@UFCG e a IBM — destaca o protagonismo nacional na construção de métricas mais justas, seguras e representativas para LLMs, especialmente em contextos multilíngues e culturais diversos.&lt;/p>&lt;p>A parceria entre Computação@UFCG e a IBM resultou em 15 contribuições significativas ao HELM-Stanford em 2025. Essas contribuições incluem a adição de benchmarks voltados à língua portuguesa, correções de bugs, melhorias no código-fonte e a inclusão de novos conjuntos de avaliação, ampliando a diversidade linguística e a robustez do framework.&lt;/p>&lt;p>O projeto coordenado pelo professor João Brunet, com participação dos professores Fábio Morais e Leandro Balby, conta com uma equipe multidisciplinar dedicada à avaliação de LLMs. Participam também um professor do IFPB, três alunos de pós-graduação, três de graduação e um profissional com experiência em desenvolvimento de software. A IBM, parceira no projeto, também destaca profissionais para atuarem diretamente na colaboração. Juntos, o grupo tem contribuído de forma expressiva para o avanço do HELM-Stanford, com foco na inclusão da língua portuguesa e na melhoria contínua do &lt;em>framework&lt;/em>.&lt;/p>&lt;figure>&lt;img src="https://llm-pt-ibm.github.io/images/carvalheira.jpeg" alt="Equipe multidisciplinar do projeto"/>&lt;figcaption> &lt;p>Equipe multidisciplinar do projeto&lt;/p> &lt;/figcaption>&lt;/figure></description></item><item><title>API de inferência de Modelos de Linguagem no servidor Power9 IBM</title><link>https://llm-pt-ibm.github.io/posts/tutorial_power9_pt4_en/</link><pubDate>Thu, 03 Jul 2025 00:00:00 +0000</pubDate><guid>https://llm-pt-ibm.github.io/posts/tutorial_power9_pt4_en/</guid><description>&lt;h2 id="contexto">Contexto&lt;/h2>&lt;p>Este é o quarto e último post de uma série de tutoriais cujo objetivo é mostrar passo a passo como construir uma API de Modelos de Linguagem em um servidor Power9, desde a configuração do sistema operacional até a execução remota de inferências. Já configuramos o sistema operacional, os drivers NVIDIA, CUDA e cuDNN no &lt;a href="https://llm-pt-ibm.github.io/posts/tutorial_power9_pt1_en/">&lt;span class="link-personalizado">primeiro post&lt;/span>&lt;/a>, no &lt;a href="https://llm-pt-ibm.github.io/posts/tutorial_power9_pt2_en/">&lt;span class="link-personalizado">segundo post&lt;/span>&lt;/a> instalamos Conda e PyTorch e no &lt;a href="https://llm-pt-ibm.github.io/posts/tutorial_power9_pt3_en/">&lt;span class="link-personalizado">terceiro post&lt;/span>&lt;/a> construímos a API. Nesta etapa, vamos apresentar a API construída e mostrar como realizar requisições.&lt;/p>&lt;h2 id="tldr">TL;DR&lt;/h2>&lt;ul>&lt;li>Este post apresenta a API de inferência de LLMs construída e como utilizar.&lt;/li>&lt;li>Vamos mostrar como realizar requisições via python e curl.&lt;/li>&lt;/ul>&lt;h2 id="apresentando-a-api">Apresentando a API&lt;/h2>&lt;p>Esta API foi desenvolvida para expor modelos de linguagem de grande porte para inferência remota. Permite ao usuário carregar modelos específicos, mantê-los na memória da GPU para chamadas sucessivas e gerar texto a partir de prompts enviados via requisição HTTP. Foi implementada em FastAPI e inclui controle de acesso via API Key, gerenciamento de memória (carregar e descarregar modelos), suporte a múltiplas GPUs com sharding automático e endpoints para consulta de status. O objetivo é oferecer um serviço robusto, otimizado para uso intensivo, garantindo rapidez nas inferências e facilidade de integração com aplicações externas.&lt;/p>&lt;h4 id="visão-geral-da-arquitetura">Visão Geral da Arquitetura&lt;/h4>&lt;p>A API expõe modelos de linguagem via FastAPI com endpoints REST. O ModelManager gerencia o carregamento, descarregamento e a inferência dos modelos, mantendo-os em GPU para chamadas rápidas. A autenticação é feita por API Key. A arquitetura suporta múltiplas GPUs com sharding automático para otimizar o uso de memória e desempenho. Os modelos são importados do HuggingFace e utiliza a biblioteca Transformers para execução de inferências.&lt;/p>&lt;figure>&lt;img src="https://llm-pt-ibm.github.io/images/arquitetura_api_llm_01.png" alt="Descrição alternativa"/>&lt;figcaption> &lt;p>Diagrama da arquitetura&lt;/p> &lt;/figcaption>&lt;/figure>&lt;h4 id="principais-funcionalidades">Principais Funcionalidades&lt;/h4>&lt;ul>&lt;li>&lt;p>&lt;strong>Carregar Modelos&lt;/strong>&lt;/p>&lt;ul>&lt;li>&lt;code>/load_model&lt;/code>&lt;/li>&lt;li>Carrega modelo do HuggingFace Hub&lt;/li>&lt;li>Faz sharding para as GPUs&lt;/li>&lt;li>Suporte ao HuggingFace Token&lt;/li>&lt;/ul>&lt;/li>&lt;li>&lt;p>&lt;strong>Gerar Texto&lt;/strong>&lt;/p>&lt;ul>&lt;li>&lt;code>/generate&lt;/code>&lt;/li>&lt;li>Recebe prompt, max_tokens, nome do modelo, temperatura e top_p&lt;/li>&lt;li>Usa modelo já carregado ou carrega um novo&lt;/li>&lt;li>Retorna resultado em JSON&lt;/li>&lt;/ul>&lt;/li>&lt;li>&lt;p>&lt;strong>Gerenciamento&lt;/strong>&lt;/p>&lt;ul>&lt;li>&lt;code>/status&lt;/code>: Verifica modelo carregado em device (CPU/GPU)&lt;/li>&lt;li>&lt;code>/unload_model&lt;/code>: libera GPU e memória&lt;/li>&lt;li>&lt;code>/generate_apikey&lt;/code>: cria chaves a partir de usuário LDAP&lt;/li>&lt;/ul>&lt;/li>&lt;/ul>&lt;h4 id="fluxo-de-uso">Fluxo de Uso&lt;/h4>&lt;figure>&lt;img src="https://llm-pt-ibm.github.io/images/arquitetura_api_llm_02.png" alt="Descrição alternativa"/>&lt;figcaption> &lt;p>Diagrama do fluxo de uso&lt;/p> &lt;/figcaption>&lt;/figure>&lt;h4 id="entradas-e-endpoints">Entradas e Endpoints&lt;/h4>&lt;p>Na tabela abaixo estão descritos o endpoints da API, entradas necessárias e retornos.&lt;/p>&lt;style>table { border-collapse: collapse; width: 100%;}th { background-color: #cccccc; text-align: center; padding: 8px; border: 1px solid #b3b3b3;}td { padding: 8px; border: 1px solid #ccc; text-align: left;}td.center { text-align: center;}caption { caption-side: bottom}&lt;/style>&lt;table> &lt;caption>Tabela de endpoints e entradas &lt;thead> &lt;tr> &lt;th>Endpoints&lt;/th> &lt;th>Método&lt;/th> &lt;th>Api Key&lt;/th> &lt;th>Entrada (Body/Query)&lt;/th> &lt;th>Retorno&lt;/th> &lt;/tr> &lt;/thead> &lt;tbody> &lt;tr> &lt;td>&lt;code>/generate_apikey&lt;/code>&lt;/td> &lt;td class="center">POST&lt;/td> &lt;td class="center">❌&lt;/td> &lt;td class="center">{username}&lt;/td> &lt;td class="center">API Key&lt;/td> &lt;/tr> &lt;tr> &lt;td>&lt;code>/load_model&lt;/code>&lt;/td> &lt;td class="center">POST&lt;/td> &lt;td class="center">✅&lt;/td> &lt;td class="center">{model_name &lt;br> hf_token(opcional) &lt;br> device(opcional)}&lt;/td> &lt;td class="center">Nenhum, apenas carrega o modelo&lt;/td> &lt;/tr> &lt;tr> &lt;td>&lt;code>/generate&lt;/code>&lt;/td> &lt;td class="center">POST&lt;/td> &lt;td class="center">✅&lt;/td> &lt;td class="center">{model_name &lt;br> prompt &lt;br> hf_token(opcional) &lt;br> max_tokens(opcional) &lt;br> temperature(opcional) &lt;br> top_p(opcional)}&lt;/td> &lt;td class="center">Texto gerado pelo modelo&lt;/td> &lt;/tr> &lt;tr> &lt;td>&lt;code>/status&lt;/code>&lt;/td> &lt;td class="center">GET&lt;/td> &lt;td class="center">✅&lt;/td> &lt;td class="center">Nenhuma&lt;/td> &lt;td class="center">Status do modelo e dispositivo que ele está carregado&lt;/td> &lt;/tr> &lt;tr> &lt;td>&lt;code>/unload_model&lt;/code>&lt;/td> &lt;td class="center">POST&lt;/td> &lt;td class="center">✅&lt;/td> &lt;td class="center">Nenhuma&lt;/td> &lt;td class="center">Nenhum, apenas descarrega o modelo&lt;/td> &lt;/tr> &lt;/tbody>&lt;/table>&lt;h2 id="como-usar-a-api-com-python">Como usar a API com Python&lt;/h2>&lt;h4 id="gerar-api-key">Gerar API Key&lt;/h4>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1&lt;/span>&lt;span>&lt;span style="color:#f92672">import&lt;/span> requests&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2&lt;/span>&lt;span>&lt;span style="color:#f92672">import&lt;/span> json&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3&lt;/span>&lt;span>&lt;span style="color:#f92672">import&lt;/span> os&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5&lt;/span>&lt;span>url &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;http://&amp;lt;ip_servidor_power9&amp;gt;:8000/&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6&lt;/span>&lt;span>username &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span>usuario_ldap&lt;span style="color:#f92672">&amp;gt;&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7&lt;/span>&lt;span>hf_token &lt;span style="color:#f92672">=&lt;/span> os&lt;span style="color:#f92672">.&lt;/span>getenv(&lt;span style="color:#e6db74">&amp;#34;HUGGINGFACE_TOKEN&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9&lt;/span>&lt;span>response &lt;span style="color:#f92672">=&lt;/span> requests&lt;span style="color:#f92672">.&lt;/span>post(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>url&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/generate_apikey&amp;#34;&lt;/span>, json&lt;span style="color:#f92672">=&lt;/span>{&lt;span style="color:#e6db74">&amp;#34;username&amp;#34;&lt;/span>: username})&lt;span style="color:#f92672">.&lt;/span>content&lt;span style="color:#f92672">.&lt;/span>decode()&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11&lt;/span>&lt;span>api_key &lt;span style="color:#f92672">=&lt;/span> json&lt;span style="color:#f92672">.&lt;/span>loads(response)&lt;span style="color:#f92672">.&lt;/span>get(&lt;span style="color:#e6db74">&amp;#34;api_key&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>&lt;li>É importante que o HuggingFace Token esteja definido como variável de ambiente no local em que esteja executando a inferência.&lt;/li>&lt;li>&lt;code>api_key&lt;/code> será o retorno da função chamada.&lt;/li>&lt;/ul>&lt;h4 id="carregar-modelo">Carregar Modelo&lt;/h4>&lt;p>Primeiramente precisamos criar um header que irá conter a API Key retornada com o código acima e o payload que irá conter o &lt;code>model_name&lt;/code> o token do huggingface &lt;code>hf_token&lt;/code>. Após isso, podemos enviar a requisições com essas duas informações.&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1&lt;/span>&lt;span>headers &lt;span style="color:#f92672">=&lt;/span> {&lt;span style="color:#e6db74">&amp;#34;Content-Type&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;application/json&amp;#34;&lt;/span>,&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2&lt;/span>&lt;span>&lt;span style="color:#e6db74">&amp;#34;x-api-key&amp;#34;&lt;/span>: api_key}&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4&lt;/span>&lt;span>payload &lt;span style="color:#f92672">=&lt;/span> {&lt;span style="color:#e6db74">&amp;#34;model_name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;ibm-granite/granite-3.3-8b-instruct&amp;#34;&lt;/span>,&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5&lt;/span>&lt;span> &lt;span style="color:#e6db74">&amp;#34;hf_token&amp;#34;&lt;/span>: hf_token}&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7&lt;/span>&lt;span>resp &lt;span style="color:#f92672">=&lt;/span> requests&lt;span style="color:#f92672">.&lt;/span>post(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>url&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/load_model&amp;#34;&lt;/span>, headers&lt;span style="color:#f92672">=&lt;/span>headers, json&lt;span style="color:#f92672">=&lt;/span>payload)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="gerar-texto">Gerar Texto&lt;/h4>&lt;p>Agora precisamos criar um novo payload com as informações necessárias para gerar um texto com uma llm, são elas: &lt;code>prompt&lt;/code>, &lt;code>model_name&lt;/code> e &lt;code>hf_token&lt;/code>.&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1&lt;/span>&lt;span>payload &lt;span style="color:#f92672">=&lt;/span> {&lt;span style="color:#e6db74">&amp;#34;prompt&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;Olá, me fale um pouco sobre a Universidade Federal de Campina Grande (UFCG)&amp;#34;&lt;/span>,&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2&lt;/span>&lt;span> &lt;span style="color:#e6db74">&amp;#34;model_name&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">&amp;#34;ibm-granite/granite-3.3-8b-instruct&amp;#34;&lt;/span>,&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3&lt;/span>&lt;span> &lt;span style="color:#e6db74">&amp;#34;hf_token&amp;#34;&lt;/span>: hf_token}&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5&lt;/span>&lt;span>resp &lt;span style="color:#f92672">=&lt;/span> requests&lt;span style="color:#f92672">.&lt;/span>post(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>url&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/generate&amp;#34;&lt;/span>, headers&lt;span style="color:#f92672">=&lt;/span>headers, json&lt;span style="color:#f92672">=&lt;/span>payload)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7&lt;/span>&lt;span>resp &lt;span style="color:#f92672">=&lt;/span> json&lt;span style="color:#f92672">.&lt;/span>loads(resp&lt;span style="color:#f92672">.&lt;/span>content&lt;span style="color:#f92672">.&lt;/span>decode())&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="consultar-status-e-descarregar-o-modelo">Consultar status e descarregar o modelo&lt;/h4>&lt;p>Para consultar o status e descarregar o modelo não precisamos passar conteúdo pelo payload, apenas o header com a API key:&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1&lt;/span>&lt;span>requests&lt;span style="color:#f92672">.&lt;/span>get(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>url&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/status&amp;#34;&lt;/span>, headers&lt;span style="color:#f92672">=&lt;/span>headers)&lt;span style="color:#f92672">.&lt;/span>content&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1&lt;/span>&lt;span>resp &lt;span style="color:#f92672">=&lt;/span> requests&lt;span style="color:#f92672">.&lt;/span>post(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">{&lt;/span>url&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">/unload_model&amp;#34;&lt;/span>, headers&lt;span style="color:#f92672">=&lt;/span>headers)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="como-usar-a-api-com-curl-em-cli">Como usar a API com curl em CLI&lt;/h2>&lt;h4 id="gerar-api-key-1">Gerar API Key&lt;/h4>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl -X POST &lt;span style="color:#e6db74">&amp;#34;http://&amp;lt;ip_servidor_power9&amp;gt;:8000/generate_apikey&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -H &lt;span style="color:#e6db74">&amp;#34;Content-Type: application/json&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -d &lt;span style="color:#e6db74">&amp;#39;{&amp;#34;username&amp;#34;: &amp;lt;usuario_ldap&amp;gt;}&amp;#39;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>&lt;li>É importante que o HuggingFace Token esteja definido como variável de ambiente no local em que esteja executando a inferência.&lt;/li>&lt;li>O usuário no campo de &lt;code>username&lt;/code> deve estar entre aspas (&amp;quot; &amp;ldquo;)&lt;/li>&lt;li>Após executar a requisição acima, a API key retornada deverá ser salva como variável de ambiente para facilitar as próximas execuções. Para salvar você deve copiar a API key retornada e executar o comando:&lt;/li>&lt;/ul>&lt;pre tabindex="0">&lt;code>export API_KEY_P9=&amp;lt;api_key_retornada&amp;gt;&lt;/code>&lt;/pre>&lt;h4 id="carregar-modelo-1">Carregar Modelo&lt;/h4>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl -X POST &lt;span style="color:#e6db74">&amp;#34;http://&amp;lt;ip_servidor_power9&amp;gt;:8000/load_model&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -H &lt;span style="color:#e6db74">&amp;#34;Content-Type: application/json&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -H &lt;span style="color:#e6db74">&amp;#34;x-api-key: &lt;/span>$API_KEY&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -d &lt;span style="color:#e6db74">&amp;#39;{&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> &amp;#34;model_name&amp;#34;:&amp;#34;ibm-granite/granite-3.3-8b-instruct&amp;#34;,&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> &amp;#34;hf_token&amp;#34;:&amp;#34;&amp;#39;&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>$HUGGINGFACE_TOKEN&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">&amp;#39;&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> }&amp;#39;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="gerar-texto-1">Gerar Texto&lt;/h4>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl -X POST &lt;span style="color:#e6db74">&amp;#34;http://&amp;lt;ip_servidor_power9&amp;gt;:8000/generate&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -H &lt;span style="color:#e6db74">&amp;#34;Content-Type: application/json&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -H &lt;span style="color:#e6db74">&amp;#34;x-api-key: &lt;/span>$API_KEY&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -d &lt;span style="color:#e6db74">&amp;#39;{&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> &amp;#34;model_name&amp;#34;: &amp;#34;ibm-granite/granite-3.3-8b-instruct&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> &amp;#34;prompt&amp;#34;:&amp;#34;Olá, me fale um pouco sobre a Universidade Federal de Campina Grande (UFCG)&amp;#34;,&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> &amp;#34;hf_token&amp;#34;: &amp;#34;&amp;#39;&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>$HUGGINGFACE_TOKEN&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#e6db74">&amp;#39;&amp;#34;,&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> &amp;#34;max_tokens&amp;#34;:50&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74"> }&amp;#39;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="consultar-status-e-descarregar-o-modelo-1">Consultar status e descarregar o modelo&lt;/h4>&lt;p>Para consultar o status e descarregar o modelo não precisamos passar conteúdo pelo payload, apenas o header com a API key:&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl -X GET &lt;span style="color:#e6db74">&amp;#34;http://&amp;lt;ip_servidor_power9&amp;gt;:8000/status&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -H &lt;span style="color:#e6db74">&amp;#34;Content-Type: application/json&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -H &lt;span style="color:#e6db74">&amp;#34;x-api-key: &lt;/span>$API_KEY&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>curl -X POST &lt;span style="color:#e6db74">&amp;#34;http://&amp;lt;ip_servidor_power9&amp;gt;:8000/unload_model&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -H &lt;span style="color:#e6db74">&amp;#34;Content-Type: applicatzion/json&amp;#34;&lt;/span> &lt;span style="color:#ae81ff">\&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">&lt;/span> -H &lt;span style="color:#e6db74">&amp;#34;x-api-key: &lt;/span>$API_KEY&lt;span style="color:#e6db74">&amp;#34;&lt;/span> &lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Esperamos que estes posts tenham ajudado a esclarecer todo o processo de desenvolvimento e implantação. O time LLM-IBM-UFCG está à disposição para dúvidas ou sugestões sobre aprimoramentos futuros.&lt;/p></description></item><item><title>Construindo API para inferências de LLMs em um servidor IBM Power9</title><link>https://llm-pt-ibm.github.io/posts/tutorial_power9_pt3_en/</link><pubDate>Wed, 02 Jul 2025 00:00:00 +0000</pubDate><guid>https://llm-pt-ibm.github.io/posts/tutorial_power9_pt3_en/</guid><description>&lt;h2 id="contexto">Contexto&lt;/h2>&lt;p>Este é o terceiro post de uma série de tutoriais cujo objetivo é mostrar passo a passo como construir uma API de Modelos de Linguagem em um servidor Power9, desde a configuração do sistema operacional até a execução remota de inferências. Já configuramos o sistema operacional, os drivers NVIDIA, CUDA e cuDNN no &lt;a href="https://llm-pt-ibm.github.io/posts/tutorial_power9_pt1_en/">&lt;span class="link-personalizado">primeiro post&lt;/span>&lt;/a>, e no &lt;a href="https://llm-pt-ibm.github.io/posts/tutorial_power9_pt2_en/">&lt;span class="link-personalizado">segundo post&lt;/span>&lt;/a> instalamos Conda e PyTorch. Nesta etapa, vamos construir a API usando FastAPI e a biblioteca Transformers, baixando modelos do Hugging Face e executando o servidor web com uvicorn.&lt;/p>&lt;p>A API implementada terá as funcionalidades de gerar API Key, carregar modelos, realizar inferências, obter status e desccaregar modelos.&lt;/p>&lt;p>&lt;strong>FastAPI&lt;/strong>: Framework web moderno para construção de APIs com Python 3.8+, baseado em tipagem estática e assíncrona. Foi projetado para ser rápido, fácil de usar e robusto, tornando o desenvolvimento de APIs mais eficiente.&lt;/p>&lt;p>&lt;strong>Transformers&lt;/strong>: Biblioteca de código aberto desenvolvida pela Hugging Face. Fornece acesso prático e eficiente a uma ampla coleção de modelos pré-treinados de última geração para Processamento de Linguagem Natural (PLN), visão computacional e áudio.&lt;/p>&lt;p>&lt;strong>Hugging Face&lt;/strong>: Hugging Face é uma plataforma focada em inteligência artificial, conhecida por hospedar modelos de NLP e outras tarefas. O Hugging Face Hub é um repositório colaborativo onde desenvolvedores e pesquisadores podem compartilhar, versionar e baixar modelos prontos para uso, facilitando o acesso e integração de modelos.&lt;/p>&lt;p>&lt;strong>Uvicorn&lt;/strong>: Servidor web ASGI (Asynchronous Server Gateway Interface). O Uvicorn é um servidor de alta performance para aplicações Python assíncronas.&lt;/p>&lt;h2 id="tldr">TL;DR&lt;/h2>&lt;ul>&lt;li>Este post apresenta o passo a passo para implementar uma API que realiza inferências de Grandes Modelos de Linguagem.&lt;/li>&lt;li>Usaremos FastAPI e Transformers para desenvolver essa API e Hugging Face para baixar os modelos.&lt;/li>&lt;/ul>&lt;h2 id="configuração-do-ambiente">Configuração do Ambiente&lt;/h2>&lt;h4 id="estrutura-de-diretórios">Estrutura de Diretórios&lt;/h4>&lt;p>Primeiro, vamos criar a estrutura básica do projeto:&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-txt" data-lang="txt">&lt;span style="display:flex;">&lt;span>model_api/&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── requirements.txt&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>├── app/&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── __init__.py&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── main.py&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── schemas.py&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── auth.py&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── model_manager.py&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ ├── utils.py&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>│ └── apikey_store.json&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>└── README.md (opcional)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="arquivo-requirementstxt">Arquivo &lt;code>requirements.txt&lt;/code>&lt;/h4>&lt;p>Vamos usar FastAPI e Transformers para implementar a API. Além disso, usaremos uvicorn para executar o servidor, pydantic para validação de dados de entrada e torch, que já instalamos no &lt;a href="https://llm-pt-ibm.github.io/posts/tutorial_power9_pt2_en/">tutorial anterior&lt;/a>.&lt;/p>&lt;p>Primeiro, vamos instalar as bibliotecas necessárias e depois preencher o arquivo &lt;code>requirements.txt&lt;/code>. Lembre-se de ativar o ambiente &lt;code>conda&lt;/code> se você o criou, para garantir o uso correto do &lt;code>pytorch&lt;/code>.&lt;/p>&lt;pre tabindex="0">&lt;code>conda activate llm_apipip install fastapi uvicorn transformers&lt;/code>&lt;/pre>&lt;p>O arquivo &lt;code>requirements.txt&lt;/code> ficará assim:&lt;/p>&lt;p>&lt;strong>requirements.txt&lt;/strong>&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-txt" data-lang="txt">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1&lt;/span>&lt;span>fastapi&amp;gt;=0.104.0&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2&lt;/span>&lt;span>uvicorn&amp;gt;=0.24.0&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3&lt;/span>&lt;span>torch&amp;gt;=2.0.0&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4&lt;/span>&lt;span>transformers&amp;gt;=4.35.0&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5&lt;/span>&lt;span>pydantic&amp;gt;=2.0.0&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="arquivo-de-armazenamento-de-api-keys">Arquivo de Armazenamento de API Keys&lt;/h4>&lt;p>O arquivo &lt;code>apikey_store.json&lt;/code> será usado para armazenar as chaves de API geradas. Vamos iniciá-lo vazio, contendo apenas &lt;code>{}&lt;/code>.&lt;/p>&lt;p>&lt;strong>apikey_store.json&lt;/strong>&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1&lt;/span>&lt;span>{}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="schemas-e-validação-de-dados">Schemas e validação de dados&lt;/h2>&lt;p>Os schemas são essenciais para validar os dados de entrada e saída da API. Eles garantem que os dados estejam no formato correto e permitem a geração automática de documentação.&lt;/p>&lt;p>Vamos criar o arquivo &lt;code>app/schemas.py&lt;/code> com todos os modelos de dados. Teremos quatro modelos: &lt;code>GenerateRequest&lt;/code>, &lt;code>LoadModelRequest&lt;/code>, &lt;code>ApiKeyResponse&lt;/code> e &lt;code>LDAPUserRequest&lt;/code>.&lt;/p>&lt;p>&lt;strong>schemas.py&lt;/strong>&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1&lt;/span>&lt;span>&lt;span style="color:#f92672">from&lt;/span> pydantic &lt;span style="color:#f92672">import&lt;/span> BaseModel, Field&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2&lt;/span>&lt;span>&lt;span style="color:#f92672">from&lt;/span> typing &lt;span style="color:#f92672">import&lt;/span> Optional&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4&lt;/span>&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">GenerateRequest&lt;/span>(BaseModel):&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5&lt;/span>&lt;span> model_name: str &lt;span style="color:#f92672">=&lt;/span> Field(&lt;span style="color:#f92672">...&lt;/span>, description&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;The name of the model to use for generation.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6&lt;/span>&lt;span> prompt: str &lt;span style="color:#f92672">=&lt;/span> Field(&lt;span style="color:#f92672">...&lt;/span>, description&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;The input text to generate a response for.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7&lt;/span>&lt;span> max_tokens: Optional[int] &lt;span style="color:#f92672">=&lt;/span> Field(&lt;span style="color:#ae81ff">300&lt;/span>, description&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;The maximum length of the generated response.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8&lt;/span>&lt;span> temperature: Optional[float] &lt;span style="color:#f92672">=&lt;/span> Field(&lt;span style="color:#ae81ff">1.0&lt;/span>, description&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;The sampling temperature for generation.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9&lt;/span>&lt;span> top_p: Optional[float] &lt;span style="color:#f92672">=&lt;/span> Field(&lt;span style="color:#ae81ff">1.0&lt;/span>, description&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;The cumulative probability for nucleus sampling.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10&lt;/span>&lt;span> hf_token: Optional[str] &lt;span style="color:#f92672">=&lt;/span> Field(&lt;span style="color:#66d9ef">None&lt;/span>, description&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;The Hugging Face tokenizer to use, if applicable.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13&lt;/span>&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">LoadModelRequest&lt;/span>(BaseModel):&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14&lt;/span>&lt;span> model_name: str &lt;span style="color:#f92672">=&lt;/span> Field(&lt;span style="color:#f92672">...&lt;/span>, description&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;The name of the model to load.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15&lt;/span>&lt;span> device: Optional[str] &lt;span style="color:#f92672">=&lt;/span> Field(&lt;span style="color:#e6db74">&amp;#34;cuda&amp;#34;&lt;/span>, description&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;The device to load the model on (e.g., &amp;#39;cpu&amp;#39;, &amp;#39;cuda&amp;#39;).&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16&lt;/span>&lt;span> hf_token: Optional[str] &lt;span style="color:#f92672">=&lt;/span> Field(&lt;span style="color:#66d9ef">None&lt;/span>, description&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;The Hugging Face tokenizer to use, if applicable.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18&lt;/span>&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ApiKeyResponse&lt;/span>(BaseModel):&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19&lt;/span>&lt;span> api_key: str &lt;span style="color:#f92672">=&lt;/span> Field(&lt;span style="color:#f92672">...&lt;/span>, description&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;The API key for accessing the model API.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21&lt;/span>&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">LDAPUserRequest&lt;/span>(BaseModel):&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22&lt;/span>&lt;span> username: str &lt;span style="color:#f92672">=&lt;/span> Field(&lt;span style="color:#f92672">...&lt;/span>, description&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;The username for LDAP authentication.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>&lt;li>Todas as classes herdam da classe &lt;code>BaseModel&lt;/code> da biblioteca &lt;code>pydantic&lt;/code>, obtendo funcionalidades de validação, serialização e documentação automática.&lt;/li>&lt;li>O campo &lt;code>Field(...)&lt;/code> define um campo obrigatório sem valor padrão.&lt;/li>&lt;li>O campo &lt;code>Field(value)&lt;/code> define um campo obrigatório com &lt;code>value&lt;/code> como valor padrão.&lt;/li>&lt;li>O tipo &lt;code>Optional[type]&lt;/code> indica que o campo é opcional, mas deve ser do tipo &lt;code>type&lt;/code> se fornecido.&lt;/li>&lt;/ul>&lt;p>Com os schemas definidos, vamos criar o arquivo responsável pela autenticação via API Key.&lt;/p>&lt;h2 id="autenticação-e-api-keys">Autenticação e API Keys&lt;/h2>&lt;p>O sistema de autenticação protege a API, garantindo que apenas usuários autorizados possam acessar os endpoints. Vamos implementar um mecanismo baseado em API Keys.&lt;/p>&lt;p>Vamos criar o arquivo &lt;code>app/auth.py&lt;/code> com todas as funcionalidades de autenticação.&lt;/p>&lt;p>&lt;strong>auth.py&lt;/strong>&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1&lt;/span>&lt;span>&lt;span style="color:#f92672">import&lt;/span> secrets &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2&lt;/span>&lt;span>&lt;span style="color:#f92672">import&lt;/span> json&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3&lt;/span>&lt;span>&lt;span style="color:#f92672">from&lt;/span> fastapi &lt;span style="color:#f92672">import&lt;/span> HTTPException, Request&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5&lt;/span>&lt;span>APIKEY_STORE_FILE &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;app/apikey_store.json&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7&lt;/span>&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">load_apikeys&lt;/span>():&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8&lt;/span>&lt;span> &lt;span style="color:#66d9ef">try&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9&lt;/span>&lt;span> &lt;span style="color:#66d9ef">with&lt;/span> open(APIKEY_STORE_FILE, &lt;span style="color:#e6db74">&amp;#34;r&amp;#34;&lt;/span>) &lt;span style="color:#66d9ef">as&lt;/span> f:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> json&lt;span style="color:#f92672">.&lt;/span>load(f)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11&lt;/span>&lt;span> &lt;span style="color:#66d9ef">except&lt;/span> &lt;span style="color:#a6e22e">FileNotFoundError&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12&lt;/span>&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> HTTPException(&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13&lt;/span>&lt;span> status_code&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">404&lt;/span>,&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14&lt;/span>&lt;span> detail&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Arquivo de API keys não encontrado: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>APIKEY_STORE_FILE&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15&lt;/span>&lt;span> &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16&lt;/span>&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">save_apikeys&lt;/span>(keys: dict):&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17&lt;/span>&lt;span> &lt;span style="color:#66d9ef">with&lt;/span> open(APIKEY_STORE_FILE, &lt;span style="color:#e6db74">&amp;#34;w&amp;#34;&lt;/span>) &lt;span style="color:#66d9ef">as&lt;/span> f:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18&lt;/span>&lt;span> json&lt;span style="color:#f92672">.&lt;/span>dump(keys, f, indent&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">4&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20&lt;/span>&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">generate_apikey&lt;/span>(user:str) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> str:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21&lt;/span>&lt;span> key &lt;span style="color:#f92672">=&lt;/span> secrets&lt;span style="color:#f92672">.&lt;/span>token_hex(&lt;span style="color:#ae81ff">32&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22&lt;/span>&lt;span> keys &lt;span style="color:#f92672">=&lt;/span> load_apikeys()&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23&lt;/span>&lt;span> keys[user] &lt;span style="color:#f92672">=&lt;/span> key&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24&lt;/span>&lt;span> save_apikeys(keys)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> key&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27&lt;/span>&lt;span>&lt;span style="color:#66d9ef">async&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">verify_apikey&lt;/span>(request: Request) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> bool:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28&lt;/span>&lt;span> apikey &lt;span style="color:#f92672">=&lt;/span> request&lt;span style="color:#f92672">.&lt;/span>headers&lt;span style="color:#f92672">.&lt;/span>get(&lt;span style="color:#e6db74">&amp;#34;x-API-Key&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29&lt;/span>&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">not&lt;/span> apikey:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30&lt;/span>&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> HTTPException(&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31&lt;/span>&lt;span> status_code&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">401&lt;/span>,&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32&lt;/span>&lt;span> detail&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;API key não fornecida.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33&lt;/span>&lt;span> &lt;span style="color:#66d9ef">try&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34&lt;/span>&lt;span> keys &lt;span style="color:#f92672">=&lt;/span> load_apikeys()&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35&lt;/span>&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> apikey &lt;span style="color:#f92672">in&lt;/span> keys&lt;span style="color:#f92672">.&lt;/span>values():&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">True&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37&lt;/span>&lt;span> &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38&lt;/span>&lt;span> &lt;span style="color:#66d9ef">except&lt;/span> json&lt;span style="color:#f92672">.&lt;/span>JSONDecodeError:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">39&lt;/span>&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> HTTPException(&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">40&lt;/span>&lt;span> status_code&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">403&lt;/span>,&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">41&lt;/span>&lt;span> detail&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;API key inválida.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>&lt;li>A função &lt;code>load_apikeys&lt;/code> carrega as informações armazenadas no arquivo &lt;code>app/apikey_store.json&lt;/code>.&lt;/li>&lt;li>&lt;code>save_apikeys&lt;/code> é responsável por salvar o conteúdo no formato JSON.&lt;/li>&lt;li>A função &lt;code>generate_apikey&lt;/code> cria uma chave para um usuário e a adiciona ao dicionário, usando o username como chave.&lt;/li>&lt;li>&lt;code>verify_apikey&lt;/code> será chamada sempre que uma requisição chegar, para realizar a validação.&lt;/li>&lt;/ul>&lt;h2 id="gerenciador-de-modelos-e-gpu">Gerenciador de Modelos e GPU&lt;/h2>&lt;p>O &lt;code>app/model_manager.py&lt;/code> é o coração da API, responsável por carregar, gerenciar e executar os modelos de linguagem. Ele otimiza o uso de GPU/CPU e garante eficiência na geração do texto.&lt;/p>&lt;p>&lt;strong>model_manager.py&lt;/strong>&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1&lt;/span>&lt;span>&lt;span style="color:#f92672">import&lt;/span> torch &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2&lt;/span>&lt;span>&lt;span style="color:#f92672">from&lt;/span> transformers &lt;span style="color:#f92672">import&lt;/span> AutoTokenizer, AutoModelForCausalLM&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3&lt;/span>&lt;span>&lt;span style="color:#f92672">from&lt;/span> fastapi &lt;span style="color:#f92672">import&lt;/span> HTTPException&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4&lt;/span>&lt;span>&lt;span style="color:#f92672">import&lt;/span> gc&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5&lt;/span>&lt;span>&lt;span style="color:#f92672">from&lt;/span> .utils &lt;span style="color:#f92672">import&lt;/span> is_model_on_gpu&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7&lt;/span>&lt;span>DEVICE &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;cuda&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> torch&lt;span style="color:#f92672">.&lt;/span>cuda&lt;span style="color:#f92672">.&lt;/span>is_available() &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#e6db74">&amp;#34;cpu&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9&lt;/span>&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ModelManager&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10&lt;/span>&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> __init__(self):&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>model &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>tokenizer &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>model_name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15&lt;/span>&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">load_model&lt;/span>(self, model_name: str, hf_token:str &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>, device: str &lt;span style="color:#f92672">=&lt;/span> DEVICE):&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16&lt;/span>&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>model_name &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span> &lt;span style="color:#f92672">and&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>model_name &lt;span style="color:#f92672">!=&lt;/span> model_name:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17&lt;/span>&lt;span> print(&lt;span style="color:#e6db74">&amp;#34;Removendo modelo carregado anteriormente...&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>unload_model() &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20&lt;/span>&lt;span> print(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Carregando modelo &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>model_name&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> no dispositivo &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>device&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">...&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21&lt;/span>&lt;span> &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22&lt;/span>&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>model_name &lt;span style="color:#f92672">!=&lt;/span> model_name:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23&lt;/span>&lt;span> &lt;span style="color:#66d9ef">try&lt;/span>: &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24&lt;/span>&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> hf_token: &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>tokenizer &lt;span style="color:#f92672">=&lt;/span> AutoTokenizer&lt;span style="color:#f92672">.&lt;/span>from_pretrained(model_name, token&lt;span style="color:#f92672">=&lt;/span>hf_token)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>model &lt;span style="color:#f92672">=&lt;/span> AutoModelForCausalLM&lt;span style="color:#f92672">.&lt;/span>from_pretrained(model_name, device_map&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;balanced&amp;#34;&lt;/span>, token&lt;span style="color:#f92672">=&lt;/span>hf_token)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27&lt;/span>&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>tokenizer &lt;span style="color:#f92672">=&lt;/span> AutoTokenizer&lt;span style="color:#f92672">.&lt;/span>from_pretrained(model_name)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>model &lt;span style="color:#f92672">=&lt;/span> AutoModelForCausalLM&lt;span style="color:#f92672">.&lt;/span>from_pretrained(model_name, device_map&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;balanced&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>model&lt;span style="color:#f92672">.&lt;/span>eval()&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>model_name &lt;span style="color:#f92672">=&lt;/span> model_name&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32&lt;/span>&lt;span> print(is_model_on_gpu(self&lt;span style="color:#f92672">.&lt;/span>model&lt;span style="color:#f92672">.&lt;/span>hf_device_map, self&lt;span style="color:#f92672">.&lt;/span>model_name))&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33&lt;/span>&lt;span> &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34&lt;/span>&lt;span> &lt;span style="color:#66d9ef">except&lt;/span> &lt;span style="color:#a6e22e">Exception&lt;/span> &lt;span style="color:#66d9ef">as&lt;/span> e:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35&lt;/span>&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> HTTPException(status_code&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">500&lt;/span>, detail&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Erro ao carregar modelo: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>str(e)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36&lt;/span>&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37&lt;/span>&lt;span> print(&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;O modelo &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>model_name&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> já está carregado.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">39&lt;/span>&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">generate&lt;/span>(self, model_name:str, hf_token: str, prompt:str, max_tokens:int &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">300&lt;/span>, temperature:float &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1.0&lt;/span>, top_p:float &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1.0&lt;/span>) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> str:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">40&lt;/span>&lt;span> &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">41&lt;/span>&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>model_name &lt;span style="color:#f92672">!=&lt;/span> model_name:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">42&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>load_model(model_name, hf_token, device&lt;span style="color:#f92672">=&lt;/span>DEVICE)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">43&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">44&lt;/span>&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>model &lt;span style="color:#f92672">is&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span> &lt;span style="color:#f92672">or&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>tokenizer &lt;span style="color:#f92672">is&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">45&lt;/span>&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> HTTPException(status_code&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">400&lt;/span>, detail&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Nenhum modelo carregado.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">46&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">47&lt;/span>&lt;span> &lt;span style="color:#66d9ef">try&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">48&lt;/span>&lt;span> inputs &lt;span style="color:#f92672">=&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>tokenizer(prompt, return_tensors&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;pt&amp;#34;&lt;/span>)&lt;span style="color:#f92672">.&lt;/span>to(self&lt;span style="color:#f92672">.&lt;/span>model&lt;span style="color:#f92672">.&lt;/span>device)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">49&lt;/span>&lt;span> &lt;span style="color:#66d9ef">with&lt;/span> torch&lt;span style="color:#f92672">.&lt;/span>no_grad(): &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">50&lt;/span>&lt;span> outputs &lt;span style="color:#f92672">=&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>model&lt;span style="color:#f92672">.&lt;/span>generate(&lt;span style="color:#f92672">**&lt;/span>inputs, max_new_tokens&lt;span style="color:#f92672">=&lt;/span>max_tokens,temperature&lt;span style="color:#f92672">=&lt;/span>temperature, top_p&lt;span style="color:#f92672">=&lt;/span>top_p, eos_token_id&lt;span style="color:#f92672">=&lt;/span>self&lt;span style="color:#f92672">.&lt;/span>tokenizer&lt;span style="color:#f92672">.&lt;/span>eos_token_id)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">51&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>tokenizer&lt;span style="color:#f92672">.&lt;/span>decode(outputs[&lt;span style="color:#ae81ff">0&lt;/span>], skip_special_tokens&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">True&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">52&lt;/span>&lt;span> &lt;span style="color:#66d9ef">except&lt;/span> &lt;span style="color:#a6e22e">Exception&lt;/span> &lt;span style="color:#66d9ef">as&lt;/span> e:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">53&lt;/span>&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> HTTPException(status_code&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">500&lt;/span>, detail&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Erro ao gerar texto: &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>str(e)&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">54&lt;/span>&lt;span> &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">55&lt;/span>&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">get_status&lt;/span>(self) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> str: &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">56&lt;/span>&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>model &lt;span style="color:#f92672">is&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">57&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>unload_model()&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">58&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Nenhum modelo carregado.&amp;#34;&lt;/span> &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">59&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> is_model_on_gpu(self&lt;span style="color:#f92672">.&lt;/span>model&lt;span style="color:#f92672">.&lt;/span>hf_device_map, self&lt;span style="color:#f92672">.&lt;/span>model_name)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">60&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">61&lt;/span>&lt;span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">unload_model&lt;/span>(self):&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">62&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>model &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">63&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>tokenizer &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">64&lt;/span>&lt;span> old_model &lt;span style="color:#f92672">=&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>model_name &lt;span style="color:#66d9ef">if&lt;/span> self&lt;span style="color:#f92672">.&lt;/span>model_name &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">False&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">65&lt;/span>&lt;span> self&lt;span style="color:#f92672">.&lt;/span>model_name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">None&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">66&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">67&lt;/span>&lt;span> gc&lt;span style="color:#f92672">.&lt;/span>collect()&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">68&lt;/span>&lt;span> torch&lt;span style="color:#f92672">.&lt;/span>cuda&lt;span style="color:#f92672">.&lt;/span>empty_cache()&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">69&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Modelo &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>old_model&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> descarregado com sucesso.&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> old_model &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Nenhum modelo carregado para descarregar.&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">70&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">71&lt;/span>&lt;span>manager &lt;span style="color:#f92672">=&lt;/span> ModelManager()&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>&lt;li>A função &lt;code>load_model&lt;/code> carrega o novo modelo na memória, removendo algum modelo que foi carregado anteriormente.&lt;/li>&lt;li>&lt;code>generate&lt;/code> é a principal função da API, ela é responsável por realizar a inferência do modelo. Permite alterar os parâmetros: temperature, top_p e max_tokens.&lt;/li>&lt;li>&lt;code>get_status&lt;/code> é responsável por informar se existe modelo carregado e se está em GPU ou CPU.&lt;/li>&lt;li>A função &lt;code>unload_model&lt;/code> remove o modelo da memória, limpando o cache do CUDA e utilizando o garbage collector do python para não restar resquícios que possam atrapalhar futuros carregamentos.&lt;/li>&lt;/ul>&lt;h2 id="endpoints-da-api-fastapi">Endpoints da API FastAPI&lt;/h2>&lt;p>O arquivo &lt;code>app/main.py&lt;/code> é onde todos os componentes se conectam. Nele definimos todos os endpoints e a lógica de roteamento da API.&lt;/p>&lt;p>&lt;strong>main.py&lt;/strong>&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1&lt;/span>&lt;span>&lt;span style="color:#f92672">from&lt;/span> fastapi &lt;span style="color:#f92672">import&lt;/span> FastAPI, Request, HTTPException, Depends&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2&lt;/span>&lt;span>&lt;span style="color:#f92672">from&lt;/span> fastapi.responses &lt;span style="color:#f92672">import&lt;/span> JSONResponse&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3&lt;/span>&lt;span>&lt;span style="color:#f92672">from&lt;/span> app &lt;span style="color:#f92672">import&lt;/span> schemas, model_manager, auth&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5&lt;/span>&lt;span>app &lt;span style="color:#f92672">=&lt;/span> FastAPI()&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7&lt;/span>&lt;span>&lt;span style="color:#66d9ef">async&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">require_api_key&lt;/span>(request: Request) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> schemas&lt;span style="color:#f92672">.&lt;/span>LDAPUserRequest:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8&lt;/span>&lt;span> user &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">await&lt;/span> auth&lt;span style="color:#f92672">.&lt;/span>verify_apikey(request)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9&lt;/span>&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">not&lt;/span> user:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10&lt;/span>&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> HTTPException(status_code&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">401&lt;/span>, detail&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;API key invalida.&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">11&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> user&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">12&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">13&lt;/span>&lt;span>&lt;span style="color:#a6e22e">@app.post&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/generate_apikey&amp;#34;&lt;/span>)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">14&lt;/span>&lt;span>&lt;span style="color:#66d9ef">async&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">generate_apikey&lt;/span>(payload: schemas&lt;span style="color:#f92672">.&lt;/span>LDAPUserRequest) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> JSONResponse:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">15&lt;/span>&lt;span> key &lt;span style="color:#f92672">=&lt;/span> auth&lt;span style="color:#f92672">.&lt;/span>generate_apikey(payload&lt;span style="color:#f92672">.&lt;/span>username)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">16&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> JSONResponse(status_code&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">200&lt;/span>, content&lt;span style="color:#f92672">=&lt;/span>{&lt;span style="color:#e6db74">&amp;#34;api_key&amp;#34;&lt;/span>: key})&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">17&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">18&lt;/span>&lt;span>&lt;span style="color:#a6e22e">@app.post&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/load_model&amp;#34;&lt;/span>, dependencies&lt;span style="color:#f92672">=&lt;/span>[Depends(require_api_key)])&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">19&lt;/span>&lt;span>&lt;span style="color:#66d9ef">async&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">load_model&lt;/span>(payload: schemas&lt;span style="color:#f92672">.&lt;/span>LoadModelRequest) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> JSONResponse:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">20&lt;/span>&lt;span> &lt;span style="color:#66d9ef">try&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">21&lt;/span>&lt;span> model_manager&lt;span style="color:#f92672">.&lt;/span>manager&lt;span style="color:#f92672">.&lt;/span>load_model(payload&lt;span style="color:#f92672">.&lt;/span>model_name, payload&lt;span style="color:#f92672">.&lt;/span>hf_token, payload&lt;span style="color:#f92672">.&lt;/span>device)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">22&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> JSONResponse(content&lt;span style="color:#f92672">=&lt;/span>{&lt;span style="color:#e6db74">&amp;#34;message&amp;#34;&lt;/span>: &lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Modelo &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>payload&lt;span style="color:#f92672">.&lt;/span>model_name&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> carregado com sucesso.&amp;#34;&lt;/span>})&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">23&lt;/span>&lt;span> &lt;span style="color:#66d9ef">except&lt;/span> &lt;span style="color:#a6e22e">Exception&lt;/span> &lt;span style="color:#66d9ef">as&lt;/span> e:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">24&lt;/span>&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> HTTPException(status_code&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">500&lt;/span>, content&lt;span style="color:#f92672">=&lt;/span>{&lt;span style="color:#e6db74">&amp;#34;error&amp;#34;&lt;/span>: str(e)})&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">25&lt;/span>&lt;span> &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">26&lt;/span>&lt;span>&lt;span style="color:#a6e22e">@app.post&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/generate&amp;#34;&lt;/span>, dependencies&lt;span style="color:#f92672">=&lt;/span>[Depends(require_api_key)])&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">27&lt;/span>&lt;span>&lt;span style="color:#66d9ef">async&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">generate&lt;/span>(payload: schemas&lt;span style="color:#f92672">.&lt;/span>GenerateRequest)&lt;span style="color:#f92672">-&amp;gt;&lt;/span> JSONResponse:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">28&lt;/span>&lt;span> &lt;span style="color:#66d9ef">try&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">29&lt;/span>&lt;span> result &lt;span style="color:#f92672">=&lt;/span> model_manager&lt;span style="color:#f92672">.&lt;/span>manager&lt;span style="color:#f92672">.&lt;/span>generate(payload&lt;span style="color:#f92672">.&lt;/span>model_name, payload&lt;span style="color:#f92672">.&lt;/span>hf_token,payload&lt;span style="color:#f92672">.&lt;/span>prompt, payload&lt;span style="color:#f92672">.&lt;/span>max_tokens, payload&lt;span style="color:#f92672">.&lt;/span>temperature, payload&lt;span style="color:#f92672">.&lt;/span>top_p)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">30&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> {&lt;span style="color:#e6db74">&amp;#34;result&amp;#34;&lt;/span>: result}&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">31&lt;/span>&lt;span> &lt;span style="color:#66d9ef">except&lt;/span> &lt;span style="color:#a6e22e">Exception&lt;/span> &lt;span style="color:#66d9ef">as&lt;/span> e:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">32&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> JSONResponse(status_code&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">500&lt;/span>, content&lt;span style="color:#f92672">=&lt;/span>{&lt;span style="color:#e6db74">&amp;#34;error&amp;#34;&lt;/span>: str(e)})&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">33&lt;/span>&lt;span> &lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">34&lt;/span>&lt;span>&lt;span style="color:#a6e22e">@app.get&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/status&amp;#34;&lt;/span>, dependencies&lt;span style="color:#f92672">=&lt;/span>[Depends(require_api_key)])&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">35&lt;/span>&lt;span>&lt;span style="color:#66d9ef">async&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">status&lt;/span>()&lt;span style="color:#f92672">-&amp;gt;&lt;/span> JSONResponse:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">36&lt;/span>&lt;span> str_status &lt;span style="color:#f92672">=&lt;/span> model_manager&lt;span style="color:#f92672">.&lt;/span>manager&lt;span style="color:#f92672">.&lt;/span>get_status()&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">37&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> JSONResponse(content&lt;span style="color:#f92672">=&lt;/span>{&lt;span style="color:#e6db74">&amp;#34;status&amp;#34;&lt;/span>: str_status})&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">38&lt;/span>&lt;span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">39&lt;/span>&lt;span>&lt;span style="color:#a6e22e">@app.post&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;/unload_model&amp;#34;&lt;/span>, dependencies&lt;span style="color:#f92672">=&lt;/span>[Depends(require_api_key)])&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">40&lt;/span>&lt;span>&lt;span style="color:#66d9ef">async&lt;/span> &lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">unload_model&lt;/span>() &lt;span style="color:#f92672">-&amp;gt;&lt;/span> JSONResponse:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">41&lt;/span>&lt;span> &lt;span style="color:#66d9ef">try&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">42&lt;/span>&lt;span> str_unload &lt;span style="color:#f92672">=&lt;/span> model_manager&lt;span style="color:#f92672">.&lt;/span>manager&lt;span style="color:#f92672">.&lt;/span>unload_model()&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">43&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> JSONResponse(content&lt;span style="color:#f92672">=&lt;/span>{&lt;span style="color:#e6db74">&amp;#34;message&amp;#34;&lt;/span>:str_unload})&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">44&lt;/span>&lt;span> &lt;span style="color:#66d9ef">except&lt;/span> &lt;span style="color:#a6e22e">Exception&lt;/span> &lt;span style="color:#66d9ef">as&lt;/span> e:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">45&lt;/span>&lt;span> &lt;span style="color:#66d9ef">raise&lt;/span> HTTPException(status_code&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">500&lt;/span>, content&lt;span style="color:#f92672">=&lt;/span>{&lt;span style="color:#e6db74">&amp;#34;error&amp;#34;&lt;/span>: str(e)})&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>&lt;li>A função &lt;code>require_api_key&lt;/code> verifica a API Key sempre que chega uma requisição e retorna o usuário autenticado ou gera erro 401.&lt;/li>&lt;li>&lt;code>generate_apikey&lt;/code> gera e retorna uma nova chave de API para o usuário informado.&lt;/li>&lt;li>&lt;code>load_model&lt;/code> carrega o modelo especificado. Caso o modelo necessite de um token Hugging Face, a função também recebe esse parâmetro.&lt;/li>&lt;li>A função &lt;code>generate&lt;/code> é responsável por fazer o modelo realizar a inferência a partir do prompt e os parâmetros passados.&lt;/li>&lt;li>Ao chamar o endpoint &lt;code>status&lt;/code> o usuário recebe o status atual do gerenciador de modelos.&lt;/li>&lt;li>&lt;code>unload_model&lt;/code> descarrega o modelo atualmente carregado e retorna uma mensagem de sucesso caso tenha concluído corretamente.&lt;/li>&lt;/ul>&lt;h2 id="arquivo-utilspy">Arquivo &lt;code>utils.py&lt;/code>&lt;/h2>&lt;p>O arquivo &lt;code>app/utils.py&lt;/code> contém a função que verifica se o modelo carregado está totalmente/parcialmente em GPU ou foi carregado em CPU.&lt;/p>&lt;p>&lt;strong>utils.py&lt;/strong>&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">1&lt;/span>&lt;span>&lt;span style="color:#66d9ef">def&lt;/span> &lt;span style="color:#a6e22e">is_model_on_gpu&lt;/span>(hf_device_map: dict, model_name: str) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> str:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">2&lt;/span>&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span> &lt;span style="color:#f92672">in&lt;/span> hf_device_map&lt;span style="color:#f92672">.&lt;/span>keys() &lt;span style="color:#f92672">and&lt;/span> hf_device_map[&lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>] &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#39;cpu&amp;#39;&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">3&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Modelo &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>model_name&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> carregado totalmente na CPU.&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">4&lt;/span>&lt;span> &lt;span style="color:#66d9ef">elif&lt;/span> &lt;span style="color:#e6db74">&amp;#39;cpu&amp;#39;&lt;/span> &lt;span style="color:#f92672">in&lt;/span> hf_device_map&lt;span style="color:#f92672">.&lt;/span>values():&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">5&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Algumas camadas do modelo &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>model_name&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> estão carregadas na CPU.&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">6&lt;/span>&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>:&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">7&lt;/span>&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">f&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Modelo &lt;/span>&lt;span style="color:#e6db74">{&lt;/span>model_name&lt;span style="color:#e6db74">}&lt;/span>&lt;span style="color:#e6db74"> carregado totalmente na GPU.&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="executando-a-api">Executando a API&lt;/h2>&lt;p>Para executar a API com o &lt;code>uvicorn&lt;/code> é muito simples, basta executar um comando com as informações de host e porta para o serviço rodar.&lt;/p>&lt;pre tabindex="0">&lt;code>uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload&lt;/code>&lt;/pre>&lt;ul>&lt;li>&lt;p>&lt;code>app:main&lt;/code> se refere ao arquivo &lt;code>app/main.py&lt;/code> responsável por conectar todos os componentes e receber as requisições realizadas pelo usuário.&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;code>--host 0.0.0.0&lt;/code> define o endereço IP no qual o servidor Uvicorn irá escutar as requisições. O valor &lt;code>0.0.0.0&lt;/code> define que este servidor estará acessível de qualquer interface de rede disponível na máquina Power9.&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;code>--port 8000&lt;/code> especifica a porta na qual o servidor irá escutar as requisições.&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;code>--reload&lt;/code> flag para ser utilizada em desenvolvimento. Recarrega a aplicação sempre que uma mudança é realizada.&lt;/p>&lt;/li>&lt;/ul>&lt;p>Seguindo estas implementações, você terá uma API capaz de realizar inferências com Modelos de Linguagem baixados do Hugging Face. No &lt;a href="https://llm-pt-ibm.github.io/posts/tutorial_power9_pt4_en/">&lt;span class="link-personalizado">próximo tutorial&lt;/span>&lt;/a> será demonstrado como enviar requisições para a API via curl e python.&lt;/p></description></item><item><title>Configurando Conda e PyTorch em um servidor IBM Power9</title><link>https://llm-pt-ibm.github.io/posts/tutorial_power9_pt2_en/</link><pubDate>Mon, 30 Jun 2025 00:00:00 +0000</pubDate><guid>https://llm-pt-ibm.github.io/posts/tutorial_power9_pt2_en/</guid><description>&lt;h2 id="contexto">Contexto&lt;/h2>&lt;p>Este é o segundo post de uma série de tutoriais que vamos mostrar o passo-a-passo de como construir uma API de Modelos de Linguagem em um servidor Power9, desde da configuração do Sistema Operacional, até a API executando inferências de forma remota. O &lt;a href="https://llm-pt-ibm.github.io/posts/tutorial_power9_pt1_en/">&lt;span class="link-personalizado">primeiro post&lt;/span>&lt;/a> mostra como instalar o S.O e configurar drivers NVIDIA, CUDA e CUDNN. Nesta etapa do tutorial vamos mostrar a configuração do gerenciador de pacotes Conda e da biblioteca PyTorch&lt;/p>&lt;p>&lt;strong>Conda&lt;/strong>: Conda é um sistema de gerenciamento de pacotes e ambientes de código aberto e multiplataforma. Ele funciona como uma &amp;ldquo;caixa de ferramentas&amp;rdquo; para cientistas de dados e desenvolvedores, ajudando a organizar seus projetos.&lt;/p>&lt;p>&lt;strong>PyTorch&lt;/strong>: PyTorch é uma biblioteca de código aberto para aprendizado de máquina, desenvolvida principalmente pelo Facebook AI Research (FAIR). Ela é especialmente popular para o desenvolvimento de aplicações de deep learning (aprendizado profundo), um subcampo do aprendizado de máquina que se inspira no funcionamento do cérebro humano.&lt;/p>&lt;h2 id="tldr">TL;DR&lt;/h2>&lt;ul>&lt;li>Este post apresenta o passo-a-passo para a instalação do Conda e PyTorch.&lt;/li>&lt;li>O desafio maior é encontrar versões compatíveis com a arquitetura das máquinas Power.&lt;/li>&lt;/ul>&lt;h2 id="configurando-conda">Configurando Conda&lt;/h2>&lt;p>Vamos começar com a instalação do &lt;strong>Conda&lt;/strong>. Em sistemas Power, a arquitetura usada é a &lt;code>ppc64le&lt;/code> (PowerPC 64 bits little-endian), por isso é essencial que a versão baixada seja para esta arquitetura. Para isso, vamos utilizar o &lt;strong>miniconda&lt;/strong>, uma versão mais leve e direta para setups customizados como o servidor Power9.&lt;/p>&lt;ol>&lt;li>Para baixar e instalar a versão mais atualizada do miniconda:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sudo wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-ppc64le.shbash ~/Miniconda3-latest-Linux-ppc64le.sh&lt;/code>&lt;/pre>&lt;ol start="2">&lt;li>Verifique se a instalação ativou o conda automático:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>conda -–version&lt;/code>&lt;/pre>&lt;p>Caso não tenha iniciado automaticamente, o Conda precisa ser ativado.&lt;/p>&lt;ol start="3">&lt;li>Para não precisar ativar sempre que realizar uma nova conexão, vamos escrever o comando no bashrc (ou zshrc):&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>echo &amp;#39;source ~/miniconda3/etc/profile.d/conda.sh&amp;#39; &amp;gt;&amp;gt; ~/.bashrcsource ~/.bashrc&lt;/code>&lt;/pre>&lt;p>Verifique novamente com o comando:&lt;/p>&lt;pre tabindex="0">&lt;code>conda --version&lt;/code>&lt;/pre>&lt;p>A saída esperada é algo semelhante a: &lt;code>conda 23.10.0&lt;/code>&lt;/p>&lt;h2 id="instalando-e-configurando-a-biblioteca-pytorch">Instalando e configurando a biblioteca PyTorch&lt;/h2>&lt;p>Não existem builds oficiais ou wheels Conda/PyPi com suporte completo para a arquitetura ppc64le, sendo assim, para instalar o PyTorch precisamos buildar manualmente.&lt;/p>&lt;h4 id="opcional-criação-de-ambiente-virtual-conda">(Opcional) Criação de ambiente virtual Conda&lt;/h4>&lt;p>Para iniciarmos a instalação é aconselhável criar um ambiente virtual para instalar o pytorch apenas nele.&lt;/p>&lt;ol>&lt;li>Para criar e ativar o ambiente virtual executamos os comandos:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>conda create -y -n api_llm python=3.10conda activate api_llm&lt;/code>&lt;/pre>&lt;h4 id="instalando-pré-requisitos">Instalando pré-requisitos&lt;/h4>&lt;p>Precisamos instalar alguns pacotes necessários para realizar o build do PyTorch da forma correta.&lt;/p>&lt;ol>&lt;li>Inicialmente, vamos instalar os pacotes com os seguintes comandos:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>conda install -y -c conda-forge openblas libblas cmake ninja python3-devel gcc-c++ rust cargo&lt;/code>&lt;/pre>&lt;p>O CMake (sistema de build utilizado pelo PyTorch) removeu o suporte a scripts que declaram compatibilidade com versões antigas (&amp;lt;3.5). Para resolver isso, precisamos instalar via pip uma versão do cmake &amp;lt;3.5.&lt;/p>&lt;ol start="2">&lt;li>Executamos o comando:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>pip install cmake==3.27.7&lt;/code>&lt;/pre>&lt;p>Para garantir que a versão correta foi instalada, executamos o comando:&lt;/p>&lt;pre tabindex="0">&lt;code>cmake --version&lt;/code>&lt;/pre>&lt;p>A saída esperada é: &lt;code>cmake version 3.27.7&lt;/code>&lt;/p>&lt;h4 id="build-do-pytorch">Build do Pytorch&lt;/h4>&lt;p>Agora vamos iniciar o processo de build do &lt;strong>PyTorch&lt;/strong>.&lt;/p>&lt;ol>&lt;li>O primeiro passo é clonar o repositório e configurar para instalar a versão 2.6.0:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>git clone --recursive https://github.com/pytorch/pytorchcd pytorchgit checkout v2.6.0 git submodule sync git submodule update --init --recursive &lt;/code>&lt;/pre>&lt;ol start="2">&lt;li>Para instalar os pacotes necessários via pip executamos o seguinte comando:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>pip install -r requirements.txt&lt;/code>&lt;/pre>&lt;ol start="3">&lt;li>E, finalmente, para realizar o build do PyTorch, executamos o setup.py do python:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sudo USE_CUDA=1 USE_DISTRIBUTED=1 USE_NCCL=1 USE_GLOO=1 USE_CUDNN=1 python setup.py install&lt;/code>&lt;/pre>&lt;p>O processo de build geralmente demora um tempo considerável, cerca de 15 minutos.&lt;/p>&lt;ol start="4">&lt;li>Para testar se tudo ocorreu certo, vamos criar um arquivo chamado &lt;code>test_torch.py&lt;/code>&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>nano test_torch.py&lt;/code>&lt;/pre>&lt;p>Esse arquivo deve conter as seguintes linhas:&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 1&lt;/span>&lt;span>&lt;span style="color:#f92672">import&lt;/span> torch&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 2&lt;/span>&lt;span>print(torch&lt;span style="color:#f92672">.&lt;/span>__version__)&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 3&lt;/span>&lt;span>print(&lt;span style="color:#e6db74">&amp;#34;CUDA disponível:&amp;#34;&lt;/span>, torch&lt;span style="color:#f92672">.&lt;/span>cuda&lt;span style="color:#f92672">.&lt;/span>is_available())&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 4&lt;/span>&lt;span>print(&lt;span style="color:#e6db74">&amp;#34;Número de GPUs:&amp;#34;&lt;/span>, torch&lt;span style="color:#f92672">.&lt;/span>cuda&lt;span style="color:#f92672">.&lt;/span>device_count())&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 5&lt;/span>&lt;span>print(&lt;span style="color:#e6db74">&amp;#34;Nome da GPU:&amp;#34;&lt;/span>, torch&lt;span style="color:#f92672">.&lt;/span>cuda&lt;span style="color:#f92672">.&lt;/span>get_device_name(&lt;span style="color:#ae81ff">0&lt;/span>))&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 6&lt;/span>&lt;span>x &lt;span style="color:#f92672">=&lt;/span> torch&lt;span style="color:#f92672">.&lt;/span>rand(&lt;span style="color:#ae81ff">3&lt;/span>, &lt;span style="color:#ae81ff">3&lt;/span>)&lt;span style="color:#f92672">.&lt;/span>cuda()&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 7&lt;/span>&lt;span>y &lt;span style="color:#f92672">=&lt;/span> torch&lt;span style="color:#f92672">.&lt;/span>rand(&lt;span style="color:#ae81ff">3&lt;/span>, &lt;span style="color:#ae81ff">3&lt;/span>)&lt;span style="color:#f92672">.&lt;/span>cuda()&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 8&lt;/span>&lt;span>print(&lt;span style="color:#e6db74">&amp;#34;Soma na GPU:&amp;#34;&lt;/span>, (x &lt;span style="color:#f92672">+&lt;/span> y))&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f"> 9&lt;/span>&lt;span>print(&lt;span style="color:#e6db74">&amp;#34;cuDNN disponível:&amp;#34;&lt;/span>, torch&lt;span style="color:#f92672">.&lt;/span>backends&lt;span style="color:#f92672">.&lt;/span>cudnn&lt;span style="color:#f92672">.&lt;/span>is_available())&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f">10&lt;/span>&lt;span>print(&lt;span style="color:#e6db74">&amp;#34;Extensões C carregadas:&amp;#34;&lt;/span>, torch&lt;span style="color:#f92672">.&lt;/span>_C&lt;span style="color:#f92672">.&lt;/span>_cuda_getDeviceCount() &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Ao executar esse arquivo, saberemos:&lt;/p>&lt;ul>&lt;li>Versão instalada do pytorch&lt;/li>&lt;li>Disponibilidade do CUDA&lt;/li>&lt;li>Quantidade de GPUs disponíveis&lt;/li>&lt;li>Nome da GPU no servidor Power9&lt;/li>&lt;li>Se a utilização da GPU está acontecendo de forma correta&lt;/li>&lt;li>Disponibilidade do CUDNN&lt;/li>&lt;li>Se os arquivos .so foram compilados corretamentes&lt;/li>&lt;/ul>&lt;p>Esse arquivo apenas checa algumas informações do CUDA e PyTorch e executa uma operação de soma utilizando tensores em GPU.&lt;/p>&lt;ol start="5">&lt;li>Vamos executar o arquivo com o comando:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>python test_gpu.py&lt;/code>&lt;/pre>&lt;p>A saída deve ser algo semelhante a:&lt;/p>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span>2.6.0a0+git1eba9b3&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CUDA disponível: True&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Número de GPUs: &lt;span style="color:#ae81ff">4&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Nome da GPU: Tesla V100-SXM2-16GB&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Soma na GPU: tensor&lt;span style="color:#f92672">([[&lt;/span>1.9163, 1.2208, 0.5998&lt;span style="color:#f92672">]&lt;/span>,&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">[&lt;/span>1.7962, 0.6040, 1.3943&lt;span style="color:#f92672">]&lt;/span>,&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">[&lt;/span>0.9536, 0.8010, 0.0668&lt;span style="color:#f92672">]]&lt;/span>, device&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#39;cuda:0&amp;#39;&lt;/span>&lt;span style="color:#f92672">)&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>cuDNN disponível: True&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Extensões C carregadas: True&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>É importante lembrar que as saídas podem ser diferentes em relação ao número e modelo das GPUs e a soma de tensores (devido a aleatoriedade). É importante que as saídas booleanas do código que executamos tenham resultados igual a &lt;code>True&lt;/code>.&lt;/p>&lt;p>Com isso, a biblioteca PyTorch está instalada e configurada para ser utilizada. No &lt;a href="https://llm-pt-ibm.github.io/posts/tutorial_power9_pt3_en/">&lt;span class="link-personalizado">próximo tutorial&lt;/span>&lt;/a> vamos realizar a primeira inferência de um Modelo de Linguagem no servidor Power9.&lt;/p></description></item><item><title>Configurando S.O, NVIDIA Drivers, CUDA e CUDNN em um servidor IBM Power9</title><link>https://llm-pt-ibm.github.io/posts/tutorial_power9_pt1_en/</link><pubDate>Sun, 29 Jun 2025 00:00:00 +0000</pubDate><guid>https://llm-pt-ibm.github.io/posts/tutorial_power9_pt1_en/</guid><description>&lt;h2 id="contexto">Contexto&lt;/h2>&lt;p>Este é o primeiro post de uma série de tutoriais sobre como construir uma API de Modelos de Linguagem em um servidor Power9, desde da configuração do Sistema Operacional, até a API executando inferências de forma remota.Esta etapa do tutorial mostra como configurar o Sistema Operacional, instalar os drivers da NVIDIA, CUDA e CUDNN em máquinas com processador IBM Power9 AC922. O foco é garantir que tudo funcione corretamente em arquiteturas &lt;code>ppc64le&lt;/code>, comuns em ambientes de alto desempenho.&lt;/p>&lt;p>&lt;strong>IBM Power9&lt;/strong>: A IBM Power9 AC922 é uma máquina de alto desempenho usada em tarefas pesadas como inteligência artificial e processamento científico. Ela usa processadores Power9 e trabalha bem com GPUs NVIDIA, oferecendo alta velocidade de comunicação entre CPU e GPU.&lt;/p>&lt;p>&lt;strong>NVIDIA Drivers&lt;/strong>: Programas que permitem que o sistema operacional se comunique corretamente com as placas de vídeo da marca. São essenciais para ativar o uso de GPUs.&lt;/p>&lt;p>&lt;strong>CUDA&lt;/strong>: Plataforma NVIDIA que permite usar GPUs para acelerar cálculos paralelos. Com essa plataforma é possível rodar algoritmos complexos de forma rápida, como a execução de Grandes Modelos de Linguagem, por exemplo.&lt;/p>&lt;p>&lt;strong>CUDNN&lt;/strong>: Uma biblioteca de primitivas otimizadas para redes neurais profundas (DNNs), desenvolvida pela NVIDIA. Ele oferece implementações de alto desempenho para operações essenciais em DNNs, como convoluções, pooling e normalização, acelerando significativamente o treinamento e a inferência em GPUs.&lt;/p>&lt;h2 id="tldr">TL;DR&lt;/h2>&lt;ul>&lt;li>Este post apresenta o passo-a-passo de configurar um servidor Power9 incluindo setup do SO e configurações NVIDIA.&lt;/li>&lt;li>O desafio maior é encontrar versões compatíveis com a arquitetura das máquinas Power.&lt;/li>&lt;/ul>&lt;h2 id="configurando-sistema-operacional">Configurando Sistema Operacional&lt;/h2>&lt;p>Vamos começar com a instalação do &lt;strong>Red Hat Enterprise Linux 8.10 (Ootpa)&lt;/strong>. Em sistemas Power, a arquitetura usada é a &lt;code>ppc64le&lt;/code> (PowerPC 64 bits little-endian), por isso é essencial que a imagem .iso seja compatível com essa arquitetura. Caso contrário, o petitboot da Power9 não reconhecerá a mídia e a instalação não poderá continuar.&lt;/p>&lt;ol>&lt;li>Você pode baixar a imagem correta pelo &lt;a href="https://access.redhat.com/downloads/content/279/ver=/rhel---8/8.10/ppc64le/product-software" rel="external">&lt;span class="link-personalizado">link&lt;/span>&lt;/a> indicado.&lt;/li>&lt;li>Neste tutorial, usaremos a opção &lt;strong>Boot ISO&lt;/strong> e seguiremos as instruções da &lt;a href="https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/8/html/interactively_installing_rhel_from_installation_media/assembly_creating-a-bootable-installation-medium_rhel-installer" rel="external">&lt;span class="link-personalizado">documentação oficial da Red Hat&lt;/span>&lt;/a> para criar uma mídia USB inicializável.&lt;/li>&lt;li>Após inserir a mídia de instalação no servidor Power 9 e reiniciar a máquina, o sistema deve iniciar automaticamente no petitboot.&lt;/li>&lt;li>A partir desta etapa, basta seguir o &lt;a href="https://www.ibm.com/docs/en/linuxonibm/liabw/rhelqs_guide_Power_p9_usb.pdf" rel="external">&lt;span class="link-personalizado">guia de instalação&lt;/span>&lt;/a> oficial para concluir a configuração do sistema.&lt;/li>&lt;/ol>&lt;h2 id="configurando-driver-nvidia-e-cuda">Configurando Driver NVIDIA e CUDA&lt;/h2>&lt;h4 id="checagem-de-gpus-e-sistema-operacional">Checagem de GPUs e Sistema Operacional&lt;/h4>&lt;p>Para o sistema operacional realizar comunicação correta com as GPUs do servidor, precisamos instalar e configurar o driver da NVIDIA.&lt;/p>&lt;ol>&lt;li>Inicialmente, vamos checar a presença da(s) GPU(s):&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>lspci | grep -i nvidia&lt;/code>&lt;/pre>&lt;p>A saída esperada é algo como:&lt;/p>&lt;p>&lt;code>0004:04:00.0 3D controller: NVIDIA Corporation GV100GL [Tesla V100 SXM2 16GB] (rev a1)&lt;/code>&lt;/p>&lt;ol start="2">&lt;li>Após isso, vamos verificar arquitetura e nome do sistema operacional:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>uname -m &amp;amp;&amp;amp; cat /etc/redhat-release&lt;/code>&lt;/pre>&lt;p>A saída esperada é:&lt;/p>&lt;p>&lt;code>ppc64le Red Hat Enterprise Linux release 8.10 (Ootpa)&lt;/code>&lt;/p>&lt;h4 id="evitando-interferências">Evitando interferências&lt;/h4>&lt;p>Para evitar algumas interferências, é recomendável desativar o driver &lt;code>nouveau&lt;/code> e &lt;code>SELinux&lt;/code>.&lt;/p>&lt;p>O &lt;code>noveau&lt;/code> é um driver de código aberto para GPUs NVIDIA que subsitui o driver proprietário quando o usuário quer apenas usar o software livre, sem necessidade de de alto desempenho.&lt;/p>&lt;p>O &lt;code>SELinux=enable&lt;/code> restringe alguns processos de aplicarem mudanças no sistema, podendo conflitar com as instalações que vamos fazer neste tutorial.&lt;/p>&lt;ol>&lt;li>Desative o driver &lt;code>nouveau&lt;/code>:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>echo -e &amp;#34;blacklist nouveau\noptions nouveau modeset=0&amp;#34; | sudo tee /etc/modprobe.d/disable-nouveau.conf&lt;/code>&lt;/pre>&lt;ol start="2">&lt;li>Para desativar o &lt;code>SELinux&lt;/code>, primeiro vamos checar o status executando:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sestatus&lt;/code>&lt;/pre>&lt;p>Caso esteja ativo, será preciso setar o parâmetro &lt;code>SELINUX=disabled&lt;/code> no arquivo &lt;code>/etc/selinux/config&lt;/code> para prosseguir. É importante lembrar que a edição só será salva com permissão sudo.&lt;/p>&lt;ol start="3">&lt;li>Após isso, vamos atualizar o &lt;code>initrafms&lt;/code> e reiniciar a máquina com os seguintes comandos:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sudo dracut --forcesudo reboot&lt;/code>&lt;/pre>&lt;ol start="4">&lt;li>Para checar se tudo deu certo até agora, vamos checar se o &lt;code>nouveau&lt;/code> foi desabilitado:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>lsmod | grep nouveau&lt;/code>&lt;/pre>&lt;p>Caso tenha sido desabilitado, não terá saída.&lt;/p>&lt;ol start="5">&lt;li>Para checar o SELinux:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sestatus&lt;/code>&lt;/pre>&lt;p>Caso tenha sido desabilitado, a saída será: &lt;code>SELinux status: disabled&lt;/code>&lt;/p>&lt;h4 id="instalando-pré-requisitos">Instalando pré-requisitos&lt;/h4>&lt;ol>&lt;li>Vamos instalar alguns pré-requisitos antes de iniciar a instalação de fato:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sudo dnf install pciutils environment-modulessudo dnf install kernel-devel-$(uname -r) kernel-headerssudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpmsudo dnf clean all sudo dnf install dkms&lt;/code>&lt;/pre>&lt;ol start="2">&lt;li>Também precisamos habilitar alguns repositórios:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sudo subscription-manager repos --enable=rhel-8-for-ppc64le-appstream-rpmssudo subscription-manager repos --enable=rhel-8-for-ppc64le-baseos-rpmssudo subscription-manager repos --enable=codeready-builder-for-rhel-8-ppc64le-rpms&lt;/code>&lt;/pre>&lt;h4 id="baixando-e-instalando-repositórios-dos-pacotes-cuda">Baixando e instalando repositórios dos pacotes CUDA&lt;/h4>&lt;ol>&lt;li>Vamos baixar a versão &lt;strong>12.2 do CUDA&lt;/strong> e o &lt;strong>Driver NVIDIA 535.54.03-1&lt;/strong> com o comando seguinte:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>wget https://developer.download.nvidia.com/compute/cuda/12.2.0/local_installers/cuda-repo-rhel8-12-2-local-12.2.0_535.54.03-1.ppc64le.rpm&lt;/code>&lt;/pre>&lt;ol start="2">&lt;li>Para instalar o pacote baixado:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sudo rpm -i cuda-repo-rhel8-12-2-local-12.2.0_535.54.03-1.ppc64le.rpm&lt;/code>&lt;/pre>&lt;ol start="3">&lt;li>Para instalar o driver NVIDIA e o CUDA, os seguintes comandos serão executados:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sudo dnf install nvidia-driver-cuda sudo dnf clean all sudo dnf module reset nvidia-driver sudo dnf module enable nvidia-driver:latest-dkmssudo dnf -y module install nvidia-driver:latest-dkmssudo dnf -y install cuda &lt;/code>&lt;/pre>&lt;p>Com esses comandos a instalação do driver e do CUDA estão finalizadas.&lt;/p>&lt;h4 id="processos-pós-instalação">Processos pós-instalação&lt;/h4>&lt;ol>&lt;li>Vamos declarar as variáveis de ambiente &lt;code>PATH&lt;/code> e &lt;code>LD_LIBRARY_PATH&lt;/code>. Para isso, deve-se editar o arquivo &lt;code>.bashrc&lt;/code> e adicionar essas duas linhas:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>export PATH=/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH&lt;/code>&lt;/pre>&lt;p>Para atualizar as variáveis de ambiente, vamos executar o comando:&lt;/p>&lt;pre tabindex="0">&lt;code>source ~/.bashrc&lt;/code>&lt;/pre>&lt;p>Precisamos realizar duas mudanças de forma manual, pois não são tratadas de forma automática pela instalação dos pacotes CUDA. Caso não sejam realizadas, a instalação do driver CUDA ficará inoperante.&lt;/p>&lt;ol start="2">&lt;li>A primeira mudança será configurar o &lt;code>deamon&lt;/code> de persistência da NVIDIA. Primeiro vamos verificar o status e caso não esteja ativo, vamos ativar:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>systemctl status nvidia-persistencedsystemctl enable nvidia-persistenced&lt;/code>&lt;/pre>&lt;p>Algumas distros Linux possuem uma regra do udev que coloca a memória hot-plug em estado online assim que é detectada fisicamente, impedindo que o software da NVIDIA configure a memória da GPU com os parâmetros corretos no Power9.&lt;/p>&lt;ol start="3">&lt;li>Para desativar esta regra, vamos executar os comandos:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sudo cp /lib/udev/rules.d/40-redhat.rules /etc/udev/rules.d/sudo sed -i &amp;#39;s/SUBSYSTEM!=&amp;#34;memory&amp;#34;,.*GOTO=&amp;#34;memory_hotplug_end&amp;#34;/SUBSYSTEM==&amp;#34;*&amp;#34;, GOTO=&amp;#34;memory_hotplug_end&amp;#34;/&amp;#39; /etc/udev/rules.d/40-redhat.rules&lt;/code>&lt;/pre>&lt;h4 id="checagem-de-instalação">Checagem de instalação&lt;/h4>&lt;p>Após realizar todos esses procedimentos, vamos reiniciar a máquina e checar as instalações:&lt;/p>&lt;ol>&lt;li>Reiniciando a máquina:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sudo reboot&lt;/code>&lt;/pre>&lt;ol start="2">&lt;li>Checagem de driver NVIDIA:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>nvidia-smi&lt;/code>&lt;/pre>&lt;p>A saída do comando acima deve mostrar informações do compilador CUDA: versão e data de instalação. Além de mostrar os dispositivos (GPUs) disponíveis com nome, memória, temperatura entre outras informações.&lt;/p>&lt;p>Para realizar a última checagem, vamos baixar o repositório &lt;code>cuda-samples&lt;/code> e executar o teste de dispositivos.&lt;/p>&lt;ol start="3">&lt;li>Baixando o repositório e acessando a versão do &lt;code>cuda-samples&lt;/code> referente ao CUDA instalado:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>git clone https://github.com/NVIDIA/cuda-samples.git cd cuda-samples/Samples/1_Utilities/deviceQuerygit checkout v12.2 &lt;/code>&lt;/pre>&lt;ol start="4">&lt;li>Para buildar e executar os testes:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>make./deviceQuery&lt;/code>&lt;/pre>&lt;p>Após executar este teste, espera-se que na última linha contenha: &lt;code>Result = PASS&lt;/code>. Com isso, a Power9 está configurada, com driver NVIDIA e CUDA funcionando corretamente.&lt;/p>&lt;h2 id="configurando-cudnn">Configurando CUDNN&lt;/h2>&lt;ol>&lt;li>Inicialmente, precisamos baixar e instalar o &lt;code>.rpm&lt;/code> específico para &lt;code>ppc64le&lt;/code>.&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>wget https://developer.download.nvidia.com/compute/cudnn/9.0.0/local_installers/cudnn-local-repo-rhel8-9.0.0-1.0-1.ppc64le.rpmsudo rpm -i cudnn-local-repo-rhel8-9.0.0-1.0-1.ppc64le.rpmsudo dnf clean allsudo dnf -y install cudnn&lt;/code>&lt;/pre>&lt;ol start="2">&lt;li>Após a instalação, precisamos configurar as variáveis de ambiente &lt;code>CUDNN_LIBRARY&lt;/code> e &lt;code>CUDNN_INCLUDE_DIR&lt;/code>: (De uma forma mais direta do que fizemos anteriormente)&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>echo &amp;#39;export CUDNN_LIBRARY=/usr/lib64&amp;#39; &amp;gt;&amp;gt; ~/.bashrc echo &amp;#39;export CUDNN_LIBRARY=/usr/lib64&amp;#39; &amp;gt;&amp;gt; ~/.bashrc &lt;/code>&lt;/pre>&lt;p>Após isso, o processo de instalação do CUDNN está finalizado.&lt;/p>&lt;p>Esta é a primeira parte do nosso tutorial. Uma vez que todas as etapas mostradas neste post foram finalizadas, o servidor está pronto para ter o gerenciador de pacotes &lt;code>conda&lt;/code> e a biblioteca &lt;code>pytorch&lt;/code> instaladas, você pode acessar a segunda parte deste tutorial neste &lt;a href="https://llm-pt-ibm.github.io/posts/tutorial_power9_pt2_en/">&lt;span class="link-personalizado">link&lt;/span>&lt;/a>.&lt;/p></description></item><item><title>Avaliando LLMs de Pequeno Porte (até 8B) em Benchmarks PT-BR</title><link>https://llm-pt-ibm.github.io/posts/experimentos_benchmarks_pt_br/</link><pubDate>Mon, 02 Jun 2025 00:00:00 +0000</pubDate><guid>https://llm-pt-ibm.github.io/posts/experimentos_benchmarks_pt_br/</guid><description>&lt;h2 id="contexto">Contexto&lt;/h2>&lt;p>Este é o primeiro de dois posts desta série, que tem como objetivo apresentar um resumo da investigação que conduzimos utilizando o &lt;em>framework&lt;/em> de avaliação &lt;a href="https://github.com/stanford-crfm/helm" rel="external">&lt;span class="link-personalizado">HELM&lt;/span>&lt;/a> &lt;em>(Holistic Evaluation of Language Models)&lt;/em> para avaliar os modelos da família &lt;a href="https://huggingface.co/ibm-granite" rel="external">&lt;span class="link-personalizado">Granite&lt;/span>&lt;/a>, o modelo &lt;a href="https://huggingface.co/meta-llama/Llama-3.1-8B" rel="external">&lt;span class="link-personalizado">Llama-3.1-8B&lt;/span>&lt;/a> e o modelo &lt;a href="https://huggingface.co/deepseek-ai/DeepSeek-R1-Distill-Llama-8B" rel="external">&lt;span class="link-personalizado">DeepSeek-R1-Distill-Llama-3.1-8B&lt;/span>&lt;/a>. As avaliações contemplam tanto &lt;em>benchmarks&lt;/em> em português quanto tarefas voltadas à geração de código. Nesta primeira parte, o foco é avaliar o desempenho dos modelos no contexto do português brasileiro (PT-BR) para as tarefas de &lt;strong>análise de sentimentos&lt;/strong> e &lt;strong>MQA&lt;/strong> &lt;em>(Multiple-Choice Question Answering)&lt;/em>. Depois, na segunda parte, que será publicada em breve, abordará os resultados das avaliações em tarefas de geração de código.&lt;/p>&lt;p>O uso de conjuntos de dados em inglês para a avaliação de modelos de linguagem é uma prática comum. No entanto, para verificar a eficácia desses modelos em diferentes idiomas e contextos culturais, é relevante testá-los em &lt;em>benchmarks&lt;/em> de outras línguas. No caso do PT-BR, que costuma representar uma parcela menor dos dados utilizados no treinamento de modelos multilíngues, compreender o comportamento desses modelos é um passo importante para avaliar sua adequação a tarefas e contextos específicos dessa língua. Neste sentido, este post busca contribuir para esse entendimento, destacando avanços e desafios ainda presentes no desempenho dessas LLMs em tarefas no contexto do PT-BR.&lt;/p>&lt;h2 id="tldr">TL;DR&lt;/h2>&lt;div style="text-align: justify;">&lt;ul>&lt;li>Avaliamos os modelos: Granite, Llama-3.1-8B e DeepSeek-R1-Distill-Llama-3.1-8B nos &lt;em>benchmarks&lt;/em> ENEM Challenge, TweetSent-Br e IMDB.&lt;/li>&lt;li>Nosso método envolveu uma experimentação apoiada pelo &lt;em>framework&lt;/em> HELM, que apresentamos em detalhes neste documento.&lt;/li>&lt;li>Os resultados revelam que os modelos classificam com precisão os sentimentos em críticas de filmes em PT-BR.&lt;/li>&lt;/ul>&lt;/div>&lt;h2 id="método">Método&lt;/h2>&lt;h3 id="ambiente-de-execução-e-ferramenta-utilizada">Ambiente de Execução e Ferramenta Utilizada&lt;/h3>&lt;p>O HELM foi a ferramenta utilizada para conduzir as avaliações. Trata-se de um &lt;em>framework&lt;/em> de avaliação de LLMs, desenvolvido por pesquisadores da Universidade de Stanford, que contempla uma variedade de &lt;em>benchmarks&lt;/em>, como análise de sentimentos, geração de código, questões de múltipla escolha, entre outros. Com base nesses &lt;em>benchmarks&lt;/em>, utilizamos os modelos Granite (até 8B), Llama-3.1-8B e DeepSeek-R1-Distill-Llama-3.1-8B para medir e comparar seus desempenhos.&lt;/p>&lt;p>Para a execução dos experimentos, utilizamos o Google Colab como ambiente, que conta com uma GPU A100. Neste ambiente, foi possível clonar o repositório do HELM e executar modelos com até 8 bilhões de parâmetros. Todo o processo de configuração e testes foi realizado nessa plataforma, garantindo praticidade e acesso aos recursos computacionais necessários.&lt;/p>&lt;p>Em uma postagem futura, iremos detalhar as estratégias e ferramentas de avaliação de LLMs, com um foco mais aprofundado no funcionamento e nas capacidades do HELM.&lt;/p>&lt;h3 id="benchmarks-e-modelos">&lt;em>Benchmarks&lt;/em> e Modelos&lt;/h3>&lt;p>Para realizar os testes em cenários voltados ao português brasileiro, foi necessário estender o HELM com a inserção de novos &lt;em>benchmarks&lt;/em>, uma vez que, até então, a ferramenta não apresentava suporte para esse idioma. Essa iniciativa representou uma contribuição direta ao HELM, com a adição de três &lt;em>benchmarks&lt;/em>:&lt;/p>&lt;ul>&lt;li>&lt;p>&lt;a href="https://huggingface.co/datasets/eduagarcia/enem_challenge" rel="external">&lt;span class="link-personalizado">&lt;strong>ENEM Challenge&lt;/strong>&lt;/span>&lt;/a>: construído a partir de questões do Exame Nacional do Ensino Médio (ENEM), com o objetivo de avaliar a capacidade dos LLMs em resolver tarefas de MQA em diversas áreas do conhecimento, incluindo Ciências Humanas, Ciências da Natureza, Linguagens e Códigos e Matemática.&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;a href="https://huggingface.co/datasets/eduagarcia/tweetsentbr_fewshot" rel="external">&lt;span class="link-personalizado">&lt;strong>TweetSent-Br&lt;/strong>&lt;/span>&lt;/a>: composto por &lt;em>tweets&lt;/em>, voltado especificamente para tarefas de análise de sentimentos. O dataset é organizado em três classes principais de avaliação: positivo (&lt;em>tweets&lt;/em> que expressam uma reação ou avaliação positiva em relação ao tópico principal da postagem), negativo (&lt;em>tweets&lt;/em> que expressam uma reação ou avaliação negativa sobre o tema central) e neutro (&lt;em>tweets&lt;/em> que não se enquadram nas categorias anteriores).&lt;/p>&lt;/li>&lt;li>&lt;p>&lt;a href="https://huggingface.co/datasets/maritaca-ai/imdb_pt" rel="external">&lt;span class="link-personalizado">&lt;strong>IMDB&lt;/strong>&lt;/span>&lt;/a>: composto por críticas de filmes escritas em português brasileiro, esse &lt;em>benchmark&lt;/em> também se concentra em tarefas de classificação de sentimentos, mas utiliza textos originados de resenhas mais completas, ao contrário do TweetSent-Br, que usa publicações breves.&lt;/p>&lt;/li>&lt;/ul>&lt;p>Em relação aos modelos, a seleção foi guiada pela compatibilidade com a infraestrutura de execução disponível e com base na relevância de citações e performance. Estes incluem os modelos da família Granite, desenvolvidos pela IBM; os modelos Llama, da Meta; e o DeepSeek-R1-Distill-Llama-8B, uma versão compacta e otimizada derivada do Llama 3.1. Essa escolha permitiu uma comparação justa e viável entre os modelos.&lt;/p>&lt;h2 id="resultados">Resultados&lt;/h2>&lt;p>A seguir, apresentamos os resultados obtidos, acompanhados de gráficos desenvolvidos pela equipe, com o objetivo de facilitar a visualização e compreensão do desempenho dos modelos nas tarefas avaliadas.&lt;/p>&lt;ul>&lt;li>&lt;strong>ENEM Challenge&lt;/strong>:&lt;/li>&lt;/ul>&lt;!--&lt;div style="text-align: center;"> &lt;img src="https://llm-pt-ibm.github.io/images/experimentos_benchmarks_pt_br_image001.png" style="max-width: 90%;">&lt;/div> -->&lt;figure>&lt;img src="https://llm-pt-ibm.github.io/images/experimentos_benchmarks_pt_br_image001.png" alt="Gráfico dos resultados no ENEM Challenge"/>&lt;figcaption> &lt;p>Gráfico dos resultados no ENEM Challenge&lt;/p> &lt;/figcaption>&lt;/figure>&lt;p>Os resultados indicam que os modelos apresentaram desempenhos semelhantes, com uma leve vantagem para o Llama. Os modelos alcançaram uma média de acerto de 62,53%, esse percentual sugere que, embora os modelos demonstrem algum nível de compreensão das questões, ainda não possuem aptidão suficiente para responder de forma satisfatória às provas do ENEM, ou seja, para selecionar a alternativa correta. Há, portanto, um espaço para melhorias, especialmente no que diz respeito à capacidade de raciocínio e interpretação em língua portuguesa.&lt;/p>&lt;ul>&lt;li>&lt;strong>TweetSent-Br&lt;/strong>:&lt;/li>&lt;/ul>&lt;!--&lt;div style="text-align: center;"> &lt;img src="https://llm-pt-ibm.github.io/images/experimentos_benchmarks_pt_br_image002.png" style="max-width: 90%;">&lt;/div> -->&lt;figure>&lt;img src="https://llm-pt-ibm.github.io/images/experimentos_benchmarks_pt_br_image002.png" alt="Gráfico dos resultados no TweetSent-Br"/>&lt;figcaption> &lt;p>Gráfico dos resultados no TweetSent-Br&lt;/p> &lt;/figcaption>&lt;/figure>&lt;p>Nesse &lt;em>benchmark&lt;/em>, assim como observado no ENEM Challenge, os resultados também foram semelhantes entre os modelos. Isso reforça a percepção de que ainda existem lacunas no desempenho dos modelos em tarefas relacionadas à classificação de sentimentos em português. Classificar uma mensagem como positiva, negativa ou neutra ainda representa um desafio para esses modelos, especialmente diante das nuances e ambiguidades da linguagem.&lt;/p>&lt;ul>&lt;li>&lt;strong>IMDB&lt;/strong>:&lt;/li>&lt;/ul>&lt;!--&lt;div style="text-align: center;"> &lt;img src="https://llm-pt-ibm.github.io/images/experimentos_benchmarks_pt_br_image003.png" style="max-width: 90%;">&lt;/div>-->&lt;figure>&lt;img src="https://llm-pt-ibm.github.io/images/experimentos_benchmarks_pt_br_image003.png" alt="Gráfico dos resultados no IMDB"/>&lt;figcaption> &lt;p>Gráfico dos resultados no IMDB&lt;/p> &lt;/figcaption>&lt;/figure>&lt;p>No IMDB os resultados foram bastante positivos, os modelos apresentaram taxas de acerto superiores a 90%, demonstrando boa performance na tarefa de classificação de sentimentos. O destaque foi o modelo Granite com 8B de parâmetros, que teve uma leve superioridade em relação aos demais. Esses resultados indicam que os modelos conseguem categorizar com facilidade as críticas de filmes em português, mostrando maior domínio nesse tipo de tarefa.&lt;/p>&lt;h2 id="conclusão">Conclusão&lt;/h2>&lt;p>Com este estudo, foi possível obter uma visão mais clara sobre o desempenho dos modelos de linguagem em PT-BR, por meio da avaliação em três &lt;em>benchmarks&lt;/em> distintos. Os resultados indicam que os modelos analisados possuem desempenho razoável ao selecionar uma alternativa para áreas do conhecimento do ENEM, e evidenciam que ainda há espaço para melhorias. Por outro lado, em tarefas de análise de sentimentos no &lt;em>benchmark&lt;/em> IMDB, os modelos de pequeno porte demonstraram boa capacidade de classificação.&lt;/p>&lt;p>A equipe planeja, em estudos futuros, conduzir experimentos com modelos de grande porte, a fim de possibilitar comparações mais amplas de desempenho e eficiência. Isso permitirá uma análise detalhada dos erros cometidos por cada modelo, contribuindo para uma compreensão mais aprofundada de seus pontos fortes e limitações.&lt;/p></description></item><item><title>Realizando Inferências em CPU na Power10</title><link>https://llm-pt-ibm.github.io/posts/power10/</link><pubDate>Sun, 06 Apr 2025 00:00:00 +0000</pubDate><guid>https://llm-pt-ibm.github.io/posts/power10/</guid><description>&lt;h2 id="contexto">Contexto&lt;/h2>&lt;p>Neste post iremos apresentar a nossa experiência em executar o modelo Granite-20b-Code-Instruct em uma máquina Power10, apresentando os desafios e demais configurações necessárias para realizar inferências utilizando o Llama.cpp, uma das bibliotecas opensource mais populares neste domínio.&lt;/p>&lt;h2 id="tldr">TL;DR&lt;/h2>&lt;ul>&lt;li>Este post apresenta detalhes sobre como configurar e realizar inferências utilizando a infraestrutura da IBM Power 10;&lt;/li>&lt;li>Nosso maior desafio foi a configuração do Llama cpp, que demandou ajustes como a instalação do Ninja-builder, realização da compilação do OpenBLAS e atualização do compilador C.&lt;/li>&lt;/ul>&lt;h2 id="infraestrutura">Infraestrutura&lt;/h2>&lt;p>As inferências foram realizadas em uma máquina com arquitetura IBM POWER10, equipada com 750 GB de memória RAM e executando o sistema operacional Red Hat Enterprise Linux 8.10. O acesso ao ambiente é realizado por meio de uma VM, sendo necessário o uso de uma VPN para estabelecer uma comunicação segura e controlada com o sistema, possibilitando a execução das atividades de forma remota e eficiente.&lt;/p>&lt;h2 id="setup-inicial">Setup Inicial&lt;/h2>&lt;p>A biblioteca que nos permite executar LLMs utilizando os recursos computacionais da CPU é o Llama.cpp. Para a sua configuração, foi necessário resolver duas dependências externas: o Ninja-builder e o OpenBLAS. O NinjaBuilder é responsável por otimizar o processo de compilação, enquanto o OpenBLAS é uma biblioteca responsável pelos cálculos matriciais de alto desempenho.&lt;/p>&lt;p>Durante o processo de build do OpenBLAS, identificamos discrepâncias nos testes internos de validação dos cálculos matriciais, indicando um problema de compatibilidade com o compilador C disponível, que estava em uma versão mais antiga, a 8.5.0. A solução, portanto, &lt;strong>foi a atualização do compilador para uma versão mais recente, a 13.2&lt;/strong>, garantindo melhor compatibilidade com a arquitetura Power10 e validando a precisão das operações numéricas necessárias para o funcionamento do Llama.cpp. A seguir, apresentamos o passo a passo realizado para viabilizar a compilação das bibliotecas necessárias, bem como a atualização do compilador C.&lt;/p>&lt;ol>&lt;li>Criando o ambiente de compilação para o builder&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>sudo dnf update -y &amp;amp;&amp;amp; dnf -y groupinstall &amp;#39;Development Tools&amp;#39; &amp;amp;&amp;amp; dnf install -y \ cmake git ninja-build-debugsource.ppc64le \ &amp;amp;&amp;amp; dnf clean all&lt;/code>&lt;/pre>&lt;ol start="2">&lt;li>Atualizando compilador C e definindo variáveis de ambiente&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>scl enable gcc-toolset-13 bashexport CC=/usr/bin/gcc-13export CXX=/usr/bin/g++-13&lt;/code>&lt;/pre>&lt;ol start="3">&lt;li>Baixando e compilando o OpenBLAS&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>git clone --recursive https://github.com/DanielCasali/OpenBLAS.git &amp;amp;&amp;amp; cd OpenBLAS &amp;amp;&amp;amp; \ make -j$(nproc --all) TARGET=POWER10 DYNAMIC_ARCH=1 &amp;amp;&amp;amp; \ make PREFIX=/opt/OpenBLAS install &amp;amp;&amp;amp; \ cd /&lt;/code>&lt;/pre>&lt;ol start="4">&lt;li>Baixando e compilando o Llama.cpp usando a biblioteca OpenBLAS que acabamos de baixar&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code> git clone https://github.com/DanielCasali/llama.cpp.git &amp;amp;&amp;amp; cd llama.cpp &amp;amp;&amp;amp; sed -i &amp;#34;s/powerpc64le/native -mvsx -mtune=native -D__POWER10_VECTOR__/g&amp;#34; ggml/src/CMakeLists.txt &amp;amp;&amp;amp; \ mkdir build; \ cd build; \ cmake -DGGML_BLAS=ON -DGGML_BLAS_VENDOR=OpenBLAS -DBLAS_INCLUDE_DIRS=/opt/OpenBLAS/include -G Ninja ..; \ cmake --build . --config Release&lt;/code>&lt;/pre>&lt;p>Com todos esses passos realizados com sucesso, o ambiente foi devidamente configurado e otimizado para a execução local do Llama.cpp. Agora, somos capazes de iniciar um servidor para realizar inferências com LLM&amp;rsquo;s de forma eficiente, utilizando exclusivamente os recursos da CPU.&lt;/p>&lt;h2 id="realizando-inferência">Realizando Inferência&lt;/h2>&lt;p>Nós escolhemos o modelo Granite-20b-code-instruct no formato .GGUF, que é desenvolvido especificamente para otimizar o desempenho de modelos de linguagem em ambientes que utilizam apenas CPU. Esses modelos são quantizados, ou seja, a precisão dos cálculos feitos por eles são reduzidas, e, por conseguinte, o tamanho e consumo de memória também são menores, tornando-os ideais para a execução eficiente com Llama.cpp. Essa abordagem viabiliza inferências locais com alto desempenho, mesmo em arquiteturas baseadas exclusivamente em processadores, como é o caso da POWER10.O download do modelo foi feito diretamente do Hugging Face. A seguir, mostraremos o passo a passo para realizar o download:&lt;/p>&lt;ol>&lt;li>Criar um diretório para o modelo no Llama.cpp:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>mkdir -p /root/llama.cpp/models/granite-20b-code-instruct-8k-GGUF&lt;/code>&lt;/pre>&lt;ol start="2">&lt;li>Acessar o diretório no Llama.cpp:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>cd /root/llama.cpp/models/granite-20b-code-instruct-8k-GGUF&lt;/code>&lt;/pre>&lt;ol start="3">&lt;li>Baixar o modelo via Hugging Face:&lt;/li>&lt;/ol>&lt;pre tabindex="0">&lt;code>wget https://huggingface.co/ibm-granite/granite-20b-code-instruct-8k-GGUF/resolve/main/granite-20b-code-instruct.Q4_K_M.gguf&lt;/code>&lt;/pre>&lt;p>O último passo pode ser mais demorado a depender da quantidade de parâmetros do modelo. Todavia, após concluir os passos acima, podemos subir um servidor Llama.cpp para que seja possível realizarmos inferências, por padrão, o servidor é exposto na porta 8080 da Power10, mas isso é completamente customizável. O código a seguir ilustra como configurar e executar o servidor Llama:&lt;/p>&lt;pre tabindex="0">&lt;code>/root/llama.cpp/build/bin/llama-server --host 0.0.0.0 --model /root/llama.cpp/models/granite-20b-code-instruct-8k-GGUF/granite-20b-code-instruct.Q4_K_M.gguf&lt;/code>&lt;/pre>&lt;p>Com o servidor do Llama.cpp executando na porta 8080, agora somos capazes de realizar inferências via requisições HTTP. Neste exemplo, para fins de simplicidade, utilizamos o curl para requisições:&lt;/p>&lt;pre tabindex="0">&lt;code>curl -X POST http://localhost:8080/completion \ -H &amp;#34;Content-Type: application/json&amp;#34; \ -d &amp;#39;{ &amp;#34;prompt&amp;#34;: &amp;#34;Make a hello world program in Java. Your answer should be in Java code only.&amp;#34;, &amp;#34;max_tokens&amp;#34;: 100 }&amp;#39;&lt;/code>&lt;/pre>&lt;p>A seguir, um exemplo de como a resposta é retornada:&lt;/p>&lt;pre tabindex="0">&lt;code>{ &amp;#34;content&amp;#34;: &amp;#34;public class HelloWorld { public static void main(String[] args) { System.out.println(&amp;#34;Hello, World!&amp;#34;); }}&lt;/code>&lt;/pre>&lt;p>Com isso, agora somos capazes de realizar inferências em CPU. Nossos próximos passos visa realizar essas inferências utilizando o &lt;em>Framework&lt;/em> de avaliação HELM (&lt;em>Holistic Evaluation of Language Models&lt;/em>) como mediador.&lt;/p></description></item><item><title>Introdução</title><link>https://llm-pt-ibm.github.io/posts/introducao/</link><pubDate>Wed, 12 Mar 2025 00:00:00 +0000</pubDate><guid>https://llm-pt-ibm.github.io/posts/introducao/</guid><description>&lt;p>Bem-vindo ao blog da parceria entre a &lt;strong>Universidade Federal de Campina Grande (UFCG)&lt;/strong> e a &lt;strong>IBM&lt;/strong>!&lt;/p>&lt;p>Este espaço reúne artigos, tutoriais e resultados de pesquisa produzidos pela nossa equipe ao longo de diferentes projetos. Cada projeto aborda uma área de investigação distinta:&lt;/p>&lt;ul>&lt;li>&lt;strong>&lt;a href="https://llm-pt-ibm.github.io/projects/llm-eval/">LLM Evaluation&lt;/a>&lt;/strong> — avaliação de modelos de linguagem de grande porte, com foco em benchmarks para o português brasileiro.&lt;/li>&lt;li>&lt;strong>&lt;a href="https://llm-pt-ibm.github.io/projects/agents-ai">AgentOps&lt;/a>&lt;/strong> — criação de agentes de inteligência artificial capazes de executar múltiplas tarefas de forma autônoma.&lt;/li>&lt;li>&lt;strong>&lt;a href="https://llm-pt-ibm.github.io/projects/judo-ai/">Judo-AI&lt;/a>&lt;/strong> — uso de modelos de IA para análise de partidas e sessões de treinamento de judô, usando técnicas de visão computacional e deep learning para detecção de movimentos e reconhecimento de ações.&lt;/li>&lt;li>&lt;strong>&lt;a href="https://llm-pt-ibm.github.io/projects/5g/">5G&lt;/a>&lt;/strong> — interação de técnicas de IA em ambientes de rede 5G, com controle inteligente, otimização e mecanismos de gestão de rede.&lt;/li>&lt;li>&lt;strong>&lt;a href="https://llm-pt-ibm.github.io/projects/multiarq/">MultiArq&lt;/a>&lt;/strong> — provisão de ferramentas comuns para novas arquiteturas (ppc64le), buscando e adaptando ferramentas específicas e criando documentações técnicas acerca da arquitetura.&lt;/li>&lt;/ul>&lt;p>Explore os posts e acompanhe as novidades!&lt;/p></description></item></channel></rss>