INTEGRITY Dokumentace

Úvod do Vectorize

Vectorize je vektorová databáze společnosti Cloudflare. Vektorové databáze umožňují pomocí modelů strojového učení (ML) provádět sémantické vyhledávání, doporučování, klasifikaci a detekci anomálií a také poskytovat kontext jazykovým modelům LLM (Large Language Models).

Tento návod vás provede:

Předpoklady

Pro pokračování budete potřebovat:

  1. Zaregistrujte si účet Cloudflare ↗ pokud jste to ještě neudělali.
  2. Nainstalujte npm ↗.
  3. Nainstalujte Node.js ↗. Použijte správce verzí Node, například Volta ↗ nebo nvm ↗ abyste se vyhnuli problémům s oprávněními a mohli měnit verze Node.js. Wrangler vyžaduje verzi Node 16.17.0 nebo novější.

1. Vytvořte Worker

Vytvoříte nový projekt, který bude obsahovat Worker sloužící jako klientská aplikace pro váš index Vectorize.

Vytvořte nový projekt s názvem vectorize-tutorial spuštěním:

npm create cloudflare@latest -- vectorize-tutorial

Při nastavení vyberte následující možnosti:

Tímto vytvoříte nový vectorize-tutorial adresáři. Váš nový vectorize-tutorial adresář bude obsahovat:

2. Vytvořte index

Vektorová databáze se liší od tradiční SQL nebo NoSQL databáze. Je navržena tak, aby ukládala vektorové embeddingy, tedy reprezentace dat, nikoli data samotná.

Chcete-li vytvořit svůj první index Vectorize, přejděte do adresáře, který jste právě vytvořili pro svůj projekt Workers:

cd vectorize-tutorial

Chcete-li vytvořit index, budete muset použít wrangler vectorize create příkaz a zadejte název indexu. Vhodný název indexu:

Kromě toho budete muset definovat dimensions vektorů, které budete ukládat v indexu, a také vzdálenost metric použitá k určení podobných vektorů při vytváření indexu. Skóre metric může být euklidovská, kosinová nebo skalární součin (dot product). Tuto konfiguraci nelze později změnit, protože vektorová databáze je nakonfigurována pro pevně danou konfiguraci vektorů.

Spusťte následující wrangler vectorize příkaz:

npx wrangler vectorize create tutorial-index --dimensions=32 --metric=euclidean
🚧 Creating index: 'tutorial-index'
✅ Successfully created a new Vectorize index: 'tutorial-index'
📋 To start querying from a Worker, add the following binding configuration into 'wrangler.toml':

[[vectorize]]
binding = "VECTORIZE" # available in your Worker on env.VECTORIZE
index_name = "tutorial-index"

Výše uvedený příkaz vytvoří novou vektorovou databázi a vypíše binding konfiguraci potřebnou v dalším kroku.

3. Připojte svůj Worker ke svému indexu

Aby se váš Worker mohl připojit k indexu Vectorize, musíte vytvořit binding. Bindings umožňují vašim Workerům přistupovat k prostředkům, jako je Vectorize nebo R2, z Cloudflare Workers. Bindingy vytvoříte úpravou souboru Wrangler daného workeru.

Chcete-li index svázat s Workerem, přidejte na konec souboru Wrangler následující:

{
	"vectorize": [
		{
			"binding": "VECTORIZE", // available in your Worker on env.VECTORIZE
			"index_name": "tutorial-index"
		}
	]
}
[[vectorize]]
binding = "VECTORIZE"
index_name = "tutorial-index"

Konkrétně:

4. [Volitelné] Vytvořte indexy metadat

Vectorize umožňuje přidat k jednomu vektoru v indexu až 10KiB metadat a následně podle nich při dotazování vektory filtrovat. K tomu je potřeba dané pole metadat v indexu Vectorize označit jako „metadata index“.

Chcete-li povolit filtrování vektorů podle metadatového pole během dotazu, použijte příkaz podobný tomuto:

npx wrangler vectorize create-metadata-index tutorial-index --property-name=url --type=string
📋 Creating metadata index...
✅ Successfully enqueued metadata index creation request. Mutation changeset identifier: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.

Zde url je pole metadat, u kterého bude povoleno filtrování. Vlastnost --type parametr definuje datový typ pole metadat; string, number a boolean typy jsou podporovány.

