Skip to main content
Orux AIOruxAI

Orux AI / Notas sobre modelos

API de embeddings: migrar índices y poder revertir

Migra entre text-embedding-3-small y large sin mezclar espacios vectoriales. Ejecuta seis comprobaciones y calcula costes de reconstrucción, almacenamiento y reversión.

Orux AIPublicado 11 min de lectura
API de embeddings: migrar índices y poder revertir — Migra entre text-embedding-3-small y large sin mezclar espacios vectori…
En este artículo

Cambiar de modelo de embeddings exige un nuevo índice de búsqueda

Al migrar de text-embedding-3-small a text-embedding-3-large, crea un índice independiente a partir del texto original de los documentos y procesa las consultas con la configuración de embeddings correspondiente. No adaptes los vectores antiguos añadiendo ceros ni interpretes una longitud idéntica como prueba de que dos modelos comparten un sistema de coordenadas. Conserva el índice antiguo hasta que los nuevos flujos de documentos y consultas superen tu propia evaluación de recuperación.

Para un equipo de documentación que migra el buscador de ayuda de un producto, esto implica presupuestar una nueva generación de embeddings de todo el corpus, almacenamiento temporal para ambos índices y un cambio de configuración reversible. El ejemplo ejecutable de Python que sigue demuestra por qué comprobar solo las dimensiones resulta insuficiente, rechaza seis casos de prueba inválidos y calcula un presupuesto concreto de reconstrucción. Se ejecuta completamente sin conexión: sus vectores bidimensionales son geometría definida a mano, no resultados de ninguno de los modelos de OpenAI.

Los espacios vectoriales original y rotado recuperan A de forma coherente; al mezclarlos se recupera B.
Los espacios vectoriales original y rotado recuperan A de forma coherente; al mezclarlos se recupera B.

Los vectores definidos a mano conservan el resultado correcto dentro de cada espacio. Al mezclar la consulta y el índice, se obtiene B aunque todos los vectores tengan la misma longitud. Diagrama derivado del ejemplo ejecutado localmente.

Dimensiones de los modelos y límites actuales de Orux

La guía de embeddings de OpenAI indica longitudes predeterminadas de 1,536 para text-embedding-3-small y de 3,072 para text-embedding-3-large. También documenta el parámetro nativo dimensions para reducir las dimensiones de los embeddings de tercera generación. Reducir la salida de un modelo compatible es una elección de configuración; no convierte ese modelo en otro.

Ambos alias exactos figuran actualmente en Orux. La página del modelo text-embedding-3-small y la página del modelo text-embedding-3-large ofrecen entrada de texto y vectores en formato float. Sus ejemplos públicos guardados indican 1,536 y 3,072 dimensiones, respectivamente. Esos ejemplos respaldan la forma de salida indicada, no una clasificación general de precisión entre modelos.

Los formularios comprobados el 3 de noviembre de 2026 no muestran un control de dimensiones. Por tanto, no planifiques un índice de Orux con dimensiones reducidas solo porque la documentación nativa de OpenAI describa esa posibilidad. Confirma el contrato de integración exacto antes de depender de ella. Este artículo no envía solicitudes de embeddings de pago ni demuestra que Orux reenvíe el parámetro de dimensiones. Consulta la documentación de la API de Orux para conocer la interfaz de integración actual.

Registra conjuntamente el alias del modelo, el número de dimensiones devuelto, la versión del preprocesamiento de texto y la métrica de distancia. Por ejemplo, un artículo de ayuda formado por title + body debe tener una versión de preprocesamiento distinta de otro que solo genere embeddings de body. Guarda los hashes de revisión de los documentos junto con los identificadores de fragmento para detectar texto desactualizado en una reconstrucción posterior. Una coincidencia de dimensiones detecta un error evidente de forma; los demás campos del contrato detectan errores de configuración que la forma no revela.

Un ejemplo bidimensional que revela la incompatibilidad oculta

Imagina dos vectores de documentos en un espacio antiguo de juguete: A es (1, 0) y B es (0, 1). La consulta antigua (1, 0) recupera A. Ahora gira todo el espacio 90 grados. A pasa a ser (0, 1), B pasa a ser (-1, 0) y la consulta del mismo concepto pasa a ser (0, 1). Una búsqueda coherente dentro de cualquiera de los dos espacios sigue recuperando A.

Sin embargo, al mezclar la consulta girada con los documentos antiguos, gana B. Todos los vectores siguen teniendo dos coordenadas. El cálculo se ejecuta correctamente, pero el significado de la búsqueda cambia. Es un contraejemplo matemático a la idea de que unas dimensiones iguales establecen compatibilidad; no simula el comportamiento aprendido de ninguno de los modelos ni estima tasas de fallo de migraciones reales.

