Vektorbutikker¶
Rememberizer Vektorbutik forenkler processen med at håndtere vektordata, så du kan fokusere på tekstinput og udnytte kraften i vektorer til forskellige applikationer såsom søgning og dataanalyse.
Introduktion¶
Rememberizer Vector Store tilbyder en brugervenlig grænseflade til håndtering af vektordata, mens kompleksiteten ved vektorindlejringer abstraheres. Drevet af PostgreSQL med pgvector-udvidelsen, giver Rememberizer Vector Store dig mulighed for at arbejde direkte med tekst. Tjenesten håndterer opdeling, vektorisering og lagring af tekstdata, hvilket gør det lettere for dig at fokusere på din kerneapplikationslogik.
For en dybere forståelse af de teoretiske koncepter bag vektorindlejringer og vektordatabaser, se Hvad er vektorindlejringer og vektordatabaser?.
Teknisk Oversigt¶
Hvordan Vektorbutikker Fungerer¶
Rememberizer Vektorbutikker konverterer tekst til højdimensionale vektorrepræsentationer (indlejring), der fanger semantisk betydning. Dette muliggør:
- Semantisk Søgning: Find dokumenter baseret på betydning snarere end blot nøgleord
- Ligheds Matching: Identificer konceptuelt relateret indhold
- Effektiv Hentning: Hurtigt finde relevant information fra store datasæt
Nøglekomponenter¶
- Dokumentbehandling: Teksten opdeles i optimalt størrelsesdelte bidder med overlappende grænser for at bevare konteksten
- Vektorisering: Bidder konverteres til indlejringer ved hjælp af state-of-the-art modeller
- Indeksering: Specialiserede algoritmer organiserer vektorer til effektiv lighedssøgning
- Forespørgselsbehandling: Søgeforespørgsler vektorisers og sammenlignes med gemte indlejringer
Arkitektur¶
Rememberizer implementerer vektorbutikker ved hjælp af:
- PostgreSQL med pgvector-udvidelse: Til effektiv vektoropbevaring og søgning
- Samling-baseret organisering: Hver vektorbutik har sin egen isolerede samling
- API-drevet adgang: Enkle RESTful slutpunkter til alle operationer
Kom godt i gang¶
Oprettelse af en Vektorbutik¶
- Naviger til sektionen for Vektorbutikker i dit dashboard
- Klik på "Opret ny Vektorbutik":
- En formular vises, der beder dig om at indtaste oplysninger.
- Udfyld oplysningerne:
- Navn: Angiv et unikt navn til din vektorbutik.
- Beskrivelse: Skriv en kort beskrivelse af vektorbutikken.
- Indlejringsmodel: Vælg den model, der konverterer tekst til vektorer.
- Indekseringsalgoritme: Vælg, hvordan vektorer vil blive organiseret til søgning.
- Søgemetrik: Definer, hvordan lighed mellem vektorer beregnes.
- Vektordimension: Størrelsen på vektorindlejringerne (typisk 768-1536).
- Indsend formularen:
- Klik på "Opret" knappen. Du vil modtage en succesmeddelelse, og den nye butik vil vises i din liste over vektorbutikker.

Opret en ny vektorbutik
Konfigurationsmuligheder¶
Indlejringsmodeller¶
| Model | Dimensioner | Beskrivelse | Bedst til |
|---|---|---|---|
| openai/text-embedding-3-large | 1536 | Højpræcisions indlejringsmodel fra OpenAI | Produktionsapplikationer, der kræver maksimal nøjagtighed |
| openai/text-embedding-3-small | 1536 | Mindre, hurtigere indlejringsmodel fra OpenAI | Applikationer med højere gennemstrømningskrav |
Indekseringsalgoritmer¶
| Algoritme | Beskrivelse | Afvejninger |
|---|---|---|
| IVFFLAT (standard) | Inverteret fil med flad kompression | God balance mellem hastighed og nøjagtighed; fungerer godt for de fleste datasæt |
| HNSW | Hierarkisk Navigerbar Lille Verden | Bedre nøjagtighed for store datasæt; højere hukommelseskrav |
Søgemetrikker¶
| Metode | Beskrivelse | Bedst til |
|---|---|---|
| cosine (standard) | Måler vinklen mellem vektorer | Generel formål lighedsmatch |
| indre produkt (ip) | Punktprodukt mellem vektorer | Når vektormagnituden er vigtig |
| L2 (Euclidean) | Lige afstand mellem vektorer | Når rumlige forhold betyder noget |
Håndtering af Vektorbutikker¶
- Vis og Rediger Vektorbutikker:
- Få adgang til administrationsdashboardet for at se, redigere eller slette vektorbutikker.
- Visning af Dokumenter:
- Gennemse individuelle dokumenter og deres tilknyttede metadata inden for en specifik vektorbutik.
- Statistik:
- Se detaljerede statistikker såsom antallet af gemte vektorer, forespørgselsydelse og driftsmålinger.

