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

Overview

The VLM (Vision Language Model) module enables multimodal inference — you can feed an image and a text prompt to get descriptions, answers, or analysis. It uses llama.cpp’s mtmd (multimodal) backend compiled to WebAssembly and runs inference in a dedicated Web Worker to keep the UI responsive.

Package Imports

VLM classes come from @runanywhere/web-llamacpp, while model management is in @runanywhere/web:

Worker Setup

VLM inference runs in a dedicated Web Worker for responsiveness. You need to set up the worker bridge during SDK initialization:
runanywhere.ts
workers/vlm-worker.ts
The ?worker&url import syntax is Vite-specific and not recognized by TypeScript, requiring a @ts-ignore directive. For other bundlers, you may need to configure the worker URL differently.
“non-JavaScript MIME type” error for VLM worker: If you see Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html", the worker URL is resolving to your SPA’s index.html instead of the actual JavaScript file. This typically happens when:
  1. Your server’s catch-all route intercepts .js file requests
  2. The worker file isn’t included in the production build output
  3. worker: { format: 'es' } is missing from your Vite config
Ensure static .js files are served before the SPA catch-all route. See Installation troubleshooting.

Basic Usage

Use VLMWorkerBridge for the best user experience — inference runs in a Web Worker so the UI stays responsive:
Always wait for camera readiness before calling captureFrame(). The video stream takes time to initialize after camera.start() resolves. If you call captureFrame() before the video has valid dimensions, you’ll get Error: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The source width is 0. Wait for the loadedmetadata event or check videoElement.videoWidth > 0.

API Reference

VLMWorkerBridge.process() does NOT support systemPrompt in its options. The options only accept maxTokens and temperature. To include system-level instructions, prepend them to the prompt parameter directly:
The standalone VLMGenerationOptions type (below) does include systemPrompt, but that is for the native VLM API, not for VLMWorkerBridge.process() which uses a simplified options type.

Types

Camera Integration

VideoCapture

The VideoCapture class is in @runanywhere/web-llamacpp:

Waiting for Camera Readiness

The camera stream takes a moment to initialize after start() resolves. Always guard against zero-dimension frames:
Calling captureFrame() before the video stream is fully initialized causes: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The source width is 0. This commonly happens in React components that call captureFrame() immediately after start() without waiting for video dimensions to be valid.

Examples

Live Camera Streaming

React Component

VisionChat.tsx

Supported Models

Registering VLM Models

VLM models require two files: the main model GGUF and a multimodal projector (mmproj) GGUF. Register them using the files array — the first file is the main model, the second is the projector:

WASM Memory Crash Handling

VLM image encoding is computationally expensive in WASM and can occasionally trigger memory access out of bounds errors. Always wrap VLM calls in try/catch and handle these gracefully:

Performance Tips

  • Use 256x256 capture dimensions — larger images dramatically increase encoding time
  • Use VLMWorkerBridge instead of direct VLM — it runs in a Web Worker and won’t freeze the UI
  • Limit maxTokens for descriptions (30-60 tokens for quick descriptions, 80+ for detailed analysis)
  • Liquid LFM2-VL 450M is the best starting point — smallest multimodal model, fast and memory-efficient (~500MB)
  • Handle WASM crashesmemory access out of bounds is recoverable; display a retry message

LLM Generation

Text-only generation

Tool Calling

Function calling with LLMs

Best Practices

Performance optimization