Encontrar el ajuste adecuado: Creación de embeddings para la recuperación con IA (RAG) en Zilliz Cloud Pipelines desde OSS, VoyageAI y OpenAI
Esta publicación está escrita por Christy Bergman y Jiang Chen.
Bienvenido a nuestra publicación de blog sobre modelos de embeddings adaptados a aplicaciones de IA de Retrieval Augmented Generation (RAG). Esto es lo que cubriremos:
Introducción a cómo se utilizan los modelos de embeddings en RAG (IA generativa con recuperación)
Introducción a SBERT, el tipo más común de modelo de embeddings
Tabla de clasificación MTEB de modelos de embeddings y cómo usarla
Seis modelos de embeddings incluidos automáticamente en Zilliz Cloud Pipelines
Explicación de cada modelo y consejos para seleccionar el mejor modelo de embeddings para tus necesidades
¡Vamos a ello!
Añade tus datos a la IA con Rag: cómo se utilizan los modelos de embeddings + LLMs
Retrieval Augmented Generation (RAG) se ha convertido en el enfoque de referencia para los bots de preguntas y respuestas. Sin embargo, dada la fecha límite de entrenamiento de conocimiento inherente a todos los modelos, pueden carecer de conocimiento sobre datos recientes. La mayoría de los casos de uso en producción complementan sus modelos con conocimiento específico para cerrar esta brecha.
¿Tus respuestas de IA están atrapadas en el pasado? ¿Cansado de bots que solo saben aquello con lo que fueron entrenados?
RAG presenta una solución al integrar tus datos en el conocimiento de la IA. Este patrón utiliza modelos de embeddings y Large Language Models (LLMs). Así es como funciona:
Preparación de datos usando un modelo de embeddings: Inicia RAG utilizando un modelo de embeddings para generar vector embeddings de fragmentos de texto de TODOS tus documentos. Esto se convierte en TU espacio vectorial que representa TU conocimiento de dominio, con cada pieza de información representada como un vector.
Indexación y búsqueda usando el mismo modelo de embeddings: Las computadoras pueden ejecutar búsquedas vectoriales rápidamente una vez que tu conocimiento está codificado en vectores. Organizar los vectores en estructuras de datos para algoritmos de búsqueda se llama indexación. Los índices se utilizan en bases de datos vectoriales como Milvus. Cuando haces una pregunta, la base de datos usará el índice para encontrar los vectores más cercanos (que representan oraciones o párrafos) en el espacio vectorial de conocimiento de tu dominio a tu vector de pregunta. Crea tu vector de pregunta usando el mismo modelo de embeddings utilizado para incrustar tus datos.
Generación de respuestas con un modelo LLM: Esta es la parte de “IA generativa”. En este paso, un modelo LLM, como ChatGPT, aprovecha tu conocimiento de dominio relevante para responder la pregunta. Los datos RAG se proporcionan al modelo LLM inyectando los textos recuperados top-K en el prompt, que incluye tu pregunta, contexto (textos Top-K) e instrucciones como “Responde la pregunta usando solo el conocimiento en el contexto de este prompt”.
Con RAG, el LLM genera una respuesta basada en tu conocimiento de dominio proporcionado, accediendo instantáneamente a los datos más recientes y comprendiendo mejor tus preguntas.
Este patrón RAG está respaldado por la investigación; consulta el artículo Lost in the Middle. El artículo muestra que la precisión de Recall de las respuestas generadas por LLMs disminuye con la cantidad de textos recuperados insertados en el prompt de contexto del modelo. Además:
Los LLMs tienen límites en el tamaño del contexto (ahora mismo, es 128K para GPT-4 Turbo).
Coste por token, por lo que es más caro pasar toda la información todo el tiempo.
Modelos de embeddings Sentence-BERT
Los modelos de embeddings modernos se derivan de la parte del codificador de los transformers; mientras que los modelos LLM (como ChatGPT) se construyen a partir de la parte del decodificador de los transformers. La clase más común de modelo de embeddings es SBERT (Sentence-BERT), que se basa en BERT pero se especializa en comprender oraciones completas. Así, SBERT puede notar la diferencia entre "The cat sat on the mat" y "The mat sat on the cat" - ¡algo que BERT básico no podría!
Semántica se refiere al significado detrás de las palabras. Esto es particularmente importante en el contexto de los LLM porque las mismas palabras pueden tener diferentes significados según el contexto, el orden o el uso. Para obtener más información sobre SBERT, los lectores interesados deberían consultar estos buenos artículos introductorios sobre ese modelo aquí.
Supón que estás programando aplicaciones RAG desde cero. Un excelente punto de partida es seleccionar un modelo de embeddings de la HuggingFace MTEB Leaderboard, ordenada (descendentemente) por la columna "Retrieval Average'', ya que es la más relevante para RAG. Luego, elige el modelo de embeddings más pequeño y mejor clasificado. ¡La tabla de clasificación cambia constantemente! Pero cambiar el modelo de embeddings con HuggingFace en Python es tan simple como ajustar una sola variable.
El rendimiento de recuperación de MTEB se mide mediante la ganancia acumulada descontada normalizada en 10 (NDCG@10). Esta métrica mide la calidad de las listas top-K calculando sumas de proporciones en las que los elementos con posiciones más altas reciben más peso que los elementos con posiciones más bajas, tal como se devuelven a un usuario en proporción a un orden clasificado ideal.
Fuente de la imagen: HuggingFace MTEB Leaderboard, consultada el 20 de febrero de 2024.
Massive Text Embedding Benchmark (MTEB) evalúa modelos de embeddings en 8 tareas y 58 conjuntos de datos (10 multilingües, 112 idiomas). Las ocho tareas son minería bitextual, clasificación, agrupamiento, clasificación por pares, reordenamiento, recuperación, similitud textual semántica (STS) y resumen.
6 modelos de embeddings clave integrados en Zilliz Cloud Pipelines
Zilliz Cloud Pipelines lanzó recientemente soporte para un amplio conjunto de opciones de modelos de embeddings.
| Creador | Modelo | Dim. de embedding | Longitud de contexto | Tareas de caso de uso | Código abierto | *Puntuación MTEB |
| BAAI | bge-base-en-v1.5 | 768 | 512 | Texto EN general | Sí | 53 |
| BAAI | bge-base-zh-v1.5 | 768 | 512 | Texto ZH general | Sí | 69 |
| VoyageAI | voyage-2 | 1024 | 4K | Chatbots RAG de alta calidad | No | No disponible |
| VoyageAI | voyage-code-2 | 1536 | 16K | Finalización de código con alta tasa de recuperación | No | No disponible |
| OpenAI | text-embedding-3-small | 512-1536 | 8K | Chatbots de texto multilingües en tiempo real | No | 62 (512) 62 (1536) |
| OpenAI | text-embedding-3-large | 256-3072 | 8K | Chatbots de texto multilingües en tiempo real | No | 65 (3072) 62 (256) |
*HuggingFace MTEB Leaderboard, ordenada descendentemente por Retrieval, consultada el 26 de febrero de 2024.
Dim. de embedding = longitud del vector producido por un modelo; los vectores más grandes podrían capturar más significado, pero pueden ser menos eficientes en almacenamiento.
Longitud de contexto = número máximo de tokens que el modelo puede procesar a la vez en un único paso temporal. Los vectores de salida de la mayoría de los modelos de embeddings están normalizados, por lo que el producto punto y la similitud coseno son iguales.
⚠️ Nota: Aunque los benchmarks MTEB ofrecen una guía valiosa, ¡se sabe que algunos modelos están sobreajustados! ¡Realiza siempre tus propias evaluaciones!
Con Zilliz Cloud Pipelines, puedes empezar gratis registrándote y creando tu aplicación RAG sin complicaciones de DevOps ni de infraestructura de ML.
Fuente de la imagen: Blog que anuncia los modelos de embedding integrados en Zilliz Cloud Pipelines
Modelos de embedding BAAI/bge-base-en(or zh)-v1.5
Estos modelos SBERT de código abierto están disponibles en HuggingFace. Algunas ventajas de estos modelos pequeños:
Pequeños, de código abierto y aptos para CPU.
Es una buena opción para trabajar en una laptop o/o con recursos mínimos en la nube.
Los más rápidos para la ingesta al fragmentar datos y para la latencia de consulta cada vez que se hace una pregunta.
Rentables, ya que las llamadas a la API son gratuitas y no se requiere GPU.
Entrenados en los idiomas chino e inglés.
| Creador | Modelo | Dim****Embedding | Longitud de contexto | Tareas de caso de uso | Código abierto | *Puntuación MTEB |
| BAAI | bge-base-en-v1.5 | 768 | 512 | Texto EN general | Sí | 53 |
| BAAI | bge-base-zh-v1.5 | 768 | 512 | Texto ZH general | Sí | 69 |
*HuggingFace MTEB Leaderboard, ordenado de forma descendente por Retrieval, consultado el 26 de febrero de 2024.
Modelos de embedding voyage-2 y voyage-code-2 de VoyageAI
Estos modelos propietarios se entrenan mediante aprendizaje contrastivo y remuestreo por importancia con distintos datos y se ajustan finamente para distintas tareas. Voyage-2 está entrenado con datos de diálogo y ajustado finamente para la intención conversacional. Voyage-code-2 está entrenado con datos de código y ajustado finamente para la finalización de código.
Nota: Voyage-lite-02-instruct, que figura en el leaderboard MTEB (ordenado de forma descendente por STS o categoría “corpora diversos”), es diferente y no debe confundirse con los modelos de producción voyage-2 y voyage-code-2 descritos aquí.
Algunas ventajas de estos modelos:
Para chatbots RAG de documentación técnica, se demostró que voyage-01 (obsoleto) tenía mayor calidad de recuperación (medida como NDCG@10). Voyage-2 es la versión más reciente.
Para tareas de código, voyage-code-2 tiene una tasa de recall un 14% mayor para texto intensivo en código.
| Creador | Modelo | Dim****Embedding | Longitud de contexto | Tareas de caso de uso | Código abierto | Puntuación MTEB |
| VoyageAI | voyage-2 | 1024 | 4K | Chatbots RAG de alta calidad | No | No disponible |
| VoyageAI | voyage-code-2 | 1536 | 16K | Finalización de código con alta tasa de recall | No | No disponible |
Modelos de embedding text-embedding-3-small(or large) de OpenAI
De OpenAI, los modelos de embedding más recientes ocupan puestos más altos en la clasificación MTEB que su anterior ada-002. Estos nuevos modelos de embedding también tienen un mayor rendimiento multilingüe (MIRACL) y precios más bajos.
Según el blog de OpenAI, se utilizó entrenamiento consciente de la compresión para crear los embeddings. Las técnicas tradicionales de reducción de dimensionalidad, como la cuantización, ahorran espacio, pero con una enorme pérdida de precisión porque la compresión se aplica “post-hoc” después de que se aprendieron los embeddings. El entrenamiento consciente de la compresión, como Matryoshka Representation Learning, aprende embeddings de diferentes tamaños (dimensiones), con cierta pérdida de precisión, aunque no tan significativa como con PCA.
De manera impresionante, ambos modelos admiten embeddings más pequeños sin sacrificar mucho la calidad de recuperación. Por ejemplo, reducir la dimensión del vector de 3072 a 256 solo reduce la puntuación MTEB del 65% al 62%. Sin embargo, ¡eso supone un requisito de memoria 12 veces menor! Aunque existe un equilibrio entre precisión y coste asociado con una menor dimensionalidad, en la era de los chatbots impulsados por IA, a veces se priorizan las respuestas rápidas por encima de la precisión de las respuestas.
Algunas ventajas de estos modelos:
Capacidades multilingües mejoradas.
Vectores de menor dimensión con la menor sobrecarga de inferencia y mucha menos pérdida de precisión que la cuantización binaria o de producto tradicional.
| Creador | Modelo | Dim.****Embedding | Longitud de contexto | Tareas de caso de uso | Código abierto | *Puntuación MTEB |
| OpenAI | text-embedding-3-small | 512-1536 | 8K | Chatbots de texto multilingües en tiempo real | No | 62 (512) 62 (1536) |
| OpenAI | text-embedding-3-large | 256-3072 | 8K | Chatbots de texto multilingües en tiempo real | No | 65 (3072) 62 (256) |
*Clasificación MTEB de HuggingFace, ordenada de forma descendente por Retrieval, consultada el 26 de febrero de 2024.
A continuación se muestra un ejemplo de código para llamar a los nuevos modelos de embedding. El código completo se encuentra en nuestro github del 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,
)
A continuación, especificamos el modelo de embedding de 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
A continuación, creamos una colección Milvus sin esquema y especificamos un í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}`")
# Crea la colección.
mc.create_collection(COLLECTION_NAME,
EMBEDDING_DIM,
consistency_level="Eventually",
auto_id=True,
overwrite=True)
A continuación, leemos la documentación técnica de LangChain como archivos .html descargados en una carpeta. Fragmentamos e incrustamos la documentación. El ejemplo a continuación utiliza el analizador HTML integrado de LangChain como estrategia de fragmentación. Tu estrategia de fragmentación podría ser mucho más simple.
# STEP 4. PREPARE DATA: CHUNK AND EMBED
# Read docs into 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
# Define the headers to split on for the HTMLHeaderTextSplitter
headers_to_split_on = [
("h1", "Header 1"),
("h2", "Header 2"),
]
# Create an instance of the HTMLHeaderTextSplitter
html_splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
# Specify chunk size and overlap.
chunk_size = 511
chunk_overlap = np.round(chunk_size * 0.10, 0)
print(f"chunk_size: {chunk_size}, chunk_overlap: {chunk_overlap}")
# Create an instance of the RecursiveCharacterTextSplitter
child_splitter = RecursiveCharacterTextSplitter(
chunk_size = chunk_size,
chunk_overlap = chunk_overlap,
length_function = len,
)
# Split the HTML text using the 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:
# Add the source URL and header values to the metadata
metadata = {}
new_text = split.page_content
for header_name, metadata_header_name in headers_to_split_on:
# Handle exceptions if h1 does not exist.
try:
header_value = new_text.split("¶ ")[0].strip()[:100]
metadata[header_name] = header_value
except:
break
split.metadata = {
**metadata,
"source": doc.metadata["source"]
}
# Add the header to the text
split.page_content = split.page_content
html_header_splits.extend(splits)
# Split the documents further into smaller, recursive chunks.
chunks = child_splitter.split_documents(html_header_splits)
Inserta los fragmentos y las incrustaciones en Milvus.
# STEP 5. INSERT CHUNKS AND EMBEDDINGS IN ZILLIZ.
# Convert chunks to a list of dictionaries.
chunk_list = []
for chunk in chunks:
# Generate the embeddings.
response = openai_client.embeddings.create(
input=chunk.page_content,
model=EMBEDDING_MODEL,
dimensions=EMBEDDING_DIM
)
embeddings = response.data[0].embedding
# Assemble embedding vector, original text chunk, metadata.
chunk_dict = {
'vector': embeddings,
'chunk': chunk.page_content,
'source': chunk.metadata['source'],
'h1': chunk.metadata['h1'][:50],
}
chunk_list.append(chunk_dict)
# Insert data into the Milvus collection.
insert_result = mc.insert(
COLLECTION_NAME,
data=chunk_list,
progress_bar=True)
# After the final entity is inserted, call flush to stop growing segments left in memory.
mc.flush(COLLECTION_NAME)
Haz una pregunta a Milvus, que ahora está cargado con incrustaciones de documentación técnica de Milvus.
# Define a sample question about your data.
SAMPLE_QUESTION = "What do the parameters for HNSW mean?"
# Embed the question using the same encoder.
response = openai_client.embeddings.create(
input=SAMPLE_QUESTION,
model=EMBEDDING_MODEL,
dimensions=EMBEDDING_DIM
)
query_embeddings = response.data[0].embedding
# Define output fields to return.
OUTPUT_FIELDS = ["h1", "h2", "source", "chunk"]
# Ejecuta una búsqueda vectorial semántica usando tu consulta y la base de datos vectorial Milvus.
start_time = time.time()
results = mc.search(
COLLECTION_NAME,
data=[query_embeddings],
output_fields=OUTPUT_FIELDS,
limit=2,
consistency_level="Eventually"
)
Genera una respuesta usando ChatGPT y los fragmentos 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")
¡La respuesta usando text-embedding-3-small con embeddings reducidos dim=256 es perfecta en comparación con la misma respuesta con dim=1536, al menos para este ejemplo de RAG!
Conclusión
En este blog, presentamos cómo se usan los modelos de embedding en RAG y SBERT, el tipo más común de modelo de embedding. Mostramos la clasificación MTEB de modelos de embedding y explicamos cómo usarla. Luego, repasamos los seis modelos de embedding diferentes incluidos automáticamente en Zilliz Pipelines. Los diferentes modelos de embedding son mejores para distintos casos de uso; analizamos cuándo elegir cada modelo. Finalmente, mostramos código para llamar a los nuevos modelos de embedding de OpenAI; y el código completo se encuentra en nuestro bootcamp github.
Referencias
Milvus (¡danos una estrella!)
Tutorial sobre las partes Encoder-Decoder de los transformers
Tutorial sobre modelos de embedding SBERT Encoder
HuggingFace MTEB Leaderboard de modelos de embedding
Tarjeta de modelo de HuggingFace para BAAI/bg-large-en-v1.5
Modelos de embedding de VoyageAI
Modelos de embedding de OpenAI
Sigue leyendo

A Few Notes from Databricks Data + AI Summit 2026: Why the Data Layer Matters Again
James Luan shares notes from Databricks Data + AI Summit 2026 on why production AI is pushing the data layer back to the center of infrastructure.

Context Engineering Strategies for AI Agents: A Developer’s Guide
Learn practical context engineering strategies for AI agents. Explore frameworks, tools, and techniques to improve reliability, efficiency, and cost.

VidTok: Rethinking Video Processing with Compact Tokenization
VidTok tokenizes videos to reduce redundancy while preserving spatial and temporal details for efficient processing.



