Conversation
Reserve physical roots across downloads, cancellation and removal; preserve paused targets and require confirmed runtime shutdown before deleting files. Stop install-all on interrupted work and refresh dependent readiness after partial success. Fix live model paths and explicit generator identity, reject portable node aliases, and exercise the regressions on Windows/Linux with Python 3.11 and 3.12.
|
Is this possible with different venv's though? Each venv has its own dependencies that are weight based for calculations in many cases. I would LOVE if this would work as it would reduce some memory and space on my laptop. Very curious how this plays out @DrHepa |
|
Thanks, @iammojogo-sudo! Sharing checkpoint files doesn’t mean sharing a Python environment. This PR only reuses weights within one extension, whose nodes already share a venv. I checked our extensions: SD15/SDXL have matching dependency versions, but others need different Torch/CUDA or Transformers versions, so one shared venv isn’t a safe default. I’ve opened a separate proposal to keep venvs isolated while reusing verified package files where possible. That could save disk space—not RAM/VRAM. |
|
" so one shared venv isn’t a safe default" exactly! That's why I was wondering. But it is good that "keep venvs isolated while reusing verified package files" because that right there could save a lot of re-downloading python dependencies at the least. Good stuff! If it can be made internal (in the .asar), that would be helpful for extension creators too, so that they don't have to code a shared communication across extensions. Could be a big deal! I love this. |
Summary
This PR implements extension-scoped shared weight groups for model extensions.
Multiple model nodes within the same extension can now reuse one or more physical weight groups while retaining their own capability identity and optional node-private weights.
This supports both primary use cases described in #343:
Closes #343.
Motivation
Modly currently treats each model node as both a capability and the physical owner of its weights:
///
This causes every node to download its own copy of the same checkpoint, even when several nodes within an extension use an identical base model.
A simple node-owner alias is insufficient because some nodes need to combine a shared base checkpoint with additional private weights. It would also couple runtime identity and deletion behavior to a physical directory.
This PR separates:
Manifest contract
Model extensions can declare top-level "weight_groups". Each group owns its own validated "model_sources" plan.
Nodes reference the shared groups they require and may continue declaring private "model_sources".
Example:
{
"id": "pixal3d",
"type": "model",
"weight_groups": [
{
"id": "pixal3d-base",
"model_sources": [
{
"id": "pixal3d",
"provider": "huggingface",
"repo_id": "TencentARC/Pixal3D",
"revision": "",
"destination": ".",
"checks": [
"pipeline.json"
]
}
]
}
],
"nodes": [
{
"id": "generate",
"weight_groups": [
"pixal3d-base"
]
},
{
"id": "worldsculpt",
"weight_groups": [
"pixal3d-base"
],
"model_sources": [
{
"id": "worldsculpt-adapter",
"provider": "huggingface",
"repo_id": "AlayaLab/WorldSculpt",
"revision": "",
"destination": "worldsculpt",
"checks": [
"worldsculpt/"
]
}
]
}
]
}
Storage layout
Shared groups are stored independently from node-private weights:
/
/
_shared/
/
...
/
...
Rules enforced by the implementation:
Download behavior
Installing a node builds an effective download plan containing:
The download lifecycle now:
Readiness behavior
A node is ready only when:
This allows states such as:
Runtime contract
Capability identity is now explicitly separated from storage identity.
The runtime no longer depends on "MODEL_DIR.name" to determine which node is running.
Direct and subprocess extensions receive:
MODEL_ID=/
MODEL_NODE_ID=
MODEL_DIR=
SHARED_MODEL_DIRS={"":""}
The Python generator context also exposes the resolved "shared_model_dirs" mapping.
"MODEL_DIR" keeps its existing node-private meaning for backward compatibility.
When the configured model storage path changes, both private and shared directories are resolved again from the host configuration.
Deletion and uninstall behavior
Shared groups have an independent lifecycle:
UI changes
The Models UI and extension drawer now expose:
Manifest validation
The Electron and Python implementations apply equivalent normalization and validation rules.
Validation rejects:
Backward compatibility
Extensions that do not declare "weight_groups" retain their existing behavior and directory layout.
The following remain node-private and fully supported:
This PR does not migrate or deduplicate existing downloaded files automatically. Extension authors can provide migration guidance when adopting the new layout.
Test coverage
Regression coverage includes:
Validation results
Out of scope
This first phase intentionally does not add:
Cross-extension sharing can be designed separately once ownership, versioning, trust, reference counting and garbage-collection semantics have been defined.