Rememberizer Docs
Sign inSign upContact us
Português
Português
  • Por que Rememberizer?
  • Contexto
    • O que são Embeddings Vetoriais e Bancos de Dados Vetoriais?
    • Glossário
    • Terminologia Padronizada
  • Uso Pessoal
    • Introdução
      • Pesquise seu conhecimento
      • Acesso ao Filtro de Mementos
      • Conhecimento Comum
      • Gerencie seu conhecimento incorporado
  • Integrações
    • Aplicativo Rememberizer
    • Integração do Rememberizer com o Slack
    • Integração do Rememberizer com o Google Drive
    • Integração do Rememberizer com o Dropbox
    • Integração do Rememberizer com o Gmail
    • Integração do Rememberizer com a Memória
    • Servidores MCP do Rememberizer
    • Gerenciar aplicativos de terceiros
  • Recursos para Desenvolvedores
    • Visão Geral do Desenvolvedor
  • Opções de Integração
    • Registrando e usando Chaves de API
    • Registrando aplicativos Rememberizer
    • Autorizando aplicativos Rememberizer
    • Criando um Rememberizer GPT
    • Integração com LangChain
    • Armazenamentos de Vetores
    • Talk-to-Slack o Aplicativo Web de Exemplo
  • Integração Empresarial
    • Padrões de Integração Empresarial
  • Referência da API
    • Página Inicial da Documentação da API
    • Autenticação
  • APIs Principais
    • Pesquisar documentos por similaridade semântica
    • Recuperar documentos
    • Recuperar conteúdos de documentos
    • Recuperar conteúdo do Slack
    • Memorizar conteúdo para Rememberizer
  • Conta e Configuração
    • Recuperar detalhes da conta do usuário atual
    • Listar integrações de fontes de dados disponíveis
    • Mementos
    • Obter todo o conhecimento público adicionado
  • APIs de Armazenamento Vetorial
    • Documentação do Armazenamento Vetorial
    • Obter informações do armazenamento vetorial
    • Obter uma lista de documentos em um Armazenamento Vetorial
    • Obter informações do documento
    • Adicionar novo documento de texto a um Armazenamento Vetorial
    • Enviar arquivos para um Armazenamento Vetorial
    • Atualizar conteúdo de arquivo em um Armazenamento Vetorial
    • Remover um documento no Armazenamento Vetorial
    • Pesquisar documentos do Armazenamento Vetorial por similaridade semântica
  • Recursos Adicionais
    • Avisos
      • Termos de Uso
      • Política de Privacidade
      • B2B
        • Sobre o Reddit Agent
  • Lançamentos
    • Notas de Lançamento
  • Lançamentos de 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 Jan, 2025
  • Lançamentos de 2024
    • 27 de Dezembro de 2024
    • 20 de Dezembro de 2024
    • 13 de Dezembro de 2024
    • 6 de Dezembro de 2024
  • 29 de Nov, 2024
  • 22 de Nov, 2024
  • 15 de Nov, 2024
  • 8 de Nov, 2024
  • 1 de Nov, 2024
  • 25 de Out, 2024
  • 18 de Out, 2024
  • 11 de Out, 2024
  • 4 de Out, 2024
  • 27 de Set, 2024
  • 20 de Set, 2024
  • 13 de Set, 2024
  • 16 de Ago, 2024
  • 9 de Ago, 2024
  • 2 de Ago, 2024
  • 26 de Jul, 2024
  • 12 de Jul, 2024
  • 28 de Jun, 2024
  • 14 de Jun, 2024
  • 31 de Maio de 2024
  • 17 de Maio de 2024
  • 10 de Maio 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 Fev, 2024
  • 19 de Fev, 2024
  • 12 de Fev, 2024
  • 5 de Fev, 2024
  • 29 de Jan, 2024
  • 22 de Jan, 2024
  • 15 de Jan, 2024
  • Documentação LLM
    • Documentação LLM Ready do Rememberizer
Powered by GitBook
On this page
  • Introdução
  • Visão Técnica
  • Como Funcionam os Armazenamentos de Vetores
  • Componentes Chave
  • Arquitetura
  • Começando
  • Criando um Armazenamento de Vetores
  • Opções de Configuração
  • Gerenciando Armazenamentos de Vetores
  • Gerenciamento de Chaves de API
  • Criando Chaves de API
  • Revogando Chaves de API
  • Usando a API do Armazenamento Vetorial
  • Exemplos de Código
  • Considerações de Desempenho
  • Otimizando para Diferentes Volumes de Dados
  • Estratégias de Fragmentação
  • Otimização de Consulta
  • Uso Avançado
  • Reindexação
  • Aprimoramento de Consulta
  • Migrando de Outras Bases de Dados Vetoriais
  • Visão Geral da Migração
  • Benefícios da Migração para Rememberizer
  • Migrando do Pinecone
  • Migrando do Qdrant
  • Migrando do Supabase pgvector
  • Melhores Práticas de Migração
  1. Opções de Integração