Vytvoření indexu metadat obvykle trvá několik sekund. Seznam indexů metadat pro váš index Vectorize můžete zkontrolovat spuštěním:

npx wrangler vectorize list-metadata-index tutorial-index
📋 Fetching metadata indexes...
┌──────────────┬────────┐
│ propertyName │ type   │
├──────────────┼────────┤
│ url          │ String │
└──────────────┴────────┘

Pro každý index Vectorize můžete vytvořit až 10 metadatových indexů.

U metadatových indexů typu number, je přesnost indexovaného čísla float64.

U metadatových indexů typu string, každý vektor indexuje prvních 64 B textových dat oříznutých na hranicích znaků UTF-8 na nejdelší platný podřetězec UTF-8 v rámci tohoto limitu, takže vektory lze filtrovat podle prvních 64 B hodnoty každé indexované vlastnosti.

Viz Limity Vectorize pro úplný seznam limitů.

5. Vložte vektory

Než budete moci vektorovou databázi dotazovat, musíte do ní vložit vektory, vůči kterým se bude dotazovat. Tyto vektory by se běžně generovaly z dat, například textu nebo obrázků, která předáte modelu strojového učení. V tomto tutoriálu ale použijeme statické vektory, abychom ukázali, jak vektorové vyhledávání funguje samo o sobě.

Nejprve přejděte na svůj vectorize-tutorial Worker a otevřete src/index.ts soubor. index.ts je soubor, ve kterém konfigurujete interakce vašeho Workeru s indexem Vectorize.

Vymažte obsah index.ts, a vložte následující úryvek kódu do svého index.ts soubor. Na env parametru nahraďte <BINDING_NAME> hodnotou VECTORIZE:

export interface Env {
	// This makes your vector index methods available on env.VECTORIZE.*
	// For example, env.VECTORIZE.insert() or query()
	VECTORIZE: Vectorize;
}

// Sample vectors: 32 dimensions wide.
//
// Vectors from popular machine-learning models are typically ~100 to 1536 dimensions
// wide (or wider still).
const sampleVectors: Array<VectorizeVector> = [
	{
		id: "1",
		values: [
			0.12, 0.45, 0.67, 0.89, 0.23, 0.56, 0.34, 0.78, 0.12, 0.9, 0.24, 0.67,
			0.89, 0.35, 0.48, 0.7, 0.22, 0.58, 0.74, 0.33, 0.88, 0.66, 0.45, 0.27,
			0.81, 0.54, 0.39, 0.76, 0.41, 0.29, 0.83, 0.55,
		],
		metadata: { url: "/products/sku/13913913" },
	},
	{
		id: "2",
		values: [
			0.14, 0.23, 0.36, 0.51, 0.62, 0.47, 0.59, 0.74, 0.33, 0.89, 0.41, 0.53,
			0.68, 0.29, 0.77, 0.45, 0.24, 0.66, 0.71, 0.34, 0.86, 0.57, 0.62, 0.48,
			0.78, 0.52, 0.37, 0.61, 0.69, 0.28, 0.8, 0.53,
		],
		metadata: { url: "/products/sku/10148191" },
	},
	{
		id: "3",
		values: [
			0.21, 0.33, 0.55, 0.67, 0.8, 0.22, 0.47, 0.63, 0.31, 0.74, 0.35, 0.53,
			0.68, 0.45, 0.55, 0.7, 0.28, 0.64, 0.71, 0.3, 0.77, 0.6, 0.43, 0.39, 0.85,
			0.55, 0.31, 0.69, 0.52, 0.29, 0.72, 0.48,
		],
		metadata: { url: "/products/sku/97913813" },
	},
	{
		id: "4",
		values: [
			0.17, 0.29, 0.42, 0.57, 0.64, 0.38, 0.51, 0.72, 0.22, 0.85, 0.39, 0.66,
			0.74, 0.32, 0.53, 0.48, 0.21, 0.69, 0.77, 0.34, 0.8, 0.55, 0.41, 0.29,
			0.7, 0.62, 0.35, 0.68, 0.53, 0.3, 0.79, 0.49,
		],
		metadata: { url: "/products/sku/418313" },
	},
	{
		id: "5",
		values: [
			0.11, 0.46, 0.68, 0.82, 0.27, 0.57, 0.39, 0.75, 0.16, 0.92, 0.28, 0.61,
			0.85, 0.4, 0.49, 0.67, 0.19, 0.58, 0.76, 0.37, 0.83, 0.64, 0.53, 0.3,
			0.77, 0.54, 0.43, 0.71, 0.36, 0.26, 0.8, 0.53,
		],
		metadata: { url: "/products/sku/55519183" },
	},
];

