Skip to content

Simplify store #18234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Aug 8, 2023
Merged
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
71 changes: 0 additions & 71 deletions .azure/app-cloud-store.yml

This file was deleted.

10 changes: 5 additions & 5 deletions .github/checkgroup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -302,18 +302,18 @@ subprojects:

- id: "lightning: Store"
paths:
- ".azure/app-cloud-store.yml"
- ".github/workflows/ci-tests-store.yml"
- "src/lightning/__about__.py"
- "src/lightning/__init__.py"
- "src/lightning/__main__.py"
- "src/lightning/__setup__.py"
- "src/lightning/__version__.py"
- "src/lightning/store/**"
- "tests/tests_cloud/**"
- "tests/tests_store/**"
checks:
- "Store.cloud (test_store Linux)"
- "Store.cloud (test_store Mac)"
- "Store.cloud (test_store Windows)"
- "store-cpu (macOS-11, lightning, 3.10, 2.0)"
- "store-cpu (ubuntu-20.04, lightning, 3.10, 2.0)"
- "store-cpu (windows-2022, lightning, 3.10, 2.0)"

# FixMe: re-enable when BE stabilize
# - id: "lightning_app: Azure"
Expand Down
92 changes: 92 additions & 0 deletions .github/workflows/ci-tests-store.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
name: Test Store

