Desenvolver um sistema RAG com Gemma do Google, Hugging Face e MongoDB
Avalie esse Tutorial
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*
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.
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 2 from datasets import load_dataset 3 import pandas as pd 4 # https://huggingface.co/datasets/MongoDB/embedded_movies 5 dataset = load_dataset("MongoDB/embedded_movies") 6 # Convert the dataset to a pandas DataFrame 7 dataset_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.
- 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. - 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, ogte-large
.
1 # Remove data point where plot column is missing 2 dataset_df = dataset_df.dropna(subset=['fullplot']) 3 print("\nNumber of missing values in each column after removal:") 4 print(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 7 dataset_df = dataset_df.drop(columns=['plot_embedding'])
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ão | Classificação de benchmark de incorporações de texto em grande escala (MTEB) - Recuperação de informações (média) |
GTE-large | 1024 | 52.22 |
GTE-base | 768 | 51.14 |
GTE-small | 384 | 49.46 |
text-embedding-ada-002 | 1536 | 49.25 |
text-embedding-3-small | 256 | 51.08 |
text-embedding-3-large | 256 | 51.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:
- Importe a classe
SentenceTransformer
para acessar os modelos de incorporação. - Carregue o modelo de incorporação usando o construtor
SentenceTransformer
para instanciar o modelo de incorporaçãogte-large
. - 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. - Gerar incorporações aplicando a função
get_embedding
à coluna "fullplot" do DataFramedataset_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.
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.
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.
1 import pymongo 2 from google.colab import userdata 3 4 def 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 14 mongo_uri = userdata.get("MONGO_URI") 15 if not mongo_uri: 16 print("MONGO_URI not set in environment variables") 17 18 mongo_client = get_mongo_client(mongo_uri) 19 20 # Ingest data into MongoDB 21 db = mongo_client["movies"] 22 collection = 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 2 collection.delete_many({})
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.1 documents = dataset_df.to_dict('records') 2 collection.insert_many(documents) 3 print("Data ingestion into MongoDB completed")
As operações abaixo são realizadas no trecho de código:
- Converta o conjunto de dados DataFrame em um dicionário usando o método
to_dict('records')
emdataset_df
. Esse método transforma o DataFrame em uma lista de dicionários. O parâmetrorecords
é crucial, pois encapsula cada linha como um único dicionário. - 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çãoinsert_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.1 def 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:
- 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. - 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. - Construa um pipeline para a função agregada do MongoDB, incorporando dois estágios principais:
$vectorSearch
e$project
. - O estágio
$vectorSearch
realiza a pesquisa vetorial real. O campoindex
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 campoqueryVector
utiliza a representação incorporada da query. O campopath
corresponde ao campo do documento que contém as incorporações. OnumCandidates
especifica o número de documentos candidatos a serem considerados e o limite do número de resultados a serem retornados. - 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
. - 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.
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.1 def 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 2 query = "What is the best romantic movie to watch and why?" 3 source_information = get_search_result(query, collection) 4 combined_information = f"Query: {query}\nContinue to answer the query by using the Search Results:\n{source_information}." 5 print(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.
1 from transformers import AutoTokenizer, AutoModelForCausalLM 2 3 tokenizer = 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 👇🏽 7 model = AutoModelForCausalLM.from_pretrained("google/gemma-2b-it", device_map="auto")
Aqui estão as etapas para carregar o modelo aberto Gemma:
- Importe as classes
AutoTokenizer
eAutoModelForCausalLM
do módulo transformers. - 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. - 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. - 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
. - 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 2 input_ids = tokenizer(combined_information, return_tensors="pt").to("cuda") 3 response = model.generate(**input_ids, max_new_tokens=500) 4 print(tokenizer.decode(response[0]))
As etapas para processar entradas do usuário e a saída do Gemma são as seguintes:
- 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ávelinput_ids
. - 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. - 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. - 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. Oresponse[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 |
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.
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.