From 8b91920058d6b76ff57d99c7d108106520853eb9 Mon Sep 17 00:00:00 2001 From: Will Miao Date: Sat, 14 Mar 2026 22:49:57 +0800 Subject: [PATCH] docs: add comprehensive metadata.json schema documentation (#856) - Create docs/metadata-json-schema.md with complete field reference - All base fields for LoRA, Checkpoint, and Embedding models - Complete civitai object structure with Used vs Stored field classification - Model-level fields (allowCommercialUse, allowDerivatives, etc.) - Creator fields (username, image) - customImages structure with actual field names and types - Field behavior categories (Auto-Updated, Set Once, User-Editable) - Add .specs/metadata.schema.json for programmatic validation - JSON Schema draft-07 format - oneOf schemas for each model type - Definitions for civitaiObject and usageTips - Add example metadata files for each model type - lora-civitai.json: LoRA with full Civitai data - lora-custom.json: User-defined LoRA with trigger words - lora-no-triggerwords.json: LoRA without trigger words - checkpoint-civitai.json: Checkpoint from Civitai - embedding-custom.json: Custom embedding Key clarifications: - modified: Import timestamp (Set Once, never changes after import) - size: File size at import time (Set Once) - base_model: Optional with actual values (SDXL 1.0, Flux.1 D, etc.) - model_type: Used in metadata.json (not sub_type which is internal) - allowCommercialUse: ["Image", "Video", "RentCivit", "Rent"] - civitai.files/images: Marked as Used by Lora Manager - User-editable fields clearly documented (model_name, tags, etc.) --- .specs/metadata.schema.json | 464 +++++++++++++++++ docs/metadata-json-schema.md | 526 ++++++++++++++++++++ examples/metadata/checkpoint-civitai.json | 41 ++ examples/metadata/embedding-custom.json | 24 + examples/metadata/lora-civitai.json | 57 +++ examples/metadata/lora-custom.json | 34 ++ examples/metadata/lora-no-triggerwords.json | 25 + 7 files changed, 1171 insertions(+) create mode 100644 .specs/metadata.schema.json create mode 100644 docs/metadata-json-schema.md create mode 100644 examples/metadata/checkpoint-civitai.json create mode 100644 examples/metadata/embedding-custom.json create mode 100644 examples/metadata/lora-civitai.json create mode 100644 examples/metadata/lora-custom.json create mode 100644 examples/metadata/lora-no-triggerwords.json diff --git a/.specs/metadata.schema.json b/.specs/metadata.schema.json new file mode 100644 index 00000000..a3af6be3 --- /dev/null +++ b/.specs/metadata.schema.json @@ -0,0 +1,464 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://github.com/willmiao/ComfyUI-Lora-Manager/.specs/metadata.schema.json", + "title": "ComfyUI LoRa Manager Model Metadata", + "description": "Schema for .metadata.json sidecar files used by ComfyUI LoRa Manager", + "type": "object", + "oneOf": [ + { + "title": "LoRA Model Metadata", + "properties": { + "file_name": { + "type": "string", + "description": "Filename without extension" + }, + "model_name": { + "type": "string", + "description": "Display name of the model" + }, + "file_path": { + "type": "string", + "description": "Full absolute path to the model file" + }, + "size": { + "type": "integer", + "minimum": 0, + "description": "File size in bytes at time of import/download" + }, + "modified": { + "type": "number", + "description": "Unix timestamp when model was imported/added (Date Added)" + }, + "sha256": { + "type": "string", + "pattern": "^[a-f0-9]{64}$", + "description": "SHA256 hash of the model file (lowercase)" + }, + "base_model": { + "type": "string", + "description": "Base model type (SD1.5, SD2.1, SDXL, SD3, Flux, Unknown, etc.)" + }, + "preview_url": { + "type": "string", + "description": "Path to preview image file" + }, + "preview_nsfw_level": { + "type": "integer", + "minimum": 0, + "default": 0, + "description": "NSFW level using bitmask values: 0 (none), 1 (PG), 2 (PG13), 4 (R), 8 (X), 16 (XXX), 32 (Blocked)" + }, + "notes": { + "type": "string", + "default": "", + "description": "User-defined notes" + }, + "from_civitai": { + "type": "boolean", + "default": true, + "description": "Whether the model originated from Civitai" + }, + "civitai": { + "$ref": "#/definitions/civitaiObject" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "Model tags" + }, + "modelDescription": { + "type": "string", + "default": "", + "description": "Full model description" + }, + "civitai_deleted": { + "type": "boolean", + "default": false, + "description": "Whether the model was deleted from Civitai" + }, + "favorite": { + "type": "boolean", + "default": false, + "description": "Whether the model is marked as favorite" + }, + "exclude": { + "type": "boolean", + "default": false, + "description": "Whether to exclude from cache/scanning" + }, + "db_checked": { + "type": "boolean", + "default": false, + "description": "Whether checked against archive database" + }, + "skip_metadata_refresh": { + "type": "boolean", + "default": false, + "description": "Skip this model during bulk metadata refresh" + }, + "metadata_source": { + "type": ["string", "null"], + "enum": ["civitai_api", "civarchive", "archive_db", null], + "default": null, + "description": "Last provider that supplied metadata" + }, + "last_checked_at": { + "type": "number", + "default": 0, + "description": "Unix timestamp of last metadata check" + }, + "hash_status": { + "type": "string", + "enum": ["pending", "calculating", "completed", "failed"], + "default": "completed", + "description": "Hash calculation status" + }, + "usage_tips": { + "type": "string", + "default": "{}", + "description": "JSON string containing recommended usage parameters (LoRA only)" + } + }, + "required": [ + "file_name", + "model_name", + "file_path", + "size", + "modified", + "sha256", + "base_model" + ], + "additionalProperties": true + }, + { + "title": "Checkpoint Model Metadata", + "properties": { + "file_name": { + "type": "string" + }, + "model_name": { + "type": "string" + }, + "file_path": { + "type": "string" + }, + "size": { + "type": "integer", + "minimum": 0 + }, + "modified": { + "type": "number" + }, + "sha256": { + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + "base_model": { + "type": "string" + }, + "preview_url": { + "type": "string" + }, + "preview_nsfw_level": { + "type": "integer", + "minimum": 0, + "maximum": 3, + "default": 0 + }, + "notes": { + "type": "string", + "default": "" + }, + "from_civitai": { + "type": "boolean", + "default": true + }, + "civitai": { + "$ref": "#/definitions/civitaiObject" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "modelDescription": { + "type": "string", + "default": "" + }, + "civitai_deleted": { + "type": "boolean", + "default": false + }, + "favorite": { + "type": "boolean", + "default": false + }, + "exclude": { + "type": "boolean", + "default": false + }, + "db_checked": { + "type": "boolean", + "default": false + }, + "skip_metadata_refresh": { + "type": "boolean", + "default": false + }, + "metadata_source": { + "type": ["string", "null"], + "enum": ["civitai_api", "civarchive", "archive_db", null], + "default": null + }, + "last_checked_at": { + "type": "number", + "default": 0 + }, + "hash_status": { + "type": "string", + "enum": ["pending", "calculating", "completed", "failed"], + "default": "completed" + }, + "sub_type": { + "type": "string", + "default": "checkpoint", + "description": "Model sub-type (checkpoint, diffusion_model, etc.)" + } + }, + "required": [ + "file_name", + "model_name", + "file_path", + "size", + "modified", + "sha256", + "base_model" + ], + "additionalProperties": true + }, + { + "title": "Embedding Model Metadata", + "properties": { + "file_name": { + "type": "string" + }, + "model_name": { + "type": "string" + }, + "file_path": { + "type": "string" + }, + "size": { + "type": "integer", + "minimum": 0 + }, + "modified": { + "type": "number" + }, + "sha256": { + "type": "string", + "pattern": "^[a-f0-9]{64}$" + }, + "base_model": { + "type": "string" + }, + "preview_url": { + "type": "string" + }, + "preview_nsfw_level": { + "type": "integer", + "minimum": 0, + "maximum": 3, + "default": 0 + }, + "notes": { + "type": "string", + "default": "" + }, + "from_civitai": { + "type": "boolean", + "default": true + }, + "civitai": { + "$ref": "#/definitions/civitaiObject" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "modelDescription": { + "type": "string", + "default": "" + }, + "civitai_deleted": { + "type": "boolean", + "default": false + }, + "favorite": { + "type": "boolean", + "default": false + }, + "exclude": { + "type": "boolean", + "default": false + }, + "db_checked": { + "type": "boolean", + "default": false + }, + "skip_metadata_refresh": { + "type": "boolean", + "default": false + }, + "metadata_source": { + "type": ["string", "null"], + "enum": ["civitai_api", "civarchive", "archive_db", null], + "default": null + }, + "last_checked_at": { + "type": "number", + "default": 0 + }, + "hash_status": { + "type": "string", + "enum": ["pending", "calculating", "completed", "failed"], + "default": "completed" + }, + "sub_type": { + "type": "string", + "default": "embedding", + "description": "Model sub-type" + } + }, + "required": [ + "file_name", + "model_name", + "file_path", + "size", + "modified", + "sha256", + "base_model" + ], + "additionalProperties": true + } + ], + "definitions": { + "civitaiObject": { + "type": "object", + "default": {}, + "description": "Civitai/CivArchive API data and user-defined fields", + "properties": { + "id": { + "type": "integer", + "description": "Version ID from Civitai" + }, + "modelId": { + "type": "integer", + "description": "Model ID from Civitai" + }, + "name": { + "type": "string", + "description": "Version name" + }, + "description": { + "type": "string", + "description": "Version description" + }, + "baseModel": { + "type": "string", + "description": "Base model type from Civitai" + }, + "type": { + "type": "string", + "description": "Model type (checkpoint, embedding, etc.)" + }, + "trainedWords": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Trigger words for the model (from API or user-defined)" + }, + "customImages": { + "type": "array", + "items": { + "type": "object" + }, + "description": "Custom example images added by user" + }, + "model": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "files": { + "type": "array", + "items": { + "type": "object" + } + }, + "images": { + "type": "array", + "items": { + "type": "object" + } + }, + "creator": { + "type": "object" + } + }, + "additionalProperties": true + }, + "usageTips": { + "type": "object", + "description": "Structure for usage_tips JSON string (LoRA models)", + "properties": { + "strength_min": { + "type": "number", + "description": "Minimum recommended model strength" + }, + "strength_max": { + "type": "number", + "description": "Maximum recommended model strength" + }, + "strength_range": { + "type": "string", + "description": "Human-readable strength range" + }, + "strength": { + "type": "number", + "description": "Single recommended strength value" + }, + "clip_strength": { + "type": "number", + "description": "Recommended CLIP/embedding strength" + }, + "clip_skip": { + "type": "integer", + "description": "Recommended CLIP skip value" + } + }, + "additionalProperties": true + } + } +} diff --git a/docs/metadata-json-schema.md b/docs/metadata-json-schema.md new file mode 100644 index 00000000..88bf3940 --- /dev/null +++ b/docs/metadata-json-schema.md @@ -0,0 +1,526 @@ +# metadata.json Schema Documentation + +This document defines the complete schema for `.metadata.json` files used by Lora Manager. These sidecar files store model metadata alongside model files (LoRA, Checkpoint, Embedding). + +## Overview + +- **File naming**: `.metadata.json` (e.g., `my_lora.safetensors` → `my_lora.metadata.json`) +- **Format**: JSON with UTF-8 encoding +- **Purpose**: Store model metadata, tags, descriptions, preview images, and Civitai/CivArchive integration data +- **Extensibility**: Unknown fields are preserved via `_unknown_fields` mechanism for forward compatibility + +--- + +## Base Fields (All Model Types) + +These fields are present in all model metadata files. + +| Field | Type | Required | Auto-Updated | Description | +|-------|------|----------|--------------|-------------| +| `file_name` | string | ✅ Yes | ✅ Yes | Filename without extension (e.g., `"my_lora"`) | +| `model_name` | string | ✅ Yes | ❌ No | Display name of the model. **Default**: `file_name` if no other source | +| `file_path` | string | ✅ Yes | ✅ Yes | Full absolute path to the model file (normalized with `/` separators) | +| `size` | integer | ✅ Yes | ❌ No | File size in bytes. **Set at**: Initial scan or download completion. Does not change thereafter. | +| `modified` | float | ✅ Yes | ❌ No | **Import timestamp** — Unix timestamp when the model was first imported/added to the system. Used for "Date Added" sorting. Does not change after initial creation. | +| `sha256` | string | ⚠️ Conditional | ✅ Yes | SHA256 hash of the model file (lowercase). **LoRA**: Required. **Checkpoint**: May be empty when `hash_status="pending"` (lazy hash calculation) | +| `base_model` | string | ❌ No | ❌ No | Base model type. **Examples**: `"SD 1.5"`, `"SDXL 1.0"`, `"SDXL Lightning"`, `"Flux.1 D"`, `"Flux.1 S"`, `"Flux.1 Krea"`, `"Illustrious"`, `"Pony"`, `"AuraFlow"`, `"Kolors"`, `"ZImageTurbo"`, `"Wan Video"`, etc. **Default**: `"Unknown"` or `""` | +| `preview_url` | string | ❌ No | ✅ Yes | Path to preview image file | +| `preview_nsfw_level` | integer | ❌ No | ❌ No | NSFW level using **bitmask values** from Civitai: `1` (PG), `2` (PG13), `4` (R), `8` (X), `16` (XXX), `32` (Blocked). **Default**: `0` (none) | +| `notes` | string | ❌ No | ❌ No | User-defined notes | +| `from_civitai` | boolean | ❌ No (default: `true`) | ❌ No | Whether the model originated from Civitai | +| `civitai` | object | ❌ No | ⚠️ Partial | Civitai/CivArchive API data and user-defined fields | +| `tags` | array[string] | ❌ No | ⚠️ Partial | Model tags (merged from API and user input) | +| `modelDescription` | string | ❌ No | ⚠️ Partial | Full model description (from API or user) | +| `civitai_deleted` | boolean | ❌ No (default: `false`) | ❌ No | Whether the model was deleted from Civitai | +| `favorite` | boolean | ❌ No (default: `false`) | ❌ No | Whether the model is marked as favorite | +| `exclude` | boolean | ❌ No (default: `false`) | ❌ No | Whether to exclude from cache/scanning. User can set from `false` to `true` (currently no UI to revert) | +| `db_checked` | boolean | ❌ No (default: `false`) | ❌ No | Whether checked against archive database | +| `skip_metadata_refresh` | boolean | ❌ No (default: `false`) | ❌ No | Skip this model during bulk metadata refresh | +| `metadata_source` | string\|null | ❌ No | ✅ Yes | Last provider that supplied metadata (see below) | +| `last_checked_at` | float | ❌ No (default: `0`) | ✅ Yes | Unix timestamp of last metadata check | +| `hash_status` | string | ❌ No (default: `"completed"`) | ✅ Yes | Hash calculation status: `"pending"`, `"calculating"`, `"completed"`, `"failed"` | + +--- + +## Model-Specific Fields + +### LoRA Models + +LoRA models do not have a `model_type` field in metadata.json. The type is inferred from context or `civitai.type` (e.g., `"LoRA"`, `"LoCon"`, `"DoRA"`). + +| Field | Type | Required | Auto-Updated | Description | +|-------|------|----------|--------------|-------------| +| `usage_tips` | string (JSON) | ❌ No (default: `"{}"`) | ❌ No | JSON string containing recommended usage parameters | + +**`usage_tips` JSON structure:** + +```json +{ + "strength_min": 0.3, + "strength_max": 0.8, + "strength_range": "0.3-0.8", + "strength": 0.6, + "clip_strength": 0.5, + "clip_skip": 2 +} +``` + +| Key | Type | Description | +|-----|------|-------------| +| `strength_min` | number | Minimum recommended model strength | +| `strength_max` | number | Maximum recommended model strength | +| `strength_range` | string | Human-readable strength range | +| `strength` | number | Single recommended strength value | +| `clip_strength` | number | Recommended CLIP/embedding strength | +| `clip_skip` | integer | Recommended CLIP skip value | + +--- + +### Checkpoint Models + +| Field | Type | Required | Auto-Updated | Description | +|-------|------|----------|--------------|-------------| +| `model_type` | string | ❌ No (default: `"checkpoint"`) | ❌ No | Model type: `"checkpoint"`, `"diffusion_model"` | + +--- + +### Embedding Models + +| Field | Type | Required | Auto-Updated | Description | +|-------|------|----------|--------------|-------------| +| `model_type` | string | ❌ No (default: `"embedding"`) | ❌ No | Model type: `"embedding"` | + +--- + +## The `civitai` Field Structure + +The `civitai` object stores the complete Civitai/CivArchive API response. Lora Manager preserves all fields from the API for future compatibility and extracts specific fields for use in the application. + +### Version-Level Fields (Civitai API) + +**Fields Used by Lora Manager:** + +| Field | Type | Description | +|-------|------|-------------| +| `id` | integer | Version ID | +| `modelId` | integer | Parent model ID | +| `name` | string | Version name (e.g., `"v1.0"`, `"v2.0-pruned"`) | +| `nsfwLevel` | integer | NSFW level (bitmask: 1=PG, 2=PG13, 4=R, 8=X, 16=XXX, 32=Blocked) | +| `baseModel` | string | Base model (e.g., `"SDXL 1.0"`, `"Flux.1 D"`, `"Illustrious"`, `"Pony"`) | +| `trainedWords` | array[string] | **Trigger words** for the model | +| `type` | string | Model type (`"LoRA"`, `"Checkpoint"`, `"TextualInversion"`) | +| `earlyAccessEndsAt` | string\|null | Early access end date (used for update notifications) | +| `description` | string | Version description (HTML) | +| `model` | object | Parent model object (see Model-Level Fields below) | +| `creator` | object | Creator information (see Creator Fields below) | +| `files` | array[object] | File list with hashes, sizes, download URLs (used for metadata extraction) | +| `images` | array[object] | Image list with metadata, prompts, NSFW levels (used for preview/examples) | + +**Fields Stored but Not Currently Used:** + +| Field | Type | Description | +|-------|------|-------------| +| `createdAt` | string (ISO 8601) | Creation timestamp | +| `updatedAt` | string (ISO 8601) | Last update timestamp | +| `status` | string | Version status (e.g., `"Published"`, `"Draft"`) | +| `publishedAt` | string (ISO 8601) | Publication timestamp | +| `baseModelType` | string | Base model type (e.g., `"Standard"`, `"Inpaint"`, `"Refiner"`) | +| `earlyAccessConfig` | object | Early access configuration | +| `uploadType` | string | Upload type (`"Created"`, `"FineTuned"`, etc.) | +| `usageControl` | string | Usage control setting | +| `air` | string | Artifact ID (URN format: `urn:air:sdxl:lora:civitai:122359@135867`) | +| `stats` | object | Download count, ratings, thumbs up count | +| `videos` | array[object] | Video list | +| `downloadUrl` | string | Direct download URL | +| `trainingStatus` | string\|null | Training status (for on-site training) | +| `trainingDetails` | object\|null | Training configuration | + +### Model-Level Fields (`civitai.model.*`) + +**Fields Used by Lora Manager:** + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Model name | +| `type` | string | Model type (`"LoRA"`, `"Checkpoint"`, `"TextualInversion"`) | +| `description` | string | Model description (HTML, used for `modelDescription`) | +| `tags` | array[string] | Model tags (used for `tags` field) | +| `allowNoCredit` | boolean | License: allow use without credit | +| `allowCommercialUse` | array[string] | License: allowed commercial uses. **Values**: `"Image"` (sell generated images), `"Video"` (sell generated videos), `"RentCivit"` (rent on Civitai), `"Rent"` (rent elsewhere) | +| `allowDerivatives` | boolean | License: allow derivatives | +| `allowDifferentLicense` | boolean | License: allow different license | + +**Fields Stored but Not Currently Used:** + +| Field | Type | Description | +|-------|------|-------------| +| `nsfw` | boolean | Model NSFW flag | +| `poi` | boolean | Person of Interest flag | + +### Creator Fields (`civitai.creator.*`) + +Both fields are used by Lora Manager: + +| Field | Type | Description | +|-------|------|-------------| +| `username` | string | Creator username (used for author display and search) | +| `image` | string | Creator avatar URL (used for display) | + +### Model Type Field (Top-Level, Outside `civitai`) + +| Field | Type | Values | Description | +|-------|------|--------|-------------| +| `model_type` | string | `"checkpoint"`, `"diffusion_model"`, `"embedding"` | Stored in metadata.json for Checkpoint and Embedding models. **Note**: LoRA models do not have this field; type is inferred from `civitai.type` or context. | + +### User-Defined Fields (Within `civitai`) + +For models not from Civitai or user-added data: + +| Field | Type | Description | +|-------|------|-------------| +| `trainedWords` | array[string] | **Trigger words** — manually added by user | +| `customImages` | array[object] | Custom example images added by user | + +### customImages Structure + +Each custom image entry has the following structure: + +```json +{ + "url": "", + "id": "short_id", + "nsfwLevel": 0, + "width": 832, + "height": 1216, + "type": "image", + "meta": { + "prompt": "...", + "negativePrompt": "...", + "steps": 20, + "cfgScale": 7, + "seed": 123456 + }, + "hasMeta": true, + "hasPositivePrompt": true +} +``` + +| Field | Type | Description | +|-------|------|-------------| +| `url` | string | Empty for local custom images | +| `id` | string | Short ID or filename | +| `nsfwLevel` | integer | NSFW level (bitmask) | +| `width` | integer | Image width in pixels | +| `height` | integer | Image height in pixels | +| `type` | string | `"image"` or `"video"` | +| `meta` | object\|null | Generation metadata (prompt, seed, etc.) extracted from image | +| `hasMeta` | boolean | Whether metadata is available | +| `hasPositivePrompt` | boolean | Whether a positive prompt is available | + +### Minimal Non-Civitai Example + +```json +{ + "civitai": { + "trainedWords": ["my_trigger_word"] + } +} +``` + +### Non-Civitai Example Without Trigger Words + +```json +{ + "civitai": {} +} +``` + +### Example: User-Added Custom Images + +```json +{ + "civitai": { + "trainedWords": ["custom_style"], + "customImages": [ + { + "url": "", + "id": "example_1", + "nsfwLevel": 0, + "width": 832, + "height": 1216, + "type": "image", + "meta": { + "prompt": "example prompt", + "seed": 12345 + }, + "hasMeta": true, + "hasPositivePrompt": true + } + ] + } +} +``` + +--- + +## Metadata Source Values + +The `metadata_source` field indicates which provider last updated the metadata: + +| Value | Source | +|-------|--------| +| `"civitai_api"` | Civitai API | +| `"civarchive"` | CivArchive API | +| `"archive_db"` | Metadata Archive Database | +| `null` | No external source (user-defined only) | + +--- + +## Auto-Update Behavior + +### Fields Updated During Scanning + +These fields are automatically synchronized with the filesystem: + +- `file_name` — Updated if actual filename differs +- `file_path` — Normalized and updated if path changes +- `preview_url` — Updated if preview file is moved/removed +- `sha256` — Updated during hash calculation (when `hash_status="pending"`) +- `hash_status` — Updated during hash calculation +- `last_checked_at` — Timestamp of scan +- `metadata_source` — Set based on metadata provider + +### Fields Set Once (Immutable After Import) + +These fields are set when the model is first imported/scanned and **never change** thereafter: + +- `modified` — Import timestamp (used for "Date Added" sorting) +- `size` — File size at time of import/download + +### User-Editable Fields + +These fields can be edited by users at any time through the Lora Manager UI or by manually editing the metadata.json file: + +- `model_name` — Display name +- `tags` — Model tags +- `modelDescription` — Model description +- `notes` — User notes +- `favorite` — Favorite flag +- `exclude` — Exclude from scanning (user can set `false`→`true`, currently no UI to revert) +- `skip_metadata_refresh` — Skip during bulk refresh +- `civitai.trainedWords` — Trigger words +- `civitai.customImages` — Custom example images +- `usage_tips` — Usage recommendations (LoRA only) + +--- + +## Complete Examples + +### Example 1: LoRA from Civitai + +```json +{ + "file_name": "anime_style_lora", + "model_name": "Anime Style LoRA", + "file_path": "/models/loras/anime_style_lora.safetensors", + "size": 104857600, + "modified": 1710000000.0, + "sha256": "abc123def456...", + "base_model": "SDXL", + "preview_url": "/models/loras/anime_style_lora.preview.png", + "preview_nsfw_level": 0, + "notes": "", + "from_civitai": true, + "civitai": { + "id": 12345, + "modelId": 67890, + "name": "v1.0", + "baseModel": "SDXL", + "trainedWords": ["anime style", "cel shading"], + "model": { + "name": "Anime Style LoRA", + "description": "A LoRA for anime-style images", + "tags": ["anime", "style", "cel shading"] + } + }, + "tags": ["anime", "style", "cel shading"], + "modelDescription": "A LoRA for anime-style images", + "civitai_deleted": false, + "favorite": true, + "exclude": false, + "db_checked": true, + "skip_metadata_refresh": false, + "metadata_source": "civitai_api", + "last_checked_at": 1710100000.0, + "hash_status": "completed", + "usage_tips": "{\"strength_min\":0.3,\"strength_max\":0.8,\"strength\":0.6}" +} +``` + +### Example 2: LoRA Not from Civitai (User-Defined) + +```json +{ + "file_name": "custom_effect_lora", + "model_name": "My Custom Effect LoRA", + "file_path": "/models/loras/custom_effect_lora.safetensors", + "size": 52428800, + "modified": 1710000000.0, + "sha256": "def789abc123...", + "base_model": "SD1.5", + "preview_url": "/models/loras/custom_effect_lora.preview.png", + "preview_nsfw_level": 0, + "notes": "Custom trained LoRA for special effects", + "from_civitai": true, + "civitai": { + "trainedWords": ["custom_effect", "special_fx"], + "customImages": [ + { + "url": "custom_example_1.png", + "seed": 12345, + "prompt": "example prompt 1" + } + ] + }, + "tags": ["custom", "experimental", "effects"], + "modelDescription": "My custom trained LoRA for creating special visual effects", + "civitai_deleted": false, + "favorite": false, + "exclude": false, + "db_checked": false, + "skip_metadata_refresh": false, + "metadata_source": null, + "last_checked_at": 1710100000.0, + "hash_status": "completed", + "usage_tips": "{\"strength\":0.7}" +} +``` + +### Example 2b: LoRA Without Trigger Words + +```json +{ + "file_name": "no_trigger_lora", + "model_name": "LoRA Without Trigger Words", + "file_path": "/models/loras/no_trigger_lora.safetensors", + "size": 10485760, + "modified": 1710000000.0, + "sha256": "abc123...", + "base_model": "SDXL", + "preview_url": "", + "preview_nsfw_level": 0, + "from_civitai": true, + "civitai": {}, + "tags": ["abstract"], + "modelDescription": "A LoRA with no trigger words", + "metadata_source": null, + "hash_status": "completed", + "usage_tips": "{}" +} +``` + +### Example 3: Checkpoint Model + +```json +{ + "file_name": "realistic_checkpoint", + "model_name": "Realistic Vision v5", + "file_path": "/models/checkpoints/realistic_v5.safetensors", + "size": 6943152000, + "modified": 1710000000.0, + "sha256": "ghi456jkl789...", + "base_model": "SDXL", + "preview_url": "/models/checkpoints/realistic_v5.preview.png", + "preview_nsfw_level": 0, + "from_civitai": true, + "civitai": { + "id": 54321, + "modelId": 98765, + "name": "v5.0", + "type": "Checkpoint", + "trainedWords": ["realistic photo"], + "model": { + "name": "Realistic Vision", + "type": "Checkpoint", + "tags": ["realistic", "photorealistic"] + } + }, + "tags": ["realistic", "photorealistic"], + "modelDescription": "Photorealistic checkpoint model", + "model_type": "checkpoint", + "metadata_source": "civitai_api", + "hash_status": "completed" +} +``` + +### Example 4: Embedding Model + +```json +{ + "file_name": "bad_hand_fix", + "model_name": "Bad Hand Fix", + "file_path": "/models/embeddings/bad_hand_fix.pt", + "size": 512000, + "modified": 1710000000.0, + "sha256": "mno789pqr012...", + "base_model": "SDXL", + "preview_url": "", + "from_civitai": false, + "civitai": {}, + "tags": ["fix", "hands"], + "modelDescription": "Embedding to fix bad hands", + "model_type": "embedding", + "metadata_source": null, + "hash_status": "completed" +} +``` + +--- + +## Field Reference by Behavior + +### Required Fields (Must Always Exist) + +- `file_name` +- `model_name` (defaults to `file_name` if not provided) +- `file_path` +- `size` +- `modified` +- `sha256` (LoRA: always required; Checkpoint: may be empty when `hash_status="pending"`) + +### Optional Fields with Defaults + +| Field | Default | +|-------|---------| +| `base_model` | `"Unknown"` or `""` | +| `preview_nsfw_level` | `0` | +| `from_civitai` | `true` | +| `civitai` | `{}` | +| `tags` | `[]` | +| `modelDescription` | `""` | +| `notes` | `""` | +| `civitai_deleted` | `false` | +| `favorite` | `false` | +| `exclude` | `false` | +| `db_checked` | `false` | +| `skip_metadata_refresh` | `false` | +| `metadata_source` | `null` | +| `last_checked_at` | `0` | +| `hash_status` | `"completed"` | +| `usage_tips` | `"{}"` (LoRA only) | +| `model_type` | `"checkpoint"` or `"embedding"` (not present in LoRA models) | + +--- + +## Version History + +| Version | Date | Changes | +|---------|------|---------| +| 1.0 | 2026-03 | Initial schema documentation | + +--- + +## See Also + +- [JSON Schema Definition](../.specs/metadata.schema.json) — Formal JSON Schema for validation +- [Example Files](../examples/metadata/) — Sample metadata.json files diff --git a/examples/metadata/checkpoint-civitai.json b/examples/metadata/checkpoint-civitai.json new file mode 100644 index 00000000..ab674928 --- /dev/null +++ b/examples/metadata/checkpoint-civitai.json @@ -0,0 +1,41 @@ +{ + "file_name": "realistic_vision_v5", + "model_name": "Realistic Vision v5.0", + "file_path": "/home/user/ComfyUI/models/checkpoints/realistic_vision_v5.safetensors", + "size": 6943152000, + "modified": 1710000000.0, + "sha256": "ghi456jkl789012345678901234567890123456789012345678901234567ijkl", + "base_model": "SDXL", + "preview_url": "/home/user/ComfyUI/models/checkpoints/realistic_vision_v5.preview.png", + "preview_nsfw_level": 0, + "from_civitai": true, + "civitai": { + "id": 54321, + "modelId": 98765, + "name": "v5.0", + "description": "Realistic Vision v5.0 - photorealistic checkpoint", + "baseModel": "SDXL", + "type": "checkpoint", + "trainedWords": ["realistic photo", "photorealistic"], + "model": { + "name": "Realistic Vision", + "description": "A photorealistic checkpoint model for SDXL", + "tags": ["realistic", "photorealistic", "portrait", "landscape"] + }, + "creator": { + "id": 44444, + "name": "CheckpointCreator" + } + }, + "tags": ["realistic", "photorealistic", "portrait", "landscape"], + "modelDescription": "Photorealistic checkpoint model optimized for portraits and landscapes. Works best with positive prompts.", + "civitai_deleted": false, + "favorite": true, + "exclude": false, + "db_checked": true, + "skip_metadata_refresh": false, + "metadata_source": "civitai_api", + "last_checked_at": 1710100000.0, + "hash_status": "completed", + "sub_type": "checkpoint" +} diff --git a/examples/metadata/embedding-custom.json b/examples/metadata/embedding-custom.json new file mode 100644 index 00000000..e21fb3c3 --- /dev/null +++ b/examples/metadata/embedding-custom.json @@ -0,0 +1,24 @@ +{ + "file_name": "bad_hand_fix", + "model_name": "Bad Hand Fix Embedding", + "file_path": "/home/user/ComfyUI/models/embeddings/bad_hand_fix.pt", + "size": 512000, + "modified": 1710000000.0, + "sha256": "mno789pqr012345678901234567890123456789012345678901234567890mnop", + "base_model": "SDXL", + "preview_url": "", + "preview_nsfw_level": 0, + "from_civitai": false, + "civitai": {}, + "tags": ["fix", "hands", "negative"], + "modelDescription": "Textual inversion embedding to fix bad hands in generated images. Use in negative prompts.", + "civitai_deleted": false, + "favorite": false, + "exclude": false, + "db_checked": false, + "skip_metadata_refresh": false, + "metadata_source": null, + "last_checked_at": 1710100000.0, + "hash_status": "completed", + "sub_type": "embedding" +} diff --git a/examples/metadata/lora-civitai.json b/examples/metadata/lora-civitai.json new file mode 100644 index 00000000..a019abf2 --- /dev/null +++ b/examples/metadata/lora-civitai.json @@ -0,0 +1,57 @@ +{ + "file_name": "anime_style_lora", + "model_name": "Anime Style LoRA", + "file_path": "/home/user/ComfyUI/models/loras/anime_style_lora.safetensors", + "size": 104857600, + "modified": 1710000000.0, + "sha256": "abc123def456789012345678901234567890123456789012345678901234abcd", + "base_model": "SDXL", + "preview_url": "/home/user/ComfyUI/models/loras/anime_style_lora.preview.png", + "preview_nsfw_level": 0, + "notes": "", + "from_civitai": true, + "civitai": { + "id": 12345, + "modelId": 67890, + "name": "v1.0", + "description": "Version 1.0 release", + "baseModel": "SDXL", + "trainedWords": ["anime style", "cel shading"], + "model": { + "name": "Anime Style LoRA", + "description": "A LoRA for creating anime-style images with cel shading effects", + "tags": ["anime", "style", "cel shading", "illustration"] + }, + "files": [ + { + "id": 11111, + "name": "anime_style_lora.safetensors", + "sizeKB": 102400, + "primary": true + } + ], + "images": [ + { + "id": 22222, + "url": "https://example.com/preview.png", + "nsfwLevel": 0 + } + ], + "creator": { + "id": 33333, + "name": "ModelCreator", + "image": "https://example.com/avatar.png" + } + }, + "tags": ["anime", "style", "cel shading", "illustration"], + "modelDescription": "A LoRA for creating anime-style images with cel shading effects. Works best with SDXL models and anime checkpoints.", + "civitai_deleted": false, + "favorite": true, + "exclude": false, + "db_checked": true, + "skip_metadata_refresh": false, + "metadata_source": "civitai_api", + "last_checked_at": 1710100000.0, + "hash_status": "completed", + "usage_tips": "{\"strength_min\":0.3,\"strength_max\":0.8,\"strength\":0.6,\"clip_strength\":0.5}" +} diff --git a/examples/metadata/lora-custom.json b/examples/metadata/lora-custom.json new file mode 100644 index 00000000..f172a2d9 --- /dev/null +++ b/examples/metadata/lora-custom.json @@ -0,0 +1,34 @@ +{ + "file_name": "custom_effect_lora", + "model_name": "My Custom Effect LoRA", + "file_path": "/home/user/ComfyUI/models/loras/custom_effect_lora.safetensors", + "size": 52428800, + "modified": 1710000000.0, + "sha256": "def789abc123456789012345678901234567890123456789012345678901efgh", + "base_model": "SD1.5", + "preview_url": "/home/user/ComfyUI/models/loras/custom_effect_lora.preview.png", + "preview_nsfw_level": 0, + "notes": "Custom trained LoRA for special effects", + "from_civitai": true, + "civitai": { + "trainedWords": ["custom_effect", "special_fx"], + "customImages": [ + { + "url": "custom_example_1.png", + "seed": 12345, + "prompt": "example prompt 1" + } + ] + }, + "tags": ["custom", "experimental", "effects"], + "modelDescription": "My custom trained LoRA for creating special visual effects", + "civitai_deleted": false, + "favorite": false, + "exclude": false, + "db_checked": false, + "skip_metadata_refresh": false, + "metadata_source": null, + "last_checked_at": 1710100000.0, + "hash_status": "completed", + "usage_tips": "{\"strength\":0.7}" +} diff --git a/examples/metadata/lora-no-triggerwords.json b/examples/metadata/lora-no-triggerwords.json new file mode 100644 index 00000000..1a99a0cf --- /dev/null +++ b/examples/metadata/lora-no-triggerwords.json @@ -0,0 +1,25 @@ +{ + "file_name": "no_trigger_lora", + "model_name": "LoRA Without Trigger Words", + "file_path": "/home/user/ComfyUI/models/loras/no_trigger_lora.safetensors", + "size": 10485760, + "modified": 1710000000.0, + "sha256": "abc123def456789012345678901234567890123456789012345678901234wxyz", + "base_model": "SDXL", + "preview_url": "", + "preview_nsfw_level": 0, + "notes": "", + "from_civitai": true, + "civitai": {}, + "tags": ["abstract"], + "modelDescription": "A LoRA with no trigger words", + "civitai_deleted": false, + "favorite": false, + "exclude": false, + "db_checked": false, + "skip_metadata_refresh": false, + "metadata_source": null, + "last_checked_at": 1710100000.0, + "hash_status": "completed", + "usage_tips": "{}" +}