Armazenamentos de Vetores

Este guia ajudará você a entender como usar o Armazenamento Vetorial Rememberizer como um desenvolvedor.

PreviousIntegração com LangChainNextTalk-to-Slack o Aplicativo Web de Exemplo

Last updated 23 days ago

O Armazenamento de Vetores Rememberizer simplifica o processo de lidar com dados vetoriais, permitindo que você se concentre na entrada de texto e aproveite o poder dos vetores para várias aplicações, como pesquisa e análise de dados.

Introdução

O Rememberizer Vector Store fornece uma interface fácil de usar para lidar com dados vetoriais, enquanto abstrai a complexidade das incorporações vetoriais. Alimentado pelo PostgreSQL com a extensão pgvector, o Rememberizer Vector Store permite que você trabalhe diretamente com texto. O serviço lida com a fragmentação, vetorização e armazenamento dos dados de texto, facilitando para você se concentrar na lógica central de sua aplicação.

Para uma compreensão mais profunda dos conceitos teóricos por trás das incorporações vetoriais e bancos de dados vetoriais, veja .

Visão Técnica

Como Funcionam os Armazenamentos de Vetores

Os Armazenamentos de Vetores Rememberizer convertem texto em representações vetoriais de alta dimensão (embeddings) que capturam o significado semântico. Isso possibilita:

  1. Busca Semântica: Encontrar documentos com base no significado em vez de apenas palavras-chave

  2. Correspondência de Similaridade: Identificar conteúdo conceitualmente relacionado

  3. Recuperação Eficiente: Localizar rapidamente informações relevantes em grandes conjuntos de dados

Componentes Chave

  • Processamento de Documentos: O texto é dividido em pedaços de tamanho otimizado com limites sobrepostos para preservação de contexto

  • Vetorização: Os pedaços são convertidos em embeddings usando modelos de ponta

  • Indexação: Algoritmos especializados organizam vetores para busca de similaridade eficiente

  • Processamento de Consultas: Consultas de busca são vetorizadas e comparadas com embeddings armazenados

Arquitetura

Rememberizer implementa armazenamentos de vetores usando:

  • PostgreSQL com extensão pgvector: Para armazenamento e busca de vetores eficientes

  • Organização baseada em coleções: Cada armazenamento de vetores tem sua própria coleção isolada

  • Acesso orientado a API: Pontos finais RESTful simples para todas as operações

Começando

Criando um Armazenamento de Vetores

  1. Navegue até a Seção de Armazenamentos de Vetores no seu painel

  2. Clique em "Criar novo Armazenamento de Vetores":

    • Um formulário aparecerá solicitando que você insira os detalhes.

  3. Preencha os Detalhes:

    • Nome: Forneça um nome único para o seu armazenamento de vetores.

    • Descrição: Escreva uma breve descrição do armazenamento de vetores.

    • Modelo de Embedding: Selecione o modelo que converte texto em vetores.

    • Algoritmo de Indexação: Escolha como os vetores serão organizados para busca.

    • Métrica de Busca: Defina como a similaridade entre vetores é calculada.

    • Dimensão do Vetor: O tamanho das embeddings de vetores (tipicamente 768-1536).

  4. Envie o Formulário:

    • Clique no botão "Criar". Você receberá uma notificação de sucesso, e o novo armazenamento aparecerá na sua lista de armazenamentos de vetores.

Opções de Configuração

Modelos de Embedding

Modelo
Dimensões
Descrição
Melhor Para

openai/text-embedding-3-large

1536

Modelo de embedding de alta precisão da OpenAI

Aplicações de produção que exigem máxima precisão

openai/text-embedding-3-small

1536

Modelo de embedding menor e mais rápido da OpenAI

Aplicações com requisitos de maior taxa de transferência

Algoritmos de Indexação

Algoritmo
Descrição
Compensações

IVFFLAT (padrão)

Arquivo invertido com compressão plana

Bom equilíbrio entre velocidade e precisão; funciona bem para a maioria dos conjuntos de dados

HNSW

Mundo Pequeno Navegável Hierárquico

Melhor precisão para grandes conjuntos de dados; maiores requisitos de memória

Métricas de Busca

Métrica
Descrição
Melhor Para

cosseno (padrão)

Mede o ângulo entre vetores

Correspondência de similaridade de propósito geral

produto interno (ip)

Produto escalar entre vetores

Quando a magnitude do vetor é importante

L2 (Euclidiana)

Distância em linha reta entre vetores

Quando relações espaciais são importantes

