Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Junte-se a nós no Amazon Web Services re:Invent 2024! Saiba como usar o MongoDB para casos de uso de AI .
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Produtoschevron-right
Atlaschevron-right

Desenvolver um sistema RAG com Gemma do Google, Hugging Face e MongoDB

Richmond Alake12 min read • Published Feb 22, 2024 • Updated Mar 21, 2024
IAPythonAtlas
SNIPPET
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty

Introdução

O Google lançou recentemente um modelo aberto de última geração na comunidade de AI chamada Gemma. Especificamente, o Google lançou quatro variantes do Gemma: modelo de base Gemma 2B, modelo de instrução Gemma 2B, modelo de base Gemma 7B e modelo de instrução Gemma 7B. O modelo aberto Gemma e suas variantes usam blocos de construção semelhantes ao Gemini, o modelo de base mais capaz e eficiente do Google construído com arquitetura Mix-of-Expert (MoE).
Este artigo apresenta como aproveitar o Gemma como modelo básico em um pipeline ou sistema de geração aumentada de recuperação (RAG), com modelos de suporte fornecidos pelo Hugging Face, um repositório para modelos de código aberto, conjuntos de dados e recursos computacionais. A pilha de AI apresentada neste artigo utiliza os grandes modelos de incorporação GTE do Hugging Face e MongoDB como banco de dados vetorial.
O que esperar deste artigo:
  • Visão geral rápida de um sistema RAG
  • Informações sobre o Gemma, o mais recente modelo aberto do Google
  • Utilizando o Gemma em um sistema RAG como modelo base
  • Criando um sistema RAG de ponta a ponta com uma base de código aberto e incorporando modelos do Hugging Face*
Representação de um pipeline RAG usando MongoDB, Gemma e Hugging Face

Etapa 1: instalar bibliotecas

Todas as etapas de implementação podem ser acessadas no repositório, que possui uma versão em notebook do sistema RAG apresentado neste artigo.
A sequência de comandos do shell abaixo instala bibliotecas para aproveitar grandes modelos de linguagem (LLMs) de código aberto, modelos de incorporação e funcionalidades de interação de banco de dados. Essas bibliotecas simplificam o desenvolvimento de um sistema RAG, reduzindo a complexidade a uma pequena quantidade de código:
1!pip install datasets pandas pymongo sentence_transformers
2!pip install -U transformers
3# Install below if using GPU
4!pip install accelerate
  • PyMongo: uma biblioteca Python para interagir com o MongoDB que habilita funcionalidades para se conectar a um cluster e executar query de dados armazenados em coleções e documentos.
  • Pandas: fornece uma estrutura de dados para processamento e análise eficientes de dados usando Python
  • Conjuntos de dados do Hugging Face: contêm conjuntos de dados de áudio, visão e texto
  • Hugging Face Accelerate: abstrai a complexidade de gravação de código que aproveita aceleradores de hardware, como GPUs. O Accelerate é aproveitado na implementação para utilizar o modelo Gemma em recursos de GPU.
  • Hugging Face Transformers: acesso a uma vasta coleção de modelos pré-treinados
  • Hugging Face Sentence Transformers: fornece acesso a incorporações de frases, textos e imagens.

Etapa 2: fonte de dados e preparação

Os dados utilizados neste tutorial são provenientes de conjuntos de dados da Hugging Face, especificamente do conjunto de dados AIatMongoDB/embedded_movies
Um ponto de dados dentro do conjunto de dados de filmes contém atributos específicos de uma entrada de filme individual; enredo, gênero, elenco, tempo de execução e outros são capturados para cada ponto de dados. Depois de carregar o conjunto de dados no ambiente de desenvolvimento, ele é convertido em um objeto Pandas DataFrame, que permite a manipulação e a análise eficientes da estrutura de dados.
1# Load Dataset
2from datasets import load_dataset
3import pandas as pd
4# https://huggingface.co/datasets/MongoDB/embedded_movies
5dataset = load_dataset("MongoDB/embedded_movies")
6# Convert the dataset to a pandas DataFrame
7dataset_df = pd.DataFrame(dataset['train'])
As operações no trecho de código a seguir se concentram em reforçar a integridade e a qualidade dos dados. 
  1. O primeiro processo garante que o atributo fullplot de cada ponto de dados não esteja vazio, pois esses são os dados primários que utilizamos no processo de incorporação. 
  2. Esta etapa também garante a remoção do atributo plot_embedding de todos os pontos de dados, pois ele será substituído por novas incorporações criadas com um modelo de incorporação diferente, o gte-large.
