Rememberizer Docs
RegistrazioneIscrizioneContattaci
Italiano
Italiano
  • Perché Rememberizer?
  • Contesto
    • Cosa sono gli Embedding Vettoriali e i Database Vettoriali?
    • Glossario
    • Terminologia Standardizzata
  • Uso personale
    • Iniziare
      • Cerca la tua conoscenza
      • Accesso al filtro Mementos
      • Conoscenza comune
      • Gestisci la tua conoscenza incorporata
  • Integrazioni
    • App Rememberizer
    • Integrazione Rememberizer Slack
    • Integrazione Rememberizer Google Drive
    • Integrazione Rememberizer Dropbox
    • Integrazione Rememberizer Gmail
    • Integrazione Rememberizer Memory
    • Server MCP Rememberizer
    • Gestisci app di terze parti
  • Risorse per Sviluppatori
    • Panoramica per Sviluppatori
  • Opzioni di integrazione
    • Registrazione e utilizzo delle chiavi API
    • Registrazione delle app Rememberizer
    • Autorizzazione delle app Rememberizer
    • Creazione di un Rememberizer GPT
    • Integrazione con LangChain
    • Archivi vettoriali
    • Talk-to-Slack l'app web di esempio
  • Integrazione Aziendale
    • Modelli di Integrazione Aziendale
  • Riferimento API
    • Home Documentazione API
    • Autenticazione
  • API principali
    • Cerca documenti per somiglianza semantica
    • Recupera documenti
    • Recupera contenuti dei documenti
    • Recupera contenuti di Slack
    • Memorizza contenuti in Rememberizer
  • Account & Configurazione
    • Recupera i dettagli dell'account utente corrente
    • Elenca le integrazioni delle fonti di dati disponibili
    • Mementi
    • Ottieni tutta la conoscenza pubblica aggiunta
  • API di Archiviazione Vettoriale
    • Documentazione dell'Archiviazione Vettoriale
    • Ottieni informazioni sull'archiviazione vettoriale
    • Ottieni un elenco di documenti in un'Archiviazione Vettoriale
    • Ottieni informazioni sul documento
    • Aggiungi un nuovo documento di testo a un'Archiviazione Vettoriale
    • Carica file in un'Archiviazione Vettoriale
    • Aggiorna il contenuto del file in un'Archiviazione Vettoriale
    • Rimuovi un documento nell'Archiviazione Vettoriale
    • Cerca documenti dell'Archiviazione Vettoriale per somiglianza semantica
  • Risorse Aggiuntive
    • Avvisi
      • Termini di Utilizzo
      • Informativa sulla Privacy
      • B2B
        • Informazioni su Reddit Agent
  • Rilasci
    • Note di Rilascio Home
  • Rilasci 2025
    • 25 Aprile 2025
    • 18 Aprile 2025
    • 11 Aprile 2025
    • 4 Aprile 2025
    • 28 Marzo 2025
    • 21 Marzo 2025
    • 14 Marzo 2025
    • 17 Gennaio 2025
  • Rilasci 2024
    • 27 Dicembre 2024
    • 20 Dicembre 2024
    • 13 Dicembre 2024
    • 6 Dicembre 2024
  • 29 Nov 2024
  • 22 Nov 2024
  • 15 Nov 2024
  • 8 Nov 2024
  • 1 Nov 2024
  • 25 Ottobre 2024
  • 18 Ottobre 2024
  • 11 Ottobre 2024
  • 4 Ottobre 2024
  • 27 Settembre 2024
  • 20 Settembre 2024
  • 13 Settembre 2024
  • 16 Ago 2024
  • 9 Ago 2024
  • 2 Ago 2024
  • 26 Lug 2024
  • 12 Lug 2024
  • 28 Giugno 2024
  • 14 Giugno 2024
  • 31 maggio 2024
  • 17 maggio 2024
  • 10 maggio 2024
  • 26 Aprile 2024
  • 19 Aprile 2024
  • 12 Aprile 2024
  • 5 Aprile 2024
  • 25 Mar 2024
  • 18 Mar 2024
  • 11 Mar 2024
  • 4 Mar 2024
  • 26 Febbraio 2024
  • 19 Febbraio 2024
  • 12 Febbraio 2024
  • 5 Febbraio 2024
  • 29 Gennaio 2024
  • 22 Gennaio 2024
  • 15 Gennaio 2024
  • Documentazione LLM
    • Documentazione LLM Pronta di Rememberizer
