Menu iconMenu icon
OpenAI API Biblia Volumen 2

Capítulo 3: Embeddings y Búsqueda Semántica

3.4 Introducción a Pinecone y Otras Bases de Datos Vectoriales

En esta sección, profundizaremos en las bases de datos vectoriales - sistemas especializados diseñados para manejar datos de alta dimensión eficientemente. Estas poderosas herramientas están revolucionando cómo almacenamos y recuperamos representaciones complejas de datos.

Exploraremos tres soluciones líderes que sirven diferentes necesidades:

  • Pinecone: Una solución en la nube totalmente administrada perfecta para aplicaciones empresariales que necesitan manejar millones de vectores con rendimiento consistente
  • Chroma: Una base de datos eficiente y amigable para desarrolladores, ideal para desarrollo local y aplicaciones de menor escala
  • Weaviate: Una opción robusta de código abierto que sobresale en capacidades de búsqueda híbrida

Aprenderás cómo estas bases de datos te permiten:

  • Almacenar y gestionar vastas colecciones de embeddings (representaciones vectoriales de texto, imágenes u otros datos)
  • Realizar búsquedas de similitud ultrarrápidas en conjuntos de datos masivos
  • Escalar tus aplicaciones sin problemas desde prototipo a producción
  • Mantener un rendimiento consistente incluso cuando tus datos crecen

Lo más importante, te mostraremos cómo estas herramientas mantienen tiempos de respuesta y fiabilidad excepcionales mientras operan en entornos en la nube, haciéndolas perfectas para aplicaciones de IA a nivel de producción.

3.4.1 ¿Qué son las Bases de Datos Vectoriales?

Una base de datos vectorial es un sistema especializado diseñado para almacenar y recuperar eficientemente embeddings — representaciones numéricas de alta dimensión de contenido como texto, audio o imágenes. Estos embeddings son esencialmente largas listas de números (vectores) que representan las características y el significado del contenido. Por ejemplo, una sola frase podría convertirse en un vector de 1,536 números, donde cada número captura algún aspecto del significado, tono o estructura de la frase. Estos embeddings capturan el significado semántico del contenido en un formato que las computadoras pueden procesar eficientemente, haciendo posible encontrar contenido similar mediante la comparación de estos patrones numéricos.

Para ilustrar este concepto, imagina cada pieza de contenido como un punto en un vasto espacio multidimensional. El contenido similar aparece más cerca entre sí en este espacio, mientras que el contenido diferente aparece alejado. Por ejemplo, dos artículos sobre "cocinar pasta" tendrían representaciones vectoriales similares y por lo tanto estarían cerca uno del otro en este espacio, mientras que un artículo sobre "física cuántica" estaría ubicado lejos de ellos.

Las bases de datos tradicionales sobresalen en el almacenamiento de datos estructurados, pero tienen dificultades con los desafíos únicos de las operaciones vectoriales. Estos desafíos incluyen encontrar eficientemente los vecinos más cercanos en el espacio de alta dimensión, manejar la complejidad computacional de los cálculos de similitud y gestionar los requisitos de memoria de grandes conjuntos de datos vectoriales. Si bien bibliotecas como FAISS funcionan bien en tu máquina local, no persisten los datos entre sesiones ni escalan fácilmente a millones de vectores. Ahí es donde entran las bases de datos vectoriales, ofreciendo soluciones especializadas para operaciones vectoriales a gran escala. Estas bases de datos están específicamente diseñadas para manejar las complejidades de las matemáticas vectoriales mientras proporcionan la confiabilidad y escalabilidad de los sistemas de bases de datos tradicionales.

Estos sistemas sofisticados proporcionan varias capacidades cruciales que los hacen indispensables para las aplicaciones modernas de IA:

  • Almacenar y gestionar miles de millones de embeddings con estructuras de almacenamiento optimizadas diseñadas específicamente para datos vectoriales de alta dimensión. Estas estructuras utilizan técnicas avanzadas de compresión y asignación eficiente de memoria para manejar cantidades masivas de datos vectoriales mientras mantienen tiempos de acceso rápidos.
  • Admiten búsqueda vectorial en tiempo real con filtros, utilizando técnicas avanzadas de indexación como grafos HNSW (Hierarchical Navigable Small World). Estos grafos crean múltiples capas de conexiones entre vectores, permitiendo que el sistema navegue rápidamente a través del espacio vectorial y encuentre elementos similares en microsegundos, incluso cuando se trata de miles de millones de vectores. La capacidad de filtrado permite combinar consultas de bases de datos tradicionales con búsqueda de similitud vectorial.
  • Se integran perfectamente con APIs y servicios en la nube, ofreciendo arquitectura distribuida para alta disponibilidad y escalado automático. Esto significa que tu base de datos vectorial puede manejar automáticamente cargas de trabajo crecientes distribuyendo datos entre múltiples servidores, asegurando un rendimiento consistente incluso durante momentos de uso máximo. La arquitectura nativa en la nube también proporciona redundancia y tolerancia a fallos incorporadas.
  • Permiten combinar metadatos + similitud vectorial para consultas más inteligentes, habilitando filtrado y clasificación sofisticados basados tanto en similitud semántica como en criterios tradicionales de bases de datos. Por ejemplo, puedes buscar documentos que sean semánticamente similares a una consulta mientras filtras por rango de fechas, categoría o cualquier otro campo de metadatos. Este enfoque híbrido proporciona resultados de búsqueda más precisos y relevantes.
  • Garantizan la persistencia y consistencia de datos a través de múltiples sesiones y usuarios, haciéndolas adecuadas para entornos de producción. A diferencia de las soluciones en memoria, las bases de datos vectoriales proporcionan cumplimiento ACID (Atomicidad, Consistencia, Aislamiento, Durabilidad) y soporte de transacciones, asegurando que tus datos permanezcan confiables y consistentes incluso en caso de fallos del sistema o acceso concurrente.

Principales actores de un vistazo



3.4.2 Eligiendo la base de datos vectorial adecuada: Pinecone, Chroma o Weaviate

Cada base de datos vectorial tiene sus características únicas y casos de uso especializados. Explorémoslas en detalle:

Pinecone

  • Mejor para: Aplicaciones de producción a gran escala que exigen alta disponibilidad consistente y rendimiento superior. Esto lo hace particularmente adecuado para empresas que manejan millones de consultas por día, especialmente aquellas que ejecutan aplicaciones de IA críticas como sistemas de recomendación en tiempo real, plataformas de moderación de contenido o servicios de búsqueda a gran escala.
  • Ventajas: Como servicio en la nube totalmente administrado, Pinecone elimina las complejidades de infraestructura al manejar todas las operaciones backend. Su red de distribución global asegura una latencia mínima independientemente de la ubicación del usuario, mientras que el escalado automático ajusta los recursos según la demanda, desde manejar unos pocos miles hasta millones de consultas. La plataforma incluye características de seguridad de nivel empresarial como cumplimiento SOC 2, cifrado en reposo y en tránsito, y control de acceso basado en roles (RBAC) para la gestión de equipos.
  • Usar cuando: Tu aplicación requiere confiabilidad de nivel profesional y rendimiento consistente, particularmente en entornos de alta exigencia donde el tiempo de inactividad podría ser costoso. Si bien viene con un precio premium, la inversión se justifica para empresas que necesitan tiempo de actividad garantizado, tiempos de consulta predecibles y soporte de nivel empresarial. Es especialmente valioso para entornos de producción que manejan datos sensibles o sirven a una base de usuarios global donde la confiabilidad del sistema impacta directamente en las operaciones comerciales.

Chroma

  • Mejor para: Entornos de desarrollo, proyectos de prueba de concepto y aplicaciones más pequeñas que no requieren escala masiva. Es particularmente adecuado para investigadores y desarrolladores que trabajan en prototipos de IA, experimentos de ciencia de datos y flujos de trabajo de desarrollo local. Su naturaleza ligera lo hace perfecto para prototipado rápido y pruebas de diferentes enfoques de embeddings sin la sobrecarga de infraestructura en la nube.
  • Ventajas: Chroma ofrece un proceso de configuración extremadamente simple que puede completarse en minutos - solo pip install y estás listo para comenzar. Su integración nativa con Python significa una integración perfecta con herramientas populares de ciencia de datos y ML como pandas, numpy y scikit-learn. Al ser completamente gratuito y de código abierto, permite experimentación ilimitada sin preocupaciones de costos. Los requisitos mínimos de recursos significan que puede funcionar eficientemente incluso en hardware modesto. Además, incluye soporte integrado para modelos de embeddings populares de OpenAI, Cohere y otros proveedores, facilitando la experimentación con diferentes estrategias de embeddings.
  • Usar cuando: Estás desarrollando localmente y necesitas ciclos rápidos de iteración para probar diferentes enfoques. Es ideal para entornos educativos donde los estudiantes están aprendiendo sobre embeddings y búsqueda vectorial. Perfecto para construir aplicaciones autocontenidas sin dependencias externas, especialmente cuando quieres evitar la complejidad y el costo de los servicios en la nube. Chroma brilla en escenarios donde necesitas prototipar rápidamente y validar características basadas en embeddings antes de pasar a un entorno de producción. También es excelente para proyectos de investigación donde necesitas control completo sobre el pipeline de embeddings y quieres experimentar con diferentes configuraciones.

Weaviate

  • Ideal para: Aplicaciones que necesitan funcionalidad de búsqueda sofisticada combinando búsqueda tradicional por palabras clave con similitud vectorial. Este enfoque dual lo hace particularmente potente para sistemas de gestión de contenido, plataformas de comercio electrónico y aplicaciones de búsqueda avanzada donde los usuarios pueden combinar consultas en lenguaje natural con criterios específicos de filtrado. Sus capacidades de búsqueda híbrida sobresalen en escenarios donde las coincidencias exactas y la comprensión semántica necesitan trabajar juntas de manera fluida.
  • Ventajas: Como solución de código abierto, Weaviate ofrece flexibilidad y opciones de personalización sin igual. Sus potentes capacidades de diseño de esquemas permiten a los desarrolladores definir estructuras de datos complejas con propiedades personalizadas, relaciones y reglas de validación. La plataforma admite múltiples paradigmas de búsqueda, incluyendo búsqueda semántica para comprender el significado de las consultas, búsqueda tradicional por palabras clave para coincidencias exactas, y búsqueda híbrida que combina inteligentemente ambos enfoques. Además, ofrece opciones de implementación tanto en la nube como autoalojadas, dando a las organizaciones control completo sobre sus datos e infraestructura.
  • Usar cuando: Tu proyecto requiere la sofisticación tanto de búsqueda por similitud vectorial como características de búsqueda tradicional en una plataforma unificada. Es particularmente valioso para organizaciones que construyen sistemas complejos de gestión del conocimiento, interfaces de búsqueda avanzada o motores de recomendación de contenido. La plataforma destaca en escenarios que requieren control granular sobre la estructura de datos, comportamiento de búsqueda personalizado y requisitos específicos de implementación. Su flexibilidad lo hace ideal para equipos que necesitan ajustar su arquitectura de búsqueda para cumplir con requisitos comerciales únicos.

3.4.3 Pinecone

Pinecone es una sofisticada solución en la nube totalmente administrada, diseñada específicamente para operaciones vectoriales a escala empresarial. En su núcleo, Pinecone utiliza algoritmos avanzados de indexación y arquitectura de computación distribuida para manejar operaciones vectoriales con notable eficiencia. El sistema sobresale en la gestión de millones de vectores de alta dimensionalidad - piensa en estos como representaciones matemáticas complejas de texto, imágenes u otros datos - mientras mantiene un rendimiento consistente de baja latencia, típicamente respondiendo en milisegundos.

Su arquitectura distribuida es particularmente notable, empleando un sofisticado mecanismo de fragmentación que distribuye los datos entre múltiples nodos. Esto garantiza operaciones de búsqueda confiables en conjuntos de datos masivos, con redundancia incorporada y mecanismos automáticos de recuperación ante fallos. Esta robusta infraestructura la hace ideal para:

  • Sistemas de recomendación a gran escala - Estos sistemas procesan millones de interacciones de usuarios en tiempo real y características de productos para entregar recomendaciones personalizadas. Por ejemplo, una plataforma de comercio electrónico podría analizar el historial de navegación, patrones de compra y atributos de productos de millones de usuarios para sugerir artículos relevantes instantáneamente.
  • Plataformas de descubrimiento de contenido - Estas plataformas utilizan algoritmos sofisticados para emparejar contenido a través de vastas bibliotecas multimedia, analizando metadatos, preferencias de usuarios y características de contenido. Pueden procesar contenido multimedia como videos, artículos y música para conectar a los usuarios con contenido relevante que podrían disfrutar, manejando bibliotecas con petabytes de datos.
  • Aplicaciones de búsqueda semántica - Estas aplicaciones comprenden el contexto y significado detrás de las consultas de búsqueda, no solo palabras clave. Entregan resultados altamente relevantes en milisegundos comparando el significado semántico de la consulta contra millones de documentos, teniendo en cuenta matices, sinónimos y conceptos relacionados.
  • Soluciones de servicio al cliente impulsadas por IA - Estos sistemas revolucionan el soporte al cliente al acceder y analizar instantáneamente vastas bases de datos de documentación de soporte, interacciones previas con clientes e información de productos. Pueden comprender las consultas de los clientes en contexto y proporcionar soluciones relevantes procesando datos históricos que abarcan años de interacciones con clientes.

Lo que verdaderamente distingue a Pinecone es su excepcional optimización del rendimiento. La plataforma mantiene tiempos de consulta inferiores al segundo incluso cuando su base de datos vectorial escala a miles de millones de entradas - una hazaña lograda a través de sofisticadas técnicas de indexación como grafos HNSW (Hierarchical Navigable Small World) y particionamiento eficiente de datos. Esto se complementa con características de nivel empresarial que incluyen:

  • Escalado horizontal automático que responde a cargas de trabajo variables
  • Alta disponibilidad a través de implementación multi-región
  • Medidas robustas de seguridad incluyendo cifrado en reposo y en tránsito
  • Capacidades avanzadas de monitoreo y registro
  • Sistemas automáticos de respaldo y recuperación ante desastres

3.4.4 Caso de Uso: Búsqueda Semántica con Pinecone

Ahora veamos cómo integrar embeddings de OpenAI con Pinecone para realizar búsqueda semántica en la nube.

Este código demuestra cómo realizar búsqueda semántica usando OpenAI y Pinecone. La búsqueda semántica va más allá de la coincidencia de palabras clave al comprender el significado de la consulta y los documentos. Utiliza OpenAI para generar embeddings (representaciones numéricas) de texto, y Pinecone, una base de datos vectorial, para almacenar y buscar eficientemente estos embeddings.

Desglose del Código

Aquí hay una explicación paso a paso del código:

Paso 1: Importar Bibliotecas

import openai
import pinecone
import os
from dotenv import load_dotenv
import time  # For exponential backoff
  • openai: Para interactuar con la API de OpenAI y generar embeddings.
  • pinecone: Para interactuar con la base de datos vectorial Pinecone.
  • os: Para acceder a las variables de entorno.
  • dotenv: Para cargar variables de entorno desde un archivo .env.
  • time: Para implementar retroceso exponencial en caso de errores de API.

Paso 2: Cargar Variables de Entorno e Inicializar Clientes

load_dotenv()

# API keys
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
PINECONE_API_KEY = os.getenv("PINECONE_API_KEY")
PINECONE_ENV = os.getenv("PINECONE_ENV")  # e.g., "gcp-starter"

openai.api_key = OPENAI_API_KEY

pinecone.init(
    api_key=PINECONE_API_KEY,
    environment=PINECONE_ENV
)
  • load_dotenv(): Carga variables de entorno desde un archivo .env. Aquí es donde almacenas tus claves API de OpenAI y Pinecone.
  • os.getenv(): Obtiene las claves API y el entorno de Pinecone desde las variables de entorno.
  • El código luego inicializa el cliente de OpenAI con la clave API de OpenAI y el cliente de Pinecone con la clave API y el entorno de Pinecone.

Paso 3: Definir Configuración del Índice de Pinecone

# Pinecone index configuration
INDEX_NAME = "semantic-search-index"
EMBEDDING_MODEL = "text-embedding-3-small"
EMBEDDING_DIMENSION = 1536
SIMILARITY_METRIC = "cosine"
BATCH_SIZE = 100  # Batch size for upserting vectors
  • INDEX_NAME: El nombre del índice de Pinecone.
  • EMBEDDING_MODEL: El modelo de OpenAI utilizado para generar embeddings.
  • EMBEDDING_DIMENSION: La dimensionalidad de los embeddings (1536 para text-embedding-3-small).
  • SIMILARITY_METRIC: La métrica utilizada para medir la similitud entre embeddings (similitud del coseno).
  • BATCH_SIZE: El número de vectores a insertar en Pinecone a la vez.

Paso 4: Función Auxiliar: get_embedding()

def get_embedding(text, model=EMBEDDING_MODEL):
    """Gets the embedding for a given text using OpenAI's API with retry logic."""
    max_retries = 3
    for attempt in range(max_retries):
        try:
            response = openai.Embedding.create(input=text, model=model)
            return response["data"][0]["embedding"]
        except openai.APIError as e:
            print(f"OpenAI API error: {e}")
            if attempt < max_retries - 1:
                time.sleep(2 ** attempt)  # Exponential backoff
            else:
                raise  # Raise the exception if all retries fail
        except Exception as e:
            print(f"Error getting embedding: {e}")
            raise
  • Esta función toma un texto como entrada y devuelve su vector de embedding utilizando la API de OpenAI.
  • Incluye manejo de errores con retroceso exponencial para gestionar posibles errores de la API. Si ocurre un error en la API de OpenAI, reintenta la solicitud hasta max_retries veces, esperando más tiempo entre cada intento.

Paso 5: Función Auxiliar: upsert_embeddings()

def upsert_embeddings(index, documents, batch_size=BATCH_SIZE):
    """Upserts embeddings for a list of documents into Pinecone with batching."""
    vectors = []
    for doc_id, text in documents.items():
        embedding = get_embedding(text)
        vectors.append((doc_id, embedding, {"text": text}))

    for i in range(0, len(vectors), batch_size):
        batch = vectors[i:i + batch_size]
        try:
            index.upsert(vectors=batch)
            print(f"✅ Upserted batch {i // batch_size + 1}/{len(vectors) // batch_size + 1}")
        except pinecone.PineconeException as e:
            print(f"Error upserting batch: {e}")
            raise
  • Esta función toma como entrada un índice de Pinecone, un diccionario de documentos y un tamaño de lote.
  • Genera embeddings para cada documento usando la función get_embedding().
  • Prepara los datos en el formato que espera el método upsert() de Pinecone: una lista de tuplas, donde cada tupla contiene el ID del documento, el vector de embedding y metadatos (en este caso, el texto original).
  • Luego inserta los vectores en Pinecone en lotes, según el batch_size. El procesamiento por lotes es más eficiente para cargar grandes cantidades de datos a Pinecone.

Paso 6: Función Auxiliar: query_pinecone()

def query_pinecone(index, query_text, top_k=2):
    """Queries Pinecone with a given query text and returns the top-k results."""
    query_embedding = get_embedding(query_text)
    try:
        results = index.query(vector=query_embedding, top_k=top_k, include_metadata=True)
        return results
    except pinecone.PineconeException as e:
        print(f"Error querying Pinecone: {e}")
        raise
  • Esta función toma un índice de Pinecone, un texto de consulta y el número de resultados a devolver (top_k).
  • Genera el embedding para el texto de consulta usando get_embedding().
  • Consulta el índice de Pinecone usando el embedding de la consulta, solicitando los top_k vectores más similares. include_metadata=True asegura que también se devuelva el texto original de los documentos coincidentes.
  • Maneja posibles errores de Pinecone.