Rellenar con ceros un vector antiguo cambia su longitud, pero no aporta una transformación hacia la representación aprendida por un modelo nuevo. Truncarlo tampoco establece compatibilidad entre modelos. Incluso al reducir dimensiones dentro de un mismo modelo compatible, aplica una política coherente a documentos y consultas y evalúa el comportamiento de recuperación resultante. La reducción nativa de dimensiones no autoriza a mezclar representaciones antiguas y nuevas indiscriminadamente.

La comprobación del ejemplo compara la configuración completa antes de calcular la similitud coseno. Esa comparación solo funciona si los metadatos son veraces: etiquetar deliberadamente una consulta nueva como antigua elude la comprobación. El resultado unsafe_mixed_top que aparece más abajo ilustra precisamente esa limitación. En producción, la procedencia debe derivarse de la configuración del codificador y de la ruta de almacenamiento, no de una afirmación del solicitante sin verificar.

Coste de reconstrucción: calcula el corpus, no el número de vectores

Los precios siguientes se comprobaron el 3 de noviembre de 2026. Las tarifas de Orux proceden de las fichas públicas de los dos modelos. Las tarifas estándar de entrada de OpenAI directo proceden de sus páginas de precios del modelo small y precios del modelo large. Son opciones de compra distintas; no se afirma que sus condiciones de cuenta o su comportamiento operativo sean idénticos.

La conversión configurada actualmente es 1 Credit = USD 0.005. Los valores en USD que siguen son equivalencias aritméticas; Orux factura en Credits. Todas las tarifas corresponden a un millón de tokens de entrada, no a un millón de documentos. La tabla excluye los costes adicionales de almacenamiento, alojamiento del índice e ingeniería, y no presupone descuentos Batch ni una reconstrucción gratuita.

ModeloTarifa de entrada de Orux / 1M tokensTarifa estándar de OpenAI directo / 1M tokensReconstrucción prevista de 5M tokens en Orux
text-embedding-3-small1.53336 Credits (USD 0.0076668)Equivalente a 4 Credits (USD 0.02)7.6668 Credits (USD 0.038334)
text-embedding-3-large9.96672 Credits (USD 0.0498336)Equivalente a 26 Credits (USD 0.13)49.8336 Credits (USD 0.249168)

Desliza horizontalmente para ver toda la tabla.

Un corpus de planificación de 10,000 fragmentos con una media de 500 tokens de entrada suma cinco millones de tokens. Migrar todo ese corpus a large exige, por tanto, presupuestar la reconstrucción con large, no limitarse a pagar la diferencia entre las dos filas. Lo gastado anteriormente en small no compra vectores de large. En esta captura, la tarifa de large en Orux es aproximadamente 6.5 veces la de small; esa proporción no dice nada sobre la mejora de recuperación en tus documentos.

Estos totales son estimaciones basadas en un número supuesto de tokens y un cálculo agregado. La longitud real de los fragmentos, el tráfico de consultas, los reintentos y la granularidad de facturación pueden cambiar el gasto. Mide los tokens del corpus con el tokenizador adecuado antes de autorizar una ejecución real. El código ejecutable calcula las tarifas con micro-Credits enteros y usa Decimal para mostrarlas, evitando cálculos monetarios con coma flotante binaria.

La memoria requiere una estimación aparte. En float32, 10,000 vectores necesitan 61,440,000 bytes con 1,536 dimensiones o 122,880,000 bytes con 3,072 dimensiones: aproximadamente 58.59 MiB y 117.19 MiB. Son únicamente las matrices de coordenadas sin sobrecarga. Los metadatos, identificadores, estructuras de grafos de búsqueda, réplicas y serialización añaden espacio. Durante una migración reversible, conservar ambas matrices sin sobrecarga ya requiere 184,320,000 bytes.

Ejecuta la demostración de compatibilidad y presupuesto

Guarda el código siguiente como migration_demo.py y ejecuta python3 migration_demo.py con Python 3.9 o posterior. Solo usa la biblioteca estándar y no realiza solicitudes de red. Las tarifas corresponden a una fecha concreta para que el cálculo sea reproducible; sustitúyelas por tarifas actuales verificadas al planificar una migración posterior.

Python
import json
import math
from dataclasses import asdict, dataclass
from decimal import Decimal

@dataclass(frozen=True)
class Contract:
    model: str
    dimensions: int
    preprocessing: str
    metric: str = 'cosine'

def validate(vector, contract):
    if len(vector) != contract.dimensions:
        raise ValueError('dimension mismatch')
    if any(isinstance(x, bool) or not isinstance(x, (int, float))
           or not math.isfinite(x) for x in vector):
        raise ValueError('non-finite or non-numeric vector')
    if math.hypot(*vector) == 0:
        raise ValueError('zero vector')

