<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Node.js on kenji.blog</title><link>http://kenji.blog/pt/tags/node.js/</link><description>Recent content in Node.js on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>pt</language><copyright>kenjinote</copyright><lastBuildDate>Fri, 11 Sep 2026 02:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/pt/tags/node.js/index.xml" rel="self" type="application/rss+xml"/><item><title>Construção Simples de LLM Local e Integração de API usando Ollama</title><link>http://kenji.blog/pt/p/ollama-local-llm-api-guide/</link><pubDate>Fri, 11 Sep 2026 02:00:00 +0900</pubDate><guid>http://kenji.blog/pt/p/ollama-local-llm-api-guide/</guid><description>&lt;img src="http://kenji.blog/p/ollama-local-llm-api-guide/img/eyecatch.jpg" alt="Featured image of post Construção Simples de LLM Local e Integração de API usando Ollama" />&lt;h1 id="introdução-por-que-precisamos-de-um-llm-local">Introdução: Por que precisamos de um LLM local?
&lt;/h1>&lt;p>Com a ascensão dos Grandes Modelos de Linguagem (LLMs), nossas vidas e métodos de desenvolvimento passaram por mudanças drásticas. Poderosos serviços de IA baseados em nuvem, como ChatGPT, Claude e Gemini, continuam evoluindo diariamente, oferecendo capacidades de raciocínio altamente avançadas. No entanto, um LLM baseado em nuvem não é necessariamente a melhor opção para todos os casos de uso. Os LLMs em nuvem apresentam os seguintes desafios:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Problemas de Privacidade e Segurança&lt;/strong>: Enviar dados contendo informações confidenciais ou pessoais para servidores externos costuma ser inaceitável do ponto de vista de segurança e conformidade corporativa.&lt;/li>
&lt;li>&lt;strong>Incerteza de Custos&lt;/strong>: Como as taxas de uso de API dependem do número de tokens, sistemas que processam grandes volumes de dados ou fazem solicitações frequentes correm o risco de ter custos operacionais ilimitados.&lt;/li>
&lt;li>&lt;strong>Latência e Dependência de Rede&lt;/strong>: O uso em ambientes offline ou a execução em dispositivos de borda (&lt;em>edge devices&lt;/em>), que exigem latência extremamente baixa, encontram na comunicação de rede um gargalo.&lt;/li>
&lt;li>&lt;strong>Dependência de Fornecedor (Vendor Lock-in)&lt;/strong>: A dependência de um modelo de um provedor específico pode torná-lo suscetível a encerramentos futuros do serviço, mudanças nos termos de uso e alterações não intencionais de comportamento devido a atualizações do modelo.&lt;/li>
&lt;/ol>
&lt;p>Os &amp;ldquo;LLMs locais&amp;rdquo; estão ganhando atenção como um meio para resolver esses desafios. Ao executar o modelo em seu próprio hardware, você pode utilizar a IA livremente sem enviar nenhum dado para o exterior e sem se preocupar com custos mensais.&lt;/p>
&lt;p>Neste artigo, explicaremos detalhadamente sobre o &amp;ldquo;&lt;strong>Ollama&lt;/strong>&amp;rdquo;, uma ferramenta que permite introduzir, gerenciar e integrar LLMs locais de forma incrivelmente fácil por meio de APIs. Abordaremos desde os fundamentos até sua arquitetura interna, integração avançada de API usando Python e Node.js e fórmulas para ajuste de desempenho.&lt;/p>
&lt;hr>
&lt;h1 id="o-que-é-o-ollama-sua-arquitetura-interna">O que é o Ollama? Sua Arquitetura Interna
&lt;/h1>&lt;p>O Ollama é uma plataforma para executar e gerenciar facilmente grandes modelos de linguagem de código aberto (Llama 3, Phi-3, Mistral, Gemma, etc.) em um ambiente local. Anteriormente, a construção de um ambiente LLM local exigia procedimentos extremamente complexos, como configurar o ambiente Python, instalar o kit de ferramentas CUDA, resolver dependências do PyTorch, baixar arquivos de modelos gigantescos do Hugging Face e convertê-los de formato (de Safetensors para GGUF, por exemplo).&lt;/p>
&lt;p>O Ollama oculta essas complexidades, permitindo que você lide com LLMs com a mesma facilidade de uso do Docker. Com um único comando, você pode baixar o modelo (&lt;code>pull&lt;/code>), executá-lo (&lt;code>run&lt;/code>) e iniciá-lo como um servidor HTTP.&lt;/p>
&lt;h2 id="tecnologia-principal-wrapper-do-llamacpp">Tecnologia Principal: Wrapper do llama.cpp
&lt;/h2>&lt;p>O backend do mecanismo de inferência do Ollama é o &amp;ldquo;&lt;strong>llama.cpp&lt;/strong>&amp;rdquo;, uma biblioteca de inferência de LLM de alta velocidade implementada em C/C++. O llama.cpp tem a capacidade de executar o modelo maximizando o desempenho do hardware, seja no Apple Silicon (Metal), GPU NVIDIA (CUDA), GPU AMD (ROCm) ou até mesmo em ambientes que usam apenas a CPU.&lt;/p>
&lt;p>O Ollama inclui o llama.cpp internamente e adota uma arquitetura onde o processo do servidor, escrito em linguagem Go, fornece uma API REST, chamando o mecanismo de inferência do llama.cpp em segundo plano.&lt;/p>
&lt;p>O diagrama Mermaid abaixo ilustra a arquitetura geral do Ollama.&lt;/p>
&lt;div class="mermaid">graph TD
A["Aplicativos Cliente (Python / Node.js)"] -- "HTTP/REST API" --> B["Servidor Ollama (Go)"]
B --> C["Gerenciador de Modelos (Lidando com GGUF)"]
B --> D["Mecanismo de Inferência (llama.cpp)"]
D --> E["Aceleração por GPU (CUDA / Metal / ROCm)"]
D --> F["Fallback de CPU (AVX2 / AVX-512)"]
C --> G["Armazenamento de Modelos Locais"]&lt;/div>
&lt;p>Com essa arquitetura, os desenvolvedores podem utilizar recursos avançados de inferência por meio de solicitações HTTP padrão, sem se preocuparem com compilações em C++ ou configurações detalhadas de drivers de GPU.&lt;/p>
&lt;hr>
&lt;h1 id="instalação-e-configuração-inicial-do-ollama">Instalação e Configuração Inicial do Ollama
&lt;/h1>&lt;p>A instalação do Ollama é muito simples. São fornecidos binários otimizados para cada sistema operacional.&lt;/p>
&lt;h2 id="macos--windows">macOS / Windows
&lt;/h2>&lt;p>Basta baixar o instalador do site oficial (&lt;a class="link" href="https://ollama.com/" target="_blank" rel="noopener"
>https://ollama.com/&lt;/a>) e executá-lo. A versão para macOS reconhece automaticamente a API Metal do Apple Silicon, enquanto a versão para Windows reconhece GPUs NVIDIA (CUDA), ativando a aceleração de hardware se estiverem disponíveis.&lt;/p>
&lt;h2 id="linux">Linux
&lt;/h2>&lt;p>Em ambientes Linux (como Ubuntu), ao executar o seguinte comando de uma linha, os componentes necessários são instalados e o servidor Ollama é iniciado como um serviço systemd.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">curl -fsSL https://ollama.com/install.sh &lt;span class="p">|&lt;/span> sh
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Após a conclusão da instalação, vamos verificar a versão no terminal.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ollama --version
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Se as informações da versão forem exibidas, a instalação foi realizada com sucesso.&lt;/p>
&lt;h2 id="execução-usando-docker">Execução usando Docker
&lt;/h2>&lt;p>Se você não deseja sujar o ambiente existente ou se quer integrá-lo a uma infraestrutura baseada em contêineres, é possível usar a imagem oficial do Docker. Para utilizar a GPU, é necessária a instalação do NVIDIA Container Toolkit.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Para executar usando apenas CPU&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Para utilizar a GPU NVIDIA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">docker run -d --gpus&lt;span class="o">=&lt;/span>all -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Por padrão, o servidor Ollama escuta em &lt;code>http://localhost:11434&lt;/code>.&lt;/p>
&lt;hr>
&lt;h1 id="gerenciamento-de-modelos-e-comandos-básicos-da-cli">Gerenciamento de Modelos e Comandos Básicos da CLI
&lt;/h1>&lt;p>O maior atrativo do Ollama é que o gerenciamento de modelos é muito intuitivo. Você pode experimentar vários modelos com a mesma facilidade de lidar com imagens Docker.&lt;/p>
&lt;h2 id="1-execução-do-modelo-run">1. Execução do Modelo (&lt;code>run&lt;/code>)
&lt;/h2>&lt;p>Este é o comando usado com mais frequência. Se o modelo especificado não existir, ele será baixado automaticamente (&lt;code>pull&lt;/code>) e, em seguida, um prompt interativo será iniciado.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ollama run llama3.1
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ao executar o comando acima, o Llama 3.1 (versão de parâmetros de 8B), o modelo mais recente da Meta, será iniciado. Ao digitar uma mensagem no prompt, a resposta do modelo será exibida via streaming. Para sair, digite &lt;code>/bye&lt;/code> ou &lt;code>Ctrl+D&lt;/code>.&lt;/p>
&lt;h2 id="2-download-do-modelo-pull">2. Download do Modelo (&lt;code>pull&lt;/code>)
&lt;/h2>&lt;p>Use o comando &lt;code>pull&lt;/code> se quiser baixar o modelo em segundo plano.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ollama pull phi3:instruct
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ollama pull mistral:v0.3
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Na biblioteca de modelos do Ollama, você pode especificar a versão ou o nível de quantização no formato &lt;code>nome-do-modelo:tag&lt;/code>. Se a tag for omitida, &lt;code>latest&lt;/code> será aplicado, mas também é possível especificar explicitamente um modelo quantizado específico (por exemplo: &lt;code>llama3:8b-instruct-q4_0&lt;/code>).&lt;/p>
&lt;h3 id="o-que-é-quantização">O que é Quantização?
&lt;/h3>&lt;p>Vamos abordar brevemente a quantização aqui. Em LLMs comuns, um único parâmetro de peso é mantido em formato de ponto flutuante de 16 bits (FP16), por exemplo. Para um modelo com 8 bilhões (8B) de parâmetros, apenas os pesos consumiriam cerca de 16 GB de VRAM. A quantização é a técnica que comprime isso em tipos inteiros de 4 bits (Q4) ou 8 bits (Q8).&lt;/p>
&lt;p>Com a quantização, o consumo de memória necessário e a largura de banda da memória podem ser reduzidos drasticamente, enquanto a degradação da precisão do modelo é minimizada. Os modelos distribuídos pelo Ollama estão, por padrão, no formato GGUF e aplicam a quantização ideal (na maioria das vezes 4 bits).&lt;/p>
&lt;h2 id="3-listagem-de-modelos-list">3. Listagem de Modelos (&lt;code>list&lt;/code>)
&lt;/h2>&lt;p>Exibe uma lista dos modelos baixados localmente e seus respectivos tamanhos.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ollama list
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Exemplo de saída:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">NAME ID SIZE MODIFIED
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">llama3.1:latest 43f7a214e532 4.7 GB 2 hours ago
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">phi3:instruct a2c89ceaed85 2.3 GB 3 days ago
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="4-remoção-de-modelo-rm">4. Remoção de Modelo (&lt;code>rm&lt;/code>)
&lt;/h2>&lt;p>Libere espaço em disco excluindo modelos que não são mais necessários.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ollama rm phi3:instruct
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h1 id="personalização-de-modelo-usando-o-modelfile">Personalização de Modelo usando o Modelfile
&lt;/h1>&lt;p>No Ollama, você pode usar um mecanismo chamado &amp;ldquo;&lt;strong>Modelfile&lt;/strong>&amp;rdquo; para criar seu próprio modelo personalizado ajustando hiperparâmetros ou injetando um prompt de sistema no modelo existente. É exatamente o mesmo conceito do Dockerfile do Docker.&lt;/p>
&lt;p>O diagrama abaixo mostra como um modelo personalizado deriva do modelo base.&lt;/p>
&lt;div class="mermaid">graph LR
A["Modelo Base (llama3.1)"] -->|"Adicionar Prompt de Sistema"| B["Configuração Intermediária"]
B -->|"Definir Temperature &amp; Top_p"| C["Modelo Personalizado (kansai-coder)"]
C -->|"Executar"| D["CLI Interativo / API"]&lt;/div>
&lt;p>Como exemplo, vamos criar um modelo assistente de programação que responde em dialeto Kansai (japonês).&lt;/p>
&lt;p>Crie um arquivo de texto com o nome &lt;code>Modelfile&lt;/code> no seu diretório de trabalho e escreva o seguinte:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl"># Especifica o modelo base
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">FROM llama3.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># Define hiperparâmetros como criatividade (temperature)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">PARAMETER temperature 0.7
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">PARAMETER top_p 0.9
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">PARAMETER repeat_penalty 1.1
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">PARAMETER num_ctx 4096
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># Configura o prompt de sistema
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">SYSTEM &amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Você é um engenheiro de software sênior de classe mundial.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Você deve responder às perguntas técnicas dos usuários de maneira amigável, utilizando um tom coloquial ou um dialeto regional.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">Ao mostrar exemplos de código, forneça um código moderno que siga as melhores práticas.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Crie (compile) um novo modelo a partir deste Modelfile.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ollama create kansai-coder -f Modelfile
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Após a conclusão da compilação, vamos executá-lo e testá-lo.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">ollama run kansai-coder
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;gt;&amp;gt;&amp;gt; Como faço para classificar uma lista em Python?
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>A resposta será algo como: &amp;ldquo;Olha, você pode usar a função &lt;code>sorted()&lt;/code> ou o método &lt;code>sort()&lt;/code> do Python!&amp;rdquo;, mostrando um comportamento personalizado. Isso permite criar e gerenciar uma infinidade de agentes locais especializados para cada caso de uso.&lt;/p>
&lt;hr>
&lt;h1 id="explicação-completa-da-rest-api-do-ollama">Explicação Completa da REST API do Ollama
&lt;/h1>&lt;p>A interação por meio do CLI é conveniente, mas na prática, o verdadeiro valor do Ollama no desenvolvimento de aplicativos está em sua poderosa API REST. Você pode obter resultados de inferência enviando solicitações HTTP para o processo do servidor (por padrão, &lt;code>http://localhost:11434&lt;/code>).&lt;/p>
&lt;p>Os três principais endpoints são os seguintes:&lt;/p>
&lt;ol>
&lt;li>&lt;code>/api/generate&lt;/code>: Geração de texto a partir de um prompt único&lt;/li>
&lt;li>&lt;code>/api/chat&lt;/code>: Geração de chat (diálogo) semelhante à API da OpenAI&lt;/li>
&lt;li>&lt;code>/api/embeddings&lt;/code>: Geração de embeddings de vetor&lt;/li>
&lt;/ol>
&lt;h2 id="geração-de-texto-com-apigenerate">Geração de texto com /api/generate
&lt;/h2>&lt;p>Este é o endpoint de geração mais básico. Vamos tentar enviar uma solicitação usando cURL.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">curl -X POST http://localhost:11434/api/generate -d &lt;span class="s1">&amp;#39;{
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#34;model&amp;#34;: &amp;#34;llama3.1&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#34;prompt&amp;#34;: &amp;#34;Explain the concept of quantum entanglement in simple terms.&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#34;stream&amp;#34;: false
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ao definir &lt;code>&amp;quot;stream&amp;quot;: false&lt;/code>, todo o JSON é retornado de uma vez após a conclusão da geração. O padrão (&lt;code>true&lt;/code>) envia os tokens gerados sequencialmente em formato JSON Lines, o que é adequado para a implementação de UIs de streaming.&lt;/p>
&lt;p>Exemplo de resposta (parcialmente omitida):&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;model&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;llama3.1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;created_at&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2026-09-11T10:00:00.000Z&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;response&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Quantum entanglement is like having a pair of magical dice...&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;done&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;context&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">128006&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">882&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">128007&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">271&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10445&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;total_duration&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">4567890000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;load_duration&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1234000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;prompt_eval_count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">14&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;eval_count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">256&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;eval_duration&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">4321000000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>A matriz &lt;code>context&lt;/code> codifica os estados de conversação passados, e você pode manter o contexto incluindo-a na sua próxima solicitação. Contudo, para um gerenciamento mais fácil do histórico de conversas, utilizamos o &lt;code>/api/chat&lt;/code> a seguir.&lt;/p>
&lt;h2 id="geração-de-chat-com-apichat">Geração de chat com /api/chat
&lt;/h2>&lt;p>Como os LLMs recentes são ajustados (&lt;em>fine-tuned&lt;/em>) para formato de chat, o uso de &lt;code>/api/chat&lt;/code> é recomendado no desenvolvimento de aplicativos.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">curl -X POST http://localhost:11434/api/chat -d &lt;span class="s1">&amp;#39;{
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#34;model&amp;#34;: &amp;#34;llama3.1&amp;#34;,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#34;messages&amp;#34;: [
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> { &amp;#34;role&amp;#34;: &amp;#34;system&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;You are a helpful AI assistant.&amp;#34; },
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> { &amp;#34;role&amp;#34;: &amp;#34;user&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;What is the capital of France?&amp;#34; },
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> { &amp;#34;role&amp;#34;: &amp;#34;assistant&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;The capital of France is Paris.&amp;#34; },
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> { &amp;#34;role&amp;#34;: &amp;#34;user&amp;#34;, &amp;#34;content&amp;#34;: &amp;#34;What is its famous tower?&amp;#34; }
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ],
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#34;stream&amp;#34;: false
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1">}&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dessa forma, você pode lidar facilmente com contextos de conversação complexos passando uma matriz de objetos de mensagens com atribuições de &lt;code>role&lt;/code> (system, user, assistant).&lt;/p>
&lt;hr>
&lt;h1 id="integração-com-aplicações-python">Integração com Aplicações Python
&lt;/h1>&lt;p>Python é a linguagem padrão no desenvolvimento de IA. Existem várias maneiras de usar o Ollama com Python, mas o pacote oficial &lt;code>ollama-python&lt;/code> é a forma mais fácil e confiável.&lt;/p>
&lt;h2 id="instalação">Instalação
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">pip install ollama
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="uso-da-api-síncrona">Uso da API Síncrona
&lt;/h2>&lt;p>Este é o código básico para geração de chat.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ollama&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Lista para manter o histórico de chat&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">messages&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;role&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;system&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Você é um excelente assistente.&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">chat_with_ollama&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">user_input&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s1">&amp;#39;role&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;user&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">user_input&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Chama a API do Ollama&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ollama&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chat&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;llama3.1&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">messages&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">assistant_reply&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;message&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s1">&amp;#39;role&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;assistant&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">assistant_reply&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">assistant_reply&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">chat_with_ollama&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Quais são as três principais abordagens de aprendizado de máquina?&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="uso-de-streaming-assíncrono">Uso de Streaming Assíncrono
&lt;/h2>&lt;p>Ao desenvolver aplicativos web (como FastAPI e Starlette) ou bots para Discord e Slack, é essencial utilizar a API assíncrona e streaming para evitar bloqueios.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">asyncio&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">ollama&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">AsyncClient&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">async&lt;/span> &lt;span class="k">def&lt;/span> &lt;span class="nf">generate_stream&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">client&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">AsyncClient&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Ao definir stream=True, um gerador assíncrono é retornado&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">async&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">chunk&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="n">client&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chat&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;llama3.1&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">messages&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[{&lt;/span>&lt;span class="s1">&amp;#39;role&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;user&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Explique em detalhes os decoradores do Python.&amp;#39;&lt;/span>&lt;span class="p">}],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">stream&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Exibição sequencial na saída padrão para cada chunk&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">chunk&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;message&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">end&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">flush&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1"># Quebra de linha no final&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Executar a função assíncrona&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">asyncio&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">generate_stream&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dessa forma, você pode implementar facilmente uma experiência de usuário (UX) onde os caracteres vão aparecendo um a um, de maneira similar à interface do ChatGPT.&lt;/p>
&lt;h2 id="integração-com-langchain-e-llamaindex">Integração com LangChain e LlamaIndex
&lt;/h2>&lt;p>O Ollama é suportado nativamente no LangChain e no LlamaIndex, que são frequentemente usados na criação de sistemas de RAG (&lt;em>Retrieval-Augmented Generation&lt;/em>).&lt;/p>
&lt;p>Exemplo no LangChain:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">langchain_community.llms&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Ollama&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Ollama&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;llama3.1&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">llm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">invoke&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Explain dark matter.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Você pode executar localmente as poderosas funcionalidades de cadeias (&lt;em>chains&lt;/em>) e agentes do LangChain sem precisar configurar nenhuma chave de API externa.&lt;/p>
&lt;hr>
&lt;h1 id="integração-com-aplicações-nodejs">Integração com Aplicações Node.js
&lt;/h1>&lt;p>Para engenheiros front-end e desenvolvedores full-stack, a capacidade de chamar um LLM local a partir do ambiente TypeScript/Node.js é uma enorme vantagem. Utilizaremos o pacote NPM oficial &lt;code>ollama&lt;/code>.&lt;/p>
&lt;h2 id="instalação-1">Instalação
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">npm install ollama
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="exemplo-de-implementação-de-chatbot-usando-typescript">Exemplo de Implementação de Chatbot usando TypeScript
&lt;/h2>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-typescript" data-lang="typescript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="nx">ollama&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">Message&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="kr">from&lt;/span> &lt;span class="s1">&amp;#39;ollama&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">async&lt;/span> &lt;span class="kd">function&lt;/span> &lt;span class="nx">runChatbot() {&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">messages&lt;/span>: &lt;span class="kt">Message&lt;/span>&lt;span class="p">[]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span> &lt;span class="nx">role&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;system&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">content&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;You are a concise expert.&amp;#39;&lt;/span> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span> &lt;span class="nx">role&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;user&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">content&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;Explain RESTful APIs.&amp;#39;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">await&lt;/span> &lt;span class="nx">ollama&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">chat&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">model&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;llama3.1&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">messages&lt;/span>: &lt;span class="kt">messages&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">stream&lt;/span>: &lt;span class="kt">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Assistant:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">response&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">message&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">content&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">error&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">error&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Error communicating with Ollama:&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">error&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">runChatbot&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="construção-de-servidor-express-com-suporte-a-streaming">Construção de Servidor Express com Suporte a Streaming
&lt;/h2>&lt;p>Abaixo está um exemplo de implementação de uma API backend que retorna uma resposta via streaming para o frontend web. Ele envia blocos (chunks) usando SSE (Server-Sent Events) ou streaming HTTP comum.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="nx">express&lt;/span> &lt;span class="nx">from&lt;/span> &lt;span class="s1">&amp;#39;express&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">import&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">Ollama&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="nx">from&lt;/span> &lt;span class="s1">&amp;#39;ollama&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">app&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">express&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">use&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">express&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">json&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">const&lt;/span> &lt;span class="nx">ollama&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="nx">Ollama&lt;/span>&lt;span class="p">({&lt;/span> &lt;span class="nx">host&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;http://127.0.0.1:11434&amp;#39;&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">post&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;/api/stream-chat&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kr">async&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">req&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">res&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nx">prompt&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">req&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">body&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Configuração do cabeçalho de resposta HTTP (transferência em blocos)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nx">res&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">setHeader&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Content-Type&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;text/plain; charset=utf-8&amp;#39;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">res&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">setHeader&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Transfer-Encoding&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;chunked&amp;#39;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">const&lt;/span> &lt;span class="nx">stream&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kr">await&lt;/span> &lt;span class="nx">ollama&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">generate&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">model&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;llama3.1&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">prompt&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="nx">prompt&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">stream&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="kr">await&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kr">const&lt;/span> &lt;span class="nx">chunk&lt;/span> &lt;span class="k">of&lt;/span> &lt;span class="nx">stream&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">res&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">chunk&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">response&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">res&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">end&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">err&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">res&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">status&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">500&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="nx">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Error generating response.&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">res&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">end&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nx">app&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">listen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3000&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">()&lt;/span> &lt;span class="p">=&amp;gt;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Server is running on port 3000&amp;#39;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h1 id="métricas-de-desempenho-e-análise-matemática">Métricas de Desempenho e Análise Matemática
&lt;/h1>&lt;p>Para prover um LLM local em um nível viável para produção, é indispensável analisar latência e taxa de transferência (&lt;em>throughput&lt;/em>). As respostas da API do Ollama contêm métricas detalhadas sobre o desempenho.&lt;/p>
&lt;h2 id="modelo-de-cálculo-para-a-velocidade-de-geração-de-tokens">Modelo de Cálculo para a Velocidade de Geração de Tokens
&lt;/h2>&lt;p>O tempo de resposta do LLM, que está diretamente ligado à experiência do usuário, pode ser amplamente dividido em &amp;ldquo;&lt;strong>Tempo para o Primeiro Token (TTFT - Time To First Token)&lt;/strong>&amp;rdquo; e &amp;ldquo;&lt;strong>Tempo por Token de Saída (TPOT - Time Per Output Token)&lt;/strong>&amp;rdquo;.&lt;/p>
&lt;p>O tempo total de geração $T_{total}$ pode ser formulado conforme abaixo, supondo que $N$ seja o número de tokens gerados:&lt;/p>
$$
T_{total} = t_{ttft} + \sum_{i=1}^{N-1} t_{tpot}^{(i)}
$$
&lt;p>Aqui, se aproximarmos o tempo médio para gerar cada token para $\bar{t}_{tpot}$, a equação é simplificada:&lt;/p>
$$
T_{total} \approx t_{ttft} + (N - 1) \times \bar{t}_{tpot}
$$
&lt;p>A correspondência com os campos de resposta da API do Ollama é a seguinte:&lt;/p>
&lt;ul>
&lt;li>&lt;code>prompt_eval_duration&lt;/code>: Corresponde aproximadamente ao $t_{ttft}$ (tempo de avaliação do prompt). Retornado em nanossegundos.&lt;/li>
&lt;li>&lt;code>eval_duration&lt;/code>: O tempo total gasto no processo de geração.&lt;/li>
&lt;li>&lt;code>eval_count&lt;/code>: O número $N$ de tokens gerados.&lt;/li>
&lt;/ul>
&lt;p>Portanto, a taxa de geração de tokens por segundo (Tokens Per Second: TPS) pode ser calculada usando a seguinte fórmula:&lt;/p>
$$
TPS = \frac{eval\_count}{(eval\_duration / 10^9)} \quad [\text{tokens/sec}]
$$
&lt;p>Por exemplo, se tivermos &lt;code>eval_count: 256&lt;/code> e &lt;code>eval_duration: 4321000000&lt;/code> (cerca de 4,32 segundos):
&lt;/p>
$$
TPS = \frac{256}{4.321} \approx 59.24 \text{ tokens/sec}
$$
&lt;p>
Como resultado, temos cerca de 59,24 tokens/segundo. Em um ambiente local, se ultrapassar 50 tokens por segundo, você estará oferecendo uma experiência de resposta muito confortável, excedendo de longe a velocidade de leitura humana.&lt;/p>
&lt;h2 id="equação-de-estimativa-para-capacidade-de-vram-necessária">Equação de Estimativa para Capacidade de VRAM Necessária
&lt;/h2>&lt;p>Ao executar um modelo localmente, a capacidade do modelo caber na VRAM da GPU é a chave para o desempenho. Se não couber e recair (fallback) para a memória principal (RAM) do sistema, a velocidade de geração cairá significativamente.&lt;/p>
&lt;p>Uma fórmula simplificada para estimar a capacidade de memória necessária $M$ (em gigabytes) é a seguinte:&lt;/p>
$$
M \approx \frac{P \times Q}{8 \times 1024} + C
$$
&lt;ul>
&lt;li>$P$: O número de parâmetros do modelo (Exemplo: 8B = $8000 \times 10^6$)&lt;/li>
&lt;li>$Q$: Número de bits da quantização (Ex: 4-bit, 8-bit, 16-bit)&lt;/li>
&lt;li>$C$: Memória adicional para a janela de contexto (Cache KV, etc. Depende do modelo e das configurações, mas geralmente aloca-se entre 1 e 2 GB)&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Exemplo de cálculo&lt;/strong>: Para rodar o Llama 3 (com 8B de parâmetros) usando quantização de 4 bits:
&lt;/p>
$$
M_{model} = \frac{8,000 \times 4}{8 \times 1024} = \frac{32,000}{8192} \approx 3.9 \text{ GB}
$$
&lt;p>
Ao adicionar a memória para contexto a isso, notamos que se você tiver de 5 GB a 6 GB de VRAM, é possível carregar completamente o modelo (Full Offload) na GPU. Assim, mesmo com placas de vídeo de classe intermediária (como a RTX 4060) que vêm com 8 GB de VRAM, é totalmente possível rodar LLMs poderosos de maneira eficiente.&lt;/p>
&lt;hr>
&lt;h1 id="casos-de-uso-avançados-e-conclusão">Casos de Uso Avançados e Conclusão
&lt;/h1>&lt;p>Ao expor o Ollama como uma API em uma rede local, uma série de aplicações além dos simples chatbots tornam-se possíveis.&lt;/p>
&lt;h3 id="1-construção-de-um-rag-local-retrieval-augmented-generation">1. Construção de um RAG Local (Retrieval-Augmented Generation)
&lt;/h3>&lt;p>Ao combinar bancos de dados vetoriais locais como ChromaDB ou Qdrant com o endpoint &lt;code>/api/embeddings&lt;/code> do Ollama (usando um modelo de embeddings como &lt;code>nomic-embed-text&lt;/code>), você pode criar um sistema RAG completamente offline e seguro para responder a perguntas, inserindo os documentos confidenciais da sua empresa.&lt;/p>
&lt;h3 id="2-assistente-de-ia-para-ides-e-editores">2. Assistente de IA para IDEs e Editores
&lt;/h3>&lt;p>Ao definir o Ollama como backend para extensões de VS Code (como o Continue.dev) ou plug-ins do Neovim, você pode usar um modelo local (como &lt;code>codellama&lt;/code> ou &lt;code>deepseek-coder&lt;/code>) de forma gratuita, oferecendo preenchimento ou explicação de código nos moldes do GitHub Copilot.&lt;/p>
&lt;h3 id="3-integração-em-scripts-de-automação">3. Integração em Scripts de Automação
&lt;/h3>&lt;p>Ao integrar as solicitações de API do Ollama em scripts Python e Shell, você pode infundir o poder da IA em todas as partes do seu fluxo de trabalho diário, como o resumo automatizado de logs, a geração de mensagens de commit no Git e tarefas de classificação de textos padronizados.&lt;/p>
&lt;h2 id="conclusão">Conclusão
&lt;/h2>&lt;p>Com a chegada do Ollama, a barreira de entrada para introduzir LLMs locais caiu drasticamente. A combinação de uma estrutura de comandos simples, como operar contêineres Docker, com uma API REST facilmente acessível a partir de aplicativos externos, é o atual padrão de mercado no desenvolvimento de IA local, sem exagero.&lt;/p>
&lt;p>Desenvolvedores que sofrem com as restrições de custos e segurança dos LLMs em nuvem devem aproveitar as etapas introduzidas neste artigo para tentar construir um ambiente LLM local usando o Ollama e integrá-lo em seus aplicativos. Vocês poderão sentir o potencial da IA de maneira muito mais livre e próxima.&lt;/p></description></item></channel></rss>