Inteligência Artificial

O que aprendi ao tentar construir algo com uma LLM local

Embora minha experiência tenha começado com modelos locais, utilizando Ollama e Qwen, percebi que muitos dos desafios encontrados fazem parte do desenvolvimento de aplicações que utilizam LLMs em geral.

Valdiney França · 31 out 2026 · 5 min de leitura

Ao descobrir que era possível rodar uma LLM localmente na minha máquina, veio logo a vontade de criar algo ao redor dela. A ideia era montar um conjunto de ferramentas que pudessem ser utilizadas em conjunto.

Meu primeiro pensamento foi criar um cliente de chat persistente. Acho que muitas pessoas pensariam na mesma coisa, principalmente pela influência do ChatGPT. Porém, durante esse processo, acabei aprendendo algumas coisas muito interessantes.

Primeiro aprendizado: modelos não guardam o histórico da conversa por conta própria

Uma das primeiras coisas que descobri é que os modelos não guardam o histórico das conversas entre uma requisição e outra. Em termos simples, eles não se lembram automaticamente do que foi dito anteriormente. Cada nova requisição precisa receber as informações necessárias para que o modelo consiga entender o contexto.

É por isso que, normalmente, a aplicação que conversa com o modelo fica responsável por armazenar o histórico e enviá-lo novamente, junto com a nova mensagem do usuário. Esse comportamento é comum nas APIs de modelos como GPT, Claude e Gemini, embora algumas plataformas ofereçam recursos adicionais de memória e gerenciamento de conversas.

Segundo aprendizado: existe um limite para a quantidade de informações que um modelo consegue processar

Outro conceito importante é a janela de contexto (context window). Quando enviamos um texto para um modelo, esse conteúdo passa por um processo chamado tokenização. O texto é dividido em pequenas unidades chamadas tokens, que são representadas internamente por identificadores numéricos. Esses tokens são a forma como o modelo recebe e processa as informações.

O detalhe é que existe um limite para a quantidade de informações que ele consegue considerar em uma interação. Esse limite é chamado de janela de contexto e envolve as instruções, as mensagens anteriores, a nova solicitação e também o espaço utilizado para gerar a resposta. Além disso, existe um limite específico para a quantidade de tokens que o modelo pode gerar em uma resposta. Na API da Anthropic, por exemplo, utilizamos o parâmetro max_tokens para definir esse limite.

Se a geração atingir esse valor, o modelo interrompe a resposta. Na API da Anthropic, isso pode ser identificado pelo stop_reason com o valor max_tokens. O resultado pode ficar incompleto, inclusive com uma frase interrompida.

Outro ponto interessante é que provedores como Anthropic, OpenAI e Google podem cobrar valores diferentes pelos tokens de entrada e de saída. Em muitos modelos, os tokens de saída custam mais caro, embora isso dependa do modelo e do provedor.

Isso significa que não basta se preocupar apenas com o tamanho das informações que enviamos ao modelo. Também precisamos considerar o tamanho das respostas que solicitamos.

Terceiro aprendizado: como manter o histórico sem ultrapassar a janela de contexto

Voltando à ideia inicial de criar um chat persistente, surgiu outro desafio. Como o histórico cresce a cada mensagem, chega um momento em que não é possível continuar enviando toda a conversa ao modelo sem considerar o limite da janela de contexto.

Algumas alternativas para lidar com esse crescimento são:

  • Resumir a conversa: em vez de enviar todas as mensagens anteriores, a aplicação mantém um resumo com os principais acontecimentos e informações relevantes.
  • Remover mensagens antigas: manter apenas uma parte mais recente do histórico.

Mas essas estratégias exigem cuidado. Um resumo malfeito ou a remoção de mensagens importantes pode fazer o modelo perder referências, interpretar algo de forma equivocada ou produzir respostas que não consideram decisões anteriores da conversa. Ou seja, manter um histórico persistente não significa simplesmente salvar todas as mensagens em um banco de dados. Também precisamos pensar em como selecionar e organizar as informações que serão enviadas a cada nova interação.

Quarto aprendizado: streaming

Por último, uma coisa que fez bastante diferença na experiência de uso foi entender o streaming. Sem ele, a aplicação precisa aguardar a geração completa da resposta para só então apresentá-la ao usuário. Podemos até mostrar um indicador de carregamento, mas a sensação é de que nada está acontecendo.

Com streaming, a resposta começa a aparecer enquanto o modelo ainda está trabalhando. Em vez de esperar pelo resultado completo, a aplicação recebe pequenos fragmentos à medida que são gerados. Isso melhora bastante a experiência, principalmente quando o modelo demora alguns segundos para responder.

Também pode ajudar a reduzir problemas com tempo limite de espera (timeout) no cliente, já que os dados começam a chegar antes da conclusão da resposta. Naturalmente, isso não elimina todos os possíveis problemas de conexão ou de tempo limite. Na API da Anthropic, por exemplo, esse processo utiliza eventos enviados pelo servidor, conhecidos como SSE (Server-Sent Events).

Foi interessante perceber que uma funcionalidade aparentemente simples na interface envolve decisões importantes sobre comunicação entre a aplicação e o modelo.

#InteligenciaArtificial #LLM #LLMLocal #DesenvolvimentoDeSoftware #JanelaDeContexto #Tokens #Streaming #ArquiteturaDeSoftware #AprendizadoContinuo