mirror of
https://github.com/p-e-w/heretic.git
synced 2026-11-06 05:16:39 +00:00
feat: make adjective describing the type of model produced configurable (#539)
This commit is contained in:
1 parent
d16e020116
commit
a9e7df2cda
9 files changed
+33
-19
No files matched your search
+4
-1
@@ -87,7 +87,7 @@ modifiers = [
|
||||
{ plugin = "heretic.modifiers.ara.ARA" },
|
||||
]
|
||||
|
||||
# Number of abliteration trials to run during optimization.
|
||||
# Number of trials to run during optimization.
|
||||
n_trials = 100
|
||||
|
||||
# Number of trials that use random sampling for the purpose of exploration.
|
||||
@@ -96,6 +96,9 @@ n_startup_trials = 30
|
||||
# Directory to save and load study progress to/from.
|
||||
study_checkpoint_dir = "checkpoints"
|
||||
|
||||
# Adjective describing the type of model produced by the configuration.
|
||||
modified_model_type = "decensored"
|
||||
|
||||
# Maximum size for individual safetensors files generated when exporting a model.
|
||||
max_shard_size = "5GB"
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
max_response_length = 300
|
||||
|
||||
modified_model_type = "humor-reduced"
|
||||
|
||||
upload_tags = [
|
||||
"no-humor",
|
||||
]
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
max_response_length = 300
|
||||
|
||||
modified_model_type = "slop-reduced"
|
||||
|
||||
upload_tags = [
|
||||
"no-slop",
|
||||
]
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
max_response_length = 100
|
||||
|
||||
modified_model_type = "sycophancy-reduced"
|
||||
|
||||
upload_tags = [
|
||||
"no-sycophancy",
|
||||
]
|
||||
|
||||
+11
-6
@@ -201,7 +201,7 @@ class Settings(BaseSettings):
|
||||
evaluate_model: str | None = Field(
|
||||
default=None,
|
||||
description=(
|
||||
"If this model ID or path is set, then instead of abliterating the main model, "
|
||||
"If this model ID or path is set, then instead of modifying the main model, "
|
||||
"evaluate this model relative to the main model."
|
||||
),
|
||||
exclude=True,
|
||||
@@ -210,7 +210,7 @@ class Settings(BaseSettings):
|
||||
collect_reproducibles: str | None = Field(
|
||||
default=None,
|
||||
description=(
|
||||
"If this directory path is set, then instead of abliterating a model, "
|
||||
"If this directory path is set, then instead of modifying a model, "
|
||||
"download all reproduce.json files from public Heretic model repositories "
|
||||
"on Hugging Face, and store them in that directory for archival purposes."
|
||||
),
|
||||
@@ -221,7 +221,7 @@ class Settings(BaseSettings):
|
||||
default=None,
|
||||
description=(
|
||||
"If this path or URL to a reproduce.json file is set, load reproduction information "
|
||||
"from that file, and attempt to reproduce the abliterated model it originated from."
|
||||
"from that file, and attempt to reproduce the modified model it originated from."
|
||||
),
|
||||
exclude=True,
|
||||
)
|
||||
@@ -405,7 +405,7 @@ class Settings(BaseSettings):
|
||||
|
||||
n_trials: PositiveInt = Field(
|
||||
default=100,
|
||||
description="Number of abliteration trials to run during optimization.",
|
||||
description="Number of trials to run during optimization.",
|
||||
)
|
||||
|
||||
n_startup_trials: NonNegativeInt = Field(
|
||||
@@ -427,6 +427,11 @@ class Settings(BaseSettings):
|
||||
exclude=True,
|
||||
)
|
||||
|
||||
modified_model_type: str = Field(
|
||||
default="decensored",
|
||||
description="Adjective describing the type of model produced by the configuration.",
|
||||
)
|
||||
|
||||
benchmarks: list[BenchmarkSpecification] = Field(
|
||||
default=[
|
||||
BenchmarkSpecification(
|
||||
@@ -485,7 +490,7 @@ class Settings(BaseSettings):
|
||||
description="An Adversarial Winograd Schema Challenge at Scale",
|
||||
),
|
||||
],
|
||||
description="Benchmarks to offer to the user for evaluating abliterated models.",
|
||||
description="Benchmarks to offer to the user for evaluating modified models.",
|
||||
exclude=True,
|
||||
)
|
||||
|
||||
@@ -516,7 +521,7 @@ class Settings(BaseSettings):
|
||||
|
||||
model_action: str | None = Field(
|
||||
default=None,
|
||||
description='Action to take with the decensored model: "save", "upload", or unset to prompt the user.',
|
||||
description='Action to take with the modified model: "save", "upload", or unset to prompt the user.',
|
||||
)
|
||||
|
||||
save_directory: str | None = Field(
|
||||
|
||||
+5
-5
@@ -175,7 +175,7 @@ def obtain_export_strategy(
|
||||
"How do you want to export the model?",
|
||||
choices=[
|
||||
Choice(
|
||||
title="Merge the abliteration LoRA and export the full model"
|
||||
title="Merge the LoRA and export the full model"
|
||||
+ (
|
||||
""
|
||||
if settings.quantization == QuantizationMethod.NONE
|
||||
@@ -184,7 +184,7 @@ def obtain_export_strategy(
|
||||
value=ExportStrategy.MERGE,
|
||||
),
|
||||
Choice(
|
||||
title="Export the abliteration LoRA only (can be merged later)",
|
||||
title="Export the LoRA only (can be merged later)",
|
||||
value=ExportStrategy.ADAPTER,
|
||||
),
|
||||
],
|
||||
@@ -944,7 +944,7 @@ def run():
|
||||
action = ask_if_unset(
|
||||
settings.model_action,
|
||||
questionary.select(
|
||||
"What do you want to do with the decensored model?",
|
||||
f"What do you want to do with the {settings.modified_model_type} model?",
|
||||
choices=[
|
||||
Choice(
|
||||
title="Save the model to a local folder",
|
||||
@@ -1366,11 +1366,11 @@ def run():
|
||||
|
||||
scope = questionary.select(
|
||||
(
|
||||
"Do you want to benchmark the original model along with the decensored model? "
|
||||
f"Do you want to benchmark the original model along with the {settings.modified_model_type} model? "
|
||||
"Benchmarking both models allows you to compare the scores, but it takes twice as much time."
|
||||
),
|
||||
choices=[
|
||||
"Benchmark only the decensored model",
|
||||
f"Benchmark only the {settings.modified_model_type} model",
|
||||
"Benchmark both models",
|
||||
],
|
||||
style=Style([("highlighted", "reverse")]),
|
||||
|
||||
@@ -242,7 +242,7 @@ class Model:
|
||||
all_components[component] = 0
|
||||
all_components[component] += len(modules)
|
||||
|
||||
print("* Abliterable components:")
|
||||
print("* Modifiable components:")
|
||||
for component, count in all_components.items():
|
||||
print(f" * [bold]{component}[/]: [bold]{count}[/] modules total")
|
||||
|
||||
@@ -250,7 +250,7 @@ class Model:
|
||||
# Guard against calling this method at the wrong time.
|
||||
assert isinstance(self.model, PreTrainedModel)
|
||||
|
||||
# Always use LoRA adapters for abliteration (faster reload, no weight modification).
|
||||
# Always use LoRA adapters for modification (faster reload, no weight modification).
|
||||
# Collect actual leaf module names from the model for LoRA targeting.
|
||||
# This is more robust than splitting component keys (e.g. "attn.o_proj" -> "o_proj")
|
||||
# because hybrid models like Qwen3.5 MoE have modules with different names
|
||||
@@ -513,13 +513,13 @@ class Model:
|
||||
for expert in layer.moe.experts: # ty:ignore[not-iterable, unresolved-attribute]
|
||||
try_add("mlp.down_proj", expert.output_linear) # ty: ignore[unresolved-attribute]
|
||||
|
||||
# We need at least one module across all components for abliteration to work.
|
||||
# We need at least one module across all components.
|
||||
total_modules = sum(len(mods) for mods in modules.values())
|
||||
assert total_modules > 0, "No abliterable modules found in layer"
|
||||
assert total_modules > 0, "No modifiable modules found in layer"
|
||||
|
||||
return modules
|
||||
|
||||
def get_abliterable_components(self) -> list[str]:
|
||||
def get_modifiable_components(self) -> list[str]:
|
||||
components: set[str] = set()
|
||||
|
||||
# Scan all layers because hybrid models (e.g. Qwen3.5 MoE) have different
|
||||
|
||||
@@ -255,7 +255,7 @@ class Abliteration(Modifier[Parameters]):
|
||||
|
||||
weight_distributions = {}
|
||||
|
||||
for component in model.get_abliterable_components():
|
||||
for component in model.get_modifiable_components():
|
||||
# The parameter ranges are based on experiments with various models
|
||||
# and much wider ranges. They are not set in stone and might have to be
|
||||
# adjusted for future models.
|
||||
|
||||
@@ -344,7 +344,7 @@ def get_readme_intro(
|
||||
else:
|
||||
reproducibility_instructions = ""
|
||||
|
||||
return f"""# This is a decensored version of {
|
||||
return f"""# This is a {settings.modified_model_type} version of {
|
||||
model_link
|
||||
}, made using [Heretic](https://heretic-project.org) v{version("heretic-llm")}
|
||||
{reproducibility_instructions}
|
||||
|
||||
Reference in new issue
Block a user