Skip to main content
Early Beta — The Web SDK is in early beta. APIs may change between releases.

Overview

Vision language models take an image plus a text prompt and produce text: a description, an answer, or an analysis. The Web SDK runs them through llama.cpp’s mtmd multimodal path in the @runanywhere/web-llamacpp WASM artifact. Two entry points, both on the root facade:
Note that processImageStream returns a promise wrapping the iterable, so it needs two awaits: one for the handle, then for await over it.

Imports

Everything comes from the core package plus the browser helper entrypoint. The backend package root exposes only its registration facade.

Loading a model

Loading a multimodal model syncs the SDK’s vision-language provider automatically. There is no separate VLM initialization step.

Building a VLMImage

VLMImage is a proto message with a format discriminator. Use the factory helpers rather than constructing it by hand. Width and height are required for the raw formats because there is no header to read them from.

Generation options

VLMGenerationOptions carries the prompt, unlike the LLM options object which keeps it separate. VLMModelFamily values are UNSPECIFIED, AUTO, QWEN2_VL, SMOLVLM, LLAVA, and CUSTOM. Leave it unspecified unless a model needs a template the SDK cannot infer. 2048 default tokens is generous for a caption. Drop maxTokens to 30-60 for one-line descriptions; image encoding already dominates the latency budget in WASM.

Streaming a camera frame

Stream event kinds are UNSPECIFIED, STARTED, IMAGE_ENCODED, TOKEN, COMPLETED, and ERROR. Each event carries seq, timestampUs, requestId, token, tokenIndex, isFinal, tokensPerSecond, and, on terminal events, result. To cancel mid-generation, call RunAnywhere.cancelVLMGeneration() or pass an AbortSignal to the non-streaming processImage().

Result

VideoCapture

VideoCapture from @runanywhere/web/browser owns the getUserMedia stream, an internal <video> element, and an offscreen canvas for pixel extraction.
captureFrame(maxDimension = 512) returns null when the stream has no valid dimensions yet, so a null check is enough. If you need to know exactly when the camera is ready, videoWidth and videoHeight report the live stream dimensions.

Registering VLM models

A VLM needs two files: the primary GGUF and a multimodal projector. Register them with registerModelMultiFile and a ModelFileRole per entry.
The SDK assembles the MultiFileArtifact and ExpectedModelFiles protos from that list and drives the download orchestrator; the app never builds those messages itself.

Models in the example app

Exact URLs and per-file sizes live in examples/web/RunAnywhereAI/src/services/model-catalog.ts. Larger VLMs are omitted deliberately. WASM32 caps the heap at 4 GB and a download must fit in memory before it lands in OPFS, so a multi-GB multimodal GGUF is not practical in a tab.

Performance notes

Capture at 256 to 384 pixels. Image encoding cost grows quickly with resolution and it usually dominates total latency. Keep maxTokens low for live captioning. 30 to 60 tokens is enough for a sentence. SmolVLM2 256M is the cheapest starting point at roughly 420 MB of working memory.

LLM generation

Text-only generation

Tool calling

Function calling with LLMs

Best practices

Performance optimization