antonio leandro

busca e recuperação

Dense Passage Retrieval for Open-Domain Question Answering

paper · núcleo · Karpukhin, Vladimir, Oğuz, Barlas, Min, Sewon, Lewis, Patrick, Wu, Ledell, Edunov, Sergey, Chen, Danqi, Yih, Wen-tau · · ~41 min de leitura do original

a tese

retrieval denso não precisava de pré-treino especial: dois encoders bert, os pares de pergunta e passagem que já existiam e negativos tirados do próprio batch bastam para enterrar o bm25

o que fica

  1. Mil pares de pergunta e passagem já bastam para o DPR superar o BM25 no Natural Questions — a crença de que retrieval denso exigia milhões de rótulos estava errada.
  2. O que decide a qualidade do encoder não é a arquitetura, é a escolha dos negativos: com 1-of-N clássico o top-5 fica em torno de 42% a 50%, e com negativos do próprio batch mais um negativo difícil do BM25 sobe para 65,8%.
  3. Batch maior treina retriever melhor porque o batch é a fonte de negativos: 7, 31 e 127 negativos in-batch deram 51,1%, 52,1% e 55,8% de top-5.
  4. O DPR perde para o BM25 no SQuAD, onde as perguntas foram escritas por quem já tinha lido a passagem — sobreposição lexical alta continua sendo território de índice invertido.
  5. Consulta densa é muito mais rápida que Lucene (995,0 perguntas por segundo contra 23,7 por thread), mas a indexação é ordens de grandeza mais cara: 8,8 horas em 8 GPUs para embutir 21 milhões de passagens, mais 8,5 horas de FAISS, contra 30 minutos de Lucene.
  6. Dot product, distância L2 e triplet loss entregam resultados parecidos, e treinar retriever e reader juntos ficou pior que treinar cada um em separado (39,8 contra 41,5 de exact match).

o problema

Question answering de domínio aberto virou, depois de 2017, um pipeline de duas peças: um retriever escolhe algumas dezenas de passagens num corpus gigante, um reader lê essas passagens e extrai o span da resposta. A segunda peça funcionava bem. A primeira era um gargalo tão feio que o exact match no SQuAD despencava de mais de 80% para menos de 40% quando o sistema precisava achar o parágrafo em vez de receber ele pronto. Se a passagem certa não entra no top-k, nenhum reader salva a resposta.

O retriever de praxe era BM25 ou TF-IDF: vetor esparso, índice invertido, casamento de token. Rápido, barato e cego para sinônimo. A pergunta “who is the bad guy in lord of the rings?” é respondida por um texto que diz “Sala Baker is best known for portraying the villain Sauron” — e não há um termo em comum que ajude. Representação densa resolve isso por construção, mas até 2019 nenhum retriever denso tinha batido o BM25 em QA aberto. O ORQA conseguiu, ao custo de um pré-treino próprio (inverse cloze task) caro e de um encoder de passagens que nunca era ajustado com pares de pergunta e resposta. A crença dominante era que aprender bons embeddings de recuperação exigia uma montanha de pares rotulados.

a ideia

O DPR desmonta a crença testando o caminho mais preguiçoso: pegar BERT pronto, colocar dois deles lado a lado — um para a pergunta, outro para a passagem —, definir similaridade como produto interno dos vetores e treinar só isso, com os pares de pergunta e passagem que os datasets de QA já ofereciam. Sem pré-treino novo, sem cross-attention, sem treinar retriever e reader juntos.

O trabalho de verdade não está na arquitetura, está em de onde vêm os exemplos negativos. Positivo é fácil: o dataset dá. Negativo é qualquer uma das 21 milhões de outras passagens, e escolher mal significa treinar o modelo contra um adversário fraco demais para ensinar alguma coisa. A resposta do paper é usar o próprio batch como fonte de negativos, e acrescentar um negativo difícil vindo do BM25.

como funciona

