Marcio Cunha

Cómo usar embeddings locales con ChromaDB en búsqueda semántica

Aprende a construir un motor de búsqueda vectorial totalmente local y privado usando Python y ChromaDB para recuperar contexto en LLMs sin depender de nubes externas.

Marcio Cunha•5 min
También disponible en:PortuguêsEnglish
Resumen
  • La búsqueda vectorial local garantiza total privacidad de los datos al procesar embeddings sin enviar información a servidores de terceros
  • Los modelos de embedding convierten textos en vectores numéricos capaces de capturar el significado semántico y las intenciones reales de las palabras
  • ChromaDB actúa como una base de datos vectorial ligera que almacena y recupera similitudes de forma extremadamente rápida en entornos locales
  • Bibliotecas como Sentence Transformers facilitan la generación local de representaciones vectoriales optimizadas para hardware común
  • La recuperación correcta de contexto reduce drásticamente las alucinaciones en grandes modelos de lenguaje al proveer hechos verificables en la misma base

Por qué construir un motor de búsqueda vectorial totalmente local?

Cuando conversamos con asistentes de inteligencia artificial, a menudo necesitamos que conozcan nuestros propios documentos, códigos o notas privadas. Enviar estos datos sensibles a APIs externas en la nube puede violar políticas de privacidad y seguridad. Es exactamente ahí donde entra la búsqueda semántica local, permitiendo procesar todo en tu propia máquina.

En términos simples, los embeddings son representaciones numéricas de palabras o frases que capturan el significado real del texto, y no solo las palabras exactas. Cuando un sistema entiende el sentido, logra encontrar documentos relevantes aunque el usuario use términos diferentes. Para profundizar en este concepto de procesamiento y escala, vale la pena entender cómo gestionar embeddings en bases de datos vectoriales para evitar cuellos de botella en el rendimiento.

La gran ventaja de mantener esta arquitectura en tu propio ordenador o servidor privado es el control absoluto sobre la información. No dependes de conexión a internet, no pagas por peticiones de API y garantizas que los datos confidenciales jamás salgan de tu perímetro de seguridad. En la práctica, esto significa ejecutar modelos compactos directamente en tu hardware usando herramientas de código abierto.

Entendiendo los conceptos fundamentales de vectores y similitud

Para que una computadora entienda textos, necesita transformar letras en números. Este proceso es realizado por modelos de lenguaje especializados llamados encoders, que leen una frase y generan una lista larga de números decimales, conocida como vector. Textos con significados similares generan listas de números cuyos puntos quedan muy cerca en un mapa matemático multidimensional.

Imagina un gráfico gigante donde la palabra 'perro' queda cerca de 'gato', pero muy lejos de 'avión'. El motor de búsqueda calcula la distancia matemática entre la pregunta del usuario y los documentos almacenados, encontrando los fragmentos más parecidos en milisegundos. Este enfoque resuelve el problema clásico de la búsqueda por palabras clave tradicionales, que fallan si olvidas el término exacto.

Para llevar esta teoría a la práctica diaria, muchos desarrolladores combinan bases de datos vectoriales con motores de inferencia locales, como exploramos en nuestra guía sobre cómo ejecutar IA local con Llama.cpp y API REST, creando ecosistemas totalmente independientes de servicios externos.

Preparando el entorno Python e instalando las bibliotecas

El primer paso práctico para poner en marcha el motor es preparar un entorno aislado en Python. Usar entornos virtuales previene conflictos de versiones entre paquetes instalados en el sistema operativo. Instalaremos ChromaDB, que es la base de datos vectorial ligera que guardará nuestros datos, y la biblioteca de transformadores para generar los embeddings.

Abre tu terminal y ejecuta los comandos siguientes para crear la carpeta del proyecto, activar el entorno virtual e instalar las dependencias necesarias:

python3 -m venv venv
source venv/bin/activate
pip install chromadb sentence-transformers

Con estas herramientas listas, tu computadora ya tiene todo lo necesario para transformar textos en números y enlazarlos localmente sin depender de ninguna clave de API comercial.

