* fix: minor change
use `W_org` matrix where needed...
* Update model.py
* Update model.py
* fix: Windows hash, remove BOM marker
* docs: Add info about test cases
* feat: Tests for row_normalization PRE & NONE
* feat: CI hash files for row_normalization PRE & NONE models
* feat: Documentation instructions about test suite
* add recommendation
* fix: remove notebook input shims
Closes#280
* feat: support headless operation (no interactive input)
* fix: prevent infinite loops
* feat: add end-to-end tests
* ci: run tests in CI
* ci: fix test output ordering
* fix: replace home-cooked `set_seed` function with Transformers builtin
* feat: print PyTorch config when running tests
* feat: print additional information
* experiment: try to standardize test environment
* fix: revert environment changes
* feat: support multiple valid hashes for each output file
* feat: add test output hashes for CI
* feat: add test output hashes for CI (alternative environment)
* feat: add hashes for Windows (#394)
* fix: Hash on windows
* trigger ci
* fix: prefer .yaml (used widely than .toml for model configs)
* use removeprefix
* docs: restore commet
* use removeprefix again
* tests: Add windows hash files for all test models
* trigger ci
* fix: minor cleanup
* clean merge mismatch
* remove unnecessary CRLF replace, now that we support more SUMS files
* fix: use binary mode for hashes everywhere
---------
Co-authored-by: Vinay Umrethe <umrethevinay@gmail.com>
* fix: ensure utf-8 encoding for standard output and error to prevent UnicodeEncodeError on Windows
* fix: address bot review feedback
* refactor: deduplicate stream reconfiguration loop
* feat: let the optimizer disable MLP ablation via a 0 max_weight floor
The MLP max_weight lower bound was 0.8 for every component, so the optimizer
always applied at least 0.8x MLP ablation and could never turn it off, even
when ablating the MLP is pure collateral damage. Give the MLP a 0 lower bound
so the optimizer can disable it per model; attention keeps the 0.8 floor.
See #202.
* perf: skip the abliteration decomposition when the weight is 0
With a 0 max_weight the component's ablation is a no-op, and reset_model()
has already left the adapter at identity. Abort that layer/component before
the decomposition, which avoids the wasted work (and the degenerate
zero-matrix decomposition raised in review on #387).
* fix: clamp a negative MLP max_weight floor so 0 is reachable
A continuous suggest_float never samples exactly 0, so a 0 lower bound could
not actually disable the MLP. Use a small negative lower bound and clamp with
max(0, ...), which puts finite probability mass on exactly 0.
When a study is cancelled mid-way and the user selects 'Run additional
trials', settings.n_trials was incremented by n_additional_trials,
accumulating the original total into the new count. E.g. cancelling 200
trials at 30 and adding 10 gave n_trials=210 instead of 40, causing
'Running trial 31 of 210...' and planning 180 more trials instead of 10.
Fix by recalculating n_trials from actual completed trials + additional,
so the total reflects the new intended target, not the old one.
Fixes#379
Co-authored-by: Claude <noreply@anthropic.com>
* feat: load reproduction information
* feat: check reproduction environment against original environment
* fix: remove `trust_remote_code` setting
This improves security when running Heretic with an untrusted config file. The prompt is now always shown.
This is NOT a breaking change, because we currently ignore values for unknown settings, so existing configs continue to work.
* feat: reproduce model from JSON file
* feat: verify hashes of uploaded weight files
* fix: fix issues in automatic reproduction system (#352)
* fix: Check if a model is gated / accessible
* fix: handle unknown gated models
* feat: Auto install requirements
* simplify
* Revert "simplify"
This reverts commit 10287926e9.
* Revert "feat: Auto install requirements"
This reverts commit f4be1abd04.
* fix: Seed pytorch method
* reference, style
* simplify token
* feat: Export strategy in reproduce.json, v2
* style: Name
* simplify export strategy
* style: Rename
* enumeration
* maybe remove seed as well
* fix: don't lock settings with permanent strategy
* simplify no choice, use try/finally block
* feat: verify hashes of locally saved weight files
* fix: remove obsolete code from merge
* docs: add automatic reproduction instructions to reproduce README
---------
Co-authored-by: Vinay-Umrethe <vinayumrethe99@gmail.com>
* 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
* 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
* 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>
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.
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 <ricyoung@gmail.com>
* fix: Reset model after saving merged model
The adapter is lost and writes 0-byte adapters if you save an adapter after saving the merged model.
* Revert "Revert "Revert "fix: disable LoRA export for now" (#308)" (#319)"
This reverts commit 216c089974.
* Add comment as to why resetting model is needed
* fix: various cleanups and improvements for the reproducibility system
* fix: save only essential settings
* fix: improve model commit handling
* feat: make including system information optional
* fix: improve formatting of reproducibility README
* fix: fix remaining issues
* fix: prevent UnboundLocalError when analyzer is not initialized
Move cleanup of analyzer and residuals inside the conditional block
where they are actually defined to avoid crashing when
--print-residual-geometry or --plot-residuals are not used.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: address AI review feedback on residual cleanup
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* feat: implement reproducibility features with safetensors
* feat: prompt user before creating reproducibility folder
* fix: use prompt_confirm wrapper
* style comment
* style comment
* fix: ignore None values in Settings dump for TOML compatibility
* fix: imports
* feat: auto-generate seed if none provided for full reproducibility
* style: fix ruff formatting issues
* style: ruff
* style: fix ty check errors with ty:ignore
* Update src/heretic/main.py
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
* Update src/heretic/utils.py
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
* add period at end.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
* Improve: Add README, checkpoint.jsonl, to Reproduce
* fix: use centralize device info, remove random states file
* feat: Add CUDA driver version
* ruff
* ruff...
* ty fix
* LGTM: Rich native strip, use nvidia-smi
* ruff fix
* ruff
* revert kaggle hack)
* normalize names for deduplication of packages/versions
* docstring
* rufff
* cleanup, add suffix for torch CUDA version, distinguish ROCm
* add PyTorch index URL detection
* revert index URL to be simple
* flip priority of index..
* add Important note
* add exact suffix for WHL in instruction
* add warning for heterogeneous GPU env
* extend driver version info (more accelerators)
* fix: style
* sync
* no abbreviation
* use multi-line string
* fix: prompt_confirm
* feat: CPU info
* strip 'slow' warning from environment.txt
* feat: Add virtual env info to environment.txt
* ruffff
* feat: AMD (Radeon) GPU driver version
* Refactor: system.py
* feat: LGTM capturing specifc installation origin of heretic
* feat: Include chosen trial into reproduce/README
* style: run ruff format on utils.py
* feat: reproduce.json
* fix: seperate values in different keys
* restore comment
* style, clean, seperate commit key
* no abbreviation, cleanup
* remove labels, store only dependencies
* missed import, ruff
* sort import
* feat: More CPU Info
* only store direct dependencies of heretic
* complete comment
* refactor: use cpuinfo package instead
* ruff import sort
* distinguish cores & threads
* move function amd-driver
* rename
* moving heretic package info,
* rufff
* Move: cleanup memory cache
* fix: model.py import
* no unknowns
* generalize all accelerator info stuff
* ruff f
* move package info
* type change
* feat: no reproducibility suite for local saving/model used
* import fix
* fix: type check
* style change
* style ruff
* feat: no env.txt, SHA256SUMS file, cleanup
* feat: ADD tip to readme
* remove trial index, two-keys only
* fix: No time-zone
* feat: No suite for local datasets allowed
* simplify
* featt: capture both direct and transitive dependencies
* style: sort readme of reproducibility suite
* feat: Store commit hash for datasets too
* add total refusal prompts for evaluation display
* remove try/except from cpu
* extend SHA256 support
* remove .txt
* only have safetensors for SHA256
* style comment
* use HF api to get commit hash
* fix: requirements containing irrelevant dependencies
* only store heretic-llm if from PyPI..
* add SELECTED tag to the trial that was pushed
* AttributeError fix
* simplify trial preservation
* add direction_index in trial info
* remove unwanted CPU info
* style: rename
---------
Co-authored-by: Vinayyyy7 <vinayumrethe99@gmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>