Vektor-Speicher¶
Der Rememberizer Vektor-Speicher vereinfacht den Umgang mit Vektordaten, sodass Sie sich auf die Texteingabe konzentrieren und die Leistungsfähigkeit von Vektoren für verschiedene Anwendungen wie Suche und Datenanalyse nutzen können.
Einführung¶
Der Rememberizer Vector Store bietet eine benutzerfreundliche Schnittstelle zur Handhabung von Vektordaten und abstrahiert dabei die Komplexität von Vektor-Embeddings. Angetrieben von PostgreSQL mit der pgvector-Erweiterung ermöglicht der Rememberizer Vector Store die direkte Arbeit mit Text. Der Dienst kümmert sich um das Chunking, die Vektorisierung und das Speichern der Textdaten, sodass Sie sich leichter auf Ihre Kernanwendungslogik konzentrieren können.
Für ein tieferes Verständnis der theoretischen Konzepte hinter Vektor-Embeddings und Vektordatenbanken siehe Was sind Vektor-Embeddings und Vektordatenbanken?.
Technische Übersicht¶
Wie Vektor-Speicher funktionieren¶
Rememberizer Vektor-Speicher wandeln Text in hochdimensionale Vektor-Darstellungen (Embeddings) um, die die semantische Bedeutung erfassen. Dies ermöglicht:
- Semantische Suche: Dokumente basierend auf Bedeutung und nicht nur auf Schlüsselwörtern finden
- Ähnlichkeitsabgleich: Konzeptuell verwandte Inhalte identifizieren
- Effiziente Abrufung: Relevante Informationen schnell aus großen Datensätzen lokalisieren
Schlüsselkomponenten¶
- Dokumentenverarbeitung: Texte werden in optimal große Abschnitte mit überlappenden Grenzen zur Kontextbewahrung aufgeteilt
- Vektorisierung: Abschnitte werden mit modernsten Modellen in Einbettungen umgewandelt
- Indizierung: Spezialisierte Algorithmen organisieren Vektoren für eine effiziente Ähnlichkeitssuche
- Abfrageverarbeitung: Suchanfragen werden vektorisiert und mit gespeicherten Einbettungen verglichen
Architektur¶
Rememberizer implementiert Vektorspeicher mit:
- PostgreSQL mit pgvector-Erweiterung: Für effiziente Vektorspeicherung und -suche
- Sammlungsbasierte Organisation: Jeder Vektorspeicher hat seine eigene isolierte Sammlung
- API-gesteuerter Zugriff: Einfache RESTful-Endpunkte für alle Operationen
Erste Schritte¶
Erstellen eines Vektor-Speichers¶
- Navigieren Sie zum Abschnitt Vektor-Speicher in Ihrem Dashboard
- Klicken Sie auf "Neuen Vektor-Speicher erstellen":
- Ein Formular wird angezeigt, das Sie auffordert, Details einzugeben.
- Füllen Sie die Details aus:
- Name: Geben Sie einen eindeutigen Namen für Ihren Vektor-Speicher an.
- Beschreibung: Schreiben Sie eine kurze Beschreibung des Vektor-Speichers.
- Einbettungsmodell: Wählen Sie das Modell aus, das Text in Vektoren umwandelt.
- Indexierungsalgorithmus: Wählen Sie aus, wie Vektoren für die Suche organisiert werden.
- Suchmetrik: Definieren Sie, wie die Ähnlichkeit zwischen Vektoren berechnet wird.
- Vektor-Dimension: Die Größe der Vektor-Einbettungen (typischerweise 768-1536).
- Reichen Sie das Formular ein:
- Klicken Sie auf die Schaltfläche "Erstellen". Sie erhalten eine Erfolgsmeldung, und der neue Speicher wird in Ihrer Liste der Vektor-Speicher angezeigt.

