chore: import upstream snapshot with attribution
docs / deploy (push) Has been cancelled
docs / changes (push) Has been cancelled
docs / check-and-build (push) Has been cancelled
build container image / cpu (push) Has been cancelled
build container image / cuda (push) Has been cancelled
build container image / rocm (push) Has been cancelled
frontend checks / frontend-checks (push) Has been cancelled
frontend tests / frontend-tests (push) Has been cancelled
lfs checks / lfs-check (push) Has been cancelled
python checks / python-checks (push) Has been cancelled
python tests / py3.12: macos-default (push) Has been cancelled
python tests / py3.11: windows-cpu (push) Has been cancelled
python tests / py3.12: windows-cpu (push) Has been cancelled
python tests / py3.11: linux-cpu (push) Has been cancelled
typegen checks / typegen-checks (push) Has been cancelled
uv lock checks / uv-lock-checks (push) Has been cancelled
openapi checks / openapi-checks (push) Has been cancelled
python tests / py3.11: macos-default (push) Has been cancelled
python tests / py3.12: linux-cpu (push) Has been cancelled
docs / deploy (push) Has been cancelled
docs / changes (push) Has been cancelled
docs / check-and-build (push) Has been cancelled
build container image / cpu (push) Has been cancelled
build container image / cuda (push) Has been cancelled
build container image / rocm (push) Has been cancelled
frontend checks / frontend-checks (push) Has been cancelled
frontend tests / frontend-tests (push) Has been cancelled
lfs checks / lfs-check (push) Has been cancelled
python checks / python-checks (push) Has been cancelled
python tests / py3.12: macos-default (push) Has been cancelled
python tests / py3.11: windows-cpu (push) Has been cancelled
python tests / py3.12: windows-cpu (push) Has been cancelled
python tests / py3.11: linux-cpu (push) Has been cancelled
typegen checks / typegen-checks (push) Has been cancelled
uv lock checks / uv-lock-checks (push) Has been cancelled
openapi checks / openapi-checks (push) Has been cancelled
python tests / py3.11: macos-default (push) Has been cancelled
python tests / py3.12: linux-cpu (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
# Model Probe (Identification) Testing
|
||||
|
||||
Invoke's model Identification system is tested against example model files. Test cases are lightweight representations of real models which have been "stripped" of their tensor data.
|
||||
|
||||
## Setup
|
||||
|
||||
Test cases are stored with git lfs. You _must_ [install git lfs](https://git-lfs.com/) to pull down the test cases and add to them.
|
||||
|
||||
```bash
|
||||
# Only need to do this once
|
||||
git lfs install
|
||||
# Pull the actual model files down - if you just do `git pull` you'll only get pointers
|
||||
git lfs pull
|
||||
```
|
||||
|
||||
## Running the Tests
|
||||
|
||||
To run the tests use:
|
||||
|
||||
```bash
|
||||
pytest -v tests/test_model_probe/test_identification.py
|
||||
```
|
||||
|
||||
## Stripped Model Files
|
||||
|
||||
Invoke abstracts the loading of a model's state dict and metadata in a class called [`ModelOnDisk`](../../invokeai/backend/model_manager/model_on_disk.py). This class loads real model weights. We use it to inspect models and identify them.
|
||||
|
||||
For testing purposes, we create a stripped-down version of model weights that contain only the model structure and metadata for each key, without the actual tensor data. The state dict structure is typically all we need to identify models; the tensors themselves are not needed. This allows us to store test cases in the repo without adding many gigabytes of data.
|
||||
|
||||
To see how this works, check out [`StrippedModelOnDisk`](./stripped_model_on_disk.py). This class includes logic to strip models and to load these stripped models for testing.
|
||||
|
||||
### Some Models Cannot Be Stripped
|
||||
|
||||
Certain models cannot be stripped because identification relies on inspecting the actual tensor data. We have to store the full model files for these test cases.
|
||||
|
||||
> Currently, the only models that cannot be stripped are [`spandrel`](https://github.com/chaiNNer-org/spandrel/) image-to-image models. `spandrel` supports _many_ model architectures but doesn't provide a way to identify or assert support for a model by its state dict structure alone.
|
||||
>
|
||||
> To positively identify these models, we must attempt to load the model using spandrel. If it loads successfully, we assume it is a supported model. Therefore, we cannot strip these models and must store the full model files in the test cases. We only store one such model to keep the test suite size manageable.
|
||||
>
|
||||
> `StrippedModelOnDisk` will simply pass-through the "live" tensor data for these models when loading them to test.
|
||||
|
||||
## Adding New Test Cases
|
||||
|
||||
Run the [`strip_model.py`](./strip_model.py) script to create a new test case. For example:
|
||||
|
||||
```bash
|
||||
python strip_model.py /path/to/your/model --output_dir ./stripped_models
|
||||
```
|
||||
|
||||
It supports single-file models and multi-file models (e.g. diffusers-style models). The output will be a directory named with a UUID, containing the stripped model files and a dummy `__test_metadata__.json` file.
|
||||
|
||||
Example output structure for a single-file model:
|
||||
|
||||
```
|
||||
stripped_models/
|
||||
└── 19fd1a40-c5b7-4734-bd3a-6e0e948cce0b/
|
||||
├── __test_metadata__.json
|
||||
└── Standard Reference (XLabs FLUX IP-Adapter v2).safetensors
|
||||
```
|
||||
|
||||
This test metadata file should contain a single JSON dict and must be filled out manually with the expected identification results.
|
||||
|
||||
### Structure of `__test_metadata__.json`
|
||||
|
||||
This file contains a single JSON dict. Here's an example for a FLUX IP Adapter checkpoint:
|
||||
|
||||
```json
|
||||
{
|
||||
"source": "https://huggingface.co/XLabs-AI/flux-ip-adapter-v2/resolve/main/ip_adapter.safetensors",
|
||||
"file_name": "Standard Reference (XLabs FLUX IP-Adapter v2).safetensors",
|
||||
"expected_config_attrs": {
|
||||
"type": "ip_adapter",
|
||||
"format": "checkpoint",
|
||||
"base": "flux"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
See the details below for each field.
|
||||
|
||||
#### `"source"`
|
||||
|
||||
A string indicating the source of the model (e.g. a Hugging Face repo ID or URL). This is not used for identification, but is useful for reference so we know where the model came from. Nothing will break if this field is missing or incorrect, but it is good practice to fill it out.
|
||||
|
||||
- Example HF Repo ID: `"RunDiffusion/Juggernaut-XL-v9"`
|
||||
- Example URL: `"https://huggingface.co/XpucT/Deliberate/resolve/main/Deliberate_v5.safetensors"`
|
||||
|
||||
#### `"file_name"`
|
||||
|
||||
If the model is a single file (e.g. a `.safetensors` file), this is the name of that file. The test suite will look for this file in the test case directory.
|
||||
|
||||
If the model is multi-file (e.g. diffusers-style), omit this key or set it to a falsey value like `null` or an empty string.
|
||||
|
||||
- Example: `"model.safetensors"`
|
||||
|
||||
> The `strip_model.py` script will automatically fill this field in for single-file models.
|
||||
|
||||
#### `"expected_config_attrs"`
|
||||
|
||||
This field is a dict of expected configuration attributes for the model. It is required for all test cases.
|
||||
|
||||
It is used to verify that the model's configuration matches expectations. The keys and values in this dict depend on the specific model and its configuration.
|
||||
|
||||
These attributes must be included, as they are the primary discriminators for models:
|
||||
|
||||
- `"type"`: The type of the model. This is the value of the `ModelType` enum.
|
||||
- `"format"`: The format of the model files. This is the value of the `ModelFormat` enum.
|
||||
- `"base"`: The base model pipeline architecture associated with this model. Many models do not have an associated base. For these, use `"any"`. This is the value of the `BaseModelType` enum.
|
||||
|
||||
Depending on the kind of model, these additional keys may be useful:
|
||||
|
||||
- `"prediction_type"`: The prediction type used by the model. This is the value of the `SchedulerPredictionType` enum.
|
||||
- `"variant"`: The variant of the model, if applicable. This is the value of the `ModelVariantType` enum.
|
||||
|
||||
To see all possible values for these enums, check out their definitions in [`invokeai/backend/model_manager/taxonomy.py`](../../invokeai/backend/model_manager/taxonomy.py).
|
||||
|
||||
For example, for a SD1.5 main (pipeline) inpainting model in diffusers format, you might have:
|
||||
|
||||
```json
|
||||
{
|
||||
"expected_config_attrs": {
|
||||
"type": "main",
|
||||
"format": "diffusers",
|
||||
"base": "sd-1",
|
||||
"prediction_type": "epsilon",
|
||||
"variant": "inpaint"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `"notes"`
|
||||
|
||||
This is an optional string field where you can add any notes or comments about the test case. It can be useful for providing context or explaining any special considerations.
|
||||
|
||||
#### `"override_fields"`
|
||||
|
||||
In some rare cases, we may need to provide additional hints to the identification system to help it identify the model correctly.
|
||||
|
||||
Currently, the only known case where we need extra information is to differentiate between single-file SD1.x, SD2.x and SDXL VAEs. These models have identical structures, so we need to provide a hint. Though it is far from ideal, we use simple string matching on the model's name to provide this hint.
|
||||
|
||||
For example, when users install the `taesdxl` VAE from the HF repo `madebyollin/taesdxl`, the identification system will get the model name `taesdxl`. It sees "xl" in the name and infers that this is a SDXL VAE. To reproduce this in a test case, we add the following to `__test_metadata__.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"override_fields": {
|
||||
"name": "taesdxl"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,112 @@
|
||||
"""
|
||||
Usage:
|
||||
strip_model.py <model_path> <output_dir>
|
||||
|
||||
Strips tensor data from model state_dict while preserving metadata.
|
||||
Used to create lightweight models for testing model classification.
|
||||
|
||||
Parameters:
|
||||
<model_path> The path to the model to be stripped.
|
||||
<output_dir> Directory where stripped models will be saved (e.g. tests/test_model_probe/stripped_models)
|
||||
|
||||
Options:
|
||||
-h, --help Show this help message and exit
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import shutil
|
||||
import sys
|
||||
from copy import deepcopy
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import humanize
|
||||
|
||||
from invokeai.app.util.misc import uuid_string
|
||||
from invokeai.backend.model_manager.model_on_disk import ModelOnDisk
|
||||
from tests.model_identification.stripped_model_on_disk import StrippedModelOnDisk
|
||||
|
||||
TEST_METADATA_FILENAME = "__test_metadata__.json"
|
||||
|
||||
|
||||
TEST_METADATA: dict[str, Any] = {
|
||||
"source": "",
|
||||
"file_name": "",
|
||||
"override_fields": {},
|
||||
"expected_config_attrs": {},
|
||||
"notes": "",
|
||||
}
|
||||
|
||||
|
||||
def create_stripped_model(model_path: Path, output_dir: Path):
|
||||
"""Creates a stripped version of the model at model_path in output_dir. A test metadata file is also created."""
|
||||
|
||||
original_mod = ModelOnDisk(model_path)
|
||||
|
||||
# The stripped model will be stored in a new directory named with a UUID. This mirrors the application's
|
||||
# normalized model storage file structure.
|
||||
uuid = uuid_string()
|
||||
stripped_model_dir = output_dir / uuid
|
||||
stripped_model_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
test_metadata_content = deepcopy(TEST_METADATA)
|
||||
|
||||
if original_mod.path.is_file():
|
||||
shutil.copy2(original_mod.path, stripped_model_dir / original_mod.path.name)
|
||||
test_metadata_content["file_name"] = original_mod.path.name
|
||||
else:
|
||||
shutil.copytree(original_mod.path, stripped_model_dir, dirs_exist_ok=True)
|
||||
|
||||
stripped_mod = ModelOnDisk(stripped_model_dir)
|
||||
|
||||
print(f"Created clone of {original_mod.name} at {stripped_mod.path}")
|
||||
|
||||
for component_path in stripped_mod.weight_files():
|
||||
original_state_dict = stripped_mod.load_state_dict(component_path)
|
||||
|
||||
stripped_state_dict = StrippedModelOnDisk.strip(original_state_dict)
|
||||
metadata = stripped_mod.metadata()
|
||||
contents = {**stripped_state_dict, StrippedModelOnDisk.METADATA_KEY: metadata}
|
||||
component_path.write_text(json.dumps(contents, indent=2))
|
||||
|
||||
test_metadata_path = stripped_model_dir / TEST_METADATA_FILENAME
|
||||
test_metadata_path.write_text(json.dumps(test_metadata_content, indent=2))
|
||||
|
||||
before_size = humanize.naturalsize(original_mod.size())
|
||||
after_size = humanize.naturalsize(stripped_mod.size())
|
||||
|
||||
print(f"{original_mod.name} before: {before_size}, after: {after_size}")
|
||||
|
||||
return stripped_mod
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
class Parser(argparse.ArgumentParser):
|
||||
def error(self, message: str):
|
||||
raise ValueError(message)
|
||||
|
||||
parser = Parser()
|
||||
parser.add_argument("model_path", type=Path)
|
||||
parser.add_argument("output_dir", type=Path)
|
||||
|
||||
try:
|
||||
args = parser.parse_args()
|
||||
except ValueError as e:
|
||||
print(f"Error: {e}", file=sys.stderr)
|
||||
print(__doc__, file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
if not args.model_path.exists():
|
||||
parser.error(f"Error: Input model path '{args.model_path}' does not exist.")
|
||||
|
||||
return args
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = parse_arguments()
|
||||
|
||||
model_path = Path(args.model_path)
|
||||
output_dir = Path(args.output_dir)
|
||||
|
||||
create_stripped_model(model_path, output_dir)
|
||||
@@ -0,0 +1,83 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
|
||||
import gguf
|
||||
import torch
|
||||
|
||||
from invokeai.backend.model_manager.model_on_disk import ModelOnDisk, StateDict
|
||||
from invokeai.backend.quantization.gguf.ggml_tensor import GGMLTensor
|
||||
|
||||
|
||||
class StrippedModelOnDisk(ModelOnDisk):
|
||||
METADATA_KEY = "metadata_key_for_stripped_models"
|
||||
STR_TO_DTYPE = {str(dtype): dtype for dtype in torch.__dict__.values() if isinstance(dtype, torch.dtype)}
|
||||
|
||||
def load_state_dict(self, path: Optional[Path] = None) -> StateDict:
|
||||
path = self.resolve_weight_file(path)
|
||||
return self.load_stripped_model(path)
|
||||
|
||||
def metadata(self, path: Optional[Path] = None) -> dict[str, str]:
|
||||
path = self.resolve_weight_file(path)
|
||||
with open(path, "r") as f:
|
||||
contents = json.load(f)
|
||||
return contents.get(self.METADATA_KEY, {})
|
||||
|
||||
@classmethod
|
||||
def strip(cls, v: Any):
|
||||
match v:
|
||||
case GGMLTensor():
|
||||
# GGMLTensor needs special handling to preserve quantization metadata. It is a subclass of torch.Tensor,
|
||||
# so we need to check for it before checking for torch.Tensor.
|
||||
return {
|
||||
"quantized_data": cls.strip(v.quantized_data),
|
||||
"ggml_quantization_type": v._ggml_quantization_type.name,
|
||||
"tensor_shape": list(v.tensor_shape),
|
||||
"compute_dtype": str(v.compute_dtype),
|
||||
"fakeGGMLTensor": True,
|
||||
}
|
||||
case torch.Tensor():
|
||||
return {"shape": v.shape, "dtype": str(v.dtype), "fakeTensor": True}
|
||||
case dict():
|
||||
return {k: cls.strip(v) for k, v in v.items()}
|
||||
case list() | tuple():
|
||||
return [cls.strip(x) for x in v]
|
||||
case _:
|
||||
return v
|
||||
|
||||
@classmethod
|
||||
def dress(cls, v: Any):
|
||||
match v:
|
||||
case {
|
||||
"quantized_data": quantized_data,
|
||||
"ggml_quantization_type": qtype_name,
|
||||
"tensor_shape": tensor_shape,
|
||||
"compute_dtype": compute_dtype_str,
|
||||
"fakeGGMLTensor": True,
|
||||
}:
|
||||
# Reconstruct the GGMLTensor from stripped data
|
||||
qtype = gguf.GGMLQuantizationType[qtype_name]
|
||||
compute_dtype = cls.STR_TO_DTYPE[compute_dtype_str]
|
||||
dressed_quantized_data = cls.dress(quantized_data)
|
||||
return GGMLTensor(
|
||||
data=dressed_quantized_data,
|
||||
ggml_quantization_type=qtype,
|
||||
tensor_shape=torch.Size(tensor_shape),
|
||||
compute_dtype=compute_dtype,
|
||||
)
|
||||
case {"shape": shape, "dtype": dtype_str, "fakeTensor": True}:
|
||||
dtype = cls.STR_TO_DTYPE[dtype_str]
|
||||
return torch.empty(shape, dtype=dtype, device="meta")
|
||||
case dict():
|
||||
return {k: cls.dress(v) for k, v in v.items()}
|
||||
case list() | tuple():
|
||||
return [cls.dress(x) for x in v]
|
||||
case _:
|
||||
return v
|
||||
|
||||
@classmethod
|
||||
def load_stripped_model(cls, path: Path, *args, **kwargs):
|
||||
with open(path, "r") as f:
|
||||
contents = json.load(f)
|
||||
contents.pop(cls.METADATA_KEY, None)
|
||||
return cls.dress(contents)
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b9203265975f0a76fce9435a52d7c406bf0a78c33aace1d790aaaee82145f108
|
||||
size 160
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b5b8f9a7619c9452f19407ef73a01ce3f061fcf932de43ddbaca336d12d02801
|
||||
size 1235
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:764b113f9978f30219a355c559e198aa2e400ad93ee42e90b8b18e5c45d620e2
|
||||
size 137262
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:764b113f9978f30219a355c559e198aa2e400ad93ee42e90b8b18e5c45d620e2
|
||||
size 137262
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f406592ff8542bc6c441b1b9ce7b7871969d4934b71f197d356c542bfc6100dc
|
||||
size 421
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3fe679f2af6b172b4359708cc9d499d0731796a1a5695c3561284892be37d910
|
||||
size 158706
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5cc69c42f1579faa712d66cc7864d2dd49b9cb75b032182a446295f290f71ac1
|
||||
size 170
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a8b619cf6d992fccde14c00af034a7d58516642acb6dc9b6ea2c4f233a026312
|
||||
size 1230
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d713facffb33213a0893e7386c29c1b088361713beff027a21d8bbfd1a732fed
|
||||
size 137262
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8cc85c48a1a03c570280424807982b57d8a93dbb341ecf9a8751b9a49490d865
|
||||
size 165
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:190f74eab53d6605b4587e8635930602341e6a0ba10a2b2cae6f44c93fad7e40
|
||||
size 251
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9f2acce0645d1450869c1e941cced0544dfe2ae64d56ef3642c4975dac79f4a3
|
||||
size 242
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b79928d2b392f4b530bd4afd1ba32f029c57ad57543bd3efbaf20709f4e0c7a0
|
||||
size 2812
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4380556fba7a05d8095ab7373d2cf054b3dc6f637d69760ff3259dd912a1c309
|
||||
size 161
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:625d37b31afbf2f0792a87846b3654ee23f20568409e35b78a1f795b04e1a7a1
|
||||
size 560
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:43baf829cca18f27b6c561e422965c05ad81fe032e381eb9d2ab87bf679eaad9
|
||||
size 79623
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:14992635efcb76a20a07d90dc79faaedabf16113c82ecf29104436af0bf184af
|
||||
size 13469
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6ca25466bbe5b289a9a77c43c12b607775d204e23c2691595f9afbe7d4fefa74
|
||||
size 288
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5a5f1a97f5f940688c2249cf8cd23bc38e2cbe20243c10b39e2611883f2835ab
|
||||
size 161
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7b3ffef6d26ad273aad2fe8cddb9d225f4d5bc8962dcc9c9987925c46a1b2adc
|
||||
size 998
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:95618921255d678347fa7ba4490afeef084a27a49c42c14cf99cde29306eb74d
|
||||
size 52258
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c54537e57e94fa4493a0da78af4e0d37d1f3ee6f5216605185e5943f666f48a9
|
||||
size 162
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b92e42e1f42918321c1a927d5ae7a128b16e95e0570961fb7af69c10472c761c
|
||||
size 999
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:95618921255d678347fa7ba4490afeef084a27a49c42c14cf99cde29306eb74d
|
||||
size 52258
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f31e6051478d14a1cc49c6a62c1c5f3735761ba8ec86e6833e634bb81703bf4d
|
||||
size 160
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5cbf68b91bd3065716b88b9ef85785023fef6f59ffae2d5762b05553cef9450d
|
||||
size 1274
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:764b113f9978f30219a355c559e198aa2e400ad93ee42e90b8b18e5c45d620e2
|
||||
size 137262
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5972b48f1ee690922e944b4cc58a8cfe8fff5548febd67641fc468c5de678106
|
||||
size 193
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:33e0fb93dadacb864bd2f2e8441e147daa2baceb67f94d3ef5283b495572cea0
|
||||
size 122
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2466d1704df30f0067f28d8e30e0190a1bf74e5b430942697af974d162a056bd
|
||||
size 826
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:839a4fba0bd6949f0db22d4f840935cb0318f6ac28b29c9ce1a5b15735a4a740
|
||||
size 2591
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:89dc53229f50b59570b6852056dafeac8116c458f1a748bff491b6d4d24d3b51
|
||||
size 126
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8831e4f1a044471340f7c0a83d7bd71306a5b867e95fd870f74d0c5308a904d5
|
||||
size 1671853
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a0e4b0349d188ce8618b4cfdc01f87d58f912bf9c55cfb8a2d80b9ecae39a870
|
||||
size 136697
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3644c108b9f0fa53e62ff422a9be6639642f0e64dab4a71f961c7911d4386384
|
||||
size 1732
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:04e9899e93f2a412c94e153cab4081457c9a44defb3b2c0b9df673d42c42cdd0
|
||||
size 178
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f4f79e08d97f4d1c87f8d89264f525c8789da3b73b3bb55d1e12f692f41a7b1b
|
||||
size 367
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3c0ce3213b50ff38d8aa1e91136a2d2cb142a3f569246170872e439cb2a29d15
|
||||
size 7028579
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:494a5592a446535be00acc531ccf7a53fd6c6c392c122d444c389160261572e0
|
||||
size 1800
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1e71b2e75b90ddf696692529485b4a75fd54ecd4bbc03e2cc7be4af032875765
|
||||
size 428
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ca10d7e9fb3ed18575dd1e277a2579c16d108e32f27439684afa0e10b1440910
|
||||
size 2776833
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7b7055054103676636b98eb87e6f712fbfa1d32fe61d2839ac91e6dd8efdf569
|
||||
size 160
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b5b8f9a7619c9452f19407ef73a01ce3f061fcf932de43ddbaca336d12d02801
|
||||
size 1235
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:764b113f9978f30219a355c559e198aa2e400ad93ee42e90b8b18e5c45d620e2
|
||||
size 137262
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:30c2bc3cc3a01876bb237332ce046c3914d59200ecc2d266e1c7b3bb8c03e6a1
|
||||
size 108625
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d99c6db720916e6fdc756c1270f6547f755386901e96cb989b252656e9459be8
|
||||
size 240
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f08ce127136cb04fea2ace436533a8117b1aaefc3c7d86740336ffc35e8028d8
|
||||
size 163
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1fe6a5da6d1c39714934544613352f02fe755bf3ee07c726521a8d50e007db95
|
||||
size 1988
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7f3cddb8d6c5c36ef1a4248c600c8cf72f70ced509d087229a4e15b3e947d4ae
|
||||
size 118855
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e3b3402f5d83838bfddc533d14ab0226c0654345b3c21b2b58de9184da4e5829
|
||||
size 159
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8f13c37bac4c495785d6b5edcd604c013776690794d2dddff7579bbc70960801
|
||||
size 996
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:95618921255d678347fa7ba4490afeef084a27a49c42c14cf99cde29306eb74d
|
||||
size 52258
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:836d3065e0ddf91ac744a46c489d01701c413b2bf2cf56ac57537b65d278578f
|
||||
size 156
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8a09b467700c58138c29d53c605b34ebc69beaadd13274a8a2af8ad2c2f4032a
|
||||
size 4519
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6b28d56fdb9a2048a6ae38bf6afcc781d555300f2bb537c4b4c4a4a15412fe78
|
||||
size 89593
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:587cdb874c248b9ee9ff5c2e258d717cbec9ddc088eb5984a1332f947c774758
|
||||
size 157
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:eff7d79f38df62238b62951a87eeb942ffbc06d4f25c58cd838dab3ad9174758
|
||||
size 994
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:95618921255d678347fa7ba4490afeef084a27a49c42c14cf99cde29306eb74d
|
||||
size 52258
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:75d154190528bace5b3b8f5e9300964edf4c7d991ae01cf55cd7248ac5358f03
|
||||
size 160
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c6488d01fc339c83d777b6d71df4f5bc36c035b2c977f987e8a5c0a54c79b706
|
||||
size 955
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d89c76fb682a4c29a668c84d33ac2503f7f7ed4219aa2f70e4fc6779962e2303
|
||||
size 52258
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9f639b0732cb9544db020c515b163e2c9f65995f9fcb1efff441c5b9f5337062
|
||||
size 503787
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ec1a9b5b5f451306aa2660dec27db9e66c5c2b12cd9506dca4cdfe961f6bae46
|
||||
size 253
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bdcc653ce6538878e8e4b96552a17048c95387a210431deecfd531a8ef7822df
|
||||
size 207
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:153b1da39e7cc780003d5b25eb8d07b9c84b08cc20fd05b95652e780a15c8011
|
||||
size 667
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:db6b4739b5e23285a9552ec7c59de7ce40f6a4a3562fc1eccbd843f6444e5102
|
||||
size 496
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:47ced7a4ab2ecec78818ac4e8e1578c66253c2b93861c67c0b6d6c33ce3ff829
|
||||
size 565
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1664c0837272bb24919c0a5b6b9fb6970eed2fbfc21d58f87a4ca126f1732023
|
||||
size 29272
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d9f7e7eb1e2d162908ecf7925234425c4f1c978152fd60e18e4af2c67ccebb19
|
||||
size 575
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e4d60954dc9025adad03bc8512700adb50b0726f71971902e2d48b81a93a7ce6
|
||||
size 78037
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9fd691f7c8039210e0fced15865466c65820d09b63988b0174bfe25de299051a
|
||||
size 524619
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2cdb3b8331a60c92fc1e55a13e9fd61fd2293c5a51275fdcccd62b780052530e
|
||||
size 588
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6bdcee9ccce2a16ca2b4c0c5ed00b42c50ea225f4472a8c4c1e963a2902c2881
|
||||
size 705
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e089ad92ba36837a0d31433e555c8f45fe601ab5c221d4f607ded32d9f7a4349
|
||||
size 1059962
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9fd691f7c8039210e0fced15865466c65820d09b63988b0174bfe25de299051a
|
||||
size 524619
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c934044566ac411c4739e9cec969e061e8dcdf2bd108196a66ce917376d4d68e
|
||||
size 462
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e70eb3e2b85a508e32bb81c32c13fc3f2b015548ca469b94627c2f32e445cba1
|
||||
size 856
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e089ad92ba36837a0d31433e555c8f45fe601ab5c221d4f607ded32d9f7a4349
|
||||
size 1059962
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:73cd3f7bd618835b6d09eefd5155b84ccdeea07c32a4d201574af19bd405a5bc
|
||||
size 1778
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8572891666dca7988bc7cdab5ea18a206c7d6ab9e84d619da19d0babdff35777
|
||||
size 273411
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bcbed358bb80da88bc8b61785b7d14c39b5be5745d813e4c6a56e9084d4dc9d2
|
||||
size 607
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:57f04fab20ea8867d504056b1c04f807247f0760c59a5ee4ae733977a5797416
|
||||
size 36362
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6109f6f70e72601468fde241c3b20e37f35a468c4271352c5837fb0fbf8f68b3
|
||||
size 33769
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a562c7040fd26f65ba8a6d6803595c32e3a4f6a547f0cbc6e4297bc4b24e3f3e
|
||||
size 215
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9804b670940d0923d209724b4cadd30cc305fc307f55878e608b3f6d18d1c892
|
||||
size 225
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6ea2ee286dd9a1b1275fdb02222808590d0084b470aea9861a263c7e6a30aeb5
|
||||
size 2934
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e6289a8c39add7a686eb605c0f1c55f2b630ac2098d7ddbf75aa7e39fe169803
|
||||
size 162
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:aa6fecc8745c0d0b26f0d2ca0f686600c8b33177c667d44eb41a51e56e44a697
|
||||
size 999
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:95618921255d678347fa7ba4490afeef084a27a49c42c14cf99cde29306eb74d
|
||||
size 52258
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a388e94405bf905efe5ba92d0b144db6e44d7becadc670c05e6e09d922209071
|
||||
size 197
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6f638fb9401a6d6296feff533ee7efe657b787c49f954f82f5906b36ef2a1b1f
|
||||
size 520
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fcee0918cf5816238f4fd35ce1bdc329616b6213ada6dbf5a22953c71390aa35
|
||||
size 642
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:55ce0f16fe75a93e1da5873db2e9acee88a6e2982891cf118490a684cdfae408
|
||||
size 796
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0a3950c0fd1dd49873439bb933edf269630d909526467527f8227f7e71c0dc83
|
||||
size 65438
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:725c528a8f6f91d3e11a543718f1066b6d1682a147483c1a4a4aecf67fd9c824
|
||||
size 614
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:52e29b35e93261515dc07bf248ec8398a729e54f1886e946f8c095ede26be29b
|
||||
size 724
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user