1# Remove data point where plot column is missing
2dataset_df = dataset_df.dropna(subset=['fullplot'])
3print("\nNumber of missing values in each column after removal:")
4print(dataset_df.isnull().sum())
5
6# Remove the plot_embedding from each data point in the dataset as we are going to create new embeddings with an open-source embedding model from Hugging Face: gte-large
7dataset_df = dataset_df.drop(columns=['plot_embedding'])

Etapa 3: gerar incorporações

Os modelos de incorporação convertem dados de alta dimensão, como texto, áudio e imagens, em uma representação numérica de dimensão inferior que captura a semântica e o contexto dos dados de entrada. Essa representação de incorporação de dados pode ser usada para realizar pesquisas semânticas com base nas posições e na proximidade das incorporações entre si em um espaço vetorial.
O modelo de incorporação usado no sistema RAG é o modelo Generate Text Embedding (GTE), baseado no modelo BERT. Os modelos de incorporação do GTE vêm em três variantes, mencionadas abaixo, e foram treinados e lançados pela Alibaba DAMO Academy, uma instituição de pesquisa.
Modelo DimensãoClassificação de benchmark de incorporações de texto em grande escala (MTEB) - Recuperação de informações (média)
GTE-large102452.22
GTE-base76851.14
GTE-small38449.46
text-embedding-ada-002153649.25
text-embedding-3-small25651.08
text-embedding-3-large25651.66
Na comparação entre os modelos de incorporação de código aberto GTE e os modelos de incorporação fornecidos pela OpenAI, o modelo de incorporação GTE-Large oferece melhor desempenho nas tarefas de recuperação, mas requer mais armazenamento para incorporar vetores em comparação com os modelos de incorporação mais recentes da OpenAI. Em especial, o modelo de incorporação GTE só pode ser usado em textos em inglês.
O trecho de código abaixo demonstra a geração de incorporações de texto com base no texto no atributo "fullplot" para cada registro de filme no DataFrame. Usando a biblioteca SentenceTransformers, temos acesso ao modelo "thenlper/gte-large" hospedado no Hugging Face. Se o seu ambiente de desenvolvimento tiver recursos computacionais limitados e não puder conter o modelo de incorporação na RAM, utilize outras variantes do modelo de incorporação GTE: gte-base ou gte-small.
As etapas nos trechos de código são as seguintes:
  1. Importe a classe SentenceTransformer para acessar os modelos de incorporação.
  2. Carregue o modelo de incorporação usando o construtor SentenceTransformer para instanciar o modelo de incorporação gte-large.
  3. Defina a função get_embedding function, que recebe uma string de texto como entrada e retorna uma lista de floats que representam a incorporação. A função primeiro verifica se o texto de entrada não está vazio (depois de remover os espaços em branco). Se o texto estiver vazio, ela retorna uma lista vazia. Caso contrário, ela gera uma incorporação usando o modelo carregado.
  4. Gerar incorporações aplicando a função get_embedding à coluna "fullplot" do DataFrame dataset_df, gerando incorporações para o enredo de cada filme. A lista resultante de incorporações é atribuída a uma nova coluna denominada incorporações.
1 from sentence_transformers import SentenceTransformer
2 # https://huggingface.co/thenlper/gte-large
3 embedding_model = SentenceTransformer("thenlper/gte-large")
4
5 def get_embedding(text: str) -> list[float]:
6     if not text.strip():
7         print("Attempted to get embedding for empty text.")
8         return []
9
10     embedding = embedding_model.encode(text)
11
12     return embedding.tolist()
13
14 dataset_df["embedding"] = dataset_df["fullplot"].apply(get_embedding)
Após esta seção, agora temos um conjunto de dados completo com incorporações que podem ser ingeridas em um banco de dados vetorial, como o MongoDB, onde as operações de pesquisa vetorial podem ser realizadas.