Gerenciando Armazenamentos de Vetores

  1. Visualizar e Editar Armazenamentos de Vetores:

    • Acesse o painel de gerenciamento para visualizar, editar ou excluir armazenamentos de vetores.

  2. Visualizando Documentos:

    • Navegue por documentos individuais e seus metadados associados dentro de um armazenamento de vetores específico.

  3. Estatísticas:

    • Veja estatísticas detalhadas, como o número de vetores armazenados, desempenho de consultas e métricas operacionais.

Gerenciamento de Chaves de API

As chaves de API são usadas para autenticar e autorizar o acesso aos endpoints da API do Rememberizer Vector Store. O gerenciamento adequado das chaves de API é essencial para manter a segurança e a integridade dos seus armazéns de vetores.

Criando Chaves de API

  1. Vá para a página de detalhes do seu Vector Store

  2. Navegue até a Seção de Gerenciamento de Chaves de API:

    • Ela pode ser encontrada na aba "Configuração"

  3. Clique em "Adicionar Chave de API":

    • Um formulário aparecerá solicitando que você insira os detalhes.

  4. Preencha os Detalhes:

    • Nome: Forneça um nome para a chave de API para ajudá-lo a identificar seu caso de uso.

  5. Envie o Formulário:

    • Clique no botão "Criar". A nova chave de API será gerada e exibida. Certifique-se de copiá-la e armazená-la com segurança. Esta chave é usada para autenticar solicitações a esse vetor store específico.

Revogando Chaves de API

Se uma chave de API não for mais necessária, você pode excluí-la para evitar qualquer uso indevido potencial.

Por razões de segurança, você pode querer girar suas chaves de API periodicamente. Isso envolve gerar uma nova chave e revogar a antiga.

Usando a API do Armazenamento Vetorial

Após criar um Armazenamento Vetorial e gerar uma chave de API, você pode interagir com ele usando a API REST.

Exemplos de Código

import requests
import json

API_KEY = "sua_chave_api_aqui"
VECTOR_STORE_ID = "vs_abc123"  # Substitua pelo seu ID de armazenamento de vetores
BASE_URL = "https://api.rememberizer.a

# Carregar um documento para o armazenamento vetorial
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}' carregado com sucesso!")
            return response.json()
        else:
            print(f"Erro ao carregar o documento: {response.text}")
            return None

# Carregar conteúdo de texto para o armazenamento vetorial
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}' carregado com sucesso!")
        return response.json()
    else:
        print(f"Erro ao carregar texto: {response.text}")
        return None

# Pesquisar no armazenamento vetorial
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'])} correspondências para '{query}'")
        
        # Imprimir o melhor resultado
        if results['matched_chunks']:
            top_match = results['matched_chunks'][0]
            print(f"Melhor correspondência (distância: {top_match['distance']}):")
            print(f"Documento: {top_match['document']['name']}")
            print(f"Conteúdo: {top_match['matched_content']}")
        
        return results
    else:
        print(f"Erro ao pesquisar: {response.text}")
        return None

# Exemplo de uso
# upload_document("path/to/document.pdf")
# upload_text("Este é um texto de exemplo para ser vetorizado", "sample-document.txt")
# search_vector_store("Como funciona a similaridade de vetores?")
// Cliente da API do Armazenamento de Vetores
class VectorStoreClient {
  constructor(apiKey, vectorStoreId) {
    this.apiKey = apiKey;
    this.vectorStoreId = vectorStoreId;
    this.baseUrl = 'https://api.rememberizer.ai/api/v1';
  }

  // Obter informações do armazenamento de vetores
  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(`Falha ao obter informações do armazenamento de vetores: ${response.statusText}`);
    }
    
    return response.json();
  }

  // Fazer upload de um 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(`Falha ao fazer upload do documento de texto: ${response.statusText}`);
    }
    
    return response.json();
  }

  // Fazer upload de um arquivo
  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(`Falha ao fazer upload do arquivo: ${xhr.statusText}`));
        }
      };
      
      xhr.onerror = () => {
        reject(new Error('Erro de rede durante o upload do arquivo'));
      };
      
      xhr.send(formData);
    });
  }

  // Pesquisar documentos no armazenamento de vetores
  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(`Falha na pesquisa: ${response.statusText}`);
    }
    
    return response.json();
  }

  // Listar todos os documentos no armazenamento de vetores
  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(`Falha ao listar documentos: ${response.statusText}`);
    }
    
    return response.json();
  }

  // Deletar um 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(`Falha ao deletar documento: ${response.statusText}`);
    }
    
    return true;
  }
}

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