Paso 7: Función Principal

def main():
    """Main function to perform semantic search with Pinecone and OpenAI."""
    openai.api_key = OPENAI_API_KEY

    pinecone.init(
        api_key=PINECONE_API_KEY,
        environment=PINECONE_ENV
    )

    # Create Pinecone index if it doesn't exist
    if INDEX_NAME not in pinecone.list_indexes():
        try:
            pinecone.create_index(
                name=INDEX_NAME,
                dimension=EMBEDDING_DIMENSION,
                metric=SIMILARITY_METRIC
            )
            print(f"✅ Created Pinecone index: {INDEX_NAME}")
        except pinecone.PineconeException as e:
            print(f"Error creating Pinecone index: {e}")
            return

    index = pinecone.Index(INDEX_NAME)

    # Documents to embed and store in Pinecone
    documents = {
        "doc1": "How to reset your password",
        "doc2": "Updating your billing information",
        "doc3": "Steps to cancel your subscription",
    }

    # Upsert documents into Pinecone
    upsert_embeddings(index, documents)

    # Query Pinecone with a user question
    query_text = "How do I change my payment method?"
    results = query_pinecone(index, query_text)

    # Print the search results
    print("\nSearch Results:")
    for match in results["matches"]:
        print(f"📄 Match: {match['metadata']['text']} (Score: {round(match['score'], 3)})")

    pinecone.deinit()  # Clean up Pinecone connection

if __name__ == "__main__":
    main()
  • Esta es la función principal que orquesta el proceso de búsqueda semántica.
  • Inicializa los clientes de OpenAI y Pinecone.
  • Crea el índice de Pinecone si aún no existe.
  • Define un conjunto de documentos de muestra para indexar.
  • Llama a upsert_embeddings() para almacenar los embeddings de documentos en Pinecone.
  • Define una consulta y llama a query_pinecone() para realizar la búsqueda.
  • Imprime los resultados de la búsqueda, incluyendo los documentos coincidentes y sus puntajes de similitud.
  • Llama a pinecone.deinit() para limpiar la conexión de Pinecone.
  • El bloque if __name__ == "__main__": asegura que la función main() se ejecute cuando se ejecuta el script.

3.4.5 Chroma

Chroma es una base de datos vectorial sofisticada y amigable para desarrolladores, específicamente diseñada para operaciones eficientes de almacenamiento y recuperación de embeddings. Lo que la distingue es su rendimiento excepcional en entornos de desarrollo local y aplicaciones de menor escala, gracias a su arquitectura ligera y proceso de configuración simplificado. A diferencia de soluciones más complejas, Chroma prioriza la experiencia del desarrollador sin sacrificar funcionalidad.

La base de datos ofrece varias características y capacidades poderosas que la hacen destacar:

  • Fácil integración con frameworks populares de ML
    • Proporciona soporte integral para las principales bibliotecas de aprendizaje automático, incluyendo PyTorch, TensorFlow y scikit-learn, permitiendo una integración fluida con pipelines de ML existentes
    • Presenta un diseño de API intuitivo que reduce significativamente el tiempo y la complejidad del desarrollo, haciéndola accesible tanto para principiantes como para desarrolladores experimentados
    • Incluye documentación extensa y ejemplos de código para ayudar a los desarrolladores a comenzar rápidamente
  • Soporte incorporado para múltiples modelos de embedding
    • Ofrece compatibilidad inmediata con proveedores líderes de embeddings como OpenAI, Hugging Face y Sentence Transformers, permitiendo diversas opciones de modelos
    • Implementa una arquitectura flexible que permite a los desarrolladores cambiar fácilmente entre diferentes modelos de embedding sin requerir modificaciones extensas del código
    • Admite funciones de embedding personalizadas para casos de uso especializados
  • Opciones robustas de almacenamiento persistente para durabilidad de datos
    • Soporta varios backends de almacenamiento incluyendo SQLite para desarrollo local y PostgreSQL para entornos de producción, asegurando la persistencia de datos en diferentes escalas
    • Presenta mecanismos sofisticados de recuperación de datos que protegen contra pérdida de datos y fallos del sistema
    • Implementa estrategias eficientes de indexación para un rendimiento óptimo de consultas
  • Requisitos mínimos de recursos, perfecta para prototipado
    • Gestión optimizada de memoria asegura una utilización eficiente de recursos, haciéndola adecuada para máquinas de desarrollo
    • Tiempos de inicio rápidos permiten ciclos rápidos de desarrollo y pruebas
    • Elimina la necesidad de servicios externos complejos o infraestructura, reduciendo la complejidad y costos de implementación

Si bien Chroma puede no igualar la escalabilidad de soluciones basadas en la nube como Pinecone al manejar conjuntos de datos masivos (típicamente aquellos que exceden millones de vectores), su simplicidad y capacidades de desarrollo rápido la convierten en una excelente opción para desarrolladores que construyen pruebas de concepto o aplicaciones con requisitos moderados de datos. La base de datos es particularmente adecuada para proyectos que necesitan ciclos rápidos de iteración, desarrollo y pruebas locales, o implementación en entornos donde los servicios en la nube podrían no estar fácilmente disponibles o ser rentables.

3.4.6 Usando Chroma para Proyectos Locales

Este ejemplo demuestra cómo realizar búsqueda semántica usando Chroma, una base de datos vectorial local y ligera. Al igual que el ejemplo de Pinecone, utiliza embeddings para capturar el significado del texto, pero Chroma está específicamente diseñada para casos de uso locales.

Desglose del Código

Aquí hay una explicación paso a paso del código:

Paso 1: Instalar Biblioteca

pip install chromadb
  • Este comando instala la biblioteca chromadb, que proporciona las herramientas necesarias para trabajar con la base de datos vectorial Chroma.

Paso 2: Importar Bibliotecas

import chromadb
from chromadb.utils.embedding_functions import OpenAIEmbeddingFunction
import os
from dotenv import load_dotenv

load_dotenv()
  • chromadb: La biblioteca principal de Chroma.
  • OpenAIEmbeddingFunction: Una función de utilidad de Chroma para usar la API de OpenAI en la generación de embeddings.
  • os: Para acceder a las variables de entorno (para obtener la clave API de OpenAI).
  • dotenv: Para cargar variables de entorno desde un archivo .env.

Paso 3: Inicializar el Cliente de Chroma

client = chromadb.Client()
  • Esta línea crea un objeto cliente de Chroma. En la configuración predeterminada, Chroma se ejecuta localmente.

Paso 4: Crear una Colección

collection = client.create_collection(name="my_embeddings")
  • Esto crea una colección en Chroma. Una colección es similar a un índice en Pinecone; es donde almacenas y consultas tus embeddings. La colección se llama "my_embeddings".

Paso 5: Inicializar la Función de Embedding de OpenAI

embedding_function = OpenAIEmbeddingFunction(api_key=os.getenv("OPENAI_API_KEY"))
  • Esto crea una instancia de OpenAIEmbeddingFunction, que se utilizará para generar embeddings usando la API de OpenAI. Obtiene la clave API de OpenAI desde las variables de entorno.

Paso 6: Agregar Documentos a la Colección

collection.add(
    documents=["Learn how to train a model", "Understanding neural networks"],
    ids=["doc1", "doc2"]
)
  • Esto agrega documentos y sus IDs correspondientes a la colección "my_embeddings".
    • documents: Una lista de documentos de texto.
    • ids: Una lista de identificadores únicos para cada documento. Chroma usa estos IDs para rastrear los vectores. El orden de los ids debe corresponder al orden de los documents.
  • Entre bastidores, Chroma utiliza la embedding_function (la función de embedding de OpenAI) para generar embeddings para los documentos proporcionados. Estos embeddings se almacenan en la colección junto con los documentos e IDs.

Paso 7: Realizar una Consulta

query = "How do I build an AI model?"
results = collection.query(query_texts=[query], n_results=1)
print("🔍 Best Match:", results["documents"][0][0])
  • query: El texto de la consulta.
  • collection.query(): Esto realiza la búsqueda.
    • query_texts: Una lista que contiene el texto de la consulta. Incluso si solo estás consultando un fragmento de texto, Chroma espera una lista.
    • n_results: El número de vecinos más cercanos (documentos más similares) a recuperar. Aquí, está configurado en 1, por lo que recupera la única mejor coincidencia.
  • El código luego imprime el texto del documento con mejor coincidencia. results["documents"] es una lista de listas. La lista exterior corresponde a las consultas (en este caso, una sola consulta), y la lista interior contiene los documentos.

3.4.7 Weaviate

Weaviate es una potente base de datos vectorial de código abierto que combina la búsqueda tradicional basada en palabras clave con la búsqueda por similitud vectorial de una manera única. A diferencia de las bases de datos vectoriales simples que solo realizan coincidencias por similitud, las capacidades de búsqueda híbrida de Weaviate le permiten comprender simultáneamente tanto las palabras exactas (palabras clave) como el significado subyacente (semántica) de una consulta. Este enfoque dual significa que puede manejar consultas complejas como "Encontrar documentos sobre aprendizaje automático que mencionen programación en Python" combinando tanto la comprensión semántica como la coincidencia específica de palabras clave.

Lo que distingue a Weaviate es su arquitectura integral. Ofrece múltiples formas de interactuar con la base de datos: GraphQL para consultas flexibles y estructuradas; APIs RESTful para integración web tradicional; y soporte para varios modelos de aprendizaje automático que se pueden conectar según tus necesidades. Esta flexibilidad significa que los desarrolladores pueden elegir el enfoque más apropiado para su caso de uso específico.

La plataforma incluye varias características poderosas que revolucionan cómo trabajamos con bases de datos vectoriales:

  • Gestión Automática de Esquemas
    • Inferencia Inteligente de Esquemas: La IA de Weaviate analiza los patrones de tu conjunto de datos y recomienda automáticamente estructuras de datos óptimas, ahorrando horas de configuración manual
    • Organización Inteligente de Datos: Utiliza algoritmos avanzados para categorizar, etiquetar y estructurar automáticamente tus datos basándose en similitudes y relaciones de contenido
    • Evolución Dinámica de Esquemas: Adapta tu estructura de datos sobre la marcha a medida que tu aplicación crece, sin tiempo de inactividad ni dolores de cabeza por migración de datos
  • Procesamiento Avanzado en Tiempo Real
    • Indexación Instantánea: A diferencia de las bases de datos tradicionales que requieren procesamiento por lotes, Weaviate indexa nuevos datos en el momento en que llegan
    • Disponibilidad sin Latencia: Los nuevos datos se pueden buscar inmediatamente, perfecto para aplicaciones que requieren actualizaciones en tiempo real
    • Sincronización Continua: Los resultados de búsqueda incorporan automáticamente nuevos datos, asegurando que los usuarios siempre vean la información más actualizada
  • Capacidades Multimodales Integrales
    • Comprensión Avanzada de Texto: Utiliza modelos de PNL de última generación para comprender el contexto, el sentimiento y las relaciones semánticas en datos de texto
    • Análisis Sofisticado de Imágenes: Implementa algoritmos de visión por computadora para búsqueda de similitud visual, detección de objetos y clasificación de imágenes
    • Sistema de Tipos Extensible: Construye tipos de datos personalizados con lógica de procesamiento especializada para tus casos de uso únicos, desde procesamiento de audio hasta análisis de datos científicos

3.4.8 Búsqueda Semántica usando Weaviate

Este caso de uso demuestra cómo realizar búsqueda semántica usando Weaviate. La búsqueda semántica mejora la búsqueda tradicional basada en palabras clave al comprender el significado de las consultas y documentos, devolviendo resultados más relevantes. Weaviate almacena objetos de datos y sus embeddings vectoriales correspondientes, permitiendo una recuperación eficiente basada en similitud. Este ejemplo usa OpenAI para generar los embeddings.

Paso 1: Instalar Bibliotecas Requeridas

pip install weaviate-client
  • Este comando instala la biblioteca weaviate-client, que proporciona el cliente de Python para interactuar con Weaviate.

Paso 2: Configurar el Cliente de Weaviate

import weaviate
import os
from dotenv import load_dotenv

load_dotenv()  # Load environment variables

client = weaviate.Client(
    url=os.getenv("WEAVIATE_URL"),  # Replace with your Weaviate URL
    #   auth_client_secret=weaviate.auth.AuthApiKey(api_key=os.getenv("WEAVIATE_API_KEY")) #Uncomment if you are using an API key.
)
  • import weaviate: Importa la biblioteca cliente de Weaviate.
  • import os: Importa el módulo os para acceder a las variables de entorno.
  • from dotenv import load_dotenv: Importa la función load_dotenv de la biblioteca dotenv para cargar variables de entorno desde un archivo .env.
  • load_dotenv(): Carga las variables de entorno desde un archivo .env. Aquí es donde debes almacenar tu URL de Weaviate (y la clave API, si corresponde).
  • client = weaviate.Client(...): Inicializa una instancia del cliente de Weaviate, estableciendo una conexión con el servidor de Weaviate.
    • url: Especifica la URL de tu instancia de Weaviate. Esta se obtiene de la variable de entorno WEAVIATE_URL.
    • auth_client_secret: (Opcional) Si tu instancia de Weaviate requiere autenticación, puedes proporcionar una clave API usando weaviate.auth.AuthApiKey. La clave API debe almacenarse en la variable de entorno WEAVIATE_API_KEY.

Paso 3: Definir el Esquema

class_schema = {
    "class": "Document",
    "description": "A document to be used for semantic search",
    "properties": [
        {
            "name": "content",
            "dataType": ["text"],
            "description": "The text content of the document",
        },
    ],
}

if not client.schema.exists("Document"):
    client.schema.create_class(class_schema)
  • class_schema: Define el esquema para una clase en Weaviate. Una clase es una colección de objetos de datos (similar a una tabla en una base de datos relacional).
  • class: El nombre de la clase ("Document" en este caso).
  • description: Una descripción de la clase.
  • properties: Una lista de propiedades que tiene la clase.
    • name: El nombre de la propiedad ("content").
    • dataType: El tipo de datos de la propiedad (["text"] en este caso).
    • description: Una descripción de la propiedad.
  • if not client.schema.exists("Document"): Verifica si ya existe una clase llamada "Document" en el esquema de Weaviate.
  • client.schema.create_class(class_schema): Si la clase no existe, esto crea la clase en Weaviate con el esquema definido.

Paso 4: Importar Datos (Almacenar Objetos)

import openai

openai.api_key = os.getenv("OPENAI_API_KEY")


def get_embedding(text):
    response = openai.Embedding.create(
        input=text,
        model="text-embedding-3-small"  # Or your preferred embedding model
    )
    return response["data"][0]["embedding"]



documents = [
    {"content": "How to reset your password"},
    {"content": "Updating your billing information"},
    {"content": "Steps to cancel your subscription"},
]

with client.batch(batch_size=100) as batch:
    for i, doc in enumerate(documents):
        try:
            embedding = get_embedding(doc["content"])
            data_object = {
                "content": doc["content"],
            }
            batch.add_data_object(
                data_object=data_object,
                class_name="Document",
                vector=embedding,
            )
            print(f"Imported document {i + 1}/{len(documents)}")
        except Exception as e:
            print(f"Error importing document {i + 1}: {e}")
  • import openai: Importa la biblioteca OpenAI para usar en la generación de embeddings.
  • openai.api_key = os.getenv("OPENAI_API_KEY"): Establece la clave API de OpenAI usando el valor de la variable de entorno OPENAI_API_KEY.
  • get_embedding(text):
    • Toma una cadena de texto como entrada.
    • Llama a la API de OpenAI para generar un vector de embedding para el texto.
    • Devuelve el vector de embedding.
  • documents: Una lista de diccionarios, donde cada diccionario representa un documento que se almacenará en Weaviate.
  • with client.batch(batch_size=100) as batch: Inicializa un proceso de importación por lotes. Esto es más eficiente para importar múltiples objetos. El parámetro batch_size especifica el número de objetos a incluir en cada lote.
  • El bucle for itera a través de la lista documents:
    • embedding = get_embedding(doc["content"]): Genera el vector de embedding para el contenido del documento usando la función get_embedding.
    • data_object: Crea un diccionario que representa el objeto de datos a almacenar en Weaviate.
    • batch.add_data_object(...): Añade el objeto de datos al lote actual.
      • data_object: El diccionario del objeto de datos.
      • class_name: El nombre de la clase a la que pertenece el objeto ("Document").
      • vector: El vector de embedding para el objeto de datos.
    • El bloque try...except maneja posibles errores durante el proceso de importación.

Paso 5: Consultar Weaviate

query_text = "How do I change my payment method?"
query_vector = get_embedding(query_text)

results = (
    client.query
    .get("Document", ["content"])  # Specify the class and properties to retrieve
    .with_near_vector(
        {"vector": query_vector}
    )
    .with_limit(2)  # Limit the number of results
    .do()
)

print("Search Results:")
for result in results["data"]["Get"]["Document"]:
    print(f"📄 Match: {result['content']}")
  • query_text: El texto de la consulta.
  • query_vector = get_embedding(query_text): Genera el vector de embedding para el texto de la consulta usando la función get_embedding.
  • results = client.query.get("Document", ["content"]).with_near_vector({"vector": query_vector}).with_limit(2).do(): Construye y ejecuta la consulta.
    • client.query.get("Document", ["content"]): Especifica la clase a consultar ("Document") y las propiedades a recuperar ("content").
    • with_near_vector({"vector": query_vector}): Especifica que la consulta debe encontrar objetos cuyos vectores estén más cercanos al query_vector.
    • with_limit(2): Limita el número de resultados a los 2 mejores.
    • do(): Ejecuta la consulta.
  • El código luego imprime los resultados de la búsqueda, extrayendo el contenido de cada documento encontrado.

Más información: https://weaviate.io

Resumen Breve

En este completo capítulo, has adquirido conocimientos valiosos en varias áreas clave:

  • Bases de Datos Vectoriales e IA Escalable
    • Comprender cómo las bases de datos vectoriales sirven como columna vertebral para aplicaciones de IA a gran escala
    • Aprender por qué las bases de datos tradicionales se quedan cortas para la búsqueda y recuperación impulsada por IA
    • Explorar los principios arquitectónicos que hacen que las bases de datos vectoriales sean eficientes a escala
  • Implementación de Pinecone
    • Configurar y ajustar Pinecone para entornos de producción
    • Gestionar embeddings vectoriales en una arquitectura distribuida en la nube
    • Optimizar el rendimiento del índice y la eficiencia de las consultas
  • Construcción de Sistemas de Búsqueda Global
    • Implementar búsqueda semántica que comprende el contexto y significado
    • Diseñar sistemas que mantienen tiempos de respuesta rápidos a escala global
    • Manejar requisitos de búsqueda multilingüe y transcultural
  • Soluciones Alternativas
    • Chroma: Perfecto para implementaciones pequeñas y prototipos rápidos
    • Weaviate: Ideal para búsqueda híbrida y relaciones de datos complejas
    • Entender cuándo elegir cada solución según casos de uso específicos

Armado con este conocimiento, ahora estás equipado para ir más allá de los prototipos básicos y crear aplicaciones de IA sofisticadas de nivel producción que aprovechan todo el poder de los embeddings, la comprensión contextual y la búsqueda inteligente a escala. Ya sea que estés construyendo una aplicación pequeña o un sistema global, tienes las herramientas para elegir e implementar la solución correcta para tus necesidades.

