MediaPipe LLM Inference:在WEB浏览器中“裸跑”大语言模型
摘要:无需后端、无需显卡服务器、零 API 成本!本文基于 Google MediaPipe 官方示例,手把手教你用 WebGPU 在浏览器端直接运行 Gemma 2 / Gemma 3 270M 等轻量大模型,附完整源码与避坑清单,开发者照做即可复现。
📖 目录
- 为什么要在浏览器跑 LLM?
- 核心原理:WebGPU × LiteRT × MediaPipe
- 环境准备与硬件门槛
- 实战:5 分钟搭建本地 AI 聊天室
- 核心业务场景与产品设计
- 资源合集与结语
一、为什么要在浏览器跑 LLM?
| 场景痛点 | 纯前端 LLM 的优势 |
|---|---|
| API 费用飙升、算力难订 | 推理跑在用户本地 GPU/统一内存,云端成本≈0 |
| 敏感数据无法出网(医疗、法务、金融) | 输入输出全留在浏览器内存,天然满足隐私与合规 |
| 弱网/离线导致 AI 功能不可用 | 模型首次下载后缓存,断网依旧可用 |
| 延迟高、体验割裂 | 无需走公网,响应时间由算力决定,常见 10~80ms |
MediaPipe 的 LLM Inference API 将这些需求统一到一个纯前端 SDK 中,前端工程师只需一个 HTML 页面 + 一个 JS 文件就能完成最小可行产品,PM 也能快速验证“端智能”是不是自家业务的新卖点。
二、核心原理:WebGPU × LiteRT × MediaPipe
Prompt → 浏览器 UI→ MediaPipe Tasks Runtime (WASM + WebGPU 内核)→ LiteRT 模型文件(Gemma 2 / Gemma 3 270M / Phi-2)→ 生成 Token → 流式写回 UI
| 模块 | 作用 | 必知要点 |
|---|---|---|
| WebGPU | 让 JavaScript 调用显卡算力 | Chrome 121+/Edge 121+ 默认启用,可用 navigator.gpu 检测 |
| LiteRT (旧称 TFLite) | 针对端侧优化的推理格式 | Web 端加载 .bin / .task,含量化权重与 tokenizer |
| MediaPipe Tasks Runtime | 将模型、tokenizer、KV cache 打包成 JS 可用接口 | 通过 FilesetResolver.forGenAiTasks() 下载所需的 WASM + shader |
| LlmInference API | 上层封装,提供 generateResponse、流式回调、参数控制 | 支持 maxTokens、temperature、topK、randomSeed 等配置 |
✅ 当前官方示例已验证 Gemma 2 2B (int8/int4)、Phi-2,以及 Gemma 3 270M int8(Kaggle 提供 TFLite/LiteRT 版本);尚未发布的“未来型号”并不能直接套用。
2.1 Wasm 运行时如何装配?
- 在
index.js(本地与 官方仓库同名文件)中,我们通过FilesetResolver.forGenAiTasks('https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai/wasm')拉取genai.wasm、tasks-core.wasm等依赖,它们封装了 tokenizer、调度器与 LiteRT kernel。 - 这些 Wasm 模块使用
SharedArrayBuffer与页面主线程通信,并在 COOP/COEP 正确设置后启用多线程 worker,保证加载 1GB 级模型也不会阻塞 UI。 - MediaPipe 运行时会根据
modelAssetPath只下载必要的算子与权重 metadata,保持主包体积精简,同时允许我们在业务层动态切换不同模型。
2.2 WebGPU 负责算力调度
- Wasm 模块初始化时会隐式调用
navigator.gpu.requestAdapter()、adapter.requestDevice(),并请求shader-f16等特性;若设备不满足,控制台会输出可读的错误,方便我们在 UI 中向用户提示。 - 真正的矩阵乘法、RMSNorm、注意力运算会被编译成 WGSL shader,分块提交给 GPU Compute Pipeline。这就是为什么 Gemma 2B 在桌面 Chrome 中也能跑到 10~20 token/s ——瓶颈从网络延迟转移到了本地显卡。
- WebGPU 处理完一批 token 后,MediaPipe 会立刻从 GPU buffer 中取回结果并触发
displayPartialResults(partial, complete)回调,实现index.js和官方 demo 里熟悉的“流式打字机”效果。
2.3 与项目代码的映射
- 仓库根目录的
index.js与示例仓库保持完全一致:顶部导入FilesetResolver、LlmInference,中间指定modelFileName(如model/gemma3-1B-it-int4.task或 Kaggle 下载的.bin),底部调用runDemo()。 - 我们只需要在这个文件里调整 prompt 模板、采样参数或 UI 按钮逻辑,就可以把 MediaPipe LLM 嵌入任意 Web 应用;若集成到 React/Vue,只需把
runDemo()放进对应生命周期,并用组件状态替代document.getElementById。
三、环境准备与硬件门槛
3.1 浏览器支持
| 平台 | 最低版本 | 备注 |
|---|---|---|
| Chrome / Edge (Windows, macOS, Linux) | 121+ | 默认支持 WebGPU,无需手动开启 |
| Safari (macOS 14+) | 需在 Develop > Experimental Features 中启用 WebGPU | 仍属实验阶段 |
| Android Chrome (旗舰机) | 121+ | 仅限高端 SoC,表现不稳定,谨慎用于生产 |
快速检测:在控制台输入
await navigator.gpu?.requestAdapter(),若返回对象说明 WebGPU 可用。
3.2 硬件建议
- 显存/统一内存:≥2GB 可运行 Gemma 2B int4;≥512MB 即可运行 Gemma 3 270M int8。
- GPU:Apple M1/M2/M3、Intel Iris Xe、NVIDIA GTX 1650 起步,越高越好。
- 存储:至少 2GB 用于缓存模型。
四、实战:5 分钟搭建本地 AI 聊天室
4.1 项目结构
mediapipe-llm-demo/
├── index.html # 前端页面
├── index.js # 核心逻辑(MediaPipe API 调用)
└── model/ # 模型文件目录└── gemma-3-tflite-gemma3-1b-it-int4-v1/└── gemma3-1B-it-int4.task
4.2 完整代码实现
📄 index.html(前端页面)
<!doctype html>
<html lang="en">
<head><title>LLM Inference Web Demo</title>
</head>
<body>Input:<br /><textarea id="input" style="height: 300px; width: 600px"></textarea><br /><input type="button" id="submit" value="Get Response" disabled /><br /><br />Result:<br /><textarea id="output" style="height: 300px; width: 600px"></textarea><script type="module" src="index.js"></script>
</body>
</html>
📄 index.js(核心逻辑)
import {FilesetResolver, LlmInference} from 'https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai';const input = document.getElementById('input');
const output = document.getElementById('output');
const submit = document.getElementById('submit');// 模型文件路径(根据你下载的模型调整)
const modelFileName = 'model/gemma-3-tflite-gemma3-1b-it-int4-v1/gemma3-1B-it-int4.task';/*** 显示流式生成的部分结果*/
function displayPartialResults(partialResults, complete) {output.textContent += partialResults;if (complete) {if (!output.textContent) {output.textContent = 'Result is empty';}submit.disabled = false;}
}/*** 主函数:初始化 LLM Inference 任务*/
async function runDemo() {// 1. 加载 WebAssembly 文件集const genaiFileset = await FilesetResolver.forGenAiTasks('https://cdn.jsdelivr.net/npm/@mediapipe/tasks-genai/wasm');let llmInference;// 2. 绑定按钮点击事件submit.onclick = () => {output.textContent = '';submit.disabled = true;llmInference.generateResponse(input.value, displayPartialResults);};submit.value = 'Loading the model...'// 3. 创建 LLM Inference 实例LlmInference.createFromOptions(genaiFileset, {baseOptions: {modelAssetPath: modelFileName},// 可选配置:// maxTokens: 512, // 最大 token 数(输入+输出)// randomSeed: 1, // 随机种子(可复现结果)// topK: 40, // Top-K 采样// temperature: 0.8, // 温度参数(0.0=确定性,1.0=高随机性)}).then(llm => {llmInference = llm;submit.disabled = false;submit.value = 'Get Response'}).catch(() => {alert('Failed to initialize the task.');});
}runDemo();
4.3 模型下载地址(LiteRT 格式)
根据你的硬件选择合适的模型:
| 模型名称 | 参数量 | 显存需求 | Kaggle 下载地址 | 适用场景 |
|---|---|---|---|---|
| Gemma 3 270M (int8) | 270M | ~512MB | 点击下载 | 入门测试、低端设备 |
| Gemma 3 1B (int4) | 1B | ~1GB | HuggingFace 下载 | 平衡性能与质量 |
| Gemma 2 2B (int8) | 2B | ~2GB | 点击下载 | 最佳效果、高端设备 |
⚠️ 关键提示:必须下载 LiteRT 格式(
.task或.bin文件),不能使用原始的.tflite文件!
4.4 快速启动步骤
步骤 1:创建项目目录
mkdir mediapipe-llm-demo
cd mediapipe-llm-demo
步骤 2:创建文件
将上面的 index.html 和 index.js 代码保存到项目根目录。
步骤 3:下载模型文件
# 创建模型目录
mkdir -p model/gemma-3-tflite-gemma3-1b-it-int4-v1# 下载 Gemma 3 1B 模型(约 600MB)
cd model/gemma-3-tflite-gemma3-1b-it-int4-v1
wget https://huggingface.co/litert-community/Gemma3-1B-IT/resolve/main/gemma3-1b-it-int4.task -O gemma3-1B-it-int4.task# 返回项目根目录
cd ../..
如果没有安装
wget,可以直接在浏览器中访问下载链接,然后手动放入model目录。
步骤 4:启动本地 HTTP 服务器
⚠️ 重要:由于浏览器的 CORS 安全策略,不能直接双击打开 HTML 文件,必须通过 HTTP 服务器访问。
# 方法 1:使用 Python 3
python3 -m http.server 8000# 方法 2:使用 Python 2
python -m SimpleHTTPServer 8000# 方法 3:使用 Node.js
npx http-server -p 8000
步骤 5:访问应用
打开 Chrome 浏览器,访问:
http://localhost:8000
首次加载需要 10-30 秒(初始化模型),之后即可流畅使用。看到按钮变为 “Get Response” 即表示加载成功!
4.5 使用示例
在输入框中尝试以下 Prompt:

