INTEGRITY Dokumentace

AI SDK

Vercel AI SDK ↗ je sada nástrojů TypeScript pro vytváření aplikací s velkými jazykovými modely. ai-search-provider ↗ balíček propojuje AI Search s AI SDK, takže z jednoho API můžete generovat odpovědi podložené vaším indexovaným obsahem, načítat části obsahu a spravovat dokumenty.

Tento návod sestaví Worker, který vytvoří instanci AI Search, nahraje a zaindexuje dokument a poté ji dotáže pomocí AI SDK.

Předpoklady

  1. Zaregistrujte si účet Cloudflare ↗.
  2. Nainstalujte Node.js ↗.

Správce verzí Node.js

Použijte správce verzí Node, jako je Volta ↗ nebo nvm ↗ abyste se vyhnuli problémům s oprávněními a mohli měnit verze Node.js. Wrangler, o kterém se dozvíte dále v této příručce, vyžaduje verzi Node 16.17.0 nebo novější.

1. Vytvořte projekt Worker

Vytvořte nový projekt Worker pomocí create-cloudflare CLI (C3). C3 ↗ je nástroj příkazové řádky, který vám pomůže nastavit a nasadit nové aplikace na Cloudflare.

Vytvořte nový projekt s názvem ai-search-ai-sdk spuštěním:

npm create cloudflare@latest -- ai-search-ai-sdk

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

Přejděte do adresáře své aplikace:

cd ai-search-ai-sdk

2. Nainstalujte AI SDK a poskytovatele

Nainstalujte AI SDK a poskytovatele AI Search. Poskytovatel vyžaduje AI SDK v6 (ai@^6):

npm i ai ai-search-provider

Vytvořte vazbu mezi svým Workerem a AI Search. Bindings umožňují vašemu Workeru pracovat se zdroji na Cloudflare Developer Platform.

Přidejte následující do svého Konfigurační soubor Wrangler:

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "ai_search_namespaces": [
    {
      "binding": "AI_SEARCH",
      "namespace": "default",
      "remote": true
    }
  ]
}
[[ai_search_namespaces]]
binding = "AI_SEARCH"
namespace = "default"
remote = true

Tím se naváže default namespace na env.AI_SEARCH. remote volba umožňuje wrangler dev předávají požadavky na vaši nasazenou instanci, protože AI Search neběží lokálně. ai_search_namespaces vazba vyžaduje compatibility_date z 2026-03-27 nebo novější, což nové projekty C3 už splňují.

4. Vytvořte instanci a zaindexujte obsah

Přidejte /setup trasu, která vytvoří instanci a nahraje dokument. Povolte hybridní vyhledávání při vytváření nastavením index_method na indexování vektorů i klíčových slov.

create() metoda je součástí vazby jmenného prostoru (env.AI_SEARCH), nikoli na klientovi poskytovatele. Vytvoření instance, která už existuje, vyvolá chybu, takže následující kód ji vytvoří a při dalším spuštění ji už jen aktualizuje.

src/index.js
import { createAISearchNamespace } from "ai-search-provider";
import { generateText, streamText } from "ai";

const INSTANCE_NAME = "knowledge-base";

const SAMPLE_DOC = `# Caching on Cloudflare
Cloudflare caches static assets at the edge. Use Cache Rules to control what is
cached, set an Edge Cache TTL to control how long objects stay in cache, and
purge the cache after a deploy.`;

// Create the instance with hybrid search, or update it if it already exists.
async function ensureInstance(env) {
	// index_method with both vector and keyword enables hybrid search.
	const hybrid = { index_method: { vector: true, keyword: true } };
	try {
		await env.AI_SEARCH.create({ id: INSTANCE_NAME, ...hybrid });
	} catch {
		await env.AI_SEARCH.get(INSTANCE_NAME).update(hybrid);
	}
}

export default {
	async fetch(request, env) {
		const url = new URL(request.url);
		// createAISearchNamespace adapts the binding to the AI SDK provider API.
		const aiSearch = createAISearchNamespace({ binding: env.AI_SEARCH });

		// Visit /setup once to create the instance and index a document.
		if (url.pathname === "/setup") {
			await ensureInstance(env);

			const instance = aiSearch.get(INSTANCE_NAME);

			// upload() queues the file and returns immediately. Indexing runs in
			// the background, so poll the item's status until it is searchable.
			const { id, key } = await instance.items.upload("caching.md", SAMPLE_DOC);

			let info = await instance.items.get(id).info();
			while (info.status === "queued" || info.status === "running") {
				await new Promise((resolve) => setTimeout(resolve, 2_000));
				info = await instance.items.get(id).info();
			}

			return Response.json({ key, status: info.status });
		}

		// Query the instance (see the next step).
		return new Response("Visit /setup first, then query with ?q=");
	},
};
src/index.ts
import { createAISearchNamespace } from "ai-search-provider";
import { generateText, streamText } from "ai";

interface Env {
	AI_SEARCH: AiSearchNamespace;
}

