Rememberizer Docs
Iniciar sesiónInscribirseContáctenos
Español
Español
  • ¿Por qué Rememberizer?
  • Antecedentes
    • ¿Qué son los Embeddings Vectoriales y las Bases de Datos Vectoriales?
    • Glosario
    • Terminología Estandarizada
  • Uso Personal
    • Comenzando
      • Buscar tu conocimiento
      • Acceso al Filtro de Mementos
      • Conocimiento Común
      • Gestiona tu conocimiento incrustado
  • Integraciones
    • Aplicación Rememberizer
    • Integración de Rememberizer con Slack
    • Integración de Rememberizer con Google Drive
    • Integración de Rememberizer con Dropbox
    • Integración de Rememberizer con Gmail
    • Integración de Rememberizer con Memory
    • Servidores MCP de Rememberizer
    • Gestionar aplicaciones de terceros
  • Recursos para Desarrolladores
    • Descripción General del Desarrollador
  • Opciones de Integración
    • Registrar y usar claves API
    • Registrar aplicaciones de Rememberizer
    • Autorizar aplicaciones de Rememberizer
    • Crear un Rememberizer GPT
    • Integración de LangChain
    • Almacenes de Vectores
    • Hablar con Slack la Aplicación Web de Ejemplo
  • Integración Empresarial
    • Patrones de Integración Empresarial
  • Referencia de la API
    • Inicio de la Documentación de la API
    • Autenticación
  • APIs principales
    • Buscar documentos por similitud semántica
    • Recuperar documentos
    • Recuperar contenidos de documentos
    • Recuperar contenido de Slack
    • Memorizar contenido en Rememberizer
  • Cuenta y Configuración
    • Recuperar detalles de la cuenta de usuario actual
    • Listar integraciones de fuentes de datos disponibles
    • Mementos
    • Obtener todo el conocimiento público agregado
  • APIs de Almacenamiento de Vectores
    • Documentación del Almacenamiento de Vectores
    • Obtener información del almacenamiento de vectores
    • Obtener una lista de documentos en un Almacenamiento de Vectores
    • Obtener información del documento
    • Agregar un nuevo documento de texto a un Almacenamiento de Vectores
    • Subir archivos a un Almacenamiento de Vectores
    • Actualizar el contenido del archivo en un Almacenamiento de Vectores
    • Eliminar un documento en el Almacenamiento de Vectores
    • Buscar documentos del Almacenamiento de Vectores por similitud semántica
  • Recursos Adicionales
    • Avisos
      • Términos de Uso
      • Política de Privacidad
      • B2B
        • Acerca de Reddit Agent
  • Lanzamientos
    • Notas de la versión Inicio
  • Lanzamientos 2025
    • 25 de abr, 2025
    • 18 de abr, 2025
    • 11 de abr, 2025
    • 4 de abr, 2025
    • 28 de mar, 2025
    • 21 de mar, 2025
    • 14 de mar, 2025
    • 17 de ene, 2025
  • Lanzamientos 2024
    • 27 de diciembre de 2024
    • 20 de diciembre de 2024
    • 13 de diciembre de 2024
    • 6 de diciembre de 2024
  • 29 de Noviembre de 2024
  • 22 de Noviembre de 2024
  • 15 de Noviembre de 2024
  • 8 de Noviembre de 2024
  • 1 de Noviembre de 2024
  • 25 de oct, 2024
  • 18 de oct, 2024
  • 11 de oct, 2024
  • 4 de oct, 2024
  • 27 de sep, 2024
  • 20 de sep, 2024
  • 13 de sep, 2024
  • 16 de agosto de 2024
  • 9 de agosto de 2024
  • 2 de agosto de 2024
  • 26 de julio de 2024
  • 12 de julio de 2024
  • 28 de jun, 2024
  • 14 de jun, 2024
  • 31 de mayo de 2024
  • 17 de mayo de 2024
  • 10 de mayo de 2024
  • 26 de abr, 2024
  • 19 de abr, 2024
  • 12 de abr, 2024
  • 5 de abr, 2024
  • 25 de mar, 2024
  • 18 de mar, 2024
  • 11 de mar, 2024
  • 4 de mar, 2024
  • 26 de Febrero de 2024
  • 19 de Febrero de 2024
  • 12 de Febrero de 2024
  • 5 de Febrero de 2024
  • 29 de enero de 2024
  • 22 de enero de 2024
  • 15 de enero de 2024
  • Documentación LLM
    • Documentación Lista para LLM de Rememberizer
Powered by GitBook
On this page
  • Introducción
  • Visión Técnica
  • Cómo Funcionan los Almacenes de Vectores
  • Componentes Clave
  • Arquitectura
  • Empezando
  • Creando un Almacén de Vectores
  • Opciones de Configuración
  • Gestión de Almacenes de Vectores
  • Gestión de Claves API
  • Creando Claves API
  • Revocación de Claves API
  • Uso de la API de Vector Store
  • Ejemplos de Código
  • Consideraciones de Rendimiento
  • Optimización para Diferentes Volúmenes de Datos
  • Estrategias de Fragmentación
  • Optimización de Consultas
  • Uso Avanzado
  • Reindexación
  • Mejora de Consultas
  • Migrando desde Otras Bases de Datos Vectoriales
  • Visión general de la migración
  • Beneficios de Migrar a Rememberizer
  • Migrando de Pinecone
  • Migrando desde Qdrant
  • Migrando de Supabase pgvector
  • Mejores Prácticas de Migración
  1. Opciones de Integración

Almacenes de Vectores

Esta guía te ayudará a entender cómo usar el Almacén de Vectores Rememberizer como desarrollador.

PreviousIntegración de LangChainNextHablar con Slack la Aplicación Web de Ejemplo

Last updated 22 days ago

El Almacén de Vectores de Rememberizer simplifica el proceso de manejo de datos vectoriales, permitiéndote concentrarte en la entrada de texto y aprovechando el poder de los vectores para diversas aplicaciones como la búsqueda y el análisis de datos.

Introducción

El Almacén de Vectores Rememberizer proporciona una interfaz fácil de usar para manejar datos vectoriales mientras abstrae la complejidad de las incrustaciones vectoriales. Impulsado por PostgreSQL con la extensión pgvector, el Almacén de Vectores Rememberizer te permite trabajar directamente con texto. El servicio se encarga de dividir, vectorizar y almacenar los datos de texto, facilitándote el enfoque en la lógica central de tu aplicación.

Para una comprensión más profunda de los conceptos teóricos detrás de las incrustaciones vectoriales y las bases de datos vectoriales, consulta .

Visión Técnica

Cómo Funcionan los Almacenes de Vectores