// Pesquisar documentos
client.searchDocuments('Como funciona a pesquisa semântica?')
  .then(results => {
    console.log(`Encontrados ${results.matched_chunks.length} correspondências`);
    results.matched_chunks.forEach(match => {
      console.log(`Documento: ${match.document.name}`);
      console.log(`Pontuação: ${match.distance}`);
      console.log(`Conteúdo: ${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

  # Obter detalhes do armazenamento de vetores
  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

  # Fazer upload de conteúdo 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

  # Pesquisar 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

  # Fazer upload de arquivo (formulário 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 "A solicitação da API falhou: #{response.code} #{response.message}\n#{response.body}"
    end
    
    response
  end
end

Exemplo de uso

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

Pesquisar documentos

results = client.search('Quais são as melhores práticas para segurança de dados?') puts "Encontrados #{results['matched_chunks'].length} resultados"

Exibir o melhor resultado

if results['matched_chunks'].any? top_match = results['matched_chunks'].first puts "Melhor correspondência (distância: #{top_match['distance']}):" puts "Documento: #{top_match['document']['name']}" puts "Conteúdo: #{top_match['matched_content']}" end =end


</div>

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

```bash
# Defina sua chave de API e ID do Armazenamento Vetorial
API_KEY="your_api_key_here"
VECTOR_STORE_ID="vs_abc123"
BASE_URL="https://api.rememberizer.ai/api/v1"

# Obter informações do armazenamento de vetores
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}" \
  -H "x-api-key: ${API_KEY}"

# Carregar um 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 é um documento de exemplo que será vetorizado e armazenado no banco de dados vetorial para busca semântica."
  }'

# Carregar um arquivo
curl -X POST "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents" \
  -H "x-api-key: ${API_KEY}" \
  -F "file=@/caminho/para/seu/documento.pdf"

# Pesquisar 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 os documentos
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents" \
  -H "x-api-key: ${API_KEY}"

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

Considerações de Desempenho

Em breve: Diagrama de Arquitetura do Armazenamento Vetorial

Este diagrama de arquitetura técnica ilustrará:

  • A arquitetura de fundação PostgreSQL + pgvector

  • Estruturas de algoritmos de indexação (IVFFLAT vs. HNSW)

  • Como as métricas de busca funcionam no espaço vetorial (comparação visual)

  • Processo de fragmentação de documentos com visualização de sobreposição

  • Considerações de desempenho visualizadas em diferentes escalas

Otimizando para Diferentes Volumes de Dados

Volume de Dados
Configuração Recomendada
Notas

Pequeno (<10k documentos)

IVFFLAT, similaridade cosseno

Configuração simples proporciona bom desempenho

Médio (10k-100k documentos)

IVFFLAT, garantir reindexação regular

Equilíbrio entre velocidade de busca e manutenção do índice

Grande (>100k documentos)

HNSW, considerar aumentar as dimensões do vetor

Maior uso de memória, mas mantém desempenho em escala

Estratégias de Fragmentação

O processo de fragmentação impacta significativamente a qualidade da busca:

  • Tamanho do Fragmento: Rememberizer utiliza um tamanho de fragmento padrão de 1024 bytes com uma sobreposição de 200 bytes

  • Fragmentos Menores (512-1024 bytes): Correspondências mais precisas, melhores para perguntas específicas

  • Fragmentos Maiores (1500-2048 bytes): Mais contexto em cada correspondência, melhores para tópicos mais amplos

  • Sobreposição: Garante que o contexto não seja perdido nas fronteiras dos fragmentos

Otimização de Consulta

  • Janelas de Contexto: Use prev_chunks e next_chunks para recuperar conteúdo ao redor

  • Contagem de Resultados: Comece com 3-5 resultados (n parameter) e ajuste com base nas necessidades de precisão

  • Limite: Ajuste o parâmetro t para filtrar resultados por pontuação de similaridade

Uso Avançado

Reindexação

Rememberizer aciona automaticamente a reindexação quando a contagem de vetores excede os limites predefinidos, mas considere a reindexação manual após:

  • Carregar um grande número de documentos

  • Alterar o modelo de incorporação

  • Modificar o algoritmo de indexação

Aprimoramento de Consulta

Para melhores resultados de busca:

  1. Seja específico nas consultas de busca

  2. Inclua contexto quando possível

  3. Use linguagem natural em vez de palavras-chave

  4. Ajuste parâmetros com base na qualidade do resultado

Migrando de Outras Bases de Dados Vetoriais

Se você está atualmente usando outras soluções de banco de dados vetoriais e deseja migrar para o Rememberizer Vector Store, os seguintes guias o ajudarão a transitar seus dados de forma eficiente.

Visão Geral da Migração

Migrar dados vetoriais envolve:

  1. Exportar dados do seu banco de dados vetorial de origem

  2. Converter os dados para um formato compatível com o Rememberizer

  3. Importar os dados para o seu Armazenamento Vetorial Rememberizer

  4. Verificar se a migração foi bem-sucedida

Benefícios da Migração para Rememberizer

  • Fundação PostgreSQL: Construído sobre tecnologia de banco de dados madura com backup e recuperação integrados

  • Ecossistema Integrado: Conexão perfeita com outros componentes do Rememberizer

  • Gerenciamento Simplificado: Interface unificada para operações vetoriais

  • Segurança Avançada: Segurança em nível de linha e controles de acesso granulares

  • Arquitetura Escalável: Otimização de desempenho à medida que seus dados crescem

Migrando do Pinecone

import os
import pinecone
import requests
import json
import time

# Configurar cliente Pinecone
pinecone.init(api_key="PINECONE_API_KEY", environment="PINECONE_ENV")
source_index = pinecone.Index("seu-indice-pinecone")

# Configurar cliente do Armazenamento Vetorial Rememberizer
REMEMBERIZER_API_KEY = "your_rememberizer_api_key"
VECTOR_STORE_ID = "vs_abc123"  # Seu ID de armazenamento vetorial Rememberizer
BASE_URL = "https://api.rememberizer.ai/api/v1"

# 1. Defina o tamanho do lote para migração (ajuste com base no tamanho dos seus dados)
BATCH_SIZE = 100

# 2. Função para obter vetores do Pinecone
def fetch_vectors_from_pinecone(index_name, batch_size, cursor=None):
    # Use a operação de lista se disponível na sua versão do 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 versões mais antigas do Pinecone sem operação de lista
        # Esta é uma abordagem simplificada; a implementação real depende do seu padrão de acesso a dados
        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. Função para enviar vetores para 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():
        # Converter dados do vetor Pinecone para o 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"Pulando {vector_id} - nenhum conteúdo de texto encontrado nos metadados")
            continue
            
        data = {
            "name": document_name,
            "content": content,
            # Opcional: incluir metadados adicionais
            "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}' enviado com sucesso!")
        else:
            print(f"Erro ao enviar o documento {document_name}: {response.text}")
        
        # Adicionar um pequeno atraso para evitar limitação de taxa
        time.sleep(0.1)

# 4. Função principal de migração
def migrate_pinecone_to_rememberizer():
    cursor = None
    total_migrated = 0
    
    print("Iniciando a migração do Pinecone para o Rememberizer...")
    
    while True:
        vectors, cursor = fetch_vectors_from_pinecone("your-pinecone-index", BATCH_SIZE, cursor)
        
        if not vectors:
            break
            
        print(f"Buscou {len(vectors)} vetores do Pinecone")
        upload_to_rememberizer(vectors)
        
        total_migrated += len(vectors)
        print(f"Progresso: {total_migrated} vetores migrados")
        
        if not cursor:
            break
    
    print(f"Migração completa! {total_migrated} vetores migrados para o Rememberizer")

# Execute a migração
# migrate_pinecone_to_rememberizer()
const { PineconeClient } = require('@pinecone-database/pinecone');
const axios = require('axios');

// Configuração do Pinecone
const pineconeApiKey = 'PINECONE_API_KEY';
const pineconeEnvironment = 'PINECONE_ENVIRONMENT';
const pineconeIndexName = 'YOUR_PINECONE_INDEX';

// Configuração do Rememberizer
const rememberizerApiKey = 'YOUR_REMEMBERIZER_API_KEY';
const vectorStoreId = 'vs_abc123';
const baseUrl = 'https://api.rememberizer.ai/api/v1';

// Configuração do tamanho do lote
const BATCH_SIZE = 100;

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

// Buscar vetores do Pinecone
async function fetchVectorsFromPinecone(pinecone, batchSize, paginationToken = null) {
  const index = pinecone.Index(pineconeIndexName);
  
  try {
    // Para versões mais novas do Pinecone
    const listResponse = await index.list({
      limit: batchSize,
      paginationToken: paginationToken
    });
    
    return {
      vectors: listResponse.vectors || {},
      nextToken: listResponse.paginationToken
    };
  } catch (error) {
    // Fallback para versões mais antigas do Pinecone
    // Isso é simplificado; a implementação real depende do seu padrão de acesso a dados
    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 };
  }
}

// Fazer upload de vetores para o 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(`Ignorando ${vectorId} - nenhum conteúdo de texto encontrado nos metadados`);
      continue;
    }
    
    const data = {
      name: documentName,
      content: content,
      // Opcional: incluir metadados adicionais
      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}' enviado com sucesso!`);
        results.push({ id: vectorId, success: true });
      } else {
        console.error(`Erro ao enviar documento ${documentName}: ${response.statusText}`);
        results.push({ id: vectorId, success: false, error: response.statusText });
      }
    } catch (error) {
      console.error(`Erro ao enviar documento ${documentName}: ${error.message}`);
      results.push({ id: vectorId, success: false, error: error.message });
    }
    
    // Adicionar um pequeno atraso para evitar limitação de taxa
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  return results;
}

