Adicione memória ao seu aplicativo JavaScript RAG usando MongoDB e LangChain
Jesse Hall9 min read • Published Sep 18, 2024 • Updated Sep 18, 2024
Avalie esse Tutorial
Aplicativos deAI com recursos de AI generativa, como geração de texto e imagem, exigem mais do que apenas os modelos de linguagem grande (LLMs) básicos. Isso ocorre porque os LLMs estão limitados ao seu conhecimento paramétrico, que pode estar desatualizado e não ser específico do contexto de uma query do usuário. O padrão de design de geração aumentada de recuperação (RAG) resolve o problema experimentado com sistemas LLM ingênuos, adicionando informações relevantes e contexto recuperados de uma fonte de informações, como um banco de dados, à query do usuário antes de obter uma resposta do LLM base. O padrão de design de arquitetura RAG para aplicativos de AI foi amplamente aceito devido à sua facilidade de implementação e eficácia na base de sistemas LLM com dados atualizados e relevantes.
Para desenvolvedores que criam novos projetos de AI que usam LLMs e esse tipo de AI avançada, é importante pensar em mais do que apenas dar respostas inteligentes. Antes de compartilhar seus projetos baseados em RAG com o mundo, eles precisam adicionar recursos como memória. Adicionar memória aos seus sistemas de AI pode ajudar a reduzir custos, torná-los mais rápidos e lidar com conversas de maneira mais inteligente.
Os chatbots que usam LLMs são agora uma funcionalidade regular em muitas plataformas online, desde o serviço de apoio ao cliente até aos assistentes pessoais. No entanto, uma das chaves para tornar esses chatbots mais eficazes está em sua capacidade de recuperar e utilizar conversas anteriores. Ao manter um registro detalhado das interações, os sistemas de AI podem melhorar significativamente sua compreensão das necessidades, preferências e contexto do usuário. Essa visão histórica permite que o chatbot ofereça respostas que não são apenas relevantes, mas também personalizadas para cada usuário individual, melhorando a experiência geral do usuário.
Considere, por exemplo, um cliente que entra em contato com o chatbot de uma livraria on-line durante vários dias, perguntando sobre diferentes romances e autores de ficção científica. No primeiro dia, o cliente pede recomendações de livros com base em temas clássicos de ficção científica. No dia seguinte, eles voltam para perguntar sobre livros de autores específicos desse gênero. Se o chatbot mantiver um registro dessas interações, ele poderá conectar os pontos entre os vários interesses do cliente. Na terceira interação, o chatbot poderia sugerir novos lançamentos que se alinhem à preferência demonstrada do cliente pela ficção científica clássica, até mesmo recomendando ofertas especiais ou gêneros relacionados que o cliente talvez ainda não tenha explorado.
Essa capacidade vai além da simples dinâmica de perguntas e respostas; ele cria uma memória de conversa para o chatbot, tornando cada interação mais pessoal e envolvente. Os usuários se sentem compreendidos e valorizados, o que leva ao aumento da satisfação e da fidelidade. Em essência, ao acompanhar as conversas, os chatbots movidos por LLMs se transformam de atendedores de chamadas impassíveis em parceiros de conversas dinâmicos, capazes de fornecer relacionamentos altamente personalizados e significativos.
O MongoDB Atlas Vector Search e a nova integração LangChain-MongoDB facilitam a adição desses recursos avançados de manuseio de dados aos projetos RAG.
O que é abordado neste artigo:
- Como adicionar memória e salvar registros de bate-papos usando LangChain e MongoDB
- Como a adição de memória ajuda em projetos RAG
Para obter mais informações, incluindo guias passo a passo e exemplos, consulte o repositório doGitHub.
Este artigo descreve como adicionar memória a um aplicativo RAG baseado em JavaScript. Veja como isso é feito no Python e até mesmo adicione cache semântica!
Você pode estar acostumado com notebooks que usam Python, mas deve ter notado que o notebook vinculado acima usa JavaScript, especificamente Deno.
Para executar este bloco de anotações, você precisará instalar o Deno e configurar o kernel Deno Jupyter. Você também pode seguir as instruções.
Como o Deno não exige que nenhum pacote seja “installed,, não é necessário instalar nada com npm.
Aqui está um detalhamento das dependências deste projeto:
- mongodb: driver oficial do Node.js da MongoDB
- nodejs-polars: biblioteca JavaScript para análise, pesquisa e manipulação de dados
- ```@langchain: kit de ferramentas JavaScript para LangChain```
- ```@langchain/openai: biblioteca JavaScript para usar OpenAI com LangChain```
- @langchain/MongoDB: biblioteca JavaScript para usar o MongoDB como armazenamento de vetores e armazenamento de histórico de bate-papo com o LangChain
Você também precisará de uma chave de API OpenAI, pois utilizaremos o OpenAI para incorporação e modelos básicos. Salve sua chave de API como uma variável de ambiente.
Para este tutorial, usaremos um cluster de camada grátis no Atlas. Se você ainda não tiver uma conta, registre-see siga as instruções para implantar seu primeiro cluster.
Obtenha sua connection stringdo banco de dados a partir da UI do Atlas e salve-a como uma variável de ambiente.
Vamos usar o conjunto de dados de amostra do MongoDB chamado embedded_movies. Esse conjunto de dados contém uma grande variedade de detalhes de filmes, como roteiro, gênero, elenco e tempo de duração. As incorporações no campo full_plog já foram criadas usando o modelo
text-embedding-ada-002
do OpenAI e podem ser encontradas no campo plot_embedding.Depois de carregar o conjunto de dados, usaremos o Polars para convertê-lo em um DataFrame, o que nos permitirá manipulá-lo e analisá-lo facilmente.
O código acima executa as seguintes operações:
- Importe a biblioteca nodejs-polars para gerenciamento de dados.
- buscar o arquivo sample_mflix.embedded_movies.json diretamente do HuggingFace.
- A variável df analisa o JSON em um DataFrame.
- O DataFrame é limpo para manter apenas os registros que têm informações no campo fullplot. Isso garante que as etapas ou análises futuras que dependem do campo fullplot, como o procedimento de incorporação, não sejam interrompidas por nenhuma ausência de dados.
- Além disso, a coluna plot_embedding dentro do DataFrame é renomeada para inserção. Essa etapa é necessária, pois o LangChain requer um campo de entrada chamado “embedding.”
Depois de concluir as etapas desta parte, acabamos com um conjunto de dados completo que serve como base de informações para o chatbot. Em seguida, adicionaremos os dados em nosso MongoDB database e configuraremos nosso primeiro RAG usando-os.
Começaremos criando uma cadeia RAG simples usando o LangChain, com o MongoDB como armazenamento vetorial. Depois de configurarmos essa configuração, adicionaremos o histórico de bate-papo para otimizá-lo ainda mais.
Nessa cadeia ingênua de RAG , a pergunta do usuário é convertida em uma incorporação e, em seguida, os documentos relevantes do armazenamento de vetores do MongoDB podem ser pesquisados efetivamente usando a Atlas Search vetorial. Esse contexto adicional é então repassado para o LLM na forma de um prompt, que gera uma resposta à pergunta original utilizando o contexto adicional.
Primeiro, precisamos configurar nossa conexão de banco de dados do MongoDB.
Aqui, inicializamos nosso cliente MongoDB usando o driver oficial do MongoDB Node.js. Sim! O motorista Node.js funciona em Deno! 😀 ) Em seguida, definimos nossas variáveis de banco de dados, como nome, coleção e nome do índice. Em seguida, os combinamos para obter nossa coleção.
Você deve estar se perguntado de onde vêm esse banco de dados e essa collection. Mesmo que você esteja começando com um cluster em branco, eles serão criados automaticamente para você se não existirem.
Agora, é hora de consumir o conjunto de dados em nossa coleção de banco de dados.
O ideal é que executemos essa ingestão apenas uma vez, mas, por via das dúvidas, estamos limpando a collection chamando
deleteMany({})
para evitar duplicação de dados.Para inserir os dados, convertemos o DataFrame em registros e os passamos para nosso método
insertMany()
. Não gostaria de registrar todos os IDs retornados (1500), portanto, estou omitindo-os e retornando apenas o restante dos resultados.Se tudo correr bem, você verá isto:
Antes de começarmos a construir nosso armazenamento de vetor para nossa cadeia RAG, precisaremos criar um índice de pesquisa vetorial no MongoDB Atlas. É isso que permite que nosso aplicativo RAG consulte registros semanticamente semelhantes para usar como contexto adicional em nossos prompts LLM.
Certifique-se de criar seu índice de pesquisa vetorial na coleção
data
e nomeá-lo vector_index
. Esta é a definição de índice que você precisará:OBSERVAÇÃO: definimos
numDimensions
como 1536
porque usamos o modelotext-embedding-ada-002
do OpenAI para criar incorporações.Agora, podemos começar a construir o armazenamento vetorial para nossa cadeia RAG.
Usaremos
OpenAIEmbeddings
da LangChain e definimos o modelo utilizado. Novamente, é o modelotext-embedding-ada-002
, que foi utilizado nas incorporações originais deste conjunto de dados.Em seguida, definimos nossa configuração identificando a coleção, o nome do índice, a chave de texto (campo de texto completo da incorporação) e a chave de incorporação (qual campo contém as incorporações).
Em seguida, passe tudo para o nosso método
MongoDBAtlasVectorSearch()
para criar nosso armazenamento de vetores.Agora, podemos "do stuff " com nosso armazenamento de vetores. Precisamos de uma maneira de devolver os documentos que são devolvidos da nossa pesquisa vetorial. Para isso, podemos usar um retriever. (Não do tipo dourado.)
Usaremos o método retriever em nosso repositório vetorial e identificaremos o tipo de pesquisa e o número de documentos a serem recuperados representados por k.
Isso retornará os cinco documentos mais semelhantes que correspondem à nossa query de pesquisa vetorial.
A etapa final é montar tudo em uma cadeia RAG.
KNOWLEDGE: No LangChain, o conceito de cadeias refere-se a uma sequência que pode incluir interações com um LLM, utilização de uma ferramenta específica ou uma etapa relacionada ao processamento de dados. Para construir efetivamente essas cadeias, é aconselhável empregar a LangChain Expression Language (LCEL). Dentro dessa estrutura, cada parte de uma cadeia é chamada de Runnable, permitindo operação ou transmissão independente, separada dos outros componentes da cadeia.
Aqui está o detalhamento do código acima:
- recuperar: utiliza a entrada do usuário para recuperar documentos semelhantes usando o recuperador. A entrada (pergunta) também é passada usando um RunnablePassthrough().
- prompt: o chatPromptTemplate nos permite construir um prompt com instruções específicas para nosso bot ou sistema AI, passando duas variáveis: contexto e pergunta. Essas variáveis são preenchidas a partir do estágio de recuperação acima.
- model: Aqui, podemos especificar qual modelo queremos usar para responder à pergunta. O padrão é atualmente gpt-3.5-turbo se não for especificado.
- naiveRagChain: usando um RunnableSequence, passamos cada estágio em ordem: recuperar, solicitar, modelo e, finalmente, analisamos a saída do LLM em uma string usando StringOutputParser().
É hora de testar! Vamos fazer uma pergunta. Usaremos o método invoke () para fazer isso.
Essa foi uma cadeia RAG simples do dia a dia. Em seguida, vamos dar um passo adiante e implementar o histórico persistente de mensagens de bate-papo. Veja como isso poderia ser.
Primeiro, usamos a pergunta do usuário e qualquer histórico de bate-papo que temos para fazer uma única pergunta que nos ajude a obter documentos do armazenamento de vetores. Em seguida, pegamos a pergunta do usuário, os documentos que encontramos e o histórico de bate-papo e colocamos todos em um LLM para encontrar uma resposta.
Vamos construir outra cadeia que obtenha o histórico de bate-papo separado por sessões do MongoDB.
Definiremos nossa coleção de histórico de bate-papo e a chamaremos de histórico. eu reconheço — único. 😀
Em seguida, usaremos o método MongoDBChatMessageHistory para definir uma sessão. Passamos a coleção de histórico junto com um identificador de sessão exclusivo. Em seguida, para garantir, limparemos o histórico caso executemos isso várias vezes para testes. As funções de procedimento serão adicionadas a esse histórico.
Em seguida, definiremos a cadeia. Este usará o histórico de mensagens de chat e uma pergunta de acompanhamento como entrada e reformulará em uma pergunta autônoma.
Aqui, construiremos outro ChartPromptTemplate semelhante ao anterior. Desta vez, também incluímos o histórico como um espaço reservado para mensagens.
O recuperador usa RunnablePassthrough.assign(...) para adicionar argumentos adicionais antes de passar para o próximo estágio. Aqui, estamos adicionando o contexto do retriever à entrada do usuário antes de continuar para o prompt.
Esse prompt contém a pergunta do usuário, o contexto recuperado e o histórico de chat da sessão.
Na última etapa, montamos uma cadeia RAG e a colocamos dentro de RunnableWithMessageHistory. Este é um tipo de Runnable que lida com o histórico de mensagens de chat para outro Runnable, e isso inclui fazer atualizações.
No método RunnableWithMessageHistory, incluímos o seguinte:
- runnable: o executável básico
- ```getMessageHistory: a função usada para obter o histórico de mensagens do chat```
- inputMessagesKey: a chave usada para identificar a mensagem de entrada
- históricoMessagesKey: a chave usada para identificar o histórico de mensagens
Agora, vamos testar a implementação final:
Quando chamamos o comando
invoke
, especificamosquestion
e sessionId
. Elas devem corresponder às chaves definidas anteriormente.A jornada do avanço da AI de modelos simples de perguntas e respostas para sistemas que podem lembrar e usar conversas anteriores é inovadora. A integração do MongoDB e do LangChain em aplicativos JavaScript RAG empurra significativamente os limites, tornando a AI responsiva e genuinamente perspicaz. Essas tecnologias permitem que os desenvolvedores criem sistemas de AI que entendam e se tornem mais inteligentes a cada interação, oferecendo uma experiência personalizada que lembra a interação humana.
No entanto, a criação de um aplicativo moderno e chamativo vai além da simples configuração de uma estrutura RAG básica. Conforme exploramos, aprimorar a forma como os aplicativos se comunicam com os usuários, personalizando as respostas e rastreando o histórico de conversas, é crucial. Esses elementos devem ser considerados desde o início, mesmo durante a fase preliminar de prova de conceito.
Este guia simplificou o processo de incorporação de memória em aplicativos RAG por meio do MongoDB e do LangChain. Ele forneceu uma abordagem clara e passo a passo para configurar um aplicativo RAG, incluindo a criação de banco de dados, coleta e configuração de índice, e utilizar o LangChain para construir uma cadeia e aplicativo RAG.
Para uma exploração mais aprofundada e para acessar todos os exemplos de código mencionados neste guia, você pode visitar o repositóriofornecido.
- O que é geração aumentada de recuperação (RAG)?O RAG é uma forma de tornar os grandes modelos cerebrais computadorizados (como os LLMs) mais inteligentes, fornecendo a eles as informações mais recentes e corretas. Isso é feito misturando detalhes extras de fora do conhecimento interno do modelo, ajudando-o a dar respostas melhores e mais corretas.
- Como a integração da memória e do histórico de bate-papo aprimora os aplicativos RAG?Adicionar memória e histórico de conversas aos aplicativos RAG permite que eles mantenham e visualizem mensagens anteriores entre o modelo de linguagem grande (LLM) e as pessoas. Esse recurso torna o modelo mais consciente do contexto, ajudando-o a fornecer respostas que se encaixam na pergunta atual e correspondem ao fluxo de conversas em andamento. Ao acompanhar um histórico de bate-papo, os aplicativos RAG podem fornecer respostas mais pessoais e corretas, melhorando consideravelmente a experiência do usuário e melhorando o funcionamento geral do aplicativo.
- Como o MongoDB Atlas oferece suporte a aplicativos RAG?Os recursos de pesquisa vetorial do MongoDB permitem que os aplicativos RAG se tornem mais inteligentes e forneçam respostas mais relevantes. Melhora as funções de memória, simplificando o armazenamento e a recuperação de conversas. Isso aumenta a conscientização do contexto e personaliza as interações do usuário. O resultado é uma melhoria significativa no desempenho do aplicativo e na experiência do usuário, tornando as interações de AI mais dinâmicas e centralizadas no usuário.
- Quais benefícios a integração LangChain-MongoDB oferece?Essa configuração facilita a inclusão de memória baseada em significado em aplicativos RAG. Ele permite o fácil manuseio de registros de conversas anteriores por meio das fortes ferramentas de pesquisa vetorial do MongoDB, levando a um aplicativo melhor executado e a uma experiência melhor para o usuário.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.