chore: import upstream snapshot with attribution
Build / build (push) Has been cancelled
Tests / test (push) Has been cancelled
Build site and push to gh-pages / Build site (push) Has been cancelled
Linter / lint (push) Has been cancelled
Security / dependency-review (push) Has been cancelled
Security / npm-audit (push) Has been cancelled
Security / codeql (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:42:51 +08:00
commit f73e710e38
276 changed files with 36598 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
# WebLLM Subgroups Usage App
This folder provides a minimum demo to show capability-based routing between
baseline and subgroup WebGPU WASM builds in a webapp setting.
To try it out, you can do the following steps under this folder
```bash
npm install
npm start
```
Edit `src/subgroups_usage.ts` if you would like to point the example at your own
model path and baseline `model_lib`. The example will suffix the WASM filename
with `-subgroups` before the `.wasm` extension when the adapter reports
subgroup support.
Note if you would like to hack WebLLM core package.
You can change the WebLLM dependency to `"file:../.."`, and follow the build
from source instruction in the project to build webllm locally. This option is only recommended
if you would like to hack WebLLM core package.
+25
View File
@@ -0,0 +1,25 @@
{
"name": "subgroups-usage",
"version": "0.1.0",
"private": true,
"scripts": {
"start": "parcel src/subgroups_usage.html --port 8888",
"build": "parcel build src/subgroups_usage.html --dist-dir lib"
},
"devDependencies": {
"buffer": "^5.7.1",
"crypto-browserify": "^3.12.1",
"events": "^3.3.0",
"parcel": "^2.8.3",
"process": "^0.11.10",
"stream-browserify": "^3.0.0",
"string_decoder": "^1.3.0",
"tslib": "^2.3.1",
"typescript": "^4.9.5",
"url": "^0.11.3",
"vm-browserify": "^1.1.2"
},
"dependencies": {
"@mlc-ai/web-llm": "^0.2.84"
}
}
@@ -0,0 +1,26 @@
<!doctype html>
<html>
<script>
webLLMGlobal = {};
</script>
<body>
<h2>WebLLM Test Page</h2>
Open console to see output
<br />
<br />
<label id="init-label"> </label>
<br />
<br />
<h3>Prompt</h3>
<label id="prompt-label"> </label>
<br />
<br />
<h3>Response</h3>
<label id="generate-label"> </label>
<br />
<br />
<label id="stats-label"> </label>
<script type="module" src="./subgroups_usage.ts"></script>
</body>
</html>
@@ -0,0 +1,136 @@
import * as webllm from "@mlc-ai/web-llm";
function setLabel(id: string, text: string) {
const label = document.getElementById(id);
if (label == null) {
throw Error("Cannot find label " + id);
}
label.innerText = text;
}
function toSg32ModelLib(modelLib: string): string {
const modelLibUrl = new URL(modelLib);
const pathParts = modelLibUrl.pathname.split("/");
const wasmFileIndex = pathParts.length - 1;
const variantDirIndex = wasmFileIndex - 1;
if (variantDirIndex < 0 || pathParts[variantDirIndex] !== "base") {
throw Error(
`Expected model_lib path variant directory to be "base": ${modelLib}`,
);
}
pathParts[variantDirIndex] = "sg32";
modelLibUrl.pathname = pathParts.join("/");
return modelLibUrl.toString();
}
async function main() {
const initProgressCallback = (report: webllm.InitProgressReport) => {
setLabel("init-label", report.text);
};
const selectedModel = "Llama-3.1-8B-Instruct-q4f32_1-MLC";
const adapter = await (navigator as any).gpu?.requestAdapter({
powerPreference: "high-performance",
});
if (adapter == null) {
throw Error("Unable to request a WebGPU adapter.");
}
const adapterInfo =
adapter.info || (await (adapter as any).requestAdapterInfo());
const subgroupMinSize = adapterInfo.subgroupMinSize;
const subgroupMaxSize = adapterInfo.subgroupMaxSize;
const supportsSubgroups =
adapter.features.has("subgroups") &&
subgroupMinSize !== undefined &&
subgroupMinSize <= 32 &&
subgroupMaxSize !== undefined &&
32 <= subgroupMaxSize &&
adapter.limits.maxComputeInvocationsPerWorkgroup >= 1024;
console.log("supportsSubgroups: ", supportsSubgroups);
// Option 1: If we do not specify appConfig, we use `prebuiltAppConfig` defined in `config.ts`
const modelRecord = webllm.prebuiltAppConfig.model_list.find(
(entry: webllm.ModelRecord) => entry.model_id === selectedModel,
);
const appConfig =
supportsSubgroups && modelRecord !== undefined
? {
model_list: [
{
...modelRecord,
model_lib: toSg32ModelLib(modelRecord.model_lib),
},
],
}
: undefined;
const engine: webllm.MLCEngineInterface = await webllm.CreateMLCEngine(
selectedModel,
{
appConfig: appConfig,
initProgressCallback: initProgressCallback,
logLevel: "INFO", // specify the log level
},
// customize kv cache, use either context_window_size or sliding_window_size (with attention sink)
{
context_window_size: 2048,
// sliding_window_size: 1024,
// attention_sink_size: 4,
},
);
// Option 2: Specify your own model other than the prebuilt ones
// const appConfig: webllm.AppConfig = {
// model_list: [
// {
// model: "https://huggingface.co/mlc-ai/Llama-3.1-8B-Instruct-q4f32_1-MLC",
// model_id: "Llama-3.1-8B-Instruct-q4f32_1-MLC",
// model_lib:
// webllm.modelLibURLPrefix +
// webllm.modelVersion +
// "/Llama-3_1-8B-Instruct-q4f32_1-ctx4k_cs1k-webgpu.wasm",
// overrides: {
// context_window_size: 2048,
// },
// },
// ],
// };
// if (supportsSubgroups) {
// appConfig.model_list[0].model_lib = toSg32ModelLib(
// appConfig.model_list[0].model_lib,
// );
// }
// const engine: webllm.MLCEngineInterface = await webllm.CreateMLCEngine(
// selectedModel,
// { appConfig: appConfig, initProgressCallback: initProgressCallback },
// );
// Option 3: Instantiate MLCEngine() and call reload() separately
// const engine: webllm.MLCEngineInterface = new webllm.MLCEngine({
// appConfig: appConfig, // if do not specify, we use webllm.prebuiltAppConfig
// initProgressCallback: initProgressCallback,
// });
// await engine.reload(selectedModel);
const reply0 = await engine.chat.completions.create({
messages: [{ role: "user", content: "List three US states." }],
// below configurations are all optional
n: 3,
temperature: 1.5,
max_tokens: 256,
// 46510 and 7188 are "California", and 8421 and 51325 are "Texas" in Llama-3.1-8B-Instruct
// So we would have a higher chance of seeing the latter two, but never the first in the answer
logit_bias: {
"46510": -100,
"7188": -100,
"8421": 5,
"51325": 5,
},
logprobs: true,
top_logprobs: 2,
});
console.log(reply0);
console.log(reply0.usage);
// To change model, either create a new engine via `CreateMLCEngine()`, or call `engine.reload(modelId)`
}
main();