DEV Community

Alberto Luiz Souza
Alberto Luiz Souza

Posted on

Semantic Cache: Como Otimizar Aplicações RAG com Cache Semântico

Disclaimer

Este texto foi inicialmente concebido pela IA Generativa em função da transcrição de um vídeo do canal de Daniel Romero(a pessoa que lidera nossa especialização em Engenharia de IA). Se preferir acompanhar por vídeo, é só dar o play.

Introdução

Ao trabalhar com aplicações baseadas em RAG (Retrieval-Augmented Generation), um dos desafios é lidar com o custo e a latência de processar perguntas repetidas. Cada vez que um usuário faz uma pergunta, todo o pipeline precisa ser executado novamente, mesmo que a resposta já tenha sido gerada anteriormente. Neste post, vamos explorar como o Semantic Cache pode resolver esse problema de forma elegante e eficiente.

O que é Cache?

Um cache é uma memória de alta velocidade que armazena de forma eficiente os dados acessados com frequência. A ideia é simples: em vez de recalcular ou buscar uma informação toda vez que ela é solicitada, armazenamos o resultado para uso futuro.

O Pipeline RAG Tradicional

Em um RAG tradicional, quando um usuário faz uma pergunta, o sistema executa várias etapas: faz o embedding da pergunta, pesquisa em um vector database (podendo realizar busca por palavra-chave, semântica ou híbrida), recupera os documentos relevantes, envia o contexto junto com o prompt e a pergunta original para o LLM, e finalmente retorna a resposta gerada ao usuário.

Se o usuário fizer a mesma pergunta repetidamente, todo esse processo ocorre a cada requisição. Como você pode imaginar, isso é custoso tanto em termos de tempo quanto de dinheiro.

O Problema do Cache Tradicional

Para evitar gerar a mesma resposta várias vezes para uma pergunta frequente, podemos armazenar as perguntas e suas respectivas respostas em um cache. Por exemplo, se o usuário perguntar "Qual é a capital do Brasil?" pela primeira vez, geramos a resposta seguindo o pipeline de RAG e salvamos no cache. Na próxima vez que a mesma pergunta for feita, recuperamos a resposta do cache.

Esse tipo de cache é bastante comum e funciona com um mecanismo de chave-valor: a pergunta é a chave e a resposta é o valor. Porém, há um problema importante.

Ao trabalhar com um cache do tipo key-value, pequenas variações na formulação de uma pergunta podem resultar em um valor de hash diferente. Por exemplo, "Qual é a capital do Brasil?" e "Você pode me dizer a capital do Brasil?" são essencialmente a mesma pergunta, mas sua formulação literal é diferente. Se usarmos uma abordagem simples para procurar a resposta no cache, provavelmente não vamos conseguir encontrar, porque a versão hash da pergunta é diferente.

A Solução: Semantic Cache

Para melhorar a precisão dos resultados da busca, podemos usar um cache semântico em vez de confiar em um mecanismo de combinação exata (Exact Match). Isso envolve armazenar as perguntas, respostas e seus embeddings em um mecanismo de chave-valor.

Quando um usuário faz uma pergunta, podemos realizar uma busca semântica em todas as perguntas no cache para encontrar a mais semelhante. Se o score de similaridade entre a pergunta do usuário e a pergunta mais similar no cache estiver acima de um determinado limite, podemos assumir que a pergunta é essencialmente a mesma e fornecer a resposta correspondente.

O cache tradicional opera com base em combinação exata: quando você procura uma chave, ele verifica se ela existe no cache. Já o cache semântico funciona de maneira diferente: ele pesquisa semanticamente, procurando o significado da chave em vez de uma combinação exata. Por exemplo, "Qual é a capital do Brasil?" versus "Me diga o nome da capital do Brasil" terão o mesmo resultado em um cache semântico, pois a formulação é diferente, mas o significado é o mesmo. Em contraste, um cache tradicional falharia para a segunda pergunta.

Vantagens e Considerações

Se você estiver utilizando um LLM em um sistema de perguntas e respostas e tiver que fazer muitas chamadas para a API, essa operação vai custar caro. É aqui que uma solução de cache semântico se destaca, porque será extremamente eficiente e rápida, economizando tempo e dinheiro do projeto.

Usar cache também é uma ótima maneira de otimizar o desempenho de chatbots, armazenando dados acessados com frequência. Uma abordagem interessante é criar patches ad-hoc para diálogos de chatbots, identificando perguntas feitas com frequência e preparando respostas pré-escritas. O chatbot pode recuperar rapidamente as respostas do cache e responder instantaneamente, sem acessar um LLM. Isso garante consistência nas respostas para perguntas como "Qual é o endereço da loja?".

Por outro lado, usar cache pode não ser uma boa ideia se você quiser diferentes variações para a mesma consulta. No entanto, em um sistema de perguntas e respostas, a variação geralmente não importa.

Implementação Prática

Em uma implementação prática, é possível utilizar o mesmo vector database tanto para armazenamento dos documentos quanto para o cache semântico. Por exemplo, utilizando Qdrant: o armazenamento vetorial com dados em cloud para busca semântica, e o cache com persistência em memória.

Quando o usuário faz uma pergunta, é necessário fazer o embedding da pergunta. Essa parte deve ser feita independentemente de utilizar cache ou não, porque para fazer uma busca, tanto no vector database quanto no cache, são necessários embeddings. Lembrando que esse custo está bem reduzido se comparado com os LLMs.

A função de cache verifica se a pergunta já foi respondida, buscando através de todos os embeddings e comparando com o embedding da pergunta. Se estiver no cache, retorna a resposta armazenada. É importante definir um limite adequado baseado na métrica utilizada. Por exemplo, com distância euclidiana, quanto menor o valor, melhor (mais próximo de zero significa maior similaridade). Se fosse similaridade do cosseno, números maiores significariam maior semelhança.

Se a pergunta não existir no cache, o sistema passa pelo processo normal de RAG: busca semântica no vector database, encontra os chunks mais similares, envia como contexto junto com a consulta do usuário e o prompt para o LLM. Ao final, gera uma nova resposta e a salva no cache para uso futuro.

Conclusão

O Semantic Cache é uma técnica poderosa para otimizar aplicações RAG, permitindo economia significativa de tempo e custos ao evitar processamentos redundantes. A chave está em entender que perguntas semanticamente equivalentes devem retornar a mesma resposta, mesmo quando formuladas de maneiras diferentes.

Dev+ Eficiente

Este conteúdo é parte do ecossistema Dev+ Eficiente, mantido por Alberto junto com Maurício Aniche e Rafael Ponte, que inclui um canal e dois treinamentos. O primeiro é a Jornada Dev+ Eficiente, cujo foco é fazer com que você seja capaz de entregar software que de fato gera valor com o máximo de qualidade e eficiência.

O segundo é a especialização em Engenharia de IA, uma parceria com Daniel Romero, cuja ideia é habilitar você para entregar software de excelência, integrando sistemas com LLMs.

Conheça mais em https://deveficiente.com/interesse-especializacao-engenharia-ia

Top comments (0)