// Função principal de migração
async function migratePineconeToRememberizer() {
  try {
    console.log('Iniciando a migração do Pinecone para o 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(`Buscou ${Object.keys(vectors).length} vetores do Pinecone`);
      
      const results = await uploadToRememberizer(vectors);
      const successCount = results.filter(r => r.success).length;
      
      totalMigrated += successCount;
      console.log(`Progresso: ${totalMigrated} vetores migrados com sucesso`);
      
    } while (nextToken);
    
    console.log(`Migração completa! ${totalMigrated} vetores migrados para o Rememberizer`);
    
  } catch (error) {
    console.error('Migração falhou:', error);
  }
}

// Executar a migração
// migratePineconeToRememberizer();

Migrando do 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"  # ou sua URL da nuvem Qdrant
QDRANT_API_KEY = "your_qdrant_api_key"  # se estiver usando a nuvem Qdrant
QDRANT_COLLECTION_NAME = "sua_colecao"

qdrant_client = QdrantClient(
    url=QDRANT_URL,
    api_key=QDRANT_API_KEY  # Apenas para a nuvem Qdrant
)

# Configurar cliente do Armazenamento Vetorial Rememberizer
REMEMBERIZER_API_KEY = "your_rememberizer_api_key"
VECTOR_STORE_ID = "vs_abc123"  # Seu ID de armazenamento vetorial Rememberizer
BASE_URL = "https://api.rememberizer.ai/api/v1"