O corpus é a Wikipedia em inglês cortada em blocos disjuntos de 100 palavras — 21.015.324 passagens —, cada uma prefixada pelo título do artigo e um [SEP]. Os dois encoders são BERT base uncased, saída no token [CLS], portanto d = 768. A perda é log-verossimilhança negativa da passagem positiva contra as negativas.

O truque do in-batch negative é aritmética de matriz. Com B perguntas no batch, monta-se Q e P de tamanho B × d e calcula-se S = QPᵀ, uma matriz B × B de scores. A diagonal são os pares corretos; todo o resto é negativo. Um único produto de matrizes gera B² pares de treino a partir de B pares rotulados, sem custo extra de forward pass. O modelo final usa batch de 128 e mais uma passagem difícil do BM25 — que casa muitos termos da pergunta mas não contém a resposta — compartilhada como negativa por todas as perguntas do batch. Treino com Adam, learning rate 10⁻⁵, dropout 0,1, até 40 épocas nos datasets grandes.

Em inferência, as 21 milhões de passagens são embutidas offline e indexadas com FAISS (índice HNSW). A pergunta vira um vetor e o top-k sai por busca de produto interno máximo. O reader é outro BERT base, separado, que dá a cada passagem um score de seleção e extrai um span; ele processa até 100 passagens de uma vez numa GPU de 32 GB.

o que isso custou

O SQuAD é a derrota declarada: 63,2% de top-20 contra 68,8% do BM25, e 51,6% quando o retriever é treinado em vários datasets. Os autores explicam sem rodeio — os anotadores escreveram as perguntas depois de ler a passagem, o que garante sobreposição lexical, e o dataset vem de pouco mais de 500 artigos. Ou seja: onde a pergunta reusa as palavras do texto, o índice invertido continua ganhando.

A análise qualitativa mostra o outro buraco. O DPR não representa bem frases salientes e raras: pedir quem interpreta “Thoros of Myr” traz um ator norueguês qualquer, enquanto o BM25 acha o texto certo. Daí a linha BM25+DPR do paper, que soma os dois scores e ganha em vários casos (85,2% contra 79,8% de top-20 no TREC) — o denso não substitui o esparso em toda parte.

O custo de infraestrutura inverte o do Lucene. A consulta fica barata (995,0 perguntas por segundo contra 23,7 por thread), mas construir o índice leva 8,8 horas em 8 GPUs para os embeddings mais 8,5 horas para o FAISS, contra 30 minutos de Lucene. E o índice é refém do encoder: no experimento de treino conjunto os autores precisam congelar o encoder de passagens só para não ter que reindexar. Esse treino conjunto, aliás, não pagou — 39,8 de exact match contra 41,5 do pipeline separado. Generalizar entre datasets custa de 3 a 5 pontos de top-20, e o cenário todo pressupõe resposta extrativa, um span literal em algum lugar do corpus.

onde isso aparece hoje

A receita do DPR — dual encoder, in-batch negatives, hard negatives de um retriever léxico — virou o modo padrão de treinar modelos de embedding para busca. E o retriever pronto virou peça de encaixe: o próprio paper já registra que o DPR foi acoplado a modelos generativos como BART e T5, que é exatamente o que faz o Retrieval-Augmented Generation, publicado meses depois com um dos mesmos autores. O que hoje se chama de RAG começa neste índice.

O ColBERT saiu na mesma época com uma aposta diferente, guardar um vetor por token e adiar a interação em vez de comprimir a passagem num único vetor; o contraste entre as duas está em ColBERT. A biblioteca usada aqui para servir os 21 milhões de vetores ganhou vida própria e está em The Faiss library. E o híbrido que o DPR testa como uma linha extra da tabela é hoje default: somar score denso e score BM25 é a base de pipelines como a recuperação contextual.

lido na íntegra por pipeline de llm, revisado por antonio leandro antes de publicar ·