Insluitingen opslaan en er query's op uitvoeren met pgvector

Voltooid

Vector embeddings transformeren tekst, afbeeldingen en andere inhoud in numerieke representaties die semantische betekenis vastleggen. Azure Database for PostgreSQL biedt ondersteuning voor het opslaan en opvragen van deze insluitingen via de pgvector-extensie, zodat u vectorzoekmogelijkheden kunt toevoegen aan uw bestaande PostgreSQL-database zonder dat u een afzonderlijk vectorarchief hoeft te beheren.

In deze les wordt beschreven hoe u de pgvector-extensie inschakelt, schema's voor vectoropslag ontwerpt, invoegt en bijwerkt en eenvoudige overeenkomstenquery's uitvoert. Deze basisbewerkingen vormen de basis voor het bouwen van semantische zoek- en ophaalfuncties in uw AI-toepassingen.

De pgvector-extensie inschakelen

De pgvector-extensie voegt vectorgegevenstypen en overeenkomstenzoekoperators toe aan PostgreSQL. Voordat u insluitingen kunt opslaan, moet u de extensie inschakelen in uw database. Azure Database for PostgreSQL bevat pgvector als een van de ondersteunde extensies, waardoor deze beschikbaar is zonder extra installatie.

Als u pgvector wilt inschakelen, maakt u verbinding met uw database en voert u de CREATE EXTENSION opdracht uit. U hebt de juiste machtigingen nodig om extensies te maken, die doorgaans worden verleend aan de serverbeheerder of gebruikers met de azure_pg_admin rol.

CREATE EXTENSION IF NOT EXISTS vector;

Nadat u de extensie hebt ingeschakeld, kunt u controleren of deze beschikbaar is door een query uit te voeren op de geïnstalleerde extensies:

SELECT * FROM pg_extension WHERE extname = 'vector';

De pgvector-extensie introduceert het vector gegevenstype, waarin insluitingen worden opgeslagen als matrices van drijvendekommagetallen met één precisie. Elke vector heeft een vast aantal dimensies die u opgeeft bij het maken van een kolom. De extensie biedt ook operators voor het berekenen van afstanden tussen vectoren en indextypen voor snelle overeenkomsten zoeken.

Schema's ontwerpen voor vectoropslag

Effectief schemaontwerp voor vectoropslag combineert insluitingen met de metagegevens die uw toepassing nodig heeft voor filteren en weergeven. Wanneer u een vectorkolom definieert, geeft u het aantal dimensies op met behulp van de vector(n) syntaxis, waar n de uitvoerdimensie van het insluitmodel moet overeenkomen.

Algemene insluitingsdimensies variëren per model. Transformatormodellen voor zinnen produceren doorgaans 384 dimensionale vectoren. Het model tekst-insluiten-ada-002 van OpenAI levert 1536 dimensies, terwijl tekst-insluiten-3-groot maximaal 3072 dimensies kan produceren. Als u het verkeerde aantal dimensies gebruikt, worden er invoegfouten veroorzaakt, dus controleer de uitvoerdimensie van uw model voordat u tabellen maakt.

In het volgende voorbeeld wordt een tabel gemaakt waarin juridische documenten met insluitingen naast metagegevens worden opgeslagen die handig zijn voor filteren en weergeven:

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)
);

In dit schema wordt het document ingesloten in dezelfde rij als de metagegevens. Deze aanpak vereenvoudigt query's omdat u geen joins nodig hebt om zowel de vergelijkbare documenten als de bijbehorende gegevens op te halen. Voor grote inhoudsvelden kunt u overwegen om de volledige tekst in een afzonderlijke tabel op te slaan en alleen samenvattingen of titels in de hoofdtabel te bewaren om de gegevens die worden overgedragen tijdens zoekopdrachten naar overeenkomsten te verminderen.

Bij het ontwerpen voor meerdere insluitmodellen of het insluiten van verschillende inhoudstypen (zoals titels versus volledige inhoud), kunt u meerdere vectorkolommen toevoegen:

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

Insluitingen invoegen en bijwerken

Nadat u uw schema hebt gemaakt, voegt u insluitingen in met behulp van standaard SQL-instructies INSERT . Vectoren worden weergegeven als letterlijke tekenreeksen in array-indeling en omgezet naar het vector type. Uw toepassingscode genereert het insluiten met behulp van een insluit-API (zoals Azure OpenAI) en geeft deze als parameter door aan de database.

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
);

