Appearance
Cloudflare Serverless RAG 部署完整指南
本文梳理了在 Cloudflare 全家桶(Workers + Pages + D1 + Vectorize + Workers AI)上构建无服务器 RAG 知识检索系统的完整架构,以及实际部署过程中遇到的问题与正确操作流程,适合作为可复用的工程参考。
一、整体架构概览
用户提问 + 图片上传
│
▼
Cloudflare Pages (静态前端)
│ /api/* 服务绑定
▼
Cloudflare Workers (panjiayuan-backend)
│
├─ /api/get-verdict ──► [1] Vectorize 向量检索
│ [2] D1 SQL 精准点查
│ [3] 返回结构化 JSON
│
├─ /api/analyze-bracelet ──► [RAG Context 注入]
│ DeepSeek 流式深度报告
│
└─ /api/sync-rag ──► D1 全量读取
Workers AI Embedding
Vectorize 批量 upsert双轨并发设计:前端在点击分析时同时发起两个请求:
GET /api/get-verdict:毫秒级返回卡片 JSON(走 Vectorize → D1)GET /api/analyze-bracelet:流式返回深度 Markdown 报告(RAG 上下文注入大模型)
二、关键组件说明
| 组件 | 角色 | 费用 |
|---|---|---|
| Cloudflare Pages | 静态前端托管 + API 路由代理 | 免费 |
| Cloudflare Workers | 边缘 API 网关(panjiayuan-backend) | 免费额度内 |
| Cloudflare D1 | 关系型 SQL 百科知识库 | 免费 |
| Cloudflare Vectorize | 1024 维语义向量索引 | 免费额度内 |
| Cloudflare Workers AI | 文本嵌入 (bge-large-en-v1.5) | 免费额度内 |
三、部署完整步骤
步骤 1:创建 D1 数据库与 Vectorize 索引
bash
# 创建 D1 数据库
npx wrangler d1 create panjiayuan-db
# 记录输出的 database_id
# 创建 1024 维向量索引(必须与 Workers AI 模型维度对齐)
npx wrangler vectorize create panjiayuan-vector-index \
--dimensions=1024 \
--metric=cosine步骤 2:编写 wrangler.toml(关键!)
必须在 Worker 代码目录下创建 wrangler.toml,否则每次 deploy 会清除控制台配置的绑定关系:
toml
name = "panjiayuan-backend"
main = "worker.js"
compatibility_date = "2026-06-16"
# Workers AI 绑定(文本向量化)
[ai]
binding = "AI"
# D1 SQL 数据库绑定
[[d1_databases]]
binding = "DB"
database_name = "panjiayuan-db"
database_id = "你的-database-id-uuid"
# Vectorize 向量索引绑定
[[vectorize]]
binding = "VECTOR_INDEX"
index_name = "panjiayuan-vector-index"步骤 3:部署 Worker
bash
# 必须加 --keep-vars,避免清除控制台配置的 API Key 等环境变量
npx wrangler deploy --keep-vars步骤 4:初始化数据库表结构与种子数据
bash
# 将 schema.sql 里的建表与初始数据注入远端 D1
npx wrangler d1 execute panjiayuan-db \
--remote \
--file=./schema.sql步骤 5:触发向量冷启动同步
D1 数据注入后,Vectorize 索引仍为空,需要执行一键同步将所有百科条目向量化并写入:
bash
curl -X POST https://your-domain.com/api/sync-rag
# 成功响应:{"success":true,"message":"Sync D1 to Vectorize database successfully!","recordsSynced":7}四、踩坑记录与修复方案
坑 1:无 wrangler.toml 直接 deploy 会清除云端绑定
问题:执行 npx wrangler deploy worker.js --name panjiayuan-backend 后,D1 / Vectorize / AI 绑定从控制台消失。
原因:wrangler 在没有 wrangler.toml 时以"本地零配置"为基准,会将远端已有的资源绑定清空覆盖。
解决:在 Worker 目录下创建 wrangler.toml,显式声明全部绑定关系,并在 deploy 时加 --keep-vars。
坑 2:向量模型 @cf/baai/bge-large-zh-v1.5 已下线
问题:调用 Workers AI 时返回 5007: No such model @cf/baai/bge-large-zh-v1.5 or task。
原因:截至 2026-06-16,Cloudflare Workers AI 已不再提供该中文模型。
正确替代模型(1024 维,中英文均可用):
| 模型 ID | 维度 | 说明 |
|---|---|---|
@cf/baai/bge-large-en-v1.5 | 1024 | 推荐,英文优先兼容中文词汇 |
@cf/qwen/qwen3-embedding-0.6b | 1024 | 阿里千问,中文效果更优 |
@cf/baai/bge-base-en-v1.5 | 768 | 轻量,需调整 Vectorize 维度 |
解决:将代码中的模型名称统一替换为 @cf/baai/bge-large-en-v1.5,Vectorize 索引维度保持 1024 不变。
坑 3:Pages "服务绑定" 指向的是独立 Worker,不是 Pages 函数目录
问题:在 Pages 项目 Settings → Bindings 页面配置了 D1/Vectorize/AI,但 API 请求实际由 panjiayuan-backend Worker 处理,Pages 层的绑定对其无效。
原因:Cloudflare Pages 的 API 路由通过"服务绑定"代理到了一个独立的 Workers 服务,两者的绑定是分开配置的。
解决:在 Workers 控制台(而非 Pages 控制台)为 panjiayuan-backend 分别绑定 D1、Vectorize、AI,或者通过 wrangler.toml 在代码层显式声明(推荐后者,更可追踪)。
坑 4:sync-rag 接口因 FormData 解析顺序问题报错
问题:/api/sync-rag 返回 Parsing a Body as FormData requires a Content-Type header。
原因:Worker 代码在路由判断前统一执行了 await request.formData(),而 sync-rag 请求没有携带 FormData body。
解决:在 Worker 中将 isSyncRoute 的处理逻辑提前到 request.formData() 之前,让同步路由直接返回,不触碰 FormData 解析。
五、RAG 核心代码片段
D1 百科表结构(schema.sql)
sql
CREATE TABLE IF NOT EXISTS panjiayuan_wiki (
id INTEGER PRIMARY KEY AUTOINCREMENT,
category TEXT NOT NULL, -- 文玩类别
title TEXT NOT NULL, -- 百科词条标题
description TEXT NOT NULL, -- 特征与骗局识别描述
price_range TEXT NOT NULL, -- 地摊合理拿货价区间
phrases TEXT NOT NULL, -- 砍价金句 JSON 字符串
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);Worker 向量检索与 D1 点查(queryRAGContext)
javascript
async function queryRAGContext(vlmResult, userVoiceText, env) {
if (!env.VECTOR_INDEX || !env.AI || !env.DB) return null;
const queryText = `分析材质与提问:${vlmResult} ${userVoiceText}`;
// 1. 将查询文本向量化
const embeddingRes = await env.AI.run('@cf/baai/bge-large-en-v1.5', {
text: [queryText]
});
// 2. 语义检索 Vectorize,取最相似 Top 1
const vectorMatches = await env.VECTOR_INDEX.query(
embeddingRes.data[0],
{ topK: 2, returnMetadata: true }
);
const bestMatch = vectorMatches.matches[0];
if (!bestMatch || bestMatch.score < 0.6) return null;
// 3. 精准点查 D1,还原结构化百科
const sqlId = bestMatch.metadata.sqlId;
return await env.DB.prepare(
"SELECT * FROM panjiayuan_wiki WHERE id = ?"
).bind(sqlId).first();
}一键冷启动同步路由(/api/sync-rag)
javascript
// 读取 D1 所有百科,向量化后批量 upsert 到 Vectorize
const { results } = await env.DB.prepare("SELECT * FROM panjiayuan_wiki").all();
const upsertVectors = [];
for (const row of results) {
const vectorText = `品类:${row.category}。防坑描述:${row.description}。拿货价:${row.price_range}`;
const embeddingRes = await env.AI.run('@cf/baai/bge-large-en-v1.5', { text: [vectorText] });
upsertVectors.push({
id: `wiki_${row.id}`,
values: embeddingRes.data[0],
metadata: { type: "wiki", category: row.category, sqlId: row.id }
});
}
await env.VECTOR_INDEX.upsert(upsertVectors);六、快速重建检查清单
每次修改 Worker 代码后,按以下顺序操作:
npx wrangler deploy --keep-vars(确保wrangler.toml在当前目录)- 如 D1 数据有变更:
npx wrangler d1 execute panjiayuan-db --remote --file=./schema.sql - 如百科数据变更,重新同步向量:
curl -X POST https://your-domain.com/api/sync-rag - 验证:
curl -X POST https://your-domain.com/api/get-verdict查看source字段是否包含CF_RAG_WIKI_ID_