Los Almacenes de Vectores de Rememberizer convierten texto en representaciones vectoriales de alta dimensión (embeddings) que capturan el significado semántico. Esto permite:

  1. Búsqueda Semántica: Encontrar documentos basados en el significado en lugar de solo palabras clave

  2. Coincidencia de Similitud: Identificar contenido conceptualmente relacionado

  3. Recuperación Eficiente: Localizar rápidamente información relevante de grandes conjuntos de datos

Componentes Clave

  • Procesamiento de Documentos: El texto se divide en fragmentos de tamaño óptimo con límites superpuestos para la preservación del contexto

  • Vectorización: Los fragmentos se convierten en incrustaciones utilizando modelos de última generación

  • Indexación: Algoritmos especializados organizan vectores para una búsqueda de similitud eficiente

  • Procesamiento de Consultas: Las consultas de búsqueda se vectorizan y se comparan con las incrustaciones almacenadas

Arquitectura

Rememberizer implementa almacenes de vectores utilizando:

  • PostgreSQL con la extensión pgvector: Para almacenamiento y búsqueda de vectores eficientes

  • Organización basada en colecciones: Cada almacén de vectores tiene su propia colección aislada

  • Acceso impulsado por API: Puntos finales RESTful simples para todas las operaciones

Empezando

Creando un Almacén de Vectores

  1. Navega a la Sección de Almacenes de Vectores en tu panel de control

  2. Haz clic en "Crear nuevo Almacén de Vectores":

    • Aparecerá un formulario que te pedirá que ingreses detalles.

  3. Completa los Detalles:

    • Nombre: Proporciona un nombre único para tu almacén de vectores.

    • Descripción: Escribe una breve descripción del almacén de vectores.

    • Modelo de Embedding: Selecciona el modelo que convierte texto en vectores.

    • Algoritmo de Indexación: Elige cómo se organizarán los vectores para la búsqueda.

    • Métrica de Búsqueda: Define cómo se calcula la similitud entre vectores.

    • Dimensión del Vector: El tamaño de las incrustaciones de vectores (típicamente 768-1536).

  4. Envía el Formulario:

    • Haz clic en el botón "Crear". Recibirás una notificación de éxito, y el nuevo almacén aparecerá en tu lista de almacenes de vectores.

Opciones de Configuración

Modelos de Embedding

Modelo
Dimensiones
Descripción
Mejor Para

openai/text-embedding-3-large

1536

Modelo de embedding de alta precisión de OpenAI

Aplicaciones de producción que requieren la máxima precisión

openai/text-embedding-3-small

1536

Modelo de embedding más pequeño y rápido de OpenAI

Aplicaciones con mayores requisitos de rendimiento

Algoritmos de Indexación

Algoritmo
Descripción
Compensaciones

IVFFLAT (predeterminado)

Archivo invertido con compresión plana

Buen equilibrio entre velocidad y precisión; funciona bien para la mayoría de los conjuntos de datos

HNSW

Mundo Pequeño Navegable Jerárquico

Mejor precisión para conjuntos de datos grandes; mayores requisitos de memoria

Métricas de Búsqueda

Métrica
Descripción
Mejor Para

coseno (predeterminado)

Mide el ángulo entre vectores

Coincidencia de similitud de propósito general

producto interno (ip)

Producto punto entre vectores

Cuando la magnitud del vector es importante

L2 (Euclidiana)

Distancia en línea recta entre vectores

Cuando las relaciones espaciales son importantes

Gestión de Almacenes de Vectores

  1. Ver y Editar Almacenes de Vectores:

    • Accede al panel de gestión para ver, editar o eliminar almacenes de vectores.

  2. Visualización de Documentos:

    • Navega por documentos individuales y su metadatos asociados dentro de un almacén de vectores específico.

  3. Estadísticas:

    • Visualiza estadísticas detalladas como el número de vectores almacenados, el rendimiento de las consultas y métricas operativas.

Gestión de Claves API

Las claves API se utilizan para autenticar y autorizar el acceso a los puntos finales de la API del Almacén de Vectores de Rememberizer. La gestión adecuada de las claves API es esencial para mantener la seguridad y la integridad de sus almacenes de vectores.

Creando Claves API

  1. Dirígete a la página de detalles de tu Almacén de Vectores

  2. Navega a la Sección de Gestión de Claves API:

    • Se puede encontrar dentro de la pestaña "Configuración"

  3. Haz clic en "Agregar Clave API":

    • Aparecerá un formulario que te pedirá que ingreses los detalles.

  4. Completa los Detalles:

    • Nombre: Proporciona un nombre para la clave API que te ayude a identificar su caso de uso.

  5. Envía el Formulario:

    • Haz clic en el botón "Crear". La nueva clave API será generada y mostrada. Asegúrate de copiarla y almacenarla de forma segura. Esta clave se utiliza para autenticar solicitudes a ese almacén de vectores específico.

Revocación de Claves API

Si una clave API ya no es necesaria, puedes eliminarla para prevenir cualquier posible uso indebido.

Por razones de seguridad, es posible que desees rotar tus claves API periódicamente. Esto implica generar una nueva clave y revocar la antigua.

Uso de la API de Vector Store

Después de crear un Vector Store y generar una clave API, puedes interactuar con él utilizando la API REST.

Ejemplos de Código

import requests
import json

API_KEY = "your_api_key_here"
VECTOR_STORE_ID = "vs_abc123"  # Reemplaza con tu ID de almacén de vectores
BASE_URL = "https://api.rememberizer.a

# Cargar un documento en el almacén de vectores
def upload_document(file_path, document_name=None):
    if document_name is None:
        document_name = file_path.split("/")[-1]
    
    with open(file_path, "rb") as f:
        files = {"file": (document_name, f)}
        headers = {"x-api-key": API_KEY}
        
        response = requests.post(
            f"{BASE_URL}/vector-stores/{VECTOR_STORE_ID}/documents",
            headers=headers,
            files=files
        )
        
        if response.status_code == 201:
            print(f"¡Documento '{document_name}' cargado con éxito!")
            return response.json()
        else:
            print(f"Error al cargar el documento: {response.text}")
            return None

# Cargar contenido de texto en el almacén de vectores
def upload_text(content, document_name):
    headers = {
        "x-api-key": API_KEY,
        "Content-Type": "application/json"
    }
    
    data = {
        "name": document_name,
        "content": content
    }
    
    response = requests.post(
        f"{BASE_URL}/vector-stores/{VECTOR_STORE_ID}/documents/text",
        headers=headers,
        json=data
    )
    
    if response.status_code == 201:
        print(f"¡Documento de texto '{document_name}' cargado con éxito!")
        return response.json()
    else:
        print(f"Error al cargar el texto: {response.text}")
        return None

