Pgvector: Cómo convertir PostgreSQL en una base de datos vectorial sin esfuerzo
Published on
Si estás utilizando PostgreSQL y aún no has oído hablar de pgvector, te estás perdiendo de una extensión que está cambiando el juego. Diseñado para potenciar tu base de datos PostgreSQL, pgvector es la herramienta definitiva para almacenamiento eficiente de vectores y búsqueda de similitud. No es solo un complemento, es una solución completa que se integra perfectamente con PostgreSQL, mejorando sus capacidades a nuevos niveles.
Pero ¿por qué deberías preocuparte? Porque en el mundo actual impulsado por datos, la capacidad de almacenar y consultar de manera eficiente grandes conjuntos de vectores es crucial para el aprendizaje automático, sistemas de recomendación y muchas otras aplicaciones. pgvector no solo hace esto posible, sino que lo hace con un nivel de eficiencia y velocidad difícil de igualar.
Por qué pgvector es esencial para los usuarios de PostgreSQL
¿Qué es pgvector?
pgvector es una extensión de PostgreSQL especializada en el almacenamiento de vectores y la realización de búsquedas de similitud dentro de esos vectores. A diferencia de los tipos de datos tradicionales de PostgreSQL, pgvector está optimizado para datos de alta dimensión, lo que lo hace ideal para modelos de aprendizaje automático, reconocimiento de imágenes y tareas de procesamiento de lenguaje natural.
Funciones principales de pgvector:
-
Almacenamiento eficiente de vectores: pgvector comprime vectores de alta dimensión sin perder la integridad de los datos. Esto es importante porque los datos de alta dimensión pueden ser una pesadilla de almacenamiento.
-
Múltiples métricas de distancia: Ya sea que estés trabajando con distancias euclídeas, coseno o Manhattan, pgvector te tiene cubierto. Soporta una variedad de métricas de distancia, dándote la flexibilidad de elegir la mejor para tu caso de uso específico.
-
Integración perfecta: Una de las mejores cosas de pgvector es lo fácil que se integra con PostgreSQL. No tienes que lidiar con diferentes bases de datos; pgvector funciona como una extensión nativa, lo que te permite realizar consultas complejas directamente dentro de PostgreSQL.
Vamos a los números. Con pgvector, puedes ejecutar 1 millón de embeddings de OpenAI a aproximadamente 1800 consultas por segundo (QPS) con una tasa de precisión del 91%. Si buscas una mayor precisión, puedes lograr 670 QPS con una impresionante precisión del 98%. Estas métricas no solo son impresionantes, son revolucionarias.
El rendimiento de pgvector no se limita solo a altos QPS y precisión. También es increíblemente escalable. Ya sea que lo ejecutes en un ARM de 8 núcleos con 32 GB de RAM o en un ARM de 64 núcleos con 256 GB, pgvector se escala de manera óptima, asegurando que aproveches al máximo tus recursos de hardware.
¿Qué tan rápido es pgvector realmente? (Benchmarks de pgvector)
Desglosando la velocidad y la precisión de pgvector
Si buscas velocidad y precisión en las búsquedas de vectores, pgvector te tiene cubierto. La última versión, pgvector 0.4.0, ha sido sometida a rigurosas pruebas para medir su rendimiento. Veamos los detalles:
Metodología de los benchmarks
- Ejecución de pruebas: Se utilizó un script en Python para la carga de datos, la creación de índices y la ejecución de consultas.
- Tiempo de ejecución: Cada prueba se ejecutó durante 30-40 minutos, cubriendo varios niveles de carga de trabajo para medir el rendimiento.
- Precalentamiento de RAM: Antes de cada prueba, se ejecutaron de 10,000 a 50,000 consultas de "precalentamiento" para optimizar la utilización de la RAM.
Hardware utilizado para las pruebas
- 2XL: ARM de 8 núcleos, 32 GB de RAM
- 4XL: ARM de 16 núcleos, 64 GB de RAM
- 8XL: ARM de 32 núcleos, 128 GB de RAM
- 12XL: ARM de 48 núcleos, 192 GB de RAM
- 16XL: ARM de 64 núcleos, 256 GB de RAM
Dataset
Las pruebas utilizaron el conjunto de datos dbpedia-entities-openai-1M (opens in a new tab), que incluye 1 millón de embeddings con 1536 dimensiones. Este conjunto de datos se crea utilizando OpenAI y está basado en artículos de Wikipedia.
Resultados de rendimiento
- Con sondas configuradas en 10: pgvector logró una precisión@10 de 0.91 y un QPS (consultas por segundo) de 380.
- Con sondas configuradas en 40: pgvector no solo se volvió más rápido, sino que también mantuvo casi la misma precisión que Qdrant, con una precisión@10 de 0.98 y un QPS de 140.
Escalado de la base de datos
El rendimiento de pgvector escala de manera predecible con el tamaño de la base de datos. Por ejemplo, una instancia 4XL logró una precisión@10 de 0.98 y un QPS de 270 con sondas configuradas en 40. Una instancia 8XL obtuvo una precisión@10 de 0.98 y un QPS de 470, superando los resultados de Qdrant.
Resultados de referencia de pgvector
En un servidor de 64 núcleos y 256 GB, pgvector logró alrededor de 1800 QPS con una precisión del 0.91. Esto es para la versión 0.4.0, y vale la pena mencionar que se espera que las versiones más nuevas muestren un rendimiento aún mejor.
Por qué pgvector supera a las bases de datos vectoriales comerciales
Después de analizar los impresionantes benchmarks de pgvector, es posible que te preguntes cómo se compara con otras soluciones de bases de datos vectoriales comerciales como Milvus. Bueno, veamos:
Facilidad de integración
- Milvus: Opera como un servicio separado, lo que agrega complejidad a tu conjunto de tecnologías.
- pgvector: Se integra de manera perfecta con PostgreSQL, simplificando tu conjunto de tecnologías.
Sincronización de datos
- Milvus: Carece de integración nativa, lo que lleva a problemas de sincronización de datos.
- pgvector: Ofrece integración nativa, eliminando los problemas de sincronización.
Métricas de rendimiento
- Milvus: Lucha para igualar el rendimiento de pgvector.
- pgvector: Maneja 1 millón de embeddings de OpenAI a 1800 QPS con una tasa de precisión del 91%.
Métrica | Milvus | pgvector |
---|---|---|
Complejidad de Integración | Alta | Baja |
Sincronización de Datos | Problemática | Sin Problemas |
Velocidad de Consulta (QPS) | Más Baja | 1800 |
Exactitud | Más Baja | 91% |
En resumen, si estás buscando una solución eficiente, optimizada y de alto rendimiento para el almacenamiento y búsqueda de vectores, pgvector es la clara ganadora.
Consejos para optimizar el rendimiento de pgvector
- Ajusta la configuración de tu Postgres: Asegúrate de que coincida con la RAM y los núcleos de tu CPU.
- Pre-calienta tu base de datos: Utiliza la técnica de precalentamiento descrita anteriormente.
- Elige la función de distancia correcta: Si tus vectores están normalizados, prefiere el producto interno en lugar de las distancias L2 o coseno.
- Ajusta la constante de listas: Aumentar esto puede acelerar tus consultas. Por ejemplo, las pruebas con incrustaciones de OpenAI utilizaron una constante de listas de 2000 en lugar de los 1000 sugeridos.
Al observar estas métricas detalladas y consejos, queda claro que pgvector ofrece un rendimiento sólido para el almacenamiento de vectores y la búsqueda de similitudes, lo que lo convierte en una opción principal para los usuarios de PostgreSQL.
Qué puedes hacer con pgvector?
Cómo utilizar pgvector como una base de datos de vectores de código abierto
Pgvector no es solo una extensión; es una herramienta transformadora que convierte tu base de datos PostgreSQL en una potente base de datos de vectores. Esto es particularmente útil para aquellos que buscan realizar operaciones complejas en datos de alta dimensión sin tener que cambiar a una base de datos especializada. En esta sección, profundizaremos en cómo configurar y utilizar pgvector como una base de datos de vectores de código abierto.
Instalación y configuración:
- Clona el repositorio: Comienza clonando el repositorio de GitHub de pgvector en tu máquina local.
git clone https://github.com/your/pgvector/repo.git
- Compila e instala: Navega hasta el directorio y compila la extensión.
cd pgvector
make
make install
- Configuración de la base de datos: Inicia sesión en tu base de datos PostgreSQL y crea la extensión pgvector.
CREATE EXTENSION pgvector;
- Creación de la tabla: Crea una tabla con una columna de vector para almacenar tus datos de alta dimensión.
CREATE TABLE my_vectors (id SERIAL PRIMARY KEY, vector_field VECTOR(128));
Operaciones básicas:
- Inserción de vectores: Inserta datos en el campo de vector.
INSERT INTO my_vectors (vector_field) VALUES ('{1.1, 2.2, 3.3, ..., 128.128}');
- Búsqueda de vectores: Realiza una búsqueda de similitud utilizando el campo de vector.
SELECT * FROM my_vectors ORDER BY vector_field <-> '{3.3, 2.2, 1.1, ..., 128.128}' LIMIT 10;
- Indexación: Crea un índice para acelerar tus búsquedas de similitud.
CREATE INDEX idx_vector_field ON my_vectors USING ivfflat(vector_field);
Funciones avanzadas:
- Ajuste de parámetros: Puedes ajustar los parámetros de tu índice para equilibrar entre velocidad y precisión.
SET pgvector.index_type = 'hnsw';
SET pgvector.ef_search = 64;
-
Operaciones por lotes: Pgvector admite operaciones por lotes para insertar y actualizar vectores, lo cual puede ser especialmente útil para aplicaciones de aprendizaje automático.
-
Monitoreo y observabilidad: Utiliza las herramientas de monitoreo incorporadas de PostgreSQL para vigilar el rendimiento de tus operaciones de vectores.
Capacidades de búsqueda k-NN de pgvector
¿Qué es la búsqueda k-NN?
La búsqueda k-NN (k-Nearest Neighbors) es un algoritmo utilizado para encontrar los "k" puntos más cercanos a un punto dado en un espacio multidimensional. Se utiliza ampliamente en el aprendizaje automático para la clasificación y agrupación.
Cómo pgvector habilita k-NN:
- Tipo de datos: pgvector introduce un nuevo tipo de datos llamado
vector
, que puede almacenar datos multidimensionales. - Operadores: Proporciona operadores como
<->
para la distancia euclidiana y<=>
para la distancia del coseno para calcular la similitud entre vectores. - Indexación: Puedes crear índices en las columnas de vectores para acelerar las consultas k-NN.
Aquí tienes una función SQL que realiza una búsqueda k-NN utilizando pgvector:
CREATE OR REPLACE FUNCTION knn_search(query_vector vector, k int)
RETURNS TABLE(id INT, distance FLOAT)
LANGUAGE SQL STABLE AS $$
SELECT id, query_vector <=> vector_column AS distance
FROM your_table
ORDER BY distance ASC
LIMIT k;
$$;
Almacenar incrustaciones de OpenAI con pgvector
¿Por qué almacenar incrustaciones de OpenAI? Las incrustaciones de OpenAI son vectores de alta dimensión que capturan el significado semántico del texto. Son útiles para tareas como la similitud de texto, agrupación y clasificación.
Cómo almacenar incrustaciones de OpenAI con pgvector
- Crear una tabla: Crea una tabla de PostgreSQL con una columna de tipo
vector
.
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT,
embedding VECTOR(1536)
);
- Insertar datos: Inserta las incrustaciones de OpenAI en la columna
embedding
.
INSERT INTO documents(content, embedding) VALUES ('some text', '{your 1536-dim vector}');
- Consulta: Utiliza los operadores de pgvector para consultar las incrustaciones.
SELECT * FROM documents WHERE embedding <=> '{query vector}' < 0.5;
PGVector con Langchain: Búsqueda de texto avanzada
Langchain y PGVector se pueden combinar para crear un potente sistema de búsqueda y recuperación de texto. A continuación, se muestra una guía sobre cómo integrar PGVector con Langchain para realizar operaciones de búsqueda de texto avanzadas.
Pre-requisitos
- Asegúrate de haber instalado todos los paquetes necesarios y configurado tus variables de entorno como se muestra en la sección inicial de tu cuaderno.
Paso 1. Inicializa los componentes de Langchain
En primer lugar, inicializa los componentes de Langchain como OpenAIEmbeddings
, TextLoader
y CharacterTextSplitter
.
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter
from langchain.document_loaders import TextLoader
loader = TextLoader("your_text_file.txt")
documents = loader.load();
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)
embeddings = OpenAIEmbeddings()
Paso 2. Inicializar PGVector A continuación, inicializar PGVector con la cadena de conexión a tu base de datos de Postgres.
from langchain.vectorstores.pgvector import PGVector
CONNECTION_STRING = "tu_cadena_de_conexión_aquí"
COLLECTION_NAME = "tu_nombre_de_colección_aquí"
db = PGVector.from_documents(
embedding=embeddings,
documents=docs,
collection_name=COLLECTION_NAME,
connection_string=CONNECTION_STRING,
)
** Paso 3. Realizar una búsqueda de similitud**
Ahora puedes realizar una búsqueda de similitud utilizando el método similarity_search_with_score
de PGVector.
query = "Tu consulta de búsqueda aquí"
docs_with_score = db.similarity_search_with_score(query)
for doc, score in docs_with_score:
print("Score: ", score)
print(doc.page_content)
** Paso 4. Búsqueda de Máxima Relevancia Marginal** Para realizar una búsqueda más avanzada, puedes utilizar la Búsqueda de Máxima Relevancia Marginal (MMR) para optimizar tanto la similitud con la consulta como la diversidad entre los documentos seleccionados.
docs_with_score = db.max_marginal_relevance_search_with_score(query)
for doc, score in docs_with_score:
print("Score: ", score)
print(doc.page_content)
Paso 5. Trabajar con VectorStore existente Si ya tienes un VectorStore existente, puedes inicializarlo directamente y agregar documentos.
store = PGVector(
collection_name=COLLECTION_NAME,
connection_string=CONNECTION_STRING,
embedding_function=embeddings,
)
store.add_documents([Document(page_content="nuevo_contenido_aquí")])
** Paso 6. Sobrescribir un VectorStore existente** Si necesitas actualizar una colección existente, puedes sobrescribirla.
db = PGVector.from_documents(
documents=docs,
embedding=embeddings,
collection_name=COLLECTION_NAME,
connection_string=CONNECTION_STRING,
pre_delete_collection=True,
)
** Paso 7. Usar VectorStore como recuperador** Finalmente, puedes utilizar el VectorStore como recuperador para realizar operaciones más avanzadas.
retriever = store.as_retriever()
print(retriever)
Creación de una búsqueda de IA potenciada con Amazon SageMaker, Amazon RDS para PostgreSQL, y pgvector
En esta sección, demostraremos cómo construir una solución de búsqueda de similitud de catálogo de productos utilizando Amazon SageMaker y Amazon RDS para PostgreSQL con la extensión pgvector. Utilizaremos un modelo pre-entrenado de Hugging Face para generar vectores de embeddings de documentos y almacenarlos en una base de datos de RDS para PostgreSQL. Luego, utilizaremos las capacidades de búsqueda de similitud de pgvector para encontrar los artículos del catálogo de productos que mejor se ajusten a la consulta de búsqueda de un cliente.
Pasos para implementar la solución:
-
Configurar una instancia de cuaderno de SageMaker: Cree una instancia de cuaderno de SageMaker para ejecutar el código de Python en un cuaderno Jupyter.
-
Preparación de datos: Traduzca las descripciones de los artículos de alemán a inglés utilizando Amazon Translate.
-
Hospedaje de modelos: Despliegue un modelo pre-entrenado de Hugging Face en SageMaker para generar vectores de embeddings de 384 dimensiones para el catálogo de productos.
-
Almacenamiento de datos: Conéctese a RDS para PostgreSQL y cree una tabla para almacenar el texto en bruto y los embeddings de texto.
-
Inferencia en tiempo real: Utilice SageMaker para codificar el texto de consulta en embeddings.
-
Búsqueda de similitud: Realice una búsqueda de similitud utilizando pgvector en la base de datos de RDS para PostgreSQL.
Requisitos previos:
- Una cuenta de AWS con permisos IAM adecuados.
- Familiaridad con los servicios de AWS como SageMaker, RDS y CloudFormation.
Implementación: Utilizar una pila de CloudFormation de AWS para implementar la solución, que creará todos los recursos necesarios, incluyendo componentes de redes, una instancia de cuaderno de SageMaker y una instancia de RDS para PostgreSQL.
Aquí tienes algunos fragmentos de código clave para implementar la solución:
- Ingesta de datos: Utilizar Amazon Translate para traducir las descripciones de los artículos de alemán a inglés.
import boto3
translate = boto3.client(service_name='translate', use_ssl=True)
result = translate.translate_text(Text=str(j), SourceLanguageCode="de", TargetLanguageCode="en")
- Hospedaje de modelos: Despliegue un modelo pre-entrenado de Hugging Face en SageMaker.
from sagemaker.huggingface.model import HuggingFaceModel
predictor = HuggingFaceModel(env=hub, role=role).deploy(initial_instance_count=1, instance_type="ml.m5.xlarge")
- Almacenamiento de datos: Cree una tabla en RDS para PostgreSQL para almacenar los embeddings.
CREATE TABLE IF NOT EXISTS products(
id bigserial primary key,
description text,
descriptions_embeddings vector(384)
);
- Búsqueda de similitud: Realice una búsqueda de similitud utilizando pgvector.
SELECT id, url, description, descriptions_embeddings
FROM products
ORDER BY descriptions_embeddings <-> ARRAY[...];
Cómo utilizar PgVector en Python
Ciertamente, puedes ampliar la funcionalidad de pgvector
en Python añadiendo métodos personalizados o integrándolo con otras bibliotecas de Python. A continuación se muestra un ejemplo de cómo podrías ampliar pgvector
para incluir un método para calcular la distancia euclidiana entre dos vectores en Django.
Ampliación de la funcionalidad de Django
Primero, creemos un gestor personalizado para el modelo Item
que incluya un método para calcular la distancia euclidiana.
from django.db import models
from pgvector.django import VectorField, L2Distance
import math
class ItemManager(models.Manager):
def euclidean_distance(self, vector):
# Utilizamos la función L2Distance de pgvector para obtener la distancia euclidiana al cuadrado
queryset = self.annotate(distance_squared=L2Distance('embedding', vector))
# Tomamos la raíz cuadrada para obtener la distancia euclidiana real
for item in queryset:
item.distance = math.sqrt(item.distance_squared)
return queryset
class Item(models.Model):
embedding = VectorField(dimensions=3)
objects = ItemManager()
Ahora puedes usar este administrador personalizado en tus vistas o en la consola de Django:
```python
# Obtener elementos ordenados por su distancia euclidiana con respecto al vector [3, 1, 2]
items = Item.objects.euclidean_distance([3, 1, 2]).order_by('distance')
# Imprimir los elementos y sus distancias
for item in items:
print(f"ID del elemento: {item.id}, Distancia: {item.distance}")
Ampliar la funcionalidad de SQLAlchemy
De manera similar, puedes ampliar la funcionalidad de SQLAlchemy agregando una clase de consulta personalizada.
from sqlalchemy import Column, Integer, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, BaseQuery
from sqlalchemy.sql import func
from pgvector.sqlalchemy import Vector
Base = declarative_base()
class VectorQuery(BaseQuery):
def euclidean_distance(self, vector):
return self.add_columns(
func.sqrt(
func.pow(Vector.l2_distance(self._entities[0].field, vector), 2)
).label('distance')
)
class Item(Base):
__tablename__ = 'items'
id = Column(Integer, primary_key=True, autoincrement=True)
embedding = Column(Vector(3))
@classmethod
def query(cls):
return VectorQuery(cls)
# Configuración de la base de datos
engine = create_engine('postgresql://localhost/mydatabase')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
# Obtener elementos y su distancia euclidiana con respecto al vector [3, 1, 2]
items_with_distance = session.query(Item).euclidean_distance([3, 1, 2]).all()
# Imprimir los elementos y sus distancias
for item, distance in items_with_distance:
print(f"ID del elemento: {item.id}, Distancia: {distance}")
En este ejemplo, he agregado un campo "id" a la clase Item como clave primaria. La clase VectorQuery se utiliza para ampliar las capacidades de consulta, agregando un método para calcular la distancia euclidiana. Finalmente, el método de clase "query" se utiliza para establecer esta clase de consulta personalizada para el modelo Item.
Luego puedes usar esto en tu código de SQLAlchemy:
# Obtener elementos y su distancia euclidiana con respecto al vector [3, 1, 2]
items = session.query(Item).euclidean_distance([3, 1, 2]).all()
# Imprimir los elementos y sus distancias
for item, distance in items:
print(f"ID del elemento: {item.id}, Distancia: {distance}")
Conclusión
Pgvector es un cambio de juego si estás utilizando bases de datos PostgreSQL. No es solo un complemento; es como un turbo para tu base de datos. Te permite almacenar y buscar rápidamente grandes conjuntos de datos con precisión. Esto es muy útil para cosas como el aprendizaje automático, donde necesitas buscar rápidamente toneladas de datos.
Además, pgvector se integra perfectamente en PostgreSQL, por lo que no tienes que manejar múltiples bases de datos. También es flexible, lo que te permite elegir cómo quieres medir la "distancia" entre puntos de datos. Incluso puedes ampliar sus características si utilizas frameworks de Python como Django. En resumen, si te interesa los datos y utilizas PostgreSQL, no puedes perderte pgvector.
Preguntas frecuentes
¿Cuál es el uso de Pgvector?
Pgvector es una extensión para bases de datos PostgreSQL que se especializa en almacenar y buscar a través de grandes conjuntos de vectores. Es especialmente útil para aplicaciones que requieren búsquedas de similitud rápidas y precisas, como modelos de aprendizaje automático, sistemas de recomendación y tareas de procesamiento de lenguaje natural.
¿Cuáles son las ventajas de Pgvector?
Pgvector ofrece varios beneficios:
- Velocidad: Permite consultas rápidas, incluso cuando se trata de datos de alta dimensión.
- Eficiencia: Comprime los datos sin perder su integridad, ahorrando espacio de almacenamiento.
- Flexibilidad: Admite múltiples métricas de distancia como Euclidiana, Coseno y Manhattan, lo que te permite elegir la mejor opción para tus necesidades.
- Integración sin problemas: Se integra directamente en PostgreSQL, por lo que no tienes que gestionar múltiples bases de datos.
- Escalabilidad: Funciona bien en varias configuraciones de hardware, garantizando un uso óptimo de los recursos.
¿Es PostgreSQL una base de datos de vectores?
No, PostgreSQL no es inherentemente una base de datos de vectores. Sin embargo, con la extensión Pgvector, puedes convertir eficazmente PostgreSQL en una potente base de datos de vectores capaz de almacenar y realizar búsquedas de similitud en datos de alta dimensión.
¿Cómo utilizar Pgvector en PostgreSQL?
Para utilizar Pgvector en PostgreSQL, debes seguir los siguientes pasos:
- Instalar la extensión Pgvector ejecutando
CREATE EXTENSION pgvector;
en tu base de datos de PostgreSQL. - Crear una tabla con una columna de vector, por ejemplo:
CREATE TABLE my_vectors (id SERIAL PRIMARY KEY, vector_field VECTOR(128));
. - Insertar vectores en la tabla:
INSERT INTO my_vectors (vector_field) VALUES ('{1.1, 2.2, 3.3, ..., 128.128}');
. - Realizar búsquedas de similitud mediante consultas SQL, por ejemplo:
SELECT * FROM my_vectors ORDER BY vector_field <-> '{3.3, 2.2, 1.1, ..., 128.128}' LIMIT 10;
.