3.4 Introducción a Pinecone y Otras Bases de Datos Vectoriales

En esta sección, profundizaremos en las bases de datos vectoriales - sistemas especializados diseñados para manejar datos de alta dimensión eficientemente. Estas poderosas herramientas están revolucionando cómo almacenamos y recuperamos representaciones complejas de datos.

Exploraremos tres soluciones líderes que sirven diferentes necesidades:

  • Pinecone: Una solución en la nube totalmente administrada perfecta para aplicaciones empresariales que necesitan manejar millones de vectores con rendimiento consistente
  • Chroma: Una base de datos eficiente y amigable para desarrolladores, ideal para desarrollo local y aplicaciones de menor escala
  • Weaviate: Una opción robusta de código abierto que sobresale en capacidades de búsqueda híbrida

Aprenderás cómo estas bases de datos te permiten:

  • Almacenar y gestionar vastas colecciones de embeddings (representaciones vectoriales de texto, imágenes u otros datos)
  • Realizar búsquedas de similitud ultrarrápidas en conjuntos de datos masivos
  • Escalar tus aplicaciones sin problemas desde prototipo a producción
  • Mantener un rendimiento consistente incluso cuando tus datos crecen

Lo más importante, te mostraremos cómo estas herramientas mantienen tiempos de respuesta y fiabilidad excepcionales mientras operan en entornos en la nube, haciéndolas perfectas para aplicaciones de IA a nivel de producción.

3.4.1 ¿Qué son las Bases de Datos Vectoriales?

Una base de datos vectorial es un sistema especializado diseñado para almacenar y recuperar eficientemente embeddings — representaciones numéricas de alta dimensión de contenido como texto, audio o imágenes. Estos embeddings son esencialmente largas listas de números (vectores) que representan las características y el significado del contenido. Por ejemplo, una sola frase podría convertirse en un vector de 1,536 números, donde cada número captura algún aspecto del significado, tono o estructura de la frase. Estos embeddings capturan el significado semántico del contenido en un formato que las computadoras pueden procesar eficientemente, haciendo posible encontrar contenido similar mediante la comparación de estos patrones numéricos.

Para ilustrar este concepto, imagina cada pieza de contenido como un punto en un vasto espacio multidimensional. El contenido similar aparece más cerca entre sí en este espacio, mientras que el contenido diferente aparece alejado. Por ejemplo, dos artículos sobre "cocinar pasta" tendrían representaciones vectoriales similares y por lo tanto estarían cerca uno del otro en este espacio, mientras que un artículo sobre "física cuántica" estaría ubicado lejos de ellos.

Las bases de datos tradicionales sobresalen en el almacenamiento de datos estructurados, pero tienen dificultades con los desafíos únicos de las operaciones vectoriales. Estos desafíos incluyen encontrar eficientemente los vecinos más cercanos en el espacio de alta dimensión, manejar la complejidad computacional de los cálculos de similitud y gestionar los requisitos de memoria de grandes conjuntos de datos vectoriales. Si bien bibliotecas como FAISS funcionan bien en tu máquina local, no persisten los datos entre sesiones ni escalan fácilmente a millones de vectores. Ahí es donde entran las bases de datos vectoriales, ofreciendo soluciones especializadas para operaciones vectoriales a gran escala. Estas bases de datos están específicamente diseñadas para manejar las complejidades de las matemáticas vectoriales mientras proporcionan la confiabilidad y escalabilidad de los sistemas de bases de datos tradicionales.

Estos sistemas sofisticados proporcionan varias capacidades cruciales que los hacen indispensables para las aplicaciones modernas de IA:

  • Almacenar y gestionar miles de millones de embeddings con estructuras de almacenamiento optimizadas diseñadas específicamente para datos vectoriales de alta dimensión. Estas estructuras utilizan técnicas avanzadas de compresión y asignación eficiente de memoria para manejar cantidades masivas de datos vectoriales mientras mantienen tiempos de acceso rápidos.
  • Admiten búsqueda vectorial en tiempo real con filtros, utilizando técnicas avanzadas de indexación como grafos HNSW (Hierarchical Navigable Small World). Estos grafos crean múltiples capas de conexiones entre vectores, permitiendo que el sistema navegue rápidamente a través del espacio vectorial y encuentre elementos similares en microsegundos, incluso cuando se trata de miles de millones de vectores. La capacidad de filtrado permite combinar consultas de bases de datos tradicionales con búsqueda de similitud vectorial.
  • Se integran perfectamente con APIs y servicios en la nube, ofreciendo arquitectura distribuida para alta disponibilidad y escalado automático. Esto significa que tu base de datos vectorial puede manejar automáticamente cargas de trabajo crecientes distribuyendo datos entre múltiples servidores, asegurando un rendimiento consistente incluso durante momentos de uso máximo. La arquitectura nativa en la nube también proporciona redundancia y tolerancia a fallos incorporadas.
  • Permiten combinar metadatos + similitud vectorial para consultas más inteligentes, habilitando filtrado y clasificación sofisticados basados tanto en similitud semántica como en criterios tradicionales de bases de datos. Por ejemplo, puedes buscar documentos que sean semánticamente similares a una consulta mientras filtras por rango de fechas, categoría o cualquier otro campo de metadatos. Este enfoque híbrido proporciona resultados de búsqueda más precisos y relevantes.
  • Garantizan la persistencia y consistencia de datos a través de múltiples sesiones y usuarios, haciéndolas adecuadas para entornos de producción. A diferencia de las soluciones en memoria, las bases de datos vectoriales proporcionan cumplimiento ACID (Atomicidad, Consistencia, Aislamiento, Durabilidad) y soporte de transacciones, asegurando que tus datos permanezcan confiables y consistentes incluso en caso de fallos del sistema o acceso concurrente.

Principales actores de un vistazo



3.4.2 Eligiendo la base de datos vectorial adecuada: Pinecone, Chroma o Weaviate

Cada base de datos vectorial tiene sus características únicas y casos de uso especializados. Explorémoslas en detalle:

Pinecone

  • Mejor para: Aplicaciones de producción a gran escala que exigen alta disponibilidad consistente y rendimiento superior. Esto lo hace particularmente adecuado para empresas que manejan millones de consultas por día, especialmente aquellas que ejecutan aplicaciones de IA críticas como sistemas de recomendación en tiempo real, plataformas de moderación de contenido o servicios de búsqueda a gran escala.
  • Ventajas: Como servicio en la nube totalmente administrado, Pinecone elimina las complejidades de infraestructura al manejar todas las operaciones backend. Su red de distribución global asegura una latencia mínima independientemente de la ubicación del usuario, mientras que el escalado automático ajusta los recursos según la demanda, desde manejar unos pocos miles hasta millones de consultas. La plataforma incluye características de seguridad de nivel empresarial como cumplimiento SOC 2, cifrado en reposo y en tránsito, y control de acceso basado en roles (RBAC) para la gestión de equipos.
  • Usar cuando: Tu aplicación requiere confiabilidad de nivel profesional y rendimiento consistente, particularmente en entornos de alta exigencia donde el tiempo de inactividad podría ser costoso. Si bien viene con un precio premium, la inversión se justifica para empresas que necesitan tiempo de actividad garantizado, tiempos de consulta predecibles y soporte de nivel empresarial. Es especialmente valioso para entornos de producción que manejan datos sensibles o sirven a una base de usuarios global donde la confiabilidad del sistema impacta directamente en las operaciones comerciales.

Chroma

  • Mejor para: Entornos de desarrollo, proyectos de prueba de concepto y aplicaciones más pequeñas que no requieren escala masiva. Es particularmente adecuado para investigadores y desarrolladores que trabajan en prototipos de IA, experimentos de ciencia de datos y flujos de trabajo de desarrollo local. Su naturaleza ligera lo hace perfecto para prototipado rápido y pruebas de diferentes enfoques de embeddings sin la sobrecarga de infraestructura en la nube.
  • Ventajas: Chroma ofrece un proceso de configuración extremadamente simple que puede completarse en minutos - solo pip install y estás listo para comenzar. Su integración nativa con Python significa una integración perfecta con herramientas populares de ciencia de datos y ML como pandas, numpy y scikit-learn. Al ser completamente gratuito y de código abierto, permite experimentación ilimitada sin preocupaciones de costos. Los requisitos mínimos de recursos significan que puede funcionar eficientemente incluso en hardware modesto. Además, incluye soporte integrado para modelos de embeddings populares de OpenAI, Cohere y otros proveedores, facilitando la experimentación con diferentes estrategias de embeddings.
  • Usar cuando: Estás desarrollando localmente y necesitas ciclos rápidos de iteración para probar diferentes enfoques. Es ideal para entornos educativos donde los estudiantes están aprendiendo sobre embeddings y búsqueda vectorial. Perfecto para construir aplicaciones autocontenidas sin dependencias externas, especialmente cuando quieres evitar la complejidad y el costo de los servicios en la nube. Chroma brilla en escenarios donde necesitas prototipar rápidamente y validar características basadas en embeddings antes de pasar a un entorno de producción. También es excelente para proyectos de investigación donde necesitas control completo sobre el pipeline de embeddings y quieres experimentar con diferentes configuraciones.

Weaviate

  • Ideal para: Aplicaciones que necesitan funcionalidad de búsqueda sofisticada combinando búsqueda tradicional por palabras clave con similitud vectorial. Este enfoque dual lo hace particularmente potente para sistemas de gestión de contenido, plataformas de comercio electrónico y aplicaciones de búsqueda avanzada donde los usuarios pueden combinar consultas en lenguaje natural con criterios específicos de filtrado. Sus capacidades de búsqueda híbrida sobresalen en escenarios donde las coincidencias exactas y la comprensión semántica necesitan trabajar juntas de manera fluida.
  • Ventajas: Como solución de código abierto, Weaviate ofrece flexibilidad y opciones de personalización sin igual. Sus potentes capacidades de diseño de esquemas permiten a los desarrolladores definir estructuras de datos complejas con propiedades personalizadas, relaciones y reglas de validación. La plataforma admite múltiples paradigmas de búsqueda, incluyendo búsqueda semántica para comprender el significado de las consultas, búsqueda tradicional por palabras clave para coincidencias exactas, y búsqueda híbrida que combina inteligentemente ambos enfoques. Además, ofrece opciones de implementación tanto en la nube como autoalojadas, dando a las organizaciones control completo sobre sus datos e infraestructura.
  • Usar cuando: Tu proyecto requiere la sofisticación tanto de búsqueda por similitud vectorial como características de búsqueda tradicional en una plataforma unificada. Es particularmente valioso para organizaciones que construyen sistemas complejos de gestión del conocimiento, interfaces de búsqueda avanzada o motores de recomendación de contenido. La plataforma destaca en escenarios que requieren control granular sobre la estructura de datos, comportamiento de búsqueda personalizado y requisitos específicos de implementación. Su flexibilidad lo hace ideal para equipos que necesitan ajustar su arquitectura de búsqueda para cumplir con requisitos comerciales únicos.

3.4.3 Pinecone

Pinecone es una sofisticada solución en la nube totalmente administrada, diseñada específicamente para operaciones vectoriales a escala empresarial. En su núcleo, Pinecone utiliza algoritmos avanzados de indexación y arquitectura de computación distribuida para manejar operaciones vectoriales con notable eficiencia. El sistema sobresale en la gestión de millones de vectores de alta dimensionalidad - piensa en estos como representaciones matemáticas complejas de texto, imágenes u otros datos - mientras mantiene un rendimiento consistente de baja latencia, típicamente respondiendo en milisegundos.

Su arquitectura distribuida es particularmente notable, empleando un sofisticado mecanismo de fragmentación que distribuye los datos entre múltiples nodos. Esto garantiza operaciones de búsqueda confiables en conjuntos de datos masivos, con redundancia incorporada y mecanismos automáticos de recuperación ante fallos. Esta robusta infraestructura la hace ideal para:

  • Sistemas de recomendación a gran escala - Estos sistemas procesan millones de interacciones de usuarios en tiempo real y características de productos para entregar recomendaciones personalizadas. Por ejemplo, una plataforma de comercio electrónico podría analizar el historial de navegación, patrones de compra y atributos de productos de millones de usuarios para sugerir artículos relevantes instantáneamente.
  • Plataformas de descubrimiento de contenido - Estas plataformas utilizan algoritmos sofisticados para emparejar contenido a través de vastas bibliotecas multimedia, analizando metadatos, preferencias de usuarios y características de contenido. Pueden procesar contenido multimedia como videos, artículos y música para conectar a los usuarios con contenido relevante que podrían disfrutar, manejando bibliotecas con petabytes de datos.
  • Aplicaciones de búsqueda semántica - Estas aplicaciones comprenden el contexto y significado detrás de las consultas de búsqueda, no solo palabras clave. Entregan resultados altamente relevantes en milisegundos comparando el significado semántico de la consulta contra millones de documentos, teniendo en cuenta matices, sinónimos y conceptos relacionados.
  • Soluciones de servicio al cliente impulsadas por IA - Estos sistemas revolucionan el soporte al cliente al acceder y analizar instantáneamente vastas bases de datos de documentación de soporte, interacciones previas con clientes e información de productos. Pueden comprender las consultas de los clientes en contexto y proporcionar soluciones relevantes procesando datos históricos que abarcan años de interacciones con clientes.

Lo que verdaderamente distingue a Pinecone es su excepcional optimización del rendimiento. La plataforma mantiene tiempos de consulta inferiores al segundo incluso cuando su base de datos vectorial escala a miles de millones de entradas - una hazaña lograda a través de sofisticadas técnicas de indexación como grafos HNSW (Hierarchical Navigable Small World) y particionamiento eficiente de datos. Esto se complementa con características de nivel empresarial que incluyen:

  • Escalado horizontal automático que responde a cargas de trabajo variables
  • Alta disponibilidad a través de implementación multi-región
  • Medidas robustas de seguridad incluyendo cifrado en reposo y en tránsito
  • Capacidades avanzadas de monitoreo y registro
  • Sistemas automáticos de respaldo y recuperación ante desastres

3.4.4 Caso de Uso: Búsqueda Semántica con Pinecone

Ahora veamos cómo integrar embeddings de OpenAI con Pinecone para realizar búsqueda semántica en la nube.

Este código demuestra cómo realizar búsqueda semántica usando OpenAI y Pinecone. La búsqueda semántica va más allá de la coincidencia de palabras clave al comprender el significado de la consulta y los documentos. Utiliza OpenAI para generar embeddings (representaciones numéricas) de texto, y Pinecone, una base de datos vectorial, para almacenar y buscar eficientemente estos embeddings.

Desglose del Código

Aquí hay una explicación paso a paso del código:

Paso 1: Importar Bibliotecas

import openai
import pinecone
import os
from dotenv import load_dotenv
import time  # For exponential backoff
  • openai: Para interactuar con la API de OpenAI y generar embeddings.
  • pinecone: Para interactuar con la base de datos vectorial Pinecone.
  • os: Para acceder a las variables de entorno.
  • dotenv: Para cargar variables de entorno desde un archivo .env.
  • time: Para implementar retroceso exponencial en caso de errores de API.

Paso 2: Cargar Variables de Entorno e Inicializar Clientes

load_dotenv()

# API keys
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
PINECONE_API_KEY = os.getenv("PINECONE_API_KEY")
PINECONE_ENV = os.getenv("PINECONE_ENV")  # e.g., "gcp-starter"

openai.api_key = OPENAI_API_KEY

pinecone.init(
    api_key=PINECONE_API_KEY,
    environment=PINECONE_ENV
)
  • load_dotenv(): Carga variables de entorno desde un archivo .env. Aquí es donde almacenas tus claves API de OpenAI y Pinecone.
  • os.getenv(): Obtiene las claves API y el entorno de Pinecone desde las variables de entorno.
  • El código luego inicializa el cliente de OpenAI con la clave API de OpenAI y el cliente de Pinecone con la clave API y el entorno de Pinecone.

Paso 3: Definir Configuración del Índice de Pinecone

# Pinecone index configuration
INDEX_NAME = "semantic-search-index"
EMBEDDING_MODEL = "text-embedding-3-small"
EMBEDDING_DIMENSION = 1536
SIMILARITY_METRIC = "cosine"
BATCH_SIZE = 100  # Batch size for upserting vectors
  • INDEX_NAME: El nombre del índice de Pinecone.
  • EMBEDDING_MODEL: El modelo de OpenAI utilizado para generar embeddings.
  • EMBEDDING_DIMENSION: La dimensionalidad de los embeddings (1536 para text-embedding-3-small).
  • SIMILARITY_METRIC: La métrica utilizada para medir la similitud entre embeddings (similitud del coseno).
  • BATCH_SIZE: El número de vectores a insertar en Pinecone a la vez.

Paso 4: Función Auxiliar: get_embedding()

def get_embedding(text, model=EMBEDDING_MODEL):
    """Gets the embedding for a given text using OpenAI's API with retry logic."""
    max_retries = 3
    for attempt in range(max_retries):
        try:
            response = openai.Embedding.create(input=text, model=model)
            return response["data"][0]["embedding"]
        except openai.APIError as e:
            print(f"OpenAI API error: {e}")
            if attempt < max_retries - 1:
                time.sleep(2 ** attempt)  # Exponential backoff
            else:
                raise  # Raise the exception if all retries fail
        except Exception as e:
            print(f"Error getting embedding: {e}")
            raise
  • Esta función toma un texto como entrada y devuelve su vector de embedding utilizando la API de OpenAI.
  • Incluye manejo de errores con retroceso exponencial para gestionar posibles errores de la API. Si ocurre un error en la API de OpenAI, reintenta la solicitud hasta max_retries veces, esperando más tiempo entre cada intento.

Paso 5: Función Auxiliar: upsert_embeddings()

def upsert_embeddings(index, documents, batch_size=BATCH_SIZE):
    """Upserts embeddings for a list of documents into Pinecone with batching."""
    vectors = []
    for doc_id, text in documents.items():
        embedding = get_embedding(text)
        vectors.append((doc_id, embedding, {"text": text}))

    for i in range(0, len(vectors), batch_size):
        batch = vectors[i:i + batch_size]
        try:
            index.upsert(vectors=batch)
            print(f"✅ Upserted batch {i // batch_size + 1}/{len(vectors) // batch_size + 1}")
        except pinecone.PineconeException as e:
            print(f"Error upserting batch: {e}")
            raise
  • Esta función toma como entrada un índice de Pinecone, un diccionario de documentos y un tamaño de lote.
  • Genera embeddings para cada documento usando la función get_embedding().
  • Prepara los datos en el formato que espera el método upsert() de Pinecone: una lista de tuplas, donde cada tupla contiene el ID del documento, el vector de embedding y metadatos (en este caso, el texto original).
  • Luego inserta los vectores en Pinecone en lotes, según el batch_size. El procesamiento por lotes es más eficiente para cargar grandes cantidades de datos a Pinecone.

Paso 6: Función Auxiliar: query_pinecone()

def query_pinecone(index, query_text, top_k=2):
    """Queries Pinecone with a given query text and returns the top-k results."""
    query_embedding = get_embedding(query_text)
    try:
        results = index.query(vector=query_embedding, top_k=top_k, include_metadata=True)
        return results
    except pinecone.PineconeException as e:
        print(f"Error querying Pinecone: {e}")
        raise
  • Esta función toma un índice de Pinecone, un texto de consulta y el número de resultados a devolver (top_k).
  • Genera el embedding para el texto de consulta usando get_embedding().
  • Consulta el índice de Pinecone usando el embedding de la consulta, solicitando los top_k vectores más similares. include_metadata=True asegura que también se devuelva el texto original de los documentos coincidentes.
  • Maneja posibles errores de Pinecone.

