Motor de inferência no navegador de alto desempenho.
Documentação | BlogPost | Papel | Exemplos
O WebLLM é um mecanismo de inferência no navegador LLM de alto desempenho que traz a inferência do modelo de idioma diretamente nos navegadores da Web com aceleração de hardware. Tudo corre dentro do navegador sem suporte ao servidor e é acelerado com o WebGPU.
O Webllm é totalmente compatível com a API OpenAI. Ou seja, você pode usar a mesma API OpenAI em qualquer modelos de código aberto localmente, com funcionalidades, incluindo streaming, JSOD-Mode, Função de Função (WIP), etc.
Podemos trazer muitas oportunidades divertidas para construir assistentes de IA para todos e permitir a privacidade enquanto desfrutamos de aceleração da GPU.
Você pode usar o WebLLM como um pacote NPM básico e criar seu próprio aplicativo da web, seguindo os exemplos abaixo. Este projeto é um projeto complementar da MLC LLM, que permite a implantação universal do LLM em ambientes de hardware.
Confira o chat webllm para experimentar!
Inferência no navegador : o Webllm é um mecanismo de inferência de modelo de linguagem no navegador de alto desempenho que aproveita a aceleração do WebGPU para aceleração de hardware, permitindo operações poderosas de LLM diretamente nos navegadores da Web sem processamento do lado do servidor.
Compatibilidade completa da API do OpenAI : integre perfeitamente seu aplicativo com o WebLLM usando a API OpenAI com funcionalidades como streaming, modo JSON, controle de nível logit, semeadura e muito mais.
Geração JSON estruturada : Webllm suporta geração estruturada de modo JSON de ponta, implementada na parte WebAssembly da biblioteca de modelos para obter o melhor desempenho. Verifique o Webllm JSON Playground no Huggingface para tentar gerar saída JSON com esquema JSON personalizado.
Suporte de modelo extenso : WebllM suporta de maneira nativamente uma variedade de modelos, incluindo LLAMA 3, PHI 3, GEMMA, MISTRAL, QWEN (通义千问 通义千问) e muitos outros, tornando -o versátil para várias tarefas de IA. Para a lista de modelos suportados completos, verifique os modelos MLC.
Integração de modelos personalizados : integrar e implantar facilmente modelos personalizados no formato MLC, permitindo que você adapte as necessidades e cenários específicos, aumentando a flexibilidade na implantação do modelo.
Integração plug-and-play : integrar facilmente o Webllm em seus projetos usando gerentes de pacotes como NPM e YARN, ou diretamente via CDN, completos com exemplos abrangentes e um design modular para se conectar com componentes da interface do usuário.
Streaming e interações em tempo real : suporta o streaming de conclusões de bate-papo, permitindo a geração de saída em tempo real, o que aprimora aplicativos interativos, como chatbots e assistentes virtuais.
Support Work Worker & Service Worker : Otimize o desempenho da interface do usuário e gerencie o ciclo de vida de modelos com eficiência, descarregando cálculos para separar tópicos dos trabalhadores ou trabalhadores de serviço.
Suporte de extensão do Chrome : estenda a funcionalidade dos navegadores da Web através de extensões de Chrome personalizadas usando Webllm, com exemplos disponíveis para a criação de extensões básicas e avançadas.
Verifique a lista completa dos modelos disponíveis nos modelos MLC. O WebLLM suporta um subconjunto desses modelos disponíveis e a lista pode ser acessada em prebuiltAppConfig.model_list .
Aqui estão as principais famílias de modelos atualmente suportados:
Se você precisar de mais modelos, solicite um novo modelo abrindo um problema ou verifique os modelos personalizados como compilar e use seus próprios modelos com o Webllm.
Aprenda a usar o Webllm para integrar grandes modelos de linguagem em seu aplicativo e gerar conclusões de bate -papo através deste exemplo simples de chatbot:
Para um exemplo avançado de um projeto maior e mais complicado, verifique o Webllm Chat.
Mais exemplos para diferentes casos de uso estão disponíveis na pasta Exemplos.
O WebLLM oferece uma interface minimalista e modular para acessar o chatbot no navegador. O pacote foi projetado de maneira modular de conectar a qualquer um dos componentes da interface do usuário.
# npm
npm install @mlc-ai/web-llm
# yarn
yarn add @mlc-ai/web-llm
# or pnpm
pnpm install @mlc-ai/web-llmEm seguida, importe o módulo em seu código.
// Import everything
import * as webllm from "@mlc-ai/web-llm" ;
// Or only import what you need
import { CreateMLCEngine } from "@mlc-ai/web-llm" ; Graças ao jsdelivr.com, o webllm pode ser importado diretamente através do URL e trabalhar fora da caixa em plataformas de desenvolvimento em nuvem como jsfiddle.net, codepen.io e scribbler:
import * as webllm from "https://esm.run/@mlc-ai/web-llm" ;Também pode ser importado dinamicamente como:
const webllm = await import ( "https://esm.run/@mlc-ai/web-llm" ) ; A maioria das operações no WebLLM é invocada através da interface MLCEngine . Você pode criar uma instância MLCEngine e carregar o modelo chamando a função CreateMLCEngine() Factory.
(Observe que o carregamento dos modelos requer download e pode levar uma quantidade significativa de tempo para a primeira execução sem o cache anteriormente. Você deve lidar adequadamente com essa chamada assíncrona.)
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
) ;Sob o capô, essa função de fábrica faz as seguintes etapas para primeiro criar uma instância do motor (síncrona) e depois carregar o modelo (assíncrono). Você também pode fazê -los separadamente em seu aplicativo.
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 ) ; Depois de inicializar com êxito o mecanismo, agora você pode invocar as conclusões do bate -papo usando as APIs de bate -papo no estilo OpenAI através da interface engine.chat.completions . Para obter a lista completa de parâmetros e suas descrições, verifique a seção abaixo e a referência da API do OpenAI.
(Nota: o parâmetro model não é suportado e será ignorado aqui. Em vez disso, ligue para CreateMLCEngine(model) ou engine.reload(model) como mostrado no MLCEngine Criar acima.)
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 ) ; O WebLLM também suporta a geração de conclusão de bate -papo por streaming. Para usá -lo, basta passar stream: true para o engine.chat.completions.create CALL.
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 ) ; Você pode colocar o cálculo pesado em um script de trabalhador para otimizar o desempenho do seu aplicativo. Para fazer isso, você precisa:
Para implementações detalhadas de diferentes tipos de trabalhadores, consulte as seções a seguir.
O WebLLM vem com suporte da API para o WebWorker para que você possa conectar o processo de geração em um thread de trabalhador separado, para que a computação no thread do trabalhador não interrompa a interface do usuário.
Criamos um manipulador no tópico do trabalhador que se comunica com o front -end enquanto lida com os pedidos.
// 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 ) ;
} ; Na lógica principal, criamos um WebWorkerMLCEngine que implementa o mesmo MLCEngineInterface . O restante da lógica permanece o mesmo.
// 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
}O WebLLM vem com o suporte da API para o ServiceWorker para que você possa conectar o processo de geração em um trabalhador de serviço para evitar recarregar o modelo em todas as páginas, visitar e otimizar a experiência offline do seu aplicativo.
(Observe que o ciclo de vida do trabalhador do serviço é gerenciado pelo navegador e pode ser morto a qualquer momento sem missedHeatbeat o WebApp. ServiceWorkerMLCEngine tentará manter o tópico do trabalhador do serviço vivo periodicamente enviando eventos de batimentos keepAliveMs , mas seu ServiceWorkerMLCEngine também deve incluir mais detalhes.
Criamos um manipulador no tópico do trabalhador que se comunica com o front -end enquanto lida com os pedidos.
// 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" ) ;
} ) ; Então, na lógica principal, registramos o funcionário do serviço e criamos o mecanismo usando a função CreateServiceWorkerMLCEngine . O restante da lógica permanece o mesmo.
// 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
) ;Você pode encontrar um exemplo completo sobre como executar o Webllm no Serviço Trabalhador em Exemplos/Serviços de Trabalho.
Você também pode encontrar exemplos de construção de extensão cromo com WebLLM em exemplos/Extensão Chrome e Exemplos/Chrome-Extensão-WebGPU-Serviço-Worker. O último alavanca o trabalhador do serviço, portanto a extensão é persistente em segundo plano. Além disso, você pode explorar outro projeto completo de uma extensão do Chrome, o WebllM Assistant, que aproveita o WebLlm aqui.
O WebLLM foi projetado para ser totalmente compatível com a API OpenAI. Assim, além de construir um chatbot simples, você também pode ter as seguintes funcionalidades com Webllm:
seed dos campos.tools Fields e tool_choice (com suporte preliminar); ou chamada de função manual sem tools ou tool_choice (mantém a maior flexibilidade). O Webllm funciona como um projeto complementar da MLC LLM e suporta modelos personalizados no formato MLC. Ele reutiliza o artefato do modelo e constrói o fluxo do MLC LLM. Para compilar e usar seus próprios modelos com o WebLLM, consulte o documento MLC LLM sobre como compilar e implantar novos pesos e bibliotecas de modelos no Webllm.
Aqui, analisamos a ideia de alto nível. Existem dois elementos do pacote webllm que permitem novos modelos e variantes de peso.
model : contém um URL para modelar artefatos, como pesos e metadados.model_lib : um URL para a biblioteca da Web Assembly (arquivo WASM) que contém os executáveis para acelerar os cálculos do modelo.Ambos são personalizáveis no 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 ,
) ;
} Em muitos casos, queremos fornecer apenas a variante de peso do modelo, mas não necessariamente um novo modelo (por exemplo NeuralHermes-Mistral pode reutilizar a biblioteca de modelos de Mistral ). Para exemplos de como uma biblioteca de modelos pode ser compartilhada por diferentes variantes de modelo, consulte webllm.prebuiltAppConfig .
Nota: Você não precisa construir a partir da fonte, a menos que deseje modificar o pacote Webllm. Para usar o NPM, basta seguir em frente ou qualquer um dos exemplos.
Para construir a partir da fonte, basta executar:
npm install
npm run build Em seguida, para testar os efeitos da alteração do seu código em um exemplo, examples/get-started/package.json , altere de "@mlc-ai/web-llm": "^0.2.77" para "@mlc-ai/web-llm": ../..
Em seguida, corra:
cd examples/get-started
npm install
npm start Observe que às vezes você precisaria alternar entre file:../.. e ../.. para acionar o NPM para reconhecer novas alterações. Na pior das hipóteses, você pode executar:
cd examples/get-started
rm -rf node_modules dist package-lock.json .parcel-cache
npm install
npm startO tempo de execução do Webllm depende em grande parte do TVMJS: https://github.com/apache/tvm/tree/main/web
Embora também esteja disponível como um pacote npm: https://www.npmjs.com/package/@mlc-ai/web-runtime, você pode construí-lo a partir da fonte, se necessário, seguindo as etapas abaixo.
Instale o emscripten. É um compilador baseado em LLVM que compila código-fonte C/C ++ com a WebAssembly.
emsdk_env.sh pelo source path/to/emsdk_env.sh , para que emcc seja acessível a partir do caminho e o comando emcc funciona. Podemos verificar a instalação bem -sucedida experimentando o terminal emcc .
Nota: descobrimos recentemente que o uso da versão mais recente emcc pode ter problemas durante o tempo de execução. Use ./emsdk install 3.1.56 em vez de ./emsdk install latest por enquanto como uma solução alternativa. O erro pode parecer
Init error, LinkError: WebAssembly.instantiate(): Import #6 module="wasi_snapshot_preview1"
function="proc_exit": function import requires a callable
Em ./package.json , altere de "@mlc-ai/web-runtime": "0.18.0-dev2", para "@mlc-ai/web-runtime": "file:./tvm_home/web", .
Configurar o ambiente necessário
Prepare todas as dependências necessárias para a construção da web:
./scripts/prep_deps.sh Nesta etapa, se $TVM_SOURCE_DIR não for definido no ambiente, executaremos a seguinte linha para criar a dependência tvmjs :
git clone https://github.com/mlc-ai/relax 3rdparty/tvm-unity --recursive Isso clones o atual chefe do mlc-ai/relax . No entanto, nem sempre pode ser o ramo correto ou se comprometer a clonar. Para criar uma versão NPM específica a partir da fonte, consulte a versão Bump PR, que afirma qual ramificação (ou seja, mlc-ai/relax ou apache/tvm ) e qual comprometeu a versão WebLLM atual depende. Por exemplo, a versão 0.2.52, de acordo com sua versão Bump PR #521, foi construída verificando o seguinte commit https://github.com/apache/tvm/commit/e6476847753c80e054719ac4bc2091c888418b6bache054719ac41091c818888418b80e054719Ac41091C88888418B6 In mlc-ai/relax apache/tvm .
Além disso, --recursive é necessário e importante. Caso contrário, você pode encontrar erros como fatal error: 'dlpack/dlpack.h' file not found .
Construa o pacote webllm
npm run buildValidar alguns dos sub-pacotes
Você pode ir para as subpastas em exemplos para validar alguns dos sub-pacotes. Usamos o Parcelv2 para agrupamento. Embora o Parcel não seja muito bom em rastrear as mudanças do diretório pai às vezes. Quando você faz uma alteração no pacote Webllm, tente editar o package.json da subpasta e salvá -lo, que acionará a parcela para reconstruir.
Este projeto é iniciado por membros da CMU Catalyst, UW Sampl, SJTU, OCTOML e MLC Community. Gostaríamos muito de continuar desenvolvendo e apoiando a comunidade de ML de código aberto.
Este projeto só é possível graças aos ombros ecossistemas de código aberto em que estamos. Queremos agradecer à comunidade Apache TVM e aos desenvolvedores do esforço da TVM Unity. Os membros da comunidade ML de código aberto disponibilizaram esses modelos publicamente. As comunidades de pytorch e abraços de rosto tornam esses modelos acessíveis. Gostaríamos de agradecer às equipes por trás de Vicuna, Sinencepiece, Llama e Alpaca. Também gostaríamos de agradecer às comunidades WebAssembly, EMScriptten e WebGPU. Finalmente, graças aos desenvolvedores de Dawn e WebGPU.
Se você acha que este projeto é útil, cite:
@misc{ruan2024webllmhighperformanceinbrowserllm,
title={WebLLM: A High-Performance In-Browser LLM Inference Engine},
author={Charlie F. Ruan and Yucheng Qin and Xun Zhou and Ruihang Lai and Hongyi Jin and Yixin Dong and Bohan Hou and Meng-Shiun Yu and Yiyan Zhai and Sudeep Agarwal and Hangrui Cao and Siyuan Feng and Tianqi Chen},
year={2024},
eprint={2412.15803},
archivePrefix={arXiv},
primaryClass={cs.LG},
url={https://arxiv.org/abs/2412.15803},
}
⬆ Voltar ao topo ⬆