@browser-ai/web-llm 2.1.0 → 2.1.2
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 +116 -12
- package/dist/index.d.ts +116 -12
- package/dist/index.js +211 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +210 -4
- 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) {
|
|
@@ -1116,7 +1118,8 @@ var WebLLMLanguageModel = class {
|
|
|
1116
1118
|
responseFormat,
|
|
1117
1119
|
seed,
|
|
1118
1120
|
tools,
|
|
1119
|
-
toolChoice
|
|
1121
|
+
toolChoice,
|
|
1122
|
+
providerOptions
|
|
1120
1123
|
}) {
|
|
1121
1124
|
const warnings = [];
|
|
1122
1125
|
const functionTools = (tools ?? []).filter(isFunctionTool).map((tool) => ({
|
|
@@ -1183,6 +1186,12 @@ var WebLLMLanguageModel = class {
|
|
|
1183
1186
|
top_p: topP,
|
|
1184
1187
|
seed
|
|
1185
1188
|
};
|
|
1189
|
+
if (providerOptions?.extra_body) {
|
|
1190
|
+
requestOptions.extra_body = {
|
|
1191
|
+
enable_thinking: providerOptions.extra_body.enable_thinking,
|
|
1192
|
+
enable_latency_breakdown: providerOptions.extra_body.enable_latency_breakdown
|
|
1193
|
+
};
|
|
1194
|
+
}
|
|
1186
1195
|
if (responseFormat?.type === "json") {
|
|
1187
1196
|
requestOptions.response_format = {
|
|
1188
1197
|
type: "json_object",
|
|
@@ -1688,16 +1697,213 @@ var WebLLMLanguageModel = class {
|
|
|
1688
1697
|
}
|
|
1689
1698
|
};
|
|
1690
1699
|
|
|
1700
|
+
// src/web-llm-embedding-model.ts
|
|
1701
|
+
import {
|
|
1702
|
+
CreateWebWorkerMLCEngine as CreateWebWorkerMLCEngine2,
|
|
1703
|
+
MLCEngine as MLCEngine2
|
|
1704
|
+
} from "@mlc-ai/web-llm";
|
|
1705
|
+
var WebLLMEmbeddingModel = class {
|
|
1706
|
+
constructor(modelId, options = {}) {
|
|
1707
|
+
this.specificationVersion = "v3";
|
|
1708
|
+
this.provider = "web-llm";
|
|
1709
|
+
this.supportsParallelCalls = false;
|
|
1710
|
+
this.isInitialized = false;
|
|
1711
|
+
this.modelId = modelId;
|
|
1712
|
+
this.maxEmbeddingsPerCall = options.maxEmbeddingsPerCall ?? 100;
|
|
1713
|
+
this.config = {
|
|
1714
|
+
provider: this.provider,
|
|
1715
|
+
modelId,
|
|
1716
|
+
options
|
|
1717
|
+
};
|
|
1718
|
+
}
|
|
1719
|
+
/**
|
|
1720
|
+
* Check if the model is initialized and ready to use
|
|
1721
|
+
*/
|
|
1722
|
+
get isModelInitialized() {
|
|
1723
|
+
return this.isInitialized;
|
|
1724
|
+
}
|
|
1725
|
+
async getEngine(options, onInitProgress) {
|
|
1726
|
+
const availability = await this.availability();
|
|
1727
|
+
if (availability === "unavailable") {
|
|
1728
|
+
throw new LoadSettingError({
|
|
1729
|
+
message: "WebLLM is not available. This library requires a browser with WebGPU support."
|
|
1730
|
+
});
|
|
1731
|
+
}
|
|
1732
|
+
if (this.engine && this.isInitialized) return this.engine;
|
|
1733
|
+
if (this.initializationPromise) {
|
|
1734
|
+
await this.initializationPromise;
|
|
1735
|
+
if (this.engine) return this.engine;
|
|
1736
|
+
}
|
|
1737
|
+
this.initializationPromise = this._initializeEngine(
|
|
1738
|
+
options,
|
|
1739
|
+
onInitProgress
|
|
1740
|
+
);
|
|
1741
|
+
await this.initializationPromise;
|
|
1742
|
+
if (!this.engine) {
|
|
1743
|
+
throw new LoadSettingError({
|
|
1744
|
+
message: "Engine initialization failed"
|
|
1745
|
+
});
|
|
1746
|
+
}
|
|
1747
|
+
return this.engine;
|
|
1748
|
+
}
|
|
1749
|
+
async _initializeEngine(options, onInitProgress) {
|
|
1750
|
+
try {
|
|
1751
|
+
const engineConfig = {
|
|
1752
|
+
...this.config.options.engineConfig,
|
|
1753
|
+
...options,
|
|
1754
|
+
initProgressCallback: onInitProgress || this.config.options.initProgressCallback
|
|
1755
|
+
};
|
|
1756
|
+
if (this.config.options.worker) {
|
|
1757
|
+
this.engine = await CreateWebWorkerMLCEngine2(
|
|
1758
|
+
this.config.options.worker,
|
|
1759
|
+
this.modelId,
|
|
1760
|
+
engineConfig
|
|
1761
|
+
);
|
|
1762
|
+
} else {
|
|
1763
|
+
this.engine = new MLCEngine2(engineConfig);
|
|
1764
|
+
await this.engine.reload(this.modelId);
|
|
1765
|
+
}
|
|
1766
|
+
this.isInitialized = true;
|
|
1767
|
+
} catch (error) {
|
|
1768
|
+
this.engine = void 0;
|
|
1769
|
+
this.isInitialized = false;
|
|
1770
|
+
this.initializationPromise = void 0;
|
|
1771
|
+
throw new LoadSettingError({
|
|
1772
|
+
message: `Failed to initialize WebLLM embedding engine: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1773
|
+
});
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
/**
|
|
1777
|
+
* Check the availability of the WebLLM embedding model
|
|
1778
|
+
* @returns Promise resolving to "unavailable", "available", or "downloadable"
|
|
1779
|
+
*/
|
|
1780
|
+
async availability() {
|
|
1781
|
+
if (this.isInitialized) {
|
|
1782
|
+
return "available";
|
|
1783
|
+
}
|
|
1784
|
+
if (this.config.options.worker && isMobile()) {
|
|
1785
|
+
return "downloadable";
|
|
1786
|
+
}
|
|
1787
|
+
const supported = checkWebGPU();
|
|
1788
|
+
return supported ? "downloadable" : "unavailable";
|
|
1789
|
+
}
|
|
1790
|
+
/**
|
|
1791
|
+
* Creates an engine session with download progress monitoring.
|
|
1792
|
+
*
|
|
1793
|
+
* @example
|
|
1794
|
+
* ```typescript
|
|
1795
|
+
* const engine = await model.createSessionWithProgress(
|
|
1796
|
+
* (progress) => {
|
|
1797
|
+
* console.log(`Download progress: ${Math.round(progress.progress * 100)}%`);
|
|
1798
|
+
* }
|
|
1799
|
+
* );
|
|
1800
|
+
* ```
|
|
1801
|
+
*
|
|
1802
|
+
* @param onInitProgress Optional callback receiving progress reports during model download
|
|
1803
|
+
* @returns Promise resolving to a configured WebLLM engine
|
|
1804
|
+
* @throws {LoadSettingError} When WebLLM isn't available or model is unavailable
|
|
1805
|
+
*/
|
|
1806
|
+
async createSessionWithProgress(onInitProgress) {
|
|
1807
|
+
return this.getEngine(void 0, onInitProgress);
|
|
1808
|
+
}
|
|
1809
|
+
/**
|
|
1810
|
+
* Embed texts using the WebLLM embedding model
|
|
1811
|
+
*/
|
|
1812
|
+
async doEmbed(options) {
|
|
1813
|
+
const { values, abortSignal } = options;
|
|
1814
|
+
if (values.length > this.maxEmbeddingsPerCall) {
|
|
1815
|
+
throw new TooManyEmbeddingValuesForCallError({
|
|
1816
|
+
provider: this.provider,
|
|
1817
|
+
modelId: this.modelId,
|
|
1818
|
+
maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
|
|
1819
|
+
values
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1822
|
+
if (abortSignal?.aborted) {
|
|
1823
|
+
throw new Error("Operation was aborted");
|
|
1824
|
+
}
|
|
1825
|
+
const engine = await this.getEngine();
|
|
1826
|
+
const abortHandler = () => {
|
|
1827
|
+
engine.interruptGenerate();
|
|
1828
|
+
};
|
|
1829
|
+
if (abortSignal) {
|
|
1830
|
+
abortSignal.addEventListener("abort", abortHandler);
|
|
1831
|
+
}
|
|
1832
|
+
try {
|
|
1833
|
+
const response = await engine.embeddings.create({
|
|
1834
|
+
input: values,
|
|
1835
|
+
model: this.modelId,
|
|
1836
|
+
...abortSignal && !this.config.options.worker && { signal: abortSignal }
|
|
1837
|
+
});
|
|
1838
|
+
const sortedEmbeddings = response.data.sort((a, b) => a.index - b.index).map((e) => e.embedding);
|
|
1839
|
+
return {
|
|
1840
|
+
embeddings: sortedEmbeddings,
|
|
1841
|
+
usage: {
|
|
1842
|
+
tokens: response.usage.total_tokens
|
|
1843
|
+
},
|
|
1844
|
+
providerMetadata: {
|
|
1845
|
+
webllm: {
|
|
1846
|
+
model: response.model,
|
|
1847
|
+
promptTokens: response.usage.prompt_tokens,
|
|
1848
|
+
totalTokens: response.usage.total_tokens,
|
|
1849
|
+
prefillTokensPerSecond: response.usage.extra?.prefill_tokens_per_s
|
|
1850
|
+
}
|
|
1851
|
+
},
|
|
1852
|
+
warnings: []
|
|
1853
|
+
};
|
|
1854
|
+
} catch (error) {
|
|
1855
|
+
throw new Error(
|
|
1856
|
+
`WebLLM embedding failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1857
|
+
);
|
|
1858
|
+
} finally {
|
|
1859
|
+
if (abortSignal) {
|
|
1860
|
+
abortSignal.removeEventListener("abort", abortHandler);
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
};
|
|
1865
|
+
|
|
1691
1866
|
// src/index.ts
|
|
1692
1867
|
import { WebWorkerMLCEngineHandler } from "@mlc-ai/web-llm";
|
|
1693
1868
|
|
|
1694
1869
|
// src/web-llm-provider.ts
|
|
1695
|
-
function
|
|
1696
|
-
|
|
1870
|
+
function createWebLLM() {
|
|
1871
|
+
const createLanguageModel = (modelId, settings) => {
|
|
1872
|
+
return new WebLLMLanguageModel(modelId, settings);
|
|
1873
|
+
};
|
|
1874
|
+
const createEmbeddingModel = (modelId, settings) => {
|
|
1875
|
+
return new WebLLMEmbeddingModel(modelId, settings);
|
|
1876
|
+
};
|
|
1877
|
+
const provider = function(modelId, settings) {
|
|
1878
|
+
if (new.target) {
|
|
1879
|
+
throw new Error(
|
|
1880
|
+
"The WebLLM model function cannot be called with the new keyword."
|
|
1881
|
+
);
|
|
1882
|
+
}
|
|
1883
|
+
return createLanguageModel(modelId, settings);
|
|
1884
|
+
};
|
|
1885
|
+
provider.specificationVersion = "v3";
|
|
1886
|
+
provider.languageModel = createLanguageModel;
|
|
1887
|
+
provider.chat = createLanguageModel;
|
|
1888
|
+
provider.embedding = createEmbeddingModel;
|
|
1889
|
+
provider.embeddingModel = createEmbeddingModel;
|
|
1890
|
+
provider.imageModel = (modelId) => {
|
|
1891
|
+
throw new NoSuchModelError({ modelId, modelType: "imageModel" });
|
|
1892
|
+
};
|
|
1893
|
+
provider.speechModel = (modelId) => {
|
|
1894
|
+
throw new NoSuchModelError({ modelId, modelType: "speechModel" });
|
|
1895
|
+
};
|
|
1896
|
+
provider.transcriptionModel = (modelId) => {
|
|
1897
|
+
throw new NoSuchModelError({ modelId, modelType: "transcriptionModel" });
|
|
1898
|
+
};
|
|
1899
|
+
return provider;
|
|
1697
1900
|
}
|
|
1901
|
+
var webLLM = createWebLLM();
|
|
1698
1902
|
export {
|
|
1903
|
+
WebLLMEmbeddingModel,
|
|
1699
1904
|
WebLLMLanguageModel,
|
|
1700
1905
|
WebWorkerMLCEngineHandler,
|
|
1906
|
+
createWebLLM,
|
|
1701
1907
|
doesBrowserSupportWebLLM,
|
|
1702
1908
|
webLLM
|
|
1703
1909
|
};
|