# Tamanho do lote para processamento
BATCH_SIZE = 100

# Função para buscar pontos do Qdrant
def fetch_points_from_qdrant(collection_name, batch_size, offset=0):
    try:
        # Obter informações da coleção para determinar a dimensão do vetor
        collection_info = qdrant_client.get_collection(collection_name=collection_name)
        
        # Rolagem através dos pontos
        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 (pontos, próximo_offset)
        next_offset = scroll_result[1]
        
        return points, next_offset
    except Exception as e:
        print(f"Erro ao buscar pontos do Qdrant: {e}")
        return [], None

# Função para enviar vetores para Rememberizer
def upload_to_rememberizer(points):
    headers = {
        "x-api-key": REMEMBERIZER_API_KEY,
        "Content-Type": "application/json"
    }
    
    results = []
    
    for point in points:
        # Extrair dados do ponto 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"Pulando {point_id} - nenhum conteúdo de texto encontrado na carga útil")
            continue
            
        data = {
            "name": document_name,
            "content": text_content,
            # Opcional: incluir metadados adicionais
            "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}' enviado com sucesso!")
                results.append({"id": point_id, "success": True})
            else:
                print(f"Erro ao enviar o documento {document_name}: {response.text}")
                results.append({"id": point_id, "success": False, "error": response.text})
        except Exception as e:
            print(f"Exceção ao enviar o documento {document_name}: {str(e)}")
            results.append({"id": point_id, "success": False, "error": str(e)})
        
        # Adicionar um pequeno atraso para evitar limitação de taxa
        time.sleep(0.1)
    
    return results

# Função principal de migração
def migrate_qdrant_to_rememberizer():
    offset = None
    total_migrated = 0
    
    print("Iniciando a migração do Qdrant para o Rememberizer...")
    
    while True:
        points, next_offset = fetch_points_from_qdrant(
            QDRANT_COLLECTION_NAME, 
            BATCH_SIZE,
            offset
        )
        
        if not points:
            break
            
        print(f"Buscou {len(points)} pontos do 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} pontos migrados com sucesso")
        
        if next_offset is None:
            break
            
        offset = next_offset
    
    print(f"Migração completa! {total_migrated} pontos totais migrados para o Rememberizer")

# Execute a migração
# migrate_qdrant_to_rememberizer()
const { QdrantClient } = require('@qdrant/js-client-rest');
const axios = require('axios');

// Configuração do Qdrant
const qdrantUrl = 'http://localhost:6333'; // ou sua URL da nuvem Qdrant
const qdrantApiKey = 'your_qdrant_api_key'; // se estiver usando a nuvem Qdrant
const qdrantCollectionName = 'sua_colecao';

// Configuração do Rememberizer
const rememberizerApiKey = 'YOUR_REMEMBERIZER_API_KEY';
const vectorStoreId = 'vs_abc123';
const baseUrl = 'https://api.rememberizer.ai/api/v1';

// Configuração do tamanho do lote
const BATCH_SIZE = 100;

// Inicializa o cliente Qdrant
const qdrantClient = new QdrantClient({ 
  url: qdrantUrl,
  apiKey: qdrantApiKey // Apenas para a nuvem Qdrant
});