export default {
	async fetch(request, env, ctx): Promise<Response> {
		let path = new URL(request.url).pathname;
		if (path.startsWith("/favicon")) {
			return new Response("", { status: 404 });
		}

		// You only need to insert vectors into your index once
		if (path.startsWith("/insert")) {
			// Insert some sample vectors into your index
			// In a real application, these vectors would be the output of a machine learning (ML) model,
			// such as Workers AI, OpenAI, or Cohere.
			const inserted = await env.VECTORIZE.insert(sampleVectors);

			// Return the mutation identifier for this insert operation
			return Response.json(inserted);
		}

		return Response.json({ text: "nothing to do... yet" }, { status: 404 });
	},
} satisfies ExportedHandler<Env>;

V kódu výše:

  1. Definujte binding na svůj index Vectorize ve svém kódu Workers. Tento binding odpovídá binding hodnotu, kterou jste nastavili v wrangler.jsonc soubor v "vectorise" klíč.
  2. Zadejte sadu ukázkových vektorů, vůči kterým budete v dalším kroku provádět dotazy.
  3. Vložte tyto vektory do indexu a ověřte, že se to podařilo.

V dalším kroku Worker rozšíříte tak, aby dotazoval index a vektory, které vložíte.

6. Proveďte dotaz na vektory

V tomto kroku vezmete vektor reprezentující příchozí dotaz a použijete ho k prohledání indexu.

Nejprve přejděte na svůj vectorize-tutorial Worker a otevřete src/index.ts soubor. index.ts je soubor, ve kterém konfigurujete interakce vašeho Workeru s indexem Vectorize.

Vymažte obsah index.ts. Vložte následující úryvek kódu do svého index.ts soubor. Na env parametru nahraďte <BINDING_NAME> hodnotou VECTORIZE:

export interface Env {
	// This makes your vector index methods available on env.VECTORIZE.*
	// For example, env.VECTORIZE.insert() or query()
	VECTORIZE: Vectorize;
}

// Sample vectors: 32 dimensions wide.
//
// Vectors from popular machine-learning models are typically ~100 to 1536 dimensions
// wide (or wider still).
const sampleVectors: Array<VectorizeVector> = [
	{
		id: "1",
		values: [
			0.12, 0.45, 0.67, 0.89, 0.23, 0.56, 0.34, 0.78, 0.12, 0.9, 0.24, 0.67,
			0.89, 0.35, 0.48, 0.7, 0.22, 0.58, 0.74, 0.33, 0.88, 0.66, 0.45, 0.27,
			0.81, 0.54, 0.39, 0.76, 0.41, 0.29, 0.83, 0.55,
		],
		metadata: { url: "/products/sku/13913913" },
	},
	{
		id: "2",
		values: [
			0.14, 0.23, 0.36, 0.51, 0.62, 0.47, 0.59, 0.74, 0.33, 0.89, 0.41, 0.53,
			0.68, 0.29, 0.77, 0.45, 0.24, 0.66, 0.71, 0.34, 0.86, 0.57, 0.62, 0.48,
			0.78, 0.52, 0.37, 0.61, 0.69, 0.28, 0.8, 0.53,
		],
		metadata: { url: "/products/sku/10148191" },
	},
	{
		id: "3",
		values: [
			0.21, 0.33, 0.55, 0.67, 0.8, 0.22, 0.47, 0.63, 0.31, 0.74, 0.35, 0.53,
			0.68, 0.45, 0.55, 0.7, 0.28, 0.64, 0.71, 0.3, 0.77, 0.6, 0.43, 0.39, 0.85,
			0.55, 0.31, 0.69, 0.52, 0.29, 0.72, 0.48,
		],
		metadata: { url: "/products/sku/97913813" },
	},
	{
		id: "4",
		values: [
			0.17, 0.29, 0.42, 0.57, 0.64, 0.38, 0.51, 0.72, 0.22, 0.85, 0.39, 0.66,
			0.74, 0.32, 0.53, 0.48, 0.21, 0.69, 0.77, 0.34, 0.8, 0.55, 0.41, 0.29,
			0.7, 0.62, 0.35, 0.68, 0.53, 0.3, 0.79, 0.49,
		],
		metadata: { url: "/products/sku/418313" },
	},
	{
		id: "5",
		values: [
			0.11, 0.46, 0.68, 0.82, 0.27, 0.57, 0.39, 0.75, 0.16, 0.92, 0.28, 0.61,
			0.85, 0.4, 0.49, 0.67, 0.19, 0.58, 0.76, 0.37, 0.83, 0.64, 0.53, 0.3,
			0.77, 0.54, 0.43, 0.71, 0.36, 0.26, 0.8, 0.53,
		],
		metadata: { url: "/products/sku/55519183" },
	},
];