def search(query, query_contract, documents, index_contract):
    if query_contract != index_contract:
        raise ValueError('embedding contract mismatch')
    validate(query, query_contract)
    scores = []
    for doc_id, vector in documents.items():
        validate(vector, index_contract)
        score = sum(a*b for a, b in zip(query, vector)) / (
            math.hypot(*query) * math.hypot(*vector))
        scores.append((doc_id, score))
    return sorted(scores, key=lambda row: (-row[1], row[0]))

def budget(rate_micro_credits, total_tokens):
    micro = (rate_micro_credits * total_tokens + 999999) // 1000000
    credits = Decimal(micro) / 1000000
    return {'credits': str(credits), 'usd': str(credits * Decimal('0.005'))}

def main():
    # Handwritten two-dimensional geometry, NOT model outputs.
    old = Contract('toy-old', 2, 'title-body-v1')
    new = Contract('toy-new', 2, 'title-body-v1')
    old_docs = {'A': [1, 0], 'B': [0, 1]}
    new_docs = {'A': [0, 1], 'B': [-1, 0]}
    old_top = search([1, 0], old, old_docs, old)[0][0]
    new_top = search([0, 1], new, new_docs, new)[0][0]
    unsafe_top = search([0, 1], old, old_docs, old)[0][0]
    assert (old_top, new_top, unsafe_top) == ('A', 'A', 'B')
    failures = [
        lambda: search([0, 1], new, old_docs, old),
        lambda: validate([1], old),
        lambda: validate([0, 0], old),
        lambda: validate([float('nan'), 1], old),
        lambda: validate([True, 1], old),
        lambda: search([1, 0], Contract('toy-old', 2, 'title-body-v2'), old_docs, old),
    ]
    rejected = 0
    for test in failures:
        try:
            test()
        except ValueError:
            rejected += 1
        else:
            raise AssertionError('invalid fixture was accepted')
    chunks, tokens_per_chunk = 10000, 500
    tokens = chunks * tokens_per_chunk
    result = {
        'toy_results': {'old_top': old_top, 'new_top': new_top,
                        'unsafe_mixed_top': unsafe_top},
        'rejected_fixtures': rejected,
        'planning_tokens': tokens,
        'orux_small': budget(1533360, tokens),
        'orux_large': budget(9966720, tokens),
        'raw_float32_bytes': {'small_1536': chunks * 1536 * 4,
                             'large_3072': chunks * 3072 * 4},
        'new_contract': asdict(new),
    }
    print(json.dumps(result, indent=2))

if __name__ == '__main__':
    main()

La ejecución local produjo old_top: A, new_top: A, unsafe_mixed_top: B y rejected_fixtures: 6. Los casos rechazados son un contrato de modelo diferente, una longitud de vector incorrecta, un vector nulo, una coordenada no finita, una coordenada booleana y una versión de preprocesamiento modificada. Los presupuestos de small y large son 7.6668 y 49.8336 Credits, en consonancia con la tabla.

Es una demostración ejecutable de la regla de compatibilidad y del cálculo de costes, no un adaptador de base de datos. No obtiene embeddings, construye un índice de vecinos más próximos aproximados, demuestra la calidad de recuperación de un modelo ni implementa controles de acceso de producción. Sus coordenadas sintéticas tienen valores pequeños; una biblioteca numérica de producción también debe manejar todo el rango numérico de las entradas que acepte.

Dos pares separados de codificador e índice permiten un cambio coordinado y una reversión.
Dos pares separados de codificador e índice permiten un cambio coordinado y una reversión.

Plan de despliegue: mantén cada codificador de consultas conectado a su índice correspondiente; cambia y revierte el par completo. El diagrama describe la arquitectura propuesta, no una migración desplegada.

Cambia el codificador de consultas y el índice como una sola configuración

Crea una colección o un espacio de nombres nuevo con el contrato de destino. Lee el texto fuente original, aplica las reglas registradas de fragmentación y preprocesamiento, y guarda los vectores del modelo de destino con identificadores estables de documento y fragmento. No alteres la colección existente. Registra los identificadores de fragmento esperados, los completados y las revisiones de origen, en lugar de depender de un único contador de filas procesadas.

Si los documentos fuente cambian durante la reconstrucción, elige una política de coherencia clara. Una captura durante una ventana de mantenimiento evita escrituras concurrentes, pero retrasa las actualizaciones. Una reconstrucción en línea necesita un registro de cambios reproducible o una conciliación equivalente para que las modificaciones y eliminaciones lleguen al índice nuevo antes del cambio. Un número igual de vectores no basta si un documento eliminado y otro ausente se compensan numéricamente por casualidad.

