Imagina el montaje habitual en 2026: una app en Symfony o Laravel, un worker de cola que genera embeddings de cada documento subido, y un nodo de Qdrant junto a la base de datos haciendo búsqueda semántica sobre todo ello. La app en sí es barata de operar. El almacén de vectores no, porque los vectores quieren RAM, y la RAM es lo más caro que puedes alquilar. Qdrant 1.19 trae dos respuestas a eso, y quiero defender que la menos glamurosa, la API unificada de niveles de memoria, es la funcionalidad por la que la mayoría deberíamos actualizar, mientras que el datatype turbo4, el que acapara titulares, merece admiración y una pegatina de advertencia a la vez. Descarta permanentemente tus vectores en precisión completa, y esa decisión no pertenece solo a un archivo de configuración de infraestructura.
{
"vectors": {
"size": 1536,
"distance": "Cosine",
"datatype": "turbo4"
}
}Empecemos por la victoria aburrida. Antes de 1.19, controlar dónde guardaba Qdrant los datos implicaba hacer malabares con on_disk en los parámetros del vector, always_ram en la configuración de cuantización y on_disk_payload a nivel de colección, tres flags con tres nombres en tres sitios. El propio grafo HNSW no se podía colocar en ningún lado; vivía siempre en memoria heap. La versión 1.19 lo colapsa todo en un único parámetro memory con tres valores: pinned (fijado en RAM), cached (en disco, con la page cache precalentada y desalojable) y cold (en disco, cargado de forma perezosa). Funciona por igual sobre vectores, enlaces HNSW, copias cuantizadas, payloads e índices de payload, y puedes cambiarlo en una colección en vivo con update_collection, sin reconstruir nada. Para quienes operamos Qdrant como sidecar de una app PHP, hablándole por HTTP, eso convierte la planificación de memoria de folclore en un mando de verdad.
El mando importa porque la aritmética es fea. La RAM en la nube ronda entre $3 y $8 por GB al mes; el disco NVMe cuesta más o menos entre $0.10 y $0.30. El propio ejemplo de las notas de la versión: mil millones de vectores float32 de 768 dimensiones necesitan unos 2.9 TB de almacenamiento, y un despliegue todo en pinned pide aproximadamente 3.7 TB de RAM. Mueve los originales a almacenamiento cold y fija solo una copia cuantizada en int8 para recorrer el grafo, y te quedas en unos 768 GB. A $5 por GB al mes son $18,500 frente a $3,840. Tú y yo probablemente no estamos en los mil millones de vectores, pero la proporción sobrevive perfectamente al viaje de bajada hasta los diez millones, y diez millones de fragmentos es una cifra muy alcanzable para cualquier producto que genere embeddings de documentos de clientes.
Ahora el cuchillo afilado. TurboQuant llegó en 1.18 como un método de cuantización basado en una idea de Google Research: rotar el vector aleatoriamente antes de comprimirlo, de modo que la información se reparta de forma uniforme entre dimensiones y la codificación de 4 bits pierda un poco en todas partes en lugar de mucho en un solo sitio. En 1.18 esa copia de 4 bits se apilaba sobre tus originales float32, lo que suponía 36 bits por dimensión en total. En 1.19, turbo4 se convierte en un datatype. Lo defines al crear la colección y Qdrant almacena únicamente la forma de 4 bits. Nada de float32 en disco, nada en RAM, nada en ninguna parte. Diez millones de vectores de text-embedding-3-small de 1536 dimensiones encogen de unos 64 GB con el patrón antiguo a unos 7 GB. Para colecciones multivector al estilo ColBERT, donde cada documento arrastra decenas de embeddings de tokens, el ahorro se multiplica por vector.
El precio es el rescoring, o más bien su ausencia permanente. Sin copia en precisión completa, tanto el recorrido del grafo como el ranking final operan con distancias de 4 bits, y el recall típico cae en torno a 0.90 a 0.95, frente a 0.97 a 0.99 cuando reordenas contra float32. Y aquí va mi punto de verdad: esa brecha es una decisión de producto vestida con disfraz de ops. Quien escribe datatype turbo4 en la configuración de una colección está decidiendo que más o menos uno de cada veinte resultados relevantes puede, silenciosamente, no volver. Para una primera etapa de recuperación que alimenta un reranker cross-encoder, o para un widget de recomendaciones, ese intercambio suele ser correcto. Para cualquier cosa donde una coincidencia perdida tenga consecuencias, un archivo legal, una consulta de cumplimiento normativo, la persona que despliega la configuración no debería ser la única que la firmó.
El contraargumento justo es que esta puerta no está cerrada del todo. Si conservaste el texto original, y deberías haberlo hecho, puedes regenerar los embeddings y reconstruir una colección float32 cuando quieras. Cierto, y eso le quita dramatismo a la decisión. Pero reprocesar diez millones de fragmentos cuesta dinero real en API y días reales, y el modo de fallo es feo precisamente porque es silencioso: las regresiones de recall afloran como un ticket de soporte diciendo que la búsqueda se siente peor, y a nadie se le ocurre sospechar primero de un datatype de almacenamiento elegido hace ocho meses. Así que antes de activarlo, mide el recall con tus propias consultas contra tus propios datos, no con vectores sintéticos. Y ojo a la letra pequeña: turbo4 es solo para vectores densos, y la distancia Manhattan fuerza la reconstrucción completa del vector, así que quédate con Cosine, Dot o Euclidean. Además hay un camino intermedio que me gusta de verdad: apilar TurboQuant de 1 bit sobre turbo4 y hacer rescoring contra los valores de 4 bits, mejor recall que ninguno, con la misma huella de disco de 4 bits.
Merece la pena decir que nadie más ofrece este intercambio exacto ahora mismo. Weaviate tiene su propio esquema de cuantización basado en rotaciones pero siempre retiene los vectores sin comprimir, Milvus no baja de 8 bits, y el nivel serverless de Pinecone no expone ningún control de compresión ni de colocación. Desde el mundo PHP, donde el almacén de vectores suele ser un servicio al que llamamos desde un worker más que un sistema que parcheamos, prefiero un dial explícito antes que una decisión gestionada y opaca, siempre, porque la factura llega a nuestra dirección de todos modos.
Así que esta es mi conclusión: actualiza por los niveles de memoria, trata turbo4 como una migración de esquema que no puedes revertir barato, y pon la cifra de recall en la descripción del pull request, donde un humano tenga que leerla. Ahora dime dónde está tu línea. ¿Usarías turbo4 para búsqueda de cara al usuario en producción, y si es así, qué cifra de recall, medida sobre tu propio log de consultas, te dejaría tranquilo para borrar los originales? Sospecho que las respuestas bajo esta columna irán desde 0.99 hasta un encogimiento de hombros, y quiero ver ambas.
Comentarios
Aún no hay comentarios — escribe el primero.
Inicia la conversación
Sin cuenta ni contraseña — introduce tu correo y te enviamos un enlace de acceso de un solo uso. ¿Primera vez? Todo se configura automáticamente.
Tu valoración se aplicará automáticamente al iniciar sesión.
Revisa tu bandeja de entrada
Hemos enviado un enlace de acceso a …. Ábrelo en este dispositivo — esta pestaña te conectará automáticamente.
¿No llega nada? Mira en la carpeta de spam — y marca el correo como «No es spam» para que la próxima vez llegue directo.