-
Notifications
You must be signed in to change notification settings - Fork 14
Dev Server README
Auto-generated from
server/README.md. Do not edit this page manually.
This is the Python-based core of LrGeniusAI. It acts as the bridge between Adobe Lightroom Classic (Lua) and various AI models, handling image processing, metadata storage, and high-speed semantic search.
- 📂 Database Management: Stores image metadata, AI-generated descriptions, and vector embeddings in a local SQLite database to ensure blazing-fast retrieval without re-scanning images.
-
🧠 AI Orchestration: - Interfaces with Cloud APIs (Google Gemini, Vertex AI, OpenAI).
- Connects to Local LLMs via Ollama and LM Studio (enhancing privacy and saving costs).
-
🔎 Semantic Search Engine: Uses
vertexai/SigLip2to generate image embeddings. This allows users to search their Lightroom catalog using natural language descriptions instead of just keywords. -
🎭 Face Intelligence: Provides face detection and recognition capabilities (powered by
Insightface). - ⚙️ Metadata Sync: Handles the import of existing keywords and metadata from Lightroom to build a comprehensive search index.
The server is built with Python and designed to run as a local background process (provided as a standalone .exe for Windows or a binary for macOS).
- API Framework: FastAPI / Flask-based REST interface for communication with the Lightroom Lua plugin.
-
Computer Vision: -
open-clip-torch: For generating semantic embeddings.-
Insightface: For advanced face detection and recognition. -
vertexai: For even better semantic embeddings.
-
- Database: SQLite (local-first approach).
- Task Handling: Efficient processing of batch image analysis.
The backend exposes dedicated database endpoints for status and backup operations.
Returns aggregated counters for the current backend database, including:
- total indexed photos
- photos with SigLIP embeddings
- photos with title / caption / keywords
- photos with Vertex AI embeddings
- total indexed faces
- total detected persons
Creates and returns a ZIP backup of the persistent backend data directory. This includes the Chroma data as well as accompanying JSON and SQLite files stored under the configured DB path.
Recommended use cases:
- before one-time DB migrations
- before moving or rebuilding the backend host
- before larger maintenance work on the server
The ZIP is created temporarily on the server for download and removed again after the response is sent.
In Plug-in Manager -> LrGeniusAI -> Backend Server, the button Download DB backup downloads this ZIP from the backend and reveals the saved file in Finder or Explorer.
If you run the backend remotely via Docker Compose, authenticate inside the container so Vertex AI uses Application Default Credentials (ADC) from the same runtime that executes the Python code.
The Compose file mounts ./gcloud to /root/.config/gcloud, which keeps the active gcloud config and application_default_credentials.json persistent across container restarts and rebuilds.
mkdir -p gcloud
docker compose up -d --build
docker compose exec geniusai-server gcloud config set project YOUR_PROJECT_ID
docker compose exec geniusai-server gcloud auth application-default login
docker compose exec geniusai-server gcloud auth application-default print-access-tokenIf the server is only reachable via SSH and has no browser, use:
docker compose exec geniusai-server gcloud auth application-default login --no-browserThen complete the remote bootstrap flow on a second trusted machine with a browser and Google Cloud CLI installed.
- Do not set
GOOGLE_APPLICATION_CREDENTIALSif you want the backend to use ADC created bygcloud auth application-default login. - Set
Vertex AI Project IDandVertex AI Locationin the Lightroom plugin settings, or provideGOOGLE_CLOUD_PROJECT/VERTEX_LOCATIONas environment variables. - For fully non-interactive deployments, a service account via
GOOGLE_APPLICATION_CREDENTIALSis still the better option.
When running the backend in Docker (or any long‑lived environment), you can enable optional background housekeeping tasks using environment variables.
The server can automatically re‑cluster face embeddings in the background, using the same logic as the POST /faces/cluster endpoint:
-
GENIUSAI_FACES_CLUSTER_ENABLED-
true/1/yes/onto enable. - Default: disabled.
-
-
GENIUSAI_FACES_CLUSTER_INTERVAL- Interval in seconds between clustering runs.
- Default:
3600(1 hour). Minimum effective interval is 60 seconds.
-
GENIUSAI_FACES_CLUSTER_DISTANCE- Cosine distance threshold, same scale as Immich “Maximum recognition distance”.
- Typical range:
0.45–0.65. Default:0.5.
-
GENIUSAI_FACES_CLUSTER_MIN_FACES- Minimum number of faces required to form a person cluster (DBSCAN mode).
- Example:
3(singletons go toperson_unassigned). - If unset/empty, every face is assigned to a cluster (Agglomerative mode).
-
GENIUSAI_FACES_CLUSTER_LINKAGE-
"complete"(default) = tighter clusters, fewer false merges. -
"average"= more merging.
-
These runs happen entirely in the backend process and do not require Lightroom to be open.
The backend can also create periodic ZIP backups of the database directory and prune older backups automatically:
-
GENIUSAI_BACKUP_ENABLED-
true/1/yes/onto enable. - Default: disabled.
-
-
GENIUSAI_BACKUP_INTERVAL- Interval in seconds between backup runs.
- Default:
86400(once per day). Minimum is 600 seconds.
-
GENIUSAI_BACKUP_MAX_KEEP- Number of newest backup ZIPs to keep under
<db-path>/backups. - Default:
14. Values ≤ 0 are treated as1.
- Number of newest backup ZIPs to keep under
Each run:
- Calls the same backup logic used by
GET /db/backupto create a ZIP of the DB path. - Stores a persistent copy under
<db-path>/backups. - Deletes older ZIPs so that only the newest
GENIUSAI_BACKUP_MAX_KEEPremain.
The server switched primary IDs from legacy Lightroom UUIDs to file-based photo_id values.
If you run an existing database, perform a one-time migration.
- Trigger from Lightroom plugin UI:
File -> Plug-in Manager -> LrGeniusAI -> Backend Server -> Migrate existing DB IDs to photo_id
- Trigger via API:
POST /db/migrate-photo-ids- Body:
{ "mappings": [{ "old_id": "...", "new_id": "..." }] }
- Trigger on server startup:
- Set
GENIUSAI_MIGRATION_FILEto a JSON mapping file path
- Set
image_embeddingsimage_embeddings_vertex-
face_embeddings(metadata references)
The current photo_id / hash / derived canonicalId strategy is more stable than legacy Lightroom UUIDs, but it is still not guaranteed to be 100% cross-catalog safe in every workflow.
In practice, backend identity should still be treated as best-effort and mostly catalog-scoped, especially when:
- the same source files exist in multiple Lightroom catalogs
- files were duplicated, re-exported, or rewritten outside Lightroom
- ID generation had to fall back to partial file hashes because stable metadata IDs were unavailable
For workflows that depend on strict cross-catalog identity, re-indexing and migration validation are still recommended when moving photos between catalogs or restoring older backend databases.
When multiple Lightroom catalogs use the same remote backend, the server never deletes photo data. Instead it tracks which catalog “has” each photo.
- Each catalog has a stable catalog_id (managed by the plugin).
- Each photo in the backend has metadata catalog_ids: a list of catalog_ids that currently “have” that photo.
- Indexing adds the requesting catalog’s id to catalog_ids. All read operations (search, get/ids, stats, check-unprocessed, get photo) accept an optional catalog_id and return only photos that include that catalog in catalog_ids.
-
POST /sync/cleanup
Body:{ "catalog_id": "...", "photo_ids": ["id1", "id2", ...] }.
Disassociates the given catalog_id from any backend photo that is not in photo_ids (photos removed from the Lightroom catalog). Does not delete documents; only updates metadata so other catalogs still see those photos. -
POST /sync/claim
Body:{ "catalog_id": "...", "photo_ids": ["id1", "id2", ...] }.
Adds catalog_id to catalog_ids for each listed photo. Used to “claim” existing backend photos for a catalog (e.g. after upgrading to this behavior so previously indexed photos become visible to that catalog).
- No physical deletion: Removing a photo from a catalog only removes that catalog’s id from the photo’s catalog_ids.
- Catalog-scoped reads: When catalog_id is sent, search, stats, get/ids, and related endpoints filter to photos that have that catalog in catalog_ids.
- Backward compatibility: Requests without catalog_id are unchanged (no catalog filter).
The LrGeniusAI core and backend server are released under the GNU Affero General Public License v3 (AGPL-3.0). Project license details can be found in the root LICENSE file.