Desde o lançamento do ChatGPT no final de 2022, o mundo tem descoberto novas formas de utilizar os modelos de linguagem de grande porte (LLMs), como na criação de e-mails e posts em redes sociais, além de ajuda com lições de casa, pesquisas e tarefas de programação. No entanto, quanto mais se utilizam essas ferramentas, mais surgem exemplos de "alucinações" — respostas incorretas ou inventadas. Certa vez, pedimos ao ChatGPT uma lista de artigos acadêmicos sobre um tema que estávamos pesquisando e, dos dez títulos retornados, nenhum existia de fato.
Esse problema se agrava quando tentamos usar uma LLM para tratar de assuntos muito específicos, como questões internas de uma empresa ou informações baseadas em documentos particulares. Embora as LLMs sejam treinadas com uma quantidade imensa de dados, o corpus de treinamento geralmente não inclui manuais de produtos, históricos de atendimento ao cliente ou outras fontes privadas.
Os modelos de linguagem atuais foram treinados para uma tarefa fundamental: prever a próxima palavra em um texto. Eles obtêm resultados impressionantes graças a dois fatores: seu tamanho colossal, que proporciona flexibilidade na interpretação dos comandos fornecidos, e a vasta quantidade de dados usados em seu treinamento. O Llama 3, da Meta, por exemplo, foi treinado com 15 trilhões de tokens!
O desafio é que, para prever a próxima palavra, o modelo se baseia em todos os textos que consumiu durante o treino. Isso significa que temas frequentes em sua base de dados têm maior chance de aparecer nas respostas. Como resultado, os modelos são excelentes em discutir assuntos comuns, mas podem se confundir quando lidam com tópicos menos explorados.
Tradicionalmente, o fine-tuning era a solução para introduzir conhecimento específico em um modelo. Nos primeiros modelos menores de transformers, isso era relativamente barato. Com um conjunto de dados de algumas dezenas de milhares de páginas e alguns dias de treinamento, o modelo assimilava novas informações. Porém, essa tarefa sempre exigiu conhecimento técnico. Com os modelos mais modernos, que possuem bilhões de parâmetros, o fine-tuning se tornou inviável para a maioria das empresas devido aos custos elevados e à quantidade massiva de dados necessários.
Uma alternativa, nas LLMs, é fornecer o conhecimento diretamente no prompt. Os modelos maiores conseguem processar documentos extensos, permitindo que façamos perguntas com base nesses textos. Contudo, essa abordagem apresenta alguns desafios. Modelos comerciais cobram por token, então um documento extenso aumenta os custos e o tempo de resposta. Além disso, grande parte do texto inserido no prompt pode não estar diretamente relacionada à pergunta, o que eleva o risco de alucinações.
Para contornar esses problemas, é mais eficiente inserir apenas as partes do documento que realmente respondem à pergunta do usuário. Isso reduz o tamanho do prompt, o custo e o risco de respostas incorretas. É exatamente isso que a arquitetura de Retrieval Augmented Generation (RAG) faz. Primeiro, o sistema identifica os trechos mais relevantes de um documento e, em seguida, constrói um prompt com base nesses trechos.
Existem várias formas de identificar trechos relevantes em um documento. Os métodos tradicionais utilizam palavras-chave e algoritmos de busca, como o BM25. Já com as LLMs, é possível usar embeddings – representações vetoriais de blocos de texto. Esses modelos agrupam textos com significados semelhantes e afastam aqueles com temas distintos. A saída é um vetor que codifica o significado do texto de entrada, permitindo medir a similaridade entre dois trechos. Entre os modelos mais utilizados para gerar esses embeddings estão o text-embeddings da OpenAI e o Embed v3 da Cohere, ambos disponíveis via API.
Após a geração dos embeddings, os dados precisam ser armazenados de maneira que facilite sua busca. Para isso, utilizam-se os bancos de dados vetoriais, que possibilitam buscas com base na similaridade semântica em vez de palavras-chave. A pesquisa ocorre por meio de índices baseados nos vetores, e as principais métricas utilizadas são a distância euclidiana e a similaridade de cossenos. O sistema retorna os trechos que mais se aproximam da consulta.
Existem bancos de dados dedicados exclusivamente ao armazenamento vetorial, como o Pinecone e o QDrant, enquanto outros bancos mais gerais, como PostgreSQL, MongoDB, ElasticSearch e Redis, também suportam esse tipo de indexação. Já a implementação do RAG pode ser feita com ferramentas específicas, mas muitas vezes ele é construído com bibliotecas de IA de propósito mais amplo, como Langchain, Semantic Kernel e Haystack.
Mas como, na prática, o RAG funciona? Vamos ilustrar com o exemplo de um chatbot de atendimento ao cliente.
A empresa tem um longo manual de atendimento, aprimorado ao longo de anos de interações com os seus clientes. O chatbot deve responder usando como base este manual. A primeira coisa que devemos fazer é separar o manual em pedaços menores e transformar cada pedaço em um vetor, usando um modelo de embeddings.
Quando o usuário faz uma pergunta ao chatbot, o sistema transforma essa pergunta também em vetor, usando o mesmo modelo. Com base nesse vetor, o sistema busca no banco de dados os trechos do manual com mais chance de conter a resposta desejada.
Um prompt é criado inserindo essas informações em um modelo de template, que poderia ser algo como: "Com base nas seguintes informações [trechos retornados], responda à pergunta: [pergunta do usuário]".
O prompt é enviado a uma LLM, que processa a resposta e a devolve ao usuário, garantindo que a resposta seja gerada com o contexto adequado.
— Rogerio Bromfman, Co-Founder Beaver e Rafael Girolineto, Founder & CTO Gaida