A Thousand Words is a captioning suite that combines many different captioning models in one place, with a GUI, CLI and input args.
13
stars
40
commits
Python
primary language
Aug 22, 2026
updated
A powerful, customizable, and user-friendly batch captioning tool for VLM (Vision Language Models). Designed for dataset creation, this tool supports 20+ state-of-the-art models and versions, offering both a feature-rich GUI and a fully scriptable CLI commands.
Run the setup script:
setup.bat
This creates a virtual environment (venv), upgrades pip, and installs uv (fast package installer).
It does not install the requirements. This need to be done manually after PyTorch and Flash Attention (optional) is installed.
After the virtual environment creation, the setup should leave you with the virtual environment activated. It should say (venv) at the start of your console. Ensure the remaining steps is done with the virtual environment active. You can also use the venv_activate.bat script to activate the environment.
Install PyTorch: Visit PyTorch Get Started and select your CUDA version.
Example for CUDA 12.8:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
Install Flash Attention (Optional, for better performance on some models): Download a pre-built wheel compatible with your setup:
Place the .whl file in your project folder, then install your version, for example:
pip install flash_attn-2.8.2+cu128torch2.8-cp312-cp312-win_amd64.whl
Install Requirements:
uv pip install -r requirements.txt
Note: This requires transformers 5.x. If the install fails to resolve it from PyPI, install it manually first, then re-run:
pip install git+https://github.com/huggingface/transformers.git uv pip install -r requirements.txt⚠️ Moondream compatibility: The Moondream models (Moondream 2 and Moondream 3) require
transformers <= 4.56.1and are not compatible with transformers 5.x. On 5.x they load without error but produce garbage/empty captions. Because the newer Qwen3.5 models require transformers 5.x, the two families cannot be used from the same environment — pintransformers==4.56.1if you need Moondream, or use a separate environment for it.
Launch the Application:
gui.bat
or
py gui.py
Server Mode:
To allow access from other computers on your network (and enable file zipping/downloads).
This also enables the REST API on port 8000 (/api/caption, /api/models, /api/health):
gui.bat --server
or
py gui.py --server
To enable only the REST API without network exposure (localhost only):
py gui.py --enable-api
Prefer containers? A Dockerfile and docker-compose.yml are included. This builds a CUDA 12.8 image (Flash Attention is installed from a prebuilt wheel, no compiling) and serves the GUI + REST API together on port 8585.
docker compose up --build
Then open http://localhost:8585 in your browser.
Note: The build downloads PyTorch and a prebuilt Flash Attention wheel (~a few GB total), so the first build takes a while on a slow connection. There's no source compilation, and layers are cached, so rebuilds are fast.
The compose file bind-mounts these host folders into the container, so they persist and are not baked into the image:
| Host path | Container path | Purpose |
|---|---|---|
./models | /app/models | Hugging Face cache/models (HF_HOME) — downloaded on first use |
./user | /app/user | User config and uploads |
./input | /app/input | Input images |
./src, ./gui.py, ./captioner.py | (same) | Live code, so edits apply without a rebuild |
Models download into ./models on first run and are reused afterward.
Gated models (and higher download rate limits) need an HF token. Copy .env.example to .env next to the compose file and set it:
HF_TOKEN=hf_your_token_here
Left unset, the container runs unauthenticated.
docker compose up -d --build # build and run in the background
docker compose logs -f # follow logs
docker compose down # stop and remove the container
The main workspace for image and video captioning:
Run multiple models on the same dataset for comparison or ensemble captioning:
Run various scripts and tools to manipulate and manage your files:
Augment small datasets with randomized variations:
Credit: a-l-e-x-d-s-9/stable_diffusion_tools
Analyze and organize images by aspect ratio for training optimization:
Extract and analyze image metadata:
Batch resize images with flexible options:
Manage prompt templates for quick access:
Configure global application defaults:
A detailed list of model properties and requirements to get an overview of what features the different models support.
| Model | Min VRAM | Speed | Tags | Natural Language | Custom Prompts | Versions | Video | License |
|---|---|---|---|---|---|---|---|---|
| WD14 Tagger | 8 GB (Sys) | 16 it/s | ✓ | ✓ | Apache 2.0 | |||
| JoyTag | 4 GB | 9.1 it/s | ✓ | Apache 2.0 | ||||
| JoyCaption | 20 GB | 1 it/s | ✓ | ✓ | ✓ | Unknown | ||
| Florence 2 Large | 4 GB | 3.7 it/s | ✓ | MIT | ||||
| MiaoshouAI Florence-2 | 4 GB | 3.3 it/s | ✓ | MIT | ||||
| MimoVL | 24 GB | 0.4 it/s | ✓ | ✓ | MIT | |||
| QwenVL 2.7B | 24 GB | 0.9 it/s | ✓ | ✓ | ✓ | Apache 2.0 | ||
| Qwen2-VL-7B Relaxed | 24 GB | 0.9 it/s | ✓ | ✓ | ✓ | Apache 2.0 | ||
| Qwen3-VL | 8 GB | 1.36 it/s | ✓ | ✓ | ✓ | ✓ | Apache 2.0 | |
| Qwen3.5-9B Gliese Abliterated | 24 GB | - | ✓ | ✓ | ✓ | Apache 2.0 | ||
| Moondream 1 | 8 GB | 0.44 it/s | ✓ | ✓ | Non-Commercial | |||
| Moondream 2 | 8 GB | 0.6 it/s | ✓ | ✓ | Apache 2.0 | |||
| Moondream 3 | 24 GB | 0.16 it/s | ✓ | ✓ | BSL 1.1 | |||
| PaliGemma 2 10B | 24 GB | 0.75 it/s | ✓ | ✓ | Gemma | |||
| Paligemma LongPrompt | 8 GB | 2 it/s | ✓ | ✓ | Gemma | |||
| Pixtral 12B | 16 GB | 0.17 it/s | ✓ | ✓ | ✓ | Apache 2.0 | ||
| SmolVLM | 4 GB | 1.5 it/s | ✓ | ✓ | ✓ | Apache 2.0 | ||
| SmolVLM 2 | 4 GB | 2 it/s | ✓ | ✓ | ✓ | ✓ | Apache 2.0 | |
| ToriiGate | 16 GB | 0.16 it/s | ✓ | ✓ | Apache 2.0 |
Note: Minimum VRAM estimates based on quantization and optimized batch sizes. Speed measured on RTX 5090.
| Parameter | Description | Typical Range |
|---|---|---|
| Temperature | Controls randomness. Lower = more deterministic, higher = more creative | 0.1 - 1.0 |
| Top-K | Limits vocabulary to top K tokens. Higher = more variety | 10 - 100 |
| Max Tokens | Maximum output length in tokens | 50 - 500 |
| Repetition Penalty | Reduces word/phrase repetition. Higher = less repetition | 1.0 - 1.5 |
| Feature | Description |
|---|---|
| Clean Text | Removes artifacts, normalizes spacing |
| Collapse Newlines | Converts multiple newlines to single line breaks |
| Normalize Text | Standardizes punctuation and formatting |
| Remove Chinese | Filters out Chinese characters (for English-only outputs) |
| Strip Loop | Detects and removes repetitive content loops |
| Strip Thinking Tags | Removes <think>...</think> reasoning blocks from chain-of-thought models |
| Option | Description |
|---|---|
| Prefix/Suffix | Add consistent text before/after every caption |
| Output Format | Choose between .txt, .json, or .caption file extensions |
| Overwrite | Replace existing caption files or skip |
| Recursive | Search subdirectories for images |
| Feature | Description | Models |
|---|---|---|
| Model Versions | Select model size/variant (e.g., 2B, 7B, quantized) | SmolVLM, Pixtral, WD14 |
| Model Modes | Special operation modes (Caption, Query, Detect, Point) | Moondream |
| Caption Length | Short/Normal/Long presets | JoyCaption |
| Flash Attention | Enable memory-efficient attention | Most transformer models |
| FPS | Frame rate for video processing | Video-capable models |
| Threshold | Tag confidence threshold (taggers only) | WD14, JoyTag |
To add new models or features, first READ GEMINI.md. It contains strict architectural rules:
src/config/models/*.yaml. Do not hardcode defaults in Python.BaseFeature and be registered in src/features.BaseCaptionModel in src/wrappers. Only implement _load_model and _run_inference.Process a local folder using the standard model default settings.
python captioner.py --model smolVLM --input ./input
Specify exact paths and customize output handling.
# Absolute path input, recursive search, overwrite existing captions
python captioner.py --model wd14 --input "C:\Images\Dataset" --recursive --overwrite
# Output to specific folder, custom prefix/suffix
python captioner.py --model smolVLM2 --input ./test_images --output ./results --prefix "photo of " --suffix ", 4k quality"
Fine-tune the model creativity and length.
# Creative settings
python captioner.py --model joycaption --input ./input --temperature 0.8 --top-k 60 --max-tokens 300
# Deterministic/Focused settings
python captioner.py --model qwen3_vl --input ./input --temperature 0.1 --repetition-penalty 1.2
Leverage unique features of different architectures.
Model Versions (Size/Variant selection)
python captioner.py --model smolVLM2 --model-version 2.2B
python captioner.py --model pixtral_12b --model-version "Quantized (nf4)"
Moondream Special Modes
# Query Mode: Ask questions about the image
python captioner.py --model moondream3 --model-mode Query --task-prompt "What color is the car?"
# Detection Mode: Get bounding boxes
python captioner.py --model moondream3 --model-mode Detect --task-prompt "person"
Video Processing
# Caption videos with strict frame rate control
python captioner.py --model qwen3_vl --input ./videos --fps 4 --flash-attention
Clean and format the output automatically.
python captioner.py --model paligemma2 --input ./input --clean-text --collapse-newlines --strip-thinking-tags --remove-chinese
Run a quick test on limited files with console output.
python captioner.py --model smolVLM --input ./input --input-limit 4 --print-console
40 commits
Python
99.3%
A Thousand Words is a captioning suite that combines many different captioning models in one place, with a GUI, CLI and input args.
13
stars
40
commits
Python
primary language
Aug 22, 2026
updated
A powerful, customizable, and user-friendly batch captioning tool for VLM (Vision Language Models). Designed for dataset creation, this tool supports 20+ state-of-the-art models and versions, offering both a feature-rich GUI and a fully scriptable CLI commands.
Run the setup script:
setup.bat
This creates a virtual environment (venv), upgrades pip, and installs uv (fast package installer).
It does not install the requirements. This need to be done manually after PyTorch and Flash Attention (optional) is installed.
After the virtual environment creation, the setup should leave you with the virtual environment activated. It should say (venv) at the start of your console. Ensure the remaining steps is done with the virtual environment active. You can also use the venv_activate.bat script to activate the environment.
Install PyTorch: Visit PyTorch Get Started and select your CUDA version.
Example for CUDA 12.8:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
Install Flash Attention (Optional, for better performance on some models): Download a pre-built wheel compatible with your setup:
Place the .whl file in your project folder, then install your version, for example:
pip install flash_attn-2.8.2+cu128torch2.8-cp312-cp312-win_amd64.whl
Install Requirements:
uv pip install -r requirements.txt
Note: This requires transformers 5.x. If the install fails to resolve it from PyPI, install it manually first, then re-run:
pip install git+https://github.com/huggingface/transformers.git uv pip install -r requirements.txt⚠️ Moondream compatibility: The Moondream models (Moondream 2 and Moondream 3) require
transformers <= 4.56.1and are not compatible with transformers 5.x. On 5.x they load without error but produce garbage/empty captions. Because the newer Qwen3.5 models require transformers 5.x, the two families cannot be used from the same environment — pintransformers==4.56.1if you need Moondream, or use a separate environment for it.
Launch the Application:
gui.bat
or
py gui.py
Server Mode:
To allow access from other computers on your network (and enable file zipping/downloads).
This also enables the REST API on port 8000 (/api/caption, /api/models, /api/health):
gui.bat --server
or
py gui.py --server
To enable only the REST API without network exposure (localhost only):
py gui.py --enable-api
Prefer containers? A Dockerfile and docker-compose.yml are included. This builds a CUDA 12.8 image (Flash Attention is installed from a prebuilt wheel, no compiling) and serves the GUI + REST API together on port 8585.
docker compose up --build
Then open http://localhost:8585 in your browser.
Note: The build downloads PyTorch and a prebuilt Flash Attention wheel (~a few GB total), so the first build takes a while on a slow connection. There's no source compilation, and layers are cached, so rebuilds are fast.
The compose file bind-mounts these host folders into the container, so they persist and are not baked into the image:
| Host path | Container path | Purpose |
|---|---|---|
./models | /app/models | Hugging Face cache/models (HF_HOME) — downloaded on first use |
./user | /app/user | User config and uploads |
./input | /app/input | Input images |
./src, ./gui.py, ./captioner.py | (same) | Live code, so edits apply without a rebuild |
Models download into ./models on first run and are reused afterward.
Gated models (and higher download rate limits) need an HF token. Copy .env.example to .env next to the compose file and set it:
HF_TOKEN=hf_your_token_here
Left unset, the container runs unauthenticated.
docker compose up -d --build # build and run in the background
docker compose logs -f # follow logs
docker compose down # stop and remove the container
The main workspace for image and video captioning:
Run multiple models on the same dataset for comparison or ensemble captioning:
Run various scripts and tools to manipulate and manage your files:
Augment small datasets with randomized variations:
Credit: a-l-e-x-d-s-9/stable_diffusion_tools
Analyze and organize images by aspect ratio for training optimization:
Extract and analyze image metadata:
Batch resize images with flexible options:
Manage prompt templates for quick access:
Configure global application defaults:
A detailed list of model properties and requirements to get an overview of what features the different models support.
| Model | Min VRAM | Speed | Tags | Natural Language | Custom Prompts | Versions | Video | License |
|---|---|---|---|---|---|---|---|---|
| WD14 Tagger | 8 GB (Sys) | 16 it/s | ✓ | ✓ | Apache 2.0 | |||
| JoyTag | 4 GB | 9.1 it/s | ✓ | Apache 2.0 | ||||
| JoyCaption | 20 GB | 1 it/s | ✓ | ✓ | ✓ | Unknown | ||
| Florence 2 Large | 4 GB | 3.7 it/s | ✓ | MIT | ||||
| MiaoshouAI Florence-2 | 4 GB | 3.3 it/s | ✓ | MIT | ||||
| MimoVL | 24 GB | 0.4 it/s | ✓ | ✓ | MIT | |||
| QwenVL 2.7B | 24 GB | 0.9 it/s | ✓ | ✓ | ✓ | Apache 2.0 | ||
| Qwen2-VL-7B Relaxed | 24 GB | 0.9 it/s | ✓ | ✓ | ✓ | Apache 2.0 | ||
| Qwen3-VL | 8 GB | 1.36 it/s | ✓ | ✓ | ✓ | ✓ | Apache 2.0 | |
| Qwen3.5-9B Gliese Abliterated | 24 GB | - | ✓ | ✓ | ✓ | Apache 2.0 | ||
| Moondream 1 | 8 GB | 0.44 it/s | ✓ | ✓ | Non-Commercial | |||
| Moondream 2 | 8 GB | 0.6 it/s | ✓ | ✓ | Apache 2.0 | |||
| Moondream 3 | 24 GB | 0.16 it/s | ✓ | ✓ | BSL 1.1 | |||
| PaliGemma 2 10B | 24 GB | 0.75 it/s | ✓ | ✓ | Gemma | |||
| Paligemma LongPrompt | 8 GB | 2 it/s | ✓ | ✓ | Gemma | |||
| Pixtral 12B | 16 GB | 0.17 it/s | ✓ | ✓ | ✓ | Apache 2.0 | ||
| SmolVLM | 4 GB | 1.5 it/s | ✓ | ✓ | ✓ | Apache 2.0 | ||
| SmolVLM 2 | 4 GB | 2 it/s | ✓ | ✓ | ✓ | ✓ | Apache 2.0 | |
| ToriiGate | 16 GB | 0.16 it/s | ✓ | ✓ | Apache 2.0 |
Note: Minimum VRAM estimates based on quantization and optimized batch sizes. Speed measured on RTX 5090.
| Parameter | Description | Typical Range |
|---|---|---|
| Temperature | Controls randomness. Lower = more deterministic, higher = more creative | 0.1 - 1.0 |
| Top-K | Limits vocabulary to top K tokens. Higher = more variety | 10 - 100 |
| Max Tokens | Maximum output length in tokens | 50 - 500 |
| Repetition Penalty | Reduces word/phrase repetition. Higher = less repetition | 1.0 - 1.5 |
| Feature | Description |
|---|---|
| Clean Text | Removes artifacts, normalizes spacing |
| Collapse Newlines | Converts multiple newlines to single line breaks |
| Normalize Text | Standardizes punctuation and formatting |
| Remove Chinese | Filters out Chinese characters (for English-only outputs) |
| Strip Loop | Detects and removes repetitive content loops |
| Strip Thinking Tags | Removes <think>...</think> reasoning blocks from chain-of-thought models |
| Option | Description |
|---|---|
| Prefix/Suffix | Add consistent text before/after every caption |
| Output Format | Choose between .txt, .json, or .caption file extensions |
| Overwrite | Replace existing caption files or skip |
| Recursive | Search subdirectories for images |
| Feature | Description | Models |
|---|---|---|
| Model Versions | Select model size/variant (e.g., 2B, 7B, quantized) | SmolVLM, Pixtral, WD14 |
| Model Modes | Special operation modes (Caption, Query, Detect, Point) | Moondream |
| Caption Length | Short/Normal/Long presets | JoyCaption |
| Flash Attention | Enable memory-efficient attention | Most transformer models |
| FPS | Frame rate for video processing | Video-capable models |
| Threshold | Tag confidence threshold (taggers only) | WD14, JoyTag |
To add new models or features, first READ GEMINI.md. It contains strict architectural rules:
src/config/models/*.yaml. Do not hardcode defaults in Python.BaseFeature and be registered in src/features.BaseCaptionModel in src/wrappers. Only implement _load_model and _run_inference.Process a local folder using the standard model default settings.
python captioner.py --model smolVLM --input ./input
Specify exact paths and customize output handling.
# Absolute path input, recursive search, overwrite existing captions
python captioner.py --model wd14 --input "C:\Images\Dataset" --recursive --overwrite
# Output to specific folder, custom prefix/suffix
python captioner.py --model smolVLM2 --input ./test_images --output ./results --prefix "photo of " --suffix ", 4k quality"
Fine-tune the model creativity and length.
# Creative settings
python captioner.py --model joycaption --input ./input --temperature 0.8 --top-k 60 --max-tokens 300
# Deterministic/Focused settings
python captioner.py --model qwen3_vl --input ./input --temperature 0.1 --repetition-penalty 1.2
Leverage unique features of different architectures.
Model Versions (Size/Variant selection)
python captioner.py --model smolVLM2 --model-version 2.2B
python captioner.py --model pixtral_12b --model-version "Quantized (nf4)"
Moondream Special Modes
# Query Mode: Ask questions about the image
python captioner.py --model moondream3 --model-mode Query --task-prompt "What color is the car?"
# Detection Mode: Get bounding boxes
python captioner.py --model moondream3 --model-mode Detect --task-prompt "person"
Video Processing
# Caption videos with strict frame rate control
python captioner.py --model qwen3_vl --input ./videos --fps 4 --flash-attention
Clean and format the output automatically.
python captioner.py --model paligemma2 --input ./input --clean-text --collapse-newlines --strip-thinking-tags --remove-chinese
Run a quick test on limited files with console output.
python captioner.py --model smolVLM --input ./input --input-limit 4 --print-console
40 commits
Python
99.3%