Powered by GitBook
On this page
  • Introduzione
  • Panoramica Tecnica
  • Come Funzionano gli Archivi Vettoriali
  • Componenti Chiave
  • Architettura
  • Iniziare
  • Creazione di un Negozio di Vettori
  • Opzioni di Configurazione
  • Gestione degli Archivi Vettoriali
  • Gestione delle Chiavi API
  • Creazione di Chiavi API
  • Revoca delle chiavi API
  • Utilizzo dell'API del Vector Store
  • Esempi di Codice
  • Considerazioni sulle Prestazioni
  • Ottimizzazione per Diversi Volumi di Dati
  • Strategie di Suddivisione
  • Ottimizzazione delle Query
  • Utilizzo Avanzato
  • Reindicizzazione
  • Miglioramento delle Query
  • Migrazione da Altri Database Vettoriali
  • Panoramica della Migrazione
  • Vantaggi della Migrazione a Rememberizer
  • Migrazione da Pinecone
  • Migrazione da Qdrant
  • Migrazione da Supabase pgvector
  • Migliori Pratiche per la Migrazione
  1. Opzioni di integrazione

Archivi vettoriali

Questa guida ti aiuterà a capire come utilizzare il Rememberizer Vector Store come sviluppatore.

PreviousIntegrazione con LangChainNextTalk-to-Slack l'app web di esempio

Last updated 17 days ago

L'Archivio Vettoriale di Rememberizer semplifica il processo di gestione dei dati vettoriali, consentendoti di concentrarti sull'input di testo e sfruttare la potenza dei vettori per varie applicazioni come la ricerca e l'analisi dei dati.

Introduzione

Il Rememberizer Vector Store fornisce un'interfaccia facile da usare per gestire i dati vettoriali, astrando la complessità delle embedding vettoriali. Alimentato da PostgreSQL con l'estensione pgvector, il Rememberizer Vector Store ti consente di lavorare direttamente con il testo. Il servizio gestisce il chunking, la vettorizzazione e l'archiviazione dei dati testuali, rendendo più facile per te concentrarti sulla logica principale della tua applicazione.

Per una comprensione più profonda dei concetti teorici dietro le embedding vettoriali e i database vettoriali, vedi .

Panoramica Tecnica

Come Funzionano gli Archivi Vettoriali

Gli Archivi Vettoriali di Rememberizer convertono il testo in rappresentazioni vettoriali ad alta dimensione (embedding) che catturano il significato semantico. Questo consente:

  1. Ricerca Semantica: Trovare documenti basati sul significato piuttosto che solo su parole chiave

  2. Corrispondenza di Somiglianza: Identificare contenuti concettualmente correlati

  3. Recupero Efficiente: Localizzare rapidamente informazioni rilevanti da grandi set di dati

Componenti Chiave

  • Elaborazione dei Documenti: Il testo viene suddiviso in pezzi di dimensioni ottimali con confini sovrapposti per preservare il contesto

  • Vettorizzazione: I pezzi vengono convertiti in embedding utilizzando modelli all'avanguardia

  • Indicizzazione: Algoritmi specializzati organizzano i vettori per una ricerca di similarità efficiente

  • Elaborazione delle Query: Le query di ricerca vengono vettorizzate e confrontate con gli embedding memorizzati

Architettura

Rememberizer implementa i vettori di archiviazione utilizzando:

  • PostgreSQL con estensione pgvector: Per un'archiviazione e ricerca dei vettori efficiente

  • Organizzazione basata su collezioni: Ogni vettore di archiviazione ha la propria collezione isolata

  • Accesso guidato da API: Endpoint RESTful semplici per tutte le operazioni

Iniziare

Creazione di un Negozio di Vettori

  1. Naviga nella Sezione Negozio di Vettori nel tuo pannello di controllo

  2. Clicca su "Crea nuovo Negozio di Vettori":

    • Apparirà un modulo che ti chiederà di inserire i dettagli.

  3. Compila i Dettagli:

    • Nome: Fornisci un nome unico per il tuo negozio di vettori.

    • Descrizione: Scrivi una breve descrizione del negozio di vettori.

    • Modello di Embedding: Seleziona il modello che converte il testo in vettori.

    • Algoritmo di Indicizzazione: Scegli come i vettori saranno organizzati per la ricerca.

    • Metrica di Ricerca: Definisci come viene calcolata la somiglianza tra i vettori.

    • Dimensione del Vettore: La dimensione degli embedding dei vettori (tipicamente 768-1536).

  4. Invia il Modulo:

    • Clicca sul pulsante "Crea". Riceverai una notifica di successo e il nuovo negozio apparirà nella tua lista di negozi di vettori.

Opzioni di Configurazione

Modelli di Embedding

Modello
Dimensioni
Descrizione
Migliore per

openai/text-embedding-3-large

1536

Modello di embedding ad alta precisione di OpenAI

Applicazioni di produzione che richiedono la massima precisione

openai/text-embedding-3-small

1536

Modello di embedding più piccolo e veloce di OpenAI

Applicazioni con requisiti di throughput più elevati

Algoritmi di indicizzazione

Algoritmo
Descrizione
Compromessi

IVFFLAT (predefinito)

File invertito con compressione piatta

Buon equilibrio tra velocità e precisione; funziona bene per la maggior parte dei dataset

HNSW

Mondo piccolo navigabile gerarchico

Maggiore precisione per grandi dataset; requisiti di memoria più elevati

Metriche di Ricerca

Metri
Descrizione
Migliore per

coseno (predefinito)