const INSTANCE_NAME = "knowledge-base";

const SAMPLE_DOC = `# Caching on Cloudflare
Cloudflare caches static assets at the edge. Use Cache Rules to control what is
cached, set an Edge Cache TTL to control how long objects stay in cache, and
purge the cache after a deploy.`;

// Create the instance with hybrid search, or update it if it already exists.
async function ensureInstance(env: Env) {
	// index_method with both vector and keyword enables hybrid search.
	const hybrid = { index_method: { vector: true, keyword: true } };
	try {
		await env.AI_SEARCH.create({ id: INSTANCE_NAME, ...hybrid });
	} catch {
		await env.AI_SEARCH.get(INSTANCE_NAME).update(hybrid);
	}
}

export default {
	async fetch(request, env): Promise<Response> {
		const url = new URL(request.url);
		// createAISearchNamespace adapts the binding to the AI SDK provider API.
		const aiSearch = createAISearchNamespace({ binding: env.AI_SEARCH });

		// Visit /setup once to create the instance and index a document.
		if (url.pathname === "/setup") {
			await ensureInstance(env);

			const instance = aiSearch.get(INSTANCE_NAME);

			// upload() queues the file and returns immediately. Indexing runs in
			// the background, so poll the item's status until it is searchable.
			const { id, key } = await instance.items.upload("caching.md", SAMPLE_DOC);

			let info = await instance.items.get(id).info();
			while (info.status === "queued" || info.status === "running") {
				await new Promise((resolve) => setTimeout(resolve, 2_000));
				info = await instance.items.get(id).info();
			}

			return Response.json({ key, status: info.status });
		}

		// Query the instance (see the next step).
		return new Response("Visit /setup first, then query with ?q=");
	},
} satisfies ExportedHandler<Env>;

AiSearchNamespace je ambientní typ dostupný po spuštění wrangler types.

5. Dotazujte se na instanci

Z AI SDK můžete svou instanci dotazovat třemi způsoby. Vyberte ten, který se hodí pro vaši aplikaci:

Vygenerovat odpověď

Předejte instance.chat() na generateText, a AI Search v jediném volání načte relevantní obsah a vygeneruje odpověď.

Nahraďte zástupný text pro dotaz ve svém fetch obslužnou rutinu pomocí následujícího:

src/index.js
const query = url.searchParams.get("q") ?? "How does caching work?";

// chat() returns an AI SDK model that retrieves matching chunks and generates
// a grounded answer in one call, so there is no separate search step.
const { text, sources } = await generateText({
	model: aiSearch.get(INSTANCE_NAME).chat({
		ai_search_options: {
			// "hybrid" ranks results from both the vector and keyword indexes.
			retrieval: { retrieval_type: "hybrid", max_num_results: 5 },
		},
	}),
	messages: [{ role: "user", content: query }],
});

// `sources` holds the retrieved chunks, so you can cite them alongside `text`.
return Response.json({ text, sources });
src/index.ts
const query = url.searchParams.get("q") ?? "How does caching work?";

// chat() returns an AI SDK model that retrieves matching chunks and generates
// a grounded answer in one call, so there is no separate search step.
const { text, sources } = await generateText({
	model: aiSearch.get(INSTANCE_NAME).chat({
		ai_search_options: {
			// "hybrid" ranks results from both the vector and keyword indexes.
			retrieval: { retrieval_type: "hybrid", max_num_results: 5 },
		},
	}),
	messages: [{ role: "user", content: query }],
});

// `sources` holds the retrieved chunks, so you can cite them alongside `text`.
return Response.json({ text, sources });

AI Search vrací načtené části obsahu jako source parts AI SDK v sources, abyste je mohli citovat spolu s vygenerovaným textem. Protože instance indexuje jak vektory, tak klíčová slova, retrieval_type: "hybrid" používá obojí.

Streamování odpovědi

Pro delší odpovědi použijte streamText místo generateText. AI Search odešle načtené části obsahu jako zdrojové části ještě před první textovou částí.

// streamText returns right away; tokens stream in as they are generated.
const result = streamText({
	model: aiSearch.get(INSTANCE_NAME).chat(),
	messages: [{ role: "user", content: query }],
});

// toTextStreamResponse() streams the generated text only.
return result.toTextStreamResponse();
// streamText returns right away; tokens stream in as they are generated.
const result = streamText({
	model: aiSearch.get(INSTANCE_NAME).chat(),
	messages: [{ role: "user", content: query }],
});

// toTextStreamResponse() streams the generated text only.
return result.toTextStreamResponse();

toTextStreamResponse() odesílá vygenerovaný text a zdroje zahodí. Pokud chcete streamovat i načtené části obsahu, vraťte stream zpráv UI s sendSources povoleno, nebo si přečtěte result.fullStream přímo:

// sendSources forwards each retrieved chunk as a source-url part. They arrive
// before the first text part, so you can render citations as the answer streams.
return result.toUIMessageStreamResponse({ sendSources: true });
// sendSources forwards each retrieved chunk as a source-url part. They arrive
// before the first text part, so you can render citations as the answer streams.
return result.toUIMessageStreamResponse({ sendSources: true });