Paso 7: Función Principal

def main():
    """Main function to perform semantic search with Pinecone and OpenAI."""
    openai.api_key = OPENAI_API_KEY

    pinecone.init(
        api_key=PINECONE_API_KEY,
        environment=PINECONE_ENV
    )

    # Create Pinecone index if it doesn't exist
    if INDEX_NAME not in pinecone.list_indexes():
        try:
            pinecone.create_index(
                name=INDEX_NAME,
                dimension=EMBEDDING_DIMENSION,
                metric=SIMILARITY_METRIC
            )
            print(f"✅ Created Pinecone index: {INDEX_NAME}")
        except pinecone.PineconeException as e:
            print(f"Error creating Pinecone index: {e}")
            return

    index = pinecone.Index(INDEX_NAME)

    # Documents to embed and store in Pinecone
    documents = {
        "doc1": "How to reset your password",
        "doc2": "Updating your billing information",
        "doc3": "Steps to cancel your subscription",
    }

    # Upsert documents into Pinecone
    upsert_embeddings(index, documents)

    # Query Pinecone with a user question
    query_text = "How do I change my payment method?"
    results = query_pinecone(index, query_text)

    # Print the search results
    print("\nSearch Results:")
    for match in results["matches"]:
        print(f"📄 Match: {match['metadata']['text']} (Score: {round(match['score'], 3)})")

    pinecone.deinit()  # Clean up Pinecone connection

if __name__ == "__main__":
    main()
  • Esta es la función principal que orquesta el proceso de búsqueda semántica.
  • Inicializa los clientes de OpenAI y Pinecone.
  • Crea el índice de Pinecone si aún no existe.
  • Define un conjunto de documentos de muestra para indexar.
  • Llama a upsert_embeddings() para almacenar los embeddings de documentos en Pinecone.
  • Define una consulta y llama a query_pinecone() para realizar la búsqueda.
  • Imprime los resultados de la búsqueda, incluyendo los documentos coincidentes y sus puntajes de similitud.
  • Llama a pinecone.deinit() para limpiar la conexión de Pinecone.
  • El bloque if __name__ == "__main__": asegura que la función main() se ejecute cuando se ejecuta el script.

3.4.5 Chroma

Chroma es una base de datos vectorial sofisticada y amigable para desarrolladores, específicamente diseñada para operaciones eficientes de almacenamiento y recuperación de embeddings. Lo que la distingue es su rendimiento excepcional en entornos de desarrollo local y aplicaciones de menor escala, gracias a su arquitectura ligera y proceso de configuración simplificado. A diferencia de soluciones más complejas, Chroma prioriza la experiencia del desarrollador sin sacrificar funcionalidad.

La base de datos ofrece varias características y capacidades poderosas que la hacen destacar:

  • Fácil integración con frameworks populares de ML
    • Proporciona soporte integral para las principales bibliotecas de aprendizaje automático, incluyendo PyTorch, TensorFlow y scikit-learn, permitiendo una integración fluida con pipelines de ML existentes
    • Presenta un diseño de API intuitivo que reduce significativamente el tiempo y la complejidad del desarrollo, haciéndola accesible tanto para principiantes como para desarrolladores experimentados
    • Incluye documentación extensa y ejemplos de código para ayudar a los desarrolladores a comenzar rápidamente
  • Soporte incorporado para múltiples modelos de embedding
    • Ofrece compatibilidad inmediata con proveedores líderes de embeddings como OpenAI, Hugging Face y Sentence Transformers, permitiendo diversas opciones de modelos
    • Implementa una arquitectura flexible que permite a los desarrolladores cambiar fácilmente entre diferentes modelos de embedding sin requerir modificaciones extensas del código
    • Admite funciones de embedding personalizadas para casos de uso especializados
  • Opciones robustas de almacenamiento persistente para durabilidad de datos
    • Soporta varios backends de almacenamiento incluyendo SQLite para desarrollo local y PostgreSQL para entornos de producción, asegurando la persistencia de datos en diferentes escalas
    • Presenta mecanismos sofisticados de recuperación de datos que protegen contra pérdida de datos y fallos del sistema
    • Implementa estrategias eficientes de indexación para un rendimiento óptimo de consultas
  • Requisitos mínimos de recursos, perfecta para prototipado
    • Gestión optimizada de memoria asegura una utilización eficiente de recursos, haciéndola adecuada para máquinas de desarrollo
    • Tiempos de inicio rápidos permiten ciclos rápidos de desarrollo y pruebas
    • Elimina la necesidad de servicios externos complejos o infraestructura, reduciendo la complejidad y costos de implementación

Si bien Chroma puede no igualar la escalabilidad de soluciones basadas en la nube como Pinecone al manejar conjuntos de datos masivos (típicamente aquellos que exceden millones de vectores), su simplicidad y capacidades de desarrollo rápido la convierten en una excelente opción para desarrolladores que construyen pruebas de concepto o aplicaciones con requisitos moderados de datos. La base de datos es particularmente adecuada para proyectos que necesitan ciclos rápidos de iteración, desarrollo y pruebas locales, o implementación en entornos donde los servicios en la nube podrían no estar fácilmente disponibles o ser rentables.

3.4.6 Usando Chroma para Proyectos Locales

Este ejemplo demuestra cómo realizar búsqueda semántica usando Chroma, una base de datos vectorial local y ligera. Al igual que el ejemplo de Pinecone, utiliza embeddings para capturar el significado del texto, pero Chroma está específicamente diseñada para casos de uso locales.

Desglose del Código

Aquí hay una explicación paso a paso del código:

Paso 1: Instalar Biblioteca

pip install chromadb
  • Este comando instala la biblioteca chromadb, que proporciona las herramientas necesarias para trabajar con la base de datos vectorial Chroma.

Paso 2: Importar Bibliotecas

import chromadb
from chromadb.utils.embedding_functions import OpenAIEmbeddingFunction
import os
from dotenv import load_dotenv

load_dotenv()
  • chromadb: La biblioteca principal de Chroma.
  • OpenAIEmbeddingFunction: Una función de utilidad de Chroma para usar la API de OpenAI en la generación de embeddings.
  • os: Para acceder a las variables de entorno (para obtener la clave API de OpenAI).
  • dotenv: Para cargar variables de entorno desde un archivo .env.

Paso 3: Inicializar el Cliente de Chroma

client = chromadb.Client()
  • Esta línea crea un objeto cliente de Chroma. En la configuración predeterminada, Chroma se ejecuta localmente.

Paso 4: Crear una Colección

collection = client.create_collection(name="my_embeddings")
  • Esto crea una colección en Chroma. Una colección es similar a un índice en Pinecone; es donde almacenas y consultas tus embeddings. La colección se llama "my_embeddings".

Paso 5: Inicializar la Función de Embedding de OpenAI

embedding_function = OpenAIEmbeddingFunction(api_key=os.getenv("OPENAI_API_KEY"))
  • Esto crea una instancia de OpenAIEmbeddingFunction, que se utilizará para generar embeddings usando la API de OpenAI. Obtiene la clave API de OpenAI desde las variables de entorno.

Paso 6: Agregar Documentos a la Colección

collection.add(
    documents=["Learn how to train a model", "Understanding neural networks"],
    ids=["doc1", "doc2"]
)
  • Esto agrega documentos y sus IDs correspondientes a la colección "my_embeddings".
    • documents: Una lista de documentos de texto.
    • ids: Una lista de identificadores únicos para cada documento. Chroma usa estos IDs para rastrear los vectores. El orden de los ids debe corresponder al orden de los documents.
  • Entre bastidores, Chroma utiliza la embedding_function (la función de embedding de OpenAI) para generar embeddings para los documentos proporcionados. Estos embeddings se almacenan en la colección junto con los documentos e IDs.

Paso 7: Realizar una Consulta

query = "How do I build an AI model?"
results = collection.query(query_texts=[query], n_results=1)
print("🔍 Best Match:", results["documents"][0][0])
  • query: El texto de la consulta.
  • collection.query(): Esto realiza la búsqueda.
    • query_texts: Una lista que contiene el texto de la consulta. Incluso si solo estás consultando un fragmento de texto, Chroma espera una lista.
    • n_results: El número de vecinos más cercanos (documentos más similares) a recuperar. Aquí, está configurado en 1, por lo que recupera la única mejor coincidencia.
  • El código luego imprime el texto del documento con mejor coincidencia. results["documents"] es una lista de listas. La lista exterior corresponde a las consultas (en este caso, una sola consulta), y la lista interior contiene los documentos.

3.4.7 Weaviate

Weaviate es una potente base de datos vectorial de código abierto que combina la búsqueda tradicional basada en palabras clave con la búsqueda por similitud vectorial de una manera única. A diferencia de las bases de datos vectoriales simples que solo realizan coincidencias por similitud, las capacidades de búsqueda híbrida de Weaviate le permiten comprender simultáneamente tanto las palabras exactas (palabras clave) como el significado subyacente (semántica) de una consulta. Este enfoque dual significa que puede manejar consultas complejas como "Encontrar documentos sobre aprendizaje automático que mencionen programación en Python" combinando tanto la comprensión semántica como la coincidencia específica de palabras clave.

Lo que distingue a Weaviate es su arquitectura integral. Ofrece múltiples formas de interactuar con la base de datos: GraphQL para consultas flexibles y estructuradas; APIs RESTful para integración web tradicional; y soporte para varios modelos de aprendizaje automático que se pueden conectar según tus necesidades. Esta flexibilidad significa que los desarrolladores pueden elegir el enfoque más apropiado para su caso de uso específico.

La plataforma incluye varias características poderosas que revolucionan cómo trabajamos con bases de datos vectoriales:

  • Gestión Automática de Esquemas
    • Inferencia Inteligente de Esquemas: La IA de Weaviate analiza los patrones de tu conjunto de datos y recomienda automáticamente estructuras de datos óptimas, ahorrando horas de configuración manual
    • Organización Inteligente de Datos: Utiliza algoritmos avanzados para categorizar, etiquetar y estructurar automáticamente tus datos basándose en similitudes y relaciones de contenido
    • Evolución Dinámica de Esquemas: Adapta tu estructura de datos sobre la marcha a medida que tu aplicación crece, sin tiempo de inactividad ni dolores de cabeza por migración de datos
  • Procesamiento Avanzado en Tiempo Real
    • Indexación Instantánea: A diferencia de las bases de datos tradicionales que requieren procesamiento por lotes, Weaviate indexa nuevos datos en el momento en que llegan
    • Disponibilidad sin Latencia: Los nuevos datos se pueden buscar inmediatamente, perfecto para aplicaciones que requieren actualizaciones en tiempo real
    • Sincronización Continua: Los resultados de búsqueda incorporan automáticamente nuevos datos, asegurando que los usuarios siempre vean la información más actualizada
  • Capacidades Multimodales Integrales
    • Comprensión Avanzada de Texto: Utiliza modelos de PNL de última generación para comprender el contexto, el sentimiento y las relaciones semánticas en datos de texto
    • Análisis Sofisticado de Imágenes: Implementa algoritmos de visión por computadora para búsqueda de similitud visual, detección de objetos y clasificación de imágenes
    • Sistema de Tipos Extensible: Construye tipos de datos personalizados con lógica de procesamiento especializada para tus casos de uso únicos, desde procesamiento de audio hasta análisis de datos científicos

3.4.8 Búsqueda Semántica usando Weaviate

Este caso de uso demuestra cómo realizar búsqueda semántica usando Weaviate. La búsqueda semántica mejora la búsqueda tradicional basada en palabras clave al comprender el significado de las consultas y documentos, devolviendo resultados más relevantes. Weaviate almacena objetos de datos y sus embeddings vectoriales correspondientes, permitiendo una recuperación eficiente basada en similitud. Este ejemplo usa OpenAI para generar los embeddings.

Paso 1: Instalar Bibliotecas Requeridas

pip install weaviate-client
  • Este comando instala la biblioteca weaviate-client, que proporciona el cliente de Python para interactuar con Weaviate.

Paso 2: Configurar el Cliente de Weaviate

import weaviate
import os
from dotenv import load_dotenv

load_dotenv()  # Load environment variables

client = weaviate.Client(
    url=os.getenv("WEAVIATE_URL"),  # Replace with your Weaviate URL
    #   auth_client_secret=weaviate.auth.AuthApiKey(api_key=os.getenv("WEAVIATE_API_KEY")) #Uncomment if you are using an API key.
)
  • import weaviate: Importa la biblioteca cliente de Weaviate.
  • import os: Importa el módulo os para acceder a las variables de entorno.
  • from dotenv import load_dotenv: Importa la función load_dotenv de la biblioteca dotenv para cargar variables de entorno desde un archivo .env.
  • load_dotenv(): Carga las variables de entorno desde un archivo .env. Aquí es donde debes almacenar tu URL de Weaviate (y la clave API, si corresponde).
  • client = weaviate.Client(...): Inicializa una instancia del cliente de Weaviate, estableciendo una conexión con el servidor de Weaviate.
    • url: Especifica la URL de tu instancia de Weaviate. Esta se obtiene de la variable de entorno WEAVIATE_URL.
    • auth_client_secret: (Opcional) Si tu instancia de Weaviate requiere autenticación, puedes proporcionar una clave API usando weaviate.auth.AuthApiKey. La clave API debe almacenarse en la variable de entorno WEAVIATE_API_KEY.

Paso 3: Definir el Esquema

class_schema = {
    "class": "Document",
    "description": "A document to be used for semantic search",
    "properties": [
        {
            "name": "content",
            "dataType": ["text"],
            "description": "The text content of the document",
        },
    ],
}

if not client.schema.exists("Document"):
    client.schema.create_class(class_schema)
  • class_schema: Define el esquema para una clase en Weaviate. Una clase es una colección de objetos de datos (similar a una tabla en una base de datos relacional).
  • class: El nombre de la clase ("Document" en este caso).
  • description: Una descripción de la clase.
  • properties: Una lista de propiedades que tiene la clase.
    • name: El nombre de la propiedad ("content").
    • dataType: El tipo de datos de la propiedad (["text"] en este caso).
    • description: Una descripción de la propiedad.
  • if not client.schema.exists("Document"): Verifica si ya existe una clase llamada "Document" en el esquema de Weaviate.
  • client.schema.create_class(class_schema): Si la clase no existe, esto crea la clase en Weaviate con el esquema definido.

Paso 4: Importar Datos (Almacenar Objetos)

import openai

openai.api_key = os.getenv("OPENAI_API_KEY")


def get_embedding(text):
    response = openai.Embedding.create(
        input=text,
        model="text-embedding-3-small"  # Or your preferred embedding model
    )
    return response["data"][0]["embedding"]



documents = [
    {"content": "How to reset your password"},
    {"content": "Updating your billing information"},
    {"content": "Steps to cancel your subscription"},
]

with client.batch(batch_size=100) as batch:
    for i, doc in enumerate(documents):
        try:
            embedding = get_embedding(doc["content"])
            data_object = {
                "content": doc["content"],
            }
            batch.add_data_object(
                data_object=data_object,
                class_name="Document",
                vector=embedding,
            )
            print(f"Imported document {i + 1}/{len(documents)}")
        except Exception as e:
            print(f"Error importing document {i + 1}: {e}")
  • import openai: Importa la biblioteca OpenAI para usar en la generación de embeddings.
  • openai.api_key = os.getenv("OPENAI_API_KEY"): Establece la clave API de OpenAI usando el valor de la variable de entorno OPENAI_API_KEY.
  • get_embedding(text):
    • Toma una cadena de texto como entrada.
    • Llama a la API de OpenAI para generar un vector de embedding para el texto.
    • Devuelve el vector de embedding.
  • documents: Una lista de diccionarios, donde cada diccionario representa un documento que se almacenará en Weaviate.
  • with client.batch(batch_size=100) as batch: Inicializa un proceso de importación por lotes. Esto es más eficiente para importar múltiples objetos. El parámetro batch_size especifica el número de objetos a incluir en cada lote.
  • El bucle for itera a través de la lista documents:
    • embedding = get_embedding(doc["content"]): Genera el vector de embedding para el contenido del documento usando la función get_embedding.
    • data_object: Crea un diccionario que representa el objeto de datos a almacenar en Weaviate.
    • batch.add_data_object(...): Añade el objeto de datos al lote actual.
      • data_object: El diccionario del objeto de datos.
      • class_name: El nombre de la clase a la que pertenece el objeto ("Document").
      • vector: El vector de embedding para el objeto de datos.
    • El bloque try...except maneja posibles errores durante el proceso de importación.

Paso 5: Consultar Weaviate

query_text = "How do I change my payment method?"
query_vector = get_embedding(query_text)

results = (
    client.query
    .get("Document", ["content"])  # Specify the class and properties to retrieve
    .with_near_vector(
        {"vector": query_vector}
    )
    .with_limit(2)  # Limit the number of results
    .do()
)

print("Search Results:")
for result in results["data"]["Get"]["Document"]:
    print(f"📄 Match: {result['content']}")
  • query_text: El texto de la consulta.
  • query_vector = get_embedding(query_text): Genera el vector de embedding para el texto de la consulta usando la función get_embedding.
  • results = client.query.get("Document", ["content"]).with_near_vector({"vector": query_vector}).with_limit(2).do(): Construye y ejecuta la consulta.
    • client.query.get("Document", ["content"]): Especifica la clase a consultar ("Document") y las propiedades a recuperar ("content").
    • with_near_vector({"vector": query_vector}): Especifica que la consulta debe encontrar objetos cuyos vectores estén más cercanos al query_vector.
    • with_limit(2): Limita el número de resultados a los 2 mejores.
    • do(): Ejecuta la consulta.
  • El código luego imprime los resultados de la búsqueda, extrayendo el contenido de cada documento encontrado.

Más información: https://weaviate.io

Resumen Breve

En este completo capítulo, has adquirido conocimientos valiosos en varias áreas clave:

  • Bases de Datos Vectoriales e IA Escalable
    • Comprender cómo las bases de datos vectoriales sirven como columna vertebral para aplicaciones de IA a gran escala
    • Aprender por qué las bases de datos tradicionales se quedan cortas para la búsqueda y recuperación impulsada por IA
    • Explorar los principios arquitectónicos que hacen que las bases de datos vectoriales sean eficientes a escala
  • Implementación de Pinecone
    • Configurar y ajustar Pinecone para entornos de producción
    • Gestionar embeddings vectoriales en una arquitectura distribuida en la nube
    • Optimizar el rendimiento del índice y la eficiencia de las consultas
  • Construcción de Sistemas de Búsqueda Global
    • Implementar búsqueda semántica que comprende el contexto y significado
    • Diseñar sistemas que mantienen tiempos de respuesta rápidos a escala global
    • Manejar requisitos de búsqueda multilingüe y transcultural
  • Soluciones Alternativas
    • Chroma: Perfecto para implementaciones pequeñas y prototipos rápidos
    • Weaviate: Ideal para búsqueda híbrida y relaciones de datos complejas
    • Entender cuándo elegir cada solución según casos de uso específicos

Armado con este conocimiento, ahora estás equipado para ir más allá de los prototipos básicos y crear aplicaciones de IA sofisticadas de nivel producción que aprovechan todo el poder de los embeddings, la comprensión contextual y la búsqueda inteligente a escala. Ya sea que estés construyendo una aplicación pequeña o un sistema global, tienes las herramientas para elegir e implementar la solución correcta para tus necesidades.