Creando la base de datos vectorial e insertando documentos

Ahora que el entorno está configurado, escribiremos el código Python responsable de inicializar ChromaDB y añadir algunos documentos de ejemplo. ChromaDB gestiona automáticamente la persistencia de los datos en disco, guardando todo en una carpeta local para que no pierdas nada al cerrar el script.

Crea un archivo llamado indexador.py en tu ordenador y pega el código funcional siguiente, que lee frases cortas, las convierte en vectores y las guarda en la base:

import chromadb
from chromadb.utils import embedding_functions

# Inicializa el cliente de ChromaDB apuntando a una carpeta local
client = chromadb.PersistentClient(path='./mi_base_vectorial')

# Usa un modelo predeterminado eficiente y ligero para embeddings
emb_fn = embedding_functions.SentenceTransformerEmbeddingFunction(
    model_name='all-MiniLM-L6-v2'
)

# Crea o recupera una colección de documentos
collection = client.get_or_create_collection(
    name='documentos_internos',
    embedding_function=emb_fn
)

# Añade documentos de ejemplo a la base local
collection.add(
    documents=[
        'El servidor de base de datos presentó lentitud debido al alto uso de IOPS.',
        'La política de seguridad exige contraseñas con un mínimo de doce caracteres.',
        'La copia de seguridad diaria se ejecuta automáticamente cada madrugada a las tres.'
    ],
    ids=['doc1', 'doc2', 'doc3']
)

print('Documentos indexados con éxito en el ChromaDB local!')

Ejecuta el script en la terminal con python indexador.py. En la práctica, ChromaDB descargará el modelo ligero en la primera ejecución, procesará los textos y grabará los archivos vectoriales en la carpeta mi_base_vectorial creada en el directorio del proyecto.

Realizando búsquedas semánticas y recuperando contexto para LLMs

Con los datos indexados, el siguiente paso es consultar la base haciendo una pregunta en lenguaje natural. El motor transformará tu pregunta en un vector, la comparará con todos los documentos guardados y devolverá los fragmentos más relevantes. Este contexto recuperado puede enviarse directamente a una inteligencia artificial para generar una respuesta precisa basada en hechos reales.

Crea un archivo llamado busqueda.py e ingresa el código siguiente para probar la recuperación semántica:

import chromadb
from chromadb.utils import embedding_functions

client = chromadb.PersistentClient(path='./mi_base_vectorial')

emb_fn = embedding_functions.SentenceTransformerEmbeddingFunction(
    model_name='all-MiniLM-L6-v2'
)

collection = client.get_collection(
    name='documentos_internos',
    embedding_function=emb_fn
)

# Pregunta en lenguaje natural que no usa las palabras exactas del documento
pregunta = 'Cómo está el rendimiento de los discos?'

resultados = collection.query(
    query_texts=[pregunta],
    n_results=1
)

print('Pregunta:', pregunta)
print('Documento más relevante encontrado:', resultados['documents'][0])

Al ejecutar este script, nota que incluso sin usar la palabra 'IOPS' o 'lentitud' en la pregunta, el sistema comprendió el sentido y localizó el documento correcto sobre el servidor. Esta es la esencia de la recuperación de contexto para LLMs. Para profundizar en estos conceptos arquitectónicos en producción, consulte también nuestro análisis técnico sobre Cómo gestionar concurrencia en Rust con Tokio y Channels.

Buenas prácticas de mantenimiento y consideraciones finales

Construir un motor de búsqueda vectorial local transforma la forma en que manejamos datos privados y automatizaciones basadas en inteligencia artificial. Para mantener el sistema rápido a medida que la base crece, es importante monitorear el tamaño de la carpeta de persistencia y actualizar los modelos de embedding a medida que surgen versiones más eficientes en la comunidad open-source.

En resumen, combinar Python, ChromaDB y modelos locales elimina costos recurrentes de API y blinda tu información contra fugas externas. Adoptar esta arquitectura garantiza soberanía total sobre los datos y abre puertas para crear asistentes inteligentes verdaderamente útiles y seguros dentro de tu propia infraestructura.