ai-model-manager 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ai_model_manager-0.1.0/LICENSE +21 -0
- ai_model_manager-0.1.0/PKG-INFO +244 -0
- ai_model_manager-0.1.0/README.md +216 -0
- ai_model_manager-0.1.0/ai_model_manager.egg-info/PKG-INFO +244 -0
- ai_model_manager-0.1.0/ai_model_manager.egg-info/SOURCES.txt +32 -0
- ai_model_manager-0.1.0/ai_model_manager.egg-info/dependency_links.txt +1 -0
- ai_model_manager-0.1.0/ai_model_manager.egg-info/entry_points.txt +2 -0
- ai_model_manager-0.1.0/ai_model_manager.egg-info/top_level.txt +1 -0
- ai_model_manager-0.1.0/aim.py +5334 -0
- ai_model_manager-0.1.0/pyproject.toml +47 -0
- ai_model_manager-0.1.0/setup.cfg +4 -0
- ai_model_manager-0.1.0/tests/test_backup.py +83 -0
- ai_model_manager-0.1.0/tests/test_backup_cli.py +54 -0
- ai_model_manager-0.1.0/tests/test_config_merge.py +31 -0
- ai_model_manager-0.1.0/tests/test_download_core.py +54 -0
- ai_model_manager-0.1.0/tests/test_download_e2e.py +342 -0
- ai_model_manager-0.1.0/tests/test_download_progress.py +41 -0
- ai_model_manager-0.1.0/tests/test_env_cli.py +155 -0
- ai_model_manager-0.1.0/tests/test_env_detector.py +138 -0
- ai_model_manager-0.1.0/tests/test_external_links.py +97 -0
- ai_model_manager-0.1.0/tests/test_flatfile_adapters.py +69 -0
- ai_model_manager-0.1.0/tests/test_ingest_common.py +147 -0
- ai_model_manager-0.1.0/tests/test_ingest_flatfile.py +193 -0
- ai_model_manager-0.1.0/tests/test_ingest_hf.py +198 -0
- ai_model_manager-0.1.0/tests/test_ingest_ms.py +118 -0
- ai_model_manager-0.1.0/tests/test_ingest_ollama.py +113 -0
- ai_model_manager-0.1.0/tests/test_ingest_robustness.py +45 -0
- ai_model_manager-0.1.0/tests/test_ollama_detect.py +102 -0
- ai_model_manager-0.1.0/tests/test_restore.py +148 -0
- ai_model_manager-0.1.0/tests/test_secret_service.py +50 -0
- ai_model_manager-0.1.0/tests/test_shell_writer.py +80 -0
- ai_model_manager-0.1.0/tests/test_sources_config.py +82 -0
- ai_model_manager-0.1.0/tests/test_sources_registry.py +41 -0
- ai_model_manager-0.1.0/tests/test_verify_shim.py +53 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 wingsfly
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ai-model-manager
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: aim — a single-file, zero-dependency CLI to manage local AI models across HuggingFace, Ollama, ModelScope, PyTorch Hub & openai-whisper: store-as-source-of-truth, in-place load shims, portable backup/restore.
|
|
5
|
+
Author-email: wingsfly <nemosapple@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/wingsfly/ai-model-manager
|
|
8
|
+
Project-URL: Repository, https://github.com/wingsfly/ai-model-manager
|
|
9
|
+
Project-URL: Issues, https://github.com/wingsfly/ai-model-manager/issues
|
|
10
|
+
Keywords: ai,models,model-management,huggingface,ollama,modelscope,pytorch-hub,whisper,llm,cli
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Classifier: Topic :: System :: Archiving :: Mirroring
|
|
23
|
+
Classifier: Topic :: Utilities
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
# aim — AI Model Manager
|
|
30
|
+
|
|
31
|
+
Unified CLI for managing AI models across multiple inference engines.
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- **Multi-engine support**: Ollama, Hugging Face, MLX (omlx), ComfyUI, Whisper, Coqui TTS, SparkTTS, Piper, Fish Speech
|
|
36
|
+
- **Canonical Store**: Models organized by category in `~/AI/store/{category}/{model_id}/`, with symlinks/hardlinks back to engine directories
|
|
37
|
+
- **Deduplication**: Detect and deduplicate identical model files across engines via hardlinks
|
|
38
|
+
- **Registry**: Track all models in a single JSON registry with metadata, provenance, and provision info
|
|
39
|
+
|
|
40
|
+
## Docs
|
|
41
|
+
|
|
42
|
+
- Download PRD: `docs/download-prd.md`
|
|
43
|
+
- Download implementation plan: `docs/download-implementation-plan.md`
|
|
44
|
+
- Download JSON contract: `docs/download-json-contract.md`
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Symlink to PATH
|
|
50
|
+
ln -sf "$(pwd)/aim.py" ~/.local/bin/aim
|
|
51
|
+
chmod +x aim.py
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Usage
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Scan all engines and register models
|
|
58
|
+
aim scan
|
|
59
|
+
|
|
60
|
+
# List registered models
|
|
61
|
+
aim list
|
|
62
|
+
aim list --engine comfyui --sort size
|
|
63
|
+
aim list --json # JSON array output
|
|
64
|
+
|
|
65
|
+
# Show model details
|
|
66
|
+
aim info <model_id>
|
|
67
|
+
aim info <model_id> --json # full metadata as JSON
|
|
68
|
+
|
|
69
|
+
# Resolve model to absolute path (for inference)
|
|
70
|
+
aim resolve <model_id> # prints absolute path
|
|
71
|
+
aim resolve <model_id> --json # full metadata + path + resolved_file
|
|
72
|
+
aim resolve <model_id> --engine comfyui # prefer engine provision path
|
|
73
|
+
|
|
74
|
+
# Organize models into canonical store (preview)
|
|
75
|
+
aim organize
|
|
76
|
+
|
|
77
|
+
# Organize all non-CAS models
|
|
78
|
+
aim organize --all
|
|
79
|
+
|
|
80
|
+
# Organize a single model
|
|
81
|
+
aim organize <model_id>
|
|
82
|
+
|
|
83
|
+
# Download a model
|
|
84
|
+
aim download hf:org/repo
|
|
85
|
+
aim download ollama:model:tag
|
|
86
|
+
aim download hf:org/repo --json
|
|
87
|
+
aim download status <job_id> --json
|
|
88
|
+
aim download cancel <job_id>
|
|
89
|
+
aim download hf:org/repo --category llm/chat
|
|
90
|
+
aim download hf:org/repo --path /custom/path
|
|
91
|
+
aim download url:https://example.com/model.bin --no-progress
|
|
92
|
+
aim download url:https://example.com/model.bin --no-resume
|
|
93
|
+
aim download hf:org/repo --proxy http://127.0.0.1:7890 --retry 3 --retry-backoff 1.5
|
|
94
|
+
|
|
95
|
+
# Import/register existing local model path
|
|
96
|
+
aim import /path/to/local/model-dir --id my-model --category llm/chat
|
|
97
|
+
|
|
98
|
+
# Ingest a native-cache model (HF/Ollama/ModelScope) into the store + rebuild its load shim
|
|
99
|
+
aim ingest <model_id> # one model: copy real files flat into store/, rebuild the tool's load shim
|
|
100
|
+
aim ingest --all-native # ingest all native_cas (HF/Ollama/MS) models
|
|
101
|
+
aim ingest <model_id> --dry-run # preview, change nothing
|
|
102
|
+
aim ingest <model_id> --keep-native # keep original native bytes (default reclaims them)
|
|
103
|
+
aim convert <model_id> # deprecated alias -> ingest
|
|
104
|
+
aim verify --fix # also rebuilds storage shims from the recorded annotation
|
|
105
|
+
|
|
106
|
+
# Ingestable sources now include single-file weights:
|
|
107
|
+
# PyTorch Hub ($TORCH_HOME/hub/checkpoints/*.pth) -> aim ingest <torch-id>
|
|
108
|
+
# openai-whisper (${XDG_CACHE_HOME:-~/.cache}/whisper/*.pt) -> aim ingest <whisper-id>
|
|
109
|
+
# aim scan discovers them; ingest copies into store and leaves a file symlink so the tool still loads.
|
|
110
|
+
|
|
111
|
+
# Portable backup / restore (store/ + manifest; shims are regenerated on restore)
|
|
112
|
+
aim backup /Volumes/Backup/aim # mirror store/ + write aim-backup.json (idempotent; re-runnable)
|
|
113
|
+
aim backup /Volumes/Backup/aim --verify
|
|
114
|
+
aim restore /Volumes/Backup/aim # recreate store, rebuild tool shims for THIS machine, print env to set
|
|
115
|
+
aim restore /Volumes/Backup/aim --apply-env # also write env to shell config
|
|
116
|
+
|
|
117
|
+
# Provision a model for an engine
|
|
118
|
+
aim provision <model_id> --engine comfyui
|
|
119
|
+
|
|
120
|
+
# Verify link integrity
|
|
121
|
+
aim verify
|
|
122
|
+
aim verify --fix
|
|
123
|
+
|
|
124
|
+
# Storage overview
|
|
125
|
+
aim status
|
|
126
|
+
aim status --by category
|
|
127
|
+
|
|
128
|
+
# Detect / manage download-source env vars (HF, Ollama, ModelScope, PyTorch Hub, Civitai, Git)
|
|
129
|
+
aim env show # detected vars + resolved cache dirs (read-only)
|
|
130
|
+
aim env show --json # machine-readable; secret values are masked
|
|
131
|
+
aim env path huggingface # resolved cache dir for a source
|
|
132
|
+
aim env apply --shell zsh # write ~/.aim/env.{sh,fish} + wire rc (one guarded line)
|
|
133
|
+
aim env apply --set HF_ENDPOINT=https://hf-mirror.com --set HF_HUB_ENABLE_HF_TRANSFER=1
|
|
134
|
+
aim env apply --dry-run # preview, write nothing
|
|
135
|
+
aim env apply --service # also print daemon-level (launchctl/systemd) env commands
|
|
136
|
+
aim sources list # sources, tool install state, env summary
|
|
137
|
+
aim sources install huggingface -y # install a source's download tool
|
|
138
|
+
|
|
139
|
+
# Find duplicates
|
|
140
|
+
aim dedup
|
|
141
|
+
aim dedup --apply
|
|
142
|
+
|
|
143
|
+
# Find unregistered model files
|
|
144
|
+
aim orphans
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## JSON Output
|
|
148
|
+
|
|
149
|
+
`aim list`, `aim info`, and `aim resolve` support `--json` for programmatic integration.
|
|
150
|
+
`aim download --json` emits JSONL progress events and a final JSON summary.
|
|
151
|
+
|
|
152
|
+
`aim resolve <id> --json` is the recommended single-call API — it returns the full model
|
|
153
|
+
metadata (superset of `aim info --json`) plus two extra fields:
|
|
154
|
+
|
|
155
|
+
```jsonc
|
|
156
|
+
{
|
|
157
|
+
"id": "whisper-large-v3-turbo",
|
|
158
|
+
"name": "whisper-large-v3-turbo",
|
|
159
|
+
"source": { "type": "local", "repo_id": "openai/whisper-large-v3-turbo" },
|
|
160
|
+
"format": "pt",
|
|
161
|
+
"size_bytes": 1617941637,
|
|
162
|
+
"category": "asr/model",
|
|
163
|
+
"engines": ["whisper"],
|
|
164
|
+
// ... all other model fields ...
|
|
165
|
+
"path": "/Users/you/AI/store/asr/model/whisper-large-v3-turbo",
|
|
166
|
+
"resolved_file": "/Users/you/AI/store/asr/model/whisper-large-v3-turbo/large-v3-turbo.pt"
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
| Field | Description |
|
|
171
|
+
|-------|-------------|
|
|
172
|
+
| `path` | Absolute directory (or file) path, resolved via provision or canonical store |
|
|
173
|
+
| `resolved_file` | Primary weight file inside the directory, or `null` for sharded / complex models |
|
|
174
|
+
|
|
175
|
+
Download placement policy:
|
|
176
|
+
|
|
177
|
+
1. `--path` has highest priority
|
|
178
|
+
2. Else auto place under `store/<category>/<model_id>/`
|
|
179
|
+
3. Missing category falls back to inferred category, then `uncategorized`
|
|
180
|
+
|
|
181
|
+
Download control flags:
|
|
182
|
+
|
|
183
|
+
1. `--no-progress`: only final summary (especially useful with `--json`)
|
|
184
|
+
2. `--resume` / `--no-resume`: toggle resume behavior
|
|
185
|
+
3. `--proxy --timeout --connect-timeout --retry --retry-backoff --max-speed --concurrency`
|
|
186
|
+
|
|
187
|
+
`resolved_file` detection: scans top-level weight files (`.safetensors`, `.pt`, `.pth`, `.gguf`,
|
|
188
|
+
`.bin`, `.onnx`). Single file → returned directly. Multiple → picks largest matching format.
|
|
189
|
+
Sharded models (`model-00001-of-00006`) → `null` (load from directory).
|
|
190
|
+
|
|
191
|
+
## Store Layout
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
~/AI/store/
|
|
195
|
+
├── asr/model/ — Whisper models
|
|
196
|
+
├── image-gen/
|
|
197
|
+
│ ├── checkpoint/ — FLUX, SDXL checkpoints
|
|
198
|
+
│ ├── lora/ — LoRA weights
|
|
199
|
+
│ ├── text-encoder/ — CLIP, T5 encoders
|
|
200
|
+
│ └── vae/ — VAE models
|
|
201
|
+
├── llm/chat/ — LLM chat models (MLX)
|
|
202
|
+
└── tts/
|
|
203
|
+
├── model/ — TTS models
|
|
204
|
+
└── vocoder/ — Vocoder models
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## How It Works
|
|
208
|
+
|
|
209
|
+
1. **`aim scan`** discovers models in engine directories, registers them
|
|
210
|
+
2. **`aim organize`** moves models into `store/{category}/{id}/`, replaces originals with:
|
|
211
|
+
- **Directories** → symlink back to engine location
|
|
212
|
+
- **Files in shared dirs** → hardlink back
|
|
213
|
+
3. **`aim verify`** checks all links are intact
|
|
214
|
+
4. **`aim provision`** creates links for a model in any supported engine
|
|
215
|
+
|
|
216
|
+
## Configuration
|
|
217
|
+
|
|
218
|
+
Config is stored at `~/.aim/config.json`. Registry at `~/.aim/registry.json`.
|
|
219
|
+
|
|
220
|
+
## Requirements
|
|
221
|
+
|
|
222
|
+
- Python 3.10+
|
|
223
|
+
- macOS / Linux
|
|
224
|
+
- Optional: `gh` CLI, `hfd.sh` for downloads
|
|
225
|
+
|
|
226
|
+
## Testing
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
# Run syntax check
|
|
230
|
+
make lint
|
|
231
|
+
|
|
232
|
+
# Run all tests (unit + e2e)
|
|
233
|
+
make test
|
|
234
|
+
|
|
235
|
+
# Run only unit tests
|
|
236
|
+
make test-unit
|
|
237
|
+
|
|
238
|
+
# Run only end-to-end tests
|
|
239
|
+
make test-e2e
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## License
|
|
243
|
+
|
|
244
|
+
MIT
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# aim — AI Model Manager
|
|
2
|
+
|
|
3
|
+
Unified CLI for managing AI models across multiple inference engines.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multi-engine support**: Ollama, Hugging Face, MLX (omlx), ComfyUI, Whisper, Coqui TTS, SparkTTS, Piper, Fish Speech
|
|
8
|
+
- **Canonical Store**: Models organized by category in `~/AI/store/{category}/{model_id}/`, with symlinks/hardlinks back to engine directories
|
|
9
|
+
- **Deduplication**: Detect and deduplicate identical model files across engines via hardlinks
|
|
10
|
+
- **Registry**: Track all models in a single JSON registry with metadata, provenance, and provision info
|
|
11
|
+
|
|
12
|
+
## Docs
|
|
13
|
+
|
|
14
|
+
- Download PRD: `docs/download-prd.md`
|
|
15
|
+
- Download implementation plan: `docs/download-implementation-plan.md`
|
|
16
|
+
- Download JSON contract: `docs/download-json-contract.md`
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Symlink to PATH
|
|
22
|
+
ln -sf "$(pwd)/aim.py" ~/.local/bin/aim
|
|
23
|
+
chmod +x aim.py
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Scan all engines and register models
|
|
30
|
+
aim scan
|
|
31
|
+
|
|
32
|
+
# List registered models
|
|
33
|
+
aim list
|
|
34
|
+
aim list --engine comfyui --sort size
|
|
35
|
+
aim list --json # JSON array output
|
|
36
|
+
|
|
37
|
+
# Show model details
|
|
38
|
+
aim info <model_id>
|
|
39
|
+
aim info <model_id> --json # full metadata as JSON
|
|
40
|
+
|
|
41
|
+
# Resolve model to absolute path (for inference)
|
|
42
|
+
aim resolve <model_id> # prints absolute path
|
|
43
|
+
aim resolve <model_id> --json # full metadata + path + resolved_file
|
|
44
|
+
aim resolve <model_id> --engine comfyui # prefer engine provision path
|
|
45
|
+
|
|
46
|
+
# Organize models into canonical store (preview)
|
|
47
|
+
aim organize
|
|
48
|
+
|
|
49
|
+
# Organize all non-CAS models
|
|
50
|
+
aim organize --all
|
|
51
|
+
|
|
52
|
+
# Organize a single model
|
|
53
|
+
aim organize <model_id>
|
|
54
|
+
|
|
55
|
+
# Download a model
|
|
56
|
+
aim download hf:org/repo
|
|
57
|
+
aim download ollama:model:tag
|
|
58
|
+
aim download hf:org/repo --json
|
|
59
|
+
aim download status <job_id> --json
|
|
60
|
+
aim download cancel <job_id>
|
|
61
|
+
aim download hf:org/repo --category llm/chat
|
|
62
|
+
aim download hf:org/repo --path /custom/path
|
|
63
|
+
aim download url:https://example.com/model.bin --no-progress
|
|
64
|
+
aim download url:https://example.com/model.bin --no-resume
|
|
65
|
+
aim download hf:org/repo --proxy http://127.0.0.1:7890 --retry 3 --retry-backoff 1.5
|
|
66
|
+
|
|
67
|
+
# Import/register existing local model path
|
|
68
|
+
aim import /path/to/local/model-dir --id my-model --category llm/chat
|
|
69
|
+
|
|
70
|
+
# Ingest a native-cache model (HF/Ollama/ModelScope) into the store + rebuild its load shim
|
|
71
|
+
aim ingest <model_id> # one model: copy real files flat into store/, rebuild the tool's load shim
|
|
72
|
+
aim ingest --all-native # ingest all native_cas (HF/Ollama/MS) models
|
|
73
|
+
aim ingest <model_id> --dry-run # preview, change nothing
|
|
74
|
+
aim ingest <model_id> --keep-native # keep original native bytes (default reclaims them)
|
|
75
|
+
aim convert <model_id> # deprecated alias -> ingest
|
|
76
|
+
aim verify --fix # also rebuilds storage shims from the recorded annotation
|
|
77
|
+
|
|
78
|
+
# Ingestable sources now include single-file weights:
|
|
79
|
+
# PyTorch Hub ($TORCH_HOME/hub/checkpoints/*.pth) -> aim ingest <torch-id>
|
|
80
|
+
# openai-whisper (${XDG_CACHE_HOME:-~/.cache}/whisper/*.pt) -> aim ingest <whisper-id>
|
|
81
|
+
# aim scan discovers them; ingest copies into store and leaves a file symlink so the tool still loads.
|
|
82
|
+
|
|
83
|
+
# Portable backup / restore (store/ + manifest; shims are regenerated on restore)
|
|
84
|
+
aim backup /Volumes/Backup/aim # mirror store/ + write aim-backup.json (idempotent; re-runnable)
|
|
85
|
+
aim backup /Volumes/Backup/aim --verify
|
|
86
|
+
aim restore /Volumes/Backup/aim # recreate store, rebuild tool shims for THIS machine, print env to set
|
|
87
|
+
aim restore /Volumes/Backup/aim --apply-env # also write env to shell config
|
|
88
|
+
|
|
89
|
+
# Provision a model for an engine
|
|
90
|
+
aim provision <model_id> --engine comfyui
|
|
91
|
+
|
|
92
|
+
# Verify link integrity
|
|
93
|
+
aim verify
|
|
94
|
+
aim verify --fix
|
|
95
|
+
|
|
96
|
+
# Storage overview
|
|
97
|
+
aim status
|
|
98
|
+
aim status --by category
|
|
99
|
+
|
|
100
|
+
# Detect / manage download-source env vars (HF, Ollama, ModelScope, PyTorch Hub, Civitai, Git)
|
|
101
|
+
aim env show # detected vars + resolved cache dirs (read-only)
|
|
102
|
+
aim env show --json # machine-readable; secret values are masked
|
|
103
|
+
aim env path huggingface # resolved cache dir for a source
|
|
104
|
+
aim env apply --shell zsh # write ~/.aim/env.{sh,fish} + wire rc (one guarded line)
|
|
105
|
+
aim env apply --set HF_ENDPOINT=https://hf-mirror.com --set HF_HUB_ENABLE_HF_TRANSFER=1
|
|
106
|
+
aim env apply --dry-run # preview, write nothing
|
|
107
|
+
aim env apply --service # also print daemon-level (launchctl/systemd) env commands
|
|
108
|
+
aim sources list # sources, tool install state, env summary
|
|
109
|
+
aim sources install huggingface -y # install a source's download tool
|
|
110
|
+
|
|
111
|
+
# Find duplicates
|
|
112
|
+
aim dedup
|
|
113
|
+
aim dedup --apply
|
|
114
|
+
|
|
115
|
+
# Find unregistered model files
|
|
116
|
+
aim orphans
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## JSON Output
|
|
120
|
+
|
|
121
|
+
`aim list`, `aim info`, and `aim resolve` support `--json` for programmatic integration.
|
|
122
|
+
`aim download --json` emits JSONL progress events and a final JSON summary.
|
|
123
|
+
|
|
124
|
+
`aim resolve <id> --json` is the recommended single-call API — it returns the full model
|
|
125
|
+
metadata (superset of `aim info --json`) plus two extra fields:
|
|
126
|
+
|
|
127
|
+
```jsonc
|
|
128
|
+
{
|
|
129
|
+
"id": "whisper-large-v3-turbo",
|
|
130
|
+
"name": "whisper-large-v3-turbo",
|
|
131
|
+
"source": { "type": "local", "repo_id": "openai/whisper-large-v3-turbo" },
|
|
132
|
+
"format": "pt",
|
|
133
|
+
"size_bytes": 1617941637,
|
|
134
|
+
"category": "asr/model",
|
|
135
|
+
"engines": ["whisper"],
|
|
136
|
+
// ... all other model fields ...
|
|
137
|
+
"path": "/Users/you/AI/store/asr/model/whisper-large-v3-turbo",
|
|
138
|
+
"resolved_file": "/Users/you/AI/store/asr/model/whisper-large-v3-turbo/large-v3-turbo.pt"
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
| Field | Description |
|
|
143
|
+
|-------|-------------|
|
|
144
|
+
| `path` | Absolute directory (or file) path, resolved via provision or canonical store |
|
|
145
|
+
| `resolved_file` | Primary weight file inside the directory, or `null` for sharded / complex models |
|
|
146
|
+
|
|
147
|
+
Download placement policy:
|
|
148
|
+
|
|
149
|
+
1. `--path` has highest priority
|
|
150
|
+
2. Else auto place under `store/<category>/<model_id>/`
|
|
151
|
+
3. Missing category falls back to inferred category, then `uncategorized`
|
|
152
|
+
|
|
153
|
+
Download control flags:
|
|
154
|
+
|
|
155
|
+
1. `--no-progress`: only final summary (especially useful with `--json`)
|
|
156
|
+
2. `--resume` / `--no-resume`: toggle resume behavior
|
|
157
|
+
3. `--proxy --timeout --connect-timeout --retry --retry-backoff --max-speed --concurrency`
|
|
158
|
+
|
|
159
|
+
`resolved_file` detection: scans top-level weight files (`.safetensors`, `.pt`, `.pth`, `.gguf`,
|
|
160
|
+
`.bin`, `.onnx`). Single file → returned directly. Multiple → picks largest matching format.
|
|
161
|
+
Sharded models (`model-00001-of-00006`) → `null` (load from directory).
|
|
162
|
+
|
|
163
|
+
## Store Layout
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
~/AI/store/
|
|
167
|
+
├── asr/model/ — Whisper models
|
|
168
|
+
├── image-gen/
|
|
169
|
+
│ ├── checkpoint/ — FLUX, SDXL checkpoints
|
|
170
|
+
│ ├── lora/ — LoRA weights
|
|
171
|
+
│ ├── text-encoder/ — CLIP, T5 encoders
|
|
172
|
+
│ └── vae/ — VAE models
|
|
173
|
+
├── llm/chat/ — LLM chat models (MLX)
|
|
174
|
+
└── tts/
|
|
175
|
+
├── model/ — TTS models
|
|
176
|
+
└── vocoder/ — Vocoder models
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## How It Works
|
|
180
|
+
|
|
181
|
+
1. **`aim scan`** discovers models in engine directories, registers them
|
|
182
|
+
2. **`aim organize`** moves models into `store/{category}/{id}/`, replaces originals with:
|
|
183
|
+
- **Directories** → symlink back to engine location
|
|
184
|
+
- **Files in shared dirs** → hardlink back
|
|
185
|
+
3. **`aim verify`** checks all links are intact
|
|
186
|
+
4. **`aim provision`** creates links for a model in any supported engine
|
|
187
|
+
|
|
188
|
+
## Configuration
|
|
189
|
+
|
|
190
|
+
Config is stored at `~/.aim/config.json`. Registry at `~/.aim/registry.json`.
|
|
191
|
+
|
|
192
|
+
## Requirements
|
|
193
|
+
|
|
194
|
+
- Python 3.10+
|
|
195
|
+
- macOS / Linux
|
|
196
|
+
- Optional: `gh` CLI, `hfd.sh` for downloads
|
|
197
|
+
|
|
198
|
+
## Testing
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Run syntax check
|
|
202
|
+
make lint
|
|
203
|
+
|
|
204
|
+
# Run all tests (unit + e2e)
|
|
205
|
+
make test
|
|
206
|
+
|
|
207
|
+
# Run only unit tests
|
|
208
|
+
make test-unit
|
|
209
|
+
|
|
210
|
+
# Run only end-to-end tests
|
|
211
|
+
make test-e2e
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## License
|
|
215
|
+
|
|
216
|
+
MIT
|