3.4 Introducción a Pinecone y Otras Bases de Datos Vectoriales

En esta sección, profundizaremos en las bases de datos vectoriales - sistemas especializados diseñados para manejar datos de alta dimensión eficientemente. Estas poderosas herramientas están revolucionando cómo almacenamos y recuperamos representaciones complejas de datos.

Exploraremos tres soluciones líderes que sirven diferentes necesidades:

  • Pinecone: Una solución en la nube totalmente administrada perfecta para aplicaciones empresariales que necesitan manejar millones de vectores con rendimiento consistente
  • Chroma: Una base de datos eficiente y amigable para desarrolladores, ideal para desarrollo local y aplicaciones de menor escala
  • Weaviate: Una opción robusta de código abierto que sobresale en capacidades de búsqueda híbrida

Aprenderás cómo estas bases de datos te permiten:

  • Almacenar y gestionar vastas colecciones de embeddings (representaciones vectoriales de texto, imágenes u otros datos)
  • Realizar búsquedas de similitud ultrarrápidas en conjuntos de datos masivos
  • Escalar tus aplicaciones sin problemas desde prototipo a producción
  • Mantener un rendimiento consistente incluso cuando tus datos crecen

Lo más importante, te mostraremos cómo estas herramientas mantienen tiempos de respuesta y fiabilidad excepcionales mientras operan en entornos en la nube, haciéndolas perfectas para aplicaciones de IA a nivel de producción.

3.4.1 ¿Qué son las Bases de Datos Vectoriales?

Una base de datos vectorial es un sistema especializado diseñado para almacenar y recuperar eficientemente embeddings — representaciones numéricas de alta dimensión de contenido como texto, audio o imágenes. Estos embeddings son esencialmente largas listas de números (vectores) que representan las características y el significado del contenido. Por ejemplo, una sola frase podría convertirse en un vector de 1,536 números, donde cada número captura algún aspecto del significado, tono o estructura de la frase. Estos embeddings capturan el significado semántico del contenido en un formato que las computadoras pueden procesar eficientemente, haciendo posible encontrar contenido similar mediante la comparación de estos patrones numéricos.

Para ilustrar este concepto, imagina cada pieza de contenido como un punto en un vasto espacio multidimensional. El contenido similar aparece más cerca entre sí en este espacio, mientras que el contenido diferente aparece alejado. Por ejemplo, dos artículos sobre "cocinar pasta" tendrían representaciones vectoriales similares y por lo tanto estarían cerca uno del otro en este espacio, mientras que un artículo sobre "física cuántica" estaría ubicado lejos de ellos.

Las bases de datos tradicionales sobresalen en el almacenamiento de datos estructurados, pero tienen dificultades con los desafíos únicos de las operaciones vectoriales. Estos desafíos incluyen encontrar eficientemente los vecinos más cercanos en el espacio de alta dimensión, manejar la complejidad computacional de los cálculos de similitud y gestionar los requisitos de memoria de grandes conjuntos de datos vectoriales. Si bien bibliotecas como FAISS funcionan bien en tu máquina local, no persisten los datos entre sesiones ni escalan fácilmente a millones de vectores. Ahí es donde entran las bases de datos vectoriales, ofreciendo soluciones especializadas para operaciones vectoriales a gran escala. Estas bases de datos están específicamente diseñadas para manejar las complejidades de las matemáticas vectoriales mientras proporcionan la confiabilidad y escalabilidad de los sistemas de bases de datos tradicionales.

Estos sistemas sofisticados proporcionan varias capacidades cruciales que los hacen indispensables para las aplicaciones modernas de IA:

  • Almacenar y gestionar miles de millones de embeddings con estructuras de almacenamiento optimizadas diseñadas específicamente para datos vectoriales de alta dimensión. Estas estructuras utilizan técnicas avanzadas de compresión y asignación eficiente de memoria para manejar cantidades masivas de datos vectoriales mientras mantienen tiempos de acceso rápidos.
  • Admiten búsqueda vectorial en tiempo real con filtros, utilizando técnicas avanzadas de indexación como grafos HNSW (Hierarchical Navigable Small World). Estos grafos crean múltiples capas de conexiones entre vectores, permitiendo que el sistema navegue rápidamente a través del espacio vectorial y encuentre elementos similares en microsegundos, incluso cuando se trata de miles de millones de vectores. La capacidad de filtrado permite combinar consultas de bases de datos tradicionales con búsqueda de similitud vectorial.
  • Se integran perfectamente con APIs y servicios en la nube, ofreciendo arquitectura distribuida para alta disponibilidad y escalado automático. Esto significa que tu base de datos vectorial puede manejar automáticamente cargas de trabajo crecientes distribuyendo datos entre múltiples servidores, asegurando un rendimiento consistente incluso durante momentos de uso máximo. La arquitectura nativa en la nube también proporciona redundancia y tolerancia a fallos incorporadas.
  • Permiten combinar metadatos + similitud vectorial para consultas más inteligentes, habilitando filtrado y clasificación sofisticados basados tanto en similitud semántica como en criterios tradicionales de bases de datos. Por ejemplo, puedes buscar documentos que sean semánticamente similares a una consulta mientras filtras por rango de fechas, categoría o cualquier otro campo de metadatos. Este enfoque híbrido proporciona resultados de búsqueda más precisos y relevantes.
  • Garantizan la persistencia y consistencia de datos a través de múltiples sesiones y usuarios, haciéndolas adecuadas para entornos de producción. A diferencia de las soluciones en memoria, las bases de datos vectoriales proporcionan cumplimiento ACID (Atomicidad, Consistencia, Aislamiento, Durabilidad) y soporte de transacciones, asegurando que tus datos permanezcan confiables y consistentes incluso en caso de fallos del sistema o acceso concurrente.

Principales actores de un vistazo



3.4.2 Eligiendo la base de datos vectorial adecuada: Pinecone, Chroma o Weaviate

Cada base de datos vectorial tiene sus características únicas y casos de uso especializados. Explorémoslas en detalle:

Pinecone

  • Mejor para: Aplicaciones de producción a gran escala que exigen alta disponibilidad consistente y rendimiento superior. Esto lo hace particularmente adecuado para empresas que manejan millones de consultas por día, especialmente aquellas que ejecutan aplicaciones de IA críticas como sistemas de recomendación en tiempo real, plataformas de moderación de contenido o servicios de búsqueda a gran escala.
  • Ventajas: Como servicio en la nube totalmente administrado, Pinecone elimina las complejidades de infraestructura al manejar todas las operaciones backend. Su red de distribución global asegura una latencia mínima independientemente de la ubicación del usuario, mientras que el escalado automático ajusta los recursos según la demanda, desde manejar unos pocos miles hasta millones de consultas. La plataforma incluye características de seguridad de nivel empresarial como cumplimiento SOC 2, cifrado en reposo y en tránsito, y control de acceso basado en roles (RBAC) para la gestión de equipos.
  • Usar cuando: Tu aplicación requiere confiabilidad de nivel profesional y rendimiento consistente, particularmente en entornos de alta exigencia donde el tiempo de inactividad podría ser costoso. Si bien viene con un precio premium, la inversión se justifica para empresas que necesitan tiempo de actividad garantizado, tiempos de consulta predecibles y soporte de nivel empresarial. Es especialmente valioso para entornos de producción que manejan datos sensibles o sirven a una base de usuarios global donde la confiabilidad del sistema impacta directamente en las operaciones comerciales.

Chroma

  • Mejor para: Entornos de desarrollo, proyectos de prueba de concepto y aplicaciones más pequeñas que no requieren escala masiva. Es particularmente adecuado para investigadores y desarrolladores que trabajan en prototipos de IA, experimentos de ciencia de datos y flujos de trabajo de desarrollo local. Su naturaleza ligera lo hace perfecto para prototipado rápido y pruebas de diferentes enfoques de embeddings sin la sobrecarga de infraestructura en la nube.
  • Ventajas: Chroma ofrece un proceso de configuración extremadamente simple que puede completarse en minutos - solo pip install y estás listo para comenzar. Su integración nativa con Python significa una integración perfecta con herramientas populares de ciencia de datos y ML como pandas, numpy y scikit-learn. Al ser completamente gratuito y de código abierto, permite experimentación ilimitada sin preocupaciones de costos. Los requisitos mínimos de recursos significan que puede funcionar eficientemente incluso en hardware modesto. Además, incluye soporte integrado para modelos de embeddings populares de OpenAI, Cohere y otros proveedores, facilitando la experimentación con diferentes estrategias de embeddings.
  • Usar cuando: Estás desarrollando localmente y necesitas ciclos rápidos de iteración para probar diferentes enfoques. Es ideal para entornos educativos donde los estudiantes están aprendiendo sobre embeddings y búsqueda vectorial. Perfecto para construir aplicaciones autocontenidas sin dependencias externas, especialmente cuando quieres evitar la complejidad y el costo de los servicios en la nube. Chroma brilla en escenarios donde necesitas prototipar rápidamente y validar características basadas en embeddings antes de pasar a un entorno de producción. También es excelente para proyectos de investigación donde necesitas control completo sobre el pipeline de embeddings y quieres experimentar con diferentes configuraciones.

Weaviate

  • Ideal para: Aplicaciones que necesitan funcionalidad de búsqueda sofisticada combinando búsqueda tradicional por palabras clave con similitud vectorial. Este enfoque dual lo hace particularmente potente para sistemas de gestión de contenido, plataformas de comercio electrónico y aplicaciones de búsqueda avanzada donde los usuarios pueden combinar consultas en lenguaje natural con criterios específicos de filtrado. Sus capacidades de búsqueda híbrida sobresalen en escenarios donde las coincidencias exactas y la comprensión semántica necesitan trabajar juntas de manera fluida.
  • Ventajas: Como solución de código abierto, Weaviate ofrece flexibilidad y opciones de personalización sin igual. Sus potentes capacidades de diseño de esquemas permiten a los desarrolladores definir estructuras de datos complejas con propiedades personalizadas, relaciones y reglas de validación. La plataforma admite múltiples paradigmas de búsqueda, incluyendo búsqueda semántica para comprender el significado de las consultas, búsqueda tradicional por palabras clave para coincidencias exactas, y búsqueda híbrida que combina inteligentemente ambos enfoques. Además, ofrece opciones de implementación tanto en la nube como autoalojadas, dando a las organizaciones control completo sobre sus datos e infraestructura.
  • Usar cuando: Tu proyecto requiere la sofisticación tanto de búsqueda por similitud vectorial como características de búsqueda tradicional en una plataforma unificada. Es particularmente valioso para organizaciones que construyen sistemas complejos de gestión del conocimiento, interfaces de búsqueda avanzada o motores de recomendación de contenido. La plataforma destaca en escenarios que requieren control granular sobre la estructura de datos, comportamiento de búsqueda personalizado y requisitos específicos de implementación. Su flexibilidad lo hace ideal para equipos que necesitan ajustar su arquitectura de búsqueda para cumplir con requisitos comerciales únicos.

3.4.3 Pinecone

Pinecone es una sofisticada solución en la nube totalmente administrada, diseñada específicamente para operaciones vectoriales a escala empresarial. En su núcleo, Pinecone utiliza algoritmos avanzados de indexación y arquitectura de computación distribuida para manejar operaciones vectoriales con notable eficiencia. El sistema sobresale en la gestión de millones de vectores de alta dimensionalidad - piensa en estos como representaciones matemáticas complejas de texto, imágenes u otros datos - mientras mantiene un rendimiento consistente de baja latencia, típicamente respondiendo en milisegundos.

Su arquitectura distribuida es particularmente notable, empleando un sofisticado mecanismo de fragmentación que distribuye los datos entre múltiples nodos. Esto garantiza operaciones de búsqueda confiables en conjuntos de datos masivos, con redundancia incorporada y mecanismos automáticos de recuperación ante fallos. Esta robusta infraestructura la hace ideal para:

  • Sistemas de recomendación a gran escala - Estos sistemas procesan millones de interacciones de usuarios en tiempo real y características de productos para entregar recomendaciones personalizadas. Por ejemplo, una plataforma de comercio electrónico podría analizar el historial de navegación, patrones de compra y atributos de productos de millones de usuarios para sugerir artículos relevantes instantáneamente.
  • Plataformas de descubrimiento de contenido - Estas plataformas utilizan algoritmos sofisticados para emparejar contenido a través de vastas bibliotecas multimedia, analizando metadatos, preferencias de usuarios y características de contenido. Pueden procesar contenido multimedia como videos, artículos y música para conectar a los usuarios con contenido relevante que podrían disfrutar, manejando bibliotecas con petabytes de datos.
  • Aplicaciones de búsqueda semántica - Estas aplicaciones comprenden el contexto y significado detrás de las consultas de búsqueda, no solo palabras clave. Entregan resultados altamente relevantes en milisegundos comparando el significado semántico de la consulta contra millones de documentos, teniendo en cuenta matices, sinónimos y conceptos relacionados.
  • Soluciones de servicio al cliente impulsadas por IA - Estos sistemas revolucionan el soporte al cliente al acceder y analizar instantáneamente vastas bases de datos de documentación de soporte, interacciones previas con clientes e información de productos. Pueden comprender las consultas de los clientes en contexto y proporcionar soluciones relevantes procesando datos históricos que abarcan años de interacciones con clientes.

Lo que verdaderamente distingue a Pinecone es su excepcional optimización del rendimiento. La plataforma mantiene tiempos de consulta inferiores al segundo incluso cuando su base de datos vectorial escala a miles de millones de entradas - una hazaña lograda a través de sofisticadas técnicas de indexación como grafos HNSW (Hierarchical Navigable Small World) y particionamiento eficiente de datos. Esto se complementa con características de nivel empresarial que incluyen:

  • Escalado horizontal automático que responde a cargas de trabajo variables
  • Alta disponibilidad a través de implementación multi-región
  • Medidas robustas de seguridad incluyendo cifrado en reposo y en tránsito
  • Capacidades avanzadas de monitoreo y registro
  • Sistemas automáticos de respaldo y recuperación ante desastres

3.4.4 Caso de Uso: Búsqueda Semántica con Pinecone

Ahora veamos cómo integrar embeddings de OpenAI con Pinecone para realizar búsqueda semántica en la nube.

Este código demuestra cómo realizar búsqueda semántica usando OpenAI y Pinecone. La búsqueda semántica va más allá de la coincidencia de palabras clave al comprender el significado de la consulta y los documentos. Utiliza OpenAI para generar embeddings (representaciones numéricas) de texto, y Pinecone, una base de datos vectorial, para almacenar y buscar eficientemente estos embeddings.

Desglose del Código

Aquí hay una explicación paso a paso del código:

Paso 1: Importar Bibliotecas

import openai
import pinecone
import os
from dotenv import load_dotenv
import time  # For exponential backoff
  • openai: Para interactuar con la API de OpenAI y generar embeddings.
  • pinecone: Para interactuar con la base de datos vectorial Pinecone.
  • os: Para acceder a las variables de entorno.
  • dotenv: Para cargar variables de entorno desde un archivo .env.
  • time: Para implementar retroceso exponencial en caso de errores de API.

Paso 2: Cargar Variables de Entorno e Inicializar Clientes

load_dotenv()

# API keys
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
PINECONE_API_KEY = os.getenv("PINECONE_API_KEY")
PINECONE_ENV = os.getenv("PINECONE_ENV")  # e.g., "gcp-starter"

openai.api_key = OPENAI_API_KEY

pinecone.init(
    api_key=PINECONE_API_KEY,
    environment=PINECONE_ENV
)
  • load_dotenv(): Carga variables de entorno desde un archivo .env. Aquí es donde almacenas tus claves API de OpenAI y Pinecone.
  • os.getenv(): Obtiene las claves API y el entorno de Pinecone desde las variables de entorno.
  • El código luego inicializa el cliente de OpenAI con la clave API de OpenAI y el cliente de Pinecone con la clave API y el entorno de Pinecone.

Paso 3: Definir Configuración del Índice de Pinecone

# Pinecone index configuration
INDEX_NAME = "semantic-search-index"
EMBEDDING_MODEL = "text-embedding-3-small"
EMBEDDING_DIMENSION = 1536
SIMILARITY_METRIC = "cosine"
BATCH_SIZE = 100  # Batch size for upserting vectors
  • INDEX_NAME: El nombre del índice de Pinecone.
  • EMBEDDING_MODEL: El modelo de OpenAI utilizado para generar embeddings.
  • EMBEDDING_DIMENSION: La dimensionalidad de los embeddings (1536 para text-embedding-3-small).
  • SIMILARITY_METRIC: La métrica utilizada para medir la similitud entre embeddings (similitud del coseno).
  • BATCH_SIZE: El número de vectores a insertar en Pinecone a la vez.

Paso 4: Función Auxiliar: get_embedding()

def get_embedding(text, model=EMBEDDING_MODEL):
    """Gets the embedding for a given text using OpenAI's API with retry logic."""
    max_retries = 3
    for attempt in range(max_retries):
        try:
            response = openai.Embedding.create(input=text, model=model)
            return response["data"][0]["embedding"]
        except openai.APIError as e:
            print(f"OpenAI API error: {e}")
            if attempt < max_retries - 1:
                time.sleep(2 ** attempt)  # Exponential backoff
            else:
                raise  # Raise the exception if all retries fail
        except Exception as e:
            print(f"Error getting embedding: {e}")
            raise
  • Esta función toma un texto como entrada y devuelve su vector de embedding utilizando la API de OpenAI.
  • Incluye manejo de errores con retroceso exponencial para gestionar posibles errores de la API. Si ocurre un error en la API de OpenAI, reintenta la solicitud hasta max_retries veces, esperando más tiempo entre cada intento.

Paso 5: Función Auxiliar: upsert_embeddings()

def upsert_embeddings(index, documents, batch_size=BATCH_SIZE):
    """Upserts embeddings for a list of documents into Pinecone with batching."""
    vectors = []
    for doc_id, text in documents.items():
        embedding = get_embedding(text)
        vectors.append((doc_id, embedding, {"text": text}))

    for i in range(0, len(vectors), batch_size):
        batch = vectors[i:i + batch_size]
        try:
            index.upsert(vectors=batch)
            print(f"✅ Upserted batch {i // batch_size + 1}/{len(vectors) // batch_size + 1}")
        except pinecone.PineconeException as e:
            print(f"Error upserting batch: {e}")
            raise
  • Esta función toma como entrada un índice de Pinecone, un diccionario de documentos y un tamaño de lote.
  • Genera embeddings para cada documento usando la función get_embedding().
  • Prepara los datos en el formato que espera el método upsert() de Pinecone: una lista de tuplas, donde cada tupla contiene el ID del documento, el vector de embedding y metadatos (en este caso, el texto original).
  • Luego inserta los vectores en Pinecone en lotes, según el batch_size. El procesamiento por lotes es más eficiente para cargar grandes cantidades de datos a Pinecone.

Paso 6: Función Auxiliar: query_pinecone()

def query_pinecone(index, query_text, top_k=2):
    """Queries Pinecone with a given query text and returns the top-k results."""
    query_embedding = get_embedding(query_text)
    try:
        results = index.query(vector=query_embedding, top_k=top_k, include_metadata=True)
        return results
    except pinecone.PineconeException as e:
        print(f"Error querying Pinecone: {e}")
        raise
  • Esta función toma un índice de Pinecone, un texto de consulta y el número de resultados a devolver (top_k).
  • Genera el embedding para el texto de consulta usando get_embedding().
  • Consulta el índice de Pinecone usando el embedding de la consulta, solicitando los top_k vectores más similares. include_metadata=True asegura que también se devuelva el texto original de los documentos coincidentes.
  • Maneja posibles errores de Pinecone.

