<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://leeroopedia.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Agent</id>
	<title>Leeroopedia - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://leeroopedia.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Agent"/>
	<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php/Special:Contributions/Agent"/>
	<updated>2026-10-10T15:16:30Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Environment:InternLM_Lmdeploy_Python_Dependencies&amp;diff=30817</id>
		<title>Environment:InternLM Lmdeploy Python Dependencies</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Environment:InternLM_Lmdeploy_Python_Dependencies&amp;diff=30817"/>
		<updated>2026-09-27T10:53:40Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Environment|title=InternLM_Lmdeploy_Python_Dependencies}}&lt;br /&gt;
{{PageInfo|type=Environment|title=InternLM_Lmdeploy_Python_Dependencies}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Knowledge Sources&lt;br /&gt;
|&lt;br /&gt;
* [https://github.com/InternLM/lmdeploy LMDeploy]&lt;br /&gt;
* [https://pypi.org/project/lmdeploy/ PyPI lmdeploy]&lt;br /&gt;
|-&lt;br /&gt;
! Domains&lt;br /&gt;
| [[domain::Infrastructure]], [[domain::Python]]&lt;br /&gt;
|-&lt;br /&gt;
! Last Updated&lt;br /&gt;
| [[last_updated::2026-02-07 15:00 GMT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3.10+ runtime with HuggingFace Transformers, accelerate, and serving framework dependencies for LMDeploy inference and quantization.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
This environment defines the Python-level software stack required to run LMDeploy. The dependencies span several categories: core ML libraries (PyTorch, Transformers), serving frameworks (FastAPI, uvicorn), quantization utilities (peft), communication (pyzmq, ray), and tokenization (sentencepiece, tiktoken). The package is installable via `pip install lmdeploy` with extras for `[all]`, `[lite]` (quantization), and `[serve]` (API server).&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
Use this environment for &#039;&#039;&#039;all Python-level LMDeploy operations&#039;&#039;&#039;: loading models, running pipelines, serving APIs, performing quantization. This is always required alongside the CUDA GPU runtime for CUDA deployments. For non-CUDA platforms (Ascend, MACA, Cambricon, ROCm), replace `requirements/runtime_cuda.txt` with the appropriate platform file.&lt;br /&gt;
&lt;br /&gt;
== System Requirements ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Category !! Requirement !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Python || 3.10, 3.11, 3.12, or 3.13 || Defined in `setup.py` classifiers&lt;br /&gt;
|-&lt;br /&gt;
| OS || Linux (primary), Windows (limited) || Triton requires Linux x86_64&lt;br /&gt;
|-&lt;br /&gt;
| pip || &amp;gt;= 21.0 || For PEP 517 builds&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencies ==&lt;br /&gt;
&lt;br /&gt;
=== Core ML Libraries ===&lt;br /&gt;
&lt;br /&gt;
* `torch` &amp;gt;= 2.0.0, &amp;lt;= 2.8.0&lt;br /&gt;
* `torchvision` &amp;gt;= 0.15.0, &amp;lt;= 0.23.0&lt;br /&gt;
* `transformers` &amp;lt; 5.0.0&lt;br /&gt;
* `accelerate` &amp;gt;= 0.29.3&lt;br /&gt;
* `peft` &amp;lt;= 0.14.0 (LoRA adapter support)&lt;br /&gt;
* `safetensors` (efficient model weight loading)&lt;br /&gt;
* `einops` (tensor operations)&lt;br /&gt;
&lt;br /&gt;
=== Serving Dependencies ===&lt;br /&gt;
&lt;br /&gt;
* `fastapi` (API framework)&lt;br /&gt;
* `uvicorn` (ASGI server)&lt;br /&gt;
* `aiohttp` (async HTTP client)&lt;br /&gt;
* `openai` (OpenAI-compatible client)&lt;br /&gt;
* `pydantic` &amp;gt; 2.0.0 (data validation)&lt;br /&gt;
&lt;br /&gt;
=== Tokenization ===&lt;br /&gt;
&lt;br /&gt;
* `sentencepiece` (SentencePiece tokenizer)&lt;br /&gt;
* `tiktoken` (BPE tokenizer)&lt;br /&gt;
&lt;br /&gt;
=== Infrastructure ===&lt;br /&gt;
&lt;br /&gt;
* `triton` &amp;gt;= 3.0.0, &amp;lt;= 3.4.0 (Linux x86_64 only; JIT kernel compilation)&lt;br /&gt;
* `ray` (distributed execution and multi-node)&lt;br /&gt;
* `pyzmq` (inter-process communication)&lt;br /&gt;
* `xgrammar` (grammar-guided generation)&lt;br /&gt;
&lt;br /&gt;
=== Optional Dependencies ===&lt;br /&gt;
&lt;br /&gt;
* `flash_attn_interface` (FlashAttention-3 for SM90+ with CUDA &amp;gt;= 12.3)&lt;br /&gt;
* `flash_mla` (Multi-head Latent Attention for SM90+)&lt;br /&gt;
* `fast_hadamard_transform` (required for DeepSeek V3.2 models)&lt;br /&gt;
&lt;br /&gt;
== Credentials ==&lt;br /&gt;
&lt;br /&gt;
No credentials required for package installation. See [[Environment:InternLM_Lmdeploy_CUDA_GPU_Runtime]] for model download credentials.&lt;br /&gt;
&lt;br /&gt;
== Quick Install ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Standard installation (CUDA)&lt;br /&gt;
pip install lmdeploy&lt;br /&gt;
&lt;br /&gt;
# With all extras&lt;br /&gt;
pip install lmdeploy[all]&lt;br /&gt;
&lt;br /&gt;
# Quantization only&lt;br /&gt;
pip install lmdeploy[lite]&lt;br /&gt;
&lt;br /&gt;
# API serving&lt;br /&gt;
pip install lmdeploy[serve]&lt;br /&gt;
&lt;br /&gt;
# For Ascend NPU&lt;br /&gt;
LMDEPLOY_TARGET_DEVICE=ascend pip install lmdeploy&lt;br /&gt;
&lt;br /&gt;
# For ROCm (AMD GPU)&lt;br /&gt;
LMDEPLOY_TARGET_DEVICE=rocm pip install lmdeploy&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Evidence ==&lt;br /&gt;
&lt;br /&gt;
Target device selection from `setup.py:13-14`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def get_target_device():&lt;br /&gt;
    return os.getenv(&#039;LMDEPLOY_TARGET_DEVICE&#039;, &#039;cuda&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Platform-specific install from `setup.py:176`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
install_requires=parse_requirements(&lt;br /&gt;
    f&#039;requirements/runtime_{get_target_device()}.txt&#039;&lt;br /&gt;
) + extra_deps,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Triton version validation from `lmdeploy/pytorch/check_env/triton.py:6-7`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
MAX_TRITON_VERSION = &#039;3.4.0&#039;&lt;br /&gt;
MIN_TRITON_VERSION = &#039;3.0.0&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Device type validation from `lmdeploy/messages.py:432`:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
assert self.device_type in [&#039;cuda&#039;, &#039;ascend&#039;, &#039;maca&#039;, &#039;camb&#039;], (&lt;br /&gt;
    f&#039;invalid device_type: {self.device_type}&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Common Errors ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Error Message !! Cause !! Solution&lt;br /&gt;
|-&lt;br /&gt;
|| `ImportError: Please install fast_hadamard_transform package.` || Missing optional dependency for DeepSeek V3.2 || `pip install fast_hadamard_transform`&lt;br /&gt;
|-&lt;br /&gt;
|| `ImportError: To use LlavaVLModel, please install llava` || Missing llava package for LLaVA VLM models || `pip install llava`&lt;br /&gt;
|-&lt;br /&gt;
|| `Could not import transformers_modules used for remote code` || Missing remote code module || Add `--trust-remote-code` flag; ensure `transformers_modules` is available&lt;br /&gt;
|-&lt;br /&gt;
|| Triton version mismatch errors || Triton outside 3.0.0-3.4.0 range || `pip install triton&amp;gt;=3.0.0,&amp;lt;=3.4.0`&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Triton:&#039;&#039;&#039; Only available on Linux x86_64. Not supported on ARM (`aarch64`) or Windows. Required for PyTorch backend CUDA kernels.&lt;br /&gt;
* &#039;&#039;&#039;peft:&#039;&#039;&#039; Pinned to &amp;lt;= 0.14.0 for LoRA adapter compatibility. Newer versions may cause issues.&lt;br /&gt;
* &#039;&#039;&#039;transformers:&#039;&#039;&#039; Must be &amp;lt; 5.0.0. The codebase uses internal APIs that may break with major version changes.&lt;br /&gt;
* &#039;&#039;&#039;Platform files:&#039;&#039;&#039; Each supported platform has its own requirements file: `runtime_cuda.txt`, `runtime_rocm.txt`, `runtime_ascend.txt`, `runtime_maca.txt`, `runtime_camb.txt`.&lt;br /&gt;
* &#039;&#039;&#039;DeepLink (dlinfer):&#039;&#039;&#039; Non-CUDA devices (Ascend, MACA, Cambricon) require the `dlinfer` framework (`dlinfer-ascend`, `dlinfer-maca`) for device abstraction.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[required_by::Implementation:InternLM_Lmdeploy_TurbomindEngineConfig]]&lt;br /&gt;
* [[required_by::Implementation:InternLM_Lmdeploy_PytorchEngineConfig]]&lt;br /&gt;
* [[required_by::Implementation:InternLM_Lmdeploy_Pipeline_Factory]]&lt;br /&gt;
* [[required_by::Implementation:InternLM_Lmdeploy_Serve_Api_Server]]&lt;br /&gt;
* [[required_by::Implementation:InternLM_Lmdeploy_Calibrate]]&lt;br /&gt;
* [[required_by::Implementation:InternLM_Lmdeploy_Load_Image]]&lt;br /&gt;
* [[required_by::Implementation:InternLM_Lmdeploy_BaseChatTemplate_Messages2prompt]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Environments]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Environments]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Environment:Huggingface_Datasets_TensorFlow_Integration&amp;diff=30816</id>
		<title>Environment:Huggingface Datasets TensorFlow Integration</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Environment:Huggingface_Datasets_TensorFlow_Integration&amp;diff=30816"/>
		<updated>2026-09-27T10:53:40Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Environment|title=Huggingface_Datasets_TensorFlow_Integration}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Knowledge Sources&lt;br /&gt;
|&lt;br /&gt;
* [https://github.com/huggingface/datasets HuggingFace Datasets]&lt;br /&gt;
|-&lt;br /&gt;
! Domains&lt;br /&gt;
| [[domain::Deep_Learning]], [[domain::Data_Processing]]&lt;br /&gt;
|-&lt;br /&gt;
! Last Updated&lt;br /&gt;
| [[last_updated::2026-02-14 19:00 GMT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
TensorFlow integration in HuggingFace Datasets enables the library to produce native &amp;lt;code&amp;gt;tf.Tensor&amp;lt;/code&amp;gt; outputs and to convert datasets into &amp;lt;code&amp;gt;tf.data.Dataset&amp;lt;/code&amp;gt; pipelines suitable for Keras training loops. Detection is performed at import time through &amp;lt;code&amp;gt;importlib.util.find_spec&amp;lt;/code&amp;gt; against a broad list of TensorFlow package variants, and the entire integration is gated behind a minimum major version requirement of TensorFlow 2.&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
At startup the library reads the &amp;lt;code&amp;gt;USE_TF&amp;lt;/code&amp;gt; environment variable (default: &amp;lt;code&amp;gt;&amp;quot;AUTO&amp;quot;&amp;lt;/code&amp;gt;). When the value is in the auto-or-true set and PyTorch has not been explicitly forced via &amp;lt;code&amp;gt;USE_TORCH&amp;lt;/code&amp;gt;, the detection routine runs &amp;lt;code&amp;gt;importlib.util.find_spec(&amp;quot;tensorflow&amp;quot;)&amp;lt;/code&amp;gt;. If the spec is found, it iterates over multiple known package names to resolve the installed version:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;tensorflow&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;tensorflow-cpu&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;tensorflow-gpu&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;tf-nightly&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;tf-nightly-cpu&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;tf-nightly-gpu&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;intel-tensorflow&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;tensorflow-rocm&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;tensorflow-macos&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If none of these packages provide valid metadata, &amp;lt;code&amp;gt;TF_AVAILABLE&amp;lt;/code&amp;gt; is set to &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt;. If a version is found but its major version is less than 2, the integration is also disabled with an informational log message.&lt;br /&gt;
&lt;br /&gt;
When TensorFlow is available, the &amp;lt;code&amp;gt;TFFormatter&amp;lt;/code&amp;gt; class is registered under the format type &amp;lt;code&amp;gt;&amp;quot;tensorflow&amp;quot;&amp;lt;/code&amp;gt; with aliases &amp;lt;code&amp;gt;&amp;quot;tf&amp;quot;&amp;lt;/code&amp;gt;. When TensorFlow is unavailable, a placeholder is registered that raises &amp;lt;code&amp;gt;ValueError(&amp;quot;Tensorflow needs to be installed to be able to return Tensorflow tensors.&amp;quot;)&amp;lt;/code&amp;gt; on use.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;to_tf_dataset()&amp;lt;/code&amp;gt; method on &amp;lt;code&amp;gt;Dataset&amp;lt;/code&amp;gt; converts a HuggingFace dataset into a &amp;lt;code&amp;gt;tf.data.Dataset&amp;lt;/code&amp;gt; that can be passed directly to &amp;lt;code&amp;gt;model.fit()&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;model.predict()&amp;lt;/code&amp;gt;. It supports batching, shuffling, custom collation, label column separation, prefetching, and multi-worker loading. A runtime check detects TPU strategies and emits a warning that the generator-based loading approach is not compatible with remote TPU connections.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
Set the dataset format to TensorFlow tensors:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from datasets import load_dataset&lt;br /&gt;
&lt;br /&gt;
dataset = load_dataset(&amp;quot;glue&amp;quot;, &amp;quot;mrpc&amp;quot;, split=&amp;quot;train&amp;quot;)&lt;br /&gt;
dataset.set_format(type=&amp;quot;tensorflow&amp;quot;, columns=[&amp;quot;input_ids&amp;quot;, &amp;quot;attention_mask&amp;quot;, &amp;quot;label&amp;quot;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Convert directly to a &amp;lt;code&amp;gt;tf.data.Dataset&amp;lt;/code&amp;gt; for Keras:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tf_dataset = dataset.to_tf_dataset(&lt;br /&gt;
    columns=[&amp;quot;input_ids&amp;quot;, &amp;quot;attention_mask&amp;quot;],&lt;br /&gt;
    label_cols=[&amp;quot;label&amp;quot;],&lt;br /&gt;
    batch_size=16,&lt;br /&gt;
    shuffle=True,&lt;br /&gt;
)&lt;br /&gt;
model.fit(tf_dataset, epochs=3)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== System Requirements ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Python:&#039;&#039;&#039; 3.9+ (TensorFlow constraint). For Python &amp;lt; 3.10, TensorFlow &amp;gt;= 2.6.0 is required. For Python &amp;gt;= 3.10, TensorFlow &amp;gt;= 2.16.0 is required.&lt;br /&gt;
* &#039;&#039;&#039;Operating System:&#039;&#039;&#039; Linux or macOS. TensorFlow tests in this repository explicitly exclude Windows (&amp;lt;code&amp;gt;sys_platform != &#039;win32&#039;&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &#039;&#039;&#039;Python upper bound:&#039;&#039;&#039; Python &amp;gt;= 3.14 is excluded from TensorFlow test dependencies.&lt;br /&gt;
* &#039;&#039;&#039;NumPy:&#039;&#039;&#039; TensorFlow is listed in &amp;lt;code&amp;gt;NUMPY2_INCOMPATIBLE_LIBRARIES&amp;lt;/code&amp;gt;, meaning it is excluded from NumPy 2 test runs.&lt;br /&gt;
&lt;br /&gt;
== Dependencies ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dependency !! Version Constraint !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tensorflow&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;gt;=2.6.0&amp;lt;/code&amp;gt; || Core extra; also accepts &amp;lt;code&amp;gt;tensorflow-cpu&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;tensorflow-gpu&amp;lt;/code&amp;gt;, and other variants&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;protobuf&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;lt;4.0.0&amp;lt;/code&amp;gt; || Required for compatibility with TensorFlow &amp;lt; 2.12 in test environments&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Install via the extras:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pip install datasets[tensorflow]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or for the GPU variant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pip install datasets[tensorflow_gpu]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credentials ==&lt;br /&gt;
&lt;br /&gt;
No credentials are required for TensorFlow integration itself. Standard HuggingFace Hub authentication (token-based) is used when downloading datasets from the Hub but is independent of the TensorFlow environment.&lt;br /&gt;
&lt;br /&gt;
== Quick Install ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pip install datasets[tensorflow]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To verify the integration is active:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from datasets import config&lt;br /&gt;
print(f&amp;quot;TF available: {config.TF_AVAILABLE}&amp;quot;)&lt;br /&gt;
print(f&amp;quot;TF version:   {config.TF_VERSION}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Evidence ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Environment variable and detection logic&#039;&#039;&#039; (from &amp;lt;code&amp;gt;src/datasets/config.py&amp;lt;/code&amp;gt; lines 42, 81-114):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
USE_TF = os.environ.get(&amp;quot;USE_TF&amp;quot;, &amp;quot;AUTO&amp;quot;).upper()&lt;br /&gt;
&lt;br /&gt;
TF_VERSION = &amp;quot;N/A&amp;quot;&lt;br /&gt;
TF_AVAILABLE = False&lt;br /&gt;
&lt;br /&gt;
if USE_TF in ENV_VARS_TRUE_AND_AUTO_VALUES and USE_TORCH not in ENV_VARS_TRUE_VALUES:&lt;br /&gt;
    TF_AVAILABLE = importlib.util.find_spec(&amp;quot;tensorflow&amp;quot;) is not None&lt;br /&gt;
    if TF_AVAILABLE:&lt;br /&gt;
        for package in [&lt;br /&gt;
            &amp;quot;tensorflow&amp;quot;,&lt;br /&gt;
            &amp;quot;tensorflow-cpu&amp;quot;,&lt;br /&gt;
            &amp;quot;tensorflow-gpu&amp;quot;,&lt;br /&gt;
            &amp;quot;tf-nightly&amp;quot;,&lt;br /&gt;
            &amp;quot;tf-nightly-cpu&amp;quot;,&lt;br /&gt;
            &amp;quot;tf-nightly-gpu&amp;quot;,&lt;br /&gt;
            &amp;quot;intel-tensorflow&amp;quot;,&lt;br /&gt;
            &amp;quot;tensorflow-rocm&amp;quot;,&lt;br /&gt;
            &amp;quot;tensorflow-macos&amp;quot;,&lt;br /&gt;
        ]:&lt;br /&gt;
            try:&lt;br /&gt;
                TF_VERSION = version.parse(importlib.metadata.version(package))&lt;br /&gt;
            except importlib.metadata.PackageNotFoundError:&lt;br /&gt;
                continue&lt;br /&gt;
            else:&lt;br /&gt;
                break&lt;br /&gt;
        else:&lt;br /&gt;
            TF_AVAILABLE = False&lt;br /&gt;
    if TF_AVAILABLE:&lt;br /&gt;
        if TF_VERSION.major &amp;lt; 2:&lt;br /&gt;
            logger.info(f&amp;quot;TensorFlow found but with version {TF_VERSION}. `datasets` requires version 2 minimum.&amp;quot;)&lt;br /&gt;
            TF_AVAILABLE = False&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Formatter registration&#039;&#039;&#039; (from &amp;lt;code&amp;gt;src/datasets/formatting/__init__.py&amp;lt;/code&amp;gt; lines 98-104):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if config.TF_AVAILABLE:&lt;br /&gt;
    from .tf_formatter import TFFormatter&lt;br /&gt;
    _register_formatter(TFFormatter, &amp;quot;tensorflow&amp;quot;, aliases=[&amp;quot;tf&amp;quot;])&lt;br /&gt;
else:&lt;br /&gt;
    _tf_error = ValueError(&amp;quot;Tensorflow needs to be installed to be able to return Tensorflow tensors.&amp;quot;)&lt;br /&gt;
    _register_unavailable_formatter(_tf_error, &amp;quot;tensorflow&amp;quot;, aliases=[&amp;quot;tf&amp;quot;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TPU strategy warning&#039;&#039;&#039; (from &amp;lt;code&amp;gt;src/datasets/arrow_dataset.py&amp;lt;/code&amp;gt; lines 415-421):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if isinstance(tf.distribute.get_strategy(), tf.distribute.TPUStrategy):&lt;br /&gt;
    logger.warning(&lt;br /&gt;
        &amp;quot;Note that to_tf_dataset() loads the data with a generator rather than a full tf.data &amp;quot;&lt;br /&gt;
        &amp;quot;pipeline and is not compatible with remote TPU connections. If you encounter errors, please &amp;quot;&lt;br /&gt;
        &amp;quot;try using a TPU VM or, if your data can fit in memory, loading it into memory as a dict of &amp;quot;&lt;br /&gt;
        &amp;quot;Tensors instead of streaming with to_tf_dataset().&amp;quot;&lt;br /&gt;
    )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Extras in setup.py&#039;&#039;&#039; (from &amp;lt;code&amp;gt;setup.py&amp;lt;/code&amp;gt; lines 217-220):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;tensorflow&amp;quot;: [&lt;br /&gt;
    &amp;quot;tensorflow&amp;gt;=2.6.0&amp;quot;,&lt;br /&gt;
],&lt;br /&gt;
&amp;quot;tensorflow_gpu&amp;quot;: [&amp;quot;tensorflow&amp;gt;=2.6.0&amp;quot;],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Common Errors ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Error !! Cause !! Resolution&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ValueError: Tensorflow needs to be installed to be able to return Tensorflow tensors.&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;set_format(type=&amp;quot;tensorflow&amp;quot;)&amp;lt;/code&amp;gt; called when TensorFlow is not installed or detected || Install TensorFlow: &amp;lt;code&amp;gt;pip install tensorflow&amp;gt;=2.6.0&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ImportError: Called a Tensorflow-specific function but Tensorflow is not installed.&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;to_tf_dataset()&amp;lt;/code&amp;gt; called when &amp;lt;code&amp;gt;config.TF_AVAILABLE&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt; || Install TensorFlow or check that &amp;lt;code&amp;gt;USE_TF&amp;lt;/code&amp;gt; is not set to a false value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TensorFlow found but with version {X}. datasets requires version 2 minimum.&amp;lt;/code&amp;gt; || TensorFlow 1.x is installed || Upgrade to TensorFlow &amp;gt;= 2.6.0&lt;br /&gt;
|-&lt;br /&gt;
| TPU warning: &amp;quot;not compatible with remote TPU connections&amp;quot; || &amp;lt;code&amp;gt;to_tf_dataset()&amp;lt;/code&amp;gt; used under a &amp;lt;code&amp;gt;TPUStrategy&amp;lt;/code&amp;gt; || Use a TPU VM instead of a remote TPU connection, or load data into memory as a dict of tensors&lt;br /&gt;
|-&lt;br /&gt;
| TF disabled because &amp;lt;code&amp;gt;USE_TORCH&amp;lt;/code&amp;gt; is set to a true value || Mutual exclusion logic in &amp;lt;code&amp;gt;config.py&amp;lt;/code&amp;gt;: when &amp;lt;code&amp;gt;USE_TORCH&amp;lt;/code&amp;gt; is explicitly true, TF detection is skipped || Set &amp;lt;code&amp;gt;USE_TF=1&amp;lt;/code&amp;gt; explicitly to override, or unset &amp;lt;code&amp;gt;USE_TORCH&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Mutual exclusion with PyTorch:&#039;&#039;&#039; When &amp;lt;code&amp;gt;USE_TORCH&amp;lt;/code&amp;gt; is explicitly set to a true value, TensorFlow detection is skipped entirely. Conversely, when &amp;lt;code&amp;gt;USE_TF&amp;lt;/code&amp;gt; is explicitly true, PyTorch is disabled. In &amp;lt;code&amp;gt;AUTO&amp;lt;/code&amp;gt; mode both can coexist.&lt;br /&gt;
* &#039;&#039;&#039;Windows:&#039;&#039;&#039; TensorFlow test dependencies carry the marker &amp;lt;code&amp;gt;sys_platform != &#039;win32&#039;&amp;lt;/code&amp;gt;, indicating that TensorFlow integration is not tested or officially supported on Windows within this project.&lt;br /&gt;
* &#039;&#039;&#039;NumPy 2:&#039;&#039;&#039; TensorFlow is listed in &amp;lt;code&amp;gt;NUMPY2_INCOMPATIBLE_LIBRARIES&amp;lt;/code&amp;gt; and is excluded from the &amp;lt;code&amp;gt;tests_numpy2&amp;lt;/code&amp;gt; extras. Environments using NumPy &amp;gt;= 2.0 should not expect TensorFlow compatibility.&lt;br /&gt;
* &#039;&#039;&#039;Python 3.14:&#039;&#039;&#039; TensorFlow test dependencies are restricted to &amp;lt;code&amp;gt;python_version &amp;lt; &#039;3.14&#039;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;&#039;protobuf:&#039;&#039;&#039; Test environments pin &amp;lt;code&amp;gt;protobuf&amp;lt;4.0.0&amp;lt;/code&amp;gt; because protobuf 4.x breaks compatibility with TensorFlow versions prior to 2.12.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[Implementation:Huggingface_Datasets_TFFormatter]] -- The &amp;lt;code&amp;gt;TFFormatter&amp;lt;/code&amp;gt; class that converts Arrow tables to TensorFlow tensors&lt;br /&gt;
* [[Implementation:Huggingface_Datasets_Dataset_To_Tf_Dataset]] -- The &amp;lt;code&amp;gt;to_tf_dataset()&amp;lt;/code&amp;gt; method for creating &amp;lt;code&amp;gt;tf.data.Dataset&amp;lt;/code&amp;gt; pipelines&lt;br /&gt;
* [[Implementation:Huggingface_Datasets_Dataset_Set_Format]] -- The &amp;lt;code&amp;gt;set_format()&amp;lt;/code&amp;gt; method used to select the TensorFlow output format&lt;br /&gt;
&lt;br /&gt;
[[Category:Environments]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Environment:Huggingface_Datasets_SQL_Dependencies&amp;diff=30815</id>
		<title>Environment:Huggingface Datasets SQL Dependencies</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Environment:Huggingface_Datasets_SQL_Dependencies&amp;diff=30815"/>
		<updated>2026-09-27T10:53:40Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Environment|title=Huggingface_Datasets_SQL_Dependencies}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Knowledge Sources&lt;br /&gt;
|&lt;br /&gt;
* [https://github.com/huggingface/datasets HuggingFace Datasets]&lt;br /&gt;
|-&lt;br /&gt;
! Domains&lt;br /&gt;
| [[domain::Database]], [[domain::SQL]], [[domain::Data Import]], [[domain::Data Export]]&lt;br /&gt;
|-&lt;br /&gt;
! Last Updated&lt;br /&gt;
| [[last_updated::2026-02-14 19:00 GMT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;SQL Dependencies&#039;&#039;&#039; environment defines the packages required to enable reading from and writing to SQL databases within the HuggingFace Datasets library. SQL support relies on &#039;&#039;&#039;SQLAlchemy&#039;&#039;&#039; as the database abstraction layer, with Python&#039;s built-in &#039;&#039;&#039;sqlite3&#039;&#039;&#039; module available as a lightweight alternative for SQLite databases. SQLAlchemy is &#039;&#039;&#039;not&#039;&#039;&#039; included in the base datasets installation and is currently listed as a test dependency.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
SQL features enable the ability to:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Read&#039;&#039;&#039; datasets from SQL databases using &amp;lt;code&amp;gt;SqlDatasetReader&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;io/sql.py&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Write&#039;&#039;&#039; datasets to SQL databases using the dataset-to-SQL export functionality&lt;br /&gt;
* Connect to any database supported by SQLAlchemy (PostgreSQL, MySQL, SQLite, Oracle, SQL Server, etc.)&lt;br /&gt;
&lt;br /&gt;
The library checks for the availability of SQLAlchemy at runtime using &amp;lt;code&amp;gt;importlib.util.find_spec(&amp;quot;sqlalchemy&amp;quot;)&amp;lt;/code&amp;gt; and stores the result in the &amp;lt;code&amp;gt;SQLALCHEMY_AVAILABLE&amp;lt;/code&amp;gt; flag defined in &amp;lt;code&amp;gt;config.py&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== System Requirements ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Python&#039;&#039;&#039;: Compatible with the Python versions supported by HuggingFace Datasets&lt;br /&gt;
* &#039;&#039;&#039;Operating System&#039;&#039;&#039;: Linux, macOS, or Windows&lt;br /&gt;
* &#039;&#039;&#039;Database&#039;&#039;&#039;: A running database instance accessible via a SQLAlchemy connection string, or a local SQLite file&lt;br /&gt;
* &#039;&#039;&#039;Database Drivers&#039;&#039;&#039;: Depending on the target database, additional driver packages may be needed (e.g., &amp;lt;code&amp;gt;psycopg2&amp;lt;/code&amp;gt; for PostgreSQL, &amp;lt;code&amp;gt;pymysql&amp;lt;/code&amp;gt; for MySQL)&lt;br /&gt;
&lt;br /&gt;
== Dependencies ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Package !! Minimum Version !! Purpose !! Required By&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;sqlalchemy&#039;&#039;&#039; || &#039;&#039;(see setup.py)&#039;&#039; || Database abstraction, connection management, SQL query execution || &amp;lt;code&amp;gt;io/sql.py&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;sqlite3&#039;&#039;&#039; || &#039;&#039;(stdlib)&#039;&#039; || Lightweight SQL database support (built into Python) || &amp;lt;code&amp;gt;io/sql.py&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
As defined in &amp;lt;code&amp;gt;setup.py&amp;lt;/code&amp;gt;, &#039;&#039;&#039;sqlalchemy&#039;&#039;&#039; is listed in &amp;lt;code&amp;gt;TESTS_REQUIRE&amp;lt;/code&amp;gt;, indicating it is used in the test suite and is an optional runtime dependency.&lt;br /&gt;
&lt;br /&gt;
Depending on the target database, additional driver packages may also be required:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Database !! Driver Package !! Install Command&lt;br /&gt;
|-&lt;br /&gt;
| PostgreSQL || &amp;lt;code&amp;gt;psycopg2&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;psycopg2-binary&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;pip install psycopg2-binary&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| MySQL || &amp;lt;code&amp;gt;pymysql&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;mysqlclient&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;pip install pymysql&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| SQLite || &#039;&#039;(none, uses stdlib sqlite3)&#039;&#039; || &#039;&#039;No additional install needed&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| SQL Server || &amp;lt;code&amp;gt;pyodbc&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;pip install pyodbc&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Credentials ==&lt;br /&gt;
&lt;br /&gt;
Database credentials are passed via SQLAlchemy connection strings. These typically include:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Username&#039;&#039;&#039; and &#039;&#039;&#039;password&#039;&#039;&#039; for the database&lt;br /&gt;
* &#039;&#039;&#039;Host&#039;&#039;&#039; and &#039;&#039;&#039;port&#039;&#039;&#039; of the database server&lt;br /&gt;
* &#039;&#039;&#039;Database name&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example connection string format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dialect+driver://username:password@host:port/database&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Security note:&#039;&#039;&#039; Connection strings containing credentials should &#039;&#039;&#039;not&#039;&#039;&#039; be committed to version control. Use environment variables or secrets management tools to handle database credentials.&lt;br /&gt;
&lt;br /&gt;
== Quick Install ==&lt;br /&gt;
&lt;br /&gt;
Install SQLAlchemy with pip:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pip install sqlalchemy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a specific database backend, install the appropriate driver alongside SQLAlchemy:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# PostgreSQL&lt;br /&gt;
pip install sqlalchemy psycopg2-binary&lt;br /&gt;
&lt;br /&gt;
# MySQL&lt;br /&gt;
pip install sqlalchemy pymysql&lt;br /&gt;
&lt;br /&gt;
# SQLite (no additional driver needed)&lt;br /&gt;
pip install sqlalchemy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Evidence ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Runtime availability check&#039;&#039;&#039; in &amp;lt;code&amp;gt;config.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SQLALCHEMY_AVAILABLE = importlib.util.find_spec(&amp;quot;sqlalchemy&amp;quot;) is not None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TYPE_CHECKING imports&#039;&#039;&#039; in &amp;lt;code&amp;gt;io/sql.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from typing import TYPE_CHECKING&lt;br /&gt;
&lt;br /&gt;
if TYPE_CHECKING:&lt;br /&gt;
    import sqlalchemy&lt;br /&gt;
    import sqlite3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This pattern indicates that &amp;lt;code&amp;gt;sqlalchemy&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;sqlite3&amp;lt;/code&amp;gt; are used for type annotations and are imported at runtime only when needed, allowing the module to be loaded without these dependencies installed.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test dependency&#039;&#039;&#039; in &amp;lt;code&amp;gt;setup.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
TESTS_REQUIRE = [&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;quot;sqlalchemy&amp;quot;,&lt;br /&gt;
    ...&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Common Errors ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Error Message !! Cause !! Resolution&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ModuleNotFoundError: No module named &#039;sqlalchemy&#039;&amp;lt;/code&amp;gt; || SQLAlchemy is not installed || Run &amp;lt;code&amp;gt;pip install sqlalchemy&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) unable to open database file&amp;lt;/code&amp;gt; || SQLite database file path is incorrect or inaccessible || Verify the database file path and permissions&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sqlalchemy.exc.NoSuchModuleError: Can&#039;t load plugin: sqlalchemy.dialects:postgresql&amp;lt;/code&amp;gt; || Database driver for the specified dialect is not installed || Install the appropriate driver (e.g., &amp;lt;code&amp;gt;pip install psycopg2-binary&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sqlalchemy.exc.OperationalError: could not connect to server&amp;lt;/code&amp;gt; || Database server is not running or connection parameters are incorrect || Verify the database server is running and the connection string is correct&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;SQLAlchemy&#039;&#039;&#039; is listed in &amp;lt;code&amp;gt;TESTS_REQUIRE&amp;lt;/code&amp;gt; rather than as a core or optional extra dependency, which means it is primarily validated through the test suite. Users must install it manually for SQL functionality.&lt;br /&gt;
* The &#039;&#039;&#039;sqlite3&#039;&#039;&#039; module is part of Python&#039;s standard library and does not require separate installation. It is always available in standard CPython distributions.&lt;br /&gt;
* The &amp;lt;code&amp;gt;TYPE_CHECKING&amp;lt;/code&amp;gt; import pattern in &amp;lt;code&amp;gt;io/sql.py&amp;lt;/code&amp;gt; means that &amp;lt;code&amp;gt;sqlalchemy&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;sqlite3&amp;lt;/code&amp;gt; are lazily imported, so the SQL module can be loaded even when these packages are not installed.&lt;br /&gt;
* The &amp;lt;code&amp;gt;SQLALCHEMY_AVAILABLE&amp;lt;/code&amp;gt; flag in &amp;lt;code&amp;gt;config.py&amp;lt;/code&amp;gt; allows the library to check for SQLAlchemy availability before attempting SQL operations, enabling graceful error messages.&lt;br /&gt;
* SQLAlchemy 1.x and 2.x have significant API differences; consult the datasets library documentation for the supported version range.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[Implementation:Huggingface_Datasets_SqlDatasetReader]] — SQL dataset reader implementation&lt;br /&gt;
* [[Implementation:Huggingface_Datasets_Dataset_To_Sql]] — Dataset to SQL export functionality&lt;br /&gt;
&lt;br /&gt;
[[Category:Environments]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Environment:Huggingface_Datasets_JAX_Integration&amp;diff=30814</id>
		<title>Environment:Huggingface Datasets JAX Integration</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Environment:Huggingface_Datasets_JAX_Integration&amp;diff=30814"/>
		<updated>2026-09-27T10:53:40Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Environment|title=Huggingface_Datasets_JAX_Integration}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Knowledge Sources&lt;br /&gt;
|&lt;br /&gt;
* [https://github.com/huggingface/datasets HuggingFace Datasets]&lt;br /&gt;
|-&lt;br /&gt;
! Domains&lt;br /&gt;
| [[domain::Deep_Learning]], [[domain::Data_Processing]]&lt;br /&gt;
|-&lt;br /&gt;
! Last Updated&lt;br /&gt;
| [[last_updated::2026-02-14 19:00 GMT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
JAX integration in HuggingFace Datasets enables the library to produce native &amp;lt;code&amp;gt;jax.Array&amp;lt;/code&amp;gt; outputs with device placement and dtype selection that respects JAX&#039;s 64-bit precision configuration. Unlike the TensorFlow and PyTorch integrations, JAX requires two separate packages (&amp;lt;code&amp;gt;jax&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;jaxlib&amp;lt;/code&amp;gt;) to both be importable, and the integration is not supported on Windows.&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
At startup the library reads the &amp;lt;code&amp;gt;USE_JAX&amp;lt;/code&amp;gt; environment variable (default: &amp;lt;code&amp;gt;&amp;quot;AUTO&amp;quot;&amp;lt;/code&amp;gt;). When the value is in the auto-or-true set, the detection routine checks that both &amp;lt;code&amp;gt;importlib.util.find_spec(&amp;quot;jax&amp;quot;)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;importlib.util.find_spec(&amp;quot;jaxlib&amp;quot;)&amp;lt;/code&amp;gt; return non-None values. Both packages must be present for &amp;lt;code&amp;gt;JAX_AVAILABLE&amp;lt;/code&amp;gt; to be set to &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt;. The JAX version is then resolved from the &amp;lt;code&amp;gt;jax&amp;lt;/code&amp;gt; package metadata.&lt;br /&gt;
&lt;br /&gt;
When JAX is available, the &amp;lt;code&amp;gt;JaxFormatter&amp;lt;/code&amp;gt; class is registered under the format type &amp;lt;code&amp;gt;&amp;quot;jax&amp;quot;&amp;lt;/code&amp;gt; with no aliases. When JAX is unavailable, a placeholder is registered that raises &amp;lt;code&amp;gt;ValueError(&amp;quot;JAX needs to be installed to be able to return JAX arrays.&amp;quot;)&amp;lt;/code&amp;gt; on use.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;JaxFormatter&amp;lt;/code&amp;gt; handles several JAX-specific concerns:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Device validation:&#039;&#039;&#039; The constructor checks whether the provided &amp;lt;code&amp;gt;device&amp;lt;/code&amp;gt; argument is a &amp;lt;code&amp;gt;jaxlib.xla_client.Device&amp;lt;/code&amp;gt; object. If so, it raises a &amp;lt;code&amp;gt;ValueError&amp;lt;/code&amp;gt; because &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt; objects are not serializable with either &amp;lt;code&amp;gt;pickle&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;dill&amp;lt;/code&amp;gt;. Users must pass the device as a string identifier instead. A global &amp;lt;code&amp;gt;DEVICE_MAPPING&amp;lt;/code&amp;gt; dictionary maps string identifiers to actual device objects.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Precision-aware dtype selection:&#039;&#039;&#039; When tensorizing integer values, the formatter checks &amp;lt;code&amp;gt;jax.config.jax_enable_x64&amp;lt;/code&amp;gt;. If 64-bit mode is enabled, integers default to &amp;lt;code&amp;gt;jnp.int64&amp;lt;/code&amp;gt;; otherwise they default to &amp;lt;code&amp;gt;jnp.int32&amp;lt;/code&amp;gt;. Floating-point values default to &amp;lt;code&amp;gt;jnp.float32&amp;lt;/code&amp;gt; regardless of the x64 setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Device placement:&#039;&#039;&#039; All array creation is wrapped in a &amp;lt;code&amp;gt;jax.default_device(DEVICE_MAPPING[self.device])&amp;lt;/code&amp;gt; context manager, ensuring tensors land on the intended device.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
Set the dataset format to JAX arrays:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from datasets import load_dataset&lt;br /&gt;
&lt;br /&gt;
dataset = load_dataset(&amp;quot;glue&amp;quot;, &amp;quot;mrpc&amp;quot;, split=&amp;quot;train&amp;quot;)&lt;br /&gt;
dataset.set_format(type=&amp;quot;jax&amp;quot;, columns=[&amp;quot;input_ids&amp;quot;, &amp;quot;attention_mask&amp;quot;, &amp;quot;label&amp;quot;])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Specify a target device by string identifier:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dataset.set_format(type=&amp;quot;jax&amp;quot;, columns=[&amp;quot;input_ids&amp;quot;], device=&amp;quot;cpu:0&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Access formatted samples (returns &amp;lt;code&amp;gt;jax.Array&amp;lt;/code&amp;gt; objects):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sample = dataset[0]&lt;br /&gt;
print(type(sample[&amp;quot;input_ids&amp;quot;]))  # &amp;lt;class &#039;jaxlib.xla_extension.ArrayImpl&#039;&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== System Requirements ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Python:&#039;&#039;&#039; 3.9+&lt;br /&gt;
* &#039;&#039;&#039;Operating System:&#039;&#039;&#039; Linux or macOS only. JAX dependencies carry the marker &amp;lt;code&amp;gt;sys_platform != &#039;win32&#039;&amp;lt;/code&amp;gt; in both the extras and test requirements. JAX is not supported on Windows within this project.&lt;br /&gt;
&lt;br /&gt;
== Dependencies ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dependency !! Version Constraint !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;jax&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;gt;=0.3.14&amp;lt;/code&amp;gt; || Core JAX library; must be importable for integration to activate&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;jaxlib&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;gt;=0.3.14&amp;lt;/code&amp;gt; || XLA compilation backend; must also be importable alongside &amp;lt;code&amp;gt;jax&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Install via the extras:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pip install datasets[jax]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credentials ==&lt;br /&gt;
&lt;br /&gt;
No credentials are required for JAX integration itself. Standard HuggingFace Hub authentication (token-based) is used when downloading datasets from the Hub but is independent of the JAX environment.&lt;br /&gt;
&lt;br /&gt;
== Quick Install ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pip install datasets[jax]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To verify the integration is active:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from datasets import config&lt;br /&gt;
print(f&amp;quot;JAX available: {config.JAX_AVAILABLE}&amp;quot;)&lt;br /&gt;
print(f&amp;quot;JAX version:   {config.JAX_VERSION}&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Evidence ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Environment variable and detection logic&#039;&#039;&#039; (from &amp;lt;code&amp;gt;src/datasets/config.py&amp;lt;/code&amp;gt; lines 44, 117-129):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
USE_JAX = os.environ.get(&amp;quot;USE_JAX&amp;quot;, &amp;quot;AUTO&amp;quot;).upper()&lt;br /&gt;
&lt;br /&gt;
JAX_VERSION = &amp;quot;N/A&amp;quot;&lt;br /&gt;
JAX_AVAILABLE = False&lt;br /&gt;
&lt;br /&gt;
if USE_JAX in ENV_VARS_TRUE_AND_AUTO_VALUES:&lt;br /&gt;
    JAX_AVAILABLE = importlib.util.find_spec(&amp;quot;jax&amp;quot;) is not None and importlib.util.find_spec(&amp;quot;jaxlib&amp;quot;) is not None&lt;br /&gt;
    if JAX_AVAILABLE:&lt;br /&gt;
        try:&lt;br /&gt;
            JAX_VERSION = version.parse(importlib.metadata.version(&amp;quot;jax&amp;quot;))&lt;br /&gt;
            logger.info(f&amp;quot;JAX version {JAX_VERSION} available.&amp;quot;)&lt;br /&gt;
        except importlib.metadata.PackageNotFoundError:&lt;br /&gt;
            pass&lt;br /&gt;
else:&lt;br /&gt;
    logger.info(&amp;quot;Disabling JAX because USE_JAX is set to False&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Formatter registration&#039;&#039;&#039; (from &amp;lt;code&amp;gt;src/datasets/formatting/__init__.py&amp;lt;/code&amp;gt; lines 106-112):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if config.JAX_AVAILABLE:&lt;br /&gt;
    from .jax_formatter import JaxFormatter&lt;br /&gt;
    _register_formatter(JaxFormatter, &amp;quot;jax&amp;quot;, aliases=[])&lt;br /&gt;
else:&lt;br /&gt;
    _jax_error = ValueError(&amp;quot;JAX needs to be installed to be able to return JAX arrays.&amp;quot;)&lt;br /&gt;
    _register_unavailable_formatter(_jax_error, &amp;quot;jax&amp;quot;, aliases=[])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Device validation in JaxFormatter constructor&#039;&#039;&#039; (from &amp;lt;code&amp;gt;src/datasets/formatting/jax_formatter.py&amp;lt;/code&amp;gt; lines 39-64):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
class JaxFormatter(TensorFormatter[Mapping, &amp;quot;jax.Array&amp;quot;, Mapping]):&lt;br /&gt;
    def __init__(self, features=None, device=None, token_per_repo_id=None, **jnp_array_kwargs):&lt;br /&gt;
        super().__init__(features=features, token_per_repo_id=token_per_repo_id)&lt;br /&gt;
        import jax&lt;br /&gt;
        from jaxlib.xla_client import Device&lt;br /&gt;
&lt;br /&gt;
        if isinstance(device, Device):&lt;br /&gt;
            raise ValueError(&lt;br /&gt;
                f&amp;quot;Expected {device} to be a `str` not {type(device)}, as `jaxlib.xla_extension.Device` &amp;quot;&lt;br /&gt;
                &amp;quot;is not serializable neither with `pickle` nor with `dill`. Instead you can surround &amp;quot;&lt;br /&gt;
                &amp;quot;the device with `str()` to get its string identifier that will be internally mapped &amp;quot;&lt;br /&gt;
                &amp;quot;to the actual `jaxlib.xla_extension.Device`.&amp;quot;&lt;br /&gt;
            )&lt;br /&gt;
        self.device = device if isinstance(device, str) else str(jax.devices()[0])&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Precision-aware dtype selection&#039;&#039;&#039; (from &amp;lt;code&amp;gt;src/datasets/formatting/jax_formatter.py&amp;lt;/code&amp;gt; lines 92-102):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
default_dtype = {}&lt;br /&gt;
&lt;br /&gt;
if isinstance(value, (np.number, np.ndarray)) and np.issubdtype(value.dtype, np.integer):&lt;br /&gt;
    if jax.config.jax_enable_x64:&lt;br /&gt;
        default_dtype = {&amp;quot;dtype&amp;quot;: jnp.int64}&lt;br /&gt;
    else:&lt;br /&gt;
        default_dtype = {&amp;quot;dtype&amp;quot;: jnp.int32}&lt;br /&gt;
elif isinstance(value, (np.number, np.ndarray)) and np.issubdtype(value.dtype, np.floating):&lt;br /&gt;
    default_dtype = {&amp;quot;dtype&amp;quot;: jnp.float32}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Device-aware tensor creation&#039;&#039;&#039; (from &amp;lt;code&amp;gt;src/datasets/formatting/jax_formatter.py&amp;lt;/code&amp;gt; lines 126-129):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
with jax.default_device(DEVICE_MAPPING[self.device]):&lt;br /&gt;
    return jnp.array(value, **{**default_dtype, **self.jnp_array_kwargs})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Extras in setup.py&#039;&#039;&#039; (from &amp;lt;code&amp;gt;setup.py&amp;lt;/code&amp;gt; line 222):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;jax&amp;quot;: [&amp;quot;jax&amp;gt;=0.3.14&amp;quot;, &amp;quot;jaxlib&amp;gt;=0.3.14&amp;quot;],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Windows exclusion in test dependencies&#039;&#039;&#039; (from &amp;lt;code&amp;gt;setup.py&amp;lt;/code&amp;gt; lines 171-172):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;jax&amp;gt;=0.3.14; sys_platform != &#039;win32&#039;&amp;quot;,&lt;br /&gt;
&amp;quot;jaxlib&amp;gt;=0.3.14; sys_platform != &#039;win32&#039;&amp;quot;,&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Common Errors ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Error !! Cause !! Resolution&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ValueError: JAX needs to be installed to be able to return JAX arrays.&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;set_format(type=&amp;quot;jax&amp;quot;)&amp;lt;/code&amp;gt; called when JAX or jaxlib is not installed || Install both packages: &amp;lt;code&amp;gt;pip install jax&amp;gt;=0.3.14 jaxlib&amp;gt;=0.3.14&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ValueError: Expected {device} to be a `str` not {type}, as `jaxlib.xla_extension.Device` is not serializable...&amp;lt;/code&amp;gt; || A &amp;lt;code&amp;gt;jaxlib.xla_extension.Device&amp;lt;/code&amp;gt; object was passed directly as the &amp;lt;code&amp;gt;device&amp;lt;/code&amp;gt; parameter || Wrap the device with &amp;lt;code&amp;gt;str()&amp;lt;/code&amp;gt; to pass its string identifier instead of the object&lt;br /&gt;
|-&lt;br /&gt;
| Device not listed among available devices (warning, falls back to default) || The string device identifier does not match any device returned by &amp;lt;code&amp;gt;jax.devices()&amp;lt;/code&amp;gt; || Use a valid device string such as &amp;lt;code&amp;gt;&amp;quot;cpu:0&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;gpu:0&amp;quot;&amp;lt;/code&amp;gt; matching the output of &amp;lt;code&amp;gt;jax.devices()&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Disabling JAX because USE_JAX is set to False&amp;lt;/code&amp;gt; (info log) || &amp;lt;code&amp;gt;USE_JAX&amp;lt;/code&amp;gt; environment variable is set to a false value (&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OFF&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;FALSE&amp;lt;/code&amp;gt;) || Unset &amp;lt;code&amp;gt;USE_JAX&amp;lt;/code&amp;gt; or set it to &amp;lt;code&amp;gt;AUTO&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Integer precision mismatch (int32 vs int64) || JAX defaults to 32-bit integers unless &amp;lt;code&amp;gt;jax_enable_x64&amp;lt;/code&amp;gt; is enabled || Set &amp;lt;code&amp;gt;jax.config.update(&amp;quot;jax_enable_x64&amp;quot;, True)&amp;lt;/code&amp;gt; before loading data if 64-bit integers are needed&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Windows:&#039;&#039;&#039; JAX is explicitly excluded on Windows. Both the extras and test dependencies carry the &amp;lt;code&amp;gt;sys_platform != &#039;win32&#039;&amp;lt;/code&amp;gt; platform marker.&lt;br /&gt;
* &#039;&#039;&#039;Dual-package requirement:&#039;&#039;&#039; Unlike TensorFlow or PyTorch, JAX requires both &amp;lt;code&amp;gt;jax&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;jaxlib&amp;lt;/code&amp;gt; to be importable. Having only one installed will result in &amp;lt;code&amp;gt;JAX_AVAILABLE = False&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;&#039;No mutual exclusion:&#039;&#039;&#039; Unlike the TensorFlow/PyTorch pair, JAX detection has no mutual exclusion logic with other frameworks. JAX can be active simultaneously with PyTorch or TensorFlow.&lt;br /&gt;
* &#039;&#039;&#039;Serialization constraint:&#039;&#039;&#039; &amp;lt;code&amp;gt;jaxlib.xla_extension.Device&amp;lt;/code&amp;gt; objects cannot be serialized with &amp;lt;code&amp;gt;pickle&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;dill&amp;lt;/code&amp;gt;. The formatter uses a global &amp;lt;code&amp;gt;DEVICE_MAPPING&amp;lt;/code&amp;gt; dictionary and string-based device references to work around this limitation. This design means device objects are re-resolved from strings after deserialization.&lt;br /&gt;
* &#039;&#039;&#039;64-bit precision:&#039;&#039;&#039; JAX&#039;s default 32-bit behavior affects dtype selection in the formatter. Code relying on 64-bit integer precision must explicitly enable &amp;lt;code&amp;gt;jax_enable_x64&amp;lt;/code&amp;gt; before data loading.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[Implementation:Huggingface_Datasets_JaxFormatter]] -- The &amp;lt;code&amp;gt;JaxFormatter&amp;lt;/code&amp;gt; class that converts Arrow tables to JAX arrays with device placement&lt;br /&gt;
* [[Implementation:Huggingface_Datasets_Dataset_Set_Format]] -- The &amp;lt;code&amp;gt;set_format()&amp;lt;/code&amp;gt; method used to select the JAX output format&lt;br /&gt;
&lt;br /&gt;
[[Category:Environments]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Environment:Huggingface_Datasets_Image_Dependencies&amp;diff=30813</id>
		<title>Environment:Huggingface Datasets Image Dependencies</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Environment:Huggingface_Datasets_Image_Dependencies&amp;diff=30813"/>
		<updated>2026-09-27T10:53:39Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Environment|title=Huggingface_Datasets_Image_Dependencies}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Knowledge Sources&lt;br /&gt;
|&lt;br /&gt;
* [https://github.com/huggingface/datasets HuggingFace Datasets]&lt;br /&gt;
|-&lt;br /&gt;
! Domains&lt;br /&gt;
| [[domain::Image Processing]], [[domain::Computer Vision]], [[domain::Media Encoding]], [[domain::Media Decoding]]&lt;br /&gt;
|-&lt;br /&gt;
! Last Updated&lt;br /&gt;
| [[last_updated::2026-02-14 19:00 GMT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;Image Dependencies&#039;&#039;&#039; environment defines the optional packages required to enable image encoding and decoding within the HuggingFace Datasets library. Image support relies on &#039;&#039;&#039;Pillow&#039;&#039;&#039; (the PIL fork), which is the standard Python library for opening, manipulating, and saving image files. Pillow is &#039;&#039;&#039;not&#039;&#039;&#039; included in the base datasets installation and must be installed separately or via the &amp;lt;code&amp;gt;[vision]&amp;lt;/code&amp;gt; extra.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
Image features are activated by installing the optional &amp;lt;code&amp;gt;[vision]&amp;lt;/code&amp;gt; extra. This unlocks the ability to:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Encode&#039;&#039;&#039; image data into dataset-compatible formats via &amp;lt;code&amp;gt;image.py&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Decode&#039;&#039;&#039; image data from stored representations via &amp;lt;code&amp;gt;image.py&amp;lt;/code&amp;gt;&lt;br /&gt;
* Access EXIF metadata and other image properties through PIL&#039;s API&lt;br /&gt;
&lt;br /&gt;
The library checks for the availability of Pillow at runtime using &amp;lt;code&amp;gt;importlib.util.find_spec(&amp;quot;PIL&amp;quot;)&amp;lt;/code&amp;gt; and stores the result in the &amp;lt;code&amp;gt;PIL_AVAILABLE&amp;lt;/code&amp;gt; flag defined in &amp;lt;code&amp;gt;config.py&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== System Requirements ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Python&#039;&#039;&#039;: Compatible with the Python versions supported by HuggingFace Datasets&lt;br /&gt;
* &#039;&#039;&#039;Operating System&#039;&#039;&#039;: Linux, macOS, or Windows&lt;br /&gt;
* &#039;&#039;&#039;System Libraries&#039;&#039;&#039;: Pillow may require system-level imaging libraries (e.g., &amp;lt;code&amp;gt;libjpeg&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;libpng&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;zlib&amp;lt;/code&amp;gt;) depending on the image formats used&lt;br /&gt;
&lt;br /&gt;
== Dependencies ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Package !! Minimum Version !! Purpose !! Required By&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Pillow&#039;&#039;&#039; || 9.4.0 || Image encoding, decoding, and manipulation || &amp;lt;code&amp;gt;image.py&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
As defined in &amp;lt;code&amp;gt;setup.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
VISION_REQUIRE = [&amp;quot;Pillow&amp;gt;=9.4.0&amp;quot;]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The minimum version of &#039;&#039;&#039;Pillow 9.4.0&#039;&#039;&#039; was chosen because this is when &amp;lt;code&amp;gt;PIL.Image.ExifTags&amp;lt;/code&amp;gt; was introduced, which the datasets library uses for EXIF metadata handling.&lt;br /&gt;
&lt;br /&gt;
== Credentials ==&lt;br /&gt;
&lt;br /&gt;
No credentials are required to install or use the image dependencies. All packages are available from public PyPI repositories.&lt;br /&gt;
&lt;br /&gt;
== Quick Install ==&lt;br /&gt;
&lt;br /&gt;
Install the vision extras with pip:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pip install datasets[vision]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or install the dependency directly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pip install &amp;quot;Pillow&amp;gt;=9.4.0&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Evidence ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Runtime availability check&#039;&#039;&#039; in &amp;lt;code&amp;gt;config.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
PIL_AVAILABLE = importlib.util.find_spec(&amp;quot;PIL&amp;quot;) is not None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Image encoding guard&#039;&#039;&#039; in &amp;lt;code&amp;gt;image.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Raises an error when Pillow is not installed&lt;br /&gt;
&amp;quot;To support encoding images, please install &#039;Pillow&#039;.&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Image decoding guard&#039;&#039;&#039; in &amp;lt;code&amp;gt;image.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Raises an error when Pillow is not installed&lt;br /&gt;
&amp;quot;To support decoding images, please install &#039;Pillow&#039;.&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Version requirement rationale&#039;&#039;&#039; in &amp;lt;code&amp;gt;setup.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
VISION_REQUIRE = [&amp;quot;Pillow&amp;gt;=9.4.0&amp;quot;]  # When PIL.Image.ExifTags was introduced&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Common Errors ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Error Message !! Cause !! Resolution&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;To support encoding images, please install &#039;Pillow&#039;.&amp;lt;/code&amp;gt; || Pillow is not installed and image encoding was attempted || Run &amp;lt;code&amp;gt;pip install &amp;quot;Pillow&amp;gt;=9.4.0&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;To support decoding images, please install &#039;Pillow&#039;.&amp;lt;/code&amp;gt; || Pillow is not installed and image decoding was attempted || Run &amp;lt;code&amp;gt;pip install &amp;quot;Pillow&amp;gt;=9.4.0&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ModuleNotFoundError: No module named &#039;PIL&#039;&amp;lt;/code&amp;gt; || Pillow package is missing from the environment || Run &amp;lt;code&amp;gt;pip install &amp;quot;Pillow&amp;gt;=9.4.0&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ImportError: cannot import name &#039;ExifTags&#039; from &#039;PIL.Image&#039;&amp;lt;/code&amp;gt; || Installed Pillow version is older than 9.4.0 || Run &amp;lt;code&amp;gt;pip install --upgrade &amp;quot;Pillow&amp;gt;=9.4.0&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;&#039;Pillow &amp;gt;= 9.4.0&#039;&#039;&#039; requirement is specifically tied to the introduction of &amp;lt;code&amp;gt;PIL.Image.ExifTags&amp;lt;/code&amp;gt;. Earlier Pillow versions will not provide full functionality.&lt;br /&gt;
* Pillow is imported under the &amp;lt;code&amp;gt;PIL&amp;lt;/code&amp;gt; namespace (the original Python Imaging Library name), which is why the availability check uses &amp;lt;code&amp;gt;find_spec(&amp;quot;PIL&amp;quot;)&amp;lt;/code&amp;gt; rather than &amp;lt;code&amp;gt;find_spec(&amp;quot;Pillow&amp;quot;)&amp;lt;/code&amp;gt;.&lt;br /&gt;
* The &amp;lt;code&amp;gt;PIL_AVAILABLE&amp;lt;/code&amp;gt; flag in &amp;lt;code&amp;gt;config.py&amp;lt;/code&amp;gt; allows the library to gracefully degrade when Pillow is absent, rather than failing at import time.&lt;br /&gt;
* Pillow supports a wide range of image formats (JPEG, PNG, TIFF, BMP, GIF, WebP, etc.), but some formats may require additional system libraries to be installed.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[Implementation:Huggingface_Datasets_Image]] — Image feature type implementation&lt;br /&gt;
&lt;br /&gt;
[[Category:Environments]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Environment:Huggingface_Datasets_Audio_Video_Dependencies&amp;diff=30812</id>
		<title>Environment:Huggingface Datasets Audio Video Dependencies</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Environment:Huggingface_Datasets_Audio_Video_Dependencies&amp;diff=30812"/>
		<updated>2026-09-27T10:53:39Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Environment|title=Huggingface_Datasets_Audio_Video_Dependencies}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Knowledge Sources&lt;br /&gt;
|&lt;br /&gt;
* [https://github.com/huggingface/datasets HuggingFace Datasets]&lt;br /&gt;
|-&lt;br /&gt;
! Domains&lt;br /&gt;
| [[domain::Audio Processing]], [[domain::Video Processing]], [[domain::Media Encoding]], [[domain::Media Decoding]]&lt;br /&gt;
|-&lt;br /&gt;
! Last Updated&lt;br /&gt;
| [[last_updated::2026-02-14 19:00 GMT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;Audio/Video Dependencies&#039;&#039;&#039; environment defines the optional packages required to enable audio and video encoding and decoding within the HuggingFace Datasets library. Audio and video support is &#039;&#039;&#039;not&#039;&#039;&#039; included in the base installation; users must install additional dependencies to work with these media types. The primary dependency is &#039;&#039;&#039;torchcodec&#039;&#039;&#039;, which provides both encoding and decoding capabilities for audio data, and decoding capabilities for video data. The &#039;&#039;&#039;torch&#039;&#039;&#039; (PyTorch) library is also required as a foundational dependency.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
Audio and video features are activated by installing the optional &amp;lt;code&amp;gt;[audio]&amp;lt;/code&amp;gt; extra. This unlocks the ability to:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Encode&#039;&#039;&#039; audio data into dataset-compatible formats via &amp;lt;code&amp;gt;audio.py&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Decode&#039;&#039;&#039; audio data from stored representations via &amp;lt;code&amp;gt;audio.py&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;_torchcodec.py&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Decode&#039;&#039;&#039; video data from stored representations via &amp;lt;code&amp;gt;video.py&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The library checks for the availability of torchcodec at runtime using &amp;lt;code&amp;gt;importlib.util.find_spec(&amp;quot;torchcodec&amp;quot;)&amp;lt;/code&amp;gt; and stores the result in the &amp;lt;code&amp;gt;TORCHCODEC_AVAILABLE&amp;lt;/code&amp;gt; flag defined in &amp;lt;code&amp;gt;config.py&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== System Requirements ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Python&#039;&#039;&#039;: Compatible with the Python versions supported by HuggingFace Datasets&lt;br /&gt;
* &#039;&#039;&#039;Operating System&#039;&#039;&#039;: Linux, macOS, or Windows (subject to PyTorch and torchcodec platform support)&lt;br /&gt;
* &#039;&#039;&#039;Hardware&#039;&#039;&#039;: A PyTorch-compatible environment; GPU is optional but may accelerate encoding/decoding operations&lt;br /&gt;
&lt;br /&gt;
== Dependencies ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Package !! Minimum Version !! Purpose !! Required By&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;torchcodec&#039;&#039;&#039; || 0.6.0 || Audio encoding/decoding, video decoding || &amp;lt;code&amp;gt;audio.py&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;video.py&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;_torchcodec.py&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;torch&#039;&#039;&#039; (PyTorch) || 2.8.0 || Tensor operations, backend for torchcodec || &amp;lt;code&amp;gt;_torchcodec.py&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;audio.py&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;video.py&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;numpy&#039;&#039;&#039; || &#039;&#039;(transitive)&#039;&#039; || Array operations used by torchcodec internals || &amp;lt;code&amp;gt;_torchcodec.py&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
As defined in &amp;lt;code&amp;gt;setup.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
AUDIO_REQUIRE = [&amp;quot;torchcodec&amp;gt;=0.6.0&amp;quot;, &amp;quot;torch&amp;gt;=2.8.0&amp;quot;]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Credentials ==&lt;br /&gt;
&lt;br /&gt;
No credentials are required to install or use the audio/video dependencies. All packages are available from public PyPI repositories.&lt;br /&gt;
&lt;br /&gt;
== Quick Install ==&lt;br /&gt;
&lt;br /&gt;
Install the audio/video extras with pip:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pip install datasets[audio]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or install the dependencies directly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pip install &amp;quot;torchcodec&amp;gt;=0.6.0&amp;quot; &amp;quot;torch&amp;gt;=2.8.0&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Evidence ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Runtime availability check&#039;&#039;&#039; in &amp;lt;code&amp;gt;config.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
TORCHCODEC_AVAILABLE = importlib.util.find_spec(&amp;quot;torchcodec&amp;quot;) is not None&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Audio encoding guard&#039;&#039;&#039; in &amp;lt;code&amp;gt;audio.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Raises an error when torchcodec is not installed&lt;br /&gt;
&amp;quot;To support encoding audio data, please install &#039;torchcodec&#039;.&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Audio decoding guard&#039;&#039;&#039; in &amp;lt;code&amp;gt;audio.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Raises an error when torchcodec is not installed&lt;br /&gt;
&amp;quot;To support decoding audio data, please install &#039;torchcodec&#039;.&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Video decoding guard&#039;&#039;&#039; in &amp;lt;code&amp;gt;video.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Raises an error when torchcodec is not installed&lt;br /&gt;
&amp;quot;To support decoding videos, please install &#039;torchcodec&#039;.&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Direct imports&#039;&#039;&#039; in &amp;lt;code&amp;gt;_torchcodec.py&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
from torchcodec.decoders import AudioDecoder&lt;br /&gt;
import numpy&lt;br /&gt;
import torch&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Common Errors ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Error Message !! Cause !! Resolution&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;To support encoding audio data, please install &#039;torchcodec&#039;.&amp;lt;/code&amp;gt; || torchcodec is not installed and audio encoding was attempted || Run &amp;lt;code&amp;gt;pip install &amp;quot;torchcodec&amp;gt;=0.6.0&amp;quot; &amp;quot;torch&amp;gt;=2.8.0&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;To support decoding audio data, please install &#039;torchcodec&#039;.&amp;lt;/code&amp;gt; || torchcodec is not installed and audio decoding was attempted || Run &amp;lt;code&amp;gt;pip install &amp;quot;torchcodec&amp;gt;=0.6.0&amp;quot; &amp;quot;torch&amp;gt;=2.8.0&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;To support decoding videos, please install &#039;torchcodec&#039;.&amp;lt;/code&amp;gt; || torchcodec is not installed and video decoding was attempted || Run &amp;lt;code&amp;gt;pip install &amp;quot;torchcodec&amp;gt;=0.6.0&amp;quot; &amp;quot;torch&amp;gt;=2.8.0&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ModuleNotFoundError: No module named &#039;torchcodec&#039;&amp;lt;/code&amp;gt; || torchcodec package is missing from the environment || Run &amp;lt;code&amp;gt;pip install &amp;quot;torchcodec&amp;gt;=0.6.0&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ModuleNotFoundError: No module named &#039;torch&#039;&amp;lt;/code&amp;gt; || PyTorch is missing from the environment || Run &amp;lt;code&amp;gt;pip install &amp;quot;torch&amp;gt;=2.8.0&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;&#039;torchcodec &amp;gt;= 0.6.0&#039;&#039;&#039; requirement indicates that earlier versions of torchcodec lack the APIs used by the datasets library (e.g., &amp;lt;code&amp;gt;AudioDecoder&amp;lt;/code&amp;gt;).&lt;br /&gt;
* The &#039;&#039;&#039;torch &amp;gt;= 2.8.0&#039;&#039;&#039; requirement ensures compatibility with torchcodec 0.6.0 and above.&lt;br /&gt;
* The &amp;lt;code&amp;gt;TORCHCODEC_AVAILABLE&amp;lt;/code&amp;gt; flag in &amp;lt;code&amp;gt;config.py&amp;lt;/code&amp;gt; allows the library to gracefully degrade when these optional dependencies are absent, rather than failing at import time.&lt;br /&gt;
* Audio and video features share the same dependency set, so installing for one automatically enables the other.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[Implementation:Huggingface_Datasets_Audio]] — Audio feature type implementation&lt;br /&gt;
* [[Implementation:Huggingface_Datasets_Video]] — Video feature type implementation&lt;br /&gt;
&lt;br /&gt;
[[Category:Environments]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Environment:Googleapis_Python_genai_Vertex_AI_Service_Account&amp;diff=30811</id>
		<title>Environment:Googleapis Python genai Vertex AI Service Account</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Environment:Googleapis_Python_genai_Vertex_AI_Service_Account&amp;diff=30811"/>
		<updated>2026-09-27T10:53:38Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Environment|title=Googleapis_Python_genai_Vertex_AI_Service_Account}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Knowledge Sources&lt;br /&gt;
|&lt;br /&gt;
* [https://github.com/googleapis/python-genai googleapis/python-genai]&lt;br /&gt;
* [https://cloud.google.com/vertex-ai/docs Vertex AI Documentation]&lt;br /&gt;
|-&lt;br /&gt;
! Domains&lt;br /&gt;
| [[domain::Authentication]], [[domain::Infrastructure]], [[domain::Google_Cloud]]&lt;br /&gt;
|-&lt;br /&gt;
! Last Updated&lt;br /&gt;
| [[last_updated::2026-02-15 14:00 GMT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Google Cloud service account / Application Default Credentials (ADC) environment for Vertex AI API access, configured via `GOOGLE_GENAI_USE_VERTEXAI`, `GOOGLE_CLOUD_PROJECT`, and `GOOGLE_CLOUD_LOCATION`.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
This environment configures authentication for the &#039;&#039;&#039;Vertex AI API&#039;&#039;&#039; path. When `vertexai=True` or the `GOOGLE_GENAI_USE_VERTEXAI` environment variable is set, the SDK uses Google Cloud Application Default Credentials (ADC) with the `cloud-platform` OAuth scope. The base URL becomes `https://{location}-aiplatform.googleapis.com/` with API version `v1beta1`.&lt;br /&gt;
&lt;br /&gt;
The SDK automatically loads credentials via `google.auth.default()` and manages token refresh using a thread-safe lock mechanism. Credentials are refreshed before each request if they have expired.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
Use this environment when accessing Gemini models through &#039;&#039;&#039;Vertex AI&#039;&#039;&#039; in Google Cloud. This is required for enterprise features, VPC Service Controls, private endpoints, and when billing through a Google Cloud project.&lt;br /&gt;
&lt;br /&gt;
== System Requirements ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Category !! Requirement !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Network || HTTPS to `{location}-aiplatform.googleapis.com` || Location-specific endpoint&lt;br /&gt;
|-&lt;br /&gt;
| Authentication || Google Cloud service account or ADC || Application Default Credentials&lt;br /&gt;
|-&lt;br /&gt;
| Google Cloud || Active GCP project with Vertex AI API enabled || Billing must be configured&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencies ==&lt;br /&gt;
&lt;br /&gt;
No additional dependencies beyond the base SDK runtime ([[Environment:Googleapis_Python_genai_Python_3_10_SDK_Runtime]]). The `google-auth` package (already a core dependency) handles credential loading.&lt;br /&gt;
&lt;br /&gt;
== Credentials ==&lt;br /&gt;
&lt;br /&gt;
The following environment variables configure Vertex AI authentication:&lt;br /&gt;
&lt;br /&gt;
* `GOOGLE_GENAI_USE_VERTEXAI`: Set to `true` or `1` to enable Vertex AI mode.&lt;br /&gt;
* `GOOGLE_CLOUD_PROJECT`: Google Cloud project ID. Auto-detected from ADC if not set.&lt;br /&gt;
* `GOOGLE_CLOUD_LOCATION`: Google Cloud region (e.g., `us-central1`). Required for Vertex AI.&lt;br /&gt;
* `GOOGLE_VERTEX_BASE_URL`: (Optional) Custom Vertex AI base URL for private endpoints.&lt;br /&gt;
* `SSL_CERT_FILE`: (Optional) Path to custom CA certificate file. Defaults to certifi bundle.&lt;br /&gt;
* `SSL_CERT_DIR`: (Optional) Directory containing CA certificates.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Credential sources&#039;&#039;&#039; (in order of precedence):&lt;br /&gt;
# Explicitly passed `credentials` parameter&lt;br /&gt;
# Application Default Credentials via `google.auth.default()`&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OAuth Scope:&#039;&#039;&#039; `https://www.googleapis.com/auth/cloud-platform`&lt;br /&gt;
&lt;br /&gt;
== Quick Install ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Set up Vertex AI mode&lt;br /&gt;
export GOOGLE_GENAI_USE_VERTEXAI=true&lt;br /&gt;
export GOOGLE_CLOUD_PROJECT=&#039;my-project-id&#039;&lt;br /&gt;
export GOOGLE_CLOUD_LOCATION=&#039;us-central1&#039;&lt;br /&gt;
&lt;br /&gt;
# Authenticate with Google Cloud&lt;br /&gt;
gcloud auth application-default login&lt;br /&gt;
&lt;br /&gt;
# Install the SDK&lt;br /&gt;
pip install google-genai&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Evidence ==&lt;br /&gt;
&lt;br /&gt;
Vertex AI mode detection from `_api_client.py:559-564`:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
if self.vertexai is None:&lt;br /&gt;
    if os.environ.get(&#039;GOOGLE_GENAI_USE_VERTEXAI&#039;, &#039;0&#039;).lower() in [&lt;br /&gt;
        &#039;true&#039;,&lt;br /&gt;
        &#039;1&#039;,&lt;br /&gt;
    ]:&lt;br /&gt;
        self.vertexai = True&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Project and location from environment in `_api_client.py:597-602`:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
env_project = os.environ.get(&#039;GOOGLE_CLOUD_PROJECT&#039;, None)&lt;br /&gt;
env_location = os.environ.get(&#039;GOOGLE_CLOUD_LOCATION&#039;, None)&lt;br /&gt;
env_api_key = get_env_api_key()&lt;br /&gt;
self.project = project or env_project&lt;br /&gt;
self.location = location or env_location&lt;br /&gt;
self.api_key = api_key or env_api_key&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ADC credential loading from `_api_client.py:182-203`:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def load_auth(*, project: Union[str, None]) -&amp;gt; Tuple[Credentials, str]:&lt;br /&gt;
    os.environ[&#039;GOOGLE_API_PREVENT_AGENT_TOKEN_SHARING_FOR_GCP_SERVICES&#039;] = &#039;false&#039;&lt;br /&gt;
    credentials, loaded_project_id = google.auth.default(&lt;br /&gt;
        scopes=[&#039;https://www.googleapis.com/auth/cloud-platform&#039;],&lt;br /&gt;
    )&lt;br /&gt;
    if not project:&lt;br /&gt;
        project = loaded_project_id&lt;br /&gt;
    if not project:&lt;br /&gt;
        raise ValueError(&lt;br /&gt;
            &#039;Could not resolve project using application default credentials.&#039;&lt;br /&gt;
        )&lt;br /&gt;
    return credentials, project&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Precedence logic for Vertex AI mode from `_api_client.py:615-644`:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
if self.vertexai:&lt;br /&gt;
    if credentials and env_api_key:&lt;br /&gt;
        # Explicit credentials take precedence over implicit api_key.&lt;br /&gt;
        self.api_key = None&lt;br /&gt;
    elif (env_location or env_project) and api_key:&lt;br /&gt;
        # Explicit api_key takes precedence over implicit project/location.&lt;br /&gt;
        self.project = None&lt;br /&gt;
        self.location = None&lt;br /&gt;
    elif (project or location) and env_api_key:&lt;br /&gt;
        # Explicit project/location takes precedence over implicit api_key.&lt;br /&gt;
        self.api_key = None&lt;br /&gt;
    elif (env_location or env_project) and env_api_key:&lt;br /&gt;
        # Implicit project/location takes precedence over implicit api_key.&lt;br /&gt;
        self.api_key = None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SSL configuration from `_api_client.py:834-835`:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
cafile=os.environ.get(&#039;SSL_CERT_FILE&#039;, certifi.where())&lt;br /&gt;
capath=os.environ.get(&#039;SSL_CERT_DIR&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Common Errors ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Error Message !! Cause !! Solution&lt;br /&gt;
|-&lt;br /&gt;
|| `ValueError: Could not resolve project using application default credentials.` || No project ID found via ADC or env var || Set `GOOGLE_CLOUD_PROJECT` or pass `project=` parameter&lt;br /&gt;
|-&lt;br /&gt;
|| `ValueError: Project/location and API key are mutually exclusive` || Both API key and project/location provided || Use one authentication mode&lt;br /&gt;
|-&lt;br /&gt;
|| `google.auth.exceptions.DefaultCredentialsError` || No ADC configured || Run `gcloud auth application-default login`&lt;br /&gt;
|-&lt;br /&gt;
|| `PermissionDenied` (403) || Vertex AI API not enabled or missing IAM roles || Enable Vertex AI API; grant `roles/aiplatform.user`&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Vertex AI Express Mode:&#039;&#039;&#039; API keys can be used with Vertex AI (bypassing ADC), but project/location takes precedence when both are available from environment.&lt;br /&gt;
* &#039;&#039;&#039;Token Sharing:&#039;&#039;&#039; The SDK internally sets `GOOGLE_API_PREVENT_AGENT_TOKEN_SHARING_FOR_GCP_SERVICES=false` to disable bound token sharing.&lt;br /&gt;
* &#039;&#039;&#039;Thread Safety:&#039;&#039;&#039; Credential refresh is protected by `threading.Lock` (sync) and `asyncio.Lock` (async) for concurrent access.&lt;br /&gt;
* &#039;&#039;&#039;Custom Endpoints:&#039;&#039;&#039; Use `GOOGLE_VERTEX_BASE_URL` for private or regional endpoints.&lt;br /&gt;
* &#039;&#039;&#039;Live API:&#039;&#039;&#039; Vertex AI Live API uses bearer token authentication over WebSocket, with automatic credential refresh if the token has expired.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[required_by::Implementation:Googleapis_Python_genai_Client_Init]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Environments]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Environment:Googleapis_Python_genai_Python_3_10_SDK_Runtime&amp;diff=30810</id>
		<title>Environment:Googleapis Python genai Python 3 10 SDK Runtime</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Environment:Googleapis_Python_genai_Python_3_10_SDK_Runtime&amp;diff=30810"/>
		<updated>2026-09-27T10:53:38Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Environment|title=Googleapis_Python_genai_Python_3_10_SDK_Runtime}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Knowledge Sources&lt;br /&gt;
|&lt;br /&gt;
* [https://github.com/googleapis/python-genai googleapis/python-genai]&lt;br /&gt;
* [https://pypi.org/project/google-genai/ PyPI google-genai]&lt;br /&gt;
|-&lt;br /&gt;
! Domains&lt;br /&gt;
| [[domain::Infrastructure]], [[domain::SDK_Runtime]]&lt;br /&gt;
|-&lt;br /&gt;
! Last Updated&lt;br /&gt;
| [[last_updated::2026-02-15 14:00 GMT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Python 3.10+ runtime environment with core dependencies (httpx, pydantic, google-auth, websockets, aiohttp) required to run the Google GenAI SDK v1.63.0.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
This environment defines the base Python runtime and package dependencies needed to use the &#039;&#039;&#039;google-genai&#039;&#039;&#039; SDK. The SDK requires Python 3.10 or higher due to use of &#039;&#039;&#039;types.UnionType&#039;&#039;&#039; (PEP 604) and other 3.10+ features in the automatic function calling utilities and type system. The SDK supports Python 3.10 through 3.14 as declared in its classifiers.&lt;br /&gt;
&lt;br /&gt;
Core dependencies include &#039;&#039;&#039;httpx&#039;&#039;&#039; for HTTP transport, &#039;&#039;&#039;pydantic&#039;&#039;&#039; v2 for data modeling, &#039;&#039;&#039;google-auth&#039;&#039;&#039; for authentication, &#039;&#039;&#039;websockets&#039;&#039;&#039; for the Live API, &#039;&#039;&#039;aiohttp&#039;&#039;&#039; for async HTTP, and &#039;&#039;&#039;tenacity&#039;&#039;&#039; for retry logic.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
This environment is required for &#039;&#039;&#039;all&#039;&#039;&#039; workflows in the Google GenAI SDK. Every operation — from text generation to fine-tuning to Live API streaming — requires these base dependencies to be installed.&lt;br /&gt;
&lt;br /&gt;
== System Requirements ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Category !! Requirement !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| OS || Any (OS Independent) || Classified as OS Independent in pyproject.toml&lt;br /&gt;
|-&lt;br /&gt;
| Python || &amp;gt;= 3.10 || Supports 3.10, 3.11, 3.12, 3.13, 3.14&lt;br /&gt;
|-&lt;br /&gt;
| Network || Internet access || Required for API calls to Google endpoints&lt;br /&gt;
|-&lt;br /&gt;
| Disk || Minimal || SDK itself is lightweight; no large model files&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencies ==&lt;br /&gt;
&lt;br /&gt;
=== System Packages ===&lt;br /&gt;
&lt;br /&gt;
No OS-level system packages are required beyond a standard Python installation.&lt;br /&gt;
&lt;br /&gt;
=== Python Packages (Core) ===&lt;br /&gt;
&lt;br /&gt;
* `google-genai` &amp;gt;= 1.63.0&lt;br /&gt;
* `anyio` &amp;gt;= 4.8.0, &amp;lt; 5.0.0&lt;br /&gt;
* `google-auth[requests]` &amp;gt;= 2.47.0, &amp;lt; 3.0.0&lt;br /&gt;
* `httpx` &amp;gt;= 0.28.1, &amp;lt; 1.0.0&lt;br /&gt;
* `pydantic` &amp;gt;= 2.9.0, &amp;lt; 3.0.0&lt;br /&gt;
* `requests` &amp;gt;= 2.28.1, &amp;lt; 3.0.0&lt;br /&gt;
* `tenacity` &amp;gt;= 8.2.3, &amp;lt; 9.2.0&lt;br /&gt;
* `websockets` &amp;gt;= 13.0.0, &amp;lt; 15.1.0&lt;br /&gt;
* `typing-extensions` &amp;gt;= 4.11.0, &amp;lt; 5.0.0&lt;br /&gt;
* `distro` &amp;gt;= 1.7.0, &amp;lt; 2&lt;br /&gt;
* `sniffio`&lt;br /&gt;
* `aiohttp` &amp;gt;= 3.10.11&lt;br /&gt;
&lt;br /&gt;
=== Python Packages (Optional) ===&lt;br /&gt;
&lt;br /&gt;
* `pillow` — Required for &#039;&#039;&#039;Image&#039;&#039;&#039; display/save via `Image.show()` and PIL-based content parts&lt;br /&gt;
* `mcp` &amp;gt;= 1.14.0 — Required for Model Context Protocol tool integration (Python &amp;gt; 3.9)&lt;br /&gt;
* `sentencepiece` &amp;gt;= 0.2.0 — Required for local token counting&lt;br /&gt;
* `protobuf` — Required alongside sentencepiece for local tokenizer&lt;br /&gt;
&lt;br /&gt;
== Credentials ==&lt;br /&gt;
&lt;br /&gt;
No credentials are required at the environment level. Authentication credentials (API keys, service accounts) are configured at the &#039;&#039;&#039;Client&#039;&#039;&#039; initialization level — see the [[Environment:Googleapis_Python_genai_Gemini_API_Key_Authentication]] and [[Environment:Googleapis_Python_genai_Vertex_AI_Service_Account]] environment pages.&lt;br /&gt;
&lt;br /&gt;
== Quick Install ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Install the SDK with all core dependencies&lt;br /&gt;
pip install google-genai&amp;gt;=1.63.0&lt;br /&gt;
&lt;br /&gt;
# For optional features:&lt;br /&gt;
# Local tokenizer support&lt;br /&gt;
pip install google-genai[local-tokenizer]&lt;br /&gt;
&lt;br /&gt;
# MCP tool integration (Python 3.10+)&lt;br /&gt;
pip install mcp&amp;gt;=1.14.0&lt;br /&gt;
&lt;br /&gt;
# PIL image support&lt;br /&gt;
pip install pillow&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Evidence ==&lt;br /&gt;
&lt;br /&gt;
Python 3.10+ requirement from `_automatic_function_calling_util.py:28`:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
if sys.version_info &amp;gt;= (3, 10):&lt;br /&gt;
    import types as builtin_types&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Same pattern in `_extra_utils.py:37`:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
if sys.version_info &amp;gt;= (3, 10):&lt;br /&gt;
    import types as builtin_types&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional PIL import from `types.py:60-65`:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
    import PIL.Image&lt;br /&gt;
    PIL_Image = PIL.Image.Image&lt;br /&gt;
    _is_pillow_image_imported = True&lt;br /&gt;
except ImportError:&lt;br /&gt;
    PIL_Image = None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional MCP import from `_mcp_utils.py:31-36`:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
try:&lt;br /&gt;
    from mcp.types import Tool as McpTool&lt;br /&gt;
    from mcp import ClientSession as McpClientSession&lt;br /&gt;
except ImportError:&lt;br /&gt;
    McpTool = None&lt;br /&gt;
    McpClientSession = None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dependency declaration from `pyproject.toml:10`:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;toml&amp;quot;&amp;gt;&lt;br /&gt;
requires-python = &amp;quot;&amp;gt;=3.10&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Common Errors ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Error Message !! Cause !! Solution&lt;br /&gt;
|-&lt;br /&gt;
|| `SyntaxError: X | Y` || Python &amp;lt; 3.10 used with union type syntax || Upgrade to Python 3.10+&lt;br /&gt;
|-&lt;br /&gt;
|| `ImportError: No module named &#039;PIL&#039;` || Pillow not installed, used `Image.show()` || `pip install pillow`&lt;br /&gt;
|-&lt;br /&gt;
|| `ImportError: No module named &#039;mcp&#039;` || MCP package not installed || `pip install mcp&amp;gt;=1.14.0`&lt;br /&gt;
|-&lt;br /&gt;
|| `ImportError: No module named &#039;sentencepiece&#039;` || Local tokenizer optional dep missing || `pip install google-genai[local-tokenizer]`&lt;br /&gt;
|-&lt;br /&gt;
|| `ValidationError` from pydantic || pydantic v1 installed instead of v2 || `pip install pydantic&amp;gt;=2.9.0`&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Python 3.10+:&#039;&#039;&#039; Required minimum. The SDK uses `types.UnionType` (PEP 604) and other 3.10+ features.&lt;br /&gt;
* &#039;&#039;&#039;Python 3.12+:&#039;&#039;&#039; Additional typing features are leveraged via `typing.override` when available.&lt;br /&gt;
* &#039;&#039;&#039;MCP Integration:&#039;&#039;&#039; Requires Python &amp;gt; 3.9 (declared in requirements.txt conditional).&lt;br /&gt;
* &#039;&#039;&#039;Websockets Compatibility:&#039;&#039;&#039; The SDK handles both old (`websockets.client`) and new (`websockets.asyncio.client`) import paths for websockets version compatibility.&lt;br /&gt;
* &#039;&#039;&#039;Pydantic v2 Only:&#039;&#039;&#039; The SDK requires pydantic &amp;gt;= 2.9.0; pydantic v1 is not supported.&lt;br /&gt;
* &#039;&#039;&#039;aiohttp:&#039;&#039;&#039; Async interactions client falls back to httpx if aiohttp is used, with a warning.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[required_by::Implementation:Googleapis_Python_genai_Client_Init]]&lt;br /&gt;
* [[required_by::Implementation:Googleapis_Python_genai_Models_Generate_Content]]&lt;br /&gt;
* [[required_by::Implementation:Googleapis_Python_genai_Chat_Send_Message]]&lt;br /&gt;
* [[required_by::Implementation:Googleapis_Python_genai_Files_Upload]]&lt;br /&gt;
* [[required_by::Implementation:Googleapis_Python_genai_Tunings_Tune]]&lt;br /&gt;
* [[required_by::Implementation:Googleapis_Python_genai_Caches_Create]]&lt;br /&gt;
* [[required_by::Implementation:Googleapis_Python_genai_Models_Generate_Images]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Environments]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Environment:Googleapis_Python_genai_Gemini_API_Key_Authentication&amp;diff=30809</id>
		<title>Environment:Googleapis Python genai Gemini API Key Authentication</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Environment:Googleapis_Python_genai_Gemini_API_Key_Authentication&amp;diff=30809"/>
		<updated>2026-09-27T10:53:37Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Environment|title=Googleapis_Python_genai_Gemini_API_Key_Authentication}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Knowledge Sources&lt;br /&gt;
|&lt;br /&gt;
* [https://github.com/googleapis/python-genai googleapis/python-genai]&lt;br /&gt;
* [https://aistudio.google.com/ Google AI Studio]&lt;br /&gt;
|-&lt;br /&gt;
! Domains&lt;br /&gt;
| [[domain::Authentication]], [[domain::Infrastructure]]&lt;br /&gt;
|-&lt;br /&gt;
! Last Updated&lt;br /&gt;
| [[last_updated::2026-02-15 14:00 GMT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
API key-based authentication environment for the Gemini Developer API, using `GOOGLE_API_KEY` or `GEMINI_API_KEY` environment variables.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
This environment configures authentication for the &#039;&#039;&#039;Gemini Developer API&#039;&#039;&#039; (non-Vertex AI) path. The SDK reads API keys from environment variables with a defined precedence order: `GOOGLE_API_KEY` takes priority over `GEMINI_API_KEY`. If both are set, a warning is logged and `GOOGLE_API_KEY` is used.&lt;br /&gt;
&lt;br /&gt;
The API key is passed as the `x-goog-api-key` HTTP header on every request. The base URL for this mode is `https://generativelanguage.googleapis.com/` with API version `v1beta`.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
Use this environment for &#039;&#039;&#039;Gemini Developer API&#039;&#039;&#039; access. This is the simplest authentication mode — obtain an API key from Google AI Studio and set it as an environment variable or pass it directly to the Client constructor.&lt;br /&gt;
&lt;br /&gt;
This is &#039;&#039;&#039;mutually exclusive&#039;&#039;&#039; with the Vertex AI Service Account environment. You cannot provide both an API key and project/location or credentials simultaneously.&lt;br /&gt;
&lt;br /&gt;
== System Requirements ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Category !! Requirement !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Network || HTTPS to `generativelanguage.googleapis.com` || Default Gemini API endpoint&lt;br /&gt;
|-&lt;br /&gt;
| Authentication || Google API Key || Obtainable from Google AI Studio&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Dependencies ==&lt;br /&gt;
&lt;br /&gt;
No additional dependencies beyond the base SDK runtime ([[Environment:Googleapis_Python_genai_Python_3_10_SDK_Runtime]]).&lt;br /&gt;
&lt;br /&gt;
== Credentials ==&lt;br /&gt;
&lt;br /&gt;
The following environment variables configure API key authentication:&lt;br /&gt;
&lt;br /&gt;
* `GOOGLE_API_KEY`: &#039;&#039;&#039;Primary&#039;&#039;&#039; API key for Google Gemini Developer API. Takes precedence if both keys are set.&lt;br /&gt;
* `GEMINI_API_KEY`: &#039;&#039;&#039;Fallback&#039;&#039;&#039; API key. Used only if `GOOGLE_API_KEY` is not set.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Alternatively&#039;&#039;&#039;, pass the API key directly:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
client = genai.Client(api_key=&#039;your-api-key&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Quick Install ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Set the API key environment variable&lt;br /&gt;
export GOOGLE_API_KEY=&#039;your-api-key-here&#039;&lt;br /&gt;
&lt;br /&gt;
# Install the SDK&lt;br /&gt;
pip install google-genai&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Evidence ==&lt;br /&gt;
&lt;br /&gt;
API key retrieval with precedence logic from `_api_client.py:95-109`:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def get_env_api_key() -&amp;gt; Optional[str]:&lt;br /&gt;
  env_google_api_key = os.environ.get(&#039;GOOGLE_API_KEY&#039;, None)&lt;br /&gt;
  env_gemini_api_key = os.environ.get(&#039;GEMINI_API_KEY&#039;, None)&lt;br /&gt;
  if env_google_api_key and env_gemini_api_key:&lt;br /&gt;
    logger.warning(&lt;br /&gt;
        &#039;Both GOOGLE_API_KEY and GEMINI_API_KEY are set. Using GOOGLE_API_KEY.&#039;&lt;br /&gt;
    )&lt;br /&gt;
  return env_google_api_key or env_gemini_api_key or None&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mutual exclusivity validation from `_api_client.py:567-578`:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
if (project or location) and api_key:&lt;br /&gt;
    raise ValueError(&lt;br /&gt;
        &#039;Project/location and API key are mutually exclusive in the client&#039;&lt;br /&gt;
        &#039; initializer.&#039;&lt;br /&gt;
    )&lt;br /&gt;
elif credentials and api_key:&lt;br /&gt;
    raise ValueError(&lt;br /&gt;
        &#039;Credentials and API key are mutually exclusive in the client&#039;&lt;br /&gt;
        &#039; initializer.&#039;&lt;br /&gt;
    )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ephemeral token restriction from `_api_client.py:1147-1150`:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
if self.api_key and self.api_key.startswith(&#039;auth_tokens/&#039;):&lt;br /&gt;
    raise EphemeralTokenAPIKeyError(&lt;br /&gt;
        &#039;Ephemeral tokens can only be used with the live API.&#039;&lt;br /&gt;
    )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Common Errors ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Error Message !! Cause !! Solution&lt;br /&gt;
|-&lt;br /&gt;
|| `ValueError: Project/location and API key are mutually exclusive` || Both `api_key` and `project`/`location` provided || Use only one authentication mode&lt;br /&gt;
|-&lt;br /&gt;
|| `ValueError: Credentials and API key are mutually exclusive` || Both `credentials` and `api_key` provided || Use only one authentication mode&lt;br /&gt;
|-&lt;br /&gt;
|| `EphemeralTokenAPIKeyError: Ephemeral tokens can only be used with the live API` || Used `auth_tokens/` key with non-Live API || Ephemeral tokens only work with `client.aio.live`&lt;br /&gt;
|-&lt;br /&gt;
|| `Both GOOGLE_API_KEY and GEMINI_API_KEY are set` (warning) || Both env vars configured || Remove one; `GOOGLE_API_KEY` takes precedence&lt;br /&gt;
|-&lt;br /&gt;
|| `ClientError` with 401/403 || Invalid or expired API key || Regenerate key from Google AI Studio&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Compatibility Notes ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Precedence:&#039;&#039;&#039; `GOOGLE_API_KEY` &amp;gt; `GEMINI_API_KEY` &amp;gt; None.&lt;br /&gt;
* &#039;&#039;&#039;Ephemeral Tokens:&#039;&#039;&#039; API keys starting with `auth_tokens/` are restricted to the Live API only and require `api_version=&#039;v1alpha&#039;`.&lt;br /&gt;
* &#039;&#039;&#039;Explicit vs Implicit:&#039;&#039;&#039; Explicitly passed `api_key` parameter always overrides environment variables.&lt;br /&gt;
* &#039;&#039;&#039;Vertex AI Express:&#039;&#039;&#039; API keys can also be used with Vertex AI (when `vertexai=True`), but explicit project/location takes precedence over implicit API key in that mode.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[required_by::Implementation:Googleapis_Python_genai_Client_Init]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Environments]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_SAT_Read_From_CLI_File&amp;diff=30808</id>
		<title>Implementation:Zai org CogVideo SAT Read From CLI File</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_SAT_Read_From_CLI_File&amp;diff=30808"/>
		<updated>2026-09-27T10:53:36Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_SAT_Read_From_CLI_File}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_SAT_Read_From_CLI_File}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || SAT Read From CLI File&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || SAT Video Generation&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 3 of 5&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || API Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;sat/sample_video.py:L23-41&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of two prompt input functions for the SAT video generation pipeline: &amp;lt;code&amp;gt;read_from_cli&amp;lt;/code&amp;gt; for interactive single-prompt input and &amp;lt;code&amp;gt;read_from_file&amp;lt;/code&amp;gt; for batch file-based input with distributed worker sharding.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The module provides two generator functions:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;read_from_cli()&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Uses Python&#039;s built-in &amp;lt;code&amp;gt;input()&amp;lt;/code&amp;gt; to interactively collect prompts from the user. Yields &amp;lt;code&amp;gt;(text, count)&amp;lt;/code&amp;gt; tuples with an incrementing counter.&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;read_from_file(p, rank, world_size)&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Reads lines from a text file and yields prompts assigned to the current worker based on modular distribution. Line index &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; is processed by worker &amp;lt;code&amp;gt;i mod world_size == rank&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Both functions return Python generators that yield &amp;lt;code&amp;gt;(text, count)&amp;lt;/code&amp;gt; tuples, enabling lazy evaluation and memory-efficient processing of large prompt files.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Interactive mode&lt;br /&gt;
for text, count in read_from_cli():&lt;br /&gt;
    generate_video(text, count)&lt;br /&gt;
&lt;br /&gt;
# Batch mode (distributed)&lt;br /&gt;
for text, count in read_from_file(&amp;quot;prompts.txt&amp;quot;, rank=0, world_size=4):&lt;br /&gt;
    generate_video(text, count)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sat/sample_video.py&amp;lt;/code&amp;gt; || L23-41 || &amp;lt;code&amp;gt;read_from_cli&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;read_from_file&amp;lt;/code&amp;gt; functions&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def read_from_cli() -&amp;gt; Generator[Tuple[str, int], None, None]:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Interactive prompt input. Yields (text, count) tuples.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def read_from_file(p: str, rank: int = 0, world_size: int = 1) -&amp;gt; Generator[Tuple[str, int], None, None]:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;File-based prompt input with distributed sharding.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from sample_video import read_from_cli, read_from_file&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;read_from_cli&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;(none)&#039;&#039; || -- || -- || Reads from standard input interactively&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;read_from_file&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Required || Path to the prompt text file&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;rank&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; || Current worker rank for distributed sharding&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;world_size&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; || Total number of workers for distributed sharding&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Yielded tuples || &amp;lt;code&amp;gt;Generator[Tuple[str, int], None, None]&amp;lt;/code&amp;gt; || Each yield produces &amp;lt;code&amp;gt;(text, count)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt; is the prompt string and &amp;lt;code&amp;gt;count&amp;lt;/code&amp;gt; is the sequential index&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Interactive CLI input&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from sample_video import read_from_cli&lt;br /&gt;
&lt;br /&gt;
for text, count in read_from_cli():&lt;br /&gt;
    print(f&amp;quot;Generating video {count} for prompt: {text}&amp;quot;)&lt;br /&gt;
    # User types: &amp;quot;A cat playing piano&amp;quot;&lt;br /&gt;
    # Yields: (&amp;quot;A cat playing piano&amp;quot;, 0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: File-based batch input&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from sample_video import read_from_file&lt;br /&gt;
&lt;br /&gt;
# prompts.txt contains one prompt per line&lt;br /&gt;
for text, count in read_from_file(&amp;quot;prompts.txt&amp;quot;):&lt;br /&gt;
    print(f&amp;quot;Generating video {count} for prompt: {text}&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 3: Distributed file input (4 GPUs)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from sample_video import read_from_file&lt;br /&gt;
&lt;br /&gt;
# Worker 0 of 4 processes lines 0, 4, 8, ...&lt;br /&gt;
for text, count in read_from_file(&amp;quot;prompts.txt&amp;quot;, rank=0, world_size=4):&lt;br /&gt;
    generate_video(text, count)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 4: Image-to-video prompt format&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# In prompts.txt for I2V:&lt;br /&gt;
# A cat playing piano@@/data/images/cat.jpg&lt;br /&gt;
# The &amp;quot;@@&amp;quot; separator splits text and image path&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_SAT_Prompt_Input]] -- Principle governing prompt input modes&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_SAT_Framework_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_SAT_Get_Model_Load_Checkpoint]] -- Previous step: model loading&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_SAT_Diffusion_Sample]] -- Next step: sampling with the prompt text&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_SAT_Inference_Get_Args]] -- Configuration that selects CLI vs file mode&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_SAT_Inference_Get_Args&amp;diff=30807</id>
		<title>Implementation:Zai org CogVideo SAT Inference Get Args</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_SAT_Inference_Get_Args&amp;diff=30807"/>
		<updated>2026-09-27T10:53:36Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_SAT_Inference_Get_Args}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_SAT_Inference_Get_Args}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || SAT Inference Get Args&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || SAT Video Generation&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 1 of 5&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || API Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;sat/sample_video.py:L285-301&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sat/arguments.py:L58-185&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of the argument parsing system for SAT-based CogVideoX inference. The &amp;lt;code&amp;gt;get_args&amp;lt;/code&amp;gt; function extends SAT&#039;s base argument parser with inference-specific parameters for controlling video generation resolution, frame count, FPS, prompt input method, and image-to-video mode.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;get_args&amp;lt;/code&amp;gt; function builds an argument parser that combines:&lt;br /&gt;
&lt;br /&gt;
# SAT framework&#039;s base arguments (model architecture, distributed settings, checkpoint path)&lt;br /&gt;
# YAML configuration loading via &amp;lt;code&amp;gt;--base&amp;lt;/code&amp;gt;&lt;br /&gt;
# Inference-specific arguments added by the sample_video module&lt;br /&gt;
&lt;br /&gt;
The function returns a fully populated &amp;lt;code&amp;gt;argparse.Namespace&amp;lt;/code&amp;gt; object that is passed to all subsequent pipeline stages including model loading, prompt reading, and sampling.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from arguments import get_args&lt;br /&gt;
&lt;br /&gt;
# Parse from sys.argv&lt;br /&gt;
args = get_args()&lt;br /&gt;
&lt;br /&gt;
# Or parse from explicit list&lt;br /&gt;
args = get_args([&amp;quot;--base&amp;quot;, &amp;quot;configs/cogvideox_2b.yaml&amp;quot;,&lt;br /&gt;
                 &amp;quot;--sampling-image-size&amp;quot;, &amp;quot;768&amp;quot;, &amp;quot;1360&amp;quot;,&lt;br /&gt;
                 &amp;quot;--sampling-num-frames&amp;quot;, &amp;quot;32&amp;quot;])&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sat/sample_video.py&amp;lt;/code&amp;gt; || L285-301 || Inference argument additions&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sat/arguments.py&amp;lt;/code&amp;gt; || L58-185 || Base SAT argument parser&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def get_args(args_list=None) -&amp;gt; argparse.Namespace:&lt;br /&gt;
    # Key inference-specific params:&lt;br /&gt;
    # --base: YAML config files&lt;br /&gt;
    # --input-type: &amp;quot;cli&amp;quot; or &amp;quot;txt&amp;quot;&lt;br /&gt;
    # --input-file: prompt file path&lt;br /&gt;
    # --sampling-image-size: [768, 1360]&lt;br /&gt;
    # --sampling-num-frames: 32&lt;br /&gt;
    # --sampling-fps: 8&lt;br /&gt;
    # --image2video: bool flag&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from arguments import get_args&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;args_list&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Optional[List[str]]&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; (uses sys.argv) || Explicit argument list for testing&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--base&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;List[str]&amp;lt;/code&amp;gt; || Required || YAML config file paths&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--input-type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;cli&amp;quot;&amp;lt;/code&amp;gt; || Prompt input method: &amp;lt;code&amp;gt;&amp;quot;cli&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;txt&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--input-file&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; || Path to prompt text file (required if input-type is &amp;lt;code&amp;gt;&amp;quot;txt&amp;quot;&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--sampling-image-size&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;List[int]&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;[768, 1360]&amp;lt;/code&amp;gt; || Output video resolution [height, width]&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--sampling-num-frames&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;32&amp;lt;/code&amp;gt; || Number of frames to generate&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--sampling-fps&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; || Frames per second of output video&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--image2video&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt; || Enable image-to-video generation mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Return value || &amp;lt;code&amp;gt;argparse.Namespace&amp;lt;/code&amp;gt; || Fully populated argument namespace combining YAML config and CLI overrides&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Text-to-video generation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
python sat/sample_video.py \&lt;br /&gt;
    --base configs/cogvideox_2b.yaml \&lt;br /&gt;
    --sampling-image-size 768 1360 \&lt;br /&gt;
    --sampling-num-frames 32 \&lt;br /&gt;
    --sampling-fps 8 \&lt;br /&gt;
    --input-type cli&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Batch generation from file&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
python sat/sample_video.py \&lt;br /&gt;
    --base configs/cogvideox_5b.yaml \&lt;br /&gt;
    --sampling-image-size 480 720 \&lt;br /&gt;
    --sampling-num-frames 48 \&lt;br /&gt;
    --input-type txt \&lt;br /&gt;
    --input-file prompts.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 3: Image-to-video generation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
python sat/sample_video.py \&lt;br /&gt;
    --base configs/cogvideox_5b_i2v.yaml \&lt;br /&gt;
    --sampling-image-size 480 720 \&lt;br /&gt;
    --sampling-num-frames 48 \&lt;br /&gt;
    --input-type cli \&lt;br /&gt;
    --image2video&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_SAT_Inference_Configuration]] -- Principle governing inference configuration&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_SAT_Framework_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_SAT_Get_Model_Load_Checkpoint]] -- Next step: model loading using the parsed args&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_SAT_Read_From_CLI_File]] -- Prompt reading controlled by &amp;lt;code&amp;gt;--input-type&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_SAT_Get_Model_Load_Checkpoint&amp;diff=30806</id>
		<title>Implementation:Zai org CogVideo SAT Get Model Load Checkpoint</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_SAT_Get_Model_Load_Checkpoint&amp;diff=30806"/>
		<updated>2026-09-27T10:53:35Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_SAT_Get_Model_Load_Checkpoint}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_SAT_Get_Model_Load_Checkpoint}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || SAT Get Model Load Checkpoint&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || SAT Video Generation&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 2 of 5&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || Wrapper Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;sat/sample_video.py:L137-144&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;External Dependencies&#039;&#039;&#039; || sat&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of model loading for SAT-based CogVideoX inference. This wrapper combines SAT framework&#039;s &amp;lt;code&amp;gt;get_model&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;load_checkpoint&amp;lt;/code&amp;gt; functions to instantiate the &amp;lt;code&amp;gt;SATVideoDiffusionEngine&amp;lt;/code&amp;gt; with pretrained weights and prepare it for inference.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The model loading implementation consists of three sequential calls:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;code&amp;gt;get_model(args, model_cls=SATVideoDiffusionEngine)&amp;lt;/code&amp;gt; -- Constructs the model architecture from configuration&lt;br /&gt;
# &amp;lt;code&amp;gt;load_checkpoint(model, args)&amp;lt;/code&amp;gt; -- Loads pretrained weights from the checkpoint path&lt;br /&gt;
# &amp;lt;code&amp;gt;model.eval()&amp;lt;/code&amp;gt; -- Sets the model to evaluation mode&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;get_model&amp;lt;/code&amp;gt; function reads model architecture parameters from &amp;lt;code&amp;gt;args.model_config&amp;lt;/code&amp;gt; (populated from the YAML config file) and instantiates the specified model class. The &amp;lt;code&amp;gt;load_checkpoint&amp;lt;/code&amp;gt; function reads weights from &amp;lt;code&amp;gt;args.load&amp;lt;/code&amp;gt; and applies them to the model.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from sat.model.base_model import get_model&lt;br /&gt;
from sat.training.model_io import load_checkpoint&lt;br /&gt;
from diffusion_video import SATVideoDiffusionEngine&lt;br /&gt;
&lt;br /&gt;
# args is obtained from get_args()&lt;br /&gt;
model = get_model(args, model_cls=SATVideoDiffusionEngine)&lt;br /&gt;
load_checkpoint(model, args)&lt;br /&gt;
model.eval()&lt;br /&gt;
&lt;br /&gt;
# Model is now ready for inference&lt;br /&gt;
with torch.no_grad():&lt;br /&gt;
    samples = model.sample(cond, uc, batch_size=1, shape=shape)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sat/sample_video.py&amp;lt;/code&amp;gt; || L137-144 || Model loading wrapper&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from sat.model.base_model import get_model&lt;br /&gt;
from sat.training.model_io import load_checkpoint&lt;br /&gt;
&lt;br /&gt;
model = get_model(args, model_cls=SATVideoDiffusionEngine)&lt;br /&gt;
load_checkpoint(model, args)&lt;br /&gt;
model.eval()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from sat.model.base_model import get_model&lt;br /&gt;
from sat.training.model_io import load_checkpoint&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;args&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;argparse.Namespace&amp;lt;/code&amp;gt; || Required || Parsed arguments containing model config and checkpoint path&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;args.model_config&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;dict&amp;lt;/code&amp;gt; || From YAML || Model architecture configuration loaded from YAML&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;args.load&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Required || Path to pretrained checkpoint directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;model_cls&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;SATVideoDiffusionEngine&amp;lt;/code&amp;gt; || Model class to instantiate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;SATVideoDiffusionEngine&amp;lt;/code&amp;gt; || Loaded model in eval mode, ready for inference&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Standard model loading&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from arguments import get_args&lt;br /&gt;
from sat.model.base_model import get_model&lt;br /&gt;
from sat.training.model_io import load_checkpoint&lt;br /&gt;
from diffusion_video import SATVideoDiffusionEngine&lt;br /&gt;
&lt;br /&gt;
args = get_args()&lt;br /&gt;
model = get_model(args, model_cls=SATVideoDiffusionEngine)&lt;br /&gt;
load_checkpoint(model, args)&lt;br /&gt;
model.eval()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Model loading with distributed setup&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import torch&lt;br /&gt;
from arguments import get_args&lt;br /&gt;
from sat.model.base_model import get_model&lt;br /&gt;
from sat.training.model_io import load_checkpoint&lt;br /&gt;
from diffusion_video import SATVideoDiffusionEngine&lt;br /&gt;
&lt;br /&gt;
args = get_args()&lt;br /&gt;
model = get_model(args, model_cls=SATVideoDiffusionEngine)&lt;br /&gt;
load_checkpoint(model, args)&lt;br /&gt;
model.eval()&lt;br /&gt;
&lt;br /&gt;
# Distributed inference uses SAT&#039;s built-in model parallelism&lt;br /&gt;
# configured via args (--model-parallel-size, etc.)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_SAT_Model_Loading_for_Inference]] -- Principle governing model loading for inference&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_SAT_Framework_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_SAT_Inference_Get_Args]] -- Previous step: argument parsing that provides model config&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_SAT_Read_From_CLI_File]] -- Next step: reading prompts for generation&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_SAT_Diffusion_Sample]] -- Sampling step using the loaded model&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_SAT_Diffusion_Sample&amp;diff=30805</id>
		<title>Implementation:Zai org CogVideo SAT Diffusion Sample</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_SAT_Diffusion_Sample&amp;diff=30805"/>
		<updated>2026-09-27T10:53:34Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_SAT_Diffusion_Sample}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_SAT_Diffusion_Sample}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || SAT Diffusion Sample&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || SAT Video Generation&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 4 of 5&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || API Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;sat/diffusion_video.py:L250-287&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sat/sgm/modules/diffusionmodules/sampling.py:L25-43&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;External Dependencies&#039;&#039;&#039; || torch, sat.mpu, sgm.modules.diffusionmodules.sampling&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of the diffusion sampling method on the &amp;lt;code&amp;gt;SATVideoDiffusionEngine&amp;lt;/code&amp;gt; class. The &amp;lt;code&amp;gt;sample&amp;lt;/code&amp;gt; method orchestrates the iterative denoising process using the EulerEDM sampler, classifier-free guidance, and optional image conditioning for I2V generation.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;sample&amp;lt;/code&amp;gt; method:&lt;br /&gt;
&lt;br /&gt;
# Initializes random Gaussian noise of the specified shape&lt;br /&gt;
# Delegates to the configured sampler (EulerEDM) via &amp;lt;code&amp;gt;BaseDiffusionSampler&amp;lt;/code&amp;gt;&lt;br /&gt;
# The sampler iterates over the timestep schedule, calling the denoiser at each step&lt;br /&gt;
# Classifier-free guidance is applied by running both conditional and unconditional forward passes&lt;br /&gt;
# For I2V, &amp;lt;code&amp;gt;concat_images&amp;lt;/code&amp;gt; are concatenated to the noise and &amp;lt;code&amp;gt;ofs&amp;lt;/code&amp;gt; provides temporal offset embedding&lt;br /&gt;
# Returns the final denoised latent tensor&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;BaseDiffusionSampler&amp;lt;/code&amp;gt; at &amp;lt;code&amp;gt;sgm/modules/diffusionmodules/sampling.py&amp;lt;/code&amp;gt; defines the abstract sampling interface and timestep scheduling.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
with torch.no_grad():&lt;br /&gt;
    samples = model.sample(&lt;br /&gt;
        cond=conditioner_output,&lt;br /&gt;
        uc=unconditional_output,&lt;br /&gt;
        batch_size=1,&lt;br /&gt;
        shape=(T, C, H // 8, W // 8),&lt;br /&gt;
    )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sat/diffusion_video.py&amp;lt;/code&amp;gt; || L250-287 || &amp;lt;code&amp;gt;SATVideoDiffusionEngine.sample&amp;lt;/code&amp;gt; method&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sat/sgm/modules/diffusionmodules/sampling.py&amp;lt;/code&amp;gt; || L25-43 || &amp;lt;code&amp;gt;BaseDiffusionSampler&amp;lt;/code&amp;gt; abstract class&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class SATVideoDiffusionEngine:&lt;br /&gt;
    def sample(&lt;br /&gt;
        self,&lt;br /&gt;
        cond: Dict,&lt;br /&gt;
        uc: Dict = None,&lt;br /&gt;
        batch_size: int = 1,&lt;br /&gt;
        shape: Tuple = (T, C, H, W),&lt;br /&gt;
        concat_images: torch.Tensor = None,  # For I2V&lt;br /&gt;
        ofs: torch.Tensor = None,            # For I2V offset&lt;br /&gt;
    ) -&amp;gt; torch.Tensor:&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Returns denoised latent tensor [B, T, C, H, W]&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from diffusion_video import SATVideoDiffusionEngine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cond&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Dict&amp;lt;/code&amp;gt; || Required || Conditioner output dict containing text embeddings (crossattn, vector, concat keys)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;uc&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Dict&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; || Unconditional conditioner output for classifier-free guidance&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;batch_size&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; || Number of samples to generate in parallel&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;shape&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Tuple[int, ...]&amp;lt;/code&amp;gt; || Required || Latent shape &amp;lt;code&amp;gt;(T, C, H//F, W//F)&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;F=8&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;concat_images&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.Tensor&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; || Image latents for I2V mode, concatenated along channel dimension&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ofs&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.Tensor&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; || Temporal offset embedding for I2V, typically &amp;lt;code&amp;gt;[2.0]&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Return value || &amp;lt;code&amp;gt;torch.Tensor&amp;lt;/code&amp;gt; || Denoised latent tensor of shape &amp;lt;code&amp;gt;[B, T, C, H//F, W//F]&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Text-to-video sampling&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import torch&lt;br /&gt;
from diffusion_video import SATVideoDiffusionEngine&lt;br /&gt;
&lt;br /&gt;
# Assume model is loaded and args are parsed&lt;br /&gt;
T = args.sampling_num_frames&lt;br /&gt;
H, W = args.sampling_image_size&lt;br /&gt;
C = 16  # Latent channels&lt;br /&gt;
&lt;br /&gt;
# Encode text prompt&lt;br /&gt;
cond = model.conditioner(text_prompt)&lt;br /&gt;
uc = model.conditioner(&amp;quot;&amp;quot;)  # Empty prompt for CFG&lt;br /&gt;
&lt;br /&gt;
with torch.no_grad():&lt;br /&gt;
    samples = model.sample(&lt;br /&gt;
        cond=cond,&lt;br /&gt;
        uc=uc,&lt;br /&gt;
        batch_size=1,&lt;br /&gt;
        shape=(T, C, H // 8, W // 8),&lt;br /&gt;
    )&lt;br /&gt;
# samples shape: [1, T, C, H//8, W//8]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Image-to-video sampling&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import torch&lt;br /&gt;
&lt;br /&gt;
# Encode source image through VAE&lt;br /&gt;
image_latents = model.encode_first_stage(source_image)&lt;br /&gt;
&lt;br /&gt;
# Set I2V offset&lt;br /&gt;
ofs = torch.tensor([2.0], device=&amp;quot;cuda&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
with torch.no_grad():&lt;br /&gt;
    samples = model.sample(&lt;br /&gt;
        cond=cond,&lt;br /&gt;
        uc=uc,&lt;br /&gt;
        batch_size=1,&lt;br /&gt;
        shape=(T, C, H // 8, W // 8),&lt;br /&gt;
        concat_images=image_latents,&lt;br /&gt;
        ofs=ofs,&lt;br /&gt;
    )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_Diffusion_Sampling]] -- Principle governing diffusion sampling with EulerEDM and CFG&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_SAT_Framework_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_SAT_Read_From_CLI_File]] -- Previous step: prompt input&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_SAT_Decode_First_Stage_Export]] -- Next step: decoding latents and exporting video&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_SAT_Get_Model_Load_Checkpoint]] -- Model loading that prepares the model for sampling&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_SAT_Decode_First_Stage_Export&amp;diff=30804</id>
		<title>Implementation:Zai org CogVideo SAT Decode First Stage Export</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_SAT_Decode_First_Stage_Export&amp;diff=30804"/>
		<updated>2026-09-27T10:53:34Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_SAT_Decode_First_Stage_Export}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_SAT_Decode_First_Stage_Export}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || SAT Decode First Stage Export&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || SAT Video Generation&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 5 of 5&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || API Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;sat/diffusion_video.py:L197-229&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sat/sample_video.py:L120-134&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;External Dependencies&#039;&#039;&#039; || imageio, einops, torch, numpy&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of the VAE decoding and video export steps in the SAT video generation pipeline. The &amp;lt;code&amp;gt;decode_first_stage&amp;lt;/code&amp;gt; method converts diffusion latents to pixel-space video, and &amp;lt;code&amp;gt;save_video_as_grid_and_mp4&amp;lt;/code&amp;gt; exports the decoded frames as a playable MP4 file.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
Two functions work together to produce the final video output:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;SATVideoDiffusionEngine.decode_first_stage(z)&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Takes the denoised latent tensor, applies inverse scale factor, passes through the 3D VAE decoder, and returns pixel-space frames. Context-parallel decoding distributes temporal chunks across available GPUs.&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;save_video_as_grid_and_mp4(samples, save_path, fps)&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Takes the decoded video tensor, rearranges dimensions using einops, clamps and normalizes values to &amp;lt;code&amp;gt;[0, 255]&amp;lt;/code&amp;gt;, converts to numpy uint8, and writes to MP4 using imageio.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# After sampling&lt;br /&gt;
with torch.no_grad():&lt;br /&gt;
    decoded = model.decode_first_stage(samples)&lt;br /&gt;
&lt;br /&gt;
save_video_as_grid_and_mp4(decoded, save_path=&amp;quot;output/video_001.mp4&amp;quot;, fps=8)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sat/diffusion_video.py&amp;lt;/code&amp;gt; || L197-229 || &amp;lt;code&amp;gt;decode_first_stage&amp;lt;/code&amp;gt; method&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sat/sample_video.py&amp;lt;/code&amp;gt; || L120-134 || &amp;lt;code&amp;gt;save_video_as_grid_and_mp4&amp;lt;/code&amp;gt; function&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class SATVideoDiffusionEngine:&lt;br /&gt;
    def decode_first_stage(self, z: torch.Tensor) -&amp;gt; torch.Tensor:&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;Decode latents to pixel space.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def save_video_as_grid_and_mp4(samples: torch.Tensor, save_path: str, fps: int):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Save decoded video tensor as MP4 using imageio.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from diffusion_video import SATVideoDiffusionEngine&lt;br /&gt;
from sample_video import save_video_as_grid_and_mp4&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;decode_first_stage&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;z&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.Tensor&amp;lt;/code&amp;gt; || Required || Denoised latent tensor of shape &amp;lt;code&amp;gt;[B, T, C, H//8, W//8]&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;save_video_as_grid_and_mp4&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;samples&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.Tensor&amp;lt;/code&amp;gt; || Required || Decoded video tensor in pixel space&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;save_path&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Required || Output file path for the MP4 video&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;fps&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || Required || Frames per second for the output video (default 8 from args)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;decode_first_stage&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Return value || &amp;lt;code&amp;gt;torch.Tensor&amp;lt;/code&amp;gt; || Pixel-space video tensor of shape &amp;lt;code&amp;gt;[B, C, T, H, W]&amp;lt;/code&amp;gt; with values in &amp;lt;code&amp;gt;[-1, 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;save_video_as_grid_and_mp4&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Side effect || MP4 file || Video file written to &amp;lt;code&amp;gt;save_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Full decode and export pipeline&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import torch&lt;br /&gt;
from diffusion_video import SATVideoDiffusionEngine&lt;br /&gt;
from sample_video import save_video_as_grid_and_mp4&lt;br /&gt;
&lt;br /&gt;
# After diffusion sampling produces denoised latents&lt;br /&gt;
with torch.no_grad():&lt;br /&gt;
    decoded_video = model.decode_first_stage(samples)&lt;br /&gt;
&lt;br /&gt;
# Save as MP4&lt;br /&gt;
save_video_as_grid_and_mp4(&lt;br /&gt;
    samples=decoded_video,&lt;br /&gt;
    save_path=&amp;quot;outputs/generated_video.mp4&amp;quot;,&lt;br /&gt;
    fps=8&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Batch export with custom FPS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
output_dir = &amp;quot;outputs/batch_run&amp;quot;&lt;br /&gt;
os.makedirs(output_dir, exist_ok=True)&lt;br /&gt;
&lt;br /&gt;
for idx, sample in enumerate(all_samples):&lt;br /&gt;
    with torch.no_grad():&lt;br /&gt;
        decoded = model.decode_first_stage(sample.unsqueeze(0))&lt;br /&gt;
    save_video_as_grid_and_mp4(&lt;br /&gt;
        decoded,&lt;br /&gt;
        save_path=os.path.join(output_dir, f&amp;quot;video_{idx:04d}.mp4&amp;quot;),&lt;br /&gt;
        fps=args.sampling_fps&lt;br /&gt;
    )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_SAT_Video_Decoding_and_Export]] -- Principle governing VAE decoding and video export&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_SAT_Framework_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_SAT_Diffusion_Sample]] -- Previous step: diffusion sampling that produces the latents&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_SAT_Inference_Get_Args]] -- Configuration providing FPS and output path parameters&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_Get_Video_Frames&amp;diff=30803</id>
		<title>Implementation:Zai org CogVideo Get Video Frames</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_Get_Video_Frames&amp;diff=30803"/>
		<updated>2026-09-27T10:53:33Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_Get_Video_Frames}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_Get_Video_Frames}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || Get Video Frames&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || Video Editing DDIM Inversion&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 1 of 6&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || API Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;inference/ddim_inversion.py:L263-300&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;External Dependencies&#039;&#039;&#039; || decord, torchvision.transforms&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of video loading, frame sampling, resizing, and normalization for the DDIM inversion pipeline. The &amp;lt;code&amp;gt;get_video_frames&amp;lt;/code&amp;gt; function produces a tensor of preprocessed frames ready for VAE encoding.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;get_video_frames&amp;lt;/code&amp;gt; function performs:&lt;br /&gt;
&lt;br /&gt;
# Loads the video file using decord&#039;s &amp;lt;code&amp;gt;VideoReader&amp;lt;/code&amp;gt;&lt;br /&gt;
# Applies start/end frame skipping&lt;br /&gt;
# Samples frames to the target count using uniform stepping or automatic stride calculation&lt;br /&gt;
# Resizes frames to the target resolution using torchvision transforms&lt;br /&gt;
# Normalizes pixel values from &amp;lt;code&amp;gt;[0, 255]&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;[-1, 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The function enforces the VAE constraint that the frame count must satisfy &amp;lt;code&amp;gt;(F mod 4) == 1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from inference.ddim_inversion import get_video_frames&lt;br /&gt;
&lt;br /&gt;
video_frames = get_video_frames(&lt;br /&gt;
    video_path=&amp;quot;input_video.mp4&amp;quot;,&lt;br /&gt;
    width=720,&lt;br /&gt;
    height=480,&lt;br /&gt;
    max_num_frames=81,&lt;br /&gt;
)&lt;br /&gt;
# video_frames shape: [F, C, H, W] in [-1, 1]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;inference/ddim_inversion.py&amp;lt;/code&amp;gt; || L263-300 || &amp;lt;code&amp;gt;get_video_frames&amp;lt;/code&amp;gt; function&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def get_video_frames(&lt;br /&gt;
    video_path: str,&lt;br /&gt;
    width: int = 720,&lt;br /&gt;
    height: int = 480,&lt;br /&gt;
    skip_frames_start: int = 0,&lt;br /&gt;
    skip_frames_end: int = 0,&lt;br /&gt;
    max_num_frames: int = 81,&lt;br /&gt;
    frame_sample_step: Optional[int] = None,&lt;br /&gt;
) -&amp;gt; torch.FloatTensor:  # [F, C, H, W] in [-1, 1]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from inference.ddim_inversion import get_video_frames&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;video_path&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Required || Path to the input video file&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;width&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;720&amp;lt;/code&amp;gt; || Target width for resizing&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;height&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;480&amp;lt;/code&amp;gt; || Target height for resizing&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;skip_frames_start&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; || Number of frames to skip at the beginning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;skip_frames_end&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; || Number of frames to skip at the end&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;max_num_frames&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;81&amp;lt;/code&amp;gt; || Maximum number of frames to sample (must satisfy &amp;lt;code&amp;gt;F mod 4 == 1&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;frame_sample_step&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Optional[int]&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; || Explicit frame sampling step; if None, computed automatically&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Return value || &amp;lt;code&amp;gt;torch.FloatTensor&amp;lt;/code&amp;gt; || Video frames tensor of shape &amp;lt;code&amp;gt;[F, C, H, W]&amp;lt;/code&amp;gt; with values in &amp;lt;code&amp;gt;[-1, 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Default loading&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from inference.ddim_inversion import get_video_frames&lt;br /&gt;
&lt;br /&gt;
frames = get_video_frames(&amp;quot;input.mp4&amp;quot;)&lt;br /&gt;
# frames.shape: [81, 3, 480, 720]&lt;br /&gt;
# frames.dtype: torch.float32&lt;br /&gt;
# frames.min() &amp;gt;= -1.0, frames.max() &amp;lt;= 1.0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Custom resolution and frame count&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
frames = get_video_frames(&lt;br /&gt;
    &amp;quot;input.mp4&amp;quot;,&lt;br /&gt;
    width=1360,&lt;br /&gt;
    height=768,&lt;br /&gt;
    max_num_frames=49,&lt;br /&gt;
    skip_frames_start=10,&lt;br /&gt;
    skip_frames_end=5,&lt;br /&gt;
)&lt;br /&gt;
# frames.shape: [49, 3, 768, 1360]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 3: Explicit frame sampling step&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
frames = get_video_frames(&lt;br /&gt;
    &amp;quot;input.mp4&amp;quot;,&lt;br /&gt;
    frame_sample_step=3,  # Take every 3rd frame&lt;br /&gt;
    max_num_frames=25,&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_Video_Loading_and_Preprocessing]] -- Principle governing video loading and preprocessing&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_Diffusers_Inference_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_Encode_Video_Frames]] -- Next step: encoding frames to latent space&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_DDIM_CogVideoXPipeline_From_Pretrained]] -- Pipeline providing the VAE for subsequent encoding&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_Encode_Video_Frames&amp;diff=30802</id>
		<title>Implementation:Zai org CogVideo Encode Video Frames</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_Encode_Video_Frames&amp;diff=30802"/>
		<updated>2026-09-27T10:53:33Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_Encode_Video_Frames}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_Encode_Video_Frames}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || Encode Video Frames&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || Video Editing DDIM Inversion&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 3 of 6&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || API Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;inference/ddim_inversion.py:L303-309&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;External Dependencies&#039;&#039;&#039; || diffusers (AutoencoderKLCogVideoX)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of video frame encoding using the CogVideoX 3D VAE. The &amp;lt;code&amp;gt;encode_video_frames&amp;lt;/code&amp;gt; function converts preprocessed video frames from pixel space into the latent representation used by the diffusion model.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;encode_video_frames&amp;lt;/code&amp;gt; function:&lt;br /&gt;
&lt;br /&gt;
# Accepts preprocessed video frames as a &amp;lt;code&amp;gt;[F, C, H, W]&amp;lt;/code&amp;gt; tensor&lt;br /&gt;
# Rearranges the tensor to match the VAE&#039;s expected input format&lt;br /&gt;
# Passes through the VAE encoder to obtain latent distribution parameters&lt;br /&gt;
# Samples from the distribution and applies the scaling factor&lt;br /&gt;
# Returns the latent tensor in &amp;lt;code&amp;gt;[B, T, C, H&#039;, W&#039;]&amp;lt;/code&amp;gt; format&lt;br /&gt;
&lt;br /&gt;
The function wraps the VAE&#039;s encode method and handles the scaling factor application in a single call.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from inference.ddim_inversion import encode_video_frames&lt;br /&gt;
&lt;br /&gt;
latents = encode_video_frames(pipe.vae, video_frames)&lt;br /&gt;
# latents shape: [B, T, C, H&#039;, W&#039;]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;inference/ddim_inversion.py&amp;lt;/code&amp;gt; || L303-309 || &amp;lt;code&amp;gt;encode_video_frames&amp;lt;/code&amp;gt; function&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def encode_video_frames(&lt;br /&gt;
    vae: AutoencoderKLCogVideoX,&lt;br /&gt;
    video_frames: torch.FloatTensor  # [F, C, H, W]&lt;br /&gt;
) -&amp;gt; torch.FloatTensor:  # [B, T, C, H&#039;, W&#039;]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from inference.ddim_inversion import encode_video_frames&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;vae&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;AutoencoderKLCogVideoX&amp;lt;/code&amp;gt; || Required || The 3D VAE from the loaded CogVideoX pipeline (&amp;lt;code&amp;gt;pipe.vae&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;video_frames&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.FloatTensor&amp;lt;/code&amp;gt; || Required || Preprocessed video frames of shape &amp;lt;code&amp;gt;[F, C, H, W]&amp;lt;/code&amp;gt; with values in &amp;lt;code&amp;gt;[-1, 1]&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Return value || &amp;lt;code&amp;gt;torch.FloatTensor&amp;lt;/code&amp;gt; || Latent tensor of shape &amp;lt;code&amp;gt;[B, T, C, H&#039;, W&#039;]&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;H&#039; = H // 8&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;W&#039; = W // 8&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;T&amp;lt;/code&amp;gt; is the temporally compressed frame count&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Basic video encoding&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from inference.ddim_inversion import get_video_frames, encode_video_frames&lt;br /&gt;
from diffusers import CogVideoXPipeline&lt;br /&gt;
import torch&lt;br /&gt;
&lt;br /&gt;
pipe = CogVideoXPipeline.from_pretrained(&lt;br /&gt;
    &amp;quot;THUDM/CogVideoX-5b&amp;quot;, torch_dtype=torch.bfloat16&lt;br /&gt;
).to(&amp;quot;cuda&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Load and preprocess video&lt;br /&gt;
video_frames = get_video_frames(&amp;quot;input.mp4&amp;quot;, width=720, height=480)&lt;br /&gt;
&lt;br /&gt;
# Encode to latent space&lt;br /&gt;
latents = encode_video_frames(pipe.vae, video_frames)&lt;br /&gt;
# latents.shape: [1, T, 16, 60, 90] for 480x720 input&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Encoding as part of the inversion pipeline&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Encode video frames&lt;br /&gt;
video_frames = get_video_frames(video_path, width=720, height=480, max_num_frames=49)&lt;br /&gt;
latents = encode_video_frames(pipe.vae, video_frames)&lt;br /&gt;
&lt;br /&gt;
# latents are now ready for DDIM inversion&lt;br /&gt;
inverted = sample(pipe, latents, inverse_scheduler, prompt=&amp;quot;&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_Video_Encoding]] -- Principle governing video encoding with the 3D VAE&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_Diffusers_Inference_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_Get_Video_Frames]] -- Previous step: video loading and preprocessing&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_DDIM_Inversion_Sample]] -- Next step: DDIM inversion of the encoded latents&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_DDIM_Export_Latents_To_Video]] -- Decoding that inverts this encoding step&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_DDIM_Inversion_Sample&amp;diff=30801</id>
		<title>Implementation:Zai org CogVideo DDIM Inversion Sample</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_DDIM_Inversion_Sample&amp;diff=30801"/>
		<updated>2026-09-27T10:53:32Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_DDIM_Inversion_Sample}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_DDIM_Inversion_Sample}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || DDIM Inversion Sample&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || Video Editing DDIM Inversion&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 4 of 6&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || API Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;inference/ddim_inversion.py:L321-452&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;inference/ddim_inversion.py:L489-498&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;External Dependencies&#039;&#039;&#039; || diffusers, torch&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of the DDIM inversion sampling function. The &amp;lt;code&amp;gt;sample&amp;lt;/code&amp;gt; function serves dual purpose: it performs both DDIM inversion (when called with the inverse scheduler and empty prompt) and forward DDIM reconstruction (when called with the forward scheduler and edit prompt). The function stores the full latent trajectory for use in attention injection.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;sample&amp;lt;/code&amp;gt; function implements the core DDIM loop:&lt;br /&gt;
&lt;br /&gt;
# Sets up the scheduler timesteps for the specified number of inference steps&lt;br /&gt;
# Encodes the prompt (or empty string for inversion) using the pipeline&#039;s text encoder&lt;br /&gt;
# Iterates over timesteps, at each step:&lt;br /&gt;
#* Concatenates the latent with itself for classifier-free guidance (if guidance_scale &amp;gt; 1)&lt;br /&gt;
#* Runs the transformer forward pass to predict noise&lt;br /&gt;
#* Applies CFG to combine conditional and unconditional predictions&lt;br /&gt;
#* Steps the scheduler (forward for reconstruction, inverse for inversion)&lt;br /&gt;
#* Stores the latent in the trajectory&lt;br /&gt;
# Returns the complete trajectory tensor&lt;br /&gt;
&lt;br /&gt;
For inversion specifically (lines L489-498): the function is called with &amp;lt;code&amp;gt;DDIMInverseScheduler&amp;lt;/code&amp;gt;, an empty prompt, and &amp;lt;code&amp;gt;reference_latents=None&amp;lt;/code&amp;gt;. The trajectory is then reversed and passed as &amp;lt;code&amp;gt;reference_latents&amp;lt;/code&amp;gt; to the reconstruction call.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from inference.ddim_inversion import sample&lt;br /&gt;
&lt;br /&gt;
# Inversion&lt;br /&gt;
inversion_trajectory = sample(&lt;br /&gt;
    pipeline=pipe,&lt;br /&gt;
    latents=encoded_latents,&lt;br /&gt;
    scheduler=inverse_scheduler,&lt;br /&gt;
    prompt=&amp;quot;&amp;quot;,&lt;br /&gt;
    num_inference_steps=50,&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;inference/ddim_inversion.py&amp;lt;/code&amp;gt; || L321-452 || &amp;lt;code&amp;gt;sample&amp;lt;/code&amp;gt; function (main DDIM loop)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;inference/ddim_inversion.py&amp;lt;/code&amp;gt; || L489-498 || Inversion call site&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def sample(&lt;br /&gt;
    pipeline: CogVideoXPipeline,&lt;br /&gt;
    latents: torch.FloatTensor,&lt;br /&gt;
    scheduler: Union[DDIMInverseScheduler, CogVideoXDDIMScheduler],&lt;br /&gt;
    prompt: Optional[str] = None,&lt;br /&gt;
    num_inference_steps: int = 50,&lt;br /&gt;
    guidance_scale: float = 6.0,&lt;br /&gt;
    generator: Optional[torch.Generator] = None,&lt;br /&gt;
    reference_latents: torch.FloatTensor = None,&lt;br /&gt;
) -&amp;gt; torch.FloatTensor:  # trajectory [num_steps, B, T, C, H&#039;, W&#039;]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from inference.ddim_inversion import sample&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pipeline&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;CogVideoXPipeline&amp;lt;/code&amp;gt; || Required || Loaded CogVideoX pipeline with transformer, text encoder, and VAE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;latents&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.FloatTensor&amp;lt;/code&amp;gt; || Required || Starting latents: encoded video for inversion, or random noise for reconstruction&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;scheduler&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Union[DDIMInverseScheduler, CogVideoXDDIMScheduler]&amp;lt;/code&amp;gt; || Required || Inverse scheduler for inversion, forward scheduler for reconstruction&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;prompt&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Optional[str]&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; || Text prompt; empty string for inversion, edit prompt for reconstruction&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;num_inference_steps&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;50&amp;lt;/code&amp;gt; || Number of DDIM steps&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;guidance_scale&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;6.0&amp;lt;/code&amp;gt; || Classifier-free guidance scale&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;generator&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Optional[torch.Generator]&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; || Random number generator for reproducibility&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;reference_latents&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.FloatTensor&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;None&amp;lt;/code&amp;gt; || Inversion trajectory for attention injection during reconstruction; None for inversion&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Return value || &amp;lt;code&amp;gt;torch.FloatTensor&amp;lt;/code&amp;gt; || Latent trajectory tensor of shape &amp;lt;code&amp;gt;[num_steps, B, T, C, H&#039;, W&#039;]&amp;lt;/code&amp;gt; containing latents at each timestep&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: DDIM inversion (finding noise representation)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from diffusers import DDIMInverseScheduler&lt;br /&gt;
from inference.ddim_inversion import sample, encode_video_frames, get_video_frames&lt;br /&gt;
&lt;br /&gt;
# Prepare inverse scheduler&lt;br /&gt;
inverse_scheduler = DDIMInverseScheduler.from_config(pipe.scheduler.config)&lt;br /&gt;
&lt;br /&gt;
# Load and encode video&lt;br /&gt;
video_frames = get_video_frames(&amp;quot;input.mp4&amp;quot;)&lt;br /&gt;
latents = encode_video_frames(pipe.vae, video_frames)&lt;br /&gt;
&lt;br /&gt;
# Run inversion&lt;br /&gt;
inversion_trajectory = sample(&lt;br /&gt;
    pipeline=pipe,&lt;br /&gt;
    latents=latents,&lt;br /&gt;
    scheduler=inverse_scheduler,&lt;br /&gt;
    prompt=&amp;quot;&amp;quot;,  # Empty prompt for unconditional inversion&lt;br /&gt;
    num_inference_steps=50,&lt;br /&gt;
    guidance_scale=1.0,  # No CFG during inversion&lt;br /&gt;
)&lt;br /&gt;
# inversion_trajectory.shape: [50, 1, T, 16, H&#039;, W&#039;]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Forward reconstruction (verifying inversion quality)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from diffusers import CogVideoXDDIMScheduler&lt;br /&gt;
&lt;br /&gt;
forward_scheduler = CogVideoXDDIMScheduler.from_config(pipe.scheduler.config)&lt;br /&gt;
&lt;br /&gt;
# Reverse the trajectory for reconstruction&lt;br /&gt;
reversed_trajectory = inversion_trajectory.flip(0)&lt;br /&gt;
&lt;br /&gt;
reconstruction = sample(&lt;br /&gt;
    pipeline=pipe,&lt;br /&gt;
    latents=inversion_trajectory[-1],  # Start from noise&lt;br /&gt;
    scheduler=forward_scheduler,&lt;br /&gt;
    prompt=&amp;quot;original prompt&amp;quot;,&lt;br /&gt;
    num_inference_steps=50,&lt;br /&gt;
    reference_latents=reversed_trajectory,&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_DDIM_Inversion]] -- Principle governing DDIM inversion&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_Diffusers_Inference_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_Encode_Video_Frames]] -- Previous step: video encoding that produces input latents&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_DDIM_Attention_Injection_Reconstruction]] -- Next step: prompted reconstruction with attention injection&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_DDIM_Export_Latents_To_Video]] -- Export step for trajectory endpoints&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_DDIM_Export_Latents_To_Video&amp;diff=30800</id>
		<title>Implementation:Zai org CogVideo DDIM Export Latents To Video</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_DDIM_Export_Latents_To_Video&amp;diff=30800"/>
		<updated>2026-09-27T10:53:31Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_DDIM_Export_Latents_To_Video}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_DDIM_Export_Latents_To_Video}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || DDIM Export Latents To Video&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || Video Editing DDIM Inversion&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 6 of 6&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || API Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;inference/ddim_inversion.py:L312-317&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;External Dependencies&#039;&#039;&#039; || diffusers (CogVideoXPipeline)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of the latent-to-video export function for the DDIM inversion pipeline. The &amp;lt;code&amp;gt;export_latents_to_video&amp;lt;/code&amp;gt; function decodes latent tensors through the pipeline&#039;s VAE and saves the result as an MP4 video file.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;export_latents_to_video&amp;lt;/code&amp;gt; function:&lt;br /&gt;
&lt;br /&gt;
# Calls &amp;lt;code&amp;gt;pipeline.decode_latents(latents)&amp;lt;/code&amp;gt; to convert latent-space tensors to pixel-space video&lt;br /&gt;
# Calls &amp;lt;code&amp;gt;pipeline.video_processor.postprocess_video(video, output_type=&amp;quot;pil&amp;quot;)&amp;lt;/code&amp;gt; to convert to PIL format&lt;br /&gt;
# Exports the PIL frames as an MP4 video file at the specified FPS using &amp;lt;code&amp;gt;export_to_video&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function is called twice in the typical DDIM editing workflow: once for the inversion reconstruction (to verify quality) and once for the edited reconstruction.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from inference.ddim_inversion import export_latents_to_video&lt;br /&gt;
&lt;br /&gt;
# Export the final trajectory step as video&lt;br /&gt;
export_latents_to_video(pipe, trajectory[-1], &amp;quot;output.mp4&amp;quot;, fps=8)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;inference/ddim_inversion.py&amp;lt;/code&amp;gt; || L312-317 || &amp;lt;code&amp;gt;export_latents_to_video&amp;lt;/code&amp;gt; function&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def export_latents_to_video(&lt;br /&gt;
    pipeline: CogVideoXPipeline,&lt;br /&gt;
    latents: torch.FloatTensor,&lt;br /&gt;
    video_path: str,&lt;br /&gt;
    fps: int = 8&lt;br /&gt;
) -&amp;gt; None:&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from inference.ddim_inversion import export_latents_to_video&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pipeline&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;CogVideoXPipeline&amp;lt;/code&amp;gt; || Required || Loaded CogVideoX pipeline with VAE decoder and video processor&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;latents&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.FloatTensor&amp;lt;/code&amp;gt; || Required || Latent tensor of shape &amp;lt;code&amp;gt;[B, T, C, H&#039;, W&#039;]&amp;lt;/code&amp;gt; (typically the final step of a trajectory)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;video_path&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Required || Output file path for the MP4 video&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;fps&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; || Frames per second for the output video&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Side effect || MP4 file || Video file written to &amp;lt;code&amp;gt;video_path&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Export inversion reconstruction for verification&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from inference.ddim_inversion import export_latents_to_video&lt;br /&gt;
&lt;br /&gt;
# After DDIM inversion&lt;br /&gt;
inversion_trajectory = sample(pipe, latents, inverse_scheduler, prompt=&amp;quot;&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Export the inversion reconstruction (should match source video)&lt;br /&gt;
export_latents_to_video(&lt;br /&gt;
    pipeline=pipe,&lt;br /&gt;
    latents=inversion_trajectory[0],  # First step = clean latents&lt;br /&gt;
    video_path=&amp;quot;inversion_verification.mp4&amp;quot;,&lt;br /&gt;
    fps=8&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Export edited reconstruction&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# After prompted reconstruction&lt;br /&gt;
with OverrideAttnProcessors(pipe.transformer):&lt;br /&gt;
    reconstruction = sample(&lt;br /&gt;
        pipe, noise, forward_scheduler,&lt;br /&gt;
        prompt=&amp;quot;A cat running through autumn leaves&amp;quot;,&lt;br /&gt;
        reference_latents=reversed_trajectory,&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
# Export the edited video&lt;br /&gt;
export_latents_to_video(&lt;br /&gt;
    pipeline=pipe,&lt;br /&gt;
    latents=reconstruction[-1],  # Last step = denoised result&lt;br /&gt;
    video_path=&amp;quot;edited_video.mp4&amp;quot;,&lt;br /&gt;
    fps=8&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 3: Side-by-side comparison&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Export both for comparison&lt;br /&gt;
export_latents_to_video(pipe, inversion_trajectory[0],&lt;br /&gt;
                        &amp;quot;original_reconstruction.mp4&amp;quot;, fps=8)&lt;br /&gt;
export_latents_to_video(pipe, reconstruction[-1],&lt;br /&gt;
                        &amp;quot;edited_result.mp4&amp;quot;, fps=8)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_DDIM_Video_Export]] -- Principle governing latent decoding and video export&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_Diffusers_Inference_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_DDIM_Attention_Injection_Reconstruction]] -- Previous step: prompted reconstruction&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_DDIM_Inversion_Sample]] -- Inversion step producing the trajectory to export&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_Encode_Video_Frames]] -- Encoding step that is inverted by this export&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_DDIM_CogVideoXPipeline_From_Pretrained&amp;diff=30799</id>
		<title>Implementation:Zai org CogVideo DDIM CogVideoXPipeline From Pretrained</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_DDIM_CogVideoXPipeline_From_Pretrained&amp;diff=30799"/>
		<updated>2026-09-27T10:53:30Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_DDIM_CogVideoXPipeline_From_Pretrained}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_DDIM_CogVideoXPipeline_From_Pretrained}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || DDIM CogVideoXPipeline From Pretrained&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || Video Editing DDIM Inversion&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 2 of 6&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || Wrapper Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;inference/ddim_inversion.py:L474-478&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;External Dependencies&#039;&#039;&#039; || diffusers (CogVideoXPipeline)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of the CogVideoX pipeline loading for DDIM inversion. The pipeline is loaded from a pretrained CogVideoX-5B model path with bfloat16 precision and moved directly to CUDA.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The pipeline loading is a straightforward call to &amp;lt;code&amp;gt;CogVideoXPipeline.from_pretrained&amp;lt;/code&amp;gt; with two key constraints:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Model variant&#039;&#039;&#039;: Must use a CogVideoX-5B variant (requires rotary positional embeddings). The 2B variant is not supported.&lt;br /&gt;
# &#039;&#039;&#039;No CPU offloading&#039;&#039;&#039;: The pipeline is loaded directly to GPU via &amp;lt;code&amp;gt;.to(device=&amp;quot;cuda&amp;quot;)&amp;lt;/code&amp;gt; rather than using &amp;lt;code&amp;gt;enable_model_cpu_offload()&amp;lt;/code&amp;gt;, since both forward and inverse passes are needed in the same session.&lt;br /&gt;
&lt;br /&gt;
The loaded pipeline provides access to all components needed for DDIM inversion: &amp;lt;code&amp;gt;pipe.vae&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;pipe.transformer&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;pipe.text_encoder&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;pipe.tokenizer&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;pipe.scheduler&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from diffusers import CogVideoXPipeline&lt;br /&gt;
import torch&lt;br /&gt;
&lt;br /&gt;
pipe = CogVideoXPipeline.from_pretrained(&lt;br /&gt;
    &amp;quot;THUDM/CogVideoX-5b&amp;quot;,&lt;br /&gt;
    torch_dtype=torch.bfloat16&lt;br /&gt;
).to(device=&amp;quot;cuda&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;inference/ddim_inversion.py&amp;lt;/code&amp;gt; || L474-478 || Pipeline loading&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
pipe = CogVideoXPipeline.from_pretrained(&lt;br /&gt;
    model_path: str,  # Must be CogVideoX-5B variant&lt;br /&gt;
    torch_dtype: torch.dtype = torch.bfloat16&lt;br /&gt;
).to(device=&amp;quot;cuda&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from diffusers import CogVideoXPipeline&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;model_path&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Required || Path or HuggingFace model ID for a CogVideoX-5B variant (e.g., &amp;lt;code&amp;gt;&amp;quot;THUDM/CogVideoX-5b&amp;quot;&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;torch_dtype&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.dtype&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.bfloat16&amp;lt;/code&amp;gt; || Model precision; bfloat16 recommended for memory efficiency&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pipe&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;CogVideoXPipeline&amp;lt;/code&amp;gt; || Loaded pipeline on CUDA with VAE, transformer, text encoder, tokenizer, and scheduler&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Load from HuggingFace Hub&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from diffusers import CogVideoXPipeline&lt;br /&gt;
import torch&lt;br /&gt;
&lt;br /&gt;
pipe = CogVideoXPipeline.from_pretrained(&lt;br /&gt;
    &amp;quot;THUDM/CogVideoX-5b&amp;quot;,&lt;br /&gt;
    torch_dtype=torch.bfloat16&lt;br /&gt;
).to(device=&amp;quot;cuda&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Access pipeline components&lt;br /&gt;
vae = pipe.vae&lt;br /&gt;
transformer = pipe.transformer&lt;br /&gt;
text_encoder = pipe.text_encoder&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Load from local path&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
pipe = CogVideoXPipeline.from_pretrained(&lt;br /&gt;
    &amp;quot;/models/CogVideoX-5b&amp;quot;,&lt;br /&gt;
    torch_dtype=torch.bfloat16&lt;br /&gt;
).to(device=&amp;quot;cuda&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 3: Verify scheduler compatibility&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from diffusers import CogVideoXDDIMScheduler, DDIMInverseScheduler&lt;br /&gt;
&lt;br /&gt;
# The pipeline&#039;s default scheduler can be replaced for inversion&lt;br /&gt;
inverse_scheduler = DDIMInverseScheduler.from_config(pipe.scheduler.config)&lt;br /&gt;
forward_scheduler = CogVideoXDDIMScheduler.from_config(pipe.scheduler.config)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_DDIM_Pipeline_Loading]] -- Principle governing DDIM pipeline loading&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_Diffusers_Inference_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_Get_Video_Frames]] -- Previous step: video frame loading and preprocessing&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_Encode_Video_Frames]] -- Next step: encoding frames using the pipeline&#039;s VAE&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_DDIM_Inversion_Sample]] -- Inversion step using the loaded pipeline&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_DDIM_Attention_Injection_Reconstruction&amp;diff=30798</id>
		<title>Implementation:Zai org CogVideo DDIM Attention Injection Reconstruction</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_DDIM_Attention_Injection_Reconstruction&amp;diff=30798"/>
		<updated>2026-09-27T10:53:30Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_DDIM_Attention_Injection_Reconstruction}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_DDIM_Attention_Injection_Reconstruction}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || DDIM Attention Injection Reconstruction&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || Video Editing DDIM Inversion&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 5 of 6&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || API Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;inference/ddim_inversion.py:L118-243&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;inference/ddim_inversion.py:L246-260&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;inference/ddim_inversion.py:L499-509&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;External Dependencies&#039;&#039;&#039; || diffusers (CogVideoXAttnProcessor2_0, CogVideoXBlock, CogVideoXTransformer3DModel), torch.nn.functional&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of the prompted reconstruction step in the DDIM inversion video editing pipeline. This includes the custom attention processor (&amp;lt;code&amp;gt;CogVideoXAttnProcessor2_0ForDDIMInversion&amp;lt;/code&amp;gt;), the context manager for attention processor replacement (&amp;lt;code&amp;gt;OverrideAttnProcessors&amp;lt;/code&amp;gt;), and the reconstruction call that combines these components.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
Three components work together for prompted reconstruction:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;CogVideoXAttnProcessor2_0ForDDIMInversion&amp;lt;/code&amp;gt;&#039;&#039;&#039; (L118-243): Extends the standard &amp;lt;code&amp;gt;CogVideoXAttnProcessor2_0&amp;lt;/code&amp;gt; to inject reference attention features from the source video&#039;s inversion trajectory. During each attention computation, it blends reference keys/values with current keys/values.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;OverrideAttnProcessors&amp;lt;/code&amp;gt;&#039;&#039;&#039; (L246-260): A Python context manager that temporarily replaces all attention processors in the transformer with the DDIM inversion variant. On entry, it swaps processors; on exit, it restores the originals.&lt;br /&gt;
# &#039;&#039;&#039;Reconstruction call&#039;&#039;&#039; (L499-509): Uses the context manager and calls the &amp;lt;code&amp;gt;sample&amp;lt;/code&amp;gt; function with the forward scheduler, edit prompt, and reversed inversion trajectory as reference latents.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from inference.ddim_inversion import OverrideAttnProcessors, sample&lt;br /&gt;
&lt;br /&gt;
with OverrideAttnProcessors(pipe.transformer):&lt;br /&gt;
    reconstruction_trajectory = sample(&lt;br /&gt;
        pipeline=pipe,&lt;br /&gt;
        latents=torch.randn_like(latents),&lt;br /&gt;
        scheduler=pipe.scheduler,&lt;br /&gt;
        prompt=edit_prompt,&lt;br /&gt;
        reference_latents=reversed_inversion_trajectory,&lt;br /&gt;
    )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;inference/ddim_inversion.py&amp;lt;/code&amp;gt; || L118-243 || &amp;lt;code&amp;gt;CogVideoXAttnProcessor2_0ForDDIMInversion&amp;lt;/code&amp;gt; class&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;inference/ddim_inversion.py&amp;lt;/code&amp;gt; || L246-260 || &amp;lt;code&amp;gt;OverrideAttnProcessors&amp;lt;/code&amp;gt; context manager&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;inference/ddim_inversion.py&amp;lt;/code&amp;gt; || L499-509 || Reconstruction call site&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class CogVideoXAttnProcessor2_0ForDDIMInversion(CogVideoXAttnProcessor2_0):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Custom attention processor that injects reference attention features.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
class OverrideAttnProcessors:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Context manager to temporarily replace attention processors.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    def __init__(self, transformer: CogVideoXTransformer3DModel): ...&lt;br /&gt;
&lt;br /&gt;
# Usage:&lt;br /&gt;
with OverrideAttnProcessors(pipe.transformer):&lt;br /&gt;
    reconstruction_trajectory = sample(&lt;br /&gt;
        pipeline=pipe,&lt;br /&gt;
        latents=torch.randn_like(latents),&lt;br /&gt;
        scheduler=pipe.scheduler,  # CogVideoXDDIMScheduler&lt;br /&gt;
        prompt=edit_prompt,&lt;br /&gt;
        reference_latents=reversed_inversion_trajectory,&lt;br /&gt;
    )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from inference.ddim_inversion import (&lt;br /&gt;
    CogVideoXAttnProcessor2_0ForDDIMInversion,&lt;br /&gt;
    OverrideAttnProcessors,&lt;br /&gt;
    sample,&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;CogVideoXAttnProcessor2_0ForDDIMInversion&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Inherits from &amp;lt;code&amp;gt;CogVideoXAttnProcessor2_0&amp;lt;/code&amp;gt; || -- || -- || All standard attention processor inputs (hidden_states, encoder_hidden_states, attention_mask, etc.)&lt;br /&gt;
|-&lt;br /&gt;
| Reference features || &amp;lt;code&amp;gt;torch.FloatTensor&amp;lt;/code&amp;gt; || Via reference_latents || Attention keys/values from the inversion trajectory at the current timestep&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;OverrideAttnProcessors&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;transformer&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;CogVideoXTransformer3DModel&amp;lt;/code&amp;gt; || Required || The pipeline&#039;s transformer model whose attention processors will be replaced&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Reconstruction call&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pipeline&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;CogVideoXPipeline&amp;lt;/code&amp;gt; || Required || Loaded CogVideoX pipeline&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;latents&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.FloatTensor&amp;lt;/code&amp;gt; || Required || Random noise tensor (same shape as encoded video latents)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;scheduler&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;CogVideoXDDIMScheduler&amp;lt;/code&amp;gt; || Required || Forward DDIM scheduler&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;prompt&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Required || Edit prompt describing the desired output&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;reference_latents&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.FloatTensor&amp;lt;/code&amp;gt; || Required || Reversed inversion trajectory of shape &amp;lt;code&amp;gt;[num_steps, B, T, C, H&#039;, W&#039;]&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;reconstruction_trajectory&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.FloatTensor&amp;lt;/code&amp;gt; || Reconstruction trajectory of shape &amp;lt;code&amp;gt;[num_steps, B, T, C, H&#039;, W&#039;]&amp;lt;/code&amp;gt;; final step contains the edited video latents&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Full video editing pipeline&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from diffusers import CogVideoXPipeline, CogVideoXDDIMScheduler, DDIMInverseScheduler&lt;br /&gt;
from inference.ddim_inversion import (&lt;br /&gt;
    get_video_frames, encode_video_frames, sample,&lt;br /&gt;
    OverrideAttnProcessors, export_latents_to_video,&lt;br /&gt;
)&lt;br /&gt;
import torch&lt;br /&gt;
&lt;br /&gt;
# Load pipeline&lt;br /&gt;
pipe = CogVideoXPipeline.from_pretrained(&lt;br /&gt;
    &amp;quot;THUDM/CogVideoX-5b&amp;quot;, torch_dtype=torch.bfloat16&lt;br /&gt;
).to(&amp;quot;cuda&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Prepare schedulers&lt;br /&gt;
inverse_scheduler = DDIMInverseScheduler.from_config(pipe.scheduler.config)&lt;br /&gt;
forward_scheduler = CogVideoXDDIMScheduler.from_config(pipe.scheduler.config)&lt;br /&gt;
&lt;br /&gt;
# Load and encode video&lt;br /&gt;
video_frames = get_video_frames(&amp;quot;input.mp4&amp;quot;)&lt;br /&gt;
latents = encode_video_frames(pipe.vae, video_frames)&lt;br /&gt;
&lt;br /&gt;
# Step 1: Inversion&lt;br /&gt;
inversion_trajectory = sample(&lt;br /&gt;
    pipe, latents, inverse_scheduler, prompt=&amp;quot;&amp;quot;, num_inference_steps=50&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
# Step 2: Reconstruction with edit&lt;br /&gt;
reversed_trajectory = inversion_trajectory.flip(0)&lt;br /&gt;
&lt;br /&gt;
with OverrideAttnProcessors(pipe.transformer):&lt;br /&gt;
    reconstruction = sample(&lt;br /&gt;
        pipe,&lt;br /&gt;
        torch.randn_like(latents),&lt;br /&gt;
        forward_scheduler,&lt;br /&gt;
        prompt=&amp;quot;A dog playing in snow&amp;quot;,&lt;br /&gt;
        reference_latents=reversed_trajectory,&lt;br /&gt;
        num_inference_steps=50,&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
# Export edited video&lt;br /&gt;
export_latents_to_video(pipe, reconstruction[-1], &amp;quot;edited_output.mp4&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Using the context manager pattern&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# The OverrideAttnProcessors context manager ensures&lt;br /&gt;
# original processors are restored after reconstruction&lt;br /&gt;
with OverrideAttnProcessors(pipe.transformer):&lt;br /&gt;
    # Inside: attention processors are replaced with DDIM inversion variants&lt;br /&gt;
    result = sample(pipe, noise, forward_scheduler, &amp;quot;new prompt&amp;quot;,&lt;br /&gt;
                    reference_latents=ref)&lt;br /&gt;
# Outside: original processors are restored&lt;br /&gt;
&lt;br /&gt;
# Pipeline can be used normally for other tasks&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_Prompted_Reconstruction]] -- Principle governing attention injection and prompted reconstruction&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_Diffusers_Inference_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_DDIM_Inversion_Sample]] -- Previous step: DDIM inversion producing the reference trajectory&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_DDIM_Export_Latents_To_Video]] -- Next step: exporting the edited video&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_DDIM_CogVideoXPipeline_From_Pretrained]] -- Pipeline loading&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_CogVLM2_Predict&amp;diff=30797</id>
		<title>Implementation:Zai org CogVideo CogVLM2 Predict</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_CogVLM2_Predict&amp;diff=30797"/>
		<updated>2026-09-27T10:53:29Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_CogVLM2_Predict}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_CogVLM2_Predict}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || CogVLM2 Predict&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || Video Captioning&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 4 of 5&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || API Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;tools/caption/video_caption.py:L72-100&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;External Dependencies&#039;&#039;&#039; || transformers, torch&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of the caption prediction function for the CogVLM2 video captioning pipeline. The &amp;lt;code&amp;gt;predict&amp;lt;/code&amp;gt; function orchestrates video frame loading, input construction, and autoregressive text generation to produce a natural language description of the video content.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;predict&amp;lt;/code&amp;gt; function:&lt;br /&gt;
&lt;br /&gt;
# Calls &amp;lt;code&amp;gt;load_video(video_data)&amp;lt;/code&amp;gt; to extract representative frames&lt;br /&gt;
# Uses the model&#039;s &amp;lt;code&amp;gt;build_conversation_input_ids&amp;lt;/code&amp;gt; to construct multimodal input&lt;br /&gt;
# Moves all input tensors to the target device with appropriate dtypes&lt;br /&gt;
# Calls &amp;lt;code&amp;gt;model.generate()&amp;lt;/code&amp;gt; with controlled generation parameters&lt;br /&gt;
# Decodes the generated token IDs to text using the tokenizer&lt;br /&gt;
# Returns the caption string&lt;br /&gt;
&lt;br /&gt;
Key generation parameters are hardcoded for deterministic, high-quality captions:&lt;br /&gt;
* &amp;lt;code&amp;gt;max_new_tokens=2048&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;pad_token_id=128002&amp;lt;/code&amp;gt; (Llama3 EOS token)&lt;br /&gt;
* &amp;lt;code&amp;gt;top_k=1&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;do_sample=False&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;top_p=0.1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from tools.caption.video_caption import predict&lt;br /&gt;
&lt;br /&gt;
with open(&amp;quot;video.mp4&amp;quot;, &amp;quot;rb&amp;quot;) as f:&lt;br /&gt;
    video_data = f.read()&lt;br /&gt;
&lt;br /&gt;
caption = predict(&lt;br /&gt;
    prompt=&amp;quot;Please describe this video in detail.&amp;quot;,&lt;br /&gt;
    video_data=video_data,&lt;br /&gt;
    temperature=0.1&lt;br /&gt;
)&lt;br /&gt;
print(caption)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tools/caption/video_caption.py&amp;lt;/code&amp;gt; || L72-100 || &amp;lt;code&amp;gt;predict&amp;lt;/code&amp;gt; function&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def predict(&lt;br /&gt;
    prompt: str,          # e.g. &amp;quot;Please describe this video in detail.&amp;quot;&lt;br /&gt;
    video_data: bytes,    # Raw video file bytes&lt;br /&gt;
    temperature: float    # e.g. 0.1&lt;br /&gt;
) -&amp;gt; str:                 # Generated caption&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from tools.caption.video_caption import predict&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;prompt&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Required || Instruction prompt for the model (e.g., &amp;lt;code&amp;gt;&amp;quot;Please describe this video in detail.&amp;quot;&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;video_data&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; || Required || Raw video file bytes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || Required || Temperature for generation (typically 0.1 for deterministic captions)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Internal generation kwargs (hardcoded)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Value !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;max_new_tokens&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;2048&amp;lt;/code&amp;gt; || Maximum number of tokens to generate&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pad_token_id&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;128002&amp;lt;/code&amp;gt; || Llama3 EOS token ID used for padding&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;top_k&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; || Greedy decoding (select most probable token)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;do_sample&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;False&amp;lt;/code&amp;gt; || Disable stochastic sampling&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;top_p&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;0.1&amp;lt;/code&amp;gt; || Nucleus sampling threshold&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Return value || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Generated caption text describing the video content&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Basic caption generation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from tools.caption.video_caption import predict&lt;br /&gt;
&lt;br /&gt;
with open(&amp;quot;cooking_video.mp4&amp;quot;, &amp;quot;rb&amp;quot;) as f:&lt;br /&gt;
    video_data = f.read()&lt;br /&gt;
&lt;br /&gt;
caption = predict(&lt;br /&gt;
    prompt=&amp;quot;Please describe this video in detail.&amp;quot;,&lt;br /&gt;
    video_data=video_data,&lt;br /&gt;
    temperature=0.1&lt;br /&gt;
)&lt;br /&gt;
print(caption)&lt;br /&gt;
# Output: &amp;quot;The video shows a person in a kitchen preparing a meal.&lt;br /&gt;
#          They begin by chopping vegetables on a wooden cutting board...&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Specific aspect captioning&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
caption = predict(&lt;br /&gt;
    prompt=&amp;quot;Describe the main actions happening in this video.&amp;quot;,&lt;br /&gt;
    video_data=video_data,&lt;br /&gt;
    temperature=0.1&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 3: Batch captioning multiple videos&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
video_dir = &amp;quot;/data/videos/&amp;quot;&lt;br /&gt;
captions = {}&lt;br /&gt;
&lt;br /&gt;
for filename in os.listdir(video_dir):&lt;br /&gt;
    if filename.endswith(&amp;quot;.mp4&amp;quot;):&lt;br /&gt;
        with open(os.path.join(video_dir, filename), &amp;quot;rb&amp;quot;) as f:&lt;br /&gt;
            video_data = f.read()&lt;br /&gt;
        caption = predict(&lt;br /&gt;
            prompt=&amp;quot;Please describe this video in detail.&amp;quot;,&lt;br /&gt;
            video_data=video_data,&lt;br /&gt;
            temperature=0.1&lt;br /&gt;
        )&lt;br /&gt;
        captions[filename] = caption&lt;br /&gt;
        print(f&amp;quot;{filename}: {caption[:100]}...&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_Caption_Generation]] -- Principle governing caption generation&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_Video_Captioning_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_Caption_Load_Video]] -- Frame extraction called internally by predict&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_Caption_File_Output]] -- Next step: saving the generated caption&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_CogVLM2_Model_Loading]] -- Model loading that provides the model and tokenizer used by predict&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_CogVLM2_Model_Loading&amp;diff=30796</id>
		<title>Implementation:Zai org CogVideo CogVLM2 Model Loading</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_CogVLM2_Model_Loading&amp;diff=30796"/>
		<updated>2026-09-27T10:53:28Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_CogVLM2_Model_Loading}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_CogVLM2_Model_Loading}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || CogVLM2 Model Loading&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || Video Captioning&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 2 of 5&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || Wrapper Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;tools/caption/video_caption.py:L60-69&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;External Dependencies&#039;&#039;&#039; || transformers (AutoModelForCausalLM, AutoTokenizer)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of CogVLM2 model and tokenizer loading for the video captioning pipeline. The model is loaded from the HuggingFace Hub or a local path with appropriate precision and set to evaluation mode.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The model loading code:&lt;br /&gt;
&lt;br /&gt;
# Loads the tokenizer using &amp;lt;code&amp;gt;AutoTokenizer.from_pretrained&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;trust_remote_code=True&amp;lt;/code&amp;gt;&lt;br /&gt;
# Loads the model using &amp;lt;code&amp;gt;AutoModelForCausalLM.from_pretrained&amp;lt;/code&amp;gt; with the selected torch dtype&lt;br /&gt;
# Sets the model to eval mode with &amp;lt;code&amp;gt;.eval()&amp;lt;/code&amp;gt;&lt;br /&gt;
# Moves the model to the target device with &amp;lt;code&amp;gt;.to(DEVICE)&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The model path defaults to &amp;lt;code&amp;gt;&amp;quot;THUDM/cogvlm2-llama3-caption&amp;quot;&amp;lt;/code&amp;gt;, a CogVLM2 variant specifically fine-tuned for video captioning.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from transformers import AutoModelForCausalLM, AutoTokenizer&lt;br /&gt;
import torch&lt;br /&gt;
&lt;br /&gt;
MODEL_PATH = &amp;quot;THUDM/cogvlm2-llama3-caption&amp;quot;&lt;br /&gt;
TORCH_TYPE = torch.bfloat16 if torch.cuda.is_bf16_supported() else torch.float16&lt;br /&gt;
DEVICE = &amp;quot;cuda&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)&lt;br /&gt;
model = AutoModelForCausalLM.from_pretrained(&lt;br /&gt;
    MODEL_PATH, torch_dtype=TORCH_TYPE, trust_remote_code=True&lt;br /&gt;
).eval().to(DEVICE)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tools/caption/video_caption.py&amp;lt;/code&amp;gt; || L60-69 || Model and tokenizer loading&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
tokenizer = AutoTokenizer.from_pretrained(&lt;br /&gt;
    MODEL_PATH,  # &amp;quot;THUDM/cogvlm2-llama3-caption&amp;quot;&lt;br /&gt;
    trust_remote_code=True&lt;br /&gt;
)&lt;br /&gt;
model = AutoModelForCausalLM.from_pretrained(&lt;br /&gt;
    MODEL_PATH,&lt;br /&gt;
    torch_dtype=TORCH_TYPE,  # bfloat16 or float16&lt;br /&gt;
    trust_remote_code=True&lt;br /&gt;
).eval().to(DEVICE)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from transformers import AutoModelForCausalLM, AutoTokenizer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MODEL_PATH&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;THUDM/cogvlm2-llama3-caption&amp;quot;&amp;lt;/code&amp;gt; || HuggingFace model ID or local path to CogVLM2 weights&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TORCH_TYPE&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;torch.dtype&amp;lt;/code&amp;gt; || Auto-detected || &amp;lt;code&amp;gt;torch.bfloat16&amp;lt;/code&amp;gt; if supported, else &amp;lt;code&amp;gt;torch.float16&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DEVICE&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;cuda&amp;quot;&amp;lt;/code&amp;gt; || Target device for model inference&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;trust_remote_code&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;True&amp;lt;/code&amp;gt; || Required for CogVLM2 custom model code&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tokenizer&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;AutoTokenizer&amp;lt;/code&amp;gt; || Loaded Llama3-based tokenizer for text encoding/decoding&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;model&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;AutoModelForCausalLM&amp;lt;/code&amp;gt; || Loaded CogVLM2 model in eval mode on target device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Standard loading&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from transformers import AutoModelForCausalLM, AutoTokenizer&lt;br /&gt;
import torch&lt;br /&gt;
&lt;br /&gt;
MODEL_PATH = &amp;quot;THUDM/cogvlm2-llama3-caption&amp;quot;&lt;br /&gt;
TORCH_TYPE = torch.bfloat16 if torch.cuda.is_bf16_supported() else torch.float16&lt;br /&gt;
DEVICE = &amp;quot;cuda&amp;quot;&lt;br /&gt;
&lt;br /&gt;
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)&lt;br /&gt;
model = AutoModelForCausalLM.from_pretrained(&lt;br /&gt;
    MODEL_PATH, torch_dtype=TORCH_TYPE, trust_remote_code=True&lt;br /&gt;
).eval().to(DEVICE)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Loading from local path&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
MODEL_PATH = &amp;quot;/models/cogvlm2-llama3-caption&amp;quot;&lt;br /&gt;
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_code=True)&lt;br /&gt;
model = AutoModelForCausalLM.from_pretrained(&lt;br /&gt;
    MODEL_PATH, torch_dtype=torch.bfloat16, trust_remote_code=True&lt;br /&gt;
).eval().to(&amp;quot;cuda&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 3: Loading with 4-bit quantization&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from transformers import BitsAndBytesConfig&lt;br /&gt;
&lt;br /&gt;
quant_config = BitsAndBytesConfig(&lt;br /&gt;
    load_in_4bit=True,&lt;br /&gt;
    bnb_4bit_compute_dtype=torch.bfloat16,&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
model = AutoModelForCausalLM.from_pretrained(&lt;br /&gt;
    MODEL_PATH,&lt;br /&gt;
    torch_dtype=TORCH_TYPE,&lt;br /&gt;
    trust_remote_code=True,&lt;br /&gt;
    quantization_config=quant_config,&lt;br /&gt;
).eval()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_Caption_Model_Loading]] -- Principle governing caption model loading&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_Video_Captioning_Environment]]&lt;br /&gt;
* [[uses_heuristic::Heuristic:Zai_org_CogVideo_BF16_FP16_Precision_Selection]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_Captioning_Requirements_Install]] -- Previous step: environment setup&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_Caption_Load_Video]] -- Next step: loading video frames for captioning&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_CogVLM2_Predict]] -- Prediction step using the loaded model&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_Captioning_Requirements_Install&amp;diff=30795</id>
		<title>Implementation:Zai org CogVideo Captioning Requirements Install</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_Captioning_Requirements_Install&amp;diff=30795"/>
		<updated>2026-09-27T10:53:28Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_Captioning_Requirements_Install}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_Captioning_Requirements_Install}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || Captioning Requirements Install&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || Video Captioning&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 1 of 5&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || External Tool Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;tools/caption/requirements.txt:L1-23&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of the environment setup for the video captioning pipeline. Dependencies are specified in a requirements.txt file and installed via pip.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The requirements file specifies all Python packages needed for the captioning workflow:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;transformers&#039;&#039;&#039;: HuggingFace model loading and tokenization&lt;br /&gt;
* &#039;&#039;&#039;torch&#039;&#039;&#039;: Tensor computation and GPU acceleration&lt;br /&gt;
* &#039;&#039;&#039;decord&#039;&#039;&#039;: Efficient video frame extraction&lt;br /&gt;
* &#039;&#039;&#039;numpy&#039;&#039;&#039;: Numerical array operations&lt;br /&gt;
* &#039;&#039;&#039;accelerate&#039;&#039;&#039;: Model loading and device management&lt;br /&gt;
* &#039;&#039;&#039;sentencepiece&#039;&#039;&#039;: Tokenizer backend for Llama3&lt;br /&gt;
* &#039;&#039;&#039;xformers&#039;&#039;&#039; (optional): Memory-efficient attention for reduced GPU memory&lt;br /&gt;
&lt;br /&gt;
The installation command installs all dependencies in a single pip invocation.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
pip install -r tools/caption/requirements.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tools/caption/requirements.txt&amp;lt;/code&amp;gt; || L1-23 || Package dependency list&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
pip install -r tools/caption/requirements.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
Not applicable (installation command).&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;requirements.txt&amp;lt;/code&amp;gt; || File || Required || Dependency specification file at &amp;lt;code&amp;gt;tools/caption/requirements.txt&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Side effect || Installed packages || All required Python packages installed in the current environment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Standard installation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /path/to/CogVideo&lt;br /&gt;
pip install -r tools/caption/requirements.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Installation in a virtual environment&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
python -m venv caption_env&lt;br /&gt;
source caption_env/bin/activate&lt;br /&gt;
pip install -r tools/caption/requirements.txt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 3: Installation with optional xformers&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
pip install -r tools/caption/requirements.txt&lt;br /&gt;
pip install xformers  # Optional, for memory-efficient attention&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 4: Verify installation&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import torch&lt;br /&gt;
import decord&lt;br /&gt;
import transformers&lt;br /&gt;
import sentencepiece&lt;br /&gt;
&lt;br /&gt;
print(f&amp;quot;torch: {torch.__version__}&amp;quot;)&lt;br /&gt;
print(f&amp;quot;CUDA available: {torch.cuda.is_available()}&amp;quot;)&lt;br /&gt;
print(f&amp;quot;bfloat16 supported: {torch.cuda.is_bf16_supported()}&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_Captioning_Environment_Setup]] -- Principle governing captioning environment setup&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_Video_Captioning_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_CogVLM2_Model_Loading]] -- Next step: loading the model using the installed packages&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_Caption_Load_Video]] -- Frame extraction using the installed decord package&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_Caption_Load_Video&amp;diff=30794</id>
		<title>Implementation:Zai org CogVideo Caption Load Video</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_Caption_Load_Video&amp;diff=30794"/>
		<updated>2026-09-27T10:53:27Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_Caption_Load_Video}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_Caption_Load_Video}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || Caption Load Video&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || Video Captioning&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 3 of 5&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || API Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;tools/caption/video_caption.py:L25-57&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;External Dependencies&#039;&#039;&#039; || decord, numpy&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of video frame extraction for the captioning pipeline. The &amp;lt;code&amp;gt;load_video&amp;lt;/code&amp;gt; function extracts a fixed number of representative frames from raw video bytes using configurable temporal sampling strategies.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;load_video&amp;lt;/code&amp;gt; function:&lt;br /&gt;
&lt;br /&gt;
# Creates a decord &amp;lt;code&amp;gt;VideoReader&amp;lt;/code&amp;gt; from the raw video bytes&lt;br /&gt;
# Determines the total number of frames in the video&lt;br /&gt;
# Selects frame indices based on the chosen strategy:&lt;br /&gt;
#* &#039;&#039;&#039;Chat mode&#039;&#039;&#039;: Computes 1-FPS sampling indices up to 24 frames&lt;br /&gt;
#* &#039;&#039;&#039;Base mode&#039;&#039;&#039;: Computes uniform sampling indices for exactly 24 frames&lt;br /&gt;
# Extracts the selected frames using decord&#039;s batch frame access&lt;br /&gt;
# Returns the frames as a tensor in &amp;lt;code&amp;gt;[C, T, H, W]&amp;lt;/code&amp;gt; format&lt;br /&gt;
&lt;br /&gt;
The function accepts raw video bytes rather than a file path, enabling in-memory video processing without intermediate file I/O.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from tools.caption.video_caption import load_video&lt;br /&gt;
&lt;br /&gt;
with open(&amp;quot;video.mp4&amp;quot;, &amp;quot;rb&amp;quot;) as f:&lt;br /&gt;
    video_data = f.read()&lt;br /&gt;
&lt;br /&gt;
frames = load_video(video_data, strategy=&amp;quot;chat&amp;quot;)&lt;br /&gt;
# frames.shape: [3, 24, H, W]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tools/caption/video_caption.py&amp;lt;/code&amp;gt; || L25-57 || &amp;lt;code&amp;gt;load_video&amp;lt;/code&amp;gt; function&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def load_video(&lt;br /&gt;
    video_data: bytes,&lt;br /&gt;
    strategy: str = &amp;quot;chat&amp;quot;  # &amp;quot;chat&amp;quot; or &amp;quot;base&amp;quot;&lt;br /&gt;
) -&amp;gt; torch.Tensor:  # [C, T, H, W]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from tools.caption.video_caption import load_video&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;video_data&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;bytes&amp;lt;/code&amp;gt; || Required || Raw video file bytes (e.g., from &amp;lt;code&amp;gt;open(&amp;quot;video.mp4&amp;quot;, &amp;quot;rb&amp;quot;).read()&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;strategy&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;chat&amp;quot;&amp;lt;/code&amp;gt; || Sampling strategy: &amp;lt;code&amp;gt;&amp;quot;chat&amp;quot;&amp;lt;/code&amp;gt; (1 FPS up to 24 frames) or &amp;lt;code&amp;gt;&amp;quot;base&amp;quot;&amp;lt;/code&amp;gt; (uniform 24 frames)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Return value || &amp;lt;code&amp;gt;torch.Tensor&amp;lt;/code&amp;gt; || Video frames tensor of shape &amp;lt;code&amp;gt;[C, T, H, W]&amp;lt;/code&amp;gt; where &amp;lt;code&amp;gt;C=3&amp;lt;/code&amp;gt; (RGB), &amp;lt;code&amp;gt;T&amp;lt;=24&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;H, W&amp;lt;/code&amp;gt; are the original video dimensions&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Chat mode (1 FPS sampling)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from tools.caption.video_caption import load_video&lt;br /&gt;
&lt;br /&gt;
with open(&amp;quot;natural_scene.mp4&amp;quot;, &amp;quot;rb&amp;quot;) as f:&lt;br /&gt;
    video_data = f.read()&lt;br /&gt;
&lt;br /&gt;
frames = load_video(video_data, strategy=&amp;quot;chat&amp;quot;)&lt;br /&gt;
print(f&amp;quot;Extracted {frames.shape[1]} frames&amp;quot;)&lt;br /&gt;
# For a 30-second video: 24 frames (capped)&lt;br /&gt;
# For a 10-second video: 10 frames&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Base mode (uniform sampling)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
frames = load_video(video_data, strategy=&amp;quot;base&amp;quot;)&lt;br /&gt;
print(f&amp;quot;Extracted {frames.shape[1]} frames&amp;quot;)&lt;br /&gt;
# Always 24 frames regardless of video length&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 3: Integration with prediction&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from tools.caption.video_caption import load_video, predict&lt;br /&gt;
&lt;br /&gt;
with open(&amp;quot;input_video.mp4&amp;quot;, &amp;quot;rb&amp;quot;) as f:&lt;br /&gt;
    video_data = f.read()&lt;br /&gt;
&lt;br /&gt;
# load_video is called internally by predict()&lt;br /&gt;
caption = predict(&lt;br /&gt;
    prompt=&amp;quot;Please describe this video in detail.&amp;quot;,&lt;br /&gt;
    video_data=video_data,&lt;br /&gt;
    temperature=0.1&lt;br /&gt;
)&lt;br /&gt;
print(caption)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_Video_Frame_Extraction]] -- Principle governing video frame extraction&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_Video_Captioning_Environment]]&lt;br /&gt;
* [[uses_heuristic::Heuristic:Zai_org_CogVideo_Decord_Import_Order_Bug]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_CogVLM2_Model_Loading]] -- Previous step: model loading&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_CogVLM2_Predict]] -- Next step: caption generation using extracted frames&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_Caption_File_Output&amp;diff=30793</id>
		<title>Implementation:Zai org CogVideo Caption File Output</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Zai_org_CogVideo_Caption_File_Output&amp;diff=30793"/>
		<updated>2026-09-27T10:53:27Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Zai_org_CogVideo_Caption_File_Output}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Zai_org_CogVideo_Caption_File_Output}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Attribute !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Implementation Name&#039;&#039;&#039; || Caption File Output&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Workflow&#039;&#039;&#039; || Video Captioning&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Step&#039;&#039;&#039; || 5 of 5&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || Pattern Doc&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;tools/caption/video_caption.py:L103-112&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/zai-org/CogVideo zai-org/CogVideo]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Last Updated&#039;&#039;&#039; || 2026-02-10 00:00 GMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Implementation of caption text output for the video captioning pipeline. This pattern document describes how to save generated captions to files compatible with the CogVideoX fine-tuning dataset format.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The caption file output pattern:&lt;br /&gt;
&lt;br /&gt;
# Calls &amp;lt;code&amp;gt;predict()&amp;lt;/code&amp;gt; to generate the caption text for a video&lt;br /&gt;
# Writes the caption to a file using standard Python I/O&lt;br /&gt;
# The output format matches the fine-tuning dataset&#039;s &amp;lt;code&amp;gt;caption_column&amp;lt;/code&amp;gt; expectations&lt;br /&gt;
&lt;br /&gt;
The implementation uses a simple append-mode file write to build up a prompts file across multiple videos. Each caption is written on a separate line.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from tools.caption.video_caption import predict&lt;br /&gt;
&lt;br /&gt;
with open(&amp;quot;video.mp4&amp;quot;, &amp;quot;rb&amp;quot;) as f:&lt;br /&gt;
    video_data = f.read()&lt;br /&gt;
&lt;br /&gt;
response = predict(&amp;quot;Please describe this video in detail.&amp;quot;, video_data, 0.1)&lt;br /&gt;
&lt;br /&gt;
with open(&amp;quot;prompts.txt&amp;quot;, &amp;quot;a&amp;quot;) as f:&lt;br /&gt;
    f.write(response + &amp;quot;\n&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tools/caption/video_caption.py&amp;lt;/code&amp;gt; || L103-112 || Caption output section&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Pattern: Save caption text to file&lt;br /&gt;
# The output format should match the dataset&#039;s caption_column expectations&lt;br /&gt;
response = predict(prompt, video_data, temperature)&lt;br /&gt;
# Save to file (user implements this pattern):&lt;br /&gt;
with open(&amp;quot;prompts.txt&amp;quot;, &amp;quot;a&amp;quot;) as f:&lt;br /&gt;
    f.write(response + &amp;quot;\n&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Standard Python I/O - no additional imports needed&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Required || Generated caption text from &amp;lt;code&amp;gt;predict()&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Output file path || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;prompts.txt&amp;quot;&amp;lt;/code&amp;gt; || Path to the output caption file&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Side effect || Text file || Caption text appended to the output file, one caption per line&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 1: Single video caption to file&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from tools.caption.video_caption import predict&lt;br /&gt;
&lt;br /&gt;
with open(&amp;quot;my_video.mp4&amp;quot;, &amp;quot;rb&amp;quot;) as f:&lt;br /&gt;
    video_data = f.read()&lt;br /&gt;
&lt;br /&gt;
caption = predict(&lt;br /&gt;
    &amp;quot;Please describe this video in detail.&amp;quot;,&lt;br /&gt;
    video_data,&lt;br /&gt;
    0.1&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
with open(&amp;quot;prompts.txt&amp;quot;, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
    f.write(caption + &amp;quot;\n&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 2: Batch captioning with aggregated output&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
from tools.caption.video_caption import predict&lt;br /&gt;
&lt;br /&gt;
video_dir = &amp;quot;/data/training_videos/&amp;quot;&lt;br /&gt;
output_file = &amp;quot;prompts.txt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
with open(output_file, &amp;quot;w&amp;quot;) as out_f:&lt;br /&gt;
    for filename in sorted(os.listdir(video_dir)):&lt;br /&gt;
        if filename.endswith(&amp;quot;.mp4&amp;quot;):&lt;br /&gt;
            video_path = os.path.join(video_dir, filename)&lt;br /&gt;
            with open(video_path, &amp;quot;rb&amp;quot;) as f:&lt;br /&gt;
                video_data = f.read()&lt;br /&gt;
&lt;br /&gt;
            caption = predict(&lt;br /&gt;
                &amp;quot;Please describe this video in detail.&amp;quot;,&lt;br /&gt;
                video_data,&lt;br /&gt;
                0.1&lt;br /&gt;
            )&lt;br /&gt;
            out_f.write(caption + &amp;quot;\n&amp;quot;)&lt;br /&gt;
            print(f&amp;quot;Captioned: {filename}&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 3: Per-video caption files&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import os&lt;br /&gt;
from tools.caption.video_caption import predict&lt;br /&gt;
&lt;br /&gt;
video_dir = &amp;quot;/data/training_videos/&amp;quot;&lt;br /&gt;
caption_dir = &amp;quot;/data/captions/&amp;quot;&lt;br /&gt;
os.makedirs(caption_dir, exist_ok=True)&lt;br /&gt;
&lt;br /&gt;
for filename in sorted(os.listdir(video_dir)):&lt;br /&gt;
    if filename.endswith(&amp;quot;.mp4&amp;quot;):&lt;br /&gt;
        video_path = os.path.join(video_dir, filename)&lt;br /&gt;
        caption_path = os.path.join(&lt;br /&gt;
            caption_dir,&lt;br /&gt;
            filename.replace(&amp;quot;.mp4&amp;quot;, &amp;quot;.txt&amp;quot;)&lt;br /&gt;
        )&lt;br /&gt;
&lt;br /&gt;
        with open(video_path, &amp;quot;rb&amp;quot;) as f:&lt;br /&gt;
            video_data = f.read()&lt;br /&gt;
&lt;br /&gt;
        caption = predict(&lt;br /&gt;
            &amp;quot;Please describe this video in detail.&amp;quot;,&lt;br /&gt;
            video_data,&lt;br /&gt;
            0.1&lt;br /&gt;
        )&lt;br /&gt;
&lt;br /&gt;
        with open(caption_path, &amp;quot;w&amp;quot;) as f:&lt;br /&gt;
            f.write(caption)&lt;br /&gt;
        print(f&amp;quot;Saved: {caption_path}&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example 4: CSV format for dataset integration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import csv&lt;br /&gt;
import os&lt;br /&gt;
from tools.caption.video_caption import predict&lt;br /&gt;
&lt;br /&gt;
video_dir = &amp;quot;/data/training_videos/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
with open(&amp;quot;dataset.csv&amp;quot;, &amp;quot;w&amp;quot;, newline=&amp;quot;&amp;quot;) as csvfile:&lt;br /&gt;
    writer = csv.writer(csvfile)&lt;br /&gt;
    writer.writerow([&amp;quot;video_path&amp;quot;, &amp;quot;caption&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
    for filename in sorted(os.listdir(video_dir)):&lt;br /&gt;
        if filename.endswith(&amp;quot;.mp4&amp;quot;):&lt;br /&gt;
            video_path = os.path.join(video_dir, filename)&lt;br /&gt;
            with open(video_path, &amp;quot;rb&amp;quot;) as f:&lt;br /&gt;
                video_data = f.read()&lt;br /&gt;
&lt;br /&gt;
            caption = predict(&lt;br /&gt;
                &amp;quot;Please describe this video in detail.&amp;quot;,&lt;br /&gt;
                video_data,&lt;br /&gt;
                0.1&lt;br /&gt;
            )&lt;br /&gt;
            writer.writerow([video_path, caption])&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Zai_org_CogVideo_Caption_Output]] -- Principle governing caption output to files&lt;br /&gt;
* [[requires_env::Environment:Zai_org_CogVideo_Video_Captioning_Environment]]&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_CogVLM2_Predict]] -- Previous step: caption generation providing the text to save&lt;br /&gt;
* [[Implementation:Zai_org_CogVideo_Captioning_Requirements_Install]] -- Environment setup for the captioning pipeline&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_SpecReporter_Class&amp;diff=30792</id>
		<title>Implementation:Webdriverio Webdriverio SpecReporter Class</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_SpecReporter_Class&amp;diff=30792"/>
		<updated>2026-09-27T10:53:26Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Webdriverio_Webdriverio_SpecReporter_Class}}&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Concrete tool for formatted console test result reporting provided by the &amp;lt;code&amp;gt;@wdio/spec-reporter&amp;lt;/code&amp;gt; package.&lt;br /&gt;
&lt;br /&gt;
== Metadata ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Page Type&#039;&#039;&#039; || Implementation&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/webdriverio/webdriverio webdriverio/webdriverio]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Package&#039;&#039;&#039; || &amp;lt;code&amp;gt;@wdio/spec-reporter&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;packages/wdio-spec-reporter/src/index.ts&amp;lt;/code&amp;gt;, Lines L17-697&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Types&#039;&#039;&#039; || &amp;lt;code&amp;gt;packages/wdio-spec-reporter/src/types.ts&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Related Principle&#039;&#039;&#039; || [[Principle:Webdriverio_Webdriverio_Test_Result_Reporting|Principle: Test_Result_Reporting]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;SpecReporter&amp;lt;/code&amp;gt; class extends &amp;lt;code&amp;gt;WDIOReporter&amp;lt;/code&amp;gt; to produce formatted, colored console output showing test suite hierarchy, individual test results (checkmark for pass, X for fail, dash for skipped), timing information, and error stacks for failures. It is the default and most commonly used reporter for WDIO projects.&lt;br /&gt;
&lt;br /&gt;
The reporter tracks suite ordering, maintains state counts (passed, failed, skipped, pending, retried), computes indentation for nested suites, and produces a final summary with pass/fail counts and total duration. It supports real-time reporting (printing results as tests complete) and deferred reporting (printing a complete summary after all tests in a worker finish).&lt;br /&gt;
&lt;br /&gt;
For Sauce Labs users, the reporter can generate sharable test result links. It also handles multiremote sessions, Cucumber data tables and docstrings, and suite-level retries.&lt;br /&gt;
&lt;br /&gt;
== Source Reference ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-spec-reporter/src/index.ts&amp;lt;/code&amp;gt; || L17-697 || SpecReporter class with all event handlers and formatting logic&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-spec-reporter/src/types.ts&amp;lt;/code&amp;gt; || L1-95 || SpecReporterOptions, StateCount, Symbols, State enum, ChalkColors&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-spec-reporter/src/utils.ts&amp;lt;/code&amp;gt; || -- || Table formatting utilities for Cucumber data tables&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Signature ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
class SpecReporter extends WDIOReporter {&lt;br /&gt;
    constructor(options: SpecReporterOptions)&lt;br /&gt;
&lt;br /&gt;
    // Event handlers&lt;br /&gt;
    onRunnerStart(runner: RunnerStats): void&lt;br /&gt;
    onSuiteStart(suite: SuiteStats): void&lt;br /&gt;
    onSuiteEnd(): void&lt;br /&gt;
    onSuiteRetry(): void&lt;br /&gt;
    onHookEnd(hook: HookStats): void&lt;br /&gt;
    onTestStart(): void&lt;br /&gt;
    onTestPass(testStat: TestStats): void&lt;br /&gt;
    onTestFail(testStat: TestStats): void&lt;br /&gt;
    onTestSkip(testStat: TestStats): void&lt;br /&gt;
    onTestPending(testStat: TestStats): void&lt;br /&gt;
    onRunnerEnd(runner: RunnerStats): void&lt;br /&gt;
&lt;br /&gt;
    // Formatting methods&lt;br /&gt;
    printReport(runner: RunnerStats): void&lt;br /&gt;
    getResultDisplay(preface?: string): string[]&lt;br /&gt;
    getCountDisplay(duration: string): string[]&lt;br /&gt;
    getFailureDisplay(): string[]&lt;br /&gt;
    getHeaderDisplay(runner: RunnerStats): string[]&lt;br /&gt;
    getOrderedSuites(): SuiteStats[]&lt;br /&gt;
    getEventsToReport(suite: SuiteStats): (HookStats | TestStats)[]&lt;br /&gt;
    getEnviromentCombo(capability: Capabilities, verbose?: boolean, isMultiremote?: boolean): string&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Import ==&lt;br /&gt;
&lt;br /&gt;
Configured via the reporters array in &amp;lt;code&amp;gt;wdio.conf.ts&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// String form (default options)&lt;br /&gt;
reporters: [&#039;spec&#039;]&lt;br /&gt;
&lt;br /&gt;
// Array form (with options)&lt;br /&gt;
reporters: [[&#039;spec&#039;, {&lt;br /&gt;
    onlyFailures: true,&lt;br /&gt;
    addConsoleLogs: true,&lt;br /&gt;
    realtimeReporting: false,&lt;br /&gt;
    showPreface: true,&lt;br /&gt;
    color: true&lt;br /&gt;
}]]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Or as a direct import for programmatic use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
import SpecReporter from &#039;@wdio/spec-reporter&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Options ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Option !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onlyFailures&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; || Only print results for runners that had failures&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;addConsoleLogs&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; || Capture and display console.log output from tests&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;realtimeReporting&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; || Print test results as they complete (not just at runner end)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;showPreface&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; || Show browser/capability prefix on each line (e.g., &amp;lt;code&amp;gt;[Chrome 120 #0]&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;color&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; || Enable/disable colored output via Chalk&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;symbols&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Partial&amp;lt;Symbols&amp;gt;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;{passed: &#039;&amp;amp;#10003;&#039;, failed: &#039;&amp;amp;#10006;&#039;, skipped: &#039;-&#039;, pending: &#039;?&#039;, retried: &#039;&amp;amp;#8635;&#039;}&amp;lt;/code&amp;gt; || Custom symbols for test states&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sauceLabsSharableLinks&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; || Generate sharable Sauce Labs test result links&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Inputs / Outputs Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs (Event Handlers) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Handler !! Input Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onRunnerStart&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;RunnerStats&amp;lt;/code&amp;gt; || Worker started: capabilities, cid, session info&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onSuiteStart&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;SuiteStats&amp;lt;/code&amp;gt; || Suite (describe/feature) started: title, file&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onSuiteEnd&amp;lt;/code&amp;gt; || -- || Suite completed&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onSuiteRetry&amp;lt;/code&amp;gt; || -- || Suite is being retried (adjusts state counts)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onHookEnd&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;HookStats&amp;lt;/code&amp;gt; || Hook completed (counts as failure if hook.error exists)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onTestStart&amp;lt;/code&amp;gt; || -- || Test started (resets console output buffer)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onTestPass&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;TestStats&amp;lt;/code&amp;gt; || Test passed&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onTestFail&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;TestStats&amp;lt;/code&amp;gt; || Test failed&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onTestSkip&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;TestStats&amp;lt;/code&amp;gt; || Test skipped&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onTestPending&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;TestStats&amp;lt;/code&amp;gt; || Test pending (with pendingReason)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onRunnerEnd&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;RunnerStats&amp;lt;/code&amp;gt; || Worker finished: triggers final report output&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
Formatted console output with the following structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
------------------------------------------------------------------&lt;br /&gt;
[Chrome 120 linux #0] Running: Chrome 120 linux&lt;br /&gt;
[Chrome 120 linux #0] Session ID: abc123def456&lt;br /&gt;
[Chrome 120 linux #0]&lt;br /&gt;
[Chrome 120 linux #0] &amp;gt;&amp;gt; test/specs/login.spec.ts&lt;br /&gt;
[Chrome 120 linux #0] Login Page&lt;br /&gt;
[Chrome 120 linux #0]    ✓ should display the login form&lt;br /&gt;
[Chrome 120 linux #0]    ✓ should accept valid credentials&lt;br /&gt;
[Chrome 120 linux #0]    ✖ should show error for invalid credentials&lt;br /&gt;
[Chrome 120 linux #0]&lt;br /&gt;
[Chrome 120 linux #0] 2 passing (3.2s)&lt;br /&gt;
[Chrome 120 linux #0] 1 failing&lt;br /&gt;
[Chrome 120 linux #0]&lt;br /&gt;
[Chrome 120 linux #0] 1) Login Page should show error for invalid credentials&lt;br /&gt;
[Chrome 120 linux #0] Expected &amp;quot;Login failed&amp;quot; to equal &amp;quot;Invalid credentials&amp;quot;&lt;br /&gt;
[Chrome 120 linux #0]     at Context.&amp;lt;anonymous&amp;gt; (test/specs/login.spec.ts:25:9)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Color Scheme ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! State !! Color !! Symbol&lt;br /&gt;
|-&lt;br /&gt;
| Passed || Green || &amp;lt;code&amp;gt;&amp;amp;#10003;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Failed || Red || &amp;lt;code&amp;gt;&amp;amp;#10006;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Skipped || Cyan || &amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Pending || Cyan || &amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Retried || Yellow || &amp;lt;code&amp;gt;&amp;amp;#8635;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Unknown/Default || Gray || (none)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Implemented via the &amp;lt;code&amp;gt;getColor()&amp;lt;/code&amp;gt; method and Chalk:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-spec-reporter/src/index.ts L622-643&lt;br /&gt;
getColor(state?: string): ChalkColors {&lt;br /&gt;
    let color = ChalkColors.GRAY&lt;br /&gt;
    switch (state) {&lt;br /&gt;
    case State.PASSED:  color = ChalkColors.GREEN;  break&lt;br /&gt;
    case State.PENDING:&lt;br /&gt;
    case State.SKIPPED: color = ChalkColors.CYAN;   break&lt;br /&gt;
    case State.FAILED:  color = ChalkColors.RED;    break&lt;br /&gt;
    case State.RETRIED: color = ChalkColors.YELLOW; break&lt;br /&gt;
    }&lt;br /&gt;
    return color&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Usage Example ==&lt;br /&gt;
&lt;br /&gt;
=== Basic Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// wdio.conf.ts&lt;br /&gt;
export const config: WebdriverIO.Config = {&lt;br /&gt;
    reporters: [&#039;spec&#039;],&lt;br /&gt;
    // ... other config&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Show Only Failures (CI-friendly) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// wdio.conf.ts&lt;br /&gt;
export const config: WebdriverIO.Config = {&lt;br /&gt;
    reporters: [[&#039;spec&#039;, {&lt;br /&gt;
        onlyFailures: true,&lt;br /&gt;
        showPreface: false&lt;br /&gt;
    }]],&lt;br /&gt;
    // ... other config&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== With Console Log Capture ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// wdio.conf.ts&lt;br /&gt;
export const config: WebdriverIO.Config = {&lt;br /&gt;
    reporters: [[&#039;spec&#039;, {&lt;br /&gt;
        addConsoleLogs: true,&lt;br /&gt;
        realtimeReporting: true&lt;br /&gt;
    }]],&lt;br /&gt;
    // ... other config&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Internal State Management ==&lt;br /&gt;
&lt;br /&gt;
The SpecReporter tracks state using several internal structures:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-spec-reporter/src/index.ts L38-44&lt;br /&gt;
private _stateCounts: StateCount = {&lt;br /&gt;
    passed: 0,&lt;br /&gt;
    failed: 0,&lt;br /&gt;
    skipped: 0,&lt;br /&gt;
    pending: 0,&lt;br /&gt;
    retried: 0&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Suite ordering is maintained by tracking UIDs in the order suites are started:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-spec-reporter/src/index.ts L96-106&lt;br /&gt;
onSuiteStart(suite: SuiteStats) {&lt;br /&gt;
    this._suiteName = suite.file?.replace(process.cwd(), &#039;&#039;)&lt;br /&gt;
    this.printCurrentStats(suite)&lt;br /&gt;
    this._suiteUids.add(suite.uid)&lt;br /&gt;
    if (suite.type === &#039;feature&#039;) {&lt;br /&gt;
        this._indents = 0&lt;br /&gt;
        this._suiteIndents[suite.uid] = this._indents&lt;br /&gt;
    } else {&lt;br /&gt;
        this._suiteIndents[suite.uid] = ++this._indents&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;getEventsToReport()&amp;lt;/code&amp;gt; method filters events to show only the latest retry of each test and only failed hooks, avoiding duplicate output for retried tests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-spec-reporter/src/index.ts L331-359&lt;br /&gt;
getEventsToReport(suite: SuiteStats) {&lt;br /&gt;
    return [&lt;br /&gt;
        ...suite.hooksAndTests.reduce((accumulator, currentItem) =&amp;gt; {&lt;br /&gt;
            if (currentItem instanceof TestStats) {&lt;br /&gt;
                const existingTestIndex = accumulator.findIndex(&lt;br /&gt;
                    (test) =&amp;gt; test instanceof TestStats &amp;amp;&amp;amp;&lt;br /&gt;
                    test.fullTitle === currentItem.fullTitle&lt;br /&gt;
                )&lt;br /&gt;
                if (existingTestIndex === -1) {&lt;br /&gt;
                    accumulator.push(currentItem)&lt;br /&gt;
                } else {&lt;br /&gt;
                    // Keep the test with the highest retry count&lt;br /&gt;
                    const existingTest = accumulator[existingTestIndex] as TestStats&lt;br /&gt;
                    if (currentItem.retries &amp;gt; existingTest.retries) {&lt;br /&gt;
                        accumulator.splice(existingTestIndex, 1, currentItem)&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            } else {&lt;br /&gt;
                accumulator.push(currentItem)&lt;br /&gt;
            }&lt;br /&gt;
            return accumulator&lt;br /&gt;
        }, []).filter((item) =&amp;gt; {&lt;br /&gt;
            return item.type === &#039;test&#039; || Boolean(item.error)&lt;br /&gt;
        })&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Implements:&#039;&#039;&#039; [[Principle:Webdriverio_Webdriverio_Test_Result_Reporting|Principle: Test_Result_Reporting]]&lt;br /&gt;
* &#039;&#039;&#039;Receives events from:&#039;&#039;&#039; [[Implementation:Webdriverio_Webdriverio_Mocha_BDD_Globals|Implementation: Mocha_BDD_Globals]]&lt;br /&gt;
* &#039;&#039;&#039;Orchestrated by:&#039;&#039;&#039; [[Implementation:Webdriverio_Webdriverio_Launcher_Class|Implementation: Launcher_Class]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_Page_Object_Class_Pattern&amp;diff=30791</id>
		<title>Implementation:Webdriverio Webdriverio Page Object Class Pattern</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_Page_Object_Class_Pattern&amp;diff=30791"/>
		<updated>2026-09-27T10:53:25Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Webdriverio_Webdriverio_Page_Object_Class_Pattern}}&lt;br /&gt;
== Metadata ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Page ID&#039;&#039;&#039; || Page_Object_Class_Pattern&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Wiki&#039;&#039;&#039; || Webdriverio_Webdriverio&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || Implementation (Pattern Doc)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Domains&#039;&#039;&#039; || Testing, Design_Patterns&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Knowledge Sources&#039;&#039;&#039; || Repo (https://github.com/webdriverio/webdriverio), Doc (https://webdriver.io/docs/pageobjects)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Related Principles&#039;&#039;&#039; || [[Principle:Webdriverio_Webdriverio_Page_Object_Model|Principle: Page_Object_Model]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Interface specification for implementing the Page Object Model pattern in WebdriverIO test projects. The pattern consists of a base &amp;lt;code&amp;gt;Page&amp;lt;/code&amp;gt; class with an &amp;lt;code&amp;gt;open(path)&amp;lt;/code&amp;gt; method, and subclasses that define element getters using &amp;lt;code&amp;gt;$(&#039;selector&#039;)&amp;lt;/code&amp;gt; and action methods. Page objects are exported as singletons. Tests import these singletons and call their methods.&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The Page Object Class Pattern in WebdriverIO is implemented through a class inheritance hierarchy:&lt;br /&gt;
&lt;br /&gt;
* A &#039;&#039;&#039;base Page class&#039;&#039;&#039; defines the &amp;lt;code&amp;gt;open(path)&amp;lt;/code&amp;gt; method that delegates to &amp;lt;code&amp;gt;browser.url(path)&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;&#039;Page-specific subclasses&#039;&#039;&#039; extend the base class and define element getters using &amp;lt;code&amp;gt;$(&#039;selector&#039;)&amp;lt;/code&amp;gt; (without &amp;lt;code&amp;gt;await&amp;lt;/code&amp;gt;) and action methods that compose element interactions.&lt;br /&gt;
* Each page module exports a &#039;&#039;&#039;singleton instance&#039;&#039;&#039; (&amp;lt;code&amp;gt;export default new PageClass()&amp;lt;/code&amp;gt;).&lt;br /&gt;
* &#039;&#039;&#039;Test specs&#039;&#039;&#039; import these singletons and invoke their methods using &amp;lt;code&amp;gt;await&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The getter pattern leverages WebdriverIO&#039;s &#039;&#039;&#039;ChainablePromiseElement&#039;&#039;&#039; -- calling &amp;lt;code&amp;gt;$(&#039;#username&#039;)&amp;lt;/code&amp;gt; returns a thenable wrapper that resolves the element only when an action is performed. This means element lookups are always fresh and never stale.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;examples/pageobject/pageobjects/page.js&amp;lt;/code&amp;gt; || L1-5 || Base Page class with open(path) method&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;examples/pageobject/pageobjects/form.page.js&amp;lt;/code&amp;gt; || L1-24 || FormPage subclass with element getters and action methods&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;examples/pageobject/specs/form.spec.js&amp;lt;/code&amp;gt; || L1-26 || Test spec using FormPage singleton&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Pattern Interface ==&lt;br /&gt;
&lt;br /&gt;
=== Base Page Class ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// examples/pageobject/pageobjects/page.js&lt;br /&gt;
export default class Page {&lt;br /&gt;
    open (path) {&lt;br /&gt;
        return browser.url(path)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Interface contract:&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Input:&#039;&#039;&#039; &amp;lt;code&amp;gt;path&amp;lt;/code&amp;gt; (string) -- the URL path segment to navigate to.&lt;br /&gt;
* &#039;&#039;&#039;Output:&#039;&#039;&#039; Returns the result of &amp;lt;code&amp;gt;browser.url(path)&amp;lt;/code&amp;gt;, a Promise that resolves when navigation completes.&lt;br /&gt;
* &#039;&#039;&#039;Behavior:&#039;&#039;&#039; Navigates the browser to the given path. Subclasses call &amp;lt;code&amp;gt;super.open(&#039;specific-path&#039;)&amp;lt;/code&amp;gt; to navigate to their page.&lt;br /&gt;
&lt;br /&gt;
=== Page Subclass ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// examples/pageobject/pageobjects/form.page.js&lt;br /&gt;
import Page from &#039;./page.js&#039;&lt;br /&gt;
&lt;br /&gt;
class FormPage extends Page {&lt;br /&gt;
    /**&lt;br /&gt;
     * define elements&lt;br /&gt;
     */&lt;br /&gt;
    get username () { return $(&#039;#username&#039;) }&lt;br /&gt;
    get password () { return $(&#039;#password&#039;) }&lt;br /&gt;
    get submitButton () { return $(&#039;#login button[type=submit]&#039;) }&lt;br /&gt;
    get flash () { return $(&#039;#flash&#039;) }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * define or overwrite page methods&lt;br /&gt;
     */&lt;br /&gt;
    open () {&lt;br /&gt;
        return super.open(&#039;login&#039;)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    submit () {&lt;br /&gt;
        return this.submitButton.click()&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
export default new FormPage()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Interface contract:&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Element getters:&#039;&#039;&#039; Each getter returns a &amp;lt;code&amp;gt;ChainablePromiseElement&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;$(&#039;selector&#039;)&amp;lt;/code&amp;gt;. No &amp;lt;code&amp;gt;await&amp;lt;/code&amp;gt; is used in the getter body.&lt;br /&gt;
** &#039;&#039;&#039;Input:&#039;&#039;&#039; None (getter property).&lt;br /&gt;
** &#039;&#039;&#039;Output:&#039;&#039;&#039; &amp;lt;code&amp;gt;ChainablePromiseElement&amp;lt;/code&amp;gt; -- a thenable that resolves to a WebdriverIO Element when acted upon.&lt;br /&gt;
* &#039;&#039;&#039;Action methods:&#039;&#039;&#039; Compose element interactions into domain-specific actions (e.g., &amp;lt;code&amp;gt;submit()&amp;lt;/code&amp;gt;).&lt;br /&gt;
** &#039;&#039;&#039;Input:&#039;&#039;&#039; Method-specific parameters (none for &amp;lt;code&amp;gt;submit()&amp;lt;/code&amp;gt;).&lt;br /&gt;
** &#039;&#039;&#039;Output:&#039;&#039;&#039; Promise from the underlying WebdriverIO command.&lt;br /&gt;
* &#039;&#039;&#039;Singleton export:&#039;&#039;&#039; &amp;lt;code&amp;gt;export default new FormPage()&amp;lt;/code&amp;gt; provides a shared instance.&lt;br /&gt;
&lt;br /&gt;
=== Test Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// examples/pageobject/specs/form.spec.js&lt;br /&gt;
import FormPage from &#039;../pageobjects/form.page.js&#039;&lt;br /&gt;
&lt;br /&gt;
describe(&#039;auth form&#039;, () =&amp;gt; {&lt;br /&gt;
    it(&#039;should deny access with wrong creds&#039;, async () =&amp;gt; {&lt;br /&gt;
        await FormPage.open()&lt;br /&gt;
        await FormPage.username.addValue(&#039;foo&#039;)&lt;br /&gt;
        await FormPage.password.addValue(&#039;bar&#039;)&lt;br /&gt;
        await FormPage.submit()&lt;br /&gt;
&lt;br /&gt;
        await expect(FormPage.flash).toHaveText(&lt;br /&gt;
            expect.stringContaining(&#039;Your username is invalid!&#039;)&lt;br /&gt;
        )&lt;br /&gt;
    })&lt;br /&gt;
&lt;br /&gt;
    it(&#039;should allow access with correct creds&#039;, async () =&amp;gt; {&lt;br /&gt;
        await FormPage.open()&lt;br /&gt;
        await FormPage.username.addValue(&#039;tomsmith&#039;)&lt;br /&gt;
        await FormPage.password.addValue(&#039;SuperSecretPassword!&#039;)&lt;br /&gt;
        await FormPage.submit()&lt;br /&gt;
&lt;br /&gt;
        await FormPage.flash.waitForDisplayed()&lt;br /&gt;
        await expect(FormPage.flash).toHaveText(&lt;br /&gt;
            expect.stringContaining(&#039;You logged into a secure area!&#039;)&lt;br /&gt;
        )&lt;br /&gt;
    })&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test contract:&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Input:&#039;&#039;&#039; Page object method calls with test data.&lt;br /&gt;
* &#039;&#039;&#039;Output:&#039;&#039;&#039; Assertions on element state using &amp;lt;code&amp;gt;expect-webdriverio&amp;lt;/code&amp;gt; matchers.&lt;br /&gt;
* &#039;&#039;&#039;Pattern:&#039;&#039;&#039; Open page, interact with elements, assert on outcomes.&lt;br /&gt;
&lt;br /&gt;
== Directory Convention ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Directory !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pageobjects/&amp;lt;/code&amp;gt; || Page object classes (base + page-specific)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;specs/&amp;lt;/code&amp;gt; || Test specification files&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;wdio.conf.js&amp;lt;/code&amp;gt; || WebdriverIO configuration at project root&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== I/O Contract Summary ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Component !! Input !! Output&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Page.open(path)&amp;lt;/code&amp;gt; || URL path string || Promise (navigation complete)&lt;br /&gt;
|-&lt;br /&gt;
| Element getter (&amp;lt;code&amp;gt;get username()&amp;lt;/code&amp;gt;) || None || &amp;lt;code&amp;gt;ChainablePromiseElement&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Action method (&amp;lt;code&amp;gt;submit()&amp;lt;/code&amp;gt;) || Method-specific params || Promise (action complete)&lt;br /&gt;
|-&lt;br /&gt;
| Singleton export || None || Page object instance&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
=== Creating a new page object ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import Page from &#039;./page.js&#039;&lt;br /&gt;
&lt;br /&gt;
class DashboardPage extends Page {&lt;br /&gt;
    get welcomeMessage () { return $(&#039;[data-testid=&amp;quot;welcome&amp;quot;]&#039;) }&lt;br /&gt;
    get logoutButton () { return $(&#039;button.logout&#039;) }&lt;br /&gt;
    get navItems () { return $$(&#039;.nav-item&#039;) }&lt;br /&gt;
&lt;br /&gt;
    open () {&lt;br /&gt;
        return super.open(&#039;dashboard&#039;)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    logout () {&lt;br /&gt;
        return this.logoutButton.click()&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
export default new DashboardPage()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using multiple page objects in a test ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import LoginPage from &#039;../pageobjects/login.page.js&#039;&lt;br /&gt;
import DashboardPage from &#039;../pageobjects/dashboard.page.js&#039;&lt;br /&gt;
&lt;br /&gt;
describe(&#039;user flow&#039;, () =&amp;gt; {&lt;br /&gt;
    it(&#039;should login and see dashboard&#039;, async () =&amp;gt; {&lt;br /&gt;
        await LoginPage.open()&lt;br /&gt;
        await LoginPage.username.addValue(&#039;admin&#039;)&lt;br /&gt;
        await LoginPage.password.addValue(&#039;secret&#039;)&lt;br /&gt;
        await LoginPage.submit()&lt;br /&gt;
&lt;br /&gt;
        await expect(DashboardPage.welcomeMessage).toBeDisplayed()&lt;br /&gt;
        await expect(DashboardPage.welcomeMessage).toHaveTextContaining(&#039;Welcome&#039;)&lt;br /&gt;
    })&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;implements&#039;&#039;&#039; [[Principle:Webdriverio_Webdriverio_Page_Object_Model|Principle: Page_Object_Model]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_Mocha_BDD_Globals&amp;diff=30790</id>
		<title>Implementation:Webdriverio Webdriverio Mocha BDD Globals</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_Mocha_BDD_Globals&amp;diff=30790"/>
		<updated>2026-09-27T10:53:24Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Webdriverio_Webdriverio_Mocha_BDD_Globals}}&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Wrapper documentation for Mocha BDD test syntax with WebdriverIO-injected globals for browser automation testing.&lt;br /&gt;
&lt;br /&gt;
== Metadata ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Page Type&#039;&#039;&#039; || Implementation (Wrapper Doc)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/webdriverio/webdriverio webdriverio/webdriverio]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Packages&#039;&#039;&#039; || &amp;lt;code&amp;gt;@wdio/mocha-framework&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;@wdio/globals&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;External Reference&#039;&#039;&#039; || [https://mochajs.org/ Mocha BDD Interface], [https://webdriver.io/docs/api/globals WDIO Globals API]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Related Principle&#039;&#039;&#039; || [[Principle:Webdriverio_Webdriverio_Test_Spec_Authoring|Principle: Test_Spec_Authoring]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
When using the WDIO testrunner with &amp;lt;code&amp;gt;framework: &#039;mocha&#039;&amp;lt;/code&amp;gt;, the &#039;&#039;&#039;MochaAdapter&#039;&#039;&#039; sets up Mocha&#039;s BDD interface (&amp;lt;code&amp;gt;describe&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;it&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;before&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;after&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;beforeEach&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;afterEach&amp;lt;/code&amp;gt;) and the &#039;&#039;&#039;&amp;lt;code&amp;gt;@wdio/globals&amp;lt;/code&amp;gt;&#039;&#039;&#039; module injects &amp;lt;code&amp;gt;browser&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$$&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;expect&amp;lt;/code&amp;gt; into the test worker scope. Tests use &amp;lt;code&amp;gt;describe&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;it&amp;lt;/code&amp;gt; for structure and the globals for browser interaction without explicit imports.&lt;br /&gt;
&lt;br /&gt;
The MochaAdapter wraps the standard Mocha test runner with WDIO-specific lifecycle management: it maps Mocha events to WDIO reporter events, wraps hook execution with &amp;lt;code&amp;gt;executeHooksWithArgs&amp;lt;/code&amp;gt; for proper error handling, and provides UID-based tracking for nested suite/test hierarchies.&lt;br /&gt;
&lt;br /&gt;
The globals module uses a &#039;&#039;&#039;Proxy-based&#039;&#039;&#039; delegation pattern. Each exported global (&amp;lt;code&amp;gt;browser&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$$&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;expect&amp;lt;/code&amp;gt;) is a Proxy that intercepts property access and delegates to the real object stored in a global &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;globalThis._wdioGlobals&amp;lt;/code&amp;gt;). This enables the globals to work across both ESM and CJS module boundaries within the same worker process.&lt;br /&gt;
&lt;br /&gt;
== Source References ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-mocha-framework/src/index.ts&amp;lt;/code&amp;gt; || L30-288 || MochaAdapter class: initializes Mocha, loads specs, runs tests, emits events&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-mocha-framework/src/common.ts&amp;lt;/code&amp;gt; || L151-176 || &amp;lt;code&amp;gt;setupEnv()&amp;lt;/code&amp;gt;: configures BDD/TDD/QUnit interface and wraps global test methods&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-mocha-framework/src/constants.ts&amp;lt;/code&amp;gt; || L1-30 || INTERFACES, TEST_INTERFACES, EVENTS mapping (Mocha events to WDIO events)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-globals/src/index.ts&amp;lt;/code&amp;gt; || L1-134 || Proxy-based globals: browser, driver, $, $$, expect, _setGlobal()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== APIs ==&lt;br /&gt;
&lt;br /&gt;
=== Mocha BDD Interface (injected globally) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Function !! Signature !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;describe&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;describe(title: string, fn: () =&amp;gt; void): void&amp;lt;/code&amp;gt; || Define a test suite&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;it&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;it(title: string, fn: () =&amp;gt; Promise&amp;lt;void&amp;gt;): void&amp;lt;/code&amp;gt; || Define an individual test case&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;before&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;before(fn: () =&amp;gt; Promise&amp;lt;void&amp;gt;): void&amp;lt;/code&amp;gt; || Run once before all tests in a suite&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;beforeEach&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;beforeEach(fn: () =&amp;gt; Promise&amp;lt;void&amp;gt;): void&amp;lt;/code&amp;gt; || Run before each test in a suite&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;after&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;after(fn: () =&amp;gt; Promise&amp;lt;void&amp;gt;): void&amp;lt;/code&amp;gt; || Run once after all tests in a suite&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afterEach&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;afterEach(fn: () =&amp;gt; Promise&amp;lt;void&amp;gt;): void&amp;lt;/code&amp;gt; || Run after each test in a suite&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== WDIO Globals (injected by testrunner) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Global !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;browser&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;WebdriverIO.Browser&amp;lt;/code&amp;gt; (Proxy) || The automated browser session; provides &amp;lt;code&amp;gt;url()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;getTitle()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt;, etc.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;(selector: string) =&amp;gt; WebdriverIO.Element&amp;lt;/code&amp;gt; || Shorthand for &amp;lt;code&amp;gt;browser.$(selector)&amp;lt;/code&amp;gt;; returns a single element&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$$&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;(selector: string) =&amp;gt; WebdriverIO.Element[]&amp;lt;/code&amp;gt; || Shorthand for &amp;lt;code&amp;gt;browser.$$(selector)&amp;lt;/code&amp;gt;; returns multiple elements&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;expect&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ExpectWebdriverIO.Expect&amp;lt;/code&amp;gt; || Assertion function with WDIO-specific matchers (toBeDisplayed, toHaveText, etc.)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;driver&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;WebdriverIO.Browser&amp;lt;/code&amp;gt; (Proxy) || Alias for &amp;lt;code&amp;gt;browser&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Import ==&lt;br /&gt;
&lt;br /&gt;
No import is needed -- globals are injected by the testrunner automatically. If explicit imports are desired (e.g., for IDE autocompletion outside the testrunner):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
import { browser, $, $$, expect } from &#039;@wdio/globals&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Mocha Event Mapping ==&lt;br /&gt;
&lt;br /&gt;
The MochaAdapter maps Mocha runner events to WDIO reporter events:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Mocha Event !! WDIO Event&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;suite&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;suite:start&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;suite end&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;suite:end&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;test:start&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;test end&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;test:end&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hook&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;hook:start&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hook end&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;hook:end&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pass&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;test:pass&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;fail&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;test:fail&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;retry&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;test:retry&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pending&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;test:pending&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Supported UI Types ==&lt;br /&gt;
&lt;br /&gt;
The MochaAdapter supports multiple Mocha interfaces, configured via &amp;lt;code&amp;gt;mochaOpts.ui&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! UI Type !! Test Functions !! Hook Functions&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bdd&amp;lt;/code&amp;gt; (default) || &amp;lt;code&amp;gt;it&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;specify&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;before&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;beforeEach&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;after&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;afterEach&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tdd&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;suiteSetup&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;setup&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;suiteTeardown&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;teardown&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;qunit&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;before&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;beforeEach&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;after&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;afterEach&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Example ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// test/specs/login.spec.ts&lt;br /&gt;
// No imports needed -- describe, it, browser, $, $$, expect are all globals&lt;br /&gt;
&lt;br /&gt;
describe(&#039;Login Page&#039;, () =&amp;gt; {&lt;br /&gt;
    before(async () =&amp;gt; {&lt;br /&gt;
        // Runs once before all tests in this describe block&lt;br /&gt;
        await browser.url(&#039;/login&#039;)&lt;br /&gt;
    })&lt;br /&gt;
&lt;br /&gt;
    it(&#039;should display the login form&#039;, async () =&amp;gt; {&lt;br /&gt;
        const form = await $(&#039;#login-form&#039;)&lt;br /&gt;
        await expect(form).toBeDisplayed()&lt;br /&gt;
    })&lt;br /&gt;
&lt;br /&gt;
    it(&#039;should accept valid credentials&#039;, async () =&amp;gt; {&lt;br /&gt;
        await $(&#039;#username&#039;).setValue(&#039;testuser&#039;)&lt;br /&gt;
        await $(&#039;#password&#039;).setValue(&#039;secret&#039;)&lt;br /&gt;
        await $(&#039;button[type=&amp;quot;submit&amp;quot;]&#039;).click()&lt;br /&gt;
&lt;br /&gt;
        // WDIO-specific assertion matcher&lt;br /&gt;
        await expect(browser).toHaveUrl(expect.stringContaining(&#039;/dashboard&#039;))&lt;br /&gt;
    })&lt;br /&gt;
&lt;br /&gt;
    it(&#039;should show all navigation links&#039;, async () =&amp;gt; {&lt;br /&gt;
        const links = await $$(&#039;nav a&#039;)&lt;br /&gt;
        await expect(links).toBeElementsArrayOfSize({ gte: 3 })&lt;br /&gt;
    })&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Configuration for Mocha framework ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// wdio.conf.ts&lt;br /&gt;
export const config: WebdriverIO.Config = {&lt;br /&gt;
    framework: &#039;mocha&#039;,&lt;br /&gt;
    mochaOpts: {&lt;br /&gt;
        ui: &#039;bdd&#039;,           // default&lt;br /&gt;
        timeout: 60000,      // test timeout in ms&lt;br /&gt;
        retries: 1,          // retry failed tests once&lt;br /&gt;
        grep: &#039;login&#039;,       // only run tests matching pattern&lt;br /&gt;
        invert: false&lt;br /&gt;
    },&lt;br /&gt;
    // ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Globals Proxy Mechanism ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;@wdio/globals&amp;lt;/code&amp;gt; package uses a Proxy handler to lazily delegate access:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-globals/src/index.ts L27-42&lt;br /&gt;
function proxyHandler(key: SupportedGlobals) {&lt;br /&gt;
    return {&lt;br /&gt;
        get: (self: never, prop: any) =&amp;gt; {&lt;br /&gt;
            if (!globals.has(key)) {&lt;br /&gt;
                throw new Error(&lt;br /&gt;
                    &#039;No browser instance registered. Don\&#039;t import @wdio/globals &#039; +&lt;br /&gt;
                    &#039;outside of the WDIO testrunner context.&#039;&lt;br /&gt;
                )&lt;br /&gt;
            }&lt;br /&gt;
            const receiver = globals.get(key)&lt;br /&gt;
            const field = receiver[prop]&lt;br /&gt;
            return typeof field === &#039;function&#039;&lt;br /&gt;
                ? field.bind(receiver)&lt;br /&gt;
                : field&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
export const browser: WebdriverIO.Browser = new Proxy(&lt;br /&gt;
    class Browser {} as unknown as WebdriverIO.Browser,&lt;br /&gt;
    proxyHandler(&#039;browser&#039;)&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The testrunner registers actual implementations via the private &amp;lt;code&amp;gt;_setGlobal(key, value)&amp;lt;/code&amp;gt; function, which stores the value in the shared &amp;lt;code&amp;gt;Map&amp;lt;/code&amp;gt; and optionally sets it on &amp;lt;code&amp;gt;globalThis&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Implements:&#039;&#039;&#039; [[Principle:Webdriverio_Webdriverio_Test_Spec_Authoring|Principle: Test_Spec_Authoring]]&lt;br /&gt;
* &#039;&#039;&#039;Results consumed by:&#039;&#039;&#039; [[Implementation:Webdriverio_Webdriverio_SpecReporter_Class|Implementation: SpecReporter_Class]]&lt;br /&gt;
* &#039;&#039;&#039;Executed by:&#039;&#039;&#039; [[Implementation:Webdriverio_Webdriverio_Launcher_Class|Implementation: Launcher_Class]]&lt;br /&gt;
* [[requires_env::Environment:Webdriverio_Webdriverio_Node_Runtime_Environment]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_Launcher_Class&amp;diff=30789</id>
		<title>Implementation:Webdriverio Webdriverio Launcher Class</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_Launcher_Class&amp;diff=30789"/>
		<updated>2026-09-27T10:53:24Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Webdriverio_Webdriverio_Launcher_Class}}&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Concrete tool for orchestrating parallel test execution provided by the &amp;lt;code&amp;gt;@wdio/cli&amp;lt;/code&amp;gt; package.&lt;br /&gt;
&lt;br /&gt;
== Metadata ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Page Type&#039;&#039;&#039; || Implementation&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/webdriverio/webdriverio webdriverio/webdriverio]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Package&#039;&#039;&#039; || &amp;lt;code&amp;gt;@wdio/cli&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;packages/wdio-cli/src/launcher.ts&amp;lt;/code&amp;gt;, Lines L40-683&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;CLI Handler&#039;&#039;&#039; || &amp;lt;code&amp;gt;packages/wdio-cli/src/commands/run.ts&amp;lt;/code&amp;gt;, Lines L17-272&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Related Principle&#039;&#039;&#039; || [[Principle:Webdriverio_Webdriverio_Test_Execution_Orchestration|Principle: Test_Execution_Orchestration]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Launcher&amp;lt;/code&amp;gt; class is the top-level test execution coordinator. It parses configuration via &amp;lt;code&amp;gt;ConfigParser&amp;lt;/code&amp;gt;, initializes services (&amp;lt;code&amp;gt;onPrepare&amp;lt;/code&amp;gt; hooks), creates a schedule of spec-to-capability assignments, spawns worker processes via the Runner (typically &amp;lt;code&amp;gt;LocalRunner&amp;lt;/code&amp;gt;), monitors progress, handles retries, and collects results. It provides both CLI (&amp;lt;code&amp;gt;npx wdio run&amp;lt;/code&amp;gt;) and programmatic interfaces.&lt;br /&gt;
&lt;br /&gt;
The Launcher manages the full lifecycle:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Initialization:&#039;&#039;&#039; Loads &amp;lt;code&amp;gt;tsx&amp;lt;/code&amp;gt; for TypeScript support, initializes ConfigParser, validates config&lt;br /&gt;
# &#039;&#039;&#039;Service setup:&#039;&#039;&#039; Initializes launcher services, runs &amp;lt;code&amp;gt;onPrepare&amp;lt;/code&amp;gt; hooks&lt;br /&gt;
# &#039;&#039;&#039;Driver setup:&#039;&#039;&#039; Pre-configures browser drivers via &amp;lt;code&amp;gt;setupDriver&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;setupBrowser&amp;lt;/code&amp;gt;&lt;br /&gt;
# &#039;&#039;&#039;Scheduling:&#039;&#039;&#039; Creates a schedule mapping spec files to capabilities with instance limits&lt;br /&gt;
# &#039;&#039;&#039;Execution:&#039;&#039;&#039; Spawns workers, monitors completion, handles retries&lt;br /&gt;
# &#039;&#039;&#039;Cleanup:&#039;&#039;&#039; Runs &amp;lt;code&amp;gt;onComplete&amp;lt;/code&amp;gt; hooks, shuts down the runner, returns exit code&lt;br /&gt;
&lt;br /&gt;
== Source Reference ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-cli/src/launcher.ts&amp;lt;/code&amp;gt; || L40-683 || Launcher class with full orchestration logic&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-cli/src/commands/run.ts&amp;lt;/code&amp;gt; || L17-272 || CLI command handler, tsconfig resolution, watch mode entry point&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-cli/src/watcher.ts&amp;lt;/code&amp;gt; || -- || Watch mode file monitoring and re-execution&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-cli/src/interface.ts&amp;lt;/code&amp;gt; || -- || CLInterface for terminal output management&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Signature ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
class Launcher {&lt;br /&gt;
    public configParser: ConfigParser&lt;br /&gt;
    public isMultiremote: boolean&lt;br /&gt;
    public isParallelMultiremote: boolean&lt;br /&gt;
    public runner?: Services.RunnerInstance&lt;br /&gt;
    public interface?: CLInterface&lt;br /&gt;
&lt;br /&gt;
    constructor(&lt;br /&gt;
        _configFilePath: string,&lt;br /&gt;
        _args?: Partial&amp;lt;RunCommandArguments&amp;gt;,&lt;br /&gt;
        _isWatchMode?: boolean&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    async initialize(): Promise&amp;lt;void&amp;gt;&lt;br /&gt;
    async run(): Promise&amp;lt;undefined | number&amp;gt;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Import ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
import Launcher from &#039;@wdio/cli&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Inputs / Outputs Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Required !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;_configFilePath&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Yes || Path to the wdio.conf.ts/js configuration file&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;_args&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Partial&amp;lt;RunCommandArguments&amp;gt;&amp;lt;/code&amp;gt; || No || CLI overrides: spec, suite, watch, bail, baseUrl, logLevel, shard, etc.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;_isWatchMode&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || No || Whether to run in watch mode (default: false)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== CLI Arguments (RunCommandArguments) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Argument !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--spec&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string[]&amp;lt;/code&amp;gt; || Run specific spec files (overrides config specs)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--suite&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string[]&amp;lt;/code&amp;gt; || Run named suites defined in config&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--exclude&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string[]&amp;lt;/code&amp;gt; || Exclude spec files or suite names&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--watch&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || Enable watch mode&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--bail&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt; || Stop after N failures&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--baseUrl&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Override base URL&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--logLevel&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Override log level (trace/debug/info/warn/error/silent)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--shard&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Shard spec: &amp;quot;current/total&amp;quot; (e.g., &amp;quot;1/4&amp;quot;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--repeat&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt; || Repeat specs N times (requires --spec or --suite)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;--coverage&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || Enable coverage for browser runner&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Exit code || &amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; = all tests passed, &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; = one or more failures&lt;br /&gt;
|-&lt;br /&gt;
| Worker processes || Child processes || Spawned via Runner for each spec-capability pair&lt;br /&gt;
|-&lt;br /&gt;
| Console output || via CLInterface || Progress indicators, reporter output, error messages&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Execution Chain ==&lt;br /&gt;
&lt;br /&gt;
The full execution chain from CLI to test execution:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
CLI (npx wdio run wdio.conf.ts)&lt;br /&gt;
  -&amp;gt; handler() in packages/wdio-cli/src/commands/run.ts&lt;br /&gt;
    -&amp;gt; new Launcher(configPath, params)&lt;br /&gt;
      -&amp;gt; new ConfigParser(configPath, args)&lt;br /&gt;
    -&amp;gt; launcher.run()&lt;br /&gt;
      -&amp;gt; launcher.initialize()&lt;br /&gt;
        -&amp;gt; load tsx for TypeScript support&lt;br /&gt;
        -&amp;gt; configParser.initialize(args)&lt;br /&gt;
      -&amp;gt; configParser.getConfig()&lt;br /&gt;
      -&amp;gt; configParser.getCapabilities()&lt;br /&gt;
      -&amp;gt; initializeLauncherService(config, caps)&lt;br /&gt;
      -&amp;gt; runner.initialize()&lt;br /&gt;
      -&amp;gt; runLauncherHook(config.onPrepare)&lt;br /&gt;
      -&amp;gt; setupDriver(config, caps)&lt;br /&gt;
      -&amp;gt; _runMode(config, caps)&lt;br /&gt;
        -&amp;gt; build schedule (spec-to-capability mapping)&lt;br /&gt;
        -&amp;gt; _runSpecs() loop&lt;br /&gt;
          -&amp;gt; _startInstance(specs, caps, cid, rid, retries)&lt;br /&gt;
            -&amp;gt; runLauncherHook(config.onWorkerStart)&lt;br /&gt;
            -&amp;gt; runner.run({ cid, command, configFile, args, caps, specs })&lt;br /&gt;
            -&amp;gt; worker.on(&#039;exit&#039;, _endHandler)&lt;br /&gt;
        -&amp;gt; _endHandler()&lt;br /&gt;
          -&amp;gt; handle retries if specFileRetries &amp;gt; 0&lt;br /&gt;
          -&amp;gt; update schedule, spawn next spec&lt;br /&gt;
          -&amp;gt; resolve when all complete&lt;br /&gt;
      -&amp;gt; runner.shutdown()&lt;br /&gt;
      -&amp;gt; runOnCompleteHook(config.onComplete)&lt;br /&gt;
      -&amp;gt; return exitCode&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Usage Example ==&lt;br /&gt;
&lt;br /&gt;
=== Programmatic Usage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
import Launcher from &#039;@wdio/cli&#039;&lt;br /&gt;
&lt;br /&gt;
// Basic test run&lt;br /&gt;
const launcher = new Launcher(&#039;./wdio.conf.ts&#039;)&lt;br /&gt;
const exitCode = await launcher.run()&lt;br /&gt;
console.log(`Tests completed with exit code: ${exitCode}`)&lt;br /&gt;
&lt;br /&gt;
// With CLI overrides&lt;br /&gt;
const launcher2 = new Launcher(&#039;./wdio.conf.ts&#039;, {&lt;br /&gt;
    spec: [&#039;./test/specs/smoke/*.ts&#039;],&lt;br /&gt;
    baseUrl: &#039;http://staging.example.com&#039;,&lt;br /&gt;
    logLevel: &#039;debug&#039;,&lt;br /&gt;
    bail: 1&lt;br /&gt;
})&lt;br /&gt;
const exitCode2 = await launcher2.run()&lt;br /&gt;
&lt;br /&gt;
// Access parsed config after initialization&lt;br /&gt;
await launcher2.initialize()&lt;br /&gt;
const config = launcher2.configParser.getConfig()&lt;br /&gt;
console.log(`Framework: ${config.framework}`)&lt;br /&gt;
console.log(`Max instances: ${config.maxInstances}`)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== CLI Handler Flow ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-cli/src/commands/run.ts L161-177&lt;br /&gt;
export async function launch(wdioConfPath: string, params: Partial&amp;lt;RunCommandArguments&amp;gt;) {&lt;br /&gt;
    const launcher = new Launcher(wdioConfPath, params)&lt;br /&gt;
    return launcher.run()&lt;br /&gt;
        .then((...args) =&amp;gt; {&lt;br /&gt;
            if (!process.env.WDIO_UNIT_TESTS) {&lt;br /&gt;
                process.exit(...args)&lt;br /&gt;
            }&lt;br /&gt;
        })&lt;br /&gt;
        .catch(err =&amp;gt; {&lt;br /&gt;
            console.error(err)&lt;br /&gt;
            if (!process.env.WDIO_UNIT_TESTS) {&lt;br /&gt;
                process.exit(1)&lt;br /&gt;
            }&lt;br /&gt;
        })&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Scheduling Algorithm ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;_runSpecs()&amp;lt;/code&amp;gt; method implements the scheduling loop:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-cli/src/launcher.ts L371-435 (simplified)&lt;br /&gt;
private _runSpecs(): boolean {&lt;br /&gt;
    const config = this.configParser.getConfig()&lt;br /&gt;
    while (this._getNumberOfRunningInstances() &amp;lt; config.maxInstances) {&lt;br /&gt;
        const schedulableCaps = this._schedule&lt;br /&gt;
            .filter((session) =&amp;gt; {&lt;br /&gt;
                // Bail check: stop if too many failures&lt;br /&gt;
                if (config.bail &amp;gt; 0 &amp;amp;&amp;amp; config.bail &amp;lt;= this._runnerFailed) return false&lt;br /&gt;
                // Global maxInstances check&lt;br /&gt;
                if (this._getNumberOfRunningInstances() &amp;gt;= config.maxInstances) return false&lt;br /&gt;
                // Capability has available slots and pending specs&lt;br /&gt;
                return session.availableInstances &amp;gt; 0 &amp;amp;&amp;amp; session.specs.length &amp;gt; 0&lt;br /&gt;
            })&lt;br /&gt;
            // Load balance: run capability with fewest running instances first&lt;br /&gt;
            .sort((a, b) =&amp;gt; a.runningInstances - b.runningInstances)&lt;br /&gt;
&lt;br /&gt;
        if (schedulableCaps.length === 0) break&lt;br /&gt;
&lt;br /&gt;
        const specs = schedulableCaps[0].specs.shift()&lt;br /&gt;
        this._startInstance(specs.files, schedulableCaps[0].caps, ...)&lt;br /&gt;
        schedulableCaps[0].availableInstances--&lt;br /&gt;
        schedulableCaps[0].runningInstances++&lt;br /&gt;
    }&lt;br /&gt;
    // Return true when all done&lt;br /&gt;
    return this._getNumberOfRunningInstances() === 0 &amp;amp;&amp;amp;&lt;br /&gt;
           this._getNumberOfSpecsLeft() === 0&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Retry Handling ==&lt;br /&gt;
&lt;br /&gt;
When a worker exits with a non-zero code and retries remain, the spec is re-queued:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-cli/src/launcher.ts L596-606&lt;br /&gt;
if (!passed &amp;amp;&amp;amp; retries &amp;gt; 0) {&lt;br /&gt;
    // specFileRetriesDeferred: true -&amp;gt; push (run after others)&lt;br /&gt;
    // specFileRetriesDeferred: false -&amp;gt; unshift (run immediately)&lt;br /&gt;
    const requeue = this.configParser.getConfig().specFileRetriesDeferred&lt;br /&gt;
        ? &#039;push&#039; : &#039;unshift&#039;&lt;br /&gt;
    this._schedule[cid].specs[requeue]({&lt;br /&gt;
        files: specs, retries: retries - 1, rid&lt;br /&gt;
    })&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Implements:&#039;&#039;&#039; [[Principle:Webdriverio_Webdriverio_Test_Execution_Orchestration|Principle: Test_Execution_Orchestration]]&lt;br /&gt;
* &#039;&#039;&#039;Uses:&#039;&#039;&#039; [[Implementation:Webdriverio_Webdriverio_ConfigParser_Class|Implementation: ConfigParser_Class]]&lt;br /&gt;
* &#039;&#039;&#039;Executes:&#039;&#039;&#039; [[Implementation:Webdriverio_Webdriverio_Mocha_BDD_Globals|Implementation: Mocha_BDD_Globals]]&lt;br /&gt;
* &#039;&#039;&#039;Reports to:&#039;&#039;&#039; [[Implementation:Webdriverio_Webdriverio_SpecReporter_Class|Implementation: SpecReporter_Class]]&lt;br /&gt;
* [[requires_env::Environment:Webdriverio_Webdriverio_Node_Runtime_Environment]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_ConfigParser_Class&amp;diff=30788</id>
		<title>Implementation:Webdriverio Webdriverio ConfigParser Class</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_ConfigParser_Class&amp;diff=30788"/>
		<updated>2026-09-27T10:53:23Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Webdriverio_Webdriverio_ConfigParser_Class}}&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Concrete tool for parsing and validating WebdriverIO configuration files provided by the &amp;lt;code&amp;gt;@wdio/config&amp;lt;/code&amp;gt; package.&lt;br /&gt;
&lt;br /&gt;
== Metadata ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Page Type&#039;&#039;&#039; || Implementation&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Repository&#039;&#039;&#039; || [https://github.com/webdriverio/webdriverio webdriverio/webdriverio]&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Package&#039;&#039;&#039; || &amp;lt;code&amp;gt;@wdio/config&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Source File&#039;&#039;&#039; || &amp;lt;code&amp;gt;packages/wdio-config/src/node/ConfigParser.ts&amp;lt;/code&amp;gt;, Lines L42-563&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Related Principle&#039;&#039;&#039; || [[Principle:Webdriverio_Webdriverio_Test_Configuration_Parsing|Principle: Test_Configuration_Parsing]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ConfigParser&amp;lt;/code&amp;gt; class reads a &amp;lt;code&amp;gt;wdio.conf.ts&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;wdio.conf.js&amp;lt;/code&amp;gt; configuration file, applies defaults from &amp;lt;code&amp;gt;DEFAULT_CONFIGS()&amp;lt;/code&amp;gt;, merges CLI overrides, resolves spec file paths using glob patterns, validates the result, and provides the finalized configuration via &amp;lt;code&amp;gt;getConfig()&amp;lt;/code&amp;gt;. It uses &amp;lt;code&amp;gt;deepmerge-ts&amp;lt;/code&amp;gt; for merging nested objects with a custom merge strategy that deduplicates array entries for &amp;lt;code&amp;gt;services&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;reporters&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;capabilities&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The class follows a two-phase initialization pattern: the constructor performs synchronous setup (applying defaults and merging initial CLI config), while the asynchronous &amp;lt;code&amp;gt;initialize()&amp;lt;/code&amp;gt; method loads the config file (which may require ESM dynamic import) and completes the merge. The &amp;lt;code&amp;gt;getConfig()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;getCapabilities()&amp;lt;/code&amp;gt; methods throw if called before initialization.&lt;br /&gt;
&lt;br /&gt;
== Source Reference ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-config/src/node/ConfigParser.ts&amp;lt;/code&amp;gt; || L42-563 || Main ConfigParser class&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-config/src/constants.ts&amp;lt;/code&amp;gt; || L7-89 || DEFAULT_CONFIGS, SUPPORTED_HOOKS, SUPPORTED_FILE_EXTENSIONS&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-config/src/node/FileSystemPathService.ts&amp;lt;/code&amp;gt; || -- || PathService implementation for glob resolution&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Signature ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
class ConfigParser {&lt;br /&gt;
    constructor(&lt;br /&gt;
        configFilePath: string,&lt;br /&gt;
        _initialConfig?: Partial&amp;lt;TestrunnerOptionsWithParameters&amp;gt;,&lt;br /&gt;
        _pathService?: PathService&lt;br /&gt;
    )&lt;br /&gt;
    async initialize(object?: MergeConfig): Promise&amp;lt;void&amp;gt;&lt;br /&gt;
    getConfig(): Required&amp;lt;WebdriverIO.Config&amp;gt;&lt;br /&gt;
    getCapabilities(i?: number): Capabilities.TestrunnerCapabilities | Capabilities.RequestedStandaloneCapabilities&lt;br /&gt;
    getSpecs(capSpecs?: Spec[], capExclude?: Spec[]): string[]&lt;br /&gt;
    addService(service: Services.Hooks): void&lt;br /&gt;
    static getFilePaths(patterns: Spec[], rootDir: string, findAndGlob?: PathService, hierarchyDepth?: number): Spec[]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Import ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
import { ConfigParser } from &#039;@wdio/config/node&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Inputs / Outputs Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Required !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;configFilePath&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Yes || Path to the wdio.conf.ts/js configuration file&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;_initialConfig&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Partial&amp;lt;TestrunnerOptionsWithParameters&amp;gt;&amp;lt;/code&amp;gt; || No || CLI argument overrides (spec, suite, watch, bail, coverage, etc.)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;_pathService&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;PathService&amp;lt;/code&amp;gt; || No || Custom path service for glob resolution (defaults to FileSystemPathService)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method !! Return Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getConfig()&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Required&amp;lt;WebdriverIO.Config&amp;gt;&amp;lt;/code&amp;gt; || Fully-merged configuration object with all defaults applied&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getCapabilities()&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Capabilities.TestrunnerCapabilities&amp;lt;/code&amp;gt; || Merged capabilities array or multiremote object&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;getSpecs()&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string[]&amp;lt;/code&amp;gt; || Resolved spec file paths filtered by exclude patterns, suite selection, and shard settings&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Key Configuration Properties ==&lt;br /&gt;
&lt;br /&gt;
The parsed configuration object includes these key properties:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;specs&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string[]&amp;lt;/code&amp;gt; || Glob patterns for spec files&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;capabilities&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Capabilities.TestrunnerCapabilities&amp;lt;/code&amp;gt; || Browser capability definitions&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;framework&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&#039;mocha&#039; | &#039;jasmine&#039; | &#039;cucumber&#039;&amp;lt;/code&amp;gt; || Test framework adapter&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;reporters&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string[]&amp;lt;/code&amp;gt; || Reporter plugins for output formatting&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;services&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string[]&amp;lt;/code&amp;gt; || Service plugins (driver management, etc.)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;baseUrl&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Base URL for relative navigation commands&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logLevel&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&#039;trace&#039; | &#039;debug&#039; | &#039;info&#039; | &#039;warn&#039; | &#039;error&#039; | &#039;silent&#039;&amp;lt;/code&amp;gt; || Logging verbosity&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;maxInstances&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt; || Maximum concurrent worker processes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mochaOpts&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;MochaOpts&amp;lt;/code&amp;gt; || Mocha framework options (timeout, ui, etc.)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cucumberOpts&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;CucumberOpts&amp;lt;/code&amp;gt; || Cucumber framework options&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;shard&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;{ current: number, total: number }&amp;lt;/code&amp;gt; || Shard configuration for distributed execution&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Example ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
import { ConfigParser } from &#039;@wdio/config/node&#039;&lt;br /&gt;
&lt;br /&gt;
// Create parser with config file path and CLI overrides&lt;br /&gt;
const configParser = new ConfigParser(&#039;./wdio.conf.ts&#039;, {&lt;br /&gt;
    spec: [&#039;./test/specs/login.ts&#039;],&lt;br /&gt;
    baseUrl: &#039;http://staging.example.com&#039;,&lt;br /&gt;
    logLevel: &#039;debug&#039;&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
// Initialize (loads config file asynchronously)&lt;br /&gt;
await configParser.initialize()&lt;br /&gt;
&lt;br /&gt;
// Access the finalized configuration&lt;br /&gt;
const config = configParser.getConfig()&lt;br /&gt;
console.log(config.framework)    // &#039;mocha&#039;&lt;br /&gt;
console.log(config.baseUrl)      // &#039;http://staging.example.com&#039; (CLI override applied)&lt;br /&gt;
console.log(config.logLevel)     // &#039;debug&#039; (CLI override applied)&lt;br /&gt;
&lt;br /&gt;
// Get resolved spec file paths&lt;br /&gt;
const specs = configParser.getSpecs()&lt;br /&gt;
console.log(specs)  // [&#039;/absolute/path/to/test/specs/login.ts&#039;]&lt;br /&gt;
&lt;br /&gt;
// Get capabilities&lt;br /&gt;
const caps = configParser.getCapabilities()&lt;br /&gt;
console.log(caps)   // [{ browserName: &#039;chrome&#039; }]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Programmatic usage in the Launcher ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// The Launcher class creates a ConfigParser internally&lt;br /&gt;
// packages/wdio-cli/src/launcher.ts L59-64&lt;br /&gt;
class Launcher {&lt;br /&gt;
    public configParser: ConfigParser&lt;br /&gt;
    constructor(configFilePath: string, args: Partial&amp;lt;RunCommandArguments&amp;gt; = {}) {&lt;br /&gt;
        this.configParser = new ConfigParser(configFilePath, args)&lt;br /&gt;
    }&lt;br /&gt;
    async run(): Promise&amp;lt;number | undefined&amp;gt; {&lt;br /&gt;
        await this.configParser.initialize(this._args)&lt;br /&gt;
        const config = this.configParser.getConfig()&lt;br /&gt;
        // ... orchestrate test execution using config&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Internal Behavior ==&lt;br /&gt;
&lt;br /&gt;
The merge strategy uses &amp;lt;code&amp;gt;deepmergeCustom&amp;lt;/code&amp;gt; from &amp;lt;code&amp;gt;deepmerge-ts&amp;lt;/code&amp;gt; with special handling for arrays:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-config/src/node/ConfigParser.ts L186-195&lt;br /&gt;
const customDeepMerge = deepmergeCustom({&lt;br /&gt;
    mergeArrays: ([oldValue, newValue], utils, meta) =&amp;gt; {&lt;br /&gt;
        const key = meta?.key as KeyWithMergeDuplication&lt;br /&gt;
        if (meta &amp;amp;&amp;amp; MERGE_DUPLICATION.includes(key)) {&lt;br /&gt;
            // For &#039;services&#039;, &#039;reporters&#039;, &#039;capabilities&#039;:&lt;br /&gt;
            // filter non-object entries from old, merge with new, deduplicate&lt;br /&gt;
            const origWithoutObjectEntries = oldValue.filter(&lt;br /&gt;
                (value) =&amp;gt; typeof value !== &#039;object&#039;&lt;br /&gt;
            )&lt;br /&gt;
            return Array.from(new Set(deepmerge(newValue, origWithoutObjectEntries)))&lt;br /&gt;
        }&lt;br /&gt;
        return utils.actions.defaultMerge&lt;br /&gt;
    }&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Spec resolution supports both flat string arrays and grouped arrays (string[][]) for parallel execution of related specs. The &amp;lt;code&amp;gt;getSpecs()&amp;lt;/code&amp;gt; method handles suite selection (&amp;lt;code&amp;gt;--suite&amp;lt;/code&amp;gt;), exclusion patterns (&amp;lt;code&amp;gt;--exclude&amp;lt;/code&amp;gt;), sharding (&amp;lt;code&amp;gt;--shard&amp;lt;/code&amp;gt;), and repetition (&amp;lt;code&amp;gt;--repeat&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Implements:&#039;&#039;&#039; [[Principle:Webdriverio_Webdriverio_Test_Configuration_Parsing|Principle: Test_Configuration_Parsing]]&lt;br /&gt;
* &#039;&#039;&#039;Used by:&#039;&#039;&#039; [[Implementation:Webdriverio_Webdriverio_Launcher_Class|Implementation: Launcher_Class]]&lt;br /&gt;
* [[requires_env::Environment:Webdriverio_Webdriverio_Node_Runtime_Environment]]&lt;br /&gt;
* [[uses_heuristic::Heuristic:Webdriverio_Webdriverio_Default_Timeout_Configuration]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_Cloud_Capabilities_Config&amp;diff=30787</id>
		<title>Implementation:Webdriverio Webdriverio Cloud Capabilities Config</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_Cloud_Capabilities_Config&amp;diff=30787"/>
		<updated>2026-09-27T10:53:22Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Webdriverio_Webdriverio_Cloud_Capabilities_Config}}&lt;br /&gt;
== Metadata ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Page ID&#039;&#039;&#039; || Cloud_Capabilities_Config&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Wiki&#039;&#039;&#039; || Webdriverio_Webdriverio&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || Implementation (API Doc)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Domains&#039;&#039;&#039; || Testing, Cloud, Configuration&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Knowledge Sources&#039;&#039;&#039; || Repo (https://github.com/webdriverio/webdriverio), Doc (https://webdriver.io/docs/browserstack-service), Doc (https://www.browserstack.com/docs/automate/selenium/getting-started/nodejs)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Related Principles&#039;&#039;&#039; || [[Principle:Webdriverio_Webdriverio_Cloud_Capabilities_Definition|Principle: Cloud_Capabilities_Definition]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Concrete configuration interface for cloud provider capabilities provided by WDIO cloud service packages. Cloud capabilities are defined using W3C capability objects augmented with vendor extensions. The &amp;lt;code&amp;gt;BrowserstackConfig&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SauceServiceConfig&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TestingbotOptions&amp;lt;/code&amp;gt; interfaces define the provider-specific configuration. These are used in the &amp;lt;code&amp;gt;capabilities&amp;lt;/code&amp;gt; array and &amp;lt;code&amp;gt;services&amp;lt;/code&amp;gt; configuration in &amp;lt;code&amp;gt;wdio.conf.ts&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
Cloud capabilities are configured at two levels:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Capabilities level&#039;&#039;&#039; -- W3C capability objects with vendor-namespaced extensions (&amp;lt;code&amp;gt;bstack:options&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sauce:options&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;tb:options&amp;lt;/code&amp;gt;) define per-session browser and platform settings.&lt;br /&gt;
# &#039;&#039;&#039;Service level&#039;&#039;&#039; -- Service configuration interfaces (&amp;lt;code&amp;gt;BrowserstackConfig&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SauceServiceConfig&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;TestingbotOptions&amp;lt;/code&amp;gt;) define cross-session settings like local tunneling, session naming behavior, test reporting, and accessibility automation.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-browserstack-service/src/types.ts&amp;lt;/code&amp;gt; || L62-212 || &amp;lt;code&amp;gt;BrowserstackConfig&amp;lt;/code&amp;gt; service configuration interface&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-sauce-service/src/types.ts&amp;lt;/code&amp;gt; || L4-51 || &amp;lt;code&amp;gt;SauceServiceConfig&amp;lt;/code&amp;gt; service configuration interface&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-testingbot-service/src/types.ts&amp;lt;/code&amp;gt; || L49-60 || &amp;lt;code&amp;gt;TestingbotOptions&amp;lt;/code&amp;gt; service configuration interface&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== BrowserStack Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== BrowserstackConfig Interface ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-browserstack-service/src/types.ts (L62-212)&lt;br /&gt;
export interface BrowserstackConfig {&lt;br /&gt;
    buildIdentifier?: string;           // Unique build ID (supports ${BUILD_NUMBER}, ${DATE_TIME})&lt;br /&gt;
    testObservability?: boolean;         // Enable Test Reporting and Analytics (default: true) [deprecated]&lt;br /&gt;
    testReporting?: boolean;             // Enable Test Reporting and Analytics (default: true)&lt;br /&gt;
    testObservabilityOptions?: TestObservabilityOptions;  // Reporting options [deprecated]&lt;br /&gt;
    testReportingOptions?: TestReportingOptions;          // Reporting options&lt;br /&gt;
    percy?: boolean;                     // Enable Percy visual testing (default: false)&lt;br /&gt;
    percyCaptureMode?: string;           // Screenshot capture mode: &#039;auto&#039;|&#039;click&#039;|&#039;testcase&#039;|&#039;screenshot&#039;|&#039;manual&#039;&lt;br /&gt;
    accessibility?: boolean;             // Enable Accessibility Automation (default: false)&lt;br /&gt;
    accessibilityOptions?: { [key: string]: unknown };  // Accessibility config&lt;br /&gt;
    app?: string | AppConfig;            // App file path or hashed ID for app testing&lt;br /&gt;
    browserstackLocal?: boolean;         // Enable local tunnel (default: false)&lt;br /&gt;
    forcedStop?: boolean;                // Kill tunnel without waiting for callback (default: false)&lt;br /&gt;
    opts?: Partial&amp;lt;BSOptions&amp;gt;;           // BrowserStack Local binary options&lt;br /&gt;
    preferScenarioName?: boolean;        // Use Cucumber Scenario name as session name (default: false)&lt;br /&gt;
    sessionNameFormat?: Function;        // Custom session name formatter&lt;br /&gt;
    sessionNameOmitTestTitle?: boolean;  // Omit test title from session name (default: false)&lt;br /&gt;
    sessionNamePrependTopLevelSuiteTitle?: boolean;  // Prepend suite title (default: false)&lt;br /&gt;
    setSessionName?: boolean;            // Auto-set session name (default: true)&lt;br /&gt;
    setSessionStatus?: boolean;          // Auto-set session status (default: true)&lt;br /&gt;
    turboScale?: boolean;               // Enable TurboScale grid (default: false)&lt;br /&gt;
    selfHeal?: boolean;                  // Enable self-healing selectors&lt;br /&gt;
    testOrchestrationOptions?: TestOrchestrationOptions;  // Smart test selection config&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== BrowserStack Capability Extensions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;I/O Contract -- &amp;lt;code&amp;gt;bstack:options&amp;lt;/code&amp;gt; namespace:&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;os&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Operating system (e.g., &amp;lt;code&amp;gt;&#039;Windows&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;OS X&#039;&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;osVersion&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || OS version (e.g., &amp;lt;code&amp;gt;&#039;11&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;Ventura&#039;&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;buildName&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Build name for grouping sessions in dashboard&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sessionName&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Session name for individual test identification&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;debug&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || Enable visual logs (screenshots at each step)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;video&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || Enable video recording of the session&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;networkLogs&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || Enable network traffic logging&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;consoleLogs&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Console log level (&amp;lt;code&amp;gt;&#039;disable&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;errors&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;warnings&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;info&#039;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&#039;verbose&#039;&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;local&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || Route traffic through BrowserStack Local tunnel&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;localIdentifier&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Tunnel identifier for multiple concurrent tunnels&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Sauce Labs Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== SauceServiceConfig Interface ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-sauce-service/src/types.ts (L4-51)&lt;br /&gt;
export interface SauceServiceConfig {&lt;br /&gt;
    maxErrorStackLength?: number;        // Max error stack lines sent to Sauce Labs&lt;br /&gt;
    tunnelName?: string;                 // Sauce Connect tunnel identifier&lt;br /&gt;
    tunnelOwner?: string;                // Tunnel owner account&lt;br /&gt;
    sauceConnect?: boolean;              // Enable Sauce Connect tunnel (default: false)&lt;br /&gt;
    sauceConnectOpts?: SauceConnectOptions;  // Sauce Connect binary options&lt;br /&gt;
    uploadLogs?: boolean;                // Upload WDIO logs to Sauce Labs (default: true)&lt;br /&gt;
    setJobName?: Function;               // Custom job name formatter&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sauce Labs Capability Extensions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;I/O Contract -- &amp;lt;code&amp;gt;sauce:options&amp;lt;/code&amp;gt; namespace:&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Build identifier for grouping jobs&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Test/job name&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tags&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string[]&amp;lt;/code&amp;gt; || Tags for filtering and searching jobs&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tunnelName&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Sauce Connect tunnel identifier&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tunnelOwner&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Owner of the shared tunnel&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;screenResolution&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Browser window resolution (e.g., &amp;lt;code&amp;gt;&#039;1920x1080&#039;&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;extendedDebugging&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || Enable extended debugging features&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== TestingBot Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== TestingbotOptions Interface ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-testingbot-service/src/types.ts (L49-60)&lt;br /&gt;
export interface TestingbotOptions {&lt;br /&gt;
    tbTunnel?: boolean;                  // Enable TestingBot Tunnel (default: false)&lt;br /&gt;
    tbTunnelOpts?: TunnelLauncherOptions;  // Tunnel binary options&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== TestingBot Capability Extensions ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;I/O Contract -- &amp;lt;code&amp;gt;tb:options&amp;lt;/code&amp;gt; namespace:&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tunnel-identifier&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Tunnel identifier for routing traffic&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;build&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Build name for grouping sessions&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || Test session name&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Full Example: BrowserStack Capabilities Configuration ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// wdio.conf.ts&lt;br /&gt;
export const config: WebdriverIO.Config = {&lt;br /&gt;
    user: process.env.BROWSERSTACK_USERNAME,&lt;br /&gt;
    key: process.env.BROWSERSTACK_ACCESS_KEY,&lt;br /&gt;
&lt;br /&gt;
    services: [[&#039;browserstack&#039;, {&lt;br /&gt;
        browserstackLocal: false,&lt;br /&gt;
        testReporting: true,&lt;br /&gt;
        testReportingOptions: {&lt;br /&gt;
            buildName: &#039;My Project - CI Build&#039;,&lt;br /&gt;
            projectName: &#039;My Project&#039;&lt;br /&gt;
        },&lt;br /&gt;
        setSessionName: true,&lt;br /&gt;
        setSessionStatus: true&lt;br /&gt;
    }]],&lt;br /&gt;
&lt;br /&gt;
    capabilities: [&lt;br /&gt;
        // Chrome on Windows 11&lt;br /&gt;
        {&lt;br /&gt;
            browserName: &#039;chrome&#039;,&lt;br /&gt;
            browserVersion: &#039;latest&#039;,&lt;br /&gt;
            &#039;bstack:options&#039;: {&lt;br /&gt;
                os: &#039;Windows&#039;,&lt;br /&gt;
                osVersion: &#039;11&#039;,&lt;br /&gt;
                buildName: &#039;Regression Suite&#039;,&lt;br /&gt;
                sessionName: &#039;Chrome Windows Test&#039;,&lt;br /&gt;
                debug: true,&lt;br /&gt;
                video: true,&lt;br /&gt;
                networkLogs: true&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        // Safari on macOS&lt;br /&gt;
        {&lt;br /&gt;
            browserName: &#039;safari&#039;,&lt;br /&gt;
            browserVersion: &#039;latest&#039;,&lt;br /&gt;
            &#039;bstack:options&#039;: {&lt;br /&gt;
                os: &#039;OS X&#039;,&lt;br /&gt;
                osVersion: &#039;Ventura&#039;,&lt;br /&gt;
                buildName: &#039;Regression Suite&#039;,&lt;br /&gt;
                sessionName: &#039;Safari macOS Test&#039;,&lt;br /&gt;
                debug: true,&lt;br /&gt;
                video: true&lt;br /&gt;
            }&lt;br /&gt;
        },&lt;br /&gt;
        // Firefox on Windows 10&lt;br /&gt;
        {&lt;br /&gt;
            browserName: &#039;firefox&#039;,&lt;br /&gt;
            browserVersion: &#039;latest&#039;,&lt;br /&gt;
            &#039;bstack:options&#039;: {&lt;br /&gt;
                os: &#039;Windows&#039;,&lt;br /&gt;
                osVersion: &#039;10&#039;,&lt;br /&gt;
                buildName: &#039;Regression Suite&#039;,&lt;br /&gt;
                sessionName: &#039;Firefox Windows Test&#039;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Full Example: Sauce Labs Capabilities Configuration ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// wdio.conf.ts&lt;br /&gt;
export const config: WebdriverIO.Config = {&lt;br /&gt;
    user: process.env.SAUCE_USERNAME,&lt;br /&gt;
    key: process.env.SAUCE_ACCESS_KEY,&lt;br /&gt;
&lt;br /&gt;
    services: [[&#039;sauce&#039;, {&lt;br /&gt;
        sauceConnect: false,&lt;br /&gt;
        uploadLogs: true&lt;br /&gt;
    }]],&lt;br /&gt;
&lt;br /&gt;
    capabilities: [{&lt;br /&gt;
        browserName: &#039;chrome&#039;,&lt;br /&gt;
        browserVersion: &#039;latest&#039;,&lt;br /&gt;
        platformName: &#039;Windows 11&#039;,&lt;br /&gt;
        &#039;sauce:options&#039;: {&lt;br /&gt;
            build: &#039;CI Build #42&#039;,&lt;br /&gt;
            name: &#039;Login Flow Tests&#039;,&lt;br /&gt;
            tags: [&#039;regression&#039;, &#039;login&#039;],&lt;br /&gt;
            screenResolution: &#039;1920x1080&#039;,&lt;br /&gt;
            extendedDebugging: true&lt;br /&gt;
        }&lt;br /&gt;
    }]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
=== Multi-browser matrix ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
capabilities: [&lt;br /&gt;
    { browserName: &#039;chrome&#039;, &#039;bstack:options&#039;: { os: &#039;Windows&#039;, osVersion: &#039;11&#039; } },&lt;br /&gt;
    { browserName: &#039;firefox&#039;, &#039;bstack:options&#039;: { os: &#039;Windows&#039;, osVersion: &#039;11&#039; } },&lt;br /&gt;
    { browserName: &#039;safari&#039;, &#039;bstack:options&#039;: { os: &#039;OS X&#039;, osVersion: &#039;Ventura&#039; } },&lt;br /&gt;
    { browserName: &#039;edge&#039;, &#039;bstack:options&#039;: { os: &#039;Windows&#039;, osVersion: &#039;11&#039; } }&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mobile device testing ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
capabilities: [{&lt;br /&gt;
    browserName: &#039;safari&#039;,&lt;br /&gt;
    &#039;bstack:options&#039;: {&lt;br /&gt;
        deviceName: &#039;iPhone 14&#039;,&lt;br /&gt;
        osVersion: &#039;16&#039;,&lt;br /&gt;
        realMobile: true,&lt;br /&gt;
        buildName: &#039;Mobile Tests&#039;&lt;br /&gt;
    }&lt;br /&gt;
}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;implements&#039;&#039;&#039; [[Principle:Webdriverio_Webdriverio_Cloud_Capabilities_Definition|Principle: Cloud_Capabilities_Definition]]&lt;br /&gt;
* [[requires_env::Environment:Webdriverio_Webdriverio_Cloud_Service_Credentials]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_Browser_Runner_Render&amp;diff=30786</id>
		<title>Implementation:Webdriverio Webdriverio Browser Runner Render</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_Browser_Runner_Render&amp;diff=30786"/>
		<updated>2026-09-27T10:53:22Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Webdriverio_Webdriverio_Browser_Runner_Render}}&lt;br /&gt;
== Metadata ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Page ID&#039;&#039;&#039; || Browser_Runner_Render&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Wiki&#039;&#039;&#039; || Webdriverio_Webdriverio&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || Implementation (Wrapper Doc)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Domains&#039;&#039;&#039; || Testing, Component_Testing, Frontend&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Knowledge Sources&#039;&#039;&#039; || Repo (https://github.com/webdriverio/webdriverio), Doc (https://webdriver.io/docs/component-testing)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Related Principles&#039;&#039;&#039; || [[Principle:Webdriverio_Webdriverio_Component_Test_Rendering|Principle: Component_Test_Rendering]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Wrapper documentation for component rendering in WebdriverIO browser runner tests using framework testing libraries. When using the WDIO browser runner, components are rendered using framework-specific testing libraries (e.g., &amp;lt;code&amp;gt;@testing-library/vue&amp;lt;/code&amp;gt; for Vue, &amp;lt;code&amp;gt;@testing-library/react&amp;lt;/code&amp;gt; for React). The &amp;lt;code&amp;gt;render()&amp;lt;/code&amp;gt; function mounts a component into the browser DOM. After rendering, &amp;lt;code&amp;gt;$()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;$$()&amp;lt;/code&amp;gt; query the component&#039;s DOM, and &amp;lt;code&amp;gt;expect()&amp;lt;/code&amp;gt; validates output. The browser runner includes mock/spy support via &amp;lt;code&amp;gt;@vitest/spy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The browser runner render flow involves three stages:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Rendering&#039;&#039;&#039; -- The framework-specific &amp;lt;code&amp;gt;render()&amp;lt;/code&amp;gt; function mounts a component into the real browser DOM with specified props and slots.&lt;br /&gt;
# &#039;&#039;&#039;Querying&#039;&#039;&#039; -- Testing Library query utilities (&amp;lt;code&amp;gt;getByText&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;getByRole&amp;lt;/code&amp;gt;, etc.) or WebdriverIO selectors (&amp;lt;code&amp;gt;$()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;$$()&amp;lt;/code&amp;gt;) locate elements in the rendered output.&lt;br /&gt;
# &#039;&#039;&#039;Asserting&#039;&#039;&#039; -- WebdriverIO&#039;s &amp;lt;code&amp;gt;expect()&amp;lt;/code&amp;gt; function with &amp;lt;code&amp;gt;expect-webdriverio&amp;lt;/code&amp;gt; matchers validates the component&#039;s output and behavior.&lt;br /&gt;
&lt;br /&gt;
The browser runner&#039;s expect system is implemented in &amp;lt;code&amp;gt;packages/wdio-browser-runner/src/browser/expect.ts&amp;lt;/code&amp;gt;, which creates matcher factories that serialize assertions and send them to the Node.js worker process for evaluation. The mocking system in &amp;lt;code&amp;gt;packages/wdio-browser-runner/src/browser/spy.ts&amp;lt;/code&amp;gt; re-exports &amp;lt;code&amp;gt;@vitest/spy&amp;lt;/code&amp;gt; and provides &amp;lt;code&amp;gt;mock()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;unmock()&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;mocked()&amp;lt;/code&amp;gt; functions.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;examples/wdio/vite-vue-example/src/components/HelloWorld.test.ts&amp;lt;/code&amp;gt; || L1-27 || Full Vue component test example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-browser-runner/src/browser/expect.ts&amp;lt;/code&amp;gt; || L1-50+ || Browser-side expect matcher factory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-browser-runner/src/browser/spy.ts&amp;lt;/code&amp;gt; || L1-55 || Mock/spy module (re-exports @vitest/spy, provides mock/unmock)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;examples/wdio/vite-vue-example/src/components/HelloWorld.vue&amp;lt;/code&amp;gt; || L1-38 || Vue component under test&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== APIs ==&lt;br /&gt;
&lt;br /&gt;
=== render(Component, options?) ===&lt;br /&gt;
&lt;br /&gt;
Mounts a UI component into the browser DOM. Provided by the framework-specific testing library.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;For Vue:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
import { render } from &#039;@testing-library/vue&#039;&lt;br /&gt;
import Component from &#039;./MyComponent.vue&#039;&lt;br /&gt;
&lt;br /&gt;
const { getByText, getByRole, container } = render(Component, {&lt;br /&gt;
    props: { msg: &#039;Hello&#039; },&lt;br /&gt;
    slots: { default: &#039;&amp;lt;span&amp;gt;slot content&amp;lt;/span&amp;gt;&#039; }&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;I/O Contract:&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Component&amp;lt;/code&amp;gt; || Framework component || The component to render&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;options.props&amp;lt;/code&amp;gt; || Object (optional) || Props to pass to the component&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;options.slots&amp;lt;/code&amp;gt; || Object (optional) || Slot content (Vue-specific)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Returns&#039;&#039;&#039; || RenderResult || Object with query utilities: &amp;lt;code&amp;gt;getByText&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;getByRole&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;container&amp;lt;/code&amp;gt;, etc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== $(&#039;selector&#039;) / $$(&#039;selector&#039;) ===&lt;br /&gt;
&lt;br /&gt;
WebdriverIO global selectors for querying the rendered DOM. Can also wrap DOM elements returned by Testing Library queries.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// Query by CSS selector&lt;br /&gt;
const button = await $(&#039;button.submit&#039;)&lt;br /&gt;
&lt;br /&gt;
// Wrap a Testing Library query result&lt;br /&gt;
const { getByText } = render(Component)&lt;br /&gt;
const element = await $(getByText(&#039;Click me&#039;))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;I/O Contract:&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;selector&amp;lt;/code&amp;gt; || string or HTMLElement || CSS selector string or DOM element&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Returns&#039;&#039;&#039; || &amp;lt;code&amp;gt;ChainablePromiseElement&amp;lt;/code&amp;gt; || WebdriverIO element wrapper with full command API&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== expect(element).matcher() ===&lt;br /&gt;
&lt;br /&gt;
Assertion function using &amp;lt;code&amp;gt;expect-webdriverio&amp;lt;/code&amp;gt; matchers. The browser runner&#039;s expect implementation serializes matcher calls and evaluates them in the Node.js worker process.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
await expect(button).toHaveText(&#039;count is 2&#039;)&lt;br /&gt;
await expect($(&#039;.message&#039;)).toBeDisplayed()&lt;br /&gt;
await expect($(&#039;input&#039;)).toHaveValue(&#039;test&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== mock(path, factory?) / unmock(moduleName) ===&lt;br /&gt;
&lt;br /&gt;
Module mocking functions provided by the browser runner&#039;s spy module.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
import { fn, spyOn } from &#039;@wdio/browser-runner&#039;&lt;br /&gt;
&lt;br /&gt;
// Mock a module with a factory&lt;br /&gt;
mock(&#039;./api.js&#039;, () =&amp;gt; ({&lt;br /&gt;
    fetchData: fn().mockResolvedValue({ items: [] })&lt;br /&gt;
}))&lt;br /&gt;
&lt;br /&gt;
// Remove a mock&lt;br /&gt;
unmock(&#039;./api.js&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;I/O Contract:&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Function !! Parameters !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mock(path, factory?)&amp;lt;/code&amp;gt; || path: string, factory: function (optional) || Replaces module imports with factory return value&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;unmock(moduleName)&amp;lt;/code&amp;gt; || moduleName: string || Removes a previously registered mock&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mocked(item)&amp;lt;/code&amp;gt; || item: T || Type utility for casting to MaybeMocked&amp;lt;T&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;fn()&amp;lt;/code&amp;gt; || None || Creates a mock function (from @vitest/spy)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;spyOn(obj, method)&amp;lt;/code&amp;gt; || obj: object, method: string || Creates a spy on an object method (from @vitest/spy)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Full Example: Vue Component Test ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Component under test (&amp;lt;code&amp;gt;HelloWorld.vue&amp;lt;/code&amp;gt;):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script setup lang=&amp;quot;ts&amp;quot;&amp;gt;&lt;br /&gt;
import { ref } from &#039;vue&#039;&lt;br /&gt;
&lt;br /&gt;
defineProps&amp;lt;{ msg: string }&amp;gt;()&lt;br /&gt;
&lt;br /&gt;
const count = ref(0)&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;template&amp;gt;&lt;br /&gt;
  &amp;lt;h1&amp;gt;{{ msg }}&amp;lt;/h1&amp;gt;&lt;br /&gt;
  &amp;lt;div class=&amp;quot;card&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;button type=&amp;quot;button&amp;quot; @click=&amp;quot;count++&amp;quot;&amp;gt;count is {{ count }}&amp;lt;/button&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/template&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test file (&amp;lt;code&amp;gt;HelloWorld.test.ts&amp;lt;/code&amp;gt;):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
import { expect, $ } from &#039;@wdio/globals&#039;&lt;br /&gt;
import { render } from &#039;@testing-library/vue&#039;&lt;br /&gt;
&lt;br /&gt;
import * as matchers from &#039;@testing-library/jest-dom/matchers&#039;&lt;br /&gt;
expect.extend(matchers as any)&lt;br /&gt;
&lt;br /&gt;
import Component from &#039;./HelloWorld.vue&#039;&lt;br /&gt;
&lt;br /&gt;
describe(&#039;Vue Component Tests&#039;, () =&amp;gt; {&lt;br /&gt;
    it(&#039;should do something cool&#039;, async () =&amp;gt; {&lt;br /&gt;
        // The render method returns a collection of utilities to query your component.&lt;br /&gt;
        const { getByText } = render(Component)&lt;br /&gt;
&lt;br /&gt;
        // getByText returns the first matching node for the provided text, and&lt;br /&gt;
        // throws an error if no elements match or if more than one match is found.&lt;br /&gt;
        getByText(&#039;count is 0&#039;)&lt;br /&gt;
&lt;br /&gt;
        const button = await $(getByText(&#039;count is 0&#039;))&lt;br /&gt;
&lt;br /&gt;
        // Dispatch a native click event to our button element.&lt;br /&gt;
        await button.click()&lt;br /&gt;
        await button.click()&lt;br /&gt;
&lt;br /&gt;
        getByText(&#039;count is 2&#039;)&lt;br /&gt;
        await expect(button).toHaveText(&#039;count is 2&#039;)&lt;br /&gt;
    })&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Test flow:&#039;&#039;&#039;&lt;br /&gt;
# Import &amp;lt;code&amp;gt;render&amp;lt;/code&amp;gt; from &amp;lt;code&amp;gt;@testing-library/vue&amp;lt;/code&amp;gt; and the component.&lt;br /&gt;
# Call &amp;lt;code&amp;gt;render(Component)&amp;lt;/code&amp;gt; to mount the component in the real browser DOM.&lt;br /&gt;
# Use &amp;lt;code&amp;gt;getByText(&#039;count is 0&#039;)&amp;lt;/code&amp;gt; to verify initial render text.&lt;br /&gt;
# Wrap the DOM element with &amp;lt;code&amp;gt;$(getByText(...))&amp;lt;/code&amp;gt; to get a WebdriverIO element.&lt;br /&gt;
# Call &amp;lt;code&amp;gt;.click()&amp;lt;/code&amp;gt; twice to simulate user interaction.&lt;br /&gt;
# Assert the button text changed to &amp;lt;code&amp;gt;&#039;count is 2&#039;&amp;lt;/code&amp;gt; using &amp;lt;code&amp;gt;toHaveText()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Import Summary ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// WebdriverIO globals (available in browser runner context)&lt;br /&gt;
import { expect, $ } from &#039;@wdio/globals&#039;&lt;br /&gt;
&lt;br /&gt;
// Framework-specific render function&lt;br /&gt;
import { render } from &#039;@testing-library/vue&#039;    // Vue&lt;br /&gt;
import { render } from &#039;@testing-library/react&#039;   // React&lt;br /&gt;
import { render } from &#039;@testing-library/svelte&#039;   // Svelte&lt;br /&gt;
&lt;br /&gt;
// Mocking (from browser runner)&lt;br /&gt;
import { fn, spyOn, mock, unmock } from &#039;@wdio/browser-runner&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;implements&#039;&#039;&#039; [[Principle:Webdriverio_Webdriverio_Component_Test_Rendering|Principle: Component_Test_Rendering]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_Browser_Runner_Config&amp;diff=30785</id>
		<title>Implementation:Webdriverio Webdriverio Browser Runner Config</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_Browser_Runner_Config&amp;diff=30785"/>
		<updated>2026-09-27T10:53:21Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Webdriverio_Webdriverio_Browser_Runner_Config}}&lt;br /&gt;
== Metadata ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Page ID&#039;&#039;&#039; || Browser_Runner_Config&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Wiki&#039;&#039;&#039; || Webdriverio_Webdriverio&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || Implementation (API Doc)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Domains&#039;&#039;&#039; || Testing, Configuration, Frontend&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Knowledge Sources&#039;&#039;&#039; || Repo (https://github.com/webdriverio/webdriverio), Doc (https://webdriver.io/docs/component-testing/vue)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Related Principles&#039;&#039;&#039; || [[Principle:Webdriverio_Webdriverio_Browser_Runner_Configuration|Principle: Browser_Runner_Configuration]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Concrete tool for configuring the Vite-based browser runner provided by the &amp;lt;code&amp;gt;@wdio/browser-runner&amp;lt;/code&amp;gt; package. The browser runner configuration is specified as the &amp;lt;code&amp;gt;runner&amp;lt;/code&amp;gt; property in &amp;lt;code&amp;gt;wdio.conf.ts&amp;lt;/code&amp;gt;. It configures Vite dev server settings, framework presets, and project paths. The &amp;lt;code&amp;gt;PRESET_DEPENDENCIES&amp;lt;/code&amp;gt; constant maps framework names to their required Vite plugins. The &amp;lt;code&amp;gt;DEFAULT_VITE_CONFIG&amp;lt;/code&amp;gt; provides sensible defaults for testing.&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The browser runner configuration controls how Vite serves test files to the browser. It consists of three layers:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;User configuration&#039;&#039;&#039; -- The &amp;lt;code&amp;gt;BrowserRunnerOptions&amp;lt;/code&amp;gt; interface in &amp;lt;code&amp;gt;wdio.conf.ts&amp;lt;/code&amp;gt; specifying preset, viteConfig, rootDir, and other options.&lt;br /&gt;
# &#039;&#039;&#039;Preset resolution&#039;&#039;&#039; -- The &amp;lt;code&amp;gt;PRESET_DEPENDENCIES&amp;lt;/code&amp;gt; constant that maps preset names to Vite plugin packages and their export names.&lt;br /&gt;
# &#039;&#039;&#039;Default Vite config&#039;&#039;&#039; -- The &amp;lt;code&amp;gt;DEFAULT_VITE_CONFIG&amp;lt;/code&amp;gt; that provides sensible defaults including CJS dependency optimization, source maps, and logging.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-browser-runner/src/types.ts&amp;lt;/code&amp;gt; || L75-125 || &amp;lt;code&amp;gt;BrowserRunnerOptions&amp;lt;/code&amp;gt; interface definition&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-browser-runner/src/vite/constants.ts&amp;lt;/code&amp;gt; || L14-31 || &amp;lt;code&amp;gt;PRESET_DEPENDENCIES&amp;lt;/code&amp;gt; mapping framework presets to Vite plugins&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-browser-runner/src/vite/constants.ts&amp;lt;/code&amp;gt; || L33-80 || &amp;lt;code&amp;gt;DEFAULT_VITE_CONFIG&amp;lt;/code&amp;gt; with optimized defaults&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-browser-runner/src/vite/frameworks/index.ts&amp;lt;/code&amp;gt; || L7-26 || &amp;lt;code&amp;gt;updateViteConfig&amp;lt;/code&amp;gt; function for framework-specific optimizations&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-browser-runner/src/types.ts&amp;lt;/code&amp;gt; || L13 || &amp;lt;code&amp;gt;FrameworkPreset&amp;lt;/code&amp;gt; type definition&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;examples/wdio/vite-vue-example/wdio.conf.ts&amp;lt;/code&amp;gt; || L1-300 || Full example wdio.conf.ts with browser runner&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Configuration Format ==&lt;br /&gt;
&lt;br /&gt;
The browser runner is configured via the &amp;lt;code&amp;gt;runner&amp;lt;/code&amp;gt; property in &amp;lt;code&amp;gt;wdio.conf.ts&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
runner: [&#039;browser&#039;, BrowserRunnerOptions]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== BrowserRunnerOptions Interface ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-browser-runner/src/types.ts&lt;br /&gt;
export interface BrowserRunnerOptions {&lt;br /&gt;
    rootDir?: string                    // Project root directory (default: process.cwd())&lt;br /&gt;
    preset?: FrameworkPreset            // Framework preset for auto-configuration&lt;br /&gt;
    viteConfig?: string | InlineConfig | ((env: ConfigEnv) =&amp;gt; InlineConfig | Promise&amp;lt;InlineConfig&amp;gt;)&lt;br /&gt;
    headless?: boolean                  // Run in headless mode (default: false, true in CI)&lt;br /&gt;
    coverage?: CoverageOptions          // Test coverage settings&lt;br /&gt;
    automock?: boolean                  // Auto-mock dependencies in automockDir (default: true)&lt;br /&gt;
    automockDir?: string                // Path to auto-mock directory (default: ./__mocks__)&lt;br /&gt;
    host?: string                       // Custom hostname for remote grids (default: http://0.0.0.0)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;I/O Contract:&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;rootDir&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;process.cwd()&amp;lt;/code&amp;gt; || Project root for file resolution&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;preset&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;FrameworkPreset&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;undefined&amp;lt;/code&amp;gt; || Auto-configures Vite plugin for framework&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;viteConfig&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string &amp;amp;#124; InlineConfig &amp;amp;#124; Function&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;undefined&amp;lt;/code&amp;gt; || Custom Vite configuration (merged with defaults)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;headless&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; (CI: &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;) || Headless browser mode&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;coverage&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;CoverageOptions&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;undefined&amp;lt;/code&amp;gt; || Istanbul coverage settings&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;automock&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; || Auto-mock from &amp;lt;code&amp;gt;automockDir&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;automockDir&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;./__mocks__&amp;lt;/code&amp;gt; || Directory for auto-mock files&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;host&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;http://0.0.0.0&amp;lt;/code&amp;gt; || Server hostname for remote grids&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== FrameworkPreset Type ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-browser-runner/src/types.ts&lt;br /&gt;
export type FrameworkPreset = &#039;react&#039; | &#039;preact&#039; | &#039;vue&#039; | &#039;svelte&#039; | &#039;lit&#039; | &#039;solid&#039; | &#039;stencil&#039;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== PRESET_DEPENDENCIES Mapping ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-browser-runner/src/vite/constants.ts&lt;br /&gt;
export const PRESET_DEPENDENCIES: Record&amp;lt;FrameworkPreset, [string, string, unknown] | undefined&amp;gt; = {&lt;br /&gt;
    react: [&#039;@vitejs/plugin-react&#039;, &#039;default&#039;, {&lt;br /&gt;
        babel: {&lt;br /&gt;
            assumptions: { setPublicClassFields: true },&lt;br /&gt;
            parserOpts: { plugins: [&#039;decorators-legacy&#039;, &#039;classProperties&#039;] }&lt;br /&gt;
        }&lt;br /&gt;
    }],&lt;br /&gt;
    preact: [&#039;@preact/preset-vite&#039;, &#039;default&#039;, undefined],&lt;br /&gt;
    vue: [&#039;@vitejs/plugin-vue&#039;, &#039;default&#039;, undefined],&lt;br /&gt;
    svelte: [&#039;@sveltejs/vite-plugin-svelte&#039;, &#039;svelte&#039;, undefined],&lt;br /&gt;
    solid: [&#039;vite-plugin-solid&#039;, &#039;default&#039;, undefined],&lt;br /&gt;
    stencil: undefined,&lt;br /&gt;
    lit: undefined&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Mapping structure:&#039;&#039;&#039; Each entry is a tuple &amp;lt;code&amp;gt;[packageName, exportName, pluginOptions]&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;undefined&amp;lt;/code&amp;gt; (for frameworks that do not need a Vite plugin).&lt;br /&gt;
&lt;br /&gt;
=== DEFAULT_VITE_CONFIG ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-browser-runner/src/vite/constants.ts&lt;br /&gt;
export const DEFAULT_VITE_CONFIG: Partial&amp;lt;InlineConfig&amp;gt; = {&lt;br /&gt;
    configFile: false,&lt;br /&gt;
    server: { host: &#039;localhost&#039; },&lt;br /&gt;
    logLevel: &#039;info&#039;,&lt;br /&gt;
    plugins: [topLevelAwait()],&lt;br /&gt;
    build: {&lt;br /&gt;
        sourcemap: &#039;inline&#039;,&lt;br /&gt;
        commonjsOptions: { include: [/node_modules/] }&lt;br /&gt;
    },&lt;br /&gt;
    optimizeDeps: {&lt;br /&gt;
        include: [&lt;br /&gt;
            &#039;expect&#039;, &#039;minimatch&#039;, &#039;css-shorthand-properties&#039;, &#039;lodash.merge&#039;,&lt;br /&gt;
            &#039;lodash.zip&#039;, &#039;ws&#039;, &#039;lodash.clonedeep&#039;, &#039;lodash.pickby&#039;,&lt;br /&gt;
            &#039;lodash.flattendeep&#039;, &#039;aria-query&#039;, &#039;grapheme-splitter&#039;,&lt;br /&gt;
            &#039;css-value&#039;, &#039;rgb2hex&#039;, &#039;p-iteration&#039;, &#039;deepmerge-ts&#039;,&lt;br /&gt;
            &#039;jest-util&#039;, &#039;jest-matcher-utils&#039;, &#039;split2&#039;&lt;br /&gt;
        ],&lt;br /&gt;
        esbuildOptions: {&lt;br /&gt;
            logLevel: &#039;silent&#039;,&lt;br /&gt;
            define: { global: &#039;globalThis&#039; },&lt;br /&gt;
            plugins: [&lt;br /&gt;
                esbuildCommonjs([&#039;@testing-library/vue&#039;]),&lt;br /&gt;
                codeFrameFix()&lt;br /&gt;
            ]&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Framework-Specific Optimizations ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;updateViteConfig&amp;lt;/code&amp;gt; function in &amp;lt;code&amp;gt;packages/wdio-browser-runner/src/vite/frameworks/index.ts&amp;lt;/code&amp;gt; auto-detects and applies optimizations for specific project types:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-browser-runner/src/vite/frameworks/index.ts&lt;br /&gt;
export default async function updateViteConfig (&lt;br /&gt;
    options: WebdriverIO.BrowserRunnerOptions,&lt;br /&gt;
    config: WebdriverIO.Config&lt;br /&gt;
) {&lt;br /&gt;
    const optimizations: InlineConfig = {}&lt;br /&gt;
    const rootDir = options.rootDir || config.rootDir || process.cwd()&lt;br /&gt;
&lt;br /&gt;
    if (await isNuxtFramework(rootDir)) {&lt;br /&gt;
        Object.assign(optimizations, await optimizeForNuxt(options, config))&lt;br /&gt;
    }&lt;br /&gt;
    if (await isUsingTailwindCSS(rootDir)) {&lt;br /&gt;
        Object.assign(optimizations, await optimizeForTailwindCSS(rootDir))&lt;br /&gt;
    }&lt;br /&gt;
    if (await isUsingStencilJS(rootDir, options)) {&lt;br /&gt;
        Object.assign(optimizations, await optimizeForStencil(rootDir))&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return optimizations&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Full Example: wdio.conf.ts for Vue Component Testing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// examples/wdio/vite-vue-example/wdio.conf.ts&lt;br /&gt;
import url from &#039;node:url&#039;&lt;br /&gt;
import viteConfig from &#039;./vite.config.js&#039;&lt;br /&gt;
&lt;br /&gt;
const __dirname = url.fileURLToPath(new URL(&#039;.&#039;, import.meta.url))&lt;br /&gt;
&lt;br /&gt;
export const config: WebdriverIO.Config = {&lt;br /&gt;
    runner: [&#039;browser&#039;, {&lt;br /&gt;
        viteConfig,&lt;br /&gt;
        rootDir: __dirname&lt;br /&gt;
    }],&lt;br /&gt;
    specs: [&#039;./src/**/*.test.ts&#039;],&lt;br /&gt;
    maxInstances: 10,&lt;br /&gt;
    capabilities: [{&lt;br /&gt;
        maxInstances: 5,&lt;br /&gt;
        browserName: &#039;chrome&#039;&lt;br /&gt;
    }],&lt;br /&gt;
    logLevel: &#039;info&#039;,&lt;br /&gt;
    bail: 0,&lt;br /&gt;
    baseUrl: &#039;&#039;,&lt;br /&gt;
    waitforTimeout: 10000,&lt;br /&gt;
    connectionRetryTimeout: 120000,&lt;br /&gt;
    connectionRetryCount: 3,&lt;br /&gt;
    services: [],&lt;br /&gt;
    framework: &#039;mocha&#039;,&lt;br /&gt;
    reporters: [&#039;spec&#039;],&lt;br /&gt;
    mochaOpts: {&lt;br /&gt;
        ui: &#039;bdd&#039;,&lt;br /&gt;
        timeout: 60000&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
=== Minimal Vue setup ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// wdio.conf.ts&lt;br /&gt;
export const config: WebdriverIO.Config = {&lt;br /&gt;
    runner: [&#039;browser&#039;, { preset: &#039;vue&#039; }],&lt;br /&gt;
    specs: [&#039;./src/**/*.test.ts&#039;],&lt;br /&gt;
    capabilities: [{ browserName: &#039;chrome&#039; }],&lt;br /&gt;
    framework: &#039;mocha&#039;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== React with coverage ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// wdio.conf.ts&lt;br /&gt;
export const config: WebdriverIO.Config = {&lt;br /&gt;
    runner: [&#039;browser&#039;, {&lt;br /&gt;
        preset: &#039;react&#039;,&lt;br /&gt;
        coverage: {&lt;br /&gt;
            enabled: true,&lt;br /&gt;
            reportsDirectory: &#039;./coverage&#039;,&lt;br /&gt;
            reporter: [&#039;text&#039;, &#039;html&#039;, &#039;json-summary&#039;],&lt;br /&gt;
            lines: 80,&lt;br /&gt;
            functions: 80,&lt;br /&gt;
            branches: 80,&lt;br /&gt;
            statements: 80&lt;br /&gt;
        }&lt;br /&gt;
    }],&lt;br /&gt;
    specs: [&#039;./src/**/*.test.tsx&#039;],&lt;br /&gt;
    capabilities: [{ browserName: &#039;chrome&#039; }],&lt;br /&gt;
    framework: &#039;mocha&#039;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Svelte with headless mode ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// wdio.conf.ts&lt;br /&gt;
export const config: WebdriverIO.Config = {&lt;br /&gt;
    runner: [&#039;browser&#039;, {&lt;br /&gt;
        preset: &#039;svelte&#039;,&lt;br /&gt;
        headless: true&lt;br /&gt;
    }],&lt;br /&gt;
    specs: [&#039;./src/**/*.test.ts&#039;],&lt;br /&gt;
    capabilities: [{ browserName: &#039;chrome&#039; }],&lt;br /&gt;
    framework: &#039;mocha&#039;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;implements&#039;&#039;&#039; [[Principle:Webdriverio_Webdriverio_Browser_Runner_Configuration|Principle: Browser_Runner_Configuration]]&lt;br /&gt;
* [[requires_env::Environment:Webdriverio_Webdriverio_Node_Runtime_Environment]]&lt;br /&gt;
* [[requires_env::Environment:Webdriverio_Webdriverio_Browser_Driver_Environment]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_BrowserStack_Launcher_Tunnel&amp;diff=30784</id>
		<title>Implementation:Webdriverio Webdriverio BrowserStack Launcher Tunnel</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Webdriverio_Webdriverio_BrowserStack_Launcher_Tunnel&amp;diff=30784"/>
		<updated>2026-09-27T10:53:20Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Webdriverio_Webdriverio_BrowserStack_Launcher_Tunnel}}&lt;br /&gt;
== Metadata ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field !! Value&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Page ID&#039;&#039;&#039; || BrowserStack_Launcher_Tunnel&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Wiki&#039;&#039;&#039; || Webdriverio_Webdriverio&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Type&#039;&#039;&#039; || Implementation (API Doc)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Domains&#039;&#039;&#039; || Testing, Cloud, Networking&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Knowledge Sources&#039;&#039;&#039; || Repo (https://github.com/webdriverio/webdriverio), Doc (https://www.browserstack.com/docs/local-testing)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Related Principles&#039;&#039;&#039; || [[Principle:Webdriverio_Webdriverio_Local_Tunnel_Connectivity|Principle: Local_Tunnel_Connectivity]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Concrete tool for managing local tunnels within the WDIO service lifecycle for cloud testing providers. This document covers the BrowserStack Local tunnel (primary), Sauce Connect tunnel, and TestingBot tunnel implementations. Each service manages the tunnel binary lifecycle: starting in &amp;lt;code&amp;gt;onPrepare&amp;lt;/code&amp;gt; (before any tests run), automatically injecting tunnel identifiers into capabilities, and stopping in &amp;lt;code&amp;gt;onComplete&amp;lt;/code&amp;gt; (after all tests finish).&lt;br /&gt;
&lt;br /&gt;
== Description ==&lt;br /&gt;
&lt;br /&gt;
The tunnel launcher services follow a consistent pattern across all three providers:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Constructor&#039;&#039;&#039; -- Receives service options and WDIO configuration.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;onPrepare&amp;lt;/code&amp;gt;&#039;&#039;&#039; -- Checks if tunneling is enabled, configures tunnel options, injects tunnel identifiers into capabilities, starts the tunnel binary, and measures boot time.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;code&amp;gt;onComplete&amp;lt;/code&amp;gt;&#039;&#039;&#039; -- Stops the tunnel binary and cleans up.&lt;br /&gt;
&lt;br /&gt;
The BrowserStack implementation is the most feature-rich, with support for local testing, test reporting, Percy visual testing, accessibility automation, and test orchestration. The tunnel management is one component of the larger &amp;lt;code&amp;gt;BrowserstackLauncherService&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Source ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! File !! Lines !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-browserstack-service/src/launcher.ts&amp;lt;/code&amp;gt; || L70-577 || &amp;lt;code&amp;gt;BrowserstackLauncherService&amp;lt;/code&amp;gt; class with tunnel management in &amp;lt;code&amp;gt;onPrepare&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-browserstack-service/src/launcher.ts&amp;lt;/code&amp;gt; || L529-577 || BrowserStack Local tunnel start logic&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-browserstack-service/src/launcher.ts&amp;lt;/code&amp;gt; || L580-670+ || &amp;lt;code&amp;gt;onComplete&amp;lt;/code&amp;gt; hook with tunnel stop logic&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-sauce-service/src/launcher.ts&amp;lt;/code&amp;gt; || L20-143 || &amp;lt;code&amp;gt;SauceLauncher&amp;lt;/code&amp;gt; with Sauce Connect tunnel management&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-testingbot-service/src/launcher.ts&amp;lt;/code&amp;gt; || L12-78 || &amp;lt;code&amp;gt;TestingBotLauncher&amp;lt;/code&amp;gt; with TestingBot Tunnel management&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-browserstack-service/src/types.ts&amp;lt;/code&amp;gt; || L62-212 || &amp;lt;code&amp;gt;BrowserstackConfig&amp;lt;/code&amp;gt; interface (tunnel options)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-sauce-service/src/types.ts&amp;lt;/code&amp;gt; || L4-51 || &amp;lt;code&amp;gt;SauceServiceConfig&amp;lt;/code&amp;gt; interface (tunnel options)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;packages/wdio-testingbot-service/src/types.ts&amp;lt;/code&amp;gt; || L49-60 || &amp;lt;code&amp;gt;TestingbotOptions&amp;lt;/code&amp;gt; interface (tunnel options)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== BrowserStack Local Tunnel ==&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
services: [[&#039;browserstack&#039;, {&lt;br /&gt;
    browserstackLocal: boolean,     // Enable/disable the tunnel (default: false)&lt;br /&gt;
    forcedStop: boolean,            // Kill tunnel without waiting for callback (default: false)&lt;br /&gt;
    opts: Partial&amp;lt;BSOptions&amp;gt;        // BrowserStack Local binary options&lt;br /&gt;
}]]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;I/O Contract -- Service Configuration:&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;browserstackLocal&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; || Enable local tunnel&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;forcedStop&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; || Force-kill tunnel binary on completion&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;opts&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Partial&amp;lt;BSOptions&amp;gt;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; || Binary options (localIdentifier, verbose, proxy, etc.)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;opts.localIdentifier&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || auto-generated || Unique identifier for this tunnel instance&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Tunnel Start (onPrepare) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-browserstack-service/src/launcher.ts (L529-577)&lt;br /&gt;
// Simplified tunnel start logic:&lt;br /&gt;
&lt;br /&gt;
if (!this._options.browserstackLocal) {&lt;br /&gt;
    return BStackLogger.info(&#039;browserstackLocal is not enabled - skipping...&#039;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const opts = {&lt;br /&gt;
    key: this._config.key,&lt;br /&gt;
    ...this._options.opts&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
this.browserstackLocal = new BrowserstackLocalLauncher.Local()&lt;br /&gt;
&lt;br /&gt;
// Inject &#039;local&#039; flag into all capabilities&lt;br /&gt;
this._updateCaps(capabilities, &#039;local&#039;)&lt;br /&gt;
if (opts.localIdentifier) {&lt;br /&gt;
    this._updateCaps(capabilities, &#039;localIdentifier&#039;, opts.localIdentifier)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Start with 60-second timeout&lt;br /&gt;
performance.mark(&#039;tbTunnelStart&#039;)&lt;br /&gt;
return Promise.race([&lt;br /&gt;
    promisify(this.browserstackLocal.start.bind(this.browserstackLocal))(opts),&lt;br /&gt;
    new Promise((resolve, reject) =&amp;gt; {&lt;br /&gt;
        timer = setTimeout(function () {&lt;br /&gt;
            reject(&#039;Browserstack Local failed to start within 60 seconds!&#039;)&lt;br /&gt;
        }, 60000)&lt;br /&gt;
    })&lt;br /&gt;
])&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;I/O Contract -- onPrepare:&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Input !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Options.Testrunner&amp;lt;/code&amp;gt; || WDIO configuration (includes &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; for authentication)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;capabilities&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Capabilities.TestrunnerCapabilities&amp;lt;/code&amp;gt; || Capabilities array (mutated to add tunnel flags)&lt;br /&gt;
|-&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Returns || &amp;lt;code&amp;gt;Promise&amp;lt;void&amp;gt;&amp;lt;/code&amp;gt; || Resolves when tunnel is ready, rejects on timeout (60s) or error&lt;br /&gt;
|-&lt;br /&gt;
| Side effects || Capability mutation || Adds &amp;lt;code&amp;gt;local: true&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;localIdentifier&amp;lt;/code&amp;gt; to all capabilities&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Tunnel Stop (onComplete) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-browserstack-service/src/launcher.ts (L653-670+)&lt;br /&gt;
if (!this.browserstackLocal || !this.browserstackLocal.isRunning()) {&lt;br /&gt;
    return&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const pid = this.browserstackLocal.pid&lt;br /&gt;
this.browserstackLocal.stop((err: Error) =&amp;gt; {&lt;br /&gt;
    // cleanup callback&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Sauce Connect Tunnel ==&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
services: [[&#039;sauce&#039;, {&lt;br /&gt;
    sauceConnect: boolean,              // Enable/disable Sauce Connect (default: false)&lt;br /&gt;
    sauceConnectOpts: SauceConnectOptions  // Sauce Connect options&lt;br /&gt;
}]]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tunnel Start (onPrepare) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-sauce-service/src/launcher.ts (L35-101)&lt;br /&gt;
async onPrepare (config, capabilities) {&lt;br /&gt;
    if (!this._options.sauceConnect) {&lt;br /&gt;
        return&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const sauceConnectTunnelName = (&lt;br /&gt;
        this._options.sauceConnectOpts?.tunnelName ||&lt;br /&gt;
        `SC-tunnel-${Math.random().toString().slice(2)}`&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    const sauceConnectOpts: SauceConnectOptions = {&lt;br /&gt;
        tunnelName: sauceConnectTunnelName,&lt;br /&gt;
        ...this._options.sauceConnectOpts,&lt;br /&gt;
        metadata: metadata&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Inject tunnel name into all capabilities&lt;br /&gt;
    const prepareCapability = makeCapabilityFactory(sauceConnectTunnelName)&lt;br /&gt;
    for (const capability of capabilities) {&lt;br /&gt;
        prepareCapability(capability)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    log.info(&#039;Starting Sauce Connect Tunnel&#039;)&lt;br /&gt;
    performance.mark(&#039;sauceConnectStart&#039;)&lt;br /&gt;
    this._sauceConnectProcess = await this.startTunnel(sauceConnectOpts)&lt;br /&gt;
    performance.mark(&#039;sauceConnectEnd&#039;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;I/O Contract -- SauceServiceConfig tunnel options:&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sauceConnect&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; || Enable Sauce Connect tunnel&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sauceConnectOpts&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;SauceConnectOptions&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; || Sauce Connect binary options&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sauceConnectOpts.tunnelName&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || auto-generated || Unique tunnel identifier&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Tunnel Stop (onComplete) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-sauce-service/src/launcher.ts (L136-142)&lt;br /&gt;
onComplete () {&lt;br /&gt;
    if (!this._sauceConnectProcess) {&lt;br /&gt;
        return&lt;br /&gt;
    }&lt;br /&gt;
    return this._sauceConnectProcess.close()&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TestingBot Tunnel ==&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
services: [[&#039;testingbot&#039;, {&lt;br /&gt;
    tbTunnel: boolean,                   // Enable/disable TestingBot Tunnel (default: false)&lt;br /&gt;
    tbTunnelOpts: TunnelLauncherOptions  // Tunnel binary options&lt;br /&gt;
}]]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tunnel Start (onPrepare) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-testingbot-service/src/launcher.ts (L20-65)&lt;br /&gt;
async onPrepare (config, capabilities) {&lt;br /&gt;
    if (!this.options.tbTunnel || !config.user || !config.key) {&lt;br /&gt;
        return&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    const tbTunnelIdentifier = (&lt;br /&gt;
        this.options.tbTunnelOpts?.tunnelIdentifier ||&lt;br /&gt;
        `TB-tunnel-${Math.random().toString().slice(2)}`&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    this.tbTunnelOpts = Object.assign({&lt;br /&gt;
        apiKey: config.user,&lt;br /&gt;
        apiSecret: config.key,&lt;br /&gt;
        &#039;tunnel-identifier&#039;: tbTunnelIdentifier,&lt;br /&gt;
    }, this.options.tbTunnelOpts)&lt;br /&gt;
&lt;br /&gt;
    // Inject tunnel identifier into all capabilities&lt;br /&gt;
    for (const capability of capabilitiesEntries) {&lt;br /&gt;
        const c = (caps as Capabilities.W3CCapabilities).alwaysMatch || caps&lt;br /&gt;
        if (!c[&#039;tb:options&#039;]) {&lt;br /&gt;
            c[&#039;tb:options&#039;] = {}&lt;br /&gt;
        }&lt;br /&gt;
        c[&#039;tb:options&#039;][&#039;tunnel-identifier&#039;] = tbTunnelIdentifier&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    performance.mark(&#039;tbTunnelStart&#039;)&lt;br /&gt;
    this.tunnel = await promisify(testingbotTunnel)(this.tbTunnelOpts)&lt;br /&gt;
    performance.mark(&#039;tbTunnelEnd&#039;)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;I/O Contract -- TestingbotOptions tunnel options:&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Default !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tbTunnel&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; || Enable TestingBot Tunnel&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tbTunnelOpts&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;TunnelLauncherOptions&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt; || Tunnel binary options&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tbTunnelOpts.tunnelIdentifier&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || auto-generated || Unique tunnel identifier&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tbTunnelOpts.apiKey&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || from &amp;lt;code&amp;gt;config.user&amp;lt;/code&amp;gt; || TestingBot API key&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tbTunnelOpts.apiSecret&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; || from &amp;lt;code&amp;gt;config.key&amp;lt;/code&amp;gt; || TestingBot API secret&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Tunnel Stop (onComplete) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// packages/wdio-testingbot-service/src/launcher.ts (L71-77)&lt;br /&gt;
onComplete () {&lt;br /&gt;
    if (!this.tunnel) {&lt;br /&gt;
        return&lt;br /&gt;
    }&lt;br /&gt;
    return new Promise(resolve =&amp;gt; this.tunnel!.close(resolve))&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Cross-Provider Comparison ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Feature !! BrowserStack !! Sauce Labs !! TestingBot&lt;br /&gt;
|-&lt;br /&gt;
| Enable flag || &amp;lt;code&amp;gt;browserstackLocal: true&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;sauceConnect: true&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;tbTunnel: true&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Options key || &amp;lt;code&amp;gt;opts&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;sauceConnectOpts&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;tbTunnelOpts&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Tunnel ID property || &amp;lt;code&amp;gt;opts.localIdentifier&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;sauceConnectOpts.tunnelName&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;tbTunnelOpts.tunnelIdentifier&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Capability namespace || &amp;lt;code&amp;gt;bstack:options.localIdentifier&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;sauce:options.tunnelName&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;tb:options[&#039;tunnel-identifier&#039;]&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Auto-ID generation || No (requires manual ID) || Yes (&amp;lt;code&amp;gt;SC-tunnel-*&amp;lt;/code&amp;gt;) || Yes (&amp;lt;code&amp;gt;TB-tunnel-*&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Start timeout || 60 seconds || No explicit timeout || No explicit timeout&lt;br /&gt;
|-&lt;br /&gt;
| Retry on failure || No || Yes (3 retries for ENOENT) || No&lt;br /&gt;
|-&lt;br /&gt;
| Boot time measurement || Yes (PerformanceObserver) || Yes (PerformanceObserver) || Yes (PerformanceObserver)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Full Example: BrowserStack Local Configuration ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
// wdio.conf.ts&lt;br /&gt;
export const config: WebdriverIO.Config = {&lt;br /&gt;
    user: process.env.BROWSERSTACK_USERNAME,&lt;br /&gt;
    key: process.env.BROWSERSTACK_ACCESS_KEY,&lt;br /&gt;
&lt;br /&gt;
    services: [[&#039;browserstack&#039;, {&lt;br /&gt;
        browserstackLocal: true,&lt;br /&gt;
        opts: {&lt;br /&gt;
            localIdentifier: &#039;ci-tunnel-&#039; + process.env.BUILD_NUMBER,&lt;br /&gt;
            verbose: true&lt;br /&gt;
        },&lt;br /&gt;
        forcedStop: false,&lt;br /&gt;
        setSessionName: true,&lt;br /&gt;
        setSessionStatus: true&lt;br /&gt;
    }]],&lt;br /&gt;
&lt;br /&gt;
    capabilities: [{&lt;br /&gt;
        browserName: &#039;chrome&#039;,&lt;br /&gt;
        browserVersion: &#039;latest&#039;,&lt;br /&gt;
        &#039;bstack:options&#039;: {&lt;br /&gt;
            os: &#039;Windows&#039;,&lt;br /&gt;
            osVersion: &#039;11&#039;,&lt;br /&gt;
            local: true,&lt;br /&gt;
            localIdentifier: &#039;ci-tunnel-&#039; + process.env.BUILD_NUMBER,&lt;br /&gt;
            buildName: &#039;Local Dev Build&#039;,&lt;br /&gt;
            video: true&lt;br /&gt;
        }&lt;br /&gt;
    }],&lt;br /&gt;
&lt;br /&gt;
    baseUrl: &#039;http://localhost:3000&#039;,&lt;br /&gt;
    specs: [&#039;./test/specs/**/*.spec.ts&#039;],&lt;br /&gt;
    framework: &#039;mocha&#039;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;implements&#039;&#039;&#039; [[Principle:Webdriverio_Webdriverio_Local_Tunnel_Connectivity|Principle: Local_Tunnel_Connectivity]]&lt;br /&gt;
* [[requires_env::Environment:Webdriverio_Webdriverio_Cloud_Service_Credentials]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Vespa_Logctl&amp;diff=30783</id>
		<title>Implementation:Vespa engine Vespa Vespa Logctl</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Vespa_Logctl&amp;diff=30783"/>
		<updated>2026-09-27T10:53:19Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Vespa_Logctl}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Vespa_Logctl}}&lt;br /&gt;
== vespa-logctl ==&lt;br /&gt;
&lt;br /&gt;
[[domain::Logging]] [[domain::Observability]]&lt;br /&gt;
&lt;br /&gt;
=== Tool Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
vespa-logctl [options] &amp;lt;service&amp;gt;[:component] [&amp;lt;level-mods&amp;gt;]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;CLI source&#039;&#039;&#039;: [https://github.com/vespa-engine/vespa/blob/master/vespalog/src/logctl/logctl.cpp vespalog/src/logctl/logctl.cpp] (Lines L94-230)&lt;br /&gt;
* &#039;&#039;&#039;ControlFile class&#039;&#039;&#039;: [https://github.com/vespa-engine/vespa/blob/master/vespalog/src/vespa/log/control-file.cpp vespalog/src/vespa/log/control-file.cpp] (Lines L1-450)&lt;br /&gt;
* &#039;&#039;&#039;ControlFile header&#039;&#039;&#039;: [https://github.com/vespa-engine/vespa/blob/master/vespalog/src/vespa/log/control-file.h vespalog/src/vespa/log/control-file.h] (Lines L1-89)&lt;br /&gt;
* &#039;&#039;&#039;Type&#039;&#039;&#039;: External Tool Doc&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;vespa-logctl&amp;lt;/code&amp;gt; is a &#039;&#039;&#039;command-line tool&#039;&#039;&#039; for viewing and modifying the runtime log level settings of running Vespa processes. It operates by directly reading and writing the &#039;&#039;&#039;memory-mapped log control files&#039;&#039;&#039; that each Vespa process creates at startup. Because the control files are memory-mapped by the target processes, level changes take effect &#039;&#039;&#039;immediately&#039;&#039;&#039; without any signal or restart.&lt;br /&gt;
&lt;br /&gt;
=== CLI Flags ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Flag !! Long Form !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;-c&amp;lt;/code&amp;gt; || || Create the control file if it does not exist&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;-n&amp;lt;/code&amp;gt; || || Create a new entry for the specified component if it does not exist&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;-a&amp;lt;/code&amp;gt; || || Apply the operation to &#039;&#039;&#039;all&#039;&#039;&#039; control files in the control directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;-f &amp;amp;lt;file&amp;amp;gt;&amp;lt;/code&amp;gt; || || Specify an explicit control file path instead of deriving it from the service name&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;-d &amp;amp;lt;dir&amp;amp;gt;&amp;lt;/code&amp;gt; || || Specify the control file directory (default: &amp;lt;code&amp;gt;$VESPA_LOG_CONTROL_DIR&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;/var/log/vespa/logcontrol&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;-r&amp;lt;/code&amp;gt; || || Reset all levels for the specified component to their default values&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Level Modification Syntax ===&lt;br /&gt;
&lt;br /&gt;
Level modifications are specified as a &#039;&#039;&#039;comma-separated list&#039;&#039;&#039; of assignments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;level&amp;gt;=&amp;lt;on|off&amp;gt;[,&amp;lt;level&amp;gt;=&amp;lt;on|off&amp;gt;]...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The special level name &amp;lt;code&amp;gt;all&amp;lt;/code&amp;gt; applies to all 8 levels simultaneously:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Modifier !! Effect&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;all=on&amp;lt;/code&amp;gt; || Enable all 8 log levels (fatal, error, warning, config, info, event, debug, spam)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;all=off&amp;lt;/code&amp;gt; || Disable all 8 log levels&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;debug=on&amp;lt;/code&amp;gt; || Enable only the debug level&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;spam=off&amp;lt;/code&amp;gt; || Disable only the spam level&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;all=on,debug=off,spam=off&amp;lt;/code&amp;gt; || Enable all levels except debug and spam (the default configuration)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Modifiers are applied &#039;&#039;&#039;left to right&#039;&#039;&#039;, so &amp;lt;code&amp;gt;all=on,debug=off&amp;lt;/code&amp;gt; first enables everything and then disables debug.&lt;br /&gt;
&lt;br /&gt;
=== Usage Examples ===&lt;br /&gt;
&lt;br /&gt;
==== View Current Levels ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Show all component levels for the searchnode service&lt;br /&gt;
vespa-logctl searchnode&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
searchnode.com.yahoo.search.handler     ON  ON  ON  ON  ON  ON  OFF OFF&lt;br /&gt;
searchnode.com.yahoo.container           ON  ON  ON  ON  ON  ON  OFF OFF&lt;br /&gt;
searchnode.com.yahoo.jdisc               ON  ON  ON  ON  ON  ON  OFF OFF&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The columns correspond to: fatal, error, warning, config, info, event, debug, spam.&lt;br /&gt;
&lt;br /&gt;
==== Enable Debug for a Specific Component ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Enable debug logging for query handler only&lt;br /&gt;
vespa-logctl searchnode:com.yahoo.search.handler debug=on&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Enable Debug for All Components ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Enable debug for everything in searchnode&lt;br /&gt;
vespa-logctl searchnode debug=on&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Reset to Defaults ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Reset all components of configserver to default levels&lt;br /&gt;
vespa-logctl -r configserver&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Use Explicit Control File ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Modify levels using a specific control file path&lt;br /&gt;
vespa-logctl -f /var/log/vespa/logcontrol/searchnode.logcontrol \&lt;br /&gt;
    searchnode:com.yahoo.search debug=on&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Pre-Create Component Entry ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Create a control file entry before the component has logged anything&lt;br /&gt;
vespa-logctl -n searchnode:com.yahoo.search.newmodule all=on&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ControlFile C++ Class ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;vespa-logctl&amp;lt;/code&amp;gt; tool uses the &amp;lt;code&amp;gt;ControlFile&amp;lt;/code&amp;gt; C++ class to manipulate the memory-mapped control files.&lt;br /&gt;
&lt;br /&gt;
==== Class Declaration ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
class ControlFile {&lt;br /&gt;
public:&lt;br /&gt;
    enum Mode { READONLY, READWRITE, CREATE };&lt;br /&gt;
&lt;br /&gt;
    ControlFile(const char *filename, Mode mode);&lt;br /&gt;
    ~ControlFile();&lt;br /&gt;
&lt;br /&gt;
    unsigned int *getLevels(const char *name);&lt;br /&gt;
    char *getComponentName(unsigned int offset);&lt;br /&gt;
    void ensureComponent(const char *pattern);&lt;br /&gt;
    void flush();&lt;br /&gt;
&lt;br /&gt;
    ComponentIterator begin();&lt;br /&gt;
    ComponentIterator end();&lt;br /&gt;
&lt;br /&gt;
private:&lt;br /&gt;
    int _fd;&lt;br /&gt;
    char *_mapBase;&lt;br /&gt;
    size_t _mapSize;&lt;br /&gt;
    // ...&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Modes ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mode !! Description !! Used By&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;READONLY&amp;lt;/code&amp;gt; || Open for reading only. Used when listing current levels. || &amp;lt;code&amp;gt;vespa-logctl&amp;lt;/code&amp;gt; (no level-mods argument)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;READWRITE&amp;lt;/code&amp;gt; || Open for reading and writing. Used when modifying levels. || &amp;lt;code&amp;gt;vespa-logctl&amp;lt;/code&amp;gt; (with level-mods argument)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;CREATE&amp;lt;/code&amp;gt; || Create the file if it does not exist. Write header and prefix. || &amp;lt;code&amp;gt;vespa-logctl -c&amp;lt;/code&amp;gt;, Vespa processes at startup&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Key Methods ====&lt;br /&gt;
&lt;br /&gt;
===== getLevels =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
unsigned int *getLevels(const char *name);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns a pointer to the level bitmask for the named component. The pointer points directly into the memory-mapped region, so modifications are immediately visible to the target process.&lt;br /&gt;
&lt;br /&gt;
===== ensureComponent =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void ensureComponent(const char *pattern);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensures that an entry exists for the specified component. If no entry exists, one is created with default level settings. This is used with the &amp;lt;code&amp;gt;-n&amp;lt;/code&amp;gt; flag to pre-register components.&lt;br /&gt;
&lt;br /&gt;
===== flush =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
void flush();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Forces any pending memory-mapped writes to be synchronized to disk. Called after level modifications to ensure persistence.&lt;br /&gt;
&lt;br /&gt;
==== ComponentIterator ====&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ComponentIterator&amp;lt;/code&amp;gt; allows enumeration of all registered components:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
for (auto it = controlFile.begin(); it != controlFile.end(); ++it) {&lt;br /&gt;
    printf(&amp;quot;%s\t&amp;quot;, it-&amp;gt;name());&lt;br /&gt;
    unsigned int *levels = it-&amp;gt;levels();&lt;br /&gt;
    for (int i = 0; i &amp;lt; 8; i++) {&lt;br /&gt;
        printf(&amp;quot;%s &amp;quot;, levels[i] ? &amp;quot;ON&amp;quot; : &amp;quot;OFF&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the mechanism used by &amp;lt;code&amp;gt;vespa-logctl&amp;lt;/code&amp;gt; to display the current level table when invoked without level modifications.&lt;br /&gt;
&lt;br /&gt;
=== Internal Operation Flow ===&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;code&amp;gt;vespa-logctl&amp;lt;/code&amp;gt; is invoked with level modifications, it performs the following steps:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Parse arguments&#039;&#039;&#039;: Extract the service name, optional component, and level modifications from the command line.&lt;br /&gt;
# &#039;&#039;&#039;Locate control file&#039;&#039;&#039;: Either use the explicit &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; path, or derive it from the service name and control directory as &amp;lt;code&amp;gt;&amp;amp;lt;dir&amp;amp;gt;/&amp;amp;lt;service&amp;amp;gt;.logcontrol&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &#039;&#039;&#039;Open control file&#039;&#039;&#039;: Create a &amp;lt;code&amp;gt;ControlFile&amp;lt;/code&amp;gt; object in &amp;lt;code&amp;gt;READWRITE&amp;lt;/code&amp;gt; mode (or &amp;lt;code&amp;gt;CREATE&amp;lt;/code&amp;gt; mode with &amp;lt;code&amp;gt;-c&amp;lt;/code&amp;gt;).&lt;br /&gt;
# &#039;&#039;&#039;Find or create component entry&#039;&#039;&#039;: Use &amp;lt;code&amp;gt;getLevels()&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;ensureComponent()&amp;lt;/code&amp;gt; to locate the entry.&lt;br /&gt;
# &#039;&#039;&#039;Apply level modifications&#039;&#039;&#039;: Parse the level-mods string and set each level byte to 1 (on) or 0 (off).&lt;br /&gt;
# &#039;&#039;&#039;Flush changes&#039;&#039;&#039;: Call &amp;lt;code&amp;gt;flush()&amp;lt;/code&amp;gt; to ensure the changes are persisted.&lt;br /&gt;
# &#039;&#039;&#039;Close control file&#039;&#039;&#039;: The &amp;lt;code&amp;gt;ControlFile&amp;lt;/code&amp;gt; destructor unmaps and closes the file.&lt;br /&gt;
&lt;br /&gt;
=== Interaction with Java Processes ===&lt;br /&gt;
&lt;br /&gt;
The control file format is identical for Java and C++ processes. When &amp;lt;code&amp;gt;vespa-logctl&amp;lt;/code&amp;gt; modifies the control file:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Java processes&#039;&#039;&#039; see the change through their &amp;lt;code&amp;gt;MappedByteBuffer&amp;lt;/code&amp;gt;, which maps the same physical file.&lt;br /&gt;
* &#039;&#039;&#039;C++ processes&#039;&#039;&#039; see the change through their &amp;lt;code&amp;gt;mmap()&amp;lt;/code&amp;gt; mapping of the same file.&lt;br /&gt;
&lt;br /&gt;
No inter-process communication (signals, sockets, etc.) is needed. The memory-mapped file &#039;&#039;&#039;is&#039;&#039;&#039; the communication channel.&lt;br /&gt;
&lt;br /&gt;
=== Error Handling ===&lt;br /&gt;
&lt;br /&gt;
* If the control file does not exist and &amp;lt;code&amp;gt;-c&amp;lt;/code&amp;gt; is not specified, the tool prints an error and exits with a non-zero status.&lt;br /&gt;
* If the specified component does not exist in the control file and &amp;lt;code&amp;gt;-n&amp;lt;/code&amp;gt; is not specified, the tool prints a warning. With the &amp;lt;code&amp;gt;-a&amp;lt;/code&amp;gt; flag, non-matching components are silently skipped.&lt;br /&gt;
* If the level-mods string is malformed, a usage message is printed.&lt;br /&gt;
&lt;br /&gt;
=== Implements Principle ===&lt;br /&gt;
&lt;br /&gt;
[[Principle:Vespa_engine_Vespa_Runtime_Level_Control|Runtime Level Control]]&lt;br /&gt;
&lt;br /&gt;
=== Related Implementations ===&lt;br /&gt;
&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_VespaLevelControllerRepo_Constructor|VespaLevelControllerRepo Constructor]] -- Creates the Java-side memory-mapped level controller that &amp;lt;code&amp;gt;vespa-logctl&amp;lt;/code&amp;gt; modifies&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_VespaLogHandler_Publish|VespaLogHandler.publish]] -- Reads the level control bytes on every log call&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Vespa_engine_Vespa_Runtime_Level_Control]]&lt;br /&gt;
* [[requires_env::Environment:Vespa_engine_Vespa_CMake_Cpp23_Build_Environment]]&lt;br /&gt;
* [[requires_env::Environment:Vespa_engine_Vespa_POSIX_Mmap_Log_Control]]&lt;br /&gt;
* [[uses_heuristic::Heuristic:Vespa_engine_Vespa_Log_Level_Inheritance_Polling]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_VespaLogHandler_Publish&amp;diff=30782</id>
		<title>Implementation:Vespa engine Vespa VespaLogHandler Publish</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_VespaLogHandler_Publish&amp;diff=30782"/>
		<updated>2026-09-27T10:53:18Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_VespaLogHandler_Publish}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_VespaLogHandler_Publish}}&lt;br /&gt;
== VespaLogHandler.publish ==&lt;br /&gt;
&lt;br /&gt;
[[domain::Logging]] [[domain::Observability]]&lt;br /&gt;
&lt;br /&gt;
=== API Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public synchronized void publish(LogRecord record)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;File&#039;&#039;&#039;: [https://github.com/vespa-engine/vespa/blob/master/vespalog/src/main/java/com/yahoo/log/VespaLogHandler.java vespalog/src/main/java/com/yahoo/log/VespaLogHandler.java]&lt;br /&gt;
* &#039;&#039;&#039;Lines&#039;&#039;&#039;: L64-90&lt;br /&gt;
* &#039;&#039;&#039;Class&#039;&#039;&#039;: &amp;lt;code&amp;gt;class VespaLogHandler extends StreamHandler&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Package&#039;&#039;&#039;: &amp;lt;code&amp;gt;com.yahoo.log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;publish&amp;lt;/code&amp;gt; method is the &#039;&#039;&#039;hot path&#039;&#039;&#039; of Vespa&#039;s logging framework. It is called for every log record produced by any JUL logger in the process. The method applies level reduction, level control, reject filtering, and then opens the log target, writes the formatted record, flushes, and closes the file target. The method is &amp;lt;code&amp;gt;synchronized&amp;lt;/code&amp;gt; to prevent interleaved output from concurrent threads.&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;record&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;LogRecord&amp;lt;/code&amp;gt; || The JUL log record to publish. Contains the level, logger name, message, thread ID, timestamp, optional thrown exception, and optional parameters.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Return Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; -- The record is either written to the log target or silently dropped (if filtered out by level control or reject filter).&lt;br /&gt;
&lt;br /&gt;
=== Full Method Source ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public synchronized void publish(LogRecord record) {&lt;br /&gt;
    String loggerName = record.getLoggerName();&lt;br /&gt;
&lt;br /&gt;
    Level level = possiblyReduceLogLevel(loggerName, record.getLevel());&lt;br /&gt;
&lt;br /&gt;
    LevelController ctrl = getLevelControl(loggerName);&lt;br /&gt;
    if (!ctrl.shouldLog(level)) { return; }&lt;br /&gt;
&lt;br /&gt;
    if (logRejectFilter.shouldReject(record.getMessage())) { return; }&lt;br /&gt;
&lt;br /&gt;
    try {&lt;br /&gt;
        setOutputStream(logTarget.open());&lt;br /&gt;
    } catch (RuntimeException e) {&lt;br /&gt;
        LogRecord r = new LogRecord(Level.SEVERE, &amp;quot;Unable to open file target&amp;quot;);&lt;br /&gt;
        r.setThrown(e);&lt;br /&gt;
        emergencyLog(r);&lt;br /&gt;
        setOutputStream(System.err);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    super.publish(record);&lt;br /&gt;
    flush();&lt;br /&gt;
    closeFileTarget();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step-by-Step Execution Flow ===&lt;br /&gt;
&lt;br /&gt;
==== Step 1: Extract Logger Name ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
String loggerName = record.getLoggerName();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The logger name is the JUL logger name (e.g., &amp;lt;code&amp;gt;&amp;quot;com.yahoo.search.handler.SearchHandler&amp;quot;&amp;lt;/code&amp;gt;). It is used for both level reduction and level control lookups.&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Apply Level Reduction ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
Level level = possiblyReduceLogLevel(loggerName, record.getLevel());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For certain noisy third-party loggers, the effective level is &#039;&#039;&#039;reduced&#039;&#039;&#039;. For example, Jetty INFO messages are treated as DEBUG. The &amp;lt;code&amp;gt;possiblyReduceLogLevel()&amp;lt;/code&amp;gt; method checks if the logger name matches any prefix in the level reduction map. If it matches, the level is lowered; otherwise, the original level is returned unchanged.&lt;br /&gt;
&lt;br /&gt;
This reduced level is used for the &amp;lt;code&amp;gt;shouldLog()&amp;lt;/code&amp;gt; check but does &#039;&#039;&#039;not&#039;&#039;&#039; modify the &amp;lt;code&amp;gt;LogRecord&amp;lt;/code&amp;gt; itself. The original level is preserved in the record for formatting purposes.&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Check Level Control ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
LevelController ctrl = getLevelControl(loggerName);&lt;br /&gt;
if (!ctrl.shouldLog(level)) { return; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The level controller for the logger&#039;s component is retrieved from the &amp;lt;code&amp;gt;LevelControllerRepo&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;shouldLog()&amp;lt;/code&amp;gt; method reads a single byte from the memory-mapped control file to determine if the (possibly reduced) level is enabled.&lt;br /&gt;
&lt;br /&gt;
If the level is disabled, the method returns &#039;&#039;&#039;immediately&#039;&#039;&#039; without performing any formatting, I/O, or synchronization beyond the method-level lock. This is the &#039;&#039;&#039;fast path&#039;&#039;&#039; for disabled levels.&lt;br /&gt;
&lt;br /&gt;
==== Step 4: Apply Reject Filter ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
if (logRejectFilter.shouldReject(record.getMessage())) { return; }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Even if the level is enabled, the reject filter can drop messages that match known-useless patterns. This is a &#039;&#039;&#039;content-based filter&#039;&#039;&#039; that examines the actual message text. If the message is rejected, the method returns without writing anything.&lt;br /&gt;
&lt;br /&gt;
==== Step 5: Open Log Target ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
    setOutputStream(logTarget.open());&lt;br /&gt;
} catch (RuntimeException e) {&lt;br /&gt;
    LogRecord r = new LogRecord(Level.SEVERE, &amp;quot;Unable to open file target&amp;quot;);&lt;br /&gt;
    r.setThrown(e);&lt;br /&gt;
    emergencyLog(r);&lt;br /&gt;
    setOutputStream(System.err);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The log target is opened &#039;&#039;&#039;on every publish call&#039;&#039;&#039;. This is the key mechanism that enables &#039;&#039;&#039;external log rotation&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* For &#039;&#039;&#039;file targets&#039;&#039;&#039;: &amp;lt;code&amp;gt;open()&amp;lt;/code&amp;gt; opens the file at the configured path. If an external tool has renamed the file since the last call, the new &amp;lt;code&amp;gt;open()&amp;lt;/code&amp;gt; creates a fresh file at the original path.&lt;br /&gt;
* For &#039;&#039;&#039;file descriptor targets&#039;&#039;&#039; (e.g., &amp;lt;code&amp;gt;fd:2&amp;lt;/code&amp;gt;): &amp;lt;code&amp;gt;open()&amp;lt;/code&amp;gt; returns the same file descriptor each time.&lt;br /&gt;
&lt;br /&gt;
If the open fails (e.g., disk full, permission denied), the handler:&lt;br /&gt;
# Creates a SEVERE log record describing the failure&lt;br /&gt;
# Logs it via &amp;lt;code&amp;gt;emergencyLog()&amp;lt;/code&amp;gt; (which writes to stderr)&lt;br /&gt;
# Falls back to using &amp;lt;code&amp;gt;System.err&amp;lt;/code&amp;gt; as the output stream&lt;br /&gt;
&lt;br /&gt;
This ensures the original log record is still written (to stderr) even when the primary target is unavailable.&lt;br /&gt;
&lt;br /&gt;
==== Step 6: Write the Record ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
super.publish(record);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Delegates to &amp;lt;code&amp;gt;StreamHandler.publish()&amp;lt;/code&amp;gt;, which:&lt;br /&gt;
# Calls the &amp;lt;code&amp;gt;VespaFormatter.format(record)&amp;lt;/code&amp;gt; method to produce the tab-delimited log line&lt;br /&gt;
# Writes the formatted string to the output stream set in Step 5&lt;br /&gt;
&lt;br /&gt;
==== Step 7: Flush ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
flush();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Immediately flushes the output stream to ensure the record is committed to the underlying file or file descriptor. This guarantees that:&lt;br /&gt;
* Log monitoring tools see the record immediately&lt;br /&gt;
* A process crash loses at most the record currently being written&lt;br /&gt;
&lt;br /&gt;
==== Step 8: Close File Target ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
closeFileTarget();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For file-based targets, the file is closed after each write. This:&lt;br /&gt;
* Releases the file descriptor&lt;br /&gt;
* Ensures the file can be rotated by external tools&lt;br /&gt;
* Prevents accumulation of open file handles&lt;br /&gt;
&lt;br /&gt;
For file descriptor targets (&amp;lt;code&amp;gt;fd:2&amp;lt;/code&amp;gt;, etc.), this is a no-op since the handler should not close shared file descriptors.&lt;br /&gt;
&lt;br /&gt;
=== Synchronization Details ===&lt;br /&gt;
&lt;br /&gt;
The method is declared &amp;lt;code&amp;gt;synchronized&amp;lt;/code&amp;gt;, which means:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Thread safety&#039;&#039;&#039;: Only one thread can execute &amp;lt;code&amp;gt;publish()&amp;lt;/code&amp;gt; at a time, preventing interleaved output.&lt;br /&gt;
* &#039;&#039;&#039;Atomicity&#039;&#039;&#039;: The open-write-flush-close cycle is atomic with respect to other log calls.&lt;br /&gt;
* &#039;&#039;&#039;Bottleneck risk&#039;&#039;&#039;: Under extreme logging load, threads will contend on the monitor. However, logging should not be on the critical path of request processing.&lt;br /&gt;
&lt;br /&gt;
=== Error Recovery ===&lt;br /&gt;
&lt;br /&gt;
The error recovery strategy is designed for &#039;&#039;&#039;robustness over correctness&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* If the log target fails, output goes to stderr rather than being lost.&lt;br /&gt;
* The next &amp;lt;code&amp;gt;publish()&amp;lt;/code&amp;gt; call will attempt to reopen the original target. If the underlying issue is resolved (e.g., disk space freed), normal operation resumes automatically.&lt;br /&gt;
* The emergency log record documents the failure for post-mortem analysis.&lt;br /&gt;
&lt;br /&gt;
=== Performance Characteristics ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Scenario !! Operations !! Cost&lt;br /&gt;
|-&lt;br /&gt;
| Level disabled || Memory read + return || Nanoseconds (fast path)&lt;br /&gt;
|-&lt;br /&gt;
| Message rejected || Memory read + string match + return || Microseconds&lt;br /&gt;
|-&lt;br /&gt;
| Normal write (fd target) || Format + write + flush || Tens of microseconds&lt;br /&gt;
|-&lt;br /&gt;
| Normal write (file target) || Open + format + write + flush + close || Hundreds of microseconds&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;fast path&#039;&#039;&#039; (disabled level) is the most common case in production, where only a small fraction of log calls actually produce output.&lt;br /&gt;
&lt;br /&gt;
=== Usage Context ===&lt;br /&gt;
&lt;br /&gt;
This method is &#039;&#039;&#039;never called directly&#039;&#039;&#039; by application code. It is invoked by the JUL framework when any logger produces a log record:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// Application code:&lt;br /&gt;
Logger logger = Logger.getLogger(&amp;quot;com.yahoo.search.handler&amp;quot;);&lt;br /&gt;
logger.info(&amp;quot;Query completed in 42ms&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// JUL framework internally calls:&lt;br /&gt;
// vespaLogHandler.publish(logRecord);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implements Principle ===&lt;br /&gt;
&lt;br /&gt;
[[Principle:Vespa_engine_Vespa_Log_Rotation_and_Special_Handling|Log Rotation and Special Handling]]&lt;br /&gt;
&lt;br /&gt;
=== Related Implementations ===&lt;br /&gt;
&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_VespaLogHandler_Constructor|VespaLogHandler Constructor]] -- Constructs the handler and its dependencies&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_VespaFormatter_Format|VespaFormatter.format]] -- Formats the log record into the tab-delimited output&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Vespa_Logctl|vespa-logctl]] -- Modifies the level control bytes that &amp;lt;code&amp;gt;shouldLog()&amp;lt;/code&amp;gt; reads&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_VespaLevelControllerRepo_Constructor|VespaLevelControllerRepo Constructor]] -- Creates the level controller repo used by &amp;lt;code&amp;gt;getLevelControl()&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Vespa_engine_Vespa_Log_Rotation_and_Special_Handling]]&lt;br /&gt;
* [[uses_heuristic::Heuristic:Vespa_engine_Vespa_Log_Level_Inheritance_Polling]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_VespaLogHandler_Constructor&amp;diff=30781</id>
		<title>Implementation:Vespa engine Vespa VespaLogHandler Constructor</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_VespaLogHandler_Constructor&amp;diff=30781"/>
		<updated>2026-09-27T10:53:17Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_VespaLogHandler_Constructor}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_VespaLogHandler_Constructor}}&lt;br /&gt;
== VespaLogHandler Constructor ==&lt;br /&gt;
&lt;br /&gt;
[[domain::Logging]] [[domain::Observability]]&lt;br /&gt;
&lt;br /&gt;
=== API Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
VespaLogHandler(LogTarget logTarget, LevelControllerRepo levelControllerRepo,&lt;br /&gt;
                String serviceName, String applicationPrefix)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;File&#039;&#039;&#039;: [https://github.com/vespa-engine/vespa/blob/master/vespalog/src/main/java/com/yahoo/log/VespaLogHandler.java vespalog/src/main/java/com/yahoo/log/VespaLogHandler.java]&lt;br /&gt;
* &#039;&#039;&#039;Lines&#039;&#039;&#039;: L51-59&lt;br /&gt;
* &#039;&#039;&#039;Class&#039;&#039;&#039;: &amp;lt;code&amp;gt;class VespaLogHandler extends StreamHandler&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Package&#039;&#039;&#039;: &amp;lt;code&amp;gt;com.yahoo.log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;VespaLogHandler&amp;lt;/code&amp;gt; constructor assembles the core logging handler that replaces the default JUL handlers. It wires together the log target (output destination), level controller repository (per-component level checking), service metadata, and the reject filter. After construction, the &amp;lt;code&amp;gt;initialize()&amp;lt;/code&amp;gt; method sets up the &amp;lt;code&amp;gt;VespaFormatter&amp;lt;/code&amp;gt; and configures the handler for use.&lt;br /&gt;
&lt;br /&gt;
=== Key Fields ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Field !! Type !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logTarget&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;LogTarget&amp;lt;/code&amp;gt; || Output destination (file, stderr, etc.) that provides an &amp;lt;code&amp;gt;OutputStream&amp;lt;/code&amp;gt; on each &amp;lt;code&amp;gt;open()&amp;lt;/code&amp;gt; call&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;serviceName&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || The Vespa service identity (e.g., &amp;lt;code&amp;gt;&amp;quot;searchnode&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;configserver&amp;quot;&amp;lt;/code&amp;gt;) included in every log line&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;appPrefix&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || Application prefix prepended to component names in the control file and log output&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;repo&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;LevelControllerRepo&amp;lt;/code&amp;gt; || Repository that provides per-component &amp;lt;code&amp;gt;LevelController&amp;lt;/code&amp;gt; instances for &amp;lt;code&amp;gt;shouldLog()&amp;lt;/code&amp;gt; checks&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logRejectFilter&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;RejectFilter&amp;lt;/code&amp;gt; || Content-based filter that drops known-useless log messages&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logTarget&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;LogTarget&amp;lt;/code&amp;gt; || The log output target. Created from the &amp;lt;code&amp;gt;VESPA_LOG_TARGET&amp;lt;/code&amp;gt; configuration value. Supports file descriptors (&amp;lt;code&amp;gt;fd:2&amp;lt;/code&amp;gt;), file paths (&amp;lt;code&amp;gt;file:/path&amp;lt;/code&amp;gt;), and stdout.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;levelControllerRepo&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;LevelControllerRepo&amp;lt;/code&amp;gt; || The level controller repository, either a &amp;lt;code&amp;gt;VespaLevelControllerRepo&amp;lt;/code&amp;gt; (memory-mapped) or &amp;lt;code&amp;gt;DefaultLevelControllerRepo&amp;lt;/code&amp;gt; (static levels).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;serviceName&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || The Vespa service name (from &amp;lt;code&amp;gt;VESPA_SERVICE_NAME&amp;lt;/code&amp;gt;). Used in the &amp;lt;code&amp;gt;VespaFormatter&amp;lt;/code&amp;gt; to populate the service field of each log line.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;applicationPrefix&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || The application prefix (typically the program name). Used as the component prefix in log output and control file entries.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Constructor Source ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
VespaLogHandler(LogTarget logTarget, LevelControllerRepo levelControllerRepo,&lt;br /&gt;
                String serviceName, String applicationPrefix) {&lt;br /&gt;
    this.logTarget = logTarget;&lt;br /&gt;
    this.serviceName = serviceName;&lt;br /&gt;
    this.appPrefix = applicationPrefix;&lt;br /&gt;
    this.repo = levelControllerRepo;&lt;br /&gt;
    this.logRejectFilter = RejectFilter.createDefaultRejectFilter();&lt;br /&gt;
    initialize();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Initialization Sequence ===&lt;br /&gt;
&lt;br /&gt;
==== Step 1: Store Dependencies ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
this.logTarget = logTarget;&lt;br /&gt;
this.serviceName = serviceName;&lt;br /&gt;
this.appPrefix = applicationPrefix;&lt;br /&gt;
this.repo = levelControllerRepo;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All four constructor parameters are stored as instance fields. These are used during the &amp;lt;code&amp;gt;publish()&amp;lt;/code&amp;gt; call path.&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Create the Reject Filter ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
this.logRejectFilter = RejectFilter.createDefaultRejectFilter();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;RejectFilter&amp;lt;/code&amp;gt; is a content-based filter that examines log message text and drops messages matching known-useless patterns. The default filter is created via a factory method that includes patterns for common noisy messages. This filter is applied &#039;&#039;&#039;after&#039;&#039;&#039; level checking, as an additional layer of noise reduction.&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Initialize the Handler ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
initialize();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;initialize()&amp;lt;/code&amp;gt; method (not shown in the constructor) performs the following setup:&lt;br /&gt;
&lt;br /&gt;
# Creates a &amp;lt;code&amp;gt;VespaFormatter&amp;lt;/code&amp;gt; with the service name and application prefix.&lt;br /&gt;
# Sets the formatter on this handler via &amp;lt;code&amp;gt;setFormatter()&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Sets the handler level to &amp;lt;code&amp;gt;ALL&amp;lt;/code&amp;gt; so that level filtering is handled by the &amp;lt;code&amp;gt;LevelController&amp;lt;/code&amp;gt; rather than the JUL framework.&lt;br /&gt;
&lt;br /&gt;
=== Level Reduction Map ===&lt;br /&gt;
&lt;br /&gt;
The handler also maintains a &#039;&#039;&#039;level reduction map&#039;&#039;&#039; for noisy third-party loggers. This is a static mapping that reduces the effective log level for specific logger name prefixes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// Conceptual level reduction:&lt;br /&gt;
// &amp;quot;org.eclipse.jetty&amp;quot; -&amp;gt; reduce INFO to DEBUG&lt;br /&gt;
// &amp;quot;org.apache.aries.spifly&amp;quot; -&amp;gt; reduce INFO to DEBUG&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;possiblyReduceLogLevel(String loggerName, Level level)&amp;lt;/code&amp;gt; method checks if the logger name matches any prefix in the reduction map. If it does, the level is reduced (e.g., INFO becomes DEBUG), effectively silencing these loggers under default configuration.&lt;br /&gt;
&lt;br /&gt;
=== The getLevelControl Method ===&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;code&amp;gt;publish()&amp;lt;/code&amp;gt; needs to check if a log record should be output, it calls:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
LevelController ctrl = getLevelControl(loggerName);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This method:&lt;br /&gt;
# Looks up the logger name in the &amp;lt;code&amp;gt;LevelControllerRepo&amp;lt;/code&amp;gt;.&lt;br /&gt;
# If a per-component entry exists in the control file, returns its &amp;lt;code&amp;gt;LevelController&amp;lt;/code&amp;gt;.&lt;br /&gt;
# If no entry exists, registers the component in the control file and returns a new controller initialized with default levels.&lt;br /&gt;
&lt;br /&gt;
=== Usage Context ===&lt;br /&gt;
&lt;br /&gt;
The constructor is called from &amp;lt;code&amp;gt;LogSetup.initInternal()&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// Inside LogSetup.initInternal():&lt;br /&gt;
LogTarget target = LogTarget.createLogTarget(logTargetString);&lt;br /&gt;
LevelControllerRepo repo = new VespaLevelControllerRepo(logControlFile, logLevel, programName);&lt;br /&gt;
VespaLogHandler handler = new VespaLogHandler(target, repo, serviceName, programName);&lt;br /&gt;
&lt;br /&gt;
// Install on root logger&lt;br /&gt;
Logger rootLogger = Logger.getLogger(&amp;quot;&amp;quot;);&lt;br /&gt;
for (Handler h : rootLogger.getHandlers()) {&lt;br /&gt;
    rootLogger.removeHandler(h);&lt;br /&gt;
}&lt;br /&gt;
rootLogger.addHandler(handler);&lt;br /&gt;
rootLogger.setLevel(Level.ALL);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implements Principle ===&lt;br /&gt;
&lt;br /&gt;
[[Principle:Vespa_engine_Vespa_Logger_Handler_Installation|Logger Handler Installation]]&lt;br /&gt;
&lt;br /&gt;
=== Related Implementations ===&lt;br /&gt;
&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_LogSetup_InitVespaLogging|LogSetup.initVespaLogging]] -- Resolves configuration and triggers handler construction&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_VespaLevelControllerRepo_Constructor|VespaLevelControllerRepo Constructor]] -- Creates the level controller repo passed to this constructor&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_VespaLogHandler_Publish|VespaLogHandler.publish]] -- The method called on each log record after the handler is installed&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_VespaFormatter_Format|VespaFormatter.format]] -- The formatter used to produce tab-delimited output&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Vespa_engine_Vespa_Logger_Handler_Installation]]&lt;br /&gt;
* [[requires_env::Environment:Vespa_engine_Vespa_POSIX_Mmap_Log_Control]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_VespaLevelControllerRepo_Constructor&amp;diff=30780</id>
		<title>Implementation:Vespa engine Vespa VespaLevelControllerRepo Constructor</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_VespaLevelControllerRepo_Constructor&amp;diff=30780"/>
		<updated>2026-09-27T10:53:17Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_VespaLevelControllerRepo_Constructor}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_VespaLevelControllerRepo_Constructor}}&lt;br /&gt;
== VespaLevelControllerRepo Constructor ==&lt;br /&gt;
&lt;br /&gt;
[[domain::Logging]] [[domain::Observability]]&lt;br /&gt;
&lt;br /&gt;
=== API Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
VespaLevelControllerRepo(String logCtlFn, String logLevel, String applicationPrefix)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;File&#039;&#039;&#039;: [https://github.com/vespa-engine/vespa/blob/master/vespalog/src/main/java/com/yahoo/log/VespaLevelControllerRepo.java vespalog/src/main/java/com/yahoo/log/VespaLevelControllerRepo.java]&lt;br /&gt;
* &#039;&#039;&#039;Lines&#039;&#039;&#039;: L58-63&lt;br /&gt;
* &#039;&#039;&#039;Class&#039;&#039;&#039;: &amp;lt;code&amp;gt;class VespaLevelControllerRepo implements LevelControllerRepo&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Package&#039;&#039;&#039;: &amp;lt;code&amp;gt;com.yahoo.log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;VespaLevelControllerRepo&amp;lt;/code&amp;gt; constructor initializes the &#039;&#039;&#039;memory-mapped level control subsystem&#039;&#039;&#039;. It stores the control file path and application prefix, creates a default level controller from the level string, and then opens (or creates) the control file via &amp;lt;code&amp;gt;openCtlFile()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This class implements &amp;lt;code&amp;gt;LevelControllerRepo&amp;lt;/code&amp;gt;, which provides the interface for looking up per-component level controllers. The repository is the bridge between the memory-mapped control file on disk and the level-checking logic used by the &amp;lt;code&amp;gt;VespaLogHandler&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Key Fields ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Field !! Type !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ctlFile&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;RandomAccessFile&amp;lt;/code&amp;gt; || Handle to the log control file opened in read-write mode&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mapBuf&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;MappedByteBuffer&amp;lt;/code&amp;gt; || Memory-mapped view of the control file contents&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;levelControllerRepo&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;MappedLevelControllerRepo&amp;lt;/code&amp;gt; || Repository backed by the mapped buffer for per-component lookups&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logControlFilename&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || Absolute path to the log control file&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;appPrefix&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || Application prefix prepended to component names in the control file&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;defaultLevelCtrl&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;DefaultLevelController&amp;lt;/code&amp;gt; || Fallback level controller used when no per-component entry exists&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Constants ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Constant !! Value !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;maxPrefix&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;64&amp;lt;/code&amp;gt; || Maximum length of the application prefix in the control file&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;CFHEADER&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Vespa log control file version 1\n&amp;quot;&amp;lt;/code&amp;gt; || Header string written to and validated in the control file&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;numLevels&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; || Number of log levels supported (fatal, error, warning, config, info, event, debug, spam)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logCtlFn&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || Absolute path to the log control file. Derived from &amp;lt;code&amp;gt;VESPA_LOG_CONTROL_DIR&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;VESPA_SERVICE_NAME&amp;lt;/code&amp;gt;, or set explicitly via &amp;lt;code&amp;gt;VESPA_LOG_CONTROL_FILE&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logLevel&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || Default log level string (e.g., &amp;lt;code&amp;gt;&amp;quot;all -debug -spam&amp;quot;&amp;lt;/code&amp;gt;). Used by the &amp;lt;code&amp;gt;DefaultLevelController&amp;lt;/code&amp;gt; for components without explicit entries.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;applicationPrefix&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || The application prefix (e.g., the program name) written to the control file header and used to scope component entries.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Constructor Source ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
VespaLevelControllerRepo(String logCtlFn, String logLevel, String applicationPrefix) {&lt;br /&gt;
    this.logControlFilename = logCtlFn;&lt;br /&gt;
    this.appPrefix = applicationPrefix;&lt;br /&gt;
    defaultLevelCtrl = new DefaultLevelController(logLevel);&lt;br /&gt;
    openCtlFile();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Initialization Sequence ===&lt;br /&gt;
&lt;br /&gt;
==== Step 1: Store Configuration ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
this.logControlFilename = logCtlFn;&lt;br /&gt;
this.appPrefix = applicationPrefix;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The control file path and application prefix are stored for use by &amp;lt;code&amp;gt;openCtlFile()&amp;lt;/code&amp;gt; and subsequent component registration.&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Create Default Level Controller ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
defaultLevelCtrl = new DefaultLevelController(logLevel);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;DefaultLevelController&amp;lt;/code&amp;gt; parses the level string (e.g., &amp;lt;code&amp;gt;&amp;quot;all -debug -spam&amp;quot;&amp;lt;/code&amp;gt;) and creates a level controller that can answer &amp;lt;code&amp;gt;shouldLog(level)&amp;lt;/code&amp;gt; queries. This serves as the &#039;&#039;&#039;fallback&#039;&#039;&#039; for any component that does not have an explicit entry in the control file.&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Open the Control File ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
openCtlFile();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;openCtlFile()&amp;lt;/code&amp;gt; method performs the heavy lifting:&lt;br /&gt;
&lt;br /&gt;
# Opens (or creates) the file at &amp;lt;code&amp;gt;logControlFilename&amp;lt;/code&amp;gt; using &amp;lt;code&amp;gt;RandomAccessFile&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;&amp;quot;rw&amp;quot;&amp;lt;/code&amp;gt; mode.&lt;br /&gt;
# If the file is newly created, writes the &amp;lt;code&amp;gt;CFHEADER&amp;lt;/code&amp;gt; and the application prefix.&lt;br /&gt;
# If the file exists, validates the header string.&lt;br /&gt;
# Maps the file into memory via &amp;lt;code&amp;gt;FileChannel.map(MapMode.READ_WRITE, ...)&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Creates a &amp;lt;code&amp;gt;MappedLevelControllerRepo&amp;lt;/code&amp;gt; from the &amp;lt;code&amp;gt;MappedByteBuffer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== LevelControllerRepo Interface ===&lt;br /&gt;
&lt;br /&gt;
The class implements the &amp;lt;code&amp;gt;LevelControllerRepo&amp;lt;/code&amp;gt; interface, which provides:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public interface LevelControllerRepo {&lt;br /&gt;
    LevelController getLevelController(String component);&lt;br /&gt;
    void close();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When &amp;lt;code&amp;gt;getLevelController(component)&amp;lt;/code&amp;gt; is called:&lt;br /&gt;
# It first checks the &amp;lt;code&amp;gt;MappedLevelControllerRepo&amp;lt;/code&amp;gt; for an existing entry.&lt;br /&gt;
# If no entry exists, it creates a new entry in the memory-mapped file for that component.&lt;br /&gt;
# If the control file is not available, it returns the &amp;lt;code&amp;gt;defaultLevelCtrl&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Error Handling ===&lt;br /&gt;
&lt;br /&gt;
* If the control file cannot be opened or created, the repository falls back to using only the &amp;lt;code&amp;gt;defaultLevelCtrl&amp;lt;/code&amp;gt;. Runtime level control is disabled in this case.&lt;br /&gt;
* If the file header does not match &amp;lt;code&amp;gt;CFHEADER&amp;lt;/code&amp;gt;, the file is treated as corrupt and a warning is logged.&lt;br /&gt;
&lt;br /&gt;
=== Usage Context ===&lt;br /&gt;
&lt;br /&gt;
The constructor is called from within &amp;lt;code&amp;gt;LogSetup.initInternal()&amp;lt;/code&amp;gt; after the control file path and log level have been resolved:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// Inside LogSetup.initInternal():&lt;br /&gt;
LevelControllerRepo repo;&lt;br /&gt;
if (logControlFile != null) {&lt;br /&gt;
    repo = new VespaLevelControllerRepo(logControlFile, logLevel, programName);&lt;br /&gt;
} else {&lt;br /&gt;
    repo = new DefaultLevelControllerRepo(logLevel);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Implements Principle ===&lt;br /&gt;
&lt;br /&gt;
[[Principle:Vespa_engine_Vespa_Control_File_Initialization|Control File Initialization]]&lt;br /&gt;
&lt;br /&gt;
=== Related Implementations ===&lt;br /&gt;
&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_LogSetup_InitVespaLogging|LogSetup.initVespaLogging]] -- Resolves the control file path and calls this constructor&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Vespa_Logctl|vespa-logctl]] -- The CLI tool that reads and modifies the same control file at runtime&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Vespa_engine_Vespa_Control_File_Initialization]]&lt;br /&gt;
* [[requires_env::Environment:Vespa_engine_Vespa_POSIX_Mmap_Log_Control]]&lt;br /&gt;
* [[uses_heuristic::Heuristic:Vespa_engine_Vespa_Log_Level_Inheritance_Polling]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_VespaFormatter_Format&amp;diff=30779</id>
		<title>Implementation:Vespa engine Vespa VespaFormatter Format</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_VespaFormatter_Format&amp;diff=30779"/>
		<updated>2026-09-27T10:53:16Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_VespaFormatter_Format}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_VespaFormatter_Format}}&lt;br /&gt;
== VespaFormatter.format ==&lt;br /&gt;
&lt;br /&gt;
[[domain::Logging]] [[domain::Observability]]&lt;br /&gt;
&lt;br /&gt;
=== API Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public String format(LogRecord r)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;File&#039;&#039;&#039;: [https://github.com/vespa-engine/vespa/blob/master/vespalog/src/main/java/com/yahoo/log/VespaFormatter.java vespalog/src/main/java/com/yahoo/log/VespaFormatter.java]&lt;br /&gt;
* &#039;&#039;&#039;Lines&#039;&#039;&#039;: L94-135&lt;br /&gt;
* &#039;&#039;&#039;Class&#039;&#039;&#039;: &amp;lt;code&amp;gt;class VespaFormatter extends SimpleFormatter&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Package&#039;&#039;&#039;: &amp;lt;code&amp;gt;com.yahoo.log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;format&amp;lt;/code&amp;gt; method converts a JUL &amp;lt;code&amp;gt;LogRecord&amp;lt;/code&amp;gt; into Vespa&#039;s &#039;&#039;&#039;tab-delimited log line format&#039;&#039;&#039;. It produces a single line containing the timestamp, hostname, process/thread IDs, service name, component path, log level, and escaped message. This method is called by the &amp;lt;code&amp;gt;VespaLogHandler&amp;lt;/code&amp;gt; for every log record that passes level control and reject filtering.&lt;br /&gt;
&lt;br /&gt;
=== Key Fields ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Field !! Type !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hostname&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || The hostname of the machine, resolved once at formatter construction time&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;processID&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || The process ID (PID) of the current JVM, resolved once at construction time&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;serviceName&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || The Vespa service name (e.g., &amp;lt;code&amp;gt;&amp;quot;searchnode&amp;quot;&amp;lt;/code&amp;gt;) from &amp;lt;code&amp;gt;VESPA_SERVICE_NAME&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;componentPrefix&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || The application prefix (e.g., &amp;lt;code&amp;gt;&amp;quot;container&amp;quot;&amp;lt;/code&amp;gt;) prepended to the logger name in the component field&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;LogRecord&amp;lt;/code&amp;gt; || The JUL log record to format. Contains the log level, logger name, message, thread ID, timestamp, optional thrown exception, and optional parameters.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Return Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; -- A single tab-delimited log line ending with &amp;lt;code&amp;gt;\n&amp;lt;/code&amp;gt;. The format is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;time&amp;gt;\t&amp;lt;hostname&amp;gt;\t&amp;lt;pid/tid&amp;gt;\t&amp;lt;service&amp;gt;\t&amp;lt;component&amp;gt;\t&amp;lt;level&amp;gt;\t&amp;lt;message&amp;gt;\n&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Full Method Source ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public String format(LogRecord r) {&lt;br /&gt;
    StringBuilder sbuf = new StringBuilder(300);&lt;br /&gt;
&lt;br /&gt;
    String levelName = LogLevel.getVespaLogLevel(r.getLevel())&lt;br /&gt;
                               .toString().toLowerCase();&lt;br /&gt;
&lt;br /&gt;
    String component = r.getLoggerName();&lt;br /&gt;
&lt;br /&gt;
    sbuf.append(VespaFormat.formatTime(r.getInstant()));&lt;br /&gt;
    sbuf.append(&amp;quot;\t&amp;quot;);&lt;br /&gt;
    sbuf.append(hostname).append(&amp;quot;\t&amp;quot;)&lt;br /&gt;
        .append(processID).append(&amp;quot;/&amp;quot;)&lt;br /&gt;
        .append(r.getThreadID()).append(&amp;quot;\t&amp;quot;)&lt;br /&gt;
        .append(serviceName).append(&amp;quot;\t&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    if (component == null &amp;amp;&amp;amp; componentPrefix == null) {&lt;br /&gt;
        sbuf.append(&amp;quot;-&amp;quot;);&lt;br /&gt;
    } else if (component == null) {&lt;br /&gt;
        sbuf.append(componentPrefix);&lt;br /&gt;
    } else if (componentPrefix == null) {&lt;br /&gt;
        sbuf.append(&amp;quot;.&amp;quot;).append(component);&lt;br /&gt;
    } else {&lt;br /&gt;
        sbuf.append(componentPrefix).append(&amp;quot;.&amp;quot;).append(component);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    sbuf.append(&amp;quot;\t&amp;quot;).append(levelName).append(&amp;quot;\t&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    if (r.getLevel() == LogLevel.EVENT) {&lt;br /&gt;
        Event event = (Event) r.getParameters()[0];&lt;br /&gt;
        sbuf.append(VespaFormat.escape(event.toString()));&lt;br /&gt;
    } else {&lt;br /&gt;
        sbuf.append(VespaFormat.escape(formatMessage(r)));&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    appendException(r.getThrown(), sbuf);&lt;br /&gt;
    sbuf.append(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    return sbuf.toString();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Field-by-Field Breakdown ===&lt;br /&gt;
&lt;br /&gt;
==== 1. Timestamp ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
sbuf.append(VespaFormat.formatTime(r.getInstant()));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Formats the log record&#039;s &amp;lt;code&amp;gt;Instant&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;seconds.microseconds&amp;lt;/code&amp;gt; in Unix epoch format (e.g., &amp;lt;code&amp;gt;1696000000.123456&amp;lt;/code&amp;gt;). The &amp;lt;code&amp;gt;VespaFormat.formatTime()&amp;lt;/code&amp;gt; utility method handles the conversion.&lt;br /&gt;
&lt;br /&gt;
==== 2. Hostname ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
sbuf.append(hostname);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The hostname is resolved &#039;&#039;&#039;once&#039;&#039;&#039; at formatter construction time and stored as a field. It does not change during the lifetime of the process.&lt;br /&gt;
&lt;br /&gt;
==== 3. PID/TID ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
sbuf.append(processID).append(&amp;quot;/&amp;quot;).append(r.getThreadID());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The process ID is resolved once at construction. The thread ID is extracted from the &amp;lt;code&amp;gt;LogRecord&amp;lt;/code&amp;gt; and changes per log call. The format is &amp;lt;code&amp;gt;pid/tid&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;12345/67&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== 4. Service Name ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
sbuf.append(serviceName);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The service name is set during formatter construction from the &amp;lt;code&amp;gt;VESPA_SERVICE_NAME&amp;lt;/code&amp;gt; value (e.g., &amp;lt;code&amp;gt;&amp;quot;searchnode&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;configserver&amp;quot;&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== 5. Component ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
if (component == null &amp;amp;&amp;amp; componentPrefix == null) {&lt;br /&gt;
    sbuf.append(&amp;quot;-&amp;quot;);&lt;br /&gt;
} else if (component == null) {&lt;br /&gt;
    sbuf.append(componentPrefix);&lt;br /&gt;
} else if (componentPrefix == null) {&lt;br /&gt;
    sbuf.append(&amp;quot;.&amp;quot;).append(component);&lt;br /&gt;
} else {&lt;br /&gt;
    sbuf.append(componentPrefix).append(&amp;quot;.&amp;quot;).append(component);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The component field is built from the application prefix and the JUL logger name:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! componentPrefix !! component (logger name) !! Output&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;container&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;container&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;com.yahoo.search&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;.com.yahoo.search&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&amp;quot;container&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;com.yahoo.search&amp;quot;&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;container.com.yahoo.search&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 6. Level ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
String levelName = LogLevel.getVespaLogLevel(r.getLevel())&lt;br /&gt;
                           .toString().toLowerCase();&lt;br /&gt;
sbuf.append(levelName);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The JUL level is mapped to Vespa&#039;s level names via &amp;lt;code&amp;gt;LogLevel.getVespaLogLevel()&amp;lt;/code&amp;gt; and converted to lowercase (e.g., &amp;lt;code&amp;gt;&amp;quot;info&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;warning&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;error&amp;quot;&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== 7. Message ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
if (r.getLevel() == LogLevel.EVENT) {&lt;br /&gt;
    Event event = (Event) r.getParameters()[0];&lt;br /&gt;
    sbuf.append(VespaFormat.escape(event.toString()));&lt;br /&gt;
} else {&lt;br /&gt;
    sbuf.append(VespaFormat.escape(formatMessage(r)));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Two code paths exist:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;EVENT level&#039;&#039;&#039;: The first parameter of the log record is cast to an &amp;lt;code&amp;gt;Event&amp;lt;/code&amp;gt; object and serialized via its &amp;lt;code&amp;gt;toString()&amp;lt;/code&amp;gt; method. Events represent structured occurrences (service start/stop, state changes).&lt;br /&gt;
* &#039;&#039;&#039;All other levels&#039;&#039;&#039;: The standard JUL &amp;lt;code&amp;gt;formatMessage(r)&amp;lt;/code&amp;gt; is used, which handles message format substitution if parameters are present.&lt;br /&gt;
&lt;br /&gt;
In both cases, the output is passed through &amp;lt;code&amp;gt;VespaFormat.escape()&amp;lt;/code&amp;gt; to escape tabs, newlines, and backslashes.&lt;br /&gt;
&lt;br /&gt;
==== 8. Exception (Optional) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
appendException(r.getThrown(), sbuf);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the log record has a thrown exception, the full stack trace is appended to the message. Stack trace newlines are escaped so the entire record remains on a single line.&lt;br /&gt;
&lt;br /&gt;
==== 9. Newline ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
sbuf.append(&amp;quot;\n&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The log line is terminated with a single newline character.&lt;br /&gt;
&lt;br /&gt;
=== Example Output ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1696000000.123456	node-01.example.com	12345/67	searchnode	container.com.yahoo.search.handler	info	Query completed in 42ms&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Performance Notes ===&lt;br /&gt;
&lt;br /&gt;
* The &amp;lt;code&amp;gt;StringBuilder&amp;lt;/code&amp;gt; is initialized with a capacity of &#039;&#039;&#039;300&#039;&#039;&#039; characters, which is a reasonable estimate for most log lines and avoids reallocation in the common case.&lt;br /&gt;
* The hostname and process ID are resolved once and cached, avoiding per-record system calls.&lt;br /&gt;
* The &amp;lt;code&amp;gt;VespaFormat.escape()&amp;lt;/code&amp;gt; method only allocates a new string if the input contains characters that need escaping.&lt;br /&gt;
&lt;br /&gt;
=== Implements Principle ===&lt;br /&gt;
&lt;br /&gt;
[[Principle:Vespa_engine_Vespa_Log_Message_Formatting|Log Message Formatting]]&lt;br /&gt;
&lt;br /&gt;
=== Related Implementations ===&lt;br /&gt;
&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_VespaLogHandler_Publish|VespaLogHandler.publish]] -- Calls this format method for each log record that passes filtering&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_VespaLogHandler_Constructor|VespaLogHandler Constructor]] -- Creates the formatter during handler initialization&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Vespa_engine_Vespa_Log_Message_Formatting]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Publish_Artifacts_Sh&amp;diff=30778</id>
		<title>Implementation:Vespa engine Vespa Publish Artifacts Sh</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Publish_Artifacts_Sh&amp;diff=30778"/>
		<updated>2026-09-27T10:53:15Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Publish_Artifacts_Sh}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Publish_Artifacts_Sh}}&lt;br /&gt;
{{DISPLAYTITLE:Artifact Publishing Implementation}}&lt;br /&gt;
[[domain::CI_CD]] [[domain::Build_Systems]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This page documents the implementation of the Vespa artifact signing and publishing script: &#039;&#039;.buildkite/publish-artifacts.sh&#039;&#039;. This script creates tar archives of the RPM and Maven repositories, signs each artifact using Sigstore cosign with Buildkite OIDC identity, and uploads everything to the configured artifact destination.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Type:&#039;&#039;&#039; External Tool Doc&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env bash&lt;br /&gt;
# .buildkite/publish-artifacts.sh (L1-31)&lt;br /&gt;
&lt;br /&gt;
set -o errexit&lt;br /&gt;
set -o nounset&lt;br /&gt;
set -o pipefail&lt;br /&gt;
&lt;br /&gt;
if [[ -n &amp;quot;${DEBUG:-}&amp;quot; ]]; then&lt;br /&gt;
    set -o xtrace&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;--- Publishing build artifacts&amp;quot;&lt;br /&gt;
cd &amp;quot;$WORKDIR/artifacts/$ARCH&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Creating archives...&amp;quot;&lt;br /&gt;
tar -cf rpm-repo.tar rpms &amp;amp;&lt;br /&gt;
tar -cf maven-repo.tar maven-repo&lt;br /&gt;
cp -a rpms/vespa-config-model-fat-*.rpm .&lt;br /&gt;
wait&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Signing artifacts...&amp;quot;&lt;br /&gt;
for FILE in *.tar *.rpm; do&lt;br /&gt;
    cosign sign-blob -y --oidc-provider=buildkite-agent \&lt;br /&gt;
        --output-signature &amp;quot;$FILE.sig&amp;quot; \&lt;br /&gt;
        --output-certificate &amp;quot;$FILE.pem&amp;quot; &amp;quot;$FILE&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
ARTIFACT_DESTINATION=&amp;quot;${VESPA_ENGINE_ARTIFACTS_BUCKET}/${VESPA_ENGINE_ARTIFACTS_PREFIX}/${VESPA_VERSION}/artifacts/${ARCH}&amp;quot;&lt;br /&gt;
echo &amp;quot;Uploading artifacts to ${ARTIFACT_DESTINATION} ...&amp;quot;&lt;br /&gt;
buildkite-agent artifact upload &amp;quot;*.tar;*.tar.sig;*.tar.pem;*.rpm;*.rpm.sig;*.rpm.pem&amp;quot; \&lt;br /&gt;
    &amp;quot;$ARTIFACT_DESTINATION&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs (Environment Variables) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Required !! Description !! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;WORKDIR&amp;lt;/code&amp;gt; || Yes || Working directory containing build artifacts || &amp;lt;code&amp;gt;/tmp/vespa-build&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ARCH&amp;lt;/code&amp;gt; || Yes || CPU architecture identifier || &amp;lt;code&amp;gt;x86_64&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;aarch64&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_ENGINE_ARTIFACTS_BUCKET&amp;lt;/code&amp;gt; || Yes || Cloud storage bucket for uploads || &amp;lt;code&amp;gt;s3://vespa-artifacts&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_ENGINE_ARTIFACTS_PREFIX&amp;lt;/code&amp;gt; || Yes || Path prefix within the bucket || &amp;lt;code&amp;gt;builds&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_VERSION&amp;lt;/code&amp;gt; || Yes || Version string for the artifact path || &amp;lt;code&amp;gt;8.432.17&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt; || No || If set to a non-empty value, enables bash xtrace || &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Inputs (Prerequisite Files) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! File/Directory !! Produced By !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$WORKDIR/artifacts/$ARCH/rpms/&amp;lt;/code&amp;gt; || build-rpms.sh || YUM repository with RPM packages and metadata&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$WORKDIR/artifacts/$ARCH/maven-repo/&amp;lt;/code&amp;gt; || java.sh || Maven local repository with compiled JARs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Inputs (System Dependencies) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Tool !! Purpose !! Authentication&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cosign&amp;lt;/code&amp;gt; || Sigstore keyless signing || Buildkite OIDC token (automatic)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;buildkite-agent&amp;lt;/code&amp;gt; || Artifact upload to Buildkite || Agent token (pre-configured)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tar&amp;lt;/code&amp;gt; || Archive creation || N/A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs (Files Created Locally) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;rpm-repo.tar&amp;lt;/code&amp;gt; || Tar archive || Archive of the complete YUM repository&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;maven-repo.tar&amp;lt;/code&amp;gt; || Tar archive || Archive of the Maven local repository&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;vespa-config-model-fat-*.rpm&amp;lt;/code&amp;gt; || RPM file || Extracted fat config model RPM&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;*.sig&amp;lt;/code&amp;gt; files || Detached signatures || Cosign signatures for each artifact&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;*.pem&amp;lt;/code&amp;gt; files || Certificates || Sigstore Fulcio certificates for each artifact&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs (Uploaded Artifacts) ===&lt;br /&gt;
&lt;br /&gt;
All files matching &amp;lt;code&amp;gt;*.tar&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;*.tar.sig&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;*.tar.pem&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;*.rpm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;*.rpm.sig&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;*.rpm.pem&amp;lt;/code&amp;gt; are uploaded to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
${VESPA_ENGINE_ARTIFACTS_BUCKET}/${VESPA_ENGINE_ARTIFACTS_PREFIX}/${VESPA_VERSION}/artifacts/${ARCH}/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Key Implementation Details ==&lt;br /&gt;
&lt;br /&gt;
=== Parallel Archive Creation ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tar -cf rpm-repo.tar rpms &amp;amp;&lt;br /&gt;
tar -cf maven-repo.tar maven-repo&lt;br /&gt;
cp -a rpms/vespa-config-model-fat-*.rpm .&lt;br /&gt;
wait&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The RPM repository archive is created in a background process (&amp;lt;code&amp;gt;&amp;amp;&amp;lt;/code&amp;gt;), while the Maven repository archive runs in the foreground. The &amp;lt;code&amp;gt;cp -a&amp;lt;/code&amp;gt; command extracts the fat config model RPM for separate distribution. The &amp;lt;code&amp;gt;wait&amp;lt;/code&amp;gt; command synchronizes with the background process before proceeding.&lt;br /&gt;
&lt;br /&gt;
This parallel approach reduces total archiving time. Both tar operations are I/O-bound, so they can share disk bandwidth. The archives are uncompressed (&amp;lt;code&amp;gt;-cf&amp;lt;/code&amp;gt; without a compression flag) because the downstream upload and any further packaging will handle compression.&lt;br /&gt;
&lt;br /&gt;
=== Signing Loop ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
for FILE in *.tar *.rpm; do&lt;br /&gt;
    cosign sign-blob -y --oidc-provider=buildkite-agent \&lt;br /&gt;
        --output-signature &amp;quot;$FILE.sig&amp;quot; \&lt;br /&gt;
        --output-certificate &amp;quot;$FILE.pem&amp;quot; &amp;quot;$FILE&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The loop iterates over all tar archives and RPM files in the working directory. For each file, cosign performs keyless signing:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;-y&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Automatically accepts the Sigstore terms of service (non-interactive mode for CI).&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;--oidc-provider=buildkite-agent&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Uses the Buildkite agent&#039;s built-in OIDC provider to obtain an identity token. The token contains claims identifying the Buildkite organization, pipeline, and build.&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;--output-signature &amp;quot;$FILE.sig&amp;quot;&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Writes the detached signature to a &amp;lt;code&amp;gt;.sig&amp;lt;/code&amp;gt; file alongside the artifact.&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;--output-certificate &amp;quot;$FILE.pem&amp;quot;&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Writes the short-lived Fulcio certificate to a &amp;lt;code&amp;gt;.pem&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
Each signing operation involves network calls to:&lt;br /&gt;
# The Buildkite OIDC endpoint (for identity token)&lt;br /&gt;
# Sigstore Fulcio (for certificate issuance)&lt;br /&gt;
# Sigstore Rekor (for transparency log recording)&lt;br /&gt;
&lt;br /&gt;
=== Artifact Upload ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ARTIFACT_DESTINATION=&amp;quot;${VESPA_ENGINE_ARTIFACTS_BUCKET}/${VESPA_ENGINE_ARTIFACTS_PREFIX}/${VESPA_VERSION}/artifacts/${ARCH}&amp;quot;&lt;br /&gt;
buildkite-agent artifact upload &amp;quot;*.tar;*.tar.sig;*.tar.pem;*.rpm;*.rpm.sig;*.rpm.pem&amp;quot; &amp;quot;$ARTIFACT_DESTINATION&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;buildkite-agent artifact upload&amp;lt;/code&amp;gt; command uploads matching files to the specified destination. Key aspects:&lt;br /&gt;
&lt;br /&gt;
* The glob patterns are semicolon-separated, matching multiple file types in a single command.&lt;br /&gt;
* The destination path is hierarchically structured: bucket / prefix / version / artifacts / architecture.&lt;br /&gt;
* The Buildkite agent handles authentication to the underlying storage backend (S3, GCS, etc.) using pre-configured credentials.&lt;br /&gt;
&lt;br /&gt;
=== Working Directory Management ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cd &amp;quot;$WORKDIR/artifacts/$ARCH&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script changes to the architecture-specific artifact directory at the outset. All subsequent operations (archiving, signing, uploading) use relative paths within this directory. This simplifies the tar and glob commands and ensures the archive internal paths are clean (e.g., &amp;lt;code&amp;gt;rpms/vespa-8.432.17-1.x86_64.rpm&amp;lt;/code&amp;gt; rather than &amp;lt;code&amp;gt;/tmp/vespa-build/artifacts/x86_64/rpms/...&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
== Error Handling ==&lt;br /&gt;
&lt;br /&gt;
The script uses strict error handling (&amp;lt;code&amp;gt;set -o errexit&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set -o nounset&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;set -o pipefail&amp;lt;/code&amp;gt;). If any command fails -- archiving, signing, or uploading -- the script terminates immediately. This is important because:&lt;br /&gt;
&lt;br /&gt;
* A failed signing operation should not be followed by an upload of unsigned artifacts.&lt;br /&gt;
* A failed upload should be clearly reported rather than silently skipped.&lt;br /&gt;
* The &amp;lt;code&amp;gt;wait&amp;lt;/code&amp;gt; command propagates the exit code of the background tar process.&lt;br /&gt;
&lt;br /&gt;
== Execution Context ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Buildkite Pipeline&lt;br /&gt;
  --&amp;gt; .buildkite/build-rpms.sh (produces RPMs)&lt;br /&gt;
  --&amp;gt; .buildkite/java.sh (produces Maven repo)&lt;br /&gt;
  --&amp;gt; .buildkite/publish-artifacts.sh&lt;br /&gt;
        --&amp;gt; cd $WORKDIR/artifacts/$ARCH&lt;br /&gt;
        --&amp;gt; tar -cf rpm-repo.tar rpms &amp;amp;&lt;br /&gt;
        --&amp;gt; tar -cf maven-repo.tar maven-repo&lt;br /&gt;
        --&amp;gt; cp vespa-config-model-fat RPM&lt;br /&gt;
        --&amp;gt; wait (synchronize background tar)&lt;br /&gt;
        --&amp;gt; cosign sign-blob (for each *.tar and *.rpm)&lt;br /&gt;
        --&amp;gt; buildkite-agent artifact upload&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Source File Locations ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/vespa-engine/vespa/blob/master/.buildkite/publish-artifacts.sh &amp;lt;code&amp;gt;.buildkite/publish-artifacts.sh&amp;lt;/code&amp;gt;] (Lines 1-31)&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Principle:Vespa_engine_Vespa_Artifact_Signing_and_Publishing|Artifact Signing and Publishing Principle]] -- The design rationale for keyless signing and artifact distribution.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Build_Rpms_Sh|RPM Build Implementation]] -- The preceding stage that produces RPM packages.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Build_Container_Sh|Container Build Implementation]] -- The parallel stage that produces container images.&lt;br /&gt;
* [https://docs.sigstore.dev/cosign/overview/ Sigstore cosign documentation]&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Vespa_engine_Vespa_Artifact_Signing_and_Publishing]]&lt;br /&gt;
* [[requires_env::Environment:Vespa_engine_Vespa_Java_17_Build_Runtime]]&lt;br /&gt;
* [[requires_env::Environment:Vespa_engine_Vespa_Cosign_Sigstore_Signing]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Prepare_Sh&amp;diff=30777</id>
		<title>Implementation:Vespa engine Vespa Prepare Sh</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Prepare_Sh&amp;diff=30777"/>
		<updated>2026-09-27T10:53:15Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Prepare_Sh}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Prepare_Sh}}&lt;br /&gt;
{{DISPLAYTITLE:Prepare.sh Implementation}}&lt;br /&gt;
[[domain::CI_CD]] [[domain::Build_Systems]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This page documents the implementation of the Vespa version preparation scripts: &#039;&#039;prepare.sh&#039;&#039; and &#039;&#039;replace-vespa-version-in-poms.sh&#039;&#039;. These scripts form the first stage of the Vespa CI/CD build pipeline and are responsible for injecting a release version string into all Maven POM files and creating the artifact directory structure.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Type:&#039;&#039;&#039; External Tool Doc&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== prepare.sh ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env bash&lt;br /&gt;
# .buildkite/prepare.sh (L1-21)&lt;br /&gt;
&lt;br /&gt;
set -o errexit&lt;br /&gt;
set -o nounset&lt;br /&gt;
set -o pipefail&lt;br /&gt;
&lt;br /&gt;
if [[ -n &amp;quot;${DEBUG:-}&amp;quot; ]]; then&lt;br /&gt;
    set -o xtrace&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;--- Preparing build environment&amp;quot;&lt;br /&gt;
echo &amp;quot;Updating Vespa version in POMs to $VESPA_VERSION...&amp;quot;&lt;br /&gt;
&amp;quot;$SOURCE_DIR/.buildkite/replace-vespa-version-in-poms.sh&amp;quot; &amp;quot;$VESPA_VERSION&amp;quot; &amp;quot;$SOURCE_DIR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Creating artifact directories...&amp;quot;&lt;br /&gt;
mkdir -p &amp;quot;$WORKDIR/artifacts/$ARCH/rpms&amp;quot;&lt;br /&gt;
mkdir -p &amp;quot;$WORKDIR/artifacts/$ARCH/maven-repo&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== replace-vespa-version-in-poms.sh ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env bash&lt;br /&gt;
# .buildkite/replace-vespa-version-in-poms.sh (L1-46)&lt;br /&gt;
&lt;br /&gt;
set -o errexit&lt;br /&gt;
set -o nounset&lt;br /&gt;
set -o pipefail&lt;br /&gt;
&lt;br /&gt;
if [[ -n &amp;quot;${DEBUG:-}&amp;quot; ]]; then&lt;br /&gt;
    set -o xtrace&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [[ $# -ne 2 ]]; then&lt;br /&gt;
    echo &amp;quot;Usage: $(basename &amp;quot;$0&amp;quot;) &amp;lt;Vespa version&amp;gt; &amp;lt;path&amp;gt;&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
readonly VESPA_VERSION=$1&lt;br /&gt;
readonly DIR=$2&lt;br /&gt;
&lt;br /&gt;
# Fail if DIR does not exist or is not a directory&lt;br /&gt;
if [[ ! -d &amp;quot;$DIR&amp;quot; ]]; then&lt;br /&gt;
    echo &amp;quot;Directory $DIR does not exist or is not a directory.&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [[ -z $(find -L &amp;quot;$DIR&amp;quot; -name &amp;quot;pom.xml&amp;quot;) ]]; then&lt;br /&gt;
    echo &amp;quot;No pom.xml files found in $DIR&amp;quot;&lt;br /&gt;
    exit 0&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Updating version strings in POM files...&amp;quot;&lt;br /&gt;
if [[ &amp;quot;$(uname)&amp;quot; == &amp;quot;Darwin&amp;quot; ]]; then&lt;br /&gt;
    SED_INPLACE=(sed -i &#039;&#039;)&lt;br /&gt;
else&lt;br /&gt;
    SED_INPLACE=(sed -i)&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
find -L &amp;quot;$DIR&amp;quot; -name &amp;quot;pom.xml&amp;quot; -exec &amp;quot;${SED_INPLACE[@]}&amp;quot; \&lt;br /&gt;
     -e &amp;quot;s,&amp;lt;version&amp;gt;.*SNAPSHOT.*&amp;lt;/version&amp;gt;,&amp;lt;version&amp;gt;$VESPA_VERSION&amp;lt;/version&amp;gt;,&amp;quot; \&lt;br /&gt;
     -e &amp;quot;s,&amp;lt;vespaversion&amp;gt;.*project.version.*&amp;lt;/vespaversion&amp;gt;,&amp;lt;vespaversion&amp;gt;$VESPA_VERSION&amp;lt;/vespaversion&amp;gt;,&amp;quot; \&lt;br /&gt;
     -e &amp;quot;s,&amp;lt;test-framework.version&amp;gt;.*project.version.*&amp;lt;/test-framework.version&amp;gt;,&amp;lt;test-framework.version&amp;gt;$VESPA_VERSION&amp;lt;/test-framework.version&amp;gt;,&amp;quot; \&lt;br /&gt;
     {} \;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs (Environment Variables) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Required !! Description !! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_VERSION&amp;lt;/code&amp;gt; || Yes || Target version string to inject into POM files || &amp;lt;code&amp;gt;8.432.17&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SOURCE_DIR&amp;lt;/code&amp;gt; || Yes || Absolute path to the Vespa source checkout root || &amp;lt;code&amp;gt;/vespa&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;WORKDIR&amp;lt;/code&amp;gt; || Yes || Working directory for build artifacts || &amp;lt;code&amp;gt;/tmp/vespa-build&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ARCH&amp;lt;/code&amp;gt; || Yes || CPU architecture identifier || &amp;lt;code&amp;gt;x86_64&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;aarch64&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt; || No || If set to a non-empty value, enables bash xtrace for debugging || &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Inputs (Arguments to replace-vespa-version-in-poms.sh) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Position !! Description !! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$1&amp;lt;/code&amp;gt; || Vespa version string || &amp;lt;code&amp;gt;8.432.17&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$2&amp;lt;/code&amp;gt; || Path to directory containing POM files || &amp;lt;code&amp;gt;/vespa&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs (Files) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Modified &amp;lt;code&amp;gt;pom.xml&amp;lt;/code&amp;gt; files || In-place file modification || All POM files under &amp;lt;code&amp;gt;$SOURCE_DIR&amp;lt;/code&amp;gt; have SNAPSHOT versions replaced&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$WORKDIR/artifacts/$ARCH/rpms/&amp;lt;/code&amp;gt; || Directory || Empty directory for RPM artifacts&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$WORKDIR/artifacts/$ARCH/maven-repo/&amp;lt;/code&amp;gt; || Directory || Empty directory for Maven repository artifacts&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Key Implementation Details ==&lt;br /&gt;
&lt;br /&gt;
=== sed Substitution Patterns ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find ... -exec sed&amp;lt;/code&amp;gt; command applies three substitution expressions to each POM file:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Module version replacement&#039;&#039;&#039;: Matches any &amp;lt;code&amp;gt;&amp;lt;version&amp;gt;&amp;lt;/code&amp;gt; tag containing the string &amp;lt;code&amp;gt;SNAPSHOT&amp;lt;/code&amp;gt; and replaces the entire content with the target version. The regex uses &amp;lt;code&amp;gt;.*SNAPSHOT.*&amp;lt;/code&amp;gt; to match version strings like &amp;lt;code&amp;gt;8.999.1-SNAPSHOT&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;8-SNAPSHOT&amp;lt;/code&amp;gt;.&lt;br /&gt;
# &#039;&#039;&#039;Vespa dependency version replacement&#039;&#039;&#039;: Matches &amp;lt;code&amp;gt;&amp;lt;vespaversion&amp;gt;&amp;lt;/code&amp;gt; tags that contain Maven property expressions like &amp;lt;code&amp;gt;${project.version}&amp;lt;/code&amp;gt; and replaces them with the literal version string.&lt;br /&gt;
# &#039;&#039;&#039;Test framework version replacement&#039;&#039;&#039;: Same as above, but for the &amp;lt;code&amp;gt;&amp;lt;test-framework.version&amp;gt;&amp;lt;/code&amp;gt; tag used by Vespa&#039;s test modules.&lt;br /&gt;
&lt;br /&gt;
All three patterns use commas as the sed delimiter (&amp;lt;code&amp;gt;s,pattern,replacement,&amp;lt;/code&amp;gt;) to avoid conflicts with forward slashes in XML tag syntax.&lt;br /&gt;
&lt;br /&gt;
=== Platform Detection ===&lt;br /&gt;
&lt;br /&gt;
The script detects macOS vs. Linux to handle the &amp;lt;code&amp;gt;sed -i&amp;lt;/code&amp;gt; syntax difference:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [[ &amp;quot;$(uname)&amp;quot; == &amp;quot;Darwin&amp;quot; ]]; then&lt;br /&gt;
    SED_INPLACE=(sed -i &#039;&#039;)   # macOS BSD sed requires empty string argument&lt;br /&gt;
else&lt;br /&gt;
    SED_INPLACE=(sed -i)      # GNU sed on Linux&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This allows the script to be used both in CI (Linux) and during local development on macOS.&lt;br /&gt;
&lt;br /&gt;
=== Symbolic Link Following ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;find -L&amp;lt;/code&amp;gt; flag follows symbolic links during directory traversal. This is important because the Vespa source tree may contain symlinked modules or directories.&lt;br /&gt;
&lt;br /&gt;
=== Error Handling ===&lt;br /&gt;
&lt;br /&gt;
Both scripts use strict Bash error handling:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;set -o errexit&amp;lt;/code&amp;gt;: Exit immediately if any command fails.&lt;br /&gt;
* &amp;lt;code&amp;gt;set -o nounset&amp;lt;/code&amp;gt;: Treat unset variables as errors.&lt;br /&gt;
* &amp;lt;code&amp;gt;set -o pipefail&amp;lt;/code&amp;gt;: Return the exit code of the first failed command in a pipeline.&lt;br /&gt;
&lt;br /&gt;
The POM replacement script also validates its arguments, checking that exactly two arguments are provided and that the directory exists.&lt;br /&gt;
&lt;br /&gt;
== Execution Context ==&lt;br /&gt;
&lt;br /&gt;
These scripts are invoked by the Buildkite pipeline as the first step of the build process. The typical invocation chain is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Buildkite Pipeline&lt;br /&gt;
  --&amp;gt; .buildkite/prepare.sh&lt;br /&gt;
        --&amp;gt; .buildkite/replace-vespa-version-in-poms.sh $VESPA_VERSION $SOURCE_DIR&lt;br /&gt;
        --&amp;gt; mkdir -p $WORKDIR/artifacts/$ARCH/rpms&lt;br /&gt;
        --&amp;gt; mkdir -p $WORKDIR/artifacts/$ARCH/maven-repo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Source File Locations ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/vespa-engine/vespa/blob/master/.buildkite/prepare.sh &amp;lt;code&amp;gt;.buildkite/prepare.sh&amp;lt;/code&amp;gt;] (Lines 1-21)&lt;br /&gt;
* [https://github.com/vespa-engine/vespa/blob/master/.buildkite/replace-vespa-version-in-poms.sh &amp;lt;code&amp;gt;.buildkite/replace-vespa-version-in-poms.sh&amp;lt;/code&amp;gt;] (Lines 1-46)&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Principle:Vespa_engine_Vespa_Version_Preparation|Version Preparation Principle]] -- The design rationale behind version preparation in CI/CD pipelines.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Bootstrap_And_Java_Sh|Bootstrap and Java Build Implementation]] -- The next pipeline stage that consumes the version-prepared POM files.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Vespa_engine_Vespa_Version_Preparation]]&lt;br /&gt;
* [[requires_env::Environment:Vespa_engine_Vespa_Java_17_Build_Runtime]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_LogSetup_InitVespaLogging&amp;diff=30776</id>
		<title>Implementation:Vespa engine Vespa LogSetup InitVespaLogging</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_LogSetup_InitVespaLogging&amp;diff=30776"/>
		<updated>2026-09-27T10:53:14Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_LogSetup_InitVespaLogging}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_LogSetup_InitVespaLogging}}&lt;br /&gt;
== LogSetup.initVespaLogging ==&lt;br /&gt;
&lt;br /&gt;
[[domain::Logging]] [[domain::Observability]]&lt;br /&gt;
&lt;br /&gt;
=== API Signature ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void initVespaLogging(String programName)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;File&#039;&#039;&#039;: [https://github.com/vespa-engine/vespa/blob/master/vespalog/src/main/java/com/yahoo/log/LogSetup.java vespalog/src/main/java/com/yahoo/log/LogSetup.java]&lt;br /&gt;
* &#039;&#039;&#039;Lines&#039;&#039;&#039;: L81-129&lt;br /&gt;
* &#039;&#039;&#039;Class&#039;&#039;&#039;: &amp;lt;code&amp;gt;public class LogSetup&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Package&#039;&#039;&#039;: &amp;lt;code&amp;gt;com.yahoo.log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;initVespaLogging&amp;lt;/code&amp;gt; is the &#039;&#039;&#039;primary entry point&#039;&#039;&#039; for initializing Vespa&#039;s logging framework in Java processes. It resolves log configuration from system properties and environment variables, sets up the log target, creates the level controller, and installs the custom &amp;lt;code&amp;gt;VespaLogHandler&amp;lt;/code&amp;gt; on the root JUL logger.&lt;br /&gt;
&lt;br /&gt;
This method must be called &#039;&#039;&#039;exactly once&#039;&#039;&#039; at process startup before any logging occurs. It is a static method that sets global state.&lt;br /&gt;
&lt;br /&gt;
=== Key Fields ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Field !! Type !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;taskRunner&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;Timer&amp;lt;/code&amp;gt; || Schedules periodic tasks (e.g., control file re-check)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logHandler&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;VespaLogHandler&amp;lt;/code&amp;gt; || The installed JUL handler for Vespa-format logging&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;zooKeeperFilter&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;ZooKeeperFilter&amp;lt;/code&amp;gt; || Filters ZooKeeper client log messages to a separate target&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;isInitialized&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;boolean&amp;lt;/code&amp;gt; || Guard flag preventing double initialization&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;programName&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; || The name of the program (e.g., &amp;lt;code&amp;gt;&amp;quot;configserver&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;container&amp;quot;&amp;lt;/code&amp;gt;). Must be non-null and non-empty.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Return Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;void&amp;lt;/code&amp;gt; -- This method has no return value. It modifies global logging state as a side effect.&lt;br /&gt;
&lt;br /&gt;
=== Exceptions ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Exception !! Condition&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RuntimeException&amp;lt;/code&amp;gt; || If &amp;lt;code&amp;gt;programName&amp;lt;/code&amp;gt; is null or empty&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;RuntimeException&amp;lt;/code&amp;gt; || If the log target file cannot be opened (wraps &amp;lt;code&amp;gt;FileNotFoundException&amp;lt;/code&amp;gt;)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Full Method Source ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public static void initVespaLogging(String programName) {&lt;br /&gt;
    if (isInitialized) {&lt;br /&gt;
        System.err.println(&amp;quot;WARNING: initVespaLogging called twice&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    isInitialized = true;&lt;br /&gt;
&lt;br /&gt;
    String logLevel = System.getProperty(&amp;quot;vespa.log.level&amp;quot;);&lt;br /&gt;
    String logTarget = System.getProperty(&amp;quot;vespa.log.target&amp;quot;);&lt;br /&gt;
    String logService = System.getProperty(&amp;quot;vespa.service.name&amp;quot;);&lt;br /&gt;
    String logControlDir = System.getProperty(&amp;quot;vespa.log.control.dir&amp;quot;);&lt;br /&gt;
    String logControlFile = System.getProperty(&amp;quot;vespa.log.control.file&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    if (programName == null || programName.equals(&amp;quot;&amp;quot;)) {&lt;br /&gt;
        throw new RuntimeException(&amp;quot;invalid programName: &amp;quot; + programName);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (logTarget == null) logTarget = System.getenv(&amp;quot;VESPA_LOG_TARGET&amp;quot;);&lt;br /&gt;
    if (logService == null) logService = System.getenv(&amp;quot;VESPA_SERVICE_NAME&amp;quot;);&lt;br /&gt;
    if (logControlDir == null) logControlDir = System.getenv(&amp;quot;VESPA_LOG_CONTROL_DIR&amp;quot;);&lt;br /&gt;
    if (logControlFile == null) logControlFile = System.getenv(&amp;quot;VESPA_LOG_CONTROL_FILE&amp;quot;);&lt;br /&gt;
    if (logLevel == null) logLevel = System.getenv(&amp;quot;VESPA_LOG_LEVEL&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    if (logTarget == null) logTarget = &amp;quot;fd:2&amp;quot;;&lt;br /&gt;
    if (logLevel == null) logLevel = &amp;quot;all -debug -spam&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    if (logControlFile == null &amp;amp;&amp;amp; logControlDir != null &amp;amp;&amp;amp; logService != null&lt;br /&gt;
        &amp;amp;&amp;amp; !logService.equals(&amp;quot;&amp;quot;) &amp;amp;&amp;amp; !logService.equals(&amp;quot;-&amp;quot;)) {&lt;br /&gt;
        logControlFile = logControlDir + &amp;quot;/&amp;quot; + logService + &amp;quot;.logcontrol&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (logService == null) logService = System.getProperty(&amp;quot;config.id&amp;quot;);&lt;br /&gt;
    if (logService == null) logService = &amp;quot;-&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    System.setProperty(&amp;quot;vespa.service.name&amp;quot;, logService);&lt;br /&gt;
    System.setProperty(&amp;quot;vespa.program.name&amp;quot;, programName);&lt;br /&gt;
&lt;br /&gt;
    try {&lt;br /&gt;
        initInternal(logTarget, logService, logControlFile, programName, logLevel);&lt;br /&gt;
    } catch (FileNotFoundException e) {&lt;br /&gt;
        throw new RuntimeException(&amp;quot;Unable to initialize logging&amp;quot;, e);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Configuration Resolution Logic ===&lt;br /&gt;
&lt;br /&gt;
The method resolves each configuration value through a &#039;&#039;&#039;three-tier precedence chain&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
==== Step 1: Read System Properties ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
String logLevel = System.getProperty(&amp;quot;vespa.log.level&amp;quot;);&lt;br /&gt;
String logTarget = System.getProperty(&amp;quot;vespa.log.target&amp;quot;);&lt;br /&gt;
String logService = System.getProperty(&amp;quot;vespa.service.name&amp;quot;);&lt;br /&gt;
String logControlDir = System.getProperty(&amp;quot;vespa.log.control.dir&amp;quot;);&lt;br /&gt;
String logControlFile = System.getProperty(&amp;quot;vespa.log.control.file&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
System properties have the highest precedence. They are typically set via JVM flags like &amp;lt;code&amp;gt;-Dvespa.log.target=file:/var/log/vespa.log&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Step 2: Fall Back to Environment Variables ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
if (logTarget == null) logTarget = System.getenv(&amp;quot;VESPA_LOG_TARGET&amp;quot;);&lt;br /&gt;
if (logService == null) logService = System.getenv(&amp;quot;VESPA_SERVICE_NAME&amp;quot;);&lt;br /&gt;
if (logControlDir == null) logControlDir = System.getenv(&amp;quot;VESPA_LOG_CONTROL_DIR&amp;quot;);&lt;br /&gt;
if (logControlFile == null) logControlFile = System.getenv(&amp;quot;VESPA_LOG_CONTROL_FILE&amp;quot;);&lt;br /&gt;
if (logLevel == null) logLevel = System.getenv(&amp;quot;VESPA_LOG_LEVEL&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a system property was not set, the corresponding environment variable is checked. These are typically set by the Vespa process launcher (&amp;lt;code&amp;gt;vespa-start-services&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Step 3: Apply Defaults ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
if (logTarget == null) logTarget = &amp;quot;fd:2&amp;quot;;&lt;br /&gt;
if (logLevel == null) logLevel = &amp;quot;all -debug -spam&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If neither system property nor environment variable is set, hardcoded defaults are used:&lt;br /&gt;
* Log target defaults to &#039;&#039;&#039;stderr&#039;&#039;&#039; (&amp;lt;code&amp;gt;fd:2&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Log level defaults to &#039;&#039;&#039;all except debug and spam&#039;&#039;&#039; (&amp;lt;code&amp;gt;all -debug -spam&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
==== Step 4: Derive Control File Path ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
if (logControlFile == null &amp;amp;&amp;amp; logControlDir != null &amp;amp;&amp;amp; logService != null&lt;br /&gt;
    &amp;amp;&amp;amp; !logService.equals(&amp;quot;&amp;quot;) &amp;amp;&amp;amp; !logService.equals(&amp;quot;-&amp;quot;)) {&lt;br /&gt;
    logControlFile = logControlDir + &amp;quot;/&amp;quot; + logService + &amp;quot;.logcontrol&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If no explicit control file was specified but both a control directory and a valid service name exist, the control file path is derived as &amp;lt;code&amp;gt;&amp;amp;lt;dir&amp;amp;gt;/&amp;amp;lt;service&amp;amp;gt;.logcontrol&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Step 5: Final Service Name Fallback ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
if (logService == null) logService = System.getProperty(&amp;quot;config.id&amp;quot;);&lt;br /&gt;
if (logService == null) logService = &amp;quot;-&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The service name has an additional fallback to &amp;lt;code&amp;gt;config.id&amp;lt;/code&amp;gt; (the Vespa config identity), and then to the literal &amp;lt;code&amp;gt;&amp;quot;-&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Environment Variables ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! System Property !! Default !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_LOG_TARGET&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;vespa.log.target&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;fd:2&amp;lt;/code&amp;gt; || Log output destination&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_LOG_LEVEL&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;vespa.log.level&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;all -debug -spam&amp;lt;/code&amp;gt; || Default log levels&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_SERVICE_NAME&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;vespa.service.name&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt; || Service identity&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_LOG_CONTROL_DIR&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;vespa.log.control.dir&amp;lt;/code&amp;gt; || &#039;&#039;(none)&#039;&#039; || Control file directory&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_LOG_CONTROL_FILE&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;vespa.log.control.file&amp;lt;/code&amp;gt; || &#039;&#039;(derived)&#039;&#039; || Explicit control file path&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Usage Example ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public class MyVespaService {&lt;br /&gt;
    public static void main(String[] args) {&lt;br /&gt;
        // Must be called before any logging&lt;br /&gt;
        LogSetup.initVespaLogging(&amp;quot;my-vespa-service&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // Now logging works with Vespa format&lt;br /&gt;
        Logger logger = Logger.getLogger(MyVespaService.class.getName());&lt;br /&gt;
        logger.info(&amp;quot;Service started successfully&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Behavior Notes ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Double initialization warning&#039;&#039;&#039;: If called twice, a warning is printed to stderr but initialization proceeds. The &amp;lt;code&amp;gt;isInitialized&amp;lt;/code&amp;gt; flag is set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; immediately, not after successful completion.&lt;br /&gt;
* &#039;&#039;&#039;System property side effects&#039;&#039;&#039;: The method sets &amp;lt;code&amp;gt;vespa.service.name&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;vespa.program.name&amp;lt;/code&amp;gt; as system properties, making them available to downstream components like the &amp;lt;code&amp;gt;VespaFormatter&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;&#039;Delegation to initInternal&#039;&#039;&#039;: The actual handler installation, level controller creation, and JUL configuration happen inside &amp;lt;code&amp;gt;initInternal()&amp;lt;/code&amp;gt;, which is called at the end.&lt;br /&gt;
&lt;br /&gt;
=== Implements Principle ===&lt;br /&gt;
&lt;br /&gt;
[[Principle:Vespa_engine_Vespa_Log_Target_and_Level_Configuration|Log Target and Level Configuration]]&lt;br /&gt;
&lt;br /&gt;
=== Related Implementations ===&lt;br /&gt;
&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_VespaLevelControllerRepo_Constructor|VespaLevelControllerRepo Constructor]] -- Creates the level controller using the resolved control file path&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_VespaLogHandler_Constructor|VespaLogHandler Constructor]] -- Installs the handler using the resolved log target and level controller&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Vespa_engine_Vespa_Log_Target_and_Level_Configuration]]&lt;br /&gt;
* [[requires_env::Environment:Vespa_engine_Vespa_Java_17_Build_Runtime]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Cpp_Sh&amp;diff=30775</id>
		<title>Implementation:Vespa engine Vespa Cpp Sh</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Cpp_Sh&amp;diff=30775"/>
		<updated>2026-09-27T10:53:13Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Cpp_Sh}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Cpp_Sh}}&lt;br /&gt;
{{DISPLAYTITLE:C++ Compilation Implementation}}&lt;br /&gt;
[[domain::CI_CD]] [[domain::Build_Systems]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This page documents the implementation of the Vespa C++ compilation script: &#039;&#039;.buildkite/cpp.sh&#039;&#039;. This script activates the GCC toolset, sets up the dependency PATH, and runs &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; with parallel threads to compile all C++ components of Vespa.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Type:&#039;&#039;&#039; External Tool Doc&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env bash&lt;br /&gt;
# .buildkite/cpp.sh (L1-29)&lt;br /&gt;
&lt;br /&gt;
set -o errexit&lt;br /&gt;
set -o nounset&lt;br /&gt;
set -o pipefail&lt;br /&gt;
&lt;br /&gt;
if [[ -n &amp;quot;${DEBUG:-}&amp;quot; ]]; then&lt;br /&gt;
    set -o xtrace&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
mydir=${0%/*}&lt;br /&gt;
shlim=${mydir}/show-limits.sh&lt;br /&gt;
if [ -x &amp;quot;${shlim}&amp;quot; ]; then&lt;br /&gt;
    &amp;quot;${shlim}&amp;quot; || echo &amp;quot;failed: ${shlim}&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;--- Building C++ components&amp;quot;&lt;br /&gt;
# shellcheck disable=1091&lt;br /&gt;
source /etc/profile.d/enable-gcc-toolset.sh&lt;br /&gt;
&lt;br /&gt;
PATH=/opt/vespa-deps/bin:$PATH&lt;br /&gt;
&lt;br /&gt;
cd &amp;quot;$SOURCE_DIR&amp;quot;&lt;br /&gt;
echo &amp;quot;Running make with $NUM_CPP_THREADS threads...&amp;quot;&lt;br /&gt;
make -j &amp;quot;$NUM_CPP_THREADS&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs (Environment Variables) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Required !! Description !! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NUM_CPP_THREADS&amp;lt;/code&amp;gt; || Yes || Number of parallel compilation threads for &amp;lt;code&amp;gt;make -j&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;16&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SOURCE_DIR&amp;lt;/code&amp;gt; || Yes || Root directory of the Vespa source checkout || &amp;lt;code&amp;gt;/vespa&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt; || No || If set to a non-empty value, enables bash xtrace for debugging || &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Inputs (System Dependencies) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Dependency !! Path !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| GCC Toolset || &amp;lt;code&amp;gt;/etc/profile.d/enable-gcc-toolset.sh&amp;lt;/code&amp;gt; || Activates GCC 12+ with C++20 support&lt;br /&gt;
|-&lt;br /&gt;
| Vespa Dependencies || &amp;lt;code&amp;gt;/opt/vespa-deps/bin&amp;lt;/code&amp;gt; || Pre-built third-party libraries (protobuf, abseil, gRPC, etc.)&lt;br /&gt;
|-&lt;br /&gt;
| Generated Makefiles || Current working directory || Output from the CMake configuration stage&lt;br /&gt;
|-&lt;br /&gt;
| show-limits.sh || &amp;lt;code&amp;gt;.buildkite/show-limits.sh&amp;lt;/code&amp;gt; || Optional resource limit reporter&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Inputs (Prerequisite Build Artifacts) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Artifact !! Produced By !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| Makefiles and CMakeCache.txt || CMake configuration stage || Build rules for all C++ targets&lt;br /&gt;
|-&lt;br /&gt;
| Java JAR files || Java bootstrap stage || JNI headers and test dependencies&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs (Compiled Artifacts) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;*.so&amp;lt;/code&amp;gt; files || Shared libraries || Vespa&#039;s native libraries (search core, document storage, etc.)&lt;br /&gt;
|-&lt;br /&gt;
| Executable binaries || Executables || Server processes and CLI utilities&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;*.a&amp;lt;/code&amp;gt; files || Static libraries || Libraries statically linked into other targets&lt;br /&gt;
|-&lt;br /&gt;
| Test binaries || Executables || Unit test programs for subsequent test stages&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Key Implementation Details ==&lt;br /&gt;
&lt;br /&gt;
=== Resource Limit Reporting ===&lt;br /&gt;
&lt;br /&gt;
Before starting compilation, the script optionally runs &amp;lt;code&amp;gt;show-limits.sh&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mydir=${0%/*}&lt;br /&gt;
shlim=${mydir}/show-limits.sh&lt;br /&gt;
if [ -x &amp;quot;${shlim}&amp;quot; ]; then&lt;br /&gt;
    &amp;quot;${shlim}&amp;quot; || echo &amp;quot;failed: ${shlim}&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;${0%/*}&amp;lt;/code&amp;gt; pattern extracts the directory containing the script itself. If &amp;lt;code&amp;gt;show-limits.sh&amp;lt;/code&amp;gt; exists and is executable, it runs and logs system resource limits (ulimits, memory, file descriptors). If it fails, the error is logged but the build continues -- this is purely diagnostic.&lt;br /&gt;
&lt;br /&gt;
=== GCC Toolset Activation ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
source /etc/profile.d/enable-gcc-toolset.sh&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This script is provided by the build container and activates a modern GCC version (12+) that supports C++20. Without this, the system default compiler (often GCC 8 on CentOS/AlmaLinux 8) would be used, which lacks full C++20 support.&lt;br /&gt;
&lt;br /&gt;
=== Dependency PATH Setup ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
PATH=/opt/vespa-deps/bin:$PATH&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pre-built Vespa dependencies are installed under &amp;lt;code&amp;gt;/opt/vespa-deps/&amp;lt;/code&amp;gt;. Adding this to the PATH ensures that tools like &amp;lt;code&amp;gt;protoc&amp;lt;/code&amp;gt; (Protocol Buffer compiler) and other code generators are found during compilation.&lt;br /&gt;
&lt;br /&gt;
=== Parallel Make Invocation ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cd &amp;quot;$SOURCE_DIR&amp;quot;&lt;br /&gt;
make -j &amp;quot;$NUM_CPP_THREADS&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script changes to &amp;lt;code&amp;gt;$SOURCE_DIR&amp;lt;/code&amp;gt; and runs &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; with the &amp;lt;code&amp;gt;-j&amp;lt;/code&amp;gt; flag for parallel execution. Key aspects:&lt;br /&gt;
&lt;br /&gt;
* The Makefiles in the build directory were generated by the preceding CMake configuration stage.&lt;br /&gt;
* &amp;lt;code&amp;gt;make -j &amp;quot;$NUM_CPP_THREADS&amp;quot;&amp;lt;/code&amp;gt; launches up to &amp;lt;code&amp;gt;$NUM_CPP_THREADS&amp;lt;/code&amp;gt; concurrent compilation jobs.&lt;br /&gt;
* Make&#039;s dependency tracking ensures that targets are built in the correct order -- a shared library is not linked until all its object files are compiled.&lt;br /&gt;
* The &amp;lt;code&amp;gt;set -o errexit&amp;lt;/code&amp;gt; flag causes the script to terminate immediately if &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; returns a non-zero exit code (indicating a compilation or linking error).&lt;br /&gt;
&lt;br /&gt;
=== Working Directory ===&lt;br /&gt;
&lt;br /&gt;
The script changes to &amp;lt;code&amp;gt;$SOURCE_DIR&amp;lt;/code&amp;gt; before running make. This is the directory where CMake was configured (the build directory), which contains the generated Makefiles. The build directory may be the same as the source directory (in-source build) or a separate directory (out-of-source build), depending on pipeline configuration.&lt;br /&gt;
&lt;br /&gt;
== Execution Context ==&lt;br /&gt;
&lt;br /&gt;
The compilation script is invoked after CMake configuration completes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Buildkite Pipeline&lt;br /&gt;
  --&amp;gt; .buildkite/bootstrap.sh (Java bootstrap)&lt;br /&gt;
  --&amp;gt; .buildkite/bootstrap-cmake.sh (CMake configuration)&lt;br /&gt;
  --&amp;gt; .buildkite/cpp.sh&lt;br /&gt;
        --&amp;gt; source enable-gcc-toolset.sh&lt;br /&gt;
        --&amp;gt; PATH=/opt/vespa-deps/bin:$PATH&lt;br /&gt;
        --&amp;gt; cd $SOURCE_DIR&lt;br /&gt;
        --&amp;gt; make -j $NUM_CPP_THREADS&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The compilation step is typically the longest stage in the pipeline, taking 20-60 minutes depending on the number of available CPU cores.&lt;br /&gt;
&lt;br /&gt;
== Source File Locations ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/vespa-engine/vespa/blob/master/.buildkite/cpp.sh &amp;lt;code&amp;gt;.buildkite/cpp.sh&amp;lt;/code&amp;gt;] (Lines 1-29)&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Principle:Vespa_engine_Vespa_CPP_Compilation|C++ Compilation Principle]] -- The design rationale for parallel C++ compilation.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Bootstrap_Cmake_Sh|CMake Configuration Implementation]] -- The preceding stage that generates Makefiles.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Build_Rpms_Sh|RPM Package Creation Implementation]] -- The next stage that packages compiled binaries.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Vespa_engine_Vespa_CPP_Compilation]]&lt;br /&gt;
* [[requires_env::Environment:Vespa_engine_Vespa_CMake_Cpp23_Build_Environment]]&lt;br /&gt;
* [[uses_heuristic::Heuristic:Vespa_engine_Vespa_Maven_Parallel_Build_Optimization]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Build_Rpms_Sh&amp;diff=30774</id>
		<title>Implementation:Vespa engine Vespa Build Rpms Sh</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Build_Rpms_Sh&amp;diff=30774"/>
		<updated>2026-09-27T10:53:13Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Build_Rpms_Sh}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Build_Rpms_Sh}}&lt;br /&gt;
{{DISPLAYTITLE:RPM Build Implementation}}&lt;br /&gt;
[[domain::CI_CD]] [[domain::Build_Systems]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This page documents the implementation of the Vespa RPM package creation script: &#039;&#039;.buildkite/build-rpms.sh&#039;&#039;. This script generates a source RPM, rebuilds it into binary RPMs with zstd compression, and creates a YUM repository from the results.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Type:&#039;&#039;&#039; External Tool Doc&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env bash&lt;br /&gt;
# .buildkite/build-rpms.sh (L1-30)&lt;br /&gt;
&lt;br /&gt;
set -o errexit&lt;br /&gt;
set -o nounset&lt;br /&gt;
set -o pipefail&lt;br /&gt;
&lt;br /&gt;
if [[ -n &amp;quot;${DEBUG:-}&amp;quot; ]]; then&lt;br /&gt;
    set -o xtrace&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;--- Building RPM packages&amp;quot;&lt;br /&gt;
ulimit -c 0&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Creating source RPM...&amp;quot;&lt;br /&gt;
make  -f .copr/Makefile srpm outdir=&amp;quot;$WORKDIR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Building binary RPMs...&amp;quot;&lt;br /&gt;
rpmbuild --rebuild \&lt;br /&gt;
  --define=&amp;quot;_topdir $WORKDIR/vespa-rpmbuild&amp;quot; \&lt;br /&gt;
  --define &amp;quot;_debugsource_template %{nil}&amp;quot; \&lt;br /&gt;
  --define &amp;quot;_binary_payload w10T4.zstdio&amp;quot; \&lt;br /&gt;
  --define &amp;quot;installdir $WORKDIR/vespa-install&amp;quot; &amp;quot;$WORKDIR&amp;quot;/vespa-&amp;quot;$VESPA_VERSION&amp;quot;-*.src.rpm&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Moving RPMs and creating repository...&amp;quot;&lt;br /&gt;
mv &amp;quot;$WORKDIR&amp;quot;/vespa-rpmbuild/RPMS/*/*.rpm &amp;quot;$WORKDIR/artifacts/$ARCH/rpms&amp;quot;&lt;br /&gt;
createrepo &amp;quot;$WORKDIR/artifacts/$ARCH/rpms&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs (Environment Variables) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Required !! Description !! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;WORKDIR&amp;lt;/code&amp;gt; || Yes || Working directory for all build artifacts || &amp;lt;code&amp;gt;/tmp/vespa-build&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_VERSION&amp;lt;/code&amp;gt; || Yes || Version string for the RPM package name || &amp;lt;code&amp;gt;8.432.17&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ARCH&amp;lt;/code&amp;gt; || Yes || CPU architecture identifier || &amp;lt;code&amp;gt;x86_64&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;aarch64&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt; || No || If set to a non-empty value, enables bash xtrace || &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Inputs (Prerequisite Files) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! File/Directory !! Produced By !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;.copr/Makefile&amp;lt;/code&amp;gt; || Source repository || Makefile with &amp;lt;code&amp;gt;srpm&amp;lt;/code&amp;gt; target for SRPM generation&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$WORKDIR/vespa-install/&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; (C++ build) || Pre-built binaries and libraries&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$WORKDIR/artifacts/$ARCH/rpms/&amp;lt;/code&amp;gt; || prepare.sh || Pre-created empty directory for RPM output&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs (Files) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$WORKDIR/vespa-$VESPA_VERSION-*.src.rpm&amp;lt;/code&amp;gt; || Source RPM || Contains spec file and source tarball&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$WORKDIR/artifacts/$ARCH/rpms/*.rpm&amp;lt;/code&amp;gt; || Binary RPMs || Installable RPM packages&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$WORKDIR/artifacts/$ARCH/rpms/repodata/&amp;lt;/code&amp;gt; || YUM metadata || Repository metadata for &amp;lt;code&amp;gt;yum&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;dnf&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Key Implementation Details ==&lt;br /&gt;
&lt;br /&gt;
=== Core Dump Suppression ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ulimit -c 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script sets the core dump size limit to zero at the outset. This prevents any process that crashes during the RPM build from writing a core dump file, which could consume gigabytes of disk space and potentially fill the build disk.&lt;br /&gt;
&lt;br /&gt;
=== Source RPM Generation ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
make -f .copr/Makefile srpm outdir=&amp;quot;$WORKDIR&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;.copr/Makefile&amp;lt;/code&amp;gt; follows the Copr build service convention. The &amp;lt;code&amp;gt;srpm&amp;lt;/code&amp;gt; target:&lt;br /&gt;
&lt;br /&gt;
# Generates a source tarball from the current source tree.&lt;br /&gt;
# Combines the tarball with the RPM spec file (&amp;lt;code&amp;gt;vespa.spec&amp;lt;/code&amp;gt;).&lt;br /&gt;
# Produces an SRPM file named &amp;lt;code&amp;gt;vespa-$VESPA_VERSION-*.src.rpm&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;$WORKDIR&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;outdir&amp;lt;/code&amp;gt; variable is passed to the Makefile to control where the SRPM is written.&lt;br /&gt;
&lt;br /&gt;
=== Binary RPM Rebuild ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
rpmbuild --rebuild \&lt;br /&gt;
  --define=&amp;quot;_topdir $WORKDIR/vespa-rpmbuild&amp;quot; \&lt;br /&gt;
  --define &amp;quot;_debugsource_template %{nil}&amp;quot; \&lt;br /&gt;
  --define &amp;quot;_binary_payload w10T4.zstdio&amp;quot; \&lt;br /&gt;
  --define &amp;quot;installdir $WORKDIR/vespa-install&amp;quot; \&lt;br /&gt;
  &amp;quot;$WORKDIR&amp;quot;/vespa-&amp;quot;$VESPA_VERSION&amp;quot;-*.src.rpm&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;rpmbuild --rebuild&amp;lt;/code&amp;gt; command processes the SRPM through the full RPM build lifecycle. The &amp;lt;code&amp;gt;--define&amp;lt;/code&amp;gt; flags override default RPM macros:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;_topdir&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Redirects the RPM build tree (BUILD, RPMS, SRPMS, SOURCES, SPECS directories) to an isolated working directory. This avoids conflicts with any system-level RPM build configuration.&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;_debugsource_template %{nil}&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Sets the debug source template to nil, suppressing the creation of debugsource RPMs. This reduces build time and disk usage.&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;_binary_payload w10T4.zstdio&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Configures the RPM payload compression:&lt;br /&gt;
** &amp;lt;code&amp;gt;w&amp;lt;/code&amp;gt;: Write mode&lt;br /&gt;
** &amp;lt;code&amp;gt;10&amp;lt;/code&amp;gt;: Compression level 10 (high compression)&lt;br /&gt;
** &amp;lt;code&amp;gt;T4&amp;lt;/code&amp;gt;: Use 4 threads for compression&lt;br /&gt;
** &amp;lt;code&amp;gt;zstdio&amp;lt;/code&amp;gt;: Use the Zstandard algorithm&lt;br /&gt;
* &#039;&#039;&#039;&amp;lt;code&amp;gt;installdir&amp;lt;/code&amp;gt;&#039;&#039;&#039;: Points to the directory where &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; placed the compiled binaries. The spec file uses this to avoid recompilation during the &amp;lt;code&amp;gt;%install&amp;lt;/code&amp;gt; phase.&lt;br /&gt;
&lt;br /&gt;
The glob pattern &amp;lt;code&amp;gt;vespa-&amp;quot;$VESPA_VERSION&amp;quot;-*.src.rpm&amp;lt;/code&amp;gt; matches the SRPM file regardless of the release suffix.&lt;br /&gt;
&lt;br /&gt;
=== RPM Collection and Repository Creation ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mv &amp;quot;$WORKDIR&amp;quot;/vespa-rpmbuild/RPMS/*/*.rpm &amp;quot;$WORKDIR/artifacts/$ARCH/rpms&amp;quot;&lt;br /&gt;
createrepo &amp;quot;$WORKDIR/artifacts/$ARCH/rpms&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After &amp;lt;code&amp;gt;rpmbuild&amp;lt;/code&amp;gt; completes, the binary RPMs are scattered across architecture-specific subdirectories under &amp;lt;code&amp;gt;RPMS/&amp;lt;/code&amp;gt; (e.g., &amp;lt;code&amp;gt;RPMS/x86_64/&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RPMS/noarch/&amp;lt;/code&amp;gt;). The &amp;lt;code&amp;gt;mv&amp;lt;/code&amp;gt; command with the glob &amp;lt;code&amp;gt;*/*.rpm&amp;lt;/code&amp;gt; collects all RPMs into the flat artifact directory.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;createrepo&amp;lt;/code&amp;gt; command then generates YUM repository metadata, creating a &amp;lt;code&amp;gt;repodata/&amp;lt;/code&amp;gt; directory containing:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;repomd.xml&amp;lt;/code&amp;gt;: Repository metadata index&lt;br /&gt;
* &amp;lt;code&amp;gt;primary.xml.gz&amp;lt;/code&amp;gt;: Package names, versions, and dependencies&lt;br /&gt;
* &amp;lt;code&amp;gt;filelists.xml.gz&amp;lt;/code&amp;gt;: File lists for each package&lt;br /&gt;
* &amp;lt;code&amp;gt;other.xml.gz&amp;lt;/code&amp;gt;: Changelog and supplementary data&lt;br /&gt;
&lt;br /&gt;
This enables downstream consumers (the container image build and artifact publishing) to use the directory as a YUM repository.&lt;br /&gt;
&lt;br /&gt;
== Execution Context ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Buildkite Pipeline&lt;br /&gt;
  --&amp;gt; .buildkite/prepare.sh (creates artifact directories)&lt;br /&gt;
  --&amp;gt; .buildkite/bootstrap.sh + java.sh (Java build)&lt;br /&gt;
  --&amp;gt; .buildkite/bootstrap-cmake.sh + cpp.sh (C++ build + make install)&lt;br /&gt;
  --&amp;gt; .buildkite/build-rpms.sh&lt;br /&gt;
        --&amp;gt; ulimit -c 0&lt;br /&gt;
        --&amp;gt; make -f .copr/Makefile srpm&lt;br /&gt;
        --&amp;gt; rpmbuild --rebuild ...&lt;br /&gt;
        --&amp;gt; mv RPMs to artifact directory&lt;br /&gt;
        --&amp;gt; createrepo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Source File Locations ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/vespa-engine/vespa/blob/master/.buildkite/build-rpms.sh &amp;lt;code&amp;gt;.buildkite/build-rpms.sh&amp;lt;/code&amp;gt;] (Lines 1-30)&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Principle:Vespa_engine_Vespa_RPM_Package_Creation|RPM Package Creation Principle]] -- The design rationale for RPM packaging in the Vespa build.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Cpp_Sh|C++ Compilation Implementation]] -- The preceding stage that produces compiled binaries.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Build_Container_Sh|Container Image Building Implementation]] -- The next stage that consumes RPMs.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Publish_Artifacts_Sh|Artifact Publishing Implementation]] -- The stage that signs and uploads RPMs.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Vespa_engine_Vespa_RPM_Package_Creation]]&lt;br /&gt;
* [[requires_env::Environment:Vespa_engine_Vespa_CMake_Cpp23_Build_Environment]]&lt;br /&gt;
* [[uses_heuristic::Heuristic:Vespa_engine_Vespa_Maven_Parallel_Build_Optimization]]&lt;br /&gt;
* [[uses_heuristic::Heuristic:Vespa_engine_Vespa_RPM_Zstd_Compression_Settings]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Build_Container_Sh&amp;diff=30773</id>
		<title>Implementation:Vespa engine Vespa Build Container Sh</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Build_Container_Sh&amp;diff=30773"/>
		<updated>2026-09-27T10:53:12Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Build_Container_Sh}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Build_Container_Sh}}&lt;br /&gt;
{{DISPLAYTITLE:Container Build Implementation}}&lt;br /&gt;
[[domain::CI_CD]] [[domain::Build_Systems]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This page documents the implementation of the Vespa container image building script: &#039;&#039;.buildkite/build-container.sh&#039;&#039;. This script builds two Docker images -- a Vespa preview image and a system-test image -- for the target architecture and OS combination.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Type:&#039;&#039;&#039; External Tool Doc&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env bash&lt;br /&gt;
# .buildkite/build-container.sh (L1-91)&lt;br /&gt;
&lt;br /&gt;
set -o errexit&lt;br /&gt;
set -o nounset&lt;br /&gt;
set -o pipefail&lt;br /&gt;
&lt;br /&gt;
if [[ -n &amp;quot;${DEBUG:-}&amp;quot; ]]; then&lt;br /&gt;
    set -o xtrace&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if ! docker ps &amp;amp;&amp;gt; /dev/null; then&lt;br /&gt;
    echo &amp;quot;No working docker command found.&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
case &amp;quot;${VESPA_BUILDOS_LABEL}&amp;quot; in&lt;br /&gt;
    alma8)&lt;br /&gt;
        VESPA_BASE_IMAGE=&amp;quot;el8&amp;quot;&lt;br /&gt;
        SYSTEM_TEST_BASE_IMAGE=&amp;quot;almalinux:8&amp;quot;&lt;br /&gt;
        ;;&lt;br /&gt;
    alma9)&lt;br /&gt;
        VESPA_BASE_IMAGE=&amp;quot;el9&amp;quot;&lt;br /&gt;
        SYSTEM_TEST_BASE_IMAGE=&amp;quot;almalinux:9&amp;quot;&lt;br /&gt;
        ;;&lt;br /&gt;
    *)&lt;br /&gt;
        echo &amp;quot;Unknown build os: ${VESPA_BUILDOS_LABEL}&amp;quot; 1&amp;gt;&amp;amp;2&lt;br /&gt;
        exit 1&lt;br /&gt;
        ;;&lt;br /&gt;
esac&lt;br /&gt;
&lt;br /&gt;
# --- Clone docker-image repository ---&lt;br /&gt;
if [[ ! -d &amp;quot;${WORKDIR}/docker-image&amp;quot; ]]; then&lt;br /&gt;
    git clone --quiet --depth 1 https://github.com/vespa-engine/docker-image &amp;quot;$WORKDIR/docker-image&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# --- Prepare RPMs for container build ---&lt;br /&gt;
rm -rf &amp;quot;${WORKDIR}/docker-image/rpms&amp;quot;&lt;br /&gt;
cp -a &amp;quot;${WORKDIR}/artifacts/$ARCH/rpms&amp;quot; &amp;quot;${WORKDIR}/docker-image/&amp;quot;&lt;br /&gt;
&lt;br /&gt;
cd &amp;quot;${WORKDIR}/docker-image&amp;quot;&lt;br /&gt;
SOURCE_GITREF=$(git rev-parse HEAD)&lt;br /&gt;
&lt;br /&gt;
# --- Build Vespa preview container ---&lt;br /&gt;
GHCR_PREVIEW_TAG=ghcr.io/vespa-engine/vespa-preview-${ARCH}:${VESPA_VERSION}${VESPA_CONTAINER_IMAGE_VERSION_TAG_SUFFIX}&lt;br /&gt;
docker build --progress plain \&lt;br /&gt;
             --build-arg SOURCE_GITREF=&amp;quot;$SOURCE_GITREF&amp;quot; \&lt;br /&gt;
             --build-arg VESPA_VERSION=&amp;quot;$VESPA_VERSION&amp;quot; \&lt;br /&gt;
             --build-arg VESPA_BASE_IMAGE=&amp;quot;$VESPA_BASE_IMAGE&amp;quot; \&lt;br /&gt;
             --tag vespaengine/vespa \&lt;br /&gt;
             --tag &amp;quot;${GHCR_PREVIEW_TAG}&amp;quot; \&lt;br /&gt;
             --file Dockerfile .&lt;br /&gt;
&lt;br /&gt;
# --- Clone system-test repository ---&lt;br /&gt;
declare -r GITREF=&amp;quot;${GITREF_SYSTEM_TEST:-HEAD}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
cd &amp;quot;$WORKDIR&amp;quot;&lt;br /&gt;
if [[ ! -d $WORKDIR/system-test ]]; then&lt;br /&gt;
    git clone --quiet --filter=&amp;quot;blob:none&amp;quot; https://github.com/vespa-engine/system-test&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
cd system-test&lt;br /&gt;
git checkout &amp;quot;$GITREF&amp;quot;&lt;br /&gt;
mkdir -p docker/vespa-systemtests&lt;br /&gt;
git archive HEAD --format tar | tar x -C docker/vespa-systemtests&lt;br /&gt;
cd docker&lt;br /&gt;
rm -rf maven-repo&lt;br /&gt;
cp -a &amp;quot;$HOME/.m2/repository&amp;quot; maven-repo&lt;br /&gt;
rm -rf rpms&lt;br /&gt;
mv &amp;quot;$WORKDIR/docker-image/rpms&amp;quot; rpms&lt;br /&gt;
&lt;br /&gt;
# --- Build system-test container ---&lt;br /&gt;
DOCKER_SYSTEMTEST_TAG=docker.io/vespaengine/vespa-systemtest-preview-${ARCH}:${VESPA_VERSION}${VESPA_CONTAINER_IMAGE_VERSION_TAG_SUFFIX}&lt;br /&gt;
docker build --progress=plain \&lt;br /&gt;
             --build-arg BASE_IMAGE=&amp;quot;$SYSTEM_TEST_BASE_IMAGE&amp;quot; \&lt;br /&gt;
             --build-arg VESPA_BASE_IMAGE=&amp;quot;${GHCR_PREVIEW_TAG}&amp;quot; \&lt;br /&gt;
             --target systemtest \&lt;br /&gt;
             --tag &amp;quot;$DOCKER_SYSTEMTEST_TAG&amp;quot; \&lt;br /&gt;
             --file Dockerfile .&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs (Environment Variables) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Required !! Description !! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_BUILDOS_LABEL&amp;lt;/code&amp;gt; || Yes || Build OS identifier determining base images || &amp;lt;code&amp;gt;alma8&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;alma9&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_VERSION&amp;lt;/code&amp;gt; || Yes || Version string for image tags || &amp;lt;code&amp;gt;8.432.17&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ARCH&amp;lt;/code&amp;gt; || Yes || CPU architecture identifier || &amp;lt;code&amp;gt;x86_64&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;aarch64&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;WORKDIR&amp;lt;/code&amp;gt; || Yes || Working directory containing build artifacts || &amp;lt;code&amp;gt;/tmp/vespa-build&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_CONTAINER_IMAGE_VERSION_TAG_SUFFIX&amp;lt;/code&amp;gt; || Yes || Optional suffix appended to image version tags || (empty string or custom)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;GITREF_SYSTEM_TEST&amp;lt;/code&amp;gt; || No || Git ref for system-test checkout (defaults to HEAD) || &amp;lt;code&amp;gt;abc123&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;HEAD&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt; || No || If set to a non-empty value, enables bash xtrace || &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Inputs (Prerequisite Files) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! File/Directory !! Produced By !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$WORKDIR/artifacts/$ARCH/rpms/&amp;lt;/code&amp;gt; || build-rpms.sh || YUM repository with Vespa RPM packages&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$HOME/.m2/repository/&amp;lt;/code&amp;gt; || java.sh || Maven local repository with compiled JARs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Inputs (External Repositories) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Repository !! URL !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| docker-image || &amp;lt;code&amp;gt;https://github.com/vespa-engine/docker-image&amp;lt;/code&amp;gt; || Contains Dockerfile for the Vespa production image&lt;br /&gt;
|-&lt;br /&gt;
| system-test || &amp;lt;code&amp;gt;https://github.com/vespa-engine/system-test&amp;lt;/code&amp;gt; || Contains test framework and system-test Dockerfile&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs (Docker Images) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Image !! Tag !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Vespa Preview || &amp;lt;code&amp;gt;ghcr.io/vespa-engine/vespa-preview-${ARCH}:${VESPA_VERSION}${SUFFIX}&amp;lt;/code&amp;gt; || Production Vespa image&lt;br /&gt;
|-&lt;br /&gt;
| Vespa Preview (local) || &amp;lt;code&amp;gt;vespaengine/vespa&amp;lt;/code&amp;gt; || Local tag for the production image&lt;br /&gt;
|-&lt;br /&gt;
| System Test Preview || &amp;lt;code&amp;gt;docker.io/vespaengine/vespa-systemtest-preview-${ARCH}:${VESPA_VERSION}${SUFFIX}&amp;lt;/code&amp;gt; || System test image with test frameworks&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Key Implementation Details ==&lt;br /&gt;
&lt;br /&gt;
=== Docker Availability Check ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if ! docker ps &amp;amp;&amp;gt; /dev/null; then&lt;br /&gt;
    echo &amp;quot;No working docker command found.&amp;quot;&lt;br /&gt;
    exit 1&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The script immediately verifies that the Docker daemon is accessible by running &amp;lt;code&amp;gt;docker ps&amp;lt;/code&amp;gt; and redirecting all output to &amp;lt;code&amp;gt;/dev/null&amp;lt;/code&amp;gt;. This provides an early, clear failure message if Docker is not available, rather than a confusing error later during the build.&lt;br /&gt;
&lt;br /&gt;
=== Base Image Selection ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
case &amp;quot;${VESPA_BUILDOS_LABEL}&amp;quot; in&lt;br /&gt;
    alma8)&lt;br /&gt;
        VESPA_BASE_IMAGE=&amp;quot;el8&amp;quot;&lt;br /&gt;
        SYSTEM_TEST_BASE_IMAGE=&amp;quot;almalinux:8&amp;quot;&lt;br /&gt;
        ;;&lt;br /&gt;
    alma9)&lt;br /&gt;
        VESPA_BASE_IMAGE=&amp;quot;el9&amp;quot;&lt;br /&gt;
        SYSTEM_TEST_BASE_IMAGE=&amp;quot;almalinux:9&amp;quot;&lt;br /&gt;
        ;;&lt;br /&gt;
    *)&lt;br /&gt;
        echo &amp;quot;Unknown build os: ${VESPA_BUILDOS_LABEL}&amp;quot; 1&amp;gt;&amp;amp;2&lt;br /&gt;
        exit 1&lt;br /&gt;
        ;;&lt;br /&gt;
esac&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;case&amp;lt;/code&amp;gt; statement maps the build OS label to two different base image references:&lt;br /&gt;
* &amp;lt;code&amp;gt;VESPA_BASE_IMAGE&amp;lt;/code&amp;gt; uses a short label (&amp;lt;code&amp;gt;el8&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;el9&amp;lt;/code&amp;gt;) that is resolved inside the Dockerfile to the appropriate internal base image.&lt;br /&gt;
* &amp;lt;code&amp;gt;SYSTEM_TEST_BASE_IMAGE&amp;lt;/code&amp;gt; uses a full Docker Hub reference (&amp;lt;code&amp;gt;almalinux:8&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;almalinux:9&amp;lt;/code&amp;gt;) for the system test base.&lt;br /&gt;
&lt;br /&gt;
=== Docker-Image Repository Cloning ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [[ ! -d &amp;quot;${WORKDIR}/docker-image&amp;quot; ]]; then&lt;br /&gt;
    git clone --quiet --depth 1 https://github.com/vespa-engine/docker-image &amp;quot;$WORKDIR/docker-image&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
rm -rf &amp;quot;${WORKDIR}/docker-image/rpms&amp;quot;&lt;br /&gt;
cp -a &amp;quot;${WORKDIR}/artifacts/$ARCH/rpms&amp;quot; &amp;quot;${WORKDIR}/docker-image/&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The docker-image repository is cloned with &amp;lt;code&amp;gt;--depth 1&amp;lt;/code&amp;gt; (shallow clone) for minimal download. The built RPMs are then copied into the clone to serve as the Docker build context. The &amp;lt;code&amp;gt;cp -a&amp;lt;/code&amp;gt; flag preserves file attributes and timestamps.&lt;br /&gt;
&lt;br /&gt;
=== Vespa Preview Image Build ===&lt;br /&gt;
&lt;br /&gt;
The Docker build uses three build arguments:&lt;br /&gt;
* &amp;lt;code&amp;gt;SOURCE_GITREF&amp;lt;/code&amp;gt;: The git commit hash of the docker-image repo, used for image metadata.&lt;br /&gt;
* &amp;lt;code&amp;gt;VESPA_VERSION&amp;lt;/code&amp;gt;: Baked into the image for runtime version reporting.&lt;br /&gt;
* &amp;lt;code&amp;gt;VESPA_BASE_IMAGE&amp;lt;/code&amp;gt;: Selects the OS variant within the Dockerfile.&lt;br /&gt;
&lt;br /&gt;
Two tags are applied: a local tag (&amp;lt;code&amp;gt;vespaengine/vespa&amp;lt;/code&amp;gt;) used as the base for the system-test image, and a GHCR preview tag for registry storage.&lt;br /&gt;
&lt;br /&gt;
=== System-Test Image Build ===&lt;br /&gt;
&lt;br /&gt;
The system-test build is more involved:&lt;br /&gt;
&lt;br /&gt;
# The system-test repository is cloned with &amp;lt;code&amp;gt;--filter=&amp;quot;blob:none&amp;quot;&amp;lt;/code&amp;gt; (blobless clone) for efficiency.&lt;br /&gt;
# A specific git ref is checked out (defaulting to HEAD).&lt;br /&gt;
# &amp;lt;code&amp;gt;git archive HEAD | tar x&amp;lt;/code&amp;gt; exports the test framework without &amp;lt;code&amp;gt;.git&amp;lt;/code&amp;gt; metadata.&lt;br /&gt;
# The Maven repository and RPMs are copied into the Docker build context.&lt;br /&gt;
# The image is built with &amp;lt;code&amp;gt;--target systemtest&amp;lt;/code&amp;gt;, using a multi-stage Dockerfile.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;--target systemtest&amp;lt;/code&amp;gt; flag selects the systemtest stage in the multi-stage Dockerfile, which extends the base Vespa image with test dependencies.&lt;br /&gt;
&lt;br /&gt;
=== RPM Movement Between Images ===&lt;br /&gt;
&lt;br /&gt;
After the Vespa preview image is built, the RPMs are moved (not copied) from the docker-image context into the system-test context:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
rm -rf rpms&lt;br /&gt;
mv &amp;quot;$WORKDIR/docker-image/rpms&amp;quot; rpms&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;code&amp;gt;mv&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;cp&amp;lt;/code&amp;gt; avoids doubling the disk usage for the RPM repository.&lt;br /&gt;
&lt;br /&gt;
== Execution Context ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Buildkite Pipeline&lt;br /&gt;
  --&amp;gt; .buildkite/build-rpms.sh (produces RPMs)&lt;br /&gt;
  --&amp;gt; .buildkite/build-container.sh&lt;br /&gt;
        --&amp;gt; Verify Docker availability&lt;br /&gt;
        --&amp;gt; Map VESPA_BUILDOS_LABEL to base images&lt;br /&gt;
        --&amp;gt; Clone vespa-engine/docker-image (shallow)&lt;br /&gt;
        --&amp;gt; Copy RPMs into docker-image context&lt;br /&gt;
        --&amp;gt; docker build (Vespa preview image)&lt;br /&gt;
        --&amp;gt; Clone vespa-engine/system-test (blobless)&lt;br /&gt;
        --&amp;gt; Prepare test context (git archive, copy Maven repo)&lt;br /&gt;
        --&amp;gt; docker build --target systemtest (system-test image)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Source File Locations ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/vespa-engine/vespa/blob/master/.buildkite/build-container.sh &amp;lt;code&amp;gt;.buildkite/build-container.sh&amp;lt;/code&amp;gt;] (Lines 1-91)&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Principle:Vespa_engine_Vespa_Container_Image_Building|Container Image Building Principle]] -- The design rationale for Vespa container images.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Build_Rpms_Sh|RPM Build Implementation]] -- The preceding stage that produces the RPMs installed in the image.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Publish_Artifacts_Sh|Artifact Publishing Implementation]] -- The stage that signs and uploads build artifacts.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Vespa_engine_Vespa_Container_Image_Building]]&lt;br /&gt;
* [[requires_env::Environment:Vespa_engine_Vespa_Docker_OCI_Container_Runtime]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Bootstrap_Cmake_Sh&amp;diff=30772</id>
		<title>Implementation:Vespa engine Vespa Bootstrap Cmake Sh</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Bootstrap_Cmake_Sh&amp;diff=30772"/>
		<updated>2026-09-27T10:53:12Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Bootstrap_Cmake_Sh}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Bootstrap_Cmake_Sh}}&lt;br /&gt;
{{DISPLAYTITLE:CMake Configuration Implementation}}&lt;br /&gt;
[[domain::CI_CD]] [[domain::Build_Systems]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This page documents the implementation of the Vespa CMake configuration script: &#039;&#039;.buildkite/bootstrap-cmake.sh&#039;&#039;. This script sets up the build environment, resolves sanitizer and ccache options, and invokes CMake to generate Makefiles for the C++ build.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Type:&#039;&#039;&#039; External Tool Doc&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env bash&lt;br /&gt;
# .buildkite/bootstrap-cmake.sh (L1-35)&lt;br /&gt;
&lt;br /&gt;
set -o errexit&lt;br /&gt;
set -o nounset&lt;br /&gt;
set -o pipefail&lt;br /&gt;
&lt;br /&gt;
if [[ -n &amp;quot;${DEBUG:-}&amp;quot; ]]; then&lt;br /&gt;
    set -o xtrace&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;--- Configuring CMake build&amp;quot;&lt;br /&gt;
# shellcheck disable=1091&lt;br /&gt;
source /etc/profile.d/enable-gcc-toolset.sh&lt;br /&gt;
&lt;br /&gt;
PATH=/opt/vespa-deps/bin:$PATH&lt;br /&gt;
&lt;br /&gt;
VESPA_CMAKE_SANITIZERS_OPTION=&amp;quot;&amp;quot;&lt;br /&gt;
VESPA_CMAKE_CCACHE_OPTION=&amp;quot;&amp;quot;&lt;br /&gt;
if [[ $VESPA_USE_SANITIZER != null ]]; then&lt;br /&gt;
    echo &amp;quot;Enabling sanitizer: $VESPA_USE_SANITIZER&amp;quot;&lt;br /&gt;
    VESPA_CMAKE_SANITIZERS_OPTION=&amp;quot;-DVESPA_USE_SANITIZER=$VESPA_USE_SANITIZER&amp;quot;&lt;br /&gt;
    VESPA_CMAKE_CCACHE_OPTION=&amp;quot;-DVESPA_USE_CCACHE=false&amp;quot;&lt;br /&gt;
    VALGRIND_UNIT_TESTS=false&lt;br /&gt;
fi&lt;br /&gt;
if [[ $BUILDKITE_PULL_REQUEST != &amp;quot;false&amp;quot; ]]; then&lt;br /&gt;
    VALGRIND_UNIT_TESTS=false&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Running CMake configuration...&amp;quot;&lt;br /&gt;
cmake -DVESPA_UNPRIVILEGED=no -DVALGRIND_UNIT_TESTS=&amp;quot;$VALGRIND_UNIT_TESTS&amp;quot; \&lt;br /&gt;
  &amp;quot;$VESPA_CMAKE_SANITIZERS_OPTION&amp;quot; &amp;quot;$VESPA_CMAKE_CCACHE_OPTION&amp;quot; &amp;quot;$SOURCE_DIR&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs (Environment Variables) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Required !! Description !! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_USE_SANITIZER&amp;lt;/code&amp;gt; || Yes || Sanitizer type to enable, or &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt; for none || &amp;lt;code&amp;gt;address&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;thread&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;null&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;BUILDKITE_PULL_REQUEST&amp;lt;/code&amp;gt; || Yes || PR number or &amp;lt;code&amp;gt;&amp;quot;false&amp;quot;&amp;lt;/code&amp;gt; if this is not a PR build || &amp;lt;code&amp;gt;35801&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VALGRIND_UNIT_TESTS&amp;lt;/code&amp;gt; || Yes || Initial setting for Valgrind test enablement || &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SOURCE_DIR&amp;lt;/code&amp;gt; || Yes || Absolute path to the Vespa source checkout || &amp;lt;code&amp;gt;/vespa&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt; || No || If set to a non-empty value, enables bash xtrace || &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Inputs (System Dependencies) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Dependency !! Path !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| GCC Toolset || &amp;lt;code&amp;gt;/etc/profile.d/enable-gcc-toolset.sh&amp;lt;/code&amp;gt; || Activates the GCC 12+ compiler suite&lt;br /&gt;
|-&lt;br /&gt;
| Vespa Dependencies || &amp;lt;code&amp;gt;/opt/vespa-deps/bin&amp;lt;/code&amp;gt; || Pre-built libraries (protobuf, abseil, gRPC, etc.)&lt;br /&gt;
|-&lt;br /&gt;
| CMake || System PATH (after deps setup) || Build system generator&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs (Files) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Output !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; || Generated file || Top-level Makefile for the C++ build&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;CMakeCache.txt&amp;lt;/code&amp;gt; || Generated file || Cache of all resolved CMake variables&lt;br /&gt;
|-&lt;br /&gt;
| Subdirectory Makefiles || Generated files || Per-module Makefiles for each CMakeLists.txt&lt;br /&gt;
|-&lt;br /&gt;
| Generated headers || Generated files || Platform-specific config headers (e.g., &amp;lt;code&amp;gt;config.h&amp;lt;/code&amp;gt;)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Key Implementation Details ==&lt;br /&gt;
&lt;br /&gt;
=== Sanitizer Option Resolution ===&lt;br /&gt;
&lt;br /&gt;
The script determines sanitizer and ccache options through conditional logic:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
VESPA_CMAKE_SANITIZERS_OPTION=&amp;quot;&amp;quot;&lt;br /&gt;
VESPA_CMAKE_CCACHE_OPTION=&amp;quot;&amp;quot;&lt;br /&gt;
if [[ $VESPA_USE_SANITIZER != null ]]; then&lt;br /&gt;
    VESPA_CMAKE_SANITIZERS_OPTION=&amp;quot;-DVESPA_USE_SANITIZER=$VESPA_USE_SANITIZER&amp;quot;&lt;br /&gt;
    VESPA_CMAKE_CCACHE_OPTION=&amp;quot;-DVESPA_USE_CCACHE=false&amp;quot;&lt;br /&gt;
    VALGRIND_UNIT_TESTS=false&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a sanitizer is active:&lt;br /&gt;
* The corresponding CMake variable is set (e.g., &amp;lt;code&amp;gt;-DVESPA_USE_SANITIZER=address&amp;lt;/code&amp;gt;).&lt;br /&gt;
* Ccache is explicitly disabled to prevent cache poisoning with sanitizer-instrumented object files.&lt;br /&gt;
* Valgrind is disabled because sanitizers already provide memory error detection.&lt;br /&gt;
&lt;br /&gt;
=== Pull Request Optimization ===&lt;br /&gt;
&lt;br /&gt;
For pull request builds, Valgrind unit tests are unconditionally disabled:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [[ $BUILDKITE_PULL_REQUEST != &amp;quot;false&amp;quot; ]]; then&lt;br /&gt;
    VALGRIND_UNIT_TESTS=false&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This reduces PR build times significantly since Valgrind adds 10-50x overhead to test execution. Full Valgrind testing is reserved for post-merge builds on the main branch.&lt;br /&gt;
&lt;br /&gt;
=== CMake Variable Passing ===&lt;br /&gt;
&lt;br /&gt;
The variables &amp;lt;code&amp;gt;$VESPA_CMAKE_SANITIZERS_OPTION&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;$VESPA_CMAKE_CCACHE_OPTION&amp;lt;/code&amp;gt; are passed as unquoted arguments to CMake. When they are empty strings, Bash word splitting causes them to be omitted entirely, which is the desired behavior -- CMake receives no sanitizer or ccache flags when they are not configured.&lt;br /&gt;
&lt;br /&gt;
=== GCC Toolset and Dependency Path ===&lt;br /&gt;
&lt;br /&gt;
The script sets up the compilation environment before invoking CMake:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
source /etc/profile.d/enable-gcc-toolset.sh&lt;br /&gt;
PATH=/opt/vespa-deps/bin:$PATH&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This ensures that:&lt;br /&gt;
* CMake detects the correct C++ compiler (GCC 12+ with C++20 support).&lt;br /&gt;
* &amp;lt;code&amp;gt;find_package()&amp;lt;/code&amp;gt; calls in CMakeLists.txt files can locate pre-built Vespa dependency libraries under &amp;lt;code&amp;gt;/opt/vespa-deps/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== VESPA_UNPRIVILEGED Flag ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;-DVESPA_UNPRIVILEGED=no&amp;lt;/code&amp;gt; flag tells CMake that the build targets a privileged (root) installation. This affects installation paths, file permissions, and systemd service configurations in the generated build system.&lt;br /&gt;
&lt;br /&gt;
== Execution Context ==&lt;br /&gt;
&lt;br /&gt;
This script is invoked from the Buildkite pipeline after the Java bootstrap has completed. It runs in the build directory (not the source directory), creating an out-of-source build:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Buildkite Pipeline&lt;br /&gt;
  --&amp;gt; .buildkite/bootstrap.sh (Java bootstrap)&lt;br /&gt;
  --&amp;gt; cd $BUILD_DIR&lt;br /&gt;
  --&amp;gt; .buildkite/bootstrap-cmake.sh&lt;br /&gt;
        --&amp;gt; source enable-gcc-toolset.sh&lt;br /&gt;
        --&amp;gt; cmake ... $SOURCE_DIR&lt;br /&gt;
  --&amp;gt; .buildkite/cpp.sh (uses generated Makefiles)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Source File Locations ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/vespa-engine/vespa/blob/master/.buildkite/bootstrap-cmake.sh &amp;lt;code&amp;gt;.buildkite/bootstrap-cmake.sh&amp;lt;/code&amp;gt;] (Lines 1-35)&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Principle:Vespa_engine_Vespa_CMake_Configuration|CMake Configuration Principle]] -- The design rationale for CMake configuration in the Vespa build.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Cpp_Sh|C++ Compilation Implementation]] -- The next stage that runs &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; on the generated Makefiles.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Bootstrap_And_Java_Sh|Bootstrap and Java Build Implementation]] -- The preceding stage that produces JAR dependencies for CMake.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Vespa_engine_Vespa_CMake_Configuration]]&lt;br /&gt;
* [[requires_env::Environment:Vespa_engine_Vespa_CMake_Cpp23_Build_Environment]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Bootstrap_And_Java_Sh&amp;diff=30771</id>
		<title>Implementation:Vespa engine Vespa Bootstrap And Java Sh</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Vespa_engine_Vespa_Bootstrap_And_Java_Sh&amp;diff=30771"/>
		<updated>2026-09-27T10:53:11Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Bootstrap_And_Java_Sh}}&lt;br /&gt;
{{PageInfo|type=Implementation|title=Vespa_engine_Vespa_Bootstrap_And_Java_Sh}}&lt;br /&gt;
{{DISPLAYTITLE:Bootstrap and Java Build Implementation}}&lt;br /&gt;
[[domain::CI_CD]] [[domain::Build_Systems]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This page documents the implementation of the Vespa Java bootstrap and Maven build scripts: &#039;&#039;.buildkite/bootstrap.sh&#039;&#039;, &#039;&#039;.buildkite/java.sh&#039;&#039;, and the root-level &#039;&#039;bootstrap.sh&#039;&#039;. Together these scripts set up the Maven wrapper, build parent POMs and plugins, compile all Java modules, and collect JAR files needed by C++ tests.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Type:&#039;&#039;&#039; External Tool Doc&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== .buildkite/bootstrap.sh ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env bash&lt;br /&gt;
# .buildkite/bootstrap.sh (L1-24)&lt;br /&gt;
&lt;br /&gt;
set -o errexit&lt;br /&gt;
set -o nounset&lt;br /&gt;
set -o pipefail&lt;br /&gt;
&lt;br /&gt;
if [[ -n &amp;quot;${DEBUG:-}&amp;quot; ]]; then&lt;br /&gt;
    set -o xtrace&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;--- Running Vespa bootstrap&amp;quot;&lt;br /&gt;
cd &amp;quot;$SOURCE_DIR&amp;quot;&lt;br /&gt;
./bootstrap.sh full&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Setting up test JAR directory...&amp;quot;&lt;br /&gt;
mkdir -p &amp;quot;$VESPA_CPP_TEST_JARS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Collecting JAR files for C++ tests...&amp;quot;&lt;br /&gt;
# shellcheck disable=2038&lt;br /&gt;
find . -type d -name target -exec find {} -mindepth 1 -maxdepth 1 -name &amp;quot;*.jar&amp;quot; \; \&lt;br /&gt;
    | xargs -I &#039;{}&#039; cp &#039;{}&#039; &amp;quot;$VESPA_CPP_TEST_JARS&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== .buildkite/java.sh ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env bash&lt;br /&gt;
# .buildkite/java.sh (L1-31)&lt;br /&gt;
&lt;br /&gt;
set -o errexit&lt;br /&gt;
set -o nounset&lt;br /&gt;
set -o pipefail&lt;br /&gt;
&lt;br /&gt;
if [[ -n &amp;quot;${DEBUG:-}&amp;quot; ]]; then&lt;br /&gt;
    set -o xtrace&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
mydir=${0%/*}&lt;br /&gt;
shlim=${mydir}/show-limits.sh&lt;br /&gt;
if [ -x &amp;quot;${shlim}&amp;quot; ]; then&lt;br /&gt;
    &amp;quot;${shlim}&amp;quot; || echo &amp;quot;failed: ${shlim}&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;--- Building Java components&amp;quot;&lt;br /&gt;
# shellcheck disable=1091&lt;br /&gt;
source /etc/profile.d/enable-gcc-toolset.sh&lt;br /&gt;
&lt;br /&gt;
PATH=/opt/vespa-deps/bin:$PATH&lt;br /&gt;
&lt;br /&gt;
cd &amp;quot;$SOURCE_DIR&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Running Maven build with target: ${VESPA_MAVEN_TARGET} [threads: ${NUM_MVN_THREADS}]&amp;quot;&lt;br /&gt;
read -ra MVN_EXTRA_OPTS &amp;lt;&amp;lt;&amp;lt; &amp;quot;$VESPA_MAVEN_EXTRA_OPTS&amp;quot;&lt;br /&gt;
./mvnw -T &amp;quot;$NUM_MVN_THREADS&amp;quot; &amp;quot;${MVN_EXTRA_OPTS[@]}&amp;quot; &amp;quot;$VESPA_MAVEN_TARGET&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== bootstrap.sh (Root-Level) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env bash&lt;br /&gt;
# bootstrap.sh (L1-133) -- key sections shown&lt;br /&gt;
&lt;br /&gt;
# Mode selection: full | java | default | wrapper&lt;br /&gt;
MODE=$1  # or &amp;quot;default&amp;quot; if no argument&lt;br /&gt;
&lt;br /&gt;
# Maven wrapper setup&lt;br /&gt;
MAVEN_CMD=$(get_env_var_with_optional_default VESPA_MAVEN_COMMAND &amp;quot;$(pwd)/mvnw&amp;quot;)&lt;br /&gt;
mvn -B wrapper:wrapper -Dmaven=3.9.12 -N ${MAVEN_EXTRA_OPTS}&lt;br /&gt;
&lt;br /&gt;
# Proxy script allowing plain &amp;quot;mvn&amp;quot; to use the wrapper&lt;br /&gt;
wbdir=maven-wrapper/bin&lt;br /&gt;
mkdir -p ${wbdir}&lt;br /&gt;
printf &#039;#!/bin/sh\nexec %s/mvnw &amp;quot;$@&amp;quot;\n&#039; &amp;quot;$(pwd)&amp;quot; &amp;gt; ${wbdir}/mvn&lt;br /&gt;
chmod +x ${wbdir}/mvn&lt;br /&gt;
&lt;br /&gt;
# Core build function&lt;br /&gt;
mvn_install() {&lt;br /&gt;
    ${MAVEN_CMD} --batch-mode --no-snapshot-updates \&lt;br /&gt;
        -Dmaven.wagon.http.retryHandler.count=5 \&lt;br /&gt;
        clean &amp;quot;${MAVEN_TARGET}&amp;quot; ${MAVEN_EXTRA_OPTS} &amp;quot;$@&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Build order:&lt;br /&gt;
# 1. Parent POMs (dependency-versions, container-dependency-versions, parent)&lt;br /&gt;
# 2. Root POM (non-recursive)&lt;br /&gt;
# 3. Maven plugins&lt;br /&gt;
# 4. Mode-specific modules (full mode: jrt, linguistics, messagebus)&lt;br /&gt;
&lt;br /&gt;
cd dependency-versions &amp;amp;&amp;amp; mvn_install&lt;br /&gt;
cd container-dependency-versions &amp;amp;&amp;amp; mvn_install&lt;br /&gt;
cd parent &amp;amp;&amp;amp; mvn_install&lt;br /&gt;
mvn_install -N&lt;br /&gt;
mvn_install -f maven-plugins/pom.xml&lt;br /&gt;
&lt;br /&gt;
# Full mode: build C++ test dependencies&lt;br /&gt;
mvn_install -am -T1C -Dmaven.test.skip=true \&lt;br /&gt;
    -Dmaven.javadoc.skip=true -Dmaven.source.skip=true \&lt;br /&gt;
    -pl jrt,linguistics,messagebus&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== Inputs (Environment Variables) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Required !! Script !! Description !! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SOURCE_DIR&amp;lt;/code&amp;gt; || Yes || bootstrap.sh, java.sh || Root directory of the Vespa source checkout || &amp;lt;code&amp;gt;/vespa&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_CPP_TEST_JARS&amp;lt;/code&amp;gt; || Yes || bootstrap.sh || Destination directory for collected JAR files || &amp;lt;code&amp;gt;/tmp/vespa-build/test-jars&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NUM_MVN_THREADS&amp;lt;/code&amp;gt; || Yes || java.sh || Number of parallel Maven threads || &amp;lt;code&amp;gt;4&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_MAVEN_TARGET&amp;lt;/code&amp;gt; || Yes || java.sh, bootstrap.sh || Maven lifecycle target || &amp;lt;code&amp;gt;install&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_MAVEN_EXTRA_OPTS&amp;lt;/code&amp;gt; || Yes || java.sh, bootstrap.sh || Additional Maven options || &amp;lt;code&amp;gt;-Dmaven.test.skip=true&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;VESPA_MAVEN_COMMAND&amp;lt;/code&amp;gt; || No || bootstrap.sh || Override for Maven command path || &amp;lt;code&amp;gt;./mvnw&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MAVEN_OPTS&amp;lt;/code&amp;gt; || No || java.sh || JVM arguments for Maven process || &amp;lt;code&amp;gt;-Xms256m -Xmx2g&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt; || No || All || Enables bash xtrace when non-empty || &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Outputs (Files and Artifacts) ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Output !! Produced By !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;./mvnw&amp;lt;/code&amp;gt; || bootstrap.sh (root) || Maven wrapper script (Maven 3.9.12)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;maven-wrapper/bin/mvn&amp;lt;/code&amp;gt; || bootstrap.sh (root) || Proxy script redirecting &amp;lt;code&amp;gt;mvn&amp;lt;/code&amp;gt; to the wrapper&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;~/.m2/repository/&amp;lt;/code&amp;gt; || bootstrap.sh (root), java.sh || Local Maven repository containing all compiled JARs&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$VESPA_CPP_TEST_JARS/*.jar&amp;lt;/code&amp;gt; || .buildkite/bootstrap.sh || Flat directory of JAR files needed by C++ tests&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;dist/vtag.map&amp;lt;/code&amp;gt; || bootstrap.sh (root) || Version tag map generated by &amp;lt;code&amp;gt;getversionmap.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Key Implementation Details ==&lt;br /&gt;
&lt;br /&gt;
=== Maven Wrapper Setup ===&lt;br /&gt;
&lt;br /&gt;
The root &#039;&#039;bootstrap.sh&#039;&#039; installs the Maven wrapper at a pinned version (3.9.12):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mvn -B wrapper:wrapper -Dmaven=3.9.12 -N ${MAVEN_EXTRA_OPTS}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;-N&amp;lt;/code&amp;gt; (non-recursive) flag ensures only the root module is processed. After installation, a proxy script is created at &amp;lt;code&amp;gt;maven-wrapper/bin/mvn&amp;lt;/code&amp;gt; so that any script invoking plain &amp;lt;code&amp;gt;mvn&amp;lt;/code&amp;gt; transparently uses the wrapper instead.&lt;br /&gt;
&lt;br /&gt;
=== Build Order in bootstrap.sh ===&lt;br /&gt;
&lt;br /&gt;
The root bootstrap script enforces a specific build order due to Maven&#039;s plugin resolution limitation:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;dependency-versions&#039;&#039;&#039; -- Defines version constraints for third-party dependencies.&lt;br /&gt;
# &#039;&#039;&#039;container-dependency-versions&#039;&#039;&#039; -- Defines version constraints for container-related dependencies.&lt;br /&gt;
# &#039;&#039;&#039;parent&#039;&#039;&#039; -- The parent POM that all modules inherit from.&lt;br /&gt;
# &#039;&#039;&#039;Root POM&#039;&#039;&#039; (non-recursive) -- Installs the root aggregator POM.&lt;br /&gt;
# &#039;&#039;&#039;maven-plugins&#039;&#039;&#039; -- Custom Maven plugins used by other modules.&lt;br /&gt;
# &#039;&#039;&#039;Mode-specific modules&#039;&#039;&#039; -- In &amp;lt;code&amp;gt;full&amp;lt;/code&amp;gt; mode, builds &amp;lt;code&amp;gt;jrt&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;linguistics&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;messagebus&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;-am&amp;lt;/code&amp;gt; (also-make-dependencies) and &amp;lt;code&amp;gt;-T1C&amp;lt;/code&amp;gt; (one thread per core).&lt;br /&gt;
&lt;br /&gt;
=== JAR Collection for C++ Tests ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;.buildkite/bootstrap.sh&#039;&#039; script uses a nested &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; command to locate all JAR files:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
find . -type d -name target -exec find {} -mindepth 1 -maxdepth 1 -name &amp;quot;*.jar&amp;quot; \; \&lt;br /&gt;
    | xargs -I &#039;{}&#039; cp &#039;{}&#039; &amp;quot;$VESPA_CPP_TEST_JARS&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This two-level find first locates all Maven &amp;lt;code&amp;gt;target/&amp;lt;/code&amp;gt; directories, then within each one finds JAR files at the top level (not in subdirectories). The JARs are copied into a flat directory for easy classpath construction by C++ test binaries.&lt;br /&gt;
&lt;br /&gt;
=== GCC Toolset and PATH Setup ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;.buildkite/java.sh&#039;&#039; script activates the GCC toolset and adds Vespa dependency binaries to the PATH before invoking Maven:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
source /etc/profile.d/enable-gcc-toolset.sh&lt;br /&gt;
PATH=/opt/vespa-deps/bin:$PATH&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is necessary because some Java modules contain JNI (Java Native Interface) code that requires native compilation during the Maven build.&lt;br /&gt;
&lt;br /&gt;
=== Resource Limit Reporting ===&lt;br /&gt;
&lt;br /&gt;
Before starting the build, &#039;&#039;java.sh&#039;&#039; optionally executes &amp;lt;code&amp;gt;show-limits.sh&amp;lt;/code&amp;gt; to log system resource limits (e.g., open file descriptors, stack size). This diagnostic output helps troubleshoot build failures caused by resource exhaustion.&lt;br /&gt;
&lt;br /&gt;
== Execution Context ==&lt;br /&gt;
&lt;br /&gt;
The typical invocation sequence in the Buildkite pipeline is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Buildkite Pipeline&lt;br /&gt;
  --&amp;gt; .buildkite/bootstrap.sh&lt;br /&gt;
        --&amp;gt; cd $SOURCE_DIR &amp;amp;&amp;amp; ./bootstrap.sh full&lt;br /&gt;
              --&amp;gt; mvn wrapper:wrapper (Maven 3.9.12)&lt;br /&gt;
              --&amp;gt; mvn_install dependency-versions&lt;br /&gt;
              --&amp;gt; mvn_install container-dependency-versions&lt;br /&gt;
              --&amp;gt; mvn_install parent&lt;br /&gt;
              --&amp;gt; mvn_install -N (root POM)&lt;br /&gt;
              --&amp;gt; mvn_install maven-plugins&lt;br /&gt;
              --&amp;gt; mvn_install jrt,linguistics,messagebus&lt;br /&gt;
        --&amp;gt; mkdir -p $VESPA_CPP_TEST_JARS&lt;br /&gt;
        --&amp;gt; find + xargs cp (collect JARs)&lt;br /&gt;
  --&amp;gt; .buildkite/java.sh&lt;br /&gt;
        --&amp;gt; source enable-gcc-toolset.sh&lt;br /&gt;
        --&amp;gt; ./mvnw -T $NUM_MVN_THREADS $VESPA_MAVEN_EXTRA_OPTS $VESPA_MAVEN_TARGET&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Source File Locations ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/vespa-engine/vespa/blob/master/.buildkite/bootstrap.sh &amp;lt;code&amp;gt;.buildkite/bootstrap.sh&amp;lt;/code&amp;gt;] (Lines 1-24)&lt;br /&gt;
* [https://github.com/vespa-engine/vespa/blob/master/.buildkite/java.sh &amp;lt;code&amp;gt;.buildkite/java.sh&amp;lt;/code&amp;gt;] (Lines 1-31)&lt;br /&gt;
* [https://github.com/vespa-engine/vespa/blob/master/bootstrap.sh &amp;lt;code&amp;gt;bootstrap.sh&amp;lt;/code&amp;gt;] (Lines 1-133)&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[Principle:Vespa_engine_Vespa_Java_Bootstrap_and_Maven_Build|Java Bootstrap and Maven Build Principle]] -- The design rationale for the two-phase Java build.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Prepare_Sh|Prepare.sh Implementation]] -- The preceding pipeline stage.&lt;br /&gt;
* [[Implementation:Vespa_engine_Vespa_Bootstrap_Cmake_Sh|CMake Configuration Implementation]] -- The next stage that depends on bootstrap output.&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[implements::Principle:Vespa_engine_Vespa_Java_Bootstrap_and_Maven_Build]]&lt;br /&gt;
* [[requires_env::Environment:Vespa_engine_Vespa_Java_17_Build_Runtime]]&lt;br /&gt;
* [[uses_heuristic::Heuristic:Vespa_engine_Vespa_Maven_Parallel_Build_Optimization]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Turboderp_org_Exllamav2_WebSocket_Actions&amp;diff=30770</id>
		<title>Implementation:Turboderp org Exllamav2 WebSocket Actions</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Turboderp_org_Exllamav2_WebSocket_Actions&amp;diff=30770"/>
		<updated>2026-09-27T10:53:10Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Turboderp_org_Exllamav2_WebSocket_Actions}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Knowledge Sources&lt;br /&gt;
|&lt;br /&gt;
* [https://github.com/turboderp-org/exllamav2 Turboderp_org_Exllamav2]&lt;br /&gt;
|-&lt;br /&gt;
! Domains&lt;br /&gt;
| [[domain::Server]], [[domain::WebSocket]], [[domain::Text_Generation]]&lt;br /&gt;
|-&lt;br /&gt;
! Last Updated&lt;br /&gt;
| [[last_updated::2026-02-15 00:00 GMT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;WebSocket_Actions&#039;&#039;&#039; module defines the request handler functions for the ExLlamaV2 WebSocket server, including token estimation, text trimming, streaming inference, and interrupt control.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
This module contains the action handler functions that are dispatched by &#039;&#039;&#039;ExLlamaV2WebSocketServer&#039;&#039;&#039;. The &#039;&#039;&#039;dispatch()&#039;&#039;&#039; function routes incoming JSON requests based on the &#039;&#039;&#039;action&#039;&#039;&#039; field to the appropriate handler. Each handler receives the parsed request dict, the WebSocket connection, the server instance, and a pre-initialized response dict.&lt;br /&gt;
&lt;br /&gt;
The available actions are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;echo&#039;&#039;&#039; - Returns the response with only the echoed request/response IDs. Used as a ping/health check.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;estimate_token&#039;&#039;&#039; - Encodes the provided &#039;&#039;&#039;text&#039;&#039;&#039; using the server&#039;s tokenizer and returns the token count as &#039;&#039;&#039;num_tokens&#039;&#039;&#039;. Useful for clients to estimate prompt length before sending an inference request.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;lefttrim_token&#039;&#039;&#039; - Encodes the input &#039;&#039;&#039;text&#039;&#039;&#039;, trims from the left to keep only &#039;&#039;&#039;trimmed_length&#039;&#039;&#039; tokens from the right, then decodes back to text. Returns &#039;&#039;&#039;trimmed_text&#039;&#039;&#039;. This is used for context window management.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;infer&#039;&#039;&#039; - The main generation handler (async). Acquires the &#039;&#039;&#039;model_lock&#039;&#039;&#039; to ensure exclusive model access. Configures sampler settings from request parameters (top_k, top_p, top_a, min_p, typical, temperature, skew, repetition/frequency/presence penalties). Handles prompt tokenization, context overflow trimming, custom BOS tokens, stop conditions, and token healing. Generates tokens in a streaming loop, sending &#039;&#039;&#039;response_type: &amp;quot;chunk&amp;quot;&#039;&#039;&#039; messages for each generated piece of text. Supports &#039;&#039;&#039;stream_full&#039;&#039;&#039; mode where each chunk message includes the full response so far. Generation terminates on EOS, max tokens reached, or the &#039;&#039;&#039;stop_signal&#039;&#039;&#039; being set. The final response has &#039;&#039;&#039;response_type: &amp;quot;full&amp;quot;&#039;&#039;&#039; with the complete text and &#039;&#039;&#039;stop_reason&#039;&#039;&#039; (&amp;quot;eos&amp;quot;, &amp;quot;num_tokens&amp;quot;, or &amp;quot;interrupted&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;stop&#039;&#039;&#039; - Sets the server&#039;s &#039;&#039;&#039;stop_signal&#039;&#039;&#039; event to interrupt any active inference. The next iteration of the infer loop will detect the signal and terminate.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
These functions are not called directly by users. They are invoked by &#039;&#039;&#039;ExLlamaV2WebSocketServer.main()&#039;&#039;&#039; via the &#039;&#039;&#039;dispatch()&#039;&#039;&#039; function when a JSON message arrives on a WebSocket connection. Clients interact with these actions by sending appropriately formatted JSON messages.&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
* &#039;&#039;&#039;Repository:&#039;&#039;&#039; [https://github.com/turboderp-org/exllamav2 Turboderp_org_Exllamav2]&lt;br /&gt;
* &#039;&#039;&#039;File:&#039;&#039;&#039; [https://github.com/turboderp-org/exllamav2/blob/main/exllamav2/server/websocket_actions.py exllamav2/server/websocket_actions.py]&lt;br /&gt;
* &#039;&#039;&#039;Lines:&#039;&#039;&#039; 1-259&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
async def dispatch(request: dict, ws, server) -&amp;gt; None: ...&lt;br /&gt;
&lt;br /&gt;
def echo(request: dict, ws, server, response: dict) -&amp;gt; None: ...&lt;br /&gt;
&lt;br /&gt;
def estimate_token(request: dict, ws, server, response: dict) -&amp;gt; None: ...&lt;br /&gt;
&lt;br /&gt;
def lefttrim_token(request: dict, ws, server, response: dict) -&amp;gt; None: ...&lt;br /&gt;
&lt;br /&gt;
async def infer(request: dict, ws, server, response: dict) -&amp;gt; None: ...&lt;br /&gt;
&lt;br /&gt;
def stop(request: dict, ws, server, response: dict) -&amp;gt; None: ...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
from exllamav2.server import websocket_actions&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
=== dispatch() ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| request || &amp;lt;code&amp;gt;dict&amp;lt;/code&amp;gt; || Parsed JSON request with an &amp;quot;action&amp;quot; field&lt;br /&gt;
|-&lt;br /&gt;
| ws || &amp;lt;code&amp;gt;WebSocketServerProtocol&amp;lt;/code&amp;gt; || WebSocket connection for sending responses&lt;br /&gt;
|-&lt;br /&gt;
| server || &amp;lt;code&amp;gt;ExLlamaV2WebSocketServer&amp;lt;/code&amp;gt; || Server instance providing model, tokenizer, generator, and locks&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== infer() Request Fields ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field !! Type !! Required !! Description&lt;br /&gt;
|-&lt;br /&gt;
| action || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Yes || Must be &amp;quot;infer&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| text || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Yes || Input prompt text&lt;br /&gt;
|-&lt;br /&gt;
| max_new_tokens || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || Yes || Maximum number of tokens to generate&lt;br /&gt;
|-&lt;br /&gt;
| stream || &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt; || Yes || Whether to stream chunk responses&lt;br /&gt;
|-&lt;br /&gt;
| stream_full || &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt; || No || If True, each chunk includes full response so far&lt;br /&gt;
|-&lt;br /&gt;
| top_k || &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; || No || Top-K sampling (default: 100, 0 to disable)&lt;br /&gt;
|-&lt;br /&gt;
| top_p || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || No || Top-P / nucleus sampling (default: 0.8, 0 to disable)&lt;br /&gt;
|-&lt;br /&gt;
| top_a || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || No || Top-A sampling threshold (default: 0)&lt;br /&gt;
|-&lt;br /&gt;
| min_p || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || No || Min-P sampling threshold (default: 0)&lt;br /&gt;
|-&lt;br /&gt;
| typical || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || No || Typical sampling threshold (default: 0)&lt;br /&gt;
|-&lt;br /&gt;
| temperature || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || No || Sampling temperature (default: 0.9)&lt;br /&gt;
|-&lt;br /&gt;
| skew || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || No || Skew factor (default: 0.0)&lt;br /&gt;
|-&lt;br /&gt;
| rep_pen || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || No || Repetition penalty (default: 1.05)&lt;br /&gt;
|-&lt;br /&gt;
| freq_pen || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || No || Frequency penalty (default: 0.0)&lt;br /&gt;
|-&lt;br /&gt;
| pres_pen || &amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt; || No || Presence penalty (default: 0.0)&lt;br /&gt;
|-&lt;br /&gt;
| customBos || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || No || Custom BOS token prepended to prompt&lt;br /&gt;
|-&lt;br /&gt;
| stop_conditions || &amp;lt;code&amp;gt;list[str|int]&amp;lt;/code&amp;gt; || No || Additional stop strings/token IDs&lt;br /&gt;
|-&lt;br /&gt;
| token_healing || &amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt; || No || Enable token healing (default: False)&lt;br /&gt;
|-&lt;br /&gt;
| tag || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || No || Echoed in response for client-side correlation&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== infer() Response Format ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Field !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| action || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || &amp;quot;infer&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| response_type || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || &amp;quot;chunk&amp;quot; for streaming, &amp;quot;full&amp;quot; for final&lt;br /&gt;
|-&lt;br /&gt;
| chunk || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Next text chunk (streaming only)&lt;br /&gt;
|-&lt;br /&gt;
| response || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Full generated text (final response, or partial when stream_full=True)&lt;br /&gt;
|-&lt;br /&gt;
| util_text || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Input context after overflow trimming (final response only)&lt;br /&gt;
|-&lt;br /&gt;
| stop_reason || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || &amp;quot;eos&amp;quot;, &amp;quot;num_tokens&amp;quot;, or &amp;quot;interrupted&amp;quot; (final response only)&lt;br /&gt;
|-&lt;br /&gt;
| tag || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Echoed tag (if provided in request)&lt;br /&gt;
|-&lt;br /&gt;
| request_id || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Echoed request ID (if provided)&lt;br /&gt;
|-&lt;br /&gt;
| response_id || &amp;lt;code&amp;gt;str&amp;lt;/code&amp;gt; || Echoed response ID (if provided)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Client-side Python example using the websockets library&lt;br /&gt;
import asyncio&lt;br /&gt;
import json&lt;br /&gt;
import websockets&lt;br /&gt;
&lt;br /&gt;
async def chat():&lt;br /&gt;
    async with websockets.connect(&amp;quot;ws://localhost:7862&amp;quot;) as ws:&lt;br /&gt;
        # Send an inference request&lt;br /&gt;
        request = {&lt;br /&gt;
            &amp;quot;action&amp;quot;: &amp;quot;infer&amp;quot;,&lt;br /&gt;
            &amp;quot;text&amp;quot;: &amp;quot;Explain quantum computing in simple terms:&amp;quot;,&lt;br /&gt;
            &amp;quot;max_new_tokens&amp;quot;: 200,&lt;br /&gt;
            &amp;quot;stream&amp;quot;: True,&lt;br /&gt;
            &amp;quot;temperature&amp;quot;: 0.7,&lt;br /&gt;
            &amp;quot;top_p&amp;quot;: 0.9,&lt;br /&gt;
            &amp;quot;top_k&amp;quot;: 50,&lt;br /&gt;
            &amp;quot;rep_pen&amp;quot;: 1.05,&lt;br /&gt;
            &amp;quot;stop_conditions&amp;quot;: [&amp;quot;\n\n&amp;quot;],&lt;br /&gt;
            &amp;quot;token_healing&amp;quot;: True,&lt;br /&gt;
        }&lt;br /&gt;
        await ws.send(json.dumps(request))&lt;br /&gt;
&lt;br /&gt;
        # Receive streaming chunks&lt;br /&gt;
        while True:&lt;br /&gt;
            msg = json.loads(await ws.recv())&lt;br /&gt;
            if msg[&amp;quot;response_type&amp;quot;] == &amp;quot;chunk&amp;quot;:&lt;br /&gt;
                print(msg.get(&amp;quot;chunk&amp;quot;, &amp;quot;&amp;quot;), end=&amp;quot;&amp;quot;, flush=True)&lt;br /&gt;
            elif msg[&amp;quot;response_type&amp;quot;] == &amp;quot;full&amp;quot;:&lt;br /&gt;
                print(f&amp;quot;\n[Stop reason: {msg[&#039;stop_reason&#039;]}]&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
asyncio.run(chat())&lt;br /&gt;
&lt;br /&gt;
# Estimate token count&lt;br /&gt;
# {&amp;quot;action&amp;quot;: &amp;quot;estimate_token&amp;quot;, &amp;quot;text&amp;quot;: &amp;quot;Hello world&amp;quot;}&lt;br /&gt;
# Response: {&amp;quot;action&amp;quot;: &amp;quot;estimate_token&amp;quot;, &amp;quot;num_tokens&amp;quot;: 2}&lt;br /&gt;
&lt;br /&gt;
# Left-trim to fit context&lt;br /&gt;
# {&amp;quot;action&amp;quot;: &amp;quot;lefttrim_token&amp;quot;, &amp;quot;text&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;trimmed_length&amp;quot;: 2048}&lt;br /&gt;
# Response: {&amp;quot;action&amp;quot;: &amp;quot;lefttrim_token&amp;quot;, &amp;quot;trimmed_text&amp;quot;: &amp;quot;...&amp;quot;}&lt;br /&gt;
&lt;br /&gt;
# Interrupt active generation&lt;br /&gt;
# {&amp;quot;action&amp;quot;: &amp;quot;stop&amp;quot;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
&lt;br /&gt;
* [[Implementation:Turboderp_org_Exllamav2_ExLlamaV2WebSocketServer]] - The WebSocket server that dispatches to these action handlers&lt;br /&gt;
* [[Implementation:Turboderp_org_Exllamav2_ExLlamaV2DynamicGeneratorAsync]] - Alternative async generation interface for more advanced use cases&lt;br /&gt;
* [[Implementation:Turboderp_org_Exllamav2_ExLlamaV2TokenizerBase]] - Base tokenizer class used for encoding/decoding in these actions&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Turboderp_org_Exllamav2_ThreadPool&amp;diff=30769</id>
		<title>Implementation:Turboderp org Exllamav2 ThreadPool</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Turboderp_org_Exllamav2_ThreadPool&amp;diff=30769"/>
		<updated>2026-09-27T10:53:10Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Turboderp_org_Exllamav2_ThreadPool}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Knowledge Sources&lt;br /&gt;
|&lt;br /&gt;
* [https://github.com/turboderp-org/exllamav2 Turboderp_org_Exllamav2]&lt;br /&gt;
|-&lt;br /&gt;
! Domains&lt;br /&gt;
| [[domain::Concurrency]], [[domain::C_Extension]]&lt;br /&gt;
|-&lt;br /&gt;
! Last Updated&lt;br /&gt;
| [[last_updated::2026-02-15 00:00 GMT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
Header-only C++ library providing a &#039;&#039;&#039;ThreadPool&#039;&#039;&#039; class for asynchronous task execution and a &#039;&#039;&#039;Barrier&#039;&#039;&#039; class for thread synchronization, used throughout ExLlamaV2&#039;s C++ extension layer.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;threadpool.h&#039;&#039;&#039; defines two concurrency primitives:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ThreadPool&#039;&#039;&#039; implements a classic thread pool pattern with:&lt;br /&gt;
* A configurable number of worker threads created at construction time via &#039;&#039;&#039;ThreadPool(size_t threads)&#039;&#039;&#039;.&lt;br /&gt;
* A task queue protected by a &#039;&#039;&#039;std::mutex&#039;&#039;&#039; and signaled via a &#039;&#039;&#039;std::condition_variable&#039;&#039;&#039;.&lt;br /&gt;
* A templated &#039;&#039;&#039;enqueue()&#039;&#039;&#039; method that accepts any callable with arguments and returns a &#039;&#039;&#039;std::future&#039;&#039;&#039; for the result, allowing callers to submit work and retrieve results asynchronously.&lt;br /&gt;
* Worker threads that loop indefinitely, waiting on the condition variable for new tasks. They exit cleanly when &#039;&#039;&#039;stop&#039;&#039;&#039; is set to true and the queue is drained.&lt;br /&gt;
* The destructor sets the stop flag, notifies all workers, and joins all threads to ensure clean shutdown.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Barrier&#039;&#039;&#039; implements a reusable synchronization barrier with:&lt;br /&gt;
* &#039;&#039;&#039;arrive_and_wait()&#039;&#039;&#039; -- Each thread increments a counter; when the counter reaches &#039;&#039;&#039;num_threads&#039;&#039;&#039;, the generation is advanced and all waiting threads are released via &#039;&#039;&#039;cv.notify_all()&#039;&#039;&#039;. Threads that arrive early wait on a condition variable gated by the generation counter, preventing spurious wakeups.&lt;br /&gt;
* &#039;&#039;&#039;reset(int new_num_threads)&#039;&#039;&#039; -- Dynamically changes the thread count, resets the counter, advances the generation to unblock any currently waiting threads, and notifies all.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;ThreadPool&#039;&#039;&#039; is used by &#039;&#039;&#039;ExtTPContext&#039;&#039;&#039; (tensor parallelism context) to dispatch parallel operations across multiple GPU devices. The &#039;&#039;&#039;Barrier&#039;&#039;&#039; is used for cross-device synchronization points during tensor-parallel inference, ensuring all devices have completed a phase before proceeding.&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
* &#039;&#039;&#039;Repository:&#039;&#039;&#039; [https://github.com/turboderp-org/exllamav2 Turboderp_org_Exllamav2]&lt;br /&gt;
* &#039;&#039;&#039;File:&#039;&#039;&#039; [https://github.com/turboderp-org/exllamav2/blob/main/exllamav2/exllamav2_ext/cpp/threadpool.h exllamav2/exllamav2_ext/cpp/threadpool.h]&lt;br /&gt;
* &#039;&#039;&#039;Lines:&#039;&#039;&#039; 1-124&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
class ThreadPool&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
    ThreadPool(size_t threads);&lt;br /&gt;
    ~ThreadPool();&lt;br /&gt;
&lt;br /&gt;
    template&amp;lt;class F, class... Args&amp;gt;&lt;br /&gt;
    auto enqueue(F&amp;amp;&amp;amp; f, Args&amp;amp;&amp;amp;... args)&lt;br /&gt;
        -&amp;gt; std::future&amp;lt;typename std::result_of&amp;lt;F(Args...)&amp;gt;::type&amp;gt;;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
class Barrier&lt;br /&gt;
{&lt;br /&gt;
public:&lt;br /&gt;
    Barrier(int num_threads);&lt;br /&gt;
    void arrive_and_wait();&lt;br /&gt;
    void reset(int new_num_threads);&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;quot;threadpool.h&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Class !! Method !! Input !! Output !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;ThreadPool&#039;&#039;&#039; || constructor || size_t threads || ThreadPool instance || Creates pool with specified number of worker threads&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;ThreadPool&#039;&#039;&#039; || enqueue(f, args...) || Callable + arguments || std::future&amp;lt;return_type&amp;gt; || Submits task, returns future for asynchronous result retrieval&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;ThreadPool&#039;&#039;&#039; || destructor || -- || -- || Sets stop flag, notifies all workers, joins all threads&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Barrier&#039;&#039;&#039; || constructor || int num_threads || Barrier instance || Creates barrier for the specified number of participating threads&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Barrier&#039;&#039;&#039; || arrive_and_wait() || -- || -- || Blocks until all threads have arrived; uses generation counter to prevent spurious wakeups&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Barrier&#039;&#039;&#039; || reset(new_num_threads) || int new_num_threads || -- || Resets barrier for a new thread count, unblocks any waiting threads&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;quot;threadpool.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Create a pool with 4 worker threads&lt;br /&gt;
ThreadPool pool(4);&lt;br /&gt;
&lt;br /&gt;
// Submit tasks and collect futures&lt;br /&gt;
std::vector&amp;lt;std::future&amp;lt;int&amp;gt;&amp;gt; results;&lt;br /&gt;
for (int i = 0; i &amp;lt; 8; i++) {&lt;br /&gt;
    results.push_back(pool.enqueue([i] {&lt;br /&gt;
        // perform work on device i % 4&lt;br /&gt;
        return i * i;&lt;br /&gt;
    }));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Collect results&lt;br /&gt;
for (auto&amp;amp; f : results) {&lt;br /&gt;
    int result = f.get();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Barrier usage for synchronizing 4 threads&lt;br /&gt;
Barrier barrier(4);&lt;br /&gt;
// Each thread calls:&lt;br /&gt;
barrier.arrive_and_wait();  // blocks until all 4 arrive&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
* [[Implementation:Turboderp_org_Exllamav2_Ext_TP_H]] -- Tensor parallelism context that uses ThreadPool and Barrier&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
	<entry>
		<id>https://leeroopedia.com/index.php?title=Implementation:Turboderp_org_Exllamav2_Softmax_AVX2&amp;diff=30768</id>
		<title>Implementation:Turboderp org Exllamav2 Softmax AVX2</title>
		<link rel="alternate" type="text/html" href="https://leeroopedia.com/index.php?title=Implementation:Turboderp_org_Exllamav2_Softmax_AVX2&amp;diff=30768"/>
		<updated>2026-09-27T10:53:10Z</updated>

		<summary type="html">&lt;p&gt;Agent: Sync from local file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PageInfo|type=Implementation|title=Turboderp_org_Exllamav2_Softmax_AVX2}}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; margin-left:1em; width:300px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Knowledge Sources&lt;br /&gt;
|&lt;br /&gt;
* [https://github.com/turboderp-org/exllamav2 Turboderp_org_Exllamav2]&lt;br /&gt;
|-&lt;br /&gt;
! Domains&lt;br /&gt;
| [[domain::Sampling]], [[domain::SIMD]], [[domain::Performance_Optimization]]&lt;br /&gt;
|-&lt;br /&gt;
! Last Updated&lt;br /&gt;
| [[last_updated::2026-02-15 00:00 GMT]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
AVX2-optimized implementation of the softmax function that converts raw logits into a probability distribution using SIMD vectorized operations for high-throughput CPU-side sampling.&lt;br /&gt;
&lt;br /&gt;
=== Description ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;softmax_cpu_avx2&#039;&#039;&#039; provides a performance-critical softmax implementation that leverages Intel AVX2 (256-bit SIMD) intrinsics to process 8 float values simultaneously. The function aligns the vocabulary size to a 32-element boundary for optimal vector processing.&lt;br /&gt;
&lt;br /&gt;
The implementation handles three distinct code paths based on the &#039;&#039;&#039;exponent&#039;&#039;&#039; parameter:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;exponent == 2.0f (fast path):&#039;&#039;&#039; Uses a squared subtraction approach where logit differences from the maximum are squared, negated via XOR with a sign mask, and then multiplied by the inverse temperature before exponentiation. This avoids the expensive &#039;&#039;&#039;powf&#039;&#039;&#039; call entirely by leveraging SIMD multiply and XOR operations.&lt;br /&gt;
* &#039;&#039;&#039;exponent == 1.0f (standard path):&#039;&#039;&#039; The classic softmax with temperature. If temperature is exactly 1.0, the inverse-temperature multiply is skipped as an additional optimization. Uses &#039;&#039;&#039;exp256_ps&#039;&#039;&#039; (vectorized exp from &#039;&#039;&#039;avx_mathfun.h&#039;&#039;&#039;) for SIMD exponentiation.&lt;br /&gt;
* &#039;&#039;&#039;exponent != 1.0f and != 2.0f (fallback path):&#039;&#039;&#039; Falls back to scalar &#039;&#039;&#039;powf&#039;&#039;&#039; and &#039;&#039;&#039;expf&#039;&#039;&#039; calls per element, as arbitrary exponents cannot be efficiently vectorized.&lt;br /&gt;
&lt;br /&gt;
The normalization phase accumulates the exponential sum across 8 SIMD lanes, reduces it to a scalar, and then divides all probabilities by the sum using vectorized multiply with the reciprocal.&lt;br /&gt;
&lt;br /&gt;
On non-x86 platforms (e.g., aarch64), a dummy fallback function is compiled that returns 0, ensuring the build does not fail.&lt;br /&gt;
&lt;br /&gt;
=== Usage ===&lt;br /&gt;
&lt;br /&gt;
This function is called as a drop-in replacement for the scalar &#039;&#039;&#039;softmax_cpu&#039;&#039;&#039; when the build detects AVX2 support (&#039;&#039;&#039;USE_AVX2&#039;&#039;&#039; preprocessor macro). It is used in the sampling pipeline to convert model logits into probabilities before top-K, top-P, and other filtering stages are applied.&lt;br /&gt;
&lt;br /&gt;
== Code Reference ==&lt;br /&gt;
&lt;br /&gt;
=== Source Location ===&lt;br /&gt;
* &#039;&#039;&#039;Repository:&#039;&#039;&#039; [https://github.com/turboderp-org/exllamav2 Turboderp_org_Exllamav2]&lt;br /&gt;
* &#039;&#039;&#039;File:&#039;&#039;&#039; [https://github.com/turboderp-org/exllamav2/blob/main/exllamav2/exllamav2_ext/cpp/sampling_avx2.cpp exllamav2/exllamav2_ext/cpp/sampling_avx2.cpp]&lt;br /&gt;
* &#039;&#039;&#039;Lines:&#039;&#039;&#039; 1-166&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
AVX2_TARGET&lt;br /&gt;
int softmax_cpu_avx2(&lt;br /&gt;
    const int vocab_size,&lt;br /&gt;
    const float temperature,&lt;br /&gt;
    const float* logits,&lt;br /&gt;
    const bool* logits_filter,&lt;br /&gt;
    const float exponent,&lt;br /&gt;
    float* output&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;quot;sampling_avx2.h&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O Contract ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Type !! Direction !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;vocab_size&#039;&#039;&#039; || const int || in || Size of the vocabulary (number of logits)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;temperature&#039;&#039;&#039; || const float || in || Softmax temperature; higher values produce more uniform distributions&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;logits&#039;&#039;&#039; || const float* || in || Raw logit values from the model, length = vocab_size&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;logits_filter&#039;&#039;&#039; || const bool* || in || Optional filter mask; NULL means all tokens allowed, true = allowed&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;exponent&#039;&#039;&#039; || const float || in || Exponent applied to logit differences (1.0 = standard, 2.0 = quadratic fast path)&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;output&#039;&#039;&#039; || float* || out || Probability distribution, must be aligned to 32 floats (vocab_size_aligned)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Return !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| max logit index || int || Index of the token with the highest raw logit value&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Usage Examples ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;quot;sampling_avx2.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Allocate aligned output buffer (32-element aligned)&lt;br /&gt;
int vocab_size = 32000;&lt;br /&gt;
int aligned_size = ((vocab_size + 31) / 32) * 32;&lt;br /&gt;
float* output = (float*)aligned_alloc(32, aligned_size * sizeof(float));&lt;br /&gt;
&lt;br /&gt;
// Standard softmax with temperature=0.8&lt;br /&gt;
int max_idx = softmax_cpu_avx2(vocab_size, 0.8f, logits, nullptr, 1.0f, output);&lt;br /&gt;
&lt;br /&gt;
// Quadratic softmax (exponent=2.0) with logit filtering&lt;br /&gt;
bool logit_filter[32000];&lt;br /&gt;
// ... set filter values ...&lt;br /&gt;
int max_idx2 = softmax_cpu_avx2(vocab_size, 1.0f, logits, logit_filter, 2.0f, output);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Related Pages ==&lt;br /&gt;
* [[Implementation:Turboderp_org_Exllamav2_Sampling_H]] -- Header declaring all sampling function signatures&lt;br /&gt;
* [[Implementation:Turboderp_org_Exllamav2_Ext_Norm]] -- GPU normalization operations&lt;br /&gt;
&lt;br /&gt;
[[Category:Implementations]]&lt;/div&gt;</summary>
		<author><name>Agent</name></author>
	</entry>
</feed>