hyper-models 0.3.0__tar.gz → 0.3.2__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.
- {hyper_models-0.3.0 → hyper_models-0.3.2}/PKG-INFO +9 -7
- {hyper_models-0.3.0 → hyper_models-0.3.2}/README.md +4 -4
- {hyper_models-0.3.0 → hyper_models-0.3.2}/pyproject.toml +8 -2
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper_models/__init__.py +10 -1
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper_models/models.py +3 -1
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper_models/registry.py +12 -4
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper_models/torch_models.py +46 -7
- {hyper_models-0.3.0 → hyper_models-0.3.2}/.gitignore +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/LICENSE +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper3_clip/__init__.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper3_clip/models/__init__.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper3_clip/models/encoders.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper3_clip/models/experimental.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper3_clip/models/himo.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper3_clip/models/hyper3_clip.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper3_clip/models/lorentz.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper3_clip/models/losses.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper3_clip/models/objectives.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper3_clip/models/tren.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper3_clip/training/__init__.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper3_clip/training/distributed.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper_models/loader.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper_models/loaders.py +0 -0
- {hyper_models-0.3.0 → hyper_models-0.3.2}/src/hyper_models/preprocessing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: hyper-models
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: A model zoo for non-Euclidean embedding models (hyperbolic, spherical, product manifolds)
|
|
5
5
|
Project-URL: Homepage, https://github.com/Hyper3Labs/hyper-models
|
|
6
6
|
Project-URL: Repository, https://github.com/Hyper3Labs/hyper-models
|
|
@@ -22,11 +22,13 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
23
|
Requires-Dist: huggingface-hub>=1.0
|
|
24
24
|
Requires-Dist: numpy>=1.26
|
|
25
|
-
Requires-Dist: onnxruntime
|
|
25
|
+
Requires-Dist: onnxruntime<1.24,>=1.20; python_version < '3.11'
|
|
26
|
+
Requires-Dist: onnxruntime>=1.20; python_version >= '3.11'
|
|
26
27
|
Requires-Dist: pillow>=10.0
|
|
27
28
|
Provides-Extra: dev
|
|
28
29
|
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
29
30
|
Requires-Dist: ruff>=0.1; extra == 'dev'
|
|
31
|
+
Requires-Dist: tomli>=2.0; (python_version < '3.11') and extra == 'dev'
|
|
30
32
|
Provides-Extra: ml
|
|
31
33
|
Requires-Dist: protobuf>=4.25.0; extra == 'ml'
|
|
32
34
|
Requires-Dist: pyyaml>=6.0.0; extra == 'ml'
|
|
@@ -85,7 +87,7 @@ from PIL import Image
|
|
|
85
87
|
|
|
86
88
|
# List available models
|
|
87
89
|
hyper_models.list_models()
|
|
88
|
-
# ['hycoclip-vit-s', 'hycoclip-vit-b', 'meru-vit-s', 'meru-vit-b', 'uncha-vit-s', 'uncha-vit-b', 'hyper3-clip-
|
|
90
|
+
# ['hycoclip-vit-s', 'hycoclip-vit-b', 'meru-vit-s', 'meru-vit-b', 'uncha-vit-s', 'uncha-vit-b', 'hyper3-clip-v1']
|
|
89
91
|
|
|
90
92
|
# Inspect supported internal loader kinds
|
|
91
93
|
hyper_models.list_loaders()
|
|
@@ -128,7 +130,7 @@ This keeps callers on one stable API:
|
|
|
128
130
|
```python
|
|
129
131
|
model = hyper_models.load("hycoclip-vit-s")
|
|
130
132
|
model = hyper_models.load("uncha-vit-b")
|
|
131
|
-
model = hyper_models.load("hyper3-clip-
|
|
133
|
+
model = hyper_models.load("hyper3-clip-v1")
|
|
132
134
|
```
|
|
133
135
|
|
|
134
136
|
Callers do not need to know which internal loader is used, except for optional
|
|
@@ -157,7 +159,7 @@ HyperView's simple path remains torch-free. If you use the default ONNX-backed
|
|
|
157
159
|
`hyper-models` entries or the default `embed-anything` provider, HyperView does
|
|
158
160
|
not need PyTorch. PyTorch is only needed when you explicitly select a
|
|
159
161
|
torch-backed catalog entry such as `uncha-vit-s`, `uncha-vit-b`, or
|
|
160
|
-
`hyper3-clip-
|
|
162
|
+
`hyper3-clip-v1`.
|
|
161
163
|
|
|
162
164
|
## Models
|
|
163
165
|
|
|
@@ -171,7 +173,7 @@ torch-backed catalog entry such as `uncha-vit-s`, `uncha-vit-b`, or
|
|
|
171
173
|
| `meru-vit-b` | [](https://huggingface.co/mnm-matin/hyperbolic-clip/tree/main/meru-vit-b) | [ICML 2023](https://arxiv.org/abs/2304.09172) | [facebookresearch/meru](https://github.com/facebookresearch/meru) |
|
|
172
174
|
| `uncha-vit-s` | [](https://huggingface.co/hayeonkim/uncha/blob/main/uncha_vit_s.pth) | [CVPR 2026](https://arxiv.org/abs/2603.22042) | [jeeit17/UNCHA](https://github.com/jeeit17/UNCHA) |
|
|
173
175
|
| `uncha-vit-b` | [](https://huggingface.co/hayeonkim/uncha/blob/main/uncha_vit_b.pth) | [CVPR 2026](https://arxiv.org/abs/2603.22042) | [jeeit17/UNCHA](https://github.com/jeeit17/UNCHA) |
|
|
174
|
-
| `hyper3-clip-
|
|
176
|
+
| `hyper3-clip-v1` | [](https://huggingface.co/hyper3labs/hyper3-clip-v1) | — | [Hyper3Labs/hyper3-clip](https://github.com/Hyper3Labs/hyper3-clip) |
|
|
175
177
|
| `hyp-vit` | — | [CVPR 2022](https://arxiv.org/abs/2203.10833) | [htdt/hyp_metric](https://github.com/htdt/hyp_metric) |
|
|
176
178
|
| `hie` | — | [CVPR 2020](https://arxiv.org/abs/1904.02239) | [leymir/hyperbolic-image-embeddings](https://github.com/leymir/hyperbolic-image-embeddings) |
|
|
177
179
|
| `hcnn` | — | [ICLR 2024](https://openreview.net/forum?id=ekz1hN5QNh) | [kschwethelm/HyperbolicCV](https://github.com/kschwethelm/HyperbolicCV) |
|
|
@@ -46,7 +46,7 @@ from PIL import Image
|
|
|
46
46
|
|
|
47
47
|
# List available models
|
|
48
48
|
hyper_models.list_models()
|
|
49
|
-
# ['hycoclip-vit-s', 'hycoclip-vit-b', 'meru-vit-s', 'meru-vit-b', 'uncha-vit-s', 'uncha-vit-b', 'hyper3-clip-
|
|
49
|
+
# ['hycoclip-vit-s', 'hycoclip-vit-b', 'meru-vit-s', 'meru-vit-b', 'uncha-vit-s', 'uncha-vit-b', 'hyper3-clip-v1']
|
|
50
50
|
|
|
51
51
|
# Inspect supported internal loader kinds
|
|
52
52
|
hyper_models.list_loaders()
|
|
@@ -89,7 +89,7 @@ This keeps callers on one stable API:
|
|
|
89
89
|
```python
|
|
90
90
|
model = hyper_models.load("hycoclip-vit-s")
|
|
91
91
|
model = hyper_models.load("uncha-vit-b")
|
|
92
|
-
model = hyper_models.load("hyper3-clip-
|
|
92
|
+
model = hyper_models.load("hyper3-clip-v1")
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
Callers do not need to know which internal loader is used, except for optional
|
|
@@ -118,7 +118,7 @@ HyperView's simple path remains torch-free. If you use the default ONNX-backed
|
|
|
118
118
|
`hyper-models` entries or the default `embed-anything` provider, HyperView does
|
|
119
119
|
not need PyTorch. PyTorch is only needed when you explicitly select a
|
|
120
120
|
torch-backed catalog entry such as `uncha-vit-s`, `uncha-vit-b`, or
|
|
121
|
-
`hyper3-clip-
|
|
121
|
+
`hyper3-clip-v1`.
|
|
122
122
|
|
|
123
123
|
## Models
|
|
124
124
|
|
|
@@ -132,7 +132,7 @@ torch-backed catalog entry such as `uncha-vit-s`, `uncha-vit-b`, or
|
|
|
132
132
|
| `meru-vit-b` | [](https://huggingface.co/mnm-matin/hyperbolic-clip/tree/main/meru-vit-b) | [ICML 2023](https://arxiv.org/abs/2304.09172) | [facebookresearch/meru](https://github.com/facebookresearch/meru) |
|
|
133
133
|
| `uncha-vit-s` | [](https://huggingface.co/hayeonkim/uncha/blob/main/uncha_vit_s.pth) | [CVPR 2026](https://arxiv.org/abs/2603.22042) | [jeeit17/UNCHA](https://github.com/jeeit17/UNCHA) |
|
|
134
134
|
| `uncha-vit-b` | [](https://huggingface.co/hayeonkim/uncha/blob/main/uncha_vit_b.pth) | [CVPR 2026](https://arxiv.org/abs/2603.22042) | [jeeit17/UNCHA](https://github.com/jeeit17/UNCHA) |
|
|
135
|
-
| `hyper3-clip-
|
|
135
|
+
| `hyper3-clip-v1` | [](https://huggingface.co/hyper3labs/hyper3-clip-v1) | — | [Hyper3Labs/hyper3-clip](https://github.com/Hyper3Labs/hyper3-clip) |
|
|
136
136
|
| `hyp-vit` | — | [CVPR 2022](https://arxiv.org/abs/2203.10833) | [htdt/hyp_metric](https://github.com/htdt/hyp_metric) |
|
|
137
137
|
| `hie` | — | [CVPR 2020](https://arxiv.org/abs/1904.02239) | [leymir/hyperbolic-image-embeddings](https://github.com/leymir/hyperbolic-image-embeddings) |
|
|
138
138
|
| `hcnn` | — | [ICLR 2024](https://openreview.net/forum?id=ekz1hN5QNh) | [kschwethelm/HyperbolicCV](https://github.com/kschwethelm/HyperbolicCV) |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "hyper-models"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.2"
|
|
4
4
|
description = "A model zoo for non-Euclidean embedding models (hyperbolic, spherical, product manifolds)"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "MIT" }
|
|
@@ -20,7 +20,11 @@ classifiers = [
|
|
|
20
20
|
]
|
|
21
21
|
dependencies = [
|
|
22
22
|
"numpy>=1.26",
|
|
23
|
-
|
|
23
|
+
# onnxruntime stopped publishing cp310 wheels after 1.23.x; without this
|
|
24
|
+
# split a universal resolution picks a release that cannot install on the
|
|
25
|
+
# 3.10 this package still supports.
|
|
26
|
+
"onnxruntime>=1.20,<1.24; python_version<'3.11'",
|
|
27
|
+
"onnxruntime>=1.20; python_version>='3.11'",
|
|
24
28
|
"huggingface-hub>=1.0",
|
|
25
29
|
"pillow>=10.0",
|
|
26
30
|
]
|
|
@@ -29,6 +33,8 @@ dependencies = [
|
|
|
29
33
|
dev = [
|
|
30
34
|
"pytest>=7.0",
|
|
31
35
|
"ruff>=0.1",
|
|
36
|
+
# tomllib is stdlib from 3.11; the version test reads pyproject.toml on 3.10 too.
|
|
37
|
+
"tomli>=2.0; python_version<'3.11'",
|
|
32
38
|
]
|
|
33
39
|
ml = [
|
|
34
40
|
"torch>=2.9.1",
|
|
@@ -11,6 +11,9 @@ Example:
|
|
|
11
11
|
>>> model.dim # 513
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
+
from importlib.metadata import PackageNotFoundError
|
|
15
|
+
from importlib.metadata import version as _installed_version
|
|
16
|
+
|
|
14
17
|
from hyper_models.loader import load
|
|
15
18
|
from hyper_models.loaders import list_loaders
|
|
16
19
|
from hyper_models.models import ONNXModel
|
|
@@ -27,4 +30,10 @@ __all__ = [
|
|
|
27
30
|
"ImageConfig",
|
|
28
31
|
"preprocess_images",
|
|
29
32
|
]
|
|
30
|
-
|
|
33
|
+
try:
|
|
34
|
+
# Read the installed distribution so this cannot drift from pyproject.toml:
|
|
35
|
+
# a hand-maintained literal here stayed at 0.3.0 through the 0.3.1 release,
|
|
36
|
+
# and the demo Dockerfiles print this value to confirm what they installed.
|
|
37
|
+
__version__ = _installed_version("hyper-models")
|
|
38
|
+
except PackageNotFoundError: # running from a source tree that was never installed
|
|
39
|
+
__version__ = "0.0.0.dev0"
|
|
@@ -37,7 +37,9 @@ class ONNXModel:
|
|
|
37
37
|
if self._session is None:
|
|
38
38
|
import onnxruntime as ort
|
|
39
39
|
|
|
40
|
-
self._session = ort.InferenceSession(
|
|
40
|
+
self._session = ort.InferenceSession(
|
|
41
|
+
str(self._path), providers=["CPUExecutionProvider"]
|
|
42
|
+
)
|
|
41
43
|
|
|
42
44
|
def encode(self, inputs: np.ndarray) -> np.ndarray:
|
|
43
45
|
"""Encode preprocessed inputs (B, C, H, W) to embeddings (B, D)."""
|
|
@@ -31,6 +31,7 @@ class ModelInfo:
|
|
|
31
31
|
description: str = ""
|
|
32
32
|
input_name: str = "image"
|
|
33
33
|
output_name: str | None = None
|
|
34
|
+
modalities: tuple[str, ...] = ("image",) # what the loaded model can encode
|
|
34
35
|
image_config: ImageConfig = field(default_factory=ImageConfig)
|
|
35
36
|
|
|
36
37
|
|
|
@@ -99,17 +100,18 @@ _MODELS: dict[str, ModelInfo] = {
|
|
|
99
100
|
optional_dependencies=("ml",),
|
|
100
101
|
description="UNCHA ViT-B/16 checkpoint (HF .pth, torch inference)",
|
|
101
102
|
),
|
|
102
|
-
"hyper3-clip-
|
|
103
|
-
name="hyper3-clip-
|
|
103
|
+
"hyper3-clip-v1": ModelInfo(
|
|
104
|
+
name="hyper3-clip-v1",
|
|
104
105
|
geometry="hyperboloid",
|
|
105
106
|
dim=513,
|
|
106
|
-
hub_id="hyper3labs/hyper3-clip-
|
|
107
|
+
hub_id="hyper3labs/hyper3-clip-v1",
|
|
107
108
|
hub_path="model.safetensors",
|
|
108
109
|
hub_patterns=("config.yaml", "model.safetensors"),
|
|
109
110
|
license="Unknown",
|
|
110
111
|
loader="hyper3-clip-torch",
|
|
111
112
|
optional_dependencies=("ml",),
|
|
112
|
-
|
|
113
|
+
modalities=("image", "text"),
|
|
114
|
+
description="Hyper3-CLIP v1 ViT-B image+text encoder (HF safetensors, torch inference)",
|
|
113
115
|
image_config=ImageConfig(
|
|
114
116
|
size=224,
|
|
115
117
|
interpolation="bicubic",
|
|
@@ -130,6 +132,11 @@ _MODELS: dict[str, ModelInfo] = {
|
|
|
130
132
|
),
|
|
131
133
|
}
|
|
132
134
|
|
|
135
|
+
_ALIASES = {
|
|
136
|
+
# Compatibility for callers that selected the model before its v1 rename.
|
|
137
|
+
"hyper3-clip-v0.5": "hyper3-clip-v1",
|
|
138
|
+
}
|
|
139
|
+
|
|
133
140
|
|
|
134
141
|
def list_models(geometry: str | None = None) -> list[str]:
|
|
135
142
|
"""List available model names, optionally filtered by geometry."""
|
|
@@ -140,6 +147,7 @@ def list_models(geometry: str | None = None) -> list[str]:
|
|
|
140
147
|
|
|
141
148
|
def get_model_info(name: str) -> ModelInfo:
|
|
142
149
|
"""Get metadata for a model. Raises KeyError if not found."""
|
|
150
|
+
name = _ALIASES.get(name, name)
|
|
143
151
|
if name not in _MODELS:
|
|
144
152
|
raise KeyError(f"Model '{name}' not found. Available: {', '.join(_MODELS.keys())}")
|
|
145
153
|
return _MODELS[name]
|
|
@@ -232,6 +232,30 @@ class UNCHATorchModel:
|
|
|
232
232
|
return self.encode(preprocess_images(images, self._image_config))
|
|
233
233
|
|
|
234
234
|
|
|
235
|
+
_CHECKPOINT_TEXT_PREFIX = "text_encoder.backbone.text_model."
|
|
236
|
+
_MODEL_TEXT_PREFIX = "text_encoder.backbone."
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def _align_text_tower_keys(state: dict[str, Any]) -> dict[str, Any]:
|
|
240
|
+
"""Match published Hyper3-CLIP text weights to the model's parameter names.
|
|
241
|
+
|
|
242
|
+
The checkpoint stores the text tower under the full Hugging Face
|
|
243
|
+
``CLIPTextModel`` path, while :class:`Hyper3CLIP` binds its backbone one
|
|
244
|
+
level deeper, at ``CLIPTextModel.text_model``. Without this rename the text
|
|
245
|
+
tower silently loads no pretrained weights and every text embedding comes
|
|
246
|
+
from a randomly initialised encoder.
|
|
247
|
+
"""
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
(
|
|
251
|
+
_MODEL_TEXT_PREFIX + key[len(_CHECKPOINT_TEXT_PREFIX) :]
|
|
252
|
+
if key.startswith(_CHECKPOINT_TEXT_PREFIX)
|
|
253
|
+
else key
|
|
254
|
+
): value
|
|
255
|
+
for key, value in state.items()
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
|
|
235
259
|
class Hyper3ClipTorchModel:
|
|
236
260
|
"""Hyper3-CLIP catalog entry runtime using torch for image inference."""
|
|
237
261
|
|
|
@@ -297,14 +321,11 @@ class Hyper3ClipTorchModel:
|
|
|
297
321
|
model_config["vision_pretrained"] = False
|
|
298
322
|
model_config["text_pretrained"] = False
|
|
299
323
|
model = Hyper3CLIP(**model_config)
|
|
300
|
-
state = load_file(self._checkpoint_path, device="cpu")
|
|
324
|
+
state = _align_text_tower_keys(load_file(self._checkpoint_path, device="cpu"))
|
|
301
325
|
load_result = model.load_state_dict(state, strict=False)
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
if missing_non_text:
|
|
306
|
-
missing = ", ".join(missing_non_text[:8])
|
|
307
|
-
raise RuntimeError(f"Hyper3-CLIP checkpoint missing required image keys: {missing}")
|
|
326
|
+
if load_result.missing_keys:
|
|
327
|
+
missing = ", ".join(load_result.missing_keys[:8])
|
|
328
|
+
raise RuntimeError(f"Hyper3-CLIP checkpoint missing required keys: {missing}")
|
|
308
329
|
model.to(self._device)
|
|
309
330
|
model.eval()
|
|
310
331
|
self._model = model
|
|
@@ -326,3 +347,21 @@ class Hyper3ClipTorchModel:
|
|
|
326
347
|
def encode_images(self, images: list[Image.Image]) -> np.ndarray:
|
|
327
348
|
"""Encode PIL images to Hyper3-CLIP embeddings (B, D)."""
|
|
328
349
|
return self.encode(preprocess_images(images, self._image_config))
|
|
350
|
+
|
|
351
|
+
def encode_texts(self, texts: list[str]) -> np.ndarray:
|
|
352
|
+
"""Encode text queries into the same hyperboloid as the images (B, D)."""
|
|
353
|
+
self._ensure_model()
|
|
354
|
+
|
|
355
|
+
assert self._model is not None
|
|
356
|
+
assert self._torch is not None
|
|
357
|
+
assert self._device is not None
|
|
358
|
+
|
|
359
|
+
encoded = self._model.tokenizer(
|
|
360
|
+
list(texts), padding=True, truncation=True, return_tensors="pt"
|
|
361
|
+
)
|
|
362
|
+
input_ids = encoded["input_ids"].to(self._device)
|
|
363
|
+
attention_mask = encoded["attention_mask"].to(self._device)
|
|
364
|
+
with self._torch.inference_mode():
|
|
365
|
+
emb = self._model.encode_text(input_ids, attention_mask)
|
|
366
|
+
|
|
367
|
+
return np.asarray(emb.detach().cpu().numpy(), dtype=np.float32)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|