From 1e0b785a795d7b84ebcd7700f9a9af907c223b5c Mon Sep 17 00:00:00 2001 From: sushant khemalapure Date: Wed, 8 Apr 2026 21:59:50 +0530 Subject: [PATCH 1/2] resolve Streamlit model paths relative to app directory --- .../__pycache__/app_streamlit.cpython-39.pyc | Bin 0 -> 20331 bytes .../code/app/app_streamlit.py | 54 ++++++++++++++---- 2 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 RenAIssance_Transformer_OCR_Utsav_Rai/code/app/__pycache__/app_streamlit.cpython-39.pyc diff --git a/RenAIssance_Transformer_OCR_Utsav_Rai/code/app/__pycache__/app_streamlit.cpython-39.pyc b/RenAIssance_Transformer_OCR_Utsav_Rai/code/app/__pycache__/app_streamlit.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d3d8648c7b6760b2f584c92001dd762c80a3a3da GIT binary patch literal 20331 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 Date: Wed, 29 Apr 2026 18:31:43 +0530 Subject: [PATCH 2/2] Make self-supervised OCR config portable --- .gitignore | 10 ++- .../README.md | 76 +++++++++++++---- .../check_config_paths.py | 85 +++++++++++++++++++ .../config.json | 20 ++--- .../data/.gitkeep | 1 + .../data/README.md | 13 +++ .../data/finetuning/.gitkeep | 1 + .../data/finetuning/ezcaray/.gitkeep | 1 + .../data/finetuning/ezcaray/word_images.csv | 1 + .../finetuning/ezcaray/word_images/.gitkeep | 1 + .../data/finetuning/perfecto/.gitkeep | 1 + .../data/finetuning/perfecto/word_images.csv | 1 + .../finetuning/perfecto/word_images/.gitkeep | 1 + .../data/finetuning/virtuosa/.gitkeep | 1 + .../data/finetuning/virtuosa/word_images.csv | 1 + .../finetuning/virtuosa/word_images/.gitkeep | 1 + .../data/ssl/.gitkeep | 1 + .../data/ssl/word_images/.gitkeep | 1 + .../models/.gitkeep | 1 + 19 files changed, 192 insertions(+), 26 deletions(-) create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/check_config_paths.py create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/.gitkeep create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/README.md create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/.gitkeep create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/ezcaray/.gitkeep create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/ezcaray/word_images.csv create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/ezcaray/word_images/.gitkeep create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/perfecto/.gitkeep create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/perfecto/word_images.csv create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/perfecto/word_images/.gitkeep create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/virtuosa/.gitkeep create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/virtuosa/word_images.csv create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/virtuosa/word_images/.gitkeep create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/ssl/.gitkeep create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/ssl/word_images/.gitkeep create mode 100644 RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/models/.gitkeep diff --git a/.gitignore b/.gitignore index f5f96cd2..beabcb52 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,11 @@ RenAIssance_Transformer_OCR_Utsav_Rai/weights RenAIssance_Transformer_OCR_Utsav_Rai/models -RenAIssance_Transformer_OCR_Utsav_Rai/quantized_model \ No newline at end of file +RenAIssance_Transformer_OCR_Utsav_Rai/quantized_model +RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/models/*.pt +RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/models/*.pth +RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/ssl/word_images/* +!RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/ssl/word_images/.gitkeep +RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/*/word_images/* +!RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/perfecto/word_images/.gitkeep +!RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/ezcaray/word_images/.gitkeep +!RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/virtuosa/word_images/.gitkeep diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/README.md b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/README.md index 4870d4b3..8a6d693a 100644 --- a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/README.md +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/README.md @@ -1,24 +1,70 @@ # Spanish Historical OCR using Self-Supervised Learning ## Overview -This repository implements a word-level OCR model for Renaissance Spanish documents using Self-Supervised Learning. The model was developed with reference to SeqCLR ([Aberdam A., et al., 2021](https://arxiv.org/abs/2012.10873)). According to the paper, SeqCLR employs a Contrastive Learning method, wherein its encoder learns to become robust against certain image transformations. The architecture includes a combination of ResNet50(or ViT tiny) and a 2-layer BiLSTM as the Encoder, and an Attention LSTM Decoder. At this point, the model achieves approximately 4% CER. This model can be tested in `test_model.ipynb`. For further information, please refer to my [blog](https://medium.com/@yamanko1234/historical-ocr-with-self-supervised-learning-c4f00da6637f). +This repository implements a word-level OCR model for Renaissance Spanish documents using self-supervised learning. The model was developed with reference to SeqCLR ([Aberdam A., et al., 2021](https://arxiv.org/abs/2012.10873)). According to the paper, SeqCLR uses contrastive learning so its encoder becomes robust to image transformations. The architecture combines a ResNet50 (or ViT tiny) and a 2-layer BiLSTM encoder with an attention LSTM decoder. + +At this point, the model achieves approximately 4% CER. This model can be tested in `test_model.ipynb`. For more background, see the [project blog post](https://medium.com/@yamanko1234/historical-ocr-with-self-supervised-learning-c4f00da6637f). + +## Portable Configuration +The default `config.json` now uses paths relative to this folder instead of machine-specific absolute paths. That makes the project easier to clone and configure on another machine. + +Populate the directories below with your local datasets and checkpoints, or update `config.json` to match your own layout: + +```text +RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/ +├── config.json +├── data/ +│ ├── ssl/ +│ │ └── word_images/ +│ └── finetuning/ +│ ├── perfecto/ +│ │ ├── word_images/ +│ │ └── word_images.csv +│ ├── ezcaray/ +│ │ ├── word_images/ +│ │ └── word_images.csv +│ └── virtuosa/ +│ ├── word_images/ +│ └── word_images.csv +├── models/ +└── test_images/ +``` + +The bundled `test_images/` folder is used as the default `test dataset` path so contributors can validate notebook setup without first changing that entry. + +Before running the notebooks, you can verify the configured paths: + +```bash +python check_config_paths.py +``` ## File/Folder Descriptions -- **Tokenizer**: A folder containing Tokenizer pickle files for the Decoder training. -- **test_image**: A folder containing images used for testing. -- **Decoder.py**: Implementation of the SeqCLR’s Decoder. -- **ResNet.py**: Implementation of ResNet, a component of the Encoder. -- **config.json**: A JSON file that sets the configuration for training. -- **custom_dataset.py**: Implementation of a custom dataset used in training. -- **decoder_training.ipynb**: A notebook to train the Decoder. -- **encoder.py**: Implementation of the SeqCLR’s Encoder. -- **ViT_encoder.py** Implementation of ViT version Encoder. -- **encoder_training.ipynb**: A notebook to train the Encoder. -- **test_model.ipynb**: A notebook to test a saved model. +- **Tokenizer**: Pickle files used for decoder training and decoding. +- **data**: Local SSL and fine-tuning datasets referenced by `config.json`. +- **models**: Saved encoder and decoder checkpoints. +- **test_images**: Sample images used for testing. +- **Decoder.py**: SeqCLR decoder implementation. +- **ResNet.py**: ResNet implementation used by the encoder. +- **config.json**: Training and inference configuration. +- **check_config_paths.py**: Helper script that verifies configured dataset and model paths exist. +- **custom_dataset.py**: Custom dataset implementations used in training. +- **decoder_training.ipynb**: Notebook for decoder training and evaluation. +- **encoder.py**: SeqCLR encoder implementation. +- **ViT encoder support**: The notebooks include an optional ViT encoder path controlled by `config.json`. +- **encoder_training.ipynb**: Notebook for encoder training. +- **test_model.ipynb**: Notebook for testing a saved model. ## Testing the Model -First, you need to install the dependencies: -``` +Install the dependencies: + +```bash pip install -r requirements.txt ``` -Then, you can test the saved model by executing the cells in `test_model.ipynb` one by one. \ No newline at end of file + +Confirm `config.json` points to valid paths for your environment: + +```bash +python check_config_paths.py +``` + +Then run the cells in `test_model.ipynb`. diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/check_config_paths.py b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/check_config_paths.py new file mode 100644 index 00000000..5026b2d3 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/check_config_paths.py @@ -0,0 +1,85 @@ +from __future__ import annotations + +import json +from pathlib import Path + + +PROJECT_ROOT = Path(__file__).resolve().parent +CONFIG_PATH = PROJECT_ROOT / "config.json" + + +def resolve_path(raw_path: str | None) -> str: + if raw_path is None: + return "" + return str((PROJECT_ROOT / raw_path).resolve()) + + +def path_exists(raw_path: str | None) -> bool | None: + if raw_path is None: + return None + return (PROJECT_ROOT / raw_path).exists() + + +def iter_config_paths(config: dict) -> list[tuple[str, str | None, bool]]: + return [ + ("SSL.dataset 1", config["SSL"].get("dataset 1"), True), + ("SSL.dataset 2", config["SSL"].get("dataset 2"), False), + ("SSL.dataset 3", config["SSL"].get("dataset 3"), False), + ("SSL.saved Encoder path", config["SSL"].get("saved Encoder path"), False), + ("fine-tuning.dataset 1", config["fine-tuning"].get("dataset 1"), True), + ("fine-tuning.dataset 1 csv", config["fine-tuning"].get("dataset 1 csv"), True), + ("fine-tuning.dataset 2", config["fine-tuning"].get("dataset 2"), False), + ("fine-tuning.dataset 2 csv", config["fine-tuning"].get("dataset 2 csv"), False), + ("fine-tuning.dataset 3", config["fine-tuning"].get("dataset 3"), False), + ("fine-tuning.dataset 3 csv", config["fine-tuning"].get("dataset 3 csv"), False), + ("fine-tuning.test dataset", config["fine-tuning"].get("test dataset"), True), + ( + "fine-tuning.Encoder path for fine-tuning", + config["fine-tuning"].get("Encoder path for fine-tuning"), + False, + ), + ( + "fine-tuning.Decoder path for fine-tuning", + config["fine-tuning"].get("Decoder path for fine-tuning"), + False, + ), + ("fine-tuning.char to token", config["fine-tuning"].get("char to token"), True), + ("fine-tuning.token to char", config["fine-tuning"].get("token to char"), True), + ("fine-tuning.saved Encoder path", config["fine-tuning"].get("saved Encoder path"), False), + ("fine-tuning.saved Decoder path", config["fine-tuning"].get("saved Decoder path"), False), + ] + + +def main() -> int: + with CONFIG_PATH.open("r", encoding="utf-8") as config_file: + config = json.load(config_file) + + print(f"Checking paths in {CONFIG_PATH}") + print() + + missing_required = False + for label, raw_path, must_exist in iter_config_paths(config): + exists = path_exists(raw_path) + absolute_path = resolve_path(raw_path) + if exists is None: + status = "OPTIONAL" + elif exists: + status = "OK" + elif not must_exist: + status = "OPTIONAL" + else: + status = "MISSING" + missing_required = True + print(f"[{status:<8}] {label}: {absolute_path}") + + print() + if missing_required: + print("Some configured paths are missing. Update config.json or place your data/models in the expected folders.") + return 1 + + print("All configured paths exist.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/config.json b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/config.json index 64209c53..2a0355d4 100644 --- a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/config.json +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/config.json @@ -3,23 +3,23 @@ "ViT": false }, "SSL": { - "dataset 1": "/home/yukinori/Desktop/CRAFT-pytorch/self_supervised_data/word_images", + "dataset 1": "data/ssl/word_images", "dataset 2": null, "dataset 3": null, "epoch size": 1, "Batch size": 32, "start lr": 0.001, "lr scheduler step size": 2, - "saved Encoder path": "ViT_encoder.pth" + "saved Encoder path": "models/ViT_encoder.pth" }, "fine-tuning": { - "dataset 1": "/home/yukinori/Desktop/CRAFT-pytorch/Perfecto/Perfecto/word_images", - "dataset 1 csv": "/home/yukinori/Desktop/CRAFT-pytorch/Perfecto/Perfecto/word_images.csv", - "dataset 2": "/home/yukinori/Desktop/CRAFT-pytorch/Ezcaray/word_images", - "dataset 2 csv": "/home/yukinori/Desktop/CRAFT-pytorch/Ezcaray/word_images.csv", - "dataset 3": "/home/yukinori/Desktop/CRAFT-pytorch/Virtuosa/word_images", - "dataset 3 csv": "/home/yukinori/Desktop/CRAFT-pytorch/Virtuosa/word_images.csv", - "test dataset": "/home/yukinori/Desktop/CRAFT-pytorch/self_supervised_data/word_images", + "dataset 1": "data/finetuning/perfecto/word_images", + "dataset 1 csv": "data/finetuning/perfecto/word_images.csv", + "dataset 2": "data/finetuning/ezcaray/word_images", + "dataset 2 csv": "data/finetuning/ezcaray/word_images.csv", + "dataset 3": "data/finetuning/virtuosa/word_images", + "dataset 3 csv": "data/finetuning/virtuosa/word_images.csv", + "test dataset": "test_images", "fine-tune on other dataset": true, "Encoder path for fine-tuning": "models/trdg_Encoder_9_13.pt", "Decoder path for fine-tuning": "models/trdg_Decoder_9_13.pt", @@ -33,4 +33,4 @@ "saved Encoder path": "models/trdg_fine_tuned_Encoder_withoutSSL_9_13.pt", "saved Decoder path": "models/trdg_fine_tuned_Decoder_withoutSSL_9_13.pt" } -} \ No newline at end of file +} diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/.gitkeep b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/.gitkeep @@ -0,0 +1 @@ + diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/README.md b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/README.md new file mode 100644 index 00000000..3d78119c --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/README.md @@ -0,0 +1,13 @@ +Place local training data under this directory. + +Expected layout: + +- `data/ssl/word_images/` +- `data/finetuning/perfecto/word_images/` +- `data/finetuning/perfecto/word_images.csv` +- `data/finetuning/ezcaray/word_images/` +- `data/finetuning/ezcaray/word_images.csv` +- `data/finetuning/virtuosa/word_images/` +- `data/finetuning/virtuosa/word_images.csv` + +These paths match the defaults in `config.json`. diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/.gitkeep b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/.gitkeep @@ -0,0 +1 @@ + diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/ezcaray/.gitkeep b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/ezcaray/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/ezcaray/.gitkeep @@ -0,0 +1 @@ + diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/ezcaray/word_images.csv b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/ezcaray/word_images.csv new file mode 100644 index 00000000..43291c31 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/ezcaray/word_images.csv @@ -0,0 +1 @@ +label,image diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/ezcaray/word_images/.gitkeep b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/ezcaray/word_images/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/ezcaray/word_images/.gitkeep @@ -0,0 +1 @@ + diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/perfecto/.gitkeep b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/perfecto/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/perfecto/.gitkeep @@ -0,0 +1 @@ + diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/perfecto/word_images.csv b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/perfecto/word_images.csv new file mode 100644 index 00000000..43291c31 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/perfecto/word_images.csv @@ -0,0 +1 @@ +label,image diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/perfecto/word_images/.gitkeep b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/perfecto/word_images/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/perfecto/word_images/.gitkeep @@ -0,0 +1 @@ + diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/virtuosa/.gitkeep b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/virtuosa/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/virtuosa/.gitkeep @@ -0,0 +1 @@ + diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/virtuosa/word_images.csv b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/virtuosa/word_images.csv new file mode 100644 index 00000000..43291c31 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/virtuosa/word_images.csv @@ -0,0 +1 @@ +label,image diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/virtuosa/word_images/.gitkeep b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/virtuosa/word_images/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/finetuning/virtuosa/word_images/.gitkeep @@ -0,0 +1 @@ + diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/ssl/.gitkeep b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/ssl/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/ssl/.gitkeep @@ -0,0 +1 @@ + diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/ssl/word_images/.gitkeep b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/ssl/word_images/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/data/ssl/word_images/.gitkeep @@ -0,0 +1 @@ + diff --git a/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/models/.gitkeep b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/models/.gitkeep new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/RenAIssance_SelfSupervisedLearning_OCR_YukinoriYamamoto/models/.gitkeep @@ -0,0 +1 @@ +