# Buscar en el almacén de vectores
def search_vector_store(query, num_results=5, prev_chunks=1, next_chunks=1):
    headers = {"x-api-key": API_KEY}
    
    params = {
        "q": query,
        "n": num_results,
        "prev_chunks": prev_chunks,
        "next_chunks": next_chunks
    }
    
    response = requests.get(
        f"{BASE_URL}/vector-stores/{VECTOR_STORE_ID}/documents/search",
        headers=headers,
        params=params
    )
    
    if response.status_code == 200:
        results = response.json()
        print(f"Encontrados {len(results['matched_chunks'])} coincidencias para '{query}'")
        
        # Imprimir el resultado principal
        if results['matched_chunks']:
            top_match = results['matched_chunks'][0]
            print(f"Coincidencia principal (distancia: {top_match['distance']}):")
            print(f"Documento: {top_match['document']['name']}")
            print(f"Contenido: {top_match['matched_content']}")
        
        return results
    else:
        print(f"Error al buscar: {response.text}")
        return None

# Ejemplo de uso
# subir_documento("ruta/al/documento.pdf")
# upload_text("Este es un texto de muestra para ser vectorizado", "sample-document.txt")
# search_vector_store("¿Cómo funciona la similitud de vectores?")
// Cliente de API de Almacén de Vectores
class VectorStoreClient {
  constructor(apiKey, vectorStoreId) {
    this.apiKey = apiKey;
    this.vectorStoreId = vectorStoreId;
    this.baseUrl = 'https://api.rememberizer.ai/api/v1';
  }

  // Obtener información del almacén de vectores
  async getVectorStoreInfo() {
    const response = await fetch(`${this.baseUrl}/vector-stores/${this.vectorStoreId}`, {
      method: 'GET',
      headers: {
        'x-api-key': this.apiKey
      }
    });
    
    if (!response.ok) {
      throw new Error(`Error al obtener información del almacén de vectores: ${response.statusText}`);
    }
    
    return response.json();
  }

  // Subir un documento de texto
  async uploadTextDocument(name, content) {
    const response = await fetch(`${this.baseUrl}/vector-stores/${this.vectorStoreId}/documents/text`, {
      method: 'POST',
      headers: {
        'x-api-key': this.apiKey,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name,
        content
      })
    });
    
    if (!response.ok) {
      throw new Error(`Error al subir el documento de texto: ${response.statusText}`);
    }
    
    return response.json();
  }

  // Subir un archivo
  async uploadFile(file, onProgress) {
    const formData = new FormData();
    formData.append('file', file);
    
    const xhr = new XMLHttpRequest();
    
    return new Promise((resolve, reject) => {
      xhr.open('POST', `${this.baseUrl}/vector-stores/${this.vectorStoreId}/documents`);
      xhr.setRequestHeader('x-api-key', this.apiKey);
      
      xhr.upload.onprogress = (event) => {
        if (event.lengthComputable && onProgress) {
          const percentComplete = (event.loaded / event.total) * 100;
          onProgress(percentComplete);
        }
      };
      
      xhr.onload = () => {
        if (xhr.status === 201) {
          resolve(JSON.parse(xhr.responseText));
        } else {
          reject(new Error(`Error al subir el archivo: ${xhr.statusText}`));
        }
      };
      
      xhr.onerror = () => {
        reject(new Error('Error de red durante la subida del archivo'));
      };
      
      xhr.send(formData);
    });
  }

  // Buscar documentos en el almacén de vectores
  async searchDocuments(query, options = {}) {
    const params = new URLSearchParams({
      q: query,
      n: options.numResults || 10,
      prev_chunks: options.prevChunks || 1,
      next_chunks: options.nextChunks || 1
    });
    
    if (options.threshold) {
      params.append('t', options.threshold);
    }
    
    const response = await fetch(
      `${this.baseUrl}/vector-stores/${this.vectorStoreId}/documents/search?${params}`,
      {
        method: 'GET',
        headers: {
          'x-api-key': this.apiKey
        }
      }
    );
    
    if (!response.ok) {
      throw new Error(`Error de búsqueda: ${response.statusText}`);
    }
    
    return response.json();
  }

  // Listar todos los documentos en el almacén de vectores
  async listDocuments() {
    const response = await fetch(
      `${this.baseUrl}/vector-stores/${this.vectorStoreId}/documents`,
      {
        method: 'GET',
        headers: {
          'x-api-key': this.apiKey
        }
      }
    );
    
    if (!response.ok) {
      throw new Error(`Error al listar documentos: ${response.statusText}`);
    }
    
    return response.json();
  }

  // Eliminar un documento
  async deleteDocument(documentId) {
    const response = await fetch(
      `${this.baseUrl}/vector-stores/${this.vectorStoreId}/documents/${documentId}`,
      {
        method: 'DELETE',
        headers: {
          'x-api-key': this.apiKey
        }
      }
    );
    
    if (!response.ok) {
      throw new Error(`Error al eliminar el documento: ${response.statusText}`);
    }
    
    return true;
  }
}

// Ejemplo de uso
/*
const client = new VectorStoreClient('your_api_key', 'vs_abc123');

// Buscar documentos
client.searchDocuments('¿Cómo funciona la búsqueda semántica?')
  .then(results => {
    console.log(`Se encontraron ${results.matched_chunks.length} coincidencias`);
    results.matched_chunks.forEach(match => {
      console.log(`Documento: ${match.document.name}`);
      console.log(`Puntuación: ${match.distance}`);
      console.log(`Contenido: ${match.matched_content}`);
      console.log('---');
    });
  })
  .catch(error => console.error(error));
*/
require 'net/http'
require 'uri'
require 'json'