五、核心业务场景与产品设计
5.1 隐私保护型文档处理 🔒
场景:律师事务所需要 AI 分析客户合同,但不能将敏感信息上传到 OpenAI 等云端服务。
实现思路:
// 用户上传 PDF 后,在浏览器中提取文本
const pdfText = await extractTextFromPDF(file);// 本地 LLM 生成风险分析
const prompt = `请分析以下合同的潜在法律风险:\n\n${pdfText}`;
llmInference.generateResponse(prompt, displayResults);
商业价值:
- 符合 GDPR、HIPAA 等隐私法规
- 避免数据泄露风险
- 降低 API 调用成本
5.2 离线生产力工具 ✈️
场景:作家在飞机上写作,需要 AI 辅助润色文章。
实现思路:
// 利用 Service Worker 缓存模型
self.addEventListener('install', (event) => {event.waitUntil(caches.open('llm-cache').then((cache) => {return cache.addAll(['/model/gemma3-1b-it-int4.task','/index.html','/index.js']);}));
});
适用场景:
- 旅行中的翻译助手
- 离线写作辅助
- 弱网环境下的内容生成
5.3 Web 游戏中的智能 NPC 🎮
场景:RPG 网页游戏需要 NPC 动态生成对话。
实现示例:
const npcPrompt = `
你是一位智慧的老法师,玩家问你:"${playerInput}"
请以老法师的口吻回复(不超过 50 字):
`;llmInference.generateResponse(npcPrompt, (reply) => {showNPCDialog(reply);
});
优势:
- 零网络延迟(本地推理)
- 零 API 成本(玩家自己的算力)
- 无限对话轮次
六、资源合集与结语
6.1 官方资源
- 📄 官方文档:https://ai.google.dev/edge/mediapipe/solutions/genai/llm_inference/web_js
- 💻 示例仓库:https://github.com/google-ai-edge/mediapipe-samples/tree/main/examples/llm_inference/js
6.2 模型下载地址(LiteRT 格式)
| 模型 | Kaggle 地址 |
|---|---|
| Gemma 3 270M (int8) | https://www.kaggle.com/models/google/gemma-3/tfLite/gemma-3-270m-it-int8 |
| Gemma 2 2B (int8) | https://www.kaggle.com/models/google/gemma-2/tfLite/gemma2-2b-it-gpu-int8 |
| 模型 | HuggingFace 直链 |
|---|---|
| Gemma 3 1B (int4) | https://huggingface.co/litert-community/Gemma3-1B-IT/resolve/main/gemma3-1b-it-int4.task |
6.3 技术支持
- 🐛 问题反馈:https://github.com/google-ai-edge/mediapipe/issues
- 💬 社区讨论:https://discuss.tensorflow.org/c/tflite
总结
MediaPipe LLM Inference 让浏览器端 AI 从"概念验证"走向"生产可用"。通过本文,你已经掌握了:
✅ 核心原理:WebGPU + LiteRT + MediaPipe 技术栈
✅ 快速上手:5 分钟搭建本地 AI 聊天室
✅ 避坑指南:CORS、模型格式、WebGPU 兼容性
✅ 业务场景:隐私保护、离线可用、成本节省
✅ 完整代码:可直接复制运行的 HTML + JS
作者提醒:端侧 LLM 不是"更聪明",而是"更私密、更便宜、更稳定"。先用 Gemma 3 270M 或 1B 跑通 Demo,再结合自家场景设计 Prompt 与功能体验,就能快速验证端智能的真实价值。