Paso 7: Función Principal

def main():
    """Main function to perform semantic search with Pinecone and OpenAI."""
    openai.api_key = OPENAI_API_KEY

    pinecone.init(
        api_key=PINECONE_API_KEY,
        environment=PINECONE_ENV
    )

    # Create Pinecone index if it doesn't exist
    if INDEX_NAME not in pinecone.list_indexes():
        try:
            pinecone.create_index(
                name=INDEX_NAME,
                dimension=EMBEDDING_DIMENSION,
                metric=SIMILARITY_METRIC
            )
            print(f"✅ Created Pinecone index: {INDEX_NAME}")
        except pinecone.PineconeException as e:
            print(f"Error creating Pinecone index: {e}")
            return

    index = pinecone.Index(INDEX_NAME)

    # Documents to embed and store in Pinecone
    documents = {
        "doc1": "How to reset your password",
        "doc2": "Updating your billing information",
        "doc3": "Steps to cancel your subscription",
    }

    # Upsert documents into Pinecone
    upsert_embeddings(index, documents)

    # Query Pinecone with a user question
    query_text = "How do I change my payment method?"
    results = query_pinecone(index, query_text)

    # Print the search results
    print("\nSearch Results:")
    for match in results["matches"]:
        print(f"📄 Match: {match['metadata']['text']} (Score: {round(match['score'], 3)})")

    pinecone.deinit()  # Clean up Pinecone connection

if __name__ == "__main__":
    main()
  • Esta es la función principal que orquesta el proceso de búsqueda semántica.
  • Inicializa los clientes de OpenAI y Pinecone.
  • Crea el índice de Pinecone si aún no existe.
  • Define un conjunto de documentos de muestra para indexar.
  • Llama a upsert_embeddings() para almacenar los embeddings de documentos en Pinecone.
  • Define una consulta y llama a query_pinecone() para realizar la búsqueda.
  • Imprime los resultados de la búsqueda, incluyendo los documentos coincidentes y sus puntajes de similitud.
  • Llama a pinecone.deinit() para limpiar la conexión de Pinecone.
  • El bloque if __name__ == "__main__": asegura que la función main() se ejecute cuando se ejecuta el script.

3.4.5 Chroma

Chroma es una base de datos vectorial sofisticada y amigable para desarrolladores, específicamente diseñada para operaciones eficientes de almacenamiento y recuperación de embeddings. Lo que la distingue es su rendimiento excepcional en entornos de desarrollo local y aplicaciones de menor escala, gracias a su arquitectura ligera y proceso de configuración simplificado. A diferencia de soluciones más complejas, Chroma prioriza la experiencia del desarrollador sin sacrificar funcionalidad.

La base de datos ofrece varias características y capacidades poderosas que la hacen destacar:

  • Fácil integración con frameworks populares de ML
    • Proporciona soporte integral para las principales bibliotecas de aprendizaje automático, incluyendo PyTorch, TensorFlow y scikit-learn, permitiendo una integración fluida con pipelines de ML existentes
    • Presenta un diseño de API intuitivo que reduce significativamente el tiempo y la complejidad del desarrollo, haciéndola accesible tanto para principiantes como para desarrolladores experimentados
    • Incluye documentación extensa y ejemplos de código para ayudar a los desarrolladores a comenzar rápidamente
  • Soporte incorporado para múltiples modelos de embedding
    • Ofrece compatibilidad inmediata con proveedores líderes de embeddings como OpenAI, Hugging Face y Sentence Transformers, permitiendo diversas opciones de modelos
    • Implementa una arquitectura flexible que permite a los desarrolladores cambiar fácilmente entre diferentes modelos de embedding sin requerir modificaciones extensas del código
    • Admite funciones de embedding personalizadas para casos de uso especializados
  • Opciones robustas de almacenamiento persistente para durabilidad de datos
    • Soporta varios backends de almacenamiento incluyendo SQLite para desarrollo local y PostgreSQL para entornos de producción, asegurando la persistencia de datos en diferentes escalas
    • Presenta mecanismos sofisticados de recuperación de datos que protegen contra pérdida de datos y fallos del sistema
    • Implementa estrategias eficientes de indexación para un rendimiento óptimo de consultas
  • Requisitos mínimos de recursos, perfecta para prototipado
    • Gestión optimizada de memoria asegura una utilización eficiente de recursos, haciéndola adecuada para máquinas de desarrollo
    • Tiempos de inicio rápidos permiten ciclos rápidos de desarrollo y pruebas
    • Elimina la necesidad de servicios externos complejos o infraestructura, reduciendo la complejidad y costos de implementación

Si bien Chroma puede no igualar la escalabilidad de soluciones basadas en la nube como Pinecone al manejar conjuntos de datos masivos (típicamente aquellos que exceden millones de vectores), su simplicidad y capacidades de desarrollo rápido la convierten en una excelente opción para desarrolladores que construyen pruebas de concepto o aplicaciones con requisitos moderados de datos. La base de datos es particularmente adecuada para proyectos que necesitan ciclos rápidos de iteración, desarrollo y pruebas locales, o implementación en entornos donde los servicios en la nube podrían no estar fácilmente disponibles o ser rentables.

3.4.6 Usando Chroma para Proyectos Locales

Este ejemplo demuestra cómo realizar búsqueda semántica usando Chroma, una base de datos vectorial local y ligera. Al igual que el ejemplo de Pinecone, utiliza embeddings para capturar el significado del texto, pero Chroma está específicamente diseñada para casos de uso locales.

Desglose del Código

Aquí hay una explicación paso a paso del código:

Paso 1: Instalar Biblioteca

pip install chromadb
  • Este comando instala la biblioteca chromadb, que proporciona las herramientas necesarias para trabajar con la base de datos vectorial Chroma.

Paso 2: Importar Bibliotecas

import chromadb
from chromadb.utils.embedding_functions import OpenAIEmbeddingFunction
import os
from dotenv import load_dotenv

load_dotenv()
  • chromadb: La biblioteca principal de Chroma.
  • OpenAIEmbeddingFunction: Una función de utilidad de Chroma para usar la API de OpenAI en la generación de embeddings.
  • os: Para acceder a las variables de entorno (para obtener la clave API de OpenAI).
  • dotenv: Para cargar variables de entorno desde un archivo .env.

Paso 3: Inicializar el Cliente de Chroma

client = chromadb.Client()
  • Esta línea crea un objeto cliente de Chroma. En la configuración predeterminada, Chroma se ejecuta localmente.

Paso 4: Crear una Colección

collection = client.create_collection(name="my_embeddings")
  • Esto crea una colección en Chroma. Una colección es similar a un índice en Pinecone; es donde almacenas y consultas tus embeddings. La colección se llama "my_embeddings".

Paso 5: Inicializar la Función de Embedding de OpenAI

embedding_function = OpenAIEmbeddingFunction(api_key=os.getenv("OPENAI_API_KEY"))
  • Esto crea una instancia de OpenAIEmbeddingFunction, que se utilizará para generar embeddings usando la API de OpenAI. Obtiene la clave API de OpenAI desde las variables de entorno.

Paso 6: Agregar Documentos a la Colección

collection.add(
    documents=["Learn how to train a model", "Understanding neural networks"],
    ids=["doc1", "doc2"]
)
  • Esto agrega documentos y sus IDs correspondientes a la colección "my_embeddings".
    • documents: Una lista de documentos de texto.
    • ids: Una lista de identificadores únicos para cada documento. Chroma usa estos IDs para rastrear los vectores. El orden de los ids debe corresponder al orden de los documents.
  • Entre bastidores, Chroma utiliza la embedding_function (la función de embedding de OpenAI) para generar embeddings para los documentos proporcionados. Estos embeddings se almacenan en la colección junto con los documentos e IDs.

Paso 7: Realizar una Consulta

query = "How do I build an AI model?"
results = collection.query(query_texts=[query], n_results=1)
print("🔍 Best Match:", results["documents"][0][0])
  • query: El texto de la consulta.
  • collection.query(): Esto realiza la búsqueda.
    • query_texts: Una lista que contiene el texto de la consulta. Incluso si solo estás consultando un fragmento de texto, Chroma espera una lista.
    • n_results: El número de vecinos más cercanos (documentos más similares) a recuperar. Aquí, está configurado en 1, por lo que recupera la única mejor coincidencia.
  • El código luego imprime el texto del documento con mejor coincidencia. results["documents"] es una lista de listas. La lista exterior corresponde a las consultas (en este caso, una sola consulta), y la lista interior contiene los documentos.

3.4.7 Weaviate

Weaviate es una potente base de datos vectorial de código abierto que combina la búsqueda tradicional basada en palabras clave con la búsqueda por similitud vectorial de una manera única. A diferencia de las bases de datos vectoriales simples que solo realizan coincidencias por similitud, las capacidades de búsqueda híbrida de Weaviate le permiten comprender simultáneamente tanto las palabras exactas (palabras clave) como el significado subyacente (semántica) de una consulta. Este enfoque dual significa que puede manejar consultas complejas como "Encontrar documentos sobre aprendizaje automático que mencionen programación en Python" combinando tanto la comprensión semántica como la coincidencia específica de palabras clave.

Lo que distingue a Weaviate es su arquitectura integral. Ofrece múltiples formas de interactuar con la base de datos: GraphQL para consultas flexibles y estructuradas; APIs RESTful para integración web tradicional; y soporte para varios modelos de aprendizaje automático que se pueden conectar según tus necesidades. Esta flexibilidad significa que los desarrolladores pueden elegir el enfoque más apropiado para su caso de uso específico.

La plataforma incluye varias características poderosas que revolucionan cómo trabajamos con bases de datos vectoriales:

  • Gestión Automática de Esquemas
    • Inferencia Inteligente de Esquemas: La IA de Weaviate analiza los patrones de tu conjunto de datos y recomienda automáticamente estructuras de datos óptimas, ahorrando horas de configuración manual
    • Organización Inteligente de Datos: Utiliza algoritmos avanzados para categorizar, etiquetar y estructurar automáticamente tus datos basándose en similitudes y relaciones de contenido
    • Evolución Dinámica de Esquemas: Adapta tu estructura de datos sobre la marcha a medida que tu aplicación crece, sin tiempo de inactividad ni dolores de cabeza por migración de datos
  • Procesamiento Avanzado en Tiempo Real
    • Indexación Instantánea: A diferencia de las bases de datos tradicionales que requieren procesamiento por lotes, Weaviate indexa nuevos datos en el momento en que llegan
    • Disponibilidad sin Latencia: Los nuevos datos se pueden buscar inmediatamente, perfecto para aplicaciones que requieren actualizaciones en tiempo real
    • Sincronización Continua: Los resultados de búsqueda incorporan automáticamente nuevos datos, asegurando que los usuarios siempre vean la información más actualizada
  • Capacidades Multimodales Integrales
    • Comprensión Avanzada de Texto: Utiliza modelos de PNL de última generación para comprender el contexto, el sentimiento y las relaciones semánticas en datos de texto
    • Análisis Sofisticado de Imágenes: Implementa algoritmos de visión por computadora para búsqueda de similitud visual, detección de objetos y clasificación de imágenes
    • Sistema de Tipos Extensible: Construye tipos de datos personalizados con lógica de procesamiento especializada para tus casos de uso únicos, desde procesamiento de audio hasta análisis de datos científicos

3.4.8 Búsqueda Semántica usando Weaviate

Este caso de uso demuestra cómo realizar búsqueda semántica usando Weaviate. La búsqueda semántica mejora la búsqueda tradicional basada en palabras clave al comprender el significado de las consultas y documentos, devolviendo resultados más relevantes. Weaviate almacena objetos de datos y sus embeddings vectoriales correspondientes, permitiendo una recuperación eficiente basada en similitud. Este ejemplo usa OpenAI para generar los embeddings.

Paso 1: Instalar Bibliotecas Requeridas

pip install weaviate-client
  • Este comando instala la biblioteca weaviate-client, que proporciona el cliente de Python para interactuar con Weaviate.

Paso 2: Configurar el Cliente de Weaviate

import weaviate
import os
from dotenv import load_dotenv

load_dotenv()  # Load environment variables

client = weaviate.Client(
    url=os.getenv("WEAVIATE_URL"),  # Replace with your Weaviate URL
    #   auth_client_secret=weaviate.auth.AuthApiKey(api_key=os.getenv("WEAVIATE_API_KEY")) #Uncomment if you are using an API key.
)
  • import weaviate: Importa la biblioteca cliente de Weaviate.
  • import os: Importa el módulo os para acceder a las variables de entorno.
  • from dotenv import load_dotenv: Importa la función load_dotenv de la biblioteca dotenv para cargar variables de entorno desde un archivo .env.
  • load_dotenv(): Carga las variables de entorno desde un archivo .env. Aquí es donde debes almacenar tu URL de Weaviate (y la clave API, si corresponde).
  • client = weaviate.Client(...): Inicializa una instancia del cliente de Weaviate, estableciendo una conexión con el servidor de Weaviate.
    • url: Especifica la URL de tu instancia de Weaviate. Esta se obtiene de la variable de entorno WEAVIATE_URL.
    • auth_client_secret: (Opcional) Si tu instancia de Weaviate requiere autenticación, puedes proporcionar una clave API usando weaviate.auth.AuthApiKey. La clave API debe almacenarse en la variable de entorno WEAVIATE_API_KEY.

Paso 3: Definir el Esquema

class_schema = {
    "class": "Document",
    "description": "A document to be used for semantic search",
    "properties": [
        {
            "name": "content",
            "dataType": ["text"],
            "description": "The text content of the document",
        },
    ],
}

if not client.schema.exists("Document"):
    client.schema.create_class(class_schema)
  • class_schema: Define el esquema para una clase en Weaviate. Una clase es una colección de objetos de datos (similar a una tabla en una base de datos relacional).
  • class: El nombre de la clase ("Document" en este caso).
  • description: Una descripción de la clase.
  • properties: Una lista de propiedades que tiene la clase.
    • name: El nombre de la propiedad ("content").
    • dataType: El tipo de datos de la propiedad (["text"] en este caso).
    • description: Una descripción de la propiedad.
  • if not client.schema.exists("Document"): Verifica si ya existe una clase llamada "Document" en el esquema de Weaviate.
  • client.schema.create_class(class_schema): Si la clase no existe, esto crea la clase en Weaviate con el esquema definido.

Paso 4: Importar Datos (Almacenar Objetos)

import openai

openai.api_key = os.getenv("OPENAI_API_KEY")


def get_embedding(text):
    response = openai.Embedding.create(
        input=text,
        model="text-embedding-3-small"  # Or your preferred embedding model
    )
    return response["data"][0]["embedding"]



documents = [
    {"content": "How to reset your password"},
    {"content": "Updating your billing information"},
    {"content": "Steps to cancel your subscription"},
]

with client.batch(batch_size=100) as batch:
    for i, doc in enumerate(documents):
        try:
            embedding = get_embedding(doc["content"])
            data_object = {
                "content": doc["content"],
            }
            batch.add_data_object(
                data_object=data_object,
                class_name="Document",
                vector=embedding,
            )
            print(f"Imported document {i + 1}/{len(documents)}")
        except Exception as e:
            print(f"Error importing document {i + 1}: {e}")
  • import openai: Importa la biblioteca OpenAI para usar en la generación de embeddings.
  • openai.api_key = os.getenv("OPENAI_API_KEY"): Establece la clave API de OpenAI usando el valor de la variable de entorno OPENAI_API_KEY.
  • get_embedding(text):
    • Toma una cadena de texto como entrada.
    • Llama a la API de OpenAI para generar un vector de embedding para el texto.
    • Devuelve el vector de embedding.
  • documents: Una lista de diccionarios, donde cada diccionario representa un documento que se almacenará en Weaviate.
  • with client.batch(batch_size=100) as batch: Inicializa un proceso de importación por lotes. Esto es más eficiente para importar múltiples objetos. El parámetro batch_size especifica el número de objetos a incluir en cada lote.
  • El bucle for itera a través de la lista documents:
    • embedding = get_embedding(doc["content"]): Genera el vector de embedding para el contenido del documento usando la función get_embedding.
    • data_object: Crea un diccionario que representa el objeto de datos a almacenar en Weaviate.
    • batch.add_data_object(...): Añade el objeto de datos al lote actual.
      • data_object: El diccionario del objeto de datos.
      • class_name: El nombre de la clase a la que pertenece el objeto ("Document").
      • vector: El vector de embedding para el objeto de datos.
    • El bloque try...except maneja posibles errores durante el proceso de importación.

Paso 5: Consultar Weaviate

query_text = "How do I change my payment method?"
query_vector = get_embedding(query_text)

results = (
    client.query
    .get("Document", ["content"])  # Specify the class and properties to retrieve
    .with_near_vector(
        {"vector": query_vector}
    )
    .with_limit(2)  # Limit the number of results
    .do()
)

print("Search Results:")
for result in results["data"]["Get"]["Document"]:
    print(f"📄 Match: {result['content']}")
  • query_text: El texto de la consulta.
  • query_vector = get_embedding(query_text): Genera el vector de embedding para el texto de la consulta usando la función get_embedding.
  • results = client.query.get("Document", ["content"]).with_near_vector({"vector": query_vector}).with_limit(2).do(): Construye y ejecuta la consulta.
    • client.query.get("Document", ["content"]): Especifica la clase a consultar ("Document") y las propiedades a recuperar ("content").
    • with_near_vector({"vector": query_vector}): Especifica que la consulta debe encontrar objetos cuyos vectores estén más cercanos al query_vector.
    • with_limit(2): Limita el número de resultados a los 2 mejores.
    • do(): Ejecuta la consulta.
  • El código luego imprime los resultados de la búsqueda, extrayendo el contenido de cada documento encontrado.

Más información: https://weaviate.io

Resumen Breve

En este completo capítulo, has adquirido conocimientos valiosos en varias áreas clave:

  • Bases de Datos Vectoriales e IA Escalable
    • Comprender cómo las bases de datos vectoriales sirven como columna vertebral para aplicaciones de IA a gran escala
    • Aprender por qué las bases de datos tradicionales se quedan cortas para la búsqueda y recuperación impulsada por IA
    • Explorar los principios arquitectónicos que hacen que las bases de datos vectoriales sean eficientes a escala
  • Implementación de Pinecone
    • Configurar y ajustar Pinecone para entornos de producción
    • Gestionar embeddings vectoriales en una arquitectura distribuida en la nube
    • Optimizar el rendimiento del índice y la eficiencia de las consultas
  • Construcción de Sistemas de Búsqueda Global
    • Implementar búsqueda semántica que comprende el contexto y significado
    • Diseñar sistemas que mantienen tiempos de respuesta rápidos a escala global
    • Manejar requisitos de búsqueda multilingüe y transcultural
  • Soluciones Alternativas
    • Chroma: Perfecto para implementaciones pequeñas y prototipos rápidos
    • Weaviate: Ideal para búsqueda híbrida y relaciones de datos complejas
    • Entender cuándo elegir cada solución según casos de uso específicos

Armado con este conocimiento, ahora estás equipado para ir más allá de los prototipos básicos y crear aplicaciones de IA sofisticadas de nivel producción que aprovechan todo el poder de los embeddings, la comprensión contextual y la búsqueda inteligente a escala. Ya sea que estés construyendo una aplicación pequeña o un sistema global, tienes las herramientas para elegir e implementar la solución correcta para tus necesidades.

