INTEGRITY Dokumentace

Vkládání vektorů

Do indexů Vectorize můžete vektory vkládat kdykoli: Vectorize na pozadí index optimalizuje, takže vyhledávání ve vektorech zůstává efektivní i při přidávání nových nebo aktualizaci stávajících vektorů.

Podporované formáty vektorů

Vectorize podporuje vkládání a upsert vektorů ve třech formátech:

Ve většině případů number[] pole je nejjednodušší při práci s jinými API a je návratovým typem většiny API pro strojové učení.

Vectorize ukládá i vrací vektorové dimenze ve formátu Float32; dimenze zadané ve formátu Float64 se před uložením převedou na Float32.

Metadata

Metadata jsou volitelná sada dvojic klíč-hodnota, kterou lze k vektoru připojit při vložení nebo upsertu. Umožňují tak uložit data o samotném vektoru přímo v něm nebo společně s ním.

Klíče metadat nesmí být prázdné, obsahovat znak tečky (.), obsahovat znak dvojité uvozovky ("), nebo začínat znakem dolaru ($).

Metadata lze použít k:

Vektorový embedding reprezentující obrázek může například obsahovat cestu k objekt R2 ze kterého byl vygenerován, formát a vyhledávání kategorie:

{ id: '1', values: [32.4, 74.1, 3.2, ...], metadata: { path: 'r2://bucket-name/path/to/image.png', format: 'png', category: 'profile_image' } }

Tipy pro výkon při filtrování podle metadat

Při vytváření indexů metadat pro rozsáhlý index Vectorize doporučujeme předem promyslet, jak budete vektory podle těchto metadat filtrovat při dotazování.

Pečlivě zvažte kardinalitu hodnot metadat ve vztahu ke svým dotazům. Kardinalita udává míru jedinečnosti hodnot dat v rámci množiny. Nízká kardinalita znamená, že existuje jen málo unikátních hodnot: například počet planet ve sluneční soustavě; počet zemí na světě. Vysoká kardinalita znamená mnoho unikátních hodnot: řetězce UUIv4; časová razítka s přesností na milisekundy.

Vysoká kardinalita je výhodná pro selektivitu operátoru rovná se ($eq) filtr. Pokud chcete například najít vektory patřící k ID jednoho uživatele. Filtr ale nepomůže, pokud mají všechny vektory stejnou hodnotu. Jde o příklad extrémně nízké kardinality.

Vysoká kardinalita může ovlivnit i rozsahové dotazy, které prohledávají více jedinečných hodnot metadat. Pokud například indexovaná hodnota metadat používá časová razítka v milisekundách, výkon klesne v případě, že rozsah pokrývá dlouhé časové období, během něhož bylo zapsáno tisíce vektorů s jedinečnými časovými razítky.

Vectorize na pozadí používá reverzní index, který mapuje hodnoty na ID vektorů. Pokud je počet unikátních hodnot v daném rozsahu příliš vysoký, vyžaduje to čtení velkých částí indexu, v nejhorším případě jeho úplné prohledání. To by mohlo vést k problémům s pamětí, a proto Vectorize v takovém případě sníží výkon i přesnost dotazu, aby požadavek dokončil.

Jedním z přístupů k datům s vysokou kardinalitou je vytvořit skupiny (buckets), do kterých se seskupí více vektorů se stejnou hodnotou. Pokud navážeme na příklad s časovým razítkem v milisekundách, představme si, že běžně filtrujeme podle datových rozsahů s granularitou 5 minut. Časové razítko můžeme zaokrouhlit dolů na nejbližší interval 5 minut. Tím se hodnoty metadat rozdělí do 5minutových "oken". Původní časové razítko v milisekundách si přitom můžeme ponechat jako samostatné neindexované pole.

Jmenné prostory

Namespace umožňují rozdělit vektory v rámci indexu do segmentů, například podle zákazníka, obchodníka nebo ID obchodu.

Chcete-li vektory přiřadit k jmennému prostoru, můžete volitelně uvést namespace: string hodnotu při provádění operace insert nebo upsert. Při dotazování můžete jako volitelný parametr dotazu předat namespace, ve kterém se má vyhledávat.

Jmenný prostor může mít délku až 64 znaků (bajtů) a na jeden index můžete mít až 1,000 jmenných prostorů. Více informací najdete v Limity dokumentaci, kde najdete další podrobnosti.

Pokud je v operaci dotazování zadán namespace, do vyhledávání se zapojí pouze vektory z tohoto namespace. Filtrování podle namespace se uplatní ještě před samotným vyhledáváním ve vektorech, což zvyšuje přesnost výsledků.

Chcete-li vložit vektory se jmenným prostorem:

// Mock vectors
// Vectors from a machine-learning model are typically ~100 to 1536 dimensions
// wide (or wider still).
const sampleVectors: Array<VectorizeVector> = [
	{
		id: "1",
		values: [32.4, 74.1, 3.2, ...],
		namespace: "text",
	},
	{
		id: "2",
		values: [15.1, 19.2, 15.8, ...],
		namespace: "images",
	},
	{
		id: "3",
		values: [0.16, 1.2, 3.8, ...],
		namespace: "pdfs",
	},
];

// Insert your vectors, returning a count of the vectors inserted and their vector IDs.
let inserted = await env.TUTORIAL_INDEX.insert(sampleVectors);

Chcete-li dotazovat vektory v rámci jmenného prostoru:

// Your queryVector will be searched against vectors within the namespace (only)
let matches = await env.TUTORIAL_INDEX.query(queryVector, {
	namespace: "images",
});

Zlepšení propustnosti zápisu

Jedním ze způsobů, jak zkrátit dobu, za kterou se aktualizace projeví ve výsledcích dotazů, je seskupit více vektorů do menšího počtu požadavků. To je důležité zejména u zátěže s vysokým podílem zápisů. Kolik vektorů lze zapsat v jednom požadavku, zjistíte v Limity stránce.

Vectorize kvůli trvanlivosti zapisuje změny ihned do write ahead logu. Aby se tyto zápisy projevily i při čtení, musí asynchronní úloha načíst aktuální soubory indexu z R2, vytvořit aktualizovaný index, zapsat nové soubory indexu zpět do R2 a změnu potvrdit. Aby zůstala režie zápisů nízká a zvýšila se jejich propustnost, Vectorize spojuje více změn do jedné dávky. Maximální velikost dávky je 200,000 vektorů celkem nebo 1,000 jednotlivých aktualizací, podle toho, který limit nastane dřív.

Uveďme si příklad: máme 250,000 vektorů, které chceme vložit do indexu. Rozhodneme se je vkládat po jednom, takže insert API zavoláme celkem 250,000krát. Vectorize ale v každé úloze zpracuje jen 1000 vektorů, takže bude potřeba projít celkem 250 úloh. Celý proces tak může trvat přinejmenším hodinu.

Lepším přístupem je dávkové zpracování aktualizací. Můžeme si například rozdělit 250,000 vektorů do 100 souborů, přičemž každý soubor bude obsahovat 2,500 vektorů. HTTP API pro vkládání bychom zavolali 100krát. Vectorize by index aktualizoval jen ve 2 až 3 úlohách. Všech 250,000 vektorů bude v dotazech viditelných během několika minut.

Příklady

Workers API

Použijte insert() a upsert() metody dostupné na indexu z Cloudflare Workeru k vložení vektorů do aktuálního indexu.

// Mock vectors
// Vectors from a machine-learning model are typically ~100 to 1536 dimensions
// wide (or wider still).
const sampleVectors: Array<VectorizeVector> = [
	{
		id: "1",
		values: [32.4, 74.1, 3.2, ...],
		metadata: { url: "/products/sku/13913913" },
	},
	{
		id: "2",
		values: [15.1, 19.2, 15.8, ...],
		metadata: { url: "/products/sku/10148191" },
	},
	{
		id: "3",
		values: [0.16, 1.2, 3.8, ...],
		metadata: { url: "/products/sku/97913813" },
	},
];

// Insert your vectors, returning a count of the vectors inserted and their vector IDs.
let inserted = await env.TUTORIAL_INDEX.insert(sampleVectors);

Viz Vectorize API pro další příklady.

wrangler CLI

Vektorové embeddingy můžete nahrát přímo hromadně:

Příklad souboru ve formátu NDJSON:

{ "id": "4444", "values": [175.1, 167.1, 129.9], "metadata": {"url": "/products/sku/918318313"}}
{ "id": "5555", "values": [158.8, 116.7, 311.4], "metadata": {"url": "/products/sku/183183183"}}
{ "id": "6666", "values": [113.2, 67.5, 11.2], "metadata": {"url": "/products/sku/717313811"}}
wrangler vectorize insert <your-index-name> --file=embeddings.ndjson

HTTP API

Vectorize také umožňuje vkládat vektory přes REST API, což vám umožňuje pracovat s indexem Vectorize pomocí stávajících nástrojů a jazyků pro strojové učení (včetně Pythonu).

Chcete-li například vložit embeddingy v Formát NDJSON přímo z Python skriptu:

import requests

url = "https://api.cloudflare.com/client/v4/accounts/{}/vectorize/v2/indexes/{}/insert".format("your-account-id", "index-name")

headers = {
    "Authorization": "Bearer <your-api-token>"
}

with open('embeddings.ndjson', 'rb') as embeddings:
    resp = requests.post(url, headers=headers, files=dict(vectors=embeddings))
    print(resp)

Tento kód vloží vektory definované v embeddings.ndjson do zadaného indexu. Knihovny Pythonu, včetně Pandas, také podporují formát NDJSON prostřednictvím vestavěné read_json metoda:

import pandas as pd
data = pd.read_json('embeddings.ndjson', lines=True)