AI Engineering Academy · Lección

Generación de embeddings con OpenAI

Usará los modelos text-embedding-3-small y text-embedding-3-large para generar embeddings de oraciones, párrafos y documentos, y comparará sus ventajas y desventajas en calidad y coste.

Lección 2 de 413 pasos

Generación de embeddings con OpenAI es una lección gratuita de AI Engineering Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Engineering Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Engineering Academy incluye 4 lecciones en total.

Descripción general de los modelos de embeddings de OpenAI

OpenAI ofrece dos modelos de embeddings para producción: text-embedding-3-small y text-embedding-3-large. El modelo pequeño produce vectores de 1536 dimensiones y cuesta 5 veces menos por token, mientras que el modelo grande produce vectores de 3072 dimensiones con mayor precisión en las pruebas de referencia. Para la mayoría de las aplicaciones RAG, el modelo pequeño es el punto de partida adecuado.

Realizar su primera llamada de embedding

El método client.embeddings.create() recibe un nombre de model y una cadena o lista en input. Devuelve un objeto de respuesta con una lista data, donde cada elemento tiene un atributo embedding que contiene el vector como una lista de valores float de Python.

Guarde siempre su clave de API en una variable de entorno; nunca la escriba directamente en los archivos de código fuente.

import os
from openai import OpenAI

client = OpenAI(api_key=os.environ['OPENAI_API_KEY'])

response = client.embeddings.create(
    model='text-embedding-3-small',
    input='What is retrieval-augmented generation?'
)

vector = response.data[0].embedding
print(f'Vector length: {len(vector)}')      # 1536
print(f'Type: {type(vector[0])}')           # float
print(f'Sample values: {vector[:3]}')       # [-0.02, 0.01, ...]

Procesar lotes de embeddings de forma eficiente

Pasar una lista de cadenas a input genera sus embeddings en un solo viaje de ida y vuelta a la API. Este es el enfoque recomendado al indexar un corpus de documentos. La lista data de la respuesta conserva el orden original, lo que facilita crear un diccionario de consulta.

Los lotes están limitados a 2048 elementos por solicitud y el total de tokens de todas las entradas debe mantenerse dentro del límite de tokens del modelo.

from openai import OpenAI

client = OpenAI()

documents = [
    'RAG stands for Retrieval-Augmented Generation.',
    'Embeddings convert text to numerical vectors.',
    'Pinecone is a managed vector database service.'
]

response = client.embeddings.create(
    model='text-embedding-3-small',
    input=documents
)

embeddings = [item.embedding for item in response.data]
print(f'Got {len(embeddings)} embeddings')
print(f'Each has {len(embeddings[0])} dimensions')

Reducir las dimensiones de los embeddings

Ambos modelos text-embedding-3 admiten un parámetro dimensions que trunca el vector de salida. Por ejemplo, establecer dimensions=256 devuelve un vector de 256 elementos en lugar de uno de 1536. Los vectores más cortos requieren menos almacenamiento y capacidad de cómputo, con una reducción moderada de la precisión.

Esto resulta útil cuando desea experimentar rápidamente o cuando el coste de almacenamiento es más importante que la calidad máxima de recuperación.

from openai import OpenAI

client = OpenAI()

response = client.embeddings.create(
    model='text-embedding-3-small',
    input='Shorter vectors save storage and query time.',
    dimensions=256   # truncate from 1536 to 256
)

print(len(response.data[0].embedding))  # 256

Formato de codificación: Base64 frente a lista de valores float

De forma predeterminada, la API devuelve los embeddings como una matriz JSON de valores float (encoding_format='float'). Puede solicitar encoding_format='base64' para recibir un bloque binario compacto codificado en base64, que se transfiere más rápidamente por la red en lotes grandes.

Al utilizar base64, debe decodificarlo con NumPy: np.frombuffer(base64.b64decode(b64_str), dtype='float32').

import base64
import numpy as np
from openai import OpenAI

client = OpenAI()

response = client.embeddings.create(
    model='text-embedding-3-small',
    input='Base64 encoding transfers faster.',
    encoding_format='base64'
)

b64 = response.data[0].embedding
vector = np.frombuffer(base64.b64decode(b64), dtype='float32')
print(f'Decoded {len(vector)} floats')

Seguimiento del uso de tokens y del coste

Cada respuesta de embedding incluye un objeto usage con prompt_tokens. El pago se calcula por token: text-embedding-3-small cuesta 0,02 $ por millón de tokens y text-embedding-3-large cuesta 0,13 $ por millón de tokens (a mediados de 2024).

Hacer un seguimiento del uso le permite estimar cuánto costará indexar todo su corpus antes de comprometerse con una ejecución en producción.

from openai import OpenAI

client = OpenAI()

texts = ['Document one content here.', 'Document two content here.']

response = client.embeddings.create(
    model='text-embedding-3-small',
    input=texts
)

tokens_used = response.usage.prompt_tokens
cost_usd = tokens_used * 0.00000002  # $0.02 per 1M tokens
print(f'Tokens: {tokens_used}, Cost: ${cost_usd:.6f}')

Comparación entre text-embedding-3-small y large

La elección entre los modelos pequeño y grande depende de sus requisitos de precisión y de su presupuesto:

  • text-embedding-3-small: 1536D, más rápido, 5 veces más económico y excelente para la mayoría de las cargas de trabajo RAG
  • text-embedding-3-large: 3072D, mejores puntuaciones en la prueba de referencia MTEB y más adecuado para contenido multilingüe y tareas semánticas complejas