Misura l'angolo tra i vettori

Abbinamento di somiglianza di uso generale

prodotto interno (ip)

Prodotto scalare tra vettori

Quando la magnitudine del vettore è importante

L2 (Euclideo)

Distanza in linea retta tra i vettori

Quando le relazioni spaziali sono importanti

Gestione degli Archivi Vettoriali

  1. Visualizza e Modifica gli Archivi Vettoriali:

    • Accedi al pannello di gestione per visualizzare, modificare o eliminare gli archivi vettoriali.

  2. Visualizzazione dei Documenti:

    • Sfoglia i singoli documenti e i loro metadati associati all'interno di un archivio vettoriale specifico.

  3. Statistiche:

    • Visualizza statistiche dettagliate come il numero di vettori memorizzati, le prestazioni delle query e le metriche operative.

Gestione delle Chiavi API

Le chiavi API vengono utilizzate per autenticare e autorizzare l'accesso agli endpoint API del Rememberizer Vector Store. Una corretta gestione delle chiavi API è essenziale per mantenere la sicurezza e l'integrità dei tuoi vector store.

Creazione di Chiavi API

  1. Vai alla pagina dei dettagli del tuo Vector Store

  2. Naviga alla Sezione di Gestione delle Chiavi API:

    • Può essere trovata all'interno della scheda "Configurazione"

  3. Clicca su "Aggiungi Chiave API":

    • Apparirà un modulo che ti chiederà di inserire i dettagli.

  4. Compila i Dettagli:

    • Nome: Fornisci un nome per la chiave API per aiutarti a identificare il suo caso d'uso.

  5. Invia il Modulo:

    • Clicca sul pulsante "Crea". La nuova chiave API verrà generata e visualizzata. Assicurati di copiarla e conservarla in modo sicuro. Questa chiave viene utilizzata per autenticare le richieste a quel specifico vector store.

Revoca delle chiavi API

Se una chiave API non è più necessaria, puoi eliminarla per prevenire potenziali abusi.

Per motivi di sicurezza, potresti voler ruotare le tue chiavi API periodicamente. Questo comporta la generazione di una nuova chiave e la revoca della vecchia.

Utilizzo dell'API del Vector Store

Dopo aver creato un Vector Store e generato una chiave API, puoi interagire con esso utilizzando l'API REST.

Esempi di Codice

import requests
import json

API_KEY = "your_api_key_here"
VECTOR_STORE_ID = "vs_abc123"  # Sostituisci con il tuo ID del vettore
BASE_URL = "https://api.rememberizer.a

# Carica un documento nello store vettoriale
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}' caricato con successo!")
            return response.json()
        else:
            print(f"Errore durante il caricamento del documento: {response.text}")
            return None

# Carica contenuti testuali nel negozio vettoriale
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 di testo '{document_name}' caricato con successo!")
        return response.json()
    else:
        print(f"Errore durante il caricamento del testo: {response.text}")
        return None

# Cerca nel negozio di vettori
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"Trovati {len(results['matched_chunks'])} risultati per '{query}'")
        
        # Stampa il risultato migliore
        if results['matched_chunks']:
            top_match = results['matched_chunks'][0]
            print(f"Miglior risultato (distanza: {top_match['distance']}):")
            print(f"Documento: {top_match['document']['name']}")
            print(f"Contenuto: {top_match['matched_content']}")
        
        return results
    else:
        print(f"Errore nella ricerca: {response.text}")
        return None

# Esempio di utilizzo
# carica_documento("path/to/document.pdf")
# upload_text("Questo è un testo di esempio da vettorizzare", "sample-document.txt")
# search_vector_store("Come funziona la similarità vettoriale?")
// Client API per il Vector Store
class VectorStoreClient {
  constructor(apiKey, vectorStoreId) {
    this.apiKey = apiKey;
    this.vectorStoreId = vectorStoreId;
    this.baseUrl = 'https://api.rememberizer.ai/api/v1';
  }

  // Ottieni informazioni sul vector store
  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(`Impossibile ottenere informazioni sul vector store: ${response.statusText}`);
    }
    
    return response.json();
  }

  // Carica un documento di testo
  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(`Impossibile caricare il documento di testo: ${response.statusText}`);
    }
    
    return response.json();
  }

  // Carica un file
  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(`Impossibile caricare il file: ${xhr.statusText}`));
        }
      };
      
      xhr.onerror = () => {
        reject(new Error('Errore di rete durante il caricamento del file'));
      };
      
      xhr.send(formData);
    });
  }

  // Cerca documenti nel vector store
  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(`La ricerca è fallita: ${response.statusText}`);
    }
    
    return response.json();
  }

  // Elenca tutti i documenti nel vector store
  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(`Impossibile elencare i documenti: ${response.statusText}`);
    }
    
    return response.json();
  }

  // Elimina 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(`Impossibile eliminare il documento: ${response.statusText}`);
    }
    
    return true;
  }
}

