LangChain ↗ は、大規模言語モデルを使ったアプリケーションを構築するためのフレームワークです。langchain-cloudflare ↗ パッケージは、AI Search をバックエンドとする標準 LangChain retriever である CloudflareAISearchRetriever を提供します。
retriever は検索だけを行います。インスタンスの作成とコンテンツのアップロードには、Cloudflare Python SDK ↗ と組み合わせます。このガイドでは、Python SDK でハイブリッド検索を有効にした AI Search インスタンスを作成してファイルをインデックスし、LangChain retriever をツールとして検索します。
トークンを作成するには、API トークンを作成する に従い、両方の権限を追加します。Edit はインスタンスのプロビジョニングとファイルのアップロードに使います。Run は検索を実行します。
プロジェクトディレクトリと仮想環境を作成し、依存関係を分離します。
mkdir ai-search-langchain && cd ai-search-langchain
python3 -m venv .venv
source .venv/bin/activateWindows では、代わりに .venv\Scripts\activate で仮想環境を有効にします。
両方のパッケージをインストールします。
pip install -U langchain-cloudflare cloudflarecloudflare SDK はインスタンスの作成とファイルのアップロードを行います。langchain-cloudflare パッケージは retriever と、RAG およびエージェントツールのヘルパーを提供します。langchain-cloudflare をインストールすると langchain-core も入るため、langchain を別途インストールする必要はありません。
アカウント ID と API トークンをエクスポートします。Cloudflare SDK はこれらを自動で読み取ります。
export CLOUDFLARE_ACCOUNT_ID="<ACCOUNT_ID>"
export CLOUDFLARE_API_TOKEN="<API_TOKEN>"main.py というファイルを作成します。次のコードは、index_method を設定してベクトルとキーワードの両方をインデックスし、ハイブリッド検索 を有効にしたインスタンスを作成します。データソースを接続していないため、インスタンスは 組み込みストレージ を使います。
既存のインスタンスを作成しようとすると失敗します。そのため、コードは先に存在を確認し、ない場合だけ作成します。
import os
from cloudflare import Cloudflare, NotFoundError
ACCOUNT_ID = os.environ["CLOUDFLARE_ACCOUNT_ID"]
API_TOKEN = os.environ["CLOUDFLARE_API_TOKEN"]
NAMESPACE = "default"
INSTANCE_NAME = "knowledge-base"
# The SDK authenticates with this token; the account ID is passed on each call.
client = Cloudflare(api_token=API_TOKEN)
# create() fails if the instance already exists, so check for it with read()
# first and only create it when read() raises NotFoundError.
try:
client.aisearch.namespaces.instances.read(
INSTANCE_NAME, account_id=ACCOUNT_ID, name=NAMESPACE
)
print(f"Instance '{INSTANCE_NAME}' already exists.")
except NotFoundError:
client.aisearch.namespaces.instances.create(
name=NAMESPACE,
account_id=ACCOUNT_ID,
id=INSTANCE_NAME,
# Index both vectors and keywords to enable hybrid search.
index_method={"vector": True, "keyword": True},
)
print(f"Created instance '{INSTANCE_NAME}'.")create() の最初の位置引数は名前空間名です。以前にベクトルのみのインスタンスを作成した場合は、代わりに client.aisearch.namespaces.instances.update(...) でハイブリッド検索を有効にします。
組み込みストレージにドキュメントをアップロードするため、次を main.py に追加します。file 引数内で wait_for_completion を True にすると、ファイルのインデックスが完了するまで待機してから戻ります。
item = client.aisearch.namespaces.instances.items.upload(
id=INSTANCE_NAME,
account_id=ACCOUNT_ID,
name=NAMESPACE,
file={
# (filename, file bytes, content type)
"file": (
"workers-ai.md",
b"To configure Workers AI, add an [ai] binding and call env.AI.run().",
"text/markdown",
),
# Block until indexing finishes so the file is searchable right away.
"wait_for_completion": True,
},
)
print(f"Uploaded '{item.key}' (status: {item.status}).")インデックスがまだ完了していない場合、item.status は running になることがあります。ファイルはバックグラウンドでインデックスを続け、まもなく検索可能になります。
LangChain からインスタンスを使う方法は 3 つあります。アプリケーションに合うものを選びます。
- 直接検索する は、一致するドキュメントを返します。
- AI Search をエージェントツールとして使う は、エージェントにコンテンツを検索する能力を与えます。
- RAG チェーンを構築する は、取得したドキュメントから回答を生成します。
3 つとも同じ CloudflareAISearchRetriever を使います。最初のオプションで作成します。
CloudflareAISearchRetriever をインスタンスに向けます。有効にしたベクトルインデックスとキーワードインデックスを使うには、retrieval_type を hybrid に設定します。
from langchain_cloudflare import CloudflareAISearchRetriever
retriever = CloudflareAISearchRetriever(
account_id=ACCOUNT_ID,
api_token=API_TOKEN,
instance_name=INSTANCE_NAME,
namespace=NAMESPACE,
retrieval_type="hybrid", # query both the vector and keyword indexes
k=5, # maximum number of results to return (capped at 50)
)
# invoke() runs a search and returns standard LangChain Documents.
docs = retriever.invoke("How do I configure Workers AI?")
for doc in docs:
# Each document carries its relevance score and source filename in metadata.
print(doc.metadata["score"], doc.metadata["filename"])
print(doc.page_content)k パラメーターは結果の最大数を設定します。max_num_results に対応し、上限は 50 です。
retriever を create_retriever_tool でラップすると、エージェントにコンテンツを検索する能力を与えられます。LangChain エージェントから AI Search を使う推奨方法です。
from langchain_core.tools import create_retriever_tool
# create_retriever_tool wraps the retriever as a standard LangChain tool. The
# name and description are what the agent's model sees when deciding to call it.
search_tool = create_retriever_tool(
retriever,
name="cloudflare_ai_search",
description="Search the knowledge base for relevant passages.",
)
print(search_tool.invoke({"query": "How do I configure Workers AI?"}))search_tool は標準の LangChain ツールです。ほかのツールと一緒に、任意の LangChain または LangGraph エージェントに渡せます。
取得したコンテンツから質問に答えるには、retriever とモデルを組み合わせます。この例では、同じパッケージに含まれる ChatCloudflareWorkersAI を使います。retriever と同じ方法でアカウント ID とトークンを渡します。
このオプションは回答生成に Workers AI を呼び出すため、ここで渡すトークンには Workers AI 権限も必要です。すでに作成したトークンに追加するか、別のトークンを渡します。
from langchain_cloudflare import ChatCloudflareWorkersAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
llm = ChatCloudflareWorkersAI(
account_id=ACCOUNT_ID,
api_token=API_TOKEN,
model="@cf/zai-org/glm-5.2",
)
prompt = ChatPromptTemplate.from_template(
"Answer the question using only the context below.\n\n"
"Context:\n{context}\n\n"
"Question: {question}"
)
# Join the retrieved documents into a single context string for the prompt.
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
# LCEL chain: retrieve context and pass the question through, fill the prompt,
# call the model, then parse the response down to a plain string.
chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
print(chain.invoke("How do I configure Workers AI?"))Python Worker 内では、REST 資格情報の代わりに Worker バインディングを渡します。バインディングパスは非同期なので、ainvoke を使います。
from workers import WorkerEntrypoint, Response
from langchain_cloudflare import CloudflareAISearchRetriever
class Default(WorkerEntrypoint):
async def fetch(self, request):
# Pass a Worker binding instead of REST credentials.
retriever = CloudflareAISearchRetriever(binding=self.env.MY_SEARCH)
# The binding path is asynchronous, so use ainvoke.
docs = await retriever.ainvoke("How do I configure Workers AI?")
return Response.json({"matches": [doc.page_content for doc in docs]})self.env.MY_SEARCH は専用の ai_search バインディングであり、Workers AI バインディング(self.env.AI)ではありません。名前空間バインディング の場合は、self.env.<NAMESPACE>.get("my-instance") を渡します。