Encontrando o Ajuste Certo: Criação de Embeddings para Recuperação por IA (RAG) em Pipelines do Zilliz Cloud a partir de OSS, VoyageAI e OpenAI
Este post foi escrito por Christy Bergman e Jiang Chen.
Bem-vindo ao nosso post no blog sobre modelos de embedding adaptados para aplicações de IA de Geração Aumentada por Recuperação (RAG). Veja o que abordaremos:
Introdução a como os modelos de embedding são usados em RAG (IA Generativa com recuperação)
Introdução ao SBERT, o tipo mais comum de modelo de embedding
Leaderboard MTEB de modelos de embedding e como usá-lo
Seis modelos de embedding incluídos automaticamente no Zilliz Cloud Pipelines
Explicação de cada modelo e dicas sobre como selecionar o melhor modelo de embedding para suas necessidades
Vamos começar!
Adicione Seus Dados à IA Com RAG: Como Modelos de Embedding + LLMs São Usados
A Geração Aumentada por Recuperação (RAG) surgiu como a abordagem preferida para bots de perguntas e respostas. No entanto, dada a data limite de treinamento de conhecimento inerente a todos os modelos, eles podem não ter consciência de dados recentes. A maioria dos casos de uso em produção complementa seus modelos com conhecimento específico para preencher essa lacuna.
Suas respostas de IA estão presas no passado? Cansado de bots que só sabem aquilo em que foram treinados?
RAG apresenta uma solução ao integrar seus dados ao conhecimento da IA. Esse padrão usa modelos de embedding e Grandes Modelos de Linguagem (LLMs). Veja como funciona:
Preparação de dados usando um Modelo de Embedding: Inicie o RAG usando um modelo de embedding para gerar embeddings vetoriais de trechos de texto de TODOS os seus documentos. Isso se torna SEU espaço vetorial representando SEU conhecimento de domínio, com cada informação representada como um vetor.
Indexação e Busca usando o mesmo Modelo de Embedding: Computadores podem executar buscas vetoriais rapidamente quando seu conhecimento está codificado em vetores. Organizar os vetores em estruturas de dados para algoritmos de busca é chamado de Indexação. Índices são usados em Bancos de Dados Vetoriais como Milvus. Quando você faz uma pergunta, o banco de dados usará o índice para encontrar os vetores mais próximos (representando frases ou parágrafos) no seu espaço vetorial de conhecimento de domínio em relação ao vetor da sua pergunta. Crie o vetor da sua pergunta usando o mesmo modelo de embedding usado para incorporar seus dados.
Geração de resposta com um Modelo LLM: Esta é a parte de “IA Generativa”. Nesta etapa, um modelo LLM, como o ChatGPT, aproveita seu conhecimento de domínio relevante para responder à pergunta. Os dados RAG são fornecidos ao modelo LLM inserindo os textos top-K recuperados no prompt, que inclui sua pergunta, contexto (textos Top-K) e instruções como “Responda à pergunta usando apenas o conhecimento no contexto deste prompt”.
Com RAG, o LLM gera uma resposta com base no seu conhecimento de domínio fornecido, acessando instantaneamente os dados mais recentes e entendendo melhor suas perguntas.
Esse padrão RAG é apoiado por pesquisas; veja o artigo Lost in the Middle. O artigo mostra que a precisão de Recall das respostas geradas por LLMs diminui com o número de textos recuperados inseridos no prompt de Contexto do modelo. Além disso:
LLMs têm limites no tamanho do contexto (agora, é 128K para o GPT-4 Turbo).
Custo por token, então é mais caro passar todas as informações o tempo todo.
Modelos de Embedding Sentence-BERT
Modelos de embedding modernos são derivados da parte Encoder dos transformers; enquanto modelos LLM (como o ChatGPT) são construídos a partir da parte Decoder dos transformers. A classe mais comum de modelo de embedding é SBERT (Sentence-BERT), que se baseia no BERT, mas se especializa em entender frases completas. Portanto, o SBERT consegue diferenciar "The cat sat on the mat" de "The mat sat on the cat" - algo que o BERT básico não conseguiria!
Semântica refere-se ao significado por trás das palavras. Isso é particularmente importante no contexto dos LLMs porque as mesmas palavras podem ter significados diferentes com base no contexto, na ordem ou no uso. Para mais informações sobre SBERT, os leitores interessados devem ver estes bons artigos introdutórios sobre esse modelo aqui.
Suponha que você esteja programando aplicações RAG do zero. Um excelente ponto de partida é selecionar um modelo de embedding no HuggingFace MTEB Leaderboard, ordenado (decrescente) pela coluna "Retrieval Average'', pois ela é a mais relevante para RAG. Em seguida, escolha o menor modelo de embedding com a classificação mais alta. O leaderboard está mudando constantemente! Mas trocar o modelo de embedding com HuggingFace em Python é tão simples quanto ajustar uma única variável.
O desempenho de recuperação do MTEB é medido por Ganho Cumulativo Descontado Normalizado em 10 (NDCG@10). Essa métrica mede a qualidade das listas top-K calculando somas de razões em que itens com classificação mais alta recebem mais peso do que itens com classificação mais baixa, conforme retornados a um usuário em proporção a uma ordem ranqueada ideal.
Fonte da imagem: HuggingFace MTEB Leaderboard, acessado em 20 de fevereiro de 2024.
O Massive Text Embedding Benchmark (MTEB) avalia modelos de embedding em 8 tarefas e 58 conjuntos de dados (10 multilíngues, 112 idiomas). As oito tarefas são mineração de bitexto, classificação, clustering, classificação de pares, reranking, recuperação, similaridade textual semântica (STS) e sumarização.
6 Principais Modelos de Embedding Integrados aos Pipelines do Zilliz Cloud
O Zilliz Cloud Pipelines lançou recentemente suporte para um rico conjunto de opções de modelos de embedding.
| Criador | Modelo | Dim Embedding | Comprimento de Contexto | Tarefas de Caso de Uso | Open Source | *Pontuação MTEB |
| BAAI | bge-base-en-v1.5 | 768 | 512 | Texto geral EN | Sim | 53 |
| BAAI | bge-base-zh-v1.5 | 768 | 512 | Texto geral ZH | Sim | 69 |
| VoyageAI | voyage-2 | 1024 | 4K | Chatbots RAG de alta qualidade | Não | Não disponível |
| VoyageAI | voyage-code-2 | 1536 | 16K | Conclusão de código com alta taxa de recall | Não | Não disponível |
| OpenAI | text-embedding-3-small | 512-1536 | 8K | Chatbots de texto multilíngues em tempo real | Não | 62 (512) 62 (1536) |
| OpenAI | text-embedding-3-large | 256-3072 | 8K | Chatbots de texto multilíngues em tempo real | Não | 65 (3072) 62 (256) |
*HuggingFace MTEB Leaderboard, ordenado em ordem decrescente por Retrieval, acessado em 26 de fevereiro de 2024.
Dim Embedding = comprimento do vetor produzido por um modelo; vetores maiores podem capturar mais significado, mas podem ser menos eficientes em armazenamento.
Comprimento de Contexto = número máximo de tokens que o modelo pode processar de uma só vez em uma única etapa de tempo. Os vetores de saída da maioria dos modelos de embedding são normalizados, portanto produto escalar e similaridade de cosseno são iguais.
⚠️ Observação: Embora os benchmarks MTEB ofereçam orientações valiosas, sabe-se que alguns modelos sofrem overfitting! Sempre realize suas próprias avaliações!
Com Zilliz Cloud Pipelines, você pode começar gratuitamente cadastrando-se e criando sua aplicação RAG sem complicações de DevOps ou infraestrutura de ML.
Fonte da imagem: Blog anunciando modelos de embedding integrados ao Zilliz Cloud Pipelines
Modelos de embedding BAAI/bge-base-en(or zh)-v1.5
Esses modelos SBERT de código aberto estão disponíveis no HuggingFace. Algumas vantagens desses modelos pequenos:
Pequenos, de código aberto e adequados para CPU.
É uma boa escolha para trabalhar em um laptop ou/ou recursos de nuvem mínimos.
Mais rápidos para ingestão ao fragmentar dados e para latência de consulta sempre que uma pergunta é feita.
Econômicos, já que as chamadas de API são gratuitas e GPU não é necessária.
Treinados nos idiomas chinês e inglês.
| Criador | Modelo | Dim****Embedding | Tamanho do Contexto | Tarefas de Caso de Uso | Código Aberto | *Pontuação MTEB |
| BAAI | bge-base-en-v1.5 | 768 | 512 | Texto EN geral | Sim | 53 |
| BAAI | bge-base-zh-v1.5 | 768 | 512 | Texto ZH geral | Sim | 69 |
*HuggingFace MTEB Leaderboard, ordenado em ordem decrescente por Retrieval, acessado em 26 de fev. de 2024.
Modelos de embedding voyage-2 e voyage-code-2 da VoyageAI
Esses modelos proprietários são treinados usando aprendizado contrastivo e reamostragem por importância em diferentes dados e ajustados para diferentes tarefas. Voyage-2 é treinado em dados de diálogo e ajustado para intenção conversacional. Voyage-code-2 é treinado em dados de código e ajustado para conclusão de código.
Observação: Voyage-lite-02-instruct listado no leaderboard MTEB (ordenado em ordem decrescente por STS ou categoria “corpora diversos”) é diferente e não deve ser confundido com os modelos de produção voyage-2 e voyage-code-2 descritos aqui.
Algumas vantagens desses modelos:
Para chatbots RAG de documentação técnica, voyage-01 (descontinuado) demonstrou ter maior qualidade de recuperação (medida como NDCG@10). Voyage-2 é a versão mais recente.
Para tarefas de código, voyage-code-2 tem uma taxa de recall 14% maior para texto intensivo em código.
| Criador | Modelo | Dim****Embedding | Tamanho do Contexto | Tarefas de Caso de Uso | Código Aberto | Pontuação MTEB |
| VoyageAI | voyage-2 | 1024 | 4K | Chatbots RAG de alta qualidade | Não | Não disponível |
| VoyageAI | voyage-code-2 | 1536 | 16K | Conclusão de código com alta taxa de recall | Não | Não disponível |
Modelos de embedding text-embedding-3-small(or large) da OpenAI
Da OpenAI, os modelos de embedding mais recentes têm classificação mais alta no ranking MTEB do que o ada-002 anterior. Esses novos modelos de embedding também têm desempenho multilíngue superior (MIRACL) e preços mais baixos.
De acordo com o blog da OpenAI, o treinamento consciente de compressão foi usado para criar os embeddings. Técnicas tradicionais de redução de dimensionalidade, como quantização, economizam espaço, mas com uma enorme perda de precisão porque a compressão é aplicada “post-hoc” depois que os embeddings foram aprendidos. O treinamento consciente de compressão, como Matryoshka Representation Learning, aprende embeddings em diferentes tamanhos (dimensões), com alguma perda de precisão, embora não tão significativa quanto com PCA.
De forma impressionante, ambos os modelos suportam embeddings menores sem sacrificar muito a qualidade da recuperação. Por exemplo, reduzir a dimensão do vetor de 3072 para 256 reduz a pontuação MTEB apenas de 65% para 62%. No entanto, isso representa uma exigência de memória 12 vezes menor! Embora exista uma relação de troca entre precisão e custo associada à menor dimensionalidade, na era dos Chatbots impulsionados por IA, respostas rápidas às vezes são priorizadas em relação à precisão da resposta.
Algumas vantagens desses modelos:
Capacidades multilíngues aprimoradas.
Vetores de menor dimensão com a menor sobrecarga de inferência e muito menos perda de precisão do que a quantização binária ou por produto tradicional.
| Criador | Modelo | Dim****Embedding | Comprimento do contexto | Tarefas de caso de uso | Open Source | *Pontuação MTEB |
| OpenAI | text-embedding-3-small | 512-1536 | 8K | Chatbots de texto multilíngues em tempo real | Não | 62 (512) 62 (1536) |
| OpenAI | text-embedding-3-large | 256-3072 | 8K | Chatbots de texto multilíngues em tempo real | Não | 65 (3072) 62 (256) |
*Ranking MTEB da HuggingFace, ordenado em ordem decrescente por Retrieval, acessado em 26 de fevereiro de 2024.
Abaixo está um exemplo de código para chamar os novos modelos de embedding. O código completo está localizado em nosso github do bootcamp.
# STEP 1. CONNECT TO MILVUS
# !pip install pymilvus
from pymilvus import connections, utility
from dotenv import load_dotenv
load_dotenv()
TOKEN = os.getenv("ZILLIZ_API_KEY")
# Connect to Zilliz cloud using endpoint URI and API key TOKEN.
CLUSTER_ENDPOINT="https://in03-xxxx.api.gcp-us-west1.zillizcloud.com:443"
connections.connect(
alias='default',
uri=CLUSTER_ENDPOINT,
token=TOKEN,
)
Em seguida, especificamos o modelo de embedding da OpenAI.
# STEP 2. EMBEDDING MODEL.
import openai, pprint
from openai import OpenAI
# OpenAI embedding model name, `text-embedding-3-large` or `ext-embedding-3-small`.
EMBEDDING_MODEL = "text-embedding-3-small"
EMBEDDING_DIM = 512
Em seguida, criamos uma coleção Milvus sem esquema e especificamos um índice.
# STEP 3. CREATE A NO-SCHEMA MILVUS COLLECTION AND USE AUTOINDEX.
from pymilvus import MilvusClient
COLLECTION_NAME = "MilvusDocs_text_embedding_3_small"
# https://milvus.io/docs/using_milvusclient.md
mc = MilvusClient(
uri=CLUSTER_ENDPOINT,
token=TOKEN)
# Check if collection already exists, if so drop it.
has = utility.has_collection(COLLECTION_NAME)
if has:
drop_result = utility.drop_collection(COLLECTION_NAME)
print(f"Successfully dropped collection: `{COLLECTION_NAME}`")
# Crie a coleção.
mc.create_collection(COLLECTION_NAME,
EMBEDDING_DIM,
consistency_level="Eventually",
auto_id=True,
overwrite=True)
Em seguida, lemos a documentação técnica do LangChain como arquivos .html baixados em uma pasta. Divida e incorpore os documentos. O exemplo abaixo usa o parser HTML integrado do LangChain como estratégia de divisão. Sua estratégia de divisão poderia ser muito mais simples.
# STEP 4. PREPARE DATA: CHUNK AND EMBED
# Leia os documentos no LangChain.
from langchain.document_loaders import DirectoryLoader
path = "../RAG/rtdocs/pymilvus.readthedocs.io/en/latest/"
loader = DirectoryLoader(path, glob='*.html')
docs = loader.load()
from langchain.text_splitter import HTMLHeaderTextSplitter, RecursiveCharacterTextSplitter
from bs4 import BeautifulSoup
# Defina os cabeçalhos nos quais dividir para o HTMLHeaderTextSplitter
headers_to_split_on = [
("h1", "Header 1"),
("h2", "Header 2"),
]
# Crie uma instância do HTMLHeaderTextSplitter
html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
# Especifique o tamanho do chunk e a sobreposição.
chunk_size = 511
chunk_overlap = np.round(chunk_size * 0.10, 0)
print(f"chunk_size: {chunk_size}, chunk_overlap: {chunk_overlap}")
# Crie uma instância do RecursiveCharacterTextSplitter
child_splitter = RecursiveCharacterTextSplitter(
chunk_size = chunk_size,
chunk_overlap = chunk_overlap,
length_function = len,
)
# Divida o texto HTML usando o HTMLHeaderTextSplitter.
start_time = time.time()
html_header_splits = []
for doc in docs:
soup = BeautifulSoup(doc.page_content, 'html.parser')
splits = html_splitter.split_text(str(soup))
for split in splits:
# Adicione a URL de origem e os valores de cabeçalho aos metadados
metadata = {}
new_text = split.page_content
for header_name, metadata_header_name in headers_to_split_on:
# Trate exceções se h1 não existir.
try:
header_value = new_text.split("¶ ")[0].strip()[:100]
metadata[header_name] = header_value
except:
break
split.metadata = {
**metadata,
"source": doc.metadata["source"]
}
# Adicione o cabeçalho ao texto
split.page_content = split.page_content
html_header_splits.extend(splits)
# Divida os documentos ainda mais em chunks recursivos menores.
chunks = child_splitter.split_documents(html_header_splits)
Insira os chunks e embeddings no Milvus.
# STEP 5. INSERT CHUNKS AND EMBEDDINGS IN ZILLIZ.
# Converta os chunks em uma lista de dicionários.
chunk_list = []
for chunk in chunks:
# Gere os embeddings.
response = openai_client.embeddings.create(
input=chunk.page_content,
model=EMBEDDING_MODEL,
dimensions=EMBEDDING_DIM
)
embeddings = response.data[0].embedding
# Monte o vetor de embedding, o chunk de texto original, os metadados.
chunk_dict = {
'vector': embeddings,
'chunk': chunk.page_content,
'source': chunk.metadata['source'],
'h1': chunk.metadata['h1'][:50],
}
chunk_list.append(chunk_dict)
# Insira os dados na coleção Milvus.
insert_result = mc.insert(
COLLECTION_NAME,
data=chunk_list,
progress_bar=True)
# Depois que a entidade final for inserida, chame flush para interromper segmentos em crescimento deixados na memória.
mc.flush(COLLECTION_NAME)
Faça uma Pergunta ao Milvus, que agora está carregado com embeddings da documentação técnica do Milvus.
# Defina uma pergunta de exemplo sobre seus dados.
SAMPLE_QUESTION = "O que significam os parâmetros para HNSW?"
# Incorpore a pergunta usando o mesmo codificador.
response = openai_client.embeddings.create(
input=SAMPLE_QUESTION,
model=EMBEDDING_MODEL,
dimensions=EMBEDDING_DIM
)
query_embeddings = response.data[0].embedding
# Defina os campos de saída a retornar.
OUTPUT_FIELDS = ["h1", "h2", "source", "chunk"]
# Execute a busca vetorial semântica usando sua consulta e o banco de dados vetorial Milvus.
start_time = time.time()
results = mc.search(
COLLECTION_NAME,
data=[query_embeddings],
output_fields=OUTPUT_FIELDS,
limit=2,
consistency_level="Eventually"
)
Gere uma resposta usando o ChatGPT e os trechos de contexto de texto recuperados.
LLM_NAME = "gpt-3.5-turbo"
TEMPERATURE = 0.1
RANDOM_SEED = 415
# Separate all the context together by space.
contexts_combined = ' '.join(context)
SYSTEM_PROMPT = f"""Use the Context below to answer the user's question. Be clear, factual, complete, concise.
If the answer is not in the Context, say "I don't know".
Otherwise answer with fewer than 4 sentences and cite the grounding sources.
Context: contexts_combined
Answer: The answer to the question.
Grounding sources: {context_metadata[0]['source']}
"""
# Generate response using the OpenAI API.
response = openai_client.chat.completions.create(
messages=[
{"role": "system", "content": SYSTEM_PROMPT,},
{"role": "user", "content": f"question: {SAMPLE_QUESTION}",}
],
model=LLM_NAME,
temperature=TEMPERATURE,
seed=RANDOM_SEED,
)
# Print the question and answer along with grounding sources and citations.
print(f"Question: {SAMPLE_QUESTION}")
for i, choice in enumerate(response.choices, 1):
pprint.pprint(f"Answer: {choice.message.content}")
print("\n")
A resposta usando text-embedding-3-small com embeddings reduzidos dim=256 é perfeita em comparação com a mesma resposta com dim=1536, pelo menos para este exemplo de RAG!
Conclusão
Neste blog, apresentamos como os modelos de embedding são usados em RAG e SBERT, o tipo mais comum de modelo de embedding. Mostramos o ranking MTEB de modelos de embedding e explicamos como usá-lo. Em seguida, passamos pelos seis diferentes modelos de embedding incluídos automaticamente no Zilliz Pipelines. Diferentes modelos de embedding são melhores para diferentes casos de uso; discutimos quando escolher cada modelo. Por fim, mostramos o código para chamar os novos modelos de embedding da OpenAI; e o código completo está localizado em nosso bootcamp github.
Referências
Milvus (dê-nos uma estrela!)
Tutorial sobre partes Encoder-Decoder dos transformers
Tutorial sobre modelos de embedding SBERT Encoder
Ranking MTEB da HuggingFace de modelos de embedding
Card do modelo HuggingFace para BAAI/bg-large-en-v1.5
Modelos de embedding da VoyageAI
Modelos de embedding da OpenAI
Continue lendo
Stop Building AI Data Infra for the Wrong Stage
Learn how AI data infrastructure should evolve from prototype to enterprise scale, and when Vector Lakebase becomes the right architecture for AI apps.

Smarter Autoscaling in Zilliz Cloud: Always Optimized for Every Workload
With the latest upgrade, Zilliz Cloud introduces smarter autoscaling—a fully automated, more streamlined, elastic resource management system.

Zilliz Cloud Introduces Advanced BYOC-I Solution for Ultimate Enterprise Data Sovereignty
Explore Zilliz Cloud BYOC-I, the solution that balances AI innovation with data control, enabling secure deployments in finance, healthcare, and education sectors.



