Qué son los embeddings y sus fundamentos
Los embeddings son representaciones numéricas de texto que capturan el significado semántico de las palabras, frases o documentos completos. En lugar de trabajar con texto plano, los embeddings convierten el lenguaje natural en vectores de números decimales que las máquinas pueden procesar y comparar matemáticamente.
Un embedding es esencialmente una lista de números decimales (vector) donde cada posición representa una característica semántica del texto original. Por ejemplo, el texto "El gato duerme en el sofá" se convierte en un vector como [-0.006929, -0.005336, 0.000045, -0.024047, ...]
con cientos o miles de dimensiones.
Fundamentos matemáticos de los embeddings
La característica fundamental de los embeddings es que la distancia matemática entre vectores refleja la similitud semántica entre los textos originales. Dos conceptos relacionados tendrán embeddings con distancias pequeñas, mientras que conceptos no relacionados tendrán distancias grandes.
# Ejemplo conceptual de distancias entre embeddings
embedding_gato = [-0.1, 0.3, 0.8, -0.2]
embedding_perro = [-0.2, 0.4, 0.7, -0.1] # Similar a gato
embedding_coche = [0.9, -0.5, 0.1, 0.6] # Muy diferente
# La distancia entre gato y perro será menor que entre gato y coche
Esta propiedad permite realizar operaciones semánticas como encontrar textos similares, agrupar contenido relacionado o medir la relevancia de un documento respecto a una consulta.
Dimensionalidad y representación
Los embeddings modernos utilizan espacios vectoriales de alta dimensionalidad para capturar matices semánticos complejos. Los modelos de OpenAI generan embeddings con las siguientes características:
- text-embedding-3-small: 1536 dimensiones por defecto
- text-embedding-3-large: 3072 dimensiones por defecto
- Capacidad de reducción: Ambos modelos permiten especificar menos dimensiones sin perder propiedades semánticas significativas
# Estructura típica de un embedding
embedding_ejemplo = [
-0.006929283495992422,
-0.005336422007530928,
-4.547132266452536e-05,
-0.024047505110502243,
# ... continúa hasta 1536 o 3072 valores
]
Propiedades semánticas fundamentales
Los embeddings capturan relaciones semánticas complejas que van más allá de la coincidencia de palabras exactas. Estas propiedades incluyen:
Similitud conceptual: Palabras con significados relacionados tienen embeddings próximos, incluso si no comparten caracteres comunes. "Automóvil" y "vehículo" tendrán embeddings similares.
Contexto semántico: Los embeddings consideran el contexto completo del texto, no solo palabras individuales. "Banco" tendrá diferentes representaciones según se refiera a una institución financiera o a un asiento.
Invariancia lingüística: Los modelos modernos mantienen relaciones semánticas consistentes entre diferentes idiomas, permitiendo búsquedas y comparaciones multilingües.
Casos de uso fundamentales
Los embeddings habilitan múltiples aplicaciones prácticas en el procesamiento de lenguaje natural:
- Búsqueda semántica: Encontrar documentos relevantes basándose en el significado, no solo en palabras clave exactas
- Agrupación de contenido: Clasificar automáticamente textos por temas o categorías similares
- Sistemas de recomendación: Sugerir contenido relacionado basándose en similitudes semánticas
- Detección de anomalías: Identificar textos que se desvían significativamente del patrón esperado
- Análisis de sentimientos: Clasificar textos según su tono emocional o intención
Esto permite recuperar información relevante y añadirla en los prompts que enviamos a los LLM:
Ventajas sobre métodos tradicionales
Los embeddings superan las limitaciones de los enfoques clásicos de procesamiento de texto:
Más allá de palabras clave: Mientras que los métodos tradicionales dependen de coincidencias exactas de términos, los embeddings capturan significados implícitos y sinónimos.
Comprensión contextual: Los embeddings consideran el contexto completo, resolviendo ambigüedades que los métodos basados en palabras individuales no pueden manejar.
Escalabilidad: Una vez generados, los embeddings permiten comparaciones rápidas entre miles o millones de documentos mediante operaciones vectoriales optimizadas.
Flexibilidad multidominio: Los mismos embeddings funcionan efectivamente en diferentes dominios y tipos de contenido sin requerir configuraciones específicas.
Esta representación vectorial del lenguaje forma la base tecnológica para sistemas RAG avanzados, donde la capacidad de encontrar información semánticamente relevante es crucial para generar respuestas precisas y contextualmente apropiadas.
Embeddings API de OpenAI
Guarda tu progreso
Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.
Más de 25.000 desarrolladores ya confían en CertiDevs
La API de Embeddings de OpenAI proporciona acceso directo a los modelos de embeddings más avanzados disponibles comercialmente. Esta API permite convertir cualquier texto en representaciones vectoriales de alta calidad mediante una interfaz simple y eficiente.
Modelos disponibles
OpenAI ofrece dos modelos principales de tercera generación optimizados para diferentes necesidades:
text-embedding-3-small:
- 1536 dimensiones por defecto
- Costo optimizado para aplicaciones de gran volumen
- Rendimiento equilibrado para la mayoría de casos de uso
- Máximo 8192 tokens de entrada
text-embedding-3-large:
- 3072 dimensiones por defecto
- Máximo rendimiento en tareas complejas
- Superior precisión en búsquedas semánticas avanzadas
- Máximo 8192 tokens de entrada
from openai import OpenAI
client = OpenAI()
# Usando el modelo pequeño para casos generales
response_small = client.embeddings.create(
input="Análisis de sentimientos en redes sociales",
model="text-embedding-3-small"
)
# Usando el modelo grande para máxima precisión
response_large = client.embeddings.create(
input="Análisis de sentimientos en redes sociales",
model="text-embedding-3-large"
)
Estructura de la respuesta
La API devuelve una estructura JSON que contiene el vector de embedding junto con metadatos útiles para el procesamiento:
response = client.embeddings.create(
input="Ejemplo de texto para embedding",
model="text-embedding-3-small"
)
# Estructura de la respuesta
print(f"Modelo utilizado: {response.model}")
print(f"Tokens procesados: {response.usage.total_tokens}")
print(f"Dimensiones del vector: {len(response.data[0].embedding)}")
# Acceso al vector de embedding
embedding_vector = response.data[0].embedding
print(f"Primeros 5 valores: {embedding_vector[:5]}")
Ejemplo de uso:
Procesamiento de múltiples textos
La API permite procesar múltiples textos simultáneamente en una sola petición, optimizando tanto el rendimiento como los costos:
textos_para_procesar = [
"Inteligencia artificial y machine learning",
"Desarrollo web con Python y Django",
"Análisis de datos con pandas y numpy",
"Sistemas distribuidos y microservicios"
]
response = client.embeddings.create(
input=textos_para_procesar,
model="text-embedding-3-small"
)
# Procesamiento de resultados múltiples
embeddings_resultados = []
for i, item in enumerate(response.data):
embedding = item.embedding
texto_original = textos_para_procesar[i]
embeddings_resultados.append({
'texto': texto_original,
'embedding': embedding,
'indice': item.index
})
print(f"Procesados {len(embeddings_resultados)} textos")
print(f"Total de tokens: {response.usage.total_tokens}")
Además, con librerías como numpy y conceptos de álgebra podemos calcular la métrica de similitud de coseno para saber qué textos se acercan más a lo que pregunta el usuario:
import numpy as np
def get_embedding(text, model="text-embedding-3-small"):
embedding = client.embeddings.create(input=[text], model=model).data[0].embedding
return embedding
def calculate_cosine_similarity(query_vector, vector):
return np.dot(query_vector, vector) / (np.linalg.norm(query_vector) * np.linalg.norm(vector))
Ejemplo de uso:
Control de dimensionalidad
Una característica avanzada permite reducir las dimensiones del embedding sin perder propiedades semánticas significativas:
# Embedding con dimensiones reducidas
response_reducido = client.embeddings.create(
input="Texto de ejemplo para dimensiones reducidas",
model="text-embedding-3-large",
dimensions=1024 # Reducido desde 3072 a 1024
)
embedding_reducido = response_reducido.data[0].embedding
print(f"Dimensiones reducidas: {len(embedding_reducido)}")
# Comparación de rendimiento vs tamaño
response_completo = client.embeddings.create(
input="Texto de ejemplo para dimensiones reducidas",
model="text-embedding-3-large"
)
embedding_completo = response_completo.data[0].embedding
print(f"Dimensiones completas: {len(embedding_completo)}")
Implementación práctica para búsqueda
Un caso de uso común es crear un sistema de búsqueda semántica donde los embeddings permiten encontrar contenido relevante:
import numpy as np
from typing import List, Tuple
class BuscadorSemantico:
def __init__(self):
self.client = OpenAI()
self.documentos = []
self.embeddings_documentos = []
def agregar_documento(self, texto: str):
"""Agrega un documento al índice de búsqueda"""
response = self.client.embeddings.create(
input=texto,
model="text-embedding-3-small"
)
embedding = response.data[0].embedding
self.documentos.append(texto)
self.embeddings_documentos.append(embedding)
def buscar(self, consulta: str, top_k: int = 3) -> List[Tuple[str, float]]:
"""Busca documentos similares a la consulta"""
# Generar embedding de la consulta
response = self.client.embeddings.create(
input=consulta,
model="text-embedding-3-small"
)
embedding_consulta = response.data[0].embedding
# Calcular similitudes
similitudes = []
for i, doc_embedding in enumerate(self.embeddings_documentos):
similitud = self._similitud_coseno(embedding_consulta, doc_embedding)
similitudes.append((self.documentos[i], similitud))
# Ordenar por similitud y devolver top_k
similitudes.sort(key=lambda x: x[1], reverse=True)
return similitudes[:top_k]
def _similitud_coseno(self, vec1: List[float], vec2: List[float]) -> float:
"""Calcula la similitud coseno entre dos vectores"""
vec1_np = np.array(vec1)
vec2_np = np.array(vec2)
dot_product = np.dot(vec1_np, vec2_np)
norm1 = np.linalg.norm(vec1_np)
norm2 = np.linalg.norm(vec2_np)
return dot_product / (norm1 * norm2)
# Uso del buscador
buscador = BuscadorSemantico()
# Agregar documentos
documentos_ejemplo = [
"Python es un lenguaje de programación versátil y fácil de aprender",
"JavaScript permite crear aplicaciones web interactivas",
"Los algoritmos de machine learning requieren grandes datasets",
"Las bases de datos relacionales utilizan SQL para consultas"
]
for doc in documentos_ejemplo:
buscador.agregar_documento(doc)
# Realizar búsqueda
resultados = buscador.buscar("programación web", top_k=2)
for documento, similitud in resultados:
print(f"Similitud: {similitud:.3f} - {documento}")
Optimización de costos y rendimiento
Para aplicaciones de producción, es importante considerar estrategias de optimización:
def procesar_lote_optimizado(textos: List[str], tamaño_lote: int = 100):
"""Procesa textos en lotes para optimizar costos"""
client = OpenAI()
todos_embeddings = []
for i in range(0, len(textos), tamaño_lote):
lote = textos[i:i + tamaño_lote]
response = client.embeddings.create(
input=lote,
model="text-embedding-3-small"
)
# Extraer embeddings del lote
embeddings_lote = [item.embedding for item in response.data]
todos_embeddings.extend(embeddings_lote)
print(f"Procesado lote {i//tamaño_lote + 1}: {len(lote)} textos")
print(f"Tokens utilizados: {response.usage.total_tokens}")
return todos_embeddings
# Ejemplo de uso con gran volumen de datos
textos_grandes = [f"Documento número {i} con contenido específico" for i in range(500)]
embeddings_resultado = procesar_lote_optimizado(textos_grandes)
Manejo de errores y límites
La implementación robusta debe considerar limitaciones de la API y manejo de errores:
import time
from openai import OpenAI, RateLimitError, APIError
def generar_embedding_robusto(texto: str, max_reintentos: int = 3):
"""Genera embedding con manejo de errores y reintentos"""
client = OpenAI()
for intento in range(max_reintentos):
try:
response = client.embeddings.create(
input=texto,
model="text-embedding-3-small"
)
return response.data[0].embedding
except RateLimitError:
tiempo_espera = 2 ** intento # Backoff exponencial
print(f"Límite de velocidad alcanzado. Esperando {tiempo_espera}s...")
time.sleep(tiempo_espera)
except APIError as e:
print(f"Error de API en intento {intento + 1}: {e}")
if intento == max_reintentos - 1:
raise
time.sleep(1)
raise Exception("No se pudo generar el embedding después de todos los reintentos")
# Uso con manejo de errores
try:
embedding = generar_embedding_robusto("Texto de ejemplo")
print(f"Embedding generado exitosamente: {len(embedding)} dimensiones")
except Exception as e:
print(f"Error final: {e}")
La API de Embeddings de OpenAI proporciona una base sólida para implementar sistemas RAG avanzados, donde la calidad de las representaciones vectoriales determina directamente la efectividad de la recuperación de información relevante.
Aprendizajes de esta lección
- Comprender qué son los embeddings y cómo representan el significado semántico del texto.
- Conocer los fundamentos matemáticos y propiedades semánticas de los embeddings.
- Identificar los casos de uso principales de los embeddings en procesamiento de lenguaje natural.
- Aprender a utilizar la API de embeddings de OpenAI para generar y manipular vectores semánticos.
- Implementar ejemplos prácticos de búsqueda semántica y optimización en el uso de embeddings.
Completa OpenAI y certifícate
Únete a nuestra plataforma y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.
Asistente IA
Resuelve dudas al instante
Ejercicios
Practica con proyectos reales
Certificados
Valida tus conocimientos
Más de 25.000 desarrolladores ya se han certificado con CertiDevs