3.4 Introducción a Pinecone y Otras Bases de Datos Vectoriales

En esta sección, profundizaremos en las bases de datos vectoriales - sistemas especializados diseñados para manejar datos de alta dimensión eficientemente. Estas poderosas herramientas están revolucionando cómo almacenamos y recuperamos representaciones complejas de datos.

Exploraremos tres soluciones líderes que sirven diferentes necesidades:

  • Pinecone: Una solución en la nube totalmente administrada perfecta para aplicaciones empresariales que necesitan manejar millones de vectores con rendimiento consistente
  • Chroma: Una base de datos eficiente y amigable para desarrolladores, ideal para desarrollo local y aplicaciones de menor escala
  • Weaviate: Una opción robusta de código abierto que sobresale en capacidades de búsqueda híbrida

Aprenderás cómo estas bases de datos te permiten:

  • Almacenar y gestionar vastas colecciones de embeddings (representaciones vectoriales de texto, imágenes u otros datos)
  • Realizar búsquedas de similitud ultrarrápidas en conjuntos de datos masivos
  • Escalar tus aplicaciones sin problemas desde prototipo a producción
  • Mantener un rendimiento consistente incluso cuando tus datos crecen

Lo más importante, te mostraremos cómo estas herramientas mantienen tiempos de respuesta y fiabilidad excepcionales mientras operan en entornos en la nube, haciéndolas perfectas para aplicaciones de IA a nivel de producción.

3.4.1 ¿Qué son las Bases de Datos Vectoriales?

Una base de datos vectorial es un sistema especializado diseñado para almacenar y recuperar eficientemente embeddings — representaciones numéricas de alta dimensión de contenido como texto, audio o imágenes. Estos embeddings son esencialmente largas listas de números (vectores) que representan las características y el significado del contenido. Por ejemplo, una sola frase podría convertirse en un vector de 1,536 números, donde cada número captura algún aspecto del significado, tono o estructura de la frase. Estos embeddings capturan el significado semántico del contenido en un formato que las computadoras pueden procesar eficientemente, haciendo posible encontrar contenido similar mediante la comparación de estos patrones numéricos.

Para ilustrar este concepto, imagina cada pieza de contenido como un punto en un vasto espacio multidimensional. El contenido similar aparece más cerca entre sí en este espacio, mientras que el contenido diferente aparece alejado. Por ejemplo, dos artículos sobre "cocinar pasta" tendrían representaciones vectoriales similares y por lo tanto estarían cerca uno del otro en este espacio, mientras que un artículo sobre "física cuántica" estaría ubicado lejos de ellos.

Las bases de datos tradicionales sobresalen en el almacenamiento de datos estructurados, pero tienen dificultades con los desafíos únicos de las operaciones vectoriales. Estos desafíos incluyen encontrar eficientemente los vecinos más cercanos en el espacio de alta dimensión, manejar la complejidad computacional de los cálculos de similitud y gestionar los requisitos de memoria de grandes conjuntos de datos vectoriales. Si bien bibliotecas como FAISS funcionan bien en tu máquina local, no persisten los datos entre sesiones ni escalan fácilmente a millones de vectores. Ahí es donde entran las bases de datos vectoriales, ofreciendo soluciones especializadas para operaciones vectoriales a gran escala. Estas bases de datos están específicamente diseñadas para manejar las complejidades de las matemáticas vectoriales mientras proporcionan la confiabilidad y escalabilidad de los sistemas de bases de datos tradicionales.

Estos sistemas sofisticados proporcionan varias capacidades cruciales que los hacen indispensables para las aplicaciones modernas de IA:

  • Almacenar y gestionar miles de millones de embeddings con estructuras de almacenamiento optimizadas diseñadas específicamente para datos vectoriales de alta dimensión. Estas estructuras utilizan técnicas avanzadas de compresión y asignación eficiente de memoria para manejar cantidades masivas de datos vectoriales mientras mantienen tiempos de acceso rápidos.
  • Admiten búsqueda vectorial en tiempo real con filtros, utilizando técnicas avanzadas de indexación como grafos HNSW (Hierarchical Navigable Small World). Estos grafos crean múltiples capas de conexiones entre vectores, permitiendo que el sistema navegue rápidamente a través del espacio vectorial y encuentre elementos similares en microsegundos, incluso cuando se trata de miles de millones de vectores. La capacidad de filtrado permite combinar consultas de bases de datos tradicionales con búsqueda de similitud vectorial.
  • Se integran perfectamente con APIs y servicios en la nube, ofreciendo arquitectura distribuida para alta disponibilidad y escalado automático. Esto significa que tu base de datos vectorial puede manejar automáticamente cargas de trabajo crecientes distribuyendo datos entre múltiples servidores, asegurando un rendimiento consistente incluso durante momentos de uso máximo. La arquitectura nativa en la nube también proporciona redundancia y tolerancia a fallos incorporadas.
  • Permiten combinar metadatos + similitud vectorial para consultas más inteligentes, habilitando filtrado y clasificación sofisticados basados tanto en similitud semántica como en criterios tradicionales de bases de datos. Por ejemplo, puedes buscar documentos que sean semánticamente similares a una consulta mientras filtras por rango de fechas, categoría o cualquier otro campo de metadatos. Este enfoque híbrido proporciona resultados de búsqueda más precisos y relevantes.
  • Garantizan la persistencia y consistencia de datos a través de múltiples sesiones y usuarios, haciéndolas adecuadas para entornos de producción. A diferencia de las soluciones en memoria, las bases de datos vectoriales proporcionan cumplimiento ACID (Atomicidad, Consistencia, Aislamiento, Durabilidad) y soporte de transacciones, asegurando que tus datos permanezcan confiables y consistentes incluso en caso de fallos del sistema o acceso concurrente.

Principales actores de un vistazo



3.4.2 Eligiendo la base de datos vectorial adecuada: Pinecone, Chroma o Weaviate

Cada base de datos vectorial tiene sus características únicas y casos de uso especializados. Explorémoslas en detalle:

Pinecone

  • Mejor para: Aplicaciones de producción a gran escala que exigen alta disponibilidad consistente y rendimiento superior. Esto lo hace particularmente adecuado para empresas que manejan millones de consultas por día, especialmente aquellas que ejecutan aplicaciones de IA críticas como sistemas de recomendación en tiempo real, plataformas de moderación de contenido o servicios de búsqueda a gran escala.
  • Ventajas: Como servicio en la nube totalmente administrado, Pinecone elimina las complejidades de infraestructura al manejar todas las operaciones backend. Su red de distribución global asegura una latencia mínima independientemente de la ubicación del usuario, mientras que el escalado automático ajusta los recursos según la demanda, desde manejar unos pocos miles hasta millones de consultas. La plataforma incluye características de seguridad de nivel empresarial como cumplimiento SOC 2, cifrado en reposo y en tránsito, y control de acceso basado en roles (RBAC) para la gestión de equipos.
  • Usar cuando: Tu aplicación requiere confiabilidad de nivel profesional y rendimiento consistente, particularmente en entornos de alta exigencia donde el tiempo de inactividad podría ser costoso. Si bien viene con un precio premium, la inversión se justifica para empresas que necesitan tiempo de actividad garantizado, tiempos de consulta predecibles y soporte de nivel empresarial. Es especialmente valioso para entornos de producción que manejan datos sensibles o sirven a una base de usuarios global donde la confiabilidad del sistema impacta directamente en las operaciones comerciales.

Chroma

  • Mejor para: Entornos de desarrollo, proyectos de prueba de concepto y aplicaciones más pequeñas que no requieren escala masiva. Es particularmente adecuado para investigadores y desarrolladores que trabajan en prototipos de IA, experimentos de ciencia de datos y flujos de trabajo de desarrollo local. Su naturaleza ligera lo hace perfecto para prototipado rápido y pruebas de diferentes enfoques de embeddings sin la sobrecarga de infraestructura en la nube.
  • Ventajas: Chroma ofrece un proceso de configuración extremadamente simple que puede completarse en minutos - solo pip install y estás listo para comenzar. Su integración nativa con Python significa una integración perfecta con herramientas populares de ciencia de datos y ML como pandas, numpy y scikit-learn. Al ser completamente gratuito y de código abierto, permite experimentación ilimitada sin preocupaciones de costos. Los requisitos mínimos de recursos significan que puede funcionar eficientemente incluso en hardware modesto. Además, incluye soporte integrado para modelos de embeddings populares de OpenAI, Cohere y otros proveedores, facilitando la experimentación con diferentes estrategias de embeddings.
  • Usar cuando: Estás desarrollando localmente y necesitas ciclos rápidos de iteración para probar diferentes enfoques. Es ideal para entornos educativos donde los estudiantes están aprendiendo sobre embeddings y búsqueda vectorial. Perfecto para construir aplicaciones autocontenidas sin dependencias externas, especialmente cuando quieres evitar la complejidad y el costo de los servicios en la nube. Chroma brilla en escenarios donde necesitas prototipar rápidamente y validar características basadas en embeddings antes de pasar a un entorno de producción. También es excelente para proyectos de investigación donde necesitas control completo sobre el pipeline de embeddings y quieres experimentar con diferentes configuraciones.

Weaviate

  • Ideal para: Aplicaciones que necesitan funcionalidad de búsqueda sofisticada combinando búsqueda tradicional por palabras clave con similitud vectorial. Este enfoque dual lo hace particularmente potente para sistemas de gestión de contenido, plataformas de comercio electrónico y aplicaciones de búsqueda avanzada donde los usuarios pueden combinar consultas en lenguaje natural con criterios específicos de filtrado. Sus capacidades de búsqueda híbrida sobresalen en escenarios donde las coincidencias exactas y la comprensión semántica necesitan trabajar juntas de manera fluida.
  • Ventajas: Como solución de código abierto, Weaviate ofrece flexibilidad y opciones de personalización sin igual. Sus potentes capacidades de diseño de esquemas permiten a los desarrolladores definir estructuras de datos complejas con propiedades personalizadas, relaciones y reglas de validación. La plataforma admite múltiples paradigmas de búsqueda, incluyendo búsqueda semántica para comprender el significado de las consultas, búsqueda tradicional por palabras clave para coincidencias exactas, y búsqueda híbrida que combina inteligentemente ambos enfoques. Además, ofrece opciones de implementación tanto en la nube como autoalojadas, dando a las organizaciones control completo sobre sus datos e infraestructura.
  • Usar cuando: Tu proyecto requiere la sofisticación tanto de búsqueda por similitud vectorial como características de búsqueda tradicional en una plataforma unificada. Es particularmente valioso para organizaciones que construyen sistemas complejos de gestión del conocimiento, interfaces de búsqueda avanzada o motores de recomendación de contenido. La plataforma destaca en escenarios que requieren control granular sobre la estructura de datos, comportamiento de búsqueda personalizado y requisitos específicos de implementación. Su flexibilidad lo hace ideal para equipos que necesitan ajustar su arquitectura de búsqueda para cumplir con requisitos comerciales únicos.

3.4.3 Pinecone

Pinecone es una sofisticada solución en la nube totalmente administrada, diseñada específicamente para operaciones vectoriales a escala empresarial. En su núcleo, Pinecone utiliza algoritmos avanzados de indexación y arquitectura de computación distribuida para manejar operaciones vectoriales con notable eficiencia. El sistema sobresale en la gestión de millones de vectores de alta dimensionalidad - piensa en estos como representaciones matemáticas complejas de texto, imágenes u otros datos - mientras mantiene un rendimiento consistente de baja latencia, típicamente respondiendo en milisegundos.

Su arquitectura distribuida es particularmente notable, empleando un sofisticado mecanismo de fragmentación que distribuye los datos entre múltiples nodos. Esto garantiza operaciones de búsqueda confiables en conjuntos de datos masivos, con redundancia incorporada y mecanismos automáticos de recuperación ante fallos. Esta robusta infraestructura la hace ideal para:

  • Sistemas de recomendación a gran escala - Estos sistemas procesan millones de interacciones de usuarios en tiempo real y características de productos para entregar recomendaciones personalizadas. Por ejemplo, una plataforma de comercio electrónico podría analizar el historial de navegación, patrones de compra y atributos de productos de millones de usuarios para sugerir artículos relevantes instantáneamente.
  • Plataformas de descubrimiento de contenido - Estas plataformas utilizan algoritmos sofisticados para emparejar contenido a través de vastas bibliotecas multimedia, analizando metadatos, preferencias de usuarios y características de contenido. Pueden procesar contenido multimedia como videos, artículos y música para conectar a los usuarios con contenido relevante que podrían disfrutar, manejando bibliotecas con petabytes de datos.
  • Aplicaciones de búsqueda semántica - Estas aplicaciones comprenden el contexto y significado detrás de las consultas de búsqueda, no solo palabras clave. Entregan resultados altamente relevantes en milisegundos comparando el significado semántico de la consulta contra millones de documentos, teniendo en cuenta matices, sinónimos y conceptos relacionados.
  • Soluciones de servicio al cliente impulsadas por IA - Estos sistemas revolucionan el soporte al cliente al acceder y analizar instantáneamente vastas bases de datos de documentación de soporte, interacciones previas con clientes e información de productos. Pueden comprender las consultas de los clientes en contexto y proporcionar soluciones relevantes procesando datos históricos que abarcan años de interacciones con clientes.

Lo que verdaderamente distingue a Pinecone es su excepcional optimización del rendimiento. La plataforma mantiene tiempos de consulta inferiores al segundo incluso cuando su base de datos vectorial escala a miles de millones de entradas - una hazaña lograda a través de sofisticadas técnicas de indexación como grafos HNSW (Hierarchical Navigable Small World) y particionamiento eficiente de datos. Esto se complementa con características de nivel empresarial que incluyen:

  • Escalado horizontal automático que responde a cargas de trabajo variables
  • Alta disponibilidad a través de implementación multi-región
  • Medidas robustas de seguridad incluyendo cifrado en reposo y en tránsito
  • Capacidades avanzadas de monitoreo y registro
  • Sistemas automáticos de respaldo y recuperación ante desastres

3.4.4 Caso de Uso: Búsqueda Semántica con Pinecone

Ahora veamos cómo integrar embeddings de OpenAI con Pinecone para realizar búsqueda semántica en la nube.

Este código demuestra cómo realizar búsqueda semántica usando OpenAI y Pinecone. La búsqueda semántica va más allá de la coincidencia de palabras clave al comprender el significado de la consulta y los documentos. Utiliza OpenAI para generar embeddings (representaciones numéricas) de texto, y Pinecone, una base de datos vectorial, para almacenar y buscar eficientemente estos embeddings.

Desglose del Código

Aquí hay una explicación paso a paso del código:

Paso 1: Importar Bibliotecas

import openai
import pinecone
import os
from dotenv import load_dotenv
import time  # For exponential backoff
  • openai: Para interactuar con la API de OpenAI y generar embeddings.
  • pinecone: Para interactuar con la base de datos vectorial Pinecone.
  • os: Para acceder a las variables de entorno.
  • dotenv: Para cargar variables de entorno desde un archivo .env.
  • time: Para implementar retroceso exponencial en caso de errores de API.

Paso 2: Cargar Variables de Entorno e Inicializar Clientes

load_dotenv()

# API keys
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
PINECONE_API_KEY = os.getenv("PINECONE_API_KEY")
PINECONE_ENV = os.getenv("PINECONE_ENV")  # e.g., "gcp-starter"

openai.api_key = OPENAI_API_KEY

pinecone.init(
    api_key=PINECONE_API_KEY,
    environment=PINECONE_ENV
)
  • load_dotenv(): Carga variables de entorno desde un archivo .env. Aquí es donde almacenas tus claves API de OpenAI y Pinecone.
  • os.getenv(): Obtiene las claves API y el entorno de Pinecone desde las variables de entorno.
  • El código luego inicializa el cliente de OpenAI con la clave API de OpenAI y el cliente de Pinecone con la clave API y el entorno de Pinecone.

Paso 3: Definir Configuración del Índice de Pinecone

# Pinecone index configuration
INDEX_NAME = "semantic-search-index"
EMBEDDING_MODEL = "text-embedding-3-small"
EMBEDDING_DIMENSION = 1536
SIMILARITY_METRIC = "cosine"
BATCH_SIZE = 100  # Batch size for upserting vectors
  • INDEX_NAME: El nombre del índice de Pinecone.
  • EMBEDDING_MODEL: El modelo de OpenAI utilizado para generar embeddings.
  • EMBEDDING_DIMENSION: La dimensionalidad de los embeddings (1536 para text-embedding-3-small).
  • SIMILARITY_METRIC: La métrica utilizada para medir la similitud entre embeddings (similitud del coseno).
  • BATCH_SIZE: El número de vectores a insertar en Pinecone a la vez.

Paso 4: Función Auxiliar: get_embedding()

def get_embedding(text, model=EMBEDDING_MODEL):
    """Gets the embedding for a given text using OpenAI's API with retry logic."""
    max_retries = 3
    for attempt in range(max_retries):
        try:
            response = openai.Embedding.create(input=text, model=model)
            return response["data"][0]["embedding"]
        except openai.APIError as e:
            print(f"OpenAI API error: {e}")
            if attempt < max_retries - 1:
                time.sleep(2 ** attempt)  # Exponential backoff
            else:
                raise  # Raise the exception if all retries fail
        except Exception as e:
            print(f"Error getting embedding: {e}")
            raise
  • Esta función toma un texto como entrada y devuelve su vector de embedding utilizando la API de OpenAI.
  • Incluye manejo de errores con retroceso exponencial para gestionar posibles errores de la API. Si ocurre un error en la API de OpenAI, reintenta la solicitud hasta max_retries veces, esperando más tiempo entre cada intento.

Paso 5: Función Auxiliar: upsert_embeddings()

def upsert_embeddings(index, documents, batch_size=BATCH_SIZE):
    """Upserts embeddings for a list of documents into Pinecone with batching."""
    vectors = []
    for doc_id, text in documents.items():
        embedding = get_embedding(text)
        vectors.append((doc_id, embedding, {"text": text}))

    for i in range(0, len(vectors), batch_size):
        batch = vectors[i:i + batch_size]
        try:
            index.upsert(vectors=batch)
            print(f"✅ Upserted batch {i // batch_size + 1}/{len(vectors) // batch_size + 1}")
        except pinecone.PineconeException as e:
            print(f"Error upserting batch: {e}")
            raise
  • Esta función toma como entrada un índice de Pinecone, un diccionario de documentos y un tamaño de lote.
  • Genera embeddings para cada documento usando la función get_embedding().
  • Prepara los datos en el formato que espera el método upsert() de Pinecone: una lista de tuplas, donde cada tupla contiene el ID del documento, el vector de embedding y metadatos (en este caso, el texto original).
  • Luego inserta los vectores en Pinecone en lotes, según el batch_size. El procesamiento por lotes es más eficiente para cargar grandes cantidades de datos a Pinecone.

Paso 6: Función Auxiliar: query_pinecone()

def query_pinecone(index, query_text, top_k=2):
    """Queries Pinecone with a given query text and returns the top-k results."""
    query_embedding = get_embedding(query_text)
    try:
        results = index.query(vector=query_embedding, top_k=top_k, include_metadata=True)
        return results
    except pinecone.PineconeException as e:
        print(f"Error querying Pinecone: {e}")
        raise
  • Esta función toma un índice de Pinecone, un texto de consulta y el número de resultados a devolver (top_k).
  • Genera el embedding para el texto de consulta usando get_embedding().
  • Consulta el índice de Pinecone usando el embedding de la consulta, solicitando los top_k vectores más similares. include_metadata=True asegura que también se devuelva el texto original de los documentos coincidentes.
  • Maneja posibles errores de Pinecone.

