Guia Técnico

Como Integrar LLMsem Aplicações

Da primeira chamada à API até streaming, function calling, RAG e gestão de custos em produção. Um guia técnico completo para 2026, com exemplos em Python e JavaScript.

IntermediárioPythonJavaScriptAPI RESTRAGProdução

Pré-requisitos

Conhecimento básico de Python ou JavaScript
Conta em OpenAI, Anthropic ou Google (API key)
Familiaridade com HTTP e APIs REST
01

Escolha do Modelo e Provedor

A primeira decisão impacta custo, qualidade e latência. Para a maioria dos casos: comece com um modelo mid-tier (GPT-4o-mini, Claude Haiku, Gemini Flash) e suba para frontier somente se qualidade for insuficiente.

CritérioEscolha
Qualidade máximaGPT-4o, Claude Sonnet 4, Gemini 2.5 Pro
Custo-benefícioGPT-4o-mini, Claude Haiku, Gemini Flash
Velocidade (chatbot real-time)Groq (Llama), Claude Haiku, Gemini Flash
Privacidade / on-premisesLlama 3.1, Mistral, Qwen 2.5 via Ollama
Context longo (200K+)Claude Sonnet, Gemini 2.5 Pro
Código e programaçãoClaude Sonnet, GPT-4o, DeepSeek Coder

Dica de produção: use LiteLLM como camada de abstração. Você escreve o código uma vez e troca de modelo mudando apenas uma variável de ambiente. Economiza reescrita quando preços ou qualidade mudam.

02

Chamada Básica à API

Toda integração começa com uma chamada simples. O padrão é o mesmo em todos os provedores principais: mensagens com roles (system, user, assistant).

Python
from openai import OpenAI

client = OpenAI(api_key="sua-chave-aqui")

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {
            "role": "system",
            "content": "Você é um assistente útil em PT-BR."
        },
        {
            "role": "user",
            "content": "Explique o que é RAG em 2 parágrafos."
        }
    ],
    max_tokens=500,
    temperature=0.7,
)

print(response.choices[0].message.content)
print(f"Tokens usados: {response.usage.total_tokens}")
JavaScript / Node.js
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

const response = await client.chat.completions.create({
  model: "gpt-4o-mini",
  messages: [
    {
      role: "system",
      content: "Você é um assistente útil em PT-BR.",
    },
    {
      role: "user",
      content: "Explique o que é RAG em 2 parágrafos.",
    },
  ],
  max_tokens: 500,
  temperature: 0.7,
});

console.log(response.choices[0].message.content);
console.log(`Tokens: ${response.usage.total_tokens}`);
03

Streaming para UX Responsiva

Com streaming, tokens aparecem à medida que são gerados — como o ChatGPT faz. A percepção de velocidade melhora drasticamente sem reduzir o tempo total de processamento.

Python — Streaming
with client.chat.completions.stream(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Escreva um poema sobre IA"}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)  # imprime token a token
Next.js — API Route com Streaming (Edge Runtime)
// app/api/chat/route.ts
import { OpenAIStream, StreamingTextResponse } from "ai"; // Vercel AI SDK
import OpenAI from "openai";

export const runtime = "edge";

const openai = new OpenAI();

export async function POST(req: Request) {
  const { messages } = await req.json();

  const response = await openai.chat.completions.create({
    model: "gpt-4o-mini",
    stream: true,
    messages,
  });

  const stream = OpenAIStream(response);
  return new StreamingTextResponse(stream);
}
04

Function Calling

Function calling permite que o LLM decida quando e como chamar funções que você define. É a base de agentes — o modelo pode buscar dados externos, chamar APIs e executar ações.

Python — Function Calling
import json

tools = [
    {
        "type": "function",
        "function": {
            "name": "buscar_preco_modelo",
            "description": "Busca o preço de um modelo de LLM por nome",
            "parameters": {
                "type": "object",
                "properties": {
                    "nome_modelo": {
                        "type": "string",
                        "description": "Nome do modelo, ex: gpt-4o-mini"
                    }
                },
                "required": ["nome_modelo"]
            }
        }
    }
]

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Quanto custa o GPT-4o?"}],
    tools=tools,
    tool_choice="auto",
)

if response.choices[0].finish_reason == "tool_calls":
    tool_call = response.choices[0].message.tool_calls[0]
    args = json.loads(tool_call.function.arguments)
    # Aqui você executa a função real
    resultado = buscar_preco_modelo(args["nome_modelo"])
    print(f"Modelo chamou: {tool_call.function.name}({args})")
05

RAG — Contexto com Seus Dados

RAG (Retrieval-Augmented Generation) permite que o LLM responda com base nos seus dados sem fine-tuning. Você recupera trechos relevantes de um banco vetorial e os injeta no contexto da requisição.

Python — RAG Simples com OpenAI Embeddings
import numpy as np

# 1. Gerar embedding da pergunta do usuário
def get_embedding(text: str) -> list[float]:
    response = client.embeddings.create(
        model="text-embedding-3-small",
        input=text
    )
    return response.data[0].embedding