Etapa 4: configuração e conexão do banco de dados

Antes de prosseguir, certifique-se de que os seguintes pré-requisitos sejam atendidos
  • Cluster de banco de dados configurado no MongoDB Atlas
  • Obteve o URI para seu cluster
Para obter assistência com a configuração de cluster de banco de dados e a obtenção do URI, consulte nosso guia para configurar um MongoDB cluster e obter a string de conexão. Como alternativa, siga a etapa 5 deste artigo sobre o uso de incorporações em um sistema RAG, que oferece instruções detalhadas sobre a configuração de cluster de banco de dados.
Depois de criar um cluster, crie o banco de dados e a coleção no MongoDB Atlas cluster clicando em + Criar banco de dados. O banco de dados terá o nome de movies e a coleção terá o nome de movies_records.
Criando um banco de dados e coleção Certifique-se de que o URI de conexão esteja armazenado com segurança em seu ambiente de desenvolvimento depois de configurar o banco de dados e obter o URI de conexão do cluster do Atlas.
Este guia usa o Google Colab, que oferece um recurso para o armazenamento seguro de segredos de ambiente. Esses segredos podem ser acessados no ambiente de desenvolvimento. Especificamente, o código mongo_uri = userdata.get('MONGO_URI') recupera o URI do armazenamento seguro. Você pode clicar no ícone "key" no lado direito do Colab Notebook para definir valores para os segredos.
O trecho de código abaixo também usa o PyMongo para criar um objeto de cliente MongoDB, representando a conexão com o cluster e permitindo o acesso aos seus bancos de dados e coleções.
1import pymongo
2from google.colab import userdata
3
4def get_mongo_client(mongo_uri):
5 """Establish connection to the MongoDB."""
6 try:
7 client = pymongo.MongoClient(mongo_uri)
8 print("Connection to MongoDB successful")
9 return client
10 except pymongo.errors.ConnectionFailure as e:
11 print(f"Connection failed: {e}")
12 return None
13
14mongo_uri = userdata.get("MONGO_URI")
15if not mongo_uri:
16 print("MONGO_URI not set in environment variables")
17
18mongo_client = get_mongo_client(mongo_uri)
19
20# Ingest data into MongoDB
21db = mongo_client["movies"]
22collection = db["movie_collection_2"]
O código a seguir garante que a coleção de banco de dados atual esteja vazia executando a operação delete_many() na coleção.
1# Delete any existing records in the collection
2collection.delete_many({})

Etapa 5: criação do índice de pesquisa vetorial

Criar um índice de pesquisa vetorial dentro da coleção movies_records é essencial para a recuperação eficiente de documento do MongoDB em nosso ambiente de desenvolvimento. Para conseguir isso, consulte o guia oficial de criação de índice de pesquisa vetorial.
Na criação de um índice de pesquisa vetorial usando o editor JSON no MongoDB Atlas, certifique-se de que seu índice de pesquisa vetorial seja nomeado como vector_index e que a definição do índice de pesquisa vetorial seja a seguinte:
1{
2 "fields": [{
3 "numDimensions": 1024,
4 "path": "embedding",
5 "similarity": "cosine",
6 "type": "vector"
7 }]
8}
O valor 1024 do campo NumDimension corresponde à dimensão do vetor gerado pelo modelo de incorporação gte-large. Se você usar os modelos de incorporação gte-base ou gte-small, o valor numDimension no índice de pesquisa vetorial deverá ser definido como 768 e 384, respectivamente .
Até este ponto, fizemos o seguinte com sucesso:
  • Dados carregados obtidos do Hugging Face
  • Fornecido a cada ponto de dados com incorporação usando o modelo de incorporação GTE-large do Hugging Face
  • Configurar um MongoDB database projetado para armazenar incorporações de vetor
  • Estabelecemos uma conexão com esse banco de dados a partir de nosso ambiente de desenvolvimento
  • Definimos um índice de pesquisa vetorial para consulta eficiente de incorporações vetoriais
