你是否曾想过:让 AI 不再只背维基百科,而是真正“吃懂”你自己的博客公司文档或产品手册,然后以对话式可追溯的方式为访客服务?借助 Cloudflare 的 Workers AI + Vectorize + Pages,无服务器低成本易扩展的 AutoRAG(检索增强生成)系统完全可以实现 — 并且做得非常好玩。
下面这篇文章在你已有内容的基础上做了必要的扩展:补全实战细节增加生产建议排查清单与示例 prompt,保留并扩展了你的每一章要点。阅读完它,你会拿到一套可复用的工程化方法论——从抓取向量化检索到前端体验部署与运维,一条龙落地。
第一章:地基与蓝图 —— 理解核心技术与准备环境
什么是 RAG(检索增强生成)——一句话理解
RAG 就像给 LLM 发放你自己写的“小抄”:当用户提问时,系统先从你准备的知识库检索最相关段落(Retrieval),把这些段落连同提问和历史对话一起供给 LLM(Augmented),让 LLM 在受限且有来源的材料上生成回答(Generation)。
为什么用 Cloudflare AutoRAG?
- 无服务器近用户:Workers 在 Cloudflare 边缘运行,延迟小。
- 内建向量库(Vectorize):无需自己架向量数据库。
- Workers AI:把 embeddingreranker生成模型放在同一平台,端到端简单。
环境准备(必备)
- Cloudflare 账号(绑定 WorkersPagesVectorize)
- Node.js & npm(脚本与构建)
- Wrangler CLI:
npm install -g wrangler,并wrangler login - 本地工具:
cheerio(HTML 解析)dotenv(管理密钥)
第二章:原料加工 —— 智能地喂养你的 AI
AI 的聪明来自于「好食材」与「好加工」。抓取清洗分块与 embedding 是质量核心。
2.1 抓取(Scrape)与增量更新
- 读取站点
sitemap.xml,与本地状态.scrape_state.json比对,只抓取新增/更新页面,支持增量更新,节省请求配额与时间。 - 抓取策略:优先抓文章正文标题发布时间canonical URL,忽略评论/广告脚本。
2.2 智能分块(Chunking)与标题注入
Cloudflare Vectorize 对 metadata 有 10240 字节 限制。避免超限并提升相关性的方法:
- 分块大小:
CHUNK_SIZE = 1024(字符)是安全且常用的值若你内容短则更细,长则可适当放大但务必测试 metadata 长度。 - 标题注入:在每块前注入
这篇文章的标题是《xxx》。内容片段如下:...,让检索时每块自带上下文来源信息,极大提升检索准确性。 - 智能切点:以句/段为单元切分,避免把一句话硬切成两半。
伪代码(分块示意):
function chunkText(title body CHUNK_SIZE=1024) {
const prefix = `这篇文章的标题是《${title}》。内容片段如下:`
const maxBodyPerChunk = CHUNK_SIZE - prefix.length
let chunks = []
for (let i = 0 i < body.length i += maxBodyPerChunk) {
const slice = body.slice(i i + maxBodyPerChunk)
chunks.push({ text: prefix + slice source_title: title })
}
return chunks
}
2.3 向量化(Embedding)
- 使用 Cloudflare 的中文 embedding(如
@cf/baai/bge-m3),把每个 chunk 转成向量(例如 1024 维)。 - 生成 metadata 包括
urltitlepublished_atchunk_index等,便于来源追溯与后续过滤(按时间标签等)。 - 批量插入时使用
wrangler vectorize insert,脚本中加上重试与速率限制(sleep分批次)以避免 API 限流。
2.4 抓取脚本要点(robustness)
- 自动重试与指数退避(exponential backoff)
- 降速(throttling)与并发限制,避免短时间内耗尽免费额度或被封 IP
- 增量文件
.scrape_state.json的幂等设计(记录每页 hash 或 last_mod)
第三章:搭建“大脑” —— Cloudflare Worker API(src/index.ts)
后端 Worker 是 RAG 流程的核心。它需要实现从 query 到答复的全流程并处理边界情况。
3.1 项目结构(建议)
src/
index.ts // Worker entry — RAG orchestrator
utils.ts // 工具函数(embeddings query vec formatting)
prompts.ts // system prompt 与模板
scripts/
scrape-and-embed.mjs
public/
index.html
script.js
wrangler.toml
3.2 RAG 流程(实现细节)
-
意图识别(Intent)
- 预定义“人设问答”(比如 “你是谁?”)直接返回静态响应,避免消耗模型调用。
-
向量化查询
- 使用同一 embedding 模型(
bge-m3)把用户问题向量化(保持 embedding 与索引一致)。
- 使用同一 embedding 模型(
-
两阶段检索(粗召回 + 精排序)
- 粗召回:
VECTORIZE_INDEX.query(queryVec { topK: 20 })→ 得到 20 个候选 chunk。 - 精排序(reranker):把 20 个候选和原问题发给
bge-reranker-base,得到排序并选 topK(例如 5)。
- 粗召回:
-
构建 prompt(Prompt Engineering)
- 把 topN 段按得分排序拼入 system prompt,附带严格规则:仅使用下列材料回答必须给出来源 URL长度或格式限制等。
-
生成(LLM)
- 使用
@cf/meta/llama-3.1-8b-instruct-fast或其他合适模型生成。注意上下文窗口(例如 8192 tokens)限制,必要时降低 topN 或做摘要(summarize each chunk)再供给模型。
- 使用
-
流式响应
- 打开
stream: true让前端能一边拿到答复一边显示(更好体验)。
- 打开
3.3 示例 Prompt(简化版)
System:
你是公司文档的问答助手。**只允许使用下面提供的文档段落回答问题。** 回答要简洁准确,并在回答末尾列出引用来源(标题 + URL)。
Documents:
[1] 标题: xxx
内容: ...
来源: https://your.site/xxx
User: <用户问题>
Assistant:
第四章:赋予“面容” —— 前端聊天界面(Pages + 静态文件)
一个好的 UI 会显著提升访客转化率和体验。你已经有了基本架构(index.htmlstyle.cssscript.js),下面补充一些实用细节。
前端关键点
- 打字机效果(流式):通过 Fetch 的 ReadableStream 或 Server-Sent Events(SSE)消费 Worker 的流式响应,分段渲染。
- Markdown 渲染:用
marked.js将回答中的链接渲染成可点击<a>,并对来源链接做 target_blank防逃逸。 - 引导问题:前端可以从
article_titles.json随机挑选若干句作为“示例问题”提升触发率。 - 多轮对话:维护对话历史(localStorage 或 session),把历史短时加入每次后端请求中,注意控制历史长度以免超上下文。
- 错误提示与重试:友好显示网络错误速率限制,并提供“重试”或“发送到邮箱”的选项。
第五章:部署与运维(包含免费额度速率限制策略)
首次部署(从零重建知识库)
-
清理云端索引:
wrangler vectorize delete my-knowledge-base -
清理本地状态与缓存:删除
.scrape_state.jsonvectors.jsonlarticle_titles.json(如需要) -
创建索引:
wrangler vectorize create my-knowledge-base --dimensions=1024 --metric=cosine -
生成全量 vectors:
node scrape-and-embed.mjs -
注入数据:
wrangler vectorize insert my-knowledge-base --file=vectors.jsonl(分批上传以防限流,多次传入cloudflare Vectorize不会覆盖,是追加(append),训练数据利用这种规则) -
部署后端:
wrangler deploy -
部署前端(Cloudflare Pages):上传
public/内容
日常更新流程(发布新文章后的轻流程)
node scrape-and-embed.mjs(脚本自动只抓新文章)wrangler vectorize insert my-knowledge-base --file=vectors.jsonl(插入增量)- 如果
article_titles.json更新,重新部署 Pages(或通过 CI 更新静态文件)
监控与调试
- 查看索引大小:Cloudflare 控制台 → Vectorize → 索引详情(Vectors 总数)。
- 实时日志:
wrangler tail可以实时查看 Worker 日志。 - 速率限制:脚本应实现退避与分批提交(每批 N 条,间隔 t 秒)。
成本与免费额度注意
- Cloudflare 对 Workers AI + Vectorize 有免费额度,适合个人博客和中小项目。但在全量注入或大量生成时会消耗配额,务必在脚本里限制并批量分发以避免短时大量调用。
第六章:进阶要点(安全质量提示工程故障排查)
安全与权限
- 密钥管理:使用 Cloudflare 的 Secret 或 Wrangler 环境变量,不要在前端或公开仓库暴露 API Key。
- 访问控制:若知识库或对话包含敏感信息,给 Worker 加上认证(JWTAPI KeyCloudflare Access)。
- 输入过滤:对用户输入做长度频率限制与 XSS 防护(前端渲染时对 HTML 进行消毒)。
质量评估(离线与在线)
- 离线测试:准备一组问题-参考答案集合,计算召回率(Recall@K)精确率(Precision)与最终生成质量(人工打分)。
- A/B 测试:在不同 prompt / topK / reranker 配置间进行线上 A/B,观察用户满意率与点击来源链接率。
- 自动化回归:每次大规模 reindex 或模型切换后跑一遍测试集。
Prompt Engineering 提示
- 强制模型 只引用给定材料,并列出来源。
- 限制输出格式(例如 JSON with
answerandsources),便于前端解析显示与埋点统计。 - 对长内容场景,优先做 “摘要后检索” 或 “两阶段:先召回再摘要” 的流程,减少 token 使用并提升一致性。
常见故障与排查(快速清单)
-
CORS 错误:确保 Worker 响应带
Access-Control-Allow-Origin(或由 Pages 代理)。 -
oversized metadata(元数据超限):减小标题/metadata,或把长 metadata(如全文)移动到
content,并只把必要字段放入 metadata。使用智能分块并注入短标题。 -
速率限制:加入分批延时与重试策略尽量在非高峰时间(或用后端任务队列)做全量注入。
-
检索失败(RAG 中的核心问题):
- 检查 embedding 模型是否与索引一致(相同模型/规范)。
- 调整
topKreranker 阈值与 chunking 策略(过小或过大的 chunk 都会影响召回)。 - 在检索结果不足时,返回“未找到符合你问题的来源”,并建议用户放宽或重述问题。
-
上下文超限:对历史对话或候选文本做摘要,或将对话状态保存在外部存储并按需裁剪。
第七章:实用模板与示例(快速复制粘贴)
wrangler.toml(示例片段)
name = "my-autorag-bot"
main = "src/index.ts"
compatibility_date = "2024-04-05"
[ai]
binding = "AI"
[[vectorize]]
binding = "VECTORIZE_INDEX"
index_name = "my-knowledge-base"
常用 shell 命令汇总
# 创建索引
wrangler vectorize create my-knowledge-base --dimensions=1024 --metric=cosine
# 插入数据(若大文件请分批)
wrangler vectorize insert my-knowledge-base --file=vectors.jsonl
# 删除索引(谨慎)
wrangler vectorize delete my-knowledge-base
# 部署 Worker
wrangler deploy
# 实时 tail 日志
wrangler tail
推荐系统 prompt(更完整)
System:
你是面向用户的文档问答助手。**绝对只能使用以下材料回答**。如果材料不足以直接回答,请直接说明并提供可点击的来源链接。回答要简洁明确,最后给出“来源标题 — URL”。
[DOCUMENTS]
1) 标题: ...
内容: ...
URL: ...
User: <问题>
Assistant:
最后检查清单(部署前必做)
- 抓取脚本是否已经做过全量跑通并生成 vectors.jsonl?
- 是否用增量模式验证过
.scrape_state.json? - metadata 字段是否小于 10240 字节?是否做好标题注入?
- Worker 的 prompt 是否强制要求来源并限制输出格式?
- 已实现速率限制/分批上传与重试?
- 前端是否支持流式输出并已做好 XSS 过滤?
- 密钥是否放到了 Cloudflare Secrets?前端没有暴露任何敏感信息?
- 已在测试集上跑过召回+生成质量评估?
结语 — 把“AI 助手”当作产品来打磨
把你的网站数据变成一个智能可对话的助手,不只是技术实现,更是一项产品工作:数据治理检索策略Prompt 设计用户体验与监控都要一并考虑。Cloudflare 提供了非常便捷且经济的工具链,把这些环节串起来后,你会发现,即使是个人博客,也能拥有近乎企业级的智能问答体验。
评论区(0 条)
发表评论⏳ 加载编辑器…