VAB is a local REST API server that brings semantic search to your DAZ Studio content library. It indexes your installed products into a vector database and exposes a query interface so you can find assets by meaning rather than by name — "asian city streets", "soft fantasy lighting", "gritty cyberpunk outfit" — across your entire collection.
The server is the product. A web UI is included as a reference client and demonstration of what the API can do, but the API itself is the interface designed for integration, automation, and building your own tools on top of.
Note
The reference web UI uses the Script Server DAZ plugin to allow users to open the DAZ content manager to a product page in a running DAZ Studio directly from a search result. It's not strictly necessary for searching, but to get full benefit consider installing the plugin. It's free and available here: https://github.com/bluemoonfoundry/daz-script-server/releases/latest
- Semantic search — query your library with natural language; results ranked by meaning, not keywords
- Hybrid filtering — combine a semantic query with hard filters on category, artist, and compatible figure
- Full product index — browsable paginated catalogue with sorting and filtering
- DAZ Studio integration — open products in the Content Library, load assets into scenes, and read content directories from a running DAZ Studio instance via the DAZ Script Server plugin
- Incremental indexing — tracks what's already indexed; re-runs only process new products
- Demo mode — runs with mock data and no database, useful for UI development and trying the interface
- Web UI — a reference browser client served at
/whenui/dist/is present
Three distribution formats are available from the Releases page.
Requires Python 3.11+ installed. No other setup.
-
Download
vab-release.zipand unzip to a permanent location (e.g.C:\Tools\VAB). -
Open a terminal in that folder and run the installer:
python install.py
-
The installer will ask whether you want CPU-only or CUDA PyTorch. Choose CPU if you are unsure — you can switch later by re-running
install.py. For CUDA version guidance consult pytorch.org/get-started/locally. -
Once installation finishes, start the server:
run.bat # Windows ./run.sh # Mac / Linux
The run scripts support optional flags:
--demo- Run in demo mode (mock data, no database required)--dev-ui- Run with Vite dev server for UI development (requiresui/src/)
Command API Server UI Access URL ./run.shProduction Pre-built http://localhost:8000./run.sh --demoDemo mode Pre-built http://localhost:8000./run.sh --dev-uiProduction Vite (hot-reload) http://localhost:5173./run.sh --demo --dev-uiDemo mode Vite (hot-reload) http://localhost:5173Interactive API docs are always available at
http://localhost:8000/docs
To switch between CPU and GPU later, just re-run
python install.py— it will ask again and reinstall the correct torch build.
pip install "visual-asset-browser[local_llm]"
pip install torch --index-url https://download.pytorch.org/whl/cpu
vab serverThe vab command is added to your PATH by pip. Replace the torch index URL with your CUDA version if needed (see pytorch.org/get-started/locally).
Download vab-windows.zip, unzip it, and run vab\vab.exe server. No Python installation needed.
The standalone executable is large (~2–3 GB) because PyTorch is bundled inside it. Options A and B are faster to download.
Important
After installation, you need to index your content before the UI will display anything. The server will run, but your library will be empty until you build the index. See Production setup below for configuration and indexing instructions. To try the UI immediately with mock data, use Demo mode instead.
Demo mode runs the server with built-in mock data. No database or configuration required — useful for trying the UI or developing against the API.
# From release zip
run.bat --demo # Windows
./run.sh --demo # Mac/Linux
# From source or pip
python vab.py server --demo
vab server --demoOnce started:
- Web UI:
http://localhost:8000 - API docs:
http://localhost:8000/docs
cp .env.example .env| Variable | Description |
|---|---|
DAZ_STUDIO_EXE_PATH |
Full path to DAZStudio.exe |
DB_HOST / DB_PORT |
DAZ CMS PostgreSQL host and port (defaults: 127.0.0.1 / 17237) |
DB_NAME / DB_USER / DB_PASS |
DAZ CMS credentials |
EMBEDDING_DEVICE |
cpu (default) or cuda for GPU acceleration |
The DAZ CMS database is installed and managed by DAZ Studio — you do not need to set it up. Run DAZ Studio at least once before indexing.
python vab.py loadPulls products from the DAZ CMS database, generates embeddings, and stores everything in the local SQLite + ChromaDB index. First run is slow (embedding generation); subsequent runs are incremental.
python vab.py load --force # full rebuild from scratch
python vab.py load --limit 100 # process only 100 products (testing)
python vab.py load --phase etl # ETL only, skip embeddingpython vab.py server
python vab.py server --host 0.0.0.0 --port 9000All endpoints are under /api/v1/. The server exposes interactive Swagger docs at /docs and ReDoc at /redoc — these are the authoritative reference for request/response schemas.
Base URL (default): http://localhost:8000
Health check and index counts. Polled frequently by the UI.
{
"status": "ok",
"postgres_connected": true,
"sqlite_connected": true,
"chromadb_connected": true,
"postgres_count": 4821,
"sqlite_count": 4821,
"chromadb_count": 4821,
"new_products": 0,
"update_available": false
}Trigger an incremental re-index. Returns immediately; indexing runs in the background.
// Request body
{ "force": false }
// Response 202
{ "message": "Update process started.", "task_id": "uuid" }Set force: true to rebuild the entire index from scratch.
Status of the most recently triggered update. Poll this while an update is running.
{
"running": true,
"progress": "Embedding product 412 of 800…",
"stage": "embed",
"error": null,
"last_run": "2026-05-05T12:00:00+00:00"
}Status for a specific background task by ID (returned by POST /api/v1/update).
Paginated product catalogue.
| Parameter | Type | Default | Description |
|---|---|---|---|
page |
int | 1 | Page number (1-based) |
page_size |
int | 25 | Results per page (max 10000) |
category |
string | — | Filter by category |
artist |
string | — | Filter by artist |
compatible_figure |
string | — | Filter by compatible figure |
sort_by |
string | name |
Field to sort by |
sort_dir |
string | asc |
asc or desc |
{
"products": [ /* product objects */ ],
"total": 4821,
"page": 1,
"page_size": 25,
"total_pages": 193
}Full details for a single product by SKU.
{
"sku": "54841",
"name": "dForce Night Runner Outfit for Genesis 8",
"artist": ["Daz Originals", "GolaM"],
"category": "People",
"subcategories": ["Clothing"],
"tags": ["sci-fi", "cyberpunk", "outfit"],
"compatible_figures": ["Genesis 8 Female"],
"store_url": "https://www.daz3d.com/...",
"install_date": "2025-01-15T10:00:00",
"is_installed": true,
"asset_count": 0
}Asset file paths for a product, with resolved absolute paths where the files can be found on disk.
Navigate the DAZ Studio Content Library to this product. Uses the DAZ Script Server plugin if available, falls back to subprocess launch.
// Response
{ "success": true, "message": "Opened 'Night Runner' via DAZ Script Server.", "via": "plugin" }Semantic search with optional filters. Primary search endpoint for the UI.
// Request body
{
"query": "gritty cyberpunk street clothes",
"filters": {
"category": "People",
"artist": "Daz Originals",
"compatible_figures": "Genesis 9",
"is_installed": true
},
"limit": 25,
"min_relevance": 0.0
}
// Response
{
"results": [ /* product objects with relevance_score */ ],
"total": 12,
"query": "gritty cyberpunk street clothes",
"took_ms": 84
}All filter fields are optional. min_relevance filters out results below a score threshold (0.0 = no filtering).
Full-featured semantic search with multi-value filters. Designed for programmatic and MCP use.
// Request body
{
"prompt": "elegant fantasy gown",
"limit": 10,
"offset": 0,
"tags": ["fantasy", "gown"],
"artists": ["Daz Originals"],
"categories": ["Clothing"],
"compatible_figures": ["Genesis 9"],
"score_threshold": 1.0,
"sort_by": "relevance",
"sort_order": "descending"
}All filter arrays are optional. score_threshold is the maximum distance score (lower = more similar; 1.0 returns all results).
All distinct filter values present in the index. Use this to populate filter UI dropdowns.
{
"categories": ["Clothing", "Environments", "People", ...],
"artists": ["Daz Originals", "Renderosity", ...],
"compatible_figures": ["Genesis 9", "Genesis 8 Female", ...]
}Returns current configuration (environment + settings.json overlay). Password field is omitted.
Saves settings to settings.json. Only fields included in the request body are updated; omitted fields are left unchanged.
// Request body (all fields optional)
{
"cms_host": "localhost",
"cms_port": 17237,
"cms_db": "Content",
"cms_user": "dzcms",
"cms_password": "secret",
"cms_schema": "dzcontent",
"embedding_model": "mixedbread-ai/mxbai-embed-large-v1",
"query_model": "mixedbread-ai/mxbai-embed-large-v1",
"daz_script_server_url": "http://localhost:18811",
"daz_script_server_enabled": true
}Test a PostgreSQL connection with the given credentials. Accepts the same body as PUT /api/v1/settings.
// Response
{ "success": true, "message": "Connected in 12ms", "latency_ms": 12 }These endpoints require a running DAZ Studio instance with the DAZ Script Server plugin installed and enabled.
Probe whether the DAZ Script Server plugin is running.
{ "plugin_detected": true, "plugin_url": "http://localhost:18811", "version": "1.0" }Returns the content library directories from the running DAZ Studio instance.
| Parameter | Type | Default | Description |
|---|---|---|---|
refresh |
bool | false | Force re-query from DAZ Studio |
{ "dirs": ["C:/Users/.../Documents/DAZ 3D/Studio/My Library", ...], "count": 3 }Load an asset file into the current DAZ Studio scene.
// Request body
{ "path": "C:/Users/.../My Library/People/Genesis 9/Starter Essentials/Figures/Genesis 9.duf" }
// Response
{ "success": true, "message": "Loaded 'Genesis 9.duf' into scene.", "detail": { ... } }Asset file records for a product with resolved absolute paths. Searches both PostgreSQL content roots and DAZ Script Server content directories to find files on disk.
{
"sku": "54841",
"files": [
{
"path": "/People/Genesis 8 Female/Clothing",
"filename": "Night Runner Jacket.duf",
"resolved_path": "C:/Users/.../My Library/People/Genesis 8 Female/Clothing/Night Runner Jacket.duf"
}
]
}resolved_path is null if the file cannot be found on disk.
Serve the companion thumbnail image for a DAZ asset file. DAZ Studio places thumbnails alongside content files with the same filename and a .png extension.
Returns the PNG directly, or 404 if no thumbnail exists.
Open the system file explorer with the given file selected (Windows Explorer, Finder, or xdg-open).
// Request body
{ "path": "C:/Users/.../Night Runner Jacket.duf" }Full database statistics including category, artist, and tag histograms. Expensive — intended for dashboards and MCP clients, not frequent polling.
Content root directories from the DAZ CMS PostgreSQL database.
{ "content_roots": ["C:/Users/.../Documents/DAZ 3D/Studio/My Library"] }All commands run via python vab.py <command> (or vab <command> if installed via pip).
python vab.py # show help
python vab.py <command> --help # per-command help| Command | Description |
|---|---|
server |
Start the API server |
load |
Build / update the search index from DAZ CMS |
query |
Semantic search from the terminal |
stats |
Print index summary and histograms |
openproduct |
Open a product in DAZ Studio Content Library |
python vab.py server [--host HOST] [--port PORT] [--demo]python vab.py load [--force] [--all] [--limit N] [--phase {etl,embed,all}]python vab.py query "elegant gown" [--categories Clothing] [--compatible_figures "Genesis 9"]
[--artists "Daz Originals"] [--tags tag1 tag2]
[--limit N] [--score F] [--sort-by relevance|name]
[--sort-order ascending|descending]
[--format pretty|json|table]python vab.py statspython vab.py openproduct --product "dForce Night Runner Outfit"CPU-only PyTorch is installed by default. To switch to a CUDA build for faster indexing:
# Replace cu121 with your CUDA version (cu118, cu121, cu124, etc.)
pip install torch --index-url https://download.pytorch.org/whl/cu121Also set EMBEDDING_DEVICE=cuda in your .env file.
Find your CUDA version in the NVIDIA Control Panel under Help → System Information.
- Python 3.11+
- Node.js 18+ (for the UI)
- Git with submodule support
git clone https://github.com/bluemoonfoundry/daz-content-browser.git
cd daz-content-browser
make install # Python deps + UI node modules
make install-torch-cpu # CPU PyTorch (or install CUDA version manually)
make build # build UI into ui/dist/For development, you can run:
| Command | Mode | UI | Access URL |
|---|---|---|---|
./run.sh |
Production | Pre-built from ui/dist/ |
http://localhost:8000 |
./run.sh --demo |
Demo | Pre-built from ui/dist/ |
http://localhost:8000 |
./run.sh --dev-ui |
Production | Vite with hot-reload | http://localhost:5173 |
./run.sh --demo --dev-ui |
Demo | Vite with hot-reload | http://localhost:5173 |
Note: The
--dev-uiflag requires theui/src/submodule to be present. Without it, use the pre-built UI at:8000.
| Target | Description |
|---|---|
install |
Install Python deps and UI node modules |
install-torch-cpu |
Install CPU-only PyTorch |
build |
Build the UI into ui/dist/ |
dev-server |
Run the API server at :8000 |
demo-server |
Run the server in demo mode |
dev-ui |
Run the Vite dev server at :5173 |
test |
Run smoke tests |
sync-ui |
Pull latest UI submodule commits |
release-zip |
Build dist/vab-release.zip |
release-wheel |
Build pip-installable wheel into dist/ |
release-exe |
Build standalone Windows executable via PyInstaller |
gh-release |
Publish dist/ artifacts to a GitHub release |
clean |
Remove ui/dist/, dist/, src/ui_dist/ |
make build # required first — populates ui/dist/
make release-zip # → dist/vab-release.zip
make release-wheel # → dist/visual_asset_browser-*.whl
make release-exe # → dist/vab/vab.exe (~2-3 GB)
# Publish to GitHub Releases
make gh-release VERSION=v1.0.0 TITLE="Initial Release" NOTES="First public release"
# Update an existing release
make gh-release VERSION=v1.0.0 UPDATE=1 NOTES="Fixed wheel packaging"TITLE defaults to VERSION if omitted. All *.zip and *.whl files in dist/ are attached. The PyInstaller output directory (dist/vab/) is zipped automatically if present.