From 907b60662dc464268ec0840d2b75af7991da3ad6 Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Mon, 15 Jul 2024 18:07:21 -0400 Subject: [PATCH 01/15] Module 3 --- module-3/classic-example/Makefile | 4 +-- .../classic-example/classic_example/cli.py | 6 ++-- .../classic-example/classic_example/data.py | 10 +++--- .../pipeline_api.py | 0 .../pipeline_open.py | 0 module-3/generative-example/Makefile | 17 ++-------- module-3/generative-example/README.md | 2 +- .../generative_example/config.py | 1 - .../generative_example/predictor.py | 2 +- module-3/generative-example/tests/conftest.py | 32 ------------------- module-3/generative-example/tests/test_llm.py | 21 ------------ 11 files changed, 14 insertions(+), 81 deletions(-) rename module-3/{generative-example/generative_example => generative-api}/pipeline_api.py (100%) rename module-3/{generative-example/generative_example => generative-api}/pipeline_open.py (100%) delete mode 100644 module-3/generative-example/tests/test_llm.py diff --git a/module-3/classic-example/Makefile b/module-3/classic-example/Makefile index 06e6a71..a0f9698 100644 --- a/module-3/classic-example/Makefile +++ b/module-3/classic-example/Makefile @@ -29,12 +29,12 @@ test_all: pytest --cov=classic_example tests/ train_example: - python classic_example/cli.py load-cola-data ./data + python classic_example/cli.py load-sst2-data ./data python classic_example/cli.py train ./conf/example.json python classic_example/cli.py upload-to-registry example_model /tmp/results train_fast_ci: - python classic_example/cli.py load-cola-data ./data + python classic_example/cli.py load-sst2-data ./data python classic_example/cli.py train ./conf/fast.json python classic_example/cli.py upload-to-registry fast-model /tmp/results \ No newline at end of file diff --git a/module-3/classic-example/classic_example/cli.py b/module-3/classic-example/classic_example/cli.py index 726424f..018a5df 100644 --- a/module-3/classic-example/classic_example/cli.py +++ b/module-3/classic-example/classic_example/cli.py @@ -1,14 +1,14 @@ import typer -from classic_example.data import load_cola_data, load_cola_data_file_input +from classic_example.data import load_sst2_data, load_sst2_data_file_input from classic_example.train import train from classic_example.utils import load_from_registry, upload_to_registry from classic_example.predictor import run_inference_on_dataframe app = typer.Typer() app.command()(train) -app.command()(load_cola_data) -app.command()(load_cola_data_file_input) +app.command()(load_sst2_data) +app.command()(load_sst2_data_file_input) app.command()(upload_to_registry) app.command()(load_from_registry) app.command()(run_inference_on_dataframe) diff --git a/module-3/classic-example/classic_example/data.py b/module-3/classic-example/classic_example/data.py index 0109860..f3f0d13 100644 --- a/module-3/classic-example/classic_example/data.py +++ b/module-3/classic-example/classic_example/data.py @@ -5,7 +5,7 @@ from sklearn.model_selection import train_test_split -def _get_cola_data(random_state: int = 42): +def _get_sst2_data(random_state: int = 42): dataset = load_dataset("glue", "sst2") df_all = ArrowReader.read_table( dataset.cache_files["train"][0]["filename"] @@ -19,24 +19,24 @@ def _get_cola_data(random_state: int = 42): return df_train, df_val, df_test -def load_cola_data(path_to_save: Path): +def load_sst2_data(path_to_save: Path): path_to_save.mkdir(parents=True, exist_ok=True) - df_train, df_val, df_test = _get_cola_data() + df_train, df_val, df_test = _get_sst2_data() df_train.to_csv(path_to_save / "train.csv", index=False) df_val.to_csv(path_to_save / "val.csv", index=False) df_test.to_csv(path_to_save / "test.csv", index=False) -def load_cola_data_file_input( +def load_sst2_data_file_input( path_to_train: Path, path_to_val: Path, path_to_test: Path ): path_to_train.parent.mkdir(parents=True, exist_ok=True) path_to_val.parent.mkdir(parents=True, exist_ok=True) path_to_test.parent.mkdir(parents=True, exist_ok=True) - df_train, df_val, df_test = _get_cola_data() + df_train, df_val, df_test = _get_sst2_data() df_train.to_csv(path_to_train, index=False) df_val.to_csv(path_to_val, index=False) diff --git a/module-3/generative-example/generative_example/pipeline_api.py b/module-3/generative-api/pipeline_api.py similarity index 100% rename from module-3/generative-example/generative_example/pipeline_api.py rename to module-3/generative-api/pipeline_api.py diff --git a/module-3/generative-example/generative_example/pipeline_open.py b/module-3/generative-api/pipeline_open.py similarity index 100% rename from module-3/generative-example/generative_example/pipeline_open.py rename to module-3/generative-api/pipeline_open.py diff --git a/module-3/generative-example/Makefile b/module-3/generative-example/Makefile index 00e8071..f8a409f 100644 --- a/module-3/generative-example/Makefile +++ b/module-3/generative-example/Makefile @@ -8,25 +8,12 @@ run_dev_gpu: build docker run --net=host --gpus all -it -v ${PWD}:/main generative-example:latest /bin/bash format: - ruff format nlp_sample/ tests/ + ruff format nlp_sample/ lint: - ruff check nlp_sample/ tests/ + ruff check nlp_sample/ -test: - pytest --disable-warnings ./tests/ -test_data: - pytest --disable-warnings -rc ./tests/test_data.py - -test_code: - pytest --disable-warnings -rc ./tests/test_code.py - -test_model: - pytest --disable-warnings -ss ./tests/test_model.py - -test_all: - pytest --cov=generative_example tests/ train_example: python generative_example/cli.py load-sql-data --subsample 0.1 ./data diff --git a/module-3/generative-example/README.md b/module-3/generative-example/README.md index 1ea6d74..ee11b6a 100644 --- a/module-3/generative-example/README.md +++ b/module-3/generative-example/README.md @@ -22,7 +22,7 @@ export WANDB_API_KEY=*********************** make test ``` -reference: https://madewithml.com/courses/mlops/testing/ +reference: https://docs.confident-ai.com/docs/confident-ai-github-actions ## Reports diff --git a/module-3/generative-example/generative_example/config.py b/module-3/generative-example/generative_example/config.py index 71ea69c..cd55271 100644 --- a/module-3/generative-example/generative_example/config.py +++ b/module-3/generative-example/generative_example/config.py @@ -1,5 +1,4 @@ from dataclasses import dataclass -from typing import Optional @dataclass diff --git a/module-3/generative-example/generative_example/predictor.py b/module-3/generative-example/generative_example/predictor.py index 0d898e8..89f9420 100644 --- a/module-3/generative-example/generative_example/predictor.py +++ b/module-3/generative-example/generative_example/predictor.py @@ -22,7 +22,7 @@ def __init__(self, model_load_path: str): model_load_path, low_cpu_mem_usage=True, return_dict=True, - torch_dtype=torch.bfloat16, #torch.float16, + torch_dtype=torch.bfloat16, trust_remote_code=True, device_map=device_map, ) diff --git a/module-3/generative-example/tests/conftest.py b/module-3/generative-example/tests/conftest.py index 4348b2a..e69de29 100644 --- a/module-3/generative-example/tests/conftest.py +++ b/module-3/generative-example/tests/conftest.py @@ -1,32 +0,0 @@ -from pathlib import Path -from typing import Tuple - -import great_expectations as ge -import pandas as pd -import pytest -from great_expectations.dataset.pandas_dataset import PandasDataset - -from nlp_sample.data import load_cola_data - - -@pytest.fixture(scope="session") -def data_path() -> Path: - _data_path = Path("/tmp/data") - _data_path.mkdir(exist_ok=True, parents=True) - - load_cola_data(path_to_save=_data_path) - - return _data_path - - -@pytest.fixture(scope="session") -def data(data_path: Path) -> Tuple[PandasDataset, PandasDataset]: - df_train = pd.read_csv(data_path / "train.csv") - df_val = pd.read_csv(data_path / "val.csv") - df_test = pd.read_csv(data_path / "test.csv") - - return ( - ge.dataset.PandasDataset(df_train), - ge.dataset.PandasDataset(df_val), - ge.dataset.PandasDataset(df_test), - ) diff --git a/module-3/generative-example/tests/test_llm.py b/module-3/generative-example/tests/test_llm.py deleted file mode 100644 index b6ccb63..0000000 --- a/module-3/generative-example/tests/test_llm.py +++ /dev/null @@ -1,21 +0,0 @@ -from typer.testing import CliRunner -from pathlib import Path -from nlp_sample.cli import app - -runner = CliRunner() - - -def test_app(): - result = runner.invoke(app, ["load-cola-data", "/tmp/data"]) - assert result.exit_code == 0, result.exception - assert Path("/tmp/data/train.csv").exists() - assert Path("/tmp/data/val.csv").exists() - assert Path("/tmp/data/test.csv").exists() - - result = runner.invoke(app, ["train", "tests/data/test_config.json"]) - assert result.exit_code == 0, result.exception - assert Path("/tmp/results").exists() - - result = runner.invoke(app, ["upload-to-registry", "cli-test", "/tmp/results"]) - assert result.exit_code == 0, result.exception - From 78c5524751b365e2ee881a68d80315a326bed3c4 Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Mon, 15 Jul 2024 18:28:10 -0400 Subject: [PATCH 02/15] fix bug --- module-3/classic-example/tests/conftest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module-3/classic-example/tests/conftest.py b/module-3/classic-example/tests/conftest.py index 713d17c..dbb2d38 100644 --- a/module-3/classic-example/tests/conftest.py +++ b/module-3/classic-example/tests/conftest.py @@ -6,7 +6,7 @@ import pytest from great_expectations.dataset.pandas_dataset import PandasDataset -from classic_example.data import load_cola_data +from classic_example.data import load_sst2_data @pytest.fixture(scope="session") @@ -14,7 +14,7 @@ def data_path() -> Path: _data_path = Path("/tmp/data") _data_path.mkdir(exist_ok=True, parents=True) - load_cola_data(path_to_save=_data_path) + load_sst2_data(path_to_save=_data_path) return _data_path From 88e9e51d72a647a4a3443c9c9f0a66533aa1bbde Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Mon, 15 Jul 2024 18:36:42 -0400 Subject: [PATCH 03/15] add modal jobs --- module-3/classic-example/run_training_job.py | 28 ++++++++++++++++++ module-3/classic-example/tests/test_cli.py | 2 +- .../generative-example/run_training_job.py | 29 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 module-3/classic-example/run_training_job.py create mode 100644 module-3/generative-example/run_training_job.py diff --git a/module-3/classic-example/run_training_job.py b/module-3/classic-example/run_training_job.py new file mode 100644 index 0000000..d957f0d --- /dev/null +++ b/module-3/classic-example/run_training_job.py @@ -0,0 +1,28 @@ +import os + +import modal +from modal import Image + + +app = modal.App("ml-in-production-practice") +env = {"WANDB_PROJECT": os.getenv("WANDB_PROJECT"), "WANDB_API_KEY": os.getenv("WANDB_API_KEY")} +custom_image = Image.from_registry("ghcr.io/kyryl-opens-ml/classic-example:pr-11").env(env) + + +@app.function(image=custom_image, gpu="a10g", timeout=15 * 60) +def run_training_modal(): + from classic_example.data import load_sst2_data + from classic_example.train import train + from classic_example.utils import load_from_registry, upload_to_registry + from classic_example.predictor import run_inference_on_dataframe + + load_sst2_data(path_to_save='/tmp/data') + train(config_path="/app/conf/example.json") + upload_to_registry(model_name='modal-classic-example', model_path='results') + load_from_registry(model_name='modal-classic-example', model_path='loaded-model') + run_inference_on_dataframe(df_path='/tmp/data/test.csv', model_load_path='loaded-model', result_path='/tmp/inference.csv') + + +@app.local_entrypoint() +def main(): + print(run_training_modal.spawn()) diff --git a/module-3/classic-example/tests/test_cli.py b/module-3/classic-example/tests/test_cli.py index 5e3791a..96d6749 100644 --- a/module-3/classic-example/tests/test_cli.py +++ b/module-3/classic-example/tests/test_cli.py @@ -6,7 +6,7 @@ def test_app(): - result = runner.invoke(app, ["load-cola-data", "/tmp/data"]) + result = runner.invoke(app, ["load-sst2-data", "/tmp/data"]) assert result.exit_code == 0, result.exception assert Path("/tmp/data/train.csv").exists() assert Path("/tmp/data/val.csv").exists() diff --git a/module-3/generative-example/run_training_job.py b/module-3/generative-example/run_training_job.py new file mode 100644 index 0000000..ea94f1f --- /dev/null +++ b/module-3/generative-example/run_training_job.py @@ -0,0 +1,29 @@ +import os + +import modal +from modal import Image + + +app = modal.App("ml-in-production-practice") +env = {"WANDB_PROJECT": os.getenv("WANDB_PROJECT"), "WANDB_API_KEY": os.getenv("WANDB_API_KEY")} +custom_image = Image.from_registry("ghcr.io/kyryl-opens-ml/classic-example:pr-11").env(env) + + +@app.function(image=custom_image, gpu="a10g", timeout=15 * 60) +def run_training_modal(): + from generative_example.data import load_sql_data + from generative_example.train import train + from generative_example.utils import load_from_registry, upload_to_registry + from generative_example.predictor import run_evaluate_on_json, run_inference_on_json + + load_sql_data(path_to_save='/tmp/data') + train(config_path="/app/conf/example.json") + upload_to_registry(model_name='modal-classic-example', model_path='./phi-3-mini-lora-text2sql') + load_from_registry(model_name='modal-classic-example', model_path='./phi-3-mini-lora-text2sql-loaded-model') + + run_inference_on_dataframe(df_path='/tmp/data/test.csv', model_load_path='loaded-model', result_path='/tmp/inference.csv') + + +@app.local_entrypoint() +def main(): + print(run_training_modal.spawn()) From 3a2ca1e1714ea7d001e6068c6839ebcf3969add1 Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Mon, 15 Jul 2024 18:49:56 -0400 Subject: [PATCH 04/15] re-build docker --- module-3/classic-example/README.md | 7 +++ .../classic-example/conf/example-modal.json | 45 +++++++++++++++++++ module-3/classic-example/run_training_job.py | 22 +++++---- .../conf/example-modal.json | 35 +++++++++++++++ 4 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 module-3/classic-example/conf/example-modal.json create mode 100644 module-3/generative-example/conf/example-modal.json diff --git a/module-3/classic-example/README.md b/module-3/classic-example/README.md index 1ea6d74..eb9327c 100644 --- a/module-3/classic-example/README.md +++ b/module-3/classic-example/README.md @@ -24,6 +24,13 @@ make test reference: https://madewithml.com/courses/mlops/testing/ +## Run training job + +```bash +modal deploy run_training_job.py +python run_training_job.py +``` + ## Reports ```bash diff --git a/module-3/classic-example/conf/example-modal.json b/module-3/classic-example/conf/example-modal.json new file mode 100644 index 0000000..17b2cfe --- /dev/null +++ b/module-3/classic-example/conf/example-modal.json @@ -0,0 +1,45 @@ +{ + "model_name_or_path": "google/mobilebert-uncased", + + "train_file": "/tmp/data/train.csv", + "validation_file": "/tmp/data/val.csv", + "output_dir": "results", + "max_seq_length": 128, + + + + "use_fast_tokenizer": true, + + + "eval_strategy": "steps", + "per_device_train_batch_size": 32, + "per_device_eval_batch_size": 32, + "gradient_accumulation_steps": 1, + "eval_delay": 0, + "learning_rate": 5e-05, + "weight_decay": 0, + "adam_beta1": 0.9, + "adam_beta2": 0.999, + "adam_epsilon": 1e-08, + "max_grad_norm": 1, + "num_train_epochs": 5, + "max_steps": -1, + "lr_scheduler_type": "linear", + "logging_strategy": "steps", + "logging_first_step": true, + "logging_steps": 250, + "save_strategy": "steps", + "save_steps": 250, + "save_total_limit": 5, + "no_cuda": false, + "seed": 42, + "eval_steps": 250, + "run_name": "results", + "disable_tqdm": false, + "remove_unused_columns": true, + "label_names": null, + "load_best_model_at_end": true, + "metric_for_best_model": "eval_f1", + "greater_is_better": true, + "report_to": ["wandb"] + } \ No newline at end of file diff --git a/module-3/classic-example/run_training_job.py b/module-3/classic-example/run_training_job.py index d957f0d..70db1a3 100644 --- a/module-3/classic-example/run_training_job.py +++ b/module-3/classic-example/run_training_job.py @@ -10,19 +10,25 @@ @app.function(image=custom_image, gpu="a10g", timeout=15 * 60) -def run_training_modal(): +def run_classic_example(): + from pathlib import Path from classic_example.data import load_sst2_data from classic_example.train import train from classic_example.utils import load_from_registry, upload_to_registry from classic_example.predictor import run_inference_on_dataframe - load_sst2_data(path_to_save='/tmp/data') - train(config_path="/app/conf/example.json") - upload_to_registry(model_name='modal-classic-example', model_path='results') - load_from_registry(model_name='modal-classic-example', model_path='loaded-model') - run_inference_on_dataframe(df_path='/tmp/data/test.csv', model_load_path='loaded-model', result_path='/tmp/inference.csv') + load_sst2_data(path_to_save=Path('/tmp/data/')) + train(config_path=Path("/app/conf/example.json")) + upload_to_registry(model_name='modal-classic-example', model_path=Path('results')) + load_from_registry(model_name='modal-classic-example', model_path=Path('loaded-model')) + run_inference_on_dataframe(df_path=Path('/tmp/data/test.csv'), model_load_path=Path('loaded-model'), result_path=Path('/tmp/data/inference.csv')) -@app.local_entrypoint() def main(): - print(run_training_modal.spawn()) + fn = modal.Function.lookup("ml-in-production-practice", "run_classic_example") + fn_id = fn.spawn() + print(f"Run training object: {fn_id}") + + +if __name__ == '__main__': + main() diff --git a/module-3/generative-example/conf/example-modal.json b/module-3/generative-example/conf/example-modal.json new file mode 100644 index 0000000..1470314 --- /dev/null +++ b/module-3/generative-example/conf/example-modal.json @@ -0,0 +1,35 @@ +{ + "train_file": "/tmp/data/train.json", + "test_file": "/tmp/data/test.json", + + "model_id": "microsoft/Phi-3-mini-4k-instruct", + "lora_r": 16, + "lora_alpha": 16, + "lora_dropout": 0.05, + + + "output_dir": "/tmp/phi-3-mini-lora-text2sql", + "eval_strategy": "steps", + "do_eval": true, + "optim": "adamw_torch", + "per_device_train_batch_size": 8, + "per_device_eval_batch_size": 8, + "gradient_accumulation_steps": 4, + "learning_rate": 0.0001, + "num_train_epochs": 3, + "warmup_ratio": 0.1, + "logging_first_step": true, + "logging_steps": 100, + "save_steps": 500, + "seed": 42, + "bf16": true, + "fp16": false, + "eval_steps": 100, + "report_to": [ + "wandb" + ], + "lr_scheduler_type": "linear", + "log_level" : "debug", + "evaluation_strategy": "steps", + "eval_on_start": true +} \ No newline at end of file From 81e21219e1874d09bdc70d1bd4c1d3d00928af58 Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Mon, 15 Jul 2024 19:13:31 -0400 Subject: [PATCH 05/15] fomat --- .../classic-example/classic_example/train.py | 6 +- .../classic-example/conf/example-modal.json | 2 +- module-3/classic-example/run_training_job.py | 27 +++-- module-3/classic-example/tests/test_cli.py | 1 - module-3/generative-api/pipeline_api.py | 19 ++-- module-3/generative-api/pipeline_open.py | 84 +++++++------- module-3/generative-example/README.md | 7 ++ .../generative_example/config.py | 2 +- .../generative_example/data.py | 17 +-- .../generative_example/predictor.py | 38 ++++--- .../generative_example/train.py | 103 +++++++++++------- .../generative_example/utils.py | 2 - .../generative-example/run_training_job.py | 41 +++++-- 13 files changed, 206 insertions(+), 143 deletions(-) diff --git a/module-3/classic-example/classic_example/train.py b/module-3/classic-example/classic_example/train.py index 587f8ce..8e3cabb 100644 --- a/module-3/classic-example/classic_example/train.py +++ b/module-3/classic-example/classic_example/train.py @@ -18,7 +18,11 @@ ) from classic_example.config import DataTrainingArguments, ModelArguments -from classic_example.utils import compute_metrics, preprocess_function_examples, setup_logger +from classic_example.utils import ( + compute_metrics, + preprocess_function_examples, + setup_logger, +) logger = logging.getLogger(__name__) diff --git a/module-3/classic-example/conf/example-modal.json b/module-3/classic-example/conf/example-modal.json index 17b2cfe..14af9c0 100644 --- a/module-3/classic-example/conf/example-modal.json +++ b/module-3/classic-example/conf/example-modal.json @@ -3,7 +3,7 @@ "train_file": "/tmp/data/train.csv", "validation_file": "/tmp/data/val.csv", - "output_dir": "results", + "output_dir": "/tmp/results", "max_seq_length": 128, diff --git a/module-3/classic-example/run_training_job.py b/module-3/classic-example/run_training_job.py index 70db1a3..5484dc0 100644 --- a/module-3/classic-example/run_training_job.py +++ b/module-3/classic-example/run_training_job.py @@ -5,8 +5,13 @@ app = modal.App("ml-in-production-practice") -env = {"WANDB_PROJECT": os.getenv("WANDB_PROJECT"), "WANDB_API_KEY": os.getenv("WANDB_API_KEY")} -custom_image = Image.from_registry("ghcr.io/kyryl-opens-ml/classic-example:pr-11").env(env) +env = { + "WANDB_PROJECT": os.getenv("WANDB_PROJECT"), + "WANDB_API_KEY": os.getenv("WANDB_API_KEY"), +} +custom_image = Image.from_registry("ghcr.io/kyryl-opens-ml/classic-example:pr-11").env( + env +) @app.function(image=custom_image, gpu="a10g", timeout=15 * 60) @@ -17,11 +22,17 @@ def run_classic_example(): from classic_example.utils import load_from_registry, upload_to_registry from classic_example.predictor import run_inference_on_dataframe - load_sst2_data(path_to_save=Path('/tmp/data/')) + load_sst2_data(path_to_save=Path("/tmp/data/")) train(config_path=Path("/app/conf/example.json")) - upload_to_registry(model_name='modal-classic-example', model_path=Path('results')) - load_from_registry(model_name='modal-classic-example', model_path=Path('loaded-model')) - run_inference_on_dataframe(df_path=Path('/tmp/data/test.csv'), model_load_path=Path('loaded-model'), result_path=Path('/tmp/data/inference.csv')) + upload_to_registry(model_name="modal-classic-example", model_path=Path("results")) + load_from_registry( + model_name="modal-classic-example", model_path=Path("loaded-model") + ) + run_inference_on_dataframe( + df_path=Path("/tmp/data/test.csv"), + model_load_path=Path("loaded-model"), + result_path=Path("/tmp/data/inference.csv"), + ) def main(): @@ -29,6 +40,6 @@ def main(): fn_id = fn.spawn() print(f"Run training object: {fn_id}") - -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/module-3/classic-example/tests/test_cli.py b/module-3/classic-example/tests/test_cli.py index 96d6749..49c9f9e 100644 --- a/module-3/classic-example/tests/test_cli.py +++ b/module-3/classic-example/tests/test_cli.py @@ -18,4 +18,3 @@ def test_app(): result = runner.invoke(app, ["upload-to-registry", "cli-test", "/tmp/results"]) assert result.exit_code == 0, result.exception - diff --git a/module-3/generative-api/pipeline_api.py b/module-3/generative-api/pipeline_api.py index a2aa710..5aa05f5 100644 --- a/module-3/generative-api/pipeline_api.py +++ b/module-3/generative-api/pipeline_api.py @@ -1,12 +1,10 @@ from openai import OpenAI from random import randrange -import torch -from datasets import load_dataset from joblib import Memory from tqdm import tqdm import json from datasets import Dataset - +import evaluate import numpy as np cache_directory = ".cache" @@ -14,7 +12,6 @@ persistent_cache = memory.cache - @persistent_cache def get_sql(query: str, context: str) -> str: client = OpenAI() @@ -37,23 +34,23 @@ def get_sql(query: str, context: str) -> str: model="gpt-4o", response_format={"type": "json_object"}, ) - - return json.loads(chat_completion.choices[0].message.content)['sql'] + + return json.loads(chat_completion.choices[0].message.content)["sql"] def pipeline(test_json: str): dataset = Dataset.from_json(test_json) - generate_sql = [] + generated_sql = [] gt_sql = [] for row in tqdm(dataset): - _generate_sql = get_sql(query=query, context=context) - _gt_sql = row['answer'] + _generate_sql = get_sql(query=row["question"], context=row["context"]) + _gt_sql = row["answer"] - generate_sql.append(_generate_sql) + generated_sql.append(_generate_sql) gt_sql.append(_gt_sql) - rouge = evaluate.load('rouge') + rouge = evaluate.load("rouge") results = rouge.compute(predictions=generated_sql, references=gt_sql) print(f"results = {results}") diff --git a/module-3/generative-api/pipeline_open.py b/module-3/generative-api/pipeline_open.py index 2ae8ede..d27b37c 100644 --- a/module-3/generative-api/pipeline_open.py +++ b/module-3/generative-api/pipeline_open.py @@ -6,17 +6,17 @@ from tqdm import tqdm import json from datasets import Dataset -import torch -from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline - +import torch +from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline +import evaluate import numpy as np +import re cache_directory = ".cache" memory = Memory(cache_directory) persistent_cache = memory.cache - # @persistent_cache def get_sql(query: str, context: str, pipe) -> str: prompt = f"""" @@ -28,61 +28,57 @@ def get_sql(query: str, context: str, pipe) -> str: Please return in JSON format: {{"sql": ""}} """ - - messages = [ - {"role": "system", "content": "You are a SQL expert."}, - {"role": "user", "content": prompt}, - ] - - - generation_args = { - "max_new_tokens": 500, - "return_full_text": False, - "temperature": 0.0, - "do_sample": False, - } - - output = pipe(messages, **generation_args) - sql = output[0]['generated_text'] - match = re.search(r'\{(.*?)\}', sql, re.DOTALL) + messages = [ + {"role": "system", "content": "You are a SQL expert."}, + {"role": "user", "content": prompt}, + ] + + generation_args = { + "max_new_tokens": 500, + "return_full_text": False, + "temperature": 0.0, + "do_sample": False, + } + + output = pipe(messages, **generation_args) + sql = output[0]["generated_text"] + match = re.search(r"\{(.*?)\}", sql, re.DOTALL) match.group(0) - return json.loads(match.group(0))['sql'] + return json.loads(match.group(0))["sql"] def pipeline(test_json: str): - - dataset = Dataset.from_json(test_json) + torch.random.manual_seed(0) + model = AutoModelForCausalLM.from_pretrained( + "microsoft/Phi-3-mini-128k-instruct", + device_map="cuda", + torch_dtype="auto", + trust_remote_code=True, + ) + tokenizer = AutoTokenizer.from_pretrained("microsoft/Phi-3-mini-128k-instruct") - torch.random.manual_seed(0) - model = AutoModelForCausalLM.from_pretrained( - "microsoft/Phi-3-mini-128k-instruct", - device_map="cuda", - torch_dtype="auto", - trust_remote_code=True, - ) - - tokenizer = AutoTokenizer.from_pretrained("microsoft/Phi-3-mini-128k-instruct") - - pipe = pipeline( - "text-generation", - model=model, - tokenizer=tokenizer, - ) + pipe = pipeline( + "text-generation", + model=model, + tokenizer=tokenizer, + ) - generate_sql = [] + generated_sql = [] gt_sql = [] for row in tqdm(dataset): - _generate_sql = get_sql(query=row['question'], context=row['context']) - _gt_sql = row['answer'] + _generate_sql = get_sql( + query=row["question"], context=row["context"], pipe=pipe + ) + _gt_sql = row["answer"] - generate_sql.append(_generate_sql) + generated_sql.append(_generate_sql) gt_sql.append(_gt_sql) - rouge = evaluate.load('rouge') + rouge = evaluate.load("rouge") results = rouge.compute(predictions=generated_sql, references=gt_sql) print(f"results = {results}") diff --git a/module-3/generative-example/README.md b/module-3/generative-example/README.md index ee11b6a..d7fb447 100644 --- a/module-3/generative-example/README.md +++ b/module-3/generative-example/README.md @@ -24,6 +24,13 @@ make test reference: https://docs.confident-ai.com/docs/confident-ai-github-actions +## Run training job + +```bash +modal deploy run_training_job.py +python run_training_job.py +``` + ## Reports ```bash diff --git a/module-3/generative-example/generative_example/config.py b/module-3/generative-example/generative_example/config.py index cd55271..9c6a8db 100644 --- a/module-3/generative-example/generative_example/config.py +++ b/module-3/generative-example/generative_example/config.py @@ -10,6 +10,6 @@ class DataTrainingArguments: @dataclass class ModelArguments: model_id: str - lora_r: int + lora_r: int lora_alpha: int lora_dropout: float diff --git a/module-3/generative-example/generative_example/data.py b/module-3/generative-example/generative_example/data.py index 24022d7..e1dfc65 100644 --- a/module-3/generative-example/generative_example/data.py +++ b/module-3/generative-example/generative_example/data.py @@ -3,15 +3,17 @@ from datasets import load_dataset, DatasetDict from random import randrange -def _get_sql_data(random_state: int = 42, subsample: float = None) -> DatasetDict: +def _get_sql_data(random_state: int = 42, subsample: float = None) -> DatasetDict: dataset_name = "b-mc2/sql-create-context" - dataset = load_dataset(dataset_name, split='train') + dataset = load_dataset(dataset_name, split="train") print(f"dataset size: {len(dataset)}") print(dataset[randrange(len(dataset))]) if subsample is not None: - dataset = dataset.shuffle(seed=random_state).select(range(int(len(dataset) * subsample))) + dataset = dataset.shuffle(seed=random_state).select( + range(int(len(dataset) * subsample)) + ) print(f"dataset new size: {len(dataset)}") datasets = dataset.train_test_split(test_size=0.05, seed=random_state) @@ -23,8 +25,9 @@ def load_sql_data(path_to_save: Path, subsample: float = None): datasets = _get_sql_data(subsample=subsample) - datasets['train'].to_json(path_to_save / "train.json") - datasets['test'].to_json(path_to_save / "test.json") + datasets["train"].to_json(path_to_save / "train.json") + datasets["test"].to_json(path_to_save / "test.json") + def load_sql_data_file_input( path_to_train: Path, path_to_test: Path, subsample: float = None @@ -34,5 +37,5 @@ def load_sql_data_file_input( datasets = _get_sql_data(subsample=subsample) - datasets['train'].to_json(path_to_train) - datasets['test'].to_json(path_to_test) + datasets["train"].to_json(path_to_train) + datasets["test"].to_json(path_to_test) diff --git a/module-3/generative-example/generative_example/predictor.py b/module-3/generative-example/generative_example/predictor.py index 89f9420..cbf83fd 100644 --- a/module-3/generative-example/generative_example/predictor.py +++ b/module-3/generative-example/generative_example/predictor.py @@ -28,7 +28,9 @@ def __init__(self, model_load_path: str): ) merged_model = new_model.merge_and_unload() - tokenizer = AutoTokenizer.from_pretrained(model_load_path,trust_remote_code=True) + tokenizer = AutoTokenizer.from_pretrained( + model_load_path, trust_remote_code=True + ) pipe = pipeline("text-generation", model=merged_model, tokenizer=tokenizer) self.pipe = pipe @@ -36,15 +38,22 @@ def __init__(self, model_load_path: str): def predict(self, question: str, context: str) -> str: pipe = self.pipe - messages = [{ - "content": f"{context}\n Input: {question}", - "role": "user" - }] - + messages = [{"content": f"{context}\n Input: {question}", "role": "user"}] - prompt = pipe.tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) - outputs = pipe(prompt, max_new_tokens=256, do_sample=True, num_beams=1, temperature=0.3, top_k=50, top_p=0.95, max_time= 180) - sql = outputs[0]['generated_text'][len(prompt):].strip() + prompt = pipe.tokenizer.apply_chat_template( + messages, tokenize=False, add_generation_prompt=True + ) + outputs = pipe( + prompt, + max_new_tokens=256, + do_sample=True, + num_beams=1, + temperature=0.3, + top_k=50, + top_p=0.95, + max_time=180, + ) + sql = outputs[0]["generated_text"][len(prompt) :].strip() return sql @@ -62,6 +71,7 @@ def run_inference_on_json(json_path: Path, model_load_path: Path, result_path: P df["generated_sql"] = generated_sql df.to_csv(result_path, index=False) + def run_evaluate_on_json(json_path: Path, model_load_path: Path, result_path: Path): df = Dataset.from_json(str(json_path)).to_pandas() model = Predictor(model_load_path=model_load_path) @@ -73,11 +83,9 @@ def run_evaluate_on_json(json_path: Path, model_load_path: Path, result_path: Pa sql = model.predict(question=question, context=context) generated_sql.append(sql) - - gt_sql = df['answer'].values - rouge = evaluate.load('rouge') + + gt_sql = df["answer"].values + rouge = evaluate.load("rouge") results = rouge.compute(predictions=generated_sql, references=gt_sql) - with open(result_path, 'w') as f: + with open(result_path, "w") as f: json.dump(results, f) - - diff --git a/module-3/generative-example/generative_example/train.py b/module-3/generative-example/generative_example/train.py index 8eee4f1..15501ec 100644 --- a/module-3/generative-example/generative_example/train.py +++ b/module-3/generative-example/generative_example/train.py @@ -9,7 +9,7 @@ TrainingArguments, set_seed, pipeline, - HfArgumentParser + HfArgumentParser, ) from pathlib import Path import logging @@ -27,98 +27,119 @@ def create_message_column(row): messages = [] - user = { - "content": f"{row['context']}\n Input: {row['question']}", - "role": "user" - } + user = {"content": f"{row['context']}\n Input: {row['question']}", "role": "user"} messages.append(user) - assistant = { - "content": f"{row['answer']}", - "role": "assistant" - } + assistant = {"content": f"{row['answer']}", "role": "assistant"} messages.append(assistant) return {"messages": messages} + def format_dataset_chatml(row, tokenizer): - return {"text": tokenizer.apply_chat_template(row["messages"], add_generation_prompt=False, tokenize=False)} + return { + "text": tokenizer.apply_chat_template( + row["messages"], add_generation_prompt=False, tokenize=False + ) + } def process_dataset(model_id: str, train_file: str, test_file: str) -> DatasetDict: - - dataset = DatasetDict({ - 'train': Dataset.from_json(train_file), - 'test': Dataset.from_json(test_file), - }) + dataset = DatasetDict( + { + "train": Dataset.from_json(train_file), + "test": Dataset.from_json(test_file), + } + ) tokenizer_id = model_id tokenizer = AutoTokenizer.from_pretrained(tokenizer_id) - tokenizer.padding_side = 'right' + tokenizer.padding_side = "right" dataset_chatml = dataset.map(create_message_column) - dataset_chatml = dataset_chatml.map(partial(format_dataset_chatml, tokenizer=tokenizer)) + dataset_chatml = dataset_chatml.map( + partial(format_dataset_chatml, tokenizer=tokenizer) + ) return dataset_chatml def get_model(model_id: str, device_map): if torch.cuda.is_bf16_supported(): compute_dtype = torch.bfloat16 - attn_implementation = 'flash_attention_2' + attn_implementation = "flash_attention_2" # If bfloat16 is not supported, 'compute_dtype' is set to 'torch.float16' and 'attn_implementation' is set to 'sdpa'. else: compute_dtype = torch.float16 - attn_implementation = 'sdpa' + attn_implementation = "sdpa" # This line of code is used to print the value of 'attn_implementation', which indicates the chosen attention implementation. print(attn_implementation) - - tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True, add_eos_token=True, use_fast=True) + tokenizer = AutoTokenizer.from_pretrained( + model_id, trust_remote_code=True, add_eos_token=True, use_fast=True + ) tokenizer.pad_token = tokenizer.unk_token tokenizer.pad_token_id = tokenizer.convert_tokens_to_ids(tokenizer.pad_token) - tokenizer.padding_side = 'left' + tokenizer.padding_side = "left" model = AutoModelForCausalLM.from_pretrained( - model_id, torch_dtype=compute_dtype, trust_remote_code=True, device_map=device_map, - attn_implementation=attn_implementation + model_id, + torch_dtype=compute_dtype, + trust_remote_code=True, + device_map=device_map, + attn_implementation=attn_implementation, ) return tokenizer, model + def get_config(config_path: Path): - parser = HfArgumentParser((ModelArguments, DataTrainingArguments, TrainingArguments)) + parser = HfArgumentParser( + (ModelArguments, DataTrainingArguments, TrainingArguments) + ) model_args, data_args, training_args = parser.parse_json_file(config_path) return model_args, data_args, training_args + def train(config_path: Path): setup_logger(logger) model_args, data_args, training_args = get_config(config_path=config_path) - + logger.info(f"model_args = {model_args}") logger.info(f"data_args = {data_args}") logger.info(f"training_args = {training_args}") - device_map = {"": 0} - target_modules= ['k_proj', 'q_proj', 'v_proj', 'o_proj', "gate_proj", "down_proj", "up_proj"] - - set_seed(training_args.seed) - - dataset_chatml = process_dataset(model_id=model_args.model_id, train_file=data_args.train_file, test_file=data_args.test_file) - logger.info(dataset_chatml['train'][0]) + target_modules = [ + "k_proj", + "q_proj", + "v_proj", + "o_proj", + "gate_proj", + "down_proj", + "up_proj", + ] + + set_seed(training_args.seed) + + dataset_chatml = process_dataset( + model_id=model_args.model_id, + train_file=data_args.train_file, + test_file=data_args.test_file, + ) + logger.info(dataset_chatml["train"][0]) tokenizer, model = get_model(model_id=model_args.model_id, device_map=device_map) peft_config = LoraConfig( - r=model_args.lora_r, - lora_alpha=model_args.lora_alpha, - lora_dropout=model_args.lora_dropout, - task_type=TaskType.CAUSAL_LM, - target_modules=target_modules, + r=model_args.lora_r, + lora_alpha=model_args.lora_alpha, + lora_dropout=model_args.lora_dropout, + task_type=TaskType.CAUSAL_LM, + target_modules=target_modules, ) - + trainer = SFTTrainer( model=model, - train_dataset=dataset_chatml['train'], - eval_dataset=dataset_chatml['test'], + train_dataset=dataset_chatml["train"], + eval_dataset=dataset_chatml["test"], peft_config=peft_config, dataset_text_field="text", max_seq_length=512, diff --git a/module-3/generative-example/generative_example/utils.py b/module-3/generative-example/generative_example/utils.py index 4ed5912..f2970bd 100644 --- a/module-3/generative-example/generative_example/utils.py +++ b/module-3/generative-example/generative_example/utils.py @@ -11,8 +11,6 @@ from transformers import EvalPrediction - - def setup_logger(logger): # Setup logging logging.basicConfig( diff --git a/module-3/generative-example/run_training_job.py b/module-3/generative-example/run_training_job.py index ea94f1f..26d7f69 100644 --- a/module-3/generative-example/run_training_job.py +++ b/module-3/generative-example/run_training_job.py @@ -5,25 +5,44 @@ app = modal.App("ml-in-production-practice") -env = {"WANDB_PROJECT": os.getenv("WANDB_PROJECT"), "WANDB_API_KEY": os.getenv("WANDB_API_KEY")} -custom_image = Image.from_registry("ghcr.io/kyryl-opens-ml/classic-example:pr-11").env(env) +env = { + "WANDB_PROJECT": os.getenv("WANDB_PROJECT"), + "WANDB_API_KEY": os.getenv("WANDB_API_KEY"), +} +custom_image = Image.from_registry( + "ghcr.io/kyryl-opens-ml/generative-example:pr-11" +).env(env) @app.function(image=custom_image, gpu="a10g", timeout=15 * 60) -def run_training_modal(): +def run_generative_example(): + from pathlib import Path from generative_example.data import load_sql_data from generative_example.train import train from generative_example.utils import load_from_registry, upload_to_registry from generative_example.predictor import run_evaluate_on_json, run_inference_on_json - load_sql_data(path_to_save='/tmp/data') - train(config_path="/app/conf/example.json") - upload_to_registry(model_name='modal-classic-example', model_path='./phi-3-mini-lora-text2sql') - load_from_registry(model_name='modal-classic-example', model_path='./phi-3-mini-lora-text2sql-loaded-model') - - run_inference_on_dataframe(df_path='/tmp/data/test.csv', model_load_path='loaded-model', result_path='/tmp/inference.csv') + load_sql_data(path_to_save=Path("/tmp/data"), subsample=0.1) + train(config_path=Path("/app/conf/example-modal.json")) + upload_to_registry( + model_name="modal-generative-example", + model_path=Path("/tmp/phi-3-mini-lora-text2sql"), + ) + load_from_registry( + model_name="modal-generative-example", model_path=Path("/tmp/loaded-model") + ) + run_evaluate_on_json( + json_path=Path("/tmp/data/test.json"), + model_load_path=Path("/tmp/loaded-model"), + result_path=Path("/tmp/data/results.json"), + ) -@app.local_entrypoint() def main(): - print(run_training_modal.spawn()) + fn = modal.Function.lookup("ml-in-production-practice", "run_generative_example") + fn_id = fn.spawn() + print(f"Run training object: {fn_id}") + + +if __name__ == "__main__": + main() From 7a9be492347f2062b9d15e5a30da37a9d0334d3c Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Mon, 15 Jul 2024 19:26:24 -0400 Subject: [PATCH 06/15] add flash-attention --- module-3/generative-example/Dockerfile | 1 + module-3/generative-example/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/module-3/generative-example/Dockerfile b/module-3/generative-example/Dockerfile index 114ce71..2944246 100644 --- a/module-3/generative-example/Dockerfile +++ b/module-3/generative-example/Dockerfile @@ -7,6 +7,7 @@ ENV LANG=C.UTF-8 COPY requirements.txt requirements.txt RUN pip install -r requirements.txt +RUN pip install flash-attention RUN ln -s /usr/bin/python3 /usr/bin/python diff --git a/module-3/generative-example/requirements.txt b/module-3/generative-example/requirements.txt index 0022098..3f496cc 100644 --- a/module-3/generative-example/requirements.txt +++ b/module-3/generative-example/requirements.txt @@ -8,4 +8,4 @@ ruff==0.5.0 great-expectations==0.15.25 pytest-cov==3.0.0 peft==0.11.1 -evaluate==0.4.2 \ No newline at end of file +evaluate==0.4.2 From 673ebf2cd991b57d8ffe38012273ffb190602615 Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Mon, 15 Jul 2024 19:29:08 -0400 Subject: [PATCH 07/15] add style --- .../classic-example/classic_example/cli.py | 2 +- .../classic_example/predictor.py | 6 +++--- module-3/classic-example/run_training_job.py | 4 ++-- module-3/classic-example/tests/conftest.py | 3 +-- module-3/classic-example/tests/test_cli.py | 3 ++- module-3/classic-example/tests/test_code.py | 3 +-- module-3/classic-example/tests/test_model.py | 3 +-- module-3/generative-api/pipeline_api.py | 15 +++++++-------- module-3/generative-api/pipeline_open.py | 18 +++++++----------- .../generative_example/cli.py | 2 +- .../generative_example/data.py | 4 ++-- .../generative_example/predictor.py | 13 +++++-------- .../generative_example/train.py | 19 +++++++------------ .../generative_example/utils.py | 4 ---- .../generative-example/run_training_job.py | 4 ++-- 15 files changed, 42 insertions(+), 61 deletions(-) diff --git a/module-3/classic-example/classic_example/cli.py b/module-3/classic-example/classic_example/cli.py index 018a5df..8009b2b 100644 --- a/module-3/classic-example/classic_example/cli.py +++ b/module-3/classic-example/classic_example/cli.py @@ -1,9 +1,9 @@ import typer from classic_example.data import load_sst2_data, load_sst2_data_file_input +from classic_example.predictor import run_inference_on_dataframe from classic_example.train import train from classic_example.utils import load_from_registry, upload_to_registry -from classic_example.predictor import run_inference_on_dataframe app = typer.Typer() app.command()(train) diff --git a/module-3/classic-example/classic_example/predictor.py b/module-3/classic-example/classic_example/predictor.py index d2b8d10..8d07732 100644 --- a/module-3/classic-example/classic_example/predictor.py +++ b/module-3/classic-example/classic_example/predictor.py @@ -1,11 +1,11 @@ import logging +from pathlib import Path +import pandas as pd import torch from torch.nn.functional import softmax -from transformers import AutoModelForSequenceClassification, AutoTokenizer -from pathlib import Path -import pandas as pd from tqdm import tqdm +from transformers import AutoModelForSequenceClassification, AutoTokenizer logger = logging.getLogger() diff --git a/module-3/classic-example/run_training_job.py b/module-3/classic-example/run_training_job.py index 5484dc0..3159197 100644 --- a/module-3/classic-example/run_training_job.py +++ b/module-3/classic-example/run_training_job.py @@ -3,7 +3,6 @@ import modal from modal import Image - app = modal.App("ml-in-production-practice") env = { "WANDB_PROJECT": os.getenv("WANDB_PROJECT"), @@ -17,10 +16,11 @@ @app.function(image=custom_image, gpu="a10g", timeout=15 * 60) def run_classic_example(): from pathlib import Path + from classic_example.data import load_sst2_data + from classic_example.predictor import run_inference_on_dataframe from classic_example.train import train from classic_example.utils import load_from_registry, upload_to_registry - from classic_example.predictor import run_inference_on_dataframe load_sst2_data(path_to_save=Path("/tmp/data/")) train(config_path=Path("/app/conf/example.json")) diff --git a/module-3/classic-example/tests/conftest.py b/module-3/classic-example/tests/conftest.py index dbb2d38..6094c58 100644 --- a/module-3/classic-example/tests/conftest.py +++ b/module-3/classic-example/tests/conftest.py @@ -4,9 +4,8 @@ import great_expectations as ge import pandas as pd import pytest -from great_expectations.dataset.pandas_dataset import PandasDataset - from classic_example.data import load_sst2_data +from great_expectations.dataset.pandas_dataset import PandasDataset @pytest.fixture(scope="session") diff --git a/module-3/classic-example/tests/test_cli.py b/module-3/classic-example/tests/test_cli.py index 49c9f9e..6dd281f 100644 --- a/module-3/classic-example/tests/test_cli.py +++ b/module-3/classic-example/tests/test_cli.py @@ -1,6 +1,7 @@ -from typer.testing import CliRunner from pathlib import Path + from classic_example.cli import app +from typer.testing import CliRunner runner = CliRunner() diff --git a/module-3/classic-example/tests/test_code.py b/module-3/classic-example/tests/test_code.py index f4f3dc1..d7b9b67 100644 --- a/module-3/classic-example/tests/test_code.py +++ b/module-3/classic-example/tests/test_code.py @@ -1,8 +1,7 @@ import numpy as np import pytest -from transformers import EvalPrediction - from classic_example.utils import compute_metrics +from transformers import EvalPrediction @pytest.fixture() diff --git a/module-3/classic-example/tests/test_model.py b/module-3/classic-example/tests/test_model.py index 36fe2f0..e2c9e66 100644 --- a/module-3/classic-example/tests/test_model.py +++ b/module-3/classic-example/tests/test_model.py @@ -1,8 +1,6 @@ from pathlib import Path import pytest -from transformers import Trainer, TrainingArguments - from classic_example.config import DataTrainingArguments, ModelArguments from classic_example.train import ( get_models, @@ -11,6 +9,7 @@ read_dataset, train, ) +from transformers import Trainer, TrainingArguments @pytest.fixture() diff --git a/module-3/generative-api/pipeline_api.py b/module-3/generative-api/pipeline_api.py index 5aa05f5..70d2672 100644 --- a/module-3/generative-api/pipeline_api.py +++ b/module-3/generative-api/pipeline_api.py @@ -1,11 +1,10 @@ -from openai import OpenAI -from random import randrange -from joblib import Memory -from tqdm import tqdm import json -from datasets import Dataset + import evaluate -import numpy as np +from datasets import Dataset +from joblib import Memory +from openai import OpenAI +from tqdm import tqdm cache_directory = ".cache" memory = Memory(cache_directory) @@ -38,7 +37,7 @@ def get_sql(query: str, context: str) -> str: return json.loads(chat_completion.choices[0].message.content)["sql"] -def pipeline(test_json: str): +def run_pipeline(test_json: str): dataset = Dataset.from_json(test_json) generated_sql = [] @@ -56,4 +55,4 @@ def pipeline(test_json: str): if __name__ == "__main__": - pipeline() + run_pipeline() diff --git a/module-3/generative-api/pipeline_open.py b/module-3/generative-api/pipeline_open.py index d27b37c..5137b29 100644 --- a/module-3/generative-api/pipeline_open.py +++ b/module-3/generative-api/pipeline_open.py @@ -1,16 +1,12 @@ -from openai import OpenAI -from random import randrange +import json +import re + +import evaluate import torch -from datasets import load_dataset +from datasets import Dataset from joblib import Memory from tqdm import tqdm -import json -from datasets import Dataset -import torch from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline -import evaluate -import numpy as np -import re cache_directory = ".cache" memory = Memory(cache_directory) @@ -47,7 +43,7 @@ def get_sql(query: str, context: str, pipe) -> str: return json.loads(match.group(0))["sql"] -def pipeline(test_json: str): +def run_pipeline(test_json: str): dataset = Dataset.from_json(test_json) torch.random.manual_seed(0) @@ -84,4 +80,4 @@ def pipeline(test_json: str): if __name__ == "__main__": - pipeline() + run_pipeline() diff --git a/module-3/generative-example/generative_example/cli.py b/module-3/generative-example/generative_example/cli.py index 18a9fce..de4ef78 100644 --- a/module-3/generative-example/generative_example/cli.py +++ b/module-3/generative-example/generative_example/cli.py @@ -1,8 +1,8 @@ import typer from generative_example.data import load_sql_data, load_sql_data_file_input +from generative_example.predictor import run_evaluate_on_json, run_inference_on_json from generative_example.train import train -from generative_example.predictor import run_inference_on_json, run_evaluate_on_json from generative_example.utils import load_from_registry, upload_to_registry app = typer.Typer() diff --git a/module-3/generative-example/generative_example/data.py b/module-3/generative-example/generative_example/data.py index e1dfc65..10703b3 100644 --- a/module-3/generative-example/generative_example/data.py +++ b/module-3/generative-example/generative_example/data.py @@ -1,8 +1,8 @@ from pathlib import Path - -from datasets import load_dataset, DatasetDict from random import randrange +from datasets import DatasetDict, load_dataset + def _get_sql_data(random_state: int = 42, subsample: float = None) -> DatasetDict: dataset_name = "b-mc2/sql-create-context" diff --git a/module-3/generative-example/generative_example/predictor.py b/module-3/generative-example/generative_example/predictor.py index cbf83fd..d411951 100644 --- a/module-3/generative-example/generative_example/predictor.py +++ b/module-3/generative-example/generative_example/predictor.py @@ -1,16 +1,13 @@ +import json import logging +from pathlib import Path +import evaluate import torch -from torch.nn.functional import softmax from datasets import Dataset -from transformers import AutoModelForSequenceClassification, AutoTokenizer -from pathlib import Path -import pandas as pd -from tqdm import tqdm from peft import AutoPeftModelForCausalLM -from transformers import pipeline -import evaluate -import json +from tqdm import tqdm +from transformers import AutoTokenizer, pipeline logger = logging.getLogger() diff --git a/module-3/generative-example/generative_example/train.py b/module-3/generative-example/generative_example/train.py index 15501ec..0c12af2 100644 --- a/module-3/generative-example/generative_example/train.py +++ b/module-3/generative-example/generative_example/train.py @@ -1,27 +1,22 @@ -from random import randrange +import logging +from functools import partial +from pathlib import Path + import torch -from datasets import load_dataset, Dataset, DatasetDict -from peft import LoraConfig, prepare_model_for_kbit_training, TaskType, PeftModel +from datasets import Dataset, DatasetDict +from peft import LoraConfig, TaskType from transformers import ( AutoModelForCausalLM, AutoTokenizer, - BitsAndBytesConfig, + HfArgumentParser, TrainingArguments, set_seed, - pipeline, - HfArgumentParser, ) -from pathlib import Path -import logging from trl import SFTTrainer -from functools import partial -from datasets import load_metric -from transformers import EvalPrediction from generative_example.config import DataTrainingArguments, ModelArguments from generative_example.utils import setup_logger - logger = logging.getLogger(__name__) diff --git a/module-3/generative-example/generative_example/utils.py b/module-3/generative-example/generative_example/utils.py index f2970bd..250a6d1 100644 --- a/module-3/generative-example/generative_example/utils.py +++ b/module-3/generative-example/generative_example/utils.py @@ -1,14 +1,10 @@ import logging import sys from pathlib import Path -from typing import Dict import datasets -import numpy as np import transformers import wandb -from sklearn.metrics import f1_score, fbeta_score -from transformers import EvalPrediction def setup_logger(logger): diff --git a/module-3/generative-example/run_training_job.py b/module-3/generative-example/run_training_job.py index 26d7f69..7b2ceef 100644 --- a/module-3/generative-example/run_training_job.py +++ b/module-3/generative-example/run_training_job.py @@ -3,7 +3,6 @@ import modal from modal import Image - app = modal.App("ml-in-production-practice") env = { "WANDB_PROJECT": os.getenv("WANDB_PROJECT"), @@ -17,10 +16,11 @@ @app.function(image=custom_image, gpu="a10g", timeout=15 * 60) def run_generative_example(): from pathlib import Path + from generative_example.data import load_sql_data + from generative_example.predictor import run_evaluate_on_json from generative_example.train import train from generative_example.utils import load_from_registry, upload_to_registry - from generative_example.predictor import run_evaluate_on_json, run_inference_on_json load_sql_data(path_to_save=Path("/tmp/data"), subsample=0.1) train(config_path=Path("/app/conf/example-modal.json")) From 8c6acee3d611612d40daa9c5c27d18791ecc6ef5 Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Tue, 16 Jul 2024 14:31:47 -0400 Subject: [PATCH 08/15] build image --- module-3/README.md | 13 ++++ module-3/classic-example/conf/example.json | 6 -- module-3/classic-example/run_training_job.py | 4 +- module-3/generative-api/pipeline_api.py | 5 +- .../{pipeline_open.py => pipeline_phi3.py} | 60 +++++++++++-------- module-3/generative-example/Dockerfile | 2 +- .../generative_example/predictor.py | 1 + .../generative-example/run_training_job.py | 19 ++---- 8 files changed, 56 insertions(+), 54 deletions(-) rename module-3/generative-api/{pipeline_open.py => pipeline_phi3.py} (67%) diff --git a/module-3/README.md b/module-3/README.md index 42c3193..efdf63a 100644 --- a/module-3/README.md +++ b/module-3/README.md @@ -52,6 +52,19 @@ https://huggingface.co/models?sort=downloads - https://github.com/microsoft/Phi-3CookBook - https://huggingface.co/spaces/open-llm-leaderboard/open_llm_leaderboard +## LLM API + +Run API LLMs + +```bash +python generative-api/pipeline_api.py ./data/test.json +``` + +Run open LLMs + +```bash +python generative-api/pipeline_phi3.py ./data/test.json +``` ## LLM API testing diff --git a/module-3/classic-example/conf/example.json b/module-3/classic-example/conf/example.json index 2090ed7..1aa7c65 100644 --- a/module-3/classic-example/conf/example.json +++ b/module-3/classic-example/conf/example.json @@ -1,16 +1,10 @@ { "model_name_or_path": "google/mobilebert-uncased", - "train_file": "./data/train.csv", "validation_file": "./data/val.csv", "output_dir": "results", "max_seq_length": 128, - - - "use_fast_tokenizer": true, - - "eval_strategy": "steps", "per_device_train_batch_size": 32, "per_device_eval_batch_size": 32, diff --git a/module-3/classic-example/run_training_job.py b/module-3/classic-example/run_training_job.py index 3159197..bd3318f 100644 --- a/module-3/classic-example/run_training_job.py +++ b/module-3/classic-example/run_training_job.py @@ -8,9 +8,7 @@ "WANDB_PROJECT": os.getenv("WANDB_PROJECT"), "WANDB_API_KEY": os.getenv("WANDB_API_KEY"), } -custom_image = Image.from_registry("ghcr.io/kyryl-opens-ml/classic-example:pr-11").env( - env -) +custom_image = Image.from_registry("ghcr.io/kyryl-opens-ml/classic-example:pr-11").env(env) @app.function(image=custom_image, gpu="a10g", timeout=15 * 60) diff --git a/module-3/generative-api/pipeline_api.py b/module-3/generative-api/pipeline_api.py index 70d2672..623012c 100644 --- a/module-3/generative-api/pipeline_api.py +++ b/module-3/generative-api/pipeline_api.py @@ -5,7 +5,7 @@ from joblib import Memory from openai import OpenAI from tqdm import tqdm - +import typer cache_directory = ".cache" memory = Memory(cache_directory) persistent_cache = memory.cache @@ -39,7 +39,6 @@ def get_sql(query: str, context: str) -> str: def run_pipeline(test_json: str): dataset = Dataset.from_json(test_json) - generated_sql = [] gt_sql = [] for row in tqdm(dataset): @@ -55,4 +54,4 @@ def run_pipeline(test_json: str): if __name__ == "__main__": - run_pipeline() + typer.run(run_pipeline) diff --git a/module-3/generative-api/pipeline_open.py b/module-3/generative-api/pipeline_phi3.py similarity index 67% rename from module-3/generative-api/pipeline_open.py rename to module-3/generative-api/pipeline_phi3.py index 5137b29..c979aaa 100644 --- a/module-3/generative-api/pipeline_open.py +++ b/module-3/generative-api/pipeline_phi3.py @@ -7,14 +7,35 @@ from joblib import Memory from tqdm import tqdm from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline +import typer cache_directory = ".cache" memory = Memory(cache_directory) persistent_cache = memory.cache +def create_pipeline(phi_model_name: str = "microsoft/Phi-3-mini-128k-instruct"): + torch.random.manual_seed(0) + model = AutoModelForCausalLM.from_pretrained( + phi_model_name, + device_map="cuda", + torch_dtype="auto", + trust_remote_code=True, + ) + + tokenizer = AutoTokenizer.from_pretrained(phi_model_name) + + pipe = pipeline( + "text-generation", + model=model, + tokenizer=tokenizer, + ) + return pipe + +print("Creating pipeline") +pipe = create_pipeline() -# @persistent_cache -def get_sql(query: str, context: str, pipe) -> str: +@persistent_cache +def get_sql(query: str, context: str) -> str: prompt = f"""" Write the corresponding SQL query based on user requests and database context: @@ -37,38 +58,25 @@ def get_sql(query: str, context: str, pipe) -> str: } output = pipe(messages, **generation_args) - sql = output[0]["generated_text"] - match = re.search(r"\{(.*?)\}", sql, re.DOTALL) - match.group(0) - return json.loads(match.group(0))["sql"] + generated_text = output[0]["generated_text"] + match = re.search(r"\{(.*?)\}", generated_text, re.DOTALL) + matched_text = match.group(0) + try: + sql = json.loads(matched_text)["sql"] + except json.JSONDecodeError as ex: + print(f"Cannot parse {generated_text} output") + sql = "" + return sql def run_pipeline(test_json: str): dataset = Dataset.from_json(test_json) - torch.random.manual_seed(0) - model = AutoModelForCausalLM.from_pretrained( - "microsoft/Phi-3-mini-128k-instruct", - device_map="cuda", - torch_dtype="auto", - trust_remote_code=True, - ) - - tokenizer = AutoTokenizer.from_pretrained("microsoft/Phi-3-mini-128k-instruct") - - pipe = pipeline( - "text-generation", - model=model, - tokenizer=tokenizer, - ) - generated_sql = [] gt_sql = [] for row in tqdm(dataset): - _generate_sql = get_sql( - query=row["question"], context=row["context"], pipe=pipe - ) + _generate_sql = get_sql(query=row["question"], context=row["context"]) _gt_sql = row["answer"] generated_sql.append(_generate_sql) @@ -80,4 +88,4 @@ def run_pipeline(test_json: str): if __name__ == "__main__": - run_pipeline() + typer.run(run_pipeline) \ No newline at end of file diff --git a/module-3/generative-example/Dockerfile b/module-3/generative-example/Dockerfile index 2944246..150ec30 100644 --- a/module-3/generative-example/Dockerfile +++ b/module-3/generative-example/Dockerfile @@ -7,7 +7,7 @@ ENV LANG=C.UTF-8 COPY requirements.txt requirements.txt RUN pip install -r requirements.txt -RUN pip install flash-attention +RUN pip install flash-attention==flash-attn==2.6.0 RUN ln -s /usr/bin/python3 /usr/bin/python diff --git a/module-3/generative-example/generative_example/predictor.py b/module-3/generative-example/generative_example/predictor.py index d411951..dbbed86 100644 --- a/module-3/generative-example/generative_example/predictor.py +++ b/module-3/generative-example/generative_example/predictor.py @@ -84,5 +84,6 @@ def run_evaluate_on_json(json_path: Path, model_load_path: Path, result_path: Pa gt_sql = df["answer"].values rouge = evaluate.load("rouge") results = rouge.compute(predictions=generated_sql, references=gt_sql) + print(f"Metrics {results}") with open(result_path, "w") as f: json.dump(results, f) diff --git a/module-3/generative-example/run_training_job.py b/module-3/generative-example/run_training_job.py index 7b2ceef..8f0b30c 100644 --- a/module-3/generative-example/run_training_job.py +++ b/module-3/generative-example/run_training_job.py @@ -8,9 +8,7 @@ "WANDB_PROJECT": os.getenv("WANDB_PROJECT"), "WANDB_API_KEY": os.getenv("WANDB_API_KEY"), } -custom_image = Image.from_registry( - "ghcr.io/kyryl-opens-ml/generative-example:pr-11" -).env(env) +custom_image = Image.from_registry("ghcr.io/kyryl-opens-ml/generative-example:pr-11").env(env) @app.function(image=custom_image, gpu="a10g", timeout=15 * 60) @@ -24,18 +22,9 @@ def run_generative_example(): load_sql_data(path_to_save=Path("/tmp/data"), subsample=0.1) train(config_path=Path("/app/conf/example-modal.json")) - upload_to_registry( - model_name="modal-generative-example", - model_path=Path("/tmp/phi-3-mini-lora-text2sql"), - ) - load_from_registry( - model_name="modal-generative-example", model_path=Path("/tmp/loaded-model") - ) - run_evaluate_on_json( - json_path=Path("/tmp/data/test.json"), - model_load_path=Path("/tmp/loaded-model"), - result_path=Path("/tmp/data/results.json"), - ) + upload_to_registry(model_name="modal-generative-example", model_path=Path("/tmp/phi-3-mini-lora-text2sql")) + load_from_registry(model_name="modal-generative-example", model_path=Path("/tmp/loaded-model")) + run_evaluate_on_json(json_path=Path("/tmp/data/test.json"), model_load_path=Path("/tmp/loaded-model"), result_path=Path("/tmp/data/results.json")) def main(): From d860d53a879c4a91759e0d7cbb613a05e65dbda6 Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Tue, 16 Jul 2024 14:35:59 -0400 Subject: [PATCH 09/15] fix version --- module-3/generative-example/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module-3/generative-example/Dockerfile b/module-3/generative-example/Dockerfile index 150ec30..fdae076 100644 --- a/module-3/generative-example/Dockerfile +++ b/module-3/generative-example/Dockerfile @@ -7,7 +7,7 @@ ENV LANG=C.UTF-8 COPY requirements.txt requirements.txt RUN pip install -r requirements.txt -RUN pip install flash-attention==flash-attn==2.6.0 +RUN pip install flash-attention==2.6.0 RUN ln -s /usr/bin/python3 /usr/bin/python From 25834ee5c9bb57bcf8a8dd4a0ab41d64f71a7980 Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Tue, 16 Jul 2024 14:41:54 -0400 Subject: [PATCH 10/15] Docker fix --- module-3/generative-example/Dockerfile | 2 +- module-3/generative-example/requirements.txt | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/module-3/generative-example/Dockerfile b/module-3/generative-example/Dockerfile index fdae076..4ba6157 100644 --- a/module-3/generative-example/Dockerfile +++ b/module-3/generative-example/Dockerfile @@ -7,7 +7,7 @@ ENV LANG=C.UTF-8 COPY requirements.txt requirements.txt RUN pip install -r requirements.txt -RUN pip install flash-attention==2.6.0 +RUN MAX_JOBS=4 pip install flash-attn==2.5.7 --no-build-isolation RUN ln -s /usr/bin/python3 /usr/bin/python diff --git a/module-3/generative-example/requirements.txt b/module-3/generative-example/requirements.txt index 3f496cc..b421643 100644 --- a/module-3/generative-example/requirements.txt +++ b/module-3/generative-example/requirements.txt @@ -9,3 +9,5 @@ great-expectations==0.15.25 pytest-cov==3.0.0 peft==0.11.1 evaluate==0.4.2 +packaging==23.2 +ninja==1.11.1.1 \ No newline at end of file From e3565fc55921bd8e8ca98e80ace88f9de60530fe Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Tue, 16 Jul 2024 15:06:57 -0400 Subject: [PATCH 11/15] step to 500 --- module-3/generative-example/conf/example-modal.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module-3/generative-example/conf/example-modal.json b/module-3/generative-example/conf/example-modal.json index 1470314..7af9b6d 100644 --- a/module-3/generative-example/conf/example-modal.json +++ b/module-3/generative-example/conf/example-modal.json @@ -19,12 +19,12 @@ "num_train_epochs": 3, "warmup_ratio": 0.1, "logging_first_step": true, - "logging_steps": 100, + "logging_steps": 500, "save_steps": 500, "seed": 42, "bf16": true, "fp16": false, - "eval_steps": 100, + "eval_steps": 500, "report_to": [ "wandb" ], From 5929e5871dee0c19d7884e5ffad79aff5f17a6e9 Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Tue, 16 Jul 2024 15:47:55 -0400 Subject: [PATCH 12/15] update --- module-3/generative-example/run_training_job.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/module-3/generative-example/run_training_job.py b/module-3/generative-example/run_training_job.py index 8f0b30c..5e307d3 100644 --- a/module-3/generative-example/run_training_job.py +++ b/module-3/generative-example/run_training_job.py @@ -11,7 +11,7 @@ custom_image = Image.from_registry("ghcr.io/kyryl-opens-ml/generative-example:pr-11").env(env) -@app.function(image=custom_image, gpu="a10g", timeout=15 * 60) +@app.function(image=custom_image, gpu="a10g", timeout=6 * 60 * 60) def run_generative_example(): from pathlib import Path @@ -20,11 +20,11 @@ def run_generative_example(): from generative_example.train import train from generative_example.utils import load_from_registry, upload_to_registry - load_sql_data(path_to_save=Path("/tmp/data"), subsample=0.1) + load_sql_data(path_to_save=Path("/tmp/data"), subsample=0.01) train(config_path=Path("/app/conf/example-modal.json")) - upload_to_registry(model_name="modal-generative-example", model_path=Path("/tmp/phi-3-mini-lora-text2sql")) - load_from_registry(model_name="modal-generative-example", model_path=Path("/tmp/loaded-model")) - run_evaluate_on_json(json_path=Path("/tmp/data/test.json"), model_load_path=Path("/tmp/loaded-model"), result_path=Path("/tmp/data/results.json")) + # upload_to_registry(model_name="modal_generative_example", model_path=Path("/tmp/phi-3-mini-lora-text2sql")) + # load_from_registry(model_name="modal_generative_example", model_path=Path("/tmp/loaded-model")) + run_evaluate_on_json(json_path=Path("/tmp/data/test.json"), model_load_path=Path("/tmp/phi-3-mini-lora-text2sql"), result_path=Path("/tmp/data/results.json")) def main(): From b4b54e8fb385836ef81daee7db91655017216bf0 Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Tue, 16 Jul 2024 17:03:55 -0400 Subject: [PATCH 13/15] ci --- module-3/classic-example/run_training_job.py | 2 +- module-3/generative-example/run_training_job.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/module-3/classic-example/run_training_job.py b/module-3/classic-example/run_training_job.py index bd3318f..668f490 100644 --- a/module-3/classic-example/run_training_job.py +++ b/module-3/classic-example/run_training_job.py @@ -24,7 +24,7 @@ def run_classic_example(): train(config_path=Path("/app/conf/example.json")) upload_to_registry(model_name="modal-classic-example", model_path=Path("results")) load_from_registry( - model_name="modal-classic-example", model_path=Path("loaded-model") + model_name="modal-classic-example:latest", model_path=Path("loaded-model") ) run_inference_on_dataframe( df_path=Path("/tmp/data/test.csv"), diff --git a/module-3/generative-example/run_training_job.py b/module-3/generative-example/run_training_job.py index 5e307d3..96a8d19 100644 --- a/module-3/generative-example/run_training_job.py +++ b/module-3/generative-example/run_training_job.py @@ -22,9 +22,9 @@ def run_generative_example(): load_sql_data(path_to_save=Path("/tmp/data"), subsample=0.01) train(config_path=Path("/app/conf/example-modal.json")) - # upload_to_registry(model_name="modal_generative_example", model_path=Path("/tmp/phi-3-mini-lora-text2sql")) - # load_from_registry(model_name="modal_generative_example", model_path=Path("/tmp/loaded-model")) - run_evaluate_on_json(json_path=Path("/tmp/data/test.json"), model_load_path=Path("/tmp/phi-3-mini-lora-text2sql"), result_path=Path("/tmp/data/results.json")) + upload_to_registry(model_name="modal_generative_example", model_path=Path("/tmp/phi-3-mini-lora-text2sql")) + load_from_registry(model_name="modal_generative_example:latest", model_path=Path("/tmp/loaded-model")) + run_evaluate_on_json(json_path=Path("/tmp/data/test.json"), model_load_path=Path("/tmp/loaded-model"), result_path=Path("/tmp/data/results.json")) def main(): From c7fe74d520a3ef9f4350cb986546ca5c044efc1a Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Tue, 16 Jul 2024 17:10:51 -0400 Subject: [PATCH 14/15] fix style --- module-3/generative-api/pipeline_phi3.py | 2 +- module-3/generative-example/run_training_job.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/module-3/generative-api/pipeline_phi3.py b/module-3/generative-api/pipeline_phi3.py index c979aaa..8e70eff 100644 --- a/module-3/generative-api/pipeline_phi3.py +++ b/module-3/generative-api/pipeline_phi3.py @@ -63,7 +63,7 @@ def get_sql(query: str, context: str) -> str: matched_text = match.group(0) try: sql = json.loads(matched_text)["sql"] - except json.JSONDecodeError as ex: + except json.JSONDecodeError: print(f"Cannot parse {generated_text} output") sql = "" return sql diff --git a/module-3/generative-example/run_training_job.py b/module-3/generative-example/run_training_job.py index 96a8d19..6bbe1ff 100644 --- a/module-3/generative-example/run_training_job.py +++ b/module-3/generative-example/run_training_job.py @@ -11,7 +11,7 @@ custom_image = Image.from_registry("ghcr.io/kyryl-opens-ml/generative-example:pr-11").env(env) -@app.function(image=custom_image, gpu="a10g", timeout=6 * 60 * 60) +@app.function(image=custom_image, gpu="a10g", timeout=10 * 60 * 60) def run_generative_example(): from pathlib import Path @@ -20,7 +20,7 @@ def run_generative_example(): from generative_example.train import train from generative_example.utils import load_from_registry, upload_to_registry - load_sql_data(path_to_save=Path("/tmp/data"), subsample=0.01) + load_sql_data(path_to_save=Path("/tmp/data")) train(config_path=Path("/app/conf/example-modal.json")) upload_to_registry(model_name="modal_generative_example", model_path=Path("/tmp/phi-3-mini-lora-text2sql")) load_from_registry(model_name="modal_generative_example:latest", model_path=Path("/tmp/loaded-model")) From 7d1cb7d7f6c5f171335d5bd12a1a7400e4f51486 Mon Sep 17 00:00:00 2001 From: truskovskiyk Date: Tue, 16 Jul 2024 22:15:23 -0400 Subject: [PATCH 15/15] update to A100 --- module-3/generative-example/run_training_job.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module-3/generative-example/run_training_job.py b/module-3/generative-example/run_training_job.py index 6bbe1ff..c6dc03a 100644 --- a/module-3/generative-example/run_training_job.py +++ b/module-3/generative-example/run_training_job.py @@ -11,7 +11,7 @@ custom_image = Image.from_registry("ghcr.io/kyryl-opens-ml/generative-example:pr-11").env(env) -@app.function(image=custom_image, gpu="a10g", timeout=10 * 60 * 60) +@app.function(image=custom_image, gpu="A100", timeout=10 * 60 * 60) def run_generative_example(): from pathlib import Path