Seu pipeline de RAG passa em um teste de carga padrão com louvor. A latência p95 parece saudável. As taxas de erro estão próximas de zero. No entanto, os usuários relatam respostas que esquivam da pergunta, citam documentos que não existem ou trazem parágrafos irrelevantes de um white paper enviado há seis meses. O dashboard diz que está tudo bem. A experiência diz que está quebrado.
Essa desconexão existe porque os testes de desempenho convencionais foram construídos para sistemas de requisição-resposta, não para sistemas que pensam. Quando você dispara mil requisições paralelas para um endpoint REST, você descobre se seus servidores permanecem de pé. Você não aprende nada sobre se sua camada de recuperação busca os chunks corretos, se seu template de prompt preserva o contexto ou se o modelo inventa fontes quando o vector store retorna vazio. O teste de carga padrão mede a velocidade. Aplicações de RAG exigem que você meça a compreensão.
Além do Status Code 200
Um teste de carga de API típico verifica três coisas: disponibilidade, latência e throughput. Ele pergunta se o servidor respondeu, quanto tempo levou e quantos usuários simultâneos ele suportou. Para uma aplicação de RAG, esses números são pré-requisitos, não conclusões. Uma resposta errada rápida ainda é uma resposta errada, e respostas erradas em escala custam mais do que as lentas.
O RAG adiciona duas fases distintas a cada requisição. Primeiro, o sistema transforma uma pergunta do usuário em um embedding, consulta um vector store e recupera um conjunto de chunks de contexto. Segundo, ele insere esses chunks em um prompt, envia tudo para um modelo de linguagem e transmite de volta uma completion. Testes tradicionais costumam colapsar isso em uma única métrica de "tempo de resposta". Eles tratam o mecanismo de recuperação e o gerador como uma única caixa preta.
Você precisa abrir essa caixa. Se o seu banco de dados vetorial ficar lento sob carga, a latência de recuperação aumenta. O LLM ainda pode responder rapidamente, mas estará respondendo com base em um contexto de lixo recuperado às pressas. Alternativamente, a busca vetorial permanece ágil enquanto a fila do LLM acumula, aumentando o time-to-first-token até que os usuários fiquem encarando um cursor piscando. Um único cronômetro de ponta a ponta esconde ambos os fracassos.
Teste a Recuperação, Não Apenas o Banco de Dados
A maioria das equipes executa um benchmark rápido de busca vetorial e considera a camada de recuperação testada. Esse benchmark geralmente mede a rapidez com que o banco de dados retorna os vizinhos mais próximos (nearest neighbors) para uma consulta selecionada manualmente. Raramente ele mede se esses vizinhos realmente contêm a resposta.
A qualidade da recuperação muda com a carga de maneiras sutis. Sob pressão de concorrência, índices de vizinhos mais próximos aproximados (approximate nearest neighbor) podem se comportar de forma diferente do que em isolamento. Estratégias de chunking que pareciam perfeitas em um notebook começam a vazar contexto entre as fronteiras quando dez mil documentos competem pelo mesmo espaço de embedding. Uma consulta que retorna o parágrafo ideal em um ambiente tranquilo pode trazer um slide de marketing enganoso quando o índice está sendo reconstruído ou quando a filtragem de metadados é removida sob pressão de requisições.
Para testar isso adequadamente, você precisa de um conjunto de dados de ground-truth. Selecione perguntas onde você já sabe quais documentos de origem devem aparecer. Execute essas perguntas em vários níveis de concorrência e verifique se os chunks esperados aparecem nos resultados top-k. Acompanhe a taxa de acerto (hit rate), não apenas a duração da consulta. Se os seus cinco principais chunks perderem a fonte crítica inteiramente, seu pipeline de recuperação falhou antes mesmo do LLM acordar.
Você também deve realizar testes de estresse nos limites. Envie consultas que não tenham resposta no corpus. Envie perguntas ambíguas que possam se mapear para múltiplos domínios. Envie perguntas longas que excedam o limite de tokens do seu modelo de embedding e sejam truncadas silenciosamente. Observe o que a camada de recuperação entrega. Em cada caso, o modo de falha importa mais do que os milissegundos decorridos.
Quando o Modelo Engasga Silenciosamente
Assim que os chunks chegam ao LLM, o teste de carga padrão continua a mentir
