Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions docs/introduction/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@ You can find CUDA installers on [NVIDIA CUDA Toolkit Archive Website](https://de
- Install [SSCMA](https://github.com/Seeed-Studio/ModelAssistant) deps

```sh
pip3 install openmim && \
pip3 install -r requirements/base.txt && \
mim install -r requirements/mmlab.txt && \
mim install -e .
pip3 install -e . --no-deps
```

### Step 4 - Install Extra Dependencies (Optional)
Expand Down Expand Up @@ -124,16 +125,18 @@ Or you can do the configuration manually using Conda's configuration file.
conda env create -n sscma -f environment.yml && \
conda activate sscma && \
pip3 install -r requirements/inference.txt -r requirements/export.txt -r requirements/tests.txt && \
pip3 install openmim && \
mim install -r requirements/mmlab.txt && \
mim install -e .
pip3 install -e . --no-deps
```

```sh [GPU (CUDA)]
conda env create -n sscma -f environment_cuda.yml && \
conda activate sscma && \
pip3 install -r requirements/inference.txt -r requirements/export.txt -r requirements/tests.txt && \
pip3 install openmim && \
mim install -r requirements/mmlab.txt && \
mim install -e .
pip3 install -e . --no-deps
```

:::
Expand Down
9 changes: 6 additions & 3 deletions docs/zh_cn/introduction/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@ conda activate sscma
- 安装 [SSCMA](https://github.com/Seeed-Studio/ModelAssistant) 依赖项

```sh
pip3 install openmim && \
pip3 install -r requirements/base.txt && \
mim install -r requirements/mmlab.txt && \
mim install -e .
pip3 install -e . --no-deps
```

### 第 4 步 - 安装额外依赖项(可选)
Expand Down Expand Up @@ -124,16 +125,18 @@ bash scripts/setup_linux.sh
conda env create -n sscma -f environment.yml && \
conda activate sscma && \
pip3 install -r requirements/inference.txt -r requirements/export.txt -r requirements/tests.txt && \
pip3 install openmim && \
mim install -r requirements/mmlab.txt && \
mim install -e .
pip3 install -e . --no-deps
```

```sh [GPU(CUDA)]
conda env create -n sscma -f environment_cuda.yml && \
conda activate sscma && \
pip3 install -r requirements/inference.txt -r requirements/export.txt -r requirements/tests.txt && \
pip3 install openmim && \
mim install -r requirements/mmlab.txt && \
mim install -e .
pip3 install -e . --no-deps
```

:::
Expand Down
13 changes: 4 additions & 9 deletions notebooks/Google-Colab-SWFIT-YOLO-A1101-Example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,8 @@
},
"outputs": [],
"source": [
"# Ethos-U-Vela need to be installed this way, or SSCMA does not work anymore...\n",
"!git clone https://review.mlplatform.org/ml/ethos-u/ethos-u-vela.git\n",
"%cd ethos-u-vela\n",
"!pip install .\n",
"%cd..\n",
"!git clone https://github.com/Seeed-Studio/SSCMA.git # currently we're using experimental 2.0 version branch\n",
"%cd /content/SSCMA"
"!git clone https://github.com/Seeed-Studio/ModelAssistant.git -b 2.0.0\n",
"%cd ModelAssistant"
]
},
{
Expand All @@ -67,7 +62,7 @@
"id": "LWAE--J9sAmW"
},
"source": [
"**Step 1:** Install python third-party library"
"**Step 1:** Install the dependencies. The setup script installs a modern PyTorch-compatible dependency stack and compiles [MMCV](https://github.com/open-mmlab/mmcv) from source (there are no prebuilt MMCV wheels for recent PyTorch/Python versions), which takes about 10-15 minutes on Colab."
]
},
{
Expand All @@ -78,7 +73,7 @@
},
"outputs": [],
"source": [
"!pip install ."
"!bash scripts/setup_colab.sh"
]
},
{
Expand Down
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
[build-system]
# PEP 517/660 build via setuptools. Without this, pip falls back to the
# deprecated legacy `setup.py egg_info`/`setup.py develop` path, which is
# removed in newer pip releases and fails on modern environments (e.g. Colab).
requires = ["setuptools>=64,<81", "wheel"]
build-backend = "setuptools.build_meta"

[tool.isort]
profile = "black"

Expand Down
14 changes: 11 additions & 3 deletions requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,24 @@ libusb1

# sensor
cbor
numpy>=1.23.0,<2.0.0
# numpy < 2.3: numba (preinstalled on Colab) requires numpy < 2.3, while
# everything else in a modern image (opencv 5, jax, ml-dtypes, tensorflow
# 2.20, h5py, keras) requires numpy >= 2. A numpy < 2.0 pin forces a numpy
# 1.26 source build on Python 3.13 and makes pip downgrade half of the
# preinstalled stack (opencv, keras, ml-dtypes, h5py, vela).
numpy>=1.23.0,<2.3.0



# vision
opencv-python>=4.9.0.80


# openmmlab package manager
openmim>=0.3.7
# NOTE: openmim is intentionally NOT listed here. It pulls in `openxlab`,
# which hard-pins `setuptools~=60.2.0` - a version too old to build anything
# on Python >= 3.12 (pkgutil.ImpImporter was removed). If you need the `mim`
# command, install it separately with `pip install openmim` and mind your
# setuptools version afterwards.
packaging>=23.1
pandas>=2.0.0
pillow>=9.4.0
Expand Down
10 changes: 9 additions & 1 deletion requirements/export.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,12 @@ TinyNeuralNetwork @ https://files.seeedstudio.com/sscma/library/TinyNeuralNetwor
pnnx

# vela
ethos-u-vela
# NOTE: pinned to a range with prebuilt wheels for Python >= 3.12.
# ethos-u-vela <= 4.1.0 ships sdists only and its legacy setup.py fails to
# build on Python >= 3.12 (needs flatbuffers at build time). Worse, vela
# 3.7.0 declares NO dependencies at all, so pip's resolver can always
# backtrack to it when anything else conflicts - silently turning a
# dependency conflict into a source build that then fails.
# 5.1.0 is verified with tools/export.py and the vela CLI flags used in the
# docs/notebooks; bump the ceiling after re-verifying.
ethos-u-vela>=4.2.0,<=5.1.0
8 changes: 7 additions & 1 deletion requirements/inference.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
libusb1>=3.0.0
pnnx==0.0.4
# NOTE: keep unpinned. The previous pin (==0.0.4) resolved to an ancient
# placeholder release, and it conflicts with the unpinned pnnx in
# requirements/export.txt.
pnnx
ncnn>=1.0.20230517
onnx>=1.14.0
# torch.onnx.export uses the dynamo exporter by default since PyTorch 2.9,
# which requires onnxscript
onnxscript>=0.1.0
onnxmltools>=1.11.2
onnxruntime>=1.15.1
onnxsim>=0.4.33
Expand Down
16 changes: 11 additions & 5 deletions requirements/mmlab.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# use openmim to install
mmcls>=1.0.0.rc6
mmcv-full<=2.1.0
mmdet>=3.0.0, <3.1.0 # mmyolo currently does not support mmdet 3.1.0
mmengine>=0.8.2
# OpenMMLab dependencies
# NOTE: mmcv 2.2.0 is the last mmcv release and the only one that compiles
# against recent PyTorch (>= 2.6). There are no prebuilt mmcv wheels for
# recent PyTorch/Python combinations, so mmcv must be built from source
# (scripts/setup_colab.sh does this). mmdet 3.0.x / mmcls 1.0.0rc6 hard-code
# an mmcv < 2.1.0 ceiling at import time; use scripts/patch_mmlab_versions.py
# to relax that assertion after installation.
mmcls>=1.0.0rc6
mmcv>=2.2.0,<=2.2.0
mmdet>=3.0.0,<3.1.0
mmengine>=0.8.2,<1.0.0
10 changes: 7 additions & 3 deletions requirements/pytorch_cpu.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
-i https://download.pytorch.org/whl/cpu

torch<=2.0.1
torchaudio<=2.0.2
torchvision<=0.15.2
# NOTE: no upper version bound on purpose. The previous ceiling (torch<=2.0.1)
# has no wheels for Python >= 3.12 and made the whole installation fail.
# torch/torchvision/torchaudio versions must stay mutually compatible;
# on Google Colab the preinstalled versions are used as-is.
torch>=2.1.0
torchaudio>=2.1.0
torchvision>=0.16.0
14 changes: 9 additions & 5 deletions requirements/pytorch_cuda.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
-i https://download.pytorch.org/whl/cu118

torch<=2.0.1
torchaudio<=2.0.2
torchvision<=0.15.2
# NOTE: no upper version bound on purpose. The previous ceiling (torch<=2.0.1)
# has no wheels for Python >= 3.12 and made the whole installation fail.
# Modern PyPI torch wheels already bundle the CUDA runtime, so no custom
# index URL is required anymore. torch/torchvision/torchaudio versions must
# stay mutually compatible; on Google Colab the preinstalled versions are
# used as-is.
torch>=2.1.0
torchaudio>=2.1.0
torchvision>=0.16.0
144 changes: 144 additions & 0 deletions scripts/patch_mmlab_versions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#!/usr/bin/env python3
# Copyright (c) Seeed Technology Co.,Ltd. All rights reserved.
"""Relax the hard-coded MMCV upper-version assertions of mmdet/mmcls.

mmdet 3.0.x and mmcls 1.0.0rc6 assert ``mmcv < 2.1.0`` at import time.
We deliberately use mmcv 2.2.0 - the final mmcv release and the only one
that compiles against recent PyTorch (>= 2.6) - so the assertion must be
relaxed in the *installed* packages.

The patch is applied in-place to the installed ``__init__.py`` files and
fails loudly if the expected pattern is not found (e.g. the package
versions drifted), instead of silently doing nothing.

Usage:
python scripts/patch_mmlab_versions.py # patch
python scripts/patch_mmlab_versions.py --verify # patch + import check
"""

import argparse
import importlib.util
import os
import re
import sys

# packages -> new mmcv maximum version (mmcv 3.x does not exist, so this
# effectively disables the upper bound while remaining an explicit bound)
PACKAGES = {
'mmdet': '3.0.0',
'mmcls': '3.0.0',
}

PATTERN = re.compile(r"mmcv_maximum_version\s*=\s*['\"][\d.]+['\"]")


def patch_package(name: str, new_maximum: str) -> bool:
spec = importlib.util.find_spec(name)
if spec is None or not spec.submodule_search_locations:
print(f'[SKIP] {name} is not installed')
return False

init_file = os.path.join(spec.submodule_search_locations[0], '__init__.py')
with open(init_file, 'r', encoding='utf-8') as f:
content = f.read()

replacement = f"mmcv_maximum_version = '{new_maximum}'"
patched, count = PATTERN.subn(replacement, content)

if count == 0:
if f"mmcv_maximum_version = '{new_maximum}'" in content:
print(f'[OK] {name}: already patched ({init_file})')
return True
print(f'[FAIL] {name}: no mmcv_maximum_version found in {init_file}')
print(' The installed version may have changed - please check it manually.')
return False

with open(init_file, 'w', encoding='utf-8') as f:
f.write(patched)
print(f'[OK] {name}: mmcv_maximum_version -> {new_maximum} ({init_file})')
return True


ADAFACTOR_OLD = " OPTIMIZERS.register_module(name='Adafactor', module=Adafactor)\n transformer_optimizers.append('Adafactor')"
ADAFACTOR_NEW = (
" if 'Adafactor' not in OPTIMIZERS:\n"
" OPTIMIZERS.register_module(name='Adafactor', module=Adafactor)\n"
" transformer_optimizers.append('Adafactor')"
)


def patch_mmengine_adafactor() -> bool:
"""Guard mmengine's transformers-Adafactor registration.

mmengine (<= 0.10.7, including the current upstream) unconditionally
registers transformers' Adafactor when transformers is installed. Since
torch >= 2.9 ships torch.optim.Adafactor - already registered under the
same name - importing mmengine.optim crashes with
``KeyError: 'Adafactor is already registered in optimizer ...'`` whenever
both torch >= 2.9 and transformers are present (both are preinstalled on
Colab).
"""
spec = importlib.util.find_spec('mmengine')
if spec is None or not spec.submodule_search_locations:
print('[SKIP] mmengine is not installed')
return False

builder_file = os.path.join(
spec.submodule_search_locations[0], 'optim', 'optimizer', 'builder.py'
)
with open(builder_file, 'r', encoding='utf-8') as f:
content = f.read()

if ADAFACTOR_NEW in content:
print(f'[OK] mmengine: Adafactor guard already present ({builder_file})')
return True
if ADAFACTOR_OLD not in content:
print(f'[FAIL] mmengine: Adafactor registration pattern not found in {builder_file}')
print(' The installed mmengine version may have changed - please check it manually.')
return False

with open(builder_file, 'w', encoding='utf-8') as f:
f.write(content.replace(ADAFACTOR_OLD, ADAFACTOR_NEW))
print(f'[OK] mmengine: guarded Adafactor registration ({builder_file})')
return True


def verify_imports() -> bool:
ok = True
for name in ('mmcv', 'mmdet', 'mmcls', 'mmengine'):
try:
module = __import__(name)
print(f'[OK] import {name} {module.__version__}')
except Exception as exc: # noqa: BLE001
print(f'[FAIL] import {name}: {exc}')
ok = False
if ok:
try:
# triggers the optimizer registration code paths
from mmengine.optim.optimizer import OPTIMIZERS # noqa: F401

print('[OK] mmengine optimizer registry builds')
except Exception as exc: # noqa: BLE001
print(f'[FAIL] mmengine optimizer registry: {exc}')
ok = False
return ok


def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--verify', action='store_true', help='also verify the patched packages can be imported')
args = parser.parse_args()

results = [patch_package(name, maximum) for name, maximum in PACKAGES.items()]
results.append(patch_mmengine_adafactor())
if not all(results):
sys.exit(1)

if args.verify and not verify_imports():
sys.exit(1)

print('Done.')


if __name__ == '__main__':
main()
Loading