// Esempio di utilizzo
/*
const client = new VectorStoreClient('your_api_key', 'vs_abc123');

// Cerca documenti
client.searchDocuments('Come funziona la ricerca semantica?')
  .then(results => {
    console.log(`Trovati ${results.matched_chunks.length} risultati`);
    results.matched_chunks.forEach(match => {
      console.log(`Documento: ${match.document.name}`);
      console.log(`Punteggio: ${match.distance}`);
      console.log(`Contenuto: ${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

  # Ottieni dettagli sul vector store
  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

  # Carica contenuto di testo
  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

  # Cerca documenti
  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

  # Elenca documenti
  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

  # Carica file (form 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 "La richiesta API è fallita: #{response.code} #{response.message}\n#{response.body}"
    end
    
    response
  end
end

Esempio di utilizzo

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

Cerca documenti

results = client.search('Quali sono le migliori pratiche per la sicurezza dei dati?') puts "Trovati #{results['matched_chunks'].length} risultati"

Mostra il risultato migliore

if results['matched_chunks'].any? top_match = results['matched_chunks'].first puts "Miglior corrispondenza (distanza: #{top_match['distance']}):" puts "Documento: #{top_match['document']['name']}" puts "Contenuto: #{top_match['matched_content']}" end =end


</div>

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

```bash
# Imposta la tua chiave API e l'ID del Vector Store
API_KEY="your_api_key_here"
VECTOR_STORE_ID="vs_abc123"
BASE_URL="https://api.rememberizer.ai/api/v1"

# Ottieni informazioni sullo store vettoriale
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}" \
  -H "x-api-key: ${API_KEY}"

# Carica un documento di testo
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": "Questo è un documento di esempio che sarà vettorizzato e memorizzato nel database vettoriale per la ricerca semantica."
  }'

# Carica un file
curl -X POST "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents" \
  -H "x-api-key: ${API_KEY}" \
  -F "file=@/path/to/your/document.pdf"

# Cerca documenti
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}"

# Elenca tutti i documenti
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents" \
  -H "x-api-key: ${API_KEY}"

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

Considerazioni sulle Prestazioni

In arrivo: Diagramma dell'Architettura del Vector Store

Questo diagramma dell'architettura tecnica illustrerà:

  • L'architettura di base PostgreSQL + pgvector

  • Strutture degli algoritmi di indicizzazione (IVFFLAT vs. HNSW)

  • Come funzionano le metriche di ricerca nello spazio vettoriale (confronto visivo)

  • Processo di suddivisione dei documenti con visualizzazione delle sovrapposizioni

  • Considerazioni sulle prestazioni visualizzate su diverse scale

Ottimizzazione per Diversi Volumi di Dati

Volume di Dati
Configurazione Raccomandata
Note

Piccolo (<10k documenti)

IVFFLAT, similarità coseno

Configurazione semplice che offre buone prestazioni

Medio (10k-100k documenti)

IVFFLAT, assicurarsi di effettuare regolarmente il reindicizzazione

Equilibrio tra velocità di ricerca e manutenzione dell'indice

Grande (>100k documenti)

HNSW, considerare di aumentare le dimensioni del vettore

Maggiore utilizzo di memoria ma mantiene le prestazioni su larga scala

Strategie di Suddivisione

Il processo di suddivisione influisce significativamente sulla qualità della ricerca:

  • Dimensione del Chunk: Rememberizer utilizza una dimensione di chunk predefinita di 1024 byte con un sovrapposizione di 200 byte

  • Chunk Più Piccoli (512-1024 byte): Corrispondenze più precise, migliori per domande specifiche

  • Chunk Più Grandi (1500-2048 byte): Maggiore contesto in ogni corrispondenza, migliori per argomenti più ampi

  • Sovrapposizione: Garantisce che il contesto non venga perso ai confini dei chunk

Ottimizzazione delle Query

  • Finestre di Contesto: Usa prev_chunks e next_chunks per recuperare contenuti circostanti

  • Conteggio dei Risultati: Inizia con 3-5 risultati (n parametro) e adatta in base alle esigenze di precisione

  • Soglia: Regola il parametro t per filtrare i risultati in base al punteggio di somiglianza

Utilizzo Avanzato

Reindicizzazione

Rememberizer attiva automaticamente la reindicizzazione quando il numero di vettori supera le soglie predefinite, ma considera la reindicizzazione manuale dopo:

  • Aver caricato un gran numero di documenti

  • Aver cambiato il modello di embedding

  • Aver modificato l'algoritmo di indicizzazione

Miglioramento delle Query

Per risultati di ricerca migliori:

  1. Essere specifici nelle query di ricerca

  2. Includere contesto quando possibile

  3. Usare linguaggio naturale piuttosto che parole chiave

  4. Regolare i parametri in base alla qualità dei risultati

Migrazione da Altri Database Vettoriali

Se attualmente stai utilizzando altre soluzioni di database vettoriali e desideri migrare a Rememberizer Vector Store, le seguenti guide ti aiuteranno a trasferire i tuoi dati in modo efficiente.

Panoramica della Migrazione

La migrazione dei dati vettoriali comporta:

  1. Esportare i dati dal tuo database vettoriale di origine

  2. Convertire i dati in un formato compatibile con Rememberizer

  3. Importare i dati nel tuo Rememberizer Vector Store

  4. Verificare che la migrazione sia stata completata con successo

Vantaggi della Migrazione a Rememberizer

  • Fondazione PostgreSQL: Costruito su una tecnologia di database matura con backup e recupero integrati

  • Ecosistema Integrato: Connessione senza soluzione di continuità con altri componenti di Rememberizer

  • Gestione Semplificata: Interfaccia unificata per le operazioni vettoriali

  • Sicurezza Avanzata: Sicurezza a livello di riga e controlli di accesso dettagliati

  • Architettura Scalabile: Ottimizzazione delle prestazioni man mano che i tuoi dati crescono

Migrazione da Pinecone

import os
import pinecone
import requests
import json
import time

# Configura il client Pinecone
pinecone.init(api_key="PINECONE_API_KEY", environment="PINECONE_ENV")
source_index = pinecone.Index("your-pinecone-index")

# Configura il client Rememberizer Vector Store
REMEMBERIZER_API_KEY = "your_rememberizer_api_key"
VECTOR_STORE_ID = "vs_abc123"  # Il tuo ID del vector store Rememberizer
BASE_URL = "https://api.rememberizer.ai/api/v1"

# 1. Imposta la dimensione del batch per la migrazione (regola in base alle dimensioni dei tuoi dati)
BATCH_SIZE = 100

# 2. Funzione per ottenere vettori da Pinecone
def fetch_vectors_from_pinecone(index_name, batch_size, cursor=None):
    # Usa l'operazione di elenco se disponibile nella tua versione di 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:
        # Per versioni più vecchie di Pinecone senza operazione di elenco
        # Questo è un approccio semplificato; l'implementazione effettiva dipende dal tuo modello di accesso ai dati
        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. Funzione per caricare vettori su 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():
        # Converti i dati del vettore Pinecone nel formato 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"Salto {vector_id} - nessun contenuto testuale trovato nei metadati")
            continue
            
        data = {
            "name": document_name,
            "content": content,
            # Facoltativo: includere metadati aggiuntivi
            "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}' caricato con successo!")
        else:
            print(f"Errore nel caricamento del documento {document_name}: {response.text}")
        
        # Aggiungi un piccolo ritardo per prevenire il limite di velocità
        time.sleep(0.1)

# 4. Funzione principale di migrazione
def migrate_pinecone_to_rememberizer():
    cursor = None
    total_migrated = 0
    
    print("Inizio della migrazione da Pinecone a Rememberizer...")
    
    while True:
        vectors, cursor = fetch_vectors_from_pinecone("your-pinecone-index", BATCH_SIZE, cursor)
        
        if not vectors:
            break
            
        print(f"Recuperati {len(vectors)} vettori da Pinecone")
        upload_to_rememberizer(vectors)
        
        total_migrated += len(vectors)
        print(f"Progresso: {total_migrated} vettori migrati")
        
        if not cursor:
            break
    
    print(f"Migrazione completata! {total_migrated} vettori totali migrati a Rememberizer")

# Esegui la migrazione
# migrate_pinecone_to_rememberizer()
const { PineconeClient } = require('@pinecone-database/pinecone');
const axios = require('axios');

// Configurazione di Pinecone
const pineconeApiKey = 'PINECONE_API_KEY';
const pineconeEnvironment = 'PINECONE_ENVIRONMENT';
const pineconeIndexName = 'YOUR_PINECONE_INDEX';

// Configurazione di Rememberizer
const rememberizerApiKey = 'YOUR_REMEMBERIZER_API_KEY';
const vectorStoreId = 'vs_abc123';
const baseUrl = 'https://api.rememberizer.ai/api/v1';

// Configurazione della dimensione del batch
const BATCH_SIZE = 100;

// Inizializza il client di Pinecone
async function initPinecone() {
  const pinecone = new PineconeClient();
  await pinecone.init({
    apiKey: pineconeApiKey,
    environment: pineconeEnvironment,
  });
  return pinecone;
}

// Recupera i vettori da Pinecone
async function fetchVectorsFromPinecone(pinecone, batchSize, paginationToken = null) {
  const index = pinecone.Index(pineconeIndexName);
  
  try {
    // Per le versioni più recenti di Pinecone
    const listResponse = await index.list({
      limit: batchSize,
      paginationToken: paginationToken
    });
    
    return {
      vectors: listResponse.vectors || {},
      nextToken: listResponse.paginationToken
    };
  } catch (error) {
    // Fallback per le versioni più vecchie di Pinecone
    // Questo è semplificato; l'implementazione effettiva dipende dal tuo modello di accesso ai dati
    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 };
  }
}

// Carica i vettori su 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(`Salto ${vectorId} - nessun contenuto testuale trovato nei metadati`);
      continue;
    }
    
    const data = {
      name: documentName,
      content: content,
      // Facoltativo: includere metadati aggiuntivi
      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}' caricato con successo!`);
        results.push({ id: vectorId, success: true });
      } else {
        console.error(`Errore durante il caricamento del documento ${documentName}: ${response.statusText}`);
        results.push({ id: vectorId, success: false, error: response.statusText });
      }
    } catch (error) {
      console.error(`Errore durante il caricamento del documento ${documentName}: ${error.message}`);
      results.push({ id: vectorId, success: false, error: error.message });
    }
    
    // Aggiungi un piccolo ritardo per prevenire il limite di velocità
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  return results;
}

// Funzione principale di migrazione
async function migratePineconeToRememberizer() {
  try {
    console.log('Inizio della migrazione da 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(`Recuperati ${Object.keys(vectors).length} vettori da Pinecone`);
      
      const results = await uploadToRememberizer(vectors);
      const successCount = results.filter(r => r.success).length;
      
      totalMigrated += successCount;
      console.log(`Progresso: ${totalMigrated} vettori migrati con successo`);
      
    } while (nextToken);
    
    console.log(`Migrazione completata! ${totalMigrated} vettori totali migrati su Rememberizer`);
    
  } catch (error) {
    console.error('Migrazione fallita:', error);
  }
}

// Esegui la migrazione
// migratePineconeToRememberizer();

Migrazione da Qdrant

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

# Configura il client Qdrant
QDRANT_URL = "http://localhost:6333"  # o il tuo URL Qdrant cloud
QDRANT_API_KEY = "your_qdrant_api_key"  # se utilizzi Qdrant Cloud
QDRANT_COLLECTION_NAME = "your_collection"

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

# Configura il client Rememberizer Vector Store
REMEMBERIZER_API_KEY = "your_rememberizer_api_key"
VECTOR_STORE_ID = "vs_abc123"  # Il tuo ID del vector store Rememberizer
BASE_URL = "https://api.rememberizer.ai/api/v1"

# Dimensione del batch per l'elaborazione
BATCH_SIZE = 100

# Funzione per recuperare punti da Qdrant
def fetch_points_from_qdrant(collection_name, batch_size, offset=0):
    try:
        # Ottieni informazioni sulla collezione per determinare la dimensione del vettore
        collection_info = qdrant_client.get_collection(collection_name=collection_name)
        
        # Scorri attraverso i punti
        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 di (punti, next_offset)
        next_offset = scroll_result[1]
        
        return points, next_offset
    except Exception as e:
        print(f"Errore nel recupero dei punti da Qdrant: {e}")
        return [], None

# Funzione per caricare vettori su Rememberizer
def upload_to_rememberizer(points):
    headers = {
        "x-api-key": REMEMBERIZER_API_KEY,
        "Content-Type": "application/json"
    }
    
    results = []
    
    for point in points:
        # Estrai dati dal punto 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"Salto {point_id} - nessun contenuto testuale trovato nel payload")
            continue
            
        data = {
            "name": document_name,
            "content": text_content,
            # Facoltativo: includere metadati aggiuntivi
            "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}' caricato con successo!")
                results.append({"id": point_id, "success": True})
            else:
                print(f"Errore nel caricamento del documento {document_name}: {response.text}")
                results.append({"id": point_id, "success": False, "error": response.text})
        except Exception as e:
            print(f"Eccezione nel caricamento del documento {document_name}: {str(e)}")
            results.append({"id": point_id, "success": False, "error": str(e)})
        
        # Aggiungi un piccolo ritardo per prevenire il limite di velocità
        time.sleep(0.1)
    
    return results

# Funzione principale di migrazione
def migrate_qdrant_to_rememberizer():
    offset = None
    total_migrated = 0
    
    print("Inizio della migrazione da Qdrant a Rememberizer...")
    
    while True:
        points, next_offset = fetch_points_from_qdrant(
            QDRANT_COLLECTION_NAME, 
            BATCH_SIZE,
            offset
        )
        
        if not points:
            break
            
        print(f"Recuperati {len(points)} punti da 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"Progresso: {total_migrated} punti migrati con successo")
        
        if next_offset is None:
            break
            
        offset = next_offset
    
    print(f"Migrazione completata! {total_migrated} punti totali migrati a Rememberizer")

# Esegui la migrazione
# migra_qdrant_a_rememberizer()
const { QdrantClient } = require('@qdrant/js-client-rest');
const axios = require('axios');

// Configurazione di Qdrant
const qdrantUrl = 'http://localhost:6333'; // o il tuo URL cloud di Qdrant
const qdrantApiKey = 'your_qdrant_api_key'; // se utilizzi Qdrant Cloud
const qdrantCollectionName = 'your_collection';

// Configurazione di Rememberizer
const rememberizerApiKey = 'YOUR_REMEMBERIZER_API_KEY';
const vectorStoreId = 'vs_abc123';
const baseUrl = 'https://api.rememberizer.ai/api/v1';

// Configurazione della dimensione del batch
const BATCH_SIZE = 100;

// Inizializza il client Qdrant
const qdrantClient = new QdrantClient({ 
  url: qdrantUrl,
  apiKey: qdrantApiKey // Solo per Qdrant Cloud
});

// Recupera i punti da Qdrant
async function fetchPointsFromQdrant(collectionName, batchSize, offset = 0) {
  try {
    // Ottieni informazioni sulla collezione
    const collectionInfo = await qdrantClient.getCollection(collectionName);
    
    // Scorri attraverso i punti
    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(`Errore nel recupero dei punti da Qdrant: ${error.message}`);
    return { points: [], nextOffset: null };
  }
}

// Carica i vettori su Rememberizer
async function uploadToRememberizer(points) {
  const headers = {
    'x-api-key': rememberizerApiKey,
    'Content-Type': 'application/json'
  };
  
  const results = [];
  
  for (const point of points) {
    // Estrai i dati dal punto di Qdrant
    const pointId = point.id;
    const metadata = point.payload || {};
    const textContent = metadata.text || '';
    const documentName = metadata.filename || `qdrant_doc_${pointId}`;
    
    if (!textContent) {
      console.log(`Salto ${pointId} - nessun contenuto testuale trovato nel payload`);
      continue;
    }
    
    const data = {
      name: documentName,
      content: textContent,
      // Facoltativo: includi metadati aggiuntivi
      metadata: metadata
    };
    
    try {
      const response = await axios.post(
        `${baseUrl}/vector-stores/${vectorStoreId}/documents/text`,
        data,
        { headers }
      );
      
      if (response.status === 201) {
        console.log(`Documento '${documentName}' caricato con successo!`);
        results.push({ id: pointId, success: true });
      } else {
        console.error(`Errore nel caricamento del documento ${documentName}: ${response.statusText}`);
        results.push({ id: pointId, success: false, error: response.statusText });
      }
    } catch (error) {
      console.error(`Errore nel caricamento del documento ${documentName}: ${error.message}`);
      results.push({ id: pointId, success: false, error: error.message });
    }
    
    // Aggiungi un piccolo ritardo per prevenire il rate limiting
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  return results;
}

// Funzione principale di migrazione
async function migrateQdrantToRememberizer() {
  try {
    console.log('Inizio migrazione da 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(`Recuperati ${points.length} punti da Qdrant`);
      
      const results = await uploadToRememberizer(points);
      const successCount = results.filter(r => r.success).length;
      
      totalMigrated += successCount;
      console.log(`Progresso: ${totalMigrated} punti migrati con successo`);
      
    } while (offset !== null);
    
    console.log(`Migrazione completata! ${totalMigrated} punti totali migrati a Rememberizer`);
    
  } catch (error) {
    console.error('Migrazione fallita:', error);
  }
}

// Esegui la migrazione
// migrateQdrantToRememberizer();

Migrazione da Supabase pgvector

Se stai già utilizzando Supabase con pgvector, la migrazione a Rememberizer è particolarmente semplice poiché entrambi utilizzano PostgreSQL con l'estensione pgvector.

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

# Carica le variabili d'ambiente
load_dotenv()

# Configurazione PostgreSQL di 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")

# Configurazione di Rememberizer
REMEMBERIZER_API_KEY = os.getenv("REMEMBERIZER_API_KEY")
VECTOR_STORE_ID = os.getenv("VECTOR_STORE_ID")  # ad esempio, "vs_abc123"
BASE_URL = "https://api.rememberizer.ai/api/v1"

# Dimensione del batch per l'elaborazione
BATCH_SIZE = 100

# Connettersi 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"Errore nella connessione a Supabase PostgreSQL: {e}")
        return None

# Recupera documenti da Supabase pgvector
def fetch_documents_from_supabase(conn, batch_size, offset=0):
    try:
        cursor = conn.cursor()
        
        # Regola questa query in base alla struttura della tua tabella
        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"Errore durante il recupero dei documenti da Supabase: {e}")
        return []

# Carica documenti su 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
        
        # Analizza i metadati se sono memorizzati come stringa 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"Salto {doc_id} - nessun contenuto trovato")
            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}' caricato con successo!")
                results.append({"id": doc_id, "success": True})
            else:
                print(f"Errore durante il caricamento del documento {document_name}: {response.text}")
                results.append({"id": doc_id, "success": False, "error": response.text})
        except Exception as e:
            print(f"Eccezione durante il caricamento del documento {document_name}: {str(e)}")
            results.append({"id": doc_id, "success": False, "error": str(e)})
        
        # Aggiungi un piccolo ritardo per prevenire il limite di velocità
        time.sleep(0.1)
    
    return results

# Funzione principale di migrazione
def migrate_supabase_to_rememberizer():
    conn = connect_to_supabase()
    if not conn:
        print("Impossibile connettersi a Supabase. Interruzione della migrazione.")
        return
    
    offset = 0
    total_migrated = 0
    
    print("Inizio della migrazione da Supabase pgvector a Rememberizer...")
    
    try:
        while True:
            documents = fetch_documents_from_supabase(conn, BATCH_SIZE, offset)
            
            if not documents:
                break
                
            print(f"Recuperati {len(documents)} documenti da 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"Progresso: {total_migrated} documenti migrati con successo")
            
            offset += BATCH_SIZE
            
    finally:
        conn.close()
    
    print(f"Migrazione completata! {total_migrated} documenti totali migrati a Rememberizer")

# Esegui la migrazione
# migrate_supabase_to_rememberizer()
const { Pool } = require('pg');
const axios = require('axios');
require('dotenv').config();

// Configurazione PostgreSQL di 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';

// Configurazione di Rememberizer
const rememberizerApiKey = process.env.REMEMBERIZER_API_KEY;
const vectorStoreId = process.env.VECTOR_STORE_ID; // e.g., "vs_abc123"
const baseUrl = 'https://api.rememberizer.ai/api/v1';

// Configurazione della dimensione del batch
const BATCH_SIZE = 100;

// Recupera documenti da Supabase pgvector
async function fetchDocumentsFromSupabase(batchSize, offset = 0) {
  try {
    // Modifica questa query in base alla struttura della tua tabella
    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(`Errore nel recupero dei documenti da Supabase: ${error.message}`);
    return [];
  }
}

// Carica documenti su Rememberizer
async function uploadToRememberizer(documents) {
  const headers = {
    'x-api-key': rememberizerApiKey,
    'Content-Type': 'application/json'
  };
  
  const results = [];
  
  for (const doc of documents) {
    // Analizza i metadati se sono memorizzati come stringa 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(`Salto ${doc.id} - nessun contenuto trovato`);
      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}' caricato con successo!`);
        results.push({ id: doc.id, success: true });
      } else {
        console.error(`Errore nel caricamento del documento ${documentName}: ${response.statusText}`);
        results.push({ id: doc.id, success: false, error: response.statusText });
      }
    } catch (error) {
      console.error(`Errore nel caricamento del documento ${documentName}: ${error.message}`);
      results.push({ id: doc.id, success: false, error: error.message });
    }
    
    // Aggiungi un piccolo ritardo per prevenire il limite di velocità
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  return results;
}

// Funzione principale di migrazione
async function migrateSupabaseToRememberizer() {
  try {
    console.log('Inizio migrazione da 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(`Recuperati ${documents.length} documenti da Supabase`);
      
      const results = await uploadToRememberizer(documents);
      const successCount = results.filter(r => r.success).length;
      
      totalMigrated += successCount;
      console.log(`Progresso: ${totalMigrated} documenti migrati con successo`);
      
      offset += BATCH_SIZE;
    }
    
    console.log(`Migrazione completata! ${totalMigrated} documenti totali migrati su Rememberizer`);
    
  } catch (error) {
    console.error('Migrazione fallita:', error);
  } finally {
    await supabasePool.end();
  }
}

// Esegui la migrazione
// migrateSupabaseToRememberizer();

Migliori Pratiche per la Migrazione

Segui queste raccomandazioni per una migrazione di successo:

  1. Pianifica in Anticipo:

    • Stima il volume dei dati e il tempo necessario per la migrazione

    • Pianifica la migrazione durante i periodi di bassa affluenza

    • Aumenta lo spazio su disco prima di iniziare grandi migrazioni

  2. Testa Prima:

    • Crea un archivio vettoriale di prova in Rememberizer

    • Migra un piccolo sottoinsieme di dati (100-1000 vettori)

    • Verifica la funzionalità di ricerca con query chiave

  3. Validazione dei Dati:

    • Confronta i conteggi dei documenti prima e dopo la migrazione

    • Esegui query di benchmark per garantire risultati simili

    • Valida che i metadati siano correttamente preservati

  4. Ottimizza per le Prestazioni:

    • Usa operazioni in batch per efficienza

    • Considera la collocazione geografica dei database sorgente e di destinazione

    • Monitora i limiti di velocità dell'API e regola le dimensioni dei batch di conseguenza

  5. Passi Post-Migrazione:

    • Verifica la creazione dell'indice in Rememberizer

    • Aggiorna le configurazioni dell'applicazione per puntare al nuovo archivio vettoriale

    • Tieni il database sorgente come backup fino a quando la migrazione non è verificata

Per un riferimento API dettagliato e documentazione sugli endpoint, visita la pagina Documentazione dell'Archiviazione Vettoriale.


Assicurati di gestire le chiavi API in modo sicuro e segui le migliori pratiche per la gestione delle chiavi API.

Crea un Nuovo Negozio di Vettori
Visualizza Dettagli di un Archivio Vettoriale
Crea una Nuova Chiave API
Cosa sono le embedding vettoriali e i database vettoriali?
Crea un Nuovo Negozio di Vettori
Crea una Nuova Chiave API
Visualizza Dettagli di un Archivio Vettoriale