Diagnóstico e Correção de Problemas com Perplexity: Guia Prático de 72 Horas

Fundamentos da Métrica Perplexity

A perplexidade (PPX) quantifica a capacidade preditiva de modelos de linguagem, sendo a exponenciação da entropia cruzada média. Valores menores indicam maior confiança do modelo na distribuição textual observada.

Formalmente, para uma sequência de tokens w₁, w₂, ..., wₙ com probabilidade estimada P:

PPX = exp( - (1/N) × Σ log P(wᵢ | w₁...wᵢ₋₁) )

Uma PPX de 20 equivale a um modelo que se comporta como se escolhesse entre 20 palavras equiprováveis a cada passo.

Implementação com PyTorch

import torch
import torch.nn.functional as F

def avaliar_perplexidade(rede, carregador, dispositivo):
    rede.eval()
    entropia_acumulada = 0.0
    total_tokens = 0
    
    with torch.no_grad():
        for lote in carregador:
            entradas = lote['ids'].to(dispositivo)
            alvos = lote['rotulos'].to(dispositivo)
            
            saidas = rede(entradas).logits
            logits_ajustados = saidas[:, :-1, :].contiguous()
            rotulos_ajustados = alvos[:, 1:].contiguous()
            
            perda = F.cross_entropy(
                logits_ajustados.reshape(-1, logits_ajustados.size(-1)),
                rotulos_ajustados.reshape(-1),
                ignore_index=-100
            )
            
            entropia_acumulada += perda.item() * rotulos_ajustados.numel()
            total_tokens += rotulos_ajustados.numel()
    
    perda_media = entropia_acumulada / total_tokens
    return torch.exp(torch.tensor(perda_media)).item()

Tabela de Referência em WikiText-103

Arquitetura Perplexidade (Validação) Observações
LSTM (2 camadas) 73.4 Linha de base clássica
Transformer-XL 18.3 Posições relativas e memória segmentada
GPT-2 Small 15.1 12 camadas, 768 dimensões ocultas

Taxonomia de Falhas e Diagnóstico

Categoria 1: Erros de Tokenização e AST

Fragmentação de identificadores em tokens inválidos corrompe a aálise sintática:

# Código original
def calcular_total(itens):
    return sum(itens)

# Após tokenização incorreta
def calcu
lar_total(itens):
    return sum(itens)
Sintoma Origem Verificação
Unexpected EOF Fluxo de tokens truncado Inspecionar presença de LPAR/COLON no final
Identificador inválido Cisão em bytes UTF-8 Comparar token.text com índices de bytes originais

Categoria 2: Colapso de Contexto

Template curl para reproduzir truncamento silencioso:

curl -X POST http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "llama3",
    "messages": [{"role":"user","content":"'$(python3 -c "print('A '*4097)")'"}],
    "max_tokens": 10
  }'

Categoria 3: Inconsistências em Chamada de Ferramentas

Exemplo de violação de schema OpenAPI v3:

{
  "nome": "consultar_clima",
  "argumentos": {
    "cidade": "São Paulo",
    "unidade": "celsius",
    "dias": 7.5
  }
}

Problemas: unidade deve estar em ["c", "f"] (enum); dias deve ser inteiro.

Categoria 4: Alucinações e Deriva Factual

Métrica combinada para detecção:

escore_drift = confianca / (entropia + 1e-8)
LIMIAR_OTIMO = 0.62  # F1 maximizado via validação cruzada em 12 domínios
Limiar Recall Alucinações Falsos Positivos
0.50 89.2% 14.7%
0.62 76.5% 5.3%
0.75 41.1% 1.2%

Templates curl para Diagnóstico

Templaet 1: Rastreamento Completo

