@browser-ai/web-llm 2.0.4 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -957,7 +957,7 @@ ${existingContent}` : "")
957
957
  ];
958
958
  }
959
959
 
960
- // src/web-llm-language-model.ts
960
+ // src/utils/browser.ts
961
961
  function isMobile() {
962
962
  if (typeof navigator === "undefined") return false;
963
963
  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
@@ -974,6 +974,8 @@ function checkWebGPU() {
974
974
  function doesBrowserSupportWebLLM() {
975
975
  return checkWebGPU();
976
976
  }
977
+
978
+ // src/web-llm-language-model.ts
977
979
  function extractToolName(content) {
978
980
  const jsonMatch = content.match(/\{\s*"name"\s*:\s*"([^"]+)"/);
979
981
  if (jsonMatch) {
@@ -1346,19 +1348,23 @@ var WebLLMLanguageModel = class {
1346
1348
  *
1347
1349
  * @example
1348
1350
  * ```typescript
1349
- * const engine = await model.createSessionWithProgress(
1351
+ * const model = await model.createSessionWithProgress(
1350
1352
  * (progress) => {
1351
- * console.log(`Download progress: ${Math.round(progress.loaded * 100)}%`);
1353
+ * console.log(`Download progress: ${Math.round(progress * 100)}%`);
1352
1354
  * }
1353
1355
  * );
1354
1356
  * ```
1355
1357
  *
1356
- * @param onInitProgress Optional callback receiving progress reports during model download
1357
- * @returns Promise resolving to a configured WebLLM engine
1358
+ * @param onDownloadProgress Optional callback receiving progress values from 0 to 1
1359
+ * @returns Promise resolving to the model instance
1358
1360
  * @throws {LoadSettingError} When WebLLM is not available or model is unavailable
1359
1361
  */
1360
- async createSessionWithProgress(onInitProgress) {
1361
- return this.getEngine(void 0, onInitProgress);
1362
+ async createSessionWithProgress(onDownloadProgress) {
1363
+ const adaptedCallback = onDownloadProgress ? (report) => {
1364
+ onDownloadProgress(report.progress);
1365
+ } : void 0;
1366
+ await this.getEngine(void 0, adaptedCallback);
1367
+ return this;
1362
1368
  }
1363
1369
  /**
1364
1370
  * Generates a streaming text response using WebLLM
@@ -1684,16 +1690,213 @@ var WebLLMLanguageModel = class {
1684
1690
  }
1685
1691
  };
1686
1692
 
1693
+ // src/web-llm-embedding-model.ts
1694
+ import {
1695
+ CreateWebWorkerMLCEngine as CreateWebWorkerMLCEngine2,
1696
+ MLCEngine as MLCEngine2
1697
+ } from "@mlc-ai/web-llm";
1698
+ var WebLLMEmbeddingModel = class {
1699
+ constructor(modelId, options = {}) {
1700
+ this.specificationVersion = "v3";
1701
+ this.provider = "web-llm";
1702
+ this.supportsParallelCalls = false;
1703
+ this.isInitialized = false;
1704
+ this.modelId = modelId;
1705
+ this.maxEmbeddingsPerCall = options.maxEmbeddingsPerCall ?? 100;
1706
+ this.config = {
1707
+ provider: this.provider,
1708
+ modelId,
1709
+ options
1710
+ };
1711
+ }
1712
+ /**
1713
+ * Check if the model is initialized and ready to use
1714
+ */
1715
+ get isModelInitialized() {
1716
+ return this.isInitialized;
1717
+ }
1718
+ async getEngine(options, onInitProgress) {
1719
+ const availability = await this.availability();
1720
+ if (availability === "unavailable") {
1721
+ throw new LoadSettingError({
1722
+ message: "WebLLM is not available. This library requires a browser with WebGPU support."
1723
+ });
1724
+ }
1725
+ if (this.engine && this.isInitialized) return this.engine;
1726
+ if (this.initializationPromise) {
1727
+ await this.initializationPromise;
1728
+ if (this.engine) return this.engine;
1729
+ }
1730
+ this.initializationPromise = this._initializeEngine(
1731
+ options,
1732
+ onInitProgress
1733
+ );
1734
+ await this.initializationPromise;
1735
+ if (!this.engine) {
1736
+ throw new LoadSettingError({
1737
+ message: "Engine initialization failed"
1738
+ });
1739
+ }
1740
+ return this.engine;
1741
+ }
1742
+ async _initializeEngine(options, onInitProgress) {
1743
+ try {
1744
+ const engineConfig = {
1745
+ ...this.config.options.engineConfig,
1746
+ ...options,
1747
+ initProgressCallback: onInitProgress || this.config.options.initProgressCallback
1748
+ };
1749
+ if (this.config.options.worker) {
1750
+ this.engine = await CreateWebWorkerMLCEngine2(
1751
+ this.config.options.worker,
1752
+ this.modelId,
1753
+ engineConfig
1754
+ );
1755
+ } else {
1756
+ this.engine = new MLCEngine2(engineConfig);
1757
+ await this.engine.reload(this.modelId);
1758
+ }
1759
+ this.isInitialized = true;
1760
+ } catch (error) {
1761
+ this.engine = void 0;
1762
+ this.isInitialized = false;
1763
+ this.initializationPromise = void 0;
1764
+ throw new LoadSettingError({
1765
+ message: `Failed to initialize WebLLM embedding engine: ${error instanceof Error ? error.message : "Unknown error"}`
1766
+ });
1767
+ }
1768
+ }
1769
+ /**
1770
+ * Check the availability of the WebLLM embedding model
1771
+ * @returns Promise resolving to "unavailable", "available", or "downloadable"
1772
+ */
1773
+ async availability() {
1774
+ if (this.isInitialized) {
1775
+ return "available";
1776
+ }
1777
+ if (this.config.options.worker && isMobile()) {
1778
+ return "downloadable";
1779
+ }
1780
+ const supported = checkWebGPU();
1781
+ return supported ? "downloadable" : "unavailable";
1782
+ }
1783
+ /**
1784
+ * Creates an engine session with download progress monitoring.
1785
+ *
1786
+ * @example
1787
+ * ```typescript
1788
+ * const engine = await model.createSessionWithProgress(
1789
+ * (progress) => {
1790
+ * console.log(`Download progress: ${Math.round(progress.progress * 100)}%`);
1791
+ * }
1792
+ * );
1793
+ * ```
1794
+ *
1795
+ * @param onInitProgress Optional callback receiving progress reports during model download
1796
+ * @returns Promise resolving to a configured WebLLM engine
1797
+ * @throws {LoadSettingError} When WebLLM isn't available or model is unavailable
1798
+ */
1799
+ async createSessionWithProgress(onInitProgress) {
1800
+ return this.getEngine(void 0, onInitProgress);
1801
+ }
1802
+ /**
1803
+ * Embed texts using the WebLLM embedding model
1804
+ */
1805
+ async doEmbed(options) {
1806
+ const { values, abortSignal } = options;
1807
+ if (values.length > this.maxEmbeddingsPerCall) {
1808
+ throw new TooManyEmbeddingValuesForCallError({
1809
+ provider: this.provider,
1810
+ modelId: this.modelId,
1811
+ maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
1812
+ values
1813
+ });
1814
+ }
1815
+ if (abortSignal?.aborted) {
1816
+ throw new Error("Operation was aborted");
1817
+ }
1818
+ const engine = await this.getEngine();
1819
+ const abortHandler = () => {
1820
+ engine.interruptGenerate();
1821
+ };
1822
+ if (abortSignal) {
1823
+ abortSignal.addEventListener("abort", abortHandler);
1824
+ }
1825
+ try {
1826
+ const response = await engine.embeddings.create({
1827
+ input: values,
1828
+ model: this.modelId,
1829
+ ...abortSignal && !this.config.options.worker && { signal: abortSignal }
1830
+ });
1831
+ const sortedEmbeddings = response.data.sort((a, b) => a.index - b.index).map((e) => e.embedding);
1832
+ return {
1833
+ embeddings: sortedEmbeddings,
1834
+ usage: {
1835
+ tokens: response.usage.total_tokens
1836
+ },
1837
+ providerMetadata: {
1838
+ webllm: {
1839
+ model: response.model,
1840
+ promptTokens: response.usage.prompt_tokens,
1841
+ totalTokens: response.usage.total_tokens,
1842
+ prefillTokensPerSecond: response.usage.extra?.prefill_tokens_per_s
1843
+ }
1844
+ },
1845
+ warnings: []
1846
+ };
1847
+ } catch (error) {
1848
+ throw new Error(
1849
+ `WebLLM embedding failed: ${error instanceof Error ? error.message : "Unknown error"}`
1850
+ );
1851
+ } finally {
1852
+ if (abortSignal) {
1853
+ abortSignal.removeEventListener("abort", abortHandler);
1854
+ }
1855
+ }
1856
+ }
1857
+ };
1858
+
1687
1859
  // src/index.ts
1688
1860
  import { WebWorkerMLCEngineHandler } from "@mlc-ai/web-llm";
1689
1861
 
1690
1862
  // src/web-llm-provider.ts
1691
- function webLLM(modelId, settings) {
1692
- return new WebLLMLanguageModel(modelId, settings);
1863
+ function createWebLLM() {
1864
+ const createLanguageModel = (modelId, settings) => {
1865
+ return new WebLLMLanguageModel(modelId, settings);
1866
+ };
1867
+ const createEmbeddingModel = (modelId, settings) => {
1868
+ return new WebLLMEmbeddingModel(modelId, settings);
1869
+ };
1870
+ const provider = function(modelId, settings) {
1871
+ if (new.target) {
1872
+ throw new Error(
1873
+ "The WebLLM model function cannot be called with the new keyword."
1874
+ );
1875
+ }
1876
+ return createLanguageModel(modelId, settings);
1877
+ };
1878
+ provider.specificationVersion = "v3";
1879
+ provider.languageModel = createLanguageModel;
1880
+ provider.chat = createLanguageModel;
1881
+ provider.embedding = createEmbeddingModel;
1882
+ provider.embeddingModel = createEmbeddingModel;
1883
+ provider.imageModel = (modelId) => {
1884
+ throw new NoSuchModelError({ modelId, modelType: "imageModel" });
1885
+ };
1886
+ provider.speechModel = (modelId) => {
1887
+ throw new NoSuchModelError({ modelId, modelType: "speechModel" });
1888
+ };
1889
+ provider.transcriptionModel = (modelId) => {
1890
+ throw new NoSuchModelError({ modelId, modelType: "transcriptionModel" });
1891
+ };
1892
+ return provider;
1693
1893
  }
1894
+ var webLLM = createWebLLM();
1694
1895
  export {
1896
+ WebLLMEmbeddingModel,
1695
1897
  WebLLMLanguageModel,
1696
1898
  WebWorkerMLCEngineHandler,
1899
+ createWebLLM,
1697
1900
  doesBrowserSupportWebLLM,
1698
1901
  webLLM
1699
1902
  };