Voor batchinvoegingen bij het laden van grote gegevenssets gebruikt u instructies met meerdere rijen INSERT of de COPY opdracht voor betere prestaties:

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

Wanneer documentinhoud wordt gewijzigd, werkt u de insluiting bij zodat deze overeenkomt met de nieuwe semantische betekenis:

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

Voor toepassingen met frequente updates kunt u overwegen om tijdens daluren batchgewijs insluiten opnieuw in te sluiten in plaats van insluitingen synchroon bij te werken met wijzigingen in inhoud. Deze aanpak vermindert de latentie voor inhoudsupdates en consolideert aanroepen naar de insluit-API.

Queryvectoren met afstandsoperatoren

De pgvector-extensie biedt drie afstandsoperatoren voor het meten van overeenkomsten tussen vectoren. Elke operator berekent een ander type afstand en het kiezen van de juiste is afhankelijk van uw insluitingsmodel en gebruiksvoorbeeld.

L2 afstand (Euclidische afstand) meet de rechte lijnafstand tussen twee vectoren in de insluitruimte. Gebruik de <-> operator voor L2-afstand. Kleinere waarden geven meer vergelijkbare vectoren aan. Deze metrische waarde werkt goed wanneer de omvang van vectoren betekenis heeft.

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

Cosinusafstand meet de hoek tussen twee vectoren, waarbij hun grootten worden genegeerd. Gebruik de <=> operator voor cosinusafstand. Waarden variëren van 0 (identieke richting) tot 2 (tegenovergestelde richtingen). Cosinusafstand is de meest voorkomende keuze voor tekstinsluitingen, omdat deze zich richt op de richting van betekenis in plaats van de lengte van de vector.

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

Negatief binnenproduct berekent het puntproduct van twee vectoren en negeert het. Gebruik de <#> operator. Deze metrische waarde is handig voor het maximale zoeken naar binnenste producten, waarbij grotere puntproducten meer vergelijkbare vectoren aangeven. De negatie converteert deze naar een afstand waar kleinere waarden beter zijn, wat overeenkomt met het gedrag van de andere operators.

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

De meeste insluitingsmodellen, waaronder de insluitingen van OpenAI, zijn geoptimaliseerd voor cosinus-overeenkomsten. Controleer de documentatie van uw insluitmodel om te controleren welke metrische afstandsgegevens het aanbeveelt.

Vectorgegevenstypen en -precisie

De pgvector-extensie biedt drie gegevenstypen voor het opslaan van vectoren, elk met verschillende opslag- en prestatiekenmerken.

Het vectortype slaat elementen op als drijvendekommanummers met één precisie (32-bits). Dit is het standaardtype voor de meeste gebruiksvoorbeelden en biedt een goede balans tussen precisie en opslagefficiëntie. Een 1536-dimensionale vector maakt gebruik van ongeveer 6 kB aan opslag.

Het type halfvec slaat elementen op als halfprecisie (16-bits) drijvendekommanummers. Dit type vermindert de opslag met de helft in vergelijking met vector en behoudt voldoende precisie voor de meeste zoektaken op overeenkomsten. Gebruik halfvec deze functie wanneer opslag een probleem is en u hebt gecontroleerd of verminderde precisie geen aanzienlijke invloed heeft op uw zoekkwaliteit.

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

Het sparsevec-type slaat sparse vectoren op waarbij de meeste elementen nul zijn. In plaats van alle dimensies op te slaan, worden alleen de niet-nulwaarden en hun posities opgeslagen. Dit type is handig voor modellen die geparseerde insluitingen produceren, zoals bepaalde documentweergaven. Geef het maximumaantal dimensies op bij het maken van de kolom.

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

Opmerking

HNSW-indexen op sparsevec kolommen ondersteunen maximaal 1000 niet-nulelementen. Als uw sparse vectoren deze limiet overschrijden, kunt u dimensionaliteitsreductie of alternatieve indexeringsstrategieën overwegen.

Voor de meeste AI-toepassingen die gebruikmaken van dichte insluitingen van modellen zoals OpenAI of zinnentransformatoren, gebruikt u het standaardtype vector . Overweeg halfvec pas nadat benchmarking bevestigt dat halve precisie acceptabele zoekkwaliteit biedt voor uw specifieke use-case.