← Cloudflare Vectorize / vectorize / best-practices
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:
- Pole čísel s plovoucí desetinnou čárkou (převedené na JavaScript
number[]pole). - A Float32Array ↗
- A Float64Array ↗
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:
- Zahrnutí klíče úložiště objektů, UUID databáze nebo jiného identifikátoru pro vyhledání obsahu, který vektorový embedding reprezentuje.
- Ukládejte data JSON (až do limity metadat), což vám může u menšího obsahu umožnit vynechat další vyhledávání.
- Sledování dat, časových razítek nebo jiných metadat popisujících, kdy nebo jak byl vektorový embedding vygenerován.
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ě:
- Soubor musí být ve formátu JSON odděleného novými řádky (formát NDJSON): každý úplný vektor musí být oddělen novým řádkem, nikoli uzavřen v poli nebo objektu.
- Vektory musí být kompletní a obsahovat jedinečný řetězec
idna vektor.
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.ndjsonHTTP 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)