A ingestão de dados em uma coleção do MongoDB a partir de um DataFrame do pandas é um processo simples que pode ser realizado com eficiência convertendo o DataFrame em dicionários e, em seguida, utilizando o método insert_many na coleção para passar os registros do conjunto de dados convertidos.
1documents = dataset_df.to_dict('records')
2collection.insert_many(documents)
3print("Data ingestion into MongoDB completed")
As operações abaixo são realizadas no trecho de código:
  1. Converta o conjunto de dados DataFrame em um dicionário usando o método to_dict('records') em dataset_df. Esse método transforma o DataFrame em uma lista de dicionários. O parâmetro records é crucial, pois encapsula cada linha como um único dicionário.
  2. Faça a ingestão de dados no banco de dados vetorial do MongoDB chamando a função insert_many(documents) na coleção do MongoDB, passando a lista de dicionários. A função insert_many do MongoDB ingere cada dicionário da lista como um documento individual dentro da coleção.
A etapa a seguir implementa uma função que retorna um resultado de pesquisa vetorial gerando uma query de incorporação e definindo um pipeline de agregação do MongoDB. 
O pipeline, que consiste nos estágios $vectorSearch e $project, executa queries usando o vetor gerado e formata os resultados para incluir somente as informações necessárias, como trama, título e gêneros, incorporando uma pontuação de pesquisa para cada resultado.
1def vector_search(user_query, collection):
2 """
3 Perform a vector search in the MongoDB collection based on the user query.
4
5 Args:
6 user_query (str): The user's query string.
7 collection (MongoCollection): The MongoDB collection to search.
8
9 Returns:
10 list: A list of matching documents.
11 """
12
13 # Generate embedding for the user query
14 query_embedding = get_embedding(user_query)
15
16 if query_embedding is None:
17 return "Invalid query or embedding generation failed."
18
19 # Define the vector search pipeline
20 pipeline = [
21 {
22 "$vectorSearch": {
23 "index": "vector_index",
24 "queryVector": query_embedding,
25 "path": "embedding",
26 "numCandidates": 150, # Number of candidate matches to consider
27 "limit": 4, # Return top 4 matches
28 }
29 },
30 {
31 "$project": {
32 "_id": 0, # Exclude the _id field
33 "fullplot": 1, # Include the plot field
34 "title": 1, # Include the title field
35 "genres": 1, # Include the genres field
36 "score": {"$meta": "vectorSearchScore"}, # Include the search score
37 }
38 },
39 ]
40
41 # Execute the search
42 results = collection.aggregate(pipeline)
43 return list(results)
O trecho de código acima realiza as seguintes operações para permitir a pesquisa semântica de filmes:
  1. Defina a função vector_search que recebe a string de query de um usuário e uma coleção do MongoDB como entradas e retorna uma lista de documentos que correspondem à query com base na pesquisa de similaridade de vetores.
  2. Gere uma incorporação para a query do usuário chamando a função definida anteriormente, get_embedding, que converte a string de query em uma representação vetorial.
  3. Construa um pipeline para a função agregada do MongoDB, incorporando dois estágios principais: $vectorSearch e $project.
  4. O estágio $vectorSearch realiza a pesquisa vetorial real. O campo index especifica o índice vetorial a ser utilizado para a pesquisa vetorial e deve corresponder ao nome inserido na definição do índice de pesquisa vetorial nas etapas anteriores. O campo queryVector utiliza a representação incorporada da query. O campo path corresponde ao campo do documento que contém as incorporações. O numCandidates especifica o número de documentos candidatos a serem considerados e o limite do número de resultados a serem retornados.
  5. O estágio $project formata os resultados para incluir somente os campos obrigatórios: enredo, título, gênero e pontuação da pesquisa. Exclui explicitamente o campo _id.
  6. O aggregate executa o pipeline definido para obter os resultados da pesquisa vetorial. A operação final converte o cursor retornado do banco de dados em uma lista.