Un patrón habitual consiste en crear un prototipo y validar la calidad de recuperación con el modelo pequeño, y cambiar al grande únicamente si las métricas de evaluación quedan por debajo de su objetivo.

Normalizar embeddings para búsquedas mediante producto punto

OpenAI devuelve embeddings normalizados mediante L2, lo que significa que cada vector ya tiene una magnitud de 1. Esto permite utilizar el producto punto como una aproximación rápida de la similitud coseno sin realizar un paso adicional de normalización, algo importante al buscar entre millones de vectores, donde las microoptimizaciones se acumulan.

import numpy as np
from openai import OpenAI

client = OpenAI()

response = client.embeddings.create(
    model='text-embedding-3-small',
    input='Are OpenAI embeddings normalized?'
)

vec = np.array(response.data[0].embedding)
magnitude = np.linalg.norm(vec)
print(f'Vector magnitude: {magnitude:.6f}')  # very close to 1.0

Trabajar con documentos grandes

El modelo text-embedding-3-small acepta hasta 8191 tokens por entrada. Si su documento supera este límite, la API devolverá un error. La solución estándar consiste en dividir primero el documento en fragmentos (normalmente de 200 a 500 tokens por fragmento) y generar un embedding para cada uno por separado.

Esta división no es solo un requisito técnico: también mejora la recuperación, porque generar embeddings de fragmentos pequeños y enfocados devuelve resultados más precisos que generarlos para páginas completas.

import tiktoken

enc = tiktoken.encoding_for_model('text-embedding-3-small')

def count_tokens(text):
    return len(enc.encode(text))

max_tokens = 8191
text = 'Very long document content...'  # pretend this is huge

if count_tokens(text) > max_tokens:
    print('Document too long — chunk before embedding')
else:
    print(f'Safe to embed: {count_tokens(text)} tokens')

Generación asíncrona de embeddings para un alto rendimiento

Al indexar miles de documentos, utilice el cliente asíncrono de OpenAI con asyncio.gather para enviar varias solicitudes de embeddings de forma simultánea. Esto es mucho más rápido que realizar llamadas secuenciales, porque el cuello de botella es la latencia de red, no la CPU.

Añada siempre gestión de límites de velocidad con retroceso exponencial al ejecutar solicitudes simultáneas, para evitar alcanzar el límite de tokens por minuto.

import asyncio
from openai import AsyncOpenAI

async def embed_batch(texts):
    client = AsyncOpenAI()
    response = await client.embeddings.create(
        model='text-embedding-3-small',
        input=texts
    )
    return [item.embedding for item in response.data]

async def main():
    batches = [['doc1', 'doc2'], ['doc3', 'doc4']]
    results = await asyncio.gather(*[embed_batch(b) for b in batches])
    all_embeddings = [emb for batch in results for emb in batch]
    print(f'Embedded {len(all_embeddings)} documents')

asyncio.run(main())

Almacenamiento en caché de embeddings para ahorrar costes

Generar embeddings para el mismo texto varias veces desperdicia dinero y tiempo. Almacene los embeddings en un diccionario cuya clave sea la cadena de texto (o un hash de esta) y conserve esta caché en disco entre sesiones.

En sistemas de producción, almacene los embeddings en una base de datos vectorial que elimine duplicados por ID de documento. Vuelva a generar el embedding de un documento solo cuando su contenido cambie realmente, no en cada ejecución de indexación.

import json, hashlib, os
from openai import OpenAI

CACHE_FILE = '/tmp/embedding_cache.json'
client = OpenAI()

try:
    cache = json.load(open(CACHE_FILE))
except FileNotFoundError:
    cache = {}

def get_embedding(text):
    key = hashlib.md5(text.encode()).hexdigest()
    if key not in cache:
        r = client.embeddings.create(model='text-embedding-3-small', input=text)
        cache[key] = r.data[0].embedding
        json.dump(cache, open(CACHE_FILE, 'w'))
    return cache[key]

vec = get_embedding('Caching saves API costs.')
print(f'Retrieved {len(vec)}-dim embedding')

Comprobación rápida

Compruebe su comprensión de los conceptos de ingeniería de IA de esta lección.

Resumen de la lección

En esta lección ha aprendido que text-embedding-3-small es la opción rentable para la mayoría de las cargas de trabajo de RAG, que generar embeddings de varios textos en una sola llamada a la API es más eficiente que realizar llamadas secuenciales y que el parámetro dimensions puede reducir el tamaño de los vectores para intercambiar precisión por ahorro de almacenamiento. A continuación, crearemos un sistema de búsqueda semántica utilizando estos embeddings y NumPy.

Gratis para empezar

Aprende Python con un tutor de IA — gratis

Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.

Cursos
30
Lecciones
120

Preguntas frecuentes

¿La lección «Generación de embeddings con OpenAI» es gratis?

Sí — el texto completo de «Generación de embeddings con OpenAI» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Engineering Academy, actualiza a CoddyKit PRO. El curso de AI Engineering Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Generación de embeddings con OpenAI»?

Usará los modelos text-embedding-3-small y text-embedding-3-large para generar embeddings de oraciones, párrafos y documentos, y comparará sus ventajas y desventajas en calidad y coste. Practicas AI Engineering Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar AI Engineering Academy?

No se requiere experiencia previa. AI Engineering Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.

¿Cuánto tiempo toma la lección «Generación de embeddings con OpenAI»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de AI Engineering Academy?

Sí. Cada lección de AI Engineering Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. ¿Qué son los vector embeddings?
  2. Generación de embeddings con OpenAI
  3. Búsqueda semántica con NumPy
  4. Clustering y visualización de embeddings
← Volver a AI Engineering Academy