GET /api/v1/completions HTTP/1.1
Host: api.exemplo.com
X-Request-ID: req-7f8a2c1e-9b4d-4e6f-8a1c-3d5e7f9a1b2c
X-B3-TraceId: 4bf92f3577b34da6a3ce929d0e0e4736
X-B3-SpanId: 00f067aa0ba902b7
X-B3-Sampled: 1

Template 2: Consistência de Sessão

Verificação de context_hash no servidor:

hash_esperado := sha256.Sum256([]byte(
    fmt.Sprintf("%s|%s|%d", 
        sessao.Token, 
        strings.Join(sessao.Mensagens, "\n"), 
        sessao.ContadorTurnos,
    ),
))
if !bytes.Equal(hash_esperado[:], requisicao.ContextHash) {
    return errors.New("divergencia de contexto: possivel replay ou drift")
}

Template 3: Injeção Reversa em function_response

resposta = {
    "role": "function",
    "name": "obter_clima",
    "content": '{"cidade": "São Paulo", "temperatura": 25} // injetado: {"malicioso": true}'
}
Modo tool_choice Ferramenta Obrigatória Suscetibilidade a Injeção
"auto" Não Alta
{"type": "function", ...} Sim Baixa

Template 4: Snapshot DOM Multimodal

function capturarSnapshotConsistente() {
  return Promise.all([
    MathJax.typesetPromise(),
    mermaid.run({ querySelector: '.mermaid' }),
    Prism.highlightAll()
  ]).then(() => document.documentElement.outerHTML);
}

Template 5: Teste de Carga com curl

for i in {1..100}; do
  curl -s -o /dev/null -w "%{http_code} %{time_total}\n" \
    -H "X-Request-ID: req-$RANDOM" \
    http://localhost:8000/v1/completions
done

Template 6: Validação de Contrato OpenAPI

curl -X POST http://localhost:8000/v1/tools/validate \
  -H "Content-Type: application/json" \
  -d '{
    "schema_url": "https://api.exemplo.com/openapi.json",
    "invocation": {"name": "consultar_clima", "arguments": {"dias": 7.5}}
  }'

Ferramenta CLI perp-blame

Arquitetura de Dupla Modalidade

O motor correlaciona diferenças em nós AST com mapas de atenção do LLM via projeção linear:

projecao = torch.nn.Linear(768, len(nos_ast))
logits_atencao = projecao(estado_oculto.mean(dim=1))

Métricas de Confiança

Indicador Fórmula Limiar
Jaccard AST-Atenção |ΔAST ∩ Atendido| / |ΔAST ∪ Atendido| ≥ 0.62
Cobertura Top-3 Nós de diff cobertos / Total de nós de diff ≥ 0.85

Geração de Patch e Reescrita de Prompt

A partir da resposta estruturada:

{
  "erro": "undefined method `strip' for nil:NilClass",
  "rastreamento": ["app/models/usuario.rb:42"],
  "sugestao": "Adicionar verificação de nil antes de strip"
}

Geração de git diff com inserção de guarda condicional e instrução de resecrita contextualizada.

Sistema de Plugins por Rule Pack

// plugins/sql-inject/regras.go
func init() {
    RegistrarPacoteRegras("sql-inject", &PacoteSQLInject{
        Regras: []Regra{
            {ID: "sql-001", Padrao: `(?i)select.*from.*union.*select`, Severidade: "ALTA"},
        },
    })
}

Otimizações de Performance

Processamento paralelo em 128 slots para milhões de tokens:

func (m *Motor) processarSlot(idSlot int, tokens []Token) {
    m.cache.Lock()
    defer m.cache.Unlock()
    
    atribuicao := m.poolAtribuicoes.Get().(*Atribuicao)
    defer m.poolAtribuicoes.Put(atribuicao)
    
    atribuicao.Calcular(tokens)
}
Métrica Antes Depois
Latência P99 1.82s 0.89s
Pico de Memória 4.2 GB 2.6 GB

Tags: perplexity Pytorch language-models ast-analysis cURL

Publicado em 8-9 17:04