Etapa 7: lidando com queries de usuários e carregando Gemma

O trecho de código define a função get_search_result, um wrapper personalizado para executar a pesquisa vetorial usando o MongoDB e formatar os resultados a serem passados para os estágios posteriores no pipeline do RAG.
1def get_search_result(query, collection):
2
3 get_knowledge = vector_search(query, collection)
4
5 search_result = ""
6 for result in get_knowledge:
7 search_result += f"Title: {result.get('title', 'N/A')}, Plot: {result.get('fullplot', 'N/A')}\n"
8
9 return search_result
A formatação dos resultados de pesquisa extrai o título e o gráfico usando o método get e fornece valores padrão ("N/A") se um dos campos estiver faltando. Os resultados retornados são formatados em uma string que inclui o título e o gráfico de cada documento, que é anexado a search_result, com os detalhes de cada documento separados por um caractere de nova linha.
O sistema RAG implementado nesse caso de uso é um mecanismo de consulta que realiza recomendações de filmes e fornece uma justificativa para sua seleção.
1# Conduct query with retrieval of sources
2query = "What is the best romantic movie to watch and why?"
3source_information = get_search_result(query, collection)
4combined_information = f"Query: {query}\nContinue to answer the query by using the Search Results:\n{source_information}."
5print(combined_information)
Uma query do usuário é definida no trecho de código acima; essa query é o alvo da pesquisa semântica em relação às incorporações de filmes na coleção do banco de dados. Os resultados da query e da pesquisa vetorial são combinados em uma única string para passar como um contexto completo para o modelo base do sistema RAG. 
As etapas a seguir carregam o modelo de instrução Gemma-2b ("google/gemma-2b-it") no ambiente de desenvolvimento usando a biblioteca Transformers da Hugging Face. O trecho de código abaixo carrega um tokenizador e um modelo da biblioteca Transformers da Hugging Face.
1from transformers import AutoTokenizer, AutoModelForCausalLM
2
3tokenizer = AutoTokenizer.from_pretrained("google/gemma-2b-it")
4# CPU Enabled uncomment below 👇🏽
5# model = AutoModelForCausalLM.from_pretrained("google/gemma-2b-it")
6# GPU Enabled use below 👇🏽
7model = AutoModelForCausalLM.from_pretrained("google/gemma-2b-it", device_map="auto")
Aqui estão as etapas para carregar o modelo aberto Gemma:
  1. Importe as classes AutoTokenizer e AutoModelForCausalLM do módulo transformers.
  2. Carregue o tokenizador usando o método AutoTokenizer.from_pretrained para instanciar um tokenizador para o modelo "google/gemma-2b-it". Este tokenizador converte o texto de entrada em uma sequência de tokens que o modelo pode processar.
  3. Carregue o modelo usando o método AutoModelForCausalLM.from_pretrained. Existem duas opções fornecidas para carregamento de modelo e cada uma acomoda diferentes ambientes de computação.
  4. Uso da CPU: para ambientes que só usam a CPU para cálculos, o modelo pode ser carregado sem especificar o parâmetro device_map.
  5. Uso de GPU: o parâmetro device_map="auto" é incluído para ambientes com suporte a GPU para mapear automaticamente os componentes do modelo para os recursos de computação de GPU disponíveis.
