From f7db51fd8100a0a9af6a365ced4f5ddb06408d23 Mon Sep 17 00:00:00 2001 From: Brad Hilton Date: Mon, 11 Aug 2025 19:21:29 -0600 Subject: [PATCH 1/5] pypi: remove direct git deps from metadata; add requirements/backend.vcs.txt; lock torchtune+unsloth-zoo commits via uv sources --- pyproject.toml | 6 +++--- requirements/backend.vcs.txt | 11 +++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 requirements/backend.vcs.txt diff --git a/pyproject.toml b/pyproject.toml index 984e0817..a6ab2aa8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,9 +19,7 @@ backend = [ "hf-xet>=1.1.0", "bitsandbytes>=0.45.2", "unsloth==2025.8.1", - "unsloth-zoo @ git+https://github.com/bradhilton/unsloth-zoo@323cf5e", "vllm==0.10.0", - "torchtune @ git+https://github.com/pytorch/torchtune.git@2344509cf83bd886538fe3e8263e5145d1afb5c2", "trl>=0.19.0", "torch>=2.7.0", "torchao>=0.9.0", @@ -50,7 +48,7 @@ requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.metadata] -allow-direct-references = true +allow-direct-references = false [tool.hatch.build.targets.wheel] packages = ["src/art", "src/mp_actors"] @@ -95,3 +93,5 @@ dev-dependencies = [ [tool.uv.sources] panza = { git = "https://github.com/corbt/panza.git" } sweagent = { git = "https://github.com/bradhilton/SWE-agent" } +torchtune = { git = "https://github.com/pytorch/torchtune.git", rev = "2344509cf83bd886538fe3e8263e5145d1afb5c2" } +unsloth-zoo = { git = "https://github.com/bradhilton/unsloth-zoo", rev = "323cf5e" } diff --git a/requirements/backend.vcs.txt b/requirements/backend.vcs.txt new file mode 100644 index 00000000..13539e64 --- /dev/null +++ b/requirements/backend.vcs.txt @@ -0,0 +1,11 @@ +# Pinned backend dependencies that must come from VCS (not allowed in PyPI metadata). +# Install with: +# uv pip install -r requirements/backend.vcs.txt +# or +# pip install -r requirements/backend.vcs.txt + +# Torchtune pinned to known-good commit + torchtune @ git+https://github.com/pytorch/torchtune.git@2344509cf83bd886538fe3e8263e5145d1afb5c2 + +# Unsloth Zoo pinned to known-good commit + unsloth-zoo @ git+https://github.com/bradhilton/unsloth-zoo@323cf5e From 4a1a45173e9c7657830eb25b64804785ab87b8c0 Mon Sep 17 00:00:00 2001 From: Brad Hilton Date: Mon, 11 Aug 2025 19:32:30 -0600 Subject: [PATCH 2/5] chore: Revert pin removals --- pyproject.toml | 6 +++--- uv.lock | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a6ab2aa8..984e0817 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,9 @@ backend = [ "hf-xet>=1.1.0", "bitsandbytes>=0.45.2", "unsloth==2025.8.1", + "unsloth-zoo @ git+https://github.com/bradhilton/unsloth-zoo@323cf5e", "vllm==0.10.0", + "torchtune @ git+https://github.com/pytorch/torchtune.git@2344509cf83bd886538fe3e8263e5145d1afb5c2", "trl>=0.19.0", "torch>=2.7.0", "torchao>=0.9.0", @@ -48,7 +50,7 @@ requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.metadata] -allow-direct-references = false +allow-direct-references = true [tool.hatch.build.targets.wheel] packages = ["src/art", "src/mp_actors"] @@ -93,5 +95,3 @@ dev-dependencies = [ [tool.uv.sources] panza = { git = "https://github.com/corbt/panza.git" } sweagent = { git = "https://github.com/bradhilton/SWE-agent" } -torchtune = { git = "https://github.com/pytorch/torchtune.git", rev = "2344509cf83bd886538fe3e8263e5145d1afb5c2" } -unsloth-zoo = { git = "https://github.com/bradhilton/unsloth-zoo", rev = "323cf5e" } diff --git a/uv.lock b/uv.lock index ee9308cf..327b9818 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 2 requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.13' and sys_platform == 'linux'", From 59aa3b897aba0d7b78783e4ac226c3f17d3af371 Mon Sep 17 00:00:00 2001 From: Brad Hilton Date: Mon, 11 Aug 2025 21:18:09 -0600 Subject: [PATCH 3/5] fix: Patch Unsloth issue --- pyproject.toml | 5 ++-- src/art/unsloth/state.py | 6 ++++ src/art/vllm/__init__.py | 2 ++ src/art/vllm/patches.py | 63 ++++++++++++++++++++++++++++++++++++++++ uv.lock | 10 +++++-- 5 files changed, 81 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 984e0817..fac60fae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,9 +19,9 @@ backend = [ "hf-xet>=1.1.0", "bitsandbytes>=0.45.2", "unsloth==2025.8.1", - "unsloth-zoo @ git+https://github.com/bradhilton/unsloth-zoo@323cf5e", + "unsloth-zoo==2025.8.1", "vllm==0.10.0", - "torchtune @ git+https://github.com/pytorch/torchtune.git@2344509cf83bd886538fe3e8263e5145d1afb5c2", + "torchtune", "trl>=0.19.0", "torch>=2.7.0", "torchao>=0.9.0", @@ -95,3 +95,4 @@ dev-dependencies = [ [tool.uv.sources] panza = { git = "https://github.com/corbt/panza.git" } sweagent = { git = "https://github.com/bradhilton/SWE-agent" } +torchtune = { git = "https://github.com/pytorch/torchtune.git", rev = "2344509cf83bd886538fe3e8263e5145d1afb5c2" } diff --git a/src/art/unsloth/state.py b/src/art/unsloth/state.py index 32868f48..d1296640 100644 --- a/src/art/unsloth/state.py +++ b/src/art/unsloth/state.py @@ -41,6 +41,8 @@ class ModelState: def __init__(self, config: InternalModelConfig) -> None: from vllm.engine import async_llm_engine + from ..vllm import patch_patch_vllm + # Patch MultiStepModelRunner for Unsloth compatibility if not hasattr(MultiStepModelRunner, "model"): MultiStepModelRunner.model = property( # type: ignore @@ -74,6 +76,10 @@ def _from_engine_args( ) AsyncLLMEngine.from_engine_args = _from_engine_args + + # Patch patch_vllm before loading an Unsloth model + patch_patch_vllm() + self.model, self.tokenizer = cast( tuple[CausallLM, PreTrainedTokenizerBase], unsloth.FastLanguageModel.from_pretrained(**config.get("init_args", {})), diff --git a/src/art/vllm/__init__.py b/src/art/vllm/__init__.py index 8d14ddfe..be5c91e5 100644 --- a/src/art/vllm/__init__.py +++ b/src/art/vllm/__init__.py @@ -17,6 +17,7 @@ patch_listen_for_disconnect, patch_lora_request, patch_multi_step_model_runner, + patch_patch_vllm, patch_tool_parser_manager, subclass_chat_completion_request, ) @@ -45,4 +46,5 @@ "patch_listen_for_disconnect", "patch_tool_parser_manager", "patch_multi_step_model_runner", + "patch_patch_vllm", ] diff --git a/src/art/vllm/patches.py b/src/art/vllm/patches.py index 1190b217..53c04dce 100644 --- a/src/art/vllm/patches.py +++ b/src/art/vllm/patches.py @@ -199,3 +199,66 @@ def patch_multi_step_model_runner(runner: MultiStepModelRunner) -> None: runner.remove_lora = base_runner.remove_lora runner.pin_lora = base_runner.pin_lora runner.list_loras = base_runner.list_loras + + +def patch_patch_vllm() -> None: + """ + Unironically patches the vLLM patch_vllm function to address a bug (see below). + """ + import os + + from unsloth_zoo import vllm_utils + from unsloth_zoo.vllm_lora_request import ( + LoRARequest as PatchedLoRARequest, # type: ignore + ) + from unsloth_zoo.vllm_lora_worker_manager import ( + LRUCacheWorkerLoRAManager as PatchedLRUCacheWorkerLoRAManager, + ) + from unsloth_zoo.vllm_lora_worker_manager import ( # type: ignore + WorkerLoRAManager as PatchedWorkerLoRAManager, + ) + + def patch_vllm_lora_load_tensors() -> None: + import vllm.lora.request + + vllm.lora.request.LoRARequest = PatchedLoRARequest + import vllm.lora.worker_manager + + vllm.lora.worker_manager.LoRARequest = PatchedLoRARequest # type: ignore + vllm.lora.worker_manager.WorkerLoRAManager = PatchedWorkerLoRAManager + vllm.lora.worker_manager.LRUCacheWorkerLoRAManager = ( + PatchedLRUCacheWorkerLoRAManager + ) + try: + import vllm.v1.worker.lora_model_runner_mixin + + vllm.v1.worker.lora_model_runner_mixin.LRUCacheWorkerLoRAManager = ( # type: ignore + PatchedLRUCacheWorkerLoRAManager + ) + except: + pass + # We comment this out because it causes issues with vLLM's LoRARequest + # try: + # import vllm.worker.model_runner + # vllm.worker.model_runner.LRUCacheWorkerLoRAManager = PatchedLRUCacheWorkerLoRAManager + # except: + # pass + + def patch_vllm(debug: bool = True) -> None: + # Temporary patch to disable multiprocessing for vLLM + # Allows accessing model_executor + os.environ["VLLM_ENABLE_V1_MULTIPROCESSING"] = "0" + if debug: + os.environ["VLLM_LOGGING_LEVEL"] = "DEBUG" + # os.environ["VLLM_TRACE_FUNCTION"] = "1" + vllm_utils.patch_vllm_set_inductor_config() + vllm_utils.patch_bitsandbytes_quant_state() + vllm_utils.patch_vllm_bitsandbytes() + vllm_utils.patch_vllm_lora_tokenizer() + # sub our patch in + patch_vllm_lora_load_tensors() + vllm_utils.patch_vllm_enable_sleep_mode() + vllm_utils.patch_vllm_graph_capture() + vllm_utils.LORA_REQUEST_ID = 1 + + vllm_utils.patch_vllm = patch_vllm diff --git a/uv.lock b/uv.lock index 327b9818..5de3d707 100644 --- a/uv.lock +++ b/uv.lock @@ -3574,7 +3574,7 @@ requires-dist = [ { name = "trl", marker = "extra == 'backend'", specifier = ">=0.19.0" }, { name = "typer", specifier = ">=0.15.2" }, { name = "unsloth", marker = "extra == 'backend'", specifier = "==2025.8.1" }, - { name = "unsloth-zoo", marker = "extra == 'backend'", git = "https://github.com/bradhilton/unsloth-zoo?rev=323cf5e" }, + { name = "unsloth-zoo", marker = "extra == 'backend'", specifier = "==2025.8.1" }, { name = "vllm", marker = "extra == 'backend'", specifier = "==0.10.0" }, { name = "wandb", marker = "extra == 'backend'", specifier = ">=0.19.8" }, { name = "weave", specifier = ">=0.51.51" }, @@ -6630,8 +6630,8 @@ wheels = [ [[package]] name = "unsloth-zoo" -version = "2025.8.2" -source = { git = "https://github.com/bradhilton/unsloth-zoo?rev=323cf5e#323cf5e4cd0a9e62e49bb40d4dfd52b7bc8354f2" } +version = "2025.8.1" +source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "accelerate" }, { name = "cut-cross-entropy" }, @@ -6657,6 +6657,10 @@ dependencies = [ { name = "tyro" }, { name = "wheel" }, ] +sdist = { url = "https://files.pythonhosted.org/packages/37/bc/c710b9da0d70ca1cb324adc3310b9d1ed31dc340956cbb64cbb7412ef57a/unsloth_zoo-2025.8.1.tar.gz", hash = "sha256:02401f77e7496fc03d71460afd51f7d10e71376056ff1e33ca776723237dcb5e", size = 148526, upload-time = "2025-08-02T10:38:43.356Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/d9/7199031146fbf00eeea1af1b8b9db16c6ec0e86ae86db515eabcedfaa00d/unsloth_zoo-2025.8.1-py3-none-any.whl", hash = "sha256:3dc80e8909072e5812efaca38f965ebb4cdc2c8bd87df9fb0690dc37dcf5003c", size = 166706, upload-time = "2025-08-02T10:38:41.728Z" }, +] [[package]] name = "uritemplate" From c3f5e00a513007db99ccc6db35848152ce2c4e51 Mon Sep 17 00:00:00 2001 From: Bohdan Kovalevskyi Date: Mon, 11 Aug 2025 20:18:32 -0700 Subject: [PATCH 4/5] fix: unsloth-zoo ascii encoding issue --- .env.example | 2 +- skypilot-config.yaml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index c9bb6809..8cbf94d3 100644 --- a/.env.example +++ b/.env.example @@ -20,4 +20,4 @@ TOGETHER_API_KEY=YOUR_TOGETHER_API_KEY AWS_ACCESS_KEY_ID=YOUR_AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_ACCESS_KEY AWS_REGION=YOUR_AWS_REGION -BACKUP_BUCKET=YOUR_BACKUP_BUCKET +BACKUP_BUCKET=YOUR_BACKUP_BUCKET \ No newline at end of file diff --git a/skypilot-config.yaml b/skypilot-config.yaml index c3212619..e6a204f3 100644 --- a/skypilot-config.yaml +++ b/skypilot-config.yaml @@ -391,5 +391,6 @@ envs: GIT_USER_NAME: "Your Name" GIT_USER_EMAIL: "your.email@example.com" GITHUB_TOKEN: "" + PYTHONUTF8: "1" #Enforce UTF-8 Encoding to fix ASCII encoding issue in unsloth-zoo setup: | ./scripts/setup.sh From b854664e6f6c74d9650ea31941b5812fc126c42a Mon Sep 17 00:00:00 2001 From: Brad Hilton Date: Tue, 12 Aug 2025 07:22:56 -0600 Subject: [PATCH 5/5] release: Bump version to 0.4.7 Co-authored-by: GitHub Action --- pyproject.toml | 2 +- uv.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fac60fae..be77218f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openpipe-art" -version = "0.4.6" +version = "0.4.7" description = "The OpenPipe Agent Reinforcement Training (ART) library" readme = "README.md" requires-python = ">=3.10" diff --git a/uv.lock b/uv.lock index 5de3d707..35ecf01b 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.10" resolution-markers = [ "python_full_version >= '3.13' and sys_platform == 'linux'", @@ -3499,7 +3499,7 @@ wheels = [ [[package]] name = "openpipe-art" -version = "0.4.6" +version = "0.4.7" source = { editable = "." } dependencies = [ { name = "litellm" },