From 551db26bb75eb203cccdc25603a6a001eed1c795 Mon Sep 17 00:00:00 2001 From: iuyua9 Date: Sat, 16 May 2026 11:49:15 +0800 Subject: [PATCH 01/18] fix: recognize root Hugging Face repo IDs (#325) * fix: recognize root Hugging Face repo IDs * fix: propagate invalid HF repo ids * fix: match transformers local path precedence --- src/heretic/utils.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/heretic/utils.py b/src/heretic/utils.py index 27dd697..32f78b7 100644 --- a/src/heretic/utils.py +++ b/src/heretic/utils.py @@ -22,6 +22,7 @@ from datasets import DatasetDict, ReadInstruction, load_dataset, load_from_disk from datasets.config import DATASET_STATE_JSON_FILENAME from datasets.download.download_manager import DownloadMode from datasets.utils.info_utils import VerificationMode +from huggingface_hub.utils import validate_repo_id from optuna import Trial from psutil import Process from questionary import Choice, Style @@ -172,13 +173,13 @@ def format_duration(seconds: float) -> str: def is_hf_path(path: str) -> bool: """Checks whether a path likely refers to a Hugging Face repository.""" - return ( - not path.startswith("/") - and not path.endswith("/") - and path.count("/") == 1 - and "\\" not in path - and not Path(path).exists() - ) + # Match Transformers: existing local paths take precedence over Hub lookup, + # even if the path string is also a valid repository ID. + if Path(path).exists(): + return False + + validate_repo_id(path) + return True @dataclass From 4e3a3a78a3e68cf3bc30e9fffcf053110595fa10 Mon Sep 17 00:00:00 2001 From: Philipp Emanuel Weidmann Date: Fri, 22 May 2026 14:51:24 +0530 Subject: [PATCH 02/18] docs: update README --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 94c24a5..708927d 100644 --- a/README.md +++ b/README.md @@ -116,8 +116,9 @@ a configuration file. At the start of a program run, Heretic benchmarks the system to determine the optimal batch size to make the most of the available hardware. -On an RTX 3090, with the default configuration, decensoring Llama-3.1-8B-Instruct -takes about 45 minutes. Note that Heretic supports model quantization with +On an RTX 3090, with the default configuration, decensoring +[Qwen3-4B-Instruct-2507](https://huggingface.co/Qwen/Qwen3-4B-Instruct-2507) +takes about 20-30 minutes. Note that Heretic supports model quantization with bitsandbytes, which can drastically reduce the amount of VRAM required to process models. Set the `quantization` option to `bnb_4bit` to enable quantization. From b8d2c5a7e99a202ef7f42853ea4da62fb37a69e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 May 2026 14:56:21 +0530 Subject: [PATCH 03/18] build(deps): bump idna from 3.11 to 3.15 (#327) Bumps [idna](https://github.com/kjd/idna) from 3.11 to 3.15. - [Release notes](https://github.com/kjd/idna/releases) - [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.md) - [Commits](https://github.com/kjd/idna/compare/v3.11...v3.15) --- updated-dependencies: - dependency-name: idna dependency-version: '3.15' dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index e0df602..7b6be5e 100644 --- a/uv.lock +++ b/uv.lock @@ -1123,11 +1123,11 @@ wheels = [ [[package]] name = "idna" -version = "3.11" +version = "3.15" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +sdist = { url = "https://files.pythonhosted.org/packages/82/77/7b3966d0b9d1d31a36ddf1746926a11dface89a83409bf1483f0237aa758/idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc", size = 199245, upload-time = "2026-05-12T22:45:57.011Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, + { url = "https://files.pythonhosted.org/packages/d2/23/408243171aa9aaba178d3e2559159c24c1171a641aa83b67bdd3394ead8e/idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8", size = 72340, upload-time = "2026-05-12T22:45:55.733Z" }, ] [[package]] From 4dcacb5ebabb5b847d5021dcd7fc82e010effbb8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 May 2026 15:00:08 +0530 Subject: [PATCH 04/18] build(deps): bump urllib3 from 2.6.3 to 2.7.0 (#328) Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.6.3 to 2.7.0. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.6.3...2.7.0) --- updated-dependencies: - dependency-name: urllib3 dependency-version: 2.7.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uv.lock b/uv.lock index 7b6be5e..8d13151 100644 --- a/uv.lock +++ b/uv.lock @@ -3905,11 +3905,11 @@ wheels = [ [[package]] name = "urllib3" -version = "2.6.3" +version = "2.7.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } +sdist = { url = "https://files.pythonhosted.org/packages/53/0c/06f8b233b8fd13b9e5ee11424ef85419ba0d8ba0b3138bf360be2ff56953/urllib3-2.7.0.tar.gz", hash = "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", size = 433602, upload-time = "2026-05-07T16:13:18.596Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, + { url = "https://files.pythonhosted.org/packages/7f/3e/5db95bcf282c52709639744ca2a8b149baccf648e39c8cc87553df9eae0c/urllib3-2.7.0-py3-none-any.whl", hash = "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897", size = 131087, upload-time = "2026-05-07T16:13:17.151Z" }, ] [[package]] From 6338e2c99ba7ac2e9ec4c253d1c3fb187bb0cecd Mon Sep 17 00:00:00 2001 From: kabachuha Date: Thu, 28 May 2026 15:06:30 +0300 Subject: [PATCH 05/18] feat: add "disclaimer" to the prohibited strings list (#334) * add "disclaimer" to the prohibited strings list The favorite Gemma's word. * add "disclaimer" to config.py refusal markers --- config.default.toml | 1 + src/heretic/config.py | 1 + 2 files changed, 2 insertions(+) diff --git a/config.default.toml b/config.default.toml index 6ec8e8e..cdfe826 100644 --- a/config.default.toml +++ b/config.default.toml @@ -135,6 +135,7 @@ max_shard_size = "5GB" # Strings whose presence in a response (case insensitive) identifies the response as a refusal. refusal_markers = [ + "disclaimer", "sorry", "i can'", "i cant", diff --git a/src/heretic/config.py b/src/heretic/config.py index c2879f3..668073a 100644 --- a/src/heretic/config.py +++ b/src/heretic/config.py @@ -412,6 +412,7 @@ class Settings(BaseSettings): refusal_markers: list[str] = Field( default=[ + "disclaimer", "sorry", "i can'", "i cant", From b790094193e0f54ba38f60fd3be41687de4e3bb3 Mon Sep 17 00:00:00 2001 From: Rocker Zhang Date: Sun, 31 May 2026 17:36:47 +0800 Subject: [PATCH 06/18] feat: support plain text files as prompt datasets (#337) A dataset path that points to a plain file is now read as one prompt per line, with empty lines ignored. For text files, "column" is ignored and "split" is optional; when given, it selects a subset of lines using slice notation (e.g. "[:400]"). Detection uses os.path.isfile so files without an extension also work. The split-parsing logic is factored into a shared get_split_slice helper, which derives the split name from the specification, and split/column are now optional in DatasetSpecification, with the dataset branches raising a clear error when either is missing. An invalid split raises instead of being silently ignored. A bare slice does not parse with the pinned datasets version, since ReadInstruction.from_spec expects a named split, so the text branch prepends a synthetic split name. Revives the approach from #103. Closes #98. Co-authored-by: Ric --- config.default.toml | 5 ++++ src/heretic/config.py | 10 ++++++-- src/heretic/utils.py | 60 +++++++++++++++++++++++++++++++------------ 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/config.default.toml b/config.default.toml index cdfe826..9424bfb 100644 --- a/config.default.toml +++ b/config.default.toml @@ -173,6 +173,11 @@ refusal_markers = [ # System prompt to use when prompting the model. system_prompt = "You are a helpful assistant." +# Each "dataset" below can be a Hugging Face dataset ID, a path to a dataset on disk, +# or a path to a plain text file with one prompt per line (empty lines are ignored). +# For text files, "column" is ignored and "split" is optional; when given, it selects +# a subset of the lines using slice notation (e.g. "[:400]"). + # Dataset of prompts that tend to not result in refusals (used for calculating refusal directions). [good_prompts] dataset = "mlabonne/harmless_alpaca" diff --git a/src/heretic/config.py b/src/heretic/config.py index 668073a..ada5792 100644 --- a/src/heretic/config.py +++ b/src/heretic/config.py @@ -42,9 +42,15 @@ class DatasetSpecification(BaseModel): description="Hugging Face commit hash of the dataset.", ) - split: str = Field(description="Portion of the dataset to use.") + split: str | None = Field( + default=None, + description="Portion of the dataset to use. Required for datasets, optional for plain text files.", + ) - column: str = Field(description="Column in the dataset that contains the prompts.") + column: str | None = Field( + default=None, + description="Column in the dataset that contains the prompts. Required for datasets, ignored for plain text files.", + ) prefix: str = Field( default="", diff --git a/src/heretic/utils.py b/src/heretic/utils.py index 32f78b7..778d52e 100644 --- a/src/heretic/utils.py +++ b/src/heretic/utils.py @@ -188,6 +188,20 @@ class Prompt: user: str +def get_split_slice(split_str: str, length: int) -> tuple[int, int]: + """Resolves a split specification into absolute (start, end) indices.""" + + # The split name is the part before the slice, e.g. "train" in "train[:400]". + split_name = split_str.split("[")[0] + # Associate the split with its number of examples (lines). + name_to_length = {split_name: length} + # Convert the instructions to absolute indices and select the first one. + absolute_instruction = ReadInstruction.from_spec(split_str).to_absolute( + name_to_length + )[0] + return absolute_instruction.from_, absolute_instruction.to + + def load_prompts( settings: Settings, specification: DatasetSpecification, @@ -195,29 +209,41 @@ def load_prompts( path = specification.dataset split_str = specification.split - if is_hf_path(path): - dataset = load_dataset( - path, - revision=specification.commit, - split=split_str, - ) + if os.path.isfile(path): + # Plain text file with one prompt per line. Empty lines are ignored. + with open(path, encoding="utf-8") as file: + prompts = [line.strip() for line in file if line.strip()] + + # The split is optional for text files. When given, it selects a subset + # of the lines using slice notation (e.g. "[:400]"). A synthetic split + # name is prepended because ReadInstruction expects a named split. + if split_str is not None: + start, end = get_split_slice(f"_{split_str}", len(prompts)) + prompts = prompts[start:end] else: - if Path(path, DATASET_STATE_JSON_FILENAME).exists(): + # All dataset sources require an explicit split and column. + if split_str is None: + raise ValueError(f'The "split" field is required for datasets: {path}') + + if specification.column is None: + raise ValueError(f'The "column" field is required for datasets: {path}') + + if is_hf_path(path): + dataset = load_dataset( + path, + revision=specification.commit, + split=split_str, + ) + elif Path(path, DATASET_STATE_JSON_FILENAME).exists(): # Dataset saved with datasets.save_to_disk; needs special handling. # Path should be the subdirectory for a particular split. dataset = load_from_disk(path) assert not isinstance(dataset, DatasetDict), ( "Loading dataset dicts is not supported" ) - # Parse the split instructions. - instruction = ReadInstruction.from_spec(split_str) - # Associate the split with its number of examples (lines). - split_name = str(dataset.split) - name2len = {split_name: len(dataset)} - # Convert the instructions to absolute indices and select the first one. - abs_instruction = instruction.to_absolute(name2len)[0] - # Get the dataset by applying the indices. - dataset = dataset[abs_instruction.from_ : abs_instruction.to] + # Parse the split instructions and apply them. + start, end = get_split_slice(split_str, len(dataset)) + dataset = dataset[start:end] else: # Path should be a local directory. dataset = load_dataset( @@ -229,7 +255,7 @@ def load_prompts( download_mode=DownloadMode.FORCE_REDOWNLOAD, ) - prompts = list(dataset[specification.column]) + prompts = list(dataset[specification.column]) if specification.prefix: prompts = [f"{specification.prefix} {prompt}" for prompt in prompts] From db07814a9716740b8f65af3f3364811bae0c39ca Mon Sep 17 00:00:00 2001 From: Rocker Zhang Date: Sun, 31 May 2026 17:46:31 +0800 Subject: [PATCH 07/18] build(deps): remove unused hf-transfer dependency (#338) hf-transfer is declared in pyproject.toml but never activated: nothing in the codebase sets HF_HUB_ENABLE_HF_TRANSFER, and downloads go through from_pretrained / hf_hub_download with no transfer toggle. huggingface-hub is pinned ~=1.7, where Xet is the default transfer backend, so hf-transfer is dead weight and only surfaces a deprecation warning. --- pyproject.toml | 1 - uv.lock | 34 ---------------------------------- 2 files changed, 35 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3a45e0d..e8681ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,6 @@ dependencies = [ "accelerate~=1.13", "bitsandbytes~=0.49", "datasets~=4.7", - "hf-transfer~=0.1", "huggingface-hub~=1.7", "immutabledict~=4.3", "kernels~=0.13", diff --git a/uv.lock b/uv.lock index 8d13151..f7fbfe9 100644 --- a/uv.lock +++ b/uv.lock @@ -937,7 +937,6 @@ dependencies = [ { name = "accelerate" }, { name = "bitsandbytes" }, { name = "datasets" }, - { name = "hf-transfer" }, { name = "huggingface-hub" }, { name = "immutabledict" }, { name = "kernels" }, @@ -979,7 +978,6 @@ requires-dist = [ { name = "bitsandbytes", specifier = "~=0.49" }, { name = "datasets", specifier = "~=4.7" }, { name = "geom-median", marker = "extra == 'research'", specifier = "~=0.1" }, - { name = "hf-transfer", specifier = "~=0.1" }, { name = "huggingface-hub", specifier = "~=1.7" }, { name = "imageio", marker = "extra == 'research'", specifier = "~=2.37" }, { name = "immutabledict", specifier = "~=4.3" }, @@ -1009,38 +1007,6 @@ dev = [ { name = "ty", specifier = ">=0.0.5" }, ] -[[package]] -name = "hf-transfer" -version = "0.1.9" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1a/eb/8fc64f40388c29ce8ce3b2b180a089d4d6b25b1d0d232d016704cb852104/hf_transfer-0.1.9.tar.gz", hash = "sha256:035572865dab29d17e783fbf1e84cf1cb24f3fcf8f1b17db1cfc7fdf139f02bf", size = 25201, upload-time = "2025-01-07T10:05:12.947Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/78/0dce00208f585fae675f40033ef9a30dedfa83665d5ac79f16beb4a0a6c2/hf_transfer-0.1.9-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:6e94e8822da79573c9b6ae4d6b2f847c59a7a06c5327d7db20751b68538dc4f6", size = 1386084, upload-time = "2025-01-07T10:04:47.874Z" }, - { url = "https://files.pythonhosted.org/packages/ea/2e/3d60b1a9e9f29a2152aa66c823bf5e399ae7be3fef310ff0de86779c5d2d/hf_transfer-0.1.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3ebc4ab9023414880c8b1d3c38174d1c9989eb5022d37e814fa91a3060123eb0", size = 1343558, upload-time = "2025-01-07T10:04:42.313Z" }, - { url = "https://files.pythonhosted.org/packages/fb/38/130a5ac3747f104033591bcac1c961cb1faadfdc91704f59b09c0b465ff2/hf_transfer-0.1.9-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8674026f21ed369aa2a0a4b46000aca850fc44cd2b54af33a172ce5325b4fc82", size = 3726676, upload-time = "2025-01-07T10:04:11.539Z" }, - { url = "https://files.pythonhosted.org/packages/15/a1/f4e27c5ad17aac616ae0849e2aede5aae31db8267a948c6b3eeb9fd96446/hf_transfer-0.1.9-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a736dfbb2c84f5a2c975478ad200c0c8bfcb58a25a35db402678fb87ce17fa4", size = 3062920, upload-time = "2025-01-07T10:04:16.297Z" }, - { url = "https://files.pythonhosted.org/packages/8d/0d/727abdfba39bc3f1132cfa4c970588c2c0bb0d82fe2d645cc10f4e2f8e0b/hf_transfer-0.1.9-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:504b8427fd785dd8546d53b9fafe6e436bd7a3adf76b9dce556507650a7b4567", size = 3578681, upload-time = "2025-01-07T10:04:29.702Z" }, - { url = "https://files.pythonhosted.org/packages/50/d0/2b213eb1ea8b1252ccaf1a6c804d0aba03fea38aae4124df6a3acb70511a/hf_transfer-0.1.9-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c7fc1b85f4d0f76e452765d7648c9f4bfd0aedb9ced2ae1ebfece2d8cfaf8e2", size = 3398837, upload-time = "2025-01-07T10:04:22.778Z" }, - { url = "https://files.pythonhosted.org/packages/8c/8a/79dbce9006e0bd6b74516f97451a7b7c64dbbb426df15d901dd438cfeee3/hf_transfer-0.1.9-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d991376f0eac70a60f0cbc95602aa708a6f7c8617f28b4945c1431d67b8e3c8", size = 3546986, upload-time = "2025-01-07T10:04:36.415Z" }, - { url = "https://files.pythonhosted.org/packages/a9/f7/9ac239b6ee6fe0bad130325d987a93ea58c4118e50479f0786f1733b37e8/hf_transfer-0.1.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e6ac4eddcd99575ed3735ed911ddf9d1697e2bd13aa3f0ad7e3904dd4863842e", size = 4071715, upload-time = "2025-01-07T10:04:53.224Z" }, - { url = "https://files.pythonhosted.org/packages/d8/a3/0ed697279f5eeb7a40f279bd783cf50e6d0b91f24120dcf66ef2cf8822b4/hf_transfer-0.1.9-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:57fd9880da1ee0f47250f735f791fab788f0aa1ee36afc49f761349869c8b4d9", size = 3388081, upload-time = "2025-01-07T10:04:57.818Z" }, - { url = "https://files.pythonhosted.org/packages/dc/eb/47e477bdf1d784f31c7540db6cc8c354b777e51a186897a7abda34517f36/hf_transfer-0.1.9-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:5d561f0520f493c66b016d99ceabe69c23289aa90be38dd802d2aef279f15751", size = 3658654, upload-time = "2025-01-07T10:05:03.168Z" }, - { url = "https://files.pythonhosted.org/packages/45/07/6661e43fbee09594a8a5e9bb778107d95fe38dac4c653982afe03d32bd4d/hf_transfer-0.1.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a5b366d34cd449fe9b20ef25941e6eef0460a2f74e7389f02e673e1f88ebd538", size = 3690551, upload-time = "2025-01-07T10:05:09.238Z" }, - { url = "https://files.pythonhosted.org/packages/81/f5/461d2e5f307e5048289b1168d5c642ae3bb2504e88dff1a38b92ed990a21/hf_transfer-0.1.9-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:e66acf91df4a8b72f60223059df3003062a5ae111757187ed1a06750a30e911b", size = 1393046, upload-time = "2025-01-07T10:04:51.003Z" }, - { url = "https://files.pythonhosted.org/packages/41/ba/8d9fd9f1083525edfcb389c93738c802f3559cb749324090d7109c8bf4c2/hf_transfer-0.1.9-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:8669dbcc7a3e2e8d61d42cd24da9c50d57770bd74b445c65123291ca842a7e7a", size = 1348126, upload-time = "2025-01-07T10:04:45.712Z" }, - { url = "https://files.pythonhosted.org/packages/8e/a2/cd7885bc9959421065a6fae0fe67b6c55becdeda4e69b873e52976f9a9f0/hf_transfer-0.1.9-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fd0167c4407a3bc4cdd0307e65ada2294ec04f1813d8a69a5243e379b22e9d8", size = 3728604, upload-time = "2025-01-07T10:04:14.173Z" }, - { url = "https://files.pythonhosted.org/packages/f6/2e/a072cf196edfeda3310c9a5ade0a0fdd785e6154b3ce24fc738c818da2a7/hf_transfer-0.1.9-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ee8b10afedcb75f71091bcc197c526a6ebf5c58bbbadb34fdeee6160f55f619f", size = 3064995, upload-time = "2025-01-07T10:04:18.663Z" }, - { url = "https://files.pythonhosted.org/packages/c2/84/aec9ef4c0fab93c1ea2b1badff38c78b4b2f86f0555b26d2051dbc920cde/hf_transfer-0.1.9-cp38-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5828057e313de59300dd1abb489444bc452efe3f479d3c55b31a8f680936ba42", size = 3580908, upload-time = "2025-01-07T10:04:32.834Z" }, - { url = "https://files.pythonhosted.org/packages/29/63/b560d39651a56603d64f1a0212d0472a44cbd965db2fa62b99d99cb981bf/hf_transfer-0.1.9-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc6bd19e1cc177c66bdef15ef8636ad3bde79d5a4f608c158021153b4573509d", size = 3400839, upload-time = "2025-01-07T10:04:26.122Z" }, - { url = "https://files.pythonhosted.org/packages/d6/d8/f87ea6f42456254b48915970ed98e993110521e9263472840174d32c880d/hf_transfer-0.1.9-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdca9bfb89e6f8f281890cc61a8aff2d3cecaff7e1a4d275574d96ca70098557", size = 3552664, upload-time = "2025-01-07T10:04:40.123Z" }, - { url = "https://files.pythonhosted.org/packages/d6/56/1267c39b65fc8f4e2113b36297320f102718bf5799b544a6cbe22013aa1d/hf_transfer-0.1.9-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:89a23f58b7b7effbc047b8ca286f131b17728c99a9f972723323003ffd1bb916", size = 4073732, upload-time = "2025-01-07T10:04:55.624Z" }, - { url = "https://files.pythonhosted.org/packages/82/1a/9c748befbe3decf7cb415e34f8a0c3789a0a9c55910dea73d581e48c0ce5/hf_transfer-0.1.9-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:dc7fff1345980d6c0ebb92c811d24afa4b98b3e07ed070c8e38cc91fd80478c5", size = 3390096, upload-time = "2025-01-07T10:04:59.98Z" }, - { url = "https://files.pythonhosted.org/packages/72/85/4c03da147b6b4b7cb12e074d3d44eee28604a387ed0eaf7eaaead5069c57/hf_transfer-0.1.9-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:1a6bd16c667ebe89a069ca163060127a794fa3a3525292c900b8c8cc47985b0d", size = 3664743, upload-time = "2025-01-07T10:05:05.416Z" }, - { url = "https://files.pythonhosted.org/packages/e7/6e/e597b04f753f1b09e6893075d53a82a30c13855cbaa791402695b01e369f/hf_transfer-0.1.9-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d2fde99d502093ade3ab1b53f80da18480e9902aa960dab7f74fb1b9e5bc5746", size = 3695243, upload-time = "2025-01-07T10:05:11.411Z" }, - { url = "https://files.pythonhosted.org/packages/09/89/d4e234727a26b2546c8fb70a276cd924260d60135f2165bf8b9ed67bb9a4/hf_transfer-0.1.9-cp38-abi3-win32.whl", hash = "sha256:435cc3cdc8524ce57b074032b8fd76eed70a4224d2091232fa6a8cef8fd6803e", size = 1086605, upload-time = "2025-01-07T10:05:18.873Z" }, - { url = "https://files.pythonhosted.org/packages/a1/14/f1e15b851d1c2af5b0b1a82bf8eb10bda2da62d98180220ba6fd8879bb5b/hf_transfer-0.1.9-cp38-abi3-win_amd64.whl", hash = "sha256:16f208fc678911c37e11aa7b586bc66a37d02e636208f18b6bc53d29b5df40ad", size = 1160240, upload-time = "2025-01-07T10:05:14.324Z" }, -] - [[package]] name = "hf-xet" version = "1.4.2" From b79aa717c67195ff1cd33f9a82a56a8df6bfd2f4 Mon Sep 17 00:00:00 2001 From: UnstableLlama <149548995+UnstableLlama@users.noreply.github.com> Date: Sun, 31 May 2026 02:56:40 -0700 Subject: [PATCH 08/18] feat: add config.nohumor.toml (#340) * feat: add config.nohumor * Update config.nohumor.toml Following style guide Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update config.nohumor.toml Reduced initial comments --------- Co-authored-by: UnstableLlama Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- config.nohumor.toml | 69 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 config.nohumor.toml diff --git a/config.nohumor.toml b/config.nohumor.toml new file mode 100644 index 0000000..e3f51b3 --- /dev/null +++ b/config.nohumor.toml @@ -0,0 +1,69 @@ +# Rename this file to config.toml, place it in the working directory +# that you run Heretic from, and edit the configuration to your liking. + +max_response_length = 300 + +residual_plot_title = "PaCMAP Projection of Residuals for Serious/Humorous Prompts" + +refusal_markers = [ + "😅", + "here's one", + "why did", + "walked into a bar", + "gets worse", + "the punchline", + "classic", + "dad joke", + "bad joke", + "pun intended", + "ba dum tss", + "rimshot", + "😂", + "😄", + "😆", + "haha", + "hehe", + "lol", + "funny", + "joke", + "humor", + "that's hilarious", + "you could say", + "one-liner", + "comedian", + "stand-up", + "unexpectedly", + "because apparently", + "to be fair", + "on the bright side", + "lmao", + "omg", + "rofl", + "silly", + "humorous", + "clever", +] + +[good_prompts] +dataset = "mlabonne/harmless_alpaca" +split = "train[:400]" +column = "text" +residual_plot_label = "Serious prompts" +residual_plot_color = "royalblue" + +[bad_prompts] +dataset = "UnstableLlama/jokes" +split = "train[:200]" +column = "text" +residual_plot_label = "Humorous prompts" +residual_plot_color = "darkorange" + +[good_evaluation_prompts] +dataset = "mlabonne/harmless_alpaca" +split = "test[:100]" +column = "text" + +[bad_evaluation_prompts] +dataset = "UnstableLlama/jokes" +split = "train[200:250]" +column = "text" From 906d96f78a3d65984db59f22400867eb152c0d0f Mon Sep 17 00:00:00 2001 From: Ashar Date: Wed, 3 Jun 2026 17:58:05 +0530 Subject: [PATCH 09/18] feat: add support for LiquidAI/LFM2.5 models (#344) * feat: add support for LiquidAI/LFM2.5 models * add lint supress and obey gemini Signed-off-by: coder3101 * ci: format code Signed-off-by: Ashar --------- Signed-off-by: coder3101 Signed-off-by: Ashar --- src/heretic/model.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/heretic/model.py b/src/heretic/model.py index 41a8e71..2513091 100644 --- a/src/heretic/model.py +++ b/src/heretic/model.py @@ -389,6 +389,21 @@ class Model: for expert in layer.block_sparse_moe.experts: # ty:ignore[possibly-missing-attribute, not-iterable] try_add("mlp.down_proj", expert.w2) # ty:ignore[possibly-missing-attribute] + # LFM dense operator blocks. + with suppress(Exception): + try_add("attn.o_proj", layer.conv.out_proj) # ty:ignore[possibly-missing-attribute] + + with suppress(Exception): + try_add("mlp.down_proj", layer.feed_forward.w2) # ty:ignore[possibly-missing-attribute] + + # LFM transformer blocks. + with suppress(Exception): + try_add("attn.o_proj", layer.self_attn.out_proj) # ty:ignore[possibly-missing-attribute] + + with suppress(Exception): + for expert in layer.feed_forward.experts: # ty:ignore[possibly-missing-attribute, not-iterable] + try_add("mlp.down_proj", expert.w2) # ty:ignore[possibly-missing-attribute] + # Granite MoE Hybrid - attention layers with shared_mlp. with suppress(Exception): try_add("mlp.down_proj", layer.shared_mlp.output_linear) # ty:ignore[possibly-missing-attribute] From c62e10d570ca4af2b8c01eb0811e1f994ceaca47 Mon Sep 17 00:00:00 2001 From: Philipp Emanuel Weidmann Date: Thu, 4 Jun 2026 12:17:35 +0530 Subject: [PATCH 10/18] fix: install `kernels` as a Transformers extra Fixes #343 --- pyproject.toml | 3 +-- uv.lock | 29 +++++++++++------------------ 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e8681ba..9359ef0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,6 @@ dependencies = [ "datasets~=4.7", "huggingface-hub~=1.7", "immutabledict~=4.3", - "kernels~=0.13", "langdetect~=1.0", "lm-eval[hf]~=0.4", "numpy~=2.2", @@ -40,7 +39,7 @@ dependencies = [ "rich~=14.3", "tomli-w~=1.2", "tqdm~=4.67", - "transformers~=5.6", + "transformers[kernels]~=5.6", ] [project.optional-dependencies] diff --git a/uv.lock b/uv.lock index f7fbfe9..d988e92 100644 --- a/uv.lock +++ b/uv.lock @@ -8,7 +8,7 @@ resolution-markers = [ ] [options] -exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. +exclude-newer = "2026-05-28T06:40:14.509192809Z" exclude-newer-span = "P7D" [[package]] @@ -939,7 +939,6 @@ dependencies = [ { name = "datasets" }, { name = "huggingface-hub" }, { name = "immutabledict" }, - { name = "kernels" }, { name = "langdetect" }, { name = "lm-eval", extra = ["hf"] }, { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, @@ -953,7 +952,7 @@ dependencies = [ { name = "rich" }, { name = "tomli-w" }, { name = "tqdm" }, - { name = "transformers" }, + { name = "transformers", extra = ["kernels"] }, ] [package.optional-dependencies] @@ -981,7 +980,6 @@ requires-dist = [ { name = "huggingface-hub", specifier = "~=1.7" }, { name = "imageio", marker = "extra == 'research'", specifier = "~=2.37" }, { name = "immutabledict", specifier = "~=4.3" }, - { name = "kernels", specifier = "~=0.13" }, { name = "langdetect", specifier = "~=1.0" }, { name = "lm-eval", extras = ["hf"], specifier = "~=0.4" }, { name = "matplotlib", marker = "extra == 'research'", specifier = "~=3.10" }, @@ -997,7 +995,7 @@ requires-dist = [ { name = "scikit-learn", marker = "extra == 'research'", specifier = "~=1.7" }, { name = "tomli-w", specifier = "~=1.2" }, { name = "tqdm", specifier = "~=4.67" }, - { name = "transformers", specifier = "~=5.6" }, + { name = "transformers", extras = ["kernels"], specifier = "~=5.6" }, ] provides-extras = ["research"] @@ -1154,18 +1152,17 @@ wheels = [ [[package]] name = "kernels" -version = "0.13.0" +version = "0.12.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "huggingface-hub" }, { name = "packaging" }, { name = "pyyaml" }, { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "tomlkit" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/3e/0d/e9c158c527a7b51382fe816a7b7e60caae17ff1153640c1803211a067c99/kernels-0.13.0.tar.gz", hash = "sha256:bf7908206009bff0017d09b87f0f6b5934a1a20520562caf1cbb06cab36418cc", size = 74755, upload-time = "2026-04-10T14:30:45.356Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b3/84/9f68f355f6ce99e977872021fbdbafadcf2820f51d3f7bd697ec3801cb7a/kernels-0.12.3.tar.gz", hash = "sha256:87e29716578e7e71dc5a7578e0132bfdae305bedaeb602698f87c88ca6c60e32", size = 57407, upload-time = "2026-03-20T10:20:42.166Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/45/2cb29e965c199ab01151fee24cbb57b23550c9e6bc897ca242b1e4b8c4bf/kernels-0.13.0-py3-none-any.whl", hash = "sha256:5d857ee4e06dc7496bcd59c4756e84eb71c019b34524dea58ccb0eaaae3bb6df", size = 69177, upload-time = "2026-04-10T14:30:43.551Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3e/778e4a86830e9139df2d16d86c4488fce426ec19daa83cbd2854ef389030/kernels-0.12.3-py3-none-any.whl", hash = "sha256:5d1d33fcb774e03bb7f0688ac24d91ef6b963692f80f0a85ddd2286e69f3cf2f", size = 55501, upload-time = "2026-03-20T10:20:40.643Z" }, ] [[package]] @@ -3663,15 +3660,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" }, ] -[[package]] -name = "tomlkit" -version = "0.14.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c3/af/14b24e41977adb296d6bd1fb59402cf7d60ce364f90c890bd2ec65c43b5a/tomlkit-0.14.0.tar.gz", hash = "sha256:cf00efca415dbd57575befb1f6634c4f42d2d87dbba376128adb42c121b87064", size = 187167, upload-time = "2026-01-13T01:14:53.304Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b5/11/87d6d29fb5d237229d67973a6c9e06e048f01cf4994dee194ab0ea841814/tomlkit-0.14.0-py3-none-any.whl", hash = "sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680", size = 39310, upload-time = "2026-01-13T01:14:51.965Z" }, -] - [[package]] name = "torch" version = "2.9.1" @@ -3766,6 +3754,11 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5d/95/0b0218149b0d6f14df35f5b8f676fa83df4f19ed253c3cc447107ef86eca/transformers-5.6.2-py3-none-any.whl", hash = "sha256:f8d3a1bb96778fed9b8aabfd0dd6e19843e4b0f2bb6b59f32b8a92051b0f348f", size = 10364898, upload-time = "2026-04-23T18:33:26.081Z" }, ] +[package.optional-dependencies] +kernels = [ + { name = "kernels" }, +] + [[package]] name = "triton" version = "3.5.1" From 46b5ced274780b24a865b1153e639e454e652471 Mon Sep 17 00:00:00 2001 From: MoonRide303 <130458190+MoonRide303@users.noreply.github.com> Date: Thu, 4 Jun 2026 14:50:46 +0200 Subject: [PATCH 11/18] feat: add support for gemma-4-12B-it (#350) --- src/heretic/model.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/heretic/model.py b/src/heretic/model.py index 2513091..9afff98 100644 --- a/src/heretic/model.py +++ b/src/heretic/model.py @@ -747,7 +747,7 @@ class Model: _, outputs = self.generate( prompts, max_new_tokens=1, - output_scores=True, + output_logits=True, return_dict_in_generate=True, use_cache=False, ) @@ -756,9 +756,9 @@ class Model: # of model.generate with return_dict_in_generate=True. outputs = cast(GenerateDecoderOnlyOutput, outputs) - # Logits for the first (only) generated token. - # This cast is valid because we passed output_scores=True above. - logits = cast(tuple[FloatTensor], outputs.scores)[0] + # Use raw logits, not processed generation scores; processors can insert + # -inf for suppressed tokens, which can make KL divergence evaluate to NaN. + logits = cast(tuple[FloatTensor], outputs.logits)[0] # The returned tensor has shape (prompt, token). logprobs = F.log_softmax(logits, dim=-1) From 61c59f72271ad41a49755fee49599af401a03fd4 Mon Sep 17 00:00:00 2001 From: zaakir <90780598+zaakirio@users.noreply.github.com> Date: Fri, 5 Jun 2026 15:11:45 +0100 Subject: [PATCH 12/18] feat: save processor for multimodal models (#353) * feat: save processor for multimodal models VL models load via AutoModelForImageTextToText, but only the tokenizer was saved/pushed, dropping the processor's image/audio preprocessing config. Save/push it alongside the tokenizer so multimodal models stay complete. * Update src/heretic/model.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Adjusted processor type to use ProcessorMixin --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- src/heretic/main.py | 8 ++++++++ src/heretic/model.py | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/heretic/main.py b/src/heretic/main.py index 48eece7..baada1e 100644 --- a/src/heretic/main.py +++ b/src/heretic/main.py @@ -813,6 +813,8 @@ def run(): del merged_model empty_cache() model.tokenizer.save_pretrained(save_directory) + if model.processor is not None: + model.processor.save_pretrained(save_directory) reset_trial_model() print(f"Model saved to [bold]{save_directory}[/].") @@ -923,6 +925,12 @@ def run(): private=private, token=token, ) + if model.processor is not None: + model.processor.push_to_hub( + repo_id, + private=private, + token=token, + ) reset_trial_model() if is_hf_path(settings.model): diff --git a/src/heretic/model.py b/src/heretic/model.py index 9afff98..92eb98c 100644 --- a/src/heretic/model.py +++ b/src/heretic/model.py @@ -17,12 +17,14 @@ from torch.nn import Module, ModuleList from transformers import ( AutoModelForCausalLM, AutoModelForImageTextToText, + AutoProcessor, AutoTokenizer, BatchEncoding, BitsAndBytesConfig, PretrainedConfig, PreTrainedModel, PreTrainedTokenizerBase, + ProcessorMixin, TextStreamer, ) from transformers.generation import ( @@ -56,6 +58,8 @@ class AbliterationParameters: class Model: model: PreTrainedModel | PeftModel tokenizer: PreTrainedTokenizerBase + # Set for multimodal models, None for text-only ones. + processor: ProcessorMixin | None peft_config: LoraConfig def __init__(self, settings: Settings): @@ -75,6 +79,15 @@ class Model: **self.revision_kwargs, ) + # Multimodal models have a processor we'll want to save. + self.processor = None + if get_model_class(settings.model) == AutoModelForImageTextToText: + self.processor = AutoProcessor.from_pretrained( + settings.model, + trust_remote_code=settings.trust_remote_code, + **self.revision_kwargs, + ) + # Fallback for tokenizers that don't declare a special pad token. if self.tokenizer.pad_token is None: self.tokenizer.pad_token = self.tokenizer.eos_token From a3dbfd21e6928de91cf1dad32588e111c3d7c4e7 Mon Sep 17 00:00:00 2001 From: UmranPros <152087084+umran666@users.noreply.github.com> Date: Fri, 5 Jun 2026 20:16:26 +0530 Subject: [PATCH 13/18] fix: resolve variable shadowing of error in ValidationError handler (#356) --- src/heretic/main.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/heretic/main.py b/src/heretic/main.py index baada1e..ffe0748 100644 --- a/src/heretic/main.py +++ b/src/heretic/main.py @@ -195,8 +195,10 @@ def run(): except ValidationError as error: print(f"[red]Configuration contains [bold]{error.error_count()}[/] errors:[/]") - for error in error.errors(): - print(f"[bold]{error['loc'][0]}[/]: [yellow]{error['msg']}[/]") + for error_detail in error.errors(): + print( + f"[bold]{error_detail['loc'][0]}[/]: [yellow]{error_detail['msg']}[/]" + ) print() print( From d68a41fb54f1bf55af757c9ec1f699bc12fd3fa2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 6 Jun 2026 18:18:04 +0530 Subject: [PATCH 14/18] build(deps): bump pyarrow from 22.0.0 to 23.0.1 (#358) Bumps [pyarrow](https://github.com/apache/arrow) from 22.0.0 to 23.0.1. - [Release notes](https://github.com/apache/arrow/releases) - [Commits](https://github.com/apache/arrow/compare/apache-arrow-22.0.0...apache-arrow-23.0.1) --- updated-dependencies: - dependency-name: pyarrow dependency-version: 23.0.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- uv.lock | 104 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/uv.lock b/uv.lock index d988e92..f58c0e1 100644 --- a/uv.lock +++ b/uv.lock @@ -8,7 +8,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-05-28T06:40:14.509192809Z" +exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. exclude-newer-span = "P7D" [[package]] @@ -2624,59 +2624,59 @@ wheels = [ [[package]] name = "pyarrow" -version = "22.0.0" +version = "23.0.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/53/04a7fdc63e6056116c9ddc8b43bc28c12cdd181b85cbeadb79278475f3ae/pyarrow-22.0.0.tar.gz", hash = "sha256:3d600dc583260d845c7d8a6db540339dd883081925da2bd1c5cb808f720b3cd9", size = 1151151, upload-time = "2025-10-24T12:30:00.762Z" } +sdist = { url = "https://files.pythonhosted.org/packages/88/22/134986a4cc224d593c1afde5494d18ff629393d74cc2eddb176669f234a4/pyarrow-23.0.1.tar.gz", hash = "sha256:b8c5873e33440b2bc2f4a79d2b47017a89c5a24116c055625e6f2ee50523f019", size = 1167336, upload-time = "2026-02-16T10:14:12.39Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d9/9b/cb3f7e0a345353def531ca879053e9ef6b9f38ed91aebcf68b09ba54dec0/pyarrow-22.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:77718810bd3066158db1e95a63c160ad7ce08c6b0710bc656055033e39cdad88", size = 34223968, upload-time = "2025-10-24T10:03:31.21Z" }, - { url = "https://files.pythonhosted.org/packages/6c/41/3184b8192a120306270c5307f105b70320fdaa592c99843c5ef78aaefdcf/pyarrow-22.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:44d2d26cda26d18f7af7db71453b7b783788322d756e81730acb98f24eb90ace", size = 35942085, upload-time = "2025-10-24T10:03:38.146Z" }, - { url = "https://files.pythonhosted.org/packages/d9/3d/a1eab2f6f08001f9fb714b8ed5cfb045e2fe3e3e3c0c221f2c9ed1e6d67d/pyarrow-22.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:b9d71701ce97c95480fecb0039ec5bb889e75f110da72005743451339262f4ce", size = 44964613, upload-time = "2025-10-24T10:03:46.516Z" }, - { url = "https://files.pythonhosted.org/packages/46/46/a1d9c24baf21cfd9ce994ac820a24608decf2710521b29223d4334985127/pyarrow-22.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:710624ab925dc2b05a6229d47f6f0dac1c1155e6ed559be7109f684eba048a48", size = 47627059, upload-time = "2025-10-24T10:03:55.353Z" }, - { url = "https://files.pythonhosted.org/packages/3a/4c/f711acb13075c1391fd54bc17e078587672c575f8de2a6e62509af026dcf/pyarrow-22.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f963ba8c3b0199f9d6b794c90ec77545e05eadc83973897a4523c9e8d84e9340", size = 47947043, upload-time = "2025-10-24T10:04:05.408Z" }, - { url = "https://files.pythonhosted.org/packages/4e/70/1f3180dd7c2eab35c2aca2b29ace6c519f827dcd4cfeb8e0dca41612cf7a/pyarrow-22.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd0d42297ace400d8febe55f13fdf46e86754842b860c978dfec16f081e5c653", size = 50206505, upload-time = "2025-10-24T10:04:15.786Z" }, - { url = "https://files.pythonhosted.org/packages/80/07/fea6578112c8c60ffde55883a571e4c4c6bc7049f119d6b09333b5cc6f73/pyarrow-22.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:00626d9dc0f5ef3a75fe63fd68b9c7c8302d2b5bbc7f74ecaedba83447a24f84", size = 28101641, upload-time = "2025-10-24T10:04:22.57Z" }, - { url = "https://files.pythonhosted.org/packages/2e/b7/18f611a8cdc43417f9394a3ccd3eace2f32183c08b9eddc3d17681819f37/pyarrow-22.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:3e294c5eadfb93d78b0763e859a0c16d4051fc1c5231ae8956d61cb0b5666f5a", size = 34272022, upload-time = "2025-10-24T10:04:28.973Z" }, - { url = "https://files.pythonhosted.org/packages/26/5c/f259e2526c67eb4b9e511741b19870a02363a47a35edbebc55c3178db22d/pyarrow-22.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:69763ab2445f632d90b504a815a2a033f74332997052b721002298ed6de40f2e", size = 35995834, upload-time = "2025-10-24T10:04:35.467Z" }, - { url = "https://files.pythonhosted.org/packages/50/8d/281f0f9b9376d4b7f146913b26fac0aa2829cd1ee7e997f53a27411bbb92/pyarrow-22.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:b41f37cabfe2463232684de44bad753d6be08a7a072f6a83447eeaf0e4d2a215", size = 45030348, upload-time = "2025-10-24T10:04:43.366Z" }, - { url = "https://files.pythonhosted.org/packages/f5/e5/53c0a1c428f0976bf22f513d79c73000926cb00b9c138d8e02daf2102e18/pyarrow-22.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:35ad0f0378c9359b3f297299c3309778bb03b8612f987399a0333a560b43862d", size = 47699480, upload-time = "2025-10-24T10:04:51.486Z" }, - { url = "https://files.pythonhosted.org/packages/95/e1/9dbe4c465c3365959d183e6345d0a8d1dc5b02ca3f8db4760b3bc834cf25/pyarrow-22.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8382ad21458075c2e66a82a29d650f963ce51c7708c7c0ff313a8c206c4fd5e8", size = 48011148, upload-time = "2025-10-24T10:04:59.585Z" }, - { url = "https://files.pythonhosted.org/packages/c5/b4/7caf5d21930061444c3cf4fa7535c82faf5263e22ce43af7c2759ceb5b8b/pyarrow-22.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1a812a5b727bc09c3d7ea072c4eebf657c2f7066155506ba31ebf4792f88f016", size = 50276964, upload-time = "2025-10-24T10:05:08.175Z" }, - { url = "https://files.pythonhosted.org/packages/ae/f3/cec89bd99fa3abf826f14d4e53d3d11340ce6f6af4d14bdcd54cd83b6576/pyarrow-22.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:ec5d40dd494882704fb876c16fa7261a69791e784ae34e6b5992e977bd2e238c", size = 28106517, upload-time = "2025-10-24T10:05:14.314Z" }, - { url = "https://files.pythonhosted.org/packages/af/63/ba23862d69652f85b615ca14ad14f3bcfc5bf1b99ef3f0cd04ff93fdad5a/pyarrow-22.0.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:bea79263d55c24a32b0d79c00a1c58bb2ee5f0757ed95656b01c0fb310c5af3d", size = 34211578, upload-time = "2025-10-24T10:05:21.583Z" }, - { url = "https://files.pythonhosted.org/packages/b1/d0/f9ad86fe809efd2bcc8be32032fa72e8b0d112b01ae56a053006376c5930/pyarrow-22.0.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:12fe549c9b10ac98c91cf791d2945e878875d95508e1a5d14091a7aaa66d9cf8", size = 35989906, upload-time = "2025-10-24T10:05:29.485Z" }, - { url = "https://files.pythonhosted.org/packages/b4/a8/f910afcb14630e64d673f15904ec27dd31f1e009b77033c365c84e8c1e1d/pyarrow-22.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:334f900ff08ce0423407af97e6c26ad5d4e3b0763645559ece6fbf3747d6a8f5", size = 45021677, upload-time = "2025-10-24T10:05:38.274Z" }, - { url = "https://files.pythonhosted.org/packages/13/95/aec81f781c75cd10554dc17a25849c720d54feafb6f7847690478dcf5ef8/pyarrow-22.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:c6c791b09c57ed76a18b03f2631753a4960eefbbca80f846da8baefc6491fcfe", size = 47726315, upload-time = "2025-10-24T10:05:47.314Z" }, - { url = "https://files.pythonhosted.org/packages/bb/d4/74ac9f7a54cfde12ee42734ea25d5a3c9a45db78f9def949307a92720d37/pyarrow-22.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c3200cb41cdbc65156e5f8c908d739b0dfed57e890329413da2748d1a2cd1a4e", size = 47990906, upload-time = "2025-10-24T10:05:58.254Z" }, - { url = "https://files.pythonhosted.org/packages/2e/71/fedf2499bf7a95062eafc989ace56572f3343432570e1c54e6599d5b88da/pyarrow-22.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ac93252226cf288753d8b46280f4edf3433bf9508b6977f8dd8526b521a1bbb9", size = 50306783, upload-time = "2025-10-24T10:06:08.08Z" }, - { url = "https://files.pythonhosted.org/packages/68/ed/b202abd5a5b78f519722f3d29063dda03c114711093c1995a33b8e2e0f4b/pyarrow-22.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:44729980b6c50a5f2bfcc2668d36c569ce17f8b17bccaf470c4313dcbbf13c9d", size = 27972883, upload-time = "2025-10-24T10:06:14.204Z" }, - { url = "https://files.pythonhosted.org/packages/a6/d6/d0fac16a2963002fc22c8fa75180a838737203d558f0ed3b564c4a54eef5/pyarrow-22.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e6e95176209257803a8b3d0394f21604e796dadb643d2f7ca21b66c9c0b30c9a", size = 34204629, upload-time = "2025-10-24T10:06:20.274Z" }, - { url = "https://files.pythonhosted.org/packages/c6/9c/1d6357347fbae062ad3f17082f9ebc29cc733321e892c0d2085f42a2212b/pyarrow-22.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:001ea83a58024818826a9e3f89bf9310a114f7e26dfe404a4c32686f97bd7901", size = 35985783, upload-time = "2025-10-24T10:06:27.301Z" }, - { url = "https://files.pythonhosted.org/packages/ff/c0/782344c2ce58afbea010150df07e3a2f5fdad299cd631697ae7bd3bac6e3/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:ce20fe000754f477c8a9125543f1936ea5b8867c5406757c224d745ed033e691", size = 45020999, upload-time = "2025-10-24T10:06:35.387Z" }, - { url = "https://files.pythonhosted.org/packages/1b/8b/5362443737a5307a7b67c1017c42cd104213189b4970bf607e05faf9c525/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e0a15757fccb38c410947df156f9749ae4a3c89b2393741a50521f39a8cf202a", size = 47724601, upload-time = "2025-10-24T10:06:43.551Z" }, - { url = "https://files.pythonhosted.org/packages/69/4d/76e567a4fc2e190ee6072967cb4672b7d9249ac59ae65af2d7e3047afa3b/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cedb9dd9358e4ea1d9bce3665ce0797f6adf97ff142c8e25b46ba9cdd508e9b6", size = 48001050, upload-time = "2025-10-24T10:06:52.284Z" }, - { url = "https://files.pythonhosted.org/packages/01/5e/5653f0535d2a1aef8223cee9d92944cb6bccfee5cf1cd3f462d7cb022790/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:252be4a05f9d9185bb8c18e83764ebcfea7185076c07a7a662253af3a8c07941", size = 50307877, upload-time = "2025-10-24T10:07:02.405Z" }, - { url = "https://files.pythonhosted.org/packages/2d/f8/1d0bd75bf9328a3b826e24a16e5517cd7f9fbf8d34a3184a4566ef5a7f29/pyarrow-22.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:a4893d31e5ef780b6edcaf63122df0f8d321088bb0dee4c8c06eccb1ca28d145", size = 27977099, upload-time = "2025-10-24T10:08:07.259Z" }, - { url = "https://files.pythonhosted.org/packages/90/81/db56870c997805bf2b0f6eeeb2d68458bf4654652dccdcf1bf7a42d80903/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:f7fe3dbe871294ba70d789be16b6e7e52b418311e166e0e3cba9522f0f437fb1", size = 34336685, upload-time = "2025-10-24T10:07:11.47Z" }, - { url = "https://files.pythonhosted.org/packages/1c/98/0727947f199aba8a120f47dfc229eeb05df15bcd7a6f1b669e9f882afc58/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:ba95112d15fd4f1105fb2402c4eab9068f0554435e9b7085924bcfaac2cc306f", size = 36032158, upload-time = "2025-10-24T10:07:18.626Z" }, - { url = "https://files.pythonhosted.org/packages/96/b4/9babdef9c01720a0785945c7cf550e4acd0ebcd7bdd2e6f0aa7981fa85e2/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:c064e28361c05d72eed8e744c9605cbd6d2bb7481a511c74071fd9b24bc65d7d", size = 44892060, upload-time = "2025-10-24T10:07:26.002Z" }, - { url = "https://files.pythonhosted.org/packages/f8/ca/2f8804edd6279f78a37062d813de3f16f29183874447ef6d1aadbb4efa0f/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:6f9762274496c244d951c819348afbcf212714902742225f649cf02823a6a10f", size = 47504395, upload-time = "2025-10-24T10:07:34.09Z" }, - { url = "https://files.pythonhosted.org/packages/b9/f0/77aa5198fd3943682b2e4faaf179a674f0edea0d55d326d83cb2277d9363/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a9d9ffdc2ab696f6b15b4d1f7cec6658e1d788124418cb30030afbae31c64746", size = 48066216, upload-time = "2025-10-24T10:07:43.528Z" }, - { url = "https://files.pythonhosted.org/packages/79/87/a1937b6e78b2aff18b706d738c9e46ade5bfcf11b294e39c87706a0089ac/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ec1a15968a9d80da01e1d30349b2b0d7cc91e96588ee324ce1b5228175043e95", size = 50288552, upload-time = "2025-10-24T10:07:53.519Z" }, - { url = "https://files.pythonhosted.org/packages/60/ae/b5a5811e11f25788ccfdaa8f26b6791c9807119dffcf80514505527c384c/pyarrow-22.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:bba208d9c7decf9961998edf5c65e3ea4355d5818dd6cd0f6809bec1afb951cc", size = 28262504, upload-time = "2025-10-24T10:08:00.932Z" }, - { url = "https://files.pythonhosted.org/packages/bd/b0/0fa4d28a8edb42b0a7144edd20befd04173ac79819547216f8a9f36f9e50/pyarrow-22.0.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:9bddc2cade6561f6820d4cd73f99a0243532ad506bc510a75a5a65a522b2d74d", size = 34224062, upload-time = "2025-10-24T10:08:14.101Z" }, - { url = "https://files.pythonhosted.org/packages/0f/a8/7a719076b3c1be0acef56a07220c586f25cd24de0e3f3102b438d18ae5df/pyarrow-22.0.0-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:e70ff90c64419709d38c8932ea9fe1cc98415c4f87ea8da81719e43f02534bc9", size = 35990057, upload-time = "2025-10-24T10:08:21.842Z" }, - { url = "https://files.pythonhosted.org/packages/89/3c/359ed54c93b47fb6fe30ed16cdf50e3f0e8b9ccfb11b86218c3619ae50a8/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:92843c305330aa94a36e706c16209cd4df274693e777ca47112617db7d0ef3d7", size = 45068002, upload-time = "2025-10-24T10:08:29.034Z" }, - { url = "https://files.pythonhosted.org/packages/55/fc/4945896cc8638536ee787a3bd6ce7cec8ec9acf452d78ec39ab328efa0a1/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:6dda1ddac033d27421c20d7a7943eec60be44e0db4e079f33cc5af3b8280ccde", size = 47737765, upload-time = "2025-10-24T10:08:38.559Z" }, - { url = "https://files.pythonhosted.org/packages/cd/5e/7cb7edeb2abfaa1f79b5d5eb89432356155c8426f75d3753cbcb9592c0fd/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:84378110dd9a6c06323b41b56e129c504d157d1a983ce8f5443761eb5256bafc", size = 48048139, upload-time = "2025-10-24T10:08:46.784Z" }, - { url = "https://files.pythonhosted.org/packages/88/c6/546baa7c48185f5e9d6e59277c4b19f30f48c94d9dd938c2a80d4d6b067c/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:854794239111d2b88b40b6ef92aa478024d1e5074f364033e73e21e3f76b25e0", size = 50314244, upload-time = "2025-10-24T10:08:55.771Z" }, - { url = "https://files.pythonhosted.org/packages/3c/79/755ff2d145aafec8d347bf18f95e4e81c00127f06d080135dfc86aea417c/pyarrow-22.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:b883fe6fd85adad7932b3271c38ac289c65b7337c2c132e9569f9d3940620730", size = 28757501, upload-time = "2025-10-24T10:09:59.891Z" }, - { url = "https://files.pythonhosted.org/packages/0e/d2/237d75ac28ced3147912954e3c1a174df43a95f4f88e467809118a8165e0/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:7a820d8ae11facf32585507c11f04e3f38343c1e784c9b5a8b1da5c930547fe2", size = 34355506, upload-time = "2025-10-24T10:09:02.953Z" }, - { url = "https://files.pythonhosted.org/packages/1e/2c/733dfffe6d3069740f98e57ff81007809067d68626c5faef293434d11bd6/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:c6ec3675d98915bf1ec8b3c7986422682f7232ea76cad276f4c8abd5b7319b70", size = 36047312, upload-time = "2025-10-24T10:09:10.334Z" }, - { url = "https://files.pythonhosted.org/packages/7c/2b/29d6e3782dc1f299727462c1543af357a0f2c1d3c160ce199950d9ca51eb/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:3e739edd001b04f654b166204fc7a9de896cf6007eaff33409ee9e50ceaff754", size = 45081609, upload-time = "2025-10-24T10:09:18.61Z" }, - { url = "https://files.pythonhosted.org/packages/8d/42/aa9355ecc05997915af1b7b947a7f66c02dcaa927f3203b87871c114ba10/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:7388ac685cab5b279a41dfe0a6ccd99e4dbf322edfb63e02fc0443bf24134e91", size = 47703663, upload-time = "2025-10-24T10:09:27.369Z" }, - { url = "https://files.pythonhosted.org/packages/ee/62/45abedde480168e83a1de005b7b7043fd553321c1e8c5a9a114425f64842/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f633074f36dbc33d5c05b5dc75371e5660f1dbf9c8b1d95669def05e5425989c", size = 48066543, upload-time = "2025-10-24T10:09:34.908Z" }, - { url = "https://files.pythonhosted.org/packages/84/e9/7878940a5b072e4f3bf998770acafeae13b267f9893af5f6d4ab3904b67e/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4c19236ae2402a8663a2c8f21f1870a03cc57f0bef7e4b6eb3238cc82944de80", size = 50288838, upload-time = "2025-10-24T10:09:44.394Z" }, - { url = "https://files.pythonhosted.org/packages/7b/03/f335d6c52b4a4761bcc83499789a1e2e16d9d201a58c327a9b5cc9a41bd9/pyarrow-22.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0c34fe18094686194f204a3b1787a27456897d8a2d62caf84b61e8dfbc0252ae", size = 29185594, upload-time = "2025-10-24T10:09:53.111Z" }, + { url = "https://files.pythonhosted.org/packages/bc/a8/24e5dc6855f50a62936ceb004e6e9645e4219a8065f304145d7fb8a79d5d/pyarrow-23.0.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:3fab8f82571844eb3c460f90a75583801d14ca0cc32b1acc8c361650e006fd56", size = 34307390, upload-time = "2026-02-16T10:08:08.654Z" }, + { url = "https://files.pythonhosted.org/packages/bc/8e/4be5617b4aaae0287f621ad31c6036e5f63118cfca0dc57d42121ff49b51/pyarrow-23.0.1-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:3f91c038b95f71ddfc865f11d5876c42f343b4495535bd262c7b321b0b94507c", size = 35853761, upload-time = "2026-02-16T10:08:17.811Z" }, + { url = "https://files.pythonhosted.org/packages/2e/08/3e56a18819462210432ae37d10f5c8eed3828be1d6c751b6e6a2e93c286a/pyarrow-23.0.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:d0744403adabef53c985a7f8a082b502a368510c40d184df349a0a8754533258", size = 44493116, upload-time = "2026-02-16T10:08:25.792Z" }, + { url = "https://files.pythonhosted.org/packages/f8/82/c40b68001dbec8a3faa4c08cd8c200798ac732d2854537c5449dc859f55a/pyarrow-23.0.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:c33b5bf406284fd0bba436ed6f6c3ebe8e311722b441d89397c54f871c6863a2", size = 47564532, upload-time = "2026-02-16T10:08:34.27Z" }, + { url = "https://files.pythonhosted.org/packages/20/bc/73f611989116b6f53347581b02177f9f620efdf3cd3f405d0e83cdf53a83/pyarrow-23.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ddf743e82f69dcd6dbbcb63628895d7161e04e56794ef80550ac6f3315eeb1d5", size = 48183685, upload-time = "2026-02-16T10:08:42.889Z" }, + { url = "https://files.pythonhosted.org/packages/b0/cc/6c6b3ecdae2a8c3aced99956187e8302fc954cc2cca2a37cf2111dad16ce/pyarrow-23.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e052a211c5ac9848ae15d5ec875ed0943c0221e2fcfe69eee80b604b4e703222", size = 50605582, upload-time = "2026-02-16T10:08:51.641Z" }, + { url = "https://files.pythonhosted.org/packages/8d/94/d359e708672878d7638a04a0448edf7c707f9e5606cee11e15aaa5c7535a/pyarrow-23.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:5abde149bb3ce524782d838eb67ac095cd3fd6090eba051130589793f1a7f76d", size = 27521148, upload-time = "2026-02-16T10:08:58.077Z" }, + { url = "https://files.pythonhosted.org/packages/b0/41/8e6b6ef7e225d4ceead8459427a52afdc23379768f54dd3566014d7618c1/pyarrow-23.0.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:6f0147ee9e0386f519c952cc670eb4a8b05caa594eeffe01af0e25f699e4e9bb", size = 34302230, upload-time = "2026-02-16T10:09:03.859Z" }, + { url = "https://files.pythonhosted.org/packages/bf/4a/1472c00392f521fea03ae93408bf445cc7bfa1ab81683faf9bc188e36629/pyarrow-23.0.1-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:0ae6e17c828455b6265d590100c295193f93cc5675eb0af59e49dbd00d2de350", size = 35850050, upload-time = "2026-02-16T10:09:11.877Z" }, + { url = "https://files.pythonhosted.org/packages/0c/b2/bd1f2f05ded56af7f54d702c8364c9c43cd6abb91b0e9933f3d77b4f4132/pyarrow-23.0.1-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:fed7020203e9ef273360b9e45be52a2a47d3103caf156a30ace5247ffb51bdbd", size = 44491918, upload-time = "2026-02-16T10:09:18.144Z" }, + { url = "https://files.pythonhosted.org/packages/0b/62/96459ef5b67957eac38a90f541d1c28833d1b367f014a482cb63f3b7cd2d/pyarrow-23.0.1-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:26d50dee49d741ac0e82185033488d28d35be4d763ae6f321f97d1140eb7a0e9", size = 47562811, upload-time = "2026-02-16T10:09:25.792Z" }, + { url = "https://files.pythonhosted.org/packages/7d/94/1170e235add1f5f45a954e26cd0e906e7e74e23392dcb560de471f7366ec/pyarrow-23.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3c30143b17161310f151f4a2bcfe41b5ff744238c1039338779424e38579d701", size = 48183766, upload-time = "2026-02-16T10:09:34.645Z" }, + { url = "https://files.pythonhosted.org/packages/0e/2d/39a42af4570377b99774cdb47f63ee6c7da7616bd55b3d5001aa18edfe4f/pyarrow-23.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db2190fa79c80a23fdd29fef4b8992893f024ae7c17d2f5f4db7171fa30c2c78", size = 50607669, upload-time = "2026-02-16T10:09:44.153Z" }, + { url = "https://files.pythonhosted.org/packages/00/ca/db94101c187f3df742133ac837e93b1f269ebdac49427f8310ee40b6a58f/pyarrow-23.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:f00f993a8179e0e1c9713bcc0baf6d6c01326a406a9c23495ec1ba9c9ebf2919", size = 27527698, upload-time = "2026-02-16T10:09:50.263Z" }, + { url = "https://files.pythonhosted.org/packages/9a/4b/4166bb5abbfe6f750fc60ad337c43ecf61340fa52ab386da6e8dbf9e63c4/pyarrow-23.0.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:f4b0dbfa124c0bb161f8b5ebb40f1a680b70279aa0c9901d44a2b5a20806039f", size = 34214575, upload-time = "2026-02-16T10:09:56.225Z" }, + { url = "https://files.pythonhosted.org/packages/e1/da/3f941e3734ac8088ea588b53e860baeddac8323ea40ce22e3d0baa865cc9/pyarrow-23.0.1-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:7707d2b6673f7de054e2e83d59f9e805939038eebe1763fe811ee8fa5c0cd1a7", size = 35832540, upload-time = "2026-02-16T10:10:03.428Z" }, + { url = "https://files.pythonhosted.org/packages/88/7c/3d841c366620e906d54430817531b877ba646310296df42ef697308c2705/pyarrow-23.0.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:86ff03fb9f1a320266e0de855dee4b17da6794c595d207f89bba40d16b5c78b9", size = 44470940, upload-time = "2026-02-16T10:10:10.704Z" }, + { url = "https://files.pythonhosted.org/packages/2c/a5/da83046273d990f256cb79796a190bbf7ec999269705ddc609403f8c6b06/pyarrow-23.0.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:813d99f31275919c383aab17f0f455a04f5a429c261cc411b1e9a8f5e4aaaa05", size = 47586063, upload-time = "2026-02-16T10:10:17.95Z" }, + { url = "https://files.pythonhosted.org/packages/5b/3c/b7d2ebcff47a514f47f9da1e74b7949138c58cfeb108cdd4ee62f43f0cf3/pyarrow-23.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:bf5842f960cddd2ef757d486041d57c96483efc295a8c4a0e20e704cbbf39c67", size = 48173045, upload-time = "2026-02-16T10:10:25.363Z" }, + { url = "https://files.pythonhosted.org/packages/43/b2/b40961262213beaba6acfc88698eb773dfce32ecdf34d19291db94c2bd73/pyarrow-23.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:564baf97c858ecc03ec01a41062e8f4698abc3e6e2acd79c01c2e97880a19730", size = 50621741, upload-time = "2026-02-16T10:10:33.477Z" }, + { url = "https://files.pythonhosted.org/packages/f6/70/1fdda42d65b28b078e93d75d371b2185a61da89dda4def8ba6ba41ebdeb4/pyarrow-23.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:07deae7783782ac7250989a7b2ecde9b3c343a643f82e8a4df03d93b633006f0", size = 27620678, upload-time = "2026-02-16T10:10:39.31Z" }, + { url = "https://files.pythonhosted.org/packages/47/10/2cbe4c6f0fb83d2de37249567373d64327a5e4d8db72f486db42875b08f6/pyarrow-23.0.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:6b8fda694640b00e8af3c824f99f789e836720aa8c9379fb435d4c4953a756b8", size = 34210066, upload-time = "2026-02-16T10:10:45.487Z" }, + { url = "https://files.pythonhosted.org/packages/cb/4f/679fa7e84dadbaca7a65f7cdba8d6c83febbd93ca12fa4adf40ba3b6362b/pyarrow-23.0.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:8ff51b1addc469b9444b7c6f3548e19dc931b172ab234e995a60aea9f6e6025f", size = 35825526, upload-time = "2026-02-16T10:10:52.266Z" }, + { url = "https://files.pythonhosted.org/packages/f9/63/d2747d930882c9d661e9398eefc54f15696547b8983aaaf11d4a2e8b5426/pyarrow-23.0.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:71c5be5cbf1e1cb6169d2a0980850bccb558ddc9b747b6206435313c47c37677", size = 44473279, upload-time = "2026-02-16T10:11:01.557Z" }, + { url = "https://files.pythonhosted.org/packages/b3/93/10a48b5e238de6d562a411af6467e71e7aedbc9b87f8d3a35f1560ae30fb/pyarrow-23.0.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:9b6f4f17b43bc39d56fec96e53fe89d94bac3eb134137964371b45352d40d0c2", size = 47585798, upload-time = "2026-02-16T10:11:09.401Z" }, + { url = "https://files.pythonhosted.org/packages/5c/20/476943001c54ef078dbf9542280e22741219a184a0632862bca4feccd666/pyarrow-23.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fc13fc6c403d1337acab46a2c4346ca6c9dec5780c3c697cf8abfd5e19b6b37", size = 48179446, upload-time = "2026-02-16T10:11:17.781Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b6/5dd0c47b335fcd8edba9bfab78ad961bd0fd55ebe53468cc393f45e0be60/pyarrow-23.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c16ed4f53247fa3ffb12a14d236de4213a4415d127fe9cebed33d51671113e2", size = 50623972, upload-time = "2026-02-16T10:11:26.185Z" }, + { url = "https://files.pythonhosted.org/packages/d5/09/a532297c9591a727d67760e2e756b83905dd89adb365a7f6e9c72578bcc1/pyarrow-23.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:cecfb12ef629cf6be0b1887f9f86463b0dd3dc3195ae6224e74006be4736035a", size = 27540749, upload-time = "2026-02-16T10:12:23.297Z" }, + { url = "https://files.pythonhosted.org/packages/a5/8e/38749c4b1303e6ae76b3c80618f84861ae0c55dd3c2273842ea6f8258233/pyarrow-23.0.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:29f7f7419a0e30264ea261fdc0e5fe63ce5a6095003db2945d7cd78df391a7e1", size = 34471544, upload-time = "2026-02-16T10:11:32.535Z" }, + { url = "https://files.pythonhosted.org/packages/a3/73/f237b2bc8c669212f842bcfd842b04fc8d936bfc9d471630569132dc920d/pyarrow-23.0.1-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:33d648dc25b51fd8055c19e4261e813dfc4d2427f068bcecc8b53d01b81b0500", size = 35949911, upload-time = "2026-02-16T10:11:39.813Z" }, + { url = "https://files.pythonhosted.org/packages/0c/86/b912195eee0903b5611bf596833def7d146ab2d301afeb4b722c57ffc966/pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:cd395abf8f91c673dd3589cadc8cc1ee4e8674fa61b2e923c8dd215d9c7d1f41", size = 44520337, upload-time = "2026-02-16T10:11:47.764Z" }, + { url = "https://files.pythonhosted.org/packages/69/c2/f2a717fb824f62d0be952ea724b4f6f9372a17eed6f704b5c9526f12f2f1/pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:00be9576d970c31defb5c32eb72ef585bf600ef6d0a82d5eccaae96639cf9d07", size = 47548944, upload-time = "2026-02-16T10:11:56.607Z" }, + { url = "https://files.pythonhosted.org/packages/84/a7/90007d476b9f0dc308e3bc57b832d004f848fd6c0da601375d20d92d1519/pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c2139549494445609f35a5cda4eb94e2c9e4d704ce60a095b342f82460c73a83", size = 48236269, upload-time = "2026-02-16T10:12:04.47Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3f/b16fab3e77709856eb6ac328ce35f57a6d4a18462c7ca5186ef31b45e0e0/pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7044b442f184d84e2351e5084600f0d7343d6117aabcbc1ac78eb1ae11eb4125", size = 50604794, upload-time = "2026-02-16T10:12:11.797Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a1/22df0620a9fac31d68397a75465c344e83c3dfe521f7612aea33e27ab6c0/pyarrow-23.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a35581e856a2fafa12f3f54fce4331862b1cfb0bef5758347a858a4aa9d6bae8", size = 27660642, upload-time = "2026-02-16T10:12:17.746Z" }, + { url = "https://files.pythonhosted.org/packages/8d/1b/6da9a89583ce7b23ac611f183ae4843cd3a6cf54f079549b0e8c14031e73/pyarrow-23.0.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:5df1161da23636a70838099d4aaa65142777185cc0cdba4037a18cee7d8db9ca", size = 34238755, upload-time = "2026-02-16T10:12:32.819Z" }, + { url = "https://files.pythonhosted.org/packages/ae/b5/d58a241fbe324dbaeb8df07be6af8752c846192d78d2272e551098f74e88/pyarrow-23.0.1-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:fa8e51cb04b9f8c9c5ace6bab63af9a1f88d35c0d6cbf53e8c17c098552285e1", size = 35847826, upload-time = "2026-02-16T10:12:38.949Z" }, + { url = "https://files.pythonhosted.org/packages/54/a5/8cbc83f04aba433ca7b331b38f39e000efd9f0c7ce47128670e737542996/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:0b95a3994f015be13c63148fef8832e8a23938128c185ee951c98908a696e0eb", size = 44536859, upload-time = "2026-02-16T10:12:45.467Z" }, + { url = "https://files.pythonhosted.org/packages/36/2e/c0f017c405fcdc252dbccafbe05e36b0d0eb1ea9a958f081e01c6972927f/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:4982d71350b1a6e5cfe1af742c53dfb759b11ce14141870d05d9e540d13bc5d1", size = 47614443, upload-time = "2026-02-16T10:12:55.525Z" }, + { url = "https://files.pythonhosted.org/packages/af/6b/2314a78057912f5627afa13ba43809d9d653e6630859618b0fd81a4e0759/pyarrow-23.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c250248f1fe266db627921c89b47b7c06fee0489ad95b04d50353537d74d6886", size = 48232991, upload-time = "2026-02-16T10:13:04.729Z" }, + { url = "https://files.pythonhosted.org/packages/40/f2/1bcb1d3be3460832ef3370d621142216e15a2c7c62602a4ea19ec240dd64/pyarrow-23.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5f4763b83c11c16e5f4c15601ba6dfa849e20723b46aa2617cb4bffe8768479f", size = 50645077, upload-time = "2026-02-16T10:13:14.147Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3f/b1da7b61cd66566a4d4c8383d376c606d1c34a906c3f1cb35c479f59d1aa/pyarrow-23.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:3a4c85ef66c134161987c17b147d6bffdca4566f9a4c1d81a0a01cdf08414ea5", size = 28234271, upload-time = "2026-02-16T10:14:09.397Z" }, + { url = "https://files.pythonhosted.org/packages/b5/78/07f67434e910a0f7323269be7bfbf58699bd0c1d080b18a1ab49ba943fe8/pyarrow-23.0.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:17cd28e906c18af486a499422740298c52d7c6795344ea5002a7720b4eadf16d", size = 34488692, upload-time = "2026-02-16T10:13:21.541Z" }, + { url = "https://files.pythonhosted.org/packages/50/76/34cf7ae93ece1f740a04910d9f7e80ba166b9b4ab9596a953e9e62b90fe1/pyarrow-23.0.1-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:76e823d0e86b4fb5e1cf4a58d293036e678b5a4b03539be933d3b31f9406859f", size = 35964383, upload-time = "2026-02-16T10:13:28.63Z" }, + { url = "https://files.pythonhosted.org/packages/46/90/459b827238936d4244214be7c684e1b366a63f8c78c380807ae25ed92199/pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:a62e1899e3078bf65943078b3ad2a6ddcacf2373bc06379aac61b1e548a75814", size = 44538119, upload-time = "2026-02-16T10:13:35.506Z" }, + { url = "https://files.pythonhosted.org/packages/28/a1/93a71ae5881e99d1f9de1d4554a87be37da11cd6b152239fb5bd924fdc64/pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:df088e8f640c9fae3b1f495b3c64755c4e719091caf250f3a74d095ddf3c836d", size = 47571199, upload-time = "2026-02-16T10:13:42.504Z" }, + { url = "https://files.pythonhosted.org/packages/88/a3/d2c462d4ef313521eaf2eff04d204ac60775263f1fb08c374b543f79f610/pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:46718a220d64677c93bc243af1d44b55998255427588e400677d7192671845c7", size = 48259435, upload-time = "2026-02-16T10:13:49.226Z" }, + { url = "https://files.pythonhosted.org/packages/cc/f1/11a544b8c3d38a759eb3fbb022039117fd633e9a7b19e4841cc3da091915/pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a09f3876e87f48bc2f13583ab551f0379e5dfb83210391e68ace404181a20690", size = 50629149, upload-time = "2026-02-16T10:13:57.238Z" }, + { url = "https://files.pythonhosted.org/packages/50/f2/c0e76a0b451ffdf0cf788932e182758eb7558953f4f27f1aff8e2518b653/pyarrow-23.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:527e8d899f14bd15b740cd5a54ad56b7f98044955373a17179d5956ddb93d9ce", size = 28365807, upload-time = "2026-02-16T10:14:03.892Z" }, ] [[package]] From c9ce36dddedbdd12238c3c49fecdb5552a94f725 Mon Sep 17 00:00:00 2001 From: Vinay-Umrethe Date: Sun, 7 Jun 2026 08:33:40 +0530 Subject: [PATCH 15/18] style: remove annoying gray bg from logo (#359) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 708927d..2c4bf55 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Logo +Logo # Heretic: Fully automatic censorship removal for language models

[![Discord](https://img.shields.io/discord/1447831134212984903?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=for-the-badge)](https://discord.gg/gdXc48gSyT) [![Follow us on Hugging Face](https://huggingface.co/datasets/huggingface/badges/resolve/main/follow-us-on-hf-md-dark.svg)](https://huggingface.co/heretic-org) [![Codeberg mirror](https://img.shields.io/badge/Codeberg%20mirror-black?logo=codeberg&style=for-the-badge)](https://codeberg.org/p-e-w/heretic) From 1a9d01c00283a4b26281e56999c38c3cbe2da49c Mon Sep 17 00:00:00 2001 From: UmranPros <152087084+umran666@users.noreply.github.com> Date: Sun, 7 Jun 2026 09:15:14 +0530 Subject: [PATCH 16/18] fix: count all trials, not just completed trials (#357) --- src/heretic/main.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/heretic/main.py b/src/heretic/main.py index ffe0748..b99b1ac 100644 --- a/src/heretic/main.py +++ b/src/heretic/main.py @@ -615,11 +615,7 @@ def run(): study.set_user_attr("settings", settings.model_dump_json()) study.set_user_attr("finished", False) - def count_completed_trials() -> int: - # Count number of complete trials to compute trials to run. - return sum([(1 if t.state == TrialState.COMPLETE else 0) for t in study.trials]) - - start_index = trial_index = count_completed_trials() + start_index = trial_index = len(study.trials) if start_index > 0: print() print("Resuming existing study.") @@ -627,7 +623,7 @@ def run(): try: study.optimize( objective_wrapper, - n_trials=settings.n_trials - count_completed_trials(), + n_trials=settings.n_trials - len(study.trials), ) except KeyboardInterrupt: # This additional handler takes care of the small chance that KeyboardInterrupt @@ -635,7 +631,7 @@ def run(): # defined in objective_wrapper above. pass - if count_completed_trials() == settings.n_trials: + if len(study.trials) == settings.n_trials: study.set_user_attr("finished", True) while True: @@ -733,12 +729,12 @@ def run(): try: study.optimize( objective_wrapper, - n_trials=settings.n_trials - count_completed_trials(), + n_trials=settings.n_trials - len(study.trials), ) except KeyboardInterrupt: pass - if count_completed_trials() == settings.n_trials: + if len(study.trials) == settings.n_trials: study.set_user_attr("finished", True) break @@ -971,7 +967,7 @@ def run(): if reproducibility_information != "none": # Set the number of trials to the number of actual completed trials # for the reproduction configuration. - settings.n_trials = count_completed_trials() + settings.n_trials = len(study.trials) upload_reproduce_folder( repo_id, From ed14dd14cab095f0704814acc75ff0d42c2110b4 Mon Sep 17 00:00:00 2001 From: UmranPros <152087084+umran666@users.noreply.github.com> Date: Tue, 9 Jun 2026 08:27:25 +0530 Subject: [PATCH 17/18] fix: improve exception formatting (#146) (#363) * fix: fall back to exception class name when string representation is empty (#146) * fix: walk stacktrace and causal chain to extract exception details in format_exception * fix: fall back to complete stacktrace when exception has no message, as suggested by maintainer * fix: address maintainer review, push newline control to printing boundaries --- src/heretic/main.py | 13 +++++++++++-- src/heretic/model.py | 8 ++++++-- src/heretic/utils.py | 14 ++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/heretic/main.py b/src/heretic/main.py index b99b1ac..20895b9 100644 --- a/src/heretic/main.py +++ b/src/heretic/main.py @@ -69,6 +69,7 @@ from .reproduce import collect_reproducibles from .system import empty_cache, get_accelerator_info from .utils import ( format_duration, + format_exception, get_readme_intro, get_trial_parameters, is_hf_path, @@ -364,7 +365,11 @@ def run(): # We cannot recover from this. raise - print(f"[red]Failed[/] ({error})") + formatted = format_exception(error) + if "\n" in formatted: + print(f"[red]Failed[/]:\n{formatted}") + else: + print(f"[red]Failed[/] ({formatted})") break response_lengths = [ @@ -1120,7 +1125,11 @@ def run(): print(table) except Exception as error: - print(f"[red]Error: {error}[/]") + formatted = format_exception(error) + if "\n" in formatted: + print(f"[red]Error:[/]\n{formatted}") + else: + print(f"[red]Error: {formatted}[/]") def main(): diff --git a/src/heretic/model.py b/src/heretic/model.py index 92eb98c..cb4c103 100644 --- a/src/heretic/model.py +++ b/src/heretic/model.py @@ -33,7 +33,7 @@ from transformers.generation import ( from .config import QuantizationMethod, RowNormalization, Settings from .system import empty_cache -from .utils import Prompt, batchify, print +from .utils import Prompt, batchify, format_exception, print def get_model_class( @@ -150,7 +150,11 @@ class Model: except Exception as error: self.model = None # ty:ignore[invalid-assignment] empty_cache() - print(f"* [red]Failed[/] ({error})") + formatted = format_exception(error) + if "\n" in formatted: + print(f"* [red]Failed[/]:\n{formatted}") + else: + print(f"* [red]Failed[/] ({formatted})") continue if settings.quantization == QuantizationMethod.BNB_4BIT: diff --git a/src/heretic/utils.py b/src/heretic/utils.py index 778d52e..3d2d788 100644 --- a/src/heretic/utils.py +++ b/src/heretic/utils.py @@ -7,6 +7,7 @@ import os import platform import random import tempfile +import traceback from dataclasses import dataclass from datetime import datetime, timezone from importlib.metadata import version @@ -746,3 +747,16 @@ def upload_reproduce_folder( repo_id=repo_id, token=token, ) + + +def format_exception(error: Exception) -> str: + # Walk causal chain to find a non-empty message. + current = error + while current is not None: + message = str(current).strip() + if message: + return message + current = current.__cause__ or current.__context__ + + # If there is no message in the entire causal chain, fall back to the complete traceback. + return traceback.format_exc().strip() From e735203d56e6844ef349a3660703639e9376150a Mon Sep 17 00:00:00 2001 From: UmranPros <152087084+umran666@users.noreply.github.com> Date: Thu, 11 Jun 2026 11:05:58 +0530 Subject: [PATCH 18/18] fix: make reset_model null-safe to handle study cancellations (#77) (#367) * fix: make reset_model null-safe to handle study cancellations (#77) * fix: address bot review, use nested getattr and fallback to settings dtypes * fix: address maintainer review comments in model.py * fix: address maintainer review feedback on reset_model * fix: update Model.dtype type annotation to torch.dtype * chore: revert pyproject.toml and uv.lock changes --- src/heretic/model.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/heretic/model.py b/src/heretic/model.py index cb4c103..401f5b2 100644 --- a/src/heretic/model.py +++ b/src/heretic/model.py @@ -61,6 +61,7 @@ class Model: # Set for multimodal models, None for text-only ones. processor: ProcessorMixin | None peft_config: LoraConfig + dtype: torch.dtype def __init__(self, settings: Settings): self.settings = settings @@ -129,6 +130,7 @@ class Model: **self.revision_kwargs, **extra_kwargs, ) + self.dtype = self.model.dtype # If we reach this point and the model requires trust_remote_code, # either the user accepted, or settings.trust_remote_code is True. @@ -317,30 +319,34 @@ class Model: - Slow path: If switching models or after merge_and_unload(), performs full model reload with quantization config. """ - current_model = getattr(self.model.config, "name_or_path", None) + # If a prior model load was interrupted/cancelled mid-process, self.model will be None. + current_model = None + if self.model is not None: + current_model = getattr(self.model.config, "name_or_path", None) + if current_model == self.settings.model and not self.needs_reload: - # Reset LoRA adapters to zero (identity transformation) + # Reset LoRA adapters to zero (identity transformation). for name, module in self.model.named_modules(): if "lora_B" in name and hasattr(module, "weight"): torch.nn.init.zeros_(module.weight) return - dtype = self.model.dtype - # Purge existing model object from memory to make space. self.model = None # ty:ignore[invalid-assignment] empty_cache() - quantization_config = self._get_quantization_config(str(dtype).split(".")[-1]) + quantization_config = self._get_quantization_config( + str(self.dtype).split(".")[-1] + ) - # Build kwargs, only include quantization_config if it's not None + # Build kwargs, only include quantization_config if it's not None. extra_kwargs = {} if quantization_config is not None: extra_kwargs["quantization_config"] = quantization_config self.model = get_model_class(self.settings.model).from_pretrained( self.settings.model, - dtype=dtype, + dtype=self.dtype, device_map=self.settings.device_map, max_memory=self.max_memory, trust_remote_code=self.trusted_models.get(self.settings.model),