@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.d.mts +126 -16
- package/dist/index.d.ts +126 -16
- package/dist/index.js +213 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +212 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -957,7 +957,7 @@ ${existingContent}` : "")
|
|
|
957
957
|
];
|
|
958
958
|
}
|
|
959
959
|
|
|
960
|
-
// src/
|
|
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
|
|
1351
|
+
* const model = await model.createSessionWithProgress(
|
|
1350
1352
|
* (progress) => {
|
|
1351
|
-
* console.log(`Download progress: ${Math.round(progress
|
|
1353
|
+
* console.log(`Download progress: ${Math.round(progress * 100)}%`);
|
|
1352
1354
|
* }
|
|
1353
1355
|
* );
|
|
1354
1356
|
* ```
|
|
1355
1357
|
*
|
|
1356
|
-
* @param
|
|
1357
|
-
* @returns Promise resolving to
|
|
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(
|
|
1361
|
-
|
|
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
|
|
1692
|
-
|
|
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
|
};
|