Después, vincula cada codificador de consultas con el índice previsto. No actualices la aplicación para generar consultas con large mientras siga leyendo la colección de small. Trata el par como una configuración de aplicación versionada que incluya preprocesamiento, dimensiones y métrica. Rechaza las solicitudes cuando el manifiesto guardado de la colección y la configuración de la consulta no coincidan. En sistemas multiinquilino, conserva los mismos filtros por inquilino y permisos de documentos en ambas colecciones.

Para poder revertir, conserva juntos la configuración antigua de consultas y su colección. Guardar solo los vectores antiguos no basta si la aplicación ya no puede generar consultas antiguas compatibles. Tras el cambio, observa la calidad de los resultados, los informes de documentos ausentes, la latencia y los costes de consulta. Retira el par antiguo únicamente después del periodo de evaluación y conservación acordado, no simplemente cuando la colección nueva acepte escrituras.

Decide con consultas etiquetadas, no por el tamaño del vector

Prepara un conjunto de evaluación pequeño y representativo antes de reconstruirlo todo. Para un servicio de ayuda de producto, incluye referencias exactas de piezas, preguntas imprecisas de resolución de problemas, solicitudes multilingües y documentos con restricciones de acceso. Registra qué identificadores de documento son relevantes para cada pregunta. Separa la evaluación de relevancia de la fluidez aparente de la respuesta generada.

Para cada configuración candidata, recupera el mismo número de resultados a partir de la misma captura de documentos. Compara la presencia de documentos relevantes entre los primeros resultados y examina las omisiones importantes. No compares un índice de small construido con fragmentos breves del cuerpo con un índice de large construido con texto enriquecido de título y cuerpo para después atribuir toda la diferencia al modelo. La fragmentación, el preprocesamiento y los filtros de acceso son variables experimentales independientes.

Este artículo no establece un ganador medido. Elige small cuando su propia evaluación cumpla tus requisitos con el menor coste actual de entrada y almacenamiento. Considera large cuando sus mejoras medidas en tu carga de trabajo justifiquen la reconstrucción, los vectores mayores y el coste continuo de consultas. Una prueba local de compatibilidad superada proporciona una protección, no un motivo para comprar un modelo más caro.

FAQ

¿Debo regenerar todos los vectores de documentos al cambiar de modelo?

Sí: en la migración descrita aquí, regenera el corpus consultable en el espacio del modelo de destino. Conserva el texto original y los identificadores estables de fragmento, y codifica las consultas futuras con la misma configuración de destino. Cambiar el nombre del campo de modelo no vuelve compatibles los vectores existentes.

¿Puedo rellenar vectores de 1,536 dimensiones hasta alcanzar 3,072?

El relleno puede cumplir un requisito de longitud de matriz, pero no establece una transformación entre modelos. No es una estrategia de compatibilidad adecuada para esta migración. El ejemplo de juguete muestra que una forma válida todavía puede recuperar el documento incorrecto al mezclar espacios.

¿Orux expone el parámetro nativo dimensions de OpenAI?

Los formularios públicos comprobados para estos dos alias de Orux no lo muestran. La documentación nativa de OpenAI, por sí sola, no verifica el comportamiento de Orux. Confirma el contrato de integración real antes de depender de salidas reducidas y, después, construye y consulta un índice con una configuración coherente.

¿text-embedding-3-large es automáticamente mejor para mi buscador?

Este artículo no demuestra una mejora específica para tu carga de trabajo. Evalúa ambas configuraciones con tus propias preguntas etiquetadas y la misma captura de origen. Más dimensiones y precios mayores no sustituyen la medición de si se recuperan los documentos relevantes.

¿Qué comprobó realmente el ejemplo de Python?

Comprobó la geometría de vectores definidos a mano, el rechazo de contratos incompatibles, seis casos de prueba inválidos y los cálculos de presupuesto y almacenamiento de una fecha concreta. No llamó a ninguna API de embeddings, no gastó Credits de Orux ni evaluó resultados de modelos o una base de datos vectorial real.

Prueba página del modelo text-embedding-3-small en Orux AIEjecútalo en línea y consulta precios y ejemplos de API en la página del modelo.Abrir modeloPrueba página del modelo text-embedding-3-large en Orux AIEjecútalo en línea y consulta precios y ejemplos de API en la página del modelo.Abrir modelo

Usa estos modelos con una sola API

Una API compatible con OpenAI para modelos de chat, imagen, vídeo y audio, facturada en Credits.

Artículos relacionados

Ver todos los artículos →