export default {
	async fetch(request, env, ctx): Promise<Response> {
		let path = new URL(request.url).pathname;
		if (path.startsWith("/favicon")) {
			return new Response("", { status: 404 });
		}

		// You only need to insert vectors into your index once
		if (path.startsWith("/insert")) {
			// Insert some sample vectors into your index
			// In a real application, these vectors would be the output of a machine learning (ML) model,
			// such as Workers AI, OpenAI, or Cohere.
			let inserted = await env.VECTORIZE.insert(sampleVectors);

			// Return the mutation identifier for this insert operation
			return Response.json(inserted);
		}

		// return Response.json({text: "nothing to do... yet"}, { status: 404 })

		// In a real application, you would take a user query. For example, "what is a
		// vector database" - and transform it into a vector embedding first.
		//
		// In this example, you will construct a vector that should
		// match vector id #4
		const queryVector: Array<number> = [
			0.13, 0.25, 0.44, 0.53, 0.62, 0.41, 0.59, 0.68, 0.29, 0.82, 0.37, 0.5,
			0.74, 0.46, 0.57, 0.64, 0.28, 0.61, 0.73, 0.35, 0.78, 0.58, 0.42, 0.32,
			0.77, 0.65, 0.49, 0.54, 0.31, 0.29, 0.71, 0.57,
		]; // vector of dimensions 32

		// Query your index and return the three (topK = 3) most similar vector
		// IDs with their similarity score.
		//
		// By default, vector values are not returned, as in many cases the
		// vector id and scores are sufficient to map the vector back to the
		// original content it represents.
		const matches = await env.VECTORIZE.query(queryVector, {
			topK: 3,
			returnValues: true,
			returnMetadata: "all",
		});

		return Response.json({
			// This will return the closest vectors: the vectors are arranged according
			// to their scores. Vectors that are more similar would show up near the top.
			// In this example, Vector id #4 would turn out to be the most similar to the queried vector.
			// You return the full set of matches so you can check the possible scores.
			matches: matches,
		});
	},
} satisfies ExportedHandler<Env>;

Vectorize můžete využít také pomocí queryById() operaci k vyhledání vektorů podobných vektoru, který již v indexu existuje.

7. Nasaďte svůj Worker

Než Worker nasadíte globálně, přihlaste se ke svému účtu Cloudflare spuštěním:

npx wrangler login

Budete přesměrováni na webovou stránku s výzvou k přihlášení do dashboardu Cloudflare. Po přihlášení se zobrazí dotaz, zda Wrangler smí provádět změny ve vašem účtu Cloudflare. Přejděte dolů a vyberte Allow pokračovat.

Odtud můžete nasadit svůj Worker, aby byl projekt dostupný na internetu. Worker nasadíte příkazem:

npx wrangler deploy

Po nasazení si Worker prohlédněte na adrese https://vectorize-tutorial.<YOUR_SUBDOMAIN>.workers.dev.

8. Proveďte dotaz na svůj index

Chcete-li vektory vložit a poté je dotazovat, použijte URL svého nasazeného Workeru, například https://vectorize-tutorial.<YOUR_SUBDOMAIN>.workers.dev/. Otevřete prohlížeč a:

  1. Vektory nejprve vložte tak, že navštívíte /insert. Mělo by se vrátit následující JSON:
// https://vectorize-tutorial.<YOUR_SUBDOMAIN>.workers.dev/insert
{
	"mutationId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

mutationId zde označuje jedinečný identifikátor odpovídající této asynchronní operaci vkládání. Vložené vektory jsou obvykle k dispozici pro dotazování během několika sekund.

Pomocí operace pro získání informací o indexu můžete zkontrolovat poslední zpracovanou mutaci:

npx wrangler vectorize info tutorial-index
📋 Fetching index info...
┌────────────┬─────────────┬──────────────────────────────────────┬──────────────────────────┐
│ dimensions │ vectorCount │ processedUpToMutation                │ processedUpToDatetime    │
├────────────┼─────────────┼──────────────────────────────────────┼──────────────────────────┤
│ 32         │ 5           │ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx │ YYYY-MM-DDThh:mm:ss.SSSZ │
└────────────┴─────────────┴──────────────────────────────────────┴──────────────────────────┘

Další vkládání se stejnými ID vektorů vrátí ID mutace, ale nezmění počet vektorů v indexu, protože stejná ID vektorů nelze vložit dvakrát. Budete muset použít upsert operaci k aktualizaci hodnot vektoru pro ID, které v indexu již existuje.

  1. Dotaz na váš index: očekává se vektor dotazu s délkou [0.13, 0.25, 0.44, ...] za nejbližší vektoru s ID 4 návštěvou kořenové cesty / . Tento dotaz vrátí tři (topK: 3) nejbližších shod, včetně jejich vektorových hodnot a metadat.

Všimnete si, že id: 4 má score z 0.46348256. Protože používáte euclidean jako metriku vzdálenosti, tím blíže je skóre 0.0, tím blíže jsou vaše vektory.

// https://vectorize-tutorial.<YOUR_SUBDOMAIN>.workers.dev/
{
	"matches": {
		"count": 3,
		"matches": [
			{
				"id": "4",
				"score": 0.46348256,
				"values": [
					0.17, 0.29, 0.42, 0.57, 0.64, 0.38, 0.51, 0.72, 0.22, 0.85, 0.39,
					0.66, 0.74, 0.32, 0.53, 0.48, 0.21, 0.69, 0.77, 0.34, 0.8, 0.55, 0.41,
					0.29, 0.7, 0.62, 0.35, 0.68, 0.53, 0.3, 0.79, 0.49
				],
				"metadata": {
					"url": "/products/sku/418313"
				}
			},
			{
				"id": "3",
				"score": 0.52920616,
				"values": [
					0.21, 0.33, 0.55, 0.67, 0.8, 0.22, 0.47, 0.63, 0.31, 0.74, 0.35, 0.53,
					0.68, 0.45, 0.55, 0.7, 0.28, 0.64, 0.71, 0.3, 0.77, 0.6, 0.43, 0.39,
					0.85, 0.55, 0.31, 0.69, 0.52, 0.29, 0.72, 0.48
				],
				"metadata": {
					"url": "/products/sku/97913813"
				}
			},
			{
				"id": "2",
				"score": 0.6337869,
				"values": [
					0.14, 0.23, 0.36, 0.51, 0.62, 0.47, 0.59, 0.74, 0.33, 0.89, 0.41,
					0.53, 0.68, 0.29, 0.77, 0.45, 0.24, 0.66, 0.71, 0.34, 0.86, 0.57,
					0.62, 0.48, 0.78, 0.52, 0.37, 0.61, 0.69, 0.28, 0.8, 0.53
				],
				"metadata": {
					"url": "/products/sku/10148191"
				}
			}
		]
	}
}

Odtud můžete experimentovat, například zadáním jiného queryVector a sledujte výsledky: shody a score by se mělo měnit na základě změny vzdálenosti mezi dotazovaným vektorem a vektory v našem indexu.

V reálné aplikaci queryVector by představovalo vektorovou reprezentaci dotazu od uživatele nebo systému a naše sampleVectors by byl vygenerován ze skutečného obsahu. Pro rozšíření tohoto příkladu si přečtěte tutoriál k vyhledávání vektorů která kombinuje Workers AI a Vectorize a umožňuje vytvořit kompletní aplikaci s Workers.

Dokončením tohoto tutoriálu jste úspěšně vytvořili a dotázali svůj první index Vectorize, vytvořili Worker pro přístup k tomuto indexu a globálně nasadili svůj projekt.