ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

WebLLM 浏览器端视觉语言模型推理实战:基于 Phi-3.5-vision 的多模态图片理解示例全解析

2026/9/13 16:47:08 拓冰建站 浏览量
WebLLM 浏览器端视觉语言模型推理实战:基于 Phi-3.5-vision 的多模态图片理解示例全解析 WebLLM 浏览器端视觉语言模型推理实战基于 Phi-3.5-vision 的多模态图片理解示例全解析【免费下载链接】web-llmHigh-performance In-browser LLM Inference Engine项目地址: https://gitcode.com/GitHub_Trending/we/web-llmWebLLM 是运行在浏览器内部的 LLM 推理引擎而本示例则进一步展示了如何在其上运行视觉语言模型VLM让网页应用直接看懂图片。本文将围绕仓库中 examples/vision-model 示例完整讲解它的运行方式、源码结构与底层原理从 Web Worker 引擎创建、多模态消息构造到图片转 base64 预处理、多图 prefill 与多轮追问读完即可照搬这套模式在自己的 WebLLM 项目中实现端侧图片问答能力。示例概览一个最小化的多模态 Web 应用examples/vision-model目录提供的是一个最小化演示目标是在 webapp 环境中展示 WebLLM 的视觉能力——使用 Phi-3.5-vision 视觉模型在浏览器内直接对网络图片完成内容识别与多轮对话。它的全部构成如下examples/vision-model/ ├── src/ │ ├── utils.ts # 图片 URL 转 base64 的工具函数 │ ├── vision_model.html # 页面骨架负责展示初始化进度与结果 │ ├── vision_model.ts # 主逻辑引擎创建、多模态请求、多轮对话 │ └── worker.ts # Web Worker 端引擎处理器 ├── README.md # 快速开始说明 └── package.json # 依赖与构建脚本整个示例不依赖任何后端服务模型权重、推理计算全部发生在浏览器端基于 WebGPU前端只负责收集图片与展示输出。这也正是 WebLLM 项目High-performance In-browser LLM Inference Engine定位的直接体现。快速开始安装、启动与构建原 README 给出的运行步骤非常简洁在examples/vision-model目录下依次执行npm install npm startnpm start实际执行的是 Parcel 的开发服务器从 package.json 可以看到完整脚本定义{ scripts: { start: parcel src/vision_model.html --port 8888, build: parcel build src/vision_model.html --dist-dir lib }, devDependencies: { buffer: ^5.7.1, parcel: ^2.8.3, process: ^0.11.10, tslib: ^2.3.1, typescript: ^4.9.5, url: ^0.11.3 }, dependencies: { mlc-ai/web-llm: ^0.2.84 } }启动后访问http://localhost:8888页面会加载模型并在init-label标签上实时显示初始化进度示例的输出统一打印在浏览器控制台页面本身只提供h2WebLLM Test Page/h2和几个空标签见 vision_model.html。如需生成生产构建则运行npm run build产物输出到lib/目录。说明当前示例声明依赖mlc-ai/web-llm^0.2.84模型从远程下载后在本地WebGPU推理因此请使用支持 WebGPU 的浏览器访问。引擎创建Web Worker 与主线程两种模式主逻辑位于 vision_model.ts文件开头的常量USE_WEB_WORKER true决定引擎的承载方式。示例默认把推理放到 Web Worker 中避免阻塞 UI 线程import * as webllm from mlc-ai/web-llm; import { imageURLToBase64 } from ./utils; const USE_WEB_WORKER true; const engine: webllm.MLCEngineInterface USE_WEB_WORKER ? await webllm.CreateWebWorkerMLCEngine( new Worker(new URL(./worker.ts, import.meta.url), { type: module, }), selectedModel, engineConfig, chatOpts, ) : await webllm.CreateMLCEngine(selectedModel, engineConfig, chatOpts);两个工厂函数的导出位置可以分别在 src/index.tsCreateMLCEngine、CreateWebWorkerMLCEngine中确认。Worker 侧只需极简的桥接代码见 worker.tsimport { WebWorkerMLCEngineHandler } from mlc-ai/web-llm; const handler new WebWorkerMLCEngineHandler(); self.onmessage (msg: MessageEvent) { handler.onmessage(msg); };WebWorkerMLCEngineHandler负责在主线程与 Worker 之间转发初始化进度、请求与生成结果。若想对比两种模式把USE_WEB_WORKER改为false即可走CreateMLCEngine的主线程路径——这一模式切换成本极低便于实测二者的界面流畅度差异。引擎配置与上下文窗口示例通过两个配置对象控制引擎行为const engineConfig: webllm.MLCEngineConfig { initProgressCallback: initProgressCallback, logLevel: INFO, // specify the log level }; const chatOpts { context_window_size: 6144, };initProgressCallback在初始化期间持续回调InitProgressReport包含progress、timeElapsed、text字段定义见 src/types.ts页面借此把下载/加载进度写到init-labellogLevel支持TRACE、DEBUG、INFO、WARN、ERROR、SILENT六级见 src/types.ts 的LOG_LEVELS生产环境可调低以减小日志开销chatOpts中的context_window_size属于ChatOptionsPartialChatConfig定义见 src/config.ts用于覆盖模型默认的 KV Cache 上下文长度。视觉场景下图片会被切块编码进序列序列更长示例将其放宽到 6144同时这会相应增加显存占用需按实际设备调整。图片预处理从 HTTP URL 到 base64WebLLM 的多模态接口同时接受HTTP 图片 URL与base64 编码的图片数据示例特意演示了二者混用。对于第一张图片它先把远程 URL 转成 base64 再提交转换逻辑在 utils.tsexport function getImageDataFromURL(url: string): PromiseImageData { return new Promise((resolve, reject) { const img: any new Image(); img.crossOrigin anonymous; // Important for CORS img.onload () { const canvas: HTMLCanvasElement document.createElement(canvas); const ctx: CanvasRenderingContext2D canvas.getContext(2d)!; canvas.width img.width; canvas.height img.height; ctx.drawImage(img as CanvasImageSource, 0, 0); const imageData ctx.getImageData(0, 0, img.width, img.height); resolve(imageData); }; img.onerror () reject(new Error(Failed to load image)); img.src url; }); } export async function imageURLToBase64(url: string): Promisestring { const imageData: ImageData await getImageDataFromURL(url); const canvas document.createElement(canvas); const ctx canvas.getContext(2d); canvas.width imageData.width; canvas.height imageData.height; ctx!.putImageData(imageData, 0, 0); return canvas.toDataURL(); }实现要点crossOrigin anonymous是跨域加载图片的关键否则 canvas 会被污染后续toDataURL()抛错利用Image→canvas→ImageData的链路最终通过canvas.toDataURL()产出data:image/...形式的 base64 字符串示例中远程图还统一加了proxyUrlhttps://cors-anywhere.herokuapp.com/作为 CORS 代理。需要注意的是该代理为社区公共服务稳定性不受本仓库控制在自有环境中更稳妥的做法是把图片托管在与页面同源的位置或由自有后端代理。多模态消息构造与引擎侧校验视觉问答的本质是构造 OpenAI 风格的 Chat Completion 请求其中user消息的content不再是纯字符串而是text与image_url两类内容块的数组。示例第一轮请求同时投喂两张图const messages: webllm.ChatCompletionMessageParam[] [ { role: user, content: [ { type: text, text: List the items in each image concisely. }, { type: image_url, image_url: { url: url_base64_street } }, { type: image_url, image_url: { url: proxyUrl url_https_sea } }, ], }, ]; const request0: webllm.ChatCompletionRequest { stream: false, // can be streaming, same behavior messages: messages, }; const reply0 await engine.chat.completions.create(request0);底层协议类型定义在 src/openai_api_protocols/chat_completion.tsChatCompletionContentPart ChatCompletionContentPartText | ChatCompletionContentPartImage其中图片块为{ type: image_url, image_url: { url, detail? } }detail支持auto | low | high当前实现不接受detail传入会抛UnsupportedDetailError。引擎侧对图片 URL 还有一道强校验同样位于 src/openai_api_protocols/chat_completion.tsimage_url.url必须以data:image或http开头否则抛出UnsupportedImageURLError。这说明直接传本地相对路径如/img/a.png是不合法的——要么给绝对 HTTP 地址要么走 base64。同时stream参数true/false对多模态请求同样适用行为与文本模型一致。三轮对话流程prefill 与 KV Cache 复用示例把演示组织成三个阶段串起视觉问答的典型用法完整代码见 vision_model.ts第一轮多图 prefill。一条 user 消息内混排 1 段文本 2 张图一张 base64、一张 HTTP URL模型一次理解两张图并列出每张图中的物品第二轮纯文本追问。把第一轮回复以assistant消息压回历史再追加一条纯文本 user 消息What is special about each image?考察模型基于已编码图片的上下文理解能力第三轮单图追问。继续追加历史并在新 user 消息中带入第三张新图片What about this image?验证对话过程中持续注入新图像的能力。// 第二轮 messages.push({ role: assistant, content: replyMessage0 }); messages.push({ role: user, content: What is special about each image? }); // 第三轮 messages.push({ role: assistant, content: replyMessage1 }); messages.push({ role: user, content: [ { type: text, text: What about this image? Answer concisely. }, { type: image_url, image_url: { url: proxyUrl url_https_tree } }, ], });每轮生成后示例同时打印三个对象console.log(reply0); // 完整 ChatCompletion 响应含 finish_reason、usage 等 console.log(replyMessage0); // 通过 engine.getMessage() 获取的纯文本回复 console.log(reply0.usage); // token 用量统计这里有个重要的引擎行为chat.completions.create()是功能性接口多轮对话历史需要调用方自己维护示例即用messages数组累积而 src/types.ts 中MLCEngineInterface.chatCompletion的文档注释指出作为隐式内部优化引擎检测到多轮对话时会保留 KV Cache、只对新增 token 做 prefill这正是示例三轮请求一次比一次快的原因。getMessage()则用于取回当前轮次的生成文本定义见 src/types.ts 的getMessage。模型选择与 VLM 资源要求示例选用的模型 ID 为const selectedModel Phi-3.5-vision-instruct-q4f16_1-MLC;该模型以预构建记录形式存在于 WebLLM 的prebuiltAppConfig中见 src/config.ts。从源码记录可以看到 Phi-3.5-vision 的两个量化版本模型 IDvram_required_MB是否低资源友好备注Phi-3.5-vision-instruct-q4f16_1-MLC3952.18是model_type: ModelType.VLM默认context_window_size: 4096Phi-3.5-vision-instruct-q4f32_1-MLC5879.84是model_type: ModelType.VLM默认context_window_size: 4096model_type: ModelType.VLM标记表明该模型走视觉语言模型分支vram_required_MB是官方预估的显存需求可用于在加载前判断当前设备是否够用。示例额外把context_window_size提到 6144相当于在默认 4096 之上为长图片序列预留了更多 KV Cache 空间。若设备报显存不足OOM可优先下调该值重试。进阶本地开发 WebLLM 核心包README 专门给出了一条面向核心贡献者的提示如果要在本地修改并调试 WebLLM 核心源码可以把示例的依赖指向仓库根目录mlc-ai/web-llm: file:../..将 package.json 中的mlc-ai/web-llm依赖改为上述file:协议路径再执行npm install重新链接。原 README 强调该选项仅在确实需要 hack WebLLM 核心包时才推荐——日常使用请保持 npm 上发布的版本。改依赖后需要先按项目的源码构建流程产出本地web-llm包完整步骤见文档 docs/developer/building_from_source.rst。构建成功后示例改动会立即反映到npm start的调试会话中非常适合追踪引擎内部行为配合logLevel: DEBUG效果更佳。小结与可复用清单examples/vision-model用不到两百行代码完整覆盖了 WebLLM 多模态能力的关键链路可以作为自有视觉应用的起点运行npm install npm start浏览器访问localhost:8888观察控制台输出引擎CreateWebWorkerMLCEngine默认Worker 内推理或CreateMLCEngine主线程通过USE_WEB_WORKER一键切换配置MLCEngineConfiginitProgressCallback、logLevel与ChatOptionscontext_window_size分工明确图片输入图片可以是 HTTP URL须以http开头或data:imagebase64跨域图片需crossOrigin anonymous并经 canvas 转 base64多模态消息content为text/image_url内容块数组支持单消息多图多轮对话自行累积messages历史引擎自动复用 KV Cache 只 prefill 新增内容模型Phi-3.5-vision-instruct-q4f16_1-MLC属于预构建 VLM显存约 3.95 GBq4f16_1 量化档二次开发将依赖改为file:../..并按 building_from_source.rst 构建即可调试 WebLLM 核心。把三轮对话换成真实的用户交互——本地图片选择、canvas 截图、摄像头帧——就可以扩展出完整的端侧视觉问答、OCR、无障碍图像描述等应用全程无需任何云端推理服务。【免费下载链接】web-llmHigh-performance In-browser LLM Inference Engine项目地址: https://gitcode.com/GitHub_Trending/we/web-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考