Repository navigation
Conversation
Serves one static page, behind ENABLE_WEBGPU_PLAYGROUND (default off), that turns a phone, tablet or laptop browser into an on-device inference target: it checks WebGPU, measures the GPU's memory bandwidth and fp32 throughput with two compute shaders, estimates decode speed per model, and runs a small instruction-tuned LLM entirely in the browser through WebLLM. Prompts and outputs stay on the device; the router adds no inference endpoints.
- Register the page with app.add_api_route. On FastAPI 0.141, a router added with include_router becomes an _IncludedRouter without .path, and prometheus-fastapi-instrumentator 6.0.0 raises on it while it names a request, so the page answered 500 with metrics on (the default). A test now covers the instrumented app. - Read WebLLM's decode speed from the final stream chunk (stream_options.include_usage), with runtimeStatsText as the fallback. - Mark software adapters (SwiftShader, lavapipe, WARP) and show no bandwidth estimate for them. - Label the build row "Model builds: fp16 / fp32".
swizzley
requested review from
MTaraszewski,
PawelPeczek-Roboflow,
dkosowski87,
grzegorz-roboflow,
hansent,
probicheaux,
rafel-roboflow and
yeldarby
as code owners
October 30, 2026 02:32
Collaborator
|
In order to proceed with the review, pleas sign the CLA. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds an opt-in on-device WebGPU playground at
/webgpu. It turns a phone, tablet or laptop browser into an on-device inference target. The flag is off by default (ENABLE_WEBGPU_PLAYGROUND=Trueturns it on), the same pattern the Builder uses withENABLE_BUILDER.Open
/webgpuon any device that can reach the server. The page:shader-f16support and buffer limits. It also flags software renderers (SwiftShader, lavapipe, WARP).vec4copy over a 64 MB buffer;shader-f16.Prompts and answers stay on the device. The server hands out one static HTML page and adds no inference endpoints: both routes are
include_in_schema=False, and the OpenAPI schema is unchanged. The page is also a quick way to see what the GPU in someone's pocket can do before you target it for edge deployment.Files
inference/core/interfaces/http/webgpu/playground.html@mlc-ai/web-llm@0.2.78(Apache-2.0) and imported from jsDelivr only when the visitor starts a model.inference/core/interfaces/http/webgpu/routes.pymount_webgpu_playground(app, prefix)registersGET /webgpuandGET /webgpu/.inference/core/env.pyENABLE_WEBGPU_PLAYGROUND, defaultFalse.inference/core/interfaces/http/http_api.pytests/.../test_webgpu_playground.pydocs/webgpu_playground.md,mkdocs.ymlBrowsers expose WebGPU only to secure contexts.
localhostworks as is. From a phone, serve the page over HTTPS or a tunnel. When the page is opened over plain HTTP, it says so and explains the fix.Type of Change
Testing
pytest tests/inference/unit_tests/core/interfaces/http/test_webgpu_playground.py test_builder_availability.py: 9 passed.black,isortandflake8at the versions inrequirements.code_analysis.txt: clean on the changed Python files.docker/config/cpu_http.pyunder uvicorn withENABLE_WEBGPU_PLAYGROUND=True, then drove the page with headless Chromium at phone size (390 × 844, mobile, touch). WebGPU came from SwiftShader because the test machine has no GPU. Results:/webgpuand/webgpu/return 200, and/metricscounts both under their own handler names./openapi.json.Checklist
Additional Context
A finding on
main, outside this PR: with the dependency versions a fresh install resolves today (FastAPI 0.141.1, insidefastapi>=0.134,<0.142, and prometheus-fastapi-instrumentator 6.0.0), the Builder returns 500 at/buildwhile metrics are on, which is the default (METRICS_ENABLED=True).The cause: FastAPI 0.141 wraps a router added with
include_routerin an_IncludedRouterobject that has no.pathattribute. The instrumentator's_get_route_namereadsroute.pathon every route while it names a request, so it raises:To reproduce:
ENABLE_BUILDER=True, startcpu_http:app, thencurl localhost:9001/build.This PR keeps its own page clear of it:
mount_webgpu_playgroundregisters its routes withapp.add_api_route, and a test covers the instrumented app. The Builder is left as it is, to keep this PR to one feature. Pinningfastapi<0.141or upgrading the instrumentator would fix it there.Packaging: the page ships the same way as the Builder's
editor.html. The Docker images copy the source tree (COPY inference inference), so it needs nopackage_datachange.Network access: the page itself comes from the inference server. Model weights come from Hugging Face (
mlc-ai/*), and WebLLM comes from jsDelivr. On an air-gapped network, the GPU check and measurement still work; loading a model needs those two hosts.