Vyhledávání jako nástroj

S chat(), AI Search prohledává vaši instanci při každém požadavku. Pokud chcete, aby o vyhledávání rozhodoval model sám, zpřístupněte instance.search() jako AI SDK nástroj ↗ a předejte ho modelu, který podporuje volání funkcí, například Workers AI model. Toto je vzor, který se má použít u agenta, kde si model sám volí mezi vyhledáváním a dalšími nástroji.

Nainstalujte poskytovatele Workers AI a Zod. Použijte verzi 3 workers-ai-provider: nejnovější verze 4 vyžaduje AI SDK v7, ale ai-search-provider vyžaduje v6, takže npm je společně nenainstaluje.

npm i workers-ai-provider@^3 zod

Přidejte vazbu Workers AI do konfigurace Wrangler:

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "ai": {
    "binding": "AI"
  }
}
[ai]
binding = "AI"

Poté definujte nástroj pro vyhledávání. Model ho zavolá, když potřebuje načíst obsah:

import { createWorkersAI } from "workers-ai-provider";
import { generateText, tool, stepCountIs } from "ai";
import { z } from "zod";

const instance = aiSearch.get(INSTANCE_NAME);
// The tool-caller must support function calling. Use a dedicated model here
// rather than the AI Search chat model, which retrieves on every request.
const workersai = createWorkersAI({ binding: env.AI });

const { text } = await generateText({
	model: workersai("@cf/zai-org/glm-5.2"),
	messages: [{ role: "user", content: query }],
	tools: {
		search_knowledge_base: tool({
			description: "Search the indexed knowledge base for relevant content.",
			inputSchema: z.object({
				query: z.string().describe("The search query"),
			}),
			// The model decides when to call this; it searches the instance.
			execute: async ({ query }) =>
				instance.search({
					query,
					ai_search_options: { retrieval: { max_num_results: 5 } },
				}),
		}),
	},
	// Cap the tool-call loop so the model cannot invoke tools indefinitely.
	stopWhen: stepCountIs(5),
});
import { createWorkersAI } from "workers-ai-provider";
import { generateText, tool, stepCountIs } from "ai";
import { z } from "zod";

const instance = aiSearch.get(INSTANCE_NAME);
// The tool-caller must support function calling. Use a dedicated model here
// rather than the AI Search chat model, which retrieves on every request.
const workersai = createWorkersAI({ binding: env.AI });

const { text } = await generateText({
	model: workersai("@cf/zai-org/glm-5.2"),
	messages: [{ role: "user", content: query }],
	tools: {
		search_knowledge_base: tool({
			description: "Search the indexed knowledge base for relevant content.",
			inputSchema: z.object({
				query: z.string().describe("The search query"),
			}),
			// The model decides when to call this; it searches the instance.
			execute: async ({ query }) =>
				instance.search({
					query,
					ai_search_options: { retrieval: { max_num_results: 5 } },
				}),
		}),
	},
	// Cap the tool-call loop so the model cannot invoke tools indefinitely.
	stopWhen: stepCountIs(5),
});

6. Otestujte to lokálně

Před nasazením ověřte, že celý postup funguje s vaší instancí pomocí wrangler dev, který slouží jako proxy pro vzdálený binding AI Search. Výstup níže pochází z vygenerovat odpověď možnost.

Spusťte místní vývojový server:

npx wrangler dev

Nejprve zaindexujte ukázkový dokument návštěvou /setup:

curl http://localhost:8787/setup

První /setup může trvat minutu až dvě, než se dokument zaindexuje. Po dokončení se vám vrátí klíč položky a completed stav:

{ "key": "caching.md", "status": "completed" }

Poté dotazujte instanci:

curl "http://localhost:8787/?q=How+does+caching+work%3F"

Funkční integrace vrací vygenerované text podloženou vaším dokumentem, spolu s sources array odkazující na soubor, který načetl (pole zkrácena):

{
	"text": "Cloudflare caches static assets at the edge...",
	"sources": [{ "sourceType": "url", "url": "caching.md" }]
}

Pokud sources vrátí prázdný výsledek, dokument ještě není zaindexovaný. Spusťte /setup znovu a poté dotaz zopakujte.

7. Nasaďte

Přihlaste se ke svému účtu Cloudflare:

npx wrangler login

Nasaďte svůj Worker, aby byl dostupný na internetu:

npx wrangler deploy

Co zvážit

Další kroky

Hybridní vyhledávání

Kombinace vektorového a klíčového vyhledávání s konfigurovatelnou fúzí.

Instances Workers binding

Úplná referenční dokumentace k vytváření, aktualizaci, výpisu a mazání.

Vazba Workers pro Search

Úplná referenční dokumentace k vyhledávání a chatování z Workeru.

Agents SDK

Sestavte stavového chatovacího agenta, který vyhledává ve vaší instanci.