Guia de início rápido para aplicativos RAG usando LangChain e LlamaIndex
Kushagra Kesav10 min read • Published Jun 06, 2024 • Updated Sep 18, 2024
Avalie esse Início rápido
Embora grandes modelos de linguagem como o GPT-4 sejam muito bons para gerar conteúdo e argumentos lógicos, eles enfrentam limitações quando se trata de acessar e recuperar dados precisos ou informações contextualmente relevantes. Uma abordagem popular para resolver isso envolve a implementação de um sistema de RAG. Esse sistema integra o modelo de linguagem a um banco de dados vetorial, como o MongoDB Atlas Vector Search, para formar uma framework de AI abrangente, capaz de orquestrar interações entre esses componentes.
À medida que a demanda por recuperação eficiente de informações continua a aumentar, torna-se importante entender a sintaxe e os recursos de vários frameworks. Neste artigo, veremos os fundamentos do vetor Atlas Search em termos simples. Vamos dar uma olhada em LangChain, LlamaIndex e PyMongo, mostrando passo a passo como usar seus métodos para semântica Atlas Search. Ao analisar esses frameworks, pretendemos entender sua respectiva sintaxe e mostrar como eles se comparam com o Atlas Search do vetor MongoDB .
- Visão geral da pesquisa vetorial e do RAG
- Extraia dados salvos do MongoDB, converta em embeddings, armazene de volta e execute pesquisa semântica para obter informações contextuais
- Construa um sistema RAG de ponta a ponta usando o MongoDB ao lado de AI como LlamaIndex e LangChain e, em seguida, compare sua sintaxe
Um banco de dados vetorial é um tipo de solução de armazenamento de dados que gerencia e pesquisa grandes quantidades de dados numéricos de alta dimensão (também conhecidos como dados vetorizados). Esses dados são representados como vetores, criados usando um modelo de incorporação que recebe entradas — como imagens, áudio, vídeo e texto — e as converte em vetores. Esses vetores são armazenados em um banco de dados e podem ser consultados usando métodos semânticas do Atlas Search para recuperação rápida e precisa de objetos de dados semelhantes.
Quando múltiplas representações vetoriais são mapeadas em um espaço de alta dimensão, a distância entre estes vetores nesse espaço reflete a similaridade entre eles. Isso ocorre porque os vetores capturam o contexto e o significado dos dados originais, permitindo uma compreensão refinada de seus relacionamentos. Os bancos de dados vetoriais são projetados para calcular rapidamente a distância entre vetores, permitindo a recuperação eficiente de informações com base em um vetor de query ou na semântica Atlas Search. Por outro lado, os bancos de dados tradicionais dependem da correspondência de palavras-chave para recuperar informações, o que é uma abordagem fundamentalmente diferente.
A geração aumentada por recuperação (RAG) é uma abordagem que usa a recuperação de informações e a AI generativa para fornecer respostas precisas e relevantes às queries do usuário, coletando dados semanticamente relacionados para enriquecer as queries do usuário com contexto extra, processadas como entrada para LLMs.
Esta seção orienta você pelo processo de instalação das bibliotecas essenciais necessárias para implementar o aplicativo RAG com LangChain. Aqui está a lista de bibliotecas necessárias:
- langchain: O kit de ferramentas Python para LangChain
- langchain-mongodb: Um pacote Python para usar o MongoDB como armazenamento de vetores, cache semântico, armazenamento de histórico de bate-papo etc. no LangChain
- pymongo: O kit de ferramentas Python para MongoDB
- openAI: uma biblioteca Python para a API OpenAI
- Neste-asyncio: uma biblioteca de utilitários para executar um loop de eventos assíncronos incorporados
Aqui vamos usar a coleção de amostras
embedding_movies
desample_mflix
e vamos fazer uma limpeza antes de usá-la. Execute o seguinte comando para remover os documentos que não contêm o campoplot
, para que não encontremos erros:1 db.embedded_movies.deleteMany({ plot: { $exists: false } } ) 2 3 { acknowledged: true, deletedCount: 80 }
Agora, criaremos um bloco de anotações Jupyter e anotaremos o código a seguir, que extrairá os dados da coleção especificada.
1 import os 2 from dotenv import load_dotenv 3 from langchain_community.document_loaders.mongodb import MongodbLoader 4 import nest_asyncio 5 6 nest_asyncio.apply() 7 load_dotenv() 8 loader = MongodbLoader( 9 connection_string=os.environ['MONGODB_URI'], 10 db_name=os.environ['MONGODB_DB'], 11 collection_name=os.environ['MONGODB_COLL'], 12 filter_criteria={}, 13 field_names=["title", "plot"] 14 ) 15 docs = loader.load() 16 17 print(len(docs)) 18 docs[0]
Aqui vemos algumas variáveis de ambiente usadas no código. Portanto, criaremos um arquivo .env e colocaremos essas variáveis nele.
1 # MongoDB URI 2 # Replace <username> and <password> with your MongoDB credentials 3 MONGODB_URI='mongodb+srv://<username>:<password>@kushagracluster.abcedf.mongodb.net/' 4 5 # Name of the MongoDB database to use 6 MONGODB_DB='sample_mflix' 7 8 # Name of the MongoDB collection to use within the specified database 9 MONGODB_COLL='embedded_movies' 10 11 # API key for OpenAI. 12 OPENAI_API_KEY="<OPENAI_API_KEY>" 13 14 # Name of the index to use for vector storage 15 MONGODB_VECTOR_INDEX='vector_index' 16 17 # Name of the collection in MongoDB where embedding data is stored 18 MONGODB_VECTOR_COLL_LANGCHAIN='langchain_coll'
No código acima, estamos usando a classe
MongoLoader
para recuperar documentos do MongoDB. A biblioteca dotenv é usada para carregar variáveis de ambiente de um arquivo .env, e a bibliotecanest_asyncio
permite o aninhamento de loop de eventos do Asyncio.Além disso, também inicializamos a classe MongoLoader com parâmetros como a connection string do MongoDB, o nome do banco de dados, o nome da coleção etc. para obter dados de cada documento.
O método
load()
da MongoLoader
é invocado para buscar documentos do MongoDB com base nos parâmetros especificados e, além disso, nós os imprimimos.Agora, adicionaremos outra célula de código no notebook Jupyter e executaremos o código a seguir para criar as incorporações com o OpenAI.
1 from pymongo import MongoClient 2 from langchain.vectorstores import MongoDBAtlasVectorSearch 3 from langchain_community.embeddings import OpenAIEmbeddings 4 from langchain.llms import OpenAI 5 from langchain_community.chat_models import ChatOpenAI 6 from langchain.prompts import ChatPromptTemplate 7 from langchain.chains import LLMChain 8 9 client = MongoClient(os.environ['MONGODB_URI'], appname="devrel.content.langchain_llamaIndex.python") 10 collection = client.get_database(os.environ['MONGODB_DB']).get_collection(os.environ['MONGODB_VECTOR_COLL_LANGCHAIN']) 11 12 vector_search = MongoDBAtlasVectorSearch.from_documents( 13 documents=docs, 14 embedding=OpenAIEmbeddings(openai_api_key=os.environ['OPENAI_API_KEY']), 15 collection=collection, 16 index_name=os.environ['MONGODB_VECTOR_INDEX'])
Este segmento de código executa algumas tarefas relacionadas à configuração de um sistema de pesquisa usando incorporações MongoDB Vector Search, LangChain e OpenAI.
Primeiro, inicializamos um cliente MongoDB usando
client = MongoClient(os.environ['MONGODB_URI'])
e usamos a instância do cliente para acessar uma coleção específica dentro do MongoDB database. Essa coleção manterá os dados de incorporação junto com o texto.Aqui está o documento de amostra:
1 { 2 "_id": { 3 "$oid": "66375d1ff77b69f7b5f0c7ec" 4 }, 5 "text": "The Black Pirate Seeking revenge, an athletic young man joins the pirate band responsible for his father's death....", 6 "embedding": [ 7 -0.003676240383024406, 8 -0.02721614428071944, 9 ... 10 0.02543453162153851, 11 ] 12 ], 13 "database": "sample_mflix", 14 "collection": "embedded_movies" 15 }
Além disso, configuramos a pesquisa vetorial inicializando um objeto de pesquisa vetorial usando a classe MongoDBAtlasVectorSearch do LangChain.
Em seguida, passamos a Docs, que contém documentos obtidos do MongoDB anteriormente, para serem usados na configuração da pesquisa vetorial. Essa linha específica de código,
embedding=OpenAIEmbeddings(openai_api_key=os.environ['OPENAI_API_KEY'])
, usa a chave da API da OpenAI e cria uma incorporação. Em seguida, ela passa a instância da collection para o parâmetro "collection", onde as incorporações de vetores serão armazenadas.Também especificamos o nome do índice do vetor (aqui, vector_index) na coleção que será usada para a pesquisa semântica.
No geral, essa parte do código manipula as conexões com uma instância do MongoDB e configura um sistema de busca vetorial usando o LangChain, com dados vetoriais armazenados no MongoDB e incorporações geradas pelo OpenAI.
Agora, vamos para o MongoDB Atlas e criar um índice de pesquisa vetorial em nossacollection ' langchain_coll'.
Para fazer isso, visite cloud.mongodb.com e selecione a opção de guiaAtlas Search no painel de navegação para criar um índice do Atlas Vector Search. Clique no botãoCriar índice de pesquisa para criar um índice do Atlas Vector Search.
Na página para criar um índice de pesquisa vetorial, selecione a opção Atlas Vector Search, que permite a criação de um índice de pesquisa vetorial definindo o índice que usa JSON.
Para concluir a criação do índice, selecione o banco de dados e a collection para os quais o índice deve ser criado. Neste caso, é o banco de dadossample_mflix e a collectionlangchain_coll. O JSON inserido no editor JSON deve ter a seguinte aparência:
Nota: Certifique-se de que o nome do índice esteja vector_index, pois você o definiu em seu arquivo .env.
1 { 2 "fields": [ 3 { 4 "numDimensions": 1536, 5 "path": "embedding", 6 "similarity": "cosine", 7 "type": "vector" 8 } 9 ] 10 }
Aqui, certifique-se de que está criando um índice vetorial com o mesmo nome que você passou em seu .env. Neste caso, é vector_index.
Até este ponto, fizemos o seguinte com sucesso:
- Dados carregados do nosso banco de dados MongoDB
- Fornecemos cada documento com incorporações usando o modelo de incorporação OpenAI
- Configurado um banco de dados MongoDB para armazenar incorporações de vetor
- Estabelecemos uma conexão com esse banco de dados a partir de nosso ambiente de desenvolvimento
- Criamos um índice de pesquisa vetorial para consulta otimizada de incorporações vetoriais
Agora, volte ao VS Code e escreva o seguinte código que colocará a pesquisa vetorial para funcionar:
1 # perform a similarity search on the ingested documents 2 prompt='What is the best horror movie to watch?' 3 docs_with_score = vector_search.similarity_search_with_score(query=prompt,k=1) 4 5 llm = ChatOpenAI(openai_api_key=os.environ['OPENAI_API_KEY']) 6 7 prompt_template = ChatPromptTemplate.from_messages([ 8 ("system", "You are a movie recommendation engine which posts a concise and short summary on relevant movies."), 9 ("user", "List of movies: {input}") 10 ]) 11 12 # Create an LLMChain 13 chain = LLMChain( 14 llm=llm, 15 prompt=prompt_template 16 ) 17 18 # Prepare the input for the chat model 19 input_docs = "\n".join([doc.page_content for doc, _ in docs_with_score]) 20 21 # Invoke the chain with the input documents 22 response = chain.invoke({"input": input_docs}) 23 print(response['text'])
Essa etapa envolve o processo para configurar uma Atlas Search de similaridade em documentos ingeridos para encontrar as melhores recomendações de filmes de gênero e, em seguida, usar um modelo de linguagem de AI para gerar um resumo conciso dessas recomendações. Então agora, passaremos o prompt contendo a pergunta. Usando o método
similarity_search_with_score
do objetovector_search
, o código procura o documento que mais se aproxima dessa query, retornando o resultado superior.Em seguida, o modelo de idioma
ChatOpenAI
é inicializado com uma chave API . O modelo de prompt é então criado usando ChatPromptTemplate
, que define o contexto do modelo de idioma como um mecanismo de recomendações de filmes. Esse modelo inclui uma mensagem do sistema que define a função da AI e um modelo de mensagem do usuário com um espaço reservado para a saída.Além disso, um objeto
LLMChain
é criado, combinando o modelo de idioma e o modelo de prompt. O conteúdo dos documentos recuperados é extraído e concatenado em uma única string, que serve como entrada para o modelo de idioma. E, finalmente, imprimimos o texto de saída no console.Você pode executar todo o código e ver a pesquisa semântica em ação, onde retornará o melhor filme de terror para assistir. Isso é o que chamamos de magia.
Esta seção orienta você pelo processo de instalação das bibliotecas essenciais necessárias para implementar o aplicativo RAG com LlamaIndex. Aqui está a lista de bibliotecas necessárias:
- openAI: uma biblioteca python para API OpenAI
- llama_index: pacote Python para usar o MongoDB como armazenamento de vetores, cache semântico, armazenamento de histórico de chat etc. em llama_index
- pymongo: conjunto de ferramentas Python para MongoDB
Como já limpamos os dados no processo anterior, não há necessidade de repetir esta etapa. No entanto, se você estiver começando com esta etapa, consulte a ETAPA 2 do método LangChain acima. O processo de limpeza de dados permanece o mesmo.
Seguindo em frente, usaremos a função
SimpleMongoReader
oferecida pelo Llamaindex para carregar os dados:1 import os 2 from llama_index.readers.mongodb import SimpleMongoReader 3 4 reader = SimpleMongoReader(uri=os.environ["MONGODB_URI"]) 5 documents = reader.load_data( 6 os.environ["MONGODB_DB"], 7 os.environ["MONGODB_COLL"], 8 field_names=["title","plot"], # these is a list of the top-level fields in your objects that will be indexed 9 query_dict={} # this is a mongo query dict that will filter your data if you don't want to index everything 10 ) 11 print(documents[0])
Esta parte nos ajuda a conectar a um MongoDB database e recupera documentos de uma coleção especificada. Ele usa uma classe
SimpleMongoReader
fornecida pelo pacotellama_index
para lidar com a interação com o MongoDB. Além dos parâmetros básicos, ele especifica adicionalmente quais campos dos documentos devem ser indexados (neste caso, "title" e "plot"). Também podemos especificar um dicionário de query que pode ser usado para filtrar os dados que estão sendo indexados. Como é empty {}
, indica que nenhuma filtragem específica foi aplicada.1 import pymongo 2 import openai 3 from llama_index.core import VectorStoreIndex,StorageContext 4 from llama_index.vector_stores.mongodb import MongoDBAtlasVectorSearch 5 6 # Create a new client and connect to the server 7 client = pymongo.MongoClient(os.environ["MONGODB_URI"], appname="devrel.content.langchain_llamaIndex.python") 8 9 store = MongoDBAtlasVectorSearch( 10 client, 11 db_name=os.environ['MONGODB_DB'], 12 collection_name=os.environ['MONGODB_VECTOR_COLL_LLAMAINDEX'], # this is where your embeddings will be stored 13 index_name=os.environ['MONGODB_VECTOR_INDEX'] 14 ) 15 16 storage_context = StorageContext.from_defaults(vector_store=store) 17 index = VectorStoreIndex.from_documents( 18 documents, storage_context=storage_context, 19 show_progress=True, # this will show you a progress bar as the embeddings are created 20 )
Nesta etapa, importamos bibliotecas como PyMongo, openAI e mais algumas do LlamaIndex para trabalhar com dados armazenados em um MongoDB database e executar indexação vetorial e operações de pesquisa.
Em seguida, estabelecemos uma conexão MongoDB usando
client = pymongo.MongoClient(os.environ["MONGODB_URI"])
, passando a variável de ambiente "MONGODB_URI"
. Aqui, a funçãoos.environ
recupera o valor da variável de ambiente especificada.Em seguida, criamos um armazenamento de vetor Atlas usando um objeto do tipo
MongoDBAtlasVectorSearch
. Ele usa o nome do banco de dados, o nome da collection e o nome do índice como parâmetros e armazena as incorporações na collection MongoDB especificada.Observação: não se lembre de criar um índice de pesquisa vetorial como fez anteriormente acessando cloud.mongodb.com, selecionando a opção de guia Atlas Search no painel de navegação e selecionando o banco de dadossample_mflix e a coleçãollamaindex_coll.
O JSON inserido no editor de JSON deve ser semelhante ao seguinte:
1 { 2 "fields": [ 3 { 4 "numDimensions": 1536, 5 "path": "embedding", 6 "similarity": "cosine", 7 "type": "vector" 8 } 9 ] 10 }
Em seguida, criamos um índice vetorial usando
storage_context = StorageContext.from_defaults(vector_store=store)
, que gera um objeto de contexto de armazenamento usando as configurações padrão e o associa ao armazenamento vetorial especificado. Em seguida, ele cria um índice vetorial nos documentos carregados em nosso banco de dados. O parâmetroshow_progress
determina se deve ou não ser exibida uma barra de progresso durante o processo de indexação.No geral, esta etapa trata da configuração de uma conexão com um MongoDB database usando o PyMongo e da criação de um armazenamento vetorial usando uma implementação personalizada para o MongoDB Atlas. Além disso, ele gera um índice vetorial a partir de um conjunto de documentos e os incorpora em representações vetoriais para pesquisa e recuperação eficientes.
Até agora, carregamos com sucesso os dados em nossas coleções juntamente com a incorporação gerada para eles usando OpenAI.
Agora, esta etapa combina todas as atividades da etapa anterior para fornecer a funcionalidade de realizar pesquisa vetorial em documentos armazenados com base em consultas incorporadas do usuário. Esta etapa recebe o prompt e o passa como uma consulta. A parte
.as_query_engine(similarity_top_k=1)
determina que ela está configurando o índice para operar como um mecanismo de consulta e especificando que ele retornará apenas o resultado mais semelhante.1 prompt="What is the best horror movie to watch?" 2 response = index.as_query_engine(similarity_top_k=1).query(prompt) 3 4 print(response)
E você verá o seguinte resultado, após a execução de todo o trecho de código, em que ele retorna o melhor filme de terror para assistir:
Se você estiver procurando usar um pipeline de agregação puro ($vectorsearch) para pesquisa semântica sem nenhum framework LLM, consulte nosso tutorial. Você encontrará instruções passo a passo sobre como construir um sistema RAG usando PyMongo, OpenAI e MongoDB.
Neste tutorial, percorremos o processo de criação de um aplicativo RAG com o MongoDB usando duas estruturas diferentes. Mostrei como conectar seu MongoDB database ao LangChain e LlamaIndex separadamente, carregar os dados, criar incorporações, armazená-los de volta à collection MongoDB e, em seguida, executar uma pesquisa semântica usando os recursos de pesquisa vetorial do MongoDB Atlas. Visualize o Github para obter o código de implementação.
Se você tiver alguma dúvida ou feedback, entre em contato com os MongoDB Community e informe-nos o que você criou usando o MongoDB Atlas Vector Search.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.