// Busca pontos do Qdrant
async function fetchPointsFromQdrant(collectionName, batchSize, offset = 0) {
  try {
    // Obtém informações da coleção
    const collectionInfo = await qdrantClient.getCollection(collectionName);
    
    // Rola pelos pontos
    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(`Erro ao buscar pontos do Qdrant: ${error.message}`);
    return { points: [], nextOffset: null };
  }
}

// Envia vetores para o Rememberizer
async function uploadToRememberizer(points) {
  const headers = {
    'x-api-key': rememberizerApiKey,
    'Content-Type': 'application/json'
  };
  
  const results = [];
  
  for (const point of points) {
    // Extrai dados do ponto do Qdrant
    const pointId = point.id;
    const metadata = point.payload || {};
    const textContent = metadata.text || '';
    const documentName = metadata.filename || `qdrant_doc_${pointId}`;
    
    if (!textContent) {
      console.log(`Ignorando ${pointId} - nenhum conteúdo de texto encontrado na carga útil`);
      continue;
    }
    
    const data = {
      name: documentName,
      content: textContent,
      // Opcional: incluir metadados adicionais
      metadata: metadata
    };
    
    try {
      const response = await axios.post(
        `${baseUrl}/vector-stores/${vectorStoreId}/documents/text`,
        data,
        { headers }
      );
      
      if (response.status === 201) {
        console.log(`Documento '${documentName}' enviado com sucesso!`);
        results.push({ id: pointId, success: true });
      } else {
        console.error(`Erro ao enviar documento ${documentName}: ${response.statusText}`);
        results.push({ id: pointId, success: false, error: response.statusText });
      }
    } catch (error) {
      console.error(`Erro ao enviar documento ${documentName}: ${error.message}`);
      results.push({ id: pointId, success: false, error: error.message });
    }
    
    // Adiciona um pequeno atraso para evitar limitação de taxa
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  return results;
}

// Função principal de migração
async function migrateQdrantToRememberizer() {
  try {
    console.log('Iniciando migração do Qdrant para o 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(`Buscou ${points.length} pontos do Qdrant`);
      
      const results = await uploadToRememberizer(points);
      const successCount = results.filter(r => r.success).length;
      
      totalMigrated += successCount;
      console.log(`Progresso: ${totalMigrated} pontos migrados com sucesso`);
      
    } while (offset !== null);
    
    console.log(`Migração completa! ${totalMigrated} pontos totais migrados para o Rememberizer`);
    
  } catch (error) {
    console.error('Migração falhou:', error);
  }
}

// Executa a migração
// migrateQdrantToRememberizer();

Migrando do Supabase pgvector

Se você já está usando o Supabase com pgvector, a migração para o Rememberizer é particularmente simples, uma vez que ambos usam PostgreSQL com a extensão pgvector.

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

# Carregar variáveis de ambiente
load_dotenv()

# Configuração do PostgreSQL do 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")

# Configuração do Rememberizer
REMEMBERIZER_API_KEY = os.getenv("REMEMBERIZER_API_KEY")
VECTOR_STORE_ID = os.getenv("VECTOR_STORE_ID")  # por exemplo, "vs_abc123"
BASE_URL = "https://api.rememberizer.ai/api/v1"

# Tamanho do lote para processamento
BATCH_SIZE = 100

# Conectar ao 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"Erro ao conectar ao Supabase PostgreSQL: {e}")
        return None

# Buscar documentos do Supabase pgvector
def fetch_documents_from_supabase(conn, batch_size, offset=0):
    try:
        cursor = conn.cursor()
        
        # Ajuste esta consulta com base na estrutura da sua tabela
        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"Erro ao buscar documentos do Supabase: {e}")
        return []

# Carregar documentos para o 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
        
        # Analisar metadados se estiver armazenado como string 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"Pulando {doc_id} - nenhum conteúdo encontrado")
            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}' carregado com sucesso!")
                results.append({"id": doc_id, "success": True})
            else:
                print(f"Erro ao carregar o documento {document_name}: {response.text}")
                results.append({"id": doc_id, "success": False, "error": response.text})
        except Exception as e:
            print(f"Exceção ao carregar o documento {document_name}: {str(e)}")
            results.append({"id": doc_id, "success": False, "error": str(e)})
        
        # Adicionar um pequeno atraso para evitar limitação de taxa
        time.sleep(0.1)
    
    return results

# Função principal de migração
def migrate_supabase_to_rememberizer():
    conn = connect_to_supabase()
    if not conn:
        print("Falha ao conectar ao Supabase. Abortando a migração.")
        return
    
    offset = 0
    total_migrated = 0
    
    print("Iniciando a migração do pgvector do Supabase para o Rememberizer...")
    
    try:
        while True:
            documents = fetch_documents_from_supabase(conn, BATCH_SIZE, offset)
            
            if not documents:
                break
                
            print(f"Buscou {len(documents)} documentos do 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} documentos migrados com sucesso")
            
            offset += BATCH_SIZE
            
    finally:
        conn.close()
    
    print(f"Migração completa! {total_migrated} documentos migrados para o Rememberizer")

