Fecha de publicación: 13 de enero de 2024
Esta es la segunda de una serie de tres partes sobre los LLM y los chatbots. En el artículo anterior, se analizaron los beneficios y las desventajas de los LLM en el dispositivo y en el navegador.
Ahora que comprendes mejor la IA del cliente, puedes agregar WebLLM a una
aplicación web de listas de tareas pendientes. Puedes encontrar el código en la rama web-llm
del repositorio de GitHub.
WebLLM es un entorno de ejecución basado en la Web para LLMs que proporciona la compilación de aprendizaje automático. Puedes probar WebLLM como una aplicación independiente. La aplicación se inspira en aplicaciones de chat respaldadas por la nube, como Gemini, pero la inferencia de LLM se ejecuta en tu dispositivo en lugar de la nube. Tus instrucciones y datos nunca salen de tu dispositivo, y puedes estar seguro de que no se usan para entrenar modelos.
Para realizar la inferencia de modelos en el dispositivo, WebLLM combina WebAssembly y WebGPU. Si bien WebAssembly permite cálculos eficientes en la unidad central de procesamiento (CPU), WebGPU les brinda a los desarrolladores acceso de bajo nivel a la unidad de procesamiento gráfico (GPU) del dispositivo.
Instala WebLLM
WebLLM está disponible como un paquete npm.
Para agregar este paquete a tu aplicación de listas de tareas pendientes, ejecuta npm install @mlc-ai/web-llm
.
Seleccionar un modelo
A continuación, debes decidir qué LLM ejecutarás de forma local. Hay varios modelos disponibles.
Para tomar una decisión, debes conocer los siguientes términos y cifras clave:
- Token: Es la unidad de texto más pequeña que puede procesar un LLM.
- Ventana de contexto: Es la cantidad máxima de tokens que puede procesar el modelo.
- Parámetros o pesos: Son las variables internas que se aprenden durante el entrenamiento y se cuentan en miles de millones.
- Cuantización: Es la cantidad de bits que representan los pesos. Más bits significan una mayor precisión, pero también un mayor uso de memoria.
- Formatos de números de punto flotante: Los números de punto flotante de 32 bits (precisión completa, F32) ofrecen una mejor precisión, mientras que los números de punto flotante de 16 bits (precisión media, F16) tienen velocidades más altas y menos uso de memoria, pero requieren hardware compatible.
Estos términos clave suelen ser parte del nombre del modelo. Por ejemplo, Llama-3.2-3B-Instruct-q4f32_1-MLC
contiene la siguiente información:
- El modelo es LLaMa 3.2.
- El modelo tiene 3,000 millones de parámetros.
- Está optimizado para instrucciones y asistentes de estilo de instrucciones (Instruct).
- Usa cuantización uniforme (_1) de 4 bits (q4).
- Tiene números de punto flotante de 32 bits con precisión completa.
- Es una versión especial creada por la compilación de aprendizaje automático.
Es posible que debas probar diferentes modelos para determinar cuál se adapta a tu caso de uso.
Un modelo con 3,000 millones de parámetros y 4 bits por parámetro ya podría tener un tamaño de archivo de hasta 1.4 GB en el momento de escribir este artículo, que la aplicación debe descargar en el dispositivo del usuario antes del primer uso. Es posible trabajar con modelos de 3B, pero cuando se trata de capacidades de traducción o conocimiento de trivia, los modelos de 7B ofrecen mejores resultados. Sin embargo, con 3.3 GB o más, son mucho más grandes.
Para crear el motor WebLLM y comenzar la descarga del modelo de tu chatbot de lista de tareas pendientes, agrega el siguiente código a tu aplicación:
import {CreateMLCEngine} from '@mlc-ai/web-llm';
const engine = await CreateMLCEngine('Llama-3.2-3B-Instruct-q4f32_1-MLC', {
initProgressCallback: ({progress}) => console.log(progress);
});
El método CreateMLCEngine
toma la cadena de modelo y un objeto de configuración opcional. Con el método initProgressCallback
, puedes consultar el progreso de la descarga del modelo para presentarlo a los usuarios mientras esperan.
API de Cache: Haz que tu LLM se ejecute sin conexión
El modelo se descarga en el almacenamiento en caché de tu sitio web. La API de Cache se introdujo junto con los trabajadores de servicio para que tu sitio web o aplicación web se ejecute sin conexión. Es el mejor mecanismo de almacenamiento para almacenar en caché modelos de IA. A diferencia de la caché HTTP, la API de Cache es una caché programable que está completamente bajo el control del desarrollador.
Una vez descargado, WebLLM lee los archivos de modelo de la API de Cache en lugar de solicitarlos a través de la red, lo que hace que WebLLM sea totalmente compatible con la conexión sin conexión.
Al igual que con todo el almacenamiento de sitios web, la caché se aísla por origen. Esto significa que dos orígenes, example.com y example.net, no pueden compartir el mismo almacenamiento. Si esos dos sitios web quisieran usar el mismo modelo, tendrían que descargarlo por separado.
Para inspeccionar la caché con DevTools, ve a Application > Storage y abre el almacenamiento en caché.
Cómo configurar la conversación
El modelo se puede inicializar con un conjunto de instrucciones iniciales. Por lo general, hay tres roles de mensaje:
- Consigna del sistema: Esta consigna define el comportamiento, el rol y el carácter del modelo. También se puede usar para la puesta a tierra, es decir, para ingresar datos personalizados al modelo que no forman parte de su conjunto de entrenamiento (como tus datos específicos del dominio). Solo puedes especificar un mensaje del sistema.
- Mensaje del usuario: Son los mensajes que ingresa el usuario.
- Consigna de Asistente: Respuestas del asistente, opcionales.
Las instrucciones del usuario y del asistente se pueden usar para las instrucciones de N instancias, ya que proporcionan ejemplos de lenguaje natural al LLM sobre cómo debe comportarse o responder.
Este es un ejemplo mínimo para configurar la conversación de la app de listas de tareas pendientes:
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?"}
];
Responde tu primera pregunta
La función de finalización de chat se expone como una propiedad en el motor de WebLLM que se creó antes (engine.chat.completions
). Después de que se descargue el modelo, puedes ejecutar la inferencia del modelo llamando al método create()
en esta propiedad. Para tu caso de uso, quieres transmitir respuestas para que el usuario pueda comenzar a leerlas mientras se generan, lo que reduce el tiempo de espera percibido:
const chunks = await engine.chat.completions.create({ messages, stream: true, });
Este método muestra una AsyncGenerator
, una subclase de la clase AsyncIterator
oculta. Usa un bucle for await...of
para esperar a los fragmentos a medida que llegan. Sin embargo, la respuesta solo contiene los tokens nuevos (delta
), por lo que debes armar la respuesta completa por tu cuenta.
let reply = '';
for await (const chunk of chunks) {
reply += chunk.choices[0]?.delta.content ?? '';
console.log(reply);
}
Resulta que la Web siempre tuvo que lidiar con respuestas de transmisión continua. Puedes usar APIs como DOMImplementation para trabajar con estas respuestas de transmisión y actualizar tu HTML de manera eficiente.
Los resultados se basan únicamente en cadenas. Primero, debes analizarlos si quieres interpretarlos como JSON o como otros formatos de archivo.
Sin embargo, WebLLM tiene algunas restricciones: la aplicación debe descargar un modelo enorme antes del primer uso, que no se puede compartir entre orígenes, por lo que es posible que otra app web deba volver a descargar el mismo modelo. Si bien WebGPU logra un rendimiento de inferencia casi nativo, no alcanza la velocidad nativa completa.
Demostración
La API de Prompt, una API exploratoria que propuso Google y que también se ejecuta del cliente, pero usa un modelo central descargado en Chrome, aborda estas desventajas. Esto significa que varias aplicaciones pueden usar el mismo modelo a la velocidad de ejecución completa.
Obtén más información para agregar capacidades de chatbot con la API de Prompt en el siguiente artículo.