← Přehled / ai-search / agent-sdks
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
- Zaregistrujte si účet Cloudflare ↗.
- 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-sdkPři nastavení vyberte následující možnosti:
- Pro S čím byste chtěli začít?, vyberte
Hello World example. - Pro Jakou šablonu chcete použít?, vyberte
Worker only. - Pro Jaký jazyk chcete použít?, vyberte
TypeScript. - Pro Chcete používat git pro správu verzí?, vyberte
Yes. - Pro Chcete nasadit svou aplikaci?, vyberte
No(před nasazením provedeme ještě několik změn).
Přejděte do adresáře své aplikace:
cd ai-search-ai-sdk2. 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-provider3. Propojte Worker s AI Search pomocí vazby
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 = trueTí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.
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=");
},
};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ěď vrátí kompletní odpověď jedním voláním.
- Streamování odpovědi odesílá tokeny postupně, jak vznikají, což se hodí pro dlouhé odpovědi a chatovací rozhraní.
- Vyhledávání jako nástroj nechává rozhodnutí, kdy vyhledávat, na modelu, což je přesně to, co chcete u agenta.
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:
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 });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 zodPř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 devNejprve zaindexujte ukázkový dokument návštěvou /setup:
curl http://localhost:8787/setupPrvní /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 loginNasaďte svůj Worker, aby byl dostupný na internetu:
npx wrangler deployCo zvážit
- Model chatu je pouze textový. Části zprávy typu soubor a obrázek nejsou podporovány.
- Možnosti generování, jako například
temperatureamaxOutputTokensse předávají generujícímu modelu instance.maxOutputTokenszkrátí odpověď a nastavífinishReasonna"length". Pokud model danou možnost ignoruje, výsledkuwarningsarray zůstává prázdné, takže nepodporovaná možnost tiše selže. - AI Search ve výchozím nastavení používá generační model nakonfigurovaný na instanci. Předejte
instance.chat({ model: "..." })a přepište tak model pro jednotlivý požadavek.