问答社区
WebLLM与OpenAI API完全兼容。 本地任何开源模型上使用相同的 OpenAI API
WebLLM与OpenAI API完全兼容。 也就是说,您可以在本地任何开源模型上使用相同的 OpenAI API ,其功能包括流式处理、JSON 模式、函数调用 (WIP) 等。
我们可以带来很多有趣的机会,为每个人构建人工智能助手,并在享受 GPU 加速的同时实现隐私。
您可以使用 WebLLM 作为基础npm 包,并按照以下示例在其上构建您自己的 Web 应用程序。该项目是MLC LLM的姊妹项目,可实现跨硬件环境的 LLM 通用部署。
-
浏览器内推理:WebLLM 是一种高性能、浏览器内语言模型推理引擎,利用 WebGPU 进行硬件加速,直接在 Web 浏览器中实现强大的 LLM 操作,无需服务器端处理。
-
完全 OpenAI API 兼容性:使用 OpenAI API 将您的应用程序与 WebLLM 无缝集成,并具有流式传输、JSON 模式、logit 级别控制、播种等功能。
-
结构化 JSON 生成:WebLLM 支持最先进的 JSON 模式结构化生成,在模型库的 WebAssembly 部分中实现,以实现最佳性能。检查HuggingFace 上的WebLLM JSON Playground,尝试使用自定义 JSON 模式生成 JSON 输出。
-
广泛的模型支持:WebLLM 原生支持一系列模型,包括 Llama 3、Phi 3、Gemma、Mistral、Qwen(通义千问)等,使其适用于各种 AI 任务。有关完整支持的型号列表,请查看MLC 型号。
-
自定义模型集成:轻松集成和部署 MLC 格式的自定义模型,让您能够根据特定需求和场景调整 WebLLM,增强模型部署的灵活性。
-
即插即用集成:使用 NPM 和 Yarn 等包管理器或直接通过 CDN 轻松将 WebLLM 集成到您的项目中,并提供全面的示例和用于连接 UI 组件的模块化设计。
-
流式传输和实时交互:支持流式聊天完成,允许实时输出生成,从而增强聊天机器人和虚拟助手等交互式应用程序。
-
Web Worker 和 Service Worker 支持:通过将计算卸载到单独的工作线程或服务工作线程,优化 UI 性能并有效管理模型的生命周期。
-
Chrome 扩展支持:使用 WebLLM 通过自定义 Chrome 扩展来扩展 Web 浏览器的功能,并提供可用于构建基本和高级扩展的示例。
检查MLC 型号上可用型号的完整列表。 WebLLM 支持这些可用模型的子集,可以在 访问该列表prebuiltAppConfig.model_list
。
以下是当前支持的主要模型系列:
- 羊驼:羊驼 3、羊驼 2、Hermes-2-Pro-Llama-3
- Φ:Φ3、Φ2、Φ1.5
- 杰玛:杰玛-2B
- 米斯特拉尔:米斯特拉尔-7B-v0.3、Hermes-2-Pro-Mistral-7B、NeuralHermes-2.5-Mistral-7B、OpenHermes-2.5-Mistral-7B
- Qwen (通义千问) : Qwen2 0.5B, 1.5B, 7B
如果您需要更多模型,请通过打开问题请求新模型,或检查自定义模型以了解如何通过 WebLLM 编译和使用您自己的模型。
了解如何使用 WebLLM 将大型语言模型集成到您的应用程序中,并通过这个简单的聊天机器人示例生成聊天完成:
有关更大、更复杂项目的高级示例,请查看WebLLM 聊天。
示例文件夹中提供了不同用例的更多示例。
WebLLM 提供了一个极简且模块化的界面来访问浏览器中的聊天机器人。该包以模块化方式设计,可以连接到任何 UI 组件。
# npm
npm install @mlc-ai/web-llm
# yarn
yarn add @mlc-ai/web-llm
# or pnpm
pnpm install @mlc-ai/web-llm
然后将模块导入到您的代码中。
// Import everything
import * as webllm from "@mlc-ai/web-llm";
// Or only import what you need
import { CreateMLCEngine } from "@mlc-ai/web-llm";
感谢jsdelivr.com ,WebLLM 可以直接通过 URL 导入,并在jsfiddle.net、Codepen.io和Scribbler等云开发平台上开箱即用:
import * as webllm from "https://esm.run/@mlc-ai/web-llm";
它也可以动态导入为:
const webllm = await import ("https://esm.run/@mlc-ai/web-llm");
WebLLM 中的大多数操作都是通过MLCEngine
接口调用的。您可以MLCEngine
通过调用工厂函数来创建实例并加载模型CreateMLCEngine()
。
(请注意,加载模型需要下载,并且在之前没有缓存的情况下首次运行可能会花费大量时间。您应该正确处理此异步调用。)
import { CreateMLCEngine } from "@mlc-ai/web-llm";
// Callback function to update model loading progress
const initProgressCallback = (initProgress) => {
console.log(initProgress);
}
const selectedModel = "Llama-3.1-8B-Instruct-q4f32_1-MLC";
const engine = await CreateMLCEngine(
selectedModel,
{ initProgressCallback: initProgressCallback }, // engineConfig
);
在底层,该工厂函数执行以下步骤,首先创建引擎实例(同步),然后加载模型(异步)。您也可以在您的应用程序中单独执行它们。
import { MLCEngine } from "@mlc-ai/web-llm";
// This is a synchronous call that returns immediately
const engine = new MLCEngine({
initProgressCallback: initProgressCallback
});
// This is an asynchronous call and can take a long time to finish
await engine.reload(selectedModel);
成功初始化引擎后,您现在可以通过界面使用 OpenAI 风格的聊天 API 调用聊天完成engine.chat.completions
。有关参数及其描述的完整列表,请查看下面的部分和OpenAI API 参考。
(注意:该model
参数不受支持,此处将被忽略。而是调用CreateMLCEngine(model)
或 ,engine.reload(model)
如上面的创建 MLCEngine所示。)
const messages = [
{ role: "system", content: "You are a helpful AI assistant." },
{ role: "user", content: "Hello!" },
]
const reply = await engine.chat.completions.create({
messages,
});
console.log(reply.choices[0].message);
console.log(reply.usage);
WebLLM 还支持流式聊天完成生成。要使用它,只需传递stream: true
到engine.chat.completions.create
调用即可。
const messages = [
{ role: "system", content: "You are a helpful AI assistant." },
{ role: "user", content: "Hello!" },
]
// Chunks is an AsyncGenerator object
const chunks = await engine.chat.completions.create({
messages,
temperature: 1,
stream: true, // <-- Enable streaming
stream_options: { include_usage: true },
});
let reply = "";
for await (const chunk of chunks) {
reply += chunk.choices[0]?.delta.content || "";
console.log(reply);
if (chunk.usage) {
console.log(chunk.usage); // only last chunk has usage
}
}
const fullReply = await engine.getMessage();
console.log(fullReply);
您可以将繁重的计算放入工作脚本中以优化应用程序性能。为此,您需要:
- 在工作线程中创建一个处理程序,在处理请求时与前端进行通信。
- 在主应用程序中创建一个工作引擎,该引擎在幕后将消息发送到工作线程中的处理程序。
有关不同类型 Worker 的详细实现,请查看以下部分。
WebLLM 附带了对 WebWorker 的 API 支持,因此您可以将生成过程挂钩到单独的工作线程中,这样工作线程中的计算就不会破坏 UI。
我们在工作线程中创建一个处理程序,在处理请求时与前端进行通信。
// worker.ts
import { WebWorkerMLCEngineHandler } from "@mlc-ai/web-llm";
// A handler that resides in the worker thread
const handler = new WebWorkerMLCEngineHandler();
self.onmessage = (msg: MessageEvent) => {
handler.onmessage(msg);
};
在主逻辑中,我们创建一个WebWorkerMLCEngine
实现相同的MLCEngineInterface
.其余逻辑保持不变。
// main.ts
import { CreateWebWorkerMLCEngine } from "@mlc-ai/web-llm";
async function main() {
// Use a WebWorkerMLCEngine instead of MLCEngine here
const engine = await CreateWebWorkerMLCEngine(
new Worker(
new URL("./worker.ts", import.meta.url),
{
type: "module",
}
),
selectedModel,
{ initProgressCallback }, // engineConfig
);
// everything else remains the same
}
WebLLM 附带对 ServiceWorker 的 API 支持,因此您可以将生成过程挂接到 Service Worker 中,以避免在每次页面访问时重新加载模型,并优化应用程序的离线体验。
(请注意,Service Worker 的生命周期由浏览器管理,可以随时终止,而无需通知 Web 应用程序。ServiceWorkerMLCEngine
将尝试通过定期发送心跳事件来保持 Service Worker 线程处于活动状态,但您的应用程序还应包括适当的错误处理。检查keepAliveMs
并missedHeatbeat
了解ServiceWorkerMLCEngine
更多详情。)
我们在工作线程中创建一个处理程序,在处理请求时与前端进行通信。
// sw.ts
import { ServiceWorkerMLCEngineHandler } from "@mlc-ai/web-llm";
let handler: ServiceWorkerMLCEngineHandler;
self.addEventListener("activate", function (event) {
handler = new ServiceWorkerMLCEngineHandler();
console.log("Service Worker is ready");
});
然后在主逻辑中,我们注册 Service Worker 并使用函数创建引擎 CreateServiceWorkerMLCEngine
。其余逻辑保持不变。
// main.ts
import { MLCEngineInterface, CreateServiceWorkerMLCEngine } from "@mlc-ai/web-llm";
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register(
new URL("sw.ts", import.meta.url), // worker script
{ type: "module" },
);
}
const engine: MLCEngineInterface =
await CreateServiceWorkerMLCEngine(
selectedModel,
{ initProgressCallback }, // engineConfig
);
您可以在example/service-worker中找到有关如何在服务工作线程中运行 WebLLM 的完整示例。
您还可以在example/chrome-extension和Examples/chrome-extension-webgpu-service-worker中找到使用 WebLLM 构建 Chrome 扩展程序的示例。后一种利用服务工作者,因此扩展在后台持久存在。
WebLLM 的设计与OpenAI API完全兼容。因此,除了构建一个简单的聊天机器人外,您还可以使用 WebLLM 获得以下功能:
- Streaming:以 AsyncGenerator 的形式实时返回输出块
- json-mode:有效确保输出为 JSON 格式,请参阅OpenAI 参考了解更多信息。
- 种子繁殖:使用播种来确保田地的可重复输出
seed
。 - 函数调用(WIP):使用字段
tools
和进行函数调用tool_choice
(初步支持);或不带tools
or的手动函数调用tool_choice
(保持最大的灵活性)。
WebLLM 作为MLC LLM的配套项目,支持 MLC 格式的自定义模型。它重用模型工件并构建 MLC LLM 流程。要通过 WebLLM 编译和使用您自己的模型,请查看 MLC LLM 文档, 了解如何编译新模型权重和库并将其部署到 WebLLM。
在这里,我们回顾一下高层的想法。 WebLLM 包中有两个元素可实现新模型和权重变体。
model
:包含模型工件的 URL,例如权重和元数据。model_lib
:Web 程序集库(即 wasm 文件)的 URL,其中包含加速模型计算的可执行文件。
两者均可在 WebLLM 中自定义。
import { CreateMLCEngine } from "@mlc-ai/web-llm";
async main() {
const appConfig = {
"model_list": [
{
"model": "/url/to/my/llama",
"model_id": "MyLlama-3b-v1-q4f32_0",
"model_lib": "/url/to/myllama3b.wasm",
}
],
};
// override default
const chatOpts = {
"repetition_penalty": 1.01
};
// load a prebuilt model
// with a chat option override and app config
// under the hood, it will load the model from myLlamaUrl
// and cache it in the browser cache
// The chat will also load the model library from "/url/to/myllama3b.wasm",
// assuming that it is compatible to the model in myLlamaUrl.
const engine = await CreateMLCEngine(
"MyLlama-3b-v1-q4f32_0",
{ appConfig }, // engineConfig
chatOpts,
);
}
在许多情况下,我们只想提供模型权重变体,但不一定是新模型(例如NeuralHermes-Mistral
可以重用Mistral
的模型库)。有关不同模型变体如何共享模型库的示例,请参阅webllm.prebuiltAppConfig
。
注意:除非您想修改 WebLLM 包,否则您不需要从源代码构建。要使用 npm,只需按照入门或任何示例进行操作即可。
要从源代码构建,只需运行:
npm install
npm run build
然后,要测试示例中代码更改的效果,请在 内部examples/get-started/package.json
从 更改"@mlc-ai/web-llm": "^0.2.73"
为"@mlc-ai/web-llm": ../..
。
然后运行:
cd examples/get-started
npm install
npm start
请注意,有时您需要在file:../..
和之间切换../..
以触发 npm 来识别新更改。在最坏的情况下,你可以运行:
cd examples/get-started
rm -rf node_modules dist package-lock.json .parcel-cache
npm install
npm start
WebLLM的运行时很大程度上取决于TVMjs:https://github.com/apache/tvm/tree/main/web
虽然它也可以作为 npm 包提供:https://www.npmjs.com/package/@mlc-ai/web-runtime,但如果需要,您可以按照以下步骤从源代码构建它。
-
安装emscripten。它是一个基于 LLVM 的编译器,可将 C/C++ 源代码编译为 WebAssembly。
- 按照安装说明安装最新的 emsdk。
- 源由,以便
emsdk_env.sh
可以从 PATH 访问并且该命令有效。source path/to/emsdk_env.sh
emcc
emcc
我们可以通过终端测试来验证安装是否成功
emcc
。注意:我们最近发现使用最新
emcc
版本可能会在运行时遇到问题。现在使用./emsdk install 3.1.56
而不是作为解决方法。./emsdk install latest
错误可能看起来像Init error, LinkError: WebAssembly.instantiate(): Import #6 module="wasi_snapshot_preview1" function="proc_exit": function import requires a callable
-
在 中
./package.json
,从 更改"@mlc-ai/web-runtime": "0.18.0-dev2",
为"@mlc-ai/web-runtime": "file:./tvm_home/web",
。 -
设置必要的环境
准备 Web 构建所需的所有依赖项:
./scripts/prep_deps.sh
在这一步中,如果
$TVM_SOURCE_DIR
环境中没有定义,我们将执行以下行来构建tvmjs
依赖关系:git clone https://github.com/mlc-ai/relax 3rdparty/tvm-unity --recursive
这会克隆 的当前 HEAD
mlc-ai/relax
。但是,它可能并不总是正确的分支或提交克隆。要从源代码构建特定的 npm 版本,请参阅版本升级 PR,其中说明当前 WebLLM 版本依赖于哪个分支(即mlc-ai/relax
或)以及哪个提交。apache/tvm
例如,版本 0.2.52,根据其版本凹凸 PR #521,是通过检查 中的以下提交https://github.com/apache/tvm/commit/e6476847753c80e054719ac47bc2091c888418b6而构建的apache/tvm
,而不是mlc-ai/relax
.除此之外,
--recursive
是必要且重要的。否则,您可能会遇到类似的错误fatal error: 'dlpack/dlpack.h' file not found
。 -
构建WebLLM包
npm run build
-
验证一些子包
然后,您可以转到示例中的子文件夹来验证某些子包。我们使用 Parcelv2 进行捆绑。尽管 Parcel 有时不太擅长跟踪父目录的更改。当您在 WebLLM 包中进行更改时,尝试编辑
package.json
子文件夹并保存它,这将触发 Parcel 重建。