VLM Inference Engine#
Docling's VLM inference engine layer is a unified abstraction for running vision-language model inference across multiple runtime backends. It decouples pipeline stages (document elements, page images) from backend-specific inference details, letting the same high-level stages drive HuggingFace Transformers, Apple MLX, vLLM, or any OpenAI-compatible API endpoint without code changes.
Key files:
| File | Purpose |
|---|---|
base.py | VlmEngineType, BaseVlmEngineOptions, VlmEngineInput, VlmEngineOutput, BaseVlmEngine |
factory.py | create_vlm_engine() — single entry point for constructing any backend |
vlm_engine_options.py | Concrete option classes per backend |
auto_inline_engine.py | AUTO_INLINE automatic backend selection logic |
Core Interfaces#
VlmEngineType#
VlmEngineType is a str enum with two class methods (is_api_variant, is_inline_variant) for grouping:
| Value | Kind |
|---|---|
AUTO_INLINE | Auto-selects best local backend |
TRANSFORMERS | HuggingFace Transformers (inline) |
MLX | Apple MLX / mlx-vlm (inline) |
VLLM | vLLM server (inline) |
API / API_OLLAMA / API_LMSTUDIO / API_OPENAI | OpenAI-compatible HTTP endpoint |
VlmEngineInput / VlmEngineOutput#
VlmEngineInput is a Pydantic model holding:
image— a PILImageprompt— text prompt stringtemperature(default0.0),max_new_tokens(default4096)stop_strings— list of generation-stop triggersextra_generation_config— backend-specific pass-through dict
VlmEngineOutput holds text, optional stop_reason, and a metadata dict.
BaseVlmEngine#
BaseVlmEngine is the ABC all backends implement. Key contract points:
initialize()— load model/connect once; implementations setself._initialized = Truepredict_batch(input_batch)— the single required method; takes aList[VlmEngineInput]and returnsList[VlmEngineOutput]predict()— convenience wrapper that callspredict_batch([input_data])[0]; engines must NOT override it__call__()— dispatches single inputs topredict()and lists topredict_batch()cleanup()— optional resource release hook
Lazy initialization: initialize() is called automatically on the first predict() or __call__() invocation, not at construction time.
BaseVlmEngineOptions#
BaseVlmEngineOptions is a Pydantic model with a _registry class-var that auto-registers concrete subclasses by their engine_type literal. This powers the VlmEngineOptionsMixin deserialization: when engine_options is provided as a dict (e.g., from JSON config), the mixin looks up the concrete class by engine_type and validates into it.
Factory and Backend Instantiation#
create_vlm_engine() is the single entry point for constructing any backend. It receives:
options: BaseVlmEngineOptions— determines which branch to takemodel_spec: VlmModelSpec— used to generate the engine-specificEngineModelConfig(repo_id, revision, torch dtype, generation settings) viamodel_spec.get_engine_config(engine_type)enable_remote_services,artifacts_path,accelerator_options— forwarded to inline engines
All backend modules are lazy-imported inside each branch, so unused backends don't require their optional dependencies to be installed .
For API-type engines, model_spec.get_api_params(engine_type) is called to inject provider-specific parameters (model name aliases, etc.) into model_config.extra_config["api_params"] .
Concrete Backend Classes#
| Engine type | Class | Options class |
|---|---|---|
AUTO_INLINE | AutoInlineVlmEngine | AutoInlineVlmEngineOptions |
TRANSFORMERS | TransformersVlmEngine | TransformersVlmEngineOptions |
MLX | MlxVlmEngine | MlxVlmEngineOptions |
VLLM | VllmVlmEngine | VllmVlmEngineOptions |
API* (all API variants) | ApiVlmEngine | ApiVlmEngineOptions |
All concrete option classes are in vlm_engine_options.py. Key per-backend settings:
- Transformers —
device, 8-bit loading, quantization, torch dtype, model compilation - MLX —
trust_remote_codeonly; Apple Silicon exclusive - vLLM — tensor parallelism, GPU memory utilization,
cudagraph_mode(PIECEWISE by default) - API — base URL, headers, timeout, max concurrency; supports OpenAI, Ollama, LM Studio
AUTO_INLINE Backend Selection#
AUTO_INLINE is the default for all built-in presets. AutoInlineVlmEngine defers backend selection to initialize() via an internal _select_engine() call :
- macOS + Apple Silicon (MPS detected): Selects
MLXif the model has an explicit MLX export declared andmlx_vlmis importable. Otherwise logs a warning and falls back to Transformers. - CUDA +
prefer_vllm=True: SelectsVLLMif the model'ssupported_enginesincludes it andvllmis importable. - Default: Selects
TRANSFORMERS.
AutoInlineVlmEngineOptions exposes a prefer_vllm: bool flag (default False) to opt into the VLLM path on CUDA .
Note: The Transformers VLM engine explicitly excludes MPS from its
supported_devices([CPU, CUDA, XPU]only). If you run on Apple Silicon without an MLX model export, the engine falls back to CPU via Transformers.
Usage in Pipeline Stages#
Pipeline stages call create_vlm_engine() to get a backend instance and then drive it entirely through predict_batch(). The code/formula enrichment stage (CodeFormulaVlmModel) illustrates the typical pattern:
- Construct
VlmEngineInputobjects — one per cropped region, carrying the PIL image, a sentinel prompt (<code>or<formula>),temperature=0.0,max_new_tokens=2048, and model-defined stop strings. - Call
engine.predict_batch(batch)in groups of 5 elements. - Post-process the
VlmEngineOutput.textresults (strip special tokens, extract language tags, etc.).
The engine is fully decoupled from document data structures: it only sees PIL images and strings, making it reusable across different pipeline stages (VLM-based table structure, caption enrichment, code/formula extraction, etc.) without modification.