1# Moving tensors to GPU
2input_ids = tokenizer(combined_information, return_tensors="pt").to("cuda")
3response = model.generate(**input_ids, max_new_tokens=500)
4print(tokenizer.decode(response[0]))
As etapas para processar entradas do usuário e a saída do Gemma são as seguintes:
  1. Tokenize a entrada de texto combined_information para obter uma sequência de tokens numéricos como tensores PyTorch; o resultado desta operação é atribuído à variável input_ids.
  2. Os input_ids são movidos para o recurso GPU disponível usando o método `.to("cuda ")'; o objetivo é acelerar a computação do modelo.
  3. Gere uma resposta a partir do modelo envolvendo a função model.generate com o tensor input_ids. O parâmetro max_new_tokens=500 limita o comprimento do texto gerado, evitando que o modelo produza saídas excessivamente longas.
  4. Por fim, decodifique a resposta do modelo usando o método tokenizer.decode, que converte os tokens gerados em uma string de texto legível. O response[0] acessa o tensor de resposta contendo os tokens gerados.
Query Respostas de Gemma
Qual é o melhor filme romântico para assistir e por quê?Com base nos resultados da pesquisa, o melhor filme romântico para assistir é **Venha me beijar** porque é uma comédia romântica que explora as complexidades do amor e dos relacionamentos. O filme é cômico, comovente e instigante

Conclusão

A implementação de um sistema RAG neste artigo utilizou conjuntos de dados, modelos e modelos de incorporação totalmente abertos disponíveis via Hugging Face. Utilizando o Gemma, é possível criar sistemas RAG com modelos que não dependem do gerenciamento e da disponibilidade de modelos de provedores de modelos de código fechado. 
As vantagens de aproveitar os modelos abertos incluem a transparência nos detalhes de treinamento dos modelos utilizados, a oportunidade de ajustar os modelos de base para a utilização de outras tarefas de nicho e a capacidade de utilizar dados confidenciais privados com modelos hospedados localmente.
Para entender melhor os modelos abertos versus fechados e seu aplicativo a um sistema RAG, temos um artigo que implementa um sistema RAG de ponta a ponta usando a pilha POLM, que usa modelos de incorporação e LLMs fornecidos pela OpenAI.
Todas as etapas de implementação podem ser acessadas no repositório, que tem uma versão para notebook do sistema RAG apresentado neste artigo.

Perguntas frequentes

1. O que são os modelos Gemma? Os modelos Gemma são uma família de modelos abertos, leves e de última geração para geração de texto, incluindo resposta a perguntas, resumo e argumentos. Inspirados no Gemini do Google, eles estão disponíveis nos tamanhos 2 B e 7 B, com variantes pré-treinadas e ajustadas por instruções.
2. Como os modelos Gemma se encaixam em um sistema RAG?
Em um sistema RAG, os modelos Gemma são o modelo base para gerar respostas com base em queries de entrada e informações de origem recuperadas por meio de pesquisa vetorial. Sua eficiência e versatilidade no manuseio de uma ampla faixa de formatos de texto os tornam ideais para essa finalidade.
3. Por que usar o MongoDB em um sistema RAG?
O MongoDB é usado por seu gerenciamento robusto de incorporações vetoriais, permitindo armazenamento, recuperação e queries eficientes de vetores de documentos. O MongoDB também serve como um banco de dados operacional que permite recursos tradicionais de banco de dados transacional. O MongoDB serve como banco de dados operacional e vetorial para aplicativos modernos de IA.
4. Os modelos Gemma podem funcionar com recursos limitados?
Apesar de seus recursos avançados, os modelos Gemma são projetados para implantação em ambientes com recursos computacionais limitados, como notebooks ou desktops, tornando-os acessíveis para uma ampla variedade de aplicativos. Os modelos Gemma também podem ser implantados usando as opções de implantação habilitadas pelo Hugging Face, como API de inferência, pontos de extremidade de inferência e soluções de implantação por meio de vários serviços em nuvem.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.
Iniciar a conversa

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Artigo

Dimensões que mudam lentamente e seu uso no MongoDB


Dec 13, 2022 | 7 min read
Tutorial

Modelagem de dados em várias linguagens do Atlas Search


Sep 09, 2022 | 2 min read
Tutorial

Desenvolvendo seus aplicativos de forma mais eficiente com as instâncias sem servidor do MongoDB Atlas


Feb 03, 2023 | 7 min read
Artigo

Implantação fácil do MEAN stack com MongoDB Atlas, Cloud Run e HashiCorp Terraform


Jan 30, 2023 | 4 min read
Sumário