# 2. Buscar trechos relevantes (simplificado — use pgvector/Pinecone em prod)
def buscar_contexto(pergunta: str, documentos: list[dict]) -> str:
    emb_pergunta = get_embedding(pergunta)

    # Calcular similaridade cosseno com cada documento
    scores = []
    for doc in documentos:
        score = np.dot(emb_pergunta, doc["embedding"]) / (
            np.linalg.norm(emb_pergunta) * np.linalg.norm(doc["embedding"])
        )
        scores.append((score, doc["texto"]))

    # Retornar top-3 mais relevantes
    top3 = sorted(scores, reverse=True)[:3]
    return "\n---\n".join([t for _, t in top3])

# 3. Injetar contexto no prompt
pergunta = "Qual o preço do GPT-4o?"
contexto = buscar_contexto(pergunta, documentos)

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {
            "role": "system",
            "content": f"""Responda com base APENAS no contexto abaixo.
Se a resposta não estiver no contexto, diga que não sabe.

CONTEXTO:
{contexto}"""
        },
        {"role": "user", "content": pergunta}
    ]
)
print(response.choices[0].message.content)
Aprofundar: RAG vs Fine-Tuning — quando usar cada um →
06

Cache e Controle de Custos

Em produção, cache é a ferramenta mais eficaz para cortar custos. Requisições idênticas ou muito similares não precisam chegar ao LLM.

Python — Cache simples com Redis
import hashlib
import redis
import json

r = redis.Redis(host="localhost", port=6379, db=0)

def llm_com_cache(messages: list, model: str = "gpt-4o-mini", ttl: int = 3600) -> str:
    # Gerar chave de cache determinística
    cache_key = hashlib.sha256(
        json.dumps({"model": model, "messages": messages}, sort_keys=True).encode()
    ).hexdigest()

    # Verificar cache
    cached = r.get(cache_key)
    if cached:
        return json.loads(cached)["content"]

    # Chamar LLM
    response = client.chat.completions.create(model=model, messages=messages)
    content = response.choices[0].message.content

    # Salvar no cache
    r.setex(cache_key, ttl, json.dumps({"content": content}))
    return content

Estratégias de Redução de Custo

  • Cache de respostas frequentes (Redis, Upstash)
  • Prompt caching nativo (Anthropic, OpenAI) para system prompts longos
  • Modelo menor para triagem, maior apenas para casos complexos
  • Limitar max_tokens ao mínimo necessário
  • Comprimir histórico de conversas longas

Monitoramento em Produção

  • Logar tokens de input/output por requisição
  • Budget limit por usuário/dia (bloquear ao atingir)
  • Alertas quando custo diário excede threshold
  • LangFuse ou Helicone para observabilidade detalhada
  • Dashboard de custo por feature/endpoint

Checklist de Produção

API key em variáveis de ambiente (nunca no código)
Rate limiting por usuário implementado
Timeout configurado (evitar requisições penduradas)
Retry com backoff exponencial para erros 429/500
Budget limit diário por usuário
Logging de tokens input/output por requisição
Validação de output antes de exibir ao usuário
Versão do modelo fixada (evitar breaking changes)
Fallback para modelo alternativo em caso de indisponibilidade
Dados sensíveis nunca enviados ao LLM sem DPA

Perguntas Frequentes

Qual a diferença entre usar a API diretamente e usar um framework como LangChain?
A API direta oferece mais controle, menor overhead e menos dependências — ideal para casos de uso simples. LangChain e similares abstraem patterns comuns (RAG, agentes, memória) e aceleram o desenvolvimento de sistemas complexos. Recomendação: comece com a API direta. Se precisar de agentes complexos ou RAG elaborado, avalie frameworks. Evite abstrações prematuras.
Como calcular o custo de um LLM em produção?
Custo = (tokens_input × preco_input/1M) + (tokens_output × preco_output/1M). Use tiktoken (Python) ou js-tiktoken para estimar tokens antes de enviar. Para GPT-4o: ~$2.50/1M input + $10/1M output. Para Claude Haiku: ~$0.25/1M input + $1.25/1M output. Multiplique pelo volume de requisições esperado. Adicione 20% de margem para tokens do sistema e formatação.
Como evitar que usuários abusem da minha integração com LLM?
Implemente: (1) autenticação obrigatória antes de qualquer chamada; (2) rate limiting por usuário (ex: 10 requisições/minuto); (3) limite de tokens por requisição; (4) budget limit diário por usuário — bloqueie automaticamente ao atingir; (5) monitoring de custo em tempo real com alertas. Nunca exponha sua API key no frontend.
Vale a pena fazer fine-tuning ou usar RAG?
RAG primeiro, sempre. Fine-tuning é caro (tempo + compute + dados rotulados), difícil de manter atualizado e não resolve alucinação. RAG adiciona contexto recuperado dinamicamente — mais fácil de atualizar e depurar. Use fine-tuning apenas para: adaptar o estilo/tom do modelo, melhorar performance em formato específico (JSON estruturado, código de nicho), ou reduzir latência em modelos menores especializados.
Como escolher entre stream e resposta completa?
Use streaming para interfaces de usuário (chatbots, editores de texto) — a percepção de velocidade melhora dramaticamente mesmo sem reduzir latência total. Use resposta completa para: processamento em batch (sem usuário aguardando), quando precisa parsear JSON da resposta inteira antes de agir, ou quando a latência total é menor que overhead de stream.

Conteúdo relacionado: