Nesta postagem do blog, irei guiá-lo através dos fundamentos dos bancos de dados vetoriais, da pesquisa vetorial e do pacote Langchain em Python, que facilita o armazenamento e a recuperação de vetores comparáveis.
Para embarcar em nossa jornada, começaremos com um conceito fundamental conhecido como “Incorporações”.
Neste artigo, exploraremos o conceito de embeddings – um aspecto fundamental do aprendizado de máquina que nos permite representar dados textuais em um formato que as máquinas podem compreender prontamente.
Essencialmente, os embeddings servem como representações vetoriais de texto, convertendo a intrincada rede de palavras, frases e passagens em um formato numérico que as máquinas podem processar.
Surge uma questão urgente: os humanos podem decifrar essas incorporações? A resposta é não. Embeddings são essencialmente sequências de números que encapsulam informações textuais.
Consequentemente, compreender e trabalhar com um vetor de incorporação pode ser uma tarefa difícil para os humanos, enquanto as máquinas lidam com isso com facilidade.
Existe uma infinidade de técnicas para gerar embeddings a partir de texto. Métodos notáveis incluem TF-IDF, Word2Vec, Glove e BERT, entre outros. No domínio contemporâneo do aprendizado de máquina, os embeddings de frases ganharam popularidade em relação aos embeddings de palavras.
Esses embeddings de frases, que representam a essência de um texto, podem ser obtidos a partir de modelos de transformadores de frases pré-treinados, como "all-MiniLM-L6-V2" e "all-mpnet-base-v2".
Esses modelos produzem incorporações com dimensões fixas, normalmente 384 ou 768 dimensões, para um determinado texto.
Agora que exploramos os fundamentos dos embeddings e diversas técnicas para sua geração, vamos mudar nosso foco para o desafio de armazenar esses vetores de incorporação de alta dimensão em um armazenamento de vetores.
Um armazenamento de dados vetoriais é um banco de dados especializado projetado para armazenar representações de incorporação de alta dimensão de diversos tipos de dados, incluindo áudio, vídeo, imagens, texto e muito mais.
Uma de suas principais funcionalidades é a capacidade de pesquisar com eficiência vetores na loja que se assemelhem muito a um determinado vetor de consulta.
Os armazenamentos de vetores agilizam o processo de armazenamento de embeddings e de realização de pesquisas de similaridade entre esses vetores, simplificando o gerenciamento e a recuperação de representações de dados de alta dimensão.
No domínio dos embeddings vetoriais, a busca por similaridade envolve quantificar a proximidade ou parentesco entre dois ou mais embeddings. Normalmente, isso é conseguido calculando a similaridade usando várias métricas de distância. Algumas métricas de distância comumente usadas e amplamente reconhecidas incluem a distância euclidiana, a distância de Manhattan e a distância do cosseno, entre outras. Essas métricas nos ajudam a avaliar o grau de similaridade ou dissimilaridade entre os vetores, facilitando pesquisas eficazes de similaridade nos dados.
Por exemplo, ao determinar a semelhança ou proximidade entre dois pontos em um gráfico, a distância euclidiana é comumente empregada. Essa distância pode ser calculada usando a seguinte fórmula:
Distância Euclidiana = [(x2 - x1)^2 + (y2 - y1)^2]^0,5
Aqui, (x1, y1) representa as coordenadas do primeiro ponto e (x2, y2) representa as coordenadas do segundo ponto no gráfico. O resultado deste cálculo fornece uma medida da separação espacial entre os dois pontos, indicando sua semelhança ou dissimilaridade em termos de suas posições dentro do gráfico.
Da mesma forma, na busca por similaridade, os embeddings são representados dentro de um espaço de alta dimensão, com cada registro servindo como um ponto de dados.
A linha de código abaixo demonstra como recuperar os 5 principais embeddings semelhantes para determinados dados de entrada:
distance, n = vector_store.search(input_embedding, k=5)
Esse código retornaria uma lista dos 5 principais embeddings que se assemelham muito aos dados de entrada, tornando-o uma ferramenta valiosa para diversas aplicações, como sistemas de recomendação, recuperação de conteúdo e muito mais.
A saída da função vector_store.search() compreende os k principais embeddings semelhantes junto com suas respectivas distâncias do input_embedding. O parâmetro "k" é um valor configurável que determina o número de embeddings mais próximos a serem recuperados na busca por similaridade. Você pode definir "k" para controlar o número desejado de resultados retornados pela operação de pesquisa.
Agora que estabelecemos uma compreensão básica das lojas de vetores, vamos nos aprofundar no pacote LangChain e no FAISS. Essas ferramentas irão aprimorar ainda mais nossa capacidade de trabalhar com incorporações de alta dimensão e realizar pesquisas eficientes de similaridade.
Simplificando, LangChain é uma estrutura projetada para construir aplicativos que aproveitam os recursos de Large Language Models (LLMs). Para obter informações e recursos mais detalhados, você pode consultar a documentação oficial do LangChain.
Por outro lado, FAISS, que significa "Facebook AI Similarity Search", é uma biblioteca Python que fornece aos desenvolvedores um meio rápido e eficiente de pesquisar embeddings semelhantes, afastando-se das abordagens convencionais baseadas em hash.
Esta biblioteca foi desenvolvida pela equipe de IA do Facebook e oferece recursos poderosos para tarefas de pesquisa de similaridade em espaços de alta dimensão.
FAISS é uma biblioteca de código aberto que pode ser hospedada em seu próprio servidor.
Em nossa exploração do LangChain e do FAISS, pretendemos agora implementar o FAISS dentro da estrutura do LangChain. Abaixo estão algumas APIs principais da integração FAISS da LangChain nas quais nos concentraremos neste artigo:
add_documents() : Esta função nos permite incorporar documentos adicionais ao armazenamento de vetores.
add_embeddings() : permite adicionar mais embeddings ao armazenamento de vetores.
from_documents() : Esta API retorna um VectorStore com base nos documentos fornecidos.
from_embeddings() : Esta função fornece um índice FAISS gerado a partir dos embeddings fornecidos.
load_local() : Use para carregar o índice FAISS do disco.
save_local() : permite salvar um índice FAISS no disco.
similarity_search() : Esta função recupera documentos mais semelhantes a uma determinada consulta.
similarity_search_by_vector() : recupera documentos mais semelhantes a uma determinada incorporação.
Essas APIs formam a base para combinar os recursos do LangChain com o FAISS, permitindo que você trabalhe com incorporações e realize pesquisas eficientes de similaridade em seus aplicativos.
A metafiltragem é uma técnica valiosa usada para refinar os resultados de uma consulta de pesquisa no LangChain FAISS. Normalmente existem dois tipos de metafiltragem: pré-filtragem e pós-filtragem. Em nossa estrutura, oferecemos suporte específico à pós-filtragem para consultas de pesquisa.
É importante observar que o conceito de metafiltragem para resultados de pesquisa é um recurso disponível na versão LangChain do FAISS e não está presente na implementação original do FAISS. Esse recurso de pós-filtragem aumenta a precisão e a relevância dos resultados da pesquisa, oferecendo resultados mais personalizados aos usuários.
Armados com o conhecimento das APIs LangChain FAISS, vamos mergulhar na implementação Python do LangChain FAISS. Esta implementação irá capacitá-lo a trabalhar com embeddings, realizar pesquisas de similaridade e aplicar técnicas de pós-filtragem para ajustar seus resultados de pesquisa dentro da estrutura LangChain.
Sinta-se à vontade para explorar e aproveitar esses recursos para criar aplicativos que aproveitem o poder dos modelos de linguagem grande e da pesquisa avançada de similaridade com o FAISS.
Neste guia de instrução, escolhemos o conjunto de dados Stanford como conjunto de dados base e adicionamos algumas colunas para mostrar o trabalho de metafiltragem no LangChain FAISS.
Começaremos instalando e importando os pacotes necessários
!pip install langchain[all] !pip3 install Langchain[FAISS] !pip install faiss-cpu # WARNING: langchain 0.0.74 does not provide the extra 'faiss'
from langchain import FAISS import pandas as pd import numpy as np import os import time import pickle
Agora, importaremos o conjunto de dados:
passage_data = pd.read_csv("/Users/shyam/Python_Programs/Text Similarity Codes/Standford_Edited.csv") passage_data.drop(columns=["Unnamed: 0"],axis=1, inplace=True) passage_data
De posse do conjunto de dados, precisamos inicializar uma função de incorporação para converter os dados de texto em vetores. Usamos “transformadores de frases/all-MiniLM-L6-V2“ que gera embeddings em 384 dimensões,
from langchain.embeddings import SentenceTransformerEmbeddings embedding_function = SentenceTransformerEmbeddings(model_name="all-MiniLM-L6-v2")
Definiremos as informações de metadados. Nos metadados, adicionamos o ID do documento e o idioma do documento para cada incorporação (conteúdo),
start=time.time() metadatas = [] for index, row in passage_data.iterrows(): doc_meta = { "id": row['Id'], "language": row['Language'] } metadatas.append(doc_meta)
É isso… Vamos construir nosso índice FAISS agora,
faiss = FAISS.from_texts(passage_data['Content'].tolist(), embedding_function, metadatas) print("Time Taken --> ", time.time()-start)
Agora, tentaremos salvar o índice FAISS em disco e carregá-lo de volta:
faiss.save_local("/Users/shyam/Python_Programs/LangChain_FAISS", "Standford") loaded_faiss = faiss.load_local("/Users/shyam/Python_Programs/LangChain_FAISS",embedding_function, "Standford")
Concluímos a construção do índice FAISS, armazenamento e carregamento. É hora de inferência. Tentaremos pesquisar algumas consultas e testar o índice FAISS.
Primeiro, obteremos os cinco principais documentos semelhantes relacionados ao “ateísmo”.
start=time.time() loaded_faiss.similarity_search_with_score("What is atheism?",5)
Bem, os resultados são convincentes. Mas ainda assim, exploraremos mais…
Desta vez, tentaremos uma consulta de idioma diferente com alguma metafiltragem. Faremos uma consulta em russo informando que os critérios de filtragem devem ser {lang: 'ru_RU'}.
#Что такое атеизм? - Russian loaded_faiss.similarity_search_with_score("Что такое атеизм?",5, {"language":"ru_RU"}, 10)
Aqui, mencionamos pegar os dez documentos mais semelhantes do armazenamento de vetores e, em seguida, aplicar nossa condição de filtragem para obter os cinco principais documentos para nossa consulta.
Ao concluir este artigo, acredito que você tenha adquirido uma sólida compreensão sobre armazenamento de vetores e pesquisa de vetores. Também fornecemos uma demonstração do LangChain FAISS para ilustrar sua funcionalidade.
Eu recomendo fortemente que você explore outras lojas de vetores, como ChromaDb, Qdrant, Milvus e muito mais.
Cada armazenamento de vetores vem com seu conjunto exclusivo de vantagens e desvantagens, portanto, faça sua seleção com base nos requisitos específicos do seu caso de uso.
Desejo a você uma jornada de aprendizado agradável e frutífera!