Erstellen eines neuen Vektor-Speichers
Konfigurationsoptionen¶
Einbettungsmodelle¶
| Modell | Dimensionen | Beschreibung | Am besten geeignet für |
|---|---|---|---|
| openai/text-embedding-3-large | 1536 | Hochgenaues Einbettungsmodell von OpenAI | Produktionsanwendungen, die maximale Genauigkeit erfordern |
| openai/text-embedding-3-small | 1536 | Kleineres, schnelleres Einbettungsmodell von OpenAI | Anwendungen mit höheren Durchsatzanforderungen |
Indexierungsalgorithmen¶
| Algorithmus | Beschreibung | Kompromisse |
|---|---|---|
| IVFFLAT (Standard) | Umgekehrte Datei mit flacher Kompression | Gute Balance zwischen Geschwindigkeit und Genauigkeit; funktioniert gut für die meisten Datensätze |
| HNSW | Hierarchisches navigierbares kleines Welt | Bessere Genauigkeit für große Datensätze; höhere Speicheranforderungen |
Suchmetriken¶
| Metrik | Beschreibung | Am besten geeignet für |
|---|---|---|
| cosinus (Standard) | Misst den Winkel zwischen Vektoren | Allgemeine Ähnlichkeitsabgleichung |
| inneres Produkt (ip) | Skalarprodukt zwischen Vektoren | Wenn die Vektormagnitude wichtig ist |
| L2 (Euklidisch) | Luftlinienentfernung zwischen Vektoren | Wenn räumliche Beziehungen wichtig sind |
Verwaltung von Vektor-Speichern¶
- Vektor-Speicher anzeigen und bearbeiten:
- Greifen Sie auf das Verwaltungs-Dashboard zu, um Vektor-Speicher anzuzeigen, zu bearbeiten oder zu löschen.
- Dokumente anzeigen:
- Durchsuchen Sie einzelne Dokumente und deren zugehörige Metadaten innerhalb eines bestimmten Vektor-Speichers.
- Statistiken:
- Sehen Sie sich detaillierte Statistiken wie die Anzahl der gespeicherten Vektoren, die Abfrageleistung und betriebliche Kennzahlen an.

Details eines Vektor-Speichers anzeigen
API-Schlüsselverwaltung¶
API-Schlüssel werden verwendet, um den Zugriff auf die API-Endpunkte des Rememberizer Vector Store zu authentifizieren und zu autorisieren. Eine ordnungsgemäße Verwaltung der API-Schlüssel ist entscheidend für die Aufrechterhaltung der Sicherheit und Integrität Ihrer Vektor-Stores.
Erstellen von API-Schlüsseln¶
- Gehen Sie zu Ihrer Seite mit den Details zum Vector Store
- Navigieren Sie zum Abschnitt zur Verwaltung von API-Schlüsseln:
- Er kann im Tab "Konfiguration" gefunden werden
- Klicken Sie auf "API-Schlüssel hinzufügen":
- Ein Formular wird angezeigt, das Sie auffordert, Details einzugeben.
- Füllen Sie die Details aus:
- Name: Geben Sie einen Namen für den API-Schlüssel an, um Ihnen zu helfen, seinen Anwendungsfall zu identifizieren.
- Reichen Sie das Formular ein:
- Klicken Sie auf die Schaltfläche "Erstellen". Der neue API-Schlüssel wird generiert und angezeigt. Stellen Sie sicher, dass Sie ihn kopieren und sicher aufbewahren. Dieser Schlüssel wird verwendet, um Anfragen an diesen speziellen Vector Store zu authentifizieren.