Vis Detaljer om en Vektorbutik
API Nøglehåndtering¶
API-nøgler bruges til at autentificere og autorisere adgang til Rememberizer Vector Store's API-endepunkter. Korrekt håndtering af API-nøgler er afgørende for at opretholde sikkerheden og integriteten af dine vektorlager.
Oprettelse af API-nøgler¶
- Gå til din Vector Store detaljer side
- Naviger til sektionen for API-nøgleadministration:
- Den kan findes under fanen "Konfiguration"
- Klik på "Tilføj API-nøgle":
- En formular vises, der beder dig om at indtaste oplysninger.
- Udfyld oplysningerne:
- Navn: Angiv et navn til API-nøglen for at hjælpe dig med at identificere dens anvendelsestilfælde.
- Indsend formularen:
- Klik på "Opret" knappen. Den nye API-nøgle vil blive genereret og vist. Sørg for at kopiere og opbevare den sikkert. Denne nøgle bruges til at godkende anmodninger til den specifikke vector store.

Opret en ny API-nøgle
Tilbagetrækning af API-nøgler¶
Hvis en API-nøgle ikke længere er nødvendig, kan du slette den for at forhindre potentiel misbrug.
Af sikkerhedsmæssige årsager kan du overveje at rotere dine API-nøgler periodisk. Dette indebærer at generere en ny nøgle og tilbagetrække den gamle.
Brug af Vector Store API¶
Efter at have oprettet en Vector Store og genereret en API-nøgle, kan du interagere med den ved hjælp af REST API'en.
Kodeeksempler¶
import requests
import json
API_KEY = "your_api_key_here"
VECTOR_STORE_ID = "vs_abc123" # Erstat med dit vector store ID
BASE_URL = "https://api.rememberizer.a
# Upload et dokument til vektorbutikken
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"Dokument '{document_name}' uploadet med succes!")
return response.json()
else:
print(f"Fejl ved upload af dokument: {response.text}")
return None
# Upload tekstindhold til vektorbutikken
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"Tekstdokument '{document_name}' uploadet med succes!")
return response.json()
else:
print(f"Fejl ved upload af tekst: {response.text}")
return None
# Søg i vektorbutikken
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"Fundet {len(results['matched_chunks'])} match for '{query}'")
# Udskriv det bedste resultat
if results['matched_chunks']:
top_match = results['matched_chunks'][0]
print(f"Bedste match (afstand: {top_match['distance']}):")
print(f"Dokument: {top_match['document']['name']}")
print(f"Indhold: {top_match['matched_content']}")
return results
else:
print(f"Fejl ved søgning: {response.text}")
return None
# Eksempel på brug
# upload_document("path/to/document.pdf")
# upload_text("Dette er en prøve tekst, der skal vektorisere", "sample-document.txt")
# search_vector_store("Hvordan fungerer vektorsimilaritet?")
// Vektorbutik API-klient
class VectorStoreClient {
constructor(apiKey, vectorStoreId) {
this.apiKey = apiKey;
this.vectorStoreId = vectorStoreId;
this.baseUrl = 'https://api.rememberizer.ai/api/v1';
}
// Hent information om vektorbutikken
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(`Mislykkedes med at hente information om vektorbutikken: ${response.statusText}`);
}
return response.json();
}
// Upload et tekstdokument
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(`Mislykkedes med at uploade tekstdokument: ${response.statusText}`);
}
return response.json();
}
// Upload en fil
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(`Mislykkedes med at uploade fil: ${xhr.statusText}`));
}
};
xhr.onerror = () => {
reject(new Error('Netværksfejl under filupload'));
};
xhr.send(formData);
});
}
// Søg dokumenter i vektorbutikken
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(`Søgning mislykkedes: ${response.statusText}`);
}
return response.json();
}
// Liste alle dokumenter i vektorbutikken
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(`Mislykkedes med at liste dokumenter: ${response.statusText}`);
}
return response.json();
}
// Slet et dokument
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(`Mislykkedes med at slette dokument: ${response.statusText}`);
}
return true;
}
}
// Eksempel på brug
/*
const client = new VectorStoreClient('your_api_key', 'vs_abc123');
// Søg dokumenter
client.searchDocuments('Hvordan fungerer semantisk søgning?')
.then(results => {
console.log(`Fundet ${results.matched_chunks.length} matches`);
results.matched_chunks.forEach(match => {
console.log(`Dokument: ${match.document.name}`);
console.log(`Score: ${match.distance}`);
console.log(`Indhold: ${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
# Hent detaljer om vektorbutikken
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
# Upload tekstindhold
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
# Søg dokumenter
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
# Liste dokumenter
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
# Upload fil (multipart form)
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 "API-anmodning mislykkedes: #{response.code} #{response.message}\n#{response.body}"
end
response
end
end
Eksempel på brug¶
=begin client = VectorStoreClient.new('your_api_key', 'vs_abc123')
Søg efter dokumenter¶
results = client.search('Hvad er de bedste praksisser for datasikkerhed?') puts "Fundet #{results['matched_chunks'].length} resultater"
Vis top resultat¶
if results['matched_chunks'].any? top_match = results['matched_chunks'].first puts "Top match (afstand: #{top_match['distance']}):" puts "Dokument: #{top_match['document']['name']}" puts "Indhold: #{top_match['matched_content']}" end =end ```
# Indstil din API-nøgle og Vector Store ID
API_KEY="your_api_key_here"
VECTOR_STORE_ID="vs_abc123"
BASE_URL="https://api.rememberizer.ai/api/v1"
# Få vektorlagerinformation
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}"
-H "x-api-key: ${API_KEY}"
# Upload et tekstdokument
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": "Dette er et eksempel på et dokument, der vil blive vektorisert og gemt i vektordatabasen til semantisk søgning."
}'
# Upload en fil
curl -X POST "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents"
-H "x-api-key: ${API_KEY}"
-F "file=@/path/to/your/document.pdf"
# Søg efter dokumenter
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}"
# Liste alle dokumenter
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents"
-H "x-api-key: ${API_KEY}"
# Slet et dokument
curl -X DELETE "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents/123"
-H "x-api-key: ${API_KEY}"
Ydelsesovervejelser¶
Kommer snart: Vektorbutik Arkitekturdiagram
Dette tekniske arkitekturdiagram vil illustrere:
- PostgreSQL + pgvector fundamentarkitektur
- Indekseringsalgoritmestrukturer (IVFFLAT vs. HNSW)
- Hvordan søgemetrikker fungerer i vektorrum (visuel sammenligning)
- Dokumentchunking-proces med overlapvisualisering
- Ydelsesovervejelser visualiseret på tværs af forskellige skalaer
Optimering for Forskellige Datavolumener¶
| Datavolumen | Anbefalet Konfiguration | Noter |
|---|---|---|
| Lille (<10k dokumenter) | IVFFLAT, cosinuslighed | Enkel konfiguration giver god ydeevne |
| Medium (10k-100k dokumenter) | IVFFLAT, sørg for regelmæssig reindeksering | Balance mellem søgehastighed og indeksvedligeholdelse |
| Stor (>100k dokumenter) | HNSW, overvej at øge vektordimensioner | Højere hukommelsesforbrug, men opretholder ydeevne i stor skala |
Chunking Strategier¶
Chunking-processen påvirker søgekvaliteten betydeligt:
- Chunk Størrelse: Rememberizer bruger en standard chunk størrelse på 1024 bytes med en overlapning på 200 bytes
- Mindre Chunks (512-1024 bytes): Mere præcise matches, bedre til specifikke spørgsmål
- Større Chunks (1500-2048 bytes): Mere kontekst i hvert match, bedre til bredere emner
- Overlapning: Sikrer at konteksten ikke går tabt ved chunk-grænser
Forespørgselsoptimering¶
- Kontekstvinduer: Brug
prev_chunksognext_chunkstil at hente omgivende indhold - Resultatantal: Start med 3-5 resultater (
nparameter) og juster baseret på præcisionsbehov - Tærskel: Juster
tparameteren for at filtrere resultater efter lighedsscore
Avanceret brug¶
Reindeksering¶
Rememberizer udløser automatisk reindeksering, når vektortællinger overstiger foruddefinerede tærskler, men overvej manuel reindeksering efter:
- Upload af et stort antal dokumenter
- Ændring af indlejringsmodellen
- Modifikation af indekseringsalgoritmen
Spørgsmål Forbedring¶
For bedre søgeresultater:
- Vær specifik i søgespørgsmål
- Inkluder kontekst når det er muligt
- Brug naturligt sprog frem for nøgleord
- Justér parametre baseret på resultatkvalitet
Migration fra Andre Vektordatabaser¶
Hvis du i øjeblikket bruger andre vektordatabase-løsninger og ønsker at migrere til Rememberizer Vector Store, vil de følgende vejledninger hjælpe dig med at overføre dine data effektivt.
Migrering Oversigt¶
Migrering af vektordata involverer: 1. Eksportering af data fra din kildevektordatabase 2. Konvertering af data til et format, der er kompatibelt med Rememberizer 3. Importering af data til din Rememberizer Vektorbutik 4. Verificering af, at migreringen var vellykket
Fordele ved at migrere til Rememberizer¶
- PostgreSQL Foundation: Bygget på moden databasteknologi med indbygget backup og gendannelse
- Integreret Økosystem: Problemfri forbindelse med andre Rememberizer-komponenter
- Forenklet Administration: Unified interface til vektoroperationer
- Avanceret Sikkerhed: Sikkerhed på række-niveau og detaljerede adgangskontroller
- Skalerbar Arkitektur: Ydelsesoptimering efterhånden som dine data vokser
Migrering fra Pinecone¶
import os
import pinecone
import requests
import json
import time
# Opsæt Pinecone-klient
pinecone.init(api_key="PINECONE_API_KEY", environment="PINECONE_ENV")
source_index = pinecone.Index("your-pinecone-index")
# Opsæt Rememberizer Vector Store-klient
REMEMBERIZER_API_KEY = "your_rememberizer_api_key"
VECTOR_STORE_ID = "vs_abc123" # Dit Rememberizer vector store ID
BASE_URL = "https://api.rememberizer.ai/api/v1"
# 1. Opsæt batchstørrelse til migration (juster baseret på din datastørrelse)
BATCH_SIZE = 100
# 2. Funktion til at hente vektorer fra Pinecone
def fetch_vectors_from_pinecone(index_name, batch_size, cursor=None):
# Brug listeoperationen, hvis den er tilgængelig i din Pinecone-version
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:
# For ældre Pinecone-versioner uden listeoperation
# Dette er en forenklet tilgang; den faktiske implementering afhænger af dit dataadgangsmønster
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. Funktion til at uploade vektorer til 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():
# Konverter Pinecone vektordata til Rememberizer format
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"Springer {vector_id} over - ingen tekstindhold fundet i metadata")
continue
data = {
"name": document_name,
"content": content,
# Valgfrit: inkluder yderligere metadata
"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"Dokument '{document_name}' uploadet med succes!")
else:
print(f"Fejl ved upload af dokument {document_name}: {response.text}")
# Tilføj en lille forsinkelse for at forhindre rate limiting
time.sleep(0.1)
# 4. Hoved migrationsfunktion
def migrate_pinecone_to_rememberizer():
cursor = None
total_migrated = 0
print("Starter migration fra Pinecone til Rememberizer...")
while True:
vectors, cursor = fetch_vectors_from_pinecone("your-pinecone-index", BATCH_SIZE, cursor)
if not vectors:
break
print(f"Hentet {len(vectors)} vektorer fra Pinecone")
upload_to_rememberizer(vectors)
total_migrated += len(vectors)
print(f"Fremdrift: {total_migrated} vektorer migreret")
if not cursor:
break
print(f"Migrering fuldført! {total_migrated} samlede vektorer migreret til Rememberizer")
# Kør migrationen
# migrate_pinecone_to_rememberizer()
const { PineconeClient } = require('@pinecone-database/pinecone');
const axios = require('axios');
// Pinecone konfiguration
const pineconeApiKey = 'PINECONE_API_KEY';
const pineconeEnvironment = 'PINECONE_ENVIRONMENT';
const pineconeIndexName = 'YOUR_PINECONE_INDEX';
// Rememberizer konfiguration
const rememberizerApiKey = 'YOUR_REMEMBERIZER_API_KEY';
const vectorStoreId = 'vs_abc123';
const baseUrl = 'https://api.rememberizer.ai/api/v1';
// Batch størrelse konfiguration
const BATCH_SIZE = 100;
// Initialiser Pinecone klient
async function initPinecone() {
const pinecone = new PineconeClient();
await pinecone.init({
apiKey: pineconeApiKey,
environment: pineconeEnvironment,
});
return pinecone;
}
// Hent vektorer fra Pinecone
async function fetchVectorsFromPinecone(pinecone, batchSize, paginationToken = null) {
const index = pinecone.Index(pineconeIndexName);
try {
// For nyere Pinecone versioner
const listResponse = await index.list({
limit: batchSize,
paginationToken: paginationToken
});
return {
vectors: listResponse.vectors || {},
nextToken: listResponse.paginationToken
};
} catch (error) {
// Fallback for ældre Pinecone versioner
// Dette er forenklet; den faktiske implementering afhænger af dit dataadgangsmønster
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 };
}
}
// Upload vektorer til 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(`Springer over ${vectorId} - ingen tekstindhold fundet i metadata`);
continue;
}
const data = {
name: documentName,
content: content,
// Valgfri: inkluder yderligere metadata
metadata: vectorData.metadata || {}
};
try {
const response = await axios.post(
`${baseUrl}/vector-stores/${vectorStoreId}/documents/text`,
data,
{ headers }
);
if (response.status === 201) {
console.log(`Dokument '${documentName}' uploadet med succes!`);
results.push({ id: vectorId, success: true });
} else {
console.error(`Fejl ved upload af dokument ${documentName}: ${response.statusText}`);
results.push({ id: vectorId, success: false, error: response.statusText });
}
} catch (error) {
console.error(`Fejl ved upload af dokument ${documentName}: ${error.message}`);
results.push({ id: vectorId, success: false, error: error.message });
}
// Tilføj en lille forsinkelse for at forhindre rate limiting
await new Promise(resolve => setTimeout(resolve, 100));
}
return results;
}
// Hoved migrationsfunktion
async function migratePineconeToRememberizer() {
try {
console.log('Starter migration fra Pinecone til 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(`Hentede ${Object.keys(vectors).length} vektorer fra Pinecone`);
const results = await uploadToRememberizer(vectors);
const successCount = results.filter(r => r.success).length;
totalMigrated += successCount;
console.log(`Fremskridt: ${totalMigrated} vektorer migreret med succes`);
} while (nextToken);
console.log(`Migration fuldført! ${totalMigrated} samlede vektorer migreret til Rememberizer`);
} catch (error) {
console.error('Migration mislykkedes:', error);
}
}
// Kør migrationen
// migratePineconeToRememberizer();
Migrering fra Qdrant¶
import requests
import json
import time
from qdrant_client import QdrantClient
from qdrant_client.http import models as rest
# Opsæt Qdrant-klient
QDRANT_URL = "http://localhost:6333" # eller din Qdrant cloud URL
QDRANT_API_KEY = "your_qdrant_api_key" # hvis du bruger Qdrant Cloud
QDRANT_COLLECTION_NAME = "your_collection"
qdrant_client = QdrantClient(
url=QDRANT_URL,
api_key=QDRANT_API_KEY # Kun for Qdrant Cloud
)
# Opsæt Rememberizer Vector Store-klient
REMEMBERIZER_API_KEY = "your_rememberizer_api_key"
VECTOR_STORE_ID = "vs_abc123" # Dit Rememberizer vector store ID
BASE_URL = "https://api.rememberizer.ai/api/v1"
# Batch størrelse til behandling
BATCH_SIZE = 100
# Funktion til at hente punkter fra Qdrant
def fetch_points_from_qdrant(collection_name, batch_size, offset=0):
try:
# Hent kollektionsinfo for at bestemme vektordimension
collection_info = qdrant_client.get_collection(collection_name=collection_name)
# Rul gennem punkter
scroll_result = qdrant_client.scroll(
collection_name=collection_name,
limit=batch_size,
offset=offset,
with_payload=True,
with_vectors=True
)
points = scroll_result[0] # Tuple af (punkter, næste_offset)
next_offset = scroll_result[1]
return points, next_offset
except Exception as e:
print(f"Fejl ved hentning af punkter fra Qdrant: {e}")
return [], None
# Funktion til at uploade vektorer til Rememberizer
def upload_to_rememberizer(points):
headers = {
"x-api-key": REMEMBERIZER_API_KEY,
"Content-Type": "application/json"
}
results = []
for point in points:
# Uddrag data fra Qdrant punkt
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"Springer over {point_id} - ingen tekstindhold fundet i payload")
continue
data = {
"name": document_name,
"content": text_content,
# Valgfrit: inkluder yderligere metadata
"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"Dokument '{document_name}' uploadet med succes!")
results.append({"id": point_id, "success": True})
else:
print(f"Fejl ved upload af dokument {document_name}: {response.text}")
results.append({"id": point_id, "success": False, "error": response.text})
except Exception as e:
print(f"Undtagelse ved upload af dokument {document_name}: {str(e)}")
results.append({"id": point_id, "success": False, "error": str(e)})
# Tilføj en lille forsinkelse for at forhindre rate limiting
time.sleep(0.1)
return results
# Hoved migrationsfunktion
def migrate_qdrant_to_rememberizer():
offset = None
total_migrated = 0
print("Starter migration fra Qdrant til Rememberizer...")
while True:
points, next_offset = fetch_points_from_qdrant(
QDRANT_COLLECTION_NAME,
BATCH_SIZE,
offset
)
if not points:
break
print(f"Hentet {len(points)} punkter fra 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"Fremdrift: {total_migrated} punkter migreret med succes")
if next_offset is None:
break
offset = next_offset
print(f"Migrering fuldført! {total_migrated} samlede punkter migreret til Rememberizer")
# Kør migrationen
# migrate_qdrant_to_rememberizer()
const { QdrantClient } = require('@qdrant/js-client-rest');
const axios = require('axios');
// Qdrant konfiguration
const qdrantUrl = 'http://localhost:6333'; // eller din Qdrant cloud URL
const qdrantApiKey = 'your_qdrant_api_key'; // hvis du bruger Qdrant Cloud
const qdrantCollectionName = 'your_collection';
// Rememberizer konfiguration
const rememberizerApiKey = 'YOUR_REMEMBERIZER_API_KEY';
const vectorStoreId = 'vs_abc123';
const baseUrl = 'https://api.rememberizer.ai/api/v1';
// Batch størrelse konfiguration
const BATCH_SIZE = 100;
// Initialiser Qdrant klient
const qdrantClient = new QdrantClient({
url: qdrantUrl,
apiKey: qdrantApiKey // Kun for Qdrant Cloud
});
// Hent punkter fra Qdrant
async function fetchPointsFromQdrant(collectionName, batchSize, offset = 0) {
try {
// Få kollektionsinfo
const collectionInfo = await qdrantClient.getCollection(collectionName);
// Scroll gennem punkter
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(`Fejl ved hentning af punkter fra Qdrant: ${error.message}`);
return { points: [], nextOffset: null };
}
}
// Upload vektorer til Rememberizer
async function uploadToRememberizer(points) {
const headers = {
'x-api-key': rememberizerApiKey,
'Content-Type': 'application/json'
};
const results = [];
for (const point of points) {
// Uddrag data fra Qdrant punkt
const pointId = point.id;
const metadata = point.payload || {};
const textContent = metadata.text || '';
const documentName = metadata.filename || `qdrant_doc_${pointId}`;
if (!textContent) {
console.log(`Springer over ${pointId} - ingen tekstindhold fundet i payload`);
continue;
}
const data = {
name: documentName,
content: textContent,
// Valgfrit: inkluder yderligere metadata
metadata: metadata
};
try {
const response = await axios.post(
`${baseUrl}/vector-stores/${vectorStoreId}/documents/text`,
data,
{ headers }
);
if (response.status === 201) {
console.log(`Dokument '${documentName}' uploadet med succes!`);
results.push({ id: pointId, success: true });
} else {
console.error(`Fejl ved upload af dokument ${documentName}: ${response.statusText}`);
results.push({ id: pointId, success: false, error: response.statusText });
}
} catch (error) {
console.error(`Fejl ved upload af dokument ${documentName}: ${error.message}`);
results.push({ id: pointId, success: false, error: error.message });
}
// Tilføj en lille forsinkelse for at forhindre rate limiting
await new Promise(resolve => setTimeout(resolve, 100));
}
return results;
}
// Hoved migrationsfunktion
async function migrateQdrantToRememberizer() {
try {
console.log('Starter migration fra Qdrant til 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(`Hentede ${points.length} punkter fra Qdrant`);
const results = await uploadToRememberizer(points);
const successCount = results.filter(r => r.success).length;
totalMigrated += successCount;
console.log(`Fremdrift: ${totalMigrated} punkter migreret med succes`);
} while (offset !== null);
console.log(`Migration fuldført! ${totalMigrated} samlede punkter migreret til Rememberizer`);
} catch (error) {
console.error('Migration mislykkedes:', error);
}
}
// Kør migrationen
// migrateQdrantToRememberizer();
Migration fra Supabase pgvector¶
Hvis du allerede bruger Supabase med pgvector, er migrationen til Rememberizer særligt ligetil, da begge bruger PostgreSQL med pgvector-udvidelsen.
import psycopg2
import requests
import json
import time
import os
from dotenv import load_dotenv
# Indlæs miljøvariabler
load_dotenv()
# Supabase PostgreSQL konfiguration
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")
# Rememberizer konfiguration
REMEMBERIZER_API_KEY = os.getenv("REMEMBERIZER_API_KEY")
VECTOR_STORE_ID = os.getenv("VECTOR_STORE_ID") # f.eks. "vs_abc123"
BASE_URL = "https://api.rememberizer.ai/api/v1"
# Batch størrelse til behandling
BATCH_SIZE = 100
# Forbind til 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"Fejl ved forbindelse til Supabase PostgreSQL: {e}")
return None
# Hent dokumenter fra Supabase pgvector
def fetch_documents_from_supabase(conn, batch_size, offset=0):
try:
cursor = conn.cursor()
# Juster denne forespørgsel baseret på din tabelstruktur
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"Fejl ved hentning af dokumenter fra Supabase: {e}")
return []
# Upload dokumenter til Rememberizer
def upload_to_rememberizer(dokumenter):
headers = {
"x-api-key": REMEMBERIZER_API_KEY,
"Content-Type": "application/json"
}
resultater = []
for doc in dokumenter:
doc_id, indhold, metadata, embedding = doc
# Parse metadata hvis det er gemt som JSON-streng
if isinstance(metadata, str):
try:
metadata = json.loads(metadata)
except:
metadata = {}
elif metadata is None:
metadata = {}
dokument_navn = metadata.get("filename", f"supabase_doc_{doc_id}")
if not indhold:
print(f"Springer {doc_id} over - ingen indhold fundet")
continue
data = {
"name": dokument_navn,
"content": indhold,
"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"Dokument '{dokument_navn}' uploadet med succes!")
resultater.append({"id": doc_id, "success": True})
else:
print(f"Fejl ved upload af dokument {dokument_navn}: {response.text}")
resultater.append({"id": doc_id, "success": False, "error": response.text})
except Exception as e:
print(f"Undtagelse ved upload af dokument {dokument_navn}: {str(e)}")
resultater.append({"id": doc_id, "success": False, "error": str(e)})
# Tilføj en lille forsinkelse for at forhindre rate limiting
time.sleep(0.1)
return resultater
# Hoved migrationsfunktion
def migrate_supabase_to_rememberizer():
conn = connect_to_supabase()
if not conn:
print("Mislykkedes at oprette forbindelse til Supabase. Afbryder migration.")
return
offset = 0
total_migrated = 0
print("Starter migration fra Supabase pgvector til Rememberizer...")
try:
while True:
documents = fetch_documents_from_supabase(conn, BATCH_SIZE, offset)
if not documents:
break
print(f"Hentede {len(documents)} dokumenter fra 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"Fremdrift: {total_migrated} dokumenter migreret med succes")
offset += BATCH_SIZE
finally:
conn.close()
print(f"Migrering fuldført! {total_migrated} samlede dokumenter migreret til Rememberizer")
# Kør migrationen
# migrate_supabase_to_rememberizer()
const { Pool } = require('pg');
const axios = require('axios');
require('dotenv').config();
// Supabase PostgreSQL konfiguration
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';
// Rememberizer konfiguration
const rememberizerApiKey = process.env.REMEMBERIZER_API_KEY;
const vectorStoreId = process.env.VECTOR_STORE_ID; // f.eks. "vs_abc123"
const baseUrl = 'https://api.rememberizer.ai/api/v1';
// Batch størrelse konfiguration
const BATCH_SIZE = 100;
// Hent dokumenter fra Supabase pgvector
async function fetchDocumentsFromSupabase(batchSize, offset = 0) {
try {
// Juster denne forespørgsel baseret på din tabelstruktur
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(`Fejl ved hentning af dokumenter fra Supabase: ${error.message}`);
return [];
}
}
// Upload dokumenter til Rememberizer
async function uploadToRememberizer(documents) {
const headers = {
'x-api-key': rememberizerApiKey,
'Content-Type': 'application/json'
};
const results = [];
for (const doc of documents) {
// Parse metadata hvis det er gemt som JSON-streng
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(`Springer over ${doc.id} - ingen indhold fundet`);
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(`Dokument '${documentName}' uploadet med succes!`);
results.push({ id: doc.id, success: true });
} else {
console.error(`Fejl ved upload af dokument ${documentName}: ${response.statusText}`);
results.push({ id: doc.id, success: false, error: response.statusText });
}
} catch (error) {
console.error(`Fejl ved upload af dokument ${documentName}: ${error.message}`);
results.push({ id: doc.id, success: false, error: error.message });
}
// Tilføj en lille forsinkelse for at forhindre rate limiting
await new Promise(resolve => setTimeout(resolve, 100));
}
return results;
}
// Hoved migrationsfunktion
async function migrateSupabaseToRememberizer() {
try {
console.log('Starter migration fra Supabase pgvector til Rememberizer...');
let offset = 0;
let totalMigrated = 0;
while (true) {
const documents = await fetchDocumentsFromSupabase(BATCH_SIZE, offset);
if (documents.length === 0) {
break;
}
console.log(`Hentede ${documents.length} dokumenter fra Supabase`);
const results = await uploadToRememberizer(documents);
const successCount = results.filter(r => r.success).length;
totalMigrated += successCount;
console.log(`Fremdrift: ${totalMigrated} dokumenter migreret med succes`);
offset += BATCH_SIZE;
}
console.log(`Migration fuldført! ${totalMigrated} samlede dokumenter migreret til Rememberizer`);
} catch (error) {
console.error('Migration mislykkedes:', error);
} finally {
await supabasePool.end();
}
}
// Kør migrationen
// migrateSupabaseToRememberizer();
Migrerings bedste praksis¶
Følg disse anbefalinger for en vellykket migrering:
- Planlæg på forhånd:
- Estimér datamængden og den tid, der kræves til migrering
- Planlæg migrering i perioder med lav trafik
-
Øg diskpladsen før du starter store migreringer
-
Test først:
- Opret et testvektorlager i Rememberizer
- Migrer et lille udsnit af data (100-1000 vektorer)
-
Bekræft søgefunktionaliteten med nøglespørgsmål
-
Datavalidering:
- Sammenlign dokumenttællinger før og efter migrering
- Kør benchmark-spørgsmål for at sikre lignende resultater
-
Valider at metadata er korrekt bevaret
-
Optimer for ydeevne:
- Brug batchoperationer for effektivitet
- Overvej geografisk kolokation af kilde- og mål-databaser
-
Overvåg API-hastighedsgrænser og juster batchstørrelserne derefter
-
Post-migrerings trin:
- Bekræft indeksoprettelse i Rememberizer
- Opdater applikationskonfigurationer til at pege på det nye vektorlager
- Behold kilde-databasen som backup, indtil migreringen er bekræftet
For detaljeret API-referencer og endpoint-dokumentation, besøg vector-store siden.
Sørg for at håndtere API-nøgler sikkert og følge bedste praksis for API-nøglehåndtering.