# Execute a migração
# migrate_supabase_to_rememberizer()
const { Pool } = require('pg');
const axios = require('axios');
require('dotenv').config();

// Configuração do PostgreSQL do 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';

// Configuração do 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';

// Configuração do tamanho do lote
const BATCH_SIZE = 100;

// Buscar documentos do Supabase pgvector
async function fetchDocumentsFromSupabase(batchSize, offset = 0) {
  try {
    // Ajuste esta consulta com base na estrutura da sua tabela
    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(`Erro ao buscar documentos do Supabase: ${error.message}`);
    return [];
  }
}

// Fazer upload de documentos para o Rememberizer
async function uploadToRememberizer(documents) {
  const headers = {
    'x-api-key': rememberizerApiKey,
    'Content-Type': 'application/json'
  };
  
  const results = [];
  
  for (const doc of documents) {
    // Analisar metadata se estiver armazenado como string 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(`Ignorando ${doc.id} - nenhum conteúdo encontrado`);
      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}' enviado com sucesso!`);
        results.push({ id: doc.id, success: true });
      } else {
        console.error(`Erro ao enviar documento ${documentName}: ${response.statusText}`);
        results.push({ id: doc.id, success: false, error: response.statusText });
      }
    } catch (error) {
      console.error(`Erro ao enviar documento ${documentName}: ${error.message}`);
      results.push({ id: doc.id, success: false, error: error.message });
    }
    
    // Adicionar um pequeno atraso para evitar limitação de taxa
    await new Promise(resolve => setTimeout(resolve, 100));
  }
  
  return results;
}

// Função principal de migração
async function migrateSupabaseToRememberizer() {
  try {
    console.log('Iniciando a migração do Supabase pgvector para o Rememberizer...');
    
    let offset = 0;
    let totalMigrated = 0;
    
    while (true) {
      const documents = await fetchDocumentsFromSupabase(BATCH_SIZE, offset);
      
      if (documents.length === 0) {
        break;
      }
      
      console.log(`Buscou ${documents.length} documentos do Supabase`);
      
      const results = await uploadToRememberizer(documents);
      const successCount = results.filter(r => r.success).length;
      
      totalMigrated += successCount;
      console.log(`Progresso: ${totalMigrated} documentos migrados com sucesso`);
      
      offset += BATCH_SIZE;
    }
    
    console.log(`Migração completa! ${totalMigrated} documentos migrados para o Rememberizer`);
    
  } catch (error) {
    console.error('Migração falhou:', error);
  } finally {
    await supabasePool.end();
  }
}

// Executar a migração
// migrateSupabaseToRememberizer();

Melhores Práticas de Migração

Siga estas recomendações para uma migração bem-sucedida:

  1. Planeje com Antecedência:

    • Estime o volume de dados e o tempo necessário para a migração

    • Programe a migração durante períodos de baixo tráfego

    • Aumente o espaço em disco antes de iniciar grandes migrações

  2. Teste Primeiro:

    • Crie um vetor de teste no Rememberizer

    • Migre um pequeno subconjunto de dados (100-1000 vetores)

    • Verifique a funcionalidade de busca com consultas-chave

  3. Validação de Dados:

    • Compare a contagem de documentos antes e depois da migração

    • Execute consultas de benchmark para garantir resultados semelhantes

    • Valide se os metadados estão corretamente preservados

  4. Otimize para Desempenho:

    • Use operações em lote para eficiência

    • Considere a colocação geográfica dos bancos de dados de origem e destino

    • Monitore os limites de taxa da API e ajuste os tamanhos dos lotes conforme necessário

  5. Etapas Pós-Migração:

    • Verifique a criação do índice no Rememberizer

    • Atualize as configurações do aplicativo para apontar para o novo vetor de armazenamento

    • Mantenha o banco de dados de origem como backup até que a migração seja verificada

Para referência detalhada da API e documentação de endpoints, visite a página Documentação do Armazenamento Vetorial.


Certifique-se de manusear as chaves da API de forma segura e siga as melhores práticas para gerenciamento de chaves da API.

O que são Incorporações Vetoriais e Bancos de Dados Vetoriais?
Criar um Novo Armazenamento de Vetores
Ver Detalhes de um Armazenamento de Vetores
Criar uma Nova Chave de API
Criar um Novo Armazenamento de Vetores
Ver Detalhes de um Armazenamento de Vetores
Criar uma Nova Chave de API