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 a linha mini/Haiku/Flash de cada fornecedor e suba para frontier somente se qualidade for insuficiente.

CritérioEscolha
Qualidade máximaModelo frontier de cada fornecedor — ver /ranking
Custo-benefícioLinha mini/Haiku/Flash de cada fornecedor
Velocidade (chatbot real-time)Groq (Llama), Claude Haiku, Gemini Flash
Privacidade / on-premisesLlama, Mistral, Qwen via Ollama
Context longo (200K+)Claude Sonnet, Gemini Pro
Código e programaçãoClaude, ChatGPT, 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). O valor de model nos exemplos abaixo é ilustrativo — confira a lista atual de modelos de cada provedor antes de usar em produção.

Python
from openai import OpenAI

client = OpenAI(api_key="your-api-key-here")

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {
            "role": "system",
            "content": "You are a helpful assistant."
        },
        {
            "role": "user",
            "content": "Explain what RAG is in 2 paragraphs."
        }
    ],
    max_tokens=500,
    temperature=0.7,
)

print(response.choices[0].message.content)
print(f"Tokens used: {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: "You are a helpful assistant.",
    },
    {
      role: "user",
      content: "Explain what RAG is in 2 paragraphs.",
    },
  ],
  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": "Write a poem about AI"}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)  # prints token by 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": "get_model_price",
            "description": "Retrieves the price of an LLM model by name",
            "parameters": {
                "type": "object",
                "properties": {
                    "model_name": {
                        "type": "string",
                        "description": "Model name, e.g. gpt-4o-mini"
                    }
                },
                "required": ["model_name"]
            }
        }
    }
]

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "How much does this model cost?"}],
    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)
    # Execute the real function here
    result = get_model_price(args["model_name"])
    print(f"Model called: {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. Generate embedding for the user's question
def get_embedding(text: str) -> list[float]:
    response = client.embeddings.create(
        model="text-embedding-3-small",
        input=text
    )
    return response.data[0].embedding

# 2. Retrieve relevant chunks (simplified — use pgvector/Pinecone in prod)
def search_context(question: str, documents: list[dict]) -> str:
    q_emb = get_embedding(question)

    # Compute cosine similarity with each document
    scores = []
    for doc in documents:
        score = np.dot(q_emb, doc["embedding"]) / (
            np.linalg.norm(q_emb) * np.linalg.norm(doc["embedding"])
        )
        scores.append((score, doc["text"]))

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

# 3. Inject context into the prompt
question = "How much does this model cost?"
context = search_context(question, documents)

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {
            "role": "system",
            "content": f"""Answer ONLY based on the context below.
If the answer is not in the context, say you don't know.

CONTEXT:
{context}"""
        },
        {"role": "user", "content": question}
    ]
)
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_with_cache(messages: list, model: str = "gpt-4o-mini", ttl: int = 3600) -> str:
    # Generate deterministic cache key
    cache_key = hashlib.sha256(
        json.dumps({"model": model, "messages": messages}, sort_keys=True).encode()
    ).hexdigest()

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

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

    # Save to 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. Preços variam bastante entre tier flagship e tier econômico — veja os valores atuais por modelo em /benchmark/custo-api. 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: