Speichern und Abfragen von Einbettungen mit pgvector

Abgeschlossen

Vektoreinbettungen transformieren Text, Bilder und andere Inhalte in numerische Darstellungen, die die semantische Bedeutung erfassen. Azure Database for PostgreSQL unterstützt das Speichern und Abfragen dieser Einbettungen über die pgvector-Erweiterung, sodass Sie Ihrer vorhandenen PostgreSQL-Datenbank Vektorsuchfunktionen hinzufügen können, ohne einen separaten Vektorspeicher zu verwalten.

Diese Einheit behandelt die Aktivierung der pgvector-Erweiterung, das Entwerfen von Schemas für die Vektorspeicherung, das Einfügen und Aktualisieren von Einbettungen und das Ausführen grundlegender Ähnlichkeitsabfragen. Diese grundlegenden Vorgänge bilden die Grundlage für die Erstellung semantischer Such- und Abruffunktionen in Ihren KI-Anwendungen.

Aktivieren der pgvector-Erweiterung

Die pgvector-Erweiterung fügt Vektordatentypen und Ähnlichkeitssuchoperatoren zu PostgreSQL hinzu. Bevor Sie Einbettungen speichern können, müssen Sie die Erweiterung in Ihrer Datenbank aktivieren. Azure Database for PostgreSQL umfasst pgvector als eine der unterstützten Erweiterungen, sodass sie ohne zusätzliche Installation zur Verfügung gestellt wird.

Um pgvector zu aktivieren, stellen Sie eine Verbindung mit Ihrer Datenbank her, und führen Sie den CREATE EXTENSION Befehl aus. Sie benötigen die entsprechenden Berechtigungen zum Erstellen von Erweiterungen, die normalerweise dem Serveradministrator oder den Benutzern mit der azure_pg_admin Rolle erteilt werden.

CREATE EXTENSION IF NOT EXISTS vector;

Nach dem Aktivieren der Erweiterung können Sie überprüfen, ob sie verfügbar ist, indem Sie die installierten Erweiterungen abfragen:

SELECT * FROM pg_extension WHERE extname = 'vector';

Die pgvector-Erweiterung führt den vector Datentyp ein, der Einbettungen als Arrays von Gleitkommazahlen mit einfacher Genauigkeit speichert. Jeder Vektor verfügt über eine feste Anzahl von Dimensionen, die Sie beim Erstellen einer Spalte angeben. Die Erweiterung stellt außerdem Operatoren zum Berechnen von Abständen zwischen Vektoren und Indextypen für schnelle Ähnlichkeitssuche bereit.

Designschemas für Vektorspeicher

Ein effektives Schemadesign für Vektorspeicher kombiniert Einbettungen mit den Metadaten, die Ihre Anwendung zum Filtern und Anzeigen benötigt. Wenn Sie eine Vektorspalte definieren, geben Sie die Anzahl der Dimensionen mithilfe der vector(n) Syntax an, wobei n sie mit der Ausgabedimension Ihres Einbettungsmodells übereinstimmen muss.

Allgemeine Einbettungsabmessungen variieren je nach Modell. Satztransformatorenmodelle erzeugen in der Regel 384-dimensionale Vektoren. Das OpenAI-Modell "text-embedding-ada-002" gibt 1.536 Dimensionen aus, während text-embedding-3-large bis zu 3.072 Dimensionen erzeugen kann. Die Verwendung der falschen Dimensionsanzahl verursacht Einfügefehler. Überprüfen Sie daher die Ausgabedimension Ihres Modells, bevor Sie Tabellen erstellen.

Im folgenden Beispiel wird eine Tabelle erstellt, in der legale Dokumente mit Einbettungen zusammen mit Metadaten gespeichert werden, die zum Filtern und Anzeigen nützlich sind:

CREATE TABLE documents (
    id SERIAL PRIMARY KEY,
    title TEXT NOT NULL,
    content TEXT,
    category TEXT,
    practice_area TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW(),
    embedding vector(1536)
);

Dieses Schema speichert das Einbetten des Dokuments in derselben Zeile wie seine Metadaten. Dieser Ansatz vereinfacht Abfragen, da Sie keine Verknüpfungen zum Abrufen der ähnlichen Dokumente und deren Details benötigen. Bei großen Inhaltsfeldern sollten Sie den vollständigen Text in einer separaten Tabelle speichern und nur Zusammenfassungen oder Titel in der Haupttabelle beibehalten, um die übertragenen Daten bei Ähnlichkeitssuchen zu reduzieren.

Beim Entwerfen für mehrere Einbettungsmodelle oder das Einbetten verschiedener Inhaltstypen (z. B. Titel und vollständiger Inhalt) können Sie mehrere Vektorspalten hinzufügen:

CREATE TABLE documents (
    id SERIAL PRIMARY KEY,
    title TEXT NOT NULL,
    content TEXT,
    title_embedding vector(384),
    content_embedding vector(1536)
);

Einfügen und Aktualisieren von Einbettungen

Nachdem Sie Ihr Schema erstellt haben, fügen Sie Einbettungen mithilfe von SQL-Standardanweisungen INSERT ein. Vektoren werden als Zeichenfolgenliterale im Arrayformat dargestellt und in den vector-Typ umgewandelt. Ihr Anwendungscode generiert die Einbettung mithilfe einer Einbettungs-API (z. B. Azure OpenAI) und übergibt sie als Parameter an die Datenbank.

INSERT INTO documents (title, content, category, practice_area, embedding)
VALUES (
    'Corporate Merger Agreement Template',
    'This agreement outlines the terms and conditions for the merger of...',
    'contracts',
    'corporate',
    '[0.0123, -0.0456, 0.0789, -0.0321, ...]'::vector
);

Verwenden Sie für Batcheinfügungen beim Laden großer Datensätze Mehrzeilenanweisungen INSERT oder den COPY-Befehl für eine bessere Leistung.

INSERT INTO documents (title, content, category, embedding)
VALUES
    ('Document 1', 'Content...', 'legal', '[...]'::vector),
    ('Document 2', 'Content...', 'legal', '[...]'::vector),
    ('Document 3', 'Content...', 'legal', '[...]'::vector);

Aktualisieren Sie beim Ändern von Dokumentinhalten die Einbettung so, dass sie die neue semantische Bedeutung widerspiegelt:

UPDATE documents
SET content = 'Updated document content...',
    embedding = '[0.0234, -0.0567, ...]'::vector,
    updated_at = NOW()
WHERE id = 42;

Bei Anwendungen mit häufigen Updates sollten Sie die Batch-Regeneration von Einbettungen während der Nebenzeiten in Betracht ziehen, anstatt Einbettungen synchron mit Inhaltsänderungen zu aktualisieren. Dieser Ansatz reduziert die Latenz für Inhaltsupdates und konsolidiert Aufrufe der Einbettungs-API.

Abfragevektoren mit Entfernungsoperatoren

Die pgvector-Erweiterung bietet drei Entfernungsoperatoren zur Messung der Ähnlichkeit zwischen Vektoren. Jeder Operator berechnet einen anderen Abstandstyp, und die Auswahl des richtigen ist von Ihrem Einbettungsmodell und Anwendungsfall abhängig.

L2-Abstand (Euklidischer Abstand) misst den geraden Abstand zwischen zwei Vektoren im Einbettungsraum. Verwenden Sie den Operator für den <-> L2-Abstand. Kleinere Werte deuten auf ähnliche Vektoren hin. Diese Metrik funktioniert gut, wenn die Größe von Vektoren Bedeutung trägt.

SELECT id, title, embedding <-> '[0.0123, -0.0456, ...]'::vector AS distance
FROM documents
ORDER BY distance
LIMIT 10;

Der Kosinusabstand misst den Winkel zwischen zwei Vektoren, wobei dessen Größe ignoriert wird. Verwenden Sie den Operator für den <=> Kosinusabstand. Werte reichen von 0 (identische Richtung) bis 2 (entgegengesetzte Richtung). Kosinusabstand ist die am häufigsten verwendete Wahl für Texteinbettungen, da sie sich auf die Richtung der Bedeutung und nicht auf die Länge des Vektors konzentriert.

SELECT id, title, embedding <=> '[0.0123, -0.0456, ...]'::vector AS distance
FROM documents
ORDER BY distance
LIMIT 10;

Das negative innere Produkt berechnet das Punktprodukt von zwei Vektoren und negiert es. Verwenden Sie den <#> Operator. Diese Metrik ist nützlich für die maximale interne Produktsuche, bei der größere Punkteprodukte auf ähnliche Vektoren hinweisen. Die Negation wandelt sie in einen Abstand um, in dem kleinere Werte besser sind und dem Verhalten der anderen Operatoren entsprechen.

SELECT id, title, embedding <#> '[0.0123, -0.0456, ...]'::vector AS distance
FROM documents
ORDER BY distance
LIMIT 10;

Die meisten Einbettungsmodelle, einschließlich der Einbettungen von OpenAI, sind für Kosinusgleichheit optimiert. Überprüfen Sie die Dokumentation des Einbettungsmodells, um zu überprüfen, welche Entfernungsmetrik empfohlen wird.

Vektordatentypen und Genauigkeit

Die pgvector-Erweiterung bietet drei Datentypen zum Speichern von Vektoren, jeweils mit unterschiedlichen Speicher- und Leistungsmerkmalen.

Der Vektortyp speichert Elemente als Gleitkommazahlen mit einfacher Genauigkeit (32-Bit). Dies ist der Standardtyp für die meisten Anwendungsfälle und bietet eine gute Balance zwischen Präzision und Speichereffizienz. Ein 1536-dimensionaler Vektor verwendet ca. 6 KB Speicherplatz.

Der Halfvec-Typ speichert Elemente als Gleitkommazahlen mit halber Genauigkeit (16-Bit). Dieser Typ reduziert den Speicherbedarf im Vergleich zu vector um die Hälfte und erhält dabei für die meisten Ähnlichkeitssuchaufgaben eine ausreichende Genauigkeit. Verwenden Sie halfvec, wenn die Speicherung ein Problem darstellt und Sie überprüft haben, dass sich die verringerte Präzision nicht erheblich auf die Suchqualität auswirkt.

CREATE TABLE documents_compact (
    id SERIAL PRIMARY KEY,
    title TEXT NOT NULL,
    embedding halfvec(1536)
);

Der sparsevec-Typ speichert spärliche Vektoren, bei denen die meisten Elemente null sind. Statt alle Dimensionen zu speichern, speichert sie nur die Nichtzerowerte und deren Positionen. Dieser Typ ist nützlich für Modelle, die geringe Einbettungen erzeugen, z. B. bestimmte Dokumentdarstellungen. Geben Sie bei der Erstellung der Spalte die maximale Maßzahl an.

CREATE TABLE sparse_documents (
    id SERIAL PRIMARY KEY,
    title TEXT NOT NULL,
    embedding sparsevec(10000)
);

Hinweis

HNSW-Indizes für sparsevec Spalten unterstützen bis zu 1.000 Nicht-Null-Elemente. Wenn Ihre geringen Vektoren diesen Grenzwert überschreiten, sollten Sie die Dimensionalitätsreduktion oder alternative Indizierungsstrategien in Betracht ziehen.

Für die meisten KI-Anwendungen, die dichte Einbettungen aus Modellen wie OpenAI oder Satztransformatoren verwenden, verwenden Sie den Standardtyp vector . Berücksichtigen Sie halfvec nur, nachdem das Benchmarking bestätigt hat, dass die Halbgenauigkeit für Ihren spezifischen Anwendungsfall eine akzeptable Suchqualität bietet.