Читать книгу Практическая реализация AI-агента в Chrome с LangChain - - Страница 3
Глава 3. Создание экземпляра LLM в браузере
ОглавлениеСоздание экземпляра LLM в браузере представляет собой ключевой шаг в практической реализации AI‑агентов с помощью LangChain, поскольку именно в этом месте происходит переход от поиска и подготовки данных к непосредственному использованию модели для генерации ответов, планирования действий и взаимодействия с пользователем; в данном разделе мы подробно рассмотрим, как собрать и запустить локальную или облачную LLM напрямую в окружении Chrome, используя возможности WebAssembly, промисы и динамические импорты, а также как интегрировать её в цепочку происходящих в браузере вычислений через LangChain.
Первым делом нужно выбрать подходящий движок модели, который может работать в клиентском JavaScript‑окружении; наиболее популярными являются проекты, такие как GGUF‑формат модели с поддержкой llama.cpp, а также специализированные библиотеки вроде of‑the‑shelf‑transformers‑js, которые предоставляют готовые обёртки над TensorFlow.js и ONNX‑runtime‑web. Для целей демонстрации возьмём небольшую модель «Phi‑2» (≈256 МБ в GGUF‑формате), поскольку она достаточно лёгка, чтобы полностью загрузиться в память браузера без превышения обычных ограничений на размер скриптов и ресурсов. Загрузка модели осуществляется асинхронно через fetch API, после чего её байты конвертируются в бинарный буфер, из которого создаётся внутренний объект llama.cpp‑engine, экспортируемый в виде WebAssembly‑модуля.
В коде мы начинаем с импорта необходимых модулей LangChain:
```javascript
import { LLM } from "langchain/llms";
import { PromptTemplate } from "langchain/prompts";
import { AgentType } from "langchain/agents";
```
а затем объявляем собственный класс `BrowserLLM`, наследующий от `LLM` базового класса LangChain и реализующий требуемый интерфейс `generate(prompt: string) : Promise<string>`. Внутри конструктора мы инициализируем трансформер модели, указываем путь к файлу `.bin` (например, `"phi2-q4_0.gguf"`), и запускаем асинхронную функцию `loadModel` которая загружает весовые данные через `fetch`, начинает трансформацию в `Wasm.Decoder` и сохраняет ссылку на готовый `llamaEngine` в поле инстанса; важно добавить обработчики прогресса и ошибок, чтобы пользователь видел индикатор загрузки и мог отменить процесс, если он оказался слишком тяжёлым для конкретного устройства.
После того как модель полностью готова, метод `generate` принимает строку‑запрос, формирует её в виде токенов с помощью встроенного токенизатора (в нашем случае токенизатор, экспортированный из той же скачанной модели), передаёт массив токенов в `llamaEngine.evaluate(promptTokens, maxNewTokens, temperature, topP)`, ждёт завершения вычислений через `await engine.run(…)`, получает обратно массив новых токенов, преобразует их в строку и возвращает её как результат. Этот метод автоматически использует `Promise` и поэтому полностью совместим с цепочками `then`/`await`, что делает его идеальным для использования в агентах LangChain, где каждый шаг обработки может быть асинхронным и зависеть от внешних запросов.