发布时间:2024 年 1 月 13 日
本文是有关 LLM 和聊天机器人的三篇系列文章中的第二篇。上一篇文章讨论了设备端和浏览器端 LLM 的优缺点。
现在,您已经更好地了解了客户端 AI,接下来可以将 WebLLM 添加到待办事项 Web 应用了。您可以在 GitHub 代码库的 web-llm
分支中找到该代码。
WebLLM 是机器学习编译提供的面向 LLM 的基于 Web 的运行时。您可以试用将 WebLLM 作为一款独立应用。该应用的灵感来自于云端支持的聊天应用(例如 Gemini),但 LLM 推理是在设备上运行的,而不是在云端运行。您的提示和数据绝不会离开您的设备,您可以放心,它们不会用于训练模型。
为了在设备上执行模型推理,WebLLM 结合使用了 WebAssembly 和 WebGPU。虽然 WebAssembly 支持在中央处理器 (CPU) 上高效计算,但 WebGPU 可让开发者对设备的图形处理单元 (GPU) 进行低级访问。
安装 WebLLM
WebLLM 可作为 npm 软件包提供。您可以通过运行 npm install @mlc-ai/web-llm
将此软件包添加到您的待办事项应用。
选择模型
接下来,您需要确定要在本地执行的 LLM。有多种型号可供选择。
为此,您应了解以下关键术语和数据:
- 令牌:LLM 可处理的最小文本单元。
- 上下文窗口:模型可以处理的词元数量上限。
- 参数或权重:在训练期间学习到的内部变量,数量以十亿计。
- 量化:表示权重的位数。位数越多,精度越高,但内存用量也越高。
- 浮点数格式:32 位浮点数(全精度,F32)提供更高的精确度,而 16 位浮点数(半精度,F16)速度更快且内存用量更低,但需要兼容的硬件。
这些关键字通常是模型名称的一部分。例如,Llama-3.2-3B-Instruct-q4f32_1-MLC
包含以下信息:
- 模型是 LLaMa 3.2。
- 该模型有 30 亿个参数。
- 它经过了精细调整,适用于指令和提示式助理(Instruct)。
- 它使用 4 位 (q4)均匀 (_1) 量化。
- 它使用全精度 32 位浮点数。
- 这是机器学习编译创建的特殊版本。
您可能需要测试不同的模型,以确定哪种模型适合您的用例。
在撰写本文时,一个包含 30 亿个参数且每个参数为 4 位的模型的文件大小已经达到 1.4 GB,应用需要在首次使用前将其下载到用户设备上。您可以使用 3B 模型,但在翻译功能或琐事知识方面,7B 模型可以提供更好的结果。不过,如果超过 3.3 GB,则会大得多。
如需创建 WebLLM 引擎并为待办事项聊天机器人启动模型下载,请将以下代码添加到您的应用:
import {CreateMLCEngine} from '@mlc-ai/web-llm';
const engine = await CreateMLCEngine('Llama-3.2-3B-Instruct-q4f32_1-MLC', {
initProgressCallback: ({progress}) => console.log(progress);
});
CreateMLCEngine
方法采用模型字符串和可选的配置对象。您可以使用 initProgressCallback
方法查询模型的下载进度,以便在用户等待时向他们显示进度。
Cache API:让 LLM 离线运行
该模型会下载到您网站的缓存存储空间中。 Cache API 与 Service Worker 一起推出,旨在让您的网站或 Web 应用能够离线运行。它是缓存 AI 模型的最佳存储机制。与 HTTP 缓存不同,Cache API 是一种可编程缓存,完全由开发者控制。
下载后,WebLLM 会从 Cache API 读取模型文件,而不是通过网络请求这些文件,从而使 WebLLM 完全脱离线。
与所有网站存储空间一样,缓存是按源站隔离的。这意味着,两个源(example.com 和 example.net)不能共享同一存储空间。如果这两个网站想要使用相同的模型,则必须单独下载该模型。
您可以使用开发者工具检查缓存,方法是前往应用 > 存储,然后打开“缓存”存储空间。
设置对话
模型可以使用一组初始提示进行初始化。通常,消息有三种角色:
- 系统提示:此提示定义了模型的行为、角色和性格。它还可用于对齐,即将不属于其训练集的自定义数据(例如特定于领域的数据)馈送到模型。您只能指定一个系统提示。
- 用户提示:用户输入的提示。
- Google 助理提示:Google 助理的回答,可选。
用户和助理提示可用于 N 次提示,方法是向 LLM 提供有关其应如何行为或响应的自然语言示例。
以下是为待办事项应用设置对话的最小示例:
const messages = [
{ role: "system",
content: `You are a helpful assistant. You will answer questions related to
the user's to-do list. Decline all other requests not related to the user's
todos. This is the to-do list in JSON: ${JSON.stringify(todos)}`
},
{role: "user", content: "How many open todos do I have?"}
];
回答第一个问题
聊天内容补全功能会作为之前创建的 WebLLM 引擎 (engine.chat.completions
) 上的属性公开。下载模型后,您可以通过对此属性调用 create()
方法来运行模型推理。对于您的用例,您希望流式传输回答,以便用户在回答生成时开始阅读,从而缩短感知等待时间:
const chunks = await engine.chat.completions.create({ messages, stream: true, });
此方法会返回 AsyncGenerator
,它是隐藏的 AsyncIterator
类的子类。使用 for await...of
循环等待数据块的传入。不过,响应中仅包含新令牌 (delta
),因此您必须自行组合完整的回复。
let reply = '';
for await (const chunk of chunks) {
reply += chunk.choices[0]?.delta.content ?? '';
console.log(reply);
}
事实证明,网络始终必须处理流式响应。您可以使用 DOMImplementation 等 API 处理这些流式响应并高效更新 HTML。
结果完全基于字符串。如果您想将其解读为 JSON 或其他文件格式,则必须先对其进行解析。
不过,WebLLM 有一些限制:应用需要在首次使用前下载一个巨大的模型,该模型无法跨源共享,因此其他 Web 应用可能必须重新下载相同的模型。虽然 WebGPU 可实现接近原生推理性能,但未达到完全原生速度。
演示
Prompt API 解决了这些缺点。Prompt API 是由 Google 提出的一种探索性 API,它也运行在客户端,但使用下载到 Chrome 中的中央模型。这意味着,多个应用可以以全速执行速度使用相同的模型。
请参阅下一部分,详细了解如何使用 Prompt API 添加聊天机器人功能。