hyper-models 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.
- hyper_models-0.1.0/.gitignore +129 -0
- hyper_models-0.1.0/LICENSE +21 -0
- hyper_models-0.1.0/PKG-INFO +134 -0
- hyper_models-0.1.0/README.md +103 -0
- hyper_models-0.1.0/pyproject.toml +59 -0
- hyper_models-0.1.0/src/hyper_models/__init__.py +28 -0
- hyper_models-0.1.0/src/hyper_models/loader.py +45 -0
- hyper_models-0.1.0/src/hyper_models/models.py +55 -0
- hyper_models-0.1.0/src/hyper_models/preprocessing.py +70 -0
- hyper_models-0.1.0/src/hyper_models/registry.py +78 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# hyper_models - Model Zoo for Non-Euclidean Embeddings
|
|
3
|
+
# =============================================================================
|
|
4
|
+
|
|
5
|
+
# -----------------------------------------------------------------------------
|
|
6
|
+
# Python
|
|
7
|
+
# -----------------------------------------------------------------------------
|
|
8
|
+
__pycache__/
|
|
9
|
+
**/__pycache__/
|
|
10
|
+
*.py[cod]
|
|
11
|
+
*$py.class
|
|
12
|
+
*.so
|
|
13
|
+
.Python
|
|
14
|
+
build/
|
|
15
|
+
develop-eggs/
|
|
16
|
+
dist/
|
|
17
|
+
downloads/
|
|
18
|
+
eggs/
|
|
19
|
+
.eggs/
|
|
20
|
+
lib/
|
|
21
|
+
lib64/
|
|
22
|
+
parts/
|
|
23
|
+
sdist/
|
|
24
|
+
var/
|
|
25
|
+
wheels/
|
|
26
|
+
*.egg-info/
|
|
27
|
+
.installed.cfg
|
|
28
|
+
*.egg
|
|
29
|
+
|
|
30
|
+
# -----------------------------------------------------------------------------
|
|
31
|
+
# Virtual Environments
|
|
32
|
+
# -----------------------------------------------------------------------------
|
|
33
|
+
.venv/
|
|
34
|
+
**/.venv/
|
|
35
|
+
venv/
|
|
36
|
+
ENV/
|
|
37
|
+
env/
|
|
38
|
+
|
|
39
|
+
# -----------------------------------------------------------------------------
|
|
40
|
+
# Large Local Artifacts (not committed - use HuggingFace Hub)
|
|
41
|
+
# -----------------------------------------------------------------------------
|
|
42
|
+
# Model checkpoints (PyTorch weights)
|
|
43
|
+
**/checkpoints/
|
|
44
|
+
*.pth
|
|
45
|
+
*.pt
|
|
46
|
+
*.bin
|
|
47
|
+
*.safetensors
|
|
48
|
+
|
|
49
|
+
# ONNX outputs (local exports before uploading to HF)
|
|
50
|
+
**/outputs/
|
|
51
|
+
*.onnx
|
|
52
|
+
*.onnx.data
|
|
53
|
+
|
|
54
|
+
# Cloned upstream repos (recreated via git clone)
|
|
55
|
+
hycoclip_repo/
|
|
56
|
+
**/hycoclip_repo/
|
|
57
|
+
|
|
58
|
+
# -----------------------------------------------------------------------------
|
|
59
|
+
# Package Management
|
|
60
|
+
# -----------------------------------------------------------------------------
|
|
61
|
+
# uv lockfile - can be committed for reproducibility, but optional
|
|
62
|
+
uv.lock
|
|
63
|
+
|
|
64
|
+
# pip
|
|
65
|
+
pip-log.txt
|
|
66
|
+
pip-delete-this-directory.txt
|
|
67
|
+
|
|
68
|
+
# -----------------------------------------------------------------------------
|
|
69
|
+
# Testing & Coverage
|
|
70
|
+
# -----------------------------------------------------------------------------
|
|
71
|
+
.tox/
|
|
72
|
+
.nox/
|
|
73
|
+
.coverage
|
|
74
|
+
.coverage.*
|
|
75
|
+
htmlcov/
|
|
76
|
+
.pytest_cache/
|
|
77
|
+
nosetests.xml
|
|
78
|
+
coverage.xml
|
|
79
|
+
*.cover
|
|
80
|
+
*.py,cover
|
|
81
|
+
.hypothesis/
|
|
82
|
+
|
|
83
|
+
# -----------------------------------------------------------------------------
|
|
84
|
+
# IDE / Editor
|
|
85
|
+
# -----------------------------------------------------------------------------
|
|
86
|
+
.idea/
|
|
87
|
+
.vscode/
|
|
88
|
+
*.swp
|
|
89
|
+
*.swo
|
|
90
|
+
*~
|
|
91
|
+
.project
|
|
92
|
+
.pydevproject
|
|
93
|
+
.settings/
|
|
94
|
+
|
|
95
|
+
# -----------------------------------------------------------------------------
|
|
96
|
+
# OS Generated
|
|
97
|
+
# -----------------------------------------------------------------------------
|
|
98
|
+
.DS_Store
|
|
99
|
+
.DS_Store?
|
|
100
|
+
._*
|
|
101
|
+
.Spotlight-V100
|
|
102
|
+
.Trashes
|
|
103
|
+
ehthumbs.db
|
|
104
|
+
Thumbs.db
|
|
105
|
+
|
|
106
|
+
# -----------------------------------------------------------------------------
|
|
107
|
+
# Jupyter / IPython
|
|
108
|
+
# -----------------------------------------------------------------------------
|
|
109
|
+
.ipynb_checkpoints/
|
|
110
|
+
*.ipynb_checkpoints
|
|
111
|
+
profile_default/
|
|
112
|
+
ipython_config.py
|
|
113
|
+
|
|
114
|
+
# -----------------------------------------------------------------------------
|
|
115
|
+
# Documentation
|
|
116
|
+
# -----------------------------------------------------------------------------
|
|
117
|
+
docs/_build/
|
|
118
|
+
site/
|
|
119
|
+
|
|
120
|
+
# -----------------------------------------------------------------------------
|
|
121
|
+
# Misc
|
|
122
|
+
# -----------------------------------------------------------------------------
|
|
123
|
+
*.log
|
|
124
|
+
*.tmp
|
|
125
|
+
*.temp
|
|
126
|
+
.cache/
|
|
127
|
+
*.hf/
|
|
128
|
+
AGENTS.md
|
|
129
|
+
.specstory/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Hyper3Labs
|
|
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,134 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hyper-models
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A model zoo for non-Euclidean embedding models (hyperbolic, spherical, product manifolds)
|
|
5
|
+
Project-URL: Homepage, https://github.com/Hyper3Labs/hyper-models
|
|
6
|
+
Project-URL: Repository, https://github.com/Hyper3Labs/hyper-models
|
|
7
|
+
Project-URL: Documentation, https://github.com/Hyper3Labs/hyper-models#readme
|
|
8
|
+
Project-URL: Issues, https://github.com/Hyper3Labs/hyper-models/issues
|
|
9
|
+
Author: Hyper3Labs
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: clip,embeddings,hyperbolic,model-zoo,non-euclidean,onnx
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: huggingface-hub>=1.0
|
|
24
|
+
Requires-Dist: numpy>=1.26
|
|
25
|
+
Requires-Dist: onnxruntime>=1.20
|
|
26
|
+
Requires-Dist: pillow>=10.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.1; extra == 'dev'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# hyper-models
|
|
33
|
+
|
|
34
|
+
<p align="center">
|
|
35
|
+
<strong>A model zoo for non-Euclidean embedding models</strong>
|
|
36
|
+
<br>
|
|
37
|
+
<em>Hyperbolic · Spherical · Product Manifolds</em>
|
|
38
|
+
</p>
|
|
39
|
+
|
|
40
|
+
<p align="center">
|
|
41
|
+
<a href="https://huggingface.co/mnm-matin/hyperbolic-clip">
|
|
42
|
+
<img src="https://img.shields.io/badge/🤗_Models-hyperbolic--clip-orange" alt="Hugging Face">
|
|
43
|
+
</a>
|
|
44
|
+
<a href="LICENSE">
|
|
45
|
+
<img src="https://img.shields.io/badge/License-MIT-blue" alt="License: MIT">
|
|
46
|
+
</a>
|
|
47
|
+
</p>
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Why?
|
|
52
|
+
|
|
53
|
+
- **Standardized access** to non-Euclidean embedding models
|
|
54
|
+
- **Torch-free runtime** via ONNX (models published to Hugging Face Hub)
|
|
55
|
+
- **Simple API** — `load()` and `encode_images()`
|
|
56
|
+
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install hyper-models
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
import hyper_models
|
|
67
|
+
from PIL import Image
|
|
68
|
+
|
|
69
|
+
# List available models
|
|
70
|
+
hyper_models.list_models()
|
|
71
|
+
# ['hycoclip-vit-s', 'hycoclip-vit-b', 'meru-vit-s', 'meru-vit-b']
|
|
72
|
+
|
|
73
|
+
# Load model (auto-downloads from Hugging Face Hub)
|
|
74
|
+
model = hyper_models.load("hycoclip-vit-s")
|
|
75
|
+
model.geometry # 'hyperboloid'
|
|
76
|
+
model.dim # 513
|
|
77
|
+
|
|
78
|
+
# Encode PIL images
|
|
79
|
+
images = [Image.open("image.jpg")]
|
|
80
|
+
embeddings = model.encode_images(images) # (1, 513) ndarray
|
|
81
|
+
|
|
82
|
+
# Get model info
|
|
83
|
+
info = hyper_models.get_model_info("hycoclip-vit-s")
|
|
84
|
+
info.hub_id # 'mnm-matin/hyperbolic-clip'
|
|
85
|
+
info.license # 'CC-BY-NC'
|
|
86
|
+
|
|
87
|
+
# Low-level: preprocess images yourself
|
|
88
|
+
batch = hyper_models.preprocess_images(images) # (B, 3, 224, 224)
|
|
89
|
+
embeddings = model.encode(batch)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Models
|
|
93
|
+
|
|
94
|
+
### Hyperbolic
|
|
95
|
+
|
|
96
|
+
| Model | Available | Paper | Code |
|
|
97
|
+
|-------|:---------:|-------|------|
|
|
98
|
+
| `hycoclip-vit-s` | [](https://huggingface.co/mnm-matin/hyperbolic-clip/tree/main/hycoclip-vit-s) | [ICLR 2025](https://arxiv.org/abs/2410.06912) | [PalAvik/hycoclip](https://github.com/PalAvik/hycoclip) |
|
|
99
|
+
| `hycoclip-vit-b` | [](https://huggingface.co/mnm-matin/hyperbolic-clip/tree/main/hycoclip-vit-b) | [ICLR 2025](https://arxiv.org/abs/2410.06912) | [PalAvik/hycoclip](https://github.com/PalAvik/hycoclip) |
|
|
100
|
+
| `meru-vit-s` | [](https://huggingface.co/mnm-matin/hyperbolic-clip/tree/main/meru-vit-s) | [ICML 2023](https://arxiv.org/abs/2304.09172) | [facebookresearch/meru](https://github.com/facebookresearch/meru) |
|
|
101
|
+
| `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) |
|
|
102
|
+
| `hyp-vit` | — | [CVPR 2022](https://arxiv.org/abs/2203.10833) | [htdt/hyp_metric](https://github.com/htdt/hyp_metric) |
|
|
103
|
+
| `hie` | — | [CVPR 2020](https://arxiv.org/abs/1904.02239) | [leymir/hyperbolic-image-embeddings](https://github.com/leymir/hyperbolic-image-embeddings) |
|
|
104
|
+
| `hcnn` | — | [ICLR 2024](https://openreview.net/forum?id=ekz1hN5QNh) | [kschwethelm/HyperbolicCV](https://github.com/kschwethelm/HyperbolicCV) |
|
|
105
|
+
|
|
106
|
+
### Spherical
|
|
107
|
+
|
|
108
|
+
| Model | Available | Paper | Code |
|
|
109
|
+
|-------|:---------:|-------|------|
|
|
110
|
+
| `sphereface` | — | [CVPR 2017](https://arxiv.org/abs/1704.08063) | [wy1iu/sphereface](https://github.com/wy1iu/sphereface) |
|
|
111
|
+
| `arcface` | — | [CVPR 2019](https://arxiv.org/abs/1801.07698) | [deepinsight/insightface](https://github.com/deepinsight/insightface) |
|
|
112
|
+
|
|
113
|
+
### Product Manifolds
|
|
114
|
+
|
|
115
|
+
| Model | Available | Paper | Code |
|
|
116
|
+
|-------|:---------:|-------|------|
|
|
117
|
+
| `hyperbolics` | — | [ICLR 2019](https://openreview.net/forum?id=HJxeWnCcF7) | [HazyResearch/hyperbolics](https://github.com/HazyResearch/hyperbolics) |
|
|
118
|
+
|
|
119
|
+
## Export Tooling
|
|
120
|
+
|
|
121
|
+
This repo also contains tooling to export PyTorch models to ONNX:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
cd export/hycoclip
|
|
125
|
+
uv run python export_onnx.py --checkpoint model.pth --onnx model.onnx
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
See [export/hycoclip/README.md](export/hycoclip/README.md) for details.
|
|
129
|
+
|
|
130
|
+
## References
|
|
131
|
+
|
|
132
|
+
- [HyCoCLIP](https://github.com/PalAvik/hycoclip)
|
|
133
|
+
- [MERU](https://github.com/facebookresearch/meru)
|
|
134
|
+
- [geoopt](https://github.com/geoopt/geoopt)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# hyper-models
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>A model zoo for non-Euclidean embedding models</strong>
|
|
5
|
+
<br>
|
|
6
|
+
<em>Hyperbolic · Spherical · Product Manifolds</em>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://huggingface.co/mnm-matin/hyperbolic-clip">
|
|
11
|
+
<img src="https://img.shields.io/badge/🤗_Models-hyperbolic--clip-orange" alt="Hugging Face">
|
|
12
|
+
</a>
|
|
13
|
+
<a href="LICENSE">
|
|
14
|
+
<img src="https://img.shields.io/badge/License-MIT-blue" alt="License: MIT">
|
|
15
|
+
</a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Why?
|
|
21
|
+
|
|
22
|
+
- **Standardized access** to non-Euclidean embedding models
|
|
23
|
+
- **Torch-free runtime** via ONNX (models published to Hugging Face Hub)
|
|
24
|
+
- **Simple API** — `load()` and `encode_images()`
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install hyper-models
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
import hyper_models
|
|
36
|
+
from PIL import Image
|
|
37
|
+
|
|
38
|
+
# List available models
|
|
39
|
+
hyper_models.list_models()
|
|
40
|
+
# ['hycoclip-vit-s', 'hycoclip-vit-b', 'meru-vit-s', 'meru-vit-b']
|
|
41
|
+
|
|
42
|
+
# Load model (auto-downloads from Hugging Face Hub)
|
|
43
|
+
model = hyper_models.load("hycoclip-vit-s")
|
|
44
|
+
model.geometry # 'hyperboloid'
|
|
45
|
+
model.dim # 513
|
|
46
|
+
|
|
47
|
+
# Encode PIL images
|
|
48
|
+
images = [Image.open("image.jpg")]
|
|
49
|
+
embeddings = model.encode_images(images) # (1, 513) ndarray
|
|
50
|
+
|
|
51
|
+
# Get model info
|
|
52
|
+
info = hyper_models.get_model_info("hycoclip-vit-s")
|
|
53
|
+
info.hub_id # 'mnm-matin/hyperbolic-clip'
|
|
54
|
+
info.license # 'CC-BY-NC'
|
|
55
|
+
|
|
56
|
+
# Low-level: preprocess images yourself
|
|
57
|
+
batch = hyper_models.preprocess_images(images) # (B, 3, 224, 224)
|
|
58
|
+
embeddings = model.encode(batch)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Models
|
|
62
|
+
|
|
63
|
+
### Hyperbolic
|
|
64
|
+
|
|
65
|
+
| Model | Available | Paper | Code |
|
|
66
|
+
|-------|:---------:|-------|------|
|
|
67
|
+
| `hycoclip-vit-s` | [](https://huggingface.co/mnm-matin/hyperbolic-clip/tree/main/hycoclip-vit-s) | [ICLR 2025](https://arxiv.org/abs/2410.06912) | [PalAvik/hycoclip](https://github.com/PalAvik/hycoclip) |
|
|
68
|
+
| `hycoclip-vit-b` | [](https://huggingface.co/mnm-matin/hyperbolic-clip/tree/main/hycoclip-vit-b) | [ICLR 2025](https://arxiv.org/abs/2410.06912) | [PalAvik/hycoclip](https://github.com/PalAvik/hycoclip) |
|
|
69
|
+
| `meru-vit-s` | [](https://huggingface.co/mnm-matin/hyperbolic-clip/tree/main/meru-vit-s) | [ICML 2023](https://arxiv.org/abs/2304.09172) | [facebookresearch/meru](https://github.com/facebookresearch/meru) |
|
|
70
|
+
| `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) |
|
|
71
|
+
| `hyp-vit` | — | [CVPR 2022](https://arxiv.org/abs/2203.10833) | [htdt/hyp_metric](https://github.com/htdt/hyp_metric) |
|
|
72
|
+
| `hie` | — | [CVPR 2020](https://arxiv.org/abs/1904.02239) | [leymir/hyperbolic-image-embeddings](https://github.com/leymir/hyperbolic-image-embeddings) |
|
|
73
|
+
| `hcnn` | — | [ICLR 2024](https://openreview.net/forum?id=ekz1hN5QNh) | [kschwethelm/HyperbolicCV](https://github.com/kschwethelm/HyperbolicCV) |
|
|
74
|
+
|
|
75
|
+
### Spherical
|
|
76
|
+
|
|
77
|
+
| Model | Available | Paper | Code |
|
|
78
|
+
|-------|:---------:|-------|------|
|
|
79
|
+
| `sphereface` | — | [CVPR 2017](https://arxiv.org/abs/1704.08063) | [wy1iu/sphereface](https://github.com/wy1iu/sphereface) |
|
|
80
|
+
| `arcface` | — | [CVPR 2019](https://arxiv.org/abs/1801.07698) | [deepinsight/insightface](https://github.com/deepinsight/insightface) |
|
|
81
|
+
|
|
82
|
+
### Product Manifolds
|
|
83
|
+
|
|
84
|
+
| Model | Available | Paper | Code |
|
|
85
|
+
|-------|:---------:|-------|------|
|
|
86
|
+
| `hyperbolics` | — | [ICLR 2019](https://openreview.net/forum?id=HJxeWnCcF7) | [HazyResearch/hyperbolics](https://github.com/HazyResearch/hyperbolics) |
|
|
87
|
+
|
|
88
|
+
## Export Tooling
|
|
89
|
+
|
|
90
|
+
This repo also contains tooling to export PyTorch models to ONNX:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
cd export/hycoclip
|
|
94
|
+
uv run python export_onnx.py --checkpoint model.pth --onnx model.onnx
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
See [export/hycoclip/README.md](export/hycoclip/README.md) for details.
|
|
98
|
+
|
|
99
|
+
## References
|
|
100
|
+
|
|
101
|
+
- [HyCoCLIP](https://github.com/PalAvik/hycoclip)
|
|
102
|
+
- [MERU](https://github.com/facebookresearch/meru)
|
|
103
|
+
- [geoopt](https://github.com/geoopt/geoopt)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "hyper-models"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A model zoo for non-Euclidean embedding models (hyperbolic, spherical, product manifolds)"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = { text = "MIT" }
|
|
7
|
+
requires-python = ">=3.10"
|
|
8
|
+
authors = [{ name = "Hyper3Labs" }]
|
|
9
|
+
keywords = ["embeddings", "hyperbolic", "onnx", "clip", "model-zoo", "non-euclidean"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Development Status :: 3 - Alpha",
|
|
12
|
+
"Intended Audience :: Developers",
|
|
13
|
+
"Intended Audience :: Science/Research",
|
|
14
|
+
"License :: OSI Approved :: MIT License",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"numpy>=1.26",
|
|
23
|
+
"onnxruntime>=1.20",
|
|
24
|
+
"huggingface-hub>=1.0",
|
|
25
|
+
"pillow>=10.0",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.optional-dependencies]
|
|
29
|
+
dev = [
|
|
30
|
+
"pytest>=7.0",
|
|
31
|
+
"ruff>=0.1",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/Hyper3Labs/hyper-models"
|
|
36
|
+
Repository = "https://github.com/Hyper3Labs/hyper-models"
|
|
37
|
+
Documentation = "https://github.com/Hyper3Labs/hyper-models#readme"
|
|
38
|
+
Issues = "https://github.com/Hyper3Labs/hyper-models/issues"
|
|
39
|
+
|
|
40
|
+
[build-system]
|
|
41
|
+
requires = ["hatchling"]
|
|
42
|
+
build-backend = "hatchling.build"
|
|
43
|
+
|
|
44
|
+
[tool.hatch.build.targets.wheel]
|
|
45
|
+
packages = ["src/hyper_models"]
|
|
46
|
+
|
|
47
|
+
[tool.hatch.build.targets.sdist]
|
|
48
|
+
include = ["/src", "/README.md", "/LICENSE"]
|
|
49
|
+
|
|
50
|
+
[tool.ruff]
|
|
51
|
+
line-length = 100
|
|
52
|
+
target-version = "py310"
|
|
53
|
+
|
|
54
|
+
[tool.ruff.lint]
|
|
55
|
+
select = ["E", "F", "I", "W"]
|
|
56
|
+
ignore = ["E501"]
|
|
57
|
+
|
|
58
|
+
[tool.pytest.ini_options]
|
|
59
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""hyper-models: A model zoo for non-Euclidean embedding models.
|
|
2
|
+
|
|
3
|
+
Hyperbolic, spherical, and product manifold models with torch-free ONNX inference.
|
|
4
|
+
|
|
5
|
+
Example:
|
|
6
|
+
>>> import hyper_models
|
|
7
|
+
>>> model = hyper_models.load("hycoclip-vit-s")
|
|
8
|
+
>>> embeddings = model.encode_images([Image.open("photo.jpg")])
|
|
9
|
+
>>> model.geometry # 'hyperboloid'
|
|
10
|
+
>>> model.dim # 513
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from hyper_models.loader import load
|
|
14
|
+
from hyper_models.registry import ModelInfo, get_model_info, list_models
|
|
15
|
+
from hyper_models.models import ONNXModel
|
|
16
|
+
from hyper_models.preprocessing import ImageConfig, preprocess_images
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"load",
|
|
20
|
+
"list_models",
|
|
21
|
+
"get_model_info",
|
|
22
|
+
"ModelInfo",
|
|
23
|
+
"ONNXModel",
|
|
24
|
+
"ImageConfig",
|
|
25
|
+
"preprocess_images",
|
|
26
|
+
]
|
|
27
|
+
__version__ = "0.1.0"
|
|
28
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Model loading - download from Hub and instantiate."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from huggingface_hub import snapshot_download
|
|
8
|
+
|
|
9
|
+
from hyper_models.models import ONNXModel
|
|
10
|
+
from hyper_models.registry import get_model_info
|
|
11
|
+
|
|
12
|
+
__all__ = ["load"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def load(name: str, *, local_path: str | Path | None = None) -> ONNXModel:
|
|
16
|
+
"""Load a model by name.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
name: Model name (e.g., 'hycoclip-vit-s').
|
|
20
|
+
local_path: Optional local ONNX path (skips Hub download).
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
Model instance ready for inference.
|
|
24
|
+
|
|
25
|
+
Example:
|
|
26
|
+
>>> model = hyper_models.load("hycoclip-vit-s")
|
|
27
|
+
>>> embeddings = model.encode_images([Image.open("photo.jpg")])
|
|
28
|
+
"""
|
|
29
|
+
info = get_model_info(name)
|
|
30
|
+
|
|
31
|
+
if local_path is None:
|
|
32
|
+
hub_path = f"{info.name}/model.onnx"
|
|
33
|
+
local_dir = snapshot_download(info.hub_id, allow_patterns=[f"{hub_path}*"])
|
|
34
|
+
local_path = Path(local_dir) / hub_path
|
|
35
|
+
else:
|
|
36
|
+
local_path = Path(local_path)
|
|
37
|
+
|
|
38
|
+
return ONNXModel(
|
|
39
|
+
path=Path(local_path),
|
|
40
|
+
geometry=info.geometry,
|
|
41
|
+
dim=info.dim,
|
|
42
|
+
input_name=info.input_name,
|
|
43
|
+
output_name=info.output_name,
|
|
44
|
+
image_config=info.image_config,
|
|
45
|
+
)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""ONNX model wrapper for hyper-models."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
from PIL import Image
|
|
9
|
+
|
|
10
|
+
from hyper_models.preprocessing import ImageConfig, preprocess_images
|
|
11
|
+
|
|
12
|
+
__all__ = ["ONNXModel"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ONNXModel:
|
|
16
|
+
"""ONNX Runtime model wrapper for embedding inference."""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
path: Path,
|
|
21
|
+
geometry: str,
|
|
22
|
+
dim: int,
|
|
23
|
+
*,
|
|
24
|
+
input_name: str = "image",
|
|
25
|
+
output_name: str | None = None,
|
|
26
|
+
image_config: ImageConfig | None = None,
|
|
27
|
+
) -> None:
|
|
28
|
+
self._path = path
|
|
29
|
+
self.geometry = geometry
|
|
30
|
+
self.dim = dim
|
|
31
|
+
self._input_name = input_name
|
|
32
|
+
self._output_name = output_name
|
|
33
|
+
self._image_config = image_config or ImageConfig()
|
|
34
|
+
self._session = None
|
|
35
|
+
|
|
36
|
+
def _ensure_session(self) -> None:
|
|
37
|
+
if self._session is None:
|
|
38
|
+
import onnxruntime as ort
|
|
39
|
+
|
|
40
|
+
self._session = ort.InferenceSession(str(self._path), providers=["CPUExecutionProvider"])
|
|
41
|
+
|
|
42
|
+
def encode(self, inputs: np.ndarray) -> np.ndarray:
|
|
43
|
+
"""Encode preprocessed inputs (B, C, H, W) to embeddings (B, D)."""
|
|
44
|
+
self._ensure_session()
|
|
45
|
+
outputs = self._session.run(None, {self._input_name: inputs})
|
|
46
|
+
|
|
47
|
+
if self._output_name:
|
|
48
|
+
output_names = [o.name for o in self._session.get_outputs()]
|
|
49
|
+
return np.asarray(outputs[output_names.index(self._output_name)], dtype=np.float32)
|
|
50
|
+
|
|
51
|
+
return np.asarray(outputs[0], dtype=np.float32)
|
|
52
|
+
|
|
53
|
+
def encode_images(self, images: list[Image.Image]) -> np.ndarray:
|
|
54
|
+
"""Encode PIL images to embeddings (B, D)."""
|
|
55
|
+
return self.encode(preprocess_images(images, self._image_config))
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Image preprocessing for ONNX inference."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Literal
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
from PIL import Image
|
|
10
|
+
|
|
11
|
+
__all__ = ["preprocess_images", "ImageConfig"]
|
|
12
|
+
|
|
13
|
+
_RESAMPLE = {
|
|
14
|
+
"nearest": Image.Resampling.NEAREST,
|
|
15
|
+
"bilinear": Image.Resampling.BILINEAR,
|
|
16
|
+
"bicubic": Image.Resampling.BICUBIC,
|
|
17
|
+
"lanczos": Image.Resampling.LANCZOS,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True)
|
|
22
|
+
class ImageConfig:
|
|
23
|
+
"""Image preprocessing configuration (CLIP-style defaults)."""
|
|
24
|
+
|
|
25
|
+
size: int = 224
|
|
26
|
+
interpolation: Literal["nearest", "bilinear", "bicubic", "lanczos"] = "bicubic"
|
|
27
|
+
rescale: float = 1.0 / 255.0
|
|
28
|
+
mean: tuple[float, float, float] | None = None
|
|
29
|
+
std: tuple[float, float, float] | None = None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def preprocess_images(images: list[Image.Image], config: ImageConfig | None = None) -> np.ndarray:
|
|
33
|
+
"""Preprocess PIL images for ONNX inference.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
images: List of PIL Images.
|
|
37
|
+
config: Preprocessing config. Uses CLIP defaults if None.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
(B, 3, H, H) float32 array.
|
|
41
|
+
"""
|
|
42
|
+
config = config or ImageConfig()
|
|
43
|
+
resample = _RESAMPLE[config.interpolation]
|
|
44
|
+
|
|
45
|
+
batch = []
|
|
46
|
+
for img in images:
|
|
47
|
+
if img.mode != "RGB":
|
|
48
|
+
img = img.convert("RGB")
|
|
49
|
+
|
|
50
|
+
# Resize shortest side, then center crop
|
|
51
|
+
w, h = img.size
|
|
52
|
+
scale = config.size / min(w, h)
|
|
53
|
+
img = img.resize((int(round(w * scale)), int(round(h * scale))), resample=resample)
|
|
54
|
+
|
|
55
|
+
w, h = img.size
|
|
56
|
+
left, top = (w - config.size) // 2, (h - config.size) // 2
|
|
57
|
+
img = img.crop((left, top, left + config.size, top + config.size))
|
|
58
|
+
|
|
59
|
+
# To float32 CHW
|
|
60
|
+
arr = np.asarray(img, dtype=np.float32) * config.rescale
|
|
61
|
+
arr = np.transpose(arr, (2, 0, 1))
|
|
62
|
+
|
|
63
|
+
if config.mean is not None and config.std is not None:
|
|
64
|
+
mean = np.array(config.mean, dtype=np.float32).reshape(3, 1, 1)
|
|
65
|
+
std = np.array(config.std, dtype=np.float32).reshape(3, 1, 1)
|
|
66
|
+
arr = (arr - mean) / std
|
|
67
|
+
|
|
68
|
+
batch.append(arr)
|
|
69
|
+
|
|
70
|
+
return np.stack(batch, axis=0)
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Model registry - maps model names to hub locations and metadata."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
|
|
7
|
+
from hyper_models.preprocessing import ImageConfig
|
|
8
|
+
|
|
9
|
+
__all__ = ["ModelInfo", "list_models", "get_model_info"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class ModelInfo:
|
|
14
|
+
"""Metadata for a registered model."""
|
|
15
|
+
|
|
16
|
+
name: str
|
|
17
|
+
geometry: str # 'hyperboloid', 'poincare', 'sphere', 'euclidean'
|
|
18
|
+
dim: int
|
|
19
|
+
hub_id: str
|
|
20
|
+
license: str
|
|
21
|
+
description: str = ""
|
|
22
|
+
input_name: str = "image"
|
|
23
|
+
output_name: str | None = None
|
|
24
|
+
image_config: ImageConfig = field(default_factory=ImageConfig)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
_MODELS: dict[str, ModelInfo] = {
|
|
28
|
+
"hycoclip-vit-s": ModelInfo(
|
|
29
|
+
name="hycoclip-vit-s",
|
|
30
|
+
geometry="hyperboloid",
|
|
31
|
+
dim=513,
|
|
32
|
+
hub_id="mnm-matin/hyperbolic-clip",
|
|
33
|
+
license="CC-BY-NC",
|
|
34
|
+
description="HyCoCLIP ViT-Small (512D hyperboloid)",
|
|
35
|
+
output_name="embedding_hyperboloid",
|
|
36
|
+
),
|
|
37
|
+
"hycoclip-vit-b": ModelInfo(
|
|
38
|
+
name="hycoclip-vit-b",
|
|
39
|
+
geometry="hyperboloid",
|
|
40
|
+
dim=513,
|
|
41
|
+
hub_id="mnm-matin/hyperbolic-clip",
|
|
42
|
+
license="CC-BY-NC",
|
|
43
|
+
description="HyCoCLIP ViT-Base (512D hyperboloid)",
|
|
44
|
+
output_name="embedding_hyperboloid",
|
|
45
|
+
),
|
|
46
|
+
"meru-vit-s": ModelInfo(
|
|
47
|
+
name="meru-vit-s",
|
|
48
|
+
geometry="hyperboloid",
|
|
49
|
+
dim=513,
|
|
50
|
+
hub_id="mnm-matin/hyperbolic-clip",
|
|
51
|
+
license="CC-BY-NC",
|
|
52
|
+
description="MERU ViT-Small (512D hyperboloid)",
|
|
53
|
+
output_name="embedding_hyperboloid",
|
|
54
|
+
),
|
|
55
|
+
"meru-vit-b": ModelInfo(
|
|
56
|
+
name="meru-vit-b",
|
|
57
|
+
geometry="hyperboloid",
|
|
58
|
+
dim=513,
|
|
59
|
+
hub_id="mnm-matin/hyperbolic-clip",
|
|
60
|
+
license="CC-BY-NC",
|
|
61
|
+
description="MERU ViT-Base (512D hyperboloid)",
|
|
62
|
+
output_name="embedding_hyperboloid",
|
|
63
|
+
),
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def list_models(geometry: str | None = None) -> list[str]:
|
|
68
|
+
"""List available model names, optionally filtered by geometry."""
|
|
69
|
+
if geometry is None:
|
|
70
|
+
return list(_MODELS.keys())
|
|
71
|
+
return [name for name, info in _MODELS.items() if info.geometry == geometry]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_model_info(name: str) -> ModelInfo:
|
|
75
|
+
"""Get metadata for a model. Raises KeyError if not found."""
|
|
76
|
+
if name not in _MODELS:
|
|
77
|
+
raise KeyError(f"Model '{name}' not found. Available: {', '.join(_MODELS.keys())}")
|
|
78
|
+
return _MODELS[name]
|