《AI 前端实战》第 7/8 篇
上篇:Agent 前端状态机(多工具并发、Abort 与错误隔离)
下篇预告:AI 前端监控与降级
第 6 篇把 Agent 调度讲清楚了。很多场景下一步是检索 ------文档、笔记、工单塞进上下文。
全部走云端 Embedding + 向量库,延迟和成本都上去;有些数据还不适合出浏览器。
这一篇:浏览器里用 Transformers.js 算 Embedding,WebGPU 加速,内存里做检索------端侧 RAG 最小闭环。
标签思路 :WebGPU,RAG,React,AI,前端
你将学到
- 端侧 RAG 适用 / 不适用场景
- Transformers.js 加载 Embedding 模型
- WebGPU 加速与降级路径
- 内存版向量检索(cosine + Top-K)
- 与云端 RAG 的边界怎么划
一、端侧 RAG 解决什么问题
| 场景 | 端侧 RAG 优势 | 云端 RAG 更合适 |
|---|---|---|
| 私有笔记 / 本地 PDF | 数据不出设备 | 跨设备同步、协作 |
| 弱网 / 离线预览 | 检索不依赖 API | 模型本身也要在线 |
| 高频小库(< 5k 段) | 无 Embedding 账单 | 百万级文档、混合检索 |
| 原型 / 内网禁外网 | 零后端向量库 | 生产 SLA、审计、重排 |
结论:端侧 RAG 是补充,不是替代。适合「小库 + 强隐私 + 可接受首次加载慢」。
二、架构:浏览器内最小 RAG 闭环
text
[用户文档] → chunk → Transformers.js embed (WebGPU) → IndexedDB / 内存
[用户提问] → embed query → cosine Top-K → 拼 prompt → /api/chat(第 2 篇)
检索可建模为本地 tool(第 6 篇):phase: running 时展示「正在检索本地知识库...」。
三、Transformers.js:加载 Embedding 模型
bash
npm i @huggingface/transformers
ts
import { pipeline, env } from "@huggingface/transformers";
env.backends.onnx.wasm.numThreads = navigator.hardwareConcurrency ?? 4;
let embedder: Awaited<ReturnType<typeof pipeline>> | null = null;
export async function getEmbedder() {
if (embedder) return embedder;
embedder = await pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2", { device: "webgpu" });
return embedder;
}
export async function embedTexts(texts: string[]): Promise<Float32Array[]> {
const model = await getEmbedder();
const out = await model(texts, { pooling: "mean", normalize: true });
const dim = out.dims[1] as number;
return texts.map((_, i) => out.data.slice(i * dim, (i + 1) * dim));
}
| 模型 | 维度 | 体积 | 说明 |
|---|---|---|---|
Xenova/all-MiniLM-L6-v2 |
384 | ~23MB | Demo 首选 |
Xenova/multilingual-e5-small |
384 | ~130MB | 中英混合 |
Xenova/bge-small-en-v1.5 |
384 | ~33MB | 英文稍好 |
首次加载会下载 ONNX + 权重,务必做进度 UI。
四、WebGPU:加速与注意点
ts
async function pickDevice(): Promise<"webgpu" | "wasm"> {
if (!("gpu" in navigator)) return "wasm";
try {
const adapter = await navigator.gpu.requestAdapter();
return adapter ? "webgpu" : "wasm";
} catch { return "wasm"; }
}
| 点 | 说明 |
|---|---|
| Safari / 旧 Chrome | 可能只有 WASM,慢 3~10 倍 |
| 首次编译 Shader | 第一次 inference 额外数百 ms~数 s |
| 内存 | GPU + CPU 双份 buffer,大 batch 易 OOM |
| 移动端 | 能跑但慢;限制 chunk 数、降低 batch |
产品文案:「本地检索」≠「本地大模型」------生成仍走云端 API。
五、分块与内存向量检索
ts
function chunkText(text: string, size = 500, overlap = 80): string[] {
const chunks: string[] = [];
for (let i = 0; i < text.length; i += size - overlap) chunks.push(text.slice(i, i + size));
return chunks.filter((c) => c.trim().length > 20);
}
type ChunkRecord = { id: string; text: string; vector: Float32Array };
function cosineTopK(queryVec: Float32Array, records: ChunkRecord[], k: number) {
const scored = records.map((r) => ({
text: r.text,
score: r.vector.reduce((s, v, i) => s + v * queryVec[i], 0), // 已 normalize → 点积
}));
return scored.sort((a, b) => b.score - a.score).slice(0, k);
}
| chunk 数 | 建议 |
|---|---|
| < 2k | 主线程暴力 Top-K OK |
| 2k~10k | Web Worker + WASM |
| > 10k | 上云端或 hnswlib-wasm |
向量持久化用 IndexedDB (ArrayBuffer),避免每次刷新重新 embed。
六、接到 Chat 与 Agent Tool
ts
function buildRagPrompt(question: string, hits: { text: string; score: number }[]) {
const context = hits.map((h, i) => `[${i + 1}] (${h.score.toFixed(3)})\n${h.text}`).join("\n\n");
return `仅根据以下片段回答;不知道就说不知道。\n\n## 片段\n${context}\n\n## 问题\n${question}`;
}
本地检索可封装为 tool search_local_kb,前端 Tool Handler 内跑检索,结果回灌------与第 4、6 篇同一套 UI;记得传 AbortSignal。
七、与云端 RAG 的边界
| 能力 | 浏览器端 | 云端 |
|---|---|---|
| Embedding | Mini 模型 | 大模型、批处理 |
| 向量库 | 内存 / IDB | Milvus / pgvector |
| 混合检索 / Rerank | 难 | 成熟 |
| 权限 | 单用户设备 | 租户 / ACL |
推荐:默认云端 RAG;设置里提供「仅本地检索」给隐私场景。
踩坑清单
- 主线程 embed 整本书------UI 卡死;放 Web Worker。
- 不做 normalize------Top-K 乱序。
- chunk 过大 / 过小------500/80 只是起点。
- WebGPU 失败当 bug------必须 WASM 降级 + 文案。
- IndexedDB 丢 Float32 类型 ------用
ArrayBuffer存取。 - 低分片段也进 prompt------设 score 阈值。
- 混淆端侧 RAG 与端侧 LLM------用户以为完全离线。
小结
浏览器端 RAG 最小路径:
- 场景选对:小库、隐私、Demo
- Transformers.js + WebGPU,WASM 兜底
- 分块 → embed → Top-K → 模板拼 prompt
- IndexedDB 持久化
- 与 Agent tool 统一,停止与错误隔离复用第 6 篇
下篇预告 :《AI 前端实战》第 8/8 篇(收官)
AI 前端监控与降级:首 Token 延迟、限流与熔断。
系列导航
- 2026 年前端还要不要卷 AI?一张能力地图讲清
- Next.js + Vercel AI SDK:30 分钟搭出流式 Chat
- Streaming UI 工程化:SSE、断线重连、消息合并
- Tool Calling 前端怎么接:进度、错误、权限边界
- 生成式 UI 实战:JSON Schema + React 动态渲染
- Agent 前端状态机:多工具并发、Abort 与错误隔离
- 浏览器端 RAG:Transformers.js + WebGPU 本地检索入门(本篇)
- AI 前端监控与降级:首 Token 延迟、限流与熔断