# see: https://help.github.com/en/actions/reference/events-that-trigger-workflows
on:
push:
branches: [master, "release/*"]
pull_request:
branches: [master, "release/*"]
types: [opened, reopened, ready_for_review, synchronize] # added `ready_for_review` since draft is skipped
paths:
- ".actions/*"
- "requirements/store/**"
- "src/lightning/store/**"
- "tests/tests_store/**"
- "pyproject.toml" # includes pytest config
- ".github/workflows/ci-tests-store.yml"
- "!requirements/*/docs.txt"
- "!*.md"
- "!**/*.md"

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.head_ref }}
cancel-in-progress: ${{ ! (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release/')) }}

defaults:
run:
shell: bash

jobs:
store-cpu:
runs-on: ${{ matrix.os }}
if: github.event.pull_request.draft == false
strategy:
fail-fast: false
matrix:
os: ["macOS-11", "ubuntu-20.04", "windows-2022"]
pkg-name: ["lightning"]
python-version: ["3.10"]
pytorch-version: ["2.0"]
timeout-minutes: 25 # because of building grpcio on Mac
env:
PACKAGE_NAME: ${{ matrix.pkg-name }}
FREEZE_REQUIREMENTS: ${{ ! (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release/')) }}
# PYPI_CACHE_DIR: "_pip-wheels"
TORCH_URL_STABLE: "https://download.pytorch.org/whl/cpu/torch_stable.html"
steps:
- uses: actions/checkout@v3

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Adjust PyTorch versions in requirements files
if: ${{ matrix.requires != 'oldest' && matrix.release != 'pre' }}
run: |
pip install -q wget packaging
python -m wget https://raw.githubusercontent.com/Lightning-AI/utilities/main/scripts/adjust-torch-versions.py
for fpath in `ls requirements/store/*.txt`; do \
python ./adjust-torch-versions.py $fpath ${{ matrix.pytorch-version }}; \
done

- name: Install package & dependencies
run: |
python -m pip install -q pip -U
pip install -e ".[store-test]" "pytest-timeout" -U -f ${TORCH_URL} --prefer-binary
pip list

- name: Testing Store
working-directory: tests/tests_store
# NOTE: do not include coverage report here, see: https://github.com/nedbat/coveragepy/issues/1003
run: |
python -m coverage run --source lightning \
-m pytest -v --timeout=60 --durations=60

- name: Statistics
if: success()
working-directory: tests/tests_store
run: |
coverage report
coverage xml

- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
# see: https://github.com/actions/toolkit/issues/399
continue-on-error: true
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: tests/tests_store/coverage.xml
flags: lightning,cpu,pytest,python${{ matrix.python-version }}
name: CPU-coverage
fail_ci_if_error: false
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ known_first_party = [
"parity_pytorch",
"integrations_app",
"tests_app",
"tests_cloud",
"tests_store",
"tests_fabric",
"tests_pytorch",
]
Expand Down
5 changes: 5 additions & 0 deletions requirements/store/test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
coverage ==7.2.7
pytest ==7.4.0
pytest-cov ==4.1.0
pytest-rerunfailures ==10.3
pytest-random-order ==1.1.0
1 change: 1 addition & 0 deletions src/lightning/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from lightning.pytorch.trainer import Trainer # noqa: E402

import lightning.app # isort: skip # noqa: E402
import lightning.store # isort: skip # noqa: E402

lightning.app._PROJECT_ROOT = os.path.dirname(lightning.app._PROJECT_ROOT)

Expand Down
80 changes: 11 additions & 69 deletions src/lightning/store/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
- Store your models on the cloud \<-- simple call: `upload_model(...)`. 🗳️
- Share it with your friends \<-- just share the "username/model_name" (and version if required) format. :handshake:
- They download using a simple call: `download_model("username/model_name", version="your_version")`. :wink:
- They load your cool model. `load_model("username/model_name", version="your_version")`. :tada:
- Lightning :zap: fast, isn't it?. :heart:

## Usage
Expand All @@ -13,87 +12,30 @@

```python
import lightning as L
from sample.model import LitAutoEncoder, Encoder, Decoder

# Initialize your model here
autoencoder = LitAutoEncoder(Encoder(), Decoder())
# Upload a checkpoint:
L.store.upload_model("mnist_model", "mnist_model.ckpt")

# Pass the model object:
# No need to pass the username (we'll deduce ourselves), just pass the model name you want as the first argument (with an optional version):
# format: `model_name:version` (version can either be latest or combination of digits and full-stops: 1.0.0 for example)
L.store.upload_model("unique_model_mnist", model=autoencoder, source_code_path="sample")

# version:
L.store.upload_model(
"unique_model_mnist",
version="1.0.0",
model=autoencoder,
source_code_path="sample/model.py",
)

# OR: (this will save the file which has the model defined)
L.store.upload_model("krshrimali/unique_model_mnist", model=autoencoder)
```

You can also pass the checkpoint path: `upload_model("model_name", version="latest", checkpoint_path=...)`.

**Downloading from the cloud**

At first, you need to download the model to your local machine.

```python
import lightning as L

L.store.download_model(
"krshrimali/unique_model_mnist",
output_dir="your_output_dir",
)
# OR: (default to model_storage
# $HOME
# |- .lightning
# | |- model_store
# | | |- username
# | | | |- <model_name>
# | | | | |- version_<version_with_dots_replaced_by_underscores>
# folder)
L.store.download_model("krshrimali/unique_model_mnist")
# Optionally provide a version:
L.store.upload_model("mnist_model", "mnist_model.ckpt", version="1.0.0")
```

**Loading model**

Then you can load the model to your program.
**List your models**

```python
import lightning as L

# from <username>.<model_name>.version_<version_with_dots_replaced_by_underscores>.<model_source_file> import LitAutoEncoder, Encoder, Decoder
model = L.store.load_model("<username>/<model_name>>", version="version") # version is optional (defaults to latest)
models = L.store.list_models()

# OR: load weights or checkpoint (if they were uploaded)
L.store.load_model(
"<username>/<model_name>", version="version", load_weights=True | False, load_checkpoint=True | False
)
print(model)
print([model.name for model in models])
# ['username/mnist_model']
```

**Loading model weights**
**Downloading from the cloud**

```python
import lightning as L
from sample.model import LitAutoEncoder, Encoder, Decoder

# If you had passed an `output_dir=...` to download_model(...), then you can just do:
# from output_dir.<model_source_file> import LitAutoEncoder, Encoder, Decoder

model = LitAutoEncoder(Encoder(), Decoder())

model = L.store.load_model(load_weights=True, model=model)
print("State dict: ", model.state_dict())
# Download a checkpoint
L.store.download_model("username/mnist_model", "any_path.ckpt")
```

Loading checkpoint is similar, just do: `load_checkpoint=True`.

## Known limitations

- missing web UI for user to brows his uploads
- missing CLI/API to list and delete uploaded models
4 changes: 2 additions & 2 deletions src/lightning/store/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from lightning.store.cloud_api import download_model, load_model, upload_model
from lightning.store.store import download_model, list_models, upload_model

__all__ = ["download_model", "load_model", "upload_model"]
__all__ = ["download_model", "upload_model", "list_models"]
64 changes: 0 additions & 64 deletions src/lightning/store/authentication.py

This file was deleted.

Loading