Опубликовано: 13 января 2024 г.
Это вторая серия из трех частей, посвященная LLM и чат-ботам. В предыдущей статье обсуждались преимущества и недостатки LLM на устройстве и в браузере .
Теперь, когда вы лучше понимаете ИИ на стороне клиента, вы готовы добавить WebLLM в веб-приложение списка дел. Код вы можете найти в ветке web-llm
репозитория GitHub .
WebLLM — это веб-среда выполнения для LLM, предоставляемая компиляцией машинного обучения. Вы можете опробовать WebLLM как отдельное приложение . Приложение создано на основе облачных чат-приложений, таких как Gemini , но вывод LLM выполняется на вашем устройстве, а не в облаке. Ваши подсказки и данные никогда не покидают ваше устройство, и вы можете быть уверены, что они не будут использованы для обучения моделей.
Чтобы выполнить вывод модели на устройстве, WebLLM объединяет WebAssembly и WebGPU . В то время как WebAssembly позволяет эффективно выполнять вычисления на центральном процессоре (ЦП), WebGPU предоставляет разработчикам низкоуровневый доступ к графическому процессору (GPU) устройства.
Установить ВебЛЛМ
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.
- Модель имеет 3 миллиарда параметров.
- Он идеально настроен для инструкций и быстрых помощников (Instruct).
- Он использует 4-битное (q4) равномерное (_1) квантование .
- Он имеет 32-битные числа с плавающей запятой полной точности.
- Это специальная версия, созданная Machine Learning Compilation.
Возможно, вам придется протестировать разные модели, чтобы определить, какая из них подходит вашему варианту использования.
Модель с 3 миллиардами параметров и 4 битами на параметр уже на момент написания этой статьи могла иметь размер файла до 1,4 ГБ, который приложению необходимо загрузить на устройство пользователя перед первым использованием. Можно работать с моделями 3B, но когда дело доходит до возможностей перевода или простых знаний, модели 7B дают лучшие результаты. Однако с 3,3 ГБ и выше они значительно больше.
Чтобы создать механизм 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 работающим в автономном режиме
Модель загружается в кэш-хранилище вашего сайта. API Cache был представлен вместе с Service Workers, чтобы ваш веб-сайт или веб-приложение работали в автономном режиме. Это лучший механизм хранения для кэширования моделей ИИ . В отличие от HTTP-кэширования, Cache API представляет собой программируемый кеш, который полностью находится под контролем разработчика.
После загрузки WebLLM считывает файлы модели из Cache API, а не запрашивает их по сети, что делает WebLLM полностью автономным.
Как и во всех хранилищах веб-сайтов, кеш изолирован для каждого источника. Это означает, что два источника, example.com и example.net , не могут использовать одно и то же хранилище. Если бы эти два веб-сайта хотели использовать одну и ту же модель, им пришлось бы загрузить ее отдельно.
Вы можете проверить кеш с помощью DevTools , перейдя в раздел «Приложение» > «Хранилище» и открыв хранилище кэша.
Настроить разговор
Модель можно инициализировать с помощью набора начальных подсказок. Обычно существует три роли сообщения:
- Системная подсказка : эта подсказка определяет поведение, роль и характер модели. Его также можно использовать для заземления, то есть ввода в модель пользовательских данных, которые не являются частью ее обучающего набора (например, данных, специфичных для вашей предметной области). Вы можете указать только одно системное приглашение.
- Подсказка пользователя : подсказки, вводимые пользователем.
- Подсказка помощника : ответы помощника по желанию.
Подсказки для пользователя и помощника можно использовать для подсказок N-shot, предоставляя 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);
}
Оказывается, сети всегда приходилось иметь дело с потоковой передачей ответов. Вы можете использовать API, такие как DOMImplementation, для работы с этими потоковыми ответами и эффективного обновления HTML.
Результаты основаны исключительно на строках. Вы должны сначала проанализировать их, если хотите интерпретировать их как JSON или другие форматы файлов.
Однако у WebLLM есть некоторые ограничения: перед первым использованием приложению необходимо загрузить огромную модель, которую нельзя использовать совместно с разными источниками, поэтому другому веб-приложению, возможно, придется загрузить ту же модель еще раз. Хотя WebGPU обеспечивает производительность вывода, близкую к исходной, он не достигает полной собственной скорости.
Демо
Эти недостатки устраняются с помощью Prompt API — исследовательского API, предложенного Google, который также работает на стороне клиента, но использует центральную модель, загруженную в Chrome. Это означает, что несколько приложений могут использовать одну и ту же модель на полной скорости выполнения.
Подробнее о добавлении возможностей чат-бота с помощью Prompt API читайте в следующей статье.