Erstellen eines neuen API-Schlüssels
Widerrufen von API-Schlüsseln¶
Wenn ein API-Schlüssel nicht mehr benötigt wird, können Sie ihn löschen, um möglichen Missbrauch zu verhindern.
Aus Sicherheitsgründen möchten Sie möglicherweise Ihre API-Schlüssel regelmäßig rotieren. Dies beinhaltet das Generieren eines neuen Schlüssels und das Widerrufen des alten.
Verwendung der Vector Store API¶
Nachdem Sie einen Vector Store erstellt und einen API-Schlüssel generiert haben, können Sie über die REST API mit ihm interagieren.
Codebeispiele¶
Dokument in den Vektor-Speicher hochladen¶
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}' erfolgreich hochgeladen!")
return response.json()
else:
print(f"Fehler beim Hochladen des Dokuments: {response.text}")
return None
Textinhalt in den Vektorstore hochladen¶
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"Textdokument '{document_name}' erfolgreich hochgeladen!")
return response.json()
else:
print(f"Fehler beim Hochladen des Textes: {response.text}")
return None
Suche im Vektor-Store¶
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"Gefunden: {len(results['matched_chunks'])} Übereinstimmungen für '{query}'")
# Drucke das beste Ergebnis
if results['matched_chunks']:
top_match = results['matched_chunks'][0]
print(f"Bester Treffer (Distanz: {top_match['distance']}):")
print(f"Dokument: {top_match['document']['name']}")
print(f"Inhalt: {top_match['matched_content']}")
return results
else:
print(f"Fehler bei der Suche: {response.text}")
return None
Beispielverwendung¶
dokument_hochladen("pfad/zum/dokument.pdf")¶
upload_text("Dies ist ein Beispieltext, der vektorisiert werden soll", "sample-document.txt")¶
search_vector_store("Wie funktioniert die Vektorsimilarität?")¶
```
```javascript // Vector Store API Client class VectorStoreClient { constructor(apiKey, vectorStoreId) { this.apiKey = apiKey; this.vectorStoreId = vectorStoreId; this.baseUrl = 'https://api.rememberizer.ai/api/v1'; }
// Informationen zum Vektor-Store abrufen
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(`Fehler beim Abrufen der Vektor-Store-Informationen: ${response.statusText}`);
}
return response.json();
}
// Ein Textdokument hochladen
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(`Fehler beim Hochladen des Textdokuments: ${response.statusText}`);
}
return response.json();
}
// Eine Datei hochladen 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(`Fehler beim Hochladen der Datei: ${xhr.statusText}`));
}
};
xhr.onerror = () => {
reject(new Error('Netzwerkfehler beim Hochladen der Datei'));
};
xhr.send(formData);
});
}
// Dokumente im Vektor-Store durchsuchen 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(`Suche fehlgeschlagen: ${response.statusText}`);
}
return response.json();
}
// Alle Dokumente im Vektor-Store auflisten
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(`Fehler beim Auflisten der Dokumente: ${response.statusText}`);
}
return response.json();
}
// Ein Dokument löschen
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(`Fehler beim Löschen des Dokuments: ${response.statusText}`);
}
return true;
} }
// Beispielverwendung /* const client = new VectorStoreClient('your_api_key', 'vs_abc123');
// Dokumente durchsuchen
client.searchDocuments('Wie funktioniert die semantische Suche?')
.then(results => {
console.log(Gefundene ${results.matched_chunks.length} Übereinstimmungen);
results.matched_chunks.forEach(match => {
console.log(Dokument: ${match.document.name});
console.log(Punktzahl: ${match.distance});
console.log(Inhalt: ${match.matched_content});
console.log('---');
});
})
.catch(error => console.error(error));
*/
```
```ruby 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
# Details zum Vektor-Store abrufen 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
# Textinhalt hochladen 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
# Dokumente durchsuchen 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
# Dokumente auflisten 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
# Datei hochladen (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-Anfrage fehlgeschlagen: #{response.code} #{response.message}\n#{response.body}"
end
response
end end ```
Beispielverwendung¶
=begin client = VectorStoreClient.new('your_api_key', 'vs_abc123')
Suche nach Dokumenten¶
results = client.search('Was sind die besten Praktiken für Datensicherheit?') puts "Gefunden #{results['matched_chunks'].length} Ergebnisse"
Zeige das beste Ergebnis an¶
if results['matched_chunks'].any? top_match = results['matched_chunks'].first puts "Bester Treffer (Distanz: #{top_match['distance']}):" puts "Dokument: #{top_match['document']['name']}" puts "Inhalt: #{top_match['matched_content']}" end =end ```
```bash
Setzen Sie Ihren API-Schlüssel und die Vector Store-ID¶
API_KEY="your_api_key_here" VECTOR_STORE_ID="vs_abc123" BASE_URL="https://api.rememberizer.ai/api/v1"
Informationen zum Vektor-Store abrufen¶
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}"
-H "x-api-key: ${API_KEY}"
Laden Sie ein Textdokument hoch¶
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": "Dies ist ein Beispiel-Dokument, das vektorisiert und in der Vektordatenbank für die semantische Suche gespeichert wird."
}'
Eine Datei hochladen¶
curl -X POST "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents"
-H "x-api-key: ${API_KEY}"
-F "file=@/path/to/your/document.pdf"
Suche nach Dokumenten¶
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents/search?q=semantische%20suche&n=5&prev_chunks=1&next_chunks=1"
-H "x-api-key: ${API_KEY}"
Alle Dokumente auflisten¶
curl -X GET "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents"
-H "x-api-key: ${API_KEY}"
Löschen eines Dokuments¶
curl -X DELETE "${BASE_URL}/vector-stores/${VECTOR_STORE_ID}/documents/123"
-H "x-api-key: ${API_KEY}"
```
Leistungsüberlegungen¶
Demnächst: Architekturdiagramm des Vektor-Speichers
Dieses technische Architekturdiagramm wird veranschaulichen:
- Die Architektur der PostgreSQL + pgvector-Grundlage
- Strukturen der Indexierungsalgorithmen (IVFFLAT vs. HNSW)
- Wie Suchmetriken im Vektorraum funktionieren (visueller Vergleich)
- Dokumentchunking-Prozess mit Überlappungsvisualisierung
- Leistungsüberlegungen, die über verschiedene Skalen visualisiert werden
Optimierung für verschiedene Datenmengen¶
| Datenmenge | Empfohlene Konfiguration | Hinweise |
|---|---|---|
| Klein (<10k Dokumente) | IVFFLAT, Kosinusähnlichkeit | Einfache Konfiguration bietet gute Leistung |
| Mittel (10k-100k Dokumente) | IVFFLAT, regelmäßige Neuanordnung sicherstellen | Balance zwischen Suchgeschwindigkeit und Indexpflege |
| Groß (>100k Dokumente) | HNSW, Erwägung der Erhöhung der Vektordimensionen | Höherer Speicherverbrauch, aber hält die Leistung im großen Maßstab |
Chunking-Strategien¶
Der Chunking-Prozess hat einen erheblichen Einfluss auf die Suchqualität:
- Chunk-Größe: Rememberizer verwendet eine Standard-Chunk-Größe von 1024 Bytes mit einer Überlappung von 200 Bytes
- Kleinere Chunks (512-1024 Bytes): Präzisere Übereinstimmungen, besser für spezifische Fragen
- Größere Chunks (1500-2048 Bytes): Mehr Kontext in jeder Übereinstimmung, besser für breitere Themen
- Überlappung: Stellt sicher, dass der Kontext an den Chunk-Grenzen nicht verloren geht
Abfrageoptimierung¶
- Kontextfenster: Verwenden Sie
prev_chunksundnext_chunks, um umgebende Inhalte abzurufen - Ergebnisanzahl: Beginnen Sie mit 3-5 Ergebnissen (
n-Parameter) und passen Sie diese je nach Präzisionsbedarf an - Schwellenwert: Passen Sie den
t-Parameter an, um Ergebnisse nach Ähnlichkeitspunktzahl zu filtern
Erweiterte Nutzung¶
Neuindizierung¶
Rememberizer löst automatisch eine Neuindizierung aus, wenn die Vektoranzahlen vordefinierte Schwellenwerte überschreiten, aber ziehen Sie eine manuelle Neuindizierung in Betracht nach:
- Hochladen einer großen Anzahl von Dokumenten
- Ändern des Einbettungsmodells
- Modifizieren des Indizierungsalgorithmus
Abfrageverbesserung¶
Für bessere Suchergebnisse:
- Seien Sie spezifisch in Suchanfragen
- Fügen Sie Kontext hinzu, wenn möglich
- Verwenden Sie natürliche Sprache anstelle von Schlüsselwörtern
- Passen Sie die Parameter an basierend auf der Ergebnisqualität
Migration von anderen Vektor-Datenbanken¶
Wenn Sie derzeit andere Vektor-Datenbanklösungen verwenden und zu Rememberizer Vector Store migrieren möchten, helfen Ihnen die folgenden Anleitungen, Ihre Daten effizient zu übertragen.
Migrationsübersicht¶
Die Migration von Vektordaten umfasst: 1. Exportieren von Daten aus Ihrer Quell-Vektordatenbank 2. Konvertieren der Daten in ein mit Rememberizer kompatibles Format 3. Importieren der Daten in Ihren Rememberizer Vektor-Speicher 4. Überprüfen, ob die Migration erfolgreich war
Vorteile der Migration zu Rememberizer¶
- PostgreSQL-Grundlage: Basierend auf reifer Datenbanktechnologie mit integrierter Sicherung und Wiederherstellung
- Integriertes Ökosystem: Nahtlose Verbindung mit anderen Rememberizer-Komponenten
- Vereinfachte Verwaltung: Einheitliche Schnittstelle für Vektoroperationen
- Erweiterte Sicherheit: Zeilenbasierte Sicherheit und feingranulare Zugriffskontrollen
- Skalierbare Architektur: Leistungsoptimierung, während Ihre Daten wachsen
Migration von Pinecone¶
```python import os import pinecone import requests import json import time
Richten Sie den Pinecone-Client ein¶
pinecone.init(api_key="PINECONE_API_KEY", environment="PINECONE_ENV") source_index = pinecone.Index("your-pinecone-index")
Richten Sie den Rememberizer Vector Store-Client ein¶
REMEMBERIZER_API_KEY = "your_rememberizer_api_key" VECTOR_STORE_ID = "vs_abc123" # Ihre Rememberizer-Vektorstore-ID BASE_URL = "https://api.rememberizer.ai/api/v1"
1. Batchgröße für die Migration festlegen (an Ihre Datengröße anpassen)¶
BATCH_SIZE = 100
2. Funktion zum Abrufen von Vektoren aus Pinecone¶
def fetch_vectors_from_pinecone(index_name, batch_size, cursor=None): # Verwenden Sie die Listenoperation, wenn sie in Ihrer Pinecone-Version verfügbar ist 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: # Für ältere Pinecone-Versionen ohne Listenoperation # Dies ist ein vereinfachter Ansatz; die tatsächliche Implementierung hängt von Ihrem Datenzugriffsmuster ab 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 zum Hochladen von Vektoren zu 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():
# Konvertiere Pinecone-Vektordaten in 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"Überspringe {vector_id} - kein Textinhalt in den Metadaten gefunden")
continue
data = {
"name": document_name,
"content": content,
# Optional: zusätzliche Metadaten einfügen
"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}' erfolgreich hochgeladen!")
else:
print(f"Fehler beim Hochladen des Dokuments {document_name}: {response.text}")
# Füge eine kleine Verzögerung hinzu, um eine Überlastung zu vermeiden
time.sleep(0.1)
4. Hauptmigrationfunktion¶
def migrate_pinecone_to_rememberizer(): cursor = None total_migrated = 0
print("Migration von Pinecone zu Rememberizer startet...")
while True:
vectors, cursor = fetch_vectors_from_pinecone("your-pinecone-index", BATCH_SIZE, cursor)
if not vectors:
break
print(f"{len(vectors)} Vektoren von Pinecone abgerufen")
upload_to_rememberizer(vectors)
total_migrated += len(vectors)
print(f"Fortschritt: {total_migrated} Vektoren migriert")
if not cursor:
break
print(f"Migration abgeschlossen! Insgesamt {total_migrated} Vektoren zu Rememberizer migriert")
Führen Sie die Migration durch¶
migrate_pinecone_to_rememberizer()¶
```
```javascript 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-Größe Konfiguration const BATCH_SIZE = 100;
// Pinecone-Client initialisieren async function initPinecone() { const pinecone = new PineconeClient(); await pinecone.init({ apiKey: pineconeApiKey, environment: pineconeEnvironment, }); return pinecone; }
// Vektoren von Pinecone abrufen async function fetchVectorsFromPinecone(pinecone, batchSize, paginationToken = null) { const index = pinecone.Index(pineconeIndexName);
try { // Für neuere Pinecone-Versionen const listResponse = await index.list({ limit: batchSize, paginationToken: paginationToken });
return {
vectors: listResponse.vectors || {},
nextToken: listResponse.paginationToken
};
} catch (error) { // Fallback für ältere Pinecone-Versionen // Dies ist vereinfacht; die tatsächliche Implementierung hängt von Ihrem Datenzugriffsmuster ab 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 };
} }
// Vektoren zu Rememberizer hochladen 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(`Überspringe ${vectorId} - kein Textinhalt in den Metadaten gefunden`);
continue;
}
const data = {
name: documentName,
content: content,
// Optional: zusätzliche Metadaten einfügen
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}' erfolgreich hochgeladen!`);
results.push({ id: vectorId, success: true });
} else {
console.error(`Fehler beim Hochladen des Dokuments ${documentName}: ${response.statusText}`);
results.push({ id: vectorId, success: false, error: response.statusText });
}
} catch (error) {
console.error(`Fehler beim Hochladen des Dokuments ${documentName}: ${error.message}`);
results.push({ id: vectorId, success: false, error: error.message });
}
// Eine kleine Verzögerung hinzufügen, um eine Ratenbegrenzung zu verhindern
await new Promise(resolve => setTimeout(resolve, 100));
}
return results; }
// Hauptmigrationsfunktion async function migratePineconeToRememberizer() { try { console.log('Migration von Pinecone zu Rememberizer startet...');
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(`${Object.keys(vectors).length} Vektoren von Pinecone abgerufen`);
const results = await uploadToRememberizer(vectors);
const successCount = results.filter(r => r.success).length;
totalMigrated += successCount;
console.log(`Fortschritt: ${totalMigrated} Vektoren erfolgreich migriert`);
} while (nextToken);
console.log(`Migration abgeschlossen! ${totalMigrated} insgesamt Vektoren zu Rememberizer migriert`);
} catch (error) { console.error('Migration fehlgeschlagen:', error); } }
// Migration ausführen // migratePineconeToRememberizer(); ```
Migration von Qdrant¶
```python import requests import json import time from qdrant_client import QdrantClient from qdrant_client.http import models as rest
Richten Sie den Qdrant-Client ein¶
QDRANT_URL = "http://localhost:6333" # oder Ihre Qdrant-Cloud-URL QDRANT_API_KEY = "your_qdrant_api_key" # falls Sie Qdrant Cloud verwenden QDRANT_COLLECTION_NAME = "your_collection"
qdrant_client = QdrantClient( url=QDRANT_URL, api_key=QDRANT_API_KEY # Nur für Qdrant Cloud )
Richten Sie den Rememberizer Vector Store-Client ein¶
REMEMBERIZER_API_KEY = "your_rememberizer_api_key" VECTOR_STORE_ID = "vs_abc123" # Ihre Rememberizer-Vektorstore-ID BASE_URL = "https://api.rememberizer.ai/api/v1"
Batch-Größe für die Verarbeitung¶
BATCH_SIZE = 100
Funktion zum Abrufen von Punkten aus Qdrant¶
def fetch_points_from_qdrant(collection_name, batch_size, offset=0): try: # Sammlung Informationen abrufen, um die Vektor-Dimension zu bestimmen collection_info = qdrant_client.get_collection(collection_name=collection_name)
# Durch Punkte scrollen
scroll_result = qdrant_client.scroll(
collection_name=collection_name,
limit=batch_size,
offset=offset,
with_payload=True,
with_vectors=True
)
points = scroll_result[0] # Tupel von (punkten, next_offset)
next_offset = scroll_result[1]
return points, next_offset
except Exception as e:
print(f"Fehler beim Abrufen von Punkten aus Qdrant: {e}")
return [], None
Funktion zum Hochladen von Vektoren zu Rememberizer¶
def upload_to_rememberizer(points): headers = { "x-api-key": REMEMBERIZER_API_KEY, "Content-Type": "application/json" }
results = []
for point in points:
# Daten aus dem Qdrant-Punkt extrahieren
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"Überspringe {point_id} - kein Textinhalt im Payload gefunden")
continue
data = {
"name": document_name,
"content": text_content,
# Optional: zusätzliche Metadaten einfügen
"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}' erfolgreich hochgeladen!")
results.append({"id": point_id, "success": True})
else:
print(f"Fehler beim Hochladen des Dokuments {document_name}: {response.text}")
results.append({"id": point_id, "success": False, "error": response.text})
except Exception as e:
print(f"Ausnahme beim Hochladen des Dokuments {document_name}: {str(e)}")
results.append({"id": point_id, "success": False, "error": str(e)})
# Eine kleine Verzögerung hinzufügen, um Ratenbegrenzung zu vermeiden
time.sleep(0.1)
return results
Hauptmigrationsfunktion¶
def migrate_qdrant_to_rememberizer(): offset = None total_migrated = 0
print("Migration von Qdrant zu Rememberizer startet...")
while True:
points, next_offset = fetch_points_from_qdrant(
QDRANT_COLLECTION_NAME,
BATCH_SIZE,
offset
)
if not points:
break
print(f"{len(points)} Punkte von Qdrant abgerufen")
results = upload_to_rememberizer(points)
success_count = sum(1 for r in results if r.get("success", False))
total_migrated += success_count
print(f"Fortschritt: {total_migrated} Punkte erfolgreich migriert")
if next_offset is None:
break
offset = next_offset
print(f"Migration abgeschlossen! Insgesamt {total_migrated} Punkte zu Rememberizer migriert")
Führen Sie die Migration durch¶
migrate_qdrant_to_rememberizer()¶
```
```javascript const { QdrantClient } = require('@qdrant/js-client-rest'); const axios = require('axios');
// Qdrant-Konfiguration const qdrantUrl = 'http://localhost:6333'; // oder Ihre Qdrant-Cloud-URL const qdrantApiKey = 'your_qdrant_api_key'; // falls Sie Qdrant Cloud verwenden 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-Größe Konfiguration const BATCH_SIZE = 100;
// Qdrant-Client initialisieren const qdrantClient = new QdrantClient({ url: qdrantUrl, apiKey: qdrantApiKey // Nur für Qdrant Cloud });
// Punkte von Qdrant abrufen async function fetchPointsFromQdrant(collectionName, batchSize, offset = 0) { try { // Sammlung Informationen abrufen const collectionInfo = await qdrantClient.getCollection(collectionName);
// Durch Punkte scrollen
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(Fehler beim Abrufen von Punkten aus Qdrant: ${error.message});
return { points: [], nextOffset: null };
}
}
// Vektoren zu Rememberizer hochladen async function uploadToRememberizer(points) { const headers = { 'x-api-key': rememberizerApiKey, 'Content-Type': 'application/json' };
const results = [];
for (const point of points) {
// Daten aus dem Qdrant-Punkt extrahieren
const pointId = point.id;
const metadata = point.payload || {};
const textContent = metadata.text || '';
const documentName = metadata.filename || qdrant_doc_${pointId};
if (!textContent) {
console.log(`Überspringe ${pointId} - kein Textinhalt im Payload gefunden`);
continue;
}
const data = {
name: documentName,
content: textContent,
// Optional: zusätzliche Metadaten einfügen
metadata: metadata
};
try {
const response = await axios.post(
`${baseUrl}/vector-stores/${vectorStoreId}/documents/text`,
data,
{ headers }
);
if (response.status === 201) {
console.log(`Dokument '${documentName}' erfolgreich hochgeladen!`);
results.push({ id: pointId, success: true });
} else {
console.error(`Fehler beim Hochladen des Dokuments ${documentName}: ${response.statusText}`);
results.push({ id: pointId, success: false, error: response.statusText });
}
} catch (error) {
console.error(`Fehler beim Hochladen des Dokuments ${documentName}: ${error.message}`);
results.push({ id: pointId, success: false, error: error.message });
}
// Eine kleine Verzögerung hinzufügen, um Ratenbegrenzung zu verhindern
await new Promise(resolve => setTimeout(resolve, 100));
}
return results; }
// Hauptmigrationsfunktion async function migrateQdrantToRememberizer() { try { console.log('Migration von Qdrant zu Rememberizer startet...');
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(`${points.length} Punkte von Qdrant abgerufen`);
const results = await uploadToRememberizer(points);
const successCount = results.filter(r => r.success).length;
totalMigrated += successCount;
console.log(`Fortschritt: ${totalMigrated} Punkte erfolgreich migriert`);
} while (offset !== null);
console.log(`Migration abgeschlossen! ${totalMigrated} insgesamt Punkte zu Rememberizer migriert`);
} catch (error) { console.error('Migration fehlgeschlagen:', error); } }
// Migration ausführen // migrateQdrantToRememberizer(); ```
Migration von Supabase pgvector¶
Wenn Sie bereits Supabase mit pgvector verwenden, ist die Migration zu Rememberizer besonders einfach, da beide PostgreSQL mit der pgvector-Erweiterung verwenden.
```python import psycopg2 import requests import json import time import os from dotenv import load_dotenv
Lade Umgebungsvariablen¶
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") # z.B. "vs_abc123" BASE_URL = "https://api.rememberizer.ai/api/v1"
Batch-Größe für die Verarbeitung¶
BATCH_SIZE = 100
Mit Supabase PostgreSQL verbinden¶
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"Fehler beim Verbinden mit Supabase PostgreSQL: {e}") return None
Dokumente von Supabase pgvector abrufen¶
def fetch_documents_from_supabase(conn, batch_size, offset=0): try: cursor = conn.cursor()
# Passen Sie diese Abfrage basierend auf Ihrer Tabellenstruktur an
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"Fehler beim Abrufen von Dokumenten von Supabase: {e}")
return []
Dokumente an Rememberizer hochladen¶
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
# Metadaten analysieren, wenn sie als JSON-String gespeichert sind
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"Überspringe {doc_id} - kein Inhalt gefunden")
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"Dokument '{document_name}' erfolgreich hochgeladen!")
results.append({"id": doc_id, "success": True})
else:
print(f"Fehler beim Hochladen des Dokuments {document_name}: {response.text}")
results.append({"id": doc_id, "success": False, "error": response.text})
except Exception as e:
print(f"Ausnahme beim Hochladen des Dokuments {document_name}: {str(e)}")
results.append({"id": doc_id, "success": False, "error": str(e)})
# Eine kleine Verzögerung hinzufügen, um eine Überlastung zu vermeiden
time.sleep(0.1)
return results
Hauptmigration Funktion¶
def migrate_supabase_to_rememberizer(): conn = connect_to_supabase() if not conn: print("Verbindung zu Supabase fehlgeschlagen. Migration wird abgebrochen.") return
offset = 0
total_migrated = 0
print("Migration von Supabase pgvector zu Rememberizer beginnt...")
try:
while True:
documents = fetch_documents_from_supabase(conn, BATCH_SIZE, offset)
if not documents:
break
print(f"{len(documents)} Dokumente von Supabase abgerufen")
results = upload_to_rememberizer(documents)
success_count = sum(1 for r in results if r.get("success", False))
total_migrated += success_count
print(f"Fortschritt: {total_migrated} Dokumente erfolgreich migriert")
offset += BATCH_SIZE
finally:
conn.close()
print(f"Migration abgeschlossen! Insgesamt {total_migrated} Dokumente nach Rememberizer migriert")
Führen Sie die Migration durch¶
migrate_supabase_to_rememberizer()¶
```
```javascript 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; // z.B. "vs_abc123" const baseUrl = 'https://api.rememberizer.ai/api/v1';
// Batch-Größe Konfiguration const BATCH_SIZE = 100;
// Dokumente von Supabase pgvector abrufen
async function fetchDocumentsFromSupabase(batchSize, offset = 0) {
try {
// Passen Sie diese Abfrage basierend auf Ihrer Tabellenstruktur an
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(Fehler beim Abrufen von Dokumenten aus Supabase: ${error.message});
return [];
}
}
// Dokumente zu Rememberizer hochladen async function uploadToRememberizer(documents) { const headers = { 'x-api-key': rememberizerApiKey, 'Content-Type': 'application/json' };
const results = [];
for (const doc of documents) { // Metadaten parsen, falls sie als JSON-String gespeichert sind 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(`Überspringe ${doc.id} - kein Inhalt gefunden`);
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}' erfolgreich hochgeladen!`);
results.push({ id: doc.id, success: true });
} else {
console.error(`Fehler beim Hochladen des Dokuments ${documentName}: ${response.statusText}`);
results.push({ id: doc.id, success: false, error: response.statusText });
}
} catch (error) {
console.error(`Fehler beim Hochladen des Dokuments ${documentName}: ${error.message}`);
results.push({ id: doc.id, success: false, error: error.message });
}
// Fügen Sie eine kleine Verzögerung hinzu, um eine Überlastung zu vermeiden
await new Promise(resolve => setTimeout(resolve, 100));
}
return results; }
// Hauptmigration Funktion async function migrateSupabaseToRememberizer() { try { console.log('Migration von Supabase pgvector zu Rememberizer startet...');
let offset = 0;
let totalMigrated = 0;
while (true) {
const documents = await fetchDocumentsFromSupabase(BATCH_SIZE, offset);
if (documents.length === 0) {
break;
}
console.log(`${documents.length} Dokumente von Supabase abgerufen`);
const results = await uploadToRememberizer(documents);
const successCount = results.filter(r => r.success).length;
totalMigrated += successCount;
console.log(`Fortschritt: ${totalMigrated} Dokumente erfolgreich migriert`);
offset += BATCH_SIZE;
}
console.log(`Migration abgeschlossen! ${totalMigrated} insgesamt Dokumente zu Rememberizer migriert`);
} catch (error) { console.error('Migration fehlgeschlagen:', error); } finally { await supabasePool.end(); } }
// Migration ausführen // migrateSupabaseToRememberizer(); ```
Migrationsbest Practices¶
Befolgen Sie diese Empfehlungen für eine erfolgreiche Migration:
- Vorausplanen:
- Schätzen Sie das Datenvolumen und die für die Migration benötigte Zeit
- Planen Sie die Migration während verkehrsärmerer Zeiten
-
Erhöhen Sie den Speicherplatz, bevor Sie große Migrationen starten
-
Zuerst Testen:
- Erstellen Sie einen Test-Vektor-Speicher in Rememberizer
- Migrieren Sie eine kleine Teilmenge von Daten (100-1000 Vektoren)
-
Überprüfen Sie die Suchfunktionalität mit wichtigen Abfragen
-
Datenvalidierung:
- Vergleichen Sie die Dokumentenzahlen vor und nach der Migration
- Führen Sie Benchmark-Abfragen durch, um ähnliche Ergebnisse sicherzustellen
-
Validieren Sie, dass Metadaten korrekt erhalten bleiben
-
Leistung optimieren:
- Verwenden Sie Batch-Operationen für Effizienz
- Berücksichtigen Sie die geografische Nähe von Quell- und Ziel-Datenbanken
-
Überwachen Sie die API-Ratenlimits und passen Sie die Batch-Größen entsprechend an
-
Nach der Migration:
- Überprüfen Sie die Indexerstellung in Rememberizer
- Aktualisieren Sie die Anwendungs-Konfigurationen, um auf den neuen Vektor-Speicher zu verweisen
- Halten Sie die Quell-Datenbank als Backup, bis die Migration verifiziert ist
Für detaillierte API-Referenzen und Endpunktdokumentationen besuchen Sie die vector-store-Seite.
Stellen Sie sicher, dass Sie die API-Schlüssel sicher verwalten und bewährte Praktiken für das Management von API-Schlüsseln befolgen.