O que são embeddings?
- "Embedding" é a conversão de conteúdo em um "array de números de ponto flutuante"
- O ponto principal desse array é que, independentemente do "tamanho do conteúdo", o "tamanho do array" é sempre o mesmo
- O tamanho do array é determinado pelo modelo de embedding usado: 300, 1000, 1536 etc.
- A melhor forma de pensar nesse array é imaginá-lo como as "coordenadas em um espaço multidimensional muito estranho"
- Por que posicionar conteúdo em um espaço multidimensional? Porque é possível aprender coisas interessantes sobre esse conteúdo com base em sua posição, especialmente em relação a outros conteúdos próximos
- A posição no espaço representa o "significado semântico (Semantic Meaning)" do conteúdo, de acordo com a "compreensão estranha, e em grande parte incompreensível, que o modelo de embedding tem do mundo"
- Ele pode capturar cor, forma, conceito ou todo tipo de outra característica do conteúdo embutido
- Ninguém entende completamente o que cada um desses números individuais significa, mas sabemos que a posição deles pode ser usada para encontrar informações úteis sobre o conteúdo
Encontrando conteúdo relacionado com embeddings
- O primeiro problema que resolvi com embeddings foi criar o recurso de "Related Content" no meu blog TIL
- Usei o modelo
text-embedding-ada-002 da OpenAI, disponível via API
- Hoje meu site tem 472 textos, e para cada um deles calculei um vetor de embedding de 1536 dimensões (um array de números de ponto flutuante) e armazenei esse vetor no banco SQLite do meu site
- Agora, para encontrar textos relacionados a um texto específico, basta calcular a similaridade de cosseno (Cosine Similarity) entre o vetor de embedding desse texto e os outros textos do banco, e então retornar os 10 resultados mais próximos por distância
- O código Python que usei para similaridade de cosseno é este
def cosine_similarity(a, b):
dot_product = sum(x * y for x, y in zip(a, b))
magnitude_a = sum(x * x for x in a) ** 0.5
magnitude_b = sum(x * x for x in b) ** 0.5
return dot_product / (magnitude_a * magnitude_b)
- A API de embeddings da OpenAI é muito barata e fácil de usar
- Eu gerei embeddings para cerca de 400 mil tokens no meu site TIL, e a $0.0001 por mil tokens, isso custou apenas $0.04 no total
- Basta fazer um POST com a chave da API e o texto, e ela retorna um array JSON de números de ponto flutuante
- Mas este é um modelo proprietário, e alguns meses atrás a OpenAI encerrou alguns de seus modelos de embedding
- Ou seja, se você armazenou um grande número de embeddings desse modelo, terá que recalculá-los para um novo modelo
- A OpenAI disse que compensaria o custo de re-embedding para o novo modelo, mas é preciso ter cuidado com modelos proprietários
- Isso pode ser evitado usando modelos com licenças abertas e robustas
Entendendo como isso funciona com o modelo Word2Vec
- Há 10 anos, o Google Research publicou um artigo influente explicando um dos primeiros modelos de embedding, o Word2Vec
- O artigo de 2013, "Efficient Estimation of Word Representations in Vector Space", despertou o interesse por embeddings
- Word2Vec é um modelo que pega uma única palavra e a transforma em uma lista de 300 números. Essa lista captura informações sobre o significado de palavras relacionadas
- Ao procurar uma palavra, é possível encontrar palavras semelhantes com base na distância de cosseno em relação à representação Word2Vec dessa palavra
- Se você buscar por "france", pode obter valores como "french : 0.70007~", "belgium: 0.69331~", "paris: 0.63349~", "germany: 0.62707~"
- Isso mistura aspectos do que é francês com a geografia da Europa
- O mais interessante aqui é que você pode fazer operações aritméticas com esses vetores
- Se você pegar o vetor de "germany", somar "paris" e subtrair "france", o vetor resultante ficará mais próximo de "berlin"
- Esse modelo capturou ideias sobre nacionalidade e geografia, a ponto de permitir explorar fatos adicionais sobre o mundo por meio de aritmética
- O Word2Vec foi treinado com 1,6 bilhão de palavras, e os modelos de embedding que usamos hoje são treinados com conjuntos de dados muito maiores, capturando uma compreensão muito mais rica das relações subjacentes
Calculando e pesquisando embeddings com minhas ferramentas
- Estou criando uma CLI e biblioteca Python chamada LLM
- Ela pode ser usada como CLI para interagir com LLMs, e também permite integração com OpenAPI
- Alguns meses atrás, também adicionei a essa ferramenta a capacidade de executar modelos de embedding via plugins (com suporte à biblioteca SentenceTransformers)
- É possível escolher uma coleção de embeddings e fazer buscas semânticas baseadas em "vibe"
- Também estou criando a ferramenta Symbex para encontrar símbolos em bases de código Python. Com ela, é possível calcular embeddings para funções do código e construir um mecanismo de busca para código
- (A implementação detalhada foi omitida)
Embeddings conjuntos de texto e imagem com CLIP
- Meu modelo de embedding favorito no momento é o CLIP
- É um modelo lançado pela OpenAI em janeiro de 2021 que consegue gerar embeddings tanto de "texto quanto de imagem", colocando ambos no mesmo espaço vetorial
- Se você inserir "dog", obterá uma posição em um espaço de 512 dimensões (varia conforme a configuração do CLIP)
- Se gerar o embedding de uma foto de cachorro, ela também ganhará uma posição nesse mesmo espaço, próxima da string "dog" em termos de distância
- Isso significa que você pode usar texto para buscar imagens relacionadas, ou usar imagens para buscar textos relacionados
- Se inserir uma foto de praia, pode obter pontuações de similaridade como "beach: 26.946%", "city: 19.839%", "sunshine: 24.146%"
Encontrando torneiras com CLIP
- Drew Breunig construiu um mecanismo de busca de torneiras com o plugin llm-clip
- Ele reuniu 20 mil fotos de torneiras e rodou o CLIP nelas
- Depois disso, passou a ser possível encontrar torneiras parecidas com outras torneiras e, entre elas, localizar opções semelhantes, mas mais baratas
Respondendo perguntas com RAG
- A pergunta final de todo mundo que já usou o ChatGPT é sempre a mesma
"Como faço para ele responder sobre as minhas anotações ou os documentos da minha empresa?"
- As pessoas presumem que isso exige treinar um modelo customizado com esse conteúdo, a um custo enorme
- Mas na prática isso não é necessário. Isso se tornou possível com LLMs e RAG (Retrieval Augmented Generation)
- A ideia central é que "o usuário faz uma pergunta"
- Em seguida, você encontra nos seus documentos pessoais o que for relevante para essa pergunta
- Então você envia trechos desse conteúdo para o LLM junto com a pergunta original
- Aí o LLM consegue responder à pergunta com base no conteúdo extra que você forneceu
- Esse truque barato funciona de forma surpreendentemente eficaz
- Mas não é fácil fazer funcionar bem nem mesmo a versão básica disso
- É preciso fazer com que funcione bem diante do conjunto infinito de perguntas que os usuários podem fazer
- O principal problema do RAG é descobrir quais são os melhores trechos de conteúdo para incluir no prompt enviado ao LLM
- A busca semântica baseada em "vibe", impulsionada por embeddings, é o recurso necessário para reunir conteúdo altamente relevante que possa ajudar a responder à pergunta do usuário
- Construí e publiquei uma versão disso para o "conteúdo do meu blog"
- Como resultado, ficou possível fazer RAG com um script Bash de uma linha
5 comentários
Vi este artigo e tentei no fim de semana. Cheguei a testar um modelo em coreano, mas como não foi fácil configurar o ambiente, usei o ada v2 e gastei no total US$ 0,03. Se for um usuário novo que ainda não usou o ChatGPT, dá para testar tranquilamente com os US$ 5 de crédito grátis haha.
Também calculei e comparei até a similaridade de cosseno, e os resultados fizeram sentido. Obrigado por compartilhar o texto.
Acho que vou tentar seguir isso no fim de semana.
Obrigado~
Acho que estou entendendo, nem que seja um pouco.
Obrigado.
Aprendi bastante sobre pontos que eu sempre tive curiosidade, mas não entendia bem. Como sempre, obrigado pelo ótimo conteúdo.