class VectorStoreClient
  def initialize(api_key, vector_store_id)
    @api_key = api_key
    @vector_store_id = vector_store_id
    @base_url = 'https://api.rememberizer.ai/api/v1'
  end

  # Obtener detalles del almacén de vectores
  def get_vector_store_info
    uri = URI("#{@base_url}/vector-stores/#{@vector_store_id}")
    request = Net::HTTP::Get.new(uri)
    request['x-api-key'] = @api_key
    
    response = send_request(uri, request)
    JSON.parse(response.body)
  end

  # Subir contenido de texto
  def upload_text(name, content)
    uri = URI("#{@base_url}/vector-stores/#{@vector_store_id}/documents/text")
    request = Net::HTTP::Post.new(uri)
    request['Content-Type'] = 'application/json'
    request['x-api-key'] = @api_key
    
    request.body = {
      name: name,
      content: content
    }.to_json
    
    response = send_request(uri, request)
    JSON.parse(response.body)
  end

  # Buscar documentos
  def search(query, num_results: 5, prev_chunks: 1, next_chunks: 1, threshold: nil)
    uri = URI("#{@base_url}/vector-stores/#{@vector_store_id}/documents/search")
    params = {
      q: query,
      n: num_results,
      prev_chunks: prev_chunks,
      next_chunks: next_chunks
    }
    
    params[:t] = threshold if threshold
    
    uri.query = URI.encode_www_form(params)
    request = Net::HTTP::Get.new(uri)
    request['x-api-key'] = @api_key
    
    response = send_request(uri, request)
    JSON.parse(response.body)
  end

  # Listar documentos
  def list_documents
    uri = URI("#{@base_url}/vector-stores/#{@vector_store_id}/documents")
    request = Net::HTTP::Get.new(uri)
    request['x-api-key'] = @api_key
    
    response = send_request(uri, request)
    JSON.parse(response.body)
  end

  # Subir archivo (formulario multipart)
  def upload_file(file_path)
    uri = URI("#{@base_url}/vector-stores/#{@vector_store_id}/documents")
    
    file_name = File.basename(file_path)
    file_content = File.binread(file_path)
    
    boundary = "RememberizerBoundary#{rand(1000000)}"
    
    request = Net::HTTP::Post.new(uri)
    request['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
    request['x-api-key'] = @api_key
    
    post_body = []
    post_body << "--#{boundary}\r\n"
    post_body << "Content-Disposition: form-data; name=\"file\"; filename=\"#{file_name}\"\r\n"
    post_body << "Content-Type: application/octet-stream\r\n\r\n"
    post_body << file_content
    post_body << "\r\n--#{boundary}--\r\n"
    
    request.body = post_body.join
    
    response = send_request(uri, request)
    JSON.parse(response.body)
  end

  private

  def send_request(uri, request)
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = (uri.scheme == 'https')
    
    response = http.request(request)
    
    unless response.is_a?(Net::HTTPSuccess)
      raise "Error en la solicitud a la API: #{response.code} #{response.message}\n#{response.body}"
    end
    
    response
  end
end

Ejemplo de uso

=begin client = VectorStoreClient.new('your_api_key', 'vs_abc123')

Buscar documentos

results = client.search('¿Cuáles son las mejores prácticas para la seguridad de datos?') puts "Encontrados #{results['matched_chunks'].length} resultados"

Mostrar el mejor resultado

if results['matched_chunks'].any? top_match = results['matched_chunks'].first puts "Mejor coincidencia (distancia: #{top_match['distance']}):" puts "Documento: #{top_match['document']['name']}" puts "Contenido: #{top_match['matched_content']}" end =end


</div>

<div data-gb-custom-block data-tag="tab" data-title='cURL'>

```bash
# Establece tu clave API y el ID de la tienda de vectores
API_KEY="your_api_key_here"
VECTOR_STORE_ID="vs_abc123"
BASE_URL="https://api.rememberizer.ai/api/v1"

# Obtener información del almacén de vectores
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}" \
  -H "x-api-key: ${API_KEY}"

# Subir un documento de texto
curl -X POST "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents/text" \
  -H "x-api-key: ${API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "example-document.txt",
    "content": "Este es un documento de muestra que será vectorizado y almacenado en la base de datos vectorial para búsqueda semántica."
  }'

# Subir un archivo
curl -X POST "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents" \
  -H "x-api-key: ${API_KEY}" \
  -F "file=@/ruta/a/tu/documento.pdf"

# Buscar documentos
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents/search?q=semantic%20search&n=5&prev_chunks=1&next_chunks=1" \
  -H "x-api-key: ${API_KEY}"

# Listar todos los documentos
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents" \
  -H "x-api-key: ${API_KEY}"

# Eliminar un documento
curl -X DELETE "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents/123" \
  -H "x-api-key: ${API_KEY}"

Consideraciones de Rendimiento

Próximamente: Diagrama de Arquitectura de Almacenamiento de Vectores

Este diagrama de arquitectura técnica ilustrará:

  • La arquitectura de base de PostgreSQL + pgvector

  • Estructuras de algoritmos de indexación (IVFFLAT vs. HNSW)

  • Cómo funcionan las métricas de búsqueda en el espacio vectorial (comparación visual)

  • Proceso de fragmentación de documentos con visualización de superposición

  • Consideraciones de rendimiento visualizadas a través de diferentes escalas

Optimización para Diferentes Volúmenes de Datos

Volumen de Datos
Configuración Recomendada
Notas

Pequeño (<10k documentos)

IVFFLAT, similitud coseno

La configuración simple proporciona un buen rendimiento

Medio (10k-100k documentos)

IVFFLAT, asegurar reindexación regular

Equilibrio entre velocidad de búsqueda y mantenimiento del índice

Grande (>100k documentos)

HNSW, considerar aumentar las dimensiones del vector

Mayor uso de memoria pero mantiene el rendimiento a gran escala

Estrategias de Fragmentación

El proceso de fragmentación impacta significativamente la calidad de búsqueda:

  • Tamaño del Fragmento: Rememberizer utiliza un tamaño de fragmento predeterminado de 1024 bytes con una superposición de 200 bytes

  • Fragmentos Más Pequeños (512-1024 bytes): Coincidencias más precisas, mejor para preguntas específicas

  • Fragmentos Más Grandes (1500-2048 bytes): Más contexto en cada coincidencia, mejor para temas más amplios

  • Superposición: Asegura que el contexto no se pierda en los límites de los fragmentos

Optimización de Consultas

  • Ventanas de Contexto: Utiliza prev_chunks y next_chunks para recuperar contenido circundante

  • Cantidad de Resultados: Comienza con 3-5 resultados (n parameter) y ajusta según las necesidades de precisión

  • Umbral: Ajusta el parámetro t para filtrar resultados por puntuación de similitud

Uso Avanzado

Reindexación

Rememberizer activa automáticamente la reindexación cuando los recuentos de vectores superan los umbrales predefinidos, pero considere la reindexación manual después de:

  • Subir una gran cantidad de documentos

  • Cambiar el modelo de incrustación

  • Modificar el algoritmo de indexación

Mejora de Consultas

Para obtener mejores resultados de búsqueda:

  1. Sé específico en las consultas de búsqueda

  2. Incluye contexto cuando sea posible

  3. Usa lenguaje natural en lugar de palabras clave

  4. Ajusta los parámetros según la calidad del resultado

Migrando desde Otras Bases de Datos Vectoriales

Si actualmente estás utilizando otras soluciones de bases de datos vectoriales y deseas migrar a Rememberizer Vector Store, las siguientes guías te ayudarán a transferir tus datos de manera eficiente.

Visión general de la migración

Migrar datos vectoriales implica:

  1. Exportar datos de su base de datos vectorial de origen

  2. Convertir los datos a un formato compatible con Rememberizer

  3. Importar los datos en su Almacén Vectorial de Rememberizer

  4. Verificar que la migración fue exitosa

Beneficios de Migrar a Rememberizer

  • Fundación PostgreSQL: Construido sobre tecnología de base de datos madura con copias de seguridad y recuperación integradas

  • Ecosistema Integrado: Conexión fluida con otros componentes de Rememberizer

  • Gestión Simplificada: Interfaz unificada para operaciones vectoriales

  • Seguridad Avanzada: Seguridad a nivel de fila y controles de acceso granulares

  • Arquitectura Escalable: Optimización del rendimiento a medida que crece su datos

Migrando de Pinecone

import os
import pinecone
import requests
import json
import time

# Configurar el cliente de Pinecone
pinecone.init(api_key="PINECONE_API_KEY", environment="PINECONE_ENV")
source_index = pinecone.Index("your-pinecone-index")

# Configurar el cliente de Rememberizer Vector Store
REMEMBERIZER_API_KEY = "your_rememberizer_api_key"
VECTOR_STORE_ID = "vs_abc123"  # Tu ID de tienda de vectores de Rememberizer
BASE_URL = "https://api.rememberizer.ai/api/v1"

# 1. Configurar el tamaño del lote para la migración (ajustar según el tamaño de sus datos)
BATCH_SIZE = 100

# 2. Función para obtener vectores de Pinecone
def fetch_vectors_from_pinecone(index_name, batch_size, cursor=None):
    # Utiliza la operación de lista si está disponible en tu versión de Pinecone
    try:
        result = source_index.list(limit=batch_size, cursor=cursor)
        vectors = result.get("vectors", {})
        next_cursor = result.get("cursor")
        return vectors, next_cursor
    except AttributeError:
        # Para versiones más antiguas de Pinecone sin operación de lista
        # Este es un enfoque simplificado; la implementación real depende de tu patrón de acceso a datos
        query_response = source_index.query(
            vector=[0] * source_index.describe_index_stats()["dimension"],
            top_k=batch_size,
            include_metadata=True,
            include_values=True
        )
        return {item.id: {"id": item.id, "values": item.values, "metadata": item.metadata} 
                for item in query_response.matches}, None

# 3. Función para subir vectores a Rememberizer
def upload_to_rememberizer(vectors):
    headers = {
        "x-api-key": REMEMBERIZER_API_KEY,
        "Content-Type": "application/json"
    }
    
    for vector_id, vector_data in vectors.items():
        # Convertir datos de vectores de Pinecone al formato de Rememberizer
        document_name = vector_data.get("metadata", {}).get("filename", f"pinecone_doc_{vector_id}")
        content = vector_data.get("metadata", {}).get("text", "")
        
        if not content:
            print(f"Omitiendo {vector_id} - no se encontró contenido de texto en los metadatos")
            continue
            
        data = {
            "name": document_name,
            "content": content,
            # Opcional: incluir metadatos adicionales
            "metadata": vector_data.get("metadata", {})
        }
        
        response = requests.post(
            f"{BASE_URL}/vector-stores/{VECTOR_STORE_ID}/documents/text",
            headers=headers,
            json=data
        )
        
        if response.status_code == 201:
            print(f"¡Documento '{document_name}' subido con éxito!")
        else:
            print(f"Error al subir el documento {document_name}: {response.text}")
        
        # Agregar un pequeño retraso para prevenir limitaciones de tasa
        time.sleep(0.1)

# 4. Función principal de migración
def migrate_pinecone_to_rememberizer():
    cursor = None
    total_migrated = 0
    
    print("Iniciando la migración de Pinecone a Rememberizer...")
    
    while True:
        vectors, cursor = fetch_vectors_from_pinecone("your-pinecone-index", BATCH_SIZE, cursor)
        
        if not vectors:
            break
            
        print(f"Se obtuvieron {len(vectors)} vectores de Pinecone")
        upload_to_rememberizer(vectors)
        
        total_migrated += len(vectors)
        print(f"Progreso: {total_migrated} vectores migrados")
        
        if not cursor:
            break
    
    print(f"¡Migración completa! {total_migrated} vectores migrados en total a Rememberizer")

# Ejecutar la migración
# migrate_pinecone_to_rememberizer()
const { PineconeClient } = require('@pinecone-database/pinecone');
const axios = require('axios');

// Configuración de Pinecone
const pineconeApiKey = 'PINECONE_API_KEY';
const pineconeEnvironment = 'PINECONE_ENVIRONMENT';
const pineconeIndexName = 'YOUR_PINECONE_INDEX';

// Configuración de Rememberizer
const rememberizerApiKey = 'YOUR_REMEMBERIZER_API_KEY';
const vectorStoreId = 'vs_abc123';
const baseUrl = 'https://api.rememberizer.ai/api/v1';

// Configuración del tamaño del lote
const BATCH_SIZE = 100;

// Inicializar el cliente de Pinecone
async function initPinecone() {
  const pinecone = new PineconeClient();
  await pinecone.init({
    apiKey: pineconeApiKey,
    environment: pineconeEnvironment,
  });
  return pinecone;
}

// Obtener vectores de Pinecone
async function fetchVectorsFromPinecone(pinecone, batchSize, paginationToken = null) {
  const index = pinecone.Index(pineconeIndexName);
  
  try {
    // Para versiones más nuevas de Pinecone
    const listResponse = await index.list({
      limit: batchSize,
      paginationToken: paginationToken
    });
    
    return {
      vectors: listResponse.vectors || {},
      nextToken: listResponse.paginationToken
    };
  } catch (error) {
    // Respaldo para versiones más antiguas de Pinecone
    // Esto está simplificado; la implementación real depende de tu patrón de acceso a datos
    const stats = await index.describeIndexStats();
    const dimension = stats.dimension;
    
    const queryResponse = await index.query({
      vector: Array(dimension).fill(0),
      topK: batchSize,
      includeMetadata: true,
      includeValues: true
    });
    
    const vectors = {};
    queryResponse.matches.forEach(match => {
      vectors[match.id] = {
        id: match.id,
        values: match.values,
        metadata: match.metadata
      };
    });
    
    return { vectors, nextToken: null };
  }
}

// Subir vectores a Rememberizer
async function uploadToRememberizer(vectors) {
  const headers = {
    'x-api-key': rememberizerApiKey,
    'Content-Type': 'application/json'
  };
  
  const results = [];
  
  for (const [vectorId, vectorData] of Object.entries(vectors)) {
    const documentName = vectorData.metadata?.filename || `pinecone_doc_${vectorId}`;
    const content = vectorData.metadata?.text || '';
    
    if (!content) {
      console.log(`Saltando ${vectorId} - no se encontró contenido de texto en los metadatos`);
      continue;
    }
    
    const data = {
      name: documentName,
      content: content,
      // Opcional: incluir metadatos adicionales
      metadata: vectorData.metadata || {}
    };
    
    try {
      const response = await axios.post(
        `${baseUrl}/vector-stores/${vectorStoreId}/documents/text`,
        data,
        { headers }
      );
      
      if (response.status === 201) {
        console.log(`¡Documento '${documentName}' subido con éxito!`);
        results.push({ id: vectorId, success: true });
      } else {
        console.error(`Error al subir el documento ${documentName}: ${response.statusText}`);
        results.push({ id: vectorId, success: false, error: response.statusText });
      }
    } catch (error) {
      console.error(`Error al subir el documento ${documentName}: ${error.message}`);
      results.push({ id: vectorId, success: false, error: error.message });
    }
    
    // Agregar un pequeño retraso para prevenir limitaciones de tasa
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  return results;
}

// Función principal de migración
async function migratePineconeToRememberizer() {
  try {
    console.log('Iniciando la migración de Pinecone a Rememberizer...');
    
    const pinecone = await initPinecone();
    let nextToken = null;
    let totalMigrated = 0;
    
    do {
      const { vectors, nextToken: token } = await fetchVectorsFromPinecone(
        pinecone, 
        BATCH_SIZE, 
        nextToken
      );
      
      nextToken = token;
      
      if (Object.keys(vectors).length === 0) {
        break;
      }
      
      console.log(`Se obtuvieron ${Object.keys(vectors).length} vectores de Pinecone`);
      
      const results = await uploadToRememberizer(vectors);
      const successCount = results.filter(r => r.success).length;
      
      totalMigrated += successCount;
      console.log(`Progreso: ${totalMigrated} vectores migrados con éxito`);
      
    } while (nextToken);
    
    console.log(`¡Migración completa! ${totalMigrated} vectores migrados en total a Rememberizer`);
    
  } catch (error) {
    console.error('La migración falló:', error);
  }
}

// Ejecutar la migración
// migratePineconeToRememberizer();

Migrando desde Qdrant

import requests
import json
import time
from qdrant_client import QdrantClient
from qdrant_client.http import models as rest

# Configurar cliente Qdrant
QDRANT_URL = "http://localhost:6333"  # o tu URL de Qdrant en la nube
QDRANT_API_KEY = "your_qdrant_api_key"  # si usas Qdrant Cloud
QDRANT_COLLECTION_NAME = "your_collection"

qdrant_client = QdrantClient(
    url=QDRANT_URL,
    api_key=QDRANT_API_KEY  # Solo para Qdrant Cloud
)

# Configurar el cliente de Rememberizer Vector Store
REMEMBERIZER_API_KEY = "your_rememberizer_api_key"
VECTOR_STORE_ID = "vs_abc123"  # Tu ID de tienda de vectores de Rememberizer
BASE_URL = "https://api.rememberizer.ai/api/v1"

# Tamaño del lote para el procesamiento
BATCH_SIZE = 100

# Función para obtener puntos de Qdrant
def fetch_points_from_qdrant(collection_name, batch_size, offset=0):
    try:
        # Obtener información de la colección para determinar la dimensión del vector
        collection_info = qdrant_client.get_collection(collection_name=collection_name)
        
        # Desplazarse a través de los puntos
        scroll_result = qdrant_client.scroll(
            collection_name=collection_name,
            limit=batch_size,
            offset=offset,
            with_payload=True,
            with_vectors=True
        )
        
        points = scroll_result[0]  # Tupla de (puntos, siguiente_offset)
        next_offset = scroll_result[1]
        
        return points, next_offset
    except Exception as e:
        print(f"Error al obtener puntos de Qdrant: {e}")
        return [], None

# Función para subir vectores a Rememberizer
def upload_to_rememberizer(points):
    headers = {
        "x-api-key": REMEMBERIZER_API_KEY,
        "Content-Type": "application/json"
    }
    
    results = []
    
    for point in points:
        # Extraer datos del punto de Qdrant
        point_id = point.id
        metadata = point.payload
        text_content = metadata.get("text", "")
        document_name = metadata.get("filename", f"qdrant_doc_{point_id}")
        
        if not text_content:
            print(f"Omitiendo {point_id} - no se encontró contenido de texto en la carga")
            continue
            
        data = {
            "name": document_name,
            "content": text_content,
            # Opcional: incluir metadatos adicionales
            "metadata": metadata
        }
        
        try:
            response = requests.post(
                f"{BASE_URL}/vector-stores/{VECTOR_STORE_ID}/documents/text",
                headers=headers,
                json=data
            )
            
            if response.status_code == 201:
                print(f"¡Documento '{document_name}' subido con éxito!")
                results.append({"id": point_id, "success": True})
            else:
                print(f"Error al subir el documento {document_name}: {response.text}")
                results.append({"id": point_id, "success": False, "error": response.text})
        except Exception as e:
            print(f"Excepción al subir el documento {document_name}: {str(e)}")
            results.append({"id": point_id, "success": False, "error": str(e)})
        
        # Agregar un pequeño retraso para prevenir limitaciones de tasa
        time.sleep(0.1)
    
    return results

# Función principal de migración
def migrate_qdrant_to_rememberizer():
    offset = None
    total_migrated = 0
    
    print("Iniciando la migración de Qdrant a Rememberizer...")
    
    while True:
        points, next_offset = fetch_points_from_qdrant(
            QDRANT_COLLECTION_NAME, 
            BATCH_SIZE,
            offset
        )
        
        if not points:
            break
            
        print(f"Se obtuvieron {len(points)} puntos de Qdrant")
        
        results = upload_to_rememberizer(points)
        success_count = sum(1 for r in results if r.get("success", False))
        
        total_migrated += success_count
        print(f"Progreso: {total_migrated} puntos migrados con éxito")
        
        if next_offset is None:
            break
            
        offset = next_offset
    
    print(f"¡Migración completa! {total_migrated} puntos migrados en total a Rememberizer")

# Ejecutar la migración
# migrate_qdrant_to_rememberizer()
const { QdrantClient } = require('@qdrant/js-client-rest');
const axios = require('axios');

// Configuración de Qdrant
const qdrantUrl = 'http://localhost:6333'; // o tu URL de Qdrant en la nube
const qdrantApiKey = 'your_qdrant_api_key'; // si usas Qdrant Cloud
const qdrantCollectionName = 'your_collection';

// Configuración de Rememberizer
const rememberizerApiKey = 'YOUR_REMEMBERIZER_API_KEY';
const vectorStoreId = 'vs_abc123';
const baseUrl = 'https://api.rememberizer.ai/api/v1';

// Configuración del tamaño del lote
const BATCH_SIZE = 100;

// Inicializar cliente de Qdrant
const qdrantClient = new QdrantClient({ 
  url: qdrantUrl,
  apiKey: qdrantApiKey // Solo para Qdrant Cloud
});

// Obtener puntos de Qdrant
async function fetchPointsFromQdrant(collectionName, batchSize, offset = 0) {
  try {
    // Obtener información de la colección
    const collectionInfo = await qdrantClient.getCollection(collectionName);
    
    // Desplazarse a través de los puntos
    const scrollResult = await qdrantClient.scroll(collectionName, {
      limit: batchSize,
      offset: offset,
      with_payload: true,
      with_vectors: true
    });
    
    return {
      points: scrollResult.points,
      nextOffset: scrollResult.next_page_offset
    };
  } catch (error) {
    console.error(`Error al obtener puntos de Qdrant: ${error.message}`);
    return { points: [], nextOffset: null };
  }
}

// Subir vectores a Rememberizer
async function uploadToRememberizer(points) {
  const headers = {
    'x-api-key': rememberizerApiKey,
    'Content-Type': 'application/json'
  };
  
  const results = [];
  
  for (const point of points) {
    // Extraer datos del punto de Qdrant
    const pointId = point.id;
    const metadata = point.payload || {};
    const textContent = metadata.text || '';
    const documentName = metadata.filename || `qdrant_doc_${pointId}`;
    
    if (!textContent) {
      console.log(`Saltando ${pointId} - no se encontró contenido de texto en la carga útil`);
      continue;
    }
    
    const data = {
      name: documentName,
      content: textContent,
      // Opcional: incluir metadatos adicionales
      metadata: metadata
    };
    
    try {
      const response = await axios.post(
        `${baseUrl}/vector-stores/${vectorStoreId}/documents/text`,
        data,
        { headers }
      );
      
      if (response.status === 201) {
        console.log(`¡Documento '${documentName}' subido con éxito!`);
        results.push({ id: pointId, success: true });
      } else {
        console.error(`Error al subir el documento ${documentName}: ${response.statusText}`);
        results.push({ id: pointId, success: false, error: response.statusText });
      }
    } catch (error) {
      console.error(`Error al subir el documento ${documentName}: ${error.message}`);
      results.push({ id: pointId, success: false, error: error.message });
    }
    
    // Agregar un pequeño retraso para evitar limitaciones de tasa
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  return results;
}

// Función principal de migración
async function migrateQdrantToRememberizer() {
  try {
    console.log('Iniciando la migración de Qdrant a Rememberizer...');
    
    let offset = null;
    let totalMigrated = 0;
    
    do {
      const { points, nextOffset } = await fetchPointsFromQdrant(
        qdrantCollectionName, 
        BATCH_SIZE, 
        offset
      );
      
      offset = nextOffset;
      
      if (points.length === 0) {
        break;
      }
      
      console.log(`Se obtuvieron ${points.length} puntos de Qdrant`);
      
      const results = await uploadToRememberizer(points);
      const successCount = results.filter(r => r.success).length;
      
      totalMigrated += successCount;
      console.log(`Progreso: ${totalMigrated} puntos migrados con éxito`);
      
    } while (offset !== null);
    
    console.log(`¡Migración completa! ${totalMigrated} puntos migrados en total a Rememberizer`);
    
  } catch (error) {
    console.error('La migración falló:', error);
  }
}

// Ejecutar la migración
// migrateQdrantToRememberizer();

Migrando de Supabase pgvector

Si ya estás utilizando Supabase con pgvector, la migración a Rememberizer es particularmente sencilla ya que ambos utilizan PostgreSQL con la extensión pgvector.

import psycopg2
import requests
import json
import time
import os
from dotenv import load_dotenv

# Cargar variables de entorno
load_dotenv()

# Configuración de PostgreSQL de Supabase
SUPABASE_DB_HOST = os.getenv("SUPABASE_DB_HOST")
SUPABASE_DB_PORT = os.getenv("SUPABASE_DB_PORT", "5432")
SUPABASE_DB_NAME = os.getenv("SUPABASE_DB_NAME")
SUPABASE_DB_USER = os.getenv("SUPABASE_DB_USER")
SUPABASE_DB_PASSWORD = os.getenv("SUPABASE_DB_PASSWORD")
SUPABASE_VECTOR_TABLE = os.getenv("SUPABASE_VECTOR_TABLE", "documents")

# Configuración de Rememberizer
REMEMBERIZER_API_KEY = os.getenv("REMEMBERIZER_API_KEY")
VECTOR_STORE_ID = os.getenv("VECTOR_STORE_ID")  # p. ej., "vs_abc123"
BASE_URL = "https://api.rememberizer.ai/api/v1"

# Tamaño del lote para el procesamiento
BATCH_SIZE = 100

# Conectar a Supabase PostgreSQL
def connect_to_supabase():
    try:
        conn = psycopg2.connect(
            host=SUPABASE_DB_HOST,
            port=SUPABASE_DB_PORT,
            dbname=SUPABASE_DB_NAME,
            user=SUPABASE_DB_USER,
            password=SUPABASE_DB_PASSWORD
        )
        return conn
    except Exception as e:
        print(f"Error al conectar a Supabase PostgreSQL: {e}")
        return None

# Obtener documentos de Supabase pgvector
def fetch_documents_from_supabase(conn, batch_size, offset=0):
    try:
        cursor = conn.cursor()
        
        # Ajusta esta consulta según la estructura de tu tabla
        query = f"""
        SELECT id, content, metadata, embedding
        FROM {SUPABASE_VECTOR_TABLE}
        ORDER BY id
        LIMIT %s OFFSET %s
        """
        
        cursor.execute(query, (batch_size, offset))
        documents = cursor.fetchall()
        cursor.close()
        
        return documents
    except Exception as e:
        print(f"Error al obtener documentos de Supabase: {e}")
        return []

# Cargar documentos a Rememberizer
def upload_to_rememberizer(documents):
    headers = {
        "x-api-key": REMEMBERIZER_API_KEY,
        "Content-Type": "application/json"
    }
    
    results = []
    
    for doc in documents:
        doc_id, content, metadata, embedding = doc
        
        # Analizar metadatos si se almacenan como cadena JSON
        if isinstance(metadata, str):
            try:
                metadata = json.loads(metadata)
            except:
                metadata = {}
        elif metadata is None:
            metadata = {}
        
        document_name = metadata.get("filename", f"supabase_doc_{doc_id}")
        
        if not content:
            print(f"Omitiendo {doc_id} - no se encontró contenido")
            continue
            
        data = {
            "name": document_name,
            "content": content,
            "metadata": metadata
        }
        
        try:
            response = requests.post(
                f"{BASE_URL}/vector-stores/{VECTOR_STORE_ID}/documents/text",
                headers=headers,
                json=data
            )
            
            if response.status_code == 201:
                print(f"¡Documento '{document_name}' cargado con éxito!")
                results.append({"id": doc_id, "success": True})
            else:
                print(f"Error al cargar el documento {document_name}: {response.text}")
                results.append({"id": doc_id, "success": False, "error": response.text})
        except Exception as e:
            print(f"Excepción al cargar el documento {document_name}: {str(e)}")
            results.append({"id": doc_id, "success": False, "error": str(e)})
        
        # Agregar un pequeño retraso para prevenir limitaciones de tasa
        time.sleep(0.1)
    
    return results

# Función principal de migración
def migrate_supabase_to_rememberizer():
    conn = connect_to_supabase()
    if not conn:
        print("Error al conectar a Supabase. Abortando la migración.")
        return
    
    offset = 0
    total_migrated = 0
    
    print("Iniciando la migración de Supabase pgvector a Rememberizer...")
    
    try:
        while True:
            documents = fetch_documents_from_supabase(conn, BATCH_SIZE, offset)
            
            if not documents:
                break
                
            print(f"Se obtuvieron {len(documents)} documentos de Supabase")
            
            results = upload_to_rememberizer(documents)
            success_count = sum(1 for r in results if r.get("success", False))
            
            total_migrated += success_count
            print(f"Progreso: {total_migrated} documentos migrados con éxito")
            
            offset += BATCH_SIZE
            
    finally:
        conn.close()
    
    print(f"¡Migración completa! {total_migrated} documentos migrados en total a Rememberizer")

# Ejecutar la migración
# migrate_supabase_to_rememberizer()
const { Pool } = require('pg');
const axios = require('axios');
require('dotenv').config();

// Configuración de PostgreSQL de Supabase
const supabasePool = new Pool({
  host: process.env.SUPABASE_DB_HOST,
  port: process.env.SUPABASE_DB_PORT || 5432,
  database: process.env.SUPABASE_DB_NAME,
  user: process.env.SUPABASE_DB_USER,
  password: process.env.SUPABASE_DB_PASSWORD,
  ssl: {
    rejectUnauthorized: false
  }
});

const supabaseVectorTable = process.env.SUPABASE_VECTOR_TABLE || 'documents';

// Configuración de Rememberizer
const rememberizerApiKey = process.env.REMEMBERIZER_API_KEY;
const vectorStoreId = process.env.VECTOR_STORE_ID; // por ejemplo, "vs_abc123"
const baseUrl = 'https://api.rememberizer.ai/api/v1';

// Configuración del tamaño del lote
const BATCH_SIZE = 100;

// Obtener documentos de Supabase pgvector
async function fetchDocumentsFromSupabase(batchSize, offset = 0) {
  try {
    // Ajusta esta consulta según la estructura de tu tabla
    const query = `
      SELECT id, content, metadata, embedding
      FROM ${supabaseVectorTable}
      ORDER BY id
      LIMIT $1 OFFSET $2
    `;
    
    const result = await supabasePool.query(query, [batchSize, offset]);
    return result.rows;
  } catch (error) {
    console.error(`Error al obtener documentos de Supabase: ${error.message}`);
    return [];
  }
}

// Subir documentos a Rememberizer
async function uploadToRememberizer(documents) {
  const headers = {
    'x-api-key': rememberizerApiKey,
    'Content-Type': 'application/json'
  };
  
  const results = [];
  
  for (const doc of documents) {
    // Analizar metadata si está almacenada como cadena JSON
    let metadata = doc.metadata;
    if (typeof metadata === 'string') {
      try {
        metadata = JSON.parse(metadata);
      } catch (e) {
        metadata = {};
      }
    } else if (metadata === null) {
      metadata = {};
    }
    
    const documentName = metadata.filename || `supabase_doc_${doc.id}`;
    
    if (!doc.content) {
      console.log(`Saltando ${doc.id} - no se encontró contenido`);
      continue;
    }
    
    const data = {
      name: documentName,
      content: doc.content,
      metadata: metadata
    };
    
    try {
      const response = await axios.post(
        `${baseUrl}/vector-stores/${vectorStoreId}/documents/text`,
        data,
        { headers }
      );
      
      if (response.status === 201) {
        console.log(`¡Documento '${documentName}' subido exitosamente!`);
        results.push({ id: doc.id, success: true });
      } else {
        console.error(`Error al subir el documento ${documentName}: ${response.statusText}`);
        results.push({ id: doc.id, success: false, error: response.statusText });
      }
    } catch (error) {
      console.error(`Error al subir el documento ${documentName}: ${error.message}`);
      results.push({ id: doc.id, success: false, error: error.message });
    }
    
    // Agregar un pequeño retraso para evitar limitaciones de tasa
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  return results;
}

// Función principal de migración
async function migrateSupabaseToRememberizer() {
  try {
    console.log('Iniciando la migración de Supabase pgvector a Rememberizer...');
    
    let offset = 0;
    let totalMigrated = 0;
    
    while (true) {
      const documents = await fetchDocumentsFromSupabase(BATCH_SIZE, offset);
      
      if (documents.length === 0) {
        break;
      }
      
      console.log(`Se obtuvieron ${documents.length} documentos de Supabase`);
      
      const results = await uploadToRememberizer(documents);
      const successCount = results.filter(r => r.success).length;
      
      totalMigrated += successCount;
      console.log(`Progreso: ${totalMigrated} documentos migrados exitosamente`);
      
      offset += BATCH_SIZE;
    }
    
    console.log(`¡Migración completa! ${totalMigrated} documentos migrados en total a Rememberizer`);
    
  } catch (error) {
    console.error('La migración falló:', error);
  } finally {
    await supabasePool.end();
  }
}

// Ejecutar la migración
// migrateSupabaseToRememberizer();

Mejores Prácticas de Migración

Sigue estas recomendaciones para una migración exitosa:

  1. Planifica con Anticipación:

    • Estima el volumen de datos y el tiempo requerido para la migración

    • Programa la migración durante períodos de baja actividad

    • Aumenta el espacio en disco antes de comenzar migraciones grandes

  2. Prueba Primero:

    • Crea un almacén de vectores de prueba en Rememberizer

    • Migra un pequeño subconjunto de datos (100-1000 vectores)

    • Verifica la funcionalidad de búsqueda con consultas clave

  3. Validación de Datos:

    • Compara el conteo de documentos antes y después de la migración

    • Ejecuta consultas de referencia para asegurar resultados similares

    • Valida que los metadatos se conserven correctamente

  4. Optimiza para el Rendimiento:

    • Utiliza operaciones por lotes para mayor eficiencia

    • Considera la colocación geográfica de las bases de datos de origen y destino

    • Monitorea los límites de tasa de la API y ajusta los tamaños de los lotes en consecuencia

  5. Pasos Post-Migración:

    • Verifica la creación del índice en Rememberizer

    • Actualiza las configuraciones de la aplicación para apuntar al nuevo almacén de vectores

    • Mantén la base de datos de origen como respaldo hasta que la migración sea verificada


Asegúrate de manejar las claves de API de manera segura y seguir las mejores prácticas para la gestión de claves de API.

Para referencia detallada de la API y documentación de puntos finales, visita la página de .

¿Qué son las Incrustaciones Vectoriales y las Bases de Datos Vectoriales?
vector-store
Crear un Nuevo Almacén de Vectores
Ver Detalles de un Almacén de Vectores
Crear una Nueva Clave API
Crear un Nuevo Almacén de Vectores
Ver Detalles de un Almacén de Vectores
Crear una Nueva Clave API