Paso 7: Función Principal

def main():
    """Main function to perform semantic search with Pinecone and OpenAI."""
    openai.api_key = OPENAI_API_KEY

    pinecone.init(
        api_key=PINECONE_API_KEY,
        environment=PINECONE_ENV
    )

    # Create Pinecone index if it doesn't exist
    if INDEX_NAME not in pinecone.list_indexes():
        try:
            pinecone.create_index(
                name=INDEX_NAME,
                dimension=EMBEDDING_DIMENSION,
                metric=SIMILARITY_METRIC
            )
            print(f"✅ Created Pinecone index: {INDEX_NAME}")
        except pinecone.PineconeException as e:
            print(f"Error creating Pinecone index: {e}")
            return

    index = pinecone.Index(INDEX_NAME)

    # Documents to embed and store in Pinecone
    documents = {
        "doc1": "How to reset your password",
        "doc2": "Updating your billing information",
        "doc3": "Steps to cancel your subscription",
    }

    # Upsert documents into Pinecone
    upsert_embeddings(index, documents)

    # Query Pinecone with a user question
    query_text = "How do I change my payment method?"
    results = query_pinecone(index, query_text)

    # Print the search results
    print("\nSearch Results:")
    for match in results["matches"]:
        print(f"📄 Match: {match['metadata']['text']} (Score: {round(match['score'], 3)})")

    pinecone.deinit()  # Clean up Pinecone connection

if __name__ == "__main__":
    main()
  • Esta es la función principal que orquesta el proceso de búsqueda semántica.
  • Inicializa los clientes de OpenAI y Pinecone.
  • Crea el índice de Pinecone si aún no existe.
  • Define un conjunto de documentos de muestra para indexar.
  • Llama a upsert_embeddings() para almacenar los embeddings de documentos en Pinecone.
  • Define una consulta y llama a query_pinecone() para realizar la búsqueda.
  • Imprime los resultados de la búsqueda, incluyendo los documentos coincidentes y sus puntajes de similitud.
  • Llama a pinecone.deinit() para limpiar la conexión de Pinecone.
  • El bloque if __name__ == "__main__": asegura que la función main() se ejecute cuando se ejecuta el script.

3.4.5 Chroma

Chroma es una base de datos vectorial sofisticada y amigable para desarrolladores, específicamente diseñada para operaciones eficientes de almacenamiento y recuperación de embeddings. Lo que la distingue es su rendimiento excepcional en entornos de desarrollo local y aplicaciones de menor escala, gracias a su arquitectura ligera y proceso de configuración simplificado. A diferencia de soluciones más complejas, Chroma prioriza la experiencia del desarrollador sin sacrificar funcionalidad.

La base de datos ofrece varias características y capacidades poderosas que la hacen destacar:

  • Fácil integración con frameworks populares de ML
    • Proporciona soporte integral para las principales bibliotecas de aprendizaje automático, incluyendo PyTorch, TensorFlow y scikit-learn, permitiendo una integración fluida con pipelines de ML existentes
    • Presenta un diseño de API intuitivo que reduce significativamente el tiempo y la complejidad del desarrollo, haciéndola accesible tanto para principiantes como para desarrolladores experimentados
    • Incluye documentación extensa y ejemplos de código para ayudar a los desarrolladores a comenzar rápidamente
  • Soporte incorporado para múltiples modelos de embedding
    • Ofrece compatibilidad inmediata con proveedores líderes de embeddings como OpenAI, Hugging Face y Sentence Transformers, permitiendo diversas opciones de modelos
    • Implementa una arquitectura flexible que permite a los desarrolladores cambiar fácilmente entre diferentes modelos de embedding sin requerir modificaciones extensas del código
    • Admite funciones de embedding personalizadas para casos de uso especializados
  • Opciones robustas de almacenamiento persistente para durabilidad de datos
    • Soporta varios backends de almacenamiento incluyendo SQLite para desarrollo local y PostgreSQL para entornos de producción, asegurando la persistencia de datos en diferentes escalas
    • Presenta mecanismos sofisticados de recuperación de datos que protegen contra pérdida de datos y fallos del sistema
    • Implementa estrategias eficientes de indexación para un rendimiento óptimo de consultas
  • Requisitos mínimos de recursos, perfecta para prototipado
    • Gestión optimizada de memoria asegura una utilización eficiente de recursos, haciéndola adecuada para máquinas de desarrollo
    • Tiempos de inicio rápidos permiten ciclos rápidos de desarrollo y pruebas
    • Elimina la necesidad de servicios externos complejos o infraestructura, reduciendo la complejidad y costos de implementación

Si bien Chroma puede no igualar la escalabilidad de soluciones basadas en la nube como Pinecone al manejar conjuntos de datos masivos (típicamente aquellos que exceden millones de vectores), su simplicidad y capacidades de desarrollo rápido la convierten en una excelente opción para desarrolladores que construyen pruebas de concepto o aplicaciones con requisitos moderados de datos. La base de datos es particularmente adecuada para proyectos que necesitan ciclos rápidos de iteración, desarrollo y pruebas locales, o implementación en entornos donde los servicios en la nube podrían no estar fácilmente disponibles o ser rentables.

3.4.6 Usando Chroma para Proyectos Locales

Este ejemplo demuestra cómo realizar búsqueda semántica usando Chroma, una base de datos vectorial local y ligera. Al igual que el ejemplo de Pinecone, utiliza embeddings para capturar el significado del texto, pero Chroma está específicamente diseñada para casos de uso locales.

Desglose del Código

Aquí hay una explicación paso a paso del código:

Paso 1: Instalar Biblioteca

pip install chromadb
  • Este comando instala la biblioteca chromadb, que proporciona las herramientas necesarias para trabajar con la base de datos vectorial Chroma.

Paso 2: Importar Bibliotecas

import chromadb
from chromadb.utils.embedding_functions import OpenAIEmbeddingFunction
import os
from dotenv import load_dotenv

load_dotenv()
  • chromadb: La biblioteca principal de Chroma.
  • OpenAIEmbeddingFunction: Una función de utilidad de Chroma para usar la API de OpenAI en la generación de embeddings.
  • os: Para acceder a las variables de entorno (para obtener la clave API de OpenAI).
  • dotenv: Para cargar variables de entorno desde un archivo .env.

Paso 3: Inicializar el Cliente de Chroma

client = chromadb.Client()
  • Esta línea crea un objeto cliente de Chroma. En la configuración predeterminada, Chroma se ejecuta localmente.

Paso 4: Crear una Colección

collection = client.create_collection(name="my_embeddings")
  • Esto crea una colección en Chroma. Una colección es similar a un índice en Pinecone; es donde almacenas y consultas tus embeddings. La colección se llama "my_embeddings".

Paso 5: Inicializar la Función de Embedding de OpenAI

embedding_function = OpenAIEmbeddingFunction(api_key=os.getenv("OPENAI_API_KEY"))
  • Esto crea una instancia de OpenAIEmbeddingFunction, que se utilizará para generar embeddings usando la API de OpenAI. Obtiene la clave API de OpenAI desde las variables de entorno.

Paso 6: Agregar Documentos a la Colección

collection.add(
    documents=["Learn how to train a model", "Understanding neural networks"],
    ids=["doc1", "doc2"]
)
  • Esto agrega documentos y sus IDs correspondientes a la colección "my_embeddings".
    • documents: Una lista de documentos de texto.
    • ids: Una lista de identificadores únicos para cada documento. Chroma usa estos IDs para rastrear los vectores. El orden de los ids debe corresponder al orden de los documents.
  • Entre bastidores, Chroma utiliza la embedding_function (la función de embedding de OpenAI) para generar embeddings para los documentos proporcionados. Estos embeddings se almacenan en la colección junto con los documentos e IDs.

Paso 7: Realizar una Consulta

query = "How do I build an AI model?"
results = collection.query(query_texts=[query], n_results=1)
print("🔍 Best Match:", results["documents"][0][0])
  • query: El texto de la consulta.
  • collection.query(): Esto realiza la búsqueda.
    • query_texts: Una lista que contiene el texto de la consulta. Incluso si solo estás consultando un fragmento de texto, Chroma espera una lista.
    • n_results: El número de vecinos más cercanos (documentos más similares) a recuperar. Aquí, está configurado en 1, por lo que recupera la única mejor coincidencia.
  • El código luego imprime el texto del documento con mejor coincidencia. results["documents"] es una lista de listas. La lista exterior corresponde a las consultas (en este caso, una sola consulta), y la lista interior contiene los documentos.

3.4.7 Weaviate

Weaviate es una potente base de datos vectorial de código abierto que combina la búsqueda tradicional basada en palabras clave con la búsqueda por similitud vectorial de una manera única. A diferencia de las bases de datos vectoriales simples que solo realizan coincidencias por similitud, las capacidades de búsqueda híbrida de Weaviate le permiten comprender simultáneamente tanto las palabras exactas (palabras clave) como el significado subyacente (semántica) de una consulta. Este enfoque dual significa que puede manejar consultas complejas como "Encontrar documentos sobre aprendizaje automático que mencionen programación en Python" combinando tanto la comprensión semántica como la coincidencia específica de palabras clave.

Lo que distingue a Weaviate es su arquitectura integral. Ofrece múltiples formas de interactuar con la base de datos: GraphQL para consultas flexibles y estructuradas; APIs RESTful para integración web tradicional; y soporte para varios modelos de aprendizaje automático que se pueden conectar según tus necesidades. Esta flexibilidad significa que los desarrolladores pueden elegir el enfoque más apropiado para su caso de uso específico.

La plataforma incluye varias características poderosas que revolucionan cómo trabajamos con bases de datos vectoriales:

  • Gestión Automática de Esquemas
    • Inferencia Inteligente de Esquemas: La IA de Weaviate analiza los patrones de tu conjunto de datos y recomienda automáticamente estructuras de datos óptimas, ahorrando horas de configuración manual
    • Organización Inteligente de Datos: Utiliza algoritmos avanzados para categorizar, etiquetar y estructurar automáticamente tus datos basándose en similitudes y relaciones de contenido
    • Evolución Dinámica de Esquemas: Adapta tu estructura de datos sobre la marcha a medida que tu aplicación crece, sin tiempo de inactividad ni dolores de cabeza por migración de datos
  • Procesamiento Avanzado en Tiempo Real
    • Indexación Instantánea: A diferencia de las bases de datos tradicionales que requieren procesamiento por lotes, Weaviate indexa nuevos datos en el momento en que llegan
    • Disponibilidad sin Latencia: Los nuevos datos se pueden buscar inmediatamente, perfecto para aplicaciones que requieren actualizaciones en tiempo real
    • Sincronización Continua: Los resultados de búsqueda incorporan automáticamente nuevos datos, asegurando que los usuarios siempre vean la información más actualizada
  • Capacidades Multimodales Integrales
    • Comprensión Avanzada de Texto: Utiliza modelos de PNL de última generación para comprender el contexto, el sentimiento y las relaciones semánticas en datos de texto
    • Análisis Sofisticado de Imágenes: Implementa algoritmos de visión por computadora para búsqueda de similitud visual, detección de objetos y clasificación de imágenes
    • Sistema de Tipos Extensible: Construye tipos de datos personalizados con lógica de procesamiento especializada para tus casos de uso únicos, desde procesamiento de audio hasta análisis de datos científicos

3.4.8 Búsqueda Semántica usando Weaviate

Este caso de uso demuestra cómo realizar búsqueda semántica usando Weaviate. La búsqueda semántica mejora la búsqueda tradicional basada en palabras clave al comprender el significado de las consultas y documentos, devolviendo resultados más relevantes. Weaviate almacena objetos de datos y sus embeddings vectoriales correspondientes, permitiendo una recuperación eficiente basada en similitud. Este ejemplo usa OpenAI para generar los embeddings.

Paso 1: Instalar Bibliotecas Requeridas

pip install weaviate-client
  • Este comando instala la biblioteca weaviate-client, que proporciona el cliente de Python para interactuar con Weaviate.

Paso 2: Configurar el Cliente de Weaviate

import weaviate
import os
from dotenv import load_dotenv

load_dotenv()  # Load environment variables

client = weaviate.Client(
    url=os.getenv("WEAVIATE_URL"),  # Replace with your Weaviate URL
    #   auth_client_secret=weaviate.auth.AuthApiKey(api_key=os.getenv("WEAVIATE_API_KEY")) #Uncomment if you are using an API key.
)
  • import weaviate: Importa la biblioteca cliente de Weaviate.
  • import os: Importa el módulo os para acceder a las variables de entorno.
  • from dotenv import load_dotenv: Importa la función load_dotenv de la biblioteca dotenv para cargar variables de entorno desde un archivo .env.
  • load_dotenv(): Carga las variables de entorno desde un archivo .env. Aquí es donde debes almacenar tu URL de Weaviate (y la clave API, si corresponde).
  • client = weaviate.Client(...): Inicializa una instancia del cliente de Weaviate, estableciendo una conexión con el servidor de Weaviate.
    • url: Especifica la URL de tu instancia de Weaviate. Esta se obtiene de la variable de entorno WEAVIATE_URL.
    • auth_client_secret: (Opcional) Si tu instancia de Weaviate requiere autenticación, puedes proporcionar una clave API usando weaviate.auth.AuthApiKey. La clave API debe almacenarse en la variable de entorno WEAVIATE_API_KEY.

Paso 3: Definir el Esquema

class_schema = {
    "class": "Document",
    "description": "A document to be used for semantic search",
    "properties": [
        {
            "name": "content",
            "dataType": ["text"],
            "description": "The text content of the document",
        },
    ],
}

if not client.schema.exists("Document"):
    client.schema.create_class(class_schema)
  • class_schema: Define el esquema para una clase en Weaviate. Una clase es una colección de objetos de datos (similar a una tabla en una base de datos relacional).
  • class: El nombre de la clase ("Document" en este caso).
  • description: Una descripción de la clase.
  • properties: Una lista de propiedades que tiene la clase.
    • name: El nombre de la propiedad ("content").
    • dataType: El tipo de datos de la propiedad (["text"] en este caso).
    • description: Una descripción de la propiedad.
  • if not client.schema.exists("Document"): Verifica si ya existe una clase llamada "Document" en el esquema de Weaviate.
  • client.schema.create_class(class_schema): Si la clase no existe, esto crea la clase en Weaviate con el esquema definido.

Paso 4: Importar Datos (Almacenar Objetos)

import openai

openai.api_key = os.getenv("OPENAI_API_KEY")


def get_embedding(text):
    response = openai.Embedding.create(
        input=text,
        model="text-embedding-3-small"  # Or your preferred embedding model
    )
    return response["data"][0]["embedding"]



documents = [
    {"content": "How to reset your password"},
    {"content": "Updating your billing information"},
    {"content": "Steps to cancel your subscription"},
]

with client.batch(batch_size=100) as batch:
    for i, doc in enumerate(documents):
        try:
            embedding = get_embedding(doc["content"])
            data_object = {
                "content": doc["content"],
            }
            batch.add_data_object(
                data_object=data_object,
                class_name="Document",
                vector=embedding,
            )
            print(f"Imported document {i + 1}/{len(documents)}")
        except Exception as e:
            print(f"Error importing document {i + 1}: {e}")
  • import openai: Importa la biblioteca OpenAI para usar en la generación de embeddings.
  • openai.api_key = os.getenv("OPENAI_API_KEY"): Establece la clave API de OpenAI usando el valor de la variable de entorno OPENAI_API_KEY.
  • get_embedding(text):
    • Toma una cadena de texto como entrada.
    • Llama a la API de OpenAI para generar un vector de embedding para el texto.
    • Devuelve el vector de embedding.
  • documents: Una lista de diccionarios, donde cada diccionario representa un documento que se almacenará en Weaviate.
  • with client.batch(batch_size=100) as batch: Inicializa un proceso de importación por lotes. Esto es más eficiente para importar múltiples objetos. El parámetro batch_size especifica el número de objetos a incluir en cada lote.
  • El bucle for itera a través de la lista documents:
    • embedding = get_embedding(doc["content"]): Genera el vector de embedding para el contenido del documento usando la función get_embedding.
    • data_object: Crea un diccionario que representa el objeto de datos a almacenar en Weaviate.
    • batch.add_data_object(...): Añade el objeto de datos al lote actual.
      • data_object: El diccionario del objeto de datos.
      • class_name: El nombre de la clase a la que pertenece el objeto ("Document").
      • vector: El vector de embedding para el objeto de datos.
    • El bloque try...except maneja posibles errores durante el proceso de importación.

Paso 5: Consultar Weaviate

query_text = "How do I change my payment method?"
query_vector = get_embedding(query_text)

results = (
    client.query
    .get("Document", ["content"])  # Specify the class and properties to retrieve
    .with_near_vector(
        {"vector": query_vector}
    )
    .with_limit(2)  # Limit the number of results
    .do()
)

print("Search Results:")
for result in results["data"]["Get"]["Document"]:
    print(f"📄 Match: {result['content']}")
  • query_text: El texto de la consulta.
  • query_vector = get_embedding(query_text): Genera el vector de embedding para el texto de la consulta usando la función get_embedding.
  • results = client.query.get("Document", ["content"]).with_near_vector({"vector": query_vector}).with_limit(2).do(): Construye y ejecuta la consulta.
    • client.query.get("Document", ["content"]): Especifica la clase a consultar ("Document") y las propiedades a recuperar ("content").
    • with_near_vector({"vector": query_vector}): Especifica que la consulta debe encontrar objetos cuyos vectores estén más cercanos al query_vector.
    • with_limit(2): Limita el número de resultados a los 2 mejores.
    • do(): Ejecuta la consulta.
  • El código luego imprime los resultados de la búsqueda, extrayendo el contenido de cada documento encontrado.

Más información: https://weaviate.io

Resumen Breve

En este completo capítulo, has adquirido conocimientos valiosos en varias áreas clave:

  • Bases de Datos Vectoriales e IA Escalable
    • Comprender cómo las bases de datos vectoriales sirven como columna vertebral para aplicaciones de IA a gran escala
    • Aprender por qué las bases de datos tradicionales se quedan cortas para la búsqueda y recuperación impulsada por IA
    • Explorar los principios arquitectónicos que hacen que las bases de datos vectoriales sean eficientes a escala
  • Implementación de Pinecone
    • Configurar y ajustar Pinecone para entornos de producción
    • Gestionar embeddings vectoriales en una arquitectura distribuida en la nube
    • Optimizar el rendimiento del índice y la eficiencia de las consultas
  • Construcción de Sistemas de Búsqueda Global
    • Implementar búsqueda semántica que comprende el contexto y significado
    • Diseñar sistemas que mantienen tiempos de respuesta rápidos a escala global
    • Manejar requisitos de búsqueda multilingüe y transcultural
  • Soluciones Alternativas
    • Chroma: Perfecto para implementaciones pequeñas y prototipos rápidos
    • Weaviate: Ideal para búsqueda híbrida y relaciones de datos complejas
    • Entender cuándo elegir cada solución según casos de uso específicos

Armado con este conocimiento, ahora estás equipado para ir más allá de los prototipos básicos y crear aplicaciones de IA sofisticadas de nivel producción que aprovechan todo el poder de los embeddings, la comprensión contextual y la búsqueda inteligente a escala. Ya sea que estés construyendo una aplicación pequeña o un sistema global, tienes las herramientas para elegir e implementar la solución correcta para tus necesidades.