Quando se trata de processamento de linguagem natural (NLP) e recuperação de informações, a capacidade de recuperar informações relevantes de forma eficiente e precisa é fundamental. À medida que o campo continua a evoluir, novas técnicas e metodologias estão sendo desenvolvidas para melhorar o desempenho dos sistemas de recuperação, particularmente no contexto da Geração Aumentada por Recuperação (RAG). Uma dessas técnicas, conhecida como recuperação em duas etapas com rerankers, emergiu como uma solução poderosa para abordar as limitações inerentes dos métodos de recuperação tradicionais.
Neste artigo, discutimos as nuances da recuperação em duas etapas e rerankers, explorando seus princípios subjacentes, estratégias de implementação e os benefícios que oferecem para melhorar a precisão e eficiência dos sistemas RAG. Também forneceremos exemplos práticos e trechos de código para ilustrar os conceitos e facilitar uma compreensão mais profunda dessa técnica de ponta.
Entendendo a Geração Aumentada por Recuperação (RAG)
Antes de mergulhar nos detalhes da recuperação em duas etapas e rerankers, vamos revisitar brevemente o conceito de Geração Aumentada por Recuperação (RAG). RAG é uma técnica que estende o conhecimento e as capacidades dos grandes modelos de linguagem (LLMs) fornecendo-lhes acesso a fontes de informações externas, como bancos de dados ou coleções de documentos. Consulte mais sobre o artigo “Uma Imersão Profunda na Geração Aumentada por Recuperação em LLM“.
O processo típico de RAG envolve as seguintes etapas:
Consulta: Um usuário formula uma pergunta ou fornece uma instrução ao sistema.
Recuperação: O sistema consulta um banco de dados de vetores ou uma coleção de documentos para encontrar informações relevantes para a consulta do usuário.
Aumento: As informações recuperadas são combinadas com a consulta original do usuário ou instrução.
Geração: O modelo de linguagem processa a entrada aumentada e gera uma resposta, aproveitando as informações externas para melhorar a precisão e a abrangência de sua saída.
Embora a RAG tenha se provado uma técnica poderosa, ela não está isenta de desafios. Um dos principais problemas está na etapa de recuperação, onde os métodos de recuperação tradicionais podem falhar em identificar os documentos mais relevantes, levando a respostas subótimas ou imprecisas do modelo de linguagem.
A Necessidade de Recuperação em Duas Etapas e Rerankers
Os métodos de recuperação tradicionais, como aqueles baseados em correspondência de palavras-chave ou modelos de espaço de vetores, frequentemente lutam para capturar as relações semânticas nuances entre consultas e documentos. Essa limitação pode resultar na recuperação de documentos que são apenas superficialmente relevantes ou perdem informações cruciais que poderiam melhorar significativamente a qualidade da resposta gerada.
Para abordar esse desafio, pesquisadores e profissionais têm se voltado para a recuperação em duas etapas com rerankers. Essa abordagem envolve um processo de duas etapas:
Recuperação Inicial: Na primeira etapa, um conjunto relativamente grande de documentos potencialmente relevantes é recuperado usando um método de recuperação rápido e eficiente, como um modelo de espaço de vetores ou uma busca baseada em palavras-chave.
Reranking: Na segunda etapa, um modelo de reranking mais sofisticado é empregado para reordenar os documentos inicialmente recuperados com base em sua relevância para a consulta, efetivamente trazendo os documentos mais relevantes para o topo da lista.
O modelo de reranking, frequentemente uma rede neural ou uma arquitetura baseada em transformadores, é especificamente treinado para avaliar a relevância de um documento para uma consulta dada. Ao aproveitar capacidades avançadas de compreensão de linguagem natural, o reranker pode capturar as nuances semânticas e as relações contextuais entre a consulta e os documentos, resultando em uma classificação mais precisa e relevante.
Benefícios da Recuperação em Duas Etapas e Rerankers
A adoção da recuperação em duas etapas com rerankers oferece vários benefícios significativos no contexto dos sistemas RAG:
Melhoria da Precisão: Ao rerankar os documentos inicialmente recuperados e promover os mais relevantes para o topo, o sistema pode fornecer informações mais precisas e precisas para o modelo de linguagem, levando a respostas geradas de maior qualidade.
Mitigação de Problemas Fora do Domínio: Os modelos de incorporação usados para recuperação tradicional são frequentemente treinados em corpora de texto de propósito geral, que podem não capturar adequadamente a linguagem e a semântica específicas do domínio. Os modelos de reranking, por outro lado, podem ser treinados em dados específicos do domínio, mitigando o problema “fora do domínio” e melhorando a relevância dos documentos recuperados dentro de domínios especializados.
Escalabilidade: A abordagem de duas etapas permite uma escalabilidade eficiente, aproveitando métodos de recuperação rápidos e leves na etapa inicial, enquanto reserva o processo de reranking mais computacionalmente intensivo para um subconjunto menor de documentos.
Flexibilidade: Os modelos de reranking podem ser trocados ou atualizados independentemente do método de recuperação inicial, fornecendo flexibilidade e adaptabilidade às necessidades evolutivas do sistema.
ColBERT: Interação Tardia Eficiente e Eficaz
Um dos modelos de destaque no campo de reranking é o ColBERT (Interação Tardia Contextualizada sobre BERT). O ColBERT é um modelo de reranking de documentos que aproveita as capacidades de compreensão de linguagem profunda do BERT, introduzindo um mecanismo de interação novo conhecido como “interação tardia”.
ColBERT: Busca de Passagem Eficiente e Eficaz via Interação Tardia Contextualizada sobre BERT
O mecanismo de interação tardia no ColBERT permite uma recuperação eficiente e precisa, processando consultas e documentos separadamente até as etapas finais do processo de recuperação. Especificamente, o ColBERT codifica a consulta e o documento de forma independente usando o BERT, e então emprega uma etapa de interação leve, mas poderosa, que modela a similaridade fina entre eles. Ao retardar, mas reter essa interação fina, o ColBERT pode aproveitar a expressividade dos modelos de linguagem profundos, ao mesmo tempo em que ganha a capacidade de pré-computar representações de documentos offline, acelerando significativamente o processamento de consultas.
A arquitetura de interação tardia do ColBERT oferece vários benefícios, incluindo eficiência computacional melhorada, escalabilidade com o tamanho da coleção de documentos e aplicabilidade prática para cenários do mundo real. Além disso, o ColBERT foi aprimorado com técnicas como supervisão denoised e compressão residual (no ColBERTv2), que refinam o processo de treinamento e reduzem a pegada espacial do modelo, mantendo a eficácia de recuperação.
Este trecho de código demonstra como configurar e usar o modelo jina-colbert-v1-en para indexar uma coleção de documentos, aproveitando sua capacidade de lidar com contextos longos de forma eficiente.
Implementando a Recuperação em Duas Etapas com Rerankers
Agora que temos uma compreensão dos princípios por trás da recuperação em duas etapas e rerankers, vamos explorar sua implementação prática dentro do contexto de um sistema RAG. Vamos aproveitar bibliotecas e frameworks populares para demonstrar a integração dessas técnicas.
Configurando o Ambiente
Antes de mergulharmos no código, vamos configurar nosso ambiente de desenvolvimento. Estaremos usando Python e várias bibliotecas de NLP populares, incluindo Hugging Face Transformers, Sentence Transformers e LanceDB.
Para fins de demonstração, vamos usar o conjunto de dados “ai-arxiv-chunked” do Hugging Face Datasets, que contém mais de 400 artigos do ArXiv sobre aprendizado de máquina, processamento de linguagem natural e grandes modelos de linguagem.
from datasets import load_dataset
<p>dataset = load_dataset("jamescalam/ai-arxiv-chunked", split="train")</p>
&lt;pre&gt;
Em seguida, vamos pré-processar os dados e dividi-los em pedaços menores para facilitar a recuperação e processamento eficientes.
from transformers import AutoTokenizer
<p>tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")</p>
<p>def chunk_text(text, chunk_size=512, overlap=64):
tokens = tokenizer.encode(text, return_tensors="pt", truncation=True)
chunks = tokens.split(chunk_size - overlap)
texts = [tokenizer.decode(chunk) for chunk in chunks]
return texts</p>
<p>chunked_data = []
for doc in dataset:
text = doc["chunk"]
chunked_texts = chunk_text(text)
chunked_data.extend(chunked_texts)</p>
Para a etapa de recuperação inicial, vamos usar um modelo de Sentence Transformer para codificar nossos documentos e consultas em representações de vetores densos e, em seguida, realizar uma busca de vizinhos mais próximos aproximada usando um banco de dados de vetores como o LanceDB.
from sentence_transformers import SentenceTransformer
from lancedb import lancedb
<p># Carregue o modelo de Sentence Transformer
model = SentenceTransformer('all-MiniLM-L6-v2')</p>
<p># Crie um armazenamento de vetores do LanceDB
db = lancedb.lancedb('/path/to/store')
db.create_collection('docs', vector_dimension=model.get_sentence_embedding_dimension())</p>
<p># Indexe os documentos
for text in chunked_data:
vector = model.encode(text).tolist()
db.insert_document('docs', vector, text)</p>
<p>from sentence_transformers import SentenceTransformer
from lancedb import lancedb</p>
<p># Carregue o modelo de Sentence Transformer
model = SentenceTransformer('all-MiniLM-L6-v2')</p>
<p># Crie um armazenamento de vetores do LanceDB
db = lancedb.lancedb('/path/to/store')
db.create_collection('docs', vector_dimension=model.get_sentence_embedding_dimension())</p>
<p># Indexe os documentos
for text in chunked_data:
vector = model.encode(text).tolist()
db.insert_document('docs', vector, text)
Com os documentos indexados, podemos realizar a recuperação inicial encontrando os vizinhos mais próximos de um vetor de consulta dado.
from transformers import AutoTokenizer
<p>tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")</p>
<p>def chunk_text(text, chunk_size=512, overlap=64):
tokens = tokenizer.encode(text, return_tensors="pt", truncation=True)
chunks = tokens.split(chunk_size - overlap)
texts = [tokenizer.decode(chunk) for chunk in chunks]
return texts</p>
<p>chunked_data = []
for doc in dataset:
text = doc["chunk"]
chunked_texts = chunk_text(text)
chunked_data.extend(chunked_texts)
Reranking
Após a recuperação inicial, vamos empregar um modelo de reranking para reordenar os documentos recuperados com base em sua relevância para a consulta. Neste exemplo, vamos usar o reranker ColBERT, um modelo de transformadores rápido e preciso, especificamente projetado para classificação de documentos.
from lancedb.rerankers import ColbertReranker
reranker = ColbertReranker()
<p># Rerank os documentos inicialmente recuperados
reranked_docs = reranker.rerank(query, initial_docs)
A lista reranked_docs agora contém os documentos reordenados com base em sua relevância para a consulta, conforme determinado pelo reranker ColBERT.
Aumento e Geração
Com os documentos reordenados e relevantes em mãos, podemos prosseguir para as etapas de aumento e geração do pipeline RAG. Vamos usar um modelo de linguagem da biblioteca Hugging Face Transformers para gerar a resposta final.
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
<p>tokenizer = AutoTokenizer.from_pretrained("t5-base")
model = AutoModelForSeq2SeqLM.from_pretrained("t5-base")</p>
<p># Aumente a consulta com os documentos reordenados
augmented_query = query + " " + " ".join(reranked_docs[:3])</p>
<p># Gere a resposta do modelo de linguagem
input_ids = tokenizer.encode(augmented_query, return_tensors="pt")
output_ids = model.generate(input_ids, max_length=500)
response = tokenizer.decode(output_ids[0], skip_special_tokens=True)</p>
print(response)
No trecho de código acima, aumentamos a consulta original com os três documentos reordenados, criando uma augmented_query. Em seguida, passamos essa consulta aumentada para um modelo de linguagem T5, que gera uma resposta com base no contexto fornecido.
A variável response conterá a saída final, aproveitando as informações externas dos documentos recuperados e reordenados para fornecer uma resposta mais precisa e abrangente para a consulta original.
Técnicas Avançadas e Considerações
Embora a implementação que cobrimos forneça uma base sólida para integrar a recuperação em duas etapas e rerankers em um sistema RAG, existem várias técnicas avançadas e considerações que podem melhorar ainda mais o desempenho e a robustez da abordagem.
Expansão de Consulta: Para melhorar a etapa de recuperação inicial, você pode empregar técnicas de expansão de consulta, que envolvem aumentar a consulta original com termos ou frases relacionados. Isso pode ajudar a recuperar um conjunto mais diversificado de documentos potencialmente relevantes.
Reranking Ensemble: Em vez de confiar em um único modelo de reranking, você pode combinar vários rerankers em um ensemble, aproveitando as forças de diferentes modelos para melhorar o desempenho geral.
Ajuste Fino de Rerankers: Embora os modelos de reranking pré-treinados possam ser eficazes, ajustar o treinamento deles em dados específicos do domínio pode melhorar ainda mais sua capacidade de capturar semântica e sinais de relevância específicos do domínio.
Recuperação e Reranking Iterativos: Em alguns casos, uma única iteração de recuperação e reranking pode não ser suficiente. Você pode explorar abordagens iterativas, onde a saída do modelo de linguagem é usada para refinar a consulta e o processo de recuperação, levando a um sistema mais interativo e dinâmico.
Equilíbrio entre Relevância e Diversidade: Embora os rerankers visem promover os documentos mais relevantes, é essencial encontrar um equilíbrio entre relevância e diversidade. Incorporar técnicas que promovam a diversidade pode ajudar a evitar que o sistema se torne muito estreito ou tendencioso em suas fontes de informações.
Métricas de Avaliação: Para avaliar a eficácia da abordagem de recuperação em duas etapas e reranking, você precisará definir métricas de avaliação apropriadas. Isso pode incluir métricas tradicionais de recuperação de informações, como precisão, recall e rank médio recíproco (MRR), bem como métricas específicas da tarefa adaptadas ao seu caso de uso.
Conclusão
A Geração Aumentada por Recuperação (RAG) emergiu como uma técnica poderosa para melhorar as capacidades dos grandes modelos de linguagem, aproveitando fontes de informações externas. No entanto, os métodos de recuperação tradicionais frequentemente lutam para identificar os documentos mais relevantes, levando a um desempenho subótimo.
A recuperação em duas etapas com rerankers oferece uma solução convincente para esse desafio. Ao combinar uma etapa de recuperação inicial rápida com um modelo de reranking mais sofisticado, essa abordagem pode melhorar significativamente a precisão e a relevância dos documentos recuperados, levando a respostas geradas de maior qualidade pelo modelo de linguagem.
Eu passei os últimos cinco anos me imergindo no fascinante mundo de Aprendizado de Máquina e Aprendizado Profundo. Minha paixão e expertise me levaram a contribuir para mais de 50 projetos de engenharia de software diversificados, com um foco particular em IA/ML. Minha curiosidade contínua também me levou em direção ao Processamento de Linguagem Natural, um campo que estou ansioso para explorar mais.